modes/ctr128.c: pay attention to ecount_buf alignment in CRYPTO_ctr128_encrypt.

It's never problem if CRYPTO_ctr128_encrypt is called from EVP, because
buffer in question is always aligned within EVP_CIPHER_CTX structure.

RT#4218

Reviewed-by: Richard Levitte <levitte@openssl.org>
(cherry picked from commit 5e4bbeb49f)
This commit is contained in:
Andy Polyakov 2016-02-12 14:07:27 +01:00
parent b4b23d05d3
commit 6533a0b8d1

View file

@ -67,23 +67,20 @@
/* increment counter (128-bit int) by 1 */ /* increment counter (128-bit int) by 1 */
static void ctr128_inc(unsigned char *counter) static void ctr128_inc(unsigned char *counter)
{ {
u32 n = 16; u32 n = 16, c = 1;
u8 c;
do { do {
--n; --n;
c = counter[n]; c += counter[n];
++c; counter[n] = (u8)c;
counter[n] = c; c >>= 8;
if (c)
return;
} while (n); } while (n);
} }
#if !defined(OPENSSL_SMALL_FOOTPRINT) #if !defined(OPENSSL_SMALL_FOOTPRINT)
static void ctr128_inc_aligned(unsigned char *counter) static void ctr128_inc_aligned(unsigned char *counter)
{ {
size_t *data, c, n; size_t *data, c, d, n;
const union { const union {
long one; long one;
char little; char little;
@ -91,20 +88,19 @@ static void ctr128_inc_aligned(unsigned char *counter)
1 1
}; };
if (is_endian.little) { if (is_endian.little || ((size_t)counter % sizeof(size_t)) != 0) {
ctr128_inc(counter); ctr128_inc(counter);
return; return;
} }
data = (size_t *)counter; data = (size_t *)counter;
c = 1;
n = 16 / sizeof(size_t); n = 16 / sizeof(size_t);
do { do {
--n; --n;
c = data[n]; d = data[n] += c;
++c; /* did addition carry? */
data[n] = c; c = ((d - c) ^ d) >> (sizeof(size_t) * 8 - 1);
if (c)
return;
} while (n); } while (n);
} }
#endif #endif
@ -144,14 +140,14 @@ void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out,
} }
# if defined(STRICT_ALIGNMENT) # if defined(STRICT_ALIGNMENT)
if (((size_t)in | (size_t)out | (size_t)ivec) % sizeof(size_t) != if (((size_t)in | (size_t)out | (size_t)ecount_buf)
0) % sizeof(size_t) != 0)
break; break;
# endif # endif
while (len >= 16) { while (len >= 16) {
(*block) (ivec, ecount_buf, key); (*block) (ivec, ecount_buf, key);
ctr128_inc_aligned(ivec); ctr128_inc_aligned(ivec);
for (; n < 16; n += sizeof(size_t)) for (n = 0; n < 16; n += sizeof(size_t))
*(size_t *)(out + n) = *(size_t *)(out + n) =
*(size_t *)(in + n) ^ *(size_t *)(ecount_buf + n); *(size_t *)(in + n) ^ *(size_t *)(ecount_buf + n);
len -= 16; len -= 16;
@ -189,16 +185,13 @@ void CRYPTO_ctr128_encrypt(const unsigned char *in, unsigned char *out,
/* increment upper 96 bits of 128-bit counter by 1 */ /* increment upper 96 bits of 128-bit counter by 1 */
static void ctr96_inc(unsigned char *counter) static void ctr96_inc(unsigned char *counter)
{ {
u32 n = 12; u32 n = 12, c = 1;
u8 c;
do { do {
--n; --n;
c = counter[n]; c += counter[n];
++c; counter[n] = (u8)c;
counter[n] = c; c >>= 8;
if (c)
return;
} while (n); } while (n);
} }