2 * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
21 * @APPLE_LICENSE_HEADER_END@
25 * sslContext.c - SSLContext accessors
28 #include "SecureTransport.h"
30 #include "SSLRecordInternal.h"
31 #include "SecureTransportPriv.h"
32 #include "appleSession.h"
34 #include "sslCipherSpecs.h"
35 #include "sslContext.h"
36 #include "sslCrypto.h"
38 #include "sslDigests.h"
39 #include "sslKeychain.h"
40 #include "sslMemory.h"
43 #include <AssertMacros.h>
44 #include <CoreFoundation/CFData.h>
45 #include <CoreFoundation/CFPreferences.h>
46 #include <Security/SecCertificate.h>
47 #include <Security/SecCertificatePriv.h>
48 #include <Security/SecTrust.h>
49 #include <Security/SecTrustSettingsPriv.h>
50 #include <Security/oidsalg.h>
51 #include "utilities/SecCFRelease.h"
56 #include <Security/SecCertificateInternal.h>
58 #include <Security/oidsalg.h>
59 #include <Security/oidscert.h>
60 #include <Security/SecTrustSettingsPriv.h>
64 static void sslFreeDnList(
67 DNListElem
*dn
, *nextDN
;
69 dn
= ctx
->acceptableDNList
;
72 SSLFreeBuffer(&dn
->derDN
);
77 ctx
->acceptableDNList
= NULL
;
81 Boolean
sslIsSessionActive(const SSLContext
*ctx
)
85 case SSL_HdskStateUninit
:
86 case SSL_HdskStateServerUninit
:
87 case SSL_HdskStateClientUninit
:
88 case SSL_HdskStateGracefulClose
:
89 case SSL_HdskStateErrorClose
:
97 * Minimum and maximum supported versions
99 //#define MINIMUM_STREAM_VERSION SSL_Version_2_0 /* Disabled */
100 #define MINIMUM_STREAM_VERSION SSL_Version_3_0
101 #define MAXIMUM_STREAM_VERSION TLS_Version_1_2
102 #define MINIMUM_DATAGRAM_VERSION DTLS_Version_1_0
104 /* This should be changed when we start supporting DTLS_Version_1_x */
105 #define MAXIMUM_DATAGRAM_VERSION DTLS_Version_1_0
107 #define SSL_ENABLE_ECDSA_SIGN_AUTH 0
108 #define SSL_ENABLE_RSA_FIXED_ECDH_AUTH 0
109 #define SSL_ENABLE_ECDSA_FIXED_ECDH_AUTH 0
111 #define DEFAULT_DTLS_TIMEOUT 1
112 #define DEFAULT_DTLS_MTU 1400
113 #define MIN_ALLOWED_DTLS_MTU 64 /* this ensure than there will be no integer
114 underflow when calculating max write size */
116 static CFTypeID kSSLContextTypeID
;
117 int kSplitDefaultValue
;
118 bool kAllowServerIdentityChangeDefaultValue
;
120 static void _sslContextDestroy(CFTypeRef arg
);
121 static Boolean
_sslContextEqual(CFTypeRef a
, CFTypeRef b
);
122 static CFHashCode
_sslContextHash(CFTypeRef arg
);
123 static CFStringRef
_sslContextDescribe(CFTypeRef arg
);
125 static void _SSLContextReadDefault()
127 /* 0 = disabled, 1 = split every write, 2 = split second and subsequent writes */
128 /* Enabled by default, this make cause some interop issues, see <rdar://problem/12307662> and <rdar://problem/12323307> */
129 const int defaultSplitDefaultValue
= 2;
131 //sudo defaults write /Library/Preferences/com.apple.security SSLWriteSplit -int 0
132 CFTypeRef value
= (CFTypeRef
)CFPreferencesCopyValue(CFSTR("SSLWriteSplit"),
133 CFSTR("com.apple.security"),
134 kCFPreferencesAnyUser
,
135 kCFPreferencesCurrentHost
);
137 if (CFGetTypeID(value
) == CFBooleanGetTypeID())
138 kSplitDefaultValue
= CFBooleanGetValue((CFBooleanRef
)value
) ? 1 : 0;
139 else if (CFGetTypeID(value
) == CFNumberGetTypeID()) {
140 if (!CFNumberGetValue((CFNumberRef
)value
, kCFNumberIntType
, &kSplitDefaultValue
))
141 kSplitDefaultValue
= defaultSplitDefaultValue
;
143 if (kSplitDefaultValue
< 0 || kSplitDefaultValue
> 2) {
144 kSplitDefaultValue
= defaultSplitDefaultValue
;
149 kSplitDefaultValue
= defaultSplitDefaultValue
;
153 /* 0 = disallowed, 1 = allowed */
154 /* Disallowed by default */
155 const bool defaultValue
= false;
157 //sudo defaults write /Library/Preferences/com.apple.security SSLAllowServerIdentityChange -bool YES
158 value
= (CFTypeRef
)CFPreferencesCopyValue(CFSTR("SSLAllowServerIdentityChange"),
159 CFSTR("com.apple.security"),
160 kCFPreferencesAnyUser
,
161 kCFPreferencesCurrentHost
);
163 if (CFGetTypeID(value
) == CFBooleanGetTypeID())
164 kAllowServerIdentityChangeDefaultValue
= CFBooleanGetValue((CFBooleanRef
)value
);
165 else if (CFGetTypeID(value
) == CFNumberGetTypeID()) {
167 if (!CFNumberGetValue((CFNumberRef
)value
, kCFNumberIntType
, &localValue
)) {
168 kAllowServerIdentityChangeDefaultValue
= defaultValue
;
170 kAllowServerIdentityChangeDefaultValue
= localValue
;
176 kAllowServerIdentityChangeDefaultValue
= defaultValue
;
180 static void _SSLContextRegisterClass()
182 static const CFRuntimeClass kSSLContextRegisterClass
= {
184 "SSLContext", /* class name */
187 _sslContextDestroy
, /* dealloc */
188 _sslContextEqual
, /* equal */
189 _sslContextHash
, /* hash */
190 NULL
, /* copyFormattingDesc */
191 _sslContextDescribe
/* copyDebugDesc */
194 kSSLContextTypeID
= _CFRuntimeRegisterClass(&kSSLContextRegisterClass
);
198 SSLContextGetTypeID(void)
200 static pthread_once_t sOnce
= PTHREAD_ONCE_INIT
;
201 pthread_once(&sOnce
, _SSLContextRegisterClass
);
202 return kSSLContextTypeID
;
207 SSLNewContext (Boolean isServer
,
208 SSLContextRef
*contextPtr
) /* RETURNED */
210 if(contextPtr
== NULL
) {
214 *contextPtr
= SSLCreateContext(kCFAllocatorDefault
, isServer
?kSSLServerSide
:kSSLClientSide
, kSSLStreamType
);
216 if (*contextPtr
== NULL
)
217 return errSecAllocate
;
219 return errSecSuccess
;
222 SSLContextRef
SSLCreateContext(CFAllocatorRef alloc
, SSLProtocolSide protocolSide
, SSLConnectionType connectionType
)
226 ctx
= SSLCreateContextWithRecordFuncs(alloc
, protocolSide
, connectionType
, &SSLRecordLayerInternal
);
231 ctx
->recCtx
= SSLCreateInternalRecordLayer(connectionType
);
232 if(ctx
->recCtx
==NULL
) {
240 SSLContextRef
SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc
, SSLProtocolSide protocolSide
, SSLConnectionType connectionType
, const struct SSLRecordFuncs
*recFuncs
)
242 OSStatus serr
= errSecSuccess
;
243 SSLContext
*ctx
= (SSLContext
*) _CFRuntimeCreateInstance(alloc
, SSLContextGetTypeID(), sizeof(SSLContext
) - sizeof(CFRuntimeBase
), NULL
);
249 /* subsequent errors to errOut: */
250 memset(((uint8_t*) ctx
) + sizeof(CFRuntimeBase
), 0, sizeof(SSLContext
) - sizeof(CFRuntimeBase
));
252 ctx
->state
= SSL_HdskStateUninit
;
253 ctx
->timeout_duration
= DEFAULT_DTLS_TIMEOUT
;
254 ctx
->clientCertState
= kSSLClientCertNone
;
256 ctx
->minProtocolVersion
= MINIMUM_STREAM_VERSION
;
257 ctx
->maxProtocolVersion
= MAXIMUM_STREAM_VERSION
;
260 ctx
->dtlsCookie
.data
= NULL
;
261 ctx
->dtlsCookie
.length
= 0;
262 ctx
->hdskMessageSeq
= 0;
263 ctx
->hdskMessageSeqNext
= 0;
264 ctx
->mtu
= DEFAULT_DTLS_MTU
;
266 ctx
->negProtocolVersion
= SSL_Version_Undetermined
;
269 ctx
->protocolSide
= protocolSide
;
270 /* Default value so we can send and receive hello msgs */
271 ctx
->sslTslCalls
= &Ssl3Callouts
;
273 ctx
->recFuncs
= recFuncs
;
275 /* Initialize the cipher state to NULL_WITH_NULL_NULL */
276 ctx
->selectedCipher
= TLS_NULL_WITH_NULL_NULL
;
277 InitCipherSpecParams(ctx
);
279 /* this gets init'd on first call to SSLHandshake() */
280 ctx
->validCipherSuites
= NULL
;
281 ctx
->numValidCipherSuites
= 0;
283 ctx
->numValidNonSSLv2Suites
= 0;
286 ctx
->peerDomainName
= NULL
;
287 ctx
->peerDomainNameLen
= 0;
289 #ifdef USE_CDSA_CRYPTO
290 /* attach to CSP, CL, TP */
291 serr
= attachToAll(ctx
);
295 #endif /* USE_CDSA_CRYPTO */
297 /* Initial cert verify state: verify with default system roots */
298 ctx
->enableCertVerify
= true;
300 /* Default for RSA blinding is ENABLED */
301 ctx
->rsaBlindingEnable
= true;
303 /* Default for sending one-byte app data record is DISABLED */
304 ctx
->oneByteRecordEnable
= false;
306 /* Default for allowing server identity change on renegotiation is FALSE */
307 ctx
->allowServerIdentityChange
= false;
309 /* Consult global system preference for default behavior:
310 * 0 = disabled, 1 = split every write, 2 = split second and subsequent writes
311 * (caller can override by setting kSSLSessionOptionSendOneByteRecord)
313 static pthread_once_t sReadDefault
= PTHREAD_ONCE_INIT
;
314 pthread_once(&sReadDefault
, _SSLContextReadDefault
);
315 if (kSplitDefaultValue
> 0)
316 ctx
->oneByteRecordEnable
= true;
317 if (kAllowServerIdentityChangeDefaultValue
>0)
318 ctx
->allowServerIdentityChange
= true;
320 /* default for anonymous ciphers is DISABLED */
321 ctx
->anonCipherEnable
= false;
323 ctx
->breakOnServerAuth
= false;
324 ctx
->breakOnCertRequest
= false;
325 ctx
->breakOnClientAuth
= false;
326 ctx
->signalServerAuth
= false;
327 ctx
->signalCertRequest
= false;
328 ctx
->signalClientAuth
= false;
331 * Initial/default set of ECDH curves
333 ctx
->ecdhNumCurves
= SSL_ECDSA_NUM_CURVES
;
334 ctx
->ecdhCurves
[0] = SSL_Curve_secp256r1
;
335 ctx
->ecdhCurves
[1] = SSL_Curve_secp384r1
;
336 ctx
->ecdhCurves
[2] = SSL_Curve_secp521r1
;
338 ctx
->ecdhPeerCurve
= SSL_Curve_None
; /* until we negotiate one */
339 ctx
->negAuthType
= SSLClientAuthNone
; /* ditto */
341 ctx
->messageWriteQueue
= NULL
;
343 if(connectionType
==kSSLDatagramType
) {
344 ctx
->minProtocolVersion
= MINIMUM_DATAGRAM_VERSION
;
345 ctx
->maxProtocolVersion
= MAXIMUM_DATAGRAM_VERSION
;
349 ctx
->secure_renegotiation
= false;
351 if (serr
!= errSecSuccess
) {
359 SSLNewDatagramContext (Boolean isServer
,
360 SSLContextRef
*contextPtr
) /* RETURNED */
362 if (contextPtr
== NULL
)
364 *contextPtr
= SSLCreateContext(kCFAllocatorDefault
, isServer
?kSSLServerSide
:kSSLClientSide
, kSSLDatagramType
);
365 if (*contextPtr
== NULL
)
366 return errSecAllocate
;
367 return errSecSuccess
;
371 * Dispose of an SSLContext. (private)
372 * This function is invoked after our dispatch queue is safely released,
373 * or directly from SSLDisposeContext if there is no dispatch queue.
376 SSLDisposeContext (SSLContextRef context
)
378 if(context
== NULL
) {
382 return errSecSuccess
;
385 CF_RETURNS_RETAINED CFStringRef
_sslContextDescribe(CFTypeRef arg
)
387 SSLContext
* ctx
= (SSLContext
*) arg
;
392 CFStringRef result
= CFStringCreateWithFormat(kCFAllocatorDefault
, NULL
, CFSTR("<SSLContext(%p) { ... }>"), ctx
);
397 Boolean
_sslContextEqual(CFTypeRef a
, CFTypeRef b
)
402 CFHashCode
_sslContextHash(CFTypeRef arg
)
404 return (CFHashCode
) arg
;
407 void _sslContextDestroy(CFTypeRef arg
)
409 SSLContext
* ctx
= (SSLContext
*) arg
;
411 #if USE_SSLCERTIFICATE
412 sslDeleteCertificateChain(ctx
->localCert
, ctx
);
413 sslDeleteCertificateChain(ctx
->encryptCert
, ctx
);
414 sslDeleteCertificateChain(ctx
->peerCert
, ctx
);
415 ctx
->localCert
= ctx
->encryptCert
= ctx
->peerCert
= NULL
;
417 CFReleaseNull(ctx
->localCert
);
418 CFReleaseNull(ctx
->encryptCert
);
419 CFReleaseNull(ctx
->peerCert
);
420 CFReleaseNull(ctx
->trustedCerts
);
423 /* Free the last handshake message flight */
426 if(ctx
->peerSecTrust
) {
427 CFRelease(ctx
->peerSecTrust
);
428 ctx
->peerSecTrust
= NULL
;
430 SSLFreeBuffer(&ctx
->sessionTicket
);
433 SSLFreeBuffer(&ctx
->dhParamsEncoded
);
434 #ifdef USE_CDSA_CRYPTO
435 sslFreeKey(ctx
->cspHand
, &ctx
->dhPrivate
, NULL
);
437 if (ctx
->secDHContext
)
438 SecDHDestroy(ctx
->secDHContext
);
439 #endif /* !USE_CDSA_CRYPTO */
440 SSLFreeBuffer(&ctx
->dhPeerPublic
);
441 SSLFreeBuffer(&ctx
->dhExchangePublic
);
442 #endif /* APPLE_DH */
444 SSLFreeBuffer(&ctx
->ecdhPeerPublic
);
445 SSLFreeBuffer(&ctx
->ecdhExchangePublic
);
447 if(ctx
->ecdhPrivCspHand
== ctx
->cspHand
) {
448 sslFreeKey(ctx
->ecdhPrivCspHand
, &ctx
->ecdhPrivate
, NULL
);
450 /* else we got this key from a SecKeyRef, no free needed */
453 /* Only destroy if we were using the internal record layer */
454 if(ctx
->recFuncs
==&SSLRecordLayerInternal
)
455 SSLDestroyInternalRecordLayer(ctx
->recCtx
);
457 CloseHash(&SSLHashSHA1
, &ctx
->shaState
);
458 CloseHash(&SSLHashMD5
, &ctx
->md5State
);
459 CloseHash(&SSLHashSHA256
, &ctx
->sha256State
);
460 CloseHash(&SSLHashSHA384
, &ctx
->sha512State
);
462 SSLFreeBuffer(&ctx
->sessionID
);
463 SSLFreeBuffer(&ctx
->peerID
);
464 SSLFreeBuffer(&ctx
->resumableSession
);
465 SSLFreeBuffer(&ctx
->preMasterSecret
);
466 SSLFreeBuffer(&ctx
->fragmentedMessageCache
);
467 SSLFreeBuffer(&ctx
->receivedDataBuffer
);
469 if(ctx
->peerDomainName
) {
470 sslFree(ctx
->peerDomainName
);
471 ctx
->peerDomainName
= NULL
;
472 ctx
->peerDomainNameLen
= 0;
475 sslFree(ctx
->validCipherSuites
);
476 ctx
->validCipherSuites
= NULL
;
477 ctx
->numValidCipherSuites
= 0;
481 * NOTE: currently, all public keys come from the CL via CSSM_CL_CertGetKeyInfo.
482 * We really don't know what CSP the CL used to generate a public key (in fact,
483 * it uses the raw CSP only to get LogicalKeySizeInBits, but we can't know
484 * that). Thus using e.g. signingKeyCsp (or any other CSP) to free
485 * signingPubKey is not tecnically accurate. However, our public keys
486 * are all raw keys, and all Apple CSPs dispose of raw keys in the same
489 sslFreeKey(ctx
->cspHand
, &ctx
->signingPubKey
, NULL
);
490 sslFreeKey(ctx
->cspHand
, &ctx
->encryptPubKey
, NULL
);
491 sslFreeKey(ctx
->peerPubKeyCsp
, &ctx
->peerPubKey
, NULL
);
493 if(ctx
->signingPrivKeyRef
) {
494 CFRelease(ctx
->signingPrivKeyRef
);
496 if(ctx
->encryptPrivKeyRef
) {
497 CFRelease(ctx
->encryptPrivKeyRef
);
499 if(ctx
->trustedCerts
) {
500 CFRelease(ctx
->trustedCerts
);
504 sslFreePubKey(&ctx
->signingPubKey
);
505 sslFreePubKey(&ctx
->encryptPubKey
);
506 sslFreePubKey(&ctx
->peerPubKey
);
507 sslFreePrivKey(&ctx
->signingPrivKeyRef
);
508 sslFreePrivKey(&ctx
->encryptPrivKeyRef
);
509 #endif /* USE_CDSA_CRYPTO */
510 CFReleaseSafe(ctx
->acceptableCAs
);
511 CFReleaseSafe(ctx
->trustedLeafCerts
);
512 CFReleaseSafe(ctx
->localCertArray
);
513 CFReleaseSafe(ctx
->encryptCertArray
);
514 CFReleaseSafe(ctx
->encryptCertArray
);
515 if(ctx
->clientAuthTypes
) {
516 sslFree(ctx
->clientAuthTypes
);
518 if(ctx
->serverSigAlgs
!= NULL
) {
519 sslFree(ctx
->serverSigAlgs
);
521 if(ctx
->clientSigAlgs
!= NULL
) {
522 sslFree(ctx
->clientSigAlgs
);
526 SSLFreeBuffer(&ctx
->ownVerifyData
);
527 SSLFreeBuffer(&ctx
->peerVerifyData
);
529 SSLFreeBuffer(&ctx
->pskIdentity
);
530 SSLFreeBuffer(&ctx
->pskSharedSecret
);
532 memset(((uint8_t*) ctx
) + sizeof(CFRuntimeBase
), 0, sizeof(SSLContext
) - sizeof(CFRuntimeBase
));
538 * Determine the state of an SSL session.
541 SSLGetSessionState (SSLContextRef context
,
542 SSLSessionState
*state
) /* RETURNED */
544 SSLSessionState rtnState
= kSSLIdle
;
546 if(context
== NULL
) {
550 switch(context
->state
) {
551 case SSL_HdskStateUninit
:
552 case SSL_HdskStateServerUninit
:
553 case SSL_HdskStateClientUninit
:
556 case SSL_HdskStateGracefulClose
:
557 rtnState
= kSSLClosed
;
559 case SSL_HdskStateErrorClose
:
560 case SSL_HdskStateNoNotifyClose
:
561 rtnState
= kSSLAborted
;
563 case SSL_HdskStateServerReady
:
564 case SSL_HdskStateClientReady
:
565 rtnState
= kSSLConnected
;
568 assert((context
->state
>= SSL_HdskStateServerHello
) &&
569 (context
->state
<= SSL_HdskStateFinished
));
570 rtnState
= kSSLHandshake
;
575 return errSecSuccess
;
579 * Set options for an SSL session.
582 SSLSetSessionOption (SSLContextRef context
,
583 SSLSessionOption option
,
586 if(context
== NULL
) {
589 if(sslIsSessionActive(context
)) {
590 /* can't do this with an active session */
594 case kSSLSessionOptionBreakOnServerAuth
:
595 context
->breakOnServerAuth
= value
;
596 context
->enableCertVerify
= !value
;
598 case kSSLSessionOptionBreakOnCertRequested
:
599 context
->breakOnCertRequest
= value
;
601 case kSSLSessionOptionBreakOnClientAuth
:
602 context
->breakOnClientAuth
= value
;
603 context
->enableCertVerify
= !value
;
605 case kSSLSessionOptionSendOneByteRecord
:
606 context
->oneByteRecordEnable
= value
;
608 case kSSLSessionOptionFalseStart
:
609 context
->falseStartEnabled
= value
;
611 case kSSLSessionOptionAllowServerIdentityChange
:
612 context
->allowServerIdentityChange
= value
;
618 return errSecSuccess
;
622 * Determine current value for the specified option in an SSL session.
625 SSLGetSessionOption (SSLContextRef context
,
626 SSLSessionOption option
,
629 if(context
== NULL
|| value
== NULL
) {
633 case kSSLSessionOptionBreakOnServerAuth
:
634 *value
= context
->breakOnServerAuth
;
636 case kSSLSessionOptionBreakOnCertRequested
:
637 *value
= context
->breakOnCertRequest
;
639 case kSSLSessionOptionBreakOnClientAuth
:
640 *value
= context
->breakOnClientAuth
;
642 case kSSLSessionOptionSendOneByteRecord
:
643 *value
= context
->oneByteRecordEnable
;
645 case kSSLSessionOptionFalseStart
:
646 *value
= context
->falseStartEnabled
;
652 return errSecSuccess
;
656 SSLSetRecordContext (SSLContextRef ctx
,
657 SSLRecordContextRef recCtx
)
662 if(sslIsSessionActive(ctx
)) {
663 /* can't do this with an active session */
666 ctx
->recCtx
= recCtx
;
667 return errSecSuccess
;
670 /* Those two trampolines are used to make the connetion between
671 the record layer IO callbacks and the user provided IO callbacks.
672 Those are currently necessary because the record layer read/write callbacks
673 have different prototypes that the user callbacks advertised in the API.
674 They have different prototypes because the record layer callback have to build in kernelland.
676 This situation is not desirable. So we should figure out a way to get rid of them.
678 static int IORead(SSLIOConnectionRef connection
,
683 SSLContextRef ctx
= connection
;
686 rc
= ctx
->ioCtx
.read(ctx
->ioCtx
.ioRef
, data
, dataLength
);
688 /* We may need to translate error codes at this layer */
689 if(rc
==errSSLWouldBlock
) {
690 rc
=errSSLRecordWouldBlock
;
696 static int IOWrite(SSLIOConnectionRef connection
,
701 SSLContextRef ctx
= connection
;
703 rc
= ctx
->ioCtx
.write(ctx
->ioCtx
.ioRef
, data
, dataLength
);
705 /* We may need to translate error codes at this layer */
706 if(rc
==errSSLWouldBlock
) {
707 rc
=errSSLRecordWouldBlock
;
714 SSLSetIOFuncs (SSLContextRef ctx
,
715 SSLReadFunc readFunc
,
716 SSLWriteFunc writeFunc
)
721 if(ctx
->recFuncs
!=&SSLRecordLayerInternal
) {
722 /* Can Only do this with the internal record layer */
726 if(sslIsSessionActive(ctx
)) {
727 /* can't do this with an active session */
731 ctx
->ioCtx
.read
=readFunc
;
732 ctx
->ioCtx
.write
=writeFunc
;
734 return SSLSetInternalRecordLayerIOFuncs(ctx
->recCtx
, IORead
, IOWrite
);
738 SSLSetConnection (SSLContextRef ctx
,
739 SSLConnectionRef connection
)
744 if(ctx
->recFuncs
!=&SSLRecordLayerInternal
) {
745 /* Can Only do this with the internal record layer */
749 if(sslIsSessionActive(ctx
)) {
750 /* can't do this with an active session */
754 /* Need to keep a copy of it this layer for the Get function */
755 ctx
->ioCtx
.ioRef
= connection
;
757 return SSLSetInternalRecordLayerConnection(ctx
->recCtx
, ctx
);
761 SSLGetConnection (SSLContextRef ctx
,
762 SSLConnectionRef
*connection
)
764 if((ctx
== NULL
) || (connection
== NULL
)) {
767 *connection
= ctx
->ioCtx
.ioRef
;
768 return errSecSuccess
;
772 SSLSetPeerDomainName (SSLContextRef ctx
,
773 const char *peerName
,
779 if(sslIsSessionActive(ctx
)) {
780 /* can't do this with an active session */
784 /* free possible existing name */
785 if(ctx
->peerDomainName
) {
786 sslFree(ctx
->peerDomainName
);
790 ctx
->peerDomainName
= (char *)sslMalloc(peerNameLen
);
791 if(ctx
->peerDomainName
== NULL
) {
792 return errSecAllocate
;
794 memmove(ctx
->peerDomainName
, peerName
, peerNameLen
);
795 ctx
->peerDomainNameLen
= peerNameLen
;
796 return errSecSuccess
;
800 * Determine the buffer size needed for SSLGetPeerDomainName().
803 SSLGetPeerDomainNameLength (SSLContextRef ctx
,
804 size_t *peerNameLen
) // RETURNED
809 *peerNameLen
= ctx
->peerDomainNameLen
;
810 return errSecSuccess
;
814 SSLGetPeerDomainName (SSLContextRef ctx
,
815 char *peerName
, // returned here
816 size_t *peerNameLen
) // IN/OUT
821 if(*peerNameLen
< ctx
->peerDomainNameLen
) {
822 return errSSLBufferOverflow
;
824 memmove(peerName
, ctx
->peerDomainName
, ctx
->peerDomainNameLen
);
825 *peerNameLen
= ctx
->peerDomainNameLen
;
826 return errSecSuccess
;
830 SSLSetDatagramHelloCookie (SSLContextRef ctx
,
840 if(!ctx
->isDTLS
) return errSecParam
;
842 if((ctx
== NULL
) || (cookieLen
>32)) {
845 if(sslIsSessionActive(ctx
)) {
846 /* can't do this with an active session */
850 /* free possible existing cookie */
851 if(ctx
->dtlsCookie
.data
) {
852 SSLFreeBuffer(&ctx
->dtlsCookie
);
856 if((err
=SSLAllocBuffer(&ctx
->dtlsCookie
, cookieLen
)))
859 memmove(ctx
->dtlsCookie
.data
, cookie
, cookieLen
);
860 return errSecSuccess
;
864 SSLSetMaxDatagramRecordSize (SSLContextRef ctx
,
868 if(ctx
== NULL
) return errSecParam
;
869 if(!ctx
->isDTLS
) return errSecParam
;
870 if(maxSize
< MIN_ALLOWED_DTLS_MTU
) return errSecParam
;
874 return errSecSuccess
;
878 SSLGetMaxDatagramRecordSize (SSLContextRef ctx
,
881 if(ctx
== NULL
) return errSecParam
;
882 if(!ctx
->isDTLS
) return errSecParam
;
886 return errSecSuccess
;
891 Keys to to math below:
893 A DTLS record looks like this: | header (13 bytes) | fragment |
895 For Null cipher, fragment is clear text as follows:
898 For block cipher, fragment size must be a multiple of the cipher block size, and is the
899 encryption of the following plaintext :
900 | IV (1 block) | content | MAC | padding (0 to 255 bytes) | Padlen (1 byte) |
902 The maximum content length in that case is achieved for 0 padding bytes.
907 SSLGetDatagramWriteSize (SSLContextRef ctx
,
910 if(ctx
== NULL
) return errSecParam
;
911 if(!ctx
->isDTLS
) return errSecParam
;
912 if(bufSize
== NULL
) return errSecParam
;
914 size_t max_fragment_size
= ctx
->mtu
-13; /* 13 = dtls record header */
916 SSLCipherSpecParams
*currCipher
= &ctx
->selectedCipherSpecParams
;
918 size_t blockSize
= currCipher
->blockSize
;
919 size_t macSize
= currCipher
->macSize
;
922 /* max_fragment_size must be a multiple of blocksize */
923 max_fragment_size
= max_fragment_size
& ~(blockSize
-1);
924 max_fragment_size
-= blockSize
; /* 1 block for IV */
925 max_fragment_size
-= 1; /* 1 byte for pad length */
928 /* less the mac size */
929 max_fragment_size
-= macSize
;
931 /* Thats just a sanity check */
932 assert(max_fragment_size
<ctx
->mtu
);
934 *bufSize
= max_fragment_size
;
936 return errSecSuccess
;
939 static SSLProtocolVersion
SSLProtocolToProtocolVersion(SSLProtocol protocol
) {
941 case kSSLProtocol2
: return SSL_Version_2_0
;
942 case kSSLProtocol3
: return SSL_Version_3_0
;
943 case kTLSProtocol1
: return TLS_Version_1_0
;
944 case kTLSProtocol11
: return TLS_Version_1_1
;
945 case kTLSProtocol12
: return TLS_Version_1_2
;
946 case kDTLSProtocol1
: return DTLS_Version_1_0
;
947 default: return SSL_Version_Undetermined
;
951 /* concert between private SSLProtocolVersion and public SSLProtocol */
952 static SSLProtocol
SSLProtocolVersionToProtocol(SSLProtocolVersion version
)
955 case SSL_Version_2_0
: return kSSLProtocol2
;
956 case SSL_Version_3_0
: return kSSLProtocol3
;
957 case TLS_Version_1_0
: return kTLSProtocol1
;
958 case TLS_Version_1_1
: return kTLSProtocol11
;
959 case TLS_Version_1_2
: return kTLSProtocol12
;
960 case DTLS_Version_1_0
: return kDTLSProtocol1
;
962 sslErrorLog("SSLProtocolVersionToProtocol: bad prot (%04x)\n",
965 case SSL_Version_Undetermined
: return kSSLProtocolUnknown
;
970 SSLSetProtocolVersionMin (SSLContextRef ctx
,
971 SSLProtocol minVersion
)
973 if(ctx
== NULL
) return errSecParam
;
975 SSLProtocolVersion version
= SSLProtocolToProtocolVersion(minVersion
);
977 if (version
> MINIMUM_DATAGRAM_VERSION
||
978 version
< MAXIMUM_DATAGRAM_VERSION
)
979 return errSSLIllegalParam
;
980 if (version
< ctx
->maxProtocolVersion
)
981 ctx
->maxProtocolVersion
= version
;
983 if (version
< MINIMUM_STREAM_VERSION
|| version
> MAXIMUM_STREAM_VERSION
)
984 return errSSLIllegalParam
;
985 if (version
> ctx
->maxProtocolVersion
)
986 ctx
->maxProtocolVersion
= version
;
988 ctx
->minProtocolVersion
= version
;
990 return errSecSuccess
;
994 SSLGetProtocolVersionMin (SSLContextRef ctx
,
995 SSLProtocol
*minVersion
)
997 if(ctx
== NULL
) return errSecParam
;
999 *minVersion
= SSLProtocolVersionToProtocol(ctx
->minProtocolVersion
);
1000 return errSecSuccess
;
1004 SSLSetProtocolVersionMax (SSLContextRef ctx
,
1005 SSLProtocol maxVersion
)
1007 if(ctx
== NULL
) return errSecParam
;
1009 SSLProtocolVersion version
= SSLProtocolToProtocolVersion(maxVersion
);
1011 if (version
> MINIMUM_DATAGRAM_VERSION
||
1012 version
< MAXIMUM_DATAGRAM_VERSION
)
1013 return errSSLIllegalParam
;
1014 if (version
> ctx
->minProtocolVersion
)
1015 ctx
->minProtocolVersion
= version
;
1017 if (version
< MINIMUM_STREAM_VERSION
|| version
> MAXIMUM_STREAM_VERSION
)
1018 return errSSLIllegalParam
;
1019 if (version
< ctx
->minProtocolVersion
)
1020 ctx
->minProtocolVersion
= version
;
1022 ctx
->maxProtocolVersion
= version
;
1024 return errSecSuccess
;
1028 SSLGetProtocolVersionMax (SSLContextRef ctx
,
1029 SSLProtocol
*maxVersion
)
1031 if(ctx
== NULL
) return errSecParam
;
1033 *maxVersion
= SSLProtocolVersionToProtocol(ctx
->maxProtocolVersion
);
1034 return errSecSuccess
;
1037 #define max(x,y) ((x)<(y)?(y):(x))
1040 SSLSetProtocolVersionEnabled(SSLContextRef ctx
,
1041 SSLProtocol protocol
,
1047 if(sslIsSessionActive(ctx
) || ctx
->isDTLS
) {
1048 /* Can't do this with an active session, nor with a DTLS session */
1049 return errSecBadReq
;
1051 if (protocol
== kSSLProtocolAll
) {
1053 ctx
->minProtocolVersion
= MINIMUM_STREAM_VERSION
;
1054 ctx
->maxProtocolVersion
= MAXIMUM_STREAM_VERSION
;
1056 ctx
->minProtocolVersion
= SSL_Version_Undetermined
;
1057 ctx
->maxProtocolVersion
= SSL_Version_Undetermined
;
1060 SSLProtocolVersion version
= SSLProtocolToProtocolVersion(protocol
);
1062 if (version
< MINIMUM_STREAM_VERSION
|| version
> MAXIMUM_STREAM_VERSION
) {
1065 if (version
> ctx
->maxProtocolVersion
) {
1066 ctx
->maxProtocolVersion
= version
;
1067 if (ctx
->minProtocolVersion
== SSL_Version_Undetermined
)
1068 ctx
->minProtocolVersion
= version
;
1070 if (version
< ctx
->minProtocolVersion
) {
1071 ctx
->minProtocolVersion
= version
;
1074 if (version
< SSL_Version_2_0
|| version
> MAXIMUM_STREAM_VERSION
) {
1077 /* Disabling a protocol version now resets the minimum acceptable
1078 * version to the next higher version. This means it's no longer
1079 * possible to enable a discontiguous set of protocol versions.
1081 SSLProtocolVersion nextVersion
;
1083 case SSL_Version_2_0
:
1084 nextVersion
= SSL_Version_3_0
;
1086 case SSL_Version_3_0
:
1087 nextVersion
= TLS_Version_1_0
;
1089 case TLS_Version_1_0
:
1090 nextVersion
= TLS_Version_1_1
;
1092 case TLS_Version_1_1
:
1093 nextVersion
= TLS_Version_1_2
;
1095 case TLS_Version_1_2
:
1097 nextVersion
= SSL_Version_Undetermined
;
1100 ctx
->minProtocolVersion
= max(ctx
->minProtocolVersion
, nextVersion
);
1101 if (ctx
->minProtocolVersion
> ctx
->maxProtocolVersion
) {
1102 ctx
->minProtocolVersion
= SSL_Version_Undetermined
;
1103 ctx
->maxProtocolVersion
= SSL_Version_Undetermined
;
1108 return errSecSuccess
;
1112 SSLGetProtocolVersionEnabled(SSLContextRef ctx
,
1113 SSLProtocol protocol
,
1114 Boolean
*enable
) /* RETURNED */
1120 /* Can't do this with a DTLS session */
1121 return errSecBadReq
;
1127 case kTLSProtocol11
:
1128 case kTLSProtocol12
:
1130 SSLProtocolVersion version
= SSLProtocolToProtocolVersion(protocol
);
1131 *enable
= (ctx
->minProtocolVersion
<= version
1132 && ctx
->maxProtocolVersion
>= version
);
1135 case kSSLProtocolAll
:
1136 *enable
= (ctx
->minProtocolVersion
<= MINIMUM_STREAM_VERSION
1137 && ctx
->maxProtocolVersion
>= MAXIMUM_STREAM_VERSION
);
1142 return errSecSuccess
;
1147 SSLSetProtocolVersion (SSLContextRef ctx
,
1148 SSLProtocol version
)
1153 if(sslIsSessionActive(ctx
) || ctx
->isDTLS
) {
1154 /* Can't do this with an active session, nor with a DTLS session */
1155 return errSecBadReq
;
1160 /* this tells us to do our best, up to 3.0 */
1161 ctx
->minProtocolVersion
= MINIMUM_STREAM_VERSION
;
1162 ctx
->maxProtocolVersion
= SSL_Version_3_0
;
1164 case kSSLProtocol3Only
:
1165 ctx
->minProtocolVersion
= SSL_Version_3_0
;
1166 ctx
->maxProtocolVersion
= SSL_Version_3_0
;
1169 /* this tells us to do our best, up to TLS, but allows 3.0 */
1170 ctx
->minProtocolVersion
= MINIMUM_STREAM_VERSION
;
1171 ctx
->maxProtocolVersion
= TLS_Version_1_0
;
1173 case kTLSProtocol1Only
:
1174 ctx
->minProtocolVersion
= TLS_Version_1_0
;
1175 ctx
->maxProtocolVersion
= TLS_Version_1_0
;
1177 case kTLSProtocol11
:
1178 /* This tells us to do our best, up to TLS 1.1, currently also
1179 allows 3.0 or TLS 1.0 */
1180 ctx
->minProtocolVersion
= MINIMUM_STREAM_VERSION
;
1181 ctx
->maxProtocolVersion
= TLS_Version_1_1
;
1183 case kTLSProtocol12
:
1184 case kSSLProtocolAll
:
1185 case kSSLProtocolUnknown
:
1186 /* This tells us to do our best, up to TLS 1.2, currently also
1187 allows 3.0 or TLS 1.0 or TLS 1.1 */
1188 ctx
->minProtocolVersion
= MINIMUM_STREAM_VERSION
;
1189 ctx
->maxProtocolVersion
= MAXIMUM_STREAM_VERSION
;
1195 return errSecSuccess
;
1200 SSLGetProtocolVersion (SSLContextRef ctx
,
1201 SSLProtocol
*protocol
) /* RETURNED */
1206 /* translate array of booleans to public value; not all combinations
1207 * are legal (i.e., meaningful) for this call */
1208 if (ctx
->maxProtocolVersion
== MAXIMUM_STREAM_VERSION
) {
1209 if(ctx
->minProtocolVersion
== MINIMUM_STREAM_VERSION
) {
1210 /* traditional 'all enabled' */
1211 *protocol
= kSSLProtocolAll
;
1212 return errSecSuccess
;
1214 } else if (ctx
->maxProtocolVersion
== TLS_Version_1_1
) {
1215 if(ctx
->minProtocolVersion
== MINIMUM_STREAM_VERSION
) {
1216 /* traditional 'all enabled' */
1217 *protocol
= kTLSProtocol11
;
1218 return errSecSuccess
;
1220 } else if (ctx
->maxProtocolVersion
== TLS_Version_1_0
) {
1221 if(ctx
->minProtocolVersion
== MINIMUM_STREAM_VERSION
) {
1222 /* TLS1.1 and below enabled */
1223 *protocol
= kTLSProtocol1
;
1224 return errSecSuccess
;
1225 } else if(ctx
->minProtocolVersion
== TLS_Version_1_0
) {
1226 *protocol
= kTLSProtocol1Only
;
1228 } else if(ctx
->maxProtocolVersion
== SSL_Version_3_0
) {
1229 if(ctx
->minProtocolVersion
== MINIMUM_STREAM_VERSION
) {
1230 /* Could also return kSSLProtocol3Only since
1231 MINIMUM_STREAM_VERSION == SSL_Version_3_0. */
1232 *protocol
= kSSLProtocol3
;
1233 return errSecSuccess
;
1241 SSLGetNegotiatedProtocolVersion (SSLContextRef ctx
,
1242 SSLProtocol
*protocol
) /* RETURNED */
1247 *protocol
= SSLProtocolVersionToProtocol(ctx
->negProtocolVersion
);
1248 return errSecSuccess
;
1252 SSLSetEnableCertVerify (SSLContextRef ctx
,
1253 Boolean enableVerify
)
1258 sslCertDebug("SSLSetEnableCertVerify %s",
1259 enableVerify
? "true" : "false");
1260 if(sslIsSessionActive(ctx
)) {
1261 /* can't do this with an active session */
1262 return errSecBadReq
;
1264 ctx
->enableCertVerify
= enableVerify
;
1265 return errSecSuccess
;
1269 SSLGetEnableCertVerify (SSLContextRef ctx
,
1270 Boolean
*enableVerify
)
1275 *enableVerify
= ctx
->enableCertVerify
;
1276 return errSecSuccess
;
1280 SSLSetAllowsExpiredCerts(SSLContextRef ctx
,
1281 Boolean allowExpired
)
1286 sslCertDebug("SSLSetAllowsExpiredCerts %s",
1287 allowExpired
? "true" : "false");
1288 if(sslIsSessionActive(ctx
)) {
1289 /* can't do this with an active session */
1290 return errSecBadReq
;
1292 ctx
->allowExpiredCerts
= allowExpired
;
1293 return errSecSuccess
;
1297 SSLGetAllowsExpiredCerts (SSLContextRef ctx
,
1298 Boolean
*allowExpired
)
1303 *allowExpired
= ctx
->allowExpiredCerts
;
1304 return errSecSuccess
;
1308 SSLSetAllowsExpiredRoots(SSLContextRef ctx
,
1309 Boolean allowExpired
)
1314 sslCertDebug("SSLSetAllowsExpiredRoots %s",
1315 allowExpired
? "true" : "false");
1316 if(sslIsSessionActive(ctx
)) {
1317 /* can't do this with an active session */
1318 return errSecBadReq
;
1320 ctx
->allowExpiredRoots
= allowExpired
;
1321 return errSecSuccess
;
1325 SSLGetAllowsExpiredRoots (SSLContextRef ctx
,
1326 Boolean
*allowExpired
)
1331 *allowExpired
= ctx
->allowExpiredRoots
;
1332 return errSecSuccess
;
1335 OSStatus
SSLSetAllowsAnyRoot(
1342 sslCertDebug("SSLSetAllowsAnyRoot %s", anyRoot
? "true" : "false");
1343 ctx
->allowAnyRoot
= anyRoot
;
1344 return errSecSuccess
;
1348 SSLGetAllowsAnyRoot(
1355 *anyRoot
= ctx
->allowAnyRoot
;
1356 return errSecSuccess
;
1359 #if !TARGET_OS_IPHONE
1360 /* obtain the system roots sets for this app, policy SSL */
1361 static OSStatus
sslDefaultSystemRoots(
1363 CFArrayRef
*systemRoots
) // created and RETURNED
1366 return SecTrustSettingsCopyQualifiedCerts(&CSSMOID_APPLE_TP_SSL
,
1367 ctx
->peerDomainName
,
1368 (uint32_t)ctx
->peerDomainNameLen
,
1369 (ctx
->protocolSide
== kSSLServerSide
) ?
1370 /* server verifies, client encrypts */
1371 CSSM_KEYUSE_VERIFY
: CSSM_KEYUSE_ENCRYPT
,
1374 #endif /* OS X only */
1377 SSLSetTrustedRoots (SSLContextRef ctx
,
1378 CFArrayRef trustedRoots
,
1379 Boolean replaceExisting
)
1381 #ifdef USE_CDSA_CRYPTO
1385 if(sslIsSessionActive(ctx
)) {
1386 /* can't do this with an active session */
1387 return errSecBadReq
;
1390 if(replaceExisting
) {
1391 /* trivial case - retain the new, throw out the old. */
1393 CFRetain(trustedRoots
);
1394 CFReleaseSafe(ctx
->trustedCerts
);
1395 ctx
->trustedCerts
= trustedRoots
;
1396 return errSecSuccess
;
1399 /* adding new trusted roots - to either our existing set, or the system set */
1400 CFArrayRef existingRoots
= NULL
;
1402 if(ctx
->trustedCerts
!= NULL
) {
1403 /* we'll release these as we exit */
1404 existingRoots
= ctx
->trustedCerts
;
1407 /* get system set for this app, policy SSL */
1408 ortn
= sslDefaultSystemRoots(ctx
, &existingRoots
);
1410 CFReleaseSafe(existingRoots
);
1415 /* Create a new root array with caller's roots first */
1416 CFMutableArrayRef newRoots
= CFArrayCreateMutableCopy(NULL
, 0, trustedRoots
);
1417 CFRange existRange
= { 0, CFArrayGetCount(existingRoots
) };
1418 CFArrayAppendArray(newRoots
, existingRoots
, existRange
);
1419 CFRelease(existingRoots
);
1420 ctx
->trustedCerts
= newRoots
;
1421 return errSecSuccess
;
1424 if (sslIsSessionActive(ctx
)) {
1425 /* can't do this with an active session */
1426 return errSecBadReq
;
1428 sslCertDebug("SSLSetTrustedRoot numCerts %d replaceExist %s",
1429 (int)CFArrayGetCount(trustedRoots
), replaceExisting
? "true" : "false");
1431 if (replaceExisting
) {
1432 ctx
->trustedCertsOnly
= true;
1433 CFReleaseNull(ctx
->trustedCerts
);
1436 if (ctx
->trustedCerts
) {
1437 CFIndex count
= CFArrayGetCount(trustedRoots
);
1438 CFRange range
= { 0, count
};
1439 CFArrayAppendArray(ctx
->trustedCerts
, trustedRoots
, range
);
1441 require(ctx
->trustedCerts
=
1442 CFArrayCreateMutableCopy(kCFAllocatorDefault
, 0, trustedRoots
),
1446 return errSecSuccess
;
1449 return errSecAllocate
;
1450 #endif /* !USE_CDSA_CRYPTO */
1454 SSLCopyTrustedRoots (SSLContextRef ctx
,
1455 CFArrayRef
*trustedRoots
) /* RETURNED */
1457 if(ctx
== NULL
|| trustedRoots
== NULL
) {
1460 if(ctx
->trustedCerts
!= NULL
) {
1461 *trustedRoots
= ctx
->trustedCerts
;
1462 CFRetain(ctx
->trustedCerts
);
1463 return errSecSuccess
;
1465 #if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE))
1466 /* use default system roots */
1467 return sslDefaultSystemRoots(ctx
, trustedRoots
);
1469 *trustedRoots
= NULL
;
1470 return errSecSuccess
;
1475 SSLSetTrustedLeafCertificates (SSLContextRef ctx
,
1476 CFArrayRef trustedCerts
)
1481 if(sslIsSessionActive(ctx
)) {
1482 /* can't do this with an active session */
1483 return errSecBadReq
;
1486 if(ctx
->trustedLeafCerts
) {
1487 CFRelease(ctx
->trustedLeafCerts
);
1489 ctx
->trustedLeafCerts
= trustedCerts
;
1490 CFRetain(trustedCerts
);
1491 return errSecSuccess
;
1495 SSLCopyTrustedLeafCertificates (SSLContextRef ctx
,
1496 CFArrayRef
*trustedCerts
) /* RETURNED */
1501 if(ctx
->trustedLeafCerts
!= NULL
) {
1502 *trustedCerts
= ctx
->trustedLeafCerts
;
1503 CFRetain(ctx
->trustedCerts
);
1504 return errSecSuccess
;
1506 *trustedCerts
= NULL
;
1507 return errSecSuccess
;
1511 SSLSetClientSideAuthenticate (SSLContext
*ctx
,
1512 SSLAuthenticate auth
)
1517 if(sslIsSessionActive(ctx
)) {
1518 /* can't do this with an active session */
1519 return errSecBadReq
;
1521 ctx
->clientAuth
= auth
;
1523 case kNeverAuthenticate
:
1524 ctx
->tryClientAuth
= false;
1526 case kAlwaysAuthenticate
:
1527 case kTryAuthenticate
:
1528 ctx
->tryClientAuth
= true;
1531 return errSecSuccess
;
1535 SSLGetClientSideAuthenticate (SSLContext
*ctx
,
1536 SSLAuthenticate
*auth
) /* RETURNED */
1538 if(ctx
== NULL
|| auth
== NULL
) {
1541 *auth
= ctx
->clientAuth
;
1542 return errSecSuccess
;
1546 SSLGetClientCertificateState (SSLContextRef ctx
,
1547 SSLClientCertificateState
*clientState
)
1552 *clientState
= ctx
->clientCertState
;
1553 return errSecSuccess
;
1557 SSLSetCertificate (SSLContextRef ctx
,
1558 CFArrayRef certRefs
)
1561 * -- free localCerts if we have any
1562 * -- Get raw cert data, convert to ctx->localCert
1563 * -- get pub, priv keys from certRef[0]
1564 * -- validate cert chain
1570 /* can't do this with an active session */
1571 if(sslIsSessionActive(ctx
) &&
1572 /* kSSLClientCertRequested implies client side */
1573 (ctx
->clientCertState
!= kSSLClientCertRequested
))
1575 return errSecBadReq
;
1577 CFReleaseNull(ctx
->localCertArray
);
1578 /* changing the client cert invalidates negotiated auth type */
1579 ctx
->negAuthType
= SSLClientAuthNone
;
1580 if(certRefs
== NULL
) {
1581 return errSecSuccess
; // we have cleared the cert, as requested
1583 OSStatus ortn
= parseIncomingCerts(ctx
,
1586 &ctx
->signingPubKey
,
1587 &ctx
->signingPrivKeyRef
,
1588 &ctx
->ourSignerAlg
);
1589 if(ortn
== errSecSuccess
) {
1590 ctx
->localCertArray
= certRefs
;
1592 /* client cert was changed, must update auth type */
1593 ortn
= SSLUpdateNegotiatedClientAuthType(ctx
);
1599 SSLSetEncryptionCertificate (SSLContextRef ctx
,
1600 CFArrayRef certRefs
)
1603 * -- free encryptCert if we have any
1604 * -- Get raw cert data, convert to ctx->encryptCert
1605 * -- get pub, priv keys from certRef[0]
1606 * -- validate cert chain
1611 if(sslIsSessionActive(ctx
)) {
1612 /* can't do this with an active session */
1613 return errSecBadReq
;
1615 CFReleaseNull(ctx
->encryptCertArray
);
1616 OSStatus ortn
= parseIncomingCerts(ctx
,
1619 &ctx
->encryptPubKey
,
1620 &ctx
->encryptPrivKeyRef
,
1621 NULL
); /* Signer alg */
1622 if(ortn
== errSecSuccess
) {
1623 ctx
->encryptCertArray
= certRefs
;
1629 OSStatus
SSLGetCertificate(SSLContextRef ctx
,
1630 CFArrayRef
*certRefs
)
1635 *certRefs
= ctx
->localCertArray
;
1636 return errSecSuccess
;
1639 OSStatus
SSLGetEncryptionCertificate(SSLContextRef ctx
,
1640 CFArrayRef
*certRefs
)
1645 *certRefs
= ctx
->encryptCertArray
;
1646 return errSecSuccess
;
1650 SSLSetPeerID (SSLContext
*ctx
,
1656 /* copy peerId to context->peerId */
1662 if(sslIsSessionActive(ctx
) &&
1663 /* kSSLClientCertRequested implies client side */
1664 (ctx
->clientCertState
!= kSSLClientCertRequested
))
1666 return errSecBadReq
;
1668 SSLFreeBuffer(&ctx
->peerID
);
1669 serr
= SSLAllocBuffer(&ctx
->peerID
, peerIDLen
);
1673 memmove(ctx
->peerID
.data
, peerID
, peerIDLen
);
1674 return errSecSuccess
;
1678 SSLGetPeerID (SSLContextRef ctx
,
1679 const void **peerID
,
1682 *peerID
= ctx
->peerID
.data
; // may be NULL
1683 *peerIDLen
= ctx
->peerID
.length
;
1684 return errSecSuccess
;
1688 SSLGetNegotiatedCipher (SSLContextRef ctx
,
1689 SSLCipherSuite
*cipherSuite
)
1694 if(!sslIsSessionActive(ctx
)) {
1695 return errSecBadReq
;
1697 *cipherSuite
= (SSLCipherSuite
)ctx
->selectedCipher
;
1698 return errSecSuccess
;
1702 * Add an acceptable distinguished name (client authentication only).
1705 SSLAddDistinguishedName(
1716 if(sslIsSessionActive(ctx
)) {
1717 return errSecBadReq
;
1720 dn
= (DNListElem
*)sslMalloc(sizeof(DNListElem
));
1722 return errSecAllocate
;
1724 if ((err
= SSLAllocBuffer(&dn
->derDN
, derDNLen
)))
1726 memcpy(dn
->derDN
.data
, derDN
, derDNLen
);
1727 dn
->next
= ctx
->acceptableDNList
;
1728 ctx
->acceptableDNList
= dn
;
1729 return errSecSuccess
;
1732 /* single-cert version of SSLSetCertificateAuthorities() */
1734 sslAddCA(SSLContextRef ctx
,
1735 SecCertificateRef cert
)
1737 OSStatus ortn
= errSecParam
;
1739 /* Get subject from certificate. */
1740 #if TARGET_OS_IPHONE
1741 CFDataRef subjectName
= NULL
;
1742 subjectName
= SecCertificateCopySubjectSequence(cert
);
1743 require(subjectName
, errOut
);
1745 CSSM_DATA_PTR subjectName
= NULL
;
1746 ortn
= SecCertificateCopyFirstFieldValue(cert
, &CSSMOID_X509V1SubjectNameStd
, &subjectName
);
1747 require_noerr(ortn
, errOut
);
1750 /* add to acceptableCAs as cert, creating array if necessary */
1751 if(ctx
->acceptableCAs
== NULL
) {
1752 require(ctx
->acceptableCAs
= CFArrayCreateMutable(NULL
, 0,
1753 &kCFTypeArrayCallBacks
), errOut
);
1754 if(ctx
->acceptableCAs
== NULL
) {
1755 return errSecAllocate
;
1758 CFArrayAppendValue(ctx
->acceptableCAs
, cert
);
1760 /* then add this cert's subject name to acceptableDNList */
1761 #if TARGET_OS_IPHONE
1762 ortn
= SSLAddDistinguishedName(ctx
,
1763 CFDataGetBytePtr(subjectName
),
1764 CFDataGetLength(subjectName
));
1766 ortn
= SSLAddDistinguishedName(ctx
, subjectName
->Data
, subjectName
->Length
);
1770 #if TARGET_OS_IPHONE
1771 CFReleaseSafe(subjectName
);
1777 * Add a SecCertificateRef, or a CFArray of them, to a server's list
1778 * of acceptable Certificate Authorities (CAs) to present to the client
1779 * when client authentication is performed.
1782 SSLSetCertificateAuthorities(SSLContextRef ctx
,
1783 CFTypeRef certificateOrArray
,
1784 Boolean replaceExisting
)
1787 OSStatus ortn
= errSecSuccess
;
1789 if((ctx
== NULL
) || sslIsSessionActive(ctx
) ||
1790 (ctx
->protocolSide
!= kSSLServerSide
)) {
1793 if(replaceExisting
) {
1795 if(ctx
->acceptableCAs
) {
1796 CFRelease(ctx
->acceptableCAs
);
1797 ctx
->acceptableCAs
= NULL
;
1800 /* else appending */
1802 itemType
= CFGetTypeID(certificateOrArray
);
1803 if(itemType
== SecCertificateGetTypeID()) {
1805 ortn
= sslAddCA(ctx
, (SecCertificateRef
)certificateOrArray
);
1807 else if(itemType
== CFArrayGetTypeID()) {
1808 CFArrayRef cfa
= (CFArrayRef
)certificateOrArray
;
1809 CFIndex numCerts
= CFArrayGetCount(cfa
);
1812 /* array of certs */
1813 for(dex
=0; dex
<numCerts
; dex
++) {
1814 SecCertificateRef cert
= (SecCertificateRef
)CFArrayGetValueAtIndex(cfa
, dex
);
1815 if(CFGetTypeID(cert
) != SecCertificateGetTypeID()) {
1818 ortn
= sslAddCA(ctx
, cert
);
1832 * Obtain the certificates specified in SSLSetCertificateAuthorities(),
1833 * if any. Returns a NULL array if SSLSetCertificateAuthorities() has not
1835 * Caller must CFRelease the returned array.
1838 SSLCopyCertificateAuthorities(SSLContextRef ctx
,
1839 CFArrayRef
*certificates
) /* RETURNED */
1841 if((ctx
== NULL
) || (certificates
== NULL
)) {
1844 if(ctx
->acceptableCAs
== NULL
) {
1845 *certificates
= NULL
;
1846 return errSecSuccess
;
1848 *certificates
= ctx
->acceptableCAs
;
1849 CFRetain(ctx
->acceptableCAs
);
1850 return errSecSuccess
;
1855 * Obtain the list of acceptable distinguished names as provided by
1856 * a server (if the SSLCotextRef is configured as a client), or as
1857 * specified by SSLSetCertificateAuthorities() (if the SSLContextRef
1858 * is configured as a server).
1861 SSLCopyDistinguishedNames (SSLContextRef ctx
,
1864 CFMutableArrayRef outArray
= NULL
;
1867 if((ctx
== NULL
) || (names
== NULL
)) {
1870 if(ctx
->acceptableDNList
== NULL
) {
1872 return errSecSuccess
;
1874 outArray
= CFArrayCreateMutable(NULL
, 0, &kCFTypeArrayCallBacks
);
1875 dn
= ctx
->acceptableDNList
;
1877 CFDataRef cfDn
= CFDataCreate(NULL
, dn
->derDN
.data
, dn
->derDN
.length
);
1878 CFArrayAppendValue(outArray
, cfDn
);
1883 return errSecSuccess
;
1888 * Request peer certificates. Valid anytime, subsequent to
1889 * a handshake attempt.
1890 * Common code for SSLGetPeerCertificates() and SSLCopyPeerCertificates().
1891 * TODO: the 'legacy' argument is not used anymore.
1894 sslCopyPeerCertificates (SSLContextRef ctx
,
1902 #ifdef USE_SSLCERTIFICATE
1904 CFMutableArrayRef ca
;
1906 SecCertificateRef cfd
;
1909 SSLCertificate
*scert
;
1914 * Copy peerCert, a chain of SSLCertificates, to a CFArray of
1915 * CFDataRefs, each of which is one DER-encoded cert.
1917 numCerts
= SSLGetCertificateChainLength(ctx
->peerCert
);
1919 return errSecSuccess
;
1921 ca
= CFArrayCreateMutable(kCFAllocatorDefault
,
1922 (CFIndex
)numCerts
, &kCFTypeArrayCallBacks
);
1924 return errSecAllocate
;
1928 * Caller gets leaf cert first, the opposite of the way we store them.
1930 scert
= ctx
->peerCert
;
1931 for(i
=0; (unsigned)i
<numCerts
; i
++) {
1932 assert(scert
!= NULL
); /* else SSLGetCertificateChainLength
1934 SSLBUF_TO_CSSM(&scert
->derCert
, &certData
);
1935 ortn
= SecCertificateCreateFromData(&certData
,
1937 CSSM_CERT_ENCODING_DER
,
1943 /* insert at head of array */
1944 CFArrayInsertValueAtIndex(ca
, 0, cfd
);
1946 /* skip for legacy SSLGetPeerCertificates() */
1949 scert
= scert
->next
;
1954 if (!ctx
->peerCert
) {
1956 return errSecBadReq
;
1959 CFArrayRef ca
= CFArrayCreateCopy(kCFAllocatorDefault
, ctx
->peerCert
);
1962 return errSecAllocate
;
1966 CFIndex ix
, count
= CFArrayGetCount(ca
);
1967 for (ix
= 0; ix
< count
; ++ix
) {
1968 CFRetain(CFArrayGetValueAtIndex(ca
, ix
));
1973 return errSecSuccess
;
1977 SSLCopyPeerCertificates (SSLContextRef ctx
,
1980 return sslCopyPeerCertificates(ctx
, certs
, false);
1983 #if !TARGET_OS_IPHONE
1984 // Permanently removing from iOS, keep for OSX (deprecated), removed from headers.
1985 // <rdar://problem/14215831> Mailsmith Crashes While Getting New Mail Under Mavericks Developer Preview
1987 SSLGetPeerCertificates (SSLContextRef ctx
,
1990 SSLGetPeerCertificates (SSLContextRef ctx
,
1993 return sslCopyPeerCertificates(ctx
, certs
, true);
1998 * Specify Diffie-Hellman parameters. Optional; if we are configured to allow
1999 * for D-H ciphers and a D-H cipher is negotiated, and this function has not
2000 * been called, a set of process-wide parameters will be calculated. However
2001 * that can take a long time (30 seconds).
2003 OSStatus
SSLSetDiffieHellmanParams(
2005 const void *dhParams
,
2012 if(sslIsSessionActive(ctx
)) {
2013 return errSecBadReq
;
2015 SSLFreeBuffer(&ctx
->dhParamsEncoded
);
2016 #if !USE_CDSA_CRYPTO
2017 if (ctx
->secDHContext
)
2018 SecDHDestroy(ctx
->secDHContext
);
2022 ortn
= SSLCopyBufferFromData(dhParams
, dhParamsLen
,
2023 &ctx
->dhParamsEncoded
);
2027 #endif /* APPLE_DH */
2031 * Return parameter block specified in SSLSetDiffieHellmanParams.
2032 * Returned data is not copied and belongs to the SSLContextRef.
2034 OSStatus
SSLGetDiffieHellmanParams(
2036 const void **dhParams
,
2037 size_t *dhParamsLen
)
2043 *dhParams
= ctx
->dhParamsEncoded
.data
;
2044 *dhParamsLen
= ctx
->dhParamsEncoded
.length
;
2045 return errSecSuccess
;
2047 return errSecUnimplemented
;
2048 #endif /* APPLE_DH */
2051 OSStatus
SSLSetRsaBlinding(
2058 ctx
->rsaBlindingEnable
= blinding
;
2059 return errSecSuccess
;
2062 OSStatus
SSLGetRsaBlinding(
2069 *blinding
= ctx
->rsaBlindingEnable
;
2070 return errSecSuccess
;
2076 SecTrustRef
*trust
) /* RETURNED */
2078 OSStatus status
= errSecSuccess
;
2079 if (ctx
== NULL
|| trust
== NULL
)
2082 /* Create a SecTrustRef if this was a resumed session and we
2083 didn't have one yet. */
2084 if (!ctx
->peerSecTrust
&& ctx
->peerCert
) {
2085 status
= sslCreateSecTrust(ctx
, ctx
->peerCert
, true,
2086 &ctx
->peerSecTrust
);
2089 *trust
= ctx
->peerSecTrust
;
2090 if (ctx
->peerSecTrust
)
2091 CFRetain(ctx
->peerSecTrust
);
2096 OSStatus
SSLGetPeerSecTrust(
2098 SecTrustRef
*trust
) /* RETURNED */
2100 OSStatus status
= errSecSuccess
;
2101 if (ctx
== NULL
|| trust
== NULL
)
2104 /* Create a SecTrustRef if this was a resumed session and we
2105 didn't have one yet. */
2106 if (!ctx
->peerSecTrust
&& ctx
->peerCert
) {
2107 status
= sslCreateSecTrust(ctx
, ctx
->peerCert
, true,
2108 &ctx
->peerSecTrust
);
2111 *trust
= ctx
->peerSecTrust
;
2115 OSStatus
SSLInternalMasterSecret(
2117 void *secret
, // mallocd by caller, SSL_MASTER_SECRET_SIZE
2118 size_t *secretSize
) // in/out
2120 if((ctx
== NULL
) || (secret
== NULL
) || (secretSize
== NULL
)) {
2123 if(*secretSize
< SSL_MASTER_SECRET_SIZE
) {
2126 memmove(secret
, ctx
->masterSecret
, SSL_MASTER_SECRET_SIZE
);
2127 *secretSize
= SSL_MASTER_SECRET_SIZE
;
2128 return errSecSuccess
;
2131 OSStatus
SSLInternalServerRandom(
2133 void *randBuf
, // mallocd by caller, SSL_CLIENT_SRVR_RAND_SIZE
2134 size_t *randSize
) // in/out
2136 if((ctx
== NULL
) || (randBuf
== NULL
) || (randSize
== NULL
)) {
2139 if(*randSize
< SSL_CLIENT_SRVR_RAND_SIZE
) {
2142 memmove(randBuf
, ctx
->serverRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
2143 *randSize
= SSL_CLIENT_SRVR_RAND_SIZE
;
2144 return errSecSuccess
;
2147 OSStatus
SSLInternalClientRandom(
2149 void *randBuf
, // mallocd by caller, SSL_CLIENT_SRVR_RAND_SIZE
2150 size_t *randSize
) // in/out
2152 if((ctx
== NULL
) || (randBuf
== NULL
) || (randSize
== NULL
)) {
2155 if(*randSize
< SSL_CLIENT_SRVR_RAND_SIZE
) {
2158 memmove(randBuf
, ctx
->clientRandom
, SSL_CLIENT_SRVR_RAND_SIZE
);
2159 *randSize
= SSL_CLIENT_SRVR_RAND_SIZE
;
2160 return errSecSuccess
;
2163 /* This is used by EAP 802.1x */
2164 OSStatus
SSLGetCipherSizes(
2167 size_t *symmetricKeySize
,
2170 const SSLCipherSpecParams
*currCipher
;
2172 if((ctx
== NULL
) || (digestSize
== NULL
) ||
2173 (symmetricKeySize
== NULL
) || (ivSize
== NULL
)) {
2176 currCipher
= &ctx
->selectedCipherSpecParams
;
2177 *digestSize
= currCipher
->macSize
;
2178 *symmetricKeySize
= currCipher
->keySize
;
2179 *ivSize
= currCipher
->ivSize
;
2180 return errSecSuccess
;
2184 SSLGetResumableSessionInfo(
2186 Boolean
*sessionWasResumed
, // RETURNED
2187 void *sessionID
, // RETURNED, mallocd by caller
2188 size_t *sessionIDLength
) // IN/OUT
2190 if((ctx
== NULL
) || (sessionWasResumed
== NULL
) ||
2191 (sessionID
== NULL
) || (sessionIDLength
== NULL
) ||
2192 (*sessionIDLength
< MAX_SESSION_ID_LENGTH
)) {
2195 if(ctx
->sessionMatch
) {
2196 *sessionWasResumed
= true;
2197 if(ctx
->sessionID
.length
> *sessionIDLength
) {
2198 /* really should never happen - means ID > 32 */
2201 if(ctx
->sessionID
.length
) {
2203 * Note PAC-based session resumption can result in sessionMatch
2206 memmove(sessionID
, ctx
->sessionID
.data
, ctx
->sessionID
.length
);
2208 *sessionIDLength
= ctx
->sessionID
.length
;
2211 *sessionWasResumed
= false;
2212 *sessionIDLength
= 0;
2214 return errSecSuccess
;
2218 * Get/set enable of anonymous ciphers. Default is enabled.
2221 SSLSetAllowAnonymousCiphers(
2228 if(sslIsSessionActive(ctx
)) {
2229 return errSecBadReq
;
2231 if(ctx
->validCipherSuites
!= NULL
) {
2232 /* SSLSetEnabledCiphers() has already been called */
2233 return errSecBadReq
;
2235 ctx
->anonCipherEnable
= enable
;
2236 return errSecSuccess
;
2240 SSLGetAllowAnonymousCiphers(
2244 if((ctx
== NULL
) || (enable
== NULL
)) {
2247 if(sslIsSessionActive(ctx
)) {
2248 return errSecBadReq
;
2250 *enable
= ctx
->anonCipherEnable
;
2251 return errSecSuccess
;
2255 * Override the default session cache timeout for a cache entry created for
2256 * the current session.
2259 SSLSetSessionCacheTimeout(
2261 uint32_t timeoutInSeconds
)
2266 ctx
->sessionCacheTimeout
= timeoutInSeconds
;
2267 return errSecSuccess
;
2271 * Register a callback for obtaining the master_secret when performing
2272 * PAC-based session resumption.
2275 SSLInternalSetMasterSecretFunction(
2277 SSLInternalMasterSecretFunction mFunc
,
2278 const void *arg
) /* opaque to SecureTransport; app-specific */
2283 ctx
->masterSecretCallback
= mFunc
;
2284 ctx
->masterSecretArg
= arg
;
2285 return errSecSuccess
;
2289 * Provide an opaque SessionTicket for use in PAC-based session
2290 * resumption. Client side only. The provided ticket is sent in
2291 * the ClientHello message as a SessionTicket extension.
2293 * We won't reject this on the server side, but server-side support
2294 * for PAC-based session resumption is currently enabled for
2295 * Development builds only. To fully support this for server side,
2296 * besides the rudimentary support that's here for Development builds,
2297 * we'd need a getter for the session ticket, so the app code can
2298 * access the SessionTicket when its SSLInternalMasterSecretFunction
2299 * callback is called.
2301 OSStatus
SSLInternalSetSessionTicket(
2304 size_t ticketLength
)
2309 if(sslIsSessionActive(ctx
)) {
2310 /* can't do this with an active session */
2311 return errSecBadReq
;
2313 if(ticketLength
> 0xffff) {
2314 /* extension data encoded with a 2-byte length! */
2317 SSLFreeBuffer(&ctx
->sessionTicket
);
2318 return SSLCopyBufferFromData(ticket
, ticketLength
, &ctx
->sessionTicket
);
2322 * ECDSA curve accessors.
2326 * Obtain the SSL_ECDSA_NamedCurve negotiated during a handshake.
2327 * Returns errSecParam if no ECDH-related ciphersuite was negotiated.
2329 OSStatus
SSLGetNegotiatedCurve(
2331 SSL_ECDSA_NamedCurve
*namedCurve
) /* RETURNED */
2333 if((ctx
== NULL
) || (namedCurve
== NULL
)) {
2336 if(ctx
->ecdhPeerCurve
== SSL_Curve_None
) {
2339 *namedCurve
= ctx
->ecdhPeerCurve
;
2340 return errSecSuccess
;
2344 * Obtain the number of currently enabled SSL_ECDSA_NamedCurves.
2346 OSStatus
SSLGetNumberOfECDSACurves(
2348 unsigned *numCurves
) /* RETURNED */
2350 if((ctx
== NULL
) || (numCurves
== NULL
)) {
2353 *numCurves
= ctx
->ecdhNumCurves
;
2354 return errSecSuccess
;
2358 * Obtain the ordered list of currently enabled SSL_ECDSA_NamedCurves.
2360 OSStatus
SSLGetECDSACurves(
2362 SSL_ECDSA_NamedCurve
*namedCurves
, /* RETURNED */
2363 unsigned *numCurves
) /* IN/OUT */
2365 if((ctx
== NULL
) || (namedCurves
== NULL
) || (numCurves
== NULL
)) {
2368 if(*numCurves
< ctx
->ecdhNumCurves
) {
2371 memmove(namedCurves
, ctx
->ecdhCurves
,
2372 (ctx
->ecdhNumCurves
* sizeof(SSL_ECDSA_NamedCurve
)));
2373 *numCurves
= ctx
->ecdhNumCurves
;
2374 return errSecSuccess
;
2378 * Specify ordered list of allowable named curves.
2380 OSStatus
SSLSetECDSACurves(
2382 const SSL_ECDSA_NamedCurve
*namedCurves
,
2385 if((ctx
== NULL
) || (namedCurves
== NULL
) || (numCurves
== 0)) {
2388 if(numCurves
> SSL_ECDSA_NUM_CURVES
) {
2391 if(sslIsSessionActive(ctx
)) {
2392 /* can't do this with an active session */
2393 return errSecBadReq
;
2395 memmove(ctx
->ecdhCurves
, namedCurves
, (numCurves
* sizeof(SSL_ECDSA_NamedCurve
)));
2396 ctx
->ecdhNumCurves
= numCurves
;
2397 return errSecSuccess
;
2401 * Obtain the number of client authentication mechanisms specified by
2402 * the server in its Certificate Request message.
2403 * Returns errSecParam if server hasn't sent a Certificate Request message
2404 * (i.e., client certificate state is kSSLClientCertNone).
2406 OSStatus
SSLGetNumberOfClientAuthTypes(
2410 if((ctx
== NULL
) || (ctx
->clientCertState
== kSSLClientCertNone
)) {
2413 *numTypes
= ctx
->numAuthTypes
;
2414 return errSecSuccess
;
2418 * Obtain the client authentication mechanisms specified by
2419 * the server in its Certificate Request message.
2420 * Caller allocates returned array and specifies its size (in
2421 * SSLClientAuthenticationTypes) in *numType on entry; *numTypes
2422 * is the actual size of the returned array on successful return.
2424 OSStatus
SSLGetClientAuthTypes(
2426 SSLClientAuthenticationType
*authTypes
, /* RETURNED */
2427 unsigned *numTypes
) /* IN/OUT */
2429 if((ctx
== NULL
) || (ctx
->clientCertState
== kSSLClientCertNone
)) {
2432 memmove(authTypes
, ctx
->clientAuthTypes
,
2433 ctx
->numAuthTypes
* sizeof(SSLClientAuthenticationType
));
2434 *numTypes
= ctx
->numAuthTypes
;
2435 return errSecSuccess
;
2439 * Obtain the SSLClientAuthenticationType actually performed.
2440 * Only valid if client certificate state is kSSLClientCertSent
2441 * or kSSLClientCertRejected; returns errSecParam otherwise.
2443 OSStatus
SSLGetNegotiatedClientAuthType(
2445 SSLClientAuthenticationType
*authType
) /* RETURNED */
2450 *authType
= ctx
->negAuthType
;
2451 return errSecSuccess
;
2455 * Update the negotiated client authentication type.
2456 * This function may be called at any time; however, note that
2457 * the negotiated authentication type will be SSLClientAuthNone
2458 * until both of the following have taken place (in either order):
2459 * - a CertificateRequest message from the server has been processed
2460 * - a client certificate has been specified
2461 * As such, this function (only) needs to be called from (both)
2462 * SSLProcessCertificateRequest and SSLSetCertificate.
2464 OSStatus
SSLUpdateNegotiatedClientAuthType(
2471 * See if we have a signing cert that matches one of the
2472 * allowed auth types. The x509Requested flag indicates "we
2473 * have a cert that we think the server will accept".
2475 ctx
->x509Requested
= 0;
2476 ctx
->negAuthType
= SSLClientAuthNone
;
2477 if(ctx
->signingPrivKeyRef
!= NULL
) {
2478 CFIndex ourKeyAlg
= sslPubKeyGetAlgorithmID(ctx
->signingPubKey
);
2480 for(i
=0; i
<ctx
->numAuthTypes
; i
++) {
2481 switch(ctx
->clientAuthTypes
[i
]) {
2482 case SSLClientAuth_RSASign
:
2483 if(ourKeyAlg
== kSecRSAAlgorithmID
) {
2484 ctx
->x509Requested
= 1;
2485 ctx
->negAuthType
= SSLClientAuth_RSASign
;
2488 #if SSL_ENABLE_ECDSA_SIGN_AUTH
2489 case SSLClientAuth_ECDSASign
:
2491 #if SSL_ENABLE_ECDSA_FIXED_ECDH_AUTH
2492 case SSLClientAuth_ECDSAFixedECDH
:
2494 if((ourKeyAlg
== kSecECDSAAlgorithmID
) &&
2495 (ctx
->ourSignerAlg
== kSecECDSAAlgorithmID
)) {
2496 ctx
->x509Requested
= 1;
2497 ctx
->negAuthType
= ctx
->clientAuthTypes
[i
];
2500 #if SSL_ENABLE_RSA_FIXED_ECDH_AUTH
2501 case SSLClientAuth_RSAFixedECDH
:
2502 /* Odd case, we differ from our signer */
2503 if((ourKeyAlg
== kSecECDSAAlgorithmID
) &&
2504 (ctx
->ourSignerAlg
== kSecRSAAlgorithmID
)) {
2505 ctx
->x509Requested
= 1;
2506 ctx
->negAuthType
= SSLClientAuth_RSAFixedECDH
;
2511 /* None others supported */
2514 if(ctx
->x509Requested
) {
2515 sslLogNegotiateDebug("===CHOOSING authType %d", (int)ctx
->negAuthType
);
2518 } /* parsing authTypes */
2519 } /* we have a signing key */
2521 return errSecSuccess
;
2524 OSStatus
SSLGetNumberOfSignatureAlgorithms(
2526 unsigned *numSigAlgs
)
2528 if((ctx
== NULL
) || (ctx
->clientCertState
== kSSLClientCertNone
)) {
2531 *numSigAlgs
= ctx
->numServerSigAlgs
;
2532 return errSecSuccess
;
2535 OSStatus
SSLGetSignatureAlgorithms(
2537 SSLSignatureAndHashAlgorithm
*sigAlgs
, /* RETURNED */
2538 unsigned *numSigAlgs
) /* IN/OUT */
2540 if((ctx
== NULL
) || (ctx
->clientCertState
== kSSLClientCertNone
)) {
2543 memmove(sigAlgs
, ctx
->serverSigAlgs
,
2544 ctx
->numServerSigAlgs
* sizeof(SSLSignatureAndHashAlgorithm
));
2545 *numSigAlgs
= ctx
->numServerSigAlgs
;
2546 return errSecSuccess
;
2550 OSStatus
SSLSetPSKSharedSecret(SSLContextRef ctx
,
2554 if(ctx
== NULL
) return errSecParam
;
2556 if(ctx
->pskSharedSecret
.data
)
2557 SSLFreeBuffer(&ctx
->pskSharedSecret
);
2559 if(SSLCopyBufferFromData(secret
, secretLen
, &ctx
->pskSharedSecret
))
2560 return errSecAllocate
;
2562 return errSecSuccess
;
2565 OSStatus
SSLSetPSKIdentity(SSLContextRef ctx
,
2566 const void *pskIdentity
,
2567 size_t pskIdentityLen
)
2569 if((ctx
== NULL
) || (pskIdentity
== NULL
) || (pskIdentityLen
== 0)) return errSecParam
;
2571 if(ctx
->pskIdentity
.data
)
2572 SSLFreeBuffer(&ctx
->pskIdentity
);
2574 if(SSLCopyBufferFromData(pskIdentity
, pskIdentityLen
, &ctx
->pskIdentity
))
2575 return errSecAllocate
;
2577 return errSecSuccess
;
2581 OSStatus
SSLGetPSKIdentity(SSLContextRef ctx
,
2582 const void **pskIdentity
,
2583 size_t *pskIdentityLen
)
2585 if((ctx
== NULL
) || (pskIdentity
== NULL
) || (pskIdentityLen
== NULL
)) return errSecParam
;
2587 *pskIdentity
=ctx
->pskIdentity
.data
;
2588 *pskIdentityLen
=ctx
->pskIdentity
.length
;
2589 return errSecSuccess
;
2593 #ifdef USE_SSLCERTIFICATE
2596 SSLGetCertificateChainLength(const SSLCertificate
*c
)
2608 OSStatus
sslDeleteCertificateChain(
2609 SSLCertificate
*certs
,
2612 SSLCertificate
*cert
;
2613 SSLCertificate
*nextCert
;
2615 assert(ctx
!= NULL
);
2617 while(cert
!= NULL
) {
2618 nextCert
= cert
->next
;
2619 SSLFreeBuffer(&cert
->derCert
);
2623 return errSecSuccess
;
2625 #endif /* USE_SSLCERTIFICATE */