]> git.saurik.com Git - apple/security.git/blobdiff - SecurityTests/cspxutils/pubKeyTool/pubKeyTool.cpp
Security-57740.51.3.tar.gz
[apple/security.git] / SecurityTests / cspxutils / pubKeyTool / pubKeyTool.cpp
diff --git a/SecurityTests/cspxutils/pubKeyTool/pubKeyTool.cpp b/SecurityTests/cspxutils/pubKeyTool/pubKeyTool.cpp
deleted file mode 100644 (file)
index ce53b0e..0000000
+++ /dev/null
@@ -1,672 +0,0 @@
-/*
- * pubKeyTool.cpp - calculate public key hash of arbitrary keys and certs; derive
- *                  public key from a private key or a cert. 
- */
-#include <stdlib.h>
-#include <strings.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <Security/Security.h>
-#include <security_cdsa_utils/cuFileIo.h>
-#include <security_cdsa_utils/cuCdsaUtils.h>
-#include "cspwrap.h"
-#include "common.h"
-
-static void usage(char **argv)
-{
-       printf("usage: %s [options]\n", argv[0]);
-       printf("Options:\n");
-       printf("   -k priv_key_file      -- private key file to read\n");
-       printf("   -b pub_key_file       -- public key file to read\n");
-       printf("   -c cert_file          -- cert file to read\n");
-       printf("   -d                    -- print public key digest\n");
-       printf("   -o out_file           -- write public key to out_file\n");
-       printf("   -f pkcs1|pkcs8|x509   -- input key format\n");
-       printf("                         -- default is PKCS8 for private key, PKCS1 for"
-                                                                                       " public\n");
-       printf("   -K keychain           -- import pub key to this keychain; workaround "
-                                                                                       "for Radar 4191851)\n");
-       exit(1);
-}
-
-/* Convert raw key blob into a respectable CSSM_KEY. */
-static CSSM_RETURN inferCssmKey(
-       const CSSM_DATA &keyBlob,
-       bool isPrivKey,
-       CSSM_KEYBLOB_FORMAT keyForm,
-       CSSM_CSP_HANDLE cspHand,
-       CSSM_KEY &outKey)
-{
-       memset(&outKey, 0, sizeof(CSSM_KEY));
-       outKey.KeyData = keyBlob;
-       CSSM_KEYHEADER &hdr = outKey.KeyHeader;
-       hdr.HeaderVersion = CSSM_KEYHEADER_VERSION;
-       /* CspId blank */
-       hdr.BlobType = CSSM_KEYBLOB_RAW;
-       hdr.AlgorithmId = CSSM_ALGID_RSA;
-       hdr.KeyAttr = CSSM_KEYATTR_EXTRACTABLE;
-       hdr.Format = keyForm;
-       hdr.KeyClass = isPrivKey ? CSSM_KEYCLASS_PRIVATE_KEY : CSSM_KEYCLASS_PUBLIC_KEY;
-       hdr.KeyUsage = CSSM_KEYUSE_ANY;
-       hdr.WrapAlgorithmId = CSSM_ALGID_NONE;
-       hdr.WrapMode = CSSM_ALGMODE_NONE;
-       /*
-        * LogicalKeySizeInBits - ask the CSP
-        */
-       CSSM_KEY_SIZE keySize;
-       CSSM_RETURN crtn;
-       crtn = CSSM_QueryKeySizeInBits(cspHand, CSSM_INVALID_HANDLE, &outKey,
-               &keySize);
-       if(crtn) {
-               cssmPerror("CSSM_QueryKeySizeInBits", crtn);
-               return crtn;
-       }
-       hdr.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits;
-       return CSSM_OK;
-}
-
-/*
- * Given any key in either blob or reference format,
- * obtain the associated public key's SHA-1 hash. 
- */
-static CSSM_RETURN keyDigest(
-       CSSM_CSP_HANDLE         cspHand,        
-       const CSSM_KEY          *key,           
-       CSSM_DATA_PTR           *hashData)      /* struct and contents cuAppMalloc'd and RETURNED */
-{
-       CSSM_CC_HANDLE          ccHand;
-       CSSM_RETURN                     crtn;
-       CSSM_DATA_PTR           dp;
-       
-       *hashData = NULL;
-       
-       /* validate input params */
-       if((key == NULL) ||
-          (hashData == NULL)) {
-               printf("keyHash: bogus args\n");
-               return CSSMERR_CSSM_INTERNAL_ERROR;                             
-       }
-       
-       /* cook up a context for a passthrough op */
-       crtn = CSSM_CSP_CreatePassThroughContext(cspHand,
-               key,
-               &ccHand);
-       if(ccHand == 0) {
-               cssmPerror("CSSM_CSP_CreatePassThroughContext", crtn);
-               return crtn;
-       }
-       
-       /* now it's up to the CSP */
-       crtn = CSSM_CSP_PassThrough(ccHand,
-               CSSM_APPLECSP_KEYDIGEST,
-               NULL,
-               (void **)&dp);
-       if(crtn) {
-               cssmPerror("CSSM_CSP_PassThrough(KEYDIGEST)", crtn);
-       }
-       else {
-               *hashData = dp;
-               crtn = CSSM_OK;
-       }
-       CSSM_DeleteContext(ccHand);
-       return crtn;
-}
-
-/* 
- * Here's a tricky one. Given a private key, obtain the correspoding public key. 
- * This uses a private key blob format that's used internally in the CSP
- * to generate key digests. 
- */
-/* 
- * this magic const copied from BinaryKey.h 
- */
-#define CSSM_KEYBLOB_RAW_FORMAT_DIGEST \
-       (CSSM_KEYBLOB_RAW_FORMAT_VENDOR_DEFINED + 0x12345)
-
-static CSSM_RETURN pubKeyFromPrivKey(
-       CSSM_CSP_HANDLE cspHand, 
-       const CSSM_KEY *privKey,                        // assumed to be raw format
-       CSSM_KEY *pubKey)                       
-{
-       /* first convert to reference key */
-       CSSM_KEY refKey;
-       CSSM_RETURN crtn;
-       crtn = cspRawKeyToRef(cspHand, privKey, &refKey);
-       if(crtn) {
-               return crtn;
-       }
-       
-       /* now a NULL wrap with the magic format attribute */
-       CSSM_CC_HANDLE ccHand;
-       CSSM_ACCESS_CREDENTIALS creds;
-       CSSM_DATA descData = {0, 0};
-       
-       crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
-                       CSSM_ALGID_NONE,
-                       CSSM_ALGMODE_NONE,
-                       NULL,                   // passPhrase,
-                       NULL,                   // key
-                       NULL,                   // initVector,
-                       CSSM_PADDING_NONE,      
-                       NULL,                   // Reserved
-                       &ccHand);
-       if(crtn) {
-               cssmPerror("CSSM_CSP_CreateSymmetricContext", crtn);
-               return crtn;
-       }
-       crtn = AddContextAttribute(ccHand,
-               /* 
-                * The output of the WrapKey is a private key as far as the CSP is 
-                * concerned, at the level that this attribute is used anyway.... 
-                */
-               CSSM_ATTRIBUTE_PRIVATE_KEY_FORMAT,
-               sizeof(uint32),
-               CAT_Uint32,
-               NULL,
-               CSSM_KEYBLOB_RAW_FORMAT_DIGEST);
-       if(crtn) {
-               cssmPerror("CSSM_CSP_CreateSymmetricContext", crtn);
-               goto errOut;
-       }
-       memset(pubKey, 0, sizeof(CSSM_KEY));
-       memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-       crtn = CSSM_WrapKey(ccHand,
-               &creds,
-               &refKey,
-               &descData,      
-               pubKey);
-       if(crtn) {
-               cssmPerror("CSSM_WrapKey", crtn);
-               goto errOut;
-       }
-       
-       /* now: presto chango - don't do this at home! */
-       pubKey->KeyHeader.KeyClass = CSSM_KEYCLASS_PUBLIC_KEY;
-errOut:
-       CSSM_FreeKey(cspHand, NULL, &refKey, CSSM_FALSE);
-       CSSM_DeleteContext(ccHand);
-       return crtn;
-}
-
-/* 
- * Import a key into a DLDB.
- */
-static CSSM_RETURN importToDlDb(
-       CSSM_CSP_HANDLE cspHand,
-       CSSM_DL_DB_HANDLE_PTR dlDbHand,
-       const CSSM_KEY *rawPubKey,
-       CSSM_DATA_PTR labelData,
-       CSSM_KEY_PTR importedKey)
-{
-       CSSM_CC_HANDLE                  ccHand = 0;
-       CSSM_RETURN                             crtn;
-       uint32                                  keyAttr;
-       CSSM_ACCESS_CREDENTIALS creds;
-       CSSM_CONTEXT_ATTRIBUTE  newAttr;        
-       CSSM_DATA                               descData = {0, 0};
-       
-       memset(importedKey, 0, sizeof(CSSM_KEY));
-       memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-       crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
-                               CSSM_ALGID_NONE,
-                               CSSM_ALGMODE_NONE,
-                               &creds,
-                               NULL,                   // unwrappingKey
-                               NULL,                   // initVector
-                               CSSM_PADDING_NONE,
-                               0,                              // Params
-                               &ccHand);
-       if(crtn) {
-               cssmPerror("CSSM_CSP_CreateSymmetricContext", crtn);
-               return crtn;
-       }
-       keyAttr = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE | CSSM_KEYATTR_PERMANENT;
-       
-       /* Add DLDB to context */
-       newAttr.AttributeType     = CSSM_ATTRIBUTE_DL_DB_HANDLE;
-       newAttr.AttributeLength   = sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE);
-       newAttr.Attribute.Data    = (CSSM_DATA_PTR)dlDbHand;
-       crtn = CSSM_UpdateContextAttributes(ccHand, 1, &newAttr);
-       if(crtn) {
-               cssmPerror("CSSM_UpdateContextAttributes", crtn);
-               goto errOut;
-       }
-       
-       /* import */
-       crtn = CSSM_UnwrapKey(ccHand,
-               NULL,                           // PublicKey
-               rawPubKey,
-               CSSM_KEYUSE_ANY,
-               keyAttr,
-               labelData,
-               NULL,                           // CredAndAclEntry
-               importedKey,
-               &descData);                     // required
-       if(crtn) {
-               cssmPerror("CSSM_UnwrapKey", crtn);
-       }
-errOut:
-       if(ccHand) {
-               CSSM_DeleteContext(ccHand);
-       }
-       return crtn;
-}
-
-/*
- * Free memory via specified plugin's app-level allocator
- */
-void impExpFreeCssmMemory(
-       CSSM_HANDLE             hand,
-       void                    *p)
-{
-       CSSM_API_MEMORY_FUNCS memFuncs;
-       CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs);
-       if(crtn) {
-               return;
-       }
-       memFuncs.free_func(p, memFuncs.AllocRef);
-}
-
-/*
- * Key attrribute names and values.
- *
- * This is where the public key hash goes.
- */
-#define SEC_KEY_HASH_ATTR_NAME                 "Label"
-
-/*
- * This is where the publicly visible name goes.
- */
-#define SEC_KEY_PRINT_NAME_ATTR_NAME   "PrintName"
-
-/* 
- * Look up public key by label 
- * Set label to new specified label (SHA1 digest)
- * Set print name to new specified user-visible name
- */
-static CSSM_RETURN setPubKeyLabel(
-       CSSM_CSP_HANDLE         cspHand,                // where the key lives
-       CSSM_DL_DB_HANDLE       *dlDbHand,              // ditto
-       const CSSM_DATA         *existKeyLabel, // existing label, a random string, for lookup
-       const CSSM_DATA         *keyDigest,             // SHA1 digest, the new label
-       const CSSM_DATA         *newPrintName)  // new user-visible name
-{
-       CSSM_QUERY                                              query;
-       CSSM_SELECTION_PREDICATE                predicate;
-       CSSM_DB_UNIQUE_RECORD_PTR               record = NULL;
-       CSSM_RETURN                                             crtn;
-       CSSM_HANDLE                                             resultHand = 0;
-       
-       /*
-        * Look up the key in the DL.
-        */
-       query.RecordType = CSSM_DL_DB_RECORD_PUBLIC_KEY;
-       query.Conjunctive = CSSM_DB_NONE;
-       query.NumSelectionPredicates = 1;
-       predicate.DbOperator = CSSM_DB_EQUAL;
-       
-       predicate.Attribute.Info.AttributeNameFormat = 
-               CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
-       predicate.Attribute.Info.Label.AttributeName = (char *)"Label";
-       predicate.Attribute.Info.AttributeFormat = 
-               CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
-       /* hope this cast is OK */
-       predicate.Attribute.Value = (CSSM_DATA_PTR)existKeyLabel;
-       query.SelectionPredicate = &predicate;
-       
-       query.QueryLimits.TimeLimit = 0;        // FIXME - meaningful?
-       query.QueryLimits.SizeLimit = 1;        // FIXME - meaningful?
-       query.QueryFlags = 0; // CSSM_QUERY_RETURN_DATA;        // FIXME - used?
-
-       /* build Record attribute with two attrs */
-       CSSM_DB_RECORD_ATTRIBUTE_DATA recordAttrs;
-       CSSM_DB_ATTRIBUTE_DATA attr[2];
-       
-       attr[0].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
-       attr[0].Info.Label.AttributeName = (char *)SEC_KEY_HASH_ATTR_NAME;
-       attr[0].Info.AttributeFormat     = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
-       attr[1].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
-       attr[1].Info.Label.AttributeName = (char *)SEC_KEY_PRINT_NAME_ATTR_NAME;
-       attr[1].Info.AttributeFormat     = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
-       
-       recordAttrs.DataRecordType               = CSSM_DL_DB_RECORD_PUBLIC_KEY;
-       recordAttrs.NumberOfAttributes   = 2;
-       recordAttrs.AttributeData        = attr;
-       
-       crtn = CSSM_DL_DataGetFirst(*dlDbHand,
-               &query,
-               &resultHand,
-               &recordAttrs,
-               NULL,                   // theData
-               &record);
-       /* abort only on success */
-       if(crtn != CSSM_OK) {
-               cssmPerror("CSSM_DL_DataGetFirst", crtn);
-               goto errOut;
-       }
-       
-       /* 
-        * Update existing attr data.
-        * NOTE: the module which allocated this attribute data - a DL -
-        * was loaded and attached by the keychain layer, not by us. Thus 
-        * we can't use the memory allocator functions *we* used when 
-        * attaching to the CSP - we have to use the ones
-        * which the client registered with the DL.
-        */
-       impExpFreeCssmMemory(dlDbHand->DLHandle, attr[0].Value->Data);
-       impExpFreeCssmMemory(dlDbHand->DLHandle, attr[0].Value);
-       impExpFreeCssmMemory(dlDbHand->DLHandle, attr[1].Value->Data);
-       impExpFreeCssmMemory(dlDbHand->DLHandle, attr[1].Value);
-       attr[0].Value = const_cast<CSSM_DATA *>(keyDigest);
-       attr[1].Value = const_cast<CSSM_DATA *>(newPrintName);
-       
-       crtn = CSSM_DL_DataModify(*dlDbHand,
-                       CSSM_DL_DB_RECORD_PUBLIC_KEY,
-                       record,
-                       &recordAttrs,
-            NULL,                              // DataToBeModified
-                       CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
-       if(crtn) {
-               cssmPerror("CSSM_DL_DataModify", crtn);
-       }
-errOut:
-       /* free resources */
-       if(resultHand) {
-               CSSM_DL_DataAbortQuery(*dlDbHand, resultHand);
-       }
-       if(record) {
-               CSSM_DL_FreeUniqueRecord(*dlDbHand, record);
-       }
-       return crtn;
-}
-
-#define SHA1_LABEL_LEN 20
-#define IMPORTED_KEY_NAME "Imported Public Key"
-
-/* 
- * Import a public key into a keychain, with proper Label attribute setting. 
- * A workaround for Radar 4191851.
- */
-static int pubKeyImport(
-       const char *kcName, 
-       const CSSM_KEY *pubKey,
-       CSSM_CSP_HANDLE rawCspHand)             /* raw CSP handle for calculating digest */
-{
-       CSSM_CSP_HANDLE cspHand;
-       CSSM_DL_DB_HANDLE dlDbHand;
-       OSStatus ortn;
-       CSSM_RETURN crtn;
-       SecKeychainRef kcRef = NULL;
-       int ourRtn = 0;
-       CSSM_DATA_PTR digest = NULL;
-       CSSM_KEY importedKey;
-       CSSM_DATA newPrintName = 
-               { (uint32)strlen(IMPORTED_KEY_NAME), (uint8 *)IMPORTED_KEY_NAME};
-               
-       /* NULL unwrap stuff */
-       uint8 tempLabel[SHA1_LABEL_LEN];
-       CSSM_DATA labelData = {SHA1_LABEL_LEN, tempLabel};
-       
-       ortn = SecKeychainOpen(kcName, &kcRef);
-       if(ortn) {
-               cssmPerror("SecKeychainOpen", ortn);
-               return -1;
-       }
-       /* subsequent errors to errOut: */
-       
-       /* Get CSSM handles */
-       ortn = SecKeychainGetCSPHandle(kcRef, &cspHand);
-       if(ortn) {
-               cssmPerror("SecKeychainGetCSPHandle", ortn);
-               ourRtn = -1;
-               goto errOut;
-       }
-       ortn = SecKeychainGetDLDBHandle(kcRef, &dlDbHand);
-       if(ortn) {
-               cssmPerror("SecKeychainGetCSPHandle", ortn);
-               ourRtn = -1;
-               goto errOut;
-       }
-       
-       /* public key hash from raw CSP */
-       crtn = keyDigest(rawCspHand, pubKey, &digest);
-       if(crtn) {
-               ourRtn = -1;
-               goto errOut;
-       }
-       
-       /* random label for initial storage and later retrieval */
-       appGetRandomBytes(tempLabel, SHA1_LABEL_LEN);
-       
-       /* import the key into the keychain's DLDB */
-       memset(&importedKey, 0, sizeof(CSSM_KEY));
-       crtn = importToDlDb(cspHand, &dlDbHand, pubKey, &labelData, &importedKey);
-       if(crtn) {
-               ourRtn = -1;
-               goto errOut;
-       }
-       
-       /* don't need this */
-       CSSM_FreeKey(cspHand, NULL, &importedKey, CSSM_FALSE);
-       
-       /* update the label and printName attributes */
-       crtn = setPubKeyLabel(cspHand, &dlDbHand, &labelData, digest, &newPrintName);
-       if(crtn) {
-               ourRtn = -1;
-       }
-errOut:
-       CFRelease(kcRef);
-       if(digest) {
-               APP_FREE(digest->Data);
-               APP_FREE(digest);
-       }
-       return ourRtn;
-}
-
-int main(int argc, char **argv)
-{
-       char *privKeyFile = NULL;
-       char *pubKeyFile = NULL;
-       char *certFile = NULL;
-       char *outFile = NULL;
-       bool printDigest = false;
-       CSSM_KEYBLOB_FORMAT keyForm = CSSM_KEYBLOB_RAW_FORMAT_NONE;
-       char *kcName = NULL;
-       
-       if(argc < 3) {
-               usage(argv);
-       }
-       extern char *optarg;
-       int arg;
-       while ((arg = getopt(argc, argv, "k:b:c:do:f:K:h")) != -1) {
-               switch (arg) {
-                       case 'k':
-                               privKeyFile = optarg;
-                               break;
-                       case 'b':
-                               pubKeyFile = optarg;
-                               break;
-                       case 'c':
-                               certFile = optarg;
-                               break;
-                       case 'd':
-                               printDigest = true;
-                               break;
-                       case 'o':
-                               outFile = optarg;
-                               break;
-                       case 'f':
-                               if(!strcmp("pkcs1", optarg)) {
-                                       keyForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
-                               }
-                               else if(!strcmp("pkcs8", optarg)) {
-                                       keyForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
-                               }
-                               else if(!strcmp("x509", optarg)) {
-                                       keyForm = CSSM_KEYBLOB_RAW_FORMAT_X509;
-                               }
-                               break;
-                       case 'K':
-                               kcName = optarg;
-                               break;
-                       case 'h':
-                               usage(argv);
-               }
-       }
-       if(optind != argc) {
-               usage(argv);
-       }
-       
-       CSSM_DATA privKeyBlob = {0, NULL};
-       CSSM_DATA pubKeyBlob = {0, NULL};
-       CSSM_KEY thePrivKey;                    // constructed
-       CSSM_KEY thePubKey;                             // null-wrapped
-       CSSM_KEY_PTR pubKey = NULL;
-       CSSM_KEY_PTR privKey = NULL;
-       CSSM_RETURN crtn;
-       CSSM_CL_HANDLE clHand = 0;
-       CSSM_CSP_HANDLE cspHand = cuCspStartup(CSSM_TRUE);
-
-       /* gather input */
-       if(privKeyFile) {
-               /* key blob from a file ==> a private CSSM_KEY */
-
-               if(pubKeyFile || certFile) {
-                       printf("****Specify exactly one of {cert_file, priv_key_file, "
-                                       "pub_key_file}.\n");
-                       exit(1);
-               }
-               unsigned len;
-               if(readFile(privKeyFile, &privKeyBlob.Data, &len)) {
-                       printf("***Error reading private key from %s. Aborting.\n", privKeyFile);
-                       exit(1);
-               }
-               privKeyBlob.Length = len;
-               if(keyForm == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
-                       /* default for private keys */
-                       keyForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS8;
-               }
-               crtn = inferCssmKey(privKeyBlob, true, keyForm, cspHand, thePrivKey);
-               if(crtn) {
-                       goto errOut;
-               }
-               privKey = &thePrivKey;
-       }
-       if(pubKeyFile) {
-               /* key blob from a file ==> a public CSSM_KEY */
-
-               if(privKeyFile || certFile) {
-                       printf("****Specify exactly one of {cert_file, priv_key_file, "
-                                       "pub_key_file}.\n");
-                       exit(1);
-               }
-               
-               unsigned len;
-               if(readFile(pubKeyFile, &pubKeyBlob.Data, &len)) {
-                       printf("***Error reading public key from %s. Aborting.\n", pubKeyFile);
-                       exit(1);
-               }
-               pubKeyBlob.Length = len;
-               if(keyForm == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
-                       /* default for public keys */
-                       keyForm = CSSM_KEYBLOB_RAW_FORMAT_PKCS1;
-               }
-               crtn = inferCssmKey(pubKeyBlob, false, keyForm, cspHand, thePubKey);
-               if(crtn) {
-                       goto errOut;
-               }
-               pubKey = &thePubKey;
-       }
-       if(certFile) {
-               /* cert from a file ==> a public CSSM_KEY */
-
-               if(privKeyFile || pubKeyFile) {
-                       printf("****Specify exactly one of {cert_file, priv_key_file, "
-                                       "pub_key_file}.\n");
-                       exit(1);
-               }
-               
-               CSSM_DATA certData = {0, NULL};
-               unsigned len;
-               if(readFile(certFile, &certData.Data, &len)) {
-                       printf("***Error reading cert from %s. Aborting.\n", certFile);
-                       exit(1);
-               }
-               certData.Length = len;
-               
-               /* Extract public key - that's what we will be using later */
-               clHand = cuClStartup();
-               crtn = CSSM_CL_CertGetKeyInfo(clHand, &certData, &pubKey);
-               if(crtn) {
-                       cssmPerror("CSSM_CL_CertGetKeyInfo", crtn);
-                       goto errOut;
-               }
-       }
-       
-       /* now do something useful */
-       if(printDigest) {
-               CSSM_KEY_PTR theKey = privKey;
-               if(theKey == NULL) {
-                       /* maybe we got public key from a cert */
-                       theKey = pubKey;
-               }
-               if(theKey == NULL) {
-                       printf("***Can't calculate digest because I don't have a key or a clue.\n");
-                       goto errOut;
-               }
-               CSSM_DATA_PTR dig = NULL;
-               crtn = keyDigest(cspHand, theKey, &dig);
-               if(crtn) {
-                       printf("Sorry, can't get the digest for this key.\n");
-                       goto errOut;
-               }
-               if((dig == NULL) || (dig->Length == 0)) {
-                       printf("Screwup calculating digest.\n");
-                       goto errOut;
-               }
-               printf("Key Digest:\n");
-               for(unsigned dex=0; dex<dig->Length; dex++) {
-                       printf("%02X ", dig->Data[dex]);
-               }
-               printf("\n");
-               APP_FREE(dig->Data);
-               APP_FREE(dig);
-       }
-       
-       if(outFile || kcName) {
-               /* get a public key if we don't already have one */
-               if(pubKey == NULL) {
-                       if(privKey == NULL) {
-                               printf("***PubKey file name specified but no privKey or cert. " 
-                                               "Aborting.\n");
-                               goto errOut;
-                       }
-                       crtn = pubKeyFromPrivKey(cspHand, privKey, &thePubKey);
-                       if(crtn) {
-                               goto errOut;
-                       }
-                       pubKey = &thePubKey;
-               }
-       }
-       if(outFile) {
-               if(writeFile(outFile, pubKey->KeyData.Data, pubKey->KeyData.Length)) {
-                       printf("***Error writing to %s.\n", outFile);
-               }
-               else {
-                       printf("...%lu bytes written to %s.\n", pubKey->KeyData.Length, outFile);
-               }
-       }
-       if(kcName) {
-               if(pubKeyImport(kcName, pubKey, cspHand) == 0) {
-                       printf("....public key %s imported to %s\n", pubKeyFile, kcName);
-               }
-               else {
-                       printf("***Error importing public key %s to %s\n", pubKeyFile, kcName);
-               }
-       }
-errOut:
-       /* clean up here if you must */
-       return 0;
-}