]> git.ipfire.org Git - thirdparty/strongswan.git/commitdiff
oqs: Support of Dilithium signature algorithms
authorAndreas Steffen <andreas.steffen@strongswan.org>
Wed, 28 Oct 2020 19:09:41 +0000 (20:09 +0100)
committerTobias Brunner <tobias@strongswan.org>
Wed, 22 Mar 2023 10:35:11 +0000 (11:35 +0100)
21 files changed:
src/libstrongswan/asn1/asn1.c
src/libstrongswan/asn1/oid.txt
src/libstrongswan/credentials/auth_cfg.c
src/libstrongswan/credentials/builder.c
src/libstrongswan/credentials/builder.h
src/libstrongswan/credentials/cred_encoding.h
src/libstrongswan/credentials/keys/public_key.c
src/libstrongswan/credentials/keys/public_key.h
src/libstrongswan/crypto/hashers/hasher.c
src/libstrongswan/plugins/oqs/Makefile.am
src/libstrongswan/plugins/oqs/oqs_plugin.c
src/libstrongswan/plugins/oqs/oqs_private_key.c [new file with mode: 0644]
src/libstrongswan/plugins/oqs/oqs_private_key.h [new file with mode: 0644]
src/libstrongswan/plugins/oqs/oqs_public_key.c [new file with mode: 0644]
src/libstrongswan/plugins/oqs/oqs_public_key.h [new file with mode: 0644]
src/libstrongswan/plugins/pem/pem_encoder.c
src/libstrongswan/plugins/pem/pem_plugin.c
src/libstrongswan/plugins/pkcs8/pkcs8_builder.c
src/libstrongswan/plugins/pkcs8/pkcs8_plugin.c
src/pki/commands/gen.c
src/pki/commands/issue.c

index ef1dd9eaab0a7319356c97cae0441a7c0eeeaa84..f7f9225f2eab0887a3f46aedcfb181eaea3bb1fd 100644 (file)
@@ -58,6 +58,9 @@ chunk_t asn1_algorithmIdentifier(int oid)
                case OID_ECDSA_WITH_SHA512:
                case OID_ED25519:
                case OID_ED448:
+               case OID_DILITHIUM_2:
+               case OID_DILITHIUM_3:
+               case OID_DILITHIUM_4:
                        parameters = chunk_empty;
                        break;
                default:
index c91c1262aff5136034b50e58b0e62b82ebc0cfdb..9fb1ca41b7f171a14650a464ce83c07c76d163ee 100644 (file)
     0x01                     "internet"
       0x04                   "private"
         0x01                 "enterprise"
+          0x02               "IBM"
+            0x82             ""
+              0x0B           "QSC"
+                0x06         "dilithium-raw"
+                  0x04       "d2r"
+                    0x03     "dilithium2" OID_DILITHIUM_2
+                  0x05       "d3r"
+                    0x04     "dilithium3" OID_DILITHIUM_3
+                  0x06       "d4r"
+                    0x05     "dilithium4" OID_DILITHIUM_4
           0x82               ""
             0x37             "Microsoft"
               0x0A           ""
index 8c0e9eaff753e737e042b7d98ccb2a491bf5e70d..d85941c43c96a1ce11bf2f7efe025bbb185c7914 100644 (file)
@@ -591,24 +591,27 @@ METHOD(auth_cfg_t, add_pubkey_constraints, void,
                        signature_scheme_t scheme;
                        key_type_t key;
                } schemes[] = {
-                       { "md5",                SIGN_RSA_EMSA_PKCS1_MD5,                KEY_RSA,         },
-                       { "sha1",               SIGN_RSA_EMSA_PKCS1_SHA1,               KEY_RSA,         },
-                       { "sha224",             SIGN_RSA_EMSA_PKCS1_SHA2_224,   KEY_RSA,         },
-                       { "sha256",             SIGN_RSA_EMSA_PKCS1_SHA2_256,   KEY_RSA,         },
-                       { "sha384",             SIGN_RSA_EMSA_PKCS1_SHA2_384,   KEY_RSA,         },
-                       { "sha512",             SIGN_RSA_EMSA_PKCS1_SHA2_512,   KEY_RSA,         },
-                       { "sha1",               SIGN_ECDSA_WITH_SHA1_DER,               KEY_ECDSA,       },
-                       { "sha256",             SIGN_ECDSA_WITH_SHA256_DER,             KEY_ECDSA,       },
-                       { "sha384",             SIGN_ECDSA_WITH_SHA384_DER,             KEY_ECDSA,       },
-                       { "sha512",             SIGN_ECDSA_WITH_SHA512_DER,             KEY_ECDSA,       },
-                       { "sha256",             SIGN_ECDSA_256,                                 KEY_ECDSA,       },
-                       { "sha384",             SIGN_ECDSA_384,                                 KEY_ECDSA,       },
-                       { "sha512",             SIGN_ECDSA_521,                                 KEY_ECDSA,       },
-                       { "sha256",             SIGN_BLISS_WITH_SHA2_256,               KEY_BLISS,       },
-                       { "sha384",             SIGN_BLISS_WITH_SHA2_384,               KEY_BLISS,       },
-                       { "sha512",             SIGN_BLISS_WITH_SHA2_512,               KEY_BLISS,       },
-                       { "identity",   SIGN_ED25519,                                   KEY_ED25519, },
-                       { "identity",   SIGN_ED448,                                             KEY_ED448,       },
+                       { "md5",                SIGN_RSA_EMSA_PKCS1_MD5,                KEY_RSA,             },
+                       { "sha1",               SIGN_RSA_EMSA_PKCS1_SHA1,               KEY_RSA,             },
+                       { "sha224",             SIGN_RSA_EMSA_PKCS1_SHA2_224,   KEY_RSA,             },
+                       { "sha256",             SIGN_RSA_EMSA_PKCS1_SHA2_256,   KEY_RSA,             },
+                       { "sha384",             SIGN_RSA_EMSA_PKCS1_SHA2_384,   KEY_RSA,             },
+                       { "sha512",             SIGN_RSA_EMSA_PKCS1_SHA2_512,   KEY_RSA,             },
+                       { "sha1",               SIGN_ECDSA_WITH_SHA1_DER,               KEY_ECDSA,           },
+                       { "sha256",             SIGN_ECDSA_WITH_SHA256_DER,             KEY_ECDSA,           },
+                       { "sha384",             SIGN_ECDSA_WITH_SHA384_DER,             KEY_ECDSA,           },
+                       { "sha512",             SIGN_ECDSA_WITH_SHA512_DER,             KEY_ECDSA,           },
+                       { "sha256",             SIGN_ECDSA_256,                                 KEY_ECDSA,           },
+                       { "sha384",             SIGN_ECDSA_384,                                 KEY_ECDSA,           },
+                       { "sha512",             SIGN_ECDSA_521,                                 KEY_ECDSA,           },
+                       { "sha256",             SIGN_BLISS_WITH_SHA2_256,               KEY_BLISS,           },
+                       { "sha384",             SIGN_BLISS_WITH_SHA2_384,               KEY_BLISS,           },
+                       { "sha512",             SIGN_BLISS_WITH_SHA2_512,               KEY_BLISS,           },
+                       { "identity",   SIGN_ED25519,                                   KEY_ED25519,     },
+                       { "identity",   SIGN_ED448,                                             KEY_ED448,           },
+                       { "identity",   SIGN_DILITHIUM_2,                               KEY_DILITHIUM_2, },
+                       { "identity",   SIGN_DILITHIUM_3,                               KEY_DILITHIUM_3, },
+                       { "identity",   SIGN_DILITHIUM_4,                               KEY_DILITHIUM_4, },
                };
 
                if (expected_strength != AUTH_RULE_MAX)
