2 * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * sslRecord.c - Encryption, decryption and MACing of data
28 #include <SecureTransport.h>
30 #include "sslRecord.h"
31 #include "sslMemory.h"
32 #include "sslContext.h"
33 #include "sslAlertMessage.h"
36 #include "sslDigests.h"
37 #include "SSLRecordInternal.h"
42 #include <utilities/SecIOFormat.h>
45 * Lots of servers fail to provide closure alerts when they disconnect.
46 * For now we'll just accept it as long as it occurs on a clean record boundary
47 * (and the handshake is complete).
49 #define SSL_ALLOW_UNNOTICED_DISCONNECT 1
52 static OSStatus
errorTranslate(int recordErr
)
57 case errSSLRecordInternal
:
58 return errSSLInternal
;
59 case errSSLRecordWouldBlock
:
60 return errSSLWouldBlock
;
61 case errSSLRecordProtocol
:
62 return errSSLProtocol
;
63 case errSSLRecordNegotiation
:
64 return errSSLNegotiation
;
65 case errSSLRecordClosedAbort
:
66 return errSSLClosedAbort
;
67 case errSSLRecordConnectionRefused
:
68 return errSSLConnectionRefused
;
69 case errSSLRecordDecryptionFail
:
70 return errSSLDecryptionFail
;
71 case errSSLRecordBadRecordMac
:
72 return errSSLBadRecordMac
;
73 case errSSLRecordRecordOverflow
:
74 return errSSLRecordOverflow
;
75 case errSSLRecordUnexpectedRecord
:
76 return errSSLUnexpectedRecord
;
78 sslErrorLog("unknown error code returned in sslErrorTranslate: %d\n", recordErr
);
84 * Attempt to encrypt and queue an SSL record.
87 SSLWriteRecord(SSLRecord rec
, SSLContext
*ctx
)
91 err
=errorTranslate(ctx
->recFuncs
->write(ctx
->recCtx
, rec
));
97 sslErrorLog("unexpected error code returned in SSLWriteRecord: %d\n", (int)err
);
105 * Free a record returned by SSLReadRecord.
108 SSLFreeRecord(SSLRecord rec
, SSLContext
*ctx
)
110 return ctx
->recFuncs
->free(ctx
->recCtx
, rec
);
114 * Attempt to read & decrypt an SSL record.
115 * Record content should be freed using SSLFreeRecord
118 SSLReadRecord(SSLRecord
*rec
, SSLContext
*ctx
)
121 err
=errorTranslate(ctx
->recFuncs
->read(ctx
->recCtx
, rec
));
125 case errSSLWouldBlock
:
127 case errSSLUnexpectedRecord
:
130 case errSSLDecryptionFail
:
131 case errSSLBadRecordMac
:
132 /* We never send a Decryption Failed alert, instead we send the BadRecordMac alert */
133 /* This is TLS 1.1 compliant - Do it for all protocols versions. */
134 /* Except for DTLS where we do not send any alert. */
136 /* This will ensure we try to read again before returning to the caller
137 We do NOT want to use errSSLWouldBlock here, as this should only indicate
138 the IO read callback status */
139 err
=errSSLUnexpectedRecord
;
141 SSLFatalSessionAlert(SSL_AlertBadRecordMac
, ctx
);
145 SSLFatalSessionAlert(SSL_AlertInternalError
, ctx
);
147 case errSSLRecordOverflow
:
148 SSLFatalSessionAlert(SSL_AlertRecordOverflow
, ctx
);
150 case errSSLClosedAbort
:
151 case errSSLConnectionRefused
:
152 SSLFatalSessionAlert(SSL_AlertCloseNotify
, ctx
);
155 sslErrorLog("unknown error code returned in SSLReadRecord: %d\n", (int)err
);
156 SSLFatalSessionAlert(SSL_AlertCloseNotify
, ctx
);
163 OSStatus
SSLServiceWriteQueue(SSLContext
*ctx
)
165 return errorTranslate(ctx
->recFuncs
->serviceWriteQueue(ctx
->recCtx
));