|
|
|
@ -231,6 +231,8 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|
|
|
|
void *pkey = NULL;
|
|
|
|
|
cx_aes_key_t aes_key = {0};
|
|
|
|
|
cx_err_t error = CX_INTERNAL_ERROR;
|
|
|
|
|
unsigned int pkey_size = 0;
|
|
|
|
|
unsigned int ksz, curve;
|
|
|
|
|
|
|
|
|
|
G_gpg_vstate.DO_current = ref;
|
|
|
|
|
|
|
|
|
@ -326,7 +328,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|
|
|
|
/* ----------------- Extended Header list -----------------*/
|
|
|
|
|
case 0x3FFF: {
|
|
|
|
|
unsigned int len_e, len_p, len_q;
|
|
|
|
|
unsigned int endof, ksz, reset_cnt;
|
|
|
|
|
unsigned int endof, reset_cnt;
|
|
|
|
|
gpg_key_t *keygpg = NULL;
|
|
|
|
|
// fecth 4D
|
|
|
|
|
gpg_io_fetch_tl(&t, &l);
|
|
|
|
@ -395,13 +397,11 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// --- RSA KEY ---
|
|
|
|
|
if (keygpg->attributes.value[0] == KEY_ID_RSA) {
|
|
|
|
|
unsigned int e = 0;
|
|
|
|
|
unsigned char *p, *q, *pq;
|
|
|
|
|
cx_rsa_public_key_t *rsa_pub;
|
|
|
|
|
cx_rsa_private_key_t *rsa_priv;
|
|
|
|
|
unsigned int pkey_size = 0;
|
|
|
|
|
// check length
|
|
|
|
|
ksz = U2BE(keygpg->attributes.value, 1) >> 3;
|
|
|
|
|
rsa_pub = (cx_rsa_public_key_t *) &G_gpg_vstate.work.rsa.public;
|
|
|
|
@ -415,10 +415,12 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|
|
|
|
pkey_size = sizeof(cx_rsa_3072_private_key_t);
|
|
|
|
|
pq = G_gpg_vstate.work.rsa.public3072.n;
|
|
|
|
|
break;
|
|
|
|
|
#ifdef WITH_SUPPORT_RSA4096
|
|
|
|
|
case 4096 / 8:
|
|
|
|
|
pkey_size = sizeof(cx_rsa_4096_private_key_t);
|
|
|
|
|
pq = G_gpg_vstate.work.rsa.public4096.n;
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
default:
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -475,15 +477,11 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|
|
|
|
nvm_write(&G_gpg_vstate.kslot->sig_count, &reset_cnt, sizeof(unsigned int));
|
|
|
|
|
}
|
|
|
|
|
sw = SW_OK;
|
|
|
|
|
}
|
|
|
|
|
// --- ECC KEY ---
|
|
|
|
|
else if ((keygpg->attributes.value[0] == KEY_ID_ECDH) ||
|
|
|
|
|
(keygpg->attributes.value[0] == KEY_ID_ECDSA) ||
|
|
|
|
|
(keygpg->attributes.value[0] == KEY_ID_EDDSA)) {
|
|
|
|
|
unsigned int curve;
|
|
|
|
|
|
|
|
|
|
} else if ((keygpg->attributes.value[0] == KEY_ID_ECDH) ||
|
|
|
|
|
(keygpg->attributes.value[0] == KEY_ID_ECDSA) ||
|
|
|
|
|
(keygpg->attributes.value[0] == KEY_ID_EDDSA)) {
|
|
|
|
|
curve = gpg_oid2curve(&keygpg->attributes.value[1], keygpg->attributes.length - 1);
|
|
|
|
|
if (curve == 0) {
|
|
|
|
|
if (curve == CX_CURVE_NONE) {
|
|
|
|
|
sw = SW_WRONG_DATA;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
@ -637,9 +635,35 @@ int gpg_apdu_put_data(unsigned int ref) {
|
|
|
|
|
sw = SW_WRONG_LENGTH;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
|
|
|
|
nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
|
|
|
|
sw = SW_OK;
|
|
|
|
|
switch (G_gpg_vstate.work.io_buffer[0]) {
|
|
|
|
|
case KEY_ID_RSA:
|
|
|
|
|
ksz = U2BE(G_gpg_vstate.work.io_buffer, 1);
|
|
|
|
|
if ((ksz != 2048) && (ksz != 3072)) {
|
|
|
|
|
sw = SW_WRONG_DATA;
|
|
|
|
|
} else {
|
|
|
|
|
sw = SW_OK;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
case KEY_ID_ECDH:
|
|
|
|
|
case KEY_ID_ECDSA:
|
|
|
|
|
case KEY_ID_EDDSA:
|
|
|
|
|
curve =
|
|
|
|
|
gpg_oid2curve(G_gpg_vstate.work.io_buffer + 1, G_gpg_vstate.io_length - 1);
|
|
|
|
|
if (curve == CX_CURVE_NONE) {
|
|
|
|
|
sw = SW_WRONG_DATA;
|
|
|
|
|
} else {
|
|
|
|
|
sw = SW_OK;
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
sw = SW_WRONG_DATA;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (sw == SW_OK) {
|
|
|
|
|
nvm_write(ptr_v, G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length);
|
|
|
|
|
nvm_write(ptr_l, &G_gpg_vstate.io_length, sizeof(unsigned int));
|
|
|
|
|
}
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
/* ----------------- PWS status ----------------- */
|
|
|
|
@ -801,11 +825,13 @@ end:
|
|
|
|
|
// cmd
|
|
|
|
|
// resp TID API COMPAT len_pub len_priv priv
|
|
|
|
|
int gpg_apdu_get_key_data(unsigned int ref) {
|
|
|
|
|
cx_aes_key_t keyenc;
|
|
|
|
|
gpg_key_t *keygpg;
|
|
|
|
|
cx_aes_key_t keyenc = {0};
|
|
|
|
|
gpg_key_t *keygpg = NULL;
|
|
|
|
|
cx_rsa_private_key_t *key = NULL;
|
|
|
|
|
unsigned int len = 0;
|
|
|
|
|
cx_err_t error = CX_INTERNAL_ERROR;
|
|
|
|
|
int sw = SW_UNKNOWN;
|
|
|
|
|
unsigned int ksz = 0;
|
|
|
|
|
|
|
|
|
|
sw = gpg_init_keyenc(&keyenc);
|
|
|
|
|
if (sw != SW_OK) {
|
|
|
|
@ -832,18 +858,39 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
|
|
|
|
|
|
|
|
|
// encrypted part
|
|
|
|
|
switch (keygpg->attributes.value[0]) {
|
|
|
|
|
case KEY_ID_RSA: // RSA
|
|
|
|
|
case KEY_ID_RSA:
|
|
|
|
|
ksz = U2BE(G_gpg_vstate.mse_dec->attributes.value, 1) >> 3;
|
|
|
|
|
switch (ksz) {
|
|
|
|
|
case 2048 / 8:
|
|
|
|
|
key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa2048;
|
|
|
|
|
len = sizeof(cx_rsa_2048_private_key_t);
|
|
|
|
|
break;
|
|
|
|
|
case 3072 / 8:
|
|
|
|
|
key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa3072;
|
|
|
|
|
len = sizeof(cx_rsa_3072_private_key_t);
|
|
|
|
|
break;
|
|
|
|
|
#ifdef WITH_SUPPORT_RSA4096
|
|
|
|
|
case 4096 / 8:
|
|
|
|
|
key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa4096;
|
|
|
|
|
len = sizeof(cx_rsa_4096_private_key_t);
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((key == NULL) || (key->size != ksz)) {
|
|
|
|
|
return SW_CONDITIONS_NOT_SATISFIED;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// insert pubkey
|
|
|
|
|
gpg_io_insert_u32(4);
|
|
|
|
|
gpg_io_insert(keygpg->pub_key.rsa, 4);
|
|
|
|
|
|
|
|
|
|
// insert privkey
|
|
|
|
|
gpg_io_mark();
|
|
|
|
|
len = GPG_IO_BUFFER_LENGTH - G_gpg_vstate.io_offset;
|
|
|
|
|
CX_CHECK(cx_aes_no_throw(&keyenc,
|
|
|
|
|
CX_ENCRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
|
|
|
|
|
(unsigned char *) &keygpg->priv_key.rsa4096,
|
|
|
|
|
sizeof(cx_rsa_4096_private_key_t),
|
|
|
|
|
(unsigned char *) key,
|
|
|
|
|
len,
|
|
|
|
|
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
|
|
|
|
&len));
|
|
|
|
|
gpg_io_inserted(len);
|
|
|
|
@ -853,7 +900,7 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
|
|
|
|
sw = SW_OK;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
case KEY_ID_ECDH: // ECC
|
|
|
|
|
case KEY_ID_ECDH:
|
|
|
|
|
case KEY_ID_ECDSA:
|
|
|
|
|
case KEY_ID_EDDSA:
|
|
|
|
|
// insert pubkey
|
|
|
|
@ -889,12 +936,14 @@ end:
|
|
|
|
|
// cmd TID API COMPAT len_pub len_priv priv
|
|
|
|
|
// resp -
|
|
|
|
|
int gpg_apdu_put_key_data(unsigned int ref) {
|
|
|
|
|
cx_aes_key_t keyenc;
|
|
|
|
|
gpg_key_t *keygpg;
|
|
|
|
|
unsigned int len;
|
|
|
|
|
unsigned int offset;
|
|
|
|
|
cx_aes_key_t keyenc = {0};
|
|
|
|
|
gpg_key_t *keygpg = NULL;
|
|
|
|
|
unsigned int len = 0;
|
|
|
|
|
cx_rsa_private_key_t *key = NULL;
|
|
|
|
|
unsigned int offset = 0;
|
|
|
|
|
cx_err_t error = CX_INTERNAL_ERROR;
|
|
|
|
|
int sw = SW_UNKNOWN;
|
|
|
|
|
unsigned int ksz = 0;
|
|
|
|
|
|
|
|
|
|
sw = gpg_init_keyenc(&keyenc);
|
|
|
|
|
if (sw != SW_OK) {
|
|
|
|
@ -920,7 +969,6 @@ int gpg_apdu_put_key_data(unsigned int ref) {
|
|
|
|
|
gpg_io_fetch_u32();
|
|
|
|
|
|
|
|
|
|
switch (keygpg->attributes.value[0]) {
|
|
|
|
|
// RSA
|
|
|
|
|
case KEY_ID_RSA:
|
|
|
|
|
// insert pubkey
|
|
|
|
|
len = gpg_io_fetch_u32();
|
|
|
|
@ -937,26 +985,51 @@ int gpg_apdu_put_key_data(unsigned int ref) {
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
offset = G_gpg_vstate.io_offset;
|
|
|
|
|
ksz = U2BE(G_gpg_vstate.mse_dec->attributes.value, 1) >> 3;
|
|
|
|
|
switch (ksz) {
|
|
|
|
|
case 2048 / 8:
|
|
|
|
|
key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa2048;
|
|
|
|
|
len = sizeof(cx_rsa_2048_private_key_t);
|
|
|
|
|
break;
|
|
|
|
|
case 3072 / 8:
|
|
|
|
|
key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa3072;
|
|
|
|
|
len = sizeof(cx_rsa_3072_private_key_t);
|
|
|
|
|
break;
|
|
|
|
|
#ifdef WITH_SUPPORT_RSA4096
|
|
|
|
|
case 4096 / 8:
|
|
|
|
|
key = (cx_rsa_private_key_t *) &keygpg->priv_key.rsa4096;
|
|
|
|
|
len = sizeof(cx_rsa_4096_private_key_t);
|
|
|
|
|
break;
|
|
|
|
|
#endif
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if ((key == NULL) || (key->size != ksz)) {
|
|
|
|
|
sw = SW_CONDITIONS_NOT_SATISFIED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
if (len != GPG_IO_BUFFER_LENGTH) {
|
|
|
|
|
sw = SW_CONDITIONS_NOT_SATISFIED;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PRINTF("[DATA] - put_key_data: key len: %d\n", len);
|
|
|
|
|
gpg_io_discard(0);
|
|
|
|
|
len = GPG_IO_BUFFER_LENGTH;
|
|
|
|
|
CX_CHECK(cx_aes_no_throw(&keyenc,
|
|
|
|
|
CX_DECRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
|
|
|
|
|
G_gpg_vstate.work.io_buffer + offset,
|
|
|
|
|
len,
|
|
|
|
|
G_gpg_vstate.work.io_buffer,
|
|
|
|
|
&len));
|
|
|
|
|
if (len != sizeof(cx_rsa_4096_private_key_t)) {
|
|
|
|
|
&ksz));
|
|
|
|
|
if (len != ksz) {
|
|
|
|
|
PRINTF("[DATA] - put_key_data: Wrong aes output len: %d / %d\n", len, ksz);
|
|
|
|
|
sw = SW_WRONG_DATA;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
nvm_write((unsigned char *) &keygpg->priv_key.rsa4096,
|
|
|
|
|
G_gpg_vstate.work.io_buffer,
|
|
|
|
|
len);
|
|
|
|
|
nvm_write((unsigned char *) key, G_gpg_vstate.work.io_buffer, len);
|
|
|
|
|
sw = SW_OK;
|
|
|
|
|
break;
|
|
|
|
|
|
|
|
|
|
// ECC
|
|
|
|
|
case KEY_ID_ECDH: // ECC
|
|
|
|
|
case KEY_ID_ECDH:
|
|
|
|
|
case KEY_ID_ECDSA:
|
|
|
|
|
case KEY_ID_EDDSA:
|
|
|
|
|
// insert pubkey
|
|
|
|
|