index bb50e097f49299e6867e2b03d6b339d2df78f658..063c2c74b1fe530c31a67e2b06109a236128928e 100644 (file)
@@ -77,6 +77,8 @@ ENUM(builder_part_names, BUILD_FROM_FILE, BUILD_END,
        "BUILD_THRESHOLD",
        "BUILD_EDDSA_PUB",
        "BUILD_EDDSA_PRIV_ASN1_DER",
+       "BUILD_PRIV_ASN1_DER",
        "BUILD_CRITICAL_EXTENSION",
+       "BUILD_DRBG",
        "BUILD_END",
 );
index 6d143dd4fc0cf076fb7bf3fa16bc64ad14dd2e03..ae0d7838692d6e75de6a5e2d677fe9b2aea7fe9b 100644 (file)
@@ -163,8 +163,12 @@ enum builder_part_t {
        BUILD_EDDSA_PUB,
        /** DER encoded ASN.1 EdDSA private key */
        BUILD_EDDSA_PRIV_ASN1_DER,
+       /** DER encoded ASN.1 private key (usually OCTET_STRING) */
+       BUILD_PRIV_ASN1_DER,
        /** OID of an [unsupported] critical extension */
        BUILD_CRITICAL_EXTENSION,
+       /** DRBG to be used for crypto tests */
+       BUILD_DRBG,
        /** end of variable argument builder list */
        BUILD_END,
 };
index 0b469d039afd136b4236d30f7033a073f5e7338e..317936760f850999325544d1066cbec72a837d5d 100644 (file)
@@ -145,6 +145,10 @@ enum cred_encoding_part_t {
        CRED_PART_PKCS10_ASN1_DER,
        /** a PGP encoded certificate */
        CRED_PART_PGP_CERT,
+       /** a DER encoded public key */
+       CRED_PART_PUB_ASN1_DER,
+       /** a DER encoded private key */
+       CRED_PART_PRIV_ASN1_DER,
        /** a DER encoded EdDSA public key */
        CRED_PART_EDDSA_PUB_ASN1_DER,
        /** a DER encoded EdDSA private key */
index f2e3b9bd36edeb303f58f30e7f5d0d6eb4504eac..4028bd30135e616b11cae35b1e653c3dbdd04689 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2015-2017 Tobias Brunner
- * Copyright (C) 2014-2016 Andreas Steffen
+ * Copyright (C) 2014-2020 Andreas Steffen
  * Copyright (C) 2007 Martin Willi
  *
  * Copyright (C) secunet Security Networks AG
@@ -28,6 +28,9 @@ ENUM(key_type_names, KEY_ANY, KEY_BLISS,
        "DSA",
        "ED25519",
        "ED448",
+       "Dilithium2",
+       "Dilithium3",
+       "Dilithium4",
        "BLISS"
 );
 
@@ -55,6 +58,9 @@ ENUM(signature_scheme_names, SIGN_UNKNOWN, SIGN_BLISS_WITH_SHA3_512,
        "ECDSA-521",
        "ED25519",
        "ED448",
+       "DILITHIUM_2",
+       "DILITHIUM_3",
+       "DILITHIUM_4",
        "BLISS_WITH_SHA2_256",
        "BLISS_WITH_SHA2_384",
        "BLISS_WITH_SHA2_512",
@@ -116,6 +122,50 @@ bool public_key_has_fingerprint(public_key_t *public, chunk_t fingerprint)
        return FALSE;
 }
 
+/**
+ * See header.
+ */
+int key_type_to_oid(key_type_t type)
+{
+       switch (type)
+       {
+               case KEY_ED25519:
+                       return OID_ED25519;
+               case KEY_ED448:
+                       return OID_ED448;
+               case KEY_DILITHIUM_2:
+                       return OID_DILITHIUM_2;
+               case KEY_DILITHIUM_3:
+                       return OID_DILITHIUM_3;
+               case KEY_DILITHIUM_4:
+                       return OID_DILITHIUM_4;
+               default:
+                       return OID_UNKNOWN;
+       }
+}
+
+/**
+ * See header.
+ */
+key_type_t key_type_from_oid(int oid)
+{
+       switch (oid)
+       {
+               case OID_ED25519:
+                       return KEY_ED25519;
+               case OID_ED448:
+                       return KEY_ED448;
+               case OID_DILITHIUM_2:
+                       return KEY_DILITHIUM_2;
+               case OID_DILITHIUM_3:
+                       return KEY_DILITHIUM_3;
+               case OID_DILITHIUM_4:
+                       return KEY_DILITHIUM_4;
+               default:
+                       return KEY_ANY;
+       }
+}
+
 /*
  * Defined in header.
  */
@@ -164,6 +214,12 @@ signature_scheme_t signature_scheme_from_oid(int oid)
                        return SIGN_ED25519;
                case OID_ED448:
                        return SIGN_ED448;
+               case OID_DILITHIUM_2:
+                       return SIGN_DILITHIUM_2;
+               case OID_DILITHIUM_3:
+                       return SIGN_DILITHIUM_3;
+               case OID_DILITHIUM_4:
+                       return SIGN_DILITHIUM_4;
                case OID_BLISS_PUBLICKEY:
                case OID_BLISS_WITH_SHA2_512:
                        return SIGN_BLISS_WITH_SHA2_512;
@@ -229,6 +285,12 @@ int signature_scheme_to_oid(signature_scheme_t scheme)
                        return OID_ED25519;
                case SIGN_ED448:
                        return OID_ED448;
+               case SIGN_DILITHIUM_2:
+                       return OID_DILITHIUM_2;
+               case SIGN_DILITHIUM_3:
+                       return OID_DILITHIUM_3;
+               case SIGN_DILITHIUM_4:
+                       return OID_DILITHIUM_4;
                case SIGN_BLISS_WITH_SHA2_256:
                        return OID_BLISS_WITH_SHA2_256;
                case SIGN_BLISS_WITH_SHA2_384:
@@ -268,20 +330,26 @@ static struct {
        int max_keysize;
        signature_params_t params;
 } scheme_map[] = {
-       { KEY_RSA,  3072, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha256, }},
-       { KEY_RSA,  7680, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha384, }},
-       { KEY_RSA,     0, { .scheme = SIGN_RSA_EMSA_PSS, .params = &pss_params_sha512, }},
-       { KEY_RSA,  3072, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256 }},
-       { KEY_RSA,  7680, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_384 }},
-       { KEY_RSA,     0, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_512 }},
-       { KEY_ECDSA, 256, { .scheme = SIGN_ECDSA_WITH_SHA256_DER }},
-       { KEY_ECDSA, 384, { .scheme = SIGN_ECDSA_WITH_SHA384_DER }},
-       { KEY_ECDSA,   0, { .scheme = SIGN_ECDSA_WITH_SHA512_DER }},
-       { KEY_ED25519, 0, { .scheme = SIGN_ED25519 }},
-       { KEY_ED448,   0, { .scheme = SIGN_ED448 }},
-       { KEY_BLISS, 128, { .scheme = SIGN_BLISS_WITH_SHA2_256 }},
-       { KEY_BLISS, 192, { .scheme = SIGN_BLISS_WITH_SHA2_384 }},
-       { KEY_BLISS,   0, { .scheme = SIGN_BLISS_WITH_SHA2_512 }},
+       { KEY_RSA,      3072, { .scheme = SIGN_RSA_EMSA_PSS,
+                               .params = &pss_params_sha256, }},
+       { KEY_RSA,      7680, { .scheme = SIGN_RSA_EMSA_PSS,
+                               .params = &pss_params_sha384, }},
+       { KEY_RSA,         0, { .scheme = SIGN_RSA_EMSA_PSS,
+                               .params = &pss_params_sha512, }},
+       { KEY_RSA,      3072, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_256 }},
+       { KEY_RSA,      7680, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_384 }},
+       { KEY_RSA,         0, { .scheme = SIGN_RSA_EMSA_PKCS1_SHA2_512 }},
+       { KEY_ECDSA,     256, { .scheme = SIGN_ECDSA_WITH_SHA256_DER }},
+       { KEY_ECDSA,     384, { .scheme = SIGN_ECDSA_WITH_SHA384_DER }},
+       { KEY_ECDSA,       0, { .scheme = SIGN_ECDSA_WITH_SHA512_DER }},
+       { KEY_ED25519,     0, { .scheme = SIGN_ED25519 }},
+       { KEY_ED448,       0, { .scheme = SIGN_ED448 }},
+       { KEY_DILITHIUM_2, 0, { .scheme = SIGN_DILITHIUM_2}},
+       { KEY_DILITHIUM_3, 0, { .scheme = SIGN_DILITHIUM_3}},
+       { KEY_DILITHIUM_4, 0, { .scheme = SIGN_DILITHIUM_4}},
+       { KEY_BLISS,     128, { .scheme = SIGN_BLISS_WITH_SHA2_256 }},
+       { KEY_BLISS,     192, { .scheme = SIGN_BLISS_WITH_SHA2_384 }},
+       { KEY_BLISS,       0, { .scheme = SIGN_BLISS_WITH_SHA2_512 }},
 };
 
 /**
@@ -370,6 +438,12 @@ key_type_t key_type_from_signature_scheme(signature_scheme_t scheme)
                        return KEY_ED25519;
                case SIGN_ED448:
                        return KEY_ED448;
+               case SIGN_DILITHIUM_2:
+                       return KEY_DILITHIUM_2;
+               case SIGN_DILITHIUM_3:
+                       return KEY_DILITHIUM_3;
+               case SIGN_DILITHIUM_4:
+                       return KEY_DILITHIUM_4;
                case SIGN_BLISS_WITH_SHA2_256:
                case SIGN_BLISS_WITH_SHA2_384:
                case SIGN_BLISS_WITH_SHA2_512:
index 55c0181ff3afb9d98492ad41f3c96596890c58ac..ba0e092e96f3997e3dfc423b64e2618bd1793c7f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2015-2017 Tobias Brunner
- * Copyright (C) 2014-2017 Andreas Steffen
+ * Copyright (C) 2014-2020 Andreas Steffen
  * Copyright (C) 2007 Martin Willi
  *
  * Copyright (C) secunet Security Networks AG
@@ -48,8 +48,14 @@ enum key_type_t {
        KEY_ED25519 = 4,
        /** Ed448   PureEdDSA instance as in RFC 8032 */
        KEY_ED448   = 5,
