Blame SOURCES/0022-EP11-Query-supported-PQC-variants-and-restrict-usage.patch

447573
From cf68e9b9d342ced84e8a7fa88b0787a40a44cebb Mon Sep 17 00:00:00 2001
447573
From: Ingo Franzki <ifranzki@linux.ibm.com>
447573
Date: Thu, 17 Feb 2022 17:04:11 +0100
447573
Subject: [PATCH 22/34] EP11: Query supported PQC variants and restrict usage
447573
447573
Allow only those PQC variants that are supported by all
447573
configured APQNs. If a key is used with an unsupported strength,
447573
CKR_KEY_SIZE_RANGE is returned.
447573
447573
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
447573
---
447573
 usr/lib/ep11_stdll/ep11_specific.c | 187 +++++++++++++++++++++++++++++++++----
447573
 1 file changed, 168 insertions(+), 19 deletions(-)
447573
447573
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
447573
index c440cac5..479951cb 100644
447573
--- a/usr/lib/ep11_stdll/ep11_specific.c
447573
+++ b/usr/lib/ep11_stdll/ep11_specific.c
447573
@@ -540,6 +540,11 @@ static CK_RV handle_all_ep11_cards(ep11_target_t * ep11_targets,
447573
 #define PKEY_MODE_DEFAULT           1
447573
 #define PKEY_MODE_ENABLE4NONEXTR    2
447573
 
447573
+#define PQC_BYTE_NO(idx)      (((idx) - 1) / 8)
447573
+#define PQC_BIT_IN_BYTE(idx)  (((idx - 1)) % 8)
447573
+#define PQC_BIT_MASK(idx)     (0x80 >> PQC_BIT_IN_BYTE(idx))
447573
+#define PQC_BYTES             ((((XCP_PQC_MAX / 32) * 32) + 32) / 8)
447573
+
447573
 typedef struct {
447573
     volatile unsigned long ref_count;
447573
     target_t target;
447573
@@ -549,6 +554,7 @@ typedef struct {
447573
     size_t control_points_len;
447573
     size_t max_control_point_index;
447573
     CK_CHAR serialNumber[16];
447573
+    CK_BYTE pqc_strength[PQC_BYTES];
447573
 } ep11_target_info_t;
447573
 
447573
 typedef struct {
447573
@@ -660,6 +666,87 @@ static CK_RV check_expected_mkvp(STDLL_TokData_t *tokdata, CK_BYTE *blob,
447573
     return CKR_OK;
447573
 }
447573
 
447573
+static CK_BBOOL ep11_pqc_strength_supported(ep11_target_info_t *target_info,
447573
+                                            CK_MECHANISM_TYPE mech,
447573
+                                            const struct pqc_oid *oid)
447573
+{
447573
+    CK_ULONG strength;
447573
+
447573
+    switch (mech) {
447573
+    case CKM_IBM_DILITHIUM:
447573
+        switch (oid->keyform) {
447573
+        case CK_IBM_DILITHIUM_KEYFORM_ROUND2_65:
447573
+            strength = XCP_PQC_S_DILITHIUM_R2_65;
447573
+            break;
447573
+        case CK_IBM_DILITHIUM_KEYFORM_ROUND2_87:
447573
+            strength = XCP_PQC_S_DILITHIUM_R2_87;
447573
+            break;
447573
+        case CK_IBM_DILITHIUM_KEYFORM_ROUND3_44:
447573
+            strength = XCP_PQC_S_DILITHIUM_R3_44;
447573
+            break;
447573
+        case CK_IBM_DILITHIUM_KEYFORM_ROUND3_65:
447573
+            strength = XCP_PQC_S_DILITHIUM_R3_65;
447573
+            break;
447573
+        case CK_IBM_DILITHIUM_KEYFORM_ROUND3_87:
447573
+            strength = XCP_PQC_S_DILITHIUM_R3_87;
447573
+            break;
447573
+        default:
447573
+            TRACE_DEVEL("Dilithium keyform %lu not supported by EP11\n",
447573
+                        oid->keyform);
447573
+            return FALSE;
447573
+        }
447573
+        break;
447573
+    case CKM_IBM_KYBER:
447573
+        switch (oid->keyform) {
447573
+        case CK_IBM_KYBER_KEYFORM_ROUND2_768:
447573
+            strength = XCP_PQC_S_KYBER_R2_768;
447573
+            break;
447573
+        case CK_IBM_KYBER_KEYFORM_ROUND2_1024:
447573
+            strength = XCP_PQC_S_KYBER_R2_1024;
447573
+            break;
447573
+        default:
447573
+            TRACE_DEVEL("Kyber keyform %lu not supported by EP11\n",
447573
+                        oid->keyform);
447573
+            return FALSE;
447573
+        }
447573
+        break;
447573
+    default:
447573
+        return FALSE;
447573
+    }
447573
+
447573
+    if ((target_info->pqc_strength[PQC_BYTE_NO(strength)] &
447573
+                                        PQC_BIT_MASK(strength)) == 0) {
447573
+        TRACE_DEVEL("Keyform %lu not supported by configured APQNs\n",
447573
+                    oid->keyform);
447573
+        return FALSE;
447573
+    }
447573
+
447573
+    return TRUE;
447573
+}
447573
+
447573
+static CK_BBOOL ep11_pqc_obj_strength_supported(ep11_target_info_t *target_info,
447573
+                                                CK_MECHANISM_TYPE mech,
447573
+                                                OBJECT *key_obj)
447573
+{
447573
+    const struct pqc_oid *oid;
447573
+
447573
+    switch (mech) {
447573
+    case CKM_IBM_DILITHIUM:
447573
+    case CKM_IBM_KYBER:
447573
+        break;
447573
+    default:
447573
+        return TRUE;
447573
+    }
447573
+
447573
+    oid = ibm_pqc_get_keyform_mode(key_obj->template, mech);
447573
+    if (oid == NULL) {
447573
+        TRACE_DEVEL("No keyform/mode found in key object\n");
447573
+        return FALSE;
447573
+    }
447573
+
447573
+    return ep11_pqc_strength_supported(target_info, mech, oid);
447573
+}
447573
+
447573
 /*******************************************************************************
447573
  *
447573
  *                    Begin EP11 protected key option
447573
@@ -3747,10 +3834,15 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
447573
 
447573
         /* encrypt */
447573
         RETRY_START(rc, tokdata)
447573
-            rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
447573
-                                     ep11_data->raw2key_wrap_blob_l,
447573
-                                     &mech_w, data, data_len,
447573
-                                     cipher, &cipher_l, target_info->target);
447573
+            if (ep11_pqc_obj_strength_supported(target_info, CKM_IBM_DILITHIUM,
447573
+                                                dilithium_key_obj))
447573
+                rc = dll_m_EncryptSingle(ep11_data->raw2key_wrap_blob,
447573
+                                         ep11_data->raw2key_wrap_blob_l,
447573
+                                         &mech_w, data, data_len,
447573
+                                         cipher, &cipher_l,
447573
+                                         target_info->target);
447573
+            else
447573
+                rc = CKR_KEY_SIZE_RANGE;
447573
         RETRY_END(rc, tokdata, sess)
447573
 
447573
         TRACE_INFO("%s wrapping wrap key rc=0x%lx cipher_l=0x%lx\n",
447573
@@ -6583,12 +6675,16 @@ static CK_RV ibm_dilithium_generate_keypair(STDLL_TokData_t *tokdata,
447573
                       &ep11_pin_blob, &ep11_pin_blob_len);
447573
 
447573
     RETRY_START(rc, tokdata)
447573
-        rc = dll_m_GenerateKeyPair(pMechanism,
447573
-                                   new_publ_attrs2, new_publ_attrs2_len,
447573
-                                   new_priv_attrs2, new_priv_attrs2_len,
447573
-                                   ep11_pin_blob, ep11_pin_blob_len,
447573
-                                   privkey_blob, &privkey_blob_len, spki,
447573
-                                   &spki_len, target_info->target);
447573
+        if (ep11_pqc_strength_supported(target_info, pMechanism->mechanism,
447573
+                                        dilithium_oid))
447573
+            rc = dll_m_GenerateKeyPair(pMechanism,
447573
+                                       new_publ_attrs2, new_publ_attrs2_len,
447573
+                                       new_priv_attrs2, new_priv_attrs2_len,
447573
+                                       ep11_pin_blob, ep11_pin_blob_len,
447573
+                                       privkey_blob, &privkey_blob_len, spki,
447573
+                                       &spki_len, target_info->target);
447573
+        else
447573
+            rc = CKR_KEY_SIZE_RANGE;
447573
     RETRY_END(rc, tokdata, sess)
447573
     if (rc != CKR_OK) {
447573
         rc = ep11_error_to_pkcs11_error(rc, sess);
447573
@@ -7336,8 +7432,13 @@ CK_RV ep11tok_sign_init(STDLL_TokData_t * tokdata, SESSION * session,
447573
     }
447573
 
447573
     RETRY_START(rc, tokdata)
447573
-        rc = dll_m_SignInit(ep11_sign_state, &ep11_sign_state_l,
447573
-                            mech, keyblob, keyblobsize, target_info->target);
447573
+        if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
447573
+                                            key_obj))
447573
+            rc = dll_m_SignInit(ep11_sign_state, &ep11_sign_state_l,
447573
+                                mech, keyblob, keyblobsize,
447573
+                                target_info->target);
447573
+        else
447573
+            rc = CKR_KEY_SIZE_RANGE;
447573
     RETRY_END(rc, tokdata, session)
447573
 
447573
     if (rc != CKR_OK) {
447573
@@ -7570,8 +7671,12 @@ CK_RV ep11tok_sign_single(STDLL_TokData_t *tokdata, SESSION *session,
447573
     }
447573
 
447573
     RETRY_START(rc, tokdata)
447573
-    rc = dll_m_SignSingle(keyblob, keyblobsize, mech, in_data, in_data_len,
447573
-                          signature, sig_len, target_info->target);
447573
+        if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
447573
+                                            key_obj))
447573
+            rc = dll_m_SignSingle(keyblob, keyblobsize, mech, in_data, in_data_len,
447573
+                                  signature, sig_len, target_info->target);
447573
+        else
447573
+            rc = CKR_KEY_SIZE_RANGE;
447573
     RETRY_END(rc, tokdata, session)
447573
     if (rc != CKR_OK) {
447573
         rc = ep11_error_to_pkcs11_error(rc, session);
447573
@@ -7689,8 +7794,12 @@ CK_RV ep11tok_verify_init(STDLL_TokData_t * tokdata, SESSION * session,
447573
     }
447573
 
447573
     RETRY_START(rc, tokdata)
447573
-        rc = dll_m_VerifyInit(ep11_sign_state, &ep11_sign_state_l, mech,
447573
-                              spki, spki_len, target_info->target);
447573
+        if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
447573
+                                            key_obj))
447573
+            rc = dll_m_VerifyInit(ep11_sign_state, &ep11_sign_state_l, mech,
447573
+                                  spki, spki_len, target_info->target);
447573
+        else
447573
+            rc = CKR_KEY_SIZE_RANGE;
447573
     RETRY_END(rc, tokdata, session)
