2 * Copyright (c) 2000-2001 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: Protocol engine for SSL 2
24 Written by: Doug Mitchell, based on Netscape SSLRef 3.0
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
29 /* *********************************************************************
32 SSLRef 3.0 Final -- 11/19/96
34 Copyright (c)1996 by Netscape Communications Corp.
36 By retrieving this software you are bound by the licensing terms
37 disclosed in the file "LICENSE.txt". Please read it, and if you don't
38 accept the terms, delete this software.
40 SSLRef 3.0 was developed by Netscape Communications Corp. of Mountain
41 View, California <http://home.netscape.com/> and Consensus Development
42 Corporation of Berkeley, California <http://www.consensus.com/>.
44 *********************************************************************
46 File: ssl2prot.c Protocol engine for SSL 2
48 This is the heart of the SSL 2 implementation, including the state
49 engine for proceeding through the handshake and the necessary code
50 for installing negotiated keys and algorithms.
52 ****************************************************************** */
90 #ifndef _APPLE_CDSA_H_
91 #include "appleCdsa.h"
100 static char *sslHdskMsgToStr(SSL2MessageType msg
)
102 static char badStr
[100];
106 return "ssl2_mt_error";
107 case ssl2_mt_client_hello
:
108 return "ssl2_mt_client_hello";
109 case ssl2_mt_client_master_key
:
110 return "ssl2_mt_client_master_key";
111 case ssl2_mt_client_finished
:
112 return "ssl2_mt_client_finished";
113 case ssl2_mt_server_hello
:
114 return "ssl2_mt_server_hello";
115 case ssl2_mt_server_verify
:
116 return "ssl2_mt_server_verify";
117 case ssl2_mt_server_finished
:
118 return "ssl2_mt_server_finished";
119 case ssl2_mt_request_certificate
:
120 return "ssl2_mt_request_certificate";
121 case ssl2_mt_client_certificate
:
122 return "ssl2_mt_client_certificate";
123 case ssl2_mt_kickstart_handshake
:
124 return "ssl2_mt_kickstart_handshake";
126 sprintf(badStr
, "Unknown msg (%d(d)", msg
);
131 static void logSsl2Msg(SSL2MessageType msg
, char sent
)
133 char *ms
= sslHdskMsgToStr(msg
);
134 printf("...msg %s: %s\n", (sent
? "sent" : "recd"), ms
);
137 #else /* SSL_DEBUG */
139 #define logSsl2Msg(m, s)
144 SSL2ProcessMessage(SSLRecord rec
, SSLContext
*ctx
)
149 if (rec
.contents
.length
< 2)
150 return ERR(SSLProtocolErr
);
152 msg
= (SSL2MessageType
)rec
.contents
.data
[0];
153 contents
.data
= rec
.contents
.data
+ 1;
154 contents
.length
= rec
.contents
.length
- 1;
159 { case ssl2_mt_error
:
160 err
= SSLConnectionClosedError
;
162 case ssl2_mt_client_hello
:
163 if (ctx
->state
!= HandshakeServerUninit
)
164 return ERR(SSLProtocolErr
);
165 ERR(err
= SSL2ProcessClientHello(contents
, ctx
));
166 if (err
== SSLNegotiationErr
)
167 ERR(SSL2SendError(ssl2_pe_no_cipher
, ctx
));
169 case ssl2_mt_client_master_key
:
170 if (ctx
->state
!= HandshakeSSL2ClientMasterKey
)
171 return ERR(SSLProtocolErr
);
172 ERR(err
= SSL2ProcessClientMasterKey(contents
, ctx
));
174 case ssl2_mt_client_finished
:
175 if (ctx
->state
!= HandshakeSSL2ClientFinished
)
176 return ERR(SSLProtocolErr
);
177 ERR(err
= SSL2ProcessClientFinished(contents
, ctx
));
179 case ssl2_mt_server_hello
:
180 if (ctx
->state
!= HandshakeSSL2ServerHello
&&
181 ctx
->state
!= HandshakeServerHelloUnknownVersion
)
182 return ERR(SSLProtocolErr
);
183 ERR(err
= SSL2ProcessServerHello(contents
, ctx
));
184 if (err
== SSLNegotiationErr
)
185 ERR(SSL2SendError(ssl2_pe_no_cipher
, ctx
));
187 case ssl2_mt_server_verify
:
188 if (ctx
->state
!= HandshakeSSL2ServerVerify
)
189 return ERR(SSLProtocolErr
);
190 ERR(err
= SSL2ProcessServerVerify(contents
, ctx
));
192 case ssl2_mt_server_finished
:
193 if (ctx
->state
!= HandshakeSSL2ServerFinished
) {
195 errorLog1("ssl2_mt_server_finished; state %s\n",
196 hdskStateToStr(ctx
->state
));
198 return ERR(SSLProtocolErr
);
200 ERR(err
= SSL2ProcessServerFinished(contents
, ctx
));
202 case ssl2_mt_request_certificate
:
203 /* Don't process the request; we don't support client certification */
205 case ssl2_mt_client_certificate
:
206 return ERR(SSLProtocolErr
);
209 DEBUGVAL1("Unknown message %d", msg
);
210 return ERR(SSLProtocolErr
);
215 { /* FIXME - use requested or negotiated protocol version here? */
216 if (msg
== ssl2_mt_client_hello
&& (ctx
->negProtocolVersion
>= SSL_Version_3_0
))
217 { /* Promote this message to SSL 3 protocol */
218 if (ERR(err
= SSL3ReceiveSSL2ClientHello(rec
, ctx
)) != 0)
222 ERR(err
= SSL2AdvanceHandshake(msg
, ctx
));
228 SSL2AdvanceHandshake(SSL2MessageType msg
, SSLContext
*ctx
)
234 { case ssl2_mt_kickstart_handshake
:
235 if (ctx
->negProtocolVersion
== SSL_Version_3_0_With_2_0_Hello
||
236 ctx
->negProtocolVersion
== SSL_Version_Undetermined
)
237 if (ERR(err
= SSLInitMessageHashes(ctx
)) != 0)
239 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientHello
, ctx
)) != 0)
241 switch (ctx
->negProtocolVersion
)
242 { case SSL_Version_Undetermined
:
243 SSLChangeHdskState(ctx
, HandshakeServerHelloUnknownVersion
);
245 case SSL_Version_3_0_With_2_0_Hello
:
246 assert((ctx
->reqProtocolVersion
== SSL_Version_3_0
) ||
247 (ctx
->reqProtocolVersion
== TLS_Version_1_0
));
248 ctx
->negProtocolVersion
= ctx
->reqProtocolVersion
;
250 dprintf2("===SSL client kickstart: negVersion is %d_%d\n",
251 ctx
->negProtocolVersion
>> 8, ctx
->negProtocolVersion
& 0xff);
253 SSLChangeHdskState(ctx
, HandshakeServerHello
);
255 case SSL_Version_2_0
:
256 SSLChangeHdskState(ctx
, HandshakeSSL2ServerHello
);
258 case SSL_Version_3_0_Only
:
259 case SSL_Version_3_0
:
260 case TLS_Version_1_0_Only
:
261 case TLS_Version_1_0
:
263 ASSERTMSG("Bad protocol version for sending SSL 2 Client Hello");
267 case ssl2_mt_client_hello
:
268 if (ERR(err
= SSL2CompareSessionIDs(ctx
)) != 0)
270 if (ctx
->ssl2SessionMatch
== 0)
271 if (ERR(err
= SSL2GenerateSessionID(ctx
)) != 0)
273 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerHello
, ctx
)) != 0)
275 if (ctx
->ssl2SessionMatch
== 0)
276 { SSLChangeHdskState(ctx
, HandshakeSSL2ClientMasterKey
);
279 SSLLogResumSess("===RESUMING SSL2 server-side session\n");
280 if (ERR(err
= SSL2InstallSessionKey(ctx
)) != 0)
282 /* Fall through for matching session; lame, but true */
283 case ssl2_mt_client_master_key
:
284 if (ERR(err
= SSL2InitCiphers(ctx
)) != 0)
286 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerVerify
, ctx
)) != 0)
288 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerFinished
, ctx
)) != 0)
290 SSLChangeHdskState(ctx
, HandshakeSSL2ClientFinished
);
292 case ssl2_mt_server_hello
:
293 if (ctx
->ssl2SessionMatch
== 0)
294 { if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientMasterKey
, ctx
)) != 0)
299 SSLLogResumSess("===RESUMING SSL2 client-side session\n");
300 if (ERR(err
= SSL2InstallSessionKey(ctx
)) != 0)
303 if (ERR(err
= SSL2InitCiphers(ctx
)) != 0)
305 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientFinished
, ctx
)) != 0)
307 SSLChangeHdskState(ctx
, HandshakeSSL2ServerVerify
);
309 case ssl2_mt_client_finished
:
310 /* Handshake is complete; turn ciphers on */
311 ctx
->writeCipher
.ready
= 1;
312 ctx
->readCipher
.ready
= 1;
313 /* original code never got out of ssl2_mt_client_finished state */
314 CASSERT(ctx
->protocolSide
== SSL_ServerSide
);
315 SSLChangeHdskState(ctx
, HandshakeServerReady
);
316 if (ctx
->peerID
.data
!= 0)
317 ERR(SSLAddSessionData(ctx
));
319 case ssl2_mt_server_verify
:
320 SSLChangeHdskState(ctx
, HandshakeSSL2ServerFinished
);
322 case ssl2_mt_request_certificate
:
323 if (ERR(err
= SSL2SendError(ssl2_pe_no_certificate
, ctx
)) != 0)
326 case ssl2_mt_server_finished
:
327 /* Handshake is complete; turn ciphers on */
328 ctx
->writeCipher
.ready
= 1;
329 ctx
->readCipher
.ready
= 1;
330 /* original code never got out of ssl2_mt_server_finished state */
331 CASSERT(ctx
->protocolSide
== SSL_ClientSide
);
332 SSLChangeHdskState(ctx
, HandshakeClientReady
);
333 if (ctx
->peerID
.data
!= 0)
334 ERR(SSLAddSessionData(ctx
));
337 case ssl2_mt_client_certificate
:
338 return ERR(SSLProtocolErr
);
346 SSL2PrepareAndQueueMessage(EncodeSSL2MessageFunc encodeFunc
, SSLContext
*ctx
)
350 rec
.contentType
= SSL_version_2_0_record
;
351 rec
.protocolVersion
= SSL_Version_2_0
;
352 if (ERR(err
= encodeFunc(&rec
.contents
, ctx
)) != 0)
355 logSsl2Msg((SSL2MessageType
)rec
.contents
.data
[0], 1);
357 assert(ctx
->sslTslCalls
!= NULL
);
358 if (ERR(err
= ctx
->sslTslCalls
->writeRecord(rec
, ctx
)) != 0)
359 { ERR(SSLFreeBuffer(&rec
.contents
, &ctx
->sysCtx
));
363 if (ctx
->negProtocolVersion
== SSL_Version_3_0_With_2_0_Hello
||
364 ctx
->negProtocolVersion
== SSL_Version_Undetermined
)
365 if (ERR(err
= SSLHashSHA1
.update(ctx
->shaState
, rec
.contents
)) != 0 ||
366 ERR(err
= SSLHashMD5
.update(ctx
->md5State
, rec
.contents
)) != 0)
369 ERR(err
= SSLFreeBuffer(&rec
.contents
, &ctx
->sysCtx
));
374 SSL2CompareSessionIDs(SSLContext
*ctx
)
376 SSLBuffer sessionIdentifier
;
378 ctx
->ssl2SessionMatch
= 0;
380 if (ctx
->resumableSession
.data
== 0)
383 if (ERR(err
= SSLRetrieveSessionID(ctx
->resumableSession
,
384 &sessionIdentifier
, ctx
)) != 0)
387 if (sessionIdentifier
.length
== ctx
->sessionID
.length
&&
388 memcmp(sessionIdentifier
.data
, ctx
->sessionID
.data
, sessionIdentifier
.length
) == 0)
389 ctx
->ssl2SessionMatch
= 1;
391 if (ERR(err
= SSLFreeBuffer(&sessionIdentifier
, &ctx
->sysCtx
)) != 0)
398 SSL2InstallSessionKey(SSLContext
*ctx
)
401 CASSERT(ctx
->ssl2SessionMatch
!= 0);
402 CASSERT(ctx
->resumableSession
.data
!= 0);
403 if (ERR(err
= SSLInstallSessionFromData(ctx
->resumableSession
, ctx
)) != 0)
409 SSL2GenerateSessionID(SSLContext
*ctx
)
412 if (ERR(err
= SSLFreeBuffer(&ctx
->sessionID
, &ctx
->sysCtx
)) != 0)
414 if (ERR(err
= SSLAllocBuffer(&ctx
->sessionID
, SSL_SESSION_ID_LEN
, &ctx
->sysCtx
)) != 0)
416 if ((err
= sslRand(ctx
, &ctx
->sessionID
)) != 0)
422 SSL2InitCiphers(SSLContext
*ctx
)
426 uint8 variantChar
, *progress
, *readKey
, *writeKey
, *iv
;
427 SSLBuffer hashDigest
, hashContext
, masterKey
, challenge
, connectionID
, variantData
;
429 keyMaterialLen
= 2 * ctx
->selectedCipherSpec
->cipher
->keySize
;
430 if (ERR(err
= SSLAllocBuffer(&keyData
, keyMaterialLen
, &ctx
->sysCtx
)) != 0)
433 /* Can't have % in assertion string... */
436 UInt32 keyModDigestSize
= keyMaterialLen
% SSLHashMD5
.digestSize
;
437 CASSERT(keyModDigestSize
== 0);
441 masterKey
.data
= ctx
->masterSecret
;
442 masterKey
.length
= ctx
->selectedCipherSpec
->cipher
->keySize
;
443 challenge
.data
= ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
444 ctx
->ssl2ChallengeLength
;
445 challenge
.length
= ctx
->ssl2ChallengeLength
;
446 connectionID
.data
= ctx
->serverRandom
;
447 connectionID
.length
= ctx
->ssl2ConnectionIDLength
;
448 variantData
.data
= &variantChar
;
449 variantData
.length
= 1;
450 if (ERR(err
= SSLAllocBuffer(&hashContext
, SSLHashMD5
.contextSize
, &ctx
->sysCtx
)) != 0)
451 { ERR(SSLFreeBuffer(&keyData
, &ctx
->sysCtx
));
455 variantChar
= 0x30; /* '0' */
456 progress
= keyData
.data
;
457 while (keyMaterialLen
)
458 { hashDigest
.data
= progress
;
459 hashDigest
.length
= SSLHashMD5
.digestSize
;
460 if (ERR(err
= SSLHashMD5
.init(hashContext
, ctx
)) != 0 ||
461 ERR(err
= SSLHashMD5
.update(hashContext
, masterKey
)) != 0 ||
462 ERR(err
= SSLHashMD5
.update(hashContext
, variantData
)) != 0 ||
463 ERR(err
= SSLHashMD5
.update(hashContext
, challenge
)) != 0 ||
464 ERR(err
= SSLHashMD5
.update(hashContext
, connectionID
)) != 0 ||
465 ERR(err
= SSLHashMD5
.final(hashContext
, hashDigest
)) != 0)
466 { SSLFreeBuffer(&keyData
, &ctx
->sysCtx
);
467 SSLFreeBuffer(&hashContext
, &ctx
->sysCtx
);
470 progress
+= hashDigest
.length
;
472 keyMaterialLen
-= hashDigest
.length
;
475 CASSERT(progress
== keyData
.data
+ keyData
.length
);
477 if (ERR(err
= SSLFreeBuffer(&hashContext
, &ctx
->sysCtx
)) != 0)
478 { ERR(SSLFreeBuffer(&keyData
, &ctx
->sysCtx
));
482 ctx
->readPending
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
483 ctx
->writePending
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
484 ctx
->readPending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
485 ctx
->writePending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
486 ctx
->readPending
.sequenceNum
= ctx
->readCipher
.sequenceNum
;
487 ctx
->writePending
.sequenceNum
= ctx
->writeCipher
.sequenceNum
;
489 if (ctx
->protocolSide
== SSL_ServerSide
)
490 { writeKey
= keyData
.data
;
491 readKey
= keyData
.data
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
494 { readKey
= keyData
.data
;
495 writeKey
= keyData
.data
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
498 iv
= ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
500 /* APPLE_CDSA symmetric cipher changes....*/
501 if (ERR(err
= ctx
->readPending
.symCipher
->initialize(readKey
, iv
,
502 &ctx
->readPending
, ctx
)) != 0 ||
503 ERR(err
= ctx
->writePending
.symCipher
->initialize(writeKey
, iv
,
504 &ctx
->writePending
, ctx
)) != 0)
505 { ERR(SSLFreeBuffer(&keyData
, &ctx
->sysCtx
));
510 * HEY! macSecret is only 20 bytes. This blows up when key size
511 * is greater than 20, e.g., 3DES.
512 * I'll increase the size of macSecret to 24, 'cause it appears
513 * from the SSL v23 spec that the macSecret really the same size as
514 * CLIENT-WRITE-KEY and SERVER-READ-KEY (see 1.2 of the spec).
516 memcpy(ctx
->readPending
.macSecret
, readKey
, ctx
->selectedCipherSpec
->cipher
->keySize
);
517 memcpy(ctx
->writePending
.macSecret
, writeKey
, ctx
->selectedCipherSpec
->cipher
->keySize
);
519 if (ERR(err
= SSLFreeBuffer(&keyData
, &ctx
->sysCtx
)) != 0)
522 ctx
->readCipher
= ctx
->readPending
;
523 ctx
->writeCipher
= ctx
->writePending
;
524 memset(&ctx
->readPending
, 0, sizeof(CipherContext
)); /* Zero out old data */
525 memset(&ctx
->writePending
, 0, sizeof(CipherContext
)); /* Zero out old data */