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 if ((msg
== SSL2_MsgClientHello
) &&
164 (ctx
->negProtocolVersion
>= SSL_Version_3_0
))
165 { /* Promote this message to SSL 3 protocol */
166 if ((err
= SSL3ReceiveSSL2ClientHello(rec
, ctx
)) != 0)
170 err
= SSL2AdvanceHandshake(msg
, ctx
);
176 SSL2AdvanceHandshake(SSL2MessageType msg
, SSLContext
*ctx
)
182 { case SSL2_MsgKickstart
:
183 assert(ctx
->negProtocolVersion
== SSL_Version_Undetermined
);
184 assert(ctx
->versionSsl2Enable
);
185 if (ctx
->versionSsl3Enable
|| ctx
->versionTls1Enable
) {
186 /* prepare for possible v3 upgrade */
187 if ((err
= SSLInitMessageHashes(ctx
)) != 0)
190 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientHello
, ctx
)) != 0)
192 if (ctx
->versionSsl3Enable
|| ctx
->versionTls1Enable
) {
193 SSLChangeHdskState(ctx
, SSL_HdskStateServerHelloUnknownVersion
);
197 SSLChangeHdskState(ctx
, SSL2_HdskStateServerHello
);
200 case SSL2_MsgClientHello
:
201 if ((err
= SSL2CompareSessionIDs(ctx
)) != 0)
203 if (ctx
->sessionMatch
== 0)
204 if ((err
= SSL2GenerateSessionID(ctx
)) != 0)
206 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerHello
, ctx
)) != 0)
208 if (ctx
->sessionMatch
== 0)
209 { SSLChangeHdskState(ctx
, SSL2_HdskStateClientMasterKey
);
212 sslLogResumSessDebug("===RESUMING SSL2 server-side session");
213 if ((err
= SSL2InstallSessionKey(ctx
)) != 0)
215 /* Fall through for matching session; lame, but true */
216 case SSL2_MsgClientMasterKey
:
217 if ((err
= SSL2InitCiphers(ctx
)) != 0)
219 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerVerify
, ctx
)) != 0)
221 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeServerFinished
, ctx
)) != 0)
223 SSLChangeHdskState(ctx
, SSL2_HdskStateClientFinished
);
225 case SSL2_MsgServerHello
:
226 if (ctx
->sessionMatch
== 0)
227 { if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientMasterKey
, ctx
)) != 0)
232 sslLogResumSessDebug("===RESUMING SSL2 client-side session");
233 if ((err
= SSL2InstallSessionKey(ctx
)) != 0)
236 if ((err
= SSL2InitCiphers(ctx
)) != 0)
238 if ((err
= SSL2PrepareAndQueueMessage(SSL2EncodeClientFinished
, ctx
)) != 0)
240 SSLChangeHdskState(ctx
, SSL2_HdskStateServerVerify
);
242 case SSL2_MsgClientFinished
:
243 /* Handshake is complete; turn ciphers on */
244 ctx
->writeCipher
.ready
= 1;
245 ctx
->readCipher
.ready
= 1;
246 /* original code never got out of SSL2_MsgClientFinished state */
247 assert(ctx
->protocolSide
== SSL_ServerSide
);
248 SSLChangeHdskState(ctx
, SSL_HdskStateServerReady
);
249 if (ctx
->peerID
.data
!= 0)
250 SSLAddSessionData(ctx
);
252 case SSL2_MsgServerVerify
:
253 SSLChangeHdskState(ctx
, SSL2_HdskStateServerFinished
);
255 case SSL2_MsgRequestCert
:
256 if ((err
= SSL2SendError(SSL2_ErrNoCert
, ctx
)) != 0)
259 case SSL2_MsgServerFinished
:
260 /* Handshake is complete; turn ciphers on */
261 ctx
->writeCipher
.ready
= 1;
262 ctx
->readCipher
.ready
= 1;
263 /* original code never got out of SSL2_MsgServerFinished state */
264 assert(ctx
->protocolSide
== SSL_ClientSide
);
265 SSLChangeHdskState(ctx
, SSL_HdskStateClientReady
);
266 if (ctx
->peerID
.data
!= 0)
267 SSLAddSessionData(ctx
);
270 case SSL2_MsgClientCert
:
271 return errSSLProtocol
;
279 SSL2PrepareAndQueueMessage(EncodeSSL2MessageFunc encodeFunc
, SSLContext
*ctx
)
283 rec
.contentType
= SSL_RecordTypeV2_0
;
284 rec
.protocolVersion
= SSL_Version_2_0
;
285 if ((err
= encodeFunc(rec
.contents
, ctx
)) != 0)
288 logSsl2Msg((SSL2MessageType
)rec
.contents
.data
[0], 1);
290 assert(ctx
->sslTslCalls
!= NULL
);
291 if ((err
= ctx
->sslTslCalls
->writeRecord(rec
, ctx
)) != 0)
292 { SSLFreeBuffer(rec
.contents
, ctx
);
296 assert((ctx
->negProtocolVersion
== SSL_Version_Undetermined
) ||
297 (ctx
->negProtocolVersion
== SSL_Version_2_0
));
298 if((ctx
->negProtocolVersion
== SSL_Version_Undetermined
) &&
299 (ctx
->versionSsl3Enable
|| ctx
->versionTls1Enable
)) {
300 /* prepare for possible V3/TLS1 upgrade */
301 if ((err
= SSLHashSHA1
.update(ctx
->shaState
, rec
.contents
)) != 0 ||
302 (err
= SSLHashMD5
.update(ctx
->md5State
, rec
.contents
)) != 0)
305 err
= SSLFreeBuffer(rec
.contents
, ctx
);
310 SSL2CompareSessionIDs(SSLContext
*ctx
)
312 SSLBuffer sessionIdentifier
;
314 ctx
->sessionMatch
= 0;
316 if (ctx
->resumableSession
.data
== 0)
319 if ((err
= SSLRetrieveSessionID(ctx
->resumableSession
,
320 &sessionIdentifier
, ctx
)) != 0)
323 if (sessionIdentifier
.length
== ctx
->sessionID
.length
&&
324 memcmp(sessionIdentifier
.data
, ctx
->sessionID
.data
, sessionIdentifier
.length
) == 0)
325 ctx
->sessionMatch
= 1;
327 if ((err
= SSLFreeBuffer(sessionIdentifier
, ctx
)) != 0)
334 SSL2InstallSessionKey(SSLContext
*ctx
)
337 assert(ctx
->sessionMatch
!= 0);
338 assert(ctx
->resumableSession
.data
!= 0);
339 if ((err
= SSLInstallSessionFromData(ctx
->resumableSession
, ctx
)) != 0)
345 SSL2GenerateSessionID(SSLContext
*ctx
)
348 if ((err
= SSLFreeBuffer(ctx
->sessionID
, ctx
)) != 0)
350 if ((err
= SSLAllocBuffer(ctx
->sessionID
, SSL_SESSION_ID_LEN
, ctx
)) != 0)
352 if ((err
= sslRand(ctx
, &ctx
->sessionID
)) != 0)
358 SSL2InitCiphers(SSLContext
*ctx
)
362 uint8 variantChar
, *charPtr
, *readKey
, *writeKey
, *iv
;
363 SSLBuffer hashDigest
, hashContext
, masterKey
, challenge
, connectionID
, variantData
;
365 keyMaterialLen
= 2 * ctx
->selectedCipherSpec
->cipher
->keySize
;
366 if ((err
= SSLAllocBuffer(keyData
, keyMaterialLen
, ctx
)) != 0)
369 /* Can't have % in assertion string... */
372 UInt32 keyModDigestSize
= keyMaterialLen
% SSLHashMD5
.digestSize
;
373 assert(keyModDigestSize
== 0);
377 masterKey
.data
= ctx
->masterSecret
;
378 masterKey
.length
= ctx
->selectedCipherSpec
->cipher
->keySize
;
379 challenge
.data
= ctx
->clientRandom
+ SSL_CLIENT_SRVR_RAND_SIZE
-
380 ctx
->ssl2ChallengeLength
;
381 challenge
.length
= ctx
->ssl2ChallengeLength
;
382 connectionID
.data
= ctx
->serverRandom
;
383 connectionID
.length
= ctx
->ssl2ConnectionIDLength
;
384 variantData
.data
= &variantChar
;
385 variantData
.length
= 1;
386 if ((err
= SSLAllocBuffer(hashContext
, SSLHashMD5
.contextSize
, ctx
)) != 0)
387 { SSLFreeBuffer(keyData
, ctx
);
391 variantChar
= 0x30; /* '0' */
392 charPtr
= keyData
.data
;
393 while (keyMaterialLen
)
394 { hashDigest
.data
= charPtr
;
395 hashDigest
.length
= SSLHashMD5
.digestSize
;
396 if ((err
= SSLHashMD5
.init(hashContext
, ctx
)) != 0 ||
397 (err
= SSLHashMD5
.update(hashContext
, masterKey
)) != 0 ||
398 (err
= SSLHashMD5
.update(hashContext
, variantData
)) != 0 ||
399 (err
= SSLHashMD5
.update(hashContext
, challenge
)) != 0 ||
400 (err
= SSLHashMD5
.update(hashContext
, connectionID
)) != 0 ||
401 (err
= SSLHashMD5
.final(hashContext
, hashDigest
)) != 0)
402 { SSLFreeBuffer(keyData
, ctx
);
403 SSLFreeBuffer(hashContext
, ctx
);
406 charPtr
+= hashDigest
.length
;
408 keyMaterialLen
-= hashDigest
.length
;
411 assert(charPtr
== keyData
.data
+ keyData
.length
);
413 if ((err
= SSLFreeBuffer(hashContext
, ctx
)) != 0)
414 { SSLFreeBuffer(keyData
, ctx
);
418 ctx
->readPending
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
419 ctx
->writePending
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
420 ctx
->readPending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
421 ctx
->writePending
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
422 ctx
->readPending
.sequenceNum
= ctx
->readCipher
.sequenceNum
;
423 ctx
->writePending
.sequenceNum
= ctx
->writeCipher
.sequenceNum
;
425 if (ctx
->protocolSide
== SSL_ServerSide
)
426 { writeKey
= keyData
.data
;
427 readKey
= keyData
.data
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
430 { readKey
= keyData
.data
;
431 writeKey
= keyData
.data
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
434 iv
= ctx
->masterSecret
+ ctx
->selectedCipherSpec
->cipher
->keySize
;
436 if ((err
= ctx
->readPending
.symCipher
->initialize(readKey
, iv
,
437 &ctx
->readPending
, ctx
)) != 0 ||
438 (err
= ctx
->writePending
.symCipher
->initialize(writeKey
, iv
,
439 &ctx
->writePending
, ctx
)) != 0)
440 { SSLFreeBuffer(keyData
, ctx
);
445 * HEY! macSecret is only 20 bytes. This blows up when key size
446 * is greater than 20, e.g., 3DES.
447 * I'll increase the size of macSecret to 24, 'cause it appears
448 * from the SSL v23 spec that the macSecret really the same size as
449 * CLIENT-WRITE-KEY and SERVER-READ-KEY (see 1.2 of the spec).
451 memcpy(ctx
->readPending
.macSecret
, readKey
, ctx
->selectedCipherSpec
->cipher
->keySize
);
452 memcpy(ctx
->writePending
.macSecret
, writeKey
, ctx
->selectedCipherSpec
->cipher
->keySize
);
454 if ((err
= SSLFreeBuffer(keyData
, ctx
)) != 0)
457 ctx
->readCipher
= ctx
->readPending
;
458 ctx
->writeCipher
= ctx
->writePending
;
459 memset(&ctx
->readPending
, 0, sizeof(CipherContext
)); /* Zero out old data */
460 memset(&ctx
->writePending
, 0, sizeof(CipherContext
)); /* Zero out old data */