mirror of
https://github.com/LedgerHQ/openpgp-card-app
synced 2024-11-09 07:10:30 +00:00
Fix crypto deprecated warnings
This commit is contained in:
parent
1b7e959b1b
commit
e8e46d7990
@ -18,9 +18,11 @@
|
||||
#include "gpg_types.h"
|
||||
#include "gpg_api.h"
|
||||
#include "gpg_vars.h"
|
||||
#include "cx_errors.h"
|
||||
|
||||
int gpg_apdu_get_challenge() {
|
||||
unsigned int olen, hlen;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
if ((G_gpg_vstate.io_p1 & 0x80) == 0x80) {
|
||||
olen = G_gpg_vstate.io_p2;
|
||||
@ -35,39 +37,46 @@ int gpg_apdu_get_challenge() {
|
||||
if ((G_gpg_vstate.io_p1 & 0x82) == 0x82) {
|
||||
unsigned int path[2];
|
||||
unsigned char chain[32];
|
||||
unsigned char Sr[32];
|
||||
unsigned char Sr[64];
|
||||
|
||||
memset(chain, 0, 32);
|
||||
path[0] = 0x80475047;
|
||||
path[1] = 0x0F0F0F0F;
|
||||
os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 2, Sr, chain);
|
||||
CX_CHECK(os_derive_bip32_no_throw(CX_CURVE_SECP256K1, path, 2, Sr, chain));
|
||||
chain[0] = 'r';
|
||||
chain[1] = 'n';
|
||||
chain[2] = 'd';
|
||||
|
||||
cx_sha256_init(&G_gpg_vstate.work.md.sha256);
|
||||
cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha256, 0, Sr, 32, NULL, 0);
|
||||
cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha256, 0, chain, 3, NULL, 0);
|
||||
hlen = cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha256,
|
||||
CX_LAST,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
G_gpg_vstate.io_length,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
32);
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha256, 0, Sr, 32, NULL, 0));
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha256, 0, chain, 3, NULL, 0));
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha256,
|
||||
CX_LAST,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
G_gpg_vstate.io_length,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
32));
|
||||
hlen = cx_hash_get_size((const cx_hash_t *) &G_gpg_vstate.work.md.sha256);
|
||||
|
||||
cx_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, olen);
|
||||
cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha3,
|
||||
CX_LAST,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
hlen,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
olen);
|
||||
CX_CHECK(cx_sha3_xof_init_no_throw(&G_gpg_vstate.work.md.sha3, 256, olen));
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha3,
|
||||
CX_LAST,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
hlen,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
olen));
|
||||
} else {
|
||||
cx_rng(G_gpg_vstate.work.io_buffer, olen);
|
||||
error = CX_OK;
|
||||
}
|
||||
|
||||
if ((G_gpg_vstate.io_p1 & 0x81) == 0x81) {
|
||||
cx_math_next_prime(G_gpg_vstate.work.io_buffer, olen);
|
||||
CX_CHECK(cx_math_next_prime_no_throw(G_gpg_vstate.work.io_buffer, olen));
|
||||
}
|
||||
|
||||
end:
|
||||
if (error != CX_OK) {
|
||||
THROW(error);
|
||||
}
|
||||
gpg_io_discard(0);
|
||||
gpg_io_inserted(olen);
|
||||
|
103
src/gpg_data.c
103
src/gpg_data.c
@ -18,6 +18,7 @@
|
||||
#include "gpg_types.h"
|
||||
#include "gpg_api.h"
|
||||
#include "gpg_vars.h"
|
||||
#include "cx_errors.h"
|
||||
|
||||
int gpg_apdu_select_data(unsigned int ref, int record) {
|
||||
G_gpg_vstate.DO_current = ref;
|
||||
@ -224,6 +225,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
||||
unsigned int t, l, sw;
|
||||
unsigned int *ptr_l;
|
||||
unsigned char *ptr_v;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
G_gpg_vstate.DO_current = ref;
|
||||
sw = SW_OK;
|
||||
@ -452,7 +454,7 @@ int gpg_apdu_put_data(unsigned int ref) {
|
||||
_e[1] = e >> 16;
|
||||
_e[2] = e >> 8;
|
||||
_e[3] = e >> 0;
|
||||
cx_rsa_generate_pair(ksz << 1, rsa_pub, rsa_priv, _e, 4, pq);
|
||||
CX_CHECK(cx_rsa_generate_pair_no_throw(ksz << 1, rsa_pub, rsa_priv, _e, 4, pq));
|
||||
|
||||
// write keys
|
||||
nvm_write(&keygpg->pub_key.rsa, rsa_pub->e, 4);
|
||||
@ -479,10 +481,10 @@ int gpg_apdu_put_data(unsigned int ref) {
|
||||
memmove(G_gpg_vstate.work.ecfp.private.d,
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
ksz);
|
||||
cx_ecfp_generate_pair(curve,
|
||||
&G_gpg_vstate.work.ecfp.public,
|
||||
&G_gpg_vstate.work.ecfp.private,
|
||||
1);
|
||||
CX_CHECK(cx_ecfp_generate_pair_no_throw(curve,
|
||||
&G_gpg_vstate.work.ecfp.public,
|
||||
&G_gpg_vstate.work.ecfp.private,
|
||||
1));
|
||||
nvm_write(&keygpg->pub_key.ecfp,
|
||||
&G_gpg_vstate.work.ecfp.public,
|
||||
sizeof(cx_ecfp_public_key_t));
|
||||
@ -682,17 +684,21 @@ int gpg_apdu_put_data(unsigned int ref) {
|
||||
pkey = &G_gpg_vstate.kslot->AES_dec;
|
||||
goto init_aes_key;
|
||||
init_aes_key:
|
||||
cx_aes_init_key(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length, &aes_key);
|
||||
CX_CHECK(cx_aes_init_key_no_throw(G_gpg_vstate.work.io_buffer,
|
||||
G_gpg_vstate.io_length,
|
||||
&aes_key));
|
||||
gpg_nvm_write(pkey, &aes_key, sizeof(cx_aes_key_t));
|
||||
break;
|
||||
|
||||
/* AES key: one shot */
|
||||
case 0xF4:
|
||||
cx_aes_init_key(G_gpg_vstate.work.io_buffer, G_gpg_vstate.io_length, &aes_key);
|
||||
CX_CHECK(cx_aes_init_key_no_throw(G_gpg_vstate.work.io_buffer,
|
||||
G_gpg_vstate.io_length,
|
||||
&aes_key));
|
||||
gpg_nvm_write((void *) &N_gpg_pstate->SM_enc, &aes_key, sizeof(cx_aes_key_t));
|
||||
cx_aes_init_key(G_gpg_vstate.work.io_buffer + 16,
|
||||
G_gpg_vstate.io_length,
|
||||
&aes_key);
|
||||
CX_CHECK(cx_aes_init_key_no_throw(G_gpg_vstate.work.io_buffer + 16,
|
||||
G_gpg_vstate.io_length,
|
||||
&aes_key));
|
||||
gpg_nvm_write((void *) &N_gpg_pstate->SM_mac, &aes_key, sizeof(cx_aes_key_t));
|
||||
break;
|
||||
}
|
||||
@ -744,14 +750,22 @@ int gpg_apdu_put_data(unsigned int ref) {
|
||||
|
||||
gpg_io_discard(1);
|
||||
return sw;
|
||||
end:
|
||||
THROW(error);
|
||||
}
|
||||
|
||||
static void gpg_init_keyenc(cx_aes_key_t *keyenc) {
|
||||
unsigned char seed[32];
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed);
|
||||
gpg_pso_derive_key_seed(seed, (unsigned char *) PIC("key "), 1, seed, 16);
|
||||
cx_aes_init_key(seed, 16, keyenc);
|
||||
CX_CHECK(cx_aes_init_key_no_throw(seed, 16, keyenc));
|
||||
|
||||
end:
|
||||
if (error != CX_OK) {
|
||||
THROW(error);
|
||||
}
|
||||
}
|
||||
|
||||
// cmd
|
||||
@ -761,6 +775,7 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
||||
gpg_key_t *keygpg;
|
||||
unsigned int len = 0;
|
||||
gpg_init_keyenc(&keyenc);
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
switch (ref) {
|
||||
case 0x00B6:
|
||||
@ -780,8 +795,13 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
||||
gpg_io_discard(1);
|
||||
// clear part
|
||||
gpg_io_insert_u32(TARGET_ID);
|
||||
gpg_io_insert_u32(CX_APILEVEL);
|
||||
gpg_io_insert_u32(CX_COMPAT_APILEVEL);
|
||||
|
||||
// TODO; Check
|
||||
// gpg_io_insert_u32(CX_APILEVEL);
|
||||
// gpg_io_insert_u32(CX_COMPAT_APILEVEL);
|
||||
gpg_io_insert_u32(get_api_level());
|
||||
gpg_io_insert_u32(get_api_level());
|
||||
|
||||
// encrypted part
|
||||
switch (keygpg->attributes.value[0]) {
|
||||
case 0x01: // RSA
|
||||
@ -791,12 +811,13 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
||||
|
||||
// insert privkey
|
||||
gpg_io_mark();
|
||||
len = cx_aes(&keyenc,
|
||||
CX_ENCRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
|
||||
(unsigned char *) &keygpg->priv_key.rsa4096,
|
||||
sizeof(cx_rsa_4096_private_key_t),
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
GPG_IO_BUFFER_LENGTH - G_gpg_vstate.io_offset);
|
||||
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),
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
&len));
|
||||
gpg_io_inserted(len);
|
||||
gpg_io_set_offset(IO_OFFSET_MARK);
|
||||
gpg_io_insert_u32(len);
|
||||
@ -813,12 +834,13 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
||||
|
||||
// insert privkey
|
||||
gpg_io_mark();
|
||||
len = cx_aes(&keyenc,
|
||||
CX_ENCRYPT | CX_CHAIN_CBC | CX_PAD_ISO9797M2 | CX_LAST,
|
||||
(unsigned char *) &keygpg->priv_key.ecfp640,
|
||||
sizeof(cx_ecfp_640_private_key_t),
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
GPG_IO_BUFFER_LENGTH - G_gpg_vstate.io_offset);
|
||||
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.ecfp640,
|
||||
sizeof(cx_ecfp_640_private_key_t),
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
&len));
|
||||
gpg_io_inserted(len);
|
||||
gpg_io_set_offset(IO_OFFSET_MARK);
|
||||
gpg_io_insert_u32(len);
|
||||
@ -830,6 +852,8 @@ int gpg_apdu_get_key_data(unsigned int ref) {
|
||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||
}
|
||||
return SW_OK;
|
||||
end:
|
||||
THROW(error);
|
||||
}
|
||||
|
||||
// cmd TID API COMPAT len_pub len_priv priv
|
||||
@ -840,6 +864,7 @@ int gpg_apdu_put_key_data(unsigned int ref) {
|
||||
unsigned int len;
|
||||
unsigned int offset;
|
||||
gpg_init_keyenc(&keyenc);
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
switch (ref) {
|
||||
case 0xB6:
|
||||
@ -881,12 +906,13 @@ int gpg_apdu_put_key_data(unsigned int ref) {
|
||||
}
|
||||
offset = G_gpg_vstate.io_offset;
|
||||
gpg_io_discard(0);
|
||||
len = cx_aes(&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,
|
||||
GPG_IO_BUFFER_LENGTH);
|
||||
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)) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
}
|
||||
@ -915,12 +941,13 @@ int gpg_apdu_put_key_data(unsigned int ref) {
|
||||
offset = G_gpg_vstate.io_offset;
|
||||
gpg_io_discard(0);
|
||||
|
||||
len = cx_aes(&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,
|
||||
GPG_IO_BUFFER_LENGTH);
|
||||
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_ecfp_640_private_key_t)) {
|
||||
THROW(SW_WRONG_DATA);
|
||||
return SW_WRONG_DATA;
|
||||
@ -936,4 +963,6 @@ int gpg_apdu_put_key_data(unsigned int ref) {
|
||||
}
|
||||
gpg_io_discard(1);
|
||||
return SW_OK;
|
||||
end:
|
||||
THROW(error);
|
||||
}
|
||||
|
@ -18,6 +18,7 @@
|
||||
#include "gpg_types.h"
|
||||
#include "gpg_api.h"
|
||||
#include "gpg_vars.h"
|
||||
#include "cx_errors.h"
|
||||
|
||||
/* @in slot slot num [0 ; GPG_KEYS_SLOTS[
|
||||
* @out seed 32 bytes master seed for given slot
|
||||
@ -25,11 +26,17 @@
|
||||
void gpg_pso_derive_slot_seed(int slot, unsigned char *seed) {
|
||||
unsigned int path[2];
|
||||
unsigned char chain[32];
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
memset(chain, 0, 32);
|
||||
path[0] = 0x80475047;
|
||||
path[1] = slot + 1;
|
||||
os_perso_derive_node_bip32(CX_CURVE_SECP256K1, path, 2, seed, chain);
|
||||
CX_CHECK(os_derive_bip32_no_throw(CX_CURVE_SECP256K1, path, 2, seed, chain));
|
||||
|
||||
end:
|
||||
if (error != CX_OK) {
|
||||
THROW(error);
|
||||
}
|
||||
}
|
||||
|
||||
/* @in Sn master seed slot number
|
||||
@ -44,21 +51,31 @@ void gpg_pso_derive_key_seed(unsigned char *Sn,
|
||||
unsigned char *Ski,
|
||||
unsigned int Ski_len) {
|
||||
unsigned char h[32];
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
h[0] = idx >> 8;
|
||||
h[1] = idx;
|
||||
|
||||
cx_sha256_init(&G_gpg_vstate.work.md.sha256);
|
||||
cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha256, 0, Sn, 32, NULL, 0);
|
||||
cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha256, 0, (unsigned char *) key_name, 4, NULL, 0);
|
||||
cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha256, CX_LAST, h, 2, h, 32);
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha256, 0, Sn, 32, NULL, 0));
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha256,
|
||||
0,
|
||||
(unsigned char *) key_name,
|
||||
4,
|
||||
NULL,
|
||||
0));
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha256, CX_LAST, h, 2, h, 32));
|
||||
#ifdef GPG_SHAKE256
|
||||
cx_shake256_init(&G_gpg_vstate.work.md.sha3, Ski_len);
|
||||
cx_sha3_update(&G_gpg_vstate.work.md.sha3, h, 32);
|
||||
cx_sha3_final(&G_gpg_vstate.work.md.sha3, Ski);
|
||||
CX_CHECK(cx_shake256_init_no_throw(&G_gpg_vstate.work.md.sha3, Ski_len));
|
||||
CX_CHECK(cx_sha3_update(&G_gpg_vstate.work.md.sha3, h, 32));
|
||||
CX_CHECK(cx_sha3_final(&G_gpg_vstate.work.md.sha3, Ski));
|
||||
#else
|
||||
cx_sha3_xof_init(&G_gpg_vstate.work.md.sha3, 256, Ski_len);
|
||||
cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha3, CX_LAST, h, 32, Ski, Ski_len);
|
||||
CX_CHECK(cx_sha3_xof_init_no_throw(&G_gpg_vstate.work.md.sha3, 256, Ski_len));
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha3, CX_LAST, h, 32, Ski, Ski_len));
|
||||
#endif
|
||||
end:
|
||||
if (error != CX_OK) {
|
||||
THROW(error);
|
||||
}
|
||||
}
|
||||
|
||||
/* assume command is fully received */
|
||||
@ -67,6 +84,7 @@ int gpg_apdu_gen() {
|
||||
gpg_key_t *keygpg;
|
||||
unsigned char seed[66];
|
||||
unsigned char *name;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
switch ((G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2) {
|
||||
case 0x8000:
|
||||
@ -147,16 +165,17 @@ int gpg_apdu_gen() {
|
||||
gpg_pso_derive_key_seed(seed, name, 2, pq + size, size);
|
||||
*pq |= 0x80;
|
||||
*(pq + size) |= 0x80;
|
||||
cx_math_next_prime(pq, size);
|
||||
cx_math_next_prime(pq + size, size);
|
||||
CX_CHECK(cx_math_next_prime_no_throw(pq, size));
|
||||
CX_CHECK(cx_math_next_prime_no_throw(pq + size, size));
|
||||
}
|
||||
|
||||
cx_rsa_generate_pair(ksz,
|
||||
rsa_pub,
|
||||
rsa_priv,
|
||||
(const unsigned char *) N_gpg_pstate->default_RSA_exponent,
|
||||
4,
|
||||
pq);
|
||||
CX_CHECK(cx_rsa_generate_pair_no_throw(
|
||||
ksz,
|
||||
rsa_pub,
|
||||
rsa_priv,
|
||||
(const unsigned char *) N_gpg_pstate->default_RSA_exponent,
|
||||
4,
|
||||
pq));
|
||||
|
||||
nvm_write(pkey, rsa_priv, pkey_size);
|
||||
nvm_write(&keygpg->pub_key.rsa[0], rsa_pub->e, 4);
|
||||
@ -182,14 +201,17 @@ int gpg_apdu_gen() {
|
||||
ksz = gpg_curve2domainlen(curve);
|
||||
gpg_pso_derive_slot_seed(G_gpg_vstate.slot, seed);
|
||||
gpg_pso_derive_key_seed(seed, name, 1, seed, ksz);
|
||||
cx_ecfp_init_private_key(curve, seed, ksz, &G_gpg_vstate.work.ecfp.private);
|
||||
CX_CHECK(cx_ecfp_init_private_key_no_throw(curve,
|
||||
seed,
|
||||
ksz,
|
||||
&G_gpg_vstate.work.ecfp.private));
|
||||
keepprivate = 1;
|
||||
}
|
||||
|
||||
cx_ecfp_generate_pair(curve,
|
||||
&G_gpg_vstate.work.ecfp.public,
|
||||
&G_gpg_vstate.work.ecfp.private,
|
||||
keepprivate);
|
||||
CX_CHECK(cx_ecfp_generate_pair_no_throw(curve,
|
||||
&G_gpg_vstate.work.ecfp.public,
|
||||
&G_gpg_vstate.work.ecfp.private,
|
||||
keepprivate));
|
||||
nvm_write(&keygpg->priv_key.ecfp,
|
||||
&G_gpg_vstate.work.ecfp.private,
|
||||
sizeof(cx_ecfp_private_key_t));
|
||||
@ -272,9 +294,9 @@ int gpg_apdu_gen() {
|
||||
memmove(G_gpg_vstate.work.io_buffer + 128,
|
||||
keygpg->pub_key.ecfp256.W,
|
||||
keygpg->pub_key.ecfp256.W_len);
|
||||
cx_edward_compress_point(CX_CURVE_Ed25519,
|
||||
G_gpg_vstate.work.io_buffer + 128,
|
||||
65);
|
||||
CX_CHECK(cx_edwards_compress_point_no_throw(CX_CURVE_Ed25519,
|
||||
G_gpg_vstate.work.io_buffer + 128,
|
||||
65));
|
||||
gpg_io_insert_tlv(0x86,
|
||||
32,
|
||||
G_gpg_vstate.work.io_buffer + 129); // 129: discard 02
|
||||
@ -301,4 +323,6 @@ int gpg_apdu_gen() {
|
||||
|
||||
THROW(SW_WRONG_DATA);
|
||||
return SW_WRONG_DATA;
|
||||
end:
|
||||
THROW(error);
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ static int gpg_pin_get_state_index(unsigned int pinref) {
|
||||
|
||||
static int gpg_pin_check_internal(gpg_pin_t *pin, unsigned char *pin_val, int pin_len) {
|
||||
unsigned int counter;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
if (pin->counter == 0) {
|
||||
return SW_PIN_BLOCKED;
|
||||
@ -58,12 +59,12 @@ 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));
|
||||
cx_sha256_init(&G_gpg_vstate.work.md.sha256);
|
||||
cx_hash((cx_hash_t *) &G_gpg_vstate.work.md.sha256,
|
||||
CX_LAST,
|
||||
pin_val,
|
||||
pin_len,
|
||||
G_gpg_vstate.work.md.H,
|
||||
sizeof(G_gpg_vstate.work.md.H));
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &G_gpg_vstate.work.md.sha256,
|
||||
CX_LAST,
|
||||
pin_val,
|
||||
pin_len,
|
||||
G_gpg_vstate.work.md.H,
|
||||
sizeof(G_gpg_vstate.work.md.H)));
|
||||
if (memcmp(G_gpg_vstate.work.md.H, pin->value, 32)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED;
|
||||
}
|
||||
@ -71,6 +72,11 @@ 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));
|
||||
return SW_OK;
|
||||
end:
|
||||
if (error != CX_OK) {
|
||||
THROW(error);
|
||||
}
|
||||
return SW_UNKNOWN;
|
||||
}
|
||||
|
||||
static void gpg_pin_check_throw(gpg_pin_t *pin, int pinID, unsigned char *pin_val, int pin_len) {
|
||||
@ -97,15 +103,19 @@ int gpg_pin_check(gpg_pin_t *pin, int pinID, unsigned char *pin_val, unsigned in
|
||||
|
||||
void gpg_pin_set(gpg_pin_t *pin, unsigned char *pin_val, unsigned int pin_len) {
|
||||
cx_sha256_t sha256;
|
||||
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
gpg_pin_t newpin;
|
||||
|
||||
cx_sha256_init(&sha256);
|
||||
cx_hash((cx_hash_t *) &sha256, CX_LAST, pin_val, pin_len, newpin.value, 32);
|
||||
CX_CHECK(cx_hash_no_throw((cx_hash_t *) &sha256, CX_LAST, pin_val, pin_len, newpin.value, 32));
|
||||
newpin.length = pin_len;
|
||||
newpin.counter = 3;
|
||||
|
||||
gpg_nvm_write(pin, &newpin, sizeof(gpg_pin_t));
|
||||
end:
|
||||
if (error != CX_OK) {
|
||||
THROW(error);
|
||||
}
|
||||
}
|
||||
|
||||
int gpg_pin_set_verified(int pinID, int verified) {
|
||||
|
132
src/gpg_pso.c
132
src/gpg_pso.c
@ -19,6 +19,7 @@
|
||||
#include "gpg_api.h"
|
||||
#include "gpg_vars.h"
|
||||
#include "gpg_ux_nanos.h"
|
||||
#include "cx_errors.h"
|
||||
|
||||
const unsigned char gpg_oid_sha256[] = {0x30,
|
||||
0x31,
|
||||
@ -67,6 +68,7 @@ static void gpg_pso_reset_PW1() {
|
||||
|
||||
static int gpg_sign(gpg_key_t *sigkey) {
|
||||
// --- RSA
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
if (sigkey->attributes.value[0] == 1) {
|
||||
cx_rsa_private_key_t *key;
|
||||
unsigned int ksz, l;
|
||||
@ -106,13 +108,13 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
||||
G_gpg_vstate.work.io_buffer[0] = 0;
|
||||
G_gpg_vstate.work.io_buffer[1] = 1;
|
||||
G_gpg_vstate.work.io_buffer[l - 1] = 0;
|
||||
ksz = cx_rsa_decrypt(key,
|
||||
CX_PAD_NONE,
|
||||
CX_NONE,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
ksz,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
ksz);
|
||||
CX_CHECK(cx_rsa_decrypt_no_throw(key,
|
||||
CX_PAD_NONE,
|
||||
CX_NONE,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
ksz,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
&ksz));
|
||||
// send
|
||||
gpg_io_discard(0);
|
||||
gpg_io_inserted(ksz);
|
||||
@ -122,7 +124,8 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
||||
// --- ECDSA/EdDSA
|
||||
if ((sigkey->attributes.value[0] == 19) || (sigkey->attributes.value[0] == 22)) {
|
||||
cx_ecfp_private_key_t *key;
|
||||
unsigned int sz, i, rs_len, info;
|
||||
size_t sz;
|
||||
unsigned int s_len, i, rs_len, info;
|
||||
unsigned char *rs;
|
||||
|
||||
key = &sigkey->priv_key.ecfp;
|
||||
@ -135,15 +138,16 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
||||
THROW(SW_CONDITIONS_NOT_SATISFIED);
|
||||
return SW_CONDITIONS_NOT_SATISFIED;
|
||||
}
|
||||
sz = cx_ecdsa_sign(key,
|
||||
CX_RND_TRNG,
|
||||
CX_NONE,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
sz,
|
||||
RS,
|
||||
256,
|
||||
&info);
|
||||
// reencode r,s in MPI format
|
||||
s_len = 256;
|
||||
CX_CHECK(cx_ecdsa_sign_no_throw(key,
|
||||
CX_RND_TRNG,
|
||||
CX_NONE,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
sz,
|
||||
RS,
|
||||
&s_len,
|
||||
&info));
|
||||
// re-encode r,s in MPI format
|
||||
gpg_io_discard(0);
|
||||
|
||||
rs_len = RS[3];
|
||||
@ -161,16 +165,15 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
||||
rs += 2;
|
||||
}
|
||||
} else {
|
||||
sz = cx_eddsa_sign(key,
|
||||
CX_NONE,
|
||||
CX_SHA512,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
G_gpg_vstate.io_length,
|
||||
NULL,
|
||||
0,
|
||||
RS,
|
||||
256,
|
||||
NULL);
|
||||
sz = 256;
|
||||
CX_CHECK(cx_eddsa_sign_no_throw(key,
|
||||
CX_SHA512,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
G_gpg_vstate.io_length,
|
||||
RS,
|
||||
sz));
|
||||
CX_CHECK(cx_ecdomain_parameters_length(key->curve, &sz));
|
||||
sz *= 2;
|
||||
gpg_io_discard(0);
|
||||
gpg_io_insert(RS, sz);
|
||||
}
|
||||
@ -183,6 +186,8 @@ static int gpg_sign(gpg_key_t *sigkey) {
|
||||
// --- PSO:CDS NOT SUPPORTED
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||
end:
|
||||
THROW(error);
|
||||
}
|
||||
|
||||
int gpg_apdu_pso() {
|
||||
@ -190,6 +195,7 @@ int gpg_apdu_pso() {
|
||||
|
||||
unsigned int pso;
|
||||
unsigned int sz;
|
||||
cx_err_t error = CX_INTERNAL_ERROR;
|
||||
|
||||
pso = (G_gpg_vstate.io_p1 << 8) | G_gpg_vstate.io_p2;
|
||||
|
||||
@ -239,12 +245,13 @@ int gpg_apdu_pso() {
|
||||
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,
|
||||
GPG_IO_BUFFER_LENGTH - 1);
|
||||
sz = GPG_IO_BUFFER_LENGTH - 1;
|
||||
CX_CHECK(cx_aes_no_throw(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,
|
||||
&sz));
|
||||
// send
|
||||
gpg_io_discard(0);
|
||||
G_gpg_vstate.work.io_buffer[0] = 0x02;
|
||||
@ -290,13 +297,15 @@ int gpg_apdu_pso() {
|
||||
return SW_CONDITIONS_NOT_SATISFIED;
|
||||
}
|
||||
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
|
||||
sz = cx_rsa_decrypt(key,
|
||||
CX_PAD_PKCS1_1o5,
|
||||
CX_NONE,
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
msg_len,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
ksz);
|
||||
sz = ksz;
|
||||
CX_CHECK(cx_rsa_decrypt_no_throw(
|
||||
key,
|
||||
CX_PAD_PKCS1_1o5,
|
||||
CX_NONE,
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
msg_len,
|
||||
G_gpg_vstate.work.io_buffer,
|
||||
&sz));
|
||||
// send
|
||||
gpg_io_discard(0);
|
||||
gpg_io_inserted(sz);
|
||||
@ -312,12 +321,13 @@ int gpg_apdu_pso() {
|
||||
return SW_CONDITIONS_NOT_SATISFIED;
|
||||
}
|
||||
msg_len = G_gpg_vstate.io_length - G_gpg_vstate.io_offset;
|
||||
sz = cx_aes(key,
|
||||
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,
|
||||
GPG_IO_BUFFER_LENGTH);
|
||||
sz = GPG_IO_BUFFER_LENGTH;
|
||||
CX_CHECK(cx_aes_no_throw(key,
|
||||
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,
|
||||
&sz));
|
||||
// send
|
||||
gpg_io_discard(0);
|
||||
gpg_io_inserted(sz);
|
||||
@ -360,24 +370,28 @@ int gpg_apdu_pso() {
|
||||
(G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset)[31 - i];
|
||||
}
|
||||
G_gpg_vstate.work.io_buffer[511] = 0x02;
|
||||
sz = cx_ecdh(key,
|
||||
CX_ECDH_X,
|
||||
G_gpg_vstate.work.io_buffer + 511,
|
||||
65,
|
||||
G_gpg_vstate.work.io_buffer + 256,
|
||||
160);
|
||||
CX_CHECK(cx_ecdh_no_throw(key,
|
||||
CX_ECDH_X,
|
||||
G_gpg_vstate.work.io_buffer + 511,
|
||||
65,
|
||||
G_gpg_vstate.work.io_buffer + 256,
|
||||
160));
|
||||
CX_CHECK(cx_ecdomain_parameters_length(key->curve, &sz));
|
||||
|
||||
for (i = 0; i <= 31; i++) {
|
||||
G_gpg_vstate.work.io_buffer[128 + i] =
|
||||
G_gpg_vstate.work.io_buffer[287 - i];
|
||||
}
|
||||
sz = 32;
|
||||
} else {
|
||||
sz = cx_ecdh(key,
|
||||
CX_ECDH_X,
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
65,
|
||||
G_gpg_vstate.work.io_buffer + 128,
|
||||
160);
|
||||
CX_CHECK(
|
||||
cx_ecdh_no_throw(key,
|
||||
CX_ECDH_X,
|
||||
G_gpg_vstate.work.io_buffer + G_gpg_vstate.io_offset,
|
||||
65,
|
||||
G_gpg_vstate.work.io_buffer + 128,
|
||||
160));
|
||||
CX_CHECK(cx_ecdomain_parameters_length(key->curve, &sz));
|
||||
}
|
||||
// send
|
||||
gpg_io_discard(0);
|
||||
@ -399,6 +413,8 @@ int gpg_apdu_pso() {
|
||||
}
|
||||
THROW(SW_REFERENCED_DATA_NOT_FOUND);
|
||||
return SW_REFERENCED_DATA_NOT_FOUND;
|
||||
end:
|
||||
THROW(error);
|
||||
}
|
||||
|
||||
int gpg_apdu_internal_authenticate() {
|
||||
|
Loading…
Reference in New Issue
Block a user