Hi,

I have added support for CKM_GENERIC_SECRET_KEY_GEN mechanism for
generating generic secret key for CCA token. This generated secret key
can be used in HMAC sign and verify operations. I plan to send patches
adding secret key generation support to other tokens.

From 12588199a47c0b69b42f60ec195012b47de51619 Mon Sep 17 00:00:00 2001
From: Vineetha Pai <[email protected]>
Date: Fri, 21 Aug 2015 13:40:57 -0400
Subject: [PATCH] changes for generating generic secret key for cca for
use in HMAC ops

Signed-off-by: Vineetha Pai <[email protected]>
---
 testcases/crypto/digest_func.c             |  132 ++++++++++++++++
 usr/lib/pkcs11/cca_stdll/cca_specific.c    |  224
+++++++++++++++++++++++++++-
 usr/lib/pkcs11/cca_stdll/cca_stdll.h       |    1 +
 usr/lib/pkcs11/cca_stdll/csulincl.h        |   29 ++++
 usr/lib/pkcs11/cca_stdll/tok_struct.h      |    3 +-
 usr/lib/pkcs11/common/h_extern.h           |    3 +
 usr/lib/pkcs11/common/key_mgr.c            |   13 ++
 usr/lib/pkcs11/common/mech_sha.c           |   17 ++
 usr/lib/pkcs11/common/tok_spec_struct.h    |    2 +
 usr/lib/pkcs11/common/tok_specific.h       |    3 +
 usr/lib/pkcs11/ep11_stdll/tok_struct.h     |    1 +
 usr/lib/pkcs11/ica_s390_stdll/tok_struct.h |    3 +-
 usr/lib/pkcs11/icsf_stdll/tok_struct.h     |    1 +
 usr/lib/pkcs11/soft_stdll/tok_struct.h     |    3 +-
 usr/lib/pkcs11/tpm_stdll/tok_struct.h      |    3 +-
 15 files changed, 428 insertions(+), 10 deletions(-)

diff --git a/testcases/crypto/digest_func.c b/testcases/crypto/digest_func.c
index 93938c9..3c33431 100644
--- a/testcases/crypto/digest_func.c
+++ b/testcases/crypto/digest_func.c
@@ -601,6 +601,132 @@ testcase_cleanup:
     return rc;
 }
 
