[openssl-users] Possible bug in DSA_verify() since CVE-2014-8275 patch (present in 1.0.1k and 1.0.1l)

arnaud.mouiche at invoxia.com arnaud.mouiche at invoxia.com
Fri Jan 16 11:56:34 UTC 2015


Hi all.

I was just checking the latest 1.0.1l version (running previously the 
1.0.1i).
some DSA signature check done with DSA_verify() are not working any 
more, for at least one private/public key I'm using.

The public key was generated from the private key, long time ago, as 
usual with command "openssl dsa -in key.priv -out key.pub -pubout"
So, it is not a forged key.

Here is the various things I tried / see.
I someone can tell me if this is an openssl issue, or simply the way I'm 
using openssl lib, I will appreciate.

1) I imagine first that old generated keys are no more valid one to 
enforce the CVE-2014-8275 warning, yet,
generating a new public key with the new openssl version lead to the 
same issue.

2) I try the lastest openssl-1.0.1-stable-SNAP-20150116 sources, but the 
issue is still here

3) trying a public key in DER format (openssl dsa -in key.priv -out 
key.pub -pubout -outform DER), it doesn't change anything

4) if I revert  CVE-2014-8275 patch 
https://github.com/openssl/openssl/commit/684400ce192dac51df3d3e92b61830a6ef90be3e,
it fix my issue.

5) diging  in the source code

    diff --git a/crypto/dsa/dsa_asn1.c b/crypto/dsa/dsa_asn1.c
    index 473af87..a018d52 100644
    --- a/crypto/dsa/dsa_asn1.c
    +++ b/crypto/dsa/dsa_asn1.c
    @@ -184,17 +184,24 @@ int DSA_verify(int type, const unsigned char
    *dgst, int dgst_len,
             s = DSA_SIG_new();
             if (s == NULL) return(ret);
             if (d2i_DSA_SIG(&s,&p,siglen) == NULL) goto err;
             /* Ensure signature uses DER and doesn't have trailing
    garbage */
             derlen = i2d_DSA_SIG(s, &der);
    -       if (derlen != siglen || memcmp(sigbuf, der, derlen))
    +       if (derlen != siglen || memcmp(sigbuf, der, derlen)) {
    +           printf(" derlen=%d siglen=%d\n", derlen, siglen);
                     goto err;
    +       }
             ret=DSA_do_verify(dgst,dgst_len,s,dsa);
      err:



it shows: derlen=47 siglen=48. this is the reason why it failed.

5) here is the public key

-----BEGIN PUBLIC KEY-----
MIIBtjCCASsGByqGSM44BAEwggEeAoGBAKeSlIE9Q3ijwBOsB4ObfZW8cSsvIyDO
wioNBzZOEm8AoeOVc8xROEmWqvt7TBvM6OK46qNMJTLeHOiIXaRjqosQVWEb4D4l
IVjMtjpQFDAzxPsJZv6EaW/jM2ZXe6tVBanCJW/gi1NgnXpIkA5ohRqPJ+nqPR8p
OPbrBERrG1bzAhUAjDqhLrONrdvTe2HJJrB9V4An0BMCgYAF6vZzaZ4GEF8urI7b
ChkD0+aQZIAXBal/cBJMHI94HeYtBThT25+whfiWtEPbc99NhNAHnvGyIDVECAjZ
Rx1ZhV0Wn45UExCm7S7hHZY/I/jjoQRFvtMR0e4OqJXjIykx4r1SqXgZuO4M8Tv7
VzBLz6hhMqGZ7TqdqxqLH/cd9gOBhAACgYAlJlPWDNetO1TbO5OFfbl0rvTgIlZV
yWnRtIlks35f/iPkb2a7PsRUXcosvblX7Lg5oheC2m68MaEDx16XMvPmHWmvaR16
/BnX6DZHMtNDNMW6o7sce/AMhnT0PGiB1SCuugTxSt32RdDgRFcNBKUUCr47Nyor
dHdD2r/2/GQqpQ==
-----END PUBLIC KEY-----

6) ... and the way I'm using DSA_verify()

static enum dsa_verify_result dsa_verify_helper(const char *name, const 
unsigned char *digest, int digest_size, const unsigned char *signature, 
int signature_size) {
     DSA * dsa = NULL;
     char pubkey_path[128];
     FILE *F = NULL;

     /* try to read a PEM formatted key */
     snprintf(pubkey_path, sizeof(pubkey_path), "/share/pubkey/%s.pub", 
name );
     F = fopen( pubkey_path, "rb" );
     if (F) {
         if (PEM_read_DSA_PUBKEY( F, &dsa, PEM_def_callback, (void *)"" )) {
             dbg("  find a PEM pub key");
             goto dsa_verify_helper_get_a_key;
         }
         fclose( F );
         F = NULL;
     }

     /* try to read a DER formatted key */
     snprintf(pubkey_path, sizeof(pubkey_path), 
"/share/pubkey/%s.pub.der", name );
     F = fopen( pubkey_path, "rb" );
     if (F) {
         if (d2i_DSA_PUBKEY_fp( F, &dsa )) {
             dbg("  find a DER pub key");
             goto dsa_verify_helper_get_a_key;
         }
     }
     /* if we are here, we failed to read a pub key */
     if (F) fclose( F );
     return DSA_VERIFY_NO_PUBKEY;


dsa_verify_helper_get_a_key:
     fclose( F );

     int r = DSA_verify( 0, digest, digest_size, signature, 
signature_size, dsa );

     DSA_free( dsa );

     if (r == 1) {
         /* ok */
         return DSA_VERIFY_OK;
     } else {
         return DSA_VERIFY_BAD;
     }
}

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mta.openssl.org/pipermail/openssl-users/attachments/20150116/65abc5b5/attachment.html>


More information about the openssl-users mailing list