[PATCH] bcrypt: Use internal helpers to generate hashes.

Hans Leidekker hans at codeweavers.com
Wed Oct 21 02:56:39 CDT 2020


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/bcrypt/bcrypt_main.c | 171 ++++++++++++++++++++------------------
 1 file changed, 90 insertions(+), 81 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 4eb1fc29e94..85d06f6001e 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -666,7 +666,7 @@ NTSTATUS WINAPI BCryptGetProperty( BCRYPT_HANDLE handle, LPCWSTR prop, UCHAR *bu
     }
 }
 
-static NTSTATUS prepare_hash( struct hash *hash )
+static NTSTATUS hash_prepare( struct hash *hash )
 {
     UCHAR buffer[MAX_HASH_BLOCK_BITS / 8] = {0};
     int block_bytes, i;
@@ -695,24 +695,12 @@ static NTSTATUS prepare_hash( struct hash *hash )
     return hash_update( &hash->inner, hash->alg_id, buffer, block_bytes );
 }
 
-NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
-                                  UCHAR *secret, ULONG secretlen, ULONG flags )
+static NTSTATUS hash_create( const struct algorithm *alg, UCHAR *secret, ULONG secret_len, ULONG flags,
+                             struct hash **ret_hash )
 {
-    struct algorithm *alg = algorithm;
     struct hash *hash;
     NTSTATUS status;
 
-    TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, objectlen,
-           secret, secretlen, flags );
-    if (flags & ~BCRYPT_HASH_REUSABLE_FLAG)
-    {
-        FIXME( "unimplemented flags %08x\n", flags );
-        return STATUS_NOT_IMPLEMENTED;
-    }
-
-    if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
-    if (object) FIXME( "ignoring object buffer\n" );
-
     if (!(hash = heap_alloc_zero( sizeof(*hash) ))) return STATUS_NO_MEMORY;
     hash->hdr.magic = MAGIC_HASH;
     hash->alg_id    = alg->id;
@@ -720,21 +708,44 @@ NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDL
     if ((alg->flags & BCRYPT_HASH_REUSABLE_FLAG) || (flags & BCRYPT_HASH_REUSABLE_FLAG))
         hash->flags |= HASH_FLAG_REUSABLE;
 
-    if (secretlen && !(hash->secret = heap_alloc( secretlen )))
+    if (secret_len && !(hash->secret = heap_alloc( secret_len )))
     {
         heap_free( hash );
         return STATUS_NO_MEMORY;
     }
-    memcpy( hash->secret, secret, secretlen );
-    hash->secret_len = secretlen;
+    memcpy( hash->secret, secret, secret_len );
+    hash->secret_len = secret_len;
 
-    if ((status = prepare_hash( hash )) != STATUS_SUCCESS)
+    if ((status = hash_prepare( hash )))
     {
         heap_free( hash->secret );
         heap_free( hash );
         return status;
     }
 
+    *ret_hash = hash;
+    return STATUS_SUCCESS;
+}
+
+NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object,
+                                  ULONG object_len, UCHAR *secret, ULONG secret_len, ULONG flags )
+{
+    struct algorithm *alg = algorithm;
+    struct hash *hash;
+    NTSTATUS status;
+
+    TRACE( "%p, %p, %p, %u, %p, %u, %08x - stub\n", algorithm, handle, object, object_len,
+           secret, secret_len, flags );
+    if (flags & ~BCRYPT_HASH_REUSABLE_FLAG)
+    {
+        FIXME( "unimplemented flags %08x\n", flags );
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
+    if (object) FIXME( "ignoring object buffer\n" );
+
+    if ((status = hash_create( alg, secret, secret_len, flags, &hash ))) return status;
     *handle = hash;
     return STATUS_SUCCESS;
 }
@@ -766,6 +777,14 @@ NTSTATUS WINAPI BCryptDuplicateHash( BCRYPT_HASH_HANDLE handle, BCRYPT_HASH_HAND
     return STATUS_SUCCESS;
 }
 
+static void hash_destroy( struct hash *hash )
+{
+    if (!hash) return;
+    hash->hdr.magic = 0;
+    heap_free( hash->secret );
+    heap_free( hash );
+}
+
 NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
 {
     struct hash *hash = handle;
@@ -773,9 +792,7 @@ NTSTATUS WINAPI BCryptDestroyHash( BCRYPT_HASH_HANDLE handle )
     TRACE( "%p\n", handle );
 
     if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_PARAMETER;
-    hash->hdr.magic = 0;
-    heap_free( hash->secret );
-    heap_free( hash );
+    hash_destroy( hash );
     return STATUS_SUCCESS;
 }
 
@@ -791,22 +808,16 @@ NTSTATUS WINAPI BCryptHashData( BCRYPT_HASH_HANDLE handle, UCHAR *input, ULONG s
     return hash_update( &hash->inner, hash->alg_id, input, size );
 }
 
-NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
+static NTSTATUS hash_finalize( struct hash *hash, UCHAR *output, ULONG size )
 {
     UCHAR buffer[MAX_HASH_OUTPUT_BYTES];
-    struct hash *hash = handle;
-    NTSTATUS status;
     int hash_length;
-
-    TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
-
-    if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
-    if (!output) return STATUS_INVALID_PARAMETER;
+    NTSTATUS status;
 
     if (!(hash->flags & HASH_FLAG_HMAC))
     {
         if ((status = hash_finish( &hash->inner, hash->alg_id, output, size ))) return status;
-        if (hash->flags & HASH_FLAG_REUSABLE) return prepare_hash( hash );
+        if (hash->flags & HASH_FLAG_REUSABLE) return hash_prepare( hash );
         return STATUS_SUCCESS;
     }
 
@@ -814,40 +825,43 @@ NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULON
     if ((status = hash_finish( &hash->inner, hash->alg_id, buffer, hash_length ))) return status;
     if ((status = hash_update( &hash->outer, hash->alg_id, buffer, hash_length ))) return status;
     if ((status = hash_finish( &hash->outer, hash->alg_id, output, size ))) return status;
-    if (hash->flags & HASH_FLAG_REUSABLE) return prepare_hash( hash );
+
+    if (hash->flags & HASH_FLAG_REUSABLE) return hash_prepare( hash );
     return STATUS_SUCCESS;
 }
 
-NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secretlen,
-                            UCHAR *input, ULONG inputlen, UCHAR *output, ULONG outputlen )
+NTSTATUS WINAPI BCryptFinishHash( BCRYPT_HASH_HANDLE handle, UCHAR *output, ULONG size, ULONG flags )
 {
-    NTSTATUS status;
-    BCRYPT_HASH_HANDLE handle;
+    struct hash *hash = handle;
 
-    TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secretlen,
-           input, inputlen, output, outputlen );
+    TRACE( "%p, %p, %u, %08x\n", handle, output, size, flags );
 
