diff --git a/docs/api.md b/docs/api.md index f03a80c6ae..6121f8d318 100644 --- a/docs/api.md +++ b/docs/api.md @@ -233,6 +233,27 @@ def Sha3_512.digest(self) -> bytes Returns the digest of hashed data. +####trezor.crypto.random + +``` python +def trezor.crypto.random.uniform(n: int) -> int +``` + +Compute uniform random number from interval 0 ... n - 1 + +``` python +def trezor.crypto.random.bytes(len: int) -> bytes +``` + +Generate random bytes sequence of length len + +``` python +def trezor.crypto.random.shuffle(data: list) -> None +``` + +Shuffles items of given list (in-place) + + ####trezor.crypto.ssss ``` python diff --git a/docs/api.template.md b/docs/api.template.md index 765f9b43e9..034c6ca74b 100644 --- a/docs/api.template.md +++ b/docs/api.template.md @@ -48,6 +48,10 @@ Syntax used below is a valid Python function declaration with type hints defined @extmod/modtrezorcrypto/modtrezorcrypto-sha3-512.h +####trezor.crypto.random + +@extmod/modtrezorcrypto/modtrezorcrypto-random.h + ####trezor.crypto.ssss @extmod/modtrezorcrypto/modtrezorcrypto-ssss.h diff --git a/extmod/modtrezorcrypto/modtrezorcrypto-random.h b/extmod/modtrezorcrypto/modtrezorcrypto-random.h new file mode 100644 index 0000000000..80da9df58c --- /dev/null +++ b/extmod/modtrezorcrypto/modtrezorcrypto-random.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) Pavol Rusnak, SatoshiLabs + * + * Licensed under TREZOR License + * see LICENSE file for details + */ + +#include "py/objstr.h" + +#include "rand.h" + +typedef struct _mp_obj_Random_t { + mp_obj_base_t base; +} mp_obj_Random_t; + +STATIC mp_obj_t mod_TrezorCrypto_Random_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, 0, false); + mp_obj_Random_t *o = m_new_obj(mp_obj_Random_t); + o->base.type = type; + return MP_OBJ_FROM_PTR(o); +} + +/// def trezor.crypto.random.uniform(n: int) -> int +/// +/// Compute uniform random number from interval 0 ... n - 1 +/// +STATIC mp_obj_t mod_TrezorCrypto_Random_uniform(mp_obj_t self, mp_obj_t n) { + uint32_t nn = mp_obj_get_int(n); + if (nn == 0) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Maximum can't be zero")); + } + return MP_OBJ_NEW_SMALL_INT(random_uniform(nn)); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_TrezorCrypto_Random_uniform_obj, mod_TrezorCrypto_Random_uniform); + +/// def trezor.crypto.random.bytes(len: int) -> bytes +/// +/// Generate random bytes sequence of length len +/// +STATIC mp_obj_t mod_TrezorCrypto_Random_bytes(mp_obj_t self, mp_obj_t len) { + uint32_t l = mp_obj_get_int(len); + vstr_t vstr; + vstr_init_len(&vstr, l); + random_buffer((uint8_t *)vstr.buf, l); + return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_TrezorCrypto_Random_bytes_obj, mod_TrezorCrypto_Random_bytes); + +/// def trezor.crypto.random.shuffle(data: list) -> None +/// +/// Shuffles items of given list (in-place) +/// +STATIC mp_obj_t mod_TrezorCrypto_Random_shuffle(mp_obj_t self, mp_obj_t data) { + mp_uint_t item_cnt; + mp_obj_t *items; + if (MP_OBJ_IS_TYPE(data, &mp_type_list)) { + mp_obj_list_get(data, &item_cnt, &items); + } else { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "List expected")); + } + if (item_cnt > 256) { + nlr_raise(mp_obj_new_exception_msg(&mp_type_ValueError, "Maximum list size is 256 items")); + } + random_permute(items, sizeof(mp_obj_t *), item_cnt); + return mp_const_none; +} +STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_TrezorCrypto_Random_shuffle_obj, mod_TrezorCrypto_Random_shuffle); + +STATIC const mp_rom_map_elem_t mod_TrezorCrypto_Random_locals_dict_table[] = { + { MP_ROM_QSTR(MP_QSTR_uniform), MP_ROM_PTR(&mod_TrezorCrypto_Random_uniform_obj) }, + { MP_ROM_QSTR(MP_QSTR_bytes), MP_ROM_PTR(&mod_TrezorCrypto_Random_bytes_obj) }, + { MP_ROM_QSTR(MP_QSTR_shuffle), MP_ROM_PTR(&mod_TrezorCrypto_Random_shuffle_obj) }, +}; +STATIC MP_DEFINE_CONST_DICT(mod_TrezorCrypto_Random_locals_dict, mod_TrezorCrypto_Random_locals_dict_table); + +STATIC const mp_obj_type_t mod_TrezorCrypto_Random_type = { + { &mp_type_type }, + .name = MP_QSTR_Random, + .make_new = mod_TrezorCrypto_Random_make_new, + .locals_dict = (void*)&mod_TrezorCrypto_Random_locals_dict, +}; + + + diff --git a/extmod/modtrezorcrypto/modtrezorcrypto.c b/extmod/modtrezorcrypto/modtrezorcrypto.c index 6e4e3c0e51..02a047fb2d 100644 --- a/extmod/modtrezorcrypto/modtrezorcrypto.c +++ b/extmod/modtrezorcrypto/modtrezorcrypto.c @@ -18,6 +18,7 @@ #include "modtrezorcrypto-bip39.h" #include "modtrezorcrypto-ed25519.h" #include "modtrezorcrypto-pbkdf2.h" +#include "modtrezorcrypto-random.h" #include "modtrezorcrypto-ripemd160.h" #include "modtrezorcrypto-nist256p1.h" #include "modtrezorcrypto-secp256k1.h" @@ -33,6 +34,7 @@ STATIC const mp_rom_map_elem_t mp_module_TrezorCrypto_globals_table[] = { { MP_ROM_QSTR(MP_QSTR_Ed25519), MP_ROM_PTR(&mod_TrezorCrypto_Ed25519_type) }, { MP_ROM_QSTR(MP_QSTR_Nist256p1), MP_ROM_PTR(&mod_TrezorCrypto_Nist256p1_type) }, { MP_ROM_QSTR(MP_QSTR_Pbkdf2), MP_ROM_PTR(&mod_TrezorCrypto_Pbkdf2_type) }, + { MP_ROM_QSTR(MP_QSTR_Random), MP_ROM_PTR(&mod_TrezorCrypto_Random_type) }, { MP_ROM_QSTR(MP_QSTR_Ripemd160), MP_ROM_PTR(&mod_TrezorCrypto_Ripemd160_type) }, { MP_ROM_QSTR(MP_QSTR_Secp256k1), MP_ROM_PTR(&mod_TrezorCrypto_Secp256k1_type) }, { MP_ROM_QSTR(MP_QSTR_Sha256), MP_ROM_PTR(&mod_TrezorCrypto_Sha256_type) }, diff --git a/extmod/modtrezorcrypto/rand.c b/extmod/modtrezorcrypto/rand.c index ef7df098e1..385244b4cd 100644 --- a/extmod/modtrezorcrypto/rand.c +++ b/extmod/modtrezorcrypto/rand.c @@ -1,3 +1,4 @@ +#include #include "rand.h" #ifdef UNIX @@ -53,14 +54,14 @@ void random_buffer(uint8_t *buf, size_t len) #endif } -void random_permute(char *str, size_t len) +void random_permute(void *buf, size_t size, size_t count) { - int i, j; - char t; - for (i = len - 1; i >= 1; i--) { - j = random_uniform(i + 1); - t = str[j]; - str[j] = str[i]; - str[i] = t; + uint8_t *d = (uint8_t *)buf; + uint8_t t[size]; + for (size_t i = count - 1; i >= 1; i--) { + size_t j = random_uniform(i + 1); + memcpy(t, d + j * size, size); + memcpy(d + j * size, d + i * size, size); + memcpy(d + i * size, t, size); } } diff --git a/extmod/modtrezorcrypto/rand.h b/extmod/modtrezorcrypto/rand.h index 4ad63b22e4..84253b9c37 100644 --- a/extmod/modtrezorcrypto/rand.h +++ b/extmod/modtrezorcrypto/rand.h @@ -7,6 +7,6 @@ uint32_t random32(void); uint32_t random_uniform(uint32_t n); void random_buffer(uint8_t *buf, size_t len); -void random_permute(char *buf, size_t len); +void random_permute(void *buf, size_t size, size_t count); #endif diff --git a/src/trezor/crypto/__init__.py b/src/trezor/crypto/__init__.py index 5c77d6413e..334b024e07 100644 --- a/src/trezor/crypto/__init__.py +++ b/src/trezor/crypto/__init__.py @@ -1,6 +1,8 @@ -from TrezorCrypto import Pbkdf2 as pbkdf2 from TrezorCrypto import Bip39 +from TrezorCrypto import Pbkdf2 as pbkdf2 +from TrezorCrypto import Random from TrezorCrypto import SSSS bip39 = Bip39() +random = Random() ssss = SSSS()