static void testRSAKeyDesc() { SecKeyRef pubKey = NULL; CFStringRef pubRef = NULL; long pubLength = 0; pubKey = SecKeyCreateRSAPublicKey(kCFAllocatorDefault, rsaPubKey, sizeof(rsaPubKey), kSecKeyEncodingBytes); require_quiet( pubKey, fail); pubRef = CFCopyDescription(pubKey); require_quiet(pubRef, fail); pubLength = CFStringGetLength(pubRef)+1; char *publicDescription = (char*)malloc(pubLength); require_quiet(publicDescription != NULL, fail); if(false == CFStringGetCString(pubRef, publicDescription, pubLength, kCFStringEncodingUTF8)) { free(publicDescription); goto fail; } ok_status(strncmp(rsaKeyDescription, publicDescription, strlen(rsaKeyDescription)-17), "rsa key descriptions don't match: %s %s", rsaKeyDescription, publicDescription); free(publicDescription); fail: CFReleaseSafe(pubRef); CFReleaseSafe(pubKey); }
/* * 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 }
SecKeyRef SecKeyCreatePublicFromDER(CFAllocatorRef allocator, const SecAsn1Oid *oid, const SecAsn1Item *params, const SecAsn1Item *keyData) { SecKeyRef publicKey = NULL; if (SecAsn1OidCompare(oid, &CSSMOID_RSA)) { /* pkcs1 1 */ publicKey = SecKeyCreateRSAPublicKey(kCFAllocatorDefault, keyData->Data, keyData->Length, kSecKeyEncodingPkcs1); } else if (SecAsn1OidCompare(oid, &CSSMOID_ecPublicKey)) { SecDERKey derKey = { .oid = oid->Data, .oidLength = oid->Length, .key = keyData->Data, .keyLength = keyData->Length, }; if (params) { derKey.parameters = params->Data; derKey.parametersLength = params->Length; } publicKey = SecKeyCreateECPublicKey(kCFAllocatorDefault, (const uint8_t *)&derKey, sizeof(derKey), kSecDERKeyEncoding); } else {
/* * 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; }