Fix Signatrure counter:  now incremented
Fix PIN status init: was not correctly initialized
Fix "only once" CDS management: PIN was not invalidated after signing
Change all return 0 by corresponding THROW error code
PIN API refacto
This commit is contained in:
Cédric Mesnil 2017-06-12 14:26:10 +02:00
parent 2e0d755fb6
commit 9dec68f892
13 changed files with 246 additions and 203 deletions

View File

@ -23,7 +23,7 @@ APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255" --curve secp256k1 $(COMMON_
APPVERSION_M=1
APPVERSION_N=0
APPVERSION_P=RC6
APPVERSION_P=RC7
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
ICONNAME=icon_pgp.gif

View File

@ -16,6 +16,7 @@
#ifndef GPG_API_H
#define GPG_API_H
int gpg_oid2curve(unsigned char* oid, unsigned int len);
void gpg_init(void);
void gpg_init_ux(void);
@ -34,17 +35,17 @@ int gpg_apdu_get_challenge(void) ;
int gpg_apdu_select(void) ;
int gpg_apdu_verify(int id) ;
int gpg_apdu_change_ref_data(int id) ;
int gpg_apdu_verify(void) ;
int gpg_apdu_change_ref_data(void) ;
int gpg_apdu_reset_retry_counter(void) ;
int gpg_oid2curve(unsigned char* oid, unsigned int len);
int gpg_is_pin_verified(int id);
int gpg_is_pin_blocked(int id);
int gpg_set_pin_verified(int id, int verified);
int gpg_check_pin(int id, unsigned char *pin_val, unsigned int pin_len);
void gpg_change_pin(int id, unsigned char *pin_val, unsigned int pin_len);
gpg_pin_t *gpg_pin_get_pin(int id);
int gpg_pin_is_verified(gpg_pin_t *pin);
int gpg_pin_is_blocked(gpg_pin_t *pin);
int gpg_pin_set_verified(gpg_pin_t *pin, int verified);
int gpg_pin_check(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len);
void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len);
void gpg_pin_sync12(void) ;
/* ----------------------------------------------------------------------- */
/* --- IO ---- */

View File

