#include "ssl.h"
#include "sslContext.h"
#include "sslMemory.h"
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
#include "sslDigests.h"
#include "sslDebug.h"
#include "appleCdsa.h"
#include "sslKeychain.h"
#include "sslUtils.h"
#include "cipherSpecs.h"
#include "appleSession.h"
#include "sslBER.h"
#include <string.h>
#include <Security/SecCertificate.h>
#include <Security/SecTrust.h>
static void sslFreeDnList(
SSLContext *ctx)
{
DNListElem *dn, *nextDN;
dn = ctx->acceptableDNList;
while (dn)
{
SSLFreeBuffer(dn->derDN, ctx);
nextDN = dn->next;
sslFree(dn);
dn = nextDN;
}
ctx->acceptableDNList = NULL;
}
static OSStatus sslFreeTrustedRoots(
SSLContext *ctx)
{
unsigned i;
assert(ctx != NULL);
if((ctx->numTrustedCerts == 0) || (ctx->trustedCerts == NULL)) {
assert((ctx->numTrustedCerts == 0) && (ctx->trustedCerts == NULL));
}
else {
for(i=0; i<ctx->numTrustedCerts; i++) {
stFreeCssmData(&ctx->trustedCerts[i], CSSM_FALSE);
}
sslFree(ctx->trustedCerts);
}
ctx->numTrustedCerts = 0;
ctx->trustedCerts = NULL;
sslFreeDnList(ctx);
return noErr;
}
#define DEFAULT_SSL2_ENABLE true
#define DEFAULT_SSL3_ENABLE true
#define DEFAULT_TLS1_ENABLE true
OSStatus
SSLNewContext (Boolean isServer,
SSLContextRef *contextPtr)
{
SSLContext *ctx;
OSStatus serr;
if(contextPtr == NULL) {
return paramErr;
}
*contextPtr = NULL;
ctx = (SSLContext *)sslMalloc(sizeof(SSLContext));
if(ctx == NULL) {
return memFullErr;
}
memset(ctx, 0, sizeof(SSLContext));
ctx->state = SSL_HdskStateUninit;
ctx->clientCertState = kSSLClientCertNone;
ctx->versionSsl2Enable = DEFAULT_SSL2_ENABLE;
ctx->versionSsl3Enable = DEFAULT_SSL3_ENABLE;
ctx->versionTls1Enable = DEFAULT_TLS1_ENABLE;
ctx->negProtocolVersion = SSL_Version_Undetermined;
if(isServer) {
ctx->protocolSide = SSL_ServerSide;
}
else {
ctx->protocolSide = SSL_ClientSide;
}
ctx->sslTslCalls = &Ssl3Callouts;
ctx->selectedCipherSpec = &SSL_NULL_WITH_NULL_NULL_CipherSpec;
ctx->selectedCipher = ctx->selectedCipherSpec->cipherSpec;
ctx->writeCipher.macRef = ctx->selectedCipherSpec->macAlgorithm;
ctx->readCipher.macRef = ctx->selectedCipherSpec->macAlgorithm;
ctx->readCipher.symCipher = ctx->selectedCipherSpec->cipher;
ctx->writeCipher.symCipher = ctx->selectedCipherSpec->cipher;
ctx->writeCipher.encrypting = 1;
ctx->writePending.encrypting = 1;
ctx->validCipherSpecs = NULL;
ctx->numValidCipherSpecs = 0;
ctx->peerDomainName = NULL;
ctx->peerDomainNameLen = 0;
serr = attachToAll(ctx);
if(serr) {
goto errOut;
}
ctx->enableCertVerify = true;
ctx->rsaBlindingEnable = true;
*contextPtr = ctx;
return noErr;
errOut:
sslFree(ctx);
return serr;
}
OSStatus
SSLDisposeContext (SSLContext *ctx)
{
WaitingRecord *wait, *next;
SSLBuffer buf;
if(ctx == NULL) {
return paramErr;
}
sslDeleteCertificateChain(ctx->localCert, ctx);
sslDeleteCertificateChain(ctx->encryptCert, ctx);
sslDeleteCertificateChain(ctx->peerCert, ctx);
ctx->localCert = ctx->encryptCert = ctx->peerCert = NULL;
SSLFreeBuffer(ctx->partialReadBuffer, ctx);
if(ctx->peerSecTrust) {
CFRelease(ctx->peerSecTrust);
ctx->peerSecTrust = NULL;
}
wait = ctx->recordWriteQueue;
while (wait)
{ SSLFreeBuffer(wait->data, ctx);
next = wait->next;
buf.data = (uint8*)wait;
buf.length = sizeof(WaitingRecord);
SSLFreeBuffer(buf, ctx);
wait = next;
}
#if APPLE_DH
SSLFreeBuffer(ctx->dhParamsPrime, ctx);
SSLFreeBuffer(ctx->dhParamsGenerator, ctx);
SSLFreeBuffer(ctx->dhParamsEncoded, ctx);
SSLFreeBuffer(ctx->dhPeerPublic, ctx);
SSLFreeBuffer(ctx->dhExchangePublic, ctx);
sslFreeKey(ctx->cspHand, &ctx->dhPrivate, NULL);
#endif
CloseHash(SSLHashSHA1, ctx->shaState, ctx);
CloseHash(SSLHashMD5, ctx->md5State, ctx);
SSLFreeBuffer(ctx->sessionID, ctx);
SSLFreeBuffer(ctx->peerID, ctx);
SSLFreeBuffer(ctx->resumableSession, ctx);
SSLFreeBuffer(ctx->preMasterSecret, ctx);
SSLFreeBuffer(ctx->partialReadBuffer, ctx);
SSLFreeBuffer(ctx->fragmentedMessageCache, ctx);
SSLFreeBuffer(ctx->receivedDataBuffer, ctx);
if(ctx->peerDomainName) {
sslFree(ctx->peerDomainName);
ctx->peerDomainName = NULL;
ctx->peerDomainNameLen = 0;
}
SSLDisposeCipherSuite(&ctx->readCipher, ctx);
SSLDisposeCipherSuite(&ctx->writeCipher, ctx);
SSLDisposeCipherSuite(&ctx->readPending, ctx);
SSLDisposeCipherSuite(&ctx->writePending, ctx);
sslFree(ctx->validCipherSpecs);
ctx->validCipherSpecs = NULL;
ctx->numValidCipherSpecs = 0;
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);
}
sslFreeTrustedRoots(ctx);
detachFromAll(ctx);
memset(ctx, 0, sizeof(SSLContext));
sslFree(ctx);
sslCleanupSession();
return noErr;
}
OSStatus
SSLGetSessionState (SSLContextRef context,
SSLSessionState *state)
{
SSLSessionState rtnState = kSSLIdle;
if(context == NULL) {
return paramErr;
}
*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 <= SSL2_HdskStateServerFinished));
rtnState = kSSLHandshake;
break;
}
*state = rtnState;
return noErr;
}
OSStatus
SSLSetIOFuncs (SSLContextRef ctx,
SSLReadFunc read,
SSLWriteFunc write)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
ctx->ioCtx.read = read;
ctx->ioCtx.write = write;
return noErr;
}
OSStatus
SSLSetConnection (SSLContextRef ctx,
SSLConnectionRef connection)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
ctx->ioCtx.ioRef = connection;
return noErr;
}
OSStatus
SSLGetConnection (SSLContextRef ctx,
SSLConnectionRef *connection)
{
if((ctx == NULL) || (connection == NULL)) {
return paramErr;
}
*connection = ctx->ioCtx.ioRef;
return noErr;
}
OSStatus
SSLSetPeerDomainName (SSLContextRef ctx,
const char *peerName,
size_t peerNameLen)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
if(ctx->peerDomainName) {
sslFree(ctx->peerDomainName);
}
ctx->peerDomainName = (char *)sslMalloc(peerNameLen);
if(ctx->peerDomainName == NULL) {
return memFullErr;
}
memmove(ctx->peerDomainName, peerName, peerNameLen);
ctx->peerDomainNameLen = peerNameLen;
return noErr;
}
OSStatus
SSLGetPeerDomainNameLength (SSLContextRef ctx,
size_t *peerNameLen) {
if(ctx == NULL) {
return paramErr;
}
*peerNameLen = ctx->peerDomainNameLen;
return noErr;
}
OSStatus
SSLGetPeerDomainName (SSLContextRef ctx,
char *peerName, size_t *peerNameLen) {
if(ctx == NULL) {
return paramErr;
}
if(*peerNameLen < ctx->peerDomainNameLen) {
return errSSLBufferOverflow;
}
memmove(peerName, ctx->peerDomainName, ctx->peerDomainNameLen);
*peerNameLen = ctx->peerDomainNameLen;
return noErr;
}
static SSLProtocol convertProtToExtern(SSLProtocolVersion prot)
{
switch(prot) {
case SSL_Version_Undetermined:
return kSSLProtocolUnknown;
case SSL_Version_2_0:
return kSSLProtocol2;
case SSL_Version_3_0:
return kSSLProtocol3;
case TLS_Version_1_0:
return kTLSProtocol1;
default:
sslErrorLog("convertProtToExtern: bad prot\n");
return kSSLProtocolUnknown;
}
return kSSLProtocolUnknown;
}
OSStatus
SSLSetProtocolVersionEnabled(SSLContextRef ctx,
SSLProtocol protocol,
Boolean enable)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
switch(protocol) {
case kSSLProtocol2:
ctx->versionSsl2Enable = enable;
break;
case kSSLProtocol3:
ctx->versionSsl3Enable = enable;
break;
case kTLSProtocol1:
ctx->versionTls1Enable = enable;
break;
case kSSLProtocolAll:
ctx->versionTls1Enable = ctx->versionSsl3Enable =
ctx->versionSsl2Enable = enable;
break;
default:
return paramErr;
}
return noErr;
}
OSStatus
SSLGetProtocolVersionEnabled(SSLContextRef ctx,
SSLProtocol protocol,
Boolean *enable)
{
if(ctx == NULL) {
return paramErr;
}
switch(protocol) {
case kSSLProtocol2:
*enable = ctx->versionSsl2Enable;
break;
case kSSLProtocol3:
*enable = ctx->versionSsl3Enable;
break;
case kTLSProtocol1:
*enable = ctx->versionTls1Enable;
break;
case kSSLProtocolAll:
if(ctx->versionTls1Enable && ctx->versionSsl3Enable &&
ctx->versionSsl2Enable) {
*enable = true;
}
else {
*enable = false;
}
break;
default:
return paramErr;
}
return noErr;
}
OSStatus
SSLSetProtocolVersion (SSLContextRef ctx,
SSLProtocol version)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
switch(version) {
case kSSLProtocolUnknown:
ctx->versionSsl2Enable = DEFAULT_SSL2_ENABLE;
ctx->versionSsl3Enable = DEFAULT_SSL3_ENABLE;
ctx->versionTls1Enable = DEFAULT_TLS1_ENABLE;
break;
case kSSLProtocol2:
ctx->versionSsl2Enable = true;
ctx->versionSsl3Enable = false;
ctx->versionTls1Enable = false;
break;
case kSSLProtocol3:
ctx->versionSsl2Enable = true;
ctx->versionSsl3Enable = true;
ctx->versionTls1Enable = false;
break;
case kSSLProtocol3Only:
ctx->versionSsl2Enable = false;
ctx->versionSsl3Enable = true;
ctx->versionTls1Enable = false;
break;
case kTLSProtocol1:
case kSSLProtocolAll:
ctx->versionSsl2Enable = true;
ctx->versionSsl3Enable = true;
ctx->versionTls1Enable = true;
break;
case kTLSProtocol1Only:
ctx->versionSsl2Enable = false;
ctx->versionSsl3Enable = false;
ctx->versionTls1Enable = true;
break;
default:
return paramErr;
}
return noErr;
}
OSStatus
SSLGetProtocolVersion (SSLContextRef ctx,
SSLProtocol *protocol)
{
if(ctx == NULL) {
return paramErr;
}
if(ctx->versionTls1Enable) {
if(ctx->versionSsl2Enable) {
if(ctx->versionSsl3Enable) {
*protocol = kTLSProtocol1;
return noErr;
}
else {
return paramErr;
}
}
else if(ctx->versionSsl3Enable) {
return paramErr;
}
else {
*protocol = kTLSProtocol1Only;
return noErr;
}
}
else {
if(ctx->versionSsl3Enable) {
*protocol = ctx->versionSsl2Enable ?
kSSLProtocol3 : kSSLProtocol3Only;
return noErr;
}
else if(ctx->versionSsl2Enable) {
*protocol = kSSLProtocol2;
return noErr;
}
else {
return paramErr;
}
}
}
OSStatus
SSLGetNegotiatedProtocolVersion (SSLContextRef ctx,
SSLProtocol *protocol)
{
if(ctx == NULL) {
return paramErr;
}
*protocol = convertProtToExtern(ctx->negProtocolVersion);
return noErr;
}
OSStatus
SSLSetEnableCertVerify (SSLContextRef ctx,
Boolean enableVerify)
{
if(ctx == NULL) {
return paramErr;
}
sslCertDebug("SSLSetEnableCertVerify %s",
enableVerify ? "true" : "false");
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
ctx->enableCertVerify = enableVerify;
return noErr;
}
OSStatus
SSLGetEnableCertVerify (SSLContextRef ctx,
Boolean *enableVerify)
{
if(ctx == NULL) {
return paramErr;
}
*enableVerify = ctx->enableCertVerify;
return noErr;
}
OSStatus
SSLSetAllowsExpiredCerts(SSLContextRef ctx,
Boolean allowExpired)
{
if(ctx == NULL) {
return paramErr;
}
sslCertDebug("SSLSetAllowsExpiredCerts %s",
allowExpired ? "true" : "false");
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
ctx->allowExpiredCerts = allowExpired;
return noErr;
}
OSStatus
SSLGetAllowsExpiredCerts (SSLContextRef ctx,
Boolean *allowExpired)
{
if(ctx == NULL) {
return paramErr;
}
*allowExpired = ctx->allowExpiredCerts;
return noErr;
}
OSStatus
SSLSetAllowsExpiredRoots(SSLContextRef ctx,
Boolean allowExpired)
{
if(ctx == NULL) {
return paramErr;
}
sslCertDebug("SSLSetAllowsExpiredRoots %s",
allowExpired ? "true" : "false");
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
ctx->allowExpiredRoots = allowExpired;
return noErr;
}
OSStatus
SSLGetAllowsExpiredRoots (SSLContextRef ctx,
Boolean *allowExpired)
{
if(ctx == NULL) {
return paramErr;
}
*allowExpired = ctx->allowExpiredRoots;
return noErr;
}
OSStatus SSLSetAllowsAnyRoot(
SSLContextRef ctx,
Boolean anyRoot)
{
if(ctx == NULL) {
return paramErr;
}
sslCertDebug("SSLSetAllowsAnyRoot %s", anyRoot ? "true" : "false");
ctx->allowAnyRoot = anyRoot;
return noErr;
}
OSStatus
SSLGetAllowsAnyRoot(
SSLContextRef ctx,
Boolean *anyRoot)
{
if(ctx == NULL) {
return paramErr;
}
*anyRoot = ctx->allowAnyRoot;
return noErr;
}
OSStatus
SSLSetTrustedRoots (SSLContextRef ctx,
CFArrayRef trustedRoots,
Boolean replaceExisting)
{
unsigned dex;
unsigned outDex;
unsigned numIncoming;
uint32 numCerts;
CSSM_DATA_PTR newRoots = NULL;
const CSSM_DATA *existAnchors = NULL;
uint32 numExistAnchors = 0;
OSStatus ortn = noErr;
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
numCerts = numIncoming = CFArrayGetCount(trustedRoots);
sslCertDebug("SSLSetTrustedRoot numCerts %d replaceExist %s",
(int)numCerts, replaceExisting ? "true" : "false");
if(!replaceExisting) {
if(ctx->trustedCerts != NULL) {
existAnchors = ctx->trustedCerts;
numExistAnchors = ctx->numTrustedCerts;
}
else {
ortn = SecTrustGetCSSMAnchorCertificates(&existAnchors,
&numExistAnchors);
if(ortn) {
return ortn;
}
}
numCerts += numExistAnchors;
}
newRoots = (CSSM_DATA_PTR)sslMalloc(numCerts * sizeof(CSSM_DATA));
memset(newRoots, 0, numCerts * sizeof(CSSM_DATA));
for(dex=0, outDex=0; dex<numIncoming; dex++, outDex++) {
CSSM_DATA certData;
SecCertificateRef secCert = (SecCertificateRef)
CFArrayGetValueAtIndex(trustedRoots, dex);
if(CFGetTypeID(secCert) != SecCertificateGetTypeID()) {
ortn = paramErr;
goto abort;
}
ortn = SecCertificateGetData(secCert, &certData);
if(ortn) {
goto abort;
}
stSetUpCssmData(&newRoots[outDex], certData.Length);
memmove(newRoots[outDex].Data, certData.Data, certData.Length);
}
for(dex=0; dex<numExistAnchors; dex++, outDex++) {
stSetUpCssmData(&newRoots[outDex], existAnchors[dex].Length);
memmove(newRoots[outDex].Data, existAnchors[dex].Data,
existAnchors[dex].Length);
}
sslFreeTrustedRoots(ctx);
ctx->numTrustedCerts = numCerts;
ctx->trustedCerts = newRoots;
return noErr;
abort:
sslFree(newRoots);
return ortn;
}
OSStatus
SSLGetTrustedRoots (SSLContextRef ctx,
CFArrayRef *trustedRoots)
{
uint32 numCerts;
const CSSM_DATA *certs;
CFMutableArrayRef certArray;
unsigned dex;
SecCertificateRef secCert;
OSStatus ortn;
if(ctx == NULL) {
return paramErr;
}
if(ctx->trustedCerts != NULL) {
certs = ctx->trustedCerts;
numCerts = ctx->numTrustedCerts;
}
else {
OSStatus ortn = SecTrustGetCSSMAnchorCertificates(&certs,
&numCerts);
if(ortn) {
return ortn;
}
}
certArray = CFArrayCreateMutable(kCFAllocatorDefault,
(CFIndex)numCerts, &kCFTypeArrayCallBacks);
if(certArray == NULL) {
return memFullErr;
}
for(dex=0; dex<numCerts; dex++) {
ortn = SecCertificateCreateFromData(&certs[dex],
CSSM_CERT_X_509v3,
CSSM_CERT_ENCODING_DER,
&secCert);
if(ortn) {
CFRelease(certArray);
return ortn;
}
CFArrayAppendValue(certArray, secCert);
}
*trustedRoots = certArray;
return noErr;
}
OSStatus
SSLSetClientSideAuthenticate (SSLContext *ctx,
SSLAuthenticate auth)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
ctx->clientAuth = auth;
switch(auth) {
case kNeverAuthenticate:
ctx->tryClientAuth = false;
break;
case kAlwaysAuthenticate:
case kTryAuthenticate:
ctx->tryClientAuth = true;
break;
}
return noErr;
}
OSStatus
SSLGetClientCertificateState (SSLContextRef ctx,
SSLClientCertificateState *clientState)
{
if(ctx == NULL) {
return paramErr;
}
*clientState = ctx->clientCertState;
return noErr;
}
OSStatus
SSLSetCertificate (SSLContextRef ctx,
CFArrayRef certRefs)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
return parseIncomingCerts(ctx,
certRefs,
&ctx->localCert,
&ctx->signingPubKey,
&ctx->signingPrivKeyRef);
}
OSStatus
SSLSetEncryptionCertificate (SSLContextRef ctx,
CFArrayRef certRefs)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
return parseIncomingCerts(ctx,
certRefs,
&ctx->encryptCert,
&ctx->encryptPubKey,
&ctx->encryptPrivKeyRef);
}
OSStatus
SSLSetPeerID (SSLContext *ctx,
const void *peerID,
size_t peerIDLen)
{
OSStatus serr;
if((ctx == NULL) ||
(peerID == NULL) ||
(peerIDLen == 0)) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
SSLFreeBuffer(ctx->peerID, ctx);
serr = SSLAllocBuffer(ctx->peerID, peerIDLen, ctx);
if(serr) {
return serr;
}
memmove(ctx->peerID.data, peerID, peerIDLen);
return noErr;
}
OSStatus
SSLGetPeerID (SSLContextRef ctx,
const void **peerID,
size_t *peerIDLen)
{
*peerID = ctx->peerID.data; *peerIDLen = ctx->peerID.length;
return noErr;
}
OSStatus
SSLGetNegotiatedCipher (SSLContextRef ctx,
SSLCipherSuite *cipherSuite)
{
if(ctx == NULL) {
return paramErr;
}
if(!sslIsSessionActive(ctx)) {
return badReqErr;
}
*cipherSuite = (SSLCipherSuite)ctx->selectedCipher;
return noErr;
}
OSStatus
SSLAddDistinguishedName(
SSLContextRef ctx,
const void *derDN,
size_t derDNLen)
{
DNListElem *dn;
OSStatus err;
dn = (DNListElem *)sslMalloc(sizeof(DNListElem));
if(dn == NULL) {
return memFullErr;
}
if ((err = SSLAllocBuffer(dn->derDN, derDNLen, ctx)) != 0)
return err;
memcpy(dn->derDN.data, derDN, derDNLen);
dn->next = ctx->acceptableDNList;
ctx->acceptableDNList = dn;
return noErr;
}
OSStatus
SSLGetPeerCertificates (SSLContextRef ctx,
CFArrayRef *certs)
{
uint32 numCerts;
CFMutableArrayRef ca;
CFIndex i;
SecCertificateRef cfd;
OSStatus ortn;
CSSM_DATA certData;
SSLCertificate *scert;
if(ctx == NULL) {
return paramErr;
}
*certs = NULL;
numCerts = SSLGetCertificateChainLength(ctx->peerCert);
if(numCerts == 0) {
return noErr;
}
ca = CFArrayCreateMutable(kCFAllocatorDefault,
(CFIndex)numCerts, &kCFTypeArrayCallBacks);
if(ca == NULL) {
return memFullErr;
}
scert = ctx->peerCert;
for(i=0; (unsigned)i<numCerts; i++) {
assert(scert != NULL);
SSLBUF_TO_CSSM(&scert->derCert, &certData);
ortn = SecCertificateCreateFromData(&certData,
CSSM_CERT_X_509v3,
CSSM_CERT_ENCODING_DER,
&cfd);
if(ortn) {
CFRelease(ca);
return ortn;
}
CFArrayInsertValueAtIndex(ca, 0, cfd);
scert = scert->next;
}
*certs = ca;
return noErr;
}
OSStatus SSLSetDiffieHellmanParams(
SSLContextRef ctx,
const void *dhParams,
size_t dhParamsLen)
{
if(ctx == NULL) {
return paramErr;
}
if(sslIsSessionActive(ctx)) {
return badReqErr;
}
SSLFreeBuffer(ctx->dhParamsPrime, ctx);
SSLFreeBuffer(ctx->dhParamsGenerator, ctx);
SSLFreeBuffer(ctx->dhParamsEncoded, ctx);
OSStatus ortn;
ortn = SSLCopyBufferFromData(dhParams, dhParamsLen,
ctx->dhParamsEncoded);
if(ortn) {
return ortn;
}
SSLBuffer sParams;
sParams.data = (UInt8 *)dhParams;
sParams.length = dhParamsLen;
return sslDecodeDhParams(&sParams, &ctx->dhParamsPrime,
&ctx->dhParamsGenerator);
}
OSStatus SSLGetDiffieHellmanParams(
SSLContextRef ctx,
const void **dhParams,
size_t *dhParamsLen)
{
if(ctx == NULL) {
return paramErr;
}
*dhParams = ctx->dhParamsEncoded.data;
*dhParamsLen = ctx->dhParamsEncoded.length;
return noErr;
}
OSStatus SSLSetRsaBlinding(
SSLContextRef ctx,
Boolean blinding)
{
if(ctx == NULL) {
return paramErr;
}
ctx->rsaBlindingEnable = blinding;
return noErr;
}
OSStatus SSLGetRsaBlinding(
SSLContextRef ctx,
Boolean *blinding)
{
if(ctx == NULL) {
return paramErr;
}
*blinding = ctx->rsaBlindingEnable;
return noErr;
}
OSStatus SSLGetPeerSecTrust(
SSLContextRef ctx,
SecTrustRef *secTrust)
{
if(ctx == NULL) {
return paramErr;
}
*secTrust = ctx->peerSecTrust;
return noErr;
}
OSStatus SSLInternalMasterSecret(
SSLContextRef ctx,
void *secret, size_t *secretSize) {
if((ctx == NULL) || (secret == NULL) || (secretSize == NULL)) {
return paramErr;
}
if(*secretSize < SSL_MASTER_SECRET_SIZE) {
return paramErr;
}
memmove(secret, ctx->masterSecret, SSL_MASTER_SECRET_SIZE);
*secretSize = SSL_MASTER_SECRET_SIZE;
return noErr;
}
OSStatus SSLInternalServerRandom(
SSLContextRef ctx,
void *rand, size_t *randSize) {
if((ctx == NULL) || (rand == NULL) || (randSize == NULL)) {
return paramErr;
}
if(*randSize < SSL_CLIENT_SRVR_RAND_SIZE) {
return paramErr;
}
memmove(rand, ctx->serverRandom, SSL_CLIENT_SRVR_RAND_SIZE);
*randSize = SSL_CLIENT_SRVR_RAND_SIZE;
return noErr;
}
OSStatus SSLInternalClientRandom(
SSLContextRef ctx,
void *rand, size_t *randSize) {
if((ctx == NULL) || (rand == NULL) || (randSize == NULL)) {
return paramErr;
}
if(*randSize < SSL_CLIENT_SRVR_RAND_SIZE) {
return paramErr;
}
memmove(rand, ctx->clientRandom, SSL_CLIENT_SRVR_RAND_SIZE);
*randSize = SSL_CLIENT_SRVR_RAND_SIZE;
return noErr;
}
OSStatus
SSLGetResumableSessionInfo(
SSLContextRef ctx,
Boolean *sessionWasResumed, void *sessionID, size_t *sessionIDLength) {
if((ctx == NULL) || (sessionWasResumed == NULL) ||
(sessionID == NULL) || (sessionIDLength == NULL) ||
(*sessionIDLength < MAX_SESSION_ID_LENGTH)) {
return paramErr;
}
if(ctx->sessionMatch) {
assert(ctx->sessionID.data != NULL);
*sessionWasResumed = true;
if(ctx->sessionID.length > *sessionIDLength) {
return paramErr;
}
memmove(sessionID, ctx->sessionID.data, ctx->sessionID.length);
*sessionIDLength = ctx->sessionID.length;
}
else {
*sessionWasResumed = false;
*sessionIDLength = 0;
}
return noErr;
}