+
+/** This function tests a single sign and verify HMAC operation using
sha-1 with a generated secret key **/
+CK_RV do_HMAC_SignVerify_WithGenKey() {
+
+        CK_MECHANISM    secret_mech = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0};
+        CK_MECHANISM    hash_mech = {CKM_SHA_1_HMAC, 0, 0};
+        CK_BYTE         key[MAX_KEY_SIZE];
+        CK_ULONG        key_len = 20;
+        CK_BYTE         data[] = {"Hi There"};
+        CK_ULONG        data_len = 8;
+        CK_BYTE         actual[MAX_HASH_SIZE];
+        CK_ULONG        actual_len;
+        CK_ULONG        expected_len = 20; /** expected hash size is 20
for sha-1 **/
+        CK_SESSION_HANDLE       session;
+        CK_SLOT_ID              slot_id = SLOT_ID;
+        CK_ULONG                flags;
+        CK_RV                   rc;
+        CK_OBJECT_HANDLE        h_key;
+
+        CK_BYTE                 user_pin[PKCS11_MAX_PIN_LEN];
+        CK_ULONG                user_pin_len;
+
+        /** begin test **/
+        printf("\n\ntestcase do_HMAC_SignVerify_WithGenKey\n");
+        testcase_rw_session();
+        testcase_user_login();
+
+        rc = CKR_OK;    // set rc
+
+        /** skip test if mech is not supported with this slot, checking
for generic secret key mechanism
+         *             and also sha1-hmac mechanism **/
+        if (! mech_supported(SLOT_ID, secret_mech.mechanism)){
+                printf("mechanism %ld is not supported with slot %ld\n",
+                                secret_mech.mechanism, slot_id);
+                goto testcase_cleanup;
+        }
+        if (! mech_supported(SLOT_ID, hash_mech.mechanism)){
+                printf("mechanism %ld is not supported with slot %ld\n",
+                                hash_mech.mechanism, slot_id);
+                goto testcase_cleanup;
+        }
+
+        /** clear buffers **/
+        memset(key, 0, sizeof(key));
+        memset(actual, 0, sizeof(actual));
+
+        /** get test vector info **/
+        actual_len = sizeof(actual);
+
+        /** generate key object **/
+        rc = generate_SecretKey(session, key_len, &secret_mech, &h_key);
+        if(rc != CKR_OK){
+                testcase_error("generate_SecretKey rc=%s",
+                                p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** initialize signing **/
+        rc = funcs->C_SignInit(session, &hash_mech, h_key);
+        if (rc != CKR_OK) {
+                testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** do signing  **/
+        rc = funcs->C_Sign(session,
+                        data,
+                        data_len,
+                        actual,
+                        &actual_len);
+
+        if (rc != CKR_OK) {
+                testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** initilaize verification **/
+        rc = funcs->C_VerifyInit(session, &hash_mech, h_key);
+        if (rc != CKR_OK) {
+                testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** do verification **/
+        rc = funcs->C_Verify(session,
+                        data,
+                        data_len,
+                        actual,
+                        actual_len);
+
+        if (rc != CKR_OK) {
+                testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** compare sign/verify results with expected results **/
+        testcase_new_assertion();
+        if(actual_len != expected_len){
+                testcase_fail("hashed data length does not match test "
+                                "vector's hashed data length\nexpected
length="
+                                "%ld, found length=%ld",
+                                expected_len, actual_len);
+        }
+        else {
+                testcase_pass("%s Sign Verify with generated secret key "
+                                "passed.", "SHA1_HMAC");
+        }
+
+error:
+        /** clean up **/
+        rc = funcs->C_DestroyObject(session, h_key);
+        if (rc != CKR_OK) {
+                testcase_error("C_DestroyObject rc=%s.",
+                                p11_get_ckr(rc));
+                goto testcase_cleanup;
+        }
+
+testcase_cleanup:
+        testcase_user_logout();
+        rc = funcs->C_CloseAllSessions(slot_id);
+        if (rc != CKR_OK) {
+                testcase_error("C_CloseAllSessions rc=%s",
p11_get_ckr(rc));
+        }
+        return rc;
+}
+
 CK_RV digest_funcs() {
     CK_RV rc;
     int i;
@@ -641,6 +767,12 @@ CK_RV digest_funcs() {
         }
     }
 
+    /* HMAC test with a generated secret key, currently cca supports
generating secret key */
+    rc = do_HMAC_SignVerify_WithGenKey();
+    if (rc && !no_stop) {
+        return rc;
+    }
+
     return rc;
 }
 
diff --git a/usr/lib/pkcs11/cca_stdll/cca_specific.c
b/usr/lib/pkcs11/cca_stdll/cca_specific.c
index 08e61c7..1dcb210 100644
--- a/usr/lib/pkcs11/cca_stdll/cca_specific.c
+++ b/usr/lib/pkcs11/cca_stdll/cca_specific.c
@@ -84,7 +84,8 @@ MECH_LIST_ELEMENT mech_list[] = {
     {CKM_ECDSA, {160, 521, CKF_HW|CKF_SIGN|CKF_VERIFY|CKF_EC_NAMEDCURVE|
                   CKF_EC_F_P}},
     {CKM_ECDSA_SHA1, {160, 521, CKF_HW|CKF_SIGN|CKF_VERIFY|
-                   CKF_EC_NAMEDCURVE|CKF_EC_F_P}}
+                   CKF_EC_NAMEDCURVE|CKF_EC_F_P}},
+        {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW|CKF_GENERATE}}
 };
 
 CK_ULONG mech_list_len = (sizeof(mech_list) / sizeof(MECH_LIST_ELEMENT));
@@ -2381,7 +2382,7 @@ static CK_RV import_generic_secret_key(OBJECT *object)
 {
     CK_RV rc;
     long return_code, reason_code, rule_array_count;
-    unsigned char key_token[CCA_KEY_TOKEN_SIZE] = { 0 };
+    unsigned char key_token[CCA_MAX_HMAC_KEY_TOKEN_SIZE] = { 0 };
     unsigned char rule_array[5 * CCA_KEYWORD_SIZE] = { 0 };
     long key_name_len = 0, clr_key_len = 0;
     long user_data_len = 0, key_part_len = 0;
@@ -2396,11 +2397,14 @@ static CK_RV import_generic_secret_key(OBJECT
*object)
         TRACE_ERROR("Incomplete Generic Secret (HMAC) key template\n");
         return CKR_TEMPLATE_INCOMPLETE;
 }
-    keylen = attr->ulValueLen;
+    keylen = attr->ulValueLen; //key length in bytes
+
+        keylen = keylen * 8; //convert keylen to bits
+
     /* key len needs to be 80-2048 bits */
-    if (8*keylen < 80 || 8*keylen > 2048) {
+    if ((keylen < 80) || (keylen > 2048)) {
         TRACE_ERROR("HMAC key size of %lu bits not within"
-                " CCA required range of 80-2048 bits\n", 8*keylen);
+                " CCA required range of 80-2048 bits\n", keylen);
         return CKR_KEY_SIZE_RANGE;
     }
 
@@ -2421,7 +2425,7 @@ static CK_RV import_generic_secret_key(OBJECT *object)
 
     memcpy(rule_array, "HMAC    FIRST   MIN1PART", 3 * CCA_KEYWORD_SIZE);
     rule_array_count = 3;
-    key_part_len = keylen * 8;
+    key_part_len = keylen;
     key_token_len = sizeof(key_token);
 
     CSNBKPI2(&return_code, &reason_code, NULL, NULL, &rule_array_count,
@@ -2549,3 +2553,211 @@ CK_RV token_specific_object_add(OBJECT *object)
 
     return CKR_OK;
 }
+
+CK_RV set_attributes_key_gen(TEMPLATE *tmpl, CK_BYTE *data, long data_len);
+
+CK_RV token_specific_generic_secret_key_gen (TEMPLATE *template)
+{
+        CK_RV rc;
+        long return_code = -1, reason_code = -1, rule_array_count = 0;
+        long zero_length = 0;
+        long key_name_length = 0, clear_key_length = 0,
user_data_length = 0;
+        CK_ATTRIBUTE *attr = NULL;
+        CK_ULONG keylength = 0;
+        unsigned char key_type1[8] = {0};
+        unsigned char key_type2[8] = {0};
+        unsigned char key_token[CCA_MAX_HMAC_KEY_TOKEN_SIZE] = { 0 };
+        long key_token_length = sizeof(key_token);
+        unsigned char rule_array[4 * CCA_KEYWORD_SIZE] = { 0 };
+
+        rc = template_attribute_find(template, CKA_VALUE_LEN, &attr);
+        if (rc == FALSE) {
+                TRACE_ERROR("Incomplete Generic Secret (HMAC) key
template\n");
+                return CKR_TEMPLATE_INCOMPLETE;
+        }
+
+        keylength = *(CK_ULONG *)attr->pValue; //app specified
keylength in bytes
+
+        keylength = keylength * 8; //convert keylength to bits
+
+        /* HMAC key length needs to be 80-2048 bits */
+        if ((keylength < 80) || (keylength > 2048)) {
+                TRACE_ERROR("HMAC key size of %lu bits not within"
+                            " CCA required range of 80-2048 bits\n",
keylength);
+                return CKR_KEY_SIZE_RANGE;
+        }
+
+        rule_array_count = 4;
+        memcpy(rule_array, "INTERNALHMAC    MAC     GENERATE",
rule_array_count * CCA_KEYWORD_SIZE);
+
+        CSNBKTB2(&return_code,
+                 &reason_code,
+                 NULL,
+                 NULL,
+                 &rule_array_count,
+                 rule_array,
+                 &clear_key_length, /* 0 here */
+                 NULL,
+                 &key_name_length, /* no key name, 0 here */
+                 NULL,
+                 &user_data_length, /* no user data, 0 here */
+                 NULL,
+                 &zero_length, /* reserved parameter and length must be
0 */
+                 NULL,
+                 &zero_length, /* reserved parameter and length must be 0 *
+                 NULL,
+                 &key_token_length, /* hmac token length */
+                 key_token); /* hmac generate token */
+        if (return_code != CCA_SUCCESS) {
+                TRACE_ERROR("CSNBKTB2 (HMAC KEY TOKEN BUILD) failed."
+                            " return:%ld, reason:%ld\n",
+                            return_code, reason_code);
+                return CKR_FUNCTION_FAILED;
+        }
+
+        /*** generate the hmac key here **/
+        return_code = -1;
+        reason_code = -1;
+
+        rule_array_count = 2;
+        memset(rule_array, 0, sizeof(rule_array));
+        /* create rule_array with 2 keywords */
+         memcpy(rule_array, "HMAC    OP      ", rule_array_count *
CCA_KEYWORD_SIZE);
+
+        /*ask to create the hmac key with application specified key
length in bits */
+        clear_key_length = keylength;
+
+        memcpy(key_type1, "TOKEN   ", CCA_KEYWORD_SIZE);
+        /*for only one copy of key generated, specify 8 spaces in
key_type2 per CCA basic services guide*/
+        memcpy(key_type2, "        ", CCA_KEYWORD_SIZE);
+
+        /*token lengths are set to size of buffer */
+        key_token_length = sizeof(key_token);
+
+        CSNBKGN2( &return_code,
+            &reason_code,
+            &zero_length,
+            NULL,
+            &rule_array_count,
+            rule_array,
+            &clear_key_length,
+            key_type1,
+            key_type2,
+            &key_name_length,     /* 0 here */
+            NULL,
+            &key_name_length,     /* 0 here */
+            NULL,
+            &user_data_length,    /* 0 here */
+            NULL,
+            &user_data_length,    /* 0 here */
+            NULL,
+            &zero_length,
+            NULL,
+            &zero_length,
+            NULL,
+            &key_token_length,    /* hmac key token length */
+            key_token,            /* generated key */
+            &zero_length,         /* 0 here for second key, only one
key generated */
+            NULL );
+
+        if (return_code != CCA_SUCCESS) {
+                TRACE_ERROR("CSNBKGN2 (HMAC KEY GENERATE) failed."
+                            " return:%ld, reason:%ld\n",
+                            return_code, reason_code);
+                return CKR_FUNCTION_FAILED;
+        }
+
+        //set the attributes in template after key generation
+        rc = set_attributes_key_gen(template, key_token, key_token_length);
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("set_attributed_key_gen for secret key
generation failed\n");
+                return rc;
+        }
+
+        return CKR_OK;
+}
+
+/** This function sets all the attributes to template after a
successful secret key generation */
+CK_RV set_attributes_key_gen(TEMPLATE *tmpl, CK_BYTE *data, long data_len)
+{
+        CK_ATTRIBUTE     *opaque_attr = NULL;
+        CK_ATTRIBUTE     *value_attr    = NULL;
+        CK_ATTRIBUTE     *key_type_attr = NULL;
+        CK_ATTRIBUTE     *class_attr    = NULL;
+        CK_ATTRIBUTE     *local_attr    = NULL;
+        CK_BYTE           dummy_key[CCA_MAX_HMAC_KEY_TOKEN_SIZE] = {0};
+        CK_RV             rc = 0;
+
+        opaque_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) +
data_len);
+        value_attr    = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) +
data_len );
+        key_type_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) +
sizeof(CK_KEY_TYPE) );
+        class_attr    = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) +
sizeof(CK_OBJECT_CLASS) );
+        local_attr    = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) +
sizeof(CK_BBOOL) );
+
+        if (!opaque_attr || !value_attr || !key_type_attr ||
!class_attr || !local_attr) {
+                if (opaque_attr)   free(opaque_attr);
+                if (value_attr)    free( value_attr );
+                if (key_type_attr) free( key_type_attr );
+                if (class_attr)    free( class_attr );
+                if (local_attr)    free( local_attr );
+
+                TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
+                rc = CKR_HOST_MEMORY;
+                return rc;
+        }
+
+        opaque_attr->type = CKA_IBM_OPAQUE;
+        opaque_attr->ulValueLen = data_len;
+        opaque_attr->pValue = (CK_BYTE *)opaque_attr +
sizeof(CK_ATTRIBUTE);
+        memcpy(opaque_attr->pValue, data, data_len);
+
+        //for secure key, set dummy value in CKA_VALUE
+        value_attr->type         = CKA_VALUE;
+        value_attr->ulValueLen   = data_len;
+        value_attr->pValue       = (CK_BYTE *)value_attr +
sizeof(CK_ATTRIBUTE);
+        memcpy( value_attr->pValue, dummy_key, data_len );
+
+        key_type_attr->type         = CKA_KEY_TYPE;
+        key_type_attr->ulValueLen   = sizeof(CK_KEY_TYPE);
+        key_type_attr->pValue       = (CK_BYTE *)key_type_attr +
sizeof(CK_ATTRIBUTE);
+        *(CK_KEY_TYPE *)key_type_attr->pValue = CKK_GENERIC_SECRET;
+
+        class_attr->type         = CKA_CLASS;
+        class_attr->ulValueLen   = sizeof(CK_OBJECT_CLASS);
+        class_attr->pValue       = (CK_BYTE *)class_attr +
sizeof(CK_ATTRIBUTE);
+        *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY;
+
+        local_attr->type         = CKA_LOCAL;
+        local_attr->ulValueLen   = sizeof(CK_BBOOL);
+        local_attr->pValue       = (CK_BYTE *)local_attr +
sizeof(CK_ATTRIBUTE);
+        *(CK_BBOOL *)local_attr->pValue = TRUE;
+
+        //update all the attributes in the template
+        rc = template_update_attribute(tmpl, opaque_attr);
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_IBM_OPAQUE)
failed\n");
+                return rc;
+        }
+        rc = template_update_attribute( tmpl, value_attr );
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_VALUE)
failed\n");
+                return rc;
+        }
+        rc = template_update_attribute( tmpl, key_type_attr );
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_KEY_TYPE)
failed\n");
+                return rc;
+        }
+        rc = template_update_attribute( tmpl, class_attr );
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_CLASS)
failed\n");
+                return rc;
+        }
+        rc = template_update_attribute( tmpl, local_attr );
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_LOCAL)
failed\n");
+                return rc;
+        }
+
+        return CKR_OK;
+}
diff --git a/usr/lib/pkcs11/cca_stdll/cca_stdll.h
b/usr/lib/pkcs11/cca_stdll/cca_stdll.h
index 4f33d80..4dcf32f 100644
--- a/usr/lib/pkcs11/cca_stdll/cca_stdll.h
+++ b/usr/lib/pkcs11/cca_stdll/cca_stdll.h
@@ -28,6 +28,7 @@
 #define CCA_PKB_E_OFFSET                18
 #define CCA_PKB_E_SIZE                  2
 #define CCA_PKB_E_SIZE_OFFSET           4
