]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
Add experimental support for post-quantum digital signature algorithms in X.509 certi...
authord-Dudas <david.dudas03@e-uvt.ro>
Sun, 28 Jul 2024 21:00:40 +0000 (00:00 +0300)
committerd-Dudas <david.dudas03@e-uvt.ro>
Fri, 15 Nov 2024 18:03:21 +0000 (20:03 +0200)
- Dilithium
- Falcon
- Sphincs family

Signed-off-by: David Dudas <david.dudas03@e-uvt.ro>
20 files changed:
doc/Makefile.am
lib/algorithms.h
lib/algorithms/publickey.c
lib/algorithms/secparams.c
lib/algorithms/sign.c
lib/crypto-backend.h
lib/dlwrap/oqsfuncs.h
lib/gnutls.asn
lib/includes/gnutls/gnutls.h.in
lib/nettle/pk.c
lib/privkey.c
lib/pubkey.c
lib/x509/common.h
lib/x509/key_decode.c
lib/x509/key_encode.c
lib/x509/mpi.c
lib/x509/privkey.c
lib/x509/privkey_pkcs8.c
lib/x509/x509_int.h
tests/privkey-keygen.c

index af7431961c22ff78401205e9a5f88569e8f2b48b..64fde86542220a6220e4735f1347c71285fb8fc9 100644 (file)
@@ -567,7 +567,6 @@ ENUMS += enums/gnutls_ocsp_verify_reason_t
 ENUMS += enums/gnutls_openpgp_crt_status_t
 ENUMS += enums/gnutls_params_type_t
 ENUMS += enums/gnutls_pin_flag_t
-ENUMS += enums/gnutls_pk_algorithm_t
 ENUMS += enums/gnutls_pkcs11_obj_flags
 ENUMS += enums/gnutls_pkcs11_obj_info_t
 ENUMS += enums/gnutls_pkcs11_obj_type_t
@@ -587,7 +586,6 @@ ENUMS += enums/gnutls_rnd_level_t
 ENUMS += enums/gnutls_sec_param_t
 ENUMS += enums/gnutls_server_name_type_t
 ENUMS += enums/gnutls_session_flags_t
-ENUMS += enums/gnutls_sign_algorithm_t
 ENUMS += enums/gnutls_srtp_profile_t
 ENUMS += enums/gnutls_supplemental_data_format_type_t
 ENUMS += enums/gnutls_tpmkey_fmt_t
index 2e1b694c64dd1aa7be3e9d1bb92b961d253eb9a4..383b6da6095514c7ac64e17352de7e0336388a0d 100644 (file)
 #define IS_KEM(x) \
        (((x) == GNUTLS_PK_MLKEM768) || ((x) == GNUTLS_PK_EXP_KYBER768))
 
+#ifdef HAVE_LIBOQS
+#define IS_DILITHIUM(x)                       \
+       (((x) == GNUTLS_PK_EXP_DILITHIUM2) || \
+        ((x) == GNUTLS_PK_EXP_DILITHIUM3) || \
+        ((x) == GNUTLS_PK_EXP_DILITHIUM5))
+
+#define IS_FALCON(x) \
+       (((x) == GNUTLS_PK_EXP_FALCON512) || ((x) == GNUTLS_PK_EXP_FALCON1024))
+
+#define IS_SIMPLE_SPHINCS(x)                          \
+       (((x) == GNUTLS_PK_EXP_SPHINCS_SHA2_128S) ||  \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHA2_192S) ||  \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHA2_256S) ||  \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHAKE_128S) || \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHAKE_192S) || \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHAKE_256S))
+
+#define IS_FAST_SPHINCS(x)                            \
+       (((x) == GNUTLS_PK_EXP_SPHINCS_SHA2_128F) ||  \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHA2_192F) ||  \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHA2_256F) ||  \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHAKE_128F) || \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHAKE_192F) || \
+        ((x) == GNUTLS_PK_EXP_SPHINCS_SHAKE_256F))
+
+#define IS_SPHINCS(x) (IS_SIMPLE_SPHINCS(x) || IS_FAST_SPHINCS(x))
+#endif
+
 #define SIG_SEM_PRE_TLS12 (1 << 1)
 #define SIG_SEM_TLS13 (1 << 2)
 #define SIG_SEM_DEFAULT (SIG_SEM_PRE_TLS12 | SIG_SEM_TLS13)
index 15f77f70c5a6027ed1d4cdd02448b4da8013c99c..6f0f7c35136f2c92ed1f04c073277f50afa272ac 100644 (file)
@@ -213,6 +213,101 @@ static const gnutls_pk_entry pk_algorithms[] = {
          .oid = NULL,
          .id = GNUTLS_PK_EXP_KYBER768,
          .curve = GNUTLS_ECC_CURVE_INVALID },
