From 2a5fe1cc6dbedde1bf2ae6cd767689d312cda64f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 22 Mar 2023 01:04:24 +0100 Subject: [PATCH] Added initialization with self-signed certificate. It will allow the initialization with OpenSC tool (sc-hsm-tool --initialize). However, it will not allow the use of card with SCS3, as it needs a PKI with trust chain. In this case, pico-hsm-tool.py shall be used for initialization. Signed-off-by: Pol Henarejos --- src/hsm/cmd_initialize.c | 17 ++++++- src/hsm/cvc.c | 85 +++++++++++++++++++-------------- src/hsm/cvc.h | 3 +- tests/pico-hsm/test_000_info.py | 9 ++-- 4 files changed, 73 insertions(+), 41 deletions(-) diff --git a/src/hsm/cmd_initialize.c b/src/hsm/cmd_initialize.c index a78daa1..06b1082 100644 --- a/src/hsm/cmd_initialize.c +++ b/src/hsm/cmd_initialize.c @@ -197,17 +197,29 @@ int cmd_initialize() { mbedtls_ecdsa_free(&ecdsa); 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) { + mbedtls_ecdsa_free(&ecdsa); + return SW_EXEC_ERROR(); + } + + if ((cvc_len = asn1_cvc_cert(&ecdsa, HSM_KEY_EC, res_APDU, 4096, NULL, 0, true)) == 0) { + mbedtls_ecdsa_free(&ecdsa); + return SW_EXEC_ERROR(); + } + memcpy(res_APDU + cvc_len, res_APDU, cvc_len); + mbedtls_ecdsa_free(&ecdsa); + fpk = search_by_fid(EF_TERMCA, NULL, SPECIFY_EF); + ret = flash_write_data_to_file(fpk, res_APDU, 2 * 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 *) "ESTERMHSM"; + *label = (const uint8_t *) "ESPICOHSMTR"; size_t prkd_len = asn1_build_prkd_ecc(label, strlen((const char *) label), keyid, @@ -217,6 +229,7 @@ int cmd_initialize() { 4096); fpk = search_by_fid(EF_PRKD_DEV, NULL, SPECIFY_EF); ret = flash_write_data_to_file(fpk, res_APDU, prkd_len); + } if (ret != 0) { return SW_EXEC_ERROR(); diff --git a/src/hsm/cvc.c b/src/hsm/cvc.c index 75ba816..9a70de9 100644 --- a/src/hsm/cvc.c +++ b/src/hsm/cvc.c @@ -86,12 +86,7 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz Y_buf, sizeof(Y_buf)); size_t c_size = 1; - size_t ptot_size = asn1_len_tag(0x81, p_size), atot_size = asn1_len_tag(0x82, - a_size ? a_size : ( - pointA[ecdsa->grp.id - ] && - ecdsa->grp.id < - 6 ? p_size : 1)); + size_t ptot_size = asn1_len_tag(0x81, p_size), atot_size = asn1_len_tag(0x82, a_size ? a_size : (pointA[ecdsa->grp.id] && ecdsa->grp.id < 6 ? p_size : 1)); size_t btot_size = asn1_len_tag(0x83, b_size), gtot_size = asn1_len_tag(0x84, g_size); size_t otot_size = asn1_len_tag(0x85, o_size), ytot_size = asn1_len_tag(0x86, y_size); size_t ctot_size = asn1_len_tag(0x87, c_size); @@ -118,9 +113,7 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz p += p_size; //A if (a_size) { - *p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A, - p, - a_size); p += a_size; + *p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A, p, a_size); p += a_size; } else { //mbedtls does not set point A for some curves if (pointA[ecdsa->grp.id] && ecdsa->grp.id < 6) { @@ -137,12 +130,7 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz p += b_size; //G size_t g_new_size = 0; - *p++ = 0x84; p += format_tlv_len(g_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp, - &ecdsa->grp.G, - MBEDTLS_ECP_PF_UNCOMPRESSED, - &g_new_size, - p, - g_size); + *p++ = 0x84; p += format_tlv_len(g_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &g_new_size, p, g_size); p += g_size; //order *p++ = 0x85; p += format_tlv_len(o_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.N, p, o_size); @@ -168,7 +156,8 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa, uint8_t *buf, size_t buf_len, const uint8_t *ext, - size_t ext_len) { + size_t ext_len, + bool full) { size_t pubkey_size = 0; if (key_type & HSM_KEY_RSA) { pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0); @@ -176,11 +165,16 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa, else if (key_type & HSM_KEY_EC) { pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0); } - size_t cpi_size = 4; - size_t ext_size = 0; + size_t cpi_size = 4, ext_size = 0, role_size = 0, valid_size = 0; if (ext && ext_len > 0) { ext_size = asn1_len_tag(0x65, ext_len); } + const uint8_t *role = (const uint8_t *)"\x06\x09\x04\x00\x7F\x00\x07\x03\x01\x02\x02\x53\x01\x00"; + size_t rolelen = 14; + if (full) { + role_size = asn1_len_tag(0x7f4c, rolelen); + valid_size = asn1_len_tag(0x5f24, 6) + asn1_len_tag(0x5f25, 6); + } uint8_t *car = NULL, *chr = NULL; size_t lencar = 0, lenchr = 0; @@ -189,15 +183,23 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa, &car) == false || lencar == 0 || car == NULL) { car = (uint8_t *) dev_name; lencar = dev_name_len; + if (dev_name == NULL) { + car = (uint8_t *)"ESPICOHSMTR00001"; + lencar = strlen((const char *)car); + } } if (asn1_find_tag(apdu.data, apdu.nc, 0x5f20, &lenchr, &chr) == false || lenchr == 0 || chr == NULL) { chr = (uint8_t *) dev_name; lenchr = dev_name_len; + if (chr == NULL) { + chr = car; + lenchr = lencar; + } } size_t car_size = asn1_len_tag(0x42, lencar), chr_size = asn1_len_tag(0x5f20, lenchr); - size_t tot_len = asn1_len_tag(0x7f4e, cpi_size + car_size + pubkey_size + chr_size + ext_size); + size_t tot_len = asn1_len_tag(0x7f4e, cpi_size + car_size + pubkey_size + chr_size + ext_size + role_size + valid_size); if (buf_len == 0 || buf == NULL) { return tot_len; @@ -207,7 +209,7 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa, } uint8_t *p = buf; memcpy(p, "\x7F\x4E", 2); p += 2; - p += format_tlv_len(cpi_size + car_size + pubkey_size + chr_size + ext_size, p); + p += format_tlv_len(cpi_size + car_size + pubkey_size + chr_size + role_size + valid_size + ext_size, p); //cpi *p++ = 0x5f; *p++ = 0x29; *p++ = 1; *p++ = 0; //car @@ -221,6 +223,25 @@ size_t asn1_cvc_cert_body(void *rsa_ecdsa, } //chr *p++ = 0x5f; *p++ = 0x20; p += format_tlv_len(lenchr, p); memcpy(p, chr, lenchr); p += lenchr; + if (full) { + *p++ = 0x7f; + *p++ = 0x4c; + p += format_tlv_len(rolelen, p); + memcpy(p, role, rolelen); + p += rolelen; + + *p++ = 0x5f; + *p++ = 0x25; + p += format_tlv_len(6, p); + memcpy(p, "\x02\x03\x00\x03\x02\x01", 6); + p += 6; + + *p++ = 0x5f; + *p++ = 0x24; + p += format_tlv_len(6, p); + memcpy(p, "\x07\x00\x01\x02\x03\x01", 6); + p += 6; + } if (ext && ext_len > 0) { *p++ = 0x65; p += format_tlv_len(ext_len, p); @@ -235,19 +256,16 @@ size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t *buf, size_t buf_len, const uint8_t *ext, - size_t ext_len) { + size_t ext_len, + bool full) { size_t key_size = 0; if (key_type & HSM_KEY_RSA) { key_size = mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N); } else if (key_type & HSM_KEY_EC) { - key_size = 2 * - (int) ((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *) rsa_ecdsa) - ->grp.id)-> - bit_size + 7) / 8); + key_size = 2 * (int)((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *) rsa_ecdsa)->grp.id)->bit_size + 7) / 8); } - size_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len), - sig_size = asn1_len_tag(0x5f37, key_size); + size_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, full), sig_size = asn1_len_tag(0x5f37, key_size); size_t tot_len = asn1_len_tag(0x7f21, body_size + sig_size); if (buf_len == 0 || buf == NULL) { return tot_len; @@ -259,14 +277,13 @@ size_t asn1_cvc_cert(void *rsa_ecdsa, memcpy(p, "\x7F\x21", 2); p += 2; 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); + p += asn1_cvc_cert_body(rsa_ecdsa, key_type, p, body_size, ext, ext_len, full); uint8_t hsh[32]; hash256(body, body_size, hsh); memcpy(p, "\x5F\x37", 2); p += 2; p += format_tlv_len(key_size, p); if (key_type & HSM_KEY_RSA) { - if (mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa_ecdsa, random_gen, NULL, MBEDTLS_MD_SHA256, 32, - hsh, p) != 0) { + if (mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa_ecdsa, random_gen, NULL, MBEDTLS_MD_SHA256, 32, hsh, p) != 0) { memset(p, 0, key_size); } p += key_size; @@ -299,7 +316,7 @@ size_t asn1_cvc_aut(void *rsa_ecdsa, 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 cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, false); size_t outcar_len = dev_name_len; const uint8_t *outcar = dev_name; size_t outcar_size = asn1_len_tag(0x42, outcar_len); @@ -314,9 +331,7 @@ size_t asn1_cvc_aut(void *rsa_ecdsa, return 0; } int ret = 0, key_size = 2 * 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); + 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; } @@ -328,7 +343,7 @@ size_t asn1_cvc_aut(void *rsa_ecdsa, p += format_tlv_len(cvcert_size + outcar_size + outsig_size, p); uint8_t *body = p; //cvcert - p += asn1_cvc_cert(rsa_ecdsa, key_type, p, cvcert_size, ext, ext_len); + p += asn1_cvc_cert(rsa_ecdsa, key_type, p, cvcert_size, ext, ext_len, false); //outcar *p++ = 0x42; p += format_tlv_len(outcar_len, p); memcpy(p, outcar, outcar_len); p += outcar_len; uint8_t hsh[32]; diff --git a/src/hsm/cvc.h b/src/hsm/cvc.h index 1ef1f3b..389574c 100644 --- a/src/hsm/cvc.h +++ b/src/hsm/cvc.h @@ -45,7 +45,8 @@ extern size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t *buf, size_t buf_len, const uint8_t *ext, - size_t ext_len); + size_t ext_len, + bool full); extern size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, diff --git a/tests/pico-hsm/test_000_info.py b/tests/pico-hsm/test_000_info.py index e1c3ca4..79ffb33 100644 --- a/tests/pico-hsm/test_000_info.py +++ b/tests/pico-hsm/test_000_info.py @@ -22,12 +22,15 @@ import pytest def test_select(device): device.select_applet() +def test_initialization(device): + device.initialize() + def test_termca(device): data = device.get_termca() assert(b'ESPICOHSMTR' == data['cv']['chr'][:11]) - assert(b'ESPICOHSMDV' == data['cv']['car'][:11]) - assert(b'ESPICOHSMDV' == data['dv']['chr'][:11]) - assert(b'ESPICOHSMCA' == data['dv']['car'][:11]) + assert(b'ESPICOHSMDV' == data['cv']['car'][:11] or b'ESPICOHSMTR' == data['cv']['car'][:11]) + assert(b'ESPICOHSMDV' == data['dv']['chr'][:11] or b'ESPICOHSMTR' == data['dv']['chr'][:11]) + assert(b'ESPICOHSMCA' == data['dv']['car'][:11] or b'ESPICOHSMTR' == data['dv']['car'][:11]) assert(data['cv']['car'] == data['dv']['chr']) def test_get_version(device):