From d01e06aa11acddb37282692acba81620562a053a Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 27 Mar 2022 18:15:06 +0200 Subject: [PATCH 1/8] 2F02 returns terminal's cvcert and DICA. Signed-off-by: Pol Henarejos --- src/fs/file.c | 40 +----------------- src/hsm/sc_hsm.c | 105 ++++++++++++++++++++++++++--------------------- 2 files changed, 60 insertions(+), 85 deletions(-) diff --git a/src/fs/file.c b/src/fs/file.c index 7db74de..39d0fea 100644 --- a/src/fs/file.c +++ b/src/fs/file.c @@ -78,51 +78,15 @@ void process_fci(const file_t *pe) { res_APDU[1] = res_APDU_size-2; } -const uint8_t cvca[] = { - 0x6A, 0x01, - 0x7f, 0x21, 0x82, 0x01, 0x65, 0x7f, 0x4e, 0x82, 0x01, 0x2d, 0x5f, - 0x29, 0x01, 0x00, 0x42, 0x0e, 0x45, 0x53, 0x48, 0x53, 0x4d, 0x43, - 0x56, 0x43, 0x41, 0x32, 0x30, 0x34, 0x30, 0x31, 0x7f, 0x49, 0x81, - 0xdd, 0x06, 0x0a, 0x04, 0x00, 0x7f, 0x00, 0x07, 0x02, 0x02, 0x02, - 0x02, 0x03, 0x81, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfe, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x82, 0x18, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0x83, - 0x18, 0x64, 0x21, 0x05, 0x19, 0xe5, 0x9c, 0x80, 0xe7, 0x0f, 0xa7, - 0xe9, 0xab, 0x72, 0x24, 0x30, 0x49, 0xfe, 0xb8, 0xde, 0xec, 0xc1, - 0x46, 0xb9, 0xb1, 0x84, 0x31, 0x04, 0x18, 0x8d, 0xa8, 0x0e, 0xb0, - 0x30, 0x90, 0xf6, 0x7c, 0xbf, 0x20, 0xeb, 0x43, 0xa1, 0x88, 0x00, - 0xf4, 0xff, 0x0a, 0xfd, 0x82, 0xff, 0x10, 0x12, 0x07, 0x19, 0x2b, - 0x95, 0xff, 0xc8, 0xda, 0x78, 0x63, 0x10, 0x11, 0xed, 0x6b, 0x24, - 0xcd, 0xd5, 0x73, 0xf9, 0x77, 0xa1, 0x1e, 0x79, 0x48, 0x11, 0x85, - 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0x99, 0xde, 0xf8, 0x36, 0x14, 0x6b, 0xc9, 0xb1, 0xb4, - 0xd2, 0x28, 0x31, 0x86, 0x31, 0x04, 0x4d, 0x28, 0x34, 0x67, 0xb5, - 0x43, 0xfd, 0x84, 0x22, 0x09, 0xbd, 0xd2, 0xd6, 0x26, 0x27, 0x2d, - 0x53, 0xa7, 0xdf, 0x52, 0x8f, 0xc2, 0xde, 0x7c, 0x9a, 0xcd, 0x1f, - 0xf2, 0x10, 0x42, 0x7c, 0x13, 0x44, 0x03, 0xb0, 0xa5, 0xdf, 0x8a, - 0xd4, 0x59, 0xd1, 0x86, 0x4b, 0xde, 0x33, 0xb1, 0x60, 0x17, 0x87, - 0x01, 0x01, 0x5f, 0x20, 0x0e, 0x45, 0x53, 0x48, 0x53, 0x4d, 0x43, - 0x56, 0x43, 0x41, 0x32, 0x30, 0x34, 0x30, 0x31, 0x7f, 0x4c, 0x12, - 0x06, 0x09, 0x04, 0x00, 0x7f, 0x00, 0x07, 0x03, 0x01, 0x02, 0x02, - 0x53, 0x05, 0xc0, 0x00, 0x00, 0x00, 0x04, 0x5f, 0x25, 0x06, 0x02, - 0x02, 0x00, 0x02, 0x01, 0x09, 0x5f, 0x24, 0x06, 0x03, 0x00, 0x01, - 0x02, 0x03, 0x01, 0x5f, 0x37, 0x30, 0x26, 0x2d, 0x6f, 0xa6, 0xd0, - 0x52, 0x01, 0xf1, 0x41, 0x1e, 0xe9, 0x33, 0x29, 0x19, 0x42, 0x42, - 0x9b, 0xb0, 0xeb, 0xf7, 0x46, 0x20, 0xcb, 0x81, 0xfe, 0xda, 0xd7, - 0xab, 0x2b, 0xdc, 0xa7, 0x38, 0xf4, 0xc8, 0xec, 0x4c, 0x66, 0xb4, - 0x0a, 0x2d, 0x16, 0xfb, 0xf3, 0x79, 0xe9, 0x93, 0xc8, 0x25 -}; - 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,.data = (uint8_t *)cvca, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.GDO + /* 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 /* 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/sc_hsm.c b/src/hsm/sc_hsm.c index 89178a8..63a08c9 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -29,6 +29,7 @@ #include "mbedtls/cmac.h" #include "mbedtls/hkdf.h" #include "version.h" +#include "cvcerts.h" const uint8_t sc_hsm_aid[] = { 11, @@ -222,6 +223,53 @@ static int cmd_select() { return SW_OK (); } +sc_context_t *create_context() { + sc_context_t *ctx; + sc_context_param_t ctx_opts; + memset(&ctx_opts, 0, sizeof(sc_context_param_t)); + ctx_opts.ver = 0; + ctx_opts.app_name = "hsm2040"; + sc_context_create(&ctx, &ctx_opts); + ctx->debug = 0; + sc_ctx_log_to_file(ctx, "stdout"); + return ctx; +} + +void cvc_init_common(sc_cvc_t *cvc, sc_context_t *ctx) { + memset(cvc, 0, sizeof(sc_cvc_t)); + + size_t lencar = 0, lenchr = 0; + const unsigned char *car = sc_asn1_find_tag(ctx, (const uint8_t *)apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, 0x42, &lencar); + const unsigned char *chr = sc_asn1_find_tag(ctx, (const uint8_t *)apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, 0x5f20, &lenchr); + if (car && lencar > 0) + strlcpy(cvc->car, car, MIN(lencar,sizeof(cvc->car))); + else + strlcpy(cvc->car, "UTSRCACC100001", sizeof(cvc->car)); + if (chr && lenchr > 0) + strlcpy(cvc->chr, chr, MIN(lenchr, sizeof(cvc->chr))); + else + strlcpy(cvc->chr, "ESHSMCVCA00001", sizeof(cvc->chr)); + strlcpy(cvc->outer_car, "ESHSM00001", sizeof(cvc->outer_car)); +} + +int cvc_prepare_signatures(sc_pkcs15_card_t *p15card, sc_cvc_t *cvc, size_t sig_len, uint8_t *hsh) { + uint8_t *cvcbin; + size_t cvclen; + cvc->signatureLen = sig_len; + cvc->signature = (uint8_t *)calloc(1, sig_len); + cvc->outerSignatureLen = 4; + cvc->outerSignature = (uint8_t *)calloc(1, sig_len); + int r = sc_pkcs15emu_sc_hsm_encode_cvc(p15card, cvc, &cvcbin, &cvclen); + if (r != SC_SUCCESS) { + if (cvcbin) + free(cvcbin); + return r; + } + hash(cvcbin, cvclen, hsh); + free(cvcbin); + return HSM_OK; +} + int parse_token_info(const file_t *f, int mode) { char *label = "Pico-HSM"; char *manu = "Pol Henarejos"; @@ -247,6 +295,16 @@ int parse_token_info(const file_t *f, int mode) { return len; } +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; +} static int cmd_list_keys() { @@ -720,53 +778,6 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) { return HSM_OK; } -sc_context_t *create_context() { - sc_context_t *ctx; - sc_context_param_t ctx_opts; - memset(&ctx_opts, 0, sizeof(sc_context_param_t)); - ctx_opts.ver = 0; - ctx_opts.app_name = "hsm2040"; - sc_context_create(&ctx, &ctx_opts); - ctx->debug = 0; - sc_ctx_log_to_file(ctx, "stdout"); - return ctx; -} - -void cvc_init_common(sc_cvc_t *cvc, sc_context_t *ctx) { - memset(cvc, 0, sizeof(sc_cvc_t)); - - size_t lencar = 0, lenchr = 0; - const unsigned char *car = sc_asn1_find_tag(ctx, (const uint8_t *)apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, 0x42, &lencar); - const unsigned char *chr = sc_asn1_find_tag(ctx, (const uint8_t *)apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, 0x5f20, &lenchr); - if (car && lencar > 0) - strlcpy(cvc->car, car, MIN(lencar,sizeof(cvc->car))); - else - strlcpy(cvc->car, "UTCA00001", sizeof(cvc->car)); - if (chr && lenchr > 0) - strlcpy(cvc->chr, chr, MIN(lenchr, sizeof(cvc->chr))); - else - strlcpy(cvc->chr, "ESHSMCVCA00001", sizeof(cvc->chr)); - strlcpy(cvc->outer_car, "ESHSM00001", sizeof(cvc->outer_car)); -} - -int cvc_prepare_signatures(sc_pkcs15_card_t *p15card, sc_cvc_t *cvc, size_t sig_len, uint8_t *hsh) { - uint8_t *cvcbin; - size_t cvclen; - cvc->signatureLen = sig_len; - cvc->signature = (uint8_t *)calloc(1, sig_len); - cvc->outerSignatureLen = 4; - cvc->outerSignature = (uint8_t *)calloc(1, sig_len); - int r = sc_pkcs15emu_sc_hsm_encode_cvc(p15card, cvc, &cvcbin, &cvclen); - if (r != SC_SUCCESS) { - if (cvcbin) - free(cvcbin); - return r; - } - hash(cvcbin, cvclen, hsh); - free(cvcbin); - return HSM_OK; -} - static int cmd_keypair_gen() { uint8_t key_id = P1(apdu); uint8_t auth_key_id = P2(apdu); From b1e83c92e99d0281b4bf469d922ee0a4f1cac862 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 27 Mar 2022 18:15:16 +0200 Subject: [PATCH 2/8] Adding cvcerts and dica Signed-off-by: Pol Henarejos --- src/hsm/cvcerts.h | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 src/hsm/cvcerts.h diff --git a/src/hsm/cvcerts.h b/src/hsm/cvcerts.h new file mode 100644 index 0000000..bdd4089 --- /dev/null +++ b/src/hsm/cvcerts.h @@ -0,0 +1,41 @@ +#ifndef CVCERTS_H_ +#define CVCERTS_H_ + +static const unsigned char termca[] = { + 0xfa, 0x00, + 0x7f,0x21,0x81,0xf6,0x7f,0x4e,0x81,0xbf,0x5f,0x29,0x01,0x00,0x42,0x0e,0x45,0x53, + 0x44,0x56,0x43,0x41,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f,0x49,0x3f,0x06, + 0x0a,0x04,0x00,0x7f,0x00,0x07,0x02,0x02,0x02,0x02,0x03,0x86,0x31,0x04,0x0f,0x89, + 0xb4,0x00,0x97,0x5e,0xdd,0x2d,0x42,0x5a,0xbf,0x85,0xf2,0xfb,0xd3,0x18,0x77,0x9b, + 0x3d,0x85,0x47,0x5e,0x65,0xd4,0xd8,0x58,0x69,0xd3,0x04,0x14,0xb7,0x1f,0x16,0x1e, + 0xb0,0x40,0xd9,0xf7,0xa7,0xe3,0x73,0xa3,0x15,0xc7,0xd9,0x9a,0x51,0xf5,0x5f,0x20, + 0x0e,0x45,0x53,0x54,0x45,0x52,0x4d,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f, + 0x4c,0x12,0x06,0x09,0x04,0x00,0x7f,0x00,0x07,0x03,0x01,0x02,0x02,0x53,0x05,0x00, + 0x00,0x00,0x00,0x04,0x5f,0x25,0x06,0x02,0x02,0x00,0x03,0x02,0x07,0x5f,0x24,0x06, + 0x02,0x03,0x01,0x02,0x03,0x01,0x65,0x2f,0x73,0x2d,0x06,0x09,0x04,0x00,0x7f,0x00, + 0x07,0x03,0x01,0x03,0x01,0x80,0x20,0x68,0x53,0x30,0xc7,0x9a,0x47,0xad,0xfd,0x37, + 0xaa,0xe8,0x53,0xf4,0xbd,0x77,0x3a,0x40,0x89,0x3a,0x79,0x7e,0x3c,0x27,0x18,0x3b, + 0x39,0x67,0xdf,0x8d,0x4f,0xe5,0x99,0x5f,0x37,0x30,0x10,0xff,0x17,0x96,0x0d,0x93, + 0x07,0xc0,0x69,0x8e,0x3a,0xa0,0x44,0x69,0x70,0x88,0xe6,0x9c,0xb4,0xd3,0x16,0x9a, + 0x22,0x4e,0x5c,0x77,0xa9,0xe7,0x83,0x75,0x9a,0xd2,0x7e,0x92,0xf2,0x04,0x93,0xb1, + 0xe9,0xc9,0xe5,0x10,0xc9,0x94,0xff,0x9d,0xe2,0x00 +}; + +static const unsigned char dica[] = { + 0xc9, 0x00, + 0x7f,0x21,0x81,0xc5,0x7f,0x4e,0x81,0x8e,0x5f,0x29,0x01,0x00,0x42,0x0e,0x45,0x53, + 0x43,0x56,0x43,0x41,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f,0x49,0x3f,0x06, + 0x0a,0x04,0x00,0x7f,0x00,0x07,0x02,0x02,0x02,0x02,0x03,0x86,0x31,0x04,0x93,0x7e, + 0xdf,0xf1,0xa6,0xd2,0x40,0x7e,0xb4,0x71,0xb2,0x97,0x50,0xdb,0x7e,0xe1,0x70,0xfb, + 0x6c,0xcd,0x06,0x47,0x2a,0x3e,0x9c,0x8d,0x59,0x56,0x57,0xbe,0x11,0x11,0x0a,0x08, + 0x81,0x54,0xed,0x22,0xc0,0x83,0xac,0xa1,0x2e,0x39,0x7b,0xd4,0x65,0x1f,0x5f,0x20, + 0x0e,0x45,0x53,0x44,0x56,0x43,0x41,0x48,0x53,0x4d,0x30,0x30,0x30,0x30,0x31,0x7f, + 0x4c,0x12,0x06,0x09,0x04,0x00,0x7f,0x00,0x07,0x03,0x01,0x02,0x02,0x53,0x05,0x80, + 0x00,0x00,0x00,0x04,0x5f,0x25,0x06,0x02,0x02,0x00,0x03,0x02,0x07,0x5f,0x24,0x06, + 0x02,0x05,0x01,0x02,0x03,0x01,0x5f,0x37,0x30,0x8b,0xb2,0x01,0xb6,0x24,0xfe,0xe5, + 0x4e,0x65,0x3a,0x02,0xa2,0xb2,0x27,0x2d,0x3d,0xb4,0xb0,0xc9,0xdd,0xbf,0x10,0x6d, + 0x99,0x49,0x46,0xd6,0xd0,0x72,0xc1,0xf3,0x4c,0xab,0x4f,0x32,0x14,0x7c,0xb0,0x99, + 0xb7,0x33,0x70,0xd6,0x00,0xff,0x73,0x0c,0x5d +}; + +#endif From 09164893889a7f1faf3e4c38986b6a73259d0119 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 27 Mar 2022 18:53:41 +0200 Subject: [PATCH 3/8] Initialization now returns free memory if no parameters are given. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 121 +++++++++++-------- src/usb/ccid-types.h | 273 ------------------------------------------- 2 files changed, 71 insertions(+), 323 deletions(-) delete mode 100644 src/usb/ccid-types.h diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 63a08c9..95b769a 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -516,62 +516,83 @@ static int cmd_challenge() { return SW_OK(); } +extern char __StackLimit; +int heapLeft() { + char *p = malloc(256); // try to avoid undue fragmentation + int left = &__StackLimit - p; + free(p); + return left; +} + static int cmd_initialize() { - initialize_flash(true); - scan_flash(); - dkeks = 0; - const uint8_t *p = apdu.cmd_apdu_data; - while (p-apdu.cmd_apdu_data < apdu.cmd_apdu_data_len) { - uint8_t tag = *p++; - uint8_t tag_len = *p++; - if (tag == 0x80) { //options - } - else if (tag == 0x81) { //user pin - if (file_pin1 && file_pin1->data) { - uint8_t dhash[33]; - dhash[0] = tag_len; - double_hash_pin(p, tag_len, dhash+1); - flash_write_data_to_file(file_pin1, dhash, sizeof(dhash)); - hash_multi(p, tag_len, session_pin); - has_session_pin = true; - } - } - else if (tag == 0x82) { //user pin - if (file_sopin && file_sopin->data) { - uint8_t dhash[33]; - dhash[0] = tag_len; - double_hash_pin(p, tag_len, dhash+1); - flash_write_data_to_file(file_sopin, dhash, sizeof(dhash)); - hash_multi(p, tag_len, session_sopin); - has_session_sopin = true; - } - } - else if (tag == 0x91) { //user pin - file_t *tf = search_by_fid(0x1082, NULL, SPECIFY_EF); - if (tf && tf->data) { - flash_write_data_to_file(tf, p, tag_len); + if (apdu.cmd_apdu_data_len > 0) { + initialize_flash(true); + scan_flash(); + dkeks = 0; + const uint8_t *p = apdu.cmd_apdu_data; + while (p-apdu.cmd_apdu_data < apdu.cmd_apdu_data_len) { + uint8_t tag = *p++; + uint8_t tag_len = *p++; + if (tag == 0x80) { //options } - if (file_retries_pin1 && file_retries_pin1->data) { - flash_write_data_to_file(file_retries_pin1, p, tag_len); + else if (tag == 0x81) { //user pin + if (file_pin1 && file_pin1->data) { + uint8_t dhash[33]; + dhash[0] = tag_len; + double_hash_pin(p, tag_len, dhash+1); + flash_write_data_to_file(file_pin1, dhash, sizeof(dhash)); + hash_multi(p, tag_len, session_pin); + has_session_pin = true; + } } + else if (tag == 0x82) { //user pin + if (file_sopin && file_sopin->data) { + uint8_t dhash[33]; + dhash[0] = tag_len; + double_hash_pin(p, tag_len, dhash+1); + flash_write_data_to_file(file_sopin, dhash, sizeof(dhash)); + hash_multi(p, tag_len, session_sopin); + has_session_sopin = true; + } + } + else if (tag == 0x91) { //user pin + file_t *tf = search_by_fid(0x1082, NULL, SPECIFY_EF); + if (tf && tf->data) { + flash_write_data_to_file(tf, p, tag_len); + } + if (file_retries_pin1 && file_retries_pin1->data) { + flash_write_data_to_file(file_retries_pin1, p, tag_len); + } + } + else if (tag == 0x92) { + dkeks = *p; + current_dkeks = 0; + } + p += tag_len; } - else if (tag == 0x92) { - dkeks = *p; - current_dkeks = 0; - } - p += tag_len; - } - p = random_bytes_get(32); - memset(tmp_dkek, 0, sizeof(tmp_dkek)); - memcpy(tmp_dkek, p, IV_SIZE); - if (dkeks == 0) { p = random_bytes_get(32); - memcpy(tmp_dkek+IV_SIZE, p, 32); - encrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32); - file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF); - flash_write_data_to_file(tf, tmp_dkek, sizeof(tmp_dkek)); + memset(tmp_dkek, 0, sizeof(tmp_dkek)); + memcpy(tmp_dkek, p, IV_SIZE); + if (dkeks == 0) { + p = random_bytes_get(32); + memcpy(tmp_dkek+IV_SIZE, p, 32); + encrypt(session_pin, tmp_dkek, tmp_dkek+IV_SIZE, 32); + file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF); + flash_write_data_to_file(tf, tmp_dkek, sizeof(tmp_dkek)); + } + low_flash_available(); + } + else { //free memory bytes request + int heap_left = heapLeft(); + res_APDU[0] = ((heap_left >> 24) & 0xff); + res_APDU[1] = ((heap_left >> 16) & 0xff); + res_APDU[2] = ((heap_left >> 8) & 0xff); + res_APDU[3] = ((heap_left >> 0) & 0xff); + res_APDU[4] = 0; + res_APDU[5] = HSM_VERSION_MAJOR; + res_APDU[6] = HSM_VERSION_MINOR; + res_APDU_size = 7; } - low_flash_available(); return SW_OK(); } diff --git a/src/usb/ccid-types.h b/src/usb/ccid-types.h deleted file mode 100644 index a74240a..0000000 --- a/src/usb/ccid-types.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Copyright (C) 2009-2015 Frank Morgner - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - */ -/** - * @file - */ -#ifndef _CCID_TYPES_H -#define _CCID_TYPES_H - -#include "pico/types.h" -#include "hardware/structs/usb.h" - -#define USB_REQ_CCID 0xA1 - -#define CCID_CONTROL_ABORT 0x01 -#define CCID_CONTROL_GET_CLOCK_FREQUENCIES 0x02 -#define CCID_CONTROL_GET_DATA_RATES 0x03 - -#define CCID_OPERATION_VERIFY 0x00; -#define CCID_OPERATION_MODIFY 0x01; -#define CCID_ENTRY_VALIDATE 0x02 - -#define CCID_BERROR_CMD_ABORTED 0xff /** Host aborted the current activity */ -#define CCID_BERROR_ICC_MUTE 0xfe /** CCID timed out while talking to the ICC */ -#define CCID_BERROR_XFR_PARITY_ERROR 0xfd /** Parity error while talking to the ICC */ -#define CCID_BERROR_XFR_OVERRUN 0xfc /** Overrun error while talking to the ICC */ -#define CCID_BERROR_HW_ERROR 0xfb /** An all inclusive hardware error occurred */ -#define CCID_BERROR_BAD_ATR_TS 0xf -#define CCID_BERROR_BAD_ATR_TCK 0xf -#define CCID_BERROR_ICC_PROTOCOL_NOT_SUPPORTED 0xf6 -#define CCID_BERROR_ICC_CLASS_NOT_SUPPORTED 0xf5 -#define CCID_BERROR_PROCEDURE_BYTE_CONFLICT 0xf4 -#define CCID_BERROR_DEACTIVATED_PROTOCOL 0xf3 -#define CCID_BERROR_BUSY_WITH_AUTO_SEQUENCE 0xf2 /** Automatic Sequence Ongoing */ -#define CCID_BERROR_PIN_TIMEOUT 0xf0 -#define CCID_BERROR_PIN_CANCELLED 0xef -#define CCID_BERROR_CMD_SLOT_BUSY 0xe0 /** A second command was sent to a slot which was already processing a command. */ -#define CCID_BERROR_CMD_NOT_SUPPORTED 0x00 -#define CCID_BERROR_OK 0x00 - -#define CCID_BSTATUS_OK_ACTIVE 0x00 /** No error. An ICC is present and active */ -#define CCID_BSTATUS_OK_INACTIVE 0x01 /** No error. ICC is present and inactive */ -#define CCID_BSTATUS_OK_NOICC 0x02 /** No error. No ICC is present */ -#define CCID_BSTATUS_ERROR_ACTIVE 0x40 /** Failed. An ICC is present and active */ -#define CCID_BSTATUS_ERROR_INACTIVE 0x41 /** Failed. ICC is present and inactive */ -#define CCID_BSTATUS_ERROR_NOICC 0x42 /** Failed. No ICC is present */ - -#define CCID_WLEVEL_DIRECT __constant_cpu_to_le16(0) /** APDU begins and ends with this command */ -#define CCID_WLEVEL_CHAIN_NEXT_XFRBLOCK __constant_cpu_to_le16(1) /** APDU begins with this command, and continue in the next PC_to_RDR_XfrBlock */ -#define CCID_WLEVEL_CHAIN_END __constant_cpu_to_le16(2) /** abData field continues a command APDU and ends the APDU command */ -#define CCID_WLEVEL_CHAIN_CONTINUE __constant_cpu_to_le16(3) /** abData field continues a command APDU and another block is to follow */ -#define CCID_WLEVEL_RESPONSE_IN_DATABLOCK __constant_cpu_to_le16(0x10) /** empty abData field, continuation of response APDU is expected in the next RDR_to_PC_DataBlock */ - -#define CCID_PIN_ENCODING_BIN 0x00 -#define CCID_PIN_ENCODING_BCD 0x01 -#define CCID_PIN_ENCODING_ASCII 0x02 -#define CCID_PIN_UNITS_BYTES 0x80 -#define CCID_PIN_JUSTIFY_RIGHT 0x04 -#define CCID_PIN_CONFIRM_NEW 0x01 -#define CCID_PIN_INSERT_OLD 0x02 -#define CCID_PIN_NO_MSG 0x00 -#define CCID_PIN_MSG1 0x01 -#define CCID_PIN_MSG2 0x02 -#define CCID_PIN_MSG_REF 0x03 -#define CCID_PIN_MSG_DEFAULT 0xff - -#define CCID_SLOTS_UNCHANGED 0x00 -#define CCID_SLOT1_CARD_PRESENT 0x01 -#define CCID_SLOT1_CHANGED 0x02 -#define CCID_SLOT2_CARD_PRESENT 0x04 -#define CCID_SLOT2_CHANGED 0x08 -#define CCID_SLOT3_CARD_PRESENT 0x10 -#define CCID_SLOT3_CHANGED 0x20 -#define CCID_SLOT4_CARD_PRESENT 0x40 -#define CCID_SLOT4_CHANGED 0x80 - -#define CCID_EXT_APDU_MAX (4 + 3 + 0xffff + 3) -#define CCID_SHORT_APDU_MAX (4 + 1 + 0xff + 1) - -typedef struct TU_ATTR_PACKED { - uint8_t bLength; - uint8_t bDescriptorType; - uint16_t bcdCCID; - uint8_t bMaxSlotIndex; - uint8_t bVoltageSupport; - uint32_t dwProtocols; - uint32_t dwDefaultClock; - uint32_t dwMaximumClock; - uint8_t bNumClockSupport; - uint32_t dwDataRate; - uint32_t dwMaxDataRate; - uint8_t bNumDataRatesSupported; - uint32_t dwMaxIFSD; - uint32_t dwSynchProtocols; - uint32_t dwMechanical; - uint32_t dwFeatures; - uint32_t dwMaxCCIDMessageLength; - uint8_t bClassGetResponse; - uint8_t bclassEnvelope; - uint16_t wLcdLayout; - uint8_t bPINSupport; - uint8_t bMaxCCIDBusySlots; -} class_desc_ccid_t; - -struct abProtocolDataStructure_T0 { - uint8_t bmFindexDindex; - uint8_t bmTCCKST0; - uint8_t bGuardTimeT0; - uint8_t bWaitingIntegerT0; - uint8_t bClockStop; -} __packed; - -struct abProtocolDataStructure_T1 { - uint8_t bmFindexDindex; - uint8_t bmTCCKST1; - uint8_t bGuardTimeT1; - uint8_t bWaitingIntegersT1; - uint8_t bClockStop; - uint8_t bIFSC; - uint8_t bNadValue; -} __packed; - -struct abPINDataStucture_Verification { - uint8_t bTimeOut; - uint8_t bmFormatString; - uint8_t bmPINBlockString; - uint8_t bmPINLengthFormat; - uint16_t wPINMaxExtraDigit; - uint8_t bEntryValidationCondition; - uint8_t bNumberMessage; - uint16_t wLangId; - uint8_t bMsgIndex; - uint8_t bTeoPrologue1; - uint16_t bTeoPrologue2; -} __packed; - -struct abPINDataStucture_Modification { - uint8_t bTimeOut; - uint8_t bmFormatString; - uint8_t bmPINBlockString; - uint8_t bmPINLengthFormat; - uint8_t bInsertionOffsetOld; - uint8_t bInsertionOffsetNew; - uint16_t wPINMaxExtraDigit; - uint8_t bConfirmPIN; - uint8_t bEntryValidationCondition; - uint8_t bNumberMessage; - uint16_t wLangId; - uint8_t bMsgIndex1; -} __packed; - -struct PC_to_RDR_XfrBlock { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t bBWI; - uint16_t wLevelParameter; -} __packed; - -struct PC_to_RDR_IccPowerOff { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t abRFU1; - uint16_t abRFU2; -} __packed; - -struct PC_to_RDR_GetSlotStatus { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t abRFU1; - uint16_t abRFU2; -} __packed; - -struct PC_to_RDR_GetParameters { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t abRFU1; - uint16_t abRFU2; -} __packed; - -struct PC_to_RDR_ResetParameters { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t abRFU1; - uint16_t abRFU2; -} __packed; - -struct PC_to_RDR_SetParameters { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t bProtocolNum; - uint16_t abRFU; -} __packed; - -struct PC_to_RDR_Secure { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t bBWI; - uint16_t wLevelParameter; -} __packed; - -struct PC_to_RDR_IccPowerOn { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t bPowerSelect; - uint16_t abRFU; -} __packed; - -struct RDR_to_PC_SlotStatus { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t bStatus; - uint8_t bError; - uint8_t bClockStatus; -} __packed; - -struct RDR_to_PC_DataBlock { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t bStatus; - uint8_t bError; - uint8_t bChainParameter; -} __packed; - -struct RDR_to_PC_Parameters { - uint8_t bMessageType; - uint32_t dwLength; - uint8_t bSlot; - uint8_t bSeq; - uint8_t bStatus; - uint8_t bError; - uint8_t bProtocolNum; -} __packed; - -struct RDR_to_PC_NotifySlotChange { - uint8_t bMessageType; - uint8_t bmSlotICCState; /* we support 1 slots, so we need 2*1 bits = 1 byte */ -} __packed; - -#endif From c6d87756ab7df9e19a1e466d7484692cf8cb6a8f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 27 Mar 2022 19:00:21 +0200 Subject: [PATCH 4/8] Adding SOPIN verification. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 95b769a..080ff2d 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -479,6 +479,12 @@ static int cmd_verify() { return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_pin1->data+2)); } else if (p2 == 0x88) { //SOPin + if (apdu.cmd_apdu_data_len > 0) { + return check_pin(file_sopin, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); + } + if (file_read_uint8(file_retries_sopin->data+2) == 0) + return SW_PIN_BLOCKED(); + return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_sopin->data+2)); } return SW_REFERENCE_NOT_FOUND(); } From c7abd1a0679af1ea8368694b147254a00d7354f6 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 27 Mar 2022 20:27:10 +0200 Subject: [PATCH 5/8] Adding DKEK report Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 080ff2d..3119813 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -551,7 +551,7 @@ static int cmd_initialize() { has_session_pin = true; } } - else if (tag == 0x82) { //user pin + else if (tag == 0x82) { //sopin pin if (file_sopin && file_sopin->data) { uint8_t dhash[33]; dhash[0] = tag_len; @@ -561,7 +561,7 @@ static int cmd_initialize() { has_session_sopin = true; } } - else if (tag == 0x91) { //user pin + else if (tag == 0x91) { //retries user pin file_t *tf = search_by_fid(0x1082, NULL, SPECIFY_EF); if (tf && tf->data) { flash_write_data_to_file(tf, p, tag_len); @@ -656,9 +656,11 @@ void generic_hash(mbedtls_md_type_t md, const uint8_t *input, size_t len, uint8_ } static int cmd_import_dkek() { - if (dkeks == 0) - return SW_COMMAND_NOT_ALLOWED(); - if (has_session_pin == false) + //if (dkeks == 0) + // return SW_COMMAND_NOT_ALLOWED(); + if (P1(apdu) != 0x0 || P2(apdu) != 0x0) + return SW_INCORRECT_P1P2(); + if (has_session_pin == false && apdu.cmd_apdu_data_len > 0) return SW_CONDITIONS_NOT_SATISFIED(); file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF); if (!authenticate_action(get_parent(tf), ACL_OP_CREATE_EF)) { From 450ec5dec19fa559360b88a858ba08c19ecc3de0 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 27 Mar 2022 20:47:11 +0200 Subject: [PATCH 6/8] Also list PRKD files. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 3119813..7689d2a 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -147,6 +147,9 @@ static int cmd_select() { if (apdu.cmd_apdu_data_len >= 2) fid = get_uint16_t(apdu.cmd_apdu_data, 0); + + //if ((fid & 0xff00) == (KEY_PREFIX << 8)) + // fid = (PRKD_PREFIX << 8) | (fid & 0xff); if ((fid & 0xff00) == (PRKD_PREFIX << 8)) { if (!(pe = search_dynamic_file(fid))) @@ -312,6 +315,8 @@ static int cmd_list_keys() for (int i = 0; i < dynamic_files; i++) { file_t *f = &dynamic_file[i]; if ((f->fid & 0xff00) == (PRKD_PREFIX << 8)) { + res_APDU[res_APDU_size++] = PRKD_PREFIX; + res_APDU[res_APDU_size++] = f->fid & 0xff; res_APDU[res_APDU_size++] = KEY_PREFIX; res_APDU[res_APDU_size++] = f->fid & 0xff; } From cd4ceb0a61c34cfa70167b3d83f44e480a935b56 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 28 Mar 2022 01:37:19 +0200 Subject: [PATCH 7/8] Fix returning current dkeks when the device is initialized without dkeks. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 7689d2a..060833d 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -539,7 +539,7 @@ static int cmd_initialize() { if (apdu.cmd_apdu_data_len > 0) { initialize_flash(true); scan_flash(); - dkeks = 0; + dkeks = current_dkeks = 0; const uint8_t *p = apdu.cmd_apdu_data; while (p-apdu.cmd_apdu_data < apdu.cmd_apdu_data_len) { uint8_t tag = *p++; @@ -577,7 +577,6 @@ static int cmd_initialize() { } else if (tag == 0x92) { dkeks = *p; - current_dkeks = 0; } p += tag_len; } From 69a406832de552e087ab7a552f337c7fb863f4fc Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 28 Mar 2022 01:37:36 +0200 Subject: [PATCH 8/8] Adding hsm initializing options Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h index d6be562..20113c9 100644 --- a/src/hsm/sc_hsm.h +++ b/src/hsm/sc_hsm.h @@ -84,6 +84,14 @@ extern const uint8_t sc_hsm_aid[]; #define ALGO_AES_CMAC 0x18 #define ALGO_AES_DERIVE 0x99 +#define HSM_OPT_RRC 0x1 +#define HSM_OPT_TRANSPORT_PIN 0x2 +#define HSM_OPT_SESSION_PIN 0x4 +#define HSM_OPT_SESSION_PIN_EXPL 0xC +#define HSM_OPT_REPLACE_PKA 0x8 +#define HSM_OPT_COMBINED_AUTH 0x10 +#define HSM_OPT_RRC_RESET_ONLY 0x20 + extern int pin_reset_retries(const file_t *pin, bool); extern int pin_wrong_retry(const file_t *pin);