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
This commit is contained in:
Cédric Mesnil 2017-08-31 17:03:27 +02:00
parent 582928a16d
commit a1c8e7766c
9 changed files with 179 additions and 130 deletions

View File

@ -22,10 +22,11 @@ APPNAME = "OpenPGP"
APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255" --curve secp256k1 $(COMMON_LOAD_PARAMS) APP_LOAD_PARAMS=--appFlags 0x40 --path "2152157255" --curve secp256k1 $(COMMON_LOAD_PARAMS)
APPVERSION_M=1 APPVERSION_M=1
APPVERSION_N=0 APPVERSION_N=1
APPVERSION_P=1 APPVERSION_P=0
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
APPVERSION=$(APPVERSION_M).$(APPVERSION_N).$(APPVERSION_P)
SPECVERSION="3.3.1"
ICONNAME=images/icon_pgp.gif 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_IO_USB HAVE_L4_USBLIB IO_USB_MAX_ENDPOINTS=7 IO_HID_EP_LENGTH=64 HAVE_USB_APDU
DEFINES += HAVE_USB_CLASS_CCID 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 # # Compiler #

View File

@ -40,12 +40,14 @@ int gpg_apdu_change_ref_data(void) ;
int gpg_apdu_reset_retry_counter(void) ; int gpg_apdu_reset_retry_counter(void) ;
gpg_pin_t *gpg_pin_get_pin(int id); 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_is_blocked(gpg_pin_t *pin);
int gpg_pin_set_verified(gpg_pin_t *pin, int verified); int gpg_pin_is_verified(int pinID);
int gpg_pin_check(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len); 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_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 ---- */ /* --- IO ---- */

View File

