]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/lib/sslRecord.c
Security-55471.14.4.tar.gz
[apple/security.git] / libsecurity_ssl / lib / sslRecord.c
1 /*
2 * Copyright (c) 1999-2001,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /*
25 * sslRecord.c - Encryption, decryption and MACing of data
26 */
27
28 #include <SecureTransport.h>
29 #include "ssl.h"
30 #include "sslRecord.h"
31 #include "sslMemory.h"
32 #include "sslContext.h"
33 #include "sslAlertMessage.h"
34 #include "sslDebug.h"
35 #include "sslUtils.h"
36 #include "sslDigests.h"
37 #include "SSLRecordInternal.h"
38
39 #include <string.h>
40 #include <assert.h>
41
42 #include <utilities/SecIOFormat.h>
43
44 /*
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).
48 */
49 #define SSL_ALLOW_UNNOTICED_DISCONNECT 1
50
51
52 static OSStatus errorTranslate(int recordErr)
53 {
54 switch(recordErr) {
55 case errSecSuccess:
56 return errSecSuccess;
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;
77 default:
78 sslErrorLog("unknown error code returned in sslErrorTranslate: %d\n", recordErr);
79 return recordErr;
80 }
81 }
82
83 /* SSLWriteRecord
84 * Attempt to encrypt and queue an SSL record.
85 */
86 OSStatus
87 SSLWriteRecord(SSLRecord rec, SSLContext *ctx)
88 {
89 OSStatus err;
90
91 err=errorTranslate(ctx->recFuncs->write(ctx->recCtx, rec));
92
93 switch(err) {
94 case errSecSuccess:
95 break;
96 default:
97 sslErrorLog("unexpected error code returned in SSLWriteRecord: %d\n", (int)err);
98 break;
99 }
100
101 return err;
102 }
103
104 /* SSLFreeRecord
105 * Free a record returned by SSLReadRecord.
106 */
107 OSStatus
108 SSLFreeRecord(SSLRecord rec, SSLContext *ctx)
109 {
110 return ctx->recFuncs->free(ctx->recCtx, rec);
111 }
112
113 /* SSLReadRecord
114 * Attempt to read & decrypt an SSL record.
115 * Record content should be freed using SSLFreeRecord
116 */
117 OSStatus
118 SSLReadRecord(SSLRecord *rec, SSLContext *ctx)
119 { OSStatus err;
120
121 err=errorTranslate(ctx->recFuncs->read(ctx->recCtx, rec));
122
123 switch(err) {
124 case errSecSuccess:
125 case errSSLWouldBlock:
126 break;
127 case errSSLUnexpectedRecord:
128 DTLSRetransmit(ctx);
129 break;
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. */
135 if(ctx->isDTLS) {
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;
140 } else {
141 SSLFatalSessionAlert(SSL_AlertBadRecordMac, ctx);
142 }
143 break;
144 case errSSLInternal:
145 SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
146 break;
147 case errSSLRecordOverflow:
148 SSLFatalSessionAlert(SSL_AlertRecordOverflow, ctx);
149 break;
150 case errSSLClosedAbort:
151 case errSSLConnectionRefused:
152 SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
153 break;
154 default:
155 sslErrorLog("unknown error code returned in SSLReadRecord: %d\n", (int)err);
156 SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
157 break;
158 }
159
160 return err;
161 }
162
163 OSStatus SSLServiceWriteQueue(SSLContext *ctx)
164 {
165 return errorTranslate(ctx->recFuncs->serviceWriteQueue(ctx->recCtx));
166 }