]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_keychain/Security/SecImportExportUtils.cpp
Security-57336.10.29.tar.gz
[apple/security.git] / OSX / libsecurity_keychain / Security / SecImportExportUtils.cpp
diff --git a/OSX/libsecurity_keychain/Security/SecImportExportUtils.cpp b/OSX/libsecurity_keychain/Security/SecImportExportUtils.cpp
deleted file mode 100644 (file)
index e0f1776..0000000
+++ /dev/null
@@ -1,972 +0,0 @@
-/*
- * Copyright (c) 2004,2011-2014 Apple Inc. All Rights Reserved.
- *
- * @APPLE_LICENSE_HEADER_START@
- * 
- * This file contains Original Code and/or Modifications of Original Code
- * as defined in and that are subject to the Apple Public Source License
- * Version 2.0 (the 'License'). You may not use this file except in
- * compliance with the License. Please obtain a copy of the License at
- * http://www.opensource.apple.com/apsl/ and read it before using this
- * file.
- * 
- * The Original Code and all software distributed under the License are
- * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
- * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
- * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
- * Please see the License for the specific language governing rights and
- * limitations under the License.
- * 
- * @APPLE_LICENSE_HEADER_END@
- *
- * SecImportExportUtils.cpp - misc. utilities for import/export module
- */
-
-#include "SecImportExportUtils.h"
-#include "SecImportExportAgg.h"
-#include "SecImportExportCrypto.h"
-#include "SecIdentityPriv.h"
-#include "SecItem.h"
-#include <security_cdsa_utils/cuCdsaUtils.h>
-#include <Security/SecBase.h>
-#pragma mark --- Debug support ---
-
-#ifndef NDEBUG
-
-const char *impExpExtFormatStr(
-       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";
-               default:                                                return "UNKNOWN FORMAT ENUM";
-       }
-}
-
-const char *impExpExtItemTypeStr(
-       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";
-       }
-}
-#endif  /* NDEBUG */
-
-/*
- * Parse file extension and attempt to map it to format and type. Returns true
- * on success.
- */
-bool impExpImportParseFileExten(
-       CFStringRef                     fstr,
-       SecExternalFormat   *inputFormat,   // RETURNED
-       SecExternalItemType     *itemType)              // RETURNED
-{
-       if(fstr == NULL) {
-               /* nothing to work with */
-               return false;
-       }
-       if(CFStringHasSuffix(fstr, CFSTR(".cer")) ||
-          CFStringHasSuffix(fstr, CFSTR(".crt"))) {
-               *inputFormat = kSecFormatX509Cert;
-               *itemType = kSecItemTypeCertificate;
-               SecImpInferDbg("Inferring kSecFormatX509Cert from file name");
-               return true;
-       }
-       if(CFStringHasSuffix(fstr, CFSTR(".p12")) ||
-          CFStringHasSuffix(fstr, CFSTR(".pfx"))) {
-               *inputFormat = kSecFormatPKCS12;
-               *itemType = kSecItemTypeAggregate;
-               SecImpInferDbg("Inferring kSecFormatPKCS12 from file name");
-               return true;
-       }
-
-       /* Get extension, look for key indicators as substrings */
-       CFURLRef url = CFURLCreateWithString(NULL, fstr, NULL);
-       if(url == NULL) {
-               SecImpInferDbg("impExpImportParseFileExten: error creating URL");
-               return false;
-       }
-       CFStringRef exten = CFURLCopyPathExtension(url);
-       CFRelease(url);
-       if(exten == NULL) {
-               /* no extension, app probably passed in only an extension */
-               exten = fstr;
-               CFRetain(exten);
-       }
-       bool ortn = false;
-       CFRange cfr;
-       cfr = CFStringFind(exten, CFSTR("p7"), kCFCompareCaseInsensitive);
-       if(cfr.length != 0) {
-               *inputFormat = kSecFormatPKCS7;
-               *itemType = kSecItemTypeAggregate;
-               SecImpInferDbg("Inferring kSecFormatPKCS7 from file name");
-               ortn = true;
-       }
-       if(!ortn) {
-               cfr = CFStringFind(exten, CFSTR("p8"), kCFCompareCaseInsensitive);
-               if(cfr.length != 0) {
-                       *inputFormat = kSecFormatWrappedPKCS8;
-                       *itemType = kSecItemTypePrivateKey;
-                       SecImpInferDbg("Inferring kSecFormatPKCS8 from file name");
-                       ortn = true;
-               }
-       }
-       CFRelease(exten);
-       return ortn;
-}
-
-/* do a [NSString stringByDeletingPathExtension] equivalent */
-CFStringRef impExpImportDeleteExtension(
-       CFStringRef                     fileStr)
-{
-       CFDataRef fileStrData = CFStringCreateExternalRepresentation(NULL, fileStr,
-               kCFStringEncodingUTF8, 0);
-       if(fileStrData == NULL) {
-               return NULL;
-       }
-
-       CFURLRef urlRef = CFURLCreateFromFileSystemRepresentation(NULL,
-               CFDataGetBytePtr(fileStrData), CFDataGetLength(fileStrData), false);
-       if(urlRef == NULL) {
-               CFRelease(fileStrData);
-               return NULL;
-       }
-       CFURLRef rtnUrl = CFURLCreateCopyDeletingPathExtension(NULL, urlRef);
-       CFStringRef rtnStr = NULL;
-       CFRelease(urlRef);
-       if(rtnUrl) {
-               rtnStr = CFURLGetString(rtnUrl);
-               CFRetain(rtnStr);
-               CFRelease(rtnUrl);
-       }
-       CFRelease(fileStrData);
-       return rtnStr;
-}
-
-#pragma mark --- mapping of external format to CDSA formats ---
-
-/*
- * For the record, here is the mapping of SecExternalFormat, algorithm, and key
- * class to CSSM-style key format (CSSM_KEYBLOB_FORMAT -
- * CSSM_KEYBLOB_RAW_FORMAT_X509, etc). The entries in the table are the
- * last component of a CSSM_KEYBLOB_FORMAT. Format kSecFormatUnknown means
- * "default for specified class and algorithm", which is currently the
- * same as kSecFormatOpenSSL.
- *
- *                                                                   algorithm/class
- *                                                   RSA                           DSA                            DH
- *                                             ----------------  ----------------  ----------------
- * SecExternalFormat    priv      pub     priv      pub         priv      pub
- * -----------------   -------  -------  -------  -------  -------  -------
- * kSecFormatOpenSSL    PKCS1    X509    OPENSSL   X509     PKCS3    X509
- * kSecFormatBSAFE       PKCS8    PKCS1   FIPS186   FIPS186  PKCS8    not supported
- * kSecFormatUnknown    PKCS1    X509    OPENSSL   X509     PKCS3    X509
- * kSecFormatSSH                 SSH      SSH      n/s     n/s       n/s     n/s
- * kSecFormatSSHv2        n/s     SSH2      n/s     SSH2      n/s     n/s
- *
- * The only external format supported for ECDSA and ECDH keys is kSecFormatOpenSSL,
- * which translates to OPENSSL for private keys and X509 for public keys.
- */
-
-/* Arrays expressing the above table. */
-
-/* l.s. dimension is pub/priv for one alg */
-typedef struct {
-       CSSM_KEYBLOB_FORMAT priv;
-       CSSM_KEYBLOB_FORMAT pub;
-} algForms;
-
-/*
- * indices into array of algForms defining all algs' formats for a given
- * SecExternalFormat
- */
-#define SIE_ALG_RSA            0
-#define SIE_ALG_DSA            1
-#define SIE_ALG_DH             2
-#define SIE_ALG_ECDSA  3
-#define SIE_ALG_LAST   SIE_ALG_ECDSA
-#define SIE_NUM_ALGS   (SIE_ALG_LAST + 1)
-
-/* kSecFormatOpenSSL */
-static algForms opensslAlgForms[SIE_NUM_ALGS] =
-{
-       { CSSM_KEYBLOB_RAW_FORMAT_PKCS1,        CSSM_KEYBLOB_RAW_FORMAT_X509 },         // RSA
-       { CSSM_KEYBLOB_RAW_FORMAT_OPENSSL,  CSSM_KEYBLOB_RAW_FORMAT_X509 },             // DSA
-       { CSSM_KEYBLOB_RAW_FORMAT_PKCS3,        CSSM_KEYBLOB_RAW_FORMAT_X509 },         // D-H
-       { CSSM_KEYBLOB_RAW_FORMAT_OPENSSL,      CSSM_KEYBLOB_RAW_FORMAT_X509 },         // ECDSA
-};
-
-/* kSecFormatBSAFE */
-static algForms bsafeAlgForms[SIE_NUM_ALGS] =
-{
-       { CSSM_KEYBLOB_RAW_FORMAT_PKCS8,        CSSM_KEYBLOB_RAW_FORMAT_PKCS1 },        // RSA
-       { CSSM_KEYBLOB_RAW_FORMAT_FIPS186,  CSSM_KEYBLOB_RAW_FORMAT_FIPS186 },  // DSA
-       { CSSM_KEYBLOB_RAW_FORMAT_PKCS8,        CSSM_KEYBLOB_RAW_FORMAT_NONE },         // D-H
-       { CSSM_KEYBLOB_RAW_FORMAT_NONE,         CSSM_KEYBLOB_RAW_FORMAT_NONE },         // ECDSA not supported
-};
-
-/* kSecFormatSSH (v1) */
-static algForms ssh1AlgForms[SIE_NUM_ALGS] =
-{
-       { CSSM_KEYBLOB_RAW_FORMAT_OPENSSH,      CSSM_KEYBLOB_RAW_FORMAT_OPENSSH },      // RSA only
-       { CSSM_KEYBLOB_RAW_FORMAT_NONE,         CSSM_KEYBLOB_RAW_FORMAT_NONE },         // DSA not supported
-       { CSSM_KEYBLOB_RAW_FORMAT_NONE,         CSSM_KEYBLOB_RAW_FORMAT_NONE },         // D-H not supported
-       { CSSM_KEYBLOB_RAW_FORMAT_NONE,         CSSM_KEYBLOB_RAW_FORMAT_NONE },         // ECDSA not supported
-};
-
-/* kSecFormatSSHv2 */
-static algForms ssh2AlgForms[SIE_NUM_ALGS] =
-{
-       { CSSM_KEYBLOB_RAW_FORMAT_NONE,         CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2 },     // RSA - public only
-       { CSSM_KEYBLOB_RAW_FORMAT_NONE,         CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2 },     // DSA - public only
-       { CSSM_KEYBLOB_RAW_FORMAT_NONE,         CSSM_KEYBLOB_RAW_FORMAT_NONE },         // D-H not supported
-       { CSSM_KEYBLOB_RAW_FORMAT_NONE,         CSSM_KEYBLOB_RAW_FORMAT_NONE },         // ECDSA not supported
-};
-
-/*
- * This routine performs a lookup into the above 3-dimensional array to
- * map {algorithm, class, SecExternalFormat} to a CSSM_KEYBLOB_FORMAT.
- * Returns errSecUnsupportedFormat in the rare appropriate case.
- */
-OSStatus impExpKeyForm(
-       SecExternalFormat               externForm,
-       SecExternalItemType             itemType,
-       CSSM_ALGORITHMS                 alg,
-       CSSM_KEYBLOB_FORMAT             *cssmForm,              // RETURNED
-       CSSM_KEYCLASS                   *cssmClass)             // RETRUNED
-{
-       if(itemType == kSecItemTypeSessionKey) {
-               /* special trivial case */
-               /* FIXME ensure caller hasn't specified bogus format */
-               *cssmForm = CSSM_KEYBLOB_RAW_FORMAT_NONE;
-               *cssmClass = CSSM_KEYCLASS_SESSION_KEY;
-               return errSecSuccess;
-       }
-       if(externForm == kSecFormatUnknown) {
-               /* default is openssl */
-               externForm = kSecFormatOpenSSL;
-       }
-
-       unsigned algDex;
-       switch(alg) {
-               case CSSM_ALGID_RSA:
-                       algDex = SIE_ALG_RSA;
-                       break;
-               case CSSM_ALGID_DSA:
-                       algDex = SIE_ALG_DSA;
-                       break;
-               case CSSM_ALGID_DH:
-                       algDex = SIE_ALG_DH;
-                       break;
-               case CSSM_ALGID_ECDSA:
-                       algDex = SIE_ALG_ECDSA;
-                       break;
-               default:
-                       return CSSMERR_CSP_INVALID_ALGORITHM;
-       }
-       const algForms *forms;
-       switch(externForm) {
-               case kSecFormatOpenSSL:
-                       forms = opensslAlgForms;
-                       break;
-               case kSecFormatBSAFE:
-                       forms = bsafeAlgForms;
-                       break;
-               case kSecFormatSSH:
-                       forms = ssh1AlgForms;
-                       break;
-               case kSecFormatSSHv2:
-                       forms = ssh2AlgForms;
-                       break;
-               default:
-                       return errSecUnsupportedFormat;
-       }
-       CSSM_KEYBLOB_FORMAT form = CSSM_KEYBLOB_RAW_FORMAT_NONE;
-       switch(itemType) {
-               case kSecItemTypePrivateKey:
-                       form = forms[algDex].priv;
-                       *cssmClass = CSSM_KEYCLASS_PRIVATE_KEY;
-                       break;
-               case kSecItemTypePublicKey:
-                       form = forms[algDex].pub;
-                       *cssmClass = CSSM_KEYCLASS_PUBLIC_KEY;
-                       break;
-               default:
-                       return errSecUnsupportedFormat;
-       }
-       if(form == CSSM_KEYBLOB_RAW_FORMAT_NONE) {
-               /* not in the tables - abort */
-               return errSecUnsupportedFormat;
-       }
-       else {
-               *cssmForm = form;
-               return errSecSuccess;
-       }
-}
-
-/*
- * Given a raw key blob and zero to three known parameters (type, format,
- * algorithm), figure out all parameters. Used for private and public keys.
- */
-static bool impExpGuessKeyParams(
-       CFDataRef                               keyData,
-       SecExternalFormat               *externForm,            // IN/OUT
-       SecExternalItemType             *itemType,                      // IN/OUT
-       CSSM_ALGORITHMS                 *keyAlg)                        // IN/OUT
-{
-       /* CSSM alg list: RSA, DSA, DH, ECDSA */
-       CSSM_ALGORITHMS minAlg           = CSSM_ALGID_RSA;
-       CSSM_ALGORITHMS maxAlg           = CSSM_ALGID_ECDSA;
-       SecExternalFormat minForm    = kSecFormatOpenSSL;               // then SSH, BSAFE, then...
-       SecExternalFormat maxForm    = kSecFormatSSHv2;
-       SecExternalItemType minType  = kSecItemTypePrivateKey;  // just two
-       SecExternalItemType maxType  = kSecItemTypePublicKey;
-
-    
-    if(keyData == NULL || CFDataGetLength(keyData) == 0){
-                MacOSError::throwMe(errSecUnsupportedKeySize);
-    }
-    
-       switch(*externForm) {
-               case kSecFormatUnknown:
-                       break;                                                          // run through all formats
-               case kSecFormatOpenSSL:
-               case kSecFormatSSH:
-               case kSecFormatSSHv2:
-               case kSecFormatBSAFE:
-                       minForm = maxForm = *externForm;        // just test this one
-                       break;
-               default:
-                       return false;
-       }
-       switch(*itemType) {
-               case kSecItemTypeUnknown:
-                       break;
-               case kSecItemTypePrivateKey:
-               case kSecItemTypePublicKey:
-                       minType = maxType = *itemType;
-                       break;
-               default:
-                       return false;
-       }
-       switch(*keyAlg) {
-               case CSSM_ALGID_NONE:
-                       break;
-               case CSSM_ALGID_RSA:
-               case CSSM_ALGID_DSA:
-               case CSSM_ALGID_DH:
-               case CSSM_ALGID_ECDSA:
-                       minAlg = maxAlg = *keyAlg;
-                       break;
-               default:
-                       return false;
-       }
-
-       CSSM_ALGORITHMS theAlg;
-       SecExternalFormat theForm;
-       SecExternalItemType theType;
-       CSSM_CSP_HANDLE cspHand = cuCspStartup(CSSM_TRUE);
-       if(cspHand == 0) {
-               return CSSMERR_CSSM_ADDIN_LOAD_FAILED;
-       }
-
-       /*
-        * Iterate through all set of enabled {alg, type, format}.
-        * We do not assume that any of the enums are sequential hence this
-        * odd iteration algorithm....
-        */
-       bool ourRtn = false;
-       for(theAlg=minAlg; ; ) {
-               for(theForm=minForm; ; ) {
-                       for(theType=minType; ; ) {
-
-                               /* do super lightweight null unwrap to parse */
-                               OSStatus ortn = impExpImportRawKey(keyData,
-                                       theForm, theType, theAlg,
-                                       NULL,           // no keychain
-                                       cspHand,
-                                       0,                      // no flags
-                                       NULL,           // no key params
-                                       NULL,           // no printName
-                                       NULL);          // no returned items
-                               if(ortn == errSecSuccess) {
-                                       *externForm = theForm;
-                                       *itemType = theType;
-                                       *keyAlg = theAlg;
-                                       ourRtn = true;
-                                       goto done;
-                               }
-
-                               /* next type or break if we're done */
-                               if(theType == maxType) {
-                                       break;
-                               }
-                               else switch(theType) {
-                                       case kSecItemTypePrivateKey:
-                                               theType = kSecItemTypePublicKey;
-                                               break;
-                                       default:
-                                               assert(0);
-                                               ourRtn = false;
-                                               goto done;
-                               }
-                       }   /* for each class/type */
-
-                       /* next format or break if we're done */
-                       if(theForm == maxForm) {
-                               break;
-                       }
-                       else switch(theForm) {
-                               case kSecFormatOpenSSL:
-                                       theForm = kSecFormatSSH;
-                                       break;
-                               case kSecFormatSSH:
-                                       theForm = kSecFormatBSAFE;
-                                       break;
-                               case kSecFormatBSAFE:
-                                       theForm = kSecFormatSSHv2;
-                                       break;
-                               default:
-                                       assert(0);
-                                       ourRtn = false;
-                                       goto done;
-                       }
-               }               /* for each format */
-
-               /* next alg or break if we're done */
-               if(theAlg == maxAlg) {
-                       break;
-               }
-               else switch(theAlg) {
-                       case CSSM_ALGID_RSA:
-                               theAlg = CSSM_ALGID_DSA;
-                               break;
-                       case CSSM_ALGID_DSA:
-                               theAlg = CSSM_ALGID_DH;
-                               break;
-                       case CSSM_ALGID_DH:
-                               theAlg = CSSM_ALGID_ECDSA;
-                               break;
-                       default:
-                               /* i.e. CSSM_ALGID_ECDSA, we already broke at theAlg == maxAlg */
-                               assert(0);
-                               ourRtn = false;
-                               goto done;
-               }
-       }                       /* for each alg */
-done:
-       cuCspDetachUnload(cspHand, CSSM_TRUE);
-       return ourRtn;
-}
-
-/*
- * Guess an incoming blob's type, format and (for keys only) algorithm
- * by examining its contents. Returns true on success, in which case
- * *inputFormat, *itemType, and *keyAlg are all valid. Caller optionally
- * passes in valid values any number of these as a clue.
- */
-bool impExpImportGuessByExamination(
-       CFDataRef                       inData,
-       SecExternalFormat   *inputFormat,       // may be kSecFormatUnknown on entry
-       SecExternalItemType     *itemType,              // may be kSecItemTypeUnknown on entry
-       CSSM_ALGORITHMS         *keyAlg)                // CSSM_ALGID_NONE - unknown
-{
-       if( ( (*inputFormat == kSecFormatUnknown) ||
-             (*inputFormat == kSecFormatX509Cert)
-               ) &&
-          ( (*itemType == kSecItemTypeUnknown) ||
-                (*itemType == kSecItemTypeCertificate) ) ) {
-               /*
-                * See if it parses as a cert
-                */
-               CSSM_CL_HANDLE clHand = cuClStartup();
-               if(clHand == 0) {
-                       return CSSMERR_CSSM_ADDIN_LOAD_FAILED;
-               }
-               CSSM_HANDLE cacheHand;
-               CSSM_RETURN crtn;
-               CSSM_DATA cdata = { CFDataGetLength(inData),
-                                                   (uint8 *)CFDataGetBytePtr(inData) };
-               crtn = CSSM_CL_CertCache(clHand, &cdata, &cacheHand);
-               bool brtn = false;
-               if(crtn == CSSM_OK) {
-                       *inputFormat = kSecFormatX509Cert;
-                       *itemType = kSecItemTypeCertificate;
-                       SecImpInferDbg("Inferred kSecFormatX509Cert via CL");
-                       CSSM_CL_CertAbortCache(clHand, cacheHand);
-                       brtn = true;
-               }
-               cuClDetachUnload(clHand);
-               if(brtn) {
-                       return true;
-               }
-       }
-       /* TBD: need way to inquire of P12 lib if this is a valid-looking PFX */
-
-       if( ( (*inputFormat == kSecFormatUnknown) ||
-             (*inputFormat == kSecFormatNetscapeCertSequence)
-               ) &&
-          ( (*itemType == kSecItemTypeUnknown) ||
-                (*itemType == kSecItemTypeAggregate) ) ) {
-               /* See if it's a netscape cert sequence */
-               CSSM_RETURN crtn = impExpNetscapeCertImport(inData, 0, NULL, NULL, NULL);
-               if(crtn == CSSM_OK) {
-                       *inputFormat = kSecFormatNetscapeCertSequence;
-                       *itemType = kSecItemTypeAggregate;
-                       SecImpInferDbg("Inferred netscape-cert-sequence by decoding");
-                       return true;
-               }
-       }
-
-       /* See if it's a key */
-       return impExpGuessKeyParams(inData, inputFormat, itemType, keyAlg);
-}
-
-#pragma mark --- Key Import support ---
-
-/*
- * Given a context specified via a CSSM_CC_HANDLE, add a new
- * CSSM_CONTEXT_ATTRIBUTE to the context as specified by AttributeType,
- * AttributeLength, and an untyped pointer.
- */
-CSSM_RETURN impExpAddContextAttribute(CSSM_CC_HANDLE CCHandle,
-       uint32 AttributeType,
-       uint32 AttributeLength,
-       const void *AttributePtr)
-{
-       CSSM_CONTEXT_ATTRIBUTE          newAttr;
-
-       newAttr.AttributeType     = AttributeType;
-       newAttr.AttributeLength   = AttributeLength;
-       newAttr.Attribute.Data    = (CSSM_DATA_PTR)AttributePtr;
-       return CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
-}
-
-/*
- * 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);
-}
-
-/*
- * Calculate digest of any CSSM_KEY. Unlike older implementations
- * of this logic, you can actually calculate the public key hash
- * on any class of key, any format, raw CSP or CSPDL (though if
- * you're using the CSPDL, the key has to be a reference key
- * in that CSPDL session).
- *
- * Caller must free keyDigest->Data using impExpFreeCssmMemory() since
- * this is allocated by the CSP's app-specified allocator.
- */
-CSSM_RETURN impExpKeyDigest(
-       CSSM_CSP_HANDLE cspHand,
-       CSSM_KEY_PTR    key,
-       CSSM_DATA_PTR   keyDigest)              // contents allocd and RETURNED
-{
-       CSSM_DATA_PTR   localDigest;
-       CSSM_CC_HANDLE  ccHand;
-
-       CSSM_RETURN crtn = CSSM_CSP_CreatePassThroughContext(cspHand,
-               key,
-               &ccHand);
-       if(crtn) {
-               return crtn;
-       }
-       crtn = CSSM_CSP_PassThrough(ccHand,
-               CSSM_APPLECSP_KEYDIGEST,
-               NULL,
-               (void **)&localDigest);
-       if(crtn) {
-               SecImpExpDbg("CSSM_CSP_PassThrough(KEY_DIGEST) failure");
-       }
-       else {
-               /*
-                * Give caller the Data referent and we'll free the
-                * CSSM_DATA struct itswelf.
-                */
-               *keyDigest = *localDigest;
-               impExpFreeCssmMemory(cspHand, localDigest);
-       }
-       CSSM_DeleteContext(ccHand);
-       return crtn;
-}
-
-
-/*
- * Given a CFTypeRef passphrase which may be a CFDataRef or a CFStringRef,
- * return a refcounted CFStringRef suitable for use with the PKCS12 library.
- * PKCS12 passphrases in CFData format must be UTF8 encoded.
- */
-OSStatus impExpPassphraseToCFString(
-       CFTypeRef   passin,
-       CFStringRef *passout)   // may be the same as passin, but refcounted
-{
-       if(CFGetTypeID(passin) == CFStringGetTypeID()) {
-               CFStringRef passInStr = (CFStringRef)passin;
-               CFRetain(passInStr);
-               *passout = passInStr;
-               return errSecSuccess;
-       }
-       else if(CFGetTypeID(passin) == CFDataGetTypeID()) {
-               CFDataRef cfData = (CFDataRef)passin;
-               CFIndex len = CFDataGetLength(cfData);
-               CFStringRef cfStr = CFStringCreateWithBytes(NULL,
-                       CFDataGetBytePtr(cfData), len, kCFStringEncodingUTF8, true);
-               if(cfStr == NULL) {
-                       SecImpExpDbg("Passphrase not in UTF8 format");
-                       return errSecParam;
-               }
-               *passout = cfStr;
-               return errSecSuccess;
-       }
-       else {
-               SecImpExpDbg("Passphrase not CFData or CFString");
-               return errSecParam;
-       }
-}
-
-/*
- * Given a CFTypeRef passphrase which may be a CFDataRef or a CFStringRef,
- * return a refcounted CFDataRef whose bytes are suitable for use with
- * PKCS5 (v1.5 and v2.0) key derivation.
- */
-OSStatus impExpPassphraseToCFData(
-       CFTypeRef   passin,
-       CFDataRef   *passout)   // may be the same as passin, but refcounted
-{
-       if(CFGetTypeID(passin) == CFDataGetTypeID()) {
-               CFDataRef passInData = (CFDataRef)passin;
-               CFRetain(passInData);
-               *passout = passInData;
-               return errSecSuccess;
-       }
-       else if(CFGetTypeID(passin) == CFStringGetTypeID()) {
-               CFStringRef passInStr = (CFStringRef)passin;
-               CFDataRef outData;
-               outData = CFStringCreateExternalRepresentation(NULL,
-                       passInStr,
-                       kCFStringEncodingUTF8,
-                       0);             // lossByte 0 ==> no loss allowed
-               if(outData == NULL) {
-                       /* Well try with lossy conversion */
-                       SecImpExpDbg("Trying lossy conversion of CFString passphrase to UTF8");
-                       outData = CFStringCreateExternalRepresentation(NULL,
-                               passInStr,
-                               kCFStringEncodingUTF8,
-                               1);
-                       if(outData == NULL) {
-                               SecImpExpDbg("Failure on conversion of CFString passphrase to UTF8");
-                               /* what do we do now, Batman? */
-                               return errSecParam;
-                       }
-               }
-               *passout = outData;
-               return errSecSuccess;
-       }
-       else {
-               SecImpExpDbg("Passphrase not CFData or CFString");
-               return errSecParam;
-       }
-}
-
-/*
-* Add a CFString to a crypto context handle.
-*/
-static CSSM_RETURN impExpAddStringAttr(
-       CSSM_CC_HANDLE ccHand,
-       CFStringRef str,
-       CSSM_ATTRIBUTE_TYPE attrType)
-{
-       /* CFStrings are passed as external rep in UTF8 encoding by convention */
-       CFDataRef outData;
-       outData = CFStringCreateExternalRepresentation(NULL,
-               str, kCFStringEncodingUTF8,     0);             // lossByte 0 ==> no loss allowed
-       if(outData == NULL) {
-               SecImpExpDbg("impExpAddStringAttr: bad string format");
-               return errSecParam;
-       }
-
-       CSSM_DATA attrData;
-       attrData.Data = (uint8 *)CFDataGetBytePtr(outData);
-       attrData.Length = CFDataGetLength(outData);
-       CSSM_RETURN crtn = impExpAddContextAttribute(ccHand, attrType, sizeof(CSSM_DATA),
-               &attrData);
-       CFRelease(outData);
-       if(crtn) {
-               SecImpExpDbg("impExpAddStringAttr: CSSM_UpdateContextAttributes error");
-       }
-       return crtn;
-}
-
-/*
- * Generate a secure passphrase key. Caller must eventually CSSM_FreeKey the result.
- */
-static CSSM_RETURN impExpCreatePassKey(
-       const SecKeyImportExportParameters *keyParams,  // required
-       CSSM_CSP_HANDLE         cspHand,                // MUST be CSPDL
-       impExpVerifyPhrase      verifyPhrase,   // for secure passphrase
-       CSSM_KEY_PTR            *passKey)               // mallocd and RETURNED
-{
-       CSSM_RETURN crtn;
-       CSSM_CC_HANDLE ccHand;
-       uint32 verifyAttr;
-       CSSM_DATA dummyLabel;
-       CSSM_KEY_PTR ourKey = NULL;
-
-       SecImpExpDbg("Generating secure passphrase key");
-       ourKey = (CSSM_KEY_PTR)malloc(sizeof(CSSM_KEY));
-       if(ourKey == NULL) {
-               return errSecAllocate;
-       }
-       memset(ourKey, 0, sizeof(CSSM_KEY));
-
-       crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
-               CSSM_ALGID_SECURE_PASSPHRASE,
-               4,                              // keySizeInBits must be non zero
-               NULL,                   // Seed
-               NULL,                   // Salt
-               NULL,                   // StartDate
-               NULL,                   // EndDate
-               NULL,                   // Params
-               &ccHand);
-       if(crtn) {
-               SecImpExpDbg("impExpCreatePassKey: CSSM_CSP_CreateKeyGenContext error");
-               return crtn;
-       }
-       /* subsequent errors to errOut: */
-
-       /* additional context attributes specific to this type of key gen */
-       assert(keyParams != NULL);                      // or we wouldn't be here
-       if(keyParams->alertTitle != NULL) {
-               crtn = impExpAddStringAttr(ccHand, keyParams->alertTitle,
-                       CSSM_ATTRIBUTE_ALERT_TITLE);
-               if(crtn) {
-                       goto errOut;
-               }
-       }
-       if(keyParams->alertPrompt != NULL) {
-               crtn = impExpAddStringAttr(ccHand, keyParams->alertPrompt,
-                       CSSM_ATTRIBUTE_PROMPT);
-               if(crtn) {
-                       goto errOut;
-               }
-       }
-       verifyAttr = (verifyPhrase == VP_Export) ? 1 : 0;
-       crtn = impExpAddContextAttribute(ccHand, CSSM_ATTRIBUTE_VERIFY_PASSPHRASE,
-               sizeof(uint32), (const void *)((size_t) verifyAttr));
-       if(crtn) {
-               SecImpExpDbg("impExpCreatePassKey: CSSM_UpdateContextAttributes error");
-               goto errOut;
-       }
-
-       dummyLabel.Data = (uint8 *)"Secure Passphrase";
-       dummyLabel.Length = strlen((char *)dummyLabel.Data);
-
-       crtn = CSSM_GenerateKey(ccHand,
-               CSSM_KEYUSE_ANY,
-               CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_SENSITIVE,
-               &dummyLabel,
-               NULL,                   // ACL
-               ourKey);
-       if(crtn) {
-               SecImpExpDbg("impExpCreatePassKey: CSSM_GenerateKey error");
-       }
-errOut:
-       CSSM_DeleteContext(ccHand);
-       if(crtn == CSSM_OK) {
-               *passKey = ourKey;
-       }
-       else if(ourKey != NULL) {
-               free(ourKey);
-       }
-       return crtn;
-}
-
-/*
- * Obtain passphrase, given a SecKeyImportExportParameters.
- *
- * Passphrase comes from one of two places: app-specified, in
- * SecKeyImportExportParameters.passphrase (either as CFStringRef
- * or CFDataRef); or via the secure passphrase mechanism.
- *
- * Passphrase is returned in AT MOST one of two forms:
- *
- * -- Secure passphrase is returned as a CSSM_KEY_PTR, which the
- *    caller must CSSM_FreeKey later as well as free()ing the actual
- *    CSSM_KEY_PTR.
- * -- CFTypeRef for app-supplied passphrases. This can be one of
- *    two types:
- *
- *    -- CFStringRef, for use with P12
- *    -- CFDataRef, for more general use (e.g. for PKCS5).
- *
- *    In either case the caller must CFRelease the result.
- */
-OSStatus impExpPassphraseCommon(
-       const SecKeyImportExportParameters *keyParams,
-       CSSM_CSP_HANDLE                 cspHand,                // MUST be CSPDL, for passKey generation
-       impExpPassphraseForm    phraseForm,
-       impExpVerifyPhrase              verifyPhrase,   // for secure passphrase
-       CFTypeRef                               *phrase,                // RETURNED, or
-       CSSM_KEY_PTR                    *passKey)               // mallocd and RETURNED
-{
-       assert(keyParams != NULL);
-
-       /* Give precedence to secure passphrase */
-       if(keyParams->flags & kSecKeySecurePassphrase) {
-               assert(passKey != NULL);
-               return impExpCreatePassKey(keyParams, cspHand, verifyPhrase, passKey);
-       }
-       else if(keyParams->passphrase != NULL) {
-               CFTypeRef phraseOut;
-               OSStatus ortn;
-               assert(phrase != NULL);
-               switch(phraseForm) {
-                       case SPF_String:
-                               ortn = impExpPassphraseToCFString(keyParams->passphrase,
-                                       (CFStringRef *)&phraseOut);
-                               break;
-                       case SPF_Data:
-                               ortn = impExpPassphraseToCFData(keyParams->passphrase,
-                                       (CFDataRef *)&phraseOut);
-                               break;
-                       default:
-                               /* only called internally */
-                               assert(0);
-                               ortn = errSecParam;
-               }
-               if(ortn == errSecSuccess) {
-                       *phrase = phraseOut;
-               }
-               return ortn;
-       }
-       else {
-               return errSecPassphraseRequired;
-       }
-}
-
-static void ToggleKeyAttribute(
-       CFArrayRef keyAttrs,
-       CFTypeRef attr,
-       CSSM_KEYATTR_FLAGS mask,
-       CSSM_KEYATTR_FLAGS &result)
-{
-       // If the keyAttrs array contains the given attribute,
-       // set the corresponding keyattr flags, otherwise clear them.
-       // (Note: caller verifies that keyAttrs is not NULL.)
-       CFIndex numItems = CFArrayGetCount(keyAttrs);
-       result &= ~(mask);
-       if (numItems > 0) {
-               CFRange range = CFRangeMake(0, numItems);
-               if (CFArrayContainsValue(keyAttrs, range, attr))
-                       result |= mask;
-       }
-}
-
-CSSM_KEYATTR_FLAGS ConvertArrayToKeyAttributes(SecKeyRef aKey, CFArrayRef keyAttrs)
-{
-       CSSM_KEYATTR_FLAGS result = CSSM_KEYATTR_RETURN_DEFAULT;
-
-       if (aKey) {
-               const CSSM_KEY* cssmKey = NULL;
-               if (errSecSuccess == SecKeyGetCSSMKey(aKey, &cssmKey))
-                       result = cssmKey->KeyHeader.KeyAttr;
-       }
-
-       if (!keyAttrs)
-               return result;
-
-       CFMutableArrayRef attrs = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks);
-       CFIndex idx, count = CFArrayGetCount(keyAttrs);
-       for (idx=0; idx<count; idx++) {
-               CFTypeRef attr = (CFTypeRef) CFArrayGetValueAtIndex(keyAttrs, idx);
-               if (attr && (CFNumberGetTypeID() == CFGetTypeID(attr))) {
-                       // Convert numeric CSSM keyattr values to equivalent attribute constants
-                       uint32 value;
-                       if (CFNumberGetValue((CFNumberRef)attr, kCFNumberSInt32Type, &value)) {
-                               switch (value) {
-                                       case CSSM_KEYATTR_SENSITIVE:
-                                               attr = kSecAttrIsSensitive;
-                                               break;
-                                       case CSSM_KEYATTR_EXTRACTABLE:
-                                               attr = kSecAttrIsExtractable;
-                                               break;
-                                       case CSSM_KEYATTR_PERMANENT:
-                                               attr = kSecAttrIsPermanent;
-                                               break;
-                                       default:
-                                               attr = NULL;
-                                               break;
-                               }
-                       }
-               }
-               if (attr)
-                       CFArrayAppendValue(attrs, attr);
-       }
-
-       // Set key attribute flag in result if present in the array, otherwise clear
-       ToggleKeyAttribute(attrs, kSecAttrIsSensitive, CSSM_KEYATTR_SENSITIVE, result);
-       ToggleKeyAttribute(attrs, kSecAttrIsExtractable, CSSM_KEYATTR_EXTRACTABLE, result);
-       ToggleKeyAttribute(attrs, kSecAttrIsPermanent, CSSM_KEYATTR_PERMANENT, result);
-
-       // if caller specified an attributes array which omitted kSecAttrIsExtractable,
-       // this implies the sensitive attribute; force it on so that at least one bit
-       // is set. If our result is 0, this is indistinguishable from the case where
-       // no key attributes were specified, causing a default bitmask to be used
-       // in subsequent import code.
-
-       if (0==(result & CSSM_KEYATTR_EXTRACTABLE))
-               result |= CSSM_KEYATTR_SENSITIVE;
-
-       CFRelease(attrs);
-       return result;
-}
-
-Boolean ConvertSecKeyImportExportParametersToSecImportExportKeyParameters(SecKeyRef aKey,
-       const SecItemImportExportKeyParameters* newPtr, SecKeyImportExportParameters* oldPtr)
-{
-       Boolean result = false;
-
-       if (NULL != oldPtr && NULL != newPtr)
-       {
-               oldPtr->version = newPtr->version;
-               oldPtr->flags = newPtr->flags;
-               oldPtr->passphrase = newPtr->passphrase;
-               oldPtr->alertTitle = newPtr->alertTitle;
-               oldPtr->alertPrompt = newPtr->alertPrompt;
-               oldPtr->accessRef = newPtr->accessRef;
-               oldPtr->keyUsage = ConvertArrayToKeyUsage(newPtr->keyUsage);
-               oldPtr->keyAttributes = ConvertArrayToKeyAttributes(aKey, newPtr->keyAttributes);
-               result = true;
-       }
-       return result;
-}
-