]> git.saurik.com Git - apple/security.git/blame - SecureTransport/sslrec.c
Security-54.1.tar.gz
[apple/security.git] / SecureTransport / sslrec.c
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/*
20 File: sslrec.c
21
22 Contains: Encryption, decryption and MACing of data
23
29654253 24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
bac41a7b
A
25
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
27
28*/
29/* *********************************************************************
30 File: sslrec.c
31
32 SSLRef 3.0 Final -- 11/19/96
33
34 Copyright (c)1996 by Netscape Communications Corp.
35
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
39
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
43
44 *********************************************************************
45
46 File: sslrec.c Encryption, decryption and MACing of data
47
48 All the transformations which occur between plaintext and the
49 secured, authenticated data that goes out over the wire. Also,
50 detects incoming SSL 2 hello messages and hands them off to the SSL 2
51 record layer (and hands all SSL 2 reading & writing off to the SSL 2
52 layer).
53
54 ****************************************************************** */
55
56
57#include "ssl.h"
58
59#ifndef _SSLREC_H_
60#include "sslrec.h"
61#endif
62
63#ifndef _SSLALLOC_H_
64#include "sslalloc.h"
65#endif
66
67#ifndef _CRYPTTYPE_H_
68#include "cryptType.h"
69#endif
70
71#ifndef _SSLCTX_H_
72#include "sslctx.h"
73#endif
74
75#ifndef _SSLALERT_H_
76#include "sslalert.h"
77#endif
78
79#ifndef _SSL_DEBUG_H_
80#include "sslDebug.h"
81#endif
82
83#ifndef _SSL2_H_
84#include "ssl2.h"
85#endif
86
87#ifndef _SSLUTIL_H_
88#include "sslutil.h"
89#endif
90
bac41a7b 91#include "appleGlue.h"
bac41a7b 92#include <string.h>
29654253 93#include <assert.h>
bac41a7b
A
94
95/*
96 * Lots of servers fail to provide closure alerts when they disconnect.
97 * For now we'll just accept it as long as it occurs on a clean record boundary
98 * (and the handshake is complete).
99 */
100#define SSL_ALLOW_UNNOTICED_DISCONNECT 1
101
bac41a7b
A
102/* ReadSSLRecord
103 * Attempt to read & decrypt an SSL record.
104 */
105SSLErr
106SSLReadRecord(SSLRecord *rec, SSLContext *ctx)
107{ SSLErr err;
108 UInt32 len, contentLen;
109 UInt8 *progress;
110 SSLBuffer readData, cipherFragment;
111
112 if (!ctx->partialReadBuffer.data || ctx->partialReadBuffer.length < 5)
113 { if (ctx->partialReadBuffer.data)
114 if ((err = SSLFreeBuffer(&ctx->partialReadBuffer, &ctx->sysCtx)) != 0)
115 { SSLFatalSessionAlert(alert_close_notify, ctx);
116 return ERR(err);
117 }
118 if ((err = SSLAllocBuffer(&ctx->partialReadBuffer, DEFAULT_BUFFER_SIZE, &ctx->sysCtx)) != 0)
119 { SSLFatalSessionAlert(alert_close_notify, ctx);
120 return ERR(err);
121 }
122 }
123
124 if (ctx->negProtocolVersion == SSL_Version_Undetermined ||
125 ctx->negProtocolVersion == SSL_Version_3_0_With_2_0_Hello)
126 if (ctx->amountRead < 1)
127 { readData.length = 1 - ctx->amountRead;
128 readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
129 len = readData.length;
bac41a7b
A
130 err = sslIoRead(readData, &len, ctx);
131 if(err != 0)
bac41a7b
A
132 { if (err == SSLWouldBlockErr)
133 ctx->amountRead += len;
134 else
135 SSLFatalSessionAlert(alert_close_notify, ctx);
136 return err;
137 }
138 ctx->amountRead += len;
139 }
140
141/* In undetermined cases, if the first byte isn't in the range of SSL 3.0
142 * record types, this is an SSL 2.0 record
143 */
144 switch (ctx->negProtocolVersion)
145 { case SSL_Version_Undetermined:
146 case SSL_Version_3_0_With_2_0_Hello:
147 if (ctx->partialReadBuffer.data[0] < SSL_smallest_3_0_type ||
148 ctx->partialReadBuffer.data[0] > SSL_largest_3_0_type)
149 return SSL2ReadRecord(rec, ctx);
150 else
151 break;
152 case SSL_Version_2_0:
153 return SSL2ReadRecord(rec, ctx);
154 default:
155 break;
156 }
157
158 if (ctx->amountRead < 5)
159 { readData.length = 5 - ctx->amountRead;
160 readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
161 len = readData.length;
bac41a7b
A
162 err = sslIoRead(readData, &len, ctx);
163 if(err != 0)
bac41a7b
A
164 {
165 switch(err) {
166 case SSLWouldBlockErr:
167 ctx->amountRead += len;
168 break;
169 #if SSL_ALLOW_UNNOTICED_DISCONNECT
170 case SSLConnectionClosedGraceful:
171 /* legal if we're on record boundary and we've gotten past
172 * the handshake */
173 if((ctx->amountRead == 0) && /* nothing pending */
174 (len == 0) && /* nothing new */
175 (ctx->state == HandshakeClientReady)) { /* handshake done */
176 /*
29654253 177 * This means that the server has disconnected without
bac41a7b
A
178 * sending a closure alert notice. This is technically
179 * illegal per the SSL3 spec, but about half of the
180 * servers out there do it, so we report it as a separate
181 * error which most clients - including (currently)
182 * URLAccess - ignore by treating it the same as
183 * a SSLConnectionClosedGraceful error. Paranoid
184 * clients can detect it and handle it however they
185 * want to.
186 */
187 SSLChangeHdskState(ctx, SSLNoNotifyClose);
188 err = SSLConnectionClosedNoNotify;
189 break;
190 }
191 else {
192 /* illegal disconnect */
193 err = SSLConnectionClosedError;
194 /* and drop thru to default: fatal alert */
195 }
196 #endif /* SSL_ALLOW_UNNOTICED_DISCONNECT */
197 default:
198 SSLFatalSessionAlert(alert_close_notify, ctx);
199 break;
200 }
201 return err;
202 }
203 ctx->amountRead += len;
204 }
205
206 CASSERT(ctx->amountRead >= 5);
207
208 progress = ctx->partialReadBuffer.data;
209 rec->contentType = *progress++;
210 if (rec->contentType < SSL_smallest_3_0_type ||
211 rec->contentType > SSL_largest_3_0_type)
212 return ERR(SSLProtocolErr);
213
214 rec->protocolVersion = (SSLProtocolVersion)SSLDecodeInt(progress, 2);
215 progress += 2;
216 contentLen = SSLDecodeInt(progress, 2);
217 progress += 2;
218 if (contentLen > (16384 + 2048)) /* Maximum legal length of an SSLCipherText payload */
219 { SSLFatalSessionAlert(alert_unexpected_message, ctx);
220 return ERR(SSLProtocolErr);
221 }
222
223 if (ctx->partialReadBuffer.length < 5 + contentLen)
224 { if ((err = SSLReallocBuffer(&ctx->partialReadBuffer, 5 + contentLen, &ctx->sysCtx)) != 0)
225 { SSLFatalSessionAlert(alert_close_notify, ctx);
226 return ERR(err);
227 }
228 }
229
230 if (ctx->amountRead < 5 + contentLen)
231 { readData.length = 5 + contentLen - ctx->amountRead;
232 readData.data = ctx->partialReadBuffer.data + ctx->amountRead;
233 len = readData.length;
bac41a7b
A
234 err = sslIoRead(readData, &len, ctx);
235 if(err != 0)
bac41a7b
A
236 { if (err == SSLWouldBlockErr)
237 ctx->amountRead += len;
238 else
239 SSLFatalSessionAlert(alert_close_notify, ctx);
240 return err;
241 }
242 ctx->amountRead += len;
243 }
244
245 CASSERT(ctx->amountRead >= 5 + contentLen);
246
247 cipherFragment.data = ctx->partialReadBuffer.data + 5;
248 cipherFragment.length = contentLen;
249
250/* Decrypt the payload & check the MAC, modifying the length of the buffer to indicate the
251 * amount of plaintext data after adjusting for the block size and removing the MAC
252 * (this function generates its own alerts)
253 */
29654253
A
254 assert(ctx->sslTslCalls != NULL);
255 if ((err = ctx->sslTslCalls->decryptRecord(rec->contentType,
256 &cipherFragment, ctx)) != 0)
bac41a7b
A
257 return err;
258
259/* We appear to have sucessfully received a record; increment the sequence number */
260 IncrementUInt64(&ctx->readCipher.sequenceNum);
261
262/* Allocate a buffer to return the plaintext in and return it */
263 if ((err = SSLAllocBuffer(&rec->contents, cipherFragment.length, &ctx->sysCtx)) != 0)
264 { SSLFatalSessionAlert(alert_close_notify, ctx);
265 return ERR(err);
266 }
267 memcpy(rec->contents.data, cipherFragment.data, cipherFragment.length);
268
269 ctx->amountRead = 0; /* We've used all the data in the cache */
270
271 return SSLNoErr;
272}
273
29654253
A
274/* common for sslv3 and tlsv1, except for the computeMac callout */
275SSLErr SSLVerifyMac(
276 UInt8 type,
277 SSLBuffer data,
278 UInt8 *compareMAC,
279 SSLContext *ctx)
280{
281 SSLErr err;
bac41a7b
A
282 UInt8 macData[MAX_DIGEST_SIZE];
283 SSLBuffer secret, mac;
284
285 secret.data = ctx->readCipher.macSecret;
29654253 286 secret.length = ctx->readCipher.macRef->hash->digestSize;
bac41a7b 287 mac.data = macData;
29654253
A
288 mac.length = ctx->readCipher.macRef->hash->digestSize;
289
290 assert(ctx->sslTslCalls != NULL);
291 if ((err = ctx->sslTslCalls->computeMac(type,
292 data,
293 mac,
294 &ctx->readCipher,
295 ctx->readCipher.sequenceNum,
296 ctx)) != 0)
bac41a7b
A
297 return ERR(err);
298
299 if ((memcmp(mac.data, compareMAC, mac.length)) != 0) {
29654253 300 errorLog0("ssl3VerifyMac: Mac verify failure\n");
bac41a7b
A
301 return ERR(SSLProtocolErr);
302 }
303 return SSLNoErr;
304}
305
29654253 306