Bug 1236720 - Provide sym key derive mechanism as result of encryption of message, to be reviwed by mt BUG1236720_BRANCH
authorElio Maldonado <elio.maldonado.batiz@gmail.com>
Sun, 03 Sep 2017 09:34:30 -0700
branchBUG1236720_BRANCH
changeset 13558 ed3604e48df4bd697486b33fa34675c44cd9cab3
parent 13557 52e38f9132204fb69d016cb9126a4a72b2f68e95
child 13624 d612538f270d99e01b2b30a7c87784e0c0bcd682
push id2346
push useremaldona@redhat.com
push dateSun, 03 Sep 2017 16:39:33 +0000
bugs1236720
Bug 1236720 - Provide sym key derive mechanism as result of encryption of message, to be reviwed by mt
gtests/pk11_gtest/manifest.mn
gtests/pk11_gtest/pk11_encrypt_derive_unittest.cc
gtests/pk11_gtest/pk11_gtest.gyp
lib/softoken/pkcs11.c
lib/softoken/pkcs11c.c
--- a/gtests/pk11_gtest/manifest.mn
+++ b/gtests/pk11_gtest/manifest.mn
@@ -6,16 +6,17 @@ CORE_DEPTH = ../..
 DEPTH      = ../..
 MODULE = nss
 
 CPPSRCS = \
       pk11_aeskeywrap_unittest.cc \
       pk11_chacha20poly1305_unittest.cc \
       pk11_curve25519_unittest.cc \
       pk11_ecdsa_unittest.cc \
+      pk11_encrypt_derive_unittest.cc \
       pk11_export_unittest.cc \
       pk11_pbkdf2_unittest.cc \
       pk11_prf_unittest.cc \
       pk11_prng_unittest.cc \
       pk11_rsapss_unittest.cc \
       pk11_der_private_key_import_unittest.cc \
       $(NULL)
 
