]> git.saurik.com Git - apple/security.git/blobdiff - OSX/libsecurity_smime/lib/cmspubkey.c
Security-58286.260.20.tar.gz
[apple/security.git] / OSX / libsecurity_smime / lib / cmspubkey.c
index a42f322b93a76e82455147321db3d5add03b2a63..c4dc0eaa4f65397f10da3b3a2bbd4c0314698cd8 100644 (file)
 #include <security_asn1/secerr.h>
 #include <Security/SecCertificatePriv.h>
 #include <Security/SecKeyPriv.h>
+#include <Security/SecItemPriv.h>
 #include <Security/Security.h>
 #include <CoreServices/../Frameworks/CarbonCore.framework/Headers/MacErrors.h>
 #include <Security/SecCmsBase.h>
 #include <Security/secasn1t.h>
 #include <security_asn1/plarenas.h>
 #include <Security/keyTemplates.h>
+#include <CommonCrypto/CommonCryptor.h>
+#include <CommonCrypto/CommonRandomSPI.h>
+#include <CommonCrypto/CommonRandom.h>
 
 /* ====== RSA ======================================================================= */
 
@@ -66,9 +70,7 @@ SecCmsUtilEncryptSymKeyRSA(PLArenaPool *poolp, SecCertificateRef cert,
                               CSSM_DATA_PTR encKey)
 {
     OSStatus rv;
-    SecPublicKeyRef publickey;
-
-    rv = SecCertificateCopyPublicKey(cert,&publickey);
+    SecPublicKeyRef publickey = SecCertificateCopyKey(cert);
     if (publickey == NULL)
        return SECFailure;
 
@@ -86,26 +88,24 @@ SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp,
     unsigned int data_len;
     //KeyType keyType;
     void *mark = NULL;
+    CFDictionaryRef theirKeyAttrs = NULL;
 
     mark = PORT_ArenaMark(poolp);
     if (!mark)
        goto loser;
-
-#if 0
-    /* sanity check */
-    keyType = SECKEY_GetPublicKeyType(publickey);
-    PORT_Assert(keyType == rsaKey);
-    if (keyType != rsaKey) {
-       goto loser;
-    }
-#endif
     /* allocate memory for the encrypted key */
-    rv = SecKeyGetStrengthInBits(publickey, NULL, &data_len);
-    if (rv)
-       goto loser;
+    theirKeyAttrs = SecKeyCopyAttributes(publickey);
+    if (!theirKeyAttrs) {
+        goto loser;
+    }
 
+    CFNumberRef keySizeNum = CFDictionaryGetValue(theirKeyAttrs, kSecAttrKeySizeInBits);
+    if (!CFNumberGetValue(keySizeNum, kCFNumberIntType, &data_len)) {
+        goto loser;
+    }
     // Convert length to bytes;
-    data_len >>= 2;
+    data_len /= 8;
+
     encKey->Data = (unsigned char*)PORT_ArenaAlloc(poolp, data_len);
     encKey->Length = data_len;
     if (encKey->Data == NULL)
@@ -120,6 +120,9 @@ SecCmsUtilEncryptSymKeyRSAPubKey(PLArenaPool *poolp,
     return SECSuccess;
 
 loser:
+    if (theirKeyAttrs) {
+        CFRelease(theirKeyAttrs);
+    }
     if (mark) {
        PORT_ArenaRelease(poolp, mark);
     }
@@ -648,59 +651,6 @@ typedef enum {
        CAT_Ptr
 } ContextAttrType;
 
-static CSSM_RETURN cmsAddContextAttribute(
-    CSSM_CC_HANDLE CCHandle,
-    uint32 AttributeType,
-    uint32 AttributeLength,
-    ContextAttrType attrType,
-    /* specify exactly one of these */
-    const void *AttributePtr,
-    uint32 attributeInt)
-{
-    CSSM_CONTEXT_ATTRIBUTE             newAttr;        
-    CSSM_RETURN                                        crtn;
-    
-    newAttr.AttributeType     = AttributeType;
-    newAttr.AttributeLength   = AttributeLength;
-    if(attrType == CAT_Uint32) {
-           newAttr.Attribute.Uint32  = attributeInt;
-    }
-    else {
-           /* this is a union of a bunch of different pointers...*/
-           newAttr.Attribute.Data    = (CSSM_DATA_PTR)AttributePtr;
-    }
-    crtn = CSSM_UpdateContextAttributes(CCHandle, 1, &newAttr);
-    if(crtn) {
-       CSSM_PERROR("CSSM_UpdateContextAttributes", crtn);
-    }
-    return crtn;
-}
-
-static CSSM_RETURN cmsGenRand(
-    CSSM_CSP_HANDLE cspHand,
-    CSSM_SIZE len,
-    uint8 *randOut)
-{
-    CSSM_CC_HANDLE ccHand = 0;
-    CSSM_DATA randData = {len, randOut};
-    
-    CSSM_RETURN crtn = CSSM_CSP_CreateRandomGenContext(cspHand,
-           CSSM_ALGID_APPLE_YARROW,
-           NULL, /* seed*/
-           len,
-           &ccHand);
-    if(crtn) {
-       CSSM_PERROR("CSSM_CSP_CreateRandomGenContext", crtn);
-       return crtn;
-    }
-    crtn = CSSM_GenerateRandom(ccHand, &randData);
-    CSSM_DeleteContext(ccHand);
-    if(crtn) {
-       CSSM_PERROR("CSSM_GenerateRandom", crtn);
-    }
-    return crtn;
-}
-
 /* convert uint32 to big-endian 4 bytes */
 static void int32ToBytes(
        uint32_t i,
@@ -713,68 +663,6 @@ static void int32ToBytes(
     }
 }
 
-/* 
- * NULL wrap a ref key to raw key in default format. 
- */ 
-static OSStatus cmsNullWrapKey(
-    CSSM_CSP_HANDLE cspHand,
-    const CSSM_KEY *refKey,
-    CSSM_KEY_PTR rawKey)
-{
-    CSSM_DATA descData = {0, 0};
-    CSSM_RETURN crtn;
-    CSSM_CC_HANDLE ccHand;
-    CSSM_ACCESS_CREDENTIALS creds;
-    uint32 keyAttr;
-    
-    memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));        
-    memset(rawKey, 0, sizeof(CSSM_KEY));
-    
-    crtn = CSSM_CSP_CreateSymmetricContext(cspHand,
-                   CSSM_ALGID_NONE,
-                   CSSM_ALGMODE_NONE,
-                   &creds,
-                   NULL,                       // unwrappingKey
-                   NULL,                       // initVector
-                   CSSM_PADDING_NONE,
-                   0,                          // Params
-                   &ccHand);
-    if(crtn) {
-       CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", crtn);
-       return crtn;
-    }
-
-    keyAttr = rawKey->KeyHeader.KeyAttr;
-    keyAttr &= ~(CSSM_KEYATTR_ALWAYS_SENSITIVE | CSSM_KEYATTR_NEVER_EXTRACTABLE |
-                            CSSM_KEYATTR_MODIFIABLE);
-    keyAttr |= CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE;
-    crtn = CSSM_WrapKey(ccHand,
-           &creds,
-           refKey,
-           &descData,
-           rawKey);
-    if(crtn != CSSM_OK) {
-       CSSM_PERROR("CSSM_WrapKey", crtn);
-    }
-    CSSM_DeleteContext(ccHand);
-    return crtn;
-}
-
-/*
- * Free memory via specified plugin's app-level allocator
- */
-static void cmsFreeCssmMemory(
-    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);
-}
-
 /* 
  * Given an OID tag, return key size and mode. 
  * NOTE: ciphers with variable key sizes, like RC2, RC4, and RC5 cannot
@@ -784,60 +672,63 @@ static void cmsFreeCssmMemory(
 static OSStatus encrAlgInfo(
     SECOidTag          oidTag,
     uint32             *keySizeBits,   /* RETURNED */
