Blame SOURCES/0021-COMMON-EP11-Allow-to-select-Dilithium-variant-via-mo.patch

1f6f0c
From 57cd8cd4db0d68c08b123b669f1cf57bed0fe34d Mon Sep 17 00:00:00 2001
1f6f0c
From: Ingo Franzki <ifranzki@linux.ibm.com>
1f6f0c
Date: Thu, 17 Feb 2022 10:27:56 +0100
1f6f0c
Subject: [PATCH 21/34] COMMON/EP11: Allow to select Dilithium variant via mode
1f6f0c
 or key form attribute
1f6f0c
1f6f0c
Attributes CKA_IBM_DILITHIUM_KEYFORM or CKA_IBM_DILITHIUM_MODE can
1f6f0c
be used to select the Dilithium variant to use.
1f6f0c
1f6f0c
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
1f6f0c
---
1f6f0c
 testcases/common/common.c          |   4 +-
1f6f0c
 usr/lib/common/asn1.c              |  20 +-
1f6f0c
 usr/lib/common/h_extern.h          |  11 +-
1f6f0c
 usr/lib/common/key.c               | 443 +++++++++++++++++++++++--------------
1f6f0c
 usr/lib/ep11_stdll/ep11_specific.c |  84 +++++--
1f6f0c
 5 files changed, 375 insertions(+), 187 deletions(-)
1f6f0c
1f6f0c
diff --git a/testcases/common/common.c b/testcases/common/common.c
1f6f0c
index 8ec5043b..fac9e4e6 100644
1f6f0c
--- a/testcases/common/common.c
1f6f0c
+++ b/testcases/common/common.c
1f6f0c
@@ -629,7 +629,7 @@ CK_RV create_DilithiumPrivateKey(CK_SESSION_HANDLE session,
1f6f0c
     CK_UTF8CHAR label[] = "A Dilithium private key object";
1f6f0c
     CK_BYTE subject[] = {0};
1f6f0c
     CK_BYTE id[] = { 123 };
1f6f0c
-    CK_ULONG keyform = IBM_DILITHIUM_KEYFORM_ROUND2;
1f6f0c
+    CK_ULONG keyform = CK_IBM_DILITHIUM_KEYFORM_ROUND2_65;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
     CK_BBOOL true = TRUE;
1f6f0c
@@ -678,7 +678,7 @@ CK_RV create_DilithiumPublicKey(CK_SESSION_HANDLE session,
1f6f0c
     CK_KEY_TYPE keyType = CKK_IBM_PQC_DILITHIUM;
1f6f0c
     CK_UTF8CHAR label[] = "A Dilithium public key object";
1f6f0c
     CK_BBOOL true = TRUE;
1f6f0c
-    CK_ULONG keyform = IBM_DILITHIUM_KEYFORM_ROUND2;
1f6f0c
+    CK_ULONG keyform = CK_IBM_DILITHIUM_KEYFORM_ROUND2_65;
1f6f0c
     CK_ATTRIBUTE template[] = {
1f6f0c
         {CKA_CLASS, &class, sizeof(class)},
1f6f0c
         {CKA_KEY_TYPE, &keyType, sizeof(keyType)},
1f6f0c
diff --git a/usr/lib/common/asn1.c b/usr/lib/common/asn1.c
1f6f0c
index dbf06dfd..85d3924c 100644
1f6f0c
--- a/usr/lib/common/asn1.c
1f6f0c
+++ b/usr/lib/common/asn1.c
1f6f0c
@@ -3788,7 +3788,8 @@ CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data,
1f6f0c
                                         CK_ULONG data_len,
1f6f0c
                                         CK_ATTRIBUTE **rho_attr,
1f6f0c
                                         CK_ATTRIBUTE **t1_attr,
1f6f0c
-                                        CK_ATTRIBUTE **value_attr)
1f6f0c
+                                        CK_ATTRIBUTE **value_attr,
1f6f0c
+                                        const struct pqc_oid **oid)
1f6f0c
 {
1f6f0c
     CK_ATTRIBUTE *rho_attr_temp = NULL;
1f6f0c
     CK_ATTRIBUTE *t1_attr_temp = NULL;
1f6f0c
@@ -3818,8 +3819,8 @@ CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data,
1f6f0c
        return rc;
1f6f0c
     }
1f6f0c
 
1f6f0c
-    if (algoid_len != dilithium_r2_65_len ||
1f6f0c
-        memcmp(algoid, dilithium_r2_65, dilithium_r2_65_len) != 0) {
1f6f0c
+    *oid = find_pqc_by_oid(dilithium_oids, algoid, algoid_len);
1f6f0c
+    if (*oid == NULL) {
1f6f0c
         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
1f6f0c
         return CKR_FUNCTION_FAILED;
1f6f0c
     }
1f6f0c
@@ -4155,7 +4156,8 @@ CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
1f6f0c
                                          CK_ATTRIBUTE **s2,
1f6f0c
                                          CK_ATTRIBUTE **t0,
1f6f0c
                                          CK_ATTRIBUTE **t1,
1f6f0c
-                                         CK_ATTRIBUTE **value)
1f6f0c
+                                         CK_ATTRIBUTE **value,
1f6f0c
+                                         const struct pqc_oid **oid)
1f6f0c
 {
1f6f0c
     CK_ATTRIBUTE *rho_attr = NULL, *seed_attr = NULL;
1f6f0c
     CK_ATTRIBUTE *tr_attr = NULL, *s1_attr = NULL, *s2_attr = NULL;
1f6f0c
@@ -4175,8 +4177,14 @@ CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
1f6f0c
         return rc;
1f6f0c
     }
1f6f0c
 
1f6f0c
-    if (len != dilithium_r2_65_len + ber_NULLLen ||
1f6f0c
-        memcmp(algoid, dilithium_r2_65, dilithium_r2_65_len) != 0) {
1f6f0c
+    if (len <= ber_NULLLen ||
1f6f0c
+        memcmp(algoid + len - ber_NULLLen, ber_NULL, ber_NULLLen) != 0) {
1f6f0c
+        TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
1f6f0c
+        return CKR_FUNCTION_FAILED;
1f6f0c
+    }
1f6f0c
+    len -= ber_NULLLen;
1f6f0c
+    *oid = find_pqc_by_oid(dilithium_oids, algoid, len);
1f6f0c
+    if (*oid == NULL) {
1f6f0c
         TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
1f6f0c
         return CKR_FUNCTION_FAILED;
1f6f0c
     }
1f6f0c
diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
1f6f0c
index 53909e99..fdbcacd9 100644
1f6f0c
--- a/usr/lib/common/h_extern.h
1f6f0c
+++ b/usr/lib/common/h_extern.h
1f6f0c
@@ -26,6 +26,7 @@
1f6f0c
 #include <stdio.h>
1f6f0c
 #include "dlist.h"
1f6f0c
 #include "host_defs.h"
1f6f0c
+#include "pqc_defs.h"
1f6f0c
 
1f6f0c
 #include <openssl/evp.h>
1f6f0c
 
1f6f0c
@@ -2504,6 +2505,10 @@ CK_RV ibm_dilithium_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data,
1f6f0c
 CK_RV ibm_dilithium_priv_unwrap_get_data(TEMPLATE *tmpl,
1f6f0c
                                          CK_BYTE *data, CK_ULONG total_length,
1f6f0c
                                          CK_BBOOL add_value);
1f6f0c
+const struct pqc_oid *ibm_pqc_get_keyform_mode(TEMPLATE *tmpl,
1f6f0c
+                                               CK_MECHANISM_TYPE mech);
1f6f0c
+CK_RV ibm_pqc_add_keyform_mode(TEMPLATE *tmpl, const struct pqc_oid *oid,
1f6f0c
+                               CK_MECHANISM_TYPE mech);
1f6f0c
 
1f6f0c
 // diffie-hellman routines
1f6f0c
 //
1f6f0c
@@ -2750,7 +2755,8 @@ CK_RV ber_decode_IBM_DilithiumPublicKey(CK_BYTE *data,
1f6f0c
                                         CK_ULONG data_len,
1f6f0c
                                         CK_ATTRIBUTE **rho_attr,
1f6f0c
                                         CK_ATTRIBUTE **t1_attr,
1f6f0c
-                                        CK_ATTRIBUTE **value_attr);
1f6f0c
+                                        CK_ATTRIBUTE **value_attr,
1f6f0c
+                                        const struct pqc_oid **oid);
1f6f0c
 
