Blame SOURCES/0033-EP11-Supply-CKA_PUBLIC_KEY_INFO-with-CKM_IBM_BTC_DER.patch

1f6f0c
From df874a780108fa1390e4cb99144b9acb0667f76b Mon Sep 17 00:00:00 2001
1f6f0c
From: Ingo Franzki <ifranzki@linux.ibm.com>
1f6f0c
Date: Fri, 4 Nov 2022 11:33:50 +0100
1f6f0c
Subject: [PATCH 33/34] EP11: Supply CKA_PUBLIC_KEY_INFO with
1f6f0c
 CKM_IBM_BTC_DERIVE of private key
1f6f0c
1f6f0c
When deriving a private EC key with the CKM_IBM_BTC_DERIVE mechanism,
1f6f0c
also supply the SPKI in the CKA_PUBLIC_KEY_INFO attribute.
1f6f0c
1f6f0c
To get the SPKI, use m_GetAttributeValue() with CKA_PUBLIC_KEY_INFO.
1f6f0c
On newer EP11 host libraries this returns the SPKI of the corresponding
1f6f0c
public key of the private key blob. In case the EP11 host library fails
1f6f0c
to get the SPKI from the blob, ignore and do not supply an SPKI.
1f6f0c
1f6f0c
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
1f6f0c
---
1f6f0c
 usr/lib/ep11_stdll/ep11_specific.c | 266 +++++++++++++++++++++++--------------
1f6f0c
 1 file changed, 168 insertions(+), 98 deletions(-)
1f6f0c
1f6f0c
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
1f6f0c
index 9efce053..d4ece223 100644
1f6f0c
--- a/usr/lib/ep11_stdll/ep11_specific.c
1f6f0c
+++ b/usr/lib/ep11_stdll/ep11_specific.c
1f6f0c
@@ -5316,7 +5316,148 @@ static CK_RV ep11tok_kyber_mech_post_process(STDLL_TokData_t *tokdata,
1f6f0c
     return CKR_OK;
1f6f0c
 }
1f6f0c
 
