/* * Obtain size of the modulus of pubKey in bytes. */ size_t sslPubKeyLengthInBytes(SSLPubKey *pubKey) { #if 0 /* Get the length of the modulus in bytes. */ return giantNumBytes(&pubKey->rsaKey.n.g); #else return SecKeyGetBlockSize(SECKEYREF(pubKey)); #endif }
/* * Obtain size of the modulus of privKey in bytes. */ size_t sslPrivKeyLengthInBytes(SSLPrivKey *privKey) { #if 0 /* Get the length of p + q (which is the size of the modulus) in bits. */ gi_uint16 bitLen = bitlen(&privKey->rsaKey.p.g) + bitlen(&privKey->rsaKey.q.g); /* Convert it to bytes. */ return (bitLen + 7) / 8; #else return SecKeyGetBlockSize(SECKEYREF(privKey)); #endif }
/* * 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 }
/* * Obtain maximum size of signature in bytes. A bit of a kludge; we could * ask the CSP to do this but that would be kind of expensive. */ OSStatus sslGetMaxSigSize( SSLPrivKey *privKey, size_t *maxSigSize) { assert(maxSigSize != NULL); #if 0 #if RSA_SIG_SHARE_GIANT *maxSigSize = sizeof(RSASignBuffer); #else *maxSigSize = MAX_PRIME_SIZE_BYTES; #endif #else *maxSigSize = SecKeyGetBlockSize(SECKEYREF(privKey)); #endif return noErr; }
static CFStringRef SecECPrivateKeyCopyKeyDescription(SecKeyRef key) { //curve long curveType = (long)SecECKeyGetNamedCurve(key); char* curve= NULL; switch (curveType) { case 23: curve = "kSecECCurveSecp256r1"; break; case 24: curve = "kSecECCurveSecp384r1"; break; case 25: curve = "kSecECCurveSecp521r1"; break; case -1: curve = "kSecECCurveNone"; break; default: curve = "kSecECCurveNone"; break; } return CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), curve, (long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key); }
static CFStringRef SecECPublicKeyCopyKeyDescription(SecKeyRef key) { ccec_pub_ctx_t ecPubkey; CFStringRef keyDescription = NULL; size_t xlen, ylen, ix; CFMutableStringRef xString = NULL; CFMutableStringRef yString = NULL; ecPubkey.pub = key->key; //curve long curveType = (long)SecECKeyGetNamedCurve(key); char* curve= NULL; switch (curveType) { case 23: curve = "kSecECCurveSecp256r1"; break; case 24: curve = "kSecECCurveSecp384r1"; break; case 25: curve = "kSecECCurveSecp521r1"; break; case -1: curve = "kSecECCurveNone"; break; default: curve = "kSecECCurveNone"; break; } uint8_t *xunit = (uint8_t*)ccec_ctx_x(ecPubkey); require_quiet( NULL != xunit, fail); xlen = (size_t)strlen((char*)xunit); xString = CFStringCreateMutable(kCFAllocatorDefault, xlen * 2); require_quiet( NULL != xString, fail); for (ix = 0; ix < xlen; ++ix) { CFStringAppendFormat(xString, NULL, CFSTR("%02X"), xunit[ix]); } uint8_t *yunit = (uint8_t*)ccec_ctx_y(ecPubkey); require_quiet( NULL != yunit, fail); ylen = (size_t)strlen((char*)yunit); yString = CFStringCreateMutable(kCFAllocatorDefault, ylen*2); require_quiet( NULL != yString, fail); for(ix = 0; ix < ylen; ++ix) { CFStringAppendFormat(yString, NULL, CFSTR("%02X"), yunit[ix]); } keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR( "<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, y: %@, x: %@, addr: %p>"), curve, (long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), yString, xString, key); fail: CFReleaseSafe(xString); CFReleaseSafe(yString); if(!keyDescription) keyDescription = CFStringCreateWithFormat(kCFAllocatorDefault,NULL,CFSTR("<SecKeyRef curve type: %s, algorithm id: %lu, key type: %s, version: %d, block size: %zu bits, addr: %p>"), curve,(long)SecKeyGetAlgorithmID(key), key->key_class->name, key->key_class->version, (8*SecKeyGetBlockSize(key)), key); return keyDescription; }
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; }
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; }