1436 lines
49 KiB
Diff
1436 lines
49 KiB
Diff
|
From 49ce634ed6fa1fddc2bb34fd0f89c0ea0cc368ee Mon Sep 17 00:00:00 2001
|
||
|
From: Ingo Franzki <ifranzki@linux.ibm.com>
|
||
|
Date: Tue, 1 Mar 2022 09:15:15 +0100
|
||
|
Subject: [PATCH 25/34] COMMON/EP11: Add Kyber key type and mechanism
|
||
|
|
||
|
Kyber requires an EP11 host library of version 4.0 or later,
|
||
|
and a CEX8P crypto card.
|
||
|
|
||
|
Signed-off-by: Ingo Franzki <ifranzki@linux.ibm.com>
|
||
|
---
|
||
|
usr/lib/api/mechtable.inc | 1 +
|
||
|
usr/lib/api/policy.c | 2 +
|
||
|
usr/lib/common/asn1.c | 563 +++++++++++++++++++++++++++++++++++
|
||
|
usr/lib/common/h_extern.h | 59 ++++
|
||
|
usr/lib/common/key.c | 476 +++++++++++++++++++++++++++++
|
||
|
usr/lib/common/key_mgr.c | 10 +
|
||
|
usr/lib/common/mech_ec.c | 3 +
|
||
|
usr/lib/common/template.c | 12 +
|
||
|
usr/lib/ep11_stdll/ep11_specific.c | 42 ++-
|
||
|
usr/lib/ep11_stdll/ep11cpfilter.conf | 2 +-
|
||
|
10 files changed, 1167 insertions(+), 3 deletions(-)
|
||
|
|
||
|
diff --git a/usr/lib/api/mechtable.inc b/usr/lib/api/mechtable.inc
|
||
|
index e3d14e3e..7aa72fbf 100644
|
||
|
--- a/usr/lib/api/mechtable.inc
|
||
|
+++ b/usr/lib/api/mechtable.inc
|
||
|
@@ -84,6 +84,7 @@ const struct mechrow mechtable_rows[] =
|
||
|
{ "CKM_IBM_EC_X448", CKM_IBM_EC_X448, 0, MC_INFORMATION_UNAVAILABLE, MCF_DERIVE },
|
||
|
{ "CKM_IBM_ED25519_SHA512", CKM_IBM_ED25519_SHA512, 128, MC_KEY_DEPENDENT, MCF_SIGNVERIFY },
|
||
|
{ "CKM_IBM_ED448_SHA3", CKM_IBM_ED448_SHA3, 144, MC_KEY_DEPENDENT, MCF_SIGNVERIFY },
|
||
|
+ { "CKM_IBM_KYBER", CKM_IBM_KYBER, 0, MC_KEY_DEPENDENT, MCF_KEYGEN | MCF_ENCRYPTDECRYPT | MCF_DERIVE | MCF_NEEDSPARAM},
|
||
|
{ "CKM_IBM_SHA3_224", CKM_IBM_SHA3_224, 144, 24, MCF_DIGEST },
|
||
|
{ "CKM_IBM_SHA3_224_HMAC", CKM_IBM_SHA3_224_HMAC, 144, 24, MCF_SIGNVERIFY },
|
||
|
{ "CKM_IBM_SHA3_256", CKM_IBM_SHA3_256, 136, 32, MCF_DIGEST },
|
||
|
diff --git a/usr/lib/api/policy.c b/usr/lib/api/policy.c
|
||
|
index 4bee5180..b513a8a9 100644
|
||
|
--- a/usr/lib/api/policy.c
|
||
|
+++ b/usr/lib/api/policy.c
|
||
|
@@ -333,6 +333,7 @@ static CK_RV policy_extract_key_data(get_attr_val_f getattr, void *d,
|
||
|
*comptarget = COMPARE_SYMMETRIC;
|
||
|
break;
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
rv = policy_get_pqc_args(*(CK_ULONG *)keytype->pValue, getattr, d,
|
||
|
free_attr, size, siglen, oid, oidlen);
|
||
|
*comptarget = COMPARE_PQC;
|
||
|
@@ -1062,6 +1063,7 @@ static CK_RV policy_update_mech_info(policy_t p, CK_MECHANISM_TYPE mech,
|
||
|
}
|
||
|
break;
|
||
|
case CKM_IBM_DILITHIUM:
|
||
|
+ case CKM_IBM_KYBER:
|
||
|
break;
|
||
|
case CKM_IBM_SHA3_224:
|
||
|
case CKM_IBM_SHA3_256:
|
||
|
diff --git a/usr/lib/common/asn1.c b/usr/lib/common/asn1.c
|
||
|
index 85d3924c..87cc5dfc 100644
|
||
|
--- a/usr/lib/common/asn1.c
|
||
|
+++ b/usr/lib/common/asn1.c
|
||
|
@@ -4384,3 +4384,566 @@ cleanup:
|
||
|
|
||
|
return rc;
|
||
|
}
|
||
|
+
|
||
|
+/**
|
||
|
+ * An IBM Kyber public key is given by:
|
||
|
+ *
|
||
|
+ * SEQUENCE (2 elem)
|
||
|
+ * SEQUENCE (2 elem)
|
||
|
+ * OBJECT IDENTIFIER 1.3.6.1.4.1.2.267.5.xxx
|
||
|
+ * NULL
|
||
|
+ * BIT STRING (1 elem)
|
||
|
+ * SEQUENCE (1 elem)
|
||
|
+ * pk BIT STRING -- public key
|
||
|
+ */
|
||
|
+CK_RV ber_encode_IBM_KyberPublicKey(CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len,
|
||
|
+ const CK_BYTE *oid, CK_ULONG oid_len,
|
||
|
+ CK_ATTRIBUTE *pk)
|
||
|
+{
|
||
|
+ CK_BYTE *buf = NULL, *buf2 = NULL, *buf3 = NULL, *buf4 = NULL;
|
||
|
+ CK_BYTE *buf5 = NULL, *algid = NULL;
|
||
|
+ CK_ULONG len, len4, offset, total, total_len, algid_len;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ UNUSED(length_only);
|
||
|
+
|
||
|
+ offset = 0;
|
||
|
+ rc = 0;
|
||
|
+ total_len = 0;
|
||
|
+ total = 0;
|
||
|
+
|
||
|
+ /* Calculate storage for AlgID sequence */
|
||
|
+ rc |= ber_encode_SEQUENCE(TRUE, NULL, &total_len, NULL,
|
||
|
+ oid_len + ber_NULLLen);
|
||
|
+
|
||
|
+ /* Calculate storage for inner sequence */
|
||
|
+ rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, pk->ulValueLen);
|
||
|
+ offset += len;
|
||
|
+
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_encode_Int failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Allocate storage for inner sequence */
|
||
|
+ buf = (CK_BYTE *) malloc(offset);
|
||
|
+ if (!buf) {
|
||
|
+ TRACE_ERROR("%s Memory allocation failed\n", __func__);
|
||
|
+ return CKR_HOST_MEMORY;
|
||
|
+ }
|
||
|
+
|
||
|
+ /**
|
||
|
+ * SEQUENCE (1 elem)
|
||
|
+ * BIT STRING -> pk
|
||
|
+ */
|
||
|
+ offset = 0;
|
||
|
+ rc = ber_encode_BIT_STRING(FALSE, &buf2, &len,
|
||
|
+ pk->pValue, pk->ulValueLen, 0);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_encode_Int failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ memcpy(buf + offset, buf2, len);
|
||
|
+ offset += len;
|
||
|
+ free(buf2);
|
||
|
+
|
||
|
+ rc = ber_encode_SEQUENCE(FALSE, &buf2, &len, buf, offset);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_encode_Seq failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ free(buf);
|
||
|
+ buf = NULL;
|
||
|
+
|
||
|
+ /* Calculate length of outer sequence */
|
||
|
+ rc = ber_encode_BIT_STRING(TRUE, NULL, &total, buf2, len, 0);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_encode_Oct_Str failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ goto error;
|
||
|
+ } else {
|
||
|
+ total_len += total;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Allocate storage for outer sequence and bit string */
|
||
|
+ buf3 = (CK_BYTE *) malloc(total_len);
|
||
|
+ if (!buf3) {
|
||
|
+ TRACE_ERROR("%s Memory allocation failed\n", __func__);
|
||
|
+ rc = CKR_HOST_MEMORY;
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+
|
||
|
+ /*
|
||
|
+ * SEQUENCE (2 elem)
|
||
|
+ * OBJECT IDENTIFIER 1.3.6.1.4.1.2.267.5.xxx
|
||
|
+ * NULL <- no parms for this oid
|
||
|
+ */
|
||
|
+ buf5 = (CK_BYTE *) malloc(oid_len + ber_NULLLen);
|
||
|
+ if (!buf5) {
|
||
|
+ TRACE_ERROR("%s Memory allocation failed\n", __func__);
|
||
|
+ rc = CKR_HOST_MEMORY;
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ memcpy(buf5, oid, oid_len);
|
||
|
+ memcpy(buf5 + oid_len, ber_NULL, ber_NULLLen);
|
||
|
+
|
||
|
+ rc = ber_encode_SEQUENCE(FALSE, &algid, &algid_len, buf5,
|
||
|
+ oid_len + ber_NULLLen);
|
||
|
+ free(buf5);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_encode_SEQUENCE failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+
|
||
|
+ total_len = algid_len;
|
||
|
+ memcpy(buf3, algid, algid_len);
|
||
|
+ free(algid);
|
||
|
+ algid = NULL;
|
||
|
+
|
||
|
+ /*
|
||
|
+ * BIT STRING (1 elem)
|
||
|
+ * SEQUENCE (1 elem)
|
||
|
+ * BIT STRING -> pk
|
||
|
+ */
|
||
|
+ rc = ber_encode_BIT_STRING(FALSE, &buf4, &len4, buf2, len, 0);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_encode_BIT_STRING failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ memcpy(buf3 + total_len, buf4, len4);
|
||
|
+ total_len += len4;
|
||
|
+ free(buf4);
|
||
|
+ buf4 = NULL;
|
||
|
+
|
||
|
+ /**
|
||
|
+ * SEQUENCE (2 elem)
|
||
|
+ * SEQUENCE (2 elem)
|
||
|
+ * OBJECT IDENTIFIER 1.3.6.1.4.1.2.267.5.xxx
|
||
|
+ * NULL -> no parms for this oid
|
||
|
+ * BIT STRING (1 elem)
|
||
|
+ * SEQUENCE (2 elem)
|
||
|
+ * BIT STRING -> pk
|
||
|
+ */
|
||
|
+ rc = ber_encode_SEQUENCE(FALSE, data, data_len, buf3, total_len);
|
||
|
+ if (rc != CKR_OK)
|
||
|
+ TRACE_ERROR("%s ber_encode_Seq failed with rc=0x%lx\n", __func__, rc);
|
||
|
+
|
||
|
+error:
|
||
|
+
|
||
|
+ if (buf)
|
||
|
+ free(buf);
|
||
|
+ if (buf2)
|
||
|
+ free(buf2);
|
||
|
+ if (buf3)
|
||
|
+ free(buf3);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+CK_RV ber_decode_IBM_KyberPublicKey(CK_BYTE *data,
|
||
|
+ CK_ULONG data_len,
|
||
|
+ CK_ATTRIBUTE **pk_attr,
|
||
|
+ CK_ATTRIBUTE **value_attr,
|
||
|
+ const struct pqc_oid **oid)
|
||
|
+{
|
||
|
+ CK_ATTRIBUTE *pk_attr_temp = NULL;
|
||
|
+ CK_ATTRIBUTE *value_attr_temp = NULL;
|
||
|
+
|
||
|
+ CK_BYTE *algoid = NULL;
|
||
|
+ CK_ULONG algoid_len;
|
||
|
+ CK_BYTE *param = NULL;
|
||
|
+ CK_ULONG param_len;
|
||
|
+ CK_BYTE *val = NULL;
|
||
|
+ CK_ULONG val_len;
|
||
|
+ CK_BYTE *seq;
|
||
|
+ CK_ULONG seq_len;
|
||
|
+ CK_BYTE *pk;
|
||
|
+ CK_ULONG pk_len;
|
||
|
+ CK_ULONG field_len, raw_spki_len;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ UNUSED(data_len); // XXX can this parameter be removed ?
|
||
|
+
|
||
|
+ rc = ber_decode_SPKI(data, &algoid, &algoid_len, ¶m, ¶m_len,
|
||
|
+ &val, &val_len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_decode_SPKI failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ *oid = find_pqc_by_oid(kyber_oids, algoid, algoid_len);
|
||
|
+ if (*oid == NULL) {
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
|
||
|
+ return CKR_FUNCTION_FAILED;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Decode sequence:
|
||
|
+ * SEQUENCE (1 elem)
|
||
|
+ * BIT STRING = pk
|
||
|
+ */
|
||
|
+ rc = ber_decode_SEQUENCE(val, &seq, &seq_len, &field_len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_decode_SEQUENCE failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Decode pk */
|
||
|
+ rc = ber_decode_BIT_STRING(seq, &pk, &pk_len, &field_len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_decode_INTEGER failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+ pk++; /* Remove unused-bits byte */
|
||
|
+ pk_len--;
|
||
|
+
|
||
|
+ /* Build pk attribute */
|
||
|
+ rc = build_attribute(CKA_IBM_KYBER_PK, pk, pk_len, &pk_attr_temp);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("build_attribute failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Add raw SPKI as CKA_VALUE to public key (z/OS ICSF compatibility) */
|
||
|
+ rc = ber_decode_SEQUENCE(data, &val, &val_len, &raw_spki_len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+ rc = build_attribute(CKA_VALUE, data, raw_spki_len, &value_attr_temp);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("build_attribute failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+
|
||
|
+ *pk_attr = pk_attr_temp;
|
||
|
+ *value_attr = value_attr_temp;
|
||
|
+
|
||
|
+ return CKR_OK;
|
||
|
+
|
||
|
+cleanup:
|
||
|
+ if (pk_attr_temp)
|
||
|
+ free(pk_attr_temp);
|
||
|
+ if (value_attr_temp)
|
||
|
+ free(value_attr_temp);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * An IBM Kyber private key is given by:
|
||
|
+ *
|
||
|
+ * KyberPrivateKey ::= SEQUENCE {
|
||
|
+ * version INTEGER, -- v0, reserved 0
|
||
|
+ * sk BIT STRING, -- private key
|
||
|
+ * pk [0] IMPLICIT OPTIONAL {
|
||
|
+ * pk||rs BIT STRING -- public key (pk) concatenated with 2x32 bytes rs
|
||
|
+ * }
|
||
|
+ * }
|
||
|
+ */
|
||
|
+CK_RV ber_encode_IBM_KyberPrivateKey(CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data,
|
||
|
+ CK_ULONG *data_len,
|
||
|
+ const CK_BYTE *oid, CK_ULONG oid_len,
|
||
|
+ CK_ATTRIBUTE *sk,
|
||
|
+ CK_ATTRIBUTE *pk)
|
||
|
+{
|
||
|
+ CK_BYTE *buf = NULL, *buf2 = NULL, *buf3 = NULL;
|
||
|
+ CK_BYTE *algid = NULL, *algid_buf = NULL, *pk_rs = NULL;
|
||
|
+ CK_ULONG len, len2 = 0, offset, algid_len = 0;
|
||
|
+ CK_BYTE version[] = { 0 };
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ /* Calculate storage for sequence */
|
||
|
+ offset = 0;
|
||
|
+ rc = 0;
|
||
|
+
|
||
|
+ rc |= ber_encode_SEQUENCE(TRUE, NULL, &algid_len, NULL,
|
||
|
+ oid_len + ber_NULLLen);
|
||
|
+
|
||
|
+ rc |= ber_encode_INTEGER(TRUE, NULL, &len, NULL, sizeof(version));
|
||
|
+ offset += len;
|
||
|
+ rc |= ber_encode_BIT_STRING(TRUE, NULL, &len, NULL, sk->ulValueLen, 0);
|
||
|
+ offset += len;
|
||
|
+ if (pk) {
|
||
|
+ rc |= ber_encode_BIT_STRING(TRUE, NULL, &len2, NULL,
|
||
|
+ pk->ulValueLen + 64, 0);
|
||
|
+ rc |= ber_encode_CHOICE(TRUE, 0, NULL, &len, NULL, len2);
|
||
|
+ offset += len;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("Calculate storage for sequence failed\n");
|
||
|
+ return CKR_FUNCTION_FAILED;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (length_only == TRUE) {
|
||
|
+ rc = ber_encode_SEQUENCE(TRUE, NULL, &len, NULL, offset);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_encode_SEQUENCE failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+ rc = ber_encode_PrivateKeyInfo(TRUE,
|
||
|
+ NULL, data_len,
|
||
|
+ NULL, algid_len,
|
||
|
+ NULL, len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_encode_PrivateKeyInfo failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Allocate storage for sequence */
|
||
|
+ buf = (CK_BYTE *) malloc(offset);
|
||
|
+ if (!buf) {
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
||
|
+ return CKR_HOST_MEMORY;
|
||
|
+ }
|
||
|
+ offset = 0;
|
||
|
+
|
||
|
+ /* Version */
|
||
|
+ rc = ber_encode_INTEGER(FALSE, &buf2, &len, version, sizeof(version));
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ber_encode_INTEGER of version failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ memcpy(buf + offset, buf2, len);
|
||
|
+ offset += len;
|
||
|
+ free(buf2);
|
||
|
+ buf2 = NULL;
|
||
|
+
|
||
|
+ /* sk */
|
||
|
+ rc = ber_encode_BIT_STRING(FALSE, &buf2, &len,
|
||
|
+ sk->pValue, sk->ulValueLen, 0);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ber_encode_BIT_STRING of sk failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ memcpy(buf + offset, buf2, len);
|
||
|
+ offset += len;
|
||
|
+ free(buf2);
|
||
|
+ buf2 = NULL;
|
||
|
+
|
||
|
+ /* (pk) Optional bit-string of public key */
|
||
|
+ if (pk && pk->pValue) {
|
||
|
+ /* append rs to public key */
|
||
|
+ pk_rs = (CK_BYTE *)malloc(pk->ulValueLen + 64);
|
||
|
+ if (!pk_rs) {
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
||
|
+ rc = CKR_HOST_MEMORY;
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+
|
||
|
+ memcpy(pk_rs, pk->pValue, pk->ulValueLen);
|
||
|
+ memset(pk_rs + pk->ulValueLen, 0x30, 64);
|
||
|
+
|
||
|
+ rc = ber_encode_BIT_STRING(FALSE, &buf3, &len2,
|
||
|
+ pk_rs, pk->ulValueLen + 64, 0);
|
||
|
+ rc |= ber_encode_CHOICE(FALSE, 0, &buf2, &len, buf3, len2);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("encoding of pk value failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ memcpy(buf + offset, buf2, len);
|
||
|
+ offset += len;
|
||
|
+ free(buf2);
|
||
|
+ buf2 = NULL;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Encode sequence */
|
||
|
+ rc = ber_encode_SEQUENCE(FALSE, &buf2, &len, buf, offset);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ber_encode_SEQUENCE failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+
|
||
|
+ algid_buf = (CK_BYTE *) malloc(oid_len + ber_NULLLen);
|
||
|
+ if (!algid_buf) {
|
||
|
+ TRACE_ERROR("%s Memory allocation failed\n", __func__);
|
||
|
+ rc = CKR_HOST_MEMORY;
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ memcpy(algid_buf, oid, oid_len);
|
||
|
+ memcpy(algid_buf + oid_len, ber_NULL, ber_NULLLen);
|
||
|
+
|
||
|
+ rc = ber_encode_SEQUENCE(FALSE, &algid, &algid_len, algid_buf,
|
||
|
+ oid_len + ber_NULLLen);
|
||
|
+ free(algid_buf);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_encode_SEQUENCE failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = ber_encode_PrivateKeyInfo(FALSE,
|
||
|
+ data, data_len,
|
||
|
+ algid, algid_len,
|
||
|
+ buf2, len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ber_encode_PrivateKeyInfo failed\n");
|
||
|
+ }
|
||
|
+
|
||
|
+error:
|
||
|
+ if (buf3)
|
||
|
+ free(buf3);
|
||
|
+ if (buf2)
|
||
|
+ free(buf2);
|
||
|
+ if (buf)
|
||
|
+ free(buf);
|
||
|
+ if (algid)
|
||
|
+ free(algid);
|
||
|
+ if (pk_rs)
|
||
|
+ free(pk_rs);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+/**
|
||
|
+ * decode an IBM Kyber private key:
|
||
|
+ *
|
||
|
+ * KyberPrivateKey ::= SEQUENCE {
|
||
|
+ * version INTEGER, -- v0, reserved 0
|
||
|
+ * sk BIT STRING, -- private key
|
||
|
+ * pk [0] IMPLICIT OPTIONAL {
|
||
|
+ * pk||rs BIT STRING -- public key (pk) concatenated with 2x32 bytes rs
|
||
|
+ * }
|
||
|
+ * }
|
||
|
+ */
|
||
|
+CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
|
||
|
+ CK_ULONG data_len,
|
||
|
+ CK_ATTRIBUTE **sk,
|
||
|
+ CK_ATTRIBUTE **pk,
|
||
|
+ CK_ATTRIBUTE **value,
|
||
|
+ const struct pqc_oid **oid)
|
||
|
+{
|
||
|
+ CK_ATTRIBUTE *sk_attr = NULL, *pk_attr = NULL, *value_attr = NULL;
|
||
|
+ CK_BYTE *algoid = NULL;
|
||
|
+ CK_BYTE *kyber_priv_key = NULL;
|
||
|
+ CK_BYTE *buf = NULL;
|
||
|
+ CK_BYTE *tmp = NULL;
|
||
|
+ CK_ULONG offset, buf_len, field_len, len, option;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ /* Check if this is a Kyber private key */
|
||
|
+ rc = ber_decode_PrivateKeyInfo(data, data_len, &algoid, &len,
|
||
|
+ &kyber_priv_key);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_decode_PrivateKeyInfo failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (len <= ber_NULLLen ||
|
||
|
+ memcmp(algoid + len - ber_NULLLen, ber_NULL, ber_NULLLen) != 0) {
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
|
||
|
+ return CKR_FUNCTION_FAILED;
|
||
|
+ }
|
||
|
+ len -= ber_NULLLen;
|
||
|
+ *oid = find_pqc_by_oid(kyber_oids, algoid, len);
|
||
|
+ if (*oid == NULL) {
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
|
||
|
+ return CKR_FUNCTION_FAILED;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Decode private Kyber key */
|
||
|
+ rc = ber_decode_SEQUENCE(kyber_priv_key, &buf, &buf_len, &field_len);
|
||
|
+ if (rc != CKR_OK)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+ /* Now build the attributes */
|
||
|
+ offset = 0;
|
||
|
+
|
||
|
+ /* Skip the version */
|
||
|
+ rc = ber_decode_INTEGER(buf + offset, &tmp, &len, &field_len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_decode_INTEGER failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+ offset += field_len;
|
||
|
+
|
||
|
+ /* sk */
|
||
|
+ rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_decode_BIT_STRING of (sk) failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ } else {
|
||
|
+ tmp++; /* Remove unused-bits byte */
|
||
|
+ len--;
|
||
|
+ rc = build_attribute(CKA_IBM_KYBER_SK, tmp, len, &sk_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("build_attribute for (sk) failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+ offset += field_len;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* pk (optional, within choice) */
|
||
|
+ if (offset < buf_len) {
|
||
|
+ rc = ber_decode_CHOICE(buf + offset, &tmp, &len, &field_len, &option);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_decode_BIT_STRING of (t1) failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+
|
||
|
+ if (option != 0x00) {
|
||
|
+ TRACE_DEVEL("ber_decode_CHOICE returned invalid option %ld\n",
|
||
|
+ option);
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+
|
||
|
+ offset += field_len - len;
|
||
|
+
|
||
|
+ rc = ber_decode_BIT_STRING(buf + offset, &tmp, &len, &field_len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_decode_BIT_STRING of (pk) failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+ tmp++; /* Remove unused-bits byte */
|
||
|
+ len--;
|
||
|
+
|
||
|
+ if (len > 64)
|
||
|
+ len -= 64; /* Remove 'rs' */
|
||
|
+
|
||
|
+ rc = build_attribute(CKA_IBM_KYBER_PK, tmp, len, &pk_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("build_attribute for (pk) failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+ offset += field_len;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Check if buffer big enough */
|
||
|
+ if (offset > buf_len) {
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_FUNCTION_FAILED));
|
||
|
+ rc = CKR_FUNCTION_FAILED;
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+
|
||
|
+ /* Add private key as CKA_VALUE to public key (z/OS ICSF compatibility) */
|
||
|
+ rc = ber_decode_SEQUENCE(data, &tmp, &len, &field_len);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("%s ber_decode_SEQUENCE failed with rc=0x%lx\n", __func__, rc);
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+ rc = build_attribute(CKA_VALUE, data, field_len, &value_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("build_attribute for (t1) failed\n");
|
||
|
+ goto cleanup;
|
||
|
+ }
|
||
|
+
|
||
|
+ *sk = sk_attr;
|
||
|
+ *pk = pk_attr;
|
||
|
+ *value = value_attr;
|
||
|
+
|
||
|
+ return CKR_OK;
|
||
|
+
|
||
|
+cleanup:
|
||
|
+
|
||
|
+ if (sk_attr)
|
||
|
+ free(sk_attr);
|
||
|
+ if (pk_attr)
|
||
|
+ free(pk_attr);
|
||
|
+ if (value_attr)
|
||
|
+ free(value_attr);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
diff --git a/usr/lib/common/h_extern.h b/usr/lib/common/h_extern.h
|
||
|
index fdbcacd9..ee1ae08d 100644
|
||
|
--- a/usr/lib/common/h_extern.h
|
||
|
+++ b/usr/lib/common/h_extern.h
|
||
|
@@ -2505,6 +2505,40 @@ CK_RV ibm_dilithium_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data,
|
||
|
CK_RV ibm_dilithium_priv_unwrap_get_data(TEMPLATE *tmpl,
|
||
|
CK_BYTE *data, CK_ULONG total_length,
|
||
|
CK_BBOOL add_value);
|
||
|
+
|
||
|
+// Kyber routines
|
||
|
+//
|
||
|
+CK_RV ibm_kyber_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode);
|
||
|
+CK_RV ibm_kyber_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode);
|
||
|
+CK_RV ibm_kyber_publ_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
|
||
|
+ CK_ATTRIBUTE *attr, CK_ULONG mode);
|
||
|
+CK_RV ibm_kyber_publ_get_spki(TEMPLATE *tmpl, CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len);
|
||
|
+CK_RV ibm_kyber_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode);
|
||
|
+CK_RV ibm_kyber_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode);
|
||
|
+CK_RV ibm_kyber_priv_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
|
||
|
+ CK_ATTRIBUTE *attr, CK_ULONG mode);
|
||
|
+CK_RV ibm_kyber_priv_wrap_get_data(TEMPLATE *tmpl, CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len);
|
||
|
+CK_RV ibm_kyber_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data,
|
||
|
+ CK_ULONG total_length, CK_BBOOL add_value);
|
||
|
+CK_RV ibm_kyber_priv_unwrap_get_data(TEMPLATE *tmpl,
|
||
|
+ CK_BYTE *data, CK_ULONG total_length,
|
||
|
+ CK_BBOOL add_value);
|
||
|
+
|
||
|
+// PQC helper routines
|
||
|
+//
|
||
|
+CK_RV ibm_pqc_publ_get_spki(TEMPLATE *tmpl, CK_KEY_TYPE keytype,
|
||
|
+ CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len);
|
||
|
+CK_RV ibm_pqc_priv_wrap_get_data(TEMPLATE *tmpl, CK_KEY_TYPE keytype,
|
||
|
+ CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len);
|
||
|
+CK_RV ibm_pqc_priv_unwrap(TEMPLATE *tmpl, CK_KEY_TYPE keytype, CK_BYTE *data,
|
||
|
+ CK_ULONG total_length, CK_BBOOL add_value);
|
||
|
+CK_RV ibm_pqc_priv_unwrap_get_data(TEMPLATE *tmpl, CK_KEY_TYPE keytype,
|
||
|
+ CK_BYTE *data, CK_ULONG total_length,
|
||
|
+ CK_BBOOL add_value);
|
||
|
const struct pqc_oid *ibm_pqc_get_keyform_mode(TEMPLATE *tmpl,
|
||
|
CK_MECHANISM_TYPE mech);
|
||
|
CK_RV ibm_pqc_add_keyform_mode(TEMPLATE *tmpl, const struct pqc_oid *oid,
|
||
|
@@ -2782,6 +2816,31 @@ CK_RV ber_decode_IBM_DilithiumPrivateKey(CK_BYTE *data,
|
||
|
CK_ATTRIBUTE **value,
|
||
|
const struct pqc_oid **oid);
|
||
|
|
||
|
+CK_RV ber_encode_IBM_KyberPublicKey(CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len,
|
||
|
+ const CK_BYTE *oid, CK_ULONG oid_len,
|
||
|
+ CK_ATTRIBUTE *pk);
|
||
|
+
|
||
|
+CK_RV ber_decode_IBM_KyberPublicKey(CK_BYTE *data,
|
||
|
+ CK_ULONG data_len,
|
||
|
+ CK_ATTRIBUTE **pk_attr,
|
||
|
+ CK_ATTRIBUTE **value_attr,
|
||
|
+ const struct pqc_oid **oid);
|
||
|
+
|
||
|
+CK_RV ber_encode_IBM_KyberPrivateKey(CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data,
|
||
|
+ CK_ULONG *data_len,
|
||
|
+ const CK_BYTE *oid, CK_ULONG oid_len,
|
||
|
+ CK_ATTRIBUTE *sk,
|
||
|
+ CK_ATTRIBUTE *pk);
|
||
|
+
|
||
|
+CK_RV ber_decode_IBM_KyberPrivateKey(CK_BYTE *data,
|
||
|
+ CK_ULONG data_len,
|
||
|
+ CK_ATTRIBUTE **sk,
|
||
|
+ CK_ATTRIBUTE **pk,
|
||
|
+ CK_ATTRIBUTE **value,
|
||
|
+ const struct pqc_oid **oid);
|
||
|
+
|
||
|
typedef CK_RV (*t_rsa_encrypt)(STDLL_TokData_t *, CK_BYTE *in_data,
|
||
|
CK_ULONG in_data_len, CK_BYTE *out_data,
|
||
|
OBJECT *key_obj);
|
||
|
diff --git a/usr/lib/common/key.c b/usr/lib/common/key.c
|
||
|
index ba40cefd..ef329452 100644
|
||
|
--- a/usr/lib/common/key.c
|
||
|
+++ b/usr/lib/common/key.c
|
||
|
@@ -722,6 +722,9 @@ CK_RV publ_key_get_spki(TEMPLATE *tmpl, CK_ULONG keytype, CK_BBOOL length_only,
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
rc = ibm_dilithium_publ_get_spki(tmpl, length_only, data, data_len);
|
||
|
break;
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ rc = ibm_kyber_publ_get_spki(tmpl, length_only, data, data_len);
|
||
|
+ break;
|
||
|
default:
|
||
|
TRACE_ERROR("%s\n", ock_err(ERR_KEY_TYPE_INCONSISTENT));
|
||
|
return CKR_KEY_TYPE_INCONSISTENT;
|
||
|
@@ -1053,6 +1056,9 @@ CK_RV priv_key_unwrap(TEMPLATE *tmpl,
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
rc = ibm_dilithium_priv_unwrap(tmpl, data, data_len, TRUE);
|
||
|
break;
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ rc = ibm_kyber_priv_unwrap(tmpl, data, data_len, TRUE);
|
||
|
+ break;
|
||
|
default:
|
||
|
TRACE_ERROR("%s\n", ock_err(ERR_WRAPPED_KEY_INVALID));
|
||
|
return CKR_WRAPPED_KEY_INVALID;
|
||
|
@@ -3030,6 +3036,240 @@ error:
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
+/*
|
||
|
+ * Extract the SubjectPublicKeyInfo from the Kyber public key
|
||
|
+ */
|
||
|
+CK_RV ibm_kyber_publ_get_spki(TEMPLATE *tmpl, CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len)
|
||
|
+{
|
||
|
+ CK_ATTRIBUTE *pk = NULL;
|
||
|
+ const struct pqc_oid *oid;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ oid = ibm_pqc_get_keyform_mode(tmpl, CKM_IBM_KYBER);
|
||
|
+ if (oid == NULL)
|
||
|
+ return CKR_TEMPLATE_INCOMPLETE;
|
||
|
+
|
||
|
+ rc = template_attribute_get_non_empty(tmpl, CKA_IBM_KYBER_PK, &pk);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("Could not find CKA_IBM_KYBER_PK for the key.\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = ber_encode_IBM_KyberPublicKey(length_only, data, data_len,
|
||
|
+ oid->oid, oid->oid_len, pk);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ber_encode_IBM_KyberPublicKey failed.\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ return CKR_OK;
|
||
|
+}
|
||
|
+
|
||
|
+
|
||
|
+CK_RV ibm_kyber_priv_wrap_get_data(TEMPLATE *tmpl,
|
||
|
+ CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len)
|
||
|
+{
|
||
|
+ CK_ATTRIBUTE *sk = NULL, *pk = NULL;
|
||
|
+ const struct pqc_oid *oid;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ oid = ibm_pqc_get_keyform_mode(tmpl, CKM_IBM_KYBER);
|
||
|
+ if (oid == NULL)
|
||
|
+ return CKR_TEMPLATE_INCOMPLETE;
|
||
|
+
|
||
|
+ rc = template_attribute_get_non_empty(tmpl, CKA_IBM_KYBER_SK, &sk);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("Could not find CKA_IBM_KYBER_SK for the key.\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = template_attribute_get_non_empty(tmpl, CKA_IBM_KYBER_PK, &pk);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("Could not find CKA_IBM_KYBER_PK for the key.\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = ber_encode_IBM_KyberPrivateKey(length_only, data, data_len,
|
||
|
+ oid->oid, oid->oid_len, sk, pk);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("ber_encode_IBM_KyberPrivateKey failed\n");
|
||
|
+ }
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+CK_RV ibm_kyber_priv_unwrap_get_data(TEMPLATE *tmpl, CK_BYTE *data,
|
||
|
+ CK_ULONG total_length,
|
||
|
+ CK_BBOOL add_value)
|
||
|
+{
|
||
|
+ CK_ATTRIBUTE *pk = NULL;
|
||
|
+ CK_ATTRIBUTE *value = NULL;
|
||
|
+ const struct pqc_oid *oid;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ rc = ber_decode_IBM_KyberPublicKey(data, total_length, &pk,
|
||
|
+ &value, &oid);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ber_decode_IBM_KyberPublicKey failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = ibm_pqc_add_keyform_mode(tmpl, oid, CKM_IBM_KYBER);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ibm_pqc_add_keyform_mode failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = template_update_attribute(tmpl, pk);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("template_update_attribute failed.\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ pk = NULL;
|
||
|
+ if (add_value) {
|
||
|
+ rc = template_update_attribute(tmpl, value);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("template_update_attribute failed.\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ free(value);
|
||
|
+ }
|
||
|
+ value = NULL;
|
||
|
+
|
||
|
+ return CKR_OK;
|
||
|
+
|
||
|
+error:
|
||
|
+ if (pk)
|
||
|
+ free(pk);
|
||
|
+ if (value)
|
||
|
+ free(value);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+//
|
||
|
+//
|
||
|
+CK_RV ibm_kyber_priv_unwrap(TEMPLATE *tmpl, CK_BYTE *data,
|
||
|
+ CK_ULONG total_length, CK_BBOOL add_value)
|
||
|
+{
|
||
|
+ CK_ATTRIBUTE *sk = NULL, *pk = NULL, *value = NULL;
|
||
|
+ const struct pqc_oid *oid;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ rc = ber_decode_IBM_KyberPrivateKey(data, total_length,
|
||
|
+ &sk, &pk, &value, &oid);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ber_decode_IBM_KyberPrivateKey failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = ibm_pqc_add_keyform_mode(tmpl, oid, CKM_IBM_KYBER);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("ibm_pqc_add_keyform_mode failed\n");
|
||
|
+ return rc;
|
||
|
+ }
|
||
|
+
|
||
|
+ rc = template_update_attribute(tmpl, sk);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ sk = NULL;
|
||
|
+ rc = template_update_attribute(tmpl, pk);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ pk = NULL;
|
||
|
+ if (add_value) {
|
||
|
+ rc = template_update_attribute(tmpl, value);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_DEVEL("template_update_attribute failed.\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ } else {
|
||
|
+ free(value);
|
||
|
+ }
|
||
|
+ value = NULL;
|
||
|
+
|
||
|
+ return CKR_OK;
|
||
|
+
|
||
|
+error:
|
||
|
+ if (sk)
|
||
|
+ free(sk);
|
||
|
+ if (pk)
|
||
|
+ free(pk);
|
||
|
+ if (value)
|
||
|
+ free(value);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+CK_RV ibm_pqc_publ_get_spki(TEMPLATE *tmpl, CK_KEY_TYPE keytype,
|
||
|
+ CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len)
|
||
|
+{
|
||
|
+ switch (keytype) {
|
||
|
+ case CKK_IBM_PQC_DILITHIUM:
|
||
|
+ return ibm_dilithium_publ_get_spki(tmpl, length_only, data, data_len);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_publ_get_spki(tmpl, length_only, data, data_len);
|
||
|
+ default:
|
||
|
+ TRACE_DEVEL("Key type 0x%lx not supported.\n", keytype);
|
||
|
+ return CKR_KEY_TYPE_INCONSISTENT;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+CK_RV ibm_pqc_priv_wrap_get_data(TEMPLATE *tmpl, CK_KEY_TYPE keytype,
|
||
|
+ CK_BBOOL length_only,
|
||
|
+ CK_BYTE **data, CK_ULONG *data_len)
|
||
|
+{
|
||
|
+ switch (keytype) {
|
||
|
+ case CKK_IBM_PQC_DILITHIUM:
|
||
|
+ return ibm_dilithium_priv_wrap_get_data(tmpl, length_only, data,
|
||
|
+ data_len);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_priv_wrap_get_data(tmpl, length_only, data, data_len);
|
||
|
+ default:
|
||
|
+ TRACE_DEVEL("Key type 0x%lx not supported.\n", keytype);
|
||
|
+ return CKR_KEY_TYPE_INCONSISTENT;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+CK_RV ibm_pqc_priv_unwrap(TEMPLATE *tmpl, CK_KEY_TYPE keytype, CK_BYTE *data,
|
||
|
+ CK_ULONG total_length, CK_BBOOL add_value)
|
||
|
+{
|
||
|
+ switch (keytype) {
|
||
|
+ case CKK_IBM_PQC_DILITHIUM:
|
||
|
+ return ibm_dilithium_priv_unwrap(tmpl, data, total_length, add_value);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_priv_unwrap(tmpl, data, total_length, add_value);
|
||
|
+ default:
|
||
|
+ TRACE_DEVEL("Key type 0x%lx not supported.\n", keytype);
|
||
|
+ return CKR_KEY_TYPE_INCONSISTENT;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+CK_RV ibm_pqc_priv_unwrap_get_data(TEMPLATE *tmpl, CK_KEY_TYPE keytype,
|
||
|
+ CK_BYTE *data, CK_ULONG total_length,
|
||
|
+ CK_BBOOL add_value)
|
||
|
+{
|
||
|
+ switch (keytype) {
|
||
|
+ case CKK_IBM_PQC_DILITHIUM:
|
||
|
+ return ibm_dilithium_priv_unwrap_get_data(tmpl, data, total_length,
|
||
|
+ add_value);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_priv_unwrap_get_data(tmpl, data, total_length,
|
||
|
+ add_value);
|
||
|
+ default:
|
||
|
+ TRACE_DEVEL("Key type 0x%lx not supported.\n", keytype);
|
||
|
+ return CKR_KEY_TYPE_INCONSISTENT;
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
// dsa_publ_check_required_attributes()
|
||
|
//
|
||
|
CK_RV dsa_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
|
||
|
@@ -4987,6 +5227,152 @@ error:
|
||
|
return rc;
|
||
|
}
|
||
|
|
||
|
+// ibm_dilithium_publ_set_default_attributes()
|
||
|
+//
|
||
|
+CK_RV ibm_kyber_publ_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
|
||
|
+{
|
||
|
+ CK_ATTRIBUTE *type_attr = NULL;
|
||
|
+ CK_ATTRIBUTE *pk_attr = NULL;
|
||
|
+ CK_ATTRIBUTE *value_attr = NULL;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ publ_key_set_default_attributes(tmpl, mode);
|
||
|
+
|
||
|
+ type_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
|
||
|
+ pk_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
|
||
|
+ value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
|
||
|
+
|
||
|
+ if (!type_attr || !pk_attr ||!value_attr) {
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
||
|
+ rc = CKR_HOST_MEMORY;
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+
|
||
|
+ type_attr->type = CKA_KEY_TYPE;
|
||
|
+ type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
|
||
|
+ type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
|
||
|
+ *(CK_KEY_TYPE *) type_attr->pValue = CKK_IBM_PQC_KYBER;
|
||
|
+
|
||
|
+ pk_attr->type = CKA_IBM_KYBER_PK;
|
||
|
+ pk_attr->ulValueLen = 0;
|
||
|
+ pk_attr->pValue = NULL;
|
||
|
+
|
||
|
+ value_attr->type = CKA_VALUE;
|
||
|
+ value_attr->ulValueLen = 0;
|
||
|
+ value_attr->pValue = NULL;
|
||
|
+
|
||
|
+ rc = template_update_attribute(tmpl, type_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ type_attr = NULL;
|
||
|
+ rc = template_update_attribute(tmpl, pk_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ pk_attr = NULL;
|
||
|
+ rc = template_update_attribute(tmpl, value_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ value_attr = NULL;
|
||
|
+
|
||
|
+ return CKR_OK;
|
||
|
+
|
||
|
+error:
|
||
|
+ if (type_attr)
|
||
|
+ free(type_attr);
|
||
|
+ if (pk_attr)
|
||
|
+ free(pk_attr);
|
||
|
+ if (value_attr)
|
||
|
+ free(value_attr);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
+// ibm_dilithium_priv_set_default_attributes()
|
||
|
+//
|
||
|
+CK_RV ibm_kyber_priv_set_default_attributes(TEMPLATE *tmpl, CK_ULONG mode)
|
||
|
+{
|
||
|
+ CK_ATTRIBUTE *type_attr = NULL;
|
||
|
+ CK_ATTRIBUTE *sk_attr = NULL;
|
||
|
+ CK_ATTRIBUTE *pk_attr = NULL;
|
||
|
+ CK_ATTRIBUTE *value_attr = NULL;
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ priv_key_set_default_attributes(tmpl, mode);
|
||
|
+
|
||
|
+ type_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE) + sizeof(CK_KEY_TYPE));
|
||
|
+ sk_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
|
||
|
+ pk_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
|
||
|
+ value_attr = (CK_ATTRIBUTE *) malloc(sizeof(CK_ATTRIBUTE));
|
||
|
+
|
||
|
+ if (!type_attr || !sk_attr || !pk_attr || !value_attr) {
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_HOST_MEMORY));
|
||
|
+ rc = CKR_HOST_MEMORY;
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+
|
||
|
+ type_attr->type = CKA_KEY_TYPE;
|
||
|
+ type_attr->ulValueLen = sizeof(CK_KEY_TYPE);
|
||
|
+ type_attr->pValue = (CK_BYTE *) type_attr + sizeof(CK_ATTRIBUTE);
|
||
|
+ *(CK_KEY_TYPE *) type_attr->pValue = CKK_IBM_PQC_KYBER;
|
||
|
+
|
||
|
+ sk_attr->type = CKA_IBM_KYBER_SK;
|
||
|
+ sk_attr->ulValueLen = 0;
|
||
|
+ sk_attr->pValue = NULL;
|
||
|
+
|
||
|
+ pk_attr->type = CKA_IBM_KYBER_PK;
|
||
|
+ pk_attr->ulValueLen = 0;
|
||
|
+ pk_attr->pValue = NULL;
|
||
|
+
|
||
|
+ value_attr->type = CKA_VALUE;
|
||
|
+ value_attr->ulValueLen = 0;
|
||
|
+ value_attr->pValue = NULL;
|
||
|
+
|
||
|
+ rc = template_update_attribute(tmpl, type_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ type_attr = NULL;
|
||
|
+ rc = template_update_attribute(tmpl, sk_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ sk_attr = NULL;
|
||
|
+ rc = template_update_attribute(tmpl, pk_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ pk_attr = NULL;
|
||
|
+ rc = template_update_attribute(tmpl, value_attr);
|
||
|
+ if (rc != CKR_OK) {
|
||
|
+ TRACE_ERROR("template_update_attribute failed\n");
|
||
|
+ goto error;
|
||
|
+ }
|
||
|
+ value_attr = NULL;
|
||
|
+
|
||
|
+ return CKR_OK;
|
||
|
+
|
||
|
+error:
|
||
|
+ if (type_attr)
|
||
|
+ free(type_attr);
|
||
|
+ if (sk_attr)
|
||
|
+ free(sk_attr);
|
||
|
+ if (pk_attr)
|
||
|
+ free(pk_attr);
|
||
|
+ if (value_attr)
|
||
|
+ free(value_attr);
|
||
|
+
|
||
|
+ return rc;
|
||
|
+}
|
||
|
+
|
||
|
static CK_RV ibm_pqc_check_attributes(TEMPLATE *tmpl, CK_ULONG mode,
|
||
|
CK_MECHANISM_TYPE mech,
|
||
|
CK_ULONG *req_attrs,
|
||
|
@@ -5122,6 +5508,43 @@ CK_RV ibm_dilithium_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode
|
||
|
return priv_key_check_required_attributes(tmpl, mode);
|
||
|
}
|
||
|
|
||
|
+// ibm_kyber_publ_check_required_attributes()
|
||
|
+//
|
||
|
+CK_RV ibm_kyber_publ_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
|
||
|
+{
|
||
|
+ static CK_ULONG req_attrs[] = {
|
||
|
+ CKA_IBM_KYBER_PK,
|
||
|
+ };
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ rc = ibm_pqc_check_attributes(tmpl, mode, CKM_IBM_KYBER, req_attrs,
|
||
|
+ sizeof(req_attrs) / sizeof(req_attrs[0]));
|
||
|
+ if (rc != CKR_OK)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+ /* All required attrs found, check them */
|
||
|
+ return publ_key_check_required_attributes(tmpl, mode);
|
||
|
+}
|
||
|
+
|
||
|
+// ibm_kyber_priv_check_required_attributes()
|
||
|
+//
|
||
|
+CK_RV ibm_kyber_priv_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
|
||
|
+{
|
||
|
+ static CK_ULONG req_attrs[] = {
|
||
|
+ CKA_IBM_KYBER_SK,
|
||
|
+ CKA_IBM_KYBER_PK,
|
||
|
+ };
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ rc = ibm_pqc_check_attributes(tmpl, mode, CKM_IBM_KYBER, req_attrs,
|
||
|
+ sizeof(req_attrs) / sizeof(req_attrs[0]));
|
||
|
+ if (rc != CKR_OK)
|
||
|
+ return rc;
|
||
|
+
|
||
|
+ /* All required attrs found, check them */
|
||
|
+ return priv_key_check_required_attributes(tmpl, mode);
|
||
|
+}
|
||
|
+
|
||
|
static CK_RV ibm_pqc_validate_keyform_mode(CK_ATTRIBUTE *attr, CK_ULONG mode,
|
||
|
CK_MECHANISM_TYPE mech)
|
||
|
{
|
||
|
@@ -5228,6 +5651,59 @@ CK_RV ibm_dilithium_priv_validate_attribute(STDLL_TokData_t *tokdata,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
+// ibm_kyber_publ_validate_attribute()
|
||
|
+//
|
||
|
+CK_RV ibm_kyber_publ_validate_attribute(STDLL_TokData_t *tokdata,
|
||
|
+ TEMPLATE *tmpl, CK_ATTRIBUTE *attr,
|
||
|
+ CK_ULONG mode)
|
||
|
+{
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ switch (attr->type) {
|
||
|
+ case CKA_IBM_KYBER_KEYFORM:
|
||
|
+ case CKA_IBM_KYBER_MODE:
|
||
|
+ rc = ibm_pqc_validate_keyform_mode(attr, mode, CKM_IBM_KYBER);
|
||
|
+ if (rc != CKR_OK)
|
||
|
+ return rc;
|
||
|
+ return CKR_OK;
|
||
|
+ case CKA_IBM_KYBER_PK:
|
||
|
+ case CKA_VALUE:
|
||
|
+ if (mode == MODE_CREATE)
|
||
|
+ return CKR_OK;
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
|
||
|
+ return CKR_ATTRIBUTE_READ_ONLY;
|
||
|
+ default:
|
||
|
+ return publ_key_validate_attribute(tokdata, tmpl, attr, mode);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
+// ibm_kyber_priv_validate_attribute()
|
||
|
+//
|
||
|
+CK_RV ibm_kyber_priv_validate_attribute(STDLL_TokData_t *tokdata,
|
||
|
+ TEMPLATE *tmpl, CK_ATTRIBUTE *attr,
|
||
|
+ CK_ULONG mode)
|
||
|
+{
|
||
|
+ CK_RV rc;
|
||
|
+
|
||
|
+ switch (attr->type) {
|
||
|
+ case CKA_IBM_KYBER_KEYFORM:
|
||
|
+ case CKA_IBM_KYBER_MODE:
|
||
|
+ rc = ibm_pqc_validate_keyform_mode(attr, mode, CKM_IBM_KYBER);
|
||
|
+ if (rc != CKR_OK)
|
||
|
+ return rc;
|
||
|
+ return CKR_OK;
|
||
|
+ case CKA_IBM_KYBER_SK:
|
||
|
+ case CKA_IBM_KYBER_PK:
|
||
|
+ case CKA_VALUE:
|
||
|
+ if (mode == MODE_CREATE)
|
||
|
+ return CKR_OK;
|
||
|
+ TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_READ_ONLY));
|
||
|
+ return CKR_ATTRIBUTE_READ_ONLY;
|
||
|
+ default:
|
||
|
+ return priv_key_validate_attribute(tokdata, tmpl, attr, mode);
|
||
|
+ }
|
||
|
+}
|
||
|
+
|
||
|
// generic_secret_check_required_attributes()
|
||
|
//
|
||
|
CK_RV generic_secret_check_required_attributes(TEMPLATE *tmpl, CK_ULONG mode)
|
||
|
diff --git a/usr/lib/common/key_mgr.c b/usr/lib/common/key_mgr.c
|
||
|
index 01103dc2..8fcdc88e 100644
|
||
|
--- a/usr/lib/common/key_mgr.c
|
||
|
+++ b/usr/lib/common/key_mgr.c
|
||
|
@@ -1421,6 +1421,16 @@ CK_RV key_mgr_get_private_key_type(CK_BYTE *keydata,
|
||
|
return CKR_OK;
|
||
|
}
|
||
|
}
|
||
|
+ // Check only the OBJECT IDENTIFIERs for KYBER
|
||
|
+ //
|
||
|
+ for (i = 0; kyber_oids[i].oid != NULL; i++) {
|
||
|
+ if (alg_len == kyber_oids[i].oid_len + ber_NULLLen &&
|
||
|
+ memcmp(alg, kyber_oids[i].oid, kyber_oids[i].oid_len) == 0 &&
|
||
|
+ memcmp(alg + kyber_oids[i].oid_len, ber_NULL, ber_NULLLen) == 0) {
|
||
|
+ *keytype = CKK_IBM_PQC_KYBER;
|
||
|
+ return CKR_OK;
|
||
|
+ }
|
||
|
+ }
|
||
|
|
||
|
TRACE_ERROR("%s\n", ock_err(ERR_TEMPLATE_INCOMPLETE));
|
||
|
return CKR_TEMPLATE_INCOMPLETE;
|
||
|
diff --git a/usr/lib/common/mech_ec.c b/usr/lib/common/mech_ec.c
|
||
|
index 9df53b46..3a642f50 100644
|
||
|
--- a/usr/lib/common/mech_ec.c
|
||
|
+++ b/usr/lib/common/mech_ec.c
|
||
|
@@ -912,6 +912,9 @@ CK_RV pkcs_get_keytype(CK_ATTRIBUTE *attrs, CK_ULONG attrs_len,
|
||
|
case CKM_IBM_DILITHIUM:
|
||
|
*type = CKK_IBM_PQC_DILITHIUM;
|
||
|
break;
|
||
|
+ case CKM_IBM_KYBER:
|
||
|
+ *type = CKK_IBM_PQC_KYBER;
|
||
|
+ break;
|
||
|
default:
|
||
|
return CKR_MECHANISM_INVALID;
|
||
|
}
|
||
|
diff --git a/usr/lib/common/template.c b/usr/lib/common/template.c
|
||
|
index 3338e847..37831efc 100644
|
||
|
--- a/usr/lib/common/template.c
|
||
|
+++ b/usr/lib/common/template.c
|
||
|
@@ -164,6 +164,8 @@ CK_RV template_add_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl,
|
||
|
return dh_publ_set_default_attributes(tmpl, mode);
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
return ibm_dilithium_publ_set_default_attributes(tmpl, mode);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_publ_set_default_attributes(tmpl, mode);
|
||
|
default:
|
||
|
TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID),
|
||
|
subclass);
|
||
|
@@ -181,6 +183,8 @@ CK_RV template_add_default_attributes(TEMPLATE *tmpl, TEMPLATE *basetmpl,
|
||
|
return dh_priv_set_default_attributes(tmpl, mode);
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
return ibm_dilithium_priv_set_default_attributes(tmpl, mode);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_priv_set_default_attributes(tmpl, mode);
|
||
|
default:
|
||
|
TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID),
|
||
|
subclass);
|
||
|
@@ -409,6 +413,8 @@ CK_RV template_check_required_attributes(TEMPLATE *tmpl, CK_ULONG class,
|
||
|
return dh_publ_check_required_attributes(tmpl, mode);
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
return ibm_dilithium_publ_check_required_attributes(tmpl, mode);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_publ_check_required_attributes(tmpl, mode);
|
||
|
default:
|
||
|
TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID),
|
||
|
subclass);
|
||
|
@@ -426,6 +432,8 @@ CK_RV template_check_required_attributes(TEMPLATE *tmpl, CK_ULONG class,
|
||
|
return dh_priv_check_required_attributes(tmpl, mode);
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
return ibm_dilithium_priv_check_required_attributes(tmpl, mode);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_priv_check_required_attributes(tmpl, mode);
|
||
|
default:
|
||
|
TRACE_ERROR("%s: %lx\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID),
|
||
|
subclass);
|
||
|
@@ -1642,6 +1650,8 @@ CK_RV template_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
|
||
|
return dh_publ_validate_attribute(tokdata, tmpl, attr, mode);
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
return ibm_dilithium_publ_validate_attribute(tokdata, tmpl, attr, mode);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_publ_validate_attribute(tokdata, tmpl, attr, mode);
|
||
|
default:
|
||
|
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
|
||
|
return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type
|
||
|
@@ -1658,6 +1668,8 @@ CK_RV template_validate_attribute(STDLL_TokData_t *tokdata, TEMPLATE *tmpl,
|
||
|
return dh_priv_validate_attribute(tokdata, tmpl, attr, mode);
|
||
|
case CKK_IBM_PQC_DILITHIUM:
|
||
|
return ibm_dilithium_priv_validate_attribute(tokdata, tmpl, attr, mode);
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ return ibm_kyber_priv_validate_attribute(tokdata, tmpl, attr, mode);
|
||
|
default:
|
||
|
TRACE_ERROR("%s\n", ock_err(ERR_ATTRIBUTE_VALUE_INVALID));
|
||
|
return CKR_ATTRIBUTE_VALUE_INVALID; // unknown key type
|
||
|
diff --git a/usr/lib/ep11_stdll/ep11_specific.c b/usr/lib/ep11_stdll/ep11_specific.c
|
||
|
index 479951cb..44796dba 100644
|
||
|
--- a/usr/lib/ep11_stdll/ep11_specific.c
|
||
|
+++ b/usr/lib/ep11_stdll/ep11_specific.c
|
||
|
@@ -362,6 +362,13 @@ static const version_req_t ibm_dilithium_req_versions[] = {
|
||
|
};
|
||
|
#define NUM_DILITHIUM_REQ (sizeof(ibm_dilithium_req_versions) / sizeof(version_req_t))
|
||
|
|
||
|
+static const CK_VERSION ibm_cex8p_kyber_support = { .major = 8, .minor = 9 };
|
||
|
+
|
||
|
+static const version_req_t ibm_kyber_req_versions[] = {
|
||
|
+ { .card_type = 8, .min_firmware_version = &ibm_cex8p_kyber_support }
|
||
|
+};
|
||
|
+#define NUM_KYBER_REQ (sizeof(ibm_kyber_req_versions) / sizeof(version_req_t))
|
||
|
+
|
||
|
static const CK_VERSION ibm_cex6p_reencrypt_single_support =
|
||
|
{ .major = 6, .minor = 15 };
|
||
|
static const CK_VERSION ibm_cex7p_reencrypt_single_support =
|
||
|
@@ -1809,7 +1816,8 @@ static CK_RV check_key_attributes(STDLL_TokData_t * tokdata,
|
||
|
check_types = &check_types_pub[0];
|
||
|
attr_cnt = sizeof(check_types_pub) / sizeof(CK_ULONG);
|
||
|
}
|
||
|
- /* do nothing for CKM_DH_PKCS_KEY_PAIR_GEN and CKK_IBM_PQC_DILITHIUM */
|
||
|
+ /* do nothing for CKM_DH_PKCS_KEY_PAIR_GEN, CKK_IBM_PQC_DILITHIUM,
|
||
|
+ and CKK_IBM_PQC_KYBER */
|
||
|
break;
|
||
|
case CKO_PRIVATE_KEY:
|
||
|
if ((kt == CKK_EC) || (kt == CKK_ECDSA) || (kt == CKK_DSA)) {
|
||
|
@@ -1824,7 +1832,7 @@ static CK_RV check_key_attributes(STDLL_TokData_t * tokdata,
|
||
|
check_types = &check_types_derive[0];
|
||
|
attr_cnt = sizeof(check_types_derive) / sizeof(CK_ULONG);
|
||
|
}
|
||
|
- /* Do nothing for CKK_IBM_PQC_DILITHIUM */
|
||
|
+ /* Do nothing for CKK_IBM_PQC_DILITHIUM and CKK_IBM_PQC_KYBER */
|
||
|
break;
|
||
|
default:
|
||
|
return CKR_OK;
|
||
|
@@ -2029,6 +2037,13 @@ static CK_BBOOL attr_applicable_for_ep11(STDLL_TokData_t * tokdata,
|
||
|
attr->type == CKA_IBM_DILITHIUM_MODE)
|
||
|
return CK_FALSE;
|
||
|
break;
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ if (attr->type == CKA_SIGN || attr->type == CKA_VERIFY ||
|
||
|
+ attr->type == CKA_WRAP || attr->type == CKA_UNWRAP ||
|
||
|
+ attr->type == CKA_IBM_KYBER_KEYFORM ||
|
||
|
+ attr->type == CKA_IBM_KYBER_MODE)
|
||
|
+ return CK_FALSE;
|
||
|
+ break;
|
||
|
default:
|
||
|
break;
|
||
|
}
|
||
|
@@ -9145,6 +9160,10 @@ CK_RV ep11tok_unwrap_key(STDLL_TokData_t * tokdata, SESSION * session,
|
||
|
rc = ibm_dilithium_priv_unwrap_get_data(key_obj->template,
|
||
|
csum, cslen, FALSE);
|
||
|
break;
|
||
|
+ case CKK_IBM_PQC_KYBER:
|
||
|
+ rc = ibm_kyber_priv_unwrap_get_data(key_obj->template,
|
||
|
+ csum, cslen, FALSE);
|
||
|
+ break;
|
||
|
}
|
||
|
|
||
|
if (rc != 0) {
|
||
|
@@ -9240,6 +9259,7 @@ static const CK_MECHANISM_TYPE ep11_supported_mech_list[] = {
|
||
|
CKM_IBM_EC_X448,
|
||
|
CKM_IBM_ED25519_SHA512,
|
||
|
CKM_IBM_ED448_SHA3,
|
||
|
+ CKM_IBM_KYBER,
|
||
|
CKM_IBM_SHA3_224,
|
||
|
CKM_IBM_SHA3_224_HMAC,
|
||
|
CKM_IBM_SHA3_256,
|
||
|
@@ -9478,6 +9498,7 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
|
||
|
CK_VERSION ver1_3 = { .major = 1, .minor = 3 };
|
||
|
CK_VERSION ver3 = { .major = 3, .minor = 0 };
|
||
|
CK_VERSION ver3_1 = { .major = 3, .minor = 0x10 };
|
||
|
+ CK_VERSION ver4 = { .major = 4, .minor = 0 };
|
||
|
CK_BBOOL found = FALSE;
|
||
|
CK_ULONG i;
|
||
|
int status;
|
||
|
@@ -9630,6 +9651,23 @@ CK_RV ep11tok_is_mechanism_supported(STDLL_TokData_t *tokdata,
|
||
|
}
|
||
|
break;
|
||
|
|
||
|
+ case CKM_IBM_KYBER:
|
||
|
+ if (compare_ck_version(&ep11_data->ep11_lib_version, &ver4) < 0) {
|
||
|
+ TRACE_INFO("%s Mech '%s' banned due to host library version\n",
|
||
|
+ __func__, ep11_get_ckm(tokdata, type));
|
||
|
+ rc = CKR_MECHANISM_INVALID;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ status = check_required_versions(tokdata, ibm_kyber_req_versions,
|
||
|
+ NUM_KYBER_REQ);
|
||
|
+ if (status != 1) {
|
||
|
+ TRACE_INFO("%s Mech '%s' banned due to mixed firmware versions\n",
|
||
|
+ __func__, ep11_get_ckm(tokdata, type));
|
||
|
+ rc = CKR_MECHANISM_INVALID;
|
||
|
+ goto out;
|
||
|
+ }
|
||
|
+ break;
|
||
|
+
|
||
|
case CKM_IBM_CPACF_WRAP:
|
||
|
if (compare_ck_version(&ep11_data->ep11_lib_version, &ver3) <= 0) {
|
||
|
TRACE_INFO("%s Mech '%s' banned due to host library version\n",
|
||
|
diff --git a/usr/lib/ep11_stdll/ep11cpfilter.conf b/usr/lib/ep11_stdll/ep11cpfilter.conf
|
||
|
index 9d6a2fc8..4353ec53 100644
|
||
|
--- a/usr/lib/ep11_stdll/ep11cpfilter.conf
|
||
|
+++ b/usr/lib/ep11_stdll/ep11cpfilter.conf
|
||
|
@@ -73,7 +73,7 @@ XCP_CPB_ALG_EC_25519: CKM_IBM_EC_X25519, CKM_IBM_ED25519_SHA512, CKM_IBM_EC_X448
|
||
|
XCP_CPB_ALG_NBSI2017: CKM_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA224_RSA_PKCS, CKM_SHA256_RSA_PKCS, CKM_SHA384_RSA_PKCS, CKM_SHA512_RSA_PKCS
|
||
|
|
||
|
#enable support of Dilithium
|
||
|
-XCP_CPB_ALG_PQC: CKM_IBM_DILITHIUM
|
||
|
+XCP_CPB_ALG_PQC: CKM_IBM_DILITHIUM, CKM_IBM_KYBER
|
||
|
|
||
|
# enable BTC-related functionality
|
||
|
XCP_CPB_BTC: CKM_IBM_BTC_DERIVE
|
||
|
--
|
||
|
2.16.2.windows.1
|
||
|
|