+       /** Dilithium2 NIST Round 3 Submission candidate */
+       KEY_DILITHIUM_2 = 6,
+       /** Dilithium3 NIST Round 3 Submission candidate */
+       KEY_DILITHIUM_3 = 7,
+       /** Dilithium4 NIST Round 3 Submission candidate */
+       KEY_DILITHIUM_4 = 8,
        /** BLISS */
-       KEY_BLISS = 6,
+       KEY_BLISS = 9,
 };
 
 /**
@@ -111,6 +117,12 @@ enum signature_scheme_t {
        SIGN_ED25519,
        /** PureEdDSA on Curve448 as in RFC 8410                           */
        SIGN_ED448,
+       /** Dilithium2 NIST Round 3 Submission signature                   */
+       SIGN_DILITHIUM_2,
+       /** Dilithium3 NIST Round 3 Submission signature                   */
+       SIGN_DILITHIUM_3,
+       /** Dilithium4 NIST Round 3 Submission signature                   */
+       SIGN_DILITHIUM_4,
        /** BLISS with SHA-2_256                                           */
        SIGN_BLISS_WITH_SHA2_256,
        /** BLISS with SHA-2_384                                           */
@@ -265,6 +277,22 @@ bool public_key_equals(public_key_t *public, public_key_t *other);
  */
 bool public_key_has_fingerprint(public_key_t *public, chunk_t fingerprint);
 
