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"
98 static char *sslHdskMsgToStr(SSL2MessageType msg
)
100 static char badStr
[100];
104 return "ssl2_mt_error";
105 case ssl2_mt_client_hello
:
106 return "ssl2_mt_client_hello";
107 case ssl2_mt_client_master_key
:
108 return "ssl2_mt_client_master_key";
109 case ssl2_mt_client_finished
:
110 return "ssl2_mt_client_finished";
111 case ssl2_mt_server_hello
:
112 return "ssl2_mt_server_hello";
113 case ssl2_mt_server_verify
:
114 return "ssl2_mt_server_verify";
115 case ssl2_mt_server_finished
:
116 return "ssl2_mt_server_finished";
117 case ssl2_mt_request_certificate
:
118 return "ssl2_mt_request_certificate";
119 case ssl2_mt_client_certificate
:
120 return "ssl2_mt_client_certificate";
121 case ssl2_mt_kickstart_handshake
:
122 return "ssl2_mt_kickstart_handshake";
124 sprintf(badStr
, "Unknown msg (%d(d)", msg
);
129 static void logSsl2Msg(SSL2MessageType msg
, char sent
)
131 char *ms
= sslHdskMsgToStr(msg
);
132 printf("...msg %s: %s\n", (sent
? "sent" : "recd"), ms
);
135 #else /* SSL_DEBUG */
137 #define logSsl2Msg(m, s)
142 SSL2ProcessMessage(SSLRecord rec
, SSLContext
*ctx
)
147 if (rec
.contents
.length
< 2)
148 return ERR(SSLProtocolErr
);
150 msg
= (SSL2MessageType
)rec
.contents
.data
[0];
151 contents
.data
= rec
.contents
.data
+ 1;
152 contents
.length
= rec
.contents
.length
- 1;
157 { case ssl2_mt_error
:
159 /* ref code returned an unitialized local err here */
160 err
= SSLConnectionClosedError
;
163 case ssl2_mt_client_hello
:
164 if (ctx
->state
!= HandshakeServerUninit
)
165 return ERR(SSLProtocolErr
);
166 ERR(err
= SSL2ProcessClientHello(contents
, ctx
));
167 if (err
== SSLNegotiationErr
)
168 ERR(SSL2SendError(ssl2_pe_no_cipher
, ctx
));
170 case ssl2_mt_client_master_key
:
171 if (ctx
->state
!= HandshakeSSL2ClientMasterKey
)
172 return ERR(SSLProtocolErr
);
173 ERR(err
= SSL2ProcessClientMasterKey(contents
, ctx
));
175 case ssl2_mt_client_finished
:
176 if (ctx
->state
!= HandshakeSSL2ClientFinished
)
177 return ERR(SSLProtocolErr
);
178 ERR(err
= SSL2ProcessClientFinished(contents
, ctx
));
180 case ssl2_mt_server_hello
:
181 if (ctx
->state
!= HandshakeSSL2ServerHello
&&
182 ctx
->state
!= HandshakeServerHelloUnknownVersion
)
183 return ERR(SSLProtocolErr
);
184 ERR(err
= SSL2ProcessServerHello(contents
, ctx
));
185 if (err
== SSLNegotiationErr
)
186 ERR(SSL2SendError(ssl2_pe_no_cipher
, ctx
));
188 case ssl2_mt_server_verify
:
189 if (ctx
->state
!= HandshakeSSL2ServerVerify
)
190 return ERR(SSLProtocolErr
);
191 ERR(err
= SSL2ProcessServerVerify(contents
, ctx
));
193 case ssl2_mt_server_finished
:
194 if (ctx
->state
!= HandshakeSSL2ServerFinished
) {
196 errorLog1("ssl2_mt_server_finished; state %s\n",
197 hdskStateToStr(ctx
->state
));
199 return ERR(SSLProtocolErr
);
201 ERR(err
= SSL2ProcessServerFinished(contents
, ctx
));
203 case ssl2_mt_request_certificate
:
204 /* Don't process the request; we don't support client certification */
206 case ssl2_mt_client_certificate
:
207 return ERR(SSLProtocolErr
);
210 DEBUGVAL1("Unknown message %d", msg
);
211 return ERR(SSLProtocolErr
);
216 { /* FIXME - use requested or negotiated protocol version here? */
217 if (msg
== ssl2_mt_client_hello
&& ctx
->negProtocolVersion
== SSL_Version_3_0
)
218 { /* Promote this message to SSL 3 protocol */
219 if (ERR(err
= SSL3ReceiveSSL2ClientHello(rec
, ctx
)) != 0)
223 ERR(err
= SSL2AdvanceHandshake(msg
, ctx
));
229 SSL2AdvanceHandshake(SSL2MessageType msg
, SSLContext
*ctx
)
235 { case ssl2_mt_kickstart_handshake
:
236 if (ctx
->negProtocolVersion
== SSL_Version_3_0_With_2_0_Hello
||
237 ctx
->negProtocolVersion
== SSL_Version_Undetermined
)
238 if (ERR(err
= SSLInitMessageHashes(ctx
)) != 0)
240 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientHello
, ctx
)) != 0)
242 switch (ctx
->negProtocolVersion
)
243 { case SSL_Version_Undetermined
:
244 SSLChangeHdskState(ctx
, HandshakeServerHelloUnknownVersion
);
246 case SSL_Version_3_0_With_2_0_Hello
:
247 ctx
->negProtocolVersion
= SSL_Version_3_0
;
249 dprintf0("===SSL client kickstart: negVersion is 3_0\n");
251 SSLChangeHdskState(ctx
, HandshakeServerHello
);
253 case SSL_Version_2_0
:
254 SSLChangeHdskState(ctx
, HandshakeSSL2ServerHello
);
256 case SSL_Version_3_0_Only
:
257 case SSL_Version_3_0
:
259 ASSERTMSG("Bad protocol version for sending SSL 2 Client Hello");
263 case ssl2_mt_client_hello
:
264 if (ERR(err
= SSL2CompareSessionIDs(ctx
)) != 0)
266 if (ctx
->ssl2SessionMatch
== 0)
267 if (ERR(err
= SSL2GenerateSessionID(ctx
)) != 0)
269 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerHello
, ctx
)) != 0)
271 if (ctx
->ssl2SessionMatch
== 0)
272 { SSLChangeHdskState(ctx
, HandshakeSSL2ClientMasterKey
);
275 if (ERR(err
= SSL2InstallSessionKey(ctx
)) != 0)
277 /* Fall through for matching session; lame, but true */
278 case ssl2_mt_client_master_key
:
279 if (ERR(err
= SSL2InitCiphers(ctx
)) != 0)
281 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerVerify
, ctx
)) != 0)
283 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerFinished
, ctx
)) != 0)
285 SSLChangeHdskState(ctx
, HandshakeSSL2ClientFinished
);
287 case ssl2_mt_server_hello
:
288 if (ctx
->ssl2SessionMatch
== 0)
289 { if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientMasterKey
, ctx
)) != 0)
293 { if (ERR(err
= SSL2InstallSessionKey(ctx
)) != 0)
296 if (ERR(err
= SSL2InitCiphers(ctx
)) != 0)
298 if (ERR(err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientFinished
, ctx
)) != 0)
300 SSLChangeHdskState(ctx
, HandshakeSSL2ServerVerify
);
302 case ssl2_mt_client_finished
:
303 /* Handshake is complete; turn ciphers on */
304 ctx
->writeCipher
.ready
= 1;
305 ctx
->readCipher
.ready
= 1;
307 /* original code never got out of ssl2_mt_client_finished state */
308 CASSERT(ctx
->protocolSide
== SSL_ServerSide
);
309 SSLChangeHdskState(ctx
, HandshakeServerReady
);
310 #endif /* _APPLE_CDSA_ */
311 if (ctx
->peerID
.data
!= 0)
312 ERR(SSLAddSessionID(ctx
));
314 case ssl2_mt_server_verify
:
315 SSLChangeHdskState(ctx
, HandshakeSSL2ServerFinished
);
317 case ssl2_mt_request_certificate
:
318 if (ERR(err
= SSL2SendError(ssl2_pe_no_certificate
, ctx
)) != 0)
321 case ssl2_mt_server_finished
:
322 /* Handshake is complete; turn ciphers on */
323 ctx
->writeCipher
.ready
= 1;
324 ctx
->readCipher
.ready
= 1;
326 /* original code never got out of ssl2_mt_server_finished state */
327 CASSERT(ctx
->protocolSide
== SSL_ClientSide
);
328 SSLChangeHdskState(ctx
, HandshakeClientReady
);
329 #endif /* _APPLE_CDSA_ */
330 if (ctx
->peerID
.data
!= 0)
331 ERR(SSLAddSessionID(ctx
));
334 case ssl2_mt_client_certificate
:
335 return ERR(SSLProtocolErr
);
343 SSL2PrepareAndQueueMessage(EncodeSSL2MessageFunc encodeFunc
, SSLContext
*ctx
)
347 rec
.contentType
= SSL_version_2_0_record
;
348 rec
.protocolVersion
= SSL_Version_2_0
;
349 if (ERR(err
= encodeFunc(&rec
.contents
, ctx
)) != 0)
352 logSsl2Msg((SSL2MessageType
)rec
.contents
.data
[0], 1);
354 if (ERR(err
= SSLWriteRecord(rec
, ctx
)) != 0)
355 { ERR(SSLFreeBuffer(&rec
.contents
, &ctx
->sysCtx
));
359 if (ctx
->negProtocolVersion
== SSL_Version_3_0_With_2_0_Hello
||
360 ctx
->negProtocolVersion
== SSL_Version_Undetermined
)
361 if (ERR(err
= SSLHashSHA1
.update(ctx
->shaState
, rec
.contents
)) != 0 ||
362 ERR(err
= SSLHashMD5
.update(ctx
->md5State
, rec
.contents
)) != 0)
365 ERR(err
= SSLFreeBuffer(&rec
.contents
, &ctx
->sysCtx
));
370 SSL2CompareSessionIDs(SSLContext
*ctx
)
372 SSLBuffer sessionIdentifier
;
374 ctx
->ssl2SessionMatch
= 0;
376 if (ctx
->resumableSession
.data
== 0)
379 if (ERR(err
= SSLRetrieveSessionIDIdentifier(ctx
->resumableSession
,
380 &sessionIdentifier
, ctx
)) != 0)
383 if (sessionIdentifier
.length
== ctx
->sessionID
.length
&&
384 memcmp(sessionIdentifier
.data
, ctx
->sessionID
.data
, sessionIdentifier
.length
) == 0)
385 ctx
->ssl2SessionMatch
= 1;
387 if (ERR(err
= SSLFreeBuffer(&sessionIdentifier
, &ctx
->sysCtx
)) != 0)
394 SSL2InstallSessionKey(SSLContext
*ctx
)
397 CASSERT(ctx
->ssl2SessionMatch
!= 0);
398 CASSERT(ctx
->resumableSession
.data
!= 0);
399 if (ERR(err
= SSLInstallSessionID(ctx
->resumableSession
, ctx
)) != 0)
405 SSL2GenerateSessionID(SSLContext
*ctx
)
408 if (ERR(err
= SSLFreeBuffer(&ctx
->sessionID
, &ctx
->sysCtx
)) != 0)
410 if (ERR(err
= SSLAllocBuffer(&ctx
->sessionID
, SSL_SESSION_ID_LEN
, &ctx
->sysCtx
)) != 0)
413 if ((err
= sslRand(ctx
, &ctx
->sessionID
)) != 0)
415 if (ERR(err
= ctx
->sysCtx
.random(ctx
->sessionID
, ctx
->sysCtx
.randomRef
)) != 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
+ 32 - ctx
->ssl2ChallengeLength
;
444 challenge
.length
= ctx
->ssl2ChallengeLength
;
445 connectionID
.data
= ctx
->serverRandom
;
446 connectionID
.length
= ctx
->ssl2ConnectionIDLength
;
447 variantData
.data
= &variantChar
;
448 variantData
.length
= 1;
449 if (ERR(err
= SSLAllocBuffer(&hashContext
, SSLHashMD5
.contextSize
, &ctx
->sysCtx
)) != 0)
450 { ERR(SSLFreeBuffer(&keyData
, &ctx
->sysCtx
));
454 variantChar
= 0x30; /* '0' */
455 progress
= keyData
.data
;
456 while (keyMaterialLen
)
457 { hashDigest
.data
= progress
;
458 hashDigest
.length
= SSLHashMD5
.digestSize
;
459 if (ERR(err
= SSLHashMD5
.init(hashContext
)) != 0 ||
460 ERR(err
= SSLHashMD5
.update(hashContext
, masterKey
)) != 0 ||
461 ERR(err
= SSLHashMD5
.update(hashContext
, variantData
)) != 0 ||
462 ERR(err
= SSLHashMD5
.update(hashContext
, challenge
)) != 0 ||
463 ERR(err
= SSLHashMD5
.update(hashContext
, connectionID
)) != 0 ||
464 ERR(err
= SSLHashMD5
.final(hashContext
, hashDigest
)) != 0)
465 { SSLFreeBuffer(&keyData
, &ctx
->sysCtx
);
466 SSLFreeBuffer(&hashContext
, &ctx
->sysCtx
);
469 progress
+= hashDigest
.length
;
471 keyMaterialLen
-= hashDigest
.length
;
474 CASSERT(progress
== keyData
.data
+ keyData
.length
);
476 if (ERR(err
= SSLFreeBuffer(&hashContext
, &ctx
->sysCtx
)) != 0)
477 { ERR(SSLFreeBuffer(&keyData
, &ctx
->sysCtx
));
481 ctx
->readPending
.hash
= ctx
->selectedCipherSpec
->macAlgorithm
;
482 ctx
->writePending
.hash
= ctx
->selectedCipherSpec
->macAlgorithm
;
483 ctx
->readPending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
484 ctx
->writePending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
485 ctx
->readPending
.sequenceNum
= ctx
->readCipher
.sequenceNum
;
486 ctx
->writePending
.sequenceNum
= ctx
->writeCipher
.sequenceNum
;
488 if (ctx
->protocolSide
== SSL_ServerSide
)
489 { writeKey
= keyData
.data
;
490 readKey
= keyData
.data
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
493 { readKey
= keyData
.data
;
494 writeKey
= keyData
.data
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
497 iv
= ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
499 /* APPLE_CDSA symmetric cipher changes....*/
500 if (ERR(err
= ctx
->readPending
.symCipher
->initialize(readKey
, iv
,
501 &ctx
->readPending
, ctx
)) != 0 ||
502 ERR(err
= ctx
->writePending
.symCipher
->initialize(writeKey
, iv
,
503 &ctx
->writePending
, ctx
)) != 0)
504 { ERR(SSLFreeBuffer(&keyData
, &ctx
->sysCtx
));
509 * HEY! macSecret is only 20 bytes. This blows up when key size
510 * is greater than 20, e.g., 3DES.
511 * I'll increase the size of macSecret to 24, 'cause it appears
512 * from the SSL v23 spec that the macSecret really the same size as
513 * CLIENT-WRITE-KEY and SERVER-READ-KEY (see 1.2 of the spec).
515 memcpy(ctx
->readPending
.macSecret
, readKey
, ctx
->selectedCipherSpec
->cipher
->keySize
);
516 memcpy(ctx
->writePending
.macSecret
, writeKey
, ctx
->selectedCipherSpec
->cipher
->keySize
);
518 if (ERR(err
= SSLFreeBuffer(&keyData
, &ctx
->sysCtx
)) != 0)
521 ctx
->readCipher
= ctx
->readPending
;
522 ctx
->writeCipher
= ctx
->writePending
;
523 memset(&ctx
->readPending
, 0, sizeof(CipherContext
)); /* Zero out old data */
524 memset(&ctx
->writePending
, 0, sizeof(CipherContext
)); /* Zero out old data */