Blob Blame History Raw
From b8bc3e183b43e9aeee8a8f23c8e48fffb6eedc35 Mon Sep 17 00:00:00 2001
From: Ingo Franzki <ifranzki@linux.ibm.com>
Date: Fri, 4 Nov 2022 10:51:08 +0100
Subject: [PATCH 08/34] EP11: Supply CKA_PUBLIC_KEY_INFO when importing private
 keys

When importing private keys, the SPKI of the corresponding public key
is returned in parameters csum/cslen of the m_UnwrapKey() EP11 host
library call. Supply this SPKI as CKA_PUBLIC_KEY_INFO to the object.

For public key import, the common code already builds the SPKI from
the clear public key attributes of the imported public key.

Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
---
 usr/lib/common/obj_mgr.c           |   5 ++
 usr/lib/ep11_stdll/ep11_specific.c | 113 +++++++++++++++++++++++++------------
 2 files changed, 83 insertions(+), 35 deletions(-)

diff --git a/usr/lib/common/obj_mgr.c b/usr/lib/common/obj_mgr.c
index 8e61cbd4..347ec3f3 100644
--- a/usr/lib/common/obj_mgr.c
+++ b/usr/lib/common/obj_mgr.c
@@ -123,6 +123,11 @@ CK_RV object_mgr_add(STDLL_TokData_t *tokdata,
     switch(class) {
     case CKO_PUBLIC_KEY:
     case CKO_PRIVATE_KEY:
+        /* Skip if there is already a non-empty CKA_PUBLIC_KEY_INFO */
+        if (template_attribute_get_non_empty(o->template, CKA_PUBLIC_KEY_INFO,
+                                             &spki_attr) == CKR_OK)
+            break;
+
         rc = template_attribute_get_ulong(o->template, CKA_KEY_TYPE, &keytype);
         if (rc != CKR_OK) {
             TRACE_ERROR("Could not find CKA_KEY_TYPE for the key object.\n");
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
index 886692c4..3b14a557 100644
--- a/usr/lib/ep11_stdll/ep11_specific.c
+++ b/usr/lib/ep11_stdll/ep11_specific.c
@@ -2745,9 +2745,10 @@ static int get_curve_type_from_template(TEMPLATE *tmpl)
  * SPKIs for public imported RSA keys.
  * Similar to rawkey_2_blob, but keys must follow a standard BER encoding.
  */
-static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
-                            OBJECT * rsa_key_obj,
-                            CK_BYTE * blob, size_t * blob_size)
+static CK_RV import_RSA_key(STDLL_TokData_t *tokdata, SESSION *sess,
+                            OBJECT *rsa_key_obj,
+                            CK_BYTE *blob, size_t *blob_size,
+                            CK_BYTE *spki, size_t *spki_size)
 {
     ep11_private_data_t *ep11_data = tokdata->private_data;
     CK_RV rc;
@@ -2759,8 +2760,6 @@ static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
     CK_ULONG attrs_len = 0;
     CK_ATTRIBUTE_PTR new_p_attrs = NULL;
     CK_ULONG new_attrs_len = 0;
-    CK_BYTE csum[MAX_BLOBSIZE];
-    CK_ULONG cslen = sizeof(csum);
     CK_OBJECT_CLASS class;
     CK_BYTE *data = NULL;
     CK_ULONG data_len;
@@ -2831,6 +2830,8 @@ static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
             goto import_RSA_key_end;
         }
 
+        *spki_size = 0; /* common code will extract SPKI from object */
+
     } else {
 
         /* imported private RSA key goes here */
@@ -2884,7 +2885,7 @@ static CK_RV import_RSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
                                  ep11_data->raw2key_wrap_blob_l, NULL, ~0,
                                  ep11_pin_blob, ep11_pin_blob_len, &mech_w,
                                  new_p_attrs, new_attrs_len, blob, blob_size,
-                                 csum, &cslen, target_info->target);
+                                 spki, spki_size, target_info->target);
         RETRY_END(rc, tokdata, sess)
 
         if (rc != CKR_OK) {
@@ -2921,9 +2922,10 @@ import_RSA_key_end:
  * SPKIs for public imported EC keys.
  * Similar to rawkey_2_blob, but keys must follow a standard BER encoding.
  */
-static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess,
-                           OBJECT * ec_key_obj,
-                           CK_BYTE * blob, size_t * blob_size)
+static CK_RV import_EC_key(STDLL_TokData_t *tokdata, SESSION *sess,
+                           OBJECT *ec_key_obj,
+                           CK_BYTE *blob, size_t *blob_size,
+                           CK_BYTE *spki, size_t *spki_size)
 {
     ep11_private_data_t *ep11_data = tokdata->private_data;
     CK_RV rc;
@@ -2935,8 +2937,6 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess,
     CK_ULONG attrs_len = 0;
     CK_ATTRIBUTE_PTR new_p_attrs = NULL;
     CK_ULONG new_attrs_len = 0;
-    CK_BYTE csum[MAX_BLOBSIZE];
-    CK_ULONG cslen = sizeof(csum);
     CK_OBJECT_CLASS class;
     CK_BYTE *data = NULL;
     CK_ULONG data_len;
@@ -3059,6 +3059,8 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess,
             goto import_EC_key_end;
         }
 
