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:
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 ""
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)
"BUILD_THRESHOLD",
"BUILD_EDDSA_PUB",
"BUILD_EDDSA_PRIV_ASN1_DER",
+ "BUILD_PRIV_ASN1_DER",
"BUILD_CRITICAL_EXTENSION",
+ "BUILD_DRBG",
"BUILD_END",
);
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,
};
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 */
/*
* 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
"DSA",
"ED25519",
"ED448",
+ "Dilithium2",
+ "Dilithium3",
+ "Dilithium4",
"BLISS"
);
"ECDSA-521",
"ED25519",
"ED448",
+ "DILITHIUM_2",
+ "DILITHIUM_3",
+ "DILITHIUM_4",
"BLISS_WITH_SHA2_256",
"BLISS_WITH_SHA2_384",
"BLISS_WITH_SHA2_512",
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.
*/
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;
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:
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 }},
};
/**
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:
/*
* 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
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,
};
/**
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 */
*/
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.
*
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;
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)
{
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;
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
#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>
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);
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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_ @}*/
--- /dev/null
+/*
+ * 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, ¶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_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;
+}
--- /dev/null
+/*
+ * 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_ @}*/
&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,
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";
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),
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;
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);
{
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;
{
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"},
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,