+#define CCA_MAX_HMAC_KEY_TOKEN_SIZE     800
 
 /* Elliptic Curve constants */
 /* CCA spec: page 94 */
diff --git a/usr/lib/pkcs11/cca_stdll/csulincl.h
b/usr/lib/pkcs11/cca_stdll/csulincl.h
index 74e7cd2..ce93826 100644
--- a/usr/lib/pkcs11/cca_stdll/csulincl.h
+++ b/usr/lib/pkcs11/cca_stdll/csulincl.h
@@ -32,6 +32,7 @@
   #define CSNBMKP   CSNBMKP_32
   #define CSNBKEX   CSNBKEX_32
   #define CSNBKGN   CSNBKGN_32
+  #define CSNBKGN2   CSNBKGN2_32
   #define CSNBKIM   CSNBKIM_32
   #define CSNBKPI   CSNBKPI_32
   #define CSNBKPI2  CSNBKPI2_32
@@ -198,6 +199,34 @@ extern void SECURITYAPI
               unsigned char * generated_key_identifier_1,
               unsigned char * generated_key_identifier_2);
 
+/* Key Generate2 */
+extern void SECURITYAPI
+    CSNBKGN2_32(long             * return_code,
+                long             * reason_code,
+                long             * exit_data_length,
+                unsigned char    * exit_data,
+                long             * rule_array_count,
+                unsigned char    * rule_array,
+                long             * clear_key_bit_length,
+                unsigned char    * key_type_1,
+                unsigned char    * key_type_2,
+                long             * key_name_1_length,
+                unsigned char    * key_name_1,
+                long             * key_name_2_length,
+                unsigned char    * key_name_2,
+                long             * user_associated_data_1_length,
+                unsigned char    * user_associated_data_1,
+                long             * user_associated_data_2_length,
+                unsigned char    * user_associated_data_2,
+                long             * key_encrypting_key_identifier_1_length,
+                unsigned char    * key_encrypting_key_identifier_1,
+                long             * key_encrypting_key_identifier_2_length,
+                unsigned char    * key_encrypting_key_identifier_2,
+                long             * generated_key_identifier_1_length,
+                unsigned char    * generated_key_identifier_1,
+                long             * generated_key_identifier_2_length,
+                unsigned char    * generated_key_identifier_2);
+
 /* Key Import */
 extern void SECURITYAPI
    CSNBKIM_32(long          * return_code,
diff --git a/usr/lib/pkcs11/cca_stdll/tok_struct.h
b/usr/lib/pkcs11/cca_stdll/tok_struct.h
index 8e84885..5b1207e 100644
--- a/usr/lib/pkcs11/cca_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/cca_stdll/tok_struct.h
@@ -129,7 +129,8 @@ token_spec_t token_specific = {
     NULL,            // dsa_verify
     &token_specific_get_mechanism_list,
     &token_specific_get_mechanism_info,
-    &token_specific_object_add
+    &token_specific_object_add,
+        &token_specific_generic_secret_key_gen,
 };
 
 #endif
diff --git a/usr/lib/pkcs11/common/h_extern.h
b/usr/lib/pkcs11/common/h_extern.h
index b9bdecb..d9dc432 100755
--- a/usr/lib/pkcs11/common/h_extern.h
+++ b/usr/lib/pkcs11/common/h_extern.h
@@ -1798,6 +1798,9 @@ CK_RV sha5_hmac_verify(SESSION *sess,
SIGN_VERIFY_CONTEXT *ctx,
                        CK_BYTE *in_data, CK_ULONG in_data_len,
                        CK_BYTE *signature, CK_ULONG sig_len);
 
+//adding the hmac secret key generation here
+CK_RV ckm_generic_secret_key_gen(TEMPLATE *tmpl);
+
 // MD2 mechanisms
 //
 CK_RV  md2_hash( SESSION  *sess,     CK_BBOOL  length_only,
diff --git a/usr/lib/pkcs11/common/key_mgr.c
b/usr/lib/pkcs11/common/key_mgr.c
index 795c8e7..fd90e68 100755
--- a/usr/lib/pkcs11/common/key_mgr.c
+++ b/usr/lib/pkcs11/common/key_mgr.c
@@ -415,6 +415,15 @@ key_mgr_generate_key( SESSION           * sess,
      subclass = CKK_AES;
      break;
 
+      case CKM_GENERIC_SECRET_KEY_GEN:
+         if (subclass != 0 && subclass != CKK_GENERIC_SECRET){
+           TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT));
+           return CKR_TEMPLATE_INCONSISTENT;
+         }
+
+         subclass = CKK_GENERIC_SECRET;
+         break;
+
       default:
          TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
          return CKR_MECHANISM_INVALID;
@@ -459,6 +468,10 @@ key_mgr_generate_key( SESSION           * sess,
         rc = ckm_aes_key_gen( key_obj->template );
         break;
 #endif
+         case CKM_GENERIC_SECRET_KEY_GEN:
+            rc = ckm_generic_secret_key_gen( key_obj->template );
+            break;
+
       default:
          TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
          rc = CKR_MECHANISM_INVALID;
diff --git a/usr/lib/pkcs11/common/mech_sha.c
b/usr/lib/pkcs11/common/mech_sha.c
index 87067cc..e05c7a3 100755
--- a/usr/lib/pkcs11/common/mech_sha.c
+++ b/usr/lib/pkcs11/common/mech_sha.c
@@ -1847,3 +1847,20 @@ void sha5_init(DIGEST_CONTEXT * ctx)
         token_specific.t_sha5_init(ctx);
     }
 }
