mirror of
https://github.com/LedgerHQ/openpgp-card-app
synced 2024-11-09 07:10:30 +00:00
Add inline comment for functions description
This commit is contained in:
parent
400ff19c6d
commit
3847b0636d
@ -18,18 +18,28 @@
|
||||
#ifndef GPG_API_H
|
||||
#define GPG_API_H
|
||||
|
||||
void gpg_activate_pinpad(uint8_t enabled);
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- INIT ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
void gpg_activate_pinpad(uint8_t enabled);
|
||||
unsigned int gpg_oid2curve(unsigned char *oid, unsigned int len);
|
||||
unsigned char *gpg_curve2oid(unsigned int cv, unsigned int *len);
|
||||
unsigned int gpg_curve2domainlen(unsigned int cv);
|
||||
|
||||
void gpg_init(void);
|
||||
void gpg_init_ux(void);
|
||||
void gpg_install(unsigned char app_state);
|
||||
void gpg_install_slot(gpg_key_slot_t *slot);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- DISPATCH ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int gpg_dispatch(void);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- DATA ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
void gpg_apdu_select_data(unsigned int ref, int record);
|
||||
int gpg_apdu_get_data(unsigned int ref);
|
||||
int gpg_apdu_get_next_data(unsigned int ref);
|
||||
@ -37,6 +47,10 @@ int gpg_apdu_put_data(unsigned int ref);
|
||||
int gpg_apdu_get_key_data(unsigned int ref);
|
||||
int gpg_apdu_put_key_data(unsigned int ref);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- PSO ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int gpg_pso_derive_slot_seed(int slot, unsigned char *seed);
|
||||
int gpg_pso_derive_key_seed(unsigned char *Sn,
|
||||
unsigned char *key_name,
|
||||
@ -45,27 +59,48 @@ int gpg_pso_derive_key_seed(unsigned char *Sn,
|
||||
unsigned int Ski_len);
|
||||
int gpg_apdu_pso(void);
|
||||
int gpg_apdu_internal_authenticate(void);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- GEN ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int gpg_apdu_gen(void);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- CHALLENGE ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int gpg_apdu_get_challenge(void);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- SELECT ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int gpg_apdu_select(void);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- PIN ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
int gpg_apdu_verify(void);
|
||||
int gpg_apdu_change_ref_data(void);
|
||||
int gpg_apdu_reset_retry_counter(void);
|
||||
|
||||
gpg_pin_t *gpg_pin_get_pin(int id);
|
||||
int gpg_pin_is_blocked(gpg_pin_t *pin);
|
||||
int gpg_pin_is_verified(int pinID);
|
||||
void gpg_pin_set_verified(int pinID, int verified);
|
||||
int gpg_pin_check(gpg_pin_t *pin, int pinID, const unsigned char *pin_val, unsigned int pin_len);
|
||||
int gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len);
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- MSE ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
void gpg_mse_reset();
|
||||
int gpg_apdu_mse();
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- IO ---- */
|
||||
/* --- IO ---- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void gpg_io_discard(int clear);
|
||||
void gpg_io_clear(void);
|
||||
|
@ -18,6 +18,12 @@
|
||||
#include "gpg_vars.h"
|
||||
#include "cx_errors.h"
|
||||
|
||||
/**
|
||||
* Generate a Random Number
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_get_challenge() {
|
||||
unsigned int olen;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
@ -19,12 +19,27 @@
|
||||
#include "gpg_ux.h"
|
||||
#include "cx_errors.h"
|
||||
|
||||
/**
|
||||
* Select a DO (Data Object) in the current template
|
||||
*
|
||||
* @param[in] ref DO tag
|
||||
* @param[in] record Offset of the record
|
||||
*
|
||||
*/
|
||||
void gpg_apdu_select_data(unsigned int ref, int record) {
|
||||
G_gpg_vstate.DO_current = ref;
|
||||
G_gpg_vstate.DO_reccord = record;
|
||||
G_gpg_vstate.DO_offset = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a DO (Data Object) from the card
|
||||
*
|
||||
* @param[in] ref DO tag
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_get_data(unsigned int ref) {
|
||||
int sw = SW_UNKNOWN;
|
||||
|
||||
@ -211,6 +226,14 @@ int gpg_apdu_get_data(unsigned int ref) {
|
||||
return sw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the next instance of the same DO (Data Object) from the card
|
||||
*
|
||||
* @param[in] ref DO tag
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_get_next_data(unsigned int ref) {
|
||||
int sw = SW_UNKNOWN;
|
||||
|
||||
@ -224,6 +247,14 @@ int gpg_apdu_get_next_data(unsigned int ref) {
|
||||
return sw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write a DO (Data Object) to the card
|
||||
*
|
||||
* @param[in] ref DO tag
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_put_data(unsigned int ref) {
|
||||
unsigned int t, l, sw;
|
||||
unsigned int *ptr_l = NULL;
|
||||
@ -799,6 +830,15 @@ end:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Init an encryption key to protect Private Key
|
||||
* Used for Backup/Restore
|
||||
*
|
||||
* @param[out] keyenc aes encryption key
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_init_keyenc(cx_aes_key_t *keyenc) {
|
||||
int sw = SW_UNKNOWN;
|
||||
unsigned char seed[32];
|
||||
@ -821,8 +861,15 @@ end:
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
// cmd
|
||||
// resp TID API COMPAT len_pub len_priv priv
|
||||
/**
|
||||
* Read a Key DO (Data Object) from the card
|
||||
* for Backup
|
||||
*
|
||||
* @param[in] ref DO tag
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_get_key_data(unsigned int ref) {
|
||||
cx_aes_key_t keyenc = {0};
|
||||
gpg_key_t *keygpg = NULL;
|
||||
@ -932,8 +979,15 @@ end:
|
||||
return error;
|
||||
}
|
||||
|
||||
// cmd TID API COMPAT len_pub len_priv priv
|
||||
// resp -
|
||||
/**
|
||||
* Write a key DO (Data Object) to the card
|
||||
* For Restore
|
||||
*
|
||||
* @param[in] ref DO tag
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_put_key_data(unsigned int ref) {
|
||||
cx_aes_key_t keyenc = {0};
|
||||
gpg_key_t *keygpg = NULL;
|
||||
|
@ -17,6 +17,13 @@
|
||||
|
||||
#include "gpg_vars.h"
|
||||
|
||||
/**
|
||||
* Check INS access condition
|
||||
* Verify if the corresponding PW is verified
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_check_access_ins() {
|
||||
int sw = SW_UNKNOWN;
|
||||
|
||||
@ -92,6 +99,13 @@ static int gpg_check_access_ins() {
|
||||
return sw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check INS Read access condition
|
||||
* Verify if the corresponding PW is verified
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_check_access_read_DO() {
|
||||
int sw = SW_UNKNOWN;
|
||||
|
||||
@ -163,6 +177,13 @@ static int gpg_check_access_read_DO() {
|
||||
return sw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check INS Write access condition
|
||||
* Verify if the corresponding PW is verified
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_check_access_write_DO() {
|
||||
int sw = SW_UNKNOWN;
|
||||
|
||||
@ -228,7 +249,12 @@ static int gpg_check_access_write_DO() {
|
||||
return sw;
|
||||
}
|
||||
|
||||
/* assume command is fully received */
|
||||
/**
|
||||
* APDU Handler: dispatch command
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_dispatch() {
|
||||
unsigned int tag, t, l;
|
||||
int sw = SW_UNKNOWN;
|
||||
|
@ -19,8 +19,14 @@
|
||||
#include "cx_ram.h"
|
||||
#include "cx_errors.h"
|
||||
|
||||
/* @in slot slot num [0 ; GPG_KEYS_SLOTS[
|
||||
* @out seed 32 bytes master seed for given slot
|
||||
/**
|
||||
* Derivate the App Path from the Master Seed for a specific slot
|
||||
*
|
||||
* @param[in] slot Selected slot
|
||||
* @param[out] seed 32 bytes seed for given slot
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_pso_derive_slot_seed(int slot, unsigned char *seed) {
|
||||
unsigned int path[2];
|
||||
@ -39,11 +45,17 @@ end:
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
/* @in Sn master seed slot number
|
||||
* @in key_name key name: 'sig ', 'auth ', 'dec '
|
||||
* @in idx sub-seed index
|
||||
* @out Ski generated sub_seed
|
||||
* @in Ski_len sub-seed length
|
||||
/**
|
||||
* Derivate the Key from the Generated Seed
|
||||
*
|
||||
* @param[in] Sn Seed for the selected slot
|
||||
* @param[in] key_name key name: 'sig ', 'auth ', 'dec '
|
||||
* @param[in] idx sub-seed index
|
||||
* @param[out] Ski generated sub_seed
|
||||
* @param[in] Ski_len sub-seed length
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_pso_derive_key_seed(unsigned char *Sn,
|
||||
unsigned char *key_name,
|
||||
@ -74,6 +86,15 @@ end:
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a RSA key pair and writes it in NVRam
|
||||
*
|
||||
* @param[in] keygpg pointer on key structure
|
||||
* @param[in] name key name: 'sig ', 'auth ', 'dec '
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_gen_rsa_kyey(gpg_key_t *keygpg, uint8_t *name) {
|
||||
cx_rsa_public_key_t *rsa_pub = NULL;
|
||||
cx_rsa_private_key_t *rsa_priv = NULL;
|
||||
@ -146,6 +167,14 @@ end:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a RSA key pair
|
||||
*
|
||||
* @param[in] keygpg pointer on key structure
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_read_rsa_kyey(gpg_key_t *keygpg) {
|
||||
uint32_t ksz = 0;
|
||||
|
||||
@ -182,6 +211,15 @@ static int gpg_read_rsa_kyey(gpg_key_t *keygpg) {
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an Elliptic Curve key pair and writes it in NVRam
|
||||
*
|
||||
* @param[in] keygpg pointer on key structure
|
||||
* @param[in] name key name: 'sig ', 'auth ', 'dec '
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_gen_ecc_kyey(gpg_key_t *keygpg, uint8_t *name) {
|
||||
uint32_t curve = 0, keepprivate = 0;
|
||||
uint32_t ksz = 0, reset_cnt = 0;
|
||||
@ -225,6 +263,14 @@ end:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read an Elliptic Curve key pair
|
||||
*
|
||||
* @param[in] keygpg pointer on key structure
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_read_ecc_kyey(gpg_key_t *keygpg) {
|
||||
uint32_t curve = 0;
|
||||
uint32_t i, len;
|
||||
@ -262,7 +308,12 @@ end:
|
||||
return error;
|
||||
}
|
||||
|
||||
/* assume command is fully received */
|
||||
/**
|
||||
* APDU handler to Generate/Read key pair
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_gen() {
|
||||
uint32_t t, l;
|
||||
gpg_key_t *keygpg = NULL;
|
||||
|
@ -91,6 +91,15 @@ const unsigned char C_OID_cv25519[10] = {
|
||||
0x01,
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieve Curve associated to a given OID
|
||||
*
|
||||
* @param[in] oid Selected OID as a reference
|
||||
* @param[in] len OID length
|
||||
*
|
||||
* @return Found Curve, or CX_CURVE_NONE if not supported
|
||||
*
|
||||
*/
|
||||
unsigned int gpg_oid2curve(unsigned char *oid, unsigned int len) {
|
||||
if ((len == sizeof(C_OID_SECP256R1)) && (memcmp(oid, C_OID_SECP256R1, len) == 0)) {
|
||||
return CX_CURVE_SECP256R1;
|
||||
@ -131,6 +140,15 @@ unsigned int gpg_oid2curve(unsigned char *oid, unsigned int len) {
|
||||
return CX_CURVE_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve OID of the selected Curve
|
||||
*
|
||||
* @param[in] cv Selected Curve as a reference
|
||||
* @param[out] len OID length
|
||||
*
|
||||
* @return Found OID, or NULL if not supported
|
||||
*
|
||||
*/
|
||||
unsigned char *gpg_curve2oid(unsigned int cv, unsigned int *len) {
|
||||
switch (cv) {
|
||||
case CX_CURVE_SECP256R1:
|
||||
@ -175,6 +193,14 @@ unsigned char *gpg_curve2oid(unsigned int cv, unsigned int *len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the selected Curve length
|
||||
*
|
||||
* @param[in] cv Selected Curve as a reference
|
||||
*
|
||||
* @return Length, or 0 if not supported
|
||||
*
|
||||
*/
|
||||
unsigned int gpg_curve2domainlen(unsigned int cv) {
|
||||
switch (cv) {
|
||||
case CX_CURVE_SECP256K1:
|
||||
@ -341,6 +367,10 @@ const unsigned char C_sha256_PW2[] = {
|
||||
/* --- boot init --- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* App global config
|
||||
*
|
||||
*/
|
||||
void gpg_init() {
|
||||
explicit_bzero(&G_gpg_vstate, sizeof(gpg_v_state_t));
|
||||
// first init ?
|
||||
@ -370,6 +400,13 @@ void gpg_init_ux() {
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- Install/ReInstall GPGapp --- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* App dedicated slot config
|
||||
*
|
||||
* @param[in] slot Selected slot to configure
|
||||
*
|
||||
*/
|
||||
void gpg_install_slot(gpg_key_slot_t *slot) {
|
||||
unsigned char tmp[4];
|
||||
unsigned int l;
|
||||
@ -396,6 +433,12 @@ void gpg_install_slot(gpg_key_slot_t *slot) {
|
||||
nvm_write((void *) (&slot->aut.UIF), &tmp, 2);
|
||||
}
|
||||
|
||||
/**
|
||||
* App 1st installation or reinstallation
|
||||
*
|
||||
* @param[in] app_state Current App (card) state
|
||||
*
|
||||
*/
|
||||
void gpg_install(unsigned char app_state) {
|
||||
gpg_pin_t pin;
|
||||
|
||||
@ -459,6 +502,14 @@ void gpg_install(unsigned char app_state) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup pinpad configuration
|
||||
*
|
||||
* @param[in] enabled pinpad configuration
|
||||
*
|
||||
* @return N/A
|
||||
*
|
||||
*/
|
||||
void gpg_activate_pinpad(uint8_t enabled) {
|
||||
uint8_t e = enabled ? 3 : 0;
|
||||
|
||||
|
158
src/gpg_io.c
158
src/gpg_io.c
@ -30,6 +30,12 @@
|
||||
/* MISC */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Set Offset in APDU buffer
|
||||
*
|
||||
* @param[in] offset value to set
|
||||
*
|
||||
*/
|
||||
void gpg_io_set_offset(unsigned int offset) {
|
||||
switch (offset) {
|
||||
case IO_OFFSET_END:
|
||||
@ -45,15 +51,32 @@ void gpg_io_set_offset(unsigned int offset) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Mark current offset in APDU buffer
|
||||
*
|
||||
*/
|
||||
void gpg_io_mark() {
|
||||
G_gpg_vstate.io_mark = G_gpg_vstate.io_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shift empty space in APDU buffer
|
||||
*
|
||||
* @param[in] len space length
|
||||
*
|
||||
*/
|
||||
void gpg_io_inserted(unsigned int len) {
|
||||
G_gpg_vstate.io_offset += len;
|
||||
G_gpg_vstate.io_length += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard APDU buffer values
|
||||
* Set Length, Offset and Mark to 0
|
||||
*
|
||||
* @param[in] clear request to fully zeroed the buffer
|
||||
*
|
||||
*/
|
||||
void gpg_io_discard(int clear) {
|
||||
G_gpg_vstate.io_length = 0;
|
||||
G_gpg_vstate.io_offset = 0;
|
||||
@ -63,6 +86,10 @@ void gpg_io_discard(int clear) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear (zeroed) the APDU buffer
|
||||
*
|
||||
*/
|
||||
void gpg_io_clear() {
|
||||
explicit_bzero(G_gpg_vstate.work.io_buffer, GPG_IO_BUFFER_LENGTH);
|
||||
}
|
||||
@ -71,6 +98,12 @@ void gpg_io_clear() {
|
||||
/* INSERT data to be sent */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Move APDU buffer content after a hole
|
||||
*
|
||||
* @param[in] sz hole length
|
||||
*
|
||||
*/
|
||||
static void gpg_io_hole(unsigned int sz) {
|
||||
LEDGER_ASSERT((G_gpg_vstate.io_length + sz) <= GPG_IO_BUFFER_LENGTH, "Bad hole!");
|
||||
memmove(G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset + sz,
|
||||
@ -79,18 +112,37 @@ static void gpg_io_hole(unsigned int sz) {
|
||||
G_gpg_vstate.io_length += sz;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a data buffer into the APDU buffer
|
||||
*
|
||||
* @param[in] buff data buffer
|
||||
* @param[in] len buffer length
|
||||
*
|
||||
*/
|
||||
void gpg_io_insert(unsigned char const *buff, unsigned int len) {
|
||||
gpg_io_hole(len);
|
||||
memmove(G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, buff, len);
|
||||
G_gpg_vstate.io_offset += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a u32 value into the APDU buffer
|
||||
*
|
||||
* @param[in] v32 value to insert
|
||||
*
|
||||
*/
|
||||
void gpg_io_insert_u32(unsigned int v32) {
|
||||
gpg_io_hole(4);
|
||||
U4BE_ENCODE(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_offset, v32);
|
||||
G_gpg_vstate.io_offset += 4;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a u24 value into the APDU buffer
|
||||
*
|
||||
* @param[in] v24 value to insert
|
||||
*
|
||||
*/
|
||||
void gpg_io_insert_u24(unsigned int v24) {
|
||||
gpg_io_hole(3);
|
||||
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] = v24 >> 16;
|
||||
@ -98,17 +150,38 @@ void gpg_io_insert_u24(unsigned int v24) {
|
||||
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 2] = v24 >> 0;
|
||||
G_gpg_vstate.io_offset += 3;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a u16 value into the APDU buffer
|
||||
*
|
||||
* @param[in] v16 value to insert
|
||||
*
|
||||
*/
|
||||
void gpg_io_insert_u16(unsigned int v16) {
|
||||
gpg_io_hole(2);
|
||||
U2BE_ENCODE(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_offset, v16);
|
||||
G_gpg_vstate.io_offset += 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a u8 value into the APDU buffer
|
||||
*
|
||||
* @param[in] v8 value to insert
|
||||
*
|
||||
*/
|
||||
void gpg_io_insert_u8(unsigned int v8) {
|
||||
gpg_io_hole(1);
|
||||
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] = v8;
|
||||
G_gpg_vstate.io_offset += 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a TAG into the APDU buffer
|
||||
* (To handle TLV)
|
||||
*
|
||||
* @param[in] T tag to insert
|
||||
*
|
||||
*/
|
||||
void gpg_io_insert_t(unsigned int T) {
|
||||
if (T & 0xFF00) {
|
||||
gpg_io_insert_u16(T);
|
||||
@ -117,6 +190,14 @@ void gpg_io_insert_t(unsigned int T) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a TAG/LENGTH into the APDU buffer
|
||||
* (To handle TLV)
|
||||
*
|
||||
* @param[in] T tag to insert
|
||||
* @param[in] L length to insert
|
||||
*
|
||||
*/
|
||||
void gpg_io_insert_tl(unsigned int T, unsigned int L) {
|
||||
gpg_io_insert_t(T);
|
||||
if (L < 128) {
|
||||
@ -129,6 +210,15 @@ void gpg_io_insert_tl(unsigned int T, unsigned int L) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert a TAG/LENGTH/VALUE into the APDU buffer
|
||||
* (To handle TLV)
|
||||
*
|
||||
* @param[in] T tag to insert
|
||||
* @param[in] L length to insert
|
||||
* @param[in] V data to insert
|
||||
*
|
||||
*/
|
||||
void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V) {
|
||||
gpg_io_insert_tl(T, L);
|
||||
gpg_io_insert(V, L);
|
||||
@ -138,6 +228,12 @@ void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V) {
|
||||
/* FECTH data from received buffer */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
/**
|
||||
* Read a u32 value from the APDU buffer
|
||||
*
|
||||
* @return value retrieved
|
||||
*
|
||||
*/
|
||||
unsigned int gpg_io_fetch_u32() {
|
||||
unsigned int v32;
|
||||
v32 = U4BE(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_offset);
|
||||
@ -145,6 +241,12 @@ unsigned int gpg_io_fetch_u32() {
|
||||
return v32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a u24 value from the APDU buffer
|
||||
*
|
||||
* @return value retrieved
|
||||
*
|
||||
*/
|
||||
unsigned int gpg_io_fetch_u24() {
|
||||
unsigned int v24;
|
||||
v24 = ((G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset + 0] << 16) |
|
||||
@ -154,6 +256,12 @@ unsigned int gpg_io_fetch_u24() {
|
||||
return v24;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a u16 value from the APDU buffer
|
||||
*
|
||||
* @return value retrieved
|
||||
*
|
||||
*/
|
||||
unsigned int gpg_io_fetch_u16() {
|
||||
unsigned int v16;
|
||||
v16 = U2BE(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_offset);
|
||||
@ -161,6 +269,12 @@ unsigned int gpg_io_fetch_u16() {
|
||||
return v16;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a u8 value from the APDU buffer
|
||||
*
|
||||
* @return value retrieved
|
||||
*
|
||||
*/
|
||||
unsigned int gpg_io_fetch_u8() {
|
||||
unsigned int v8;
|
||||
v8 = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset];
|
||||
@ -168,6 +282,13 @@ unsigned int gpg_io_fetch_u8() {
|
||||
return v8;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a TAG from the APDU buffer
|
||||
* (To handle TLV)
|
||||
*
|
||||
* @param[out] T read tag
|
||||
*
|
||||
*/
|
||||
void gpg_io_fetch_t(unsigned int *T) {
|
||||
*T = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset];
|
||||
G_gpg_vstate.io_offset++;
|
||||
@ -177,6 +298,13 @@ void gpg_io_fetch_t(unsigned int *T) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a LENGTH from the APDU buffer
|
||||
* (To handle TLV)
|
||||
*
|
||||
* @param[out] L read length
|
||||
*
|
||||
*/
|
||||
void gpg_io_fetch_l(unsigned int *L) {
|
||||
*L = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset];
|
||||
|
||||
@ -196,16 +324,40 @@ void gpg_io_fetch_l(unsigned int *L) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a TAG/LENGTH from the APDU buffer
|
||||
* (To handle TLV)
|
||||
*
|
||||
* @param[out] T read tag
|
||||
* @param[out] L read length
|
||||
*
|
||||
*/
|
||||
void gpg_io_fetch_tl(unsigned int *T, unsigned int *L) {
|
||||
gpg_io_fetch_t(T);
|
||||
gpg_io_fetch_l(L);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a buffer from the APDU buffer and write it in NVRam
|
||||
* (To handle TLV)
|
||||
*
|
||||
* @param[in] buffer NVRAM address
|
||||
* @param[in] len buffer length
|
||||
*
|
||||
*/
|
||||
void gpg_io_fetch_nv(unsigned char *buffer, int len) {
|
||||
nvm_write(buffer, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, len);
|
||||
G_gpg_vstate.io_offset += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read a buffer from the APDU buffer
|
||||
* (To handle TLV)
|
||||
*
|
||||
* @param[out] buffer data buffer
|
||||
* @param[in] len buffer length
|
||||
*
|
||||
*/
|
||||
int gpg_io_fetch(unsigned char *buffer, int len) {
|
||||
if (buffer) {
|
||||
memmove(buffer, G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset, len);
|
||||
@ -220,6 +372,12 @@ int gpg_io_fetch(unsigned char *buffer, int len) {
|
||||
|
||||
#define MAX_OUT GPG_APDU_LENGTH
|
||||
|
||||
/**
|
||||
* APDU Receive/transmit
|
||||
*
|
||||
* @param[in] flag io buffer flag
|
||||
*
|
||||
*/
|
||||
void gpg_io_do(unsigned int io_flags) {
|
||||
unsigned int rx = 0;
|
||||
|
||||
|
@ -17,6 +17,13 @@
|
||||
|
||||
#include "gpg_vars.h"
|
||||
|
||||
/**
|
||||
* Set a new MSE configuration
|
||||
*
|
||||
* @param[in] crt selected key
|
||||
* @param[in] ref new operation type
|
||||
*
|
||||
*/
|
||||
static void gpg_mse_set(int crt, int ref) {
|
||||
if (crt == KEY_AUT) {
|
||||
if (ref == 0x02) {
|
||||
@ -37,11 +44,21 @@ static void gpg_mse_set(int crt, int ref) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset MSE config
|
||||
*
|
||||
*/
|
||||
void gpg_mse_reset() {
|
||||
gpg_mse_set(KEY_AUT, 0x03);
|
||||
gpg_mse_set(KEY_DEC, 0x02);
|
||||
}
|
||||
|
||||
/**
|
||||
* APDU handler to Manage Security Environment
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_mse() {
|
||||
int crt, ref;
|
||||
|
||||
|
@ -18,6 +18,14 @@
|
||||
#include "gpg_vars.h"
|
||||
#include "gpg_ux.h"
|
||||
|
||||
/**
|
||||
* Get Pin structure from reference ID value
|
||||
*
|
||||
* @param[in] pinref PinCode reference ID
|
||||
*
|
||||
* @return Pin structure, or NULL if invalid
|
||||
*
|
||||
*/
|
||||
gpg_pin_t *gpg_pin_get_pin(int pinref) {
|
||||
switch (pinref) {
|
||||
case PIN_ID_PW1:
|
||||
@ -31,6 +39,14 @@ gpg_pin_t *gpg_pin_get_pin(int pinref) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Pin index from reference ID value
|
||||
*
|
||||
* @param[in] pinref PinCode reference ID
|
||||
*
|
||||
* @return Pin index
|
||||
*
|
||||
*/
|
||||
static int gpg_pin_get_state_index(unsigned int pinref) {
|
||||
switch (pinref) {
|
||||
case PIN_ID_PW1:
|
||||
@ -45,6 +61,16 @@ static int gpg_pin_get_state_index(unsigned int pinref) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare the PinCode hash and handle the associated counter
|
||||
*
|
||||
* @param[in] pin PinCode reference to check
|
||||
* @param[in] pin_val PinCode value
|
||||
* @param[in] pin_len PinCode length
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_pin_check_internal(gpg_pin_t *pin, const unsigned char *pin_val, int pin_len) {
|
||||
unsigned int counter;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
@ -75,6 +101,16 @@ end:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the PinCode value and set verification status
|
||||
*
|
||||
* @param[in] pin PinCode reference to check
|
||||
* @param[in] pin_val PinCode value
|
||||
* @param[in] pin_len PinCode length
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_pin_check(gpg_pin_t *pin, int pinID, const unsigned char *pin_val, unsigned int pin_len) {
|
||||
int sw = SW_UNKNOWN;
|
||||
gpg_pin_set_verified(pinID, 0);
|
||||
@ -85,6 +121,16 @@ int gpg_pin_check(gpg_pin_t *pin, int pinID, const unsigned char *pin_val, unsig
|
||||
return sw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the PinCode value in NVRam
|
||||
*
|
||||
* @param[in] pin PinCode reference to set
|
||||
* @param[in] pin_val PinCode value
|
||||
* @param[in] pin_len PinCode length
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) {
|
||||
cx_sha256_t sha256;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
@ -103,6 +149,13 @@ end:
|
||||
return SW_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Change the Pin verification status
|
||||
*
|
||||
* @param[in] pinID PinCode ID to change
|
||||
* @param[in] verified new status
|
||||
*
|
||||
*/
|
||||
void gpg_pin_set_verified(int pinID, int verified) {
|
||||
int idx;
|
||||
idx = gpg_pin_get_state_index(pinID);
|
||||
@ -111,6 +164,14 @@ void gpg_pin_set_verified(int pinID, int verified) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the selected Pin is verified
|
||||
*
|
||||
* @param[in] pinID PinCode ID to check
|
||||
*
|
||||
* @return 0 or 1 (false or true)
|
||||
*
|
||||
*/
|
||||
int gpg_pin_is_verified(int pinID) {
|
||||
int idx;
|
||||
idx = gpg_pin_get_state_index(pinID);
|
||||
@ -120,10 +181,24 @@ int gpg_pin_is_verified(int pinID) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the selected Pin is blocked
|
||||
*
|
||||
* @param[in] pin PinCode reference to check
|
||||
*
|
||||
* @return 0 or 1 (false or true)
|
||||
*
|
||||
*/
|
||||
int gpg_pin_is_blocked(gpg_pin_t *pin) {
|
||||
return pin->counter == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* APDU handler to Verify PinCode
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_verify() {
|
||||
int sw = SW_UNKNOWN;
|
||||
gpg_pin_t *pin;
|
||||
@ -196,6 +271,12 @@ int gpg_apdu_verify() {
|
||||
return SW_WRONG_DATA;
|
||||
}
|
||||
|
||||
/**
|
||||
* APDU handler to Change PinCode
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_change_ref_data() {
|
||||
int sw = SW_UNKNOWN;
|
||||
gpg_pin_t *pin;
|
||||
@ -237,6 +318,12 @@ int gpg_apdu_change_ref_data() {
|
||||
return sw;
|
||||
}
|
||||
|
||||
/**
|
||||
* APDU handler to Reste PinCode or Counter
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_reset_retry_counter() {
|
||||
int sw = SW_UNKNOWN;
|
||||
gpg_pin_t *pin_pw1;
|
||||
|
@ -58,12 +58,24 @@ const unsigned char gpg_oid_sha512[] = {0x30,
|
||||
0x04,
|
||||
0x40};
|
||||
|
||||
/**
|
||||
* Reset PW1 verified status
|
||||
*
|
||||
*/
|
||||
static void gpg_pso_reset_PW1() {
|
||||
if (N_gpg_pstate->PW_status[0] == 0) {
|
||||
gpg_pin_set_verified(PIN_ID_PW1, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a Digital Signature
|
||||
*
|
||||
* @param[in] sigKey signing key
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
static int gpg_sign(gpg_key_t *sigkey) {
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
if (sigkey->attributes.value[0] == KEY_ID_RSA) {
|
||||
@ -180,6 +192,12 @@ end:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* APDU handler to Perform Security Operation
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_pso() {
|
||||
unsigned int t, l, ksz;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
@ -387,6 +405,12 @@ end:
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* APDU handler to Internal Authentication
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_internal_authenticate() {
|
||||
// --- PSO:AUTH ---
|
||||
if (G_gpg_vstate.kslot->aut.UIF[0]) {
|
||||
|
@ -20,6 +20,12 @@
|
||||
const unsigned char C_MF[] = {0x3F, 0x00};
|
||||
const unsigned char C_ATR[] = {0x2F, 0x02};
|
||||
|
||||
/**
|
||||
* APDU handler to Select the card
|
||||
*
|
||||
* @return Status Word
|
||||
*
|
||||
*/
|
||||
int gpg_apdu_select() {
|
||||
int sw = SW_UNKNOWN;
|
||||
|
||||
|
@ -18,6 +18,10 @@
|
||||
|
||||
#include "usbd_ccid_if.h"
|
||||
|
||||
/**
|
||||
* Reset CCID
|
||||
*
|
||||
*/
|
||||
void ui_CCID_reset(void) {
|
||||
io_usb_ccid_set_card_inserted(0);
|
||||
io_usb_ccid_set_card_inserted(1);
|
||||
|
@ -39,6 +39,14 @@ unsigned int ui_pinentry_action_button(unsigned int button_mask, unsigned int bu
|
||||
|
||||
/* ------------------------------- Helpers UX ------------------------------- */
|
||||
|
||||
/**
|
||||
* Display popup message on screen
|
||||
*
|
||||
* @param[in] msg1 1st part of the message
|
||||
* @param[in] msg2 2nd part of the message
|
||||
* @param[in] menu_display next page display callback
|
||||
*
|
||||
*/
|
||||
void ui_info(const char *msg1, const char *msg2, const void *menu_display, unsigned int value) {
|
||||
explicit_bzero(&G_gpg_vstate.ui_dogsays[0], sizeof(ux_menu_entry_t));
|
||||
G_gpg_vstate.ui_dogsays[0].callback = menu_display;
|
||||
@ -95,11 +103,25 @@ const bagl_element_t ui_uifconfirm_action[] = {
|
||||
G_gpg_vstate.menu},
|
||||
};
|
||||
|
||||
/**
|
||||
* UIF page display
|
||||
*
|
||||
* @param[in] value unused
|
||||
*
|
||||
*/
|
||||
void ui_menu_uifconfirm_display(unsigned int value) {
|
||||
UNUSED(value);
|
||||
UX_DISPLAY(ui_uifconfirm_action, (void *) ui_uifconfirm_predisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF page display preparation callback
|
||||
*
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_uifconfirm_predisplay(const bagl_element_t *element) {
|
||||
explicit_bzero(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu));
|
||||
|
||||
@ -140,6 +162,15 @@ unsigned int ui_uifconfirm_predisplay(const bagl_element_t *element) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF page Action callback
|
||||
*
|
||||
* @param[in] button_mask selected button
|
||||
* @param[in] button_mask_counter unused
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_uifconfirm_action_button(unsigned int button_mask,
|
||||
unsigned int button_mask_counter) {
|
||||
UNUSED(button_mask_counter);
|
||||
@ -216,6 +247,14 @@ const bagl_element_t ui_pinconfirm_action[] = {
|
||||
G_gpg_vstate.menu},
|
||||
};
|
||||
|
||||
/**
|
||||
* Pin Confirm display preparation callback
|
||||
*
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_pinconfirm_predisplay(const bagl_element_t *element) {
|
||||
if (element->component.userid == 1) {
|
||||
if ((G_gpg_vstate.io_p2 == PIN_ID_PW1) || (G_gpg_vstate.io_p2 == PIN_ID_PW2) ||
|
||||
@ -239,11 +278,26 @@ unsigned int ui_pinconfirm_predisplay(const bagl_element_t *element) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Confirm page display
|
||||
*
|
||||
* @param[in] value unused
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinconfirm_display(unsigned int value) {
|
||||
UNUSED(value);
|
||||
UX_DISPLAY(ui_pinconfirm_action, (void *) ui_pinconfirm_predisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Confirm Action callback
|
||||
*
|
||||
* @param[in] button_mask selected button
|
||||
* @param[in] button_mask_counter unused
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_pinconfirm_action_button(unsigned int button_mask,
|
||||
unsigned int button_mask_counter) {
|
||||
UNUSED(button_mask_counter);
|
||||
@ -317,6 +371,14 @@ const bagl_element_t ui_pinentry_action[] = {
|
||||
|
||||
static const char C_pin_digit[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '<', 'A', 'V'};
|
||||
|
||||
/**
|
||||
* Pin Entry display preparation callback
|
||||
*
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_pinentry_predisplay(const bagl_element_t *element) {
|
||||
if (element->component.userid == 1) {
|
||||
if (G_gpg_vstate.io_ins == INS_CHANGE_REFERENCE_DATA) {
|
||||
@ -368,6 +430,12 @@ unsigned int ui_pinentry_predisplay(const bagl_element_t *element) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Entry page display
|
||||
*
|
||||
* @param[in] value indicate if pin is reset
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinentry_display(unsigned int value) {
|
||||
if (value == 0) {
|
||||
explicit_bzero(G_gpg_vstate.ux_pinentry, sizeof(G_gpg_vstate.ux_pinentry));
|
||||
@ -377,6 +445,10 @@ void ui_menu_pinentry_display(unsigned int value) {
|
||||
UX_DISPLAY(ui_pinentry_action, (void *) ui_pinentry_predisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Entry Validation callback
|
||||
*
|
||||
*/
|
||||
static void validate_pin() {
|
||||
unsigned int offset, len, sw = SW_UNKNOWN;
|
||||
gpg_pin_t *pin;
|
||||
@ -452,6 +524,15 @@ static void validate_pin() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Entry page Action callback
|
||||
*
|
||||
* @param[in] button_mask selected button
|
||||
* @param[in] button_mask_counter unused
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_pinentry_action_button(unsigned int button_mask, unsigned int button_mask_counter) {
|
||||
UNUSED(button_mask_counter);
|
||||
unsigned int offset = G_gpg_vstate.ux_pinLen;
|
||||
@ -541,6 +622,15 @@ const ux_menu_entry_t ui_menu_tmpl_type[] = {
|
||||
{ui_menu_template, NULL, 0, &C_icon_back, "Back", NULL, 61, 40},
|
||||
UX_MENU_END};
|
||||
|
||||
/**
|
||||
* Template page display preparation callback
|
||||
*
|
||||
* @param[in] entry selected menu to display
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return Eelement to display
|
||||
*
|
||||
*/
|
||||
const bagl_element_t *ui_menu_template_predisplay(const ux_menu_entry_t *entry,
|
||||
bagl_element_t *element) {
|
||||
if (element->component.userid == 0x20) {
|
||||
@ -593,10 +683,22 @@ const bagl_element_t *ui_menu_template_predisplay(const ux_menu_entry_t *entry,
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Template page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_template_display(unsigned int value) {
|
||||
UX_MENU_DISPLAY(value, ui_menu_template, ui_menu_template_predisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template Action callback
|
||||
*
|
||||
* @param[in] value unused
|
||||
*
|
||||
*/
|
||||
void ui_menu_tmpl_set_action(unsigned int value) {
|
||||
UNUSED(value);
|
||||
LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH);
|
||||
@ -674,11 +776,23 @@ void ui_menu_tmpl_set_action(unsigned int value) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Key Name Template Action callback
|
||||
*
|
||||
* @param[in] value selected key
|
||||
*
|
||||
*/
|
||||
void ui_menu_tmpl_key_action(unsigned int value) {
|
||||
G_gpg_vstate.ux_key = value;
|
||||
ui_menu_template_display(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Key Type Template Action callback
|
||||
*
|
||||
* @param[in] value selected key
|
||||
*
|
||||
*/
|
||||
void ui_menu_tmpl_type_action(unsigned int value) {
|
||||
G_gpg_vstate.ux_type = value;
|
||||
ui_menu_template_display(1);
|
||||
@ -693,6 +807,15 @@ const ux_menu_entry_t ui_menu_seedmode[] = {
|
||||
{ui_menu_settings, NULL, 0, &C_icon_back, "Back", NULL, 61, 40},
|
||||
UX_MENU_END};
|
||||
|
||||
/**
|
||||
* Seed Mode page display preparation callback
|
||||
*
|
||||
* @param[in] entry selected menu to display
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return Eelement to display
|
||||
*
|
||||
*/
|
||||
const bagl_element_t *ui_menu_seedmode_predisplay(const ux_menu_entry_t *entry,
|
||||
bagl_element_t *element) {
|
||||
if (element->component.userid == 0x20) {
|
||||
@ -707,10 +830,22 @@ const bagl_element_t *ui_menu_seedmode_predisplay(const ux_menu_entry_t *entry,
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed Mode page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_seedmode_display(unsigned int value) {
|
||||
UX_MENU_DISPLAY(value, ui_menu_seedmode, ui_menu_seedmode_predisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed Mode toggle callback
|
||||
*
|
||||
* @param[in] value selected seed mode
|
||||
*
|
||||
*/
|
||||
static void toggle_seed(unsigned int value) {
|
||||
if (value != 128) {
|
||||
return;
|
||||
@ -746,6 +881,12 @@ const ux_menu_entry_t ui_seed_warning[] = {
|
||||
{NULL, toggle_seed, 128, &C_icon_validate_14, "Disable", NULL, 0, 0},
|
||||
UX_MENU_END};
|
||||
|
||||
/**
|
||||
* Seed Mode Action callback
|
||||
*
|
||||
* @param[in] value selected mode
|
||||
*
|
||||
*/
|
||||
void ui_menu_seedmode_action(unsigned int value) {
|
||||
if (value == 0) {
|
||||
// Request deactivate
|
||||
@ -772,10 +913,25 @@ const ux_menu_entry_t ui_menu_pinmode[] = {
|
||||
{ui_menu_settings, NULL, 0, &C_icon_back, "Back", NULL, 61, 40},
|
||||
UX_MENU_END};
|
||||
|
||||
/**
|
||||
* Pin Mode page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinmode_display(unsigned int value) {
|
||||
UX_MENU_DISPLAY(value, ui_menu_pinmode, ui_menu_pinmode_predisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Mode page display preparation callback
|
||||
*
|
||||
* @param[in] entry selected menu to display
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return element to display
|
||||
*
|
||||
*/
|
||||
const bagl_element_t *ui_menu_pinmode_predisplay(const ux_menu_entry_t *entry,
|
||||
bagl_element_t *element) {
|
||||
if (element->component.userid == 0x20) {
|
||||
@ -811,6 +967,12 @@ const ux_menu_entry_t ui_trust_warning[] = {
|
||||
{NULL, ui_menu_pinmode_action, 127, &C_icon_validate_14, "Select", NULL, 61, 40},
|
||||
UX_MENU_END};
|
||||
|
||||
/**
|
||||
* Pin Mode Action callback
|
||||
*
|
||||
* @param[in] value selected mode
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinmode_action(unsigned int value) {
|
||||
unsigned char s;
|
||||
value = value & 0x7FFF;
|
||||
@ -886,6 +1048,15 @@ void ui_menu_uifmode_display(unsigned int value) {
|
||||
UX_MENU_DISPLAY(value, ui_menu_uifmode, ui_menu_uifmode_predisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF page display preparation callback
|
||||
*
|
||||
* @param[in] entry selected menu to display
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return element to display
|
||||
*
|
||||
*/
|
||||
const bagl_element_t *ui_menu_uifmode_predisplay(const ux_menu_entry_t *entry,
|
||||
bagl_element_t *element) {
|
||||
if (element->component.userid == 0x20) {
|
||||
@ -916,6 +1087,12 @@ const bagl_element_t *ui_menu_uifmode_predisplay(const ux_menu_entry_t *entry,
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF Action callback
|
||||
*
|
||||
* @param[in] value selected key
|
||||
*
|
||||
*/
|
||||
void ui_menu_uifmode_action(unsigned int value) {
|
||||
unsigned char *uif;
|
||||
unsigned char new_uif;
|
||||
@ -954,6 +1131,12 @@ const ux_menu_entry_t ui_menu_reset[] = {
|
||||
{NULL, ui_menu_reset_action, 0, NULL, "Yes", NULL, 0, 0},
|
||||
UX_MENU_END};
|
||||
|
||||
/**
|
||||
* Reset Action callback
|
||||
*
|
||||
* @param[in] value unused
|
||||
*
|
||||
*/
|
||||
void ui_menu_reset_action(unsigned int value) {
|
||||
UNUSED(value);
|
||||
unsigned char magic[4];
|
||||
@ -1001,6 +1184,15 @@ const ux_menu_entry_t ui_menu_main[] = {
|
||||
{NULL, (void *) os_sched_exit, 0, &C_icon_dashboard, "Quit app", NULL, 50, 29},
|
||||
UX_MENU_END};
|
||||
|
||||
/**
|
||||
* Main page display preparation callback
|
||||
*
|
||||
* @param[in] entry selected menu to display
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return Eelement to display
|
||||
*
|
||||
*/
|
||||
const bagl_element_t *ui_menu_main_predisplay(const ux_menu_entry_t *entry,
|
||||
bagl_element_t *element) {
|
||||
if (entry == &ui_menu_main[0]) {
|
||||
@ -1026,12 +1218,22 @@ const bagl_element_t *ui_menu_main_predisplay(const ux_menu_entry_t *entry,
|
||||
}
|
||||
return element;
|
||||
}
|
||||
/**
|
||||
* Main page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_main_display(unsigned int value) {
|
||||
UX_MENU_DISPLAY(value, ui_menu_main, ui_menu_main_predisplay);
|
||||
}
|
||||
|
||||
/* --- INIT --- */
|
||||
|
||||
/**
|
||||
* home page definition
|
||||
*
|
||||
*/
|
||||
void ui_init(void) {
|
||||
ui_menu_main_display(0);
|
||||
// setup the first screen changing
|
||||
|
@ -26,6 +26,7 @@
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- NanoX UI layout --- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
void ui_menu_tmpl_set_action(unsigned int value);
|
||||
void ui_menu_tmpl_key_action(unsigned int value);
|
||||
void ui_menu_tmpl_type_action(unsigned int value);
|
||||
@ -51,6 +52,13 @@ UX_STEP_CB(ux_menu_popup_1_step,
|
||||
|
||||
UX_FLOW(ux_flow_popup, &ux_menu_popup_1_step);
|
||||
|
||||
/**
|
||||
* Display popup message on screen
|
||||
*
|
||||
* @param[in] msg1 1st part of the message
|
||||
* @param[in] msg2 2nd part of the message
|
||||
*
|
||||
*/
|
||||
void ui_info(const char *msg1, const char *msg2) {
|
||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s. %s", msg1, msg2);
|
||||
ux_flow_init(0, ux_flow_popup, NULL);
|
||||
@ -75,6 +83,10 @@ UX_FLOW(ux_flow_uifconfirm,
|
||||
&ux_menu_uifconfirm_3_step,
|
||||
&ux_menu_uifconfirm_2_step);
|
||||
|
||||
/**
|
||||
* UIF page display preparation callback
|
||||
*
|
||||
*/
|
||||
void ui_menu_uifconfirm_predisplay() {
|
||||
switch (G_gpg_vstate.io_ins) {
|
||||
case INS_INTERNAL_AUTHENTICATE:
|
||||
@ -103,10 +115,24 @@ void ui_menu_uifconfirm_predisplay() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_uifconfirm_display(unsigned int value) {
|
||||
ui_flow_display(ux_flow_uifconfirm, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF Confirmation Action callback
|
||||
*
|
||||
* @param[in] confirm indicate if the user press 'Confirm' or 'Cancel'
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_uifconfirm_action(unsigned int value) {
|
||||
unsigned int sw = SW_SECURITY_UIF_ISSUE;
|
||||
|
||||
@ -165,6 +191,10 @@ UX_FLOW(ux_flow_pinconfirm,
|
||||
&ux_menu_pinconfirm_2_step,
|
||||
&ux_menu_pinconfirm_3_step);
|
||||
|
||||
/**
|
||||
* Pin Confirm page display preparation callback
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinconfirm_predisplay() {
|
||||
if ((G_gpg_vstate.io_p2 == PIN_ID_PW1) || (G_gpg_vstate.io_p2 == PIN_ID_PW2) ||
|
||||
(G_gpg_vstate.io_p2 == PIN_ID_PW3)) {
|
||||
@ -178,11 +208,25 @@ void ui_menu_pinconfirm_predisplay() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Confirm page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinconfirm_display(unsigned int value) {
|
||||
UNUSED(value);
|
||||
ux_flow_init(0, ux_flow_pinconfirm, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Confirm Confirmation Action callback
|
||||
*
|
||||
* @param[in] confirm indicate if the user press 'Confirm' or 'Cancel'
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_pinconfirm_action(unsigned int value) {
|
||||
unsigned int sw = SW_UNKNOWN;
|
||||
|
||||
@ -250,6 +294,14 @@ const bagl_element_t ui_pinentry_action[] = {
|
||||
|
||||
static const char C_pin_digit[] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '<', 'A', 'V'};
|
||||
|
||||
/**
|
||||
* Pin Entry page display preparation callback
|
||||
*
|
||||
* @param[in] element selected element to display
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_pinentry_predisplay(const bagl_element_t *element) {
|
||||
if (element->component.userid == 1) {
|
||||
if (G_gpg_vstate.io_ins == INS_CHANGE_REFERENCE_DATA) {
|
||||
@ -301,6 +353,12 @@ unsigned int ui_pinentry_predisplay(const bagl_element_t *element) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Entry page display
|
||||
*
|
||||
* @param[in] value indicate if pin is reset
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinentry_display(unsigned int value) {
|
||||
if (value == 0) {
|
||||
explicit_bzero(G_gpg_vstate.ux_pinentry, sizeof(G_gpg_vstate.ux_pinentry));
|
||||
@ -310,6 +368,10 @@ void ui_menu_pinentry_display(unsigned int value) {
|
||||
UX_DISPLAY(ui_pinentry_action, (void *) ui_pinentry_predisplay);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Entry Validation callback
|
||||
*
|
||||
*/
|
||||
static void validate_pin() {
|
||||
unsigned int offset, len, sw = SW_UNKNOWN;
|
||||
gpg_pin_t *pin;
|
||||
@ -385,6 +447,15 @@ static void validate_pin() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Entry page Action callback
|
||||
*
|
||||
* @param[in] button_mask selected button
|
||||
* @param[in] button_mask_counter unused
|
||||
*
|
||||
* @return Error code
|
||||
*
|
||||
*/
|
||||
unsigned int ui_pinentry_action_button(unsigned int button_mask, unsigned int button_mask_counter) {
|
||||
UNUSED(button_mask_counter);
|
||||
unsigned int offset = G_gpg_vstate.ux_pinLen;
|
||||
@ -451,14 +522,28 @@ const char *const tmpl_key_getter_values[] = {LABEL_SIG, LABEL_DEC, LABEL_AUT};
|
||||
|
||||
const unsigned int tmpl_key_getter_values_map[] = {1, 2, 3};
|
||||
|
||||
const char *tmpl_key_getter(unsigned int idx) {
|
||||
/**
|
||||
* Helper to get the key name
|
||||
*
|
||||
* @param[in] idx key index
|
||||
*
|
||||
* @return key name, or NULL if not found
|
||||
*
|
||||
*/
|
||||
static const char *tmpl_key_getter(unsigned int idx) {
|
||||
if (idx < ARRAYLEN(tmpl_key_getter_values)) {
|
||||
return tmpl_key_getter_values[idx];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void tmpl_key_selector(unsigned int idx) {
|
||||
/**
|
||||
* Helper to select the key name and display the Template page
|
||||
*
|
||||
* @param[in] idx key index
|
||||
*
|
||||
*/
|
||||
static void tmpl_key_selector(unsigned int idx) {
|
||||
if (idx < ARRAYLEN(tmpl_key_getter_values)) {
|
||||
idx = tmpl_key_getter_values_map[idx];
|
||||
} else {
|
||||
@ -486,14 +571,28 @@ const unsigned int tmpl_type_getter_values_map[] = {2048,
|
||||
CX_CURVE_SECP256R1,
|
||||
CX_CURVE_Ed25519};
|
||||
|
||||
const char *tmpl_type_getter(unsigned int idx) {
|
||||
/**
|
||||
* Helper to get the key type
|
||||
*
|
||||
* @param[in] idx key index
|
||||
*
|
||||
* @return key type, or NULL if not found
|
||||
*
|
||||
*/
|
||||
static const char *tmpl_type_getter(unsigned int idx) {
|
||||
if (idx < ARRAYLEN(tmpl_type_getter_values)) {
|
||||
return tmpl_type_getter_values[idx];
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void tmpl_type_selector(unsigned int idx) {
|
||||
/**
|
||||
* Helper to select the key type and display the Template page
|
||||
*
|
||||
* @param[in] idx key index
|
||||
*
|
||||
*/
|
||||
static void tmpl_type_selector(unsigned int idx) {
|
||||
if (idx < ARRAYLEN(tmpl_type_getter_values)) {
|
||||
idx = tmpl_type_getter_values_map[idx];
|
||||
} else {
|
||||
@ -546,6 +645,10 @@ UX_FLOW(ux_flow_template,
|
||||
&ux_menu_template_3_step,
|
||||
&ux_menu_template_4_step);
|
||||
|
||||
/**
|
||||
* Template page display preparation callback
|
||||
*
|
||||
*/
|
||||
void ui_menu_template_predisplay() {
|
||||
switch (G_gpg_vstate.ux_key) {
|
||||
case 1:
|
||||
@ -589,10 +692,21 @@ void ui_menu_template_predisplay() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_template_display(unsigned int value) {
|
||||
ui_flow_display(ux_flow_template, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Template Action callback
|
||||
*
|
||||
* @param[in] value unused
|
||||
*/
|
||||
void ui_menu_tmpl_set_action(unsigned int value) {
|
||||
UNUSED(value);
|
||||
LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH);
|
||||
@ -696,14 +810,28 @@ UX_STEP_CB(ux_menu_seedmode_2_step,
|
||||
|
||||
UX_FLOW(ux_flow_seedmode, &ux_menu_seedmode_1_step, &ux_menu_seedmode_2_step);
|
||||
|
||||
/**
|
||||
* Seed Mode page display preparation callback
|
||||
*
|
||||
*/
|
||||
void ui_menu_seedmode_predisplay() {
|
||||
snprintf(CUR_SEED_MODE, sizeof(CUR_SEED_MODE), "%s", G_gpg_vstate.seed_mode ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed Mode page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_seedmode_display(unsigned int value) {
|
||||
ui_flow_display(ux_flow_seedmode, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed Mode toggle callback
|
||||
*
|
||||
*/
|
||||
static void toggle_seed() {
|
||||
if (G_gpg_vstate.seed_mode) {
|
||||
G_gpg_vstate.seed_mode = 0;
|
||||
@ -746,6 +874,12 @@ UX_FLOW(ui_seed_disabling_flow,
|
||||
&ui_seed_warning_flow_cancel_step,
|
||||
&ui_seed_disabling_flow_confirm_step);
|
||||
|
||||
/**
|
||||
* Seed Mode Action callback
|
||||
*
|
||||
* @param[in] value seed mode state
|
||||
*
|
||||
*/
|
||||
void ui_menu_seedmode_action(unsigned int value) {
|
||||
if (value == 1) {
|
||||
// Current value is 'enable' -> Confirm deactivate
|
||||
@ -807,6 +941,10 @@ UX_FLOW(ux_flow_pinmode,
|
||||
&ux_menu_pinmode_4_step,
|
||||
&ux_menu_pinmode_5_step);
|
||||
|
||||
/**
|
||||
* Pin Mode page display preparation callback
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinmode_predisplay() {
|
||||
snprintf(ONSCR_BUFF, 5, "%s", PIN_MODE_SCREEN == G_gpg_vstate.pinmode ? "ON" : "OFF");
|
||||
snprintf(CONFI_BUFF, 5, "%s", PIN_MODE_CONFIRM == G_gpg_vstate.pinmode ? "ON" : "OFF");
|
||||
@ -826,6 +964,12 @@ void ui_menu_pinmode_predisplay() {
|
||||
PIN_MODE_TRUST == N_gpg_pstate->config_pin[0] ? "(Default)" : "");
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Mode page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinmode_display(unsigned int value) {
|
||||
ui_flow_display(ux_flow_pinmode, value);
|
||||
}
|
||||
@ -860,6 +1004,12 @@ UX_FLOW(ui_trust_selecting_flow,
|
||||
&ui_trust_warning_flow_cancel_step,
|
||||
&ui_trust_selecting_flow_confirm_step);
|
||||
|
||||
/**
|
||||
* Pin Mode Action callback
|
||||
*
|
||||
* @param[in] value token indication the selected action
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinmode_action(unsigned int value) {
|
||||
unsigned char s;
|
||||
|
||||
@ -956,16 +1106,32 @@ UX_FLOW(ux_flow_uif,
|
||||
&ux_menu_uif_3_step,
|
||||
&ux_menu_uif_4_step);
|
||||
|
||||
/**
|
||||
* UIF page display preparation callback
|
||||
*
|
||||
*/
|
||||
void ui_menu_uifmode_predisplay() {
|
||||
snprintf(SIG_BUFF, sizeof(SIG_BUFF), "%s", G_gpg_vstate.kslot->sig.UIF[0] ? "ON" : "OFF");
|
||||
snprintf(DEC_BUFF, sizeof(DEC_BUFF), "%s", G_gpg_vstate.kslot->dec.UIF[0] ? "ON" : "OFF");
|
||||
snprintf(AUT_BUFF, sizeof(AUT_BUFF), "%s", G_gpg_vstate.kslot->aut.UIF[0] ? "ON" : "OFF");
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_uifmode_display(unsigned int value) {
|
||||
ui_flow_display(ux_flow_uif, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF Confirmation Action callback
|
||||
*
|
||||
* @param[in] value indicate the targeted key
|
||||
*
|
||||
*/
|
||||
void ui_menu_uifmode_action(unsigned int value) {
|
||||
unsigned char *uif;
|
||||
unsigned char new_uif;
|
||||
@ -1009,10 +1175,22 @@ UX_STEP_CB(ux_menu_reset_2_step, bn, ui_menu_reset_action(0), {"YES!", "Reset th
|
||||
|
||||
UX_FLOW(ux_flow_reset, &ux_menu_reset_1_step, &ux_menu_reset_2_step);
|
||||
|
||||
/**
|
||||
* Reset page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_reset_display(unsigned int value) {
|
||||
ux_flow_init(value, ux_flow_reset, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset Action callback
|
||||
*
|
||||
* @param[in] value unused
|
||||
*
|
||||
*/
|
||||
void ui_menu_reset_action(unsigned int value) {
|
||||
UNUSED(value);
|
||||
unsigned char magic[4];
|
||||
@ -1031,6 +1209,14 @@ void ui_menu_reset_action(unsigned int value) {
|
||||
const char *const settings_getter_values[] =
|
||||
{"Key template", "Seed mode", "PIN mode", "UIF mode", "Reset", "Back"};
|
||||
|
||||
/**
|
||||
* Helper to retrieve page title
|
||||
*
|
||||
* @param[in] idx page index
|
||||
*
|
||||
* @return page title, or NULL
|
||||
*
|
||||
*/
|
||||
const char *settings_getter(unsigned int idx) {
|
||||
if (idx < ARRAYLEN(settings_getter_values)) {
|
||||
return settings_getter_values[idx];
|
||||
@ -1038,6 +1224,12 @@ const char *settings_getter(unsigned int idx) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings page display
|
||||
*
|
||||
* @param[in] idx page index
|
||||
*
|
||||
*/
|
||||
void settings_selector(unsigned int idx) {
|
||||
switch (idx) {
|
||||
case 0:
|
||||
@ -1061,6 +1253,12 @@ void settings_selector(unsigned int idx) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_settings_display(unsigned int value) {
|
||||
ux_menulist_init_select(G_ux.stack_count - 1, settings_getter, settings_selector, value);
|
||||
}
|
||||
@ -1112,6 +1310,10 @@ UX_FLOW(ux_flow_slot,
|
||||
&ux_menu_slot_4_step,
|
||||
&ux_menu_slot_5_step);
|
||||
|
||||
/**
|
||||
* Slot page display preparation callback
|
||||
*
|
||||
*/
|
||||
void ui_menu_slot_predisplay() {
|
||||
snprintf(SLOT1,
|
||||
sizeof(SLOT1),
|
||||
@ -1130,10 +1332,22 @@ void ui_menu_slot_predisplay() {
|
||||
3 == G_gpg_vstate.slot + 1 ? "+" : " ");
|
||||
}
|
||||
|
||||
/**
|
||||
* Slot page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_slot_display(unsigned int value) {
|
||||
ui_flow_display(ux_flow_slot, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Slot Action callback
|
||||
*
|
||||
* @param[in] value token indication the selected action
|
||||
*
|
||||
*/
|
||||
void ui_menu_slot_action(unsigned int value) {
|
||||
unsigned char s;
|
||||
|
||||
@ -1177,6 +1391,12 @@ UX_STEP_CB(ux_menu_info_2_step,
|
||||
|
||||
UX_FLOW(ux_flow_info, &ux_menu_info_1_step, &ux_menu_info_2_step);
|
||||
|
||||
/**
|
||||
* Info page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_info_display(unsigned int value) {
|
||||
UNUSED(value);
|
||||
ux_flow_init(0, ux_flow_info, NULL);
|
||||
@ -1210,6 +1430,10 @@ UX_FLOW(ux_flow_main,
|
||||
&ux_menu_main_4_step,
|
||||
&ux_menu_main_5_step);
|
||||
|
||||
/**
|
||||
* Main page display preparation callback
|
||||
*
|
||||
*/
|
||||
void ui_menu_main_predisplay() {
|
||||
explicit_bzero(G_gpg_vstate.ux_buff1, sizeof(G_gpg_vstate.ux_buff1));
|
||||
memmove(G_gpg_vstate.ux_buff1, (void *) (N_gpg_pstate->name.value), 20);
|
||||
@ -1230,6 +1454,12 @@ void ui_menu_main_predisplay() {
|
||||
G_gpg_vstate.slot + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Main page display
|
||||
*
|
||||
* @param[in] value flow step
|
||||
*
|
||||
*/
|
||||
void ui_menu_main_display(unsigned int value) {
|
||||
// reserve a display stack slot if none yet
|
||||
if (G_ux.stack_count == 0) {
|
||||
@ -1241,6 +1471,10 @@ void ui_menu_main_display(unsigned int value) {
|
||||
|
||||
/* --- INIT --- */
|
||||
|
||||
/**
|
||||
* home page definition
|
||||
*
|
||||
*/
|
||||
void ui_init(void) {
|
||||
ui_menu_main_display(0);
|
||||
}
|
||||
|
@ -31,32 +31,39 @@
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* --- NBGL UI layout --- */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
void ui_menu_settings();
|
||||
void ui_menu_slot_action();
|
||||
static void ui_menu_settings();
|
||||
static void ui_menu_slot_action();
|
||||
static void settings_ctrl_cb(int token, uint8_t index);
|
||||
static void ui_settings_template(void);
|
||||
static void ui_settings_seed(void);
|
||||
static void ui_settings_pin(void);
|
||||
|
||||
// contexts for background and modal pages
|
||||
// context for background and modal pages
|
||||
static nbgl_layout_t layoutCtx = {0};
|
||||
|
||||
enum {
|
||||
TOKEN_SETTINGS_TEMPLATE = FIRST_USER_TOKEN,
|
||||
TOKEN_SETTINGS_SEED,
|
||||
TOKEN_SETTINGS_PIN,
|
||||
TOKEN_SETTINGS_UIF,
|
||||
TOKEN_SETTINGS_RESET,
|
||||
};
|
||||
|
||||
/* ------------------------------- Helpers UX ------------------------------- */
|
||||
|
||||
/**
|
||||
* Display popup message on screen
|
||||
*
|
||||
* @param[in] msg1 1st part of the message
|
||||
* @param[in] msg2 2nd part of the message
|
||||
*
|
||||
*/
|
||||
static void ui_info(const char* msg1, const char* msg2, nbgl_callback_t cb, bool isSuccess) {
|
||||
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "%s\n%s", msg1, msg2);
|
||||
|
||||
nbgl_useCaseStatus((const char*) G_gpg_vstate.menu, isSuccess, cb);
|
||||
};
|
||||
|
||||
/**
|
||||
* Display Setting page header
|
||||
*
|
||||
* @param[in] title page title
|
||||
* @param[in] back_token token for back button
|
||||
* @param[in] touch_cb action callback
|
||||
*
|
||||
*/
|
||||
static void ui_setting_header(const char* title,
|
||||
uint8_t back_token,
|
||||
nbgl_layoutTouchCallback_t touch_cb) {
|
||||
@ -87,7 +94,10 @@ void app_quit(void) {
|
||||
os_sched_exit(-1);
|
||||
}
|
||||
|
||||
// home page definition
|
||||
/**
|
||||
* home page definition
|
||||
*
|
||||
*/
|
||||
void ui_init(void) {
|
||||
char name[32];
|
||||
unsigned int serial = U4BE(G_gpg_vstate.kslot->serial, 0);
|
||||
@ -129,6 +139,13 @@ enum {
|
||||
TOKEN_SLOT_BACK,
|
||||
};
|
||||
|
||||
/**
|
||||
* Slot Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void slot_cb(int token, uint8_t index) {
|
||||
switch (token) {
|
||||
case TOKEN_SLOT_BACK:
|
||||
@ -151,7 +168,11 @@ static void slot_cb(int token, uint8_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
void ui_menu_slot_action(void) {
|
||||
/**
|
||||
* Slot Navigation callback
|
||||
*
|
||||
*/
|
||||
static void ui_menu_slot_action(void) {
|
||||
nbgl_layoutRadioChoice_t choices = {0};
|
||||
nbgl_layoutButton_t buttonInfo = {0};
|
||||
static char* names[GPG_KEYS_SLOTS] = {0};
|
||||
@ -191,6 +212,7 @@ void ui_menu_slot_action(void) {
|
||||
// -----------------------------------------------------------
|
||||
|
||||
/* ------------------------------- TEMPLATE UX ------------------------------- */
|
||||
|
||||
enum {
|
||||
TOKEN_TEMPLATE_SIG = FIRST_USER_TOKEN,
|
||||
TOKEN_TEMPLATE_DEC,
|
||||
@ -222,6 +244,14 @@ static const char* const keyTypeTexts[] = {LABEL_RSA2048,
|
||||
LABEL_SECP256R1,
|
||||
LABEL_Ed25519};
|
||||
|
||||
/**
|
||||
* Determine the selected key type from its attributes
|
||||
*
|
||||
* @param[in] key token describing the selected key
|
||||
*
|
||||
* @return token describing the selected key type
|
||||
*
|
||||
*/
|
||||
static uint32_t _getKeyType(const uint8_t key) {
|
||||
uint8_t* attributes = NULL;
|
||||
uint32_t token = 0;
|
||||
@ -290,6 +320,13 @@ static uint32_t _getKeyType(const uint8_t key) {
|
||||
return token;
|
||||
}
|
||||
|
||||
/**
|
||||
* Key Template Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void template_key_cb(int token, uint8_t index) {
|
||||
LV(attributes, GPG_KEY_ATTRIBUTES_LENGTH);
|
||||
gpg_key_t* dest = NULL;
|
||||
@ -384,6 +421,13 @@ static void template_key_cb(int token, uint8_t index) {
|
||||
ui_settings_template();
|
||||
}
|
||||
|
||||
/**
|
||||
* Template Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void template_cb(int token, uint8_t index) {
|
||||
UNUSED(index);
|
||||
static nbgl_layoutRadioChoice_t choices = {0};
|
||||
@ -411,6 +455,10 @@ static void template_cb(int token, uint8_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Template Navigation callback
|
||||
*
|
||||
*/
|
||||
static void ui_settings_template(void) {
|
||||
nbgl_layoutBar_t bar = {0};
|
||||
uint32_t i;
|
||||
@ -458,11 +506,18 @@ static void ui_settings_template(void) {
|
||||
}
|
||||
|
||||
/* --------------------------------- SEED UX --------------------------------- */
|
||||
|
||||
enum {
|
||||
TOKEN_SEED = FIRST_USER_TOKEN,
|
||||
TOKEN_SEED_BACK,
|
||||
};
|
||||
|
||||
/**
|
||||
* Seed Mode Confirmation callback
|
||||
*
|
||||
* @param[in] confirm indicate if the user press 'Confirm' or 'Cancel'
|
||||
*
|
||||
*/
|
||||
void seed_confirm_cb(bool confirm) {
|
||||
if (confirm) {
|
||||
G_gpg_vstate.seed_mode = 0;
|
||||
@ -473,6 +528,13 @@ void seed_confirm_cb(bool confirm) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void seed_cb(int token, uint8_t index) {
|
||||
switch (token) {
|
||||
case TOKEN_SEED_BACK:
|
||||
@ -494,6 +556,10 @@ static void seed_cb(int token, uint8_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Seed Navigation callback
|
||||
*
|
||||
*/
|
||||
static void ui_settings_seed(void) {
|
||||
static nbgl_layoutSwitch_t option = {0};
|
||||
|
||||
@ -517,6 +583,12 @@ enum {
|
||||
TOKEN_PIN_BACK,
|
||||
};
|
||||
|
||||
/**
|
||||
* Trust Mode Confirmation callback
|
||||
*
|
||||
* @param[in] confirm indicate if the user press 'Confirm' or 'Cancel'
|
||||
*
|
||||
*/
|
||||
void trust_cb(bool confirm) {
|
||||
if (confirm) {
|
||||
G_gpg_vstate.pinmode = G_gpg_vstate.pinmode_req;
|
||||
@ -526,6 +598,13 @@ void trust_cb(bool confirm) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void pin_cb(int token, uint8_t index) {
|
||||
const char* err = NULL;
|
||||
switch (token) {
|
||||
@ -582,6 +661,10 @@ static void pin_cb(int token, uint8_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Navigation callback
|
||||
*
|
||||
*/
|
||||
static void ui_settings_pin(void) {
|
||||
static nbgl_layoutRadioChoice_t choices = {0};
|
||||
nbgl_layoutButton_t buttonInfo = {0};
|
||||
@ -624,6 +707,7 @@ static void ui_settings_pin(void) {
|
||||
}
|
||||
|
||||
/* --------------------------------- UIF UX ---------------------------------- */
|
||||
|
||||
enum {
|
||||
TOKEN_UIF_SIG = FIRST_USER_TOKEN,
|
||||
TOKEN_UIF_DEC,
|
||||
@ -631,6 +715,13 @@ enum {
|
||||
TOKEN_UIF_BACK,
|
||||
};
|
||||
|
||||
/**
|
||||
* UIF Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void uif_cb(int token, uint8_t index) {
|
||||
unsigned char* uif = NULL;
|
||||
switch (token) {
|
||||
@ -657,6 +748,10 @@ static void uif_cb(int token, uint8_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF Navigation callback
|
||||
*
|
||||
*/
|
||||
static void ui_settings_uif(void) {
|
||||
static nbgl_layoutSwitch_t option = {0};
|
||||
uint8_t nbOptions = 0;
|
||||
@ -711,10 +806,18 @@ static void ui_settings_uif(void) {
|
||||
}
|
||||
|
||||
/* -------------------------------- RESET UX --------------------------------- */
|
||||
|
||||
enum {
|
||||
TOKEN_RESET = FIRST_USER_TOKEN,
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset Navigation callback
|
||||
*
|
||||
* @param[in] page selected page to display
|
||||
* @param[in] content describe the widgets to display on the page
|
||||
*
|
||||
*/
|
||||
static bool reset_nav_cb(uint8_t page, nbgl_pageContent_t* content) {
|
||||
UNUSED(page);
|
||||
explicit_bzero(content, sizeof(nbgl_pageContent_t));
|
||||
@ -728,6 +831,13 @@ static bool reset_nav_cb(uint8_t page, nbgl_pageContent_t* content) {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void reset_ctrl_cb(int token, uint8_t index) {
|
||||
UNUSED(index);
|
||||
unsigned char magic[4] = {0, 0, 0, 0};
|
||||
@ -743,6 +853,14 @@ static void reset_ctrl_cb(int token, uint8_t index) {
|
||||
|
||||
/* ------------------------------- SETTINGS UX ------------------------------- */
|
||||
|
||||
enum {
|
||||
TOKEN_SETTINGS_TEMPLATE = FIRST_USER_TOKEN,
|
||||
TOKEN_SETTINGS_SEED,
|
||||
TOKEN_SETTINGS_PIN,
|
||||
TOKEN_SETTINGS_UIF,
|
||||
TOKEN_SETTINGS_RESET,
|
||||
};
|
||||
|
||||
enum {
|
||||
SETTINGS_PAGE_PARAMS,
|
||||
SETTINGS_PAGE_INFO,
|
||||
@ -754,6 +872,14 @@ enum {
|
||||
#else
|
||||
#define VERSION_STR "App " XSTR(APPVERSION)
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Settings Navigation callback
|
||||
*
|
||||
* @param[in] page selected page to display
|
||||
* @param[in] content describe the widgets to display on the page
|
||||
*
|
||||
*/
|
||||
static bool settings_nav_cb(uint8_t page, nbgl_pageContent_t* content) {
|
||||
bool ret = false;
|
||||
|
||||
@ -793,6 +919,13 @@ static bool settings_nav_cb(uint8_t page, nbgl_pageContent_t* content) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void settings_ctrl_cb(int token, uint8_t index) {
|
||||
UNUSED(index);
|
||||
switch (token) {
|
||||
@ -820,8 +953,11 @@ static void settings_ctrl_cb(int token, uint8_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
// settings menu definition
|
||||
void ui_menu_settings() {
|
||||
/**
|
||||
* Settings menu definition
|
||||
*
|
||||
*/
|
||||
static void ui_menu_settings() {
|
||||
nbgl_useCaseSettings(APPNAME,
|
||||
SETTINGS_PAGE_PARAMS,
|
||||
SETTINGS_PAGE_NB,
|
||||
@ -832,6 +968,13 @@ void ui_menu_settings() {
|
||||
}
|
||||
|
||||
/* ------------------------------ PIN CONFIRM UX ----------------------------- */
|
||||
|
||||
/**
|
||||
* Pin Confirmation callback
|
||||
*
|
||||
* @param[in] confirm indicate if the user press 'Confirm' or 'Cancel'
|
||||
*
|
||||
*/
|
||||
void pin_confirm_cb(bool confirm) {
|
||||
gpg_pin_set_verified(G_gpg_vstate.io_p2, confirm);
|
||||
|
||||
@ -841,6 +984,12 @@ void pin_confirm_cb(bool confirm) {
|
||||
ui_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Confirmation page display
|
||||
*
|
||||
* @param[in] value PinCode ID to confirm
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinconfirm_display(unsigned int value) {
|
||||
snprintf(G_gpg_vstate.menu,
|
||||
sizeof(G_gpg_vstate.menu),
|
||||
@ -851,13 +1000,20 @@ void ui_menu_pinconfirm_display(unsigned int value) {
|
||||
}
|
||||
|
||||
/* ------------------------------ PIN ENTRY UX ----------------------------- */
|
||||
|
||||
enum {
|
||||
TOKEN_PIN_ENTRY_BACK = FIRST_USER_TOKEN,
|
||||
};
|
||||
|
||||
static void ui_menu_pinentry_cb(void);
|
||||
|
||||
static void validate_pin(const uint8_t* pinentry, uint8_t length) {
|
||||
/**
|
||||
* Pin Entry Validation callback
|
||||
*
|
||||
* @param[in] value PinCode ID to confirm
|
||||
*
|
||||
*/
|
||||
static void pinentry_validate_cb(const uint8_t* pinentry, uint8_t length) {
|
||||
unsigned int sw = SW_UNKNOWN;
|
||||
unsigned int len1 = 0;
|
||||
unsigned char* pin1 = NULL;
|
||||
@ -952,6 +1108,13 @@ static void validate_pin(const uint8_t* pinentry, uint8_t length) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Entry Action callback
|
||||
*
|
||||
* @param[in] token button Id pressed
|
||||
* @param[in] index widget index on the page
|
||||
*
|
||||
*/
|
||||
static void pinentry_cb(int token, uint8_t index) {
|
||||
UNUSED(index);
|
||||
if (token == TOKEN_PIN_ENTRY_BACK) {
|
||||
@ -962,14 +1125,20 @@ static void pinentry_cb(int token, uint8_t index) {
|
||||
}
|
||||
}
|
||||
|
||||
void ui_menu_pinentry_display(unsigned int value) {
|
||||
/**
|
||||
* Pin Entry page display
|
||||
*
|
||||
* @param[in] step Pin Entry step
|
||||
*
|
||||
*/
|
||||
void ui_menu_pinentry_display(unsigned int step) {
|
||||
uint8_t minLen;
|
||||
char line[10];
|
||||
|
||||
// Init the page title
|
||||
explicit_bzero(G_gpg_vstate.line, sizeof(G_gpg_vstate.line));
|
||||
if (G_gpg_vstate.io_ins == INS_CHANGE_REFERENCE_DATA) {
|
||||
switch (value) {
|
||||
switch (step) {
|
||||
case 0:
|
||||
// Default or initial case
|
||||
snprintf(line, sizeof(line), "Current");
|
||||
@ -983,7 +1152,7 @@ void ui_menu_pinentry_display(unsigned int value) {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
G_gpg_vstate.ux_step = value;
|
||||
G_gpg_vstate.ux_step = step;
|
||||
} else {
|
||||
snprintf(line, sizeof(line), "Enter");
|
||||
}
|
||||
@ -1001,10 +1170,14 @@ void ui_menu_pinentry_display(unsigned int value) {
|
||||
TOKEN_PIN_ENTRY_BACK,
|
||||
false,
|
||||
TUNE_TAP_CASUAL,
|
||||
validate_pin,
|
||||
pinentry_validate_cb,
|
||||
pinentry_cb);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pin Entry Navigation callback
|
||||
*
|
||||
*/
|
||||
static void ui_menu_pinentry_cb(void) {
|
||||
unsigned int value = 0;
|
||||
|
||||
@ -1016,6 +1189,13 @@ static void ui_menu_pinentry_cb(void) {
|
||||
}
|
||||
|
||||
/* ------------------------------ UIF CONFIRM UX ----------------------------- */
|
||||
|
||||
/**
|
||||
* UIF Confirmation callback
|
||||
*
|
||||
* @param[in] confirm indicate if the user press 'Confirm' or 'Cancel'
|
||||
*
|
||||
*/
|
||||
void uif_confirm_cb(bool confirm) {
|
||||
unsigned int sw = SW_SECURITY_UIF_ISSUE;
|
||||
|
||||
@ -1037,6 +1217,12 @@ void uif_confirm_cb(bool confirm) {
|
||||
ui_init();
|
||||
}
|
||||
|
||||
/**
|
||||
* UIF page display
|
||||
*
|
||||
* @param[in] step unused
|
||||
*
|
||||
*/
|
||||
void ui_menu_uifconfirm_display(unsigned int value) {
|
||||
UNUSED(value);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user