7 Commits
v1.2 ... v1.4

Author SHA1 Message Date
Pol Henarejos
1491b9d36d Upgrading version to 1.4.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-05-09 18:56:14 +02:00
Pol Henarejos
74aa99afa6 Adding Manage Security Environment (INS 22).
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-05-09 18:54:36 +02:00
Pol Henarejos
c68fe30077 Enabling KDF.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-05-06 19:44:27 +02:00
Pol Henarejos
21284a9375 When a DO is not found, it should return REFERENCE_NOT_FOUND instead of FILE_NOT_FOUND, which reserved for selecting applet.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-05-06 19:13:26 +02:00
Pol Henarejos
151f6d134e Adding UIF DO (D6, D7 and D8).
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-05-05 22:35:17 +02:00
Pol Henarejos
d95d19a85b Adding press-to-confirm when loading a private key.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-05-05 20:55:41 +02:00
Pol Henarejos
4e2f3ce38d Upgrading pico-ccid.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2022-05-05 20:11:56 +02:00
6 changed files with 136 additions and 43 deletions

View File

@@ -1 +1 @@
Version=1.2
Version=1.4

View File

@@ -1,7 +1,7 @@
#!/bin/bash
VERSION_MAJOR="1"
VERSION_MINOR="2"
VERSION_MINOR="4"
rm -rf release/*
cd build_release

View File

@@ -54,7 +54,7 @@ uint8_t historical_bytes[] = {
uint8_t extended_capabilities[] = {
10, 0,
0x76, /*
0x77, /*
* No Secure Messaging supported
* GET CHALLENGE supported
* Key import supported
@@ -62,7 +62,7 @@ uint8_t extended_capabilities[] = {
* No private_use_DO
* Algorithm attrs are changable
* ENC/DEC with AES
* No KDF-DO available
* KDF-DO available
*/
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
0x00, 128, /* Max size of GET CHALLENGE */
@@ -137,9 +137,10 @@ file_t file_entries[] = {
/* 50 */ { .fid = EF_PB_AUT, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 51 */ { .fid = EF_PW_PRIV, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 52 */ { .fid = EF_DEK, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
/* 53 */ { .fid = EF_KDF, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
/* 53 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 54 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = ACL_NONE } //end
/* 54 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
/* 55 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = ACL_NONE } //end
};
const file_t *MF = &file_entries[0];

View File

@@ -67,6 +67,7 @@
#define EF_UIF_DEC 0x00d7 //S
#define EF_UIF_AUT 0x00d8 //S
#define EF_KEY_INFO 0x00de //S
#define EF_KDF 0x00f9 //C
#define EF_ALGO_INFO 0x00fa //C
#define EF_LANG_PREF 0x5f2d //S
#define EF_SEX 0x5f35 //S

View File

@@ -33,6 +33,7 @@ bool has_pw3 = false;
uint8_t session_pw1[32];
uint8_t session_pw3[32];
static uint8_t dek[IV_SIZE+32];
static uint16_t algo_dec = EF_ALGO_PRIV2, algo_aut = EF_ALGO_PRIV3, pk_dec = EF_PK_DEC, pk_aut = EF_PK_AUT;
uint8_t openpgp_aid[] = {
6,
@@ -52,6 +53,22 @@ char atr_openpgp[] = {
int openpgp_process_apdu();
extern uint32_t board_button_read(void);
static bool wait_button(uint16_t fid) {
file_t *ef = search_by_fid(fid, NULL, SPECIFY_ANY);
uint32_t val = EV_PRESS_BUTTON;
if (ef && ef->data && file_read_uint8(ef->data+2) > 0) {
queue_try_add(ccid_comm, &val);
do {
queue_remove_blocking(card_comm, &val);
}
while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT);
}
return val == EV_BUTTON_TIMEOUT;
}
void select_file(file_t *pe) {
if (!pe)
{
@@ -88,27 +105,27 @@ static int cmd_select() {
}
else if (apdu.cmd_apdu_data_len == 2) {
if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) {
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
}
}
}
else if (p1 == 0x01) { //Select child DF - DF identifier
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) {
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
}
}
else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) {
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
}
}
else if (p1 == 0x03) { //Select parent DF of the current DF - Absent
if (apdu.cmd_apdu_data_len != 0)
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
}
else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
if (!(pe = search_by_name(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len))) {
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
}
if (card_terminated) {
return set_res_sw (0x62, 0x85);
@@ -116,12 +133,12 @@ static int cmd_select() {
}
else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
if (!(pe = search_by_path(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, MF))) {
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
}
}
else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
if (!(pe = search_by_path(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, currentDF))) {
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
}
}
}
@@ -208,6 +225,34 @@ void scan_files() {
flash_write_data_to_file(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_UIF_SIG, NULL, SPECIFY_ANY))) {
if (!ef->data) {
TU_LOG1("UIF SIG is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x0, 0x20 };
flash_write_data_to_file(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_UIF_DEC, NULL, SPECIFY_ANY))) {
if (!ef->data) {
TU_LOG1("UIF DEC is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x0, 0x20 };
flash_write_data_to_file(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_UIF_AUT, NULL, SPECIFY_ANY))) {
if (!ef->data) {
TU_LOG1("UIF AUT is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x0, 0x20 };
flash_write_data_to_file(ef, def, sizeof(def));
}
}
if ((ef = search_by_fid(EF_KDF, NULL, SPECIFY_ANY))) {
if (!ef->data) {
TU_LOG1("KDF is empty. Initializing to default\r\n");
const uint8_t def[] = { 0x81, 0x1, 0x0 };
flash_write_data_to_file(ef, def, sizeof(def));
}
}
low_flash_available();
}
@@ -257,6 +302,10 @@ int dek_decrypt(uint8_t *data, size_t len) {
void init_openpgp() {
isUserAuthenticated = false;
has_pw1 = has_pw3 = false;
algo_dec = EF_ALGO_PRIV2;
algo_aut = EF_ALGO_PRIV3;
pk_dec = EF_PK_DEC;
pk_aut = EF_PK_AUT;
scan_files();
//cmd_select();
}
@@ -264,6 +313,10 @@ void init_openpgp() {
int openpgp_unload() {
isUserAuthenticated = false;
has_pw1 = has_pw3 = false;
algo_dec = EF_ALGO_PRIV2;
algo_aut = EF_ALGO_PRIV3;
pk_dec = EF_PK_DEC;
pk_aut = EF_PK_AUT;
return CCID_OK;
}
@@ -298,7 +351,7 @@ int parse_do(uint16_t *fids, int mode) {
else
data_len = 0;
if (mode == 1) {
if (fids[0] > 1) {
if (fids[0] > 1 && res_APDU_size > 0) {
if (fids[i+1] < 0x0100) {
res_APDU[res_APDU_size++] = fids[i+1] & 0xff;
}
@@ -670,8 +723,8 @@ int parse_app_data(const file_t *f, int mode) {
int parse_discrete_do(const file_t *f, int mode) {
uint16_t fids[] = {
8,
EF_EXT_CAP, EF_ALGO_SIG, EF_ALGO_DEC, EF_ALGO_AUT, EF_PW_STATUS, EF_FP, EF_CA_FP, EF_TS_ALL, //EF_UIF_SIG, EF_UIF_DEC, EF_UIF_AUT
11,
EF_EXT_CAP, EF_ALGO_SIG, EF_ALGO_DEC, EF_ALGO_AUT, EF_PW_STATUS, EF_FP, EF_CA_FP, EF_TS_ALL, EF_UIF_SIG, EF_UIF_DEC, EF_UIF_AUT
};
res_APDU[res_APDU_size++] = EF_DISCRETE_DO & 0xff;
res_APDU[res_APDU_size++] = 0x82;
@@ -690,7 +743,7 @@ static int cmd_get_data() {
uint16_t fid = (P1(apdu) << 8) | P2(apdu);
file_t *ef;
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF)))
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
if (!authenticate_action(ef, ACL_OP_READ_SEARCH)) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
@@ -828,7 +881,7 @@ static int cmd_put_data() {
else if (fid == EF_ALGO_SIG || fid == EF_ALGO_DEC || fid == EF_ALGO_AUT)
fid |= 0x1000;
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF)))
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
@@ -950,12 +1003,11 @@ int store_keys(void *key_ctx, int type, uint16_t key_id) {
}
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
//wait_button();
int key_size = file_read_uint16(fkey->data);
uint8_t kdata[4096/8];
memcpy(kdata, file_read(fkey->data+2), key_size);
if (dek_decrypt(kdata, key_size) != 0) {
return SW_EXEC_ERROR();
return CCID_EXEC_ERROR;
}
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size/2) != 0) {
mbedtls_rsa_free(ctx);
@@ -985,12 +1037,11 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
}
int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
//wait_button();
int key_size = file_read_uint16(fkey->data);
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
memcpy(kdata, file_read(fkey->data+2), key_size);
if (dek_decrypt(kdata, key_size) != 0) {
return SW_EXEC_ERROR();
return CCID_EXEC_ERROR;
}
mbedtls_ecp_group_id gid = kdata[0];
int r = mbedtls_ecp_read_key(gid, ctx, kdata+1, key_size-1);
@@ -1070,7 +1121,7 @@ static int cmd_keypair_gen() {
file_t *algo_ef = search_by_fid(fid-0x0010, NULL, SPECIFY_EF);
if (!algo_ef)
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
const uint8_t *algo = algorithm_attr_rsa2k+1;
uint16_t algo_len = algorithm_attr_rsa2k[0];
if (algo_ef && algo_ef->data) {
@@ -1087,13 +1138,11 @@ static int cmd_keypair_gen() {
mbedtls_rsa_init(&rsa);
uint8_t index = 0;
r = mbedtls_rsa_gen_key(&rsa, random_gen, &index, nlen, exponent);
printf("r %d\r\n",r);
if (r != 0) {
mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR();
}
r = store_keys(&rsa, ALGO_RSA, fid);
printf("r %d\r\n",r);
make_rsa_response(&rsa);
mbedtls_rsa_free(&rsa);
if (r != CCID_OK)
@@ -1122,7 +1171,7 @@ static int cmd_keypair_gen() {
return SW_FUNC_NOT_SUPPORTED();
file_t *pbef = search_by_fid(fid+3, NULL, SPECIFY_EF);
if (!pbef)
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
r = flash_write_data_to_file(pbef, res_APDU, res_APDU_size);
if (r != CCID_OK)
return SW_EXEC_ERROR();
@@ -1134,7 +1183,7 @@ static int cmd_keypair_gen() {
else if (P1(apdu) == 0x81) { //read
file_t *ef = search_by_fid(fid+3, NULL, SPECIFY_EF);
if (!ef || !ef->data)
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
res_APDU_size = file_read_uint16(ef->data);
memcpy(res_APDU, file_read(ef->data+2), res_APDU_size);
return SW_OK();
@@ -1235,14 +1284,14 @@ static int cmd_pso() {
else if (P1(apdu) == 0x80 && P2(apdu) == 0x86) {
if (!has_pw3 && !has_pw2)
return SW_SECURITY_STATUS_NOT_SATISFIED();
algo_fid = EF_ALGO_PRIV2;
pk_fid = EF_PK_DEC;
algo_fid = algo_dec;
pk_fid = pk_dec;
}
else
return SW_INCORRECT_P1P2();
file_t *algo_ef = search_by_fid(algo_fid, NULL, SPECIFY_EF);
if (!algo_ef)
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
const uint8_t *algo = algorithm_attr_rsa2k+1;
uint16_t algo_len = algorithm_attr_rsa2k[0];
if (algo_ef && algo_ef->data) {
@@ -1251,15 +1300,19 @@ static int cmd_pso() {
}
file_t *ef = search_by_fid(pk_fid, NULL, SPECIFY_EF);
if (!ef)
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
if (wait_button(pk_fid == EF_PK_SIG ? EF_UIF_SIG : EF_UIF_DEC) == true)
return SW_SECURE_MESSAGE_EXEC_ERROR();
int r = CCID_OK;
int key_size = file_read_uint16(ef->data);
if (algo[0] == ALGO_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef);
if (r != CCID_OK)
if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
size_t olen = 0;
r = rsa_sign(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, res_APDU, &olen);
@@ -1286,8 +1339,10 @@ static int cmd_pso() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef);
if (r != CCID_OK)
return SW_CONDITIONS_NOT_SATISFIED();
if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
size_t olen = 0;
r = ecdsa_sign(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, res_APDU, &olen);
mbedtls_ecdsa_free(&ctx);
@@ -1307,7 +1362,7 @@ static int cmd_pso() {
if (mbedtls_asn1_get_tag(&data, end, &len, 0x49) != 0 || mbedtls_asn1_get_tag(&data, end, &len, 0x86) != 0)
return SW_WRONG_DATA();
if (len != 2*key_size-1)
return SW_WRONG_LENGTH();
return SW_WRONG_LENGTH();
memcpy(kdata, file_read(ef->data+2), key_size);
if (dek_decrypt(kdata, key_size) != 0) {
return SW_EXEC_ERROR();
@@ -1375,25 +1430,29 @@ static int cmd_internal_aut() {
return SW_WRONG_P1P2();
if (!has_pw3 && !has_pw2)
return SW_SECURITY_STATUS_NOT_SATISFIED();
file_t *algo_ef = search_by_fid(EF_ALGO_PRIV3, NULL, SPECIFY_EF);
file_t *algo_ef = search_by_fid(algo_aut, NULL, SPECIFY_EF);
if (!algo_ef)
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
const uint8_t *algo = algorithm_attr_rsa2k+1;
uint16_t algo_len = algorithm_attr_rsa2k[0];
if (algo_ef && algo_ef->data) {
algo_len = file_read_uint16(algo_ef->data);
algo = file_read(algo_ef->data+2);
}
file_t *ef = search_by_fid(EF_PK_AUT, NULL, SPECIFY_EF);
file_t *ef = search_by_fid(pk_aut, NULL, SPECIFY_EF);
if (!ef)
return SW_FILE_NOT_FOUND();
return SW_REFERENCE_NOT_FOUND();
if (wait_button(EF_UIF_AUT) == true)
return SW_SECURE_MESSAGE_EXEC_ERROR();
int r = CCID_OK;
if (algo[0] == ALGO_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef);
if (r != CCID_OK)
if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
size_t olen = 0;
r = rsa_sign(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, res_APDU, &olen);
mbedtls_rsa_free(&ctx);
@@ -1405,8 +1464,10 @@ static int cmd_internal_aut() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef);
if (r != CCID_OK)
return SW_CONDITIONS_NOT_SATISFIED();
if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
size_t olen = 0;
r = ecdsa_sign(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, res_APDU, &olen);
mbedtls_ecdsa_free(&ctx);
@@ -1417,6 +1478,34 @@ static int cmd_internal_aut() {
return SW_OK();
}
static int cmd_mse() {
if (P1(apdu) != 0x41 || (P2(apdu) != 0xA4 && P2(apdu) != 0xB8))
return SW_WRONG_P1P2();
if (apdu.cmd_apdu_data[0] != 0x83 || apdu.cmd_apdu_data[1] != 0x1 || (apdu.cmd_apdu_data[2] != 0x2 && apdu.cmd_apdu_data[2] != 0x3))
return SW_WRONG_DATA();
if (P2(apdu) == 0xA4) {
if (apdu.cmd_apdu_data[2] == 0x2) {
algo_dec = EF_ALGO_PRIV2;
pk_dec = EF_PK_DEC;
}
else if (apdu.cmd_apdu_data[2] == 0x3) {
algo_dec = EF_ALGO_PRIV3;
pk_dec = EF_PK_AUT;
}
}
else if (P2(apdu) == 0xB8) {
if (apdu.cmd_apdu_data[2] == 0x2) {
algo_aut = EF_ALGO_PRIV2;
pk_aut = EF_PK_DEC;
}
else if (apdu.cmd_apdu_data[2] == 0x3) {
algo_aut = EF_ALGO_PRIV3;
pk_aut = EF_PK_AUT;
}
}
return SW_OK();
}
typedef struct cmd
{
uint8_t ins;
@@ -1424,6 +1513,7 @@ typedef struct cmd
} cmd_t;
#define INS_VERIFY 0x20
#define INS_MSE 0x22
#define INS_CHANGE_PIN 0x24
#define INS_PSO 0x2A
#define INS_RESET_RETRY 0x2C
@@ -1449,6 +1539,7 @@ static const cmd_t cmds[] = {
{ INS_ACTIVATE_FILE, cmd_activate_file },
{ INS_CHALLENGE, cmd_challenge },
{ INS_INTERNAL_AUT, cmd_internal_aut },
{ INS_MSE, cmd_mse },
{ 0x00, 0x0}
};