The branch master has been updated via 28833f1465a2dd197f8df80a69095d1913e6e85e (commit) via 4c6348c23ade5ce8d3ce89bbcf61b666afc2b555 (commit) via d12a2fe4e73439af46cd545c3e04d80667dc0297 (commit) from 991a6bb58182d4d2077a68eb813c897b7de73462 (commit)
- Log ----------------------------------------------------------------- commit 28833f1465a2dd197f8df80a69095d1913e6e85e Author: Matt Caswell <m...@openssl.org> Date: Thu Sep 17 14:11:21 2020 +0100 Update the EdDSA docs with information about Algorithm Identifiers Reviewed-by: Tomas Mraz <tm...@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/12884) commit 4c6348c23ade5ce8d3ce89bbcf61b666afc2b555 Author: Matt Caswell <m...@openssl.org> Date: Tue Sep 15 16:48:55 2020 +0100 Make sure we properly test for EdDSA with alg ids Reviewed-by: Tomas Mraz <tm...@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/12884) commit d12a2fe4e73439af46cd545c3e04d80667dc0297 Author: Matt Caswell <m...@openssl.org> Date: Tue Sep 15 16:20:51 2020 +0100 Teach EdDSA signature algorithms about AlgorithmIdentifiers The other signature algorithms know how to create their own AlgorithmIdentifiers, but the EdDSA algorithms missed this. Fixes #11875 Reviewed-by: Tomas Mraz <tm...@fedoraproject.org> (Merged from https://github.com/openssl/openssl/pull/12884) ----------------------------------------------------------------------- Summary of changes: .gitignore | 2 + doc/man7/EVP_SIGNATURE-ED25519.pod | 13 ++++ providers/common/der/ECX.asn1 | 11 ++++ providers/common/der/build.info | 17 ++++++ .../common/der/{der_dsa.h.in => der_ecx.h.in} | 12 ++-- .../der/{der_dsa_gen.c.in => der_ecx_gen.c.in} | 4 +- providers/common/der/der_ecx_key.c | 48 +++++++++++++++ providers/implementations/signature/build.info | 1 + providers/implementations/signature/eddsa.c | 69 ++++++++++++++++++++++ test/recipes/25-test_req.t | 12 ++-- 10 files changed, 175 insertions(+), 14 deletions(-) create mode 100644 providers/common/der/ECX.asn1 copy providers/common/der/{der_dsa.h.in => der_ecx.h.in} (58%) copy providers/common/der/{der_dsa_gen.c.in => der_ecx_gen.c.in} (85%) create mode 100644 providers/common/der/der_ecx_key.c diff --git a/.gitignore b/.gitignore index a463fc3c96..0e9405a7ff 100644 --- a/.gitignore +++ b/.gitignore @@ -54,10 +54,12 @@ doc/man1/openssl-*.pod providers/common/der/der_digests_gen.c providers/common/der/der_dsa_gen.c providers/common/der/der_ec_gen.c +providers/common/der/der_ecx_gen.c providers/common/der/der_rsa_gen.c providers/common/der/der_wrap_gen.c providers/common/include/prov/der_dsa.h providers/common/include/prov/der_ec.h +providers/common/include/prov/der_ecx.h providers/common/include/prov/der_rsa.h providers/common/include/prov/der_digests.h providers/common/include/prov/der_wrap.h diff --git a/doc/man7/EVP_SIGNATURE-ED25519.pod b/doc/man7/EVP_SIGNATURE-ED25519.pod index e3d9cd47e2..bb91ae2434 100644 --- a/doc/man7/EVP_SIGNATURE-ED25519.pod +++ b/doc/man7/EVP_SIGNATURE-ED25519.pod @@ -15,11 +15,24 @@ one-shot digest sign and digest verify using PureEdDSA and B<Ed25519> or B<Ed448 (see RFC8032). It has associated private and public key formats compatible with RFC 8410. +=head2 ED25591 and ED448 Signature Parameters + No additional parameters can be set during one-shot signing or verification. In particular, because PureEdDSA is used, a digest must B<NOT> be specified when signing or verifying. See L<EVP_PKEY-X25519(7)> for information related to B<X25519> and B<X448> keys. +The following signature parameters can be retrieved using +EVP_PKEY_CTX_get_params(). + +=over 4 + +=item "algorithm-id" (B<OSSL_SIGNATURE_PARAM_ALGORITHM_ID>) <octet string> + +The parameters are described in L<provider-signature(7)>. + +=back + =head1 NOTES The PureEdDSA algorithm does not support the streaming mechanism diff --git a/providers/common/der/ECX.asn1 b/providers/common/der/ECX.asn1 new file mode 100644 index 0000000000..72d1b451ae --- /dev/null +++ b/providers/common/der/ECX.asn1 @@ -0,0 +1,11 @@ + +-- ------------------------------------------------------------------- +-- Taken from RFC 8410, 9 ASN.1 Module +-- (https://tools.ietf.org/html/rfc8410#section-9) + +id-edwards-curve-algs OBJECT IDENTIFIER ::= { 1 3 101 } + +id-X25519 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 110 } +id-X448 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 111 } +id-Ed25519 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 112 } +id-Ed448 OBJECT IDENTIFIER ::= { id-edwards-curve-algs 113 } diff --git a/providers/common/der/build.info b/providers/common/der/build.info index f7eb86fdfb..60c0d8e66c 100644 --- a/providers/common/der/build.info +++ b/providers/common/der/build.info @@ -50,6 +50,19 @@ DEPEND[${DER_EC_GEN/.c/.o}]=$DER_EC_H GENERATE[$DER_EC_H]=der_ec.h.in DEPEND[$DER_EC_H]=oids_to_c.pm +#----- ECX +$DER_ECX_H=../include/prov/der_ecx.h +$DER_ECX_GEN=der_ecx_gen.c +$DER_ECX_AUX=der_ecx_key.c + +GENERATE[$DER_ECX_GEN]=der_ecx_gen.c.in +DEPEND[$DER_ECX_GEN]=oids_to_c.pm + +DEPEND[${DER_ECX_AUX/.c/.o}]=$DER_ECX_H +DEPEND[${DER_ECX_GEN/.c/.o}]=$DER_ECX_H +GENERATE[$DER_ECX_H]=der_ecx.h.in +DEPEND[$DER_ECX_H]=oids_to_c.pm + #----- KEY WRAP $DER_WRAP_H=../include/prov/der_wrap.h $DER_WRAP_GEN=der_wrap_gen.c @@ -73,5 +86,9 @@ $COMMON=\ $DER_DIGESTS_GEN \ $DER_WRAP_GEN +IF[{- !$disabled{ec} -}] + $COMMON = $COMMON $DER_ECX_GEN $DER_ECX_AUX +ENDIF + SOURCE[../../libfips.a]=$COMMON $DER_RSA_FIPSABLE SOURCE[../../libnonfips.a]=$COMMON $DER_RSA_FIPSABLE diff --git a/providers/common/der/der_dsa.h.in b/providers/common/der/der_ecx.h.in similarity index 58% copy from providers/common/der/der_dsa.h.in copy to providers/common/der/der_ecx.h.in index e9a8718fc6..9d9a82e399 100644 --- a/providers/common/der/der_dsa.h.in +++ b/providers/common/der/der_ecx.h.in @@ -8,16 +8,16 @@ */ #include "internal/der.h" +#include "crypto/ecx.h" /* Well known OIDs precompiled */ {- - $OUT = oids_to_c::process_leaves('providers/common/der/DSA.asn1', + $OUT = oids_to_c::process_leaves('providers/common/der/ECX.asn1', { dir => $config{sourcedir}, filter => \&oids_to_c::filter_to_H }); -} -/* Subject Public Key Info */ -int DER_w_algorithmIdentifier_DSA(WPACKET *pkt, int tag, DSA *dsa); -/* Signature */ -int DER_w_algorithmIdentifier_DSA_with_MD(WPACKET *pkt, int tag, - DSA *dsa, int mdnid); +int DER_w_algorithmIdentifier_ED25519(WPACKET *pkt, int cont, ECX_KEY *ec); +int DER_w_algorithmIdentifier_ED448(WPACKET *pkt, int cont, ECX_KEY *ec); +int DER_w_algorithmIdentifier_X25519(WPACKET *pkt, int cont, ECX_KEY *ec); +int DER_w_algorithmIdentifier_X448(WPACKET *pkt, int cont, ECX_KEY *ec); diff --git a/providers/common/der/der_dsa_gen.c.in b/providers/common/der/der_ecx_gen.c.in similarity index 85% copy from providers/common/der/der_dsa_gen.c.in copy to providers/common/der/der_ecx_gen.c.in index 95f1f5cdd1..a0ed9dd0b2 100644 --- a/providers/common/der/der_dsa_gen.c.in +++ b/providers/common/der/der_ecx_gen.c.in @@ -7,11 +7,11 @@ * https://www.openssl.org/source/license.html */ -#include "prov/der_dsa.h" +#include "prov/der_ecx.h" /* Well known OIDs precompiled */ {- - $OUT = oids_to_c::process_leaves('providers/common/der/DSA.asn1', + $OUT = oids_to_c::process_leaves('providers/common/der/ECX.asn1', { dir => $config{sourcedir}, filter => \&oids_to_c::filter_to_C }); -} diff --git a/providers/common/der/der_ecx_key.c b/providers/common/der/der_ecx_key.c new file mode 100644 index 0000000000..206795ed93 --- /dev/null +++ b/providers/common/der/der_ecx_key.c @@ -0,0 +1,48 @@ +/* + * Copyright 2020 The OpenSSL Project Authors. All Rights Reserved. + * + * Licensed under the Apache License 2.0 (the "License"). You may not use + * this file except in compliance with the License. You can obtain a copy + * in the file LICENSE in the source distribution or at + * https://www.openssl.org/source/license.html + */ + +#include <openssl/obj_mac.h> +#include "internal/packet.h" +#include "prov/der_ecx.h" + +int DER_w_algorithmIdentifier_X25519(WPACKET *pkt, int cont, ECX_KEY *ec) +{ + return DER_w_begin_sequence(pkt, cont) + /* No parameters (yet?) */ + && DER_w_precompiled(pkt, -1, der_oid_id_X25519, + sizeof(der_oid_id_X25519)) + && DER_w_end_sequence(pkt, cont); +} + +int DER_w_algorithmIdentifier_X448(WPACKET *pkt, int cont, ECX_KEY *ec) +{ + return DER_w_begin_sequence(pkt, cont) + /* No parameters (yet?) */ + && DER_w_precompiled(pkt, -1, der_oid_id_X448, + sizeof(der_oid_id_X448)) + && DER_w_end_sequence(pkt, cont); +} + +int DER_w_algorithmIdentifier_ED25519(WPACKET *pkt, int cont, ECX_KEY *ec) +{ + return DER_w_begin_sequence(pkt, cont) + /* No parameters (yet?) */ + && DER_w_precompiled(pkt, -1, der_oid_id_Ed25519, + sizeof(der_oid_id_Ed25519)) + && DER_w_end_sequence(pkt, cont); +} + +int DER_w_algorithmIdentifier_ED448(WPACKET *pkt, int cont, ECX_KEY *ec) +{ + return DER_w_begin_sequence(pkt, cont) + /* No parameters (yet?) */ + && DER_w_precompiled(pkt, -1, der_oid_id_Ed448, + sizeof(der_oid_id_Ed448)) + && DER_w_end_sequence(pkt, cont); +} diff --git a/providers/implementations/signature/build.info b/providers/implementations/signature/build.info index 24c5180662..b06f6e5c79 100644 --- a/providers/implementations/signature/build.info +++ b/providers/implementations/signature/build.info @@ -18,6 +18,7 @@ SOURCE[../../libnonfips.a]=rsa.c DEPEND[rsa.o]=../../common/include/prov/der_rsa.h DEPEND[dsa.o]=../../common/include/prov/der_dsa.h DEPEND[ecdsa.o]=../../common/include/prov/der_ec.h +DEPEND[eddsa.o]=../../common/include/prov/der_ecx.h SOURCE[../../libfips.a]=mac_legacy.c SOURCE[../../libnonfips.a]=mac_legacy.c diff --git a/providers/implementations/signature/eddsa.c b/providers/implementations/signature/eddsa.c index eda5ae1e60..9d8ab0ad3e 100644 --- a/providers/implementations/signature/eddsa.c +++ b/providers/implementations/signature/eddsa.c @@ -20,6 +20,7 @@ #include "prov/implementations.h" #include "prov/providercommonerr.h" #include "prov/provider_ctx.h" +#include "prov/der_ecx.h" #include "crypto/ecx.h" static OSSL_FUNC_signature_newctx_fn eddsa_newctx; @@ -30,10 +31,17 @@ static OSSL_FUNC_signature_digest_verify_fn ed25519_digest_verify; static OSSL_FUNC_signature_digest_verify_fn ed448_digest_verify; static OSSL_FUNC_signature_freectx_fn eddsa_freectx; static OSSL_FUNC_signature_dupctx_fn eddsa_dupctx; +static OSSL_FUNC_signature_get_ctx_params_fn eddsa_get_ctx_params; +static OSSL_FUNC_signature_gettable_ctx_params_fn eddsa_gettable_ctx_params; typedef struct { OPENSSL_CTX *libctx; ECX_KEY *key; + + /* The Algorithm Identifier of the signature algorithm */ + unsigned char aid_buf[OSSL_MAX_ALGORITHM_ID_SIZE]; + unsigned char *aid; + size_t aid_len; } PROV_EDDSA_CTX; static void *eddsa_newctx(void *provctx, const char *propq_unused) @@ -59,6 +67,8 @@ static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname, { PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; ECX_KEY *edkey = (ECX_KEY *)vedkey; + WPACKET pkt; + int ret; if (!ossl_prov_is_running()) return 0; @@ -73,6 +83,33 @@ static int eddsa_digest_signverify_init(void *vpeddsactx, const char *mdname, return 0; } + /* + * TODO(3.0) Should we care about DER writing errors? + * All it really means is that for some reason, there's no + * AlgorithmIdentifier to be had, but the operation itself is + * still valid, just as long as it's not used to construct + * anything that needs an AlgorithmIdentifier. + */ + peddsactx->aid_len = 0; + ret = WPACKET_init_der(&pkt, peddsactx->aid_buf, sizeof(peddsactx->aid_buf)); + switch (edkey->type) { + case ECX_KEY_TYPE_ED25519: + ret = ret && DER_w_algorithmIdentifier_ED25519(&pkt, -1, edkey); + break; + case ECX_KEY_TYPE_ED448: + ret = ret && DER_w_algorithmIdentifier_ED448(&pkt, -1, edkey); + break; + default: + /* Should never happen */ + PROVerr(0, ERR_R_INTERNAL_ERROR); + return 0; + } + if (ret && WPACKET_finish(&pkt)) { + WPACKET_get_total_written(&pkt, &peddsactx->aid_len); + peddsactx->aid = WPACKET_get_curr(&pkt); + } + WPACKET_cleanup(&pkt); + peddsactx->key = edkey; return 1; @@ -198,6 +235,32 @@ static void *eddsa_dupctx(void *vpeddsactx) return NULL; } +static int eddsa_get_ctx_params(void *vpeddsactx, OSSL_PARAM *params) +{ + PROV_EDDSA_CTX *peddsactx = (PROV_EDDSA_CTX *)vpeddsactx; + OSSL_PARAM *p; + + if (peddsactx == NULL || params == NULL) + return 0; + + p = OSSL_PARAM_locate(params, OSSL_SIGNATURE_PARAM_ALGORITHM_ID); + if (p != NULL && !OSSL_PARAM_set_octet_string(p, peddsactx->aid, + peddsactx->aid_len)) + return 0; + + return 1; +} + +static const OSSL_PARAM known_gettable_ctx_params[] = { + OSSL_PARAM_octet_string(OSSL_SIGNATURE_PARAM_ALGORITHM_ID, NULL, 0), + OSSL_PARAM_END +}; + +static const OSSL_PARAM *eddsa_gettable_ctx_params(ossl_unused void *provctx) +{ + return known_gettable_ctx_params; +} + const OSSL_DISPATCH ed25519_signature_functions[] = { { OSSL_FUNC_SIGNATURE_NEWCTX, (void (*)(void))eddsa_newctx }, { OSSL_FUNC_SIGNATURE_DIGEST_SIGN_INIT, @@ -210,6 +273,9 @@ const OSSL_DISPATCH ed25519_signature_functions[] = { (void (*)(void))ed25519_digest_verify }, { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx }, + { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params }, + { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, + (void (*)(void))eddsa_gettable_ctx_params }, { 0, NULL } }; @@ -225,5 +291,8 @@ const OSSL_DISPATCH ed448_signature_functions[] = { (void (*)(void))ed448_digest_verify }, { OSSL_FUNC_SIGNATURE_FREECTX, (void (*)(void))eddsa_freectx }, { OSSL_FUNC_SIGNATURE_DUPCTX, (void (*)(void))eddsa_dupctx }, + { OSSL_FUNC_SIGNATURE_GET_CTX_PARAMS, (void (*)(void))eddsa_get_ctx_params }, + { OSSL_FUNC_SIGNATURE_GETTABLE_CTX_PARAMS, + (void (*)(void))eddsa_gettable_ctx_params }, { 0, NULL } }; diff --git a/test/recipes/25-test_req.t b/test/recipes/25-test_req.t index 544d32963c..b00b8c3404 100644 --- a/test/recipes/25-test_req.t +++ b/test/recipes/25-test_req.t @@ -143,15 +143,15 @@ subtest "generating certificate requests with Ed25519" => sub { SKIP: { skip "Ed25519 is not supported by this OpenSSL build", 2 - if disabled("ec") || !@tmp_loader_hack; + if disabled("ec"); - ok(run(app(["openssl", "req", @tmp_loader_hack, + ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), "-new", "-out", "testreq-ed25519.pem", "-utf8", "-key", srctop_file("test", "tested25519.pem")])), "Generating request"); - ok(run(app(["openssl", "req", @tmp_loader_hack, + ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), "-verify", "-in", "testreq-ed25519.pem", "-noout"])), "Verifying signature on request"); @@ -163,15 +163,15 @@ subtest "generating certificate requests with Ed448" => sub { SKIP: { skip "Ed448 is not supported by this OpenSSL build", 2 - if disabled("ec") || !@tmp_loader_hack; + if disabled("ec"); - ok(run(app(["openssl", "req", @tmp_loader_hack, + ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), "-new", "-out", "testreq-ed448.pem", "-utf8", "-key", srctop_file("test", "tested448.pem")])), "Generating request"); - ok(run(app(["openssl", "req", @tmp_loader_hack, + ok(run(app(["openssl", "req", "-config", srctop_file("test", "test.cnf"), "-verify", "-in", "testreq-ed448.pem", "-noout"])), "Verifying signature on request");