+/**
+ * Return OID for a given key type
+ *
+ * @param type         type of the key
+ * @return                     OID
+ */
+int key_type_to_oid(key_type_t type);
+
+/**
+ * Return key type for a given OID
+ *
+ * @param oid          OID
+ * @return                     type of the key
+ */
+key_type_t key_type_from_oid(int oid);
+
 /**
  * Conversion of ASN.1 signature or hash OID to signature scheme.
  *
index 61533fcf04bb0f9695213a943fa19dec29abcde8..d2fcf65225ad057404d706b9919d3b1e1eed4f82 100644 (file)
@@ -156,6 +156,9 @@ hash_algorithm_t hasher_algorithm_from_oid(int oid)
                        return HASH_SHA3_512;
                case OID_ED25519:
                case OID_ED448:
+               case OID_DILITHIUM_2:
+               case OID_DILITHIUM_3:
+               case OID_DILITHIUM_4:
                        return HASH_IDENTITY;
                default:
                        return HASH_UNKNOWN;
@@ -477,6 +480,31 @@ int hasher_signature_algorithm_to_oid(hash_algorithm_t alg, key_type_t key)
                                default:
                                        return OID_UNKNOWN;
                        }
+               case KEY_DILITHIUM_2:
+                       switch (alg)
+                       {
+                               case HASH_IDENTITY:
+                                       return OID_DILITHIUM_2;
+                               default:
+                                       return OID_UNKNOWN;
+                       }
+               case KEY_DILITHIUM_3:
+                       switch (alg)
+                       {
+                               case HASH_IDENTITY:
+                                       return OID_DILITHIUM_3;
+                               default:
+                                       return OID_UNKNOWN;
+                       }
+               case KEY_DILITHIUM_4:
+                       switch (alg)
+                       {
+                               case HASH_IDENTITY:
+                                       return OID_DILITHIUM_4;
+                               default:
+                                       return OID_UNKNOWN;
+                       }
+
                case KEY_BLISS:
                        switch (alg)
                        {
@@ -521,6 +549,9 @@ hash_algorithm_t hasher_from_signature_scheme(signature_scheme_t scheme,
                        break;
                case SIGN_ED25519:
                case SIGN_ED448:
+               case SIGN_DILITHIUM_2:
+               case SIGN_DILITHIUM_3:
+               case SIGN_DILITHIUM_4:
                        return HASH_IDENTITY;
                case SIGN_RSA_EMSA_PKCS1_MD5:
                        return HASH_MD5;
index 0d96552df10b76440d9cbca8cbd99d9796a42e2a..fda6513fd7b8ee0586641fca7b6039a59a792e39 100644 (file)
@@ -20,7 +20,9 @@ plugin_LTLIBRARIES = libstrongswan-oqs.la
 endif
 
 libstrongswan_oqs_la_SOURCES = \
-       oqs_plugin.h oqs_plugin.c
+       oqs_plugin.h oqs_plugin.c \
+       oqs_public_key.h oqs_public_key.c \
+       oqs_private_key.h oqs_private_key.c
 
 libstrongswan_oqs_la_LDFLAGS = -module -avoid-version
 
index 176a898daadcdb45ccf81b38e73ebd0ed0ed7aef..288cfa63d83f848e8adbed5a7c0fd5e24c3b34e7 100644 (file)
@@ -17,6 +17,8 @@
 #include "oqs_plugin.h"
 #include "oqs_kem.h"
 #include "oqs_drbg.h"
+#include "oqs_public_key.h"
+#include "oqs_private_key.h"
 
 #include <library.h>
 #include <threading/thread_value.h>
@@ -66,6 +68,28 @@ METHOD(plugin_t, get_features, int,
                        PLUGIN_PROVIDE(KE, KE_SIKE_L2),
                        PLUGIN_PROVIDE(KE, KE_SIKE_L3),
                        PLUGIN_PROVIDE(KE, KE_SIKE_L5),
+               /* private/public keys */
+               PLUGIN_REGISTER(PRIVKEY, oqs_private_key_load, TRUE),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_2),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_3),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_4),
+               PLUGIN_REGISTER(PRIVKEY_GEN, oqs_private_key_gen, FALSE),
+                       PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_DILITHIUM_2),
+                       PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_DILITHIUM_3),
+                       PLUGIN_PROVIDE(PRIVKEY_GEN, KEY_DILITHIUM_4),
+               PLUGIN_REGISTER(PUBKEY, oqs_public_key_load, TRUE),
+                       PLUGIN_PROVIDE(PUBKEY, KEY_DILITHIUM_2),
+                       PLUGIN_PROVIDE(PUBKEY, KEY_DILITHIUM_3),
+                       PLUGIN_PROVIDE(PUBKEY, KEY_DILITHIUM_4),
+                       PLUGIN_PROVIDE(PUBKEY, KEY_ANY),
+               /* signature schemes, private */
+               PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_DILITHIUM_2),
+               PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_DILITHIUM_3),
+               PLUGIN_PROVIDE(PRIVKEY_SIGN, SIGN_DILITHIUM_4),
+               /* signature verification schemes */
+               PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_DILITHIUM_2),
+               PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_DILITHIUM_3),
+               PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_DILITHIUM_4),
        };
        *features = f;
        return countof(f);
