]> git.saurik.com Git - apple/security.git/blame - SecureTransport/sslRecord.cpp
Security-163.tar.gz
[apple/security.git] / SecureTransport / sslRecord.cpp
CommitLineData
bac41a7b
A
1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18
19/*
5a719ac8 20 File: sslRecord.cpp
bac41a7b
A
21
22 Contains: Encryption, decryption and MACing of data
23
5a719ac8 24 Written by: Doug Mitchell
bac41a7b
A
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28*/
bac41a7b
A
29
30#include "ssl.h"
31
5a719ac8
A
32#include "sslRecord.h"
33#include "sslMemory.h"
bac41a7b 34#include "cryptType.h"
5a719ac8
A
35#include "sslContext.h"
36#include "sslAlertMessage.h"
bac41a7b 37#include "sslDebug.h"
bac41a7b 38#include "ssl2.h"
5a719ac8
A
39#include "sslUtils.h"
40#include "sslDigests.h"
bac41a7b 41
bac41a7b 42#include <string.h>
29654253 43#include <assert.h>
bac41a7b
A
44
45/*
46 * Lots of servers fail to provide closure alerts when they disconnect.
47 * For now we'll just accept it as long as it occurs on a clean record boundary
48 * (and the handshake is complete).
49 */
50#define SSL_ALLOW_UNNOTICED_DISCONNECT 1
51
bac41a7b
A
52/* ReadSSLRecord
53 * Attempt to read & decrypt an SSL record.
54 */
5a719ac8
A
55OSStatus
56SSLReadRecord(SSLRecord &rec, SSLContext *ctx)
57{ OSStatus err;
bac41a7b 58 UInt32 len, contentLen;
5a719ac8 59 UInt8 *charPtr;
bac41a7b
A
60 SSLBuffer readData, cipherFragment;
61
62 if (!ctx->partialReadBuffer.data || ctx->partialReadBuffer.length < 5)
63 { if (ctx->partialReadBuffer.data)
5a719ac8 64 if ((err = SSLFreeBuffer(ctx->partialReadBuffer, ctx)) != 0)
df0e469f 65 { SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
5a719ac8 66 return err;
bac41a7b 67 }
5a719ac8
A
68 if ((err = SSLAllocBuffer(ctx->partialReadBuffer,
69 DEFAULT_BUFFER_SIZE, ctx)) != 0)
df0e469f 70 { SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
5a719ac8 71 return err;
bac41a7b
A
72 }
73 }
74
df0e469f 75 if (ctx->negProtocolVersion == SSL_Version_Undetermined) {
bac41a7b
A
76 if (ctx->amountRead < 1)
77 { readData.length = 1 - ctx->amountRead;
78 readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
79 len = readData.length;
bac41a7b
A
80 err = sslIoRead(readData, &len, ctx);
81 if(err != 0)
df0e469f
A
82 { if (err == errSSLWouldBlock) {
83 ctx->amountRead += len;
84 return err;
85 }
86 else {
87 /* abort */
5a719ac8 88 SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
df0e469f
A
89 return errSSLClosedAbort;
90 }
bac41a7b
A
91 }
92 ctx->amountRead += len;
93 }
df0e469f
A
94 }
95
5a719ac8
A
96 /*
97 * In undetermined cases, if the first byte isn't in the range of SSL 3.0
98 * record types, this is an SSL 2.0 record
99 */
bac41a7b
A
100 switch (ctx->negProtocolVersion)
101 { case SSL_Version_Undetermined:
5a719ac8
A
102 if (ctx->partialReadBuffer.data[0] < SSL_RecordTypeV3_Smallest ||
103 ctx->partialReadBuffer.data[0] > SSL_RecordTypeV3_Largest)
bac41a7b
A
104 return SSL2ReadRecord(rec, ctx);
105 else
106 break;
107 case SSL_Version_2_0:
108 return SSL2ReadRecord(rec, ctx);
109 default:
110 break;
111 }
112
113 if (ctx->amountRead < 5)
114 { readData.length = 5 - ctx->amountRead;
115 readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
116 len = readData.length;
bac41a7b
A
117 err = sslIoRead(readData, &len, ctx);
118 if(err != 0)
bac41a7b
A
119 {
120 switch(err) {
5a719ac8 121 case errSSLWouldBlock:
bac41a7b
A
122 ctx->amountRead += len;
123 break;
124 #if SSL_ALLOW_UNNOTICED_DISCONNECT
5a719ac8 125 case errSSLClosedGraceful:
bac41a7b
A
126 /* legal if we're on record boundary and we've gotten past
127 * the handshake */
128 if((ctx->amountRead == 0) && /* nothing pending */
129 (len == 0) && /* nothing new */
df0e469f 130 (ctx->state == SSL_HdskStateClientReady)) { /* handshake done */
bac41a7b 131 /*
29654253 132 * This means that the server has disconnected without
bac41a7b
A
133 * sending a closure alert notice. This is technically
134 * illegal per the SSL3 spec, but about half of the
135 * servers out there do it, so we report it as a separate
136 * error which most clients - including (currently)
137 * URLAccess - ignore by treating it the same as
5a719ac8 138 * a errSSLClosedGraceful error. Paranoid
bac41a7b
A
139 * clients can detect it and handle it however they
140 * want to.
141 */
5a719ac8
A
142 SSLChangeHdskState(ctx, SSL_HdskStateNoNotifyClose);
143 err = errSSLClosedNoNotify;
bac41a7b
A
144 break;
145 }
146 else {
147 /* illegal disconnect */
5a719ac8 148 err = errSSLClosedAbort;
bac41a7b
A
149 /* and drop thru to default: fatal alert */
150 }
151 #endif /* SSL_ALLOW_UNNOTICED_DISCONNECT */
152 default:
5a719ac8 153 SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
bac41a7b
A
154 break;
155 }
156 return err;
157 }
158 ctx->amountRead += len;
159 }
160
5a719ac8 161 assert(ctx->amountRead >= 5);
bac41a7b 162
5a719ac8
A
163 charPtr = ctx->partialReadBuffer.data;
164 rec.contentType = *charPtr++;
165 if (rec.contentType < SSL_RecordTypeV3_Smallest ||
166 rec.contentType > SSL_RecordTypeV3_Largest)
167 return errSSLProtocol;
bac41a7b 168
5a719ac8
A
169 rec.protocolVersion = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2);
170 charPtr += 2;
171 contentLen = SSLDecodeInt(charPtr, 2);
172 charPtr += 2;
173 if (contentLen > (16384 + 2048)) /* Maximum legal length of an
174 * SSLCipherText payload */
df0e469f 175 { SSLFatalSessionAlert(SSL_AlertRecordOverflow, ctx);
5a719ac8 176 return errSSLProtocol;
bac41a7b
A
177 }
178
179 if (ctx->partialReadBuffer.length < 5 + contentLen)
5a719ac8 180 { if ((err = SSLReallocBuffer(ctx->partialReadBuffer, 5 + contentLen, ctx)) != 0)
df0e469f 181 { SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
5a719ac8 182 return err;
bac41a7b
A
183 }
184 }
185
186 if (ctx->amountRead < 5 + contentLen)
187 { readData.length = 5 + contentLen - ctx->amountRead;
188 readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
189 len = readData.length;
bac41a7b
A
190 err = sslIoRead(readData, &len, ctx);
191 if(err != 0)
5a719ac8 192 { if (err == errSSLWouldBlock)
bac41a7b
A
193 ctx->amountRead += len;
194 else
5a719ac8 195 SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx);
bac41a7b
A
196 return err;
197 }
198 ctx->amountRead += len;
199 }
200
5a719ac8 201 assert(ctx->amountRead >= 5 + contentLen);
bac41a7b
A
202
203 cipherFragment.data = ctx->partialReadBuffer.data + 5;
204 cipherFragment.length = contentLen;
205
5a719ac8
A
206 /*
207 * Decrypt the payload & check the MAC, modifying the length of the
208 * buffer to indicate the amount of plaintext data after adjusting
209 * for the block size and removing the MAC (this function generates
210 * its own alerts).
211 */
29654253 212 assert(ctx->sslTslCalls != NULL);
5a719ac8 213 if ((err = ctx->sslTslCalls->decryptRecord(rec.contentType,
29654253 214 &cipherFragment, ctx)) != 0)
bac41a7b
A
215 return err;
216
5a719ac8
A
217 /*
218 * We appear to have sucessfully received a record; increment the
219 * sequence number
220 */
bac41a7b
A
221 IncrementUInt64(&ctx->readCipher.sequenceNum);
222
5a719ac8
A
223 /* Allocate a buffer to return the plaintext in and return it */
224 if ((err = SSLAllocBuffer(rec.contents, cipherFragment.length, ctx)) != 0)
df0e469f 225 { SSLFatalSessionAlert(SSL_AlertInternalError, ctx);
5a719ac8 226 return err;
bac41a7b 227 }
5a719ac8 228 memcpy(rec.contents.data, cipherFragment.data, cipherFragment.length);
bac41a7b
A
229
230 ctx->amountRead = 0; /* We've used all the data in the cache */
231
5a719ac8 232 return noErr;
bac41a7b
A
233}
234
29654253 235/* common for sslv3 and tlsv1, except for the computeMac callout */
5a719ac8 236OSStatus SSLVerifyMac(
29654253 237 UInt8 type,
5a719ac8 238 SSLBuffer &data,
29654253
A
239 UInt8 *compareMAC,
240 SSLContext *ctx)
241{
5a719ac8
A
242 OSStatus err;
243 UInt8 macData[SSL_MAX_DIGEST_LEN];
bac41a7b
A
244 SSLBuffer secret, mac;
245
246 secret.data = ctx->readCipher.macSecret;
29654253 247 secret.length = ctx->readCipher.macRef->hash->digestSize;
bac41a7b 248 mac.data = macData;
29654253
A
249 mac.length = ctx->readCipher.macRef->hash->digestSize;
250
251 assert(ctx->sslTslCalls != NULL);
252 if ((err = ctx->sslTslCalls->computeMac(type,
253 data,
254 mac,
255 &ctx->readCipher,
256 ctx->readCipher.sequenceNum,
257 ctx)) != 0)
5a719ac8 258 return err;
bac41a7b
A
259
260 if ((memcmp(mac.data, compareMAC, mac.length)) != 0) {
5a719ac8
A
261 sslErrorLog("ssl3VerifyMac: Mac verify failure\n");
262 return errSSLProtocol;
bac41a7b 263 }
5a719ac8 264 return noErr;
bac41a7b
A
265}
266
29654253 267