@ -29,7 +29,7 @@ int gpg_apdu_get_challenge() {
}
if (olen > GPG_EXT_CHALLENGE_LENTH) {
THROW(SW_WRONG_LENGTH);
return 0;
return SW_WRONG_LENGTH;
}
if ((G_gpg_vstate.io_p1&0x82) == 0x82) {

View File

@ -654,7 +654,7 @@ int gpg_apdu_put_data(unsigned int ref) {
/* ----------------- RC ----------------- */
case 0xD3:
sw = gpg_apdu_change_ref_data(PIN_ID_RC);
sw = gpg_apdu_change_ref_data();
break;
/* ----------------- UIF ----------------- */

View File

@ -20,12 +20,15 @@
#include "gpg_vars.h"
int gpg_is_verified(id) {
return G_gpg_vstate.verified_pin[id] ;
}
void gpg_check_access_ins() {
unsigned int ref;
gpg_pin_t *pin_pw1, *pin_pw2, *pin_pw3, *pin_rc;
pin_pw1 = gpg_pin_get_pin(PIN_ID_PW1);
pin_pw2 = gpg_pin_get_pin(PIN_ID_PW2);
pin_pw3 = gpg_pin_get_pin(PIN_ID_PW3);
pin_rc = gpg_pin_get_pin(PIN_ID_RC);
ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ;
switch (G_gpg_vstate.io_ins) {
@ -42,7 +45,7 @@ void gpg_check_access_ins() {
return;
case INS_RESET_RETRY_COUNTER:
if (gpg_is_verified(PIN_ID_PW3) || gpg_is_verified(PIN_ID_RC)) {
if (gpg_pin_is_verified(pin_pw3) || gpg_pin_is_verified(pin_rc)) {
return;
}
@ -54,27 +57,27 @@ void gpg_check_access_ins() {
if (G_gpg_vstate.io_p1 == 0x81) {
return;
}
if (gpg_is_verified(PIN_ID_PW3)) {
if (gpg_pin_is_verified(pin_pw3)) {
return;
}
break;
case INS_PSO:
if ((ref == 0x9e9a) && gpg_is_verified(PIN_ID_PW1)) {
if ((ref == 0x9e9a) && gpg_pin_is_verified(pin_pw1)) {
//pso:sign
if (N_gpg_pstate->PW_status[0] == 0) {
gpg_set_pin_verified(PIN_ID_PW1,0);
gpg_pin_set_verified(pin_pw1, 0);
}
return;
}
if ((ref == 0x8086 ) && gpg_is_verified(PIN_ID_PW2)) {
if ((ref == 0x8086 ) && gpg_pin_is_verified(pin_pw2)) {
//pso:dec
return;
}
break;
case INS_INTERNAL_AUTHENTICATE:
if (gpg_is_verified(PIN_ID_PW2)) {
if (gpg_pin_is_verified(pin_pw2)) {
return;
}
break;
@ -83,7 +86,7 @@ void gpg_check_access_ins() {
return;
case INS_TERMINATE_DF:
if (gpg_is_pin_verified(PIN_ID_PW3) || gpg_is_pin_blocked(PIN_ID_PW3)) {
if (gpg_pin_is_verified(pin_pw3)) {
return;
}
break;
@ -96,6 +99,11 @@ void gpg_check_access_ins() {
void gpg_check_access_read_DO() {
unsigned int ref;
gpg_pin_t *pin_pw2, *pin_pw3;
pin_pw2 = gpg_pin_get_pin(PIN_ID_PW2);
pin_pw3 = gpg_pin_get_pin(PIN_ID_PW3);
ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ;
switch(ref) {
@ -144,14 +152,14 @@ void gpg_check_access_read_DO() {
//PW1
case 0x0103:
if (gpg_is_verified(PIN_ID_PW2)) {
if (gpg_pin_is_verified(pin_pw2)) {
return;
}
break;
//PW3
case 0x0104:
if (gpg_is_verified(PIN_ID_PW3)) {
if (gpg_pin_is_verified(pin_pw3)) {
return;
}
break;
@ -164,15 +172,18 @@ char debugbuff[5];
void gpg_check_access_write_DO() {
unsigned int ref;
ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ;
gpg_pin_t *pin_pw2, *pin_pw3;
pin_pw2 = gpg_pin_get_pin(PIN_ID_PW2);
pin_pw3 = gpg_pin_get_pin(PIN_ID_PW3);
ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ;
switch(ref) {
//PW1
case 0x0101:
case 0x0103:
case 0x01F2:
if (gpg_is_verified(PIN_ID_PW2)) {
if (gpg_pin_is_verified(pin_pw2)) {
return;
}
break;
@ -214,7 +225,7 @@ void gpg_check_access_write_DO() {
case 0x00D6:
case 0x00D7:
case 0x00D8:
if (gpg_is_verified(PIN_ID_PW3)) {
if (gpg_pin_is_verified(pin_pw3)) {
return;
}
break;
@ -254,7 +265,7 @@ int gpg_dispatch() {
case INS_TERMINATE_DF:
gpg_io_discard(0);
if (G_gpg_vstate.verified_pin[PIN_ID_PW3] || (N_gpg_pstate->PW3.counter == 0)) {
if (gpg_pin_is_verified(gpg_pin_get_pin(PIN_ID_PW3)) || (N_gpg_pstate->PW3.counter == 0)) {
gpg_install(STATE_TERMINATE);
return(SW_OK);
break;
@ -335,17 +346,16 @@ int gpg_dispatch() {
(G_gpg_vstate.io_p2 == 0x82) ||
(G_gpg_vstate.io_p2 == 0x83)
) {
sw = gpg_apdu_verify(G_gpg_vstate.io_p2&0x0F);
sw = gpg_apdu_verify();
break;
}
THROW(0x9BF0);
//THROW(SW_INCORRECT_P1P2);
THROW(SW_INCORRECT_P1P2);
case INS_CHANGE_REFERENCE_DATA:
if ((G_gpg_vstate.io_p2 == 0x81) ||
(G_gpg_vstate.io_p2 == 0x83)
) {
sw = gpg_apdu_change_ref_data(G_gpg_vstate.io_p2&0x0F);
sw = gpg_apdu_change_ref_data();
break;
}
THROW(SW_INCORRECT_P1P2);

View File

@ -69,12 +69,12 @@ int gpg_apdu_gen() {
break;
default:
THROW(SW_INCORRECT_P1P2);
return 0;
return SW_INCORRECT_P1P2;
}
if (G_gpg_vstate.io_lc != 2){
THROW(SW_WRONG_LENGTH);
return 0;
return SW_WRONG_LENGTH;
}
gpg_io_fetch_tl(&t,&l);
@ -96,7 +96,7 @@ int gpg_apdu_gen() {
break;
default:
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
}
switch ((G_gpg_vstate.io_p1<<8)|G_gpg_vstate.io_p2) {
@ -210,28 +210,28 @@ int gpg_apdu_gen() {
case 1024/8:
if (keygpg->key.rsa1024.size == 0) {
THROW (SW_REFERENCED_DATA_NOT_FOUND);
return 0;
return SW_REFERENCED_DATA_NOT_FOUND;
}
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa1024.n);
break;
case 2048/8:
if (keygpg->key.rsa2048.size == 0) {
THROW (SW_REFERENCED_DATA_NOT_FOUND);
return 0;
return SW_REFERENCED_DATA_NOT_FOUND;
}
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa2048.n);
break;
case 3072/8:
if (keygpg->key.rsa3072.size == 0) {
THROW (SW_REFERENCED_DATA_NOT_FOUND);
return 0;
return SW_REFERENCED_DATA_NOT_FOUND;
}
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa3072.n);
break;
case 4096/8:
if (keygpg->key.rsa4096.size == 0) {
THROW (SW_REFERENCED_DATA_NOT_FOUND);
return 0;
return SW_REFERENCED_DATA_NOT_FOUND;
}
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa4096.n);
break;
@ -285,5 +285,5 @@ int gpg_apdu_gen() {
}
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
}

View File

@ -211,6 +211,8 @@ void gpg_init() {
gpg_nvm_write(N_gpg_pstate->magic, (void*)C_MAGIC, sizeof(C_MAGIC));
os_memset(&G_gpg_vstate, 0, sizeof(gpg_v_state_t));
}
//ensure pin1 and pin2 are sync in case of powerloss
gpg_pin_sync12();
//key conf
G_gpg_vstate.slot = N_gpg_pstate->config_slot[1];
G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot];
@ -252,16 +254,20 @@ int gpg_install(unsigned char app_state) {
G_gpg_vstate.work.io_buffer[0] = 0x39;
gpg_nvm_write(&N_gpg_pstate->sex, G_gpg_vstate.work.io_buffer, 1);
//default PW1: 1 2 3 4 5 6
//default PW1/PW2: 1 2 3 4 5 6
os_memmove(pin.value, C_sha256_PW1, sizeof(C_sha256_PW1));
pin.length = 6;
pin.counter = 3;
pin.ref = PIN_ID_PW1;
gpg_nvm_write(&N_gpg_pstate->PW1, &pin, sizeof(gpg_pin_t));
pin.ref = PIN_ID_PW2;
gpg_nvm_write(&N_gpg_pstate->PW2, &pin, sizeof(gpg_pin_t));
//default PW3: 1 2 3 4 5 6 7 8
os_memmove(pin.value, C_sha256_PW2, sizeof(C_sha256_PW2));
pin.length = 8;
pin.counter = 3;
pin.ref = PIN_ID_PW3;
gpg_nvm_write(&N_gpg_pstate->PW3, &pin, sizeof(gpg_pin_t));
//PWs status
@ -269,7 +275,7 @@ int gpg_install(unsigned char app_state) {
G_gpg_vstate.work.io_buffer[1] = GPG_MAX_PW_LENGTH;
G_gpg_vstate.work.io_buffer[2] = GPG_MAX_PW_LENGTH;
G_gpg_vstate.work.io_buffer[3] = GPG_MAX_PW_LENGTH;
gpg_nvm_write(&N_gpg_pstate->config_slot, G_gpg_vstate.work.io_buffer, 4);
gpg_nvm_write(&N_gpg_pstate->PW_status, G_gpg_vstate.work.io_buffer, 4);
//config slot
G_gpg_vstate.work.io_buffer[0] = GPG_KEYS_SLOTS;

View File

@ -42,6 +42,7 @@ void gpg_io_set_offset(unsigned int offset) {
}
else {
THROW(ERROR_IO_OFFSET);
return ;
}
}
@ -76,6 +77,7 @@ void gpg_io_clear() {
void gpg_io_hole(unsigned int sz) {
if ((G_gpg_vstate.io_length + sz) > GPG_IO_BUFFER_LENGTH) {
THROW(ERROR_IO_FULL);
return ;
}
os_memmove(G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset+sz,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
@ -340,7 +342,7 @@ int gpg_io_do(unsigned int io_flags) {
(G_io_apdu_buffer[2] != G_gpg_vstate.io_p1) ||
(G_io_apdu_buffer[3] != G_gpg_vstate.io_p2) ) {
THROW(SW_COMMAND_NOT_ALLOWED);
return 0;
return SW_COMMAND_NOT_ALLOWED;
}
G_gpg_vstate.io_cla = G_io_apdu_buffer[0];
G_gpg_vstate.io_lc = G_io_apdu_buffer[4];

View File

@ -21,11 +21,12 @@
#include "gpg_ux_nanos.h"
static gpg_pin_t *gpg_get_pin(int id) {
gpg_pin_t *gpg_pin_get_pin(int id) {
switch (id) {
case PIN_ID_PW1 :
case PIN_ID_PW2 :
return &N_gpg_pstate->PW1;
case PIN_ID_PW2 :
return &N_gpg_pstate->PW2;
case PIN_ID_PW3:
return &N_gpg_pstate->PW3;
case PIN_ID_RC:
@ -36,38 +37,89 @@ static gpg_pin_t *gpg_get_pin(int id) {
static int gpg_pin_get_index(unsigned int id) {
switch (id) {
case PIN_ID_PW1 :
return 1;
case PIN_ID_PW2 :
return 2;
case PIN_ID_PW3 :
return 3;
case PIN_ID_RC :
return 4;
}
return -1;
}
static int gpg_check_pin_internal(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) {
void gpg_pin_sync12() {
gpg_pin_t *pin1, *pin2;
pin1 = gpg_pin_get_pin(PIN_ID_PW1);
pin2 = gpg_pin_get_pin(PIN_ID_PW2);
if (os_memcmp(pin1, pin2, sizeof(gpg_pin_t))) {
pin1 = gpg_pin_get_pin(PIN_ID_PW1);
pin2 = gpg_pin_get_pin(PIN_ID_PW2);
gpg_nvm_write(pin2, pin1, sizeof(gpg_pin_t));
}
}
static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) {
cx_sha256_t sha256;
unsigned int counter;
gpg_pin_t *brother;
brother = NULL;
if (pin->ref == PIN_ID_PW1) {
brother = gpg_pin_get_pin(PIN_ID_PW2);
} else if (pin->ref == PIN_ID_PW2) {
brother = gpg_pin_get_pin(PIN_ID_PW1);
}
if (pin->counter == 0) {
THROW(SW_PIN_BLOCKED);
return SW_PIN_BLOCKED;
}
counter = pin->counter-1;
gpg_nvm_write(&(pin->counter), &counter, sizeof(int));
if (brother) {
gpg_nvm_write(&(brother->counter), &counter, sizeof(int));
}
cx_sha256_init(&sha256);
cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, NULL);
if (os_memcmp(sha256.acc, pin->value, 32)) {
return 0;
return SW_SECURITY_STATUS_NOT_SATISFIED;
}
counter = 3;
gpg_nvm_write(&(pin->counter), &counter, sizeof(int));
return 1;
if (brother) {
gpg_nvm_write(&(brother->counter), &counter, sizeof(int));
}
return SW_OK;
}
static void gpg_checkthrow_pin(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) {
if (gpg_check_pin_internal(pin,pin_val,pin_len)) {
static void gpg_pin_check_throw(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) {
int sw;
gpg_pin_set_verified(pin,0);
sw = gpg_pin_check_internal(pin,pin_val,pin_len);
if (sw == SW_OK) {
gpg_pin_set_verified(pin,1);
return;
}
THROW(SW_SECURITY_STATUS_NOT_SATISFIED);
THROW(sw);
}
static void gpg_set_pin(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) {
int gpg_pin_check(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) {
int sw;
sw = gpg_pin_check_internal(pin,pin_val,pin_len);
gpg_pin_set_verified(pin,0);
if (sw == SW_OK) {
gpg_pin_set_verified(pin,1);
}
return sw;
}
void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) {
cx_sha256_t sha256;
gpg_pin_t newpin;
@ -78,74 +130,47 @@ static void gpg_set_pin(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin
newpin.counter = 3;
gpg_nvm_write(pin, &newpin, sizeof(gpg_pin_t));
gpg_pin_sync12();
}
/*
static void gpg_unblock_pin(int id) {
gpg_pin_t *pin;
int counter;
pin = gpg_get_pin(id);
counter = 3;
gpg_nvm_write(&(pin->counter), &counter, sizeof(int));
int gpg_pin_set_verified(gpg_pin_t *pin, int verified) {
int idx;
idx = gpg_pin_get_index(pin->ref);
if (idx >= 0) {
G_gpg_vstate.verified_pin[idx]=verified;
return verified;
}
return 0;
}
*/
int gpg_set_pin_verified(int id, int verified) {
G_gpg_vstate.verified_pin[id] = verified;
return verified;
int gpg_pin_is_verified(gpg_pin_t *pin) {
int idx;
idx = gpg_pin_get_index(pin->ref);
if (idx >= 0) {
return G_gpg_vstate.verified_pin[idx];
}
return 0;
}
int gpg_check_pin(int id, unsigned char *pin_val, unsigned int pin_len) {
gpg_pin_t *pin;
pin = gpg_get_pin(id);
return gpg_set_pin_verified(id, gpg_check_pin_internal(pin,pin_val,pin_len)?1:0);
}
/*
*
*/
void gpg_change_pin(int id, unsigned char *pin_val, unsigned int pin_len) {
gpg_pin_t *pin;
pin = gpg_get_pin(id);
gpg_set_pin(pin, pin_val, pin_len);
}
/*
*
*/
int gpg_is_pin_verified(int id) {
return G_gpg_vstate.verified_pin[id] != 0;
}
/*
*
*/
int gpg_is_pin_blocked(int id) {
gpg_pin_t *pin;
pin = gpg_get_pin(id);
int gpg_pin_is_blocked(gpg_pin_t *pin) {
return pin->counter == 0;
}
/* @return: 1 verified
* 0 not verified
* -1 blocked
*/
int gpg_apdu_verify(int id) {
int gpg_apdu_verify() {
gpg_pin_t *pin;
pin = gpg_get_pin(id);
pin = gpg_pin_get_pin(G_gpg_vstate.io_p2);
if (pin == NULL) {
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
}
gpg_set_pin_verified(id,0);
if (gpg_is_pin_blocked(id)) {
gpg_pin_set_verified(pin,0);
if (gpg_pin_is_blocked(pin)) {
THROW(SW_PIN_BLOCKED);
return 0;
return SW_PIN_BLOCKED;
}
if (G_gpg_vstate.io_length == 0) {
if (G_gpg_vstate.pinmode == PIN_MODE_SCREEN) {
@ -161,34 +186,33 @@ int gpg_apdu_verify(int id) {
return 0;
}
if (G_gpg_vstate.pinmode == PIN_MODE_TRUST) {
gpg_set_pin_verified(id,1);
gpg_pin_set_verified(pin,1);
gpg_io_discard(1);
return SW_OK;
}
}
gpg_checkthrow_pin(pin,
G_gpg_vstate.work.io_buffer+ G_gpg_vstate.io_offset,
G_gpg_vstate.io_length);
gpg_set_pin_verified(id,1);
gpg_pin_check_throw(pin,
G_gpg_vstate.work.io_buffer+ G_gpg_vstate.io_offset,
G_gpg_vstate.io_length);
gpg_io_discard(1);
return SW_OK;
}
int gpg_apdu_change_ref_data(int id) {
int gpg_apdu_change_ref_data() {
gpg_pin_t *pin;
int len, newlen;
pin = gpg_get_pin(id);
pin = gpg_pin_get_pin(G_gpg_vstate.io_p2);
if (pin == NULL) {
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
}
gpg_set_pin_verified(id,0);
gpg_pin_set_verified(pin,0);
// --- RC pin ---
if (id == PIN_ID_RC) {
if (pin->ref == PIN_ID_RC) {
newlen = G_gpg_vstate.io_length;
if (newlen == 0) {
gpg_nvm_write(pin, NULL, sizeof(gpg_pin_t));
@ -197,20 +221,20 @@ int gpg_apdu_change_ref_data(int id) {
else if ((newlen > GPG_MAX_PW_LENGTH) ||
(newlen < 8)) {
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
} else {
gpg_set_pin(pin,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
newlen);
gpg_pin_set(pin,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
newlen);
}
gpg_io_discard(1);
return SW_OK;
}
// --- PW1/PW3 pin ---
if (gpg_is_pin_blocked(id)) {
if (gpg_pin_is_blocked(pin)) {
THROW(SW_PIN_BLOCKED);
return 0;
return SW_PIN_BLOCKED;
}
//avoid any-overflow whitout giving info
if (G_gpg_vstate.io_length == 0) {
@ -228,18 +252,18 @@ int gpg_apdu_change_ref_data(int id) {
len = pin->length;
}
gpg_checkthrow_pin(pin,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
len);
gpg_pin_check_throw(pin,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
len);
newlen = G_gpg_vstate.io_length-len;
if ( (newlen > GPG_MAX_PW_LENGTH) ||
((id == PIN_ID_PW1) && (newlen < 6)) ||
((id == PIN_ID_PW3) && (newlen < 8)) ) {
((pin->ref == PIN_ID_PW1) && (newlen < 6)) ||
((pin->ref == PIN_ID_PW3) && (newlen < 8)) ) {
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
}
gpg_set_pin(pin,
gpg_pin_set(pin,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset+len,
newlen);
gpg_io_discard(1);
@ -248,20 +272,23 @@ int gpg_apdu_change_ref_data(int id) {
int gpg_apdu_reset_retry_counter() {
gpg_pin_t *pin_pw1;
gpg_pin_t *pin_pw3;
gpg_pin_t *pin_rc;
int rc_len, pw1_len;
pin_pw1 = gpg_get_pin(PIN_ID_PW1);
pin_pw1 = gpg_pin_get_pin(PIN_ID_PW1);
pin_pw3 = gpg_pin_get_pin(PIN_ID_PW3);
pin_rc = gpg_pin_get_pin(PIN_ID_RC);
if (G_gpg_vstate.io_p1 == 2) {
if (!G_gpg_vstate.verified_pin[PIN_ID_PW3]) {
if (!gpg_pin_is_verified(pin_pw3)) {
THROW(SW_SECURITY_STATUS_NOT_SATISFIED);
return 0;
return SW_SECURITY_STATUS_NOT_SATISFIED;
}
rc_len = 0;
pw1_len = G_gpg_vstate.io_length;
} else {
pin_rc = gpg_get_pin(PIN_ID_RC);
//avoid any-overflow whitout giving info
if (pin_rc->length > G_gpg_vstate.io_length) {
rc_len = G_gpg_vstate.io_length;
@ -269,16 +296,16 @@ int gpg_apdu_reset_retry_counter() {
rc_len = pin_rc->length;
}
pw1_len = G_gpg_vstate.io_length-rc_len;
gpg_checkthrow_pin(pin_rc,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
rc_len);
gpg_pin_check_throw(pin_rc,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
rc_len);
}
if ((pw1_len > GPG_MAX_PW_LENGTH) ||(pw1_len < 6)) {
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
}
gpg_set_pin(pin_pw1,
gpg_pin_set(pin_pw1,
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset+rc_len,
pw1_len);
gpg_io_discard(1);

View File

@ -26,6 +26,11 @@ const unsigned char gpg_oid_sha512[] = {
0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05, 0x00, 0x04, 0x40
};
static void gpg_pso_reset_PW1() {
if (N_gpg_pstate->PW_status[0] ==0) {
gpg_pin_set_verified(gpg_pin_get_pin(PIN_ID_PW1),0);
}
}
static int gpg_sign(gpg_key_t *sigkey) {
// --- RSA
@ -50,7 +55,7 @@ static int gpg_sign(gpg_key_t *sigkey) {
}
if (key->size != ksz) {
THROW(SW_CONDITIONS_NOT_SATISFIED);
return 0;
return SW_CONDITIONS_NOT_SATISFIED;
}
//sign
@ -71,6 +76,7 @@ static int gpg_sign(gpg_key_t *sigkey) {
//send
gpg_io_discard(0);
gpg_io_inserted(ksz);
gpg_pso_reset_PW1();
return SW_OK;
}
// --- ECDSA/EdDSA
@ -83,7 +89,7 @@ static int gpg_sign(gpg_key_t *sigkey) {
key = &sigkey->key.ecfp256;
if (key->d_len != 32) {
THROW(SW_CONDITIONS_NOT_SATISFIED);
return 0;
return SW_CONDITIONS_NOT_SATISFIED;
}
//sign
if (sigkey->attributes.value[0] == 19) {
@ -120,11 +126,12 @@ static int gpg_sign(gpg_key_t *sigkey) {
}
//send
gpg_pso_reset_PW1();
return SW_OK;
}
// --- PSO:CDS NOT SUPPORTED
THROW(SW_REFERENCED_DATA_NOT_FOUND);
return 0;
return SW_REFERENCED_DATA_NOT_FOUND;
}
@ -133,7 +140,12 @@ int gpg_apdu_pso(unsigned int pso) {
switch(pso) {
// --- PSO:CDS ---
case 0x9e9a: {
return gpg_sign(&G_gpg_vstate.kslot->sig);
unsigned int cnt;
int sw;
sw = gpg_sign(&G_gpg_vstate.kslot->sig);
cnt = G_gpg_vstate.kslot->sig_count+1;
nvm_write(&G_gpg_vstate.kslot->sig_count,&cnt,sizeof(unsigned int));
return sw;
}
// --- PSO:DEC ---
@ -149,7 +161,7 @@ int gpg_apdu_pso(unsigned int pso) {
cx_rsa_private_key_t *key;
if (G_gpg_vstate.kslot->dec.attributes.value[0] != 0x01) {
THROW(SW_CONDITIONS_NOT_SATISFIED);
return 0;
return SW_CONDITIONS_NOT_SATISFIED;
}
ksz = (G_gpg_vstate.kslot->dec.attributes.value[1]<<8) | G_gpg_vstate.kslot->dec.attributes.value[2];
ksz = ksz>>3;
@ -192,7 +204,7 @@ int gpg_apdu_pso(unsigned int pso) {
key = &G_gpg_vstate.kslot->AES_dec;
if (!(key->size != 16)) {
THROW(SW_CONDITIONS_NOT_SATISFIED+5);
return 0;
return SW_CONDITIONS_NOT_SATISFIED;
}
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
sz = cx_aes(key,
@ -212,23 +224,23 @@ int gpg_apdu_pso(unsigned int pso) {
unsigned int curve;
if (G_gpg_vstate.kslot->dec.attributes.value[0] != 18) {
THROW(SW_CONDITIONS_NOT_SATISFIED);
return 0;
return SW_CONDITIONS_NOT_SATISFIED;
}
key = &G_gpg_vstate.kslot->dec.key.ecfp256;
if (key->d_len != 32) {
THROW(SW_CONDITIONS_NOT_SATISFIED);
return 0;
return SW_CONDITIONS_NOT_SATISFIED;
}
gpg_io_fetch_l(&l);
gpg_io_fetch_tl(&t, &l);
if (t != 0x7f49) {
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
}
gpg_io_fetch_tl(&t, &l);
if (t != 0x86) {
THROW(SW_WRONG_DATA);
return 0;
return SW_WRONG_DATA;
}
curve = gpg_oid2curve(G_gpg_vstate.kslot->dec.attributes.value+1, G_gpg_vstate.kslot->dec.attributes.length-1);
@ -262,7 +274,7 @@ int gpg_apdu_pso(unsigned int pso) {
// --- PSO:DEC:xx NOT SUPPORTDED
default:
THROW(SW_REFERENCED_DATA_NOT_FOUND);
return 0;
return SW_REFERENCED_DATA_NOT_FOUND;
}
}
@ -270,10 +282,10 @@ int gpg_apdu_pso(unsigned int pso) {
//--- PSO:yy NOT SUPPPORTED ---
default:
THROW(SW_REFERENCED_DATA_NOT_FOUND);
return 0;
return SW_REFERENCED_DATA_NOT_FOUND;
}
THROW(SW_REFERENCED_DATA_NOT_FOUND);
return 0;
return SW_REFERENCED_DATA_NOT_FOUND;
}
@ -284,7 +296,7 @@ int gpg_apdu_internal_authenticate() {
if (G_gpg_vstate.kslot->aut.attributes.value[0] == 1) {
if ( G_gpg_vstate.io_length > ((G_gpg_vstate.kslot->aut.attributes.value[1]<<8)|G_gpg_vstate.kslot->aut.attributes.value[2])*40/100) {
THROW(SW_WRONG_LENGTH);
return 0;
return SW_WRONG_LENGTH;
}
}
return gpg_sign(&G_gpg_vstate.kslot->aut);

View File

@ -22,22 +22,24 @@
int gpg_apdu_select() {
int sw;
if ( (G_gpg_vstate.io_length = 6) &&
if ( (G_gpg_vstate.io_length == 6) &&
(os_memcmp(G_gpg_vstate.work.io_buffer, N_gpg_pstate->AID, G_gpg_vstate.io_length) == 0) ) {
G_gpg_vstate.DO_current = 0;
G_gpg_vstate.DO_reccord = 0;
G_gpg_vstate.DO_offset = 0;
if ( G_gpg_vstate.selected == 0) {
G_gpg_vstate.verified_pin[PIN_ID_PW1] = 0;
G_gpg_vstate.verified_pin[PIN_ID_PW2] = 0;
G_gpg_vstate.verified_pin[PIN_ID_PW3] = 0;
G_gpg_vstate.verified_pin[PIN_ID_RC] = 0;
G_gpg_vstate.verified_pin[0] = 0;
G_gpg_vstate.verified_pin[1] = 0;
G_gpg_vstate.verified_pin[2] = 0;
G_gpg_vstate.verified_pin[3] = 0;
G_gpg_vstate.verified_pin[4] = 0;
}
gpg_io_discard(0);
sw = SW_OK;
} else {
THROW(SW_FILE_NOT_FOUND);
return 0;
return SW_FILE_NOT_FOUND;
}
return sw;
}

View File

@ -39,9 +39,10 @@
#define GPG_RSA_DEFAULT_PUB 0x010001U
struct gpg_pin_s {
unsigned int ref;
//initial pin length, 0 means not set
unsigned int length;
unsigned int counter;
unsigned int length;
unsigned int counter;
//only store sha256 of PIN/RC
unsigned char value[32];
};
@ -151,6 +152,7 @@ struct gpg_nv_state_s {
/* PINs */
gpg_pin_t PW1;
gpg_pin_t PW2;
gpg_pin_t PW3;
gpg_pin_t RC;
@ -259,10 +261,10 @@ typedef struct gpg_v_state_s gpg_v_state_t;
#define IO_OFFSET_END (unsigned int)-1
#define IO_OFFSET_MARK (unsigned int)-2
#define PIN_ID_PW1 1
#define PIN_ID_PW2 2
#define PIN_ID_PW3 3
#define PIN_ID_RC 4
#define PIN_ID_PW1 0x81
#define PIN_ID_PW2 0x82
#define PIN_ID_PW3 0x83
#define PIN_ID_RC 0x84
#define PIN_MODE_HOST 1
#define PIN_MODE_SCREEN 2

View File

@ -32,26 +32,6 @@
/* --- NanoS UI layout --- */
/* ----------------------------------------------------------------------- */
#define PICSTR(x) ((char*)PIC(x))
#define TEMPLATE_TYPE PICSTR(C_TEMPLATE_TYPE)
#define TEMPLATE_KEY PICSTR(C_TEMPLATE_KEY)
#define INVALID_SELECTION PICSTR(C_INVALID_SELECTION)
#define OK PICSTR(C_OK)
#define NOK PICSTR(C_NOK)
#define WRONG_PIN PICSTR(C_WRONG_PIN)
#define RIGHT_PIN PICSTR(C_RIGHT_PIN)
#define PIN_CHANGED PICSTR(C_PIN_CHANGED)
#define PIN_DIFFERS PICSTR(C_PIN_DIFFERS)
#define PIN_USER PICSTR(C_PIN_USER)
#define PIN_ADMIN PICSTR(C_PIN_ADMIN)
#define VERIFIED PICSTR(C_VERIFIED)
#define NOT_VERIFIED PICSTR(C_NOT_VERIFIED)
#define ALLOWED PICSTR(C_ALLOWED)
#define NOT_ALLOWED PICSTR(C_NOT_ALLOWED)
#define DEFAULT_MODE PICSTR(C_DEFAULT_MODE)
const ux_menu_entry_t ui_menu_template[];
void ui_menu_template_display(unsigned int value);
@ -172,13 +152,13 @@ unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, unsigned int b
sw = 0x6985;
switch(button_mask) {
case BUTTON_EVT_RELEASED|BUTTON_LEFT: // CANCEL
gpg_set_pin_verified(G_gpg_vstate.io_p2&0x0F,0);
gpg_pin_set_verified(gpg_pin_get_pin(G_gpg_vstate.io_p2),0);
sw = 0x6985;
break;
case BUTTON_EVT_RELEASED|BUTTON_RIGHT: // OK
gpg_set_pin_verified(G_gpg_vstate.io_p2&0x0F,1);
sw = 0x9000;
gpg_pin_set_verified(gpg_pin_get_pin(G_gpg_vstate.io_p2),1);
sw = 0x9000;
break;
default:
return 0;
@ -249,7 +229,7 @@ unsigned int ui_pinentry_prepro(const bagl_element_t* element) {
case 2:
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "Confirm %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User");
break;
default:
default:
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), "WAT %s PIN", (G_gpg_vstate.io_p2 == 0x83)?"Admin":"User");
break;
}
@ -336,25 +316,23 @@ unsigned int ui_pinentry_nanos_button(unsigned int button_mask, unsigned int but
// >= 0
static unsigned int validate_pin() {
unsigned int offset, len, sw;
gpg_pin_t *pin;
for (offset = 1; offset< G_gpg_vstate.ux_pinentry[0];offset++) {
G_gpg_vstate.menu[offset] = C_pin_digit[G_gpg_vstate.ux_pinentry[offset]];
}
if (G_gpg_vstate.io_ins == 0x20) {
if (gpg_check_pin(G_gpg_vstate.io_p2&0x0F, (unsigned char*)(G_gpg_vstate.menu+1), G_gpg_vstate.ux_pinentry[0])) {
sw = SW_OK;
} else {
sw = SW_CONDITIONS_NOT_SATISFIED;
}
pin = gpg_pin_get_pin(G_gpg_vstate.io_p2);
sw = gpg_pin_check(pin, (unsigned char*)(G_gpg_vstate.menu+1), G_gpg_vstate.ux_pinentry[0]);
gpg_io_discard(1);
gpg_io_insert_u16(sw);
gpg_io_do(IO_RETURN_AFTER_TX);
if (sw == SW_CONDITIONS_NOT_SATISFIED) {
ui_info(WRONG_PIN, NULL, ui_menu_main_display, 0);
} else {
ui_info(RIGHT_PIN, NULL, ui_menu_main_display, 0);
}
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %d tries remaining", pin->counter );
ui_info(WRONG_PIN, G_gpg_vstate.menu, ui_menu_main_display, 0);
}
return 0;
}
@ -365,10 +343,12 @@ static unsigned int validate_pin() {
G_gpg_vstate.io_p1++;
}
if (G_gpg_vstate.io_p1 == 3) {
if (!gpg_check_pin(G_gpg_vstate.io_p2&0x0F, G_gpg_vstate.work.io_buffer+1, G_gpg_vstate.work.io_buffer[0])) {
pin = gpg_pin_get_pin(G_gpg_vstate.io_p2);
if (gpg_pin_check(pin, G_gpg_vstate.work.io_buffer+1, G_gpg_vstate.work.io_buffer[0])!=SW_OK) {
gpg_io_discard(1);
gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED);
gpg_io_do(IO_RETURN_AFTER_TX);
snprintf(G_gpg_vstate.menu, sizeof(G_gpg_vstate.menu), " %d tries remaining", pin->counter );
ui_info(WRONG_PIN, NULL, ui_menu_main_display, 0);
return 0;
}
@ -381,11 +361,12 @@ static unsigned int validate_pin() {
gpg_io_do(IO_RETURN_AFTER_TX);
ui_info(PIN_DIFFERS, NULL, ui_menu_main_display, 0);
} else {
gpg_change_pin(G_gpg_vstate.io_p2&0x0F, G_gpg_vstate.work.io_buffer+offset+ 1, len);
gpg_pin_set(gpg_pin_get_pin(G_gpg_vstate.io_p2), G_gpg_vstate.work.io_buffer+offset+ 1, len);
gpg_io_discard(1);
gpg_io_insert_u16(SW_OK);
gpg_io_do(IO_RETURN_AFTER_TX);
ui_info(PIN_CHANGED, NULL, ui_menu_main_display, 0);
//ui_info(PIN_CHANGED, NULL, ui_menu_main_display, 0);
ui_menu_main_display(0);
}
return 0;
} else {
@ -680,7 +661,7 @@ void ui_menu_pinmode_action(unsigned int value) {
switch (value) {
case PIN_MODE_HOST:
case PIN_MODE_SCREEN:
if (!gpg_is_pin_verified(PIN_ID_PW1)) {
if (!gpg_pin_is_verified(gpg_pin_get_pin(PIN_ID_PW2))) {
ui_info(PIN_USER, NOT_VERIFIED, ui_menu_pinmode_display,0);
return;
}
@ -688,7 +669,7 @@ void ui_menu_pinmode_action(unsigned int value) {
case PIN_MODE_CONFIRM:
case PIN_MODE_TRUST:
if (!gpg_is_pin_verified(PIN_ID_PW3)) {
if (!gpg_pin_is_verified(gpg_pin_get_pin(PIN_ID_PW3))) {
ui_info(PIN_ADMIN, NOT_VERIFIED, ui_menu_pinmode_display,0);
return;
}
@ -709,8 +690,8 @@ const ux_menu_entry_t ui_menu_reset[] = {
#error menu definition not correct for current value of GPG_KEYS_SLOTS
#endif
{NULL, NULL, 0, NULL, "Really Reset ?", NULL, 0, 0},
{NULL, ui_menu_main_display, 0, &C_badge_back, "Oh No!", NULL, 61, 40},
{NULL, ui_menu_reset_action, 0, NULL, "Yes!", NULL, 0, 0},
{NULL, ui_menu_main_display, 0, &C_badge_back, "No", NULL, 61, 40},
{NULL, ui_menu_reset_action, 0, NULL, "Yes", NULL, 0, 0},
UX_MENU_END
};