-    CSSM_ENCRYPT_MODE  *mode)          /* RETURNED */
+    CCAlgorithm         *algorithm,    /* RETURNED */
+    CCOptions           *options)      /* RETURNED */
 {
     *keySizeBits = 64;             /* default */
-    *mode = CSSM_ALGMODE_CBCPadIV8; /* default */
+    *options = kCCOptionPKCS7Padding; /* default */
     
     switch(oidTag) {
-       case SEC_OID_RC2_CBC:
-       case SEC_OID_RC4:
-       case SEC_OID_RC5_CBC_PAD:
-           dprintf("encrAlgInfo: key size unknowable\n");
-           return errSecDataNotAvailable;
-           
-       case SEC_OID_DES_EDE3_CBC:
-           *keySizeBits = 192;
-           break;
-       case SEC_OID_DES_EDE:
-           /* Not sure about this; SecCmsCipherContextStart() treats this
-            * like SEC_OID_DES_EDE3_CBC... */
-       case SEC_OID_DES_ECB:
-           *mode = CSSM_ALGMODE_ECB;
-           break;
-       case SEC_OID_DES_CBC:
-           *mode = CSSM_ALGMODE_CBC;
-           break;
-       case SEC_OID_AES_128_CBC:
-           *keySizeBits = 128;
-           break;
-       case SEC_OID_AES_192_CBC:
-           *keySizeBits = 192;
-           break;
-       case SEC_OID_AES_256_CBC:
-           *keySizeBits = 256;
-           break;
-       case SEC_OID_AES_128_ECB:
-           *keySizeBits = 128;
-           *mode = CSSM_ALGMODE_ECB;
-           break;
-       case SEC_OID_AES_192_ECB:
-           *keySizeBits = 192;
-           *mode = CSSM_ALGMODE_ECB;
-           break;
-       case SEC_OID_AES_256_ECB:
-           *keySizeBits = 256;
-           *mode = CSSM_ALGMODE_ECB;
-           break;
-       case SEC_OID_DES_OFB:
-           *mode = CSSM_ALGMODE_OFB;
-           break;
-       case SEC_OID_DES_CFB:
-           *mode = CSSM_ALGMODE_CFB;
-           break;
-       default:
-           dprintf("encrAlgInfo: unknown alg tag (%d)\n", (int)oidTag);
-           return errSecDataNotAvailable;          
+        case SEC_OID_RC2_CBC:
+        case SEC_OID_RC4:
+        case SEC_OID_RC5_CBC_PAD:
+            dprintf("encrAlgInfo: key size unknowable\n");
+            return errSecDataNotAvailable;
+        case SEC_OID_DES_EDE:
+            /* Not sure about this; SecCmsCipherContextStart() treats this
+             * like SEC_OID_DES_EDE3_CBC... */
+            *options = kCCOptionECBMode;
+            // fall through
+        case SEC_OID_DES_EDE3_CBC:
+            *keySizeBits = 192;
+            *algorithm = kCCAlgorithm3DES;
+            break;
+        case SEC_OID_DES_ECB:
+            *options = kCCOptionECBMode;
+            // fall through
+        case SEC_OID_DES_CBC:
+            *algorithm = kCCAlgorithmDES;
+            break;
+        case SEC_OID_AES_128_CBC:
+            *keySizeBits = 128;
+            *algorithm = kCCAlgorithmAES;
+            break;
+        case SEC_OID_AES_192_CBC:
+            *keySizeBits = 192;
+            *algorithm = kCCAlgorithmAES;
+            break;
+        case SEC_OID_AES_256_CBC:
+            *keySizeBits = 256;
+            *algorithm = kCCAlgorithmAES;
+            break;
+        case SEC_OID_AES_128_ECB:
+            *keySizeBits = 128;
+            *algorithm = kCCAlgorithmAES;
+            *options = kCCOptionECBMode;
+            break;
+        case SEC_OID_AES_192_ECB:
+            *keySizeBits = 192;
+            *algorithm = kCCAlgorithmAES;
+            *options = kCCOptionECBMode;
+            break;
+        case SEC_OID_AES_256_ECB:
+            *keySizeBits = 256;
+            *algorithm = kCCAlgorithmAES;
+            *options = kCCOptionECBMode;
+            break;
+        default:
+            dprintf("encrAlgInfo: unknown alg tag (%d)\n", (int)oidTag);
+            return errSecDataNotAvailable;
     }
     return noErr;
 }
