X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_ssl/lib/sslContext.c diff --git a/Security/libsecurity_ssl/lib/sslContext.c b/Security/libsecurity_ssl/lib/sslContext.c deleted file mode 100644 index a0f35ae0..00000000 --- a/Security/libsecurity_ssl/lib/sslContext.c +++ /dev/null @@ -1,2576 +0,0 @@ -/* - * Copyright (c) 1999-2001,2005-2014 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 "tlsCallbacks.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include "utilities/SecCFRelease.h" -#include "utilities/SecCFWrappers.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_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 */ - -int kSplitDefaultValue; -CFIndex kMinDhGroupSizeDefaultValue; - -#if TARGET_OS_IPHONE -/* - * Instead of using CFPropertyListReadFromFile we use a - * CFPropertyListCreateWithStream directly - * here. CFPropertyListReadFromFile() uses - * CFURLCopyResourcePropertyForKey() andCF pulls in CoreServices for - * CFURLCopyResourcePropertyForKey() and that doesn't work in install - * enviroment. - */ -static CFPropertyListRef -CopyPlistFromFile(CFURLRef url) -{ - CFDictionaryRef d = NULL; - CFReadStreamRef s = CFReadStreamCreateWithFile(kCFAllocatorDefault, url); - if (s && CFReadStreamOpen(s)) { - d = (CFDictionaryRef)CFPropertyListCreateWithStream(kCFAllocatorDefault, s, 0, kCFPropertyListImmutable, NULL, NULL); - } - CFReleaseSafe(s); - - return d; -} -#endif - -static void _SSLContextReadDefault() -{ - /* 0 = disabled, 1 = split every write, 2 = split second and subsequent writes */ - /* Enabled by default, this may cause some interop issues, see and */ - const int defaultSplitDefaultValue = 2; - - 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; - } - - /* Min DH Group Size */ - kMinDhGroupSizeDefaultValue = CFPreferencesGetAppIntegerValue(CFSTR("SSLMinDhGroupSize"), kCFPreferencesCurrentApplication, NULL); - -#if TARGET_OS_IPHONE - /* on iOS, if the above returned nothing, we manually look into mobile's Managed Preferences */ - /* Note that if the process is running as mobile, the above call will already have read the Managed Preference plist. - As a result, if you have some preferences set manually with defaults, which preference applies may be different for mobile vs not-mobile. */ - if(kMinDhGroupSizeDefaultValue == 0) { - CFURLRef prefURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, CFSTR("/Library/Managed Preferences/mobile/.GlobalPreferences.plist"), kCFURLPOSIXPathStyle, false); - if(prefURL) { - CFPropertyListRef plist = CopyPlistFromFile(prefURL); - if (plist) { - value = CFDictionaryGetValue(plist, CFSTR("SSLMinDhGroupSize")); - if (isNumber(value)) { - CFNumberGetValue(value, kCFNumberCFIndexType, &kMinDhGroupSizeDefaultValue); - } - } - CFReleaseSafe(plist); - } - CFReleaseSafe(prefURL); - } -#endif -} - -CFGiblisWithHashFor(SSLContext) - -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; - SSLRecordContextRef recCtx; - - ctx = SSLCreateContextWithRecordFuncs(alloc, protocolSide, connectionType, &SSLRecordLayerInternal); - - if(ctx==NULL) - return NULL; - - recCtx = SSLCreateInternalRecordLayer(connectionType); - if(recCtx==NULL) { - CFRelease(ctx); - return NULL; - } - - SSLSetRecordContext(ctx, recCtx); - - 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->hdsk = tls_handshake_create(connectionType==kSSLDatagramType, protocolSide==kSSLServerSide); - - - tls_handshake_set_callbacks(ctx->hdsk, - &tls_handshake_callbacks, - ctx); - - ctx->isDTLS = (connectionType==kSSLDatagramType); - - ctx->state = SSL_HdskStateUninit; - ctx->timeout_duration = DEFAULT_DTLS_TIMEOUT; - ctx->mtu = DEFAULT_DTLS_MTU; - - if(ctx->isDTLS) { - ctx->minProtocolVersion = MINIMUM_DATAGRAM_VERSION; - ctx->maxProtocolVersion = MAXIMUM_DATAGRAM_VERSION; - } else { - ctx->minProtocolVersion = MINIMUM_STREAM_VERSION; - ctx->maxProtocolVersion = MAXIMUM_STREAM_VERSION; - } - tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); - tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); - - ctx->negProtocolVersion = SSL_Version_Undetermined; - ctx->protocolSide = protocolSide; - ctx->recFuncs = recFuncs; - - /* 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; - - /* Dont enable fallback behavior by default */ - ctx->fallbackEnabled = 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(kMinDhGroupSizeDefaultValue) { - tls_handshake_set_min_dh_group_size(ctx->hdsk, (unsigned)kMinDhGroupSizeDefaultValue); - } - - /* 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; - - ctx->negAuthType = SSLClientAuthNone; /* ditto */ - - 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; -} - -CFStringRef SSLContextCopyFormatDescription(CFTypeRef arg, CFDictionaryRef formatOptions) -{ - SSLContext* ctx = (SSLContext*) arg; - - if (ctx == NULL) { - return NULL; - } else { - CFStringRef result = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR(""), ctx); - return result; - } -} - -Boolean SSLContextCompare(CFTypeRef a, CFTypeRef b) -{ - return a == b; -} - -CFHashCode SSLContextHash(CFTypeRef arg) -{ - return (CFHashCode) arg; -} - -void SSLContextDestroy(CFTypeRef arg) -{ - SSLContext* ctx = (SSLContext*) arg; - - /* destroy the coreTLS handshake object */ - tls_handshake_destroy(ctx->hdsk); - - /* Only destroy if we were using the internal record layer */ - if(ctx->recFuncs==&SSLRecordLayerInternal) - SSLDestroyInternalRecordLayer(ctx->recCtx); - - SSLFreeBuffer(&ctx->sessionTicket); - SSLFreeBuffer(&ctx->sessionID); - SSLFreeBuffer(&ctx->peerID); - SSLFreeBuffer(&ctx->resumableSession); - SSLFreeBuffer(&ctx->receivedDataBuffer); - - sslFree(ctx->validCipherSuites); - ctx->validCipherSuites = NULL; - ctx->numValidCipherSuites = 0; - - CFReleaseSafe(ctx->acceptableCAs); - CFReleaseSafe(ctx->trustedLeafCerts); - CFReleaseSafe(ctx->localCertArray); - CFReleaseSafe(ctx->encryptCertArray); - CFReleaseSafe(ctx->encryptCertArray); - CFReleaseSafe(ctx->peerCert); - CFReleaseSafe(ctx->trustedCerts); - CFReleaseSafe(ctx->peerSecTrust); - - sslFreePrivKey(&ctx->signingPrivKeyRef); - sslFreePrivKey(&ctx->encryptPrivKeyRef); - - sslFree(ctx->localCert); - sslFree(ctx->encryptCert); - - - sslFreeDnList(ctx); - - SSLFreeBuffer(&ctx->ownVerifyData); - SSLFreeBuffer(&ctx->peerVerifyData); - - SSLFreeBuffer(&ctx->pskIdentity); - SSLFreeBuffer(&ctx->pskSharedSecret); - - SSLFreeBuffer(&ctx->dhParamsEncoded); - - 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: - rtnState = kSSLIdle; - break; - case SSL_HdskStateGracefulClose: - rtnState = kSSLClosed; - break; - case SSL_HdskStateErrorClose: - case SSL_HdskStateNoNotifyClose: - rtnState = kSSLAborted; - break; - case SSL_HdskStateReady: - rtnState = kSSLConnected; - break; - case SSL_HdskStatePending: - 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: - /* Only call the record layer function if the value changed */ - if(value != context->oneByteRecordEnable) - context->recFuncs->setOption(context->recCtx, kSSLRecordOptionSendOneByteRecord, value); - context->oneByteRecordEnable = value; - break; - case kSSLSessionOptionFalseStart: - context->falseStartEnabled = value; - break; - case kSSLSessionOptionFallback: - tls_handshake_set_fallback(context->hdsk, value); - context->fallbackEnabled = 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); -} - -void -SSLSetNPNFunc(SSLContextRef context, - SSLNPNFunc npnFunc, - void *info) -{ - if (context == NULL) { - return; - } - if (sslIsSessionActive(context)) { - return; - } - context->npnFunc = npnFunc; - context->npnFuncInfo = info; - if(context->protocolSide==kSSLClientSide) { - tls_handshake_set_npn_enable(context->hdsk, npnFunc!=NULL); - } -} - -OSStatus -SSLSetNPNData(SSLContextRef context, - const void *data, - size_t length) -{ - if (context == NULL || data == NULL || length == 0) { - return errSecParam; - } - - if (length > 255) { - return errSecParam; - } - - tls_buffer npn_data; - - npn_data.data = (uint8_t *)data; - npn_data.length = length; - - return tls_handshake_set_npn_data(context->hdsk, npn_data); -} - -const void * -SSLGetNPNData(SSLContextRef context, - size_t *length) -{ - if (context == NULL || length == NULL) - return NULL; - - const tls_buffer *npn_data; - - npn_data = tls_handshake_get_peer_npn_data(context->hdsk); - - if(npn_data) { - *length = npn_data->length; - return npn_data->data; - } else { - return NULL; - } -} - -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; - } - - if(ctx->protocolSide == kSSLClientSide) { - return tls_handshake_set_peer_hostname(ctx->hdsk, peerName, peerNameLen); - } else { - return 0; // This should probably return an error, but historically didnt. - } -} - -/* - * Determine the buffer size needed for SSLGetPeerDomainName(). - */ -OSStatus -SSLGetPeerDomainNameLength (SSLContextRef ctx, - size_t *peerNameLen) // RETURNED -{ - if(ctx == NULL) { - return errSecParam; - } - const char *hostname; - - return tls_handshake_get_peer_hostname(ctx->hdsk, &hostname, peerNameLen); -} - -OSStatus -SSLGetPeerDomainName (SSLContextRef ctx, - char *peerName, // returned here - size_t *peerNameLen) // IN/OUT -{ - const char *hostname; - size_t len; - - int err; - - if(ctx == NULL) { - return errSecParam; - } - - err=tls_handshake_get_peer_hostname(ctx->hdsk, &hostname, &len); - - if(err) { - return err; - } else if(*peerNameLenisDTLS) 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; - - tls_handshake_set_mtu(ctx->hdsk, 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 */ - -#warning SecureTransport: SSLGetDatagramWriteSize is wrong, need hookup with coreTLS -#if 0 - SSLCipherSpecParams *currCipher = &ctx->selectedCipherSpecParams; - - size_t blockSize = currCipher->blockSize; - size_t macSize = currCipher->macSize; -#else - size_t blockSize = 16; - size_t macSize = 32; -#endif - - 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; - - tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); - tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); - - 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; - - tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); - tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); - - 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; - } - } - } - - tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); - tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); - - 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; - } - - tls_handshake_set_min_protocol_version(ctx->hdsk, ctx->minProtocolVersion); - tls_handshake_set_max_protocol_version(ctx->hdsk, ctx->maxProtocolVersion); - - 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 - -{ - const char *hostname; - size_t len; - - tls_handshake_get_peer_hostname(ctx->hdsk, &hostname, &len); - - return SecTrustSettingsCopyQualifiedCerts(&CSSMOID_APPLE_TP_SSL, - hostname, - (uint32_t)len, - (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: - tls_handshake_set_client_auth(ctx->hdsk, false); - break; - case kAlwaysAuthenticate: - case kTryAuthenticate: - tls_handshake_set_client_auth(ctx->hdsk, 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->signingPrivKeyRef); - if(ortn == errSecSuccess) { - ctx->localCertArray = certRefs; - CFRetain(certRefs); - if(ctx->protocolSide==kSSLClientSide) - SSLUpdateNegotiatedClientAuthType(ctx); - tls_handshake_set_identity(ctx->hdsk, ctx->localCert, ctx->signingPrivKeyRef); - } - 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->encryptPrivKeyRef); - 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; - } - tls_handshake_set_resumption(ctx->hdsk, true); - 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)tls_handshake_get_negotiated_cipherspec(ctx->hdsk); - - 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; - - tls_handshake_set_acceptable_dn_list(ctx->hdsk, 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; - const DNListElem *dn; - - if((ctx == NULL) || (names == NULL)) { - return errSecParam; - } - if(ctx->protocolSide==kSSLServerSide) { - dn = ctx->acceptableDNList; - } else { - dn = tls_handshake_get_peer_acceptable_dn_list(ctx->hdsk); // ctx->acceptableDNList; - } - - if(dn == NULL) { - *names = NULL; - return errSecSuccess; - } - outArray = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); - - 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; - } - - 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)); - } - } - - 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); - - 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 SSLSetMinimumDHGroupSize(SSLContextRef ctx, unsigned nbits) -{ - return tls_handshake_set_min_dh_group_size(ctx->hdsk, nbits); -} - -OSStatus SSLGetMinimumDHGroupSize(SSLContextRef ctx, unsigned *nbits) -{ - return tls_handshake_get_min_dh_group_size(ctx->hdsk, nbits); -} - -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->peerCert) { - ctx->peerCert = tls_get_peer_certs(tls_handshake_get_peer_certificates(ctx->hdsk)); - } - 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; - } - return tls_handshake_internal_master_secret(ctx->hdsk, secret, secretSize); -} - -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; - } - return tls_handshake_internal_server_random(ctx->hdsk, randBuf, randSize); -} - -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; - } - return tls_handshake_internal_client_random(ctx->hdsk, randBuf, randSize); -} - -/* This is used by EAP 802.1x */ -OSStatus SSLGetCipherSizes( - SSLContextRef ctx, - size_t *digestSize, - size_t *symmetricKeySize, - size_t *ivSize) -{ - if((ctx == NULL) || (digestSize == NULL) || - (symmetricKeySize == NULL) || (ivSize == NULL)) { - return errSecParam; - } - - SSLCipherSuite cipher=tls_handshake_get_negotiated_cipherspec(ctx->hdsk); - - *digestSize = sslCipherSuiteGetMacSize(cipher); - *symmetricKeySize = sslCipherSuiteGetSymmetricCipherKeySize(cipher); - *ivSize = sslCipherSuiteGetSymmetricCipherBlockIvSize(cipher); - 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; - } - - SSLBuffer localSessionID; - bool sessionMatch = tls_handshake_get_session_match(ctx->hdsk, &localSessionID); - - if(sessionMatch) { - *sessionWasResumed = true; - if(localSessionID.length > *sessionIDLength) { - /* really should never happen - means ID > 32 */ - return errSecParam; - } - if(localSessionID.length) { - /* - * Note PAC-based session resumption can result in sessionMatch - * with no sessionID - */ - memmove(sessionID, localSessionID.data, localSessionID.length); - } - *sessionIDLength = localSessionID.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; -} - - -static -void tls_handshake_master_secret_function(const void *arg, /* opaque to coreTLS; app-specific */ - void *secret, /* mallocd by caller, SSL_MASTER_SECRET_SIZE */ - size_t *secretLength) -{ - SSLContextRef ctx = (SSLContextRef) arg; - ctx->masterSecretCallback(ctx, ctx->masterSecretArg, secret, secretLength); -} - - -/* - * 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->masterSecretArg = arg; - ctx->masterSecretCallback = mFunc; - - return tls_handshake_internal_set_master_secret_function(ctx->hdsk, &tls_handshake_master_secret_function, ctx); -} - -/* - * 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; - } - return tls_handshake_internal_set_session_ticket(ctx->hdsk, ticket, ticketLength); -} - - -/* - * 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; - } - unsigned int curve = tls_handshake_get_negotiated_curve(ctx->hdsk); - if(curve == SSL_Curve_None) { - return errSecParam; - } - *namedCurve = curve; - 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(sslIsSessionActive(ctx)) { - /* can't do this with an active session */ - return errSecBadReq; - } - - size_t size = numCurves * sizeof(uint16_t); - ctx->ecdhCurves = (uint16_t *)sslMalloc(size); - if(ctx->ecdhCurves == NULL) { - ctx->ecdhNumCurves = 0; - return errSecAllocate; - } - - for (unsigned i=0; iecdhCurves[i] = namedCurves[i]; - } - - ctx->ecdhNumCurves = numCurves; - - tls_handshake_set_curves(ctx->hdsk, ctx->ecdhCurves, ctx->ecdhNumCurves); - 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; - } - assert(ctx->protocolSide==kSSLClientSide); - /* - * 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 = sslPrivKeyGetAlgorithmID((SecKeyRef)tls_private_key_get_context(ctx->signingPrivKeyRef)); - assert(ourKeyAlg==kSecRSAAlgorithmID); /* We don't suport anything else */ - - 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 0 -// The code below is hopelessly broken: ctx->ourSignerAlg is never set - #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 -#endif - default: - /* None others supported */ - break; - } - if(ctx->x509Requested) { - sslLogNegotiateDebug("===CHOOSING authType %d", (int)ctx->negAuthType); - break; - } - } /* parsing authTypes */ - } /* we have a signing key */ - - tls_handshake_set_client_auth_type(ctx->hdsk, ctx->negAuthType); - - return errSecSuccess; -} - -OSStatus SSLGetNumberOfSignatureAlgorithms( - SSLContextRef ctx, - unsigned *numSigAlgs) -{ - if(ctx == NULL){ - return errSecParam; - } - - tls_handshake_get_peer_signature_algorithms(ctx->hdsk, numSigAlgs); - return errSecSuccess; -} - -_Static_assert(sizeof(SSLSignatureAndHashAlgorithm)==sizeof(tls_signature_and_hash_algorithm), - "SSLSignatureAndHashAlgorithm and tls_signature_and_hash_algorithm do not match"); - -OSStatus SSLGetSignatureAlgorithms( - SSLContextRef ctx, - SSLSignatureAndHashAlgorithm *sigAlgs, /* RETURNED */ - unsigned *numSigAlgs) /* IN/OUT */ -{ - if(ctx == NULL) { - return errSecParam; - } - - unsigned numPeerSigAlgs; - const tls_signature_and_hash_algorithm *peerAlgs = tls_handshake_get_peer_signature_algorithms(ctx->hdsk, &numPeerSigAlgs); - - memmove(sigAlgs, peerAlgs, - numPeerSigAlgs * sizeof(SSLSignatureAndHashAlgorithm)); - *numSigAlgs = numPeerSigAlgs; - 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; - - tls_handshake_set_psk_secret(ctx->hdsk, &ctx->pskSharedSecret); - - 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; - - tls_handshake_set_psk_identity(ctx->hdsk, &ctx->pskIdentity); - - 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; -} - -OSStatus SSLInternal_PRF( - SSLContext *ctx, - const void *vsecret, - size_t secretLen, - const void *label, // optional, NULL implies that seed contains - // the label - size_t labelLen, - const void *seed, - size_t seedLen, - void *vout, // mallocd by caller, length >= outLen - size_t outLen) -{ - return tls_handshake_internal_prf(ctx->hdsk, - vsecret, secretLen, - label, labelLen, - seed, seedLen, - vout, outLen); -} - -