+
+//Adding the hmac secret key gen here for lack of a better place to put
this
+CK_RV
+ckm_generic_secret_key_gen( TEMPLATE *tmpl )
+{
+        CK_ULONG           rc;
+
+        if (token_specific.t_generic_secret_key_gen == NULL) {
+                TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
+                return CKR_MECHANISM_INVALID;
+        }
+
+        rc = token_specific.t_generic_secret_key_gen(tmpl);
+
+        return rc;
+}
+
diff --git a/usr/lib/pkcs11/common/tok_spec_struct.h
b/usr/lib/pkcs11/common/tok_spec_struct.h
index a5ce813..f72ebff 100755
--- a/usr/lib/pkcs11/common/tok_spec_struct.h
+++ b/usr/lib/pkcs11/common/tok_spec_struct.h
@@ -511,6 +511,8 @@ struct token_specific_struct {
 
     CK_RV (*t_object_add)(OBJECT *);
 
+    CK_RV (*t_generic_secret_key_gen) (TEMPLATE *);
+
 };
 
 typedef struct token_specific_struct token_spec_t;
diff --git a/usr/lib/pkcs11/common/tok_specific.h
b/usr/lib/pkcs11/common/tok_specific.h
index cb72adb..348209b 100755
--- a/usr/lib/pkcs11/common/tok_specific.h
+++ b/usr/lib/pkcs11/common/tok_specific.h
@@ -627,4 +627,7 @@ token_specific_get_mechanism_info(CK_MECHANISM_TYPE
type,
 CK_RV
 token_specific_object_add(OBJECT *);
 
+CK_RV
+token_specific_generic_secret_key_gen (TEMPLATE *template);
+
 #endif
diff --git a/usr/lib/pkcs11/ep11_stdll/tok_struct.h
b/usr/lib/pkcs11/ep11_stdll/tok_struct.h
index 0b61134..f0fb668 100644
--- a/usr/lib/pkcs11/ep11_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/ep11_stdll/tok_struct.h
@@ -403,6 +403,7 @@ token_spec_t token_specific = {
     NULL,            // get_mechanism_list
     NULL,            // get mechanism_info
         &token_specific_object_add,
+        NULL    // generic_secret_key_gen
 };
 
 #endif
diff --git a/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
b/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
index 672894f..7c5720f 100644
--- a/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
@@ -396,7 +396,8 @@ token_spec_t token_specific = {
     NULL,        // dsa_verify
     &token_specific_get_mechanism_list,
     &token_specific_get_mechanism_info,
-    NULL            // object_add
+    NULL,            // object_add
+        NULL   // generic_secret_key_gen
 };
 
 #endif
diff --git a/usr/lib/pkcs11/icsf_stdll/tok_struct.h
b/usr/lib/pkcs11/icsf_stdll/tok_struct.h
index 980409f..9688ded 100644
--- a/usr/lib/pkcs11/icsf_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/icsf_stdll/tok_struct.h
@@ -122,6 +122,7 @@ token_spec_t token_specific = {
     NULL,            // get_mechanism_list
     NULL,            // get_mechanism_info
     NULL,            // object_add
+        NULL        // generic_secret_key_gen
 };
 
 #endif
diff --git a/usr/lib/pkcs11/soft_stdll/tok_struct.h
b/usr/lib/pkcs11/soft_stdll/tok_struct.h
index ebeefab..645db27 100644
--- a/usr/lib/pkcs11/soft_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/soft_stdll/tok_struct.h
@@ -411,7 +411,8 @@ token_spec_t token_specific = {
     NULL,            // dsa_verify
     &token_specific_get_mechanism_list,
     &token_specific_get_mechanism_info,
-    NULL            // object_add
+    NULL,            // object_add
+        NULL   // generic_secret_key_gen
 };
 
 #endif
diff --git a/usr/lib/pkcs11/tpm_stdll/tok_struct.h
b/usr/lib/pkcs11/tpm_stdll/tok_struct.h
index 1ff1ff0..c9500c7 100644
--- a/usr/lib/pkcs11/tpm_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/tpm_stdll/tok_struct.h
@@ -127,5 +127,6 @@ struct token_specific_struct token_specific = {
     NULL,            // dsa_verify
     &token_specific_get_mechanism_list,
     &token_specific_get_mechanism_info,
-    NULL            // object_add
+    NULL,            // object_add
+        NULL    // generic_secret_key_gen
 };
-- 
1.7.1


Thanks,

-- 
Vineetha Pai
Linux Security Development, LTC
notes - [email protected]
Phone - 203 401 8099

From 12588199a47c0b69b42f60ec195012b47de51619 Mon Sep 17 00:00:00 2001
From: Vineetha Pai <[email protected]>
Date: Fri, 21 Aug 2015 13:40:57 -0400
Subject: [PATCH] changes for generating generic secret key for cca for use in HMAC ops

Signed-off-by: Vineetha Pai <[email protected]>
---
 testcases/crypto/digest_func.c             |  132 ++++++++++++++++
 usr/lib/pkcs11/cca_stdll/cca_specific.c    |  224 +++++++++++++++++++++++++++-
 usr/lib/pkcs11/cca_stdll/cca_stdll.h       |    1 +
 usr/lib/pkcs11/cca_stdll/csulincl.h        |   29 ++++
 usr/lib/pkcs11/cca_stdll/tok_struct.h      |    3 +-
 usr/lib/pkcs11/common/h_extern.h           |    3 +
 usr/lib/pkcs11/common/key_mgr.c            |   13 ++
 usr/lib/pkcs11/common/mech_sha.c           |   17 ++
 usr/lib/pkcs11/common/tok_spec_struct.h    |    2 +
 usr/lib/pkcs11/common/tok_specific.h       |    3 +
 usr/lib/pkcs11/ep11_stdll/tok_struct.h     |    1 +
 usr/lib/pkcs11/ica_s390_stdll/tok_struct.h |    3 +-
 usr/lib/pkcs11/icsf_stdll/tok_struct.h     |    1 +
 usr/lib/pkcs11/soft_stdll/tok_struct.h     |    3 +-
 usr/lib/pkcs11/tpm_stdll/tok_struct.h      |    3 +-
 15 files changed, 428 insertions(+), 10 deletions(-)

diff --git a/testcases/crypto/digest_func.c b/testcases/crypto/digest_func.c
index 93938c9..3c33431 100644
--- a/testcases/crypto/digest_func.c
+++ b/testcases/crypto/digest_func.c
@@ -601,6 +601,132 @@ testcase_cleanup:
 	return rc;
 }
 
