[v3 PATCH 1/5] bcrypt: Implement BCryptEncrypt for AES GCM mode.

Alistair Leslie-Hughes leslie_alistair at hotmail.com
Tue Mar 20 15:27:06 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  | 59 +++++++++++++++++++++++++++++++++++++++-------
 dlls/bcrypt/tests/bcrypt.c | 18 +++++++-------
 2 files changed, 60 insertions(+), 17 deletions(-)

diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index fa80318f28..96695532b5 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -63,6 +63,12 @@ MAKE_FUNCPTR(gnutls_global_set_log_level);
 MAKE_FUNCPTR(gnutls_perror);
 #undef MAKE_FUNCPTR
 
+#if GNUTLS_VERSION_MAJOR < 3
+#define GNUTLS_CIPHER_AES_192_CBC 92
+#define GNUTLS_CIPHER_AES_128_GCM 93
+#define GNUTLS_CIPHER_AES_256_GCM 94
+#endif
+
 static void gnutls_log( int level, const char *msg )
 {
     TRACE( "<%d> %s", level, msg );
@@ -848,6 +854,7 @@ struct key
 {
     struct object      hdr;
     enum alg_id        alg_id;
+    enum mode_id       mode;
     ULONG              block_size;
     gnutls_cipher_hd_t handle;
     UCHAR             *secret;
@@ -858,6 +865,7 @@ struct key
 {
     struct object  hdr;
     enum alg_id    alg_id;
+    enum mode_id   mode;
     ULONG          block_size;
     CCCryptorRef   ref_encrypt;
     CCCryptorRef   ref_decrypt;
@@ -868,6 +876,7 @@ struct key
 struct key
 {
     struct object hdr;
+    enum mode_id  mode;
     ULONG         block_size;
 };
 #endif
@@ -923,6 +932,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s
     memcpy( buffer, secret, secret_len );
 
     key->alg_id     = alg->id;
+    key->mode       = alg->mode;
     key->handle     = 0;        /* initialized on first use */
     key->secret     = buffer;
     key->secret_len = secret_len;
@@ -935,9 +945,13 @@ 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;
-
+        WARN( "handle block size\n" );
+        switch (key->mode)
+        {
+            case MODE_ID_GCM: return GNUTLS_CIPHER_AES_128_GCM;
+            case MODE_ID_CBC:
+            default:          return GNUTLS_CIPHER_AES_128_CBC;
+        }
     default:
         FIXME( "algorithm %u not supported\n", key->alg_id );
         return GNUTLS_CIPHER_UNKNOWN;
@@ -1019,6 +1033,14 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s
     switch (alg->id)
     {
     case ALG_ID_AES:
+        switch (alg->mode)
+        {
+            case MODE_ID_CBC:
+                break;
+            default:
+                FIXME( "mode %u not supported\n", alg->mode );
+                return STATUS_NOT_SUPPORTED;
+        }
         break;
 
     default:
@@ -1031,6 +1053,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s
     memcpy( buffer, secret, secret_len );
 
     key->alg_id      = alg->id;
+    key->mode        = alg->mode;
     key->ref_encrypt = NULL;        /* initialized on first use */
     key->ref_decrypt = NULL;
     key->secret      = buffer;
@@ -1260,17 +1283,37 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp
            padding, iv, iv_len, output, output_len, ret_len, flags );
 
     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 (key->mode == MODE_ID_GCM)
+    {
+        BCRYPT_AUTHENTICATED_CIPHER_MODE_INFO *auth_info = padding;
+
+        if (!auth_info) return STATUS_INVALID_PARAMETER;
+        if (!auth_info->pbNonce) return STATUS_INVALID_PARAMETER;
+        if (!auth_info->pbTag) return STATUS_INVALID_PARAMETER;
+        if (auth_info->cbTag < 12 || auth_info->cbTag > 16) return STATUS_INVALID_PARAMETER;
+        if (auth_info->dwFlags & BCRYPT_AUTH_MODE_CHAIN_CALLS_FLAG)
+            FIXME( "call chaining not implemented\n" );
+
+        if ((status = key_set_params( key, auth_info->pbNonce, auth_info->cbNonce )))
+            return status;
+
+        *ret_len = input_len;
+        if (flags & BCRYPT_BLOCK_PADDING) return STATUS_INVALID_PARAMETER;
+        if (!output) return STATUS_SUCCESS;
+        if (output_len < *ret_len) return STATUS_BUFFER_TOO_SMALL;
+
+        if ((status = key_encrypt( key, input, input_len, output, output_len )))
+            return status;
+
+        return STATUS_SUCCESS;
+    }
+
     if ((status = key_set_params( key, iv, iv_len ))) return status;
 
     *ret_len = input_len;
diff --git a/dlls/bcrypt/tests/bcrypt.c b/dlls/bcrypt/tests/bcrypt.c
index ba2011f5df..1875fb3f89 100644
--- a/dlls/bcrypt/tests/bcrypt.c
+++ b/dlls/bcrypt/tests/bcrypt.c
@@ -751,12 +751,12 @@ static void test_BCryptEncrypt(void)
     memset(ciphertext, 0xff, sizeof(ciphertext));
     memset(tag, 0xff, sizeof(tag));
     ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 32, &size, 0);
-    todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
-    todo_wine ok(size == 32, "got %u\n", size);
-    todo_wine ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n");
+    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");
     for (i = 0; i < 32; i++)
-        todo_wine ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[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]);
 
@@ -766,12 +766,12 @@ static void test_BCryptEncrypt(void)
     memset(ciphertext, 0xff, sizeof(ciphertext));
     memset(tag, 0xff, sizeof(tag));
     ret = pBCryptEncrypt(key, data2, 24, &auth_info, ivbuf, 16, ciphertext, 24, &size, 0);
-    todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
-    todo_wine ok(size == 24, "got %u\n", size);
-    todo_wine ok(!memcmp(ciphertext, expected4, 24), "wrong data\n");
+    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");
     for (i = 0; i < 24; i++)
-        todo_wine ok(ciphertext[i] == expected4[i], "%u: %02x != %02x\n", i, ciphertext[i], expected4[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]);
 
@@ -784,7 +784,7 @@ static void test_BCryptEncrypt(void)
     memcpy(ivbuf, iv, sizeof(iv));
     memset(ciphertext, 0, sizeof(ciphertext));
     ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 48, &size, BCRYPT_BLOCK_PADDING);
-    todo_wine ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
+    ok(ret == STATUS_INVALID_PARAMETER, "got %08x\n", ret);
 
     ret = pBCryptDestroyKey(key);
     ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
-- 
2.16.2



More information about the wine-devel mailing list