summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimo Sorce <simo@redhat.com>2019-03-20 11:46:22 -0400
committerNiels Möller <nisse@lysator.liu.se>2019-03-24 11:42:31 +0100
commit794d2169c8614332f60bc29faf0010dcd0a31627 (patch)
tree95296b2223c6d3e3542c337b476e69372d986885
parent8702a4c48ae2381dd2994e5053961044fca89676 (diff)
downloadnettle-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.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/xts.c b/xts.c
index 5c37655d..ea2ceea9 100644
--- a/xts.c
+++ b/xts.c
@@ -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)