Blame SOURCES/0028-POLICY-STATISTICS-Check-for-Kyber-KEM-KDFs-and-count.patch

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