2 * Copyright (c) 2002 Apple Computer, Inc. All Rights Reserved.
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
22 Contains: TLSv1-specific routines for SslTlsCallouts.
24 Written by: Doug Mitchell
28 #include "sslMemory.h"
30 #include "sslDigests.h"
31 #include "sslAlertMessage.h"
36 #define TLS_ENC_DEBUG 0
38 #define tlsDebug(format, args...) printf(format , ## args)
39 static void tlsDump(const char *name
, void *b
, unsigned len
)
41 unsigned char *cp
= (unsigned char *)b
;
45 for(dex
=0; dex
<len
; dex
++) {
48 if((dex
% 16) == 15) {
56 #define tlsDebug(s, ...)
57 #define tlsDump(name, b, len)
58 #endif /* TLS_ENC_DEBUG */
60 #pragma *** PRF label strings ***
62 * Note we could optimize away a bunch of mallocs and frees if we, like openSSL,
63 * just mallocd buffers for inputs to SSLInternal_PRF() on the stack,
64 * with "known" max values for all of the inputs.
66 * At least we hard-code string lengths here instead of calling strlen at runtime...
68 #define PLS_MASTER_SECRET "master secret"
69 #define PLS_MASTER_SECRET_LEN 13
70 #define PLS_KEY_EXPAND "key expansion"
71 #define PLS_KEY_EXPAND_LEN 13
72 #define PLS_CLIENT_FINISH "client finished"
73 #define PLS_CLIENT_FINISH_LEN 15
74 #define PLS_SERVER_FINISH "server finished"
75 #define PLS_SERVER_FINISH_LEN 15
76 #define PLS_EXPORT_CLIENT_WRITE "client write key"
77 #define PLS_EXPORT_CLIENT_WRITE_LEN 16
78 #define PLS_EXPORT_SERVER_WRITE "server write key"
79 #define PLS_EXPORT_SERVER_WRITE_LEN 16
80 #define PLS_EXPORT_IV_BLOCK "IV block"
81 #define PLS_EXPORT_IV_BLOCK_LEN 8
83 #pragma mark *** private functions ***
86 * P_Hash function defined in RFC2246, section 5.
88 static OSStatus
tlsPHash(
90 const HMACReference
*hmac
, // &TlsHmacSHA1, TlsHmacMD5
91 const unsigned char *secret
,
95 unsigned char *out
, // mallocd by caller, size >= outLen
96 unsigned outLen
) // desired output size
98 unsigned char aSubI
[TLS_HMAC_MAX_SIZE
]; /* A(i) */
99 unsigned char digest
[TLS_HMAC_MAX_SIZE
];
100 HMACContextRef hmacCtx
;
102 unsigned digestLen
= hmac
->macSize
;
104 serr
= hmac
->alloc(hmac
, ctx
, secret
, secretLen
, &hmacCtx
);
110 /* A(1) := HMAC_hash(secret, seed) */
111 serr
= hmac
->hmac(hmacCtx
, seed
, seedLen
, aSubI
, &digestLen
);
115 assert(digestLen
= hmac
->macSize
);
117 /* starting at loopNum 1... */
120 * This loop's chunk = HMAC_hash(secret, A(loopNum) + seed))
122 serr
= hmac
->init(hmacCtx
);
126 serr
= hmac
->update(hmacCtx
, aSubI
, digestLen
);
130 serr
= hmac
->update(hmacCtx
, seed
, seedLen
);
134 serr
= hmac
->final(hmacCtx
, digest
, &digestLen
);
138 assert(digestLen
= hmac
->macSize
);
140 if(outLen
<= digestLen
) {
141 /* last time, possible partial digest */
142 memmove(out
, digest
, outLen
);
146 memmove(out
, digest
, digestLen
);
151 * A(i) = HMAC_hash(secret, A(i-1))
152 * Note there is a possible optimization involving obtaining this
153 * hmac by cloning the state of hmacCtx above after updating with
154 * aSubI, and getting the final version of that here. However CDSA
155 * does not support cloning of a MAC context (only for digest contexts).
157 serr
= hmac
->hmac(hmacCtx
, aSubI
, digestLen
,
162 assert(digestLen
= hmac
->macSize
);
166 memset(aSubI
, 0, TLS_HMAC_MAX_SIZE
);
167 memset(digest
, 0, TLS_HMAC_MAX_SIZE
);
172 * The TLS pseudorandom function, defined in RFC2246, section 5.
173 * This takes as its input a secret block, a label, and a seed, and produces
174 * a caller-specified length of pseudorandom data.
176 * Optimization TBD: make label optional, avoid malloc and two copies if it's
177 * not there, so callers can take advantage of fixed-size seeds.
179 OSStatus
SSLInternal_PRF(
183 const void *label
, // optional, NULL implies that seed contains
188 void *vout
, // mallocd by caller, length >= outLen
191 OSStatus serr
= errSSLInternal
;
192 const unsigned char *S1
, *S2
; // the two seeds
193 unsigned sLen
; // effective length of each seed
194 unsigned char *labelSeed
= NULL
; // label + seed, passed to tlsPHash
195 unsigned labelSeedLen
;
196 unsigned char *tmpOut
= NULL
; // output of P_SHA1
198 const unsigned char *secret
= (const unsigned char *)vsecret
;
200 /* two seeds for tlsPHash */
201 sLen
= secretLen
/ 2; // for partitioning
204 sLen
+= (secretLen
& 1); // secret length odd, increment effective size
207 /* concatenate label and seed */
208 labelSeedLen
= labelLen
+ seedLen
;
209 labelSeed
= (unsigned char *)sslMalloc(labelSeedLen
);
210 if(labelSeed
== NULL
) {
213 memmove(labelSeed
, label
, labelLen
);
214 memmove(labelSeed
+ labelLen
, seed
, seedLen
);
217 /* fast track - just use seed as is */
218 labelSeed
= (unsigned char *)seed
;
219 labelSeedLen
= seedLen
;
222 /* temporary output for SHA1, to be XORd with MD5 */
223 unsigned char *out
= (unsigned char *)vout
;
224 tmpOut
= (unsigned char *)sslMalloc(outLen
);
229 serr
= tlsPHash(ctx
, &TlsHmacMD5
, S1
, sLen
, labelSeed
, labelSeedLen
,
234 serr
= tlsPHash(ctx
, &TlsHmacSHA1
, S2
, sLen
, labelSeed
, labelSeedLen
,
240 /* XOR together to get final result */
241 for(i
=0; i
<outLen
; i
++) {
247 if((labelSeed
!= NULL
) && (label
!= NULL
)) {
256 /* not needed; encrypt/encode is the same for both protocols as long as
257 * we don't use the "variable length padding" feature. */
259 static OSStatus
tls1WriteRecord(
268 static OSStatus
tls1DecryptRecord(
276 if ((ctx
->readCipher
.symCipher
->blockSize
> 0) &&
277 ((payload
->length
% ctx
->readCipher
.symCipher
->blockSize
) != 0)) {
278 SSLFatalSessionAlert(SSL_AlertRecordOverflow
, ctx
);
279 return errSSLRecordOverflow
;
282 /* Decrypt in place */
283 if ((err
= ctx
->readCipher
.symCipher
->decrypt(*payload
,
287 { SSLFatalSessionAlert(SSL_AlertDecryptError
, ctx
);
288 return errSSLDecryptionFail
;
291 /* Locate content within decrypted payload */
292 content
.data
= payload
->data
;
293 content
.length
= payload
->length
- ctx
->readCipher
.macRef
->hash
->digestSize
;
294 if (ctx
->readCipher
.symCipher
->blockSize
> 0) {
295 /* for TLSv1, padding can be anywhere from 0 to 255 bytes */
296 UInt8 padSize
= payload
->data
[payload
->length
- 1];
299 /* verify that all padding bytes are equal - WARNING - OpenSSL code
300 * has a special case here dealing with some kind of bug related to
301 * even size packets...beware... */
302 if(padSize
> payload
->length
) {
303 SSLFatalSessionAlert(SSL_AlertDecodeError
, ctx
);
304 sslErrorLog("tls1DecryptRecord: bad padding length (%d)\n",
305 (unsigned)payload
->data
[payload
->length
- 1]);
306 return errSSLDecryptionFail
;
308 padChars
= payload
->data
+ payload
->length
- padSize
;
309 while(padChars
< (payload
->data
+ payload
->length
)) {
310 if(*padChars
++ != padSize
) {
311 SSLFatalSessionAlert(SSL_AlertDecodeError
, ctx
);
312 sslErrorLog("tls1DecryptRecord: bad padding value\n");
313 return errSSLDecryptionFail
;
316 /* Remove block size padding and its one-byte length */
317 content
.length
-= (1 + padSize
);
320 /* Verify MAC on payload */
321 if (ctx
->readCipher
.macRef
->hash
->digestSize
> 0)
322 /* Optimize away MAC for null case */
323 if ((err
= SSLVerifyMac(type
, content
,
324 payload
->data
+ content
.length
, ctx
)) != 0)
325 { SSLFatalSessionAlert(SSL_AlertBadRecordMac
, ctx
);
326 return errSSLBadRecordMac
;
329 *payload
= content
; /* Modify payload buffer to indicate content length */
334 /* initialize a per-CipherContext HashHmacContext for use in MACing each record */
335 static OSStatus
tls1InitMac (
336 CipherContext
*cipherCtx
, // macRef, macSecret valid on entry
337 // macCtx valid on return
340 const HMACReference
*hmac
;
343 assert(cipherCtx
->macRef
!= NULL
);
344 hmac
= cipherCtx
->macRef
->hmac
;
345 assert(hmac
!= NULL
);
347 if(cipherCtx
->macCtx
.hmacCtx
!= NULL
) {
348 hmac
->free(cipherCtx
->macCtx
.hmacCtx
);
349 cipherCtx
->macCtx
.hmacCtx
= NULL
;
351 serr
= hmac
->alloc(hmac
, ctx
, cipherCtx
->macSecret
,
352 cipherCtx
->macRef
->hmac
->macSize
, &cipherCtx
->macCtx
.hmacCtx
);
354 /* mac secret now stored in macCtx.hmacCtx, delete it from cipherCtx */
355 memset(cipherCtx
->macSecret
, 0, sizeof(cipherCtx
->macSecret
));
359 static OSStatus
tls1FreeMac (
360 CipherContext
*cipherCtx
)
362 /* this can be called on a completely zeroed out CipherContext... */
363 if(cipherCtx
->macRef
== NULL
) {
366 assert(cipherCtx
->macRef
->hmac
!= NULL
);
368 if(cipherCtx
->macCtx
.hmacCtx
!= NULL
) {
369 cipherCtx
->macRef
->hmac
->free(cipherCtx
->macCtx
.hmacCtx
);
370 cipherCtx
->macCtx
.hmacCtx
= NULL
;
376 * mac = HMAC_hash(MAC_write_secret, seq_num + TLSCompressed.type +
377 * TLSCompressed.version + TLSCompressed.length +
378 * TLSCompressed.fragment));
381 /* sequence, type, version, length */
382 #define HDR_LENGTH (8 + 1 + 2 + 2)
383 OSStatus
tls1ComputeMac (
386 SSLBuffer mac
, // caller mallocs data
387 CipherContext
*cipherCtx
, // assumes macCtx, macRef
391 unsigned char hdr
[HDR_LENGTH
];
393 HMACContextRef hmacCtx
;
395 const HMACReference
*hmac
;
398 assert(cipherCtx
!= NULL
);
399 assert(cipherCtx
->macRef
!= NULL
);
400 hmac
= cipherCtx
->macRef
->hmac
;
401 assert(hmac
!= NULL
);
402 hmacCtx
= cipherCtx
->macCtx
.hmacCtx
; // may be NULL, for null cipher
404 serr
= hmac
->init(hmacCtx
);
408 p
= SSLEncodeUInt64(hdr
, seqNo
);
410 *p
++ = TLS_Version_1_0
>> 8;
411 *p
++ = TLS_Version_1_0
& 0xff;
412 *p
++ = data
.length
>> 8;
413 *p
= data
.length
& 0xff;
414 serr
= hmac
->update(hmacCtx
, hdr
, HDR_LENGTH
);
418 serr
= hmac
->update(hmacCtx
, data
.data
, data
.length
);
422 macLength
= mac
.length
;
423 serr
= hmac
->final(hmacCtx
, mac
.data
, &macLength
);
427 mac
.length
= macLength
;
433 * On input, the following are valid:
435 * ClientHello.random[32]
436 * ServerHello.random[32]
438 * key_block = PRF(SecurityParameters.master_secret,
440 * SecurityParameters.server_random +
441 * SecurityParameters.client_random);
444 #define GKM_SEED_LEN (PLS_KEY_EXPAND_LEN + (2 * SSL_CLIENT_SRVR_RAND_SIZE))
446 OSStatus
tls1GenerateKeyMaterial (
447 SSLBuffer key
, // caller mallocs and specifies length of
448 // required key material here
451 unsigned char seedBuf
[GKM_SEED_LEN
];
454 /* use optimized label-less PRF */
455 memmove(seedBuf
, PLS_KEY_EXPAND
, PLS_KEY_EXPAND_LEN
);
456 memmove(seedBuf
+ PLS_KEY_EXPAND_LEN
, ctx
->serverRandom
,
457 SSL_CLIENT_SRVR_RAND_SIZE
);
458 memmove(seedBuf
+ PLS_KEY_EXPAND_LEN
+ SSL_CLIENT_SRVR_RAND_SIZE
,
459 ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
460 serr
= SSLInternal_PRF(ctx
,
462 SSL_MASTER_SECRET_SIZE
,
467 key
.data
, // destination
469 tlsDump("key expansion", key
.data
, key
.length
);
474 * final_client_write_key =
475 * PRF(SecurityParameters.client_write_key,
476 * "client write key",
477 * SecurityParameters.client_random +
478 * SecurityParameters.server_random);
479 * final_server_write_key =
480 * PRF(SecurityParameters.server_write_key,
481 * "server write key",
482 * SecurityParameters.client_random +
483 * SecurityParameters.server_random);
485 * iv_block = PRF("", "IV block", SecurityParameters.client_random +
486 * SecurityParameters.server_random);
488 * iv_block is broken up into:
490 * client_write_IV[SecurityParameters.IV_size]
491 * server_write_IV[SecurityParameters.IV_size]
493 OSStatus
tls1GenerateExportKeyAndIv (
494 SSLContext
*ctx
, // clientRandom, serverRandom valid
495 const SSLBuffer clientWriteKey
,
496 const SSLBuffer serverWriteKey
,
497 SSLBuffer finalClientWriteKey
, // RETURNED, mallocd by caller
498 SSLBuffer finalServerWriteKey
, // RETURNED, mallocd by caller
499 SSLBuffer finalClientIV
, // RETURNED, mallocd by caller
500 SSLBuffer finalServerIV
) // RETURNED, mallocd by caller
502 unsigned char randBuf
[2 * SSL_CLIENT_SRVR_RAND_SIZE
];
504 unsigned char *ivBlock
;
507 /* all three PRF calls use the same seed */
508 memmove(randBuf
, ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
509 memmove(randBuf
+ SSL_CLIENT_SRVR_RAND_SIZE
,
510 ctx
->serverRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
512 serr
= SSLInternal_PRF(ctx
,
514 clientWriteKey
.length
,
515 (const unsigned char *)PLS_EXPORT_CLIENT_WRITE
,
516 PLS_EXPORT_CLIENT_WRITE_LEN
,
518 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
519 finalClientWriteKey
.data
, // destination
520 finalClientWriteKey
.length
);
524 serr
= SSLInternal_PRF(ctx
,
526 serverWriteKey
.length
,
527 (const unsigned char *)PLS_EXPORT_SERVER_WRITE
,
528 PLS_EXPORT_SERVER_WRITE_LEN
,
530 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
531 finalServerWriteKey
.data
, // destination
532 finalServerWriteKey
.length
);
536 if((finalClientIV
.length
== 0) && (finalServerIV
.length
== 0)) {
537 /* skip remainder as optimization */
540 ivBlock
= (unsigned char *)sslMalloc(finalClientIV
.length
+ finalServerIV
.length
);
541 if(ivBlock
== NULL
) {
544 serr
= SSLInternal_PRF(ctx
,
545 (const unsigned char *)nullKey
,
547 (const unsigned char *)PLS_EXPORT_IV_BLOCK
,
548 PLS_EXPORT_IV_BLOCK_LEN
,
550 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
551 ivBlock
, // destination
552 finalClientIV
.length
+ finalServerIV
.length
);
556 memmove(finalClientIV
.data
, ivBlock
, finalClientIV
.length
);
557 memmove(finalServerIV
.data
, ivBlock
+ finalClientIV
.length
, finalServerIV
.length
);
564 * On entry: clientRandom, serverRandom, preMasterSecret valid
565 * On return: masterSecret valid
567 * master_secret = PRF(pre_master_secret, "master secret",
568 * ClientHello.random + ServerHello.random)
572 OSStatus
tls1GenerateMasterSecret (
575 unsigned char randBuf
[2 * SSL_CLIENT_SRVR_RAND_SIZE
];
578 memmove(randBuf
, ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
579 memmove(randBuf
+ SSL_CLIENT_SRVR_RAND_SIZE
,
580 ctx
->serverRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
581 serr
= SSLInternal_PRF(ctx
,
582 ctx
->preMasterSecret
.data
,
583 ctx
->preMasterSecret
.length
,
584 (const unsigned char *)PLS_MASTER_SECRET
,
585 PLS_MASTER_SECRET_LEN
,
587 2 * SSL_CLIENT_SRVR_RAND_SIZE
,
588 ctx
->masterSecret
, // destination
589 SSL_MASTER_SECRET_SIZE
);
590 tlsDump("master secret", ctx
->masterSecret
, SSL_MASTER_SECRET_SIZE
);
595 * Given digests contexts representing the running total of all handshake messages,
596 * calculate mac for "finished" message.
598 * verify_data = 12 bytes =
599 * PRF(master_secret, finished_label, MD5(handshake_messages) +
600 * SHA-1(handshake_messages)) [0..11];
602 OSStatus
tls1ComputeFinishedMac (
604 SSLBuffer finished
, // output - mallocd by caller
605 SSLBuffer shaMsgState
, // clone of running digest of all handshake msgs
606 SSLBuffer md5MsgState
, // ditto
609 unsigned char digests
[SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
];
612 unsigned finLabelLen
;
616 finLabel
= PLS_SERVER_FINISH
;
617 finLabelLen
= PLS_SERVER_FINISH_LEN
;
620 finLabel
= PLS_CLIENT_FINISH
;
621 finLabelLen
= PLS_CLIENT_FINISH_LEN
;
624 /* concatenate two digest results */
625 digBuf
.data
= digests
;
626 digBuf
.length
= SSL_MD5_DIGEST_LEN
;
627 serr
= SSLHashMD5
.final(md5MsgState
, digBuf
);
631 digBuf
.data
+= SSL_MD5_DIGEST_LEN
;
632 digBuf
.length
= SSL_SHA1_DIGEST_LEN
;
633 serr
= SSLHashSHA1
.final(shaMsgState
, digBuf
);
637 return SSLInternal_PRF(ctx
,
639 SSL_MASTER_SECRET_SIZE
,
640 (const unsigned char *)finLabel
,
643 SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
,
644 finished
.data
, // destination
649 * This one is trivial.
651 * mac := MD5(handshake_messages) + SHA(handshake_messages);
653 * I don't know why this one doesn't use an HMAC or the master secret (as SSLv3
656 OSStatus
tls1ComputeCertVfyMac (
658 SSLBuffer finished
, // output - mallocd by caller
659 SSLBuffer shaMsgState
, // clone of running digest of all handshake msgs
660 SSLBuffer md5MsgState
) // ditto
665 assert(finished
.length
== (SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
));
666 digBuf
.data
= finished
.data
;
667 digBuf
.length
= SSL_MD5_DIGEST_LEN
;
668 serr
= SSLHashMD5
.final(md5MsgState
, digBuf
);
672 digBuf
.data
= finished
.data
+ SSL_MD5_DIGEST_LEN
;
673 digBuf
.length
= SSL_SHA1_DIGEST_LEN
;
674 return SSLHashSHA1
.final(shaMsgState
, digBuf
);
677 const SslTlsCallouts Tls1Callouts
= {
683 tls1GenerateKeyMaterial
,
684 tls1GenerateExportKeyAndIv
,
685 tls1GenerateMasterSecret
,
686 tls1ComputeFinishedMac
,
687 tls1ComputeCertVfyMac