From: Loup Vaillant Date: Sat, 30 Nov 2019 23:08:08 +0000 (+0100) Subject: chacha20_*_ctr functions now return the new ctr X-Git-Url: https://git.codecow.com/?a=commitdiff_plain;h=c1ce546cef3c86112f76fd6e0759916203d691b9;p=Monocypher.git chacha20_*_ctr functions now return the new ctr This should facilitate building piecemeal streams. Normally you'd just increment the nonce, but in some (admittedly rare) cases we may want to increment the counter instead. Incrementing the counter is fairly dangerous, because we may overlap the streams, thus revealing the XOR of two pieces of plain text. Using the new return value makes sure this doesn't happen. --- diff --git a/src/monocypher.c b/src/monocypher.c index d1bbadb..2e70c61 100644 --- a/src/monocypher.c +++ b/src/monocypher.c @@ -136,8 +136,8 @@ static void chacha20_init_key(u32 block[16], const u8 key[32]) } } -static void chacha20_core(u32 input[16], u8 *cipher_text, const u8 *plain_text, - size_t text_size) +static u64 chacha20_core(u32 input[16], u8 *cipher_text, const u8 *plain_text, + size_t text_size) { // Whole blocks u32 pool[16]; @@ -181,6 +181,7 @@ static void chacha20_core(u32 input[16], u8 *cipher_text, const u8 *plain_text, WIPE_BUFFER(tmp); } WIPE_BUFFER(pool); + return input[12] + ((u64)input[13] << 32) + (text_size > 0); } void crypto_hchacha20(u8 out[32], const u8 key[32], const u8 in [16]) @@ -200,9 +201,9 @@ void crypto_hchacha20(u8 out[32], const u8 key[32], const u8 in [16]) WIPE_BUFFER(block); } -void crypto_chacha20_ctr(u8 *cipher_text, const u8 *plain_text, - size_t text_size, const u8 key[32], const u8 nonce[8], - u64 ctr) +u64 crypto_chacha20_ctr(u8 *cipher_text, const u8 *plain_text, + size_t text_size, const u8 key[32], const u8 nonce[8], + u64 ctr) { u32 input[16]; chacha20_init_key(input, key); @@ -210,13 +211,14 @@ void crypto_chacha20_ctr(u8 *cipher_text, const u8 *plain_text, input[13] = (u32)(ctr >> 32); input[14] = load32_le(nonce); input[15] = load32_le(nonce + 4); - chacha20_core(input, cipher_text, plain_text, text_size); + ctr = chacha20_core(input, cipher_text, plain_text, text_size); WIPE_BUFFER(input); + return ctr; } -void crypto_ietf_chacha20_ctr(u8 *cipher_text, const u8 *plain_text, - size_t text_size, - const u8 key[32], const u8 nonce[12], u32 ctr) +u32 crypto_ietf_chacha20_ctr(u8 *cipher_text, const u8 *plain_text, + size_t text_size, + const u8 key[32], const u8 nonce[12], u32 ctr) { u32 input[16]; chacha20_init_key(input, key); @@ -224,19 +226,21 @@ void crypto_ietf_chacha20_ctr(u8 *cipher_text, const u8 *plain_text, input[13] = load32_le(nonce); input[14] = load32_le(nonce + 4); input[15] = load32_le(nonce + 8); - chacha20_core(input, cipher_text, plain_text, text_size); + ctr = chacha20_core(input, cipher_text, plain_text, text_size); WIPE_BUFFER(input); + return ctr; } -void crypto_xchacha20_ctr(u8 *cipher_text, const u8 *plain_text, - size_t text_size, - const u8 key[32], const u8 nonce[24], u64 ctr) +u64 crypto_xchacha20_ctr(u8 *cipher_text, const u8 *plain_text, + size_t text_size, + const u8 key[32], const u8 nonce[24], u64 ctr) { u8 sub_key[32]; crypto_hchacha20(sub_key, key, nonce); - crypto_chacha20_ctr(cipher_text, plain_text, text_size, - sub_key, nonce+16, ctr); + ctr = crypto_chacha20_ctr(cipher_text, plain_text, text_size, + sub_key, nonce+16, ctr); WIPE_BUFFER(sub_key); + return ctr; } void crypto_chacha20(u8 *cipher_text, const u8 *plain_text, size_t text_size, diff --git a/src/monocypher.h b/src/monocypher.h index 0b9cec9..5378676 100644 --- a/src/monocypher.h +++ b/src/monocypher.h @@ -228,24 +228,24 @@ void crypto_ietf_chacha20(uint8_t *cipher_text, size_t text_size, const uint8_t key[32], const uint8_t nonce[12]); -void crypto_chacha20_ctr(uint8_t *cipher_text, - const uint8_t *plain_text, - size_t text_size, - const uint8_t key[32], - const uint8_t nonce[8], - uint64_t ctr); -void crypto_xchacha20_ctr(uint8_t *cipher_text, - const uint8_t *plain_text, - size_t text_size, - const uint8_t key[32], - const uint8_t nonce[24], - uint64_t ctr); -void crypto_ietf_chacha20_ctr(uint8_t *cipher_text, +uint64_t crypto_chacha20_ctr(uint8_t *cipher_text, + const uint8_t *plain_text, + size_t text_size, + const uint8_t key[32], + const uint8_t nonce[8], + uint64_t ctr); +uint64_t crypto_xchacha20_ctr(uint8_t *cipher_text, const uint8_t *plain_text, size_t text_size, const uint8_t key[32], - const uint8_t nonce[12], - uint32_t ctr); + const uint8_t nonce[24], + uint64_t ctr); +uint32_t crypto_ietf_chacha20_ctr(uint8_t *cipher_text, + const uint8_t *plain_text, + size_t text_size, + const uint8_t key[32], + const uint8_t nonce[12], + uint32_t ctr); // Poly 1305 diff --git a/tests/test.c b/tests/test.c index 7b6dcb7..9b3b724 100644 --- a/tests/test.c +++ b/tests/test.c @@ -20,9 +20,13 @@ static void chacha20(const vector in[], vector *out) const vector *key = in; const vector *nonce = in + 1; const vector *plain = in + 2; - u64 ctr = load64_le(in[3].buf); - crypto_chacha20_ctr(out->buf, plain->buf, plain->size, - key->buf, nonce->buf, ctr); + u64 ctr = load64_le(in[3].buf); + u64 new_ctr = crypto_chacha20_ctr(out->buf, plain->buf, plain->size, + key->buf, nonce->buf, ctr); + u64 nb_blocks = plain->size / 64 + (plain->size % 64 != 0); + if (new_ctr - ctr != nb_blocks) { + printf("FAILURE: Chacha20 returned counter not correct: "); + } } static void hchacha20(const vector in[], vector *out) @@ -37,9 +41,13 @@ static void xchacha20(const vector in[], vector *out) const vector *key = in; const vector *nonce = in + 1; const vector *plain = in + 2; - u64 ctr = load64_le(in[3].buf); - crypto_xchacha20_ctr(out->buf, plain->buf, plain->size, - key->buf, nonce->buf, ctr); + u64 ctr = load64_le(in[3].buf); + u64 new_ctr = crypto_xchacha20_ctr(out->buf, plain->buf, plain->size, + key->buf, nonce->buf, ctr); + u64 nb_blocks = plain->size / 64 + (plain->size % 64 != 0); + if (new_ctr - ctr != nb_blocks) { + printf("FAILURE: Chacha20 returned counter not correct: "); + } } static void poly1305(const vector in[], vector *out)