@ -316,7 +316,7 @@ int gpg_apdu_put_data(unsigned int ref) {
break; break;
default: default:
THROW(SW_REFERENCED_DATA_NOT_FOUND); THROW(SW_REFERENCED_DATA_NOT_FOUND);
break; return 0;
} }
//fecth 7f78 //fecth 7f78
gpg_io_fetch_tl(&t,&l); gpg_io_fetch_tl(&t,&l);
@ -343,6 +343,7 @@ int gpg_apdu_put_data(unsigned int ref) {
case 0x95: case 0x95:
case 0x96: case 0x96:
case 0x97: case 0x97:
case 0x99:
break; break;
default: default:
THROW(SW_REFERENCED_DATA_NOT_FOUND); THROW(SW_REFERENCED_DATA_NOT_FOUND);

View File

@ -23,12 +23,7 @@
void gpg_check_access_ins() { void gpg_check_access_ins() {
unsigned int ref; 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 ; ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ;
switch (G_gpg_vstate.io_ins) { switch (G_gpg_vstate.io_ins) {
@ -45,7 +40,7 @@ void gpg_check_access_ins() {
return; return;
case INS_RESET_RETRY_COUNTER: 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; return;
} }
@ -57,27 +52,30 @@ void gpg_check_access_ins() {
if (G_gpg_vstate.io_p1 == 0x81) { if (G_gpg_vstate.io_p1 == 0x81) {
return; return;
} }
if (gpg_pin_is_verified(pin_pw3)) { if (gpg_pin_is_verified(PIN_ID_PW3)) {
return; return;
} }
break; break;
case INS_MSE:
return ;
case INS_PSO: case INS_PSO:
if ((ref == 0x9e9a) && gpg_pin_is_verified(pin_pw1)) { if ((ref == 0x9e9a) && gpg_pin_is_verified(PIN_ID_PW1)) {
//pso:sign //pso:sign
if (N_gpg_pstate->PW_status[0] == 0) { if (N_gpg_pstate->PW_status[0] == 0) {
gpg_pin_set_verified(pin_pw1, 0); gpg_pin_set_verified(PIN_ID_PW1, 0);
} }
return; return;
} }
if ((ref == 0x8086 ) && gpg_pin_is_verified(pin_pw2)) { if (((ref == 0x8086 )||(ref == 0x8680)) && gpg_pin_is_verified(PIN_ID_PW2)) {
//pso:dec //pso:dec/enc
return; return;
} }
break; break;
case INS_INTERNAL_AUTHENTICATE: case INS_INTERNAL_AUTHENTICATE:
if (gpg_pin_is_verified(pin_pw2)) { if (gpg_pin_is_verified(PIN_ID_PW2)) {
return; return;
} }
break; break;
@ -86,7 +84,7 @@ void gpg_check_access_ins() {
return; return;
case INS_TERMINATE_DF: case INS_TERMINATE_DF:
if (gpg_pin_is_verified(pin_pw3)) { if (gpg_pin_is_verified(PIN_ID_PW3)) {
return; return;
} }
break; break;
@ -99,10 +97,6 @@ void gpg_check_access_ins() {
void gpg_check_access_read_DO() { void gpg_check_access_read_DO() {
unsigned int ref; 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 ; ref = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ;
@ -152,14 +146,14 @@ void gpg_check_access_read_DO() {
//PW1 //PW1
case 0x0103: case 0x0103:
if (gpg_pin_is_verified(pin_pw2)) { if (gpg_pin_is_verified(PIN_ID_PW2)) {
return; return;
} }
break; break;
//PW3 //PW3
case 0x0104: case 0x0104:
if (gpg_pin_is_verified(pin_pw3)) { if (gpg_pin_is_verified(PIN_ID_PW3)) {
return; return;
} }
break; break;
@ -183,7 +177,7 @@ void gpg_check_access_write_DO() {
case 0x0101: case 0x0101:
case 0x0103: case 0x0103:
case 0x01F2: case 0x01F2:
if (gpg_pin_is_verified(pin_pw2)) { if (gpg_pin_is_verified(PIN_ID_PW2)) {
return; return;
} }
break; break;
@ -225,7 +219,7 @@ void gpg_check_access_write_DO() {
case 0x00D6: case 0x00D6:
case 0x00D7: case 0x00D7:
case 0x00D8: case 0x00D8:
if (gpg_pin_is_verified(pin_pw3)) { if (gpg_pin_is_verified(PIN_ID_PW3)) {
return; return;
} }
break; break;
@ -242,7 +236,10 @@ int gpg_dispatch() {
unsigned int tag,t,l; unsigned int tag,t,l;
int sw; 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 ; tag = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2 ;
@ -265,7 +262,7 @@ int gpg_dispatch() {
case INS_TERMINATE_DF: case INS_TERMINATE_DF:
gpg_io_discard(0); 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); gpg_install(STATE_TERMINATE);
return(SW_OK); return(SW_OK);
break; break;
@ -361,7 +358,7 @@ int gpg_dispatch() {
THROW(SW_INCORRECT_P1P2); THROW(SW_INCORRECT_P1P2);
case INS_RESET_RETRY_COUNTER: 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 == 0) ||
(G_gpg_vstate.io_p1 == 2) ) (G_gpg_vstate.io_p1 == 2) )
) { ) {
@ -375,6 +372,11 @@ int gpg_dispatch() {
sw = gpg_apdu_gen(); sw = gpg_apdu_gen();
break; break;
/* --- MSE --- */
case INS_MSE:
sw = gpg_apdu_mse(tag);
break;
/* --- PSO --- */ /* --- PSO --- */
case INS_PSO: case INS_PSO:
sw = gpg_apdu_pso(tag); sw = gpg_apdu_pso(tag);

View File

@ -18,7 +18,7 @@
#include "gpg_types.h" #include "gpg_types.h"
#include "gpg_api.h" #include "gpg_api.h"
#include "gpg_vars.h" #include "gpg_vars.h"
#include "usbd_ccid_impl.h"
#define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF #define SHORT(x) ((x)>>8)&0xFF, (x)&0xFF
/* ----------------------*/ /* ----------------------*/
/* -- A Kind of Magic -- */ /* -- A Kind of Magic -- */
@ -171,13 +171,13 @@ const unsigned char C_default_AlgoAttrECC_dec[] = {
#else #else
const unsigned char C_default_AlgoAttrECC_sig[] = { const unsigned char C_default_AlgoAttrECC_sig[] = {
// eddsa // eddsa
22, 0x16,
// ed25519 // ed25519
0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01, 0x2B, 0x06, 0x01, 0x04, 0x01, 0xDA, 0x47, 0x0F, 0x01,
}; };
const unsigned char C_default_AlgoAttrECC_dec[] = { const unsigned char C_default_AlgoAttrECC_dec[] = {
// ecdh // ecdh
18, 0x12,
//cv25519 //cv25519
0x2B, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01, 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)); gpg_nvm_write(N_gpg_pstate->magic, (void*)C_MAGIC, sizeof(C_MAGIC));
os_memset(&G_gpg_vstate, 0, sizeof(gpg_v_state_t)); 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 //key conf
G_gpg_vstate.slot = N_gpg_pstate->config_slot[1]; G_gpg_vstate.slot = N_gpg_pstate->config_slot[1];
G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot]; G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot];
gpg_mse_reset();
//pin conf //pin conf
G_gpg_vstate.pinmode = N_gpg_pstate->config_pin[0]; G_gpg_vstate.pinmode = N_gpg_pstate->config_pin[0];
//ux conf //ux conf
@ -260,8 +260,6 @@ int gpg_install(unsigned char app_state) {
pin.counter = 3; pin.counter = 3;
pin.ref = PIN_ID_PW1; pin.ref = PIN_ID_PW1;
gpg_nvm_write(&N_gpg_pstate->PW1, &pin, sizeof(gpg_pin_t)); 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 //default PW3: 1 2 3 4 5 6 7 8
os_memmove(pin.value, C_sha256_PW2, sizeof(C_sha256_PW2)); 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)); nvm_write(&N_gpg_pstate->default_RSA_exponent, &l, sizeof(unsigned int));
//config pin //config pin
#if 1
G_gpg_vstate.work.io_buffer[0] = PIN_MODE_CONFIRM; 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); 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) //default key template: RSA 2048)
for (int s = 0; s< GPG_KEYS_SLOTS; s++) { for (int s = 0; s< GPG_KEYS_SLOTS; s++) {

View File

@ -21,12 +21,11 @@
#include "gpg_ux_nanos.h" #include "gpg_ux_nanos.h"
gpg_pin_t *gpg_pin_get_pin(int id) { gpg_pin_t *gpg_pin_get_pin(int pinref) {
switch (id) { switch (pinref) {
case PIN_ID_PW1 : case PIN_ID_PW1 :
return &N_gpg_pstate->PW1;
case PIN_ID_PW2 : case PIN_ID_PW2 :
return &N_gpg_pstate->PW2; return &N_gpg_pstate->PW1;
case PIN_ID_PW3: case PIN_ID_PW3:
return &N_gpg_pstate->PW3; return &N_gpg_pstate->PW3;
case PIN_ID_RC: 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) { static int gpg_pin_get_state_index(unsigned int pinref) {
switch (id) { switch (pinref) {
case PIN_ID_PW1 : case PIN_ID_PW1 :
return 1; return 1;
case PIN_ID_PW2 : case PIN_ID_PW2 :
@ -52,28 +51,10 @@ static int gpg_pin_get_index(unsigned int id) {
return -1; return -1;
} }
void gpg_pin_sync12() { static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) {
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; cx_sha256_t sha256;
unsigned int counter; 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) { if (pin->counter == 0) {
return SW_PIN_BLOCKED; 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; counter = pin->counter-1;
gpg_nvm_write(&(pin->counter), &counter, sizeof(int)); gpg_nvm_write(&(pin->counter), &counter, sizeof(int));
if (brother) {
gpg_nvm_write(&(brother->counter), &counter, sizeof(int));
}
cx_sha256_init(&sha256); cx_sha256_init(&sha256);
cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, NULL); cx_hash((cx_hash_t*)&sha256, CX_LAST, pin_val, pin_len, NULL);
if (os_memcmp(sha256.acc, pin->value, 32)) { 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; counter = 3;
gpg_nvm_write(&(pin->counter), &counter, sizeof(int)); gpg_nvm_write(&(pin->counter), &counter, sizeof(int));
if (brother) {
gpg_nvm_write(&(brother->counter), &counter, sizeof(int));
}
return SW_OK; 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; int sw;
gpg_pin_set_verified(pin,0); gpg_pin_set_verified(pinID,0);
sw = gpg_pin_check_internal(pin,pin_val,pin_len); sw = gpg_pin_check_internal(pin,pin_val,pin_len);
if (sw == SW_OK) { if (sw == SW_OK) {
gpg_pin_set_verified(pin,1); gpg_pin_set_verified(pinID,1);
return; return;
} }
THROW(sw); 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; int sw;
gpg_pin_set_verified(pinID,0);
sw = gpg_pin_check_internal(pin,pin_val,pin_len); sw = gpg_pin_check_internal(pin,pin_val,pin_len);
gpg_pin_set_verified(pin,0);
if (sw == SW_OK) { if (sw == SW_OK) {
gpg_pin_set_verified(pin,1); gpg_pin_set_verified(pinID,1);
} }
return sw; 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; newpin.counter = 3;
gpg_nvm_write(pin, &newpin, sizeof(gpg_pin_t)); 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; int idx;
idx = gpg_pin_get_index(pin->ref); idx = gpg_pin_get_state_index(pinID);
if (idx >= 0) { if (idx >= 0) {
G_gpg_vstate.verified_pin[idx]=verified; G_gpg_vstate.verified_pin[idx]=verified;
return verified; return verified;
@ -143,9 +119,9 @@ int gpg_pin_set_verified(gpg_pin_t *pin, int verified) {
return 0; return 0;
} }
int gpg_pin_is_verified(gpg_pin_t *pin) { int gpg_pin_is_verified(int pinID) {
int idx; int idx;
idx = gpg_pin_get_index(pin->ref); idx = gpg_pin_get_state_index(pinID);
if (idx >= 0) { if (idx >= 0) {
return G_gpg_vstate.verified_pin[idx]; return G_gpg_vstate.verified_pin[idx];
} }
@ -167,12 +143,15 @@ int gpg_apdu_verify() {
return SW_WRONG_DATA; return SW_WRONG_DATA;
} }
gpg_pin_set_verified(pin,0);
if (gpg_pin_is_blocked(pin)) {
THROW(SW_PIN_BLOCKED); //PINPAD
return SW_PIN_BLOCKED; if (G_gpg_vstate.io_cla==0xFF) {
} if (gpg_pin_is_blocked(pin)) {
if (G_gpg_vstate.io_length == 0) { THROW(SW_PIN_BLOCKED);
return SW_PIN_BLOCKED;
}
if (G_gpg_vstate.pinmode == PIN_MODE_SCREEN) { if (G_gpg_vstate.pinmode == PIN_MODE_SCREEN) {
//Delegate pin check to ui //Delegate pin check to ui
gpg_io_discard(1); gpg_io_discard(1);
@ -186,16 +165,46 @@ int gpg_apdu_verify() {
return 0; return 0;
} }
if (G_gpg_vstate.pinmode == PIN_MODE_TRUST) { 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); gpg_io_discard(1);
return SW_OK; 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, //NORMAL CHECK
G_gpg_vstate.io_length); 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); 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() { int gpg_apdu_change_ref_data() {
@ -208,7 +217,7 @@ int gpg_apdu_change_ref_data() {
return SW_WRONG_DATA; return SW_WRONG_DATA;
} }
gpg_pin_set_verified(pin,0); gpg_pin_set_verified(pin->ref,0);
// --- RC pin --- // --- RC pin ---
@ -252,7 +261,7 @@ int gpg_apdu_change_ref_data() {
len = pin->length; 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, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
len); len);
@ -281,7 +290,7 @@ int gpg_apdu_reset_retry_counter() {
pin_rc = gpg_pin_get_pin(PIN_ID_RC); pin_rc = gpg_pin_get_pin(PIN_ID_RC);
if (G_gpg_vstate.io_p1 == 2) { 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); THROW(SW_SECURITY_STATUS_NOT_SATISFIED);
return 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; rc_len = pin_rc->length;
} }
pw1_len = G_gpg_vstate.io_length-rc_len; 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, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
rc_len); rc_len);
} }

View File

@ -28,7 +28,7 @@ const unsigned char gpg_oid_sha512[] = {
static void gpg_pso_reset_PW1() { static void gpg_pso_reset_PW1() {
if (N_gpg_pstate->PW_status[0] ==0) { 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; return SW_REFERENCED_DATA_NOT_FOUND;
} }
int gpg_apdu_pso(unsigned int pso) { int gpg_apdu_pso(unsigned int pso) {
unsigned int t,l,ksz; unsigned int t,l,ksz;
switch(pso) { 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)); nvm_write(&G_gpg_vstate.kslot->sig_count,&cnt,sizeof(unsigned int));
return sw; 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 --- // --- PSO:DEC ---
case 0x8086: { case 0x8086: {
@ -159,25 +179,25 @@ int gpg_apdu_pso(unsigned int pso) {
// --- PSO:DEC:RSA // --- PSO:DEC:RSA
case 0x00: { case 0x00: {
cx_rsa_private_key_t *key; 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); THROW(SW_CONDITIONS_NOT_SATISFIED);
return 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; ksz = ksz>>3;
key = NULL; key = NULL;
switch(ksz) { switch(ksz) {
case 1024/8: 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; break;
case 2048/8: 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; break;
case 3072/8: 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; break;
case 4096/8: 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; break;
} }
@ -208,7 +228,7 @@ int gpg_apdu_pso(unsigned int pso) {
} }
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset; msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
sz = cx_aes(key, 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+G_gpg_vstate.io_offset, msg_len,
G_gpg_vstate.work.io_buffer); G_gpg_vstate.work.io_buffer);
//send //send
@ -222,11 +242,11 @@ int gpg_apdu_pso(unsigned int pso) {
cx_ecfp_private_key_t *key; cx_ecfp_private_key_t *key;
unsigned int sz; unsigned int sz;
unsigned int curve; 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); THROW(SW_CONDITIONS_NOT_SATISFIED);
return 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) { if (key->d_len != 32) {
THROW(SW_CONDITIONS_NOT_SATISFIED); THROW(SW_CONDITIONS_NOT_SATISFIED);
return SW_CONDITIONS_NOT_SATISFIED; return SW_CONDITIONS_NOT_SATISFIED;
@ -243,7 +263,7 @@ int gpg_apdu_pso(unsigned int pso) {
return SW_WRONG_DATA; 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) { if (curve == CX_CURVE_Curve25519) {
unsigned int i; unsigned int i;
@ -290,14 +310,11 @@ int gpg_apdu_pso(unsigned int pso) {
int gpg_apdu_internal_authenticate() { int gpg_apdu_internal_authenticate() {
gpg_key_t *sigkey; if (G_gpg_vstate.mse_aut->attributes.value[0] == 1) {
sigkey = &G_gpg_vstate.kslot->aut; 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) {
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); THROW(SW_WRONG_LENGTH);
return SW_WRONG_LENGTH; return SW_WRONG_LENGTH;
} }
} }
return gpg_sign(&G_gpg_vstate.kslot->aut); return gpg_sign(G_gpg_vstate.mse_aut);
} }

View File

@ -152,7 +152,6 @@ struct gpg_nv_state_s {
/* PINs */ /* PINs */
gpg_pin_t PW1; gpg_pin_t PW1;
gpg_pin_t PW2;
gpg_pin_t PW3; gpg_pin_t PW3;
gpg_pin_t RC; gpg_pin_t RC;
@ -174,7 +173,9 @@ struct gpg_v_state_s {
/* app state */ /* app state */
unsigned char selected; unsigned char selected;
unsigned char slot; /* DO 01F2 */ 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; unsigned char seed_mode;
/* io state*/ /* io state*/
@ -285,6 +286,7 @@ typedef struct gpg_v_state_s gpg_v_state_t;
#define INS_PUT_DATA_ODD 0xdb #define INS_PUT_DATA_ODD 0xdb
#define INS_VERIFY 0x20 #define INS_VERIFY 0x20
#define INS_MSE 0x22
#define INS_CHANGE_REFERENCE_DATA 0x24 #define INS_CHANGE_REFERENCE_DATA 0x24
#define INS_RESET_RETRY_COUNTER 0x2c #define INS_RESET_RETRY_COUNTER 0x2c

View File

@ -152,12 +152,12 @@ unsigned int ui_pinconfirm_nanos_button(unsigned int button_mask, unsigned int b
sw = 0x6985; sw = 0x6985;
switch(button_mask) { switch(button_mask) {
case BUTTON_EVT_RELEASED|BUTTON_LEFT: // CANCEL 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; sw = 0x6985;
break; break;
case BUTTON_EVT_RELEASED|BUTTON_RIGHT: // OK 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; sw = 0x9000;
break; break;
default: default:
@ -240,9 +240,17 @@ unsigned int ui_pinentry_prepro(const bagl_element_t* element) {
else if (element->component.userid == 2) { else if (element->component.userid == 2) {
unsigned int i; unsigned int i;
G_gpg_vstate.menu[0] = ' '; G_gpg_vstate.menu[0] = ' ';
#if 1
for (i = 1; i<= G_gpg_vstate.ux_pinentry[0]; i++) { 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++) { for (; i<= GPG_MAX_PW_LENGTH;i++) {
G_gpg_vstate.menu[i] = '-'; G_gpg_vstate.menu[i] = '-';
} }
@ -325,15 +333,16 @@ static unsigned int validate_pin() {
if (G_gpg_vstate.io_ins == 0x20) { if (G_gpg_vstate.io_ins == 0x20) {
pin = gpg_pin_get_pin(G_gpg_vstate.io_p2); 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_discard(1);
gpg_io_insert_u16(sw); gpg_io_insert_u16(sw);
gpg_io_do(IO_RETURN_AFTER_TX); 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 ); 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); ui_info(WRONG_PIN, G_gpg_vstate.menu, ui_menu_main_display, 0);
} } else {
return 0; ui_menu_main_display(0);
}
} }
if (G_gpg_vstate.io_ins == 0x24) { if (G_gpg_vstate.io_ins == 0x24) {
@ -344,7 +353,7 @@ static unsigned int validate_pin() {
} }
if (G_gpg_vstate.io_p1 == 3) { if (G_gpg_vstate.io_p1 == 3) {
pin = gpg_pin_get_pin(G_gpg_vstate.io_p2); 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_discard(1);
gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED); gpg_io_insert_u16(SW_CONDITIONS_NOT_SATISFIED);
gpg_io_do(IO_RETURN_AFTER_TX); 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_HOST:
case PIN_MODE_SCREEN: case PIN_MODE_SCREEN:
case PIN_MODE_CONFIRM: 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); ui_info(PIN_USER, NOT_VERIFIED, ui_menu_pinmode_display,0);
return; return;
} }
@ -670,7 +679,7 @@ void ui_menu_pinmode_action(unsigned int value) {
case PIN_MODE_TRUST: 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); ui_info(PIN_ADMIN, NOT_VERIFIED, ui_menu_pinmode_display,0);
return; return;
} }
@ -767,6 +776,7 @@ void ui_menu_slot_action(unsigned int value) {
if (s!= G_gpg_vstate.slot) { if (s!= G_gpg_vstate.slot) {
G_gpg_vstate.slot = s; G_gpg_vstate.slot = s;
G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot]; G_gpg_vstate.kslot = &N_gpg_pstate->keys[G_gpg_vstate.slot];
gpg_mse_reset();
ui_CCID_reset(); ui_CCID_reset();
} }
} }
@ -785,7 +795,7 @@ void ui_menu_slot_action(unsigned int value) {
const ux_menu_entry_t ui_menu_info[] = { const ux_menu_entry_t ui_menu_info[] = {
{NULL, NULL, -1, NULL, "OpenPGP Card", NULL, 0, 0}, {NULL, NULL, -1, NULL, "OpenPGP Card", NULL, 0, 0},
{NULL, NULL, -1, NULL, "(c) Ledger SAS", 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, NULL, -1, NULL, "App " XSTR(GPG_VERSION), NULL, 0, 0},
{NULL, ui_menu_main_display, 3, &C_badge_back, "Back", NULL, 61, 40}, {NULL, ui_menu_main_display, 3, &C_badge_back, "Back", NULL, 61, 40},
UX_MENU_END UX_MENU_END