Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 2 additions & 3 deletions src/chacha20poly1305.c
Original file line number Diff line number Diff line change
Expand Up @@ -328,10 +328,9 @@ int poly1305_tagcmp_scalar(const uint8_t tag1[16], const uint8_t tag2[16])
static
int chacha20_counter_wraps(uint32_t counter, size_t n)
{
/* The data call starts at counter+1 and uses ceil(n/64) blocks */
uint64_t start = (uint32_t)(counter + 1);
/* A call starting at block counter 'counter' uses ceil(n/64) blocks */
uint64_t blocks = ((uint64_t)n + 63) / 64;
return (start + blocks) > ((uint64_t)1 << 32);
return ((uint64_t)counter + blocks) > ((uint64_t)1 << 32);
}

/*
Expand Down
2 changes: 1 addition & 1 deletion src/cipher_chacha20.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ EncryptPageChaCha20Cipher(void* cipher, int page, unsigned char* data, int len,
chacha20_rng(data + n, PAGE_NONCE_LEN_CHACHA20);
counter = LOAD32_LE(data + n + PAGE_NONCE_LEN_CHACHA20 - 4) ^ (uint32_t)page;
}
while (chacha20_counter_wraps(counter, n - offset));
while (chacha20_counter_wraps(counter + 1, n - offset));
chacha20_xor(otk, OTK_LEN_CHACHA20, chacha20Cipher->m_key, data + n, counter);

chacha20_xor(data + offset, n - offset, otk + 32, data + n, counter + 1);
Expand Down
2 changes: 1 addition & 1 deletion src/sqlite3mc_vle.c
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ vle_aeadEncrypt(const VleContext* ctx,
chacha20_rng(nonce, nonceLen);
counter = vle_readU32BE(nonce + nonceLen - 4) ^ (uint32_t) VLE_MAGIC_NUM;
}
while (chacha20_counter_wraps(counter, ctextLen));
while (chacha20_counter_wraps(counter + 1, ctextLen));
/* otk is all zero, so this yields pure keystream under the subkey */
chacha20_xor(otk, VLE_OTK_LEN, subkey, nonce, counter);

Expand Down
33 changes: 32 additions & 1 deletion test/cryptotest.c
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,10 @@ static void testAesCbc(void)
/*
** ChaCha20 and Poly1305: every implementation has to reproduce the RFC 8439
** test vectors and give the same result as the first implementation in its
** list (the reference) for pseudo-random input.
** list (the reference) for pseudo-random input. In addition, chacha20_xor has
** to wrap the 32-bit block counter like sqleet when it overflows within a call,
** because a page may be read with a different implementation than the one
** that wrote it.
*/

typedef void (*ChaCha20Function)(unsigned char* output, const unsigned char* input, size_t length,
Expand Down Expand Up @@ -482,6 +485,10 @@ static const Poly1305Implementation poly1305List[] =
static void testChaCha20(void)
{
static const uint32_t counters[] = { 0, 1, 0x12345, 0xfffff000u };
#ifdef HAVE_SELECTABLE_IMPLEMENTATIONS
static const size_t overflowLengths[] = { 1024, 2048, 4064, 8000 };
const int defaultIndex = ARRAY_COUNT(chacha20List) - 1;
#endif
const ChaCha20Implementation* reference = &chacha20List[0];
int failures[ARRAY_COUNT(chacha20List)] = { 0 };
int checks[ARRAY_COUNT(chacha20List)] = { 0 };
Expand Down Expand Up @@ -531,6 +538,30 @@ static void testChaCha20(void)
}
}

#ifdef HAVE_SELECTABLE_IMPLEMENTATIONS
/* Counter overflow within the call: every start counter from just below the overflow up to 2^32-1 */
for (i = 0; i < ARRAY_COUNT(overflowLengths); i++)
{
size_t length = overflowLengths[i];
uint64_t blocks = (length + 63) / 64;
uint64_t start;
pseudoRandomBytes(testKey, sizeof(testKey));
pseudoRandomBytes(testNonce, sizeof(testNonce));
pseudoRandomBytes(inputBuffer, length);
for (start = 0x100000000ull - blocks - 1; start <= 0xffffffffull; start++)
{
chacha20Sqleet(expectedBuffer, inputBuffer, length, testKey, testNonce, (uint32_t) start);
snprintf(description, sizeof(description), "counter overflow, length %d, counter 0x%08x",
(int) length, (unsigned int) start);
memset(outputBuffer, 0, length);
chacha20Default(outputBuffer, inputBuffer, length, testKey, testNonce, (uint32_t) start);
failures[defaultIndex] += checkResult(memcmp(outputBuffer, expectedBuffer, length) == 0,
chacha20List[defaultIndex].name, description);
checks[defaultIndex]++;
}
}
#endif

for (j = 0; j < ARRAY_COUNT(chacha20List); j++)
{
if (cpuSupports(chacha20List[j].requiredCpuFeatures))
Expand Down
Loading