447573
 
447573
     if (rc != CKR_OK) {
447573
@@ -7929,8 +8038,12 @@ CK_RV ep11tok_verify_single(STDLL_TokData_t *tokdata, SESSION *session,
447573
     }
447573
 
447573
     RETRY_START(rc, tokdata)
447573
-    rc = dll_m_VerifySingle(spki, spki_len, mech, in_data, in_data_len,
447573
-                            signature, sig_len, target_info->target);
447573
+        if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
447573
+                                            key_obj))
447573
+            rc = dll_m_VerifySingle(spki, spki_len, mech, in_data, in_data_len,
447573
+                                    signature, sig_len, target_info->target);
447573
+        else
447573
+            rc = CKR_KEY_SIZE_RANGE;
447573
     RETRY_END(rc, tokdata, session)
447573
     if (rc != CKR_OK) {
447573
         rc = ep11_error_to_pkcs11_error(rc, session);
447573
@@ -11751,6 +11864,7 @@ typedef struct query_version
447573
     CK_CHAR serialNumber[16];
447573
     CK_BBOOL first;
447573
     CK_BBOOL error;
447573
+    CK_BYTE pqc_strength[PQC_BYTES];
447573
 } query_version_t;
447573
 
447573
 static CK_RV version_query_handler(uint_32 adapter, uint_32 domain,
447573
@@ -11759,9 +11873,11 @@ static CK_RV version_query_handler(uint_32 adapter, uint_32 domain,
447573
     query_version_t *qv = (query_version_t *)handler_data;
447573
     CK_IBM_XCP_INFO xcp_info;
447573
     CK_ULONG xcp_info_len = sizeof(xcp_info);
447573
+    CK_BYTE pqc_strength[PQC_BYTES] = { 0 };
447573
+    CK_ULONG pqc_strength_len = sizeof(pqc_strength);
447573
     CK_RV rc;
447573
     target_t target;
447573
-    CK_ULONG card_type;
447573
+    CK_ULONG card_type, i;
447573
     ep11_card_version_t *card_version;
447573
 
447573
     rc = get_ep11_target_for_apqn(adapter, domain, &target, 0);
447573
@@ -11877,6 +11993,30 @@ static CK_RV version_query_handler(uint_32 adapter, uint_32 domain,
447573
     if (qv->first)
447573
         memcpy(qv->serialNumber, xcp_info.serialNumber,
447573
                sizeof(qv->serialNumber));
447573
+
447573
+    /* Query for PQC strength support. If the PQC strength query is not
447573
+       available only Dilithium 6-5 round 2 is available. */
447573
+    rc = dll_m_get_xcp_info(&pqc_strength, &pqc_strength_len,
447573
+                            CK_IBM_XCPQ_PQC_STRENGTHS, 0, target);
447573
+    if (rc != CKR_OK) {
447573
+        TRACE_DEVEL("%s Failed to query PQC-strength from adapter %02X.%04X\n",
447573
+                    __func__, adapter, domain);
447573
+        /* Only R2_65 is available */
447573
+        pqc_strength[PQC_BYTE_NO(XCP_PQC_S_DILITHIUM_R2_65)] |=
447573
+                                    PQC_BIT_MASK(XCP_PQC_S_DILITHIUM_R2_65);
447573
+        rc = CKR_OK;
447573
+    }
447573
+
447573
+    TRACE_DEBUG("PQC-strength of %02X.%04X:\n", adapter, domain);
447573
+    TRACE_DEBUG_DUMP("", pqc_strength, sizeof(qv->pqc_strength));
447573
+
447573
+    if (qv->first) {
447573
+        memcpy(qv->pqc_strength, pqc_strength, sizeof(qv->pqc_strength));
447573
+    } else {
447573
+        for (i = 0; i < sizeof(qv->pqc_strength); i++)
447573
+            qv->pqc_strength[i] &= pqc_strength[i];
447573
+    }
447573
+
447573
     qv->first = FALSE;
447573
 
447573
 out:
447573
@@ -11934,6 +12074,7 @@ static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata,
447573
     ep11_private_data_t *ep11_data = tokdata->private_data;
447573
     ep11_card_version_t *card_version;
447573
     query_version_t qv;
447573
+    CK_ULONG i;
447573
     CK_RV rc;
447573
 
447573
     memset(&qv, 0, sizeof(qv));
447573
@@ -11991,6 +12132,14 @@ static CK_RV ep11tok_get_ep11_version(STDLL_TokData_t *tokdata,
447573
     TRACE_INFO("%s Used Firmware API: %lu\n", __func__,
447573
                target_info->used_firmware_API_version);
447573
 
447573
+    memcpy(target_info->pqc_strength, qv.pqc_strength, sizeof(qv.pqc_strength));
447573
+
447573
+    TRACE_INFO("Combined PQC-strength:\n");
447573
+    for (i = 1; i <= XCP_PQC_MAX; i++) {
447573
+        TRACE_INFO("  Strength %lu: %d\n", i,
447573
+                   (qv.pqc_strength[PQC_BYTE_NO(i)] & PQC_BIT_MASK(i)) != 0);
447573
+    }
447573
+
447573
     return CKR_OK;
447573
 }
447573
 
447573
-- 
447573
2.16.2.windows.1
447573