Commit d3638d42 authored by Hans Leidekker's avatar Hans Leidekker Committed by Alexandre Julliard

bcrypt: Add AES CFB chaining mode support.

parent 3df43384
......@@ -147,7 +147,8 @@ enum mode_id
{
MODE_ID_ECB,
MODE_ID_CBC,
MODE_ID_GCM
MODE_ID_GCM,
MODE_ID_CFB,
};
struct algorithm
......
......@@ -531,6 +531,7 @@ static NTSTATUS get_aes_property( enum mode_id mode, const WCHAR *prop, UCHAR *b
case MODE_ID_ECB: str = BCRYPT_CHAIN_MODE_ECB; break;
case MODE_ID_CBC: str = BCRYPT_CHAIN_MODE_CBC; break;
case MODE_ID_GCM: str = BCRYPT_CHAIN_MODE_GCM; break;
case MODE_ID_CFB: str = BCRYPT_CHAIN_MODE_CFB; break;
default: return STATUS_NOT_IMPLEMENTED;
}
......@@ -662,6 +663,11 @@ static NTSTATUS set_alg_property( struct algorithm *alg, const WCHAR *prop, UCHA
alg->mode = MODE_ID_GCM;
return STATUS_SUCCESS;
}
else if (!wcscmp( (WCHAR *)value, BCRYPT_CHAIN_MODE_CFB ))
{
alg->mode = MODE_ID_CFB;
return STATUS_SUCCESS;
}
else
{
FIXME( "unsupported mode %s\n", debugstr_w((WCHAR *)value) );
......
......@@ -506,6 +506,11 @@ static gnutls_cipher_algorithm_t get_gnutls_cipher( const struct key *key )
if (key->u.s.secret_len == 24) return GNUTLS_CIPHER_AES_192_CBC;
if (key->u.s.secret_len == 32) return GNUTLS_CIPHER_AES_256_CBC;
break;
case MODE_ID_CFB:
if (key->u.s.secret_len == 16) return GNUTLS_CIPHER_AES_128_CFB8;
if (key->u.s.secret_len == 24) return GNUTLS_CIPHER_AES_192_CFB8;
if (key->u.s.secret_len == 32) return GNUTLS_CIPHER_AES_256_CFB8;
break;
default:
break;
}
......
......@@ -578,8 +578,7 @@ static void test_aes(void)
ok(key_lengths.dwMaxLength == 256, "Expected 256, got %lu\n", key_lengths.dwMaxLength);
ok(key_lengths.dwIncrement == 64, "Expected 64, got %lu\n", key_lengths.dwIncrement);
memcpy(mode, BCRYPT_CHAIN_MODE_GCM, sizeof(BCRYPT_CHAIN_MODE_GCM));
ret = BCryptSetProperty(alg, BCRYPT_CHAINING_MODE, mode, 0, 0);
ret = BCryptSetProperty(alg, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_GCM, 0, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
size = 0;
......@@ -589,6 +588,16 @@ static void test_aes(void)
ok(!lstrcmpW((const WCHAR *)mode, BCRYPT_CHAIN_MODE_GCM), "got %s\n", wine_dbgstr_w((const WCHAR *)mode));
ok(size == 64, "got %lu\n", size);
ret = BCryptSetProperty(alg, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_CFB, 0, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
size = 0;
memset(mode, 0, sizeof(mode));
ret = BCryptGetProperty(alg, BCRYPT_CHAINING_MODE, mode, sizeof(mode), &size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(!lstrcmpW((const WCHAR *)mode, BCRYPT_CHAIN_MODE_CFB), "got %s\n", wine_dbgstr_w((const WCHAR *)mode));
ok(size == 64, "got %lu\n", size);
test_alg_name(alg, L"AES");
ret = BCryptCloseAlgorithmProvider(alg, 0);
......@@ -942,6 +951,23 @@ static void test_BCryptEncrypt(void)
{0x66,0xb8,0xbd,0xe5,0x90,0x6c,0xec,0xdf,0xfa,0x8a,0xb2,0xfd,0x92,0x84,0xeb,0xf0,
0x95,0xc4,0xdf,0xa7,0x7a,0x62,0xe4,0xab,0xd4,0x0e,0x94,0x4e,0xd7,0x6e,0xa1,0x47,
0x29,0x4b,0x37,0xfe,0x28,0x6d,0x5f,0x69,0x46,0x30,0x73,0xc0,0xaa,0x42,0xe4,0x46};
static UCHAR expected11[] =
{0x0a,0x22,0xf7,0x96,0xe1,0xb9,0x3e,0x90,0x32,0xcf,0xf8,0x04,0x83,0x8a,0xdf,0xc3};
static UCHAR expected12[] =
{0xb5,0x9d,0xe7,0x8e,0x0f,0x80,0x16,0xc3,0xf6,0x80,0xad,0xf8,0xac,0xef,0xf9,0x9f};
static UCHAR expected13[] =
{0xc6,0x41,0x37,0xd8,0x6f,0x65,0x64,0x1d,0x2b,0xa0,0xad,0xee,0x67,0xba,0x9b,0x5f};
static UCHAR expected14[] =
{0x0a,0x22,0xf7,0x96,0xe1,0xb9,0x3e,0x90,0x32,0xcf,0xf8,0x04,0x83,0x8a,0xdf,0xc3,
0xa5,0xfa,0x54,0xd7,0x62,0x9d,0x8b,0x11,0x3d,0xd8,0xe2,0x95,0xc2,0x23,0x3f,0x29};
static UCHAR expected15[] =
{0x0a,0x22,0xf7,0x96,0xe1,0xb9,0x3e,0x90,0x32,0xcf,0xf8,0x04,0x83,0x8a,0xdf,0xc3,
0xa5,0xe5,0xcd,0x29,0x48,0x37,0x3f,0x92,0x6f,0x09,0x84,0x5a,0xb8,0x88,0xda,0xfd,
0x65,0x00,0x20,0x9a,0xc6,0xdb,0xfa,0x82,0xdb,0xbc,0xf4,0x70,0x7d,0x88,0x86,0xb5};
static UCHAR expected16[] =
{0x64,0xff,0xc6,0x97,0x14,0x5e,0x21,0xfa,0xe8,0x6e,0xba,0xc1,0x0c,0xb1,0x72,0x64,
0x5d,0xf0,0x22,0x72,0xef,0x39,0xe3,0x2f,0x80,0x3e,0x53,0x00,0xc1,0xcf,0x3f,0xbb,
0xea,0x30,0x01,0x78,0x3b,0xba,0x4d,0xca,0xa0,0x2e,0x83,0x5e,0x0e,0xe2,0x65,0xcb};
static UCHAR expected_tag[] =
{0x89,0xb3,0x92,0x00,0x39,0x20,0x09,0xb4,0x6a,0xd6,0xaf,0xca,0x4b,0x5b,0xfd,0xd0};
static UCHAR expected_tag2[] =
......@@ -1378,6 +1404,144 @@ static void test_BCryptEncrypt(void)
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
HeapFree(GetProcessHeap(), 0, buf);
/******************
* AES - CFB mode *
******************/
ret = BCryptSetProperty(aes, BCRYPT_CHAINING_MODE, (UCHAR *)BCRYPT_CHAIN_MODE_CFB, sizeof(BCRYPT_CHAIN_MODE_CFB), 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
key = NULL;
buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
ret = BCryptGenerateSymmetricKey(aes, &key, buf, len, secret, sizeof(secret), 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(key != NULL, "key not set\n");
/* input size is a multiple of block size */
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
ret = BCryptEncrypt(key, data, 16, NULL, ivbuf, 16, NULL, 0, &size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 16, "got %lu\n", size);
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
memset(ciphertext, 0, sizeof(ciphertext));
ret = BCryptEncrypt(key, data, 16, NULL, ivbuf, 16, ciphertext, 16, &size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 16, "got %lu\n", size);
ok(!memcmp(ciphertext, expected11, sizeof(expected11)), "wrong data\n");
for (i = 0; i < 16; i++)
ok(ciphertext[i] == expected11[i], "%lu: %02x != %02x\n", i, ciphertext[i], expected11[i]);
/* NULL initialization vector */
size = 0;
memset(ciphertext, 0, sizeof(ciphertext));
ret = BCryptEncrypt(key, data, 16, NULL, NULL, 0, ciphertext, 16, &size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 16, "got %lu\n", size);
todo_wine ok(!memcmp(ciphertext, expected12, sizeof(expected12)), "wrong data\n");
/* all zero initialization vector */
size = 0;
memset(ciphertext, 0, sizeof(ciphertext));
memset(ivbuf, 0, sizeof(ivbuf));
ret = BCryptEncrypt(key, data, 16, NULL, ivbuf, 16, ciphertext, 16, &size, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 16, "got %lu\n", size);
ok(!memcmp(ciphertext, expected13, sizeof(expected13)), "wrong data\n");
for (i = 0; i < 16; i++)
ok(ciphertext[i] == expected13[i], "%lu: %02x != %02x\n", i, ciphertext[i], expected13[i]);
/* input size is not a multiple of block size */
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
ret = BCryptEncrypt(key, data, 17, NULL, ivbuf, 16, NULL, 0, &size, 0);
todo_wine ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 17, "got %lu\n", size);
/* input size is not a multiple of block size, block padding set */
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
ret = BCryptEncrypt(key, data, 17, NULL, ivbuf, 16, NULL, 0, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 32, "got %lu\n", size);
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
memset(ciphertext, 0, sizeof(ciphertext));
ret = BCryptEncrypt(key, data, 17, NULL, ivbuf, 16, ciphertext, 32, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 32, "got %lu\n", size);
ok(!memcmp(ciphertext, expected14, sizeof(expected14)), "wrong data\n");
for (i = 0; i < 32; i++)
ok(ciphertext[i] == expected14[i], "%lu: %02x != %02x\n", i, ciphertext[i], expected14[i]);
/* input size is a multiple of block size, block padding set */
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
ret = BCryptEncrypt(key, data2, 32, NULL, ivbuf, 16, NULL, 0, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 48, "got %lu\n", size);
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
memset(ciphertext, 0, sizeof(ciphertext));
ret = BCryptEncrypt(key, data2, 32, NULL, ivbuf, 16, ciphertext, 48, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 48, "got %lu\n", size);
ok(!memcmp(ciphertext, expected15, sizeof(expected15)), "wrong data\n");
for (i = 0; i < 48; i++)
ok(ciphertext[i] == expected15[i], "%lu: %02x != %02x\n", i, ciphertext[i], expected15[i]);
/* output size too small */
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
memset(ciphertext, 0, sizeof(ciphertext));
ret = BCryptEncrypt(key, data, 17, NULL, ivbuf, 16, ciphertext, 31, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_BUFFER_TOO_SMALL, "got %#lx\n", ret);
ok(size == 32, "got %lu\n", size);
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
memset(ciphertext, 0, sizeof(ciphertext));
ret = BCryptEncrypt(key, data2, 32, NULL, ivbuf, 16, ciphertext, 32, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_BUFFER_TOO_SMALL, "got %#lx\n", ret);
ok(size == 48, "got %lu\n", size);
ret = BCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
HeapFree(GetProcessHeap(), 0, buf);
/* 256 bit key */
buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
ret = BCryptGenerateSymmetricKey(aes, &key, buf, len, secret256, sizeof(secret256), 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ret = BCryptDestroyKey(key);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
/* Key generations succeeds if the key size exceeds maximum and uses maximum key length
* from secret. */
ret = BCryptGenerateSymmetricKey(aes, &key, buf, len, secret256, sizeof(secret256) + 1, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
ret = BCryptEncrypt(key, data2, 32, NULL, ivbuf, 16, NULL, 0, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 48, "got %lu\n", size);
size = 0;
memcpy(ivbuf, iv, sizeof(iv));
memset(ciphertext, 0, sizeof(ciphertext));
ret = BCryptEncrypt(key, data2, 32, NULL, ivbuf, 16, ciphertext, 48, &size, BCRYPT_BLOCK_PADDING);
ok(ret == STATUS_SUCCESS, "got %#lx\n", ret);
ok(size == 48, "got %lu\n", size);
ok(!memcmp(ciphertext, expected16, sizeof(expected16)), "wrong data\n");
for (i = 0; i < 48; i++)
ok(ciphertext[i] == expected16[i], "%lu: %02x != %02x\n", i, ciphertext[i], expected16[i]);
ret = BCryptCloseAlgorithmProvider(aes, 0);
ok(ret == STATUS_SUCCESS, "got %#lx\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