[gnutls-dev] Buggy RSA/DSA signature verification
Simon Josefsson
simon at josefsson.org
Wed Dec 27 21:31:07 CET 2006
ludovic.courtes at laas.fr (Ludovic Courtès) writes:
> Hi,
>
> There seems to be a bug in `_gnutls_pkcs1_rsa_verify_sig ()': Basically,
> when verifying a DSA signature, it wrongfully assumes that the SHA1 hash
> is located at `&hash_concat->data[16]'. In some cases, as visible in
> `_gnutls_verify_sig_params ()', the SHA1 hash is actually located
> `&hash_concat->data[15]' instead, because the PKCS#1 algorithm
> identifier for SHA1 is 15-octet-long, not 16. In those cases,
> `_gnutls_pkcs1_rsa_verify_sig ()' fails to verify the signature and
> performs an off-by-one memory access.
Ah, right. An important condition for this to happen is that TLS 1.2
is used, though.
> I don't know what the best way to fix `_gnutls_pkcs1_rsa_verify_sig ()'
> is. Perhaps it could decode the header of HASH_CONCAT in order to
> determine the exact location of the hash value. Alternatively, since
> the function is only used internally, we could change callers so that
> they provide it directly with the hash value in the `GNUTLS_PK_DSA'
> case.
>
> I'd be glad to help fix this based on your comments if you don't have
> time to do it.
I think we should change both the function parameters and the name of
the function -- it is quite confusing for the function to be called
_gnutls_pkcs1_rsa_verify_sig when it is actually responsible for
verifying both RSA and DSA signatures. I have installed the patch
below.
When we support more than SHA-1, this will have to be revisited again,
but at least this will solve the immediate problem.
Thanks,
Simon
--- gnutls_sig.c 26 Nov 2006 12:10:10 +0100 2.54
+++ gnutls_sig.c 27 Dec 2006 21:28:44 +0100
@@ -259,9 +259,10 @@
static int
-_gnutls_pkcs1_rsa_verify_sig (gnutls_cert * cert,
+_gnutls_verify_sig (gnutls_cert * cert,
const gnutls_datum_t * hash_concat,
- gnutls_datum_t * signature)
+ gnutls_datum_t * signature,
+ size_t sha1pos)
{
int ret;
gnutls_datum_t vdata;
@@ -302,7 +303,7 @@
break;
case GNUTLS_PK_DSA:
- vdata.data = &hash_concat->data[16];
+ vdata.data = &hash_concat->data[sha1pos];
vdata.size = 20; /* sha1 */
/* verify signature */
@@ -380,7 +381,7 @@
dconcat.data = concat;
dconcat.size = 20 + 16; /* md5+ sha */
- ret = _gnutls_pkcs1_rsa_verify_sig (cert, &dconcat, signature);
+ ret = _gnutls_verify_sig (cert, &dconcat, signature, 16);
if (ret < 0)
{
gnutls_assert ();
@@ -461,7 +462,7 @@
dconcat.data = concat;
- ret = _gnutls_pkcs1_rsa_verify_sig (cert, &dconcat, signature);
+ ret = _gnutls_verify_sig (cert, &dconcat, signature, dconcat.size - 20);
if (ret < 0)
{
gnutls_assert ();
More information about the Gnutls-dev
mailing list