1f6f0c
-CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
1f6f0c
+static CK_RV ep11tok_btc_mech_pre_process(STDLL_TokData_t *tokdata,
1f6f0c
+                                          OBJECT *key_obj,
1f6f0c
+                                          CK_ATTRIBUTE **new_attrs,
1f6f0c
+                                          CK_ULONG *new_attrs_len)
1f6f0c
+{
1f6f0c
+    CK_ATTRIBUTE *ec_params;
1f6f0c
+    CK_ULONG i, privlen;
1f6f0c
+    CK_RV rc;
1f6f0c
+
1f6f0c
+    UNUSED(tokdata);
1f6f0c
+
1f6f0c
+    /*
1f6f0c
+     * CKM_IBM_BTC_DERIVE requires CKA_VALUE_LEN to specify the byte length
1f6f0c
+     * of the to be derived EC key. CKA_VALUE_LEN is dependent on the
1f6f0c
+     * curve used.
1f6f0c
+     * CKA_VALUE_LEN can not be already in the user supplied template,
1f6f0c
+     * since this is not allowed by the key template check routines.
1f6f0c
+     */
1f6f0c
+    rc = template_attribute_get_non_empty(key_obj->template, CKA_EC_PARAMS,
1f6f0c
+                                          &ec_params);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_ERROR("CKA_EC_PARAMS is required in derive template\n");
1f6f0c
+        return rc;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    for (i = 0; i < NUMEC; i++) {
1f6f0c
+        if (der_ec_supported[i].data_size == ec_params->ulValueLen &&
1f6f0c
+            memcmp(ec_params->pValue, der_ec_supported[i].data,
1f6f0c
+                   ec_params->ulValueLen) == 0) {
1f6f0c
+            privlen = (der_ec_supported[i].len_bits + 7) / 8;
1f6f0c
+            rc = add_to_attribute_array(new_attrs, new_attrs_len,
1f6f0c
+                                        CKA_VALUE_LEN,
1f6f0c
+                                        (CK_BYTE_PTR)&privlen,
1f6f0c
+                                        sizeof(privlen));
1f6f0c
+            if (rc != CKR_OK) {
1f6f0c
+                TRACE_ERROR("Adding attribute failed type=CKA_VALUE_LEN "
1f6f0c
+                            "rc=0x%lx\n", rc);
1f6f0c
+                return rc;
1f6f0c
+            }
1f6f0c
+            break;
1f6f0c
+        }
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    return CKR_OK;
1f6f0c
+}
1f6f0c
+
1f6f0c
+static CK_RV ep11tok_btc_mech_post_process(STDLL_TokData_t *tokdata,
1f6f0c
+                                           SESSION *session, CK_MECHANISM *mech,
1f6f0c
+                                           CK_ULONG class, CK_ULONG ktype,
1f6f0c
+                                           OBJECT *key_obj,
1f6f0c
+                                           CK_BYTE *blob, CK_ULONG bloblen,
1f6f0c
+                                           CK_BYTE *csum, CK_ULONG cslen)
1f6f0c
+{
1f6f0c
+    CK_IBM_BTC_DERIVE_PARAMS *btc_params = NULL;
1f6f0c
+    CK_BYTE *spki = NULL;
1f6f0c
+    CK_ULONG spki_length = 0;
1f6f0c
+    CK_BYTE buf[MAX_BLOBSIZE];
1f6f0c
+    CK_ATTRIBUTE get_attr[1] = {{ CKA_PUBLIC_KEY_INFO, &buf, sizeof(buf) }};
1f6f0c
+    CK_ATTRIBUTE *spki_attr = NULL;
1f6f0c
+    CK_BBOOL allocated = FALSE;
1f6f0c
+    CK_RV rc = CKR_OK;
1f6f0c
+
1f6f0c
+    if (mech->ulParameterLen != sizeof(CK_IBM_BTC_DERIVE_PARAMS) ||
1f6f0c
+        mech->pParameter == NULL) {
1f6f0c
+        TRACE_ERROR("%s Param NULL or len for %s wrong: %lu\n",
1f6f0c
+                    __func__, ep11_get_ckm(tokdata, mech->mechanism),
1f6f0c
+                    mech->ulParameterLen);
1f6f0c
+        return CKR_MECHANISM_PARAM_INVALID;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    btc_params = (CK_IBM_BTC_DERIVE_PARAMS *)mech->pParameter;
1f6f0c
+
1f6f0c
+    if (btc_params != NULL && btc_params->pChainCode != NULL &&
1f6f0c
+        cslen >= CK_IBM_BTC_CHAINCODE_LENGTH) {
1f6f0c
+        memcpy(btc_params->pChainCode, csum, CK_IBM_BTC_CHAINCODE_LENGTH);
1f6f0c
+        btc_params->ulChainCodeLen = CK_IBM_BTC_CHAINCODE_LENGTH;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    switch (class) {
1f6f0c
+    case CKO_PUBLIC_KEY:
1f6f0c
+        /* Derived blob is an SPKI, extract public EC key attributes */
1f6f0c
+        rc = ecdsa_priv_unwrap_get_data(key_obj->template, blob, bloblen);
1f6f0c
+        if (rc != CKR_OK) {
1f6f0c
+            TRACE_ERROR("%s ecdsa_priv_unwrap_get_data failed with "
1f6f0c
+                        "rc=0x%lx\n", __func__, rc);
1f6f0c
+            return rc;
1f6f0c
+        }
1f6f0c
+
1f6f0c
+        /* Extract the SPKI and add CKA_PUBLIC_KEY_INFO to key */
1f6f0c
+        rc = publ_key_get_spki(key_obj->template, ktype, FALSE,
1f6f0c
+                               &spki, &spki_length);
1f6f0c
+        if (rc != CKR_OK) {
1f6f0c
+            TRACE_DEVEL("publ_key_get_spki failed\n");
1f6f0c
+            return rc;
1f6f0c
+        }
1f6f0c
+
1f6f0c
+        allocated = TRUE;
1f6f0c
+        break;
1f6f0c
+
1f6f0c
+    case CKO_PRIVATE_KEY:
1f6f0c
+        RETRY_START(rc, tokdata)
1f6f0c
+            rc = dll_m_GetAttributeValue(blob, bloblen, get_attr, 1,
1f6f0c
+                                         target_info->target);
1f6f0c
+        RETRY_END(rc, tokdata, session)
1f6f0c
+
1f6f0c
+        /* Only newer EP11 libs support this, ignore if error */
1f6f0c
+        if (rc != CKR_OK)
1f6f0c
+            return CKR_OK;
1f6f0c
+
1f6f0c
+        spki = get_attr[0].pValue;
1f6f0c
+        spki_length = get_attr[0].ulValueLen;
1f6f0c
+        break;
1f6f0c
+
1f6f0c
+    default:
1f6f0c
+        /* do nothing */
1f6f0c
+        return CKR_OK;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    rc = build_attribute(CKA_PUBLIC_KEY_INFO, spki, spki_length,
1f6f0c
+                         &spki_attr);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n",
1f6f0c
+                    __func__, rc);
1f6f0c
+        goto out;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+    rc = template_update_attribute(key_obj->template, spki_attr);
1f6f0c
+    if (rc != CKR_OK) {
1f6f0c
+        TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n",
1f6f0c
+                    __func__, rc);
1f6f0c
+        free(spki_attr);
1f6f0c
+        goto out;
1f6f0c
+    }
1f6f0c
+
1f6f0c
+out:
1f6f0c
+    if (allocated && spki != NULL)
1f6f0c
+        free(spki);
1f6f0c
+
1f6f0c
+    return rc;
1f6f0c
+}
1f6f0c
+
1f6f0c
+CK_RV ep11tok_derive_key(STDLL_TokData_t *tokdata, SESSION *session,
1f6f0c
                          CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE hBaseKey,
1f6f0c
                          CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs,
1f6f0c
                          CK_ULONG attrs_len)
1f6f0c
@@ -5345,17 +5486,12 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
1f6f0c
     CK_ULONG ecpoint_len, field_len, key_len = 0;
1f6f0c
     CK_ATTRIBUTE *new_attrs1 = NULL, *new_attrs2 = NULL;
1f6f0c
     CK_ULONG new_attrs1_len = 0, new_attrs2_len = 0;
1f6f0c
-    CK_ULONG privlen, i;
1f6f0c
+    CK_ULONG privlen;
1f6f0c
     int curve_type;
1f6f0c
     CK_BBOOL allocated = FALSE;
1f6f0c
     ep11_target_info_t* target_info;
1f6f0c
     CK_ULONG used_firmware_API_version;
1f6f0c
     CK_MECHANISM_PTR mech_orig = mech;
1f6f0c
-    CK_ATTRIBUTE *ec_params;
1f6f0c
-    CK_IBM_BTC_DERIVE_PARAMS *btc_params = NULL;
1f6f0c
-    CK_BYTE *spki = NULL;
1f6f0c
-    CK_ULONG spki_length = 0;
1f6f0c
-    CK_ATTRIBUTE *spki_attr = NULL;
1f6f0c
     struct EP11_KYBER_MECH mech_ep11;
1f6f0c
     OBJECT *kyber_secret_obj = NULL;
1f6f0c
 
1f6f0c
@@ -5476,18 +5612,6 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
1f6f0c
         }
1f6f0c
     }
