Blame SOURCES/0027-EP11-Add-support-for-encrypt-decrypt-and-KEM-operati.patch

397a93
From 51ed2d7171e5423cfec86c36ffa32e8e9e0de01c Mon Sep 17 00:00:00 2001
397a93
From: Ingo Franzki <ifranzki@linux.ibm.com>
397a93
Date: Tue, 1 Mar 2022 16:55:01 +0100
397a93
Subject: [PATCH 27/34] EP11: Add support for encrypt/decrypt and KEM
397a93
 operations with Kyber
397a93
397a93
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
397a93
---
397a93
 usr/lib/ep11_stdll/ep11_specific.c | 174 ++++++++++++++++++++++++++++++++++---
397a93
 usr/lib/ep11_stdll/new_host.c      |  24 +++--
397a93
 2 files changed, 180 insertions(+), 18 deletions(-)
397a93
397a93
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
397a93
index bc17b07a..9efce053 100644
397a93
--- a/usr/lib/ep11_stdll/ep11_specific.c
397a93
+++ b/usr/lib/ep11_stdll/ep11_specific.c
397a93
@@ -5196,6 +5196,126 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata,
397a93
     return rc;
397a93
 }
397a93
 
397a93
+struct EP11_KYBER_MECH {
397a93
+    CK_MECHANISM mech;
397a93
+    struct XCP_KYBER_KEM_PARAMS params;
397a93
+};
397a93
+
397a93
+static CK_RV ep11tok_kyber_mech_pre_process(STDLL_TokData_t *tokdata,
397a93
+                                            CK_MECHANISM *mech,
397a93
+                                            struct EP11_KYBER_MECH *mech_ep11,
397a93
+                                            OBJECT **secret_key_obj)
397a93
+{
397a93
+    CK_IBM_KYBER_PARAMS *kyber_params;
397a93
+    CK_RV rc;
397a93
+
397a93
+    kyber_params = mech->pParameter;
397a93
+    if (mech->ulParameterLen != sizeof(CK_IBM_KYBER_PARAMS)) {
397a93
+        TRACE_ERROR("Mechanism parameter length not as expected\n");
397a93
+        return CKR_MECHANISM_PARAM_INVALID;
397a93
+    }
397a93
+
397a93
+    if (kyber_params->ulVersion != CK_IBM_KYBER_KEM_VERSION) {
397a93
+        TRACE_ERROR("Unsupported version in Kyber mechanism param\n");
397a93
+        return CKR_MECHANISM_PARAM_INVALID;
397a93
+    }
397a93
+
397a93
+    mech_ep11->mech.mechanism = mech->mechanism;
397a93
+    mech_ep11->mech.pParameter = &mech_ep11->params;
397a93
+    mech_ep11->mech.ulParameterLen = sizeof(mech_ep11->params);
397a93
+
397a93
+    memset(&mech_ep11->params, 0, sizeof(mech_ep11->params));
397a93
+    mech_ep11->params.version = XCP_KYBER_KEM_VERSION;
397a93
+    mech_ep11->params.mode = kyber_params->mode;
397a93
+    mech_ep11->params.kdf = kyber_params->kdf;
397a93
+    mech_ep11->params.prepend = kyber_params->bPrepend;
397a93
+    mech_ep11->params.pSharedData = kyber_params->pSharedData;
397a93
+    mech_ep11->params.ulSharedDataLen = kyber_params->ulSharedDataLen;
397a93
+
397a93
+    switch (kyber_params->mode) {
397a93
+    case CK_IBM_KYBER_KEM_ENCAPSULATE:
397a93
+        if (kyber_params->ulCipherLen > 0 && kyber_params->pCipher == NULL) {
397a93
+            TRACE_ERROR("Unsupported cipher buffer in Kyber mechnism param "
397a93
+                        "cannot be NULL\n");
397a93
+            return CKR_MECHANISM_PARAM_INVALID;
397a93
+        }
397a93
+
397a93
+        mech_ep11->params.pCipher = NULL;
397a93
+        mech_ep11->params.ulCipherLen = 0;
397a93
+        /* Cipher is returned in 2nd output param of m_DeriveKey */
397a93
+        break;
397a93
+
397a93
+    case CK_IBM_KEM_DECAPSULATE:
397a93
+        mech_ep11->params.pCipher = kyber_params->pCipher;
397a93
+        mech_ep11->params.ulCipherLen = kyber_params->ulCipherLen;
397a93
+        break;
397a93
+
397a93
+    default:
397a93
+        TRACE_ERROR("Unsupported mode in Kyber mechanism param\n");
397a93
+        return CKR_MECHANISM_PARAM_INVALID;
397a93
+    }
397a93
+
397a93
+    if (kyber_params->bPrepend) {
397a93
+        rc = h_opaque_2_blob(tokdata, kyber_params->hSecret,
397a93
+                             &mech_ep11->params.pBlob,
397a93
+                             &mech_ep11->params.ulBlobLen,
397a93
+                             secret_key_obj, READ_LOCK);
397a93
+         if (rc != CKR_OK) {
397a93
+             TRACE_ERROR("%s failed hSecret=0x%lx\n", __func__,
397a93
+                        kyber_params->hSecret);
397a93
+             return rc;
397a93
+         }
397a93
+    }
397a93
+
397a93
+    return CKR_OK;
397a93
+}
397a93
+
397a93
+static CK_RV ep11tok_kyber_mech_post_process(STDLL_TokData_t *tokdata,
397a93
+                                             CK_MECHANISM *mech,
397a93
+                                             CK_BYTE *csum, CK_ULONG cslen)
397a93
+{
397a93
+    CK_IBM_KYBER_PARAMS *kyber_params;
397a93
+    CK_ULONG cipher_len;
397a93
+
397a93
+    UNUSED(tokdata);
397a93
+
397a93
+    kyber_params = mech->pParameter;
397a93
+    if (mech->ulParameterLen != sizeof(CK_IBM_KYBER_PARAMS)) {
397a93
+        TRACE_ERROR("Mechanism parameter length not as expected\n");
397a93
+        return CKR_MECHANISM_PARAM_INVALID;
397a93
+    }
397a93
+
397a93
+    if (kyber_params->mode != CK_IBM_KYBER_KEM_ENCAPSULATE)
397a93
+        return CKR_OK;
397a93
+
397a93
+    /*
397a93
+     * For encapsulate:
397a93
+     * Generated cipher is returned in csum prepended with the checksum of
397a93
+     * the generated symmetric key and its bit count (in total 7 bytes).
397a93
+     */
397a93
+    if (cslen < EP11_CSUMSIZE + 4) {
397a93
+        TRACE_ERROR("%s returned cipher size is invalid: %lu\n",
397a93
+                    __func__, cslen);
397a93
+        return CKR_FUNCTION_FAILED;
397a93
+    }
397a93
+
397a93
+    cipher_len = cslen - (EP11_CSUMSIZE + 4);
397a93
+
397a93
+    if (kyber_params->ulCipherLen < cipher_len) {
397a93
+        TRACE_ERROR("%s Cipher buffer in kyber mechanism param too small, required: %lu\n",
397a93
+                    __func__, cipher_len);
397a93
+        kyber_params->ulCipherLen = cipher_len;
397a93
+        OPENSSL_cleanse(&csum[EP11_CSUMSIZE + 4], cipher_len);
397a93
+        return CKR_BUFFER_TOO_SMALL;
397a93
+    }
397a93
+
397a93
+    memcpy(kyber_params->pCipher, &csum[EP11_CSUMSIZE + 4], cipher_len);
397a93
+    kyber_params->ulCipherLen = cipher_len;
397a93
+
397a93
+    OPENSSL_cleanse(&csum[EP11_CSUMSIZE + 4], cipher_len);
397a93
+    return CKR_OK;
397a93
+}
397a93
+
397a93
 CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
