diff options
author | Simo Sorce <simo@redhat.com> | 2019-03-20 11:46:22 -0400 |
---|---|---|
committer | Niels Möller <nisse@lysator.liu.se> | 2019-03-24 11:42:31 +0100 |
commit | 794d2169c8614332f60bc29faf0010dcd0a31627 (patch) | |
tree | 95296b2223c6d3e3542c337b476e69372d986885 | |
parent | 8702a4c48ae2381dd2994e5053961044fca89676 (diff) | |
download | nettle-794d2169c8614332f60bc29faf0010dcd0a31627.tar.gz |
Recode xts_shift based on endianess
This creates two implementations of xts_shift, one for little endian and
one for big endian. This way we avoid copies to additional variables and
inefficient byteswapping on platforms that do not have dedicated
instructions.
Signed-off-by: Simo Sorce <simo@redhat.com>
-rw-r--r-- | xts.c | 29 |
1 files changed, 20 insertions, 9 deletions
@@ -45,21 +45,32 @@ #include "memxor.h" #include "nettle-internal.h" -/* shift one and XOR with 0x87. */ +/* shift left one and XOR with 0x87 if there is carry. */ +/* the algorithm reads this as a 128bit Little Endian number */ /* src and dest can point to the same buffer for in-place operations */ +#if WORDS_BIGENDIAN +#define BE_SHIFT(x) ((((x) & 0x7f7f7f7f7f7f7f7f) << 1) | \ + (((x) & 0x8080808080808080) >> 15)) static void xts_shift(union nettle_block16 *dst, const union nettle_block16 *src) { - uint8_t carry = src->b[15] >> 7; - uint64_t b0 = LE_READ_UINT64(src->b); - uint64_t b1 = LE_READ_UINT64(src->b+8); - b1 = (b1 << 1) | (b0 >> 63); - b0 = b0 << 1; - LE_WRITE_UINT64(dst->b, b0); - LE_WRITE_UINT64(dst->b+8, b1); - dst->b[0] ^= 0x87 & -carry; + uint64_t carry = (src->u64[1] & 0x80) >> 7; + dst->u64[1] = BE_SHIFT(src->u64[1]) | ((src->u64[0] & 0x80) << 49); + dst->u64[0] = BE_SHIFT(src->u64[0]); + dst->u64[0] ^= 0x8700000000000000 & -carry; } +#else /* !WORDS_BIGENDIAN */ +static void +xts_shift(union nettle_block16 *dst, + const union nettle_block16 *src) +{ + uint64_t carry = src->u64[1] >> 63; + dst->u64[1] = (src->u64[1] << 1) | (src->u64[0] >> 63); + dst->u64[0] = src->u64[0] << 1; + dst->u64[0] ^= 0x87 & -carry; +} +#endif /* !WORDS_BIGNDIAN */ static void check_length(size_t length, uint8_t *dst) |