Add inline comment for functions description

This commit is contained in:
Charles-Edouard de la Vergne 2024-03-21 12:05:01 +01:00
parent 400ff19c6d
commit 3847b0636d
No known key found for this signature in database
GPG Key ID: F12296941B7BB9C6
15 changed files with 1183 additions and 42 deletions

View File

@ -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);

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -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]) {

View File

@ -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;

View File

@ -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);

View File

@ -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

View File

@ -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);
}

View File

@ -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);