]> git.saurik.com Git - apple/security.git/blobdiff - Security/libsecurity_keychain/lib/KeyItem.cpp
Security-57336.1.9.tar.gz
[apple/security.git] / Security / libsecurity_keychain / lib / KeyItem.cpp
diff --git a/Security/libsecurity_keychain/lib/KeyItem.cpp b/Security/libsecurity_keychain/lib/KeyItem.cpp
deleted file mode 100644 (file)
index b1c4d17..0000000
+++ /dev/null
@@ -1,1403 +0,0 @@
-/*
- * Copyright (c) 2002-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@
- */
-
-//
-// KeyItem.cpp
-//
-#include <security_keychain/KeyItem.h>
-#include <Security/cssmtype.h>
-#include <security_keychain/Access.h>
-#include <security_keychain/Keychains.h>
-#include <security_keychain/KeyItem.h>
-#include <security_cdsa_client/wrapkey.h>
-#include <security_cdsa_client/genkey.h>
-#include <security_cdsa_client/signclient.h>
-#include <security_cdsa_client/cryptoclient.h>
-
-#include <security_keychain/Globals.h>
-#include "KCEventNotifier.h"
-#include <CommonCrypto/CommonDigest.h>
-#include <SecBase.h>
-
-// @@@ This needs to be shared.
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wunused-const-variable"
-static CSSM_DB_NAME_ATTR(kInfoKeyPrintName, kSecKeyPrintName, (char*) "PrintName", 0, NULL, BLOB);
-static CSSM_DB_NAME_ATTR(kInfoKeyLabel, kSecKeyLabel, (char*) "Label", 0, NULL, BLOB);
-static CSSM_DB_NAME_ATTR(kInfoKeyApplicationTag, kSecKeyApplicationTag, (char*) "ApplicationTag", 0, NULL, BLOB);
-#pragma clang diagnostic pop
-
-using namespace KeychainCore;
-using namespace CssmClient;
-
-KeyItem::KeyItem(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId) :
-       ItemImpl(keychain, primaryKey, uniqueId),
-       mKey(),
-       algid(NULL),
-       mPubKeyHash(Allocator::standard())
-{
-}
-
-KeyItem::KeyItem(const Keychain &keychain, const PrimaryKey &primaryKey)  :
-       ItemImpl(keychain, primaryKey),
-       mKey(),
-       algid(NULL),
-       mPubKeyHash(Allocator::standard())
-{
-}
-
-KeyItem* KeyItem::make(const Keychain &keychain, const PrimaryKey &primaryKey, const CssmClient::DbUniqueRecord &uniqueId)
-{
-       KeyItem* k = new KeyItem(keychain, primaryKey, uniqueId);
-       keychain->addItem(primaryKey, k);
-       return k;
-}
-
-
-
-KeyItem* KeyItem::make(const Keychain &keychain, const PrimaryKey &primaryKey)
-{
-       KeyItem* k = new KeyItem(keychain, primaryKey);
-       keychain->addItem(primaryKey, k);
-       return k;
-}
-
-
-
-KeyItem::KeyItem(KeyItem &keyItem) :
-       ItemImpl(keyItem),
-       mKey(),
-       algid(NULL),
-       mPubKeyHash(Allocator::standard())
-{
-       // @@@ this doesn't work for keys that are not in a keychain.
-}
-
-KeyItem::KeyItem(const CssmClient::Key &key) :
-    ItemImpl(key->keyClass() + CSSM_DL_DB_RECORD_PUBLIC_KEY, (OSType)0, (UInt32)0, (const void*)NULL),
-       mKey(key),
-       algid(NULL),
-       mPubKeyHash(Allocator::standard())
-{
-       if (key->keyClass() > CSSM_KEYCLASS_SESSION_KEY)
-               MacOSError::throwMe(errSecParam);
-}
-
-KeyItem::~KeyItem()
-{
-}
-
-void
-KeyItem::update()
-{
-       ItemImpl::update();
-}
-
-Item
-KeyItem::copyTo(const Keychain &keychain, Access *newAccess)
-{
-       if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP))
-               MacOSError::throwMe(errSecInvalidKeychain);
-
-       /* Get the destination keychain's db. */
-       SSDbImpl* dbImpl = dynamic_cast<SSDbImpl*>(&(*keychain->database()));
-       if (dbImpl == NULL)
-       {
-               CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-       }
-
-       SSDb ssDb(dbImpl);
-
-       /* Make sure mKey is valid. */
-       const CSSM_KEY *cssmKey = key();
-       if (cssmKey && (0==(cssmKey->KeyHeader.KeyAttr & CSSM_KEYATTR_EXTRACTABLE)))
-       {
-               MacOSError::throwMe(errSecDataNotAvailable);
-       }
-
-       // Generate a random label to use initially
-       CssmClient::CSP appleCsp(gGuidAppleCSP);
-       CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW);
-       uint8 labelBytes[20];
-       CssmData label(labelBytes, sizeof(labelBytes));
-       random.generate(label, (uint32)label.Length);
-
-       /* Set up the ACL for the new key. */
-       SecPointer<Access> access;
-       if (newAccess)
-               access = newAccess;
-       else
-               access = new Access(*mKey);
-
-       /* Generate a random 3DES wrapping Key. */
-       CssmClient::GenerateKey genKey(csp(), CSSM_ALGID_3DES_3KEY, 192);
-       CssmClient::Key wrappingKey(genKey(KeySpec(CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP,
-               CSSM_KEYATTR_EXTRACTABLE /* | CSSM_KEYATTR_RETURN_DATA */)));
-
-       /* make a random IV */
-       uint8 ivBytes[8];
-       CssmData iv(ivBytes, sizeof(ivBytes));
-       random.generate(iv, (uint32)iv.length());
-
-       /* Extract the key by wrapping it with the wrapping key. */
-       CssmClient::WrapKey wrap(csp(), CSSM_ALGID_3DES_3KEY_EDE);
-       wrap.key(wrappingKey);
-       wrap.cred(getCredentials(CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, kSecCredentialTypeDefault));
-       wrap.mode(CSSM_ALGMODE_ECBPad);
-       wrap.padding(CSSM_PADDING_PKCS7);
-       wrap.initVector(iv);
-       CssmClient::Key wrappedKey(wrap(mKey));
-
-       /* Unwrap the new key into the new Keychain. */
-       CssmClient::UnwrapKey unwrap(keychain->csp(), CSSM_ALGID_3DES_3KEY_EDE);
-       unwrap.key(wrappingKey);
-       unwrap.mode(CSSM_ALGMODE_ECBPad);
-       unwrap.padding(CSSM_PADDING_PKCS7);
-       unwrap.initVector(iv);
-
-       /* Setup the dldbHandle in the context. */
-       unwrap.add(CSSM_ATTRIBUTE_DL_DB_HANDLE, ssDb->handle());
-
-       /* Set up an initial aclEntry so we can change it after the unwrap. */
-       Access::Maker maker(Allocator::standard(), Access::Maker::kAnyMakerType);
-       ResourceControlContext rcc;
-       maker.initialOwner(rcc, NULL);
-       unwrap.owner(rcc.input());
-
-       /* Unwrap the key. */
-       uint32 usage = mKey->usage();
-       /* Work around csp brokeness where it sets all usage bits in the Keyheader when CSSM_KEYUSE_ANY is set. */
-       if (usage & CSSM_KEYUSE_ANY)
-               usage = CSSM_KEYUSE_ANY;
-
-       CssmClient::Key unwrappedKey(unwrap(wrappedKey, KeySpec(usage,
-               (mKey->attributes() | CSSM_KEYATTR_PERMANENT) & ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE),
-               label)));
-
-       /* Look up unwrapped key in the DLDB. */
-       DbUniqueRecord uniqueId;
-       SSDbCursor dbCursor(ssDb, 1);
-       dbCursor->recordType(recordType());
-       dbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label);
-       CssmClient::Key copiedKey;
-       if (!dbCursor->nextKey(NULL, copiedKey, uniqueId))
-               MacOSError::throwMe(errSecItemNotFound);
-
-       /* Copy the Label, PrintName and ApplicationTag attributes from the old key to the new one. */
-       dbUniqueRecord();
-       DbAttributes oldDbAttributes(mUniqueId->database(), 3);
-       oldDbAttributes.add(kInfoKeyLabel);
-       oldDbAttributes.add(kInfoKeyPrintName);
-       oldDbAttributes.add(kInfoKeyApplicationTag);
-       mUniqueId->get(&oldDbAttributes, NULL);
-       try
-       {
-               uniqueId->modify(recordType(), &oldDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
-       }
-       catch (CssmError e)
-       {
-               // clean up after trying to insert a duplicate key
-               uniqueId->deleteRecord ();
-               throw;
-       }
-
-       /* Set the acl and owner on the unwrapped key. */
-       access->setAccess(*unwrappedKey, maker);
-
-       /* Return a keychain item which represents the new key.  */
-       Item item(keychain->item(recordType(), uniqueId));
-
-    KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, item);
-
-       return item;
-}
-
-Item
-KeyItem::importTo(const Keychain &keychain, Access *newAccess, SecKeychainAttributeList *attrList)
-{
-       if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP))
-               MacOSError::throwMe(errSecInvalidKeychain);
-
-       /* Get the destination keychain's db. */
-       SSDbImpl* dbImpl = dynamic_cast<SSDbImpl*>(&(*keychain->database()));
-       if (dbImpl == NULL)
-               CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-
-       SSDb ssDb(dbImpl);
-
-       /* Make sure mKey is valid. */
-       /* We can't call key() here, since we won't have a unique record id yet */
-       if (!mKey)
-               CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-
-       // Generate a random label to use initially
-       CssmClient::CSP appleCsp(gGuidAppleCSP);
-       CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW);
-       uint8 labelBytes[20];
-       CssmData label(labelBytes, sizeof(labelBytes));
-       random.generate(label, (uint32)label.Length);
-
-       /* Set up the ACL for the new key. */
-       SecPointer<Access> access;
-       if (newAccess)
-               access = newAccess;
-       else
-               access = new Access(*mKey);
-
-       /* Generate a random 3DES wrapping Key. */
-       CssmClient::GenerateKey genKey(csp(), CSSM_ALGID_3DES_3KEY, 192);
-       CssmClient::Key wrappingKey(genKey(KeySpec(CSSM_KEYUSE_WRAP | CSSM_KEYUSE_UNWRAP,
-               CSSM_KEYATTR_EXTRACTABLE /* | CSSM_KEYATTR_RETURN_DATA */)));
-
-       /* make a random IV */
-       uint8 ivBytes[8];
-       CssmData iv(ivBytes, sizeof(ivBytes));
-       random.generate(iv, (uint32)iv.length());
-
-       /* Extract the key by wrapping it with the wrapping key. */
-       CssmClient::WrapKey wrap(csp(), CSSM_ALGID_3DES_3KEY_EDE);
-       wrap.key(wrappingKey);
-       wrap.cred(getCredentials(CSSM_ACL_AUTHORIZATION_EXPORT_WRAPPED, kSecCredentialTypeDefault));
-       wrap.mode(CSSM_ALGMODE_ECBPad);
-       wrap.padding(CSSM_PADDING_PKCS7);
-       wrap.initVector(iv);
-       CssmClient::Key wrappedKey(wrap(mKey));
-
-       /* Unwrap the new key into the new Keychain. */
-       CssmClient::UnwrapKey unwrap(keychain->csp(), CSSM_ALGID_3DES_3KEY_EDE);
-       unwrap.key(wrappingKey);
-       unwrap.mode(CSSM_ALGMODE_ECBPad);
-       unwrap.padding(CSSM_PADDING_PKCS7);
-       unwrap.initVector(iv);
-
-       /* Setup the dldbHandle in the context. */
-       unwrap.add(CSSM_ATTRIBUTE_DL_DB_HANDLE, ssDb->handle());
-
-       /* Set up an initial aclEntry so we can change it after the unwrap. */
-       Access::Maker maker(Allocator::standard(), Access::Maker::kAnyMakerType);
-       ResourceControlContext rcc;
-       maker.initialOwner(rcc, NULL);
-       unwrap.owner(rcc.input());
-
-       /* Unwrap the key. */
-       uint32 usage = mKey->usage();
-       /* Work around csp brokeness where it sets all usage bits in the Keyheader when CSSM_KEYUSE_ANY is set. */
-       if (usage & CSSM_KEYUSE_ANY)
-               usage = CSSM_KEYUSE_ANY;
-
-       CssmClient::Key unwrappedKey(unwrap(wrappedKey, KeySpec(usage,
-               (mKey->attributes() | CSSM_KEYATTR_PERMANENT) & ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE),
-               label)));
-
-       /* Look up unwrapped key in the DLDB. */
-       DbUniqueRecord uniqueId;
-       SSDbCursor dbCursor(ssDb, 1);
-       dbCursor->recordType(recordType());
-       dbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label);
-       CssmClient::Key copiedKey;
-       if (!dbCursor->nextKey(NULL, copiedKey, uniqueId))
-               MacOSError::throwMe(errSecItemNotFound);
-
-       // Set the initial label, application label, and application tag (if provided)
-       if (attrList) {
-               DbAttributes newDbAttributes;
-               SSDbCursor otherDbCursor(ssDb, 1);
-               otherDbCursor->recordType(recordType());
-               bool checkForDuplicates = false;
-
-               for (UInt32 index=0; index < attrList->count; index++) {
-                       SecKeychainAttribute attr = attrList->attr[index];
-                       CssmData attrData(attr.data, attr.length);
-                       if (attr.tag == kSecKeyPrintName) {
-                               newDbAttributes.add(kInfoKeyPrintName, attrData);
-                       }
-                       if (attr.tag == kSecKeyLabel) {
-                               newDbAttributes.add(kInfoKeyLabel, attrData);
-                               otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, attrData);
-                               checkForDuplicates = true;
-                       }
-                       if (attr.tag == kSecKeyApplicationTag) {
-                               newDbAttributes.add(kInfoKeyApplicationTag, attrData);
-                               otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyApplicationTag, attrData);
-                               checkForDuplicates = true;
-                       }
-               }
-
-               DbAttributes otherDbAttributes;
-               DbUniqueRecord otherUniqueId;
-               CssmClient::Key otherKey;
-               try
-               {
-                       if (checkForDuplicates && otherDbCursor->nextKey(&otherDbAttributes, otherKey, otherUniqueId))
-                               MacOSError::throwMe(errSecDuplicateItem);
-
-                       uniqueId->modify(recordType(), &newDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
-               }
-               catch (CssmError e)
-               {
-                       // clean up after trying to insert a duplicate key
-                       uniqueId->deleteRecord ();
-                       throw;
-               }
-       }
-
-       /* Set the acl and owner on the unwrapped key. */
-       access->setAccess(*unwrappedKey, maker);
-
-       /* Return a keychain item which represents the new key.  */
-       Item item(keychain->item(recordType(), uniqueId));
-
-    KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, item);
-
-       return item;
-}
-
-void
-KeyItem::didModify()
-{
-}
-
-PrimaryKey
-KeyItem::add(Keychain &keychain)
-{
-       MacOSError::throwMe(errSecUnimplemented);
-}
-
-CssmClient::SSDbUniqueRecord
-KeyItem::ssDbUniqueRecord()
-{
-       DbUniqueRecordImpl *impl = &*dbUniqueRecord();
-       Security::CssmClient::SSDbUniqueRecordImpl *simpl = dynamic_cast<Security::CssmClient::SSDbUniqueRecordImpl *>(impl);
-       if (simpl == NULL)
-       {
-               CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-       }
-
-       return CssmClient::SSDbUniqueRecord(simpl);
-}
-
-CssmClient::Key &
-KeyItem::key()
-{
-       if (!mKey)
-       {
-               CssmClient::SSDbUniqueRecord uniqueId(ssDbUniqueRecord());
-               CssmDataContainer dataBlob(uniqueId->allocator());
-               uniqueId->get(NULL, &dataBlob);
-               mKey = CssmClient::Key(uniqueId->database()->csp(), *reinterpret_cast<CssmKey *>(dataBlob.Data));
-       }
-
-       return mKey;
-}
-
-CssmClient::CSP
-KeyItem::csp()
-{
-       return key()->csp();
-}
-
-
-const CSSM_X509_ALGORITHM_IDENTIFIER&
-KeyItem::algorithmIdentifier()
-{
-#if 0
-       CssmKey *mKey;
-       CSSM_KEY_TYPE algorithm
-               CSSM_KEY_PTR cssmKey =  (CSSM_KEY_PTR)thisData->Data;
-cssmKey->KeyHeader
-       static void printKeyHeader(
-       const CSSM_KEYHEADER &hdr)
-{
-       printf("   Algorithm       : ");
-       switch(hdr.AlgorithmId) {
-CSSM_X509_ALGORITHM_IDENTIFIER algID;
-
-CSSM_OID *CL_algToOid(
-       CSSM_ALGORITHMS algId)
-typedef struct cssm_x509_algorithm_identifier {
-    CSSM_OID algorithm;
-    CSSM_DATA parameters;
-} CSSM_X509_ALGORITHM_IDENTIFIER, *CSSM_X509_ALGORITHM_IDENTIFIER_PTR;
-#endif
-
-       abort();
-}
-
-/*
- * itemID, used to locate Extended Attributes, is the public key hash for keys.
- */
-const CssmData &KeyItem::itemID()
-{
-       if(mPubKeyHash.length() == 0) {
-               /*
-                * Fetch the attribute from disk.
-                */
-               UInt32 tag = kSecKeyLabel;
-               UInt32 format = 0;
-               SecKeychainAttributeInfo attrInfo = {1, &tag, &format};
-               SecKeychainAttributeList *attrList = NULL;
-               getAttributesAndData(&attrInfo, NULL, &attrList, NULL, NULL);
-               if((attrList == NULL) || (attrList->count != 1)) {
-                       MacOSError::throwMe(errSecNoSuchAttr);
-               }
-               mPubKeyHash.copy(attrList->attr->data, attrList->attr->length);
-               freeAttributesAndData(attrList, NULL);
-       }
-       return mPubKeyHash;
-}
-
-
-unsigned int
-KeyItem::strengthInBits(const CSSM_X509_ALGORITHM_IDENTIFIER *algid)
-{
-       // @@@ Make a context with key based on algid and use that to get the effective keysize and not just the logical one.
-       CSSM_KEY_SIZE keySize = {};
-       CSSM_RETURN rv = CSSM_QueryKeySizeInBits (csp()->handle(),
-                         CSSM_INVALID_HANDLE,
-                         key(),
-                         &keySize);
-       if (rv)
-               return 0;
-
-       return keySize.LogicalKeySizeInBits;
-}
-
-const AccessCredentials *
-KeyItem::getCredentials(
-       CSSM_ACL_AUTHORIZATION_TAG operation,
-       SecCredentialType credentialType)
-{
-       // @@@ Fix this to actually examine the ACL for this key and consider operation and do the right thing.
-       //AutoAclEntryInfoList aclInfos;
-       //key()->getAcl(aclInfos);
-
-       bool smartcard = keychain() != NULL ? (keychain()->database()->dl()->guid() == gGuidAppleSdCSPDL) : false;
-
-       AclFactory factory;
-       switch (credentialType)
-       {
-       case kSecCredentialTypeDefault:
-               return smartcard?globals().smartcardItemCredentials():globals().itemCredentials();
-       case kSecCredentialTypeWithUI:
-               return smartcard?globals().smartcardItemCredentials():factory.promptCred();
-       case kSecCredentialTypeNoUI:
-               return factory.nullCred();
-       default:
-               MacOSError::throwMe(errSecParam);
-       }
-}
-
-bool
-KeyItem::operator == (KeyItem &other)
-{
-       if (mKey && *mKey)
-       {
-               // Pointer compare
-               return this == &other;
-       }
-
-       // If keychains are different, then keys are different
-       Keychain otherKeychain = other.keychain();
-       return (mKeychain && otherKeychain && (*mKeychain == *otherKeychain));
-}
-
-void
-KeyItem::createPair(
-       Keychain keychain,
-       CSSM_ALGORITHMS algorithm,
-       uint32 keySizeInBits,
-       CSSM_CC_HANDLE contextHandle,
-       CSSM_KEYUSE publicKeyUsage,
-       uint32 publicKeyAttr,
-       CSSM_KEYUSE privateKeyUsage,
-       uint32 privateKeyAttr,
-       SecPointer<Access> initialAccess,
-       SecPointer<KeyItem> &outPublicKey,
-       SecPointer<KeyItem> &outPrivateKey)
-{
-       bool freeKeys = false;
-       bool deleteContext = false;
-
-       if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP))
-               MacOSError::throwMe(errSecInvalidKeychain);
-
-       SSDbImpl* impl = dynamic_cast<SSDbImpl*>(&(*keychain->database()));
-       if (impl == NULL)
-       {
-               CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-       }
-
-       SSDb ssDb(impl);
-       CssmClient::CSP csp(keychain->csp());
-       CssmClient::CSP appleCsp(gGuidAppleCSP);
-
-       // Generate a random label to use initially
-       CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW);
-       uint8 labelBytes[20];
-       CssmData label(labelBytes, sizeof(labelBytes));
-       random.generate(label, (uint32)label.Length);
-
-       // Create a Access::Maker for the initial owner of the private key.
-       ResourceControlContext rcc;
-       memset(&rcc, 0, sizeof(rcc));
-       Access::Maker maker;
-       // @@@ Potentially provide a credential argument which allows us to generate keys in the csp.  Currently the CSP let's anyone do this, but we might restrict this in the future, f.e. a smartcard could require out of band pin entry before a key can be generated.
-       maker.initialOwner(rcc);
-       // Create the cred we need to manipulate the keys until we actually set a new access control for them.
-       const AccessCredentials *cred = maker.cred();
-
-       CSSM_KEY publicCssmKey, privateCssmKey;
-       memset(&publicCssmKey, 0, sizeof(publicCssmKey));
-       memset(&privateCssmKey, 0, sizeof(privateCssmKey));
-
-       CSSM_CC_HANDLE ccHandle = 0;
-
-       Item publicKeyItem, privateKeyItem;
-       try
-       {
-               CSSM_RETURN status;
-               if (contextHandle)
-                               ccHandle = contextHandle;
-               else
-               {
-                       status = CSSM_CSP_CreateKeyGenContext(csp->handle(), algorithm, keySizeInBits, NULL, NULL, NULL, NULL, NULL, &ccHandle);
-                       if (status)
-                               CssmError::throwMe(status);
-                       deleteContext = true;
-               }
-
-               CSSM_DL_DB_HANDLE dldbHandle = ssDb->handle();
-               CSSM_DL_DB_HANDLE_PTR dldbHandlePtr = &dldbHandle;
-               CSSM_CONTEXT_ATTRIBUTE contextAttributes = { CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(dldbHandle), { (char *)dldbHandlePtr } };
-               status = CSSM_UpdateContextAttributes(ccHandle, 1, &contextAttributes);
-               if (status)
-                       CssmError::throwMe(status);
-
-               // Generate the keypair
-               status = CSSM_GenerateKeyPair(ccHandle, publicKeyUsage, publicKeyAttr, &label, &publicCssmKey, privateKeyUsage, privateKeyAttr, &label, &rcc, &privateCssmKey);
-               if (status)
-                       CssmError::throwMe(status);
-               freeKeys = true;
-
-               // Find the keys we just generated in the DL to get SecKeyRef's to them
-               // so we can change the label to be the hash of the public key, and
-               // fix up other attributes.
-
-               // Look up public key in the DLDB.
-               DbAttributes pubDbAttributes;
-               DbUniqueRecord pubUniqueId;
-               SSDbCursor dbPubCursor(ssDb, 1);
-               dbPubCursor->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY);
-               dbPubCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label);
-               CssmClient::Key publicKey;
-               if (!dbPubCursor->nextKey(&pubDbAttributes, publicKey, pubUniqueId))
-                       MacOSError::throwMe(errSecItemNotFound);
-
-               // Look up private key in the DLDB.
-               DbAttributes privDbAttributes;
-               DbUniqueRecord privUniqueId;
-               SSDbCursor dbPrivCursor(ssDb, 1);
-               dbPrivCursor->recordType(CSSM_DL_DB_RECORD_PRIVATE_KEY);
-               dbPrivCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label);
-               CssmClient::Key privateKey;
-               if (!dbPrivCursor->nextKey(&privDbAttributes, privateKey, privUniqueId))
-                       MacOSError::throwMe(errSecItemNotFound);
-
-               // Convert reference public key to a raw key so we can use it
-               // in the appleCsp.
-               CssmClient::WrapKey wrap(csp, CSSM_ALGID_NONE);
-               wrap.cred(cred);
-               CssmClient::Key rawPubKey = wrap(publicKey);
-
-               // Calculate the hash of the public key using the appleCSP.
-               CssmClient::PassThrough passThrough(appleCsp);
-               void *outData;
-               CssmData *cssmData;
-
-               /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the
-               * associated key blob.
-               * Key is specified in CSSM_CSP_CreatePassThroughContext.
-               * Hash is allocated bythe CSP, in the App's memory, and returned
-               * in *outData. */
-               passThrough.key(rawPubKey);
-               passThrough(CSSM_APPLECSP_KEYDIGEST, NULL, &outData);
-               cssmData = reinterpret_cast<CssmData *>(outData);
-               CssmData &pubKeyHash = *cssmData;
-
-               auto_ptr<string>privDescription;
-               auto_ptr<string>pubDescription;
-               try {
-                       privDescription.reset(new string(initialAccess->promptDescription()));
-                       pubDescription.reset(new string(initialAccess->promptDescription()));
-               }
-               catch(...) {
-                       /* this path taken if no promptDescription available, e.g., for complex ACLs */
-                       privDescription.reset(new string("Private key"));
-                       pubDescription.reset(new string("Public key"));
-               }
-
-               // Set the label of the public key to the public key hash.
-               // Set the PrintName of the public key to the description in the acl.
-               pubDbAttributes.add(kInfoKeyLabel, pubKeyHash);
-               pubDbAttributes.add(kInfoKeyPrintName, *pubDescription);
-               pubUniqueId->modify(CSSM_DL_DB_RECORD_PUBLIC_KEY, &pubDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
-
-               // Set the label of the private key to the public key hash.
-               // Set the PrintName of the private key to the description in the acl.
-               privDbAttributes.add(kInfoKeyLabel, pubKeyHash);
-               privDbAttributes.add(kInfoKeyPrintName, *privDescription);
-               privUniqueId->modify(CSSM_DL_DB_RECORD_PRIVATE_KEY, &privDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
-
-               // @@@ Not exception safe!
-               csp.allocator().free(cssmData->Data);
-               csp.allocator().free(cssmData);
-
-               // Finally fix the acl and owner of the private key to the specified access control settings.
-               initialAccess->setAccess(*privateKey, maker);
-
-               if(publicKeyAttr & CSSM_KEYATTR_PUBLIC_KEY_ENCRYPT) {
-                       /*
-                        * Make the public key acl completely open.
-                        * If the key was not encrypted, it already has a wide-open
-                        * ACL (though that is a feature of securityd; it's not
-                        * CDSA-specified behavior).
-                        */
-                       SecPointer<Access> pubKeyAccess(new Access());
-                       pubKeyAccess->setAccess(*publicKey, maker);
-               }
-
-               // Create keychain items which will represent the keys.
-               publicKeyItem = keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId);
-               privateKeyItem = keychain->item(CSSM_DL_DB_RECORD_PRIVATE_KEY, privUniqueId);
-
-               KeyItem* impl = dynamic_cast<KeyItem*>(&(*publicKeyItem));
-               if (impl == NULL)
-               {
-                       CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-               }
-
-               outPublicKey = impl;
-
-               impl = dynamic_cast<KeyItem*>(&(*privateKeyItem));
-               if (impl == NULL)
-               {
-                       CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-               }
-
-               outPrivateKey = impl;
-       }
-       catch (...)
-       {
-               if (freeKeys)
-               {
-                       // Delete the keys if something goes wrong so we don't end up with inaccessible keys in the database.
-                       CSSM_FreeKey(csp->handle(), cred, &publicCssmKey, TRUE);
-                       CSSM_FreeKey(csp->handle(), cred, &privateCssmKey, TRUE);
-               }
-
-               if (deleteContext)
-                       CSSM_DeleteContext(ccHandle);
-
-               throw;
-       }
-
-       if (freeKeys)
-       {
-               CSSM_FreeKey(csp->handle(), NULL, &publicCssmKey, FALSE);
-               CSSM_FreeKey(csp->handle(), NULL, &privateCssmKey, FALSE);
-       }
-
-       if (deleteContext)
-               CSSM_DeleteContext(ccHandle);
-
-       if (keychain && publicKeyItem && privateKeyItem)
-       {
-               keychain->postEvent(kSecAddEvent, publicKeyItem);
-               keychain->postEvent(kSecAddEvent, privateKeyItem);
-       }
-}
-
-void
-KeyItem::importPair(
-       Keychain keychain,
-       const CSSM_KEY &publicWrappedKey,
-       const CSSM_KEY &privateWrappedKey,
-       SecPointer<Access> initialAccess,
-       SecPointer<KeyItem> &outPublicKey,
-       SecPointer<KeyItem> &outPrivateKey)
-{
-       bool freePublicKey = false;
-       bool freePrivateKey = false;
-       bool deleteContext = false;
-
-       if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP))
-               MacOSError::throwMe(errSecInvalidKeychain);
-
-       SSDbImpl* impl = dynamic_cast<SSDbImpl *>(&(*keychain->database()));
-       if (impl == NULL)
-       {
-               CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-       }
-
-       SSDb ssDb(impl);
-       CssmClient::CSP csp(keychain->csp());
-       CssmClient::CSP appleCsp(gGuidAppleCSP);
-
-       // Create a Access::Maker for the initial owner of the private key.
-       ResourceControlContext rcc;
-       memset(&rcc, 0, sizeof(rcc));
-       Access::Maker maker(Allocator::standard(), Access::Maker::kAnyMakerType);
-       // @@@ Potentially provide a credential argument which allows us to unwrap keys in the csp.
-       // Currently the CSP lets anyone do this, but we might restrict this in the future, e.g.
-       // a smartcard could require out of band pin entry before a key can be generated.
-       maker.initialOwner(rcc);
-       // Create the cred we need to manipulate the keys until we actually set a new access control for them.
-       const AccessCredentials *cred = maker.cred();
-
-       CSSM_KEY publicCssmKey, privateCssmKey;
-       memset(&publicCssmKey, 0, sizeof(publicCssmKey));
-       memset(&privateCssmKey, 0, sizeof(privateCssmKey));
-
-       CSSM_CC_HANDLE ccHandle = 0;
-
-       Item publicKeyItem, privateKeyItem;
-       try
-       {
-               CSSM_RETURN status;
-
-               // Calculate the hash of the public key using the appleCSP.
-               CssmClient::PassThrough passThrough(appleCsp);
-               void *outData;
-               CssmData *cssmData;
-
-               /* Given a CSSM_KEY_PTR in any format, obtain the SHA-1 hash of the
-               * associated key blob.
-               * Key is specified in CSSM_CSP_CreatePassThroughContext.
-               * Hash is allocated bythe CSP, in the App's memory, and returned
-               * in *outData. */
-               passThrough.key(&publicWrappedKey);
-               passThrough(CSSM_APPLECSP_KEYDIGEST, NULL, &outData);
-               cssmData = reinterpret_cast<CssmData *>(outData);
-               CssmData &pubKeyHash = *cssmData;
-
-               status = CSSM_CSP_CreateSymmetricContext(csp->handle(), publicWrappedKey.KeyHeader.WrapAlgorithmId, CSSM_ALGMODE_NONE, NULL, NULL, NULL, CSSM_PADDING_NONE, NULL, &ccHandle);
-               if (status)
-                       CssmError::throwMe(status);
-               deleteContext = true;
-
-               CSSM_DL_DB_HANDLE dldbHandle = ssDb->handle();
-               CSSM_DL_DB_HANDLE_PTR dldbHandlePtr = &dldbHandle;
-               CSSM_CONTEXT_ATTRIBUTE contextAttributes = { CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(dldbHandle), { (char *)dldbHandlePtr } };
-               status = CSSM_UpdateContextAttributes(ccHandle, 1, &contextAttributes);
-               if (status)
-                       CssmError::throwMe(status);
-
-               // Unwrap the the keys
-               CSSM_DATA descriptiveData = {0, NULL};
-
-               status = CSSM_UnwrapKey(
-                       ccHandle,
-                       NULL,
-                       &publicWrappedKey,
-                       publicWrappedKey.KeyHeader.KeyUsage,
-                       publicWrappedKey.KeyHeader.KeyAttr | CSSM_KEYATTR_PERMANENT,
-                       &pubKeyHash,
-                       &rcc,
-                       &publicCssmKey,
-                       &descriptiveData);
-
-               if (status)
-                       CssmError::throwMe(status);
-               freePublicKey = true;
-
-               if (descriptiveData.Data != NULL)
-                       free (descriptiveData.Data);
-
-               status = CSSM_UnwrapKey(
-                       ccHandle,
-                       NULL,
-                       &privateWrappedKey,
-                       privateWrappedKey.KeyHeader.KeyUsage,
-                       privateWrappedKey.KeyHeader.KeyAttr | CSSM_KEYATTR_PERMANENT,
-                       &pubKeyHash,
-                       &rcc,
-                       &privateCssmKey,
-                       &descriptiveData);
-
-               if (status)
-                       CssmError::throwMe(status);
-
-               if (descriptiveData.Data != NULL)
-                       free (descriptiveData.Data);
-
-               freePrivateKey = true;
-
-               // Find the keys we just generated in the DL to get SecKeyRefs to them
-               // so we can change the label to be the hash of the public key, and
-               // fix up other attributes.
-
-               // Look up public key in the DLDB.
-               DbAttributes pubDbAttributes;
-               DbUniqueRecord pubUniqueId;
-               SSDbCursor dbPubCursor(ssDb, 1);
-               dbPubCursor->recordType(CSSM_DL_DB_RECORD_PUBLIC_KEY);
-               dbPubCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, pubKeyHash);
-               CssmClient::Key publicKey;
-               if (!dbPubCursor->nextKey(&pubDbAttributes, publicKey, pubUniqueId))
-                       MacOSError::throwMe(errSecItemNotFound);
-
-               // Look up private key in the DLDB.
-               DbAttributes privDbAttributes;
-               DbUniqueRecord privUniqueId;
-               SSDbCursor dbPrivCursor(ssDb, 1);
-               dbPrivCursor->recordType(CSSM_DL_DB_RECORD_PRIVATE_KEY);
-               dbPrivCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, pubKeyHash);
-               CssmClient::Key privateKey;
-               if (!dbPrivCursor->nextKey(&privDbAttributes, privateKey, privUniqueId))
-                       MacOSError::throwMe(errSecItemNotFound);
-
-               // @@@ Not exception safe!
-               csp.allocator().free(cssmData->Data);
-               csp.allocator().free(cssmData);
-
-               auto_ptr<string>privDescription;
-               auto_ptr<string>pubDescription;
-               try {
-                       privDescription.reset(new string(initialAccess->promptDescription()));
-                       pubDescription.reset(new string(initialAccess->promptDescription()));
-               }
-               catch(...) {
-                       /* this path taken if no promptDescription available, e.g., for complex ACLs */
-                       privDescription.reset(new string("Private key"));
-                       pubDescription.reset(new string("Public key"));
-               }
-
-               // Set the label of the public key to the public key hash.
-               // Set the PrintName of the public key to the description in the acl.
-               pubDbAttributes.add(kInfoKeyPrintName, *pubDescription);
-               pubUniqueId->modify(CSSM_DL_DB_RECORD_PUBLIC_KEY, &pubDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
-
-               // Set the label of the private key to the public key hash.
-               // Set the PrintName of the private key to the description in the acl.
-               privDbAttributes.add(kInfoKeyPrintName, *privDescription);
-               privUniqueId->modify(CSSM_DL_DB_RECORD_PRIVATE_KEY, &privDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
-
-               // Finally fix the acl and owner of the private key to the specified access control settings.
-               initialAccess->setAccess(*privateKey, maker);
-
-               // Make the public key acl completely open
-               SecPointer<Access> pubKeyAccess(new Access());
-               pubKeyAccess->setAccess(*publicKey, maker);
-
-               // Create keychain items which will represent the keys.
-               publicKeyItem = keychain->item(CSSM_DL_DB_RECORD_PUBLIC_KEY, pubUniqueId);
-               privateKeyItem = keychain->item(CSSM_DL_DB_RECORD_PRIVATE_KEY, privUniqueId);
-
-               KeyItem* impl = dynamic_cast<KeyItem*>(&(*publicKeyItem));
-               if (impl == NULL)
-               {
-                       CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-               }
-
-               outPublicKey = impl;
-
-               impl = dynamic_cast<KeyItem*>(&(*privateKeyItem));
-               if (impl == NULL)
-               {
-                       CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-               }
-               outPrivateKey = impl;
-       }
-       catch (...)
-       {
-               if (freePublicKey)
-                       CSSM_FreeKey(csp->handle(), cred, &publicCssmKey, TRUE);
-               if (freePrivateKey)
-                       CSSM_FreeKey(csp->handle(), cred, &privateCssmKey, TRUE);
-
-               if (deleteContext)
-                       CSSM_DeleteContext(ccHandle);
-
-               throw;
-       }
-
-       if (freePublicKey)
-               CSSM_FreeKey(csp->handle(), cred, &publicCssmKey, FALSE);
-       if (freePrivateKey)
-               CSSM_FreeKey(csp->handle(), cred, &privateCssmKey, FALSE);
-
-       if (deleteContext)
-               CSSM_DeleteContext(ccHandle);
-
-       if (keychain && publicKeyItem && privateKeyItem)
-       {
-               KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, publicKeyItem);
-               KCEventNotifier::PostKeychainEvent(kSecAddEvent, keychain, privateKeyItem);
-       }
-}
-
-SecPointer<KeyItem>
-KeyItem::generateWithAttributes(const SecKeychainAttributeList *attrList,
-       Keychain keychain,
-       CSSM_ALGORITHMS algorithm,
-       uint32 keySizeInBits,
-       CSSM_CC_HANDLE contextHandle,
-       CSSM_KEYUSE keyUsage,
-       uint32 keyAttr,
-       SecPointer<Access> initialAccess)
-{
-       CssmClient::CSP appleCsp(gGuidAppleCSP);
-       CssmClient::CSP csp(NULL);
-       SSDb ssDb(NULL);
-       uint8 labelBytes[20];
-       CssmData label(labelBytes, sizeof(labelBytes));
-       bool freeKey = false;
-       bool deleteContext = false;
-       const CSSM_DATA *plabel = NULL;
-
-       if (keychain)
-       {
-               if (!(keychain->database()->dl()->subserviceMask() & CSSM_SERVICE_CSP))
-                       MacOSError::throwMe(errSecInvalidKeychain);
-
-               SSDbImpl* impl = dynamic_cast<SSDbImpl *>(&(*keychain->database()));
-               if (impl == NULL)
-               {
-                       CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-               }
-
-               ssDb = SSDb(impl);
-               csp = keychain->csp();
-
-               // Generate a random label to use initially
-               CssmClient::Random random(appleCsp, CSSM_ALGID_APPLE_YARROW);
-               random.generate(label, (uint32)label.Length);
-               plabel = &label;
-       }
-       else
-       {
-               // Not a persistent key so create it in the regular csp
-               csp = appleCsp;
-       }
-
-       // Create a Access::Maker for the initial owner of the private key.
-       ResourceControlContext *prcc = NULL, rcc;
-       const AccessCredentials *cred = NULL;
-       Access::Maker maker;
-       if (keychain && initialAccess)
-       {
-               memset(&rcc, 0, sizeof(rcc));
-               // @@@ Potentially provide a credential argument which allows us to generate keys in the csp.
-               // Currently the CSP lets anyone do this, but we might restrict this in the future, e.g. a smartcard
-               // could require out-of-band pin entry before a key can be generated.
-               maker.initialOwner(rcc);
-               // Create the cred we need to manipulate the keys until we actually set a new access control for them.
-               cred = maker.cred();
-               prcc = &rcc;
-       }
-
-       CSSM_KEY cssmKey;
-
-       CSSM_CC_HANDLE ccHandle = 0;
-
-       Item keyItem;
-       try
-       {
-               CSSM_RETURN status;
-               if (contextHandle)
-                       ccHandle = contextHandle;
-               else
-               {
-                       status = CSSM_CSP_CreateKeyGenContext(csp->handle(), algorithm, keySizeInBits, NULL, NULL, NULL, NULL, NULL, &ccHandle);
-                       if (status)
-                               CssmError::throwMe(status);
-                       deleteContext = true;
-               }
-
-               if (ssDb)
-               {
-                       CSSM_DL_DB_HANDLE dldbHandle = ssDb->handle();
-                       CSSM_DL_DB_HANDLE_PTR dldbHandlePtr = &dldbHandle;
-                       CSSM_CONTEXT_ATTRIBUTE contextAttributes = { CSSM_ATTRIBUTE_DL_DB_HANDLE, sizeof(dldbHandle), { (char *)dldbHandlePtr } };
-                       status = CSSM_UpdateContextAttributes(ccHandle, 1, &contextAttributes);
-                       if (status)
-                               CssmError::throwMe(status);
-
-                       keyAttr |= CSSM_KEYATTR_PERMANENT;
-               }
-
-               // Generate the key
-               status = CSSM_GenerateKey(ccHandle, keyUsage, keyAttr, plabel, prcc, &cssmKey);
-               if (status)
-                       CssmError::throwMe(status);
-
-               if (ssDb)
-               {
-                       freeKey = true;
-                       // Find the key we just generated in the DL and get a SecKeyRef
-                       // so we can specify the label attribute(s) and initial ACL.
-
-                       // Look up key in the DLDB.
-                       DbAttributes dbAttributes;
-                       DbUniqueRecord uniqueId;
-                       SSDbCursor dbCursor(ssDb, 1);
-                       dbCursor->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY);
-                       dbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, label);
-                       CssmClient::Key key;
-                       if (!dbCursor->nextKey(&dbAttributes, key, uniqueId))
-                               MacOSError::throwMe(errSecItemNotFound);
-
-                       // Set the initial label, application label, and application tag (if provided)
-                       if (attrList) {
-                               DbAttributes newDbAttributes;
-                               SSDbCursor otherDbCursor(ssDb, 1);
-                               otherDbCursor->recordType(CSSM_DL_DB_RECORD_SYMMETRIC_KEY);
-                               bool checkForDuplicates = false;
-
-                               for (UInt32 index=0; index < attrList->count; index++) {
-                                       SecKeychainAttribute attr = attrList->attr[index];
-                                       CssmData attrData(attr.data, attr.length);
-                                       if (attr.tag == kSecKeyPrintName) {
-                                               newDbAttributes.add(kInfoKeyPrintName, attrData);
-                                       }
-                                       if (attr.tag == kSecKeyLabel) {
-                                               newDbAttributes.add(kInfoKeyLabel, attrData);
-                                               otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyLabel, attrData);
-                                               checkForDuplicates = true;
-                                       }
-                                       if (attr.tag == kSecKeyApplicationTag) {
-                                               newDbAttributes.add(kInfoKeyApplicationTag, attrData);
-                                               otherDbCursor->add(CSSM_DB_EQUAL, kInfoKeyApplicationTag, attrData);
-                                               checkForDuplicates = true;
-                                       }
-                               }
-
-                               DbAttributes otherDbAttributes;
-                               DbUniqueRecord otherUniqueId;
-                               CssmClient::Key otherKey;
-                               if (checkForDuplicates && otherDbCursor->nextKey(&otherDbAttributes, otherKey, otherUniqueId))
-                                       MacOSError::throwMe(errSecDuplicateItem);
-
-                               uniqueId->modify(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, &newDbAttributes, NULL, CSSM_DB_MODIFY_ATTRIBUTE_REPLACE);
-                       }
-
-                       // Finally, fix the acl and owner of the key to the specified access control settings.
-                       if (initialAccess)
-                               initialAccess->setAccess(*key, maker);
-
-                       // Create keychain item which will represent the key.
-                       keyItem = keychain->item(CSSM_DL_DB_RECORD_SYMMETRIC_KEY, uniqueId);
-               }
-               else
-               {
-                       CssmClient::Key tempKey(csp, cssmKey);
-                       keyItem = new KeyItem(tempKey);
-               }
-       }
-       catch (...)
-       {
-               if (freeKey)
-               {
-                       // Delete the key if something goes wrong so we don't end up with inaccessible keys in the database.
-                       CSSM_FreeKey(csp->handle(), cred, &cssmKey, TRUE);
-               }
-
-               if (deleteContext)
-                       CSSM_DeleteContext(ccHandle);
-
-               throw;
-       }
-
-       if (freeKey)
-       {
-               CSSM_FreeKey(csp->handle(), NULL, &cssmKey, FALSE);
-       }
-
-       if (deleteContext)
-               CSSM_DeleteContext(ccHandle);
-
-       if (keychain && keyItem)
-               keychain->postEvent(kSecAddEvent, keyItem);
-
-       KeyItem* item = dynamic_cast<KeyItem*>(&*keyItem);
-       if (item == NULL)
-       {
-               CssmError::throwMe(CSSMERR_CSSM_INVALID_POINTER);
-       }
-
-       return item;
-}
-
-SecPointer<KeyItem>
-KeyItem::generate(Keychain keychain,
-       CSSM_ALGORITHMS algorithm,
-       uint32 keySizeInBits,
-       CSSM_CC_HANDLE contextHandle,
-       CSSM_KEYUSE keyUsage,
-       uint32 keyAttr,
-       SecPointer<Access> initialAccess)
-{
-       return KeyItem::generateWithAttributes(NULL, keychain,
-               algorithm, keySizeInBits, contextHandle,
-               keyUsage, keyAttr, initialAccess);
-}
-
-
-void KeyItem::RawSign(SecPadding padding, CSSM_DATA dataToSign, const AccessCredentials *credentials, CSSM_DATA& signature)
-{
-       CSSM_ALGORITHMS baseAlg = key()->header().algorithm();
-
-    if ((baseAlg != CSSM_ALGID_RSA) && (baseAlg != CSSM_ALGID_ECDSA))
-       {
-               MacOSError::throwMe(errSecParam);
-       }
-
-       CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1;
-
-       switch (padding)
-       {
-               case kSecPaddingPKCS1:
-               {
-                       paddingAlg = CSSM_PADDING_PKCS1;
-                       break;
-               }
-
-               case kSecPaddingPKCS1MD2:
-               {
-                       baseAlg = CSSM_ALGID_MD2WithRSA;
-                       break;
-               }
-
-               case kSecPaddingPKCS1MD5:
-               {
-                       baseAlg = CSSM_ALGID_MD5WithRSA;
-                       break;
-               }
-
-               case kSecPaddingPKCS1SHA1:
-               {
-                       baseAlg = CSSM_ALGID_SHA1WithRSA;
-                       break;
-               }
-
-               default:
-               {
-                       paddingAlg = CSSM_PADDING_NONE;
-                       break;
-               }
-       }
-
-       Sign signContext(csp(), baseAlg);
-       signContext.key(key());
-       signContext.set(CSSM_ATTRIBUTE_PADDING, paddingAlg);
-       signContext.cred(credentials);
-
-       CssmData data(dataToSign.Data, dataToSign.Length);
-       signContext.sign(data);
-
-    CssmData sig(signature.Data, signature.Length);
-       signContext(sig); // yes, this is an accessor.  Believe it, or not.
-    signature.Length = sig.length();
-}
-
-
-
-void KeyItem::RawVerify(SecPadding padding, CSSM_DATA dataToVerify, const AccessCredentials *credentials, CSSM_DATA sig)
-{
-       CSSM_ALGORITHMS baseAlg = key()->header().algorithm();
-    if ((baseAlg != CSSM_ALGID_RSA) && (baseAlg != CSSM_ALGID_ECDSA))
-       {
-               MacOSError::throwMe(errSecParam);
-       }
-
-       CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1;
-
-       switch (padding)
-       {
-               case kSecPaddingPKCS1:
-               {
-                       paddingAlg = CSSM_PADDING_PKCS1;
-                       break;
-               }
-
-               case kSecPaddingPKCS1MD2:
-               {
-                       baseAlg = CSSM_ALGID_MD2WithRSA;
-                       break;
-               }
-
-               case kSecPaddingPKCS1MD5:
-               {
-                       baseAlg = CSSM_ALGID_MD5WithRSA;
-                       break;
-               }
-
-               case kSecPaddingPKCS1SHA1:
-               {
-                       baseAlg = CSSM_ALGID_SHA1WithRSA;
-                       break;
-               }
-
-               default:
-               {
-                       paddingAlg = CSSM_PADDING_NONE;
-                       break;
-               }
-       }
-
-       Verify verifyContext(csp(), baseAlg);
-       verifyContext.key(key());
-       verifyContext.set(CSSM_ATTRIBUTE_PADDING, paddingAlg);
-       verifyContext.cred(credentials);
-
-       CssmData data(dataToVerify.Data, dataToVerify.Length);
-       CssmData signature(sig.Data, sig.Length);
-       verifyContext.verify(data, signature);
-}
-
-
-
-void KeyItem::Encrypt(SecPadding padding, CSSM_DATA dataToEncrypt, const AccessCredentials *credentials, CSSM_DATA& encryptedData)
-{
-       CSSM_ALGORITHMS baseAlg = key()->header().algorithm();
-       if (baseAlg != CSSM_ALGID_RSA)
-       {
-               MacOSError::throwMe(errSecParam);
-       }
-
-       CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1;
-
-       switch (padding)
-       {
-               case kSecPaddingPKCS1:
-               {
-                       paddingAlg = CSSM_PADDING_PKCS1;
-                       break;
-               }
-
-               default:
-               {
-                       paddingAlg = CSSM_PADDING_NONE;
-                       break;
-               }
-       }
-
-       CssmClient::Encrypt encryptContext(csp(), baseAlg);
-       encryptContext.key(key());
-       encryptContext.padding(paddingAlg);
-       encryptContext.cred(credentials);
-
-       CssmData inData(dataToEncrypt.Data, dataToEncrypt.Length);
-       CssmData outData(encryptedData.Data, encryptedData.Length);
-       CssmData remData((void*) NULL, 0);
-
-       encryptedData.Length = encryptContext.encrypt(inData, outData, remData);
-}
-
-
-
-void KeyItem::Decrypt(SecPadding padding, CSSM_DATA dataToDecrypt, const AccessCredentials *credentials, CSSM_DATA& decryptedData)
-{
-       CSSM_ALGORITHMS baseAlg = key()->header().algorithm();
-       if (baseAlg != CSSM_ALGID_RSA)
-       {
-               MacOSError::throwMe(errSecParam);
-       }
-
-       CSSM_ALGORITHMS paddingAlg = CSSM_PADDING_PKCS1;
-
-       switch (padding)
-       {
-               case kSecPaddingPKCS1:
-               {
-                       paddingAlg = CSSM_PADDING_PKCS1;
-                       break;
-               }
-
-
-               default:
-               {
-                       paddingAlg = CSSM_PADDING_NONE;
-                       break;
-               }
-       }
-
-       CssmClient::Decrypt decryptContext(csp(), baseAlg);
-       decryptContext.key(key());
-       decryptContext.padding(paddingAlg);
-       decryptContext.cred(credentials);
-
-       CssmData inData(dataToDecrypt.Data, dataToDecrypt.Length);
-       CssmData outData(decryptedData.Data, decryptedData.Length);
-       CssmData remData((void*) NULL, 0);
-       decryptedData.Length = decryptContext.decrypt(inData, outData, remData);
-    if (remData.Data != NULL)
-    {
-        free(remData.Data);
-    }
-}
-
-CFHashCode KeyItem::hash()
-{
-       CFHashCode result = 0;
-       const CSSM_KEY *cssmKey = key();
-       if (NULL != cssmKey)
-       {
-               unsigned char digest[CC_SHA256_DIGEST_LENGTH];
-               
-               CFIndex size_of_data = sizeof(CSSM_KEYHEADER) +  cssmKey->KeyData.Length;
-               
-               CFMutableDataRef temp_cfdata = CFDataCreateMutable(kCFAllocatorDefault, size_of_data);
-               if (NULL == temp_cfdata)
-               {
-                       return result;
-               }
-               
-               CFDataAppendBytes(temp_cfdata, (const UInt8 *)cssmKey, sizeof(CSSM_KEYHEADER));
-               CFDataAppendBytes(temp_cfdata, cssmKey->KeyData.Data, cssmKey->KeyData.Length);
-
-               if (size_of_data < 80)
-               {
-                       // If it is less than 80 bytes then CFData can be used
-                       result = CFHash(temp_cfdata);
-                       CFRelease(temp_cfdata);
-               }
-               // CFData truncates its hash value to 80 bytes. ????
-               // In order to do the 'right thing' a SHA 256 hash will be used to
-               // include all of the data
-               else
-               {
-                       memset(digest, 0, CC_SHA256_DIGEST_LENGTH);
-
-                       CC_SHA256((const void *)CFDataGetBytePtr(temp_cfdata), (CC_LONG)CFDataGetLength(temp_cfdata), digest);
-
-                       CFDataRef data_to_hash = CFDataCreateWithBytesNoCopy(kCFAllocatorDefault,
-                               (const UInt8 *)digest, CC_SHA256_DIGEST_LENGTH, kCFAllocatorNull);
-                       result = CFHash(data_to_hash);
-                       CFRelease(data_to_hash);
-                       CFRelease(temp_cfdata);
-               }
-       }
-       return result;
-}
-