1f6f0c
 CK_RV ber_encode_IBM_DilithiumPrivateKey(CK_BBOOL length_only,
1f6f0c
                                          CK_BYTE **data,
1f6f0c
@@ -2773,7 +2779,8 @@ CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
1f6f0c
                                          CK_ATTRIBUTE **s2,
1f6f0c
                                          CK_ATTRIBUTE **t0,
1f6f0c
                                          CK_ATTRIBUTE **t1,
1f6f0c
-                                         CK_ATTRIBUTE **value);
1f6f0c
+                                         CK_ATTRIBUTE **value,
1f6f0c
+                                         const struct pqc_oid **oid);
1f6f0c
 
1f6f0c
 typedef CK_RV (*t_rsa_encrypt)(STDLL_TokData_t *, CK_BYTE *in_data,
1f6f0c
                                CK_ULONG in_data_len, CK_BYTE *out_data,
1f6f0c
diff --git a/usr/lib/common/key.c b/usr/lib/common/key.c
1f6f0c
index b0050816..ba40cefd 100644
1f6f0c
--- a/usr/lib/common/key.c
1f6f0c
+++ b/usr/lib/common/key.c
1f6f0c
@@ -2654,6 +2654,117 @@ error:
1f6f0c
     return rc;
1f6f0c
 }
1f6f0c
 
1f6f0c
+static CK_RV ibm_pqc_keyform_mode_attrs_by_mech(CK_MECHANISM_TYPE mech,
1f6f0c
+                                                CK_ATTRIBUTE_TYPE *keyform_attr,
1f6f0c
+                                                CK_ATTRIBUTE_TYPE *mode_attr,
1f6f0c
+                                                const struct pqc_oid **oids)
1f6f0c
+{
1f6f0c
+    switch (mech) {
1f6f0c
+    case CKM_IBM_DILITHIUM:
1f6f0c
+        *keyform_attr = CKA_IBM_DILITHIUM_KEYFORM;
1f6f0c
+        *mode_attr = CKA_IBM_DILITHIUM_MODE;
1f6f0c
+        *oids = dilithium_oids;
1f6f0c
+        break;
1f6f0c
+    case CKM_IBM_KYBER:
1f6f0c
+        *keyform_attr = CKA_IBM_KYBER_KEYFORM;
1f6f0c
+        *mode_attr = CKA_IBM_KYBER_MODE;
1f6f0c
+        *oids = kyber_oids;
1f6f0c
+        break;
1f6f0c
+    default:
1f6f0c
+        TRACE_ERROR("Unsupported mechanims: 0x%lx\n", mech);
1f6f0c
+        return CKR_MECHANISM_INVALID;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    return CKR_OK;
1f6f0c
+}
1f6f0c
+
1f6f0c
+const struct pqc_oid *ibm_pqc_get_keyform_mode(TEMPLATE *tmpl,
1f6f0c
+                                               CK_MECHANISM_TYPE mech)
1f6f0c
+{
1f6f0c
+    CK_ATTRIBUTE *attr = NULL;
1f6f0c
+    const struct pqc_oid *oids, *oid;
1f6f0c
+    CK_ATTRIBUTE_TYPE keyform_attr;
1f6f0c
+    CK_ATTRIBUTE_TYPE mode_attr;
1f6f0c
+
1f6f0c
+    if (ibm_pqc_keyform_mode_attrs_by_mech(mech, &keyform_attr,
1f6f0c
+                                           &mode_attr, &oids) != CKR_OK)
1f6f0c
+        return NULL;
1f6f0c
+
1f6f0c
+    if (template_attribute_find(tmpl, keyform_attr, &attr) &&
1f6f0c
+        attr->ulValueLen == sizeof(CK_ULONG) && attr->pValue != NULL) {
1f6f0c
+        oid = find_pqc_by_keyform(oids, *(CK_ULONG *)(attr->pValue));
1f6f0c
+        if (oid == NULL) {
1f6f0c
+            TRACE_ERROR("KEYFORM attribute specifies an invalid value: %lu\n",
1f6f0c
+                        *(CK_ULONG *)(attr->pValue));
1f6f0c
+            return NULL;
1f6f0c
+        }
1f6f0c
+        return oid;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    if (template_attribute_find(tmpl, mode_attr, &attr) &&
1f6f0c
+        attr->ulValueLen != 0 && attr->pValue != NULL) {
1f6f0c
+        oid = find_pqc_by_oid(oids, attr->pValue, attr->ulValueLen);
1f6f0c
+        if (oid == NULL) {
1f6f0c
+            TRACE_ERROR("MODE attribute specifies an invalid value\n");
1f6f0c
+            return NULL;
1f6f0c
+        }
1f6f0c
+        return oid;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    TRACE_ERROR("Neither KEYFORM nor MODE found\n");
1f6f0c
+    return NULL;
1f6f0c
+}
1f6f0c
+
1f6f0c
+CK_RV ibm_pqc_add_keyform_mode(TEMPLATE *tmpl, const struct pqc_oid *oid,
1f6f0c
+                               CK_MECHANISM_TYPE mech)
1f6f0c
+{
1f6f0c
+    CK_ATTRIBUTE *mode = NULL;
1f6f0c
+    CK_ATTRIBUTE *keyform = NULL;
1f6f0c
+    CK_RV rc;
1f6f0c
+    CK_ATTRIBUTE_TYPE keyform_attr;
1f6f0c
+    CK_ATTRIBUTE_TYPE mode_attr;
1f6f0c
+    const struct pqc_oid *oids;
1f6f0c
+
1f6f0c
+    if (ibm_pqc_keyform_mode_attrs_by_mech(mech, &keyform_attr,
1f6f0c
+                                           &mode_attr, &oids) != CKR_OK)
1f6f0c
+        return CKR_MECHANISM_INVALID;
1f6f0c
+
1f6f0c
+    rc = build_attribute(mode_attr, (CK_BYTE *)oid->oid, oid->oid_len, &mode);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_DEVEL("build_attribute failed\n");
1f6f0c
+        goto error;
1f6f0c
+    }
1f6f0c
+    rc = template_update_attribute(tmpl, mode);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_DEVEL("template_update_attribute failed.\n");
1f6f0c
+        goto error;
1f6f0c
+    }
1f6f0c
+    mode = NULL;
1f6f0c
+
1f6f0c
+    rc = build_attribute(keyform_attr, (CK_BYTE *)&oid->keyform,
1f6f0c
+                         sizeof(CK_ULONG), &keyform);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_DEVEL("build_attribute failed\n");
1f6f0c
+        goto error;
1f6f0c
+    }
1f6f0c
+    rc = template_update_attribute(tmpl, keyform);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_DEVEL("template_update_attribute failed.\n");
1f6f0c
+        goto error;
1f6f0c
+    }
1f6f0c
+    keyform = NULL;
1f6f0c
+
1f6f0c
+    return CKR_OK;
1f6f0c
+
1f6f0c
+error:
1f6f0c
+    if (mode)
1f6f0c
+        free(mode);
1f6f0c
+    if (keyform)
1f6f0c
+        free(keyform);
1f6f0c
+
1f6f0c
+    return rc;
1f6f0c
+}
1f6f0c
+
1f6f0c
 /*
1f6f0c
  * Extract the SubjectPublicKeyInfo from the Dilithium public key
1f6f0c
  */
