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:
parent
582928a16d
commit
a1c8e7766c
9
Makefile
9
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 #
|
||||
|
@ -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 ---- */
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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++) {
|
||||
|
123
src/gpg_pin.c
123
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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user