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

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