Fix counter wrapping in AES GCM

The generic and AESNI implementations used different conventions
regarding counter wrapping in GCM.  The generic code was based on
function block128_inc_be, for which the counter is a 128-bit value.
Whereas the AESNI code used intrinsic function _mm_add_epi64, and
therefore wrapping at 2^64.

In NIST.SP.800-38d the GCM specification mandates to use incrementing
function inc32, wrapping after 2^32 blocks.  This commit changes both
generic and AESNI implementations to align to the specification and
adds a test vector specially crafted to start encryption with IV block
0xfffffffffffffffffffffffffffffffe.
This commit is contained in:
Olivier Chéron 2019-08-20 10:34:40 +02:00
parent 0d32f9b833
commit fc07a8b931
4 changed files with 19 additions and 6 deletions

View File

@ -118,6 +118,11 @@ static inline void block128_inc_be(block128 *b)
b->q[1] = cpu_to_be64(v);
}
static inline void block128_inc32_be(block128 *b)
{
b->d[3] = cpu_to_be32(be32_to_cpu(b->d[3]) + 1);
}
#ifdef IMPL_DEBUG
#include <stdio.h>
static inline void block128_print(block128 *b)

View File

@ -199,7 +199,7 @@ void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key
for (; nb_blocks-- > 0; output += 16, input += 16) {
/* iv += 1 */
iv = _mm_add_epi64(iv, one);
iv = _mm_add_epi32(iv, one);
/* put back iv in big endian, encrypt it,
* and xor it to input */
@ -239,7 +239,7 @@ void SIZED(cryptonite_aesni_gcm_encrypt)(uint8_t *output, aes_gcm *gcm, aes_key
block128_copy_bytes(&block, input, part_block_len);
/* iv += 1 */
iv = _mm_add_epi64(iv, one);
iv = _mm_add_epi32(iv, one);
/* put back iv in big endian mode, encrypt it and xor it with input */
__m128i tmp = _mm_shuffle_epi8(iv, bswap_mask);

View File

@ -835,7 +835,7 @@ void cryptonite_aes_generic_gcm_encrypt(uint8_t *output, aes_gcm *gcm, aes_key *
gcm->length_input += length;
for (; length >= 16; input += 16, output += 16, length -= 16) {
block128_inc_be(&gcm->civ);
block128_inc32_be(&gcm->civ);
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
block128_xor(&out, (block128 *) input);
@ -846,7 +846,7 @@ void cryptonite_aes_generic_gcm_encrypt(uint8_t *output, aes_gcm *gcm, aes_key *
aes_block tmp;
int i;
block128_inc_be(&gcm->civ);
block128_inc32_be(&gcm->civ);
/* create e(civ) in out */
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
/* initialize a tmp as input and xor it to e(civ) */
@ -868,7 +868,7 @@ void cryptonite_aes_generic_gcm_decrypt(uint8_t *output, aes_gcm *gcm, aes_key *
gcm->length_input += length;
for (; length >= 16; input += 16, output += 16, length -= 16) {
block128_inc_be(&gcm->civ);
block128_inc32_be(&gcm->civ);
cryptonite_aes_encrypt_block(&out, key, &gcm->civ);
gcm_ghash_add(gcm, (block128 *) input);
@ -879,7 +879,7 @@ void cryptonite_aes_generic_gcm_decrypt(uint8_t *output, aes_gcm *gcm, aes_key *
aes_block tmp;
int i;
block128_inc_be(&gcm->civ);
block128_inc32_be(&gcm->civ);
block128_zero(&tmp);
block128_copy_bytes(&tmp, input, length);

View File

@ -56,6 +56,14 @@ vectors_aes128_enc =
, {-out = -}"\xe4\x42\xf8\xc4\xc6\x67\x84\x86\x4a\x5a\x6e\xc7\xe0\xca\x68\xac\x16\xbc\x5b\xbf\xf7\xd5\xf3\xfa\xf3\xb2\xcb\xb0\xa2\x14\xa1"
, {-taglen = -}16
, {-tag = -}"\x94\xd1\x47\xc3\xa2\xca\x93\xe9\x66\x93\x1e\x3b\xb3\xbb\x67\x01")
-- vector 6 tests 32-bit counter wrapping
, ( {-key = -}"\x01\x02\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
, {-iv = -}"\xe8\x38\x84\x1d\x75\xae\x33\xb5\x4b\x51\x57\x89\xc9\x5f\xbe\x65"
, {-aad = -}"\x54\x68\x65\x20\x66\x69\x76\x65\x20\x62\x6f\x78\x69\x6e\x67\x20\x77\x69\x7a\x61\x72\x64\x73\x20\x6a\x75\x6d\x70\x20\x71\x75\x69\x63\x6b\x6c\x79\x2e"
, {-input = -}"\x54\x68\x65\x20\x71\x75\x69\x63\x6b\x20\x62\x72\x6f\x77\x6e\x20\x66\x6f\x78\x20\x6a\x75\x6d\x70\x73\x20\x6f\x76\x65\x72\x20\x74\x68\x65\x20\x6c\x61\x7a\x79\x20\x64\x6f\x67"
, {-out = -}"\x82\x31\x9e\x5a\x6a\x7f\x43\xd0\x42\x8c\xf1\x01\xcf\x0c\x75\xf1\x5d\xda\x4f\xa1\x28\x95\xcd\xd7\x7b\xd5\x42\x68\x2f\xcd\x10\x1b\x0c\x75\x05\x54\xf4\x2f\x2b\xf6\x69\x96\x29"
, {-taglen = -}16
, {-tag = -}"\x9a\xfa\xf4\xea\xae\x2e\x6f\x40\x00\xf4\x89\x77\xd0\x1e\xd5\x14")
]
vectors_aes256_enc :: [KATGCM]