static void writePeerCerts( CFArrayRef peerCerts, const char *fileBase) { CFIndex numCerts; SecCertificateRef certRef; CFIndex i; char fileName[100]; if(peerCerts == NULL) { return; } numCerts = CFArrayGetCount(peerCerts); for(i=0; i<numCerts; i++) { sprintf(fileName, "%s%02d.cer", fileBase, (int)i); certRef = (SecCertificateRef)CFArrayGetValueAtIndex(peerCerts, i); writeFile(fileName, SecCertificateGetBytePtr(certRef), SecCertificateGetLength(certRef)); } printf("...wrote %lu certs to fileBase %s\n", numCerts, fileBase); }
/* Quick thought: we can eliminate this method if we search anchor sources before all others and we remember if we got a cert from an anchorsource. */ static bool SecSystemAnchorSourceContains(SecCertificateSourceRef source, SecCertificateRef certificate) { #ifndef SECITEM_SHIM_OSX CFDataRef nic = SecCertificateGetNormalizedSubjectContent(certificate); /* 64 bits cast: the worst that can happen here is we truncate the length and match an actual anchor. It does not matter since we would be returning the wrong anchors */ assert((unsigned long)CFDataGetLength(nic)<UINT_MAX); /* Debug check. correct as long as CFIndex is signed long */ const struct subject_to_ix_t *i2x = subject_to_anchor_ix((const char *)CFDataGetBytePtr(nic), (unsigned int)CFDataGetLength(nic)); require_quiet(i2x, errOut); CFIndex cert_length = SecCertificateGetLength(certificate); const UInt8 *cert_data = SecCertificateGetBytePtr(certificate); int anchor_ix = i2x->anchor_ix; do { if (cert_length == anchorslist[anchor_ix].length && !memcmp(anchorslist[anchor_ix].data, cert_data, cert_length)) return true; } while ((anchor_ix = anchorslist[anchor_ix].next_same_subject)); errOut: #endif return false; }
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; }