/* 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
BN_CTX *ctx=NULL;
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_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)
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);