recalculate DSA signature if r or s is zero (FIPS 186-3 requirement)
authorDr. Stephen Henson <steve@openssl.org>
Tue, 25 Jan 2011 16:01:29 +0000 (16:01 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Tue, 25 Jan 2011 16:01:29 +0000 (16:01 +0000)
crypto/dsa/dsa.h
crypto/dsa/dsa_err.c
crypto/dsa/dsa_ossl.c

index bbe8cb5..3d40183 100644 (file)
@@ -299,6 +299,7 @@ void ERR_load_DSA_strings(void);
 #define DSA_R_INVALID_DIGEST_TYPE                       106
 #define DSA_R_MISSING_PARAMETERS                        101
 #define DSA_R_MODULUS_TOO_LARGE                                 103
+#define DSA_R_NEED_NEW_SETUP_VALUES                     110
 #define DSA_R_NO_PARAMETERS_SET                                 107
 #define DSA_R_PARAMETER_ENCODING_ERROR                  105
 
index a1e9993..fda04af 100644 (file)
@@ -106,6 +106,7 @@ static ERR_STRING_DATA DSA_str_reasons[]=
 {ERR_REASON(DSA_R_INVALID_DIGEST_TYPE)   ,"invalid digest type"},
 {ERR_REASON(DSA_R_MISSING_PARAMETERS)    ,"missing parameters"},
 {ERR_REASON(DSA_R_MODULUS_TOO_LARGE)     ,"modulus too large"},
+{ERR_REASON(DSA_R_NEED_NEW_SETUP_VALUES) ,"need new setup values"},
 {ERR_REASON(DSA_R_NO_PARAMETERS_SET)     ,"no parameters set"},
 {ERR_REASON(DSA_R_PARAMETER_ENCODING_ERROR),"parameter encoding error"},
 {0,NULL}
index 1fb665e..1b41690 100644 (file)
@@ -136,6 +136,7 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
        BN_CTX *ctx=NULL;
        int reason=ERR_R_BN_LIB;
        DSA_SIG *ret=NULL;
+       int noredo = 0;
 
        BN_init(&m);
        BN_init(&xr);
@@ -159,7 +160,7 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 
        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;
@@ -170,6 +171,7 @@ 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;
                }
 
        
@@ -190,6 +192,18 @@ static DSA_SIG *dsa_do_sign(const unsigned char *dgst, int dlen, DSA *dsa)
 
        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;