+        *spki_size = 0; /* common code will extract SPKI from object */
+
     } else {
 
         /* imported private EC key goes here */
@@ -3115,7 +3117,8 @@ static CK_RV import_EC_key(STDLL_TokData_t * tokdata, SESSION * sess,
                                  ep11_pin_blob,
                                  ep11_pin_blob_len, &mech_w,
                                  new_p_attrs, new_attrs_len, blob,
-                                 blob_size, csum, &cslen, target_info->target);
+                                 blob_size, spki, spki_size,
+                                 target_info->target);
         RETRY_END(rc, tokdata, sess)
 
         if (rc != CKR_OK) {
@@ -3149,9 +3152,10 @@ import_EC_key_end:
  * SPKIs for public imported DSA keys.
  * Similar to rawkey_2_blob, but keys must follow a standard BER encoding.
  */
-static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
-                            OBJECT * dsa_key_obj,
-                            CK_BYTE * blob, size_t * blob_size)
+static CK_RV import_DSA_key(STDLL_TokData_t *tokdata, SESSION *sess,
+                            OBJECT *dsa_key_obj,
+                            CK_BYTE *blob, size_t *blob_size,
+                            CK_BYTE *spki, size_t *spki_size)
 {
     ep11_private_data_t *ep11_data = tokdata->private_data;
     CK_RV rc;
@@ -3163,8 +3167,6 @@ static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
     CK_ULONG attrs_len = 0;
     CK_ATTRIBUTE_PTR new_p_attrs = NULL;
     CK_ULONG new_attrs_len = 0;
-    CK_BYTE csum[MAX_BLOBSIZE];
-    CK_ULONG cslen = sizeof(csum);
     CK_OBJECT_CLASS class;
     CK_BYTE *data = NULL;
     CK_ULONG data_len;
@@ -3251,6 +3253,8 @@ static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
             goto import_DSA_key_end;
         }
 
