Hi,

I'm signing and verifying documents using DSA and have run into a couple of
problems.

I'm working with OpenSSL 0.9.7 on Linux with a Broadcom crypto card based on
the 5821 (so OpenSSL engine type is "ubsec").  I have version 1.81 of the
Broadcom driver.

(1) While testing I found that verification of certain signed documents crashed
OpenSSL.  The problem appears to be that hw_ubsec.c:ubsec_dsa_verify() calls
p_UBSEC_dsa_verify_ioctl() and if this call fails then the code tries using
software crypto, indirectly calling dsa_ossl.c:dsa_do_verify().  However,
dsa_do_verify() tries to do:

   if (!ENGINE_get_DSA(dsa->engine)->dsa_mod_exp(dsa, &t1,dsa->g,&u1,
                                                 dsa->pub_key,&u2,
                                                 dsa->p,ctx,mont))
      goto err;

and this dies because dsa_mod_exp is NULL.  The current workaround is to set up
pointers in ubsec_dsa for dsa_mod_exp and dsa_bn_mod_exp (just in case):

#ifndef OPENSSL_NO_DSA
static int dsa_mod_exp(DSA *dsa, BIGNUM *rr, BIGNUM *a1, BIGNUM *p1,
                BIGNUM *a2, BIGNUM *p2, BIGNUM *m, BN_CTX *ctx,
                BN_MONT_CTX *in_mont)
{
        return BN_mod_exp2_mont(rr, a1, p1, a2, p2, m, ctx, in_mont);
}

static int dsa_bn_mod_exp(DSA *dsa, BIGNUM *r, BIGNUM *a, const BIGNUM *p,
                                const BIGNUM *m, BN_CTX *ctx,
                                BN_MONT_CTX *m_ctx)
{
        return BN_mod_exp_mont(r, a, p, m, ctx, m_ctx);
}
/* Our internal DSA_METHOD that we provide pointers to */
static DSA_METHOD ubsec_dsa =
        {
        "UBSEC DSA method",
        ubsec_dsa_do_sign,  /* dsa_do_sign */
        NULL,               /* dsa_sign_setup */
        ubsec_dsa_verify,   /* dsa_do_verify */
        dsa_mod_exp,        /* ubsec_dsa_mod_exp */ /* dsa_mod_exp */
        dsa_bn_mod_exp,     /* ubsec_mod_exp_dsa */ /* bn_mod_exp */
        NULL,               /* init */
        NULL,               /* finish */
        0,                  /* flags */
        NULL                /* app_data */
        };
#endif

Not sure if this is entirely kosher, but I don't know why they were NULL to
begin with?

(2) The next question is why did the original call to
p_UBSEC_dsa_verify_ioctl() fail, since the Broadcom card is present and
functioning?  The answer is that one of the arguments passed in this ioctl call
is the length in bits of the hash (which is what was signed and we're trying to
verify).  If the hash happens to start with > 7 zero bits then when the bit
size is converted back to bytes the number of bytes will be < 20.  And deep in
the Broadcom driver this length will get rejected because the driver insists
the hash is 20 bytes long due to alignment issues.  (If you have access to the
Broadcom driver see ubsec_key.c:dsa_verify_ioctl() where the length is
converted from bits to bytes, and param.c:ubsec_keysetup_DSA() where the length
is checked against 20).  I think the solution here is to just always pass the
hash length as 160 bits and pad it with zeroes to make it the full 20 bytes
long.  I haven't tested this though.  Maybe there is an issue here in the way
the API is defined?

(3) Further testing showed that DSA signatures created using OpenSSL with the
Broadcom card appear to be broken in general somehow.  I've attached a tar file
containing a DSA private/public key pair, a small test file to sign, and a
script which does a bunch of DSA sign and verify tests.  What these tests show
is that a DSA signature generated using the Broadcom card will fail to verify
if the Broadcom card is not used during the verification.  The inverse, using a
card to verify a signature created without the card, works fine.  I don't know
whether the issue lies in the card, the driver, OpenSSL, or some combination.
(IBM's xss4j tool also cannot verify DSA signatures generated using OpenSSL
with the Broadcom card, though it can verify signatures generated without using
the Broadcom card.)

(4) To further complicate the last problem, in the tar file there is a file
"testfile-crash" which causes OpenSSL to segfault when used with the Broadcom
card for signing.  It looks like another case of a NULL pointer in the
ubsec_dsa function table, in this case for dsa_sign_setup.  I've tried making
dsa_sign_setup global and sticking it in the table and this seems to prevent
the crash, though I'm getting some error messages about memory leaks (it's a
debug build).  I don't understand the layers of function pointer tables being
used with the engine stuff so I'm not sure what the real way is to fix this, or
why it happens sometimes and not others.

Does anyone have experience with the Broadcom card and DSA and maybe can
confirm that I'm on the right track with my "fixes", and maybe shed some light
on the invalid DSA signatures?

I'm trying to get in touch with Broadcom as well to find out if they have a
later driver.  So far their response has been that they've tested with OpenSSL
and DSA and they work fine for them.

Thanks,

-- Jonathan

__________________________________________________
Do you Yahoo!?
Yahoo! Shopping - Send Flowers for Valentine's Day
http://shopping.yahoo.com

Attachment: dsa-ubsec-test.tar.gz
Description: dsa-ubsec-test.tar.gz

Reply via email to