diff --git a/.gitmodules b/.gitmodules
index 56fe23a..1cdae06 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -4,3 +4,6 @@
[submodule "mbedtls"]
path = mbedtls
url = https://github.com/ARMmbed/mbedtls
+[submodule "pico-ccid"]
+ path = pico-ccid
+ url = git@github.com-polhenarejos:polhenarejos/pico-ccid
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e46c84e..0047b02 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,14 +51,15 @@ if (NOT EXISTS ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cvcerts.h)
endif()
target_sources(pico_hsm PUBLIC
- ${CMAKE_CURRENT_LIST_DIR}/src/hsm/hsm2040.c
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/ccid2040.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c
- ${CMAKE_CURRENT_LIST_DIR}/src/usb/usb_descriptors.c
- ${CMAKE_CURRENT_LIST_DIR}/src/fs/file.c
- ${CMAKE_CURRENT_LIST_DIR}/src/fs/flash.c
- ${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}/pico-ccid/src/usb/usb_descriptors.c
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/file.c
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/flash.c
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs/low_flash.c
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/rng/random.c
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/rng/neug.c
+ ${CMAKE_CURRENT_LIST_DIR}/src/hsm/files.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/crypto_utils.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/dkek.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/eac.c
@@ -115,10 +116,11 @@ target_sources(pico_hsm PUBLIC
)
target_include_directories(pico_hsm PUBLIC
- ${CMAKE_CURRENT_LIST_DIR}/src/fs
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs
${CMAKE_CURRENT_LIST_DIR}/src/hsm
- ${CMAKE_CURRENT_LIST_DIR}/src/rng
- ${CMAKE_CURRENT_LIST_DIR}/src/usb
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/rng
+ ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/usb
${CMAKE_CURRENT_LIST_DIR}/opensc/src
${CMAKE_CURRENT_LIST_DIR}/mbedtls/include
${CMAKE_CURRENT_LIST_DIR}/mbedtls/library
diff --git a/pico-ccid b/pico-ccid
new file mode 160000
index 0000000..cffee42
--- /dev/null
+++ b/pico-ccid
@@ -0,0 +1 @@
+Subproject commit cffee4264a531b52a5991c916e131280adeb1c9d
diff --git a/src/fs/file.c b/src/fs/file.c
deleted file mode 100644
index 5adb11a..0000000
--- a/src/fs/file.c
+++ /dev/null
@@ -1,416 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "file.h"
-#include "tusb.h"
-#include "hsm2040.h"
-#include "sc_hsm.h"
-#include "libopensc/card-sc-hsm.h"
-#include
-
-extern const uintptr_t end_data_pool;
-extern const uintptr_t start_data_pool;
-extern int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len);
-extern int flash_program_halfword (uintptr_t addr, uint16_t data);
-extern int flash_program_word (uintptr_t addr, uint32_t data);
-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
-void process_fci(const file_t *pe) {
- uint8_t *p = res_APDU;
- uint8_t buf[64];
- res_APDU_size = 0;
- res_APDU[res_APDU_size++] = 0x6f;
- res_APDU[res_APDU_size++] = 0x00; //computed later
-
- res_APDU[res_APDU_size++] = 0x81;
- res_APDU[res_APDU_size++] = 2;
- if (pe->data) {
- if ((pe->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
- uint16_t len = ((int (*)(const file_t *, int))(pe->data))(pe, 0);
- res_APDU[res_APDU_size++] = (len >> 8) & 0xff;
- res_APDU[res_APDU_size++] = len & 0xff;
- }
- else {
- res_APDU[res_APDU_size++] = pe->data[1];
- res_APDU[res_APDU_size++] = pe->data[0];
- }
- }
- else {
- memset(res_APDU+res_APDU_size, 0, 2);
- res_APDU_size += 2;
- }
-
- res_APDU[res_APDU_size++] = 0x82;
- res_APDU[res_APDU_size++] = 1;
- res_APDU[res_APDU_size] = 0;
- if (pe->type == FILE_TYPE_INTERNAL_EF)
- res_APDU[res_APDU_size++] |= 0x08;
- else if (pe->type == FILE_TYPE_WORKING_EF)
- res_APDU[res_APDU_size++] |= pe->ef_structure & 0x7;
- else if (pe->type == FILE_TYPE_DF)
- res_APDU[res_APDU_size++] |= 0x38;
-
- res_APDU[res_APDU_size++] = 0x83;
- res_APDU[res_APDU_size++] = 2;
- put_uint16_t(pe->fid, res_APDU+res_APDU_size);
- res_APDU_size += 2;
- res_APDU[1] = res_APDU_size-2;
-}
-
-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 | 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
- /* 7 */ { .fid = 0x5032 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.TokenInfo
- /* 8 */ { .fid = 0x5033 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.UnusedSpace
- /* 9 */ { .fid = 0x1081 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //PIN (PIN1)
- /* 10 */ { .fid = 0x1082 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //max retries PIN (PIN1)
- /* 11 */ { .fid = 0x1083 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (PIN1)
- /* 12 */ { .fid = 0x1088 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //PIN (SOPIN)
- /* 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_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];
-const file_t *file_last = &file_entries[sizeof(file_entries)/sizeof(file_t)-1];
-const file_t *file_openpgp = &file_entries[sizeof(file_entries)/sizeof(file_t)-3];
-const file_t *file_sc_hsm = &file_entries[sizeof(file_entries)/sizeof(file_t)-2];
-file_t *file_pin1 = NULL;
-file_t *file_retries_pin1 = NULL;
-file_t *file_sopin = NULL;
-file_t *file_retries_sopin = NULL;
-
-#define MAX_DYNAMIC_FILES 64
-uint16_t dynamic_files = 0;
-file_t dynamic_file[MAX_DYNAMIC_FILES];
-
-bool card_terminated = false;
-
-bool is_parent(const file_t *child, const file_t *parent) {
- if (child == parent)
- return true;
- if (child == MF)
- return false;
- return is_parent(&file_entries[child->parent], parent);
-}
-
-file_t *get_parent(file_t *f) {
- return &file_entries[f->parent];
-}
-
-file_t *search_by_name(uint8_t *name, uint16_t namelen) {
- for (file_t *p = file_entries; p != file_last; p++) {
- if (p->name && *p->name == apdu.cmd_apdu_data_len && memcmp(p->name+1, name, namelen) == 0) {
- return p;
- }
- }
- return NULL;
-}
-
-file_t *search_by_fid(const uint16_t fid, const file_t *parent, const uint8_t sp) {
-
- for (file_t *p = file_entries; p != file_last; p++) {
- if (p->fid != 0x0000 && p->fid == fid) {
- if (!parent || (parent && is_parent(p, parent))) {
- if (!sp || sp == SPECIFY_ANY || (((sp & SPECIFY_EF) && (p->type & FILE_TYPE_INTERNAL_EF)) || ((sp & SPECIFY_DF) && p->type == FILE_TYPE_DF)))
- return p;
- }
- }
- }
- return NULL;
-}
-
-uint8_t make_path_buf(const file_t *pe, uint8_t *buf, uint8_t buflen, const file_t *top) {
- if (!buflen)
- return 0;
- if (pe == top) //MF or relative DF
- return 0;
- put_uint16_t(pe->fid, buf);
- return make_path_buf(&file_entries[pe->parent], buf+2, buflen-2, top)+2;
-}
-
-uint8_t make_path(const file_t *pe, const file_t *top, uint8_t *path) {
- uint8_t buf[MAX_DEPTH*2], *p = path;
- put_uint16_t(pe->fid, buf);
- uint8_t depth = make_path_buf(&file_entries[pe->parent], buf+2, sizeof(buf)-2, top)+2;
- for (int d = depth-2; d >= 0; d -= 2) {
- memcpy(p, buf+d, 2);
- p += 2;
- }
- return depth;
-}
-
-file_t *search_by_path(const uint8_t *pe_path, uint8_t pathlen, const file_t *parent) {
- uint8_t path[MAX_DEPTH*2];
- if (pathlen > sizeof(path)) {
- return NULL;
- }
- for (file_t *p = file_entries; p != file_last; p++) {
- uint8_t depth = make_path(p, parent, path);
- if (pathlen == depth && memcmp(path, pe_path, depth) == 0)
- return p;
- }
- return NULL;
-}
-
-file_t *currentEF = NULL;
-file_t *currentDF = NULL;
-const file_t *selected_applet = NULL;
-bool isUserAuthenticated = false;
-
-bool authenticate_action(const file_t *ef, uint8_t op) {
- uint8_t acl = ef->acl[op];
- if (acl == 0x0)
- return true;
- else if (acl == 0xff)
- return false;
- else if (acl == 0x90 || acl & 0x9F == 0x10) {
- // PIN required.
- if(isUserAuthenticated) {
- return true;
- }
- else {
- return false;
- }
- }
- return false;
-}
-
-#include "libopensc/pkcs15.h"
-
-void initialize_chain(file_chain_t **chain) {
- file_chain_t *next;
- for (file_chain_t *f = *chain; f; f = next) {
- next = f->next;
- free(f);
- }
- *chain = NULL;
-}
-
-void initialize_flash(bool hard) {
- if (hard) {
- const uint8_t empty[8] = { 0 };
- flash_program_block(end_data_pool, empty, sizeof(empty));
- low_flash_available();
- }
- for (file_t *f = file_entries; f != file_last; f++) {
- if ((f->type & FILE_DATA_FLASH) == FILE_DATA_FLASH)
- f->data = NULL;
- }
- dynamic_files = 0;
-}
-
-void scan_flash() {
- initialize_flash(false); //soft initialization
- if (*(uintptr_t *)end_data_pool == 0xffffffff && *(uintptr_t *)(end_data_pool+sizeof(uintptr_t)) == 0xffffffff)
- {
- printf("First initialization (or corrupted!)\r\n");
- const uint8_t empty[8] = { 0 };
- flash_program_block(end_data_pool, empty, sizeof(empty));
- //low_flash_available();
- //wait_flash_finish();
- }
- printf("SCAN\r\n");
-
- uintptr_t base = flash_read_uintptr(end_data_pool);
- for (uintptr_t base = flash_read_uintptr(end_data_pool); base >= start_data_pool; base = flash_read_uintptr(base)) {
- if (base == 0x0) //all is empty
- break;
-
- uint16_t fid = flash_read_uint16(base+sizeof(uintptr_t)+sizeof(uintptr_t));
- printf("[%x] scan fid %x, len %d\r\n",base,fid,flash_read_uint16(base+sizeof(uintptr_t)+sizeof(uintptr_t)+sizeof(uint16_t)));
- file_t *file = (file_t *)search_by_fid(fid, NULL, SPECIFY_EF);
- if (!file) {
- file = file_new(fid);
- uint8_t pfx = fid >> 8;
- if (pfx != KEY_PREFIX && pfx != PRKD_PREFIX && pfx != CD_PREFIX && pfx != EE_CERTIFICATE_PREFIX && pfx != DCOD_PREFIX && pfx != PROT_DATA_PREFIX && pfx != DATA_PREFIX) {
- TU_LOG1("SCAN FOUND ORPHAN FILE: %x\r\n",fid);
- continue;
- }
- }
- file->data = (uint8_t *)(base+sizeof(uintptr_t)+sizeof(uintptr_t)+sizeof(uint16_t));
- if (flash_read_uintptr(base) == 0x0) {
- break;
- }
- }
- file_pin1 = search_by_fid(0x1081, NULL, SPECIFY_EF);
- if (file_pin1) {
- if (!file_pin1->data) {
- TU_LOG1("PIN1 is empty. Initializing with default password\r\n");
- const uint8_t empty[33] = { 0 };
- flash_write_data_to_file(file_pin1, empty, sizeof(empty));
- }
- }
- else {
- TU_LOG1("FATAL ERROR: PIN1 not found in memory!\r\n");
- }
- file_sopin = search_by_fid(0x1088, NULL, SPECIFY_EF);
- if (file_sopin) {
- if (!file_sopin->data) {
- TU_LOG1("SOPIN is empty. Initializing with default password\r\n");
- const uint8_t empty[33] = { 0 };
- flash_write_data_to_file(file_sopin, empty, sizeof(empty));
- }
- }
- else {
- TU_LOG1("FATAL ERROR: SOPIN not found in memory!\r\n");
- }
- file_retries_pin1 = search_by_fid(0x1083, NULL, SPECIFY_EF);
- if (file_retries_pin1) {
- if (!file_retries_pin1->data) {
- TU_LOG1("Retries PIN1 is empty. Initializing with default retriesr\n");
- const uint8_t retries = 3;
- flash_write_data_to_file(file_retries_pin1, &retries, sizeof(uint8_t));
- }
- }
- else {
- TU_LOG1("FATAL ERROR: Retries PIN1 not found in memory!\r\n");
- }
- 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");
- const uint8_t retries = 15;
- flash_write_data_to_file(file_retries_sopin, &retries, sizeof(uint8_t));
- }
- }
- else {
- TU_LOG1("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
- }
- file_t *tf = NULL;
-
- tf = search_by_fid(0x1082, NULL, SPECIFY_EF);
- if (tf) {
- if (!tf->data) {
- TU_LOG1("Max retries PIN1 is empty. Initializing with default max retriesr\n");
- const uint8_t retries = 3;
- flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
- }
- }
- else {
- TU_LOG1("FATAL ERROR: Max Retries PIN1 not found in memory!\r\n");
- }
- tf = search_by_fid(0x1089, NULL, SPECIFY_EF);
- if (tf) {
- if (!tf->data) {
- TU_LOG1("Max Retries SOPIN is empty. Initializing with default max retries\r\n");
- const uint8_t retries = 15;
- flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
- }
- }
- else {
- TU_LOG1("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
- }
- 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);
-}
-
-file_t *search_dynamic_file(uint16_t fid) {
- for (int i = 0; i < dynamic_files; i++) {
- if (dynamic_file[i].fid == fid)
- return &dynamic_file[i];
- }
- return NULL;
-}
-
-int delete_dynamic_file(file_t *f) {
- for (int i = 0; i < dynamic_files; i++) {
- if (dynamic_file[i].fid == f->fid) {
- for (int j = i+1; j < dynamic_files; j++)
- memcpy(&dynamic_file[j-1], &dynamic_file[j], sizeof(file_t));
- dynamic_files--;
- return HSM_OK;
- }
- }
- return HSM_ERR_FILE_NOT_FOUND;
-}
-
-file_t *file_new(uint16_t fid) {
- file_t *f;
- if ((f = search_dynamic_file(fid)))
- return f;
- if (dynamic_files == MAX_DYNAMIC_FILES)
- return NULL;
- f = &dynamic_file[dynamic_files];
- dynamic_files++;
- file_t file = {
- .fid = fid,
- .parent = 5,
- .name = NULL,
- .type = FILE_TYPE_WORKING_EF,
- .ef_structure = FILE_EF_TRANSPARENT,
- .data = NULL,
- .acl = {0}
- };
- memcpy(f, &file, sizeof(file_t));
- //memset((uint8_t *)f->acl, 0x90, sizeof(f->acl));
- return f;
-}
-
-file_chain_t *add_file_to_chain(file_t *file, file_chain_t **chain) {
- if (search_file_chain(file->fid, *chain))
- return NULL;
- file_chain_t *fc = (file_chain_t *)malloc(sizeof(file_chain_t));
- fc->file = file;
- fc->next = *chain;
- *chain = fc;
- return fc;
-}
-
-file_t *search_file_chain(uint16_t fid, file_chain_t *chain) {
- for (file_chain_t *fc = chain; fc; fc = fc->next) {
- if (fid == fc->file->fid) {
- return fc->file;
- }
- }
- return NULL;
-}
\ No newline at end of file
diff --git a/src/fs/file.h b/src/fs/file.h
deleted file mode 100644
index 5b4175f..0000000
--- a/src/fs/file.h
+++ /dev/null
@@ -1,124 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#ifndef _FILE_H_
-#define _FILE_H_
-
-#include
-#include "pico/stdlib.h"
-
-#define FILE_TYPE_UNKNOWN 0x00
-#define FILE_TYPE_DF 0x04
-#define FILE_TYPE_INTERNAL_EF 0x03
-#define FILE_TYPE_WORKING_EF 0x01
-#define FILE_TYPE_BSO 0x10
-#define FILE_PERSISTENT 0x20
-#define FILE_DATA_FLASH 0x40
-#define FILE_DATA_FUNC 0x80
-
-/* EF structures */
-#define FILE_EF_UNKNOWN 0x00
-#define FILE_EF_TRANSPARENT 0x01
-#define FILE_EF_LINEAR_FIXED 0x02
-#define FILE_EF_LINEAR_FIXED_TLV 0x03
-#define FILE_EF_LINEAR_VARIABLE 0x04
-#define FILE_EF_LINEAR_VARIABLE_TLV 0x05
-#define FILE_EF_CYCLIC 0x06
-#define FILE_EF_CYCLIC_TLV 0x07
-
-#define ACL_OP_DELETE_SELF 0x00
-#define ACL_OP_CREATE_DF 0x01
-#define ACL_OP_CREATE_EF 0x02
-#define ACL_OP_DELETE_CHILD 0x03
-#define ACL_OP_WRITE 0x04
-#define ACL_OP_UPDATE_ERASE 0x05
-#define ACL_OP_READ_SEARCH 0x06
-
-#define SPECIFY_EF 0x1
-#define SPECIFY_DF 0x2
-#define SPECIFY_ANY 0x3
-
-#define EF_DKEK 0x108F
-#define EF_PRKDFS 0x6040
-#define EF_PUKDFS 0x6041
-#define EF_CDFS 0x6042
-#define EF_AODFS 0x6043
-#define EF_DODFS 0x6044
-#define EF_SKDFS 0x6045
-#define EF_DEVOPS 0x100E
-
-#define MAX_DEPTH 4
-
-typedef struct file
-{
- const uint16_t fid;
- const uint8_t parent; //entry number in the whole table!!
- const uint8_t *name;
- const uint8_t type;
- const uint8_t ef_structure;
- uint8_t *data; //should include 2 bytes len at begining
- const uint8_t acl[7];
-} __attribute__((packed)) file_t;
-
-typedef struct file_chain
-{
- file_t *file;
- struct file_chain *next;
-} file_chain_t;
-
-extern file_t *currentEF;
-extern file_t *currentDF;
-extern const file_t *selected_applet;
-
-extern const file_t *MF;
-extern const file_t *file_last;
-extern const file_t *file_openpgp;
-extern const file_t *file_sc_hsm;
-extern bool card_terminated;
-extern file_t *file_pin1;
-extern file_t *file_retries_pin1;
-extern file_t *file_sopin;
-extern file_t *file_retries_sopin;
-
-extern file_t *search_by_fid(const uint16_t fid, const file_t *parent, const uint8_t sp);
-extern file_t *search_by_name(uint8_t *name, uint16_t namelen);
-extern file_t *search_by_path(const uint8_t *pe_path, uint8_t pathlen, const file_t *parent);
-extern bool authenticate_action(const file_t *ef, uint8_t op);
-extern void process_fci(const file_t *pe);
-extern void scan_flash();
-extern void initialize_flash(bool);
-
-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);
-extern file_t *file_new(uint16_t);
-file_t *get_parent(file_t *f);
-
-extern uint16_t dynamic_files;
-extern file_t dynamic_file[];
-extern file_t *search_dynamic_file(uint16_t);
-extern int delete_dynamic_file(file_t *f);
-
-extern file_chain_t *add_file_to_chain(file_t *file, file_chain_t **chain);
-extern file_t *search_file_chain(uint16_t fid, file_chain_t *chain);
-extern bool isUserAuthenticated;
-
-#endif
-
diff --git a/src/fs/flash.c b/src/fs/flash.c
deleted file mode 100644
index 569b275..0000000
--- a/src/fs/flash.c
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#include
-#include
-
-#include "pico/stdlib.h"
-#include "hardware/flash.h"
-#include "hsm2040.h"
-#include "tusb.h"
-#include "file.h"
-#include "sc_hsm.h"
-
-/*
- * ------------------------------------------------------
- * | |
- * | next_addr | prev_addr | fid | data (len + payload) |
- * | |
- * ------------------------------------------------------
- */
-#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))
-#define FLASH_PERMANENT_REGION (4*FLASH_SECTOR_SIZE) // 4 sectors (16kb) of permanent memory
-
-//To avoid possible future allocations, data region starts at the end of flash and goes upwards to the center region
-
-const uintptr_t start_data_pool = (XIP_BASE + FLASH_TARGET_OFFSET);
-const uintptr_t end_data_pool = (XIP_BASE + PICO_FLASH_SIZE_BYTES)-FLASH_DATA_HEADER_SIZE-FLASH_PERMANENT_REGION; //This is a fixed value. DO NOT CHANGE
-#define FLASH_ADDR_DATA_STORAGE_START start_data_pool
-
-extern int flash_program_block(uintptr_t addr, const uint8_t *data, size_t len);
-extern int flash_program_halfword (uintptr_t addr, uint16_t data);
-extern int flash_program_uintptr(uintptr_t, uintptr_t);
-extern uintptr_t flash_read_uintptr(uintptr_t addr);
-extern uint16_t flash_read_uint16(uintptr_t addr);
-
-extern void low_flash_available();
-
-uintptr_t allocate_free_addr(uint16_t size) {
- if (size > FLASH_SECTOR_SIZE)
- return 0x0; //ERROR
- size_t real_size = size+sizeof(uint16_t)+sizeof(uintptr_t)+sizeof(uint16_t)+sizeof(uintptr_t); //len+len size+next address+fid+prev_addr size
- uintptr_t next_base = 0x0;
- for (uintptr_t base = end_data_pool; base >= start_data_pool; base = next_base) {
- uintptr_t addr_alg = base & -FLASH_SECTOR_SIZE; //start address of sector
- uintptr_t potential_addr = base-real_size;
- next_base = flash_read_uintptr(base);
- //printf("nb %x %x %x %x\r\n",base,next_base,addr_alg,potential_addr);
- //printf("fid %x\r\n",flash_read_uint16(next_base+sizeof(uintptr_t)));
- if (next_base == 0x0) { //we are at the end
- //now we check if we fit in the current sector
- if (addr_alg <= potential_addr) //it fits in the current sector
- {
- flash_program_uintptr(potential_addr, 0x0);
- flash_program_uintptr(potential_addr+sizeof(uintptr_t), base);
- flash_program_uintptr(base, potential_addr);
- return potential_addr;
- }
- else if (addr_alg-FLASH_SECTOR_SIZE >= start_data_pool) { //check whether it fits in the next sector, so we take addr_aligned as the base
- potential_addr = addr_alg-real_size;
- flash_program_uintptr(potential_addr, 0x0);
- flash_program_uintptr(potential_addr+sizeof(uintptr_t), base);
- flash_program_uintptr(base, potential_addr);
- return potential_addr;
- }
- return 0x0;
- }
- //we check if |base-(next_addr+size_next_addr)| > |base-potential_addr| only if fid != 1xxx (not size blocked)
- else if (addr_alg <= potential_addr && base-(next_base+flash_read_uint16(next_base+sizeof(uintptr_t)+sizeof(uintptr_t)+sizeof(uint16_t))+2*sizeof(uint16_t)+2*sizeof(uintptr_t)) > base-potential_addr && flash_read_uint16(next_base+sizeof(uintptr_t)) & 0x1000 != 0x1000) {
- flash_program_uintptr(potential_addr, next_base);
- flash_program_uintptr(potential_addr+sizeof(uintptr_t), base);
- flash_program_uintptr(base, potential_addr);
- return potential_addr;
- }
- }
- return 0x0; //probably never reached
-}
-
-int flash_clear_file(file_t *file) {
- uintptr_t base_addr = (uintptr_t)(file->data-sizeof(uintptr_t)-sizeof(uint16_t)-sizeof(uintptr_t));
- uintptr_t prev_addr = flash_read_uintptr(base_addr+sizeof(uintptr_t));
- uintptr_t next_addr = flash_read_uintptr(base_addr);
- //printf("nc %x->%x %x->%x\r\n",prev_addr,flash_read_uintptr(prev_addr),base_addr,next_addr);
- flash_program_uintptr(prev_addr, next_addr);
- flash_program_halfword((uintptr_t)file->data, 0);
- if (next_addr > 0)
- flash_program_uintptr(next_addr+sizeof(uintptr_t), prev_addr);
- //printf("na %x->%x\r\n",prev_addr,flash_read_uintptr(prev_addr));
- return HSM_OK;
-}
-
-int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len) {
- if (!file)
- return HSM_ERR_NULL_PARAM;
- if (len > FLASH_SECTOR_SIZE)
- 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);
- if (data)
- flash_program_block((uintptr_t)file->data+sizeof(uint16_t), data, len);
- return HSM_OK;
- }
- else { //we clear the old file
- flash_clear_file(file);
- }
- }
- uintptr_t new_addr = allocate_free_addr(len);
- //printf("na %x\r\n",new_addr);
- if (new_addr == 0x0)
- return HSM_ERR_NO_MEMORY;
- file->data = (uint8_t *)new_addr+sizeof(uintptr_t)+sizeof(uint16_t)+sizeof(uintptr_t); //next addr+fid+prev addr
- flash_program_halfword(new_addr+sizeof(uintptr_t)+sizeof(uintptr_t), file->fid);
- flash_program_halfword((uintptr_t)file->data, len);
- if (data)
- flash_program_block((uintptr_t)file->data+sizeof(uint16_t), data, len);
- return HSM_OK;
-}
diff --git a/src/fs/low_flash.c b/src/fs/low_flash.c
deleted file mode 100644
index 4951fc6..0000000
--- a/src/fs/low_flash.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#include
-#include
-#include
-
-#include "pico/stdlib.h"
-#include "hardware/flash.h"
-#include "hardware/sync.h"
-#include "pico/mutex.h"
-#include "pico/sem.h"
-#include "pico/multicore.h"
-#include "hsm2040.h"
-#include "sc_hsm.h"
-#include
-
-#define TOTAL_FLASH_PAGES 4
-
-typedef struct page_flash {
- uint8_t page[FLASH_SECTOR_SIZE];
- uintptr_t address;
- bool ready;
- bool erase;
- size_t page_size; //this param is for easy erase. It allows to erase with a single call. IT DOES NOT APPLY TO WRITE
-} page_flash_t;
-
-static page_flash_t flash_pages[TOTAL_FLASH_PAGES];
-
-static mutex_t mtx_flash;
-static semaphore_t sem_wait;
-
-static uint8_t ready_pages = 0;
-
-bool flash_available = false;
-static bool locked_out = false;
-
-
-//this function has to be called from the core 0
-void do_flash()
-{
- if (mutex_try_enter(&mtx_flash, NULL) == true) {
- if (locked_out == true && flash_available == true && ready_pages > 0) {
- //printf(" DO_FLASH AVAILABLE\r\n");
- for (int r = 0; r < TOTAL_FLASH_PAGES; r++) {
- if (flash_pages[r].ready == true) {
- //printf("WRITTING %X\r\n",flash_pages[r].address-XIP_BASE);
- while (multicore_lockout_start_timeout_us(1000) == false);
- //printf("WRITTING %X\r\n",flash_pages[r].address-XIP_BASE);
- uint32_t ints = save_and_disable_interrupts();
- flash_range_erase(flash_pages[r].address-XIP_BASE, FLASH_SECTOR_SIZE);
- flash_range_program(flash_pages[r].address-XIP_BASE, flash_pages[r].page, FLASH_SECTOR_SIZE);
- restore_interrupts (ints);
- while (multicore_lockout_end_timeout_us(1000) == false);
- //printf("WRITEN %X !\r\n",flash_pages[r].address);
-
- flash_pages[r].ready = false;
- ready_pages--;
- }
- else if (flash_pages[r].erase == true) {
- while (multicore_lockout_start_timeout_us(1000) == false);
- //printf("WRITTING\r\n");
- flash_range_erase(flash_pages[r].address-XIP_BASE, flash_pages[r].page_size ? ((int)(flash_pages[r].page_size/FLASH_SECTOR_SIZE))*FLASH_SECTOR_SIZE : FLASH_SECTOR_SIZE);
- while (multicore_lockout_end_timeout_us(1000) == false);
- flash_pages[r].erase = false;
- ready_pages--;
- }
- }
- flash_available = false;
- if (ready_pages != 0) {
- DEBUG_INFO("ERROR: DO FLASH DOES NOT HAVE ZERO PAGES");
- }
- }
- mutex_exit(&mtx_flash);
- }
- sem_release(&sem_wait);
-}
-
-//this function has to be called from the core 0
-void low_flash_init() {
- mutex_init(&mtx_flash);
- sem_init(&sem_wait, 0, 1);
- memset(flash_pages, 0, sizeof(page_flash_t)*TOTAL_FLASH_PAGES);
-}
-
-void low_flash_init_core1() {
- mutex_enter_blocking(&mtx_flash);
- multicore_lockout_victim_init();
- locked_out = true;
- mutex_exit(&mtx_flash);
-}
-
-void wait_flash_finish() {
- sem_acquire_blocking(&sem_wait); //blocks until released
- //wake up
- sem_acquire_blocking(&sem_wait); //decrease permits
-}
-
-void low_flash_available() {
- mutex_enter_blocking(&mtx_flash);
- flash_available = true;
- mutex_exit(&mtx_flash);
-}
-
-page_flash_t *find_free_page(uintptr_t addr) {
- uintptr_t addr_alg = addr & -FLASH_SECTOR_SIZE;
- page_flash_t *p = NULL;
- for (int r = 0; r < TOTAL_FLASH_PAGES; r++)
- {
- if ((!flash_pages[r].ready && !flash_pages[r].erase) || flash_pages[r].address == addr_alg) //first available
- {
- p = &flash_pages[r];
- if (!flash_pages[r].ready && !flash_pages[r].erase)
- {
- memcpy(p->page, (uint8_t *)addr_alg, FLASH_SECTOR_SIZE);
- ready_pages++;
- p->address = addr_alg;
- p->ready = true;
- }
- return p;
- }
- }
- return NULL;
-}
-
-int flash_program_block(uintptr_t addr, const uint8_t *data, size_t len) {
- uintptr_t addr_alg = addr & -FLASH_SECTOR_SIZE;
- page_flash_t *p = NULL;
-
- if (!data || len == 0)
- return HSM_ERR_NULL_PARAM;
-
- mutex_enter_blocking(&mtx_flash);
- if (ready_pages == TOTAL_FLASH_PAGES) {
- mutex_exit(&mtx_flash);
- DEBUG_INFO("ERROR: ALL FLASH PAGES CACHED\r\n");
- return HSM_ERR_NO_MEMORY;
- }
- if (!(p = find_free_page(addr)))
- {
- mutex_exit(&mtx_flash);
- DEBUG_INFO("ERROR: FLASH CANNOT FIND A PAGE (rare error)\r\n");
- 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 HSM_OK;
-}
-
-int flash_program_halfword (uintptr_t addr, uint16_t data) {
- return flash_program_block(addr, (const uint8_t *)&data, sizeof(uint16_t));
-}
-
-int flash_program_word (uintptr_t addr, uint32_t data) {
- return flash_program_block(addr, (const uint8_t *)&data, sizeof(uint32_t));
-}
-
-int flash_program_uintptr (uintptr_t addr, uintptr_t data) {
- return flash_program_block(addr, (const uint8_t *)&data, sizeof(uintptr_t));
-}
-
-uint8_t *flash_read(uintptr_t addr) {
- uintptr_t addr_alg = addr & -FLASH_SECTOR_SIZE;
- mutex_enter_blocking(&mtx_flash);
- if (ready_pages > 0) {
- for (int r = 0; r < TOTAL_FLASH_PAGES; r++)
- {
- if (flash_pages[r].ready && flash_pages[r].address == addr_alg) {
- uint8_t *v = &flash_pages[r].page[addr&(FLASH_SECTOR_SIZE-1)];
- mutex_exit(&mtx_flash);
- return v;
- }
- }
- }
- uint8_t *v = (uint8_t *)addr;
- mutex_exit(&mtx_flash);
- return v;
-}
-
-uintptr_t flash_read_uintptr(uintptr_t addr) {
- uint8_t *p = flash_read(addr);
- uintptr_t v = 0x0;
- for (int i = 0; i < sizeof(uintptr_t); i++) {
- v |= (uintptr_t)p[i]<<(8*i);
- }
- return v;
-}
-uint16_t flash_read_uint16(uintptr_t addr) {
- uint8_t *p = flash_read(addr);
- uint16_t v = 0x0;
- for (int i = 0; i < sizeof(uint16_t); i++) {
- v |= p[i]<<(8*i);
- }
- 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) {
- uintptr_t addr_alg = addr & -FLASH_SECTOR_SIZE;
- page_flash_t *p = NULL;
-
- mutex_enter_blocking(&mtx_flash);
- if (ready_pages == TOTAL_FLASH_PAGES) {
- mutex_exit(&mtx_flash);
- DEBUG_INFO("ERROR: ALL FLASH PAGES CACHED\r\n");
- 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 HSM_ERR_MEMORY_FATAL;
- }
- p->erase = true;
- p->ready = false;
- p->page_size = page_size;
- mutex_exit(&mtx_flash);
-
- return HSM_OK;
-}
-
-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 false;
- }
- return true;
-}
diff --git a/src/hsm/crypto_utils.c b/src/hsm/crypto_utils.c
index 4df1811..287277e 100644
--- a/src/hsm/crypto_utils.c
+++ b/src/hsm/crypto_utils.c
@@ -85,7 +85,7 @@ int aes_encrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, u
memcpy(tmp_iv, iv, IV_SIZE);
int r = mbedtls_aes_setkey_enc(&aes, key, key_size);
if (r != 0)
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
if (mode == HSM_AES_MODE_CBC)
return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, len, tmp_iv, data, data);
return mbedtls_aes_crypt_cfb128(&aes, MBEDTLS_AES_ENCRYPT, len, &iv_offset, tmp_iv, data, data);
@@ -101,7 +101,7 @@ int aes_decrypt(const uint8_t *key, const uint8_t *iv, int key_size, int mode, u
memcpy(tmp_iv, iv, IV_SIZE);
int r = mbedtls_aes_setkey_dec(&aes, key, key_size);
if (r != 0)
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
if (mode == HSM_AES_MODE_CBC)
return mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, len, tmp_iv, data, data);
r = mbedtls_aes_setkey_enc(&aes, key, key_size); //CFB requires set_enc instead set_dec
diff --git a/src/hsm/dkek.c b/src/hsm/dkek.c
index cd89c65..d40d437 100644
--- a/src/hsm/dkek.c
+++ b/src/hsm/dkek.c
@@ -27,6 +27,7 @@
#include "mbedtls/cmac.h"
#include "mbedtls/rsa.h"
#include "mbedtls/ecdsa.h"
+#include "files.h"
static uint8_t dkek[IV_SIZE+32];
static uint8_t tmp_dkek[32];
@@ -35,15 +36,15 @@ extern uint8_t session_pin[32];
int load_dkek() {
if (has_session_pin == false)
- return HSM_NO_LOGIN;
+ return CCID_NO_LOGIN;
file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF);
if (!tf)
- return HSM_ERR_FILE_NOT_FOUND;
+ return CCID_ERR_FILE_NOT_FOUND;
memcpy(dkek, file_read(tf->data+sizeof(uint16_t)), IV_SIZE+32);
int ret = aes_decrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32);
if (ret != 0)
- return HSM_EXEC_ERROR;
- return HSM_OK;
+ return CCID_EXEC_ERROR;
+ return CCID_OK;
}
void release_dkek() {
@@ -59,11 +60,11 @@ int store_dkek_key() {
aes_encrypt_cfb_256(session_pin, dkek, dkek+IV_SIZE, 32);
file_t *tf = search_by_fid(EF_DKEK, NULL, SPECIFY_EF);
if (!tf)
- return HSM_ERR_FILE_NOT_FOUND;
+ return CCID_ERR_FILE_NOT_FOUND;
flash_write_data_to_file(tf, dkek, sizeof(dkek));
low_flash_available();
release_dkek();
- return HSM_OK;
+ return CCID_OK;
}
int save_dkek_key(const uint8_t *key) {
@@ -83,43 +84,43 @@ void import_dkek_share(const uint8_t *share) {
int dkek_kcv(uint8_t *kcv) { //kcv 8 bytes
uint8_t hsh[32];
int r = load_dkek();
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
hash256(dkek+IV_SIZE, 32, hsh);
release_dkek();
memcpy(kcv, hsh, 8);
- return HSM_OK;
+ return CCID_OK;
}
int dkek_kenc(uint8_t *kenc) { //kenc 32 bytes
uint8_t buf[32+4];
int r = load_dkek();
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
memcpy(buf, dkek+IV_SIZE, 32);
release_dkek();
memcpy(buf+32, "\x0\x0\x0\x1", 4);
hash256(buf, sizeof(buf), kenc);
memset(buf, 0, sizeof(buf));
- return HSM_OK;
+ return CCID_OK;
}
int dkek_kmac(uint8_t *kmac) { //kmac 32 bytes
uint8_t buf[32+4];
int r = load_dkek();
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
memcpy(buf, dkek+IV_SIZE, 32);
release_dkek();
memcpy(buf+32, "\x0\x0\x0\x2", 4);
hash256(buf, sizeof(buf), kmac);
memset(buf, 0, sizeof(buf));
- return HSM_OK;
+ return CCID_OK;
}
int dkek_encrypt(uint8_t *data, size_t len) {
int r;
- if ((r = load_dkek()) != HSM_OK)
+ if ((r = load_dkek()) != CCID_OK)
return r;
r = aes_encrypt_cfb_256(dkek+IV_SIZE, dkek, data, len);
release_dkek();
@@ -128,7 +129,7 @@ int dkek_encrypt(uint8_t *data, size_t len) {
int dkek_decrypt(uint8_t *data, size_t len) {
int r;
- if ((r = load_dkek()) != HSM_OK)
+ if ((r = load_dkek()) != CCID_OK)
return r;
r = aes_decrypt_cfb_256(dkek+IV_SIZE, dkek, data, len);
release_dkek();
@@ -137,7 +138,7 @@ int dkek_decrypt(uint8_t *data, size_t len) {
int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len) {
if (!(key_type & HSM_KEY_RSA) && !(key_type & HSM_KEY_EC) && !(key_type & HSM_KEY_AES))
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding)
memset(kb, 0, sizeof(kb));
@@ -167,9 +168,9 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len)
kb_len = 32;
if (kb_len != 16 && kb_len != 24 && kb_len != 32)
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
if (*out_len < 8+1+10+6+4+(2+32+14)+16)
- return HSM_WRONG_LENGTH;
+ return CCID_WRONG_LENGTH;
put_uint16_t(kb_len, kb+8);
memcpy(kb+10, key_ctx, kb_len);
@@ -182,7 +183,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len)
}
else if (key_type & HSM_KEY_RSA) {
if (*out_len < 8+1+12+6+(8+2*4+2*4096/8+3+13)+16) //13 bytes pading
- return HSM_WRONG_LENGTH;
+ return CCID_WRONG_LENGTH;
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *)key_ctx;
kb_len = 0;
put_uint16_t(mbedtls_rsa_get_len(rsa)*8, kb+8+kb_len); kb_len += 2;
@@ -199,7 +200,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len)
}
else if (key_type & HSM_KEY_EC) {
if (*out_len < 8+1+12+6+(8+2*8+9*66+2+4)+16) //4 bytes pading
- return HSM_WRONG_LENGTH;
+ return CCID_WRONG_LENGTH;
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *)key_ctx;
kb_len = 0;
put_uint16_t(mbedtls_mpi_size(&ecdsa->grp.P)*8, kb+8+kb_len); kb_len += 2;
@@ -265,7 +266,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len)
kb[kb_len] = 0x80;
}
int r = aes_encrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, kb_len_pad);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
memcpy(out+*out_len, kb, kb_len_pad);
@@ -276,7 +277,7 @@ int dkek_encode_key(void *key_ctx, int key_type, uint8_t *out, size_t *out_len)
*out_len += 16;
if (r != 0)
return r;
- return HSM_OK;
+ return CCID_OK;
}
int dkek_type_key(const uint8_t *in) {
@@ -303,27 +304,27 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
dkek_kenc(kenc);
if (memcmp(kcv, in, 8) != 0)
- return HSM_WRONG_DKEK;
+ return CCID_WRONG_DKEK;
uint8_t signature[16];
int r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len-16, signature);
if (r != 0)
- return HSM_WRONG_SIGNATURE;
+ return CCID_WRONG_SIGNATURE;
if (memcmp(signature, in+in_len-16, 16) != 0)
- return HSM_WRONG_SIGNATURE;
+ return CCID_WRONG_SIGNATURE;
int key_type = in[8];
if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15)
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
if ((key_type == 5 || key_type == 6) && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0)
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
if (key_type == 12 && memcmp(in+9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0)
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
if (key_type == 15 && memcmp(in+9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0)
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
size_t ofs = 9;
@@ -344,12 +345,12 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
ofs += len+2;
if ((in_len-16-ofs) % 16 != 0)
- return HSM_WRONG_PADDING;
+ return CCID_WRONG_PADDING;
uint8_t kb[8+2*4+2*4096/8+3+13]; //worst case: RSA-4096 (plus, 13 bytes padding)
memset(kb, 0, sizeof(kb));
memcpy(kb, in+ofs, in_len-16-ofs);
r = aes_decrypt(kenc, NULL, 256, HSM_AES_MODE_CBC, kb, in_len-16-ofs);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
int key_size = get_uint16_t(kb, 8);
@@ -364,14 +365,14 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
r = mbedtls_mpi_read_binary(&rsa->D, kb+ofs, len); ofs += len;
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
}
len = get_uint16_t(kb, ofs); ofs += 2;
r = mbedtls_mpi_read_binary(&rsa->N, kb+ofs, len); ofs += len;
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
}
}
else if (key_type == 6) {
@@ -385,7 +386,7 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
r = mbedtls_mpi_read_binary(&rsa->P, kb+ofs, len); ofs += len;
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
}
//PQ
@@ -395,7 +396,7 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
r = mbedtls_mpi_read_binary(&rsa->Q, kb+ofs, len); ofs += len;
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
}
//N
len = get_uint16_t(kb, ofs); ofs += len+2;
@@ -405,33 +406,33 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
r = mbedtls_mpi_read_binary(&rsa->E, kb+ofs, len); ofs += len;
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
}
if (key_type == 5) {
r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E);
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
}
}
else if (key_type == 6) {
r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E);
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
}
}
r = mbedtls_rsa_complete(rsa);
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
}
r = mbedtls_rsa_check_privkey(rsa);
if (r != 0) {
mbedtls_rsa_free(rsa);
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
}
}
else if (key_type == 12) {
@@ -449,7 +450,7 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb+ofs, len);
if (ec_id == MBEDTLS_ECP_DP_NONE) {
mbedtls_ecdsa_free(ecdsa);
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
}
ofs += len;
@@ -464,11 +465,11 @@ int dkek_decode_key(void *key_ctx, const uint8_t *in, size_t in_len, int *key_si
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb+ofs, len);
if (r != 0) {
mbedtls_ecdsa_free(ecdsa);
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
}
}
else if (key_type == 15) {
memcpy(key_ctx, kb+ofs, key_size);
}
- return HSM_OK;
+ return CCID_OK;
}
\ No newline at end of file
diff --git a/src/hsm/eac.c b/src/hsm/eac.c
index 99ddfc4..2db30c0 100644
--- a/src/hsm/eac.c
+++ b/src/hsm/eac.c
@@ -83,9 +83,9 @@ int sm_sign(uint8_t *in, size_t in_len, uint8_t *out) {
int sm_unwrap() {
uint8_t sm_indicator = (CLA(apdu) >> 2) & 0x3;
if (sm_indicator == 0)
- return HSM_OK;
+ return CCID_OK;
int r = sm_verify();
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
int le = sm_get_le();
if (le >= 0)
@@ -106,22 +106,22 @@ int sm_unwrap() {
}
}
if (!body)
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
if (is87 && *body++ != 0x1) {
- return HSM_WRONG_PADDING;
+ return CCID_WRONG_PADDING;
}
sm_update_iv();
aes_decrypt(sm_kenc, sm_iv, 128, HSM_AES_MODE_CBC, body, body_size);
memmove(apdu.cmd_apdu_data, body, body_size);
apdu.cmd_apdu_data_len = sm_remove_padding(apdu.cmd_apdu_data, body_size);
DEBUG_PAYLOAD(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len);
- return HSM_OK;
+ return CCID_OK;
}
int sm_wrap() {
uint8_t sm_indicator = (CLA(apdu) >> 2) & 0x3;
if (sm_indicator == 0)
- return HSM_OK;
+ return CCID_OK;
uint8_t input[1024];
size_t input_len = 0;
memset(input, 0, sizeof(input));
@@ -176,7 +176,7 @@ int sm_wrap() {
res_APDU_size += 8;
if (apdu.expected_res_size > 0)
apdu.expected_res_size = res_APDU_size;
- return HSM_OK;
+ return CCID_OK;
}
int sm_get_le() {
@@ -210,7 +210,7 @@ int sm_verify() {
if (data_len % sm_blocksize)
data_len += sm_blocksize;
if (data_len+(add_header ? sm_blocksize : 0) > 1024)
- return HSM_WRONG_LENGTH;
+ return CCID_WRONG_LENGTH;
mbedtls_mpi ssc;
mbedtls_mpi_init(&ssc);
mbedtls_mpi_add_int(&ssc, &sm_mSSC, 1);
@@ -219,7 +219,7 @@ int sm_verify() {
input_len += sm_blocksize;
mbedtls_mpi_free(&ssc);
if (r != 0)
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
if (add_header) {
input[input_len++] = CLA(apdu);
input[input_len++] = INS(apdu);
@@ -248,7 +248,7 @@ int sm_verify() {
}
}
if (!mac)
- return HSM_WRONG_DATA;
+ return CCID_WRONG_DATA;
if (some_added) {
input[input_len++] = 0x80;
input_len += (sm_blocksize - (input_len%sm_blocksize));
@@ -256,10 +256,10 @@ int sm_verify() {
uint8_t signature[16];
r = sm_sign(input, input_len, signature);
if (r != 0)
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
if (memcmp(signature, mac, mac_len) == 0)
- return HSM_OK;
- return HSM_VERIFICATION_FAILED;
+ return CCID_OK;
+ return CCID_VERIFICATION_FAILED;
}
int sm_remove_padding(const uint8_t *data, size_t data_len) {
diff --git a/src/hsm/eac.h b/src/hsm/eac.h
index 3270753..c1e315a 100644
--- a/src/hsm/eac.h
+++ b/src/hsm/eac.h
@@ -20,7 +20,7 @@
#include
#include "pico/stdlib.h"
-#include "hsm2040.h"
+#include "ccid2040.h"
typedef enum MSE_protocol {
MSE_AES = 0,
diff --git a/src/hsm/files.c b/src/hsm/files.c
new file mode 100644
index 0000000..12e30fc
--- /dev/null
+++ b/src/hsm/files.c
@@ -0,0 +1,60 @@
+/*
+ * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, version 3.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "files.h"
+
+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 | 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
+ /* 7 */ { .fid = 0x5032 , .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.TokenInfo
+ /* 8 */ { .fid = 0x5033 , .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, //EF.UnusedSpace
+ /* 9 */ { .fid = 0x1081 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //PIN (PIN1)
+ /* 10 */ { .fid = 0x1082 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //max retries PIN (PIN1)
+ /* 11 */ { .fid = 0x1083 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //retries PIN (PIN1)
+ /* 12 */ { .fid = 0x1088 , .parent = 5, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0xff} }, //PIN (SOPIN)
+ /* 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_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];
+const file_t *file_last = &file_entries[sizeof(file_entries)/sizeof(file_t)-1];
+const file_t *file_openpgp = &file_entries[sizeof(file_entries)/sizeof(file_t)-3];
+const file_t *file_sc_hsm = &file_entries[sizeof(file_entries)/sizeof(file_t)-2];
+file_t *file_pin1 = NULL;
+file_t *file_retries_pin1 = NULL;
+file_t *file_sopin = NULL;
+file_t *file_retries_sopin = NULL;
\ No newline at end of file
diff --git a/src/rng/neug.h b/src/hsm/files.h
similarity index 64%
rename from src/rng/neug.h
rename to src/hsm/files.h
index 24fe1695..a1a51bd 100644
--- a/src/rng/neug.h
+++ b/src/hsm/files.h
@@ -15,15 +15,24 @@
* along with this program. If not, see .
*/
-#ifndef _NEUG_H_
-#define _NEUG_H_
-#define NEUG_PRE_LOOP 32
+#ifndef _FILES_H_
+#define _FILES_H_
-void neug_init(uint32_t *buf, uint8_t size);
-uint32_t neug_get();
-void neug_flush(void);
-void neug_wait_full(void);
-void neug_fini(void);
+#include "file.h"
+
+#define EF_DKEK 0x108F
+#define EF_PRKDFS 0x6040
+#define EF_PUKDFS 0x6041
+#define EF_CDFS 0x6042
+#define EF_AODFS 0x6043
+#define EF_DODFS 0x6044
+#define EF_SKDFS 0x6045
+#define EF_DEVOPS 0x100E
+
+extern file_t *file_pin1;
+extern file_t *file_retries_pin1;
+extern file_t *file_sopin;
+extern file_t *file_retries_sopin;
#endif
\ No newline at end of file
diff --git a/src/hsm/hsm2040.c b/src/hsm/hsm2040.c
deleted file mode 100644
index 6b4e337..0000000
--- a/src/hsm/hsm2040.c
+++ /dev/null
@@ -1,1691 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#include
-
-// Pico
-#include "pico/stdlib.h"
-#include
-
-// For memcpy
-#include
-
-#include "bsp/board.h"
-#include "tusb.h"
-#include "usb_descriptors.h"
-#include "device/usbd_pvt.h"
-#include "pico/multicore.h"
-#include "random.h"
-#include "hsm2040.h"
-#include "hardware/rtc.h"
-
-extern void do_flash();
-extern void low_flash_init();
-
-static uint8_t itf_num;
-
-#if MAX_RES_APDU_DATA_SIZE > MAX_CMD_APDU_DATA_SIZE
-#define USB_BUF_SIZE (MAX_RES_APDU_DATA_SIZE+20+9)
-#else
-#define USB_BUF_SIZE (MAX_CMD_APDU_DATA_SIZE+20+9)
-#endif
-
-struct apdu apdu;
-static struct ccid ccid;
-
-static uint8_t ccid_buffer[USB_BUF_SIZE];
-
-#define CCID_SET_PARAMS 0x61 /* non-ICCD command */
-#define CCID_POWER_ON 0x62
-#define CCID_POWER_OFF 0x63
-#define CCID_SLOT_STATUS 0x65 /* non-ICCD command */
-#define CCID_SECURE 0x69 /* non-ICCD command */
-#define CCID_GET_PARAMS 0x6C /* non-ICCD command */
-#define CCID_RESET_PARAMS 0x6D /* non-ICCD command */
-#define CCID_XFR_BLOCK 0x6F
-#define CCID_DATA_BLOCK_RET 0x80
-#define CCID_SLOT_STATUS_RET 0x81 /* non-ICCD result */
-#define CCID_PARAMS_RET 0x82 /* non-ICCD result */
-
-#define CCID_MSG_SEQ_OFFSET 6
-#define CCID_MSG_STATUS_OFFSET 7
-#define CCID_MSG_ERROR_OFFSET 8
-#define CCID_MSG_CHAIN_OFFSET 9
-#define CCID_MSG_DATA_OFFSET 10 /* == CCID_MSG_HEADER_SIZE */
-#define CCID_MAX_MSG_DATA_SIZE USB_BUF_SIZE
-
-#define CCID_STATUS_RUN 0x00
-#define CCID_STATUS_PRESENT 0x01
-#define CCID_STATUS_NOTPRESENT 0x02
-#define CCID_CMD_STATUS_OK 0x00
-#define CCID_CMD_STATUS_ERROR 0x40
-#define CCID_CMD_STATUS_TIMEEXT 0x80
-
-#define CCID_ERROR_XFR_OVERRUN 0xFC
-
-/*
- * Since command-byte is at offset 0,
- * error with offset 0 means "command not supported".
- */
-#define CCID_OFFSET_CMD_NOT_SUPPORTED 0
-#define CCID_OFFSET_DATA_LEN 1
-#define CCID_OFFSET_PARAM 8
-
-static app_t apps[4];
-static uint8_t num_apps = 0;
-
-app_t *current_app = NULL;
-
-extern void card_thread();
-
-queue_t *card_comm = NULL;
-queue_t *ccid_comm = NULL;
-extern void low_flash_init_core1();
-
-int register_app(app_t * (*select_aid)()) {
- if (num_apps < sizeof(apps)/sizeof(app_t)) {
- apps[num_apps].select_aid = select_aid;
- num_apps++;
- return 1;
- }
- return 0;
-}
-
-struct ep_in {
- uint8_t ep_num;
- uint8_t tx_done;
- const uint8_t *buf;
- size_t cnt;
- size_t buf_len;
- void *priv;
- void (*next_buf) (struct ep_in *epi, size_t len);
-};
-
-static void epi_init (struct ep_in *epi, int ep_num, void *priv)
-{
- epi->ep_num = ep_num;
- epi->tx_done = 0;
- epi->buf = NULL;
- epi->cnt = 0;
- epi->buf_len = 0;
- epi->priv = priv;
- epi->next_buf = NULL;
-}
-
-struct ep_out {
- uint8_t ep_num;
- uint8_t err;
- uint8_t *buf;
- size_t cnt;
- size_t buf_len;
- void *priv;
- void (*next_buf) (struct ep_out *epo, size_t len);
- int (*end_rx) (struct ep_out *epo, size_t orig_len);
- uint8_t ready;
-};
-
-static struct ep_out endpoint_out;
-static struct ep_in endpoint_in;
-
-static void epo_init (struct ep_out *epo, int ep_num, void *priv)
-{
- epo->ep_num = ep_num;
- epo->err = 0;
- epo->buf = NULL;
- epo->cnt = 0;
- epo->buf_len = 0;
- epo->priv = priv;
- epo->next_buf = NULL;
- epo->end_rx = NULL;
- epo->ready = 0;
-}
-
-struct ccid_header {
- uint8_t msg_type;
- uint32_t data_len;
- uint8_t slot;
- uint8_t seq;
- uint8_t rsvd;
- uint16_t param;
-} __attribute__((packed));
-
-
-/* Data structure handled by CCID layer */
-struct ccid {
- uint32_t ccid_state : 4;
- uint32_t state : 4;
- uint32_t err : 1;
- uint32_t tx_busy : 1;
- uint32_t timeout_cnt: 3;
-
- uint8_t *p;
- size_t len;
-
- struct ccid_header ccid_header;
-
- uint8_t sw1sw2[2];
- uint8_t chained_cls_ins_p1_p2[4];
-
- struct ep_out *epo;
- struct ep_in *epi;
-
- queue_t ccid_comm;
- queue_t card_comm;
-
- uint8_t application;
-
- struct apdu *a;
-};
-
-static uint8_t endp1_rx_buf[64];
-static uint8_t endp1_tx_buf[64];
-
-#define APDU_STATE_WAIT_COMMAND 0
-#define APDU_STATE_COMMAND_CHAINING 1
-#define APDU_STATE_COMMAND_RECEIVED 2
-#define APDU_STATE_RESULT 3
-#define APDU_STATE_RESULT_GET_RESPONSE 4
-
-static void ccid_prepare_receive (struct ccid *c);
-static void apdu_init (struct apdu *a);
-
-static void ccid_reset (struct ccid *c)
-{
- apdu_init(c->a);
- c->err = 0;
- c->tx_busy = 0;
- c->state = APDU_STATE_WAIT_COMMAND;
- c->p = c->a->cmd_apdu_data;
- c->len = MAX_CMD_APDU_DATA_SIZE;
- c->a->cmd_apdu_data_len = 0;
- c->a->expected_res_size = 0;
-}
-
-static void ccid_init(struct ccid *c, struct ep_in *epi, struct ep_out *epo, struct apdu *a)
-{
- c->ccid_state = CCID_STATE_START;
- c->err = 0;
- c->tx_busy = 0;
- c->state = APDU_STATE_WAIT_COMMAND;
- c->p = a->cmd_apdu_data;
- c->len = MAX_CMD_APDU_DATA_SIZE;
- memset (&c->ccid_header, 0, sizeof (struct ccid_header));
- c->sw1sw2[0] = 0x90;
- c->sw1sw2[1] = 0x00;
- c->application = 0;
- c->epi = epi;
- c->epo = epo;
- c->a = a;
-
- queue_init(&c->card_comm, sizeof(uint32_t), 64);
- queue_init(&c->ccid_comm, sizeof(uint32_t), 64);
-}
-
-#define CMD_APDU_HEAD_SIZE 5
-
-static void apdu_init (struct apdu *a)
-{
- a->seq = 0; /* will be set by lower layer */
- a->cmd_apdu_head = &ccid_buffer[0];
- a->cmd_apdu_data = &ccid_buffer[5];
- a->cmd_apdu_data_len = 0; /* will be set by lower layer */
- a->expected_res_size = 0; /* will be set by lower layer */
-
- a->sw = 0x9000; /* will be set by upper layer */
- a->res_apdu_data = &ccid_buffer[5]; /* will be set by upper layer */
- a->res_apdu_data_len = 0; /* will be set by upper layer */
-}
-
-/*
-!!!! IT USES ENDP2, Interruption
-
-#define NOTIFY_SLOT_CHANGE 0x50
-static void ccid_notify_slot_change(struct ccid *c)
-{
- uint8_t msg;
- uint8_t notification[2];
-
- if (c->ccid_state == CCID_STATE_NOCARD)
- msg = 0x02;
- else
- msg = 0x03;
-
- notification[0] = NOTIFY_SLOT_CHANGE;
- notification[1] = msg;
-
- tud_vendor_write(notification, sizeof(notification));
-}
-*/
-
-#define USB_CCID_TIMEOUT (50)
-
-#define GPG_THREAD_TERMINATED 0xffff
-#define GPG_ACK_TIMEOUT 0x6600
-
-static void ccid_init_cb(void) {
- struct ccid *c = &ccid;
- TU_LOG1("-------- CCID INIT\r\n");
- vendord_init();
-
- //ccid_notify_slot_change(c);
-}
-
-static void ccid_reset_cb(uint8_t rhport) {
- TU_LOG1("-------- CCID RESET\r\n");
- itf_num = 0;
- vendord_reset(rhport);
-}
-
-static uint16_t ccid_open(uint8_t rhport, tusb_desc_interface_t const *itf_desc, uint16_t max_len) {
- uint8_t *itf_vendor = (uint8_t *)malloc(sizeof(uint8_t)*max_len);
- TU_LOG1("-------- CCID OPEN\r\n");
- TU_VERIFY(itf_desc->bInterfaceClass == TUSB_CLASS_SMART_CARD && itf_desc->bInterfaceSubClass == 0 && itf_desc->bInterfaceProtocol == 0, 0);
-
- //vendord_open expects a CLASS_VENDOR interface class
- memcpy(itf_vendor, itf_desc, sizeof(uint8_t)*max_len);
- ((tusb_desc_interface_t *)itf_vendor)->bInterfaceClass = TUSB_CLASS_VENDOR_SPECIFIC;
- vendord_open(rhport, (tusb_desc_interface_t *)itf_vendor, max_len);
- free(itf_vendor);
-
- uint16_t const drv_len = sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t);
- TU_VERIFY(max_len >= drv_len, 0);
-
- itf_num = itf_desc->bInterfaceNumber;
- return drv_len;
-}
-
-// Support for parameterized reset via vendor interface control request
-static bool ccid_control_xfer_cb(uint8_t __unused rhport, uint8_t stage, tusb_control_request_t const * request) {
- // nothing to do with DATA & ACK stage
- TU_LOG2("-------- CCID CTRL XFER\r\n");
- if (stage != CONTROL_STAGE_SETUP) return true;
-
- if (request->wIndex == itf_num)
- {
- TU_LOG2("-------- bmRequestType %x, bRequest %x, wValue %x, wLength %x\r\n",request->bmRequestType,request->bRequest, request->wValue, request->wLength);
-/*
-#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_BOOTSEL
- if (request->bRequest == RESET_REQUEST_BOOTSEL) {
-#ifdef PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED
- uint gpio_mask = 1u << PICO_STDIO_USB_RESET_BOOTSEL_ACTIVITY_LED;
-#else
- uint gpio_mask = 0u;
-#endif
-#if !PICO_STDIO_USB_RESET_BOOTSEL_FIXED_ACTIVITY_LED
- if (request->wValue & 0x100) {
- gpio_mask = 1u << (request->wValue >> 9u);
- }
-#endif
- reset_usb_boot(gpio_mask, (request->wValue & 0x7f) | PICO_STDIO_USB_RESET_BOOTSEL_INTERFACE_DISABLE_MASK);
- // does not return, otherwise we'd return true
- }
-#endif
-
-#if PICO_STDIO_USB_RESET_INTERFACE_SUPPORT_RESET_TO_FLASH_BOOT
- if (request->bRequest == RESET_REQUEST_FLASH) {
- watchdog_reboot(0, 0, PICO_STDIO_USB_RESET_RESET_TO_FLASH_DELAY_MS);
- return true;
- }
-#endif
-*/
- return true;
- }
- return false;
-}
-
-static bool ccid_xfer_cb(uint8_t rhport, uint8_t ep_addr, xfer_result_t result, uint32_t xferred_bytes) {
- //TU_LOG2("------ CALLED XFER_CB\r\n");
- return vendord_xfer_cb(rhport, ep_addr, result, xferred_bytes);
- //return true;
-}
-
-
-static usbd_class_driver_t const ccid_driver =
-{
-#if CFG_TUSB_DEBUG >= 2
- .name = "CCID",
-#endif
- .init = ccid_init_cb,
- .reset = ccid_reset_cb,
- .open = ccid_open,
- .control_xfer_cb = ccid_control_xfer_cb,
- .xfer_cb = ccid_xfer_cb,
- .sof = NULL
-};
-
-// Implement callback to add our custom driver
-usbd_class_driver_t const *usbd_app_driver_get_cb(uint8_t *driver_count) {
- *driver_count = 1;
- return &ccid_driver;
-}
-
-
-static uint32_t blink_interval_ms = BLINK_NOT_MOUNTED;
-
-void led_set_blink(uint32_t mode) {
- blink_interval_ms = mode;
-}
-
-void execute_tasks();
-
-static void wait_button() {
- led_set_blink((1000 << 16) | 100);
- while (board_button_read() == false) {
- execute_tasks();
- //sleep_ms(10);
- }
- while (board_button_read() == true) {
- execute_tasks();
- //sleep_ms(10);
- }
- led_set_blink(BLINK_PROCESSING);
-}
-
-void usb_tx_enable(const uint8_t *buf, uint32_t len)
-{
- if (len > 0) {
- if (buf[0] != 0x81)
- DEBUG_PAYLOAD(buf,len);
- //DEBUG_PAYLOAD(buf,len);
- tud_vendor_write(buf, len);
- }
-}
-
-/*
- * ATR (Answer To Reset) string
- *
- * TS = 0x3b: Direct conversion
- * T0 = 0xda: TA1, TC1 and TD1 follow, 10 historical bytes
- * TA1 = 0x11: FI=1, DI=1
- * TC1 = 0xff
- * TD1 = 0x81: TD2 follows, T=1
- * TD2 = 0xb1: TA3, TB3 and TD3 follow, T=1
- * TA3 = 0xFE: IFSC = 254 bytes
- * TB3 = 0x55: BWI = 5, CWI = 5 (BWT timeout 3.2 sec)
- * TD3 = 0x1f: TA4 follows, T=15
- * TA4 = 0x03: 5V or 3.3V
- *
- * Minimum: 0x3b, 0x8a, 0x80, 0x01
- *
- */
-static const uint8_t ATR_head[] = {
- 0x3b, 0xda, 0x11, 0xff, 0x81, 0xb1, 0xfe, 0x55, 0x1f, 0x03,
- //0x3B,0xFE,0x18,0x00,0x00,0x81,0x31,0xFE,0x45,0x80,0x31,0x81,0x54,0x48,0x53,0x4D,0x31,0x73,0x80,0x21,0x40,0x81,0x07,0xFA
-};
-
-/* Send back ATR (Answer To Reset) */
-static enum ccid_state ccid_power_on(struct ccid *c)
-{
- TU_LOG1("!!! CCID POWER ON %d\r\n",c->application);
- uint8_t p[CCID_MSG_HEADER_SIZE+1]; /* >= size of historical_bytes -1 */
- int hist_len = historical_bytes[0];
-
- //char atr_sc_hsm[] = { 0x3B,0x8E,0x80,0x01,0x80,0x31,0x81,0x54,0x48,0x53,0x4D,0x31,0x73,0x80,0x21,0x40,0x81,0x07,0x18 };
- //char atr_sc_hsm[] = { 0x3B, 0xDE, 0x18, 0xFF, 0x81, 0x91, 0xFE, 0x1F, 0xC3, 0x80, 0x31, 0x81, 0x54, 0x48, 0x53, 0x4D, 0x31, 0x73, 0x80, 0x21, 0x40, 0x81, 0x07, 0x1C };
- char atr_sc_hsm[] = { 0x3B,0xFE,0x18,0x00,0x00,0x81,0x31,0xFE,0x45,0x80,0x31,0x81,0x54,0x48,0x53,0x4D,0x31,0x73,0x80,0x21,0x40,0x81,0x07,0xFA };
- uint8_t mode = 1; //1 sc-hsm, 0 openpgp
- size_t size_atr;
- if (mode == 1)
- size_atr = sizeof(atr_sc_hsm);
- else
- size_atr = sizeof (ATR_head) + hist_len + 1;
- uint8_t xor_check = 0;
- int i;
- if (c->application == 0)
- {
- multicore_reset_core1();
- multicore_launch_core1(card_thread);
- multicore_fifo_push_blocking((uint32_t)&c->ccid_comm);
- multicore_fifo_push_blocking((uint32_t)&c->card_comm);
- c->application = 1;
- }
- p[0] = CCID_DATA_BLOCK_RET;
- p[1] = size_atr;
- p[2] = 0x00;
- p[3] = 0x00;
- p[4] = 0x00;
- p[5] = 0x00; /* Slot */
- p[CCID_MSG_SEQ_OFFSET] = c->ccid_header.seq;
- p[CCID_MSG_STATUS_OFFSET] = 0x00;
- p[CCID_MSG_ERROR_OFFSET] = 0x00;
- p[CCID_MSG_CHAIN_OFFSET] = 0x00;
-
- memcpy(endp1_tx_buf, p, CCID_MSG_HEADER_SIZE);
- if (mode == 1)
- {
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE, atr_sc_hsm, sizeof(atr_sc_hsm));
- }
- else
- {
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE, ATR_head, sizeof (ATR_head));
-
- for (i = 1; i < (int)sizeof (ATR_head); i++)
- xor_check ^= ATR_head[i];
- memcpy (p, historical_bytes + 1, hist_len);
-#ifdef LIFE_CYCLE_MANAGEMENT_SUPPORT
- if (file_selection == 255)
- p[7] = 0x03;
-#endif
- for (i = 0; i < hist_len; i++)
- xor_check ^= p[i];
- p[i] = xor_check;
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE+sizeof (ATR_head), p, hist_len+1);
- }
-
- /* This is a single packet Bulk-IN transaction */
- c->epi->buf = NULL;
- c->epi->tx_done = 1;
-
- usb_tx_enable(endp1_tx_buf, CCID_MSG_HEADER_SIZE + size_atr);
-
- DEBUG_INFO("ON\r\n");
- c->tx_busy = 1;
- led_set_blink(BLINK_MOUNTED);
- return CCID_STATE_WAIT;
-}
-
-static void ccid_send_status(struct ccid *c)
-{
- uint8_t ccid_reply[CCID_MSG_HEADER_SIZE];
-
- ccid_reply[0] = CCID_SLOT_STATUS_RET;
- ccid_reply[1] = 0x00;
- ccid_reply[2] = 0x00;
- ccid_reply[3] = 0x00;
- ccid_reply[4] = 0x00;
- ccid_reply[5] = 0x00; /* Slot */
- ccid_reply[CCID_MSG_SEQ_OFFSET] = c->ccid_header.seq;
- if (c->ccid_state == CCID_STATE_NOCARD)
- ccid_reply[CCID_MSG_STATUS_OFFSET] = 2; /* 2: No ICC present */
- else if (c->ccid_state == CCID_STATE_START)
- /* 1: ICC present but not activated */
- ccid_reply[CCID_MSG_STATUS_OFFSET] = 1;
- else
- ccid_reply[CCID_MSG_STATUS_OFFSET] = 0; /* An ICC is present and active */
- ccid_reply[CCID_MSG_ERROR_OFFSET] = 0x00;
- ccid_reply[CCID_MSG_CHAIN_OFFSET] = 0x00;
-
- /* This is a single packet Bulk-IN transaction */
- c->epi->buf = NULL;
- c->epi->tx_done = 1;
-
- memcpy(endp1_tx_buf, ccid_reply, CCID_MSG_HEADER_SIZE);
- usb_tx_enable(endp1_tx_buf, CCID_MSG_HEADER_SIZE);
- c->tx_busy = 1;
-}
-
-static enum ccid_state ccid_power_off(struct ccid *c)
-{
- if (c->application)
- {
- uint32_t flag = EV_EXIT;
- queue_try_add(&c->card_comm, &flag);
- c->application = 0;
- }
-
- c->ccid_state = CCID_STATE_START; /* This status change should be here */
- ccid_send_status (c);
- DEBUG_INFO ("OFF\r\n");
- c->tx_busy = 1;
- led_set_blink(BLINK_SUSPENDED);
- return CCID_STATE_START;
-}
-
-static void no_buf (struct ep_in *epi, size_t len)
-{
- (void)len;
- epi->buf = NULL;
- epi->cnt = 0;
- epi->buf_len = 0;
-}
-
-static void set_sw1sw2(struct ccid *c, size_t chunk_len)
-{
- if (c->a->expected_res_size >= c->len)
- {
- c->sw1sw2[0] = 0x90;
- c->sw1sw2[1] = 0x00;
- }
- else
- {
- c->sw1sw2[0] = 0x61;
- if (c->len - chunk_len >= 256)
- c->sw1sw2[1] = 0;
- else
- c->sw1sw2[1] = (uint8_t)(c->len - chunk_len);
- }
-}
-
-static void get_sw1sw2(struct ep_in *epi, size_t len)
-{
- struct ccid *c = (struct ccid *)epi->priv;
-
- (void)len;
- epi->buf = c->sw1sw2;
- epi->cnt = 0;
- epi->buf_len = 2;
- epi->next_buf = no_buf;
-}
-
-static void ccid_send_data_block_internal(struct ccid *c, uint8_t status, uint8_t error)
-{
- int tx_size = USB_LL_BUF_SIZE;
- uint8_t p[CCID_MSG_HEADER_SIZE];
- size_t len;
-
- if (status == 0)
- len = c->a->res_apdu_data_len + 2;
- else
- len = 0;
-
- p[0] = CCID_DATA_BLOCK_RET;
- p[1] = len & 0xFF;
- p[2] = (len >> 8)& 0xFF;
- p[3] = (len >> 16)& 0xFF;
- p[4] = (len >> 24)& 0xFF;
- p[5] = 0x00; /* Slot */
- p[CCID_MSG_SEQ_OFFSET] = c->a->seq;
- p[CCID_MSG_STATUS_OFFSET] = status;
- p[CCID_MSG_ERROR_OFFSET] = error;
- p[CCID_MSG_CHAIN_OFFSET] = 0;
-
- memcpy(endp1_tx_buf, p, CCID_MSG_HEADER_SIZE);
-
- if (len == 0)
- {
- c->epi->buf = NULL;
- c->epi->tx_done = 1;
- usb_tx_enable(endp1_tx_buf, CCID_MSG_HEADER_SIZE);
- c->tx_busy = 1;
- return;
- }
-
- if (CCID_MSG_HEADER_SIZE + len <= USB_LL_BUF_SIZE)
- {
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE, c->a->res_apdu_data, c->a->res_apdu_data_len);
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE+c->a->res_apdu_data_len, c->sw1sw2, 2);
-
- c->epi->buf = NULL;
- if (CCID_MSG_HEADER_SIZE + len < USB_LL_BUF_SIZE)
- c->epi->tx_done = 1;
- tx_size = CCID_MSG_HEADER_SIZE + len;
- }
- else if (CCID_MSG_HEADER_SIZE + len - 1 == USB_LL_BUF_SIZE)
- {
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE, c->a->res_apdu_data, c->a->res_apdu_data_len);
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE+c->a->res_apdu_data_len, c->sw1sw2, 1);
-
- c->epi->buf = &c->sw1sw2[1];
- c->epi->cnt = 1;
- c->epi->buf_len = 1;
- c->epi->next_buf = no_buf;
- }
- else if (CCID_MSG_HEADER_SIZE + len - 2 == USB_LL_BUF_SIZE)
- {
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE, c->a->res_apdu_data, c->a->res_apdu_data_len);
-
- c->epi->buf = &c->sw1sw2[0];
- c->epi->cnt = 0;
- c->epi->buf_len = 2;
- c->epi->next_buf = no_buf;
- }
- else
- {
- memcpy(endp1_tx_buf+CCID_MSG_HEADER_SIZE, c->a->res_apdu_data, USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
-
- c->epi->buf = c->a->res_apdu_data + USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE;
- c->epi->cnt = USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE;
- c->epi->buf_len = c->a->res_apdu_data_len - (USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
- c->epi->next_buf = get_sw1sw2;
- }
- usb_tx_enable(endp1_tx_buf, tx_size);
- c->tx_busy = 1;
-}
-
-static void ccid_send_data_block(struct ccid *c)
-{
- ccid_send_data_block_internal (c, 0, 0);
-}
-
-static void ccid_send_data_block_time_extension(struct ccid *c)
-{
- ccid_send_data_block_internal (c, CCID_CMD_STATUS_TIMEEXT, c->ccid_state == CCID_STATE_EXECUTE? 1: 0xff);
-}
-
-static void ccid_send_data_block_0x9000(struct ccid *c)
-{
- uint8_t p[CCID_MSG_HEADER_SIZE+2];
- size_t len = 2;
-
- p[0] = CCID_DATA_BLOCK_RET;
- p[1] = len & 0xFF;
- p[2] = (len >> 8)& 0xFF;
- p[3] = (len >> 16)& 0xFF;
- p[4] = (len >> 24)& 0xFF;
- p[5] = 0x00; /* Slot */
- p[CCID_MSG_SEQ_OFFSET] = c->a->seq;
- p[CCID_MSG_STATUS_OFFSET] = 0;
- p[CCID_MSG_ERROR_OFFSET] = 0;
- p[CCID_MSG_CHAIN_OFFSET] = 0;
- p[CCID_MSG_CHAIN_OFFSET+1] = 0x90;
- p[CCID_MSG_CHAIN_OFFSET+2] = 0x00;
-
- memcpy (endp1_tx_buf, p, CCID_MSG_HEADER_SIZE + len);
-
- c->epi->buf = NULL;
- c->epi->tx_done = 1;
- usb_tx_enable (endp1_tx_buf, CCID_MSG_HEADER_SIZE + len);
- c->tx_busy = 1;
-}
-
-static void ccid_send_data_block_gr(struct ccid *c, size_t chunk_len)
-{
- int tx_size = USB_LL_BUF_SIZE;
- uint8_t p[CCID_MSG_HEADER_SIZE];
- size_t len = chunk_len + 2;
-
- p[0] = CCID_DATA_BLOCK_RET;
- p[1] = len & 0xFF;
- p[2] = (len >> 8)& 0xFF;
- p[3] = (len >> 16)& 0xFF;
- p[4] = (len >> 24)& 0xFF;
- p[5] = 0x00; /* Slot */
- p[CCID_MSG_SEQ_OFFSET] = c->a->seq;
- p[CCID_MSG_STATUS_OFFSET] = 0;
- p[CCID_MSG_ERROR_OFFSET] = 0;
- p[CCID_MSG_CHAIN_OFFSET] = 0;
-
- memcpy (endp1_tx_buf, p, CCID_MSG_HEADER_SIZE);
-
- set_sw1sw2 (c, chunk_len);
-
- if (chunk_len <= USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE)
- {
- int size_for_sw;
-
- if (chunk_len <= USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE - 2)
- size_for_sw = 2;
- else if (chunk_len == USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE - 1)
- size_for_sw = 1;
- else
- size_for_sw = 0;
-
- memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE, c->p, chunk_len);
-
- if (size_for_sw)
- memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE+chunk_len, c->sw1sw2, size_for_sw);
-
- tx_size = CCID_MSG_HEADER_SIZE + chunk_len + size_for_sw;
- if (size_for_sw == 2)
- {
- c->epi->buf = NULL;
- if (tx_size < USB_LL_BUF_SIZE)
- c->epi->tx_done = 1;
- /* Don't set epi->tx_done = 1, when it requires ZLP */
- }
- else
- {
- c->epi->buf = c->sw1sw2 + size_for_sw;
- c->epi->cnt = size_for_sw;
- c->epi->buf_len = 2 - size_for_sw;
- c->epi->next_buf = no_buf;
- }
- }
- else
- {
- memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE, c->p, USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
-
- c->epi->buf = c->p + USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE;
- c->epi->cnt = 0;
- c->epi->buf_len = chunk_len - (USB_LL_BUF_SIZE - CCID_MSG_HEADER_SIZE);
- c->epi->next_buf = get_sw1sw2;
- }
-
- c->p += chunk_len;
- c->len -= chunk_len;
- usb_tx_enable (endp1_tx_buf, tx_size);
- c->tx_busy = 1;
-}
-
-static void ccid_send_params(struct ccid *c)
-{
- uint8_t p[CCID_MSG_HEADER_SIZE];
- const uint8_t params[] = {
- 0x11, /* bmFindexDindex */
- 0x11, /* bmTCCKST1 */
- 0xFE, /* bGuardTimeT1 */
- 0x55, /* bmWaitingIntegersT1 */
- 0x03, /* bClockStop */
- 0xFE, /* bIFSC */
- 0 /* bNadValue */
- };
-
- p[0] = CCID_PARAMS_RET;
- p[1] = 0x07; /* Length = 0x00000007 */
- p[2] = 0;
- p[3] = 0;
- p[4] = 0;
- p[5] = 0x00; /* Slot */
- p[CCID_MSG_SEQ_OFFSET] = c->ccid_header.seq;
- p[CCID_MSG_STATUS_OFFSET] = 0;
- p[CCID_MSG_ERROR_OFFSET] = 0;
- p[CCID_MSG_CHAIN_OFFSET] = 0x01; /* ProtocolNum: T=1 */
-
- memcpy (endp1_tx_buf, p, CCID_MSG_HEADER_SIZE);
- memcpy (endp1_tx_buf+CCID_MSG_HEADER_SIZE, params, sizeof params);
-
- /* This is a single packet Bulk-IN transaction */
- c->epi->buf = NULL;
- c->epi->tx_done = 1;
- usb_tx_enable (endp1_tx_buf, CCID_MSG_HEADER_SIZE + sizeof params);
- c->tx_busy = 1;
-}
-
-static void ccid_error(struct ccid *c, int offset)
-{
- uint8_t ccid_reply[CCID_MSG_HEADER_SIZE];
-
- ccid_reply[0] = CCID_SLOT_STATUS_RET; /* Any value should be OK */
- ccid_reply[1] = 0x00;
- ccid_reply[2] = 0x00;
- ccid_reply[3] = 0x00;
- ccid_reply[4] = 0x00;
- ccid_reply[5] = 0x00; /* Slot */
- ccid_reply[CCID_MSG_SEQ_OFFSET] = c->ccid_header.seq;
- if (c->ccid_state == CCID_STATE_NOCARD)
- ccid_reply[CCID_MSG_STATUS_OFFSET] = 2; /* 2: No ICC present */
- else if (c->ccid_state == CCID_STATE_START)
- /* 1: ICC present but not activated */
- ccid_reply[CCID_MSG_STATUS_OFFSET] = 1;
- else
- ccid_reply[CCID_MSG_STATUS_OFFSET] = 0; /* An ICC is present and active */
- ccid_reply[CCID_MSG_STATUS_OFFSET] |= CCID_CMD_STATUS_ERROR; /* Failed */
- ccid_reply[CCID_MSG_ERROR_OFFSET] = offset;
- ccid_reply[CCID_MSG_CHAIN_OFFSET] = 0x00;
-
- /* This is a single packet Bulk-IN transaction */
- c->epi->buf = NULL;
- c->epi->tx_done = 1;
- memcpy (endp1_tx_buf, ccid_reply, CCID_MSG_HEADER_SIZE);
- usb_tx_enable (endp1_tx_buf, CCID_MSG_HEADER_SIZE);
- c->tx_busy = 1;
-}
-
-#define INS_GET_RESPONSE 0xc0
-
-static enum ccid_state ccid_handle_data(struct ccid *c)
-{
- enum ccid_state next_state = c->ccid_state;
-
- TU_LOG3("---- CCID STATE %d,msg_type %x,start %d\r\n",c->ccid_state,c->ccid_header.msg_type,CCID_STATE_START);
- if (c->err != 0)
- {
- ccid_reset(c);
- ccid_error(c, CCID_OFFSET_DATA_LEN);
- return next_state;
- }
- switch (c->ccid_state)
- {
- case CCID_STATE_NOCARD:
- if (c->ccid_header.msg_type == CCID_SLOT_STATUS)
- ccid_send_status(c);
- else
- {
- DEBUG_INFO ("ERR00\r\n");
- ccid_error(c, CCID_OFFSET_CMD_NOT_SUPPORTED);
- }
- break;
- case CCID_STATE_START:
- if (c->ccid_header.msg_type == CCID_POWER_ON)
- {
- ccid_reset(c);
- next_state = ccid_power_on(c);
- }
- else if (c->ccid_header.msg_type == CCID_POWER_OFF)
- {
- ccid_reset(c);
- next_state = ccid_power_off(c);
- }
- else if (c->ccid_header.msg_type == CCID_SLOT_STATUS)
- ccid_send_status (c);
- else
- {
- DEBUG_INFO("ERR01\r\n");
- ccid_error(c, CCID_OFFSET_CMD_NOT_SUPPORTED);
- }
- break;
- case CCID_STATE_WAIT:
- if (c->ccid_header.msg_type == CCID_POWER_ON)
- {
- /* Not in the spec., but pcscd/libccid */
- ccid_reset(c);
- next_state = ccid_power_on(c);
- }
- else if (c->ccid_header.msg_type == CCID_POWER_OFF)
- {
- ccid_reset(c);
- next_state = ccid_power_off(c);
- }
- else if (c->ccid_header.msg_type == CCID_SLOT_STATUS)
- ccid_send_status(c);
- else if (c->ccid_header.msg_type == CCID_XFR_BLOCK)
- {
- if (c->ccid_header.param == 0)
- {
- if ((c->a->cmd_apdu_head[0] & 0x10) == 0)
- {
- if (c->state == APDU_STATE_COMMAND_CHAINING)
- { /* command chaining finished */
- c->p += c->a->cmd_apdu_head[4];
- c->a->cmd_apdu_head[4] = 0;
- DEBUG_INFO ("CMD chaning finished.\r\n");
- }
-
- if (c->a->cmd_apdu_head[1] == INS_GET_RESPONSE && c->state == APDU_STATE_RESULT_GET_RESPONSE)
- {
- size_t len = c->a->expected_res_size;
-
- if (c->len <= c->a->expected_res_size)
- len = c->len;
-
- ccid_send_data_block_gr (c, len);
- if (c->len == 0)
- c->state = APDU_STATE_RESULT;
- c->ccid_state = CCID_STATE_WAIT;
- DEBUG_INFO ("GET Response.\r\n");
- }
- else
- { /* Give this message to GPG thread */
- c->state = APDU_STATE_COMMAND_RECEIVED;
-
- c->a->sw = 0x9000;
- c->a->res_apdu_data_len = 0;
- c->a->res_apdu_data = &ccid_buffer[5];
-
- uint32_t flag = EV_CMD_AVAILABLE;
- queue_try_add(&c->card_comm, &flag);
-
- next_state = CCID_STATE_EXECUTE;
- }
- }
- else
- {
- if (c->state == APDU_STATE_WAIT_COMMAND)
- { /* command chaining is started */
- c->a->cmd_apdu_head[0] &= ~0x10;
- memcpy (c->chained_cls_ins_p1_p2, c->a->cmd_apdu_head, 4);
- c->state = APDU_STATE_COMMAND_CHAINING;
- }
-
- c->p += c->a->cmd_apdu_head[4];
- c->len -= c->a->cmd_apdu_head[4];
- ccid_send_data_block_0x9000 (c);
- DEBUG_INFO ("CMD chaning...\r\n");
- }
- }
- else
- { /* ICC block chaining is not supported. */
- DEBUG_INFO ("ERR02\r\n");
- ccid_error (c, CCID_OFFSET_PARAM);
- }
- }
- else if (c->ccid_header.msg_type == CCID_SET_PARAMS || c->ccid_header.msg_type == CCID_GET_PARAMS || c->ccid_header.msg_type == CCID_RESET_PARAMS)
- ccid_send_params(c);
- else
- {
- DEBUG_INFO ("ERR03\r\n");
- DEBUG_BYTE (c->ccid_header.msg_type);
- ccid_error (c, CCID_OFFSET_CMD_NOT_SUPPORTED);
- }
- break;
- case CCID_STATE_EXECUTE:
- case CCID_STATE_ACK_REQUIRED_0:
- case CCID_STATE_ACK_REQUIRED_1:
- if (c->ccid_header.msg_type == CCID_POWER_OFF)
- next_state = ccid_power_off (c);
- else if (c->ccid_header.msg_type == CCID_SLOT_STATUS)
- ccid_send_status (c);
- else
- {
- DEBUG_INFO ("ERR04\r\n");
- DEBUG_BYTE (c->ccid_header.msg_type);
- ccid_error (c, CCID_OFFSET_CMD_NOT_SUPPORTED);
- }
- break;
- default:
- next_state = CCID_STATE_START;
- DEBUG_INFO ("ERR10\r\n");
- break;
- }
-
- return next_state;
-}
-
-static enum ccid_state ccid_handle_timeout(struct ccid *c)
-{
- enum ccid_state next_state = c->ccid_state;
- switch (c->ccid_state)
- {
- case CCID_STATE_EXECUTE:
- case CCID_STATE_ACK_REQUIRED_0:
- case CCID_STATE_ACK_REQUIRED_1:
- ccid_send_data_block_time_extension(c);
- break;
- default:
- break;
- }
-
- return next_state;
-}
-
-
-static void notify_icc (struct ep_out *epo)
-{
- struct ccid *c = (struct ccid *)epo->priv;
- c->err = epo->err;
- uint32_t val = EV_RX_DATA_READY;
- queue_try_add(&c->ccid_comm, &val);
-}
-
-static int end_ccid_rx (struct ep_out *epo, size_t orig_len)
-{
- (void)orig_len;
- if (epo->cnt < sizeof (struct ccid_header))
- /* short packet, just ignore */
- return 1;
-
- /* icc message with no abdata */
- return 0;
-}
-
-static int end_abdata (struct ep_out *epo, size_t orig_len)
-{
- struct ccid *c = (struct ccid *)epo->priv;
- size_t len = epo->cnt;
-
- if (orig_len == USB_LL_BUF_SIZE && len < c->ccid_header.data_len)
- /* more packet comes */
- return 1;
-
- if (len != c->ccid_header.data_len)
- epo->err = 1;
-
- return 0;
-}
-
-static int end_cmd_apdu_head (struct ep_out *epo, size_t orig_len)
-{
- struct ccid *c = (struct ccid *)epo->priv;
-
- (void)orig_len;
-
- if (epo->cnt < 4 || epo->cnt != c->ccid_header.data_len)
- {
- epo->err = 1;
- return 0;
- }
-
- if ((c->state == APDU_STATE_COMMAND_CHAINING)
- && (c->chained_cls_ins_p1_p2[0] != (c->a->cmd_apdu_head[0] & ~0x10)
- || c->chained_cls_ins_p1_p2[1] != c->a->cmd_apdu_head[1]
- || c->chained_cls_ins_p1_p2[2] != c->a->cmd_apdu_head[2]
- || c->chained_cls_ins_p1_p2[3] != c->a->cmd_apdu_head[3]))
- /*
- * Handling exceptional request.
- *
- * Host stops sending command APDU using command chaining,
- * and start another command APDU.
- *
- * Discard old one, and start handling new one.
- */
- {
- c->state = APDU_STATE_WAIT_COMMAND;
- c->p = c->a->cmd_apdu_data;
- c->len = MAX_CMD_APDU_DATA_SIZE;
- }
-
- if (epo->cnt == 4)
- /* No Lc and Le */
- c->a->expected_res_size = 0;
- else if (epo->cnt == 5)
- {
- /* No Lc but Le */
- c->a->expected_res_size = c->a->cmd_apdu_head[4];
- if (c->a->expected_res_size == 0)
- c->a->expected_res_size = 256;
- c->a->cmd_apdu_head[4] = 0;
- }
- else if (epo->cnt == 9) { //extended
- c->a->expected_res_size = (c->a->cmd_apdu_head[7] << 8) | c->a->cmd_apdu_head[8];
- if (c->a->expected_res_size == 0)
- c->a->expected_res_size = 65536;
- }
-
- c->a->cmd_apdu_data_len = 0;
- return 0;
-}
-
-static int end_nomore_data (struct ep_out *epo, size_t orig_len)
-{
- (void)epo;
- if (orig_len == USB_LL_BUF_SIZE)
- return 1;
- else
- return 0;
-}
-
-static int end_cmd_apdu_data (struct ep_out *epo, size_t orig_len)
-{
- struct ccid *c = (struct ccid *)epo->priv;
- size_t len = epo->cnt;
-
- if (orig_len == USB_LL_BUF_SIZE && CMD_APDU_HEAD_SIZE + len < c->ccid_header.data_len)
- /* more packet comes */
- return 1;
-
- if (CMD_APDU_HEAD_SIZE + len != c->ccid_header.data_len)
- goto error;
- //len is the length after lc (whole APDU = len+5)
- if (c->a->cmd_apdu_head[4] == 0 && len >= 2) { //extended
- if (len == 2) {
- c->a->expected_res_size = (c->a->cmd_apdu_head[5] << 8) | c->a->cmd_apdu_head[6];
- if (c->a->expected_res_size == 0)
- c->a->expected_res_size = 0xffff+1;
- }
- else {
- c->a->cmd_apdu_data_len = (c->a->cmd_apdu_data[0] << 8) | c->a->cmd_apdu_data[1];
- len -= 2;
- if (len < c->a->cmd_apdu_data_len)
- goto error;
- c->a->cmd_apdu_data += 2;
- if (len == c->a->cmd_apdu_data_len) //no LE
- c->a->expected_res_size = 0;
- else {
- if (len - c->a->cmd_apdu_data_len < 2)
- goto error;
- c->a->expected_res_size = (c->a->cmd_apdu_data[c->a->cmd_apdu_data_len] << 8) | c->a->cmd_apdu_data[c->a->cmd_apdu_data_len+1];
- if (c->a->expected_res_size == 0)
- c->a->expected_res_size = 0xffff+1;
- }
- }
- }
- else {
-
- if (len == c->a->cmd_apdu_head[4])
- /* No Le field*/
- c->a->expected_res_size = 0;
- else if (len == (size_t)c->a->cmd_apdu_head[4] + 1)
- {
- /* it has Le field*/
- c->a->expected_res_size = epo->buf[-1];
- if (c->a->expected_res_size == 0)
- c->a->expected_res_size = 256;
- len--;
- }
- else
- {
- error:
- DEBUG_INFO("APDU header size error");
- epo->err = 1;
- return 0;
- }
-
- c->a->cmd_apdu_data_len += len;
- }
- return 0;
-}
-
-static void nomore_data (struct ep_out *epo, size_t len)
-{
- (void)len;
- epo->err = 1;
- epo->end_rx = end_nomore_data;
- epo->buf = NULL;
- epo->buf_len = 0;
- epo->cnt = 0;
- epo->next_buf = nomore_data;
- epo->ready = 0;
-}
-
-static void ccid_cmd_apdu_data (struct ep_out *epo, size_t len)
-{
- struct ccid *c = (struct ccid *)epo->priv;
-
- (void)len;
- if (c->state == APDU_STATE_RESULT_GET_RESPONSE && c->a->cmd_apdu_head[1] != INS_GET_RESPONSE)
- {
- /*
- * Handling exceptional request.
- *
- * Host didn't finish receiving the whole response APDU by GET RESPONSE,
- * but initiates another command.
- */
-
- c->state = APDU_STATE_WAIT_COMMAND;
- c->p = c->a->cmd_apdu_data;
- c->len = MAX_CMD_APDU_DATA_SIZE;
- }
- else if (c->state == APDU_STATE_COMMAND_CHAINING)
- {
- if (c->chained_cls_ins_p1_p2[0] != (c->a->cmd_apdu_head[0] & ~0x10)
- || c->chained_cls_ins_p1_p2[1] != c->a->cmd_apdu_head[1]
- || c->chained_cls_ins_p1_p2[2] != c->a->cmd_apdu_head[2]
- || c->chained_cls_ins_p1_p2[3] != c->a->cmd_apdu_head[3])
- /*
- * Handling exceptional request.
- *
- * Host stops sending command APDU using command chaining,
- * and start another command APDU.
- *
- * Discard old one, and start handling new one.
- */
- {
- c->state = APDU_STATE_WAIT_COMMAND;
- c->p = c->a->cmd_apdu_data;
- c->len = MAX_CMD_APDU_DATA_SIZE;
- c->a->cmd_apdu_data_len = 0;
- }
- }
-
- epo->end_rx = end_cmd_apdu_data;
- epo->buf = c->p;
- epo->buf_len = c->len;
- epo->cnt = 0;
- epo->next_buf = nomore_data;
-}
-
-static void ccid_abdata (struct ep_out *epo, size_t len)
-{
- struct ccid *c = (struct ccid *)epo->priv;
-
- (void)len;
- c->a->seq = c->ccid_header.seq;
- if (c->ccid_header.msg_type == CCID_XFR_BLOCK)
- {
- c->a->seq = c->ccid_header.seq;
- epo->end_rx = end_cmd_apdu_head;
- epo->buf = c->a->cmd_apdu_head;
- epo->buf_len = 5;
- epo->cnt = 0;
- epo->next_buf = ccid_cmd_apdu_data;
- }
- else
- {
- epo->end_rx = end_abdata;
- epo->buf = c->p;
- epo->buf_len = c->len;
- epo->cnt = 0;
- epo->next_buf = nomore_data;
- }
-}
-
-static void ccid_prepare_receive (struct ccid *c)
-{
- c->epo->err = 0;
- c->epo->buf = (uint8_t *)&c->ccid_header;
- c->epo->buf_len = sizeof (struct ccid_header);
- c->epo->cnt = 0;
- c->epo->next_buf = ccid_abdata;
- c->epo->end_rx = end_ccid_rx;
- c->epo->ready = 1;
-}
-
-static void ccid_rx_ready (uint16_t len)
-{
- /*
- * If we support multiple CCID interfaces, we select endpoint object
- * by EP_NUM. Because it has only single CCID interface now, it's
- * hard-coded, here.
- */
- struct ep_out *epo = &endpoint_out;
- int offset = 0;
- int cont;
- size_t orig_len = len;
- while (epo->err == 0)
- {
- if (len == 0)
- break;
- else if (len <= epo->buf_len)
- {
- memcpy (epo->buf, endp1_rx_buf + offset, len);
- epo->buf += len;
- epo->cnt += len;
- epo->buf_len -= len;
- break;
- }
- else /* len > buf_len */
- {
- memcpy (epo->buf, endp1_rx_buf + offset, epo->buf_len);
- len -= epo->buf_len;
- offset += epo->buf_len;
- epo->next_buf (epo, len); /* Update epo->buf, cnt, buf_len */
- }
- }
-
- /*
- * ORIG_LEN to distingush ZLP and the end of transaction
- * (ORIG_LEN != USB_LL_BUF_SIZE)
- */
- cont = epo->end_rx (epo, orig_len);
-
- if (cont == 0)
- notify_icc (epo);
- else
- epo->ready = 1;
-}
-
-static void notify_tx (struct ep_in *epi)
-{
- struct ccid *c = (struct ccid *)epi->priv;
-
- /* The sequence of Bulk-IN transactions finished */
- uint32_t flag = EV_TX_FINISHED;
- queue_try_add(&c->ccid_comm, &flag);
- c->tx_busy = 0;
-}
-
-static void ccid_tx_done ()
-{
- /*
- * If we support multiple CCID interfaces, we select endpoint object
- * by EP_NUM. Because it has only single CCID interface now, it's
- * hard-coded, here.
- */
- struct ep_in *epi = &endpoint_in;
- if (epi->buf == NULL)
- {
- if (epi->tx_done)
- notify_tx (epi);
- else
- {
- epi->tx_done = 1;
- usb_tx_enable (endp1_tx_buf, 0);
- }
- }
- else
- {
- int tx_size = 0;
- size_t remain = USB_LL_BUF_SIZE;
- int offset = 0;
-
- while (epi->buf)
- {
- if (epi->buf_len < remain)
- {
- memcpy (endp1_tx_buf+offset, epi->buf, epi->buf_len);
- offset += epi->buf_len;
- remain -= epi->buf_len;
- tx_size += epi->buf_len;
- epi->next_buf (epi, remain); /* Update epi->buf, cnt, buf_len */
- }
- else
- {
- memcpy (endp1_tx_buf+offset, epi->buf, remain);
- epi->buf += remain;
- epi->cnt += remain;
- epi->buf_len -= remain;
- tx_size += remain;
- break;
- }
- }
- if (tx_size < USB_LL_BUF_SIZE)
- epi->tx_done = 1;
-
- usb_tx_enable (endp1_tx_buf, tx_size);
- }
-}
-
-static int usb_event_handle(struct ccid *c)
-{
- TU_LOG3("!!! tx %d, vendor %d, cfg %d, rx %d\r\n",c->tx_busy,tud_vendor_n_write_available(0),CFG_TUD_VENDOR_TX_BUFSIZE,tud_vendor_available());
- if (c->tx_busy == 1 && tud_vendor_n_write_available(0) == CFG_TUD_VENDOR_TX_BUFSIZE)
- {
- ccid_tx_done ();
- }
- if (tud_vendor_available() && c->epo->ready)
- {
- uint32_t count = tud_vendor_read(endp1_rx_buf, sizeof(endp1_rx_buf));
- if (endp1_rx_buf[0] != 0x65)
- DEBUG_PAYLOAD(endp1_rx_buf, count);
- //DEBUG_PAYLOAD(endp1_rx_buf, count);
- ccid_rx_ready(count);
- }
- return 0;
-}
-
-uint32_t timeout = USB_CCID_TIMEOUT;
-static uint32_t prev_millis = 0;
-
-void prepare_ccid()
-{
- struct ep_in *epi = &endpoint_in;
- struct ep_out *epo = &endpoint_out;
- struct ccid *c = &ccid;
- struct apdu *a = &apdu;
-
- epi_init (epi, 1, c);
- epo_init (epo, 2, c);
-
- apdu_init(a);
- ccid_init (c, epi, epo, a);
-}
-
-int process_apdu() {
- led_set_blink(BLINK_PROCESSING);
- if (!current_app) {
- if (INS(apdu) == 0xA4 && P1(apdu) == 0x04 && (P2(apdu) == 0x00 || P2(apdu) == 0x4)) { //select by AID
- for (int a = 0; a < num_apps; a++) {
- if ((current_app = apps[a].select_aid(&apps[a]))) {
- return set_res_sw(0x90,0x00);
- }
- }
- }
- return set_res_sw(0x6a, 0x82);
- }
- if (current_app->process_apdu)
- return current_app->process_apdu();
- return set_res_sw (0x6D, 0x00);
-}
-
-uint16_t set_res_sw (uint8_t sw1, uint8_t sw2)
-{
- apdu.sw = (sw1 << 8) | sw2;
- return make_uint16_t(sw1, sw2);
-}
-
-static void card_init (void)
-{
- //gpg_data_scan (flash_do_start, flash_do_end);
- low_flash_init_core1();
-}
-
-void card_thread()
-{
- ccid_comm = (queue_t *)multicore_fifo_pop_blocking();
- card_comm = (queue_t *)multicore_fifo_pop_blocking();
-
- card_init ();
-
- while (1)
- {
- uint32_t m;
- queue_remove_blocking(card_comm, &m);
-
- if (m == EV_VERIFY_CMD_AVAILABLE || m == EV_MODIFY_CMD_AVAILABLE)
- {
- set_res_sw (0x6f, 0x00);
- goto done;
- }
- else if (m == EV_EXIT) {
- if (current_app && current_app->unload)
- current_app->unload();
- break;
- }
-
- process_apdu();
-
- done:;
- uint32_t flag = EV_EXEC_FINISHED;
- queue_add_blocking(ccid_comm, &flag);
- }
-
- if (current_app && current_app->unload)
- current_app->unload();
-}
-
-
-void ccid_task(void)
-{
- struct ccid *c = &ccid;
- if (tud_vendor_mounted())
- {
- // connected and there are data available
- if ((c->epo->ready && tud_vendor_available()) || (tud_vendor_n_write_available(0) == CFG_TUD_VENDOR_TX_BUFSIZE && c->tx_busy == 1))
- {
- if (usb_event_handle (c) != 0)
- {
- if (c->application)
- {
- uint32_t flag = EV_EXIT;
- queue_try_add(&c->ccid_comm, &flag);
- c->application = 0;
- }
- prepare_ccid();
- return;
- }
- }
- if (timeout == 0)
- {
- timeout = USB_CCID_TIMEOUT;
- c->timeout_cnt++;
- }
- uint32_t m = 0x0;
- bool has_m = queue_try_remove(&c->ccid_comm, &m);
- if (m != 0)
- TU_LOG3("\r\n ------ M = %d\r\n",m);
- if (has_m)
- {
- if (m == EV_CARD_CHANGE)
- {
- if (c->ccid_state == CCID_STATE_NOCARD)
- /* Inserted! */
- c->ccid_state = CCID_STATE_START;
- else
- { /* Removed! */
- if (c->application)
- {
- uint32_t flag = EV_EXIT;
- queue_try_add(&c->card_comm, &flag);
- c->application = 0;
- }
- c->ccid_state = CCID_STATE_NOCARD;
- }
- //ccid_notify_slot_change (c);
- }
- else if (m == EV_RX_DATA_READY)
- {
- c->ccid_state = ccid_handle_data(c);
- timeout = 0;
- c->timeout_cnt = 0;
- }
- else if (m == EV_EXEC_FINISHED)
- {
- if (c->ccid_state == CCID_STATE_EXECUTE)
- {
- exec_done:
- if (c->a->sw == GPG_THREAD_TERMINATED)
- {
- c->sw1sw2[0] = 0x90;
- c->sw1sw2[1] = 0x00;
- c->state = APDU_STATE_RESULT;
- ccid_send_data_block(c);
- c->ccid_state = CCID_STATE_EXITED;
- c->application = 0;
- return;
- }
-
- c->a->cmd_apdu_data_len = 0;
- c->sw1sw2[0] = c->a->sw >> 8;
- c->sw1sw2[1] = c->a->sw & 0xff;
- if (c->a->res_apdu_data_len <= c->a->expected_res_size)
- {
- c->state = APDU_STATE_RESULT;
- ccid_send_data_block(c);
- c->ccid_state = CCID_STATE_WAIT;
- }
- else
- {
- c->state = APDU_STATE_RESULT_GET_RESPONSE;
- c->p = c->a->res_apdu_data;
- c->len = c->a->res_apdu_data_len;
- ccid_send_data_block_gr(c, c->a->expected_res_size);
- c->ccid_state = CCID_STATE_WAIT;
- }
- }
- else
- {
- DEBUG_INFO ("ERR05\r\n");
- }
- led_set_blink(BLINK_MOUNTED);
- }
- else if (m == EV_TX_FINISHED)
- {
- if (c->state == APDU_STATE_RESULT)
- ccid_reset(c);
- else
- c->tx_busy = 0;
- if (c->state == APDU_STATE_WAIT_COMMAND || c->state == APDU_STATE_COMMAND_CHAINING || c->state == APDU_STATE_RESULT_GET_RESPONSE)
- ccid_prepare_receive(c);
- }
- else if (m == EV_PRESS_BUTTON) {
- wait_button();
- uint32_t flag = EV_BUTTON_PRESSED;
- queue_try_add(&c->card_comm, &flag);
- }
- }
- else /* Timeout */
- {
- timeout -= MIN(board_millis()-prev_millis,timeout);
- if (timeout == 0)
- {
- if (c->timeout_cnt == 7 && c->ccid_state == CCID_STATE_ACK_REQUIRED_1)
- {
- c->a->sw = GPG_ACK_TIMEOUT;
- c->a->res_apdu_data_len = 0;
- c->a->sw = GPG_ACK_TIMEOUT;
- c->a->res_apdu_data_len = 0;
-
- goto exec_done;
- }
- else
- c->ccid_state = ccid_handle_timeout(c);
- }
- }
- }
-}
-
-void tud_mount_cb()
-{
- ccid_prepare_receive (&ccid);
-}
-
-void led_blinking_task()
-{
-#ifdef PICO_DEFAULT_LED_PIN
- static uint32_t start_ms = 0;
- static uint8_t led_state = false;
- static uint8_t led_color = PICO_DEFAULT_LED_PIN;
-#ifdef PICO_DEFAULT_LED_PIN_INVERTED
- uint32_t interval = !led_state ? blink_interval_ms & 0xffff : blink_interval_ms >> 16;
-#else
- uint32_t interval = led_state ? blink_interval_ms & 0xffff : blink_interval_ms >> 16;
-#endif
-
-
- // Blink every interval ms
- if (board_millis() - start_ms < interval)
- return; // not enough time
- start_ms += interval;
-
- gpio_put(led_color, led_state);
- led_state ^= 1; // toggle
-#endif
-}
-
-void led_off_all()
-{
-#ifdef PIMORONI_TINY2040
- gpio_put(TINY2040_LED_R_PIN, 1);
- gpio_put(TINY2040_LED_G_PIN, 1);
- gpio_put(TINY2040_LED_B_PIN, 1);
-#else
-#ifdef PICO_DEFAULT_LED_PIN
- gpio_put(PICO_DEFAULT_LED_PIN, 0);
-#endif
-#endif
-}
-
-void init_rtc() {
-
- rtc_init();
- datetime_t dt = {
- .year = 2020,
- .month = 1,
- .day = 1,
- .dotw = 3, // 0 is Sunday, so 5 is Friday
- .hour = 00,
- .min = 00,
- .sec = 00
- };
- rtc_set_datetime(&dt);
-}
-
-extern void neug_task();
-
-pico_unique_board_id_t unique_id;
-
-void execute_tasks() {
- prev_millis = board_millis();
- ccid_task();
- tud_task(); // tinyusb device task
- led_blinking_task();
-}
-
-int main(void)
-{
- struct apdu *a = &apdu;
- struct ccid *c = &ccid;
-
- board_init();
-
-#ifdef PIMORONI_TINY2040
- gpio_init(TINY2040_LED_R_PIN);
- gpio_set_dir(TINY2040_LED_R_PIN, GPIO_OUT);
- gpio_init(TINY2040_LED_G_PIN);
- gpio_set_dir(TINY2040_LED_G_PIN, GPIO_OUT);
- gpio_init(TINY2040_LED_B_PIN);
- gpio_set_dir(TINY2040_LED_B_PIN, GPIO_OUT);
-#else
-#ifdef PICO_DEFAULT_LED_PIN
- gpio_init(PICO_DEFAULT_LED_PIN);
- gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT);
-#endif
-#endif
-
-
- led_off_all();
-
- tusb_init();
-
- prepare_ccid();
-
- random_init();
-
- low_flash_init();
-
- init_rtc();
-
- while (1)
- {
- execute_tasks();
- neug_task();
- do_flash();
- }
-
- return 0;
-}
\ No newline at end of file
diff --git a/src/hsm/hsm2040.h b/src/hsm/hsm2040.h
deleted file mode 100644
index 0b48620..0000000
--- a/src/hsm/hsm2040.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef _HSM2040_H_
-#define _HSM2040_H_
-
-#include "ccid.h"
-#include "tusb.h"
-#include "file.h"
-#include "pico/unique_id.h"
-#include "pico/util/queue.h"
-
-#define USB_REQ_CCID 0xA1
-
-typedef struct app {
- const uint8_t *aid;
- int (*process_apdu)();
- struct app* (*select_aid)();
- int (*unload)();
-} app_t;
-
-extern int register_app(app_t * (*)());
-
-extern const uint8_t historical_bytes[];
-
-#define DEBUG_PAYLOAD(p,s) { \
- printf("Payload %s (%d bytes):\r\n", #p,s);\
- for (int i = 0; i < s; i += 16) {\
- printf("%07Xh : ",i+p);\
- for (int j = 0; j < 16; j++) {\
- if (j < s-i) printf("%02X ",(p)[i+j]);\
- else printf(" ");\
- if (j == 7) printf(" ");\
- } printf(": "); \
- for (int j = 0; j < MIN(16,s-i); j++) {\
- printf("%c",(p)[i+j] == 0x0a || (p)[i+j] == 0x0d ? '\\' : (p)[i+j]);\
- if (j == 7) printf(" ");\
- }\
- printf("\r\n");\
- } printf("\r\n"); \
- }
-
-struct apdu {
- uint8_t seq;
-
- /* command APDU */
- uint8_t *cmd_apdu_head; /* CLS INS P1 P2 [ internal Lc ] */
- uint8_t *cmd_apdu_data;
- size_t cmd_apdu_data_len; /* Nc, calculated by Lc field */
- size_t expected_res_size; /* Ne, calculated by Le field */
-
- /* response APDU */
- uint16_t sw;
- uint16_t res_apdu_data_len;
- uint8_t *res_apdu_data;
-};
-
-#define MAX_CMD_APDU_DATA_SIZE (24+4+512*4)
-#define MAX_RES_APDU_DATA_SIZE (5+9+512*4)
-#define CCID_MSG_HEADER_SIZE 10
-#define USB_LL_BUF_SIZE 64
-
-/* CCID thread */
-#define EV_CARD_CHANGE 1
-#define EV_TX_FINISHED 2 /* CCID Tx finished */
-#define EV_EXEC_ACK_REQUIRED 4 /* OpenPGPcard Execution ACK required */
-#define EV_EXEC_FINISHED 8 /* OpenPGPcard Execution finished */
-#define EV_RX_DATA_READY 16 /* USB Rx data available */
-#define EV_PRESS_BUTTON 32
-
-/* SC HSM thread */
-#define EV_MODIFY_CMD_AVAILABLE 1
-#define EV_VERIFY_CMD_AVAILABLE 2
-#define EV_CMD_AVAILABLE 4
-#define EV_EXIT 8
-#define EV_BUTTON_PRESSED 16
-
-//Variables set by core1
-extern queue_t *ccid_comm;
-extern queue_t *card_comm;
-
-enum ccid_state {
- CCID_STATE_NOCARD, /* No card available */
- CCID_STATE_START, /* Initial */
- CCID_STATE_WAIT, /* Waiting APDU */
-
- CCID_STATE_EXECUTE, /* Executing command */
- CCID_STATE_ACK_REQUIRED_0, /* Ack required (executing)*/
- CCID_STATE_ACK_REQUIRED_1, /* Waiting user's ACK (execution finished) */
-
- CCID_STATE_EXITED, /* CCID Thread Terminated */
- CCID_STATE_EXEC_REQUESTED, /* Exec requested */
-};
-
-#define CLA(a) a.cmd_apdu_head[0]
-#define INS(a) a.cmd_apdu_head[1]
-#define P1(a) a.cmd_apdu_head[2]
-#define P2(a) a.cmd_apdu_head[3]
-
-#define res_APDU apdu.res_apdu_data
-#define res_APDU_size apdu.res_apdu_data_len
-
-extern struct apdu apdu;
-
-uint16_t set_res_sw (uint8_t sw1, uint8_t sw2);
-
-
-static inline const uint16_t make_uint16_t(uint8_t b1, uint8_t b2) {
- return (b1 << 8) | b2;
-}
-static inline const uint16_t get_uint16_t(const uint8_t *b, uint16_t offset) {
- return make_uint16_t(b[offset], b[offset+1]);
-}
-static inline const void put_uint16_t(uint16_t n, uint8_t *b) {
- *b++ = (n >> 8) & 0xff;
- *b = n & 0xff;
-}
-
-
-#ifdef DEBUG
-void stdout_init (void);
-#define DEBUG_MORE 1
-/*
- * Debug functions in debug.c
- */
-void put_byte (uint8_t b);
-void put_byte_with_no_nl (uint8_t b);
-void put_short (uint16_t x);
-void put_word (uint32_t x);
-void put_int (uint32_t x);
-void put_string (const char *s);
-void put_binary (const char *s, int len);
-
-#define DEBUG_INFO(msg) put_string (msg)
-#define DEBUG_WORD(w) put_word (w)
-#define DEBUG_SHORT(h) put_short (h)
-#define DEBUG_BYTE(b) put_byte (b)
-#define DEBUG_BINARY(s,len) put_binary ((const char *)s,len)
-#else
-#define DEBUG_INFO(msg)
-#define DEBUG_WORD(w)
-#define DEBUG_SHORT(h)
-#define DEBUG_BYTE(b)
-#define DEBUG_BINARY(s,len)
-#endif
-
-extern int flash_write_data_to_file(file_t *file, const uint8_t *data, uint16_t len);
-extern void low_flash_available();
-extern int flash_clear_file(file_t *file);
-
-extern pico_unique_board_id_t unique_id;
-
-enum {
- BLINK_NOT_MOUNTED = (250 << 16) | 250,
- BLINK_MOUNTED = (250 << 16) | 250,
- BLINK_SUSPENDED = (500 << 16) | 1000,
- BLINK_PROCESSING = (50 << 16) | 50,
-
- BLINK_ALWAYS_ON = UINT32_MAX,
- BLINK_ALWAYS_OFF = 0
-};
-extern void led_set_blink(uint32_t mode);
-
-#endif
\ No newline at end of file
diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c
index 11cecea..eb4abab 100644
--- a/src/hsm/sc_hsm.c
+++ b/src/hsm/sc_hsm.c
@@ -16,7 +16,7 @@
*/
#include "sc_hsm.h"
-#include "file.h"
+#include "files.h"
#include "libopensc/card-sc-hsm.h"
#include "random.h"
#include "common.h"
@@ -65,8 +65,85 @@ void __attribute__ ((constructor)) sc_hsm_ctor() {
register_app(sc_hsm_select_aid);
}
-void init_sc_hsm() {
+void scan_files() {
+ file_pin1 = search_by_fid(0x1081, NULL, SPECIFY_EF);
+ if (file_pin1) {
+ if (!file_pin1->data) {
+ TU_LOG1("PIN1 is empty. Initializing with default password\r\n");
+ const uint8_t empty[33] = { 0 };
+ flash_write_data_to_file(file_pin1, empty, sizeof(empty));
+ }
+ }
+ else {
+ TU_LOG1("FATAL ERROR: PIN1 not found in memory!\r\n");
+ }
+ file_sopin = search_by_fid(0x1088, NULL, SPECIFY_EF);
+ if (file_sopin) {
+ if (!file_sopin->data) {
+ TU_LOG1("SOPIN is empty. Initializing with default password\r\n");
+ const uint8_t empty[33] = { 0 };
+ flash_write_data_to_file(file_sopin, empty, sizeof(empty));
+ }
+ }
+ else {
+ TU_LOG1("FATAL ERROR: SOPIN not found in memory!\r\n");
+ }
+ file_retries_pin1 = search_by_fid(0x1083, NULL, SPECIFY_EF);
+ if (file_retries_pin1) {
+ if (!file_retries_pin1->data) {
+ TU_LOG1("Retries PIN1 is empty. Initializing with default retriesr\n");
+ const uint8_t retries = 3;
+ flash_write_data_to_file(file_retries_pin1, &retries, sizeof(uint8_t));
+ }
+ }
+ else {
+ TU_LOG1("FATAL ERROR: Retries PIN1 not found in memory!\r\n");
+ }
+ 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");
+ const uint8_t retries = 15;
+ flash_write_data_to_file(file_retries_sopin, &retries, sizeof(uint8_t));
+ }
+ }
+ else {
+ TU_LOG1("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
+ }
+ file_t *tf = NULL;
+
+ tf = search_by_fid(0x1082, NULL, SPECIFY_EF);
+ if (tf) {
+ if (!tf->data) {
+ TU_LOG1("Max retries PIN1 is empty. Initializing with default max retriesr\n");
+ const uint8_t retries = 3;
+ flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
+ }
+ }
+ else {
+ TU_LOG1("FATAL ERROR: Max Retries PIN1 not found in memory!\r\n");
+ }
+ tf = search_by_fid(0x1089, NULL, SPECIFY_EF);
+ if (tf) {
+ if (!tf->data) {
+ TU_LOG1("Max Retries SOPIN is empty. Initializing with default max retries\r\n");
+ const uint8_t retries = 15;
+ flash_write_data_to_file(tf, &retries, sizeof(uint8_t));
+ }
+ }
+ else {
+ TU_LOG1("FATAL ERROR: Retries SOPIN not found in memory!\r\n");
+ }
+ low_flash_available();
+}
+
+void scan_all() {
scan_flash();
+ scan_files();
+}
+
+void init_sc_hsm() {
+ scan_all();
has_session_pin = has_session_sopin = false;
isUserAuthenticated = false;
cmd_select();
@@ -76,7 +153,7 @@ int sc_hsm_unload() {
has_session_pin = has_session_sopin = false;
isUserAuthenticated = false;
sm_session_pin_len = 0;
- return HSM_OK;
+ return CCID_OK;
}
void select_file(file_t *pe) {
@@ -302,7 +379,7 @@ int cvc_prepare_signatures(sc_pkcs15_card_t *p15card, sc_cvc_t *cvc, size_t sig_
}
hash256(cvcbin, cvclen, hsh);
free(cvcbin);
- return HSM_OK;
+ return CCID_OK;
}
int parse_token_info(const file_t *f, int mode) {
@@ -446,14 +523,14 @@ static int cmd_read_binary()
int pin_reset_retries(const file_t *pin, bool force) {
if (!pin)
- return HSM_ERR_NULL_PARAM;
+ return CCID_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 CCID_ERR_FILE_NOT_FOUND;
uint8_t retries = file_read_uint8(act->data+2);
if (retries == 0 && force == false) //blocked
- return HSM_ERR_BLOCKED;
+ return CCID_ERR_BLOCKED;
retries = file_read_uint8(max->data+2);
int r = flash_write_data_to_file((file_t *)act, &retries, sizeof(retries));
low_flash_available();
@@ -462,22 +539,22 @@ int pin_reset_retries(const file_t *pin, bool force) {
int pin_wrong_retry(const file_t *pin) {
if (!pin)
- return HSM_ERR_NULL_PARAM;
+ return CCID_ERR_NULL_PARAM;
const file_t *act = search_by_fid(pin->fid+2, NULL, SPECIFY_EF);
if (!act)
- return HSM_ERR_FILE_NOT_FOUND;
+ return CCID_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));
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
low_flash_available();
if (retries == 0)
- return HSM_ERR_BLOCKED;
+ return CCID_ERR_BLOCKED;
return retries;
}
- return HSM_ERR_BLOCKED;
+ return CCID_ERR_BLOCKED;
}
int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
@@ -491,7 +568,7 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
if (is_secured_apdu() && sm_session_pin_len > 0 && pin == file_pin1) {
if (len == sm_session_pin_len && memcmp(data, sm_session_pin, len) != 0) {
uint8_t retries;
- if ((retries = pin_wrong_retry(pin)) < HSM_OK)
+ if ((retries = pin_wrong_retry(pin)) < CCID_OK)
return SW_PIN_BLOCKED();
return set_res_sw(0x63, 0xc0 | retries);
}
@@ -503,15 +580,15 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
return SW_CONDITIONS_NOT_SATISFIED();
if (memcmp(file_read(pin->data+3), dhash, sizeof(dhash)) != 0) {
uint8_t retries;
- if ((retries = pin_wrong_retry(pin)) < HSM_OK)
+ if ((retries = pin_wrong_retry(pin)) < CCID_OK)
return SW_PIN_BLOCKED();
return set_res_sw(0x63, 0xc0 | retries);
}
}
int r = pin_reset_retries(pin, false);
- if (r == HSM_ERR_BLOCKED)
+ if (r == CCID_ERR_BLOCKED)
return SW_PIN_BLOCKED();
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_MEMORY_FAILURE();
isUserAuthenticated = true;
hash_multi(data, len, session_pin);
@@ -595,7 +672,7 @@ static int cmd_reset_retry() {
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)
+ if (pin_reset_retries(file_pin1, true) != CCID_OK)
return SW_MEMORY_FAILURE();
low_flash_available();
return SW_OK();
@@ -616,7 +693,7 @@ static int cmd_reset_retry() {
if (apdu.cmd_apdu_data_len != 0)
return SW_WRONG_LENGTH();
}
- if (pin_reset_retries(file_pin1, true) != HSM_OK)
+ if (pin_reset_retries(file_pin1, true) != CCID_OK)
return SW_MEMORY_FAILURE();
return SW_OK();
}
@@ -643,7 +720,7 @@ int heapLeft() {
static int cmd_initialize() {
if (apdu.cmd_apdu_data_len > 0) {
initialize_flash(true);
- scan_flash();
+ scan_all();
dkeks = current_dkeks = 0;
uint8_t tag = 0x0, *tag_data = NULL, *p = NULL;
size_t tag_len = 0;
@@ -687,7 +764,7 @@ static int cmd_initialize() {
}
if (dkeks == 0) {
int r = save_dkek_key(random_bytes_get(32));
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_EXEC_ERROR();
}
else
@@ -723,7 +800,7 @@ static int cmd_import_dkek() {
return SW_WRONG_LENGTH();
import_dkek_share(apdu.cmd_apdu_data);
if (++current_dkeks == dkeks) {
- if (save_dkek_key(NULL) != HSM_OK)
+ if (save_dkek_key(NULL) != CCID_OK)
return SW_FILE_NOT_FOUND();
}
@@ -765,14 +842,14 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) {
memcpy(kdata, key_ctx, key_size);
}
r = dkek_encrypt(kdata, key_size);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
return r;
}
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
if (!fpk)
return SW_MEMORY_FAILURE();
r = flash_write_data_to_file(fpk, kdata, key_size);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
//add_file_to_chain(fpk, &ef_kf);
if (type == SC_PKCS15_TYPE_PRKEY_RSA || type == SC_PKCS15_TYPE_PRKEY_EC) {
@@ -806,7 +883,7 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) {
r = flash_write_data_to_file(fpk, asn1bin, asn1len);
if (asn1bin)
free(asn1bin);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
//add_file_to_chain(fpk, &ef_prkdf);
/*
@@ -837,12 +914,12 @@ int store_keys(void *key_ctx, int type, uint8_t key_id, sc_context_t *ctx) {
fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
r = flash_write_data_to_file(fpk, asn1bin, asn1len);
free(asn1bin);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return r;
//add_file_to_chain(fpk, &ef_cdf);
*/
low_flash_available();
- return HSM_OK;
+ return CCID_OK;
}
static int cmd_keypair_gen() {
@@ -909,7 +986,7 @@ static int cmd_keypair_gen() {
uint8_t hsh[32];
ret = cvc_prepare_signatures(&p15card, &cvc, key_size/8, hsh);
- if (ret != HSM_OK) {
+ if (ret != CCID_OK) {
sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
mbedtls_rsa_free(&rsa);
free(ctx);
@@ -925,7 +1002,7 @@ static int cmd_keypair_gen() {
return SW_EXEC_ERROR();
}
ret = store_keys(&rsa, SC_PKCS15_TYPE_PRKEY_RSA, key_id, ctx);
- if (ret != HSM_OK) {
+ if (ret != CCID_OK) {
sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
mbedtls_rsa_free(&rsa);
free(ctx);
@@ -1034,7 +1111,7 @@ static int cmd_keypair_gen() {
uint8_t hsh[32];
ret = cvc_prepare_signatures(&p15card, &cvc, ecdsa.grp.pbits*2/8+9, hsh);
- if (ret != HSM_OK) {
+ if (ret != CCID_OK) {
sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
mbedtls_ecdsa_free(&ecdsa);
free(ctx);
@@ -1051,7 +1128,7 @@ static int cmd_keypair_gen() {
}
ret = store_keys(&ecdsa, SC_PKCS15_TYPE_PRKEY_EC, key_id, ctx);
- if (ret != HSM_OK) {
+ if (ret != CCID_OK) {
sc_pkcs15emu_sc_hsm_free_cvc(&cvc);
mbedtls_ecdsa_free(&ecdsa);
free(ctx);
@@ -1148,7 +1225,7 @@ static int cmd_update_ef() {
}
if (offset == 0) {
int r = flash_write_data_to_file(ef, data, data_len);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_MEMORY_FAILURE();
}
else {
@@ -1159,7 +1236,7 @@ static int cmd_update_ef() {
memcpy(data_merge+offset, data, data_len);
int r = flash_write_data_to_file(ef, data_merge, offset+data_len);
free(data_merge);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_MEMORY_FAILURE();
}
low_flash_available();
@@ -1184,9 +1261,9 @@ static int cmd_delete_file() {
}
if (!authenticate_action(ef, ACL_OP_DELETE_SELF))
return SW_SECURITY_STATUS_NOT_SATISFIED();
- if (flash_clear_file(ef) != HSM_OK)
+ if (flash_clear_file(ef) != CCID_OK)
return SW_EXEC_ERROR();
- if (delete_dynamic_file(ef) != HSM_OK)
+ if (delete_dynamic_file(ef) != CCID_OK)
return SW_EXEC_ERROR();
low_flash_available();
return SW_OK();
@@ -1205,12 +1282,12 @@ static int cmd_change_pin() {
uint16_t r = check_pin(file_pin1, apdu.cmd_apdu_data, pin_len);
if (r != 0x9000)
return r;
- if (load_dkek() != HSM_OK) //loads the DKEK with old pin
+ if (load_dkek() != CCID_OK) //loads the DKEK with old pin
return SW_EXEC_ERROR();
//encrypt DKEK with new pin
hash_multi(apdu.cmd_apdu_data+pin_len, apdu.cmd_apdu_data_len-pin_len, session_pin);
has_session_pin = true;
- if (store_dkek_key() != HSM_OK)
+ if (store_dkek_key() != CCID_OK)
return SW_EXEC_ERROR();
uint8_t dhash[33];
dhash[0] = apdu.cmd_apdu_data_len-pin_len;
@@ -1248,7 +1325,7 @@ static int cmd_key_gen() {
sc_context_t *card_ctx = create_context();
r = store_keys(aes_key, aes_type, key_id, card_ctx);
free(card_ctx);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_MEMORY_FAILURE();
low_flash_available();
return SW_OK();
@@ -1286,7 +1363,7 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
mbedtls_rsa_free(ctx);
return SW_DATA_INVALID();
}
- return HSM_OK;
+ return CCID_OK;
}
int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
@@ -1295,15 +1372,15 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) {
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
memcpy(kdata, file_read(fkey->data+2), key_size);
if (dkek_decrypt(kdata, key_size) != 0) {
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
}
mbedtls_ecp_group_id gid = kdata[0];
int r = mbedtls_ecp_read_key(gid, ctx, kdata+1, key_size-1);
if (r != 0) {
mbedtls_ecdsa_free(ctx);
- return HSM_EXEC_ERROR;
+ return CCID_EXEC_ERROR;
}
- return HSM_OK;
+ return CCID_OK;
}
static int cmd_signature() {
@@ -1332,7 +1409,7 @@ static int cmd_signature() {
int r;
r = load_private_key_rsa(&ctx, fkey);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_EXEC_ERROR();
const uint8_t *hash = apdu.cmd_apdu_data;
size_t hash_len = apdu.cmd_apdu_data_len;
@@ -1428,7 +1505,7 @@ static int cmd_signature() {
md = MBEDTLS_MD_SHA256;
int r;
r = load_private_key_ecdsa(&ctx, fkey);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_CONDITIONS_NOT_SATISFIED();
size_t olen = 0;
uint8_t buf[MBEDTLS_ECDSA_MAX_LEN];
@@ -1463,7 +1540,7 @@ static int cmd_key_wrap() {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1474,7 +1551,7 @@ static int cmd_key_wrap() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1497,7 +1574,7 @@ static int cmd_key_wrap() {
aes_type = HSM_KEY_AES_128;
r = dkek_encode_key(kdata, aes_type, res_APDU, &wrap_len);
}
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_EXEC_ERROR();
res_APDU_size = wrap_len;
return SW_OK();
@@ -1516,7 +1593,7 @@ static int cmd_key_unwrap() {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1524,7 +1601,7 @@ static int cmd_key_unwrap() {
r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_RSA, key_id, card_ctx);
free(card_ctx);
mbedtls_rsa_free(&ctx);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
}
@@ -1532,7 +1609,7 @@ static int cmd_key_unwrap() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = dkek_decode_key(&ctx, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, NULL);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1540,7 +1617,7 @@ static int cmd_key_unwrap() {
r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_EC, key_id, card_ctx);
free(card_ctx);
mbedtls_ecdsa_free(&ctx);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
}
@@ -1548,7 +1625,7 @@ static int cmd_key_unwrap() {
uint8_t aes_key[32];
int key_size = 0, aes_type;
r = dkek_decode_key(aes_key, apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, &key_size);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
if (key_size == 32)
@@ -1560,7 +1637,7 @@ static int cmd_key_unwrap() {
sc_context_t *card_ctx = create_context();
r = store_keys(aes_key, aes_type, key_id, card_ctx);
free(card_ctx);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
return SW_EXEC_ERROR();
}
}
@@ -1578,7 +1655,7 @@ static int cmd_decrypt_asym() {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
int r = load_private_key_rsa(&ctx, ef);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_EXEC_ERROR();
int key_size = file_read_uint16(ef->data);
if (apdu.cmd_apdu_data_len < key_size) //needs padding
@@ -1747,7 +1824,7 @@ static int cmd_derive_asym() {
int r;
r = load_private_key_ecdsa(&ctx, fkey);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1778,7 +1855,7 @@ static int cmd_derive_asym() {
sc_context_t *card_ctx = create_context();
r = store_keys(&ctx, SC_PKCS15_TYPE_PRKEY_EC, dest_id, card_ctx);
free(card_ctx);
- if (r != HSM_OK) {
+ if (r != CCID_OK) {
mbedtls_ecdsa_free(&ctx);
mbedtls_mpi_free(&a);
mbedtls_mpi_free(&nd);
@@ -1935,7 +2012,7 @@ int cmd_general_authenticate() {
r = sm_sign(t, pubkey_len+16, res_APDU+res_APDU_size);
free(t);
- if (r != HSM_OK)
+ if (r != CCID_OK)
return SW_EXEC_ERROR();
res_APDU_size += 8;
}
diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h
index 522b662..24c8d17 100644
--- a/src/hsm/sc_hsm.h
+++ b/src/hsm/sc_hsm.h
@@ -20,80 +20,10 @@
#include
#include "pico/stdlib.h"
-#include "hsm2040.h"
+#include "ccid2040.h"
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_WARNING_CORRUPTED() set_res_sw (0x62, 0x81)
-#define SW_WARNING_EOF() set_res_sw (0x62, 0x82)
-#define SW_WARNING_EF_DEACTIVATED() set_res_sw (0x62, 0x83)
-#define SW_WARNING_WRONG_FCI() set_res_sw (0x62, 0x84)
-#define SW_WARNING_EF_TERMINATED() set_res_sw (0x62, 0x85)
-
-#define SW_WARNING_NOINFO() set_res_sw (0x63, 0x00)
-#define SW_WARNING_FILLUP() set_res_sw (0x63, 0x81)
-
-#define SW_EXEC_ERROR() set_res_sw (0x64, 0x00)
-
-#define SW_MEMORY_FAILURE() set_res_sw (0x65, 0x81)
-
-#define SW_SECURE_MESSAGE_EXEC_ERROR() set_res_sw (0x66, 0x00)
-
-#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)
-#define SW_SECURE_MESSAGING_NOT_SUPPORTED() set_res_sw (0x68, 0x82)
-
-#define SW_COMMAND_INCOMPATIBLE() set_res_sw (0x69, 0x81)
-#define SW_SECURITY_STATUS_NOT_SATISFIED() set_res_sw (0x69, 0x82)
-#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)
-#define SW_SECURE_MESSAGING_MISSING_DO() set_res_sw (0x69, 0x87)
-#define SW_SECURE_MESSAGING_INCORRECT_DO() set_res_sw (0x69, 0x88)
-#define SW_APPLET_SELECT_FAILED() set_res_sw (0x69, 0x99)
-
-#define SW_INCORRECT_PARAMS() set_res_sw (0x6A, 0x80)
-#define SW_FUNC_NOT_SUPPORTED() set_res_sw (0x6A, 0x81)
-#define SW_FILE_NOT_FOUND() set_res_sw (0x6A, 0x82)
-#define SW_RECORD_NOT_FOUND() set_res_sw (0x6A, 0x83)
-#define SW_FILE_FULL() set_res_sw (0x6A, 0x84)
-#define SW_WRONG_NE() set_res_sw (0x6A, 0x85)
-#define SW_INCORRECT_P1P2() set_res_sw (0x6A, 0x86)
-#define SW_WRONG_NC() set_res_sw (0x6A, 0x87)
-#define SW_REFERENCE_NOT_FOUND() set_res_sw (0x6A, 0x88)
-#define SW_FILE_EXISTS() set_res_sw (0x6A, 0x89)
-
-#define SW_WRONG_P1P2() set_res_sw (0x6B, 0x00)
-
-#define SW_CORRECT_LENGTH_00() set_res_sw (0x6C, 0x00)
-
-#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 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
-#define HSM_NO_LOGIN -1005
-#define HSM_EXEC_ERROR -1006
-#define HSM_WRONG_LENGTH -1007
-#define HSM_WRONG_DATA -1008
-#define HSM_WRONG_DKEK -1009
-#define HSM_WRONG_SIGNATURE -1010
-#define HSM_WRONG_PADDING -1011
-#define HSM_VERIFICATION_FAILED -1012
#define ALGO_RSA_RAW 0x20 /* RSA signature with external padding */
#define ALGO_RSA_DECRYPT 0x21 /* RSA decrypt */
diff --git a/src/rng/neug.c b/src/rng/neug.c
deleted file mode 100644
index dabe713..0000000
--- a/src/rng/neug.c
+++ /dev/null
@@ -1,182 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-//Part of the code is taken from GnuK (GPLv3)
-
-
-#include
-#include
-#include
-#include "pico/stdlib.h"
-
-#include "neug.h"
-#include "hardware/structs/rosc.h"
-#include "hardware/gpio.h"
-#include "hardware/adc.h"
-#include "bsp/board.h"
-#include "pico/unique_id.h"
-
-void adc_start() {
- adc_init();
- adc_gpio_init(27);
- adc_select_input(1);
-}
-
-void adc_stop() {
-}
-
-static uint64_t random_word = 0xcbf29ce484222325;
-static uint8_t ep_round = 0;
-
-static void ep_init() {
- random_word = 0xcbf29ce484222325;
- ep_round = 0;
-}
-
-/* Here, we assume a little endian architecture. */
-static int ep_process () {
- if (ep_round == 0) {
- ep_init();
- }
- uint64_t word = 0x0;
- for (int n = 0; n < 64; n++) {
- uint8_t bit1, bit2;
- do
- {
- bit1 = rosc_hw->randombit&0xff;
- //sleep_ms(1);
- bit2 = rosc_hw->randombit&0xff;
- } while(bit1 == bit2);
- word = (word << 1) | bit1;
- }
- random_word ^= word^board_millis()^adc_read();
- random_word *= 0x00000100000001B3;
- if (++ep_round == 8) {
- ep_round = 0;
- return 2; //2 words
- }
- return 0;
-}
-
-static const uint32_t *ep_output() {
- return (uint32_t *)&random_word;
-}
-
-struct rng_rb {
- uint32_t *buf;
- uint8_t head, tail;
- uint8_t size;
- unsigned int full :1;
- unsigned int empty :1;
-};
-
-static void rb_init(struct rng_rb *rb, uint32_t *p, uint8_t size) {
- rb->buf = p;
- rb->size = size;
- rb->head = rb->tail = 0;
- rb->full = 0;
- rb->empty = 1;
-}
-
-static void rb_add(struct rng_rb *rb, uint32_t v) {
- rb->buf[rb->tail++] = v;
- if (rb->tail == rb->size)
- rb->tail = 0;
- if (rb->tail == rb->head)
- rb->full = 1;
- rb->empty = 0;
-}
-
-static uint32_t rb_del(struct rng_rb *rb) {
- uint32_t v = rb->buf[rb->head++];
-
- if (rb->head == rb->size)
- rb->head = 0;
- if (rb->head == rb->tail)
- rb->empty = 1;
- rb->full = 0;
-
- return v;
-}
-
-static struct rng_rb the_ring_buffer;
-
-void *neug_task() {
- struct rng_rb *rb = &the_ring_buffer;
-
- int n;
-
- if ((n = ep_process())) {
- int i;
- const uint32_t *vp;
-
- vp = ep_output();
-
- for (i = 0; i < n; i++) {
- rb_add (rb, *vp++);
- if (rb->full)
- break;
- }
- }
-
- return NULL;
-}
-
-void neug_init(uint32_t *buf, uint8_t size) {
- pico_unique_board_id_t unique_id;
- pico_get_unique_board_id(&unique_id);
- const uint32_t *u = (const uint32_t *)unique_id.id;
- struct rng_rb *rb = &the_ring_buffer;
- int i;
-
- rb_init(rb, buf, size);
-
- adc_start();
-
- ep_init();
-}
-
-void neug_flush(void) {
- struct rng_rb *rb = &the_ring_buffer;
-
- while (!rb->empty)
- rb_del (rb);
-}
-
-uint32_t neug_get(int kick) {
- struct rng_rb *rb = &the_ring_buffer;
- uint32_t v;
-
- while (rb->empty)
- neug_task();
- v = rb_del(rb);
-
- return v;
-}
-
-void neug_wait_full(void) { //should be called only on core1
- struct rng_rb *rb = &the_ring_buffer;
-
- while (!rb->full) {
- sleep_ms(1);
- }
-}
-
-void neug_fini(void) {
- neug_get(1);
-}
-
diff --git a/src/rng/random.c b/src/rng/random.c
deleted file mode 100644
index e0c08bf..0000000
--- a/src/rng/random.c
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#include
-#include
-
-#include "neug.h"
-
-#define RANDOM_BYTES_LENGTH 32
-static uint32_t random_word[RANDOM_BYTES_LENGTH/sizeof (uint32_t)];
-
-void random_init(void) {
- int i;
-
- neug_init(random_word, RANDOM_BYTES_LENGTH/sizeof (uint32_t));
-
- for (i = 0; i < NEUG_PRE_LOOP; i++)
- neug_get();
-}
-
-void random_fini(void) {
- neug_fini ();
-}
-
-/*
- * Return pointer to random 32-byte
- */
-void random_bytes_free (const uint8_t *p);
-#define MAX_RANDOM_BUFFER 1024
-const uint8_t * random_bytes_get(size_t len) {
- if (len > MAX_RANDOM_BUFFER)
- return NULL;
- static uint32_t return_word[MAX_RANDOM_BUFFER/sizeof(uint32_t)];
- for (int ix = 0; ix < len; ix += RANDOM_BYTES_LENGTH) {
- neug_wait_full();
- memcpy(return_word+ix/sizeof(uint32_t), random_word, RANDOM_BYTES_LENGTH);
- random_bytes_free((const uint8_t *)random_word);
- }
- return (const uint8_t *)return_word;
-}
-
-/*
- * Free pointer to random 32-byte
- */
-void random_bytes_free(const uint8_t *p) {
- (void)p;
- memset(random_word, 0, RANDOM_BYTES_LENGTH);
- neug_flush();
-}
-
-/*
- * Return 4-byte salt
- */
-void random_get_salt(uint8_t *p) {
- uint32_t rnd;
-
- rnd = neug_get();
- memcpy(p, &rnd, sizeof (uint32_t));
- rnd = neug_get();
- memcpy(p + sizeof (uint32_t), &rnd, sizeof (uint32_t));
-}
-
-
-/*
- * Random byte iterator
- */
-int random_gen(void *arg, unsigned char *out, size_t out_len) {
- uint8_t *index_p = (uint8_t *)arg;
- uint8_t index = index_p ? *index_p : 0;
- size_t n;
-
- while (out_len) {
- neug_wait_full();
-
- n = RANDOM_BYTES_LENGTH - index;
- if (n > out_len)
- n = out_len;
-
- memcpy(out, ((unsigned char *)random_word) + index, n);
- out += n;
- out_len -= n;
- index += n;
-
- if (index >= RANDOM_BYTES_LENGTH) {
- index = 0;
- neug_flush();
- }
- }
-
- if (index_p)
- *index_p = index;
-
- return 0;
-}
diff --git a/src/rng/random.h b/src/rng/random.h
deleted file mode 100644
index d13c415..0000000
--- a/src/rng/random.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-
-#ifndef _RANDOM_H_
-#define _RANDOM_H_
-
-#include "stdlib.h"
-#include "pico/stdlib.h"
-
-void random_init (void);
-void random_fini (void);
-
-/* 32-byte random bytes */
-const uint8_t *random_bytes_get (size_t);
-void random_bytes_free (const uint8_t *p);
-
-/* 8-byte salt */
-void random_get_salt (uint8_t *p);
-
-/* iterator returning a byta at a time */
-int random_gen (void *arg, unsigned char *output, size_t output_len);
-
-#endif
\ No newline at end of file
diff --git a/src/usb/ccid.h b/src/usb/ccid.h
deleted file mode 100644
index 4149e4b..0000000
--- a/src/usb/ccid.h
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#ifndef _CCID_H_
-#define _CCID_H_
-
-#include "libopensc/ccid-types.h"
-
-static const struct ccid_class_descriptor desc_ccid = {
- .bLength = sizeof(struct ccid_class_descriptor),
- .bDescriptorType = 0x21,
- .bcdCCID = (0x0110),
- .bMaxSlotIndex = 0,
- .bVoltageSupport = 0x01, // 5.0V
- .dwProtocols = (
- 0x01| // T=0
- 0x02), // T=1
- .dwDefaultClock = (0xDFC),
- .dwMaximumClock = (0xDFC),
- .bNumClockSupport = 0,
- .dwDataRate = (0x2580),
- .dwMaxDataRate = (0x2580),
- .bNumDataRatesSupported = 0,
- .dwMaxIFSD = (0xFE), // IFSD is handled by the real reader driver
- .dwSynchProtocols = (0),
- .dwMechanical = (0),
- .dwFeatures = 0x40840, //USB-ICC, short & extended APDU
- .dwMaxCCIDMessageLength = 65544+10,
- .bClassGetResponse = 0xFF,
- .bclassEnvelope = 0xFF,
- .wLcdLayout = 0x0,
- .bPINSupport = 0x0,
- .bMaxCCIDBusySlots = 0x01,
-};
-
-#endif
\ No newline at end of file
diff --git a/src/usb/tusb_config.h b/src/usb/tusb_config.h
deleted file mode 100644
index 69b5534..0000000
--- a/src/usb/tusb_config.h
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * The MIT License (MIT)
- *
- * Copyright (c) 2019 Ha Thach (tinyusb.org)
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- */
-
-#ifndef _TUSB_CONFIG_H_
-#define _TUSB_CONFIG_H_
-
-#ifdef __cplusplus
- extern "C" {
-#endif
-
-//--------------------------------------------------------------------
-// COMMON CONFIGURATION
-//--------------------------------------------------------------------
-
-// defined by board.mk
-#ifndef CFG_TUSB_MCU
- #error CFG_TUSB_MCU must be defined
-#endif
-
-// RHPort number used for device can be defined by board.mk, default to port 0
-#ifndef BOARD_DEVICE_RHPORT_NUM
- #define BOARD_DEVICE_RHPORT_NUM 0
-#endif
-
-// RHPort max operational speed can defined by board.mk
-// Default to Highspeed for MCU with internal HighSpeed PHY (can be port specific), otherwise FullSpeed
-#ifndef BOARD_DEVICE_RHPORT_SPEED
- #if (CFG_TUSB_MCU == OPT_MCU_LPC18XX || CFG_TUSB_MCU == OPT_MCU_LPC43XX || CFG_TUSB_MCU == OPT_MCU_MIMXRT10XX || \
- CFG_TUSB_MCU == OPT_MCU_NUC505 || CFG_TUSB_MCU == OPT_MCU_CXD56 || CFG_TUSB_MCU == OPT_MCU_SAMX7X)
- #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_HIGH_SPEED
- #else
- #define BOARD_DEVICE_RHPORT_SPEED OPT_MODE_FULL_SPEED
- #endif
-#endif
-
-// Device mode with rhport and speed defined by board.mk
-#if BOARD_DEVICE_RHPORT_NUM == 0
- #define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
-#elif BOARD_DEVICE_RHPORT_NUM == 1
- #define CFG_TUSB_RHPORT1_MODE (OPT_MODE_DEVICE | BOARD_DEVICE_RHPORT_SPEED)
-#else
- #error "Incorrect RHPort configuration"
-#endif
-
-#ifndef CFG_TUSB_OS
-#define CFG_TUSB_OS OPT_OS_PICO
-#endif
-
-// CFG_TUSB_DEBUG is defined by compiler in DEBUG build
-// #define CFG_TUSB_DEBUG 0
-
-/* USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment.
- * Tinyusb use follows macros to declare transferring memory so that they can be put
- * into those specific section.
- * e.g
- * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") ))
- * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4)))
- */
-#ifndef CFG_TUSB_MEM_SECTION
-#define CFG_TUSB_MEM_SECTION
-#endif
-
-#ifndef CFG_TUSB_MEM_ALIGN
-#define CFG_TUSB_MEM_ALIGN __attribute__ ((aligned(4)))
-#endif
-
-//--------------------------------------------------------------------
-// DEVICE CONFIGURATION
-//--------------------------------------------------------------------
-
-#ifndef CFG_TUD_ENDPOINT0_SIZE
-#define CFG_TUD_ENDPOINT0_SIZE 64
-#endif
-
-//------------- CLASS -------------//
-#define CFG_TUD_HID 0
-#define CFG_TUD_CDC 0
-#define CFG_TUD_MSC 0
-#define CFG_TUD_MIDI 0
-#define CFG_TUD_VENDOR 1
-
-// HID buffer size Should be sufficient to hold ID (if any) + Data
-#define CFG_TUD_HID_EP_BUFSIZE 16
-
-#define CFG_TUD_VENDOR_RX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-#define CFG_TUD_VENDOR_TX_BUFSIZE (TUD_OPT_HIGH_SPEED ? 512 : 64)
-
-#include "pico/types.h"
-
-static inline uint16_t tu_u32_high16(uint32_t ui32) { return (uint16_t) (ui32 >> 16); }
-static inline uint16_t tu_u32_low16 (uint32_t ui32) { return (uint16_t) (ui32 & 0x0000ffffu); }
-
-#ifdef __cplusplus
- }
-#endif
-
-#endif /* _TUSB_CONFIG_H_ */
diff --git a/src/usb/usb_descriptors.c b/src/usb/usb_descriptors.c
deleted file mode 100644
index 49d021f..0000000
--- a/src/usb/usb_descriptors.c
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
- * Copyright (c) 2022 Pol Henarejos.
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "tusb.h"
-#include "usb_descriptors.h"
-#include "ccid.h"
-#include "pico/unique_id.h"
-#include "version.h"
-
-
-#ifndef USB_VID
-#define USB_VID 0xFEFF
-#endif
-#ifndef USB_PID
-#define USB_PID 0xFCFD
-#endif
-
-#define USB_BCD 0x0200
-
-#define USB_CONFIG_ATT_ONE TU_BIT(7)
-
-#define MAX_USB_POWER 1
-
-
-//--------------------------------------------------------------------+
-// Device Descriptors
-//--------------------------------------------------------------------+
-tusb_desc_device_t const desc_device =
-{
- .bLength = sizeof(tusb_desc_device_t),
- .bDescriptorType = TUSB_DESC_DEVICE,
- .bcdUSB = (USB_BCD),
-
- .bDeviceClass = 0x00,
- .bDeviceSubClass = 0,
- .bDeviceProtocol = 0,
- .bMaxPacketSize0 = CFG_TUD_ENDPOINT0_SIZE,
-
- .idVendor = (USB_VID),
- .idProduct = (USB_PID),
- .bcdDevice = HSM_VERSION,
-
- .iManufacturer = 1,
- .iProduct = 2,
- .iSerialNumber = 3,
-
- .bNumConfigurations = 1
-};
-
-uint8_t const * tud_descriptor_device_cb(void)
-{
- return (uint8_t const *) &desc_device;
-}
-
-tusb_desc_interface_t const desc_interface =
-{
- .bLength = sizeof(tusb_desc_interface_t),
- .bDescriptorType = TUSB_DESC_INTERFACE,
- .bInterfaceNumber = 0,
- .bAlternateSetting = 0,
- .bNumEndpoints = 2,
- .bInterfaceClass = TUSB_CLASS_SMART_CARD,
- .bInterfaceSubClass = 0,
- .bInterfaceProtocol = 0,
- .iInterface = 5,
-};
-
-//--------------------------------------------------------------------+
-// Configuration Descriptor
-//--------------------------------------------------------------------+
-
-tusb_desc_configuration_t const desc_config =
-{
- .bLength = sizeof(tusb_desc_configuration_t),
- .bDescriptorType = TUSB_DESC_CONFIGURATION,
- .wTotalLength = (sizeof(tusb_desc_configuration_t) + sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)),
- .bNumInterfaces = 1,
- .bConfigurationValue = 1,
- .iConfiguration = 4,
- .bmAttributes = USB_CONFIG_ATT_ONE | TUSB_DESC_CONFIG_ATT_REMOTE_WAKEUP,
- .bMaxPower = TUSB_DESC_CONFIG_POWER_MA(MAX_USB_POWER+1),
-};
-
-tusb_desc_endpoint_t const desc_ep1 =
-{
- .bLength = sizeof(tusb_desc_endpoint_t),
- .bDescriptorType = TUSB_DESC_ENDPOINT,
- .bEndpointAddress = TUSB_DIR_IN_MASK | 1,
- .bmAttributes.xfer = TUSB_XFER_BULK,
- .wMaxPacketSize.size = (64),
- .bInterval = 0
-};
-
-tusb_desc_endpoint_t const desc_ep2 =
-{
- .bLength = sizeof(tusb_desc_endpoint_t),
- .bDescriptorType = TUSB_DESC_ENDPOINT,
- .bEndpointAddress = 2,
- .bmAttributes.xfer = TUSB_XFER_BULK,
- .wMaxPacketSize.size = (64),
- .bInterval = 0
-};
-
-static uint8_t desc_config_extended[sizeof(tusb_desc_configuration_t) + sizeof(tusb_desc_interface_t) + sizeof(struct ccid_class_descriptor) + 2*sizeof(tusb_desc_endpoint_t)];
-
-uint8_t const * tud_descriptor_configuration_cb(uint8_t index)
-{
- (void) index; // for multiple configurations
-
- static uint8_t initd = 0;
- if (initd == 0)
- {
- uint8_t *p = desc_config_extended;
- memcpy(p, &desc_config, sizeof(tusb_desc_configuration_t)); p += sizeof(tusb_desc_configuration_t);
- memcpy(p, &desc_interface, sizeof(tusb_desc_interface_t)); p += sizeof(tusb_desc_interface_t);
- memcpy(p, &desc_ccid, sizeof(struct ccid_class_descriptor)); p += sizeof(struct ccid_class_descriptor);
- memcpy(p, &desc_ep1, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t);
- memcpy(p, &desc_ep2, sizeof(tusb_desc_endpoint_t)); p += sizeof(tusb_desc_endpoint_t);
- initd = 1;
- }
- return (const uint8_t *)desc_config_extended;
-}
-
-#define BOS_TOTAL_LEN (TUD_BOS_DESC_LEN)
-
-#define MS_OS_20_DESC_LEN 0xB2
-
-uint8_t const desc_bos[] =
-{
- // total length, number of device caps
- TUD_BOS_DESCRIPTOR(BOS_TOTAL_LEN, 2)
-};
-
-uint8_t const * tud_descriptor_bos_cb(void)
-{
- return desc_bos;
-}
-
-//--------------------------------------------------------------------+
-// String Descriptors
-//--------------------------------------------------------------------+
-
-// array of pointer to string descriptors
-char const* string_desc_arr [] =
-{
- (const char[]) { 0x09, 0x04 }, // 0: is supported language is English (0x0409)
- "Pol Henarejos", // 1: Manufacturer
- "Pico HSM", // 2: Product
- "11223344", // 3: Serials, should use chip ID
- "Pico HSM Config", // 4: Vendor Interface
- "Pico HSM Interface"
-};
-
-static uint16_t _desc_str[32];
-
-uint16_t const* tud_descriptor_string_cb(uint8_t index, uint16_t langid)
-{
- (void) langid;
-
- uint8_t chr_count;
-
- if (index == 0) {
- memcpy(&_desc_str[1], string_desc_arr[0], 2);
- chr_count = 1;
- }
- else {
- // Note: the 0xEE index string is a Microsoft OS 1.0 Descriptors.
- // https://docs.microsoft.com/en-us/windows-hardware/drivers/usbcon/microsoft-defined-usb-descriptors
-
- if ( !(index < sizeof(string_desc_arr)/sizeof(string_desc_arr[0])) )
- return NULL;
-
- const char* str = string_desc_arr[index];
- char unique_id_str[2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1];
- if (index == 3) {
- pico_unique_board_id_t unique_id;
- pico_get_unique_board_id(&unique_id);
- pico_get_unique_board_id_string(unique_id_str, 2 * PICO_UNIQUE_BOARD_ID_SIZE_BYTES + 1);
- str = unique_id_str;
- }
-
- chr_count = strlen(str);
- if ( chr_count > 31 )
- chr_count = 31;
-
- // Convert ASCII string into UTF-16
- for(uint8_t i=0; i.
- */
-
-#ifndef USB_DESCRIPTORS_H_
-#define USB_DESCRIPTORS_H_
-
-enum
-{
- VENDOR_REQUEST_WEBUSB = 1,
- VENDOR_REQUEST_MICROSOFT = 2
-};
-
-extern uint8_t const desc_ms_os_20[];
-
-#endif /* USB_DESCRIPTORS_H_ */