diff options
author | Richard Levitte <levitte@openssl.org> | 2020-12-01 19:11:59 +0100 |
---|---|---|
committer | Richard Levitte <levitte@openssl.org> | 2020-12-16 11:55:39 +0100 |
commit | c829c23b67308ad8e8ab677c78db1d5151106c3c (patch) | |
tree | a1b4b7aeb5cc3093db9df76e06e02ce18f1653ed /crypto/ffc | |
parent | d33ab074ef9847b67d96961f85f4ad614395d2c2 (diff) |
EVP_PKEY & DH: Make DH EVP_PKEY_CTX parameter ctrls / setters more available
EVP_PKEY_CTX_set_dh_ functions were only available when DH was enabled
('no-dsa' not configured). However, that makes it impossible to use
these functions with an engine or a provider that happens to implement
DH. This change solves that problem by shuffling these functions to
more appropriate places.
By consequence, there are a number of places where we can remove the
check of OPENSSL_NO_DH. This requires some re-arrangements of
internal tables to translate between numeric identities and names.
Partially fixes #13550
Reviewed-by: Tomas Mraz <tmraz@fedoraproject.org>
(Merged from https://github.com/openssl/openssl/pull/13589)
Diffstat (limited to 'crypto/ffc')
-rw-r--r-- | crypto/ffc/build.info | 5 | ||||
-rw-r--r-- | crypto/ffc/ffc_backend.c | 10 | ||||
-rw-r--r-- | crypto/ffc/ffc_dh.c | 154 | ||||
-rw-r--r-- | crypto/ffc/ffc_params.c | 8 |
4 files changed, 165 insertions, 12 deletions
diff --git a/crypto/ffc/build.info b/crypto/ffc/build.info index a04430d1d1..61cca17c5f 100644 --- a/crypto/ffc/build.info +++ b/crypto/ffc/build.info @@ -1,7 +1,8 @@ LIBS=../../libcrypto -$COMMON=ffc_params.c ffc_params_generate.c ffc_key_generate.c\ - ffc_params_validate.c ffc_key_validate.c ffc_backend.c +$COMMON=ffc_params.c ffc_params_generate.c ffc_key_generate.c \ + ffc_params_validate.c ffc_key_validate.c ffc_backend.c \ + ffc_dh.c SOURCE[../../libcrypto]=$COMMON SOURCE[../../providers/libfips.a]=$COMMON diff --git a/crypto/ffc/ffc_backend.c b/crypto/ffc/ffc_backend.c index fddd41557e..43825d9216 100644 --- a/crypto/ffc/ffc_backend.c +++ b/crypto/ffc/ffc_backend.c @@ -29,14 +29,16 @@ int ossl_ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[]) prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_GROUP_NAME); if (prm != NULL) { - if (prm->data_type != OSSL_PARAM_UTF8_STRING) - goto err; -#ifndef OPENSSL_NO_DH /* * In a no-dh build we just go straight to err because we have no * support for this. */ - if (!ossl_ffc_set_group_pqg(ffc, prm->data)) +#ifndef OPENSSL_NO_DH + const DH_NAMED_GROUP *group = NULL; + + if (prm->data_type != OSSL_PARAM_UTF8_STRING + || (group = ossl_ffc_name_to_dh_named_group(prm->data)) == NULL + || !ossl_ffc_named_group_set_pqg(ffc, group)) #endif goto err; } diff --git a/crypto/ffc/ffc_dh.c b/crypto/ffc/ffc_dh.c new file mode 100644 index 0000000000..313466b0ea --- /dev/null +++ b/crypto/ffc/ffc_dh.c @@ -0,0 +1,154 @@ +/* + * 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 "internal/ffc.h" +#include "internal/nelem.h" +#include "crypto/bn_dh.h" +#include "e_os.h" /* strcasecmp */ + +#ifndef OPENSSL_NO_DH + +# define FFDHE(sz) { \ + SN_ffdhe##sz, NID_ffdhe##sz, \ + sz, \ + &_bignum_ffdhe##sz##_p, &_bignum_ffdhe##sz##_q, &_bignum_const_2, \ + } + +# define MODP(sz) { \ + SN_modp_##sz, NID_modp_##sz, \ + sz, \ + &_bignum_modp_##sz##_p, &_bignum_modp_##sz##_q, &_bignum_const_2 \ + } + +# define RFC5114(name, uid, sz, tag) { \ + name, uid, \ + sz, \ + &_bignum_dh##tag##_p, &_bignum_dh##tag##_q, &_bignum_dh##tag##_g \ + } + +#else + +# define FFDHE(sz) { SN_ffdhe##sz, NID_ffdhe##sz } +# define MODP(sz) { SN_modp_##sz, NID_modp_##sz } +# define RFC5114(name, uid, sz, tag) { name, uid } + +#endif + +struct dh_named_group_st { + const char *name; + int uid; +#ifndef OPENSSL_NO_DH + int32_t nbits; + const BIGNUM *p; + const BIGNUM *q; + const BIGNUM *g; +#endif +}; + +static const DH_NAMED_GROUP dh_named_groups[] = { + FFDHE(2048), + FFDHE(3072), + FFDHE(4096), + FFDHE(6144), + FFDHE(8192), +#ifndef FIPS_MODULE + MODP(1536), +#endif + MODP(2048), + MODP(3072), + MODP(4096), + MODP(6144), + MODP(8192), + /* + * Additional dh named groups from RFC 5114 that have a different g. + * The uid can be any unique identifier. + */ +#ifndef FIPS_MODULE + RFC5114("dh_1024_160", 1, 1024, 1024_160), + RFC5114("dh_2048_224", 2, 2048, 2048_224), + RFC5114("dh_2048_256", 3, 2048, 2048_256), +#endif +}; + +const DH_NAMED_GROUP *ossl_ffc_name_to_dh_named_group(const char *name) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) { + if (strcasecmp(dh_named_groups[i].name, name) == 0) + return &dh_named_groups[i]; + } + return NULL; +} + +const DH_NAMED_GROUP *ossl_ffc_uid_to_dh_named_group(int uid) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) { + if (dh_named_groups[i].uid == uid) + return &dh_named_groups[i]; + } + return NULL; +} + +#ifndef OPENSSL_NO_DH +const DH_NAMED_GROUP *ossl_ffc_numbers_to_dh_named_group(const BIGNUM *p, + const BIGNUM *q, + const BIGNUM *g) +{ + size_t i; + + for (i = 0; i < OSSL_NELEM(dh_named_groups); ++i) { + /* Keep searching until a matching p and g is found */ + if (BN_cmp(p, dh_named_groups[i].p) == 0 + && BN_cmp(g, dh_named_groups[i].g) == 0 + /* Verify q is correct if it exists */ + && (q == NULL || BN_cmp(q, dh_named_groups[i].q) == 0)) + return &dh_named_groups[i]; + } + return NULL; +} +#endif + +int ossl_ffc_named_group_get_uid(const DH_NAMED_GROUP *group) +{ + if (group == NULL) + return NID_undef; + return group->uid; +} + +const char *ossl_ffc_named_group_get_name(const DH_NAMED_GROUP *group) +{ + if (group == NULL) + return NULL; + return group->name; +} + +#ifndef OPENSSL_NO_DH +const BIGNUM *ossl_ffc_named_group_get_q(const DH_NAMED_GROUP *group) +{ + if (group == NULL) + return NULL; + return group->q; +} + +int ossl_ffc_named_group_set_pqg(FFC_PARAMS *ffc, const DH_NAMED_GROUP *group) +{ + if (ffc == NULL || group == NULL) + return 0; + + ossl_ffc_params_set0_pqg(ffc, (BIGNUM *)group->p, (BIGNUM *)group->q, + (BIGNUM *)group->g); + + /* flush the cached nid, The DH layer is responsible for caching */ + ffc->nid = NID_undef; + return 1; +} +#endif diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c index edcb44b152..43064c0222 100644 --- a/crypto/ffc/ffc_params.c +++ b/crypto/ffc/ffc_params.c @@ -269,18 +269,14 @@ int ossl_ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld, ffc->seed, ffc->seedlen)) return 0; if (ffc->nid != NID_undef) { -#ifndef OPENSSL_NO_DH - const char *name = ossl_ffc_named_group_from_uid(ffc->nid); + const DH_NAMED_GROUP *group = ossl_ffc_uid_to_dh_named_group(ffc->nid); + const char *name = ossl_ffc_named_group_get_name(group); if (name == NULL || !ossl_param_build_set_utf8_string(bld, params, OSSL_PKEY_PARAM_GROUP_NAME, name)) return 0; -#else - /* How could this be? We should not have a nid in a no-dh build. */ - return 0; -#endif } if (!ossl_param_build_set_utf8_string(bld, params, OSSL_PKEY_PARAM_FFC_VALIDATE_TYPE, |