tls_private_key_t tls_private_key_create(tls_private_key_desc_t *desc, tls_private_key_ctx_t ctx, tls_private_key_ctx_release ctx_release) { tls_private_key_t key; key = sslMalloc(sizeof(struct _tls_private_key)); if(key==NULL) return NULL; key->ctx = ctx; key->ctx_release = ctx_release; key->desc.type = desc->type; switch(desc->type) { case tls_private_key_type_rsa: key->desc.rsa = desc->rsa; break; case tls_private_key_type_ecdsa: key->desc.ecdsa = desc->ecdsa; break; default: sslFree(key); key = NULL; break; } return key; }
/* Set DH parameters - Server only */ int tls_handshake_set_dh_parameters(tls_handshake_t filter, tls_buffer *params) { assert(filter->isServer); assert(params); const uint8_t *der, *der_end; size_t n; der = params->data; der_end = params->data + params->length; n = ccder_decode_dhparam_n(der, der_end); sslFree(filter->dhParams.gp); filter->dhParams.gp = sslMalloc(ccdh_gp_size(ccn_sizeof_n(n))); if(!filter->dhParams.gp) { return errSSLAllocate; } CCDH_GP_N(filter->dhParams) = n; der = ccder_decode_dhparams(filter->dhParams, der, der_end); if (der == NULL) { return errSSLParam; } else { return 0; } }
/* NOTE: The SigAlgs set here are only used to select which SigAlgs to advertise and select a SigAlg for private key operations in TLS 1.2, and is mainly here to allow unit testing. If the peer select a SigAlg that we support but was not set here, coreTLS will still proceed and verify signature. */ int tls_handshake_set_sigalgs(tls_handshake_t filter, const tls_signature_and_hash_algorithm *sigalgs, unsigned n) { unsigned i; unsigned count = 0; for(i=0;i<n;i++) { if(tls_handshake_sigalg_is_supported(sigalgs[i])) count++; } sslFree(filter->localSigAlgs); filter->numLocalSigAlgs = 0; filter->localSigAlgs = sslMalloc(count*sizeof(tls_signature_and_hash_algorithm)); if(!filter->localSigAlgs) { return errSSLAllocate; } for(i=0;i<n;i++) { if(tls_handshake_sigalg_is_supported(sigalgs[i])) { filter->localSigAlgs[filter->numLocalSigAlgs++]=sigalgs[i]; } } assert(filter->numLocalSigAlgs == count); return 0; }
/* Convert a SecCertificateRef to an SSLCertificate * */ static OSStatus secCertToSslCert( SSLContext *ctx, SecCertificateRef certRef, SSLCertificate **sslCert) { CSSM_DATA certData; // struct is transient, referent owned by // Sec layer OSStatus ortn; SSLCertificate *thisSslCert = NULL; ortn = SecCertificateGetData(certRef, &certData); if(ortn) { sslErrorLog("SecCertificateGetData() returned %d\n", (int)ortn); return ortn; } thisSslCert = (SSLCertificate *)sslMalloc(sizeof(SSLCertificate)); if(thisSslCert == NULL) { return memFullErr; } if(SSLAllocBuffer(&thisSslCert->derCert, certData.Length, ctx)) { return memFullErr; } memcpy(thisSslCert->derCert.data, certData.Data, certData.Length); thisSslCert->derCert.length = certData.Length; *sslCert = thisSslCert; return noErr; }
int tls_handshake_set_curves(tls_handshake_t filter, const uint16_t *curves, unsigned n) { unsigned i; unsigned count = 0; uint16_t *_c; for(i=0;i<n;i++) { uint16_t c = curves[i]; if(tls_handshake_curve_is_supported(c)) count++; } sslFree(filter->ecdhCurves); filter->ecdhNumCurves=0; _c = sslMalloc(count*sizeof(uint16_t)); if(!_c) { return errSSLAllocate; } filter->ecdhNumCurves = count; filter->ecdhCurves = _c; for(i=0;i<n;i++) { uint16_t c = curves[i]; if(tls_handshake_curve_is_supported(c)) *_c++ = c; } return 0; }
/* * This constructor, the only one, allocs copies of the key and value * SSLBuffers. */ static SessionCacheEntry *SessionCacheEntryCreate( const tls_buffer *key, const tls_buffer *sessionData, CFAbsoluteTime expirationTime) { OSStatus serr; SessionCacheEntry *entry = sslMalloc(sizeof(SessionCacheEntry)); if (entry == NULL) return NULL; serr = SSLCopyBuffer(key, &entry->mKey); if(serr) { sslFree (entry); return NULL; } serr = SSLCopyBuffer(sessionData, &entry->mSessionData); if(serr) { SSLFreeBuffer(&entry->mKey); sslFree (entry); return NULL; } sslLogSessCacheDebug("SessionCacheEntryCreate(buf,buf) %p", entry); entry->mExpiration = expirationTime; return entry; }
int SSLDecodeBufferList(uint8_t *p, size_t listLen, int itemLenSize, tls_buffer_list_t **list) { int err = 0; tls_buffer_list_t *first = NULL; tls_buffer_list_t *last = NULL; while (listLen > 0) { size_t itemLen; tls_buffer_list_t *item; if (listLen < itemLenSize) { sslErrorLog("SSLDecodeBufferList: length decode error 2\n"); err = errSSLProtocol; goto errOut; } itemLen = SSLDecodeInt(p,itemLenSize); p += itemLenSize; if (listLen < itemLen + itemLenSize) { sslErrorLog("SSLDecodeBufferList: length decode error 3\n"); err = errSSLProtocol; goto errOut; } if(itemLen==0) { sslErrorLog("SSLDecodeBufferList: lenght decode error 4 (empty item)\n"); err = errSSLProtocol; goto errOut; } item = (tls_buffer_list_t *)sslMalloc(sizeof(tls_buffer_list_t)); if(item == NULL) { err = errSSLAllocate; goto errOut; } if ((err = SSLAllocBuffer(&item->buffer, itemLen))) { sslFree(item); goto errOut; } item->next = NULL; memcpy(item->buffer.data, p, itemLen); p += itemLen; if(first==NULL) { first=item; last=item; } else { last->next=item; last=item; } listLen -= itemLenSize+itemLen; } *list = first; return 0; errOut: tls_free_buffer_list(first); return err; }
int tls_handshake_set_acceptable_client_auth_type(tls_handshake_t filter, tls_client_auth_type *auth_types, unsigned n) { assert(filter->isServer); sslFree(filter->clientAuthTypes); filter->clientAuthTypes = sslMalloc(sizeof(tls_client_auth_type)*n); if(filter->clientAuthTypes==NULL) return errSSLAllocate; filter->numAuthTypes = n; memcpy(filter->clientAuthTypes, auth_types, sizeof(tls_client_auth_type)*n); return 0; }
uint8_t *sslAllocCopy( const uint8_t *src, size_t len) { uint8_t *dst; dst = (uint8_t *)sslMalloc(len); if(dst == NULL) { return NULL; } memmove(dst, src, len); return dst; }
/* Set TLS user agent string, for diagnostic purposes */ int tls_handshake_set_user_agent(tls_handshake_t filter, const char *user_agent) { sslFree(filter->userAgent); filter->userAgent = NULL; if(user_agent) { filter->userAgent = sslMalloc(strlen(user_agent)+1); strcpy(filter->userAgent, user_agent); } return 0; }
/* * Given raw RSA key bits, cook up a SSLPubKey. Used in * Server-initiated key exchange. */ OSStatus sslGetPubKeyFromBits( SSLContext *ctx, const SSLBuffer *modulus, const SSLBuffer *exponent, SSLPubKey **pubKey) // mallocd and RETURNED { if (!pubKey) return paramErr; #if 0 SSLPubKey *key; RSAStatus rsaStatus; RSAPubKey apiKey = { modulus->data, modulus->length, NULL, 0, exponent->data, exponent->length }; key = sslMalloc(sizeof(*key)); rsaStatus = rsaInitPubGKey(&apiKey, &key->rsaKey); if (rsaStatus) { sslFree(key); return rsaStatusToSSL(rsaStatus); } *pubKey = key; return noErr; #else check(pubKey); SecRSAPublicKeyParams params = { modulus->data, modulus->length, exponent->data, exponent->length }; #if SSL_DEBUG sslDebugLog("Creating RSA pub key from modulus=%p len=%lu exponent=%p len=%lu\n", (uintptr_t)modulus->data, modulus->length, (uintptr_t)exponent->data, exponent->length); #endif SecKeyRef key = SecKeyCreateRSAPublicKey(NULL, (const uint8_t *)¶ms, sizeof(params), kSecKeyEncodingRSAPublicParams); if (!key) { sslErrorLog("sslGetPubKeyFromBits: SecKeyCreateRSAPublicKey failed\n"); return errSSLCrypto; } #if SSL_DEBUG size_t blocksize = SecKeyGetBlockSize(key); sslDebugLog("sslGetPubKeyFromBits: RSA pub key block size=%lu\n", blocksize); #endif *pubKey = (SSLPubKey*)key; return noErr; #endif }
int SSLAllocBuffer( SSLBuffer *buf, size_t length) { buf->data = (uint8_t *)sslMalloc(length); if(buf->data == NULL) { sslErrorLog("SSLAllocBuffer: NULL buf!\n"); check(0); buf->length = 0; return -1; } buf->length = length; return 0; }
/* Create an HMAC session */ static OSStatus HMAC_Alloc( const struct HMACReference *hmac, SSLContext *ctx, const void *keyPtr, unsigned keyLen, HMACContextRef *hmacCtxOut) // RETURNED { CCHmacAlgorithm ccAlg; HMACContextRef hmacCtx = (HMACContextRef)sslMalloc(sizeof(struct HMACContext)); if(hmacCtx == NULL) { return memFullErr; } hmacCtx->ctx = ctx; hmacCtx->hmac = hmac; switch(hmac->alg) { case HA_SHA384: ccAlg = kCCHmacAlgSHA384; hmacCtx->macSize = CC_SHA384_DIGEST_LENGTH; break; case HA_SHA256: ccAlg = kCCHmacAlgSHA256; hmacCtx->macSize = CC_SHA256_DIGEST_LENGTH; break; case HA_SHA1: ccAlg = kCCHmacAlgSHA1; hmacCtx->macSize = CC_SHA1_DIGEST_LENGTH; break; case HA_MD5: ccAlg = kCCHmacAlgMD5; hmacCtx->macSize = CC_MD5_DIGEST_LENGTH; break; default: ASSERT(0); return errSSLInternal; } /* create the template from which individual record MAC-ers are cloned */ CCHmacInit(&hmacCtx->ccHmacTemplate, ccAlg, keyPtr, keyLen); *hmacCtxOut = hmacCtx; return noErr; }
void * sslRealloc(void *oldPtr, size_t oldLen, size_t newLen) { /* _REALLOC is in sys/malloc.h but is only exported in debug kernel */ /* return _REALLOC(oldPtr, newLen, M_TEMP, M_NOWAIT); */ /* FIXME */ void *newPtr; if(newLen>oldLen) { newPtr=sslMalloc(newLen); if(newPtr) { memcpy(newPtr, oldPtr, oldLen); sslFree(oldPtr); } } else { newPtr=oldPtr; } return newPtr; }
int SSLAllocCopyBuffer( const SSLBuffer *src, SSLBuffer **dst) // buffer and data mallocd and returned { int serr; SSLBuffer *rtn = (SSLBuffer *)sslMalloc(sizeof(SSLBuffer)); if(rtn == NULL) { sslErrorLog("SSLAllocCopyBuffer: NULL buf!\n"); check(0); return -1; } serr = SSLCopyBuffer(src, rtn); if(serr) { sslFree(rtn); } else { *dst = rtn; } return serr; }
static int tls_handshake_set_ciphersuites_internal(tls_handshake_t filter, tls_handshake_config_t config, const uint16_t *ciphersuites, unsigned n) { unsigned i; unsigned count = 0; uint16_t *_cs; for(i=0;i<n;i++) { uint16_t cs = ciphersuites[i]; if(tls_handshake_ciphersuite_is_supported(filter->isServer, filter->isDTLS, cs) && tls_handshake_ciphersuite_is_allowed(config, cs)) { count++; } } sslFree(filter->enabledCipherSuites); filter->numEnabledCipherSuites=0; _cs = sslMalloc(count*sizeof(uint16_t)); if(!_cs) { return errSSLAllocate; } filter->numEnabledCipherSuites = count; filter->enabledCipherSuites = _cs; for(i=0;i<n;i++) { uint16_t cs = ciphersuites[i]; if(tls_handshake_ciphersuite_is_supported(filter->isServer, filter->isDTLS, cs) && tls_handshake_ciphersuite_is_allowed(config, cs)) { *_cs++ = cs; } } sslAnalyzeCipherSpecs(filter); return 0; }
int SSLProcessCertificateRequest(tls_buffer message, tls_handshake_t ctx) { unsigned i; unsigned typeCount; unsigned shListLen = 0; UInt8 *charPtr; unsigned dnListLen; unsigned dnLen; tls_buffer dnBuf; DNListElem *dn; int err; /* * Cert request only happens in during client authentication. * Application can send a client cert if they have an appropriate one. * coreTLS does not ensure the client cert is appropriate. */ unsigned minLen = (sslVersionIsLikeTls12(ctx)) ? 5 : 3; if (message.length < minLen) { sslErrorLog("SSLProcessCertificateRequest: length decode error 1\n"); return errSSLProtocol; } charPtr = message.data; typeCount = *charPtr++; if ((typeCount < 1) || (message.length < minLen + typeCount)) { sslErrorLog("SSLProcessCertificateRequest: length decode error 2\n"); return errSSLProtocol; } /* Update the server-specified auth types */ sslFree(ctx->clientAuthTypes); ctx->numAuthTypes = typeCount; ctx->clientAuthTypes = (tls_client_auth_type *) sslMalloc(ctx->numAuthTypes * sizeof(tls_client_auth_type)); if(ctx->clientAuthTypes==NULL) return errSSLInternal; for(i=0; i<ctx->numAuthTypes; i++) { sslLogNegotiateDebug("===Server specifies authType %d", (int)(*charPtr)); ctx->clientAuthTypes[i] = (tls_client_auth_type)(*charPtr++); } if (sslVersionIsLikeTls12(ctx)) { /* Parse the supported_signature_algorithms field added in TLS1.2 */ shListLen = SSLDecodeInt(charPtr, 2); charPtr += 2; if ((shListLen < 2) || (message.length < minLen + typeCount + shListLen)) { sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n"); return errSSLProtocol; } if (shListLen & 1) { sslErrorLog("SSLProcessCertificateRequest: signAlg len odd\n"); return errSSLProtocol; } sslFree(ctx->peerSigAlgs); ctx->numPeerSigAlgs = shListLen / 2; ctx->peerSigAlgs = (tls_signature_and_hash_algorithm *) sslMalloc((ctx->numPeerSigAlgs) * sizeof(tls_signature_and_hash_algorithm)); if(ctx->peerSigAlgs==NULL) return errSSLInternal; for(i=0; i<ctx->numPeerSigAlgs; i++) { ctx->peerSigAlgs[i].hash = *charPtr++; ctx->peerSigAlgs[i].signature = *charPtr++; sslLogNegotiateDebug("===Server specifies sigAlg %d %d", ctx->peerSigAlgs[i].hash, ctx->peerSigAlgs[i].signature); } } /* Update the acceptable DNList */ SSLFreeDNList(ctx->acceptableDNList); ctx->acceptableDNList=NULL; dnListLen = SSLDecodeInt(charPtr, 2); charPtr += 2; if (message.length != minLen + typeCount + shListLen + dnListLen) { sslErrorLog("SSLProcessCertificateRequest: length decode error 3\n"); return errSSLProtocol; } while (dnListLen > 0) { if (dnListLen < 2) { sslErrorLog("SSLProcessCertificateRequest: dnListLen error 1\n"); return errSSLProtocol; } dnLen = SSLDecodeInt(charPtr, 2); charPtr += 2; if (dnListLen < 2 + dnLen) { sslErrorLog("SSLProcessCertificateRequest: dnListLen error 2\n"); return errSSLProtocol; } if ((err = SSLAllocBuffer(&dnBuf, sizeof(DNListElem)))) return err; dn = (DNListElem*)dnBuf.data; if ((err = SSLAllocBuffer(&dn->derDN, dnLen))) { SSLFreeBuffer(&dnBuf); return err; } memcpy(dn->derDN.data, charPtr, dnLen); charPtr += dnLen; dn->next = ctx->acceptableDNList; ctx->acceptableDNList = dn; dnListLen -= 2 + dnLen; } assert(charPtr == message.data + message.length); return errSSLSuccess; }
static OSStatus parseIncomingCerts(CFArrayRef certs, SSLCertificate **destCertChain, /* &ctx->{localCertChain,encryptCertChain} */ tls_private_key_t *sslPrivKey) /* &ctx->signingPrivKeyRef, etc. */ { OSStatus ortn; CFIndex ix, numCerts; SecIdentityRef identity; SSLCertificate *certChain = NULL; /* Retained */ SecCertificateRef leafCert = NULL; /* Retained */ SecKeyRef privKey = NULL; /* Retained */ assert(destCertChain != NULL); /* though its referent may be NULL */ assert(sslPrivKey != NULL); if (certs == NULL) { sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); ortn = errSSLBadCert; goto errOut; } numCerts = CFArrayGetCount(certs); if (numCerts == 0) { sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); ortn = errSSLBadCert; goto errOut; } certChain=sslMalloc(numCerts*sizeof(SSLCertificate)); if (!certChain) { ortn = errSecAllocate; goto errOut; } /* * Certs[0] is an SecIdentityRef from which we extract subject cert, * privKey, pubKey. * * 1. ensure the first element is a SecIdentityRef. */ identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); if (identity == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); ortn = errSecParam; goto errOut; } if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); ortn = errSecParam; goto errOut; } /* * 2. Extract cert, keys and convert to local format. */ ortn = SecIdentityCopyCertificate(identity, &leafCert); if (ortn) { sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); goto errOut; } /* Fetch private key from identity */ ortn = SecIdentityCopyPrivateKey(identity, &privKey); if (ortn) { sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", (int)ortn); goto errOut; } /* Convert the input array of SecIdentityRef at the start to an array of all certificates. */ SSLCopyBufferFromData(SecCertificateGetBytePtr(leafCert), SecCertificateGetLength(leafCert), &certChain[0].derCert); certChain[0].next = NULL; for (ix = 1; ix < numCerts; ++ix) { SecCertificateRef intermediate = (SecCertificateRef)CFArrayGetValueAtIndex(certs, ix); if (intermediate == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); ortn = errSecParam; goto errOut; } if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); ortn = errSecParam; goto errOut; } SSLCopyBufferFromData(SecCertificateGetBytePtr(intermediate), SecCertificateGetLength(intermediate), &certChain[ix].derCert); certChain[ix].next = NULL; certChain[ix-1].next = &certChain[ix]; } size_t size = SecKeyGetBlockSize(privKey); tls_private_key_desc_t desc; if(SecKeyGetAlgorithmId(privKey) == kSecRSAAlgorithmID) { desc.type = tls_private_key_type_rsa; desc.rsa.sign = mySSLPrivKeyRSA_sign; desc.rsa.decrypt = mySSLPrivKeyRSA_decrypt; desc.rsa.size = SecKeyGetBlockSize(privKey); } else if (SecKeyGetAlgorithmId(privKey) == kSecECDSAAlgorithmID) { desc.type = tls_private_key_type_ecdsa; desc.ecdsa.sign = mySSLPrivKeyECDSA_sign; desc.ecdsa.curve = SecECKeyGetNamedCurve(privKey); #if TARGET_OS_IPHONE /* Compute signature size from key size */ desc.ecdsa.size = 8+2*size; #else desc.ecdsa.size = size; #endif } else { ortn = errSecParam; goto errOut; } *sslPrivKey = tls_private_key_create(&desc, privKey, (tls_private_key_ctx_release)&CFRelease); if(*sslPrivKey) ortn = errSecSuccess; else ortn = errSecAllocate; /* SUCCESS */ errOut: CFReleaseSafe(leafCert); if (ortn) { free(certChain); CFReleaseSafe(privKey); *destCertChain = NULL; } else { *destCertChain = certChain; } return ortn; }
/* * Given a SSLCertificate cert, obtain its public key as a SSLPubKey. * Caller must sslFreePubKey and free the SSLPubKey itself. */ OSStatus sslPubKeyFromCert( SSLContext *ctx, const SSLCertificate *cert, SSLPubKey **pubKey) // RETURNED { DERItem der; DERSignedCertCrl signedCert; DERTBSCert tbsCert; DERSubjPubKeyInfo pubKeyInfo; DERByte numUnused; DERItem pubKeyPkcs1; SSLPubKey *key; DERReturn drtn; RSAStatus rsaStatus; assert(cert); assert(pubKey != NULL); der.data = cert->derCert.data; der.length = cert->derCert.length; /* top level decode */ drtn = DERParseSequence(&der, DERNumSignedCertCrlItemSpecs, DERSignedCertCrlItemSpecs, &signedCert, sizeof(signedCert)); if(drtn) return errSSLBadCert; /* decode the TBSCert - it was saved in full DER form */ drtn = DERParseSequence(&signedCert.tbs, DERNumTBSCertItemSpecs, DERTBSCertItemSpecs, &tbsCert, sizeof(tbsCert)); if(drtn) return errSSLBadCert; /* sequence we're given: encoded DERSubjPubKeyInfo */ drtn = DERParseSequenceContent(&tbsCert.subjectPubKey, DERNumSubjPubKeyInfoItemSpecs, DERSubjPubKeyInfoItemSpecs, &pubKeyInfo, sizeof(pubKeyInfo)); if(drtn) return errSSLBadCert; /* @@@ verify that this is an RSA key by decoding the AlgId */ /* * The contents of pubKeyInfo.pubKey is a bit string whose contents * are a PKCS1 format RSA key. */ drtn = DERParseBitString(&pubKeyInfo.pubKey, &pubKeyPkcs1, &numUnused); if(drtn) return errSSLBadCert; #if TARGET_OS_IOS /* Now we have the public key in pkcs1 format. Let's make a public key object out of it. */ key = sslMalloc(sizeof(*key)); rsaStatus = RSA_DecodePubKey(pubKeyPkcs1.data, pubKeyPkcs1.length, &key->rsaKey); if (rsaStatus) { sslFree(key); } #else SecKeyRef rsaPubKeyRef = SecKeyCreateRSAPublicKey(NULL, pubKeyPkcs1.data, pubKeyPkcs1.length, kSecKeyEncodingRSAPublicParams); rsaStatus = (rsaPubKeyRef) ? 0 : 1; key = (SSLPubKey*)rsaPubKeyRef; #endif if (rsaStatus) { return rsaStatusToSSL(rsaStatus); } *pubKey = key; return noErr; }
.p = { .length = prime->length, .data = prime->data, }, .g = { .length = generator->length, .data = generator->data, }, .l = { .length = 0, .data = NULL, } }; DERSize ioLen = DH_ENCODED_PARAM_SIZE(derParams.p.length); DERByte *der = sslMalloc(ioLen); // FIXME: What if this fails - we should probably not have a malloc here ? assert(der); ortn = (OSStatus)DEREncodeSequence(ASN1_CONSTR_SEQUENCE, &derParams, DER_NumDHParamsItemSpecs, DER_DHParamsItemSpecs, der, &ioLen); // This should never fail blob->length=ioLen; blob->data=der; return ortn; }
static void SessionCacheInit(void) { gSessionCache = sslMalloc(sizeof(SessionCache)); gSessionCache->head = NULL; gSessionCache->mTimeToLive = SESSION_CACHE_TTL; }