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.
20 File: ssl2Protocol.cpp
22 Contains: Protocol engine for SSL 2
24 Written by: Doug Mitchell
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
32 #include "sslRecord.h"
33 #include "sslMemory.h"
34 #include "sslContext.h"
35 #include "sslHandshake.h"
36 #include "sslSession.h"
37 #include "sslAlertMessage.h"
39 #include "appleCdsa.h"
41 #include "sslDigests.h"
47 static char *sslHdskMsgToStr(SSL2MessageType msg
)
49 static char badStr
[100];
53 return "SSL2_MsgError";
54 case SSL2_MsgClientHello
:
55 return "SSL2_MsgClientHello";
56 case SSL2_MsgClientMasterKey
:
57 return "SSL2_MsgClientMasterKey";
58 case SSL2_MsgClientFinished
:
59 return "SSL2_MsgClientFinished";
60 case SSL2_MsgServerHello
:
61 return "SSL2_MsgServerHello";
62 case SSL2_MsgServerVerify
:
63 return "SSL2_MsgServerVerify";
64 case SSL2_MsgServerFinished
:
65 return "SSL2_MsgServerFinished";
66 case SSL2_MsgRequestCert
:
67 return "SSL2_MsgRequestCert";
68 case SSL2_MsgClientCert
:
69 return "SSL2_MsgClientCert";
70 case SSL2_MsgKickstart
:
71 return "SSL2_MsgKickstart";
73 sprintf(badStr
, "Unknown msg (%d(d)", msg
);
78 static void logSsl2Msg(SSL2MessageType msg
, char sent
)
80 char *ms
= sslHdskMsgToStr(msg
);
81 sslHdskMsgDebug("...msg %s: %s", (sent
? "sent" : "recd"), ms
);
86 #define logSsl2Msg(m, s)
91 SSL2ProcessMessage(SSLRecord
&rec
, SSLContext
*ctx
)
96 if (rec
.contents
.length
< 2)
97 return errSSLProtocol
;
99 msg
= (SSL2MessageType
)rec
.contents
.data
[0];
100 contents
.data
= rec
.contents
.data
+ 1;
101 contents
.length
= rec
.contents
.length
- 1;
106 { case SSL2_MsgError
:
107 err
= errSSLClosedAbort
;
109 case SSL2_MsgClientHello
:
110 if (ctx
->state
!= SSL_HdskStateServerUninit
)
111 return errSSLProtocol
;
112 err
= SSL2ProcessClientHello(contents
, ctx
);
113 if (err
== errSSLNegotiation
)
114 SSL2SendError(SSL2_ErrNoCipher
, ctx
);
116 case SSL2_MsgClientMasterKey
:
117 if (ctx
->state
!= SSL2_HdskStateClientMasterKey
)
118 return errSSLProtocol
;
119 err
= SSL2ProcessClientMasterKey(contents
, ctx
);
121 case SSL2_MsgClientFinished
:
122 if (ctx
->state
!= SSL2_HdskStateClientFinished
)
123 return errSSLProtocol
;
124 err
= SSL2ProcessClientFinished(contents
, ctx
);
126 case SSL2_MsgServerHello
:
127 if (ctx
->state
!= SSL2_HdskStateServerHello
&&
128 ctx
->state
!= SSL_HdskStateServerHelloUnknownVersion
)
129 return errSSLProtocol
;
130 err
= SSL2ProcessServerHello(contents
, ctx
);
131 if (err
== errSSLNegotiation
)
132 SSL2SendError(SSL2_ErrNoCipher
, ctx
);
134 case SSL2_MsgServerVerify
:
135 if (ctx
->state
!= SSL2_HdskStateServerVerify
)
136 return errSSLProtocol
;
137 err
= SSL2ProcessServerVerify(contents
, ctx
);
139 case SSL2_MsgServerFinished
:
140 if (ctx
->state
!= SSL2_HdskStateServerFinished
) {
141 /* FIXME - this ifndef should not be necessary */
143 sslHdskStateDebug("SSL2_MsgServerFinished; state %s",
144 hdskStateToStr(ctx
->state
));
146 return errSSLProtocol
;
148 err
= SSL2ProcessServerFinished(contents
, ctx
);
150 case SSL2_MsgRequestCert
:
151 /* Don't process the request; we don't support client certification */
153 case SSL2_MsgClientCert
:
154 return errSSLProtocol
;
157 return errSSLProtocol
;
163 /* FIXME - use requested or negotiated protocol version here? */
164 if ((msg
== SSL2_MsgClientHello
) &&
165 (ctx
->negProtocolVersion
>= SSL_Version_3_0
))
166 { /* Promote this message to SSL 3 protocol */
167 if ((err
= SSL3ReceiveSSL2ClientHello(rec
, ctx
)) != 0)
171 err
= SSL2AdvanceHandshake(msg
, ctx
);
177 SSL2AdvanceHandshake(SSL2MessageType msg
, SSLContext
*ctx
)
183 { case SSL2_MsgKickstart
:
184 if (ctx
->negProtocolVersion
== SSL_Version_3_0_With_2_0_Hello
||
185 ctx
->negProtocolVersion
== SSL_Version_Undetermined
)
186 if ((err
= SSLInitMessageHashes(ctx
)) != 0)
188 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientHello
, ctx
)) != 0)
190 switch (ctx
->negProtocolVersion
)
191 { case SSL_Version_Undetermined
:
192 SSLChangeHdskState(ctx
, SSL_HdskStateServerHelloUnknownVersion
);
194 case SSL_Version_3_0_With_2_0_Hello
:
195 assert((ctx
->reqProtocolVersion
== SSL_Version_3_0
) ||
196 (ctx
->reqProtocolVersion
== TLS_Version_1_0
));
197 ctx
->negProtocolVersion
= ctx
->reqProtocolVersion
;
198 sslLogNegotiateDebug("===SSL client kickstart: negVersion "
200 ctx
->negProtocolVersion
>> 8, ctx
->negProtocolVersion
& 0xff);
201 SSLChangeHdskState(ctx
, SSL_HdskStateServerHello
);
203 case SSL_Version_2_0
:
204 SSLChangeHdskState(ctx
, SSL2_HdskStateServerHello
);
206 case SSL_Version_3_0_Only
:
207 case SSL_Version_3_0
:
208 case TLS_Version_1_0_Only
:
209 case TLS_Version_1_0
:
211 assert("Bad protocol version for sending SSL 2 Client Hello");
215 case SSL2_MsgClientHello
:
216 if ((err
= SSL2CompareSessionIDs(ctx
)) != 0)
218 if (ctx
->ssl2SessionMatch
== 0)
219 if ((err
= SSL2GenerateSessionID(ctx
)) != 0)
221 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerHello
, ctx
)) != 0)
223 if (ctx
->ssl2SessionMatch
== 0)
224 { SSLChangeHdskState(ctx
, SSL2_HdskStateClientMasterKey
);
227 sslLogResumSessDebug("===RESUMING SSL2 server-side session");
228 if ((err
= SSL2InstallSessionKey(ctx
)) != 0)
230 /* Fall through for matching session; lame, but true */
231 case SSL2_MsgClientMasterKey
:
232 if ((err
= SSL2InitCiphers(ctx
)) != 0)
234 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerVerify
, ctx
)) != 0)
236 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerFinished
, ctx
)) != 0)
238 SSLChangeHdskState(ctx
, SSL2_HdskStateClientFinished
);
240 case SSL2_MsgServerHello
:
241 if (ctx
->ssl2SessionMatch
== 0)
242 { if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientMasterKey
, ctx
)) != 0)
247 sslLogResumSessDebug("===RESUMING SSL2 client-side session");
248 if ((err
= SSL2InstallSessionKey(ctx
)) != 0)
251 if ((err
= SSL2InitCiphers(ctx
)) != 0)
253 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientFinished
, ctx
)) != 0)
255 SSLChangeHdskState(ctx
, SSL2_HdskStateServerVerify
);
257 case SSL2_MsgClientFinished
:
258 /* Handshake is complete; turn ciphers on */
259 ctx
->writeCipher
.ready
= 1;
260 ctx
->readCipher
.ready
= 1;
261 /* original code never got out of SSL2_MsgClientFinished state */
262 assert(ctx
->protocolSide
== SSL_ServerSide
);
263 SSLChangeHdskState(ctx
, SSL2_HdskStateServerReady
);
264 if (ctx
->peerID
.data
!= 0)
265 SSLAddSessionData(ctx
);
267 case SSL2_MsgServerVerify
:
268 SSLChangeHdskState(ctx
, SSL2_HdskStateServerFinished
);
270 case SSL2_MsgRequestCert
:
271 if ((err
= SSL2SendError(SSL2_ErrNoCert
, ctx
)) != 0)
274 case SSL2_MsgServerFinished
:
275 /* Handshake is complete; turn ciphers on */
276 ctx
->writeCipher
.ready
= 1;
277 ctx
->readCipher
.ready
= 1;
278 /* original code never got out of SSL2_MsgServerFinished state */
279 assert(ctx
->protocolSide
== SSL_ClientSide
);
280 SSLChangeHdskState(ctx
, SSL2_HdskStateClientReady
);
281 if (ctx
->peerID
.data
!= 0)
282 SSLAddSessionData(ctx
);
285 case SSL2_MsgClientCert
:
286 return errSSLProtocol
;
294 SSL2PrepareAndQueueMessage(EncodeSSL2MessageFunc encodeFunc
, SSLContext
*ctx
)
298 rec
.contentType
= SSL_RecordTypeV2_0
;
299 rec
.protocolVersion
= SSL_Version_2_0
;
300 if ((err
= encodeFunc(rec
.contents
, ctx
)) != 0)
303 logSsl2Msg((SSL2MessageType
)rec
.contents
.data
[0], 1);
305 assert(ctx
->sslTslCalls
!= NULL
);
306 if ((err
= ctx
->sslTslCalls
->writeRecord(rec
, ctx
)) != 0)
307 { SSLFreeBuffer(rec
.contents
, ctx
);
311 if (ctx
->negProtocolVersion
== SSL_Version_3_0_With_2_0_Hello
||
312 ctx
->negProtocolVersion
== SSL_Version_Undetermined
)
313 if ((err
= SSLHashSHA1
.update(ctx
->shaState
, rec
.contents
)) != 0 ||
314 (err
= SSLHashMD5
.update(ctx
->md5State
, rec
.contents
)) != 0)
317 err
= SSLFreeBuffer(rec
.contents
, ctx
);
322 SSL2CompareSessionIDs(SSLContext
*ctx
)
324 SSLBuffer sessionIdentifier
;
326 ctx
->ssl2SessionMatch
= 0;
328 if (ctx
->resumableSession
.data
== 0)
331 if ((err
= SSLRetrieveSessionID(ctx
->resumableSession
,
332 &sessionIdentifier
, ctx
)) != 0)
335 if (sessionIdentifier
.length
== ctx
->sessionID
.length
&&
336 memcmp(sessionIdentifier
.data
, ctx
->sessionID
.data
, sessionIdentifier
.length
) == 0)
337 ctx
->ssl2SessionMatch
= 1;
339 if ((err
= SSLFreeBuffer(sessionIdentifier
, ctx
)) != 0)
346 SSL2InstallSessionKey(SSLContext
*ctx
)
349 assert(ctx
->ssl2SessionMatch
!= 0);
350 assert(ctx
->resumableSession
.data
!= 0);
351 if ((err
= SSLInstallSessionFromData(ctx
->resumableSession
, ctx
)) != 0)
357 SSL2GenerateSessionID(SSLContext
*ctx
)
360 if ((err
= SSLFreeBuffer(ctx
->sessionID
, ctx
)) != 0)
362 if ((err
= SSLAllocBuffer(ctx
->sessionID
, SSL_SESSION_ID_LEN
, ctx
)) != 0)
364 if ((err
= sslRand(ctx
, &ctx
->sessionID
)) != 0)
370 SSL2InitCiphers(SSLContext
*ctx
)
374 uint8 variantChar
, *charPtr
, *readKey
, *writeKey
, *iv
;
375 SSLBuffer hashDigest
, hashContext
, masterKey
, challenge
, connectionID
, variantData
;
377 keyMaterialLen
= 2 * ctx
->selectedCipherSpec
->cipher
->keySize
;
378 if ((err
= SSLAllocBuffer(keyData
, keyMaterialLen
, ctx
)) != 0)
381 /* Can't have % in assertion string... */
384 UInt32 keyModDigestSize
= keyMaterialLen
% SSLHashMD5
.digestSize
;
385 assert(keyModDigestSize
== 0);
389 masterKey
.data
= ctx
->masterSecret
;
390 masterKey
.length
= ctx
->selectedCipherSpec
->cipher
->keySize
;
391 challenge
.data
= ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
392 ctx
->ssl2ChallengeLength
;
393 challenge
.length
= ctx
->ssl2ChallengeLength
;
394 connectionID
.data
= ctx
->serverRandom
;
395 connectionID
.length
= ctx
->ssl2ConnectionIDLength
;
396 variantData
.data
= &variantChar
;
397 variantData
.length
= 1;
398 if ((err
= SSLAllocBuffer(hashContext
, SSLHashMD5
.contextSize
, ctx
)) != 0)
399 { SSLFreeBuffer(keyData
, ctx
);
403 variantChar
= 0x30; /* '0' */
404 charPtr
= keyData
.data
;
405 while (keyMaterialLen
)
406 { hashDigest
.data
= charPtr
;
407 hashDigest
.length
= SSLHashMD5
.digestSize
;
408 if ((err
= SSLHashMD5
.init(hashContext
, ctx
)) != 0 ||
409 (err
= SSLHashMD5
.update(hashContext
, masterKey
)) != 0 ||
410 (err
= SSLHashMD5
.update(hashContext
, variantData
)) != 0 ||
411 (err
= SSLHashMD5
.update(hashContext
, challenge
)) != 0 ||
412 (err
= SSLHashMD5
.update(hashContext
, connectionID
)) != 0 ||
413 (err
= SSLHashMD5
.final(hashContext
, hashDigest
)) != 0)
414 { SSLFreeBuffer(keyData
, ctx
);
415 SSLFreeBuffer(hashContext
, ctx
);
418 charPtr
+= hashDigest
.length
;
420 keyMaterialLen
-= hashDigest
.length
;
423 assert(charPtr
== keyData
.data
+ keyData
.length
);
425 if ((err
= SSLFreeBuffer(hashContext
, ctx
)) != 0)
426 { SSLFreeBuffer(keyData
, ctx
);
430 ctx
->readPending
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
431 ctx
->writePending
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
432 ctx
->readPending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
433 ctx
->writePending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
434 ctx
->readPending
.sequenceNum
= ctx
->readCipher
.sequenceNum
;
435 ctx
->writePending
.sequenceNum
= ctx
->writeCipher
.sequenceNum
;
437 if (ctx
->protocolSide
== SSL_ServerSide
)
438 { writeKey
= keyData
.data
;
439 readKey
= keyData
.data
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
442 { readKey
= keyData
.data
;
443 writeKey
= keyData
.data
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
446 iv
= ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
448 if ((err
= ctx
->readPending
.symCipher
->initialize(readKey
, iv
,
449 &ctx
->readPending
, ctx
)) != 0 ||
450 (err
= ctx
->writePending
.symCipher
->initialize(writeKey
, iv
,
451 &ctx
->writePending
, ctx
)) != 0)
452 { SSLFreeBuffer(keyData
, ctx
);
457 * HEY! macSecret is only 20 bytes. This blows up when key size
458 * is greater than 20, e.g., 3DES.
459 * I'll increase the size of macSecret to 24, 'cause it appears
460 * from the SSL v23 spec that the macSecret really the same size as
461 * CLIENT-WRITE-KEY and SERVER-READ-KEY (see 1.2 of the spec).
463 memcpy(ctx
->readPending
.macSecret
, readKey
, ctx
->selectedCipherSpec
->cipher
->keySize
);
464 memcpy(ctx
->writePending
.macSecret
, writeKey
, ctx
->selectedCipherSpec
->cipher
->keySize
);
466 if ((err
= SSLFreeBuffer(keyData
, ctx
)) != 0)
469 ctx
->readCipher
= ctx
->readPending
;
470 ctx
->writeCipher
= ctx
->writePending
;
471 memset(&ctx
->readPending
, 0, sizeof(CipherContext
)); /* Zero out old data */
472 memset(&ctx
->writePending
, 0, sizeof(CipherContext
)); /* Zero out old data */