opencryptoki/SOURCES/0025-COMMON-EP11-Add-Kyber-...

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, &param, &param_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