From 181b11362e95ff8ac4e812073c8f7267a02f1bf1 Mon Sep 17 00:00:00 2001 From: Ingo Franzki Date: Wed, 2 Mar 2022 16:44:27 +0100 Subject: [PATCH 28/34] POLICY/STATISTICS: Check for Kyber KEM KDFs and count KDF digest usage Signed-off-by: Ingo Franzki --- man/man5/policy.conf.5.in | 2 +- tools/policyexamplegen.c | 8 ++++++- usr/lib/api/policy.c | 45 ++++++++++++++++++++++++++++++++++++---- usr/lib/api/statistics.c | 20 +++++++++++++++++- usr/lib/common/kdf_translation.c | 30 +++++++++++++++++++++++++++ usr/lib/common/utility_common.c | 5 +++++ 6 files changed, 103 insertions(+), 7 deletions(-) diff --git a/man/man5/policy.conf.5.in b/man/man5/policy.conf.5.in index 0b8bed27..c04b2adf 100644 --- a/man/man5/policy.conf.5.in +++ b/man/man5/policy.conf.5.in @@ -133,7 +133,7 @@ empty list allows no MGF. .BR allowedkdfs This key specifies the allowed Key Derivation Functions (KDFs) for use -in ECDH key derivation. The value is a list of +in ECDH key derivation and Kyber KEM. The value is a list of .BR CKD_ constants supported by openCryptoki. This list has the same format as the diff --git a/tools/policyexamplegen.c b/tools/policyexamplegen.c index 1649fc05..362acdf9 100644 --- a/tools/policyexamplegen.c +++ b/tools/policyexamplegen.c @@ -99,7 +99,13 @@ int main(void) puts(" CKD_SHA224_KDF,"); puts(" CKD_SHA256_KDF,"); puts(" CKD_SHA384_KDF,"); - puts(" CKD_SHA512_KDF"); + puts(" CKD_SHA512_KDF,"); + puts(" CKD_IBM_HYBRID_NULL,"); + puts(" CKD_IBM_HYBRID_SHA1_KDF,"); + puts(" CKD_IBM_HYBRID_SHA224_KDF,"); + puts(" CKD_IBM_HYBRID_SHA256_KDF,"); + puts(" CKD_IBM_HYBRID_SHA384_KDF,"); + puts(" CKD_IBM_HYBRID_SHA512_KDF"); puts(" # No comma after last element!"); puts(")"); puts(""); diff --git a/usr/lib/api/policy.c b/usr/lib/api/policy.c index b513a8a9..8189dab0 100644 --- a/usr/lib/api/policy.c +++ b/usr/lib/api/policy.c @@ -70,6 +70,7 @@ struct policy_private { CK_ULONG allowedmgfs; CK_ULONG allowedvendormgfs; CK_ULONG allowedkdfs; + CK_ULONG allowedvendorkdfs; CK_ULONG allowedprfs; CK_ULONG maxcurvesize; /* Strength struct ordered from highest to lowest. */ @@ -105,6 +106,7 @@ void policy_private_deactivate(struct policy_private *pp) pp->allowedmgfs = ~0lu; pp->allowedvendormgfs = ~0lu; pp->allowedkdfs = ~0lu; + pp->allowedvendorkdfs = ~0lu; pp->allowedprfs = ~0lu; pp->maxcurvesize = 521u; } @@ -496,8 +498,14 @@ static inline CK_RV policy_is_mgf_allowed(struct policy_private *pp, static inline CK_RV policy_is_kdf_allowed(struct policy_private *pp, CK_ULONG kdf) { - if (pp->allowedkdfs & (1u << kdf)) - return CKR_OK; + if (kdf > CKD_VENDOR_DEFINED) { + if ((kdf - CKD_VENDOR_DEFINED - 1) <= 31 && + (pp->allowedvendorkdfs & (1u << (kdf - CKD_VENDOR_DEFINED - 1)))) + return CKR_OK; + } else { + if (kdf <= 31 && (pp->allowedkdfs & (1u << kdf))) + return CKR_OK; + } TRACE_WARNING("POLICY VIOLATION: kdf not allowed: 0x%lx\n", kdf); return CKR_FUNCTION_FAILED; } @@ -920,6 +928,16 @@ static CK_RV policy_is_mech_allowed(policy_t p, CK_MECHANISM_PTR mech, break; } break; + case CKM_IBM_KYBER: + /* Only KEM uses a parameter, KeyGen, Encrypt/Decrypt don't */ + if (mech->ulParameterLen != sizeof(CK_IBM_KYBER_PARAMS)) + break; + if (policy_is_kdf_allowed(pp, + ((CK_IBM_KYBER_PARAMS *)mech->pParameter)->kdf) != CKR_OK) { + rv = CKR_FUNCTION_FAILED; + break; + } + break; default: break; } @@ -1533,7 +1551,7 @@ static CK_RV policy_parse_kdfs(struct policy_private *pp, struct ConfigBaseNode *list) { struct ConfigBaseNode *i; - CK_ULONG kdfs = 0, kdf; + CK_ULONG kdfs = 0, vkdfs = 0, kdf; CK_RV rc = CKR_OK; int f; @@ -1545,10 +1563,28 @@ static CK_RV policy_parse_kdfs(struct policy_private *pp, i->key, i->line); break; } - kdfs |= (1u << kdf); + + if (kdf >= CKD_VENDOR_DEFINED) { + if ((kdf - CKD_VENDOR_DEFINED - 1) > 31) { + TRACE_ERROR("POLICY: KDF invalid: \"%s\" (line %hd)\n", + i->key, i->line); + rc = CKR_FUNCTION_FAILED; + break; + } + vkdfs |= (1u << (kdf - CKD_VENDOR_DEFINED - 1)); + } else { + if (kdf > 31) { + TRACE_ERROR("POLICY: KDF invalid: \"%s\" (line %hd)\n", + i->key, i->line); + rc = CKR_FUNCTION_FAILED; + break; + } + kdfs |= (1u << kdf); + } } } pp->allowedkdfs = kdfs; + pp->allowedvendorkdfs = vkdfs; return rc; } @@ -1742,6 +1778,7 @@ CK_RV policy_load_policy_cfg(struct policy_private *pp, if (!allowedkdfs) { TRACE_DEVEL("POLICY: No KDF restrictions\n"); pp->allowedkdfs = ~0u; + pp->allowedvendorkdfs = ~0u; } else if (!confignode_hastype(allowedkdfs, CT_BARELIST)) { TRACE_ERROR("POLICY: allowedkdfs has wrong type!\n"); OCK_SYSLOG(LOG_ERR, "POLICY: allowedkdfs has wrong type!\n"); diff --git a/usr/lib/api/statistics.c b/usr/lib/api/statistics.c index 0830bbeb..e34dfcee 100644 --- a/usr/lib/api/statistics.c +++ b/usr/lib/api/statistics.c @@ -110,7 +110,8 @@ static CK_RV statistics_increment(struct statistics *statistics, if (mech->pParameter == NULL || mech->ulParameterLen != sizeof(CK_ECDH1_DERIVE_PARAMS)) return CKR_MECHANISM_PARAM_INVALID; - if (((CK_ECDH1_DERIVE_PARAMS *)mech->pParameter)->kdf == CKD_NULL) + if (((CK_ECDH1_DERIVE_PARAMS *)mech->pParameter)->kdf == CKD_NULL || + ((CK_ECDH1_DERIVE_PARAMS *)mech->pParameter)->kdf == CKD_IBM_HYBRID_NULL) break; rc = digest_from_kdf(((CK_ECDH1_DERIVE_PARAMS *)mech->pParameter)->kdf, &implicit_mech.mechanism); @@ -156,6 +157,23 @@ static CK_RV statistics_increment(struct statistics *statistics, break; } break; + case CKM_IBM_KYBER: + /* Only KEM uses a parameter, KeyGen, Encrypt/Decrypt don't */ + if (mech->ulParameterLen != sizeof(CK_IBM_KYBER_PARAMS)) + break; + if (((CK_IBM_KYBER_PARAMS *)mech->pParameter)->kdf == CKD_NULL || + ((CK_IBM_KYBER_PARAMS *)mech->pParameter)->kdf == CKD_IBM_HYBRID_NULL) + break; + rc = digest_from_kdf(((CK_IBM_KYBER_PARAMS *)mech->pParameter)->kdf, + &implicit_mech.mechanism); + if (rc != CKR_OK) + return rc; + rc = statistics_increment(statistics, slot, &implicit_mech, + POLICY_STRENGTH_IDX_0); + if (rc != CKR_OK) + return rc; + break; + default: break; } diff --git a/usr/lib/common/kdf_translation.c b/usr/lib/common/kdf_translation.c index 707cb912..f563234f 100644 --- a/usr/lib/common/kdf_translation.c +++ b/usr/lib/common/kdf_translation.c @@ -55,6 +55,36 @@ CK_RV translate_string_to_kdf(const char *str, size_t len, CK_ULONG* kdf) return CKR_OK; } return CKR_FUNCTION_FAILED; + case 19: + if (strcmp("CKD_IBM_HYBRID_NULL", str) == 0) { + *kdf = CKD_IBM_HYBRID_NULL; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + case 23: + if (strcmp("CKD_IBM_HYBRID_SHA1_KDF", str) == 0) { + *kdf = CKD_IBM_HYBRID_SHA1_KDF; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; + case 25: + if (strcmp("CKD_IBM_HYBRID_SHA224_KDF", str) == 0) { + *kdf = CKD_IBM_HYBRID_SHA224_KDF; + return CKR_OK; + } + if (strcmp("CKD_IBM_HYBRID_SHA256_KDF", str) == 0) { + *kdf = CKD_IBM_HYBRID_SHA256_KDF; + return CKR_OK; + } + if (strcmp("CKD_IBM_HYBRID_SHA384_KDF", str) == 0) { + *kdf = CKD_IBM_HYBRID_SHA384_KDF; + return CKR_OK; + } + if (strcmp("CKD_IBM_HYBRID_SHA512_KDF", str) == 0) { + *kdf = CKD_IBM_HYBRID_SHA512_KDF; + return CKR_OK; + } + return CKR_FUNCTION_FAILED; default: return CKR_FUNCTION_FAILED; } diff --git a/usr/lib/common/utility_common.c b/usr/lib/common/utility_common.c index 8d03c699..49ab609f 100644 --- a/usr/lib/common/utility_common.c +++ b/usr/lib/common/utility_common.c @@ -169,18 +169,23 @@ CK_RV digest_from_kdf(CK_EC_KDF_TYPE kdf, CK_MECHANISM_TYPE *mech) { switch (kdf) { case CKD_SHA1_KDF: + case CKD_IBM_HYBRID_SHA1_KDF: *mech = CKM_SHA_1; break; case CKD_SHA224_KDF: + case CKD_IBM_HYBRID_SHA224_KDF: *mech = CKM_SHA224; break; case CKD_SHA256_KDF: + case CKD_IBM_HYBRID_SHA256_KDF: *mech = CKM_SHA256; break; case CKD_SHA384_KDF: + case CKD_IBM_HYBRID_SHA384_KDF: *mech = CKM_SHA384; break; case CKD_SHA512_KDF: + case CKD_IBM_HYBRID_SHA512_KDF: *mech = CKM_SHA512; break; default: -- 2.16.2.windows.1