From fec02ca733d3c65d47149a64e2a93f703d45fd26 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 18 Aug 2022 13:29:24 +0200 Subject: [PATCH] Removing cvcerts.h dependency. A python script gets the public key of the device (EF_EE_DEV) and requests to our PKI for a CVC. Once got, it is updated to EF_TERMCA (0x2f02). termca_pk is now on EF_KEY_DEV and termca is on EF_TERMCA (concat with DICA). Signed-off-by: Pol Henarejos --- src/hsm/cmd_general_authenticate.c | 17 ++++++++++++++--- src/hsm/cmd_initialize.c | 6 +++--- src/hsm/cmd_key_domain.c | 6 ++++-- src/hsm/cmd_select.c | 2 +- src/hsm/cvc.c | 27 ++++++++++++++++----------- src/hsm/files.c | 3 +-- src/hsm/files.h | 2 ++ src/hsm/sc_hsm.c | 21 ++++----------------- 8 files changed, 45 insertions(+), 39 deletions(-) diff --git a/src/hsm/cmd_general_authenticate.c b/src/hsm/cmd_general_authenticate.c index 536d09b..4d334bf 100644 --- a/src/hsm/cmd_general_authenticate.c +++ b/src/hsm/cmd_general_authenticate.c @@ -20,9 +20,9 @@ #include "asn1.h" #include "sc_hsm.h" #include "random.h" -#include "cvcerts.h" #include "oid.h" #include "eac.h" +#include "files.h" int cmd_general_authenticate() { if (P1(apdu) == 0x0 && P2(apdu) == 0x0) { @@ -39,16 +39,27 @@ int cmd_general_authenticate() { pubkey_len = tag_len+1; } } + file_t *fkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF); + if (!fkey) + return SW_EXEC_ERROR(); + mbedtls_ecdsa_context ectx; + mbedtls_ecdsa_init(&ectx); + r = load_private_key_ecdsa(&ectx, fkey); + if (r != CCID_OK) { + mbedtls_ecdsa_free(&ectx); + return SW_EXEC_ERROR(); + } mbedtls_ecdh_context ctx; - int key_size = file_read_uint16(termca_pk); mbedtls_ecdh_init(&ctx); mbedtls_ecp_group_id gid = MBEDTLS_ECP_DP_SECP192R1; r = mbedtls_ecdh_setup(&ctx, gid); if (r != 0) { + mbedtls_ecdsa_free(&ectx); mbedtls_ecdh_free(&ctx); return SW_DATA_INVALID(); } - r = mbedtls_mpi_read_binary(&ctx.ctx.mbed_ecdh.d, termca_pk+2, key_size); + r = mbedtls_mpi_copy(&ctx.ctx.mbed_ecdh.d, &ectx.d); + mbedtls_ecdsa_free(&ectx); if (r != 0) { mbedtls_ecdh_free(&ctx); return SW_DATA_INVALID(); diff --git a/src/hsm/cmd_initialize.c b/src/hsm/cmd_initialize.c index 5c14d0b..8ca0113 100644 --- a/src/hsm/cmd_initialize.c +++ b/src/hsm/cmd_initialize.c @@ -160,18 +160,18 @@ int cmd_initialize() { mbedtls_ecdsa_free(&ecdsa); return SW_EXEC_ERROR(); } - mbedtls_ecdsa_free(&ecdsa); - size_t cvc_len = 0; if ((cvc_len = asn1_cvc_aut(&ecdsa, HSM_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) { return SW_EXEC_ERROR(); } + mbedtls_ecdsa_free(&ecdsa); + file_t *fpk = search_by_fid(EF_EE_DEV, NULL, SPECIFY_EF); ret = flash_write_data_to_file(fpk, res_APDU, cvc_len); if (ret != 0) return SW_EXEC_ERROR(); - const uint8_t *keyid = (const uint8_t *)"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", *label = (const uint8_t *)"TERMCA"; + const uint8_t *keyid = (const uint8_t *)"\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", *label = (const uint8_t *)"ESTERMHSM"; size_t prkd_len = asn1_build_prkd_ecc(label, strlen((const char *)label), keyid, 20, 192, res_APDU, 4096); fpk = search_by_fid(EF_PRKD_DEV, NULL, SPECIFY_EF); ret = flash_write_data_to_file(fpk, res_APDU, prkd_len); diff --git a/src/hsm/cmd_key_domain.c b/src/hsm/cmd_key_domain.c index 39a6037..ee6d655 100644 --- a/src/hsm/cmd_key_domain.c +++ b/src/hsm/cmd_key_domain.c @@ -20,7 +20,6 @@ #include "cvc.h" #include "kek.h" #include "files.h" -#include "cvcerts.h" uint8_t get_key_domain(file_t *fkey) { size_t tag_len = 0; @@ -110,7 +109,10 @@ int cmd_key_domain() { else if (p1 == 0x2) { //XKEK Key Domain creation if (apdu.nc > 0) { size_t pub_len = 0; - const uint8_t *pub = cvc_get_pub(termca+2, (termca[1] << 8 | termca[0]), &pub_len); + file_t *fterm = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF); + if (!fterm) + return SW_EXEC_ERROR(); + const uint8_t *pub = cvc_get_pub(file_get_data(fterm), file_get_size(fterm), &pub_len); if (!pub) return SW_EXEC_ERROR(); size_t t86_len = 0; diff --git a/src/hsm/cmd_select.c b/src/hsm/cmd_select.c index 0ec247a..b966056 100644 --- a/src/hsm/cmd_select.c +++ b/src/hsm/cmd_select.c @@ -63,7 +63,7 @@ int cmd_select() { pfx == DCOD_PREFIX || pfx == DATA_PREFIX || pfx == PROT_DATA_PREFIX) { - if (!(pe = search_dynamic_file(fid))) + if (!(pe = search_dynamic_file(fid)) && !(pe = search_by_fid(fid, NULL, SPECIFY_EF))) return SW_FILE_NOT_FOUND(); } if (!pe) { diff --git a/src/hsm/cvc.c b/src/hsm/cvc.c index 7324f31..4c00c08 100644 --- a/src/hsm/cvc.c +++ b/src/hsm/cvc.c @@ -17,9 +17,9 @@ #include "common.h" #include "cvc.h" +#include "sc_hsm.h" #include "mbedtls/rsa.h" #include "mbedtls/ecdsa.h" -#include "cvcerts.h" #include #include "asn1.h" #include "ccid2040.h" @@ -27,6 +27,7 @@ #include "random.h" #include "oid.h" #include "mbedtls/md.h" +#include "files.h" extern const uint8_t *dev_name; extern size_t dev_name_len; @@ -182,7 +183,6 @@ size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf p += format_tlv_len(body_size+sig_size, p); body = p; p += asn1_cvc_cert_body(rsa_ecdsa, key_type, p, body_size, ext, ext_len); - uint8_t hsh[32]; hash256(body, body_size, hsh); memcpy(p, "\x5F\x37", 2); p += 2; @@ -214,10 +214,19 @@ size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len, const uint8_t *ext, size_t ext_len) { size_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len); - size_t outcar_len = 0; - const uint8_t *outcar = cvc_get_chr((uint8_t *)termca+2, (termca[1] << 8) | termca[0], &outcar_len); + size_t outcar_len = dev_name_len; + const uint8_t *outcar = dev_name; size_t outcar_size = asn1_len_tag(0x42, outcar_len); - int key_size = 2*file_read_uint16(termca_pk), ret = 0; + file_t *fkey = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF); + if (!fkey) + return 0; + mbedtls_ecdsa_context ectx; + mbedtls_ecdsa_init(&ectx); + if (load_private_key_ecdsa(&ectx, fkey) != CCID_OK) { + mbedtls_ecdsa_free(&ectx); + return 0; + } + int ret = 0, key_size = mbedtls_mpi_size(&ectx.d); size_t outsig_size = asn1_len_tag(0x5f37, key_size), tot_len = asn1_len_tag(0x67, cvcert_size+outcar_size+outsig_size); if (buf_len == 0 || buf == NULL) return tot_len; @@ -231,10 +240,6 @@ size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_ p += asn1_cvc_cert(rsa_ecdsa, key_type, p, cvcert_size, ext, ext_len); //outcar *p++ = 0x42; p += format_tlv_len(outcar_len, p); memcpy(p, outcar, outcar_len); p += outcar_len; - mbedtls_ecdsa_context ctx; - mbedtls_ecdsa_init(&ctx); - if (mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP192R1, &ctx, termca_pk+2, file_read_uint16(termca_pk)) != 0) - return 0; uint8_t hsh[32]; memcpy(p, "\x5f\x37", 2); p += 2; p += format_tlv_len(key_size, p); @@ -242,8 +247,8 @@ size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_ mbedtls_mpi r, s; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); - ret = mbedtls_ecdsa_sign(&ctx.grp, &r, &s, &ctx.d, hsh, sizeof(hsh), random_gen, NULL); - mbedtls_ecdsa_free(&ctx); + ret = mbedtls_ecdsa_sign(&ectx.grp, &r, &s, &ectx.d, hsh, sizeof(hsh), random_gen, NULL); + mbedtls_ecdsa_free(&ectx); if (ret != 0) { mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); diff --git a/src/hsm/files.c b/src/hsm/files.c index 471ccb2..6effdd7 100644 --- a/src/hsm/files.c +++ b/src/hsm/files.c @@ -19,13 +19,12 @@ extern const uint8_t sc_hsm_aid[]; extern int parse_token_info(const file_t *f, int mode); -extern int parse_cvca(const file_t *f, int mode); file_t file_entries[] = { /* 0 */ { .fid = 0x3f00 , .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = {0} }, // MF /* 1 */ { .fid = 0x2f00 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DIR /* 2 */ { .fid = 0x2f01 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.ATR - /* 3 */ { .fid = 0x2f02 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC,.data = (uint8_t *)parse_cvca, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.GDO + /* 3 */ { .fid = EF_TERMCA , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.GDO /* 4 */ { .fid = 0x2f03 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC,.data = (uint8_t *)parse_token_info, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.TokenInfo /* 5 */ { .fid = 0x5015 , .parent = 0, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = {0} }, //DF.PKCS15 /* 6 */ { .fid = 0x5031 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.ODF diff --git a/src/hsm/files.h b/src/hsm/files.h index 78146c3..0b8d772 100644 --- a/src/hsm/files.h +++ b/src/hsm/files.h @@ -40,6 +40,8 @@ #define EF_PRKD_DEV 0xC400 #define EF_EE_DEV 0xCE00 +#define EF_TERMCA 0x2f02 + extern file_t *file_pin1; extern file_t *file_retries_pin1; extern file_t *file_sopin; diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 01fb448..803ffb9 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -19,7 +19,6 @@ #include "files.h" #include "common.h" #include "version.h" -#include "cvcerts.h" #include "crypto_utils.h" #include "kek.h" #include "eac.h" @@ -218,16 +217,15 @@ void init_sc_hsm() { } memset(puk_store, 0, sizeof(puk_store)); puk_store_entries = 0; - const uint8_t *cvcerts[] = { cvca, dica, termca }; - for (int i = 0; i < sizeof(cvcerts)/sizeof(uint8_t *); i++) { - add_cert_puk_store(cvcerts[i]+2, (cvcerts[i][1] << 8) | cvcerts[i][0], false); - } + file_t *fterm = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF); + if (fterm) + add_cert_puk_store(file_get_data(fterm), file_get_size(fterm), false); for (int i = 0; i < 0xfe; i++) { file_t *ef = search_dynamic_file((CA_CERTIFICATE_PREFIX << 8) | i); if (ef && file_get_size(ef) > 0) add_cert_puk_store(file_get_data(ef), file_get_size(ef), false); } - dev_name = cvc_get_chr(termca, (termca[1] << 8) | termca[0], &dev_name_len); + dev_name = cvc_get_chr(file_get_data(fterm), file_get_size(fterm), &dev_name_len); memset(puk_status, 0, sizeof(puk_status)); } @@ -278,17 +276,6 @@ int parse_token_info(const file_t *f, int mode) { return 2+(2+1)+(2+8)+(2+strlen(manu))+(2+strlen(label))+(2+2); } -int parse_cvca(const file_t *f, int mode) { - size_t termca_len = file_read_uint16(termca); - size_t dica_len = file_read_uint16(dica); - if (mode == 1) { - memcpy(res_APDU, termca+2, termca_len); - memcpy(res_APDU+termca_len, dica+2, dica_len); - res_APDU_size = termca_len+dica_len; - } - return termca_len+dica_len; -} - int pin_reset_retries(const file_t *pin, bool force) { if (!pin) return CCID_ERR_NULL_PARAM;