From a1c8e7766cde469f6faba1e4b2c98dcefd0c763a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Mesnil?= Date: Thu, 31 Aug 2017 17:03:27 +0200 Subject: [PATCH] On the road to 1.1.0 Fix PIN management Add 3.3.1 spec addons - VERIFY with get status - MSE - ECC public key import - AES PSO:ENC - AES multi blcok --- Makefile | 9 ++-- src/gpg_api.h | 10 ++-- src/gpg_data.c | 3 +- src/gpg_dispatch.c | 52 ++++++++++--------- src/gpg_init.c | 21 +++++--- src/gpg_pin.c | 123 ++++++++++++++++++++++++--------------------- src/gpg_pso.c | 53 ++++++++++++------- src/gpg_types.h | 6 ++- src/gpg_ux_nanos.c | 32 ++++++++---- 9 files changed, 179 insertions(+), 130 deletions(-) diff --git a/Makefile b/Makefile index aa8768a..d329bd0 100644 --- a/Makefile +++ b/Makefile @@ -22,10 +22,11 @@ APPNAME = "OpenPGP" APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255" --curve secp256k1 $(COMMON_LOAD_PARAMS) APPVERSION_M=1 -APPVERSION_N=0 -APPVERSION_P=1 -APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) +APPVERSION_N=1 +APPVERSION_P=0 +APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P) +SPECVERSION="3.3.1" ICONNAME=images/icon_pgp.gif @@ -43,7 +44,7 @@ DEFINES += HAVE_BAGL HAVE_PRINTF HAVE_SPRINTF DEFINES += HAVE_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=7 IO_HID_EP_LENGTH=64 HAVE_USB_APDU DEFINES += HAVE_USB_CLASS_CCID -DEFINES += $(GPG_CONFIG) GPG_VERSION=$(APPVERSION) GPG_NAME=$(APPNAME) +DEFINES += $(GPG_CONFIG) GPG_VERSION=$(APPVERSION) GPG_NAME=$(APPNAME) SPEC_VERSION=$(SPECVERSION) ############## # Compiler # diff --git a/src/gpg_api.h b/src/gpg_api.h index dfc4a44..fa9f854 100644 --- a/src/gpg_api.h +++ b/src/gpg_api.h @@ -40,12 +40,14 @@ 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_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); +int gpg_pin_is_verified(int pinID); +int gpg_pin_set_verified(int pinID, int verified); +int gpg_pin_check(gpg_pin_t *pin, int pinID,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) ; + +int gpg_mse_reset(); +int gpg_apdu_mse(); /* ----------------------------------------------------------------------- */ /* --- IO ---- */ diff --git a/src/gpg_data.c b/src/gpg_data.c index 492f626..f4e5905 100644 --- a/src/gpg_data.c +++ b/src/gpg_data.c @@ -316,7 +316,7 @@ int gpg_apdu_put_data(unsigned int ref) { break; default: THROW(SW_REFERENCED_DATA_NOT_FOUND); - break; + return 0; } //fecth 7f78 gpg_io_fetch_tl(&t,&l); @@ -343,6 +343,7 @@ int gpg_apdu_put_data(unsigned int ref) { case 0x95: case 0x96: case 0x97: + case 0x99: break; default: THROW(SW_REFERENCED_DATA_NOT_FOUND); diff --git a/src/gpg_dispatch.c b/src/gpg_dispatch.c index 81267c3..0bc7cc9 100644 --- a/src/gpg_dispatch.c +++ b/src/gpg_dispatch.c @@ -23,12 +23,7 @@ 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) { @@ -45,7 +40,7 @@ void gpg_check_access_ins() { return; case INS_RESET_RETRY_COUNTER: - if (gpg_pin_is_verified(pin_pw3) || gpg_pin_is_verified(pin_rc)) { + if (gpg_pin_is_verified(PIN_ID_PW3) || gpg_pin_is_verified(PIN_ID_RC)) { return; } @@ -57,27 +52,30 @@ void gpg_check_access_ins() { if (G_gpg_vstate.io_p1 == 0x81) { return; } - if (gpg_pin_is_verified(pin_pw3)) { + if (gpg_pin_is_verified(PIN_ID_PW3)) { return; } break; + case INS_MSE: + return ; + case INS_PSO: - if ((ref == 0x9e9a) && gpg_pin_is_verified(pin_pw1)) { + if ((ref == 0x9e9a) && gpg_pin_is_verified(PIN_ID_PW1)) { //pso:sign if (N_gpg_pstate->PW_status[0] == 0) { - gpg_pin_set_verified(pin_pw1, 0); + gpg_pin_set_verified(PIN_ID_PW1, 0); } return; } - if ((ref == 0x8086 ) && gpg_pin_is_verified(pin_pw2)) { - //pso:dec + if (((ref == 0x8086 )||(ref == 0x8680)) && gpg_pin_is_verified(PIN_ID_PW2)) { + //pso:dec/enc return; } break; case INS_INTERNAL_AUTHENTICATE: - if (gpg_pin_is_verified(pin_pw2)) { + if (gpg_pin_is_verified(PIN_ID_PW2)) { return; } break; @@ -86,7 +84,7 @@ void gpg_check_access_ins() { return; case INS_TERMINATE_DF: - if (gpg_pin_is_verified(pin_pw3)) { + if (gpg_pin_is_verified(PIN_ID_PW3)) { return; } break; @@ -99,10 +97,6 @@ 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 ; @@ -152,14 +146,14 @@ void gpg_check_access_read_DO() { //PW1 case 0x0103: - if (gpg_pin_is_verified(pin_pw2)) { + if (gpg_pin_is_verified(PIN_ID_PW2)) { return; } break; //PW3 case 0x0104: - if (gpg_pin_is_verified(pin_pw3)) { + if (gpg_pin_is_verified(PIN_ID_PW3)) { return; } break; @@ -183,7 +177,7 @@ void gpg_check_access_write_DO() { case 0x0101: case 0x0103: case 0x01F2: - if (gpg_pin_is_verified(pin_pw2)) { + if (gpg_pin_is_verified(PIN_ID_PW2)) { return; } break; @@ -225,7 +219,7 @@ void gpg_check_access_write_DO() { case 0x00D6: case 0x00D7: case 0x00D8: - if (gpg_pin_is_verified(pin_pw3)) { + if (gpg_pin_is_verified(PIN_ID_PW3)) { return; } break; @@ -242,7 +236,10 @@ int gpg_dispatch() { unsigned int tag,t,l; int sw; - + if ((G_gpg_vstate.io_cla != 0x00) && (G_gpg_vstate.io_cla != 0x10)) { + THROW(SW_CLA_NOT_SUPPORTED); + return SW_CLA_NOT_SUPPORTED; + } tag = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ; @@ -265,7 +262,7 @@ int gpg_dispatch() { case INS_TERMINATE_DF: gpg_io_discard(0); - if (gpg_pin_is_verified(gpg_pin_get_pin(PIN_ID_PW3)) || (N_gpg_pstate->PW3.counter == 0)) { + if (gpg_pin_is_verified(PIN_ID_PW3) || (N_gpg_pstate->PW3.counter == 0)) { gpg_install(STATE_TERMINATE); return(SW_OK); break; @@ -361,7 +358,7 @@ int gpg_dispatch() { THROW(SW_INCORRECT_P1P2); case INS_RESET_RETRY_COUNTER: - if ((G_gpg_vstate.io_p2 == 0x81) && + if ((G_gpg_vstate.io_p2 == 0x81) && ( (G_gpg_vstate.io_p1 == 0) || (G_gpg_vstate.io_p1 == 2) ) ) { @@ -375,6 +372,11 @@ int gpg_dispatch() { sw = gpg_apdu_gen(); break; + /* --- MSE --- */ + case INS_MSE: + sw = gpg_apdu_mse(tag); + break; + /* --- PSO --- */ case INS_PSO: sw = gpg_apdu_pso(tag); diff --git a/src/gpg_init.c b/src/gpg_init.c index 0aaf2c9..8aca2f7 100644 --- a/src/gpg_init.c +++ b/src/gpg_init.c @@ -18,7 +18,7 @@ #include "gpg_types.h" #include "gpg_api.h" #include "gpg_vars.h" - +#include "usbd_ccid_impl.h" #define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF /* ----------------------*/ /* -- A Kind of Magic -- */ @@ -171,13 +171,13 @@ const unsigned char C_default_AlgoAttrECC_dec[] = { #else const unsigned char C_default_AlgoAttrECC_sig[] = { // eddsa - 22, + 0x16, // ed25519 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01, }; const unsigned char C_default_AlgoAttrECC_dec[] = { // ecdh - 18, + 0x12, //cv25519 0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01, }; @@ -211,11 +211,11 @@ 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]; + gpg_mse_reset(); //pin conf G_gpg_vstate.pinmode = N_gpg_pstate->config_pin[0]; //ux conf @@ -260,8 +260,6 @@ int gpg_install(unsigned char app_state) { 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)); @@ -288,9 +286,16 @@ int gpg_install(unsigned char app_state) { nvm_write(&N_gpg_pstate->default_RSA_exponent, &l, sizeof(unsigned int)); //config pin + #if 1 G_gpg_vstate.work.io_buffer[0] = PIN_MODE_CONFIRM; gpg_nvm_write(&N_gpg_pstate->config_pin, G_gpg_vstate.work.io_buffer, 1); - + USBD_CCID_activate_pinpad(3); + #else + G_gpg_vstate.work.io_buffer[0] = PIN_MODE_HOST; + gpg_nvm_write(&N_gpg_pstate->config_pin, G_gpg_vstate.work.io_buffer, 1); + USBD_CCID_activate_pinpad(0); + #endif + //default key template: RSA 2048) for (int s = 0; s< GPG_KEYS_SLOTS; s++) { diff --git a/src/gpg_pin.c b/src/gpg_pin.c index 1495227..e4fdb50 100644 --- a/src/gpg_pin.c +++ b/src/gpg_pin.c @@ -21,12 +21,11 @@ #include "gpg_ux_nanos.h" -gpg_pin_t *gpg_pin_get_pin(int id) { - switch (id) { +gpg_pin_t *gpg_pin_get_pin(int pinref) { + switch (pinref) { case PIN_ID_PW1 : - return &N_gpg_pstate->PW1; case PIN_ID_PW2 : - return &N_gpg_pstate->PW2; + return &N_gpg_pstate->PW1; case PIN_ID_PW3: return &N_gpg_pstate->PW3; case PIN_ID_RC: @@ -37,8 +36,8 @@ gpg_pin_t *gpg_pin_get_pin(int id) { -static int gpg_pin_get_index(unsigned int id) { - switch (id) { +static int gpg_pin_get_state_index(unsigned int pinref) { + switch (pinref) { case PIN_ID_PW1 : return 1; case PIN_ID_PW2 : @@ -52,28 +51,10 @@ static int gpg_pin_get_index(unsigned int id) { return -1; } -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) { +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) { return SW_PIN_BLOCKED; @@ -81,9 +62,6 @@ static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int pi 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)) { @@ -92,29 +70,28 @@ static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int pi counter = 3; gpg_nvm_write(&(pin->counter), &counter, sizeof(int)); - if (brother) { - gpg_nvm_write(&(brother->counter), &counter, sizeof(int)); - } return SW_OK; } -static void gpg_pin_check_throw(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) { +static void gpg_pin_check_throw(gpg_pin_t *pin, int pinID, + unsigned char *pin_val, int pin_len) { int sw; - gpg_pin_set_verified(pin,0); + gpg_pin_set_verified(pinID,0); sw = gpg_pin_check_internal(pin,pin_val,pin_len); if (sw == SW_OK) { - gpg_pin_set_verified(pin,1); + gpg_pin_set_verified(pinID,1); return; } THROW(sw); } -int gpg_pin_check(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) { +int gpg_pin_check(gpg_pin_t *pin, int pinID, + unsigned char *pin_val, unsigned int pin_len) { int sw; + gpg_pin_set_verified(pinID,0); 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); + gpg_pin_set_verified(pinID,1); } return sw; } @@ -130,12 +107,11 @@ void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) { newpin.counter = 3; gpg_nvm_write(pin, &newpin, sizeof(gpg_pin_t)); - gpg_pin_sync12(); } -int gpg_pin_set_verified(gpg_pin_t *pin, int verified) { +int gpg_pin_set_verified(int pinID, int verified) { int idx; - idx = gpg_pin_get_index(pin->ref); + idx = gpg_pin_get_state_index(pinID); if (idx >= 0) { G_gpg_vstate.verified_pin[idx]=verified; return verified; @@ -143,9 +119,9 @@ int gpg_pin_set_verified(gpg_pin_t *pin, int verified) { return 0; } -int gpg_pin_is_verified(gpg_pin_t *pin) { +int gpg_pin_is_verified(int pinID) { int idx; - idx = gpg_pin_get_index(pin->ref); + idx = gpg_pin_get_state_index(pinID); if (idx >= 0) { return G_gpg_vstate.verified_pin[idx]; } @@ -167,12 +143,15 @@ int gpg_apdu_verify() { return SW_WRONG_DATA; } - gpg_pin_set_verified(pin,0); - if (gpg_pin_is_blocked(pin)) { - THROW(SW_PIN_BLOCKED); - return SW_PIN_BLOCKED; - } - if (G_gpg_vstate.io_length == 0) { + + + //PINPAD + if (G_gpg_vstate.io_cla==0xFF) { + if (gpg_pin_is_blocked(pin)) { + THROW(SW_PIN_BLOCKED); + return SW_PIN_BLOCKED; + } + if (G_gpg_vstate.pinmode == PIN_MODE_SCREEN) { //Delegate pin check to ui gpg_io_discard(1); @@ -186,16 +165,46 @@ int gpg_apdu_verify() { return 0; } if (G_gpg_vstate.pinmode == PIN_MODE_TRUST) { - gpg_pin_set_verified(pin,1); + gpg_pin_set_verified(G_gpg_vstate.io_p2,1); gpg_io_discard(1); return SW_OK; } + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; } - gpg_pin_check_throw(pin, - G_gpg_vstate.work.io_buffer+ G_gpg_vstate.io_offset, - G_gpg_vstate.io_length); + + //NORMAL CHECK + if ((G_gpg_vstate.io_p1==0) && G_gpg_vstate.io_length) { + if (gpg_pin_is_blocked(pin)) { + THROW(SW_PIN_BLOCKED); + return SW_PIN_BLOCKED; + } + gpg_pin_check_throw(pin, G_gpg_vstate.io_p2, + G_gpg_vstate.work.io_buffer+ G_gpg_vstate.io_offset, + G_gpg_vstate.io_length); + gpg_io_discard(1); + return SW_OK; + } + gpg_io_discard(1); - return SW_OK; + + //STATUS REQUEST + if ((G_gpg_vstate.io_p1==0) && G_gpg_vstate.io_length==0) { + if (gpg_pin_is_verified(G_gpg_vstate.io_p2)) { + return SW_OK; + } + return 0x63C0 | pin->counter; + } + + //RESET REQUEST + if ((G_gpg_vstate.io_p1==0xFF) && G_gpg_vstate.io_length==0) { + gpg_pin_set_verified(G_gpg_vstate.io_p2,0); + return SW_OK; + } + + THROW(SW_WRONG_DATA); + return SW_WRONG_DATA; + } int gpg_apdu_change_ref_data() { @@ -208,7 +217,7 @@ int gpg_apdu_change_ref_data() { return SW_WRONG_DATA; } - gpg_pin_set_verified(pin,0); + gpg_pin_set_verified(pin->ref,0); // --- RC pin --- @@ -252,7 +261,7 @@ int gpg_apdu_change_ref_data() { len = pin->length; } - gpg_pin_check_throw(pin, + gpg_pin_check_throw(pin, pin->ref, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, len); @@ -281,7 +290,7 @@ int gpg_apdu_reset_retry_counter() { pin_rc = gpg_pin_get_pin(PIN_ID_RC); if (G_gpg_vstate.io_p1 == 2) { - if (!gpg_pin_is_verified(pin_pw3)) { + if (!gpg_pin_is_verified(PIN_ID_PW3)) { THROW(SW_SECURITY_STATUS_NOT_SATISFIED); return SW_SECURITY_STATUS_NOT_SATISFIED; } @@ -296,7 +305,7 @@ int gpg_apdu_reset_retry_counter() { rc_len = pin_rc->length; } pw1_len = G_gpg_vstate.io_length-rc_len; - gpg_pin_check_throw(pin_rc, + gpg_pin_check_throw(pin_rc,pin_rc->ref, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, rc_len); } diff --git a/src/gpg_pso.c b/src/gpg_pso.c index 140d7f7..d98b0e1 100644 --- a/src/gpg_pso.c +++ b/src/gpg_pso.c @@ -28,7 +28,7 @@ const unsigned char gpg_oid_sha512[] = { 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); + gpg_pin_set_verified(PIN_ID_PW1,0); } } @@ -134,7 +134,6 @@ static int gpg_sign(gpg_key_t *sigkey) { return SW_REFERENCED_DATA_NOT_FOUND; } - int gpg_apdu_pso(unsigned int pso) { unsigned int t,l,ksz; switch(pso) { @@ -147,6 +146,27 @@ int gpg_apdu_pso(unsigned int pso) { nvm_write(&G_gpg_vstate.kslot->sig_count,&cnt,sizeof(unsigned int)); return sw; } + // --- PSO:ENC --- + case 0x8680: { + unsigned int msg_len; + cx_aes_key_t *key; + unsigned int sz; + key = &G_gpg_vstate.kslot->AES_dec; + if (!(key->size != 16)) { + THROW(SW_CONDITIONS_NOT_SATISFIED+5); + return SW_CONDITIONS_NOT_SATISFIED; + } + msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset; + sz = cx_aes(key, + CX_ENCRYPT|CX_CHAIN_CBC|CX_LAST, + G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, msg_len, + G_gpg_vstate.work.io_buffer+1); + //send + gpg_io_discard(0); + G_gpg_vstate.work.io_buffer[0] = 0x02; + gpg_io_inserted(1+sz); + return SW_OK; + } // --- PSO:DEC --- case 0x8086: { @@ -159,25 +179,25 @@ int gpg_apdu_pso(unsigned int pso) { // --- PSO:DEC:RSA case 0x00: { cx_rsa_private_key_t *key; - if (G_gpg_vstate.kslot->dec.attributes.value[0] != 0x01) { + if (G_gpg_vstate.mse_dec->attributes.value[0] != 0x01) { THROW(SW_CONDITIONS_NOT_SATISFIED); return SW_CONDITIONS_NOT_SATISFIED; } - ksz = (G_gpg_vstate.kslot->dec.attributes.value[1]<<8) | G_gpg_vstate.kslot->dec.attributes.value[2]; + ksz = (G_gpg_vstate.mse_dec->attributes.value[1]<<8) | G_gpg_vstate.mse_dec->attributes.value[2]; ksz = ksz>>3; key = NULL; switch(ksz) { case 1024/8: - key = (cx_rsa_private_key_t *)&G_gpg_vstate.kslot->dec.key.rsa1024; + key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa1024; break; case 2048/8: - key = (cx_rsa_private_key_t *)&G_gpg_vstate.kslot->dec.key.rsa2048; + key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa2048; break; case 3072/8: - key = (cx_rsa_private_key_t *)&G_gpg_vstate.kslot->dec.key.rsa3072; + key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa3072; break; case 4096/8: - key = (cx_rsa_private_key_t *)&G_gpg_vstate.kslot->dec.key.rsa4096; + key = (cx_rsa_private_key_t *)&G_gpg_vstate.mse_dec->key.rsa4096; break; } @@ -208,7 +228,7 @@ int gpg_apdu_pso(unsigned int pso) { } msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset; sz = cx_aes(key, - CX_DECRYPT|CX_LAST, + CX_DECRYPT|CX_CHAIN_CBC|CX_LAST, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, msg_len, G_gpg_vstate.work.io_buffer); //send @@ -222,11 +242,11 @@ int gpg_apdu_pso(unsigned int pso) { cx_ecfp_private_key_t *key; unsigned int sz; unsigned int curve; - if (G_gpg_vstate.kslot->dec.attributes.value[0] != 18) { + if (G_gpg_vstate.mse_dec->attributes.value[0] != 0x12) { THROW(SW_CONDITIONS_NOT_SATISFIED); return SW_CONDITIONS_NOT_SATISFIED; } - key = &G_gpg_vstate.kslot->dec.key.ecfp256; + key = &G_gpg_vstate.mse_dec->key.ecfp256; if (key->d_len != 32) { THROW(SW_CONDITIONS_NOT_SATISFIED); return SW_CONDITIONS_NOT_SATISFIED; @@ -243,7 +263,7 @@ int gpg_apdu_pso(unsigned int pso) { return SW_WRONG_DATA; } - curve = gpg_oid2curve(G_gpg_vstate.kslot->dec.attributes.value+1, G_gpg_vstate.kslot->dec.attributes.length-1); + curve = gpg_oid2curve(G_gpg_vstate.mse_dec->attributes.value+1, G_gpg_vstate.mse_dec->attributes.length-1); if (curve == CX_CURVE_Curve25519) { unsigned int i; @@ -290,14 +310,11 @@ int gpg_apdu_pso(unsigned int pso) { int gpg_apdu_internal_authenticate() { - gpg_key_t *sigkey; - sigkey = &G_gpg_vstate.kslot->aut; - - 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) { + if (G_gpg_vstate.mse_aut->attributes.value[0] == 1) { + if ( G_gpg_vstate.io_length > ((G_gpg_vstate.mse_aut->attributes.value[1]<<8)|G_gpg_vstate.mse_aut->attributes.value[2])*40/100) { THROW(SW_WRONG_LENGTH); return SW_WRONG_LENGTH; } } - return gpg_sign(&G_gpg_vstate.kslot->aut); + return gpg_sign(G_gpg_vstate.mse_aut); } diff --git a/src/gpg_types.h b/src/gpg_types.h index 707f045..988d716 100644 --- a/src/gpg_types.h +++ b/src/gpg_types.h @@ -152,7 +152,6 @@ struct gpg_nv_state_s { /* PINs */ gpg_pin_t PW1; - gpg_pin_t PW2; gpg_pin_t PW3; gpg_pin_t RC; @@ -174,7 +173,9 @@ struct gpg_v_state_s { /* app state */ unsigned char selected; unsigned char slot; /* DO 01F2 */ - gpg_key_slot_t *kslot; + gpg_key_slot_t *kslot; + gpg_key_t *mse_aut; + gpg_key_t *mse_dec; unsigned char seed_mode; /* io state*/ @@ -285,6 +286,7 @@ typedef struct gpg_v_state_s gpg_v_state_t; #define INS_PUT_DATA_ODD 0xdb #define INS_VERIFY 0x20 +#define INS_MSE 0x22 #define INS_CHANGE_REFERENCE_DATA 0x24 #define INS_RESET_RETRY_COUNTER 0x2c diff --git a/src/gpg_ux_nanos.c b/src/gpg_ux_nanos.c index 462eecb..25721e7 100644 --- a/src/gpg_ux_nanos.c +++ b/src/gpg_ux_nanos.c @@ -152,12 +152,12 @@ 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_pin_set_verified(gpg_pin_get_pin(G_gpg_vstate.io_p2),0); + gpg_pin_set_verified(G_gpg_vstate.io_p2,0); sw = 0x6985; break; case BUTTON_EVT_RELEASED|BUTTON_RIGHT: // OK - gpg_pin_set_verified(gpg_pin_get_pin(G_gpg_vstate.io_p2),1); + gpg_pin_set_verified(G_gpg_vstate.io_p2,1); sw = 0x9000; break; default: @@ -240,9 +240,17 @@ unsigned int ui_pinentry_prepro(const bagl_element_t* element) { else if (element->component.userid == 2) { unsigned int i; G_gpg_vstate.menu[0] = ' '; + #if 1 for (i = 1; i<= G_gpg_vstate.ux_pinentry[0]; i++) { - G_gpg_vstate.menu[i] = C_pin_digit[G_gpg_vstate.ux_pinentry[i]]; + G_gpg_vstate.menu[i] = C_pin_digit[G_gpg_vstate.ux_pinentry[i]]; } + #else + for (i = 1; i< G_gpg_vstate.ux_pinentry[0]; i++) { + G_gpg_vstate.menu[i] = '*'; + } + G_gpg_vstate.menu[i] = C_pin_digit[G_gpg_vstate.ux_pinentry[i]]; + i++; + #endif for (; i<= GPG_MAX_PW_LENGTH;i++) { G_gpg_vstate.menu[i] = '-'; } @@ -325,15 +333,16 @@ static unsigned int validate_pin() { if (G_gpg_vstate.io_ins == 0x20) { 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]); + sw = gpg_pin_check(pin, G_gpg_vstate.io_p2, (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) { + if (sw != SW_OK) { 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; + } else { + ui_menu_main_display(0); + } } if (G_gpg_vstate.io_ins == 0x24) { @@ -344,7 +353,7 @@ static unsigned int validate_pin() { } if (G_gpg_vstate.io_p1 == 3) { 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) { + if (gpg_pin_check(pin, G_gpg_vstate.io_p2, 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); @@ -662,7 +671,7 @@ void ui_menu_pinmode_action(unsigned int value) { case PIN_MODE_HOST: case PIN_MODE_SCREEN: case PIN_MODE_CONFIRM: - if (!gpg_pin_is_verified(gpg_pin_get_pin(PIN_ID_PW1))) { + if (!gpg_pin_is_verified(PIN_ID_PW2)) { ui_info(PIN_USER, NOT_VERIFIED, ui_menu_pinmode_display,0); return; } @@ -670,7 +679,7 @@ void ui_menu_pinmode_action(unsigned int value) { case PIN_MODE_TRUST: - if (!gpg_pin_is_verified(gpg_pin_get_pin(PIN_ID_PW3))) { + if (!gpg_pin_is_verified(PIN_ID_PW3)) { ui_info(PIN_ADMIN, NOT_VERIFIED, ui_menu_pinmode_display,0); return; } @@ -767,6 +776,7 @@ void ui_menu_slot_action(unsigned int value) { if (s!= G_gpg_vstate.slot) { G_gpg_vstate.slot = s; G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot]; + gpg_mse_reset(); ui_CCID_reset(); } } @@ -785,7 +795,7 @@ void ui_menu_slot_action(unsigned int value) { const ux_menu_entry_t ui_menu_info[] = { {NULL, NULL, -1, NULL, "OpenPGP Card", NULL, 0, 0}, {NULL, NULL, -1, NULL, "(c) Ledger SAS", NULL, 0, 0}, - {NULL, NULL, -1, NULL, "Spec 3.0", NULL, 0, 0}, + {NULL, NULL, -1, NULL, "Spec " XSTR(SPEC_VERSION),NULL, 0, 0}, {NULL, NULL, -1, NULL, "App " XSTR(GPG_VERSION), NULL, 0, 0}, {NULL, ui_menu_main_display, 3, &C_badge_back, "Back", NULL, 61, 40}, UX_MENU_END