1f6f0c
@@ -2662,21 +2773,12 @@ CK_RV ibm_dilithium_publ_get_spki(TEMPLATE *tmpl, CK_BBOOL length_only,
1f6f0c
 {
1f6f0c
     CK_ATTRIBUTE *rho = NULL;
1f6f0c
     CK_ATTRIBUTE *t1 = NULL;
1f6f0c
-    CK_ULONG keyform;
1f6f0c
+    const struct pqc_oid *oid;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
-    rc = template_attribute_get_ulong(tmpl, CKA_IBM_DILITHIUM_KEYFORM,
1f6f0c
-                                      &keyform);
1f6f0c
-    if (rc != CKR_OK) {
1f6f0c
-        TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_KEYFORM for the key.\n");
1f6f0c
-        return rc;
1f6f0c
-    }
1f6f0c
-
1f6f0c
-    if ( keyform != IBM_DILITHIUM_KEYFORM_ROUND2) {
1f6f0c
-        TRACE_ERROR("This key has an unexpected CKA_IBM_DILITHIUM_KEYFORM: "
1f6f0c
-                    "%ld \n", keyform);
1f6f0c
-        return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
-    }
1f6f0c
+    oid = ibm_pqc_get_keyform_mode(tmpl, CKM_IBM_DILITHIUM);
1f6f0c
+    if (oid == NULL)
1f6f0c
+       return CKR_TEMPLATE_INCOMPLETE;
1f6f0c
 
1f6f0c
     rc = template_attribute_get_non_empty(tmpl, CKA_IBM_DILITHIUM_RHO, &rho);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
@@ -2690,8 +2792,7 @@ CK_RV ibm_dilithium_publ_get_spki(TEMPLATE *tmpl, CK_BBOOL length_only,
1f6f0c
     }
1f6f0c
 
1f6f0c
     rc = ber_encode_IBM_DilithiumPublicKey(length_only, data, data_len,
1f6f0c
-                                           dilithium_r2_65,
1f6f0c
-                                           dilithium_r2_65_len,
1f6f0c
+                                           oid->oid, oid->oid_len,
1f6f0c
                                            rho, t1);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_ERROR("ber_encode_IBM_DilithiumPublicKey failed.\n");
1f6f0c
@@ -2709,23 +2810,12 @@ CK_RV ibm_dilithium_priv_wrap_get_data(TEMPLATE *tmpl,
1f6f0c
     CK_ATTRIBUTE *rho = NULL, *seed = NULL;
1f6f0c
     CK_ATTRIBUTE *tr = NULL, *s1 = NULL, *s2 = NULL;
1f6f0c
     CK_ATTRIBUTE *t0 = NULL, *t1 = NULL;
1f6f0c
-    CK_ULONG keyform;
1f6f0c
+    const struct pqc_oid *oid;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
-    /* A private Dilithium key must have a keyform value */
1f6f0c
-    rc = template_attribute_get_ulong(tmpl, CKA_IBM_DILITHIUM_KEYFORM,
1f6f0c
-                                      &keyform);
1f6f0c
-    if (rc != CKR_OK) {
1f6f0c
-        TRACE_ERROR("Could not find CKA_IBM_DILITHIUM_KEYFORM for the key.\n");
1f6f0c
-        return rc;
1f6f0c
-    }
1f6f0c
-
1f6f0c
-    /* Check if it's an expected keyform */
1f6f0c
-    if (keyform != IBM_DILITHIUM_KEYFORM_ROUND2) {
1f6f0c
-        TRACE_ERROR("This key has an unexpected CKA_IBM_DILITHIUM_KEYFORM: %ld\n",
1f6f0c
-                    keyform);
1f6f0c
-        return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
-    }
1f6f0c
+    oid = ibm_pqc_get_keyform_mode(tmpl, CKM_IBM_DILITHIUM);
1f6f0c
+    if (oid == NULL)
1f6f0c
+       return CKR_TEMPLATE_INCOMPLETE;
1f6f0c
 
1f6f0c
     rc = template_attribute_get_non_empty(tmpl, CKA_IBM_DILITHIUM_RHO, &rho);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
@@ -2770,8 +2860,7 @@ CK_RV ibm_dilithium_priv_wrap_get_data(TEMPLATE *tmpl,
1f6f0c
     }
1f6f0c
 
1f6f0c
     rc = ber_encode_IBM_DilithiumPrivateKey(length_only, data, data_len,
1f6f0c
-                                            dilithium_r2_65,
1f6f0c
-                                            dilithium_r2_65_len,
1f6f0c
+                                            oid->oid, oid->oid_len,
1f6f0c
                                             rho, seed, tr, s1, s2, t0, t1);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_DEVEL("ber_encode_IBM_DilithiumPrivateKey failed\n");
1f6f0c
@@ -2787,15 +2876,22 @@ CK_RV ibm_dilithium_priv_unwrap_get_data(TEMPLATE *tmpl, CK_BYTE *data,
1f6f0c
     CK_ATTRIBUTE *rho = NULL;
1f6f0c
     CK_ATTRIBUTE *t1 = NULL;
1f6f0c
     CK_ATTRIBUTE *value = NULL;
1f6f0c
+    const struct pqc_oid *oid;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
     rc = ber_decode_IBM_DilithiumPublicKey(data, total_length, &rho, &t1,
1f6f0c
-                                           &value);
1f6f0c
+                                           &value, &oid;;
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_ERROR("ber_decode_DilithiumPublicKey failed\n");
1f6f0c
         return rc;
1f6f0c
     }
1f6f0c
 
1f6f0c
+    rc = ibm_pqc_add_keyform_mode(tmpl, oid, CKM_IBM_DILITHIUM);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_ERROR("ibm_pqc_add_keyform_mode failed\n");
1f6f0c
+        return rc;
1f6f0c
+    }
1f6f0c
+
1f6f0c
     rc = template_update_attribute(tmpl, rho);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_DEVEL("template_update_attribute failed.\n");
1f6f0c
@@ -2839,16 +2935,23 @@ CK_RV ibm_dilithium_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data,
1f6f0c
 {
1f6f0c
     CK_ATTRIBUTE *rho = NULL, *seed = NULL, *tr = NULL, *value = NULL;
1f6f0c
     CK_ATTRIBUTE *s1 = NULL, *s2 = NULL, *t0 = NULL, *t1 = NULL;
1f6f0c
+    const struct pqc_oid *oid;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
     rc = ber_decode_IBM_DilithiumPrivateKey(data, total_length,
1f6f0c
                                             &rho, &seed, &tr, &s1, &s2, &t0,
1f6f0c
-                                            &t1, &value);
1f6f0c
+                                            &t1, &value, &oid;;
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_ERROR("der_decode_IBM_DilithiumPrivateKey failed\n");
1f6f0c
         return rc;
1f6f0c
     }
1f6f0c
 
1f6f0c
+    rc = ibm_pqc_add_keyform_mode(tmpl, oid, CKM_IBM_DILITHIUM);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_ERROR("ibm_pqc_add_keyform_mode failed\n");
1f6f0c
+        return rc;
1f6f0c
+    }
1f6f0c
+
1f6f0c
     rc = template_update_attribute(tmpl, rho);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_ERROR("template_update_attribute failed\n");
1f6f0c
@@ -4660,19 +4763,17 @@ CK_RV ibm_dilithium_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
     CK_ATTRIBUTE *type_attr = NULL;
1f6f0c
     CK_ATTRIBUTE *rho_attr = NULL;
1f6f0c
     CK_ATTRIBUTE *t1_attr = NULL;
1f6f0c
-    CK_ATTRIBUTE *keyform_attr = NULL;
1f6f0c
     CK_ATTRIBUTE *value_attr = NULL;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
     publ_key_set_default_attributes(tmpl, mode);
1f6f0c
 
1f6f0c
     type_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
1f6f0c
-    keyform_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
1f6f0c
     rho_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
1f6f0c
     t1_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
1f6f0c
     value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
1f6f0c
 
1f6f0c
-    if (!type_attr || !rho_attr || !t1_attr || !keyform_attr || !value_attr) {
1f6f0c
+    if (!type_attr || !rho_attr || !t1_attr || !value_attr) {
1f6f0c
         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1f6f0c
         rc = CKR_HOST_MEMORY;
1f6f0c
         goto error;
1f6f0c
@@ -4683,11 +4784,6 @@ CK_RV ibm_dilithium_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
     type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
1f6f0c
     *(CK_KEY_TYPE *) type_attr->pValue = CKK_IBM_PQC_DILITHIUM;
1f6f0c
 
1f6f0c
-    keyform_attr->type = CKA_IBM_DILITHIUM_KEYFORM;
1f6f0c
-    keyform_attr->ulValueLen = sizeof(CK_ULONG);
1f6f0c
-    keyform_attr->pValue = (CK_BYTE *) keyform_attr + sizeof(CK_ATTRIBUTE);
1f6f0c
-    *(CK_ULONG *) keyform_attr->pValue = IBM_DILITHIUM_KEYFORM_ROUND2;
1f6f0c
-
1f6f0c
     rho_attr->type = CKA_IBM_DILITHIUM_RHO;
1f6f0c
     rho_attr->ulValueLen = 0;
1f6f0c
     rho_attr->pValue = NULL;
1f6f0c
@@ -4718,12 +4814,6 @@ CK_RV ibm_dilithium_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
         goto error;
1f6f0c
     }
1f6f0c
     t1_attr = NULL;
1f6f0c
-    rc = template_update_attribute(tmpl, keyform_attr);
1f6f0c
-    if (rc != CKR_OK) {
1f6f0c
-        TRACE_ERROR("template_update_attribute failed\n");
1f6f0c
-        goto error;
1f6f0c
-    }
1f6f0c
-    keyform_attr = NULL;
1f6f0c
     rc = template_update_attribute(tmpl, value_attr);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_ERROR("template_update_attribute failed\n");
1f6f0c
@@ -4740,8 +4830,6 @@ error:
1f6f0c
         free(rho_attr);
1f6f0c
     if (t1_attr)
1f6f0c
         free(t1_attr);
1f6f0c
-    if (keyform_attr)
1f6f0c
-        free(keyform_attr);
1f6f0c
     if (value_attr)
1f6f0c
         free(value_attr);
1f6f0c
 
1f6f0c
@@ -4760,14 +4848,12 @@ CK_RV ibm_dilithium_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
     CK_ATTRIBUTE *s2_attr = NULL;
1f6f0c
     CK_ATTRIBUTE *t0_attr = NULL;
1f6f0c
     CK_ATTRIBUTE *t1_attr = NULL;
1f6f0c
-    CK_ATTRIBUTE *keyform_attr = NULL;
1f6f0c
     CK_ATTRIBUTE *value_attr = NULL;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
     priv_key_set_default_attributes(tmpl, mode);
1f6f0c
 
1f6f0c
     type_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
1f6f0c
-    keyform_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_ULONG));
1f6f0c
     rho_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