1f6f0c
 
1f6f0c
-    if (mech->mechanism == CKM_IBM_BTC_DERIVE) {
1f6f0c
-        if (mech->ulParameterLen != sizeof(CK_IBM_BTC_DERIVE_PARAMS) ||
1f6f0c
-            mech->pParameter == NULL) {
1f6f0c
-            TRACE_ERROR("%s Param NULL or len for %s wrong: %lu\n",
1f6f0c
-                        __func__, ep11_get_ckm(tokdata, mech->mechanism),
1f6f0c
-                        mech->ulParameterLen);
1f6f0c
-            return CKR_MECHANISM_PARAM_INVALID;
1f6f0c
-        }
1f6f0c
-
1f6f0c
-        btc_params = (CK_IBM_BTC_DERIVE_PARAMS *)mech->pParameter;
1f6f0c
-    }
1f6f0c
-
1f6f0c
     rc = h_opaque_2_blob(tokdata, hBaseKey, &keyblob, &keyblobsize,
1f6f0c
                          &base_key_obj, READ_LOCK);
1f6f0c
     if (rc != CKR_OK) {
1f6f0c
@@ -5605,46 +5729,24 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
1f6f0c
         goto error;
1f6f0c
     }
1f6f0c
 
1f6f0c
-    if (mech->mechanism == CKM_IBM_BTC_DERIVE) {
1f6f0c
-        /*
1f6f0c
-         * CKM_IBM_BTC_DERIVE requires CKA_VALUE_LEN to specify the byte length
1f6f0c
-         * of the to be derived EC key. CKA_VALUE_LEN is dependent on the
1f6f0c
-         * curve used.
1f6f0c
-         * CKA_VALUE_LEN can not be already in the user supplied template,
1f6f0c
-         * since this is not allowed by the key template check routines.
1f6f0c
-         */
1f6f0c
-        rc = template_attribute_get_non_empty(key_obj->template, CKA_EC_PARAMS,
1f6f0c
-                                              &ec_params);
1f6f0c
-        if (rc != CKR_OK) {
1f6f0c
-            TRACE_ERROR("CKA_EC_PARAMS is required in derive template\n");
1f6f0c
+    switch (mech->mechanism) {
1f6f0c
+    case CKM_IBM_BTC_DERIVE:
1f6f0c
+        rc = ep11tok_btc_mech_pre_process(tokdata, key_obj, &new_attrs2,
1f6f0c
+                                          &new_attrs2_len);
1f6f0c
+        if (rc != CKR_OK)
1f6f0c
             goto error;
1f6f0c
-        }
1f6f0c
-
1f6f0c
-        for (i = 0; i < NUMEC; i++) {
1f6f0c
-            if (der_ec_supported[i].data_size == ec_params->ulValueLen &&
1f6f0c
-                memcmp(ec_params->pValue, der_ec_supported[i].data,
1f6f0c
-                       ec_params->ulValueLen) == 0) {
1f6f0c
-                privlen = (der_ec_supported[i].len_bits + 7) / 8;
1f6f0c
-                rc = add_to_attribute_array(&new_attrs2, &new_attrs2_len,
1f6f0c
-                                            CKA_VALUE_LEN,
1f6f0c
-                                            (CK_BYTE_PTR)&privlen,
1f6f0c
-                                            sizeof(privlen));
1f6f0c
-                if (rc != CKR_OK) {
1f6f0c
-                    TRACE_ERROR("Adding attribute failed type=CKA_VALUE_LEN "
1f6f0c
-                                "rc=0x%lx\n", rc);
1f6f0c
-                    goto error;
1f6f0c
-                }
1f6f0c
-                break;
1f6f0c
-            }
1f6f0c
-        }
1f6f0c
-    }
1f6f0c
+        break;
1f6f0c
 
1f6f0c
-    if (mech->mechanism == CKM_IBM_KYBER) {
1f6f0c
+    case CKM_IBM_KYBER:
1f6f0c
         rc = ep11tok_kyber_mech_pre_process(tokdata, mech, &mech_ep11,
1f6f0c
                                             &kyber_secret_obj);
1f6f0c
         if (rc != CKR_OK)
1f6f0c
             goto error;
1f6f0c
         mech = &mech_ep11.mech;
1f6f0c
+        break;
1f6f0c
+
1f6f0c
+    default:
1f6f0c
+        break;
1f6f0c
     }
1f6f0c
 
1f6f0c
     trace_attributes(__func__, "Derive:", new_attrs2, new_attrs2_len);
1f6f0c
@@ -5695,47 +5797,6 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
1f6f0c
     }
