From 86e38419ac11a07bf886330dc2205ebcfdd3a132 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 13:17:16 +0200 Subject: [PATCH 01/17] PIN remaining tries only returned when user is not logged in. If so, it returns always OK. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index c0a12f9..d0927d3 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -439,6 +439,8 @@ static int cmd_verify() { } if (file_read_uint8(file_retries_pin1->data+2) == 0) return SW_PIN_BLOCKED(); + if (isUserAuthenticated && has_session_pin) + return SW_OK(); return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_pin1->data+2)); } else if (p2 == 0x88) { //SOPin From ad66170379426f9d669a24e568968e011412982d Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 13:18:56 +0200 Subject: [PATCH 02/17] Also for SOPIN. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index d0927d3..4d79af2 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -449,6 +449,8 @@ static int cmd_verify() { } if (file_read_uint8(file_retries_sopin->data+2) == 0) return SW_PIN_BLOCKED(); + if (isUserAuthenticated && has_session_pin) + return SW_OK(); return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_sopin->data+2)); } return SW_REFERENCE_NOT_FOUND(); From 923e05a36c525ebfd974e02c97def2583282d900 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 14:30:50 +0200 Subject: [PATCH 03/17] Revert "Also for SOPIN." This reverts commit ad66170379426f9d669a24e568968e011412982d. --- src/hsm/sc_hsm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 4d79af2..d0927d3 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -449,8 +449,6 @@ static int cmd_verify() { } if (file_read_uint8(file_retries_sopin->data+2) == 0) return SW_PIN_BLOCKED(); - if (isUserAuthenticated && has_session_pin) - return SW_OK(); return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_sopin->data+2)); } return SW_REFERENCE_NOT_FOUND(); From 33a2222cd8ca2e82672ad9eab32d8bd078c07412 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 14:30:50 +0200 Subject: [PATCH 04/17] Revert "PIN remaining tries only returned when user is not logged in. If so, it returns always OK." This reverts commit 86e38419ac11a07bf886330dc2205ebcfdd3a132. --- src/hsm/sc_hsm.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index d0927d3..c0a12f9 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -439,8 +439,6 @@ static int cmd_verify() { } if (file_read_uint8(file_retries_pin1->data+2) == 0) return SW_PIN_BLOCKED(); - if (isUserAuthenticated && has_session_pin) - return SW_OK(); return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_pin1->data+2)); } else if (p2 == 0x88) { //SOPin From bfc12d685643dc683c038c373f73a734409e91cb Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 18:27:00 +0200 Subject: [PATCH 05/17] Renaming files Signed-off-by: Pol Henarejos --- CMakeLists.txt | 2 +- src/hsm/{hash_utils.c => crypto_utils.c} | 2 +- src/hsm/{hash_utils.h => crypto_utils.h} | 4 ++-- src/hsm/dkek.c | 2 +- src/hsm/sc_hsm.c | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) rename src/hsm/{hash_utils.c => crypto_utils.c} (99%) rename src/hsm/{hash_utils.h => crypto_utils.h} (97%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 49b0567..9e8d413 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -51,7 +51,7 @@ target_sources(pico_hsm PUBLIC ${CMAKE_CURRENT_LIST_DIR}/src/fs/low_flash.c ${CMAKE_CURRENT_LIST_DIR}/src/rng/random.c ${CMAKE_CURRENT_LIST_DIR}/src/rng/neug.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/hash_utils.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/crypto_utils.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/dkek.c ${CMAKE_CURRENT_LIST_DIR}/mbedtls/library/sha256.c diff --git a/src/hsm/hash_utils.c b/src/hsm/crypto_utils.c similarity index 99% rename from src/hsm/hash_utils.c rename to src/hsm/crypto_utils.c index 9a665df..4df1811 100644 --- a/src/hsm/hash_utils.c +++ b/src/hsm/crypto_utils.c @@ -19,7 +19,7 @@ #include "mbedtls/md.h" #include "mbedtls/sha256.h" #include "mbedtls/aes.h" -#include "hash_utils.h" +#include "crypto_utils.h" #include "sc_hsm.h" #include "libopensc/card-sc-hsm.h" diff --git a/src/hsm/hash_utils.h b/src/hsm/crypto_utils.h similarity index 97% rename from src/hsm/hash_utils.h rename to src/hsm/crypto_utils.h index c411812..3b686c1 100644 --- a/src/hsm/hash_utils.h +++ b/src/hsm/crypto_utils.h @@ -15,8 +15,8 @@ * along with this program. If not, see . */ -#ifndef _HASH_UTILS_H_ -#define _HASH_UTILS_H_ +#ifndef _CRYPTO_UTILS_H_ +#define _CRYPTO_UTILS_H_ #include "stdlib.h" #include "pico/stdlib.h" diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 0cd5f06..153aa60 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -20,7 +20,7 @@ #include "stdlib.h" #include "pico/stdlib.h" #include "dkek.h" -#include "hash_utils.h" +#include "crypto_utils.h" #include "random.h" #include "sc_hsm.h" #include "mbedtls/md.h" diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index c0a12f9..7f9b416 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -30,7 +30,7 @@ #include "mbedtls/hkdf.h" #include "version.h" #include "cvcerts.h" -#include "hash_utils.h" +#include "crypto_utils.h" #include "dkek.h" const uint8_t sc_hsm_aid[] = { From f9ffd39661c538fd43e5f87ab663a0279197d3b9 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 18:56:42 +0200 Subject: [PATCH 06/17] Adding EF_DEVOPS to store the device options during the initialization. Signed-off-by: Pol Henarejos --- src/fs/file.c | 19 ++++++++++--------- src/fs/file.h | 1 + src/hsm/sc_hsm.c | 14 ++++++++++++-- 3 files changed, 23 insertions(+), 11 deletions(-) diff --git a/src/fs/file.c b/src/fs/file.c index 39d0fea..ad2af10 100644 --- a/src/fs/file.c +++ b/src/fs/file.c @@ -99,15 +99,16 @@ file_t file_entries[] = { /* 13 */ { .fid = 0x1089 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //max retries PIN (SOPIN) /* 14 */ { .fid = 0x108A , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (SOPIN) /* 15 */ { .fid = EF_DKEK , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //DKEK - /* 16 */ { .fid = EF_PRKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PrKDFs - /* 17 */ { .fid = EF_PUKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PuKDFs - /* 18 */ { .fid = EF_CDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.CDFs - /* 19 */ { .fid = EF_AODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.AODFs - /* 20 */ { .fid = EF_DODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DODFs - /* 21 */ { .fid = EF_SKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.SKDFs - ///* 22 */ { .fid = 0x0000, .parent = 0, .name = openpgpcard_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, - /* 23 */ { .fid = 0x0000, .parent = 5, .name = sc_hsm_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, - /* 24 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end + /* 16 */ { .fid = EF_DEVOPS , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //Device options + /* 17 */ { .fid = EF_PRKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PrKDFs + /* 18 */ { .fid = EF_PUKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PuKDFs + /* 19 */ { .fid = EF_CDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.CDFs + /* 20 */ { .fid = EF_AODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.AODFs + /* 21 */ { .fid = EF_DODFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.DODFs + /* 22 */ { .fid = EF_SKDFS , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.SKDFs + ///* 23 */ { .fid = 0x0000, .parent = 0, .name = openpgpcard_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, + /* 24 */ { .fid = 0x0000, .parent = 5, .name = sc_hsm_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, + /* 25 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL, .ef_structure = 0, .acl = {0} } //end }; const file_t *MF = &file_entries[0]; diff --git a/src/fs/file.h b/src/fs/file.h index c87db66..5b4175f 100644 --- a/src/fs/file.h +++ b/src/fs/file.h @@ -60,6 +60,7 @@ #define EF_AODFS 0x6043 #define EF_DODFS 0x6044 #define EF_SKDFS 0x6045 +#define EF_DEVOPS 0x100E #define MAX_DEPTH 4 diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 7f9b416..37c2d50 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -169,10 +169,18 @@ static int cmd_select() { if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) { process_fci(pe); if (pe == file_sc_hsm) { + file_t *ef = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); res_APDU[res_APDU_size++] = 0x85; res_APDU[res_APDU_size++] = 4; - res_APDU[res_APDU_size++] = 0xff; //options - res_APDU[res_APDU_size++] = 0xff; + if (ef && ef->data) { + uint16_t opts = file_read_uint16(ef->data+2); + res_APDU[res_APDU_size++] = opts >> 8; //options + res_APDU[res_APDU_size++] = opts & 0xff; + } + else { + res_APDU[res_APDU_size++] = 0x0; + res_APDU[res_APDU_size++] = 0x0; + } res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR; res_APDU[res_APDU_size++] = HSM_VERSION_MINOR; res_APDU[1] = res_APDU_size-2; @@ -503,6 +511,8 @@ static int cmd_initialize() { uint8_t tag = *p++; uint8_t tag_len = *p++; if (tag == 0x80) { //options + file_t *tf = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); + flash_write_data_to_file(tf, p, tag_len); } else if (tag == 0x81) { //user pin if (file_pin1 && file_pin1->data) { From c9b32ab5d045adf151f4a65a878f69347745bf32 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 18:59:54 +0200 Subject: [PATCH 07/17] Fix return pin blocked sw code. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 2 +- src/hsm/sc_hsm.h | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 37c2d50..9880c51 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -1046,7 +1046,7 @@ static int cmd_delete_file() { if (apdu.cmd_apdu_data_len == 0) { ef = currentEF; if (!(ef = search_dynamic_file(ef->fid))) - return SW_FILE_INVALID(); + return SW_FILE_NOT_FOUND(); } else { uint16_t fid = (apdu.cmd_apdu_data[0] << 8) | apdu.cmd_apdu_data[1]; diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h index c2a4f9f..6ac44f1 100644 --- a/src/hsm/sc_hsm.h +++ b/src/hsm/sc_hsm.h @@ -26,7 +26,6 @@ extern const uint8_t sc_hsm_aid[]; #define SW_BYTES_REMAINING_00() set_res_sw (0x61, 0x00) #define SW_WARNING_STATE_UNCHANGED() set_res_sw (0x62, 0x00) -#define SW_PIN_BLOCKED() set_res_sw (0x63, 0x00) #define SW_EXEC_ERROR() set_res_sw (0x64, 0x00) #define SW_MEMORY_FAILURE() set_res_sw (0x65, 0x81) #define SW_WRONG_LENGTH() set_res_sw (0x67, 0x00) @@ -34,7 +33,7 @@ extern const uint8_t sc_hsm_aid[]; #define SW_LOGICAL_CHANNEL_NOT_SUPPORTED() set_res_sw (0x68, 0x81) #define SW_SECURE_MESSAGING_NOT_SUPPORTED() set_res_sw (0x68, 0x82) #define SW_SECURITY_STATUS_NOT_SATISFIED() set_res_sw (0x69, 0x82) -#define SW_FILE_INVALID() set_res_sw (0x69, 0x83) +#define SW_PIN_BLOCKED() set_res_sw (0x69, 0x83) #define SW_DATA_INVALID() set_res_sw (0x69, 0x84) #define SW_CONDITIONS_NOT_SATISFIED() set_res_sw (0x69, 0x85) #define SW_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86) From 0cc656c6c0fe023dc9c9f84d1d63fdd665c10757 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 19:12:56 +0200 Subject: [PATCH 08/17] Adding transport PIN option. It does not allow to authenticate and returns sw code 0x6984 Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 9880c51..0953d37 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -92,6 +92,14 @@ void select_file(file_t *pe) { //sc_hsm_unload(); //reset auth status } } + +uint16_t get_device_options() { + file_t *ef = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); + if (ef && ef->data) + return file_read_uint16(ef->data+2); + return 0x0; +} + static int cmd_select() { uint8_t p1 = P1(apdu); uint8_t p2 = P2(apdu); @@ -169,18 +177,11 @@ static int cmd_select() { if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) { process_fci(pe); if (pe == file_sc_hsm) { - file_t *ef = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); res_APDU[res_APDU_size++] = 0x85; res_APDU[res_APDU_size++] = 4; - if (ef && ef->data) { - uint16_t opts = file_read_uint16(ef->data+2); - res_APDU[res_APDU_size++] = opts >> 8; //options - res_APDU[res_APDU_size++] = opts & 0xff; - } - else { - res_APDU[res_APDU_size++] = 0x0; - res_APDU[res_APDU_size++] = 0x0; - } + uint16_t opts = get_device_options(); + res_APDU[res_APDU_size++] = opts >> 8; + res_APDU[res_APDU_size++] = opts & 0xff; res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR; res_APDU[res_APDU_size++] = HSM_VERSION_MINOR; res_APDU[1] = res_APDU_size-2; @@ -442,6 +443,11 @@ static int cmd_verify() { return SW_WRONG_P1P2(); uint8_t qualifier = p2&0x1f; if (p2 == 0x81) { //UserPin + uint16_t opts = get_device_options(); + if (opts & HSM_OPT_TRANSPORT_PIN) + return SW_DATA_INVALID(); + if (file_read_uint8(file_pin1->data+2) == 0) //not initialized + return SW_REFERENCE_NOT_FOUND(); if (apdu.cmd_apdu_data_len > 0) { return check_pin(file_pin1, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); } @@ -450,6 +456,8 @@ static int cmd_verify() { return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_pin1->data+2)); } else if (p2 == 0x88) { //SOPin + if (file_read_uint8(file_sopin->data+2) == 0) //not initialized + return SW_REFERENCE_NOT_FOUND(); if (apdu.cmd_apdu_data_len > 0) { return check_pin(file_sopin, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len); } From 4400eba9741c1fd768f20fd2556645fefb6cfb81 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 19:31:02 +0200 Subject: [PATCH 09/17] Fix returning kcv Signed-off-by: Pol Henarejos --- src/hsm/dkek.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c index 153aa60..cd89c65 100644 --- a/src/hsm/dkek.c +++ b/src/hsm/dkek.c @@ -88,6 +88,7 @@ int dkek_kcv(uint8_t *kcv) { //kcv 8 bytes hash256(dkek+IV_SIZE, 32, hsh); release_dkek(); memcpy(kcv, hsh, 8); + return HSM_OK; } int dkek_kenc(uint8_t *kenc) { //kenc 32 bytes From d5378ffa417c6eb1d5f41a28ad926029cf5e6d37 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 19:31:22 +0200 Subject: [PATCH 10/17] If has_session_pin is true, it returns sw_ok Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 0953d37..1b58275 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -409,11 +409,12 @@ int pin_wrong_retry(const file_t *pin) { int check_pin(const file_t *pin, const uint8_t *data, size_t len) { if (!pin) - return SW_FILE_NOT_FOUND(); + return SW_REFERENCE_NOT_FOUND(); if (!pin->data) { return SW_REFERENCE_NOT_FOUND(); } isUserAuthenticated = false; + has_session_pin = has_session_sopin = false; uint8_t dhash[32]; double_hash_pin(data, len, dhash); if (sizeof(dhash) != file_read_uint16(pin->data)-1) //1 byte for pin len @@ -431,7 +432,10 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len) { return SW_MEMORY_FAILURE(); isUserAuthenticated = true; hash_multi(data, len, session_pin); - has_session_pin = true; + if (pin == file_pin1) + has_session_pin = true; + else if (pin == file_sopin) + has_session_sopin = true; return SW_OK(); } @@ -453,6 +457,8 @@ static int cmd_verify() { } if (file_read_uint8(file_retries_pin1->data+2) == 0) return SW_PIN_BLOCKED(); + if (has_session_pin) + return SW_OK(); return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_pin1->data+2)); } else if (p2 == 0x88) { //SOPin @@ -463,6 +469,8 @@ static int cmd_verify() { } if (file_read_uint8(file_retries_sopin->data+2) == 0) return SW_PIN_BLOCKED(); + if (has_session_sopin) + return SW_OK(); return set_res_sw(0x63, 0xc0 | file_read_uint8(file_retries_sopin->data+2)); } return SW_REFERENCE_NOT_FOUND(); From 853b8f29a2593b0b86613390f88259fbdb6319fe Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 19:31:56 +0200 Subject: [PATCH 11/17] Fix returning kcv when pin is not provided. It always return 0x0 Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 1b58275..0d6dcb4 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -607,6 +607,7 @@ static int cmd_import_dkek() { } } + memset(res_APDU,0,10); res_APDU[0] = dkeks; res_APDU[1] = dkeks-current_dkeks; dkek_kcv(res_APDU+2); From c9855f7214040b3931d1e8d2e4c5a7262df1581b Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Thu, 31 Mar 2022 19:43:33 +0200 Subject: [PATCH 12/17] Fix displaying device options. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 0d6dcb4..95f9359 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -96,7 +96,7 @@ void select_file(file_t *pe) { uint16_t get_device_options() { file_t *ef = search_by_fid(EF_DEVOPS, NULL, SPECIFY_EF); if (ef && ef->data) - return file_read_uint16(ef->data+2); + return (file_read_uint8(ef->data+2) << 8) | file_read_uint8(ef->data+3); return 0x0; } @@ -180,8 +180,8 @@ static int cmd_select() { res_APDU[res_APDU_size++] = 0x85; res_APDU[res_APDU_size++] = 4; uint16_t opts = get_device_options(); - res_APDU[res_APDU_size++] = opts >> 8; res_APDU[res_APDU_size++] = opts & 0xff; + res_APDU[res_APDU_size++] = opts >> 8; res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR; res_APDU[res_APDU_size++] = HSM_VERSION_MINOR; res_APDU[1] = res_APDU_size-2; From 2905dcc8c0f08ee1960b08de81b29114d4c89aeb Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 3 Apr 2022 19:57:56 +0200 Subject: [PATCH 13/17] Adding custom command to set datetime. Signed-off-by: Pol Henarejos --- CMakeLists.txt | 2 +- src/hsm/hsm2040.c | 4 ++++ src/hsm/sc_hsm.c | 21 +++++++++++++++++++++ 3 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e8d413..9910399 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -119,7 +119,7 @@ pico_add_extra_outputs(pico_hsm) #target_compile_definitions(pico_hsm PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1) -target_link_libraries(pico_hsm PRIVATE pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id) +target_link_libraries(pico_hsm PRIVATE pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc) # #project(flash_nuke C CXX ASM) diff --git a/src/hsm/hsm2040.c b/src/hsm/hsm2040.c index 72b0a46..228b1d5 100644 --- a/src/hsm/hsm2040.c +++ b/src/hsm/hsm2040.c @@ -33,6 +33,7 @@ #include "pico/multicore.h" #include "random.h" #include "hsm2040.h" +#include "hardware/rtc.h" extern void do_flash(); extern void low_flash_init(); @@ -1628,6 +1629,7 @@ int main(void) gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT); #endif #endif + led_off_all(); @@ -1638,6 +1640,8 @@ int main(void) random_init(); low_flash_init(); + + rtc_init(); while (1) { diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 95f9359..3ff01d9 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -32,6 +32,7 @@ #include "cvcerts.h" #include "crypto_utils.h" #include "dkek.h" +#include "hardware/rtc.h" const uint8_t sc_hsm_aid[] = { 11, @@ -1676,6 +1677,24 @@ static int cmd_derive_asym() { return SW_OK(); } +static int cmd_datetime() { + if (P1(apdu) != 0x0 || P2(apdu) != 0x0) + return SW_INCORRECT_P1P2(); + if (apdu.cmd_apdu_data_len != 8) + return SW_WRONG_LENGTH(); + datetime_t dt; + dt.year = (apdu.cmd_apdu_data[0] << 8) | (apdu.cmd_apdu_data[1]); + dt.month = apdu.cmd_apdu_data[2]; + dt.day = apdu.cmd_apdu_data[3]; + dt.dotw = apdu.cmd_apdu_data[4]; + dt.hour = apdu.cmd_apdu_data[5]; + dt.min = apdu.cmd_apdu_data[6]; + dt.sec = apdu.cmd_apdu_data[7]; + if (!rtc_set_datetime(&dt)) + return SW_WRONG_DATA(); + return SW_OK(); +} + typedef struct cmd { uint8_t ins; @@ -1697,6 +1716,7 @@ typedef struct cmd #define INS_DERIVE_ASYM 0x76 #define INS_CIPHER_SYM 0x78 #define INS_CHALLENGE 0x84 +#define INS_DATETIME 0x88 #define INS_SELECT_FILE 0xA4 #define INS_READ_BINARY 0xB0 #define INS_READ_BINARY_ODD 0xB1 @@ -1724,6 +1744,7 @@ static const cmd_t cmds[] = { { INS_DECRYPT_ASYM, cmd_decrypt_asym }, { INS_CIPHER_SYM, cmd_cipher_sym }, { INS_DERIVE_ASYM, cmd_derive_asym }, + { INS_DATETIME, cmd_datetime }, { 0x00, 0x0} }; From b1121718db43c5f8258ffd9bf524d5b285be22ca Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 3 Apr 2022 20:37:16 +0200 Subject: [PATCH 14/17] Adding capability to reset retry counter without new PIN Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 3ff01d9..35c3094 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -486,6 +486,8 @@ static int cmd_reset_retry() { if (!file_sopin->data) { return SW_REFERENCE_NOT_FOUND(); } + if (apdu.cmd_apdu_data_len <= 8) + return SW_WRONG_LENGTH(); uint16_t r = check_pin(file_sopin, apdu.cmd_apdu_data, 8); if (r != 0x9000) return r; @@ -498,7 +500,31 @@ static int cmd_reset_retry() { low_flash_available(); return SW_OK(); } + else + return SW_REFERENCE_NOT_FOUND(); } + else if (P1(apdu) == 0x1) { + if (P2(apdu) == 0x81) { + if (!file_sopin || !file_pin1) { + return SW_FILE_NOT_FOUND(); + } + if (!file_sopin->data) { + return SW_REFERENCE_NOT_FOUND(); + } + if (apdu.cmd_apdu_data_len != 8) + return SW_WRONG_LENGTH(); + uint16_t r = check_pin(file_sopin, apdu.cmd_apdu_data, 8); + if (r != 0x9000) + return r; + if (pin_reset_retries(file_pin1, true) != HSM_OK) + return SW_MEMORY_FAILURE(); + low_flash_available(); + return SW_OK(); + } + else + return SW_REFERENCE_NOT_FOUND(); + } + return SW_INCORRECT_P1P2(); } static int cmd_challenge() { From 85ff92c4ded1ef156a422dd40a0f5a6f030e34d0 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 3 Apr 2022 20:40:16 +0200 Subject: [PATCH 15/17] Adding check for device options whether it can reset retry counter with PIN or without. 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 35c3094..3cff83a 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -478,6 +478,7 @@ static int cmd_verify() { } static int cmd_reset_retry() { + uint16_t opts = get_device_options(); if (P1(apdu) == 0x0) { if (P2(apdu) == 0x81) { if (!file_sopin || !file_pin1) { @@ -488,6 +489,8 @@ static int cmd_reset_retry() { } if (apdu.cmd_apdu_data_len <= 8) return SW_WRONG_LENGTH(); + if (!(opts & HSM_OPT_RRC)) + return SW_COMMAND_NOT_ALLOWED(); uint16_t r = check_pin(file_sopin, apdu.cmd_apdu_data, 8); if (r != 0x9000) return r; @@ -513,6 +516,8 @@ static int cmd_reset_retry() { } if (apdu.cmd_apdu_data_len != 8) return SW_WRONG_LENGTH(); + if (!(opts & HSM_OPT_RRC) || !(opts & HSM_OPT_RRC_RESET_ONLY)) + return SW_COMMAND_NOT_ALLOWED(); uint16_t r = check_pin(file_sopin, apdu.cmd_apdu_data, 8); if (r != 0x9000) return r; From a6195274820fa6d633343869215cd566817ee69d Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 3 Apr 2022 20:59:50 +0200 Subject: [PATCH 16/17] Adding P1=0x2 and P1=0x3 for reset retry counter. Signed-off-by: Pol Henarejos --- src/hsm/sc_hsm.c | 78 ++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 3cff83a..21c6ee6 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -478,56 +478,62 @@ static int cmd_verify() { } static int cmd_reset_retry() { + if (P2(apdu) != 0x81) + return SW_REFERENCE_NOT_FOUND(); + if (!file_sopin || !file_pin1) { + return SW_FILE_NOT_FOUND(); + } + if (!file_sopin->data) { + return SW_REFERENCE_NOT_FOUND(); + } uint16_t opts = get_device_options(); - if (P1(apdu) == 0x0) { - if (P2(apdu) == 0x81) { - if (!file_sopin || !file_pin1) { - return SW_FILE_NOT_FOUND(); - } - if (!file_sopin->data) { - return SW_REFERENCE_NOT_FOUND(); - } + if (!(opts & HSM_OPT_RRC)) + return SW_COMMAND_NOT_ALLOWED(); + if (P1(apdu) == 0x0 || P1(apdu) == 0x2) { + int newpin_len = 0; + if (P1(apdu) == 0x0) { if (apdu.cmd_apdu_data_len <= 8) return SW_WRONG_LENGTH(); - if (!(opts & HSM_OPT_RRC)) - return SW_COMMAND_NOT_ALLOWED(); uint16_t r = check_pin(file_sopin, apdu.cmd_apdu_data, 8); if (r != 0x9000) return r; - uint8_t dhash[33]; - dhash[0] = apdu.cmd_apdu_data_len-8; - double_hash_pin(apdu.cmd_apdu_data+8, apdu.cmd_apdu_data_len-8, dhash+1); - flash_write_data_to_file(file_pin1, dhash, sizeof(dhash)); - if (pin_reset_retries(file_pin1, true) != HSM_OK) - return SW_MEMORY_FAILURE(); - low_flash_available(); - return SW_OK(); + newpin_len = apdu.cmd_apdu_data_len-8; } - else - return SW_REFERENCE_NOT_FOUND(); + else if (P1(apdu) == 0x2) { + if (!has_session_sopin) + return SW_CONDITIONS_NOT_SATISFIED(); + if (apdu.cmd_apdu_data_len > 16) + return SW_WRONG_LENGTH(); + newpin_len = apdu.cmd_apdu_data_len; + } + uint8_t dhash[33]; + dhash[0] = newpin_len; + double_hash_pin(apdu.cmd_apdu_data+(apdu.cmd_apdu_data_len-newpin_len), newpin_len, dhash+1); + flash_write_data_to_file(file_pin1, dhash, sizeof(dhash)); + if (pin_reset_retries(file_pin1, true) != HSM_OK) + return SW_MEMORY_FAILURE(); + low_flash_available(); + return SW_OK(); } - else if (P1(apdu) == 0x1) { - if (P2(apdu) == 0x81) { - if (!file_sopin || !file_pin1) { - return SW_FILE_NOT_FOUND(); - } - if (!file_sopin->data) { - return SW_REFERENCE_NOT_FOUND(); - } + else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) { + if (!(opts & HSM_OPT_RRC_RESET_ONLY)) + return SW_COMMAND_NOT_ALLOWED(); + if (P1(apdu) == 0x1) { if (apdu.cmd_apdu_data_len != 8) return SW_WRONG_LENGTH(); - if (!(opts & HSM_OPT_RRC) || !(opts & HSM_OPT_RRC_RESET_ONLY)) - return SW_COMMAND_NOT_ALLOWED(); uint16_t r = check_pin(file_sopin, apdu.cmd_apdu_data, 8); if (r != 0x9000) return r; - if (pin_reset_retries(file_pin1, true) != HSM_OK) - return SW_MEMORY_FAILURE(); - low_flash_available(); - return SW_OK(); } - else - return SW_REFERENCE_NOT_FOUND(); + else if (P1(apdu) == 0x3) { + if (!has_session_sopin) + return SW_CONDITIONS_NOT_SATISFIED(); + if (apdu.cmd_apdu_data_len != 0) + return SW_WRONG_LENGTH(); + } + if (pin_reset_retries(file_pin1, true) != HSM_OK) + return SW_MEMORY_FAILURE(); + return SW_OK(); } return SW_INCORRECT_P1P2(); } From d27d8b0c5ba725d9d7210c77be429dede8d0b257 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 4 Apr 2022 09:57:19 +0200 Subject: [PATCH 17/17] Upgrading to version 1.10 Signed-off-by: Pol Henarejos --- build_pico_hsm.sh | 2 +- patch_vidpid.sh | 2 +- src/hsm/version.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/build_pico_hsm.sh b/build_pico_hsm.sh index 10d4875..037ee77 100755 --- a/build_pico_hsm.sh +++ b/build_pico_hsm.sh @@ -1,7 +1,7 @@ #!/bin/bash VERSION_MAJOR="1" -VERSION_MINOR="8" +VERSION_MINOR="10" rm -rf release/* cd build_release diff --git a/patch_vidpid.sh b/patch_vidpid.sh index 0262343..dc1f379 100755 --- a/patch_vidpid.sh +++ b/patch_vidpid.sh @@ -18,7 +18,7 @@ # VERSION_MAJOR="1" -VERSION_MINOR="8" +VERSION_MINOR="0A" echo "----------------------------" echo "VID/PID patcher for Pico HSM" diff --git a/src/hsm/version.h b/src/hsm/version.h index 5534f9c..5340f9d 100644 --- a/src/hsm/version.h +++ b/src/hsm/version.h @@ -18,7 +18,7 @@ #ifndef __VERSION_H_ #define __VERSION_H_ -#define HSM_VERSION 0x0108 +#define HSM_VERSION 0x010A #define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff) #define HSM_VERSION_MINOR (HSM_VERSION & 0xff)