+
+/** This function tests a single sign and verify HMAC operation using sha-1 with a generated secret key **/
+CK_RV do_HMAC_SignVerify_WithGenKey() {
+
+        CK_MECHANISM    secret_mech = {CKM_GENERIC_SECRET_KEY_GEN, 0, 0};
+        CK_MECHANISM    hash_mech = {CKM_SHA_1_HMAC, 0, 0};
+        CK_BYTE         key[MAX_KEY_SIZE];
+        CK_ULONG        key_len = 20;
+        CK_BYTE         data[] = {"Hi There"};
+        CK_ULONG        data_len = 8;
+        CK_BYTE         actual[MAX_HASH_SIZE];
+        CK_ULONG        actual_len;
+        CK_ULONG        expected_len = 20; /** expected hash size is 20 for sha-1 **/
+        CK_SESSION_HANDLE       session;
+        CK_SLOT_ID              slot_id = SLOT_ID;
+        CK_ULONG                flags;
+        CK_RV                   rc;
+        CK_OBJECT_HANDLE        h_key;
+
+        CK_BYTE                 user_pin[PKCS11_MAX_PIN_LEN];
+        CK_ULONG                user_pin_len;
+
+        /** begin test **/
+        printf("\n\ntestcase do_HMAC_SignVerify_WithGenKey\n");
+        testcase_rw_session();
+        testcase_user_login();
+
+        rc = CKR_OK;    // set rc
+
+        /** skip test if mech is not supported with this slot, checking for generic secret key mechanism
+         *             and also sha1-hmac mechanism **/
+        if (! mech_supported(SLOT_ID, secret_mech.mechanism)){
+                printf("mechanism %ld is not supported with slot %ld\n",
+                                secret_mech.mechanism, slot_id);
+                goto testcase_cleanup;
+        }
+        if (! mech_supported(SLOT_ID, hash_mech.mechanism)){
+                printf("mechanism %ld is not supported with slot %ld\n",
+                                hash_mech.mechanism, slot_id);
+                goto testcase_cleanup;
+        }
+
+        /** clear buffers **/
+        memset(key, 0, sizeof(key));
+        memset(actual, 0, sizeof(actual));
+
+        /** get test vector info **/
+        actual_len = sizeof(actual);
+
+        /** generate key object **/
+        rc = generate_SecretKey(session, key_len, &secret_mech, &h_key);
+        if(rc != CKR_OK){
+                testcase_error("generate_SecretKey rc=%s",
+                                p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** initialize signing **/
+        rc = funcs->C_SignInit(session, &hash_mech, h_key);
+        if (rc != CKR_OK) {
+                testcase_error("C_SignInit rc=%s", p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** do signing  **/
+        rc = funcs->C_Sign(session,
+                        data,
+                        data_len,
+                        actual,
+                        &actual_len);
+
+        if (rc != CKR_OK) {
+                testcase_error("C_Sign rc=%s", p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** initilaize verification **/
+        rc = funcs->C_VerifyInit(session, &hash_mech, h_key);
+        if (rc != CKR_OK) {
+                testcase_error("C_VerifyInit rc=%s", p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** do verification **/
+        rc = funcs->C_Verify(session,
+                        data,
+                        data_len,
+                        actual,
+                        actual_len);
+
+        if (rc != CKR_OK) {
+                testcase_error("C_Verify rc=%s", p11_get_ckr(rc));
+                goto error;
+        }
+
+        /** compare sign/verify results with expected results **/
+        testcase_new_assertion();
+        if(actual_len != expected_len){
+                testcase_fail("hashed data length does not match test "
+                                "vector's hashed data length\nexpected length="
+                                "%ld, found length=%ld",
+                                expected_len, actual_len);
+        }
+        else {
+                testcase_pass("%s Sign Verify with generated secret key "
+                                "passed.", "SHA1_HMAC");
+        }
+
+error:
+        /** clean up **/
+        rc = funcs->C_DestroyObject(session, h_key);
+        if (rc != CKR_OK) {
+                testcase_error("C_DestroyObject rc=%s.",
+                                p11_get_ckr(rc));
+                goto testcase_cleanup;
+        }
+
+testcase_cleanup:
+        testcase_user_logout();
+        rc = funcs->C_CloseAllSessions(slot_id);
+        if (rc != CKR_OK) {
+                testcase_error("C_CloseAllSessions rc=%s", p11_get_ckr(rc));
+        }
+        return rc;
+}
+
 CK_RV digest_funcs() {
 	CK_RV rc;
 	int i;
@@ -641,6 +767,12 @@ CK_RV digest_funcs() {
 		}
 	}
 
+	/* HMAC test with a generated secret key, currently cca supports generating secret key */
+	rc = do_HMAC_SignVerify_WithGenKey();
+	if (rc && !no_stop) {
+		return rc;
+	}
+
 	return rc;
 }
 
diff --git a/usr/lib/pkcs11/cca_stdll/cca_specific.c b/usr/lib/pkcs11/cca_stdll/cca_specific.c
index 08e61c7..1dcb210 100644
--- a/usr/lib/pkcs11/cca_stdll/cca_specific.c
+++ b/usr/lib/pkcs11/cca_stdll/cca_specific.c
@@ -84,7 +84,8 @@ MECH_LIST_ELEMENT mech_list[] = {
 	{CKM_ECDSA, {160, 521, CKF_HW|CKF_SIGN|CKF_VERIFY|CKF_EC_NAMEDCURVE|
 			      CKF_EC_F_P}},
 	{CKM_ECDSA_SHA1, {160, 521, CKF_HW|CKF_SIGN|CKF_VERIFY|
-				   CKF_EC_NAMEDCURVE|CKF_EC_F_P}}
+				   CKF_EC_NAMEDCURVE|CKF_EC_F_P}},
+        {CKM_GENERIC_SECRET_KEY_GEN, {80, 2048, CKF_HW|CKF_GENERATE}}
 };
 
 CK_ULONG mech_list_len = (sizeof(mech_list) / sizeof(MECH_LIST_ELEMENT));
@@ -2381,7 +2382,7 @@ static CK_RV import_generic_secret_key(OBJECT *object)
 {
 	CK_RV rc;
 	long return_code, reason_code, rule_array_count;
-	unsigned char key_token[CCA_KEY_TOKEN_SIZE] = { 0 };
+	unsigned char key_token[CCA_MAX_HMAC_KEY_TOKEN_SIZE] = { 0 };
 	unsigned char rule_array[5 * CCA_KEYWORD_SIZE] = { 0 };
 	long key_name_len = 0, clr_key_len = 0;
 	long user_data_len = 0, key_part_len = 0;
@@ -2396,11 +2397,14 @@ static CK_RV import_generic_secret_key(OBJECT *object)
 		TRACE_ERROR("Incomplete Generic Secret (HMAC) key template\n");
 		return CKR_TEMPLATE_INCOMPLETE;
 }
-	keylen = attr->ulValueLen;
+	keylen = attr->ulValueLen; //key length in bytes
+
+        keylen = keylen * 8; //convert keylen to bits
+
 	/* key len needs to be 80-2048 bits */
-	if (8*keylen < 80 || 8*keylen > 2048) {
+	if ((keylen < 80) || (keylen > 2048)) {
 		TRACE_ERROR("HMAC key size of %lu bits not within"
-			    " CCA required range of 80-2048 bits\n", 8*keylen);
+			    " CCA required range of 80-2048 bits\n", keylen);
 		return CKR_KEY_SIZE_RANGE;
 	}
 
@@ -2421,7 +2425,7 @@ static CK_RV import_generic_secret_key(OBJECT *object)
 
 	memcpy(rule_array, "HMAC    FIRST   MIN1PART", 3 * CCA_KEYWORD_SIZE);
 	rule_array_count = 3;
-	key_part_len = keylen * 8;
+	key_part_len = keylen;
 	key_token_len = sizeof(key_token);
 
 	CSNBKPI2(&return_code, &reason_code, NULL, NULL, &rule_array_count,
@@ -2549,3 +2553,211 @@ CK_RV token_specific_object_add(OBJECT *object)
 
 	return CKR_OK;
 }
+
+CK_RV set_attributes_key_gen(TEMPLATE *tmpl, CK_BYTE *data, long data_len);
+
+CK_RV token_specific_generic_secret_key_gen (TEMPLATE *template)
+{
+        CK_RV rc;
+        long return_code = -1, reason_code = -1, rule_array_count = 0;
+        long zero_length = 0;
+        long key_name_length = 0, clear_key_length = 0, user_data_length = 0;
+        CK_ATTRIBUTE *attr = NULL;
+        CK_ULONG keylength = 0;
+        unsigned char key_type1[8] = {0};
+        unsigned char key_type2[8] = {0};
+        unsigned char key_token[CCA_MAX_HMAC_KEY_TOKEN_SIZE] = { 0 };
+        long key_token_length = sizeof(key_token);
+        unsigned char rule_array[4 * CCA_KEYWORD_SIZE] = { 0 };
+
+        rc = template_attribute_find(template, CKA_VALUE_LEN, &attr);
+        if (rc == FALSE) {
+                TRACE_ERROR("Incomplete Generic Secret (HMAC) key template\n");
+                return CKR_TEMPLATE_INCOMPLETE;
+        }
+
+        keylength = *(CK_ULONG *)attr->pValue; //app specified keylength in bytes
+
+        keylength = keylength * 8; //convert keylength to bits
+
+        /* HMAC key length needs to be 80-2048 bits */
+        if ((keylength < 80) || (keylength > 2048)) {
+                TRACE_ERROR("HMAC key size of %lu bits not within"
+                            " CCA required range of 80-2048 bits\n", keylength);
+                return CKR_KEY_SIZE_RANGE;
+        }
+
+        rule_array_count = 4;
+        memcpy(rule_array, "INTERNALHMAC    MAC     GENERATE", rule_array_count * CCA_KEYWORD_SIZE);
+
+        CSNBKTB2(&return_code,
+                 &reason_code,
+                 NULL,
+                 NULL,
+                 &rule_array_count,
+                 rule_array,
+                 &clear_key_length, /* 0 here */
+                 NULL,
+                 &key_name_length, /* no key name, 0 here */
+                 NULL,
+                 &user_data_length, /* no user data, 0 here */
+                 NULL,
+                 &zero_length, /* reserved parameter and length must be 0 */
+                 NULL,
+                 &zero_length, /* reserved parameter and length must be 0 *
+                 NULL,
+                 &key_token_length, /* hmac token length */
+                 key_token); /* hmac generate token */
+        if (return_code != CCA_SUCCESS) {
+                TRACE_ERROR("CSNBKTB2 (HMAC KEY TOKEN BUILD) failed."
+                            " return:%ld, reason:%ld\n",
+                            return_code, reason_code);
+                return CKR_FUNCTION_FAILED;
+        }
+
+        /*** generate the hmac key here **/
+        return_code = -1;
+        reason_code = -1;
+
+        rule_array_count = 2;
+        memset(rule_array, 0, sizeof(rule_array));
+        /* create rule_array with 2 keywords */
+         memcpy(rule_array, "HMAC    OP      ", rule_array_count * CCA_KEYWORD_SIZE);
+
+        /*ask to create the hmac key with application specified key length in bits */
+        clear_key_length = keylength;
+
+        memcpy(key_type1, "TOKEN   ", CCA_KEYWORD_SIZE);
+        /*for only one copy of key generated, specify 8 spaces in key_type2 per CCA basic services guide*/
+        memcpy(key_type2, "        ", CCA_KEYWORD_SIZE);
+
+        /*token lengths are set to size of buffer */
+        key_token_length = sizeof(key_token);
+
+        CSNBKGN2( &return_code,
+            &reason_code,
+            &zero_length,
+            NULL,
+            &rule_array_count,
+            rule_array,
+            &clear_key_length,
+            key_type1,
+            key_type2,
+            &key_name_length,     /* 0 here */
+            NULL,
+            &key_name_length,     /* 0 here */
+            NULL,
+            &user_data_length,    /* 0 here */
+            NULL,
+            &user_data_length,    /* 0 here */
+            NULL,
+            &zero_length,
+            NULL,
+            &zero_length,
+            NULL,
+            &key_token_length,    /* hmac key token length */
+            key_token,            /* generated key */
+            &zero_length,         /* 0 here for second key, only one key generated */
+            NULL );
+
+        if (return_code != CCA_SUCCESS) {
+                TRACE_ERROR("CSNBKGN2 (HMAC KEY GENERATE) failed."
+                            " return:%ld, reason:%ld\n",
+                            return_code, reason_code);
+                return CKR_FUNCTION_FAILED;
+        }
+
+        //set the attributes in template after key generation
+        rc = set_attributes_key_gen(template, key_token, key_token_length);
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("set_attributed_key_gen for secret key generation failed\n");
+                return rc;
+        }
+
+        return CKR_OK;
+}
+
+/** This function sets all the attributes to template after a successful secret key generation */
+CK_RV set_attributes_key_gen(TEMPLATE *tmpl, CK_BYTE *data, long data_len)
+{
+        CK_ATTRIBUTE     *opaque_attr = NULL;
+        CK_ATTRIBUTE     *value_attr    = NULL;
+        CK_ATTRIBUTE     *key_type_attr = NULL;
+        CK_ATTRIBUTE     *class_attr    = NULL;
+        CK_ATTRIBUTE     *local_attr    = NULL;
+        CK_BYTE           dummy_key[CCA_MAX_HMAC_KEY_TOKEN_SIZE] = {0};
+        CK_RV             rc = 0;
+
+        opaque_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + data_len);
+        value_attr    = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + data_len );
+        key_type_attr = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE) );
+        class_attr    = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_OBJECT_CLASS) );
+        local_attr    = (CK_ATTRIBUTE *)malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_BBOOL) );
+
+        if (!opaque_attr || !value_attr || !key_type_attr || !class_attr || !local_attr) {
+                if (opaque_attr)   free(opaque_attr);
+                if (value_attr)    free( value_attr );
+                if (key_type_attr) free( key_type_attr );
+                if (class_attr)    free( class_attr );
+                if (local_attr)    free( local_attr );
+
+                TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
+                rc = CKR_HOST_MEMORY;
+                return rc;
+        }
+
+        opaque_attr->type = CKA_IBM_OPAQUE;
+        opaque_attr->ulValueLen = data_len;
+        opaque_attr->pValue = (CK_BYTE *)opaque_attr + sizeof(CK_ATTRIBUTE);
+        memcpy(opaque_attr->pValue, data, data_len);
+
+        //for secure key, set dummy value in CKA_VALUE
+        value_attr->type         = CKA_VALUE;
+        value_attr->ulValueLen   = data_len;
+        value_attr->pValue       = (CK_BYTE *)value_attr + sizeof(CK_ATTRIBUTE);
+        memcpy( value_attr->pValue, dummy_key, data_len );
+
+        key_type_attr->type         = CKA_KEY_TYPE;
+        key_type_attr->ulValueLen   = sizeof(CK_KEY_TYPE);
+        key_type_attr->pValue       = (CK_BYTE *)key_type_attr + sizeof(CK_ATTRIBUTE);
+        *(CK_KEY_TYPE *)key_type_attr->pValue = CKK_GENERIC_SECRET;
+
+        class_attr->type         = CKA_CLASS;
+        class_attr->ulValueLen   = sizeof(CK_OBJECT_CLASS);
+        class_attr->pValue       = (CK_BYTE *)class_attr + sizeof(CK_ATTRIBUTE);
+        *(CK_OBJECT_CLASS *)class_attr->pValue = CKO_SECRET_KEY;
+
+        local_attr->type         = CKA_LOCAL;
+        local_attr->ulValueLen   = sizeof(CK_BBOOL);
+        local_attr->pValue       = (CK_BYTE *)local_attr + sizeof(CK_ATTRIBUTE);
+        *(CK_BBOOL *)local_attr->pValue = TRUE;
+
+        //update all the attributes in the template
+        rc = template_update_attribute(tmpl, opaque_attr);
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_IBM_OPAQUE) failed\n");
+                return rc;
+        }
+        rc = template_update_attribute( tmpl, value_attr );
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_VALUE) failed\n");
+                return rc;
+        }
+        rc = template_update_attribute( tmpl, key_type_attr );
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_KEY_TYPE) failed\n");
+                return rc;
+        }
+        rc = template_update_attribute( tmpl, class_attr );
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_CLASS) failed\n");
+                return rc;
+        }
+        rc = template_update_attribute( tmpl, local_attr );
+        if (rc != CKR_OK) {
+                TRACE_DEVEL("template_update_attribute(CKA_LOCAL) failed\n");
+                return rc;
+        }
+
+        return CKR_OK;
+}
diff --git a/usr/lib/pkcs11/cca_stdll/cca_stdll.h b/usr/lib/pkcs11/cca_stdll/cca_stdll.h
index 4f33d80..4dcf32f 100644
--- a/usr/lib/pkcs11/cca_stdll/cca_stdll.h
+++ b/usr/lib/pkcs11/cca_stdll/cca_stdll.h
@@ -28,6 +28,7 @@
 #define CCA_PKB_E_OFFSET                18
 #define CCA_PKB_E_SIZE                  2
 #define CCA_PKB_E_SIZE_OFFSET           4