1f6f0c
     opaque_attr = NULL;
1f6f0c
 
1f6f0c
-    if (mech->mechanism == CKM_IBM_BTC_DERIVE &&
1f6f0c
-        btc_params != NULL && btc_params->pChainCode != NULL &&
1f6f0c
-        cslen >= CK_IBM_BTC_CHAINCODE_LENGTH) {
1f6f0c
-        memcpy(btc_params->pChainCode, csum, CK_IBM_BTC_CHAINCODE_LENGTH);
1f6f0c
-        btc_params->ulChainCodeLen = CK_IBM_BTC_CHAINCODE_LENGTH;
1f6f0c
-    }
1f6f0c
-
1f6f0c
-    if (mech->mechanism == CKM_IBM_BTC_DERIVE && class == CKO_PUBLIC_KEY) {
1f6f0c
-        /* Derived blob is an SPKI, extract public EC key attributes */
1f6f0c
-        rc = ecdsa_priv_unwrap_get_data(key_obj->template,
1f6f0c
-                                        newblob, newblobsize);
1f6f0c
-        if (rc != CKR_OK) {
1f6f0c
-            TRACE_ERROR("%s ecdsa_priv_unwrap_get_data failed with rc=0x%lx\n",
1f6f0c
-                        __func__, rc);
1f6f0c
-            goto error;
1f6f0c
-        }
1f6f0c
-
1f6f0c
-        /* Extract the SPKI and add CKA_PUBLIC_KEY_INFO to key */
1f6f0c
-        rc = publ_key_get_spki(key_obj->template, ktype, FALSE,
1f6f0c
-                               &spki, &spki_length);
1f6f0c
-        if (rc != CKR_OK) {
1f6f0c
-            TRACE_DEVEL("publ_key_get_spki failed\n");
1f6f0c
-            goto error;
1f6f0c
-        }
1f6f0c
-
1f6f0c
-        rc = build_attribute(CKA_PUBLIC_KEY_INFO, spki, spki_length, &spki_attr);
1f6f0c
-        if (rc != CKR_OK) {
1f6f0c
-            TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n",
1f6f0c
-                        __func__, rc);
1f6f0c
-            goto error;
1f6f0c
-        }
1f6f0c
-
1f6f0c
-        rc = template_update_attribute(key_obj->template, spki_attr);
1f6f0c
-        if (rc != CKR_OK) {
1f6f0c
-            TRACE_ERROR("%s template_update_attribute failed with "
1f6f0c
-                        "rc=0x%lx\n", __func__, rc);
1f6f0c
-            goto error;
1f6f0c
-        }
1f6f0c
-        spki_attr = NULL;
1f6f0c
-    }
1f6f0c
-
1f6f0c
     if (class == CKO_SECRET_KEY || class == CKO_PRIVATE_KEY) {
1f6f0c
         rc = update_ep11_attrs_from_blob(tokdata, session, key_obj->template);
1f6f0c
         if (rc != CKR_OK) {
1f6f0c
@@ -5745,10 +5806,23 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
1f6f0c
         }
1f6f0c
     }
