/* * 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; }
/* 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; } }
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; }
static void SessionCacheEntryDelete(SessionCacheEntry *entry) { sslLogSessCacheDebug("~SessionCacheEntryDelete() %p", entry); SSLFreeBuffer(&entry->mKey); // no SSLContext SSLFreeBuffer(&entry->mSessionData); sslFree(entry); }
/* 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; }
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; }
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; }
/* free a session */ static OSStatus HMAC_Free( HMACContextRef hmacCtx) { if(hmacCtx != NULL) { memset(hmacCtx, 0, sizeof(*hmacCtx)); sslFree(hmacCtx); } return noErr; }
/* Free SSLCertificate array created by parseIncomingCerts */ static int freeCertificates(SSLCertificate *certs) { SSLCertificate *head = certs; while(certs) { SSLFreeBuffer(&certs->derCert); certs = certs->next; } sslFree(head); return 0; }
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; }
/* 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; }
int SSLFreeBuffer(SSLBuffer *buf) { if(buf == NULL) { sslErrorLog("SSLFreeBuffer: NULL buf!\n"); check(0); return -1; } sslFree(buf->data); buf->data = NULL; buf->length = 0; 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 }
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; }
/* * 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; }
void tls_private_key_destroy(tls_private_key_t key) { if(key->ctx_release && key->ctx) key->ctx_release(key->ctx); sslFree(key); }
void tls_handshake_destroy(tls_handshake_t filter) { tls_metric_destroyed(filter); /* Free the last handshake message flight */ SSLResetFlight(filter); CloseHash(&SSLHashSHA1, &filter->shaState); CloseHash(&SSLHashMD5, &filter->md5State); CloseHash(&SSLHashSHA256, &filter->sha256State); CloseHash(&SSLHashSHA384, &filter->sha384State); CloseHash(&SSLHashSHA512, &filter->sha512State); sslFreePubKey(&filter->peerPubKey); sslFreePubKey(&filter->rsaEncryptPubKey); SSLFreeBuffer(&filter->fragmentedMessageCache); SSLFreeBuffer(&filter->peerID); SSLFreeBuffer(&filter->proposedSessionID); SSLFreeBuffer(&filter->sessionID); SSLFreeBuffer(&filter->sessionTicket); SSLFreeBuffer(&filter->externalSessionTicket); SSLFreeBuffer(&filter->preMasterSecret); SSLFreeBuffer(&filter->dhPeerPublic); SSLFreeBuffer(&filter->ecdhPeerPublic); SSLFreeBuffer(&filter->npnOwnData); SSLFreeBuffer(&filter->npnPeerData); SSLFreeBuffer(&filter->alpnOwnData); SSLFreeBuffer(&filter->alpnPeerData); SSLFreeBuffer(&filter->ownVerifyData); SSLFreeBuffer(&filter->peerVerifyData); SSLFreeBuffer(&filter->pskIdentity); SSLFreeBuffer(&filter->pskSharedSecret); SSLFreeBuffer(&filter->peerDomainName); SSLFreeBuffer(&filter->ocsp_response); SSLFreeBuffer(&filter->ocsp_request_extensions); tls_free_buffer_list(filter->ocsp_responder_id_list); tls_free_buffer_list(filter->sct_list); sslFree(filter->userAgent); sslFree(filter->enabledCipherSuites); sslFree(filter->requestedCipherSuites); sslFree(filter->ecdhCurves); sslFree(filter->peerSigAlgs); sslFree(filter->localSigAlgs); sslFree(filter->clientAuthTypes); sslFree(filter->ecdhContext._full); sslFree(filter->dhParams.gp); sslFree(filter->dhContext._full); sslFree(filter->requested_ecdh_curves); if(filter->signingPrivKeyRef) tls_private_key_destroy(filter->signingPrivKeyRef); SSLFreeCertificates(filter->localCert); SSLFreeCertificates(filter->peerCert); if(!filter->isServer) { SSLFreeDNList(filter->acceptableDNList); } free(filter); }