+#define CCA_MAX_HMAC_KEY_TOKEN_SIZE     800
 
 /* Elliptic Curve constants */
 /* CCA spec: page 94 */
diff --git a/usr/lib/pkcs11/cca_stdll/csulincl.h b/usr/lib/pkcs11/cca_stdll/csulincl.h
index 74e7cd2..ce93826 100644
--- a/usr/lib/pkcs11/cca_stdll/csulincl.h
+++ b/usr/lib/pkcs11/cca_stdll/csulincl.h
@@ -32,6 +32,7 @@
   #define CSNBMKP   CSNBMKP_32
   #define CSNBKEX   CSNBKEX_32
   #define CSNBKGN   CSNBKGN_32
+  #define CSNBKGN2   CSNBKGN2_32
   #define CSNBKIM   CSNBKIM_32
   #define CSNBKPI   CSNBKPI_32
   #define CSNBKPI2  CSNBKPI2_32
@@ -198,6 +199,34 @@ extern void SECURITYAPI
               unsigned char * generated_key_identifier_1,
               unsigned char * generated_key_identifier_2);
 
+/* Key Generate2 */
+extern void SECURITYAPI
+    CSNBKGN2_32(long             * return_code,
+                long             * reason_code,
+                long             * exit_data_length,
+                unsigned char    * exit_data,
+                long             * rule_array_count,
+                unsigned char    * rule_array,
+                long             * clear_key_bit_length,
+                unsigned char    * key_type_1,
+                unsigned char    * key_type_2,
+                long             * key_name_1_length,
+                unsigned char    * key_name_1,
+                long             * key_name_2_length,
+                unsigned char    * key_name_2,
+                long             * user_associated_data_1_length,
+                unsigned char    * user_associated_data_1,
+                long             * user_associated_data_2_length,
+                unsigned char    * user_associated_data_2,
+                long             * key_encrypting_key_identifier_1_length,
+                unsigned char    * key_encrypting_key_identifier_1,
+                long             * key_encrypting_key_identifier_2_length,
+                unsigned char    * key_encrypting_key_identifier_2,
+                long             * generated_key_identifier_1_length,
+                unsigned char    * generated_key_identifier_1,
+                long             * generated_key_identifier_2_length,
+                unsigned char    * generated_key_identifier_2);
+
 /* Key Import */
 extern void SECURITYAPI
    CSNBKIM_32(long          * return_code,
diff --git a/usr/lib/pkcs11/cca_stdll/tok_struct.h b/usr/lib/pkcs11/cca_stdll/tok_struct.h
index 8e84885..5b1207e 100644
--- a/usr/lib/pkcs11/cca_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/cca_stdll/tok_struct.h
@@ -129,7 +129,8 @@ token_spec_t token_specific = {
 	NULL,			// dsa_verify
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
-	&token_specific_object_add
+	&token_specific_object_add,
+        &token_specific_generic_secret_key_gen,
 };
 
 #endif
diff --git a/usr/lib/pkcs11/common/h_extern.h b/usr/lib/pkcs11/common/h_extern.h
index b9bdecb..d9dc432 100755
--- a/usr/lib/pkcs11/common/h_extern.h
+++ b/usr/lib/pkcs11/common/h_extern.h
@@ -1798,6 +1798,9 @@ CK_RV sha5_hmac_verify(SESSION *sess, SIGN_VERIFY_CONTEXT *ctx,
                        CK_BYTE *in_data, CK_ULONG in_data_len,
                        CK_BYTE *signature, CK_ULONG sig_len);
 
+//adding the hmac secret key generation here
+CK_RV ckm_generic_secret_key_gen(TEMPLATE *tmpl);
+
 // MD2 mechanisms
 //
 CK_RV  md2_hash( SESSION  *sess,     CK_BBOOL  length_only,
diff --git a/usr/lib/pkcs11/common/key_mgr.c b/usr/lib/pkcs11/common/key_mgr.c
index 795c8e7..fd90e68 100755
--- a/usr/lib/pkcs11/common/key_mgr.c
+++ b/usr/lib/pkcs11/common/key_mgr.c
@@ -415,6 +415,15 @@ key_mgr_generate_key( SESSION           * sess,
 	 subclass = CKK_AES;
 	 break;
 
+      case CKM_GENERIC_SECRET_KEY_GEN:
+         if (subclass != 0 && subclass != CKK_GENERIC_SECRET){
+           TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCONSISTENT));
+           return CKR_TEMPLATE_INCONSISTENT;
+         }
+
+         subclass = CKK_GENERIC_SECRET;
+         break;
+ 
       default:
          TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
          return CKR_MECHANISM_INVALID;
@@ -459,6 +468,10 @@ key_mgr_generate_key( SESSION           * sess,
 	    rc = ckm_aes_key_gen( key_obj->template );
 	    break;
 #endif
+         case CKM_GENERIC_SECRET_KEY_GEN:
+            rc = ckm_generic_secret_key_gen( key_obj->template );
+            break;
+
       default:
          TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
          rc = CKR_MECHANISM_INVALID;
diff --git a/usr/lib/pkcs11/common/mech_sha.c b/usr/lib/pkcs11/common/mech_sha.c
index 87067cc..e05c7a3 100755
--- a/usr/lib/pkcs11/common/mech_sha.c
+++ b/usr/lib/pkcs11/common/mech_sha.c
@@ -1847,3 +1847,20 @@ void sha5_init(DIGEST_CONTEXT * ctx)
 		token_specific.t_sha5_init(ctx);
 	}
 }
