]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
pk: plumb ML-KEM 768 in addition to Kyber 768
authorDaiki Ueno <ueno@gnu.org>
Mon, 7 Oct 2024 21:34:16 +0000 (06:34 +0900)
committerDaiki Ueno <ueno@gnu.org>
Tue, 29 Oct 2024 12:37:32 +0000 (21:37 +0900)
This adds GNUTLS_PK_MLKEM768 in the regular algorithm range, while
keeping GNUTLS_PK_EXP_KYBER768 in the experimental algorithm range.
This also modifies the privkey-keygen test to skip unsupported
algorithms at run-time.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
lib/algorithms/publickey.c
lib/includes/gnutls/gnutls.h.in
lib/nettle/pk.c
tests/privkey-keygen.c

index 10938bce0e8baabdf4f06b792d946da0c0c3bbd9..15f77f70c5a6027ed1d4cdd02448b4da8013c99c 100644 (file)
@@ -202,6 +202,12 @@ static const gnutls_pk_entry pk_algorithms[] = {
          .oid = ECDH_X448_OID,
          .id = GNUTLS_PK_ECDH_X448,
          .curve = GNUTLS_ECC_CURVE_X448 },
+       { .name = "ML-KEM-768",
+         .oid = NULL,
+         .id = GNUTLS_PK_MLKEM768,
+         .curve = GNUTLS_ECC_CURVE_INVALID },
+/* Hidden behind HAVE_LIBOQS as it will be removed in the future.
+        */
 #ifdef HAVE_LIBOQS
        { .name = "KYBER768",
          .oid = NULL,
index 790406e4df82410c0a81266e362c6f80e4e544f5..02794ee61c5f127324c7d607bf23911911932465 100644 (file)
@@ -908,11 +908,12 @@ typedef enum {
        GNUTLS_PK_ECDH_X448 = 11,
        GNUTLS_PK_EDDSA_ED448 = 12,
        GNUTLS_PK_RSA_OAEP = 13,
-       GNUTLS_PK_MAX = GNUTLS_PK_RSA_OAEP,
+       GNUTLS_PK_MLKEM768 = 14,
+       GNUTLS_PK_MAX = GNUTLS_PK_MLKEM768,
 
        /* Experimental algorithms */
-       GNUTLS_PK_EXP_MIN = 256,
-       GNUTLS_PK_EXP_KYBER768 = GNUTLS_PK_EXP_MIN,
+       GNUTLS_PK_EXP_KYBER768 = 256,
+       GNUTLS_PK_EXP_MIN = GNUTLS_PK_EXP_KYBER768,
        GNUTLS_PK_EXP_MAX = GNUTLS_PK_EXP_KYBER768
 } gnutls_pk_algorithm_t;
 
index cccad6f7d41708a24823a14aba25d53c9b0ed308..755305373fc587500c5c0ba6646827457f6c7596 100644 (file)
@@ -691,6 +691,21 @@ cleanup:
        return ret;
 }
 
