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

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