X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=crypto%2Fdsa%2Fdsa_ossl.c;h=edaee5987772b078b0f4274406c7e08f7486ed2f;hb=fda29b6db038716e4409068798646c6db042e552;hp=2e5ede78268c1491ba1ddbc0a67715b3dcb722e4;hpb=46a643763de6d8e39ecf6f76fa79b4d04885aa59;p=oweals%2Fopenssl.git diff --git a/crypto/dsa/dsa_ossl.c b/crypto/dsa/dsa_ossl.c index 2e5ede7826..edaee59877 100644 --- a/crypto/dsa/dsa_ossl.c +++ b/crypto/dsa/dsa_ossl.c @@ -58,30 +58,39 @@ /* Original version from Steven Schoch */ +#define OPENSSL_FIPSAPI + #include #include "cryptlib.h" #include +#include #include #include #include +#ifdef OPENSSL_FIPS +#include +#endif static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa); -static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); +static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp); +static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp, + const unsigned char *dgst, int dlen); static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, - DSA *dsa); + DSA *dsa); static int dsa_init(DSA *dsa); static int dsa_finish(DSA *dsa); static DSA_METHOD openssl_dsa_meth = { "OpenSSL DSA method", dsa_do_sign, -dsa_sign_setup, +dsa_sign_setup_no_digest, dsa_do_verify, NULL, /* dsa_mod_exp, */ NULL, /* dsa_bn_mod_exp, */ dsa_init, dsa_finish, -0, +DSA_FLAG_FIPS_METHOD, NULL, NULL, NULL @@ -133,8 +142,26 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) BIGNUM m; BIGNUM xr; BN_CTX *ctx=NULL; - int i,reason=ERR_R_BN_LIB; + int reason=ERR_R_BN_LIB; DSA_SIG *ret=NULL; + int noredo = 0; + +#ifdef OPENSSL_FIPS + if(FIPS_selftest_failed()) + { + FIPSerr(FIPS_F_DSA_DO_SIGN,FIPS_R_FIPS_SELFTEST_FAILED); + return NULL; + } + + if (FIPS_module_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW) + && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) + { + DSAerr(DSA_F_DSA_DO_SIGN, DSA_R_KEY_SIZE_TOO_SMALL); + return NULL; + } + if (!fips_check_dsa_prng(dsa, 0, 0)) + goto err; +#endif BN_init(&m); BN_init(&xr); @@ -147,20 +174,13 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) s=BN_new(); if (s == NULL) goto err; - - i=BN_num_bytes(dsa->q); /* should be 20 */ - if ((dlen > i) || (dlen > 50)) - { - reason=DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE; - goto err; - } - ctx=BN_CTX_new(); if (ctx == NULL) goto err; - +redo: if ((dsa->kinv == NULL) || (dsa->r == NULL)) { - if (!DSA_sign_setup(dsa,ctx,&kinv,&r)) goto err; + if (!dsa_sign_setup(dsa,ctx,&kinv,&r,dgst,dlen)) + goto err; } else { @@ -168,19 +188,39 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa) dsa->kinv=NULL; r=dsa->r; dsa->r=NULL; + noredo = 1; } - if (BN_bin2bn(dgst,dlen,&m) == NULL) goto err; + + if (dlen > BN_num_bytes(dsa->q)) + /* if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see + * fips 186-3, 4.2 */ + dlen = BN_num_bytes(dsa->q); + 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) - BN_sub(s,s,dsa->q); + if (!BN_sub(s,s,dsa->q)) goto err; if (!BN_mod_mul(s,s,kinv,dsa->q,ctx)) goto err; ret=DSA_SIG_new(); if (ret == NULL) goto err; + /* Redo if r or s is zero as required by FIPS 186-3: this is + * very unlikely. + */ + if (BN_is_zero(r) || BN_is_zero(s)) + { + if (noredo) + { + reason = DSA_R_NEED_NEW_SETUP_VALUES; + goto err; + } + goto redo; + } ret->r = r; ret->s = s; @@ -199,10 +239,17 @@ err: return(ret); } -static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) +static int dsa_sign_setup_no_digest(DSA *dsa, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp) { + return dsa_sign_setup(dsa, ctx_in, kinvp, rp, NULL, 0); +} + +static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, + BIGNUM **kinvp, BIGNUM **rp, + const unsigned char *dgst, int dlen) { BN_CTX *ctx; - BIGNUM k,*kinv=NULL,*r=NULL; + BIGNUM k,kq,*K,*kinv=NULL,*r=NULL; int ret=0; if (!dsa->p || !dsa->q || !dsa->g) @@ -212,6 +259,7 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) } BN_init(&k); + BN_init(&kq); if (ctx_in == NULL) { @@ -221,15 +269,28 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) ctx=ctx_in; if ((r=BN_new()) == NULL) goto err; - kinv=NULL; /* Get random k */ do - if (!BN_rand_range(&k, dsa->q)) goto err; - while (BN_is_zero(&k)); + { +#ifndef OPENSSL_NO_SHA512 + if (dgst != NULL) + { + /* We calculate k from SHA512(private_key + H(message) + * + random). This protects the private key from a weak + * PRNG. */ + if (!BN_generate_dsa_nonce(&k, dsa->q, dsa->priv_key, dgst, + dlen, ctx)) + goto err; + } + else +#endif + if (!BN_rand_range(&k, dsa->q)) goto err; + } while (BN_is_zero(&k)); + if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) { - BN_set_flags(&k, BN_FLG_EXP_CONSTTIME); + BN_set_flags(&k, BN_FLG_CONSTTIME); } if (dsa->flags & DSA_FLAG_CACHE_MONT_P) @@ -241,7 +302,30 @@ static int dsa_sign_setup(DSA *dsa, BN_CTX *ctx_in, BIGNUM **kinvp, BIGNUM **rp) } /* Compute r = (g^k mod p) mod q */ - DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, &k, dsa->p, ctx, + + if ((dsa->flags & DSA_FLAG_NO_EXP_CONSTTIME) == 0) + { + if (!BN_copy(&kq, &k)) goto err; + + /* We do not want timing information to leak the length of k, + * so we compute g^k using an equivalent exponent of fixed length. + * + * (This is a kludge that we need because the BN_mod_exp_mont() + * does not let us specify the desired timing behaviour.) */ + + if (!BN_add(&kq, &kq, dsa->q)) goto err; + if (BN_num_bits(&kq) <= BN_num_bits(dsa->q)) + { + if (!BN_add(&kq, &kq, dsa->q)) goto err; + } + + K = &kq; + } + else + { + K = &k; + } + DSA_BN_MOD_EXP(goto err, dsa, r, dsa->g, K, dsa->p, ctx, dsa->method_mont_p); if (!BN_mod(r,r,dsa->q,ctx)) goto err; @@ -258,28 +342,56 @@ err: if (!ret) { DSAerr(DSA_F_DSA_SIGN_SETUP,ERR_R_BN_LIB); - if (kinv != NULL) BN_clear_free(kinv); - if (r != NULL) BN_clear_free(r); + if (r != NULL) + BN_clear_free(r); } if (ctx_in == NULL) BN_CTX_free(ctx); - if (kinv != NULL) BN_clear_free(kinv); BN_clear_free(&k); + BN_clear_free(&kq); return(ret); } static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, - DSA *dsa) + DSA *dsa) { BN_CTX *ctx; BIGNUM u1,u2,t1; BN_MONT_CTX *mont=NULL; - int ret = -1; + int ret = -1, i; if (!dsa->p || !dsa->q || !dsa->g) { DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MISSING_PARAMETERS); return -1; } + i = BN_num_bits(dsa->q); + /* fips 186-3 allows only different sizes for q */ + if (i != 160 && i != 224 && i != 256) + { + DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_BAD_Q_VALUE); + return -1; + } + +#ifdef OPENSSL_FIPS + if(FIPS_selftest_failed()) + { + FIPSerr(FIPS_F_DSA_DO_VERIFY,FIPS_R_FIPS_SELFTEST_FAILED); + return -1; + } + + if (FIPS_module_mode() && !(dsa->flags & DSA_FLAG_NON_FIPS_ALLOW) + && (BN_num_bits(dsa->p) < OPENSSL_DSA_FIPS_MIN_MODULUS_BITS)) + { + DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_KEY_SIZE_TOO_SMALL); + return -1; + } +#endif + + if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS) + { + DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MODULUS_TOO_LARGE); + return -1; + } BN_init(&u1); BN_init(&u2); BN_init(&t1); @@ -304,6 +416,11 @@ static int dsa_do_verify(const unsigned char *dgst, int dgst_len, DSA_SIG *sig, if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err; /* save M in u1 */ + if (dgst_len > (i >> 3)) + /* if the digest length is greater than the size of q use the + * BN_num_bits(dsa->q) leftmost bits of the digest, see + * fips 186-3, 4.2 */ + dgst_len = (i >> 3); if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err; /* u1 = M * w mod q */