1f6f0c
     seed_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
1f6f0c
     tr_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
1f6f0c
@@ -4778,7 +4864,7 @@ CK_RV ibm_dilithium_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
     value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
1f6f0c
 
1f6f0c
     if (!type_attr || !rho_attr || !seed_attr || !tr_attr || !s1_attr
1f6f0c
-        || !s2_attr || !t0_attr || !t1_attr || !keyform_attr || !value_attr) {
1f6f0c
+        || !s2_attr || !t0_attr || !t1_attr || !value_attr) {
1f6f0c
         TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
1f6f0c
         rc = CKR_HOST_MEMORY;
1f6f0c
         goto error;
1f6f0c
@@ -4789,11 +4875,6 @@ CK_RV ibm_dilithium_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
     type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
1f6f0c
     *(CK_KEY_TYPE *) type_attr->pValue = CKK_IBM_PQC_DILITHIUM;
1f6f0c
 
1f6f0c
-    keyform_attr->type = CKA_IBM_DILITHIUM_KEYFORM;
1f6f0c
-    keyform_attr->ulValueLen = sizeof(CK_ULONG);
1f6f0c
-    keyform_attr->pValue = (CK_BYTE *) keyform_attr + sizeof(CK_ATTRIBUTE);
1f6f0c
-    *(CK_ULONG *) keyform_attr->pValue = IBM_DILITHIUM_KEYFORM_ROUND2;
1f6f0c
-
1f6f0c
     rho_attr->type = CKA_IBM_DILITHIUM_RHO;
1f6f0c
     rho_attr->ulValueLen = 0;
1f6f0c
     rho_attr->pValue = NULL;
1f6f0c
@@ -4832,12 +4913,6 @@ CK_RV ibm_dilithium_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
         goto error;
1f6f0c
     }
1f6f0c
     type_attr = NULL;
1f6f0c
-    rc = template_update_attribute(tmpl, keyform_attr);
1f6f0c
-    if (rc != CKR_OK) {
1f6f0c
-        TRACE_ERROR("template_update_attribute failed\n");
1f6f0c
-        goto error;
1f6f0c
-    }
1f6f0c
-    keyform_attr = NULL;
1f6f0c
     rc = template_update_attribute(tmpl, rho_attr);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_ERROR("template_update_attribute failed\n");
1f6f0c
@@ -4906,38 +4981,59 @@ error:
1f6f0c
         free(t0_attr);
1f6f0c
     if (t1_attr)
1f6f0c
         free(t1_attr);
1f6f0c
-    if (keyform_attr)
1f6f0c
-        free(keyform_attr);
1f6f0c
     if (value_attr)
1f6f0c
         free(value_attr);
1f6f0c
 
1f6f0c
     return rc;
1f6f0c
 }
1f6f0c
 
