aboutsummaryrefslogtreecommitdiff
path: root/crypto/dsa
diff options
context:
space:
mode:
authorShane Lontis <shane.lontis@oracle.com>2020-02-16 13:03:46 +1000
committerShane Lontis <shane.lontis@oracle.com>2020-02-16 13:03:46 +1000
commit8083fd3a183d4c881d6b15727cbc6cb7faeb3280 (patch)
tree82e998aa30cc9dc610b4f262df1f7ef73b23edad /crypto/dsa
parent98ad3fe82bd3e7e7f929dd1fa4ef3915426002c0 (diff)
downloadopenssl-8083fd3a183d4c881d6b15727cbc6cb7faeb3280.zip
openssl-8083fd3a183d4c881d6b15727cbc6cb7faeb3280.tar.gz
openssl-8083fd3a183d4c881d6b15727cbc6cb7faeb3280.tar.bz2
Add FFC param/key validation
Embed libctx in dsa and dh objects and cleanup internal methods to not pass libctx (This makes it consistent with the rsa changes) Reviewed-by: Matt Caswell <matt@openssl.org> (Merged from https://github.com/openssl/openssl/pull/10910)
Diffstat (limited to 'crypto/dsa')
-rw-r--r--crypto/dsa/dsa_check.c85
-rw-r--r--crypto/dsa/dsa_gen.c30
-rw-r--r--crypto/dsa/dsa_key.c49
-rw-r--r--crypto/dsa/dsa_lib.c26
-rw-r--r--crypto/dsa/dsa_local.h4
-rw-r--r--crypto/dsa/dsa_ossl.c7
-rw-r--r--crypto/dsa/dsa_sign.c8
7 files changed, 145 insertions, 64 deletions
diff --git a/crypto/dsa/dsa_check.c b/crypto/dsa/dsa_check.c
new file mode 100644
index 0000000..3b86d2d
--- /dev/null
+++ b/crypto/dsa/dsa_check.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright 1995-2019 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 <stdio.h>
+#include "internal/cryptlib.h"
+#include <openssl/bn.h>
+#include "dsa_local.h"
+#include "crypto/dsa.h"
+
+int dsa_check_params(const DSA *dsa, int *ret)
+{
+ int nid;
+ /*
+ * (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);
+}
+
+/*
+ * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Full public key validation.
+ */
+int dsa_check_pub_key(const DSA *dsa, const BIGNUM *pub_key, int *ret)
+{
+ return ffc_validate_public_key(&dsa->params, pub_key, ret);
+}
+
+/*
+ * See SP800-56Ar3 Section 5.6.2.3.1 : FFC Partial public key validation.
+ * To only be used with ephemeral FFC public keys generated using the approved
+ * safe-prime groups.
+ */
+int dsa_check_pub_key_partial(const DSA *dsa, const BIGNUM *pub_key, int *ret)
+{
+ return ffc_validate_public_key_partial(&dsa->params, pub_key, ret);
+}
+
+int dsa_check_priv_key(const DSA *dsa, const BIGNUM *priv_key, int *ret)
+{
+ *ret = 0;
+
+ return (dsa->params.q != NULL
+ && ffc_validate_private_key(dsa->params.q, priv_key, ret));
+}
+
+/*
+ * FFC pairwise check from SP800-56A R3.
+ * Section 5.6.2.1.4 Owner Assurance of Pair-wise Consistency
+ */
+int dsa_check_pairwise(const DSA *dsa)
+{
+ int ret = 0;
+ BN_CTX *ctx = NULL;
+ BIGNUM *pub_key = NULL;
+
+ if (dsa->params.p == NULL
+ || dsa->params.g == NULL
+ || dsa->priv_key == NULL
+ || dsa->pub_key == NULL)
+ return 0;
+
+ ctx = BN_CTX_new_ex(dsa->libctx);
+ if (ctx == NULL)
+ goto err;
+ pub_key = BN_new();
+ if (pub_key == NULL)
+ goto err;
+
+ /* recalculate the public key = (g ^ priv) mod p */
+ if (!dsa_generate_public_key(ctx, dsa, dsa->priv_key, pub_key))
+ goto err;
+ /* check it matches the existing pubic_key */
+ ret = BN_cmp(pub_key, dsa->pub_key) == 0;
+err:
+ BN_free(pub_key);
+ BN_CTX_free(ctx);
+ return ret;
+}
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
index ac5907c..2148a1a 100644
--- a/crypto/dsa/dsa_gen.c
+++ b/crypto/dsa/dsa_gen.c
@@ -23,7 +23,7 @@
#include "crypto/dsa.h"
#include "dsa_local.h"
-int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type,
+int dsa_generate_ffc_parameters(DSA *dsa, int type,
int pbits, int qbits, int gindex,
BN_GENCB *cb)
{
@@ -37,12 +37,12 @@ int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type,
dsa->params.gindex = gindex;
#ifndef FIPS_MODE
if (type == DSA_PARAMGEN_TYPE_FIPS_186_2)
- ret = ffc_params_FIPS186_2_generate(libctx, &dsa->params,
+ ret = ffc_params_FIPS186_2_generate(dsa->libctx, &dsa->params,
FFC_PARAM_TYPE_DSA,
pbits, qbits, NULL, &res, cb);
else
#endif
- ret = ffc_params_FIPS186_4_generate(libctx, &dsa->params,
+ ret = ffc_params_FIPS186_4_generate(dsa->libctx, &dsa->params,
FFC_PARAM_TYPE_DSA,
pbits, qbits, NULL, &res, cb);
if (ret > 0)
@@ -50,10 +50,10 @@ int dsa_generate_ffc_parameters(OPENSSL_CTX *libctx, DSA *dsa, int type,
return ret;
}
-int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits,
- const unsigned char *seed_in, int seed_len,
- int *counter_ret, unsigned long *h_ret,
- BN_GENCB *cb)
+int DSA_generate_parameters_ex(DSA *dsa, int bits,
+ const unsigned char *seed_in, int seed_len,
+ int *counter_ret, unsigned long *h_ret,
+ BN_GENCB *cb)
{
#ifndef FIPS_MODE
if (dsa->meth->dsa_paramgen)
@@ -67,15 +67,13 @@ int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits,
#ifndef FIPS_MODE
/* The old code used FIPS 186-2 DSA Parameter generation */
if (bits <= 1024 && seed_len == 20) {
- if (!dsa_generate_ffc_parameters(libctx, dsa,
- DSA_PARAMGEN_TYPE_FIPS_186_2,
+ if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_2,
bits, 160, -1, cb))
return 0;
} else
#endif
{
- if (!dsa_generate_ffc_parameters(libctx, dsa,
- DSA_PARAMGEN_TYPE_FIPS_186_4,
+ if (!dsa_generate_ffc_parameters(dsa, DSA_PARAMGEN_TYPE_FIPS_186_4,
bits, -1, -1, cb))
return 0;
}
@@ -86,13 +84,3 @@ int dsa_generate_parameters_ctx(OPENSSL_CTX *libctx, DSA *dsa, int bits,
*h_ret = dsa->params.h;
return 1;
}
-
-int DSA_generate_parameters_ex(DSA *dsa, int bits,
- const unsigned char *seed_in, int seed_len,
- int *counter_ret, unsigned long *h_ret,
- BN_GENCB *cb)
-{
- return dsa_generate_parameters_ctx(NULL, dsa, bits,
- seed_in, seed_len,
- counter_ret, h_ret, cb);
-}
diff --git a/crypto/dsa/dsa_key.c b/crypto/dsa/dsa_key.c
index 00e7213..c93ea15 100644
--- a/crypto/dsa/dsa_key.c
+++ b/crypto/dsa/dsa_key.c
@@ -20,31 +20,43 @@
#include "crypto/dsa.h"
#include "dsa_local.h"
-static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa);
+static int dsa_builtin_keygen(DSA *dsa);
int DSA_generate_key(DSA *dsa)
{
+#ifndef FIPS_MODE
if (dsa->meth->dsa_keygen != NULL)
return dsa->meth->dsa_keygen(dsa);
- return dsa_builtin_keygen(NULL, dsa);
+#endif
+ return dsa_builtin_keygen(dsa);
}
-int dsa_generate_key_ctx(OPENSSL_CTX *libctx, DSA *dsa)
+int dsa_generate_public_key(BN_CTX *ctx, const DSA *dsa, const BIGNUM *priv_key,
+ BIGNUM *pub_key)
{
-#ifndef FIPS_MODE
- if (dsa->meth->dsa_keygen != NULL)
- return dsa->meth->dsa_keygen(dsa);
-#endif
- return dsa_builtin_keygen(libctx, dsa);
+ int ret = 0;
+ BIGNUM *prk = BN_new();
+
+ if (prk == NULL)
+ return 0;
+ BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
+
+ /* pub_key = g ^ priv_key mod p */
+ if (!BN_mod_exp(pub_key, dsa->params.g, prk, dsa->params.p, ctx))
+ goto err;
+ ret = 1;
+err:
+ BN_clear_free(prk);
+ return ret;
}
-static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa)
+static int dsa_builtin_keygen(DSA *dsa)
{
int ok = 0;
BN_CTX *ctx = NULL;
BIGNUM *pub_key = NULL, *priv_key = NULL;
- if ((ctx = BN_CTX_new_ex(libctx)) == NULL)
+ if ((ctx = BN_CTX_new_ex(dsa->libctx)) == NULL)
goto err;
if (dsa->priv_key == NULL) {
@@ -65,21 +77,8 @@ static int dsa_builtin_keygen(OPENSSL_CTX *libctx, DSA *dsa)
pub_key = dsa->pub_key;
}
- {
- BIGNUM *prk = BN_new();
-
- if (prk == NULL)
- goto err;
- BN_with_flags(prk, priv_key, BN_FLG_CONSTTIME);
-
- /* pub_key = g ^ priv_key mod p */
- if (!BN_mod_exp(pub_key, dsa->params.g, prk, dsa->params.p, ctx)) {
- BN_free(prk);
- goto err;
- }
- /* We MUST free prk before any further use of priv_key */
- BN_free(prk);
- }
+ if (!dsa_generate_public_key(ctx, dsa, priv_key, pub_key))
+ goto err;
dsa->priv_key = priv_key;
dsa->pub_key = pub_key;
diff --git a/crypto/dsa/dsa_lib.c b/crypto/dsa/dsa_lib.c
index 11f0989..4b048d4 100644
--- a/crypto/dsa/dsa_lib.c
+++ b/crypto/dsa/dsa_lib.c
@@ -23,6 +23,8 @@
#include "crypto/dsa.h"
#include "crypto/dh.h" /* required by DSA_dup_DH() */
+static DSA *dsa_new_intern(ENGINE *engine, OPENSSL_CTX *libctx);
+
#ifndef FIPS_MODE
int DSA_set_ex_data(DSA *d, int idx, void *arg)
@@ -128,29 +130,30 @@ const DSA_METHOD *DSA_get_method(DSA *d)
return d->meth;
}
-static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine)
+static DSA *dsa_new_intern(ENGINE *engine, OPENSSL_CTX *libctx)
{
DSA *ret = OPENSSL_zalloc(sizeof(*ret));
if (ret == NULL) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ DSAerr(0, ERR_R_MALLOC_FAILURE);
return NULL;
}
ret->references = 1;
ret->lock = CRYPTO_THREAD_lock_new();
if (ret->lock == NULL) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_MALLOC_FAILURE);
+ DSAerr(0, ERR_R_MALLOC_FAILURE);
OPENSSL_free(ret);
return NULL;
}
+ ret->libctx = libctx;
ret->meth = DSA_get_default_method();
#if !defined(FIPS_MODE) && !defined(OPENSSL_NO_ENGINE)
ret->flags = ret->meth->flags & ~DSA_FLAG_NON_FIPS_ALLOW; /* early default init */
if (engine) {
if (!ENGINE_init(engine)) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
+ DSAerr(0, ERR_R_ENGINE_LIB);
goto err;
}
ret->engine = engine;
@@ -159,7 +162,7 @@ static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine)
if (ret->engine) {
ret->meth = ENGINE_get_DSA(ret->engine);
if (ret->meth == NULL) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_ENGINE_LIB);
+ DSAerr(0, ERR_R_ENGINE_LIB);
goto err;
}
}
@@ -173,7 +176,7 @@ static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine)
#endif
if ((ret->meth->init != NULL) && !ret->meth->init(ret)) {
- DSAerr(DSA_F_DSA_NEW_METHOD, ERR_R_INIT_FAIL);
+ DSAerr(0, ERR_R_INIT_FAIL);
goto err;
}
@@ -186,13 +189,20 @@ static DSA *dsa_new_method(OPENSSL_CTX *libctx, ENGINE *engine)
DSA *DSA_new_method(ENGINE *engine)
{
- return dsa_new_method(NULL, engine);
+ return dsa_new_intern(engine, NULL);
+}
+
+DSA *dsa_new_with_ctx(OPENSSL_CTX *libctx)
+{
+ return dsa_new_intern(NULL, libctx);
}
+#ifndef FIPS_MODE
DSA *DSA_new(void)
{
- return DSA_new_method(NULL);
+ return dsa_new_intern(NULL, NULL);
}
+#endif
void DSA_free(DSA *r)
{
diff --git a/crypto/dsa/dsa_local.h b/crypto/dsa/dsa_local.h
index f01b0aa..f68ae2d 100644
--- a/crypto/dsa/dsa_local.h
+++ b/crypto/dsa/dsa_local.h
@@ -32,6 +32,7 @@ struct dsa_st {
/* functional reference if 'meth' is ENGINE-provided */
ENGINE *engine;
CRYPTO_RWLOCK *lock;
+ OPENSSL_CTX *libctx;
/* Provider data */
size_t dirty_cnt; /* If any key material changes, increment this */
@@ -68,5 +69,4 @@ struct dsa_method {
int (*dsa_keygen) (DSA *dsa);
};
-DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
- int dlen, DSA *dsa);
+DSA_SIG *dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa);
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index 6ff22e8..a87493a 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -67,8 +67,7 @@ const DSA_METHOD *DSA_OpenSSL(void)
return &openssl_dsa_meth;
}
-DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
- int dlen, DSA *dsa)
+DSA_SIG *dsa_do_sign_int(const unsigned char *dgst, int dlen, DSA *dsa)
{
BIGNUM *kinv = NULL;
BIGNUM *m, *blind, *blindm, *tmp;
@@ -96,7 +95,7 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
if (ret->r == NULL || ret->s == NULL)
goto err;
- ctx = BN_CTX_new_ex(libctx);
+ ctx = BN_CTX_new_ex(dsa->libctx);
if (ctx == NULL)
goto err;
m = BN_CTX_get(ctx);
@@ -186,7 +185,7 @@ DSA_SIG *dsa_do_sign_int(OPENSSL_CTX *libctx, const unsigned char *dgst,
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
- return dsa_do_sign_int(NULL, dgst, dlen, dsa);
+ return dsa_do_sign_int(dgst, dlen, dsa);
}
static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in,
diff --git a/crypto/dsa/dsa_sign.c b/crypto/dsa/dsa_sign.c
index 1ee9272..9ef8f30 100644
--- a/crypto/dsa/dsa_sign.c
+++ b/crypto/dsa/dsa_sign.c
@@ -148,16 +148,16 @@ int DSA_SIG_set0(DSA_SIG *sig, BIGNUM *r, BIGNUM *s)
return 1;
}
-int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst,
+int dsa_sign_int(int type, const unsigned char *dgst,
int dlen, unsigned char *sig, unsigned int *siglen, DSA *dsa)
{
DSA_SIG *s;
/* legacy case uses the method table */
- if (libctx == NULL || dsa->meth != DSA_get_default_method())
+ if (dsa->libctx == NULL || dsa->meth != DSA_get_default_method())
s = DSA_do_sign(dgst, dlen, dsa);
else
- s = dsa_do_sign_int(libctx, dgst, dlen, dsa);
+ s = dsa_do_sign_int(dgst, dlen, dsa);
if (s == NULL) {
*siglen = 0;
return 0;
@@ -170,7 +170,7 @@ int dsa_sign_int(OPENSSL_CTX *libctx, int type, const unsigned char *dgst,
int DSA_sign(int type, const unsigned char *dgst, int dlen,
unsigned char *sig, unsigned int *siglen, DSA *dsa)
{
- return dsa_sign_int(NULL, type, dgst, dlen, sig, siglen, dsa);
+ return dsa_sign_int(type, dgst, dlen, sig, siglen, dsa);
}
/* data has already been hashed (probably with SHA or SHA-1). */