RC6
Features: "PIN confirm" is now the default PIN input mode. Add EF 01F8 for setting default RSA public exponent for key generation. Access control is PW3/Admin. Bug fixes: Fix Issue #2: Add explicit return after each throw.
This commit is contained in:
parent
980d24d1e7
commit
2e0d755fb6
16 changed files with 369 additions and 53 deletions
|
@ -67,6 +67,7 @@ void gpg_io_insert_tlv(unsigned int T, unsigned int L, unsigned char const *V) ;
|
|||
|
||||
void gpg_io_fetch_buffer(unsigned char * buffer, unsigned int len) ;
|
||||
unsigned int gpg_io_fetch_u32(void) ;
|
||||
unsigned int gpg_io_fetch_u24(void) ;
|
||||
unsigned int gpg_io_fetch_u16(void) ;
|
||||
unsigned int gpg_io_fetch_u8(void) ;
|
||||
int gpg_io_fetch_t(unsigned int *T) ;
|
||||
|
|
|
@ -29,6 +29,7 @@ int gpg_apdu_get_challenge() {
|
|||
}
|
||||
if (olen > GPG_EXT_CHALLENGE_LENTH) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if ((G_gpg_vstate.io_p1&0x82) == 0x82) {
|
||||
|
|
|
@ -30,6 +30,7 @@ int gpg_apdu_get_data(unsigned int ref) {
|
|||
int sw;
|
||||
|
||||
|
||||
|
||||
if (G_gpg_vstate.DO_current != ref) {
|
||||
G_gpg_vstate.DO_current = ref;
|
||||
G_gpg_vstate.DO_reccord = 0;
|
||||
|
@ -64,6 +65,10 @@ int gpg_apdu_get_data(unsigned int ref) {
|
|||
case 0x01F2:
|
||||
gpg_io_insert_u8(G_gpg_vstate.slot);
|
||||
break;
|
||||
/* ----------------- Config RSA exponent ----------------- */
|
||||
case 0x01F8:
|
||||
gpg_io_insert_u32(N_gpg_pstate->default_RSA_exponent);
|
||||
break;
|
||||
|
||||
/* ----------------- Application ----------------- */
|
||||
/* Full Application identifier */
|
||||
|
@ -176,8 +181,8 @@ int gpg_apdu_get_data(unsigned int ref) {
|
|||
|
||||
/* WAT */
|
||||
default:
|
||||
sw = SW_REFERENCED_DATA_NOT_FOUND;
|
||||
break;
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return sw;
|
||||
|
@ -225,6 +230,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
WRITE_PRIVATE_DO:
|
||||
if (G_gpg_vstate.io_length > GPG_EXT_PRIVATE_DO_LENGTH) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, G_gpg_vstate.io_length);
|
||||
gpg_nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
||||
|
@ -234,29 +240,43 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
case 0x01F1:
|
||||
if (G_gpg_vstate.io_length != 3) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
if ((G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset +0] != GPG_KEYS_SLOTS) ||
|
||||
(G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset +1] >= GPG_KEYS_SLOTS) ||
|
||||
(G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset +2] > 3)) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(N_gpg_pstate->config_slot, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,3);
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
case 0x01F2:
|
||||
if ((N_gpg_pstate->config_slot[2] & 2) == 0) {
|
||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||
return 0;
|
||||
}
|
||||
if ((G_gpg_vstate.io_length != 1) ||
|
||||
(G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset] >= GPG_KEYS_SLOTS)) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
G_gpg_vstate.slot = G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset];
|
||||
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
/* ----------------- Config RSA exponent ----------------- */
|
||||
case 0x01F8: {
|
||||
unsigned int e;
|
||||
if (G_gpg_vstate.io_length != 4) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
e = gpg_io_fetch_u32();
|
||||
nvm_write(&N_gpg_pstate->default_RSA_exponent, &e, sizeof(unsigned int));
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------- Serial -----------------*/
|
||||
case 0x4f:
|
||||
if (G_gpg_vstate.io_length != 4) {
|
||||
|
@ -264,7 +284,6 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
}
|
||||
G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset] &= ~0x07;
|
||||
nvm_write(&N_gpg_pstate->AID[10], &G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset], 4);
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
/* ----------------- Extended Header list -----------------*/
|
||||
|
@ -277,6 +296,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
gpg_io_fetch_tl(&t,&l);
|
||||
if (t!=0x4D) {
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
//fecth B8/B6/A4
|
||||
gpg_io_fetch_tl(&t,&l);
|
||||
|
@ -296,11 +316,13 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
break;
|
||||
default:
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
break;
|
||||
}
|
||||
//fecth 7f78
|
||||
gpg_io_fetch_tl(&t,&l);
|
||||
if (t!=0x7f48) {
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
len_e = 0; len_p = 0; len_q = 0;
|
||||
endof = G_gpg_vstate.io_offset+l;
|
||||
|
@ -324,12 +346,14 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
break;
|
||||
default:
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
//fecth 5f78
|
||||
gpg_io_fetch_tl(&t,&l);
|
||||
if (t!=0x5f48) {
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// --- RSA KEY ---
|
||||
|
@ -373,33 +397,40 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
break;
|
||||
}
|
||||
ksz = ksz>>1;
|
||||
if ( (len_e>4)||(len_e==0) ||
|
||||
(len_p > ksz )||
|
||||
(len_q > ksz)) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
}
|
||||
|
||||
|
||||
//fetch e
|
||||
e = 0;
|
||||
switch(len_e) {
|
||||
case 4:
|
||||
e = (e<<8) | gpg_io_fetch_u8();
|
||||
e = gpg_io_fetch_u32();
|
||||
break;
|
||||
case 3:
|
||||
e = (e<<8) | gpg_io_fetch_u8();
|
||||
e = gpg_io_fetch_u24();
|
||||
break;
|
||||
case 2:
|
||||
e = (e<<8) | gpg_io_fetch_u8();
|
||||
e = gpg_io_fetch_u16();
|
||||
break;
|
||||
case 1:
|
||||
e = (e<<8) | gpg_io_fetch_u8();
|
||||
e = gpg_io_fetch_u8();
|
||||
break;
|
||||
default:
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//move p,q over pub key, this only work because adr<rsa_pub> < adr<p>
|
||||
if ( (len_p > ksz )|| (len_q > ksz)) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
p = G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset;
|
||||
q = p + len_p;
|
||||
|
||||
os_memmove(pq+ksz-len_p, p, len_p);
|
||||
os_memmove(pq+2*ksz-len_q, q, len_q);
|
||||
os_memset(pq, 0, ksz-len_p);
|
||||
os_memmove(pq+2*ksz-len_q, q, len_q);
|
||||
os_memset(pq+ksz, 0, ksz-len_q);
|
||||
|
||||
//regenerate RSA private key
|
||||
cx_rsa_generate_pair(ksz<<1, rsa_pub, rsa_priv, e, pq);
|
||||
|
||||
|
@ -421,6 +452,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
curve = gpg_oid2curve(&keygpg->attributes.value[1], keygpg->attributes.length-1);
|
||||
if (curve == 0) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
ksz = 32;
|
||||
if (ksz == 32) {
|
||||
|
@ -440,6 +472,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
// --- UNSUPPORTED KEY ---
|
||||
else {
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
} //endof of 3fff
|
||||
|
@ -450,45 +483,45 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
case 0x5B:
|
||||
if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->name.value)) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(N_gpg_pstate->name.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
||||
gpg_nvm_write(&N_gpg_pstate->name.length, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
||||
sw = SW_OK;
|
||||
break;
|
||||
/* Login data */
|
||||
case 0x5E:
|
||||
if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->login.value)) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(N_gpg_pstate->login.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
||||
gpg_nvm_write(&N_gpg_pstate->login.length, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
||||
sw = SW_OK;
|
||||
break;
|
||||
/* Language preferences */
|
||||
case 0x5F2D:
|
||||
if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->lang.value)) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(N_gpg_pstate->lang.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
||||
gpg_nvm_write(&N_gpg_pstate->lang.length, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
||||
sw = SW_OK;
|
||||
break;
|
||||
/* Sex */
|
||||
case 0x5F35:
|
||||
if (G_gpg_vstate.io_length != sizeof(N_gpg_pstate->sex)) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(N_gpg_pstate->sex, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
||||
sw = SW_OK;
|
||||
break;
|
||||
/* Uniform resource locator */
|
||||
case 0x5F50:
|
||||
if (G_gpg_vstate.io_length > sizeof(N_gpg_pstate->url.value)) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(N_gpg_pstate->url.value, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
||||
gpg_nvm_write(&N_gpg_pstate->url.length, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
/* ----------------- Cardholder certificate ----------------- */
|
||||
|
@ -508,8 +541,8 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
ptr_v = G_gpg_vstate.kslot->dec.CA.value;
|
||||
goto WRITE_CA;
|
||||
default:
|
||||
sw = SW_REFERENCED_DATA_NOT_FOUND;
|
||||
break;
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
WRITE_CA:
|
||||
if (G_gpg_vstate.io_length > GPG_EXT_CARD_HOLDER_CERT_LENTH) {
|
||||
|
@ -517,7 +550,6 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
}
|
||||
gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
||||
gpg_nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
/* ----------------- Algorithm attributes ----------------- */
|
||||
|
@ -536,10 +568,10 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
WRITE_ATTRIBUTES:
|
||||
if (G_gpg_vstate.io_length > 12) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
||||
gpg_nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
/* ----------------- PWS status ----------------- */
|
||||
|
@ -569,9 +601,9 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
WRITE_FINGERPRINTS:
|
||||
if (G_gpg_vstate.io_length != 20) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 20);
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
/* ----------------- Generation date/time ----------------- */
|
||||
|
@ -587,9 +619,9 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
WRITE_DATE:
|
||||
if (G_gpg_vstate.io_length != 4) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 4);
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
/* ----------------- AES key ----------------- */
|
||||
|
@ -638,9 +670,9 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
WRITE_UIF:
|
||||
if (G_gpg_vstate.io_length != 2) {
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
gpg_nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, 2);
|
||||
sw = SW_OK;
|
||||
break;
|
||||
|
||||
/* ----------------- WAT ----------------- */
|
||||
|
@ -648,6 +680,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|||
sw = SW_REFERENCED_DATA_NOT_FOUND;
|
||||
break;
|
||||
}
|
||||
|
||||
gpg_io_discard(1);
|
||||
return sw;
|
||||
|
||||
|
|
|
@ -102,6 +102,10 @@ void gpg_check_access_read_DO() {
|
|||
//ALWAYS
|
||||
case 0x0101:
|
||||
case 0x0102:
|
||||
case 0x01F0:
|
||||
case 0x01F1:
|
||||
case 0x01F2:
|
||||
case 0x01F8:
|
||||
case 0x006E:
|
||||
case 0x0065:
|
||||
case 0x0073:
|
||||
|
@ -179,6 +183,7 @@ void gpg_check_access_write_DO() {
|
|||
case 0x0102:
|
||||
case 0x0104:
|
||||
case 0x01F1:
|
||||
case 0x01F8:
|
||||
case 0x005E:
|
||||
case 0x005B:
|
||||
case 0x5F2D:
|
||||
|
|
|
@ -69,10 +69,12 @@ int gpg_apdu_gen() {
|
|||
break;
|
||||
default:
|
||||
THROW(SW_INCORRECT_P1P2);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (G_gpg_vstate.io_lc != 2){
|
||||
THROW(SW_WRONG_LENGTH);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gpg_io_fetch_tl(&t,&l);
|
||||
|
@ -94,6 +96,7 @@ int gpg_apdu_gen() {
|
|||
break;
|
||||
default:
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
switch ((G_gpg_vstate.io_p1<<8)|G_gpg_vstate.io_p2) {
|
||||
|
@ -102,7 +105,7 @@ int gpg_apdu_gen() {
|
|||
case 0x8001:
|
||||
// RSA
|
||||
if (keygpg->attributes.value[0] == 0x01) {
|
||||
#define GPG_RSA_DEFAULT_PUB 0x010001U
|
||||
|
||||
unsigned char *pq;
|
||||
cx_rsa_public_key_t *rsa_pub;
|
||||
cx_rsa_private_key_t *rsa_priv, *pkey;
|
||||
|
@ -151,7 +154,7 @@ int gpg_apdu_gen() {
|
|||
}
|
||||
|
||||
|
||||
cx_rsa_generate_pair(ksz, rsa_pub, rsa_priv, GPG_RSA_DEFAULT_PUB, pq);
|
||||
cx_rsa_generate_pair(ksz, rsa_pub, rsa_priv, N_gpg_pstate->default_RSA_exponent, pq);
|
||||
|
||||
nvm_write(pkey, rsa_priv, pkey_size);
|
||||
nvm_write(&keygpg->pub_key.rsa[0], rsa_pub->e, 4);
|
||||
|
@ -162,7 +165,7 @@ int gpg_apdu_gen() {
|
|||
gpg_io_clear();
|
||||
|
||||
goto send_rsa_pub;
|
||||
#undef GPG_RSA_DEFAULT_PUB
|
||||
|
||||
}
|
||||
// ECC
|
||||
if ((keygpg->attributes.value[0] == 18) ||
|
||||
|
@ -207,24 +210,28 @@ int gpg_apdu_gen() {
|
|||
case 1024/8:
|
||||
if (keygpg->key.rsa1024.size == 0) {
|
||||
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
gpg_io_insert_tlv(0x81,ksz,(unsigned char*)&keygpg->key.rsa4096.n);
|
||||
break;
|
||||
|
@ -248,6 +255,7 @@ int gpg_apdu_gen() {
|
|||
|
||||
if (keygpg->pub_key.ecfp256.W_len == 0) {
|
||||
THROW (SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
gpg_io_discard(1);
|
||||
gpg_io_mark();
|
||||
|
@ -277,4 +285,5 @@ int gpg_apdu_gen() {
|
|||
}
|
||||
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -276,9 +276,13 @@ int gpg_install(unsigned char app_state) {
|
|||
G_gpg_vstate.work.io_buffer[1] = 0;
|
||||
G_gpg_vstate.work.io_buffer[2] = 3; // 3: selection by APDU and screen
|
||||
gpg_nvm_write(&N_gpg_pstate->config_slot, G_gpg_vstate.work.io_buffer, 3);
|
||||
|
||||
|
||||
//config rsa pub
|
||||
l = GPG_RSA_DEFAULT_PUB;
|
||||
nvm_write(&N_gpg_pstate->default_RSA_exponent, &l, sizeof(unsigned int));
|
||||
|
||||
//config pin
|
||||
G_gpg_vstate.work.io_buffer[0] = PIN_MODE_SCREEN;
|
||||
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);
|
||||
|
||||
//default key template: RSA 2048)
|
||||
|
|
13
src/gpg_io.c
13
src/gpg_io.c
|
@ -162,6 +162,15 @@ unsigned int gpg_io_fetch_u32() {
|
|||
return v32;
|
||||
}
|
||||
|
||||
unsigned int gpg_io_fetch_u24() {
|
||||
unsigned int v24;
|
||||
v24 = ( (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+0] << 16) |
|
||||
(G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+1] << 8) |
|
||||
(G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+2] << 0) );
|
||||
G_gpg_vstate.io_offset += 3;
|
||||
return v24;
|
||||
}
|
||||
|
||||
unsigned int gpg_io_fetch_u16() {
|
||||
unsigned int v16;
|
||||
v16 = ( (G_gpg_vstate.work.io_buffer[G_gpg_vstate.io_offset+0] << 8) |
|
||||
|
@ -269,6 +278,7 @@ int gpg_io_do(unsigned int io_flags) {
|
|||
(G_io_apdu_buffer[2] != 0x00) ||
|
||||
(G_io_apdu_buffer[3] != 0x00) ) {
|
||||
THROW(SW_COMMAND_NOT_ALLOWED);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
os_memmove(G_io_apdu_buffer, G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset, G_gpg_vstate.io_length);
|
||||
|
@ -329,7 +339,8 @@ int gpg_io_do(unsigned int io_flags) {
|
|||
(G_io_apdu_buffer[1] != G_gpg_vstate.io_ins) ||
|
||||
(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);
|
||||
THROW(SW_COMMAND_NOT_ALLOWED);
|
||||
return 0;
|
||||
}
|
||||
G_gpg_vstate.io_cla = G_io_apdu_buffer[0];
|
||||
G_gpg_vstate.io_lc = G_io_apdu_buffer[4];
|
||||
|
|
|
@ -131,6 +131,7 @@ unsigned short io_exchange_al(unsigned char channel, unsigned short tx_len) {
|
|||
|
||||
default:
|
||||
THROW(INVALID_PARAMETER);
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -139,6 +139,7 @@ int gpg_apdu_verify(int id) {
|
|||
pin = gpg_get_pin(id);
|
||||
if (pin == NULL) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gpg_set_pin_verified(id,0);
|
||||
|
@ -168,7 +169,7 @@ int gpg_apdu_verify(int id) {
|
|||
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_set_pin_verified(id,1);
|
||||
gpg_io_discard(1);
|
||||
return SW_OK;
|
||||
}
|
||||
|
@ -180,6 +181,7 @@ int gpg_apdu_change_ref_data(int id) {
|
|||
pin = gpg_get_pin(id);
|
||||
if (pin == NULL) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
gpg_set_pin_verified(id,0);
|
||||
|
@ -195,6 +197,7 @@ int gpg_apdu_change_ref_data(int id) {
|
|||
else if ((newlen > GPG_MAX_PW_LENGTH) ||
|
||||
(newlen < 8)) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
} else {
|
||||
gpg_set_pin(pin,
|
||||
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset,
|
||||
|
@ -234,6 +237,7 @@ int gpg_apdu_change_ref_data(int id) {
|
|||
((id == PIN_ID_PW1) && (newlen < 6)) ||
|
||||
((id == PIN_ID_PW3) && (newlen < 8)) ) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
gpg_set_pin(pin,
|
||||
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset+len,
|
||||
|
@ -252,6 +256,7 @@ int gpg_apdu_reset_retry_counter() {
|
|||
if (G_gpg_vstate.io_p1 == 2) {
|
||||
if (!G_gpg_vstate.verified_pin[PIN_ID_PW3]) {
|
||||
THROW(SW_SECURITY_STATUS_NOT_SATISFIED);
|
||||
return 0;
|
||||
}
|
||||
rc_len = 0;
|
||||
pw1_len = G_gpg_vstate.io_length;
|
||||
|
@ -271,6 +276,7 @@ int gpg_apdu_reset_retry_counter() {
|
|||
|
||||
if ((pw1_len > GPG_MAX_PW_LENGTH) ||(pw1_len < 6)) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
gpg_set_pin(pin_pw1,
|
||||
G_gpg_vstate.work.io_buffer+G_gpg_vstate.io_offset+rc_len,
|
||||
|
|
|
@ -50,6 +50,7 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
|||
}
|
||||
if (key->size != ksz) {
|
||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
//sign
|
||||
|
@ -82,6 +83,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;
|
||||
}
|
||||
//sign
|
||||
if (sigkey->attributes.value[0] == 19) {
|
||||
|
@ -122,7 +124,7 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
|||
}
|
||||
// --- PSO:CDS NOT SUPPORTED
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
@ -133,6 +135,7 @@ int gpg_apdu_pso(unsigned int pso) {
|
|||
case 0x9e9a: {
|
||||
return gpg_sign(&G_gpg_vstate.kslot->sig);
|
||||
}
|
||||
|
||||
// --- PSO:DEC ---
|
||||
case 0x8086: {
|
||||
unsigned int msg_len;
|
||||
|
@ -141,11 +144,12 @@ int gpg_apdu_pso(unsigned int pso) {
|
|||
pad_byte = gpg_io_fetch_u8();
|
||||
|
||||
switch(pad_byte) {
|
||||
// --- RSA
|
||||
// --- PSO:DEC:RSA
|
||||
case 0x00: {
|
||||
cx_rsa_private_key_t *key;
|
||||
if (G_gpg_vstate.kslot->dec.attributes.value[0] != 0x01) {
|
||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||
return 0;
|
||||
}
|
||||
ksz = (G_gpg_vstate.kslot->dec.attributes.value[1]<<8) | G_gpg_vstate.kslot->dec.attributes.value[2];
|
||||
ksz = ksz>>3;
|
||||
|
@ -167,6 +171,7 @@ int gpg_apdu_pso(unsigned int pso) {
|
|||
|
||||
if ((key == NULL) || (key->size != ksz)) {
|
||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||
return 0;
|
||||
}
|
||||
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
|
||||
sz = cx_rsa_decrypt(key,
|
||||
|
@ -179,13 +184,15 @@ int gpg_apdu_pso(unsigned int pso) {
|
|||
gpg_io_inserted(sz);
|
||||
return SW_OK;
|
||||
}
|
||||
// --- AES
|
||||
|
||||
// --- PSO:DEC:AES
|
||||
case 0x02: {
|
||||
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 0;
|
||||
}
|
||||
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
|
||||
sz = cx_aes(key,
|
||||
|
@ -197,26 +204,31 @@ int gpg_apdu_pso(unsigned int pso) {
|
|||
gpg_io_inserted(sz);
|
||||
return SW_OK;
|
||||
}
|
||||
// --- ECDH
|
||||
|
||||
// --- PSO:DEC:ECDH
|
||||
case 0xA6: {
|
||||
cx_ecfp_private_key_t *key;
|
||||
unsigned int sz;
|
||||
unsigned int curve;
|
||||
if (G_gpg_vstate.kslot->dec.attributes.value[0] != 18) {
|
||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||
return 0;
|
||||
}
|
||||
key = &G_gpg_vstate.kslot->dec.key.ecfp256;
|
||||
if (key->d_len != 32) {
|
||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||
return 0;
|
||||
}
|
||||
gpg_io_fetch_l(&l);
|
||||
gpg_io_fetch_tl(&t, &l);
|
||||
if (t != 0x7f49) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
gpg_io_fetch_tl(&t, &l);
|
||||
if (t != 0x86) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return 0;
|
||||
}
|
||||
|
||||
curve = gpg_oid2curve(G_gpg_vstate.kslot->dec.attributes.value+1, G_gpg_vstate.kslot->dec.attributes.length-1);
|
||||
|
@ -246,18 +258,23 @@ int gpg_apdu_pso(unsigned int pso) {
|
|||
gpg_io_insert( G_gpg_vstate.work.io_buffer+128,sz);
|
||||
return SW_OK;
|
||||
}
|
||||
// --- PSO:DEC NOT SUPPORTDED
|
||||
default:
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
}
|
||||
|
||||
//--- PSO NOT SUPPPORTED ---
|
||||
default:
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
// --- PSO:DEC:xx NOT SUPPORTDED
|
||||
default:
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
THROW(SW_WRONG_DATA);
|
||||
}}
|
||||
|
||||
//--- PSO:yy NOT SUPPPORTED ---
|
||||
default:
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int gpg_apdu_internal_authenticate() {
|
||||
|
@ -267,6 +284,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 gpg_sign(&G_gpg_vstate.kslot->aut);
|
||||
|
|
|
@ -37,6 +37,7 @@ int gpg_apdu_select() {
|
|||
sw = SW_OK;
|
||||
} else {
|
||||
THROW(SW_FILE_NOT_FOUND);
|
||||
return 0;
|
||||
}
|
||||
return sw;
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
#define GPG_KEY_ATTRIBUTES_LENGTH 12
|
||||
|
||||
#define GPG_RSA_DEFAULT_PUB 0x010001U
|
||||
|
||||
struct gpg_pin_s {
|
||||
//initial pin length, 0 means not set
|
||||
|
@ -113,6 +114,8 @@ struct gpg_nv_state_s {
|
|||
|
||||
/* 01F1 (01F2 is volatile)*/
|
||||
unsigned char config_slot[3];
|
||||
/* RSA exponent */
|
||||
unsigned int default_RSA_exponent;
|
||||
|
||||
/* 0101 0102 0103 0104 */
|
||||
LV(private_DO1, GPG_EXT_PRIVATE_DO_LENGTH);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue