static void build_trust_chains(const void *key, const void *value, void *context) { CFMutableDictionaryRef identity_dict = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); SecKeyRef private_key = NULL; SecCertificateRef cert = NULL; SecIdentityRef identity = NULL; SecPolicyRef policy = NULL; CFMutableArrayRef cert_chain = NULL, eval_chain = NULL; SecTrustRef trust = NULL; build_trust_chains_context * a_build_trust_chains_context = (build_trust_chains_context*)context; CFDataRef key_bytes = CFDictionaryGetValue(value, CFSTR("key")); require(key_bytes, out); CFDataRef cert_bytes = CFDictionaryGetValue(value, CFSTR("cert")); require(cert_bytes, out); /* p12import only passes up rsa keys */ require (private_key = SecKeyCreateRSAPrivateKey(kCFAllocatorDefault, CFDataGetBytePtr(key_bytes), CFDataGetLength(key_bytes), kSecKeyEncodingPkcs1), out); require(cert = SecCertificateCreateWithData(kCFAllocatorDefault, cert_bytes), out); require(identity = SecIdentityCreate(kCFAllocatorDefault, cert, private_key), out); CFDictionarySetValue(identity_dict, kSecImportItemIdentity, identity); eval_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); require(eval_chain, out); CFArrayAppendValue(eval_chain, cert); CFRange all_certs = { 0, CFArrayGetCount(a_build_trust_chains_context->certs) }; CFArrayAppendArray(eval_chain, a_build_trust_chains_context->certs, all_certs); require(policy = SecPolicyCreateBasicX509(), out); SecTrustResultType result; SecTrustCreateWithCertificates(eval_chain, policy, &trust); require(trust, out); SecTrustEvaluate(trust, &result); CFDictionarySetValue(identity_dict, kSecImportItemTrust, trust); require(cert_chain = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), out); CFIndex cert_chain_length = SecTrustGetCertificateCount(trust); int i; for (i = 0; i < cert_chain_length; i++) CFArrayAppendValue(cert_chain, SecTrustGetCertificateAtIndex(trust, i)); CFDictionarySetValue(identity_dict, kSecImportItemCertChain, cert_chain); CFArrayAppendValue(a_build_trust_chains_context->identities, identity_dict); out: CFReleaseSafe(identity_dict); CFReleaseSafe(identity); CFReleaseSafe(private_key); CFReleaseSafe(cert); CFReleaseSafe(policy); CFReleaseSafe(cert_chain); CFReleaseSafe(eval_chain); CFReleaseSafe(trust); }
static void tests(void) { CFDataRef attached_signed_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, attached_signed_data_der, attached_signed_data_der_len, kCFAllocatorNull); CFDataRef detached_signed_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, detached_signed_data_der, detached_signed_data_der_len, kCFAllocatorNull); CFDataRef attached_no_data_signed_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, attached_no_data_signed_data_der, attached_no_data_signed_data_der_len, kCFAllocatorNull); CFDataRef detached_data = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault, detached_content, detached_content_len, kCFAllocatorNull); CFDataRef no_data = CFDataCreate(kCFAllocatorDefault, NULL, 0); SecPolicyRef policy = SecPolicyCreateBasicX509(); SecTrustRef trust = NULL; ok_status(SecCMSVerifyCopyDataAndAttributes(attached_signed_data, NULL, policy, &trust, NULL, NULL), "verify attached data"); CFRelease(trust); ok_status(SecCMSVerifyCopyDataAndAttributes(detached_signed_data, detached_data, policy, &trust, NULL, NULL), "verify detached data"); CFRelease(trust); ok_status(SecCMSVerifyCopyDataAndAttributes(attached_no_data_signed_data, NULL, policy, &trust, NULL, NULL), "verify attached no data"); CFRelease(trust); ok_status(SecCMSVerifyCopyDataAndAttributes(attached_no_data_signed_data, no_data, policy, &trust, NULL, NULL), "verify attached no data"); CFRelease(trust); SecCertificateRef cert = NULL; SecKeyRef privKey = NULL; SecIdentityRef identity = NULL; isnt(cert = SecCertificateCreateWithBytes(NULL, signer_der, signer_der_len), NULL, "create certificate"); isnt(privKey = SecKeyCreateRSAPrivateKey(NULL, privkey_der, privkey_der_len, kSecKeyEncodingPkcs1), NULL, "create private key"); isnt(identity = SecIdentityCreate(NULL, cert, privKey), NULL, "create identity"); CFReleaseSafe(privKey); CFMutableDataRef cms_data = CFDataCreateMutable(kCFAllocatorDefault, 0); ok_status(SecCMSCreateSignedData(identity, detached_data, NULL, NULL, cms_data), "create attached data"); //write_data("/var/tmp/attached", cms_data); CFDataSetLength(cms_data, 0); CFDictionaryRef detached_cms_dict = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecCMSSignDetached, (const void **)&kCFBooleanTrue, 1, NULL, NULL); ok_status(SecCMSCreateSignedData(identity, detached_data, detached_cms_dict, NULL, cms_data), "create attached data"); CFRelease(detached_cms_dict); //write_data("/var/tmp/detached", cms_data); CFDataSetLength(cms_data, 0); ok_status(SecCMSCreateSignedData(identity, NULL, NULL, NULL, cms_data), "create attached data"); //write_data("/var/tmp/empty_attached", cms_data); CFReleaseSafe(cms_data); CFReleaseSafe(cert); CFReleaseNull(identity); CFRelease(attached_signed_data); CFRelease(detached_signed_data); CFRelease(attached_no_data_signed_data); CFRelease(detached_data); CFRelease(no_data); CFRelease(policy); }
static int load_cert(URLContext *h) { TLSContext *c = h->priv_data; int ret = 0; CFArrayRef certArray = NULL; CFArrayRef keyArray = NULL; SecIdentityRef id = NULL; CFMutableArrayRef outArray = NULL; if ((ret = import_pem(h, c->tls_shared.cert_file, &certArray)) < 0) goto end; if ((ret = import_pem(h, c->tls_shared.key_file, &keyArray)) < 0) goto end; if (!(id = SecIdentityCreate(kCFAllocatorDefault, (SecCertificateRef)CFArrayGetValueAtIndex(certArray, 0), (SecKeyRef)CFArrayGetValueAtIndex(keyArray, 0)))) { ret = AVERROR_UNKNOWN; goto end; } if (!(outArray = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, certArray))) { ret = AVERROR(ENOMEM); goto end; } CFArraySetValueAtIndex(outArray, 0, id); SSLSetCertificate(c->ssl_context, outArray); end: if (certArray) CFRelease(certArray); if (keyArray) CFRelease(keyArray); if (outArray) CFRelease(outArray); if (id) CFRelease(id); return ret; }
static int /* O - 1 on success, 0 on failure */ make_certificate(cupsd_client_t *con) /* I - Client connection */ { # ifdef HAVE_SECGENERATESELFSIGNEDCERTIFICATE int status = 0; /* Return status */ OSStatus err; /* Error code (if any) */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) char localname[1024];/* Local hostname */ # endif /* HAVE_DNSSD || HAVE_AVAHI */ const char *servername; /* Name of server in cert */ CFStringRef cfservername = NULL; /* CF string for server name */ SecIdentityRef ident = NULL; /* Identity */ SecKeyRef publicKey = NULL, /* Public key */ privateKey = NULL; /* Private key */ CFMutableDictionaryRef keyParams = NULL; /* Key generation parameters */ cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key and certificate."); # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) { snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); servername = localname; } else # endif /* HAVE_DNSSD || HAVE_AVAHI */ servername = con->servername; cfservername = CFStringCreateWithCString(kCFAllocatorDefault, servername, kCFStringEncodingUTF8); if (!cfservername) goto cleanup; /* * Create a public/private key pair... */ keyParams = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (!keyParams) goto cleanup; CFDictionaryAddValue(keyParams, kSecAttrKeyType, kSecAttrKeyTypeRSA); CFDictionaryAddValue(keyParams, kSecAttrKeySizeInBits, CFSTR("2048")); CFDictionaryAddValue(keyParams, kSecAttrLabel, CFSTR("CUPS Self-Signed Certificate")); err = SecKeyGeneratePair(keyParams, &publicKey, &privateKey); if (err != noErr) { cupsdLogMessage(CUPSD_LOG_DEBUG, "SecKeyGeneratePair returned %ld.", (long)err); goto cleanup; } /* * Create a self-signed certificate using the public/private key pair... */ CFIndex usageInt = kSecKeyUsageAll; CFNumberRef usage = CFNumberCreate(alloc, kCFNumberCFIndexType, &usageInt); CFDictionaryRef certParams = CFDictionaryCreateMutable(kCFAllocatorDefault, kSecCSRBasicContraintsPathLen, CFINT(0), kSecSubjectAltName, cfservername, kSecCertificateKeyUsage, usage, NULL, NULL); CFRelease(usage); const void *ca_o[] = { kSecOidOrganization, CFSTR("") }; const void *ca_cn[] = { kSecOidCommonName, cfservername }; CFArrayRef ca_o_dn = CFArrayCreate(kCFAllocatorDefault, ca_o, 2, NULL); CFArrayRef ca_cn_dn = CFArrayCreate(kCFAllocatorDefault, ca_cn, 2, NULL); const void *ca_dn_array[2]; ca_dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_o_dn, 1, NULL); ca_dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_cn_dn, 1, NULL); CFArrayRef subject = CFArrayCreate(kCFAllocatorDefault, ca_dn_array, 2, NULL); SecCertificateRef cert = SecGenerateSelfSignedCertificate(subject, certParams, publicKey, privateKey); CFRelease(subject); CFRelease(certParams); if (!cert) { cupsdLogMessage(CUPSD_LOG_DEBUG, "SecGenerateSelfSignedCertificate failed."); goto cleanup; } ident = SecIdentityCreate(kCFAllocatorDefault, cert, privateKey); if (ident) cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server certificate file \"%s\".", ServerCertificate); /* * Cleanup and return... */ cleanup: if (cfservername) CFRelease(cfservername); if (keyParams) CFRelease(keyParams); if (ident) CFRelease(ident); if (cert) CFRelease(cert); if (publicKey) CFRelease(publicKey); if (privateKey) CFRelease(publicKey); if (!status) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key and certificate."); return (status); # else /* !HAVE_SECGENERATESELFSIGNEDCERTIFICATE */ int pid, /* Process ID of command */ status; /* Status of command */ char command[1024], /* Command */ *argv[4], /* Command-line arguments */ *envp[MAX_ENV + 1], /* Environment variables */ keychain[1024], /* Keychain argument */ infofile[1024], /* Type-in information for cert */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) localname[1024], /* Local hostname */ # endif /* HAVE_DNSSD || HAVE_AVAHI */ *servername; /* Name of server in cert */ cups_file_t *fp; /* Seed/info file */ int infofd; /* Info file descriptor */ # if defined(HAVE_DNSSD) || defined(HAVE_AVAHI) if (con->servername && isdigit(con->servername[0] & 255) && DNSSDHostName) { snprintf(localname, sizeof(localname), "%s.local", DNSSDHostName); servername = localname; } else # endif /* HAVE_DNSSD || HAVE_AVAHI */ servername = con->servername; /* * Run the "certtool" command to generate a self-signed certificate... */ if (!cupsFileFind("certtool", getenv("PATH"), 1, command, sizeof(command))) { cupsdLogMessage(CUPSD_LOG_ERROR, "No SSL certificate and certtool command not found."); return (0); } /* * Create a file with the certificate information fields... * * Note: This assumes that the default questions are asked by the certtool * command... */ if ((fp = cupsTempFile2(infofile, sizeof(infofile))) == NULL) { cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create certificate information file %s - %s", infofile, strerror(errno)); return (0); } cupsFilePrintf(fp, "%s\n" /* Enter key and certificate label */ "r\n" /* Generate RSA key pair */ "2048\n" /* Key size in bits */ "y\n" /* OK (y = yes) */ "b\n" /* Usage (b=signing/encryption) */ "s\n" /* Sign with SHA1 */ "y\n" /* OK (y = yes) */ "%s\n" /* Common name */ "\n" /* Country (default) */ "\n" /* Organization (default) */ "\n" /* Organizational unit (default) */ "\n" /* State/Province (default) */ "%s\n" /* Email address */ "y\n", /* OK (y = yes) */ servername, servername, ServerAdmin); cupsFileClose(fp); cupsdLogMessage(CUPSD_LOG_INFO, "Generating SSL server key and certificate."); snprintf(keychain, sizeof(keychain), "k=%s", ServerCertificate); argv[0] = "certtool"; argv[1] = "c"; argv[2] = keychain; argv[3] = NULL; cupsdLoadEnv(envp, MAX_ENV); infofd = open(infofile, O_RDONLY); if (!cupsdStartProcess(command, argv, envp, infofd, -1, -1, -1, -1, 1, NULL, NULL, &pid)) { close(infofd); unlink(infofile); return (0); } close(infofd); unlink(infofile); while (waitpid(pid, &status, 0) < 0) if (errno != EINTR) { status = 1; break; } cupsdFinishProcess(pid, command, sizeof(command), NULL); if (status) { if (WIFEXITED(status)) cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key and certificate - " "the certtool command stopped with status %d.", WEXITSTATUS(status)); else cupsdLogMessage(CUPSD_LOG_ERROR, "Unable to create SSL server key and certificate - " "the certtool command crashed on signal %d.", WTERMSIG(status)); } else { cupsdLogMessage(CUPSD_LOG_INFO, "Created SSL server certificate file \"%s\".", ServerCertificate); } return (!status); # endif /* HAVE_SECGENERATESELFSIGNEDCERTIFICATE */ }
/* Create and identity and try to retrieve it. */ static void tests(void) { SecCertificateRef cert = NULL; SecKeyRef privKey = NULL; SecIdentityRef identity = NULL; isnt(cert = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), NULL, "create certificate"); isnt(privKey = SecKeyCreateRSAPrivateKey(NULL, _k1, sizeof(_k1), kSecKeyEncodingPkcs1), NULL, "create private key"); const void *certkeys[] = { kSecValueRef }; const void *certvalues[] = { cert }; CFDictionaryRef certDict = CFDictionaryCreate(NULL, certkeys, certvalues, array_size(certkeys), NULL, NULL); ok_status(SecItemAdd(certDict, NULL), "add certificate"); CFReleaseNull(certDict); const void *privkeys[] = { kSecValueRef }; const void *privvalues[] = { privKey }; CFDictionaryRef privDict = CFDictionaryCreate(NULL, privkeys, privvalues, array_size(privkeys), NULL, NULL); ok_status(SecItemAdd(privDict, NULL), "add private key"); CFReleaseNull(privDict); isnt(identity = SecIdentityCreate(NULL, cert, privKey), NULL, "create identity"); /* Lookup the key and certificate using SecItemCopyMatching(). */ CFDataRef pk_digest = CFDataCreate(NULL, _k1_digest, sizeof(_k1_digest)); const void *q_keys[] = { kSecClass, kSecAttrApplicationLabel, kSecReturnRef }; const void *q_values[] = { kSecClassKey, pk_digest, kCFBooleanTrue }; CFDictionaryRef query = CFDictionaryCreate(NULL, q_keys, q_values, array_size(q_keys), NULL, NULL); CFTypeRef result_key; ok_status(SecItemCopyMatching(query, &result_key), "lookup key"); isnt(CFEqual(privKey, result_key), 0, "keys match"); CFReleaseNull(query); q_keys[1] = kSecAttrPublicKeyHash; q_values[0] = kSecClassCertificate; query = CFDictionaryCreate(NULL, q_keys, q_values, array_size(q_keys), NULL, NULL); CFTypeRef result_cert; ok_status(SecItemCopyMatching(query, &result_cert), "lookup certificate"); isnt(CFEqual(cert, result_cert), 0, "certificates match"); CFReleaseNull(query); /* Cleanup. */ CFReleaseNull(result_key); CFReleaseNull(result_cert); /* identity lookup */ const void *idnt_keys[] = { kSecClass, kSecAttrApplicationLabel, kSecReturnRef }; const void *idnt_values[] = { kSecClassIdentity, pk_digest, kCFBooleanTrue }; CFTypeRef result_idnt; SecCertificateRef result_cert2; query = CFDictionaryCreate(NULL, idnt_keys, idnt_values, array_size(idnt_keys), NULL, NULL); ok_status(SecItemCopyMatching(query, &result_idnt), "lookup identity"); isnt(result_idnt, NULL, "found identity?"); is(CFGetRetainCount(result_idnt), 1, "result_idnt rc = 1"); isnt(CFEqual(identity, result_idnt), 0, "identities match"); CFReleaseNull(identity); ok_status(SecIdentityCopyCertificate((SecIdentityRef)result_idnt, &result_cert2), "get cert from identity"); isnt(CFEqual(cert, result_cert2), 0, "certificates match"); CFRelease(query); CFRelease(pk_digest); CFReleaseNull(result_cert2); certDict = CFDictionaryCreate(NULL, certkeys, certvalues, array_size(certkeys), NULL, NULL); ok_status(SecItemDelete(certDict), "delete certificate via ref"); is_status(errSecItemNotFound, SecItemCopyMatching(certDict, NULL), "verify certificate is gone"); CFReleaseNull(certDict); privDict = CFDictionaryCreate(NULL, privkeys, privvalues, array_size(privkeys), NULL, NULL); ok_status(SecItemDelete(privDict), "delete key via ref"); is_status(errSecItemNotFound, SecItemCopyMatching(privDict, NULL), "verify key is gone"); CFReleaseNull(privDict); /* add certificate to offset cert row id from key row id */ SecCertificateRef apple_ca_cert = NULL; isnt(apple_ca_cert = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), NULL, "create apple ca certificate"); CFDictionaryRef appleCertDict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&apple_ca_cert, 1, NULL, NULL); ok_status(SecItemAdd(appleCertDict, NULL), "add apple ca certificate to offset key and cert rowid"); /* add identity, get persistent ref */ const void *keys_identity[] = { kSecValueRef, kSecReturnPersistentRef }; const void *values_identity[] = { result_idnt, kCFBooleanTrue }; CFDictionaryRef identity_add = CFDictionaryCreate(NULL, keys_identity, values_identity, array_size(keys_identity), NULL, NULL); CFTypeRef persist = NULL; ok_status(SecItemAdd(identity_add, &persist), "add identity ref"); ok(persist, "got back persistent ref"); /* <rdar://problem/6537195> SecItemAdd returns success when it shouldn't */ CFTypeRef persist_again = NULL; is_status(errSecDuplicateItem, SecItemAdd(identity_add, &persist_again), "fail to add identity ref again"); ok(!persist_again, "no persistent ref this time"); /* find by persistent ref */ const void *keys_persist[] = { kSecReturnRef, kSecValuePersistentRef }; const void *values_persist[] = { kCFBooleanTrue, persist }; CFDictionaryRef persist_find = CFDictionaryCreate(NULL, keys_persist, values_persist, (array_size(keys_persist)), NULL, NULL); CFTypeRef results2 = NULL; ok_status(SecItemCopyMatching(persist_find, &results2), "find identity by persistent ref"); is(CFGetRetainCount(results2), 1, "results2 rc = 1"); // not implemented ok(CFEqual(result_idnt, results2), "same item (attributes)"); CFReleaseNull(results2); /* find identity, key and cert by ref and return persistent ref */ const void *keys_ref_to_persist[] = { kSecReturnPersistentRef, kSecValueRef }; const void *values_ref_to_persist[] = { kCFBooleanTrue, NULL }; CFTypeRef items[] = { result_idnt, privKey, cert, NULL }; CFTypeRef *item = items; while (*item) { values_ref_to_persist[1] = *item; CFDictionaryRef ref_to_persist_find = CFDictionaryCreate(NULL, keys_ref_to_persist, values_ref_to_persist, (array_size(keys_ref_to_persist)), NULL, NULL); results2 = NULL; ok_status(SecItemCopyMatching(ref_to_persist_find, &results2), "find persistent ref for identity ref"); ok(NULL != results2, "good persistent ref"); is(CFGetRetainCount(results2), 1, "results2 rc = 1"); CFReleaseNull(results2); CFReleaseNull(ref_to_persist_find); item++; } /* delete identity by identity ref */ ok_status(SecItemDelete(identity_add), "delete identity by identity ref"); is(SecItemCopyMatching(persist_find, &results2), errSecItemNotFound, "make sure identity by persistent ref is no longer there"); CFRelease(persist_find); CFReleaseNull(persist); ok_status(SecItemAdd(identity_add, &persist), "add identity ref back"); CFRelease(identity_add); /* delete identity by persistent ref */ CFDictionaryRef persist_delete = CFDictionaryCreate(NULL, &kSecValuePersistentRef, &persist, 1, NULL, NULL); ok_status(SecItemDelete(persist_delete), "delete identity by persistent ref"); is(SecItemCopyMatching(persist_delete, &results2), errSecItemNotFound, "make sure identity by persistent ref is no longer there"); CFRelease(persist_delete); CFReleaseNull(persist); /* add identity with a label set */ CFStringRef zomg_label = CFSTR("zomg"); CFMutableDictionaryRef lbl_idnt_query = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(lbl_idnt_query, kSecValueRef, result_idnt); CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label); ok_status(SecItemAdd(lbl_idnt_query, NULL), "add identity ref"); /* find identity with label*/ CFDictionaryRemoveAllValues(lbl_idnt_query); CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassIdentity); CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label); ok_status(SecItemCopyMatching(lbl_idnt_query, NULL), "find identity by label"); /* find certs with label */ CFTypeRef zomg_cert; CFDictionaryRemoveAllValues(lbl_idnt_query); CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassCertificate); CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label); CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue); ok_status(SecItemCopyMatching(lbl_idnt_query, &zomg_cert), "find cert by label"); /* find keys with label */ CFTypeRef zomg_key; CFDictionaryRemoveAllValues(lbl_idnt_query); CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassKey); CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label); CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue); ok_status(SecItemCopyMatching(lbl_idnt_query, &zomg_key), "find key by label"); /* update label on key */ CFStringRef new_label_value = CFSTR("zzzomg"); CFDictionaryRef new_label = CFDictionaryCreate(kCFAllocatorDefault, (const void **)&kSecAttrLabel, (const void **)&new_label_value, 1, NULL, NULL); CFDictionaryRemoveAllValues(lbl_idnt_query); CFDictionarySetValue(lbl_idnt_query, kSecValueRef, zomg_key); ok_status(SecItemUpdate(lbl_idnt_query, new_label), "update label to zzzomg for key"); CFTypeRef zomg_idnt = NULL; CFDictionaryRemoveAllValues(lbl_idnt_query); CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue); CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label); CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassIdentity); ok_status(SecItemCopyMatching(lbl_idnt_query, &zomg_idnt), "still finding zomg ident"); CFReleaseNull(zomg_idnt); CFDictionaryRemoveAllValues(lbl_idnt_query); CFDictionarySetValue(lbl_idnt_query, kSecValueRef, zomg_cert); ok_status(SecItemUpdate(lbl_idnt_query, new_label), "update label to zzzomg for cert"); CFReleaseNull(new_label); CFDictionaryRemoveAllValues(lbl_idnt_query); CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue); CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, zomg_label); CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassIdentity); is_status(errSecItemNotFound, SecItemCopyMatching(lbl_idnt_query, &zomg_idnt), "no longer find identity by label"); CFDictionaryRemoveAllValues(lbl_idnt_query); CFDictionarySetValue(lbl_idnt_query, kSecReturnRef, kCFBooleanTrue); CFDictionarySetValue(lbl_idnt_query, kSecAttrLabel, new_label_value); CFDictionarySetValue(lbl_idnt_query, kSecClass, kSecClassIdentity); ok_status(SecItemCopyMatching(lbl_idnt_query, &zomg_idnt), "finding ident with zzzomg label"); /* Find zomg identity with canonical issuer */ { unsigned char DN[] = { 0x30, 0x32, 0x31, 0x10, 0x30, 0x0e, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x07, 0x70, 0x6c, 0x75, 0x74, 0x6f, 0x43, 0x41, 0x31, 0x1e, 0x30, 0x1c, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x09, 0x01, 0x0c, 0x0f, 0x70, 0x6c, 0x75, 0x74, 0x6f, 0x40, 0x70, 0x6c, 0x75, 0x74, 0x6f, 0x2e, 0x63, 0x6f, 0x6d }; unsigned int DN_len = 52; CFMutableDictionaryRef find_by_issuer = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDataRef issuer = SecCertificateGetNormalizedIssuerContent(cert); CFTypeRef found_by_issuer = NULL; CFDictionarySetValue(find_by_issuer, kSecAttrIssuer, issuer); CFDictionarySetValue(find_by_issuer, kSecClass, kSecClassIdentity); CFDictionarySetValue(find_by_issuer, kSecReturnRef, kCFBooleanTrue); ok_status(SecItemCopyMatching(find_by_issuer, &found_by_issuer), "find identity by cert issuer"); ok(CFEqual(found_by_issuer, zomg_idnt), "should be same as zomg_idnt"); CFReleaseNull(found_by_issuer); issuer = CFDataCreate(kCFAllocatorDefault, DN, DN_len); CFDictionarySetValue(find_by_issuer, kSecAttrIssuer, issuer); ok_status(SecItemCopyMatching(find_by_issuer, &found_by_issuer), "find identity by cert issuer"); CFReleaseNull(issuer); ok(CFEqual(found_by_issuer, zomg_idnt), "should be same as zomg_idnt"); CFReleaseNull(found_by_issuer); CFReleaseNull(find_by_issuer); } ok_status(SecItemDelete(lbl_idnt_query), "delete ident with zzzomg label"); /* Delete the apple cert last */ ok_status(SecItemDelete(appleCertDict), "delete apple ca certificate"); CFReleaseNull(appleCertDict); CFReleaseNull(apple_ca_cert); CFRelease(zomg_key); CFRelease(zomg_cert); CFRelease(zomg_idnt); CFRelease(zomg_label); CFRelease(new_label_value); CFRelease(lbl_idnt_query); CFReleaseNull(result_idnt); CFReleaseNull(privKey); CFReleaseNull(cert); }
/* * Convert a keychain name (which may be NULL) into the CFArrayRef required * by SSLSetCertificate. This is a bare-bones example of this operation, * since it requires and assumes that there is exactly one SecIdentity * in the keychain - i.e., there is exactly one matching cert/private key * pair. A real world server would probably search a keychain for a SecIdentity * matching some specific criteria. */ CFArrayRef getSslCerts( const char *kcName, // may be NULL, i.e., use default bool encryptOnly, bool completeCertChain, const char *anchorFile, // optional trusted anchor SecKeychainRef *pKcRef) // RETURNED { #if 0 SecKeychainRef kcRef = nil; OSStatus ortn; *pKcRef = nil; /* pick a keychain */ if(kcName) { ortn = SecKeychainOpen(kcName, &kcRef); if(ortn) { printf("SecKeychainOpen returned %d.\n", (int)ortn); printf("Cannot open keychain at %s. Aborting.\n", kcName); return NULL; } } else { /* use default keychain */ ortn = SecKeychainCopyDefault(&kcRef); if(ortn) { printf("SecKeychainCopyDefault returned %d; aborting.\n", (int)ortn); return nil; } } *pKcRef = kcRef; return sslKcRefToCertArray(kcRef, encryptOnly, completeCertChain, anchorFile); #else SecCertificateRef cert = NULL; SecIdentityRef identity = NULL; CFMutableArrayRef certificates = NULL, result = NULL; CFMutableDictionaryRef certQuery = NULL, keyQuery = NULL, keyResult = NULL; SecTrustRef trust = NULL; SecKeyRef key = NULL; CFTypeRef pkdigest = NULL; // Find the first private key in the keychain and return both it's // attributes and a ref to it. require(keyQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); CFDictionaryAddValue(keyQuery, kSecClass, kSecClassKey); CFDictionaryAddValue(keyQuery, kSecAttrKeyClass, kSecAttrKeyClassPrivate); CFDictionaryAddValue(keyQuery, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(keyQuery, kSecReturnAttributes, kCFBooleanTrue); require_noerr(SecItemCopyMatching(keyQuery, (CFTypeRef *)&keyResult), errOut); require(key = (SecKeyRef)CFDictionaryGetValue(keyResult, kSecValueRef), errOut); require(pkdigest = CFDictionaryGetValue(keyResult, kSecAttrApplicationLabel), errOut); // Find the first certificate that has the same public key hash as the // returned private key and return it as a ref. require(certQuery = CFDictionaryCreateMutable(NULL, 0, NULL, NULL), errOut); CFDictionaryAddValue(certQuery, kSecClass, kSecClassCertificate); CFDictionaryAddValue(certQuery, kSecAttrPublicKeyHash, pkdigest); CFDictionaryAddValue(certQuery, kSecReturnRef, kCFBooleanTrue); require_noerr(SecItemCopyMatching(certQuery, (CFTypeRef *)&cert), errOut); // Create an identity from the key and certificate. require(identity = SecIdentityCreate(NULL, cert, key), errOut); // Build a (partial) certificate chain from cert require(certificates = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks), errOut); CFArrayAppendValue(certificates, cert); require_noerr(SecTrustCreateWithCertificates(certificates, NULL, &trust), errOut); SecTrustResultType tresult; require_noerr(SecTrustEvaluate(trust, &tresult), errOut); CFIndex certCount, ix; // We need at least 1 certificate require(certCount = SecTrustGetCertificateCount(trust), errOut); // Build a result where element 0 is the identity and the other elements // are the certs in the chain starting at the first intermediate up to the // anchor, if we found one, or as far as we were able to build the chain // if not. require(result = CFArrayCreateMutable(NULL, certCount, &kCFTypeArrayCallBacks), errOut); // We are commited to returning a result now, so do not use require below // this line without setting result to NULL again. CFArrayAppendValue(result, identity); for (ix = 1; ix < certCount; ++ix) { CFArrayAppendValue(result, SecTrustGetCertificateAtIndex(trust, ix)); } errOut: CFReleaseSafe(trust); CFReleaseSafe(certificates); CFReleaseSafe(identity); CFReleaseSafe(cert); CFReleaseSafe(certQuery); CFReleaseSafe(keyResult); CFReleaseSafe(keyQuery); return result; #endif }
static void tests(void) { SecKeyRef phone_publicKey = NULL, phone_privateKey = NULL; SecKeyRef ca_publicKey = NULL, ca_privateKey = NULL; int keysize = 2048; CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keysize); const void *keygen_keys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits }; const void *keygen_vals[] = { kSecAttrKeyTypeRSA, key_size_num }; CFDictionaryRef parameters = CFDictionaryCreate(kCFAllocatorDefault, keygen_keys, keygen_vals, array_size(keygen_vals), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks ); CFReleaseNull(key_size_num); CFMutableDictionaryRef subject_alt_names = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(subject_alt_names, CFSTR("dnsname"), CFSTR("xey.nl")); int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment; CFNumberRef key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage); CFMutableDictionaryRef random_extensions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); const void *key[] = { kSecCSRChallengePassword, kSecSubjectAltName, kSecCertificateKeyUsage, kSecCertificateExtensions }; const void *val[] = { CFSTR("magic"), subject_alt_names, key_usage_num, random_extensions }; CFDictionaryRef csr_parameters = CFDictionaryCreate(kCFAllocatorDefault, key, val, array_size(key), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); SecATV cn_phone[] = { { kSecOidCommonName, SecASN1PrintableString, CFSTR("My iPhone") }, {} }; SecATV c[] = { { kSecOidCountryName, SecASN1PrintableString, CFSTR("US") }, {} }; SecATV st[] = { { kSecOidStateProvinceName, SecASN1PrintableString, CFSTR("CA") }, {} }; SecATV l[] = { { kSecOidLocalityName, SecASN1PrintableString, CFSTR("Cupertino") }, {} }; SecATV o[] = { { CFSTR("2.5.4.10"), SecASN1PrintableString, CFSTR("Apple Inc.") }, {} }; SecATV ou[] = { { kSecOidOrganizationalUnit, SecASN1PrintableString, CFSTR("iPhone") }, {} }; SecRDN atvs_phone[] = { cn_phone, c, st, l, o, ou, NULL }; ok_status(SecKeyGeneratePair(parameters, &phone_publicKey, &phone_privateKey), "generate key pair"); ok_status(SecKeyGeneratePair(parameters, &ca_publicKey, &ca_privateKey), "generate key pair"); int self_key_usage = kSecKeyUsageKeyCertSign | kSecKeyUsageCRLSign; CFNumberRef self_key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &self_key_usage); int path_len = 0; CFNumberRef path_len_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &path_len); const void *self_key[] = { kSecCertificateKeyUsage, kSecCSRBasicContraintsPathLen }; const void *self_val[] = { self_key_usage_num, path_len_num }; CFDictionaryRef self_signed_parameters = CFDictionaryCreate(kCFAllocatorDefault, self_key, self_val, array_size(self_key), NULL, NULL); const void * ca_o[] = { kSecOidOrganization, CFSTR("Apple Inc.") }; const void * ca_cn[] = { kSecOidCommonName, CFSTR("Root CA") }; CFArrayRef ca_o_dn = CFArrayCreate(kCFAllocatorDefault, ca_o, 2, NULL); CFArrayRef ca_cn_dn = CFArrayCreate(kCFAllocatorDefault, ca_cn, 2, NULL); const void *ca_dn_array[2]; ca_dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_o_dn, 1, NULL); ca_dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&ca_cn_dn, 1, NULL); CFArrayRef ca_rdns = CFArrayCreate(kCFAllocatorDefault, ca_dn_array, 2, NULL); SecCertificateRef ca_cert = SecGenerateSelfSignedCertificate(ca_rdns, self_signed_parameters, ca_publicKey, ca_privateKey); SecCertificateRef ca_cert_phone_key = SecGenerateSelfSignedCertificate(ca_rdns, self_signed_parameters, phone_publicKey, phone_privateKey); CFReleaseSafe(self_signed_parameters); CFReleaseSafe(self_key_usage_num); CFReleaseSafe(path_len_num); CFReleaseNull(ca_o_dn); CFReleaseNull(ca_cn_dn); CFReleaseNull(ca_dn_array[0]); CFReleaseNull(ca_dn_array[1]); CFReleaseNull(ca_rdns); isnt(ca_cert, NULL, "got back a cert"); ok(SecCertificateIsSelfSignedCA(ca_cert), "cert is self-signed ca cert"); isnt(ca_cert_phone_key, NULL, "got back a cert"); ok(SecCertificateIsSelfSignedCA(ca_cert_phone_key), "cert is self-signed ca cert"); CFDataRef data = SecCertificateCopyData(ca_cert); //write_data("/tmp/ca_cert.der", data); CFReleaseSafe(data); SecIdentityRef ca_identity = SecIdentityCreate(kCFAllocatorDefault, ca_cert, ca_privateKey); SecIdentityRef ca_identity_phone_key = SecIdentityCreate(kCFAllocatorDefault, ca_cert_phone_key, phone_privateKey); isnt(ca_identity, NULL, "got a identity"); isnt(ca_identity_phone_key, NULL, "got a identity"); CFDictionaryRef dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity, 1, NULL, NULL); ok_status(SecItemAdd(dict, NULL), "add ca identity"); CFReleaseSafe(dict); #if TARGET_OS_IPHONE TODO: { todo("Adding a cert with the same issuer/serial but a different key should return something other than errSecDuplicateItem"); #else { #endif dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity_phone_key, 1, NULL, NULL); is_status(errSecDuplicateItem, SecItemAdd(dict, NULL), "add ca identity"); CFReleaseSafe(dict); } CFDataRef csr = SecGenerateCertificateRequestWithParameters(atvs_phone, NULL, phone_publicKey, phone_privateKey); isnt(csr, NULL, "got back a csr"); CFReleaseNull(csr); //dict[kSecSubjectAltName, dict[ntPrincipalName, "*****@*****.**"]] CFStringRef nt_princ_name_val = CFSTR("*****@*****.**"); CFStringRef nt_princ_name_key = CFSTR("ntPrincipalName"); CFDictionaryRef nt_princ = CFDictionaryCreate(NULL, (const void **)&nt_princ_name_key, (const void **)&nt_princ_name_val, 1, NULL, NULL); CFDictionaryRef params = CFDictionaryCreate(NULL, (const void **)&kSecSubjectAltName, (const void **)&nt_princ, 1, NULL, NULL); csr = SecGenerateCertificateRequestWithParameters(atvs_phone, params, phone_publicKey, phone_privateKey); isnt(csr, NULL, "got back a csr"); //write_data("/var/tmp/csr-nt-princ", csr); CFReleaseNull(csr); CFReleaseNull(params); CFReleaseNull(nt_princ); csr = SecGenerateCertificateRequestWithParameters(atvs_phone, csr_parameters, phone_publicKey, phone_privateKey); isnt(csr, NULL, "csr w/ params"); //write_data("/tmp/csr", csr); CFDataRef subject, extensions; CFStringRef challenge; ok(SecVerifyCertificateRequest(csr, NULL, &challenge, &subject, &extensions), "verify csr"); CFReleaseNull(csr); uint8_t serialno_byte = 42; CFDataRef serialno = CFDataCreate(kCFAllocatorDefault, &serialno_byte, sizeof(serialno_byte)); SecCertificateRef cert = SecIdentitySignCertificate(ca_identity, serialno, phone_publicKey, subject, extensions); data = SecCertificateCopyData(cert); //write_data("/tmp/iphone_cert.der", data); CFReleaseNull(data); CFReleaseNull(subject); CFReleaseNull(extensions); CFReleaseNull(challenge); const void * email[] = { CFSTR("1.2.840.113549.1.9.1"), CFSTR("*****@*****.**") }; const void * cn[] = { CFSTR("2.5.4.3"), CFSTR("S/MIME Baby") }; CFArrayRef email_dn = CFArrayCreate(kCFAllocatorDefault, email, 2, NULL); CFArrayRef cn_dn = CFArrayCreate(kCFAllocatorDefault, cn, 2, NULL); const void *dn_array[2]; dn_array[0] = CFArrayCreate(kCFAllocatorDefault, (const void **)&email_dn, 1, NULL); dn_array[1] = CFArrayCreate(kCFAllocatorDefault, (const void **)&cn_dn, 1, NULL); CFArrayRef rdns = CFArrayCreate(kCFAllocatorDefault, dn_array, 2, NULL); CFDictionarySetValue(subject_alt_names, CFSTR("rfc822name"), CFSTR("*****@*****.**")); uint8_t random_extension_data[] = { 0xde, 0xad, 0xbe, 0xef }; CFDataRef random_extension_value = CFDataCreate(kCFAllocatorDefault, random_extension_data, sizeof(random_extension_data)); CFDictionarySetValue(random_extensions, CFSTR("1.2.840.113635.100.6.1.2"), random_extension_value); // APPLE_FDR_ACCESS_OID CFDictionarySetValue(random_extensions, CFSTR("1.2.840.113635.100.6.1.3"), CFSTR("that guy")); // APPLE_FDR_CLIENT_IDENTIFIER_OID CFReleaseNull(random_extension_value); csr = SecGenerateCertificateRequest(rdns, csr_parameters, phone_publicKey, phone_privateKey); isnt(csr, NULL, "csr w/ params"); //write_data("/tmp/csr_neu", csr); CFReleaseNull(csr); CFReleaseNull(subject_alt_names); CFDictionaryRemoveAllValues(random_extensions); #if TARGET_OS_IPHONE CFDataRef scep_request = SecSCEPGenerateCertificateRequest(rdns, csr_parameters, phone_publicKey, phone_privateKey, NULL, ca_cert); isnt(scep_request, NULL, "got scep blob"); //write_data("/tmp/scep_request.der", scep_request); #endif CFReleaseNull(email_dn); CFReleaseNull(cn_dn); CFReleaseNull(dn_array[0]); CFReleaseNull(dn_array[1]); CFReleaseNull(rdns); #if TARGET_OS_IPHONE CFDataRef scep_reply = SecSCEPCertifyRequest(scep_request, ca_identity, serialno, false); isnt(scep_reply, NULL, "produced scep reply"); //write_data("/tmp/scep_reply.der", scep_reply); CFArrayRef issued_certs = NULL; ok(issued_certs = SecSCEPVerifyReply(scep_request, scep_reply, ca_cert, NULL), "verify scep reply"); // take the issued cert and CA cert and pretend it's a RA/CA couple CFMutableArrayRef scep_certs = CFArrayCreateMutableCopy(kCFAllocatorDefault, 0, issued_certs); CFArrayAppendValue(scep_certs, ca_cert); SecCertificateRef ca_certificate = NULL, ra_signing_certificate = NULL, ra_encryption_certificate = NULL; ok_status(SecSCEPValidateCACertMessage(scep_certs, NULL, &ca_certificate, &ra_signing_certificate, &ra_encryption_certificate), "pull apart array again"); ok(CFEqual(ca_cert, ca_certificate), "found ca"); ok(CFArrayContainsValue(issued_certs, CFRangeMake(0, CFArrayGetCount(issued_certs)), ra_signing_certificate), "found ra"); ok(!ra_encryption_certificate, "no separate encryption cert"); CFReleaseSafe(ca_certificate); CFReleaseSafe(ra_signing_certificate); CFReleaseSafe(scep_certs); CFReleaseSafe(scep_request); CFReleaseSafe(scep_reply); CFReleaseSafe(issued_certs); #endif // cleanups dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&ca_identity, 1, NULL, NULL); ok_status(SecItemDelete(dict), "delete ca identity"); CFReleaseSafe(dict); dict = CFDictionaryCreate(NULL, (const void **)&kSecValueRef, (const void **)&phone_privateKey, 1, NULL, NULL); ok_status(SecItemDelete(dict), "delete phone private key"); CFReleaseSafe(dict); CFReleaseSafe(serialno); CFReleaseSafe(cert); CFReleaseSafe(ca_identity); CFReleaseSafe(ca_cert); CFReleaseSafe(ca_identity_phone_key); CFReleaseSafe(ca_cert_phone_key); CFReleaseSafe(csr_parameters); CFReleaseSafe(random_extensions); CFReleaseSafe(parameters); CFReleaseSafe(ca_publicKey); CFReleaseSafe(ca_privateKey); CFReleaseSafe(phone_publicKey); CFReleaseSafe(phone_privateKey); } static void test_ec_csr(void) { SecKeyRef ecPublicKey = NULL, ecPrivateKey = NULL; int keysize = 256; CFNumberRef key_size_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &keysize); const void *keyParamsKeys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits }; const void *keyParamsValues[] = { kSecAttrKeyTypeECSECPrimeRandom, key_size_num}; CFDictionaryRef keyParameters = CFDictionaryCreate(NULL, keyParamsKeys, keyParamsValues, 2, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecKeyGeneratePair(keyParameters, &ecPublicKey, &ecPrivateKey), "unable to generate EC key"); SecATV cn_phone[] = { { kSecOidCommonName, SecASN1PrintableString, CFSTR("My iPhone") }, {} }; SecATV c[] = { { kSecOidCountryName, SecASN1PrintableString, CFSTR("US") }, {} }; SecATV st[] = { { kSecOidStateProvinceName, SecASN1PrintableString, CFSTR("CA") }, {} }; SecATV l[] = { { kSecOidLocalityName, SecASN1PrintableString, CFSTR("Cupertino") }, {} }; SecATV o[] = { { CFSTR("2.5.4.10"), SecASN1PrintableString, CFSTR("Apple Inc.") }, {} }; SecATV ou[] = { { kSecOidOrganizationalUnit, SecASN1PrintableString, CFSTR("iPhone") }, {} }; SecRDN atvs_phone[] = { cn_phone, c, st, l, o, ou, NULL }; CFMutableDictionaryRef subject_alt_names = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionarySetValue(subject_alt_names, CFSTR("dnsname"), CFSTR("xey.nl")); int key_usage = kSecKeyUsageDigitalSignature | kSecKeyUsageKeyEncipherment; CFNumberRef key_usage_num = CFNumberCreate(kCFAllocatorDefault, kCFNumberIntType, &key_usage); CFMutableDictionaryRef random_extensions = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); const void *key[] = { kSecCSRChallengePassword, kSecSubjectAltName, kSecCertificateKeyUsage, kSecCertificateExtensions }; const void *val[] = { CFSTR("magic"), subject_alt_names, key_usage_num, random_extensions }; CFDictionaryRef csr_parameters = CFDictionaryCreate(kCFAllocatorDefault, key, val, array_size(key), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDataRef csr = SecGenerateCertificateRequestWithParameters(atvs_phone, csr_parameters, ecPublicKey, ecPrivateKey); isnt(csr, NULL, "csr w/ params"); //write_data("/tmp/csr", csr); CFDataRef subject, extensions; CFStringRef challenge; ok(SecVerifyCertificateRequest(csr, NULL, &challenge, &subject, &extensions), "verify csr"); CFReleaseNull(csr); CFReleaseNull(key_size_num); CFReleaseNull(keyParameters); CFReleaseNull(ecPublicKey); CFReleaseNull(ecPrivateKey); CFReleaseNull(subject_alt_names); CFReleaseNull(key_usage_num); CFReleaseNull(random_extensions); CFReleaseNull(csr_parameters); CFReleaseNull(subject); CFReleaseNull(extensions); CFReleaseNull(challenge); }
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; }