397a93
                          CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE hBaseKey,
397a93
                          CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs,
397a93
@@ -5236,6 +5356,8 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
397a93
     CK_BYTE *spki = NULL;
397a93
     CK_ULONG spki_length = 0;
397a93
     CK_ATTRIBUTE *spki_attr = NULL;
397a93
+    struct EP11_KYBER_MECH mech_ep11;
397a93
+    OBJECT *kyber_secret_obj = NULL;
397a93
 
397a93
     memset(newblob, 0, sizeof(newblob));
397a93
 
397a93
@@ -5517,16 +5639,29 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
397a93
         }
397a93
     }
397a93
 
397a93
+    if (mech->mechanism == CKM_IBM_KYBER) {
397a93
+        rc = ep11tok_kyber_mech_pre_process(tokdata, mech, &mech_ep11,
397a93
+                                            &kyber_secret_obj);
397a93
+        if (rc != CKR_OK)
397a93
+            goto error;
397a93
+        mech = &mech_ep11.mech;
397a93
+    }
397a93
+
397a93
     trace_attributes(__func__, "Derive:", new_attrs2, new_attrs2_len);
397a93
 
397a93
     ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len),
397a93
                       &ep11_pin_blob, &ep11_pin_blob_len);
397a93
 
397a93
     RETRY_START(rc, tokdata)
