From 470c8662015a099ffdf15f52807115b67f1b167f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 19 Apr 2022 20:33:27 +0200 Subject: [PATCH] Initial commit with template. Signed-off-by: Pol Henarejos --- .gitmodules | 3 + CMakeLists.txt | 101 ++++++++++++++++++++++++ pico-ccid | 1 + pico_sdk_import.cmake | 62 +++++++++++++++ src/openpgp/files.c | 29 +++++++ src/openpgp/files.h | 24 ++++++ src/openpgp/openpgp.c | 174 ++++++++++++++++++++++++++++++++++++++++++ src/openpgp/openpgp.h | 27 +++++++ src/openpgp/version.h | 27 +++++++ 9 files changed, 448 insertions(+) create mode 100644 .gitmodules create mode 100644 CMakeLists.txt create mode 160000 pico-ccid create mode 100644 pico_sdk_import.cmake create mode 100644 src/openpgp/files.c create mode 100644 src/openpgp/files.h create mode 100644 src/openpgp/openpgp.c create mode 100644 src/openpgp/openpgp.h create mode 100644 src/openpgp/version.h diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..a13336e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "pico-ccid"] + path = pico-ccid + url = https://github.com/polhenarejos/pico-ccid.git diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..71a5b17 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,101 @@ + # + # This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). + # 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 . + # + +cmake_minimum_required(VERSION 3.13) + +include(pico_sdk_import.cmake) + +project(pico_openpgp C CXX ASM) + +set(CMAKE_C_STANDARD 11) +set(CMAKE_CXX_STANDARD 17) + +pico_sdk_init() + +add_executable(pico_openpgp) + +if (NOT DEFINED USB_VID) + set(USB_VID 0xFEFF) +endif() +add_definitions(-DUSB_VID=${USB_VID}) +if (NOT DEFINED USB_PID) + set(USB_PID 0xFCFD) +endif() +add_definitions(-DUSB_PID=${USB_PID}) + +target_sources(pico_openpgp PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/ccid2040.c + ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c + ${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.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}/pico-ccid/src/ccid/crypto_utils.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/ccid/eac.c + + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/sha256.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/aes.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/sha512.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/rsa.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/bignum.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/platform_util.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/md.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/oid.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/rsa_alt_helpers.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/constant_time.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ecdsa.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ecp.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ecp_curves.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/asn1write.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/hmac_drbg.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/md5.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ripemd160.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/sha1.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ecdh.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/cmac.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/cipher.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/cipher_wrap.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/chachapoly.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/camellia.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/chacha20.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/aria.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/poly1305.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/gcm.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/ccm.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/des.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/nist_kw.c + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library/hkdf.c + ) + +target_include_directories(pico_openpgp PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/src/fs + ${CMAKE_CURRENT_LIST_DIR}/src/openpgp + ${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}/pico-ccid/mbedtls/include + ${CMAKE_CURRENT_LIST_DIR}/pico-ccid/mbedtls/library + ) + +pico_add_extra_outputs(pico_openpgp) + +#target_compile_definitions(pico_openpgp PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1) + +target_link_libraries(pico_openpgp PRIVATE pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc) diff --git a/pico-ccid b/pico-ccid new file mode 160000 index 0000000..16f23df --- /dev/null +++ b/pico-ccid @@ -0,0 +1 @@ +Subproject commit 16f23dfa6c458e027910d17b0ca0fa35e715cf9b diff --git a/pico_sdk_import.cmake b/pico_sdk_import.cmake new file mode 100644 index 0000000..28efe9e --- /dev/null +++ b/pico_sdk_import.cmake @@ -0,0 +1,62 @@ +# This is a copy of /external/pico_sdk_import.cmake + +# This can be dropped into an external project to help locate this SDK +# It should be include()ed prior to project() + +if (DEFINED ENV{PICO_SDK_PATH} AND (NOT PICO_SDK_PATH)) + set(PICO_SDK_PATH $ENV{PICO_SDK_PATH}) + message("Using PICO_SDK_PATH from environment ('${PICO_SDK_PATH}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT} AND (NOT PICO_SDK_FETCH_FROM_GIT)) + set(PICO_SDK_FETCH_FROM_GIT $ENV{PICO_SDK_FETCH_FROM_GIT}) + message("Using PICO_SDK_FETCH_FROM_GIT from environment ('${PICO_SDK_FETCH_FROM_GIT}')") +endif () + +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_PATH)) + set(PICO_SDK_FETCH_FROM_GIT_PATH $ENV{PICO_SDK_FETCH_FROM_GIT_PATH}) + message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") +endif () + +set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") +set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") +set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") + +if (NOT PICO_SDK_PATH) + if (PICO_SDK_FETCH_FROM_GIT) + include(FetchContent) + set(FETCHCONTENT_BASE_DIR_SAVE ${FETCHCONTENT_BASE_DIR}) + if (PICO_SDK_FETCH_FROM_GIT_PATH) + get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") + endif () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG master + ) + if (NOT pico_sdk) + message("Downloading Raspberry Pi Pico SDK") + FetchContent_Populate(pico_sdk) + set(PICO_SDK_PATH ${pico_sdk_SOURCE_DIR}) + endif () + set(FETCHCONTENT_BASE_DIR ${FETCHCONTENT_BASE_DIR_SAVE}) + else () + message(FATAL_ERROR + "SDK location was not specified. Please set PICO_SDK_PATH or set PICO_SDK_FETCH_FROM_GIT to on to fetch from git." + ) + endif () +endif () + +get_filename_component(PICO_SDK_PATH "${PICO_SDK_PATH}" REALPATH BASE_DIR "${CMAKE_BINARY_DIR}") +if (NOT EXISTS ${PICO_SDK_PATH}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' not found") +endif () + +set(PICO_SDK_INIT_CMAKE_FILE ${PICO_SDK_PATH}/pico_sdk_init.cmake) +if (NOT EXISTS ${PICO_SDK_INIT_CMAKE_FILE}) + message(FATAL_ERROR "Directory '${PICO_SDK_PATH}' does not appear to contain the Raspberry Pi Pico SDK") +endif () + +set(PICO_SDK_PATH ${PICO_SDK_PATH} CACHE PATH "Path to the Raspberry Pi Pico SDK" FORCE) + +include(${PICO_SDK_INIT_CMAKE_FILE}) diff --git a/src/openpgp/files.c b/src/openpgp/files.c new file mode 100644 index 0000000..cef4281 --- /dev/null +++ b/src/openpgp/files.c @@ -0,0 +1,29 @@ +/* + * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). + * 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 openpgp_aid[]; + +file_t file_entries[] = { + { .fid = 0x0000, .parent = 0, .name = openpgp_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_openpgp = &file_entries[sizeof(file_entries)/sizeof(file_t)-2]; +const file_t *file_last = &file_entries[sizeof(file_entries)/sizeof(file_t)-1]; \ No newline at end of file diff --git a/src/openpgp/files.h b/src/openpgp/files.h new file mode 100644 index 0000000..cd8cd16 --- /dev/null +++ b/src/openpgp/files.h @@ -0,0 +1,24 @@ +/* + * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). + * 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 _FILES_H_ +#define _FILES_H_ + +#include "file.h" + +#endif diff --git a/src/openpgp/openpgp.c b/src/openpgp/openpgp.c new file mode 100644 index 0000000..a557afe --- /dev/null +++ b/src/openpgp/openpgp.c @@ -0,0 +1,174 @@ +/* + * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). + * 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 "openpgp.h" +#include "version.h" +#include "eac.h" + +const uint8_t openpgp_aid[] = { + 6, + 0xD2,0x76,0x00,0x01,0x24,0x01 +}; + +char atr_openpgp[] = { + 21, + 0x3b,0xda,0x18,0xff,0x81,0xb1,0xfe,0x75,0x1f,0x03,0x00,0x31,0xf5,0x73,0xc0,0x01,0x60,0x00,0x90,0x00,0x1c +}; + +int openpgp_process_apdu(); + +void select_file(file_t *pe) { + if (!pe) + { + currentDF = (file_t *)MF; + currentEF = NULL; + } + else if (pe->type & FILE_TYPE_INTERNAL_EF) { + currentEF = pe; + currentDF = &file_entries[pe->parent]; + } + else { + currentDF = pe; + } + if (currentEF == file_openpgp) { + selected_applet = currentEF; + //sc_hsm_unload(); //reset auth status + } +} + +static int cmd_select() { + uint8_t p1 = P1(apdu); + uint8_t p2 = P2(apdu); + file_t *pe = NULL; + uint16_t fid = 0x0; + + // Only "first or only occurence" supported + //if ((p2 & 0xF3) != 0x00) { + // return SW_INCORRECT_P1P2(); + //} + + if (apdu.cmd_apdu_data_len >= 2) + fid = get_uint16_t(apdu.cmd_apdu_data, 0); + + //if ((fid & 0xff00) == (KEY_PREFIX << 8)) + // fid = (PRKD_PREFIX << 8) | (fid & 0xff); + + if (!pe) { + if (p1 == 0x0) { //Select MF, DF or EF - File identifier or absent + if (apdu.cmd_apdu_data_len == 0) { + pe = (file_t *)MF; + //ac_fini(); + } + else if (apdu.cmd_apdu_data_len == 2) { + if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) { + return SW_FILE_NOT_FOUND(); + } + } + } + else if (p1 == 0x01) { //Select child DF - DF identifier + if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) { + return SW_FILE_NOT_FOUND(); + } + } + else if (p1 == 0x02) { //Select EF under the current DF - EF identifier + if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) { + return SW_FILE_NOT_FOUND(); + } + } + else if (p1 == 0x03) { //Select parent DF of the current DF - Absent + if (apdu.cmd_apdu_data_len != 0) + return SW_FILE_NOT_FOUND(); + } + else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier + if (!(pe = search_by_name(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len))) { + return SW_FILE_NOT_FOUND(); + } + if (card_terminated) { + return set_res_sw (0x62, 0x85); + } + } + else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier + if (!(pe = search_by_path(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, MF))) { + return SW_FILE_NOT_FOUND(); + } + } + else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier + if (!(pe = search_by_path(apdu.cmd_apdu_data, apdu.cmd_apdu_data_len, currentDF))) { + return SW_FILE_NOT_FOUND(); + } + } + } + if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) { + process_fci(pe); + } + else + return SW_INCORRECT_P1P2(); + select_file(pe); + return SW_OK (); +} + +void init_openpgp() { + isUserAuthenticated = false; + cmd_select(); +} + +int openpgp_unload() { + isUserAuthenticated = false; + return CCID_OK; +} + +app_t *openpgp_select_aid(app_t *a) { + printf("AIDS \r\n"); + DEBUG_PAYLOAD(apdu.cmd_apdu_data,apdu.cmd_apdu_data_len); + DEBUG_PAYLOAD(openpgp_aid+1,openpgp_aid[0]); + if (!memcmp(apdu.cmd_apdu_data, openpgp_aid+1, MIN(apdu.cmd_apdu_data_len,openpgp_aid[0]))) { + printf("SELECTING OPENPGP\r\n"); + a->aid = openpgp_aid; + a->process_apdu = openpgp_process_apdu; + a->unload = openpgp_unload; + init_openpgp(); + return a; + } + return NULL; +} + +void __attribute__ ((constructor)) openpgp_ctor() { + ccid_atr = atr_openpgp; + register_app(openpgp_select_aid); +} + +typedef struct cmd +{ + uint8_t ins; + int (*cmd_handler)(); +} cmd_t; + +static const cmd_t cmds[] = { + { 0x00, 0x0} +}; + +int openpgp_process_apdu() { + int r = sm_unwrap(); + for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) { + if (cmd->ins == INS(apdu)) { + int r = cmd->cmd_handler(); + sm_wrap(); + return r; + } + } + return SW_INS_NOT_SUPPORTED(); +} \ No newline at end of file diff --git a/src/openpgp/openpgp.h b/src/openpgp/openpgp.h new file mode 100644 index 0000000..f91cfc5 --- /dev/null +++ b/src/openpgp/openpgp.h @@ -0,0 +1,27 @@ +/* + * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). + * 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 __OPENPGP_H_ +#define __OPENPGP_H_ + +#include "stdlib.h" +#include + +#include "ccid2040.h" + +#endif + diff --git a/src/openpgp/version.h b/src/openpgp/version.h new file mode 100644 index 0000000..ff791f8 --- /dev/null +++ b/src/openpgp/version.h @@ -0,0 +1,27 @@ +/* + * This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp). + * 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 __VERSION_H_ +#define __VERSION_H_ + +#define OPGP_VERSION 0x0100 + +#define OPGP_VERSION_MAJOR ((OPGP_VERSION >> 8) & 0xff) +#define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff) + +#endif +