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
26 Copyright: (c) 1999 by Apple Computer, Inc., all rights reserved.
31 #include "sslContext.h"
32 #include "sslMemory.h"
33 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
34 #include "sslDigests.h"
36 #include "appleCdsa.h"
37 #include "sslKeychain.h"
39 #include "cipherSpecs.h"
40 #include "appleSession.h"
43 #include <Security/SecCertificate.h>
44 #include <Security/SecTrust.h>
46 static void sslFreeDnList(
49 DNListElem
*dn
, *nextDN
;
51 dn
= ctx
->acceptableDNList
;
54 SSLFreeBuffer(dn
->derDN
, ctx
);
59 ctx
->acceptableDNList
= NULL
;
62 static OSStatus
sslFreeTrustedRoots(
68 if((ctx
->numTrustedCerts
== 0) || (ctx
->trustedCerts
== NULL
)) {
69 /* they really should both be zero, right? */
70 assert((ctx
->numTrustedCerts
== 0) && (ctx
->trustedCerts
== NULL
));
73 for(i
=0; i
<ctx
->numTrustedCerts
; i
++) {
74 stFreeCssmData(&ctx
->trustedCerts
[i
], CSSM_FALSE
);
76 sslFree(ctx
->trustedCerts
);
78 ctx
->numTrustedCerts
= 0;
79 ctx
->trustedCerts
= NULL
;
85 * Default version enables.
87 #define DEFAULT_SSL2_ENABLE true
88 #define DEFAULT_SSL3_ENABLE true
89 #define DEFAULT_TLS1_ENABLE true
92 SSLNewContext (Boolean isServer
,
93 SSLContextRef
*contextPtr
) /* RETURNED */
98 if(contextPtr
== NULL
) {
102 ctx
= (SSLContext
*)sslMalloc(sizeof(SSLContext
));
106 /* subsequent errors to errOut: */
108 memset(ctx
, 0, sizeof(SSLContext
));
109 ctx
->state
= SSL_HdskStateUninit
;
110 ctx
->clientCertState
= kSSLClientCertNone
;
112 ctx
->versionSsl2Enable
= DEFAULT_SSL2_ENABLE
;
113 ctx
->versionSsl3Enable
= DEFAULT_SSL3_ENABLE
;
114 ctx
->versionTls1Enable
= DEFAULT_TLS1_ENABLE
;
115 ctx
->negProtocolVersion
= SSL_Version_Undetermined
;
118 ctx
->protocolSide
= SSL_ServerSide
;
121 ctx
->protocolSide
= SSL_ClientSide
;
124 /* Default value so we can send and receive hello msgs */
125 ctx
->sslTslCalls
= &Ssl3Callouts
;
127 /* Initialize the cipher state to NULL_WITH_NULL_NULL */
128 ctx
->selectedCipherSpec
= &SSL_NULL_WITH_NULL_NULL_CipherSpec
;
129 ctx
->selectedCipher
= ctx
->selectedCipherSpec
->cipherSpec
;
130 ctx
->writeCipher
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
131 ctx
->readCipher
.macRef
= ctx
->selectedCipherSpec
->macAlgorithm
;
132 ctx
->readCipher
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
133 ctx
->writeCipher
.symCipher
= ctx
->selectedCipherSpec
->cipher
;
135 /* these two are invariant */
136 ctx
->writeCipher
.encrypting
= 1;
137 ctx
->writePending
.encrypting
= 1;
139 /* this gets init'd on first call to SSLHandshake() */
140 ctx
->validCipherSpecs
= NULL
;
141 ctx
->numValidCipherSpecs
= 0;
143 ctx
->peerDomainName
= NULL
;
144 ctx
->peerDomainNameLen
= 0;
146 /* attach to CSP, CL, TP */
147 serr
= attachToAll(ctx
);
152 /* Initial cert verify state: verify with default system roots */
153 ctx
->enableCertVerify
= true;
155 /* Default for RSA blinding is ENABLED */
156 ctx
->rsaBlindingEnable
= true;
168 * Dispose of an SSLContext.
171 SSLDisposeContext (SSLContext
*ctx
)
173 WaitingRecord
*wait
, *next
;
179 sslDeleteCertificateChain(ctx
->localCert
, ctx
);
180 sslDeleteCertificateChain(ctx
->encryptCert
, ctx
);
181 sslDeleteCertificateChain(ctx
->peerCert
, ctx
);
182 ctx
->localCert
= ctx
->encryptCert
= ctx
->peerCert
= NULL
;
183 SSLFreeBuffer(ctx
->partialReadBuffer
, ctx
);
184 if(ctx
->peerSecTrust
) {
185 CFRelease(ctx
->peerSecTrust
);
186 ctx
->peerSecTrust
= NULL
;
188 wait
= ctx
->recordWriteQueue
;
190 { SSLFreeBuffer(wait
->data
, ctx
);
192 buf
.data
= (uint8
*)wait
;
193 buf
.length
= sizeof(WaitingRecord
);
194 SSLFreeBuffer(buf
, ctx
);
199 SSLFreeBuffer(ctx
->dhParamsPrime
, ctx
);
200 SSLFreeBuffer(ctx
->dhParamsGenerator
, ctx
);
201 SSLFreeBuffer(ctx
->dhParamsEncoded
, ctx
);
202 SSLFreeBuffer(ctx
->dhPeerPublic
, ctx
);
203 SSLFreeBuffer(ctx
->dhExchangePublic
, ctx
);
204 sslFreeKey(ctx
->cspHand
, &ctx
->dhPrivate
, NULL
);
205 #endif /* APPLE_DH */
207 CloseHash(SSLHashSHA1
, ctx
->shaState
, ctx
);
208 CloseHash(SSLHashMD5
, ctx
->md5State
, ctx
);
210 SSLFreeBuffer(ctx
->sessionID
, ctx
);
211 SSLFreeBuffer(ctx
->peerID
, ctx
);
212 SSLFreeBuffer(ctx
->resumableSession
, ctx
);
213 SSLFreeBuffer(ctx
->preMasterSecret
, ctx
);
214 SSLFreeBuffer(ctx
->partialReadBuffer
, ctx
);
215 SSLFreeBuffer(ctx
->fragmentedMessageCache
, ctx
);
216 SSLFreeBuffer(ctx
->receivedDataBuffer
, ctx
);
218 if(ctx
->peerDomainName
) {
219 sslFree(ctx
->peerDomainName
);
220 ctx
->peerDomainName
= NULL
;
221 ctx
->peerDomainNameLen
= 0;
223 SSLDisposeCipherSuite(&ctx
->readCipher
, ctx
);
224 SSLDisposeCipherSuite(&ctx
->writeCipher
, ctx
);
225 SSLDisposeCipherSuite(&ctx
->readPending
, ctx
);
226 SSLDisposeCipherSuite(&ctx
->writePending
, ctx
);
228 sslFree(ctx
->validCipherSpecs
);
229 ctx
->validCipherSpecs
= NULL
;
230 ctx
->numValidCipherSpecs
= 0;
233 * NOTE: currently, all public keys come from the CL via CSSM_CL_CertGetKeyInfo.
234 * We really don't know what CSP the CL used to generate a public key (in fact,
235 * it uses the raw CSP only to get LogicalKeySizeInBits, but we can't know
236 * that). Thus using e.g. signingKeyCsp (or any other CSP) to free
237 * signingPubKey is not tecnically accurate. However, our public keys
238 * are all raw keys, and all Apple CSPs dispose of raw keys in the same
241 sslFreeKey(ctx
->cspHand
, &ctx
->signingPubKey
, NULL
);
242 sslFreeKey(ctx
->cspHand
, &ctx
->encryptPubKey
, NULL
);
243 sslFreeKey(ctx
->peerPubKeyCsp
, &ctx
->peerPubKey
, NULL
);
245 if(ctx
->signingPrivKeyRef
) {
246 CFRelease(ctx
->signingPrivKeyRef
);
248 if(ctx
->encryptPrivKeyRef
) {
249 CFRelease(ctx
->encryptPrivKeyRef
);
251 sslFreeTrustedRoots(ctx
);
255 memset(ctx
, 0, sizeof(SSLContext
));
262 * Determine the state of an SSL session.
265 SSLGetSessionState (SSLContextRef context
,
266 SSLSessionState
*state
) /* RETURNED */
268 SSLSessionState rtnState
= kSSLIdle
;
270 if(context
== NULL
) {
274 switch(context
->state
) {
275 case SSL_HdskStateUninit
:
276 case SSL_HdskStateServerUninit
:
277 case SSL_HdskStateClientUninit
:
280 case SSL_HdskStateGracefulClose
:
281 rtnState
= kSSLClosed
;
283 case SSL_HdskStateErrorClose
:
284 case SSL_HdskStateNoNotifyClose
:
285 rtnState
= kSSLAborted
;
287 case SSL_HdskStateServerReady
:
288 case SSL_HdskStateClientReady
:
289 rtnState
= kSSLConnected
;
292 assert((context
->state
>= SSL_HdskStateServerHello
) &&
293 (context
->state
<= SSL2_HdskStateServerFinished
));
294 rtnState
= kSSLHandshake
;
303 SSLSetIOFuncs (SSLContextRef ctx
,
310 if(sslIsSessionActive(ctx
)) {
311 /* can't do this with an active session */
314 ctx
->ioCtx
.read
= read
;
315 ctx
->ioCtx
.write
= write
;
320 SSLSetConnection (SSLContextRef ctx
,
321 SSLConnectionRef connection
)
326 if(sslIsSessionActive(ctx
)) {
327 /* can't do this with an active session */
330 ctx
->ioCtx
.ioRef
= connection
;
335 SSLGetConnection (SSLContextRef ctx
,
336 SSLConnectionRef
*connection
)
338 if((ctx
== NULL
) || (connection
== NULL
)) {
341 *connection
= ctx
->ioCtx
.ioRef
;
346 SSLSetPeerDomainName (SSLContextRef ctx
,
347 const char *peerName
,
353 if(sslIsSessionActive(ctx
)) {
354 /* can't do this with an active session */
358 /* free possible existing name */
359 if(ctx
->peerDomainName
) {
360 sslFree(ctx
->peerDomainName
);
364 ctx
->peerDomainName
= (char *)sslMalloc(peerNameLen
);
365 if(ctx
->peerDomainName
== NULL
) {
368 memmove(ctx
->peerDomainName
, peerName
, peerNameLen
);
369 ctx
->peerDomainNameLen
= peerNameLen
;
374 * Determine the buffer size needed for SSLGetPeerDomainName().
377 SSLGetPeerDomainNameLength (SSLContextRef ctx
,
378 size_t *peerNameLen
) // RETURNED
383 *peerNameLen
= ctx
->peerDomainNameLen
;
388 SSLGetPeerDomainName (SSLContextRef ctx
,
389 char *peerName
, // returned here
390 size_t *peerNameLen
) // IN/OUT
395 if(*peerNameLen
< ctx
->peerDomainNameLen
) {
396 return errSSLBufferOverflow
;
398 memmove(peerName
, ctx
->peerDomainName
, ctx
->peerDomainNameLen
);
399 *peerNameLen
= ctx
->peerDomainNameLen
;
403 /* concert between private SSLProtocolVersion and public SSLProtocol */
404 static SSLProtocol
convertProtToExtern(SSLProtocolVersion prot
)
407 case SSL_Version_Undetermined
:
408 return kSSLProtocolUnknown
;
409 case SSL_Version_2_0
:
410 return kSSLProtocol2
;
411 case SSL_Version_3_0
:
412 return kSSLProtocol3
;
413 case TLS_Version_1_0
:
414 return kTLSProtocol1
;
416 sslErrorLog("convertProtToExtern: bad prot\n");
417 return kSSLProtocolUnknown
;
419 /* not reached but make compiler happy */
420 return kSSLProtocolUnknown
;
424 SSLSetProtocolVersionEnabled(SSLContextRef ctx
,
425 SSLProtocol protocol
,
426 Boolean enable
) /* RETURNED */
431 if(sslIsSessionActive(ctx
)) {
432 /* can't do this with an active session */
437 ctx
->versionSsl2Enable
= enable
;
440 ctx
->versionSsl3Enable
= enable
;
443 ctx
->versionTls1Enable
= enable
;
445 case kSSLProtocolAll
:
446 ctx
->versionTls1Enable
= ctx
->versionSsl3Enable
=
447 ctx
->versionSsl2Enable
= enable
;
456 SSLGetProtocolVersionEnabled(SSLContextRef ctx
,
457 SSLProtocol protocol
,
458 Boolean
*enable
) /* RETURNED */
465 *enable
= ctx
->versionSsl2Enable
;
468 *enable
= ctx
->versionSsl3Enable
;
471 *enable
= ctx
->versionTls1Enable
;
473 case kSSLProtocolAll
:
474 if(ctx
->versionTls1Enable
&& ctx
->versionSsl3Enable
&&
475 ctx
->versionSsl2Enable
) {
490 SSLSetProtocolVersion (SSLContextRef ctx
,
496 if(sslIsSessionActive(ctx
)) {
497 /* can't do this with an active session */
501 /* convert external representation to three booleans */
503 case kSSLProtocolUnknown
:
504 ctx
->versionSsl2Enable
= DEFAULT_SSL2_ENABLE
;
505 ctx
->versionSsl3Enable
= DEFAULT_SSL3_ENABLE
;
506 ctx
->versionTls1Enable
= DEFAULT_TLS1_ENABLE
;
509 ctx
->versionSsl2Enable
= true;
510 ctx
->versionSsl3Enable
= false;
511 ctx
->versionTls1Enable
= false;
514 /* this tells us to do our best, up to 3.0, but allows 2.0 */
515 ctx
->versionSsl2Enable
= true;
516 ctx
->versionSsl3Enable
= true;
517 ctx
->versionTls1Enable
= false;
519 case kSSLProtocol3Only
:
520 ctx
->versionSsl2Enable
= false;
521 ctx
->versionSsl3Enable
= true;
522 ctx
->versionTls1Enable
= false;
525 case kSSLProtocolAll
:
526 /* this tells us to do our best, up to TLS, but allows 2.0 or 3.0 */
527 ctx
->versionSsl2Enable
= true;
528 ctx
->versionSsl3Enable
= true;
529 ctx
->versionTls1Enable
= true;
531 case kTLSProtocol1Only
:
532 ctx
->versionSsl2Enable
= false;
533 ctx
->versionSsl3Enable
= false;
534 ctx
->versionTls1Enable
= true;
544 SSLGetProtocolVersion (SSLContextRef ctx
,
545 SSLProtocol
*protocol
) /* RETURNED */
551 /* translate array of booleans to public value; not all combinations
552 * are legal (i.e., meaningful) for this call */
553 if(ctx
->versionTls1Enable
) {
554 if(ctx
->versionSsl2Enable
) {
555 if(ctx
->versionSsl3Enable
) {
556 /* traditional 'all enabled' */
557 *protocol
= kTLSProtocol1
;
561 /* SSL2 true, SSL3 false, TLS1 true - invalid here */
565 else if(ctx
->versionSsl3Enable
) {
566 /* SSL2 false, SSL3 true, TLS1 true - invalid here */
570 *protocol
= kTLSProtocol1Only
;
576 if(ctx
->versionSsl3Enable
) {
577 *protocol
= ctx
->versionSsl2Enable
?
578 kSSLProtocol3
: kSSLProtocol3Only
;
581 else if(ctx
->versionSsl2Enable
) {
582 *protocol
= kSSLProtocol2
;
587 * Bogus state - no enables - the API does provide a way
588 * to get into this state. Other than this path, the app
589 * will discover this bogon when attempting to do the
590 * handshake; sslGetMaxProtVersion will detect this.
599 SSLGetNegotiatedProtocolVersion (SSLContextRef ctx
,
600 SSLProtocol
*protocol
) /* RETURNED */
605 *protocol
= convertProtToExtern(ctx
->negProtocolVersion
);
610 SSLSetEnableCertVerify (SSLContextRef ctx
,
611 Boolean enableVerify
)
616 sslCertDebug("SSLSetEnableCertVerify %s",
617 enableVerify
? "true" : "false");
618 if(sslIsSessionActive(ctx
)) {
619 /* can't do this with an active session */
622 ctx
->enableCertVerify
= enableVerify
;
627 SSLGetEnableCertVerify (SSLContextRef ctx
,
628 Boolean
*enableVerify
)
633 *enableVerify
= ctx
->enableCertVerify
;
638 SSLSetAllowsExpiredCerts(SSLContextRef ctx
,
639 Boolean allowExpired
)
644 sslCertDebug("SSLSetAllowsExpiredCerts %s",
645 allowExpired
? "true" : "false");
646 if(sslIsSessionActive(ctx
)) {
647 /* can't do this with an active session */
650 ctx
->allowExpiredCerts
= allowExpired
;
655 SSLGetAllowsExpiredCerts (SSLContextRef ctx
,
656 Boolean
*allowExpired
)
661 *allowExpired
= ctx
->allowExpiredCerts
;
666 SSLSetAllowsExpiredRoots(SSLContextRef ctx
,
667 Boolean allowExpired
)
672 sslCertDebug("SSLSetAllowsExpiredRoots %s",
673 allowExpired
? "true" : "false");
674 if(sslIsSessionActive(ctx
)) {
675 /* can't do this with an active session */
678 ctx
->allowExpiredRoots
= allowExpired
;
683 SSLGetAllowsExpiredRoots (SSLContextRef ctx
,
684 Boolean
*allowExpired
)
689 *allowExpired
= ctx
->allowExpiredRoots
;
693 OSStatus
SSLSetAllowsAnyRoot(
700 sslCertDebug("SSLSetAllowsAnyRoot %s", anyRoot
? "true" : "false");
701 ctx
->allowAnyRoot
= anyRoot
;
713 *anyRoot
= ctx
->allowAnyRoot
;
718 SSLSetTrustedRoots (SSLContextRef ctx
,
719 CFArrayRef trustedRoots
,
720 Boolean replaceExisting
)
724 unsigned numIncoming
;
726 CSSM_DATA_PTR newRoots
= NULL
;
727 const CSSM_DATA
*existAnchors
= NULL
;
728 uint32 numExistAnchors
= 0;
729 OSStatus ortn
= noErr
;
734 if(sslIsSessionActive(ctx
)) {
735 /* can't do this with an active session */
738 numCerts
= numIncoming
= CFArrayGetCount(trustedRoots
);
739 sslCertDebug("SSLSetTrustedRoot numCerts %d replaceExist %s",
740 (int)numCerts
, replaceExisting
? "true" : "false");
741 if(!replaceExisting
) {
742 if(ctx
->trustedCerts
!= NULL
) {
743 /* adding to existing store */
744 existAnchors
= ctx
->trustedCerts
;
745 numExistAnchors
= ctx
->numTrustedCerts
;
748 /* adding to system roots */
749 ortn
= SecTrustGetCSSMAnchorCertificates(&existAnchors
,
752 /* should never happen */
756 numCerts
+= numExistAnchors
;
758 newRoots
= (CSSM_DATA_PTR
)sslMalloc(numCerts
* sizeof(CSSM_DATA
));
759 memset(newRoots
, 0, numCerts
* sizeof(CSSM_DATA
));
761 /* Caller's certs first */
762 for(dex
=0, outDex
=0; dex
<numIncoming
; dex
++, outDex
++) {
764 SecCertificateRef secCert
= (SecCertificateRef
)
765 CFArrayGetValueAtIndex(trustedRoots
, dex
);
767 if(CFGetTypeID(secCert
) != SecCertificateGetTypeID()) {
768 /* elements of trustedRoots must be SecCertificateRefs */
772 ortn
= SecCertificateGetData(secCert
, &certData
);
776 stSetUpCssmData(&newRoots
[outDex
], certData
.Length
);
777 memmove(newRoots
[outDex
].Data
, certData
.Data
, certData
.Length
);
780 /* now existing roots - either ours, or the system's */
781 for(dex
=0; dex
<numExistAnchors
; dex
++, outDex
++) {
782 stSetUpCssmData(&newRoots
[outDex
], existAnchors
[dex
].Length
);
783 memmove(newRoots
[outDex
].Data
, existAnchors
[dex
].Data
,
784 existAnchors
[dex
].Length
);
787 /* success - replace context values */
788 sslFreeTrustedRoots(ctx
);
789 ctx
->numTrustedCerts
= numCerts
;
790 ctx
->trustedCerts
= newRoots
;
799 SSLGetTrustedRoots (SSLContextRef ctx
,
800 CFArrayRef
*trustedRoots
) /* RETURNED */
803 const CSSM_DATA
*certs
;
804 CFMutableArrayRef certArray
;
806 SecCertificateRef secCert
;
812 if(ctx
->trustedCerts
!= NULL
) {
814 certs
= ctx
->trustedCerts
;
815 numCerts
= ctx
->numTrustedCerts
;
818 /* use default system roots */
819 OSStatus ortn
= SecTrustGetCSSMAnchorCertificates(&certs
,
822 /* should never happen */
827 certArray
= CFArrayCreateMutable(kCFAllocatorDefault
,
828 (CFIndex
)numCerts
, &kCFTypeArrayCallBacks
);
829 if(certArray
== NULL
) {
832 for(dex
=0; dex
<numCerts
; dex
++) {
833 ortn
= SecCertificateCreateFromData(&certs
[dex
],
835 CSSM_CERT_ENCODING_DER
,
838 CFRelease(certArray
);
841 CFArrayAppendValue(certArray
, secCert
);
843 *trustedRoots
= certArray
;
848 SSLSetClientSideAuthenticate (SSLContext
*ctx
,
849 SSLAuthenticate auth
)
854 if(sslIsSessionActive(ctx
)) {
855 /* can't do this with an active session */
858 ctx
->clientAuth
= auth
;
860 case kNeverAuthenticate
:
861 ctx
->tryClientAuth
= false;
863 case kAlwaysAuthenticate
:
864 case kTryAuthenticate
:
865 ctx
->tryClientAuth
= true;
872 SSLGetClientCertificateState (SSLContextRef ctx
,
873 SSLClientCertificateState
*clientState
)
878 *clientState
= ctx
->clientCertState
;
883 SSLSetCertificate (SSLContextRef ctx
,
887 * -- free localCerts if we have any
888 * -- Get raw cert data, convert to ctx->localCert
889 * -- get pub, priv keys from certRef[0]
890 * -- validate cert chain
895 if(sslIsSessionActive(ctx
)) {
896 /* can't do this with an active session */
899 return parseIncomingCerts(ctx
,
903 &ctx
->signingPrivKeyRef
);
907 SSLSetEncryptionCertificate (SSLContextRef ctx
,
911 * -- free encryptCert if we have any
912 * -- Get raw cert data, convert to ctx->encryptCert
913 * -- get pub, priv keys from certRef[0]
914 * -- validate cert chain
919 if(sslIsSessionActive(ctx
)) {
920 /* can't do this with an active session */
923 return parseIncomingCerts(ctx
,
927 &ctx
->encryptPrivKeyRef
);
931 SSLSetPeerID (SSLContext
*ctx
,
937 /* copy peerId to context->peerId */
943 if(sslIsSessionActive(ctx
)) {
944 /* can't do this with an active session */
947 SSLFreeBuffer(ctx
->peerID
, ctx
);
948 serr
= SSLAllocBuffer(ctx
->peerID
, peerIDLen
, ctx
);
952 memmove(ctx
->peerID
.data
, peerID
, peerIDLen
);
957 SSLGetPeerID (SSLContextRef ctx
,
961 *peerID
= ctx
->peerID
.data
; // may be NULL
962 *peerIDLen
= ctx
->peerID
.length
;
967 SSLGetNegotiatedCipher (SSLContextRef ctx
,
968 SSLCipherSuite
*cipherSuite
)
973 if(!sslIsSessionActive(ctx
)) {
976 *cipherSuite
= (SSLCipherSuite
)ctx
->selectedCipher
;
981 * Add an acceptable distinguished name (client authentication only).
984 SSLAddDistinguishedName(
992 dn
= (DNListElem
*)sslMalloc(sizeof(DNListElem
));
996 if ((err
= SSLAllocBuffer(dn
->derDN
, derDNLen
, ctx
)) != 0)
998 memcpy(dn
->derDN
.data
, derDN
, derDNLen
);
999 dn
->next
= ctx
->acceptableDNList
;
1000 ctx
->acceptableDNList
= dn
;
1005 * Request peer certificates. Valid anytime, subsequent to
1006 * a handshake attempt.
1009 SSLGetPeerCertificates (SSLContextRef ctx
,
1013 CFMutableArrayRef ca
;
1015 SecCertificateRef cfd
;
1018 SSLCertificate
*scert
;
1026 * Copy peerCert, a chain of SSLCertificates, to a CFArray of
1027 * CFDataRefs, each of which is one DER-encoded cert.
1029 numCerts
= SSLGetCertificateChainLength(ctx
->peerCert
);
1033 ca
= CFArrayCreateMutable(kCFAllocatorDefault
,
1034 (CFIndex
)numCerts
, &kCFTypeArrayCallBacks
);
1040 * Caller gets leaf cert first, the opposite of the way we store them.
1042 scert
= ctx
->peerCert
;
1043 for(i
=0; (unsigned)i
<numCerts
; i
++) {
1044 assert(scert
!= NULL
); /* else SSLGetCertificateChainLength
1046 SSLBUF_TO_CSSM(&scert
->derCert
, &certData
);
1047 ortn
= SecCertificateCreateFromData(&certData
,
1049 CSSM_CERT_ENCODING_DER
,
1055 /* insert at head of array */
1056 CFArrayInsertValueAtIndex(ca
, 0, cfd
);
1057 scert
= scert
->next
;
1064 * Specify Diffie-Hellman parameters. Optional; if we are configured to allow
1065 * for D-H ciphers and a D-H cipher is negotiated, and this function has not
1066 * been called, a set of process-wide parameters will be calculated. However
1067 * that can take a long time (30 seconds).
1069 OSStatus
SSLSetDiffieHellmanParams(
1071 const void *dhParams
,
1077 if(sslIsSessionActive(ctx
)) {
1080 SSLFreeBuffer(ctx
->dhParamsPrime
, ctx
);
1081 SSLFreeBuffer(ctx
->dhParamsGenerator
, ctx
);
1082 SSLFreeBuffer(ctx
->dhParamsEncoded
, ctx
);
1085 ortn
= SSLCopyBufferFromData(dhParams
, dhParamsLen
,
1086 ctx
->dhParamsEncoded
);
1091 /* decode for use by server over the wire */
1093 sParams
.data
= (UInt8
*)dhParams
;
1094 sParams
.length
= dhParamsLen
;
1095 return sslDecodeDhParams(&sParams
, &ctx
->dhParamsPrime
,
1096 &ctx
->dhParamsGenerator
);
1100 * Return parameter block specified in SSLSetDiffieHellmanParams.
1101 * Returned data is not copied and belongs to the SSLContextRef.
1103 OSStatus
SSLGetDiffieHellmanParams(
1105 const void **dhParams
,
1106 size_t *dhParamsLen
)
1111 *dhParams
= ctx
->dhParamsEncoded
.data
;
1112 *dhParamsLen
= ctx
->dhParamsEncoded
.length
;
1116 OSStatus
SSLSetRsaBlinding(
1123 ctx
->rsaBlindingEnable
= blinding
;
1127 OSStatus
SSLGetRsaBlinding(
1134 *blinding
= ctx
->rsaBlindingEnable
;
1138 OSStatus
SSLGetPeerSecTrust(
1140 SecTrustRef
*secTrust
) /* RETURNED */
1145 *secTrust
= ctx
->peerSecTrust
;
1149 OSStatus
SSLInternalMasterSecret(
1151 void *secret
, // mallocd by caller, SSL_MASTER_SECRET_SIZE
1152 size_t *secretSize
) // in/out
1154 if((ctx
== NULL
) || (secret
== NULL
) || (secretSize
== NULL
)) {
1157 if(*secretSize
< SSL_MASTER_SECRET_SIZE
) {
1160 memmove(secret
, ctx
->masterSecret
, SSL_MASTER_SECRET_SIZE
);
1161 *secretSize
= SSL_MASTER_SECRET_SIZE
;
1165 OSStatus
SSLInternalServerRandom(
1167 void *rand
, // mallocd by caller, SSL_CLIENT_SRVR_RAND_SIZE
1168 size_t *randSize
) // in/out
1170 if((ctx
== NULL
) || (rand
== NULL
) || (randSize
== NULL
)) {
1173 if(*randSize
< SSL_CLIENT_SRVR_RAND_SIZE
) {
1176 memmove(rand
, ctx
->serverRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
1177 *randSize
= SSL_CLIENT_SRVR_RAND_SIZE
;
1181 OSStatus
SSLInternalClientRandom(
1183 void *rand
, // mallocd by caller, SSL_CLIENT_SRVR_RAND_SIZE
1184 size_t *randSize
) // in/out
1186 if((ctx
== NULL
) || (rand
== NULL
) || (randSize
== NULL
)) {
1189 if(*randSize
< SSL_CLIENT_SRVR_RAND_SIZE
) {
1192 memmove(rand
, ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
1193 *randSize
= SSL_CLIENT_SRVR_RAND_SIZE
;
1198 SSLGetResumableSessionInfo(
1200 Boolean
*sessionWasResumed
, // RETURNED
1201 void *sessionID
, // RETURNED, mallocd by caller
1202 size_t *sessionIDLength
) // IN/OUT
1204 if((ctx
== NULL
) || (sessionWasResumed
== NULL
) ||
1205 (sessionID
== NULL
) || (sessionIDLength
== NULL
) ||
1206 (*sessionIDLength
< MAX_SESSION_ID_LENGTH
)) {
1209 if(ctx
->sessionMatch
) {
1210 assert(ctx
->sessionID
.data
!= NULL
);
1211 *sessionWasResumed
= true;
1212 if(ctx
->sessionID
.length
> *sessionIDLength
) {
1213 /* really should never happen - means ID > 32 */
1216 memmove(sessionID
, ctx
->sessionID
.data
, ctx
->sessionID
.length
);
1217 *sessionIDLength
= ctx
->sessionID
.length
;
1220 *sessionWasResumed
= false;
1221 *sessionIDLength
= 0;