diff --git a/src/libstrongswan/plugins/oqs/oqs_private_key.c b/src/libstrongswan/plugins/oqs/oqs_private_key.c
new file mode 100644 (file)
index 0000000..58004de
--- /dev/null
@@ -0,0 +1,375 @@
+/*
+ * Copyright (C) 2020 Andreas Steffen
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "oqs_private_key.h"
+#include "oqs_public_key.h"
+#include "oqs_drbg.h"
+
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <asn1/oid.h>
+#include <crypto/rngs/rng_tester.h>
+
+#include <oqs/oqs.h>
+
+#define _GNU_SOURCE
+#include <stdlib.h>
+
+typedef struct private_oqs_private_key_t private_oqs_private_key_t;
+
+/**
+ * Private data of a oqs_private_key_t object.
+ */
+struct private_oqs_private_key_t {
+       /**
+        * Public interface for this signer.
+        */
+       oqs_private_key_t public;
+
+       /**
+        * Key type
+        */
+       key_type_t type;
+
+       /**
+        * OID of the key type
+        */
+       int oid;
+
+       /**
+        * Internal OQS_SIG object
+        */
+       OQS_SIG *sig;
+
+       /**
+        * Public Key
+        */
+       chunk_t public_key;
+
+       /**
+        * Secret Key
+        */
+       chunk_t secret_key;
+
+       /**
+        * Deterministic Random Bit Generator (DRBG)
+        */
+       drbg_t *drbg;
+
+       /**
+        * reference count
+        */
+       refcount_t ref;
+};
+
+METHOD(private_key_t, get_type, key_type_t,
+       private_oqs_private_key_t *this)
+{
+       return this->type;
+}
+
+
+METHOD(private_key_t, sign, bool,
+       private_oqs_private_key_t *this, signature_scheme_t scheme, void *params,
+       chunk_t data, chunk_t *signature)
+{
+       if (key_type_from_signature_scheme(scheme) != this->type)
+       {
+               DBG1(DBG_LIB, "signature scheme %N not supported",
+                                          signature_scheme_names, scheme);
+               return FALSE;
+       }
+       *signature = chunk_alloc(this->sig->length_signature);
+
+       if (OQS_SIG_sign(this->sig, signature->ptr, &signature->len,
+                                        data.ptr, data.len, this->secret_key.ptr) != OQS_SUCCESS)
+       {
+               chunk_free(signature);
+               return FALSE;
+       }
+       return TRUE;
+}
+
+METHOD(private_key_t, decrypt, bool,
+       private_oqs_private_key_t *this, encryption_scheme_t scheme,
+       chunk_t crypto, chunk_t *plain)
+{
+       DBG1(DBG_LIB, "encryption scheme %N not supported",
+                                  encryption_scheme_names, scheme);
+       return FALSE;
+}
+
+METHOD(private_key_t, get_keysize, int,
+       private_oqs_private_key_t *this)
+{
+       return this->public_key.len;
+}
+
+METHOD(private_key_t, get_public_key, public_key_t*,
+       private_oqs_private_key_t *this)
+{
+       return lib->creds->create(lib->creds, CRED_PUBLIC_KEY, this->type,
+                                                         BUILD_BLOB, this->public_key, BUILD_END);
+}
+
+METHOD(private_key_t, get_encoding, bool,
+       private_oqs_private_key_t *this, cred_encoding_type_t type,
+       chunk_t *encoding)
+{
+       switch (type)
+       {
+               case PRIVKEY_ASN1_DER:
+               case PRIVKEY_PEM:
+               {
+                       bool success = TRUE;
+                       chunk_t blob;
+
+                       blob = chunk_cat("cc", this->secret_key, this->public_key);
+
+                       *encoding = asn1_wrap(ASN1_SEQUENCE, "cms",
+                                                       ASN1_INTEGER_0,
+                                                       asn1_algorithmIdentifier(this->oid),
+                                                       asn1_wrap(ASN1_OCTET_STRING, "s",
+                                                               asn1_simple_object(ASN1_OCTET_STRING, blob)
+                                                       )
+                                               );
+                       if (type == PRIVKEY_PEM)
+                       {
+                               chunk_t asn1_encoding = *encoding;
+
+                               success = lib->encoding->encode(lib->encoding, PRIVKEY_PEM,
+                                                               NULL, encoding, CRED_PART_PRIV_ASN1_DER,
+                                                               asn1_encoding, CRED_PART_END);
+                               chunk_clear(&asn1_encoding);
+                       }
+                       chunk_clear(&blob);
+
+                       return success;
+               }
+               default:
+                       return FALSE;
+       }
+}
+
+METHOD(private_key_t, get_fingerprint, bool,
+       private_oqs_private_key_t *this, cred_encoding_type_t type,
+       chunk_t *fp)
+{
+       bool success;
+
+       if (lib->encoding->get_cache(lib->encoding, type, this, fp))
+       {
+               return TRUE;
+       }
+       success = oqs_public_key_fingerprint(this->public_key, this->oid, type, fp);
+       if (success)
+       {
+               lib->encoding->cache(lib->encoding, type, this, *fp);
+       }
+       return success;
+}
+
+METHOD(private_key_t, get_ref, private_key_t*,
+       private_oqs_private_key_t *this)
+{
+       ref_get(&this->ref);
+       return &this->public.key;
+}
+
+METHOD(private_key_t, destroy, void,
+       private_oqs_private_key_t *this)
+{
+       if (ref_put(&this->ref))
+       {
+               lib->encoding->clear_cache(lib->encoding, this);
+               DESTROY_IF(this->drbg);
+               OQS_SIG_free(this->sig);
+               chunk_clear(&this->secret_key);
+               chunk_free(&this->public_key);
+               free(this);
+       }
+}
+
+/**
+ * Internal generic constructor
+ */
+static private_oqs_private_key_t *oqs_private_key_create_empty(key_type_t type)
+{
+       private_oqs_private_key_t *this;
+       char *sig_alg = NULL;
+       OQS_SIG *sig;
+
+       switch (type)
+       {
+               case KEY_DILITHIUM_2:
+                       sig_alg = OQS_SIG_alg_dilithium_2;
+                       break;
+               case KEY_DILITHIUM_3:
+                       sig_alg = OQS_SIG_alg_dilithium_3;
+                       break;
+               case KEY_DILITHIUM_4:
+                       sig_alg = OQS_SIG_alg_dilithium_4;
+                       break;
+               default:
+                       return NULL;
+       }
+
+       if (OQS_randombytes_switch_algorithm(OQS_RAND_alg_openssl) != OQS_SUCCESS)
+       {
+               DBG1(DBG_LIB, "OQS RNG could not be switched to openssl");
+               return NULL;
+       }
+
+       sig = OQS_SIG_new(sig_alg);
+       if (!sig)
+       {
+               DBG1(DBG_LIB, "OQS '%s' signature algorithm not available", sig_alg);
+               return NULL;
+       }
+
+       INIT(this,
+               .public = {
+                       .key = {
+                               .get_type = _get_type,
+                               .sign = _sign,
+                               .decrypt = _decrypt,
+                               .get_keysize = _get_keysize,
+                               .get_public_key = _get_public_key,
+                               .equals = private_key_equals,
+                               .belongs_to = private_key_belongs_to,
+                               .get_fingerprint = _get_fingerprint,
+                               .has_fingerprint = private_key_has_fingerprint,
+                               .get_encoding = _get_encoding,
+                               .get_ref = _get_ref,
+                               .destroy = _destroy,
+                       },
+               },
+               .type = type,
+               .oid = key_type_to_oid(type),
+               .sig = sig,
+               .secret_key = chunk_alloc(sig->length_secret_key),
+               .public_key = chunk_alloc(sig->length_public_key),
+               .ref = 1,
+       );
+       return this;
+}
+
+/**
+ * See header.
+ */
+oqs_private_key_t *oqs_private_key_gen(key_type_t type, va_list args)
+{
+       private_oqs_private_key_t *this;
+       drbg_t *drbg = NULL;
+
+       if (!oqs_supported(type))
+       {
+               return NULL;
+       }
+
+       while (TRUE)
+       {
+               switch (va_arg(args, builder_part_t))
+               {
+                       case BUILD_KEY_SIZE:
+                               /* key_size argument is not needed */
+                               va_arg(args, u_int);
+                               continue;
+                       case BUILD_DRBG:
+                               drbg = va_arg(args, drbg_t*);
+                               continue;
+               case BUILD_END:
+                               break;
+                       default:
+                               return NULL;
+               }
+               break;
+       }
+
+       this = oqs_private_key_create_empty(type);
+       if (!this)
+       {
+               return NULL;
+       }
+
+       if (drbg)
+       {
+               this->drbg = drbg->get_ref(drbg);
+               OQS_randombytes_custom_algorithm(oqs_drbg_rand);
+               oqs_drbg_set(this->drbg);
+       }
+
+       if (OQS_SIG_keypair(this->sig, this->public_key.ptr,
+                                                                  this->secret_key.ptr) != OQS_SUCCESS)
+       {
+               DBG1(DBG_LIB, "OQS_SIG_keypair failed!");
+               destroy(this);
+               return NULL;
+       }
+
+       return &this->public;
+}
+
+/**
+ * See header.
+ */
+oqs_private_key_t *oqs_private_key_load(key_type_t type, va_list args)
+{
+       private_oqs_private_key_t *this;
+       chunk_t blob = chunk_empty;
+
+       if (!oqs_supported(type))
+       {
+               return NULL;
+       }
+
+       while (TRUE)
+       {
+               switch (va_arg(args, builder_part_t))
+               {
+                       case BUILD_PRIV_ASN1_DER:
+                               blob = va_arg(args, chunk_t);
+                               continue;
+                       case BUILD_END:
+                               break;
+                       default:
+                               return NULL;
+               }
+               break;
+       }
+
+       if (!asn1_parse_simple_object(&blob, ASN1_OCTET_STRING, 0, "PrivateKey"))
+       {
+               return NULL;
+       }
+
+       this = oqs_private_key_create_empty(type);
+       if (!this)
+       {
+               return NULL;
+       }
+
+       /* Dilithium private keys contain the public key */
+       if (blob.len != this->sig->length_public_key + this->sig->length_secret_key)
+       {
+               return NULL;
+       }
+       memcpy(this->secret_key.ptr, blob.ptr, this->secret_key.len);
+       blob = chunk_skip(blob, this->secret_key.len);
+       memcpy(this->public_key.ptr, blob.ptr, this->public_key.len);
+
+       return &this->public;
+}
diff --git a/src/libstrongswan/plugins/oqs/oqs_private_key.h b/src/libstrongswan/plugins/oqs/oqs_private_key.h
new file mode 100644 (file)
index 0000000..df62b15
--- /dev/null
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2020 Andreas Steffen
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup oqs_private_key oqs_private_key
+ * @{ @ingroup oqs_p
+ */
+
+#ifndef OQS_PRIVATE_KEY_H_
+#define OQS_PRIVATE_KEY_H_
+
+#include <credentials/builder.h>
+#include <credentials/keys/private_key.h>
+
+typedef struct oqs_private_key_t oqs_private_key_t;
+
+/**
+ * Private_key_t implementation of OQS signature algorithm.
+ */
+struct oqs_private_key_t {
+
+       /**
+        * Implements private_key_t interface
+        */
+       private_key_t key;
+};
+
+/**
+ * Generate a OQS private key.
+ *
+ * @param type         type of the key
+ * @param args         builder_part_t argument list
+ * @return                     generated key, NULL on failure
+ */
+oqs_private_key_t *oqs_private_key_gen(key_type_t type, va_list args);
+
+/**
+ * Load a OQS private key.
+ *
+ * @param type         type of the key
+ * @param args         builder_part_t argument list
+ * @return                     loaded key, NULL on failure
+ */
+oqs_private_key_t *oqs_private_key_load(key_type_t type, va_list args);
+
+#endif /** OQS_PRIVATE_KEY_H_ @}*/
diff --git a/src/libstrongswan/plugins/oqs/oqs_public_key.c b/src/libstrongswan/plugins/oqs/oqs_public_key.c
new file mode 100644 (file)
index 0000000..2cafe09
--- /dev/null
@@ -0,0 +1,345 @@
+/*
+ * Copyright (C) 2020 Andreas Steffen
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include "oqs_public_key.h"
+
+#include <asn1/asn1.h>
+#include <asn1/asn1_parser.h>
+#include <asn1/oid.h>
+
+#include <oqs/oqs.h>
+
+typedef struct private_oqs_public_key_t private_oqs_public_key_t;
+
+/**
+ * Private data structure with signing context.
+ */
+struct private_oqs_public_key_t {
+       /**
+        * Public interface for this signer.
+        */
+       oqs_public_key_t public;
+
+       /**
+        * Key type
+        */
+       key_type_t type;
+
+       /**
+        * OID of the key type
+        */
+       int oid;
+
+       /**
+        * Internal OQS_SiG object
+        */
+       OQS_SIG *sig;
+
+       /**
+        * Public key
+        */
+       chunk_t public_key;
+
+       /**
+        * reference counter
+        */
+       refcount_t ref;
+};
+
+METHOD(public_key_t, get_type, key_type_t,
+       private_oqs_public_key_t *this)
+{
+       return this->type;
+}
+
+METHOD(public_key_t, verify, bool,
+       private_oqs_public_key_t *this, signature_scheme_t scheme, void *params,
+       chunk_t data, chunk_t signature)
+{
+       if (key_type_from_signature_scheme(scheme) != this->type)
+       {
+               DBG1(DBG_LIB, "signature scheme %N not supported",
+                                          signature_scheme_names, scheme);
+               return FALSE;
+       }
+       return OQS_SIG_verify(this->sig, data.ptr, data.len, signature.ptr,
+                                                 signature.len, this->public_key.ptr) == OQS_SUCCESS;
+}
+
+METHOD(public_key_t, encrypt_, bool,
+       private_oqs_public_key_t *this, encryption_scheme_t scheme,
+       chunk_t plain, chunk_t *crypto)
+{
+       DBG1(DBG_LIB, "encryption scheme %N not supported",
+                                  encryption_scheme_names, scheme);
+       return FALSE;
+}
+
+METHOD(public_key_t, get_keysize, int,
+       private_oqs_public_key_t *this)
+{
+       return this->public_key.len;
+}
+
+static chunk_t public_key_info_encode(chunk_t pubkey, int oid)
+{
+       return asn1_wrap(ASN1_SEQUENCE, "mm",
+                                               asn1_algorithmIdentifier(oid),
+                                               asn1_bitstring("c", pubkey)
+                                        );
+}
+
+METHOD(public_key_t, get_encoding, bool,
+       private_oqs_public_key_t *this, cred_encoding_type_t type,
+       chunk_t *encoding)
+{
+       bool success = TRUE;
+
+       *encoding = public_key_info_encode(this->public_key, this->oid);
+
+       if (type != PUBKEY_SPKI_ASN1_DER)
+       {
+               chunk_t asn1_encoding = *encoding;
+
+               success = lib->encoding->encode(lib->encoding, type,
+                                               NULL, encoding, CRED_PART_PUB_ASN1_DER,
+                                               asn1_encoding, CRED_PART_END);
+               chunk_clear(&asn1_encoding);
+       }
+
+       return success;
+}
+
+METHOD(public_key_t, get_fingerprint, bool,
+       private_oqs_public_key_t *this, cred_encoding_type_t type, chunk_t *fp)
+{
+       bool success;
+
+       if (lib->encoding->get_cache(lib->encoding, type, this, fp))
+       {
+               return TRUE;
+       }
+       success = oqs_public_key_fingerprint(this->public_key, this->oid, type, fp);
+       if (success)
+       {
+               lib->encoding->cache(lib->encoding, type, this, *fp);
+       }
+
+       return success;
+}
+
+METHOD(public_key_t, get_ref, public_key_t*,
+       private_oqs_public_key_t *this)
+{
+       ref_get(&this->ref);
+       return &this->public.key;
+}
+
+METHOD(public_key_t, destroy, void,
+       private_oqs_public_key_t *this)
+{
+       if (ref_put(&this->ref))
+       {
+               chunk_free(&this->public_key);
+               lib->encoding->clear_cache(lib->encoding, this);
+               free(this);
+       }
+}
+
+/**
+ * ASN.1 definition of an OQS public key
+ */
+static const asn1Object_t pubkeyObjects[] = {
+       { 0, "subjectPublicKeyInfo",ASN1_SEQUENCE,              ASN1_OBJ  }, /*  0 */
+       { 1,   "algorithm",                     ASN1_EOC,                       ASN1_RAW  }, /*  1 */
+       { 1,   "subjectPublicKey",      ASN1_BIT_STRING,        ASN1_BODY }, /*  2 */
+       { 0, "exit",                            ASN1_EOC,                       ASN1_EXIT }
+};
+#define OQS_SUBJECT_PUBLIC_KEY_ALGORITHM       1
+#define OQS_SUBJECT_PUBLIC_KEY                         2
+
+/**
+ * See header.
+ */
+oqs_public_key_t *oqs_public_key_load(key_type_t type, va_list args)
+{
+       private_oqs_public_key_t *this;
+       chunk_t asn1 = chunk_empty, blob = chunk_empty, object, param;
+       asn1_parser_t *parser;
+       bool success = FALSE;
+       int objectID;
+       char *sig_alg = NULL;
+
+       while (TRUE)
+       {
+               switch (va_arg(args, builder_part_t))
+               {
+                       case BUILD_BLOB:
+                               blob = va_arg(args, chunk_t);
+                               continue;
+                       case BUILD_BLOB_ASN1_DER:
+                               asn1 = va_arg(args, chunk_t);
+                               continue;
+                       case BUILD_END:
+                               break;
+                       default:
+                               return NULL;
+               }
+               break;
+       }
+
+       if ((blob.len == 0 && asn1.len == 0) ||
+               (blob.len > 0 && !oqs_supported(type)))
+       {
+               return NULL;
+       }
+
+       INIT(this,
+               .public = {
+                       .key = {
+                               .get_type = _get_type,
+                               .verify = _verify,
+                               .encrypt = _encrypt_,
+                               .equals = public_key_equals,
+                               .get_keysize = _get_keysize,
+                               .get_fingerprint = _get_fingerprint,
+                               .has_fingerprint = public_key_has_fingerprint,
+                               .get_encoding = _get_encoding,
+                               .get_ref = _get_ref,
+                               .destroy = _destroy,
+                       },
+               },
+               .ref = 1,
+       );
+
+       if (blob.len > 0)
+       {
+               /* raw public key */
+               this->type = type;
+               this->oid = key_type_to_oid(type);
+               this->public_key = chunk_clone(blob);
+       }
+       else
+       {
+               /* PKCS#1-encoded public key in ASN.1 DER format */
+               parser = asn1_parser_create(pubkeyObjects, asn1);
+
+               while (parser->iterate(parser, &objectID, &object))
+               {
+                       switch (objectID)
+                       {
+                               case OQS_SUBJECT_PUBLIC_KEY_ALGORITHM:
+                                       this->oid = asn1_parse_algorithmIdentifier(object,
+                                                                       parser->get_level(parser)+1, &param);
+                                       this->type = key_type_from_oid(this->oid);
+                                       if (this->type == KEY_ANY)
+                                       {
+                                               goto end;
+                                       }
+                                       break;
+                               case OQS_SUBJECT_PUBLIC_KEY:
+                                       this->public_key = chunk_clone(chunk_skip(object, 1));
+                                       break;
+                       }
+               }
+               success = parser->success(parser);
+
+end:
+               parser->destroy(parser);
+               if (!success)
+               {
+                       destroy(this);
+                       return NULL;
+               }
+       }
+
+       switch (this->type)
+       {
+               case KEY_DILITHIUM_2:
+                       sig_alg = OQS_SIG_alg_dilithium_2;
+                       break;
+               case KEY_DILITHIUM_3:
+                       sig_alg = OQS_SIG_alg_dilithium_3;
+                       break;
+               case KEY_DILITHIUM_4:
+                       sig_alg = OQS_SIG_alg_dilithium_4;
+                       break;
+               default:
+                       destroy(this);
+                       return NULL;
+       }
+
+       this->sig = OQS_SIG_new(sig_alg);
+       if (!this->sig)
+       {
+               DBG1(DBG_LIB, "OQS '%s' signature algorithm not available", sig_alg);
+               destroy(this);
+               return NULL;
+       }
+
+       return &this->public;
+}
+
+/**
+ * See header.
+ */
+bool oqs_supported(key_type_t type)
+{
+       switch (type)
+       {
+               case KEY_DILITHIUM_2:
+               case KEY_DILITHIUM_3:
+               case KEY_DILITHIUM_4:
+                       return TRUE;
+               default:
+                       return FALSE;
+       }
+}
+
+/**
+ * See header.
+ */
+bool oqs_public_key_fingerprint(chunk_t pubkey, int oid,
+                                                               cred_encoding_type_t type, chunk_t *fp)
+{
+       hasher_t *hasher;
+       chunk_t key;
+
+       switch (type)
+       {
+               case KEYID_PUBKEY_SHA1:
+                       key = chunk_clone(pubkey);
+                       break;
+               case KEYID_PUBKEY_INFO_SHA1:
+                       key = public_key_info_encode(pubkey, oid);
+                       break;
+               default:
+                       return FALSE;
+       }
+
+       hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
+       if (!hasher || !hasher->allocate_hash(hasher, key, fp))
+       {
+               DBG1(DBG_LIB, "SHA1 hash algorithm not supported");
+               DESTROY_IF(hasher);
+               free(key.ptr);
+               return FALSE;
+       }
+       hasher->destroy(hasher);
+       free(key.ptr);
+
+       return TRUE;
+}
diff --git a/src/libstrongswan/plugins/oqs/oqs_public_key.h b/src/libstrongswan/plugins/oqs/oqs_public_key.h
new file mode 100644 (file)
index 0000000..f3441ed
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2020 Andreas Steffen
+ *
+ * Copyright (C) secunet Security Networks AG
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+/**
+ * @defgroup oqs_public_key oqs_public_key
+ * @{ @ingroup oqs_p
+ */
+
+#ifndef OQS_PUBLIC_KEY_H_
+#define OQS_PUBLIC_KEY_H_
+
+#include <credentials/builder.h>
+#include <credentials/cred_encoding.h>
+#include <credentials/keys/public_key.h>
+
+typedef struct oqs_public_key_t oqs_public_key_t;
+
+/**
+ * public_key_t implementation of OQS signature algorithm
+ */
+struct oqs_public_key_t {
+
+       /**
+        * Implements the public_key_t interface
+        */
+       public_key_t key;
+};
+
+/**
+ * Load an OQS public key.
+ *
+ * @param type         type of the key
+ * @param args         builder_part_t argument list
+ * @return                     loaded key, NULL on failure
+ */
+oqs_public_key_t *oqs_public_key_load(key_type_t type, va_list args);
+
+/* The following functions are shared with the oqs_private_key class */
+
+/**
+ * Is the key type supported by OQS?
+ *
+ * @param type         type of the key
+ * @return                     TRUE if key type is supported
+ */
+bool oqs_supported(key_type_t type);
+
+/**
+ * Generate a public key fingerprint
+ *
+ * @param pubkey       public key
+ * @param oid          OID of the key type
+ * @param type         type of fingerprint to be generated
+ * @param fp           generated fingerprint (must be freed by caller)
+ * @result                     TRUE if generation was successful
+ */
+bool oqs_public_key_fingerprint(chunk_t pubkey, int oid,
+                                                               cred_encoding_type_t type, chunk_t *fp);
+
+#endif /** OQS_PUBLIC_KEY_H_ @}*/
index e5cf038de81191280a43eedc7b57432063fe1dc0..902e4931b9f79030af1fdc8eee71db24c28a6580 100644 (file)
@@ -41,6 +41,8 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
                                                                        &asn1, CRED_PART_END) ||
                                cred_encoding_args(args, CRED_PART_ECDSA_PUB_ASN1_DER,
                                                                        &asn1, CRED_PART_END) ||