+       { .name = "Dilithium2",
+         .oid = DILITHIUM2_OID,
+         .id = GNUTLS_PK_EXP_DILITHIUM2,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Dilithium3",
+         .oid = DILITHIUM3_OID,
+         .id = GNUTLS_PK_EXP_DILITHIUM3,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Dilithium5",
+         .oid = DILITHIUM5_OID,
+         .id = GNUTLS_PK_EXP_DILITHIUM5,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Falcon512",
+         .oid = FALCON512_OID,
+         .id = GNUTLS_PK_EXP_FALCON512,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Falcon1024",
+         .oid = FALCON1024_OID,
+         .id = GNUTLS_PK_EXP_FALCON1024,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Falcon512",
+         .oid = FALCON512_OID,
+         .id = GNUTLS_PK_EXP_FALCON512,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Falcon1024",
+         .oid = FALCON1024_OID,
+         .id = GNUTLS_PK_EXP_FALCON1024,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHA2 128F",
+         .oid = SPHINCS_SHA2_128F_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHA2_128F,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHA2 128S",
+         .oid = SPHINCS_SHA2_128S_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHA2_128S,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHA2 192F",
+         .oid = SPHINCS_SHA2_192F_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHA2_192F,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHA2 192S",
+         .oid = SPHINCS_SHA2_192S_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHA2_192S,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHA2 256F",
+         .oid = SPHINCS_SHA2_256F_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHA2_256F,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHA2 256S",
+         .oid = SPHINCS_SHA2_256S_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHA2_256S,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHAKE 128F",
+         .oid = SPHINCS_SHAKE_128F_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHAKE_128F,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHAKE 128S",
+         .oid = SPHINCS_SHAKE_128S_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHAKE_128S,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHAKE 192F",
+         .oid = SPHINCS_SHAKE_192F_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHAKE_192F,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHAKE 192S",
+         .oid = SPHINCS_SHAKE_192S_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHAKE_192S,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHAKE 256F",
+         .oid = SPHINCS_SHAKE_256F_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHAKE_256F,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
+       { .name = "Sphincs SHAKE 256S",
+         .oid = SPHINCS_SHAKE_256S_OID,
+         .id = GNUTLS_PK_EXP_SPHINCS_SHAKE_256S,
+         .curve = GNUTLS_ECC_CURVE_INVALID,
+         .no_prehashed = 1 },
 #endif
        { .name = "UNKNOWN",
          .oid = NULL,
index f498b0f5a198521b9b26a3f1cdff27d356895db1..0bc3a891f419073758dad9e235f132664b866ef2 100644 (file)
@@ -35,28 +35,92 @@ typedef struct {
                                 */
        unsigned int subgroup_bits; /* subgroup bits */
        unsigned int ecc_bits; /* bits for ECC keys */
+#ifdef HAVE_LIBOQS
+       unsigned int dilithium_bits;
+       unsigned int falcon_bits;
+       unsigned int sphincs_bits;
+#endif
 } gnutls_sec_params_entry;
 
 static const gnutls_sec_params_entry sec_params[] = {
-       { "Insecure", GNUTLS_SEC_PARAM_INSECURE, 0, 0, 0, 0, 0 },
-       { "Export", GNUTLS_SEC_PARAM_EXPORT, 42, 512, 0, 84, 0 },
-       { "Very weak", GNUTLS_SEC_PARAM_VERY_WEAK, 64, 767, 0, 128, 0 },
-       { "Weak", GNUTLS_SEC_PARAM_WEAK, 72, 1008, 1008, 160, 160 },
+       { "Insecure", GNUTLS_SEC_PARAM_INSECURE, 0, 0, 0, 0, 0,
+#ifdef HAVE_LIBOQS
+         0, 0, 0
+#endif
+       },
+       { "Export", GNUTLS_SEC_PARAM_EXPORT, 42, 512, 0, 84, 0,
+#ifdef HAVE_LIBOQS
+         0, 0, 0
+#endif
+       },
+       { "Very weak", GNUTLS_SEC_PARAM_VERY_WEAK, 64, 767, 0, 128, 0,
+#ifdef HAVE_LIBOQS
+         0, 0, 0
+#endif
+       },
+       { "Weak", GNUTLS_SEC_PARAM_WEAK, 72, 1008, 1008, 160, 160,
+#ifdef HAVE_LIBOQS
+         0, 0, 0
+#endif
+       },
 #ifdef ENABLE_FIPS140
-       { "Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160 },
-       { "Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1024, 1024, 192, 192 },
-       { "Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 224, 224 },
-       { "High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256 },
+       { "Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160,
+#ifdef HAVE_LIBOQS
+         0, 0, 0
+#endif
+       },
+       { "Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1024, 1024, 192, 192,
+#ifdef HAVE_LIBOQS
+         0, 897, 32
+#endif
+       },
+       { "Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 224, 224,
+#ifdef HAVE_LIBOQS
+         1312, 0, 0
+#endif
+       },
+       { "High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256,
+#ifdef HAVE_LIBOQS
+         0, 0, 48
+#endif
+       },
 #else
-       { "Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160,
-         160 }, /* ENISA-LEGACY */
-       { "Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1776, 2048, 192, 192 },
-       { "Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 256, 224 },
-       { "High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256 },
-#endif
-       { "Ultra", GNUTLS_SEC_PARAM_ULTRA, 192, 8192, 8192, 384, 384 },
-       { "Future", GNUTLS_SEC_PARAM_FUTURE, 256, 15360, 15360, 512, 512 },
-       { NULL, 0, 0, 0, 0, 0 }
+       { "Low", GNUTLS_SEC_PARAM_LOW, 80, 1024, 1024, 160, 160,
+#ifdef HAVE_LIBOQS
+                0, 0, 0
+#endif
+       }, /* ENISA-LEGACY */
+       { "Legacy", GNUTLS_SEC_PARAM_LEGACY, 96, 1776, 2048, 192, 192,
+#ifdef HAVE_LIBOQS
+                0, 897, 32
+#endif
+        },
+       { "Medium", GNUTLS_SEC_PARAM_MEDIUM, 112, 2048, 2048, 256, 224,
+#ifdef HAVE_LIBOQS
+                1312, 0, 0
+#endif
+                },
+       { "High", GNUTLS_SEC_PARAM_HIGH, 128, 3072, 3072, 256, 256,
+#ifdef HAVE_LIBOQS
+                0, 0, 48
+#endif
+       },
+#endif
+       { "Ultra", GNUTLS_SEC_PARAM_ULTRA, 192, 8192, 8192, 384, 384,
+#ifdef HAVE_LIBOQS
+         1952, 0, 0
+#endif
+       },
+       { "Future", GNUTLS_SEC_PARAM_FUTURE, 256, 15360, 15360, 512, 512,
+#ifdef HAVE_LIBOQS
+         2592, 1793, 64
+#endif
+       },
+       { NULL, 0, 0, 0, 0,
+#ifdef HAVE_LIBOQS
+         0, 0, 0
+#endif
+       }
 };
 
 /**
@@ -87,6 +151,14 @@ unsigned int gnutls_sec_param_to_pk_bits(gnutls_pk_algorithm_t algo,
                                ret = p->dsa_bits;
                        else if (IS_EC(algo) || IS_GOSTEC(algo))
                                ret = p->ecc_bits;
+#ifdef HAVE_LIBOQS
+                       else if (IS_DILITHIUM(algo))
+                               ret = p->dilithium_bits;
+                       else if (IS_FALCON(algo))
+                               ret = p->falcon_bits;
+                       else if (IS_SPHINCS(algo))
+                               ret = p->sphincs_bits;
+#endif
                        else
                                ret = p->pk_bits;
                        break;
@@ -216,6 +288,26 @@ gnutls_sec_param_t gnutls_pk_bits_to_sec_param(gnutls_pk_algorithm_t algo,
                                break;
                        ret = p->sec_param;
                }
+#ifdef HAVE_LIBOQS
+       } else if (IS_DILITHIUM(algo)) {
+               for (p = sec_params; p->name; p++) {
+                       if (p->dilithium_bits > bits)
+                               break;
+                       ret = p->sec_param;
+               }
+       } else if (IS_FALCON(algo)) {
+               for (p = sec_params; p->name; p++) {
+                       if (p->falcon_bits > bits)
+                               break;
+                       ret = p->sec_param;
+               }
+       } else if (IS_SPHINCS(algo)) {
+               for (p = sec_params; p->name; p++) {
+                       if (p->sphincs_bits > bits)
+                               break;
+                       ret = p->sec_param;
+               }
+#endif
        } else {
                for (p = sec_params; p->name; p++) {
                        if (p->pk_bits > bits)
index 638dfd0c9456ca8cb3918b6a25bd700dc2e22572..021da73af6404e563d75f81dfbc3697d651ae351 100644 (file)
@@ -402,7 +402,110 @@ static SYSTEM_CONFIG_OR_CONST gnutls_sign_entry_st sign_algorithms[] = {
          .pk = GNUTLS_PK_DSA,
          .hash = GNUTLS_DIG_SHA512,
          .aid = TLS_SIGN_AID_UNKNOWN },
-
+#ifdef HAVE_LIBOQS
+       { .name = "Dilithium2",
+         .oid = DILITHIUM2_OID,
+         .id = GNUTLS_SIGN_EXP_DILITHIUM2,
+         .pk = GNUTLS_PK_EXP_DILITHIUM2,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Dilithium3",
+         .oid = DILITHIUM3_OID,
+         .id = GNUTLS_SIGN_EXP_DILITHIUM3,
+         .pk = GNUTLS_PK_EXP_DILITHIUM3,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Dilithium5",
+         .oid = DILITHIUM5_OID,
+         .id = GNUTLS_SIGN_EXP_DILITHIUM5,
+         .pk = GNUTLS_PK_EXP_DILITHIUM5,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Falcon512",
+         .oid = FALCON512_OID,
+         .id = GNUTLS_SIGN_EXP_FALCON512,
+         .pk = GNUTLS_PK_EXP_FALCON512,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Falcon1024",
+         .oid = FALCON1024_OID,
+         .id = GNUTLS_SIGN_EXP_FALCON1024,
+         .pk = GNUTLS_PK_EXP_FALCON1024,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHA2-128F",
+         .oid = SPHINCS_SHA2_128F_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHA2_128F,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHA2_128F,
+         .hash = GNUTLS_DIG_SHA256, //
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHA2-128S",
+         .oid = SPHINCS_SHA2_128S_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHA2_128S,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHA2_128S,
+         .hash = GNUTLS_DIG_SHA256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHA2-192F",
+         .oid = SPHINCS_SHA2_192F_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHA2_192F,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHA2_192F,
+         .hash = GNUTLS_DIG_SHA256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHA2-192S",
+         .oid = SPHINCS_SHA2_192S_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHA2_192S,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHA2_192S,
+         .hash = GNUTLS_DIG_SHA256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHA2-256F",
+         .oid = SPHINCS_SHA2_256F_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHA2_256F,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHA2_256F,
+         .hash = GNUTLS_DIG_SHA256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHA2-256S",
+         .oid = SPHINCS_SHA2_256S_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHA2_256S,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHA2_256S,
+         .hash = GNUTLS_DIG_SHA256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHAKE-128F",
+         .oid = SPHINCS_SHAKE_128F_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHAKE_128F,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHAKE_128F,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHAKE-128S",
+         .oid = SPHINCS_SHAKE_128S_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHAKE_128S,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHAKE_128S,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHAKE-192F",
+         .oid = SPHINCS_SHAKE_192F_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHAKE_192F,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHAKE_192F,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHAKE-192S",
+         .oid = SPHINCS_SHAKE_192S_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHAKE_192S,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHAKE_192S,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHAKE-256F",
+         .oid = SPHINCS_SHAKE_256F_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHAKE_256F,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHAKE_256F,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+       { .name = "Sphincs-SHAKE-256S",
+         .oid = SPHINCS_SHAKE_256S_OID,
+         .id = GNUTLS_SIGN_EXP_SPHINCS_SHAKE_256S,
+         .pk = GNUTLS_PK_EXP_SPHINCS_SHAKE_256S,
+         .hash = GNUTLS_DIG_SHAKE_256,
+         .aid = TLS_SIGN_AID_UNKNOWN },
+#endif
        { .name = 0,
          .oid = 0,
          .id = 0,
index 5c0630adaa72393984eac32534974d9bc5b74345..28aadfcb384fe402715716674e1f432fd1e5d7a0 100644 (file)
@@ -278,6 +278,11 @@ void gnutls_pk_params_init(gnutls_pk_params_st *p);
 #define RSA_PRIVATE_PARAMS 8
 #define ECC_PRIVATE_PARAMS 3
 #define GOST_PRIVATE_PARAMS 3
+#ifdef HAVE_LIBOQS
+#define DILITHIUM_PRIVATE_PARAMS 4
+#define FALCON_PRIVATE_PARAMS 4
+#define SPHINCS_PRIVATE_PARAMS 4
+#endif
 
 #if MAX_PRIV_PARAMS_SIZE - RSA_PRIVATE_PARAMS < 0
 #error INCREASE MAX_PRIV_PARAMS
index 54a44d173a4e7257f2efe7d0179fbe62f574ee37..a6b5ffff2e9a4acfd535b49b9e50d18e573dce27 100644 (file)
@@ -16,3 +16,9 @@ VOID_FUNC(void, OQS_KEM_free, (OQS_KEM *kem), (kem))
 VOID_FUNC(void, OQS_SHA2_set_callbacks, (struct OQS_SHA2_callbacks *new_callbacks), (new_callbacks))
 VOID_FUNC(void, OQS_SHA3_set_callbacks, (struct OQS_SHA3_callbacks *new_callbacks), (new_callbacks))
 VOID_FUNC(void, OQS_SHA3_x4_set_callbacks, (struct OQS_SHA3_x4_callbacks *new_callbacks), (new_callbacks))
+FUNC(const char *, OQS_version, (void), ())
+FUNC(OQS_SIG *, OQS_SIG_new, (const char *method_name), (method_name))
+FUNC(OQS_STATUS, OQS_SIG_keypair, (const OQS_SIG* sig, uint8_t* public_key, uint8_t *secret_key), (sig, public_key, secret_key))
+FUNC(OQS_STATUS, OQS_SIG_sign, (const OQS_SIG* sig, uint8_t *signature, size_t *signature_len, const uint8_t *message, size_t message_len, const uint8_t* secret_key), (sig, signature, signature_len, message, message_len, secret_key))
+FUNC(OQS_STATUS, OQS_SIG_verify, (const OQS_SIG* sig, const uint8_t *message, size_t message_len, uint8_t *signature, size_t signature_len, const uint8_t* public_key), (sig, message, message_len, signature, signature_len, public_key))
+VOID_FUNC(void, OQS_SIG_free, (OQS_SIG *sig), (sig))
index a4b9e873c5dad99d6005ca00bea4122c09579bf5..7713e3d99626b0c8af7516a7b4c44127e301c859 100644 (file)
@@ -189,4 +189,25 @@ TPMKey ::= SEQUENCE {
     privkey         OCTET STRING
 }
 
+DilithiumPrivateKey ::= SEQUENCE {
+       version                  INTEGER,
+       privateKeyAlgorithm      AlgorithmIdentifier,
+       privateKey               OCTET STRING,
+       publicKey                [1] OCTET STRING OPTIONAL
+}
+
+FalconPrivateKey ::= SEQUENCE {
+       version                  INTEGER,
+       privateKeyAlgorithm      AlgorithmIdentifier,
+       privateKey               OCTET STRING,
+       publicKey                [1] OCTET STRING OPTIONAL
+}
+
+SphincsPrivateKey ::= SEQUENCE {
+       version                  INTEGER,
+       privateKeyAlgorithm      AlgorithmIdentifier,
+       privateKey               OCTET STRING,
+       publicKey                [1] OCTET STRING OPTIONAL
+}
+
 END
index 8b3bb5213130ef25c43988c5020e0f66b7d04ac6..dfa86d60cf7fd25a83fbda0e7af7ba7ef5f30b22 100644 (file)
@@ -912,9 +912,26 @@ typedef enum {
        GNUTLS_PK_MAX = GNUTLS_PK_MLKEM768,
 
        /* Experimental algorithms */
-       GNUTLS_PK_EXP_KYBER768 = 256,
-       GNUTLS_PK_EXP_MIN = GNUTLS_PK_EXP_KYBER768,
-       GNUTLS_PK_EXP_MAX = GNUTLS_PK_EXP_KYBER768
+       GNUTLS_PK_EXP_MIN = 256,
+       GNUTLS_PK_EXP_KYBER768 = GNUTLS_PK_EXP_MIN + 0,
+       GNUTLS_PK_EXP_DILITHIUM2 = GNUTLS_PK_EXP_MIN + 1,
+       GNUTLS_PK_EXP_DILITHIUM3 = GNUTLS_PK_EXP_MIN + 2,
+       GNUTLS_PK_EXP_DILITHIUM5 = GNUTLS_PK_EXP_MIN + 3,
+       GNUTLS_PK_EXP_FALCON512 = GNUTLS_PK_EXP_MIN + 4,
+       GNUTLS_PK_EXP_FALCON1024 = GNUTLS_PK_EXP_MIN + 5,
+       GNUTLS_PK_EXP_SPHINCS_SHA2_128F = GNUTLS_PK_EXP_MIN + 6,
+       GNUTLS_PK_EXP_SPHINCS_SHA2_128S = GNUTLS_PK_EXP_MIN + 7,
+       GNUTLS_PK_EXP_SPHINCS_SHA2_192F = GNUTLS_PK_EXP_MIN + 8,
+       GNUTLS_PK_EXP_SPHINCS_SHA2_192S = GNUTLS_PK_EXP_MIN + 9,
+       GNUTLS_PK_EXP_SPHINCS_SHA2_256F = GNUTLS_PK_EXP_MIN + 10,
+       GNUTLS_PK_EXP_SPHINCS_SHA2_256S = GNUTLS_PK_EXP_MIN + 11,
+       GNUTLS_PK_EXP_SPHINCS_SHAKE_128F = GNUTLS_PK_EXP_MIN + 12,
+       GNUTLS_PK_EXP_SPHINCS_SHAKE_128S = GNUTLS_PK_EXP_MIN + 13,
+       GNUTLS_PK_EXP_SPHINCS_SHAKE_192F = GNUTLS_PK_EXP_MIN + 14,
+       GNUTLS_PK_EXP_SPHINCS_SHAKE_192S = GNUTLS_PK_EXP_MIN + 15,
+       GNUTLS_PK_EXP_SPHINCS_SHAKE_256F = GNUTLS_PK_EXP_MIN + 16,
+       GNUTLS_PK_EXP_SPHINCS_SHAKE_256S = GNUTLS_PK_EXP_MIN + 17,
+       GNUTLS_PK_EXP_MAX = GNUTLS_PK_EXP_SPHINCS_SHAKE_256S
 } gnutls_pk_algorithm_t;
 
 const char *gnutls_pk_algorithm_get_name(gnutls_pk_algorithm_t algorithm);
@@ -1035,7 +1052,27 @@ typedef enum {
        GNUTLS_SIGN_GOST_256 = 44,
        GNUTLS_SIGN_GOST_512 = 45,
        GNUTLS_SIGN_EDDSA_ED448 = 46,
-       GNUTLS_SIGN_MAX = GNUTLS_SIGN_EDDSA_ED448
+       GNUTLS_SIGN_MAX = GNUTLS_SIGN_EDDSA_ED448,
+
+       GNUTLS_SIGN_EXP_MIN = 256,
+       GNUTLS_SIGN_EXP_DILITHIUM2 = GNUTLS_SIGN_EXP_MIN + 0,
+       GNUTLS_SIGN_EXP_DILITHIUM3 = GNUTLS_SIGN_EXP_MIN + 1,
+       GNUTLS_SIGN_EXP_DILITHIUM5 = GNUTLS_SIGN_EXP_MIN + 2,
+       GNUTLS_SIGN_EXP_FALCON512 = GNUTLS_SIGN_EXP_MIN + 3,
+       GNUTLS_SIGN_EXP_FALCON1024 = GNUTLS_SIGN_EXP_MIN + 4,
+       GNUTLS_SIGN_EXP_SPHINCS_SHA2_128F = GNUTLS_SIGN_EXP_MIN + 5,
+       GNUTLS_SIGN_EXP_SPHINCS_SHA2_128S = GNUTLS_SIGN_EXP_MIN + 6,
+       GNUTLS_SIGN_EXP_SPHINCS_SHA2_192F = GNUTLS_SIGN_EXP_MIN + 7,
+       GNUTLS_SIGN_EXP_SPHINCS_SHA2_192S = GNUTLS_SIGN_EXP_MIN + 8,
+       GNUTLS_SIGN_EXP_SPHINCS_SHA2_256F = GNUTLS_SIGN_EXP_MIN + 9,
+       GNUTLS_SIGN_EXP_SPHINCS_SHA2_256S = GNUTLS_SIGN_EXP_MIN + 10,
+       GNUTLS_SIGN_EXP_SPHINCS_SHAKE_128F = GNUTLS_SIGN_EXP_MIN + 11,
+       GNUTLS_SIGN_EXP_SPHINCS_SHAKE_128S = GNUTLS_SIGN_EXP_MIN + 12,
+       GNUTLS_SIGN_EXP_SPHINCS_SHAKE_192F = GNUTLS_SIGN_EXP_MIN + 13,
+       GNUTLS_SIGN_EXP_SPHINCS_SHAKE_192S = GNUTLS_SIGN_EXP_MIN + 14,
+       GNUTLS_SIGN_EXP_SPHINCS_SHAKE_256F = GNUTLS_SIGN_EXP_MIN + 15,
+       GNUTLS_SIGN_EXP_SPHINCS_SHAKE_256S = GNUTLS_SIGN_EXP_MIN + 16,
+       GNUTLS_SIGN_EXP_MAX = GNUTLS_SIGN_EXP_SPHINCS_SHAKE_256S,
 } gnutls_sign_algorithm_t;
 
 /**
index 00fa706b8dd0c245020cb58c59fbce5b3f9dd2ae..f2abffb25ca1253ccac3db32c158b45c52079aee 100644 (file)
@@ -1433,6 +1433,51 @@ static inline int eddsa_sign(gnutls_pk_algorithm_t algo, const uint8_t *pub,
        }
 }
 
+#ifdef HAVE_LIBOQS
+static inline const char *convert_to_oqs_alg(gnutls_pk_algorithm_t algo)
+{
+       switch (algo) {
+       case GNUTLS_PK_EXP_DILITHIUM2:
+               return OQS_SIG_alg_dilithium_2;
+       case GNUTLS_PK_EXP_DILITHIUM3:
+               return OQS_SIG_alg_dilithium_3;
+       case GNUTLS_PK_EXP_DILITHIUM5:
+               return OQS_SIG_alg_dilithium_5;
+       case GNUTLS_PK_EXP_FALCON512:
+               return OQS_SIG_alg_falcon_512;
+       case GNUTLS_PK_EXP_FALCON1024:
+               return OQS_SIG_alg_falcon_1024;
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+               return OQS_SIG_alg_sphincs_sha2_128f_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+               return OQS_SIG_alg_sphincs_sha2_128s_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+               return OQS_SIG_alg_sphincs_sha2_192f_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+               return OQS_SIG_alg_sphincs_sha2_192s_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+               return OQS_SIG_alg_sphincs_sha2_256f_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+               return OQS_SIG_alg_sphincs_sha2_256s_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+               return OQS_SIG_alg_sphincs_shake_128f_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+               return OQS_SIG_alg_sphincs_shake_128s_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+               return OQS_SIG_alg_sphincs_shake_192f_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+               return OQS_SIG_alg_sphincs_shake_192s_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+               return OQS_SIG_alg_sphincs_shake_256f_simple;
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               return OQS_SIG_alg_sphincs_shake_256s_simple;
+       default:
+               gnutls_assert_val(GNUTLS_E_UNSUPPORTED_SIGNATURE_ALGORITHM);
+               return "";
+       }
+}
+#endif
+
 /* This is the lower-level part of privkey_sign_raw_data().
  *
  * It accepts data in the appropriate hash form, i.e., DigestInfo
@@ -1852,6 +1897,56 @@ static int _wrap_nettle_pk_sign(gnutls_pk_algorithm_t algo,
 
                break;
        }
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S: {
+               OQS_SIG *sig;
+               OQS_STATUS rc;
+               size_t size;
+
+               sig = GNUTLS_OQS_FUNC(OQS_SIG_new)(convert_to_oqs_alg(algo));
+               if (sig == NULL) {
+                       ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+                       goto oqs_fail;
+               }
+
+               size = sig->length_signature;
+               signature->data = gnutls_malloc(size);
+
+               rc = GNUTLS_OQS_FUNC(OQS_SIG_sign)(sig, signature->data, &size,
+                                                  vdata->data, vdata->size,
+                                                  pk_params->raw_priv.data);
+               if (rc != OQS_SUCCESS) {
+                       ret = gnutls_assert_val(GNUTLS_E_PK_SIGN_FAILED);
+                       goto oqs_fail;
+               }
+
+               signature->size = size;
+
+               ret = GNUTLS_E_SUCCESS;
+
+       oqs_fail:
+               GNUTLS_OQS_FUNC(OQS_SIG_free)(sig);
+               if (ret < 0)
+                       goto cleanup;
+               break;
+       }
+#endif
        default:
                gnutls_assert();
                ret = GNUTLS_E_INTERNAL_ERROR;
@@ -2224,6 +2319,50 @@ static int _wrap_nettle_pk_verify(gnutls_pk_algorithm_t algo,
 
                break;
        }
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S: {
+               OQS_SIG *sig;
+               OQS_STATUS rc;
+
+               sig = GNUTLS_OQS_FUNC(OQS_SIG_new)(convert_to_oqs_alg(algo));
+               if (sig == NULL) {
+                       ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+                       goto oqs_fail;
+               }
+
+               rc = GNUTLS_OQS_FUNC(OQS_SIG_verify)(
+                       sig, vdata->data, vdata->size, signature->data,
+                       signature->size, pk_params->raw_pub.data);
+               if (rc != OQS_SUCCESS) {
+                       ret = gnutls_assert_val(GNUTLS_E_PK_SIG_VERIFY_FAILED);
+                       goto oqs_fail;
+               }
+
+               ret = GNUTLS_E_SUCCESS;
+
+       oqs_fail:
+               GNUTLS_OQS_FUNC(OQS_SIG_free)(sig);
+               if (ret < 0)
+                       goto cleanup;
+               break;
+       }
+#endif
        default:
                gnutls_assert();
                ret = GNUTLS_E_INTERNAL_ERROR;
@@ -2611,6 +2750,23 @@ static int wrap_nettle_pk_generate_params(gnutls_pk_algorithm_t algo,
        case GNUTLS_PK_GOST_12_512:
 #endif
        case GNUTLS_PK_MLKEM768:
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
                break;
        default:
                gnutls_assert();
@@ -3146,6 +3302,27 @@ cleanup:
        return ret;
 }
 
+#ifdef HAVE_LIBOQS
+static inline int pqc_alg_prepare_key_containers(OQS_SIG *sig,
+                                                gnutls_pk_params_st *params)
+{
+       params->raw_priv.size = sig->length_secret_key;
+       params->raw_priv.data =
+               gnutls_malloc(params->raw_priv.size + sig->length_public_key);
+
+       if (params->raw_priv.data == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+       params->raw_pub.size = sig->length_public_key;
+       params->raw_pub.data = gnutls_malloc(params->raw_pub.size);
+
+       if (params->raw_pub.data == NULL)
+               return gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+
+       return GNUTLS_E_SUCCESS;
+}
+#endif
+
 /* To generate a DH key either q must be set in the params or
  * level should be set to the number of required bits.
  */
@@ -3838,6 +4015,71 @@ wrap_nettle_pk_generate_keys(gnutls_pk_algorithm_t algo,
                ret = 0;
                break;
        }
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               if (params->pkflags & GNUTLS_PK_FLAG_PROVABLE)
+                       return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+               {
+                       OQS_SIG *sig = NULL;
+                       OQS_STATUS rc;
+
+                       if (_gnutls_liboqs_ensure() < 0) {
+                               ret = gnutls_assert_val(
+                                       GNUTLS_E_UNKNOWN_PK_ALGORITHM);
+                               goto cleanup;
+                       }
+
+                       not_approved = true;
+
+                       sig = GNUTLS_OQS_FUNC(OQS_SIG_new)(
+                               convert_to_oqs_alg(algo));
+                       if (sig == NULL) {
+                               ret = gnutls_assert_val(GNUTLS_E_MEMORY_ERROR);
+                               goto cleanup;
+                       }
+
+                       ret = pqc_alg_prepare_key_containers(sig, params);
+                       if (ret < 0)
+                               goto oqs_fail;
+
+                       rc = GNUTLS_OQS_FUNC(
+                               OQS_SIG_keypair)(sig, params->raw_pub.data,
+                                                params->raw_priv.data);
+                       if (rc != OQS_SUCCESS) {
+                               ret = gnutls_assert_val(
+                                       GNUTLS_E_INTERNAL_ERROR);
+                               goto oqs_fail;
+                       }
+
+                       memcpy(&params->raw_priv.data[sig->length_secret_key],
+                              params->raw_pub.data, sig->length_public_key);
+
+                       ret = GNUTLS_E_SUCCESS;
+
+               oqs_fail:
+                       GNUTLS_OQS_FUNC(OQS_SIG_free)(sig);
+
+                       if (ret < 0)
+                               goto cleanup;
+
+                       break;
+               }
 #endif
        default:
                gnutls_assert();
@@ -4110,6 +4352,25 @@ static int wrap_nettle_pk_verify_priv_params(gnutls_pk_algorithm_t algo,
                ret = 0;
                break;
        }
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               ret = 0;
+               break;
 #endif
 #if ENABLE_GOST
        case GNUTLS_PK_GOST_01:
index eb234384e21b5b4583611094b137a37cbc16f86d..46b05196750e724ce2b687d19a7a09d6a1aa5c9f 100644 (file)
@@ -243,6 +243,25 @@ static int privkey_to_pubkey(gnutls_pk_algorithm_t pk,
        case GNUTLS_PK_EDDSA_ED448:
        case GNUTLS_PK_ECDH_X25519:
        case GNUTLS_PK_ECDH_X448:
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+#endif
                ret = _gnutls_set_datum(&pub->raw_pub, priv->raw_pub.data,
                                        priv->raw_pub.size);
                if (ret < 0)
index 77565f864612955ed389b1b7ce053001a0d5a3d1..0a599a8e56125ee4e787073962f736017bb5d64f 100644 (file)
 #include "urls.h"
 #include "ecc.h"
 
+#ifdef HAVE_LIBOQS
+#include <oqs/oqs.h>
+#endif
+
 static int pubkey_verify_hashed_data(const gnutls_sign_entry_st *se,
                                     const mac_entry_st *me,
                                     const gnutls_datum_t *hash,
@@ -49,6 +53,69 @@ static int pubkey_verify_hashed_data(const gnutls_sign_entry_st *se,
 static int pubkey_supports_sig(gnutls_pubkey_t pubkey,
                               const gnutls_sign_entry_st *se);
 
+#ifdef HAVE_LIBOQS
+struct OQS_alg_pubkey_bits {
+       gnutls_pk_algorithm_t algorithm;
+       int pubkey_bits;
+};
+
+struct OQS_alg_pubkey_bits pqc_pubkey_bits[] = {
+#if defined(GNUTLS_PK_EXP_DILITHIUM2) && \
+       defined(OQS_SIG_dilithium_2_length_public_key)
+       { GNUTLS_PK_EXP_DILITHIUM2, OQS_SIG_dilithium_2_length_public_key },
+#endif
+#if defined(GNUTLS_PK_EXP_DILITHIUM3) && \
+       defined(OQS_SIG_dilithium_3_length_public_key)
+       { GNUTLS_PK_EXP_DILITHIUM3, OQS_SIG_dilithium_3_length_public_key },
+#endif
+#if defined(GNUTLS_PK_EXP_DILITHIUM5) && \
+       defined(OQS_SIG_dilithium_5_length_public_key)
+       { GNUTLS_PK_EXP_DILITHIUM5, OQS_SIG_dilithium_5_length_public_key },
+#endif
+       { GNUTLS_PK_EXP_FALCON512, OQS_SIG_falcon_512_length_public_key },
+       { GNUTLS_PK_EXP_FALCON1024, OQS_SIG_falcon_1024_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_128F,
+         OQS_SIG_sphincs_sha2_128f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_128S,
+         OQS_SIG_sphincs_sha2_128s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_192F,
+         OQS_SIG_sphincs_sha2_192f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_192S,
+         OQS_SIG_sphincs_sha2_192s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_256F,
+         OQS_SIG_sphincs_sha2_256f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_256S,
+         OQS_SIG_sphincs_sha2_256s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_128F,
+         OQS_SIG_sphincs_shake_128f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_128S,
+         OQS_SIG_sphincs_shake_128s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_192F,
+         OQS_SIG_sphincs_shake_192f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_192S,
+         OQS_SIG_sphincs_shake_192s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_256F,
+         OQS_SIG_sphincs_shake_256f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_256S,
+         OQS_SIG_sphincs_shake_256s_simple_length_public_key },
+
+       { GNUTLS_PK_UNKNOWN, 0 }
+};
+
+static int pqc_pubkey_to_bits(gnutls_pk_algorithm_t algo)
+{
+       struct OQS_alg_pubkey_bits *pubkey_to_bits = pqc_pubkey_bits;
+       while (pubkey_to_bits->algorithm != algo &&
+              pubkey_to_bits->algorithm != GNUTLS_PK_UNKNOWN)
+               pubkey_to_bits++;
+
+       if (pubkey_to_bits->algorithm == GNUTLS_PK_UNKNOWN)
+               gnutls_assert();
+
+       return pubkey_to_bits->pubkey_bits;
+}
+#endif
+
 unsigned pubkey_to_bits(const gnutls_pk_params_st *params)
 {
        switch (params->algo) {
@@ -67,6 +134,26 @@ unsigned pubkey_to_bits(const gnutls_pk_params_st *params)
        case GNUTLS_PK_GOST_12_256:
        case GNUTLS_PK_GOST_12_512:
                return gnutls_ecc_curve_get_size(params->curve) * 8;
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               return pqc_pubkey_to_bits(params->algo);
+#endif
        default:
                return 0;
        }
@@ -351,7 +438,33 @@ int gnutls_pubkey_get_preferred_hash_algorithm(gnutls_pubkey_t key,
                                pubkey_to_bits(&key->params));
                ret = 0;
                break;
-
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               if (hash)
+                       *hash = GNUTLS_DIG_SHAKE_256;
+               ret = 0;
+               break;
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+               if (hash)
+                       *hash = GNUTLS_DIG_SHA256;
+               ret = 0;
+               break;
+#endif
        default:
                gnutls_assert();
                ret = GNUTLS_E_INTERNAL_ERROR;
@@ -2650,6 +2763,25 @@ int pubkey_verify_data(const gnutls_sign_entry_st *se, const mac_entry_st *me,
 
        case GNUTLS_PK_EDDSA_ED25519:
        case GNUTLS_PK_EDDSA_ED448:
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+#endif
                if (_gnutls_pk_verify(se->pk, data, signature, params,
                                      sign_params) != 0) {
                        gnutls_assert();
index 7a556926b56785f0271628289e5e2c2179a64145..094003b11e75bf15d1966028356210892ccb6f46 100644 (file)
 #define GOST28147_89_CPC_OID "1.2.643.2.2.31.3"
 #define GOST28147_89_CPD_OID "1.2.643.2.2.31.4"
 
+#ifdef HAVE_LIBOQS
+#define DILITHIUM2_OID "1.3.6.1.4.1.2.267.7.4.4"
+#define DILITHIUM3_OID "1.3.6.1.4.1.2.267.7.5.4"
+#define DILITHIUM5_OID "1.3.6.1.4.1.2.267.7.6.4"
+
+#define FALCON512_OID "1.3.9999.3.1"
+#define FALCON1024_OID "1.3.9999.3.4"
+
+#define SPHINCS_SHA2_128F_OID "1.3.9999.6.4.1"
+#define SPHINCS_SHA2_128S_OID "1.3.9999.6.4.2"
+#define SPHINCS_SHA2_192F_OID "1.3.9999.6.5.1"
+#define SPHINCS_SHA2_192S_OID "1.3.9999.6.5.2"
+#define SPHINCS_SHA2_256F_OID "1.3.9999.6.6.1"
+#define SPHINCS_SHA2_256S_OID "1.3.9999.6.6.2"
+#define SPHINCS_SHAKE_128F_OID "1.3.9999.6.7.1"
+#define SPHINCS_SHAKE_128S_OID "1.3.9999.6.7.2"
+#define SPHINCS_SHAKE_192F_OID "1.3.9999.6.8.1"
+#define SPHINCS_SHAKE_192S_OID "1.3.9999.6.8.2"
+#define SPHINCS_SHAKE_256F_OID "1.3.9999.6.9.1"
+#define SPHINCS_SHAKE_256S_OID "1.3.9999.6.9.2"
+#endif
+
 #define ASN1_NULL "\x05\x00"
 #define ASN1_NULL_SIZE 2
 
index 7328878099dbc89983d6c5a2528aa8db6a062eec..24b87fbc7c919d21ab0ef59e5ae9ff1e615285a1 100644 (file)
@@ -735,6 +735,27 @@ int _gnutls_x509_read_pubkey(gnutls_pk_algorithm_t algo, uint8_t *der,
                        params->params_nr = GOST_PUBLIC_PARAMS;
                }
                break;
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               ret = _gnutls_set_datum(&params->raw_pub, der, dersize);
+               break;
+#endif
        default:
                ret = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
                break;
@@ -832,6 +853,25 @@ int _gnutls_x509_check_pubkey_params(gnutls_pk_params_st *params)
        case GNUTLS_PK_GOST_01:
        case GNUTLS_PK_GOST_12_256:
        case GNUTLS_PK_GOST_12_512:
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+#endif
                return 0;
        default:
                return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
index 2b090fd5e46e49f2dd049a3bd369f657186d0ab4..aa035ca54152911e40f9493b72ea7c881f5265db 100644 (file)
@@ -257,6 +257,27 @@ cleanup:
        return ret;
 }
 
+#ifdef HAVE_LIBOQS
+static int _gnutls_x509_write_pqc_alg_pubkey(const gnutls_pk_params_st *params,
+                                            gnutls_datum_t *raw)
+{
+       int ret;
+
+       raw->data = NULL;
+       raw->size = 0;
+
+       if (params->raw_pub.size == 0)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       ret = _gnutls_set_datum(raw, params->raw_pub.data,
+                               params->raw_pub.size);
+       if (ret < 0)
+               return gnutls_assert_val(ret);
+
+       return 0;
+}
+#endif
+
 int _gnutls_x509_write_pubkey_params(const gnutls_pk_params_st *params,
                                     gnutls_datum_t *der)
 {
@@ -281,6 +302,25 @@ int _gnutls_x509_write_pubkey_params(const gnutls_pk_params_st *params,
        case GNUTLS_PK_EDDSA_ED448:
        case GNUTLS_PK_ECDH_X25519:
        case GNUTLS_PK_ECDH_X448:
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+#endif
                der->data = NULL;
                der->size = 0;
 
@@ -316,6 +356,26 @@ int _gnutls_x509_write_pubkey(const gnutls_pk_params_st *params,
        case GNUTLS_PK_GOST_12_256:
        case GNUTLS_PK_GOST_12_512:
                return _gnutls_x509_write_gost_pubkey(params, der);
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               return _gnutls_x509_write_pqc_alg_pubkey(params, der);
+#endif
        default:
                return gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
        }
@@ -1146,6 +1206,205 @@ cleanup:
        return ret;
 }
 
+#ifdef HAVE_LIBOQS
+static int _gnutls_asn1_encode_pqc_alg(asn1_node *c2,
+                                      gnutls_pk_params_st *params,
+                                      const char *oid, uint8_t version)
+{
+       int ret;
+
+       if ((ret = asn1_write_value(*c2, "version", &version, 1)) !=
+           ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(ret);
+       }
+
+       if ((ret = asn1_write_value(*c2, "privateKeyAlgorithm.algorithm", oid,
+                                   1)) != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(ret);
+       }
+
+       if ((ret = asn1_write_value(*c2, "privateKeyAlgorithm.parameters", NULL,
+                                   0)) != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(ret);
+       }
+
+       if (params->raw_pub.size == 0 || params->raw_priv.size == 0)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       ret = asn1_write_value(*c2, "privateKey", params->raw_priv.data,
+                              params->raw_priv.size);
+       if (ret != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(ret);
+       }
+
+       ret = asn1_write_value(*c2, "publicKey", params->raw_pub.data,
+                              params->raw_pub.size);
+       if (ret != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(ret);
+       }
+
+       return GNUTLS_E_SUCCESS;
+}
+
+static uint8_t _gnutls_get_pqc_alg_version(gnutls_pk_params_st *params)
+{
+       switch (params->algo) {
+       case GNUTLS_PK_EXP_DILITHIUM2:
+               return '\x02';
+       case GNUTLS_PK_EXP_DILITHIUM3:
+               return '\x03';
+       case GNUTLS_PK_EXP_DILITHIUM5:
+               return '\x05';
+       case GNUTLS_PK_EXP_FALCON512:
+               return '\x01';
+       case GNUTLS_PK_EXP_FALCON1024:
+               return '\x02';
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+               return '\x01';
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+               return '\x02';
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+               return '\x03';
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+               return '\x04';
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+               return '\x05';
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+               return '\x06';
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+               return '\x07';
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+               return '\x08';
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+               return '\x09';
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+               return '\x0a';
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+               return '\x0b';
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               return '\x0c';
+       default:
+               return '\x00';
+       }
+}
+
+static int _gnutls_asn1_encode_dilithium(asn1_node *c2,
+                                        gnutls_pk_params_st *params)
+{
+       int ret;
+       const char *oid;
+
+       oid = gnutls_pk_get_oid(params->algo);
+       if (oid == NULL)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       /* first make sure that no previously allocated data are leaked */
+       if (*c2 != NULL) {
+               asn1_delete_structure(c2);
+               *c2 = NULL;
+       }
+
+       if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(),
+                                      "GNUTLS.DilithiumPrivateKey", c2)) !=
+           ASN1_SUCCESS) {
+               gnutls_assert();
+               ret = _gnutls_asn2err(ret);
+               goto cleanup;
+       }
+
+       ret = _gnutls_asn1_encode_pqc_alg(c2, params, oid,
+                                         _gnutls_get_pqc_alg_version(params));
+       if (ret < 0)
+               goto cleanup;
+
+       return GNUTLS_E_SUCCESS;
+
+cleanup:
+       asn1_delete_structure2(c2, ASN1_DELETE_FLAG_ZEROIZE);
+
+       return ret;
+}
+
+static int _gnutls_asn1_encode_falcon(asn1_node *c2,
+                                     gnutls_pk_params_st *params)
+{
+       int ret;
+       const char *oid;
+
+       oid = gnutls_pk_get_oid(params->algo);
+       if (oid == NULL)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       /* first make sure that no previously allocated data are leaked */
+       if (*c2 != NULL) {
+               asn1_delete_structure(c2);
+               *c2 = NULL;
+       }
+
+       if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(),
+                                      "GNUTLS.FalconPrivateKey", c2)) !=
+           ASN1_SUCCESS) {
+               gnutls_assert();
+               ret = _gnutls_asn2err(ret);
+               goto cleanup;
+
+               ret = _gnutls_asn1_encode_pqc_alg(
+                       c2, params, oid, _gnutls_get_pqc_alg_version(params));
+               if (ret < 0)
+                       goto cleanup;
+
+               return GNUTLS_E_SUCCESS;
+       }
+
+cleanup:
+       asn1_delete_structure2(c2, ASN1_DELETE_FLAG_ZEROIZE);
+
+       return ret;
+}
+
+static int _gnutls_asn1_encode_sphincs(asn1_node *c2,
+                                      gnutls_pk_params_st *params)
+{
+       int ret;
+       const char *oid;
+
+       oid = gnutls_pk_get_oid(params->algo);
+       if (oid == NULL)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+
+       /* first make sure that no previously allocated data are leaked */
+       if (*c2 != NULL) {
+               asn1_delete_structure(c2);
+               *c2 = NULL;
+       }
+
+       if ((ret = asn1_create_element(_gnutls_get_gnutls_asn(),
+                                      "GNUTLS.SphincsPrivateKey", c2)) !=
+           ASN1_SUCCESS) {
+               gnutls_assert();
+               ret = _gnutls_asn2err(ret);
+               goto cleanup;
+       }
+
+       ret = _gnutls_asn1_encode_pqc_alg(c2, params, oid,
+                                         _gnutls_get_pqc_alg_version(params));
+       if (ret < 0)
+               goto cleanup;
+
+       return GNUTLS_E_SUCCESS;
+
+cleanup:
+       asn1_delete_structure2(c2, ASN1_DELETE_FLAG_ZEROIZE);
+
+       return ret;
+}
+#endif
+
 int _gnutls_asn1_encode_privkey(asn1_node *c2, gnutls_pk_params_st *params)
 {
        switch (params->algo) {
@@ -1168,6 +1427,28 @@ int _gnutls_asn1_encode_privkey(asn1_node *c2, gnutls_pk_params_st *params)
        case GNUTLS_PK_DH:
                /* DH keys are only exportable in PKCS#8 format */
                return GNUTLS_E_INVALID_REQUEST;
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+               return _gnutls_asn1_encode_dilithium(c2, params);
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+               return _gnutls_asn1_encode_falcon(c2, params);
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               return _gnutls_asn1_encode_sphincs(c2, params);
+#endif
        default:
                return GNUTLS_E_UNIMPLEMENTED_FEATURE;
        }
index 14c75a92abe113d63af545a205370e20e8c0987e..d48f490fefe748e89f4742e5fcc8f2453c1fbb6d 100644 (file)
@@ -133,8 +133,28 @@ int _gnutls_get_asn_mpis(asn1_node asn, const char *root,
            pk_algorithm != GNUTLS_PK_EDDSA_ED25519 &&
            pk_algorithm != GNUTLS_PK_ECDH_X25519 &&
            pk_algorithm != GNUTLS_PK_EDDSA_ED448 &&
-           pk_algorithm != GNUTLS_PK_ECDH_X448) {
-               /* RSA and EdDSA do not use parameters */
+           pk_algorithm != GNUTLS_PK_ECDH_X448
+#ifdef HAVE_LIBOQS
+           && pk_algorithm != GNUTLS_PK_EXP_DILITHIUM2 &&
+           pk_algorithm != GNUTLS_PK_EXP_DILITHIUM3 &&
+           pk_algorithm != GNUTLS_PK_EXP_DILITHIUM5 &&
+           pk_algorithm != GNUTLS_PK_EXP_FALCON512 &&
+           pk_algorithm != GNUTLS_PK_EXP_FALCON1024 &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHA2_128F &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHA2_128S &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHA2_192F &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHA2_192S &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHA2_256F &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHA2_256S &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHAKE_128F &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHAKE_128S &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHAKE_192F &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHAKE_192S &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHAKE_256F &&
+           pk_algorithm != GNUTLS_PK_EXP_SPHINCS_SHAKE_256S
+#endif
+       ) {
+               /* RSA, EdDSA and PQC algorithms do not use parameters */
                result = _gnutls_x509_read_value(asn, name, &tmp);
                if (pk_algorithm == GNUTLS_PK_RSA_PSS &&
                    (result == GNUTLS_E_ASN1_VALUE_NOT_FOUND ||
index 131ec69dbaf20eb271a7b4ee827a243f8a8a95ed..7b0caaab97edee363a74599b5aa67cd82198d798 100644 (file)
@@ -36,6 +36,9 @@
 #include "ecc.h"
 #include "pin.h"
 
+#ifdef HAVE_LIBOQS
+#include <oqs/oqs.h>
+#endif
 /**
  * gnutls_x509_privkey_init:
  * @key: A pointer to the type to be initialized
@@ -324,6 +327,282 @@ error:
        return ret;
 }
 
+#ifdef HAVE_LIBOQS
+struct PQCAlgorithmVersion {
+       uint8_t version;
+       gnutls_pk_algorithm_t algorithm;
+       int secret_key_length;
+       int public_key_length;
+};
+
+int _gnutls_decode_pqc_keys(asn1_node *pkey_asn, const gnutls_datum_t *raw_key,
+                           gnutls_x509_privkey_t pkey, uint8_t *version)
+{
+       int result;
+       unsigned int _version;
+
+       result = _asn1_strict_der_decode(pkey_asn, raw_key->data, raw_key->size,
+                                        NULL);
+       if (result != ASN1_SUCCESS) {
+               gnutls_assert();
+               return result;
+       }
+
+       result = _gnutls_x509_read_uint(*pkey_asn, "version", &_version);
+       *version = _version;
+       if (result < 0) {
+               gnutls_assert();
+               return result;
+       }
+
+       result = _gnutls_x509_read_value(*pkey_asn, "privateKey",
+                                        &pkey->params.raw_priv);
+       if (result < 0) {
+               gnutls_assert();
+               return result;
+       }
+
+       result = _gnutls_x509_read_value(*pkey_asn, "publicKey",
+                                        &pkey->params.raw_pub);
+       if (result < 0) {
+               gnutls_assert();
+               return result;
+       }
+
+       return GNUTLS_E_SUCCESS;
+}
+
+struct PQCAlgorithmVersion dilithium_versions[] = {
+#if defined(GNUTLS_PK_EXP_DILITHIUM2) &&                  \
+       defined(OQS_SIG_dilithium_2_length_secret_key) && \
+       defined(OQS_SIG_dilithium_2_length_public_key)
+       { '\x02', GNUTLS_PK_EXP_DILITHIUM2,
+         OQS_SIG_dilithium_2_length_secret_key,
+         OQS_SIG_dilithium_2_length_public_key },
+#endif
+#if defined(GNUTLS_PK_EXP_DILITHIUM3) &&                  \
+       defined(OQS_SIG_dilithium_3_length_secret_key) && \
+       defined(OQS_SIG_dilithium_3_length_public_key)
+       { '\x03', GNUTLS_PK_EXP_DILITHIUM3,
+         OQS_SIG_dilithium_3_length_secret_key,
+         OQS_SIG_dilithium_3_length_public_key },
+#endif
+#if defined(GNUTLS_PK_EXP_DILITHIUM5) &&                  \
+       defined(OQS_SIG_dilithium_5_length_secret_key) && \
+       defined(OQS_SIG_dilithium_5_length_public_key)
+       { '\x05', GNUTLS_PK_EXP_DILITHIUM5,
+         OQS_SIG_dilithium_5_length_secret_key,
+         OQS_SIG_dilithium_5_length_public_key },
+#endif
+
+       { '\x00', GNUTLS_PK_UNKNOWN, 0, 0 }
+};
+
+static int _gnutls_set_dilithium_params(const uint8_t *version,
+                                       gnutls_x509_privkey_t pkey)
+{
+       struct PQCAlgorithmVersion *v = dilithium_versions;
+       while (v->algorithm != GNUTLS_PK_UNKNOWN && v->version != *version)
+               v++;
+
+       pkey->params.raw_priv.size = v->secret_key_length;
+       pkey->params.raw_pub.size = v->public_key_length;
+       pkey->params.params_nr = DILITHIUM_PRIVATE_PARAMS;
+       pkey->params.algo = v->algorithm;
+
+       if (v->algorithm == GNUTLS_PK_UNKNOWN)
+               return GNUTLS_E_UNKNOWN_ALGORITHM;
+
+       return 0;
+}
+
+int _gnutls_privkey_decode_dilithium_key(asn1_node *pkey_asn,
+                                        const gnutls_datum_t *raw_key,
+                                        gnutls_x509_privkey_t pkey)
+{
+       int result;
+       uint8_t version;
+
+       gnutls_pk_params_init(&pkey->params);
+
+       if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
+                                         "GNUTLS.DilithiumPrivateKey",
+                                         pkey_asn)) != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(result);
+       }
+
+       result = _gnutls_decode_pqc_keys(pkey_asn, raw_key, pkey, &version);
+       if (result < 0)
+               goto error;
+
+       result = _gnutls_set_dilithium_params(&version, pkey);
+       if (result < 0)
+               goto error;
+
+       return 0;
+
+error:
+       asn1_delete_structure2(pkey_asn, ASN1_DELETE_FLAG_ZEROIZE);
+       gnutls_pk_params_clear(&pkey->params);
+       gnutls_pk_params_release(&pkey->params);
+       return result;
+}
+
+struct PQCAlgorithmVersion falcon_versions[] = {
+       { '\x01', GNUTLS_PK_EXP_FALCON512, OQS_SIG_falcon_512_length_secret_key,
+         OQS_SIG_falcon_512_length_public_key },
+       { '\x02', GNUTLS_PK_EXP_FALCON1024,
+         OQS_SIG_falcon_1024_length_secret_key,
+         OQS_SIG_falcon_1024_length_public_key },
+
+       { '\x00', GNUTLS_PK_UNKNOWN, 0, 0 }
+};
+
+static int _gnutls_set_falcon_params(const uint8_t *version,
+                                    gnutls_x509_privkey_t pkey)
+{
+       struct PQCAlgorithmVersion *v = falcon_versions;
+       while (v->algorithm != GNUTLS_PK_UNKNOWN && v->version != *version)
+               v++;
+
+       pkey->params.raw_priv.size = v->secret_key_length;
+       pkey->params.raw_pub.size = v->public_key_length;
+       pkey->params.params_nr = FALCON_PRIVATE_PARAMS;
+       pkey->params.algo = v->algorithm;
+
+       if (v->algorithm == GNUTLS_PK_UNKNOWN)
+               return GNUTLS_E_UNKNOWN_ALGORITHM;
+
+       return 0;
+}
+
+int _gnutls_privkey_decode_falcon_key(asn1_node *pkey_asn,
+                                     const gnutls_datum_t *raw_key,
+                                     gnutls_x509_privkey_t pkey)
+{
+       int result;
+       uint8_t version;
+
+       gnutls_pk_params_init(&pkey->params);
+
+       if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
+                                         "GNUTLS.FalconPrivateKey",
+                                         pkey_asn)) != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(result);
+       }
+
+       result = _gnutls_decode_pqc_keys(pkey_asn, raw_key, pkey, &version);
+       if (result < 0)
+               goto error;
+
+       result = _gnutls_set_falcon_params(&version, pkey);
+       if (result < 0)
+               goto error;
+
+       return 0;
+
+error:
+       asn1_delete_structure2(pkey_asn, ASN1_DELETE_FLAG_ZEROIZE);
+       gnutls_pk_params_clear(&pkey->params);
+       gnutls_pk_params_release(&pkey->params);
+       return result;
+}
+
+struct PQCAlgorithmVersion sphincs_versions[] = {
+       { '\x01', GNUTLS_PK_EXP_SPHINCS_SHA2_128F,
+         OQS_SIG_sphincs_sha2_128f_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_128f_simple_length_public_key },
+       { '\x02', GNUTLS_PK_EXP_SPHINCS_SHA2_128S,
+         OQS_SIG_sphincs_sha2_128s_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_128s_simple_length_public_key },
+       { '\x03', GNUTLS_PK_EXP_SPHINCS_SHA2_192F,
+         OQS_SIG_sphincs_sha2_192f_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_192f_simple_length_public_key },
+       { '\x04', GNUTLS_PK_EXP_SPHINCS_SHA2_192S,
+         OQS_SIG_sphincs_sha2_192s_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_192s_simple_length_public_key },
+       { '\x05', GNUTLS_PK_EXP_SPHINCS_SHA2_256F,
+         OQS_SIG_sphincs_sha2_256f_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_256f_simple_length_public_key },
+       { '\x06', GNUTLS_PK_EXP_SPHINCS_SHA2_256S,
+         OQS_SIG_sphincs_sha2_256s_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_256s_simple_length_public_key },
+       { '\x07', GNUTLS_PK_EXP_SPHINCS_SHAKE_128F,
+         OQS_SIG_sphincs_shake_128f_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_128f_simple_length_public_key },
+       { '\x08', GNUTLS_PK_EXP_SPHINCS_SHAKE_128S,
+         OQS_SIG_sphincs_shake_128s_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_128s_simple_length_public_key },
+       { '\x09', GNUTLS_PK_EXP_SPHINCS_SHAKE_192F,
+         OQS_SIG_sphincs_shake_192f_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_192f_simple_length_public_key },
+       { '\x0a', GNUTLS_PK_EXP_SPHINCS_SHAKE_192S,
+         OQS_SIG_sphincs_shake_192s_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_192s_simple_length_public_key },
+       { '\x0b', GNUTLS_PK_EXP_SPHINCS_SHAKE_256F,
+         OQS_SIG_sphincs_shake_256f_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_256f_simple_length_public_key },
+       { '\x0c', GNUTLS_PK_EXP_SPHINCS_SHAKE_256S,
+         OQS_SIG_sphincs_shake_256s_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_256s_simple_length_public_key },
+
+       { '\x00', GNUTLS_PK_UNKNOWN, 0, 0 }
+};
+
+static int _gnutls_set_sphincs_params(const uint8_t *version,
+                                     gnutls_x509_privkey_t pkey)
+{
+       struct PQCAlgorithmVersion *v = sphincs_versions;
+       while (v->algorithm != GNUTLS_PK_UNKNOWN && v->version != *version)
+               v++;
+
+       pkey->params.raw_priv.size = v->secret_key_length;
+       pkey->params.raw_pub.size = v->public_key_length;
+       pkey->params.params_nr = SPHINCS_PRIVATE_PARAMS;
+       pkey->params.algo = v->algorithm;
+
+       if (v->algorithm == GNUTLS_PK_UNKNOWN)
+               return GNUTLS_E_UNKNOWN_ALGORITHM;
+
+       return 0;
+}
+
+int _gnutls_privkey_decode_sphincs_key(asn1_node *pkey_asn,
+                                      const gnutls_datum_t *raw_key,
+                                      gnutls_x509_privkey_t pkey)
+{
+       int result;
+       uint8_t version;
+
+       gnutls_pk_params_init(&pkey->params);
+
+       if ((result = asn1_create_element(_gnutls_get_gnutls_asn(),
+                                         "GNUTLS.SphincsPrivateKey",
+                                         pkey_asn)) != ASN1_SUCCESS) {
+               gnutls_assert();
+               return _gnutls_asn2err(result);
+       }
+
+       result = _gnutls_decode_pqc_keys(pkey_asn, raw_key, pkey, &version);
+       if (result < 0)
+               goto error;
+
+       result = _gnutls_set_sphincs_params(&version, pkey);
+       if (result < 0)
+               goto error;
+
+       return 0;
+
+error:
+       asn1_delete_structure2(pkey_asn, ASN1_DELETE_FLAG_ZEROIZE);
+       gnutls_pk_params_clear(&pkey->params);
+       gnutls_pk_params_release(&pkey->params);
+       return result;
+}
+#endif
+
 static asn1_node decode_dsa_key(const gnutls_datum_t *raw_key,
                                gnutls_x509_privkey_t pkey)
 {
@@ -408,6 +687,11 @@ error:
 #define PEM_KEY_DSA "DSA PRIVATE KEY"
 #define PEM_KEY_RSA "RSA PRIVATE KEY"
 #define PEM_KEY_ECC "EC PRIVATE KEY"
+#ifdef HAVE_LIBOQS
+#define PEM_KEY_DILITHIUM "DILITHIUM PRIVATE KEY"
+#define PEM_KEY_FALCON "FALCON PRIVATE KEY"
+#define PEM_KEY_SPHINCS "SPHINCS PRIVATE KEY"
+#endif
 #define PEM_KEY_PKCS8 "PRIVATE KEY"
 
 #define MAX_PEM_HEADER_SIZE 25
@@ -507,6 +791,41 @@ int gnutls_x509_privkey_import(gnutls_x509_privkey_t key,
                                        if (result >= 0)
                                                key->params.algo =
                                                        GNUTLS_PK_DSA;
+#ifdef HAVE_LIBOQS
+                               } else if (left > sizeof(PEM_KEY_DILITHIUM) &&
+                                          memcmp(ptr, PEM_KEY_DILITHIUM,
+                                                 sizeof(PEM_KEY_DILITHIUM) -
+                                                         1) == 0) {
+                                       result = _gnutls_fbase64_decode(
+                                               PEM_KEY_DILITHIUM, begin_ptr,
+                                               left, &_data);
+                                       if (result >= 0) {
+                                               key->params.algo =
+                                                       GNUTLS_PK_EXP_DILITHIUM2;
+                                       }
+                               } else if (left > sizeof(PEM_KEY_FALCON) &&
+                                          memcmp(ptr, PEM_KEY_FALCON,
+                                                 sizeof(PEM_KEY_FALCON) - 1) ==
+                                                  0) {
+                                       result = _gnutls_fbase64_decode(
+                                               PEM_KEY_FALCON, begin_ptr, left,
+                                               &_data);
+                                       if (result >= 0) {
+                                               key->params.algo =
+                                                       GNUTLS_PK_EXP_FALCON512;
+                                       }
+                               } else if (left > sizeof(PEM_KEY_SPHINCS) &&
+                                          memcmp(ptr, PEM_KEY_SPHINCS,
+                                                 sizeof(PEM_KEY_SPHINCS) -
+                                                         1) == 0) {
+                                       result = _gnutls_fbase64_decode(
+                                               PEM_KEY_SPHINCS, begin_ptr,
+                                               left, &_data);
+                                       if (result >= 0) {
+                                               key->params.algo =
+                                                       GNUTLS_PK_EXP_SPHINCS_SHA2_128F;
+                                       }
+#endif
                                }
 
                                if (key->params.algo == GNUTLS_PK_UNKNOWN &&
@@ -566,6 +885,32 @@ int gnutls_x509_privkey_import(gnutls_x509_privkey_t key,
                        gnutls_assert();
                        key->key = NULL;
                }
+#ifdef HAVE_LIBOQS
+       } else if (key->params.algo == GNUTLS_PK_EXP_DILITHIUM2) {
+               result = _gnutls_privkey_decode_dilithium_key(&key->key, &_data,
+                                                             key);
+
+               if (result < 0) {
+                       gnutls_assert();
+                       key->key = NULL;
+               }
+       } else if (key->params.algo == GNUTLS_PK_EXP_FALCON512) {
+               result = _gnutls_privkey_decode_falcon_key(&key->key, &_data,
+                                                          key);
+
+               if (result < 0) {
+                       gnutls_assert();
+                       key->key = NULL;
+               }
+       } else if (key->params.algo == GNUTLS_PK_EXP_SPHINCS_SHA2_128F) {
+               result = _gnutls_privkey_decode_sphincs_key(&key->key, &_data,
+                                                           key);
+
+               if (result < 0) {
+                       gnutls_assert();
+                       key->key = NULL;
+               }
+#endif
        } else {
                /* Try decoding each of the keys, and accept the one that
                 * succeeds.
@@ -668,6 +1013,14 @@ fail:
        return ret;
 }
 
+#ifdef HAVE_LIBOQS
+#define MAX_ALGORITHM_NAME_SIZE_IN_PEM_HEADER 21
+#define MAX_PEM_KEY_SIZE PEM_KEY_DILITHIUM
+#else
+#define MAX_ALGORITHM_NAME_SIZE_IN_PEM_HEADER 15
+#define MAX_PEM_KEY_SIZE PEM_KEY_RSA
+#endif
+
 /**
  * gnutls_x509_privkey_import2:
  * @key: The data to store the parsed key
@@ -711,9 +1064,10 @@ int gnutls_x509_privkey_import2(gnutls_x509_privkey_t key,
                        left = data->size -
                               ((ptrdiff_t)ptr - (ptrdiff_t)data->data);
 
-                       if (data->size - left > 15) {
-                               ptr -= 15;
-                               left += 15;
+                       if (data->size - left >
+                           MAX_ALGORITHM_NAME_SIZE_IN_PEM_HEADER) {
+                               ptr -= MAX_ALGORITHM_NAME_SIZE_IN_PEM_HEADER;
+                               left += MAX_ALGORITHM_NAME_SIZE_IN_PEM_HEADER;
                        } else {
                                ptr = (char *)data->data;
                                left = data->size;
@@ -727,13 +1081,23 @@ int gnutls_x509_privkey_import2(gnutls_x509_privkey_t key,
                                       ((ptrdiff_t)ptr - (ptrdiff_t)data->data);
                        }
 
-                       if (ptr != NULL && left > sizeof(PEM_KEY_RSA)) {
+                       if (ptr != NULL && left > sizeof(MAX_PEM_KEY_SIZE)) {
                                if (memcmp(ptr, PEM_KEY_RSA,
                                           sizeof(PEM_KEY_RSA) - 1) == 0 ||
                                    memcmp(ptr, PEM_KEY_ECC,
                                           sizeof(PEM_KEY_ECC) - 1) == 0 ||
                                    memcmp(ptr, PEM_KEY_DSA,
-                                          sizeof(PEM_KEY_DSA) - 1) == 0) {
+                                          sizeof(PEM_KEY_DSA) - 1) == 0
+#ifdef HAVE_LIBOQS
+                                   || memcmp(ptr, PEM_KEY_DILITHIUM,
+                                             sizeof(PEM_KEY_DILITHIUM) - 1) ==
+                                              0 ||
+                                   memcmp(ptr, PEM_KEY_FALCON,
+                                          sizeof(PEM_KEY_FALCON) - 1) == 0 ||
+                                   memcmp(ptr, PEM_KEY_SPHINCS,
+                                          sizeof(PEM_KEY_SPHINCS) - 1) == 0
+#endif
+                               ) {
                                        head_enc = 0;
                                }
                        }
@@ -1477,14 +1841,39 @@ int gnutls_x509_privkey_set_spki(gnutls_x509_privkey_t key,
 
 static const char *set_msg(gnutls_x509_privkey_t key)
 {
-       if (GNUTLS_PK_IS_RSA(key->params.algo)) {
+       switch (key->params.algo) {
+       case GNUTLS_PK_RSA:
+       case GNUTLS_PK_RSA_PSS:
                return PEM_KEY_RSA;
-       } else if (key->params.algo == GNUTLS_PK_DSA) {
+       case GNUTLS_PK_DSA:
                return PEM_KEY_DSA;
-       } else if (key->params.algo == GNUTLS_PK_EC)
+       case GNUTLS_PK_EC:
                return PEM_KEY_ECC;
-       else
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+               return PEM_KEY_DILITHIUM;
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+               return PEM_KEY_FALCON;
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               return PEM_KEY_SPHINCS;
+#endif
+       default:
                return "UNKNOWN";
+       }
 }
 
 /**
index 5f8ba89daf28a28a7a224ccc55a19e31ae919129..34e02a6143df8c22754f83f8cebd0ee680ad439e 100644 (file)
 #include "attributes.h"
 #include "prov-seed.h"
 
+#ifdef HAVE_LIBOQS
+#include <oqs/oqs.h>
+#endif
+
 static int _decode_pkcs8_ecc_key(asn1_node pkcs8_asn,
                                 gnutls_x509_privkey_t pkey);
 static int pkcs8_key_info(const gnutls_datum_t *raw_key,
@@ -78,6 +82,33 @@ inline static int _encode_privkey(gnutls_x509_privkey_t pkey,
                if (ret < 0)
                        gnutls_assert();
                return ret;
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               // Dilithium public key is appended to private key
+               ret = _gnutls_x509_encode_string(
+                       ASN1_ETYPE_OCTET_STRING, pkey->params.raw_priv.data,
+                       pkey->params.raw_priv.size + pkey->params.raw_pub.size,
+                       raw);
+               if (ret < 0)
+                       gnutls_assert();
+               return ret;
+#endif
 
        case GNUTLS_PK_GOST_01:
        case GNUTLS_PK_GOST_12_256:
@@ -1454,6 +1485,148 @@ error:
        return ret;
 }
 
+#ifdef HAVE_LIBOQS
+struct pqc_key_length_st {
+       gnutls_pk_algorithm_t algorithm;
+       int secret_key_length;
+       int public_key_length;
+};
+
+struct pqc_key_length_st pqc_key_lengths[] = {
+#ifdef defined(GNUTLS_PK_EXP_DILITHIUM2) &&               \
+       defined(OQS_SIG_dilithium_2_length_secret_key) && \
+       defined(OQS_SIG_dilithium_2_length_public_key)
+       { GNUTLS_PK_EXP_DILITHIUM2, OQS_SIG_dilithium_2_length_secret_key,
+         OQS_SIG_dilithium_2_length_public_key },
+#endif
+#ifdef defined(GNUTLS_PK_EXP_DILITHIUM3) &&               \
+       defined(OQS_SIG_dilithium_3_length_secret_key) && \
+       defined(OQS_SIG_dilithium_3_length_public_key)
+       { GNUTLS_PK_EXP_DILITHIUM3, OQS_SIG_dilithium_3_length_secret_key,
+         OQS_SIG_dilithium_3_length_public_key },
+#endif
+#ifdef defined(GNUTLS_PK_EXP_DILITHIUM5) &&               \
+       defined(OQS_SIG_dilithium_5_length_secret_key) && \
+       defined(OQS_SIG_dilithium_5_length_public_key)
+       { GNUTLS_PK_EXP_DILITHIUM5, OQS_SIG_dilithium_5_length_secret_key,
+         OQS_SIG_dilithium_5_length_public_key },
+#endif
+       { GNUTLS_PK_EXP_FALCON512, OQS_SIG_falcon_512_length_secret_key,
+         OQS_SIG_falcon_512_length_public_key },
+       { GNUTLS_PK_EXP_FALCON1024, OQS_SIG_falcon_1024_length_secret_key,
+         OQS_SIG_falcon_1024_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_128F,
+         OQS_SIG_sphincs_sha2_128f_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_128f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_128S,
+         OQS_SIG_sphincs_sha2_128s_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_128s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_192F,
+         OQS_SIG_sphincs_sha2_192f_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_192f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_192S,
+         OQS_SIG_sphincs_sha2_192s_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_192s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_256F,
+         OQS_SIG_sphincs_sha2_256f_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_256f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHA2_256S,
+         OQS_SIG_sphincs_sha2_256s_simple_length_secret_key,
+         OQS_SIG_sphincs_sha2_256s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_128F,
+         OQS_SIG_sphincs_shake_128f_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_128f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_128S,
+         OQS_SIG_sphincs_shake_128s_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_128s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_192F,
+         OQS_SIG_sphincs_shake_192f_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_192f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_192S,
+         OQS_SIG_sphincs_shake_192s_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_192s_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_256F,
+         OQS_SIG_sphincs_shake_256f_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_256f_simple_length_public_key },
+       { GNUTLS_PK_EXP_SPHINCS_SHAKE_256S,
+         OQS_SIG_sphincs_shake_256s_simple_length_secret_key,
+         OQS_SIG_sphincs_shake_256s_simple_length_public_key },
+
+       { GNUTLS_PK_UNKNOWN, 0, 0 }
+};
+
+static int _get_pqc_keys_length(gnutls_pk_algorithm_t algo,
+                               int *pqc_alg_secret_key_length,
+                               int *pqc_alg_public_key_length)
+{
+       struct pqc_key_length_st *pqc_key_length = pqc_key_lengths;
+       while (pqc_key_length->algorithm != algo &&
+              pqc_key_length->algorithm != GNUTLS_PK_UNKNOWN)
+               pqc_key_length++;
+
+       if (pqc_key_length->algorithm == GNUTLS_PK_UNKNOWN)
+               return GNUTLS_E_UNKNOWN_ALGORITHM;
+
+       *pqc_alg_secret_key_length = pqc_key_length->secret_key_length;
+       *pqc_alg_public_key_length = pqc_key_length->public_key_length;
+
+       return 0;
+}
+
+static int _decode_pkcs8_pqc_alg_key(asn1_node pkcs8_asn,
+                                    gnutls_x509_privkey_t pkey,
+                                    const char *oid)
+{
+       int ret;
+       gnutls_datum_t private_key;
+       gnutls_pk_algorithm_t algo = pkey->params.algo;
+       int pqc_alg_secret_key_length;
+       int pqc_alg_public_key_length;
+
+       ret = _get_pqc_keys_length(pkey->params.algo,
+                                  &pqc_alg_secret_key_length,
+                                  &pqc_alg_public_key_length);
+       if (ret < 0) {
+               gnutls_assert();
+               goto error;
+       }
+
+       /* TODO: support OneAsymmetricKey to read public key from a
+        * separate field
+        */
+
+       gnutls_pk_params_init(&pkey->params);
+
+       ret = _gnutls_x509_read_string(pkcs8_asn, "privateKey", &private_key,
+                                      ASN1_ETYPE_OCTET_STRING, 1);
+       if (ret < 0) {
+               gnutls_assert();
+               goto error;
+       }
+
+       pkey->params.algo = algo;
+       pkey->params.raw_priv.data = private_key.data;
+       pkey->params.raw_priv.size = pqc_alg_secret_key_length;
+
+       pkey->params.raw_pub.data = gnutls_malloc(pqc_alg_public_key_length);
+       memcpy(pkey->params.raw_pub.data,
+              &private_key.data[pqc_alg_secret_key_length],
+              pqc_alg_public_key_length);
+       pkey->params.raw_pub.size = pqc_alg_public_key_length;
+
+       private_key.data = NULL;
+
+       return GNUTLS_E_SUCCESS;
+
+error:
+       gnutls_free(pkey->params.raw_priv.data);
+       gnutls_pk_params_clear(&pkey->params);
+       gnutls_pk_params_release(&pkey->params);
+
+       return ret;
+}
+#endif
+
 static int decode_private_key_info(const gnutls_datum_t *der,
                                   gnutls_x509_privkey_t pkey)
 {
@@ -1532,6 +1705,27 @@ static int decode_private_key_info(const gnutls_datum_t *der,
                result = _decode_pkcs8_gost_key(pkcs8_asn, pkey,
                                                pkey->params.algo);
                break;
+#ifdef HAVE_LIBOQS
+       case GNUTLS_PK_EXP_DILITHIUM2:
+       case GNUTLS_PK_EXP_DILITHIUM3:
+       case GNUTLS_PK_EXP_DILITHIUM5:
+       case GNUTLS_PK_EXP_FALCON512:
+       case GNUTLS_PK_EXP_FALCON1024:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHA2_256S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_128S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_192S:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256F:
+       case GNUTLS_PK_EXP_SPHINCS_SHAKE_256S:
+               result = _decode_pkcs8_pqc_alg_key(pkcs8_asn, pkey, oid);
+               break;
+#endif
        default:
                result = gnutls_assert_val(GNUTLS_E_UNIMPLEMENTED_FEATURE);
                goto error;
index 693a4dd9249f15b441c4d0235f741e4e8c22d7a8..5fea0ce76e338aaf2378048c779c78a15c95b8ac 100644 (file)
@@ -241,6 +241,23 @@ int _gnutls_privkey_decode_ecc_key(asn1_node *pkey_asn,
                                   gnutls_x509_privkey_t pkey,
                                   gnutls_ecc_curve_t curve);
 
+#ifdef HAVE_LIBOQS
+int _gnutls_decode_pqc_keys(asn1_node *pkey_asn, const gnutls_datum_t *raw_key,
+                           gnutls_x509_privkey_t pkey, uint8_t *version);
+
+int _gnutls_privkey_decode_dilithium_key(asn1_node *pkey_asn,
+                                        const gnutls_datum_t *raw_key,
+                                        gnutls_x509_privkey_t pkey);
+
+int _gnutls_privkey_decode_falcon_key(asn1_node *pkey_asn,
+                                     const gnutls_datum_t *raw_key,
+                                     gnutls_x509_privkey_t pkey);
+
+int _gnutls_privkey_decode_sphincs_key(asn1_node *pkey_asn,
+                                      const gnutls_datum_t *raw_key,
+                                      gnutls_x509_privkey_t pkey);
+#endif
+
 int _gnutls_privkey_decode_eddsa_key(asn1_node *pkey_asn,
                                     const gnutls_datum_t *raw_key,
                                     gnutls_x509_privkey_t pkey,
index 1eea0a473cd182ad38ec3d0f83498f81a3be7cdf..f835a7a0d49bd9418bc9216b1959402dc891be1d 100644 (file)
@@ -177,7 +177,26 @@ void doit(void)
                                continue;
 #endif
                        }
-
+#ifndef HAVE_LIBOQS
+                       if (algorithm == GNUTLS_PK_EXP_DILITHIUM2 ||
+                           algorithm == GNUTLS_PK_EXP_DILITHIUM3 ||
+                           algorithm == GNUTLS_PK_EXP_DILITHIUM5 ||
+                           algorithm == GNUTLS_PK_EXP_FALCON512 ||
+                           algorithm == GNUTLS_PK_EXP_FALCON1024 ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHA2_128F ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHA2_128S ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHA2_192F ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHA2_192S ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHA2_256F ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHA2_256S ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHAKE_128F ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHAKE_128S ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHAKE_192F ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHAKE_192S ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHAKE_256F ||
+                           algorithm == GNUTLS_PK_EXP_SPHINCS_SHAKE_256S)
+                               continue;
+#endif
                        ret = gnutls_x509_privkey_init(&pkey);
                        if (ret < 0) {
                                fail("gnutls_x509_privkey_init: %d\n", ret);