-    status = BCryptCreateHash( algorithm, &handle, NULL, 0, secret, secretlen, 0);
-    if (status != STATUS_SUCCESS)
-    {
-        return status;
-    }
+    if (!hash || hash->hdr.magic != MAGIC_HASH) return STATUS_INVALID_HANDLE;
+    if (!output) return STATUS_INVALID_PARAMETER;
 
-    status = BCryptHashData( handle, input, inputlen, 0 );
-    if (status != STATUS_SUCCESS)
-    {
-        BCryptDestroyHash( handle );
-        return status;
-    }
+    return hash_finalize( hash, output, size );
+}
+
+NTSTATUS WINAPI BCryptHash( BCRYPT_ALG_HANDLE algorithm, UCHAR *secret, ULONG secret_len,
+                            UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
+{
+    struct algorithm *alg = algorithm;
+    struct hash *hash;
+    NTSTATUS status;
+
+    TRACE( "%p, %p, %u, %p, %u, %p, %u\n", algorithm, secret, secret_len, input, input_len, output, output_len );
 
-    status = BCryptFinishHash( handle, output, outputlen, 0 );
-    if (status != STATUS_SUCCESS)
+    if (!alg || alg->hdr.magic != MAGIC_ALG) return STATUS_INVALID_HANDLE;
+
+    if ((status = hash_create( alg, secret, secret_len, 0, &hash ))) return status;
+    if ((status = hash_update( &hash->inner, hash->alg_id, input, input_len )))
     {
-        BCryptDestroyHash( handle );
+        hash_destroy( hash );
         return status;
     }
-
-    return BCryptDestroyHash( handle );
+    status = hash_finalize( hash, output, output_len );
+    hash_destroy( hash );
+    return status;
 }
 
 static NTSTATUS key_asymmetric_create( struct key **ret_key, struct algorithm *alg, ULONG bitlen,
@@ -1685,7 +1699,7 @@ NTSTATUS WINAPI BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle, BCRYPT_ALG_HANDL
     }
 
     len = builtin_algorithms[hash->alg_id].hash_length;
-    if ((status = BCryptFinishHash( handle, buf, len, 0 ))) return status;
+    if ((status = hash_finalize( hash, buf, len ))) return status;
 
     if (len < keylen)
     {
@@ -1698,20 +1712,20 @@ NTSTATUS WINAPI BCryptDeriveKeyCapi( BCRYPT_HASH_HANDLE handle, BCRYPT_ALG_HANDL
             pad2[i] = 0x5c ^ (i < len ? buf[i] : 0);
         }
 
-        if ((status = prepare_hash( hash )) ||
-            (status = BCryptHashData( handle, pad1, sizeof(pad1), 0 )) ||
-            (status = BCryptFinishHash( handle, buf, len, 0 ))) return status;
+        if ((status = hash_prepare( hash )) ||
+            (status = hash_update( &hash->inner, hash->alg_id, pad1, sizeof(pad1) )) ||
+            (status = hash_finalize( hash, buf, len ))) return status;
 
-        if ((status = prepare_hash( hash )) ||
-            (status = BCryptHashData( handle, pad2, sizeof(pad2), 0 )) ||
-            (status = BCryptFinishHash( handle, buf + len, len, 0 ))) return status;
+        if ((status = hash_prepare( hash )) ||
+            (status = hash_update( &hash->inner, hash->alg_id, pad2, sizeof(pad2) )) ||
+            (status = hash_finalize( hash, buf + len, len ))) return status;
     }
 
     memcpy( key, buf, keylen );
     return STATUS_SUCCESS;
 }
 