1f6f0c
-// ibm_dilithium_publ_check_required_attributes()
1f6f0c
-//
1f6f0c
-CK_RV ibm_dilithium_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
+static CK_RV ibm_pqc_check_attributes(TEMPLATE *tmpl, CK_ULONG mode,
1f6f0c
+                                      CK_MECHANISM_TYPE mech,
1f6f0c
+                                      CK_ULONG *req_attrs,
1f6f0c
+                                      CK_ULONG num_req_attrs)
1f6f0c
 {
1f6f0c
+    CK_ATTRIBUTE_TYPE keyform_attr;
1f6f0c
+    CK_ATTRIBUTE_TYPE mode_attr;
1f6f0c
     CK_ATTRIBUTE *attr = NULL;
1f6f0c
-    static CK_ULONG req_attrs[] = {
1f6f0c
-        CKA_IBM_DILITHIUM_KEYFORM,
1f6f0c
-        CKA_IBM_DILITHIUM_RHO,
1f6f0c
-        CKA_IBM_DILITHIUM_T1,
1f6f0c
-    };
1f6f0c
+    CK_BBOOL keyform_present = FALSE;
1f6f0c
+    CK_BBOOL mode_present = FALSE;
1f6f0c
+    const struct pqc_oid *oids, *oid;
1f6f0c
     CK_ULONG i;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
+    if (ibm_pqc_keyform_mode_attrs_by_mech(mech, &keyform_attr,
1f6f0c
+                                           &mode_attr, &oids) != CKR_OK)
1f6f0c
+        return CKR_MECHANISM_INVALID;
1f6f0c
+
1f6f0c
+    if (template_attribute_find(tmpl, keyform_attr, &attr) &&
1f6f0c
+        attr->ulValueLen == sizeof(CK_ULONG) && attr->pValue != NULL) {
1f6f0c
+        oid = find_pqc_by_keyform(oids, *(CK_ULONG *)(attr->pValue));
1f6f0c
+        if (oid == NULL) {
1f6f0c
+            TRACE_ERROR("%s, attribute KEYFORM has an unsupported value.\n",
1f6f0c
+                        ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
+            return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
+        }
1f6f0c
+        keyform_present = TRUE;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    if (template_attribute_find(tmpl, mode_attr, &attr) &&
1f6f0c
+        attr->ulValueLen > 0 && attr->pValue != NULL) {
1f6f0c
+        oid = find_pqc_by_oid(oids, attr->pValue, attr->ulValueLen);
1f6f0c
+        if (oid == NULL) {
1f6f0c
+            TRACE_ERROR("%s, attribute MODE has an unsupported value.\n",
1f6f0c
+                        ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
+            return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
+        }
1f6f0c
+        mode_present = TRUE;
1f6f0c
+    }
1f6f0c
+
1f6f0c
     switch (mode) {
1f6f0c
-    case MODE_KEYGEN:
1f6f0c
-    case MODE_UNWRAP:
1f6f0c
-        /* Attrs will be added during keygen/unwrap */
1f6f0c
-        break;
1f6f0c
     case MODE_CREATE:
1f6f0c
         /* Either CKA_VALUE or all other attrs must be present */
1f6f0c
         if (template_attribute_find(tmpl, CKA_VALUE, &attr) &&
1f6f0c
             attr->ulValueLen > 0 && attr->pValue != NULL)
1f6f0c
             break;
1f6f0c
-        for (i = 0; i < sizeof(req_attrs) / sizeof(req_attrs[0]); i++) {
1f6f0c
+        for (i = 0; i < num_req_attrs; i++) {
1f6f0c
             rc = template_attribute_get_non_empty(tmpl, req_attrs[i], &attr);
1f6f0c
             if (rc != CKR_OK) {
1f6f0c
                 if (rc != CKR_ATTRIBUTE_VALUE_INVALID)
1f6f0c
@@ -4946,27 +5042,58 @@ CK_RV ibm_dilithium_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode
1f6f0c
                 return rc;
1f6f0c
             }
1f6f0c
         }
1f6f0c
+        /* fallthrough */
1f6f0c
+    case MODE_KEYGEN:
1f6f0c
+        /* Either keyform or mode or none of it must be present */
1f6f0c
+        if (keyform_present && mode_present) {
1f6f0c
+            TRACE_ERROR("%s, only one of KEYFORM or MODE can be specified .\n",
1f6f0c
+                        ock_err(ERR_TEMPLATE_INCONSISTENT));
1f6f0c
+            return CKR_TEMPLATE_INCONSISTENT;
1f6f0c
+        }
1f6f0c
+        break;
1f6f0c
+    case MODE_UNWRAP:
1f6f0c
+        /* neither keyform or mode must be present */
1f6f0c
+        if (keyform_present || mode_present) {
1f6f0c
+            TRACE_ERROR("%s, none of KEYFORM or MODE can be specified .\n",
1f6f0c
+                        ock_err(ERR_TEMPLATE_INCONSISTENT));
1f6f0c
+            return CKR_TEMPLATE_INCONSISTENT;
1f6f0c
+        }
1f6f0c
         break;
1f6f0c
     case MODE_COPY:
1f6f0c
-        /* CKA_VALUE and all other attrs must be present */
1f6f0c
-        if (!template_attribute_find(tmpl, CKA_VALUE, &attr) &&
1f6f0c
-            attr->ulValueLen > 0 && attr->pValue != NULL) {
1f6f0c
-            TRACE_ERROR("%s, attribute CKA_VALUE missing.\n",
1f6f0c
+        /* All attributes must be present */
1f6f0c
+        if (!keyform_present || !mode_present) {
1f6f0c
+            TRACE_ERROR("%s, KEYFORM or MODE must be specified .\n",
1f6f0c
                         ock_err(ERR_TEMPLATE_INCOMPLETE));
1f6f0c
             return CKR_TEMPLATE_INCOMPLETE;
1f6f0c
         }
1f6f0c
-        for (i = 0; i < sizeof(req_attrs) / sizeof(req_attrs[0]); i++) {
1f6f0c
-            rc = template_attribute_get_non_empty(tmpl, req_attrs[i], &attr);
1f6f0c
-            if (rc != CKR_OK) {
1f6f0c
-                if (rc != CKR_ATTRIBUTE_VALUE_INVALID)
1f6f0c
-                    TRACE_ERROR("%s, attribute %08lX missing.\n",
1f6f0c
-                               ock_err(ERR_TEMPLATE_INCOMPLETE), req_attrs[i]);
1f6f0c
-                return rc;
1f6f0c
+        for (i = 0; i < num_req_attrs; i++) {
1f6f0c
+            if (!template_attribute_find(tmpl, req_attrs[i], &attr)) {
1f6f0c
+                TRACE_ERROR("%s, attribute %08lX missing.\n",
1f6f0c
+                            ock_err(ERR_TEMPLATE_INCOMPLETE), req_attrs[i]);
1f6f0c
+                return CKR_TEMPLATE_INCOMPLETE;
1f6f0c
             }
1f6f0c
         }
1f6f0c
         break;
1f6f0c
     }
1f6f0c
 
1f6f0c
+    return CKR_OK;
1f6f0c
+}
1f6f0c
+
1f6f0c
+// ibm_dilithium_publ_check_required_attributes()
1f6f0c
+//
1f6f0c
+CK_RV ibm_dilithium_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
+{
1f6f0c
+    static CK_ULONG req_attrs[] = {
1f6f0c
+        CKA_IBM_DILITHIUM_RHO,
1f6f0c
+        CKA_IBM_DILITHIUM_T1,
1f6f0c
+    };
1f6f0c
+    CK_RV rc;
1f6f0c
+
1f6f0c
+    rc = ibm_pqc_check_attributes(tmpl, mode, CKM_IBM_DILITHIUM, req_attrs,
1f6f0c
+                                  sizeof(req_attrs) / sizeof(req_attrs[0]));
1f6f0c
+    if (rc != CKR_OK)
1f6f0c
+        return rc;
1f6f0c
+
1f6f0c
     /* All required attrs found, check them */
1f6f0c
     return publ_key_check_required_attributes(tmpl, mode);
1f6f0c
 }
1f6f0c
@@ -4975,9 +5102,7 @@ CK_RV ibm_dilithium_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode
1f6f0c
 //
1f6f0c
 CK_RV ibm_dilithium_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
1f6f0c
 {
1f6f0c
-    CK_ATTRIBUTE *attr = NULL;
1f6f0c
     static CK_ULONG req_attrs[] = {
1f6f0c
-        CKA_IBM_DILITHIUM_KEYFORM,
1f6f0c
         CKA_IBM_DILITHIUM_RHO,
1f6f0c
         CKA_IBM_DILITHIUM_SEED,
1f6f0c
         CKA_IBM_DILITHIUM_TR,
1f6f0c
@@ -4986,52 +5111,62 @@ CK_RV ibm_dilithium_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode
1f6f0c
         CKA_IBM_DILITHIUM_T0,
1f6f0c
         CKA_IBM_DILITHIUM_T1,
1f6f0c
     };
1f6f0c
-    CK_ULONG i;
1f6f0c
     CK_RV rc;
1f6f0c
 
1f6f0c
-    switch (mode) {
1f6f0c
-    case MODE_KEYGEN:
1f6f0c
-    case MODE_UNWRAP:
1f6f0c
-        /* Attrs will be added during keygen/unwrap */
1f6f0c
-        break;
1f6f0c
-    case MODE_CREATE:
1f6f0c
-        /* Either CKA_VALUE or all other attrs must be present */
1f6f0c
-        if (template_attribute_find(tmpl, CKA_VALUE, &attr) &&
1f6f0c
-            attr->ulValueLen > 0 && attr->pValue != NULL)
1f6f0c
-            break;
1f6f0c
-        for (i = 0; i < sizeof(req_attrs) / sizeof(req_attrs[0]); i++) {
1f6f0c
-            rc = template_attribute_get_non_empty(tmpl, req_attrs[i], &attr);
1f6f0c
-            if (rc != CKR_OK) {
1f6f0c
-                if (rc != CKR_ATTRIBUTE_VALUE_INVALID)
1f6f0c
-                    TRACE_ERROR("%s, attribute %08lX missing.\n",
1f6f0c
-                               ock_err(ERR_TEMPLATE_INCOMPLETE), req_attrs[i]);
1f6f0c
-                return rc;
1f6f0c
-            }
1f6f0c
-        }
1f6f0c
-        break;
1f6f0c
-    case MODE_COPY:
1f6f0c
-        /* CKA_VALUE and all other attrs must be present */
1f6f0c
-        if (!template_attribute_find(tmpl, CKA_VALUE, &attr) &&
1f6f0c
-            attr->ulValueLen > 0 && attr->pValue != NULL) {
1f6f0c
-            TRACE_ERROR("%s, attribute CKA_VALUE missing.\n",
1f6f0c
-                        ock_err(ERR_TEMPLATE_INCOMPLETE));
1f6f0c
-            return CKR_TEMPLATE_INCOMPLETE;
1f6f0c
+    rc = ibm_pqc_check_attributes(tmpl, mode, CKM_IBM_DILITHIUM, req_attrs,
1f6f0c
+                                  sizeof(req_attrs) / sizeof(req_attrs[0]));
1f6f0c
+    if (rc != CKR_OK)
1f6f0c
+        return rc;
1f6f0c
+
1f6f0c
+    /* All required attrs found, check them */
1f6f0c
+    return priv_key_check_required_attributes(tmpl, mode);
1f6f0c
+}
1f6f0c
+
1f6f0c
+static CK_RV ibm_pqc_validate_keyform_mode(CK_ATTRIBUTE *attr, CK_ULONG mode,
1f6f0c
+                                           CK_MECHANISM_TYPE mech)
1f6f0c
+{
1f6f0c
+    CK_ATTRIBUTE_TYPE keyform_attr;
1f6f0c
+    CK_ATTRIBUTE_TYPE mode_attr;
1f6f0c
+    const struct pqc_oid *oids, *oid;
1f6f0c
 
1f6f0c
+    if (ibm_pqc_keyform_mode_attrs_by_mech(mech, &keyform_attr,
1f6f0c
+                                           &mode_attr, &oids) != CKR_OK)
1f6f0c
+        return CKR_MECHANISM_INVALID;
1f6f0c
+
1f6f0c
+    if (attr->type == keyform_attr) {
1f6f0c
+        if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
1f6f0c
+            if (attr->ulValueLen != sizeof(CK_ULONG) || attr->pValue == NULL) {
1f6f0c
+                TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
+                return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
+            }
1f6f0c
+            oid = find_pqc_by_keyform(oids, *((CK_ULONG *)attr->pValue));
1f6f0c
+            if (oid == NULL) {
1f6f0c
+                TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
+                return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
+            }
1f6f0c
+            return CKR_OK;
1f6f0c
         }
1f6f0c
-        for (i = 0; i < sizeof(req_attrs) / sizeof(req_attrs[0]); i++) {
1f6f0c
-            rc = template_attribute_get_non_empty(tmpl, req_attrs[i], &attr);
1f6f0c
-            if (rc != CKR_OK) {
1f6f0c
-                if (rc != CKR_ATTRIBUTE_VALUE_INVALID)
1f6f0c
-                    TRACE_ERROR("%s, attribute %08lX missing.\n",
1f6f0c
-                               ock_err(ERR_TEMPLATE_INCOMPLETE), req_attrs[i]);
1f6f0c
-                return rc;
1f6f0c
+        TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
1f6f0c
+        return CKR_ATTRIBUTE_READ_ONLY;
1f6f0c
+    }
1f6f0c
+    if (attr->type == mode_attr) {
1f6f0c
+        if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
1f6f0c
+            if (attr->ulValueLen == 0 || attr->pValue == NULL) {
1f6f0c
+                TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
+                return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
+            }
1f6f0c
+            oid = find_pqc_by_oid(oids, attr->pValue, attr->ulValueLen);
1f6f0c
+            if (oid == NULL) {
1f6f0c
+                TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
+                return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
             }
1f6f0c
+            return CKR_OK;
1f6f0c
         }
1f6f0c
-        break;
1f6f0c
+        TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
1f6f0c
+        return CKR_ATTRIBUTE_READ_ONLY;
1f6f0c
     }
1f6f0c
 
1f6f0c
-    /* All required attrs found, check them */
1f6f0c
-    return priv_key_check_required_attributes(tmpl, mode);
1f6f0c
+    return CKR_OK;
1f6f0c
 }
1f6f0c
 
1f6f0c
 // ibm_dilithium_publ_validate_attribute()
1f6f0c
@@ -5040,7 +5175,15 @@ CK_RV ibm_dilithium_publ_validate_attribute(STDLL_TokData_t *tokdata,
1f6f0c
                                             TEMPLATE *tmpl, CK_ATTRIBUTE *attr,
1f6f0c
                                             CK_ULONG mode)
1f6f0c
 {
1f6f0c
+    CK_RV rc;
1f6f0c
+
1f6f0c
     switch (attr->type) {
1f6f0c
+    case CKA_IBM_DILITHIUM_KEYFORM:
1f6f0c
+    case CKA_IBM_DILITHIUM_MODE:
1f6f0c
+        rc = ibm_pqc_validate_keyform_mode(attr, mode, CKM_IBM_DILITHIUM);
1f6f0c
+        if (rc != CKR_OK)
1f6f0c
+            return rc;
1f6f0c
+        return CKR_OK;
1f6f0c
     case CKA_IBM_DILITHIUM_RHO:
1f6f0c
     case CKA_IBM_DILITHIUM_T1:
1f6f0c
     case CKA_VALUE:
1f6f0c
@@ -5048,22 +5191,6 @@ CK_RV ibm_dilithium_publ_validate_attribute(STDLL_TokData_t *tokdata,
1f6f0c
             return CKR_OK;
1f6f0c
         TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
1f6f0c
         return CKR_ATTRIBUTE_READ_ONLY;
1f6f0c
-    case CKA_IBM_DILITHIUM_KEYFORM:
1f6f0c
-        if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
1f6f0c
-            if (attr->ulValueLen != sizeof(CK_ULONG) || attr->pValue == NULL) {
1f6f0c
-                TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
-                return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
-            }
1f6f0c
-            switch (*((CK_ULONG *)attr->pValue)) {
1f6f0c
-            case IBM_DILITHIUM_KEYFORM_ROUND2:
1f6f0c
-                return CKR_OK;
1f6f0c
-            default:
1f6f0c
-                TRACE_ERROR("%s\n", ock_err(CKR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
-                return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
-            }
1f6f0c
-        }
1f6f0c
-        TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
1f6f0c
-        return CKR_ATTRIBUTE_READ_ONLY;
1f6f0c
     default:
1f6f0c
         return publ_key_validate_attribute(tokdata, tmpl, attr, mode);
1f6f0c
     }
1f6f0c
@@ -5075,7 +5202,15 @@ CK_RV ibm_dilithium_priv_validate_attribute(STDLL_TokData_t *tokdata,
1f6f0c
                                             TEMPLATE *tmpl, CK_ATTRIBUTE *attr,
1f6f0c
                                             CK_ULONG mode)
1f6f0c
 {
1f6f0c
+    CK_RV rc;
1f6f0c
+
1f6f0c
     switch (attr->type) {
1f6f0c
+    case CKA_IBM_DILITHIUM_KEYFORM:
1f6f0c
+    case CKA_IBM_DILITHIUM_MODE:
1f6f0c
+        rc = ibm_pqc_validate_keyform_mode(attr, mode, CKM_IBM_DILITHIUM);
1f6f0c
+        if (rc != CKR_OK)
1f6f0c
+            return rc;
1f6f0c
+        return CKR_OK;
1f6f0c
     case CKA_IBM_DILITHIUM_RHO:
1f6f0c
     case CKA_IBM_DILITHIUM_SEED:
1f6f0c
     case CKA_IBM_DILITHIUM_TR:
1f6f0c
@@ -5088,22 +5223,6 @@ CK_RV ibm_dilithium_priv_validate_attribute(STDLL_TokData_t *tokdata,
1f6f0c
             return CKR_OK;
1f6f0c
         TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
1f6f0c
         return CKR_ATTRIBUTE_READ_ONLY;
1f6f0c
-    case CKA_IBM_DILITHIUM_KEYFORM:
1f6f0c
-        if (mode == MODE_CREATE || mode == MODE_KEYGEN) {
1f6f0c
-            if (attr->ulValueLen != sizeof(CK_ULONG) || attr->pValue == NULL) {
1f6f0c
-                TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
-                return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
-            }
1f6f0c
-            switch (*((CK_ULONG *)attr->pValue)) {
1f6f0c
-            case IBM_DILITHIUM_KEYFORM_ROUND2:
1f6f0c
-                return CKR_OK;
1f6f0c
-            default:
1f6f0c
-                TRACE_ERROR("%s\n", ock_err(CKR_ATTRIBUTE_VALUE_INVALID));
1f6f0c
-                return CKR_ATTRIBUTE_VALUE_INVALID;
1f6f0c
-            }
1f6f0c
-        }
1f6f0c
-        TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
1f6f0c
-        return CKR_ATTRIBUTE_READ_ONLY;
1f6f0c
     default:
1f6f0c
         return priv_key_validate_attribute(tokdata, tmpl, attr, mode);
1f6f0c
     }
1f6f0c
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
1f6f0c
index 9221b8cd..c440cac5 100644
1f6f0c
--- a/usr/lib/ep11_stdll/ep11_specific.c
1f6f0c
+++ b/usr/lib/ep11_stdll/ep11_specific.c
1f6f0c
@@ -158,8 +158,8 @@ const char label[] = "ep11tok";
1f6f0c
 #define MAX_CSUMSIZE 64
1f6f0c
 #define EP11_CSUMSIZE 3
1f6f0c
 #define MAX_DIGEST_STATE_BYTES 1024
1f6f0c
-#define MAX_CRYPT_STATE_BYTES 8192
1f6f0c
-#define MAX_SIGN_STATE_BYTES 8192
1f6f0c
+#define MAX_CRYPT_STATE_BYTES 12288
1f6f0c
+#define MAX_SIGN_STATE_BYTES 12288
1f6f0c
 #define MAX_APQN 256
1f6f0c
 #define EP11_BLOB_WKID_OFFSET 32
1f6f0c
 
1f6f0c
@@ -1937,7 +1937,9 @@ static CK_BBOOL attr_applicable_for_ep11(STDLL_TokData_t * tokdata,
1f6f0c
     case CKK_IBM_PQC_DILITHIUM:
1f6f0c
         if (attr->type == CKA_ENCRYPT || attr->type == CKA_DECRYPT ||
1f6f0c
             attr->type == CKA_WRAP || attr->type == CKA_UNWRAP ||
1f6f0c
-            attr->type == CKA_DERIVE)
1f6f0c
+            attr->type == CKA_DERIVE || 
1f6f0c
+            attr->type == CKA_IBM_DILITHIUM_KEYFORM ||
1f6f0c
+            attr->type == CKA_IBM_DILITHIUM_MODE)
1f6f0c
             return CK_FALSE;
1f6f0c
         break;
1f6f0c
     default:
1f6f0c
@@ -3587,6 +3589,7 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
1f6f0c
     ep11_session_t *ep11_session = (ep11_session_t *) sess->private_data;
1f6f0c
     CK_ATTRIBUTE *value_attr = NULL;
1f6f0c
     CK_BBOOL data_alloced = TRUE;
1f6f0c
+    const struct pqc_oid *oid;
1f6f0c
 
1f6f0c
     memcpy(iv, "1234567812345678", AES_BLOCK_SIZE);
1f6f0c
 
1f6f0c
@@ -3611,7 +3614,8 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
1f6f0c
         /* Make an SPKI for the public IBM Dilithium key */
1f6f0c
 
1f6f0c
         /* A public IBM Dilithium key must either have a CKA_VALUE containing
1f6f0c
-         * the SPKI, or must have a keyform value and the individual attributes
1f6f0c
+         * the SPKI, or must have a keyform/mode value and the individual
1f6f0c
+         * attributes
1f6f0c
          */
1f6f0c
         if (template_attribute_find(dilithium_key_obj->template,
1f6f0c
                                     CKA_VALUE, &value_attr) &&
1f6f0c
@@ -3621,7 +3625,10 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
1f6f0c
             data_len = value_attr->ulValueLen;
1f6f0c
             data_alloced = FALSE;
1f6f0c
 
1f6f0c
-            /* Decode SPKI and add public key attributes */
1f6f0c
+            /*
1f6f0c
+             * Decode SPKI and add public key attributes. This also adds the
1f6f0c
+             * keyform and mode attributes to the template.
1f6f0c
+             */
1f6f0c
             rc = ibm_dilithium_priv_unwrap_get_data(dilithium_key_obj->template,
1f6f0c
                                                     data, data_len, FALSE);
1f6f0c
             if (rc != CKR_OK) {
1f6f0c
@@ -3641,6 +3648,21 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
1f6f0c
                            "data_len=0x%lx\n", __func__, class, rc, data_len);
1f6f0c
             }
1f6f0c
 
1f6f0c
+            /* Ensure both, keyform and mode attributes are added */
1f6f0c
+            oid = ibm_pqc_get_keyform_mode(dilithium_key_obj->template,
1f6f0c
+                                           CKM_IBM_DILITHIUM);
1f6f0c
+            if (oid == NULL) {
1f6f0c
+                rc = CKR_TEMPLATE_INCOMPLETE;
1f6f0c
+                goto done;
1f6f0c
+            }
1f6f0c
+
1f6f0c
+            rc = ibm_pqc_add_keyform_mode(dilithium_key_obj->template,
1f6f0c
+                                          oid, CKM_IBM_DILITHIUM);
1f6f0c
+            if (rc != CKR_OK) {
1f6f0c
+                TRACE_ERROR("ibm_pqc_add_keyform_mode failed\n");
1f6f0c
+                goto done;
1f6f0c
+            }
1f6f0c
+
1f6f0c
             /* Add SPKI as CKA_VALUE to public key (z/OS ICSF compatibility) */
1f6f0c
             rc = build_attribute(CKA_VALUE, data, data_len, &value_attr);
1f6f0c
             if (rc != CKR_OK) {
1f6f0c
@@ -3677,8 +3699,8 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
1f6f0c
         /* imported private IBM Dilithium key goes here */
1f6f0c
 
1f6f0c
         /* A public IBM Dilithium key must either have a CKA_VALUE containing
1f6f0c
-         * the PKCS#8 encoded private key, or must have a keyform value and the
1f6f0c
-         * individual attributes
1f6f0c
+         * the PKCS#8 encoded private key, or must have a keyform/mode value
1f6f0c
+         * and the individual attributes
1f6f0c
          */
1f6f0c
         if (template_attribute_find(dilithium_key_obj->template,
1f6f0c
                                     CKA_VALUE, &value_attr) &&
1f6f0c
@@ -3696,8 +3718,9 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
1f6f0c
                 goto done;
1f6f0c
             }
1f6f0c
         } else {
1f6f0c
-            /* extract the secret data to be wrapped
1f6f0c
-             * since this is AES_CBC_PAD, padding is done in mechanism.
1f6f0c
+            /* Extract the secret data to be wrapped since this is AES_CBC_PAD,
1f6f0c
+             * padding is done in mechanism. This also adds the keyform and mode
1f6f0c
+             * attributes to the template.
1f6f0c
              */
1f6f0c
             rc = ibm_dilithium_priv_wrap_get_data(dilithium_key_obj->template,
1f6f0c
                                                   FALSE, &data, &data_len);
1f6f0c
@@ -3705,6 +3728,21 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
1f6f0c
                 TRACE_DEVEL("%s Dilithium wrap get data failed\n", __func__);
1f6f0c
                 goto done;
1f6f0c
             }
1f6f0c
+
1f6f0c
+            /* Ensure both, keyform and mode attributes are added */
1f6f0c
+            oid = ibm_pqc_get_keyform_mode(dilithium_key_obj->template,
1f6f0c
+                                           CKM_IBM_DILITHIUM);
1f6f0c
+            if (oid == NULL) {
1f6f0c
+                rc = CKR_TEMPLATE_INCOMPLETE;
1f6f0c
+                goto done;
1f6f0c
+            }
1f6f0c
+
1f6f0c
+            rc = ibm_pqc_add_keyform_mode(dilithium_key_obj->template,
1f6f0c
+                                          oid, CKM_IBM_DILITHIUM);
1f6f0c
+            if (rc != CKR_OK) {
1f6f0c
+                TRACE_ERROR("ibm_pqc_add_keyform_mode failed\n");
1f6f0c
+                goto done;
1f6f0c
+            }
1f6f0c
         }
1f6f0c
 
1f6f0c
         /* encrypt */
1f6f0c
@@ -6456,8 +6494,7 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t *tokdata,
1f6f0c
     CK_ULONG new_publ_attrs_len = 0, new_priv_attrs_len = 0;
1f6f0c
     CK_ATTRIBUTE *new_publ_attrs2 = NULL, *new_priv_attrs2 = NULL;
1f6f0c
     CK_ULONG new_publ_attrs2_len = 0, new_priv_attrs2_len = 0;
1f6f0c
-    const CK_BYTE dilithium_oid[] = { 0x06, 0x0b, 0x2b, 0x06, 0x01, 0x04, 0x01,
1f6f0c
-                                      0x02, 0x82, 0x0b, 0x01, 0x06, 0x05 };
1f6f0c
+    const struct pqc_oid *dilithium_oid;
1f6f0c
 
1f6f0c
     if (pMechanism->mechanism != CKM_IBM_DILITHIUM) {
1f6f0c
         TRACE_ERROR("Invalid mechanism provided for %s\n ", __func__);
1f6f0c
@@ -6480,9 +6517,25 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t *tokdata,
1f6f0c
         goto error;
1f6f0c
     }
1f6f0c
 
1f6f0c
+    dilithium_oid = ibm_pqc_get_keyform_mode(publ_tmpl, CKM_IBM_DILITHIUM);
1f6f0c
+    if (dilithium_oid == NULL)
1f6f0c
+        dilithium_oid = ibm_pqc_get_keyform_mode(priv_tmpl, CKM_IBM_DILITHIUM);
1f6f0c
+    if (dilithium_oid == NULL)
1f6f0c
+        dilithium_oid = find_pqc_by_keyform(dilithium_oids,
1f6f0c
+                                            CK_IBM_DILITHIUM_KEYFORM_ROUND2_65);
1f6f0c
+    if (dilithium_oid == NULL) {
1f6f0c
+        TRACE_ERROR("%s Failed to determine Dilithium OID\n", __func__);
1f6f0c
+        rc = CKR_FUNCTION_FAILED;
1f6f0c
+        goto error;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    TRACE_INFO("%s Generate Dilithium key with keyform %lu\n", __func__,
1f6f0c
+               dilithium_oid->keyform);
1f6f0c
+
1f6f0c
     rc = add_to_attribute_array(&new_publ_attrs, &new_publ_attrs_len,
1f6f0c
-                                CKA_IBM_PQC_PARAMS, (CK_BYTE *)dilithium_oid,
1f6f0c
-                                sizeof(dilithium_oid));
1f6f0c
+                                CKA_IBM_PQC_PARAMS,
1f6f0c
+                                (CK_BYTE *)dilithium_oid->oid,
1f6f0c
+                                dilithium_oid->oid_len);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_ERROR("%s add_to_attribute_array failed with rc=0x%lx\n",
1f6f0c
                     __func__, rc);
1f6f0c
@@ -6490,8 +6543,9 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t *tokdata,
1f6f0c
     }
1f6f0c
 
1f6f0c
     rc = add_to_attribute_array(&new_priv_attrs, &new_priv_attrs_len,
1f6f0c
-                                CKA_IBM_PQC_PARAMS,(CK_BYTE *)dilithium_oid,
1f6f0c
-                                sizeof(dilithium_oid));
1f6f0c
+                                CKA_IBM_PQC_PARAMS,
1f6f0c
+                                (CK_BYTE *)dilithium_oid->oid,
1f6f0c
+                                dilithium_oid->oid_len);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
         TRACE_ERROR("%s add_to_attribute_array failed with rc=0x%lx\n",
1f6f0c
                     __func__, rc);
1f6f0c
-- 
1f6f0c
2.16.2.windows.1
1f6f0c