Adding support for Transport PIN.

Adding support for initialize options.
This commit is contained in:
Pol Henarejos
2022-04-04 10:06:48 +02:00
12 changed files with 133 additions and 42 deletions

View File

@@ -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
@@ -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)

View File

@@ -1,7 +1,7 @@
#!/bin/bash
VERSION_MAJOR="1"
VERSION_MINOR="8"
VERSION_MINOR="10"
rm -rf release/*
cd build_release

View File

@@ -18,7 +18,7 @@
#
VERSION_MAJOR="1"
VERSION_MINOR="8"
VERSION_MINOR="0A"
echo "----------------------------"
echo "VID/PID patcher for Pico HSM"

View File

@@ -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];

View File

@@ -60,6 +60,7 @@
#define EF_AODFS 0x6043
#define EF_DODFS 0x6044
#define EF_SKDFS 0x6045
#define EF_DEVOPS 0x100E
#define MAX_DEPTH 4

View File

@@ -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"

View File

@@ -15,8 +15,8 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _HASH_UTILS_H_
#define _HASH_UTILS_H_
#ifndef _CRYPTO_UTILS_H_
#define _CRYPTO_UTILS_H_
#include "stdlib.h"
#include "pico/stdlib.h"

View File

@@ -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"
@@ -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

View File

@@ -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)
{

View File

@@ -30,8 +30,9 @@
#include "mbedtls/hkdf.h"
#include "version.h"
#include "cvcerts.h"
#include "hash_utils.h"
#include "crypto_utils.h"
#include "dkek.h"
#include "hardware/rtc.h"
const uint8_t sc_hsm_aid[] = {
11,
@@ -92,6 +93,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_uint8(ef->data+2) << 8) | file_read_uint8(ef->data+3);
return 0x0;
}
static int cmd_select() {
uint8_t p1 = P1(apdu);
uint8_t p2 = P2(apdu);
@@ -171,8 +180,9 @@ static int cmd_select() {
if (pe == file_sc_hsm) {
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;
uint16_t opts = get_device_options();
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;
@@ -400,11 +410,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
@@ -422,7 +433,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();
}
@@ -434,46 +448,94 @@ 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);
}
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
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);
}
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();
}
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();
}
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 (!(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();
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 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 || 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();
uint16_t r = check_pin(file_sopin, apdu.cmd_apdu_data, 8);
if (r != 0x9000)
return r;
}
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();
}
static int cmd_challenge() {
@@ -503,6 +565,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) {
@@ -581,6 +645,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);
@@ -1036,7 +1101,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];
@@ -1649,6 +1714,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;
@@ -1670,6 +1753,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
@@ -1697,6 +1781,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}
};

View File

@@ -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)

View File

@@ -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)