+                               cred_encoding_args(args, CRED_PART_PUB_ASN1_DER,
+                                                                       &asn1, CRED_PART_END) ||
                                cred_encoding_args(args, CRED_PART_EDDSA_PUB_ASN1_DER,
                                                                        &asn1, CRED_PART_END) ||
                                cred_encoding_args(args, CRED_PART_BLISS_PUB_ASN1_DER,
@@ -99,7 +101,9 @@ bool pem_encoder_encode(cred_encoding_type_t type, chunk_t *encoding,
                                label ="BLISS PRIVATE KEY";
                                break;
                        }
-                       if (cred_encoding_args(args, CRED_PART_EDDSA_PRIV_ASN1_DER,
+                       if (cred_encoding_args(args, CRED_PART_PRIV_ASN1_DER,
+                                                                  &asn1, CRED_PART_END) ||
+                               cred_encoding_args(args, CRED_PART_EDDSA_PRIV_ASN1_DER,
                                                                   &asn1, CRED_PART_END))
                        {
                                label ="PRIVATE KEY";
index d8045ed594e8ec5de31241100b69a87ada8339e5..08ab883652f26148406533edf0e2a05ad2327d4a 100644 (file)
@@ -70,6 +70,13 @@ METHOD(plugin_t, get_features, int,
                PLUGIN_REGISTER(PRIVKEY, pem_private_key_load, FALSE),
                        PLUGIN_PROVIDE(PRIVKEY, KEY_ED448),
                                PLUGIN_DEPENDS(PRIVKEY, KEY_ED448),
+               PLUGIN_REGISTER(PRIVKEY, pem_private_key_load, FALSE),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_2),
+                               PLUGIN_DEPENDS(PRIVKEY, KEY_DILITHIUM_2),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_3),
+                               PLUGIN_DEPENDS(PRIVKEY, KEY_DILITHIUM_3),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_4),
+                               PLUGIN_DEPENDS(PRIVKEY, KEY_DILITHIUM_4),
 
                /* public key PEM decoding */
                PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE),
index 6f8499409fd21c29d981705d6d60a15edadebe32..0493fb49d9c7ba57e35f18d2e6510cd351b593b5 100644 (file)
@@ -89,6 +89,18 @@ static private_key_t *parse_private_key(chunk_t blob)
                                                type = KEY_ED448;
                                                part = BUILD_EDDSA_PRIV_ASN1_DER;
                                                break;
+                                       case OID_DILITHIUM_2:
+                                               type = KEY_DILITHIUM_2;
+                                               part = BUILD_PRIV_ASN1_DER;
+                                               break;
+                                       case OID_DILITHIUM_3:
+                                               type = KEY_DILITHIUM_3;
+                                               part = BUILD_PRIV_ASN1_DER;
+                                               break;
+                                       case OID_DILITHIUM_4:
+                                               type = KEY_DILITHIUM_4;
+                                               part = BUILD_PRIV_ASN1_DER;
+                                               break;
                                        default:
                                                /* key type not supported */
                                                goto end;
index 8841720a329d6887709d9002aa675960c3671cd3..639fccb9b25c87658ae89b9c577e314566154faa 100644 (file)
@@ -49,6 +49,9 @@ METHOD(plugin_t, get_features, int,
                        PLUGIN_PROVIDE(PRIVKEY, KEY_ECDSA),
                        PLUGIN_PROVIDE(PRIVKEY, KEY_ED25519),
                        PLUGIN_PROVIDE(PRIVKEY, KEY_ED448),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_2),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_3),
