Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

invalid response on cancel fixes #381 #382

Open
wants to merge 10 commits into
base: develop
Choose a base branch
from
101 changes: 54 additions & 47 deletions tiny-firmware/bootloader/usb.c
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ static int hid_control_request(usbd_device* dev, struct usb_setup_data* req, uin
enum {
STATE_READY,
STATE_OPEN,
STATE_ABOUT_TO_FLASHSTART,
STATE_FLASHSTART,
STATE_FLASHING,
STATE_CHECK,
Expand Down Expand Up @@ -481,59 +482,65 @@ static void hid_rx_callback(usbd_device* dev, uint8_t ep)
if (flash_state == STATE_OPEN) {
if (msg_id == 0x0006) { // FirmwareErase message (id 6)
if (!brand_new_firmware) {
layoutDialog(&bmp_icon_question, "Abort", "Continue", NULL, "Install new", "firmware?", NULL, "Never do this without", "your recovery card!", NULL);
do {
delay(100000);
buttonUpdate();
} while (!button.YesUp && !button.NoUp);
flash_state = STATE_ABOUT_TO_FLASHSTART;
send_msg_buttonrequest_firmwarecheck(dev);
return;
}
if (brand_new_firmware || button.YesUp) {
// check whether current firmware is signed
if (!brand_new_firmware && SIG_OK == signatures_ok(NULL)) {
old_was_unsigned = false;
// backup metadata
backup_metadata(meta_backup);
} else {
old_was_unsigned = true;
}
flash_wait_for_last_operation();
flash_clear_status_flags();
flash_unlock();
// erase metadata area
for (int i = FLASH_META_SECTOR_FIRST; i <= FLASH_META_SECTOR_LAST; i++) {
layoutProgress("ERASING ... Please wait", 1000 * (i - FLASH_META_SECTOR_FIRST) / (FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST));
flash_erase_sector(i, FLASH_CR_PROGRAM_X32);
}
// erase code area
for (int i = FLASH_CODE_SECTOR_FIRST; i <= FLASH_CODE_SECTOR_LAST; i++) {
layoutProgress("ERASING ... Please wait", 1000 * (i - FLASH_META_SECTOR_FIRST) / (FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST));
flash_erase_sector(i, FLASH_CR_PROGRAM_X32);
}
layoutProgress("INSTALLING ... Please wait", 0);
flash_wait_for_last_operation();
flash_lock();

// check that metadata was succesfully erased
// flash status register should show now error and
// the config block should contain only \xff.
uint8_t hash[32];
sha256_Raw((unsigned char*)FLASH_META_START, FLASH_META_LEN, hash);
if ((FLASH_SR & (FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR)) != 0 || memcmp(hash, "\x2d\x86\x4c\x0b\x78\x9a\x43\x21\x4e\xee\x85\x24\xd3\x18\x20\x75\x12\x5e\x5c\xa2\xcd\x52\x7f\x35\x82\xec\x87\xff\xd9\x40\x76\xbc", 32) != 0) {
send_msg_failure(dev);
flash_state = STATE_END;
layoutDialog(&bmp_icon_error, NULL, NULL, NULL, "Error installing ", "firmware.", NULL, "Unplug your Skywallet", "and try again.", NULL);
return;
}
}
}
if (flash_state == STATE_ABOUT_TO_FLASHSTART) {
if (!brand_new_firmware) {
layoutDialog(&bmp_icon_question, "Abort", "Continue", NULL, "Install new", "firmware?", NULL, "Never do this without", "your recovery card!", NULL);
do {
delay(100000);
buttonUpdate();
} while (!button.YesUp && !button.NoUp);
}
if (brand_new_firmware || button.YesUp) {
// check whether current firmware is signed
if (!brand_new_firmware && SIG_OK == signatures_ok(NULL)) {
old_was_unsigned = false;
// backup metadata
backup_metadata(meta_backup);
} else {
old_was_unsigned = true;
}
flash_wait_for_last_operation();
flash_clear_status_flags();
flash_unlock();
// erase metadata area
for (int i = FLASH_META_SECTOR_FIRST; i <= FLASH_META_SECTOR_LAST; i++) {
layoutProgress("ERASING ... Please wait", 1000 * (i - FLASH_META_SECTOR_FIRST) / (FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST));
flash_erase_sector(i, FLASH_CR_PROGRAM_X32);
}
// erase code area
for (int i = FLASH_CODE_SECTOR_FIRST; i <= FLASH_CODE_SECTOR_LAST; i++) {
layoutProgress("ERASING ... Please wait", 1000 * (i - FLASH_META_SECTOR_FIRST) / (FLASH_CODE_SECTOR_LAST - FLASH_META_SECTOR_FIRST));
flash_erase_sector(i, FLASH_CR_PROGRAM_X32);
}
layoutProgress("INSTALLING ... Please wait", 0);
flash_wait_for_last_operation();
flash_lock();

send_msg_success(dev);
flash_state = STATE_FLASHSTART;
// check that metadata was succesfully erased
// flash status register should show now error and
// the config block should contain only \xff.
uint8_t hash[32];
sha256_Raw((unsigned char*)FLASH_META_START, FLASH_META_LEN, hash);
if ((FLASH_SR & (FLASH_SR_PGAERR | FLASH_SR_PGPERR | FLASH_SR_PGSERR | FLASH_SR_WRPERR)) != 0 || memcmp(hash, "\x2d\x86\x4c\x0b\x78\x9a\x43\x21\x4e\xee\x85\x24\xd3\x18\x20\x75\x12\x5e\x5c\xa2\xcd\x52\x7f\x35\x82\xec\x87\xff\xd9\x40\x76\xbc", 32) != 0) {
send_msg_failure(dev);
flash_state = STATE_END;
layoutDialog(&bmp_icon_error, NULL, NULL, NULL, "Error installing ", "firmware.", NULL, "Unplug your Skywallet", "and try again.", NULL);
return;
}
send_msg_failure(dev);
flash_state = STATE_END;
layoutDialog(&bmp_icon_warning, NULL, NULL, NULL, "Firmware installation", "aborted.", NULL, "You may now", "unplug your Skywallet.", NULL);

send_msg_success(dev);
flash_state = STATE_FLASHSTART;
return;
}
send_msg_failure(dev);
flash_state = STATE_END;
layoutDialog(&bmp_icon_warning, NULL, NULL, NULL, "Firmware installation", "aborted.", NULL, "You may now", "unplug your Skywallet.", NULL);
return;
}

Expand Down
18 changes: 12 additions & 6 deletions tiny-firmware/firmware/fsm_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -535,18 +535,24 @@ ErrCode_t msgPingImpl(Ping* msg)
return ErrOk;
}

ErrCode_t msgChangePinImpl(ChangePin* msg, const char* (*funcRequestPin)(PinMatrixRequestType, const char*))
ErrCode_t msgChangePinImpl(ChangePin* msg, ErrCode_t (*funcRequestPin)(PinMatrixRequestType, const char*, char*))
{
bool removal = msg->has_remove && msg->remove;
if (removal) {
storage_setPin("");
storage_update();
} else {
if (!protectChangePinEx(funcRequestPin)) {
return ErrPinMismatch;
}
return ErrOk;
}
ErrCode_t err = protectChangePinEx(funcRequestPin);
switch (err) {
case ErrPinRequired:
case ErrPinCancelled:
case ErrPinMismatch:
case ErrOk:
return err;
default:
return ErrUnexpectedMessage;
}
return ErrOk;
}

ErrCode_t msgWipeDeviceImpl(WipeDevice* msg)
Expand Down
2 changes: 1 addition & 1 deletion tiny-firmware/firmware/fsm_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,7 @@ ErrCode_t msgGetFeaturesImpl(Features* resp);

ErrCode_t msgPingImpl(Ping* msg);

ErrCode_t msgChangePinImpl(ChangePin* msg, const char* (*)(PinMatrixRequestType, const char*));
ErrCode_t msgChangePinImpl(ChangePin* msg, ErrCode_t (*)(PinMatrixRequestType, const char*, char*));

ErrCode_t msgWipeDeviceImpl(WipeDevice* msg);

Expand Down
93 changes: 68 additions & 25 deletions tiny-firmware/firmware/protect.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ bool protectButton(ButtonRequestType type, bool confirm_only)
return result;
}

const char* requestPin(PinMatrixRequestType type, const char* text)
ErrCode_t requestPin(PinMatrixRequestType type, const char* text, char* out_pin)
{
PinMatrixRequest resp;
memset(&resp, 0, sizeof(PinMatrixRequest));
Expand All @@ -128,16 +128,23 @@ const char* requestPin(PinMatrixRequestType type, const char* text)
PinMatrixAck* pma = (PinMatrixAck*)msg_tiny;
pinmatrix_done(pma->pin); // convert via pinmatrix
usbTiny(0);
return pma->pin;
memcpy(out_pin, pma->pin, sizeof(pma->pin));
return ErrOk;
}
if (msg_tiny_id == MessageType_MessageType_Cancel || msg_tiny_id == MessageType_MessageType_Initialize) {
pinmatrix_done(0);
if (msg_tiny_id == MessageType_MessageType_Initialize) {
protectAbortedByInitialize = true;
msg_tiny_id = 0xFFFF;
usbTiny(0);
// TODO what does means Initialize here?
return ErrOk;
}
if (msg_tiny_id == MessageType_MessageType_Cancel) {
msg_tiny_id = 0xFFFF;
usbTiny(0);
return ErrPinCancelled;
}
msg_tiny_id = 0xFFFF;
usbTiny(0);
return 0;
}
#if DEBUG_LINK
if (msg_tiny_id == MessageType_MessageType_DebugLinkGetState) {
Expand Down Expand Up @@ -195,11 +202,20 @@ bool protectPin(bool use_cached)
wait--;
}
usbTiny(0);
const char* pin;
pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_Current, _("Please enter current PIN:"));
if (!pin) {
char pin[10] = {0};
{
PinMatrixAck pm;
_Static_assert(sizeof(pin) == sizeof(pm.pin), "invalid pin buffer size");
}
switch (requestPin(PinMatrixRequestType_PinMatrixRequestType_Current, _("Please enter current PIN:"), pin)) {
case ErrOk:
break;
case ErrPinCancelled:
fsm_sendFailure(FailureType_Failure_PinCancelled, NULL, 0);
return false;
default:
fsm_sendFailure(FailureType_Failure_UnexpectedMessage, NULL, 0);
return false;
}
if (!storage_increasePinFails(fails)) {
fsm_sendFailure(FailureType_Failure_PinInvalid, NULL, 0);
Expand All @@ -221,33 +237,60 @@ bool protectChangePin()
return protectChangePinEx(NULL);
}

bool protectChangePinEx(const char* (*funcRequestPin)(PinMatrixRequestType, const char*))
ErrCode_t protectChangePinEx(ErrCode_t (*funcRequestPin)(PinMatrixRequestType, const char*, char*))
{
static CONFIDENTIAL char pin_compare[17];
memset(pin_compare, 0, sizeof(pin_compare));
if (funcRequestPin == NULL) {
funcRequestPin = requestPin;
}

const char* pin = funcRequestPin(PinMatrixRequestType_PinMatrixRequestType_NewFirst, _("Please enter new PIN:"));

if (!pin) {
return false;
static CONFIDENTIAL char pin[10] = {0};
memset(pin, 0, sizeof(pin));
{
PinMatrixAck pm;
_Static_assert(sizeof(pin) == sizeof(pm.pin), "invalid pin buffer size");
}
ErrCode_t err = funcRequestPin(PinMatrixRequestType_PinMatrixRequestType_NewFirst, _("Please enter new PIN:"), pin);
if (err != ErrOk) {
memset(pin_compare, 0, sizeof(pin_compare));
memset(pin, 0, sizeof(pin));
return err;
}
{
char empty_pin[sizeof(pin)] = {0};
if (!memcmp(pin, empty_pin, sizeof(pin))) {
memset(pin_compare, 0, sizeof(pin_compare));
memset(pin, 0, sizeof(pin));
return ErrPinRequired;
}
}

strlcpy(pin_compare, pin, sizeof(pin_compare));

pin = funcRequestPin(PinMatrixRequestType_PinMatrixRequestType_NewSecond, _("Please re-enter new PIN:"));

const bool result = pin && *pin && (strncmp(pin_compare, pin, sizeof(pin_compare)) == 0);

if (result) {
memset(pin, 0, sizeof(pin));
err = funcRequestPin(PinMatrixRequestType_PinMatrixRequestType_NewSecond, _("Please re-enter new PIN:"), pin);
if (err != ErrOk) {
memset(pin_compare, 0, sizeof(pin_compare));
memset(pin, 0, sizeof(pin));
return err;
}
{
char empty_pin[sizeof(pin)] = {0};
if (!memcmp(pin, empty_pin, sizeof(pin))) {
memset(pin_compare, 0, sizeof(pin_compare));
memset(pin, 0, sizeof(pin));
return ErrPinRequired;
}
}
if (strncmp(pin_compare, pin, sizeof(pin_compare)) == 0) {
storage_setPin(pin_compare);
storage_update();
} else {
memset(pin_compare, 0, sizeof(pin_compare));
memset(pin, 0, sizeof(pin));
return ErrPinMismatch;
}

memzero(pin_compare, sizeof(pin_compare));

return result;
memset(pin_compare, 0, sizeof(pin_compare));
memset(pin, 0, sizeof(pin));
return ErrOk;
}

bool protectPassphrase(void)
Expand Down
11 changes: 6 additions & 5 deletions tiny-firmware/firmware/protect.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef __PROTECT_H__
#define __PROTECT_H__
#ifndef __PROTECT_HANDLER_H__
#define __PROTECT_HANDLER_H__

#include "tiny-firmware/firmware/error.h"
#include "types.pb.h"
#include <stdbool.h>

Expand All @@ -32,7 +33,7 @@ bool protectPassphrase(void);
extern bool protectAbortedByInitialize;

// Symbols exported for testing
bool protectChangePinEx(const char* (*)(PinMatrixRequestType, const char*));
const char* requestPin(PinMatrixRequestType type, const char* text);
ErrCode_t protectChangePinEx(ErrCode_t (*)(PinMatrixRequestType, const char*, char*));
ErrCode_t requestPin(PinMatrixRequestType type, const char* text, char* out_pin);

#endif
#endif // __PROTECT_HANDLER_H__
21 changes: 14 additions & 7 deletions tiny-firmware/firmware/reset.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ void reset_init(bool display_random, uint32_t _strength, bool passphrase_protect
reset_init_ex(display_random, _strength, passphrase_protection, pin_protection, language, label, _skip_backup, NULL);
}

void reset_init_ex(bool display_random, uint32_t _strength, bool passphrase_protection, bool pin_protection, const char* language, const char* label, bool _skip_backup, const char* (*funcRequestPin)(PinMatrixRequestType, const char*))
void reset_init_ex(bool display_random, uint32_t _strength, bool passphrase_protection, bool pin_protection, const char* language, const char* label, bool _skip_backup, ErrCode_t (*funcRequestPin)(PinMatrixRequestType, const char*, char*))
{
if (funcRequestPin == NULL) {
funcRequestPin = requestPin;
Expand Down Expand Up @@ -70,13 +70,20 @@ void reset_init_ex(bool display_random, uint32_t _strength, bool passphrase_prot
return;
}
}

if (pin_protection && !protectChangePinEx(funcRequestPin)) {
fsm_sendFailure(FailureType_Failure_PinMismatch, NULL, 0);
layoutHome();
return;
if (pin_protection) {
ErrCode_t err = protectChangePinEx(funcRequestPin);
switch (err) {
case ErrOk:
break;
case ErrPinMismatch:
fsm_sendFailure(FailureType_Failure_PinMismatch, NULL, 0);
layoutHome();
return;
default:
fsm_sendFailure(FailureType_Failure_UnexpectedMessage, NULL, 0);
return;
}
}

storage_setPassphraseProtection(passphrase_protection);
storage_setLanguage(language);
if (label != NULL && strcmp("", label) != 0) {
Expand Down
2 changes: 1 addition & 1 deletion tiny-firmware/firmware/reset.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,6 @@ uint32_t reset_get_int_entropy(uint8_t* entropy);
const char* reset_get_word(void);

// Functions exported or testing purposes
void reset_init_ex(bool display_random, uint32_t _strength, bool passphrase_protection, bool pin_protection, const char* language, const char* label, bool _skip_backup, const char* (*funcRequestPin)(PinMatrixRequestType mt, const char* msg));
void reset_init_ex(bool display_random, uint32_t _strength, bool passphrase_protection, bool pin_protection, const char* language, const char* label, bool _skip_backup, ErrCode_t (*funcRequestPin)(PinMatrixRequestType mt, const char* msg, char* out_pin));

#endif
Loading