summaryrefslogtreecommitdiffstats
path: root/test/evp_libctx_test.c
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2020-07-09 13:43:10 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-07-09 13:43:10 +1000
commit63794b048cbe46ac9abb883df4dd703f522e4643 (patch)
tree62a0882fc7e5be0e4579440468fb412684636bad /test/evp_libctx_test.c
parenteae4a008341149783b540198470f04f85b22730e (diff)
Add multiple fixes for ffc key generation using invalid p,q,g parameters.
Fixes #11864 - The dsa keygen assumed valid p, q, g values were being passed. If this is not correct then it is possible that dsa keygen can either hang or segfault. The fix was to do a partial validation of p, q, and g inside the keygen. - Fixed a potential double free in the dsa keypair test in the case when in failed (It should never fail!). It freed internal object members without setting them to NULL. - Changed the FFC key validation to accept 1024 bit keys in non fips mode. - Added tests that use both the default provider & fips provider to test these cases. Reviewed-by: Dmitry Belyavskiy <beldmit@gmail.com> (Merged from https://github.com/openssl/openssl/pull/12176)
Diffstat (limited to 'test/evp_libctx_test.c')
-rw-r--r--test/evp_libctx_test.c253
1 files changed, 253 insertions, 0 deletions
diff --git a/test/evp_libctx_test.c b/test/evp_libctx_test.c
new file mode 100644
index 0000000000..77054f93a2
--- /dev/null
+++ b/test/evp_libctx_test.c
@@ -0,0 +1,253 @@
+/*
+ * 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
+ */
+
+/*
+
+ * These tests are setup to load null into the default library context.
+ * Any tests are expected to use the created 'libctx' to find algorithms.
+ * The framework runs the tests twice using the 'default' provider or
+ * 'fips' provider as inputs.
+ */
+
+/*
+ * DSA/DH low level APIs are deprecated for public use, but still ok for
+ * internal use.
+ */
+#include "internal/deprecated.h"
+#include <openssl/evp.h>
+#include <openssl/provider.h>
+#include <openssl/dsa.h>
+#include "testutil.h"
+#include "internal/nelem.h"
+#include "crypto/bn_dh.h" /* _bignum_ffdhe2048_p */
+
+static OPENSSL_CTX *libctx = NULL;
+static OSSL_PROVIDER *nullprov = NULL;
+static OSSL_PROVIDER *libprov = NULL;
+
+typedef enum OPTION_choice {
+ OPT_ERR = -1,
+ OPT_EOF = 0,
+ OPT_CONFIG_FILE,
+ OPT_PROVIDER_NAME,
+ OPT_TEST_ENUM
+} OPTION_CHOICE;
+
+const OPTIONS *test_get_options(void)
+{
+ static const OPTIONS test_options[] = {
+ OPT_TEST_OPTIONS_DEFAULT_USAGE,
+ { "config", OPT_CONFIG_FILE, '<',
+ "The configuration file to use for the libctx" },
+ { "provider", OPT_PROVIDER_NAME, 's',
+ "The provider to load (The default value is 'default'" },
+ { NULL }
+ };
+ return test_options;
+}
+
+#if !defined(OPENSSL_NO_DSA) || !defined(OPENSSL_NO_DH)
+static const char *getname(int id)
+{
+ const char *name[] = {"p", "q", "g" };
+
+ if (id >= 0 && id < 3)
+ return name[id];
+ return "?";
+}
+#endif
+
+#ifndef OPENSSL_NO_DSA
+
+static int test_dsa_param_keygen(int tstid)
+{
+ int ret = 0;
+ int expected;
+ EVP_PKEY_CTX *gen_ctx = NULL;
+ EVP_PKEY *pkey_parm = NULL;
+ EVP_PKEY *pkey = NULL;
+ DSA *dsa = NULL;
+ int pind, qind, gind;
+ BIGNUM *p = NULL, *q = NULL, *g = NULL;
+
+ /*
+ * Just grab some fixed dh p, q, g values for testing,
+ * these 'safe primes' should not be used normally for dsa *.
+ */
+ static const BIGNUM *bn[] = {
+ &_bignum_dh2048_256_p, &_bignum_dh2048_256_q, &_bignum_dh2048_256_g
+ };
+
+ /*
+ * These tests are using bad values for p, q, g by reusing the values.
+ * A value of 0 uses p, 1 uses q and 2 uses g.
+ * There are 27 different combinations, with only the 1 valid combination.
+ */
+ pind = tstid / 9;
+ qind = (tstid / 3) % 3;
+ gind = tstid % 3;
+ expected = (pind == 0 && qind == 1 && gind == 2);
+
+ TEST_note("Testing with (p, q, g) = (%s, %s, %s)\n", getname(pind),
+ getname(qind), getname(gind));
+
+ if (!TEST_ptr(pkey_parm = EVP_PKEY_new())
+ || !TEST_ptr(dsa = DSA_new())
+ || !TEST_ptr(p = BN_dup(bn[pind]))
+ || !TEST_ptr(q = BN_dup(bn[qind]))
+ || !TEST_ptr(g = BN_dup(bn[gind]))
+ || !TEST_true(DSA_set0_pqg(dsa, p, q, g)))
+ goto err;
+ p = q = g = NULL;
+
+ if (!TEST_true(EVP_PKEY_assign_DSA(pkey_parm, dsa)))
+ goto err;
+ dsa = NULL;
+
+ if (!TEST_ptr(gen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey_parm, NULL))
+ || !TEST_int_gt(EVP_PKEY_keygen_init(gen_ctx), 0)
+ || !TEST_int_eq(EVP_PKEY_keygen(gen_ctx, &pkey), expected))
+ goto err;
+ ret = 1;
+err:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(gen_ctx);
+ EVP_PKEY_free(pkey_parm);
+ DSA_free(dsa);
+ BN_free(g);
+ BN_free(q);
+ BN_free(p);
+ return ret;
+}
+#endif /* OPENSSL_NO_DSA */
+
+#ifndef OPENSSL_NO_DH
+static int do_dh_param_keygen(int tstid, const BIGNUM **bn)
+{
+ int ret = 0;
+ int expected;
+ EVP_PKEY_CTX *gen_ctx = NULL;
+ EVP_PKEY *pkey_parm = NULL;
+ EVP_PKEY *pkey = NULL;
+ DH *dh = NULL;
+ int pind, qind, gind;
+ BIGNUM *p = NULL, *q = NULL, *g = NULL;
+
+ /*
+ * These tests are using bad values for p, q, g by reusing the values.
+ * A value of 0 uses p, 1 uses q and 2 uses g.
+ * There are 27 different combinations, with only the 1 valid combination.
+ */
+ pind = tstid / 9;
+ qind = (tstid / 3) % 3;
+ gind = tstid % 3;
+ expected = (pind == 0 && qind == 1 && gind == 2);
+
+ TEST_note("Testing with (p, q, g) = (%s, %s, %s)", getname(pind),
+ getname(qind), getname(gind));
+
+ if (!TEST_ptr(pkey_parm = EVP_PKEY_new())
+ || !TEST_ptr(dh = DH_new())
+ || !TEST_ptr(p = BN_dup(bn[pind]))
+ || !TEST_ptr(q = BN_dup(bn[qind]))
+ || !TEST_ptr(g = BN_dup(bn[gind]))
+ || !TEST_true(DH_set0_pqg(dh, p, q, g)))
+ goto err;
+ p = q = g = NULL;
+
+ if (!TEST_true(EVP_PKEY_assign_DH(pkey_parm, dh)))
+ goto err;
+ dh = NULL;
+
+ if (!TEST_ptr(gen_ctx = EVP_PKEY_CTX_new_from_pkey(libctx, pkey_parm, NULL))
+ || !TEST_int_gt(EVP_PKEY_keygen_init(gen_ctx), 0)
+ || !TEST_int_eq(EVP_PKEY_keygen(gen_ctx, &pkey), expected))
+ goto err;
+ ret = 1;
+err:
+ EVP_PKEY_free(pkey);
+ EVP_PKEY_CTX_free(gen_ctx);
+ EVP_PKEY_free(pkey_parm);
+ DH_free(dh);
+ BN_free(g);
+ BN_free(q);
+ BN_free(p);
+ return ret;
+}
+
+/*
+ * Note that we get the fips186-4 path being run for most of these cases since
+ * the internal code will detect that the p, q, g does not match a safe prime
+ * group (Except for when tstid = 5, which sets the correct p, q, g)
+ */
+static int test_dh_safeprime_param_keygen(int tstid)
+{
+ static const BIGNUM *bn[] = {
+ &_bignum_ffdhe2048_p, &_bignum_ffdhe2048_q, &_bignum_const_2
+ };
+ return do_dh_param_keygen(tstid, bn);
+}
+
+#endif /* OPENSSL_NO_DH */
+
+int setup_tests(void)
+{
+ const char *prov_name = "default";
+ char *config_file = NULL;
+ OPTION_CHOICE o;
+
+ while ((o = opt_next()) != OPT_EOF) {
+ switch (o) {
+ case OPT_PROVIDER_NAME:
+ prov_name = opt_arg();
+ break;
+ case OPT_CONFIG_FILE:
+ config_file = opt_arg();
+ break;
+ case OPT_TEST_CASES:
+ break;
+ default:
+ case OPT_ERR:
+ return 0;
+ }
+ }
+
+ nullprov = OSSL_PROVIDER_load(NULL, "null");
+ if (!TEST_ptr(nullprov))
+ return 0;
+
+ libctx = OPENSSL_CTX_new();
+
+ if (!TEST_ptr(libctx))
+ return 0;
+
+ if (config_file != NULL) {
+ if (!TEST_true(OPENSSL_CTX_load_config(libctx, config_file)))
+ return 0;
+ }
+
+ libprov = OSSL_PROVIDER_load(libctx, prov_name);
+ if (!TEST_ptr(libprov))
+ return 0;
+
+#ifndef OPENSSL_NO_DSA
+ ADD_ALL_TESTS(test_dsa_param_keygen, 3 * 3 * 3);
+#endif
+#ifndef OPENSSL_NO_DH
+ ADD_ALL_TESTS(test_dh_safeprime_param_keygen, 3 * 3 * 3);
+#endif
+ return 1;
+}
+
+void cleanup_tests(void)
+{
+ OSSL_PROVIDER_unload(libprov);
+ OPENSSL_CTX_free(libctx);
+ OSSL_PROVIDER_unload(nullprov);
+}