+#ifdef HAVE_LIBOQS
+static const char *pk_to_liboqs_algo(gnutls_pk_algorithm_t algo)
+{
+       switch (algo) {
+       case GNUTLS_PK_MLKEM768:
+               return OQS_KEM_alg_ml_kem_768;
+       case GNUTLS_PK_EXP_KYBER768:
+               return OQS_KEM_alg_kyber_768;
+       default:
+               gnutls_assert();
+               return NULL;
+       }
+}
+#endif
+
 static int _wrap_nettle_pk_encaps(gnutls_pk_algorithm_t algo,
                                  gnutls_datum_t *ciphertext,
                                  gnutls_datum_t *shared_secret,
@@ -700,16 +715,21 @@ static int _wrap_nettle_pk_encaps(gnutls_pk_algorithm_t algo,
 
        switch (algo) {
 #ifdef HAVE_LIBOQS
+       case GNUTLS_PK_MLKEM768:
        case GNUTLS_PK_EXP_KYBER768: {
                OQS_KEM *kem = NULL;
+               const char *algo_name;
                OQS_STATUS rc;
 
-               if (_gnutls_liboqs_ensure() < 0 ||
-                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(
-                           OQS_KEM_alg_kyber_768))
+               if (_gnutls_liboqs_ensure() < 0)
+                       return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+
+               algo_name = pk_to_liboqs_algo(algo);
+               if (algo_name == NULL ||
+                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(algo_name))
                        return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
 
-               kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768);
+               kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(algo_name);
                if (kem == NULL)
                        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
@@ -763,16 +783,21 @@ static int _wrap_nettle_pk_decaps(gnutls_pk_algorithm_t algo,
 
        switch (algo) {
 #ifdef HAVE_LIBOQS
+       case GNUTLS_PK_MLKEM768:
        case GNUTLS_PK_EXP_KYBER768: {
                OQS_KEM *kem = NULL;
+               const char *algo_name;
                OQS_STATUS rc;
 
-               if (_gnutls_liboqs_ensure() < 0 ||
-                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(
-                           OQS_KEM_alg_kyber_768))
+               if (_gnutls_liboqs_ensure() < 0)
+                       return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+
+               algo_name = pk_to_liboqs_algo(algo);
+               if (algo_name == NULL ||
+                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(algo_name))
                        return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
 
-               kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768);
+               kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(algo_name);
                if (kem == NULL)
                        return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
 
@@ -2362,10 +2387,17 @@ static int _wrap_nettle_pk_exists(gnutls_pk_algorithm_t pk)
        case GNUTLS_PK_EDDSA_ED448:
                return 1;
 #ifdef HAVE_LIBOQS
-       case GNUTLS_PK_EXP_KYBER768:
-               return _gnutls_liboqs_ensure() == 0 &&
-                      GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(
-                              OQS_KEM_alg_kyber_768);
+       case GNUTLS_PK_MLKEM768:
+       case GNUTLS_PK_EXP_KYBER768: {
+               const char *algo_name;
+
+               if (_gnutls_liboqs_ensure() < 0)
+                       return 0;
+
+               algo_name = pk_to_liboqs_algo(pk);
+               return algo_name != NULL &&
+                      GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(algo_name);
+       }
 #endif
        default:
                return 0;
@@ -2577,6 +2609,7 @@ static int wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo,
        case GNUTLS_PK_GOST_12_256:
        case GNUTLS_PK_GOST_12_512:
 #endif
+       case GNUTLS_PK_MLKEM768:
                break;
        default:
                gnutls_assert();
@@ -3002,15 +3035,24 @@ static int pct_test(gnutls_pk_algorithm_t algo,
        case GNUTLS_PK_ECDH_X448:
                break;
 #ifdef HAVE_LIBOQS
-       case GNUTLS_PK_EXP_KYBER768:
-               if (_gnutls_liboqs_ensure() < 0 ||
-                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(
-                           OQS_KEM_alg_kyber_768)) {
+       case GNUTLS_PK_MLKEM768:
+       case GNUTLS_PK_EXP_KYBER768: {
+               const char *algo_name;
+
+               if (_gnutls_liboqs_ensure() < 0) {
+                       ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+                       goto cleanup;
+               }
+
+               algo_name = pk_to_liboqs_algo(algo);
+               if (algo_name == NULL ||
+                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(algo_name)) {
                        ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
                        goto cleanup;
                }
+       }
 #endif
-               break;
+       break;
        default:
                ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
                goto cleanup;
@@ -3740,20 +3782,27 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
                break;
        }
 #ifdef HAVE_LIBOQS
+       case GNUTLS_PK_MLKEM768:
        case GNUTLS_PK_EXP_KYBER768: {
                OQS_KEM *kem = NULL;
+               const char *algo_name;
                OQS_STATUS rc;
 
-               if (_gnutls_liboqs_ensure() < 0 ||
-                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(
-                           OQS_KEM_alg_kyber_768)) {
+               if (_gnutls_liboqs_ensure() < 0) {
+                       ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+                       goto cleanup;
+               }
+
+               algo_name = pk_to_liboqs_algo(algo);
+               if (algo_name == NULL ||
+                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(algo_name)) {
                        ret = gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
                        goto cleanup;
                }
 
                not_approved = true;
 
-               kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(OQS_KEM_alg_kyber_768);
+               kem = GNUTLS_OQS_FUNC(OQS_KEM_new)(algo_name);
                if (kem == NULL) {
                        ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
                        goto cleanup;
@@ -4045,14 +4094,21 @@ static int wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo,
                break;
        }
 #ifdef HAVE_LIBOQS
-       case GNUTLS_PK_EXP_KYBER768:
-               if (_gnutls_liboqs_ensure() < 0 ||
-                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(
-                           OQS_KEM_alg_kyber_768))
+       case GNUTLS_PK_MLKEM768:
+       case GNUTLS_PK_EXP_KYBER768: {
+               const char *algo_name;
+
+               if (_gnutls_liboqs_ensure() < 0)
+                       return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+
+               algo_name = pk_to_liboqs_algo(algo);
+               if (algo_name == NULL ||
+                   !GNUTLS_OQS_FUNC(OQS_KEM_alg_is_enabled)(algo_name))
                        return gnutls_assert_val(GNUTLS_E_UNKNOWN_PK_ALGORITHM);
 
                ret = 0;
                break;
+       }
 #endif
 #if ENABLE_GOST
        case GNUTLS_PK_GOST_01:
index 6003430de3946c75980c7b2094f5cbc6fa8c3a59..1eea0a473cd182ad38ec3d0f83498f81a3be7cdf 100644 (file)
@@ -24,6 +24,7 @@
 #include "config.h"
 #endif
 
+#include <stdbool.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
@@ -103,19 +104,31 @@ static void sign_verify_data(gnutls_pk_algorithm_t algorithm,
        gnutls_free(signature.data);
 }
 
-static unsigned int is_approved_pk_algo(gnutls_pk_algorithm_t algo)
+static bool is_approved_pk_algo(gnutls_pk_algorithm_t algo)
 {
        switch (algo) {
        case GNUTLS_PK_RSA:
        case GNUTLS_PK_RSA_PSS:
        case GNUTLS_PK_RSA_OAEP:
        case GNUTLS_PK_EC:
-               return 1;
+               return true;
        default:
-               return 0;
+               return false;
        }
 }
 
+static bool is_supported_pk_algo(gnutls_pk_algorithm_t algo)
+{
+       const gnutls_pk_algorithm_t *p;
+
+       for (p = gnutls_pk_list(); *p != GNUTLS_PK_UNKNOWN; p++) {
+               if (*p == algo)
+                       return true;
+       }
+
+       return false;
+}
+
 void doit(void)
 {
        gnutls_x509_privkey_t pkey, dst;
@@ -138,12 +151,16 @@ void doit(void)
        for (i = 0; i < MAX_TRIES; i++) {
                for (algorithm = GNUTLS_PK_RSA; algorithm <= GNUTLS_PK_MAX;
                     algorithm++) {
+                       if (!is_supported_pk_algo(algorithm))
+                               continue;
+
                        if (algorithm == GNUTLS_PK_DH ||
 #ifndef ENABLE_DSA
                            algorithm == GNUTLS_PK_DSA ||
 #endif
                            algorithm == GNUTLS_PK_ECDH_X25519 ||
-                           algorithm == GNUTLS_PK_ECDH_X448)
+                           algorithm == GNUTLS_PK_ECDH_X448 ||
+                           algorithm == GNUTLS_PK_MLKEM768)
                                continue;
 
                        if (algorithm == GNUTLS_PK_GOST_01 ||