@@ -861,216 +752,120 @@ SecCmsUtilEncryptSymKeyECDH(
                                 * KeyAgreeRecipientInfo.originator.OriginatorPublicKey */
 {
     OSStatus rv = noErr;
-    CSSM_KEY ourPrivKeyCssm;
-    CSSM_KEY ourPubKeyCssm;
-    SecKeyRef theirPubKeyRef = NULL;
-    CSSM_KEY_PTR theirPubKeyCssm = NULL;
-    const CSSM_KEY *cekCssmRef = NULL;
-    uint32 ecdhKeySizeBits;
-    CSSM_CSP_HANDLE rawCspHand = SecCspHandleForAlgorithm(CSSM_ALGID_ECDH);
-    CSSM_CC_HANDLE ccHand = 0;
-    CSSM_RETURN crtn;
-    CSSM_DATA keyLabel = {8, (uint8 *)"tempKey"};
+    SecKeyRef theirPubKey = NULL, ourPubKey = NULL, ourPrivKey = NULL;
+    CFDictionaryRef theirKeyAttrs = NULL, ourKeyParams = NULL, kekParams = NULL;
+    uint8_t iv[ECDH_KEK_IV_LEN_BYTES];
+    CSSM_DATA ivData = { ECDH_KEK_IV_LEN_BYTES, iv };
     SECAlgorithmID kekAlgId;
-    uint8 iv[ECDH_KEK_IV_LEN_BYTES];
-    CSSM_DATA ivData = {ECDH_KEK_IV_LEN_BYTES, iv};
     SECOidData *kekOid;
     ECC_CMS_SharedInfo sharedInfo;
     CSSM_DATA sharedInfoEnc = {0, NULL};
     uint8 nullData[2] = {SEC_ASN1_NULL, 0};
     uint8 keyLenAsBytes[4];
-    CSSM_KEY kekDerive;
-    CSSM_DATA certData;
-    CSSM_CL_HANDLE clHand;
-    CSSM_ACCESS_CREDENTIALS creds;
-    CSSM_DATA paramData = {0, NULL};
-    CSSM_KEY cekCssm;
-    CSSM_CSP_HANDLE refCspHand;
-    CSSM_SIZE bytesEncrypted;
-    CSSM_DATA remData = {0, NULL};
-    CSSM_DATA ctext = {0, NULL};
-    CSSM_X509_SUBJECT_PUBLIC_KEY_INFO subjPubKey;
-    
-    if(rawCspHand == 0) {
-       return internalComponentErr;
-    }
-    
-    memset(&ourPrivKeyCssm, 0, sizeof(CSSM_KEY));
-    memset(&ourPubKeyCssm, 0, sizeof(CSSM_KEY));
-    memset(&cekCssm, 0, sizeof(CSSM_KEY));
-    memset(&kekDerive, 0, sizeof(kekDerive));
-   
+    CFDataRef sharedInfoData = NULL, kekData = NULL, ourPubData = NULL;
+    CFNumberRef kekLen = NULL;
+    CFErrorRef error = NULL;
+    CCCryptorRef ciphercc = NULL;
+
     encKey->Data = NULL;
     encKey->Length = 0;
-    
-    /* 
-     * Create our ECDH key pair matching the recipient's key.
-     * Get the public key in "read-only" OCTET_STRING format, which 
-     * is the ECPoint we put in 
-     * KeyAgreeRecipientInfo.originator.OriginatorPublicKey.
-     */
-    rv = SecCertificateGetData(cert, &certData);
-    if(rv) {
-       CSSM_PERROR("SecCertificateGetData", rv);
-       return rv;
-    }
-    rv = SecCertificateGetCLHandle(cert, &clHand);
-    if(rv) {
-       CSSM_PERROR("SecCertificateGetCLHandle", rv);
-       return rv;
-    }
-    rv = CSSM_CL_CertGetKeyInfo(clHand, &certData, &theirPubKeyCssm);
-     if(rv) {
-       CSSM_PERROR("CSSM_CL_CertGetKeyInfo", rv);
-       return rv;
-    }
-   
-    /* 
-     * Verify the EC curve of the recipient's public key. It's in the 
-     * public key's AlgId.parameters as an OID. The key we were
-     * given is in CSSM_X509_SUBJECT_PUBLIC_KEY_INFO form.
-     */
-    memset(&subjPubKey, 0, sizeof(subjPubKey));
-    if(SEC_ASN1DecodeItem(poolp, &subjPubKey, kSecAsn1SubjectPublicKeyInfoTemplate, 
-           &theirPubKeyCssm->KeyData)) {
-       dprintf("SecCmsUtilEncryptSymKeyECDH: error decoding SubjPubKey\n");
-       /* oh well, keep going */
-    }
-    else {
-       if(subjPubKey.algorithm.parameters.Data != NULL) {
-           CSSM_DATA curveOid;
-           if(SEC_ASN1DecodeItem(poolp, &curveOid, kSecAsn1ObjectIDTemplate, 
-                   &subjPubKey.algorithm.parameters)) {
-               dprintf("SecCmsUtilEncryptSymKeyECDH: error decoding curveOid\n");
-               /* oh well, keep going */
-           }
-           else {
-               /* We have the curve OID. Any other errors are fatal. */
-               SECOidTag oidTag = SECOID_FindOIDTag(&curveOid);
-               switch(oidTag) {
-                   case SEC_OID_SECP_256_R1:
-                   case SEC_OID_SECP_384_R1:
-                   case SEC_OID_SECP_521_R1:
-                       break;
-                   default:
-                       dprintf("SecCmsUtilEncryptSymKeyECDH: unsupported curveOid\n");
-                       rv = CSSMERR_CSP_INVALID_KEY;
-                       goto loser;
-               }
-           }
-       }
+
+    /* Copy the recipient's static public ECDH key */
+    theirPubKey = SecCertificateCopyKey(cert);
+    if (rv || !theirPubKey) {
+        dprintf("SecCmsUtilEncryptSymKeyECDH: failed to get public key from cert, %d\n", (int)rv);
+        goto out;
     }
-    
-    ecdhKeySizeBits = theirPubKeyCssm->KeyHeader.LogicalKeySizeInBits;
-    crtn = CSSM_CSP_CreateKeyGenContext(rawCspHand,
-           CSSM_ALGID_ECDSA,
-           ecdhKeySizeBits,
-           NULL,                       // Seed
-           NULL,                       // Salt
-           NULL,                       // StartDate
-           NULL,                       // EndDate
-           NULL,                       // Params
-           &ccHand);
-    if(crtn) {
-       CSSM_PERROR("CSSM_CSP_CreateKeyGenContext", crtn);
-       rv = crtn;
-       goto loser;
+
+    theirKeyAttrs = SecKeyCopyAttributes(theirPubKey);
+    if (!theirKeyAttrs) {
+        dprintf("SecCmsUtilEncryptSymKeyECDH: failed to get key attributes\n");
+        goto out;
     }
-    crtn = cmsAddContextAttribute(ccHand,
-       CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT,
-       sizeof(uint32), 
-       CAT_Uint32,
-       NULL,
-       CSSM_KEYBLOB_RAW_FORMAT_OCTET_STRING);
-    if(crtn) {
-       CSSM_PERROR("AddContextAttribute(CSSM_ATTRIBUTE_PUBLIC_KEY_FORMAT)", crtn);
-       rv = crtn;
-       goto loser;
+
+    CFStringRef keyType = NULL;
+    CFNumberRef keySizeNum = NULL;
+    keyType = CFDictionaryGetValue(theirKeyAttrs, kSecAttrKeyType);
+    keySizeNum = CFDictionaryGetValue(theirKeyAttrs, kSecAttrKeySizeInBits);
+
+    if (!CFEqual(kSecAttrKeyTypeECSECPrimeRandom, keyType)) {
+        dprintf("SecCmsUtilEncryptSymKeyECDH: unsupported key type\n");
+        rv = CSSMERR_CSP_INVALID_KEY;
+        goto out;
     }
 
-    crtn = CSSM_GenerateKeyPair(ccHand,
-           CSSM_KEYUSE_DERIVE,
-           CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE,
-           &keyLabel,
-           &ourPubKeyCssm,
-           CSSM_KEYUSE_DERIVE,
-           CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
-           &keyLabel,          
-           NULL,                       // CredAndAclEntry
-           &ourPrivKeyCssm);
-    CSSM_DeleteContext(ccHand);
-    ccHand = 0;
-    if(crtn) {
-       CSSM_PERROR("CSSM_GenerateKeyPair", crtn);
-       rv = crtn;
-       goto loser;
+    /* Generate ephemeral ECDH key */
+    const void *keys[] = { kSecAttrKeyType, kSecAttrKeySizeInBits, kSecAttrNoLegacy};
+    const void *values[] = { keyType, keySizeNum, kCFBooleanTrue };
+    ourKeyParams = CFDictionaryCreate(NULL, keys, values, 3,
+                                      &kCFTypeDictionaryKeyCallBacks,
+                                      &kCFTypeDictionaryValueCallBacks);
+    rv = SecKeyGeneratePair(ourKeyParams, &ourPubKey, &ourPrivKey);
+    if (rv || !ourPubKey || !ourPrivKey) {
+        dprintf("SecKeyGeneratePair: unable to generate ECDH key pair, %d\n", (int)rv);
+        goto out;
     }
-    pubKey->Length = ourPubKeyCssm.KeyData.Length;
-    pubKey->Data = (uint8 *)PORT_ArenaAlloc(poolp, pubKey->Length);
-    memmove(pubKey->Data, ourPubKeyCssm.KeyData.Data, pubKey->Length);
-    dumpBuf("sender's public key", pubKey);
-    
-    /*
-     * Cook up random UKM 
-     */
-    ukm->Data = (uint8 *)PORT_ArenaAlloc(poolp, UKM_LENGTH);
+
+    /* Generate UKM */
+    ukm->Data = PORT_Alloc(UKM_LENGTH);
     ukm->Length = UKM_LENGTH;
-    crtn = cmsGenRand(rawCspHand, UKM_LENGTH, ukm->Data);
-    if(crtn) {
-       goto loser;
+    rv = CCRandomCopyBytes(kCCRandomDefault, ukm->Data, UKM_LENGTH);
+    if (rv || !ukm->Data) {
+        dprintf("CCRandomGenerateBytes failed, %d", (int)rv);
+        goto out;
     }
-    dumpBuf("sender UKM", ukm);
-    
+
     /*
      * OK, we have to set up a weird SECAlgorithmID.
      * algorithm = dhSinglePass-stdDH-sha1kdf-scheme
-     * params = an encoded SECAlgorithmID representing the KEK algorithm, with 
+     * params = an encoded SECAlgorithmID representing the KEK algorithm, with
      *   algorithm = whatever we pick
      *   parameters = IV as octet string (though I haven't seen that specified
      *               anywhere; it's how the CEK IV is encoded)
-     *
-     * First, the 8-byte random IV, encoded as octet string
      */
-    crtn = cmsGenRand(rawCspHand, ECDH_KEK_IV_LEN_BYTES, iv);
-    if(crtn) {
-       goto loser;
+
+    /* Generate 8-byte IV */
+    rv = CCRandomCopyBytes(kCCRandomDefault, iv, ECDH_KEK_IV_LEN_BYTES);
+    if (rv) {
+        dprintf("CCRandomGenerateBytes failed, %d", (int)rv);
+        goto out;
     }
     dumpBuf("sender IV", &ivData);
-    
+
     memset(&kekAlgId, 0, sizeof(kekAlgId));
     if (!SEC_ASN1EncodeItem(poolp, &kekAlgId.parameters,
-           &ivData, kSecAsn1OctetStringTemplate)) {
-       rv = internalComponentErr;
-       goto loser;
+                            &ivData, kSecAsn1OctetStringTemplate)) {
+        rv = internalComponentErr;
+        goto out;
     }
 
     /* Drop in the KEK OID and encode the whole thing */
     kekOid = SECOID_FindOIDByTag(ECDH_KEK_ALG_TAG);
     if(kekOid == NULL) {
-       dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n");
-       rv = internalComponentErr;
-       goto loser;
+        dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n");
+        rv = internalComponentErr;
+        goto out;
     }
     kekAlgId.algorithm = kekOid->oid;
     memset(keyEncAlg, 0, sizeof(*keyEncAlg));
     if (!SEC_ASN1EncodeItem(poolp, &keyEncAlg->parameters,
-           &kekAlgId, SECOID_AlgorithmIDTemplate)) {
-       rv = internalComponentErr;
-       goto loser;
+                            &kekAlgId, SECOID_AlgorithmIDTemplate)) {
+        rv = internalComponentErr;
+        goto out;
     }
     kekOid = SECOID_FindOIDByTag(SEC_OID_DH_SINGLE_STD_SHA1KDF);
     if(kekOid == NULL) {
-       dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n");
-       rv = internalComponentErr;
-       goto loser;
+        dprintf("SecCmsUtilEncryptSymKeyECDH: OID screwup\n");
+        rv = internalComponentErr;
+        goto out;
     }
     keyEncAlg->algorithm = kekOid->oid;
-   
-    /* 
-     * Now in order to derive the KEK proper, we have to create a 
+
+    /*
+     * Now in order to derive the KEK proper, we have to create a
      * ECC-CMS-SharedInfo, which does not appear in the message, and DER
-     * encode that struct, the result of which is used as the 
-     * SharedInfo value in the KEK key derive. 
+     * encode that struct, the result of which is used as the
+     * SharedInfo value in the KEK key derive.
      */
     memset(&sharedInfo, 0, sizeof(sharedInfo));
     kekOid = SECOID_FindOIDByTag(ECDH_KEK_ALG_TAG);
@@ -1082,146 +877,102 @@ SecCmsUtilEncryptSymKeyECDH(
     sharedInfo.suppPubInfo.Length = 4;
     sharedInfo.suppPubInfo.Data = keyLenAsBytes;
     if (!SEC_ASN1EncodeItem(poolp, &sharedInfoEnc,
-           &sharedInfo, ECC_CMS_SharedInfoTemplate)) {
-       rv = internalComponentErr;
-       goto loser;
+                            &sharedInfo, ECC_CMS_SharedInfoTemplate)) {
+        rv = internalComponentErr;
+        goto out;
     }
     dumpBuf("sender encoded SharedInfo", &sharedInfoEnc);
-   
-    /*
-     * Since we're using the raw CSP here, we can provide the "other" public 
-     * key as an actual CSSM_KEY. When unwrapping, we won't be able to do that
-     * since we'll be using our private key obtained from a SecIdentityRef. 
-     */
-    memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-    crtn = CSSM_CSP_CreateDeriveKeyContext(rawCspHand,
-               CSSM_ALGID_ECDH_X963_KDF,
-               ECDH_KEK_KEY_CSSM_ALGID,        // algorithm of the KEK
-               ECDH_KEK_KEY_LEN_BYTES * 8,
-               &creds,
-               &ourPrivKeyCssm,        // BaseKey
-               0,                      // IterationCount
-               &sharedInfoEnc,         // Salt
-               0,                      // Seed
-               &ccHand);
-    if(crtn) {
-       CSSM_PERROR("CSSM_CSP_CreateDeriveKeyContext", crtn);
-       rv = crtn;
-       goto loser;
-    }
-    
-    /* add recipient's pub key as a context attr */
-    crtn = cmsAddContextAttribute(ccHand,
-           CSSM_ATTRIBUTE_PUBLIC_KEY,
-           sizeof(CSSM_KEY),   
-           CAT_Ptr,
-           (void *)theirPubKeyCssm,
-           0);
-    if(crtn) {
-       rv = crtn;
-       goto loser;
-    }
-    /* Derive the KEK */
-    crtn = CSSM_DeriveKey(ccHand,
-           &paramData,
-           CSSM_KEYUSE_ANY,
-           CSSM_KEYATTR_RETURN_DATA | CSSM_KEYATTR_EXTRACTABLE,
-           &keyLabel,
-           NULL,                               // cread/acl
-           &kekDerive);
-    if(crtn) {
-       CSSM_PERROR("CSSM_DeriveKey", crtn);
-       rv = crtn;
-       goto loser;
-    }
-    CSSM_DeleteContext(ccHand);
-    ccHand = 0;
-   
-    /* 
-     * Obtain the raw CEK bits.
-     */
-    rv = SecKeyGetCSSMKey(key, &cekCssmRef);
-    if(rv) {
-       CSSM_PERROR("SecKeyGetCSSMKey", rv);
-       goto loser;
-    }
-    rv = SecKeyGetCSPHandle(key, &refCspHand);
-    if(rv) {
-       CSSM_PERROR("SecKeyGetCSPHandle", rv);
-       goto loser;
-    }
-    rv = cmsNullWrapKey(refCspHand, cekCssmRef, &cekCssm);
-    if(rv) {
-       goto loser;
+
+    /* Derive KEK */
+    sharedInfoData = CFDataCreate(NULL, sharedInfoEnc.Data, sharedInfoEnc.Length);
+    int32_t ecdh_key_key_len = ECDH_KEK_KEY_LEN_BYTES;
+    kekLen = CFNumberCreate(NULL, kCFNumberSInt32Type, &ecdh_key_key_len);
+    const void *kekKeys[] = { kSecKeyKeyExchangeParameterRequestedSize, kSecKeyKeyExchangeParameterSharedInfo };
+    const void *kekValues[] = { kekLen, sharedInfoData };
+    kekParams = CFDictionaryCreate(NULL, kekKeys, kekValues, 2,
+                                   &kCFTypeDictionaryKeyCallBacks,
+                                   &kCFTypeDictionaryValueCallBacks);
+    kekData = SecKeyCopyKeyExchangeResult(ourPrivKey, kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1,
+                                          theirPubKey, kekParams, &error);
+    if (error) {
+        dprintf("SecKeyCopyKeyExchangeResult: failed\n");
+        goto out;
     }
-    
-    /* 
-     * Finally, encrypt the raw CEK bits with the KEK we just derived
+
+    /*
+     * Encrypt the raw CEK bits with the KEK we just derived
      */
-    crtn = CSSM_CSP_CreateSymmetricContext(rawCspHand,
-           ECDH_KEK_ENCR_CSSM_ALGID,
-           CSSM_ALGMODE_CBCPadIV8,
-           NULL,                       // access cred
-           &kekDerive,
-           &ivData,                    // InitVector
-           CSSM_PADDING_PKCS7, 
-           NULL,                       // Params
-           &ccHand);
-    if(rv) {
-       CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", rv);
-       goto loser;
-    }
-    rv = CSSM_EncryptData(ccHand,
-           &cekCssm.KeyData,
-           1,
-           &ctext,
-           1,
-           &bytesEncrypted,
-           &remData);
-    if(rv) {
-       CSSM_PERROR("CSSM_EncryptData", rv);
-       goto loser;
-    }
-    encKey->Data = PORT_ArenaAlloc(poolp, bytesEncrypted);
-    encKey->Length = bytesEncrypted;
-    memmove(encKey->Data, ctext.Data, ctext.Length);
-    if(bytesEncrypted != ctext.Length) {
-       memmove(encKey->Data + ctext.Length, remData.Data, remData.Length);
-    }
-    dumpBuf("sender encKey", encKey);
-    
-loser:
-    if(ccHand) {
-       CSSM_DeleteContext(ccHand);
-    }
-    CFRELEASE(theirPubKeyRef);
-    if(ourPubKeyCssm.KeyData.Data) {
-       CSSM_FreeKey(rawCspHand, NULL, &ourPubKeyCssm, CSSM_FALSE);
-    }
-    if(ourPrivKeyCssm.KeyData.Data) {
-       CSSM_FreeKey(rawCspHand, NULL, &ourPrivKeyCssm, CSSM_FALSE);
-    }
-    if(ctext.Data) {
-       cmsFreeCssmMemory(rawCspHand, ctext.Data);
-    }
-    if(remData.Data) {
-       cmsFreeCssmMemory(rawCspHand, remData.Data);
+    rv = CCCryptorCreate(kCCEncrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding,
+                         CFDataGetBytePtr(kekData), CFDataGetLength(kekData), iv, &ciphercc);
+    if (rv) {
+        dprintf("CCCryptorCreate failed: %d\n", (int)rv);
+        goto out;
     }
-    if(cekCssm.KeyData.Data) {
-       CSSM_FreeKey(refCspHand, NULL, &cekCssm, CSSM_FALSE);
+    CSSM_KEY cek;
+    rv = cmsNullWrapKey(key, &cek);
+    if (rv) {
+        dprintf("SecKeyGetCSSMKey failed: %d\n", (int)rv);
+        goto out;
     }
-    if(kekDerive.KeyData.Data) {
-       CSSM_FreeKey(rawCspHand, NULL, &kekDerive, CSSM_FALSE);
+    size_t expectedEncKeyLength = CCCryptorGetOutputLength(ciphercc, cek.KeyData.Length, true);
+    encKey->Data = PORT_ArenaAlloc(poolp, expectedEncKeyLength);
+    size_t bytes_output = 0;
+    rv = CCCryptorUpdate(ciphercc, cek.KeyData.Data, cek.KeyData.Length, encKey->Data, expectedEncKeyLength, &bytes_output);
+    if (rv) {
+        dprintf("CCCryptorUpdate failed: %d\n", (int)rv);
+        goto out;
     }
-    if(theirPubKeyCssm) {
-       /* Allocated by CL */
-       cmsFreeCssmMemory(clHand, theirPubKeyCssm->KeyData.Data);
-       cmsFreeCssmMemory(clHand, theirPubKeyCssm);
+    size_t final_bytes_output = 0;
+    rv = CCCryptorFinal(ciphercc, encKey->Data+bytes_output, expectedEncKeyLength - bytes_output, &final_bytes_output);
+    if (rv) {
+        dprintf("CCCryptorFinal failed: %d\n", (int)rv);
+        goto out;
+    }
+    encKey->Length = bytes_output + final_bytes_output;
+
+    /* Provide our ephemeral public key to the caller */
+    ourPubData = SecKeyCopyExternalRepresentation(ourPubKey, &error);
+    if (error) {
+        dprintf("SecKeyCopyExternalRepresentation failed\n");
+        goto out;
+    }
+    pubKey->Length = CFDataGetLength(ourPubData);
+    pubKey->Data = malloc(pubKey->Length);
+    if (pubKey->Data) {
+        memcpy(pubKey->Data, CFDataGetBytePtr(ourPubData), pubKey->Length);
+    } else {
+        rv = errSecAllocate;
+    }
+    /* pubKey is bit string, convert here */
+    pubKey->Length <<= 3;
+
+out:
+    if (theirPubKey) { CFRelease(theirPubKey); }
+    if (theirKeyAttrs) { CFRelease(theirKeyAttrs); }
+    if (ourKeyParams) { CFRelease(ourKeyParams); }
+    if (ourPubKey) { CFRelease(ourPubKey); }
+    if (ourPrivKey) { CFRelease(ourPrivKey); }
+    if (sharedInfoData) { CFRelease(sharedInfoData); }
+    if (kekLen) { CFRelease(kekLen); }
+    if (kekParams) { CFRelease(kekParams); }
+    if (kekData) { CFRelease(kekData); }
+    if (error) { CFRelease(error); }
+    if (ciphercc) { CCCryptorRelease(ciphercc); }
+    if (ourPubData) { CFRelease(ourPubData); }
+    if (rv && encKey->Data) {
+        PORT_Free(encKey->Data);
+        encKey->Data = NULL;
+        encKey->Length = 0;
+    }
+    if (rv && ukm->Data) {
+        PORT_Free(ukm->Data);
+        ukm->Data = NULL;
+        ukm->Length = 0;
     }
     return rv;
 }
 
+
 #pragma mark ---- ECDH CEK key unwrap ----
 
 SecSymmetricKeyRef
@@ -1234,11 +985,9 @@ SecCmsUtilDecryptSymKeyECDH(
     SECOidTag bulkalgtag,      /* algorithm of returned key */
     CSSM_DATA_PTR pubKey)      /* sender's pub key as ECPoint from
                                 * KeyAgreeRecipientInfo.originator.OriginatorPublicKey */
-    
 {
     SecSymmetricKeyRef outKey = NULL;
     OSStatus rv = noErr;
-    const CSSM_KEY *ourPrivKeyCssm;
     PLArenaPool *pool = NULL;
     SECAlgorithmID keyAlgParam;
     SECOidData *kekOid = NULL;
@@ -1247,70 +996,58 @@ SecCmsUtilDecryptSymKeyECDH(
     CSSM_DATA sharedInfoEnc = {0, NULL};
     uint8 nullData[2] = {SEC_ASN1_NULL, 0};
     uint8 keyLenAsBytes[4];
-    CSSM_ENCRYPT_MODE kekMode;
     uint32 kekSizeBits;
-    CSSM_KEY kekDerive;
-    CSSM_RETURN crtn;
-    CSSM_ACCESS_CREDENTIALS creds;
-    CSSM_CSP_HANDLE refCspHand;
-    CSSM_CC_HANDLE ccHand = 0;
-    CSSM_DATA keyLabel = {8, (uint8 *)"tempKey"};
-    const CSSM_ACCESS_CREDENTIALS *accessCred;
-    CSSM_KEY wrappedKey;
-    CSSM_KEY unwrappedKey;
-    CSSM_ALGORITHMS bulkAlg;
-    CSSM_DATA descriptiveData = {0, NULL};
-    
-    dumpBuf("receiver encKey", encKey);
-    memset(&kekDerive, 0, sizeof(kekDerive));
+    SecKeyRef theirPubKey = NULL;
+    CFStringRef keyType = NULL;
+    CFDictionaryRef theirKeyAttrs = NULL, kekParams = NULL;
+    CFMutableDictionaryRef cekParams = NULL;
+    CFDataRef sharedInfoData = NULL, theirPubData= NULL, kekData = NULL, cekData = NULL;
+    CFNumberRef kekLen = NULL, theirKeyLen = NULL;
+    CFErrorRef error = NULL;
+    CCAlgorithm alg;
+    CCOptions options = 0;
+    CCCryptorRef ciphercc = NULL;
+    size_t theirKeySizeInBits = 0;
 
-    /* our private key in CSSM form */
-    rv = SecKeyGetCSSMKey(privkey, &ourPrivKeyCssm);
-    if(rv) {
-       CSSM_PERROR("SecKeyGetCSSMKey", rv);
-       goto loser;
-    }
-    
-    /* 
+    /*
      * Decode keyEncAlg.params to get KEK algorithm and IV
-     */ 
+     */
     pool = PORT_NewArena(1024);
     if(pool == NULL) {
-       goto loser;
+        goto out;
     }
     memset(&keyAlgParam, 0, sizeof(keyAlgParam));
-    if(SEC_ASN1DecodeItem(pool, &keyAlgParam, SECOID_AlgorithmIDTemplate, 
-           &keyEncAlg->parameters)) {
-       dprintf("SecCmsUtilDecryptSymKeyECDH: error decoding keyAlgParams\n");
-       goto loser;
+    if(SEC_ASN1DecodeItem(pool, &keyAlgParam, SECOID_AlgorithmIDTemplate,
+                          &keyEncAlg->parameters)) {
+        dprintf("SecCmsUtilDecryptSymKeyECDH: error decoding keyAlgParams\n");
+        goto out;
     }
     kekOid = SECOID_FindOID(&keyAlgParam.algorithm);
     if(kekOid == NULL) {
-       dprintf("SecCmsUtilDecryptSymKeyECDH: unknown KEK enc OID\n");
-       goto loser;
+        dprintf("SecCmsUtilDecryptSymKeyECDH: unknown KEK enc OID\n");
+        goto out;
     }
-    rv = encrAlgInfo(kekOid->offset, &kekSizeBits, &kekMode);
+    rv = encrAlgInfo(kekOid->offset, &kekSizeBits, &alg, &options);
     if(rv) {
-       goto loser;
+        goto out;
     }
     /* IV is OCTET STRING in the alg params */
-    if(SEC_ASN1DecodeItem(pool, &iv, kSecAsn1OctetStringTemplate, 
-           &keyAlgParam.parameters)) {
-       /*
-        * Not sure here - is it legal to have no IV? I haven't seen this 
-        * addressed in any spec. Maybe we should condition the behavior
-        * here on the KEK algorithm.
-        */
-       dprintf("SecCmsUtilDecryptSymKeyECDH: no KEK IV\n");
-       goto loser;
+    if(SEC_ASN1DecodeItem(pool, &iv, kSecAsn1OctetStringTemplate,
+                          &keyAlgParam.parameters)) {
+        /*
+         * Not sure here - is it legal to have no IV? I haven't seen this
+         * addressed in any spec. Maybe we should condition the behavior
+         * here on the KEK algorithm.
+         */
+        dprintf("SecCmsUtilDecryptSymKeyECDH: no KEK IV\n");
+        goto out;
     }
-  
-    /* 
-     * Now in order to derive the KEK proper, we have to create a 
+
+    /*
+     * Now in order to derive the KEK proper, we have to create a
      * ECC-CMS-SharedInfo, which does not appear in the message, and DER
-     * encode that struct, the result of which is used as the 
-     * SharedInfo value in the KEK key derive. 
+     * encode that struct, the result of which is used as the
+     * SharedInfo value in the KEK key derive.
      */
     memset(&sharedInfo, 0, sizeof(sharedInfo));
     sharedInfo.algId.algorithm = kekOid->oid;
@@ -1321,129 +1058,107 @@ SecCmsUtilDecryptSymKeyECDH(
     sharedInfo.suppPubInfo.Length = 4;
     sharedInfo.suppPubInfo.Data = keyLenAsBytes;
     if (!SEC_ASN1EncodeItem(pool, &sharedInfoEnc,
-           &sharedInfo, ECC_CMS_SharedInfoTemplate)) {
-       rv = internalComponentErr;
-       goto loser;
+                            &sharedInfo, ECC_CMS_SharedInfoTemplate)) {
+        rv = internalComponentErr;
+        goto out;
     }
     dumpBuf("receiver encoded SharedInfo", &sharedInfoEnc);
     dumpBuf("receiver IV", &iv);
     dumpBuf("receiver UKM", ukm);
     dumpBuf("sender's public key", pubKey);
 
-    /* 
-     * Using the Sec-layer CSPDL, "other's" public key specified as ECPOint param. Which
-     * is fortunate because that's what we have...
-     */
-    memset(&creds, 0, sizeof(CSSM_ACCESS_CREDENTIALS));
-    rv = SecKeyGetCSPHandle(privkey, &refCspHand);
-    if(rv) {
-       CSSM_PERROR("SecKeyGetCSPHandle", rv);
-       goto loser;
+    /* pubKey is bit string, convert here */
+    theirKeySizeInBits = pubKey->Length;
+    pubKey->Length = (theirKeySizeInBits + 7) >> 3;
+    theirPubData = CFDataCreate(NULL, pubKey->Data, pubKey->Length);
+    theirKeyLen = CFNumberCreate(NULL, kCFNumberSInt32Type, &theirKeySizeInBits);
+    const void *keys[] = { kSecAttrKeyType, kSecAttrKeyClass, kSecAttrKeySizeInBits };
+    const void *values[] = { kSecAttrKeyTypeECSECPrimeRandom, kSecAttrKeyClassPublic, theirKeyLen};
+    theirKeyAttrs = CFDictionaryCreate(NULL, keys, values, 3,
+                                       &kCFTypeDictionaryKeyCallBacks,
+                                       &kCFTypeDictionaryValueCallBacks);
+    theirPubKey = SecKeyCreateWithData(theirPubData, theirKeyAttrs, &error);
+    if (error) {
+        dprintf("SecKeyCreateWithData: failed\n");
+        goto out;
+    }
+
+    /* Derive KEK */
+    sharedInfoData = CFDataCreate(NULL, sharedInfoEnc.Data, sharedInfoEnc.Length);
+    int32_t ecdh_key_key_len = (kekSizeBits + 7) >> 3;
+    kekLen = CFNumberCreate(NULL, kCFNumberSInt32Type, &ecdh_key_key_len);
+    const void *kekKeys[] = { kSecKeyKeyExchangeParameterRequestedSize, kSecKeyKeyExchangeParameterSharedInfo };
+    const void *kekValues[] = { kekLen, sharedInfoData };
+    kekParams = CFDictionaryCreate(NULL, kekKeys, kekValues, 2,
+                                   &kCFTypeDictionaryKeyCallBacks,
+                                   &kCFTypeDictionaryValueCallBacks);
+    kekData = SecKeyCopyKeyExchangeResult(privkey, kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA1,
+                                          theirPubKey, kekParams, &error);
+    if (error) {
+        dprintf("SecKeyCopyKeyExchangeResult: failed\n");
+        goto out;
     }
-    rv = SecKeyGetCredentials(privkey,
-           CSSM_ACL_AUTHORIZATION_DERIVE,
-           kSecCredentialTypeDefault,
-           &accessCred);
+
+    /*
+     * Decrypt the raw CEK bits with the KEK we just derived
+     */
+    CSSM_DATA cek = { 0, NULL };
+    rv = CCCryptorCreate(kCCDecrypt, alg, options,
+                         CFDataGetBytePtr(kekData), CFDataGetLength(kekData), iv.Data, &ciphercc);
     if (rv) {
-       CSSM_PERROR("SecKeyGetCredentials", rv);
-       goto loser;
-    }
-    crtn = CSSM_CSP_CreateDeriveKeyContext(refCspHand,
-               CSSM_ALGID_ECDH_X963_KDF,
-               kekOid->cssmAlgorithm,  // algorithm of the KEK
-               kekSizeBits,
-               &creds,
-               ourPrivKeyCssm,         // BaseKey
-               0,                      // IterationCount
-               &sharedInfoEnc,         // Salt
-               0,                      // Seed
-               &ccHand);
-    if(crtn) {
-       CSSM_PERROR("CSSM_CSP_CreateDeriveKeyContext", crtn);
-       goto loser;
+        dprintf("CCCryptorCreate failed: %d\n", (int)rv);
+        goto out;
     }
-    crtn = CSSM_DeriveKey(ccHand,
-           pubKey,                     // param
-           CSSM_KEYUSE_ANY,
-           CSSM_KEYATTR_RETURN_REF | CSSM_KEYATTR_EXTRACTABLE,
-           &keyLabel,
-           NULL,                       // cred/acl
-           &kekDerive);
-    CSSM_DeleteContext(ccHand);
-    ccHand = 0;
-    if(crtn) {
-       CSSM_PERROR("CSSM_DeriveKey", crtn);
-       goto loser;
+    size_t expectedKeyLength = CCCryptorGetOutputLength(ciphercc, encKey->Length, true);
+    cek.Data = PORT_ArenaAlloc(pool, expectedKeyLength);
+    size_t bytes_output = 0;
+    rv = CCCryptorUpdate(ciphercc, encKey->Data, encKey->Length, cek.Data, expectedKeyLength, &bytes_output);
+    if (rv) {
+        dprintf("CCCryptorUpdate failed: %d\n", (int)rv);
+        goto out;
     }
-    /* 
-     * Decrypt the encrypted key bits with the KEK key.
-     */
-    crtn = CSSM_CSP_CreateSymmetricContext(refCspHand,
-           kekOid->cssmAlgorithm,
-           kekMode,
-           NULL,                       // access cred
-           &kekDerive,
-           &iv,                        // InitVector
-           /* FIXME is this variable too? */
-           CSSM_PADDING_PKCS7, 
-           NULL,                       // Params
-           &ccHand);
-    if(rv) {
-       CSSM_PERROR("CSSM_CSP_CreateSymmetricContext", rv);
-       goto loser;
+    size_t final_bytes_output = 0;
+    rv = CCCryptorFinal(ciphercc, cek.Data+bytes_output, expectedKeyLength - bytes_output, &final_bytes_output);
+    if (rv) {
+        dprintf("CCCryptorFinal failed: %d\n", (int)rv);
+        goto out;
     }
-    
-    memset(&wrappedKey, 0, sizeof(CSSM_KEY));
-    memset(&unwrappedKey, 0, sizeof(CSSM_KEY));
+    cek.Length = bytes_output + final_bytes_output;
 
-    bulkAlg = SECOID_FindyCssmAlgorithmByTag(bulkalgtag);
-    if(bulkAlg == CSSM_ALGID_NONE) {
-       dprintf("SecCmsUtilDecryptSymKeyECDH: unknown bulk alg\n");
-       goto loser;
+    /* create the SecSymmetricKeyRef */
+    cekData = CFDataCreate(NULL, cek.Data, cek.Length);
+    keyType = SECOID_CopyKeyTypeByTag(bulkalgtag);
+    if (!keyType) {
+        goto out;
     }
-    
-    wrappedKey.KeyHeader.HeaderVersion = CSSM_KEYHEADER_VERSION;
-    wrappedKey.KeyHeader.BlobType = CSSM_KEYBLOB_WRAPPED;
-    wrappedKey.KeyHeader.Format = CSSM_KEYBLOB_WRAPPED_FORMAT_PKCS7;
-    wrappedKey.KeyHeader.AlgorithmId = bulkAlg;
-    wrappedKey.KeyHeader.KeyClass = CSSM_KEYCLASS_SESSION_KEY;
-    wrappedKey.KeyHeader.WrapAlgorithmId = kekOid->cssmAlgorithm;
-    wrappedKey.KeyHeader.WrapMode = CSSM_ALGMODE_NONE; 
-    wrappedKey.KeyData = *encKey;
-    
-    crtn = CSSM_UnwrapKey(ccHand,
-           NULL, /* publicKey */
-           &wrappedKey,
-           CSSM_KEYUSE_DECRYPT,
-           CSSM_KEYATTR_EXTRACTABLE,
-           &keyLabel,
-           NULL, /* rcc */
-           &unwrappedKey,
-           &descriptiveData);
-    CSSM_DeleteContext(ccHand);
-    ccHand = 0;
-    if(crtn) {
-       CSSM_PERROR("CSSM_UnwrapKey", crtn);
-       goto loser;
-    }
-    rv = SecKeyCreateWithCSSMKey(&unwrappedKey, &outKey);
-    if (rv) {
-       CSSM_PERROR("SecKeyCreateWithCSSMKey", rv);
+    cekParams = CFDictionaryCreateMutable(NULL, 1,
+                                          &kCFTypeDictionaryKeyCallBacks,
+                                          &kCFTypeDictionaryValueCallBacks);
+    if (!cekParams) {
+        goto out;
     }
-  
-loser:
+    CFDictionaryAddValue(cekParams, kSecAttrKeyType, keyType);
+    outKey = SecKeyCreateFromData(cekParams, cekData, NULL);
+
+out:
     if(pool != NULL) {
-       PORT_FreeArena(pool, PR_FALSE);
-    }
-    if(kekDerive.KeyData.Data) {
-       CSSM_FreeKey(refCspHand, NULL, &kekDerive, CSSM_FALSE);
-    }
+        PORT_FreeArena(pool, PR_FALSE);
+    }
+    if (theirPubData) { CFRelease(theirPubData); }
+    if (theirKeyLen) { CFRelease(theirKeyLen); }
+    if (theirPubKey) { CFRelease(theirPubKey); }
+    if (theirKeyAttrs) { CFRelease(theirKeyAttrs); }
+    if (sharedInfoData) { CFRelease(sharedInfoData); }
+    if (kekLen) { CFRelease(kekLen); }
+    if (kekParams) { CFRelease(kekParams); }
+    if (kekData) { CFRelease(kekData); }
+    if (error) { CFRelease(error); }
+    if (ciphercc) { CCCryptorRelease(ciphercc); }
+    if (cekData) { CFRelease(cekData); }
+    if (keyType) { CFRelease(keyType); }
+    if (cekParams) { CFRelease(cekParams); }
     if(outKey == NULL) {
-       PORT_SetError(SEC_ERROR_NO_KEY);    
+        PORT_SetError(SEC_ERROR_NO_KEY);
     }
     return outKey;
 }
-
-
-