+++ /dev/null
-/*
- * kcExport.cpp - export keychain items using SecKeychainItemExport
- */
-
-#include <Security/Security.h>
-#include <Security/SecImportExport.h>
-#include <security_cdsa_utils/cuFileIo.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <utilLib/common.h>
-#include <clAppUtils/identPicker.h>
-
-static void usage(char **argv)
-{
- printf("Usage: %s infile [option ...]\n", argv[0]);
- printf("Options:\n");
- printf(" -k keychain Keychain to import into\n");
- printf(" -z passphrase For PKCS12 and wrapped keys only\n");
- printf(" -w Private keys are wrapped\n");
- printf(" -d Display Imported Items\n");
- printf(" -i Interactive: displays items before possible import\n");
- printf(" -v Verbose display\n");
- printf(" -l Loop & Pause for MallocDebug\n");
- printf(" -q Quiet\n");
- printf("Import type/format options:\n");
- printf(" -t <type> type = pub|priv|session|cert|agg\n");
- printf(" -f <format> format = openssl|openssh1|openssh2|bsafe|\n"
- " raw|pkcs7|pkcs8|pkcs12|netscape|pemseq\n");
- printf("Private key options:\n");
- printf(" -a appPath Add appPath to list of trusted apps in private key's ACL\n");
- printf(" -e Allow private keys to be extractable in the clear\n");
- printf(" -n Private keys have *NO* ACL\n");
- printf(" -s Private keys can sign (only)\n");
- printf("Secure passphrase options:\n");
- printf(" -Z Get secure passphrase\n");
- printf(" -L title\n");
- printf(" -p prompt\n");
- printf("Verification options:\n");
- printf(" -C numCerts Verify number of certificates\n");
- printf(" -K numKeys Verify number of keys\n");
- printf(" -I numIdents Verify number of identities\n");
- printf(" -F rtnFormat Returned format = "
- "openssl|openssh1|openssh2|bsafe|raw|pkcs7|pkcs12|netscape|pemseq\n");
- printf(" -T <type> Returned type = pub|priv|session|cert|agg\n");
- printf(" -m Set ImportOnlyOneKey bit\n");
- printf(" -M Set ImportOnlyOneKey bit and expect errSecMultiplePrivKeys\n");
- exit(1);
-}
-
-const char *secExtFormatStr(
- SecExternalFormat format)
-{
- switch(format) {
- case kSecFormatUnknown: return "kSecFormatUnknown";
- case kSecFormatOpenSSL: return "kSecFormatOpenSSL";
- case kSecFormatSSH: return "kSecFormatSSH";
- case kSecFormatBSAFE: return "kSecFormatBSAFE";
- case kSecFormatRawKey: return "kSecFormatRawKey";
- case kSecFormatWrappedPKCS8: return "kSecFormatWrappedPKCS8";
- case kSecFormatWrappedOpenSSL: return "kSecFormatWrappedOpenSSL";
- case kSecFormatWrappedSSH: return "kSecFormatWrappedSSH";
- case kSecFormatWrappedLSH: return "kSecFormatWrappedLSH";
- case kSecFormatX509Cert: return "kSecFormatX509Cert";
- case kSecFormatPEMSequence: return "kSecFormatPEMSequence";
- case kSecFormatPKCS7: return "kSecFormatPKCS7";
- case kSecFormatPKCS12: return "kSecFormatPKCS12";
- case kSecFormatNetscapeCertSequence: return "kSecFormatNetscapeCertSequence";
- case kSecFormatSSHv2: return "kSecFormatSSHv2";
- default: return "UNKNOWN FORMAT ENUM";
- }
-}
-
-const char *secExtItemTypeStr(
- SecExternalItemType itemType)
-{
- switch(itemType) {
- case kSecItemTypeUnknown: return "kSecItemTypeUnknown";
- case kSecItemTypePrivateKey: return "kSecItemTypePrivateKey";
- case kSecItemTypePublicKey: return "kSecItemTypePublicKey";
- case kSecItemTypeSessionKey: return "kSecItemTypeSessionKey";
- case kSecItemTypeCertificate: return "kSecItemTypeCertificate";
- case kSecItemTypeAggregate: return "kSecItemTypeAggregate";
- default: return "UNKNOWN ITEM TYPE ENUM";
- }
-}
-
-static OSStatus processItem(
- SecKeychainRef keychain,
- SecKeychainItemRef item,
- int *numCerts, // IN/OUT
- int *numKeys,
- int *numIds,
- bool interactive, // unimplemented
- bool verbose)
-{
- char *kcName = NULL;
- CFTypeID itemType = CFGetTypeID(item);
- if(itemType == SecIdentityGetTypeID()) {
- (*numIds)++;
- if(verbose) {
- /* identities don't have keychains, only their components do */
- SecCertificateRef certRef = NULL;
- OSStatus ortn;
- ortn = SecIdentityCopyCertificate((SecIdentityRef)item, &certRef);
- if(ortn) {
- cssmPerror("SecIdentityCopyCertificate", ortn);
- return ortn;
- }
- kcName = kcItemKcFileName((SecKeychainItemRef)certRef);
- printf(" identity : cert keychain name %s\n", kcName ? kcName : "<none>");
- CFRelease(certRef);
-
- SecKeyRef keyRef = NULL;
- ortn = SecIdentityCopyPrivateKey((SecIdentityRef)item, &keyRef);
- if(ortn) {
- cssmPerror("SecIdentityCopyPrivateKey", ortn);
- return ortn;
- }
- free(kcName);
- kcName = kcItemKcFileName((SecKeychainItemRef)keyRef);
- printf(" identity : key keychain name %s\n", kcName ? kcName : "<none>");
- CFRelease(keyRef);
- }
- }
- else if(itemType == SecCertificateGetTypeID()) {
- (*numCerts)++;
- if(verbose) {
- kcName = kcItemKcFileName(item);
- printf(" cert : keychain name %s\n", kcName ? kcName : "<none>");
- }
- }
- else if(itemType == SecKeyGetTypeID()) {
- (*numKeys)++;
- if(verbose) {
- kcName = kcItemKcFileName(item);
- printf(" key : keychain name %s\n", kcName ? kcName : "<none>");
- }
- }
- /* FIX display attr info, at least names, eventually */
- else {
- printf("***Unknown type returned from SecKeychainItemImport()\n");
- return errSecUnknownFormat;
- }
- if(kcName) {
- free(kcName);
- }
- return noErr;
-}
-
-static OSStatus processItems(
- SecKeychainRef keychain,
- CFArrayRef outArray,
- int expectNumCerts, // -1 means don't check
- int expectNumKeys,
- int expectNumIds,
- bool interactive,
- bool displayItems,
- bool verbose)
-{
- int numCerts = 0;
- int numKeys = 0;
- int numIds = 0;
- OSStatus ortn;
-
- CFIndex numItems = CFArrayGetCount(outArray);
- for(CFIndex dex=0; dex<numItems; dex++) {
- ortn = processItem(keychain,
- (SecKeychainItemRef)CFArrayGetValueAtIndex(outArray, dex),
- &numCerts, &numKeys, &numIds, interactive, verbose);
- if(ortn) {
- break;
- }
- }
- if(ortn) {
- return ortn;
- }
-
- if(displayItems) {
- printf("Certs found : %d\n", numCerts);
- printf("Keys found : %d\n", numKeys);
- printf("Idents found : %d\n", numIds);
- }
- if(expectNumCerts >= 0) {
- if(expectNumCerts != numCerts) {
- printf("***Expected %d certs, got %d\n",
- expectNumCerts, numCerts);
- ortn = -1;
- }
- }
- if(expectNumKeys >= 0) {
- if(expectNumKeys != numKeys) {
- printf("***Expected %d keys, got %d\n",
- expectNumKeys, numKeys);
- ortn = -1;
- }
- }
- if(expectNumIds >= 0) {
- if(expectNumIds != numIds) {
- printf("***Expected %d certs, got %d\n",
- expectNumIds, numIds);
- ortn = -1;
- }
- }
- return ortn;
-}
-
-/*
- * Parse cmd-line format specifier into an SecExternalFormat.
- * Returns true if it works.
- */
-static bool formatFromString(
- const char *formStr,
- SecExternalFormat *externFormat)
-{
- if(!strcmp("openssl", formStr)) {
- *externFormat = kSecFormatOpenSSL;
- }
- else if(!strcmp("openssh1", formStr)) {
- *externFormat = kSecFormatSSH;
- }
- else if(!strcmp("openssh2", formStr)) {
- *externFormat = kSecFormatSSHv2;
- }
- else if(!strcmp("bsafe", formStr)) {
- *externFormat = kSecFormatBSAFE;
- }
- else if(!strcmp("raw", formStr)) {
- *externFormat = kSecFormatRawKey;
- }
- else if(!strcmp("pkcs7", formStr)) {
- *externFormat = kSecFormatPKCS7;
- }
- else if(!strcmp("pkcs8", formStr)) {
- *externFormat = kSecFormatWrappedPKCS8;
- }
- else if(!strcmp("pkcs12", formStr)) {
- *externFormat = kSecFormatPKCS12;
- }
- else if(!strcmp("netscape", formStr)) {
- *externFormat = kSecFormatNetscapeCertSequence;
- }
- else if(!strcmp("pemseq", formStr)) {
- *externFormat = kSecFormatPEMSequence;
- }
- else {
- return false;
- }
- return true;
-}
-
- /*
- * Parse cmd-line type specifier into an SecExternalItemType.
- * Returns true if it works.
- */
-static bool itemTypeFromString(
- const char *typeStr,
- SecExternalItemType *itemType)
-{
- if(!strcmp("pub", typeStr)) {
- *itemType = kSecItemTypePublicKey;
- }
- else if(!strcmp("priv", typeStr)) {
- *itemType = kSecItemTypePrivateKey;
- }
- else if(!strcmp("session", typeStr)) {
- *itemType = kSecItemTypeSessionKey;
- }
- else if(!strcmp("cert", typeStr)) {
- *itemType = kSecItemTypeCertificate;
- }
- else if(!strcmp("agg", typeStr)) {
- *itemType = kSecItemTypeAggregate;
- }
- else {
- return false;
- }
- return true;
-}
-
-int main(int argc, char **argv)
-{
- if(argc < 2) {
- usage(argv);
- }
-
- const char *inFileName = argv[1];
-
- extern int optind;
- extern char *optarg;
- int arg;
- optind = 2;
- int ourRtn = 0;
- SecAccessRef accessRef = NULL;
- OSStatus ortn;
-
- /* optional args */
- const char *keychainName = NULL;
- CFStringRef passphrase = NULL;
- bool interactive = false;
- bool securePassphrase = false;
- SecExternalFormat externFormat = kSecFormatUnknown;
- SecExternalItemType itemType = kSecItemTypeUnknown;
- bool doWrap = false;
- bool allowClearExtract = false;
- int expectNumCerts = -1; // >=0 means verify per user spec
- int expectNumKeys = -1;
- int expectNumIds = -1;
- bool processOutput = false;
- bool displayItems = false;
- SecExternalFormat expectFormat = kSecFormatUnknown; // otherwise verify
- SecExternalItemType expectItemType = kSecItemTypeUnknown; // ditto
- bool quiet = false;
- bool noACL = false;
- char *alertTitle = NULL;
- char *alertPrompt = NULL;
- bool setAllowOnlyOne = false;
- bool expectMultiKeysError = false;
- CFMutableArrayRef trustedAppList = NULL;
- bool loopPause = false;
- bool signOnly = false;
- bool verbose = false;
-
- while ((arg = getopt(argc, argv, "k:iZz:wet:f:C:K:I:F:T:qnL:p:mMa:dlsv")) != -1) {
- switch (arg) {
- case 'k':
- keychainName = optarg;
- break;
- case 'i':
- interactive = true;
- processOutput = true;
- break;
- case 'Z':
- securePassphrase = true;
- break;
- case 'z':
- passphrase = CFStringCreateWithCString(NULL, optarg,
- kCFStringEncodingASCII);
- break;
- case 'w':
- doWrap = true;
- break;
- case 'e':
- allowClearExtract = true;
- break;
- case 't':
- if(!itemTypeFromString(optarg, &itemType)) {
- usage(argv);
- }
- break;
- case 'T':
- if(!itemTypeFromString(optarg, &expectItemType)) {
- usage(argv);
- }
- break;
- case 'f':
- if(!formatFromString(optarg, &externFormat)) {
- usage(argv);
- }
- break;
- case 'F':
- if(!formatFromString(optarg, &expectFormat)) {
- usage(argv);
- }
- break;
- case 'C':
- expectNumCerts = atoi(optarg);
- processOutput = true;
- break;
- case 'K':
- expectNumKeys = atoi(optarg);
- processOutput = true;
- break;
- case 'I':
- expectNumIds = atoi(optarg);
- processOutput = true;
- break;
- case 'd':
- displayItems = true;
- processOutput = true;
- break;
- case 'q':
- quiet = true;
- break;
- case 'n':
- noACL = true;
- break;
- case 'L':
- alertTitle = optarg;
- break;
- case 'p':
- alertPrompt = optarg;
- break;
- case 'm':
- setAllowOnlyOne = true;
- break;
- case 'M':
- setAllowOnlyOne = true;
- expectMultiKeysError = true;
- break;
- case 'a':
- {
- if(trustedAppList == NULL) {
- trustedAppList = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
- }
- SecTrustedApplicationRef appRef;
- ortn = SecTrustedApplicationCreateFromPath(optarg, &appRef);
- if(ortn) {
- cssmPerror("SecTrustedApplicationCreateFromPath", ortn);
- exit(1);
- }
- CFArrayAppendValue(trustedAppList, appRef);
- break;
- }
- case 's':
- signOnly = true;
- break;
- case 'l':
- loopPause = true;
- break;
- case 'v':
- verbose = true;
- break;
- default:
- case '?':
- usage(argv);
- }
- }
- if(optind != argc) {
- /* getopt does not return '?' */
- usage(argv);
- }
- if(doWrap) {
- switch(externFormat) {
- case kSecFormatOpenSSL:
- case kSecFormatUnknown: // i.e., use default
- externFormat = kSecFormatWrappedOpenSSL;
- break;
- case kSecFormatSSH:
- externFormat = kSecFormatWrappedSSH;
- break;
- case kSecFormatSSHv2:
- /* there is no wrappedSSHv2 */
- externFormat = kSecFormatWrappedOpenSSL;
- break;
- case kSecFormatWrappedPKCS8:
- /* proceed */
- break;
- default:
- printf("Don't know how to wrap in specified format/type.\n");
- exit(1);
- }
- }
-
- CFArrayRef outArray = NULL;
- CFArrayRef *outArrayP = NULL;
- if(processOutput) {
- outArrayP = &outArray;
- }
-
- SecKeychainRef kcRef = NULL;
- if(keychainName) {
- OSStatus ortn = SecKeychainOpen(keychainName, &kcRef);
- if(ortn) {
- cssmPerror("SecKeychainOpen", ortn);
- exit(1);
- }
- /* why is this failing later */
- CSSM_DL_DB_HANDLE dlDbHandle;
- ortn = SecKeychainGetDLDBHandle(kcRef, &dlDbHandle);
- if(ortn) {
- cssmPerror("SecKeychainGetDLDBHandle", ortn);
- exit(1);
- }
-
- }
-
- unsigned char *inFile = NULL;
- unsigned inFileLen = 0;
- if(readFile(inFileName, &inFile, &inFileLen)) {
- printf("***Error reading input file %s. Aborting.\n", inFileName);
- exit(1);
- }
- CFDataRef inFileRef = CFDataCreate(NULL, inFile, inFileLen);
- CFStringRef fileNameStr = CFStringCreateWithCString(NULL, inFileName,
- kCFStringEncodingASCII);
-
-loopTop:
- SecKeyImportExportParameters keyParams;
- SecKeyImportExportParameters *keyParamPtr = NULL;
-
- if(passphrase || securePassphrase || allowClearExtract || noACL ||
- setAllowOnlyOne || trustedAppList || signOnly) {
- keyParamPtr = &keyParams;
- memset(&keyParams, 0, sizeof(keyParams));
- if(securePassphrase) {
- /* give this precedence */
- keyParams.flags |= kSecKeySecurePassphrase;
- if(alertTitle) {
- keyParams.alertTitle =
- CFStringCreateWithCString(NULL, alertTitle, kCFStringEncodingASCII);
- }
- if(alertPrompt) {
- keyParams.alertPrompt =
- CFStringCreateWithCString(NULL, alertPrompt, kCFStringEncodingASCII);
- }
- }
- else if(passphrase) {
- keyParams.passphrase = passphrase;
- }
- if(noACL) {
- keyParams.flags |= kSecKeyNoAccessControl;
- }
- if(setAllowOnlyOne) {
- keyParams.flags |= kSecKeyImportOnlyOne;
- }
- keyParams.keyAttributes = ( CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE);
- if(!allowClearExtract) {
- keyParams.keyAttributes |= CSSM_KEYATTR_SENSITIVE;
- }
- if(kcRef) {
- keyParams.keyAttributes |= CSSM_KEYATTR_PERMANENT;
- }
- if(signOnly) {
- keyParams.keyUsage = CSSM_KEYUSE_SIGN;
- }
- else {
- keyParams.keyUsage = CSSM_KEYUSE_ANY;
- }
- if(trustedAppList) {
- ortn = SecAccessCreate(CFSTR("Imported Private Key"), trustedAppList, &accessRef);
- if(ortn) {
- cssmPerror("SecAccessCreate", ortn);
- exit(1);
- }
- keyParams.accessRef = accessRef;
- }
- /* TBD other stuff - usage? Other? */
- }
-
- /* GO */
- ortn = SecKeychainItemImport(inFileRef,
- fileNameStr,
- &externFormat,
- &itemType,
- 0, // flags
- keyParamPtr,
- kcRef,
- outArrayP);
- ourRtn = 0;
- if(ortn) {
- if(expectMultiKeysError && (ortn == errSecMultiplePrivKeys)) {
- if(!quiet) {
- printf("...errSecMultiplePrivKeys error seen as expected\n");
- }
- }
- else {
- cssmPerror("SecKeychainItemImport", ortn);
- ourRtn = -1;
- }
- }
- else if(expectMultiKeysError) {
- printf("***errSecMultiplePrivKeys expected but no error seen\n");
- ourRtn = -1;
- }
- if(ortn == noErr) {
- if(!quiet) {
- printf("...import successful. Returned format %s\n",
- secExtFormatStr(externFormat));
- }
- if(expectFormat != kSecFormatUnknown) {
- if(expectFormat != externFormat) {
- printf("***Expected format %s, got %s\n",
- secExtFormatStr(expectFormat),
- secExtFormatStr(externFormat));
- ourRtn = -1;
- }
- }
- if(expectItemType != kSecItemTypeUnknown) {
- if(expectItemType != itemType) {
- printf("***Expected itemType %s, got %s\n",
- secExtItemTypeStr(expectItemType),
- secExtItemTypeStr(itemType));
- ourRtn = -1;
- }
- }
- if(processOutput) {
- ourRtn |= processItems(kcRef, outArray, expectNumCerts,
- expectNumKeys, expectNumIds, interactive, displayItems, verbose);
- }
- }
- if(loopPause) {
- fflush(stdin);
- printf("Pausing for MallocDebug; CR to continue: ");
- getchar();
- goto loopTop;
- }
- return ourRtn;
-}