diff --git a/CMakeLists.txt b/CMakeLists.txt index 0c5b49d..d7dc6ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,16 +54,18 @@ target_sources(pico_hsm PUBLIC ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/usb/usb.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/usb/usb_descriptors.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/ccid2040.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/asn1.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/file.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/flash.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/low_flash.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/rng/random.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/rng/neug.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/files.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/crypto_utils.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/dkek.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/eac.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cvc.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/files.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/dkek.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/sha256.c ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/aes.c diff --git a/src/hsm/cvc.c b/src/hsm/cvc.c new file mode 100644 index 0000000..ffd8662 --- /dev/null +++ b/src/hsm/cvc.c @@ -0,0 +1,224 @@ +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "cvc.h" +#include "common.h" +#include "mbedtls/rsa.h" +#include "mbedtls/ecdsa.h" +#include "cvcerts.h" +#include +#include "asn1.h" +#include "ccid2040.h" +#include "crypto_utils.h" +#include "random.h" + +size_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, size_t buf_len) { + const uint8_t oid_rsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x01, 0x02 }; + size_t n_size = mbedtls_mpi_size(&rsa->N), e_size = mbedtls_mpi_size(&rsa->E); + size_t ntot_size = asn1_len_tag(0x81, n_size), etot_size = asn1_len_tag(0x82, e_size); + size_t oid_len = asn1_len_tag(0x6, sizeof(oid_rsa)); + size_t tot_len = asn1_len_tag(0x7f49, oid_len+ntot_size+etot_size); + if (buf == NULL || buf_len == 0) + return tot_len; + if (buf_len < tot_len) + return 0; + uint8_t *p = buf; + memcpy(p, "\x7f\x49", 2); p += 2; + p += format_tlv_len(oid_len+ntot_size+etot_size, p); + //oid + *p++ = 0x6; p += format_tlv_len(sizeof(oid_rsa), p); memcpy(p, oid_rsa, sizeof(oid_rsa)); p += sizeof(oid_rsa); + //n + *p++ = 0x81; p += format_tlv_len(n_size, p); mbedtls_mpi_write_binary(&rsa->N, p, n_size); p += n_size; + //n + *p++ = 0x82; p += format_tlv_len(e_size, p); mbedtls_mpi_write_binary(&rsa->E, p, e_size); p += e_size; + return tot_len; +} + +size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, size_t buf_len) { + const uint8_t oid_ecdsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03 }; + size_t p_size = mbedtls_mpi_size(&ecdsa->grp.P), a_size = mbedtls_mpi_size(&ecdsa->grp.A); + size_t b_size = mbedtls_mpi_size(&ecdsa->grp.B), g_size = 1+mbedtls_mpi_size(&ecdsa->grp.G.X)+mbedtls_mpi_size(&ecdsa->grp.G.X); + size_t o_size = mbedtls_mpi_size(&ecdsa->grp.N), y_size = 1+mbedtls_mpi_size(&ecdsa->Q.X)+mbedtls_mpi_size(&ecdsa->Q.X); + size_t c_size = 1; + size_t ptot_size = asn1_len_tag(0x81, p_size), atot_size = asn1_len_tag(0x82, a_size); + 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); + size_t oid_len = asn1_len_tag(0x6, sizeof(oid_ecdsa)); + size_t tot_len = asn1_len_tag(0x7f49, oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+ctot_size); + if (buf == NULL || buf_len == 0) + return tot_len; + if (buf_len < tot_len) + return 0; + uint8_t *p = buf; + memcpy(p, "\x7f\x49", 2); p += 2; + p += format_tlv_len(oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+ctot_size, p); + //oid + *p++ = 0x6; p += format_tlv_len(sizeof(oid_ecdsa), p); memcpy(p, oid_ecdsa, sizeof(oid_ecdsa)); p += sizeof(oid_ecdsa); + //p + *p++ = 0x81; p += format_tlv_len(p_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.P, p, p_size); p += p_size; + //A + *p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A, p, a_size); p += a_size; + //B + *p++ = 0x83; p += format_tlv_len(b_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.B, p, b_size); 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 += g_size; + //order + *p++ = 0x85; p += format_tlv_len(o_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.N, p, o_size); p += o_size; + //Y + size_t y_new_size = 0; + *p++ = 0x86; p += format_tlv_len(y_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &y_new_size, p, y_size); p += y_size; + //cofactor + *p++ = 0x87; p += format_tlv_len(c_size, p); *p++ = 1; + return tot_len; +} + +size_t asn1_cvc_cert_body(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len) { + size_t pubkey_size = 0; + if (key_type == HSM_KEY_RSA) + pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0); + else if (key_type == HSM_KEY_EC) + pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0); + size_t cpi_size = 4; + + uint8_t *car = NULL, *chr = NULL; + size_t lencar = 0, lenchr = 0; + + if (asn1_find_tag(apdu.data, apdu.nc, 0x42, &lencar, &car) == false || lencar == 0 || car == NULL) { + car = (uint8_t *)"UTSRCACC100001"; + lencar = strlen((char *)car); + } + if (asn1_find_tag(apdu.data, apdu.nc, 0x5f20, &lenchr, &chr) == false || lenchr == 0 || chr == NULL) { + chr = (uint8_t *)"ESHSMCVCA00001"; + lenchr = strlen((char *)chr); + } + 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); + + if (buf_len == 0 || buf == NULL) + return tot_len; + if (buf_len < tot_len) + return 0; + uint8_t *p = buf; + memcpy(p, "\x7f\x4e", 2); p += 2; + p += format_tlv_len(cpi_size+car_size+pubkey_size+chr_size, p); + //cpi + *p++ = 0x5f; *p++ = 0x29; *p++ = 1; *p++ = 0; + //car + *p++ = 0x42; p += format_tlv_len(lencar, p); memcpy(p, car, lencar); p += lencar; + //pubkey + if (key_type == HSM_KEY_RSA) + p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size); + else if (key_type == HSM_KEY_EC) + p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size); + //chr + *p++ = 0x5f; *p++ = 0x20; p += format_tlv_len(lenchr, p); memcpy(p, chr, lenchr); p += lenchr; + return tot_len; +} + +size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len) { + 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 = MBEDTLS_ECDSA_MAX_SIG_LEN(((mbedtls_ecdsa_context *)rsa_ecdsa)->grp.nbits+1); + size_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0), 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; + if (buf_len < tot_len) + return 0; + uint8_t *p = buf, *body = NULL, *sig_len_pos = NULL; + 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); + + uint8_t hsh[32]; + hash256(body, body_size, hsh); + memcpy(p, "\x5f\x37", 2); p += 2; + sig_len_pos = p; + 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) + return 0; + p += key_size; + } + else if (key_type == HSM_KEY_EC) { + size_t new_key_size = 0; + if (mbedtls_ecdsa_write_signature(rsa_ecdsa, MBEDTLS_MD_SHA256, hsh, sizeof(hsh), p, key_size, &new_key_size, random_gen, NULL) != 0) + return 0; + p += new_key_size; + if (new_key_size != key_size) { + size_t new_sig_size = asn1_len_tag(0x5f37, new_key_size); + format_tlv_len(new_key_size, sig_len_pos); + if (format_tlv_len(body_size+sig_size, NULL) != format_tlv_len(body_size+new_sig_size, NULL)) + memmove(buf+2+format_tlv_len(body_size+new_sig_size, NULL), buf+2+format_tlv_len(body_size+sig_size, NULL), body_size+new_sig_size); + format_tlv_len(body_size+new_sig_size, buf+2); + tot_len = asn1_len_tag(0x7f21, body_size+new_sig_size); + } + } + return p-buf; +} + +size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len) { + size_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0); + uint8_t *outcar = (uint8_t *)"ESHSM00001"; + size_t lenoutcar = strlen((char *)outcar), outcar_size = asn1_len_tag(0x42, lenoutcar); + int key_size = 2*file_read_uint16(termca_pk)+9; + 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; + if (buf_len < tot_len) + return 0; + uint8_t *p = buf; + *p++ = 0x67; + 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); + cvcert_size = p-body; + //outcar + *p++ = 0x42; p += format_tlv_len(lenoutcar, p); memcpy(p, outcar, lenoutcar); p += lenoutcar; + 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], *sig_len_pos = NULL; + memcpy(p, "\x5f\x37", 2); p += 2; + sig_len_pos = p; + p += format_tlv_len(key_size, p); + hash256(body, cvcert_size+outcar_size, hsh); + size_t new_key_size = 0; + if (mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, hsh, sizeof(hsh), p, key_size, &new_key_size, random_gen, NULL) != 0) { + mbedtls_ecdsa_free(&ctx); + return 0; + } + p += new_key_size; + mbedtls_ecdsa_free(&ctx); + if (new_key_size != key_size) { + size_t new_sig_size = asn1_len_tag(0x5f37, new_key_size); + format_tlv_len(new_key_size, sig_len_pos); + if (format_tlv_len(cvcert_size+outcar_size+outsig_size, NULL) != format_tlv_len(cvcert_size+outcar_size+new_sig_size, NULL)) + memmove(buf+1+format_tlv_len(cvcert_size+outcar_size+new_sig_size, NULL), buf+1+format_tlv_len(cvcert_size+outcar_size+outsig_size, NULL), cvcert_size+outcar_size+new_sig_size); + format_tlv_len(cvcert_size+outcar_size+new_sig_size, buf+1); + tot_len = asn1_len_tag(0x67, cvcert_size+outcar_size+new_sig_size); + } + return p-buf; +} diff --git a/src/hsm/cvc.h b/src/hsm/cvc.h new file mode 100644 index 0000000..9cef0fd --- /dev/null +++ b/src/hsm/cvc.h @@ -0,0 +1,27 @@ +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _CVC_H_ +#define _CVC_H_ + +#include +#include "pico/stdlib.h" + +extern size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len); +extern size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len); + +#endif diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 4e88394..4423c32 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -33,6 +33,8 @@ #include "dkek.h" #include "hardware/rtc.h" #include "eac.h" +#include "cvc.h" +#include "asn1.h" const uint8_t sc_hsm_aid[] = { 11, @@ -921,203 +923,6 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, uint8_t kdom) { return CCID_OK; } -size_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, size_t buf_len) { - const uint8_t oid_rsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x01, 0x02 }; - size_t n_size = mbedtls_mpi_size(&rsa->N), e_size = mbedtls_mpi_size(&rsa->E); - size_t ntot_size = asn1_len_tag(0x81, n_size), etot_size = asn1_len_tag(0x82, e_size); - size_t oid_len = asn1_len_tag(0x6, sizeof(oid_rsa)); - size_t tot_len = asn1_len_tag(0x7f49, oid_len+ntot_size+etot_size); - if (buf == NULL || buf_len == 0) - return tot_len; - if (buf_len < tot_len) - return 0; - uint8_t *p = buf; - memcpy(p, "\x7f\x49", 2); p += 2; - p += format_tlv_len(oid_len+ntot_size+etot_size, p); - //oid - *p++ = 0x6; p += format_tlv_len(sizeof(oid_rsa), p); memcpy(p, oid_rsa, sizeof(oid_rsa)); p += sizeof(oid_rsa); - //n - *p++ = 0x81; p += format_tlv_len(n_size, p); mbedtls_mpi_write_binary(&rsa->N, p, n_size); p += n_size; - //n - *p++ = 0x82; p += format_tlv_len(e_size, p); mbedtls_mpi_write_binary(&rsa->E, p, e_size); p += e_size; - return tot_len; -} - -size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, size_t buf_len) { - const uint8_t oid_ecdsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03 }; - size_t p_size = mbedtls_mpi_size(&ecdsa->grp.P), a_size = mbedtls_mpi_size(&ecdsa->grp.A); - size_t b_size = mbedtls_mpi_size(&ecdsa->grp.B), g_size = 1+mbedtls_mpi_size(&ecdsa->grp.G.X)+mbedtls_mpi_size(&ecdsa->grp.G.X); - size_t o_size = mbedtls_mpi_size(&ecdsa->grp.N), y_size = 1+mbedtls_mpi_size(&ecdsa->Q.X)+mbedtls_mpi_size(&ecdsa->Q.X); - size_t c_size = 1; - size_t ptot_size = asn1_len_tag(0x81, p_size), atot_size = asn1_len_tag(0x82, a_size); - 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); - size_t oid_len = asn1_len_tag(0x6, sizeof(oid_ecdsa)); - size_t tot_len = asn1_len_tag(0x7f49, oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+ctot_size); - if (buf == NULL || buf_len == 0) - return tot_len; - if (buf_len < tot_len) - return 0; - uint8_t *p = buf; - memcpy(p, "\x7f\x49", 2); p += 2; - p += format_tlv_len(oid_len+ptot_size+atot_size+btot_size+gtot_size+otot_size+ytot_size+ctot_size, p); - //oid - *p++ = 0x6; p += format_tlv_len(sizeof(oid_ecdsa), p); memcpy(p, oid_ecdsa, sizeof(oid_ecdsa)); p += sizeof(oid_ecdsa); - //p - *p++ = 0x81; p += format_tlv_len(p_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.P, p, p_size); p += p_size; - //A - *p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A, p, a_size); p += a_size; - //B - *p++ = 0x83; p += format_tlv_len(b_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.B, p, b_size); 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 += g_size; - //order - *p++ = 0x85; p += format_tlv_len(o_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.N, p, o_size); p += o_size; - //Y - size_t y_new_size = 0; - *p++ = 0x86; p += format_tlv_len(y_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &y_new_size, p, y_size); p += y_size; - //cofactor - *p++ = 0x87; p += format_tlv_len(c_size, p); *p++ = 1; - return tot_len; -} - -size_t asn1_cvc_cert_body(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len) { - size_t pubkey_size = 0; - if (key_type == HSM_KEY_RSA) - pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0); - else if (key_type == HSM_KEY_EC) - pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0); - size_t cpi_size = 4; - - uint8_t *car = NULL, *chr = NULL; - size_t lencar = 0, lenchr = 0; - - if (asn1_find_tag(apdu.data, apdu.nc, 0x42, &lencar, &car) == false || lencar == 0 || car == NULL) { - car = (uint8_t *)"UTSRCACC100001"; - lencar = strlen((char *)car); - } - if (asn1_find_tag(apdu.data, apdu.nc, 0x5f20, &lenchr, &chr) == false || lenchr == 0 || chr == NULL) { - chr = (uint8_t *)"ESHSMCVCA00001"; - lenchr = strlen((char *)chr); - } - 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); - - if (buf_len == 0 || buf == NULL) - return tot_len; - if (buf_len < tot_len) - return 0; - uint8_t *p = buf; - memcpy(p, "\x7f\x4e", 2); p += 2; - p += format_tlv_len(cpi_size+car_size+pubkey_size+chr_size, p); - //cpi - *p++ = 0x5f; *p++ = 0x29; *p++ = 1; *p++ = 0; - //car - *p++ = 0x42; p += format_tlv_len(lencar, p); memcpy(p, car, lencar); p += lencar; - //pubkey - if (key_type == HSM_KEY_RSA) - p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size); - else if (key_type == HSM_KEY_EC) - p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size); - //chr - *p++ = 0x5f; *p++ = 0x20; p += format_tlv_len(lenchr, p); memcpy(p, chr, lenchr); p += lenchr; - return tot_len; -} - -size_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len) { - 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 = MBEDTLS_ECDSA_MAX_SIG_LEN(((mbedtls_ecdsa_context *)rsa_ecdsa)->grp.nbits+1); - size_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0), 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; - if (buf_len < tot_len) - return 0; - uint8_t *p = buf, *body = NULL, *sig_len_pos = NULL; - 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); - - uint8_t hsh[32]; - hash256(body, body_size, hsh); - memcpy(p, "\x5f\x37", 2); p += 2; - sig_len_pos = p; - 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) - return 0; - p += key_size; - } - else if (key_type == HSM_KEY_EC) { - size_t new_key_size = 0; - if (mbedtls_ecdsa_write_signature(rsa_ecdsa, MBEDTLS_MD_SHA256, hsh, sizeof(hsh), p, key_size, &new_key_size, random_gen, NULL) != 0) - return 0; - p += new_key_size; - if (new_key_size != key_size) { - size_t new_sig_size = asn1_len_tag(0x5f37, new_key_size); - format_tlv_len(new_key_size, sig_len_pos); - if (format_tlv_len(body_size+sig_size, NULL) != format_tlv_len(body_size+new_sig_size, NULL)) - memmove(buf+2+format_tlv_len(body_size+new_sig_size, NULL), buf+2+format_tlv_len(body_size+sig_size, NULL), body_size+new_sig_size); - format_tlv_len(body_size+new_sig_size, buf+2); - tot_len = asn1_len_tag(0x7f21, body_size+new_sig_size); - } - } - return p-buf; -} - -size_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, size_t buf_len) { - size_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0); - uint8_t *outcar = (uint8_t *)"ESHSM00001"; - size_t lenoutcar = strlen((char *)outcar), outcar_size = asn1_len_tag(0x42, lenoutcar); - int key_size = 2*file_read_uint16(termca_pk)+9; - 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; - if (buf_len < tot_len) - return 0; - uint8_t *p = buf; - *p++ = 0x67; - 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); - cvcert_size = p-body; - //outcar - *p++ = 0x42; p += format_tlv_len(lenoutcar, p); memcpy(p, outcar, lenoutcar); p += lenoutcar; - 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], *sig_len_pos = NULL; - memcpy(p, "\x5f\x37", 2); p += 2; - sig_len_pos = p; - p += format_tlv_len(key_size, p); - hash256(body, cvcert_size+outcar_size, hsh); - size_t new_key_size = 0; - if (mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, hsh, sizeof(hsh), p, key_size, &new_key_size, random_gen, NULL) != 0) { - mbedtls_ecdsa_free(&ctx); - return 0; - } - p += new_key_size; - mbedtls_ecdsa_free(&ctx); - if (new_key_size != key_size) { - size_t new_sig_size = asn1_len_tag(0x5f37, new_key_size); - format_tlv_len(new_key_size, sig_len_pos); - if (format_tlv_len(cvcert_size+outcar_size+outsig_size, NULL) != format_tlv_len(cvcert_size+outcar_size+new_sig_size, NULL)) - memmove(buf+1+format_tlv_len(cvcert_size+outcar_size+new_sig_size, NULL), buf+1+format_tlv_len(cvcert_size+outcar_size+outsig_size, NULL), cvcert_size+outcar_size+new_sig_size); - format_tlv_len(cvcert_size+outcar_size+new_sig_size, buf+1); - tot_len = asn1_len_tag(0x67, cvcert_size+outcar_size+new_sig_size); - } - return p-buf; -} - static int cmd_keypair_gen() { uint8_t key_id = P1(apdu), kdom = 0; if (!isUserAuthenticated)