// static bool OTKeyring::IOS_DeleteSecret(const OTString& strUser, const std::string& str_display) { OT_ASSERT(strUser.Exists()); CFStringRef service_name = CFSTR("opentxs"); CFStringRef account_name = CFStringCreateWithCString(nullptr, strUser.Get(), kCFStringEncodingUTF8); const void* keys[] = {kSecClass, kSecAttrService, kSecAttrAccount}; const void* values[] = {kSecClassGenericPassword, service_name, account_name}; CFDictionaryRef query = CFDictionaryCreate(nullptr, keys, values, 3, nullptr, nullptr); OSStatus theError = SecItemDelete(query); CFRelease(query); CFRelease(account_name); if (theError != noErr) { otErr << "OTKeyring::IOS_RetrieveSecret: Error in SecItemDelete.\n"; return false; } return true; }
static void DeleteIdentityFromKeychain(void) { SecCertificateRef cert = NULL; SecKeyRef privKey = NULL; //SecIdentityRef identity = NULL; isnt(cert = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), NULL, "create certificate"); #if TARGET_OS_IPHONE privKey = SecKeyCreateRSAPrivateKey(NULL, _k1, sizeof(_k1), kSecKeyEncodingPkcs1); #else #warning TODO privKey = NULL; #endif isnt(privKey, 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(SecItemDelete(certDict), "delete certificate"); CFReleaseNull(certDict); CFReleaseNull(cert); const void *privkeys[] = { kSecValueRef }; const void *privvalues[] = { privKey }; CFDictionaryRef privDict = CFDictionaryCreate(NULL, privkeys, privvalues, array_size(privkeys), NULL, NULL); ok_status(SecItemDelete(privDict), "delete private key"); CFReleaseNull(privDict); CFReleaseNull(privKey); }
/* Create an empty keychain file that can't be read or written and make sure securityd can deal with it. */ static void tests(void) { #ifndef NO_SERVER plan_skip_all("No testing against server."); #else const char *home_dir = getenv("HOME"); char keychain_dir[1000]; char keychain_name[1000]; sprintf(keychain_dir, "%s/Library/Keychains", home_dir); sprintf(keychain_name, "%s/keychain-2-debug.db", keychain_dir); ensureKeychainExists(); int fd; ok_unix(fd = open(keychain_name, O_RDWR | O_CREAT | O_TRUNC, 0644), "create keychain file '%s'", keychain_name); ok_unix(fchmod(fd, 0), " keychain file '%s'", keychain_name); ok_unix(close(fd), "close keychain file '%s'", keychain_name); kc_dbhandle_reset(); int v_eighty = 80; CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); const char *v_data = "test"; CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); CFDictionaryAddValue(query, kSecAttrServer, CFSTR("members.spamcop.net")); CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); CFDictionaryAddValue(query, kSecAttrPort, eighty); CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); CFDictionaryAddValue(query, kSecValueData, pwdata); ok_status(SecItemAdd(query, NULL), "add internet password"); is_status(SecItemAdd(query, NULL), errSecDuplicateItem, "add internet password again"); ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); ok_status(SecItemDelete(query),"Deleted the item we added"); CFReleaseSafe(eighty); CFReleaseSafe(pwdata); CFReleaseSafe(query); #endif }
static void test_persistent2(struct test_persistent_s *p) { CFTypeRef results = NULL; CFTypeRef results2 = NULL; ok_status(!SecItemCopyMatching(p->query, &results), "don't find internet password by attributes"); ok(!results, "no results"); ok_status(!SecItemCopyMatching(p->query2, &results2), "don't find internet password by persistent ref anymore"); ok(!results2, "no results"); SKIP:{ ok_status(SecItemCopyMatching(p->query4, &results2), "find non updated internet password by persistent ref"); skip("non updated internet password by persistent ref NOT FOUND!", 2, results2); ok(results2, "non updated internet password not found"); CFStringRef server = CFDictionaryGetValue(results2, kSecAttrServer); ok(CFEqual(server, CFSTR("zuigt.nl")), "verify second items attribute was not modified by update"); CFReleaseNull(results2); } is_status(SecItemCopyMatching(p->query3, &results2), errSecItemNotFound, "don't find deleted internet password by persistent ref"); CFReleaseNull(results2); ok_status(SecItemCopyMatching(p->query4, &results2), "find non deleted internet password by persistent ref"); CFReleaseNull(results2); ok_status(SecItemDelete(p->query4),"Deleted internet password by persistent ref"); CFRelease(p->query); CFRelease(p->query2); CFRelease(p->query3); CFRelease(p->query4); CFReleaseNull(p->persist[0]); CFReleaseNull(p->persist[1]); }
/* 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); }
extern "C" int32_t AppleCryptoNative_X509CopyWithPrivateKey(SecCertificateRef cert, SecKeyRef privateKey, SecKeychainRef targetKeychain, SecIdentityRef* pIdentityOut, int32_t* pOSStatus) { if (pIdentityOut != nullptr) *pIdentityOut = nullptr; if (pOSStatus != nullptr) *pOSStatus = noErr; if (cert == nullptr || privateKey == nullptr || targetKeychain == nullptr || pIdentityOut == nullptr || pOSStatus == nullptr) { return -1; } SecKeychainRef keyKeychain = nullptr; OSStatus status = SecKeychainItemCopyKeychain(reinterpret_cast<SecKeychainItemRef>(privateKey), &keyKeychain); SecKeychainItemRef itemCopy = nullptr; // This only happens with an ephemeral key, so the keychain we're adding it to is temporary. if (status == errSecNoSuchKeychain) { status = AddKeyToKeychain(privateKey, targetKeychain); } if (itemCopy != nullptr) { CFRelease(itemCopy); } CFMutableDictionaryRef query = nullptr; if (status == noErr) { query = CFDictionaryCreateMutable( kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); if (query == nullptr) { status = errSecAllocate; } } CFArrayRef searchList = nullptr; if (status == noErr) { searchList = CFArrayCreate( nullptr, const_cast<const void**>(reinterpret_cast<void**>(&targetKeychain)), 1, &kCFTypeArrayCallBacks); if (searchList == nullptr) { status = errSecAllocate; } } CFArrayRef itemMatch = nullptr; if (status == noErr) { itemMatch = CFArrayCreate( nullptr, const_cast<const void**>(reinterpret_cast<void**>(&cert)), 1, &kCFTypeArrayCallBacks); if (itemMatch == nullptr) { status = errSecAllocate; } } CFTypeRef result = nullptr; if (status == noErr) { CFDictionarySetValue(query, kSecReturnRef, kCFBooleanTrue); CFDictionarySetValue(query, kSecMatchSearchList, searchList); CFDictionarySetValue(query, kSecMatchItemList, itemMatch); CFDictionarySetValue(query, kSecClass, kSecClassIdentity); status = SecItemCopyMatching(query, &result); if (status != noErr && result != nullptr) { CFRelease(result); result = nullptr; } bool added = false; if (status == errSecItemNotFound) { status = SecCertificateAddToKeychain(cert, targetKeychain); added = (status == noErr); } if (result == nullptr && status == noErr) { status = SecItemCopyMatching(query, &result); } if (result != nullptr && status == noErr) { if (CFGetTypeID(result) != SecIdentityGetTypeID()) { status = errSecItemNotFound; } else { SecIdentityRef identity = reinterpret_cast<SecIdentityRef>(const_cast<void*>(result)); CFRetain(identity); *pIdentityOut = identity; } } if (added) { // The same query that was used to find the identity can be used // to find/delete the certificate, as long as we fix the class to just the cert. CFDictionarySetValue(query, kSecClass, kSecClassCertificate); // Ignore the output status, there's no point in telling the user // that the cleanup failed, since that just makes them have a dirty keychain // AND their program didn't work. SecItemDelete(query); } } if (result != nullptr) CFRelease(result); if (itemMatch != nullptr) CFRelease(itemMatch); if (searchList != nullptr) CFRelease(searchList); if (query != nullptr) CFRelease(query); if (keyKeychain != nullptr) CFRelease(keyKeychain); *pOSStatus = status; return status == noErr; }
static void testkeygen2(size_t keySizeInBits) { SecKeyRef pubKey = NULL, privKey = NULL; size_t keySizeInBytes = (keySizeInBits + 7) / 8; CFNumberRef kzib; int32_t keysz32 = (int32_t)keySizeInBits; CFUUIDRef ourUUID = CFUUIDCreate(kCFAllocatorDefault); CFStringRef uuidString = CFUUIDCreateString(kCFAllocatorDefault, ourUUID); CFMutableStringRef publicName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); CFMutableStringRef privateName = CFStringCreateMutableCopy(kCFAllocatorDefault, 0, uuidString); CFReleaseNull(ourUUID); CFReleaseNull(uuidString); CFStringAppend(publicName, CFSTR("-Public-41")); CFStringAppend(privateName, CFSTR("-Private-41")); CFMutableDictionaryRef pubd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecAttrLabel, publicName, NULL); CFMutableDictionaryRef privd = CFDictionaryCreateMutableForCFTypesWith(kCFAllocatorDefault, kSecAttrLabel, privateName, NULL); kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); CFDictionaryRef kgp = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecAttrKeyType, kSecAttrKeyTypeEC, kSecAttrKeySizeInBits, kzib, kSecAttrIsPermanent, kCFBooleanTrue, kSecPublicKeyAttrs, pubd, kSecPrivateKeyAttrs, privd, NULL); CFReleaseNull(kzib); OSStatus status; ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), "Generate %ld bit (%ld byte) persistent RSA keypair", keySizeInBits, keySizeInBytes); CFReleaseNull(kgp); SKIP: { skip("keygen failed", 8, status == errSecSuccess); ok(pubKey, "pubkey returned"); ok(privKey, "privKey returned"); is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); SecKeyRef pubKey2, privKey2; CFDictionaryAddValue(pubd, kSecClass, kSecClassKey); CFDictionaryAddValue(pubd, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(privd, kSecClass, kSecClassKey); CFDictionaryAddValue(privd, kSecReturnRef, kCFBooleanTrue); CFDictionaryAddValue(privd, kSecAttrCanSign, kCFBooleanTrue); ok_status(SecItemCopyMatching(pubd, (CFTypeRef *)&pubKey2), "retrieve pub key by label"); ok(pubKey2, "got valid object"); ok_status(SecItemCopyMatching(privd, (CFTypeRef *)&privKey2), "retrieve priv key by label and kSecAttrCanSign"); ok(privKey2, "got valid object"); /* Sign something. */ uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; size_t sigLen = SecKeyGetSize(privKey2, kSecKeySignatureSize); uint8_t sig[sigLen]; ok_status(SecKeyRawSign(privKey2, kSecPaddingPKCS1, something, sizeof(something), sig, &sigLen), "sign something"); ok_status(SecKeyRawVerify(pubKey2, kSecPaddingPKCS1, something, sizeof(something), sig, sigLen), "verify sig on something"); /* Cleanup. */ CFReleaseNull(pubKey2); CFReleaseNull(privKey2); } /* delete from keychain - note: do it before releasing publicName and privateName because pubd and privd have no retain/release callbacks */ ok_status(SecItemDelete(pubd), "delete generated pub key"); ok_status(SecItemDelete(privd), "delete generated priv key"); /* Cleanup. */ CFReleaseNull(pubKey); CFReleaseNull(privKey); CFReleaseNull(publicName); CFReleaseNull(privateName); CFReleaseNull(pubd); CFReleaseNull(privd); }
static void testkeygen(size_t keySizeInBits) { SecKeyRef pubKey = NULL, privKey = NULL; size_t keySizeInBytes = (keySizeInBits + 7) / 8; CFNumberRef kzib; int32_t keysz32 = (int32_t)keySizeInBits; kzib = CFNumberCreate(NULL, kCFNumberSInt32Type, &keysz32); CFMutableDictionaryRef kgp = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionaryAddValue(kgp, kSecAttrKeyType, kSecAttrKeyTypeEC); CFDictionaryAddValue(kgp, kSecAttrKeySizeInBits, kzib); OSStatus status; ok_status(status = SecKeyGeneratePair(kgp, &pubKey, &privKey), "Generate %ld bit (%ld byte) EC keypair", keySizeInBits, keySizeInBytes); CFRelease(kzib); CFRelease(kgp); SKIP: { skip("keygen failed", 8, status == errSecSuccess); ok(pubKey, "pubkey returned"); ok(privKey, "privKey returned"); is(SecKeyGetSize(pubKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "public key size is ok"); is(SecKeyGetSize(privKey, kSecKeyKeySizeInBits), (size_t) keySizeInBits, "private key size is ok"); /* Sign something. */ uint8_t something[20] = {0x80, 0xbe, 0xef, 0xba, 0xd0, }; uint8_t sig[8+2*keySizeInBytes]; size_t sigLen = sizeof(sig); ok_status(SecKeyRawSign(privKey, kSecPaddingNone, something, sizeof(something), sig, &sigLen), "sign something"); ok_status(SecKeyRawVerify(pubKey, kSecPaddingNone, something, sizeof(something), sig, sigLen), "verify sig on something"); testdigestandsign(privKey, pubKey); const void *privkeys[] = { kSecValueRef }; const void *privvalues[] = { privKey }; CFDictionaryRef privitem = CFDictionaryCreate(NULL, privkeys, privvalues, array_size(privkeys), NULL, NULL); ok_status(SecItemAdd(privitem, NULL), "add private key"); ok_status(SecItemDelete(privitem), "delete public key"); CFReleaseNull(privitem); const void *pubkeys[] = { kSecValueRef }; const void *pubvalues[] = { pubKey }; CFDictionaryRef pubitem = CFDictionaryCreate(NULL, pubkeys, pubvalues, array_size(pubkeys), NULL, NULL); ok_status(SecItemAdd(pubitem, NULL), "add public key"); ok_status(SecItemDelete(pubitem), "delete public key"); CFReleaseNull(pubitem); /* Cleanup. */ CFReleaseNull(pubKey); CFReleaseNull(privKey); } }
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); }
static void test_persistent(struct test_persistent_s *p) { int v_eighty = 80; CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); const char *v_data = "test"; CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); const void *keys[] = { kSecClass, kSecAttrServer, kSecAttrAccount, kSecAttrPort, kSecAttrProtocol, kSecAttrAuthenticationType, kSecReturnPersistentRef, kSecValueData }; const void *values[] = { kSecClassInternetPassword, CFSTR("zuigt.nl"), CFSTR("frtnbf"), eighty, CFSTR("http"), CFSTR("dflt"), kCFBooleanTrue, pwdata }; CFDictionaryRef item = CFDictionaryCreate(NULL, keys, values, array_size(keys), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); p->persist[0] = NULL; // NUKE anything we might have left around from a previous test run so we don't crash. SecItemDelete(item); ok_status(SecItemAdd(item, &p->persist[0]), "add internet password"); CFTypeRef results = NULL; CFTypeRef results2 = NULL; SKIP: { skip("no persistent ref", 6, ok(p->persist[0], "got back persistent ref")); /* Create a dict with all attrs except the data. */ keys[(array_size(keys)) - 2] = kSecReturnAttributes; p->query = CFDictionaryCreate(NULL, keys, values, (array_size(keys)) - 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecItemCopyMatching(p->query, &results), "find internet password by attr"); const void *keys_persist[] = { kSecReturnAttributes, kSecValuePersistentRef }; const void *values_persist[] = { kCFBooleanTrue, p->persist[0] }; p->query2 = CFDictionaryCreate(NULL, keys_persist, values_persist, (array_size(keys_persist)), &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); ok_status(SecItemCopyMatching(p->query2, &results2), "find internet password by persistent ref"); ok(CFEqual(results, results2 ? results2 : CFSTR("")), "same item (attributes)"); CFReleaseNull(results); CFReleaseNull(results2); ok_status(SecItemDelete(p->query), "delete internet password"); ok_status(!SecItemCopyMatching(p->query, &results), "don't find internet password by attributes"); ok(!results, "no results"); } /* clean up left over from aborted run */ if (results) { CFDictionaryRef cleanup = CFDictionaryCreate(NULL, &kSecValuePersistentRef, &results, 1, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); SecItemDelete(cleanup); CFRelease(results); CFRelease(cleanup); } ok_status(!SecItemCopyMatching(p->query2, &results2), "don't find internet password by persistent ref anymore"); ok(!results2, "no results"); CFReleaseNull(p->persist[0]); /* Add a new item and get it's persitant ref. */ ok_status(SecItemAdd(item, &p->persist[0]), "add internet password"); p->persist[1] = NULL; CFMutableDictionaryRef item2 = CFDictionaryCreateMutableCopy(NULL, 0, item); CFDictionarySetValue(item2, kSecAttrAccount, CFSTR("johndoe-bu")); // NUKE anything we might have left around from a previous test run so we don't crash. SecItemDelete(item2); ok_status(SecItemAdd(item2, &p->persist[1]), "add second internet password"); CFMutableDictionaryRef update = NULL; CFStringRef server = NULL; SKIP: { skip("no persistent ref", 3, ok(p->persist[0], "got back persistent ref from first internet password")); is(CFGetTypeID(p->persist[0]), CFDataGetTypeID(), "result is a CFData"); p->query3 = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(p->query3, kSecValuePersistentRef, p->persist[0]); update = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionaryAddValue(update, kSecAttrServer, CFSTR("zuigt.com")); ok_status(SecItemUpdate(p->query3, update), "update via persitant ref"); /* Verify that the update really worked. */ CFDictionaryAddValue(p->query3, kSecReturnAttributes, kCFBooleanTrue); ok_status(SecItemCopyMatching(p->query3, &results2), "find updated internet password by persistent ref"); server = CFDictionaryGetValue(results2, kSecAttrServer); ok(CFEqual(server, CFSTR("zuigt.com")), "verify attribute was modified by update"); CFReleaseNull(results2); CFDictionaryRemoveValue(p->query3, kSecReturnAttributes); } SKIP: { skip("no persistent ref", 2, ok(p->persist[1], "got back persistent ref")); /* Verify that item2 wasn't affected by the update. */ p->query4 = CFDictionaryCreateMutable(NULL, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks); CFDictionaryAddValue(p->query4, kSecValuePersistentRef, p->persist[1]); CFDictionaryAddValue(p->query4, kSecReturnAttributes, kCFBooleanTrue); ok_status(SecItemCopyMatching(p->query4, &results2), "find non updated internet password by persistent ref"); server = CFDictionaryGetValue(results2, kSecAttrServer); ok(CFEqual(server, CFSTR("zuigt.nl")), "verify second items attribute was not modified by update"); CFReleaseNull(results2); } /* Delete the item via persitant ref. */ ok_status(SecItemDelete(p->query3), "delete via persitant ref"); is_status(SecItemCopyMatching(p->query3, &results2), errSecItemNotFound, "don't find deleted internet password by persistent ref"); CFReleaseNull(results2); ok_status(SecItemCopyMatching(p->query4, &results2), "find non deleted internet password by persistent ref"); CFReleaseNull(results2); CFReleaseNull(update); CFReleaseNull(item); CFReleaseNull(item2); CFReleaseNull(eighty); CFReleaseNull(pwdata); }
/* Test low level keychain migration from device to device interface. */ static void tests(void) { int v_eighty = 80; CFNumberRef eighty = CFNumberCreate(NULL, kCFNumberSInt32Type, &v_eighty); const char *v_data = "test"; CFDataRef pwdata = CFDataCreate(NULL, (UInt8 *)v_data, strlen(v_data)); CFMutableDictionaryRef query = CFDictionaryCreateMutable(NULL, 0, NULL, NULL); CFDictionaryAddValue(query, kSecClass, kSecClassInternetPassword); CFDictionaryAddValue(query, kSecAttrServer, CFSTR("members.spamcop.net")); CFDictionaryAddValue(query, kSecAttrAccount, CFSTR("smith")); CFDictionaryAddValue(query, kSecAttrPort, eighty); CFDictionaryAddValue(query, kSecAttrProtocol, kSecAttrProtocolHTTP); CFDictionaryAddValue(query, kSecAttrAuthenticationType, kSecAttrAuthenticationTypeDefault); CFDictionaryAddValue(query, kSecValueData, pwdata); // NUKE anything we might have left around from a previous test run so we don't crash. SecItemDelete(query); ok_status(SecItemAdd(query, NULL), "add internet password"); is_status(SecItemAdd(query, NULL), errSecDuplicateItem, "add internet password again"); ok_status(SecItemCopyMatching(query, NULL), "Found the item we added"); struct test_persistent_s p = {}; test_persistent(&p); CFDataRef backup = NULL, keybag = NULL, password = NULL; test_add_lockdown_identity_items(); #if USE_KEYSTORE keybag = create_keybag(kAppleKeyStoreBackupBag, password); #else keybag = CFDataCreate(kCFAllocatorDefault, NULL, 0); #endif ok(backup = _SecKeychainCopyBackup(keybag, password), "_SecKeychainCopyBackup"); test_add_managedconfiguration_item(); test_remove_lockdown_identity_items(); ok_status(_SecKeychainRestoreBackup(backup, keybag, password), "_SecKeychainRestoreBackup"); CFReleaseSafe(backup); test_no_find_lockdown_identity_item(); test_find_managedconfiguration_item(); ok_status(SecItemCopyMatching(query, NULL), "Found the item we added after restore"); test_persistent2(&p); #if USE_KEYSTORE CFReleaseNull(keybag); keybag = create_keybag(kAppleKeyStoreOTABackupBag, password); #endif ok(backup = _SecKeychainCopyBackup(keybag, password), "_SecKeychainCopyBackup"); ok_status(_SecKeychainRestoreBackup(backup, keybag, password), "_SecKeychainRestoreBackup"); ok_status(SecItemCopyMatching(query, NULL), "Found the item we added after restore"); CFReleaseNull(backup); // force tombstone to be added, since it's not the default behavior per rdar://14680869 CFDictionaryAddValue(query, kSecUseTombstones, kCFBooleanTrue); ok_status(SecItemDelete(query), "Deleted item we added"); #if USE_KEYSTORE CFReleaseNull(keybag); keybag = create_keybag(kAppleKeyStoreOTABackupBag /* use truthiness bag once it's there */, password); #endif // add syncable item CFDictionaryAddValue(query, kSecAttrSynchronizable, kCFBooleanTrue); ok_status(SecItemAdd(query, NULL), "add internet password"); // and non-syncable item test_add_managedconfiguration_item(); CFDictionaryRef syncableBackup = NULL; CFErrorRef error = NULL; CFDictionaryRef scratch = NULL; SKIP: { skip("skipping syncable backup tests", 7, ok_status(_SecKeychainBackupSyncable(keybag, password, NULL, &syncableBackup), "export items")); // TODO: add item, call SecServerCopyTruthInTheCloud again // CFShow(syncableBackup); // find and delete skip("skipping syncable backup tests", 6, ok_status(SecItemCopyMatching(query, NULL), "find item we are about to destroy")); skip("skipping syncable backup tests", 5, ok_status(SecItemDelete(query), "delete item we backed up")); // ensure we added a tombstone CFDictionaryAddValue(query, kSecAttrTombstone, kCFBooleanTrue); skip("skipping syncable backup tests", 4, ok_status(SecItemCopyMatching(query, NULL), "find tombstone for item we deleted")); CFDictionaryRemoveValue(query, kSecAttrTombstone); test_find_managedconfiguration_item(); // <- 2 tests here // TODO: add a different new item - delete what's not in the syncableBackup? // Do another backup after some changes skip("skipping syncable backup tests", 1, ok_status(_SecKeychainBackupSyncable(keybag, password, syncableBackup, &scratch), "export items after changes")); skip("skipping syncable backup tests", 0, ok_status(_SecKeychainRestoreSyncable(keybag, password, syncableBackup), "import items")); } CFReleaseNull(scratch); CFReleaseNull(error); // non-syncable item should (still) be gone -> add should work test_add_managedconfiguration_item(); test_find_managedconfiguration_item(); // syncable item should have not been restored, because the tombstone was newer than the item in the backup -> copy matching should fail is_status(errSecItemNotFound, SecItemCopyMatching(query, NULL), "find restored item"); is_status(errSecItemNotFound, SecItemDelete(query), "delete restored item"); CFReleaseSafe(syncableBackup); CFReleaseSafe(keybag); CFReleaseSafe(eighty); CFReleaseSafe(pwdata); CFReleaseSafe(query); }
static void test_find_managedconfiguration_item(void) { CFMutableDictionaryRef query = test_create_managedconfiguration_query(); ok_status(SecItemCopyMatching(query, NULL), "test_find_managedconfiguration_item"); ok_status(SecItemDelete(query), "test_find_managedconfiguration_item (deleted)"); CFReleaseSafe(query); }
static void test_remove_lockdown_identity_items(void) { CFMutableDictionaryRef query = test_create_lockdown_identity_query(); ok_status(SecItemDelete(query), "test_remove_lockdown_identity_items"); CFReleaseSafe(query); }
/* Test basic add delete update copy matching stuff. */ static void tests(void) { SecTrustRef trust; SecCertificateRef cert0, cert1; isnt(cert0 = SecCertificateCreateWithBytes(NULL, _c0, sizeof(_c0)), NULL, "create cert0"); isnt(cert1 = SecCertificateCreateWithBytes(NULL, _c1, sizeof(_c1)), NULL, "create cert1"); const void *v_certs[] = { cert0, cert1 }; SecPolicyRef policy = SecPolicyCreateSSL(false, NULL); CFArrayRef certs = CFArrayCreate(NULL, v_certs, array_size(v_certs), NULL); /* SecTrustCreateWithCertificates using single cert. */ ok_status(SecTrustCreateWithCertificates(cert0, policy, &trust), "create trust with single cert0"); is(SecTrustGetCertificateCount(trust), 1, "cert count is 1"); is(SecTrustGetCertificateAtIndex(trust, 0), cert0, "cert 0 is leaf"); CFReleaseNull(trust); /* SecTrustCreateWithCertificates failures. */ is_status(SecTrustCreateWithCertificates(kCFBooleanTrue, policy, &trust), errSecParam, "create trust with boolean instead of cert"); is_status(SecTrustCreateWithCertificates(cert0, kCFBooleanTrue, &trust), errSecParam, "create trust with boolean instead of policy"); /* SecTrustCreateWithCertificates using array of certs. */ ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust"); /* NOTE: prior to <rdar://11810677 SecTrustGetCertificateCount would return 1 at this point. * Now, however, we do an implicit SecTrustEvaluate to build the chain if it has not yet been * evaluated, so we now expect the full chain length. */ is(SecTrustGetCertificateCount(trust), 3, "cert count is 3"); is(SecTrustGetCertificateAtIndex(trust, 0), cert0, "cert 0 is leaf"); /* Jan 1st 2006. */ CFDateRef date = CFDateCreate(NULL, 157680000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); is(SecTrustGetVerifyTime(trust), 157680000.0, "get date"); SecTrustResultType trustResult; SKIP: { #ifdef NO_SERVER skip("Can't fail to connect to securityd in NO_SERVER mode", 4, false); #endif // Test Restore OS environment SecServerSetMachServiceName("com.apple.security.doesn't-exist"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust without securityd running"); is_status(trustResult, kSecTrustResultInvalid, "trustResult is kSecTrustResultInvalid"); is(SecTrustGetCertificateCount(trust), 1, "cert count is 1 without securityd running"); SecKeyRef pubKey = NULL; ok(pubKey = SecTrustCopyPublicKey(trust), "copy public key without securityd running"); CFReleaseNull(pubKey); SecServerSetMachServiceName(NULL); // End of Restore OS environment tests } ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trustResult is kSecTrustResultUnspecified"); is(SecTrustGetCertificateCount(trust), 3, "cert count is 3"); CFDataRef c0_serial = CFDataCreate(NULL, _c0_serial, sizeof(_c0_serial)); CFDataRef serial; ok(serial = SecCertificateCopySerialNumber(cert0), "copy cert0 serial"); ok(CFEqual(c0_serial, serial), "serial matches"); CFArrayRef anchors = CFArrayCreate(NULL, (const void **)&cert1, 1, &kCFTypeArrayCallBacks); ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set anchors"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); is(SecTrustGetCertificateCount(trust), 2, "cert count is 2"); CFReleaseSafe(anchors); anchors = CFArrayCreate(NULL, NULL, 0, NULL); ok_status(SecTrustSetAnchorCertificates(trust, anchors), "set empty anchors list"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); ok_status(SecTrustSetAnchorCertificatesOnly(trust, false), "trust passed in anchors and system anchors"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); ok_status(SecTrustSetAnchorCertificatesOnly(trust, true), "only trust passed in anchors (default)"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); /* Test cert_1 intermididate from the keychain. */ CFReleaseSafe(trust); ok_status(SecTrustCreateWithCertificates(cert0, policy, &trust), "create trust with single cert0"); ok_status(SecTrustSetVerifyDate(trust, date), "set date"); // Add cert1 CFDictionaryRef query = CFDictionaryCreateForCFTypes(kCFAllocatorDefault, kSecClass, kSecClassCertificate, kSecValueRef, cert1, NULL); ok_status(SecItemAdd(query, NULL), "add cert1 to keychain"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate trust"); // Cleanup added cert1. ok_status(SecItemDelete(query), "remove cert1 from keychain"); CFReleaseSafe(query); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); is(SecTrustGetCertificateCount(trust), 3, "cert count is 3"); /* Set certs to be the xedge2 leaf. */ CFReleaseSafe(certs); const void *cert_xedge2; isnt(cert_xedge2 = SecCertificateCreateWithBytes(NULL, xedge2_certificate, sizeof(xedge2_certificate)), NULL, "create cert_xedge2"); certs = CFArrayCreate(NULL, &cert_xedge2, 1, NULL); CFReleaseSafe(trust); CFReleaseSafe(policy); CFReleaseSafe(date); bool server = true; policy = SecPolicyCreateSSL(server, CFSTR("xedge2.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ssl server xedge2.apple.com"); /* Jan 1st 2009. */ date = CFDateCreate(NULL, 252288000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); CFReleaseSafe(trust); CFReleaseSafe(policy); server = false; policy = SecPolicyCreateSSL(server, CFSTR("xedge2.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ssl client xedge2.apple.com"); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); CFReleaseSafe(trust); CFReleaseSafe(policy); server = true; policy = SecPolicyCreateIPSec(server, CFSTR("xedge2.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ip server xedge2.apple.com"); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); #if 0 /* Although this shouldn't be a valid ipsec cert, since we no longer check for ekus in the ipsec policy it is. */ is_status(trustResult, kSecTrustResultRecoverableTrustFailure, "trust is kSecTrustResultRecoverableTrustFailure"); #else is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); #endif CFReleaseSafe(trust); CFReleaseSafe(policy); server = true; policy = SecPolicyCreateSSL(server, CFSTR("nowhere.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ssl server nowhere.com"); SecPolicyRef replacementPolicy = SecPolicyCreateSSL(server, CFSTR("xedge2.apple.com")); SecTrustSetPolicies(trust, replacementPolicy); CFReleaseSafe(replacementPolicy); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); CFReleaseSafe(trust); CFReleaseSafe(policy); server = true; policy = SecPolicyCreateSSL(server, CFSTR("nowhere.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ssl server nowhere.com"); SecPolicyRef replacementPolicy2 = SecPolicyCreateSSL(server, CFSTR("xedge2.apple.com")); CFArrayRef replacementPolicies = CFArrayCreate(kCFAllocatorDefault, (CFTypeRef*)&replacementPolicy2, 1, &kCFTypeArrayCallBacks); SecTrustSetPolicies(trust, replacementPolicies); CFReleaseSafe(replacementPolicy2); CFReleaseSafe(replacementPolicies); ok_status(SecTrustSetVerifyDate(trust, date), "set xedge2 trust date to Jan 1st 2009"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate xedge2 trust"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); /* Test self signed ssl cert with cert itself set as anchor. */ CFReleaseSafe(trust); CFReleaseSafe(policy); CFReleaseSafe(certs); CFReleaseSafe(date); const void *garthc2; server = true; isnt(garthc2 = SecCertificateCreateWithBytes(NULL, garthc2_certificate, sizeof(garthc2_certificate)), NULL, "create garthc2"); certs = CFArrayCreate(NULL, &garthc2, 1, NULL); policy = SecPolicyCreateSSL(server, CFSTR("garthc2.apple.com")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ip server garthc2.apple.com"); date = CFDateCreate(NULL, 269568000.0); ok_status(SecTrustSetVerifyDate(trust, date), "set garthc2 trust date to Aug 2009"); ok_status(SecTrustSetAnchorCertificates(trust, certs), "set garthc2 as anchor"); ok_status(SecTrustEvaluate(trust, &trustResult), "evaluate self signed cert with cert as anchor"); is_status(trustResult, kSecTrustResultUnspecified, "trust is kSecTrustResultUnspecified"); CFReleaseSafe(garthc2); CFReleaseSafe(cert_xedge2); CFReleaseSafe(anchors); CFReleaseSafe(trust); CFReleaseSafe(serial); CFReleaseSafe(c0_serial); CFReleaseSafe(policy); CFReleaseSafe(certs); CFReleaseSafe(cert0); CFReleaseSafe(cert1); CFReleaseSafe(date); /* Test prt_forest_fi */ const void *prt_forest_fi; isnt(prt_forest_fi = SecCertificateCreateWithBytes(NULL, prt_forest_fi_certificate, sizeof(prt_forest_fi_certificate)), NULL, "create prt_forest_fi"); isnt(certs = CFArrayCreate(NULL, &prt_forest_fi, 1, NULL), NULL, "failed to create cert array"); policy = SecPolicyCreateSSL(false, CFSTR("owa.prt-forest.fi")); ok_status(SecTrustCreateWithCertificates(certs, policy, &trust), "create trust for ip client owa.prt-forest.fi"); date = CFDateCreate(NULL, 391578321.0); ok_status(SecTrustSetVerifyDate(trust, date), "set owa.prt-forest.fi trust date to May 2013"); SecKeyRef pubkey = SecTrustCopyPublicKey(trust); is(pubkey, NULL, "pubkey returned"); CFReleaseSafe(certs); CFReleaseNull(prt_forest_fi); CFReleaseNull(policy); CFReleaseNull(trust); CFReleaseNull(pubkey); CFReleaseNull(date); }