From 9dec68f892bd4ff0e3a533d7bb530cea5efd81b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mesnil?= Date: Mon, 12 Jun 2017 14:26:10 +0200 Subject: [PATCH] RC7 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 --- Makefile | 2 +- src/gpg_api.h | 19 ++-- src/gpg_challenge.c | 2 +- src/gpg_data.c | 2 +- src/gpg_dispatch.c | 50 ++++++----- src/gpg_gen.c | 16 ++-- src/gpg_init.c | 10 ++- src/gpg_io.c | 4 +- src/gpg_pin.c | 215 +++++++++++++++++++++++++------------------- src/gpg_pso.c | 40 ++++++--- src/gpg_select.c | 14 +-- src/gpg_types.h | 14 +-- src/gpg_ux_nanos.c | 61 +++++-------- 13 files changed, 246 insertions(+), 203 deletions(-) diff --git a/Makefile b/Makefile index cb333e9..4f5616a 100644 --- a/Makefile +++ b/Makefile @@ -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 diff --git a/src/gpg_api.h b/src/gpg_api.h index 4bfb092..dfc4a44 100644 --- a/src/gpg_api.h +++ b/src/gpg_api.h @@ -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 ---- */ diff --git a/src/gpg_challenge.c b/src/gpg_challenge.c index dab7b0b..1a655f7 100644 --- a/src/gpg_challenge.c +++ b/src/gpg_challenge.c @@ -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) { diff --git a/src/gpg_data.c b/src/gpg_data.c index 071a2cc..492f626 100644 --- a/src/gpg_data.c +++ b/src/gpg_data.c @@ -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 ----------------- */ diff --git a/src/gpg_dispatch.c b/src/gpg_dispatch.c index c58e9fd..81267c3 100644 --- a/src/gpg_dispatch.c +++ b/src/gpg_dispatch.c @@ -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); diff --git a/src/gpg_gen.c b/src/gpg_gen.c index 9bca64d..e7de95d 100644 --- a/src/gpg_gen.c +++ b/src/gpg_gen.c @@ -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; } diff --git a/src/gpg_init.c b/src/gpg_init.c index 28d73eb..0aaf2c9 100644 --- a/src/gpg_init.c +++ b/src/gpg_init.c @@ -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; diff --git a/src/gpg_io.c b/src/gpg_io.c index c50623b..50a46cf 100644 --- a/src/gpg_io.c +++ b/src/gpg_io.c @@ -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]; diff --git a/src/gpg_pin.c b/src/gpg_pin.c index 2d810ef..1495227 100644 --- a/src/gpg_pin.c +++ b/src/gpg_pin.c @@ -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); diff --git a/src/gpg_pso.c b/src/gpg_pso.c index 470d5fd..b74aa3d 100644 --- a/src/gpg_pso.c +++ b/src/gpg_pso.c @@ -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); diff --git a/src/gpg_select.c b/src/gpg_select.c index 0130f24..d88f672 100644 --- a/src/gpg_select.c +++ b/src/gpg_select.c @@ -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; } diff --git a/src/gpg_types.h b/src/gpg_types.h index 3ec867d..707f045 100644 --- a/src/gpg_types.h +++ b/src/gpg_types.h @@ -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 diff --git a/src/gpg_ux_nanos.c b/src/gpg_ux_nanos.c index 3b58e1a..780c79c 100644 --- a/src/gpg_ux_nanos.c +++ b/src/gpg_ux_nanos.c @@ -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 };