]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
1 | /* |
2 | * Copyright (c) 1999-2001,2005-2008,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 | * sslHandshakeHello.c - Support for client hello and server hello messages. | |
26 | */ | |
27 | ||
28 | #include "sslContext.h" | |
29 | #include "sslHandshake.h" | |
30 | #include "sslMemory.h" | |
31 | #include "sslSession.h" | |
32 | #include "sslUtils.h" | |
33 | #include "sslDebug.h" | |
34 | #include "sslCrypto.h" | |
427c49bc | 35 | #include "sslRand.h" |
b1ab9ed8 | 36 | #include "sslDigests.h" |
427c49bc | 37 | #include "sslCipherSpecs.h" |
b1ab9ed8 A |
38 | |
39 | #include <string.h> | |
427c49bc A |
40 | #include <time.h> |
41 | #include <assert.h> | |
42 | ||
43 | #include <inttypes.h> | |
44 | ||
45 | /* | |
46 | * Given a protocol version sent by peer, determine if we accept that version | |
47 | * and downgrade if appropriate (which can not be done for the client side). | |
48 | */ | |
49 | static | |
50 | OSStatus sslVerifyProtVersion( | |
51 | SSLContext *ctx, | |
52 | SSLProtocolVersion peerVersion, // sent by peer | |
53 | SSLProtocolVersion *negVersion) // final negotiated version if return success | |
54 | { | |
55 | if ((ctx->isDTLS) | |
56 | ? peerVersion > ctx->minProtocolVersion | |
57 | : peerVersion < ctx->minProtocolVersion) { | |
58 | return errSSLNegotiation; | |
59 | } | |
60 | if ((ctx->isDTLS) | |
61 | ? peerVersion < ctx->maxProtocolVersion | |
62 | : peerVersion > ctx->maxProtocolVersion) { | |
63 | if (ctx->protocolSide == kSSLClientSide) { | |
64 | return errSSLNegotiation; | |
65 | } | |
66 | *negVersion = ctx->maxProtocolVersion; | |
67 | } else { | |
68 | *negVersion = peerVersion; | |
69 | } | |
70 | ||
71 | return errSecSuccess; | |
72 | } | |
73 | ||
b1ab9ed8 A |
74 | |
75 | /* IE treats null session id as valid; two consecutive sessions with NULL ID | |
76 | * are considered a match. Workaround: when resumable sessions are disabled, | |
77 | * send a random session ID. */ | |
78 | #define SSL_IE_NULL_RESUME_BUG 1 | |
79 | #if SSL_IE_NULL_RESUME_BUG | |
80 | #define SSL_NULL_ID_LEN 32 /* length of bogus session ID */ | |
81 | #endif | |
82 | ||
83 | OSStatus | |
84 | SSLEncodeServerHello(SSLRecord *serverHello, SSLContext *ctx) | |
85 | { OSStatus err; | |
86 | UInt8 *charPtr; | |
87 | int sessionIDLen; | |
88 | size_t msglen; | |
89 | int head; | |
90 | ||
91 | sessionIDLen = 0; | |
92 | if (ctx->sessionID.data != 0) | |
93 | sessionIDLen = (UInt8)ctx->sessionID.length; | |
94 | #if SSL_IE_NULL_RESUME_BUG | |
95 | if(sessionIDLen == 0) { | |
96 | sessionIDLen = SSL_NULL_ID_LEN; | |
97 | } | |
98 | #endif /* SSL_IE_NULL_RESUME_BUG */ | |
99 | ||
100 | msglen = 38 + sessionIDLen; | |
101 | ||
102 | /* this was set to a known quantity in SSLProcessClientHello */ | |
427c49bc | 103 | check(ctx->negProtocolVersion != SSL_Version_Undetermined); |
b1ab9ed8 | 104 | /* should not be here in this case */ |
427c49bc | 105 | check(ctx->negProtocolVersion != SSL_Version_2_0); |
b1ab9ed8 A |
106 | sslLogNegotiateDebug("===SSL3 server: sending version %d_%d", |
107 | ctx->negProtocolVersion >> 8, ctx->negProtocolVersion & 0xff); | |
108 | sslLogNegotiateDebug("...sessionIDLen = %d", sessionIDLen); | |
109 | serverHello->protocolVersion = ctx->negProtocolVersion; | |
110 | serverHello->contentType = SSL_RecordTypeHandshake; | |
111 | head = SSLHandshakeHeaderSize(serverHello); | |
427c49bc | 112 | if ((err = SSLAllocBuffer(&serverHello->contents, msglen + head))) |
b1ab9ed8 A |
113 | return err; |
114 | ||
115 | charPtr = SSLEncodeHandshakeHeader(ctx, serverHello, SSL_HdskServerHello, msglen); | |
116 | ||
117 | charPtr = SSLEncodeInt(charPtr, serverHello->protocolVersion, 2); | |
118 | ||
119 | #if SSL_PAC_SERVER_ENABLE | |
120 | /* serverRandom might have already been set, in SSLAdvanceHandshake() */ | |
121 | if(!ctx->serverRandomValid) { | |
122 | if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0) { | |
123 | return err; | |
124 | } | |
125 | } | |
126 | #else | |
127 | /* This is the normal production code path */ | |
128 | if ((err = SSLEncodeRandom(ctx->serverRandom, ctx)) != 0) | |
129 | return err; | |
130 | #endif /* SSL_PAC_SERVER_ENABLE */ | |
131 | ||
132 | memcpy(charPtr, ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE); | |
133 | ||
134 | charPtr += SSL_CLIENT_SRVR_RAND_SIZE; | |
135 | *(charPtr++) = (UInt8)sessionIDLen; | |
136 | #if SSL_IE_NULL_RESUME_BUG | |
137 | if(ctx->sessionID.data != NULL) { | |
138 | /* normal path for enabled resumable session */ | |
139 | memcpy(charPtr, ctx->sessionID.data, sessionIDLen); | |
140 | } | |
141 | else { | |
142 | /* IE workaround */ | |
143 | SSLBuffer rb; | |
144 | rb.data = charPtr; | |
145 | rb.length = SSL_NULL_ID_LEN; | |
427c49bc | 146 | sslRand(&rb); |
b1ab9ed8 A |
147 | } |
148 | #else | |
149 | if (sessionIDLen > 0) | |
150 | memcpy(charPtr, ctx->sessionID.data, sessionIDLen); | |
151 | #endif /* SSL_IE_NULL_RESUME_BUG */ | |
152 | charPtr += sessionIDLen; | |
153 | charPtr = SSLEncodeInt(charPtr, ctx->selectedCipher, 2); | |
154 | *(charPtr++) = 0; /* Null compression */ | |
155 | ||
156 | sslLogNegotiateDebug("ssl3: server specifying cipherSuite 0x%lx", | |
427c49bc | 157 | (unsigned long)ctx->selectedCipher); |
b1ab9ed8 A |
158 | |
159 | assert(charPtr == serverHello->contents.data + serverHello->contents.length); | |
160 | ||
427c49bc | 161 | return errSecSuccess; |
b1ab9ed8 A |
162 | } |
163 | ||
164 | OSStatus | |
165 | SSLEncodeServerHelloVerifyRequest(SSLRecord *helloVerifyRequest, SSLContext *ctx) | |
166 | { OSStatus err; | |
167 | UInt8 *charPtr; | |
168 | size_t msglen; | |
169 | int head; | |
170 | ||
171 | assert(ctx->protocolSide == kSSLServerSide); | |
172 | assert(ctx->negProtocolVersion == DTLS_Version_1_0); | |
173 | assert(ctx->dtlsCookie.length); | |
174 | ||
175 | msglen = 3 + ctx->dtlsCookie.length; | |
176 | ||
177 | helloVerifyRequest->protocolVersion = DTLS_Version_1_0; | |
178 | helloVerifyRequest->contentType = SSL_RecordTypeHandshake; | |
179 | head = SSLHandshakeHeaderSize(helloVerifyRequest); | |
427c49bc | 180 | if ((err = SSLAllocBuffer(&helloVerifyRequest->contents, msglen + head))) |
b1ab9ed8 A |
181 | return err; |
182 | ||
183 | charPtr = SSLEncodeHandshakeHeader(ctx, helloVerifyRequest, SSL_HdskHelloVerifyRequest, msglen); | |
184 | ||
185 | charPtr = SSLEncodeInt(charPtr, helloVerifyRequest->protocolVersion, 2); | |
186 | ||
187 | *charPtr++ = ctx->dtlsCookie.length; | |
188 | memcpy(charPtr, ctx->dtlsCookie.data, ctx->dtlsCookie.length); | |
189 | charPtr += ctx->dtlsCookie.length; | |
190 | ||
191 | assert(charPtr == (helloVerifyRequest->contents.data + helloVerifyRequest->contents.length)); | |
192 | ||
427c49bc | 193 | return errSecSuccess; |
b1ab9ed8 A |
194 | } |
195 | ||
196 | ||
197 | OSStatus | |
198 | SSLProcessServerHelloVerifyRequest(SSLBuffer message, SSLContext *ctx) | |
199 | { OSStatus err; | |
200 | SSLProtocolVersion protocolVersion; | |
201 | unsigned int cookieLen; | |
202 | UInt8 *p; | |
203 | ||
204 | assert(ctx->protocolSide == kSSLClientSide); | |
205 | ||
206 | /* TODO: those length values should not be hardcoded */ | |
207 | /* 3 bytes at least with empty cookie */ | |
208 | if (message.length < 3 ) { | |
209 | sslErrorLog("SSLProcessServerHelloVerifyRequest: msg len error\n"); | |
210 | return errSSLProtocol; | |
211 | } | |
212 | p = message.data; | |
213 | ||
214 | protocolVersion = (SSLProtocolVersion)SSLDecodeInt(p, 2); | |
215 | p += 2; | |
216 | ||
217 | /* TODO: Not clear what else to do with protocol version here */ | |
218 | if(protocolVersion != DTLS_Version_1_0) { | |
219 | sslErrorLog("SSLProcessServerHelloVerifyRequest: protocol version error\n"); | |
220 | return errSSLProtocol; | |
221 | } | |
222 | ||
223 | cookieLen = *p++; | |
427c49bc | 224 | sslLogNegotiateDebug("cookieLen = %d, msglen=%d\n", (int)cookieLen, (int)message.length); |
b1ab9ed8 A |
225 | /* TODO: hardcoded '15' again */ |
226 | if (message.length < (3 + cookieLen)) { | |
227 | sslErrorLog("SSLProcessServerHelloVerifyRequest: msg len error 2\n"); | |
228 | return errSSLProtocol; | |
229 | } | |
230 | ||
427c49bc | 231 | err = SSLAllocBuffer(&ctx->dtlsCookie, cookieLen); |
b1ab9ed8 A |
232 | if (err == 0) |
233 | memcpy(ctx->dtlsCookie.data, p, cookieLen); | |
234 | ||
235 | return err; | |
236 | } | |
237 | ||
238 | static void | |
239 | SSLProcessServerHelloExtension_SecureRenegotiation(SSLContext *ctx, UInt16 extLen, UInt8 *p) | |
240 | { | |
241 | if(extLen!= (1 + ctx->ownVerifyData.length + ctx->peerVerifyData.length)) | |
242 | return; | |
243 | ||
244 | if(*p!=ctx->ownVerifyData.length + ctx->ownVerifyData.length) | |
245 | return; | |
246 | p++; | |
247 | ||
248 | if(memcmp(p, ctx->ownVerifyData.data, ctx->ownVerifyData.length)) | |
249 | return; | |
250 | p+=ctx->ownVerifyData.length; | |
251 | ||
252 | if(memcmp(p, ctx->peerVerifyData.data, ctx->peerVerifyData.length)) | |
253 | return; | |
254 | ||
255 | ctx->secure_renegotiation_received = true; | |
256 | } | |
257 | ||
258 | ||
259 | static OSStatus | |
260 | SSLProcessServerHelloExtensions(SSLContext *ctx, UInt16 extensionsLen, UInt8 *p) | |
261 | { | |
262 | Boolean got_secure_renegotiation = false; | |
263 | UInt16 remaining; | |
264 | ||
265 | if(extensionsLen<2) { | |
266 | sslErrorLog("SSLProcessHelloExtensions: need a least 2 bytes\n"); | |
267 | return errSSLProtocol; | |
268 | } | |
269 | ||
270 | remaining = SSLDecodeInt(p, 2); p+=2; | |
271 | extensionsLen -=2; | |
272 | ||
273 | /* remaining = number of bytes remaining to process according to buffer data */ | |
274 | /* extensionsLen = number of bytes in the buffer */ | |
275 | ||
276 | if(remaining>extensionsLen) { | |
277 | sslErrorLog("SSLProcessHelloExtensions: ext len error 1\n"); | |
278 | return errSSLProtocol; | |
279 | } | |
280 | ||
281 | if(remaining<extensionsLen) { | |
282 | sslErrorLog("Warning: SSLProcessServerHelloExtensions: Too many bytes\n"); | |
283 | } | |
284 | ||
285 | while(remaining) { | |
286 | UInt16 extType; | |
287 | UInt16 extLen; | |
288 | ||
289 | if (remaining<4) { | |
290 | sslErrorLog("SSLProcessHelloExtensions: ext len error\n"); | |
291 | return errSSLProtocol; | |
292 | } | |
293 | ||
294 | extType = SSLDecodeInt(p, 2); p+=2; | |
295 | extLen = SSLDecodeInt(p, 2); p+=2; | |
296 | ||
297 | if (remaining<(4+extLen)) { | |
298 | sslErrorLog("SSLProcessHelloExtension: ext len error 2\n"); | |
299 | return errSSLProtocol; | |
300 | } | |
301 | remaining -= (4+extLen); | |
302 | ||
303 | switch (extType) { | |
304 | case SSL_HE_SecureRenegotation: | |
305 | if(got_secure_renegotiation) | |
306 | return errSSLProtocol; /* Fail if we already processed one */ | |
307 | got_secure_renegotiation = true; | |
308 | SSLProcessServerHelloExtension_SecureRenegotiation(ctx, extLen, p); | |
309 | break; | |
310 | default: | |
311 | /* | |
312 | Do nothing for other extensions. Per RFC 5246, we should (MUST) error | |
313 | if we received extensions we didnt specify in the Client Hello. | |
314 | Client should also abort handshake if multiple extensions of the same | |
315 | type are found | |
316 | */ | |
317 | break; | |
318 | } | |
319 | p+=extLen; | |
320 | } | |
321 | ||
427c49bc | 322 | return errSecSuccess; |
b1ab9ed8 A |
323 | } |
324 | ||
427c49bc A |
325 | |
326 | ||
b1ab9ed8 A |
327 | OSStatus |
328 | SSLProcessServerHello(SSLBuffer message, SSLContext *ctx) | |
329 | { OSStatus err; | |
330 | SSLProtocolVersion protocolVersion, negVersion; | |
331 | size_t sessionIDLen; | |
332 | size_t extensionsLen; | |
333 | UInt8 *p; | |
334 | ||
335 | assert(ctx->protocolSide == kSSLClientSide); | |
336 | ||
337 | if (message.length < 38) { | |
338 | sslErrorLog("SSLProcessServerHello: msg len error\n"); | |
339 | return errSSLProtocol; | |
340 | } | |
341 | p = message.data; | |
342 | ||
343 | protocolVersion = (SSLProtocolVersion)SSLDecodeInt(p, 2); | |
344 | p += 2; | |
345 | /* FIXME this should probably send appropriate alerts */ | |
346 | err = sslVerifyProtVersion(ctx, protocolVersion, &negVersion); | |
347 | if(err) { | |
348 | return err; | |
349 | } | |
350 | ctx->negProtocolVersion = negVersion; | |
351 | switch(negVersion) { | |
352 | case SSL_Version_3_0: | |
353 | ctx->sslTslCalls = &Ssl3Callouts; | |
354 | break; | |
355 | case TLS_Version_1_0: | |
356 | case TLS_Version_1_1: | |
357 | case DTLS_Version_1_0: | |
358 | ctx->sslTslCalls = &Tls1Callouts; | |
359 | break; | |
360 | case TLS_Version_1_2: | |
361 | ctx->sslTslCalls = &Tls12Callouts; | |
362 | break; | |
363 | default: | |
364 | return errSSLNegotiation; | |
365 | } | |
427c49bc A |
366 | err = ctx->recFuncs->setProtocolVersion(ctx->recCtx, negVersion); |
367 | if(err) { | |
368 | return err; | |
369 | } | |
370 | ||
b1ab9ed8 A |
371 | sslLogNegotiateDebug("===SSL3 client: negVersion is %d_%d", |
372 | (negVersion >> 8) & 0xff, negVersion & 0xff); | |
373 | ||
374 | memcpy(ctx->serverRandom, p, 32); | |
375 | p += 32; | |
376 | ||
377 | sessionIDLen = *p++; | |
378 | if (message.length < (38 + sessionIDLen)) { | |
379 | sslErrorLog("SSLProcessServerHello: msg len error 2\n"); | |
380 | return errSSLProtocol; | |
381 | } | |
382 | if (sessionIDLen > 0 && ctx->peerID.data != 0) | |
383 | { /* Don't die on error; just treat it as an uncached session */ | |
384 | if (ctx->sessionID.data) | |
427c49bc A |
385 | SSLFreeBuffer(&ctx->sessionID); |
386 | err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen); | |
b1ab9ed8 A |
387 | if (err == 0) |
388 | memcpy(ctx->sessionID.data, p, sessionIDLen); | |
389 | } | |
390 | p += sessionIDLen; | |
391 | ||
392 | ctx->selectedCipher = (UInt16)SSLDecodeInt(p,2); | |
393 | sslLogNegotiateDebug("===ssl3: server requests cipherKind %x", | |
394 | (unsigned)ctx->selectedCipher); | |
395 | p += 2; | |
396 | if ((err = FindCipherSpec(ctx)) != 0) { | |
397 | return err; | |
398 | } | |
399 | ||
400 | if (*p++ != 0) /* Compression */ | |
427c49bc | 401 | return errSecUnimplemented; |
b1ab9ed8 A |
402 | |
403 | /* Process ServerHello extensions */ | |
404 | extensionsLen = message.length - (38 + sessionIDLen); | |
405 | ||
406 | if(extensionsLen) { | |
407 | err = SSLProcessServerHelloExtensions(ctx, extensionsLen, p); | |
408 | if(err) | |
409 | return err; | |
410 | } | |
411 | ||
412 | /* RFC 5746: Make sure the renegotiation is secure */ | |
413 | if(ctx->secure_renegotiation && !ctx->secure_renegotiation_received) | |
414 | return errSSLNegotiation; | |
415 | ||
416 | if(ctx->secure_renegotiation_received) | |
417 | ctx->secure_renegotiation = true; | |
418 | ||
427c49bc | 419 | |
b1ab9ed8 A |
420 | /* |
421 | * Note: the server MAY send a SSL_HE_EC_PointFormats extension if | |
422 | * we've negotiated an ECDSA ciphersuite...but | |
423 | * a) the provided format list MUST contain SSL_PointFormatUncompressed per | |
424 | * RFC 4492 5.2; and | |
425 | * b) The uncompressed format is the only one we support. | |
426 | * | |
427 | * Thus we drop a possible incoming SSL_HE_EC_PointFormats extension here. | |
428 | * IF we ever support other point formats, we have to parse the extension | |
429 | * to see what the server supports. | |
430 | */ | |
427c49bc | 431 | return errSecSuccess; |
b1ab9ed8 A |
432 | } |
433 | ||
434 | OSStatus | |
435 | SSLEncodeClientHello(SSLRecord *clientHello, SSLContext *ctx) | |
436 | { | |
437 | size_t length; | |
438 | unsigned i; | |
439 | OSStatus err; | |
440 | unsigned char *p; | |
441 | SSLBuffer sessionIdentifier = { 0, NULL }; | |
442 | size_t sessionIDLen; | |
443 | size_t sessionTicketLen = 0; | |
444 | size_t serverNameLen = 0; | |
445 | size_t pointFormatLen = 0; | |
446 | size_t suppCurveLen = 0; | |
447 | size_t signatureAlgorithmsLen = 0; | |
448 | size_t totalExtenLen = 0; | |
449 | UInt16 numCipherSuites; | |
450 | int head; | |
451 | ||
452 | assert(ctx->protocolSide == kSSLClientSide); | |
453 | ||
454 | clientHello->contents.length = 0; | |
455 | clientHello->contents.data = NULL; | |
456 | ||
457 | sessionIDLen = 0; | |
458 | if (ctx->resumableSession.data != 0) | |
459 | { if ((err = SSLRetrieveSessionID(ctx->resumableSession, | |
460 | &sessionIdentifier, ctx)) != 0) | |
461 | { return err; | |
462 | } | |
463 | sessionIDLen = sessionIdentifier.length; | |
464 | } | |
465 | ||
466 | /* | |
467 | * Since we're not in SSLv2 compatibility mode, only count non-SSLv2 ciphers. | |
468 | */ | |
469 | #if ENABLE_SSLV2 | |
470 | numCipherSuites = ctx->numValidNonSSLv2Specs; | |
471 | #else | |
472 | numCipherSuites = ctx->numValidCipherSuites; | |
473 | #endif | |
474 | ||
475 | /* RFC 5746 : add the fake ciphersuite unless we are including the extension */ | |
476 | if(!ctx->secure_renegotiation) | |
477 | numCipherSuites+=1; | |
478 | ||
479 | length = 39 + 2*numCipherSuites + sessionIDLen; | |
480 | ||
427c49bc A |
481 | /* We always use the max enabled version in the ClientHello.client_version, |
482 | even in the renegotiation case. This value is saved in the context so it | |
483 | can be used in the RSA key exchange */ | |
484 | err = sslGetMaxProtVersion(ctx, &ctx->clientReqProtocol); | |
b1ab9ed8 A |
485 | if(err) { |
486 | /* we don't have a protocol enabled */ | |
487 | goto err_exit; | |
488 | } | |
489 | ||
490 | /* RFC 5746: If are starting a new handshake, so we didnt received this yet */ | |
491 | ctx->secure_renegotiation_received = false; | |
492 | ||
427c49bc A |
493 | /* This is the protocol version used at the record layer, If we already |
494 | negotiated the protocol version previously, we should just use that, | |
495 | otherwise we use the the minimum supported version. | |
496 | We do not always use the minimum version because some TLS only servers | |
497 | will reject an SSL 3 version in client_hello. | |
498 | */ | |
b1ab9ed8 A |
499 | if(ctx->negProtocolVersion != SSL_Version_Undetermined) { |
500 | clientHello->protocolVersion = ctx->negProtocolVersion; | |
427c49bc A |
501 | } else { |
502 | if(ctx->minProtocolVersion<TLS_Version_1_0 && ctx->maxProtocolVersion>=TLS_Version_1_0) | |
503 | clientHello->protocolVersion = TLS_Version_1_0; | |
504 | else | |
505 | clientHello->protocolVersion = ctx->minProtocolVersion; | |
b1ab9ed8 A |
506 | } |
507 | ||
508 | #if ENABLE_DTLS | |
509 | if(clientHello->protocolVersion == DTLS_Version_1_0) { | |
510 | /* extra space for cookie */ | |
511 | /* TODO: cookie len - 0 for now */ | |
512 | length += 1 + ctx->dtlsCookie.length; | |
513 | sslLogNegotiateDebug("==DTLS Hello: len=%lu\n", length); | |
514 | } | |
515 | /* Because of the way the version number for DTLS is encoded, | |
516 | the following code mean that you can use extensions with DTLS... */ | |
517 | #endif /* ENABLE_DTLS */ | |
518 | ||
519 | /* RFC 5746: We add the extension only for renegotiation ClientHello */ | |
520 | if(ctx->secure_renegotiation) { | |
521 | totalExtenLen += 2 + /* extension type */ | |
522 | 2 + /* extension length */ | |
523 | 1 + /* lenght of renegotiated_conection (client verify data) */ | |
524 | ctx->ownVerifyData.length; | |
525 | } | |
526 | ||
527 | /* prepare for optional ClientHello extensions */ | |
427c49bc | 528 | if((ctx->clientReqProtocol >= TLS_Version_1_0) && |
b1ab9ed8 A |
529 | (ctx->peerDomainName != NULL) && |
530 | (ctx->peerDomainNameLen != 0)) { | |
531 | serverNameLen = 2 + /* extension type */ | |
532 | 2 + /* 2-byte vector length, extension_data */ | |
533 | 2 + /* length of server_name_list */ | |
534 | 1 + /* length of name_type */ | |
535 | 2 + /* length of HostName */ | |
536 | ctx->peerDomainNameLen; | |
537 | totalExtenLen += serverNameLen; | |
538 | } | |
539 | if(ctx->sessionTicket.length) { | |
540 | sessionTicketLen = 2 + /* extension type */ | |
541 | 2 + /* 2-byte vector length, extension_data */ | |
542 | ctx->sessionTicket.length; | |
543 | totalExtenLen += sessionTicketLen; | |
544 | } | |
427c49bc | 545 | if((ctx->clientReqProtocol >= TLS_Version_1_0) && |
b1ab9ed8 A |
546 | (ctx->ecdsaEnable)) { |
547 | /* Two more extensions: point format, supported curves */ | |
548 | pointFormatLen = 2 + /* extension type */ | |
549 | 2 + /* 2-byte vector length, extension_data */ | |
550 | 1 + /* length of the ec_point_format_list */ | |
551 | 1; /* the single format we support */ | |
552 | suppCurveLen = 2 + /* extension type */ | |
553 | 2 + /* 2-byte vector length, extension_data */ | |
554 | 2 + /* length of the elliptic_curve_list */ | |
555 | (2 * ctx->ecdhNumCurves); /* each curve is 2 bytes */ | |
556 | totalExtenLen += (pointFormatLen + suppCurveLen); | |
557 | } | |
558 | if(ctx->isDTLS | |
427c49bc A |
559 | ? ctx->clientReqProtocol < DTLS_Version_1_0 |
560 | : ctx->clientReqProtocol >= TLS_Version_1_2) { | |
b1ab9ed8 A |
561 | signatureAlgorithmsLen = 2 + /* extension type */ |
562 | 2 + /* 2-byte vector length, extension_data */ | |
563 | 2 + /* length of signatureAlgorithms list */ | |
564 | 2 * (ctx->ecdsaEnable ? 5 : 3); //FIXME: 5:3 should not be hardcoded here. | |
565 | totalExtenLen += signatureAlgorithmsLen; | |
566 | } | |
567 | if(totalExtenLen != 0) { | |
568 | /* | |
569 | * Total length extensions have to fit in a 16 bit field... | |
570 | */ | |
571 | if(totalExtenLen > 0xffff) { | |
572 | sslErrorLog("Total extensions length EXCEEDED\n"); | |
573 | totalExtenLen = 0; | |
574 | sessionTicketLen = 0; | |
575 | serverNameLen = 0; | |
576 | pointFormatLen = 0; | |
577 | suppCurveLen = 0; | |
578 | signatureAlgorithmsLen = 0; | |
579 | } | |
580 | else { | |
581 | /* add length of total length plus lengths of extensions */ | |
582 | length += (totalExtenLen + 2); | |
583 | } | |
584 | } | |
585 | ||
586 | clientHello->contentType = SSL_RecordTypeHandshake; | |
587 | head = SSLHandshakeHeaderSize(clientHello); | |
427c49bc | 588 | if ((err = SSLAllocBuffer(&clientHello->contents, length + head))) |
b1ab9ed8 A |
589 | goto err_exit; |
590 | ||
591 | p = SSLEncodeHandshakeHeader(ctx, clientHello, SSL_HdskClientHello, length); | |
592 | ||
427c49bc | 593 | p = SSLEncodeInt(p, ctx->clientReqProtocol, 2); |
b1ab9ed8 A |
594 | |
595 | sslLogNegotiateDebug("===SSL3 client: proclaiming max protocol " | |
596 | "%d_%d capable ONLY", | |
427c49bc | 597 | ctx->clientReqProtocol >> 8, ctx->clientReqProtocol & 0xff); |
b1ab9ed8 A |
598 | if ((err = SSLEncodeRandom(p, ctx)) != 0) |
599 | { goto err_exit; | |
600 | } | |
601 | memcpy(ctx->clientRandom, p, SSL_CLIENT_SRVR_RAND_SIZE); | |
602 | p += 32; | |
603 | *p++ = sessionIDLen; /* 1 byte vector length */ | |
604 | if (sessionIDLen > 0) | |
605 | { memcpy(p, sessionIdentifier.data, sessionIDLen); | |
606 | } | |
607 | p += sessionIDLen; | |
608 | #if ENABLE_DTLS | |
427c49bc | 609 | if (ctx->clientReqProtocol == DTLS_Version_1_0) { |
b1ab9ed8 A |
610 | /* TODO: Add the cookie ! Currently: size=0 -> no cookie */ |
611 | *p++ = ctx->dtlsCookie.length; | |
612 | if(ctx->dtlsCookie.length) { | |
613 | memcpy(p, ctx->dtlsCookie.data, ctx->dtlsCookie.length); | |
614 | p+=ctx->dtlsCookie.length; | |
615 | } | |
427c49bc | 616 | sslLogNegotiateDebug("==DTLS Hello: cookie len = %d\n",(int)ctx->dtlsCookie.length); |
b1ab9ed8 A |
617 | } |
618 | #endif | |
619 | ||
620 | ||
621 | p = SSLEncodeInt(p, 2*numCipherSuites, 2); | |
622 | /* 2 byte long vector length */ | |
623 | ||
624 | /* RFC 5746 : add the fake ciphersuite unless we are including the extension */ | |
625 | if(!ctx->secure_renegotiation) | |
626 | p = SSLEncodeInt(p, TLS_EMPTY_RENEGOTIATION_INFO_SCSV, 2); | |
627 | ||
628 | for (i = 0; i<ctx->numValidCipherSuites; ++i) { | |
629 | #if ENABLE_SSLV2 | |
630 | if(CIPHER_SUITE_IS_SSLv2(ctx->validCipherSuites[i])) { | |
631 | continue; | |
632 | } | |
633 | #endif | |
634 | sslLogNegotiateDebug("ssl3EncodeClientHello sending suite %x", | |
635 | (unsigned)ctx->validCipherSuites[i]); | |
636 | p = SSLEncodeInt(p, ctx->validCipherSuites[i], 2); | |
637 | } | |
638 | *p++ = 1; /* 1 byte long vector */ | |
639 | *p++ = 0; /* null compression */ | |
640 | ||
641 | /* | |
642 | * Append ClientHello extensions. | |
643 | */ | |
644 | if(totalExtenLen != 0) { | |
645 | /* first, total length of all extensions */ | |
646 | p = SSLEncodeSize(p, totalExtenLen, 2); | |
647 | } | |
648 | if(ctx->secure_renegotiation){ | |
649 | assert(ctx->ownVerifyData.length<=255); | |
650 | p = SSLEncodeInt(p, SSL_HE_SecureRenegotation, 2); | |
651 | p = SSLEncodeSize(p, ctx->ownVerifyData.length+1, 2); | |
652 | p = SSLEncodeSize(p, ctx->ownVerifyData.length, 1); | |
653 | memcpy(p, ctx->ownVerifyData.data, ctx->ownVerifyData.length); | |
654 | p += ctx->ownVerifyData.length; | |
655 | } | |
656 | if(sessionTicketLen) { | |
657 | sslEapDebug("Adding %lu bytes of sessionTicket to ClientHello", | |
658 | ctx->sessionTicket.length); | |
659 | p = SSLEncodeInt(p, SSL_HE_SessionTicket, 2); | |
660 | p = SSLEncodeSize(p, ctx->sessionTicket.length, 2); | |
661 | memcpy(p, ctx->sessionTicket.data, ctx->sessionTicket.length); | |
662 | p += ctx->sessionTicket.length; | |
663 | } | |
664 | if(serverNameLen) { | |
665 | sslEapDebug("Specifying ServerNameIndication"); | |
666 | p = SSLEncodeInt(p, SSL_HE_ServerName, 2); | |
667 | p = SSLEncodeSize(p, ctx->peerDomainNameLen + 5, 2); | |
668 | p = SSLEncodeSize(p, ctx->peerDomainNameLen + 3, 2); | |
669 | p = SSLEncodeInt(p, SSL_NT_HostName, 1); | |
670 | p = SSLEncodeSize(p, ctx->peerDomainNameLen, 2); | |
671 | memcpy(p, ctx->peerDomainName, ctx->peerDomainNameLen); | |
672 | p += ctx->peerDomainNameLen; | |
673 | } | |
674 | if(suppCurveLen) { | |
675 | UInt32 len = 2 * ctx->ecdhNumCurves; | |
676 | unsigned dex; | |
677 | p = SSLEncodeInt(p, SSL_HE_EllipticCurves, 2); | |
678 | p = SSLEncodeSize(p, len+2, 2); /* length of extension data */ | |
679 | p = SSLEncodeSize(p, len, 2); /* length of elliptic_curve_list */ | |
680 | for(dex=0; dex<ctx->ecdhNumCurves; dex++) { | |
681 | sslEcdsaDebug("+++ adding supported curves %u to ClientHello", | |
682 | (unsigned)ctx->ecdhCurves[dex]); | |
683 | p = SSLEncodeInt(p, ctx->ecdhCurves[dex], 2); | |
684 | } | |
685 | } | |
686 | if(pointFormatLen) { | |
687 | sslEcdsaDebug("+++ adding point format to ClientHello"); | |
688 | p = SSLEncodeInt(p, SSL_HE_EC_PointFormats, 2); | |
689 | p = SSLEncodeSize(p, 2, 2); /* length of extension data */ | |
690 | p = SSLEncodeSize(p, 1, 1); /* length of ec_point_format_list */ | |
691 | p = SSLEncodeInt(p, SSL_PointFormatUncompressed, 1); | |
692 | } | |
693 | if (signatureAlgorithmsLen) { | |
694 | sslEcdsaDebug("+++ adding signature algorithms to ClientHello"); | |
695 | /* TODO: Don't hardcode this */ | |
696 | /* We dont support SHA512 or SHA224 because we didnot implement the digest abstraction for those | |
697 | and we dont keep a running hash for those. | |
698 | We dont support SHA384/ECDSA because corecrypto ec does not support it with 256 bits curves */ | |
699 | UInt32 len = 2 * (ctx->ecdsaEnable ? 5 : 3); //FIXME: 5:3 should not be hardcoded here. | |
700 | p = SSLEncodeInt(p, SSL_HE_SignatureAlgorithms, 2); | |
701 | p = SSLEncodeSize(p, len+2, 2); /* length of extension data */ | |
702 | p = SSLEncodeSize(p, len, 2); /* length of extension data */ | |
703 | // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA512, 1); | |
704 | // p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); | |
705 | p = SSLEncodeInt(p, SSL_HashAlgorithmSHA384, 1); | |
706 | p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); | |
707 | p = SSLEncodeInt(p, SSL_HashAlgorithmSHA256, 1); | |
708 | p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); | |
709 | // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA224, 1); | |
710 | // p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); | |
711 | p = SSLEncodeInt(p, SSL_HashAlgorithmSHA1, 1); | |
712 | p = SSLEncodeInt(p, SSL_SignatureAlgorithmRSA, 1); | |
713 | if (ctx->ecdsaEnable) { | |
714 | // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA512, 1); | |
715 | // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); | |
716 | // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA384, 1); | |
717 | // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); | |
718 | p = SSLEncodeInt(p, SSL_HashAlgorithmSHA256, 1); | |
719 | p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); | |
720 | // p = SSLEncodeInt(p, SSL_HashAlgorithmSHA224, 1); | |
721 | // p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); | |
722 | p = SSLEncodeInt(p, SSL_HashAlgorithmSHA1, 1); | |
723 | p = SSLEncodeInt(p, SSL_SignatureAlgorithmECDSA, 1); | |
724 | } | |
725 | } | |
726 | ||
427c49bc | 727 | sslLogNegotiateDebug("Client Hello : data=%p p=%p len=%08lx\n", clientHello->contents.data, p, (unsigned long)clientHello->contents.length); |
b1ab9ed8 A |
728 | |
729 | assert(p == clientHello->contents.data + clientHello->contents.length); | |
730 | ||
731 | if ((err = SSLInitMessageHashes(ctx)) != 0) | |
732 | goto err_exit; | |
733 | ||
734 | err_exit: | |
735 | if (err != 0) { | |
427c49bc | 736 | SSLFreeBuffer(&clientHello->contents); |
b1ab9ed8 | 737 | } |
427c49bc | 738 | SSLFreeBuffer(&sessionIdentifier); |
b1ab9ed8 A |
739 | |
740 | return err; | |
741 | } | |
742 | ||
743 | OSStatus | |
744 | SSLProcessClientHello(SSLBuffer message, SSLContext *ctx) | |
745 | { OSStatus err; | |
746 | SSLProtocolVersion negVersion; | |
747 | UInt16 cipherListLen, cipherCount, desiredSuite, cipherSuite; | |
748 | UInt8 sessionIDLen, compressionCount; | |
749 | UInt8 *charPtr; | |
750 | unsigned i; | |
751 | UInt8 *eom; /* end of message */ | |
752 | ||
753 | if (message.length < 41) { | |
754 | sslErrorLog("SSLProcessClientHello: msg len error 1\n"); | |
755 | return errSSLProtocol; | |
756 | } | |
757 | charPtr = message.data; | |
758 | eom = charPtr + message.length; | |
759 | ctx->clientReqProtocol = (SSLProtocolVersion)SSLDecodeInt(charPtr, 2); | |
760 | charPtr += 2; | |
761 | err = sslVerifyProtVersion(ctx, ctx->clientReqProtocol, &negVersion); | |
762 | if(err) { | |
763 | sslErrorLog("SSLProcessClientHello: protocol version error %04x - %04x\n", ctx->clientReqProtocol, negVersion); | |
764 | return err; | |
765 | } | |
766 | switch(negVersion) { | |
767 | case SSL_Version_3_0: | |
768 | ctx->sslTslCalls = &Ssl3Callouts; | |
769 | break; | |
770 | case TLS_Version_1_0: | |
771 | case TLS_Version_1_1: | |
772 | case DTLS_Version_1_0: | |
773 | ctx->sslTslCalls = &Tls1Callouts; | |
774 | break; | |
775 | case TLS_Version_1_2: | |
776 | ctx->sslTslCalls = &Tls12Callouts; | |
777 | break; | |
778 | default: | |
779 | return errSSLNegotiation; | |
780 | } | |
781 | ctx->negProtocolVersion = negVersion; | |
427c49bc A |
782 | err = ctx->recFuncs->setProtocolVersion(ctx->recCtx, negVersion); |
783 | if(err) { | |
784 | return err; | |
785 | } | |
b1ab9ed8 A |
786 | sslLogNegotiateDebug("===SSL3 server: negVersion is %d_%d", |
787 | negVersion >> 8, negVersion & 0xff); | |
788 | ||
789 | memcpy(ctx->clientRandom, charPtr, SSL_CLIENT_SRVR_RAND_SIZE); | |
790 | charPtr += 32; | |
791 | sessionIDLen = *(charPtr++); | |
792 | if (message.length < (unsigned)(41 + sessionIDLen)) { | |
793 | sslErrorLog("SSLProcessClientHello: msg len error 2\n"); | |
794 | return errSSLProtocol; | |
795 | } | |
796 | /* FIXME peerID is never set on server side.... */ | |
797 | if (sessionIDLen > 0 && ctx->peerID.data != 0) | |
798 | { /* Don't die on error; just treat it as an uncacheable session */ | |
427c49bc | 799 | err = SSLAllocBuffer(&ctx->sessionID, sessionIDLen); |
b1ab9ed8 A |
800 | if (err == 0) |
801 | memcpy(ctx->sessionID.data, charPtr, sessionIDLen); | |
802 | } | |
803 | charPtr += sessionIDLen; | |
804 | ||
805 | #if ENABLE_DTLS | |
806 | /* TODO: actually do something with this cookie */ | |
807 | if(negVersion==DTLS_Version_1_0) { | |
808 | UInt8 cookieLen = *charPtr++; | |
809 | ||
810 | sslLogNegotiateDebug("cookieLen=%d\n", cookieLen); | |
811 | ||
812 | if((ctx->dtlsCookie.length==0) || ((cookieLen==ctx->dtlsCookie.length) && (memcmp(ctx->dtlsCookie.data, charPtr, cookieLen)==0))) | |
813 | { | |
814 | ctx->cookieVerified=true; | |
815 | } else { | |
816 | ctx->cookieVerified=false; | |
817 | } | |
818 | ||
819 | charPtr+=cookieLen; | |
820 | } | |
821 | ||
822 | /* TODO: if we are about to send a HelloVerifyRequest, we probably dont need to process the cipherspecs */ | |
823 | #endif | |
824 | ||
825 | cipherListLen = (UInt16)SSLDecodeInt(charPtr, 2); | |
826 | /* Count of cipherSuites, must be even & >= 2 */ | |
827 | charPtr += 2; | |
828 | if((charPtr + cipherListLen) > eom) { | |
829 | sslErrorLog("SSLProcessClientHello: msg len error 5\n"); | |
830 | return errSSLProtocol; | |
831 | } | |
832 | if ((cipherListLen & 1) || | |
833 | (cipherListLen < 2) || | |
834 | (message.length < (unsigned)(39 + sessionIDLen + cipherListLen))) { | |
835 | sslErrorLog("SSLProcessClientHello: msg len error 3\n"); | |
836 | return errSSLProtocol; | |
837 | } | |
838 | cipherCount = cipherListLen/2; | |
839 | cipherSuite = 0xFFFF; /* No match marker */ | |
840 | while (cipherSuite == 0xFFFF && cipherCount--) | |
841 | { desiredSuite = (UInt16)SSLDecodeInt(charPtr, 2); | |
842 | charPtr += 2; | |
843 | for (i = 0; i <ctx->numValidCipherSuites; i++) | |
844 | { if (ctx->validCipherSuites[i] == desiredSuite) | |
845 | { cipherSuite = desiredSuite; | |
846 | break; | |
847 | } | |
848 | } | |
849 | } | |
850 | ||
851 | if (cipherSuite == 0xFFFF) | |
852 | return errSSLNegotiation; | |
853 | charPtr += 2 * cipherCount; /* Advance past unchecked cipherCounts */ | |
854 | ctx->selectedCipher = cipherSuite; | |
855 | /* validate cipher later, after we get possible sessionTicket */ | |
856 | ||
857 | compressionCount = *(charPtr++); | |
858 | if ((compressionCount < 1) || | |
859 | (message.length < | |
860 | (unsigned)(38 + sessionIDLen + cipherListLen + compressionCount))) { | |
861 | sslErrorLog("SSLProcessClientHello: msg len error 4\n"); | |
862 | return errSSLProtocol; | |
863 | } | |
864 | /* Ignore list; we're doing null */ | |
865 | ||
866 | /* | |
867 | * Handle ClientHello extensions. | |
868 | */ | |
869 | /* skip compression list */ | |
870 | charPtr += compressionCount; | |
871 | if(charPtr < eom) { | |
872 | ptrdiff_t remLen = eom - charPtr; | |
873 | UInt32 totalExtensLen; | |
874 | UInt32 extenType; | |
875 | UInt32 extenLen; | |
876 | if(remLen < 6) { | |
877 | /* | |
878 | * Not enough for extension type and length, but not an error... | |
879 | * skip it and proceed. | |
880 | */ | |
881 | sslEapDebug("SSLProcessClientHello: too small for any extension"); | |
882 | goto proceed; | |
883 | } | |
884 | totalExtensLen = SSLDecodeInt(charPtr, 2); | |
885 | charPtr += 2; | |
886 | if((charPtr + totalExtensLen) > eom) { | |
887 | sslEapDebug("SSLProcessClientHello: too small for specified total_extension_length"); | |
888 | goto proceed; | |
889 | } | |
890 | while(charPtr < eom) { | |
891 | extenType = SSLDecodeInt(charPtr, 2); | |
892 | charPtr += 2; | |
893 | extenLen = SSLDecodeInt(charPtr, 2); | |
894 | charPtr += 2; | |
895 | if((charPtr + extenLen) > eom) { | |
896 | sslEapDebug("SSLProcessClientHello: too small for specified extension_length"); | |
897 | break; | |
898 | } | |
899 | switch(extenType) { | |
900 | #if SSL_PAC_SERVER_ENABLE | |
901 | ||
902 | case SSL_HE_SessionTicket: | |
427c49bc | 903 | SSLFreeBuffer(&ctx->sessionTicket); |
b1ab9ed8 A |
904 | SSLCopyBufferFromData(charPtr, extenLen, &ctx->sessionTicket); |
905 | sslEapDebug("Saved %lu bytes of sessionTicket from ClientHello", | |
906 | (unsigned long)extenLen); | |
907 | break; | |
908 | #endif | |
909 | case SSL_HE_ServerName: | |
910 | { | |
911 | /* | |
912 | * This is for debug only (it's disabled for Deployment builds). | |
913 | * Someday, I imagine we'll have a getter in the API to get this info. | |
914 | */ | |
915 | UInt8 *cp = charPtr; | |
916 | UInt32 v = SSLDecodeInt(cp, 2); | |
917 | cp += 2; | |
918 | sslEapDebug("SSL_HE_ServerName: length of server_name_list %lu", | |
919 | (unsigned long)v); | |
920 | v = SSLDecodeInt(cp, 1); | |
921 | cp++; | |
922 | sslEapDebug("SSL_HE_ServerName: name_type %lu", (unsigned long)v); | |
923 | v = SSLDecodeInt(cp, 2); | |
924 | cp += 2; | |
925 | sslEapDebug("SSL_HE_ServerName: length of HostName %lu", | |
926 | (unsigned long)v); | |
927 | char hostString[v + 1]; | |
928 | memmove(hostString, cp, v); | |
929 | hostString[v] = '\0'; | |
930 | sslEapDebug("SSL_HE_ServerName: ServerName '%s'", hostString); | |
931 | break; | |
932 | } | |
933 | case SSL_HE_SignatureAlgorithms: | |
934 | { | |
427c49bc A |
935 | UInt8 *cp = charPtr; |
936 | #ifndef NDEBUG | |
937 | UInt8 *end = charPtr + extenLen; | |
938 | #endif | |
b1ab9ed8 A |
939 | UInt32 sigAlgsSize = SSLDecodeInt(cp, 2); |
940 | cp += 2; | |
941 | ||
942 | if (extenLen != sigAlgsSize + 2 || extenLen & 1 || sigAlgsSize & 1) { | |
943 | sslEapDebug("SSL_HE_SignatureAlgorithms: odd length of signature algorithms list %lu %lu", | |
944 | (unsigned long)extenLen, (unsigned long)sigAlgsSize); | |
945 | break; | |
946 | } | |
947 | ||
948 | ctx->numClientSigAlgs = sigAlgsSize / 2; | |
949 | if(ctx->clientSigAlgs != NULL) { | |
950 | sslFree(ctx->clientSigAlgs); | |
951 | } | |
952 | ctx->clientSigAlgs = (SSLSignatureAndHashAlgorithm *) | |
953 | sslMalloc((ctx->numClientSigAlgs) * sizeof(SSLSignatureAndHashAlgorithm)); | |
954 | for(i=0; i<ctx->numClientSigAlgs; i++) { | |
955 | /* TODO: Validate hash and signature fields. */ | |
956 | ctx->clientSigAlgs[i].hash = *cp++; | |
957 | ctx->clientSigAlgs[i].signature = *cp++; | |
958 | sslLogNegotiateDebug("===Client specifies sigAlg %d %d", | |
959 | ctx->clientSigAlgs[i].hash, | |
960 | ctx->clientSigAlgs[i].signature); | |
961 | } | |
962 | assert(cp==end); | |
963 | break; | |
964 | } | |
965 | default: | |
966 | sslEapDebug("SSLProcessClientHello: unknown extenType (%lu)", | |
967 | (unsigned long)extenType); | |
968 | break; | |
969 | } | |
970 | charPtr += extenLen; | |
971 | } | |
972 | } | |
973 | proceed: | |
974 | if ((err = FindCipherSpec(ctx)) != 0) { | |
975 | return err; | |
976 | } | |
977 | sslLogNegotiateDebug("ssl3 server: selecting cipherKind 0x%x", (unsigned)ctx->selectedCipher); | |
978 | if ((err = SSLInitMessageHashes(ctx)) != 0) | |
979 | return err; | |
980 | ||
427c49bc A |
981 | return errSecSuccess; |
982 | } | |
983 | ||
984 | static | |
985 | OSStatus sslTime(uint32_t *tim) | |
986 | { | |
987 | time_t t; | |
988 | time(&t); | |
989 | *tim = (uint32_t)t; | |
990 | return errSecSuccess; | |
b1ab9ed8 A |
991 | } |
992 | ||
993 | OSStatus | |
994 | SSLEncodeRandom(unsigned char *p, SSLContext *ctx) | |
995 | { SSLBuffer randomData; | |
996 | OSStatus err; | |
997 | uint32_t now; | |
998 | ||
999 | if ((err = sslTime(&now)) != 0) | |
1000 | return err; | |
1001 | SSLEncodeInt(p, now, 4); | |
1002 | randomData.data = p+4; | |
1003 | randomData.length = 28; | |
427c49bc | 1004 | if((err = sslRand(&randomData)) != 0) |
b1ab9ed8 | 1005 | return err; |
427c49bc | 1006 | return errSecSuccess; |
b1ab9ed8 A |
1007 | } |
1008 | ||
1009 | OSStatus | |
1010 | SSLInitMessageHashes(SSLContext *ctx) | |
1011 | { OSStatus err; | |
1012 | ||
427c49bc | 1013 | if ((err = CloseHash(&SSLHashSHA1, &ctx->shaState)) != 0) |
b1ab9ed8 | 1014 | return err; |
427c49bc | 1015 | if ((err = CloseHash(&SSLHashMD5, &ctx->md5State)) != 0) |
b1ab9ed8 | 1016 | return err; |
427c49bc | 1017 | if ((err = CloseHash(&SSLHashSHA256, &ctx->sha256State)) != 0) |
b1ab9ed8 | 1018 | return err; |
427c49bc | 1019 | if ((err = CloseHash(&SSLHashSHA384, &ctx->sha512State)) != 0) |
b1ab9ed8 | 1020 | return err; |
427c49bc | 1021 | if ((err = ReadyHash(&SSLHashSHA1, &ctx->shaState)) != 0) |
b1ab9ed8 | 1022 | return err; |
427c49bc | 1023 | if ((err = ReadyHash(&SSLHashMD5, &ctx->md5State)) != 0) |
b1ab9ed8 | 1024 | return err; |
427c49bc | 1025 | if ((err = ReadyHash(&SSLHashSHA256, &ctx->sha256State)) != 0) |
b1ab9ed8 | 1026 | return err; |
427c49bc | 1027 | if ((err = ReadyHash(&SSLHashSHA384, &ctx->sha512State)) != 0) |
b1ab9ed8 | 1028 | return err; |
427c49bc | 1029 | return errSecSuccess; |
b1ab9ed8 | 1030 | } |