[v3 PATCH 3/5] bcrypt: Add support for computing/comparing cipher tag.

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Tue Mar 20 15:27:09 CDT 2018


From: Michael Müller <michael at fds-team.de>

Signed-off-by: Alistair Leslie-Hughes <leslie_alistair at hotmail.com>
---
 dlls/bcrypt/bcrypt_main.c  | 47 +++++++++++++++++++++++++++++++++++++++++++++-
 dlls/bcrypt/tests/bcrypt.c | 10 +++++-----
 2 files changed, 51 insertions(+), 6 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 573cd374a4..a08eb00269 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -50,6 +50,9 @@ static HINSTANCE instance;
 #if defined(HAVE_GNUTLS_CIPHER_INIT) && !defined(HAVE_COMMONCRYPTO_COMMONCRYPTOR_H)
 WINE_DECLARE_DEBUG_CHANNEL(winediag);
 
+/* Not present in gnutls version < 3.0 */
+static int (*pgnutls_cipher_tag)(gnutls_cipher_hd_t handle, void * tag, size_t tag_size);
+
 static void *libgnutls_handle;
 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
 MAKE_FUNCPTR(gnutls_cipher_decrypt2);
@@ -69,6 +72,11 @@ MAKE_FUNCPTR(gnutls_perror);
 #define GNUTLS_CIPHER_AES_256_GCM 94
 #endif
 
+static int compat_gnutls_cipher_tag(gnutls_cipher_hd_t handle, void * tag, size_t tag_size)
+{
+    return GNUTLS_E_UNKNOWN_CIPHER_TYPE;
+}
+
 static void gnutls_log( int level, const char *msg )
 {
     TRACE( "<%d> %s", level, msg );
@@ -102,6 +110,12 @@ static BOOL gnutls_initialize(void)
     LOAD_FUNCPTR(gnutls_perror)
 #undef LOAD_FUNCPTR
 
+    if (!(pgnutls_cipher_tag = wine_dlsym( libgnutls_handle, "gnutls_cipher_tag", NULL, 0 )))
+    {
+        WARN("gnutls_cipher_tag not found\n");
+        pgnutls_cipher_tag = compat_gnutls_cipher_tag;
+    }
+
     if ((ret = pgnutls_global_init()) != GNUTLS_E_SUCCESS)
     {
         pgnutls_perror( ret );
@@ -1018,6 +1032,19 @@ static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_le
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len )
+{
+    int ret;
+
+    if ((ret = pgnutls_cipher_tag( key->handle, tag, len )))
+    {
+        pgnutls_perror( ret );
+        return STATUS_INTERNAL_ERROR;
+    }
+
+    return STATUS_SUCCESS;
+}
+
 static NTSTATUS key_destroy( struct key *key )
 {
     if (key->handle) pgnutls_cipher_deinit( key->handle );
@@ -1123,6 +1150,12 @@ static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_le
     return STATUS_SUCCESS;
 }
 
+static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len )
+{
+    FIXME( "not implemented on Mac\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 static NTSTATUS key_destroy( struct key *key )
 {
     if (key->ref_encrypt) CCCryptorRelease( key->ref_encrypt );
@@ -1158,6 +1191,12 @@ static NTSTATUS key_decrypt( struct key *key, const UCHAR *input, ULONG input_le
     return STATUS_NOT_IMPLEMENTED;
 }
 
+static NTSTATUS key_get_tag( struct key *key, UCHAR *tag, ULONG len )
+{
+    ERR( "support for keys not available at build time\n" );
+    return STATUS_NOT_IMPLEMENTED;
+}
+
 static NTSTATUS key_destroy( struct key *key )
 {
     ERR( "support for keys not available at build time\n" );
@@ -1311,7 +1350,7 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
         if ((status = key_encrypt( key, input, input_len, output, output_len )))
             return status;
 
-        return STATUS_SUCCESS;
+        return key_get_tag( key, auth_info->pbTag, auth_info->cbTag );
     }
 
     if ((status = key_set_params( key, iv, iv_len ))) return status;
@@ -1370,6 +1409,7 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
     if (key->mode == MODE_ID_GCM)
     {
         BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
+        UCHAR tag[16];
 
         if (!auth_info) return STATUS_INVALID_PARAMETER;
         if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
@@ -1387,6 +1427,11 @@ NTSTATUS WINAPI BCryptDecrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
         if ((status = key_decrypt( key, input, input_len, output, output_len )))
             return status;
 
+        if ((status = key_get_tag( key, tag, sizeof(tag) )))
+            return status;
+        if (memcmp( tag, auth_info->pbTag, auth_info->cbTag ))
+            return STATUS_AUTH_TAG_MISMATCH;
+
         return STATUS_SUCCESS;
     }
 
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index e3cbc87db4..1176796dbc 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -754,11 +754,11 @@ static void test_BCryptEncrypt(void)
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
     ok(size == 32, "got %u\n", size);
     ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n");
-    todo_wine ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n");
+    ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n");
     for (i = 0; i < 32; i++)
         ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]);
     for (i = 0; i < 16; i++)
-        todo_wine ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[i]);
+        ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[i]);
 
     /* input size is not multiple of block size */
     size = 0;
@@ -769,11 +769,11 @@ static void test_BCryptEncrypt(void)
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
     ok(size == 24, "got %u\n", size);
     ok(!memcmp(ciphertext, expected4, 24), "wrong data\n");
-    todo_wine ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n");
+    ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n");
     for (i = 0; i < 24; i++)
         ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[i]);
     for (i = 0; i < 16; i++)
-        todo_wine ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]);
+        ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[i]);
 
     /* test with padding */
     memcpy(ivbuf, iv, sizeof(iv));
@@ -977,7 +977,7 @@ static void test_BCryptDecrypt(void)
     memcpy(ivbuf, iv, sizeof(iv));
     auth_info.pbTag = iv; /* wrong tag */
     ret = pBCryptDecrypt(key, ciphertext4, 32, &auth_info, ivbuf, 16, plaintext, 32, &size, 0);
-    todo_wine ok(ret == STATUS_AUTH_TAG_MISMATCH, "got %08x\n", ret);
+    ok(ret == STATUS_AUTH_TAG_MISMATCH, "got %08x\n", ret);
     ok(size == 32, "got %u\n", size);
 
     ret = pBCryptDestroyKey(key);
-- 
2.16.2



More information about the wine-devel mailing list