From a2d1c5cf22e6537f8e8a6902af57c302dd1cbb0e Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 12 May 2022 23:49:26 +0200 Subject: [PATCH] Adding key import. Signed-off-by: Pol Henarejos --- src/openpgp/openpgp.c | 125 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 123 insertions(+), 2 deletions(-) diff --git a/src/openpgp/openpgp.c b/src/openpgp/openpgp.c index 5428f3d..4128593 100644 --- a/src/openpgp/openpgp.c +++ b/src/openpgp/openpgp.c @@ -547,7 +547,7 @@ static const uint8_t algorithm_attr_x448[] = { static const uint8_t algorithm_attr_rsa1k[] = { 6, ALGO_RSA, - 0x04, 0x00, /* Length modulus (in bit): 2048 */ + 0x04, 0x00, /* Length modulus (in bit): 1024 */ 0x00, 0x20, /* Length exponent (in bit): 32 */ 0x00 /* 0: Acceptable format is: P and Q */ }; @@ -563,7 +563,7 @@ static const uint8_t algorithm_attr_rsa2k[] = { static const uint8_t algorithm_attr_rsa3k[] = { 6, ALGO_RSA, - 0x0C, 0x00, /* Length modulus (in bit): 2048 */ + 0x0C, 0x00, /* Length modulus (in bit): 3072 */ 0x00, 0x20, /* Length exponent (in bit): 32 */ 0x00 /* 0: Acceptable format is: P and Q */ }; @@ -1506,6 +1506,125 @@ static int cmd_mse() { return SW_OK(); } +static int cmd_import_data() { + file_t *ef = NULL; + uint16_t fid = 0x0; + if (P1(apdu) != 0x3F || P2(apdu) != 0xFF) + return SW_WRONG_P1P2(); + if (apdu.cmd_apdu_data_len < 5) + return SW_WRONG_LENGTH(); + if (apdu.cmd_apdu_data[0] != 0x4D || (apdu.cmd_apdu_data[2] != 0xB6 && apdu.cmd_apdu_data[2] != 0xB8 && apdu.cmd_apdu_data[2] != 0xA4)) + return SW_WRONG_DATA(); + if (apdu.cmd_apdu_data[2] == 0xB6) + fid = EF_PK_SIG; + else if (apdu.cmd_apdu_data[2] != 0xB8) + fid = EF_PK_DEC; + else if (apdu.cmd_apdu_data[2] != 0xA4) + fid = EF_PK_AUT; + else + return SW_WRONG_DATA(); + if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) + return SW_REFERENCE_NOT_FOUND(); + if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) { + return SW_SECURITY_STATUS_NOT_SATISFIED(); + } + + uint8_t *start = apdu.cmd_apdu_data + 4 + apdu.cmd_apdu_data[3]; + if (*start++ != 0x7F || *start++ != 0x48) + return SW_WRONG_DATA(); + uint8_t tag_len = *start++, *end = start+tag_len, len[9] = {0}, *p[9] = {NULL}; + while (start < end) { + uint8_t tag = *start++; + if ((tag >= 0x91 && tag <= 0x97) || tag == 0x99) { + len[tag-0x91] = *start++; + } + else + return SW_WRONG_DATA(); + } + if (*start++ != 0x5F || *start++ != 0x48) + return SW_WRONG_DATA(); + tag_len = *start++; + end = start+tag_len; + for (int t = 0; start < end; t++) { + if (len[t] > 0) { + p[t] = start; + start += len[t]; + } + } + + file_t *algo_ef = search_by_fid(fid-0x0010, NULL, SPECIFY_EF); + if (!algo_ef) + 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 = file_read(algo_ef->data+2); + algo_len = file_read_uint16(algo_ef->data); + } + int r = 0; + if (algo[0] == ALGO_RSA) { + mbedtls_rsa_context rsa; + if (p[0] == NULL || len[0] == 0 || p[1] == NULL || len[1] == 0 || p[2] == NULL || len[2] == 0) + return SW_WRONG_DATA(); + mbedtls_rsa_init(&rsa); + r = mbedtls_mpi_read_binary(&rsa.E, p[0], len[0]); + if (r != 0) { + mbedtls_rsa_free(&rsa); + return SW_EXEC_ERROR(); + } + r = mbedtls_mpi_read_binary(&rsa.P, p[1], len[1]); + if (r != 0) { + mbedtls_rsa_free(&rsa); + return SW_EXEC_ERROR(); + } + r = mbedtls_mpi_read_binary(&rsa.Q, p[2], len[2]); + if (r != 0) { + mbedtls_rsa_free(&rsa); + return SW_EXEC_ERROR(); + } + r = mbedtls_rsa_import(&rsa, NULL, &rsa.P, &rsa.Q, NULL, &rsa.E); + if (r != 0) { + mbedtls_rsa_free(&rsa); + return SW_EXEC_ERROR(); + } + r = mbedtls_rsa_complete(&rsa); + if (r != 0) { + mbedtls_rsa_free(&rsa); + return SW_EXEC_ERROR(); + } + r = mbedtls_rsa_check_privkey(&rsa); + if (r != 0) { + mbedtls_rsa_free(&rsa); + return SW_EXEC_ERROR(); + } + r = store_keys(&rsa, ALGO_RSA, fid); + mbedtls_rsa_free(&rsa); + if (r != CCID_OK) + return SW_EXEC_ERROR(); + } + else if (algo[0] == ALGO_ECDSA || algo[0] == ALGO_ECDH) { + mbedtls_ecdsa_context ecdsa; + if (p[1] == NULL || len[1] == 0) + return SW_WRONG_DATA(); + mbedtls_ecp_group_id gid = get_ec_group_id_from_attr(algo+1, algo_len-1); + if (gid == MBEDTLS_ECP_DP_NONE) + return SW_FUNC_NOT_SUPPORTED(); + mbedtls_ecdsa_init(&ecdsa); + r = mbedtls_ecp_read_key(gid, &ecdsa, p[1], len[1]); + if (r != 0) { + mbedtls_ecdsa_free(&ecdsa); + return SW_EXEC_ERROR(); + } + r = store_keys(&ecdsa, ALGO_ECDSA, fid); + mbedtls_ecdsa_free(&ecdsa); + if (r != CCID_OK) + return SW_EXEC_ERROR(); + } + if (fid == EF_PK_SIG) + reset_sig_count(); + return SW_OK(); +} + typedef struct cmd { uint8_t ins; @@ -1524,6 +1643,7 @@ typedef struct cmd #define INS_SELECT 0xA4 #define INS_GET_DATA 0xCA #define INS_PUT_DATA 0xDA +#define INS_IMPORT_DATA 0xDB #define INS_TERMINATE_DF 0xE6 static const cmd_t cmds[] = { @@ -1540,6 +1660,7 @@ static const cmd_t cmds[] = { { INS_CHALLENGE, cmd_challenge }, { INS_INTERNAL_AUT, cmd_internal_aut }, { INS_MSE, cmd_mse }, + { INS_IMPORT_DATA, cmd_import_data }, { 0x00, 0x0} };