Skip to content

Commit 7d239e2

Browse files
authored
feat: support change passphrasae pin (#374)
* support change passphrase pin
1 parent b1160e8 commit 7d239e2

File tree

35 files changed

+618
-148
lines changed

35 files changed

+618
-148
lines changed

core/embed/extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,21 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_0(
150150
mod_trezorcrypto_se_thd89_get_session_state_obj,
151151
mod_trezorcrypto_se_thd89_get_session_state);
152152

153+
/// def get_session_current_id() -> bytes:
154+
/// """
155+
/// get current session id.
156+
/// """
157+
STATIC mp_obj_t mod_trezorcrypto_se_thd89_get_session_current_id(void) {
158+
uint8_t session_id[32] = {0};
159+
if (!se_session_get_current_id(session_id)) {
160+
return mp_const_none;
161+
}
162+
return mp_obj_new_bytes(session_id, 32);
163+
}
164+
STATIC MP_DEFINE_CONST_FUN_OBJ_0(
165+
mod_trezorcrypto_se_thd89_get_session_current_id_obj,
166+
mod_trezorcrypto_se_thd89_get_session_current_id);
167+
153168
/// def session_is_open() -> bool:
154169
/// """
155170
/// get current session secret state.
@@ -1084,6 +1099,42 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(
10841099
mod_trezorcrypto_se_thd89_check_passphrase_btc_test_address_obj,
10851100
mod_trezorcrypto_se_thd89_check_passphrase_btc_test_address);
10861101

1102+
/// def change_pin_passphrase(old_pin: str, new_pin: str) -> bool:
1103+
/// """
1104+
/// Change the PIN of an existing passphrase entry.
1105+
/// Returns True on success, False on failure.
1106+
/// """
1107+
STATIC mp_obj_t mod_trezorcrypto_se_thd89_change_pin_passphrase(
1108+
mp_obj_t old_pin, mp_obj_t new_pin) {
1109+
mp_buffer_info_t old_pin_buf = {0};
1110+
mp_get_buffer_raise(old_pin, &old_pin_buf, MP_BUFFER_READ);
1111+
1112+
mp_buffer_info_t new_pin_buf = {0};
1113+
mp_get_buffer_raise(new_pin, &new_pin_buf, MP_BUFFER_READ);
1114+
1115+
if (old_pin_buf.len < 6 || old_pin_buf.len > PIN_MAX_LENGTH) {
1116+
mp_raise_ValueError("Old PIN length must be between 6 and 50 characters");
1117+
}
1118+
1119+
if (new_pin_buf.len < 6 || new_pin_buf.len > PIN_MAX_LENGTH) {
1120+
mp_raise_ValueError("New PIN length must be between 6 and 50 characters");
1121+
}
1122+
1123+
if (old_pin_buf.len == new_pin_buf.len) {
1124+
if (memcmp(old_pin_buf.buf, new_pin_buf.buf, old_pin_buf.len) == 0) {
1125+
mp_raise_ValueError("New PIN cannot be the same as old PIN");
1126+
}
1127+
}
1128+
1129+
secbool ret = se_change_pin_passphrase((const char *)old_pin_buf.buf,
1130+
(const char *)new_pin_buf.buf);
1131+
1132+
return ret ? mp_const_true : mp_const_false;
1133+
}
1134+
STATIC MP_DEFINE_CONST_FUN_OBJ_2(
1135+
mod_trezorcrypto_se_thd89_change_pin_passphrase_obj,
1136+
mod_trezorcrypto_se_thd89_change_pin_passphrase);
1137+
10871138
/// FIDO2_CRED_COUNT_MAX: int
10881139

10891140
STATIC const mp_rom_map_elem_t mod_trezorcrypto_se_thd89_globals_table[] = {
@@ -1100,6 +1151,8 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_se_thd89_globals_table[] = {
11001151
MP_ROM_PTR(&mod_trezorcrypto_se_thd89_end_session_obj)},
11011152
{MP_ROM_QSTR(MP_QSTR_get_session_state),
11021153
MP_ROM_PTR(&mod_trezorcrypto_se_thd89_get_session_state_obj)},
1154+
{MP_ROM_QSTR(MP_QSTR_get_session_current_id),
1155+
MP_ROM_PTR(&mod_trezorcrypto_se_thd89_get_session_current_id_obj)},
11031156
{MP_ROM_QSTR(MP_QSTR_session_is_open),
11041157
MP_ROM_PTR(&mod_trezorcrypto_se_thd89_session_is_open_obj)},
11051158
{MP_ROM_QSTR(MP_QSTR_get_session_type),
@@ -1169,6 +1222,8 @@ STATIC const mp_rom_map_elem_t mod_trezorcrypto_se_thd89_globals_table[] = {
11691222
{MP_ROM_QSTR(MP_QSTR_check_passphrase_btc_test_address),
11701223
MP_ROM_PTR(
11711224
&mod_trezorcrypto_se_thd89_check_passphrase_btc_test_address_obj)},
1225+
{MP_ROM_QSTR(MP_QSTR_change_pin_passphrase),
1226+
MP_ROM_PTR(&mod_trezorcrypto_se_thd89_change_pin_passphrase_obj)},
11721227
{MP_ROM_QSTR(MP_QSTR_USER_PIN_ENTERED), MP_ROM_INT(USER_PIN_ENTERED)},
11731228
{MP_ROM_QSTR(MP_QSTR_PASSPHRASE_PIN_ENTERED),
11741229
MP_ROM_INT(PASSPHRASE_PIN_ENTERED)},

core/embed/trezorhal/se_thd89.c

Lines changed: 69 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "common.h"
55
#include "flash.h"
6+
#include "irq.h"
67
#include "memzero.h"
78
#include "secbool.h"
89

@@ -263,15 +264,30 @@ static secbool se_transmit_mac_ex(uint8_t addr, uint8_t *session_key,
263264

264265
secbool se_transmit_mac(uint8_t ins, uint8_t p1, uint8_t p2, uint8_t *data,
265266
uint16_t data_len, uint8_t *recv, uint16_t *recv_len) {
266-
return se_transmit_mac_ex(THD89_MASTER_ADDRESS, se_session_key, ins, p1, p2,
267-
data, data_len, recv, recv_len);
267+
uint32_t irq = disable_irq();
268+
thd89_irq_nest++;
269+
secbool result = se_transmit_mac_ex(THD89_MASTER_ADDRESS, se_session_key, ins,
270+
p1, p2, data, data_len, recv, recv_len);
271+
thd89_irq_nest--;
272+
if (thd89_irq_nest == 0) {
273+
enable_irq(irq);
274+
}
275+
return result;
268276
}
269277

270278
secbool se_fp_transmit_mac(uint8_t ins, uint8_t p1, uint8_t p2, uint8_t *data,
271279
uint16_t data_len, uint8_t *recv,
272280
uint16_t *recv_len) {
273-
return se_transmit_mac_ex(THD89_FINGER_ADDRESS, se_fp_session_key, ins, p1,
274-
p2, data, data_len, recv, recv_len);
281+
uint32_t irq = disable_irq();
282+
thd89_irq_nest++;
283+
secbool result =
284+
se_transmit_mac_ex(THD89_FINGER_ADDRESS, se_fp_session_key, ins, p1, p2,
285+
data, data_len, recv, recv_len);
286+
thd89_irq_nest--;
287+
if (thd89_irq_nest == 0) {
288+
enable_irq(irq);
289+
}
290+
return result;
275291
}
276292

277293
secbool se_random_encrypted(uint8_t *rand, uint16_t len) {
@@ -1478,6 +1494,47 @@ secbool se_get_pin_passphrase_space(uint8_t *space) {
14781494
return sectrue;
14791495
}
14801496

1497+
secbool se_change_pin_passphrase_ex(uint8_t addr, uint8_t *session_key,
1498+
const char *old_pin, const char *new_pin) {
1499+
uint8_t buf[128];
1500+
uint8_t resp[1];
1501+
uint16_t resp_len = 1;
1502+
1503+
if (strlen(old_pin) < 6 || strlen(old_pin) > PIN_MAX_LENGTH ||
1504+
strlen(new_pin) < 6 || strlen(new_pin) > PIN_MAX_LENGTH) {
1505+
return secfalse;
1506+
}
1507+
1508+
buf[0] = strlen(old_pin);
1509+
memcpy(buf + 1, (uint8_t *)old_pin, strlen(old_pin));
1510+
buf[1 + strlen(old_pin)] = strlen(new_pin);
1511+
memcpy(buf + 1 + strlen(old_pin) + 1, (uint8_t *)new_pin, strlen(new_pin));
1512+
1513+
if (!se_transmit_mac_ex(addr, session_key, SE_INS_PIN, 0x00, 0x0E, buf,
1514+
1 + strlen(old_pin) + 1 + strlen(new_pin), resp,
1515+
&resp_len)) {
1516+
return secfalse;
1517+
}
1518+
if (resp[0] == PIN_SUCCESS) {
1519+
return sectrue;
1520+
}
1521+
return secfalse;
1522+
}
1523+
1524+
secbool se_change_pin_passphrase(const char *old_pin, const char *new_pin) {
1525+
secbool result = se_change_pin_passphrase_ex(
1526+
THD89_MASTER_ADDRESS, se_session_key, old_pin, new_pin);
1527+
if (result == sectrue) {
1528+
secbool fp_result = se_change_pin_passphrase_ex(
1529+
THD89_FINGER_ADDRESS, se_fp_session_key, old_pin, new_pin);
1530+
if (fp_result == sectrue) {
1531+
return sectrue;
1532+
}
1533+
return secfalse;
1534+
}
1535+
return secfalse;
1536+
}
1537+
14811538
pin_result_t se_get_pin_result_type(void) { return pin_result_type; }
14821539
pin_result_t se_get_pin_passphrase_ret(void) { return pin_passphrase_ret; }
14831540

@@ -1959,6 +2016,14 @@ secbool se_session_get_type(uint8_t *type) {
19592016
return sectrue;
19602017
}
19612018

2019+
secbool se_session_get_current_id(uint8_t id[32]) {
2020+
uint16_t recv_len = 32;
2021+
if (!se_transmit_mac(SE_INS_SESSION, 0x00, 0x0A, NULL, 0, id, &recv_len)) {
2022+
return secfalse;
2023+
}
2024+
return sectrue;
2025+
}
2026+
19622027
secbool se_node_sign_digest(const uint8_t *hash, uint8_t *sig, uint8_t *by) {
19632028
uint8_t resp[68];
19642029
uint16_t resp_len = sizeof(resp);

core/embed/trezorhal/se_thd89.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ typedef enum {
4040
PIN_TYPE_USER_AND_PASSPHRASE_PIN,
4141
PIN_TYPE_PASSPHRASE_PIN,
4242
PIN_TYPE_PASSPHRASE_PIN_CHECK,
43+
PIN_TYPE_USER_AND_PASSPHRASE_PIN_CHECK,
4344
PIN_TYPE_MAX
4445
} pin_type_t;
4546

@@ -120,6 +121,7 @@ secbool se_delete_pin_passphrase(const char *passphrase_pin, bool *current);
120121
pin_result_t se_get_pin_passphrase_ret(void);
121122
secbool se_get_pin_passphrase_space(uint8_t *space);
122123
secbool se_check_passphrase_btc_test_address(const char *address);
124+
secbool se_change_pin_passphrase(const char *old_pin, const char *new_pin);
123125
secbool se_clearSecsta(void);
124126
secbool se_getSecsta(void);
125127
secbool se_set_u2f_counter(uint32_t u2fcounter);
@@ -137,6 +139,7 @@ secbool se_session_is_open(void);
137139
secbool se_sessionClose(void);
138140
secbool se_sessionClear(void);
139141
secbool se_session_get_type(uint8_t *type);
142+
secbool se_session_get_current_id(uint8_t id[32]);
140143

141144
secbool se_set_public_region(uint16_t offset, const void *val_dest,
142145
uint16_t len);

core/embed/trezorhal/thd89.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -538,8 +538,8 @@ int i2c_master_recive(I2C_HandleTypeDef *hi2c, uint16_t DevAddress,
538538
}
539539
}
540540

541-
secbool thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len,
542-
uint8_t *resp, uint16_t *resp_len) {
541+
static secbool _thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len,
542+
uint8_t *resp, uint16_t *resp_len) {
543543
int ret = 0;
544544
char err_info[64] = {0};
545545
uint32_t irq = disable_irq();
@@ -553,7 +553,6 @@ secbool thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len,
553553
return secfalse;
554554
}
555555

556-
delay_ms(1);
557556
irq = disable_irq();
558557
ret =
559558
i2c_master_recive(&i2c_handle_se, addr, resp, resp_len, I2C_RECV_TIMEOUT);
@@ -577,6 +576,20 @@ secbool thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len,
577576
return sectrue;
578577
}
579578

579+
int thd89_irq_nest = 0;
580+
581+
secbool thd89_transmit_ex(uint8_t addr, uint8_t *cmd, uint16_t len,
582+
uint8_t *resp, uint16_t *resp_len) {
583+
uint32_t irq = disable_irq();
584+
thd89_irq_nest++;
585+
secbool result = _thd89_transmit_ex(addr, cmd, len, resp, resp_len);
586+
thd89_irq_nest--;
587+
if (thd89_irq_nest == 0) {
588+
enable_irq(irq);
589+
}
590+
return result;
591+
}
592+
580593
secbool thd89_transmit(uint8_t *cmd, uint16_t len, uint8_t *resp,
581594
uint16_t *resp_len) {
582595
return thd89_transmit_ex(THD89_MASTER_ADDRESS, cmd, len, resp, resp_len);

core/embed/trezorhal/thd89.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#define THD89_MASTER_ADDRESS THD89_1ST_ADDRESS
1212
#define THD89_FINGER_ADDRESS THD89_4TH_ADDRESS
1313

14+
extern int thd89_irq_nest;
15+
1416
void thd89_io_init(void);
1517
void thd89_init(void);
1618
void thd89_power_up(bool up);

core/mocks/generated/trezorcrypto/se_thd89.pyi

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,13 @@ def get_session_state() -> bytes:
5353
"""
5454

5555

56+
# extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h
57+
def get_session_current_id() -> bytes:
58+
"""
59+
get current session id.
60+
"""
61+
62+
5663
# extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h
5764
def session_is_open() -> bool:
5865
"""
@@ -331,4 +338,12 @@ def check_passphrase_btc_test_address(address: str) -> bool:
331338
"""
332339
Check if the passphrase is a valid Bitcoin test address.
333340
"""
341+
342+
343+
# extmod/modtrezorcrypto/modtrezorcrypto-se-thd89.h
344+
def change_pin_passphrase(old_pin: str, new_pin: str) -> bool:
345+
"""
346+
Change the PIN of an existing passphrase entry.
347+
Returns True on success, False on failure.
348+
"""
334349
FIDO2_CRED_COUNT_MAX: int

core/src/apps/base.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,7 @@ def get_onekey_features() -> OnekeyFeatures:
247247
async def handle_Initialize(
248248
ctx: wire.Context | wire.QRContext, msg: Initialize
249249
) -> Features:
250+
session_id_in_msg = getattr(msg, "session_id", None)
250251
has_attach = (
251252
hasattr(msg, "is_contains_attach") and msg.is_contains_attach is not None
252253
)
@@ -262,13 +263,20 @@ async def handle_Initialize(
262263
else:
263264
passphrase_state = None
264265

265-
session_id_in_msg = getattr(msg, "session_id", None)
266266
if passphrase_state and se_thd89.check_passphrase_btc_test_address(
267267
passphrase_state
268268
):
269-
session_id = storage.cache.start_session()
269+
session_id = se_thd89.get_session_current_id()
270+
if device_is_unlocked() and not storage.device.is_passphrase_pin_enabled():
271+
session_id = storage.cache.start_session(session_id_in_msg)
272+
elif session_id_in_msg == session_id:
273+
session_id = storage.cache.start_session(session_id_in_msg)
274+
else:
275+
session_id = storage.cache.start_session()
270276
elif has_attach and session_id_in_msg is not None and passphrase_state is None:
271277
session_id = storage.cache.start_session()
278+
elif device_is_unlocked() and storage.device.is_passphrase_pin_enabled():
279+
session_id = storage.cache.start_session()
272280
else:
273281
session_id = storage.cache.start_session(session_id_in_msg)
274282

@@ -606,6 +614,7 @@ async def unlock_device(
606614
ctx: wire.GenericContext = wire.DUMMY_CONTEXT,
607615
pin_use_type: int = PinType.USER_AND_PASSPHRASE_PIN,
608616
attach_wall_only: bool = False,
617+
allow_fingerprint: bool = True,
609618
) -> None:
610619
from apps.common.request_pin import verify_user_pin, verify_user_fingerprint
611620

@@ -627,11 +636,13 @@ async def unlock_device(
627636
close_others=False,
628637
pin_use_type=pin_use_type_int,
629638
attach_wall_only=attach_wall_only,
639+
allow_fingerprint=allow_fingerprint,
630640
)
631641
verify_finger = verify_user_fingerprint(ctx)
632642
racer = loop.race(verify_pin, verify_finger)
633643
await racer
634644
if verify_finger in racer.finished:
645+
635646
from trezor.lvglui.scrs.pinscreen import InputPin
636647

637648
pin_wind = InputPin.get_window_if_visible()
@@ -698,25 +709,15 @@ async def handle_GetPassphraseState(
698709

699710
if not device_is_unlocked():
700711
await unlock_device(ctx, pin_use_type=PinType.USER_AND_PASSPHRASE_PIN)
701-
session_id = storage.cache.start_session()
702-
703-
from trezor.lvglui.scrs import fingerprints
704712

705-
if (
706-
fingerprints.is_available()
707-
and fingerprints.is_unlocked()
708-
and not config.is_unlocked()
709-
):
710-
if storage.device.is_passphrase_pin_enabled():
711-
storage.device.set_passphrase_pin_enabled(False)
713+
session_id = se_thd89.get_session_current_id()
714+
if session_id is None or session_id == b"":
715+
session_id = storage.cache.start_session()
712716

713717
import utime
714718
from apps.bitcoin.get_address import get_address as btc_get_address
715719

716720
try:
717-
session_id = storage.cache.get_session_id()
718-
if session_id is None or session_id == b"":
719-
session_id = storage.cache.start_session()
720721
utime.sleep_ms(500)
721722
fixed_path = "m/44'/1'/0'/0/0"
722723
address_msg = messages.GetAddress(
@@ -727,9 +728,6 @@ async def handle_GetPassphraseState(
727728
)
728729

729730
address_obj = await btc_get_address(ctx, address_msg)
730-
session_id = storage.cache.get_session_id()
731-
if session_id is None or session_id == b"":
732-
session_id = storage.cache.start_session()
733731
is_attach_to_pin_state = passphrase.is_passphrase_pin_enabled()
734732
return PassphraseState(
735733
passphrase_state=address_obj.address,

core/src/apps/common/passphrase.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,10 @@ async def _request_on_host(ctx: wire.Context) -> str:
8181
from apps.common.pin_constants import PinType
8282

8383
await unlock_device(
84-
ctx, pin_use_type=PinType.PASSPHRASE_PIN, attach_wall_only=True
84+
ctx,
85+
pin_use_type=PinType.PASSPHRASE_PIN,
86+
attach_wall_only=True,
87+
allow_fingerprint=False,
8588
)
8689
storage.cache.start_session()
8790
return ""

0 commit comments

Comments
 (0)