int kc_27_key_non_extractable(int argc, char *const *argv) { plan_tests(24); initializeKeychainTests(__FUNCTION__); SecKeychainRef kc = getPopulatedTestKeychain(); // test case 1: extractable startTest("Extract extractable key"); testExtractable(kc, TRUE, TRUE); // test case 2: non-extractable startTest("Extract non-extractable key"); testExtractable(kc, FALSE, TRUE); // test case 3: extractable (when not explicitly specified) startTest("Extract implicitly extractable key"); testExtractable(kc, TRUE, FALSE); ok_status(SecKeychainDelete(kc), "%s: SecKeychainDelete", testName); CFRelease(kc); deleteTestFiles(); return 0; }
static VALUE rb_keychain_delete(VALUE self){ SecKeychainRef keychain=NULL; Data_Get_Struct(self, struct OpaqueSecKeychainRef, keychain); OSStatus result = SecKeychainDelete(keychain); CheckOSStatusOrRaise(result); return self; }
int main(int argc, char **argv) { bool verbose = false; int arg; while ((arg = getopt(argc, argv, "vh")) != -1) { switch (arg) { case 'v': verbose = true; break; case 'h': usage(argv); } } if(optind != argc) { usage(argv); } printNoDialog(); /* initial setup */ verboseDisp(verbose, "deleting keychain"); unlink(KEYCHAIN_NAME); verboseDisp(verbose, "creating keychain"); SecKeychainRef kcRef = NULL; OSStatus ortn = SecKeychainCreate(KEYCHAIN_NAME, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, false, NULL, &kcRef); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } /* * 1. Generate key pair with cleartext public key. * Ensure we can use the public key when keychain is locked with no * user interaction. */ /* generate key pair, cleartext public key */ verboseDisp(verbose, "creating key pair, cleartext public key"); SecKeyRef pubKeyRef = NULL; SecKeyRef privKeyRef = NULL; if(genKeyPair(false, kcRef, &pubKeyRef, &privKeyRef)) { exit(1); } /* Use generated cleartext public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); CFDataRef exportData = NULL; ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } CFRelease(exportData); verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } /* reset */ verboseDisp(verbose, "deleting keys"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); CFRelease(privKeyRef); /* * 2. Generate key pair with encrypted public key. * Ensure that user interaction is required when we use the public key * when keychain is locked. */ verboseDisp(verbose, "programmatically unlocking keychain"); ortn = SecKeychainUnlock(kcRef, strlen(KEYCHAIN_PWD), KEYCHAIN_PWD, TRUE); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } /* generate key pair, encrypted public key */ verboseDisp(verbose, "creating key pair, encrypted public key"); if(genKeyPair(true, kcRef, &pubKeyRef, &privKeyRef)) { exit(1); } /* Use generated encrypted public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); printExpectDialog(); ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainCreate", ortn); exit(1); } /* we'll use that exported blob later to test import */ if(!didGetDialog()) { exit(1); } verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); printExpectDialog(); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } if(!didGetDialog()) { exit(1); } /* reset */ printNoDialog(); verboseDisp(verbose, "locking keychain"); SecKeychainLock(kcRef); verboseDisp(verbose, "deleting keys"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } ortn = SecKeychainItemDelete((SecKeychainItemRef)privKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); CFRelease(privKeyRef); /* * 3. Import public key, storing in cleartext. Ensure that the import * doesn't require unlock, and ensure we can use the public key * when keychain is locked with no user interaction. */ printNoDialog(); verboseDisp(verbose, "locking keychain"); SecKeychainLock(kcRef); /* import public key - default is in the clear */ verboseDisp(verbose, "importing public key, store in the clear (default)"); CFArrayRef outArray = NULL; SecExternalFormat format = kSecFormatOpenSSL; SecExternalItemType type = kSecItemTypePublicKey; ortn = SecKeychainItemImport(exportData, NULL, &format, &type, 0, NULL, kcRef, &outArray); if(ortn) { cssmPerror("SecKeychainItemImport", ortn); exit(1); } CFRelease(exportData); if(CFArrayGetCount(outArray) != 1) { printf("***Unexpected outArray size (%ld) after import\n", (long)CFArrayGetCount(outArray)); exit(1); } pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { printf("***Unexpected item type after import\n"); exit(1); } /* Use imported cleartext public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); exportData = NULL; ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainItemExport", ortn); exit(1); } /* we'll use exportData again */ verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } /* reset */ verboseDisp(verbose, "deleting key"); ortn = SecKeychainItemDelete((SecKeychainItemRef)pubKeyRef); if(ortn) { cssmPerror("SecKeychainItemDelete", ortn); exit(1); } CFRelease(pubKeyRef); /* * Import public key, storing in encrypted form. * Ensure that user interaction is required when we use the public key * when keychain is locked. */ /* import public key, encrypted in the keychain */ SecKeyImportExportParameters impExpParams; memset(&impExpParams, 0, sizeof(impExpParams)); impExpParams.version = SEC_KEY_IMPORT_EXPORT_PARAMS_VERSION; impExpParams.keyAttributes = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT | CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT; verboseDisp(verbose, "importing public key, store encrypted"); printExpectDialog(); outArray = NULL; format = kSecFormatOpenSSL; type = kSecItemTypePublicKey; ortn = SecKeychainItemImport(exportData, NULL, &format, &type, 0, &impExpParams, kcRef, &outArray); if(ortn) { cssmPerror("SecKeychainItemImport", ortn); exit(1); } if(!didGetDialog()) { exit(1); } CFRelease(exportData); if(CFArrayGetCount(outArray) != 1) { printf("***Unexpected outArray size (%ld) after import\n", (long)CFArrayGetCount(outArray)); exit(1); } pubKeyRef = (SecKeyRef)CFArrayGetValueAtIndex(outArray, 0); if(CFGetTypeID(pubKeyRef) != SecKeyGetTypeID()) { printf("***Unexpected item type after import\n"); exit(1); } /* Use imported encrypted public key with locked keychain */ verboseDisp(verbose, "locking keychain, exporting public key"); SecKeychainLock(kcRef); printExpectDialog(); ortn = SecKeychainItemExport(pubKeyRef, kSecFormatOpenSSL, 0, NULL, &exportData); if(ortn) { cssmPerror("SecKeychainItemExport", ortn); exit(1); } if(!didGetDialog()) { exit(1); } CFRelease(exportData); verboseDisp(verbose, "locking keychain, encrypting with public key"); SecKeychainLock(kcRef); printExpectDialog(); if(pubKeyEncrypt(pubKeyRef)) { exit(1); } if(!didGetDialog()) { exit(1); } SecKeychainDelete(kcRef); printf("...test succeeded.\n"); return 0; }
void tests(int dont_skip) { SecKeychainRef source, dest; ok_status(SecKeychainCreate("source", 4, "test", FALSE, NULL, &source), "create source keychain"); ok_status(SecKeychainCreate("dest", 4, "test", FALSE, NULL, &dest), "create dest keychain"); SecKeychainItemRef original = NULL; ok_status(SecKeychainAddInternetPassword(source, 19, "members.spamcop.net", 0, NULL, 5, "smith", 0, NULL, 80, kSecProtocolTypeHTTP, kSecAuthenticationTypeDefault, 4, "test", &original), "add internet password"); SecKeychainAttribute origAttrs[] = { { kSecCreationDateItemAttr }, { kSecModDateItemAttr } }; SecKeychainAttributeList origAttrList = { sizeof(origAttrs) / sizeof(*origAttrs), origAttrs }; ok_status(SecKeychainItemCopyContent(original, NULL, &origAttrList, NULL, NULL), "SecKeychainItemCopyContent"); /* Must sleep 1 second to trigger mod date bug. */ sleep(1); SecKeychainItemRef copy; ok_status(SecKeychainItemCreateCopy(original, dest, NULL, ©), "copy item"); SecKeychainAttribute copyAttrs[] = { { kSecCreationDateItemAttr }, { kSecModDateItemAttr } }; SecKeychainAttributeList copyAttrList = { sizeof(copyAttrs) / sizeof(*copyAttrs), copyAttrs }; ok_status(SecKeychainItemCopyContent(copy, NULL, ©AttrList, NULL, NULL), "SecKeychainItemCopyContent"); is(origAttrs[0].length, 16, "creation date length 16"); is(origAttrs[1].length, 16, "mod date length 16"); is(origAttrs[0].length, copyAttrs[0].length, "creation date length same"); is(origAttrs[1].length, copyAttrs[1].length, "mod date length same"); TODO: { todo("<rdar://problem/3731664> Moving/copying a keychain item " "between keychains erroneously updates dates"); diag("original creation: %.*s copy creation: %.*s", (int)origAttrs[0].length, (const char *)origAttrs[0].data, (int)copyAttrs[0].length, (const char *)copyAttrs[0].data); ok(!memcmp(origAttrs[0].data, copyAttrs[0].data, origAttrs[0].length), "creation date same"); diag("original mod: %.*s copy mod: %.*s", (int)origAttrs[1].length, (const char *)origAttrs[1].data, (int)copyAttrs[1].length, (const char *)copyAttrs[1].data); ok(!memcmp(origAttrs[1].data, copyAttrs[1].data, origAttrs[1].length), "mod date same"); } ok_status(SecKeychainItemFreeContent(&origAttrList, NULL), "SecKeychainItemCopyContent"); ok_status(SecKeychainItemFreeContent(©AttrList, NULL), "SecKeychainItemCopyContent"); is(CFGetRetainCount(original), 1, "original retaincount is 1"); CFRelease(original); is(CFGetRetainCount(copy), 1, "copy retaincount is 1"); CFRelease(copy); is(CFGetRetainCount(source), 1, "source retaincount is 1"); ok_status(SecKeychainDelete(source), "delete keychain source"); CFRelease(source); ok_status(SecKeychainDelete(dest), "delete keychain dest"); is(CFGetRetainCount(dest), 1, "dest retaincount is 1"); CFRelease(dest); ok(tests_end(1), "cleanup"); }
static void tests(void) { char *home = getenv("HOME"); char kcname1[256], kcname2[256]; SecKeychainStatus status1, status2; if (!home || strlen(home) > 200) plan_skip_all("home too big"); sprintf(kcname1, "%s/kctests/kc1/kc1", home); SecKeychainRef kc1 = NULL, kc2 = NULL; kc1 = createNewKeychainAt(kcname1, "test"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); ok_status(SecKeychainLock(kc1), "SecKeychainLock kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecReadPermStatus|kSecWritePermStatus, "status (locked) readable writable"); } /* Make keychain non writable. */ char kcdir1[256]; sprintf(kcdir1, "%s/kctests/kc1", home); ok_unix(chmod(kcdir1, 0555), "chmod kcdir1 0555"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); is(status1, kSecReadPermStatus, "status (locked) readable"); ok_status(SecKeychainUnlock(kc1, 4, "test", TRUE), "SecKeychainLock kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus, "status unlocked readable"); } /* Reopen the keychain. */ CFRelease(kc1); ok_status(SecKeychainOpen(kcname1, &kc1), "SecKeychainOpen kc1"); ok_status(SecKeychainGetStatus(kc1, &status1), "get kc1 status"); TODO: { todo("<rdar://problem/2668794> KeychainImpl::status() returns " "incorrect status (always writable?)"); is(status1, kSecUnlockStateStatus|kSecReadPermStatus, "status unlocked readable"); } sprintf(kcname2, "%s/kctests/kc2/kc2", home); kc2 = createNewKeychainAt(kcname2, "test"); ok_unix(chmod(kcname2, 0444), "chmod kc2 0444"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); /* Reopen the keychain. */ CFRelease(kc2); ok_status(SecKeychainOpen(kcname2, &kc2), "SecKeychainOpen kc2"); ok_status(SecKeychainGetStatus(kc2, &status2), "get kc2 status"); is(status2, kSecUnlockStateStatus|kSecReadPermStatus|kSecWritePermStatus, "status unlocked readable writable"); /* Restore dir to writable so cleanup code will work ok. */ ok_unix(chmod(kcdir1, 0755), "chmod kcdir1 0755"); ok_status(SecKeychainDelete(kc1), "%s: SecKeychainDelete", testName); CFRelease(kc1); ok_status(SecKeychainDelete(kc2), "%s: SecKeychainDelete", testName); CFRelease(kc2); bool testWithFreshlyCreatedKeychain = true; SecKeychainRef keychain = createNewKeychain("test", "test"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); do { SecKeychainStatus keychainStatus = 0; is_status(SecKeychainUnlock(keychain, 0, NULL, true), -25293, "SecKeychainUnlock with NULL password (incorrect)"); ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); is( (keychainStatus & kSecUnlockStateStatus), 0, "Check it's not unlocked"); keychainStatus = 0; ok_status(SecKeychainUnlock(keychain, strlen("test"), "test", true), "SecKeychainUnlock with correct password"); ok_status(SecKeychainGetStatus(keychain, &keychainStatus), "SecKeychainGetStatus"); is( (keychainStatus & kSecUnlockStateStatus), kSecUnlockStateStatus, "Check it's unlocked"); ok_status(SecKeychainLock(keychain), "SecKeychainLock"); if (testWithFreshlyCreatedKeychain) { CFRelease(keychain); testWithFreshlyCreatedKeychain = false; ok_status(SecKeychainOpen("test", &keychain), "SecKeychainOpen"); } else { testWithFreshlyCreatedKeychain = true; ok_status(SecKeychainDelete(keychain), "%s: SecKeychainDelete", testName); CFReleaseNull(keychain); } } while(!testWithFreshlyCreatedKeychain); }