summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xConfigure1
-rw-r--r--INSTALL.md10
-rw-r--r--crypto/dh/dh_check.c4
-rw-r--r--crypto/dh/dh_gen.c15
-rw-r--r--crypto/dh/dh_pmeth.c17
-rw-r--r--crypto/dsa/dsa_check.c4
-rw-r--r--crypto/dsa/dsa_gen.c27
-rw-r--r--crypto/dsa/dsa_pmeth.c6
-rw-r--r--crypto/ffc/ffc_backend.c22
-rw-r--r--crypto/ffc/ffc_params.c59
-rw-r--r--crypto/ffc/ffc_params_generate.c208
-rw-r--r--crypto/ffc/ffc_params_validate.c24
-rw-r--r--crypto/rsa/build.info4
-rw-r--r--crypto/rsa/rsa_acvp_test_params.c167
-rw-r--r--crypto/rsa/rsa_backend.c8
-rw-r--r--crypto/rsa/rsa_gen.c4
-rw-r--r--crypto/rsa/rsa_lib.c5
-rw-r--r--crypto/rsa/rsa_local.h38
-rw-r--r--crypto/rsa/rsa_sp800_56b_gen.c74
-rw-r--r--doc/man7/EVP_PKEY-RSA.pod53
-rw-r--r--include/crypto/dh.h4
-rw-r--r--include/crypto/dsa.h4
-rw-r--r--include/crypto/rsa.h16
-rw-r--r--include/internal/ffc.h55
-rw-r--r--include/openssl/core_names.h44
-rw-r--r--providers/implementations/keymgmt/dh_kmgmt.c29
-rw-r--r--providers/implementations/keymgmt/dsa_kmgmt.c29
-rw-r--r--providers/implementations/keymgmt/ec_kmgmt.c47
-rw-r--r--providers/implementations/keymgmt/rsa_kmgmt.c23
-rw-r--r--providers/implementations/signature/build.info4
-rw-r--r--providers/implementations/signature/dsa.c18
-rw-r--r--providers/implementations/signature/ecdsa.c25
-rw-r--r--providers/implementations/signature/rsa.c19
-rw-r--r--test/acvp_test.c1367
-rw-r--r--test/acvp_test.inc1984
-rw-r--r--test/build.info7
-rw-r--r--test/ffc_internal_test.c149
-rw-r--r--test/recipes/30-test_acvp.t41
-rw-r--r--test/rsa_sp800_56b_test.c128
39 files changed, 4236 insertions, 507 deletions
diff --git a/Configure b/Configure
index 1a22f47822..a0b9c22b6d 100755
--- a/Configure
+++ b/Configure
@@ -360,6 +360,7 @@ my @dtls = qw(dtls1 dtls1_2);
# For developers: keep it sorted alphabetically
my @disablables = (
+ "acvp_tests",
"afalgeng",
"aria",
"asan",
diff --git a/INSTALL.md b/INSTALL.md
index 88961aa74b..981a86af04 100644
--- a/INSTALL.md
+++ b/INSTALL.md
@@ -501,6 +501,16 @@ never be used in production environments. It will only work when used with
gcc or clang and should be used in conjunction with the [no-shared](#no-shared)
option.
+### no-acvp_tests
+
+Do not build support for Automated Cryptographic Validation Protocol (ACVP)
+tests.
+
+This is required for FIPS validation purposes. Certain ACVP tests require
+access to algorithm internals that are not normally accessible.
+Additional information related to ACVP can be found at
+<https://github.com/usnistgov/ACVP>.
+
### no-asm
Do not use assembler code.
diff --git a/crypto/dh/dh_check.c b/crypto/dh/dh_check.c
index 9dd595ae12..a223121cd0 100644
--- a/crypto/dh/dh_check.c
+++ b/crypto/dh/dh_check.c
@@ -62,8 +62,8 @@ int DH_check_params(const DH *dh, int *ret)
* (2b) FFC domain params conform to FIPS-186-4 explicit domain param
* validity tests.
*/
- return ffc_params_FIPS186_4_validate(&dh->params, FFC_PARAM_TYPE_DH, NULL,
- FFC_PARAMS_VALIDATE_ALL, ret, NULL);
+ return ffc_params_FIPS186_4_validate(dh->libctx, &dh->params,
+ FFC_PARAM_TYPE_DH, ret, NULL);
}
#else
int DH_check_params(const DH *dh, int *ret)
diff --git a/crypto/dh/dh_gen.c b/crypto/dh/dh_gen.c
index 8c1518ad9b..52f3151bc8 100644
--- a/crypto/dh/dh_gen.c
+++ b/crypto/dh/dh_gen.c
@@ -35,28 +35,21 @@ static int dh_builtin_genparams(DH *ret, int prime_len, int generator,
BN_GENCB *cb);
#endif /* FIPS_MODULE */
-int dh_generate_ffc_parameters(DH *dh, int type, int pbits,
- int qbits, EVP_MD *md, BN_GENCB *cb)
+int dh_generate_ffc_parameters(DH *dh, int type, int pbits, int qbits,
+ BN_GENCB *cb)
{
int ret, res;
- if (qbits <= 0) {
- if (md != NULL)
- qbits = EVP_MD_size(md) * 8;
- else
- qbits = (pbits >= 2048 ? SHA256_DIGEST_LENGTH :
- SHA_DIGEST_LENGTH) * 8;
- }
#ifndef FIPS_MODULE
if (type == DH_PARAMGEN_TYPE_FIPS_186_2)
ret = ffc_params_FIPS186_2_generate(dh->libctx, &dh->params,
FFC_PARAM_TYPE_DH,
- pbits, qbits, md, &res, cb);
+ pbits, qbits, &res, cb);
else
#endif
ret = ffc_params_FIPS186_4_generate(dh->libctx, &dh->params,
FFC_PARAM_TYPE_DH,
- pbits, qbits, md, &res, cb);
+ pbits, qbits, &res, cb);
if (ret > 0)
dh->dirty_cnt++;
return ret;
diff --git a/crypto/dh/dh_pmeth.c b/crypto/dh/dh_pmeth.c
index 23527acf04..39b79ffb36 100644
--- a/crypto/dh/dh_pmeth.c
+++ b/crypto/dh/dh_pmeth.c
@@ -286,7 +286,6 @@ static DH *ffc_params_generate(OPENSSL_CTX *libctx, DH_PKEY_CTX *dctx,
int res;
int prime_len = dctx->prime_len;
int subprime_len = dctx->subprime_len;
- const EVP_MD *md = dctx->md;
if (dctx->paramgen_type > DH_PARAMGEN_TYPE_FIPS_186_4)
return NULL;
@@ -300,26 +299,22 @@ static DH *ffc_params_generate(OPENSSL_CTX *libctx, DH_PKEY_CTX *dctx,
else
subprime_len = 160;
}
- if (md == NULL) {
- if (prime_len >= 2048)
- md = EVP_sha256();
- else
- md = EVP_sha1();
- }
+
+ if (dctx->md != NULL)
+ ffc_set_digest(&ret->params, EVP_MD_name(dctx->md), NULL);
+
# ifndef FIPS_MODULE
if (dctx->paramgen_type == DH_PARAMGEN_TYPE_FIPS_186_2)
rv = ffc_params_FIPS186_2_generate(libctx, &ret->params,
FFC_PARAM_TYPE_DH,
- prime_len, subprime_len, md, &res,
- pcb);
+ prime_len, subprime_len, &res, pcb);
else
# endif
/* For FIPS we always use the DH_PARAMGEN_TYPE_FIPS_186_4 generator */
if (dctx->paramgen_type >= DH_PARAMGEN_TYPE_FIPS_186_2)
rv = ffc_params_FIPS186_4_generate(libctx, &ret->params,
FFC_PARAM_TYPE_DH,
- prime_len, subprime_len, md, &res,
- pcb);
+ prime_len, subprime_len, &res, pcb);
if (rv <= 0) {
DH_free(ret);
return NULL;
diff --git a/crypto/dsa/dsa_check.c b/crypto/dsa/dsa_check.c
index dc42ec5f5f..01cf0f6341 100644
--- a/crypto/dsa/dsa_check.c
+++ b/crypto/dsa/dsa_check.c
@@ -19,8 +19,8 @@ int dsa_check_params(const DSA *dsa, int *ret)
* (2b) FFC domain params conform to FIPS-186-4 explicit domain param
* validity tests.
*/
- return ffc_params_FIPS186_4_validate(&dsa->params, FFC_PARAM_TYPE_DSA, NULL,
- FFC_PARAMS_VALIDATE_ALL, ret, NULL);
+ return ffc_params_FIPS186_4_validate(dsa->libctx, &dsa->params,
+ FFC_PARAM_TYPE_DSA, ret, NULL);
}
/*
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
index acd088ee79..9d5e91de29 100644
--- a/crypto/dsa/dsa_gen.c
+++ b/crypto/dsa/dsa_gen.c
@@ -23,29 +23,21 @@
#include "crypto/dsa.h"
#include "dsa_local.h"
-int dsa_generate_ffc_parameters(DSA *dsa, int type,
- int pbits, int qbits,
- EVP_MD *md, BN_GENCB *cb)
+int dsa_generate_ffc_parameters(DSA *dsa, int type, int pbits, int qbits,
+ BN_GENCB *cb)
{
int ret = 0, res;
- if (qbits <= 0) {
- if (md != NULL)
- qbits = EVP_MD_size(md) * 8;
- else
- qbits = (pbits >= 2048 ? SHA256_DIGEST_LENGTH :
- SHA_DIGEST_LENGTH) * 8;
- }
#ifndef FIPS_MODULE
if (type == DSA_PARAMGEN_TYPE_FIPS_186_2)
ret = ffc_params_FIPS186_2_generate(dsa->libctx, &dsa->params,
FFC_PARAM_TYPE_DSA,
- pbits, qbits, md, &res, cb);
+ pbits, qbits, &res, cb);
else
#endif
ret = ffc_params_FIPS186_4_generate(dsa->libctx, &dsa->params,
FFC_PARAM_TYPE_DSA,
- pbits, qbits, md, &res, cb);
+ pbits, qbits, &res, cb);
if (ret > 0)
dsa->dirty_cnt++;
return ret;
@@ -57,26 +49,21 @@ int DSA_generate_parameters_ex(DSA *dsa, int bits,
int *counter_ret, unsigned long *h_ret,
BN_GENCB *cb)
{
-#ifndef FIPS_MODULE
if (dsa->meth->dsa_paramgen)
return dsa->meth->dsa_paramgen(dsa, bits, seed_in, seed_len,
counter_ret, h_ret, cb);
-#endif
if (seed_in != NULL
&& !ffc_params_set_validate_params(&dsa->params, seed_in, seed_len, -1))
return 0;
-#ifndef FIPS_MODULE
/* The old code used FIPS 186-2 DSA Parameter generation */
if (bits <= 1024 && seed_len == 20) {
if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_2,
- bits, 160, NULL, cb))
+ bits, 160, cb))
return 0;
- } else
-#endif
- {
+ } else {
if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_4,
- bits, -1, NULL, cb))
+ bits, -1, cb))
return 0;
}
diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c
index 7f7f57f6d3..7b364059e7 100644
--- a/crypto/dsa/dsa_pmeth.c
+++ b/crypto/dsa/dsa_pmeth.c
@@ -217,9 +217,11 @@ static int pkey_dsa_paramgen(EVP_PKEY_CTX *ctx, EVP_PKEY *pkey)
BN_GENCB_free(pcb);
return 0;
}
+ if (dctx->md != NULL)
+ ffc_set_digest(&dsa->params, EVP_MD_name(dctx->md), NULL);
+
ret = ffc_params_FIPS186_4_generate(NULL, &dsa->params, FFC_PARAM_TYPE_DSA,
- dctx->nbits, dctx->qbits, dctx->pmd,
- &res, pcb);
+ dctx->nbits, dctx->qbits, &res, pcb);
BN_GENCB_free(pcb);
if (ret > 0)
EVP_PKEY_assign_DSA(pkey, dsa);
diff --git a/crypto/ffc/ffc_backend.c b/crypto/ffc/ffc_backend.c
index c34e79bf4f..49f42d70d0 100644
--- a/crypto/ffc/ffc_backend.c
+++ b/crypto/ffc/ffc_backend.c
@@ -78,6 +78,28 @@ int ffc_params_fromdata(FFC_PARAMS *ffc, const OSSL_PARAM params[])
if (!ffc_params_set_seed(ffc, prm->data, prm->data_size))
goto err;
}
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_VALIDATE_TYPE);
+ if (prm != NULL) {
+ if (prm->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ ffc_params_set_flags(ffc, ffc_params_flags_from_name(prm->data));
+ }
+ prm = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST);
+ if (prm != NULL) {
+ const OSSL_PARAM *p1;
+ const char *props = NULL;
+
+ if (prm->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ p1 = OSSL_PARAM_locate_const(params, OSSL_PKEY_PARAM_FFC_DIGEST_PROPS);
+ if (p1 != NULL) {
+ if (p1->data_type != OSSL_PARAM_UTF8_STRING)
+ goto err;
+ }
+ if (!ffc_set_digest(ffc, prm->data, props))
+ goto err;
+ }
+
ffc_params_set0_pqg(ffc, p, q, g);
ffc_params_set0_j(ffc, j);
return 1;
diff --git a/crypto/ffc/ffc_params.c b/crypto/ffc/ffc_params.c
index a95a2fa12b..0796d34337 100644
--- a/crypto/ffc/ffc_params.c
+++ b/crypto/ffc/ffc_params.c
@@ -11,6 +11,8 @@
#include <openssl/core_names.h>
#include "internal/ffc.h"
#include "internal/param_build_set.h"
+#include "internal/nelem.h"
+#include "e_os.h" /* strcasecmp */
#ifndef FIPS_MODULE
# include <openssl/asn1.h> /* ffc_params_print */
@@ -21,6 +23,7 @@ void ffc_params_init(FFC_PARAMS *params)
memset(params, 0, sizeof(*params));
params->pcounter = -1;
params->gindex = FFC_UNVERIFIABLE_GINDEX;
+ params->flags = FFC_PARAM_FLAG_VALIDATE_ALL;
}
void ffc_params_cleanup(FFC_PARAMS *params)
@@ -109,6 +112,18 @@ void ffc_params_set_h(FFC_PARAMS *params, int index)
params->h = index;
}
+void ffc_params_set_flags(FFC_PARAMS *params, unsigned int flags)
+{
+ params->flags = flags;
+}
+
+int ffc_set_digest(FFC_PARAMS *params, const char *alg, const char *props)
+{
+ params->mdname = alg;
+ params->mdprops = props;
+ return 1;
+}
+
int ffc_params_set_validate_params(FFC_PARAMS *params,
const unsigned char *seed, size_t seedlen,
int counter)
@@ -182,6 +197,36 @@ int ffc_params_cmp(const FFC_PARAMS *a, const FFC_PARAMS *b, int ignore_q)
&& (ignore_q || BN_cmp(a->q, b->q) == 0); /* Note: q may be NULL */
}
+static const OSSL_ITEM flag_map[] = {
+ { FFC_PARAM_FLAG_VALIDATE_PQ, OSSL_FFC_PARAM_VALIDATE_PQ },
+ { FFC_PARAM_FLAG_VALIDATE_G, OSSL_FFC_PARAM_VALIDATE_G },
+ { FFC_PARAM_FLAG_VALIDATE_ALL, OSSL_FFC_PARAM_VALIDATE_PQG },
+ { 0, "" }
+};
+
+int ffc_params_flags_from_name(const char *name)
+{
+ size_t i;
+
+ for (i = 0; i < OSSL_NELEM(flag_map); ++i) {
+ if (strcasecmp(flag_map[i].ptr, name) == 0)
+ return flag_map[i].id;
+ }
+ return NID_undef;
+}
+
+const char *ffc_params_flags_to_name(int flags)
+{
+ size_t i;
+
+ flags &= FFC_PARAM_FLAG_VALIDATE_ALL;
+ for (i = 0; i < OSSL_NELEM(flag_map); ++i) {
+ if ((int)flag_map[i].id == flags)
+ return flag_map[i].ptr;
+ }
+ return "";
+}
+
int ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld,
OSSL_PARAM params[])
{
@@ -228,6 +273,20 @@ int ffc_params_todata(const FFC_PARAMS *ffc, OSSL_PARAM_BLD *bld,
return 0;
#endif
}
+ if (!ossl_param_build_set_utf8_string(bld, params,
+ OSSL_PKEY_PARAM_FFC_VALIDATE_TYPE,
+ ffc_params_flags_to_name(ffc->flags)))
+ return 0;
+ if (ffc->mdname != NULL
+ && !ossl_param_build_set_utf8_string(bld, params,
+ OSSL_PKEY_PARAM_FFC_DIGEST,
+ ffc->mdname))
+ return 0;
+ if (ffc->mdprops != NULL
+ && !ossl_param_build_set_utf8_string(bld, params,
+ OSSL_PKEY_PARAM_FFC_DIGEST_PROPS,
+ ffc->mdprops))
+ return 0;
return 1;
}
diff --git a/crypto/ffc/ffc_params_generate.c b/crypto/ffc/ffc_params_generate.c
index 624c24dd21..b3ab476f3f 100644
--- a/crypto/ffc/ffc_params_generate.c
+++ b/crypto/ffc/ffc_params_generate.c
@@ -413,18 +413,15 @@ err:
return ret;
}
-static EVP_MD *fetch_default_md(OPENSSL_CTX *libctx, size_t N)
+static const char *default_mdname(size_t N)
{
- char *name = NULL;
-
if (N == 160)
- name = "SHA1";
+ return "SHA1";
else if (N == 224)
- name = "SHA-224";
+ return "SHA-224";
else if (N == 256)
- name = "SHA-256";
-
- return name != NULL ? EVP_MD_fetch(libctx, name, "") : NULL;
+ return "SHA-256";
+ return NULL;
}
/*
@@ -446,6 +443,13 @@ static EVP_MD *fetch_default_md(OPENSSL_CTX *libctx, size_t N)
* the seed and index used during generation as input.
*
* params: used to pass in values for generation and validation.
+ * params->md: is the digest to use, If this value is NULL, then the digest is
+ * chosen using the value of N.
+ * params->flags:
+ * For validation one of:
+ * -FFC_PARAM_FLAG_VALIDATE_PQ
+ * -FFC_PARAM_FLAG_VALIDATE_G
+ * -FFC_PARAM_FLAG_VALIDATE_ALL
* For generation of p & q:
* - This is skipped if p & q are passed in.
* - If the seed is passed in then generation of p & q uses this seed (and if
@@ -462,48 +466,58 @@ static EVP_MD *fetch_default_md(OPENSSL_CTX *libctx, size_t N)
* - For a partial validation : p, q and g are required.
* - For a canonical validation : the gindex and seed used for generation are
* also required.
+ * mode: The mode - either FFC_PARAM_MODE_GENERATE or FFC_PARAM_MODE_VERIFY.
* type: The key type - FFC_PARAM_TYPE_DSA or FFC_PARAM_TYPE_DH.
* L: is the size of the prime p in bits (e.g 2048)
* N: is the size of the prime q in bits (e.g 256)
- * evpmd: is the digest to use, If this value is NULL, then the digest is chosen
- * using the value of N.
- * validate_flags:
- * or generation: FFC_PARAMS_GENERATE.
- * For validation one of:
- * -FFC_PARAMS_VALIDATE_PQ
- * -FFC_PARAMS_VALIDATE_G
- * -FFC_PARAMS_VALIDATE_ALL
* res: A returned failure reason (One of FFC_CHECK_XXXX),
* or 0 for general failures.
* cb: A callback (can be NULL) that is called during different phases
*
* Returns:
- * - FFC_PARAMS_RET_STATUS_FAILED: if there was an error, or validation failed.
- * - FFC_PARAMS_RET_STATUS_SUCCESS if the generation or validation succeeded.
- * - FFC_PARAMS_RET_STATUS_UNVERIFIABLE_G if the validation of G succeeded,
+ * - FFC_PARAM_RET_STATUS_FAILED: if there was an error, or validation failed.
+ * - FFC_PARAM_RET_STATUS_SUCCESS if the generation or validation succeeded.
+ * - FFC_PARAM_RET_STATUS_UNVERIFIABLE_G if the validation of G succeeded,
* but G is unverifiable.
*/
int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
- int type, size_t L, size_t N,
- const EVP_MD *evpmd, int validate_flags,
+ int mode, int type, size_t L, size_t N,
int *res, BN_GENCB *cb)
{
- int ok = FFC_PARAMS_RET_STATUS_FAILED;
+ int ok = FFC_PARAM_RET_STATUS_FAILED;
unsigned char *seed = NULL, *seed_tmp = NULL;
int mdsize, counter = 0, pcounter = 0, r = 0;
size_t seedlen = 0;
BIGNUM *tmp, *pm1, *e, *test;
BIGNUM *g = NULL, *q = NULL, *p = NULL;
BN_MONT_CTX *mont = NULL;
- int n = 0, m = 0, qsize = N >> 3;
+ int n = 0, m = 0, qsize;
int canonical_g = 0, hret = 0;
BN_CTX *ctx = NULL;
EVP_MD_CTX *mctx = NULL;
- int generate = (validate_flags == 0);
- EVP_MD *evpmd_fetch = NULL;
+ EVP_MD *md = NULL;
+ int verify = (mode == FFC_PARAM_MODE_VERIFY);
+ unsigned int flags = verify ? params->flags : 0;
*res = 0;
+ if (params->mdname != NULL) {
+ md = EVP_MD_fetch(libctx, params->mdname, params->mdprops);
+ } else {
+ if (N <= 0)
+ N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8;
+ md = EVP_MD_fetch(libctx, default_mdname(N), NULL);
+ }
+ if (md == NULL)
+ goto err;
+ mdsize = EVP_MD_size(md);
+ if (mdsize <= 0)
+ goto err;
+
+ if (N <= 0)
+ N = mdsize * 8;
+ qsize = N >> 3;
+
/*
* A.1.1.2 Step (1) AND
* A.1.1.3 Step (3)
@@ -518,15 +532,6 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
if (mctx == NULL)
goto err;
- if (evpmd == NULL) {
- evpmd_fetch = fetch_default_md(libctx, N);
- evpmd = evpmd_fetch;
- }
-
- mdsize = EVP_MD_size(evpmd);
- if (mdsize <= 0)
- goto err;
-
if ((ctx = BN_CTX_new_ex(libctx)) == NULL)
goto err;
@@ -546,7 +551,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
if (params->seed != NULL)
seed = params->seed;
- if (generate) {
+ if (!verify) {
/* For generation: p & q must both be NULL or NON-NULL */
if ((params->p == NULL) != (params->q == NULL)) {
*res = FFC_CHECK_INVALID_PQ;
@@ -554,13 +559,13 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
}
} else {
/* Validation of p,q requires seed and counter to be valid */
- if ((validate_flags & FFC_PARAMS_VALIDATE_PQ) != 0) {
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) != 0) {
if (seed == NULL || params->pcounter < 0) {
*res = FFC_CHECK_MISSING_SEED_OR_COUNTER;
goto err;
}
}
- if ((validate_flags & FFC_PARAMS_VALIDATE_G) != 0) {
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0) {
/* validation of g also requires g to be set */
if (params->g == NULL) {
*res = FFC_CHECK_INVALID_G;
@@ -574,7 +579,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
* validate_flags = 0 then skip the generation of PQ.
* validate_flags = VALIDATE_G then also skip the validation of PQ.
*/
- if (params->p != NULL && ((validate_flags & FFC_PARAMS_VALIDATE_PQ) == 0)) {
+ if (params->p != NULL && ((flags & FFC_PARAM_FLAG_VALIDATE_PQ) == 0)) {
/* p and q already exists so only generate g */
p = params->p;
q = params->q;
@@ -604,7 +609,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
if (seed == NULL) {
/* Validation requires the seed to be supplied */
- if (validate_flags) {
+ if (verify) {
*res = FFC_CHECK_MISSING_SEED_OR_COUNTER;
goto err;
}
@@ -617,7 +622,7 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
/* A.1.1.2 Step (11): max loop count = 4L - 1 */
counter = 4 * L - 1;
/* Validation requires the counter to be supplied */
- if (validate_flags) {
+ if (verify) {
/* A.1.1.3 Step (4) : if (counter > (4L -1)) return INVALID */
if (params->pcounter > counter) {
*res = FFC_CHECK_INVALID_COUNTER;
@@ -638,11 +643,11 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
goto err;
for (;;) {
- if (!generate_q_fips186_4(ctx, q, evpmd, qsize, seed, seedlen,
+ if (!generate_q_fips186_4(ctx, q, md, qsize, seed, seedlen,
seed != params->seed, &m, res, cb))
goto err;
/* A.1.1.3 Step (9): Verify that q matches the expected value */
- if (validate_flags && (BN_cmp(q, params->q) != 0)) {
+ if (verify && (BN_cmp(q, params->q) != 0)) {
*res = FFC_CHECK_Q_MISMATCH;
goto err;
}
@@ -652,8 +657,8 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
goto err;
memcpy(seed_tmp, seed, seedlen);
- r = generate_p(ctx, evpmd, counter, n, seed_tmp, seedlen, q, p, L, cb,
- &pcounter, res);
+ r = generate_p(ctx, md, counter, n, seed_tmp, seedlen, q, p, L,
+ cb, &pcounter, res);
if (r > 0)
break; /* found p */
if (r < 0)
@@ -674,11 +679,11 @@ int ffc_params_FIPS186_4_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
* Gets here if we found p.
* A.1.1.3 Step (14): return error if i != counter OR computed_p != known_p.
*/
- if (validate_flags && (pcounter != counter || (BN_cmp(p, params->p) != 0)))
+ if (verify && (pcounter != counter || (BN_cmp(p, params->p) != 0)))
goto err;
/* If validating p & q only then skip the g validation test */
- if ((validate_flags & FFC_PARAMS_VALIDATE_ALL) == FFC_PARAMS_VALIDATE_PQ)
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_ALL) == FFC_PARAM_FLAG_VALIDATE_PQ)
goto pass;
g_only:
if ((mont = BN_MONT_CTX_new()) == NULL)
@@ -686,7 +691,7 @@ g_only:
if (!BN_MONT_CTX_set(mont, p, ctx))
goto err;
- if (((validate_flags & FFC_PARAMS_VALIDATE_G) != 0)
+ if (((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0)
&& !ffc_params_validate_unverifiable_g(ctx, mont, p, q, params->g,
tmp, res))
goto err;
@@ -703,17 +708,17 @@ g_only:
/* Canonical g requires a seed and index to be set */
if ((seed != NULL) && (params->gindex != FFC_UNVERIFIABLE_GINDEX)) {
canonical_g = 1;
- if (!generate_canonical_g(ctx, mont, evpmd, g, tmp, p, e,
+ if (!generate_canonical_g(ctx, mont, md, g, tmp, p, e,
params->gindex, seed, seedlen)) {
*res = FFC_CHECK_INVALID_G;
goto err;
}
/* A.2.4 Step (13): Return valid if computed_g == g */
- if (validate_flags && BN_cmp(g, params->g) != 0) {
+ if (verify && BN_cmp(g, params->g) != 0) {
*res = FFC_CHECK_G_MISMATCH;
goto err;
}
- } else if (generate) {
+ } else if (!verify) {
if (!generate_unverifiable_g(ctx, mont, g, tmp, p, e, pm1, &hret))
goto err;
}
@@ -721,7 +726,7 @@ g_only:
if (!BN_GENCB_call(cb, 3, 1))
goto err;
- if (generate) {
+ if (!verify) {
if (p != params->p) {
BN_free(params->p);
params->p = BN_dup(p);
@@ -741,11 +746,11 @@ g_only:
params->h = hret;
}
pass:
- if ((validate_flags & FFC_PARAMS_VALIDATE_G) != 0 && (canonical_g == 0))
+ if ((flags & FFC_PARAM_FLAG_VALIDATE_G) != 0 && (canonical_g == 0))
/* Return for the case where g is partially valid */
- ok = FFC_PARAMS_RET_STATUS_UNVERIFIABLE_G;
+ ok = FFC_PARAM_RET_STATUS_UNVERIFIABLE_G;
else
- ok = FFC_PARAMS_RET_STATUS_SUCCESS;
+ ok = FFC_PARAM_RET_STATUS_SUCCESS;
err:
if (seed != params->seed)
OPENSSL_free(seed);
@@ -754,33 +759,47 @@ err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
BN_MONT_CTX_free(mont);
- EVP_MD_free(evpmd_fetch);
EVP_MD_CTX_free(mctx);
+ EVP_MD_free(md);
return ok;
}
int ffc_params_FIPS186_2_gen_verify(OPENSSL_CTX *libctx, FFC_PARAMS *params,
- int type, size_t L, size_t N,
- const EVP_MD *evpmd, int validate_flags,
+ int mode, int type, size_t L, size_t N,
int *res, BN_GENCB *cb)
{
- int ok = FFC_PARAMS_RET_STATUS_FAILED;
+ int ok = FFC_PARAM_RET_STATUS_FAILED;
unsigned char seed[SHA256_DIGEST_LENGTH];
unsigned char buf[SHA256_DIGEST_LENGTH];
BIGNUM *r0, *test, *tmp, *g = NULL, *q = NULL, *p = NULL;
BN_MONT_CTX *mont = NULL;
- size_t qsize = N >> 3;
+ EVP_MD *md = NULL;
+ size_t qsize;
int n = 0, m = 0;
int counter = 0, pcounter = 0, use_random_seed;
int rv;
BN_CTX *ctx = NULL;
int hret = -1;
- int generate = (validate_flags == 0);
unsigned char *seed_in = params->seed;
size_t seed_len = params->seedlen;
- EVP_MD *evpmd_fetch = NULL;
+ int verify = (mode == FFC_PARAM_MODE_VERIFY);
+ unsigned int flags = verify ? params->flags : 0;
*res = 0;
+
+ if (params->mdname != NULL) {
+ md = EVP_MD_fetch(libctx, params->mdname, params->mdprops);
+ } else {
+ if (N <= 0)
+ N = (L >= 2048 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH) * 8;
+ md = EVP_MD_fetch(libctx, default_mdname(N), NULL);
+ }
+ if (md == NULL)
+ goto err;