1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

Fix AES-NI SDCTR to pass the new tests.

The IV-incrementing code seems to have had several bugs. It was not
propagating a carry from bit 31 to 32 of the 128-bit integer,
apparently because of having arranged the 32-bit words wrongly within
the vector register; also, when it tried to implement carry
propagation from bit 63 to 64 by checking the low 64 bits for zero, it
checked the _high_ bits instead, leading to a spurious extra addition
in the low half if the high half happened to be zero.

This must surely have been able to cause mysterious decryption
failures about once every 2^32 cipher blocks = 64Gb of data
transferred. I suppose that must be a large enough number that either
no users of the snapshot builds have encountered the problem, or the
ones who did dismissed it as computers being randomly flaky.

The revised version now passes all the same tests as the software
implementation.
This commit is contained in:
Simon Tatham 2019-01-09 21:58:08 +00:00
parent 48ff6f13e2
commit 3347bd81b7

View File

@ -1572,8 +1572,8 @@ static void aes_decrypt_cbc_ni(unsigned char *blk, int len, AESContext * ctx)
FUNC_ISA
static void aes_sdctr_ni(unsigned char *blk, int len, AESContext *ctx)
{
const __m128i BSWAP_EPI64 = _mm_setr_epi8(3,2,1,0,7,6,5,4,11,10,9,8,15,14,13,12);
const __m128i ONE = _mm_setr_epi32(0,0,0,1);
const __m128i BSWAP_EPI64 = _mm_setr_epi8(7,6,5,4,3,2,1,0,15,14,13,12,11,10,9,8);
const __m128i ONE = _mm_setr_epi32(0,0,1,0);
const __m128i ZERO = _mm_setzero_si128();
__m128i iv;
__m128i* block = (__m128i*)blk;
@ -1620,7 +1620,7 @@ static void aes_sdctr_ni(unsigned char *blk, int len, AESContext *ctx)
iv = _mm_shuffle_epi8(iv, BSWAP_EPI64); /* Swap endianess */
iv = _mm_add_epi64(iv, ONE); /* Inc low part */
enc = _mm_cmpeq_epi64(iv, ZERO); /* Check for carry */
enc = _mm_unpacklo_epi64(ZERO, enc); /* Pack carry reg */
enc = _mm_unpackhi_epi64(enc, ZERO); /* Pack carry reg */
iv = _mm_sub_epi64(iv, enc); /* Sub carry reg */
iv = _mm_shuffle_epi8(iv, BSWAP_EPI64); /* Swap enianess back */