397a93
-        rc =
397a93
-        dll_m_DeriveKey(mech, new_attrs2, new_attrs2_len, keyblob, keyblobsize,
397a93
-                        NULL, 0, ep11_pin_blob, ep11_pin_blob_len, newblob,
397a93
-                        &newblobsize, csum, &cslen, target_info->target);
397a93
+        if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
397a93
+                                            base_key_obj))
397a93
+            rc = dll_m_DeriveKey(mech, new_attrs2, new_attrs2_len,
397a93
+                                 keyblob, keyblobsize, NULL, 0,
397a93
+                                 ep11_pin_blob, ep11_pin_blob_len, newblob,
397a93
+                                 &newblobsize, csum, &cslen,
397a93
+                                 target_info->target);
397a93
+        else
397a93
+            rc = CKR_KEY_SIZE_RANGE;
397a93
     RETRY_END(rc, tokdata, session)
397a93
 
397a93
     if (rc != CKR_OK) {
397a93
@@ -5610,6 +5745,12 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
397a93
         }
397a93
     }
397a93
 
397a93
+    if (mech->mechanism == CKM_IBM_KYBER) {
397a93
+        rc = ep11tok_kyber_mech_post_process(tokdata, mech_orig, csum, cslen);
397a93
+        if (rc != CKR_OK)
397a93
+            goto error;
397a93
+    }
397a93
+
397a93
     if (class == CKO_SECRET_KEY && cslen >= EP11_CSUMSIZE) {
397a93
         /* First 3 bytes of csum is the check value */
397a93
         rc = build_attribute(CKA_CHECK_VALUE, csum, EP11_CSUMSIZE, &chk_attr);
397a93
@@ -5666,6 +5807,8 @@ error:
397a93
 
397a93
     object_put(tokdata, base_key_obj, TRUE);
397a93
     base_key_obj = NULL;
397a93
+    object_put(tokdata, kyber_secret_obj, TRUE);
397a93
+    kyber_secret_obj = NULL;
397a93
 
397a93
     return rc;
397a93
 }
397a93
@@ -7399,6 +7542,7 @@ CK_BOOL ep11tok_mech_single_only(CK_MECHANISM *mech)
397a93
 {
397a93
     switch (mech->mechanism) {
397a93
     case CKM_IBM_ECDSA_OTHER:
397a93
+    case CKM_IBM_KYBER:
397a93
         return CK_TRUE;
397a93
     default:
397a93
         return CK_FALSE;
397a93
@@ -8301,9 +8445,14 @@ CK_RV ep11tok_decrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
397a93
     }
397a93
 
397a93
     RETRY_START(rc, tokdata)
397a93
-    rc = dll_m_DecryptSingle(keyblob, keyblobsize, mech, input_data,
397a93
-                             input_data_len, output_data, p_output_data_len,
397a93
-                             target_info->target);
397a93
+        if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
397a93
+                                            key_obj))
397a93
+            rc = dll_m_DecryptSingle(keyblob, keyblobsize, mech, input_data,
397a93
+                                     input_data_len, output_data,
397a93
+                                     p_output_data_len,
397a93
+                                     target_info->target);
397a93
+        else
397a93
+            rc = CKR_KEY_SIZE_RANGE;
397a93
     RETRY_END(rc, tokdata, session)
397a93
     if (rc != CKR_OK) {
397a93
         rc = ep11_error_to_pkcs11_error(rc, session);
397a93
@@ -8511,9 +8660,14 @@ CK_RV ep11tok_encrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
397a93
     }
397a93
 
397a93
     RETRY_START(rc, tokdata)
397a93
-    rc = dll_m_EncryptSingle(keyblob, keyblobsize, mech, input_data,
397a93
-                             input_data_len, output_data, p_output_data_len,
397a93
-                             target_info->target);
397a93
+        if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
397a93
+                                            key_obj))
397a93
+            rc = dll_m_EncryptSingle(keyblob, keyblobsize, mech, input_data,
397a93
+                                     input_data_len, output_data,
397a93
+                                     p_output_data_len,
397a93
+                                     target_info->target);
397a93
+        else
397a93
+            rc = CKR_KEY_SIZE_RANGE;
397a93
     RETRY_END(rc, tokdata, session)