-static NTSTATUS pbkdf2( BCRYPT_HASH_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
+static NTSTATUS pbkdf2( struct hash *hash, UCHAR *pwd, ULONG pwd_len, UCHAR *salt, ULONG salt_len,
                         ULONGLONG iterations, ULONG i, UCHAR *dst, ULONG hash_len )
 {
     NTSTATUS status = STATUS_INVALID_PARAMETER;
@@ -1725,8 +1739,7 @@ static NTSTATUS pbkdf2( BCRYPT_HASH_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UC
         if (j == 0)
         {
             /* use salt || INT(i) */
-            status = BCryptHashData( handle, salt, salt_len, 0 );
-            if (status != STATUS_SUCCESS)
+            if ((status = hash_update( &hash->inner, hash->alg_id, salt, salt_len )))
             {
                 heap_free( buf );
                 return status;
@@ -1735,17 +1748,17 @@ static NTSTATUS pbkdf2( BCRYPT_HASH_HANDLE handle, UCHAR *pwd, ULONG pwd_len, UC
             bytes[1] = (i >> 16) & 0xff;
             bytes[2] = (i >> 8) & 0xff;
             bytes[3] = i & 0xff;
-            status = BCryptHashData( handle, bytes, 4, 0 );
+            status = hash_update( &hash->inner, hash->alg_id, bytes, 4 );
         }
-        else status = BCryptHashData( handle, buf, hash_len, 0 ); /* use U_j */
-        if (status != STATUS_SUCCESS)
+        else status = hash_update( &hash->inner, hash->alg_id, buf, hash_len ); /* use U_j */
+
+        if (status)
         {
             heap_free( buf );
             return status;
         }
 
-        status = BCryptFinishHash( handle, buf, hash_len, 0 );
-        if (status != STATUS_SUCCESS)
+        if ((status = hash_finalize( hash, buf, hash_len )))
         {
             heap_free( buf );
             return status;
@@ -1764,7 +1777,7 @@ NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULO
 {
     struct algorithm *alg = handle;
     ULONG hash_len, block_count, bytes_left, i;
-    BCRYPT_HASH_HANDLE hash;
+    struct hash *hash;
     UCHAR *partial;
     NTSTATUS status;
 
@@ -1779,17 +1792,14 @@ NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULO
     block_count = 1 + ((dk_len - 1) / hash_len); /* ceil(dk_len / hash_len) */
     bytes_left = dk_len - (block_count - 1) * hash_len;
 
-    status = BCryptCreateHash( handle, &hash, NULL, 0, pwd, pwd_len, BCRYPT_HASH_REUSABLE_FLAG );
-    if (status != STATUS_SUCCESS)
-        return status;
+    if ((status = hash_create( alg, pwd, pwd_len, BCRYPT_HASH_REUSABLE_FLAG, &hash ))) return status;
 
     /* full blocks */
     for (i = 1; i < block_count; i++)
     {
-        status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, i, dk + ((i - 1) * hash_len), hash_len );
-        if (status != STATUS_SUCCESS)
+        if ((status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, i, dk + ((i - 1) * hash_len), hash_len )))
         {
-            BCryptDestroyHash( hash );
+            hash_destroy( hash );
             return status;
         }
     }
@@ -1797,20 +1807,19 @@ NTSTATUS WINAPI BCryptDeriveKeyPBKDF2( BCRYPT_ALG_HANDLE handle, UCHAR *pwd, ULO
     /* final partial block */
     if (!(partial = heap_alloc( hash_len )))
     {
-        BCryptDestroyHash( hash );
+        hash_destroy( hash );
         return STATUS_NO_MEMORY;
     }
 
-    status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, block_count, partial, hash_len );
-    if (status != STATUS_SUCCESS)
+    if ((status = pbkdf2( hash, pwd, pwd_len, salt, salt_len, iterations, block_count, partial, hash_len )))
     {
-        BCryptDestroyHash( hash );
+        hash_destroy( hash );
         heap_free( partial );
         return status;
     }
     memcpy( dk + ((block_count - 1) * hash_len), partial, bytes_left );
 
-    BCryptDestroyHash( hash );
+    hash_destroy( hash );
     heap_free( partial );
     return STATUS_SUCCESS;
 }
-- 
2.28.0




More information about the wine-devel mailing list