[PATCH 7/7] bcrypt: Mostly implement AES decryption

Bruno Jesus 00cpxxx at gmail.com
Fri Dec 2 16:28:37 CST 2016


Some cases have still problems but in general it works

From: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Bruno Jesus <00cpxxx at gmail.com>
---
 dlls/bcrypt/bcrypt_main.c  | 74 ++++++++++++++++++++++++++++++++++++++++++++--
 dlls/bcrypt/tests/bcrypt.c | 11 ++++---
 2 files changed, 79 insertions(+), 6 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 8649b79..8f79d1e 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -53,6 +53,7 @@ MAKE_FUNCPTR(gnutls_cipher_init);
 MAKE_FUNCPTR(gnutls_cipher_deinit);
 MAKE_FUNCPTR(gnutls_global_deinit);
 MAKE_FUNCPTR(gnutls_cipher_encrypt2);
+MAKE_FUNCPTR(gnutls_cipher_decrypt2);
 MAKE_FUNCPTR(gnutls_global_init);
 MAKE_FUNCPTR(gnutls_global_set_log_function);
 MAKE_FUNCPTR(gnutls_global_set_log_level);
@@ -91,6 +92,7 @@ static BOOL gnutls_initialize(void)
     LOAD_FUNCPTR(gnutls_cipher_deinit);
     LOAD_FUNCPTR(gnutls_global_deinit)
     LOAD_FUNCPTR(gnutls_cipher_encrypt2);
+    LOAD_FUNCPTR(gnutls_cipher_decrypt2);
     LOAD_FUNCPTR(gnutls_global_init)
     LOAD_FUNCPTR(gnutls_global_set_log_function)
     LOAD_FUNCPTR(gnutls_global_set_log_level)
@@ -657,6 +659,20 @@ static NTSTATUS key_encrypt( struct key *key, const UCHAR *input, ULONG input_le
 
     return STATUS_SUCCESS;
 }
+
+static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output,
+                             ULONG output_len  )
+{
+    int ret;
+
+    if ((ret = pgnutls_cipher_decrypt2( key->handle, input, input_len, output, output_len )))
+    {
+        pgnutls_perror( ret );
+        return STATUS_INTERNAL_ERROR;
+    }
+
+    return STATUS_SUCCESS;
+}
 #else
 struct hash
 {
@@ -730,6 +746,13 @@ static NTSTATUS key_encrypt( struct key *key, const UCHAR *input, ULONG input_le
     ERR( "support for keys not available at build time\n" );
     return STATUS_NOT_IMPLEMENTED;
 }
+
+static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output,
+                             ULONG output_len )
+{
+    ERR( "support for keys not available at build time\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
 #endif
 
 #define OBJECT_LENGTH_AES       618 /* FIXME: This is the 32 bits value */
@@ -982,9 +1005,56 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
                                void *padding, UCHAR *iv, ULONG iv_len, UCHAR *output,
                                ULONG output_len, ULONG *ret_len, ULONG flags )
 {
-    FIXME( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len,
+    struct key *key = handle;
+    ULONG bytes_left = input_len;
+    UCHAR *buf, *src, *dst;
+    NTSTATUS status;
+
+    TRACE( "%p, %p, %u, %p, %p, %u, %p, %u, %p, %08x\n", handle, input, input_len,
            padding, iv, iv_len, output, output_len, ret_len, flags );
-    return STATUS_NOT_IMPLEMENTED;
+
+    if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE;
+    if (padding)
+    {
+        FIXME( "padding info not implemented\n" );
+        return STATUS_NOT_IMPLEMENTED;
+    }
+    if (flags & ~BCRYPT_BLOCK_PADDING)
+    {
+        FIXME( "flags %08x not implemented\n", flags );
+        return STATUS_NOT_IMPLEMENTED;
+    }
+
+    if ((status = key_set_params( key, iv, iv_len ))) return status;
+
+    *ret_len = input_len;
+    if (input_len & (key->block_size - 1))
+    {
+        if (!(flags & BCRYPT_BLOCK_PADDING)) return STATUS_INVALID_BUFFER_SIZE;
+        *ret_len = (input_len + key->block_size - 1) & ~(key->block_size - 1);
+    }
+    if (!output) return STATUS_SUCCESS;
+    if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
+
+    src = input;
+    dst = output;
+    while (bytes_left >= key->block_size)
+    {
+        if ((status = key_encrypt( key, src, key->block_size, dst, key->block_size ))) return status;
+        bytes_left -= key->block_size;
+        src += key->block_size;
+        dst += key->block_size;
+    }
+    if (bytes_left)
+    {
+        if (!(buf = HeapAlloc( GetProcessHeap(), 0, key->block_size ))) return STATUS_NO_MEMORY;
+        memcpy( buf, src, bytes_left );
+        memset( buf + bytes_left, key->block_size - bytes_left, key->block_size - bytes_left );
+        status = key_encrypt( key, buf, key->block_size, dst, key->block_size );
+        HeapFree( GetProcessHeap(), 0, buf );
+    }
+
+    return status;
 }
 
 NTSTATUS WINAPI BCryptCreateHash( BCRYPT_ALG_HANDLE algorithm, BCRYPT_HASH_HANDLE *handle, UCHAR *object, ULONG objectlen,
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 4d25523..37cc54d 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -882,7 +882,7 @@ static void test_BCryptGenerateSymmetricKey(void)
     ok(!memcmp(ciphertext, expected, sizeof(expected)), "wrong data\n");
     for (i = 0; i < 16; i++)
         ok(ciphertext[i] == expected[i], "%u: %02x != %02x\n", i, ciphertext[i], expected[i]);
-todo_wine {
+
     size = 0xdeadbeef;
     ret = pBCryptDecrypt(key, NULL, 0, NULL, NULL, 0, NULL, 0, &size, 0);
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
@@ -900,8 +900,9 @@ todo_wine {
     ret = pBCryptDecrypt(key, ciphertext, 16, NULL, ivbuf, 16, plaintext, 16, &size, 0);
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
     ok(size == 16, "got %u\n", size);
+todo_wine
     ok(!memcmp(plaintext, data, sizeof(data)), "wrong data\n");
-}
+
     ret = pBCryptDestroyKey(key);
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
     HeapFree(GetProcessHeap(), 0, buf);
@@ -1027,7 +1028,6 @@ static void test_BCryptDecrypt(void)
     ret = pBCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret), 0);
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
 
-todo_wine {
     /* input size is a multiple of block size */
     size = 0;
     memcpy(ivbuf, iv, sizeof(iv));
@@ -1041,6 +1041,7 @@ todo_wine {
     ret = pBCryptDecrypt(key, ciphertext, 32, NULL, ivbuf, 16, plaintext, 32, &size, 0);
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
     ok(size == 32, "got %u\n", size);
+todo_wine
     ok(!memcmp(plaintext, expected, sizeof(expected)), "wrong data\n");
 
     /* output size too small */
@@ -1061,9 +1062,11 @@ todo_wine {
     size = 0;
     memcpy(ivbuf, iv, sizeof(iv));
     ret = pBCryptDecrypt(key, ciphertext, 17, NULL, ivbuf, 16, NULL, 0, &size, BCRYPT_BLOCK_PADDING);
+todo_wine
     ok(ret == STATUS_INVALID_BUFFER_SIZE, "got %08x\n", ret);
+todo_wine
     ok(size == 17 || broken(size == 0 /* Win < 7 */), "got %u\n", size);
-}
+
     ret = pBCryptDestroyKey(key);
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
     HeapFree(GetProcessHeap(), 0, buf);
-- 
2.9.3




More information about the wine-patches mailing list