From 1151672873a499d4095732f6cfc161d8af025967 Mon Sep 17 00:00:00 2001 From: cslashm Date: Wed, 15 Jan 2020 17:11:48 +0100 Subject: [PATCH] Add two levels of reset - Reset application - Reset current key slot only --- Makefile | 6 +- pytools/gpgcard/gpgcard.py | 24 ++++---- pytools/gpgcard/gpgcli.py | 22 ++++---- src/gpg_api.h | 3 +- src/gpg_dispatch.c | 12 ++++ src/gpg_init.c | 55 ++++++++++-------- src/gpg_types.h | 7 ++- src/gpg_ux_nanos.c | 113 ++++++++++--------------------------- src/gpg_ux_nanox.c | 19 +++++++ 9 files changed, 127 insertions(+), 134 deletions(-) diff --git a/Makefile b/Makefile index 595b318..2d6cfa5 100644 --- a/Makefile +++ b/Makefile @@ -44,8 +44,8 @@ ICONNAME = images/icon_pgp.gif endif APPVERSION_M:=1 -APPVERSION_N:=3 -APPVERSION_P:=3 +APPVERSION_N:=4 +APPVERSION_P:=0 APPVERSION:=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) SPECVERSION:="3.3.1" @@ -55,7 +55,7 @@ DEFINES += OPENPGP_VERSION=$(APPVERSION) DEFINES += OPENPGP_NAME=$(APPNAME) DEFINES += SPEC_VERSION=$(SPECVERSION) DEFINES += GPG_MULTISLOT=$(GPG_MULTISLOT) - +#DEFINES += GPG_LOG ifeq ($(TARGET_NAME),TARGET_NANOX) diff --git a/pytools/gpgcard/gpgcard.py b/pytools/gpgcard/gpgcard.py index 2dee1c9..59dd999 100644 --- a/pytools/gpgcard/gpgcard.py +++ b/pytools/gpgcard/gpgcard.py @@ -1,11 +1,11 @@ # Copyright 2017 Cedric Mesnil , Ledger SAS -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -171,7 +171,7 @@ class GPGCard() : data = [x for x in data] apdu = [x for x in apdu] #send - if data: + if data: while len(data) > 0xFE: apdux = apdu[0:5]+[0xfe]+data[0:0xFE] apdux[0] |= 0x10 @@ -187,7 +187,7 @@ class GPGCard() : resp, sw1, sw2 = self.connection.transmit(apdu) sw = (sw1<<8)|sw2 self.alog('recv', resp, sw) - + #receive while sw1==0x61: apdu = binascii.unhexlify(b"00c00000%.02x"%sw2) @@ -223,6 +223,10 @@ class GPGCard() : apdu = binascii.unhexlify(b"00E60000") return self.exchange(apdu) + def get_log(self): + apdu = binascii.unhexlify(b"00040000") + return self.exchange(apdu) + def get_data(self,tag): apdu = binascii.unhexlify(b"00CA%.04x00"%tag) return self.exchange(apdu) @@ -330,11 +334,11 @@ class GPGCard() : self.dec_key,sw = self.get_data(0x00B8) self.aut_key,sw = self.get_data(0x00A4) - + return True def set_all(self): - + self.put_data(0x4f, self.AID[10:14]) self.put_data(0x0101, self.private_01) self.put_data(0x0102, self.private_02) @@ -413,7 +417,7 @@ class GPGCard() : self.sig_date, self.dec_date, self.aut_date, self.cardholder_cert, self.UIF_SIG, self.UIF_DEC, self.UIF_AUT, - self.sig_key, self.dec_key, self.aut_key) = pickle.load(f) + self.sig_key, self.dec_key, self.aut_key) = pickle.load(f) self.set_all() return True @@ -424,7 +428,7 @@ class GPGCard() : self.exchange(apdu) apdu = binascii.unhexlify(b"0047800102A400") self.exchange(apdu) - + def decode_AID(self): return { @@ -556,7 +560,7 @@ class GPGCard() : #USER Info def set_serial(self, ser): ser=binascii.unhexlify(ser) - + self.AID = self.AID[0:10]+ser self.put_data(0x4f, self.AID[10:14]) diff --git a/pytools/gpgcard/gpgcli.py b/pytools/gpgcard/gpgcli.py index a2c6098..29465bb 100644 --- a/pytools/gpgcard/gpgcli.py +++ b/pytools/gpgcard/gpgcli.py @@ -1,11 +1,11 @@ # Copyright 2018 Cedric Mesnil , Ledger SAS -# +# # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at -# +# # http://www.apache.org/licenses/LICENSE-2.0 -# +# # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -21,17 +21,17 @@ from .gpgcard import GPGCard def get_argparser(): parser = argparse.ArgumentParser(epilog=""" -reset, backup, restore are always executed in THIS order. +reset, backup, restore are always executed in THIS order. Template identifiers are ed2559, cv25519, rsa2048, rsa3072, rsa4096. """ ) parser.add_argument('--adm-pin', metavar='PIN', help='Administrative PIN, if pinpad not used') - parser.add_argument('--backup', help='Perfom a full backup except the key', action='store_true') - parser.add_argument('--backup-keys', help='Perfom keys encrypted backup', action='store_true') + parser.add_argument('--backup', help='Perfom a full backup except the key', action='store_true') + parser.add_argument('--backup-keys', help='Perfom keys encrypted backup', action='store_true') parser.add_argument('--file', help='basckup/restore file', type=str, default='gpg_backup') parser.add_argument('--pinpad', help='PIN validation will be deledated to pinpad', action='store_true') - parser.add_argument('--reader', help='PCSC reader', type=str, default='pcsc:Ledger') + parser.add_argument('--reader', help='PCSC reader', type=str, default='pcsc:Ledger') parser.add_argument('--reset', help='Reset the application. All data are erased', action='store_true') parser.add_argument('--restore', help='Perfom a full restore except the key', action='store_true') parser.add_argument('--set-serial', metavar='SERIAL', help='set the four serial bytes') @@ -49,7 +49,7 @@ def banner(): GPG Ledger Admin Tool v0.1. Copyright 2018 Cedric Mesnil , Ledger SAS -""" +""" ) @@ -95,7 +95,7 @@ try: if args.reset: print("Reset application...", end='', flush=True) - gpgcard.terminate() + gpgcard.terminate() gpgcard.activate() print("OK") @@ -128,11 +128,11 @@ try: sig,dec,aut = args.set_templates.split(":") gpgcard.set_template(templates[sig],templates[dec],templates[aut]) print("OK", flush=True) - + if args.seed_key: print("Seed Key...", end='', flush=True) gpgcard.seed_key(); - print("OK", flush=True) + print("OK", flush=True) if args.set_fingerprints: print("Set fingerprints...", end='', flush=True) diff --git a/src/gpg_api.h b/src/gpg_api.h index 2dc64ea..ca08c5f 100644 --- a/src/gpg_api.h +++ b/src/gpg_api.h @@ -24,7 +24,8 @@ unsigned int gpg_curve2domainlen(unsigned int cv); void gpg_init(void); void gpg_init_ux(void); -int gpg_install(unsigned char app_state); +void gpg_install(unsigned char app_state); +void gpg_install_slot(gpg_key_slot_t *slot); int gpg_dispatch(void); int gpg_apdu_select_data(unsigned int ref, int reccord); diff --git a/src/gpg_dispatch.c b/src/gpg_dispatch.c index 7c61990..61ff626 100644 --- a/src/gpg_dispatch.c +++ b/src/gpg_dispatch.c @@ -30,6 +30,11 @@ void gpg_check_access_ins() { return; } break; + #ifdef GPG_LOG + #warning GPG_LOG activated + case INS_GET_LOG: + return; + #endif case INS_SELECT: return; @@ -256,6 +261,13 @@ int gpg_dispatch() { tag = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2; switch (G_gpg_vstate.io_ins) { + #ifdef GPG_LOG + case INS_GET_LOG: + gpg_io_discard(1); + gpg_io_insert(G_gpg_vstate.log_buffer, 32); + return SW_OK; + #endif + /* --- SELECT --- */ case INS_SELECT: sw = gpg_apdu_select(); diff --git a/src/gpg_init.c b/src/gpg_init.c index ff005e2..d98da0a 100644 --- a/src/gpg_init.c +++ b/src/gpg_init.c @@ -252,7 +252,7 @@ const unsigned char C_default_AlgoAttr_dec[] = { // Default template: NIST P256 132A8648CE3D030107 / 122A8648CE3D030107 #if 0 const unsigned char C_default_AlgoAttr_sig[] = { - // ecdsa + // ecdsa 0x13, // NIST-P256 0x2A,0x86,0x48,0xCE,0x3D,0x03,0x01,0x07 @@ -268,7 +268,7 @@ const unsigned char C_default_AlgoAttr_dec[] = { // Default template: Ed/Cv-25519 162B06010401DA470F01 / 122B060104019755010501 #if 0 const unsigned char C_default_AlgoAttr_sig[] = { - // eddsa + // eddsa 0x16, // ed25519 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01, @@ -323,10 +323,35 @@ void gpg_init_ux() { /* ----------------------------------------------------------------------- */ /* --- Install/ReInstall GPGapp --- */ /* ----------------------------------------------------------------------- */ -int gpg_install(unsigned char app_state) { - gpg_pin_t pin; +void gpg_install_slot(gpg_key_slot_t *slot) { + unsigned char tmp[4]; unsigned int l; + gpg_nvm_write(slot, 0, sizeof(gpg_key_slot_t)); + + cx_rng(tmp, 4); + gpg_nvm_write((void *)(slot->serial), tmp, 4); + + l = sizeof(C_default_AlgoAttr_sig); + gpg_nvm_write((void *)(&slot->sig.attributes.value), (void *)C_default_AlgoAttr_sig, l); + gpg_nvm_write((void *)(&slot->sig.attributes.length), &l, sizeof(unsigned int)); + gpg_nvm_write((void *)(&slot->aut.attributes.value), (void *)C_default_AlgoAttr_sig, l); + gpg_nvm_write((void *)(&slot->aut.attributes.length), &l, sizeof(unsigned int)); + + l = sizeof(C_default_AlgoAttr_dec); + gpg_nvm_write((void *)(&slot->dec.attributes.value), (void *)C_default_AlgoAttr_dec, l); + gpg_nvm_write((void *)(&slot->dec.attributes.length), &l, sizeof(unsigned int)); + + tmp[0] = 0x00; + tmp[1] = 0x20; + gpg_nvm_write((void *)(&slot->sig.UIF), &tmp, 2); + gpg_nvm_write((void *)(&slot->dec.UIF), &tmp, 2); + gpg_nvm_write((void *)(&slot->aut.UIF), &tmp, 2); +} + +void gpg_install(unsigned char app_state) { + gpg_pin_t pin; + // full reset data gpg_nvm_write((void *)(N_gpg_pstate), NULL, sizeof(gpg_nv_state_t)); @@ -339,11 +364,6 @@ int gpg_install(unsigned char app_state) { os_memmove(G_gpg_vstate.work.io_buffer, C_default_AID, sizeof(C_default_AID)); gpg_nvm_write((void *)(N_gpg_pstate->AID), &G_gpg_vstate.work.io_buffer, sizeof(C_default_AID)); - // Serial - cx_rng(G_gpg_vstate.work.io_buffer, 4 * GPG_KEYS_SLOTS); - for (int s = 0; s < GPG_KEYS_SLOTS; s++) { - gpg_nvm_write((void *)(N_gpg_pstate->keys[s].serial), G_gpg_vstate.work.io_buffer + 4 * s, 4); - } if (app_state == STATE_ACTIVATE) { // default sex: none @@ -390,25 +410,10 @@ int gpg_install(unsigned char app_state) { USBD_CCID_activate_pinpad(3); // default key template: RSA 2048) - for (int s = 0; s < GPG_KEYS_SLOTS; s++) { - unsigned char uif[2]; - uif[0] = 0x00; - uif[1] = 0x20; - l = sizeof(C_default_AlgoAttr_sig); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].sig.attributes.value), (void *)C_default_AlgoAttr_sig, l); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].sig.attributes.length), &l, sizeof(unsigned int)); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].aut.attributes.value), (void *)C_default_AlgoAttr_sig, l); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].aut.attributes.length), &l, sizeof(unsigned int)); - l = sizeof(C_default_AlgoAttr_dec); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].dec.attributes.value), (void *)C_default_AlgoAttr_dec, l); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].dec.attributes.length), &l, sizeof(unsigned int)); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].sig.UIF), &uif, 2); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].dec.UIF), &uif, 2); - gpg_nvm_write((void *)(&N_gpg_pstate->keys[s].aut.UIF), &uif, 2); + gpg_install_slot(&N_gpg_pstate->keys[s]); } } - return 0; } #define USBD_OFFSET_CfgDesc_bPINSupport (sizeof(USBD_CfgDesc) - 16) diff --git a/src/gpg_types.h b/src/gpg_types.h index ac93877..cc6d27d 100644 --- a/src/gpg_types.h +++ b/src/gpg_types.h @@ -207,7 +207,6 @@ struct gpg_v_state_s { unsigned short io_mark; union { unsigned char io_buffer[GPG_IO_BUFFER_LENGTH]; - struct { union { cx_rsa_public_key_t public; @@ -279,6 +278,9 @@ struct gpg_v_state_s { char ux_buff5[32]; #endif + #ifdef GPG_LOG + unsigned char log_buffer[32]; + #endif #ifdef GPG_DEBUG unsigned char print; #endif @@ -316,6 +318,9 @@ typedef struct gpg_v_state_s gpg_v_state_t; /* --- INS --- */ #define INS_EXIT 0x02 +#ifdef GPG_LOG +#define INS_GET_LOG 0x04 +#endif #define INS_SELECT 0xa4 #define INS_TERMINATE_DF 0xe6 diff --git a/src/gpg_ux_nanos.c b/src/gpg_ux_nanos.c index 0ed2af2..cf6f022 100644 --- a/src/gpg_ux_nanos.c +++ b/src/gpg_ux_nanos.c @@ -96,44 +96,21 @@ unsigned int ui_uifconfirm_prepro(const bagl_element_t *element); const bagl_element_t ui_uifconfirm_nanos[] = { // type userid x y w h str rad fill fg bg font_id icon_id - {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, + {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, + NULL}, {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, - NULL, - 0, - 0, - 0, - NULL, - NULL, NULL}, {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, - NULL, - 0, - 0, - 0, - NULL, - NULL, NULL}, {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_gpg_vstate.menu, - 0, - 0, - 0, - NULL, - NULL, - NULL}, + G_gpg_vstate.menu}, {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_gpg_vstate.menu, - 0, - 0, - 0, - NULL, - NULL, - NULL}, + G_gpg_vstate.menu}, }; void ui_menu_uifconfirm_display(unsigned int value) { @@ -218,44 +195,21 @@ unsigned int ui_uifconfirm_nanos_button(unsigned int button_mask, unsigned int b const bagl_element_t ui_pinconfirm_nanos[] = { // type userid x y w h str rad fill fg bg font_id icon_id - {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, + {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, + NULL}, {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CROSS}, - NULL, - 0, - 0, - 0, - NULL, - NULL, NULL}, {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_CHECK}, - NULL, - 0, - 0, - 0, - NULL, - NULL, NULL}, {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_gpg_vstate.menu, - 0, - 0, - 0, - NULL, - NULL, - NULL}, + G_gpg_vstate.menu}, {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_gpg_vstate.menu, - 0, - 0, - 0, - NULL, - NULL, - NULL}, + G_gpg_vstate.menu}, }; void ui_menu_pinconfirm_display(unsigned int value) { @@ -308,44 +262,21 @@ unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, unsigned int b const bagl_element_t ui_pinentry_nanos[] = { // type userid x y w h str rad fill fg bg font_id icon_id - {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, NULL, 0, 0, 0, NULL, NULL, NULL}, + {{BAGL_RECTANGLE, 0x00, 0, 0, 128, 32, 0, 0, BAGL_FILL, 0x000000, 0xFFFFFF, 0, 0}, + NULL}, {{BAGL_ICON, 0x00, 3, 12, 7, 7, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_DOWN}, - NULL, - 0, - 0, - 0, - NULL, - NULL, NULL}, {{BAGL_ICON, 0x00, 117, 13, 8, 6, 0, 0, 0, 0xFFFFFF, 0x000000, 0, BAGL_GLYPH_ICON_UP}, - NULL, - 0, - 0, - 0, - NULL, - NULL, NULL}, {{BAGL_LABELINE, 0x01, 0, 12, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_EXTRABOLD_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_gpg_vstate.menu, - 0, - 0, - 0, - NULL, - NULL, - NULL}, + G_gpg_vstate.menu}, {{BAGL_LABELINE, 0x02, 0, 26, 128, 32, 0, 0, 0, 0xFFFFFF, 0x000000, BAGL_FONT_OPEN_SANS_REGULAR_11px | BAGL_FONT_ALIGNMENT_CENTER, 0}, - G_gpg_vstate.menu, - 0, - 0, - 0, - NULL, - NULL, - NULL}, + G_gpg_vstate.menu}, }; static const char C_pin_digit[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '<', 'A', 'V'}; @@ -941,13 +872,29 @@ void ui_menu_reset_action(unsigned int value) { ui_CCID_reset(); ui_menu_main_display(0); } + +/* ------------------------------ RESET KEY SLOT ----------------------------- */ +void ui_menu_reset_slot_action(unsigned int value); + +const ux_menu_entry_t ui_menu_reset_slot[] = {{NULL, NULL, 0, NULL, "Really Reset ?", NULL, 0, 0}, + {NULL, ui_menu_main_display, 0, &C_badge_back, "No", NULL, 61, 40}, + {NULL, ui_menu_reset_slot_action, 0, NULL, "Yes", NULL, 0, 0}, + UX_MENU_END}; + +void ui_menu_reset_slot_action(unsigned int value) { + gpg_install_slot(G_gpg_vstate.kslot); + ui_menu_main_display(0); +} + + /* ------------------------------- SETTINGS UX ------------------------------- */ const ux_menu_entry_t ui_menu_settings[] = {{NULL, ui_menu_template_display, 0, NULL, "Key template", NULL, 0, 0}, {NULL, ui_menu_seed_display, 0, NULL, "Seed mode", NULL, 0, 0}, {NULL, ui_menu_pinmode_display, 0, NULL, "PIN mode", NULL, 0, 0}, {NULL, ui_menu_uifmode_display, 0, NULL, "UIF mode", NULL, 0, 0}, - {ui_menu_reset, NULL, 0, NULL, "Reset", NULL, 0, 0}, + {ui_menu_reset, NULL, 0, NULL, "Reset App", NULL, 0, 0}, + {ui_menu_reset_slot, NULL, 0, NULL, "Reset Slot", NULL, 0, 0}, {NULL, ui_menu_main_display, 2, &C_badge_back, "Back", NULL, 61, 40}, UX_MENU_END}; @@ -1030,7 +977,7 @@ const ux_menu_entry_t ui_menu_main[] = {{NULL, NULL, 0, NULL, "", "", 0, 0}, #endif {ui_menu_settings, NULL, 0, NULL, "Settings", NULL, 0, 0}, {ui_menu_info, NULL, 0, NULL, "About", NULL, 0, 0}, - {NULL, os_sched_exit, 0, &C_icon_dashboard, "Quit app", NULL, 50, 29}, + {NULL, (void*)os_sched_exit, 0, &C_icon_dashboard, "Quit app", NULL, 50, 29}, UX_MENU_END}; extern const uint8_t N_USBD_CfgDesc[]; const bagl_element_t *ui_menu_main_preprocessor(const ux_menu_entry_t *entry, bagl_element_t *element) { diff --git a/src/gpg_ux_nanox.c b/src/gpg_ux_nanox.c index 8541857..ab0429e 100644 --- a/src/gpg_ux_nanox.c +++ b/src/gpg_ux_nanox.c @@ -980,6 +980,25 @@ void ui_menu_reset_action(unsigned int value) { ui_menu_main_display(0); } +/* ------------------------------ RESET SLOT UX ------------------------------ */ + +void ui_menu_reset_slot_action(unsigned int value); + +UX_STEP_CB(ux_menu_reset_slot_1_step, bnn, ui_menu_settings_display(4), {"Ooops, NO!", "Do not reset", "the key slot"}); + +UX_STEP_CB(ux_menu_reset_slot_2_step, bn, ui_menu_reset_slot_action(0), {"YES!", "Reset the slot"}); + +UX_FLOW(ux_flow_reset_slot, &ux_menu_reset_slot_1_step, &ux_menu_reset_slot_2_step); + +void ui_menu_reset_slot_display(unsigned int value) { + ux_flow_init(value, ux_flow_reset_slot, NULL); +} + +void ui_menu_reset_slot_action(unsigned int value) { + gpg_install_slot(G_gpg_vstate.kslot); + ui_menu_main_display(0); +} + /* ------------------------------- SETTINGS UX ------------------------------- */ const char *const settings_getter_values[] = {"Key template", "Seed mode", "PIN mode", "UIF mode", "Reset", "Back"};