]> git.saurik.com Git - apple/security.git/blob - libsecurity_ssl/lib/tls1Callouts.c
Security-55471.14.tar.gz
[apple/security.git] / libsecurity_ssl / lib / tls1Callouts.c
1 /*
2 * Copyright (c) 2002,2005-2007,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 * tls1Callouts.c - TLSv1-specific routines for SslTlsCallouts.
26 */
27
28 #include "SecureTransport.h"
29
30 #include "tls_ssl.h"
31 #include "sslMemory.h"
32 #include "sslUtils.h"
33 #include "sslDigests.h"
34 #include "sslAlertMessage.h"
35 #include "sslCrypto.h"
36 #include "sslDebug.h"
37 #include "tls_hmac.h"
38 #include <assert.h>
39 #include <strings.h>
40
41 #define TLS_ENC_DEBUG 0
42 #if TLS_ENC_DEBUG
43 #define tlsDebug(format, args...) printf(format , ## args)
44 static void tlsDump(const char *name, void *b, unsigned len)
45 {
46 unsigned char *cp = (unsigned char *)b;
47 unsigned i, dex;
48
49 printf("%s\n", name);
50 for(dex=0; dex<len; dex++) {
51 i = cp[dex];
52 printf("%02X ", i);
53 if((dex % 16) == 15) {
54 printf("\n");
55 }
56 }
57 printf("\n");
58 }
59
60 #else
61 #define tlsDebug(s, ...)
62 #define tlsDump(name, b, len)
63 #endif /* TLS_ENC_DEBUG */
64
65 // MARK: -
66 // MARK: PRF label strings
67 /*
68 * Note we could optimize away a bunch of mallocs and frees if we, like openSSL,
69 * just mallocd buffers for inputs to SSLInternal_PRF() on the stack,
70 * with "known" max values for all of the inputs.
71 *
72 * At least we hard-code string lengths here instead of calling strlen at runtime...
73 */
74 #define PLS_MASTER_SECRET "master secret"
75 #define PLS_MASTER_SECRET_LEN 13
76 #define PLS_KEY_EXPAND "key expansion"
77 #define PLS_KEY_EXPAND_LEN 13
78 #define PLS_CLIENT_FINISH "client finished"
79 #define PLS_CLIENT_FINISH_LEN 15
80 #define PLS_SERVER_FINISH "server finished"
81 #define PLS_SERVER_FINISH_LEN 15
82 #define PLS_EXPORT_CLIENT_WRITE "client write key"
83 #define PLS_EXPORT_CLIENT_WRITE_LEN 16
84 #define PLS_EXPORT_SERVER_WRITE "server write key"
85 #define PLS_EXPORT_SERVER_WRITE_LEN 16
86 #define PLS_EXPORT_IV_BLOCK "IV block"
87 #define PLS_EXPORT_IV_BLOCK_LEN 8
88
89 // MARK: -
90 // MARK: private functions
91
92 /*
93 * P_Hash function defined in RFC2246, section 5.
94 */
95 static OSStatus tlsPHash(
96 SSLContext *ctx,
97 const HMACReference *hmac, // &TlsHmacSHA1, TlsHmacMD5
98 const uint8_t *secret,
99 size_t secretLen,
100 const uint8_t *seed,
101 size_t seedLen,
102 uint8_t *out, // mallocd by caller, size >= outLen
103 size_t outLen) // desired output size
104 {
105 unsigned char aSubI[TLS_HMAC_MAX_SIZE]; /* A(i) */
106 unsigned char digest[TLS_HMAC_MAX_SIZE];
107 HMACContextRef hmacCtx;
108 OSStatus serr;
109 size_t digestLen = hmac->macSize;
110
111 serr = hmac->alloc(hmac, secret, secretLen, &hmacCtx);
112 if(serr) {
113 return serr;
114 }
115
116 /* A(0) = seed */
117 /* A(1) := HMAC_hash(secret, seed) */
118 serr = hmac->hmac(hmacCtx, seed, seedLen, aSubI, &digestLen);
119 if(serr) {
120 goto fail;
121 }
122 assert(digestLen = hmac->macSize);
123
124 /* starting at loopNum 1... */
125 for (;;) {
126 /*
127 * This loop's chunk = HMAC_hash(secret, A(loopNum) + seed))
128 */
129 serr = hmac->init(hmacCtx);
130 if(serr) {
131 break;
132 }
133 serr = hmac->update(hmacCtx, aSubI, digestLen);
134 if(serr) {
135 break;
136 }
137 serr = hmac->update(hmacCtx, seed, seedLen);
138 if(serr) {
139 break;
140 }
141 serr = hmac->final(hmacCtx, digest, &digestLen);
142 if(serr) {
143 break;
144 }
145 assert(digestLen = hmac->macSize);
146
147 if(outLen <= digestLen) {
148 /* last time, possible partial digest */
149 memmove(out, digest, outLen);
150 break;
151 }
152
153 memmove(out, digest, digestLen);
154 out += digestLen;
155 outLen -= digestLen;
156
157 /*
158 * A(i) = HMAC_hash(secret, A(i-1))
159 * Note there is a possible optimization involving obtaining this
160 * hmac by cloning the state of hmacCtx above after updating with
161 * aSubI, and getting the final version of that here. However CDSA
162 * does not support cloning of a MAC context (only for digest contexts).
163 */
164 serr = hmac->hmac(hmacCtx, aSubI, digestLen,
165 aSubI, &digestLen);
166 if(serr) {
167 break;
168 }
169 assert(digestLen = hmac->macSize);
170 }
171 fail:
172 hmac->free(hmacCtx);
173 memset(aSubI, 0, TLS_HMAC_MAX_SIZE);
174 memset(digest, 0, TLS_HMAC_MAX_SIZE);
175 return serr;
176 }
177
178 /*
179 * The TLS pseudorandom function, defined in RFC2246, section 5.
180 * This takes as its input a secret block, a label, and a seed, and produces
181 * a caller-specified length of pseudorandom data.
182 *
183 * Optimization TBD: make label optional, avoid malloc and two copies if it's
184 * not there, so callers can take advantage of fixed-size seeds.
185 */
186 OSStatus SSLInternal_PRF(
187 SSLContext *ctx,
188 const void *vsecret,
189 size_t secretLen,
190 const void *label, // optional, NULL implies that seed contains
191 // the label
192 size_t labelLen,
193 const void *seed,
194 size_t seedLen,
195 void *vout, // mallocd by caller, length >= outLen
196 size_t outLen)
197 {
198 OSStatus serr = errSSLInternal;
199 const unsigned char *S1, *S2; // the two seeds
200 size_t sLen; // effective length of each seed
201 unsigned char *labelSeed = NULL; // label + seed, passed to tlsPHash
202 size_t labelSeedLen;
203 unsigned char *tmpOut = NULL; // output of P_SHA1
204 size_t i;
205 const unsigned char *secret = (const unsigned char *)vsecret;
206
207 if(label != NULL) {
208 /* concatenate label and seed */
209 labelSeedLen = labelLen + seedLen;
210 labelSeed = (unsigned char *)sslMalloc(labelSeedLen);
211 if(labelSeed == NULL) {
212 return errSecAllocate;
213 }
214 memmove(labelSeed, label, labelLen);
215 memmove(labelSeed + labelLen, seed, seedLen);
216 }
217 else {
218 /* fast track - just use seed as is */
219 labelSeed = (unsigned char *)seed;
220 labelSeedLen = seedLen;
221 }
222
223 unsigned char *out = (unsigned char *)vout;
224 if(sslVersionIsLikeTls12(ctx)) {
225 const HMACReference *mac = &TlsHmacSHA256;
226 if (ctx->selectedCipherSpecParams.macAlg == HA_SHA384) {
227 mac = &TlsHmacSHA384;
228 }
229 serr = tlsPHash(ctx, mac, secret, secretLen, labelSeed, labelSeedLen,
230 out, outLen);
231 if(serr) {
232 goto fail;
233 }
234 } else {
235 /* two seeds for tlsPHash */
236 sLen = secretLen / 2; // for partitioning
237 S1 = secret;
238 S2 = &secret[sLen];
239 sLen += (secretLen & 1); // secret length odd, increment effective size
240
241 /* temporary output for SHA1, to be XORd with MD5 */
242 tmpOut = (unsigned char *)sslMalloc(outLen);
243 if(tmpOut == NULL) {
244 serr = errSecAllocate;
245 goto fail;
246 }
247
248 serr = tlsPHash(ctx, &TlsHmacMD5, S1, sLen, labelSeed, labelSeedLen,
249 out, outLen);
250 if(serr) {
251 goto fail;
252 }
253 serr = tlsPHash(ctx, &TlsHmacSHA1, S2, sLen, labelSeed, labelSeedLen,
254 tmpOut, outLen);
255 if(serr) {
256 goto fail;
257 }
258
259 /* XOR together to get final result */
260 for(i=0; i<outLen; i++) {
261 out[i] ^= tmpOut[i];
262 }
263 }
264
265 serr = errSecSuccess;
266 fail:
267 if((labelSeed != NULL) && (label != NULL)) {
268 sslFree(labelSeed);
269 }
270 if(tmpOut != NULL) {
271 sslFree(tmpOut);
272 }
273 return serr;
274 }
275
276 /*
277 * On input, the following are valid:
278 * MasterSecret[48]
279 * ClientHello.random[32]
280 * ServerHello.random[32]
281 *
282 * key_block = PRF(SecurityParameters.master_secret,
283 * "key expansion",
284 * SecurityParameters.server_random +
285 * SecurityParameters.client_random);
286 */
287
288 #define GKM_SEED_LEN (PLS_KEY_EXPAND_LEN + (2 * SSL_CLIENT_SRVR_RAND_SIZE))
289
290 static OSStatus tls1GenerateKeyMaterial (
291 SSLBuffer key, // caller mallocs and specifies length of
292 // required key material here
293 SSLContext *ctx)
294 {
295 unsigned char seedBuf[GKM_SEED_LEN];
296 OSStatus serr;
297
298 /* use optimized label-less PRF */
299 memmove(seedBuf, PLS_KEY_EXPAND, PLS_KEY_EXPAND_LEN);
300 memmove(seedBuf + PLS_KEY_EXPAND_LEN, ctx->serverRandom,
301 SSL_CLIENT_SRVR_RAND_SIZE);
302 memmove(seedBuf + PLS_KEY_EXPAND_LEN + SSL_CLIENT_SRVR_RAND_SIZE,
303 ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE);
304 serr = SSLInternal_PRF(ctx,
305 ctx->masterSecret,
306 SSL_MASTER_SECRET_SIZE,
307 NULL, // no label
308 0,
309 seedBuf,
310 GKM_SEED_LEN,
311 key.data, // destination
312 key.length);
313 tlsDump("key expansion", key.data, key.length);
314 return serr;
315 }
316
317 /*
318 * On entry: clientRandom, serverRandom, preMasterSecret valid
319 * On return: masterSecret valid
320 *
321 * master_secret = PRF(pre_master_secret, "master secret",
322 * ClientHello.random + ServerHello.random)
323 * [0..47];
324 */
325
326 static OSStatus tls1GenerateMasterSecret (
327 SSLContext *ctx)
328 {
329 unsigned char randBuf[2 * SSL_CLIENT_SRVR_RAND_SIZE];
330 OSStatus serr;
331
332 memmove(randBuf, ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE);
333 memmove(randBuf + SSL_CLIENT_SRVR_RAND_SIZE,
334 ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE);
335 serr = SSLInternal_PRF(ctx,
336 ctx->preMasterSecret.data,
337 ctx->preMasterSecret.length,
338 (const unsigned char *)PLS_MASTER_SECRET,
339 PLS_MASTER_SECRET_LEN,
340 randBuf,
341 2 * SSL_CLIENT_SRVR_RAND_SIZE,
342 ctx->masterSecret, // destination
343 SSL_MASTER_SECRET_SIZE);
344 tlsDump("master secret", ctx->masterSecret, SSL_MASTER_SECRET_SIZE);
345 return serr;
346 }
347
348 /*
349 * Given digests contexts representing the running total of all handshake messages,
350 * calculate mac for "finished" message.
351 *
352 * verify_data = 12 bytes =
353 * PRF(master_secret, finished_label, MD5(handshake_messages) +
354 * SHA-1(handshake_messages)) [0..11];
355 */
356 static OSStatus tls1ComputeFinishedMac (
357 SSLContext *ctx,
358 SSLBuffer finished, // output - mallocd by caller
359 Boolean isServer)
360 {
361 unsigned char digests[SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN];
362 SSLBuffer digBuf;
363 char *finLabel;
364 unsigned finLabelLen;
365 OSStatus serr;
366 SSLBuffer shaMsgState, md5MsgState;
367
368 shaMsgState.data = 0;
369 md5MsgState.data = 0;
370 if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0)
371 goto fail;
372 if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0)
373 goto fail;
374
375 if(isServer) {
376 finLabel = PLS_SERVER_FINISH;
377 finLabelLen = PLS_SERVER_FINISH_LEN;
378 }
379 else {
380 finLabel = PLS_CLIENT_FINISH;
381 finLabelLen = PLS_CLIENT_FINISH_LEN;
382 }
383
384 /* concatenate two digest results */
385 digBuf.data = digests;
386 digBuf.length = SSL_MD5_DIGEST_LEN;
387 serr = SSLHashMD5.final(&md5MsgState, &digBuf);
388 if(serr) {
389 return serr;
390 }
391 digBuf.data += SSL_MD5_DIGEST_LEN;
392 digBuf.length = SSL_SHA1_DIGEST_LEN;
393 serr = SSLHashSHA1.final(&shaMsgState, &digBuf);
394 if(serr) {
395 return serr;
396 }
397 serr = SSLInternal_PRF(ctx,
398 ctx->masterSecret,
399 SSL_MASTER_SECRET_SIZE,
400 (const unsigned char *)finLabel,
401 finLabelLen,
402 digests,
403 SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN,
404 finished.data, // destination
405 finished.length);
406
407 fail:
408 SSLFreeBuffer(&shaMsgState);
409 SSLFreeBuffer(&md5MsgState);
410
411 return serr;
412 }
413
414 /*
415 * Given digests contexts representing the running total of all handshake messages,
416 * calculate mac for "finished" message.
417 *
418 * verify_data = 12 bytes =
419 * PRF(master_secret, finished_label, SHA256(handshake_messages)) [0..11];
420 */
421 static OSStatus tls12ComputeFinishedMac (
422 SSLContext *ctx,
423 SSLBuffer finished, // output - mallocd by caller
424 Boolean isServer)
425 {
426 unsigned char digest[SSL_MAX_DIGEST_LEN];
427 SSLBuffer digBuf;
428 char *finLabel;
429 unsigned finLabelLen;
430 OSStatus serr;
431 SSLBuffer hashState;
432 const HashReference *hashRef;
433 const SSLBuffer *ctxHashState;
434
435 /* The PRF used in the finished message is based on the cipherspec */
436 if (ctx->selectedCipherSpecParams.macAlg == HA_SHA384) {
437 hashRef = &SSLHashSHA384;
438 ctxHashState = &ctx->sha512State;
439 } else {
440 hashRef = &SSLHashSHA256;
441 ctxHashState = &ctx->sha256State;
442 }
443
444 hashState.data = 0;
445 if ((serr = CloneHashState(hashRef, ctxHashState, &hashState)) != 0)
446 goto fail;
447 if(isServer) {
448 finLabel = PLS_SERVER_FINISH;
449 finLabelLen = PLS_SERVER_FINISH_LEN;
450 }
451 else {
452 finLabel = PLS_CLIENT_FINISH;
453 finLabelLen = PLS_CLIENT_FINISH_LEN;
454 }
455
456 /* concatenate two digest results */
457 digBuf.data = digest;
458 digBuf.length = hashRef->digestSize;
459 if ((serr = hashRef->final(&hashState, &digBuf)) != 0)
460 goto fail;
461 serr = SSLInternal_PRF(ctx,
462 ctx->masterSecret,
463 SSL_MASTER_SECRET_SIZE,
464 (const unsigned char *)finLabel,
465 finLabelLen,
466 digBuf.data,
467 digBuf.length,
468 finished.data, // destination
469 finished.length);
470 fail:
471 SSLFreeBuffer(&hashState);
472 return serr;
473 }
474
475 /*
476 * This one is trivial.
477 *
478 * mac := MD5(handshake_messages) + SHA(handshake_messages);
479 *
480 * I don't know why this one doesn't use an HMAC or the master secret (as SSLv3
481 * does).
482 */
483 static OSStatus tls1ComputeCertVfyMac (
484 SSLContext *ctx,
485 SSLBuffer *finished, // output - mallocd by caller
486 SSL_HashAlgorithm hash) //unused in this one
487 {
488 SSLBuffer digBuf, shaMsgState, md5MsgState;
489 OSStatus serr;
490
491 shaMsgState.data = 0;
492 md5MsgState.data = 0;
493
494 if ((serr = CloneHashState(&SSLHashSHA1, &ctx->shaState, &shaMsgState)) != 0)
495 goto fail;
496 if ((serr = CloneHashState(&SSLHashMD5, &ctx->md5State, &md5MsgState)) != 0)
497 goto fail;
498
499 if ((ctx->protocolSide == kSSLServerSide && sslPubKeyGetAlgorithmID(ctx->peerPubKey) == kSecECDSAAlgorithmID) ||
500 (ctx->protocolSide == kSSLClientSide && ctx->negAuthType == SSLClientAuth_ECDSASign)) {
501 /* Only take SHA1 regardless of TLSv1.0 or TLSv1.1 If we are the server
502 and our peer signed with an ECDSA key, or if we are the client and
503 are about to sign with ECDSA. */
504 assert(finished->length >= SSL_SHA1_DIGEST_LEN);
505 digBuf.data = finished->data;
506 finished->length = SSL_SHA1_DIGEST_LEN;
507 } else {
508 /* Put MD5 follow by SHA1 hash in buffer. */
509 assert(finished->length >= (SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN));
510 digBuf.data = finished->data;
511 digBuf.length = SSL_MD5_DIGEST_LEN;
512 if ((serr = SSLHashMD5.final(&md5MsgState, &digBuf)) != 0)
513 goto fail;
514 digBuf.data = finished->data + SSL_MD5_DIGEST_LEN;
515 finished->length = SSL_MD5_DIGEST_LEN + SSL_SHA1_DIGEST_LEN;
516 }
517
518 digBuf.length = SSL_SHA1_DIGEST_LEN;
519 serr = SSLHashSHA1.final(&shaMsgState, &digBuf);
520
521 fail:
522 SSLFreeBuffer(&shaMsgState);
523 SSLFreeBuffer(&md5MsgState);
524
525 return serr;
526 }
527
528 static OSStatus tls12ComputeCertVfyMac (
529 SSLContext *ctx,
530 SSLBuffer *finished, // output - mallocd by caller
531 SSL_HashAlgorithm hash)
532 {
533 const SSLBuffer *ctxHashState;
534 const HashReference *hashRef;
535 SSLBuffer hashState;
536 OSStatus serr;
537
538 hashState.data = 0;
539
540 switch (hash) {
541 case SSL_HashAlgorithmSHA1:
542 hashRef = &SSLHashSHA1;
543 ctxHashState = &ctx->shaState;
544 break;
545 case SSL_HashAlgorithmSHA256:
546 hashRef = &SSLHashSHA256;
547 ctxHashState = &ctx->sha256State;
548 break;
549 case SSL_HashAlgorithmSHA384:
550 hashRef = &SSLHashSHA384;
551 ctxHashState = &ctx->sha512State;
552 break;
553 default:
554 return errSSLInternal;
555 break;
556 }
557
558 if ((serr = CloneHashState(hashRef, ctxHashState, &hashState)) != 0)
559 goto fail;
560
561 assert(finished->length >= (hashRef->digestSize));
562 finished->length = hashRef->digestSize;
563 serr = hashRef->final(&hashState, finished);
564
565 fail:
566 SSLFreeBuffer(&hashState);
567
568 return serr;
569 }
570
571
572 const SslTlsCallouts Tls1Callouts = {
573 tls1GenerateKeyMaterial,
574 tls1GenerateMasterSecret,
575 tls1ComputeFinishedMac,
576 tls1ComputeCertVfyMac
577 };
578
579 const SslTlsCallouts Tls12Callouts = {
580 tls1GenerateKeyMaterial,
581 tls1GenerateMasterSecret,
582 tls12ComputeFinishedMac,
583 tls12ComputeCertVfyMac
584 };