summaryrefslogtreecommitdiffstats
path: root/crypto/ffc
diff options
context:
space:
mode:
authorRichard Levitte <levitte@openssl.org>2020-12-01 19:11:59 +0100
committerRichard Levitte <levitte@openssl.org>2020-12-16 11:55:39 +0100
commitc829c23b67308ad8e8ab677c78db1d5151106c3c (patch)
treea1b4b7aeb5cc3093db9df76e06e02ce18f1653ed /crypto/ffc
parentd33ab074ef9847b67d96961f85f4ad614395d2c2 (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.info5
-rw-r--r--crypto/ffc/ffc_backend.c10
-rw-r--r--crypto/ffc/ffc_dh.c154
-rw-r--r--crypto/ffc/ffc_params.c8
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,