/* Original version from Steven Schoch <schoch@sheba.arc.nasa.gov> */
+#define OPENSSL_FIPSAPI
+
#include <stdio.h>
#include "cryptlib.h"
#include <openssl/bn.h>
#include <openssl/dsa.h>
#include <openssl/rand.h>
#include <openssl/asn1.h>
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#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);
NULL, /* dsa_bn_mod_exp, */
dsa_init,
dsa_finish,
-0,
+DSA_FLAG_FIPS_METHOD,
NULL,
NULL,
NULL
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);
s=BN_new();
if (s == NULL) goto err;
-
- /* reject a excessive digest length (currently at most
- * dsa-with-SHA256 is supported) */
- if (dlen > SHA256_DIGEST_LENGTH)
- {
- 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->meth->dsa_sign_setup(dsa,ctx,&kinv,&r)) goto err;
}
else
{
dsa->kinv=NULL;
r=dsa->r;
dsa->r=NULL;
+ noredo = 1;
}
- if (BN_bin2bn(dgst,dlen,&m) == NULL)
- goto err;
- i = BN_num_bytes(dsa->q);
- if (dlen > i)
- {
+
+ 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 */
- if (!BN_rshift(&m, &m, (dlen - i) << 3))
- goto err;
- }
+ 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;
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)
BN_CTX *ctx;
BIGNUM u1,u2,t1;
BN_MONT_CTX *mont=NULL;
- int ret = -1, i, j;
+ int ret = -1, i;
if (!dsa->p || !dsa->q || !dsa->g)
{
DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MISSING_PARAMETERS);
return -1;
}
- if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS)
+#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_MODULUS_TOO_LARGE);
+ DSAerr(DSA_F_DSA_DO_VERIFY, DSA_R_KEY_SIZE_TOO_SMALL);
return -1;
}
+#endif
- /* reject a excessive digest length (currently at most
- * dsa-with-SHA256 is supported) */
- if (dgst_len > SHA256_DIGEST_LENGTH)
+ if (BN_num_bits(dsa->p) > OPENSSL_DSA_MAX_MODULUS_BITS)
{
- DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_DATA_TOO_LARGE_FOR_KEY_SIZE);
+ DSAerr(DSA_F_DSA_DO_VERIFY,DSA_R_MODULUS_TOO_LARGE);
return -1;
}
-
BN_init(&u1);
BN_init(&u2);
BN_init(&t1);
if ((BN_mod_inverse(&u2,sig->s,dsa->q,ctx)) == NULL) goto err;
/* save M in u1 */
- if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err;
- j = dgst_len << 3;
- if (j > i)
- {
+ 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 */
- if (!BN_rshift(&u1, &u1, j - i))
- goto err;
- }
+ dgst_len = (i >> 3);
+ if (BN_bin2bn(dgst,dgst_len,&u1) == NULL) goto err;
/* u1 = M * w mod q */
if (!BN_mod_mul(&u1,&u1,&u2,dsa->q,ctx)) goto err;