397a93
     if (rc != CKR_OK) {
397a93
         rc = ep11_error_to_pkcs11_error(rc, session);
397a93
diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
397a93
index dccdfe96..60027c85 100644
397a93
--- a/usr/lib/ep11_stdll/new_host.c
397a93
+++ b/usr/lib/ep11_stdll/new_host.c
397a93
@@ -2061,7 +2061,8 @@ CK_RV SC_EncryptInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
397a93
     sess->encr_ctx.multi_init = FALSE;
397a93
     sess->encr_ctx.multi = FALSE;
397a93
 
397a93
-    if (ep11tok_optimize_single_ops(tokdata) &&
397a93
+    if ((ep11tok_optimize_single_ops(tokdata) ||
397a93
+         ep11tok_mech_single_only(pMechanism)) &&
397a93
         !ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism)) {
397a93
         /* In case of a single part encrypt operation we don't need the
397a93
          * EncryptInit, instead we can use the EncryptSingle which is much
397a93
@@ -2159,7 +2160,8 @@ CK_RV SC_Encrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
397a93
         goto done;
397a93
     }
397a93
 
397a93
-    if (ep11tok_optimize_single_ops(tokdata) &&
397a93
+    if ((ep11tok_optimize_single_ops(tokdata) ||
397a93
+         ep11tok_mech_single_only(&sess->encr_ctx.mech)) &&
397a93
         !ep11tok_pkey_usage_ok(tokdata, sess, sess->encr_ctx.key, &sess->encr_ctx.mech)) {
397a93
         rc = ep11tok_encrypt_single(tokdata, sess, &sess->encr_ctx.mech,
397a93
                                     length_only, sess->encr_ctx.key,
397a93
@@ -2217,7 +2219,8 @@ CK_RV SC_EncryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
397a93
         goto done;
397a93
     }
397a93
 
397a93
-    if (sess->encr_ctx.active == FALSE) {
397a93
+    if (sess->encr_ctx.active == FALSE ||
397a93
+        ep11tok_mech_single_only(&sess->encr_ctx.mech)) {
397a93
         TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
397a93
         rc = CKR_OPERATION_NOT_INITIALIZED;
397a93
         goto done;
397a93
@@ -2293,7 +2296,8 @@ CK_RV SC_EncryptFinal(STDLL_TokData_t * tokdata, ST_SESSION_HANDLE * sSession,
397a93
         goto done;
397a93
     }
397a93
 
397a93
-    if (sess->encr_ctx.active == FALSE) {
397a93
+    if (sess->encr_ctx.active == FALSE ||
397a93
+        ep11tok_mech_single_only(&sess->encr_ctx.mech)) {
397a93
         TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
397a93
         rc = CKR_OPERATION_NOT_INITIALIZED;
397a93
         goto done;
397a93
@@ -2385,7 +2389,8 @@ CK_RV SC_DecryptInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
397a93
     sess->decr_ctx.multi_init = FALSE;
397a93
     sess->decr_ctx.multi = FALSE;
397a93
 
397a93
-    if (ep11tok_optimize_single_ops(tokdata) &&
397a93
+    if ((ep11tok_optimize_single_ops(tokdata) ||
397a93
+         ep11tok_mech_single_only(pMechanism)) &&
397a93
         !ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism)) {
397a93
         /* In case of a single part decrypt operation we don't need the
397a93
          * DecryptInit, instead we can use the EncryptSingle which is much
397a93
@@ -2483,7 +2488,8 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
397a93
         goto done;
397a93
     }
397a93
 
397a93
-    if (ep11tok_optimize_single_ops(tokdata) &&
397a93
+    if ((ep11tok_optimize_single_ops(tokdata) ||
397a93
+         ep11tok_mech_single_only(&sess->decr_ctx.mech)) &&
397a93
         !ep11tok_pkey_usage_ok(tokdata, sess, sess->decr_ctx.key, &sess->decr_ctx.mech)) {
397a93
         rc = ep11tok_decrypt_single(tokdata, sess, &sess->decr_ctx.mech,
397a93
                                     length_only, sess->decr_ctx.key,
397a93
@@ -2541,7 +2547,8 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
397a93
         goto done;
397a93
     }
397a93
 
397a93
-    if (sess->decr_ctx.active == FALSE) {
397a93
+    if (sess->decr_ctx.active == FALSE ||
397a93
+        ep11tok_mech_single_only(&sess->decr_ctx.mech)) {
397a93
         TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
397a93
         rc = CKR_OPERATION_NOT_INITIALIZED;
397a93
         goto done;
397a93
@@ -2617,7 +2624,8 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
397a93
         goto done;
397a93
     }
397a93
 
397a93
-    if (sess->decr_ctx.active == FALSE) {
397a93
+    if (sess->decr_ctx.active == FALSE ||
397a93
+        ep11tok_mech_single_only(&sess->decr_ctx.mech)) {
397a93
         TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
397a93
         rc = CKR_OPERATION_NOT_INITIALIZED;
397a93
         goto done;
397a93
-- 
397a93
2.16.2.windows.1
397a93