+++ /dev/null
-/*
- * Copyright (c) 2003-2004 Apple Computer, 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@
- */
-
-/*
- * pkcs12Utils.cpp
- */
-
-#include "pkcs12Utils.h"
-#include <string.h>
-#include "pkcs7Templates.h"
-#include "pkcs12Templates.h"
-#include "pkcs12Crypto.h"
-#include "pkcs12Debug.h"
-#include <security_asn1/nssUtils.h>
-#include <Security/secasn1t.h>
-#include <security_utilities/devrandom.h>
-#include <security_utilities/errors.h>
-#include <security_cdsa_utils/cuCdsaUtils.h>
-#include <Security/oidsattr.h>
-#include <Security/oidsalg.h>
-#include <Security/cssmapple.h>
-
-/* malloc a NULL-ed array of pointers of size num+1 */
-void **p12NssNullArray(
- uint32 num,
- SecNssCoder &coder)
-{
- unsigned len = (num + 1) * sizeof(void *);
- void **p = (void **)coder.malloc(len);
- memset(p, 0, len);
- return p;
-}
-
-/* CSSM_DATA --> uint32. Returns true if OK. */
-bool p12DataToInt(
- const CSSM_DATA &cdata,
- uint32 &u)
-{
- if((cdata.Length == 0) || (cdata.Data == NULL)) {
- /* default/not present */
- u = 0;
- return true;
- }
- CSSM_SIZE len = cdata.Length;
- if(len > sizeof(uint32)) {
- return false;
- }
-
- uint32 rtn = 0;
- uint8 *cp = cdata.Data;
- for(uint32 i=0; i<len; i++) {
- rtn = (rtn << 8) | *cp++;
- }
- u = rtn;
- return true;
-}
-
-/* uint32 --> CSSM_DATA */
-void p12IntToData(
- uint32 num,
- CSSM_DATA &cdata,
- SecNssCoder &coder)
-{
- uint32 len = 0;
-
- if(num < 0x100) {
- len = 1;
- }
- else if(num < 0x10000) {
- len = 2;
- }
- else if(num < 0x1000000) {
- len = 3;
- }
- else {
- len = 4;
- }
- coder.allocItem(cdata, len);
- uint8 *cp = &cdata.Data[len - 1];
- for(unsigned i=0; i<len; i++) {
- *cp-- = num & 0xff;
- num >>= 8;
- }
-}
-
-/* CFDataRef <--> CSSM_DATA */
-CFDataRef p12CssmDataToCf(
- const CSSM_DATA &c)
-{
- return CFDataCreate(NULL, c.Data, c.Length);
-}
-
-void p12CfDataToCssm(
- CFDataRef cf,
- CSSM_DATA &c,
- SecNssCoder &coder)
-{
- coder.allocCopyItem(CFDataGetBytePtr(cf),
- CFDataGetLength(cf), c);
-}
-
-/*
- * Attempt to convert a CFStringRef, which represents a SafeBag's
- * FriendlyName, to a UTF8-encoded CSSM_DATA. The CSSM_DATA and its
- * referent are allocated in the specified SecNssCoder's memory.
- * No guarantee that this conversion works. If it doesn't we return
- * NULL and caller must be prepared to deal with that.
- */
-CSSM_DATA_PTR p12StringToUtf8(
- CFStringRef cfStr,
- SecNssCoder &coder)
-{
- if(cfStr == NULL) {
- return NULL;
- }
- CFIndex strLen = CFStringGetLength(cfStr);
- if(strLen == 0) {
- return NULL;
- }
- CSSM_DATA_PTR rtn = coder.mallocn<CSSM_DATA>();
- coder.allocItem(*rtn, strLen + 1);
- if(!CFStringGetCString(cfStr, (char *)rtn->Data,strLen + 1,
- kCFStringEncodingUTF8)) {
- /* not convertible from native Unicode to UTF8 */
- return NULL;
- }
- return rtn;
-}
-
-/*
- * Enum to string mappper.
- * Maybe DEBUG only.
- */
-/*
- * Each type of attribute has a name/value pair in a table of these:
- */
-typedef struct {
- unsigned value;
- const char *name;
-} p12NameValuePair;
-
-/* declare one entry in a table of p12NameValuePair */
-#define NVP(attr) {attr, #attr}
-
-/* the NULL entry which terminates all p12NameValuePair tables */
-#define NVP_END {0, NULL}
-
-static const p12NameValuePair p7CITypeNames[] =
-{
- NVP(CT_None),
- NVP(CT_Data),
- NVP(CT_SignedData),
- NVP(CT_EnvData),
- NVP(CT_SignedEnvData),
- NVP(CT_DigestData),
- NVP(CT_EncryptedData),
- NVP_END
-};
-
-static const p12NameValuePair p12BagTypeNames[] =
-{
- NVP(BT_None),
- NVP(BT_KeyBag),
- NVP(BT_ShroudedKeyBag),
- NVP(BT_CertBag),
- NVP(BT_CrlBag),
- NVP(BT_SecretBag),
- NVP(BT_SafeContentsBag),
- NVP_END
-};
-
-static const char *typeToStr(
- unsigned type,
- const p12NameValuePair *table)
-{
- while(table->name) {
- if(table->value == type) {
- return table->name;
- }
- table++;
- }
- return "Unknown";
-}
-
-const char *p12BagTypeStr(
- NSS_P12_SB_Type type)
-{
- return typeToStr(type, p12BagTypeNames);
-}
-
-const char *p7ContentInfoTypeStr(
- NSS_P7_CI_Type type)
-{
- return typeToStr(type, p7CITypeNames);
-}
-
-/*
- * OIDS for P12 and PKCS5 v1.5 (PBES1) encrypt and decrypt map to the following
- * attributes.
- */
-typedef struct {
- const CSSM_OID *oid;
- CSSM_ALGORITHMS keyAlg; // e.g., CSSM_ALGID_DES
- CSSM_ALGORITHMS encrAlg; // e.g., CSSM_ALGID_3DES_3KEY_EDE
- CSSM_ALGORITHMS pbeHashAlg; // SHA1 or MD5
- uint32 keySizeInBits;
- uint32 blockSizeInBytes; // for IV, optional
- CSSM_PADDING padding; // CSSM_PADDING_PKCS7, etc.
- CSSM_ENCRYPT_MODE mode; // CSSM_ALGMODE_CBCPadIV8, etc.
- PKCS_Which pkcs; // PW_PKCS12 (for this module) or PW_PKCS5_v1_5
-} PKCSOidInfo;
-
-static const PKCSOidInfo pkcsOidInfos[] = {
- /* PKCS12 first, the ones this module uses */
- {
- &CSSMOID_PKCS12_pbeWithSHAAnd128BitRC4,
- CSSM_ALGID_RC4,
- CSSM_ALGID_RC4,
- CSSM_ALGID_SHA1,
- 128,
- 0, // RC4 is a stream cipher
- CSSM_PADDING_NONE,
- CSSM_ALGMODE_NONE,
- PW_PKCS12
- },
- {
- &CSSMOID_PKCS12_pbeWithSHAAnd40BitRC4,
- CSSM_ALGID_RC4,
- CSSM_ALGID_RC4,
- CSSM_ALGID_SHA1,
- 40,
- 0, // RC4 is a stream cipher
- CSSM_PADDING_NONE,
- CSSM_ALGMODE_NONE,
- PW_PKCS12
- },
- {
- &CSSMOID_PKCS12_pbeWithSHAAnd3Key3DESCBC,
- CSSM_ALGID_3DES_3KEY,
- CSSM_ALGID_3DES_3KEY_EDE,
- CSSM_ALGID_SHA1,
- 64 * 3,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS12
- },
- {
- &CSSMOID_PKCS12_pbeWithSHAAnd2Key3DESCBC,
- CSSM_ALGID_3DES_2KEY,
- CSSM_ALGID_3DES_2KEY_EDE,
- CSSM_ALGID_SHA1,
- 64 * 2,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS12
- },
- {
- &CSSMOID_PKCS12_pbeWithSHAAnd128BitRC2CBC,
- CSSM_ALGID_RC2,
- CSSM_ALGID_RC2,
- CSSM_ALGID_SHA1,
- 128,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS12
- },
- {
- &CSSMOID_PKCS12_pbewithSHAAnd40BitRC2CBC,
- CSSM_ALGID_RC2,
- CSSM_ALGID_RC2,
- CSSM_ALGID_SHA1,
- 40,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS12
- },
-
- /* PKCS5 v1.5, used for SecImportExport module */
- {
- &CSSMOID_PKCS5_pbeWithMD2AndDES,
- CSSM_ALGID_DES,
- CSSM_ALGID_DES,
- CSSM_ALGID_MD2,
- 64,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS5_v1_5
- },
- {
- &CSSMOID_PKCS5_pbeWithMD2AndRC2,
- CSSM_ALGID_RC2,
- CSSM_ALGID_RC2,
- CSSM_ALGID_MD2,
- 64,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS5_v1_5
- },
- {
- &CSSMOID_PKCS5_pbeWithMD5AndDES,
- CSSM_ALGID_DES,
- CSSM_ALGID_DES,
- CSSM_ALGID_MD5,
- 64,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS5_v1_5
- },
- {
- &CSSMOID_PKCS5_pbeWithMD5AndRC2,
- CSSM_ALGID_RC2,
- CSSM_ALGID_RC2,
- CSSM_ALGID_MD5,
- 64,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS5_v1_5
- },
- {
- &CSSMOID_PKCS5_pbeWithSHA1AndDES,
- CSSM_ALGID_DES,
- CSSM_ALGID_DES,
- CSSM_ALGID_SHA1,
- 64,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS5_v1_5
- },
- {
- &CSSMOID_PKCS5_pbeWithSHA1AndRC2,
- CSSM_ALGID_RC2,
- CSSM_ALGID_RC2,
- CSSM_ALGID_SHA1,
- 64,
- 8,
- CSSM_PADDING_PKCS7,
- CSSM_ALGMODE_CBCPadIV8,
- PW_PKCS5_v1_5
- },
-
- /* finally one for PKCS5 v2.0, which has its own means of
- * cooking up all the parameters */
- {
- &CSSMOID_PKCS5_PBES2,
- CSSM_ALGID_NONE,
- CSSM_ALGID_NONE,
- CSSM_ALGID_NONE,
- 0, 0, 0, 0,
- PW_PKCS5_v2
- }
-};
-
-#define NUM_PKCS_OID_INFOS (sizeof(pkcsOidInfos) / sizeof(pkcsOidInfos[1]))
-
-/* map an OID to the components */
-/* returns false if OID not found */
-
-/*
- * NOTE: as of March 8 2004 this is also used by the SecImportExport
- * module...not just PKCS12!
- */
-bool pkcsOidToParams(
- const CSSM_OID *oid,
- CSSM_ALGORITHMS &keyAlg, // e.g., CSSM_ALGID_DES
- CSSM_ALGORITHMS &encrAlg, // e.g., CSSM_ALGID_3DES_3KEY_EDE
- CSSM_ALGORITHMS &pbeHashAlg, // SHA1 or MD5
- uint32 &keySizeInBits,
- uint32 &blockSizeInBytes, // for IV, optional
- CSSM_PADDING &padding, // CSSM_PADDING_PKCS7, etc.
- CSSM_ENCRYPT_MODE &mode, // CSSM_ALGMODE_CBCPadIV8, etc.
- PKCS_Which &pkcs) // PW_PKCS5_v1_5 or PW_PKCS12
-{
- const PKCSOidInfo *info = pkcsOidInfos;
- pkcs = PW_None;
-
- for(unsigned dex=0; dex<NUM_PKCS_OID_INFOS; dex++) {
- if(nssCompareCssmData(oid, info->oid)) {
- keyAlg = info->keyAlg;
- encrAlg = info->encrAlg;
- pbeHashAlg = info->pbeHashAlg;
- keySizeInBits = info->keySizeInBits;
- blockSizeInBytes = info->blockSizeInBytes;
- padding = info->padding;
- mode = info->mode;
- pkcs = info->pkcs;
- return true;
- }
- info++;
- }
- return false;
-}
-
-/*
- * Verify MAC on an existing PFX.
- */
-CSSM_RETURN p12VerifyMac(
- const NSS_P12_DecodedPFX &pfx,
- CSSM_CSP_HANDLE cspHand,
- const CSSM_DATA *pwd, // unicode, double null terminated
- const CSSM_KEY *passKey,
- SecNssCoder &coder) // for temp mallocs
-{
- if(pfx.macData == NULL) {
- return CSSMERR_CSP_INVALID_SIGNATURE;
- }
- NSS_P12_MacData &macData = *pfx.macData;
- NSS_P7_DigestInfo &digestInfo = macData.mac;
- CSSM_OID &algOid = digestInfo.digestAlgorithm.algorithm;
- CSSM_ALGORITHMS macAlg;
- if(!cssmOidToAlg(&algOid, &macAlg)) {
- return CSSMERR_CSP_INVALID_ALGORITHM;
- }
- uint32 iterCount = 0;
- CSSM_DATA &citer = macData.iterations;
- if(!p12DataToInt(citer, iterCount)) {
- return CSSMERR_CSP_INVALID_ATTR_ROUNDS;
- }
- if(iterCount == 0) {
- /* optional, default 1 */
- iterCount = 1;
- }
-
- /*
- * In classic fashion, the PKCS12 spec now says:
- *
- * When password integrity mode is used to secure a PFX PDU,
- * an SHA-1 HMAC is computed on the BER-encoding of the contents
- * of the content field of the authSafe field in the PFX PDU.
- *
- * So here we go.
- */
- CSSM_DATA genMac;
- CSSM_RETURN crtn = p12GenMac(cspHand, *pfx.authSafe.content.data,
- macAlg, iterCount, macData.macSalt, pwd, passKey, coder, genMac);
- if(crtn) {
- return crtn;
- }
- if(nssCompareCssmData(&genMac, &digestInfo.digest)) {
- return CSSM_OK;
- }
- else {
- return CSSMERR_CSP_VERIFY_FAILED;
- }
-}
-
-/* we generate 8 random bytes of salt */
-#define P12_SALT_LEN 8
-
-void p12GenSalt(
- CSSM_DATA &salt,
- SecNssCoder &coder)
-{
- DevRandomGenerator rng;
- coder.allocItem(salt, P12_SALT_LEN);
- rng.random(salt.Data, P12_SALT_LEN);
-}
-
-/*
- * Generate random label string to allow associating an imported private
- * key with a cert.
- */
-void p12GenLabel(
- CSSM_DATA &label,
- SecNssCoder &coder)
-{
- /* first a random uint32 */
- uint8 d[4];
- DevRandomGenerator rng;
- rng.random(d, 4);
- CSSM_DATA cd = {4, d};
- uint32 i;
- p12DataToInt(cd, i);
-
- /* sprintf that into a real string */
- coder.allocItem(label, 9);
- memset(label.Data, 0, 9);
- sprintf((char *)label.Data, "%08X", (unsigned)i);
-}
-
-/* NULL algorithm parameters */
-
-static const uint8 nullAlg[2] = {SEC_ASN1_NULL, 0};
-
-void p12NullAlgParams(
- CSSM_X509_ALGORITHM_IDENTIFIER &algId)
-{
- CSSM_DATA &p = algId.parameters;
- p.Data = (uint8 *)nullAlg;
- p.Length = 2;
-}
-
-/*
- * Free memory via specified plugin's app-level allocator
- */
-void freeCssmMemory(
- CSSM_HANDLE hand,
- void *p)
-{
- CSSM_API_MEMORY_FUNCS memFuncs;
- CSSM_RETURN crtn = CSSM_GetAPIMemoryFunctions(hand, &memFuncs);
- if(crtn) {
- p12LogCssmError("CSSM_GetAPIMemoryFunctions", crtn);
- /* oh well, leak and continue */
- return;
- }
- memFuncs.free_func(p, memFuncs.AllocRef);
-}
-
-/*
- * Find private key by label, modify its Label attr to be the
- * hash of the associated public key.
- * Also optionally re-sets the key's PrintName attribute; used to reset
- * this attr from the random label we create when first unwrap it
- * to the friendly name we find later after parsing attributes.
- * Detection of a duplicate key when updating the key's attributes
- * results in a lookup of the original key and returning it in
- * foundKey.
- */
-CSSM_RETURN p12SetPubKeyHash(
- CSSM_CSP_HANDLE cspHand, // where the key lives
- CSSM_DL_DB_HANDLE dlDbHand, // ditto
- CSSM_DATA &keyLabel, // for DB lookup
- CSSM_DATA_PTR newPrintName, // optional
- SecNssCoder &coder, // for mallocing newLabel
- CSSM_DATA &newLabel, // RETURNED with label as hash
- CSSM_KEY_PTR &foundKey) // RETURNED
-{
- CSSM_QUERY query;
- CSSM_SELECTION_PREDICATE predicate;
- CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
- CSSM_RETURN crtn;
- CSSM_HANDLE resultHand = 0;
- CSSM_DATA keyData = {0, NULL};
- CSSM_CC_HANDLE ccHand = 0;
- CSSM_KEY_PTR privKey = NULL;
- CSSM_DATA_PTR keyDigest = NULL;
-
- assert(cspHand != 0);
- query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_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*) P12_KEY_ATTR_LABEL_AND_HASH;
- predicate.Attribute.Info.AttributeFormat =
- CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
- /* hope this cast is OK */
- predicate.Attribute.Value = &keyLabel;
- query.SelectionPredicate = &predicate;
-
- query.QueryLimits.TimeLimit = 0; // FIXME - meaningful?
- query.QueryLimits.SizeLimit = 1; // FIXME - meaningful?
- query.QueryFlags = CSSM_QUERY_RETURN_DATA;
-
- /* build Record attribute with one or 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*) P12_KEY_ATTR_LABEL_AND_HASH;
- attr[0].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
- if(newPrintName) {
- attr[1].Info.AttributeNameFormat = CSSM_DB_ATTRIBUTE_NAME_AS_STRING;
- attr[1].Info.Label.AttributeName = (char*) P12_KEY_ATTR_PRINT_NAME;
- attr[1].Info.AttributeFormat = CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
- }
- recordAttrs.DataRecordType = CSSM_DL_DB_RECORD_PRIVATE_KEY;
- recordAttrs.NumberOfAttributes = newPrintName ? 2 : 1;
- recordAttrs.AttributeData = attr;
-
- crtn = CSSM_DL_DataGetFirst(dlDbHand,
- &query,
- &resultHand,
- &recordAttrs,
- &keyData, // theData
- &record);
- /* abort only on success */
- if(crtn != CSSM_OK) {
- p12LogCssmError("CSSM_DL_DataGetFirst", crtn);
- p12ErrorLog("***p12SetPubKeyHash: can't find private key\n");
- return crtn;
- }
- /* subsequent errors to errOut: */
- if(keyData.Data == NULL) {
- p12ErrorLog("***p12SetPubKeyHash: private key lookup failure\n");
- crtn = CSSMERR_CSSM_INTERNAL_ERROR;
- goto errOut;
- }
- privKey = (CSSM_KEY_PTR)keyData.Data;
-
- /* public key hash via passthrough - works on any key, any CSP/CSPDL.... */
- /*
- * Warning! This relies on the current default ACL meaning "allow this
- * current app to access this private key" since we created the key.
- */
- crtn = CSSM_CSP_CreatePassThroughContext(cspHand, privKey, &ccHand);
- if(crtn) {
- p12LogCssmError("CSSM_CSP_CreatePassThroughContext", crtn);
- goto errOut;
- }
- crtn = CSSM_CSP_PassThrough(ccHand,
- CSSM_APPLECSP_KEYDIGEST,
- NULL,
- (void **)&keyDigest);
- if(crtn) {
- p12LogCssmError("CSSM_CSP_PassThrough", crtn);
- goto errOut;
- }
-
- /*
- * Replace Label attr data with hash.
- * NOTE: the module which allocated this attribute data - a DL -
- * was loaded and attached by out client 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.
- */
- freeCssmMemory(dlDbHand.DLHandle, attr[0].Value->Data);
- freeCssmMemory(dlDbHand.DLHandle, attr[0].Value);
- if(newPrintName) {
- freeCssmMemory(dlDbHand.DLHandle, attr[1].Value->Data);
- freeCssmMemory(dlDbHand.DLHandle, attr[1].Value);
- }
- /* modify key attributes */
- attr[0].Value = keyDigest;
- if(newPrintName) {
- attr[1].Value = newPrintName;
- }
- crtn = CSSM_DL_DataModify(dlDbHand,
- CSSM_DL_DB_RECORD_PRIVATE_KEY,
- record,
- &recordAttrs,
- NULL, // DataToBeModified
- CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
- switch(crtn) {
- case CSSM_OK:
- /* give caller the key's new label */
- coder.allocCopyItem(*keyDigest, newLabel);
- break;
- default:
- p12LogCssmError("CSSM_DL_DataModify", crtn);
- break;
- case CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA:
- {
- /*
- * Special case: dup private key. The label we just tried to modify is
- * the public key hash so we can be confident that this really is a dup.
- * Delete it, look up the original, and return the original to caller.
- */
- CSSM_RETURN drtn = CSSM_DL_DataDelete(dlDbHand, record);
- if(drtn) {
- p12LogCssmError("CSSM_DL_DataDelete on dup key", drtn);
- crtn = drtn;
- break;
- }
-
- /* Free items created in last search */
- CSSM_DL_DataAbortQuery(dlDbHand, resultHand);
- resultHand = 0;
- CSSM_DL_FreeUniqueRecord(dlDbHand, record);
- record = NULL;
-
- /* lookup by label as public key hash this time */
- predicate.Attribute.Value = keyDigest;
- drtn = CSSM_DL_DataGetFirst(dlDbHand,
- &query,
- &resultHand,
- NULL, // no attrs this time
- &keyData,
- &record);
- if(drtn) {
- p12LogCssmError("CSSM_DL_DataGetFirst on original key", crtn);
- crtn = drtn;
- break;
- }
- foundKey = (CSSM_KEY_PTR)keyData.Data;
- /* give caller the key's actual label */
- coder.allocCopyItem(*keyDigest, newLabel);
- break;
- }
- }
-
-errOut:
- /* free resources */
- if(resultHand) {
- CSSM_DL_DataAbortQuery(dlDbHand, resultHand);
- }
- if(record) {
- CSSM_DL_FreeUniqueRecord(dlDbHand, record);
- }
- if(ccHand) {
- CSSM_DeleteContext(ccHand);
- }
- if(privKey) {
- /* key created by the CSPDL */
- CSSM_FreeKey(cspHand, NULL, privKey, CSSM_FALSE);
- freeCssmMemory(dlDbHand.DLHandle, privKey);
- }
- if(keyDigest) {
- /* mallocd by someone else's CSP */
- freeCssmMemory(cspHand, keyDigest->Data);
- freeCssmMemory(cspHand, keyDigest);
- }
- return crtn;
-}
-
-/*
- * 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 p12AddContextAttribute(CSSM_CC_HANDLE CCHandle,
- uint32 AttributeType,
- uint32 AttributeLength,
- const void *AttributePtr)
-{
- CSSM_CONTEXT_ATTRIBUTE newAttr;
- CSSM_RETURN crtn;
-
- newAttr.AttributeType = AttributeType;
- newAttr.AttributeLength = AttributeLength;
- newAttr.Attribute.Data = (CSSM_DATA_PTR)AttributePtr;
- crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
- if(crtn) {
- p12LogCssmError("CSSM_UpdateContextAttributes", crtn);
- }
- return crtn;
-}
-
-/*
- * Find private key by specified label, delete it.
- */
-CSSM_RETURN p12DeleteKey(
- CSSM_DL_DB_HANDLE dlDbHand,
- const CSSM_DATA &keyLabel)
-{
- CSSM_QUERY query;
- CSSM_SELECTION_PREDICATE predicate;
- CSSM_DB_UNIQUE_RECORD_PTR record = NULL;
- CSSM_RETURN crtn;
- CSSM_HANDLE resultHand = 0;
-
- query.RecordType = CSSM_DL_DB_RECORD_PRIVATE_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*) P12_KEY_ATTR_LABEL_AND_HASH;
- predicate.Attribute.Info.AttributeFormat =
- CSSM_DB_ATTRIBUTE_FORMAT_BLOB;
- predicate.Attribute.Value = const_cast<CSSM_DATA_PTR>(&keyLabel);
-
- query.SelectionPredicate = &predicate;
- query.QueryLimits.TimeLimit = 0;
- query.QueryLimits.SizeLimit = 1;
- query.QueryFlags = 0;
-
- crtn = CSSM_DL_DataGetFirst(dlDbHand,
- &query,
- &resultHand,
- NULL, // attrs - don't need 'em
- NULL, // theData - don't need it
- &record);
- /* abort only on success */
- if(crtn) {
- p12LogCssmError("CSSM_DL_DataGetFirst", crtn);
- p12ErrorLog("***p12DeleteKey: can't find private key\n");
- return crtn;
- }
-
- crtn = CSSM_DL_DataDelete(dlDbHand, record);
- if(crtn) {
- p12LogCssmError("CSSM_DL_DataDelete", crtn);
- p12ErrorLog("***p12DeleteKey: can't delete private key\n");
- }
-
- CSSM_DL_DataAbortQuery(dlDbHand, resultHand);
- CSSM_DL_FreeUniqueRecord(dlDbHand, record);
- return crtn;
-}
-
-/* convert App passphrase to array of chars used in P12 PBE */
-void p12ImportPassPhrase(
- CFStringRef inPhrase,
- SecNssCoder &coder,
- CSSM_DATA &outPhrase)
-{
- CFDataRef cfData = CFStringCreateExternalRepresentation(NULL,
- inPhrase, kCFStringEncodingUTF8, 0);
- if(cfData == NULL) {
- p12ErrorLog("***p12ImportPassPhrase: can't convert passphrase to UTF8\n");
- MacOSError::throwMe(errSecParam);
- }
- CFIndex keyLen = CFDataGetLength(cfData);
- coder.allocItem(outPhrase, keyLen);
- memmove(outPhrase.Data, CFDataGetBytePtr(cfData), keyLen);
- CFRelease(cfData);
-}