1f6f0c
 
1f6f0c
-    if (mech->mechanism == CKM_IBM_KYBER) {
1f6f0c
+    switch (mech->mechanism) {
1f6f0c
+    case CKM_IBM_BTC_DERIVE:
1f6f0c
+        rc = ep11tok_btc_mech_post_process(tokdata, session, mech, class, ktype,
1f6f0c
+                                           key_obj, newblob, newblobsize,
1f6f0c
+                                           csum, cslen);
1f6f0c
+        if (rc != CKR_OK)
1f6f0c
+            goto error;
1f6f0c
+        break;
1f6f0c
+
1f6f0c
+    case CKM_IBM_KYBER:
1f6f0c
         rc = ep11tok_kyber_mech_post_process(tokdata, mech_orig, csum, cslen);
1f6f0c
         if (rc != CKR_OK)
1f6f0c
             goto error;
1f6f0c
+        break;
1f6f0c
+
1f6f0c
+    default:
1f6f0c
+        break;
1f6f0c
     }
1f6f0c
 
1f6f0c
     if (class == CKO_SECRET_KEY && cslen >= EP11_CSUMSIZE) {
1f6f0c
@@ -5792,10 +5866,6 @@ error:
1f6f0c
         free(opaque_attr);
1f6f0c
     if (chk_attr != NULL)
1f6f0c
         free(chk_attr);
1f6f0c
-    if (spki_attr != NULL)
1f6f0c
-        free(spki_attr);
1f6f0c
-    if (spki != NULL)
1f6f0c
-        free(spki);
1f6f0c
     if (new_attrs)
1f6f0c
         free_attribute_array(new_attrs, new_attrs_len);
1f6f0c
     if (new_attrs1)
1f6f0c
-- 
1f6f0c
2.16.2.windows.1
1f6f0c