summaryrefslogtreecommitdiff
path: root/crypto/dsa
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/dsa')
-rw-r--r--crypto/dsa/dsa.h9
-rw-r--r--crypto/dsa/dsa_err.c3
-rw-r--r--crypto/dsa/dsa_gen.c19
-rw-r--r--crypto/dsa/dsa_ossl.c111
-rw-r--r--crypto/dsa/dsa_pmeth.c12
5 files changed, 119 insertions, 35 deletions
diff --git a/crypto/dsa/dsa.h b/crypto/dsa/dsa.h
index 545358f..3e6984e 100644
--- a/crypto/dsa/dsa.h
+++ b/crypto/dsa/dsa.h
@@ -249,10 +249,12 @@ int DSAparams_print_fp(FILE *fp, const DSA *x);
int DSA_print_fp(FILE *bp, const DSA *x, int off);
# endif
-# define DSS_prime_checks 50
+# define DSS_prime_checks 64
/*
- * Primality test according to FIPS PUB 186[-1], Appendix 2.1: 50 rounds of
- * Rabin-Miller
+ * Primality test according to FIPS PUB 186-4, Appendix C.3. Since we only
+ * have one value here we set the number of checks to 64 which is the 128 bit
+ * security level that is the highest level and valid for creating a 3072 bit
+ * DSA key.
*/
# define DSA_is_prime(n, callback, cb_arg) \
BN_is_prime(n, DSS_prime_checks, callback, NULL, cb_arg)
@@ -307,6 +309,7 @@ void ERR_load_DSA_strings(void);
# define DSA_F_I2D_DSA_SIG 111
# define DSA_F_OLD_DSA_PRIV_DECODE 122
# define DSA_F_PKEY_DSA_CTRL 120
+# define DSA_F_PKEY_DSA_CTRL_STR 127
# define DSA_F_PKEY_DSA_KEYGEN 121
# define DSA_F_SIG_CB 114
diff --git a/crypto/dsa/dsa_err.c b/crypto/dsa/dsa_err.c
index f5ddc66..7e507fa 100644
--- a/crypto/dsa/dsa_err.c
+++ b/crypto/dsa/dsa_err.c
@@ -1,6 +1,6 @@
/* crypto/dsa/dsa_err.c */
/* ====================================================================
- * Copyright (c) 1999-2013 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 1999-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -95,6 +95,7 @@ static ERR_STRING_DATA DSA_str_functs[] = {
{ERR_FUNC(DSA_F_I2D_DSA_SIG), "i2d_DSA_SIG"},
{ERR_FUNC(DSA_F_OLD_DSA_PRIV_DECODE), "OLD_DSA_PRIV_DECODE"},
{ERR_FUNC(DSA_F_PKEY_DSA_CTRL), "PKEY_DSA_CTRL"},
+ {ERR_FUNC(DSA_F_PKEY_DSA_CTRL_STR), "PKEY_DSA_CTRL_STR"},
{ERR_FUNC(DSA_F_PKEY_DSA_KEYGEN), "PKEY_DSA_KEYGEN"},
{ERR_FUNC(DSA_F_SIG_CB), "SIG_CB"},
{0, NULL}
diff --git a/crypto/dsa/dsa_gen.c b/crypto/dsa/dsa_gen.c
index 21af2e1..e55d585 100644
--- a/crypto/dsa/dsa_gen.c
+++ b/crypto/dsa/dsa_gen.c
@@ -146,9 +146,16 @@ int dsa_builtin_paramgen(DSA *ret, size_t bits, size_t qbits,
/* invalid q size */
return 0;
- if (evpmd == NULL)
- /* use SHA1 as default */
- evpmd = EVP_sha1();
+ if (evpmd == NULL) {
+ if (qsize == SHA_DIGEST_LENGTH)
+ evpmd = EVP_sha1();
+ else if (qsize == SHA224_DIGEST_LENGTH)
+ evpmd = EVP_sha224();
+ else
+ evpmd = EVP_sha256();
+ } else {
+ qsize = EVP_MD_size(evpmd);
+ }
if (bits < 512)
bits = 512;
@@ -428,6 +435,12 @@ int dsa_builtin_paramgen2(DSA *ret, size_t L, size_t N,
EVP_MD_CTX_init(&mctx);
+ /* make sure L > N, otherwise we'll get trapped in an infinite loop */
+ if (L <= N) {
+ DSAerr(DSA_F_DSA_BUILTIN_PARAMGEN2, DSA_R_INVALID_PARAMETERS);
+ goto err;
+ }
+
if (evpmd == NULL) {
if (N == 160)
evpmd = EVP_sha1();
diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c
index aa10dd1..c887c3c 100644
--- a/crypto/dsa/dsa_ossl.c
+++ b/crypto/dsa/dsa_ossl.c
@@ -73,6 +73,8 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len,
DSA_SIG *sig, DSA *dsa);
static int dsa_init(DSA *dsa);
static int dsa_finish(DSA *dsa);
+static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q,
+ BN_CTX *ctx);
static DSA_METHOD openssl_dsa_meth = {
"OpenSSL DSA method",
@@ -133,17 +135,13 @@ const DSA_METHOD *DSA_OpenSSL(void)
static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
{
BIGNUM *kinv = NULL, *r = NULL, *s = NULL;
- BIGNUM m;
- BIGNUM xr;
+ BIGNUM *m, *blind, *blindm, *tmp;
BN_CTX *ctx = NULL;
int reason = ERR_R_BN_LIB;
DSA_SIG *ret = NULL;
int noredo = 0;
- BN_init(&m);
- BN_init(&xr);
-
- if (!dsa->p || !dsa->q || !dsa->g) {
+ if (dsa->p == NULL || dsa->q == NULL || dsa->g == NULL) {
reason = DSA_R_MISSING_PARAMETERS;
goto err;
}
@@ -154,6 +152,13 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
ctx = BN_CTX_new();
if (ctx == NULL)
goto err;
+ m = BN_CTX_get(ctx);
+ blind = BN_CTX_get(ctx);
+ blindm = BN_CTX_get(ctx);
+ tmp = BN_CTX_get(ctx);
+ if (tmp == NULL)
+ goto err;
+
redo:
if ((dsa->kinv == NULL) || (dsa->r == NULL)) {
if (!DSA_sign_setup(dsa, ctx, &kinv, &r))
@@ -173,20 +178,52 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
* 4.2
*/
dlen = BN_num_bytes(dsa->q);
- if (BN_bin2bn(dgst, dlen, &m) == NULL)
+ if (BN_bin2bn(dgst, dlen, m) == NULL)
goto err;
- /* Compute s = inv(k) (m + xr) mod q */
- if (!BN_mod_mul(&xr, dsa->priv_key, r, dsa->q, ctx))
- goto err; /* s = xr */
- if (!BN_add(s, &xr, &m))
- goto err; /* s = m + xr */
- if (BN_cmp(s, dsa->q) > 0)
- if (!BN_sub(s, s, dsa->q))
+ /*
+ * The normal signature calculation is:
+ *
+ * s := k^-1 * (m + r * priv_key) mod q
+ *
+ * We will blind this to protect against side channel attacks
+ *
+ * s := blind^-1 * k^-1 * (blind * m + blind * r * priv_key) mod q
+ */
+
+ /* Generate a blinding value */
+ do {
+ if (!BN_rand(blind, BN_num_bits(dsa->q) - 1, -1, 0))
goto err;
+ } while (BN_is_zero(blind));
+ BN_set_flags(blind, BN_FLG_CONSTTIME);
+ BN_set_flags(blindm, BN_FLG_CONSTTIME);
+ BN_set_flags(tmp, BN_FLG_CONSTTIME);
+
+ /* tmp := blind * priv_key * r mod q */
+ if (!BN_mod_mul(tmp, blind, dsa->priv_key, dsa->q, ctx))
+ goto err;
+ if (!BN_mod_mul(tmp, tmp, r, dsa->q, ctx))
+ goto err;
+
+ /* blindm := blind * m mod q */
+ if (!BN_mod_mul(blindm, blind, m, dsa->q, ctx))
+ goto err;
+
+ /* s : = (blind * priv_key * r) + (blind * m) mod q */
+ if (!BN_mod_add_quick(s, tmp, blindm, dsa->q))
+ goto err;
+
+ /* s := s * k^-1 mod q */
if (!BN_mod_mul(s, s, kinv, dsa->q, ctx))
goto err;
+ /* s:= s * blind^-1 mod q */
+ if (BN_mod_inverse(blind, blind, dsa->q, ctx) == NULL)
+ goto err;
+ if (!BN_mod_mul(s, s, blind, dsa->q, ctx))
+ goto err;
+
/*
* Redo if r or s is zero as required by FIPS 186-3: this is very
* unlikely.
@@ -210,13 +247,9 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
BN_free(r);
BN_free(s);
}
- if (ctx != NULL)
- BN_CTX_free(ctx);
- BN_clear_free(&m);
- BN_clear_free(&xr);
- if (kinv != NULL) /* dsa->kinv is NULL now if we used it */
- BN_clear_free(kinv);
- return (ret);
+ BN_CTX_free(ctx);
+ BN_clear_free(kinv);
+ return ret;
}
static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
@@ -248,7 +281,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
goto err;
/* Preallocate space */
- q_bits = BN_num_bits(dsa->q);
+ q_bits = BN_num_bits(dsa->q) + sizeof(dsa->q->d[0]) * 16;
if (!BN_set_bit(&k, q_bits)
|| !BN_set_bit(&l, q_bits)
|| !BN_set_bit(&m, q_bits))
@@ -262,9 +295,9 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) {
BN_set_flags(&k, BN_FLG_CONSTTIME);
+ BN_set_flags(&l, BN_FLG_CONSTTIME);
}
-
if (dsa->flags & DSA_FLAG_CACHE_MONT_P) {
if (!BN_MONT_CTX_set_locked(&dsa->method_mont_p,
CRYPTO_LOCK_DSA, dsa->p, ctx))
@@ -302,8 +335,8 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp,
if (!BN_mod(r, r, dsa->q, ctx))
goto err;
- /* Compute part of 's = inv(k) (m + xr) mod q' */
- if ((kinv = BN_mod_inverse(NULL, &k, dsa->q, ctx)) == NULL)
+ /* Compute part of 's = inv(k) (m + xr) mod q' */
+ if ((kinv = dsa_mod_inverse_fermat(&k, dsa->q, ctx)) == NULL)
goto err;
if (*kinvp != NULL)
@@ -437,3 +470,31 @@ static int dsa_finish(DSA *dsa)
BN_MONT_CTX_free(dsa->method_mont_p);
return (1);
}
+
+/*
+ * Compute the inverse of k modulo q.
+ * Since q is prime, Fermat's Little Theorem applies, which reduces this to
+ * mod-exp operation. Both the exponent and modulus are public information
+ * so a mod-exp that doesn't leak the base is sufficient. A newly allocated
+ * BIGNUM is returned which the caller must free.
+ */
+static BIGNUM *dsa_mod_inverse_fermat(const BIGNUM *k, const BIGNUM *q,
+ BN_CTX *ctx)
+{
+ BIGNUM *res = NULL;
+ BIGNUM *r, e;
+
+ if ((r = BN_new()) == NULL)
+ return NULL;
+
+ BN_init(&e);
+
+ if (BN_set_word(r, 2)
+ && BN_sub(&e, q, r)
+ && BN_mod_exp_mont(r, k, &e, q, ctx, NULL))
+ res = r;
+ else
+ BN_free(r);
+ BN_free(&e);
+ return res;
+}
diff --git a/crypto/dsa/dsa_pmeth.c b/crypto/dsa/dsa_pmeth.c
index 7872483..7f00e97 100644
--- a/crypto/dsa/dsa_pmeth.c
+++ b/crypto/dsa/dsa_pmeth.c
@@ -3,7 +3,7 @@
* 2006.
*/
/* ====================================================================
- * Copyright (c) 2006 The OpenSSL Project. All rights reserved.
+ * Copyright (c) 2006-2018 The OpenSSL Project. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -230,10 +230,16 @@ static int pkey_dsa_ctrl_str(EVP_PKEY_CTX *ctx,
EVP_PKEY_CTRL_DSA_PARAMGEN_Q_BITS, qbits,
NULL);
}
- if (!strcmp(type, "dsa_paramgen_md")) {
+ if (strcmp(type, "dsa_paramgen_md") == 0) {
+ const EVP_MD *md = EVP_get_digestbyname(value);
+
+ if (md == NULL) {
+ DSAerr(DSA_F_PKEY_DSA_CTRL_STR, DSA_R_INVALID_DIGEST_TYPE);
+ return 0;
+ }
return EVP_PKEY_CTX_ctrl(ctx, EVP_PKEY_DSA, EVP_PKEY_OP_PARAMGEN,
EVP_PKEY_CTRL_DSA_PARAMGEN_MD, 0,
- (void *)EVP_get_digestbyname(value));
+ (void *)md);
}
return -2;
}