forked from pool/openCryptoki
f41ca9bf97
- Added patch for compile errors * ocki-3.19.0-0035-Fix-compile-error-error-initializer-element-is-not-c.patch - Changed spec file to use %autosetup instead of %setup. - Updated the package openCryptoki 3.19.0 (jsc#PED-616, bsc#1207760), added the following patches: * ocki-3.19.0-0001-EP11-Unify-key-pair-generation-functions.patch * ocki-3.19.0-0002-EP11-Do-not-report-DSA-DH-parameter-generation-as-be.patch * ocki-3.19.0-0003-EP11-Do-not-pass-empty-CKA_PUBLIC_KEY_INFO-to-EP11-h.patch * ocki-3.19.0-0004-Mechtable-CKM_IBM_DILITHIUM-can-also-be-used-for-key.patch * ocki-3.19.0-0005-EP11-Remove-DSA-DH-parameter-generation-mechanisms-f.patch * ocki-3.19.0-0006-EP11-Pass-back-chain-code-for-CKM_IBM_BTC_DERIVE.patch * ocki-3.19.0-0007-EP11-Supply-CKA_PUBLIC_KEY_INFO-with-CKM_IBM_BTC_DER.patch * ocki-3.19.0-0008-EP11-Supply-CKA_PUBLIC_KEY_INFO-when-importing-priva.patch * ocki-3.19.0-0009-EP11-Fix-memory-leak-introduced-with-recent-commit.patch * ocki-3.19.0-0010-p11sak-Fix-segfault-when-dilithium-version-is-not-sp.patch * ocki-3.19.0-0011-EP11-remove-dead-code-and-unused-variables.patch * ocki-3.19.0-0012-EP11-Update-EP11-host-library-header-files.patch * ocki-3.19.0-0013-EP11-Support-EP11-host-library-version-4.patch * ocki-3.19.0-0014-EP11-Add-new-control-points.patch * ocki-3.19.0-0015-EP11-Default-unknown-CPs-to-ON.patch * ocki-3.19.0-0016-COMMON-Add-defines-for-Dilithium-round-2-and-3-varia.patch * ocki-3.19.0-0017-COMMON-Add-defines-for-Kyber.patch * ocki-3.19.0-0018-COMMON-Add-post-quantum-algorithm-OIDs.patch * ocki-3.19.0-0019-COMMON-Dilithium-key-BER-encoding-decoding-allow-dif.patch * ocki-3.19.0-0020-COMMON-EP11-Add-CKA_VALUE-holding-SPKI-PKCS-8-of-key.patch * ocki-3.19.0-0021-COMMON-EP11-Allow-to-select-Dilithium-variant-via-mo.patch * ocki-3.19.0-0022-EP11-Query-supported-PQC-variants-and-restrict-usage.patch * ocki-3.19.0-0023-POLICY-Dilithium-strength-and-signature-size-depends.patch * ocki-3.19.0-0024-TESTCASES-Test-Dilithium-variants.patch * ocki-3.19.0-0025-COMMON-EP11-Add-Kyber-key-type-and-mechanism.patch * ocki-3.19.0-0026-EP11-Add-support-for-generating-and-importing-Kyber-.patch * ocki-3.19.0-0027-EP11-Add-support-for-encrypt-decrypt-and-KEM-operati.patch * ocki-3.19.0-0028-POLICY-STATISTICS-Check-for-Kyber-KEM-KDFs-and-count.patch * ocki-3.19.0-0029-TESTCASES-Add-tests-for-CKM_IBM_KYBER.patch * ocki-3.19.0-0030-p11sak-Support-additional-Dilithium-variants.patch * ocki-3.19.0-0031-p11sak-Add-support-for-IBM-Kyber-key-type.patch * ocki-3.19.0-0032-testcase-Enhance-p11sak-testcase-to-generate-IBM-Kyb.patch * ocki-3.19.0-0033-EP11-Supply-CKA_PUBLIC_KEY_INFO-with-CKM_IBM_BTC_DER.patch * ocki-3.19.0-0034-EP11-Fix-setting-unknown-CPs-to-ON.patch OBS-URL: https://build.opensuse.org/request/show/1063652 OBS-URL: https://build.opensuse.org/package/show/security/openCryptoki?expand=0&rev=128
340 lines
14 KiB
Diff
340 lines
14 KiB
Diff
From 51ed2d7171e5423cfec86c36ffa32e8e9e0de01c Mon Sep 17 00:00:00 2001
|
|
From: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
Date: Tue, 1 Mar 2022 16:55:01 +0100
|
|
Subject: [PATCH 27/34] EP11: Add support for encrypt/decrypt and KEM
|
|
operations with Kyber
|
|
|
|
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
|
---
|
|
usr/lib/ep11_stdll/ep11_specific.c | 174 ++++++++++++++++++++++++++++++++++---
|
|
usr/lib/ep11_stdll/new_host.c | 24 +++--
|
|
2 files changed, 180 insertions(+), 18 deletions(-)
|
|
|
|
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
|
index bc17b07a..9efce053 100644
|
|
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
|
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
|
@@ -5196,6 +5196,126 @@ CK_RV token_specific_aes_cmac(STDLL_TokData_t *tokdata,
|
|
return rc;
|
|
}
|
|
|
|
+struct EP11_KYBER_MECH {
|
|
+ CK_MECHANISM mech;
|
|
+ struct XCP_KYBER_KEM_PARAMS params;
|
|
+};
|
|
+
|
|
+static CK_RV ep11tok_kyber_mech_pre_process(STDLL_TokData_t *tokdata,
|
|
+ CK_MECHANISM *mech,
|
|
+ struct EP11_KYBER_MECH *mech_ep11,
|
|
+ OBJECT **secret_key_obj)
|
|
+{
|
|
+ CK_IBM_KYBER_PARAMS *kyber_params;
|
|
+ CK_RV rc;
|
|
+
|
|
+ kyber_params = mech->pParameter;
|
|
+ if (mech->ulParameterLen != sizeof(CK_IBM_KYBER_PARAMS)) {
|
|
+ TRACE_ERROR("Mechanism parameter length not as expected\n");
|
|
+ return CKR_MECHANISM_PARAM_INVALID;
|
|
+ }
|
|
+
|
|
+ if (kyber_params->ulVersion != CK_IBM_KYBER_KEM_VERSION) {
|
|
+ TRACE_ERROR("Unsupported version in Kyber mechanism param\n");
|
|
+ return CKR_MECHANISM_PARAM_INVALID;
|
|
+ }
|
|
+
|
|
+ mech_ep11->mech.mechanism = mech->mechanism;
|
|
+ mech_ep11->mech.pParameter = &mech_ep11->params;
|
|
+ mech_ep11->mech.ulParameterLen = sizeof(mech_ep11->params);
|
|
+
|
|
+ memset(&mech_ep11->params, 0, sizeof(mech_ep11->params));
|
|
+ mech_ep11->params.version = XCP_KYBER_KEM_VERSION;
|
|
+ mech_ep11->params.mode = kyber_params->mode;
|
|
+ mech_ep11->params.kdf = kyber_params->kdf;
|
|
+ mech_ep11->params.prepend = kyber_params->bPrepend;
|
|
+ mech_ep11->params.pSharedData = kyber_params->pSharedData;
|
|
+ mech_ep11->params.ulSharedDataLen = kyber_params->ulSharedDataLen;
|
|
+
|
|
+ switch (kyber_params->mode) {
|
|
+ case CK_IBM_KYBER_KEM_ENCAPSULATE:
|
|
+ if (kyber_params->ulCipherLen > 0 && kyber_params->pCipher == NULL) {
|
|
+ TRACE_ERROR("Unsupported cipher buffer in Kyber mechnism param "
|
|
+ "cannot be NULL\n");
|
|
+ return CKR_MECHANISM_PARAM_INVALID;
|
|
+ }
|
|
+
|
|
+ mech_ep11->params.pCipher = NULL;
|
|
+ mech_ep11->params.ulCipherLen = 0;
|
|
+ /* Cipher is returned in 2nd output param of m_DeriveKey */
|
|
+ break;
|
|
+
|
|
+ case CK_IBM_KEM_DECAPSULATE:
|
|
+ mech_ep11->params.pCipher = kyber_params->pCipher;
|
|
+ mech_ep11->params.ulCipherLen = kyber_params->ulCipherLen;
|
|
+ break;
|
|
+
|
|
+ default:
|
|
+ TRACE_ERROR("Unsupported mode in Kyber mechanism param\n");
|
|
+ return CKR_MECHANISM_PARAM_INVALID;
|
|
+ }
|
|
+
|
|
+ if (kyber_params->bPrepend) {
|
|
+ rc = h_opaque_2_blob(tokdata, kyber_params->hSecret,
|
|
+ &mech_ep11->params.pBlob,
|
|
+ &mech_ep11->params.ulBlobLen,
|
|
+ secret_key_obj, READ_LOCK);
|
|
+ if (rc != CKR_OK) {
|
|
+ TRACE_ERROR("%s failed hSecret=0x%lx\n", __func__,
|
|
+ kyber_params->hSecret);
|
|
+ return rc;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ return CKR_OK;
|
|
+}
|
|
+
|
|
+static CK_RV ep11tok_kyber_mech_post_process(STDLL_TokData_t *tokdata,
|
|
+ CK_MECHANISM *mech,
|
|
+ CK_BYTE *csum, CK_ULONG cslen)
|
|
+{
|
|
+ CK_IBM_KYBER_PARAMS *kyber_params;
|
|
+ CK_ULONG cipher_len;
|
|
+
|
|
+ UNUSED(tokdata);
|
|
+
|
|
+ kyber_params = mech->pParameter;
|
|
+ if (mech->ulParameterLen != sizeof(CK_IBM_KYBER_PARAMS)) {
|
|
+ TRACE_ERROR("Mechanism parameter length not as expected\n");
|
|
+ return CKR_MECHANISM_PARAM_INVALID;
|
|
+ }
|
|
+
|
|
+ if (kyber_params->mode != CK_IBM_KYBER_KEM_ENCAPSULATE)
|
|
+ return CKR_OK;
|
|
+
|
|
+ /*
|
|
+ * For encapsulate:
|
|
+ * Generated cipher is returned in csum prepended with the checksum of
|
|
+ * the generated symmetric key and its bit count (in total 7 bytes).
|
|
+ */
|
|
+ if (cslen < EP11_CSUMSIZE + 4) {
|
|
+ TRACE_ERROR("%s returned cipher size is invalid: %lu\n",
|
|
+ __func__, cslen);
|
|
+ return CKR_FUNCTION_FAILED;
|
|
+ }
|
|
+
|
|
+ cipher_len = cslen - (EP11_CSUMSIZE + 4);
|
|
+
|
|
+ if (kyber_params->ulCipherLen < cipher_len) {
|
|
+ TRACE_ERROR("%s Cipher buffer in kyber mechanism param too small, required: %lu\n",
|
|
+ __func__, cipher_len);
|
|
+ kyber_params->ulCipherLen = cipher_len;
|
|
+ OPENSSL_cleanse(&csum[EP11_CSUMSIZE + 4], cipher_len);
|
|
+ return CKR_BUFFER_TOO_SMALL;
|
|
+ }
|
|
+
|
|
+ memcpy(kyber_params->pCipher, &csum[EP11_CSUMSIZE + 4], cipher_len);
|
|
+ kyber_params->ulCipherLen = cipher_len;
|
|
+
|
|
+ OPENSSL_cleanse(&csum[EP11_CSUMSIZE + 4], cipher_len);
|
|
+ return CKR_OK;
|
|
+}
|
|
+
|
|
CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
|
|
CK_MECHANISM_PTR mech, CK_OBJECT_HANDLE hBaseKey,
|
|
CK_OBJECT_HANDLE_PTR handle, CK_ATTRIBUTE_PTR attrs,
|
|
@@ -5236,6 +5356,8 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
|
|
CK_BYTE *spki = NULL;
|
|
CK_ULONG spki_length = 0;
|
|
CK_ATTRIBUTE *spki_attr = NULL;
|
|
+ struct EP11_KYBER_MECH mech_ep11;
|
|
+ OBJECT *kyber_secret_obj = NULL;
|
|
|
|
memset(newblob, 0, sizeof(newblob));
|
|
|
|
@@ -5517,16 +5639,29 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
|
|
}
|
|
}
|
|
|
|
+ if (mech->mechanism == CKM_IBM_KYBER) {
|
|
+ rc = ep11tok_kyber_mech_pre_process(tokdata, mech, &mech_ep11,
|
|
+ &kyber_secret_obj);
|
|
+ if (rc != CKR_OK)
|
|
+ goto error;
|
|
+ mech = &mech_ep11.mech;
|
|
+ }
|
|
+
|
|
trace_attributes(__func__, "Derive:", new_attrs2, new_attrs2_len);
|
|
|
|
ep11_get_pin_blob(ep11_session, ep11_is_session_object(attrs, attrs_len),
|
|
&ep11_pin_blob, &ep11_pin_blob_len);
|
|
|
|
RETRY_START(rc, tokdata)
|
|
- rc =
|
|
- dll_m_DeriveKey(mech, new_attrs2, new_attrs2_len, keyblob, keyblobsize,
|
|
- NULL, 0, ep11_pin_blob, ep11_pin_blob_len, newblob,
|
|
- &newblobsize, csum, &cslen, target_info->target);
|
|
+ if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
|
|
+ base_key_obj))
|
|
+ rc = dll_m_DeriveKey(mech, new_attrs2, new_attrs2_len,
|
|
+ keyblob, keyblobsize, NULL, 0,
|
|
+ ep11_pin_blob, ep11_pin_blob_len, newblob,
|
|
+ &newblobsize, csum, &cslen,
|
|
+ target_info->target);
|
|
+ else
|
|
+ rc = CKR_KEY_SIZE_RANGE;
|
|
RETRY_END(rc, tokdata, session)
|
|
|
|
if (rc != CKR_OK) {
|
|
@@ -5610,6 +5745,12 @@ CK_RV ep11tok_derive_key(STDLL_TokData_t * tokdata, SESSION * session,
|
|
}
|
|
}
|
|
|
|
+ if (mech->mechanism == CKM_IBM_KYBER) {
|
|
+ rc = ep11tok_kyber_mech_post_process(tokdata, mech_orig, csum, cslen);
|
|
+ if (rc != CKR_OK)
|
|
+ goto error;
|
|
+ }
|
|
+
|
|
if (class == CKO_SECRET_KEY && cslen >= EP11_CSUMSIZE) {
|
|
/* First 3 bytes of csum is the check value */
|
|
rc = build_attribute(CKA_CHECK_VALUE, csum, EP11_CSUMSIZE, &chk_attr);
|
|
@@ -5666,6 +5807,8 @@ error:
|
|
|
|
object_put(tokdata, base_key_obj, TRUE);
|
|
base_key_obj = NULL;
|
|
+ object_put(tokdata, kyber_secret_obj, TRUE);
|
|
+ kyber_secret_obj = NULL;
|
|
|
|
return rc;
|
|
}
|
|
@@ -7399,6 +7542,7 @@ CK_BOOL ep11tok_mech_single_only(CK_MECHANISM *mech)
|
|
{
|
|
switch (mech->mechanism) {
|
|
case CKM_IBM_ECDSA_OTHER:
|
|
+ case CKM_IBM_KYBER:
|
|
return CK_TRUE;
|
|
default:
|
|
return CK_FALSE;
|
|
@@ -8301,9 +8445,14 @@ CK_RV ep11tok_decrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
|
|
}
|
|
|
|
RETRY_START(rc, tokdata)
|
|
- rc = dll_m_DecryptSingle(keyblob, keyblobsize, mech, input_data,
|
|
- input_data_len, output_data, p_output_data_len,
|
|
- target_info->target);
|
|
+ if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
|
|
+ key_obj))
|
|
+ rc = dll_m_DecryptSingle(keyblob, keyblobsize, mech, input_data,
|
|
+ input_data_len, output_data,
|
|
+ p_output_data_len,
|
|
+ target_info->target);
|
|
+ else
|
|
+ rc = CKR_KEY_SIZE_RANGE;
|
|
RETRY_END(rc, tokdata, session)
|
|
if (rc != CKR_OK) {
|
|
rc = ep11_error_to_pkcs11_error(rc, session);
|
|
@@ -8511,9 +8660,14 @@ CK_RV ep11tok_encrypt_single(STDLL_TokData_t *tokdata, SESSION *session,
|
|
}
|
|
|
|
RETRY_START(rc, tokdata)
|
|
- rc = dll_m_EncryptSingle(keyblob, keyblobsize, mech, input_data,
|
|
- input_data_len, output_data, p_output_data_len,
|
|
- target_info->target);
|
|
+ if (ep11_pqc_obj_strength_supported(target_info, mech->mechanism,
|
|
+ key_obj))
|
|
+ rc = dll_m_EncryptSingle(keyblob, keyblobsize, mech, input_data,
|
|
+ input_data_len, output_data,
|
|
+ p_output_data_len,
|
|
+ target_info->target);
|
|
+ else
|
|
+ rc = CKR_KEY_SIZE_RANGE;
|
|
RETRY_END(rc, tokdata, session)
|
|
if (rc != CKR_OK) {
|
|
rc = ep11_error_to_pkcs11_error(rc, session);
|
|
diff --git a/usr/lib/ep11_stdll/new_host.c b/usr/lib/ep11_stdll/new_host.c
|
|
index dccdfe96..60027c85 100644
|
|
--- a/usr/lib/ep11_stdll/new_host.c
|
|
+++ b/usr/lib/ep11_stdll/new_host.c
|
|
@@ -2061,7 +2061,8 @@ CK_RV SC_EncryptInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
sess->encr_ctx.multi_init = FALSE;
|
|
sess->encr_ctx.multi = FALSE;
|
|
|
|
- if (ep11tok_optimize_single_ops(tokdata) &&
|
|
+ if ((ep11tok_optimize_single_ops(tokdata) ||
|
|
+ ep11tok_mech_single_only(pMechanism)) &&
|
|
!ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism)) {
|
|
/* In case of a single part encrypt operation we don't need the
|
|
* EncryptInit, instead we can use the EncryptSingle which is much
|
|
@@ -2159,7 +2160,8 @@ CK_RV SC_Encrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
goto done;
|
|
}
|
|
|
|
- if (ep11tok_optimize_single_ops(tokdata) &&
|
|
+ if ((ep11tok_optimize_single_ops(tokdata) ||
|
|
+ ep11tok_mech_single_only(&sess->encr_ctx.mech)) &&
|
|
!ep11tok_pkey_usage_ok(tokdata, sess, sess->encr_ctx.key, &sess->encr_ctx.mech)) {
|
|
rc = ep11tok_encrypt_single(tokdata, sess, &sess->encr_ctx.mech,
|
|
length_only, sess->encr_ctx.key,
|
|
@@ -2217,7 +2219,8 @@ CK_RV SC_EncryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
goto done;
|
|
}
|
|
|
|
- if (sess->encr_ctx.active == FALSE) {
|
|
+ if (sess->encr_ctx.active == FALSE ||
|
|
+ ep11tok_mech_single_only(&sess->encr_ctx.mech)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
@@ -2293,7 +2296,8 @@ CK_RV SC_EncryptFinal(STDLL_TokData_t * tokdata, ST_SESSION_HANDLE * sSession,
|
|
goto done;
|
|
}
|
|
|
|
- if (sess->encr_ctx.active == FALSE) {
|
|
+ if (sess->encr_ctx.active == FALSE ||
|
|
+ ep11tok_mech_single_only(&sess->encr_ctx.mech)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
@@ -2385,7 +2389,8 @@ CK_RV SC_DecryptInit(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
sess->decr_ctx.multi_init = FALSE;
|
|
sess->decr_ctx.multi = FALSE;
|
|
|
|
- if (ep11tok_optimize_single_ops(tokdata) &&
|
|
+ if ((ep11tok_optimize_single_ops(tokdata) ||
|
|
+ ep11tok_mech_single_only(pMechanism)) &&
|
|
!ep11tok_pkey_usage_ok(tokdata, sess, hKey, pMechanism)) {
|
|
/* In case of a single part decrypt operation we don't need the
|
|
* DecryptInit, instead we can use the EncryptSingle which is much
|
|
@@ -2483,7 +2488,8 @@ CK_RV SC_Decrypt(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
goto done;
|
|
}
|
|
|
|
- if (ep11tok_optimize_single_ops(tokdata) &&
|
|
+ if ((ep11tok_optimize_single_ops(tokdata) ||
|
|
+ ep11tok_mech_single_only(&sess->decr_ctx.mech)) &&
|
|
!ep11tok_pkey_usage_ok(tokdata, sess, sess->decr_ctx.key, &sess->decr_ctx.mech)) {
|
|
rc = ep11tok_decrypt_single(tokdata, sess, &sess->decr_ctx.mech,
|
|
length_only, sess->decr_ctx.key,
|
|
@@ -2541,7 +2547,8 @@ CK_RV SC_DecryptUpdate(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
goto done;
|
|
}
|
|
|
|
- if (sess->decr_ctx.active == FALSE) {
|
|
+ if (sess->decr_ctx.active == FALSE ||
|
|
+ ep11tok_mech_single_only(&sess->decr_ctx.mech)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
@@ -2617,7 +2624,8 @@ CK_RV SC_DecryptFinal(STDLL_TokData_t *tokdata, ST_SESSION_HANDLE *sSession,
|
|
goto done;
|
|
}
|
|
|
|
- if (sess->decr_ctx.active == FALSE) {
|
|
+ if (sess->decr_ctx.active == FALSE ||
|
|
+ ep11tok_mech_single_only(&sess->decr_ctx.mech)) {
|
|
TRACE_ERROR("%s\n", ock_err(ERR_OPERATION_NOT_INITIALIZED));
|
|
rc = CKR_OPERATION_NOT_INITIALIZED;
|
|
goto done;
|
|
--
|
|
2.16.2.windows.1
|
|
|