[PATCH 6/7] bcrypt: Implement AES encryption
Bruno Jesus
00cpxxx at gmail.com
Tue Dec 6 19:06:20 CST 2016
From: Hans Leidekker <hans at codeweavers.com>
Signed-off-by: Bruno Jesus <00cpxxx at gmail.com>
---
dlls/bcrypt/bcrypt_main.c | 126 ++++++++++++++++++++++++++++++++++++++++++++-
dlls/bcrypt/tests/bcrypt.c | 6 +--
2 files changed, 126 insertions(+), 6 deletions(-)
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 21df85d..8649b79 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -52,6 +52,7 @@ static void *libgnutls_handle;
MAKE_FUNCPTR(gnutls_cipher_init);
MAKE_FUNCPTR(gnutls_cipher_deinit);
MAKE_FUNCPTR(gnutls_global_deinit);
+MAKE_FUNCPTR(gnutls_cipher_encrypt2);
MAKE_FUNCPTR(gnutls_global_init);
MAKE_FUNCPTR(gnutls_global_set_log_function);
MAKE_FUNCPTR(gnutls_global_set_log_level);
@@ -89,6 +90,7 @@ static BOOL gnutls_initialize(void)
LOAD_FUNCPTR(gnutls_cipher_init);
LOAD_FUNCPTR(gnutls_cipher_deinit);
LOAD_FUNCPTR(gnutls_global_deinit)
+ LOAD_FUNCPTR(gnutls_cipher_encrypt2);
LOAD_FUNCPTR(gnutls_global_init)
LOAD_FUNCPTR(gnutls_global_set_log_function)
LOAD_FUNCPTR(gnutls_global_set_log_level)
@@ -595,6 +597,66 @@ static NTSTATUS key_destroy( struct key *key )
HeapFree( GetProcessHeap(), 0, key );
return STATUS_SUCCESS;
}
+
+static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key )
+{
+ switch (key->alg_id)
+ {
+ case ALG_ID_AES:
+ FIXME( "handle block size and chaining mode\n" );
+ return GNUTLS_CIPHER_AES_128_CBC;
+
+ default:
+ FIXME( "algorithm %u not supported\n", key->alg_id );
+ return GNUTLS_CIPHER_UNKNOWN;
+ }
+}
+
+static NTSTATUS key_set_params( struct key *key, UCHAR *iv, ULONG iv_len )
+{
+ gnutls_cipher_algorithm_t cipher;
+ gnutls_datum_t secret, vector;
+ int ret;
+
+ if (key->handle)
+ {
+ pgnutls_cipher_deinit( key->handle );
+ key->handle = NULL;
+ }
+
+ if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN)
+ return STATUS_NOT_SUPPORTED;
+
+ secret.data = key->secret;
+ secret.size = key->secret_len;
+ if (iv)
+ {
+ vector.data = iv;
+ vector.size = iv_len;
+ }
+
+ if ((ret = pgnutls_cipher_init( &key->handle, cipher, &secret, iv ? &vector : NULL )))
+ {
+ pgnutls_perror( ret );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
+
+static NTSTATUS key_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output,
+ ULONG output_len )
+{
+ int ret;
+
+ if ((ret = pgnutls_cipher_encrypt2( key->handle, input, input_len, output, output_len )))
+ {
+ pgnutls_perror( ret );
+ return STATUS_INTERNAL_ERROR;
+ }
+
+ return STATUS_SUCCESS;
+}
#else
struct hash
{
@@ -655,6 +717,19 @@ static NTSTATUS key_destroy( struct key *key )
ERR( "support for keys not available at build time\n" );
return STATUS_NOT_IMPLEMENTED;
}
+
+static NTSTATUS key_set_params( struct key *key, UCHAR *iv, ULONG iv_len )
+{
+ ERR( "support for keys not available at build time\n" );
+ return STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS key_encrypt( 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 */
@@ -851,9 +926,56 @@ NTSTATUS WINAPI BCryptEncrypt( 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 BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG input_len,
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 723b58e..4d25523 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -862,7 +862,6 @@ static void test_BCryptGenerateSymmetricKey(void)
sizeof(BCRYPT_CHAIN_MODE_CBC), 0);
todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
-todo_wine {
size = 0xdeadbeef;
ret = pBCryptEncrypt(key, NULL, 0, NULL, NULL, 0, NULL, 0, &size, 0);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
@@ -883,7 +882,7 @@ todo_wine {
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);
@@ -943,7 +942,6 @@ static void test_BCryptEncrypt(void)
ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
/* input size is a multiple of block size */
-todo_wine {
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
ret = pBCryptEncrypt(key, data, 16, NULL, ivbuf, 16, NULL, 0, &size, 0);
@@ -991,7 +989,7 @@ todo_wine {
ret = pBCryptEncrypt(key, data, 17, NULL, ivbuf, 16, ciphertext, 31, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_BUFFER_TOO_SMALL, "got %08x\n", ret);
ok(size == 32, "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