const char *requestPin(PinMatrixRequestType type, const char *text) { PinMatrixRequest resp; memset(&resp, 0, sizeof(PinMatrixRequest)); resp.has_type = true; resp.type = type; usbTiny(1); msg_write(MessageType_MessageType_PinMatrixRequest, &resp); pinmatrix_start(text); for (;;) { usbPoll(); if (msg_tiny_id == MessageType_MessageType_PinMatrixAck) { msg_tiny_id = 0xFFFF; PinMatrixAck *pma = (PinMatrixAck *)msg_tiny; pinmatrix_done(pma->pin); // convert via pinmatrix usbTiny(0); return pma->pin; } 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); return 0; } #if DEBUG_LINK if (msg_tiny_id == MessageType_MessageType_DebugLinkGetState) { msg_tiny_id = 0xFFFF; fsm_msgDebugLinkGetState((DebugLinkGetState *)msg_tiny); } #endif } }
bool protectPin(bool use_cached) { if (!storage.has_pin || storage.pin[0] == 0 || (use_cached && session_isPinCached())) { return true; } uint32_t *fails = storage_getPinFailsPtr(); uint32_t wait = ~*fails; protectCheckMaxTry(wait); usbTiny(1); while (wait > 0) { // convert wait to secstr string char secstrbuf[20]; strlcpy(secstrbuf, _("________0 seconds"), sizeof(secstrbuf)); char *secstr = secstrbuf + 9; uint32_t secs = wait; while (secs > 0 && secstr >= secstrbuf) { secstr--; *secstr = (secs % 10) + '0'; secs /= 10; } if (wait == 1) { secstrbuf[16] = 0; } layoutDialog(&bmp_icon_info, NULL, NULL, NULL, _("Wrong PIN entered"), NULL, _("Please wait"), secstr, _("to continue ..."), NULL); // wait one second usbSleep(1000); if (msg_tiny_id == MessageType_MessageType_Initialize) { protectAbortedByInitialize = true; msg_tiny_id = 0xFFFF; usbTiny(0); fsm_sendFailure(FailureType_Failure_PinCancelled, NULL); return false; } wait--; } usbTiny(0); const char *pin; pin = requestPin(PinMatrixRequestType_PinMatrixRequestType_Current, _("Please enter current PIN:")); if (!pin) { fsm_sendFailure(FailureType_Failure_PinCancelled, NULL); return false; } if (!storage_increasePinFails(fails)) { fsm_sendFailure(FailureType_Failure_PinInvalid, NULL); return false; } if (storage_containsPin(pin)) { session_cachePin(); storage_resetPinFails(fails); return true; } else { protectCheckMaxTry(~*fails); fsm_sendFailure(FailureType_Failure_PinInvalid, NULL); return false; } }
bool protectPassphrase(void) { if (!storage.has_passphrase_protection || !storage.passphrase_protection || session_isPassphraseCached()) { return true; } PassphraseRequest resp; memset(&resp, 0, sizeof(PassphraseRequest)); usbTiny(1); msg_write(MessageType_MessageType_PassphraseRequest, &resp); layoutDialogSwipe(DIALOG_ICON_INFO, NULL, NULL, NULL, "Please enter your", "passphrase using", "the computer's", "keyboard.", NULL, NULL); bool result; for (;;) { usbPoll(); if (msg_tiny_id == MessageType_MessageType_PassphraseAck) { msg_tiny_id = 0xFFFF; PassphraseAck *ppa = (PassphraseAck *)msg_tiny; session_cachePassphrase(ppa->passphrase); result = true; break; } if (msg_tiny_id == MessageType_MessageType_Cancel || msg_tiny_id == MessageType_MessageType_Initialize) { if (msg_tiny_id == MessageType_MessageType_Initialize) { protectAbortedByInitialize = true; } msg_tiny_id = 0xFFFF; result = false; break; } } usbTiny(0); layoutHome(); return result; }
void u2fhid_read_start(const U2FHID_FRAME *f) { U2F_ReadBuffer readbuffer; memzero(&readbuffer, sizeof(readbuffer)); if (!(f->type & TYPE_INIT)) { return; } // Broadcast is reserved for init if (f->cid == CID_BROADCAST || f->cid == 0) { send_u2fhid_error(f->cid, ERR_INVALID_CID); return; } if ((unsigned)MSG_LEN(*f) > sizeof(reader->buf)) { send_u2fhid_error(f->cid, ERR_INVALID_LEN); return; } reader = &readbuffer; u2fhid_init_cmd(f); usbTiny(1); for(;;) { // Do we need to wait for more data while ((reader->buf_ptr - reader->buf) < (signed)reader->len) { uint8_t lastseq = reader->seq; uint8_t lastcmd = reader->cmd; int counter = U2F_TIMEOUT; while (reader->seq == lastseq && reader->cmd == lastcmd) { if (counter-- == 0) { // timeout send_u2fhid_error(cid, ERR_MSG_TIMEOUT); cid = 0; reader = 0; usbTiny(0); layoutHome(); return; } usbPoll(); } } // We have all the data switch (reader->cmd) { case 0: // message was aborted by init break; case U2FHID_PING: u2fhid_ping(reader->buf, reader->len); break; case U2FHID_MSG: u2fhid_msg((APDU *)reader->buf, reader->len); break; case U2FHID_WINK: u2fhid_wink(reader->buf, reader->len); break; default: send_u2fhid_error(cid, ERR_INVALID_CMD); break; } // wait for next commmand/ button press reader->cmd = 0; reader->seq = 255; while (dialog_timeout > 0 && reader->cmd == 0) { dialog_timeout--; usbPoll(); // may trigger new request //buttonUpdate(); if (keepkey_button_down() && (last_req_state == AUTH || last_req_state == REG)) { last_req_state++; // standard requires to remember button press for 10 seconds. dialog_timeout = 10 * U2F_TIMEOUT; } } if (reader->cmd == 0) { last_req_state = INIT; cid = 0; reader = 0; usbTiny(0); layoutHome(); return; } } }
bool protectButton(ButtonRequestType type, bool confirm_only) { ButtonRequest resp; bool result = false; bool acked = false; #if DEBUG_LINK bool debug_decided = false; #endif memset(&resp, 0, sizeof(ButtonRequest)); resp.has_code = true; resp.code = type; usbTiny(1); msg_write(MessageType_MessageType_ButtonRequest, &resp); for (;;) { usbPoll(); // check for ButtonAck if (msg_tiny_id == MessageType_MessageType_ButtonAck) { msg_tiny_id = 0xFFFF; acked = true; } // button acked - check buttons if (acked) { usbDelay(3500); buttonUpdate(); if (button.YesUp) { result = true; break; } if (!confirm_only && button.NoUp) { result = false; break; } } // check for Cancel / Initialize if (msg_tiny_id == MessageType_MessageType_Cancel || msg_tiny_id == MessageType_MessageType_Initialize) { if (msg_tiny_id == MessageType_MessageType_Initialize) { protectAbortedByInitialize = true; } msg_tiny_id = 0xFFFF; result = false; break; } #if DEBUG_LINK // check DebugLink if (msg_tiny_id == MessageType_MessageType_DebugLinkDecision) { msg_tiny_id = 0xFFFF; DebugLinkDecision *dld = (DebugLinkDecision *)msg_tiny; result = dld->yes_no; debug_decided = true; } if (acked && debug_decided) { break; } if (msg_tiny_id == MessageType_MessageType_DebugLinkGetState) { msg_tiny_id = 0xFFFF; fsm_msgDebugLinkGetState((DebugLinkGetState *)msg_tiny); } #endif } usbTiny(0); return result; }