mirror of
https://github.com/trezor/trezor-firmware.git
synced 2025-05-21 16:28:46 +00:00
firmware: implement behaviour of state (still missing in PassphraseAck)
This commit is contained in:
parent
d7de064bde
commit
7fa8ae136f
@ -232,10 +232,15 @@ static bool fsm_layoutAddress(const char *address, const char *desc, bool ignore
|
|||||||
|
|
||||||
void fsm_msgInitialize(Initialize *msg)
|
void fsm_msgInitialize(Initialize *msg)
|
||||||
{
|
{
|
||||||
(void)msg;
|
|
||||||
recovery_abort();
|
recovery_abort();
|
||||||
signing_abort();
|
signing_abort();
|
||||||
session_clear(false); // do not clear PIN
|
if (msg->has_state && msg->state.size == 64) {
|
||||||
|
if (!session_compareState(msg->state.bytes)) {
|
||||||
|
session_clear(false); // do not clear PIN
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
session_clear(false); // do not clear PIN
|
||||||
|
}
|
||||||
layoutHome();
|
layoutHome();
|
||||||
fsm_msgGetFeatures(0);
|
fsm_msgGetFeatures(0);
|
||||||
}
|
}
|
||||||
@ -301,6 +306,8 @@ void fsm_msgGetFeatures(GetFeatures *msg)
|
|||||||
resp->has_needs_backup = true; resp->needs_backup = storage_needsBackup();
|
resp->has_needs_backup = true; resp->needs_backup = storage_needsBackup();
|
||||||
resp->has_flags = true; resp->flags = storage_getFlags();
|
resp->has_flags = true; resp->flags = storage_getFlags();
|
||||||
resp->has_model = true; strlcpy(resp->model, "1", sizeof(resp->model));
|
resp->has_model = true; strlcpy(resp->model, "1", sizeof(resp->model));
|
||||||
|
resp->has_state = true; resp->state.size = 64; session_getState(NULL, resp->state.bytes);
|
||||||
|
|
||||||
msg_write(MessageType_MessageType_Features, resp);
|
msg_write(MessageType_MessageType_Features, resp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,6 +253,7 @@ bool protectPassphrase(void)
|
|||||||
bool result;
|
bool result;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
usbPoll();
|
usbPoll();
|
||||||
|
// TODO: correctly process PassphraseAck with state field set (mismatch => Failure)
|
||||||
if (msg_tiny_id == MessageType_MessageType_PassphraseAck) {
|
if (msg_tiny_id == MessageType_MessageType_PassphraseAck) {
|
||||||
msg_tiny_id = 0xFFFF;
|
msg_tiny_id = 0xFFFF;
|
||||||
PassphraseAck *ppa = (PassphraseAck *)msg_tiny;
|
PassphraseAck *ppa = (PassphraseAck *)msg_tiny;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
Initialize.state max_size:32
|
Initialize.state max_size:64
|
||||||
|
|
||||||
Features.vendor max_size:33
|
Features.vendor max_size:33
|
||||||
Features.device_id max_size:25
|
Features.device_id max_size:25
|
||||||
@ -10,7 +10,7 @@ Features.bootloader_hash max_size:32
|
|||||||
Features.model max_size:17
|
Features.model max_size:17
|
||||||
Features.fw_vendor max_size:256
|
Features.fw_vendor max_size:256
|
||||||
Features.fw_vendor_keys max_size:32
|
Features.fw_vendor_keys max_size:32
|
||||||
Features.state max_size:32
|
Features.state max_size:64
|
||||||
|
|
||||||
ApplySettings.language max_size:17
|
ApplySettings.language max_size:17
|
||||||
ApplySettings.label max_size:33
|
ApplySettings.label max_size:33
|
||||||
@ -27,7 +27,7 @@ ButtonRequest.data max_size:256
|
|||||||
PinMatrixAck.pin max_size:10
|
PinMatrixAck.pin max_size:10
|
||||||
|
|
||||||
PassphraseAck.passphrase max_size:51
|
PassphraseAck.passphrase max_size:51
|
||||||
PassphraseAck.state max_size:32
|
PassphraseAck.state max_size:64
|
||||||
|
|
||||||
Entropy.entropy max_size:1024
|
Entropy.entropy max_size:1024
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include "sha2.h"
|
#include "sha2.h"
|
||||||
#include "aes/aes.h"
|
#include "aes/aes.h"
|
||||||
#include "pbkdf2.h"
|
#include "pbkdf2.h"
|
||||||
|
#include "hmac.h"
|
||||||
#include "bip32.h"
|
#include "bip32.h"
|
||||||
#include "bip39.h"
|
#include "bip39.h"
|
||||||
#include "curves.h"
|
#include "curves.h"
|
||||||
@ -124,6 +125,9 @@ static bool sessionPinCached;
|
|||||||
static bool sessionPassphraseCached;
|
static bool sessionPassphraseCached;
|
||||||
static char CONFIDENTIAL sessionPassphrase[51];
|
static char CONFIDENTIAL sessionPassphrase[51];
|
||||||
|
|
||||||
|
static bool sessionStateSaltSet;
|
||||||
|
static uint8_t sessionStateSalt[32];
|
||||||
|
|
||||||
#define STORAGE_VERSION 9
|
#define STORAGE_VERSION 9
|
||||||
|
|
||||||
void storage_show_error(void)
|
void storage_show_error(void)
|
||||||
@ -266,6 +270,8 @@ void session_clear(bool clear_pin)
|
|||||||
memzero(&sessionSeed, sizeof(sessionSeed));
|
memzero(&sessionSeed, sizeof(sessionSeed));
|
||||||
sessionPassphraseCached = false;
|
sessionPassphraseCached = false;
|
||||||
memzero(&sessionPassphrase, sizeof(sessionPassphrase));
|
memzero(&sessionPassphrase, sizeof(sessionPassphrase));
|
||||||
|
sessionStateSaltSet = false;
|
||||||
|
memzero(&sessionStateSalt, sizeof(sessionStateSalt));
|
||||||
if (clear_pin) {
|
if (clear_pin) {
|
||||||
sessionPinCached = false;
|
sessionPinCached = false;
|
||||||
}
|
}
|
||||||
@ -709,6 +715,47 @@ bool session_isPassphraseCached(void)
|
|||||||
return sessionPassphraseCached;
|
return sessionPassphraseCached;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void session_getState(const uint8_t *salt, uint8_t *state)
|
||||||
|
{
|
||||||
|
if (!salt) {
|
||||||
|
if (!sessionStateSaltSet) {
|
||||||
|
// generate a random salt if not provided and not already cached
|
||||||
|
random_buffer(sessionStateSalt, 32);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// otherwise copy provided salt to cached salt
|
||||||
|
memcpy(sessionStateSalt, salt, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionStateSaltSet = true;
|
||||||
|
|
||||||
|
// state[0:32] = salt
|
||||||
|
memcpy(state, sessionStateSalt, 32);
|
||||||
|
|
||||||
|
// state[32:64] = HMAC(passphrase, salt || device_id)
|
||||||
|
HMAC_SHA256_CTX ctx;
|
||||||
|
if (sessionPassphraseCached) {
|
||||||
|
hmac_sha256_Init(&ctx, (const uint8_t *)sessionPassphrase, strlen(sessionPassphrase));
|
||||||
|
} else {
|
||||||
|
hmac_sha256_Init(&ctx, (const uint8_t *)"", 0);
|
||||||
|
}
|
||||||
|
hmac_sha256_Update(&ctx, sessionStateSalt, 32);
|
||||||
|
hmac_sha256_Update(&ctx, (const uint8_t *)storage_uuid, sizeof(storage_uuid));
|
||||||
|
hmac_sha256_Final(&ctx, state + 32);
|
||||||
|
|
||||||
|
memzero(&ctx, sizeof(ctx));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool session_compareState(const uint8_t *state)
|
||||||
|
{
|
||||||
|
if (!state) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
uint8_t istate[64];
|
||||||
|
session_getState(state, istate);
|
||||||
|
return 0 == memcmp(state, istate, 64);
|
||||||
|
}
|
||||||
|
|
||||||
void session_cachePin(void)
|
void session_cachePin(void)
|
||||||
{
|
{
|
||||||
sessionPinCached = true;
|
sessionPinCached = true;
|
||||||
|
@ -103,6 +103,8 @@ void storage_setHomescreen(const uint8_t *data, uint32_t size);
|
|||||||
|
|
||||||
void session_cachePassphrase(const char *passphrase);
|
void session_cachePassphrase(const char *passphrase);
|
||||||
bool session_isPassphraseCached(void);
|
bool session_isPassphraseCached(void);
|
||||||
|
void session_getState(const uint8_t *salt, uint8_t *state);
|
||||||
|
bool session_compareState(const uint8_t *state);
|
||||||
|
|
||||||
void storage_setMnemonic(const char *mnemonic);
|
void storage_setMnemonic(const char *mnemonic);
|
||||||
bool storage_containsMnemonic(const char *mnemonic);
|
bool storage_containsMnemonic(const char *mnemonic);
|
||||||
|
Loading…
Reference in New Issue
Block a user