diff --git a/file.c b/file.c index 96d4c5a..8b9e008 100644 --- a/file.c +++ b/file.c @@ -14,6 +14,8 @@ extern int flash_program_uintptr (uintptr_t addr, uintptr_t data); extern int flash_program_block(uintptr_t addr, const uint8_t *data, size_t len); extern uintptr_t flash_read_uintptr(uintptr_t addr); extern uint16_t flash_read_uint16(uintptr_t addr); +extern uint8_t flash_read_uint8(uintptr_t addr); +extern uint8_t *flash_read(uintptr_t addr); extern void low_flash_available(); //puts FCI in the RAPDU @@ -75,7 +77,7 @@ file_t file_entries[] = { /* 11 */ { .fid = 0x1083, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (PIN1) /* 12 */ { .fid = 0x1088, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //PIN (SOPIN) /* 13 */ { .fid = 0x1089, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //max retries PIN (SOPIN) - /* 14 */ { .fid = 0x1090, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (SOPIN) + /* 14 */ { .fid = 0x108A, .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (SOPIN) /* 15 */ { .fid = 0x6040, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PrKDFs /* 16 */ { .fid = 0x6041, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.PuKDFs /* 17 */ { .fid = 0x6042, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.CDFs @@ -186,27 +188,6 @@ 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) { @@ -311,7 +292,7 @@ void scan_flash() { else { TU_LOG1("FATAL ERROR: Retries PIN1 not found in memory!\r\n"); } - file_retries_sopin = search_by_fid(0x1090, NULL, SPECIFY_EF); + file_retries_sopin = search_by_fid(0x108A, NULL, SPECIFY_EF); if (file_retries_sopin) { if (!file_retries_sopin->data) { TU_LOG1("Retries SOPIN is empty. Initializing with default retries\r\n"); @@ -348,3 +329,13 @@ void scan_flash() { } low_flash_available(); } + +uint8_t *file_read(const uint8_t *addr) { + return flash_read((uintptr_t)addr); +} +uint16_t file_read_uint16(const uint8_t *addr) { + return flash_read_uint16((uintptr_t)addr); +} +uint8_t file_read_uint8(const uint8_t *addr) { + return flash_read_uint8((uintptr_t)addr); +} \ No newline at end of file diff --git a/file.h b/file.h index 1aefda5..f2e31ee 100644 --- a/file.h +++ b/file.h @@ -68,5 +68,9 @@ extern void scan_flash(); extern file_t file_entries[]; +extern uint8_t *file_read(const uint8_t *addr); +extern uint16_t file_read_uint16(const uint8_t *addr); +extern uint8_t file_read_uint8(const uint8_t *addr); + #endif diff --git a/flash.c b/flash.c index b7a5b1b..76ef6d4 100644 --- a/flash.c +++ b/flash.c @@ -43,6 +43,7 @@ #include "hsm2040.h" #include "tusb.h" #include "file.h" +#include "sc_hsm.h" #define FLASH_TARGET_OFFSET (PICO_FLASH_SIZE_BYTES >> 1) // DATA starts at the mid of flash #define FLASH_DATA_HEADER_SIZE (sizeof(uintptr_t)+sizeof(uint32_t)) @@ -130,13 +131,13 @@ int flash_clear_file(file_t *file) { int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len) { if (len > FLASH_SECTOR_SIZE) - return 1; + return HSM_ERR_NO_MEMORY; if (file->data) { //already in flash uint16_t size_file_flash = flash_read_uint16((uintptr_t)file->data); if (len <= size_file_flash) { //it fits, no need to move it flash_program_halfword((uintptr_t)file->data, len); flash_program_block((uintptr_t)file->data+sizeof(uint16_t), data, len); - return 0; + return HSM_OK; } else { //we clear the old file flash_clear_file(file); @@ -144,10 +145,10 @@ int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len) { } uintptr_t new_addr = allocate_free_addr(len); if (new_addr == 0x0) - return 2; + return HSM_ERR_NO_MEMORY; file->data = (uint8_t *)new_addr+sizeof(uintptr_t)+sizeof(uint16_t); //next addr+fid flash_program_halfword(new_addr+sizeof(uintptr_t), file->fid); flash_program_halfword((uintptr_t)file->data, len); flash_program_block((uintptr_t)file->data+sizeof(uint16_t), data, len); - return 0; + return HSM_OK; } diff --git a/hsm2040.h b/hsm2040.h index 18a1cf0..1e6b161 100644 --- a/hsm2040.h +++ b/hsm2040.h @@ -110,7 +110,5 @@ void put_binary (const char *s, int len); #endif extern int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len); - - - +extern void low_flash_available(); #endif \ No newline at end of file diff --git a/low_flash.c b/low_flash.c index eb7719f..69b7400 100644 --- a/low_flash.c +++ b/low_flash.c @@ -199,6 +199,9 @@ uint16_t flash_read_uint16(uintptr_t addr) { } return v; } +uint8_t flash_read_uint8(uintptr_t addr) { + return *flash_read(addr); +} int flash_erase_page (uintptr_t addr, size_t page_size) { diff --git a/sc_hsm.c b/sc_hsm.c index 0609349..fec1c2c 100644 --- a/sc_hsm.c +++ b/sc_hsm.c @@ -40,7 +40,7 @@ static int cmd_verify() { if (!file_retries_pin1) { return SW_REFERENCE_NOT_FOUND(); } - return set_res_sw (0x63, 0xc0 | file_retries_pin1->data[2]); + return set_res_sw (0x63, 0xc0 | file_read_uint8(file_retries_pin1->data+2)); } else if (p2 == 0x88) { //SOPin } @@ -186,34 +186,64 @@ static int cmd_read_binary() return SW_SECURITY_STATUS_NOT_SATISFIED(); } if (ef->data) { - uint16_t data_len = get_uint16_t(ef->data, 0); + uint16_t data_len = file_read_uint16(ef->data); if (offset > data_len) return SW_WRONG_P1P2(); uint16_t maxle = data_len-offset; if (apdu.expected_res_size > maxle) apdu.expected_res_size = maxle; - res_APDU = ef->data+2+offset; + res_APDU = file_read(ef->data+2+offset); res_APDU_size = data_len-offset; } return SW_OK(); } +int pin_reset_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; + uint8_t retries = file_read_uint8(max->data+2); + int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries)); + low_flash_available(); + return r; +} + +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; + uint8_t retries = file_read_uint8(act->data+2); + if (retries > 0) { + retries -= 1; + int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries)); + low_flash_available(); + return r; + } + return HSM_ERR_BLOCKED; +} + + 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]) + if (len != file_read_uint16(pin->data)) return SW_CONDITIONS_NOT_SATISFIED(); - if (memcmp(pin->data+2, data, len) != 0) { + if (memcmp(file_read(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); + return pin_reset_retries(pin); } static int cmd_reset_retry() { @@ -229,8 +259,9 @@ static int cmd_reset_retry() { 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) + if (pin_reset_retries(file_pin1) != HSM_OK) return SW_MEMORY_FAILURE(); + low_flash_available(); return SW_OK(); } } diff --git a/sc_hsm.h b/sc_hsm.h index 4161564..481b91c 100644 --- a/sc_hsm.h +++ b/sc_hsm.h @@ -41,7 +41,7 @@ extern const uint8_t sc_hsm_aid[]; #define HSM_ERR_FILE_NOT_FOUND -1003 #define HSM_ERR_BLOCKED -1004 -extern int reset_pin_retries(const file_t *pin); +extern int pin_reset_retries(const file_t *pin); extern int pin_wrong_retry(const file_t *pin); #endif \ No newline at end of file