SecImportExportUtils.cpp [plain text]
#include "SecImportExportUtils.h"
#include "SecImportExportAgg.h"
#include "SecImportExportCrypto.h"
#include "SecIdentityPriv.h"
#include "SecItem.h"
#include <security_cdsa_utils/cuCdsaUtils.h>
#include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.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
bool impExpImportParseFileExten(
CFStringRef fstr,
SecExternalFormat *inputFormat, SecExternalItemType *itemType) {
if(fstr == NULL) {
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;
}
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) {
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;
}
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 ---
typedef struct {
CSSM_KEYBLOB_FORMAT priv;
CSSM_KEYBLOB_FORMAT pub;
} algForms;
#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)
static algForms opensslAlgForms[SIE_NUM_ALGS] =
{
{ CSSM_KEYBLOB_RAW_FORMAT_PKCS1, CSSM_KEYBLOB_RAW_FORMAT_X509 }, { CSSM_KEYBLOB_RAW_FORMAT_OPENSSL, CSSM_KEYBLOB_RAW_FORMAT_X509 }, { CSSM_KEYBLOB_RAW_FORMAT_PKCS3, CSSM_KEYBLOB_RAW_FORMAT_X509 }, { CSSM_KEYBLOB_RAW_FORMAT_OPENSSL, CSSM_KEYBLOB_RAW_FORMAT_X509 }, };
static algForms bsafeAlgForms[SIE_NUM_ALGS] =
{
{ CSSM_KEYBLOB_RAW_FORMAT_PKCS8, CSSM_KEYBLOB_RAW_FORMAT_PKCS1 }, { CSSM_KEYBLOB_RAW_FORMAT_FIPS186, CSSM_KEYBLOB_RAW_FORMAT_FIPS186 }, { CSSM_KEYBLOB_RAW_FORMAT_PKCS8, CSSM_KEYBLOB_RAW_FORMAT_NONE }, { CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE }, };
static algForms ssh1AlgForms[SIE_NUM_ALGS] =
{
{ CSSM_KEYBLOB_RAW_FORMAT_OPENSSH, CSSM_KEYBLOB_RAW_FORMAT_OPENSSH }, { CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE }, { CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE }, { CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE }, };
static algForms ssh2AlgForms[SIE_NUM_ALGS] =
{
{ CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2 }, { CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_OPENSSH2 }, { CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE }, { CSSM_KEYBLOB_RAW_FORMAT_NONE, CSSM_KEYBLOB_RAW_FORMAT_NONE }, };
OSStatus impExpKeyForm(
SecExternalFormat externForm,
SecExternalItemType itemType,
CSSM_ALGORITHMS alg,
CSSM_KEYBLOB_FORMAT *cssmForm, CSSM_KEYCLASS *cssmClass) {
if(itemType == kSecItemTypeSessionKey) {
*cssmForm = CSSM_KEYBLOB_RAW_FORMAT_NONE;
*cssmClass = CSSM_KEYCLASS_SESSION_KEY;
return noErr;
}
if(externForm == kSecFormatUnknown) {
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) {
return errSecUnsupportedFormat;
}
else {
*cssmForm = form;
return noErr;
}
}
static bool impExpGuessKeyParams(
CFDataRef keyData,
SecExternalFormat *externForm, SecExternalItemType *itemType, CSSM_ALGORITHMS *keyAlg) {
CSSM_ALGORITHMS minAlg = CSSM_ALGID_RSA;
CSSM_ALGORITHMS maxAlg = CSSM_ALGID_ECDSA;
SecExternalFormat minForm = kSecFormatOpenSSL; SecExternalFormat maxForm = kSecFormatSSHv2;
SecExternalItemType minType = kSecItemTypePrivateKey; SecExternalItemType maxType = kSecItemTypePublicKey;
switch(*externForm) {
case kSecFormatUnknown:
break; case kSecFormatOpenSSL:
case kSecFormatSSH:
case kSecFormatSSHv2:
case kSecFormatBSAFE:
minForm = maxForm = *externForm; 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;
}
bool ourRtn = false;
for(theAlg=minAlg; ; ) {
for(theForm=minForm; ; ) {
for(theType=minType; ; ) {
OSStatus ortn = impExpImportRawKey(keyData,
theForm, theType, theAlg,
NULL, cspHand,
0, NULL, NULL, NULL); if(ortn == noErr) {
*externForm = theForm;
*itemType = theType;
*keyAlg = theAlg;
ourRtn = true;
goto done;
}
if(theType == maxType) {
break;
}
else switch(theType) {
case kSecItemTypePrivateKey:
theType = kSecItemTypePublicKey;
break;
default:
assert(0);
ourRtn = false;
goto 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;
}
}
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:
assert(0);
ourRtn = false;
goto done;
}
}
done:
cuCspDetachUnload(cspHand, CSSM_TRUE);
return ourRtn;
}
bool impExpImportGuessByExamination(
CFDataRef inData,
SecExternalFormat *inputFormat, SecExternalItemType *itemType, CSSM_ALGORITHMS *keyAlg) {
if( ( (*inputFormat == kSecFormatUnknown) ||
(*inputFormat == kSecFormatX509Cert)
) &&
( (*itemType == kSecItemTypeUnknown) ||
(*itemType == kSecItemTypeCertificate) ) ) {
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;
}
}
if( ( (*inputFormat == kSecFormatUnknown) ||
(*inputFormat == kSecFormatNetscapeCertSequence)
) &&
( (*itemType == kSecItemTypeUnknown) ||
(*itemType == kSecItemTypeAggregate) ) ) {
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;
}
}
return impExpGuessKeyParams(inData, inputFormat, itemType, keyAlg);
}
#pragma mark --- Key Import support ---
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);
}
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);
}
CSSM_RETURN impExpKeyDigest(
CSSM_CSP_HANDLE cspHand,
CSSM_KEY_PTR key,
CSSM_DATA_PTR keyDigest) {
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 {
*keyDigest = *localDigest;
impExpFreeCssmMemory(cspHand, localDigest);
}
CSSM_DeleteContext(ccHand);
return crtn;
}
OSStatus impExpPassphraseToCFString(
CFTypeRef passin,
CFStringRef *passout) {
if(CFGetTypeID(passin) == CFStringGetTypeID()) {
CFStringRef passInStr = (CFStringRef)passin;
CFRetain(passInStr);
*passout = passInStr;
return noErr;
}
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 paramErr;
}
*passout = cfStr;
return noErr;
}
else {
SecImpExpDbg("Passphrase not CFData or CFString");
return paramErr;
}
}
OSStatus impExpPassphraseToCFData(
CFTypeRef passin,
CFDataRef *passout) {
if(CFGetTypeID(passin) == CFDataGetTypeID()) {
CFDataRef passInData = (CFDataRef)passin;
CFRetain(passInData);
*passout = passInData;
return noErr;
}
else if(CFGetTypeID(passin) == CFStringGetTypeID()) {
CFStringRef passInStr = (CFStringRef)passin;
CFDataRef outData;
outData = CFStringCreateExternalRepresentation(NULL,
passInStr,
kCFStringEncodingUTF8,
0); if(outData == NULL) {
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");
return paramErr;
}
}
*passout = outData;
return noErr;
}
else {
SecImpExpDbg("Passphrase not CFData or CFString");
return paramErr;
}
}
static CSSM_RETURN impExpAddStringAttr(
CSSM_CC_HANDLE ccHand,
CFStringRef str,
CSSM_ATTRIBUTE_TYPE attrType)
{
CFDataRef outData;
outData = CFStringCreateExternalRepresentation(NULL,
str, kCFStringEncodingUTF8, 0); if(outData == NULL) {
SecImpExpDbg("impExpAddStringAttr: bad string format");
return paramErr;
}
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;
}
static CSSM_RETURN impExpCreatePassKey(
const SecKeyImportExportParameters *keyParams, CSSM_CSP_HANDLE cspHand, impExpVerifyPhrase verifyPhrase, CSSM_KEY_PTR *passKey) {
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 memFullErr;
}
memset(ourKey, 0, sizeof(CSSM_KEY));
crtn = CSSM_CSP_CreateKeyGenContext(cspHand,
CSSM_ALGID_SECURE_PASSPHRASE,
4, NULL, NULL, NULL, NULL, NULL, &ccHand);
if(crtn) {
SecImpExpDbg("impExpCreatePassKey: CSSM_CSP_CreateKeyGenContext error");
return crtn;
}
assert(keyParams != NULL); 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 *)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, 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;
}
OSStatus impExpPassphraseCommon(
const SecKeyImportExportParameters *keyParams,
CSSM_CSP_HANDLE cspHand, impExpPassphraseForm phraseForm,
impExpVerifyPhrase verifyPhrase, CFTypeRef *phrase, CSSM_KEY_PTR *passKey) {
assert(keyParams != NULL);
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:
assert(0);
ortn = paramErr;
}
if(ortn == noErr) {
*phrase = phraseOut;
}
return ortn;
}
else {
return errSecPassphraseRequired;
}
}
CSSM_KEYATTR_FLAGS ConvertArrayToKeyAttributes(SecKeyRef aKey, CFArrayRef usage)
{
CSSM_KEYATTR_FLAGS result = CSSM_KEYATTR_RETURN_DEFAULT;
if (NULL == aKey)
{
return result;
}
OSStatus err = noErr;
const CSSM_KEY* cssmKey = NULL;
err = SecKeyGetCSSMKey(aKey, &cssmKey);
if (noErr != err)
{
return result;
}
result = cssmKey->KeyHeader.KeyAttr;
if (NULL != usage)
{
CFTypeRef item = NULL;
CFIndex numItems = CFArrayGetCount(usage);
for (CFIndex iCnt = 0L; iCnt < numItems; iCnt++)
{
item = (CFTypeRef)CFArrayGetValueAtIndex(usage, iCnt);
if (CFEqual(item, kSecAttrIsPermanent))
{
result |= CSSM_KEYATTR_PERMANENT;
}
}
}
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;
}