X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/80e2389990082500d76eb566d4946be3e786c3ef..d8f41ccd20de16f8ebe2ccc84d47bf1cb2b26bbb:/libsecurity_ssl/lib/sslContext.c diff --git a/libsecurity_ssl/lib/sslContext.c b/libsecurity_ssl/lib/sslContext.c deleted file mode 100644 index cc74aa16..00000000 --- a/libsecurity_ssl/lib/sslContext.c +++ /dev/null @@ -1,2625 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2012 Apple Inc. All Rights Reserved. - * - * @APPLE_LICENSE_HEADER_START@ - * - * This file contains Original Code and/or Modifications of Original Code - * as defined in and that are subject to the Apple Public Source License - * Version 2.0 (the 'License'). You may not use this file except in - * compliance with the License. Please obtain a copy of the License at - * http://www.opensource.apple.com/apsl/ and read it before using this - * file. - * - * The Original Code and all software distributed under the License are - * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER - * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, - * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. - * Please see the License for the specific language governing rights and - * limitations under the License. - * - * @APPLE_LICENSE_HEADER_END@ - */ - -/* - * sslContext.c - SSLContext accessors - */ - -#include "SecureTransport.h" - -#include "SSLRecordInternal.h" -#include "SecureTransportPriv.h" -#include "appleSession.h" -#include "ssl.h" -#include "sslCipherSpecs.h" -#include "sslContext.h" -#include "sslCrypto.h" -#include "sslDebug.h" -#include "sslDigests.h" -#include "sslKeychain.h" -#include "sslMemory.h" -#include "sslUtils.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include "utilities/SecCFRelease.h" -#include -#include - -#if TARGET_OS_IPHONE -#include -#else -#include -#include -#include -#endif - - -static void sslFreeDnList( - SSLContext *ctx) -{ - DNListElem *dn, *nextDN; - - dn = ctx->acceptableDNList; - while (dn) - { - SSLFreeBuffer(&dn->derDN); - nextDN = dn->next; - sslFree(dn); - dn = nextDN; - } - ctx->acceptableDNList = NULL; -} - - -Boolean sslIsSessionActive(const SSLContext *ctx) -{ - assert(ctx != NULL); - switch(ctx->state) { - case SSL_HdskStateUninit: - case SSL_HdskStateServerUninit: - case SSL_HdskStateClientUninit: - case SSL_HdskStateGracefulClose: - case SSL_HdskStateErrorClose: - return false; - default: - return true; - } -} - -/* - * Minimum and maximum supported versions - */ -//#define MINIMUM_STREAM_VERSION SSL_Version_2_0 /* Disabled */ -#define MINIMUM_STREAM_VERSION SSL_Version_3_0 -#define MAXIMUM_STREAM_VERSION TLS_Version_1_2 -#define MINIMUM_DATAGRAM_VERSION DTLS_Version_1_0 - -/* This should be changed when we start supporting DTLS_Version_1_x */ -#define MAXIMUM_DATAGRAM_VERSION DTLS_Version_1_0 - -#define SSL_ENABLE_ECDSA_SIGN_AUTH 0 -#define SSL_ENABLE_RSA_FIXED_ECDH_AUTH 0 -#define SSL_ENABLE_ECDSA_FIXED_ECDH_AUTH 0 - -#define DEFAULT_DTLS_TIMEOUT 1 -#define DEFAULT_DTLS_MTU 1400 -#define MIN_ALLOWED_DTLS_MTU 64 /* this ensure than there will be no integer - underflow when calculating max write size */ - -static CFTypeID kSSLContextTypeID; -int kSplitDefaultValue; -bool kAllowServerIdentityChangeDefaultValue; - -static void _sslContextDestroy(CFTypeRef arg); -static Boolean _sslContextEqual(CFTypeRef a, CFTypeRef b); -static CFHashCode _sslContextHash(CFTypeRef arg); -static CFStringRef _sslContextDescribe(CFTypeRef arg); - -static void _SSLContextReadDefault() -{ - /* 0 = disabled, 1 = split every write, 2 = split second and subsequent writes */ - /* Enabled by default, this make cause some interop issues, see and */ - const int defaultSplitDefaultValue = 2; - //To change: - //sudo defaults write /Library/Preferences/com.apple.security SSLWriteSplit -int 0 - CFTypeRef value = (CFTypeRef)CFPreferencesCopyValue(CFSTR("SSLWriteSplit"), - CFSTR("com.apple.security"), - kCFPreferencesAnyUser, - kCFPreferencesCurrentHost); - if (value) { - if (CFGetTypeID(value) == CFBooleanGetTypeID()) - kSplitDefaultValue = CFBooleanGetValue((CFBooleanRef)value) ? 1 : 0; - else if (CFGetTypeID(value) == CFNumberGetTypeID()) { - if (!CFNumberGetValue((CFNumberRef)value, kCFNumberIntType, &kSplitDefaultValue)) - kSplitDefaultValue = defaultSplitDefaultValue; - } - if (kSplitDefaultValue < 0 || kSplitDefaultValue > 2) { - kSplitDefaultValue = defaultSplitDefaultValue; - } - CFRelease(value); - } - else { - kSplitDefaultValue = defaultSplitDefaultValue; - } - - - /* 0 = disallowed, 1 = allowed */ - /* Disallowed by default */ - const bool defaultValue = false; - //To change: - //sudo defaults write /Library/Preferences/com.apple.security SSLAllowServerIdentityChange -bool YES - value = (CFTypeRef)CFPreferencesCopyValue(CFSTR("SSLAllowServerIdentityChange"), - CFSTR("com.apple.security"), - kCFPreferencesAnyUser, - kCFPreferencesCurrentHost); - if (value) { - if (CFGetTypeID(value) == CFBooleanGetTypeID()) - kAllowServerIdentityChangeDefaultValue = CFBooleanGetValue((CFBooleanRef)value); - else if (CFGetTypeID(value) == CFNumberGetTypeID()) { - int localValue; - if (!CFNumberGetValue((CFNumberRef)value, kCFNumberIntType, &localValue)) { - kAllowServerIdentityChangeDefaultValue = defaultValue; - } else { - kAllowServerIdentityChangeDefaultValue = localValue; - } - } - CFRelease(value); - } - else { - kAllowServerIdentityChangeDefaultValue = defaultValue; - } -} - -static void _SSLContextRegisterClass() -{ - static const CFRuntimeClass kSSLContextRegisterClass = { - 0, /* version */ - "SSLContext", /* class name */ - NULL, /* init */ - NULL, /* copy */ - _sslContextDestroy, /* dealloc */ - _sslContextEqual, /* equal */ - _sslContextHash, /* hash */ - NULL, /* copyFormattingDesc */ - _sslContextDescribe /* copyDebugDesc */ - }; - - kSSLContextTypeID = _CFRuntimeRegisterClass(&kSSLContextRegisterClass); -} - -CFTypeID -SSLContextGetTypeID(void) -{ - static pthread_once_t sOnce = PTHREAD_ONCE_INIT; - pthread_once(&sOnce, _SSLContextRegisterClass); - return kSSLContextTypeID; -} - - -OSStatus -SSLNewContext (Boolean isServer, - SSLContextRef *contextPtr) /* RETURNED */ -{ - if(contextPtr == NULL) { - return errSecParam; - } - - *contextPtr = SSLCreateContext(kCFAllocatorDefault, isServer?kSSLServerSide:kSSLClientSide, kSSLStreamType); - - if (*contextPtr == NULL) - return errSecAllocate; - - return errSecSuccess; -} - -SSLContextRef SSLCreateContext(CFAllocatorRef alloc, SSLProtocolSide protocolSide, SSLConnectionType connectionType) -{ - SSLContextRef ctx; - - ctx = SSLCreateContextWithRecordFuncs(alloc, protocolSide, connectionType, &SSLRecordLayerInternal); - - if(ctx==NULL) - return NULL; - - ctx->recCtx = SSLCreateInternalRecordLayer(connectionType); - if(ctx->recCtx==NULL) { - CFRelease(ctx); - return NULL; - } - - return ctx; -} - -SSLContextRef SSLCreateContextWithRecordFuncs(CFAllocatorRef alloc, SSLProtocolSide protocolSide, SSLConnectionType connectionType, const struct SSLRecordFuncs *recFuncs) -{ - OSStatus serr = errSecSuccess; - SSLContext *ctx = (SSLContext*) _CFRuntimeCreateInstance(alloc, SSLContextGetTypeID(), sizeof(SSLContext) - sizeof(CFRuntimeBase), NULL); - - if(ctx == NULL) { - return NULL; - } - - /* subsequent errors to errOut: */ - memset(((uint8_t*) ctx) + sizeof(CFRuntimeBase), 0, sizeof(SSLContext) - sizeof(CFRuntimeBase)); - - ctx->state = SSL_HdskStateUninit; - ctx->timeout_duration = DEFAULT_DTLS_TIMEOUT; - ctx->clientCertState = kSSLClientCertNone; - - ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; - ctx->maxProtocolVersion = MAXIMUM_STREAM_VERSION; - - ctx->isDTLS = false; - ctx->dtlsCookie.data = NULL; - ctx->dtlsCookie.length = 0; - ctx->hdskMessageSeq = 0; - ctx->hdskMessageSeqNext = 0; - ctx->mtu = DEFAULT_DTLS_MTU; - - ctx->negProtocolVersion = SSL_Version_Undetermined; - - - ctx->protocolSide = protocolSide; - /* Default value so we can send and receive hello msgs */ - ctx->sslTslCalls = &Ssl3Callouts; - - ctx->recFuncs = recFuncs; - - /* Initialize the cipher state to NULL_WITH_NULL_NULL */ - ctx->selectedCipher = TLS_NULL_WITH_NULL_NULL; - InitCipherSpecParams(ctx); - - /* this gets init'd on first call to SSLHandshake() */ - ctx->validCipherSuites = NULL; - ctx->numValidCipherSuites = 0; -#if ENABLE_SSLV2 - ctx->numValidNonSSLv2Suites = 0; -#endif - - ctx->peerDomainName = NULL; - ctx->peerDomainNameLen = 0; - -#ifdef USE_CDSA_CRYPTO - /* attach to CSP, CL, TP */ - serr = attachToAll(ctx); - if(serr) { - goto errOut; - } -#endif /* USE_CDSA_CRYPTO */ - - /* Initial cert verify state: verify with default system roots */ - ctx->enableCertVerify = true; - - /* Default for RSA blinding is ENABLED */ - ctx->rsaBlindingEnable = true; - - /* Default for sending one-byte app data record is DISABLED */ - ctx->oneByteRecordEnable = false; - - /* Default for allowing server identity change on renegotiation is FALSE */ - ctx->allowServerIdentityChange = false; - - /* Consult global system preference for default behavior: - * 0 = disabled, 1 = split every write, 2 = split second and subsequent writes - * (caller can override by setting kSSLSessionOptionSendOneByteRecord) - */ - static pthread_once_t sReadDefault = PTHREAD_ONCE_INIT; - pthread_once(&sReadDefault, _SSLContextReadDefault); - if (kSplitDefaultValue > 0) - ctx->oneByteRecordEnable = true; - if (kAllowServerIdentityChangeDefaultValue>0) - ctx->allowServerIdentityChange = true; - - /* default for anonymous ciphers is DISABLED */ - ctx->anonCipherEnable = false; - - ctx->breakOnServerAuth = false; - ctx->breakOnCertRequest = false; - ctx->breakOnClientAuth = false; - ctx->signalServerAuth = false; - ctx->signalCertRequest = false; - ctx->signalClientAuth = false; - - /* - * Initial/default set of ECDH curves - */ - ctx->ecdhNumCurves = SSL_ECDSA_NUM_CURVES; - ctx->ecdhCurves[0] = SSL_Curve_secp256r1; - ctx->ecdhCurves[1] = SSL_Curve_secp384r1; - ctx->ecdhCurves[2] = SSL_Curve_secp521r1; - - ctx->ecdhPeerCurve = SSL_Curve_None; /* until we negotiate one */ - ctx->negAuthType = SSLClientAuthNone; /* ditto */ - - ctx->messageWriteQueue = NULL; - - if(connectionType==kSSLDatagramType) { - ctx->minProtocolVersion = MINIMUM_DATAGRAM_VERSION; - ctx->maxProtocolVersion = MAXIMUM_DATAGRAM_VERSION; - ctx->isDTLS = true; - } - - ctx->secure_renegotiation = false; - - if (serr != errSecSuccess) { - CFRelease(ctx); - ctx = NULL; - } - return ctx; -} - -OSStatus -SSLNewDatagramContext (Boolean isServer, - SSLContextRef *contextPtr) /* RETURNED */ -{ - if (contextPtr == NULL) - return errSecParam; - *contextPtr = SSLCreateContext(kCFAllocatorDefault, isServer?kSSLServerSide:kSSLClientSide, kSSLDatagramType); - if (*contextPtr == NULL) - return errSecAllocate; - return errSecSuccess; -} - -/* - * Dispose of an SSLContext. (private) - * This function is invoked after our dispatch queue is safely released, - * or directly from SSLDisposeContext if there is no dispatch queue. - */ -OSStatus -SSLDisposeContext (SSLContextRef context) -{ - if(context == NULL) { - return errSecParam; - } - CFRelease(context); - return errSecSuccess; -} - -CF_RETURNS_RETAINED CFStringRef _sslContextDescribe(CFTypeRef arg) -{ - SSLContext* ctx = (SSLContext*) arg; - - if (ctx == NULL) { - return NULL; - } else { - CFStringRef result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), ctx); - return result; - } -} - -Boolean _sslContextEqual(CFTypeRef a, CFTypeRef b) -{ - return a == b; -} - -CFHashCode _sslContextHash(CFTypeRef arg) -{ - return (CFHashCode) arg; -} - -void _sslContextDestroy(CFTypeRef arg) -{ - SSLContext* ctx = (SSLContext*) arg; - -#if USE_SSLCERTIFICATE - sslDeleteCertificateChain(ctx->localCert, ctx); - sslDeleteCertificateChain(ctx->encryptCert, ctx); - sslDeleteCertificateChain(ctx->peerCert, ctx); - ctx->localCert = ctx->encryptCert = ctx->peerCert = NULL; -#else - CFReleaseNull(ctx->localCert); - CFReleaseNull(ctx->encryptCert); - CFReleaseNull(ctx->peerCert); - CFReleaseNull(ctx->trustedCerts); -#endif - - /* Free the last handshake message flight */ - SSLResetFlight(ctx); - - if(ctx->peerSecTrust) { - CFRelease(ctx->peerSecTrust); - ctx->peerSecTrust = NULL; - } - SSLFreeBuffer(&ctx->sessionTicket); - - #if APPLE_DH - SSLFreeBuffer(&ctx->dhParamsEncoded); -#ifdef USE_CDSA_CRYPTO - sslFreeKey(ctx->cspHand, &ctx->dhPrivate, NULL); -#else - if (ctx->secDHContext) - SecDHDestroy(ctx->secDHContext); -#endif /* !USE_CDSA_CRYPTO */ - SSLFreeBuffer(&ctx->dhPeerPublic); - SSLFreeBuffer(&ctx->dhExchangePublic); - #endif /* APPLE_DH */ - - SSLFreeBuffer(&ctx->ecdhPeerPublic); - SSLFreeBuffer(&ctx->ecdhExchangePublic); -#if USE_CDSA_CRYPTO - if(ctx->ecdhPrivCspHand == ctx->cspHand) { - sslFreeKey(ctx->ecdhPrivCspHand, &ctx->ecdhPrivate, NULL); - } - /* else we got this key from a SecKeyRef, no free needed */ -#endif - - /* Only destroy if we were using the internal record layer */ - if(ctx->recFuncs==&SSLRecordLayerInternal) - SSLDestroyInternalRecordLayer(ctx->recCtx); - - CloseHash(&SSLHashSHA1, &ctx->shaState); - CloseHash(&SSLHashMD5, &ctx->md5State); - CloseHash(&SSLHashSHA256, &ctx->sha256State); - CloseHash(&SSLHashSHA384, &ctx->sha512State); - - SSLFreeBuffer(&ctx->sessionID); - SSLFreeBuffer(&ctx->peerID); - SSLFreeBuffer(&ctx->resumableSession); - SSLFreeBuffer(&ctx->preMasterSecret); - SSLFreeBuffer(&ctx->fragmentedMessageCache); - SSLFreeBuffer(&ctx->receivedDataBuffer); - - if(ctx->peerDomainName) { - sslFree(ctx->peerDomainName); - ctx->peerDomainName = NULL; - ctx->peerDomainNameLen = 0; - } - - sslFree(ctx->validCipherSuites); - ctx->validCipherSuites = NULL; - ctx->numValidCipherSuites = 0; - -#if USE_CDSA_CRYPTO - /* - * NOTE: currently, all public keys come from the CL via CSSM_CL_CertGetKeyInfo. - * We really don't know what CSP the CL used to generate a public key (in fact, - * it uses the raw CSP only to get LogicalKeySizeInBits, but we can't know - * that). Thus using e.g. signingKeyCsp (or any other CSP) to free - * signingPubKey is not tecnically accurate. However, our public keys - * are all raw keys, and all Apple CSPs dispose of raw keys in the same - * way. - */ - sslFreeKey(ctx->cspHand, &ctx->signingPubKey, NULL); - sslFreeKey(ctx->cspHand, &ctx->encryptPubKey, NULL); - sslFreeKey(ctx->peerPubKeyCsp, &ctx->peerPubKey, NULL); - - if(ctx->signingPrivKeyRef) { - CFRelease(ctx->signingPrivKeyRef); - } - if(ctx->encryptPrivKeyRef) { - CFRelease(ctx->encryptPrivKeyRef); - } - if(ctx->trustedCerts) { - CFRelease(ctx->trustedCerts); - } - detachFromAll(ctx); -#else - sslFreePubKey(&ctx->signingPubKey); - sslFreePubKey(&ctx->encryptPubKey); - sslFreePubKey(&ctx->peerPubKey); - sslFreePrivKey(&ctx->signingPrivKeyRef); - sslFreePrivKey(&ctx->encryptPrivKeyRef); -#endif /* USE_CDSA_CRYPTO */ - CFReleaseSafe(ctx->acceptableCAs); - CFReleaseSafe(ctx->trustedLeafCerts); - CFReleaseSafe(ctx->localCertArray); - CFReleaseSafe(ctx->encryptCertArray); - CFReleaseSafe(ctx->encryptCertArray); - if(ctx->clientAuthTypes) { - sslFree(ctx->clientAuthTypes); - } - if(ctx->serverSigAlgs != NULL) { - sslFree(ctx->serverSigAlgs); - } - if(ctx->clientSigAlgs != NULL) { - sslFree(ctx->clientSigAlgs); - } - sslFreeDnList(ctx); - - SSLFreeBuffer(&ctx->ownVerifyData); - SSLFreeBuffer(&ctx->peerVerifyData); - - SSLFreeBuffer(&ctx->pskIdentity); - SSLFreeBuffer(&ctx->pskSharedSecret); - - memset(((uint8_t*) ctx) + sizeof(CFRuntimeBase), 0, sizeof(SSLContext) - sizeof(CFRuntimeBase)); - - sslCleanupSession(); -} - -/* - * Determine the state of an SSL session. - */ -OSStatus -SSLGetSessionState (SSLContextRef context, - SSLSessionState *state) /* RETURNED */ -{ - SSLSessionState rtnState = kSSLIdle; - - if(context == NULL) { - return errSecParam; - } - *state = rtnState; - switch(context->state) { - case SSL_HdskStateUninit: - case SSL_HdskStateServerUninit: - case SSL_HdskStateClientUninit: - rtnState = kSSLIdle; - break; - case SSL_HdskStateGracefulClose: - rtnState = kSSLClosed; - break; - case SSL_HdskStateErrorClose: - case SSL_HdskStateNoNotifyClose: - rtnState = kSSLAborted; - break; - case SSL_HdskStateServerReady: - case SSL_HdskStateClientReady: - rtnState = kSSLConnected; - break; - default: - assert((context->state >= SSL_HdskStateServerHello) && - (context->state <= SSL_HdskStateFinished)); - rtnState = kSSLHandshake; - break; - - } - *state = rtnState; - return errSecSuccess; -} - -/* - * Set options for an SSL session. - */ -OSStatus -SSLSetSessionOption (SSLContextRef context, - SSLSessionOption option, - Boolean value) -{ - if(context == NULL) { - return errSecParam; - } - if(sslIsSessionActive(context)) { - /* can't do this with an active session */ - return errSecBadReq; - } - switch(option) { - case kSSLSessionOptionBreakOnServerAuth: - context->breakOnServerAuth = value; - context->enableCertVerify = !value; - break; - case kSSLSessionOptionBreakOnCertRequested: - context->breakOnCertRequest = value; - break; - case kSSLSessionOptionBreakOnClientAuth: - context->breakOnClientAuth = value; - context->enableCertVerify = !value; - break; - case kSSLSessionOptionSendOneByteRecord: - context->oneByteRecordEnable = value; - break; - case kSSLSessionOptionFalseStart: - context->falseStartEnabled = value; - break; - case kSSLSessionOptionAllowServerIdentityChange: - context->allowServerIdentityChange = value; - break; - default: - return errSecParam; - } - - return errSecSuccess; -} - -/* - * Determine current value for the specified option in an SSL session. - */ -OSStatus -SSLGetSessionOption (SSLContextRef context, - SSLSessionOption option, - Boolean *value) -{ - if(context == NULL || value == NULL) { - return errSecParam; - } - switch(option) { - case kSSLSessionOptionBreakOnServerAuth: - *value = context->breakOnServerAuth; - break; - case kSSLSessionOptionBreakOnCertRequested: - *value = context->breakOnCertRequest; - break; - case kSSLSessionOptionBreakOnClientAuth: - *value = context->breakOnClientAuth; - break; - case kSSLSessionOptionSendOneByteRecord: - *value = context->oneByteRecordEnable; - break; - case kSSLSessionOptionFalseStart: - *value = context->falseStartEnabled; - break; - default: - return errSecParam; - } - - return errSecSuccess; -} - -OSStatus -SSLSetRecordContext (SSLContextRef ctx, - SSLRecordContextRef recCtx) -{ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - ctx->recCtx = recCtx; - return errSecSuccess; -} - -/* Those two trampolines are used to make the connetion between - the record layer IO callbacks and the user provided IO callbacks. - Those are currently necessary because the record layer read/write callbacks - have different prototypes that the user callbacks advertised in the API. - They have different prototypes because the record layer callback have to build in kernelland. - - This situation is not desirable. So we should figure out a way to get rid of them. - */ -static int IORead(SSLIOConnectionRef connection, - void *data, - size_t *dataLength) -{ - OSStatus rc; - SSLContextRef ctx = connection; - - - rc = ctx->ioCtx.read(ctx->ioCtx.ioRef, data, dataLength); - - /* We may need to translate error codes at this layer */ - if(rc==errSSLWouldBlock) { - rc=errSSLRecordWouldBlock; - } - - return rc; -} - -static int IOWrite(SSLIOConnectionRef connection, - const void *data, - size_t *dataLength) -{ - OSStatus rc; - SSLContextRef ctx = connection; - - rc = ctx->ioCtx.write(ctx->ioCtx.ioRef, data, dataLength); - - /* We may need to translate error codes at this layer */ - if(rc==errSSLWouldBlock) { - rc=errSSLRecordWouldBlock; - } - return rc; -} - - -OSStatus -SSLSetIOFuncs (SSLContextRef ctx, - SSLReadFunc readFunc, - SSLWriteFunc writeFunc) -{ - if(ctx == NULL) { - return errSecParam; - } - if(ctx->recFuncs!=&SSLRecordLayerInternal) { - /* Can Only do this with the internal record layer */ - check(0); - return errSecBadReq; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - - ctx->ioCtx.read=readFunc; - ctx->ioCtx.write=writeFunc; - - return SSLSetInternalRecordLayerIOFuncs(ctx->recCtx, IORead, IOWrite); -} - -OSStatus -SSLSetConnection (SSLContextRef ctx, - SSLConnectionRef connection) -{ - if(ctx == NULL) { - return errSecParam; - } - if(ctx->recFuncs!=&SSLRecordLayerInternal) { - /* Can Only do this with the internal record layer */ - check(0); - return errSecBadReq; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - - /* Need to keep a copy of it this layer for the Get function */ - ctx->ioCtx.ioRef = connection; - - return SSLSetInternalRecordLayerConnection(ctx->recCtx, ctx); -} - -OSStatus -SSLGetConnection (SSLContextRef ctx, - SSLConnectionRef *connection) -{ - if((ctx == NULL) || (connection == NULL)) { - return errSecParam; - } - *connection = ctx->ioCtx.ioRef; - return errSecSuccess; -} - -OSStatus -SSLSetPeerDomainName (SSLContextRef ctx, - const char *peerName, - size_t peerNameLen) -{ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - - /* free possible existing name */ - if(ctx->peerDomainName) { - sslFree(ctx->peerDomainName); - } - - /* copy in */ - ctx->peerDomainName = (char *)sslMalloc(peerNameLen); - if(ctx->peerDomainName == NULL) { - return errSecAllocate; - } - memmove(ctx->peerDomainName, peerName, peerNameLen); - ctx->peerDomainNameLen = peerNameLen; - return errSecSuccess; -} - -/* - * Determine the buffer size needed for SSLGetPeerDomainName(). - */ -OSStatus -SSLGetPeerDomainNameLength (SSLContextRef ctx, - size_t *peerNameLen) // RETURNED -{ - if(ctx == NULL) { - return errSecParam; - } - *peerNameLen = ctx->peerDomainNameLen; - return errSecSuccess; -} - -OSStatus -SSLGetPeerDomainName (SSLContextRef ctx, - char *peerName, // returned here - size_t *peerNameLen) // IN/OUT -{ - if(ctx == NULL) { - return errSecParam; - } - if(*peerNameLen < ctx->peerDomainNameLen) { - return errSSLBufferOverflow; - } - memmove(peerName, ctx->peerDomainName, ctx->peerDomainNameLen); - *peerNameLen = ctx->peerDomainNameLen; - return errSecSuccess; -} - -OSStatus -SSLSetDatagramHelloCookie (SSLContextRef ctx, - const void *cookie, - size_t cookieLen) -{ - OSStatus err; - - if(ctx == NULL) { - return errSecParam; - } - - if(!ctx->isDTLS) return errSecParam; - - if((ctx == NULL) || (cookieLen>32)) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - - /* free possible existing cookie */ - if(ctx->dtlsCookie.data) { - SSLFreeBuffer(&ctx->dtlsCookie); - } - - /* copy in */ - if((err=SSLAllocBuffer(&ctx->dtlsCookie, cookieLen))) - return err; - - memmove(ctx->dtlsCookie.data, cookie, cookieLen); - return errSecSuccess; -} - -OSStatus -SSLSetMaxDatagramRecordSize (SSLContextRef ctx, - size_t maxSize) -{ - - if(ctx == NULL) return errSecParam; - if(!ctx->isDTLS) return errSecParam; - if(maxSize < MIN_ALLOWED_DTLS_MTU) return errSecParam; - - ctx->mtu = maxSize; - - return errSecSuccess; -} - -OSStatus -SSLGetMaxDatagramRecordSize (SSLContextRef ctx, - size_t *maxSize) -{ - if(ctx == NULL) return errSecParam; - if(!ctx->isDTLS) return errSecParam; - - *maxSize = ctx->mtu; - - return errSecSuccess; -} - -/* - - Keys to to math below: - - A DTLS record looks like this: | header (13 bytes) | fragment | - - For Null cipher, fragment is clear text as follows: - | Contents | Mac | - - For block cipher, fragment size must be a multiple of the cipher block size, and is the - encryption of the following plaintext : - | IV (1 block) | content | MAC | padding (0 to 255 bytes) | Padlen (1 byte) | - - The maximum content length in that case is achieved for 0 padding bytes. - -*/ - -OSStatus -SSLGetDatagramWriteSize (SSLContextRef ctx, - size_t *bufSize) -{ - if(ctx == NULL) return errSecParam; - if(!ctx->isDTLS) return errSecParam; - if(bufSize == NULL) return errSecParam; - - size_t max_fragment_size = ctx->mtu-13; /* 13 = dtls record header */ - - SSLCipherSpecParams *currCipher = &ctx->selectedCipherSpecParams; - - size_t blockSize = currCipher->blockSize; - size_t macSize = currCipher->macSize; - - if (blockSize > 0) { - /* max_fragment_size must be a multiple of blocksize */ - max_fragment_size = max_fragment_size & ~(blockSize-1); - max_fragment_size -= blockSize; /* 1 block for IV */ - max_fragment_size -= 1; /* 1 byte for pad length */ - } - - /* less the mac size */ - max_fragment_size -= macSize; - - /* Thats just a sanity check */ - assert(max_fragment_sizemtu); - - *bufSize = max_fragment_size; - - return errSecSuccess; -} - -static SSLProtocolVersion SSLProtocolToProtocolVersion(SSLProtocol protocol) { - switch (protocol) { - case kSSLProtocol2: return SSL_Version_2_0; - case kSSLProtocol3: return SSL_Version_3_0; - case kTLSProtocol1: return TLS_Version_1_0; - case kTLSProtocol11: return TLS_Version_1_1; - case kTLSProtocol12: return TLS_Version_1_2; - case kDTLSProtocol1: return DTLS_Version_1_0; - default: return SSL_Version_Undetermined; - } -} - -/* concert between private SSLProtocolVersion and public SSLProtocol */ -static SSLProtocol SSLProtocolVersionToProtocol(SSLProtocolVersion version) -{ - switch(version) { - case SSL_Version_2_0: return kSSLProtocol2; - case SSL_Version_3_0: return kSSLProtocol3; - case TLS_Version_1_0: return kTLSProtocol1; - case TLS_Version_1_1: return kTLSProtocol11; - case TLS_Version_1_2: return kTLSProtocol12; - case DTLS_Version_1_0: return kDTLSProtocol1; - default: - sslErrorLog("SSLProtocolVersionToProtocol: bad prot (%04x)\n", - version); - /* DROPTHROUGH */ - case SSL_Version_Undetermined: return kSSLProtocolUnknown; - } -} - -OSStatus -SSLSetProtocolVersionMin (SSLContextRef ctx, - SSLProtocol minVersion) -{ - if(ctx == NULL) return errSecParam; - - SSLProtocolVersion version = SSLProtocolToProtocolVersion(minVersion); - if (ctx->isDTLS) { - if (version > MINIMUM_DATAGRAM_VERSION || - version < MAXIMUM_DATAGRAM_VERSION) - return errSSLIllegalParam; - if (version < ctx->maxProtocolVersion) - ctx->maxProtocolVersion = version; - } else { - if (version < MINIMUM_STREAM_VERSION || version > MAXIMUM_STREAM_VERSION) - return errSSLIllegalParam; - if (version > ctx->maxProtocolVersion) - ctx->maxProtocolVersion = version; - } - ctx->minProtocolVersion = version; - - return errSecSuccess; -} - -OSStatus -SSLGetProtocolVersionMin (SSLContextRef ctx, - SSLProtocol *minVersion) -{ - if(ctx == NULL) return errSecParam; - - *minVersion = SSLProtocolVersionToProtocol(ctx->minProtocolVersion); - return errSecSuccess; -} - -OSStatus -SSLSetProtocolVersionMax (SSLContextRef ctx, - SSLProtocol maxVersion) -{ - if(ctx == NULL) return errSecParam; - - SSLProtocolVersion version = SSLProtocolToProtocolVersion(maxVersion); - if (ctx->isDTLS) { - if (version > MINIMUM_DATAGRAM_VERSION || - version < MAXIMUM_DATAGRAM_VERSION) - return errSSLIllegalParam; - if (version > ctx->minProtocolVersion) - ctx->minProtocolVersion = version; - } else { - if (version < MINIMUM_STREAM_VERSION || version > MAXIMUM_STREAM_VERSION) - return errSSLIllegalParam; - if (version < ctx->minProtocolVersion) - ctx->minProtocolVersion = version; - } - ctx->maxProtocolVersion = version; - - return errSecSuccess; -} - -OSStatus -SSLGetProtocolVersionMax (SSLContextRef ctx, - SSLProtocol *maxVersion) -{ - if(ctx == NULL) return errSecParam; - - *maxVersion = SSLProtocolVersionToProtocol(ctx->maxProtocolVersion); - return errSecSuccess; -} - -#define max(x,y) ((x)<(y)?(y):(x)) - -OSStatus -SSLSetProtocolVersionEnabled(SSLContextRef ctx, - SSLProtocol protocol, - Boolean enable) -{ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx) || ctx->isDTLS) { - /* Can't do this with an active session, nor with a DTLS session */ - return errSecBadReq; - } - if (protocol == kSSLProtocolAll) { - if (enable) { - ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; - ctx->maxProtocolVersion = MAXIMUM_STREAM_VERSION; - } else { - ctx->minProtocolVersion = SSL_Version_Undetermined; - ctx->maxProtocolVersion = SSL_Version_Undetermined; - } - } else { - SSLProtocolVersion version = SSLProtocolToProtocolVersion(protocol); - if (enable) { - if (version < MINIMUM_STREAM_VERSION || version > MAXIMUM_STREAM_VERSION) { - return errSecParam; - } - if (version > ctx->maxProtocolVersion) { - ctx->maxProtocolVersion = version; - if (ctx->minProtocolVersion == SSL_Version_Undetermined) - ctx->minProtocolVersion = version; - } - if (version < ctx->minProtocolVersion) { - ctx->minProtocolVersion = version; - } - } else { - if (version < SSL_Version_2_0 || version > MAXIMUM_STREAM_VERSION) { - return errSecParam; - } - /* Disabling a protocol version now resets the minimum acceptable - * version to the next higher version. This means it's no longer - * possible to enable a discontiguous set of protocol versions. - */ - SSLProtocolVersion nextVersion; - switch (version) { - case SSL_Version_2_0: - nextVersion = SSL_Version_3_0; - break; - case SSL_Version_3_0: - nextVersion = TLS_Version_1_0; - break; - case TLS_Version_1_0: - nextVersion = TLS_Version_1_1; - break; - case TLS_Version_1_1: - nextVersion = TLS_Version_1_2; - break; - case TLS_Version_1_2: - default: - nextVersion = SSL_Version_Undetermined; - break; - } - ctx->minProtocolVersion = max(ctx->minProtocolVersion, nextVersion); - if (ctx->minProtocolVersion > ctx->maxProtocolVersion) { - ctx->minProtocolVersion = SSL_Version_Undetermined; - ctx->maxProtocolVersion = SSL_Version_Undetermined; - } - } - } - - return errSecSuccess; -} - -OSStatus -SSLGetProtocolVersionEnabled(SSLContextRef ctx, - SSLProtocol protocol, - Boolean *enable) /* RETURNED */ -{ - if(ctx == NULL) { - return errSecParam; - } - if(ctx->isDTLS) { - /* Can't do this with a DTLS session */ - return errSecBadReq; - } - switch(protocol) { - case kSSLProtocol2: - case kSSLProtocol3: - case kTLSProtocol1: - case kTLSProtocol11: - case kTLSProtocol12: - { - SSLProtocolVersion version = SSLProtocolToProtocolVersion(protocol); - *enable = (ctx->minProtocolVersion <= version - && ctx->maxProtocolVersion >= version); - break; - } - case kSSLProtocolAll: - *enable = (ctx->minProtocolVersion <= MINIMUM_STREAM_VERSION - && ctx->maxProtocolVersion >= MAXIMUM_STREAM_VERSION); - break; - default: - return errSecParam; - } - return errSecSuccess; -} - -/* deprecated */ -OSStatus -SSLSetProtocolVersion (SSLContextRef ctx, - SSLProtocol version) -{ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx) || ctx->isDTLS) { - /* Can't do this with an active session, nor with a DTLS session */ - return errSecBadReq; - } - - switch(version) { - case kSSLProtocol3: - /* this tells us to do our best, up to 3.0 */ - ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; - ctx->maxProtocolVersion = SSL_Version_3_0; - break; - case kSSLProtocol3Only: - ctx->minProtocolVersion = SSL_Version_3_0; - ctx->maxProtocolVersion = SSL_Version_3_0; - break; - case kTLSProtocol1: - /* this tells us to do our best, up to TLS, but allows 3.0 */ - ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; - ctx->maxProtocolVersion = TLS_Version_1_0; - break; - case kTLSProtocol1Only: - ctx->minProtocolVersion = TLS_Version_1_0; - ctx->maxProtocolVersion = TLS_Version_1_0; - break; - case kTLSProtocol11: - /* This tells us to do our best, up to TLS 1.1, currently also - allows 3.0 or TLS 1.0 */ - ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; - ctx->maxProtocolVersion = TLS_Version_1_1; - break; - case kTLSProtocol12: - case kSSLProtocolAll: - case kSSLProtocolUnknown: - /* This tells us to do our best, up to TLS 1.2, currently also - allows 3.0 or TLS 1.0 or TLS 1.1 */ - ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; - ctx->maxProtocolVersion = MAXIMUM_STREAM_VERSION; - break; - default: - return errSecParam; - } - - return errSecSuccess; -} - -/* deprecated */ -OSStatus -SSLGetProtocolVersion (SSLContextRef ctx, - SSLProtocol *protocol) /* RETURNED */ -{ - if(ctx == NULL) { - return errSecParam; - } - /* translate array of booleans to public value; not all combinations - * are legal (i.e., meaningful) for this call */ - if (ctx->maxProtocolVersion == MAXIMUM_STREAM_VERSION) { - if(ctx->minProtocolVersion == MINIMUM_STREAM_VERSION) { - /* traditional 'all enabled' */ - *protocol = kSSLProtocolAll; - return errSecSuccess; - } - } else if (ctx->maxProtocolVersion == TLS_Version_1_1) { - if(ctx->minProtocolVersion == MINIMUM_STREAM_VERSION) { - /* traditional 'all enabled' */ - *protocol = kTLSProtocol11; - return errSecSuccess; - } - } else if (ctx->maxProtocolVersion == TLS_Version_1_0) { - if(ctx->minProtocolVersion == MINIMUM_STREAM_VERSION) { - /* TLS1.1 and below enabled */ - *protocol = kTLSProtocol1; - return errSecSuccess; - } else if(ctx->minProtocolVersion == TLS_Version_1_0) { - *protocol = kTLSProtocol1Only; - } - } else if(ctx->maxProtocolVersion == SSL_Version_3_0) { - if(ctx->minProtocolVersion == MINIMUM_STREAM_VERSION) { - /* Could also return kSSLProtocol3Only since - MINIMUM_STREAM_VERSION == SSL_Version_3_0. */ - *protocol = kSSLProtocol3; - return errSecSuccess; - } - } - - return errSecParam; -} - -OSStatus -SSLGetNegotiatedProtocolVersion (SSLContextRef ctx, - SSLProtocol *protocol) /* RETURNED */ -{ - if(ctx == NULL) { - return errSecParam; - } - *protocol = SSLProtocolVersionToProtocol(ctx->negProtocolVersion); - return errSecSuccess; -} - -OSStatus -SSLSetEnableCertVerify (SSLContextRef ctx, - Boolean enableVerify) -{ - if(ctx == NULL) { - return errSecParam; - } - sslCertDebug("SSLSetEnableCertVerify %s", - enableVerify ? "true" : "false"); - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - ctx->enableCertVerify = enableVerify; - return errSecSuccess; -} - -OSStatus -SSLGetEnableCertVerify (SSLContextRef ctx, - Boolean *enableVerify) -{ - if(ctx == NULL) { - return errSecParam; - } - *enableVerify = ctx->enableCertVerify; - return errSecSuccess; -} - -OSStatus -SSLSetAllowsExpiredCerts(SSLContextRef ctx, - Boolean allowExpired) -{ - if(ctx == NULL) { - return errSecParam; - } - sslCertDebug("SSLSetAllowsExpiredCerts %s", - allowExpired ? "true" : "false"); - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - ctx->allowExpiredCerts = allowExpired; - return errSecSuccess; -} - -OSStatus -SSLGetAllowsExpiredCerts (SSLContextRef ctx, - Boolean *allowExpired) -{ - if(ctx == NULL) { - return errSecParam; - } - *allowExpired = ctx->allowExpiredCerts; - return errSecSuccess; -} - -OSStatus -SSLSetAllowsExpiredRoots(SSLContextRef ctx, - Boolean allowExpired) -{ - if(ctx == NULL) { - return errSecParam; - } - sslCertDebug("SSLSetAllowsExpiredRoots %s", - allowExpired ? "true" : "false"); - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - ctx->allowExpiredRoots = allowExpired; - return errSecSuccess; -} - -OSStatus -SSLGetAllowsExpiredRoots (SSLContextRef ctx, - Boolean *allowExpired) -{ - if(ctx == NULL) { - return errSecParam; - } - *allowExpired = ctx->allowExpiredRoots; - return errSecSuccess; -} - -OSStatus SSLSetAllowsAnyRoot( - SSLContextRef ctx, - Boolean anyRoot) -{ - if(ctx == NULL) { - return errSecParam; - } - sslCertDebug("SSLSetAllowsAnyRoot %s", anyRoot ? "true" : "false"); - ctx->allowAnyRoot = anyRoot; - return errSecSuccess; -} - -OSStatus -SSLGetAllowsAnyRoot( - SSLContextRef ctx, - Boolean *anyRoot) -{ - if(ctx == NULL) { - return errSecParam; - } - *anyRoot = ctx->allowAnyRoot; - return errSecSuccess; -} - -#if !TARGET_OS_IPHONE -/* obtain the system roots sets for this app, policy SSL */ -static OSStatus sslDefaultSystemRoots( - SSLContextRef ctx, - CFArrayRef *systemRoots) // created and RETURNED - -{ - return SecTrustSettingsCopyQualifiedCerts(&CSSMOID_APPLE_TP_SSL, - ctx->peerDomainName, - (uint32_t)ctx->peerDomainNameLen, - (ctx->protocolSide == kSSLServerSide) ? - /* server verifies, client encrypts */ - CSSM_KEYUSE_VERIFY : CSSM_KEYUSE_ENCRYPT, - systemRoots); -} -#endif /* OS X only */ - -OSStatus -SSLSetTrustedRoots (SSLContextRef ctx, - CFArrayRef trustedRoots, - Boolean replaceExisting) -{ -#ifdef USE_CDSA_CRYPTO - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - - if(replaceExisting) { - /* trivial case - retain the new, throw out the old. */ - if (trustedRoots) - CFRetain(trustedRoots); - CFReleaseSafe(ctx->trustedCerts); - ctx->trustedCerts = trustedRoots; - return errSecSuccess; - } - - /* adding new trusted roots - to either our existing set, or the system set */ - CFArrayRef existingRoots = NULL; - OSStatus ortn; - if(ctx->trustedCerts != NULL) { - /* we'll release these as we exit */ - existingRoots = ctx->trustedCerts; - } - else { - /* get system set for this app, policy SSL */ - ortn = sslDefaultSystemRoots(ctx, &existingRoots); - if(ortn) { - CFReleaseSafe(existingRoots); - return ortn; - } - } - - /* Create a new root array with caller's roots first */ - CFMutableArrayRef newRoots = CFArrayCreateMutableCopy(NULL, 0, trustedRoots); - CFRange existRange = { 0, CFArrayGetCount(existingRoots) }; - CFArrayAppendArray(newRoots, existingRoots, existRange); - CFRelease(existingRoots); - ctx->trustedCerts = newRoots; - return errSecSuccess; - -#else - if (sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - sslCertDebug("SSLSetTrustedRoot numCerts %d replaceExist %s", - (int)CFArrayGetCount(trustedRoots), replaceExisting ? "true" : "false"); - - if (replaceExisting) { - ctx->trustedCertsOnly = true; - CFReleaseNull(ctx->trustedCerts); - } - - if (ctx->trustedCerts) { - CFIndex count = CFArrayGetCount(trustedRoots); - CFRange range = { 0, count }; - CFArrayAppendArray(ctx->trustedCerts, trustedRoots, range); - } else { - require(ctx->trustedCerts = - CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, trustedRoots), - errOut); - } - - return errSecSuccess; - -errOut: - return errSecAllocate; -#endif /* !USE_CDSA_CRYPTO */ -} - -OSStatus -SSLCopyTrustedRoots (SSLContextRef ctx, - CFArrayRef *trustedRoots) /* RETURNED */ -{ - if(ctx == NULL || trustedRoots == NULL) { - return errSecParam; - } - if(ctx->trustedCerts != NULL) { - *trustedRoots = ctx->trustedCerts; - CFRetain(ctx->trustedCerts); - return errSecSuccess; - } -#if (TARGET_OS_MAC && !(TARGET_OS_EMBEDDED || TARGET_OS_IPHONE)) - /* use default system roots */ - return sslDefaultSystemRoots(ctx, trustedRoots); -#else - *trustedRoots = NULL; - return errSecSuccess; -#endif -} - -OSStatus -SSLSetTrustedLeafCertificates (SSLContextRef ctx, - CFArrayRef trustedCerts) -{ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - - if(ctx->trustedLeafCerts) { - CFRelease(ctx->trustedLeafCerts); - } - ctx->trustedLeafCerts = trustedCerts; - CFRetain(trustedCerts); - return errSecSuccess; -} - -OSStatus -SSLCopyTrustedLeafCertificates (SSLContextRef ctx, - CFArrayRef *trustedCerts) /* RETURNED */ -{ - if(ctx == NULL) { - return errSecParam; - } - if(ctx->trustedLeafCerts != NULL) { - *trustedCerts = ctx->trustedLeafCerts; - CFRetain(ctx->trustedCerts); - return errSecSuccess; - } - *trustedCerts = NULL; - return errSecSuccess; -} - -OSStatus -SSLSetClientSideAuthenticate (SSLContext *ctx, - SSLAuthenticate auth) -{ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - ctx->clientAuth = auth; - switch(auth) { - case kNeverAuthenticate: - ctx->tryClientAuth = false; - break; - case kAlwaysAuthenticate: - case kTryAuthenticate: - ctx->tryClientAuth = true; - break; - } - return errSecSuccess; -} - -OSStatus -SSLGetClientSideAuthenticate (SSLContext *ctx, - SSLAuthenticate *auth) /* RETURNED */ -{ - if(ctx == NULL || auth == NULL) { - return errSecParam; - } - *auth = ctx->clientAuth; - return errSecSuccess; -} - -OSStatus -SSLGetClientCertificateState (SSLContextRef ctx, - SSLClientCertificateState *clientState) -{ - if(ctx == NULL) { - return errSecParam; - } - *clientState = ctx->clientCertState; - return errSecSuccess; -} - -OSStatus -SSLSetCertificate (SSLContextRef ctx, - CFArrayRef certRefs) -{ - /* - * -- free localCerts if we have any - * -- Get raw cert data, convert to ctx->localCert - * -- get pub, priv keys from certRef[0] - * -- validate cert chain - */ - if(ctx == NULL) { - return errSecParam; - } - - /* can't do this with an active session */ - if(sslIsSessionActive(ctx) && - /* kSSLClientCertRequested implies client side */ - (ctx->clientCertState != kSSLClientCertRequested)) - { - return errSecBadReq; - } - CFReleaseNull(ctx->localCertArray); - /* changing the client cert invalidates negotiated auth type */ - ctx->negAuthType = SSLClientAuthNone; - if(certRefs == NULL) { - return errSecSuccess; // we have cleared the cert, as requested - } - OSStatus ortn = parseIncomingCerts(ctx, - certRefs, - &ctx->localCert, - &ctx->signingPubKey, - &ctx->signingPrivKeyRef, - &ctx->ourSignerAlg); - if(ortn == errSecSuccess) { - ctx->localCertArray = certRefs; - CFRetain(certRefs); - /* client cert was changed, must update auth type */ - ortn = SSLUpdateNegotiatedClientAuthType(ctx); - } - return ortn; -} - -OSStatus -SSLSetEncryptionCertificate (SSLContextRef ctx, - CFArrayRef certRefs) -{ - /* - * -- free encryptCert if we have any - * -- Get raw cert data, convert to ctx->encryptCert - * -- get pub, priv keys from certRef[0] - * -- validate cert chain - */ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - CFReleaseNull(ctx->encryptCertArray); - OSStatus ortn = parseIncomingCerts(ctx, - certRefs, - &ctx->encryptCert, - &ctx->encryptPubKey, - &ctx->encryptPrivKeyRef, - NULL); /* Signer alg */ - if(ortn == errSecSuccess) { - ctx->encryptCertArray = certRefs; - CFRetain(certRefs); - } - return ortn; -} - -OSStatus SSLGetCertificate(SSLContextRef ctx, - CFArrayRef *certRefs) -{ - if(ctx == NULL) { - return errSecParam; - } - *certRefs = ctx->localCertArray; - return errSecSuccess; -} - -OSStatus SSLGetEncryptionCertificate(SSLContextRef ctx, - CFArrayRef *certRefs) -{ - if(ctx == NULL) { - return errSecParam; - } - *certRefs = ctx->encryptCertArray; - return errSecSuccess; -} - -OSStatus -SSLSetPeerID (SSLContext *ctx, - const void *peerID, - size_t peerIDLen) -{ - OSStatus serr; - - /* copy peerId to context->peerId */ - if((ctx == NULL) || - (peerID == NULL) || - (peerIDLen == 0)) { - return errSecParam; - } - if(sslIsSessionActive(ctx) && - /* kSSLClientCertRequested implies client side */ - (ctx->clientCertState != kSSLClientCertRequested)) - { - return errSecBadReq; - } - SSLFreeBuffer(&ctx->peerID); - serr = SSLAllocBuffer(&ctx->peerID, peerIDLen); - if(serr) { - return serr; - } - memmove(ctx->peerID.data, peerID, peerIDLen); - return errSecSuccess; -} - -OSStatus -SSLGetPeerID (SSLContextRef ctx, - const void **peerID, - size_t *peerIDLen) -{ - *peerID = ctx->peerID.data; // may be NULL - *peerIDLen = ctx->peerID.length; - return errSecSuccess; -} - -OSStatus -SSLGetNegotiatedCipher (SSLContextRef ctx, - SSLCipherSuite *cipherSuite) -{ - if(ctx == NULL) { - return errSecParam; - } - if(!sslIsSessionActive(ctx)) { - return errSecBadReq; - } - *cipherSuite = (SSLCipherSuite)ctx->selectedCipher; - return errSecSuccess; -} - -/* - * Add an acceptable distinguished name (client authentication only). - */ -OSStatus -SSLAddDistinguishedName( - SSLContextRef ctx, - const void *derDN, - size_t derDNLen) -{ - DNListElem *dn; - OSStatus err; - - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - return errSecBadReq; - } - - dn = (DNListElem *)sslMalloc(sizeof(DNListElem)); - if(dn == NULL) { - return errSecAllocate; - } - if ((err = SSLAllocBuffer(&dn->derDN, derDNLen))) - return err; - memcpy(dn->derDN.data, derDN, derDNLen); - dn->next = ctx->acceptableDNList; - ctx->acceptableDNList = dn; - return errSecSuccess; -} - -/* single-cert version of SSLSetCertificateAuthorities() */ -static OSStatus -sslAddCA(SSLContextRef ctx, - SecCertificateRef cert) -{ - OSStatus ortn = errSecParam; - - /* Get subject from certificate. */ -#if TARGET_OS_IPHONE - CFDataRef subjectName = NULL; - subjectName = SecCertificateCopySubjectSequence(cert); - require(subjectName, errOut); -#else - CSSM_DATA_PTR subjectName = NULL; - ortn = SecCertificateCopyFirstFieldValue(cert, &CSSMOID_X509V1SubjectNameStd, &subjectName); - require_noerr(ortn, errOut); -#endif - - /* add to acceptableCAs as cert, creating array if necessary */ - if(ctx->acceptableCAs == NULL) { - require(ctx->acceptableCAs = CFArrayCreateMutable(NULL, 0, - &kCFTypeArrayCallBacks), errOut); - if(ctx->acceptableCAs == NULL) { - return errSecAllocate; - } - } - CFArrayAppendValue(ctx->acceptableCAs, cert); - - /* then add this cert's subject name to acceptableDNList */ -#if TARGET_OS_IPHONE - ortn = SSLAddDistinguishedName(ctx, - CFDataGetBytePtr(subjectName), - CFDataGetLength(subjectName)); -#else - ortn = SSLAddDistinguishedName(ctx, subjectName->Data, subjectName->Length); -#endif - -errOut: -#if TARGET_OS_IPHONE - CFReleaseSafe(subjectName); -#endif - return ortn; -} - -/* - * Add a SecCertificateRef, or a CFArray of them, to a server's list - * of acceptable Certificate Authorities (CAs) to present to the client - * when client authentication is performed. - */ -OSStatus -SSLSetCertificateAuthorities(SSLContextRef ctx, - CFTypeRef certificateOrArray, - Boolean replaceExisting) -{ - CFTypeID itemType; - OSStatus ortn = errSecSuccess; - - if((ctx == NULL) || sslIsSessionActive(ctx) || - (ctx->protocolSide != kSSLServerSide)) { - return errSecParam; - } - if(replaceExisting) { - sslFreeDnList(ctx); - if(ctx->acceptableCAs) { - CFRelease(ctx->acceptableCAs); - ctx->acceptableCAs = NULL; - } - } - /* else appending */ - - itemType = CFGetTypeID(certificateOrArray); - if(itemType == SecCertificateGetTypeID()) { - /* one cert */ - ortn = sslAddCA(ctx, (SecCertificateRef)certificateOrArray); - } - else if(itemType == CFArrayGetTypeID()) { - CFArrayRef cfa = (CFArrayRef)certificateOrArray; - CFIndex numCerts = CFArrayGetCount(cfa); - CFIndex dex; - - /* array of certs */ - for(dex=0; dexacceptableCAs == NULL) { - *certificates = NULL; - return errSecSuccess; - } - *certificates = ctx->acceptableCAs; - CFRetain(ctx->acceptableCAs); - return errSecSuccess; -} - - -/* - * Obtain the list of acceptable distinguished names as provided by - * a server (if the SSLCotextRef is configured as a client), or as - * specified by SSLSetCertificateAuthorities() (if the SSLContextRef - * is configured as a server). - */ -OSStatus -SSLCopyDistinguishedNames (SSLContextRef ctx, - CFArrayRef *names) -{ - CFMutableArrayRef outArray = NULL; - DNListElem *dn; - - if((ctx == NULL) || (names == NULL)) { - return errSecParam; - } - if(ctx->acceptableDNList == NULL) { - *names = NULL; - return errSecSuccess; - } - outArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - dn = ctx->acceptableDNList; - while (dn) { - CFDataRef cfDn = CFDataCreate(NULL, dn->derDN.data, dn->derDN.length); - CFArrayAppendValue(outArray, cfDn); - CFRelease(cfDn); - dn = dn->next; - } - *names = outArray; - return errSecSuccess; -} - - -/* - * Request peer certificates. Valid anytime, subsequent to - * a handshake attempt. - * Common code for SSLGetPeerCertificates() and SSLCopyPeerCertificates(). - * TODO: the 'legacy' argument is not used anymore. - */ -static OSStatus -sslCopyPeerCertificates (SSLContextRef ctx, - CFArrayRef *certs, - Boolean legacy) -{ - if(ctx == NULL) { - return errSecParam; - } - -#ifdef USE_SSLCERTIFICATE - uint32 numCerts; - CFMutableArrayRef ca; - CFIndex i; - SecCertificateRef cfd; - OSStatus ortn; - CSSM_DATA certData; - SSLCertificate *scert; - - *certs = NULL; - - /* - * Copy peerCert, a chain of SSLCertificates, to a CFArray of - * CFDataRefs, each of which is one DER-encoded cert. - */ - numCerts = SSLGetCertificateChainLength(ctx->peerCert); - if(numCerts == 0) { - return errSecSuccess; - } - ca = CFArrayCreateMutable(kCFAllocatorDefault, - (CFIndex)numCerts, &kCFTypeArrayCallBacks); - if(ca == NULL) { - return errSecAllocate; - } - - /* - * Caller gets leaf cert first, the opposite of the way we store them. - */ - scert = ctx->peerCert; - for(i=0; (unsigned)iderCert, &certData); - ortn = SecCertificateCreateFromData(&certData, - CSSM_CERT_X_509v3, - CSSM_CERT_ENCODING_DER, - &cfd); - if(ortn) { - CFRelease(ca); - return ortn; - } - /* insert at head of array */ - CFArrayInsertValueAtIndex(ca, 0, cfd); - if(!legacy) { - /* skip for legacy SSLGetPeerCertificates() */ - CFRelease(cfd); - } - scert = scert->next; - } - *certs = ca; - -#else - if (!ctx->peerCert) { - *certs = NULL; - return errSecBadReq; - } - - CFArrayRef ca = CFArrayCreateCopy(kCFAllocatorDefault, ctx->peerCert); - *certs = ca; - if (ca == NULL) { - return errSecAllocate; - } - - if (legacy) { - CFIndex ix, count = CFArrayGetCount(ca); - for (ix = 0; ix < count; ++ix) { - CFRetain(CFArrayGetValueAtIndex(ca, ix)); - } - } -#endif - - return errSecSuccess; -} - -OSStatus -SSLCopyPeerCertificates (SSLContextRef ctx, - CFArrayRef *certs) -{ - return sslCopyPeerCertificates(ctx, certs, false); -} - -#if !TARGET_OS_IPHONE -// Permanently removing from iOS, keep for OSX (deprecated), removed from headers. -// Mailsmith Crashes While Getting New Mail Under Mavericks Developer Preview -OSStatus -SSLGetPeerCertificates (SSLContextRef ctx, - CFArrayRef *certs); -OSStatus -SSLGetPeerCertificates (SSLContextRef ctx, - CFArrayRef *certs) -{ - return sslCopyPeerCertificates(ctx, certs, true); -} -#endif - -/* - * Specify Diffie-Hellman parameters. Optional; if we are configured to allow - * for D-H ciphers and a D-H cipher is negotiated, and this function has not - * been called, a set of process-wide parameters will be calculated. However - * that can take a long time (30 seconds). - */ -OSStatus SSLSetDiffieHellmanParams( - SSLContextRef ctx, - const void *dhParams, - size_t dhParamsLen) -{ -#if APPLE_DH - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - return errSecBadReq; - } - SSLFreeBuffer(&ctx->dhParamsEncoded); -#if !USE_CDSA_CRYPTO - if (ctx->secDHContext) - SecDHDestroy(ctx->secDHContext); -#endif - - OSStatus ortn; - ortn = SSLCopyBufferFromData(dhParams, dhParamsLen, - &ctx->dhParamsEncoded); - - return ortn; - -#endif /* APPLE_DH */ -} - -/* - * Return parameter block specified in SSLSetDiffieHellmanParams. - * Returned data is not copied and belongs to the SSLContextRef. - */ -OSStatus SSLGetDiffieHellmanParams( - SSLContextRef ctx, - const void **dhParams, - size_t *dhParamsLen) -{ -#if APPLE_DH - if(ctx == NULL) { - return errSecParam; - } - *dhParams = ctx->dhParamsEncoded.data; - *dhParamsLen = ctx->dhParamsEncoded.length; - return errSecSuccess; -#else - return errSecUnimplemented; -#endif /* APPLE_DH */ -} - -OSStatus SSLSetRsaBlinding( - SSLContextRef ctx, - Boolean blinding) -{ - if(ctx == NULL) { - return errSecParam; - } - ctx->rsaBlindingEnable = blinding; - return errSecSuccess; -} - -OSStatus SSLGetRsaBlinding( - SSLContextRef ctx, - Boolean *blinding) -{ - if(ctx == NULL) { - return errSecParam; - } - *blinding = ctx->rsaBlindingEnable; - return errSecSuccess; -} - -OSStatus -SSLCopyPeerTrust( - SSLContextRef ctx, - SecTrustRef *trust) /* RETURNED */ -{ - OSStatus status = errSecSuccess; - if (ctx == NULL || trust == NULL) - return errSecParam; - - /* Create a SecTrustRef if this was a resumed session and we - didn't have one yet. */ - if (!ctx->peerSecTrust && ctx->peerCert) { - status = sslCreateSecTrust(ctx, ctx->peerCert, true, - &ctx->peerSecTrust); - } - - *trust = ctx->peerSecTrust; - if (ctx->peerSecTrust) - CFRetain(ctx->peerSecTrust); - - return status; -} - -OSStatus SSLGetPeerSecTrust( - SSLContextRef ctx, - SecTrustRef *trust) /* RETURNED */ -{ - OSStatus status = errSecSuccess; - if (ctx == NULL || trust == NULL) - return errSecParam; - - /* Create a SecTrustRef if this was a resumed session and we - didn't have one yet. */ - if (!ctx->peerSecTrust && ctx->peerCert) { - status = sslCreateSecTrust(ctx, ctx->peerCert, true, - &ctx->peerSecTrust); - } - - *trust = ctx->peerSecTrust; - return status; -} - -OSStatus SSLInternalMasterSecret( - SSLContextRef ctx, - void *secret, // mallocd by caller, SSL_MASTER_SECRET_SIZE - size_t *secretSize) // in/out -{ - if((ctx == NULL) || (secret == NULL) || (secretSize == NULL)) { - return errSecParam; - } - if(*secretSize < SSL_MASTER_SECRET_SIZE) { - return errSecParam; - } - memmove(secret, ctx->masterSecret, SSL_MASTER_SECRET_SIZE); - *secretSize = SSL_MASTER_SECRET_SIZE; - return errSecSuccess; -} - -OSStatus SSLInternalServerRandom( - SSLContextRef ctx, - void *randBuf, // mallocd by caller, SSL_CLIENT_SRVR_RAND_SIZE - size_t *randSize) // in/out -{ - if((ctx == NULL) || (randBuf == NULL) || (randSize == NULL)) { - return errSecParam; - } - if(*randSize < SSL_CLIENT_SRVR_RAND_SIZE) { - return errSecParam; - } - memmove(randBuf, ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE); - *randSize = SSL_CLIENT_SRVR_RAND_SIZE; - return errSecSuccess; -} - -OSStatus SSLInternalClientRandom( - SSLContextRef ctx, - void *randBuf, // mallocd by caller, SSL_CLIENT_SRVR_RAND_SIZE - size_t *randSize) // in/out -{ - if((ctx == NULL) || (randBuf == NULL) || (randSize == NULL)) { - return errSecParam; - } - if(*randSize < SSL_CLIENT_SRVR_RAND_SIZE) { - return errSecParam; - } - memmove(randBuf, ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE); - *randSize = SSL_CLIENT_SRVR_RAND_SIZE; - return errSecSuccess; -} - -/* This is used by EAP 802.1x */ -OSStatus SSLGetCipherSizes( - SSLContextRef ctx, - size_t *digestSize, - size_t *symmetricKeySize, - size_t *ivSize) -{ - const SSLCipherSpecParams *currCipher; - - if((ctx == NULL) || (digestSize == NULL) || - (symmetricKeySize == NULL) || (ivSize == NULL)) { - return errSecParam; - } - currCipher = &ctx->selectedCipherSpecParams; - *digestSize = currCipher->macSize; - *symmetricKeySize = currCipher->keySize; - *ivSize = currCipher->ivSize; - return errSecSuccess; -} - -OSStatus -SSLGetResumableSessionInfo( - SSLContextRef ctx, - Boolean *sessionWasResumed, // RETURNED - void *sessionID, // RETURNED, mallocd by caller - size_t *sessionIDLength) // IN/OUT -{ - if((ctx == NULL) || (sessionWasResumed == NULL) || - (sessionID == NULL) || (sessionIDLength == NULL) || - (*sessionIDLength < MAX_SESSION_ID_LENGTH)) { - return errSecParam; - } - if(ctx->sessionMatch) { - *sessionWasResumed = true; - if(ctx->sessionID.length > *sessionIDLength) { - /* really should never happen - means ID > 32 */ - return errSecParam; - } - if(ctx->sessionID.length) { - /* - * Note PAC-based session resumption can result in sessionMatch - * with no sessionID - */ - memmove(sessionID, ctx->sessionID.data, ctx->sessionID.length); - } - *sessionIDLength = ctx->sessionID.length; - } - else { - *sessionWasResumed = false; - *sessionIDLength = 0; - } - return errSecSuccess; -} - -/* - * Get/set enable of anonymous ciphers. Default is enabled. - */ -OSStatus -SSLSetAllowAnonymousCiphers( - SSLContextRef ctx, - Boolean enable) -{ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - return errSecBadReq; - } - if(ctx->validCipherSuites != NULL) { - /* SSLSetEnabledCiphers() has already been called */ - return errSecBadReq; - } - ctx->anonCipherEnable = enable; - return errSecSuccess; -} - -OSStatus -SSLGetAllowAnonymousCiphers( - SSLContextRef ctx, - Boolean *enable) -{ - if((ctx == NULL) || (enable == NULL)) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - return errSecBadReq; - } - *enable = ctx->anonCipherEnable; - return errSecSuccess; -} - -/* - * Override the default session cache timeout for a cache entry created for - * the current session. - */ -OSStatus -SSLSetSessionCacheTimeout( - SSLContextRef ctx, - uint32_t timeoutInSeconds) -{ - if(ctx == NULL) { - return errSecParam; - } - ctx->sessionCacheTimeout = timeoutInSeconds; - return errSecSuccess; -} - -/* - * Register a callback for obtaining the master_secret when performing - * PAC-based session resumption. - */ -OSStatus -SSLInternalSetMasterSecretFunction( - SSLContextRef ctx, - SSLInternalMasterSecretFunction mFunc, - const void *arg) /* opaque to SecureTransport; app-specific */ -{ - if(ctx == NULL) { - return errSecParam; - } - ctx->masterSecretCallback = mFunc; - ctx->masterSecretArg = arg; - return errSecSuccess; -} - -/* - * Provide an opaque SessionTicket for use in PAC-based session - * resumption. Client side only. The provided ticket is sent in - * the ClientHello message as a SessionTicket extension. - * - * We won't reject this on the server side, but server-side support - * for PAC-based session resumption is currently enabled for - * Development builds only. To fully support this for server side, - * besides the rudimentary support that's here for Development builds, - * we'd need a getter for the session ticket, so the app code can - * access the SessionTicket when its SSLInternalMasterSecretFunction - * callback is called. - */ -OSStatus SSLInternalSetSessionTicket( - SSLContextRef ctx, - const void *ticket, - size_t ticketLength) -{ - if(ctx == NULL) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - if(ticketLength > 0xffff) { - /* extension data encoded with a 2-byte length! */ - return errSecParam; - } - SSLFreeBuffer(&ctx->sessionTicket); - return SSLCopyBufferFromData(ticket, ticketLength, &ctx->sessionTicket); -} - -/* - * ECDSA curve accessors. - */ - -/* - * Obtain the SSL_ECDSA_NamedCurve negotiated during a handshake. - * Returns errSecParam if no ECDH-related ciphersuite was negotiated. - */ -OSStatus SSLGetNegotiatedCurve( - SSLContextRef ctx, - SSL_ECDSA_NamedCurve *namedCurve) /* RETURNED */ -{ - if((ctx == NULL) || (namedCurve == NULL)) { - return errSecParam; - } - if(ctx->ecdhPeerCurve == SSL_Curve_None) { - return errSecParam; - } - *namedCurve = ctx->ecdhPeerCurve; - return errSecSuccess; -} - -/* - * Obtain the number of currently enabled SSL_ECDSA_NamedCurves. - */ -OSStatus SSLGetNumberOfECDSACurves( - SSLContextRef ctx, - unsigned *numCurves) /* RETURNED */ -{ - if((ctx == NULL) || (numCurves == NULL)) { - return errSecParam; - } - *numCurves = ctx->ecdhNumCurves; - return errSecSuccess; -} - -/* - * Obtain the ordered list of currently enabled SSL_ECDSA_NamedCurves. - */ -OSStatus SSLGetECDSACurves( - SSLContextRef ctx, - SSL_ECDSA_NamedCurve *namedCurves, /* RETURNED */ - unsigned *numCurves) /* IN/OUT */ -{ - if((ctx == NULL) || (namedCurves == NULL) || (numCurves == NULL)) { - return errSecParam; - } - if(*numCurves < ctx->ecdhNumCurves) { - return errSecParam; - } - memmove(namedCurves, ctx->ecdhCurves, - (ctx->ecdhNumCurves * sizeof(SSL_ECDSA_NamedCurve))); - *numCurves = ctx->ecdhNumCurves; - return errSecSuccess; -} - -/* - * Specify ordered list of allowable named curves. - */ -OSStatus SSLSetECDSACurves( - SSLContextRef ctx, - const SSL_ECDSA_NamedCurve *namedCurves, - unsigned numCurves) -{ - if((ctx == NULL) || (namedCurves == NULL) || (numCurves == 0)) { - return errSecParam; - } - if(numCurves > SSL_ECDSA_NUM_CURVES) { - return errSecParam; - } - if(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - memmove(ctx->ecdhCurves, namedCurves, (numCurves * sizeof(SSL_ECDSA_NamedCurve))); - ctx->ecdhNumCurves = numCurves; - return errSecSuccess; -} - -/* - * Obtain the number of client authentication mechanisms specified by - * the server in its Certificate Request message. - * Returns errSecParam if server hasn't sent a Certificate Request message - * (i.e., client certificate state is kSSLClientCertNone). - */ -OSStatus SSLGetNumberOfClientAuthTypes( - SSLContextRef ctx, - unsigned *numTypes) -{ - if((ctx == NULL) || (ctx->clientCertState == kSSLClientCertNone)) { - return errSecParam; - } - *numTypes = ctx->numAuthTypes; - return errSecSuccess; -} - -/* - * Obtain the client authentication mechanisms specified by - * the server in its Certificate Request message. - * Caller allocates returned array and specifies its size (in - * SSLClientAuthenticationTypes) in *numType on entry; *numTypes - * is the actual size of the returned array on successful return. - */ -OSStatus SSLGetClientAuthTypes( - SSLContextRef ctx, - SSLClientAuthenticationType *authTypes, /* RETURNED */ - unsigned *numTypes) /* IN/OUT */ -{ - if((ctx == NULL) || (ctx->clientCertState == kSSLClientCertNone)) { - return errSecParam; - } - memmove(authTypes, ctx->clientAuthTypes, - ctx->numAuthTypes * sizeof(SSLClientAuthenticationType)); - *numTypes = ctx->numAuthTypes; - return errSecSuccess; -} - -/* - * Obtain the SSLClientAuthenticationType actually performed. - * Only valid if client certificate state is kSSLClientCertSent - * or kSSLClientCertRejected; returns errSecParam otherwise. - */ -OSStatus SSLGetNegotiatedClientAuthType( - SSLContextRef ctx, - SSLClientAuthenticationType *authType) /* RETURNED */ -{ - if(ctx == NULL) { - return errSecParam; - } - *authType = ctx->negAuthType; - return errSecSuccess; -} - -/* - * Update the negotiated client authentication type. - * This function may be called at any time; however, note that - * the negotiated authentication type will be SSLClientAuthNone - * until both of the following have taken place (in either order): - * - a CertificateRequest message from the server has been processed - * - a client certificate has been specified - * As such, this function (only) needs to be called from (both) - * SSLProcessCertificateRequest and SSLSetCertificate. - */ -OSStatus SSLUpdateNegotiatedClientAuthType( - SSLContextRef ctx) -{ - if(ctx == NULL) { - return errSecParam; - } - /* - * See if we have a signing cert that matches one of the - * allowed auth types. The x509Requested flag indicates "we - * have a cert that we think the server will accept". - */ - ctx->x509Requested = 0; - ctx->negAuthType = SSLClientAuthNone; - if(ctx->signingPrivKeyRef != NULL) { - CFIndex ourKeyAlg = sslPubKeyGetAlgorithmID(ctx->signingPubKey); - unsigned i; - for(i=0; inumAuthTypes; i++) { - switch(ctx->clientAuthTypes[i]) { - case SSLClientAuth_RSASign: - if(ourKeyAlg == kSecRSAAlgorithmID) { - ctx->x509Requested = 1; - ctx->negAuthType = SSLClientAuth_RSASign; - } - break; - #if SSL_ENABLE_ECDSA_SIGN_AUTH - case SSLClientAuth_ECDSASign: - #endif - #if SSL_ENABLE_ECDSA_FIXED_ECDH_AUTH - case SSLClientAuth_ECDSAFixedECDH: - #endif - if((ourKeyAlg == kSecECDSAAlgorithmID) && - (ctx->ourSignerAlg == kSecECDSAAlgorithmID)) { - ctx->x509Requested = 1; - ctx->negAuthType = ctx->clientAuthTypes[i]; - } - break; - #if SSL_ENABLE_RSA_FIXED_ECDH_AUTH - case SSLClientAuth_RSAFixedECDH: - /* Odd case, we differ from our signer */ - if((ourKeyAlg == kSecECDSAAlgorithmID) && - (ctx->ourSignerAlg == kSecRSAAlgorithmID)) { - ctx->x509Requested = 1; - ctx->negAuthType = SSLClientAuth_RSAFixedECDH; - } - break; - #endif - default: - /* None others supported */ - break; - } - if(ctx->x509Requested) { - sslLogNegotiateDebug("===CHOOSING authType %d", (int)ctx->negAuthType); - break; - } - } /* parsing authTypes */ - } /* we have a signing key */ - - return errSecSuccess; -} - -OSStatus SSLGetNumberOfSignatureAlgorithms( - SSLContextRef ctx, - unsigned *numSigAlgs) -{ - if((ctx == NULL) || (ctx->clientCertState == kSSLClientCertNone)) { - return errSecParam; - } - *numSigAlgs = ctx->numServerSigAlgs; - return errSecSuccess; -} - -OSStatus SSLGetSignatureAlgorithms( - SSLContextRef ctx, - SSLSignatureAndHashAlgorithm *sigAlgs, /* RETURNED */ - unsigned *numSigAlgs) /* IN/OUT */ -{ - if((ctx == NULL) || (ctx->clientCertState == kSSLClientCertNone)) { - return errSecParam; - } - memmove(sigAlgs, ctx->serverSigAlgs, - ctx->numServerSigAlgs * sizeof(SSLSignatureAndHashAlgorithm)); - *numSigAlgs = ctx->numServerSigAlgs; - return errSecSuccess; -} - -/* PSK SPIs */ -OSStatus SSLSetPSKSharedSecret(SSLContextRef ctx, - const void *secret, - size_t secretLen) -{ - if(ctx == NULL) return errSecParam; - - if(ctx->pskSharedSecret.data) - SSLFreeBuffer(&ctx->pskSharedSecret); - - if(SSLCopyBufferFromData(secret, secretLen, &ctx->pskSharedSecret)) - return errSecAllocate; - - return errSecSuccess; -} - -OSStatus SSLSetPSKIdentity(SSLContextRef ctx, - const void *pskIdentity, - size_t pskIdentityLen) -{ - if((ctx == NULL) || (pskIdentity == NULL) || (pskIdentityLen == 0)) return errSecParam; - - if(ctx->pskIdentity.data) - SSLFreeBuffer(&ctx->pskIdentity); - - if(SSLCopyBufferFromData(pskIdentity, pskIdentityLen, &ctx->pskIdentity)) - return errSecAllocate; - - return errSecSuccess; - -} - -OSStatus SSLGetPSKIdentity(SSLContextRef ctx, - const void **pskIdentity, - size_t *pskIdentityLen) -{ - if((ctx == NULL) || (pskIdentity == NULL) || (pskIdentityLen == NULL)) return errSecParam; - - *pskIdentity=ctx->pskIdentity.data; - *pskIdentityLen=ctx->pskIdentity.length; - return errSecSuccess; -} - - -#ifdef USE_SSLCERTIFICATE - -size_t -SSLGetCertificateChainLength(const SSLCertificate *c) -{ - size_t rtn = 0; - - while (c) - { - rtn++; - c = c->next; - } - return rtn; -} - -OSStatus sslDeleteCertificateChain( - SSLCertificate *certs, - SSLContext *ctx) -{ - SSLCertificate *cert; - SSLCertificate *nextCert; - - assert(ctx != NULL); - cert=certs; - while(cert != NULL) { - nextCert = cert->next; - SSLFreeBuffer(&cert->derCert); - sslFree(cert); - cert = nextCert; - } - return errSecSuccess; -} -#endif /* USE_SSLCERTIFICATE */