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: SSLContext accessors
24 Written by: Doug Mitchell, based on Netscape RSARef 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: sslctx.c SSLContext accessors
48 Functions called by the end user which configure an SSLContext
49 structure or access data stored there.
51 ****************************************************************** */
57 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
60 #include "appleCdsa.h"
61 #include "appleGlue.h"
62 #include "sslKeychain.h"
64 #include "cipherSpecs.h"
68 static void sslFreeDnList(
71 DNListElem
*dn
, *nextDN
;
74 dn
= ctx
->acceptableDNList
;
78 SSLFreeBuffer(&dn
->derDN
, &ctx
->sysCtx
);
80 buf
.data
= (uint8
*)dn
;
81 buf
.length
= sizeof(DNListElem
);
82 SSLFreeBuffer(&buf
, &ctx
->sysCtx
);
85 ctx
->acceptableDNList
= NULL
;
88 static SSLErr
sslFreeTrustedRoots(
94 if((ctx
->numTrustedCerts
== 0) || (ctx
->trustedCerts
== NULL
)) {
95 /* they really should both be zero, right? */
96 CASSERT((ctx
->numTrustedCerts
== 0) && (ctx
->trustedCerts
== NULL
));
99 for(i
=0; i
<ctx
->numTrustedCerts
; i
++) {
100 stFreeCssmData(&ctx
->trustedCerts
[i
], CSSM_FALSE
);
102 sslFree(ctx
->trustedCerts
);
104 ctx
->numTrustedCerts
= 0;
105 ctx
->trustedCerts
= NULL
;
111 SSLNewContext (Boolean isServer
,
112 SSLContextRef
*contextPtr
) /* RETURNED */
118 if(contextPtr
== NULL
) {
122 ctx
= (SSLContext
*)sslMalloc(sizeof(SSLContext
));
126 /* subsequent errors to errOut: */
128 memset(ctx
, 0, sizeof(SSLContext
));
129 ctx
->state
= SSLUninitialized
;
131 /* different defaults for client and server ... */
133 ctx
->protocolSide
= SSL_ServerSide
;
134 ctx
->reqProtocolVersion
= SSL_Version_3_0
;
137 ctx
->protocolSide
= SSL_ClientSide
;
138 ctx
->reqProtocolVersion
= SSL_Version_Undetermined
;
140 ctx
->negProtocolVersion
= SSL_Version_Undetermined
;
142 /* Initialize the cipher state to NULL_WITH_NULL_NULL */
143 ctx
->selectedCipherSpec
= &SSL_NULL_WITH_NULL_NULL_CipherSpec
;
144 ctx
->selectedCipher
= ctx
->selectedCipherSpec
->cipherSpec
;
145 ctx
->writeCipher
.hash
= ctx
->selectedCipherSpec
->macAlgorithm
;
146 ctx
->readCipher
.hash
= ctx
->selectedCipherSpec
->macAlgorithm
;
147 ctx
->readCipher
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
148 ctx
->writeCipher
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
151 /* these two are invariant */
152 ctx
->writeCipher
.encrypting
= 1;
153 ctx
->writePending
.encrypting
= 1;
154 #endif /* _APPLE_CDSA_ */
156 /* this gets init'd on first call to SSLHandshake() */
157 ctx
->validCipherSpecs
= NULL
;
158 ctx
->numValidCipherSpecs
= 0;
161 if(cfSetUpAllocators(ctx
)) {
166 /* attach to CSP, CL, TP */
167 serr
= attachToAll(ctx
);
169 oerr
= sslErrToOsStatus(serr
);
173 /* snag root certs from Keychain, tolerate error */
174 addBuiltInCerts(ctx
);
186 * Dispose of an SSLContext.
189 SSLDisposeContext (SSLContext
*ctx
)
191 WaitingRecord
*wait
, *next
;
197 sslDeleteCertificateChain(ctx
->localCert
, ctx
);
198 sslDeleteCertificateChain(ctx
->encryptCert
, ctx
);
199 sslDeleteCertificateChain(ctx
->peerCert
, ctx
);
200 ctx
->localCert
= ctx
->encryptCert
= ctx
->peerCert
= NULL
;
201 SSLFreeBuffer(&ctx
->partialReadBuffer
, &ctx
->sysCtx
);
203 wait
= ctx
->recordWriteQueue
;
205 { SSLFreeBuffer(&wait
->data
, &ctx
->sysCtx
);
207 buf
.data
= (uint8
*)wait
;
208 buf
.length
= sizeof(WaitingRecord
);
209 SSLFreeBuffer(&buf
, &ctx
->sysCtx
);
213 SSLFreeBuffer(&ctx
->dhPeerPublic
, &ctx
->sysCtx
);
214 SSLFreeBuffer(&ctx
->dhExchangePublic
, &ctx
->sysCtx
);
215 SSLFreeBuffer(&ctx
->dhPrivate
, &ctx
->sysCtx
);
217 SSLFreeBuffer(&ctx
->shaState
, &ctx
->sysCtx
);
218 SSLFreeBuffer(&ctx
->md5State
, &ctx
->sysCtx
);
220 SSLFreeBuffer(&ctx
->sessionID
, &ctx
->sysCtx
);
221 SSLFreeBuffer(&ctx
->peerID
, &ctx
->sysCtx
);
222 SSLFreeBuffer(&ctx
->resumableSession
, &ctx
->sysCtx
);
223 SSLFreeBuffer(&ctx
->preMasterSecret
, &ctx
->sysCtx
);
224 SSLFreeBuffer(&ctx
->partialReadBuffer
, &ctx
->sysCtx
);
225 SSLFreeBuffer(&ctx
->fragmentedMessageCache
, &ctx
->sysCtx
);
226 SSLFreeBuffer(&ctx
->receivedDataBuffer
, &ctx
->sysCtx
);
228 SSLDisposeCipherSuite(&ctx
->readCipher
, ctx
);
229 SSLDisposeCipherSuite(&ctx
->writeCipher
, ctx
);
230 SSLDisposeCipherSuite(&ctx
->readPending
, ctx
);
231 SSLDisposeCipherSuite(&ctx
->writePending
, ctx
);
233 sslFree(ctx
->validCipherSpecs
);
234 ctx
->validCipherSpecs
= NULL
;
235 ctx
->numValidCipherSpecs
= 0;
237 /* free APPLE_CDSA stuff */
238 #if ST_KEYCHAIN_ENABLE
239 sslFreeKey(ctx
->signingKeyCsp
, &ctx
->signingPrivKey
, &ctx
->signingKeyRef
);
240 sslFreeKey(ctx
->encryptKeyCsp
, &ctx
->encryptPrivKey
, &ctx
->encryptKeyRef
);
242 sslFreeKey(ctx
->signingKeyCsp
, &ctx
->signingPrivKey
, NULL
);
243 sslFreeKey(ctx
->encryptKeyCsp
, &ctx
->encryptPrivKey
, NULL
);
244 #endif /* ST_KEYCHAIN_ENABLE */
245 sslFreeKey(ctx
->signingKeyCsp
, &ctx
->signingPubKey
, NULL
);
246 sslFreeKey(ctx
->encryptKeyCsp
, &ctx
->encryptPubKey
, NULL
);
247 sslFreeKey(ctx
->peerPubKeyCsp
, &ctx
->peerPubKey
, NULL
);
250 if(ctx
->rootCertName
!= NULL
) {
251 sslFree(ctx
->rootCertName
);
253 #endif /* SSL_DEBUG */
255 sslFreeTrustedRoots(ctx
);
259 cfTearDownAllocators(ctx
);
260 memset(ctx
, 0, sizeof(SSLContext
));
266 * Determine the state of an SSL session.
269 SSLGetSessionState (SSLContextRef context
,
270 SSLSessionState
*state
) /* RETURNED */
272 SSLSessionState rtnState
= kSSLIdle
;
274 if(context
== NULL
) {
278 switch(context
->state
) {
279 case SSLUninitialized
:
280 case HandshakeServerUninit
:
281 case HandshakeClientUninit
:
284 case SSLGracefulClose
:
285 rtnState
= kSSLClosed
;
288 case SSLNoNotifyClose
:
289 rtnState
= kSSLAborted
;
291 case HandshakeServerReady
:
292 case HandshakeClientReady
:
293 rtnState
= kSSLConnected
;
296 CASSERT((context
->state
>= HandshakeServerHello
) &&
297 (context
->state
<= HandshakeSSL2ServerFinished
));
298 rtnState
= kSSLHandshake
;
307 SSLSetIOFuncs (SSLContextRef ctx
,
314 if(sslIsSessionActive(ctx
)) {
315 /* can't do this with an active session */
318 ctx
->ioCtx
.read
= read
;
319 ctx
->ioCtx
.write
= write
;
324 SSLSetConnection (SSLContextRef ctx
,
325 SSLConnectionRef connection
)
330 if(sslIsSessionActive(ctx
)) {
331 /* can't do this with an active session */
334 ctx
->ioCtx
.ioRef
= connection
;
339 SSLSetProtocolVersion (SSLContextRef ctx
,
342 SSLProtocolVersion versInt
;
347 if(sslIsSessionActive(ctx
)) {
348 /* can't do this with an active session */
352 /* convert external representation to private */
354 case kSSLProtocolUnknown
:
355 versInt
= SSL_Version_Undetermined
;
358 versInt
= SSL_Version_2_0
;
361 /* this tells us to do our best but allows 2.0 */
362 versInt
= SSL_Version_Undetermined
;
364 case kSSLProtocol3Only
:
365 versInt
= SSL_Version_3_0_Only
;
370 ctx
->reqProtocolVersion
= ctx
->negProtocolVersion
= versInt
;
374 static SSLProtocol
convertProtToExtern(SSLProtocolVersion prot
)
377 case SSL_Version_Undetermined
:
378 return kSSLProtocolUnknown
;
379 case SSL_Version_3_0_Only
:
380 return kSSLProtocol3Only
;
381 case SSL_Version_2_0
:
382 return kSSLProtocol2
;
383 case SSL_Version_3_0
:
384 return kSSLProtocol3
;
385 case SSL_Version_3_0_With_2_0_Hello
:
386 sslPanic("How did we get SSL_Version_3_0_With_2_0_Hello?");
388 sslPanic("convertProtToExtern: bad prot");
390 /* not reached but make compiler happy */
391 return kSSLProtocolUnknown
;
395 SSLGetProtocolVersion (SSLContextRef ctx
,
396 SSLProtocol
*protocol
) /* RETURNED */
401 *protocol
= convertProtToExtern(ctx
->reqProtocolVersion
);
406 SSLGetNegotiatedProtocolVersion (SSLContextRef ctx
,
407 SSLProtocol
*protocol
) /* RETURNED */
412 *protocol
= convertProtToExtern(ctx
->negProtocolVersion
);
417 SSLSetAllowExpiredCerts (SSLContextRef ctx
,
418 Boolean allowExpired
)
423 if(sslIsSessionActive(ctx
)) {
424 /* can't do this with an active session */
427 ctx
->allowExpiredCerts
= allowExpired
;
432 SSLGetAllowExpiredCerts (SSLContextRef ctx
,
433 Boolean
*allowExpired
)
438 *allowExpired
= ctx
->allowExpiredCerts
;
442 OSStatus
SSLSetAllowAnyRoot(
449 ctx
->allowAnyRoot
= anyRoot
;
461 *anyRoot
= ctx
->allowAnyRoot
;
465 #if ST_SERVER_MODE_ENABLE
467 SSLSetClientSideAuthenticate (SSLContext
*ctx
,
468 SSLAuthenticate auth
)
473 if(sslIsSessionActive(ctx
)) {
474 /* can't do this with an active session */
477 ctx
->clientAuth
= auth
;
479 case kNeverAuthenticate
:
480 ctx
->tryClientAuth
= false;
482 case kAlwaysAuthenticate
:
483 case kTryAuthenticate
:
484 /* FIXME - needs work to distinguish these cases at
486 ctx
->tryClientAuth
= true;
491 #endif /* ST_SERVER_MODE_ENABLE */
493 #if (ST_SERVER_MODE_ENABLE || ST_CLIENT_AUTHENTICATION)
496 SSLSetCertificate (SSLContextRef ctx
,
500 * -- free localCerts if we have any
501 * -- Get raw cert data, convert to ctx->localCert
502 * -- get pub, priv keys from certRef[0]
503 * -- validate cert chain
508 if(sslIsSessionActive(ctx
)) {
509 /* can't do this with an active session */
512 return parseIncomingCerts(ctx
,
516 &ctx
->signingPrivKey
,
518 &ctx
->signingKeyRef
);
520 #endif /* (ST_SERVER_MODE_ENABLE || ST_CLIENT_AUTHENTICATION) */
522 #if ST_SERVER_MODE_ENABLE
524 SSLSetEncryptionCertificate (SSLContextRef ctx
,
528 * -- free encryptCert if we have any
529 * -- Get raw cert data, convert to ctx->encryptCert
530 * -- get pub, priv keys from certRef[0]
531 * -- validate cert chain
536 if(sslIsSessionActive(ctx
)) {
537 /* can't do this with an active session */
540 return parseIncomingCerts(ctx
,
544 &ctx
->encryptPrivKey
,
546 &ctx
->encryptKeyRef
);
548 #endif /* ST_SERVER_MODE_ENABLE*/
550 #if ST_KEYCHAIN_ENABLE
553 * Add (optional, additional) trusted root certs.
556 SSLSetTrustedRootCertKC (SSLContextRef ctx
,
558 Boolean deleteExisting
)
561 * -- free trustedCerts if deleteExisting
562 * -- Get raw cert data, add to ctx->trustedCerts
563 * -- verify that each of these is a valid (self-verifying)
565 * -- add each subject name to acceptableDNList
567 if((ctx
== NULL
) || (keyChainRef
== nil
)) {
570 if(sslIsSessionActive(ctx
)) {
571 /* can't do this with an active session */
575 sslFreeTrustedRoots(ctx
);
577 return parseTrustedKeychain(ctx
, keyChainRef
);
581 SSLSetNewRootKC (SSLContextRef ctx
,
585 if((ctx
== NULL
) || (keyChainRef
== nil
)) {
588 if(sslIsSessionActive(ctx
)) {
589 /* can't do this with an active session */
592 if(ctx
->newRootCertKc
!= NULL
) {
593 /* can't do this multiple times */
596 ctx
->newRootCertKc
= keyChainRef
;
597 ctx
->accessCreds
= accessCreds
;
600 #endif /* ST_KEYCHAIN_ENABLE */
603 SSLSetPeerID (SSLContext
*ctx
,
609 /* copy peerId to context->peerId */
612 ((len
= CFDataGetLength(peerID
)) == 0)) {
615 if(sslIsSessionActive(ctx
)) {
616 /* can't do this with an active session */
619 SSLFreeBuffer(&ctx
->peerID
, &ctx
->sysCtx
);
620 serr
= SSLAllocBuffer(&ctx
->peerID
, len
, &ctx
->sysCtx
);
622 return sslErrToOsStatus(serr
);
624 memmove(ctx
->peerID
.data
, CFDataGetBytePtr(peerID
), len
);
625 ctx
->peerID
.length
= len
;
630 SSLGetNegotiatedCipher (SSLContextRef ctx
,
631 SSLCipherSuite
*cipherSuite
)
636 if(!sslIsSessionActive(ctx
)) {
639 *cipherSuite
= (SSLCipherSuite
)ctx
->selectedCipher
;
644 * Add an acceptable distinguished name.
645 * FIXME - this looks like a big hole in the SSLRef code;
646 * acceptableDNList is set here and in SSLProcessCertificateRequest();
647 * it's used and sent to a client in SSLEncodeCertificateRequest();
648 * but the list is never used to decide what certs to send!
650 * Also FIXME - this allocation of dnBufs is total horseshit. The
651 * SSLBufs can never get freed. Why not just allocate the
652 * raw DNListElems? Sheesh.
657 SSLAddDistinguishedName(SSLContext
*ctx
, SSLBuffer derDN
)
662 if ((err
= SSLAllocBuffer(&dnBuf
, sizeof(DNListElem
), &ctx
->sysCtx
)) != 0)
664 dn
= (DNListElem
*)dnBuf
.data
;
665 if ((err
= SSLAllocBuffer(&dn
->derDN
, derDN
.length
, &ctx
->sysCtx
)) != 0)
666 { SSLFreeBuffer(&dnBuf
, &ctx
->sysCtx
);
669 memcpy(dn
->derDN
.data
, derDN
.data
, derDN
.length
);
670 dn
->next
= ctx
->acceptableDNList
;
671 ctx
->acceptableDNList
= dn
;
674 #endif /* not used */
677 * Request peer certificates. Valid anytime, subsequent to
678 * a handshake attempt.
681 SSLGetPeerCertificates (SSLContextRef ctx
,
685 CFMutableArrayRef ca
;
688 SSLCertificate
*scert
;
696 * Copy peerCert, a chain of SSLCertificates, to a CFArray of
697 * CFDataRefs, each of which is one DER-encoded cert.
699 numCerts
= SSLGetCertificateChainLength(ctx
->peerCert
);
703 ca
= CFArrayCreateMutable(ctx
->cfAllocatorRef
,
704 (CFIndex
)numCerts
, &kCFTypeArrayCallBacks
);
710 * We'll give the certs in the same order we store them -
711 * caller gets root first. OK?
713 scert
= ctx
->peerCert
;
714 for(i
=0; i
<numCerts
; i
++) {
715 CASSERT(scert
!= NULL
); /* else SSLGetCertificateChainLength
717 cfd
= CFDataCreate(ctx
->cfAllocatorRef
,
719 scert
->derCert
.length
);
724 CFArrayAppendValue(ca
, cfd
);