static int32_t ProcessCertificateTypeReturn(CFArrayRef items, SecCertificateRef* pCertOut, SecIdentityRef* pIdentityOut) { assert(pCertOut != nullptr && *pCertOut == nullptr); assert(pIdentityOut != nullptr && *pIdentityOut == nullptr); if (items == nullptr) { return kErrOutItemsNull; } CFIndex itemCount = CFArrayGetCount(items); if (itemCount == 0) { return kErrOutItemsEmpty; } CFTypeRef bestItem = nullptr; for (CFIndex i = 0; i < itemCount; i++) { CFTypeRef current = CFArrayGetValueAtIndex(items, i); auto currentItemType = CFGetTypeID(current); if (currentItemType == SecIdentityGetTypeID()) { bestItem = current; break; } else if (bestItem == nullptr && currentItemType == SecCertificateGetTypeID()) { bestItem = current; } } if (bestItem == nullptr) { return -13; } if (CFGetTypeID(bestItem) == SecCertificateGetTypeID()) { CFRetain(bestItem); *pCertOut = reinterpret_cast<SecCertificateRef>(const_cast<void*>(bestItem)); return 1; } if (CFGetTypeID(bestItem) == SecIdentityGetTypeID()) { CFRetain(bestItem); *pIdentityOut = reinterpret_cast<SecIdentityRef>(const_cast<void*>(bestItem)); return 1; } return -19; }
extern "C" int32_t AppleCryptoNative_X509DemuxAndRetainHandle(CFTypeRef handle, SecCertificateRef* pCertOut, SecIdentityRef* pIdentityOut) { if (pCertOut != nullptr) *pCertOut = nullptr; if (pIdentityOut != nullptr) *pIdentityOut = nullptr; if (handle == nullptr || pCertOut == nullptr || pIdentityOut == nullptr) return kErrorBadInput; auto objectType = CFGetTypeID(handle); void* nonConstHandle = const_cast<void*>(handle); if (objectType == SecIdentityGetTypeID()) { *pIdentityOut = reinterpret_cast<SecIdentityRef>(nonConstHandle); } else if (objectType == SecCertificateGetTypeID()) { *pCertOut = reinterpret_cast<SecCertificateRef>(nonConstHandle); } else { return 0; } CFRetain(handle); return 1; }
static CFDictionaryRef SecItemCopyAttributeDictionary(CFTypeRef ref) { CFDictionaryRef refDictionary = NULL; CFTypeID typeID = CFGetTypeID(ref); if (typeID == SecKeyGetTypeID()) { refDictionary = SecKeyCopyAttributeDictionary((SecKeyRef)ref); } else if (typeID == SecCertificateGetTypeID()) { refDictionary = SecCertificateCopyAttributeDictionary((SecCertificateRef)ref); } else if (typeID == SecIdentityGetTypeID()) { assert(false); SecIdentityRef identity = (SecIdentityRef)ref; SecCertificateRef cert = NULL; SecKeyRef key = NULL; if (!SecIdentityCopyCertificate(identity, &cert) && !SecIdentityCopyPrivateKey(identity, &key)) { CFDataRef data = SecCertificateCopyData(cert); CFDictionaryRef key_dict = SecKeyCopyAttributeDictionary(key); if (key_dict && data) { refDictionary = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, key_dict); CFDictionarySetValue((CFMutableDictionaryRef)refDictionary, CFSTR(CERTIFICATE_DATA_COLUMN_LABEL), data); } CFReleaseNull(key_dict); CFReleaseNull(data); } CFReleaseNull(cert); CFReleaseNull(key); } else { refDictionary = NULL; } return refDictionary; }
/* * Assume incoming identity contains a root (e.g., created by * certtool) and add that cert to ST's trusted anchors. This * enables ST's verify of the incoming chain to succeed without * a kludgy "AllowAnyRoot" specification. */ OSStatus addIdentityAsTrustedRoot( SSLContextRef ctx, CFArrayRef identArray) { CFIndex numItems = CFArrayGetCount(identArray); if(numItems == 0) { printf("***addIdentityAsTrustedRoot: empty identArray\n"); return errSecParam; } /* Root should be the last item - could be identity, could be cert */ CFTypeRef theItem = CFArrayGetValueAtIndex(identArray, numItems - 1); if(CFGetTypeID(theItem) == SecIdentityGetTypeID()) { /* identity */ SecCertificateRef certRef; OSStatus ortn = SecIdentityCopyCertificate( (SecIdentityRef)theItem, &certRef); if(ortn) { cssmPerror("SecIdentityCopyCertificate", ortn); printf("***Error gettting cert from identity\n"); return ortn; } ortn = addTrustedSecCert(ctx, certRef, false); CFRelease(certRef); return ortn; } else if(CFGetTypeID(theItem) == SecCertificateGetTypeID()) { /* certificate */ return addTrustedSecCert(ctx, (SecCertificateRef)theItem, false); } else { printf("***Bogus item in identity array\n"); return errSecParam; } }
char * _mongoc_secure_transport_extract_subject (const char *filename, const char *passphrase) { bool success; char *retval = NULL; CFArrayRef items = NULL; SecExternalItemType type = kSecItemTypeCertificate; success = _mongoc_secure_transport_import_pem (filename, passphrase, &items, &type); if (!success) { return NULL; } if (type == kSecItemTypeAggregate) { for (CFIndex i = 0; i < CFArrayGetCount (items); ++i) { CFTypeID item_id = CFGetTypeID (CFArrayGetValueAtIndex (items, i)); if (item_id == SecCertificateGetTypeID()) { retval = _mongoc_secure_transport_RFC2253_from_cert ((SecCertificateRef)CFArrayGetValueAtIndex (items, i)); break; } } } else if (type == kSecItemTypeCertificate) { retval = _mongoc_secure_transport_RFC2253_from_cert ((SecCertificateRef)items); } if (items) { CFRelease (items); } return retval; }
static CFType typeFromCFTypeRef(CFTypeRef type) { ASSERT(type); if (type == tokenNullTypeRef()) return Null; CFTypeID typeID = CFGetTypeID(type); if (typeID == CFArrayGetTypeID()) return CFArray; if (typeID == CFBooleanGetTypeID()) return CFBoolean; if (typeID == CFDataGetTypeID()) return CFData; if (typeID == CFDictionaryGetTypeID()) return CFDictionary; if (typeID == CFNullGetTypeID()) return CFNull; if (typeID == CFNumberGetTypeID()) return CFNumber; if (typeID == CFStringGetTypeID()) return CFString; if (typeID == CFURLGetTypeID()) return CFURL; #if PLATFORM(MAC) if (typeID == SecCertificateGetTypeID()) return SecCertificate; #endif ASSERT_NOT_REACHED(); return Unknown; }
/* * Specify recipients of the message. Implies that the message will be encrypted. */ OSStatus CMSEncoderAddRecipients( CMSEncoderRef cmsEncoder, CFTypeRef recipientOrArray) { if(cmsEncoder == NULL) { return errSecParam; } if(cmsEncoder->encState != ES_Init) { return errSecParam; } return cmsAppendToArray(recipientOrArray, &cmsEncoder->recipients, SecCertificateGetTypeID()); }
/* * Specify additional certs to include in a signed message. */ OSStatus CMSEncoderAddSupportingCerts( CMSEncoderRef cmsEncoder, CFTypeRef certOrArray) { if(cmsEncoder == NULL) { return errSecParam; } if(cmsEncoder->encState != ES_Init) { return errSecParam; } return cmsAppendToArray(certOrArray, &cmsEncoder->otherCerts, SecCertificateGetTypeID()); }
bool mongoc_secure_transport_setup_ca ( mongoc_stream_tls_secure_transport_t *secure_transport, mongoc_ssl_opt_t *opt) { if (opt->ca_file) { CFArrayRef items; SecExternalItemType type = kSecItemTypeCertificate; bool success = _mongoc_secure_transport_import_pem ( opt->ca_file, NULL, &items, &type); if (!success) { MONGOC_ERROR ("Can't find certificate in \"%s\"", opt->ca_file); return false; } if (type == kSecItemTypeAggregate) { CFMutableArrayRef anchors = CFArrayCreateMutable ( kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks); for (CFIndex i = 0; i < CFArrayGetCount (items); ++i) { CFTypeID item_id = CFGetTypeID (CFArrayGetValueAtIndex (items, i)); if (item_id == SecCertificateGetTypeID ()) { CFArrayAppendValue (anchors, CFArrayGetValueAtIndex (items, i)); } } secure_transport->anchors = anchors; CFRelease (items); } else if (type == kSecItemTypeCertificate) { secure_transport->anchors = items; } else { CFRelease (items); } /* This should be SSLSetCertificateAuthorities But the /TLS/ tests fail * when it is */ success = !SSLSetTrustedRoots ( secure_transport->ssl_ctx_ref, secure_transport->anchors, true); TRACE ("Setting certificate authority %s (%s)", success ? "succeeded" : "failed", opt->ca_file); return true; } TRACE ("%s", "No CA provided, using defaults"); return false; }
static void encodeCertificateChain(Encoder& encoder, CFArrayRef certificateChain) { CFIndex size = CFArrayGetCount(certificateChain); Vector<CFTypeRef, 32> values(size); CFArrayGetValues(certificateChain, CFRangeMake(0, size), values.data()); encoder << static_cast<uint64_t>(size); for (CFIndex i = 0; i < size; ++i) { ASSERT(values[i]); ASSERT(CFGetTypeID(values[i]) == SecCertificateGetTypeID()); auto data = adoptCF(SecCertificateCopyData((SecCertificateRef)values[i])); encodeCFData(encoder, data.get()); } }
/* * Export items specified as SecKeychainItemRefs. */ void P12Coder::exportKeychainItems( CFArrayRef items) { assert(items != NULL); CFIndex numItems = CFArrayGetCount(items); for(CFIndex dex=0; dex<numItems; dex++) { const void *item = CFArrayGetValueAtIndex(items, dex); if(item == NULL) { p12ErrorLog("exportKeychainItems: NULL item\n"); MacOSError::throwMe(errSecParam); } CFTypeID itemType = CFGetTypeID(item); if(itemType == SecCertificateGetTypeID()) { addSecCert((SecCertificateRef)item); } else if(itemType == SecKeyGetTypeID()) { addSecKey((SecKeyRef)item); } else { p12ErrorLog("exportKeychainItems: unknown item\n"); MacOSError::throwMe(errSecParam); } } }
/* * Store the specified certificate (or, more likely, some platform-dependent * reference to it) as the specified principal's certificate. Passing * in NULL for the client_cert has the effect of deleting the relevant entry * in the cert storage. */ krb5_error_code krb5_pkinit_set_client_cert( const char *principal, /* full principal string */ krb5_pkinit_cert_t client_cert) { SecCertificateRef certRef = (SecCertificateRef)client_cert; OSStatus ortn; CSSM_DATA issuerSerial = {0, NULL}; CFDataRef cfIssuerSerial = NULL; CFDictionaryRef existDict = NULL; CFMutableDictionaryRef newDict = NULL; CFStringRef keyStr = NULL; krb5_error_code ourRtn = 0; if(certRef != NULL) { if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) { return KRB5KRB_ERR_GENERIC; } /* Cook up DER-encoded issuer/serial number */ ortn = pkinit_get_cert_issuer_sn(certRef, &issuerSerial); if(ortn) { ourRtn = KRB5KRB_ERR_GENERIC; goto errOut; } } /* * Obtain the existing pref for kPkinitClientCertKey as a CFDictionary, or * cook up a new one. */ ortn = pkinit_get_pref_dict(&existDict); if(ortn == noErr) { /* dup to a mutable dictionary */ newDict = CFDictionaryCreateMutableCopy(NULL, 0, existDict); } else { if(certRef == NULL) { /* no existing entry, nothing to delete, we're done */ return 0; } newDict = CFDictionaryCreateMutable(NULL, 0, &kCFCopyStringDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); } if(newDict == NULL) { ourRtn = ENOMEM; goto errOut; } /* issuer / serial number ==> that dictionary */ keyStr = CFStringCreateWithCString(NULL, principal, kCFStringEncodingASCII); if(certRef == NULL) { CFDictionaryRemoveValue(newDict, keyStr); } else { cfIssuerSerial = CFDataCreate(NULL, issuerSerial.Data, issuerSerial.Length); CFDictionarySetValue(newDict, keyStr, cfIssuerSerial); } /* dictionary ==> prefs */ CFPreferencesSetValue(CFSTR(kPkinitClientCertKey), newDict, CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, kCFPreferencesAnyHost); if(CFPreferencesSynchronize(CFSTR(kPkinitClientCertApp), kCFPreferencesCurrentUser, kCFPreferencesAnyHost)) { ourRtn = 0; } else { ourRtn = EACCES; /* any better ideas? */ } errOut: if(cfIssuerSerial) { CFRelease(cfIssuerSerial); } if(issuerSerial.Data) { free(issuerSerial.Data); } if(existDict) { CFRelease(existDict); } if(newDict) { CFRelease(newDict); } if(keyStr) { CFRelease(keyStr); } return ourRtn; }
OSStatus parseIncomingCerts( SSLContext *ctx, CFArrayRef certs, CFArrayRef *destCertChain, /* &ctx->{localCertChain,encryptCertChain} */ SSLPubKey **sslPubKey, /* &ctx->signingPubKey, etc. */ SSLPrivKey **sslPrivKey, /* &ctx->signingPrivKeyRef, etc. */ CFIndex *signerAlg) /* optional */ { OSStatus ortn; CFIndex ix, numCerts; SecIdentityRef identity; CFMutableArrayRef certChain = NULL; /* Retained */ SecCertificateRef leafCert = NULL; /* Retained */ SecKeyRef pubKey = NULL; /* Retained */ SecKeyRef privKey = NULL; /* Retained */ SecTrustRef trust = NULL; /* Retained */ SecTrustResultType trustResult; assert(ctx != NULL); assert(destCertChain != NULL); /* though its referent may be NULL */ assert(sslPubKey != 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; } /* * 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 = paramErr; goto errOut; } if (CFGetTypeID(identity) != SecIdentityGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); ortn = paramErr; 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. */ certChain = CFArrayCreateMutable(kCFAllocatorDefault, numCerts, &kCFTypeArrayCallBacks); if (!certChain) { ortn = memFullErr; goto errOut; } CFArrayAppendValue(certChain, leafCert); for (ix = 1; ix < numCerts; ++ix) { SecCertificateRef intermediate = (SecCertificateRef)CFArrayGetValueAtIndex(certs, ix); if (intermediate == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); ortn = paramErr; goto errOut; } if (CFGetTypeID(intermediate) != SecCertificateGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); ortn = paramErr; goto errOut; } CFArrayAppendValue(certChain, intermediate); } /* Obtain public key from cert */ #if TARGET_OS_IOS ortn = SecTrustCreateWithCertificates(certChain, NULL, &trust); #else { SecPolicyRef policy = SecPolicyCreateBasicX509(); ortn = SecTrustCreateWithCertificates(certChain, policy, &trust); CFReleaseSafe(policy); if (!ortn) { /* We are only interested in getting the public key from the leaf * cert here, so for best performance, don't try to build a chain * or search any keychains. */ CFArrayRef emptyArray = CFArrayCreate(NULL, NULL, 0, NULL); (void)SecTrustSetAnchorCertificates(trust, emptyArray); (void)SecTrustSetKeychains(trust, emptyArray); CFReleaseSafe(emptyArray); } } #endif if (ortn) { sslErrorLog("parseIncomingCerts: SecTrustCreateWithCertificates err %d\n", (int)ortn); goto errOut; } ortn = SecTrustEvaluate(trust, &trustResult); if (ortn) { sslErrorLog("parseIncomingCerts: SecTrustEvaluate err %d\n", (int)ortn); goto errOut; } pubKey = SecTrustCopyPublicKey(trust); if (pubKey == NULL) { sslErrorLog("parseIncomingCerts: SecTrustCopyPublicKey failed\n"); ortn = -67712; // errSecInvalidKeyRef goto errOut; } /* SUCCESS */ errOut: CFReleaseSafe(trust); CFReleaseSafe(leafCert); CFReleaseSafe(*destCertChain); sslFreePubKey(sslPubKey); sslFreePrivKey(sslPrivKey); if (ortn) { CFReleaseSafe(certChain); CFReleaseSafe(pubKey); CFReleaseSafe(privKey); *destCertChain = NULL; } else { *destCertChain = certChain; *sslPubKey = (SSLPubKey*)pubKey; *sslPrivKey = (SSLPrivKey*)privKey; } return ortn; }
OSStatus parseIncomingCerts( SSLContext *ctx, CFArrayRef certs, SSLCertificate **destCert, /* &ctx->{localCert,encryptCert} */ CSSM_KEY_PTR *pubKey, /* &ctx->signingPubKey, etc. */ SecKeyRef *privKeyRef, /* &ctx->signingPrivKeyRef, etc. */ CSSM_ALGORITHMS *signerAlg) /* optional */ { CFIndex numCerts; CFIndex cert; SSLCertificate *certChain = NULL; SSLCertificate *thisSslCert; OSStatus ortn; SecIdentityRef identity; SecCertificateRef certRef; SecKeyRef keyRef; CSSM_DATA certData; CSSM_CL_HANDLE clHand; // carefully derive from a SecCertificateRef CSSM_RETURN crtn; CSSM_KEY_PTR *pubKey; SecKeyRef *privKeyRef; assert(ctx != NULL); assert(destCert != NULL); /* though its referent may be NULL */ assert(sslPubKey != NULL); assert(sslPrivKeyRef != NULL); pubKey = &sslPubKey->key; privKeyRef = &sslPrivKey->key; sslDeleteCertificateChain(*destCert, ctx); *destCert = NULL; *pubKey = NULL; *privKeyRef = NULL; if(certs == NULL) { sslErrorLog("parseIncomingCerts: NULL incoming cert array\n"); return errSSLBadCert; } numCerts = CFArrayGetCount(certs); if(numCerts == 0) { sslErrorLog("parseIncomingCerts: empty incoming cert array\n"); return errSSLBadCert; } /* * Certs[0] is an SecIdentityRef from which we extract subject cert, * privKeyRef, pubKey. * * 1. ensure the first element is a SecIdentityRef. */ identity = (SecIdentityRef)CFArrayGetValueAtIndex(certs, 0); if(identity == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (1)\n"); return paramErr; } if(CFGetTypeID(identity) != SecIdentityGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (2)\n"); return paramErr; } /* * 2. Extract cert, keys and convert to local format. */ ortn = SecIdentityCopyCertificate(identity, &certRef); if(ortn) { sslErrorLog("parseIncomingCerts: bad cert array (3)\n"); return ortn; } ortn = secCertToSslCert(ctx, certRef, &thisSslCert); if(ortn) { sslErrorLog("parseIncomingCerts: bad cert array (4)\n"); return ortn; } /* enqueue onto head of cert chain */ thisSslCert->next = certChain; certChain = thisSslCert; if(signerAlg != NULL) { ortn = sslCertSignerAlg(certRef, signerAlg); if(ortn) { return ortn; } } /* fetch private key from identity */ ortn = SecIdentityCopyPrivateKey(identity, &keyRef); if(ortn) { sslErrorLog("parseIncomingCerts: SecIdentityCopyPrivateKey err %d\n", (int)ortn); return ortn; } *privKeyRef = keyRef; /* obtain public key from cert */ ortn = SecCertificateGetCLHandle(certRef, &clHand); if(ortn) { sslErrorLog("parseIncomingCerts: SecCertificateGetCLHandle err %d\n", (int)ortn); return ortn; } certData.Data = thisSslCert->derCert.data; certData.Length = thisSslCert->derCert.length; crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, pubKey); if(crtn) { sslErrorLog("parseIncomingCerts: CSSM_CL_CertGetKeyInfo err\n"); return (OSStatus)crtn; } /* OK, that's the subject cert. Fetch optional remaining certs. */ /* * Convert: CFArray of SecCertificateRefs --> chain of SSLCertificates. * Incoming certs have root last; SSLCertificate chain has root * first. */ for(cert=1; cert<numCerts; cert++) { certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certs, cert); if(certRef == NULL) { sslErrorLog("parseIncomingCerts: bad cert array (5)\n"); return paramErr; } if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) { sslErrorLog("parseIncomingCerts: bad cert array (6)\n"); return paramErr; } /* Extract cert, convert to local format. */ ortn = secCertToSslCert(ctx, certRef, &thisSslCert); if(ortn) { sslErrorLog("parseIncomingCerts: bad cert array (7)\n"); return ortn; } /* enqueue onto head of cert chain */ thisSslCert->next = certChain; certChain = thisSslCert; } /* SUCCESS */ *destCert = certChain; return noErr; /* free certChain, everything in it, other vars, return ortn */ sslDeleteCertificateChain(certChain, ctx); /* FIXME - anything else? */ return ortn; }
bool mongoc_secure_transport_setup_certificate (mongoc_stream_tls_secure_transport_t *secure_transport, mongoc_ssl_opt_t *opt) { bool success; CFArrayRef items; SecIdentityRef id; SecKeyRef key = NULL; SecCertificateRef cert = NULL; SecExternalItemType type = kSecItemTypeCertificate; if (!opt->pem_file) { MONGOC_INFO ("No private key provided, the server won't be able to verify us"); return false; } success = _mongoc_secure_transport_import_pem (opt->pem_file, opt->pem_pwd, &items, &type); if (!success) { MONGOC_ERROR ("Can't find certificate in: '%s'", opt->pem_file); return false; } if (type != kSecItemTypeAggregate) { MONGOC_ERROR ("Cannot work with keys of type \"%d\". Please file a JIRA", type); CFRelease (items); return false; } for (CFIndex i = 0; i < CFArrayGetCount (items); ++i) { CFTypeID item_id = CFGetTypeID (CFArrayGetValueAtIndex (items, i)); if (item_id == SecCertificateGetTypeID()) { cert = (SecCertificateRef) CFArrayGetValueAtIndex (items, i); } else if (item_id == SecKeyGetTypeID()) { key = (SecKeyRef) CFArrayGetValueAtIndex (items, i); } } if (!cert || !key) { MONGOC_ERROR ("Couldn't find valid private key"); CFRelease (items); return false; } id = SecIdentityCreate (kCFAllocatorDefault, cert, key); secure_transport->my_cert = CFArrayCreateMutableCopy(kCFAllocatorDefault, (CFIndex)2, items); CFArraySetValueAtIndex(secure_transport->my_cert, 0, id); CFArraySetValueAtIndex(secure_transport->my_cert, 1, cert); /* * Secure Transport assumes the following: * * The certificate references remain valid for the lifetime of the session. * * The identity specified in certRefs[0] is capable of signing. */ success = !SSLSetCertificate (secure_transport->ssl_ctx_ref, secure_transport->my_cert); MONGOC_DEBUG("Setting client certificate %s", success ? "succeeded" : "failed"); CFRelease (items); return true; }
OSStatus SecCertificateRequestGetResult( SecCertificateRequestRef certRequestRef, SecKeychainRef keychain, sint32 *estimatedTime, SecCertificateRef *certificateRef) { BEGIN_SECAPI CssmData certData; *certificateRef = NULL; CertificateRequest::required(certRequestRef)->getResult(estimatedTime, certData); if(certData.data() != NULL) { /* * Convert to SecCertifcateRef, optionally import. */ CFDataRef cfCert = CFDataCreate(NULL, (UInt8 *)certData.data(), certData.Length); SecExternalItemType itemType = kSecItemTypeCertificate; CFArrayRef outItems = NULL; bool freeKcRef = false; OSStatus ortn; if(keychain == NULL) { /* * Unlike most Sec* calls, if the keychain argument to SecKeychainItemImport() * is NULL, the item is not imported to the default keychain. At our * interface, however, a NULL keychain means "import to the default * keychain". */ ortn = SecKeychainCopyDefault(&keychain); if(ortn) { certReqDbg("GetResult: SecKeychainCopyDefault failure"); /* oh well, there's nothing we can do about this */ } else { freeKcRef = true; } } ortn = SecKeychainItemImport(cfCert, NULL, NULL, // format, don't care &itemType, 0, // flags NULL, // keyParams keychain, // optional, like ours &outItems); CFRelease(cfCert); if(freeKcRef) { CFRelease(keychain); } if(ortn) { certReqDbg("SecCertificateRequestGetResult: SecKeychainItemImport failure"); MacOSError::throwMe(ortn); } CFIndex numItems = CFArrayGetCount(outItems); switch(numItems) { case 0: certReqDbg("SecCertificateRequestGetResult: import zero items"); MacOSError::throwMe(errSecInternalComponent); default: certReqDbg("SecCertificateRequestGetResult: import %d items", (int)numItems); /* but drop thru anyway, take the first one */ case 1: SecCertificateRef certRef = (SecCertificateRef)(CFArrayGetValueAtIndex(outItems, 0)); if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) { certReqDbg("SecCertificateRequestGetResult: bad type"); } else { CFRetain(certRef); *certificateRef = certRef; } } CFRelease(outItems); } END_SECAPI }
int trusted_cert_dump(int argc, char * const *argv) { CFArrayRef certArray = NULL; OSStatus ortn = noErr; CFIndex numCerts; CFIndex dex; CFArrayRef trustSettings; int ourRtn = 0; SecTrustSettingsDomain domain = kSecTrustSettingsDomainUser; extern char *optarg; extern int optind; int arg; optind = 1; while ((arg = getopt(argc, argv, "sdh")) != -1) { switch (arg) { case 's': domain = kSecTrustSettingsDomainSystem; break; case 'd': domain = kSecTrustSettingsDomainAdmin; break; default: case 'h': return 2; /* @@@ Return 2 triggers usage message. */ } } if(optind != argc) { return 2; /* @@@ Return 2 triggers usage message. */ } ortn = SecTrustSettingsCopyCertificates(domain, &certArray); if(ortn) { cssmPerror("SecTrustSettingsCopyCertificates", ortn); return 1; } numCerts = CFArrayGetCount(certArray); printf("Number of trusted certs = %ld\n", (long)numCerts); for(dex=0; dex<numCerts; dex++) { SecCertificateRef certRef = (SecCertificateRef)CFArrayGetValueAtIndex(certArray, dex); if(CFGetTypeID(certRef) != SecCertificateGetTypeID()) { fprintf(stderr, "***Bad CFGetTypeID for cert %ld\n", (long)dex); ourRtn = -1; break; } /* always print the cert's label */ printf("Cert %ld: ", dex); printCertLabel(certRef); printf("\n"); /* see if the cert has any usage constraints (it should!) */ ortn = SecTrustSettingsCopyTrustSettings(certRef, domain, &trustSettings); if(ortn) { cssmPerror("SecTrustSettingsCopyTrustSettings", ortn); ourRtn = -1; continue; } if(displayTrustSettings(trustSettings)) { ourRtn = -1; } } CFRelease(certArray); return ourRtn; }
static int do_keychain_import( SecKeychainRef kcRef, CFDataRef inData, SecExternalFormat externFormat, SecExternalItemType itemType, SecAccessRef access, Boolean nonExtractable, const char *passphrase, const char *fileName, char **attrNames, char **attrValues, unsigned numExtendedAttributes) { SecKeyImportExportParameters keyParams; OSStatus ortn; CFStringRef fileStr; CFArrayRef outArray = NULL; int result = 0; int numCerts = 0; int numKeys = 0; int numIdentities = 0; int tryCount = 0; CFIndex dex; CFIndex numItems = 0; CFStringRef passStr = NULL; CFStringRef promptStr = NULL; CFStringRef retryStr = NULL; /* * Specify some kind of passphrase in case caller doesn't know this * is a wrapped object */ memset(&keyParams, 0, sizeof(SecKeyImportExportParameters)); keyParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; if(passphrase != NULL) { passStr = CFStringCreateWithCString(NULL, passphrase, kCFStringEncodingASCII); keyParams.passphrase = passStr; } else { keyParams.flags = kSecKeySecurePassphrase; } if(nonExtractable) { // explicitly set the key attributes, omitting the CSSM_KEYATTR_EXTRACTABLE bit keyParams.keyAttributes = CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_SENSITIVE; } keyParams.accessRef = access; fileStr = CFStringCreateWithCString(NULL, fileName, kCFStringEncodingUTF8); if (fileStr) { CFURLRef fileURL = CFURLCreateWithFileSystemPath(NULL, fileStr, kCFURLPOSIXPathStyle, FALSE); if (fileURL) { CFStringRef nameStr = CFURLCopyLastPathComponent(fileURL); if (nameStr) { safe_CFRelease(&fileStr); fileStr = nameStr; } safe_CFRelease(&fileURL); } } promptStr = CFStringCreateWithFormat(NULL, NULL, KC_IMPORT_KEY_PASSWORD_MESSAGE, fileStr); retryStr = CFStringCreateWithFormat(NULL, NULL, KC_IMPORT_KEY_PASSWORD_RETRYMESSAGE, fileStr); while (TRUE) { keyParams.alertPrompt = (tryCount == 0) ? promptStr : retryStr; ortn = SecKeychainItemImport(inData, fileStr, &externFormat, &itemType, 0, /* flags not used (yet) */ &keyParams, kcRef, &outArray); if(ortn) { if (ortn == errSecPkcs12VerifyFailure && ++tryCount < 3) { continue; } sec_perror("SecKeychainItemImport", ortn); result = 1; goto cleanup; } break; } /* * Parse returned items & report to user */ if(outArray == NULL) { sec_error("No keychain items found"); result = 1; goto cleanup; } numItems = CFArrayGetCount(outArray); for(dex=0; dex<numItems; dex++) { CFTypeRef item = CFArrayGetValueAtIndex(outArray, dex); CFTypeID itemType = CFGetTypeID(item); if(itemType == SecIdentityGetTypeID()) { numIdentities++; } else if(itemType == SecCertificateGetTypeID()) { numCerts++; } else if(itemType == SecKeyGetTypeID()) { numKeys++; } else { sec_error("Unexpected item type returned from SecKeychainItemImport"); result = 1; goto cleanup; } } if(numIdentities) { char *str; if(numIdentities > 1) { str = "identities"; } else { str = "identity"; } fprintf(stdout, "%d %s imported.\n", numIdentities, str); } if(numKeys) { char *str; if(numKeys > 1) { str = "keys"; } else { str = "key"; } fprintf(stdout, "%d %s imported.\n", numKeys, str); } if(numCerts) { char *str; if(numCerts > 1) { str = "certificates"; } else { str = "certificate"; } fprintf(stdout, "%d %s imported.\n", numCerts, str); } /* optionally apply extended attributes */ if(numExtendedAttributes) { unsigned attrDex; for(attrDex=0; attrDex<numExtendedAttributes; attrDex++) { CFStringRef attrNameStr = CFStringCreateWithCString(NULL, attrNames[attrDex], kCFStringEncodingASCII); CFDataRef attrValueData = CFDataCreate(NULL, (const UInt8 *)attrValues[attrDex], strlen(attrValues[attrDex])); for(dex=0; dex<numItems; dex++) { SecKeychainItemRef itemRef = (SecKeychainItemRef)CFArrayGetValueAtIndex(outArray, dex); ortn = SecKeychainItemSetExtendedAttribute(itemRef, attrNameStr, attrValueData); if(ortn) { cssmPerror("SecKeychainItemSetExtendedAttribute", ortn); result = 1; break; } } /* for each imported item */ CFRelease(attrNameStr); CFRelease(attrValueData); if(result) { break; } } /* for each extended attribute */ } cleanup: safe_CFRelease(&fileStr); safe_CFRelease(&outArray); safe_CFRelease(&passStr); safe_CFRelease(&promptStr); safe_CFRelease(&retryStr); return result; }
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; }