+++ /dev/null
-/*
- * p12ImportExport.cpp - high-level libnsspkcs12 exerciser
- */
-
-#include <security_pkcs12/SecPkcs12.h>
-#include <security_cdsa_utils/cuFileIo.h>
-#include <Security/Security.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <security_cdsa_utilities/KeySchema.h>
-#include <security_cdsa_utils/cuCdsaUtils.h>
-#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
-#include "p12GetPassKey.h"
-
-static void printOsError(
- const char *op,
- OSStatus ortn)
-{
- char *errStr = NULL;
- switch(ortn) {
- case CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA:
- errStr = "CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA"; break;
- case CSSMERR_DL_DATASTORE_DOESNOT_EXIST:
- errStr = "CSSMERR_DL_DATASTORE_DOESNOT_EXIST"; break;
- case errSecDuplicateItem:
- errStr = "errSecDuplicateItem"; break;
- case errSecNotAvailable:
- errStr = "errSecNotAvailable"; break;
- case errSecAuthFailed:
- errStr = "errSecAuthFailed"; break;
- case errSecItemNotFound:
- errStr = "errSecItemNotFound"; break;
- case errSecInvalidItemRef:
- errStr = "errSecInvalidItemRef"; break;
- default:
- break;
- }
- if(errStr) {
- printf("%s returned %s\n", op, errStr);
- }
- else {
- printf("%s returned %d\n", op, (int)ortn);
- }
-}
-
-/*
- * For now we assume "import everything"
- */
-int p12Import(
- const char *pfxFile,
- const char *kcName,
- CFStringRef pwd, // explicit passphrase, mutually exclusive with...
- bool usePassKey, // use SECURE_PASSPHRASE key
- const char *kcPwd) // optional
-{
- OSStatus ortn;
- unsigned char *pfx;
- unsigned pfxLen;
- CSSM_KEY passKey;
-
- /* get the PFX */
- if(readFile(pfxFile, &pfx, &pfxLen)) {
- printf("***Error reading pfx from %s. Aborting.\n", pfxFile);
- return 1;
- }
- CFDataRef cfd = CFDataCreate(NULL, pfx, pfxLen);
-
- /* import to keychain specified by kcName */
- SecKeychainRef kcRef = NULL;
- ortn = SecKeychainOpen(kcName, &kcRef);
- if(ortn) {
- printOsError("SecKeychainOpen", ortn);
- return ortn;
- }
-
- if(kcPwd) {
- ortn = SecKeychainUnlock(kcRef, strlen(kcPwd), (void *)kcPwd, true);
- if(ortn) {
- printOsError("SecKeychainUnlock", ortn);
- }
- }
-
- /* set up a pkcs12 coder for import */
- SecPkcs12CoderRef coder;
- ortn = SecPkcs12CoderCreate(&coder);
- if(ortn) {
- printOsError("SecPkcs12CoderCreate", ortn);
- return ortn;
- }
-
- ortn = SecPkcs12SetKeychain(coder, kcRef);
- if(ortn) {
- printOsError("SecPkcs12SetKeychain", ortn);
- return ortn;
- }
-
- if(usePassKey) {
- CSSM_CSP_HANDLE cspHand;
- ortn = SecKeychainGetCSPHandle(kcRef, &cspHand);
- if(ortn) {
- printOsError("SecPkcs12SetKeychain", ortn);
- return ortn;
- }
- ortn = p12GetPassKey(cspHand, GPK_Decode, false, &passKey);
- if(ortn) {
- return ortn;
- }
- ortn = SecPkcs12SetMACPassKey(coder, &passKey);
- if(ortn) {
- printOsError("SecPkcs12SetMACPassKey", ortn);
- return ortn;
- }
- }
- else {
- ortn = SecPkcs12SetMACPassphrase(coder, pwd);
- if(ortn) {
- printOsError("SecPkcs12SetMACPassphrase", ortn);
- return ortn;
- }
- }
-
- /*
- * For now we assume "import everything"
- */
- ortn = SecPkcs12SetImportToKeychain(coder,
- kSecImportCertificates |
- kSecImportCRLs |
- kSecImportKeys);
- if(ortn) {
- printOsError("SecPkcs12SetImportFromKeychain", ortn);
- return ortn;
- }
-
- /* Go! */
- ortn = SecPkcs12Decode(coder, cfd);
- if(ortn) {
- printOsError("SecPkcs12Decode", ortn);
- return ortn;
- }
-
- /* report how many of each item got imported */
- CFIndex num;
- SecPkcs12CertificateCount(coder, &num);
- printf("...%d certs imported\n", (int)num);
- SecPkcs12CrlCount(coder, &num);
- printf("...%d CRLs imported\n", (int)num);
- SecPkcs12PrivateKeyCount(coder, &num);
- printf("...%d private keys imported\n", (int)num);
-
- SecPkcs12CoderRelease(coder);
- CFRelease(cfd);
- free(pfx); // mallocd by readFile()
- return 0;
-}
-
-/*
- * Use the kludge from hell to get the name-as-int form of a specified
- * "known" name-as-string for the Key Schema.
- */
-OSStatus attrNameToInt(
- const char *name,
- uint32 *attrInt)
-{
- const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *attrList =
- KeySchema::KeySchemaAttributeList;
- unsigned numAttrs = KeySchema::KeySchemaAttributeCount;
- for(unsigned dex=0; dex<numAttrs; dex++) {
- const CSSM_DB_SCHEMA_ATTRIBUTE_INFO *info = &attrList[dex];
- if(!strcmp(name, info->AttributeName)) {
- *attrInt = info->AttributeId;
- return noErr;
- }
- }
- return paramErr;
-}
-
-static int p12AddExportedItem(
- SecKeychainItemRef item,
- CFMutableArrayRef itemArray,
- bool noPrompt)
-{
- if(noPrompt) {
- CFArrayAppendValue(itemArray, item);
- return 1;
- }
-
- CFTypeID itemId = CFGetTypeID(item);
- OSStatus ortn;
-
- /* the printable name attr */
- UInt32 nameAttr = 0;
- char *itemClass = "";
- if(itemId == SecCertificateGetTypeID()) {
- itemClass = "Certificate";
- nameAttr = kSecLabelItemAttr;
- }
- else if(itemId == SecKeyGetTypeID()) {
- itemClass = "Private Key";
- ortn = attrNameToInt("PrintName", &nameAttr);
- if(ortn) {
- /* out of sync with Sec layer? With KeySchema? */
- printf("warning: attrNameToInt failure\n");
- return 0;
- }
- }
- else {
- /* we don't know how to deal with this */
- printf("p12AddExportedItem: internal screwup\n");
- return 0;
- }
-
- /* get the printable name attr */
- SecKeychainAttributeInfo attrInfo;
- attrInfo.count = 1;
- attrInfo.tag = &nameAttr;
- attrInfo.format = NULL; // ???
-
- /* FIXME header says this is an IN/OUT param, but it's not */
- SecKeychainAttributeList *attrList = NULL;
-
- ortn = SecKeychainItemCopyAttributesAndData(
- item,
- &attrInfo,
- NULL, // itemClass
- &attrList,
- NULL, // don't need the data
- NULL);
- if(ortn) {
- printOsError("SecKeychainItemCopyAttributesAndData", ortn);
- return 0;
- }
- if(attrList->count != 1) {
- printf("***Unexpected attribute count (%u) for %s\n",
- (unsigned)attrList->count, itemClass);
- return 0;
- }
- SecKeychainAttribute *attr = attrList->attr;
-
- /* it's a UTF8 string: use CFString to convert to C ASCII string */
- CFStringRef cfStr = CFStringCreateWithBytes(NULL,
- (UInt8 *)attr->data, attr->length,
- kCFStringEncodingUTF8, false);
- SecKeychainItemFreeAttributesAndData(attrList, NULL);
- if(cfStr == NULL) {
- printf("***Error converting %s name to UTF CFSTring.\n",
- itemClass);
- return 0;
- }
-
- CFIndex strLen = CFStringGetLength(cfStr);
- char *printName = (char *)malloc(strLen + 1);
- if(!CFStringGetCString(cfStr, printName, strLen + 1, kCFStringEncodingASCII)) {
- printf("***Error converting %s name to ASCII\n", itemClass);
- return 0;
- }
- CFRelease(cfStr);
-
- char *aliasCStr = NULL;
- if((itemId == SecCertificateGetTypeID())) {
- /* the alias attr, for cert email */
- CFStringRef aliasCFStr = NULL;
- nameAttr = kSecAlias;
- attrInfo.count = 1;
- attrInfo.tag = &nameAttr;
- attrInfo.format = NULL; // ???
- attrList = NULL;
-
- ortn = SecKeychainItemCopyAttributesAndData(
- item,
- &attrInfo,
- NULL, // itemClass
- &attrList,
- NULL, // don't need the data
- NULL);
- if(ortn) {
- printOsError("SecKeychainItemCopyAttributesAndData", ortn);
- return 0;
- }
- if(attrList->count != 1) {
- printf("***Unexpected attribute count (%u) for Alias\n",
- (unsigned)attrList->count);
- return 0;
- }
- attr = attrList->attr;
-
- /* it's a UTF8 string: use CFString to convert to C ASCII string */
- aliasCFStr = CFStringCreateWithBytes(NULL,
- (UInt8 *)attr->data, attr->length,
- kCFStringEncodingUTF8, false);
- if(aliasCFStr == NULL) {
- printf("***Error converting Alias name to UTF CFSTring.\n");
- return 0;
- }
-
- strLen = CFStringGetLength(aliasCFStr);
- aliasCStr = (char *)malloc(strLen + 1);
- if(!CFStringGetCString(aliasCFStr, aliasCStr, strLen + 1,
- kCFStringEncodingASCII)) {
- printf("***Error converting Alias name to ASCII\n");
- return 0;
- }
- CFRelease(aliasCFStr);
- }
-
- int ourRtn = 0;
- fpurge(stdin);
- printf("Found %s\n", itemClass);
- printf(" printable name : %s\n", printName);
- if(aliasCStr != NULL) {
- printf(" alias : %s\n", aliasCStr);
- }
- printf("Export (y/anything)? ");
- char c = getchar();
- if(c == 'y') {
- CFArrayAppendValue(itemArray, item);
- ourRtn = 1;
- }
- free(printName);
- if(aliasCStr) {
- free(aliasCStr);
- }
- return ourRtn;
-}
-
-int p12Export(
- const char *pfxFile,
- const char *kcName,
- CFStringRef pwd, // explicit passphrase, mutually exclusive with...
- bool usePassKey, // use SECURE_PASSPHRASE key
- const char *kcPwd, // optional
- bool noPrompt) // true --> export all
-{
- OSStatus ortn;
- CSSM_KEY passKey;
-
- /* set up a pkcs12 coder for export */
- SecPkcs12CoderRef coder;
- ortn = SecPkcs12CoderCreate(&coder);
- if(ortn) {
- printOsError("SecPkcs12CoderCreate", ortn);
- return ortn;
- }
-
- /*
- Ê* Since we're not providing the SecPkcs12CoderRef with a
- * keychain, we have to provide the CSPDL handle
- */
- CSSM_CSP_HANDLE cspHand = cuCspStartup(CSSM_FALSE);
- if(cspHand == 0) {
- printf("***Error attaching to CSPDL. Aborting.\n");
- return 1;
- }
-
- if(usePassKey) {
- ortn = p12GetPassKey(cspHand, GPK_Encode, false, &passKey);
- if(ortn) {
- return ortn;
- }
- ortn = SecPkcs12SetMACPassKey(coder, &passKey);
- if(ortn) {
- printOsError("SecPkcs12SetMACPassKey", ortn);
- return ortn;
- }
- }
- else {
- ortn = SecPkcs12SetMACPassphrase(coder, pwd);
- if(ortn) {
- printOsError("SecPkcs12SetMACPassphrase", ortn);
- return ortn;
- }
- }
-
- ortn = SecPkcs12SetCspHandle(coder, cspHand);
- if(ortn) {
- printOsError("SecPkcs12SetCspHandle", ortn);
- return ortn;
- }
-
- /* the array of things we want to export */
- CFMutableArrayRef items = CFArrayCreateMutable(NULL, 0, NULL);
-
- /* export from keychain specified by kcName */
- SecKeychainRef kcRef = NULL;
- ortn = SecKeychainOpen(kcName, &kcRef);
- if(ortn) {
- printOsError("SecKeychainOpen", ortn);
- return ortn;
- }
-
- if(kcPwd) {
- ortn = SecKeychainUnlock(kcRef, strlen(kcPwd), (void *)kcPwd, true);
- if(ortn) {
- printOsError("SecKeychainUnlock", ortn);
- }
- }
-
- /*
- * Prompt user for each known item - it would be nice if we
- * could search for anything, eh?
- * Certs first...
- */
- SecKeychainSearchRef srchRef;
- ortn = SecKeychainSearchCreateFromAttributes(kcRef,
- kSecCertificateItemClass,
- NULL, // no attrs
- &srchRef);
- if(ortn) {
- printOsError("SecKeychainSearchCreateFromAttributes", ortn);
- return ortn;
- }
- int exported = 0;
- for(;;) {
- SecKeychainItemRef certRef;
- ortn = SecKeychainSearchCopyNext(srchRef, &certRef);
- if(ortn) {
- break;
- }
- exported += p12AddExportedItem(certRef, items, noPrompt);
- }
- CFRelease(srchRef);
-
- /* now private keys */
- ortn = SecKeychainSearchCreateFromAttributes(kcRef,
- CSSM_DL_DB_RECORD_PRIVATE_KEY, // undocumented
- NULL, // no attrs
- &srchRef);
- if(ortn) {
- printOsError("SecKeychainSearchCreateFromAttributes", ortn);
- return ortn;
- }
- for(;;) {
- SecKeychainItemRef keyRef;
- ortn = SecKeychainSearchCopyNext(srchRef, &keyRef);
- if(ortn) {
- break;
- }
- exported += p12AddExportedItem(keyRef, items, noPrompt);
- }
-
- if(exported == 0) {
- printf("...Hmmm, no items to export. Done.\n");
- return 0;
- }
- ortn = SecPkcs12ExportKeychainItems(coder, items);
- if(ortn) {
- printOsError("SecPkcs12ExportKeychainItems", ortn);
- return ortn;
- }
-
- /* go */
- CFDataRef pfx;
- ortn = SecPkcs12Encode(coder, &pfx);
- if(ortn) {
- printOsError("SecPkcs12ExportKeychainItems", ortn);
- return ortn;
- }
-
- if(writeFile(pfxFile, CFDataGetBytePtr(pfx),
- CFDataGetLength(pfx))) {
- printf("***Error writing pfx to %s\n", pfxFile);
- return 1;
- }
- printf("...%u items exported; %ld bytes written to %s\n",
- exported, CFDataGetLength(pfx), pfxFile);
-
- /* cleanup */
- SecPkcs12CoderRelease(coder);
- CFRelease(pfx);
- CFRelease(srchRef);
- CFRelease(kcRef);
- return 0;
-}