diff --git a/file.c b/file.c index 2853cb2..96d4c5a 100644 --- a/file.c +++ b/file.c @@ -2,6 +2,7 @@ #include "gnuk.h" #include "tusb.h" #include "hsm2040.h" +#include "sc_hsm.h" #include extern const uintptr_t end_data_pool; @@ -185,6 +186,26 @@ bool authenticate_action(const file_t *ef, uint8_t op) { #include "libopensc/pkcs15.h" +int reset_pin_retries(const file_t *pin) { + if (!pin) + return HSM_ERR_NULL_PARAM; + const file_t *max = search_by_fid(pin->fid+1, NULL, SPECIFY_EF); + const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF); + if (!max || !act) + return HSM_ERR_FILE_NOT_FOUND; + return flash_write_data_to_file((file_t *)act, &max->data[2], sizeof(uint8_t)); +} + +int pin_wrong_retry(const file_t *pin) { + if (!pin) + return HSM_ERR_NULL_PARAM; + const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF); + if (!act) + return HSM_ERR_FILE_NOT_FOUND; + if (act->data[2] > 0) + return flash_write_data_to_file((file_t *)act, &act->data[2]-1, sizeof(uint8_t)); + return HSM_ERR_BLOCKED; +} void scan_flash() { if (*(uintptr_t *)end_data_pool == 0xffffffff && *(uintptr_t *)(end_data_pool+sizeof(uintptr_t)) == 0xffffffff) @@ -326,4 +347,4 @@ void scan_flash() { TU_LOG1("FATAL ERROR: Retries SOPIN not found in memory!\r\n"); } low_flash_available(); -} \ No newline at end of file +} diff --git a/hsm2040.h b/hsm2040.h index 4ae85b7..18a1cf0 100644 --- a/hsm2040.h +++ b/hsm2040.h @@ -9,6 +9,7 @@ #include "ccid.h" #include "tusb.h" +#include "file.h" #define USB_REQ_CCID 0xA1 @@ -108,6 +109,8 @@ void put_binary (const char *s, int len); #define DEBUG_BINARY(s,len) #endif +extern int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len); + #endif \ No newline at end of file diff --git a/low_flash.c b/low_flash.c index 61e4f0c..eb7719f 100644 --- a/low_flash.c +++ b/low_flash.c @@ -10,6 +10,7 @@ #include "pico/multicore.h" #include "gnuk.h" #include "hsm2040.h" +#include "sc_hsm.h" #include #define TOTAL_FLASH_PAGES 4 @@ -135,18 +136,18 @@ int flash_program_block(uintptr_t addr, const uint8_t *data, size_t len) { if (ready_pages == TOTAL_FLASH_PAGES) { mutex_exit(&mtx_flash); DEBUG_INFO("ERROR: ALL FLASH PAGES CACHED\r\n"); - return 1; + return HSM_ERR_NO_MEMORY; } if (!(p = find_free_page(addr))) { DEBUG_INFO("ERROR: FLASH CANNOT FIND A PAGE (rare error)\r\n"); mutex_exit(&mtx_flash); - return 1; + return HSM_ERR_MEMORY_FATAL; } memcpy(&p->page[addr&(FLASH_SECTOR_SIZE-1)], data, len); //printf("Flash: modified page %X with data %x at [%x] (top page %X)\r\n",addr_alg,data,addr&(FLASH_SECTOR_SIZE-1),addr); mutex_exit(&mtx_flash); - return 0; + return HSM_OK; } int flash_program_halfword (uintptr_t addr, uint16_t data) @@ -208,30 +209,29 @@ int flash_erase_page (uintptr_t addr, size_t page_size) if (ready_pages == TOTAL_FLASH_PAGES) { mutex_exit(&mtx_flash); DEBUG_INFO("ERROR: ALL FLASH PAGES CACHED\r\n"); - return 1; + return HSM_ERR_NO_MEMORY; } if (!(p = find_free_page(addr))) { DEBUG_INFO("ERROR: FLASH CANNOT FIND A PAGE (rare error)\r\n"); mutex_exit(&mtx_flash); - return 1; + return HSM_ERR_MEMORY_FATAL; } p->erase = true; p->ready = false; p->page_size = page_size; mutex_exit(&mtx_flash); - return 0; + return HSM_OK; } -int -flash_check_blank (const uint8_t *p_start, size_t size) +bool flash_check_blank (const uint8_t *p_start, size_t size) { const uint8_t *p; for (p = p_start; p < p_start + size; p++) if (*p != 0xff) - return 0; + return false; - return 1; + return true; } diff --git a/sc_hsm.c b/sc_hsm.c index 7c8cbf7..0609349 100644 --- a/sc_hsm.c +++ b/sc_hsm.c @@ -200,6 +200,42 @@ static int cmd_read_binary() return SW_OK(); } +int check_pin(const file_t *pin, const uint8_t *data, size_t len) { + if (!pin) + return SW_FILE_NOT_FOUND(); + if (!pin->data) { + return SW_REFERENCE_NOT_FOUND(); + } + if (len != pin->data[0]) + return SW_CONDITIONS_NOT_SATISFIED(); + if (memcmp(pin->data+2, data, len) != 0) { + if (pin_wrong_retry(pin) != HSM_OK) + return SW_PIN_BLOCKED(); + return SW_SECURITY_STATUS_NOT_SATISFIED(); + } + return reset_pin_retries(pin); +} + +static int cmd_reset_retry() { + 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(); + } + uint16_t r = check_pin(file_sopin, apdu.cmd_apdu_data, 8); + if (r != 0x9000) + return r; + flash_write_data_to_file(file_pin1, apdu.cmd_apdu_data+8, apdu.cmd_apdu_data_len-8); + if (reset_pin_retries(file_pin1) != HSM_OK) + return SW_MEMORY_FAILURE(); + return SW_OK(); + } + } +} + typedef struct cmd { uint8_t ins; @@ -210,6 +246,7 @@ typedef struct cmd #define INS_READ_BINARY 0xB0 #define INS_READ_BINARY_ODD 0xB1 #define INS_VERIFY 0x20 +#define INS_RESET_RETRY 0x2C static const cmd_t cmds[] = { { INS_SELECT_FILE, cmd_select }, @@ -217,6 +254,7 @@ static const cmd_t cmds[] = { { INS_READ_BINARY, cmd_read_binary }, { INS_READ_BINARY_ODD, cmd_read_binary }, { INS_VERIFY, cmd_verify }, + { INS_RESET_RETRY, cmd_reset_retry }, { 0x00, 0x0} }; diff --git a/sc_hsm.h b/sc_hsm.h index f151e4b..4161564 100644 --- a/sc_hsm.h +++ b/sc_hsm.h @@ -9,6 +9,8 @@ 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_MEMORY_FAILURE() set_res_sw (0x65, 0x81) #define SW_WRONG_LENGTH() set_res_sw (0x67, 0x00) #define SW_WRONG_DATA() set_res_sw (0x67, 0x00) #define SW_LOGICAL_CHANNEL_NOT_SUPPORTED() set_res_sw (0x68, 0x81) @@ -16,7 +18,7 @@ extern const uint8_t sc_hsm_aid[]; #define SW_SECURITY_STATUS_NOT_SATISFIED() set_res_sw (0x69, 0x82) #define SW_FILE_INVALID () 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_CONDITIONS_NOT_SATISFIED() set_res_sw (0x69, 0x85) #define SW_COMMAND_NOT_ALLOWED() set_res_sw (0x69, 0x86) #define SW_APPLET_SELECT_FAILED() set_res_sw (0x69, 0x99) #define SW_FUNC_NOT_SUPPORTED() set_res_sw (0x6A, 0x81) @@ -30,6 +32,16 @@ extern const uint8_t sc_hsm_aid[]; #define SW_INS_NOT_SUPPORTED() set_res_sw (0x6D, 0x00) #define SW_CLA_NOT_SUPPORTED() set_res_sw (0x6E, 0x00) #define SW_UNKNOWN() set_res_sw (0x6F, 0x00) -#define SW_OK() set_res_sw (0x90, 0x00) +#define SW_OK() set_res_sw (0x90, 0x00) + +#define HSM_OK 0 +#define HSM_ERR_NO_MEMORY -1000 +#define HSM_ERR_MEMORY_FATAL -1001 +#define HSM_ERR_NULL_PARAM -1002 +#define HSM_ERR_FILE_NOT_FOUND -1003 +#define HSM_ERR_BLOCKED -1004 + +extern int reset_pin_retries(const file_t *pin); +extern int pin_wrong_retry(const file_t *pin); #endif \ No newline at end of file