X-Git-Url: https://git.saurik.com/apple/security.git/blobdiff_plain/5dd5f9ec28f304ca377c42fd7f711d6cf12b90e1..5c19dc3ae3bd8e40a9c028b0deddd50ff337692c:/Security/libsecurity_keychain/lib/SecImportExportCrypto.cpp?ds=inline diff --git a/Security/libsecurity_keychain/lib/SecImportExportCrypto.cpp b/Security/libsecurity_keychain/lib/SecImportExportCrypto.cpp deleted file mode 100644 index 71a4b315..00000000 --- a/Security/libsecurity_keychain/lib/SecImportExportCrypto.cpp +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Copyright (c) 2000-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@ - */ -/* - * SecImportExportCrypto.cpp - low-level crypto routines for wrapping and unwrapping - * keys. - */ - -#include "SecImportExport.h" -#include "SecImportExportCrypto.h" -#include "SecImportExportUtils.h" -#include "Keychains.h" -#include "Access.h" -#include "Item.h" -#include "SecKeyPriv.h" -#include "KCEventNotifier.h" -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * 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" - -/* - * Default values we ultimately assign to the PrintName attr. - */ -#define SEC_PRIVKEY_PRINT_NAME_ATTR_VALUE "Imported Private Key" -#define SEC_PUBKEY_PRINT_NAME_ATTR_VALUE "Imported Public Key" -#define SEC_SESSIONKEY_PRINT_NAME_ATTR_VALUE "Imported Key" - -/* - * Set private key's Label and PrintName attributes. On entry Label - * is typically a random string to faciliate finding the key in a DL; - * the PrintName is currently set to the same value by the DL. We - * replace the Label attr with the public key hash and the PrintName - * attr with a caller-supplied value. - */ -static CSSM_RETURN impExpSetKeyLabel( - CSSM_CSP_HANDLE cspHand, // where the key lives - CSSM_DL_DB_HANDLE dlDbHand, // ditto - SecKeychainRef kcRef, // ditto - CSSM_KEY_PTR cssmKey, - const CSSM_DATA *existKeyLabel, // existing label, a random string - const CSSM_DATA *newPrintName, - CssmOwnedData &newLabel, // RETURNED as what we set - SecKeyRef *secKey) // RETURNED -{ - CSSM_RETURN crtn; - CSSM_DATA keyDigest = {0, NULL}; - - crtn = impExpKeyDigest(cspHand, cssmKey, &keyDigest); - if(crtn) { - return crtn; - } - - /* caller needs this for subsequent DL lookup */ - newLabel.copy(keyDigest); - - /* Find this key as a SecKeychainItem */ - SecItemClass itemClass; - switch (cssmKey->KeyHeader.KeyClass) { - case CSSM_KEYCLASS_PRIVATE_KEY: - itemClass = kSecPrivateKeyItemClass; - break; - case CSSM_KEYCLASS_PUBLIC_KEY: - itemClass = kSecPublicKeyItemClass; - break; - case CSSM_KEYCLASS_SESSION_KEY: - itemClass = kSecSymmetricKeyItemClass; - break; - default: - itemClass = (SecItemClass) 0; - } - SecKeychainAttribute kcAttr = {kSecKeyLabel, (UInt32)existKeyLabel->Length, existKeyLabel->Data}; - SecKeychainAttributeList kcAttrList = {1, &kcAttr}; - SecKeychainSearchRef srchRef = NULL; - OSStatus ortn; - SecKeychainItemRef itemRef = NULL; - - ortn = SecKeychainSearchCreateFromAttributes(kcRef, itemClass, - &kcAttrList, &srchRef); - if(ortn) { - SecImpExpDbg("SecKeychainSearchCreateFromAttributes error"); - crtn = ortn; - goto errOut; - } - ortn = SecKeychainSearchCopyNext(srchRef, &itemRef); - if(ortn) { - SecImpExpDbg("SecKeychainSearchCopyNext error"); - crtn = ortn; - goto errOut; - } - #ifndef NDEBUG - ortn = SecKeychainSearchCopyNext(srchRef, &itemRef); - if(ortn == errSecSuccess) { - SecImpExpDbg("impExpSetKeyLabel: found second key with same label!"); - crtn = errSecInternalComponent; - goto errOut; - } - #endif /* NDEBUG */ - - /* modify two attributes... */ - SecKeychainAttribute modAttrs[2]; - modAttrs[0].tag = kSecKeyLabel; - modAttrs[0].length = (UInt32)keyDigest.Length; - modAttrs[0].data = keyDigest.Data; - modAttrs[1].tag = kSecKeyPrintName; - modAttrs[1].length = (UInt32)newPrintName->Length; - modAttrs[1].data = newPrintName->Data; - kcAttrList.count = 2; - kcAttrList.attr = modAttrs; - ortn = SecKeychainItemModifyAttributesAndData(itemRef, &kcAttrList, - 0, NULL); - if(ortn) { - SecImpExpDbg("SecKeychainItemModifyAttributesAndData error"); - crtn = ortn; - goto errOut; - } - *secKey = (SecKeyRef)itemRef; -errOut: - if(keyDigest.Data) { - /* mallocd by CSP */ - impExpFreeCssmMemory(cspHand, keyDigest.Data); - } - if(srchRef) { - CFRelease(srchRef); - } - return crtn; -} - -/* - * Import a raw key. This can be used as a lightweight "guess" evaluator - * if a handle to the raw CSP is passed in (with no keychain), or as - * the real thing which does full keychain import. - */ -OSStatus impExpImportRawKey( - CFDataRef inData, - SecExternalFormat externForm, - SecExternalItemType itemType, - CSSM_ALGORITHMS keyAlg, - SecKeychainRef importKeychain, // optional - CSSM_CSP_HANDLE cspHand, // required - SecItemImportExportFlags flags, - const SecKeyImportExportParameters *keyParams, // optional - const char *printName, // optional - CFMutableArrayRef outArray) // optional, append here -{ - CSSM_RETURN crtn; - CSSM_KEY wrappedKey; - CSSM_KEYHEADER &hdr = wrappedKey.KeyHeader; - CSSM_CSP_HANDLE rawCspHand = 0; - CSSM_KEY_SIZE keySize; - CSSM_KEYBLOB_FORMAT format; - CSSM_KEYCLASS keyClass; - - /* First convert external format and types to CSSM style. */ - crtn = impExpKeyForm(externForm, itemType, keyAlg, &format, &keyClass); - - /* cook up key to be null-unwrapped */ - memset(&wrappedKey, 0, sizeof(CSSM_KEY)); - wrappedKey.KeyData.Length = CFDataGetLength(inData); - wrappedKey.KeyData.Data = (uint8 *)CFDataGetBytePtr(inData); - - hdr.HeaderVersion = CSSM_KEYHEADER_VERSION; - /* CspId don't care */ - hdr.BlobType = CSSM_KEYBLOB_RAW; - hdr.Format = format; - hdr.AlgorithmId = keyAlg; - hdr.KeyClass = keyClass; - /* LogicalKeySizeInBits calculated below */ - /* attr and usage are for the incoming unwrapped key... */ - hdr.KeyAttr = CSSM_KEYATTR_EXTRACTABLE; - hdr.KeyUsage = CSSM_KEYUSE_ANY; - - /* - * Get key size in bits from raw CSP. Doing this right now is a good - * optimization for the "guessing" case; getting the key size from the - * raw CSP involves a full decode on an alg- and format-specific manner. - * If we've been given the wrong params, we'll fail right here without - * the complication of a full UnwrapKey op. - */ - rawCspHand = cuCspStartup(CSSM_TRUE); - if(rawCspHand == 0) { - return CSSMERR_CSSM_ADDIN_LOAD_FAILED; - } - crtn = CSSM_QueryKeySizeInBits(rawCspHand, CSSM_INVALID_HANDLE, &wrappedKey, &keySize); - cuCspDetachUnload(rawCspHand, CSSM_TRUE); - if(crtn) { - SecImpExpDbg("CSSM_QueryKeySizeInBits error"); - return crtn; - } - hdr.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; - - impExpKeyUnwrapParams unwrapParams; - memset(&unwrapParams, 0, sizeof(unwrapParams)); - unwrapParams.encrAlg = CSSM_ALGID_NONE; - unwrapParams.encrMode = CSSM_ALGMODE_NONE; - unwrapParams.unwrappingKey = NULL; - unwrapParams.encrPad = CSSM_PADDING_NONE; - - return impExpImportKeyCommon( - &wrappedKey, - importKeychain, - cspHand, - flags, - keyParams, - &unwrapParams, - printName, - outArray); -} - -using namespace KeychainCore; - -/* - * Post notification of a "new key added" event. - * If you know of another way to do this, other than a dlclient-based lookup of the - * existing key in order to get a KeychainCore::Item, by all means have at it. - */ -OSStatus impExpKeyNotify( - SecKeychainRef importKeychain, - const CssmData &keyLabel, // stored with this, we use it to do a lookup - const CSSM_KEY &cssmKey) // unwrapped key in CSSM format -{ - /* - * Look up key in the DLDB by label, key class, algorithm, and key size. - */ - CSSM_DB_RECORDTYPE recordType; - const CSSM_KEYHEADER &hdr = cssmKey.KeyHeader; - - switch(hdr.KeyClass) { - case CSSM_KEYCLASS_PUBLIC_KEY: - recordType = CSSM_DL_DB_RECORD_PUBLIC_KEY; - break; - case CSSM_KEYCLASS_PRIVATE_KEY: - recordType = CSSM_DL_DB_RECORD_PRIVATE_KEY; - break; - case CSSM_KEYCLASS_SESSION_KEY: - recordType = CSSM_DL_DB_RECORD_SYMMETRIC_KEY; - break; - default: - return errSecParam; - } - assert(importKeychain != NULL); - Keychain keychain = KeychainImpl::required(importKeychain); - - SSDbImpl* impl = dynamic_cast(&(*keychain->database())); - if (impl == NULL) // did we go bad? - { - CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER); - } - - CssmClient::SSDb ssDb(impl); - - CssmClient::DbAttributes dbAttributes; - CssmClient::DbUniqueRecord uniqueId; - CssmClient::SSDbCursor dbCursor(ssDb, 3); // three attributes - dbCursor->recordType(recordType); - dbCursor->add(CSSM_DB_EQUAL, KeySchema::Label, keyLabel); - dbCursor->add(CSSM_DB_EQUAL, KeySchema::KeyType, hdr.AlgorithmId); - dbCursor->add(CSSM_DB_EQUAL, KeySchema::KeySizeInBits, hdr.LogicalKeySizeInBits); - CssmClient::Key key; - if (!dbCursor->nextKey(&dbAttributes, key, uniqueId)) { - SecImpExpDbg("impExpKeyNotify: key not found"); - return errSecItemNotFound; - } - - /* - * Get a Keychain-style Item, post notification. - */ - Item keyItem = keychain->item(recordType, uniqueId); - keychain->postEvent(kSecAddEvent, keyItem); - - return errSecSuccess; -} - -/* - * Size of random label string in ASCII chars to facilitate DL lookup. - */ -#define SEC_RANDOM_LABEL_LEN 16 - -#define SEC_KEYATTR_RETURN_MASK \ - (CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_RETURN_NONE) - -/* - * Common code to unwrap a key, used for raw keys (which do a NULL unwrap) and - * wrapped keys. - */ -OSStatus impExpImportKeyCommon( - const CSSM_KEY *wrappedKey, - SecKeychainRef importKeychain, // optional - CSSM_CSP_HANDLE cspHand, // required, if importKeychain is - // present, must be from there - SecItemImportExportFlags flags, - const SecKeyImportExportParameters *keyParams, // optional - const impExpKeyUnwrapParams *unwrapParams, - const char *printName, // optional - CFMutableArrayRef outArray) // optional, append here -{ - CSSM_CC_HANDLE ccHand = 0; - CSSM_RETURN crtn; - CSSM_DATA labelData; - CSSM_KEY unwrappedKey; - CSSM_DL_DB_HANDLE dlDbHandle; - CSSM_DL_DB_HANDLE *dlDbPtr = NULL; - OSStatus ortn; - CSSM_ACCESS_CREDENTIALS nullCreds; - uint8 randLabel[SEC_RANDOM_LABEL_LEN + 1]; - CSSM_KEYUSE keyUsage = 0; // default - CSSM_KEYATTR_FLAGS keyAttributes = 0; // default - const CSSM_KEYHEADER &hdr = wrappedKey->KeyHeader; - CSSM_DATA descrData = {0, NULL}; - ResourceControlContext rcc; - Security::KeychainCore::Access::Maker maker; - ResourceControlContext *rccPtr = NULL; - SecAccessRef accessRef = keyParams ? keyParams->accessRef : NULL; - CssmAutoData keyLabel(Allocator::standard()); - SecKeyRef secKeyRef = NULL; - bool usedSecKeyCreate = false; - - assert(unwrapParams != NULL); - assert(cspHand != 0); - - if(importKeychain) { - ortn = SecKeychainGetDLDBHandle(importKeychain, &dlDbHandle); - if(ortn) { - return ortn; - } - dlDbPtr = &dlDbHandle; - } - - memset(&unwrappedKey, 0, sizeof(CSSM_KEY)); - memset(&nullCreds, 0, sizeof(CSSM_ACCESS_CREDENTIALS)); - - /* context for unwrap */ - crtn = CSSM_CSP_CreateSymmetricContext(cspHand, - unwrapParams->encrAlg, - unwrapParams->encrMode, - &nullCreds, - unwrapParams->unwrappingKey, - unwrapParams->iv.Data ? &unwrapParams->iv : NULL, - unwrapParams->encrPad, - 0, // Params - &ccHand); - if(crtn) { - goto errOut; - } - if(dlDbPtr) { - /* Importing to a keychain - add DLDB to context */ - crtn = impExpAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_DL_DB_HANDLE, - sizeof(CSSM_ATTRIBUTE_DL_DB_HANDLE), - dlDbPtr); - if(crtn) { - SecImpExpDbg("impExpImportKeyCommon: CSSM_UpdateContextAttributes error"); - goto errOut; - } - } - - if((hdr.KeyClass != CSSM_KEYCLASS_SESSION_KEY) && (dlDbPtr != NULL)) { - /* Generate random 16-char label to facilitate DL lookup */ - char *randAscii = (char *)randLabel; - uint8 randBinary[SEC_RANDOM_LABEL_LEN / 2]; - unsigned randBinaryLen = SEC_RANDOM_LABEL_LEN / 2; - DevRandomGenerator rng; - - rng.random(randBinary, randBinaryLen); - for(unsigned i=0; ikeyUsage; - keyAttributes = keyParams->keyAttributes; - } - if(keyUsage == 0) { - /* default */ - keyUsage = CSSM_KEYUSE_ANY; - } - if(keyAttributes == 0) { - /* default */ - keyAttributes = CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE; - if(dlDbPtr) { - keyAttributes |= CSSM_KEYATTR_PERMANENT; - } - if(hdr.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) { - keyAttributes |= (CSSM_KEYATTR_SENSITIVE | CSSM_KEYATTR_EXTRACTABLE); - } - } - else { - /* caller-supplied; ensure we're generating a reference key */ - keyAttributes &= ~SEC_KEYATTR_RETURN_MASK; - keyAttributes |= CSSM_KEYATTR_RETURN_REF; - } - - if( (dlDbPtr != NULL) && // not permanent, no ACL - (hdr.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) && // ACLs only for private key - ( (keyParams == NULL) || // NULL --> default ACL - !(keyParams->flags & kSecKeyNoAccessControl) // explicity request no ACL - ) - ) { - /* - * Prepare to set up either a default ACL or one provided by caller via - * keyParams->accessRef. - */ - memset(&rcc, 0, sizeof(rcc)); - maker.initialOwner(rcc); - rccPtr = &rcc; - } - - /* - * Additional optional parameters: block size, rounds, - * effectiveKeySize. - * WARNING: block size and rounds, used for RC5, have not been tested. - * OpenSSL, as of Panther ship, did not support RC5 encryption. - */ - if(unwrapParams->effectiveKeySizeInBits != 0) { - assert(unwrapParams->unwrappingKey->KeyHeader.AlgorithmId == - CSSM_ALGID_RC2); - SecImpExpDbg("impExpImportKeyCommon: setting effectiveKeySizeInBits to %lu", - (unsigned long)unwrapParams->effectiveKeySizeInBits); - crtn = impExpAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_EFFECTIVE_BITS, - sizeof(uint32), - (void *)((size_t) unwrapParams->effectiveKeySizeInBits)); - if(crtn) { - SecImpExpDbg("impExpImportKeyCommon: CSSM_UpdateContextAttributes error"); - goto errOut; - } - } - - if(unwrapParams->rounds != 0) { - assert(unwrapParams->unwrappingKey->KeyHeader.AlgorithmId == - CSSM_ALGID_RC5); - SecImpExpDbg("impExpImportKeyCommon: setting rounds to %lu", - (unsigned long)unwrapParams->rounds); - crtn = impExpAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_ROUNDS, - sizeof(uint32), - (void *)((size_t)unwrapParams->rounds)); - if(crtn) { - SecImpExpDbg("impExpImportKeyCommon: CSSM_UpdateContextAttributes error"); - goto errOut; - } - } - - if(unwrapParams->blockSizeInBits != 0) { - /* Our RC5 implementation has a fixed block size */ - if(unwrapParams->blockSizeInBits != 64) { - SecImpExpDbg("WARNING impExpImportKeyCommon: setting block size to %lu", - (unsigned long)unwrapParams->blockSizeInBits); - /* - * With the current CSP this will actually be ignored - */ - crtn = impExpAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_BLOCK_SIZE, - sizeof(uint32), - (void *)((size_t)unwrapParams->blockSizeInBits)); - if(crtn) { - SecImpExpDbg("impExpImportKeyCommon: CSSM_UpdateContextAttributes error"); - goto errOut; - } - } - } - - /* Here we go */ - crtn = CSSM_UnwrapKey(ccHand, - NULL, // public key - (const CSSM_WRAP_KEY *)wrappedKey, - keyUsage, - keyAttributes, - &labelData, - rccPtr, // CredAndAclEntry - &unwrappedKey, - &descrData); // required - if(crtn != CSSM_OK) { - SecImpExpDbg("CSSM_UnwrapKey failure"); - if(crtn == CSSMERR_DL_INVALID_UNIQUE_INDEX_DATA) { - /* report in a keychain-friendly way */ - crtn = errSecDuplicateItem; - } - goto errOut; - } - - /* Private and public keys: update Label as public key hash */ - if((hdr.KeyClass != CSSM_KEYCLASS_SESSION_KEY) && (dlDbPtr != NULL)) { - CSSM_DATA newPrintName; - if(printName) { - /* caller specified */ - newPrintName.Data = (uint8 *)printName; - } - else { - /* use defaults */ - if(hdr.KeyClass == CSSM_KEYCLASS_PRIVATE_KEY) { - newPrintName.Data = (uint8 *)SEC_PRIVKEY_PRINT_NAME_ATTR_VALUE; - } - else { - newPrintName.Data = (uint8 *)SEC_PUBKEY_PRINT_NAME_ATTR_VALUE; - } - } - newPrintName.Length = strlen((char *)newPrintName.Data); - #if old_way - crtn = impExpSetKeyLabel(cspHand, *dlDbPtr, &unwrappedKey, - &labelData, &newPrintName, keyLabel); - #else - crtn = impExpSetKeyLabel(cspHand, *dlDbPtr, importKeychain, - &unwrappedKey, &labelData, &newPrintName, keyLabel, &secKeyRef); - #endif - if(crtn) { - goto errOut; - } - } - - /* Private key: adjust ACL as appropriate */ - if(rccPtr != NULL) { - SecPointer theAccess(accessRef ? - KeychainCore::Access::required(accessRef) : - new KeychainCore::Access("Imported Private Key")); - try { - CssmClient::KeyAclBearer bearer(cspHand, unwrappedKey, Allocator::standard()); - theAccess->setAccess(bearer, maker); - } - catch (const CssmError &e) { - /* not implemented means we're talking to the raw CSP which does - * not implement ACLs */ - if(e.error != CSSMERR_CSP_FUNCTION_NOT_IMPLEMENTED) { - crtn = e.error; - } - } - catch(...) { - SecImpExpDbg("keyImport: exception on setAccess\n"); - crtn = errSecAuthFailed; /* ??? */ - } - } - - /* - * If importKeychain is non-NULL we've already added the key to the keychain. - * If importKeychain is NULL, and outArray is non-NULL, we have to use the - * half-baked SecKeyCreateWithCSSMKey to give the caller *something*. - */ - if(outArray) { - if(secKeyRef == NULL) { - assert(importKeychain == NULL); - ortn = SecKeyCreateWithCSSMKey(&unwrappedKey, &secKeyRef); - if(ortn) { - SecImpExpDbg("SecKeyCreateWithCSSMKey failure"); - crtn = ortn; - goto errOut; - } - /* don't CSSM_FreeKey() this key */ - usedSecKeyCreate = true; - } - CFArrayAppendValue(outArray, secKeyRef); - } - - if(importKeychain) { - impExpKeyNotify(importKeychain, keyLabel.get(), unwrappedKey); - } - -errOut: - if(ccHand != 0) { - CSSM_DeleteContext(ccHand); - } - if(secKeyRef) { - CFRelease(secKeyRef); - } - if((unwrappedKey.KeyData.Data != NULL) && !usedSecKeyCreate) { - /* skip this free if we used SecKeyCreateWithCSSMKey() */ - CSSM_FreeKey(cspHand, NULL, &unwrappedKey, CSSM_FALSE); - } - return crtn; -} - -/* - * Common code to wrap a key for export. - */ -CSSM_RETURN impExpExportKeyCommon( - CSSM_CSP_HANDLE cspHand, // for all three keys - SecKeyRef secKey, - CSSM_KEY_PTR wrappingKey, - CSSM_KEY_PTR wrappedKey, // RETURNED - CSSM_ALGORITHMS wrapAlg, - CSSM_ENCRYPT_MODE wrapMode, - CSSM_PADDING wrapPad, - CSSM_KEYBLOB_FORMAT wrapFormat, // NONE, PKCS7, PKCS8, OPENSSL - CSSM_ATTRIBUTE_TYPE blobAttrType, // optional raw key format attr - CSSM_KEYBLOB_FORMAT blobForm, // ditto - const CSSM_DATA *descData, // optional descriptive data - const CSSM_DATA *iv) -{ - OSStatus ortn; - CSSM_RETURN crtn; - - const CSSM_KEY *unwrappedKey; - ortn = SecKeyGetCSSMKey(secKey, &unwrappedKey); - if(ortn) { - SecImpExpDbg("impExpExportKeyCommon SecKeyGetCSSMKey error"); - return ortn; - } - else if(!(unwrappedKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE)) { - SecImpExpDbg("impExpExportKeyCommon: CSSM key is non-extractable"); - return errSecDataNotAvailable; - } - - /* - * Creds are needed for wrapping private and session keys. - */ - CSSM_ACCESS_CREDENTIALS nullCreds; - memset(&nullCreds, 0, sizeof(nullCreds)); - const CSSM_ACCESS_CREDENTIALS *creds = &nullCreds; // default - - CSSM_KEYCLASS keyClass = unwrappedKey->KeyHeader.KeyClass; - if(keyClass == CSSM_KEYCLASS_PRIVATE_KEY || keyClass == CSSM_KEYCLASS_SESSION_KEY) { - ortn = SecKeyGetCredentials(secKey, - CSSM_ACL_AUTHORIZATION_DECRYPT, - kSecCredentialTypeDefault, - &creds); - if(ortn) { - SecImpExpDbg("impExpExportKeyCommon SecKeyGetCredentials error"); - return ortn; - } - } - - CSSM_CC_HANDLE ccHand; - crtn = CSSM_CSP_CreateSymmetricContext(cspHand, - wrapAlg, - wrapMode, - &nullCreds, // creds for wrapping key, never a private key here - wrappingKey, - iv, - wrapPad, - 0, // Params - &ccHand); - if(ortn) { - SecImpExpDbg("impExpExportKeyCommon CSSM_CSP_CreateSymmetricContext error"); - return crtn; - } - - /* a couple of optional caller-specified attributes */ - if(wrapFormat != CSSM_KEYBLOB_WRAPPED_FORMAT_NONE) { - crtn = impExpAddContextAttribute(ccHand, - CSSM_ATTRIBUTE_WRAPPED_KEY_FORMAT, - sizeof(uint32), - (void *)((size_t)wrapFormat)); - if(crtn) { - SecImpExpDbg("impExpExportKeyCommon AddContextAttribute error (1)"); - CSSM_DeleteContext(ccHand); - return crtn; - } - } - - if(blobAttrType != CSSM_ATTRIBUTE_NONE) { - crtn = impExpAddContextAttribute(ccHand, - blobAttrType, - sizeof(uint32), - (void *)((size_t)blobForm)); - if(crtn) { - SecImpExpDbg("impExpExportKeyCommon AddContextAttribute error"); - return crtn; - } - } - - CSSM_DATA dData = {0, 0}; - if(descData) { - dData = *descData; - } - - crtn = CSSM_WrapKey(ccHand, - creds, - unwrappedKey, - &dData, - wrappedKey); - CSSM_DeleteContext(ccHand); - switch(crtn) { - case CSSM_OK: - break; - case CSSMERR_CSP_INVALID_KEYATTR_MASK: - { - /* - * This is what comes back when we try to wrap an unextractable - * key, or when we null wrap a sensitive key. Give the caller - * some useful info. - */ - CSSM_KEYATTR_FLAGS attr = unwrappedKey->KeyHeader.KeyAttr; - if(!(attr & CSSM_KEYATTR_EXTRACTABLE)) { - SecImpExpDbg("impExpExportKeyCommon !EXTRACTABLE"); - return errSecDataNotAvailable; - } - if((attr & CSSM_KEYATTR_SENSITIVE) && (wrappingKey == NULL)) { - SecImpExpDbg("impExpExportKeyCommon !SENSITIVE, NULL wrap"); - return errSecPassphraseRequired; - } - - } - default: - SecImpExpDbg("impExpExportKeyCommon CSSM_WrapKey error"); - } - return crtn; -}