Skip to content

Commit

Permalink
Support big-endian platforms
Browse files Browse the repository at this point in the history
  • Loading branch information
uweigand committed Nov 23, 2022
1 parent 450ada2 commit 3a1eeae
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 12 deletions.
22 changes: 14 additions & 8 deletions crypto/fipsmodule/aes/aes_nohw.c
Original file line number Diff line number Diff line change
Expand Up @@ -338,15 +338,15 @@ static inline void aes_nohw_compact_block(aes_word_t out[AES_NOHW_BLOCK_WORDS],
#if defined(OPENSSL_SSE2)
// No conversions needed.
#elif defined(OPENSSL_64_BIT)
uint64_t a0 = aes_nohw_compact_word(out[0]);
uint64_t a1 = aes_nohw_compact_word(out[1]);
uint64_t a0 = aes_nohw_compact_word(CRYPTO_bswap8_le(out[0]));
uint64_t a1 = aes_nohw_compact_word(CRYPTO_bswap8_le(out[1]));
out[0] = (a0 & UINT64_C(0x00000000ffffffff)) | (a1 << 32);
out[1] = (a1 & UINT64_C(0xffffffff00000000)) | (a0 >> 32);
#else
uint32_t a0 = aes_nohw_compact_word(out[0]);
uint32_t a1 = aes_nohw_compact_word(out[1]);
uint32_t a2 = aes_nohw_compact_word(out[2]);
uint32_t a3 = aes_nohw_compact_word(out[3]);
uint32_t a0 = aes_nohw_compact_word(CRYPTO_bswap4_le(out[0]));
uint32_t a1 = aes_nohw_compact_word(CRYPTO_bswap4_le(out[1]));
uint32_t a2 = aes_nohw_compact_word(CRYPTO_bswap4_le(out[2]));
uint32_t a3 = aes_nohw_compact_word(CRYPTO_bswap4_le(out[3]));
// Note clang, when building for ARM Thumb2, will sometimes miscompile
// expressions such as (a0 & 0x0000ff00) << 8, particularly when building
// without optimizations. This bug was introduced in
Expand All @@ -370,6 +370,8 @@ static inline void aes_nohw_uncompact_block(
aes_nohw_uncompact_word((a0 & UINT64_C(0x00000000ffffffff)) | (a1 << 32));
uint64_t b1 =
aes_nohw_uncompact_word((a1 & UINT64_C(0xffffffff00000000)) | (a0 >> 32));
b0 = CRYPTO_bswap8_le(b0);
b1 = CRYPTO_bswap8_le(b1);
OPENSSL_memcpy(out, &b0, 8);
OPENSSL_memcpy(out + 8, &b1, 8);
#else
Expand All @@ -392,6 +394,10 @@ static inline void aes_nohw_uncompact_block(
b1 = aes_nohw_uncompact_word(b1);
b2 = aes_nohw_uncompact_word(b2);
b3 = aes_nohw_uncompact_word(b3);
b0 = CRYPTO_bswap4_le(b0);
b1 = CRYPTO_bswap4_le(b1);
b2 = CRYPTO_bswap4_le(b2);
b3 = CRYPTO_bswap4_le(b3);
OPENSSL_memcpy(out, &b0, 4);
OPENSSL_memcpy(out + 4, &b1, 4);
OPENSSL_memcpy(out + 8, &b2, 4);
Expand Down Expand Up @@ -920,11 +926,11 @@ void aes_nohw_ctr32_encrypt_blocks(const uint8_t *in, uint8_t *out,
OPENSSL_memcpy(ivs.u8 + 16 * i, ivec, 16);
}

uint32_t ctr = CRYPTO_bswap4(ivs.u32[3]);
uint32_t ctr = CRYPTO_bswap4_be(ivs.u32[3]);
for (;;) {
// Update counters.
for (uint32_t i = 0; i < AES_NOHW_BATCH_SIZE; i++) {
ivs.u32[4 * i + 3] = CRYPTO_bswap4(ctr + i);
ivs.u32[4 * i + 3] = CRYPTO_bswap4_be(ctr + i);
}

size_t todo = blocks >= AES_NOHW_BATCH_SIZE ? AES_NOHW_BATCH_SIZE : blocks;
Expand Down
13 changes: 13 additions & 0 deletions crypto/fipsmodule/ec/p256_shared.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,20 @@ typedef unsigned char P256_SCALAR_BYTES[33];

static inline void p256_scalar_bytes_from_limbs(
P256_SCALAR_BYTES bytes_out, const BN_ULONG limbs[P256_LIMBS]) {
#ifdef RING_BIG_ENDIAN
for (int i = 0; i < P256_LIMBS; i++)
{
#if BN_BITS2 == 64
BN_ULONG limb = CRYPTO_bswap8(limbs[i]);
OPENSSL_memcpy(bytes_out + i * 8, &limb, 8);
#else
BN_ULONG limb = CRYPTO_bswap4(limbs[i]);
OPENSSL_memcpy(bytes_out + i * 4, &limb, 4);
#endif
}
#else
OPENSSL_memcpy(bytes_out, limbs, 32);
#endif
bytes_out[32] = 0;
}

Expand Down
40 changes: 40 additions & 0 deletions crypto/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,10 @@ static inline crypto_word constant_time_select_w(crypto_word mask,
static inline uint32_t CRYPTO_bswap4(uint32_t x) {
return __builtin_bswap32(x);
}

static inline uint64_t CRYPTO_bswap8(uint64_t x) {
return __builtin_bswap64(x);
}
#elif defined(_MSC_VER)
#pragma warning(push, 3)
#include <stdlib.h>
Expand All @@ -272,8 +276,44 @@ static inline uint32_t CRYPTO_bswap4(uint32_t x) {
static inline uint32_t CRYPTO_bswap4(uint32_t x) {
return _byteswap_ulong(x);
}

static inline uint64_t CRYPTO_bswap8(uint64_t x) {
return _byteswap_uint64(x);
}
#else
static inline uint32_t CRYPTO_bswap4(uint32_t x) {
x = (x >> 16) | (x << 16);
x = ((x & 0xff00ff00) >> 8) | ((x & 0x00ff00ff) << 8);
return x;
}

static inline uint64_t CRYPTO_bswap8(uint64_t x) {
return CRYPTO_bswap4(x >> 32) | (((uint64_t)CRYPTO_bswap4(x)) << 32);
}
#endif


// Convert LE or BE values to/from native endianness.

#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define RING_BIG_ENDIAN
#endif
#endif

#ifdef RING_BIG_ENDIAN
#define CRYPTO_bswap4_le(x) CRYPTO_bswap4((x))
#define CRYPTO_bswap8_le(x) CRYPTO_bswap8((x))
#define CRYPTO_bswap4_be(x) (x)
#define CRYPTO_bswap8_be(x) (x)
#else
#define CRYPTO_bswap4_le(x) (x)
#define CRYPTO_bswap8_le(x) (x)
#define CRYPTO_bswap4_be(x) CRYPTO_bswap4((x))
#define CRYPTO_bswap8_be(x) CRYPTO_bswap8((x))
#endif


#if !defined(RING_CORE_NOSTDLIBINC)
#include <string.h>
#endif
Expand Down
4 changes: 2 additions & 2 deletions crypto/poly1305/poly1305.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,14 @@
#pragma GCC diagnostic ignored "-Wconversion"
#endif

// We can assume little-endian.
static uint32_t U8TO32_LE(const uint8_t *m) {
uint32_t r;
OPENSSL_memcpy(&r, m, sizeof(r));
return r;
return CRYPTO_bswap4_le(r);
}

static void U32TO8_LE(uint8_t *m, uint32_t v) {
v = CRYPTO_bswap4_le(v);
OPENSSL_memcpy(m, &v, sizeof(v));
}

Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,5 +115,3 @@ mod sealed {
pub trait Sealed {}
}

// TODO: https://github.com/briansmith/ring/issues/1555.
const _LITTLE_ENDIAN_ONLY: () = assert!(cfg!(target_endian = "little"));

0 comments on commit 3a1eeae

Please sign in to comment.