SecSymmetricKeyRef WRAP_PubUnwrapSymKey(SecPrivateKeyRef privkey, CSSM_DATA_PTR encKey, SECOidTag bulkalgtag) { CFDataRef encryptedKey = NULL, bulkkey = NULL; CFMutableDictionaryRef keyparams = NULL; CFStringRef keyType = NULL; CFErrorRef error = NULL; SecSymmetricKeyRef bk = NULL; /* decrypt the key */ encryptedKey = CFDataCreate(NULL, encKey->Data, encKey->Length); if (!encryptedKey) { goto out; } bulkkey = SecKeyCreateDecryptedData(privkey, kSecKeyAlgorithmRSAEncryptionPKCS1, encryptedKey, &error); if (!bulkkey) { goto out; } /* create the SecSymmetricKeyRef */ keyType = SECOID_CopyKeyTypeByTag(bulkalgtag); if (!keyType) { goto out; } keyparams = CFDictionaryCreateMutable(NULL, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!keyparams) { goto out; } CFDictionaryAddValue(keyparams, kSecAttrKeyType, keyType); bk = SecKeyCreateFromData(keyparams, bulkkey, NULL); out: if (encryptedKey) { CFRelease(encryptedKey); } if (bulkkey) { CFRelease(bulkkey); } if (keyparams) { CFRelease(keyparams); } if (keyType) { CFRelease(keyType); } SEC_PrintCFError(error); return bk; }
static SecKeyRef secDeriveKeyFromAnswers(CFArrayRef answers, CFLocaleRef theLocale) { static const uint8_t salt[16] = { 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F, 0x0A, 0x1F }; static const int saltLen = sizeof(salt); SecKeyRef theKey = NULL; uint8_t rawKeyData[RETURN_KEY_SIZE]; CFIndex encodedAnswers = 0; CFIndex numAnswers = CFArrayGetCount(answers); const size_t concatenatedAnswersSize = MAXANSWERBUFF * numAnswers; char *concatenatedAnswers = (char *)malloc(concatenatedAnswersSize); if (concatenatedAnswers == NULL) { return NULL; } concatenatedAnswers[0] = 0; // NUL terminate int i; for (i = 0; i < numAnswers; i++) { CFMutableStringRef answer = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, CFArrayGetValueAtIndex(answers, i)); if (answer) { secNormalize(answer, theLocale); CFIndex theAnswerLen = CFStringGetLength(answer); CFIndex theAnswerSize = CFStringGetMaximumSizeForEncoding(theAnswerLen, kCFStringEncodingUTF8); char *theAnswer = (char *)malloc(theAnswerSize + 1); // add space for NUL byte if (theAnswer) { if (theAnswerLen == CFStringGetBytes(answer, CFRangeMake(0, CFStringGetLength(answer)), kCFStringEncodingUTF8, '?', FALSE, (UInt8*)theAnswer, theAnswerSize, &theAnswerSize)) { theAnswer[theAnswerSize] = 0; // NUL terminate if (strlcat(concatenatedAnswers, theAnswer, concatenatedAnswersSize) < concatenatedAnswersSize) { encodedAnswers += 1; } } bzero(theAnswer, theAnswerSize); free(theAnswer); } CFRelease(answer); } } // one or more of the answers failed to encode if (encodedAnswers != numAnswers) { free(concatenatedAnswers); return NULL; } if (CCKeyDerivationPBKDF(kCCPBKDF2, concatenatedAnswers, strlen(concatenatedAnswers), salt, saltLen, kCCPRFHmacAlgSHA256, PBKDF_ROUNDS, rawKeyData, RETURN_KEY_SIZE)) { free(concatenatedAnswers); return NULL; } CFDataRef keyData = CFDataCreate(kCFAllocatorDefault, rawKeyData, RETURN_KEY_SIZE); if (keyData) { CFMutableDictionaryRef params = CFDictionaryCreateMutable(kCFAllocatorDefault, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (params) { CFErrorRef error = NULL; CFDictionaryAddValue(params, kSecAttrKeyType, kSecAttrKeyTypeAES); theKey = SecKeyCreateFromData(params, keyData, &error); if (error) { CFRelease(error); } CFRelease(params); } CFRelease(keyData); } bzero(rawKeyData, RETURN_KEY_SIZE); bzero(concatenatedAnswers, concatenatedAnswersSize); free(concatenatedAnswers); return theKey; }
int init_server_keys(bool ecdsa, unsigned char *cert_der, size_t cert_der_len, unsigned char *key_der, size_t key_der_len, SSLCertificate *cert, tls_private_key_t *key) { int err = 0; cert->next = NULL; cert->derCert.data = cert_der; cert->derCert.length = cert_der_len; SecKeyRef privKey = NULL; #if TARGET_OS_IPHONE if(ecdsa) { privKey = SecKeyCreateECPrivateKey(kCFAllocatorDefault, key_der, key_der_len, kSecKeyEncodingPkcs1); } else { privKey = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, key_der, key_der_len, kSecKeyEncodingPkcs1); } require_action(privKey, fail, err=-1); #else // Create the SecKeyRef CFErrorRef error = NULL; CFDataRef keyData = CFDataCreate(kCFAllocatorDefault, key_der, key_der_len); CFMutableDictionaryRef parameters = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, NULL); CFDictionarySetValue(parameters, kSecAttrKeyType, ecdsa?kSecAttrKeyTypeECDSA:kSecAttrKeyTypeRSA); CFDictionarySetValue(parameters, kSecAttrKeyClass, kSecAttrKeyClassPrivate); privKey = SecKeyCreateFromData(parameters, keyData, &error); require_action(privKey, fail, err=(int)CFErrorGetCode(error)); #endif size_t keySize = SecKeyGetBlockSize(privKey); if(ecdsa) { #if TARGET_OS_IPHONE /* Compute signature size from key size */ size_t sigSize = 8+2*keySize; #else size_t sigSize = keySize; #endif require((*key = tls_private_key_ecdsa_create(privKey, sigSize, SecECKeyGetNamedCurve(privKey), mySSLPrivKeyECDSA_sign)), fail); } else { require((*key = tls_private_key_rsa_create(privKey, keySize, mySSLPrivKeyRSA_sign, mySSLPrivKeyRSA_decrypt)), fail); } err = 0; fail: #if !TARGET_OS_IPHONE CFReleaseSafe(parameters); CFReleaseSafe(keyData); CFReleaseSafe(error); #endif return err; }