2 * Copyright (c) 2002,2005-2007,2010-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 * ssl3Callouts.c - SSLv3-specific routines for SslTlsCallouts.
28 #include "sslMemory.h"
31 #include "sslDigests.h"
33 #include "sslAlertMessage.h"
40 * ssl3WriteRecord does not send alerts on failure, out of the assumption/fear
41 * that this might result in a loop (since sending an alert causes ssl3WriteRecord
44 * As far as I can tell, we can use this same routine for SSLv3 and TLSv1, as long
45 * as we're not trying to use the "variable length padding" feature of TLSv1.
46 * OpenSSL doesn't use that feature; for now, neither will we. Thus this routine
47 * is used for the SslTlsCallouts.writeRecord function for both protocols.
49 OSStatus
ssl3WriteRecord(
55 WaitingRecord
*out
= NULL
, *queue
;
56 SSLBuffer payload
, mac
;
58 UInt16 payloadSize
,blockSize
;
61 switch(rec
.protocolVersion
) {
62 case DTLS_Version_1_0
:
71 return errSSLInternal
;
73 assert(rec
.contents
.length
<= 16384);
75 sslLogRecordIo("type = %02x, ver = %04x, len = %ld, seq = %08x_%08x",
76 rec
.contentType
, rec
.protocolVersion
, rec
.contents
.length
,
77 ctx
->writeCipher
.sequenceNum
.high
, ctx
->writeCipher
.sequenceNum
.low
);
79 /* Allocate enough room for the transmitted record, which will be:
80 * 5 bytes of header (13 for DTLS) +
81 * IV [block cipher and TLS1.1 or DTLS 1.0 only]
82 * encrypted contents +
84 * padding [block ciphers only] +
85 * padding length field (1 byte) [block ciphers only]
87 payloadSize
= (UInt16
) (rec
.contents
.length
+ ctx
->writeCipher
.macRef
->hash
->digestSize
);
88 blockSize
= ctx
->writeCipher
.symCipher
->blockSize
;
91 padding
= blockSize
- (payloadSize
% blockSize
) - 1;
92 payloadSize
+= padding
+ 1;
93 /* TLS 1.1 and DTLS 1.0 have an extra block for IV */
94 if(ctx
->negProtocolVersion
>= TLS_Version_1_1
) {
95 payloadSize
+= blockSize
;
99 out
= (WaitingRecord
*)sslMalloc(offsetof(WaitingRecord
, data
) +
103 out
->length
= head
+ payloadSize
;
106 *(charPtr
++) = rec
.contentType
;
107 charPtr
= SSLEncodeInt(charPtr
, rec
.protocolVersion
, 2);
109 /* DTLS sequence number */
110 if(rec
.protocolVersion
== DTLS_Version_1_0
)
111 charPtr
= SSLEncodeUInt64(charPtr
,ctx
->writeCipher
.sequenceNum
);
113 charPtr
= SSLEncodeInt(charPtr
, payloadSize
, 2);
116 if((ctx
->negProtocolVersion
>= TLS_Version_1_1
) && (blockSize
>0))
119 randomIV
.data
= charPtr
;
120 randomIV
.length
= blockSize
;
121 if((err
= sslRand(ctx
, &randomIV
)) != 0)
123 charPtr
+= blockSize
;
126 /* Copy the contents into the output buffer */
127 memcpy(charPtr
, rec
.contents
.data
, rec
.contents
.length
);
128 payload
.data
= charPtr
;
129 payload
.length
= rec
.contents
.length
;
131 charPtr
+= rec
.contents
.length
;
132 /* MAC immediately follows data */
134 mac
.length
= ctx
->writeCipher
.macRef
->hash
->digestSize
;
135 charPtr
+= mac
.length
;
138 if (mac
.length
> 0) /* Optimize away null case */
140 assert(ctx
->sslTslCalls
!= NULL
);
141 if ((err
= ctx
->sslTslCalls
->computeMac(rec
.contentType
,
145 ctx
->writeCipher
.sequenceNum
,
150 /* For TLS 1.1 and DTLS, we would need to specify the IV, but instead
151 we are clever like this: since the IV is just one block in front,
152 we encrypt it with the rest of the data. The actual transmitted IV
153 is the result of the encryption, with whatever internal IV is used.
154 This method is explained in the TLS 1.1 RFC */
155 if(ctx
->negProtocolVersion
>= TLS_Version_1_1
)
158 payload
.data
-= blockSize
;
161 /* Update payload to reflect encrypted data: IV, contents, mac & padding */
162 payload
.length
= payloadSize
;
164 /* Fill in the padding bytes & padding length field with the padding value; the
165 * protocol only requires the last byte,
166 * but filling them all in avoids leaking data
168 if (ctx
->writeCipher
.symCipher
->blockSize
> 0)
169 for (i
= 1; i
<= padding
+ 1; ++i
)
170 payload
.data
[payload
.length
- i
] = padding
;
172 /* Encrypt the data */
173 if ((err
= ctx
->writeCipher
.symCipher
->encrypt(payload
.data
,
174 payload
.data
, payload
.length
,
179 /* Enqueue the record to be written from the idle loop */
180 if (ctx
->recordWriteQueue
== 0)
181 ctx
->recordWriteQueue
= out
;
183 { queue
= ctx
->recordWriteQueue
;
184 while (queue
->next
!= 0)
189 /* Increment the sequence number */
190 IncrementUInt64(&ctx
->writeCipher
.sequenceNum
);
196 * Only for if we fail between when the WaitingRecord is allocated and when
203 static OSStatus
ssl3DecryptRecord(
211 if ((ctx
->readCipher
.symCipher
->blockSize
> 0) &&
212 ((payload
->length
% ctx
->readCipher
.symCipher
->blockSize
) != 0))
213 { SSLFatalSessionAlert(SSL_AlertUnexpectedMsg
, ctx
);
214 return errSSLProtocol
;
217 /* Decrypt in place */
218 if ((err
= ctx
->readCipher
.symCipher
->decrypt(payload
->data
,
219 payload
->data
, payload
->length
,
223 /* Complies with TLS 1.1 - But we do it for every protocol version */
224 SSLFatalSessionAlert(SSL_AlertBadRecordMac
, ctx
);
228 /* Locate content within decrypted payload */
229 content
.data
= payload
->data
;
230 content
.length
= payload
->length
- ctx
->readCipher
.macRef
->hash
->digestSize
;
231 if (ctx
->readCipher
.symCipher
->blockSize
> 0)
232 { /* padding can't be equal to or more than a block */
233 if (payload
->data
[payload
->length
- 1] >= ctx
->readCipher
.symCipher
->blockSize
)
235 /* Complies with TLS 1.1 - But we do it for every protocol version */
236 SSLFatalSessionAlert(SSL_AlertBadRecordMac
, ctx
);
237 sslErrorLog("DecryptSSLRecord: bad padding length (%d)\n",
238 (unsigned)payload
->data
[payload
->length
- 1]);
239 return errSSLDecryptionFail
;
241 content
.length
-= 1 + payload
->data
[payload
->length
- 1];
242 /* Remove block size padding */
245 /* Verify MAC on payload */
246 if (ctx
->readCipher
.macRef
->hash
->digestSize
> 0)
247 /* Optimize away MAC for null case */
248 if ((err
= SSLVerifyMac(type
, &content
,
249 payload
->data
+ content
.length
, ctx
)) != 0)
250 { SSLFatalSessionAlert(SSL_AlertBadRecordMac
, ctx
);
251 return errSSLBadRecordMac
;
254 *payload
= content
; /* Modify payload buffer to indicate content length */
259 /* initialize a per-CipherContext HashHmacContext for use in MACing each record */
260 static OSStatus
ssl3InitMac (
261 CipherContext
*cipherCtx
, // macRef, macSecret valid on entry
262 // macCtx valid on return
265 const HashReference
*hash
;
269 assert(cipherCtx
->macRef
!= NULL
);
270 hash
= cipherCtx
->macRef
->hash
;
271 assert(hash
!= NULL
);
273 hashCtx
= &cipherCtx
->macCtx
.hashCtx
;
274 if(hashCtx
->data
!= NULL
) {
275 SSLFreeBuffer(hashCtx
, ctx
);
277 serr
= SSLAllocBuffer(hashCtx
, hash
->contextSize
, ctx
);
284 static OSStatus
ssl3FreeMac (
285 CipherContext
*cipherCtx
)
289 assert(cipherCtx
!= NULL
);
290 /* this can be called on a completely zeroed out CipherContext... */
291 if(cipherCtx
->macRef
== NULL
) {
294 hashCtx
= &cipherCtx
->macCtx
.hashCtx
;
295 if(hashCtx
->data
!= NULL
) {
296 sslFree(hashCtx
->data
);
297 hashCtx
->data
= NULL
;
303 static OSStatus
ssl3ComputeMac (
306 SSLBuffer mac
, // caller mallocs data
307 CipherContext
*cipherCtx
, // assumes macCtx, macRef
312 UInt8 innerDigestData
[SSL_MAX_DIGEST_LEN
];
313 UInt8 scratchData
[11], *charPtr
;
314 SSLBuffer digest
, digestCtx
, scratch
;
317 const HashReference
*hash
;
319 assert(cipherCtx
!= NULL
);
320 assert(cipherCtx
->macRef
!= NULL
);
321 hash
= cipherCtx
->macRef
->hash
;
322 assert(hash
!= NULL
);
323 assert(hash
->macPadSize
<= MAX_MAC_PADDING
);
324 assert(hash
->digestSize
<= SSL_MAX_DIGEST_LEN
);
325 digestCtx
= cipherCtx
->macCtx
.hashCtx
; // may be NULL, for null cipher
326 secret
.data
= cipherCtx
->macSecret
;
327 secret
.length
= hash
->digestSize
;
329 /* init'd early in SSLNewContext() */
330 assert(SSLMACPad1
[0] == 0x36 && SSLMACPad2
[0] == 0x5C);
333 * MAC = hash( MAC_write_secret + pad_2 +
334 * hash( MAC_write_secret + pad_1 + seq_num + type +
338 if ((err
= hash
->init(&digestCtx
, ctx
)) != 0)
340 if ((err
= hash
->update(&digestCtx
, &secret
)) != 0) /* MAC secret */
342 scratch
.data
= (UInt8
*)SSLMACPad1
;
343 scratch
.length
= hash
->macPadSize
;
344 if ((err
= hash
->update(&digestCtx
, &scratch
)) != 0) /* pad1 */
346 charPtr
= scratchData
;
347 charPtr
= SSLEncodeUInt64(charPtr
, seqNo
);
349 charPtr
= SSLEncodeSize(charPtr
, data
.length
, 2);
350 scratch
.data
= scratchData
;
352 assert(charPtr
= scratchData
+11);
353 if ((err
= hash
->update(&digestCtx
, &scratch
)) != 0)
354 /* sequenceNo, type & length */
356 if ((err
= hash
->update(&digestCtx
, &data
)) != 0) /* content */
358 digest
.data
= innerDigestData
;
359 digest
.length
= hash
->digestSize
;
360 if ((err
= hash
->final(&digestCtx
, &digest
)) != 0) /* figure inner digest */
363 if ((err
= hash
->init(&digestCtx
, ctx
)) != 0)
365 if ((err
= hash
->update(&digestCtx
, &secret
)) != 0) /* MAC secret */
367 scratch
.data
= (UInt8
*)SSLMACPad2
;
368 scratch
.length
= hash
->macPadSize
;
369 if ((err
= hash
->update(&digestCtx
, &scratch
)) != 0) /* pad2 */
371 if ((err
= hash
->update(&digestCtx
, &digest
)) != 0) /* inner digest */
373 if ((err
= hash
->final(&digestCtx
, &mac
)) != 0) /* figure the mac */
376 err
= noErr
; /* redundant, I know */
382 #define LOG_GEN_KEY 0
385 * On input, the following are valid:
387 * ClientHello.random[32]
388 * ServerHello.random[32]
391 * MD5(master_secret + SHA(`A' + master_secret +
392 * ServerHello.random +
393 * ClientHello.random)) +
394 * MD5(master_secret + SHA(`BB' + master_secret +
395 * ServerHello.random +
396 * ClientHello.random)) +
397 * MD5(master_secret + SHA(`CCC' + master_secret +
398 * ServerHello.random +
399 * ClientHello.random)) + [...];
401 static OSStatus
ssl3GenerateKeyMaterial (
402 SSLBuffer key
, // caller mallocs and specifies length of
403 // required key material here
407 UInt8 leaderData
[10]; /* Max of 10 hashes
408 * (* 16 bytes/hash = 160 bytes of key) */
409 UInt8 shaHashData
[20], md5HashData
[16];
410 SSLBuffer shaContext
, md5Context
;
412 size_t i
,j
,remaining
, satisfied
;
413 SSLBuffer leader
, masterSecret
, serverRandom
, clientRandom
, shaHash
, md5Hash
;
416 printf("GenerateKey: master ");
417 for(i
=0; i
<SSL_MASTER_SECRET_SIZE
; i
++) {
418 printf("%02X ", ctx
->masterSecret
[i
]);
423 assert(key
.length
<= 16 * sizeof(leaderData
));
425 leader
.data
= leaderData
;
426 masterSecret
.data
= ctx
->masterSecret
;
427 masterSecret
.length
= SSL_MASTER_SECRET_SIZE
;
428 serverRandom
.data
= ctx
->serverRandom
;
429 serverRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
430 clientRandom
.data
= ctx
->clientRandom
;
431 clientRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
432 shaHash
.data
= shaHashData
;
434 md5Hash
.data
= md5HashData
;
439 if ((err
= ReadyHash(&SSLHashMD5
, &md5Context
, ctx
)) != 0)
441 if ((err
= ReadyHash(&SSLHashSHA1
, &shaContext
, ctx
)) != 0)
444 keyProgress
= key
.data
;
445 remaining
= key
.length
;
447 for (i
= 0; remaining
> 0; ++i
)
448 { for (j
= 0; j
<= i
; j
++)
449 leaderData
[j
] = 0x41 + i
; /* 'A', 'BB', 'CCC', etc. */
452 if ((err
= SSLHashSHA1
.update(&shaContext
, &leader
)) != 0)
454 if ((err
= SSLHashSHA1
.update(&shaContext
, &masterSecret
)) != 0)
456 if ((err
= SSLHashSHA1
.update(&shaContext
, &serverRandom
)) != 0)
458 if ((err
= SSLHashSHA1
.update(&shaContext
, &clientRandom
)) != 0)
460 if ((err
= SSLHashSHA1
.final(&shaContext
, &shaHash
)) != 0)
462 if ((err
= SSLHashMD5
.update(&md5Context
, &masterSecret
)) != 0)
464 if ((err
= SSLHashMD5
.update(&md5Context
, &shaHash
)) != 0)
466 if ((err
= SSLHashMD5
.final(&md5Context
, &md5Hash
)) != 0)
471 satisfied
= remaining
;
472 memcpy(keyProgress
, md5HashData
, satisfied
);
473 remaining
-= satisfied
;
474 keyProgress
+= satisfied
;
477 /* at top of loop, this was done in ReadyHash() */
478 if ((err
= SSLHashMD5
.init(&md5Context
, ctx
)) != 0)
480 if ((err
= SSLHashSHA1
.init(&shaContext
, ctx
)) != 0)
485 assert(remaining
== 0 && keyProgress
== (key
.data
+ key
.length
));
488 SSLFreeBuffer(&md5Context
, ctx
);
489 SSLFreeBuffer(&shaContext
, ctx
);
492 printf("GenerateKey: DONE\n");
497 static OSStatus
ssl3GenerateExportKeyAndIv (
498 SSLContext
*ctx
, // clientRandom, serverRandom valid
499 const SSLBuffer clientWriteKey
,
500 const SSLBuffer serverWriteKey
,
501 SSLBuffer finalClientWriteKey
, // RETURNED, mallocd by caller
502 SSLBuffer finalServerWriteKey
, // RETURNED, mallocd by caller
503 SSLBuffer finalClientIV
, // RETURNED, mallocd by caller
504 SSLBuffer finalServerIV
) // RETURNED, mallocd by caller
507 SSLBuffer hashCtx
, serverRandom
, clientRandom
;
509 /* random blobs are 32 bytes */
510 serverRandom
.data
= ctx
->serverRandom
;
511 serverRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
512 clientRandom
.data
= ctx
->clientRandom
;
513 clientRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
515 if ((err
= SSLAllocBuffer(&hashCtx
, SSLHashMD5
.contextSize
, ctx
)) != 0)
517 /* client write key */
518 if ((err
= SSLHashMD5
.init(&hashCtx
, ctx
)) != 0)
520 if ((err
= SSLHashMD5
.update(&hashCtx
, &clientWriteKey
)) != 0)
522 if ((err
= SSLHashMD5
.update(&hashCtx
, &clientRandom
)) != 0)
524 if ((err
= SSLHashMD5
.update(&hashCtx
, &serverRandom
)) != 0)
526 finalClientWriteKey
.length
= 16;
527 if ((err
= SSLHashMD5
.final(&hashCtx
, &finalClientWriteKey
)) != 0)
530 /* optional client IV */
531 if (ctx
->selectedCipherSpec
.cipher
->ivSize
> 0)
532 { if ((err
= SSLHashMD5
.init(&hashCtx
, ctx
)) != 0)
534 if ((err
= SSLHashMD5
.update(&hashCtx
, &clientRandom
)) != 0)
536 if ((err
= SSLHashMD5
.update(&hashCtx
, &serverRandom
)) != 0)
538 finalClientIV
.length
= 16;
539 if ((err
= SSLHashMD5
.final(&hashCtx
, &finalClientIV
)) != 0)
543 /* server write key */
544 if ((err
= SSLHashMD5
.init(&hashCtx
, ctx
)) != 0)
546 if ((err
= SSLHashMD5
.update(&hashCtx
, &serverWriteKey
)) != 0)
548 if ((err
= SSLHashMD5
.update(&hashCtx
, &serverRandom
)) != 0)
550 if ((err
= SSLHashMD5
.update(&hashCtx
, &clientRandom
)) != 0)
552 finalServerWriteKey
.length
= 16;
553 if ((err
= SSLHashMD5
.final(&hashCtx
, &finalServerWriteKey
)) != 0)
556 /* optional server IV */
557 if (ctx
->selectedCipherSpec
.cipher
->ivSize
> 0)
558 { if ((err
= SSLHashMD5
.init(&hashCtx
, ctx
)) != 0)
560 if ((err
= SSLHashMD5
.update(&hashCtx
, &serverRandom
)) != 0)
562 if ((err
= SSLHashMD5
.update(&hashCtx
, &clientRandom
)) != 0)
564 finalServerIV
.length
= 16;
565 if ((err
= SSLHashMD5
.final(&hashCtx
, &finalServerIV
)) != 0)
571 SSLFreeBuffer(&hashCtx
, ctx
);
576 * On entry: clientRandom, serverRandom, preMasterSecret valid
577 * On return: masterSecret valid
579 static OSStatus
ssl3GenerateMasterSecret (
583 SSLBuffer shaState
, md5State
, clientRandom
,
584 serverRandom
, shaHash
, md5Hash
, leader
;
585 UInt8
*masterProgress
, shaHashData
[20], leaderData
[3];
588 md5State
.data
= shaState
.data
= 0;
589 if ((err
= SSLAllocBuffer(&md5State
, SSLHashMD5
.contextSize
, ctx
)) != 0)
591 if ((err
= SSLAllocBuffer(&shaState
, SSLHashSHA1
.contextSize
, ctx
)) != 0)
594 clientRandom
.data
= ctx
->clientRandom
;
595 clientRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
596 serverRandom
.data
= ctx
->serverRandom
;
597 serverRandom
.length
= SSL_CLIENT_SRVR_RAND_SIZE
;
598 shaHash
.data
= shaHashData
;
601 masterProgress
= ctx
->masterSecret
;
603 for (i
= 1; i
<= 3; i
++)
604 { if ((err
= SSLHashMD5
.init(&md5State
, ctx
)) != 0)
606 if ((err
= SSLHashSHA1
.init(&shaState
, ctx
)) != 0)
609 leaderData
[0] = leaderData
[1] = leaderData
[2] = 0x40 + i
; /* 'A', 'B', etc. */
610 leader
.data
= leaderData
;
613 if ((err
= SSLHashSHA1
.update(&shaState
, &leader
)) != 0)
615 if ((err
= SSLHashSHA1
.update(&shaState
, &ctx
->preMasterSecret
)) != 0)
617 if ((err
= SSLHashSHA1
.update(&shaState
, &clientRandom
)) != 0)
619 if ((err
= SSLHashSHA1
.update(&shaState
, &serverRandom
)) != 0)
621 if ((err
= SSLHashSHA1
.final(&shaState
, &shaHash
)) != 0)
623 if ((err
= SSLHashMD5
.update(&md5State
, &ctx
->preMasterSecret
)) != 0)
625 if ((err
= SSLHashMD5
.update(&md5State
, &shaHash
)) != 0)
627 md5Hash
.data
= masterProgress
;
629 if ((err
= SSLHashMD5
.final(&md5State
, &md5Hash
)) != 0)
631 masterProgress
+= 16;
636 SSLFreeBuffer(&shaState
, ctx
);
637 SSLFreeBuffer(&md5State
, ctx
);
641 /* common routine to compute a Mac for finished message and cert verify message */
643 ssl3CalculateFinishedMessage(
645 SSLBuffer finished
, // mallocd by caller
646 SSLBuffer shaMsgState
, // running total
647 SSLBuffer md5MsgState
, // ditto
648 UInt32 senderID
) // optional, nonzero for finished message
651 SSLBuffer hash
, input
;
652 UInt8 sender
[4], md5Inner
[16], shaInner
[20];
654 // assert(finished.length == 36);
657 SSLEncodeInt(sender
, senderID
, 4);
660 if ((err
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0)
662 if ((err
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0)
665 input
.data
= ctx
->masterSecret
;
666 input
.length
= SSL_MASTER_SECRET_SIZE
;
667 if ((err
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0)
669 if ((err
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0)
671 input
.data
= (UInt8
*)SSLMACPad1
;
672 input
.length
= SSLHashMD5
.macPadSize
;
673 if ((err
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0)
675 input
.length
= SSLHashSHA1
.macPadSize
;
676 if ((err
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0)
678 hash
.data
= md5Inner
;
680 if ((err
= SSLHashMD5
.final(&md5MsgState
, &hash
)) != 0)
682 hash
.data
= shaInner
;
684 if ((err
= SSLHashSHA1
.final(&shaMsgState
, &hash
)) != 0)
686 if ((err
= SSLHashMD5
.init(&md5MsgState
, ctx
)) != 0)
688 if ((err
= SSLHashSHA1
.init(&shaMsgState
, ctx
)) != 0)
690 input
.data
= ctx
->masterSecret
;
691 input
.length
= SSL_MASTER_SECRET_SIZE
;
692 if ((err
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0)
694 if ((err
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0)
696 input
.data
= (UInt8
*)SSLMACPad2
;
697 input
.length
= SSLHashMD5
.macPadSize
;
698 if ((err
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0)
700 input
.length
= SSLHashSHA1
.macPadSize
;
701 if ((err
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0)
703 input
.data
= md5Inner
;
705 if ((err
= SSLHashMD5
.update(&md5MsgState
, &input
)) != 0)
707 hash
.data
= finished
.data
;
709 if ((err
= SSLHashMD5
.final(&md5MsgState
, &hash
)) != 0)
711 input
.data
= shaInner
;
713 if ((err
= SSLHashSHA1
.update(&shaMsgState
, &input
)) != 0)
715 hash
.data
= finished
.data
+ 16;
717 if ((err
= SSLHashSHA1
.final(&shaMsgState
, &hash
)) != 0)
725 static OSStatus
ssl3ComputeFinishedMac (
727 SSLBuffer finished
, // output - mallocd by caller
728 Boolean isServer
) // refers to message, not us
731 SSLBuffer shaMsgState
, md5MsgState
;
733 shaMsgState
.data
= 0;
734 md5MsgState
.data
= 0;
735 if ((serr
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
, ctx
)) != 0)
737 if ((serr
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
, ctx
)) != 0)
740 serr
= ssl3CalculateFinishedMessage(ctx
, finished
, shaMsgState
, md5MsgState
,
741 isServer
? SSL_Finished_Sender_Server
: SSL_Finished_Sender_Client
);
744 SSLFreeBuffer(&shaMsgState
, ctx
);
745 SSLFreeBuffer(&md5MsgState
, ctx
);
750 /* TODO: Factor this and ssl3ComputeFinishedMac to share more common code. */
751 static OSStatus
ssl3ComputeCertVfyMac (
753 SSLBuffer
*finished
, // output - mallocd by caller
754 SSL_HashAlgorithm hash
) //unused in this one
757 SSLBuffer shaMsgState
, md5MsgState
;
759 shaMsgState
.data
= 0;
760 md5MsgState
.data
= 0;
761 if ((serr
= CloneHashState(&SSLHashSHA1
, &ctx
->shaState
, &shaMsgState
, ctx
)) != 0)
763 if ((serr
= CloneHashState(&SSLHashMD5
, &ctx
->md5State
, &md5MsgState
, ctx
)) != 0)
766 assert(finished
->length
>= SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
);
767 finished
->length
= SSL_MD5_DIGEST_LEN
+ SSL_SHA1_DIGEST_LEN
;
769 serr
= ssl3CalculateFinishedMessage(ctx
, *finished
, shaMsgState
, md5MsgState
, 0);
772 SSLFreeBuffer(&shaMsgState
, ctx
);
773 SSLFreeBuffer(&md5MsgState
, ctx
);
778 const SslTlsCallouts Ssl3Callouts
= {
784 ssl3GenerateKeyMaterial
,
785 ssl3GenerateExportKeyAndIv
,
786 ssl3GenerateMasterSecret
,
787 ssl3ComputeFinishedMac
,
788 ssl3ComputeCertVfyMac