From 0ca3f3456da4db28a3c2563781bc3d07b7655d21 Mon Sep 17 00:00:00 2001 From: jsing <> Date: Sun, 25 May 2025 06:24:37 +0000 Subject: Simplify AES-IGE and remove code with implementation defined behaviour. Remove the UNALIGNED_MEMOPS_ARE_FAST from AES-IGE, which can result in implementation defined behaviour on i386/amd64. While we could keep this purely for aligned inputs and outputs, it's probably not that important and can be redone in a simpler form later if we want to do so. ok tb@ --- src/lib/libcrypto/aes/aes_ige.c | 157 ++++++++++------------------------------ 1 file changed, 40 insertions(+), 117 deletions(-) diff --git a/src/lib/libcrypto/aes/aes_ige.c b/src/lib/libcrypto/aes/aes_ige.c index 1a6fcfcfbf..1330397573 100644 --- a/src/lib/libcrypto/aes/aes_ige.c +++ b/src/lib/libcrypto/aes/aes_ige.c @@ -1,4 +1,4 @@ -/* $OpenBSD: aes_ige.c,v 1.10 2024/03/30 05:14:12 joshua Exp $ */ +/* $OpenBSD: aes_ige.c,v 1.11 2025/05/25 06:24:37 jsing Exp $ */ /* ==================================================================== * Copyright (c) 2006 The OpenSSL Project. All rights reserved. * @@ -59,137 +59,60 @@ typedef struct { unsigned long data[N_WORDS]; } aes_block_t; -/* XXX: probably some better way to do this */ -#if defined(__i386__) || defined(__x86_64__) -#define UNALIGNED_MEMOPS_ARE_FAST 1 -#else -#define UNALIGNED_MEMOPS_ARE_FAST 0 -#endif - -#if UNALIGNED_MEMOPS_ARE_FAST -#define load_block(d, s) (d) = *(const aes_block_t *)(s) -#define store_block(d, s) *(aes_block_t *)(d) = (s) -#else -#define load_block(d, s) memcpy((d).data, (s), AES_BLOCK_SIZE) -#define store_block(d, s) memcpy((d), (s).data, AES_BLOCK_SIZE) -#endif - -/* N.B. The IV for this mode is _twice_ the block size */ - void AES_ige_encrypt(const unsigned char *in, unsigned char *out, size_t length, const AES_KEY *key, unsigned char *ivec, const int enc) { + aes_block_t tmp, tmp2; + aes_block_t iv; + aes_block_t iv2; size_t n; size_t len; + /* N.B. The IV for this mode is _twice_ the block size */ + OPENSSL_assert((length % AES_BLOCK_SIZE) == 0); len = length / AES_BLOCK_SIZE; - if (AES_ENCRYPT == enc) { - if (in != out && (UNALIGNED_MEMOPS_ARE_FAST || - ((size_t)in|(size_t)out|(size_t)ivec) % - sizeof(long) == 0)) { - aes_block_t *ivp = (aes_block_t *)ivec; - aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); - - while (len) { - aes_block_t *inp = (aes_block_t *)in; - aes_block_t *outp = (aes_block_t *)out; - - for (n = 0; n < N_WORDS; ++n) - outp->data[n] = inp->data[n] ^ ivp->data[n]; - AES_encrypt((unsigned char *)outp->data, (unsigned char *)outp->data, key); - for (n = 0; n < N_WORDS; ++n) - outp->data[n] ^= iv2p->data[n]; - ivp = outp; - iv2p = inp; - --len; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - memmove(ivec, ivp->data, AES_BLOCK_SIZE); - memmove(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); - } else { - aes_block_t tmp, tmp2; - aes_block_t iv; - aes_block_t iv2; + memcpy(iv.data, ivec, AES_BLOCK_SIZE); + memcpy(iv2.data, ivec + AES_BLOCK_SIZE, AES_BLOCK_SIZE); - load_block(iv, ivec); - load_block(iv2, ivec + AES_BLOCK_SIZE); - - while (len) { - load_block(tmp, in); - for (n = 0; n < N_WORDS; ++n) - tmp2.data[n] = tmp.data[n] ^ iv.data[n]; - AES_encrypt((unsigned char *)tmp2.data, - (unsigned char *)tmp2.data, key); - for (n = 0; n < N_WORDS; ++n) - tmp2.data[n] ^= iv2.data[n]; - store_block(out, tmp2); - iv = tmp2; - iv2 = tmp; - --len; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - memcpy(ivec, iv.data, AES_BLOCK_SIZE); - memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); + if (AES_ENCRYPT == enc) { + while (len) { + memcpy(tmp.data, in, AES_BLOCK_SIZE); + for (n = 0; n < N_WORDS; ++n) + tmp2.data[n] = tmp.data[n] ^ iv.data[n]; + AES_encrypt((unsigned char *)tmp2.data, + (unsigned char *)tmp2.data, key); + for (n = 0; n < N_WORDS; ++n) + tmp2.data[n] ^= iv2.data[n]; + memcpy(out, tmp2.data, AES_BLOCK_SIZE); + iv = tmp2; + iv2 = tmp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; } } else { - if (in != out && (UNALIGNED_MEMOPS_ARE_FAST || - ((size_t)in|(size_t)out|(size_t)ivec) % - sizeof(long) == 0)) { - aes_block_t *ivp = (aes_block_t *)ivec; - aes_block_t *iv2p = (aes_block_t *)(ivec + AES_BLOCK_SIZE); - - while (len) { - aes_block_t tmp; - aes_block_t *inp = (aes_block_t *)in; - aes_block_t *outp = (aes_block_t *)out; - - for (n = 0; n < N_WORDS; ++n) - tmp.data[n] = inp->data[n] ^ iv2p->data[n]; - AES_decrypt((unsigned char *)tmp.data, - (unsigned char *)outp->data, key); - for (n = 0; n < N_WORDS; ++n) - outp->data[n] ^= ivp->data[n]; - ivp = inp; - iv2p = outp; - --len; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - memmove(ivec, ivp->data, AES_BLOCK_SIZE); - memmove(ivec + AES_BLOCK_SIZE, iv2p->data, AES_BLOCK_SIZE); - } else { - aes_block_t tmp, tmp2; - aes_block_t iv; - aes_block_t iv2; - - load_block(iv, ivec); - load_block(iv2, ivec + AES_BLOCK_SIZE); - - while (len) { - load_block(tmp, in); - tmp2 = tmp; - for (n = 0; n < N_WORDS; ++n) - tmp.data[n] ^= iv2.data[n]; - AES_decrypt((unsigned char *)tmp.data, - (unsigned char *)tmp.data, key); - for (n = 0; n < N_WORDS; ++n) - tmp.data[n] ^= iv.data[n]; - store_block(out, tmp); - iv = tmp2; - iv2 = tmp; - --len; - in += AES_BLOCK_SIZE; - out += AES_BLOCK_SIZE; - } - memcpy(ivec, iv.data, AES_BLOCK_SIZE); - memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); + while (len) { + memcpy(tmp.data, in, AES_BLOCK_SIZE); + tmp2 = tmp; + for (n = 0; n < N_WORDS; ++n) + tmp.data[n] ^= iv2.data[n]; + AES_decrypt((unsigned char *)tmp.data, + (unsigned char *)tmp.data, key); + for (n = 0; n < N_WORDS; ++n) + tmp.data[n] ^= iv.data[n]; + memcpy(out, tmp.data, AES_BLOCK_SIZE); + iv = tmp2; + iv2 = tmp; + --len; + in += AES_BLOCK_SIZE; + out += AES_BLOCK_SIZE; } } + memcpy(ivec, iv.data, AES_BLOCK_SIZE); + memcpy(ivec + AES_BLOCK_SIZE, iv2.data, AES_BLOCK_SIZE); } LCRYPTO_ALIAS(AES_ige_encrypt); -- cgit v1.2.3-55-g6feb