new file mode 100644
--- /dev/null
+++ b/gtests/pk11_gtest/pk11_encrypt_derive_unittest.cc
@@ -0,0 +1,200 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "pk11pub.h"
+#include "nssutil.h"
+#include <stdio.h>
+#include "prerror.h"
+#include "nss.h"
+#include "gtest/gtest.h"
+#include "scoped_ptrs.h"
+#include "util.h"
+
+#define NSS_PERROR(string) \
+  std::cerr << string << ": " << PORT_ErrorToString(PORT_GetError()) << std::endl;
+
+#define NSS_PERROR2(string1, string2) \
+  std::cerr << string1 << "-" << string2 << ": " \
+            << PORT_ErrorToString(PORT_GetError()) << std::endl;
+
+#define kKEYSIZE 16
+
+namespace nss_test {
+
+typedef enum { TYPE_STR, TYPE_AES, TYPE_DES } TEST_TYPE;
+
+class EncryptDeriveTest : public ::testing::Test {
+
+  public:
+
+    static unsigned char IV[kKEYSIZE+1];
+    static unsigned char TEST_STRING[kKEYSIZE+1];
+
+    void setup_ed_params(
+        const TEST_TYPE param_type,
+        unsigned int blocksize,
+        SECItem& d_param, SECItem& e_param) {
+
+        switch (param_type) {
+          case TYPE_STR:
+            string_.pData = (CK_BYTE_PTR) &TEST_STRING;
+            string_.ulLen = kKEYSIZE;
+            d_param.data = (unsigned char *)&string_;
+            d_param.len = sizeof(string_);
+            e_param.data = NULL;
+            e_param.len = 0;
+            break;
+          case TYPE_AES:
+            aes_.pData = (CK_BYTE_PTR) &TEST_STRING;
+            aes_.length = kKEYSIZE;
+            PORT_Memcpy(aes_.iv, &IV, blocksize);
+            d_param.data = (unsigned char *) &aes_;
+            d_param.len = sizeof(aes_);
+            e_param.data = IV;
+            e_param.len = blocksize;
+            break;
+          case TYPE_DES:
+            des_.pData = (CK_BYTE_PTR) &TEST_STRING;
+            des_.length = kKEYSIZE;
+            PORT_Memcpy(des_.iv, &IV, blocksize);
+            d_param.data = (unsigned char *) &des_;
+            d_param.len = sizeof(des_);
+            e_param.data = IV;
+            e_param.len = blocksize;
+            break;
+          default:
+            ADD_FAILURE() << "Unexpected param_type " << param_type;
+        }
+    }
+
+    void Derive(
+        const char *name,
+        TEST_TYPE param_type,
+        CK_MECHANISM_TYPE derive_mech,
+        CK_MECHANISM_TYPE encrypt_mech,
+        unsigned int blocksize,
+        bool has_check_sum
+      ) {
+
+        unsigned char test_out[16];
+        unsigned int test_out_len;
+        SECItem d_param, e_param;
+        SECItem *data;
+        SECStatus rv;
+
+        ScopedPK11SlotInfo slot(PK11_GetBestSlot(derive_mech, NULL));
+        ASSERT_NE(nullptr, slot);
+
+        ScopedPK11SymKey baseKey(
+            PK11_TokenKeyGenWithFlags(
+                slot.get(), encrypt_mech,
+                NULL, 16, NULL, CKF_ENCRYPT|CKF_DERIVE, 0, NULL));
+        ASSERT_NE(nullptr, baseKey.get());
+
+        setup_ed_params(param_type,
+                        blocksize,
+                        d_param, e_param);
+
+        CK_MECHANISM_TYPE target = has_check_sum ? CKM_DES3_CBC : CKM_AES_CBC;
+        ScopedPK11SymKey newKey(
+            PK11_Derive(baseKey.get(), derive_mech, &d_param,
+                        target, CKA_DECRYPT, kKEYSIZE));
+
+        ASSERT_NE(nullptr, newKey.get());
+
+        rv = PK11_ExtractKeyValue(newKey.get());
+        ASSERT_EQ(SECSuccess, rv);
+
+        data = PK11_GetKeyData(newKey.get());
+        ASSERT_NE(nullptr, data);
+        ASSERT_EQ((unsigned int) data->len, (unsigned int) kKEYSIZE);
+        rv = PK11_Encrypt(baseKey.get(), encrypt_mech, &e_param,
+                 test_out, &test_out_len,
+                 kKEYSIZE, TEST_STRING, kKEYSIZE);
+        ASSERT_EQ(SECSuccess, rv);
+        ASSERT_EQ((unsigned int) kKEYSIZE, test_out_len);
+        if (has_check_sum) {
+            // Des keys have a checksum, mask them out first
+            for (unsigned int j = 0; j < kKEYSIZE; j++) {
+                test_out[j] &= 0xfe;
+                data->data[j] &= 0xfe;
+            }
+        }
+        EXPECT_EQ(0, memcmp(test_out, data->data, kKEYSIZE));
+    }
+
+  protected:
+
+    CK_AES_CBC_ENCRYPT_DATA_PARAMS aes_;
+    CK_DES_CBC_ENCRYPT_DATA_PARAMS des_;
+    CK_KEY_DERIVATION_STRING_DATA string_;
+};
+
+
+TEST_F(EncryptDeriveTest, Test_DES_ECB) {
+    Derive("DES ECB", TYPE_STR, CKM_DES_ECB_ENCRYPT_DATA, CKM_DES_ECB, 8, false);
+}
+
+TEST_F(EncryptDeriveTest, Test_DES_CBC) {
+    Derive("DES CBC", TYPE_DES, CKM_DES_CBC_ENCRYPT_DATA,  CKM_DES_CBC,  8, false);
+}
+
+TEST_F(EncryptDeriveTest, Test_DES3_ECB) {
+    Derive("DES3 ECB", TYPE_STR, CKM_DES3_ECB_ENCRYPT_DATA, CKM_DES3_ECB, 8, false);
+}
+
+TEST_F(EncryptDeriveTest, Test_DES3_CBC) {
+    Derive("DES3 CBC", TYPE_DES, CKM_DES3_CBC_ENCRYPT_DATA, CKM_DES3_CBC, 8, false);
+}
+
+TEST_F(EncryptDeriveTest, Test_AES_ECB) {
+    Derive("AES ECB", TYPE_STR, CKM_AES_ECB_ENCRYPT_DATA,  CKM_AES_ECB, 16, true);
+}
+
+TEST_F(EncryptDeriveTest, Test_AES_CBC) {
+    Derive("AES CBC", TYPE_AES, CKM_AES_CBC_ENCRYPT_DATA,  CKM_AES_CBC, 16, true);
+}
+
+TEST_F(EncryptDeriveTest, Test_CAMELLIA_ECB) {
+    Derive("CAMELLIA ECB", TYPE_STR, CKM_CAMELLIA_ECB_ENCRYPT_DATA,CKM_CAMELLIA_ECB, 16, true);
+}
+
+TEST_F(EncryptDeriveTest, Test_CAMELLIA_CBC) {
+    Derive("CAMELLIA CBC", TYPE_AES, CKM_CAMELLIA_CBC_ENCRYPT_DATA,CKM_CAMELLIA_CBC, 16, true);
+}
+
+TEST_F(EncryptDeriveTest, Test_SEED_ECB) {
+    Derive("SEED ECB", TYPE_STR, CKM_SEED_ECB_ENCRYPT_DATA, CKM_SEED_ECB, 16, true);
+}
+
+TEST_F(EncryptDeriveTest, Test_SEED_CBC) {
+    Derive("SEED CBC", TYPE_AES, CKM_SEED_CBC_ENCRYPT_DATA, CKM_SEED_CBC, 16, true);
+}
+
+
+unsigned char EncryptDeriveTest::IV[] = "1234567890abcdef";
+unsigned char EncryptDeriveTest::TEST_STRING[] = "FEDCBA0987654321";
+
+
+int main(int argc, char **argv) {
+
+  SECStatus rv;
+
+  rv = NSS_InitializePRErrorTable();
+  if (rv != SECSuccess) {
+      fprintf(stderr, "Couldn't initialize NSS error table \n");
+      exit (1);
+  }
+
+  rv = NSS_NoDB_Init(NULL);
+  if (rv != SECSuccess) {
+    NSS_PERROR("NSS_NoDB_Init");
+    exit (1);
+  }
+  ::testing::InitGoogleTest(&argc, argv);
+
+  return RUN_ALL_TESTS();
+}
+
+}  // namespace nss_test
--- a/gtests/pk11_gtest/pk11_gtest.gyp
+++ b/gtests/pk11_gtest/pk11_gtest.gyp
@@ -11,16 +11,17 @@
       'target_name': 'pk11_gtest',
       'type': 'executable',
       'sources': [
         'pk11_aeskeywrap_unittest.cc',
         'pk11_aes_gcm_unittest.cc',
         'pk11_chacha20poly1305_unittest.cc',
         'pk11_curve25519_unittest.cc',
         'pk11_ecdsa_unittest.cc',
+        'pk11_encrypt_derive_unittest.cc',
         'pk11_pbkdf2_unittest.cc',
         'pk11_prf_unittest.cc',
         'pk11_prng_unittest.cc',
         'pk11_rsapss_unittest.cc',
         'pk11_der_private_key_import_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
--- a/lib/softoken/pkcs11.c
+++ b/lib/softoken/pkcs11.c
@@ -418,21 +418,32 @@ static const struct mechanismList mechan
     { CKM_IDEA_ECB, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
     { CKM_IDEA_CBC, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
     { CKM_IDEA_MAC, { 16, 16, CKF_SN_VR }, PR_TRUE },
     { CKM_IDEA_MAC_GENERAL, { 16, 16, CKF_SN_VR }, PR_TRUE },
     { CKM_IDEA_CBC_PAD, { 16, 16, CKF_EN_DE_WR_UN }, PR_TRUE },
 #endif
     /* --------------------- Secret Key Operations ------------------------ */
     { CKM_GENERIC_SECRET_KEY_GEN, { 1, 32, CKF_GENERATE }, PR_TRUE },
-    { CKM_CONCATENATE_BASE_AND_KEY, { 1, 32, CKF_GENERATE }, PR_FALSE },
-    { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_GENERATE }, PR_FALSE },
-    { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_GENERATE }, PR_FALSE },
-    { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_GENERATE }, PR_FALSE },
+    { CKM_CONCATENATE_BASE_AND_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_CONCATENATE_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_CONCATENATE_DATA_AND_BASE, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_XOR_BASE_AND_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
     { CKM_EXTRACT_KEY_FROM_KEY, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_DES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_DES_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_DES3_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_DES3_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_AES_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_AES_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_CAMELLIA_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_CAMELLIA_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_SEED_ECB_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+    { CKM_SEED_CBC_ENCRYPT_DATA, { 1, 32, CKF_DERIVE }, PR_FALSE },
+
     /* ---------------------- SSL Key Derivations ------------------------- */
     { CKM_SSL3_PRE_MASTER_KEY_GEN, { 48, 48, CKF_GENERATE }, PR_FALSE },
     { CKM_SSL3_MASTER_KEY_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
     { CKM_SSL3_MASTER_KEY_DERIVE_DH, { 8, 128, CKF_DERIVE }, PR_FALSE },
     { CKM_SSL3_KEY_AND_MAC_DERIVE, { 48, 48, CKF_DERIVE }, PR_FALSE },
     { CKM_SSL3_MD5_MAC, { 0, 16, CKF_DERIVE }, PR_FALSE },
     { CKM_SSL3_SHA1_MAC, { 0, 20, CKF_DERIVE }, PR_FALSE },
     { CKM_MD5_KEY_DERIVATION, { 0, 16, CKF_DERIVE }, PR_FALSE },
--- a/lib/softoken/pkcs11c.c
+++ b/lib/softoken/pkcs11c.c
@@ -6264,16 +6264,54 @@ sftk_ANSI_X9_63_kdf(CK_BYTE **key, CK_UL
         return sftk_compute_ANSI_X9_63_kdf(key, key_len, SharedSecret, SharedInfo,
                                            SharedInfoLen, SHA512_HashBuf, SHA512_LENGTH);
     else
         return CKR_MECHANISM_INVALID;
 }
 #endif /* NSS_DISABLE_ECC */
 
 /*
+ *  Handle The derive from a block encryption cipher
+ */
+CK_RV
+sftk_DeriveEncrypt(SFTKObject *key, CK_ULONG keySize, void *cipherInfo,
+	int blockSize, unsigned char *data, CK_ULONG len, SFTKCipher encrypt)
+{
+    unsigned char *tmpdata = NULL;
+    SECStatus rv;
+    unsigned int outLen;
+    CK_RV crv;
+
+    if ((len % blockSize) != 0) {
+        return CKR_MECHANISM_PARAM_INVALID;
+    }
+    if (keySize && (len < keySize)) {
+        return CKR_MECHANISM_PARAM_INVALID;
+    }
+    if (keySize == 0) {
+        keySize = len;
+    }
+
+    tmpdata = PORT_Alloc(len);
+    if (tmpdata == NULL) {
+        return CKR_HOST_MEMORY;
+    }
+    rv = (*encrypt)(cipherInfo, tmpdata, &outLen, len, data, len);
+    if (rv != SECSuccess) {
+        crv = sftk_MapCryptError(PORT_GetError());
+        PORT_ZFree(tmpdata, len);
+        return crv;
+    }
+
+    crv = sftk_forceAttribute (key,CKA_VALUE,tmpdata,keySize);
+    PORT_ZFree(tmpdata,len);
+    return crv;
+}
+
+/*
  * SSL Key generation given pre master secret
  */
 #define NUM_MIXERS 9
 static const char *const mixers[NUM_MIXERS] = {
     "A",
     "BB",
     "CCC",
     "DDDD",
@@ -6308,25 +6346,29 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
     CK_ULONG tmpKeySize;
     CK_ULONG IVSize;
     CK_ULONG keySize = 0;
     CK_RV crv = CKR_OK;
     CK_BBOOL cktrue = CK_TRUE;
     CK_KEY_TYPE keyType = CKK_GENERIC_SECRET;
     CK_OBJECT_CLASS classType = CKO_SECRET_KEY;
     CK_KEY_DERIVATION_STRING_DATA *stringPtr;
+    CK_AES_CBC_ENCRYPT_DATA_PARAMS *aesEncryptPtr;
+    CK_DES_CBC_ENCRYPT_DATA_PARAMS *desEncryptPtr;
+    void *cipherInfo;
     CK_MECHANISM_TYPE mechanism = pMechanism->mechanism;
     PRBool isTLS = PR_FALSE;
     PRBool isDH = PR_FALSE;
     HASH_HashType tlsPrfHash = HASH_AlgNULL;
     SECStatus rv;
     int i;
     unsigned int outLen;
     unsigned char sha_out[SHA1_LENGTH];
     unsigned char key_block[NUM_MIXERS * SFTK_MAX_MAC_LENGTH];
+    unsigned char des3key[24];
     PRBool isFIPS;
     HASH_HashType hashType;
     PRBool extractValue = PR_TRUE;
 
     CHECK_FORK();
 
     if (!slot) {
         return CKR_SESSION_HANDLE_INVALID;
@@ -6921,16 +6963,174 @@ NSC_DeriveKey(CK_SESSION_HANDLE hSession
             }
             MD5_DestroyContext(md5, PR_TRUE);
             SHA1_DestroyContext(sha, PR_TRUE);
             sftk_FreeObject(key);
             key = NULL;
             break;
         }
 
+        case CKM_DES_ECB_ENCRYPT_DATA:
+            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
+            cipherInfo =  DES_CreateContext((unsigned char*) att->attrib.pValue,
+                                            NULL, NSS_DES, PR_TRUE);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 8,
+                                     stringPtr->pData, stringPtr->ulLen, (SFTKCipher) DES_Encrypt);
+            DES_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+        case CKM_DES_CBC_ENCRYPT_DATA:
+            desEncryptPtr = (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
+            pMechanism->pParameter;
+            cipherInfo =  DES_CreateContext((unsigned char*)att->attrib.pValue,
+                                            desEncryptPtr->iv, NSS_DES_CBC, PR_TRUE);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 8,
+                                     desEncryptPtr->pData, desEncryptPtr->length,
+                                     (SFTKCipher) DES_Encrypt);
+            DES_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+        case CKM_DES3_ECB_ENCRYPT_DATA:
+            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
+            if (att->attrib.ulValueLen == 16) {
+                PORT_Memcpy(des3key, att->attrib.pValue, 16);
+                PORT_Memcpy(des3key + 16, des3key, 8);
+            } else if (att->attrib.ulValueLen == 24) {
+                PORT_Memcpy(des3key, att->attrib.pValue, 24);
+            } else {
+               crv = CKR_KEY_SIZE_RANGE;
+               break;
+            }
+            cipherInfo =  DES_CreateContext(des3key, NULL, NSS_DES_EDE3, PR_TRUE);
+            PORT_Memset(des3key, 0, 24);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 8,
+                                     stringPtr->pData, stringPtr->ulLen, (SFTKCipher) DES_Encrypt);
+            DES_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+        case CKM_DES3_CBC_ENCRYPT_DATA:
+            desEncryptPtr = (CK_DES_CBC_ENCRYPT_DATA_PARAMS *)
+                        pMechanism->pParameter;
+            if (att->attrib.ulValueLen == 16) {
+                PORT_Memcpy(des3key, att->attrib.pValue, 16);
+                PORT_Memcpy(des3key + 16, des3key, 8);
+            } else if (att->attrib.ulValueLen == 24) {
+                PORT_Memcpy(des3key, att->attrib.pValue, 24);
+            } else {
+               crv = CKR_KEY_SIZE_RANGE; break;
+            }
+            cipherInfo =  DES_CreateContext(des3key, desEncryptPtr->iv,
+                                            NSS_DES_EDE3_CBC, PR_TRUE);
+            PORT_Memset(des3key, 0, 24);
+            if (cipherInfo == NULL) { crv = CKR_HOST_MEMORY; break; }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 8,
+                                     desEncryptPtr->pData, desEncryptPtr->length,
+                                     (SFTKCipher) DES_Encrypt);
+            DES_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+        case CKM_AES_ECB_ENCRYPT_DATA:
+            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
+            cipherInfo = AES_CreateContext((unsigned char*)att->attrib.pValue,
+                                           NULL, NSS_AES, PR_TRUE, att->attrib.ulValueLen, 16);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16,
+            stringPtr->pData, stringPtr->ulLen, (SFTKCipher) AES_Encrypt);
+            AES_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+        case CKM_AES_CBC_ENCRYPT_DATA:
+            aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
+                        pMechanism->pParameter;
+            cipherInfo = AES_CreateContext((unsigned char*)att->attrib.pValue,
+                                           aesEncryptPtr->iv, NSS_AES_CBC,
+                                           PR_TRUE, att->attrib.ulValueLen, 16);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16,
+                                     aesEncryptPtr->pData, aesEncryptPtr->length,
+                                     (SFTKCipher) AES_Encrypt);
+            AES_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+    case CKM_CAMELLIA_ECB_ENCRYPT_DATA:
+            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
+            cipherInfo = Camellia_CreateContext((unsigned char*)att->attrib.pValue,
+                                                NULL, NSS_CAMELLIA, PR_TRUE,att->attrib.ulValueLen);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16,
+                                     stringPtr->pData, stringPtr->ulLen,
+                                    (SFTKCipher) Camellia_Encrypt);
+            Camellia_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+        case CKM_CAMELLIA_CBC_ENCRYPT_DATA:
+            aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
+                        pMechanism->pParameter;
+            cipherInfo = Camellia_CreateContext((unsigned char*)att->attrib.pValue,
+                                                aesEncryptPtr->iv,NSS_CAMELLIA_CBC,
+                                                PR_TRUE, att->attrib.ulValueLen);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16,
+                                     aesEncryptPtr->pData, aesEncryptPtr->length,
+                                     (SFTKCipher) Camellia_Encrypt);
+            Camellia_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+        case CKM_SEED_ECB_ENCRYPT_DATA:
+            stringPtr = (CK_KEY_DERIVATION_STRING_DATA *) pMechanism->pParameter;
+            cipherInfo = SEED_CreateContext((unsigned char*)att->attrib.pValue,
+                                            NULL, NSS_SEED, PR_TRUE);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16,
+                                     stringPtr->pData, stringPtr->ulLen, (SFTKCipher) SEED_Encrypt);
+            SEED_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
+        case CKM_SEED_CBC_ENCRYPT_DATA:
+            aesEncryptPtr = (CK_AES_CBC_ENCRYPT_DATA_PARAMS *)
+                        pMechanism->pParameter;
+            cipherInfo = SEED_CreateContext( (unsigned char*)att->attrib.pValue,
+            aesEncryptPtr->iv, NSS_SEED_CBC, PR_TRUE);
+            if (cipherInfo == NULL) {
+                crv = CKR_HOST_MEMORY;
+                break;
+            }
+            crv = sftk_DeriveEncrypt(key, keySize, cipherInfo, 16,
+                                     aesEncryptPtr->pData, aesEncryptPtr->length,
+                                     (SFTKCipher) SEED_Encrypt);
+            SEED_DestroyContext(cipherInfo, PR_TRUE);
+            break;
+
         case CKM_CONCATENATE_BASE_AND_KEY: {
             SFTKObject *newKey;
 
             crv = sftk_DeriveSensitiveCheck(sourceKey, key);
             if (crv != CKR_OK)
                 break;
 
             session = sftk_SessionFromHandle(hSession);