+        *spki_size = 0; /* common code will extract SPKI from object */
+
     } else {
 
         /* imported private DSA key goes here */
@@ -3307,7 +3311,8 @@ static CK_RV import_DSA_key(STDLL_TokData_t * tokdata, SESSION * sess,
                                  ep11_pin_blob,
                                  ep11_pin_blob_len, &mech_w,
                                  new_p_attrs, new_attrs_len, blob,
-                                 blob_size, csum, &cslen, target_info->target);
+                                 blob_size, spki, spki_size,
+                                 target_info->target);
         RETRY_END(rc, tokdata, sess)
 
         if (rc != CKR_OK) {
@@ -3339,9 +3344,10 @@ import_DSA_key_end:
  * SPKIs for public imported DH keys.
  * Similar to rawkey_2_blob, but keys must follow a standard BER encoding.
  */
-static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess,
-                           OBJECT * dh_key_obj,
-                           CK_BYTE * blob, size_t * blob_size)
+static CK_RV import_DH_key(STDLL_TokData_t *tokdata, SESSION *sess,
+                           OBJECT *dh_key_obj,
+                           CK_BYTE *blob, size_t *blob_size,
+                           CK_BYTE *spki, size_t *spki_size)
 {
     ep11_private_data_t *ep11_data = tokdata->private_data;
     CK_RV rc;
@@ -3353,8 +3359,6 @@ static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess,
     CK_ULONG attrs_len = 0;
     CK_ATTRIBUTE_PTR new_p_attrs = NULL;
     CK_ULONG new_attrs_len = 0;
-    CK_BYTE csum[MAX_BLOBSIZE];
-    CK_ULONG cslen = sizeof(csum);
     CK_OBJECT_CLASS class;
     CK_BYTE *data = NULL;
     CK_ULONG data_len;
@@ -3433,6 +3437,8 @@ static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess,
             goto import_DH_key_end;
         }
 
+        *spki_size = 0; /* common code will extract SPKI from object */
+
     } else {
         CK_ATTRIBUTE *value;
         CK_ATTRIBUTE *value_bits;
@@ -3500,7 +3506,8 @@ static CK_RV import_DH_key(STDLL_TokData_t * tokdata, SESSION * sess,
                                  ep11_pin_blob,
                                  ep11_pin_blob_len, &mech_w,
                                  new_p_attrs, new_attrs_len, blob,
-                                 blob_size, csum, &cslen, target_info->target);
+                                 blob_size, spki, spki_size,
+                                 target_info->target);
         RETRY_END(rc, tokdata, sess)
 
         if (rc != CKR_OK) {
@@ -3547,9 +3554,10 @@ import_DH_key_end:
  * SPKIs for public imported IBM Dilithium keys.
  * Similar to rawkey_2_blob, but keys must follow a standard BER encoding.
  */
-static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess,
-                           OBJECT * dilithium_key_obj,
-                           CK_BYTE * blob, size_t * blob_size)
+static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t *tokdata, SESSION *sess,
+                                      OBJECT *dilithium_key_obj,
+                                      CK_BYTE *blob, size_t *blob_size,
+                                      CK_BYTE *spki, size_t *spki_size)
 {
     ep11_private_data_t *ep11_data = tokdata->private_data;
     CK_RV rc;
@@ -3561,8 +3569,6 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess,
     CK_ULONG attrs_len = 0;
     CK_ATTRIBUTE_PTR new_p_attrs = NULL;
     CK_ULONG new_attrs_len = 0;
-    CK_BYTE csum[MAX_BLOBSIZE];
-    CK_ULONG cslen = sizeof(csum);
     CK_OBJECT_CLASS class;
     CK_BYTE *data = NULL;
     CK_ULONG data_len;
@@ -3652,6 +3658,8 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess,
             goto done;
         }
 
+        *spki_size = 0; /* common code will extract SPKI from object */
+
     } else {
 
         /* imported private IBM Dilithium key goes here */
@@ -3709,7 +3717,8 @@ static CK_RV import_IBM_Dilithium_key(STDLL_TokData_t * tokdata, SESSION * sess,
                                  ep11_pin_blob,
                                  ep11_pin_blob_len, &mech_w,
                                  new_p_attrs, new_attrs_len, blob,
-                                 blob_size, csum, &cslen, target_info->target);
+                                 blob_size, spki, spki_size,
+                                 target_info->target);
         RETRY_END(rc, tokdata, sess)
 
         if (rc != CKR_OK) {
@@ -3747,9 +3756,13 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
     CK_ATTRIBUTE *attr = NULL;
     CK_BYTE blob[MAX_BLOBSIZE];
     size_t blobsize = sizeof(blob);
+    CK_BYTE spki[MAX_BLOBSIZE];
+    size_t spkisize = sizeof(spki);
     CK_RV rc;
     CK_ULONG class;
     CK_BBOOL attrbound;
+    CK_BYTE *temp;
+    CK_ULONG temp_len;
 
     /* get key type */
     rc = template_attribute_get_ulong(obj->template, CKA_KEY_TYPE, &keytype);
@@ -3783,7 +3796,8 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
     /* only these keys can be imported */
     switch (keytype) {
     case CKK_RSA:
-        rc = import_RSA_key(tokdata, sess, obj, blob, &blobsize);
+        rc = import_RSA_key(tokdata, sess, obj, blob, &blobsize,
+                            spki, &spkisize);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s import RSA key rc=0x%lx blobsize=0x%zx\n",
                         __func__, rc, blobsize);
@@ -3793,7 +3807,8 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
                    __func__, rc, blobsize);
         break;
     case CKK_EC:
