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 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: 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"
65 #include "appleSession.h"
67 #include <Security/SecCertificate.h>
69 static void sslFreeDnList(
72 DNListElem
*dn
, *nextDN
;
75 dn
= ctx
->acceptableDNList
;
79 SSLFreeBuffer(&dn
->derDN
, &ctx
->sysCtx
);
81 buf
.data
= (uint8
*)dn
;
82 buf
.length
= sizeof(DNListElem
);
83 SSLFreeBuffer(&buf
, &ctx
->sysCtx
);
86 ctx
->acceptableDNList
= NULL
;
89 static SSLErr
sslFreeTrustedRoots(
95 if((ctx
->numTrustedCerts
== 0) || (ctx
->trustedCerts
== NULL
)) {
96 /* they really should both be zero, right? */
97 CASSERT((ctx
->numTrustedCerts
== 0) && (ctx
->trustedCerts
== NULL
));
100 for(i
=0; i
<ctx
->numTrustedCerts
; i
++) {
101 stFreeCssmData(&ctx
->trustedCerts
[i
], CSSM_FALSE
);
103 sslFree(ctx
->trustedCerts
);
105 ctx
->numTrustedCerts
= 0;
106 ctx
->trustedCerts
= NULL
;
112 * Default attempted version.
114 #define DEFAULT_MAX_VERSION TLS_Version_1_0
117 SSLNewContext (Boolean isServer
,
118 SSLContextRef
*contextPtr
) /* RETURNED */
124 if(contextPtr
== NULL
) {
128 ctx
= (SSLContext
*)sslMalloc(sizeof(SSLContext
));
132 /* subsequent errors to errOut: */
134 memset(ctx
, 0, sizeof(SSLContext
));
135 ctx
->state
= SSLUninitialized
;
137 /* different defaults for client and server ... */
139 ctx
->protocolSide
= SSL_ServerSide
;
140 ctx
->reqProtocolVersion
= DEFAULT_MAX_VERSION
;
143 ctx
->protocolSide
= SSL_ClientSide
;
144 ctx
->reqProtocolVersion
= SSL_Version_Undetermined
;
146 ctx
->negProtocolVersion
= SSL_Version_Undetermined
;
147 ctx
->maxProtocolVersion
= DEFAULT_MAX_VERSION
;
148 /* Default value so we can send and receive hello msgs */
149 ctx
->sslTslCalls
= &Ssl3Callouts
;
151 /* Initialize the cipher state to NULL_WITH_NULL_NULL */
152 ctx
->selectedCipherSpec
= &SSL_NULL_WITH_NULL_NULL_CipherSpec
;
153 ctx
->selectedCipher
= ctx
->selectedCipherSpec
->cipherSpec
;
154 ctx
->writeCipher
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
155 ctx
->readCipher
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
156 ctx
->readCipher
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
157 ctx
->writeCipher
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
159 /* these two are invariant */
160 ctx
->writeCipher
.encrypting
= 1;
161 ctx
->writePending
.encrypting
= 1;
163 /* this gets init'd on first call to SSLHandshake() */
164 ctx
->validCipherSpecs
= NULL
;
165 ctx
->numValidCipherSpecs
= 0;
167 ctx
->peerDomainName
= NULL
;
168 ctx
->peerDomainNameLen
= 0;
172 /* attach to CSP, CL, TP */
173 serr
= attachToAll(ctx
);
175 oerr
= sslErrToOsStatus(serr
);
179 /* snag root certs from Keychain, tolerate error */
180 addBuiltInCerts(ctx
);
192 * Dispose of an SSLContext.
195 SSLDisposeContext (SSLContext
*ctx
)
197 WaitingRecord
*wait
, *next
;
203 sslDeleteCertificateChain(ctx
->localCert
, ctx
);
204 sslDeleteCertificateChain(ctx
->encryptCert
, ctx
);
205 sslDeleteCertificateChain(ctx
->peerCert
, ctx
);
206 ctx
->localCert
= ctx
->encryptCert
= ctx
->peerCert
= NULL
;
207 SSLFreeBuffer(&ctx
->partialReadBuffer
, &ctx
->sysCtx
);
209 wait
= ctx
->recordWriteQueue
;
211 { SSLFreeBuffer(&wait
->data
, &ctx
->sysCtx
);
213 buf
.data
= (uint8
*)wait
;
214 buf
.length
= sizeof(WaitingRecord
);
215 SSLFreeBuffer(&buf
, &ctx
->sysCtx
);
219 SSLFreeBuffer(&ctx
->dhPeerPublic
, &ctx
->sysCtx
);
220 SSLFreeBuffer(&ctx
->dhExchangePublic
, &ctx
->sysCtx
);
221 SSLFreeBuffer(&ctx
->dhPrivate
, &ctx
->sysCtx
);
223 CloseHash(&SSLHashSHA1
, &ctx
->shaState
, ctx
);
224 CloseHash(&SSLHashMD5
, &ctx
->md5State
, ctx
);
226 SSLFreeBuffer(&ctx
->sessionID
, &ctx
->sysCtx
);
227 SSLFreeBuffer(&ctx
->peerID
, &ctx
->sysCtx
);
228 SSLFreeBuffer(&ctx
->resumableSession
, &ctx
->sysCtx
);
229 SSLFreeBuffer(&ctx
->preMasterSecret
, &ctx
->sysCtx
);
230 SSLFreeBuffer(&ctx
->partialReadBuffer
, &ctx
->sysCtx
);
231 SSLFreeBuffer(&ctx
->fragmentedMessageCache
, &ctx
->sysCtx
);
232 SSLFreeBuffer(&ctx
->receivedDataBuffer
, &ctx
->sysCtx
);
234 if(ctx
->peerDomainName
) {
235 sslFree(ctx
->peerDomainName
);
236 ctx
->peerDomainName
= NULL
;
237 ctx
->peerDomainNameLen
= 0;
239 SSLDisposeCipherSuite(&ctx
->readCipher
, ctx
);
240 SSLDisposeCipherSuite(&ctx
->writeCipher
, ctx
);
241 SSLDisposeCipherSuite(&ctx
->readPending
, ctx
);
242 SSLDisposeCipherSuite(&ctx
->writePending
, ctx
);
244 sslFree(ctx
->validCipherSpecs
);
245 ctx
->validCipherSpecs
= NULL
;
246 ctx
->numValidCipherSpecs
= 0;
248 /* free APPLE_CDSA stuff */
250 /* As of 5/3/02, we don't need to free these keys; they belong
252 #if ST_KEYCHAIN_ENABLE && ST_KC_KEYS_NEED_REF
253 sslFreeKey(ctx
->signingKeyCsp
, &ctx
->signingPrivKey
, &ctx
->signingKeyRef
);
254 sslFreeKey(ctx
->encryptKeyCsp
, &ctx
->encryptPrivKey
, &ctx
->encryptKeyRef
);
256 sslFreeKey(ctx
->signingKeyCsp
, (CSSM_KEY_PTR
*)&ctx
->signingPrivKey
, NULL
);
257 sslFreeKey(ctx
->encryptKeyCsp
, (CSSM_KEY_PTR
*)&ctx
->encryptPrivKey
, NULL
);
258 #endif /* ST_KEYCHAIN_ENABLE && ST_KC_KEYS_NEED_REF */
262 * NOTE: currently, all public keys come from the CL via CSSM_CL_CertGetKeyInfo.
263 * We really don't know what CSP the CL used to generate a public key (in fact,
264 * it uses the raw CSP only to get LogicalKeySizeInBits, but we can't know
265 * that). Thus using e.g. signingKeyCsp (or any other CSP) to free
266 * signingPubKey is not tecnically accurate. However, our public keys
267 * are all raw keys, and all Apple CSPs dispose of raw keys in the same
270 sslFreeKey(ctx
->signingKeyCsp
, &ctx
->signingPubKey
, NULL
);
271 sslFreeKey(ctx
->encryptKeyCsp
, &ctx
->encryptPubKey
, NULL
);
272 sslFreeKey(ctx
->peerPubKeyCsp
, &ctx
->peerPubKey
, NULL
);
275 if(ctx
->rootCertName
!= NULL
) {
276 sslFree(ctx
->rootCertName
);
278 #endif /* SSL_DEBUG */
280 sslFreeTrustedRoots(ctx
);
284 memset(ctx
, 0, sizeof(SSLContext
));
291 * Determine the state of an SSL session.
294 SSLGetSessionState (SSLContextRef context
,
295 SSLSessionState
*state
) /* RETURNED */
297 SSLSessionState rtnState
= kSSLIdle
;
299 if(context
== NULL
) {
303 switch(context
->state
) {
304 case SSLUninitialized
:
305 case HandshakeServerUninit
:
306 case HandshakeClientUninit
:
309 case SSLGracefulClose
:
310 rtnState
= kSSLClosed
;
313 case SSLNoNotifyClose
:
314 rtnState
= kSSLAborted
;
316 case HandshakeServerReady
:
317 case HandshakeClientReady
:
318 rtnState
= kSSLConnected
;
321 CASSERT((context
->state
>= HandshakeServerHello
) &&
322 (context
->state
<= HandshakeSSL2ServerFinished
));
323 rtnState
= kSSLHandshake
;
332 SSLSetIOFuncs (SSLContextRef ctx
,
339 if(sslIsSessionActive(ctx
)) {
340 /* can't do this with an active session */
343 ctx
->ioCtx
.read
= read
;
344 ctx
->ioCtx
.write
= write
;
349 SSLSetConnection (SSLContextRef ctx
,
350 SSLConnectionRef connection
)
355 if(sslIsSessionActive(ctx
)) {
356 /* can't do this with an active session */
359 ctx
->ioCtx
.ioRef
= connection
;
364 SSLSetPeerDomainName (SSLContextRef ctx
,
365 const char *peerName
,
371 if(sslIsSessionActive(ctx
)) {
372 /* can't do this with an active session */
376 /* free possible existing name */
377 if(ctx
->peerDomainName
) {
378 sslFree(ctx
->peerDomainName
);
382 ctx
->peerDomainName
= sslMalloc(peerNameLen
);
383 if(ctx
->peerDomainName
== NULL
) {
386 memmove(ctx
->peerDomainName
, peerName
, peerNameLen
);
387 ctx
->peerDomainNameLen
= peerNameLen
;
392 * Determine the buffer size needed for SSLGetPeerDomainName().
395 SSLGetPeerDomainNameLength (SSLContextRef ctx
,
396 size_t *peerNameLen
) // RETURNED
401 *peerNameLen
= ctx
->peerDomainNameLen
;
406 SSLGetPeerDomainName (SSLContextRef ctx
,
407 char *peerName
, // returned here
408 size_t *peerNameLen
) // IN/OUT
413 if(*peerNameLen
< ctx
->peerDomainNameLen
) {
414 return errSSLBufferOverflow
;
416 memmove(peerName
, ctx
->peerDomainName
, ctx
->peerDomainNameLen
);
417 *peerNameLen
= ctx
->peerDomainNameLen
;
422 SSLSetProtocolVersion (SSLContextRef ctx
,
425 SSLProtocolVersion versInt
;
426 SSLProtocolVersion versMax
;
431 if(sslIsSessionActive(ctx
)) {
432 /* can't do this with an active session */
436 /* convert external representation to private */
438 case kSSLProtocolUnknown
:
439 versInt
= SSL_Version_Undetermined
;
440 versMax
= DEFAULT_MAX_VERSION
;
443 versInt
= versMax
= SSL_Version_2_0
;
446 /* this tells us to do our best but allows 2.0 */
447 versInt
= SSL_Version_Undetermined
;
448 versMax
= SSL_Version_3_0
;
450 case kSSLProtocol3Only
:
451 versInt
= SSL_Version_3_0_Only
;
452 versMax
= SSL_Version_3_0
;
455 /* this tells us to do our best but allows 2.0 */
456 versInt
= SSL_Version_Undetermined
;
457 versMax
= TLS_Version_1_0
;
459 case kTLSProtocol1Only
:
460 versInt
= TLS_Version_1_0_Only
;
461 versMax
= TLS_Version_1_0
;
466 ctx
->reqProtocolVersion
= ctx
->negProtocolVersion
= versInt
;
467 ctx
->maxProtocolVersion
= versMax
;
471 static SSLProtocol
convertProtToExtern(SSLProtocolVersion prot
)
474 case SSL_Version_Undetermined
:
475 return kSSLProtocolUnknown
;
476 case SSL_Version_3_0_Only
:
477 return kSSLProtocol3Only
;
478 case SSL_Version_2_0
:
479 return kSSLProtocol2
;
480 case SSL_Version_3_0
:
481 return kSSLProtocol3
;
482 case TLS_Version_1_0_Only
:
483 return kTLSProtocol1Only
;
484 case TLS_Version_1_0
:
485 return kTLSProtocol1
;
486 /* this can happen in an intermediate state while negotiation
487 * is in progress...right? */
488 case SSL_Version_3_0_With_2_0_Hello
:
489 return kSSLProtocolUnknown
;
491 sslPanic("convertProtToExtern: bad prot");
493 /* not reached but make compiler happy */
494 return kSSLProtocolUnknown
;
498 SSLGetProtocolVersion (SSLContextRef ctx
,
499 SSLProtocol
*protocol
) /* RETURNED */
504 *protocol
= convertProtToExtern(ctx
->reqProtocolVersion
);
509 SSLGetNegotiatedProtocolVersion (SSLContextRef ctx
,
510 SSLProtocol
*protocol
) /* RETURNED */
515 *protocol
= convertProtToExtern(ctx
->negProtocolVersion
);
520 SSLSetAllowsExpiredCerts(SSLContextRef ctx
,
521 Boolean allowExpired
)
526 if(sslIsSessionActive(ctx
)) {
527 /* can't do this with an active session */
530 ctx
->allowExpiredCerts
= allowExpired
;
535 SSLGetAllowsExpiredCerts (SSLContextRef ctx
,
536 Boolean
*allowExpired
)
541 *allowExpired
= ctx
->allowExpiredCerts
;
545 OSStatus
SSLSetAllowsAnyRoot(
552 ctx
->allowAnyRoot
= anyRoot
;
564 *anyRoot
= ctx
->allowAnyRoot
;
568 #if ST_SERVER_MODE_ENABLE
570 SSLSetClientSideAuthenticate (SSLContext
*ctx
,
571 SSLAuthenticate auth
)
576 if(sslIsSessionActive(ctx
)) {
577 /* can't do this with an active session */
580 ctx
->clientAuth
= auth
;
582 case kNeverAuthenticate
:
583 ctx
->tryClientAuth
= false;
585 case kAlwaysAuthenticate
:
586 case kTryAuthenticate
:
587 /* FIXME - needs work to distinguish these cases at
589 ctx
->tryClientAuth
= true;
594 #endif /* ST_SERVER_MODE_ENABLE */
596 #if (ST_SERVER_MODE_ENABLE || ST_CLIENT_AUTHENTICATION)
599 SSLSetCertificate (SSLContextRef ctx
,
603 * -- free localCerts if we have any
604 * -- Get raw cert data, convert to ctx->localCert
605 * -- get pub, priv keys from certRef[0]
606 * -- validate cert chain
611 if(sslIsSessionActive(ctx
)) {
612 /* can't do this with an active session */
615 return parseIncomingCerts(ctx
,
619 &ctx
->signingPrivKey
,
621 #if ST_KC_KEYS_NEED_REF
628 #endif /* (ST_SERVER_MODE_ENABLE || ST_CLIENT_AUTHENTICATION) */
630 #if ST_SERVER_MODE_ENABLE
632 SSLSetEncryptionCertificate (SSLContextRef ctx
,
636 * -- free encryptCert if we have any
637 * -- Get raw cert data, convert to ctx->encryptCert
638 * -- get pub, priv keys from certRef[0]
639 * -- validate cert chain
644 if(sslIsSessionActive(ctx
)) {
645 /* can't do this with an active session */
648 return parseIncomingCerts(ctx
,
652 &ctx
->encryptPrivKey
,
654 #if ST_KC_KEYS_NEED_REF
656 &ctx
->encryptKeyRef
);
661 #endif /* ST_SERVER_MODE_ENABLE*/
663 #if ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS
666 * Add (optional, additional) trusted root certs.
669 SSLSetTrustedRootCertKC (SSLContextRef ctx
,
671 Boolean deleteExisting
)
674 * -- free trustedCerts if deleteExisting
675 * -- Get raw cert data, add to ctx->trustedCerts
676 * -- verify that each of these is a valid (self-verifying)
678 * -- add each subject name to acceptableDNList
680 if((ctx
== NULL
) || (keyChainRef
== nil
)) {
683 if(sslIsSessionActive(ctx
)) {
684 /* can't do this with an active session */
688 sslFreeTrustedRoots(ctx
);
690 return parseTrustedKeychain(ctx
, keyChainRef
);
694 SSLSetNewRootKC (SSLContextRef ctx
,
698 if((ctx
== NULL
) || (keyChainRef
== nil
)) {
701 if(sslIsSessionActive(ctx
)) {
702 /* can't do this with an active session */
705 if(ctx
->newRootCertKc
!= NULL
) {
706 /* can't do this multiple times */
709 ctx
->newRootCertKc
= keyChainRef
;
710 ctx
->accessCreds
= accessCreds
;
713 #endif /* ST_KEYCHAIN_ENABLE && ST_MANAGES_TRUSTED_ROOTS */
716 SSLSetPeerID (SSLContext
*ctx
,
722 /* copy peerId to context->peerId */
728 if(sslIsSessionActive(ctx
)) {
729 /* can't do this with an active session */
732 SSLFreeBuffer(&ctx
->peerID
, &ctx
->sysCtx
);
733 serr
= SSLAllocBuffer(&ctx
->peerID
, peerIDLen
, &ctx
->sysCtx
);
735 return sslErrToOsStatus(serr
);
737 memmove(ctx
->peerID
.data
, peerID
, peerIDLen
);
742 SSLGetPeerID (SSLContextRef ctx
,
746 *peerID
= ctx
->peerID
.data
; // may be NULL
747 *peerIDLen
= ctx
->peerID
.length
;
752 SSLGetNegotiatedCipher (SSLContextRef ctx
,
753 SSLCipherSuite
*cipherSuite
)
758 if(!sslIsSessionActive(ctx
)) {
761 *cipherSuite
= (SSLCipherSuite
)ctx
->selectedCipher
;
766 * Add an acceptable distinguished name.
767 * FIXME - this looks like a big hole in the SSLRef code;
768 * acceptableDNList is set here and in SSLProcessCertificateRequest();
769 * it's used and sent to a client in SSLEncodeCertificateRequest();
770 * but the list is never used to decide what certs to send!
772 * Also FIXME - this allocation of dnBufs is preposterous. The
773 * SSLBufs can never get freed. Why not just allocate the
774 * raw DNListElems? Sheesh.
779 SSLAddDistinguishedName(SSLContext
*ctx
, SSLBuffer derDN
)
784 if ((err
= SSLAllocBuffer(&dnBuf
, sizeof(DNListElem
), &ctx
->sysCtx
)) != 0)
786 dn
= (DNListElem
*)dnBuf
.data
;
787 if ((err
= SSLAllocBuffer(&dn
->derDN
, derDN
.length
, &ctx
->sysCtx
)) != 0)
788 { SSLFreeBuffer(&dnBuf
, &ctx
->sysCtx
);
791 memcpy(dn
->derDN
.data
, derDN
.data
, derDN
.length
);
792 dn
->next
= ctx
->acceptableDNList
;
793 ctx
->acceptableDNList
= dn
;
796 #endif /* not used */
799 * Request peer certificates. Valid anytime, subsequent to
800 * a handshake attempt.
803 SSLGetPeerCertificates (SSLContextRef ctx
,
807 CFMutableArrayRef ca
;
809 SecCertificateRef cfd
;
812 SSLCertificate
*scert
;
820 * Copy peerCert, a chain of SSLCertificates, to a CFArray of
821 * CFDataRefs, each of which is one DER-encoded cert.
823 numCerts
= SSLGetCertificateChainLength(ctx
->peerCert
);
827 ca
= CFArrayCreateMutable(kCFAllocatorDefault
,
828 (CFIndex
)numCerts
, &kCFTypeArrayCallBacks
);
834 * Caller gets leaf cert first, the opposite of the way we store them.
836 scert
= ctx
->peerCert
;
837 for(i
=0; i
<numCerts
; i
++) {
838 CASSERT(scert
!= NULL
); /* else SSLGetCertificateChainLength
840 SSLBUF_TO_CSSM(&scert
->derCert
, &certData
);
841 ortn
= SecCertificateCreateFromData(&certData
,
843 CSSM_CERT_ENCODING_DER
,
849 /* insert at head of array */
850 CFArrayInsertValueAtIndex(ca
, 0, cfd
);