mirror of
https://github.com/trezor/trezor-firmware.git
synced 2024-12-23 23:08:14 +00:00
add sha3
This commit is contained in:
parent
92fcafa9e9
commit
f8713bad4d
@ -61,7 +61,6 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Sha256_digest_obj, mod_TrezorC
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha256___del__(mp_obj_t self) {
|
||||
mp_obj_Sha256_t *o = MP_OBJ_TO_PTR(self);
|
||||
mbedtls_sha256_free(&(o->ctx));
|
||||
printf("yay!\n");
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Sha256___del___obj, mod_TrezorCrypto_Sha256___del__);
|
||||
|
83
extmod/modtrezorcrypto/modtrezorcrypto-sha3-256.h
Normal file
83
extmod/modtrezorcrypto/modtrezorcrypto-sha3-256.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) Pavol Rusnak, SatoshiLabs
|
||||
*
|
||||
* Licensed under Microsoft Reference Source License (Ms-RSL)
|
||||
* see LICENSE.md file for details
|
||||
*/
|
||||
|
||||
#include "py/objstr.h"
|
||||
|
||||
#include "sha3.h"
|
||||
|
||||
#define HASH_SHA3_256_BLOCK_SIZE 64
|
||||
#define HASH_SHA3_256_DIGEST_SIZE 32
|
||||
|
||||
// class Sha3_256(object):
|
||||
typedef struct _mp_obj_Sha3_256_t {
|
||||
mp_obj_base_t base;
|
||||
sha3_ctx ctx;
|
||||
} mp_obj_Sha3_256_t;
|
||||
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_256_update(mp_obj_t self, mp_obj_t data);
|
||||
|
||||
// def Sha3_256.__init__(self, data: bytes = None)
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_256_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_Sha3_256_t *o = m_new_obj(mp_obj_Sha3_256_t);
|
||||
o->base.type = type;
|
||||
rhash_sha3_256_init(&(o->ctx));
|
||||
// constructor called with bytes/str as first parameter
|
||||
if (n_args == 1) {
|
||||
mod_TrezorCrypto_Sha3_256_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
// def Sha3_256.update(self, data: bytes) -> None
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_256_update(mp_obj_t self, mp_obj_t data) {
|
||||
mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self);
|
||||
mp_buffer_info_t databuf;
|
||||
mp_get_buffer_raise(data, &databuf, MP_BUFFER_READ);
|
||||
rhash_sha3_update(&(o->ctx), databuf.buf, databuf.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_TrezorCrypto_Sha3_256_update_obj, mod_TrezorCrypto_Sha3_256_update);
|
||||
|
||||
// def Sha3_256.digest(self) -> bytes
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_256_digest(mp_obj_t self) {
|
||||
mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, HASH_SHA3_256_DIGEST_SIZE);
|
||||
sha3_ctx ctx;
|
||||
memcpy(&ctx, &(o->ctx), sizeof(sha3_ctx));
|
||||
rhash_sha3_final(&ctx, (uint8_t *)vstr.buf);
|
||||
memset(&ctx, 0, sizeof(sha3_ctx));
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Sha3_256_digest_obj, mod_TrezorCrypto_Sha3_256_digest);
|
||||
|
||||
// def Sha3_256.__del__(self) -> None
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_256___del__(mp_obj_t self) {
|
||||
mp_obj_Sha3_256_t *o = MP_OBJ_TO_PTR(self);
|
||||
memset(&(o->ctx), 0, sizeof(sha3_ctx));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Sha3_256___del___obj, mod_TrezorCrypto_Sha3_256___del__);
|
||||
|
||||
// Sha3_256 stuff
|
||||
|
||||
STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Sha3_256_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_256_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_256_digest_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_256___del___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(HASH_SHA3_256_BLOCK_SIZE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(HASH_SHA3_256_DIGEST_SIZE) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mod_TrezorCrypto_Sha3_256_locals_dict, mod_TrezorCrypto_Sha3_256_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t mod_TrezorCrypto_Sha3_256_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Sha3_256,
|
||||
.make_new = mod_TrezorCrypto_Sha3_256_make_new,
|
||||
.locals_dict = (void*)&mod_TrezorCrypto_Sha3_256_locals_dict,
|
||||
};
|
83
extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h
Normal file
83
extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h
Normal file
@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) Pavol Rusnak, SatoshiLabs
|
||||
*
|
||||
* Licensed under Microsoft Reference Source License (Ms-RSL)
|
||||
* see LICENSE.md file for details
|
||||
*/
|
||||
|
||||
#include "py/objstr.h"
|
||||
|
||||
#include "sha3.h"
|
||||
|
||||
#define HASH_SHA3_512_BLOCK_SIZE 128
|
||||
#define HASH_SHA3_512_DIGEST_SIZE 64
|
||||
|
||||
// class Sha3_512(object):
|
||||
typedef struct _mp_obj_Sha3_512_t {
|
||||
mp_obj_base_t base;
|
||||
sha3_ctx ctx;
|
||||
} mp_obj_Sha3_512_t;
|
||||
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_512_update(mp_obj_t self, mp_obj_t data);
|
||||
|
||||
// def Sha3_512.__init__(self, data: bytes = None)
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_512_make_new(const mp_obj_type_t *type, size_t n_args, size_t n_kw, const mp_obj_t *args) {
|
||||
mp_arg_check_num(n_args, n_kw, 0, 1, false);
|
||||
mp_obj_Sha3_512_t *o = m_new_obj(mp_obj_Sha3_512_t);
|
||||
o->base.type = type;
|
||||
rhash_sha3_512_init(&(o->ctx));
|
||||
// constructor called with bytes/str as first parameter
|
||||
if (n_args == 1) {
|
||||
mod_TrezorCrypto_Sha3_512_update(MP_OBJ_FROM_PTR(o), args[0]);
|
||||
}
|
||||
return MP_OBJ_FROM_PTR(o);
|
||||
}
|
||||
|
||||
// def Sha3_512.update(self, data: bytes) -> None
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_512_update(mp_obj_t self, mp_obj_t data) {
|
||||
mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self);
|
||||
mp_buffer_info_t databuf;
|
||||
mp_get_buffer_raise(data, &databuf, MP_BUFFER_READ);
|
||||
rhash_sha3_update(&(o->ctx), databuf.buf, databuf.len);
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_TrezorCrypto_Sha3_512_update_obj, mod_TrezorCrypto_Sha3_512_update);
|
||||
|
||||
// def Sha3_512.digest(self) -> bytes
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_512_digest(mp_obj_t self) {
|
||||
mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self);
|
||||
vstr_t vstr;
|
||||
vstr_init_len(&vstr, HASH_SHA3_512_DIGEST_SIZE);
|
||||
sha3_ctx ctx;
|
||||
memcpy(&ctx, &(o->ctx), sizeof(sha3_ctx));
|
||||
rhash_sha3_final(&ctx, (uint8_t *)vstr.buf);
|
||||
memset(&ctx, 0, sizeof(sha3_ctx));
|
||||
return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr);
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Sha3_512_digest_obj, mod_TrezorCrypto_Sha3_512_digest);
|
||||
|
||||
// def Sha3_512.__del__(self) -> None
|
||||
STATIC mp_obj_t mod_TrezorCrypto_Sha3_512___del__(mp_obj_t self) {
|
||||
mp_obj_Sha3_512_t *o = MP_OBJ_TO_PTR(self);
|
||||
memset(&(o->ctx), 0, sizeof(sha3_ctx));
|
||||
return mp_const_none;
|
||||
}
|
||||
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_TrezorCrypto_Sha3_512___del___obj, mod_TrezorCrypto_Sha3_512___del__);
|
||||
|
||||
// Sha3_512 stuff
|
||||
|
||||
STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Sha3_512_locals_dict_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_update), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_512_update_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_512_digest_obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR___del__), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_512___del___obj) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_block_size), MP_OBJ_NEW_SMALL_INT(HASH_SHA3_512_BLOCK_SIZE) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_digest_size), MP_OBJ_NEW_SMALL_INT(HASH_SHA3_512_DIGEST_SIZE) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mod_TrezorCrypto_Sha3_512_locals_dict, mod_TrezorCrypto_Sha3_512_locals_dict_table);
|
||||
|
||||
STATIC const mp_obj_type_t mod_TrezorCrypto_Sha3_512_type = {
|
||||
{ &mp_type_type },
|
||||
.name = MP_QSTR_Sha3_512,
|
||||
.make_new = mod_TrezorCrypto_Sha3_512_make_new,
|
||||
.locals_dict = (void*)&mod_TrezorCrypto_Sha3_512_locals_dict,
|
||||
};
|
@ -19,6 +19,8 @@
|
||||
#include "modtrezorcrypto-ripemd160.h"
|
||||
#include "modtrezorcrypto-sha256.h"
|
||||
#include "modtrezorcrypto-sha512.h"
|
||||
#include "modtrezorcrypto-sha3-256.h"
|
||||
#include "modtrezorcrypto-sha3-512.h"
|
||||
|
||||
// module stuff
|
||||
|
||||
@ -27,6 +29,8 @@ STATIC const mp_rom_map_elem_t mp_module_TrezorCrypto_globals_table[] = {
|
||||
{ MP_ROM_QSTR(MP_QSTR_Ripemd160), MP_ROM_PTR(&mod_TrezorCrypto_Ripemd160_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Sha256), MP_ROM_PTR(&mod_TrezorCrypto_Sha256_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Sha512), MP_ROM_PTR(&mod_TrezorCrypto_Sha512_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Sha3_256), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_256_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_Sha3_512), MP_ROM_PTR(&mod_TrezorCrypto_Sha3_512_type) },
|
||||
{ MP_ROM_QSTR(MP_QSTR_pbkdf2_hmac), MP_ROM_PTR(&mod_TrezorCrypto_pbkdf2_hmac_obj) },
|
||||
};
|
||||
STATIC MP_DEFINE_CONST_DICT(mp_module_TrezorCrypto_globals, mp_module_TrezorCrypto_globals_table);
|
||||
|
361
extmod/modtrezorcrypto/sha3.c
Normal file
361
extmod/modtrezorcrypto/sha3.c
Normal file
@ -0,0 +1,361 @@
|
||||
/* sha3.c - an implementation of Secure Hash Algorithm 3 (Keccak).
|
||||
* based on the
|
||||
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
|
||||
* by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
|
||||
*
|
||||
* Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "sha3.h"
|
||||
|
||||
#define I64(x) x##LL
|
||||
#define ROTL64(qword, n) ((qword) << (n) ^ ((qword) >> (64 - (n))))
|
||||
#define le2me_64(x) (x)
|
||||
#define IS_ALIGNED_64(p) (0 == (7 & ((const char*)(p) - (const char*)0)))
|
||||
# define me64_to_le_str(to, from, length) memcpy((to), (from), (length))
|
||||
|
||||
/* constants */
|
||||
#define NumberOfRounds 24
|
||||
|
||||
/* SHA3 (Keccak) constants for 24 rounds */
|
||||
static uint64_t keccak_round_constants[NumberOfRounds] = {
|
||||
I64(0x0000000000000001), I64(0x0000000000008082), I64(0x800000000000808A), I64(0x8000000080008000),
|
||||
I64(0x000000000000808B), I64(0x0000000080000001), I64(0x8000000080008081), I64(0x8000000000008009),
|
||||
I64(0x000000000000008A), I64(0x0000000000000088), I64(0x0000000080008009), I64(0x000000008000000A),
|
||||
I64(0x000000008000808B), I64(0x800000000000008B), I64(0x8000000000008089), I64(0x8000000000008003),
|
||||
I64(0x8000000000008002), I64(0x8000000000000080), I64(0x000000000000800A), I64(0x800000008000000A),
|
||||
I64(0x8000000080008081), I64(0x8000000000008080), I64(0x0000000080000001), I64(0x8000000080008008)
|
||||
};
|
||||
|
||||
/* Initializing a sha3 context for given number of output bits */
|
||||
static void rhash_keccak_init(sha3_ctx *ctx, unsigned bits)
|
||||
{
|
||||
/* NB: The Keccak capacity parameter = bits * 2 */
|
||||
unsigned rate = 1600 - bits * 2;
|
||||
|
||||
memset(ctx, 0, sizeof(sha3_ctx));
|
||||
ctx->block_size = rate / 8;
|
||||
assert(rate <= 1600 && (rate % 64) == 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha3_224_init(sha3_ctx *ctx)
|
||||
{
|
||||
rhash_keccak_init(ctx, 224);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha3_256_init(sha3_ctx *ctx)
|
||||
{
|
||||
rhash_keccak_init(ctx, 256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha3_384_init(sha3_ctx *ctx)
|
||||
{
|
||||
rhash_keccak_init(ctx, 384);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize context before calculating hash.
|
||||
*
|
||||
* @param ctx context to initialize
|
||||
*/
|
||||
void rhash_sha3_512_init(sha3_ctx *ctx)
|
||||
{
|
||||
rhash_keccak_init(ctx, 512);
|
||||
}
|
||||
|
||||
/* Keccak theta() transformation */
|
||||
static void keccak_theta(uint64_t *A)
|
||||
{
|
||||
unsigned int x;
|
||||
uint64_t C[5], D[5];
|
||||
|
||||
for (x = 0; x < 5; x++) {
|
||||
C[x] = A[x] ^ A[x + 5] ^ A[x + 10] ^ A[x + 15] ^ A[x + 20];
|
||||
}
|
||||
D[0] = ROTL64(C[1], 1) ^ C[4];
|
||||
D[1] = ROTL64(C[2], 1) ^ C[0];
|
||||
D[2] = ROTL64(C[3], 1) ^ C[1];
|
||||
D[3] = ROTL64(C[4], 1) ^ C[2];
|
||||
D[4] = ROTL64(C[0], 1) ^ C[3];
|
||||
|
||||
for (x = 0; x < 5; x++) {
|
||||
A[x] ^= D[x];
|
||||
A[x + 5] ^= D[x];
|
||||
A[x + 10] ^= D[x];
|
||||
A[x + 15] ^= D[x];
|
||||
A[x + 20] ^= D[x];
|
||||
}
|
||||
}
|
||||
|
||||
/* Keccak pi() transformation */
|
||||
static void keccak_pi(uint64_t *A)
|
||||
{
|
||||
uint64_t A1;
|
||||
A1 = A[1];
|
||||
A[ 1] = A[ 6];
|
||||
A[ 6] = A[ 9];
|
||||
A[ 9] = A[22];
|
||||
A[22] = A[14];
|
||||
A[14] = A[20];
|
||||
A[20] = A[ 2];
|
||||
A[ 2] = A[12];
|
||||
A[12] = A[13];
|
||||
A[13] = A[19];
|
||||
A[19] = A[23];
|
||||
A[23] = A[15];
|
||||
A[15] = A[ 4];
|
||||
A[ 4] = A[24];
|
||||
A[24] = A[21];
|
||||
A[21] = A[ 8];
|
||||
A[ 8] = A[16];
|
||||
A[16] = A[ 5];
|
||||
A[ 5] = A[ 3];
|
||||
A[ 3] = A[18];
|
||||
A[18] = A[17];
|
||||
A[17] = A[11];
|
||||
A[11] = A[ 7];
|
||||
A[ 7] = A[10];
|
||||
A[10] = A1;
|
||||
/* note: A[ 0] is left as is */
|
||||
}
|
||||
|
||||
/* Keccak chi() transformation */
|
||||
static void keccak_chi(uint64_t *A)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < 25; i += 5) {
|
||||
uint64_t A0 = A[0 + i], A1 = A[1 + i];
|
||||
A[0 + i] ^= ~A1 & A[2 + i];
|
||||
A[1 + i] ^= ~A[2 + i] & A[3 + i];
|
||||
A[2 + i] ^= ~A[3 + i] & A[4 + i];
|
||||
A[3 + i] ^= ~A[4 + i] & A0;
|
||||
A[4 + i] ^= ~A0 & A1;
|
||||
}
|
||||
}
|
||||
|
||||
static void rhash_sha3_permutation(uint64_t *state)
|
||||
{
|
||||
int round;
|
||||
for (round = 0; round < NumberOfRounds; round++)
|
||||
{
|
||||
keccak_theta(state);
|
||||
|
||||
/* apply Keccak rho() transformation */
|
||||
state[ 1] = ROTL64(state[ 1], 1);
|
||||
state[ 2] = ROTL64(state[ 2], 62);
|
||||
state[ 3] = ROTL64(state[ 3], 28);
|
||||
state[ 4] = ROTL64(state[ 4], 27);
|
||||
state[ 5] = ROTL64(state[ 5], 36);
|
||||
state[ 6] = ROTL64(state[ 6], 44);
|
||||
state[ 7] = ROTL64(state[ 7], 6);
|
||||
state[ 8] = ROTL64(state[ 8], 55);
|
||||
state[ 9] = ROTL64(state[ 9], 20);
|
||||
state[10] = ROTL64(state[10], 3);
|
||||
state[11] = ROTL64(state[11], 10);
|
||||
state[12] = ROTL64(state[12], 43);
|
||||
state[13] = ROTL64(state[13], 25);
|
||||
state[14] = ROTL64(state[14], 39);
|
||||
state[15] = ROTL64(state[15], 41);
|
||||
state[16] = ROTL64(state[16], 45);
|
||||
state[17] = ROTL64(state[17], 15);
|
||||
state[18] = ROTL64(state[18], 21);
|
||||
state[19] = ROTL64(state[19], 8);
|
||||
state[20] = ROTL64(state[20], 18);
|
||||
state[21] = ROTL64(state[21], 2);
|
||||
state[22] = ROTL64(state[22], 61);
|
||||
state[23] = ROTL64(state[23], 56);
|
||||
state[24] = ROTL64(state[24], 14);
|
||||
|
||||
keccak_pi(state);
|
||||
keccak_chi(state);
|
||||
|
||||
/* apply iota(state, round) */
|
||||
*state ^= keccak_round_constants[round];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The core transformation. Process the specified block of data.
|
||||
*
|
||||
* @param hash the algorithm state
|
||||
* @param block the message block to process
|
||||
* @param block_size the size of the processed block in bytes
|
||||
*/
|
||||
static void rhash_sha3_process_block(uint64_t hash[25], const uint64_t *block, size_t block_size)
|
||||
{
|
||||
/* expanded loop */
|
||||
hash[ 0] ^= le2me_64(block[ 0]);
|
||||
hash[ 1] ^= le2me_64(block[ 1]);
|
||||
hash[ 2] ^= le2me_64(block[ 2]);
|
||||
hash[ 3] ^= le2me_64(block[ 3]);
|
||||
hash[ 4] ^= le2me_64(block[ 4]);
|
||||
hash[ 5] ^= le2me_64(block[ 5]);
|
||||
hash[ 6] ^= le2me_64(block[ 6]);
|
||||
hash[ 7] ^= le2me_64(block[ 7]);
|
||||
hash[ 8] ^= le2me_64(block[ 8]);
|
||||
/* if not sha3-512 */
|
||||
if (block_size > 72) {
|
||||
hash[ 9] ^= le2me_64(block[ 9]);
|
||||
hash[10] ^= le2me_64(block[10]);
|
||||
hash[11] ^= le2me_64(block[11]);
|
||||
hash[12] ^= le2me_64(block[12]);
|
||||
/* if not sha3-384 */
|
||||
if (block_size > 104) {
|
||||
hash[13] ^= le2me_64(block[13]);
|
||||
hash[14] ^= le2me_64(block[14]);
|
||||
hash[15] ^= le2me_64(block[15]);
|
||||
hash[16] ^= le2me_64(block[16]);
|
||||
/* if not sha3-256 */
|
||||
if (block_size > 136) {
|
||||
hash[17] ^= le2me_64(block[17]);
|
||||
#ifdef FULL_SHA3_FAMILY_SUPPORT
|
||||
/* if not sha3-224 */
|
||||
if (block_size > 144) {
|
||||
hash[18] ^= le2me_64(block[18]);
|
||||
hash[19] ^= le2me_64(block[19]);
|
||||
hash[20] ^= le2me_64(block[20]);
|
||||
hash[21] ^= le2me_64(block[21]);
|
||||
hash[22] ^= le2me_64(block[22]);
|
||||
hash[23] ^= le2me_64(block[23]);
|
||||
hash[24] ^= le2me_64(block[24]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
/* make a permutation of the hash */
|
||||
rhash_sha3_permutation(hash);
|
||||
}
|
||||
|
||||
#define SHA3_FINALIZED 0x80000000
|
||||
|
||||
/**
|
||||
* Calculate message hash.
|
||||
* Can be called repeatedly with chunks of the message to be hashed.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param msg message chunk
|
||||
* @param size length of the message chunk
|
||||
*/
|
||||
void rhash_sha3_update(sha3_ctx *ctx, const unsigned char *msg, size_t size)
|
||||
{
|
||||
size_t index = (size_t)ctx->rest;
|
||||
size_t block_size = (size_t)ctx->block_size;
|
||||
|
||||
if (ctx->rest & SHA3_FINALIZED) return; /* too late for additional input */
|
||||
ctx->rest = (unsigned)((ctx->rest + size) % block_size);
|
||||
|
||||
/* fill partial block */
|
||||
if (index) {
|
||||
size_t left = block_size - index;
|
||||
memcpy((char*)ctx->message + index, msg, (size < left ? size : left));
|
||||
if (size < left) return;
|
||||
|
||||
/* process partial block */
|
||||
rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
msg += left;
|
||||
size -= left;
|
||||
}
|
||||
while (size >= block_size) {
|
||||
uint64_t* aligned_message_block;
|
||||
if (IS_ALIGNED_64(msg)) {
|
||||
/* the most common case is processing of an already aligned message
|
||||
without copying it */
|
||||
aligned_message_block = (uint64_t*)msg;
|
||||
} else {
|
||||
memcpy(ctx->message, msg, block_size);
|
||||
aligned_message_block = ctx->message;
|
||||
}
|
||||
|
||||
rhash_sha3_process_block(ctx->hash, aligned_message_block, block_size);
|
||||
msg += block_size;
|
||||
size -= block_size;
|
||||
}
|
||||
if (size) {
|
||||
memcpy(ctx->message, msg, size); /* save leftovers */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result)
|
||||
{
|
||||
size_t digest_length = 100 - ctx->block_size / 2;
|
||||
const size_t block_size = ctx->block_size;
|
||||
|
||||
if (!(ctx->rest & SHA3_FINALIZED))
|
||||
{
|
||||
/* clear the rest of the data queue */
|
||||
memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
|
||||
((char*)ctx->message)[ctx->rest] |= 0x06;
|
||||
((char*)ctx->message)[block_size - 1] |= 0x80;
|
||||
|
||||
/* process final block */
|
||||
rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
|
||||
}
|
||||
|
||||
assert(block_size > digest_length);
|
||||
if (result) me64_to_le_str(result, ctx->hash, digest_length);
|
||||
}
|
||||
|
||||
#ifdef USE_KECCAK
|
||||
/**
|
||||
* Store calculated hash into the given array.
|
||||
*
|
||||
* @param ctx the algorithm context containing current hashing state
|
||||
* @param result calculated hash in binary form
|
||||
*/
|
||||
void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result)
|
||||
{
|
||||
size_t digest_length = 100 - ctx->block_size / 2;
|
||||
const size_t block_size = ctx->block_size;
|
||||
|
||||
if (!(ctx->rest & SHA3_FINALIZED))
|
||||
{
|
||||
/* clear the rest of the data queue */
|
||||
memset((char*)ctx->message + ctx->rest, 0, block_size - ctx->rest);
|
||||
((char*)ctx->message)[ctx->rest] |= 0x01;
|
||||
((char*)ctx->message)[block_size - 1] |= 0x80;
|
||||
|
||||
/* process final block */
|
||||
rhash_sha3_process_block(ctx->hash, ctx->message, block_size);
|
||||
ctx->rest = SHA3_FINALIZED; /* mark context as finalized */
|
||||
}
|
||||
|
||||
assert(block_size > digest_length);
|
||||
if (result) me64_to_le_str(result, ctx->hash, digest_length);
|
||||
}
|
||||
#endif /* USE_KECCAK */
|
73
extmod/modtrezorcrypto/sha3.h
Normal file
73
extmod/modtrezorcrypto/sha3.h
Normal file
@ -0,0 +1,73 @@
|
||||
/* sha3.h - an implementation of Secure Hash Algorithm 3 (Keccak).
|
||||
* based on the
|
||||
* The Keccak SHA-3 submission. Submission to NIST (Round 3), 2011
|
||||
* by Guido Bertoni, Joan Daemen, Michaël Peeters and Gilles Van Assche
|
||||
*
|
||||
* Copyright: 2013 Aleksey Kravchenko <rhash.admin@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. Use this program at your own risk!
|
||||
*/
|
||||
|
||||
#ifndef RHASH_SHA3_H
|
||||
#define RHASH_SHA3_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define sha3_224_hash_size 28
|
||||
#define sha3_256_hash_size 32
|
||||
#define sha3_384_hash_size 48
|
||||
#define sha3_512_hash_size 64
|
||||
#define sha3_max_permutation_size 25
|
||||
#define sha3_max_rate_in_qwords 24
|
||||
|
||||
/**
|
||||
* SHA3 Algorithm context.
|
||||
*/
|
||||
typedef struct sha3_ctx
|
||||
{
|
||||
/* 1600 bits algorithm hashing state */
|
||||
uint64_t hash[sha3_max_permutation_size];
|
||||
/* 1536-bit buffer for leftovers */
|
||||
uint64_t message[sha3_max_rate_in_qwords];
|
||||
/* count of bytes in the message[] buffer */
|
||||
unsigned rest;
|
||||
/* size of a message block processed at once */
|
||||
unsigned block_size;
|
||||
} sha3_ctx;
|
||||
|
||||
/* methods for calculating the hash function */
|
||||
|
||||
void rhash_sha3_224_init(sha3_ctx *ctx);
|
||||
void rhash_sha3_256_init(sha3_ctx *ctx);
|
||||
void rhash_sha3_384_init(sha3_ctx *ctx);
|
||||
void rhash_sha3_512_init(sha3_ctx *ctx);
|
||||
void rhash_sha3_update(sha3_ctx *ctx, const unsigned char* msg, size_t size);
|
||||
void rhash_sha3_final(sha3_ctx *ctx, unsigned char* result);
|
||||
|
||||
#ifdef USE_KECCAK
|
||||
#define rhash_keccak_224_init rhash_sha3_224_init
|
||||
#define rhash_keccak_256_init rhash_sha3_256_init
|
||||
#define rhash_keccak_384_init rhash_sha3_384_init
|
||||
#define rhash_keccak_512_init rhash_sha3_512_init
|
||||
#define rhash_keccak_update rhash_sha3_update
|
||||
void rhash_keccak_final(sha3_ctx *ctx, unsigned char* result);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* RHASH_SHA3_H */
|
56
src/tests/test_crypto_sha3_256.py
Normal file
56
src/tests/test_crypto_sha3_256.py
Normal file
@ -0,0 +1,56 @@
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
sys.path.append('../lib')
|
||||
import unittest
|
||||
import trezor.utils
|
||||
|
||||
from trezor.crypto import hashlib
|
||||
|
||||
class TestCryptoSha3_256(unittest.TestCase):
|
||||
|
||||
# vectors from http://www.di-mgt.com.au/sha_testvectors.html
|
||||
|
||||
def test_digest(self):
|
||||
self.assertEqual(hashlib.sha3_256(b'').digest(), trezor.utils.unhexlify('a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a'))
|
||||
self.assertEqual(hashlib.sha3_256(b'abc').digest(), trezor.utils.unhexlify('3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532'))
|
||||
self.assertEqual(hashlib.sha3_256(b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq').digest(), trezor.utils.unhexlify('41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376'))
|
||||
self.assertEqual(hashlib.sha3_256(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu').digest(), trezor.utils.unhexlify('916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18'))
|
||||
|
||||
def test_update(self):
|
||||
x = hashlib.sha3_256()
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a'))
|
||||
|
||||
x = hashlib.sha3_256()
|
||||
x.update(b'abc')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('3a985da74fe225b2045c172d6bd390bd855f086e3e9d525b46bfe24511431532'))
|
||||
|
||||
x = hashlib.sha3_256()
|
||||
x.update(b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('41c0dba2a9d6240849100376a8235e2c82e1b9998a999e21db32dd97496d3376'))
|
||||
|
||||
x = hashlib.sha3_256()
|
||||
x.update(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('916f6061fe879741ca6469b43971dfdb28b1a32dc36cb3254e812be27aad1d18'))
|
||||
|
||||
x = hashlib.sha3_256()
|
||||
for i in range(1000000):
|
||||
x.update(b'a')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('5c8875ae474a3634ba4fd55ec85bffd661f32aca75c6d699d0cdcb6c115891c1'))
|
||||
|
||||
'''
|
||||
x = hashlib.sha3_256()
|
||||
for i in range(16777216):
|
||||
x.update(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('ecbbc42cbf296603acb2c6bc0410ef4378bafb24b710357f12df607758b33e2b'))
|
||||
'''
|
||||
|
||||
def test_digest_multi(self):
|
||||
x = hashlib.sha3_256()
|
||||
d0 = x.digest()
|
||||
d1 = x.digest()
|
||||
d2 = x.digest()
|
||||
self.assertEqual(d0, d1)
|
||||
self.assertEqual(d0, d2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
56
src/tests/test_crypto_sha3_512.py
Normal file
56
src/tests/test_crypto_sha3_512.py
Normal file
@ -0,0 +1,56 @@
|
||||
import sys
|
||||
sys.path.append('..')
|
||||
sys.path.append('../lib')
|
||||
import unittest
|
||||
import trezor.utils
|
||||
|
||||
from trezor.crypto import hashlib
|
||||
|
||||
class TestCryptoSha3_512(unittest.TestCase):
|
||||
|
||||
# vectors from http://www.di-mgt.com.au/sha_testvectors.html
|
||||
|
||||
def test_digest(self):
|
||||
self.assertEqual(hashlib.sha3_512(b'').digest(), trezor.utils.unhexlify('a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'))
|
||||
self.assertEqual(hashlib.sha3_512(b'abc').digest(), trezor.utils.unhexlify('b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0'))
|
||||
self.assertEqual(hashlib.sha3_512(b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq').digest(), trezor.utils.unhexlify('04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e'))
|
||||
self.assertEqual(hashlib.sha3_512(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu').digest(), trezor.utils.unhexlify('afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185'))
|
||||
|
||||
def test_update(self):
|
||||
x = hashlib.sha3_512()
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26'))
|
||||
|
||||
x = hashlib.sha3_512()
|
||||
x.update(b'abc')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('b751850b1a57168a5693cd924b6b096e08f621827444f70d884f5d0240d2712e10e116e9192af3c91a7ec57647e3934057340b4cf408d5a56592f8274eec53f0'))
|
||||
|
||||
x = hashlib.sha3_512()
|
||||
x.update(b'abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('04a371e84ecfb5b8b77cb48610fca8182dd457ce6f326a0fd3d7ec2f1e91636dee691fbe0c985302ba1b0d8dc78c086346b533b49c030d99a27daf1139d6e75e'))
|
||||
|
||||
x = hashlib.sha3_512()
|
||||
x.update(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('afebb2ef542e6579c50cad06d2e578f9f8dd6881d7dc824d26360feebf18a4fa73e3261122948efcfd492e74e82e2189ed0fb440d187f382270cb455f21dd185'))
|
||||
|
||||
x = hashlib.sha3_512()
|
||||
for i in range(1000000):
|
||||
x.update(b'a')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('3c3a876da14034ab60627c077bb98f7e120a2a5370212dffb3385a18d4f38859ed311d0a9d5141ce9cc5c66ee689b266a8aa18ace8282a0e0db596c90b0a7b87'))
|
||||
|
||||
'''
|
||||
x = hashlib.sha3_512()
|
||||
for i in range(16777216):
|
||||
x.update(b'abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmnhijklmno')
|
||||
self.assertEqual(x.digest(), trezor.utils.unhexlify('235ffd53504ef836a1342b488f483b396eabbfe642cf78ee0d31feec788b23d0d18d5c339550dd5958a500d4b95363da1b5fa18affc1bab2292dc63b7d85097c'))
|
||||
'''
|
||||
|
||||
def test_digest_multi(self):
|
||||
x = hashlib.sha3_512()
|
||||
d0 = x.digest()
|
||||
d1 = x.digest()
|
||||
d2 = x.digest()
|
||||
self.assertEqual(d0, d1)
|
||||
self.assertEqual(d0, d2)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
@ -1,4 +1,6 @@
|
||||
from TrezorCrypto import Ripemd160 as ripemd160
|
||||
from TrezorCrypto import Sha256 as sha256
|
||||
from TrezorCrypto import Sha512 as sha512
|
||||
from TrezorCrypto import Sha3_256 as sha3_256
|
||||
from TrezorCrypto import Sha3_512 as sha3_512
|
||||
from TrezorCrypto import pbkdf2_hmac
|
||||
|
2
vendor/micropython
vendored
2
vendor/micropython
vendored
@ -1 +1 @@
|
||||
Subproject commit ef0505fb5c70bf89a6d42d712bc54815e6024b36
|
||||
Subproject commit f0ffa8c044759ba10bd092b3ad0e1434fa1b6654
|
Loading…
Reference in New Issue
Block a user