+                       PLUGIN_PROVIDE(PRIVKEY, KEY_DILITHIUM_4),
        };
        *features = f;
        return countof(f);
index b6e871f7957c31efaf832a8bb53117364eed4e9a..67a211d09b0bcedb7ba8d758b90752d66d2cf9e3 100644 (file)
@@ -53,6 +53,18 @@ static int gen()
                                {
                                        type = KEY_ED448;
                                }
+                               else if (streq(arg, "dilithium2"))
+                               {
+                                       type = KEY_DILITHIUM_2;
+                               }
+                               else if (streq(arg, "dilithium3"))
+                               {
+                                       type = KEY_DILITHIUM_3;
+                               }
+                               else if (streq(arg, "dilithium4"))
+                               {
+                                       type = KEY_DILITHIUM_4;
+                               }
                                else if (streq(arg, "bliss"))
                                {
                                        type = KEY_BLISS;
@@ -174,8 +186,9 @@ static void __attribute__ ((constructor))reg()
 {
        command_register((command_t) {
                gen, 'g', "gen", "generate a new private key",
-               {"[--type rsa|ecdsa|ed25519|ed448|bliss] [--size bits] [--safe-primes]",
-                "[--shares n] [--threshold l] [--outform der|pem]"},
+               {"[--type rsa|ecdsa|ed25519|ed448|dilithium2|dilithium3|dilithium4|bliss]",
+                "[--size bits] [--safe-primes] [--shares n] [--threshold l]",
+                "[--outform der|pem]"},
                {
                        {"help",                'h', 0, "show usage information"},
                        {"type",                't', 1, "type of key, default: rsa"},
index d8e908f0112b8eec9952b39bfde291abc3496630..547ee3eff6b02d8e2f3af1e29278512bce60ade1 100644 (file)
@@ -419,7 +419,7 @@ static int issue()
                goto end;
        }
 
-       DBG2(DBG_LIB, "Reading ca private key:");
+       DBG2(DBG_LIB, "Reading CA private key:");
        if (cakey)
        {
                private = lib->creds->create(lib->creds, CRED_PRIVATE_KEY,