From: Andreas Steffen Date: Wed, 28 Oct 2020 19:09:41 +0000 (+0100) Subject: oqs: Support of Dilithium signature algorithms X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a1c1e40574fce0aa51b5233224bc3071f1bab404;p=thirdparty%2Fstrongswan.git oqs: Support of Dilithium signature algorithms --- diff --git a/src/libstrongswan/asn1/asn1.c b/src/libstrongswan/asn1/asn1.c index 866b3c8575..a687875692 100644 --- a/src/libstrongswan/asn1/asn1.c +++ b/src/libstrongswan/asn1/asn1.c @@ -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_5: parameters = chunk_empty; break; default: diff --git a/src/libstrongswan/asn1/oid.txt b/src/libstrongswan/asn1/oid.txt index c91c1262af..2421d3ce2a 100644 --- a/src/libstrongswan/asn1/oid.txt +++ b/src/libstrongswan/asn1/oid.txt @@ -205,6 +205,16 @@ 0x01 "internet" 0x04 "private" 0x01 "enterprise" + 0x02 "IBM" + 0x82 "" + 0x0B "QSC" + 0x07 "dilithium-r3" + 0x04 "d2r" + 0x04 "dilithium2" OID_DILITHIUM_2 + 0x06 "d3r" + 0x05 "dilithium3" OID_DILITHIUM_3 + 0x08 "d5r" + 0x07 "dilithium5" OID_DILITHIUM_5 0x82 "" 0x37 "Microsoft" 0x0A "" diff --git a/src/libstrongswan/credentials/auth_cfg.c b/src/libstrongswan/credentials/auth_cfg.c index 675694dcbc..d949d5f894 100644 --- a/src/libstrongswan/credentials/auth_cfg.c +++ b/src/libstrongswan/credentials/auth_cfg.c @@ -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_5, KEY_DILITHIUM_5, }, }; if (expected_strength != AUTH_RULE_MAX) diff --git a/src/libstrongswan/credentials/builder.c b/src/libstrongswan/credentials/builder.c index 27ae83c8fa..fb9be1ea74 100644 --- a/src/libstrongswan/credentials/builder.c +++ b/src/libstrongswan/credentials/builder.c @@ -77,9 +77,11 @@ 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_NONCE", "BUILD_OCSP_STATUS", "BUILD_OCSP_RESPONSES", + "BUILD_DRBG", "BUILD_END", ); diff --git a/src/libstrongswan/credentials/builder.h b/src/libstrongswan/credentials/builder.h index e95265e4c6..bdeafda66c 100644 --- a/src/libstrongswan/credentials/builder.h +++ b/src/libstrongswan/credentials/builder.h @@ -163,6 +163,8 @@ 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, /** nonce needed for some security protocol */ @@ -171,6 +173,8 @@ enum builder_part_t { BUILD_OCSP_STATUS, /** enumerator_t over (ocsp_single_response_t *response) */ BUILD_OCSP_RESPONSES, + /** DRBG to be used for crypto tests */ + BUILD_DRBG, /** end of variable argument builder list */ BUILD_END, }; diff --git a/src/libstrongswan/credentials/cred_encoding.h b/src/libstrongswan/credentials/cred_encoding.h index 0b469d039a..317936760f 100644 --- a/src/libstrongswan/credentials/cred_encoding.h +++ b/src/libstrongswan/credentials/cred_encoding.h @@ -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 */ diff --git a/src/libstrongswan/credentials/keys/public_key.c b/src/libstrongswan/credentials/keys/public_key.c index f2e3b9bd36..9fe2864316 100644 --- a/src/libstrongswan/credentials/keys/public_key.c +++ b/src/libstrongswan/credentials/keys/public_key.c @@ -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", + "Dilithium5", "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_5", "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_5: + return OID_DILITHIUM_5; + 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_5: + return KEY_DILITHIUM_5; + 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_5: + return SIGN_DILITHIUM_5; 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_5: + return OID_DILITHIUM_5; 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_5, 0, { .scheme = SIGN_DILITHIUM_5}}, + { 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_5: + return KEY_DILITHIUM_5; case SIGN_BLISS_WITH_SHA2_256: case SIGN_BLISS_WITH_SHA2_384: case SIGN_BLISS_WITH_SHA2_512: diff --git a/src/libstrongswan/credentials/keys/public_key.h b/src/libstrongswan/credentials/keys/public_key.h index 55c0181ff3..772ef1fc37 100644 --- a/src/libstrongswan/credentials/keys/public_key.h +++ b/src/libstrongswan/credentials/keys/public_key.h @@ -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_5 = 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_5, /** 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. * diff --git a/src/libstrongswan/crypto/hashers/hasher.c b/src/libstrongswan/crypto/hashers/hasher.c index 61533fcf04..613ae5db9d 100644 --- a/src/libstrongswan/crypto/hashers/hasher.c +++ b/src/libstrongswan/crypto/hashers/hasher.c @@ -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_5: 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_5: + switch (alg) + { + case HASH_IDENTITY: + return OID_DILITHIUM_5; + 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_5: return HASH_IDENTITY; case SIGN_RSA_EMSA_PKCS1_MD5: return HASH_MD5; diff --git a/src/libstrongswan/plugins/oqs/Makefile.am b/src/libstrongswan/plugins/oqs/Makefile.am index 0d96552df1..fda6513fd7 100644 --- a/src/libstrongswan/plugins/oqs/Makefile.am +++ b/src/libstrongswan/plugins/oqs/Makefile.am @@ -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 diff --git a/src/libstrongswan/plugins/oqs/oqs_plugin.c b/src/libstrongswan/plugins/oqs/oqs_plugin.c index c906af1293..cf50a2baad 100644 --- a/src/libstrongswan/plugins/oqs/oqs_plugin.c +++ b/src/libstrongswan/plugins/oqs/oqs_plugin.c @@ -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 #include @@ -62,6 +64,28 @@ METHOD(plugin_t, get_features, int, PLUGIN_PROVIDE(KE, KE_FRODO_SHAKE_L1), PLUGIN_PROVIDE(KE, KE_FRODO_SHAKE_L3), PLUGIN_PROVIDE(KE, KE_FRODO_SHAKE_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_5), + 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_5), + 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_5), + 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_5), + /* signature verification schemes */ + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_DILITHIUM_2), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_DILITHIUM_3), + PLUGIN_PROVIDE(PUBKEY_VERIFY, SIGN_DILITHIUM_5), }; *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 index 0000000000..fd7eba60bb --- /dev/null +++ b/src/libstrongswan/plugins/oqs/oqs_private_key.c @@ -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 . + * + * 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 +#include +#include +#include + +#include + +#define _GNU_SOURCE +#include + +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, void *params, + 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_5: + sig_alg = OQS_SIG_alg_dilithium_5; + 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 index 0000000000..df62b15d79 --- /dev/null +++ b/src/libstrongswan/plugins/oqs/oqs_private_key.h @@ -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 . + * + * 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 +#include + +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 index 0000000000..7d6d69e4ac --- /dev/null +++ b/src/libstrongswan/plugins/oqs/oqs_public_key.c @@ -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 . + * + * 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 +#include +#include + +#include + +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, void *params, + 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 BITS_PER_BYTE * 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, ¶m); + 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_5: + sig_alg = OQS_SIG_alg_dilithium_5; + 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_5: + 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 index 0000000000..f3441ed71b --- /dev/null +++ b/src/libstrongswan/plugins/oqs/oqs_public_key.h @@ -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 . + * + * 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 +#include +#include + +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_ @}*/ diff --git a/src/libstrongswan/plugins/pem/pem_encoder.c b/src/libstrongswan/plugins/pem/pem_encoder.c index e5cf038de8..902e4931b9 100644 --- a/src/libstrongswan/plugins/pem/pem_encoder.c +++ b/src/libstrongswan/plugins/pem/pem_encoder.c @@ -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"; diff --git a/src/libstrongswan/plugins/pem/pem_plugin.c b/src/libstrongswan/plugins/pem/pem_plugin.c index d8045ed594..31fb707de6 100644 --- a/src/libstrongswan/plugins/pem/pem_plugin.c +++ b/src/libstrongswan/plugins/pem/pem_plugin.c @@ -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_5), + PLUGIN_DEPENDS(PRIVKEY, KEY_DILITHIUM_5), /* public key PEM decoding */ PLUGIN_REGISTER(PUBKEY, pem_public_key_load, FALSE), diff --git a/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c b/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c index defaac19d4..282baf8c1d 100644 --- a/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c +++ b/src/libstrongswan/plugins/pkcs8/pkcs8_builder.c @@ -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_5: + type = KEY_DILITHIUM_5; + part = BUILD_PRIV_ASN1_DER; + break; default: /* key type not supported */ goto end; diff --git a/src/libstrongswan/plugins/pkcs8/pkcs8_plugin.c b/src/libstrongswan/plugins/pkcs8/pkcs8_plugin.c index 8841720a32..93161c004f 100644 --- a/src/libstrongswan/plugins/pkcs8/pkcs8_plugin.c +++ b/src/libstrongswan/plugins/pkcs8/pkcs8_plugin.c @@ -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_5), }; *features = f; return countof(f); diff --git a/src/libstrongswan/tests/suites/test_hasher.c b/src/libstrongswan/tests/suites/test_hasher.c index cffb777cd2..6ca9303f6f 100644 --- a/src/libstrongswan/tests/suites/test_hasher.c +++ b/src/libstrongswan/tests/suites/test_hasher.c @@ -69,7 +69,9 @@ static hasher_oid_t oids[] = { { OID_BLISS_WITH_SHA3_384, HASH_SHA3_384, KEY_BLISS }, /* 37 */ { OID_BLISS_WITH_SHA3_512, HASH_SHA3_512, KEY_BLISS }, /* 38 */ { OID_UNKNOWN, HASH_UNKNOWN, KEY_BLISS }, /* 39 */ - + { OID_DILITHIUM_2, HASH_IDENTITY, KEY_DILITHIUM_2}, /* 40 */ + { OID_DILITHIUM_3, HASH_IDENTITY, KEY_DILITHIUM_3}, /* 41 */ + { OID_DILITHIUM_5, HASH_IDENTITY, KEY_DILITHIUM_5}, /* 42 */ }; START_TEST(test_hasher_from_oid) @@ -124,6 +126,9 @@ static struct { { SIGN_BLISS_WITH_SHA3_512, HASH_SHA3_512 }, { SIGN_ED25519, HASH_IDENTITY }, { SIGN_ED448, HASH_IDENTITY }, + { SIGN_DILITHIUM_2, HASH_IDENTITY }, + { SIGN_DILITHIUM_3, HASH_IDENTITY }, + { SIGN_DILITHIUM_5, HASH_IDENTITY }, { 30, HASH_UNKNOWN }, }; diff --git a/src/pki/commands/gen.c b/src/pki/commands/gen.c index b6e871f795..08720e37c5 100644 --- a/src/pki/commands/gen.c +++ b/src/pki/commands/gen.c @@ -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, "dilithium5")) + { + type = KEY_DILITHIUM_5; + } 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|dilithium5|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"}, diff --git a/src/pki/commands/issue.c b/src/pki/commands/issue.c index c106237c88..ea10e72b1b 100644 --- a/src/pki/commands/issue.c +++ b/src/pki/commands/issue.c @@ -415,7 +415,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, diff --git a/src/pki/man/pki---gen.1.in b/src/pki/man/pki---gen.1.in index 0344f9473b..4e2e7a9281 100644 --- a/src/pki/man/pki---gen.1.in +++ b/src/pki/man/pki---gen.1.in @@ -46,7 +46,8 @@ Read command line options from \fIfile\fR. .TP .BI "\-t, \-\-type " type Type of key to generate. Either \fIrsa\fR, \fIecdsa\fR, \fIed25519\fR, -\fIed448\fR or \fIbliss\fR, defaults to \fIrsa\fR. +\fIed448\fR, \fIbliss\fR, \fIdilithium2\fR, \fIdilithium3\fR or \fIdilitium4\fR, +defaults to \fIrsa\fR. .TP .BI "\-s, \-\-size " bits Key length in bits. Defaults to 2048 for \fIrsa\fR and 384 for \fIecdsa\fR.