]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 1999-2001,2005-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 | /* | |
26 | * sslHandshake.c - SSL 3.0 handshake state machine. | |
27 | */ | |
28 | ||
29 | #include "sslContext.h" | |
30 | #include "sslHandshake.h" | |
31 | #include "sslMemory.h" | |
32 | #include "sslAlertMessage.h" | |
33 | #include "sslSession.h" | |
34 | #include "sslUtils.h" | |
35 | #include "sslDebug.h" | |
36 | #include "sslCrypto.h" | |
427c49bc | 37 | #include "sslRand.h" |
b1ab9ed8 | 38 | #include "sslDigests.h" |
427c49bc | 39 | #include "sslCipherSpecs.h" |
b1ab9ed8 A |
40 | #include "cipherSpecs.h" |
41 | ||
427c49bc A |
42 | #include <utilities/SecIOFormat.h> |
43 | ||
44 | #include <AssertMacros.h> | |
b1ab9ed8 A |
45 | #include <string.h> |
46 | #include <assert.h> | |
47 | #include <inttypes.h> | |
48 | ||
49 | #define REQUEST_CERT_CORRECT 0 | |
50 | ||
51 | #if __LP64__ | |
52 | #define PRIstatus "d" | |
53 | #else | |
54 | #define PRIstatus "ld" | |
55 | #endif | |
56 | ||
427c49bc A |
57 | |
58 | uint8_t * | |
59 | SSLEncodeHandshakeHeader(SSLContext *ctx, SSLRecord *rec, SSLHandshakeType type, size_t msglen) | |
60 | { | |
61 | uint8_t *charPtr; | |
62 | ||
63 | charPtr = rec->contents.data; | |
64 | *charPtr++ = type; | |
65 | charPtr = SSLEncodeSize(charPtr, msglen, 3); | |
66 | ||
67 | if(rec->protocolVersion == DTLS_Version_1_0) { | |
68 | charPtr = SSLEncodeInt(charPtr, ctx->hdskMessageSeq, 2); | |
69 | /* fragmentation -- we encode header as if unfragmented, | |
70 | actual fragmentation happens at lower layer. */ | |
71 | charPtr = SSLEncodeInt(charPtr, 0, 3); | |
72 | charPtr = SSLEncodeSize(charPtr, msglen, 3); | |
73 | } | |
74 | ||
75 | return charPtr; | |
76 | } | |
77 | ||
b1ab9ed8 A |
78 | static OSStatus SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx); |
79 | ||
80 | static OSStatus | |
81 | SSLUpdateHandshakeMacs(const SSLBuffer *messageData, SSLContext *ctx) | |
82 | { | |
427c49bc | 83 | OSStatus err = errSSLInternal; |
b1ab9ed8 A |
84 | bool do_md5 = false; |
85 | bool do_sha1 = false; | |
86 | bool do_sha256 = false; | |
87 | bool do_sha384 = false; | |
88 | ||
89 | //TODO: We can stop updating the unecessary hashes once the CertVerify message is processed in case where we do Client Side Auth, or . | |
90 | ||
91 | if(ctx->negProtocolVersion == SSL_Version_Undetermined) | |
92 | { | |
93 | // we dont know yet, so we might need MD5 & SHA1 - Server should always call in with known protocol version. | |
94 | assert(ctx->protocolSide==kSSLClientSide); | |
95 | do_md5 = do_sha1 = true; | |
96 | if(ctx->isDTLS | |
97 | ? ctx->maxProtocolVersion < DTLS_Version_1_0 | |
98 | : ctx->maxProtocolVersion >= TLS_Version_1_2) | |
99 | { | |
100 | // We wil need those too, unless we are sure we wont end up doing TLS 1.2 | |
101 | do_sha256 = do_sha384 = true; | |
102 | } | |
103 | } else { | |
104 | // we know which version we use at this point | |
105 | if(sslVersionIsLikeTls12(ctx)) { | |
106 | do_sha1 = do_sha256 = do_sha384 = true; | |
107 | } else { | |
108 | do_md5 = do_sha1 = true; | |
109 | } | |
110 | } | |
111 | ||
112 | if (do_md5 && | |
113 | (err = SSLHashMD5.update(&ctx->md5State, messageData)) != 0) | |
114 | goto done; | |
115 | if (do_sha1 && | |
116 | (err = SSLHashSHA1.update(&ctx->shaState, messageData)) != 0) | |
117 | goto done; | |
118 | if (do_sha256 && | |
119 | (err = SSLHashSHA256.update(&ctx->sha256State, messageData)) != 0) | |
120 | goto done; | |
121 | if (do_sha384 && | |
122 | (err = SSLHashSHA384.update(&ctx->sha512State, messageData)) != 0) | |
123 | goto done; | |
124 | ||
427c49bc | 125 | sslLogNegotiateDebug("%s protocol: %02X max: %02X cipher: %02X%s%s%s%s", |
b1ab9ed8 A |
126 | ctx->protocolSide == kSSLClientSide ? "client" : "server", |
127 | ctx->negProtocolVersion, | |
128 | ctx->maxProtocolVersion, | |
129 | ctx->selectedCipher, | |
130 | do_md5 ? " md5" : "", | |
131 | do_sha1 ? " sha1" : "", | |
132 | do_sha256 ? " sha256" : "", | |
133 | do_sha384 ? " sha384" : ""); | |
134 | done: | |
135 | return err; | |
136 | } | |
137 | ||
138 | OSStatus | |
139 | SSLProcessHandshakeRecord(SSLRecord rec, SSLContext *ctx) | |
140 | { OSStatus err; | |
141 | size_t remaining; | |
142 | UInt8 *p; | |
143 | UInt8 *startingP; // top of record we're parsing | |
144 | SSLHandshakeMsg message = {}; | |
145 | SSLBuffer messageData; | |
146 | ||
147 | if (ctx->fragmentedMessageCache.data != 0) | |
148 | { | |
149 | size_t origLen = ctx->fragmentedMessageCache.length; | |
150 | if ((err = SSLReallocBuffer(&ctx->fragmentedMessageCache, | |
427c49bc | 151 | ctx->fragmentedMessageCache.length + rec.contents.length)) != 0) |
b1ab9ed8 A |
152 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
153 | return err; | |
154 | } | |
155 | memcpy(ctx->fragmentedMessageCache.data + origLen, | |
156 | rec.contents.data, rec.contents.length); | |
157 | remaining = ctx->fragmentedMessageCache.length; | |
158 | p = ctx->fragmentedMessageCache.data; | |
159 | } | |
160 | else | |
161 | { remaining = rec.contents.length; | |
162 | p = rec.contents.data; | |
163 | } | |
164 | startingP = p; | |
165 | ||
166 | size_t head = 4; | |
167 | ||
168 | while (remaining > 0) | |
169 | { | |
170 | if (remaining < head) | |
171 | break; /* we must have at least a header */ | |
172 | ||
173 | messageData.data = p; | |
174 | message.type = (SSLHandshakeType)*p++; | |
175 | message.contents.length = SSLDecodeSize(p, 3); | |
176 | ||
177 | ||
178 | p += 3; | |
179 | ||
180 | if ((message.contents.length + head) > remaining) | |
181 | break; | |
182 | ||
183 | message.contents.data = p; | |
184 | p += message.contents.length; | |
185 | messageData.length = head + message.contents.length; | |
186 | assert(p == messageData.data + messageData.length); | |
187 | ||
188 | /* message fragmentation */ | |
189 | remaining -= messageData.length; | |
190 | if ((err = SSLProcessHandshakeMessage(message, ctx)) != 0) | |
191 | return err; | |
192 | ||
193 | if (message.type != SSL_HdskHelloRequest) | |
194 | ||
195 | { if ((err = SSLUpdateHandshakeMacs(&messageData, ctx)) != 0) | |
196 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
197 | return err; | |
198 | } | |
199 | } | |
200 | ||
201 | if ((err = SSLAdvanceHandshake(message.type, ctx)) != 0) | |
202 | return err; | |
203 | } | |
204 | ||
205 | if (remaining > 0) /* Fragmented handshake message */ | |
206 | { /* If there isn't a cache, allocate one */ | |
207 | if (ctx->fragmentedMessageCache.data == 0) | |
427c49bc | 208 | { if ((err = SSLAllocBuffer(&ctx->fragmentedMessageCache, remaining))) |
b1ab9ed8 A |
209 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
210 | return err; | |
211 | } | |
212 | } | |
213 | if (startingP != ctx->fragmentedMessageCache.data) | |
214 | { memcpy(ctx->fragmentedMessageCache.data, startingP, remaining); | |
215 | ctx->fragmentedMessageCache.length = remaining; | |
216 | } | |
217 | } | |
218 | else if (ctx->fragmentedMessageCache.data != 0) | |
427c49bc | 219 | { if ((err = SSLFreeBuffer(&ctx->fragmentedMessageCache))) |
b1ab9ed8 A |
220 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
221 | return err; | |
222 | } | |
223 | } | |
224 | ||
427c49bc | 225 | return errSecSuccess; |
b1ab9ed8 A |
226 | } |
227 | ||
228 | OSStatus | |
229 | DTLSProcessHandshakeRecord(SSLRecord rec, SSLContext *ctx) | |
230 | { OSStatus err = errSecParam; | |
231 | size_t remaining; | |
232 | UInt8 *p; | |
233 | UInt8 *startingP; // top of record we're parsing | |
234 | ||
235 | const UInt32 head = 12; | |
236 | ||
237 | assert(ctx->isDTLS); | |
238 | ||
239 | remaining = rec.contents.length; | |
240 | p = rec.contents.data; | |
241 | startingP = p; | |
242 | ||
243 | while (remaining > 0) | |
244 | { | |
245 | UInt8 msgtype; | |
246 | UInt32 msglen; | |
247 | UInt32 msgseq; | |
248 | UInt32 fraglen; | |
249 | UInt32 fragofs; | |
250 | ||
251 | if (remaining < head) { | |
252 | /* flush it - record is too small */ | |
253 | sslErrorLog("DTLSProcessHandshakeRecord: remaining too small (%lu out of %lu)\n", remaining, rec.contents.length); | |
254 | assert(0); // keep this assert until we find a test case that triggers it | |
427c49bc | 255 | err = errSSLProtocol; |
b1ab9ed8 A |
256 | goto flushit; |
257 | } | |
258 | ||
259 | /* Thats the 12 bytes of header : */ | |
260 | msgtype = (SSLHandshakeType)*p++; | |
261 | msglen = SSLDecodeInt(p, 3); p+=3; | |
262 | msgseq = SSLDecodeInt(p, 2); p+=2; | |
263 | fragofs = SSLDecodeInt(p, 3); p+=3; | |
264 | fraglen = SSLDecodeInt(p, 3); p+=3; | |
265 | ||
266 | remaining -= head; | |
267 | ||
268 | SSLLogHdskMsg(msgtype, 0); | |
427c49bc A |
269 | sslHdskMsgDebug("DTLS Hdsk Record: type=%u, len=%u, seq=%u (%u), f_ofs=%u, f_len=%u, remaining=%u", |
270 | msgtype, (int)msglen, (int)msgseq, (int)ctx->hdskMessageSeqNext, (int)fragofs, (int)fraglen, (int)remaining); | |
b1ab9ed8 A |
271 | |
272 | if( | |
273 | ((fraglen+fragofs) > msglen) | |
274 | || (fraglen > remaining) | |
275 | || (msgseq!=ctx->hdskMessageSeqNext) | |
276 | || (fragofs!=ctx->hdskMessageCurrentOfs) | |
277 | || (fragofs && (msgtype!=ctx->hdskMessageCurrent.type)) | |
278 | || (fragofs && (msglen != ctx->hdskMessageCurrent.contents.length)) | |
279 | ) | |
280 | { | |
281 | sslErrorLog("DTLSProcessHandshakeRecord: wrong fragment\n"); | |
282 | // assert(0); // keep this assert until we find a test case that triggers it | |
283 | // This is a recoverable error, we just drop this fragment. | |
284 | // TODO: this should probably trigger a retransmit | |
427c49bc | 285 | err = errSecSuccess; |
b1ab9ed8 A |
286 | goto flushit; |
287 | } | |
288 | ||
289 | /* First fragment - allocate */ | |
290 | if(fragofs==0) { | |
291 | sslHdskMsgDebug("Allocating hdsk buf for msg type %d", msgtype); | |
292 | assert(ctx->hdskMessageCurrent.contents.data==NULL); | |
293 | assert(ctx->hdskMessageCurrent.contents.length==0); | |
427c49bc | 294 | if((err=SSLAllocBuffer(&(ctx->hdskMessageCurrent.contents), msglen))) { |
b1ab9ed8 A |
295 | SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
296 | return err; | |
297 | } | |
298 | ctx->hdskMessageCurrent.type = msgtype; | |
299 | } | |
300 | ||
301 | /* We have the next fragment, lets save it */ | |
302 | memcpy(ctx->hdskMessageCurrent.contents.data + ctx->hdskMessageCurrentOfs, p, fraglen); | |
303 | ctx->hdskMessageCurrentOfs+=fraglen; | |
304 | p+=fraglen; | |
305 | remaining-=fraglen; | |
306 | ||
307 | /* This was the last fragment, lets process the message */ | |
308 | if(ctx->hdskMessageCurrentOfs == ctx->hdskMessageCurrent.contents.length) { | |
309 | err = SSLProcessHandshakeMessage(ctx->hdskMessageCurrent, ctx); | |
310 | if(err) | |
311 | goto flushit; | |
312 | ||
313 | if ((msgtype != SSL_HdskHelloRequest) && (msgtype != SSL_HdskHelloVerifyRequest)) | |
314 | { | |
315 | /* We need to hash a fake header as if no fragmentation */ | |
316 | uint8_t pseudo_header[head]; | |
317 | SSLBuffer header; | |
318 | header.data=pseudo_header; | |
319 | header.length=head; | |
320 | ||
321 | pseudo_header[0]=msgtype; | |
322 | SSLEncodeInt(pseudo_header+1, msglen, 3); | |
323 | SSLEncodeInt(pseudo_header+4, msgseq, 2); | |
324 | SSLEncodeInt(pseudo_header+6, 0, 3); | |
325 | SSLEncodeInt(pseudo_header+9, msglen, 3); | |
326 | ||
327 | if ((err = SSLHashSHA1.update(&ctx->shaState, &header)) != 0 || | |
328 | (err = SSLHashMD5.update(&ctx->md5State, &header)) != 0) | |
329 | { | |
330 | SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
331 | goto flushit; | |
332 | } | |
333 | ||
334 | SSLBuffer *messageData=&ctx->hdskMessageCurrent.contents; | |
335 | if ((err = SSLHashSHA1.update(&ctx->shaState, messageData)) != 0 || | |
336 | (err = SSLHashMD5.update(&ctx->md5State, messageData)) != 0) | |
337 | { | |
338 | SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
339 | goto flushit; | |
340 | } | |
341 | ||
427c49bc | 342 | sslHdskMsgDebug("Hashing %d bytes of msg seq %d\n", (int)messageData->length, (int)msgseq); |
b1ab9ed8 A |
343 | } |
344 | ||
345 | sslHdskMsgDebug("processed message of type %d", msgtype); | |
346 | ||
347 | if ((err = SSLAdvanceHandshake(msgtype, ctx)) != 0) | |
348 | { | |
427c49bc | 349 | sslErrorLog("AdvanceHandshake error: %" PRIdOSStatus "\n", err); |
b1ab9ed8 A |
350 | goto flushit; |
351 | } | |
352 | ||
353 | /* Free the buffer for current message, and reset offset */ | |
427c49bc | 354 | SSLFreeBuffer(&(ctx->hdskMessageCurrent.contents)); |
b1ab9ed8 A |
355 | ctx->hdskMessageCurrentOfs=0; |
356 | ||
357 | /* If we successfully processed a message, we wait for the next one */ | |
358 | ctx->hdskMessageSeqNext++; | |
359 | ||
360 | } | |
361 | ||
362 | sslHdskMsgDebug("remaining = %ld", remaining); | |
363 | } | |
364 | ||
427c49bc | 365 | return errSecSuccess; |
b1ab9ed8 A |
366 | |
367 | flushit: | |
368 | sslErrorLog("DTLSProcessHandshakeRecord: flusing record (err=%"PRIstatus")\n", err); | |
369 | ||
370 | /* This will flush the current handshake message */ | |
427c49bc | 371 | SSLFreeBuffer(&(ctx->hdskMessageCurrent.contents)); |
b1ab9ed8 A |
372 | ctx->hdskMessageCurrentOfs=0; |
373 | ||
374 | return err; | |
375 | } | |
376 | ||
377 | OSStatus | |
378 | DTLSRetransmit(SSLContext *ctx) | |
379 | { | |
380 | sslHdskMsgDebug("DTLSRetransmit in state %s. Last Sent = %d, Last Recv=%d, timeout=%f\n", | |
381 | hdskStateToStr(ctx->state), ctx->hdskMessageSeq, ctx->hdskMessageSeqNext, ctx->timeout_duration); | |
382 | ||
383 | /* Too many retransmits, just give up!! */ | |
384 | if(ctx->hdskMessageRetryCount>10) | |
385 | return errSSLConnectionRefused; | |
386 | ||
387 | /* go back to previous cipher if retransmitting a flight including changecipherspec */ | |
388 | if(ctx->messageQueueContainsChangeCipherSpec) { | |
427c49bc A |
389 | OSStatus err; |
390 | err = ctx->recFuncs->rollbackWriteCipher(ctx->recCtx); | |
391 | if(err) | |
392 | return err; | |
b1ab9ed8 A |
393 | } |
394 | ||
395 | /* set timeout deadline */ | |
396 | ctx->hdskMessageRetryCount++; | |
397 | ctx->timeout_deadline = CFAbsoluteTimeGetCurrent()+((1<<ctx->hdskMessageRetryCount)*ctx->timeout_duration); | |
398 | ||
399 | /* Lets resend the last flight */ | |
400 | return SSLSendFlight(ctx); | |
401 | } | |
402 | ||
403 | static OSStatus | |
404 | SSLProcessHandshakeMessage(SSLHandshakeMsg message, SSLContext *ctx) | |
405 | { OSStatus err; | |
406 | ||
427c49bc | 407 | err = errSecSuccess; |
b1ab9ed8 A |
408 | SSLLogHdskMsg(message.type, 0); |
409 | switch (message.type) | |
410 | { case SSL_HdskHelloRequest: | |
411 | if (ctx->protocolSide != kSSLClientSide) | |
412 | goto wrongMessage; | |
413 | if (message.contents.length > 0) | |
414 | err = errSSLProtocol; | |
415 | break; | |
416 | case SSL_HdskClientHello: | |
417 | if (ctx->state != SSL_HdskStateServerUninit) | |
418 | goto wrongMessage; | |
419 | err = SSLProcessClientHello(message.contents, ctx); | |
420 | break; | |
421 | case SSL_HdskServerHello: | |
427c49bc | 422 | if (ctx->state != SSL_HdskStateServerHello) |
b1ab9ed8 A |
423 | goto wrongMessage; |
424 | err = SSLProcessServerHello(message.contents, ctx); | |
425 | break; | |
426 | #if ENABLE_DTLS | |
427 | case SSL_HdskHelloVerifyRequest: | |
428 | if (ctx->protocolSide != kSSLClientSide) | |
429 | goto wrongMessage; | |
430 | if(ctx->state != SSL_HdskStateServerHello) | |
431 | goto wrongMessage; | |
432 | /* TODO: Do we need to check the client state here ? */ | |
433 | err = SSLProcessServerHelloVerifyRequest(message.contents, ctx); | |
434 | break; | |
435 | #endif | |
436 | case SSL_HdskCert: | |
437 | if (ctx->state != SSL_HdskStateCert && | |
438 | ctx->state != SSL_HdskStateClientCert) | |
439 | goto wrongMessage; | |
440 | err = SSLProcessCertificate(message.contents, ctx); | |
441 | /* | |
442 | * Note that cert evaluation can now be performed asynchronously, | |
443 | * so SSLProcessCertificate may return errSSLWouldBlock here. | |
444 | */ | |
445 | break; | |
446 | case SSL_HdskCertRequest: | |
447 | if (((ctx->state != SSL_HdskStateHelloDone) && | |
448 | (ctx->state != SSL_HdskStateKeyExchange)) | |
449 | || ctx->certRequested) | |
450 | goto wrongMessage; | |
451 | err = SSLProcessCertificateRequest(message.contents, ctx); | |
452 | if (ctx->breakOnCertRequest) | |
453 | ctx->signalCertRequest = true; | |
454 | break; | |
455 | case SSL_HdskServerKeyExchange: | |
456 | /* | |
457 | * Since this message is optional for some key exchange | |
458 | * mechanisms, and completely at the server's discretion, | |
459 | * we need to be able to handle this in one of two states... | |
460 | */ | |
461 | switch(ctx->state) { | |
462 | case SSL_HdskStateKeyExchange: /* explicitly waiting for this */ | |
463 | case SSL_HdskStateHelloDone: | |
464 | break; | |
465 | default: | |
466 | goto wrongMessage; | |
467 | } | |
468 | err = SSLProcessServerKeyExchange(message.contents, ctx); | |
469 | break; | |
470 | case SSL_HdskServerHelloDone: | |
471 | if (ctx->state != SSL_HdskStateHelloDone) | |
472 | goto wrongMessage; | |
473 | err = SSLProcessServerHelloDone(message.contents, ctx); | |
474 | break; | |
475 | case SSL_HdskCertVerify: | |
476 | if (ctx->state != SSL_HdskStateClientCertVerify) | |
477 | goto wrongMessage; | |
478 | err = SSLProcessCertificateVerify(message.contents, ctx); | |
479 | assert(ctx->protocolSide == kSSLServerSide); | |
480 | if(err) { | |
481 | ctx->clientCertState = kSSLClientCertRejected; | |
482 | } | |
483 | break; | |
484 | case SSL_HdskClientKeyExchange: | |
485 | if (ctx->state != SSL_HdskStateClientKeyExchange) | |
486 | goto wrongMessage; | |
487 | err = SSLProcessKeyExchange(message.contents, ctx); | |
488 | break; | |
489 | case SSL_HdskFinished: | |
490 | if (ctx->state != SSL_HdskStateFinished) | |
491 | goto wrongMessage; | |
492 | err = SSLProcessFinished(message.contents, ctx); | |
493 | break; | |
494 | default: | |
495 | goto wrongMessage; | |
496 | break; | |
497 | } | |
498 | ||
499 | if (err && !ctx->sentFatalAlert) | |
500 | { if (err == errSSLProtocol) | |
501 | SSLFatalSessionAlert(SSL_AlertIllegalParam, ctx); | |
502 | else if (err == errSSLNegotiation) | |
503 | SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx); | |
504 | else if (err != errSSLWouldBlock && | |
505 | err != errSSLServerAuthCompleted /* == errSSLClientAuthCompleted */ && | |
506 | err != errSSLClientCertRequested) | |
507 | SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx); | |
508 | } | |
509 | return err; | |
510 | ||
511 | wrongMessage: | |
512 | SSLFatalSessionAlert(SSL_AlertUnexpectedMsg, ctx); | |
513 | return errSSLProtocol; | |
514 | } | |
515 | ||
516 | /* | |
517 | * Given a server-side SSLContext that's fully restored for a resumed session, | |
518 | * queue up the remaining outgoing messages to finish the handshake. | |
519 | */ | |
520 | static OSStatus | |
521 | SSLResumeServerSide( | |
522 | SSLContext *ctx) | |
523 | { | |
524 | OSStatus err; | |
525 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, ctx)) != 0) | |
526 | return err; | |
527 | if ((err = SSLInitPendingCiphers(ctx)) != 0) | |
528 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
529 | return err; | |
530 | } | |
531 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, | |
532 | ctx)) != 0) | |
533 | return err; | |
534 | ||
535 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, | |
536 | ctx)) != 0) | |
537 | return err; | |
538 | ||
539 | SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); | |
540 | ||
427c49bc | 541 | return errSecSuccess; |
b1ab9ed8 A |
542 | |
543 | } | |
544 | ||
545 | OSStatus | |
546 | SSLAdvanceHandshake(SSLHandshakeType processed, SSLContext *ctx) | |
547 | { OSStatus err; | |
548 | SSLBuffer sessionIdentifier; | |
549 | ||
550 | SSLResetFlight(ctx); | |
551 | ||
552 | switch (processed) | |
553 | { | |
554 | #if ENABLE_DTLS | |
555 | case SSL_HdskHelloVerifyRequest: | |
556 | /* Just fall through */ | |
557 | #endif | |
558 | case SSL_HdskHelloRequest: | |
559 | /* | |
560 | * Reset the client auth state machine in case this is | |
561 | * a renegotiation. | |
562 | */ | |
563 | ctx->certRequested = 0; | |
564 | ctx->certSent = 0; | |
565 | ctx->certReceived = 0; | |
566 | ctx->x509Requested = 0; | |
567 | ctx->clientCertState = kSSLClientCertNone; | |
427c49bc A |
568 | ctx->readCipher_ready = 0; |
569 | ctx->writeCipher_ready = 0; | |
b1ab9ed8 A |
570 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeClientHello, ctx)) != 0) |
571 | return err; | |
572 | SSLChangeHdskState(ctx, SSL_HdskStateServerHello); | |
573 | break; | |
574 | case SSL_HdskClientHello: | |
575 | assert(ctx->protocolSide == kSSLServerSide); | |
576 | ctx->sessionMatch = 0; | |
577 | ||
578 | if((ctx->negProtocolVersion==DTLS_Version_1_0) && (ctx->cookieVerified==false)) | |
579 | { /* Send Hello Verify Request */ | |
580 | if((err=SSLPrepareAndQueueMessage(SSLEncodeServerHelloVerifyRequest, ctx)) !=0 ) | |
581 | return err; | |
582 | break; | |
583 | } | |
584 | ||
585 | #if SSL_PAC_SERVER_ENABLE | |
586 | if((ctx->sessionTicket.data != NULL) && | |
587 | (ctx->masterSecretCallback != NULL)) { | |
588 | /* | |
589 | * Client sent us a session ticket and we know how to ask | |
590 | * the app for master secret. Go for it. | |
591 | */ | |
592 | size_t secretLen = SSL_MASTER_SECRET_SIZE; | |
593 | sslEapDebug("Server side resuming based on masterSecretCallback"); | |
594 | ||
595 | /* the master secret callback requires serverRandom, now... */ | |
596 | if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0) | |
597 | return err; | |
598 | ctx->serverRandomValid = 1; | |
599 | ||
600 | ctx->masterSecretCallback(ctx, ctx->masterSecretArg, | |
601 | ctx->masterSecret, &secretLen); | |
602 | ctx->sessionMatch = 1; | |
603 | /* set up selectedCipherSpec */ | |
604 | if ((err = FindCipherSpec(ctx)) != 0) { | |
605 | return err; | |
606 | } | |
607 | /* queue up remaining messages to finish handshake */ | |
608 | if((err = SSLResumeServerSide(ctx)) != 0) | |
609 | return err; | |
610 | break; | |
611 | } | |
612 | #endif /* SSL_PAC_SERVER_ENABLE */ | |
613 | if (ctx->sessionID.data != 0) | |
614 | /* If session ID != 0, client is trying to resume */ | |
615 | { if (ctx->resumableSession.data != 0) | |
616 | { | |
617 | SSLProtocolVersion sessionProt; | |
618 | if ((err = SSLRetrieveSessionID(ctx->resumableSession, | |
619 | &sessionIdentifier, ctx)) != 0) | |
620 | return err; | |
621 | if ((err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession, | |
622 | &sessionProt, ctx)) != 0) | |
623 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
624 | return err; | |
625 | } | |
626 | if ((sessionIdentifier.length == ctx->sessionID.length) && | |
627 | (memcmp(sessionIdentifier.data, ctx->sessionID.data, | |
628 | ctx->sessionID.length) == 0) && | |
629 | (sessionProt == ctx->negProtocolVersion)) | |
630 | { /* Everything matches; resume the session */ | |
631 | sslLogResumSessDebug("===RESUMING SSL3 server-side session"); | |
632 | if ((err = SSLInstallSessionFromData(ctx->resumableSession, | |
633 | ctx)) != 0) | |
634 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
635 | return err; | |
636 | } | |
637 | ctx->sessionMatch = 1; | |
427c49bc | 638 | SSLFreeBuffer(&sessionIdentifier); |
b1ab9ed8 A |
639 | |
640 | /* queue up remaining messages to finish handshake */ | |
641 | if((err = SSLResumeServerSide(ctx)) != 0) | |
642 | return err; | |
643 | break; | |
644 | } | |
645 | else { | |
646 | sslLogResumSessDebug( | |
647 | "===FAILED TO RESUME SSL3 server-side session"); | |
648 | } | |
427c49bc | 649 | if ((err = SSLFreeBuffer(&sessionIdentifier)) != 0 || |
b1ab9ed8 A |
650 | (err = SSLDeleteSessionData(ctx)) != 0) |
651 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
652 | return err; | |
653 | } | |
654 | } | |
427c49bc | 655 | if ((err = SSLFreeBuffer(&ctx->sessionID)) != 0) |
b1ab9ed8 A |
656 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
657 | return err; | |
658 | } | |
659 | } | |
660 | ||
661 | /* | |
662 | * If we get here, we're not resuming; generate a new session ID | |
663 | * if we know our peer | |
664 | */ | |
665 | if (ctx->peerID.data != 0) | |
666 | { /* Ignore errors; just treat as uncached session */ | |
667 | assert(ctx->sessionID.data == 0); | |
427c49bc | 668 | err = SSLAllocBuffer(&ctx->sessionID, SSL_SESSION_ID_LEN); |
b1ab9ed8 | 669 | if (err == 0) |
427c49bc A |
670 | { |
671 | if((err = sslRand(&ctx->sessionID)) != 0) | |
b1ab9ed8 A |
672 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
673 | return err; | |
674 | } | |
675 | } | |
676 | } | |
677 | ||
678 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHello, ctx)) != 0) | |
679 | return err; | |
427c49bc | 680 | switch (ctx->selectedCipherSpecParams.keyExchangeMethod) |
b1ab9ed8 A |
681 | { case SSL_NULL_auth: |
682 | #if APPLE_DH | |
683 | case SSL_DH_anon: | |
427c49bc | 684 | case SSL_ECDH_anon: |
b1ab9ed8 A |
685 | if(ctx->clientAuth == kAlwaysAuthenticate) { |
686 | /* app requires this; abort */ | |
687 | SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx); | |
688 | return errSSLNegotiation; | |
689 | } | |
690 | ctx->tryClientAuth = false; | |
691 | /* DH server side needs work */ | |
692 | break; | |
693 | #endif /* APPLE_DH */ | |
427c49bc A |
694 | case TLS_PSK: |
695 | /* skip the cert */ | |
696 | break; | |
697 | ||
698 | case SSL_RSA: | |
699 | case SSL_DH_DSS: | |
700 | case SSL_DH_RSA: | |
701 | case SSL_DHE_DSS: | |
702 | case SSL_DHE_RSA: | |
703 | case SSL_ECDH_ECDSA: | |
704 | case SSL_ECDHE_ECDSA: | |
705 | case SSL_ECDH_RSA: | |
706 | case SSL_ECDHE_RSA: | |
b1ab9ed8 A |
707 | if(ctx->localCert == NULL) { |
708 | /* no cert but configured for, and negotiated, a | |
709 | * ciphersuite which requires one */ | |
710 | sslErrorLog("SSLAdvanceHandshake: No server key!\n"); | |
711 | return errSSLBadConfiguration; | |
712 | } | |
713 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate, | |
714 | ctx)) != 0) | |
715 | return err; | |
716 | break; | |
427c49bc A |
717 | |
718 | default: /* everything else */ | |
719 | sslErrorLog("SSLAdvanceHandshake: Unsupported KEM!\n"); | |
720 | return errSSLInternal; | |
b1ab9ed8 A |
721 | } |
722 | /* | |
723 | * At this point we decide whether to send a server key exchange | |
724 | * method. For Apple servers, I think we'll ALWAYS do this, because | |
725 | * of key usage restrictions (can't decrypt and sign with the same | |
726 | * private key), but conceptually in this code, we do it if | |
727 | * enabled by the presence of encryptPrivKey. | |
728 | */ | |
729 | { | |
730 | bool doServerKeyExch = false; | |
427c49bc | 731 | switch(ctx->selectedCipherSpecParams.keyExchangeMethod) { |
b1ab9ed8 | 732 | case SSL_RSA: |
b1ab9ed8 A |
733 | if(ctx->encryptPrivKeyRef != NULL) { |
734 | doServerKeyExch = true; | |
735 | } | |
736 | break; | |
737 | case SSL_DH_anon: | |
b1ab9ed8 | 738 | case SSL_DHE_RSA: |
b1ab9ed8 | 739 | case SSL_DHE_DSS: |
b1ab9ed8 A |
740 | doServerKeyExch = true; |
741 | break; | |
427c49bc | 742 | default: /* In all other cases, we don't send a ServerkeyExchange message */ |
b1ab9ed8 A |
743 | break; |
744 | } | |
745 | if(doServerKeyExch) { | |
746 | err = SSLPrepareAndQueueMessage(SSLEncodeServerKeyExchange, ctx); | |
747 | if(err) { | |
748 | return err; | |
749 | } | |
750 | } | |
751 | } | |
752 | if (ctx->tryClientAuth) | |
753 | { if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateRequest, | |
754 | ctx)) != 0) | |
755 | return err; | |
756 | ctx->certRequested = 1; | |
757 | ctx->clientCertState = kSSLClientCertRequested; | |
758 | } | |
759 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeServerHelloDone, ctx)) != 0) | |
760 | return err; | |
761 | if (ctx->certRequested) { | |
762 | SSLChangeHdskState(ctx, SSL_HdskStateClientCert); | |
763 | } | |
764 | else { | |
765 | SSLChangeHdskState(ctx, SSL_HdskStateClientKeyExchange); | |
766 | } | |
767 | break; | |
768 | case SSL_HdskServerHello: | |
769 | ctx->sessionMatch = 0; | |
770 | if (ctx->resumableSession.data != 0 && ctx->sessionID.data != 0) | |
771 | { | |
772 | SSLProtocolVersion sessionProt; | |
773 | if ((err = SSLRetrieveSessionID(ctx->resumableSession, | |
774 | &sessionIdentifier, ctx)) != 0) | |
775 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
776 | return err; | |
777 | } | |
778 | if ((err = SSLRetrieveSessionProtocolVersion(ctx->resumableSession, | |
779 | &sessionProt, ctx)) != 0) | |
780 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
781 | return err; | |
782 | } | |
783 | if ((sessionIdentifier.length == ctx->sessionID.length) && | |
784 | (memcmp(sessionIdentifier.data, ctx->sessionID.data, | |
785 | ctx->sessionID.length) == 0) && | |
786 | (sessionProt == ctx->negProtocolVersion)) | |
787 | { /* Everything matches; resume the session */ | |
788 | sslLogResumSessDebug("===RESUMING SSL3 client-side session"); | |
789 | if ((err = SSLInstallSessionFromData(ctx->resumableSession, | |
790 | ctx)) != 0 || | |
791 | (err = SSLInitPendingCiphers(ctx)) != 0 || | |
427c49bc | 792 | (err = SSLFreeBuffer(&sessionIdentifier)) != 0) |
b1ab9ed8 A |
793 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
794 | return err; | |
795 | } | |
796 | ctx->sessionMatch = 1; | |
797 | SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); | |
798 | break; | |
799 | } | |
800 | else { | |
801 | sslLogResumSessDebug("===FAILED TO RESUME SSL3 client-side " | |
802 | "session"); | |
803 | } | |
427c49bc | 804 | if ((err = SSLFreeBuffer(&sessionIdentifier)) != 0) |
b1ab9ed8 A |
805 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
806 | return err; | |
807 | } | |
808 | } | |
427c49bc A |
809 | switch (ctx->selectedCipherSpecParams.keyExchangeMethod) |
810 | { | |
b1ab9ed8 A |
811 | /* these require a key exchange message */ |
812 | case SSL_NULL_auth: | |
813 | case SSL_DH_anon: | |
b1ab9ed8 A |
814 | SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange); |
815 | break; | |
816 | case SSL_RSA: | |
817 | case SSL_DH_DSS: | |
b1ab9ed8 | 818 | case SSL_DH_RSA: |
b1ab9ed8 A |
819 | case SSL_RSA_EXPORT: |
820 | case SSL_DHE_DSS: | |
b1ab9ed8 | 821 | case SSL_DHE_RSA: |
b1ab9ed8 A |
822 | case SSL_Fortezza: |
823 | case SSL_ECDH_ECDSA: | |
824 | case SSL_ECDHE_ECDSA: | |
825 | case SSL_ECDH_RSA: | |
826 | case SSL_ECDHE_RSA: | |
827 | SSLChangeHdskState(ctx, SSL_HdskStateCert); | |
828 | break; | |
427c49bc A |
829 | case TLS_PSK: |
830 | SSLChangeHdskState(ctx, SSL_HdskStateHelloDone); | |
831 | break; | |
b1ab9ed8 A |
832 | default: |
833 | assert("Unknown key exchange method"); | |
834 | break; | |
835 | } | |
836 | break; | |
837 | case SSL_HdskCert: | |
838 | if (ctx->state == SSL_HdskStateCert) | |
427c49bc | 839 | switch (ctx->selectedCipherSpecParams.keyExchangeMethod) |
b1ab9ed8 A |
840 | { case SSL_RSA: |
841 | /* | |
842 | * I really think the two RSA cases should be | |
843 | * handled the same here - the server key exchange is | |
844 | * optional, and is up to the server. | |
845 | * Note this isn't the same as SSL_SERVER_KEYEXCH_HACK; | |
846 | * we're a client here. | |
847 | */ | |
b1ab9ed8 | 848 | case SSL_DH_DSS: |
b1ab9ed8 | 849 | case SSL_DH_RSA: |
b1ab9ed8 A |
850 | case SSL_ECDH_ECDSA: |
851 | case SSL_ECDH_RSA: | |
852 | SSLChangeHdskState(ctx, SSL_HdskStateHelloDone); | |
853 | break; | |
854 | case SSL_DHE_DSS: | |
b1ab9ed8 | 855 | case SSL_DHE_RSA: |
b1ab9ed8 A |
856 | case SSL_Fortezza: |
857 | case SSL_ECDHE_ECDSA: | |
858 | case SSL_ECDHE_RSA: | |
859 | SSLChangeHdskState(ctx, SSL_HdskStateKeyExchange); | |
860 | break; | |
861 | default: | |
862 | assert("Unknown or unexpected key exchange method"); | |
863 | break; | |
864 | } | |
865 | else if (ctx->state == SSL_HdskStateClientCert) | |
866 | { SSLChangeHdskState(ctx, SSL_HdskStateClientKeyExchange); | |
867 | if (ctx->peerCert != 0) | |
868 | ctx->certReceived = 1; | |
869 | } | |
870 | break; | |
871 | case SSL_HdskCertRequest: | |
872 | /* state stays in SSL_HdskStateHelloDone; distinction is in | |
873 | * ctx->certRequested */ | |
874 | if (ctx->peerCert == 0) | |
875 | { SSLFatalSessionAlert(SSL_AlertHandshakeFail, ctx); | |
876 | return errSSLProtocol; | |
877 | } | |
878 | assert(ctx->protocolSide == kSSLClientSide); | |
879 | ctx->certRequested = 1; | |
880 | ctx->clientCertState = kSSLClientCertRequested; | |
881 | break; | |
882 | case SSL_HdskServerKeyExchange: | |
883 | SSLChangeHdskState(ctx, SSL_HdskStateHelloDone); | |
884 | break; | |
885 | case SSL_HdskServerHelloDone: | |
886 | /* | |
887 | * Waiting until server has sent hello done to interrupt and allow | |
888 | * setting client cert, so we can send certificate, keyexchange and | |
889 | * cert verify message together | |
890 | */ | |
891 | if (ctx->state != SSL_HdskStateClientCert) { | |
892 | if (ctx->signalServerAuth) { | |
893 | ctx->signalServerAuth = false; | |
894 | SSLChangeHdskState(ctx, SSL_HdskStateClientCert); | |
895 | return errSSLServerAuthCompleted; | |
896 | } else if (ctx->signalCertRequest) { | |
897 | ctx->signalCertRequest = false; | |
898 | SSLChangeHdskState(ctx, SSL_HdskStateClientCert); | |
899 | return errSSLClientCertRequested; | |
900 | } else if (ctx->signalClientAuth) { | |
901 | ctx->signalClientAuth = false; | |
902 | return errSSLClientAuthCompleted; | |
903 | } | |
904 | } | |
905 | ||
906 | if (ctx->clientCertState == kSSLClientCertRequested) { | |
907 | /* | |
908 | * Server wants a client authentication cert - do | |
909 | * we have one? | |
910 | */ | |
911 | if (ctx->localCert != 0 && ctx->x509Requested) { | |
912 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate, | |
913 | ctx)) != 0) { | |
914 | return err; | |
915 | } | |
916 | } | |
917 | else { | |
918 | /* response for no cert depends on protocol version */ | |
919 | if(ctx->negProtocolVersion >= TLS_Version_1_0) { | |
920 | /* TLS: send empty cert msg */ | |
921 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificate, | |
922 | ctx)) != 0) { | |
923 | return err; | |
924 | } | |
925 | } | |
926 | else { | |
927 | /* SSL3: "no cert" alert */ | |
928 | if ((err = SSLSendAlert(SSL_AlertLevelWarning, SSL_AlertNoCert_RESERVED, | |
929 | ctx)) != 0) { | |
930 | return err; | |
931 | } | |
932 | } | |
933 | } /* no cert to send */ | |
934 | } /* server requested a cert */ | |
935 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeKeyExchange, ctx)) != 0) | |
936 | return err; | |
937 | assert(ctx->sslTslCalls != NULL); | |
938 | if ((err = ctx->sslTslCalls->generateMasterSecret(ctx)) != 0 || | |
939 | (err = SSLInitPendingCiphers(ctx)) != 0) | |
940 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
941 | return err; | |
942 | } | |
943 | memset(ctx->preMasterSecret.data, 0, ctx->preMasterSecret.length); | |
427c49bc | 944 | if ((err = SSLFreeBuffer(&ctx->preMasterSecret))) { |
b1ab9ed8 A |
945 | return err; |
946 | } | |
947 | if (ctx->certSent) { | |
948 | /* Not all client auth mechanisms require a cert verify message */ | |
949 | switch(ctx->negAuthType) { | |
950 | case SSLClientAuth_RSASign: | |
951 | case SSLClientAuth_ECDSASign: | |
952 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeCertificateVerify, | |
953 | ctx)) != 0) { | |
954 | return err; | |
955 | } | |
956 | break; | |
957 | default: | |
958 | break; | |
959 | } | |
960 | } | |
961 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, | |
962 | ctx)) != 0) { | |
963 | return err; | |
964 | } | |
965 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, ctx)) != 0) | |
966 | return err; | |
967 | SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); | |
968 | break; | |
969 | case SSL_HdskCertVerify: | |
970 | SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); | |
971 | break; | |
972 | case SSL_HdskClientKeyExchange: | |
973 | assert(ctx->sslTslCalls != NULL); | |
974 | if ((err = ctx->sslTslCalls->generateMasterSecret(ctx)) != 0 || | |
975 | (err = SSLInitPendingCiphers(ctx)) != 0) | |
976 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
977 | return err; | |
978 | } | |
979 | memset(ctx->preMasterSecret.data, 0, ctx->preMasterSecret.length); | |
427c49bc | 980 | if ((err = SSLFreeBuffer(&ctx->preMasterSecret))) |
b1ab9ed8 A |
981 | return err; |
982 | if (ctx->certReceived) { | |
983 | SSLChangeHdskState(ctx, SSL_HdskStateClientCertVerify); | |
984 | } | |
985 | else { | |
986 | SSLChangeHdskState(ctx, SSL_HdskStateChangeCipherSpec); | |
987 | } | |
988 | break; | |
989 | case SSL_HdskFinished: | |
990 | /* Handshake is over; enable data transfer on read channel */ | |
427c49bc A |
991 | ctx->readCipher_ready = 1; |
992 | /* If writePending is set, we haven't yet sent a finished message; | |
b1ab9ed8 | 993 | * send it */ |
427c49bc A |
994 | /* Note: If using session resumption, the client will hit this, otherwise the server will */ |
995 | if (ctx->writePending_ready != 0) | |
996 | { if ((err = SSLPrepareAndQueueMessage(SSLEncodeChangeCipherSpec, | |
b1ab9ed8 A |
997 | ctx)) != 0) |
998 | return err; | |
999 | if ((err = SSLPrepareAndQueueMessage(SSLEncodeFinishedMessage, | |
1000 | ctx)) != 0) | |
1001 | return err; | |
1002 | } | |
1003 | if (ctx->protocolSide == kSSLServerSide) { | |
1004 | SSLChangeHdskState(ctx, SSL_HdskStateServerReady); | |
1005 | } | |
1006 | else { | |
1007 | SSLChangeHdskState(ctx, SSL_HdskStateClientReady); | |
1008 | } | |
1009 | if ((ctx->peerID.data != 0) && (ctx->sessionTicket.data == NULL)) { | |
1010 | /* note we avoid caching session data for PAC-style resumption */ | |
1011 | SSLAddSessionData(ctx); | |
1012 | } | |
1013 | break; | |
1014 | default: | |
1015 | assert(0); | |
1016 | break; | |
1017 | } | |
1018 | ||
1019 | /* We should have a full flight when we reach here, sending it for the first time */ | |
1020 | ctx->hdskMessageRetryCount = 0; | |
1021 | ctx->timeout_deadline = CFAbsoluteTimeGetCurrent() + ctx->timeout_duration; | |
1022 | return SSLSendFlight(ctx); | |
1023 | } | |
1024 | ||
1025 | OSStatus | |
1026 | SSLPrepareAndQueueMessage(EncodeMessageFunc msgFunc, SSLContext *ctx) | |
1027 | { OSStatus err; | |
1028 | SSLRecord rec = {0, 0, {0, NULL}}; | |
1029 | WaitingMessage *out; | |
1030 | WaitingMessage *queue; | |
1031 | ||
1032 | if ((err = msgFunc(&rec, ctx)) != 0) | |
1033 | { SSLFatalSessionAlert(SSL_AlertCloseNotify, ctx); | |
1034 | goto fail; | |
1035 | } | |
1036 | ||
1037 | if (rec.contentType == SSL_RecordTypeHandshake) | |
1038 | { | |
1039 | if ((err = SSLUpdateHandshakeMacs(&rec.contents, ctx)) != 0) | |
1040 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
1041 | goto fail; | |
1042 | } | |
1043 | SSLLogHdskMsg((SSLHandshakeType)rec.contents.data[0], 1); | |
1044 | ctx->hdskMessageSeq++; | |
1045 | } | |
1046 | ||
1047 | err=errSSLInternal; | |
1048 | out = (WaitingMessage *)sslMalloc(sizeof(WaitingMessage)); | |
1049 | if(out==NULL) goto fail; | |
1050 | ||
1051 | out->next = NULL; | |
1052 | out->rec = rec; | |
1053 | ||
1054 | queue=ctx->messageWriteQueue; | |
1055 | if (queue == NULL) { | |
1056 | sslHdskMsgDebug("Queuing first message in flight\n"); | |
1057 | ctx->messageWriteQueue = out; | |
1058 | } else { | |
1059 | int n=1; | |
1060 | while (queue->next != 0) { | |
1061 | queue = queue->next; | |
1062 | n++; | |
1063 | } | |
1064 | sslHdskMsgDebug("Queuing message %d in flight\n", n); | |
1065 | queue->next = out; | |
1066 | } | |
1067 | ||
427c49bc | 1068 | return errSecSuccess; |
b1ab9ed8 | 1069 | fail: |
427c49bc | 1070 | SSLFreeBuffer(&rec.contents); |
b1ab9ed8 A |
1071 | return err; |
1072 | } | |
1073 | ||
1074 | static | |
1075 | OSStatus SSLSendMessage(SSLRecord rec, SSLContext *ctx) | |
1076 | { | |
1077 | OSStatus err; | |
1078 | ||
b1ab9ed8 | 1079 | |
427c49bc | 1080 | if ((err = SSLWriteRecord(rec, ctx)) != 0) |
b1ab9ed8 A |
1081 | return err; |
1082 | if(rec.contentType == SSL_RecordTypeChangeCipher) { | |
1083 | /* Install new cipher spec on write side */ | |
427c49bc A |
1084 | /* Can't send data until Finished is sent */ |
1085 | ctx->writeCipher_ready = 0; | |
1086 | ctx->wroteAppData = 0; | |
1087 | ||
1088 | if ((err = ctx->recFuncs->advanceWriteCipher(ctx->recCtx)) != 0) | |
b1ab9ed8 A |
1089 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
1090 | return err; | |
1091 | } | |
b1ab9ed8 | 1092 | |
427c49bc A |
1093 | /* pending cipher is invalid now - this is currently used to figure out if we need |
1094 | to send out the last flight */ | |
1095 | ctx->writePending_ready = 0; | |
b1ab9ed8 A |
1096 | |
1097 | /* TODO: that should only happen after Finished message is sent. <rdar://problem/9682471> */ | |
427c49bc | 1098 | ctx->writeCipher_ready = 1; |
b1ab9ed8 A |
1099 | } |
1100 | ||
427c49bc | 1101 | return errSecSuccess; |
b1ab9ed8 A |
1102 | } |
1103 | ||
1104 | static | |
1105 | OSStatus DTLSSendMessage(SSLRecord rec, SSLContext *ctx) | |
1106 | { | |
427c49bc | 1107 | OSStatus err=errSecSuccess; |
b1ab9ed8 A |
1108 | |
1109 | if(rec.contentType != SSL_RecordTypeHandshake) { | |
427c49bc A |
1110 | sslHdskMsgDebug("Not fragmenting message type=%d len=%d\n", (int)rec.contentType, (int)rec.contents.length); |
1111 | if ((err = SSLWriteRecord(rec, ctx)) != 0) | |
b1ab9ed8 A |
1112 | return err; |
1113 | if(rec.contentType == SSL_RecordTypeChangeCipher) { | |
427c49bc A |
1114 | /* Can't send data until Finished is sent */ |
1115 | ctx->writeCipher_ready = 0; | |
1116 | ctx->wroteAppData = 0; | |
1117 | ||
b1ab9ed8 | 1118 | /* Install new cipher spec on write side */ |
427c49bc | 1119 | if ((err = ctx->recFuncs->advanceWriteCipher(ctx->recCtx)) != 0) |
b1ab9ed8 A |
1120 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); |
1121 | return err; | |
1122 | } | |
b1ab9ed8 | 1123 | |
427c49bc A |
1124 | /* pending cipher is invalid now - this is currently used to figure out if we need |
1125 | to send out the last flight */ | |
1126 | ctx->writePending_ready = 0; | |
b1ab9ed8 A |
1127 | |
1128 | /* TODO: that should only happen after Finished message is sent. See <rdar://problem/9682471> */ | |
427c49bc | 1129 | ctx->writeCipher_ready = 1; |
b1ab9ed8 A |
1130 | |
1131 | } | |
1132 | } else { | |
1133 | /* fragmenting */ | |
1134 | SSLRecord fragrec; | |
1135 | ||
1136 | int msghead = 12; /* size of message header in DTLS */ | |
1137 | size_t fraglen; | |
1138 | size_t len = rec.contents.length-msghead; | |
1139 | UInt32 seq = SSLDecodeInt(rec.contents.data+4, 2); | |
1140 | (void) seq; // Suppress warnings | |
1141 | size_t ofs = 0; | |
1142 | ||
427c49bc | 1143 | sslHdskMsgDebug("Fragmenting msg seq %d (rl=%d, ml=%d)", (int)seq, (int)rec.contents.length, |
b1ab9ed8 A |
1144 | SSLDecodeInt(rec.contents.data+1, 3)); |
1145 | ||
1146 | ||
1147 | SSLGetDatagramWriteSize(ctx, &fraglen); | |
1148 | fraglen -= msghead; | |
1149 | ||
1150 | fragrec.contentType = rec.contentType; | |
1151 | fragrec.protocolVersion = rec.protocolVersion; | |
427c49bc | 1152 | if((err=SSLAllocBuffer(&fragrec.contents, fraglen + msghead))) |
b1ab9ed8 A |
1153 | return err; |
1154 | ||
1155 | /* copy the constant part of the header */ | |
1156 | memcpy(fragrec.contents.data,rec.contents.data, 6); | |
1157 | ||
1158 | while(len>fraglen) { | |
1159 | ||
427c49bc | 1160 | sslHdskMsgDebug("Fragmenting msg seq %d (o=%d,l=%d)", (int)seq, (int)ofs, (int)fraglen); |
b1ab9ed8 A |
1161 | |
1162 | /* fragment offset and fragment length */ | |
1163 | SSLEncodeSize(fragrec.contents.data+6, ofs, 3); | |
1164 | SSLEncodeSize(fragrec.contents.data+9, fraglen, 3); | |
1165 | /* copy the payload */ | |
1166 | memcpy(fragrec.contents.data+msghead, rec.contents.data+msghead+ofs, fraglen); | |
427c49bc | 1167 | if ((err = SSLWriteRecord(fragrec, ctx)) != 0) |
b1ab9ed8 A |
1168 | goto cleanup; |
1169 | len-=fraglen; | |
1170 | ofs+=fraglen; | |
1171 | } | |
1172 | ||
427c49bc | 1173 | sslHdskMsgDebug("Fragmenting msg seq %d - Last Fragment (o=%d,l=%d)", (int)seq, (int)ofs, (int)len); |
b1ab9ed8 A |
1174 | |
1175 | /* last fragment */ | |
1176 | /* fragment offset and fragment length */ | |
1177 | SSLEncodeSize(fragrec.contents.data+6, ofs, 3); | |
1178 | SSLEncodeSize(fragrec.contents.data+9, len, 3); | |
1179 | /* copy the payload */ | |
1180 | memcpy(fragrec.contents.data+msghead, rec.contents.data+msghead+ofs, len); | |
1181 | fragrec.contents.length=len+msghead; | |
427c49bc | 1182 | err = SSLWriteRecord(fragrec, ctx); |
b1ab9ed8 A |
1183 | |
1184 | cleanup: | |
1185 | /* Free the allocated fragment buffer */ | |
427c49bc | 1186 | SSLFreeBuffer(&fragrec.contents); |
b1ab9ed8 A |
1187 | |
1188 | } | |
1189 | ||
1190 | return err; | |
1191 | } | |
1192 | ||
1193 | ||
1194 | OSStatus SSLResetFlight(SSLContext *ctx) | |
1195 | { | |
1196 | OSStatus err; | |
1197 | WaitingMessage *queue; | |
1198 | WaitingMessage *next; | |
1199 | int n=0; | |
1200 | ||
b1ab9ed8 A |
1201 | queue=ctx->messageWriteQueue; |
1202 | ctx->messageQueueContainsChangeCipherSpec=false; | |
1203 | ||
1204 | while(queue) { | |
1205 | n++; | |
427c49bc | 1206 | err = SSLFreeBuffer(&queue->rec.contents); |
b1ab9ed8 A |
1207 | if (err != 0) |
1208 | goto fail; | |
1209 | next=queue->next; | |
1210 | sslFree(queue); | |
1211 | queue=next; | |
1212 | } | |
1213 | ||
1214 | ctx->messageWriteQueue=NULL; | |
1215 | ||
427c49bc | 1216 | return errSecSuccess; |
b1ab9ed8 | 1217 | fail: |
427c49bc | 1218 | check_noerr(err); |
b1ab9ed8 A |
1219 | return err; |
1220 | } | |
1221 | ||
b1ab9ed8 A |
1222 | OSStatus SSLSendFlight(SSLContext *ctx) |
1223 | { | |
1224 | OSStatus err; | |
1225 | WaitingMessage *queue; | |
1226 | int n=0; | |
1227 | ||
b1ab9ed8 A |
1228 | queue=ctx->messageWriteQueue; |
1229 | ||
1230 | while(queue) { | |
1231 | if (ctx->isDTLS) { | |
1232 | err=DTLSSendMessage(queue->rec, ctx); | |
1233 | } else { | |
1234 | err=SSLSendMessage(queue->rec, ctx); | |
1235 | } | |
1236 | if (err != 0) | |
1237 | goto fail; | |
1238 | queue=queue->next; | |
1239 | n++; | |
1240 | } | |
1241 | ||
427c49bc | 1242 | return errSecSuccess; |
b1ab9ed8 | 1243 | fail: |
427c49bc | 1244 | check_noerr(err); |
b1ab9ed8 A |
1245 | return err; |
1246 | } | |
1247 | ||
1248 | OSStatus | |
1249 | SSL3ReceiveSSL2ClientHello(SSLRecord rec, SSLContext *ctx) | |
1250 | { OSStatus err; | |
1251 | ||
1252 | if ((err = SSLInitMessageHashes(ctx)) != 0) | |
1253 | return err; | |
1254 | ||
1255 | if ((err = SSLHashSHA1.update(&ctx->shaState, &rec.contents)) != 0 || | |
1256 | (err = SSLHashMD5.update(&ctx->md5State, &rec.contents)) != 0) | |
1257 | { SSLFatalSessionAlert(SSL_AlertInternalError, ctx); | |
1258 | return err; | |
1259 | } | |
1260 | ||
1261 | if ((err = SSLAdvanceHandshake(SSL_HdskClientHello, ctx)) != 0) | |
1262 | return err; | |
1263 | ||
427c49bc A |
1264 | return errSecSuccess; |
1265 | } | |
1266 | ||
1267 | /* | |
1268 | * Determine max enabled protocol, i.e., the one we try to negotiate for. | |
1269 | * Only returns an error (errSecParam) if NO protocols are enabled, which can | |
1270 | * in fact happen by malicious or ignorant use of SSLSetProtocolVersionEnabled(). | |
1271 | */ | |
1272 | OSStatus sslGetMaxProtVersion( | |
1273 | SSLContext *ctx, | |
1274 | SSLProtocolVersion *version) // RETURNED | |
1275 | { | |
1276 | /* This check is here until SSLSetProtocolVersionEnabled() is gone .*/ | |
1277 | if (ctx->maxProtocolVersion == SSL_Version_Undetermined) | |
1278 | return errSecBadReq; | |
1279 | ||
1280 | *version = ctx->maxProtocolVersion; | |
1281 | return errSecSuccess; | |
b1ab9ed8 A |
1282 | } |
1283 | ||
427c49bc | 1284 | |
b1ab9ed8 A |
1285 | /* log changes in handshake state */ |
1286 | #ifndef NDEBUG | |
1287 | #include <stdio.h> | |
1288 | ||
1289 | char *hdskStateToStr(SSLHandshakeState state) | |
1290 | { | |
1291 | static char badStr[100]; | |
1292 | ||
1293 | switch(state) { | |
1294 | case SSL_HdskStateUninit: | |
1295 | return "Uninit"; | |
1296 | case SSL_HdskStateServerUninit: | |
1297 | return "ServerUninit"; | |
1298 | case SSL_HdskStateClientUninit: | |
1299 | return "ClientUninit"; | |
1300 | case SSL_HdskStateGracefulClose: | |
1301 | return "GracefulClose"; | |
1302 | case SSL_HdskStateErrorClose: | |
1303 | return "ErrorClose"; | |
1304 | case SSL_HdskStateNoNotifyClose: | |
1305 | return "NoNotifyClose"; | |
1306 | case SSL_HdskStateServerHello: | |
1307 | return "ServerHello"; | |
b1ab9ed8 A |
1308 | case SSL_HdskStateKeyExchange: |
1309 | return "KeyExchange"; | |
1310 | case SSL_HdskStateCert: | |
1311 | return "Cert"; | |
1312 | case SSL_HdskStateHelloDone: | |
1313 | return "HelloDone"; | |
1314 | case SSL_HdskStateClientCert: | |
1315 | return "ClientCert"; | |
1316 | case SSL_HdskStateClientKeyExchange: | |
1317 | return "ClientKeyExchange"; | |
1318 | case SSL_HdskStateClientCertVerify: | |
1319 | return "ClientCertVerify"; | |
1320 | case SSL_HdskStateChangeCipherSpec: | |
1321 | return "ChangeCipherSpec"; | |
1322 | case SSL_HdskStateFinished: | |
1323 | return "Finished"; | |
b1ab9ed8 A |
1324 | case SSL_HdskStateServerReady: |
1325 | return "SSL_ServerReady"; | |
1326 | case SSL_HdskStateClientReady: | |
1327 | return "SSL_ClientReady"; | |
1328 | default: | |
1329 | sprintf(badStr, "Unknown state (%d(d)", state); | |
1330 | return badStr; | |
1331 | } | |
1332 | } | |
1333 | ||
427c49bc | 1334 | /* This is a macro in Release mode */ |
b1ab9ed8 A |
1335 | void SSLChangeHdskState(SSLContext *ctx, SSLHandshakeState newState) |
1336 | { | |
b1ab9ed8 | 1337 | sslHdskStateDebug("...hdskState = %s", hdskStateToStr(newState)); |
b1ab9ed8 A |
1338 | ctx->state = newState; |
1339 | } | |
1340 | ||
b1ab9ed8 A |
1341 | /* log handshake messages */ |
1342 | ||
1343 | static char *hdskMsgToStr(SSLHandshakeType msg) | |
1344 | { | |
1345 | static char badStr[100]; | |
1346 | ||
1347 | switch(msg) { | |
1348 | case SSL_HdskHelloRequest: | |
1349 | return "SSL_HdskHelloRequest"; | |
1350 | case SSL_HdskClientHello: | |
1351 | return "SSL_HdskClientHello"; | |
1352 | case SSL_HdskServerHello: | |
1353 | return "SSL_HdskServerHello"; | |
1354 | case SSL_HdskHelloVerifyRequest: | |
1355 | return "SSL_HdskHelloVerifyRequest"; | |
1356 | case SSL_HdskCert: | |
1357 | return "SSL_HdskCert"; | |
1358 | case SSL_HdskServerKeyExchange: | |
1359 | return "SSL_HdskServerKeyExchange"; | |
1360 | case SSL_HdskCertRequest: | |
1361 | return "SSL_HdskCertRequest"; | |
1362 | case SSL_HdskServerHelloDone: | |
1363 | return "SSL_HdskServerHelloDone"; | |
1364 | case SSL_HdskCertVerify: | |
1365 | return "SSL_HdskCertVerify"; | |
1366 | case SSL_HdskClientKeyExchange: | |
1367 | return "SSL_HdskClientKeyExchange"; | |
1368 | case SSL_HdskFinished: | |
1369 | return "SSL_HdskFinished"; | |
1370 | default: | |
1371 | sprintf(badStr, "Unknown msg (%d(d))", msg); | |
1372 | return badStr; | |
1373 | } | |
1374 | } | |
1375 | ||
1376 | void SSLLogHdskMsg(SSLHandshakeType msg, char sent) | |
1377 | { | |
1378 | sslHdskMsgDebug("---%s handshake msg %s", | |
1379 | hdskMsgToStr(msg), (sent ? "sent" : "recv")); | |
1380 | } | |
1381 | ||
1382 | #endif /* NDEBUG */ | |
1383 |