-
Notifications
You must be signed in to change notification settings - Fork 9
/
modtcc-bip39.c
186 lines (164 loc) · 6.8 KB
/
modtcc-bip39.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*
* Copyright (c) Pavol Rusnak, SatoshiLabs
*
* Licensed under TREZOR License
* see LICENSE file for details
*/
#include "py/objstr.h"
#include "bip39.h"
/// def lookup_nth(idx: int) -> str:
/// '''
/// Return the n-th word from the wordlist.
/// '''
STATIC mp_obj_t mod_tcc_bip39_lookup_nth(mp_obj_t idx_obj)
{
int idx = mp_obj_get_int(idx_obj);
// we've all read the BIP, so obviously 11 bits only here.
if(idx < 0 || idx > 0x7ff) {
mp_raise_ValueError("wordlist range");
}
const char * const *wordlist = mnemonic_wordlist();
const char *w = wordlist[idx];
return mp_obj_new_str(w, strlen(w));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_tcc_bip39_lookup_nth_obj, mod_tcc_bip39_lookup_nth);
/// def lookup_word(word: str) -> int:
/// '''
/// Return the 11-bit binary value for indicated word from bip39 wordlist.
/// '''
STATIC mp_obj_t mod_tcc_bip39_lookup_word(mp_obj_t word)
{
mp_buffer_info_t want;
mp_get_buffer_raise(word, &want, MP_BUFFER_READ);
int i = 0;
for (const char * const *w = mnemonic_wordlist(); *w != 0; w++, i++) {
if ((strlen(*w) == want.len) && (strncmp(*w, want.buf, want.len) == 0)) {
return MP_OBJ_NEW_SMALL_INT(i);
}
}
mp_raise_ValueError("Unknown word");
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_tcc_bip39_lookup_word_obj, mod_tcc_bip39_lookup_word);
/// def find_word(prefix: str) -> Optional[str]:
/// '''
/// Return the first word from the wordlist starting with prefix.
/// '''
STATIC mp_obj_t mod_trezorcrypto_bip39_find_word(mp_obj_t prefix)
{
mp_buffer_info_t pfx;
mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ);
if (pfx.len == 0) {
mp_raise_ValueError("Invalid word prefix");
}
for (const char * const *w = mnemonic_wordlist(); *w != 0; w++) {
if (strncmp(*w, pfx.buf, pfx.len) == 0) {
return mp_obj_new_str(*w, strlen(*w));
}
}
return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_find_word_obj, mod_trezorcrypto_bip39_find_word);
/// def complete_word(prefix: str) -> int:
/// '''
/// Return possible 1-letter suffixes for given word prefix.
/// Result is a bitmask, with 'a' on the lowest bit, 'b' on the second lowest, etc.
/// If the prefix is itself in the wordlist, bit 26 is set as well.
/// '''
STATIC mp_obj_t mod_trezorcrypto_bip39_complete_word(mp_obj_t prefix)
{
mp_buffer_info_t pfx;
mp_get_buffer_raise(prefix, &pfx, MP_BUFFER_READ);
if (pfx.len == 0) {
mp_raise_ValueError("Invalid word prefix");
}
uint32_t res = 0;
uint8_t bit;
const char *word;
const char *const *wlist;
for (wlist = mnemonic_wordlist(); *wlist != 0; wlist++) {
word = *wlist;
if (strncmp(word, pfx.buf, pfx.len) == 0) {
if(strlen(word) == pfx.len) {
res |= 1 << 26;
} else if(strlen(word) > pfx.len) {
bit = word[pfx.len] - 'a';
res |= 1 << bit;
}
}
}
return mp_obj_new_int(res);
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_complete_word_obj, mod_trezorcrypto_bip39_complete_word);
#if 0
// TODO: rework with non-static api; also maybe have caller pick random number
/// def generate(strength: int) -> str:
/// '''
/// Generate a mnemonic of given strength (128, 160, 192, 224 and 256 bits).
/// '''
STATIC mp_obj_t mod_trezorcrypto_bip39_generate(mp_obj_t strength) {
int bits = mp_obj_get_int(strength);
if (bits % 32 || bits < 128 || bits > 256) {
mp_raise_ValueError("Invalid bit strength (only 128, 160, 192, 224 and 256 values are allowed)");
}
const char *mnemo = mnemonic_generate(bits);
return mp_obj_new_str(mnemo, strlen(mnemo));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_generate_obj, mod_trezorcrypto_bip39_generate);
#endif
/// def from_data(data: bytes) -> str:
/// '''
/// Generate a mnemonic from given data (of 16, 20, 24, 28 and 32 bytes).
/// '''
STATIC mp_obj_t mod_trezorcrypto_bip39_from_data(mp_obj_t data) {
mp_buffer_info_t bin;
mp_get_buffer_raise(data, &bin, MP_BUFFER_READ);
if (bin.len % 4 || bin.len < 16 || bin.len > 32) {
mp_raise_ValueError("Invalid data length (only 16, 20, 24, 28 and 32 bytes are allowed)");
}
char mnemo[240];
mnemonic_from_data_p(bin.buf, bin.len, mnemo);
return mp_obj_new_str(mnemo, strlen(mnemo));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_from_data_obj, mod_trezorcrypto_bip39_from_data);
/// def check(mnemonic: str) -> bool:
/// '''
/// Check whether given mnemonic is valid.
/// '''
STATIC mp_obj_t mod_trezorcrypto_bip39_check(mp_obj_t mnemonic) {
mp_buffer_info_t text;
mp_get_buffer_raise(mnemonic, &text, MP_BUFFER_READ);
return (text.len > 0 && mnemonic_check(text.buf)) ? mp_const_true : mp_const_false;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(mod_trezorcrypto_bip39_check_obj, mod_trezorcrypto_bip39_check);
/// def seed(mnemonic: str, passphrase: str) -> bytes:
/// '''
/// Generate seed from mnemonic and passphrase.
/// '''
STATIC mp_obj_t mod_trezorcrypto_bip39_seed(mp_obj_t mnemonic, mp_obj_t passphrase) {
mp_buffer_info_t mnemo;
mp_buffer_info_t phrase;
mp_get_buffer_raise(mnemonic, &mnemo, MP_BUFFER_READ);
mp_get_buffer_raise(passphrase, &phrase, MP_BUFFER_READ);
uint8_t seed[64];
const char *pmnemonic = mnemo.len > 0 ? mnemo.buf : "";
const char *ppassphrase = phrase.len > 0 ? phrase.buf : "";
mnemonic_to_seed(pmnemonic, ppassphrase, seed, NULL); // no callback for now
return mp_obj_new_bytes(seed, sizeof(seed));
}
STATIC MP_DEFINE_CONST_FUN_OBJ_2(mod_trezorcrypto_bip39_seed_obj, mod_trezorcrypto_bip39_seed);
STATIC const mp_rom_map_elem_t mod_trezorcrypto_bip39_globals_table[] = {
{ MP_ROM_QSTR(MP_QSTR___name__), MP_ROM_QSTR(MP_QSTR_bip39) },
{ MP_ROM_QSTR(MP_QSTR_find_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_find_word_obj) },
{ MP_ROM_QSTR(MP_QSTR_complete_word), MP_ROM_PTR(&mod_trezorcrypto_bip39_complete_word_obj) },
//TODO//{ MP_ROM_QSTR(MP_QSTR_generate), MP_ROM_PTR(&mod_trezorcrypto_bip39_generate_obj) },
{ MP_ROM_QSTR(MP_QSTR_from_data), MP_ROM_PTR(&mod_trezorcrypto_bip39_from_data_obj) },
{ MP_ROM_QSTR(MP_QSTR_check), MP_ROM_PTR(&mod_trezorcrypto_bip39_check_obj) },
{ MP_ROM_QSTR(MP_QSTR_seed), MP_ROM_PTR(&mod_trezorcrypto_bip39_seed_obj) },
{ MP_ROM_QSTR(MP_QSTR_lookup_nth), MP_ROM_PTR(&mod_tcc_bip39_lookup_nth_obj) },
{ MP_ROM_QSTR(MP_QSTR_lookup_word), MP_ROM_PTR(&mod_tcc_bip39_lookup_word_obj) },
};
STATIC MP_DEFINE_CONST_DICT(mod_trezorcrypto_bip39_globals, mod_trezorcrypto_bip39_globals_table);
STATIC const mp_obj_module_t mod_trezorcrypto_bip39_module = {
.base = { &mp_type_module },
.globals = (mp_obj_dict_t*)&mod_trezorcrypto_bip39_globals,
};