-        rc = import_EC_key(tokdata, sess, obj, blob, &blobsize);
+        rc = import_EC_key(tokdata, sess, obj, blob, &blobsize,
+                           spki, &spkisize);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s import EC key rc=0x%lx blobsize=0x%zx\n",
                         __func__, rc, blobsize);
@@ -3803,7 +3818,8 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
                    __func__, rc, blobsize);
         break;
     case CKK_DSA:
-        rc = import_DSA_key(tokdata, sess, obj, blob, &blobsize);
+        rc = import_DSA_key(tokdata, sess, obj, blob, &blobsize,
+                            spki, &spkisize);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s import DSA key rc=0x%lx blobsize=0x%zx\n",
                         __func__, rc, blobsize);
@@ -3813,7 +3829,8 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
                    __func__, rc, blobsize);
         break;
     case CKK_DH:
-        rc = import_DH_key(tokdata, sess, obj, blob, &blobsize);
+        rc = import_DH_key(tokdata, sess, obj, blob, &blobsize,
+                           spki, &spkisize);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s import DH key rc=0x%lx blobsize=0x%zx\n",
                         __func__, rc, blobsize);
@@ -3823,7 +3840,8 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
                    __func__, rc, blobsize);
         break;
     case CKK_IBM_PQC_DILITHIUM:
-        rc = import_IBM_Dilithium_key(tokdata, sess, obj, blob, &blobsize);
+        rc = import_IBM_Dilithium_key(tokdata, sess, obj, blob, &blobsize,
+                                      spki, &spkisize);
         if (rc != CKR_OK) {
             TRACE_ERROR("%s import IBM Dilithium key rc=0x%lx blobsize=0x%zx\n",
                         __func__, rc, blobsize);
@@ -3891,6 +3909,31 @@ CK_RV token_specific_object_add(STDLL_TokData_t * tokdata, SESSION * sess,
         return rc;
     }
 
+    if (spkisize > 0 && (class == CKO_PRIVATE_KEY || class == CKO_PUBLIC_KEY)) {
+        /* spki may be a MACed SPKI, get length of SPKI part only */
+        rc = ber_decode_SEQUENCE(spki, &temp, &temp_len, &spkisize);
+        if (rc != CKR_OK) {
+            TRACE_ERROR("%s ber_decode_SEQUENCE failed rc=0x%lx\n",
+                        __func__, rc);
+            return rc;
+        }
+
+        rc = build_attribute(CKA_PUBLIC_KEY_INFO, spki, spkisize, &attr);
+        if (rc != CKR_OK) {
+            TRACE_ERROR("%s build_attribute failed with rc=0x%lx\n", __func__,
+                        rc);
+            return rc;
+        }
+
+        rc = template_update_attribute(obj->template, attr);
+        if (rc != CKR_OK) {
+            TRACE_ERROR("%s template_update_attribute failed with rc=0x%lx\n",
+                        __func__, rc);
+            free(attr);
+            return rc;
+        }
+    }
+
     rc = update_ep11_attrs_from_blob(tokdata, sess, obj->template);
     if (rc != CKR_OK) {
         TRACE_ERROR("%s update_ep11_attrs_from_blob failed with rc=0x%lx\n",
-- 
2.16.2.windows.1