/* * Get algorithm id for a SSLPrivKey object. */ CFIndex sslPrivKeyGetAlgorithmID(SecKeyRef privKey) { #if TARGET_OS_IPHONE return SecKeyGetAlgorithmID(privKey); #else return SecKeyGetAlgorithmId(privKey); #endif }
/* * Get algorithm id for a SSLPrivKey object. */ CFIndex sslPrivKeyGetAlgorithmID(SSLPrivKey *privKey) { #if TARGET_OS_IOS return SecKeyGetAlgorithmID(SECKEYREF(privKey)); #else return SecKeyGetAlgorithmId(SECKEYREF(privKey)); #endif }
/* Extract the pubkey from a cert chain, and send it to the tls_handshake context */ static int tls_set_peer_pubkey(tls_handshake_t hdsk, const SSLCertificate *certchain) { int err; CFIndex algId; SecKeyRef pubkey = NULL; CFDataRef modulus = NULL; CFDataRef exponent = NULL; CFDataRef ecpubdata = NULL; #if 0 { /* dump certs */ int i=0; int j; const SSLCertificate *tmp = certchain; while(tmp) { printf("cert%d[] = {", i); for(j=0; j<tmp->derCert.length; j++) { if((j&0xf)==0) printf("\n"); printf("0x%02x, ", tmp->derCert.data[j]); } printf("}\n"); tmp=tmp->next; i++; } } #endif require_noerr((err=sslCopyPeerPubKey(certchain, &pubkey)), errOut); #if TARGET_OS_IPHONE algId = SecKeyGetAlgorithmID(pubkey); #else algId = SecKeyGetAlgorithmId(pubkey); #endif err = errSSLCrypto; switch(algId) { case kSecRSAAlgorithmID: { require((modulus = SecKeyCopyModulus(pubkey)), errOut); require((exponent = SecKeyCopyExponent(pubkey)), errOut); tls_buffer mod; tls_buffer exp; mod.data = (uint8_t *)CFDataGetBytePtr(modulus); mod.length = CFDataGetLength(modulus); exp.data = (uint8_t *)CFDataGetBytePtr(exponent); exp.length = CFDataGetLength(exponent); err = tls_handshake_set_peer_rsa_public_key(hdsk, &mod, &exp); break; } case kSecECDSAAlgorithmID: { tls_named_curve curve = SecECKeyGetNamedCurve(pubkey); require((ecpubdata = SecECKeyCopyPublicBits(pubkey)), errOut); tls_buffer pubdata; pubdata.data = (uint8_t *)CFDataGetBytePtr(ecpubdata); pubdata.length = CFDataGetLength(ecpubdata); err = tls_handshake_set_peer_ec_public_key(hdsk, curve, &pubdata); break; } default: break; } errOut: CFReleaseSafe(pubkey); CFReleaseSafe(modulus); CFReleaseSafe(exponent); CFReleaseSafe(ecpubdata); return err; }
/* Extract the pubkey from a cert chain, and send it to the tls_handshake context */ int tls_set_encrypt_pubkey(tls_handshake_t hdsk, const SSLCertificate *certchain) { int err; CFIndex algId; SecTrustRef trustRef = NULL; SecKeyRef pubkey = NULL; CFDataRef modulus = NULL; CFDataRef exponent = NULL; #if 0 { /* dump certs */ int i=0; int j; const SSLCertificate *tmp = certchain; while(tmp) { printf("cert%d[] = {", i); for(j=0; j<tmp->derCert.length; j++) { if((j&0xf)==0) printf("\n"); printf("0x%02x, ", tmp->derCert.data[j]); } printf("}\n"); tmp=tmp->next; i++; } } #endif require_noerr((err=tls_create_trust_from_certs(certchain, &trustRef)), errOut); require_action((pubkey = SecTrustCopyPublicKey(trustRef)), errOut, err=-9808); // errSSLBadCert #if TARGET_OS_IPHONE algId = SecKeyGetAlgorithmID(pubkey); #else algId = SecKeyGetAlgorithmId(pubkey); #endif err = -9809; //errSSLCrypto; switch(algId) { case kSecRSAAlgorithmID: { require((modulus = SecKeyCopyModulus(pubkey)), errOut); require((exponent = SecKeyCopyExponent(pubkey)), errOut); tls_buffer mod; tls_buffer exp; mod.data = (uint8_t *)CFDataGetBytePtr(modulus); mod.length = CFDataGetLength(modulus); exp.data = (uint8_t *)CFDataGetBytePtr(exponent); exp.length = CFDataGetLength(exponent); err = tls_handshake_set_encrypt_rsa_public_key(hdsk, &mod, &exp); break; } default: break; } errOut: CFReleaseSafe(trustRef); CFReleaseSafe(pubkey); CFReleaseSafe(modulus); CFReleaseSafe(exponent); 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; }