[PATCH] bcrypt: Avoid recreating cipher handles when the initialization vector doesn't change.

Hans Leidekker hans at codeweavers.com
Wed Nov 6 03:16:54 CST 2019


Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
 dlls/bcrypt/bcrypt_internal.h |  9 ++++-
 dlls/bcrypt/bcrypt_main.c     | 28 ++++++++++----
 dlls/bcrypt/gnutls.c          | 62 ++++++++++++++++++++++++-------
 dlls/bcrypt/macos.c           | 57 ++++++++++++++++++++++-------
 dlls/bcrypt/tests/bcrypt.c    | 69 +++++++++++++++++++++++++++++++++++
 5 files changed, 189 insertions(+), 36 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_internal.h b/dlls/bcrypt/bcrypt_internal.h
index c6f5aebe1c..d026dab729 100644
--- a/dlls/bcrypt/bcrypt_internal.h
+++ b/dlls/bcrypt/bcrypt_internal.h
@@ -163,6 +163,8 @@ struct key_symmetric
     enum mode_id        mode;
     ULONG               block_size;
     gnutls_cipher_hd_t  handle;
+    UCHAR              *vector;
+    ULONG               vector_len;
     UCHAR              *secret;
     ULONG               secret_len;
 };
@@ -192,6 +194,8 @@ struct key_symmetric
     ULONG          block_size;
     CCCryptorRef   ref_encrypt;
     CCCryptorRef   ref_decrypt;
+    UCHAR         *vector;
+    ULONG          vector_len;
     UCHAR         *secret;
     ULONG          secret_len;
 };
