1
0
mirror of https://github.com/trezor/trezor-firmware.git synced 2024-12-18 04:18:10 +00:00

feat(crypto): add big endian support

This commit is contained in:
2128675309 2021-10-25 13:43:19 +00:00 committed by Andrew Kozlik
parent 428caf3d35
commit 684e0c886d
8 changed files with 164 additions and 29 deletions

View File

@ -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));

59
crypto/byte_order.h Normal file
View File

@ -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 <sys/types.h> (which in turn includes
* <machine/endian.h> 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

View File

@ -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);
}

View File

@ -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));

View File

@ -32,6 +32,7 @@
#include <stdint.h>
#include "sha2.h"
#include "memzero.h"
#include "byte_order.h"
/*
* ASSERT NOTE:

View File

@ -33,6 +33,7 @@
#include <stdint.h>
#include <stddef.h>
#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];

View File

@ -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
}
/**

View File

@ -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);