[PATCH 1/7] bcrypt: Introduce export_gnutls_datum() helper and use it in export_gnutls_pubkey_rsa().

Paul Gofman pgofman at codeweavers.com
Fri Jan 15 05:44:39 CST 2021


Signed-off-by: Paul Gofman <pgofman at codeweavers.com>
---
    Gnutls datum size might appear shorter than expected due to higher bits being zero
    in the random numbers. Gnutls export functions don't usually pad the data when exporting
    keys. bcrypt does not expect that currently. This is reproducible as random failures
    in some of the existing tests. Here is the testing patch which reliably reproduces
    this issue: https://gist.github.com/gofman/b15f91e2fb5246d13edcaf30eb6196f1.

 dlls/bcrypt/gnutls.c | 41 ++++++++++++++++++++++-------------------
 1 file changed, 22 insertions(+), 19 deletions(-)

diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index c065ac31fba..9e6dd4cc9a6 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -28,6 +28,7 @@
 #ifdef HAVE_GNUTLS_CIPHER_INIT
 
 #include <stdarg.h>
+#include <assert.h>
 #include <gnutls/gnutls.h>
 #include <gnutls/crypto.h>
 #include <gnutls/abstract.h>
@@ -665,11 +666,27 @@ static void CDECL key_symmetric_destroy( struct key *key )
     if (key_data(key)->cipher) pgnutls_cipher_deinit( key_data(key)->cipher );
 }
 
+static void export_gnutls_datum( UCHAR *buffer, ULONG length, gnutls_datum_t *d, ULONG *actual_length )
+{
+    ULONG size = d->size;
+    UCHAR *src = d->data;
+
+    assert( size <= length + 1 );
+    if (size == length + 1)
+    {
+        assert(!src[0]);
+        ++src;
+        --size;
+    }
+    *actual_length = size;
+    memcpy( buffer, src, size );
+}
+
 static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bitlen, UCHAR **pubkey, ULONG *pubkey_len )
 {
     BCRYPT_RSAKEY_BLOB *rsa_blob;
     gnutls_datum_t m, e;
-    UCHAR *dst, *src;
+    UCHAR *dst;
     int ret;
 
     if ((ret = pgnutls_privkey_export_rsa_raw( gnutls_key, &m, &e, NULL, NULL, NULL, NULL, NULL, NULL )))
@@ -686,32 +703,18 @@ static NTSTATUS export_gnutls_pubkey_rsa( gnutls_privkey_t gnutls_key, ULONG bit
     }
 
     dst = (UCHAR *)(rsa_blob + 1);
-    if (e.size == bitlen / 8 + 1 && !e.data[0])
-    {
-        src = e.data + 1;
-        e.size--;
-    }
-    else src = e.data;
-    memcpy( dst, src, e.size );
+    export_gnutls_datum( dst, bitlen / 8, &e, &rsa_blob->cbPublicExp );
 
-    dst += e.size;
-    if (m.size == bitlen / 8 + 1 && !m.data[0])
-    {
-        src = m.data + 1;
-        m.size--;
-    }
-    else src = m.data;
-    memcpy( dst, src, m.size );
+    dst += rsa_blob->cbPublicExp;
+    export_gnutls_datum( dst, bitlen / 8, &m, &rsa_blob->cbModulus );
 
     rsa_blob->Magic       = BCRYPT_RSAPUBLIC_MAGIC;
     rsa_blob->BitLength   = bitlen;
-    rsa_blob->cbPublicExp = e.size;
-    rsa_blob->cbModulus   = m.size;
     rsa_blob->cbPrime1    = 0;
     rsa_blob->cbPrime2    = 0;
 
     *pubkey = (UCHAR *)rsa_blob;
-    *pubkey_len = sizeof(*rsa_blob) + e.size + m.size;
+    *pubkey_len = sizeof(*rsa_blob) + rsa_blob->cbPublicExp + rsa_blob->cbModulus;
 
     free( e.data ); free( m.data );
     return STATUS_SUCCESS;
-- 
2.29.2




More information about the wine-devel mailing list