]>
Commit | Line | Data |
---|---|---|
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 | */ | |
105 | SSLErr | |
106 | SSLReadRecord(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 */ |
275 | SSLErr 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 |