+
+//Adding the hmac secret key gen here for lack of a better place to put this
+CK_RV
+ckm_generic_secret_key_gen( TEMPLATE *tmpl )
+{
+        CK_ULONG           rc;
+
+        if (token_specific.t_generic_secret_key_gen == NULL) {
+                TRACE_ERROR("%s\n", ock_err(ERR_MECHANISM_INVALID));
+                return CKR_MECHANISM_INVALID;
+        }
+
+        rc = token_specific.t_generic_secret_key_gen(tmpl);
+
+        return rc;
+}
+
diff --git a/usr/lib/pkcs11/common/tok_spec_struct.h b/usr/lib/pkcs11/common/tok_spec_struct.h
index a5ce813..f72ebff 100755
--- a/usr/lib/pkcs11/common/tok_spec_struct.h
+++ b/usr/lib/pkcs11/common/tok_spec_struct.h
@@ -511,6 +511,8 @@ struct token_specific_struct {
 
 	CK_RV (*t_object_add)(OBJECT *);
 
+	CK_RV (*t_generic_secret_key_gen) (TEMPLATE *);
+
 };
 
 typedef struct token_specific_struct token_spec_t;
diff --git a/usr/lib/pkcs11/common/tok_specific.h b/usr/lib/pkcs11/common/tok_specific.h
index cb72adb..348209b 100755
--- a/usr/lib/pkcs11/common/tok_specific.h
+++ b/usr/lib/pkcs11/common/tok_specific.h
@@ -627,4 +627,7 @@ token_specific_get_mechanism_info(CK_MECHANISM_TYPE type,
 CK_RV
 token_specific_object_add(OBJECT *);
 
+CK_RV 
+token_specific_generic_secret_key_gen (TEMPLATE *template);
+
 #endif
diff --git a/usr/lib/pkcs11/ep11_stdll/tok_struct.h b/usr/lib/pkcs11/ep11_stdll/tok_struct.h
index 0b61134..f0fb668 100644
--- a/usr/lib/pkcs11/ep11_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/ep11_stdll/tok_struct.h
@@ -403,6 +403,7 @@ token_spec_t token_specific = {
 	NULL,			// get_mechanism_list
 	NULL,			// get mechanism_info
         &token_specific_object_add,
+        NULL    // generic_secret_key_gen
 };
 
 #endif
diff --git a/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h b/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
index 672894f..7c5720f 100644
--- a/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/ica_s390_stdll/tok_struct.h
@@ -396,7 +396,8 @@ token_spec_t token_specific = {
 	NULL,		// dsa_verify
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
-	NULL			// object_add
+	NULL,			// object_add
+        NULL   // generic_secret_key_gen
 };
 
 #endif
diff --git a/usr/lib/pkcs11/icsf_stdll/tok_struct.h b/usr/lib/pkcs11/icsf_stdll/tok_struct.h
index 980409f..9688ded 100644
--- a/usr/lib/pkcs11/icsf_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/icsf_stdll/tok_struct.h
@@ -122,6 +122,7 @@ token_spec_t token_specific = {
 	NULL,			// get_mechanism_list
 	NULL,			// get_mechanism_info
 	NULL,			// object_add
+        NULL        // generic_secret_key_gen
 };
 
 #endif
diff --git a/usr/lib/pkcs11/soft_stdll/tok_struct.h b/usr/lib/pkcs11/soft_stdll/tok_struct.h
index ebeefab..645db27 100644
--- a/usr/lib/pkcs11/soft_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/soft_stdll/tok_struct.h
@@ -411,7 +411,8 @@ token_spec_t token_specific = {
 	NULL,			// dsa_verify
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
-	NULL			// object_add
+	NULL,			// object_add
+        NULL   // generic_secret_key_gen
 };
 
 #endif
diff --git a/usr/lib/pkcs11/tpm_stdll/tok_struct.h b/usr/lib/pkcs11/tpm_stdll/tok_struct.h
index 1ff1ff0..c9500c7 100644
--- a/usr/lib/pkcs11/tpm_stdll/tok_struct.h
+++ b/usr/lib/pkcs11/tpm_stdll/tok_struct.h
@@ -127,5 +127,6 @@ struct token_specific_struct token_specific = {
 	NULL,			// dsa_verify
 	&token_specific_get_mechanism_list,
 	&token_specific_get_mechanism_info,
-	NULL			// object_add
+	NULL,			// object_add
+        NULL    // generic_secret_key_gen
 };
-- 
1.7.1

------------------------------------------------------------------------------
_______________________________________________
Opencryptoki-tech mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opencryptoki-tech

Reply via email to