@@ -234,7 +238,7 @@ NTSTATUS get_alg_property( const struct algorithm *, const WCHAR *, UCHAR *, ULO
 
 NTSTATUS key_set_property( struct key *, const WCHAR *, UCHAR *, ULONG, ULONG ) DECLSPEC_HIDDEN;
 NTSTATUS key_symmetric_init( struct key *, struct algorithm *, const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
-NTSTATUS key_symmetric_set_params( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
+NTSTATUS key_symmetric_set_vector( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
 NTSTATUS key_symmetric_set_auth_data( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
 NTSTATUS key_symmetric_encrypt( struct key *, const UCHAR *, ULONG, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
 NTSTATUS key_symmetric_decrypt( struct key *, const UCHAR *, ULONG, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
@@ -248,6 +252,9 @@ BOOL key_is_symmetric( struct key * ) DECLSPEC_HIDDEN;
 NTSTATUS key_export_ecc( struct key *, UCHAR *, ULONG, ULONG * ) DECLSPEC_HIDDEN;
 NTSTATUS key_import_ecc( struct key *, UCHAR *, ULONG ) DECLSPEC_HIDDEN;
 
+BOOL is_zero_vector( const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
+BOOL is_equal_vector( const UCHAR *, ULONG, const UCHAR *, ULONG ) DECLSPEC_HIDDEN;
+
 BOOL gnutls_initialize(void) DECLSPEC_HIDDEN;
 void gnutls_uninitialize(void) DECLSPEC_HIDDEN;
 
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index d87c9fc49f..079eaebe6e 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -834,6 +834,21 @@ BOOL key_is_symmetric( struct key *key )
     return builtin_algorithms[key->alg_id].class == BCRYPT_CIPHER_INTERFACE;
 }
 
+BOOL is_zero_vector( const UCHAR *vector, ULONG len )
+{
+    ULONG i;
+    if (!vector) return FALSE;
+    for (i = 0; i < len; i++) if (vector[i]) return FALSE;
+    return TRUE;
+}
+
+BOOL is_equal_vector( const UCHAR *vector, ULONG len, const UCHAR *vector2, ULONG len2 )
+{
+    if (!vector && !vector2) return TRUE;
+    if (len != len2) return FALSE;
+    return !memcmp( vector, vector2, len );
+}
+
 static NTSTATUS key_import( BCRYPT_ALG_HANDLE algorithm, const WCHAR *type, BCRYPT_KEY_HANDLE *key, UCHAR *object,
                             ULONG object_len, UCHAR *input, ULONG input_len )
 {
@@ -968,7 +983,7 @@ static NTSTATUS key_encrypt( struct key *key,  UCHAR *input, ULONG input_len, vo
         if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG)
             FIXME( "call chaining not implemented\n" );
 
-        if ((status = key_symmetric_set_params( key, auth_info->pbNonce, auth_info->cbNonce )))
+        if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce )))
             return status;
 
         *ret_len = input_len;
@@ -983,7 +998,6 @@ static NTSTATUS key_encrypt( struct key *key,  UCHAR *input, ULONG input_len, vo
         return key_symmetric_get_tag( key, auth_info->pbTag, auth_info->cbTag );
     }
 
-    if ((status = key_symmetric_set_params( key, iv, iv_len ))) return status;
     *ret_len = input_len;
 
     if (flags & BCRYPT_BLOCK_PADDING)
@@ -994,6 +1008,7 @@ static NTSTATUS key_encrypt( struct key *key,  UCHAR *input, ULONG input_len, vo
     if (!output) return STATUS_SUCCESS;
     if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
     if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
+    if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status;
 
     src = input;
     dst = output;
@@ -1001,7 +1016,7 @@ static NTSTATUS key_encrypt( struct key *key,  UCHAR *input, ULONG input_len, vo
     {
         if ((status = key_symmetric_encrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
             return status;
-        if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_params( key, NULL, 0 ))) return status;
+        if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status;
         bytes_left -= key->u.s.block_size;
         src += key->u.s.block_size;
         dst += key->u.s.block_size;
@@ -1036,7 +1051,7 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi
         if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
         if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
 
-        if ((status = key_symmetric_set_params( key, auth_info->pbNonce, auth_info->cbNonce )))
+        if ((status = key_symmetric_set_vector( key, auth_info->pbNonce, auth_info->cbNonce )))
             return status;
 
         *ret_len = input_len;
@@ -1054,8 +1069,6 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi
         return STATUS_SUCCESS;
     }
 
-    if ((status = key_symmetric_set_params( key, iv, iv_len ))) return status;
-
     *ret_len = input_len;
 
     if (input_len & (key->u.s.block_size - 1)) return STATUS_INVALID_BUFFER_SIZE;
@@ -1069,6 +1082,7 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi
     else if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
 
     if (key->u.s.mode == MODE_ID_ECB && iv) return STATUS_INVALID_PARAMETER;
+    if ((status = key_symmetric_set_vector( key, iv, iv_len ))) return status;
 
     src = input;
     dst = output;
@@ -1076,7 +1090,7 @@ static NTSTATUS key_decrypt( struct key *key, UCHAR *input, ULONG input_len, voi
     {
         if ((status = key_symmetric_decrypt( key, src, key->u.s.block_size, dst, key->u.s.block_size )))
             return status;
-        if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_params( key, NULL, 0 ))) return status;
+        if (key->u.s.mode == MODE_ID_ECB && (status = key_symmetric_set_vector( key, NULL, 0 ))) return status;
         bytes_left -= key->u.s.block_size;
         src += key->u.s.block_size;
         dst += key->u.s.block_size;
diff --git a/dlls/bcrypt/gnutls.c b/dlls/bcrypt/gnutls.c
index 41bba0b821..a6a07fff19 100644
--- a/dlls/bcrypt/gnutls.c
+++ b/dlls/bcrypt/gnutls.c
@@ -441,6 +441,8 @@ NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, const UCHAR
     key->alg_id         = alg->id;
     key->u.s.mode       = alg->mode;
     key->u.s.handle     = 0;        /* initialized on first use */
+    key->u.s.vector     = NULL;
+    key->u.s.vector_len = 0;
 
     return STATUS_SUCCESS;
 }
@@ -475,30 +477,45 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key )
     }
 }
 
-NTSTATUS key_symmetric_set_params( struct key *key, UCHAR *iv, ULONG iv_len )
+NTSTATUS key_symmetric_set_vector( struct key *key, UCHAR *vector, ULONG vector_len )
 {
-    gnutls_cipher_algorithm_t cipher;
-    gnutls_datum_t secret, vector;
-    int ret;
-
-    if (key->u.s.handle)
+    if (key->u.s.handle && (!is_zero_vector( vector, vector_len ) ||
+        !is_equal_vector( key->u.s.vector, key->u.s.vector_len, vector, vector_len )))
     {
+        TRACE( "invalidating cipher handle\n" );
         pgnutls_cipher_deinit( key->u.s.handle );
         key->u.s.handle = NULL;
     }
 
-    if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN)
-        return STATUS_NOT_SUPPORTED;
+    heap_free( key->u.s.vector );
+    key->u.s.vector = NULL;
+    key->u.s.vector_len = 0;
+    if (vector)
+    {
+        if (!(key->u.s.vector = heap_alloc( vector_len ))) return STATUS_NO_MEMORY;
+        memcpy( key->u.s.vector, vector, vector_len );
+        key->u.s.vector_len = vector_len;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS init_cipher_handle( struct key *key )
+{
+    gnutls_cipher_algorithm_t cipher;
+    gnutls_datum_t secret, vector;
+    int ret;
+
+    if (key->u.s.handle) return STATUS_SUCCESS;
+    if ((cipher = get_gnutls_cipher( key )) == GNUTLS_CIPHER_UNKNOWN) return STATUS_NOT_SUPPORTED;
 
     secret.data = key->u.s.secret;
     secret.size = key->u.s.secret_len;
-    if (iv)
-    {
-        vector.data = iv;
-        vector.size = iv_len;
-    }
 
-    if ((ret = pgnutls_cipher_init( &key->u.s.handle, cipher, &secret, iv ? &vector : NULL )))
+    vector.data = key->u.s.vector;
+    vector.size = key->u.s.vector_len;
+
+    if ((ret = pgnutls_cipher_init( &key->u.s.handle, cipher, &secret, key->u.s.vector ? &vector : NULL )))
     {
         pgnutls_perror( ret );
         return STATUS_INTERNAL_ERROR;
@@ -509,8 +526,12 @@ NTSTATUS key_symmetric_set_params( struct key *key, UCHAR *iv, ULONG iv_len )
 
 NTSTATUS key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG len )
 {
+    NTSTATUS status;
     int ret;
+
     if (!auth_data) return STATUS_SUCCESS;
+    if ((status = init_cipher_handle( key ))) return status;
+
     if ((ret = pgnutls_cipher_add_auth( key->u.s.handle, auth_data, len )))
     {
         pgnutls_perror( ret );
@@ -521,7 +542,11 @@ NTSTATUS key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG l
 
 NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
 {
+    NTSTATUS status;
     int ret;
+
+    if ((status = init_cipher_handle( key ))) return status;
+
     if ((ret = pgnutls_cipher_encrypt2( key->u.s.handle, input, input_len, output, output_len )))
     {
         pgnutls_perror( ret );
@@ -532,7 +557,11 @@ NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input
 
 NTSTATUS key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len  )
 {
+    NTSTATUS status;
     int ret;
+
+    if ((status = init_cipher_handle( key ))) return status;
+
     if ((ret = pgnutls_cipher_decrypt2( key->u.s.handle, input, input_len, output, output_len )))
     {
         pgnutls_perror( ret );
@@ -543,7 +572,11 @@ NTSTATUS key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input
 
 NTSTATUS key_symmetric_get_tag( struct key *key, UCHAR *tag, ULONG len )
 {
+    NTSTATUS status;
     int ret;
+
+    if ((status = init_cipher_handle( key ))) return status;
+
     if ((ret = pgnutls_cipher_tag( key->u.s.handle, tag, len )))
     {
         pgnutls_perror( ret );
@@ -1128,6 +1161,7 @@ NTSTATUS key_destroy( struct key *key )
     if (key_is_symmetric( key ))
     {
         if (key->u.s.handle) pgnutls_cipher_deinit( key->u.s.handle );
+        heap_free( key->u.s.vector );
         heap_free( key->u.s.secret );
     }
     else
diff --git a/dlls/bcrypt/macos.c b/dlls/bcrypt/macos.c
index fbd0321021..9ff9772c15 100644
--- a/dlls/bcrypt/macos.c
+++ b/dlls/bcrypt/macos.c
@@ -106,6 +106,8 @@ NTSTATUS key_symmetric_init( struct key *key, struct algorithm *alg, const UCHAR
     key->u.s.mode        = alg->mode;
     key->u.s.ref_encrypt = NULL;        /* initialized on first use */
     key->u.s.ref_decrypt = NULL;
+    key->u.s.vector      = NULL;
+    key->u.s.vector_len  = 0;
 
     return STATUS_SUCCESS;
 }
@@ -122,32 +124,50 @@ static CCMode get_cryptor_mode( struct key *key )
     }
 }
 
-NTSTATUS key_symmetric_set_params( struct key *key, UCHAR *iv, ULONG iv_len )
+NTSTATUS key_symmetric_set_vector( struct key *key, UCHAR *vector, ULONG vector_len )
 {
-    CCCryptorStatus status;
-    CCMode mode;
-
-    if (!(mode = get_cryptor_mode( key ))) return STATUS_NOT_SUPPORTED;
-
-    if (key->u.s.ref_encrypt)
+    if (key->u.s.ref_encrypt && (!is_zero_vector( vector, vector_len ) ||
+        !is_equal_vector( key->u.s.vector, key->u.s.vector_len, vector, vector_len )))
     {
+        TRACE( "invalidating cryptor handles\n" );
         CCCryptorRelease( key->u.s.ref_encrypt );
         key->u.s.ref_encrypt = NULL;
-    }
-    if (key->u.s.ref_decrypt)
-    {
+
         CCCryptorRelease( key->u.s.ref_decrypt );
         key->u.s.ref_decrypt = NULL;
     }
 
-    if ((status = CCCryptorCreateWithMode( kCCEncrypt, mode, kCCAlgorithmAES128, ccNoPadding, iv, key->u.s.secret,
-                                           key->u.s.secret_len, NULL, 0, 0, 0, &key->u.s.ref_encrypt )) != kCCSuccess)
+    heap_free( key->u.s.vector );
+    key->u.s.vector = NULL;
+    key->u.s.vector_len = 0;
+    if (vector)
+    {
+        if (!(key->u.s.vector = heap_alloc( vector_len ))) return STATUS_NO_MEMORY;
+        memcpy( key->u.s.vector, vector, vector_len );
+        key->u.s.vector_len = vector_len;
+    }
+
+    return STATUS_SUCCESS;
+}
+
+static NTSTATUS init_cryptor_handles( struct key *key )
+{
+    CCCryptorStatus status;
+    CCMode mode;
+
+    if (key->u.s.ref_encrypt) return STATUS_SUCCESS;
+    if (!(mode = get_cryptor_mode( key ))) return STATUS_NOT_SUPPORTED;
+
+    if ((status = CCCryptorCreateWithMode( kCCEncrypt, mode, kCCAlgorithmAES128, ccNoPadding, key->u.s.vector,
+                                           key->u.s.secret, key->u.s.secret_len, NULL, 0, 0, 0,
+                                           &key->u.s.ref_encrypt )) != kCCSuccess)
     {
         WARN( "CCCryptorCreateWithMode failed %d\n", status );
         return STATUS_INTERNAL_ERROR;
     }
-    if ((status = CCCryptorCreateWithMode( kCCDecrypt, mode, kCCAlgorithmAES128, ccNoPadding, iv, key->u.s.secret,
-                                           key->u.s.secret_len, NULL, 0, 0, 0, &key->u.s.ref_decrypt )) != kCCSuccess)
+    if ((status = CCCryptorCreateWithMode( kCCDecrypt, mode, kCCAlgorithmAES128, ccNoPadding, key->u.s.vector,
+                                           key->u.s.secret, key->u.s.secret_len, NULL, 0, 0, 0,
+                                           &key->u.s.ref_decrypt )) != kCCSuccess)
     {
         WARN( "CCCryptorCreateWithMode failed %d\n", status );
         CCCryptorRelease( key->u.s.ref_encrypt );
@@ -167,6 +187,10 @@ NTSTATUS key_symmetric_set_auth_data( struct key *key, UCHAR *auth_data, ULONG l
 NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len  )
 {
     CCCryptorStatus status;
+    NTSTATUS ret;
+
+    if ((ret = init_cryptor_handles( key ))) return ret;
+
     if ((status = CCCryptorUpdate( key->u.s.ref_encrypt, input, input_len, output, output_len, NULL  )) != kCCSuccess)
     {
         WARN( "CCCryptorUpdate failed %d\n", status );
@@ -178,6 +202,10 @@ NTSTATUS key_symmetric_encrypt( struct key *key, const UCHAR *input, ULONG input
 NTSTATUS key_symmetric_decrypt( struct key *key, const UCHAR *input, ULONG input_len, UCHAR *output, ULONG output_len )
 {
     CCCryptorStatus status;
+    NTSTATUS ret;
+
+    if ((ret = init_cryptor_handles( key ))) return ret;
+
     if ((status = CCCryptorUpdate( key->u.s.ref_decrypt, input, input_len, output, output_len, NULL  )) != kCCSuccess)
     {
         WARN( "CCCryptorUpdate failed %d\n", status );
@@ -235,6 +263,7 @@ NTSTATUS key_destroy( struct key *key )
 {
     if (key->u.s.ref_encrypt) CCCryptorRelease( key->u.s.ref_encrypt );
     if (key->u.s.ref_decrypt) CCCryptorRelease( key->u.s.ref_decrypt );
+    heap_free( key->u.s.vector );
     heap_free( key->u.s.secret );
     heap_free( key );
     return STATUS_SUCCESS;
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index 5ae847ca6e..d125e0c89d 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -2128,6 +2128,74 @@ static void test_BCryptEnumAlgorithms(void)
     pBCryptFreeBuffer( list );
 }
 
+static void test_aes_vector(void)
+{
+    static const UCHAR secret[] = {0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x10};
+    static const UCHAR expect[] = {0xb0,0xcb,0xf5,0x80,0xd4,0xe3,0x55,0x23,0x6e,0x19,0x5b,0xdb,0xfe,0xe0,0x6c,0xd3};
+    static const UCHAR expect2[] = {0x06,0x0c,0x81,0xab,0xd4,0x28,0x80,0x42,0xce,0x30,0x56,0x17,0x15,0x00,0x9e,0xc1};
+    static const UCHAR expect3[] = {0x3e,0x99,0xbf,0x02,0xf5,0xd3,0xb8,0x81,0x91,0x4d,0x93,0xea,0xd4,0x92,0x93,0x46};
+    static UCHAR iv[16], input[] = {'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p'};
+    UCHAR output[16];
+    BCRYPT_ALG_HANDLE alg;
+    BCRYPT_KEY_HANDLE key;
+    UCHAR data[sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + sizeof(secret)];
+    BCRYPT_KEY_DATA_BLOB_HEADER *blob = (BCRYPT_KEY_DATA_BLOB_HEADER *)data;
+    ULONG size;
+    NTSTATUS ret;
+
+    ret = pBCryptOpenAlgorithmProvider(&alg, BCRYPT_AES_ALGORITHM, NULL, 0);
+    ok(!ret, "got %08x\n", ret);
+
+    size = sizeof(BCRYPT_CHAIN_MODE_CBC);
+    ret = pBCryptSetProperty(alg, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_CBC, size, 0);
+    ok(!ret, "got %08x\n", ret);
+
+    blob->dwMagic   = BCRYPT_KEY_DATA_BLOB_MAGIC;
+    blob->dwVersion = BCRYPT_KEY_DATA_BLOB_VERSION1;
+    blob->cbKeyData = sizeof(secret);
+    memcpy(data + sizeof(*blob), secret, sizeof(secret));
+    size = sizeof(BCRYPT_KEY_DATA_BLOB_HEADER) + sizeof(secret);
+    ret = pBCryptImportKey(alg, NULL, BCRYPT_KEY_DATA_BLOB, &key, NULL, 0, data, size, 0);
+    ok(!ret || broken(ret == STATUS_INVALID_PARAMETER) /* vista */, "got %08x\n", ret);
+    if (ret == STATUS_INVALID_PARAMETER)
+    {
+        win_skip("broken BCryptImportKey\n");
+        pBCryptCloseAlgorithmProvider(alg, 0);
+        return;
+    }
+
+    /* zero initialization vector */
+    size = 0;
+    memset(output, 0, sizeof(output));
+    ret = pBCryptEncrypt(key, input, sizeof(input), NULL, iv, sizeof(iv), output, sizeof(output), &size, 0);
+    ok(!ret, "got %08x\n", ret);
+    ok(size == 16, "got %u\n", size);
+    ok(!memcmp(output, expect, sizeof(expect)), "wrong cipher text\n");
+
+    /* same initialization vector */
+    size = 0;
+    memset(output, 0, sizeof(output));
+    ret = pBCryptEncrypt(key, input, sizeof(input), NULL, iv, sizeof(iv), output, sizeof(output), &size, 0);
+    ok(!ret, "got %08x\n", ret);
+    ok(size == 16, "got %u\n", size);
+    ok(!memcmp(output, expect2, sizeof(expect2)), "wrong cipher text\n");
+
+    /* different initialization vector */
+    iv[0] = 0x1;
+    size = 0;
+    memset(output, 0, sizeof(output));
+    ret = pBCryptEncrypt(key, input, sizeof(input), NULL, iv, sizeof(iv), output, sizeof(output), &size, 0);
+    ok(!ret, "got %08x\n", ret);
+    ok(size == 16, "got %u\n", size);
+    todo_wine ok(!memcmp(output, expect3, sizeof(expect3)), "wrong cipher text\n");
+
+    ret = pBCryptDestroyKey(key);
+    ok(!ret, "got %08x\n", ret);
+
+    ret = pBCryptCloseAlgorithmProvider(alg, 0);
+    ok(!ret, "got %08x\n", ret);
+}
+
 START_TEST(bcrypt)
 {
     HMODULE module;
@@ -2186,6 +2254,7 @@ START_TEST(bcrypt)
     test_BCryptEnumContextFunctions();
     test_BCryptSignHash();
     test_BCryptEnumAlgorithms();
+    test_aes_vector();
 
     FreeLibrary(module);
 }
-- 
2.20.1




More information about the wine-devel mailing list