diff --git a/crypto/blake2_common.h b/crypto/blake2_common.h index 0a7a3ad91..39cefd72c 100644 --- a/crypto/blake2_common.h +++ b/crypto/blake2_common.h @@ -1,20 +1,39 @@ + +#include "byte_order.h" + static inline uint32_t load32(const void *src) { uint32_t w; memcpy(&w, src, sizeof w); +#if BYTE_ORDER == BIG_ENDIAN + REVERSE32(w, w); +#endif return w; } static inline uint64_t load64(const void *src) { uint64_t w; memcpy(&w, src, sizeof w); +#if BYTE_ORDER == BIG_ENDIAN + REVERSE64(w, w); +#endif return w; } static inline void store16(void *dst, uint16_t w) { memcpy(dst, &w, sizeof w); } -static inline void store32(void *dst, uint32_t w) { memcpy(dst, &w, sizeof w); } +static inline void store32(void *dst, uint32_t w) { +#if BYTE_ORDER == BIG_ENDIAN + REVERSE32(w, w); +#endif + memcpy(dst, &w, sizeof w); +} -static inline void store64(void *dst, uint64_t w) { memcpy(dst, &w, sizeof w); } +static inline void store64(void *dst, uint64_t w) { +#if BYTE_ORDER == BIG_ENDIAN + REVERSE64(w, w); +#endif + memcpy(dst, &w, sizeof w); +} static inline uint32_t rotr32(const uint32_t w, const unsigned c) { return (w >> c) | (w << (32 - c)); diff --git a/crypto/byte_order.h b/crypto/byte_order.h new file mode 100644 index 000000000..33d2164bc --- /dev/null +++ b/crypto/byte_order.h @@ -0,0 +1,59 @@ +#ifndef __BYTE_ORDER_H__ +#define __BYTE_ORDER_H__ + +// FROM sha2.h: +/* + * BYTE_ORDER NOTE: + * + * Please make sure that your system defines BYTE_ORDER. If your + * architecture is little-endian, make sure it also defines + * LITTLE_ENDIAN and that the two (BYTE_ORDER and LITTLE_ENDIAN) are + * equivalent. + * + * If your system does not define the above, then you can do so by + * hand like this: + * + * #define LITTLE_ENDIAN 1234 + * #define BIG_ENDIAN 4321 + * + * And for little-endian machines, add: + * + * #define BYTE_ORDER LITTLE_ENDIAN + * + * Or for big-endian machines: + * + * #define BYTE_ORDER BIG_ENDIAN + * + * The FreeBSD machine this was written on defines BYTE_ORDER + * appropriately by including (which in turn includes + * where the appropriate definitions are actually + * made). + */ + +#ifndef LITTLE_ENDIAN +#define LITTLE_ENDIAN 1234 +#define BIG_ENDIAN 4321 +#endif + +#ifndef BYTE_ORDER +#define BYTE_ORDER LITTLE_ENDIAN +#endif + +#define REVERSE32(w, x) \ + { \ + uint32_t tmp = (w); \ + tmp = (tmp >> 16) | (tmp << 16); \ + (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ + } + +#define REVERSE64(w, x) \ + { \ + uint64_t tmp = (w); \ + tmp = (tmp >> 32) | (tmp << 32); \ + tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ + ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ + (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ + ((tmp & 0x0000ffff0000ffffULL) << 16); \ + } + +#endif diff --git a/crypto/monero/base58.c b/crypto/monero/base58.c index 6c49d1b24..689595676 100644 --- a/crypto/monero/base58.c +++ b/crypto/monero/base58.c @@ -36,6 +36,7 @@ #include "int-util.h" #include "sha2.h" #include "../base58.h" +#include "../byte_order.h" const size_t alphabet_size = 58; // sizeof(b58digits_ordered) - 1; const size_t encoded_block_sizes[] = {0, 2, 3, 5, 6, 7, 9, 10, 11}; @@ -71,7 +72,11 @@ void uint_64_to_8be(uint64_t num, size_t size, uint8_t* data) { assert(1 <= size && size <= sizeof(uint64_t)); +#if BYTE_ORDER == LITTLE_ENDIAN uint64_t num_be = SWAP64(num); +#else + uint64_t num_be = num; +#endif memcpy(data, (uint8_t*)(&num_be) + sizeof(uint64_t) - size, size); } diff --git a/crypto/monero/xmr.c b/crypto/monero/xmr.c index a49e8a2ae..c02666847 100644 --- a/crypto/monero/xmr.c +++ b/crypto/monero/xmr.c @@ -3,6 +3,7 @@ // #include "xmr.h" +#include "../byte_order.h" #include "int-util.h" #include "rand.h" #include "serialize.h" @@ -128,6 +129,12 @@ void xmr_get_subaddress_secret_key(bignum256modm r, uint32_t major, char data[sizeof(prefix) + sizeof(buff) + 2 * sizeof(uint32_t)] = {0}; memcpy(data, prefix, sizeof(prefix)); memcpy(data + sizeof(prefix), buff, sizeof(buff)); + +#if BYTE_ORDER == BIG_ENDIAN + REVERSE32(major, major); + REVERSE32(minor, minor); +#endif + memcpy(data + sizeof(prefix) + sizeof(buff), &major, sizeof(uint32_t)); memcpy(data + sizeof(prefix) + sizeof(buff) + sizeof(uint32_t), &minor, sizeof(uint32_t)); diff --git a/crypto/sha2.c b/crypto/sha2.c index 5aa0ea38c..cce5904db 100644 --- a/crypto/sha2.c +++ b/crypto/sha2.c @@ -32,6 +32,7 @@ #include #include "sha2.h" #include "memzero.h" +#include "byte_order.h" /* * ASSERT NOTE: diff --git a/crypto/sha2.h b/crypto/sha2.h index 7f519c50b..bd1c7480a 100644 --- a/crypto/sha2.h +++ b/crypto/sha2.h @@ -33,6 +33,7 @@ #include #include +#include "byte_order.h" #define SHA1_BLOCK_LENGTH 64 #define SHA1_DIGEST_LENGTH 20 @@ -60,32 +61,6 @@ typedef struct _SHA512_CTX { uint64_t buffer[SHA512_BLOCK_LENGTH/sizeof(uint64_t)]; } SHA512_CTX; -/*** ENDIAN REVERSAL MACROS *******************************************/ -#ifndef LITTLE_ENDIAN -#define LITTLE_ENDIAN 1234 -#define BIG_ENDIAN 4321 -#endif - -#ifndef BYTE_ORDER -#define BYTE_ORDER LITTLE_ENDIAN -#endif - -#if BYTE_ORDER == LITTLE_ENDIAN -#define REVERSE32(w,x) { \ - uint32_t tmp = (w); \ - tmp = (tmp >> 16) | (tmp << 16); \ - (x) = ((tmp & 0xff00ff00UL) >> 8) | ((tmp & 0x00ff00ffUL) << 8); \ -} -#define REVERSE64(w,x) { \ - uint64_t tmp = (w); \ - tmp = (tmp >> 32) | (tmp << 32); \ - tmp = ((tmp & 0xff00ff00ff00ff00ULL) >> 8) | \ - ((tmp & 0x00ff00ff00ff00ffULL) << 8); \ - (x) = ((tmp & 0xffff0000ffff0000ULL) >> 16) | \ - ((tmp & 0x0000ffff0000ffffULL) << 16); \ -} -#endif /* BYTE_ORDER == LITTLE_ENDIAN */ - extern const uint32_t sha256_initial_hash_value[8]; extern const uint64_t sha512_initial_hash_value[8]; diff --git a/crypto/sha3.c b/crypto/sha3.c index 80ac28ff6..24708ee59 100644 --- a/crypto/sha3.c +++ b/crypto/sha3.c @@ -22,6 +22,7 @@ #include "sha3.h" #include "memzero.h" +#include "byte_order.h" #define I64(x) x##LL #define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n)))) @@ -165,6 +166,13 @@ static void keccak_chi(uint64_t *A) static void sha3_permutation(uint64_t *state) { +#if BYTE_ORDER == BIG_ENDIAN + int i; + for (i = 0; i < 25; i++) + { + REVERSE64(state[i], state[i]); + } +#endif int round = 0; for (round = 0; round < NumberOfRounds; round++) { @@ -202,6 +210,12 @@ static void sha3_permutation(uint64_t *state) /* apply iota(state, round) */ *state ^= keccak_round_constants[round]; } +#if BYTE_ORDER == BIG_ENDIAN + for (i = 0; i < 25; i++) + { + REVERSE64(state[i], state[i]); + } +#endif } /** diff --git a/crypto/tests/test_check.c b/crypto/tests/test_check.c index 9ea616f21..01e87b4c3 100644 --- a/crypto/tests/test_check.c +++ b/crypto/tests/test_check.c @@ -4823,6 +4823,60 @@ START_TEST(test_blake2b) { } END_TEST +// Blake2b-256 personalized, a la ZCash +// Test vectors from https://zips.z.cash/zip-0243 +START_TEST(test_blake2bp) { + static const struct { + const char *msg; + const char *personal; + const char *hash; + } tests[] = { + { + "", + "ZcashPrevoutHash", + "d53a633bbecf82fe9e9484d8a0e727c73bb9e68c96e72dec30144f6a84afa136", + }, + { + "", + "ZcashSequencHash", + "a5f25f01959361ee6eb56a7401210ee268226f6ce764a4f10b7f29e54db37272", + + }, + { + "e7719811893e0000095200ac6551ac636565b2835a0805750200025151", + "ZcashOutputsHash", + "ab6f7f6c5ad6b56357b5f37e16981723db6c32411753e28c175e15589172194a", + }, + { + "0bbe32a598c22adfb48cef72ba5d4287c0cefbacfd8ce195b4963c34a94bba7a1" + "75dae4b090f47a068e227433f9e49d3aa09e356d8d66d0c0121e91a3c4aa3f27fa1b" + "63396e2b41d", + "ZcashPrevoutHash", + "cacf0f5210cce5fa65a59f314292b3111d299e7d9d582753cf61e1e408552ae4", + }}; + + uint8_t digest[32]; + for (size_t i = 0; i < (sizeof(tests) / sizeof(*tests)); i++) { + size_t msg_len = strlen(tests[i].msg) / 2; + + // Test progressive hashing. + size_t part_len = msg_len / 2; + BLAKE2B_CTX ctx; + ck_assert_int_eq( + blake2b_InitPersonal(&ctx, sizeof(digest), tests[i].personal, + strlen(tests[i].personal)), + 0); + ck_assert_int_eq(blake2b_Update(&ctx, fromhex(tests[i].msg), part_len), 0); + ck_assert_int_eq(blake2b_Update(&ctx, NULL, 0), 0); + ck_assert_int_eq(blake2b_Update(&ctx, fromhex(tests[i].msg) + part_len, + msg_len - part_len), + 0); + ck_assert_int_eq(blake2b_Final(&ctx, digest, sizeof(digest)), 0); + ck_assert_mem_eq(digest, fromhex(tests[i].hash), sizeof(digest)); + } +} +END_TEST + // test vectors from // https://raw.githubusercontent.com/BLAKE2/BLAKE2/master/testvectors/blake2s-kat.txt START_TEST(test_blake2s) { @@ -5530,7 +5584,7 @@ START_TEST(test_slip39_word_index) { // 9999 value is never checked since the word is not in list {"fakeword", false, 9999}}; for (size_t i = 0; i < (sizeof(vectors) / sizeof(*vectors)); i++) { - bool result = word_index(&index, vectors[i].word, sizeof(vectors[i].word)); + bool result = word_index(&index, vectors[i].word, strlen(vectors[i].word)); ck_assert_int_eq(result, vectors[i].expected_result); if (result) { ck_assert_uint_eq(index, vectors[i].expected_index); @@ -9469,6 +9523,7 @@ Suite *test_suite(void) { tc = tcase_create("blake2"); tcase_add_test(tc, test_blake2b); + tcase_add_test(tc, test_blake2bp); tcase_add_test(tc, test_blake2s); suite_add_tcase(s, tc);