Commit 7c9291ce authored by Michael Müller's avatar Michael Müller Committed by Alexandre Julliard

bcrypt: Implement BCryptEncrypt for AES GCM mode.

parent d6f45dab
...@@ -63,6 +63,12 @@ MAKE_FUNCPTR(gnutls_global_set_log_level); ...@@ -63,6 +63,12 @@ MAKE_FUNCPTR(gnutls_global_set_log_level);
MAKE_FUNCPTR(gnutls_perror); MAKE_FUNCPTR(gnutls_perror);
#undef MAKE_FUNCPTR #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 ) static void gnutls_log( int level, const char *msg )
{ {
TRACE( "<%d> %s", level, msg ); TRACE( "<%d> %s", level, msg );
...@@ -848,6 +854,7 @@ struct key ...@@ -848,6 +854,7 @@ struct key
{ {
struct object hdr; struct object hdr;
enum alg_id alg_id; enum alg_id alg_id;
enum mode_id mode;
ULONG block_size; ULONG block_size;
gnutls_cipher_hd_t handle; gnutls_cipher_hd_t handle;
UCHAR *secret; UCHAR *secret;
...@@ -858,6 +865,7 @@ struct key ...@@ -858,6 +865,7 @@ struct key
{ {
struct object hdr; struct object hdr;
enum alg_id alg_id; enum alg_id alg_id;
enum mode_id mode;
ULONG block_size; ULONG block_size;
CCCryptorRef ref_encrypt; CCCryptorRef ref_encrypt;
CCCryptorRef ref_decrypt; CCCryptorRef ref_decrypt;
...@@ -868,6 +876,7 @@ struct key ...@@ -868,6 +876,7 @@ struct key
struct key struct key
{ {
struct object hdr; struct object hdr;
enum mode_id mode;
ULONG block_size; ULONG block_size;
}; };
#endif #endif
...@@ -923,6 +932,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s ...@@ -923,6 +932,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s
memcpy( buffer, secret, secret_len ); memcpy( buffer, secret, secret_len );
key->alg_id = alg->id; key->alg_id = alg->id;
key->mode = alg->mode;
key->handle = 0; /* initialized on first use */ key->handle = 0; /* initialized on first use */
key->secret = buffer; key->secret = buffer;
key->secret_len = secret_len; key->secret_len = secret_len;
...@@ -935,9 +945,13 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key ) ...@@ -935,9 +945,13 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key )
switch (key->alg_id) switch (key->alg_id)
{ {
case ALG_ID_AES: case ALG_ID_AES:
FIXME( "handle block size and chaining mode\n" ); WARN( "handle block size\n" );
return GNUTLS_CIPHER_AES_128_CBC; 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: default:
FIXME( "algorithm %u not supported\n", key->alg_id ); FIXME( "algorithm %u not supported\n", key->alg_id );
return GNUTLS_CIPHER_UNKNOWN; return GNUTLS_CIPHER_UNKNOWN;
...@@ -1019,6 +1033,14 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s ...@@ -1019,6 +1033,14 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s
switch (alg->id) switch (alg->id)
{ {
case ALG_ID_AES: 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; break;
default: default:
...@@ -1031,6 +1053,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s ...@@ -1031,6 +1053,7 @@ static NTSTATUS key_init( struct key *key, struct algorithm *alg, const UCHAR *s
memcpy( buffer, secret, secret_len ); memcpy( buffer, secret, secret_len );
key->alg_id = alg->id; key->alg_id = alg->id;
key->mode = alg->mode;
key->ref_encrypt = NULL; /* initialized on first use */ key->ref_encrypt = NULL; /* initialized on first use */
key->ref_decrypt = NULL; key->ref_decrypt = NULL;
key->secret = buffer; key->secret = buffer;
...@@ -1260,17 +1283,37 @@ NTSTATUS WINAPI BCryptEncrypt( BCRYPT_KEY_HANDLE handle, UCHAR *input, ULONG inp ...@@ -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 ); padding, iv, iv_len, output, output_len, ret_len, flags );
if (!key || key->hdr.magic != MAGIC_KEY) return STATUS_INVALID_HANDLE; 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) if (flags & ~BCRYPT_BLOCK_PADDING)
{ {
FIXME( "flags %08x not implemented\n", flags ); FIXME( "flags %08x not implemented\n", flags );
return STATUS_NOT_IMPLEMENTED; 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; if ((status = key_set_params( key, iv, iv_len ))) return status;
*ret_len = input_len; *ret_len = input_len;
......
...@@ -751,12 +751,12 @@ static void test_BCryptEncrypt(void) ...@@ -751,12 +751,12 @@ static void test_BCryptEncrypt(void)
memset(ciphertext, 0xff, sizeof(ciphertext)); memset(ciphertext, 0xff, sizeof(ciphertext));
memset(tag, 0xff, sizeof(tag)); memset(tag, 0xff, sizeof(tag));
ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 32, &size, 0); ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 32, &size, 0);
todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
todo_wine ok(size == 32, "got %u\n", size); ok(size == 32, "got %u\n", size);
todo_wine ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n"); ok(!memcmp(ciphertext, expected4, sizeof(expected4)), "wrong data\n");
todo_wine ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n"); todo_wine ok(!memcmp(tag, expected_tag, sizeof(expected_tag)), "wrong tag\n");
for (i = 0; i < 32; i++) 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++) for (i = 0; i < 16; i++)
todo_wine ok(tag[i] == expected_tag[i], "%u: %02x != %02x\n", i, tag[i], expected_tag[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) ...@@ -766,12 +766,12 @@ static void test_BCryptEncrypt(void)
memset(ciphertext, 0xff, sizeof(ciphertext)); memset(ciphertext, 0xff, sizeof(ciphertext));
memset(tag, 0xff, sizeof(tag)); memset(tag, 0xff, sizeof(tag));
ret = pBCryptEncrypt(key, data2, 24, &auth_info, ivbuf, 16, ciphertext, 24, &size, 0); ret = pBCryptEncrypt(key, data2, 24, &auth_info, ivbuf, 16, ciphertext, 24, &size, 0);
todo_wine ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
todo_wine ok(size == 24, "got %u\n", size); ok(size == 24, "got %u\n", size);
todo_wine ok(!memcmp(ciphertext, expected4, 24), "wrong data\n"); ok(!memcmp(ciphertext, expected4, 24), "wrong data\n");
todo_wine ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n"); todo_wine ok(!memcmp(tag, expected_tag2, sizeof(expected_tag2)), "wrong tag\n");
for (i = 0; i < 24; i++) 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++) for (i = 0; i < 16; i++)
todo_wine ok(tag[i] == expected_tag2[i], "%u: %02x != %02x\n", i, tag[i], expected_tag2[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) ...@@ -784,7 +784,7 @@ static void test_BCryptEncrypt(void)
memcpy(ivbuf, iv, sizeof(iv)); memcpy(ivbuf, iv, sizeof(iv));
memset(ciphertext, 0, sizeof(ciphertext)); memset(ciphertext, 0, sizeof(ciphertext));
ret = pBCryptEncrypt(key, data2, 32, &auth_info, ivbuf, 16, ciphertext, 48, &size, BCRYPT_BLOCK_PADDING); 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); ret = pBCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %08x\n", ret); ok(ret == STATUS_SUCCESS, "got %08x\n", ret);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment