|
|
|
|
@@ -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}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|