Merge branch 'main' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -14,10 +14,10 @@ name: "Emulation and test"
|
|||||||
on:
|
on:
|
||||||
workflow_dispatch:
|
workflow_dispatch:
|
||||||
push:
|
push:
|
||||||
branches: [ "main", "eddsa" ]
|
branches: [ "main", "piv", "eddsa" ]
|
||||||
pull_request:
|
pull_request:
|
||||||
# The branches below must be a subset of the branches above
|
# The branches below must be a subset of the branches above
|
||||||
branches: [ "main", "eddsa" ]
|
branches: [ "main", "piv", "eddsa" ]
|
||||||
schedule:
|
schedule:
|
||||||
- cron: '23 5 * * 4'
|
- cron: '23 5 * * 4'
|
||||||
|
|
||||||
|
|||||||
2
.gitmodules
vendored
2
.gitmodules
vendored
@@ -1,3 +1,3 @@
|
|||||||
[submodule "pico-keys-sdk"]
|
[submodule "pico-keys-sdk"]
|
||||||
path = pico-keys-sdk
|
path = pico-keys-sdk
|
||||||
url = ../pico-keys-sdk
|
url = https://github.com/polhenarejos/pico-keys-sdk
|
||||||
|
|||||||
@@ -17,6 +17,11 @@
|
|||||||
|
|
||||||
cmake_minimum_required(VERSION 3.13)
|
cmake_minimum_required(VERSION 3.13)
|
||||||
|
|
||||||
|
if(ESP_PLATFORM)
|
||||||
|
set(EXTRA_COMPONENT_DIRS src pico-keys-sdk/src)
|
||||||
|
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||||
|
else()
|
||||||
|
|
||||||
if(ENABLE_EMULATION)
|
if(ENABLE_EMULATION)
|
||||||
else()
|
else()
|
||||||
include(pico_sdk_import.cmake)
|
include(pico_sdk_import.cmake)
|
||||||
@@ -33,10 +38,13 @@ pico_sdk_init()
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_executable(pico_openpgp)
|
add_executable(pico_openpgp)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(SOURCES ${SOURCES}
|
set(SOURCES ${SOURCES}
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c
|
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c
|
||||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
|
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/piv.c
|
||||||
|
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/management.c
|
||||||
)
|
)
|
||||||
|
|
||||||
set(INCLUDES ${INCLUDES}
|
set(INCLUDES ${INCLUDES}
|
||||||
@@ -45,7 +53,11 @@ set(INCLUDES ${INCLUDES}
|
|||||||
|
|
||||||
set(USB_ITF_CCID 1)
|
set(USB_ITF_CCID 1)
|
||||||
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
|
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
|
||||||
|
if(ESP_PLATFORM)
|
||||||
|
project(pico_fido)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(NOT ESP_PLATFORM)
|
||||||
target_sources(pico_openpgp PUBLIC ${SOURCES})
|
target_sources(pico_openpgp PUBLIC ${SOURCES})
|
||||||
target_include_directories(pico_openpgp PUBLIC ${INCLUDES})
|
target_include_directories(pico_openpgp PUBLIC ${INCLUDES})
|
||||||
|
|
||||||
@@ -69,11 +81,13 @@ target_link_options(pico_openpgp PUBLIC
|
|||||||
-Wl,--gc-sections
|
-Wl,--gc-sections
|
||||||
)
|
)
|
||||||
endif (APPLE)
|
endif (APPLE)
|
||||||
|
target_link_libraries(pico_openpgp PRIVATE pthread m)
|
||||||
else()
|
else()
|
||||||
|
|
||||||
pico_add_extra_outputs(pico_openpgp)
|
pico_add_extra_outputs(pico_openpgp)
|
||||||
|
|
||||||
#target_compile_definitions(pico_openpgp PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1)
|
#target_compile_definitions(pico_openpgp PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1)
|
||||||
|
|
||||||
target_link_libraries(pico_openpgp PRIVATE pico_hsm_sdk pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc)
|
target_link_libraries(pico_openpgp PRIVATE pico_keys_sdk pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id pico_aon_timer)
|
||||||
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
VERSION_MAJOR="1"
|
VERSION_MAJOR="2"
|
||||||
VERSION_MINOR="10"
|
VERSION_MINOR="2"
|
||||||
|
|
||||||
rm -rf release/*
|
rm -rf release/*
|
||||||
cd build_release
|
cd build_release
|
||||||
@@ -17,6 +17,7 @@ for board in adafruit_feather_rp2040 \
|
|||||||
eetree_gamekit_rp2040 \
|
eetree_gamekit_rp2040 \
|
||||||
garatronic_pybstick26_rp2040 \
|
garatronic_pybstick26_rp2040 \
|
||||||
melopero_shake_rp2040 \
|
melopero_shake_rp2040 \
|
||||||
|
nullbits_bit_c_pro \
|
||||||
pico \
|
pico \
|
||||||
pico_w \
|
pico_w \
|
||||||
pimoroni_badger2040 \
|
pimoroni_badger2040 \
|
||||||
@@ -31,6 +32,7 @@ for board in adafruit_feather_rp2040 \
|
|||||||
pimoroni_servo2040 \
|
pimoroni_servo2040 \
|
||||||
pimoroni_tiny2040 \
|
pimoroni_tiny2040 \
|
||||||
pimoroni_tiny2040_2mb \
|
pimoroni_tiny2040_2mb \
|
||||||
|
pololu_3pi_2040_robot \
|
||||||
seeed_xiao_rp2040 \
|
seeed_xiao_rp2040 \
|
||||||
solderparty_rp2040_stamp \
|
solderparty_rp2040_stamp \
|
||||||
solderparty_rp2040_stamp_carrier \
|
solderparty_rp2040_stamp_carrier \
|
||||||
@@ -40,6 +42,8 @@ for board in adafruit_feather_rp2040 \
|
|||||||
sparkfun_thingplus \
|
sparkfun_thingplus \
|
||||||
vgaboard \
|
vgaboard \
|
||||||
waveshare_rp2040_lcd_0.96 \
|
waveshare_rp2040_lcd_0.96 \
|
||||||
|
waveshare_rp2040_lcd_1.28 \
|
||||||
|
waveshare_rp2040_one \
|
||||||
waveshare_rp2040_plus_4mb \
|
waveshare_rp2040_plus_4mb \
|
||||||
waveshare_rp2040_plus_16mb \
|
waveshare_rp2040_plus_16mb \
|
||||||
waveshare_rp2040_zero \
|
waveshare_rp2040_zero \
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
#
|
#
|
||||||
|
|
||||||
VERSION_MAJOR="4" #Version of Pico CCID Core
|
VERSION_MAJOR="5" #Version of Pico Keys SDK
|
||||||
VERSION_MINOR="0"
|
VERSION_MINOR="0"
|
||||||
|
|
||||||
echo "----------------------------"
|
echo "----------------------------"
|
||||||
|
|||||||
@@ -18,9 +18,20 @@ if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_P
|
|||||||
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')")
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
|
if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG))
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG})
|
||||||
|
message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')")
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG)
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_TAG "master")
|
||||||
|
message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG")
|
||||||
|
endif()
|
||||||
|
|
||||||
set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK")
|
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 "${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")
|
set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK")
|
||||||
|
set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK")
|
||||||
|
|
||||||
if (NOT PICO_SDK_PATH)
|
if (NOT PICO_SDK_PATH)
|
||||||
if (PICO_SDK_FETCH_FROM_GIT)
|
if (PICO_SDK_FETCH_FROM_GIT)
|
||||||
@@ -29,11 +40,22 @@ if (NOT PICO_SDK_PATH)
|
|||||||
if (PICO_SDK_FETCH_FROM_GIT_PATH)
|
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}")
|
get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}")
|
||||||
endif ()
|
endif ()
|
||||||
FetchContent_Declare(
|
# GIT_SUBMODULES_RECURSE was added in 3.17
|
||||||
pico_sdk
|
if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0")
|
||||||
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
FetchContent_Declare(
|
||||||
GIT_TAG master
|
pico_sdk
|
||||||
)
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||||
|
GIT_SUBMODULES_RECURSE FALSE
|
||||||
|
)
|
||||||
|
else ()
|
||||||
|
FetchContent_Declare(
|
||||||
|
pico_sdk
|
||||||
|
GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk
|
||||||
|
GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG}
|
||||||
|
)
|
||||||
|
endif ()
|
||||||
|
|
||||||
if (NOT pico_sdk)
|
if (NOT pico_sdk)
|
||||||
message("Downloading Raspberry Pi Pico SDK")
|
message("Downloading Raspberry Pi Pico SDK")
|
||||||
FetchContent_Populate(pico_sdk)
|
FetchContent_Populate(pico_sdk)
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ extern int parse_algoinfo(const file_t *f, int mode);
|
|||||||
extern int parse_app_data(const file_t *f, int mode);
|
extern int parse_app_data(const file_t *f, int mode);
|
||||||
extern int parse_discrete_do(const file_t *f, int mode);
|
extern int parse_discrete_do(const file_t *f, int mode);
|
||||||
extern int parse_pw_status(const file_t *f, int mode);
|
extern int parse_pw_status(const file_t *f, int mode);
|
||||||
|
extern int piv_parse_discovery(const file_t *f);
|
||||||
|
|
||||||
uint8_t historical_bytes[] = {
|
uint8_t historical_bytes[] = {
|
||||||
10, 0,
|
10, 0,
|
||||||
@@ -249,10 +250,236 @@ file_t file_entries[] = {
|
|||||||
/* 56 */ { .fid = EF_CH_3, .parent = 0, .name = NULL,
|
/* 56 */ { .fid = EF_CH_3, .parent = 0, .name = NULL,
|
||||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
|
||||||
|
// ** PIV ** //
|
||||||
|
/* 57 */ { .fid = EF_PIV_ADMIN_DATA, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 58 */ { .fid = EF_PIV_ATTESTATION, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 59 */ { .fid = EF_PIV_MSCMAP, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 60 */ { .fid = EF_PIV_MSROOTS1, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 61 */ { .fid = EF_PIV_MSROOTS2, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 62 */ { .fid = EF_PIV_MSROOTS3, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 63 */ { .fid = EF_PIV_MSROOTS4, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 64 */ { .fid = EF_PIV_MSROOTS5, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 65 */ { .fid = EF_PIV_KEY_AUTHENTICATION, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 66 */ { .fid = EF_PIV_KEY_CARDMGM, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 67 */ { .fid = EF_PIV_KEY_SIGNATURE, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 68 */ { .fid = EF_PIV_KEY_KEYMGM, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 69 */ { .fid = EF_PIV_KEY_CARDAUTH, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 70 */ { .fid = EF_PIV_KEY_RETIRED1, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 71 */ { .fid = EF_PIV_KEY_RETIRED2, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 72 */ { .fid = EF_PIV_KEY_RETIRED3, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 73 */ { .fid = EF_PIV_KEY_RETIRED4, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 74 */ { .fid = EF_PIV_KEY_RETIRED5, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 75 */ { .fid = EF_PIV_KEY_RETIRED6, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 76 */ { .fid = EF_PIV_KEY_RETIRED7, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 77 */ { .fid = EF_PIV_KEY_RETIRED8, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 78 */ { .fid = EF_PIV_KEY_RETIRED9, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 79 */ { .fid = EF_PIV_KEY_RETIRED10, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 80 */ { .fid = EF_PIV_KEY_RETIRED11, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 81 */ { .fid = EF_PIV_KEY_RETIRED12, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 82 */ { .fid = EF_PIV_KEY_RETIRED12, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 83 */ { .fid = EF_PIV_KEY_RETIRED13, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 84 */ { .fid = EF_PIV_KEY_RETIRED14, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 85 */ { .fid = EF_PIV_KEY_RETIRED15, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 86 */ { .fid = EF_PIV_KEY_RETIRED16, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 87 */ { .fid = EF_PIV_KEY_RETIRED17, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 88 */ { .fid = EF_PIV_KEY_RETIRED18, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 89 */ { .fid = EF_PIV_KEY_RETIRED19, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 90 */ { .fid = EF_PIV_KEY_RETIRED20, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 91 */ { .fid = EF_PIV_KEY_ATTESTATION, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 92 */ { .fid = EF_PIV_CAPABILITY, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 93 */ { .fid = EF_PIV_CHUID, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 94 */ { .fid = EF_PIV_AUTHENTICATION, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 95 */ { .fid = EF_PIV_FINGERPRINTS, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 96 */ { .fid = EF_PIV_SECURITY, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 97 */ { .fid = EF_PIV_FACIAL, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 98 */ { .fid = EF_PIV_PRINTED, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 99 */ { .fid = EF_PIV_SIGNATURE, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 100 */ { .fid = EF_PIV_KEY_MANAGEMENT, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 101 */ { .fid = EF_PIV_CARD_AUTH, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 102 */ { .fid = EF_PIV_DISCOVERY, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) piv_parse_discovery,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 103 */ { .fid = EF_PIV_KEY_HISTORY, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 104 */ { .fid = EF_PIV_IRIS, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 105 */ { .fid = EF_PIV_BITGT, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 106 */ { .fid = EF_PIV_SM_SIGNER, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 107 */ { .fid = EF_PIV_PC_REF_DATA, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 108 */ { .fid = EF_PIV_RETIRED1, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 109 */ { .fid = EF_PIV_RETIRED2, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 110 */ { .fid = EF_PIV_RETIRED3, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 111 */ { .fid = EF_PIV_RETIRED4, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 112 */ { .fid = EF_PIV_RETIRED5, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 113 */ { .fid = EF_PIV_RETIRED6, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 114 */ { .fid = EF_PIV_RETIRED7, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 115 */ { .fid = EF_PIV_RETIRED8, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 116 */ { .fid = EF_PIV_RETIRED9, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 117 */ { .fid = EF_PIV_RETIRED10, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 118 */ { .fid = EF_PIV_RETIRED11, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 119 */ { .fid = EF_PIV_RETIRED12, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 120 */ { .fid = EF_PIV_RETIRED13, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 121 */ { .fid = EF_PIV_RETIRED14, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 122 */ { .fid = EF_PIV_RETIRED15, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 123 */ { .fid = EF_PIV_RETIRED16, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 124 */ { .fid = EF_PIV_RETIRED17, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 125 */ { .fid = EF_PIV_RETIRED18, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 126 */ { .fid = EF_PIV_RETIRED19, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 127 */ { .fid = EF_PIV_RETIRED20, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
/* 128 */ { .fid = EF_PIV_PIN, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 129 */ { .fid = EF_PIV_PUK, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||||
|
/* 130 */ { .fid = EF_META, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
|
||||||
|
/* 131 */ { .fid = EF_PW_RETRIES, .parent = 0, .name = NULL,
|
||||||
|
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||||
|
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||||
|
|
||||||
/* 57 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
|
/* 132 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
|
||||||
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
|
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
|
||||||
/* 58 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_UNKNOWN, .data = NULL,
|
/* 133 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL,
|
||||||
.ef_structure = 0, .acl = ACL_NONE } //end
|
.ef_structure = 0, .acl = ACL_NONE } //end
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -28,6 +28,7 @@
|
|||||||
#define EF_ALGO_PRIV2 0x10c2
|
#define EF_ALGO_PRIV2 0x10c2
|
||||||
#define EF_ALGO_PRIV3 0x10c3
|
#define EF_ALGO_PRIV3 0x10c3
|
||||||
#define EF_PW_PRIV 0x10c4
|
#define EF_PW_PRIV 0x10c4
|
||||||
|
#define EF_PW_RETRIES 0x10c5
|
||||||
#define EF_PK_SIG 0x10d1
|
#define EF_PK_SIG 0x10d1
|
||||||
#define EF_PK_DEC 0x10d2
|
#define EF_PK_DEC 0x10d2
|
||||||
#define EF_PK_AUT 0x10d3
|
#define EF_PK_AUT 0x10d3
|
||||||
@@ -81,4 +82,85 @@
|
|||||||
#define EF_EXLEN_INFO 0x7f66 //C
|
#define EF_EXLEN_INFO 0x7f66 //C
|
||||||
#define EF_GFM 0x7f74 //C
|
#define EF_GFM 0x7f74 //C
|
||||||
|
|
||||||
|
// PIV
|
||||||
|
|
||||||
|
#define EF_PIV_PIN 0x1184
|
||||||
|
#define EF_PIV_PUK 0x1185
|
||||||
|
|
||||||
|
#define EF_PIV_ADMIN_DATA 0xff00
|
||||||
|
#define EF_PIV_ATTESTATION 0xff01
|
||||||
|
#define EF_PIV_MSCMAP 0xff10
|
||||||
|
#define EF_PIV_MSROOTS1 0xff11
|
||||||
|
#define EF_PIV_MSROOTS2 0xff12
|
||||||
|
#define EF_PIV_MSROOTS3 0xff13
|
||||||
|
#define EF_PIV_MSROOTS4 0xff14
|
||||||
|
#define EF_PIV_MSROOTS5 0xff15
|
||||||
|
|
||||||
|
#define EF_PIV_KEY_AUTHENTICATION 0x009a
|
||||||
|
#define EF_PIV_KEY_CARDMGM 0x009b
|
||||||
|
#define EF_PIV_KEY_SIGNATURE 0x009c
|
||||||
|
#define EF_PIV_KEY_KEYMGM 0x009d
|
||||||
|
#define EF_PIV_KEY_CARDAUTH 0x009e
|
||||||
|
#define EF_PIV_KEY_RETIRED1 0x0082
|
||||||
|
#define EF_PIV_KEY_RETIRED2 0x0083
|
||||||
|
#define EF_PIV_KEY_RETIRED3 0x0084
|
||||||
|
#define EF_PIV_KEY_RETIRED4 0x0085
|
||||||
|
#define EF_PIV_KEY_RETIRED5 0x0086
|
||||||
|
#define EF_PIV_KEY_RETIRED6 0x0087
|
||||||
|
#define EF_PIV_KEY_RETIRED7 0x0088
|
||||||
|
#define EF_PIV_KEY_RETIRED8 0x0089
|
||||||
|
#define EF_PIV_KEY_RETIRED9 0x008a
|
||||||
|
#define EF_PIV_KEY_RETIRED10 0x008b
|
||||||
|
#define EF_PIV_KEY_RETIRED11 0x008c
|
||||||
|
#define EF_PIV_KEY_RETIRED12 0x008d
|
||||||
|
#define EF_PIV_KEY_RETIRED13 0x008e
|
||||||
|
#define EF_PIV_KEY_RETIRED14 0x008f
|
||||||
|
#define EF_PIV_KEY_RETIRED15 0x0090
|
||||||
|
#define EF_PIV_KEY_RETIRED16 0x0091
|
||||||
|
#define EF_PIV_KEY_RETIRED17 0x0092
|
||||||
|
#define EF_PIV_KEY_RETIRED18 0x0096 // It's 0x93 but assigned to EF_SIG_COUNT
|
||||||
|
#define EF_PIV_KEY_RETIRED19 0x0094
|
||||||
|
#define EF_PIV_KEY_RETIRED20 0x0095
|
||||||
|
#define EF_PIV_KEY_ATTESTATION 0x00fb // It's 0xf9 but assigned to EF_KDF
|
||||||
|
|
||||||
|
#define EF_PIV_CAPABILITY 0xc107
|
||||||
|
#define EF_PIV_CHUID 0xc102
|
||||||
|
#define EF_PIV_AUTHENTICATION 0xc105 /* cert for 9a key */
|
||||||
|
#define EF_PIV_FINGERPRINTS 0xc103
|
||||||
|
#define EF_PIV_SECURITY 0xc106
|
||||||
|
#define EF_PIV_FACIAL 0xc108
|
||||||
|
#define EF_PIV_PRINTED 0xc109
|
||||||
|
#define EF_PIV_SIGNATURE 0xc10a /* cert for 9c key */
|
||||||
|
#define EF_PIV_KEY_MANAGEMENT 0xc10b /* cert for 9d key */
|
||||||
|
#define EF_PIV_CARD_AUTH 0xc101 /* cert for 9e key */
|
||||||
|
#define EF_PIV_DISCOVERY 0x007e
|
||||||
|
#define EF_PIV_KEY_HISTORY 0xc10c
|
||||||
|
#define EF_PIV_IRIS 0xc121
|
||||||
|
#define EF_PIV_BITGT 0x7f61
|
||||||
|
#define EF_PIV_SM_SIGNER 0xc122
|
||||||
|
#define EF_PIV_PC_REF_DATA 0xc123
|
||||||
|
|
||||||
|
#define EF_PIV_RETIRED1 0xc10d
|
||||||
|
#define EF_PIV_RETIRED2 0xc10e
|
||||||
|
#define EF_PIV_RETIRED3 0xc10f
|
||||||
|
#define EF_PIV_RETIRED4 0xc110
|
||||||
|
#define EF_PIV_RETIRED5 0xc111
|
||||||
|
#define EF_PIV_RETIRED6 0xc112
|
||||||
|
#define EF_PIV_RETIRED7 0xc113
|
||||||
|
#define EF_PIV_RETIRED8 0xc114
|
||||||
|
#define EF_PIV_RETIRED9 0xc115
|
||||||
|
#define EF_PIV_RETIRED10 0xc116
|
||||||
|
#define EF_PIV_RETIRED11 0xc117
|
||||||
|
#define EF_PIV_RETIRED12 0xc118
|
||||||
|
#define EF_PIV_RETIRED13 0xc119
|
||||||
|
#define EF_PIV_RETIRED14 0xc11a
|
||||||
|
#define EF_PIV_RETIRED15 0xc11b
|
||||||
|
#define EF_PIV_RETIRED16 0xc11c
|
||||||
|
#define EF_PIV_RETIRED17 0xc11d
|
||||||
|
#define EF_PIV_RETIRED18 0xc11e
|
||||||
|
#define EF_PIV_RETIRED19 0xc11f
|
||||||
|
#define EF_PIV_RETIRED20 0xc120
|
||||||
|
|
||||||
|
#define EF_DEV_CONF 0x1122
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
153
src/openpgp/management.c
Normal file
153
src/openpgp/management.c
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "pico_keys.h"
|
||||||
|
#include "apdu.h"
|
||||||
|
#include "version.h"
|
||||||
|
#include "files.h"
|
||||||
|
#include "asn1.h"
|
||||||
|
#include "management.h"
|
||||||
|
|
||||||
|
int man_process_apdu();
|
||||||
|
int man_unload();
|
||||||
|
|
||||||
|
const uint8_t man_aid[] = {
|
||||||
|
8,
|
||||||
|
0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
|
||||||
|
};
|
||||||
|
|
||||||
|
extern void init_piv();
|
||||||
|
int man_select(app_t *a, uint8_t force) {
|
||||||
|
(void) force;
|
||||||
|
a->process_apdu = man_process_apdu;
|
||||||
|
a->unload = man_unload;
|
||||||
|
sprintf((char *) res_APDU, "%d.%d.0", PIV_VERSION_MAJOR, PIV_VERSION_MINOR);
|
||||||
|
res_APDU_size = strlen((char *) res_APDU);
|
||||||
|
apdu.ne = res_APDU_size;
|
||||||
|
init_piv();
|
||||||
|
return CCID_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
INITIALIZER( man_ctor ) {
|
||||||
|
register_app(man_select, man_aid);
|
||||||
|
}
|
||||||
|
|
||||||
|
int man_unload() {
|
||||||
|
return CCID_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool cap_supported(uint16_t cap) {
|
||||||
|
file_t *ef = search_dynamic_file(EF_DEV_CONF);
|
||||||
|
if (file_has_data(ef)) {
|
||||||
|
uint16_t tag = 0x0;
|
||||||
|
uint8_t *tag_data = NULL, *p = NULL;
|
||||||
|
uint16_t tag_len = 0;
|
||||||
|
asn1_ctx_t ctxi;
|
||||||
|
asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
|
||||||
|
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
|
||||||
|
if (tag == TAG_USB_ENABLED) {
|
||||||
|
uint16_t ecaps = tag_data[0];
|
||||||
|
if (tag_len == 2) {
|
||||||
|
ecaps = (tag_data[0] << 8) | tag_data[1];
|
||||||
|
}
|
||||||
|
return ecaps & cap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
int man_get_config() {
|
||||||
|
file_t *ef = search_dynamic_file(EF_DEV_CONF);
|
||||||
|
res_APDU_size = 0;
|
||||||
|
res_APDU[res_APDU_size++] = 0; // Overall length. Filled later
|
||||||
|
res_APDU[res_APDU_size++] = TAG_USB_SUPPORTED;
|
||||||
|
res_APDU[res_APDU_size++] = 1;
|
||||||
|
res_APDU[res_APDU_size++] = CAP_PIV | CAP_OPENPGP;
|
||||||
|
res_APDU[res_APDU_size++] = TAG_SERIAL;
|
||||||
|
res_APDU[res_APDU_size++] = 4;
|
||||||
|
memcpy(res_APDU + res_APDU_size, pico_serial.id, 4);
|
||||||
|
res_APDU_size += 4;
|
||||||
|
res_APDU[res_APDU_size++] = TAG_FORM_FACTOR;
|
||||||
|
res_APDU[res_APDU_size++] = 1;
|
||||||
|
res_APDU[res_APDU_size++] = 0x01;
|
||||||
|
res_APDU[res_APDU_size++] = TAG_VERSION;
|
||||||
|
res_APDU[res_APDU_size++] = 3;
|
||||||
|
res_APDU[res_APDU_size++] = PIV_VERSION_MAJOR;
|
||||||
|
res_APDU[res_APDU_size++] = PIV_VERSION_MINOR;
|
||||||
|
res_APDU[res_APDU_size++] = 0;
|
||||||
|
res_APDU[res_APDU_size++] = TAG_NFC_SUPPORTED;
|
||||||
|
res_APDU[res_APDU_size++] = 1;
|
||||||
|
res_APDU[res_APDU_size++] = 0x00;
|
||||||
|
if (!file_has_data(ef)) {
|
||||||
|
res_APDU[res_APDU_size++] = TAG_USB_ENABLED;
|
||||||
|
res_APDU[res_APDU_size++] = 1;
|
||||||
|
res_APDU[res_APDU_size++] = CAP_PIV | CAP_OPENPGP;
|
||||||
|
res_APDU[res_APDU_size++] = TAG_DEVICE_FLAGS;
|
||||||
|
res_APDU[res_APDU_size++] = 1;
|
||||||
|
res_APDU[res_APDU_size++] = FLAG_EJECT;
|
||||||
|
res_APDU[res_APDU_size++] = TAG_CONFIG_LOCK;
|
||||||
|
res_APDU[res_APDU_size++] = 1;
|
||||||
|
res_APDU[res_APDU_size++] = 0x00;
|
||||||
|
res_APDU[res_APDU_size++] = TAG_NFC_ENABLED;
|
||||||
|
res_APDU[res_APDU_size++] = 1;
|
||||||
|
res_APDU[res_APDU_size++] = 0x00;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
memcpy(res_APDU + res_APDU_size, file_get_data(ef), file_get_size(ef));
|
||||||
|
res_APDU_size += file_get_size(ef);
|
||||||
|
}
|
||||||
|
res_APDU[0] = res_APDU_size - 1;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_read_config() {
|
||||||
|
man_get_config();
|
||||||
|
return SW_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
int cmd_write_config() {
|
||||||
|
if (apdu.data[0] != apdu.nc - 1) {
|
||||||
|
return SW_WRONG_DATA();
|
||||||
|
}
|
||||||
|
file_t *ef = file_new(EF_DEV_CONF);
|
||||||
|
file_put_data(ef, apdu.data + 1, apdu.nc - 1);
|
||||||
|
low_flash_available();
|
||||||
|
return SW_OK();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define INS_READ_CONFIG 0x1D
|
||||||
|
#define INS_WRITE_CONFIG 0x1C
|
||||||
|
|
||||||
|
static const cmd_t cmds[] = {
|
||||||
|
{ INS_READ_CONFIG, cmd_read_config },
|
||||||
|
{ INS_WRITE_CONFIG, cmd_write_config },
|
||||||
|
{ 0x00, 0x0 }
|
||||||
|
};
|
||||||
|
|
||||||
|
int man_process_apdu() {
|
||||||
|
if (CLA(apdu) != 0x00) {
|
||||||
|
return SW_CLA_NOT_SUPPORTED();
|
||||||
|
}
|
||||||
|
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
|
||||||
|
if (cmd->ins == INS(apdu)) {
|
||||||
|
int r = cmd->cmd_handler();
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return SW_INS_NOT_SUPPORTED();
|
||||||
|
}
|
||||||
55
src/openpgp/management.h
Normal file
55
src/openpgp/management.h
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
|
||||||
|
* 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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _MANAGEMENT_H_
|
||||||
|
#define _MANAGEMENT_H_
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
|
||||||
|
#include "pico/stdlib.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define TAG_USB_SUPPORTED 0x01
|
||||||
|
#define TAG_SERIAL 0x02
|
||||||
|
#define TAG_USB_ENABLED 0x03
|
||||||
|
#define TAG_FORM_FACTOR 0x04
|
||||||
|
#define TAG_VERSION 0x05
|
||||||
|
#define TAG_AUTO_EJECT_TIMEOUT 0x06
|
||||||
|
#define TAG_CHALRESP_TIMEOUT 0x07
|
||||||
|
#define TAG_DEVICE_FLAGS 0x08
|
||||||
|
#define TAG_APP_VERSIONS 0x09
|
||||||
|
#define TAG_CONFIG_LOCK 0x0A
|
||||||
|
#define TAG_UNLOCK 0x0B
|
||||||
|
#define TAG_REBOOT 0x0C
|
||||||
|
#define TAG_NFC_SUPPORTED 0x0D
|
||||||
|
#define TAG_NFC_ENABLED 0x0E
|
||||||
|
|
||||||
|
#define CAP_OTP 0x01
|
||||||
|
#define CAP_U2F 0x02
|
||||||
|
#define CAP_FIDO2 0x200
|
||||||
|
#define CAP_OATH 0x20
|
||||||
|
#define CAP_PIV 0x10
|
||||||
|
#define CAP_OPENPGP 0x08
|
||||||
|
#define CAP_HSMAUTH 0x100
|
||||||
|
|
||||||
|
#define FLAG_REMOTE_WAKEUP 0x40
|
||||||
|
#define FLAG_EJECT 0x80
|
||||||
|
|
||||||
|
extern bool cap_supported(uint16_t cap);
|
||||||
|
extern int man_get_config();
|
||||||
|
|
||||||
|
#endif //_MANAGEMENT_H
|
||||||
@@ -15,15 +15,18 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#ifdef ESP_PLATFORM
|
||||||
|
#include "esp_compat.h"
|
||||||
|
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||||
|
#else
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
#endif
|
||||||
#include "openpgp.h"
|
#include "openpgp.h"
|
||||||
#include "version.h"
|
#include "version.h"
|
||||||
#include "files.h"
|
#include "files.h"
|
||||||
#include "random.h"
|
#include "random.h"
|
||||||
#include "eac.h"
|
#include "eac.h"
|
||||||
#include "crypto_utils.h"
|
#include "crypto_utils.h"
|
||||||
#include "mbedtls/rsa.h"
|
|
||||||
#include "mbedtls/ecdsa.h"
|
|
||||||
#include "mbedtls/ecdh.h"
|
#include "mbedtls/ecdh.h"
|
||||||
#include "mbedtls/asn1.h"
|
#include "mbedtls/asn1.h"
|
||||||
#include "asn1.h"
|
#include "asn1.h"
|
||||||
@@ -61,7 +64,6 @@ char atr_openpgp[] = {
|
|||||||
|
|
||||||
int openpgp_process_apdu();
|
int openpgp_process_apdu();
|
||||||
|
|
||||||
|
|
||||||
extern uint32_t board_button_read(void);
|
extern uint32_t board_button_read(void);
|
||||||
|
|
||||||
static bool wait_button_pressed(uint16_t fid) {
|
static bool wait_button_pressed(uint16_t fid) {
|
||||||
@@ -169,58 +171,9 @@ void scan_files() {
|
|||||||
file_t *ef;
|
file_t *ef;
|
||||||
if ((ef = search_by_fid(EF_FULL_AID, NULL, SPECIFY_ANY))) {
|
if ((ef = search_by_fid(EF_FULL_AID, NULL, SPECIFY_ANY))) {
|
||||||
ef->data = openpgp_aid_full;
|
ef->data = openpgp_aid_full;
|
||||||
#ifndef ENABLE_EMULATION
|
memcpy(ef->data + 12, pico_serial.id, 4);
|
||||||
pico_get_unique_board_id_string((char *) ef->data + 12, 4);
|
|
||||||
#else
|
|
||||||
memset((char *) ef->data + 12, 0, 4);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
if ((ef = search_by_fid(EF_PW1, NULL, SPECIFY_ANY))) {
|
|
||||||
if (!ef->data) {
|
|
||||||
printf("PW1 is empty. Initializing with default password\r\n");
|
|
||||||
const uint8_t def[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
|
|
||||||
uint8_t dhash[33];
|
|
||||||
dhash[0] = sizeof(def);
|
|
||||||
double_hash_pin(def, sizeof(def), dhash + 1);
|
|
||||||
flash_write_data_to_file(ef, dhash, sizeof(dhash));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((ef = search_by_fid(EF_RC, NULL, SPECIFY_ANY))) {
|
|
||||||
if (!ef->data) {
|
|
||||||
printf("RC is empty. Initializing with default password\r\n");
|
|
||||||
|
|
||||||
const uint8_t def[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
|
|
||||||
uint8_t dhash[33];
|
|
||||||
dhash[0] = sizeof(def);
|
|
||||||
double_hash_pin(def, sizeof(def), dhash + 1);
|
|
||||||
flash_write_data_to_file(ef, dhash, sizeof(dhash));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((ef = search_by_fid(EF_PW3, NULL, SPECIFY_ANY))) {
|
|
||||||
if (!ef->data) {
|
|
||||||
printf("PW3 is empty. Initializing with default password\r\n");
|
|
||||||
|
|
||||||
const uint8_t def[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
|
|
||||||
uint8_t dhash[33];
|
|
||||||
dhash[0] = sizeof(def);
|
|
||||||
double_hash_pin(def, sizeof(def), dhash + 1);
|
|
||||||
flash_write_data_to_file(ef, dhash, sizeof(dhash));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY))) {
|
|
||||||
if (!ef->data) {
|
|
||||||
printf("SigCount is empty. Initializing to zero\r\n");
|
|
||||||
const uint8_t def[3] = { 0 };
|
|
||||||
flash_write_data_to_file(ef, def, sizeof(def));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ((ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY))) {
|
|
||||||
if (!ef->data) {
|
|
||||||
printf("PW status is empty. Initializing to default\r\n");
|
|
||||||
const uint8_t def[] = { 0x1, 127, 127, 127, 3, 3, 3 };
|
|
||||||
flash_write_data_to_file(ef, def, sizeof(def));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
bool reset_dek = false;
|
||||||
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY))) {
|
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY))) {
|
||||||
if (!ef->data) {
|
if (!ef->data) {
|
||||||
printf("DEK is empty\r\n");
|
printf("DEK is empty\r\n");
|
||||||
@@ -240,50 +193,105 @@ void scan_files() {
|
|||||||
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32, 32);
|
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32, 32);
|
||||||
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
|
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
|
||||||
memset(session_pw3, 0, sizeof(session_pw3));
|
memset(session_pw3, 0, sizeof(session_pw3));
|
||||||
flash_write_data_to_file(ef, def, sizeof(def));
|
file_put_data(ef, def, sizeof(def));
|
||||||
|
reset_dek = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ef = search_by_fid(EF_PW1, NULL, SPECIFY_ANY))) {
|
||||||
|
if (!ef->data || reset_dek) {
|
||||||
|
printf("PW1 is empty. Initializing with default password\r\n");
|
||||||
|
const uint8_t def[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
|
||||||
|
uint8_t dhash[33];
|
||||||
|
dhash[0] = sizeof(def);
|
||||||
|
double_hash_pin(def, sizeof(def), dhash + 1);
|
||||||
|
file_put_data(ef, dhash, sizeof(dhash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ef = search_by_fid(EF_RC, NULL, SPECIFY_ANY))) {
|
||||||
|
if (!ef->data || reset_dek) {
|
||||||
|
printf("RC is empty. Initializing with default password\r\n");
|
||||||
|
|
||||||
|
const uint8_t def[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
|
||||||
|
uint8_t dhash[33];
|
||||||
|
dhash[0] = sizeof(def);
|
||||||
|
double_hash_pin(def, sizeof(def), dhash + 1);
|
||||||
|
file_put_data(ef, dhash, sizeof(dhash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ef = search_by_fid(EF_PW3, NULL, SPECIFY_ANY))) {
|
||||||
|
if (!ef->data || reset_dek) {
|
||||||
|
printf("PW3 is empty. Initializing with default password\r\n");
|
||||||
|
|
||||||
|
const uint8_t def[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
|
||||||
|
uint8_t dhash[33];
|
||||||
|
dhash[0] = sizeof(def);
|
||||||
|
double_hash_pin(def, sizeof(def), dhash + 1);
|
||||||
|
file_put_data(ef, dhash, sizeof(dhash));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY))) {
|
||||||
|
if (!ef->data) {
|
||||||
|
printf("SigCount is empty. Initializing to zero\r\n");
|
||||||
|
const uint8_t def[3] = { 0 };
|
||||||
|
file_put_data(ef, def, sizeof(def));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY))) {
|
||||||
|
if (!ef->data) {
|
||||||
|
printf("PW status is empty. Initializing to default\r\n");
|
||||||
|
const uint8_t def[] = { 0x1, 127, 127, 127, 3, 3, 3 };
|
||||||
|
file_put_data(ef, def, sizeof(def));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ef = search_by_fid(EF_UIF_SIG, NULL, SPECIFY_ANY))) {
|
if ((ef = search_by_fid(EF_UIF_SIG, NULL, SPECIFY_ANY))) {
|
||||||
if (!ef->data) {
|
if (!ef->data) {
|
||||||
printf("UIF SIG is empty. Initializing to default\r\n");
|
printf("UIF SIG is empty. Initializing to default\r\n");
|
||||||
const uint8_t def[] = { 0x0, 0x20 };
|
const uint8_t def[] = { 0x0, 0x20 };
|
||||||
flash_write_data_to_file(ef, def, sizeof(def));
|
file_put_data(ef, def, sizeof(def));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ef = search_by_fid(EF_UIF_DEC, NULL, SPECIFY_ANY))) {
|
if ((ef = search_by_fid(EF_UIF_DEC, NULL, SPECIFY_ANY))) {
|
||||||
if (!ef->data) {
|
if (!ef->data) {
|
||||||
printf("UIF DEC is empty. Initializing to default\r\n");
|
printf("UIF DEC is empty. Initializing to default\r\n");
|
||||||
const uint8_t def[] = { 0x0, 0x20 };
|
const uint8_t def[] = { 0x0, 0x20 };
|
||||||
flash_write_data_to_file(ef, def, sizeof(def));
|
file_put_data(ef, def, sizeof(def));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ef = search_by_fid(EF_UIF_AUT, NULL, SPECIFY_ANY))) {
|
if ((ef = search_by_fid(EF_UIF_AUT, NULL, SPECIFY_ANY))) {
|
||||||
if (!ef->data) {
|
if (!ef->data) {
|
||||||
printf("UIF AUT is empty. Initializing to default\r\n");
|
printf("UIF AUT is empty. Initializing to default\r\n");
|
||||||
const uint8_t def[] = { 0x0, 0x20 };
|
const uint8_t def[] = { 0x0, 0x20 };
|
||||||
flash_write_data_to_file(ef, def, sizeof(def));
|
file_put_data(ef, def, sizeof(def));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((ef = search_by_fid(EF_KDF, NULL, SPECIFY_ANY))) {
|
if ((ef = search_by_fid(EF_KDF, NULL, SPECIFY_ANY))) {
|
||||||
if (!ef->data) {
|
if (!ef->data) {
|
||||||
printf("KDF is empty. Initializing to default\r\n");
|
printf("KDF is empty. Initializing to default\r\n");
|
||||||
const uint8_t def[] = { 0x81, 0x1, 0x0 };
|
const uint8_t def[] = { 0x81, 0x1, 0x0 };
|
||||||
flash_write_data_to_file(ef, def, sizeof(def));
|
file_put_data(ef, def, sizeof(def));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((ef = search_by_fid(EF_SEX, NULL, SPECIFY_ANY))) {
|
if ((ef = search_by_fid(EF_SEX, NULL, SPECIFY_ANY))) {
|
||||||
if (!ef->data) {
|
if (!ef->data) {
|
||||||
printf("Sex is empty. Initializing to default\r\n");
|
printf("Sex is empty. Initializing to default\r\n");
|
||||||
const uint8_t def[] = { 0x30 };
|
const uint8_t def[] = { 0x30 };
|
||||||
flash_write_data_to_file(ef, def, sizeof(def));
|
file_put_data(ef, def, sizeof(def));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((ef = search_by_fid(EF_PW_RETRIES, NULL, SPECIFY_ANY))) {
|
||||||
|
if (!ef->data) {
|
||||||
|
printf("PW retries is empty. Initializing to default\r\n");
|
||||||
|
const uint8_t def[] = { 0x1, 3, 3, 3 };
|
||||||
|
file_put_data(ef, def, sizeof(def));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extern bool has_pwpiv;
|
||||||
|
extern uint8_t session_pwpiv[32];
|
||||||
int load_dek() {
|
int load_dek() {
|
||||||
if (!has_pw1 && !has_pw2 && !has_pw3) {
|
if (!has_pw1 && !has_pw2 && !has_pw3 && !has_pwpiv) {
|
||||||
return CCID_NO_LOGIN;
|
return CCID_NO_LOGIN;
|
||||||
}
|
}
|
||||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||||
@@ -300,6 +308,11 @@ int load_dek() {
|
|||||||
memcpy(dek + IV_SIZE, file_get_data(tf) + IV_SIZE + 32 + 32, 32);
|
memcpy(dek + IV_SIZE, file_get_data(tf) + IV_SIZE + 32 + 32, 32);
|
||||||
r = aes_decrypt_cfb_256(session_pw3, dek, dek + IV_SIZE, 32);
|
r = aes_decrypt_cfb_256(session_pw3, dek, dek + IV_SIZE, 32);
|
||||||
}
|
}
|
||||||
|
else if (has_pwpiv) {
|
||||||
|
memcpy(dek, file_get_data(tf), IV_SIZE);
|
||||||
|
memcpy(dek + IV_SIZE, file_get_data(tf) + IV_SIZE + 32 + 32 + 32, 32);
|
||||||
|
r = aes_decrypt_cfb_256(session_pwpiv, dek, dek + IV_SIZE, 32);
|
||||||
|
}
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
@@ -353,7 +366,7 @@ int openpgp_unload() {
|
|||||||
|
|
||||||
extern char __StackLimit;
|
extern char __StackLimit;
|
||||||
int heapLeft() {
|
int heapLeft() {
|
||||||
#ifndef ENABLE_EMULATION
|
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
|
||||||
char *p = malloc(256); // try to avoid undue fragmentation
|
char *p = malloc(256); // try to avoid undue fragmentation
|
||||||
int left = &__StackLimit - p;
|
int left = &__StackLimit - p;
|
||||||
free(p);
|
free(p);
|
||||||
@@ -363,30 +376,27 @@ int heapLeft() {
|
|||||||
return left;
|
return left;
|
||||||
}
|
}
|
||||||
|
|
||||||
app_t *openpgp_select_aid(app_t *a, const uint8_t *aid, uint8_t aid_len) {
|
int openpgp_select_aid(app_t *a, uint8_t force) {
|
||||||
if (!memcmp(aid, openpgp_aid + 1, MIN(aid_len, openpgp_aid[0]))) {
|
(void) force;
|
||||||
a->aid = openpgp_aid;
|
a->process_apdu = openpgp_process_apdu;
|
||||||
a->process_apdu = openpgp_process_apdu;
|
a->unload = openpgp_unload;
|
||||||
a->unload = openpgp_unload;
|
init_openpgp();
|
||||||
init_openpgp();
|
process_fci(file_openpgp, 1);
|
||||||
process_fci(file_openpgp, 1);
|
memcpy(res_APDU + res_APDU_size, "\x64\x06\x53\x04", 4);
|
||||||
memcpy(res_APDU + res_APDU_size, "\x64\x06\x53\x04", 4);
|
res_APDU_size += 4;
|
||||||
res_APDU_size += 4;
|
int heap_left = heapLeft();
|
||||||
int heap_left = heapLeft();
|
res_APDU[res_APDU_size++] = ((heap_left >> 24) & 0xff);
|
||||||
res_APDU[res_APDU_size++] = ((heap_left >> 24) & 0xff);
|
res_APDU[res_APDU_size++] = ((heap_left >> 16) & 0xff);
|
||||||
res_APDU[res_APDU_size++] = ((heap_left >> 16) & 0xff);
|
res_APDU[res_APDU_size++] = ((heap_left >> 8) & 0xff);
|
||||||
res_APDU[res_APDU_size++] = ((heap_left >> 8) & 0xff);
|
res_APDU[res_APDU_size++] = ((heap_left >> 0) & 0xff);
|
||||||
res_APDU[res_APDU_size++] = ((heap_left >> 0) & 0xff);
|
res_APDU[1] += 8;
|
||||||
res_APDU[1] += 8;
|
apdu.ne = res_APDU_size;
|
||||||
apdu.ne = res_APDU_size;
|
return CCID_OK;
|
||||||
return a;
|
|
||||||
}
|
|
||||||
return NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void __attribute__((constructor)) openpgp_ctor() {
|
INITIALIZER( openpgp_ctor ) {
|
||||||
ccid_atr = (uint8_t *) atr_openpgp;
|
ccid_atr = (uint8_t *) atr_openpgp;
|
||||||
register_app(openpgp_select_aid);
|
register_app(openpgp_select_aid, openpgp_aid);
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_do(uint16_t *fids, int mode) {
|
int parse_do(uint16_t *fids, int mode) {
|
||||||
@@ -465,7 +475,7 @@ int inc_sig_count() {
|
|||||||
if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF)) || !pw_status->data) {
|
if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF)) || !pw_status->data) {
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
if (file_get_data(pw_status)[0] == 1) {
|
if (file_get_data(pw_status)[0] == 0) {
|
||||||
has_pw1 = false;
|
has_pw1 = false;
|
||||||
}
|
}
|
||||||
file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY);
|
file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY);
|
||||||
@@ -476,7 +486,7 @@ int inc_sig_count() {
|
|||||||
uint32_t counter = (p[0] << 16) | (p[1] << 8) | p[2];
|
uint32_t counter = (p[0] << 16) | (p[1] << 8) | p[2];
|
||||||
counter++;
|
counter++;
|
||||||
uint8_t q[3] = { (counter >> 16) & 0xff, (counter >> 8) & 0xff, counter & 0xff };
|
uint8_t q[3] = { (counter >> 16) & 0xff, (counter >> 8) & 0xff, counter & 0xff };
|
||||||
int r = flash_write_data_to_file(ef, q, sizeof(q));
|
int r = file_put_data(ef, q, sizeof(q));
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
@@ -490,7 +500,7 @@ int reset_sig_count() {
|
|||||||
return CCID_ERR_FILE_NOT_FOUND;
|
return CCID_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
uint8_t q[3] = { 0 };
|
uint8_t q[3] = { 0 };
|
||||||
int r = flash_write_data_to_file(ef, q, sizeof(q));
|
int r = file_put_data(ef, q, sizeof(q));
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
@@ -583,15 +593,6 @@ int parse_pw_status(const file_t *f, int mode) {
|
|||||||
return res_APDU_size - init_len;
|
return res_APDU_size - init_len;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ALGO_RSA 0x01
|
|
||||||
#define ALGO_ECDH 0x12
|
|
||||||
#define ALGO_ECDSA 0x13
|
|
||||||
#define ALGO_EDDSA 0x16
|
|
||||||
#define ALGO_AES 0x70
|
|
||||||
#define ALGO_AES_128 0x71
|
|
||||||
#define ALGO_AES_192 0x72
|
|
||||||
#define ALGO_AES_256 0x74
|
|
||||||
|
|
||||||
#define ALGO_RSA_1K 0
|
#define ALGO_RSA_1K 0
|
||||||
#define ALGO_RSA_2k 1
|
#define ALGO_RSA_2k 1
|
||||||
#define ALGO_RSA_3K 2
|
#define ALGO_RSA_3K 2
|
||||||
@@ -834,8 +835,10 @@ static int cmd_get_data() {
|
|||||||
uint16_t data_len = parse_do(fids, 1);
|
uint16_t data_len = parse_do(fids, 1);
|
||||||
uint8_t *p = NULL;
|
uint8_t *p = NULL;
|
||||||
uint16_t tg = 0;
|
uint16_t tg = 0;
|
||||||
size_t tg_len = 0;
|
uint16_t tg_len = 0;
|
||||||
if (walk_tlv(res_APDU, data_len, &p, &tg, &tg_len, NULL)) {
|
asn1_ctx_t ctxi;
|
||||||
|
asn1_ctx_init(res_APDU, data_len, &ctxi);
|
||||||
|
if (walk_tlv(&ctxi, &p, &tg, &tg_len, NULL)) {
|
||||||
uint8_t dec = 2;
|
uint8_t dec = 2;
|
||||||
if ((tg & 0x1f) == 0x1f) {
|
if ((tg & 0x1f) == 0x1f) {
|
||||||
dec++;
|
dec++;
|
||||||
@@ -860,17 +863,22 @@ int pin_reset_retries(const file_t *pin, bool force) {
|
|||||||
return CCID_ERR_NULL_PARAM;
|
return CCID_ERR_NULL_PARAM;
|
||||||
}
|
}
|
||||||
file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
|
file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
|
||||||
if (!pw_status) {
|
file_t *pw_retries = search_by_fid(EF_PW_RETRIES, NULL, SPECIFY_EF);
|
||||||
|
if (!pw_status || !pw_retries) {
|
||||||
return CCID_ERR_FILE_NOT_FOUND;
|
return CCID_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
uint8_t p[7];
|
if (3 + (pin->fid & 0xf) >= file_get_size(pw_status) || (pin->fid & 0xf) >= file_get_size(pw_retries)) {
|
||||||
memcpy(p, file_get_data(pw_status), 7);
|
return CCID_ERR_MEMORY_FATAL;
|
||||||
uint8_t retries = p[3 + (pin->fid & 0x3)];
|
}
|
||||||
|
uint8_t p[64];
|
||||||
|
memcpy(p, file_get_data(pw_status), file_get_size(pw_status));
|
||||||
|
uint8_t retries = p[3 + (pin->fid & 0xf)];
|
||||||
if (retries == 0 && force == false) { //blocked
|
if (retries == 0 && force == false) { //blocked
|
||||||
return CCID_ERR_BLOCKED;
|
return CCID_ERR_BLOCKED;
|
||||||
}
|
}
|
||||||
p[3 + (pin->fid & 0x3)] = 3;
|
uint8_t max_retries = file_get_data(pw_retries)[(pin->fid & 0xf)];
|
||||||
int r = flash_write_data_to_file(pw_status, p, file_get_size(pw_status));
|
p[3 + (pin->fid & 0xf)] = max_retries;
|
||||||
|
int r = file_put_data(pw_status, p, file_get_size(pw_status));
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -883,19 +891,19 @@ int pin_wrong_retry(const file_t *pin) {
|
|||||||
if (!pw_status) {
|
if (!pw_status) {
|
||||||
return CCID_ERR_FILE_NOT_FOUND;
|
return CCID_ERR_FILE_NOT_FOUND;
|
||||||
}
|
}
|
||||||
uint8_t p[7];
|
uint8_t p[64];
|
||||||
memcpy(p, file_get_data(pw_status), 7);
|
memcpy(p, file_get_data(pw_status), file_get_size(pw_status));
|
||||||
if (p[3 + (pin->fid & 0x3)] > 0) {
|
if (p[3 + (pin->fid & 0xf)] > 0) {
|
||||||
p[3 + (pin->fid & 0x3)] -= 1;
|
p[3 + (pin->fid & 0xf)] -= 1;
|
||||||
int r = flash_write_data_to_file(pw_status, p, file_get_size(pw_status));
|
int r = file_put_data(pw_status, p, file_get_size(pw_status));
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
if (p[3 + (pin->fid & 0x3)] == 0) {
|
if (p[3 + (pin->fid & 0xf)] == 0) {
|
||||||
return CCID_ERR_BLOCKED;
|
return CCID_ERR_BLOCKED;
|
||||||
}
|
}
|
||||||
return p[3 + (pin->fid & 0x3)];
|
return p[3 + (pin->fid & 0xf)];
|
||||||
}
|
}
|
||||||
return CCID_ERR_BLOCKED;
|
return CCID_ERR_BLOCKED;
|
||||||
}
|
}
|
||||||
@@ -986,7 +994,7 @@ static int cmd_verify() {
|
|||||||
if (apdu.nc > 0) {
|
if (apdu.nc > 0) {
|
||||||
return check_pin(pw, apdu.data, apdu.nc);
|
return check_pin(pw, apdu.data, apdu.nc);
|
||||||
}
|
}
|
||||||
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0x3));
|
uint8_t retries = *(file_get_data(pw_status) + 3 + (fid & 0xf));
|
||||||
if (retries == 0) {
|
if (retries == 0) {
|
||||||
return SW_PIN_BLOCKED();
|
return SW_PIN_BLOCKED();
|
||||||
}
|
}
|
||||||
@@ -1028,21 +1036,21 @@ static int cmd_put_data() {
|
|||||||
uint8_t dhash[33];
|
uint8_t dhash[33];
|
||||||
dhash[0] = apdu.nc;
|
dhash[0] = apdu.nc;
|
||||||
double_hash_pin(apdu.data, apdu.nc, dhash + 1);
|
double_hash_pin(apdu.data, apdu.nc, dhash + 1);
|
||||||
r = flash_write_data_to_file(ef, dhash, sizeof(dhash));
|
r = file_put_data(ef, dhash, sizeof(dhash));
|
||||||
|
|
||||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||||
if (!tf) {
|
if (!tf) {
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
uint8_t def[IV_SIZE + 32 + 32 + 32];
|
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
|
||||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||||
hash_multi(apdu.data, apdu.nc, session_rc);
|
hash_multi(apdu.data, apdu.nc, session_rc);
|
||||||
memcpy(def + IV_SIZE + 32, dek + IV_SIZE, 32);
|
memcpy(def + IV_SIZE + 32, dek + IV_SIZE, 32);
|
||||||
aes_encrypt_cfb_256(session_rc, def, def + IV_SIZE + 32, 32);
|
aes_encrypt_cfb_256(session_rc, def, def + IV_SIZE + 32, 32);
|
||||||
r = flash_write_data_to_file(tf, def, sizeof(def));
|
r = file_put_data(tf, def, sizeof(def));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
r = flash_write_data_to_file(ef, apdu.data, apdu.nc);
|
r = file_put_data(ef, apdu.data, apdu.nc);
|
||||||
}
|
}
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
@@ -1073,13 +1081,13 @@ static int cmd_change_pin() {
|
|||||||
uint8_t dhash[33];
|
uint8_t dhash[33];
|
||||||
dhash[0] = apdu.nc - pin_len;
|
dhash[0] = apdu.nc - pin_len;
|
||||||
double_hash_pin(apdu.data + pin_len, apdu.nc - pin_len, dhash + 1);
|
double_hash_pin(apdu.data + pin_len, apdu.nc - pin_len, dhash + 1);
|
||||||
flash_write_data_to_file(pw, dhash, sizeof(dhash));
|
file_put_data(pw, dhash, sizeof(dhash));
|
||||||
|
|
||||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||||
if (!tf) {
|
if (!tf) {
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
uint8_t def[IV_SIZE + 32 + 32 + 32];
|
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32] = {0};
|
||||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||||
if (P2(apdu) == 0x81) {
|
if (P2(apdu) == 0x81) {
|
||||||
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw1);
|
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw1);
|
||||||
@@ -1091,7 +1099,7 @@ static int cmd_change_pin() {
|
|||||||
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
|
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
|
||||||
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
|
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
|
||||||
}
|
}
|
||||||
flash_write_data_to_file(tf, def, sizeof(def));
|
file_put_data(tf, def, sizeof(def));
|
||||||
low_flash_available();
|
low_flash_available();
|
||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
@@ -1138,17 +1146,17 @@ static int cmd_reset_retry() {
|
|||||||
if (!tf) {
|
if (!tf) {
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
uint8_t def[IV_SIZE + 32 + 32 + 32];
|
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
|
||||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||||
hash_multi(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pw1);
|
hash_multi(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pw1);
|
||||||
memcpy(def + IV_SIZE, dek + IV_SIZE, 32);
|
memcpy(def + IV_SIZE, dek + IV_SIZE, 32);
|
||||||
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
|
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
|
||||||
r = flash_write_data_to_file(tf, def, sizeof(def));
|
r = file_put_data(tf, def, sizeof(def));
|
||||||
|
|
||||||
uint8_t dhash[33];
|
uint8_t dhash[33];
|
||||||
dhash[0] = newpin_len;
|
dhash[0] = newpin_len;
|
||||||
double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1);
|
double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1);
|
||||||
flash_write_data_to_file(pw, dhash, sizeof(dhash));
|
file_put_data(pw, dhash, sizeof(dhash));
|
||||||
if (pin_reset_retries(pw, true) != CCID_OK) {
|
if (pin_reset_retries(pw, true) != CCID_OK) {
|
||||||
return SW_MEMORY_FAILURE();
|
return SW_MEMORY_FAILURE();
|
||||||
}
|
}
|
||||||
@@ -1158,7 +1166,7 @@ static int cmd_reset_retry() {
|
|||||||
return SW_INCORRECT_P1P2();
|
return SW_INCORRECT_P1P2();
|
||||||
}
|
}
|
||||||
|
|
||||||
int store_keys(void *key_ctx, int type, uint16_t key_id) {
|
int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek) {
|
||||||
int r, key_size = 0;
|
int r, key_size = 0;
|
||||||
uint8_t kdata[4096 / 8]; //worst
|
uint8_t kdata[4096 / 8]; //worst
|
||||||
|
|
||||||
@@ -1179,10 +1187,10 @@ int store_keys(void *key_ctx, int type, uint16_t key_id) {
|
|||||||
}
|
}
|
||||||
else if (type == ALGO_ECDSA || type == ALGO_ECDH || type == ALGO_EDDSA) {
|
else if (type == ALGO_ECDSA || type == ALGO_ECDH || type == ALGO_EDDSA) {
|
||||||
mbedtls_ecp_keypair *ecdsa = (mbedtls_ecp_keypair *) key_ctx;
|
mbedtls_ecp_keypair *ecdsa = (mbedtls_ecp_keypair *) key_ctx;
|
||||||
key_size = mbedtls_mpi_size(&ecdsa->d);
|
size_t olen = 0;
|
||||||
kdata[0] = ecdsa->grp.id & 0xff;
|
kdata[0] = ecdsa->grp.id & 0xff;
|
||||||
mbedtls_ecp_write_key(ecdsa, kdata + 1, key_size);
|
mbedtls_ecp_write_key_ext(ecdsa, &olen, kdata + 1, sizeof(kdata) - 1);
|
||||||
key_size++;
|
key_size = olen + 1;
|
||||||
}
|
}
|
||||||
else if (type & ALGO_AES) {
|
else if (type & ALGO_AES) {
|
||||||
if (type == ALGO_AES_128) {
|
if (type == ALGO_AES_128) {
|
||||||
@@ -1196,14 +1204,16 @@ int store_keys(void *key_ctx, int type, uint16_t key_id) {
|
|||||||
}
|
}
|
||||||
memcpy(kdata, key_ctx, key_size);
|
memcpy(kdata, key_ctx, key_size);
|
||||||
}
|
}
|
||||||
r = dek_encrypt(kdata, key_size);
|
if (use_kek) {
|
||||||
if (r != CCID_OK) {
|
r = dek_encrypt(kdata, key_size);
|
||||||
return r;
|
if (r != CCID_OK) {
|
||||||
|
return r;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//r = aes_encrypt_cfb_256(file_read(pw3->data+2), session_pw3, kdata, key_size);
|
//r = aes_encrypt_cfb_256(file_read(pw3->data+2), session_pw3, kdata, key_size);
|
||||||
//if (r != CCID_OK)
|
//if (r != CCID_OK)
|
||||||
// return r;
|
// return r;
|
||||||
r = flash_write_data_to_file(ef, kdata, key_size);
|
r = file_put_data(ef, kdata, key_size);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@@ -1211,11 +1221,11 @@ int store_keys(void *key_ctx, int type, uint16_t key_id) {
|
|||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek) {
|
||||||
int key_size = file_get_size(fkey);
|
int key_size = file_get_size(fkey);
|
||||||
uint8_t kdata[4096 / 8];
|
uint8_t kdata[4096 / 8];
|
||||||
memcpy(kdata, file_get_data(fkey), key_size);
|
memcpy(kdata, file_get_data(fkey), key_size);
|
||||||
if (dek_decrypt(kdata, key_size) != 0) {
|
if (use_dek && dek_decrypt(kdata, key_size) != 0) {
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) {
|
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) {
|
||||||
@@ -1245,11 +1255,11 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
|
|||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int load_private_key_ecdsa(mbedtls_ecp_keypair *ctx, file_t *fkey) {
|
int load_private_key_ecdsa(mbedtls_ecp_keypair *ctx, file_t *fkey, bool use_dek) {
|
||||||
int key_size = file_get_size(fkey);
|
int key_size = file_get_size(fkey);
|
||||||
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
|
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
|
||||||
memcpy(kdata, file_get_data(fkey), key_size);
|
memcpy(kdata, file_get_data(fkey), key_size);
|
||||||
if (dek_decrypt(kdata, key_size) != 0) {
|
if (use_dek && dek_decrypt(kdata, key_size) != 0) {
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
mbedtls_ecp_group_id gid = kdata[0];
|
mbedtls_ecp_group_id gid = kdata[0];
|
||||||
@@ -1258,6 +1268,17 @@ int load_private_key_ecdsa(mbedtls_ecp_keypair *ctx, file_t *fkey) {
|
|||||||
mbedtls_ecp_keypair_free(ctx);
|
mbedtls_ecp_keypair_free(ctx);
|
||||||
return CCID_EXEC_ERROR;
|
return CCID_EXEC_ERROR;
|
||||||
}
|
}
|
||||||
|
mbedtls_platform_zeroize(kdata, sizeof(kdata));
|
||||||
|
if (ctx->grp.id == MBEDTLS_ECP_DP_ED25519) {
|
||||||
|
r = mbedtls_ecp_point_edwards(&ctx->grp, &ctx->Q, &ctx->d, random_gen, NULL);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
r = mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL);
|
||||||
|
}
|
||||||
|
if (r != 0) {
|
||||||
|
mbedtls_ecdsa_free(ctx);
|
||||||
|
return CCID_EXEC_ERROR;
|
||||||
|
}
|
||||||
return CCID_OK;
|
return CCID_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1393,7 +1414,7 @@ static int cmd_keypair_gen() {
|
|||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = store_keys(&rsa, ALGO_RSA, fid);
|
r = store_keys(&rsa, ALGO_RSA, fid, true);
|
||||||
make_rsa_response(&rsa);
|
make_rsa_response(&rsa);
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
@@ -1414,7 +1435,7 @@ static int cmd_keypair_gen() {
|
|||||||
mbedtls_ecp_keypair_free(&ecdsa);
|
mbedtls_ecp_keypair_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = store_keys(&ecdsa, algo[0], fid);
|
r = store_keys(&ecdsa, algo[0], fid, true);
|
||||||
make_ecdsa_response(&ecdsa);
|
make_ecdsa_response(&ecdsa);
|
||||||
mbedtls_ecp_keypair_free(&ecdsa);
|
mbedtls_ecp_keypair_free(&ecdsa);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
@@ -1428,7 +1449,7 @@ static int cmd_keypair_gen() {
|
|||||||
if (!pbef) {
|
if (!pbef) {
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
r = flash_write_data_to_file(pbef, res_APDU, res_APDU_size);
|
r = file_put_data(pbef, res_APDU, res_APDU_size);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
@@ -1441,7 +1462,7 @@ static int cmd_keypair_gen() {
|
|||||||
uint8_t aes_key[32]; //maximum AES key size
|
uint8_t aes_key[32]; //maximum AES key size
|
||||||
uint8_t key_size = 32;
|
uint8_t key_size = 32;
|
||||||
memcpy(aes_key, random_bytes_get(key_size), key_size);
|
memcpy(aes_key, random_bytes_get(key_size), key_size);
|
||||||
r = store_keys(aes_key, ALGO_AES_256, EF_AES_KEY);
|
r = store_keys(aes_key, ALGO_AES_256, EF_AES_KEY, true);
|
||||||
/* if storing the key fails, we silently continue */
|
/* if storing the key fails, we silently continue */
|
||||||
//if (r != CCID_OK)
|
//if (r != CCID_OK)
|
||||||
// return SW_EXEC_ERROR();
|
// return SW_EXEC_ERROR();
|
||||||
@@ -1469,7 +1490,7 @@ int rsa_sign(mbedtls_rsa_context *ctx,
|
|||||||
uint8_t *d = (uint8_t *) data, *end = d + data_len, *hsh = NULL;
|
uint8_t *d = (uint8_t *) data, *end = d + data_len, *hsh = NULL;
|
||||||
size_t seq_len = 0, hash_len = 0;
|
size_t seq_len = 0, hash_len = 0;
|
||||||
int key_size = ctx->len, r = 0;
|
int key_size = ctx->len, r = 0;
|
||||||
mbedtls_md_type_t md = MBEDTLS_MD_SHA256;
|
mbedtls_md_type_t md = MBEDTLS_MD_NONE;
|
||||||
if (mbedtls_asn1_get_tag(&d, end, &seq_len,
|
if (mbedtls_asn1_get_tag(&d, end, &seq_len,
|
||||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0) {
|
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0) {
|
||||||
mbedtls_asn1_buf mdb;
|
mbedtls_asn1_buf mdb;
|
||||||
@@ -1609,7 +1630,7 @@ static int cmd_pso() {
|
|||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
if (P1(apdu) == 0x80 && P2(apdu) == 0x86) { //decipher
|
if (P1(apdu) == 0x80 && P2(apdu) == 0x86) { //decipher
|
||||||
r = aes_decrypt(aes_key, NULL, key_size, HSM_AES_MODE_CBC, apdu.data + 1, apdu.nc - 1);
|
r = aes_decrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data + 1, apdu.nc - 1);
|
||||||
memset(aes_key, 0, sizeof(aes_key));
|
memset(aes_key, 0, sizeof(aes_key));
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1618,7 +1639,7 @@ static int cmd_pso() {
|
|||||||
res_APDU_size = apdu.nc - 1;
|
res_APDU_size = apdu.nc - 1;
|
||||||
}
|
}
|
||||||
else if (P1(apdu) == 0x86 && P2(apdu) == 0x80) { //encipher
|
else if (P1(apdu) == 0x86 && P2(apdu) == 0x80) { //encipher
|
||||||
r = aes_encrypt(aes_key, NULL, key_size, HSM_AES_MODE_CBC, apdu.data, apdu.nc);
|
r = aes_encrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data, apdu.nc);
|
||||||
memset(aes_key, 0, sizeof(aes_key));
|
memset(aes_key, 0, sizeof(aes_key));
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1632,7 +1653,7 @@ static int cmd_pso() {
|
|||||||
if (algo[0] == ALGO_RSA) {
|
if (algo[0] == ALGO_RSA) {
|
||||||
mbedtls_rsa_context ctx;
|
mbedtls_rsa_context ctx;
|
||||||
mbedtls_rsa_init(&ctx);
|
mbedtls_rsa_init(&ctx);
|
||||||
r = load_private_key_rsa(&ctx, ef);
|
r = load_private_key_rsa(&ctx, ef, true);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1671,7 +1692,7 @@ static int cmd_pso() {
|
|||||||
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
|
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
|
||||||
mbedtls_ecp_keypair ctx;
|
mbedtls_ecp_keypair ctx;
|
||||||
mbedtls_ecp_keypair_init(&ctx);
|
mbedtls_ecp_keypair_init(&ctx);
|
||||||
r = load_private_key_ecdsa(&ctx, ef);
|
r = load_private_key_ecdsa(&ctx, ef, true);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1801,7 +1822,7 @@ static int cmd_internal_aut() {
|
|||||||
if (algo[0] == ALGO_RSA) {
|
if (algo[0] == ALGO_RSA) {
|
||||||
mbedtls_rsa_context ctx;
|
mbedtls_rsa_context ctx;
|
||||||
mbedtls_rsa_init(&ctx);
|
mbedtls_rsa_init(&ctx);
|
||||||
r = load_private_key_rsa(&ctx, ef);
|
r = load_private_key_rsa(&ctx, ef, true);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
mbedtls_rsa_free(&ctx);
|
mbedtls_rsa_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1817,7 +1838,7 @@ static int cmd_internal_aut() {
|
|||||||
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) {
|
else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) {
|
||||||
mbedtls_ecp_keypair ctx;
|
mbedtls_ecp_keypair ctx;
|
||||||
mbedtls_ecp_keypair_init(&ctx);
|
mbedtls_ecp_keypair_init(&ctx);
|
||||||
r = load_private_key_ecdsa(&ctx, ef);
|
r = load_private_key_ecdsa(&ctx, ef, true);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
mbedtls_ecp_keypair_free(&ctx);
|
mbedtls_ecp_keypair_free(&ctx);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
@@ -1864,7 +1885,7 @@ static int cmd_mse() {
|
|||||||
return SW_OK();
|
return SW_OK();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t tag_len(uint8_t **data) {
|
uint16_t tag_len(uint8_t **data) {
|
||||||
size_t len = *(*data)++;
|
size_t len = *(*data)++;
|
||||||
if (len == 0x82) {
|
if (len == 0x82) {
|
||||||
len = *(*data)++ << 8;
|
len = *(*data)++ << 8;
|
||||||
@@ -1889,7 +1910,7 @@ static int cmd_import_data() {
|
|||||||
if (*start++ != 0x4D) {
|
if (*start++ != 0x4D) {
|
||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
size_t tgl = tag_len(&start);
|
uint16_t tgl = tag_len(&start);
|
||||||
if (*start != 0xB6 && *start != 0xB8 && *start != 0xA4) {
|
if (*start != 0xB6 && *start != 0xB8 && *start != 0xA4) {
|
||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
@@ -1917,7 +1938,8 @@ static int cmd_import_data() {
|
|||||||
return SW_WRONG_DATA();
|
return SW_WRONG_DATA();
|
||||||
}
|
}
|
||||||
tgl = tag_len(&start);
|
tgl = tag_len(&start);
|
||||||
uint8_t *end = start + tgl, len[9] = { 0 }, *p[9] = { 0 };
|
uint8_t *end = start + tgl, *p[9] = { 0 };
|
||||||
|
uint16_t len[9] = { 0 };
|
||||||
while (start < end) {
|
while (start < end) {
|
||||||
uint8_t tag = *start++;
|
uint8_t tag = *start++;
|
||||||
if ((tag >= 0x91 && tag <= 0x97) || tag == 0x99) {
|
if ((tag >= 0x91 && tag <= 0x97) || tag == 0x99) {
|
||||||
@@ -1987,7 +2009,7 @@ static int cmd_import_data() {
|
|||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = store_keys(&rsa, ALGO_RSA, fid);
|
r = store_keys(&rsa, ALGO_RSA, fid, true);
|
||||||
make_rsa_response(&rsa);
|
make_rsa_response(&rsa);
|
||||||
mbedtls_rsa_free(&rsa);
|
mbedtls_rsa_free(&rsa);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
@@ -2025,13 +2047,16 @@ static int cmd_import_data() {
|
|||||||
mbedtls_ecp_keypair_free(&ecdsa);
|
mbedtls_ecp_keypair_free(&ecdsa);
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
r = store_keys(&ecdsa, ALGO_ECDSA, fid);
|
r = store_keys(&ecdsa, ALGO_ECDSA, fid, true);
|
||||||
make_ecdsa_response(&ecdsa);
|
make_ecdsa_response(&ecdsa);
|
||||||
mbedtls_ecp_keypair_free(&ecdsa);
|
mbedtls_ecp_keypair_free(&ecdsa);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
return SW_FUNC_NOT_SUPPORTED();
|
||||||
|
}
|
||||||
if (fid == EF_PK_SIG) {
|
if (fid == EF_PK_SIG) {
|
||||||
reset_sig_count();
|
reset_sig_count();
|
||||||
}
|
}
|
||||||
@@ -2039,7 +2064,7 @@ static int cmd_import_data() {
|
|||||||
if (!pbef) {
|
if (!pbef) {
|
||||||
return SW_REFERENCE_NOT_FOUND();
|
return SW_REFERENCE_NOT_FOUND();
|
||||||
}
|
}
|
||||||
r = flash_write_data_to_file(pbef, res_APDU, res_APDU_size);
|
r = file_put_data(pbef, res_APDU, res_APDU_size);
|
||||||
if (r != CCID_OK) {
|
if (r != CCID_OK) {
|
||||||
return SW_EXEC_ERROR();
|
return SW_EXEC_ERROR();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,14 +19,41 @@
|
|||||||
#define __OPENPGP_H_
|
#define __OPENPGP_H_
|
||||||
|
|
||||||
#include "stdlib.h"
|
#include "stdlib.h"
|
||||||
#ifndef ENABLE_EMULATION
|
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
|
||||||
#include <pico/stdlib.h>
|
#include <pico/stdlib.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "hsm.h"
|
#include "pico_keys.h"
|
||||||
#include "apdu.h"
|
#include "apdu.h"
|
||||||
|
#include "mbedtls/rsa.h"
|
||||||
|
#include "mbedtls/ecdsa.h"
|
||||||
|
|
||||||
extern bool has_pw1;
|
extern bool has_pw1;
|
||||||
extern bool has_pw3;
|
extern bool has_pw3;
|
||||||
|
|
||||||
|
extern int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek);
|
||||||
|
extern void make_rsa_response(mbedtls_rsa_context *rsa);
|
||||||
|
extern void make_ecdsa_response(mbedtls_ecdsa_context *ecdsa);
|
||||||
|
extern int ecdsa_sign(mbedtls_ecdsa_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
size_t data_len,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t *out_len);
|
||||||
|
extern int rsa_sign(mbedtls_rsa_context *ctx,
|
||||||
|
const uint8_t *data,
|
||||||
|
size_t data_len,
|
||||||
|
uint8_t *out,
|
||||||
|
size_t *out_len);
|
||||||
|
extern int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek);
|
||||||
|
extern int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey, bool use_dek);
|
||||||
|
extern int pin_reset_retries(const file_t *pin, bool force);
|
||||||
|
|
||||||
|
#define ALGO_RSA 0x01
|
||||||
|
#define ALGO_ECDH 0x12
|
||||||
|
#define ALGO_ECDSA 0x13
|
||||||
|
#define ALGO_AES 0x70
|
||||||
|
#define ALGO_AES_128 0x71
|
||||||
|
#define ALGO_AES_192 0x72
|
||||||
|
#define ALGO_AES_256 0x74
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
1330
src/openpgp/piv.c
Normal file
1330
src/openpgp/piv.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -24,9 +24,14 @@
|
|||||||
#define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff)
|
#define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff)
|
||||||
|
|
||||||
|
|
||||||
#define PIPGP_VERSION 0x010A
|
#define PIPGP_VERSION 0x0202
|
||||||
|
|
||||||
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
|
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
|
||||||
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)
|
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)
|
||||||
|
|
||||||
|
#define PIV_VERSION 0x0507
|
||||||
|
|
||||||
|
#define PIV_VERSION_MAJOR ((PIV_VERSION >> 8) & 0xff)
|
||||||
|
#define PIV_VERSION_MINOR (PIV_VERSION & 0xff)
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
43
tests/docker/bullseye/Dockerfile
Normal file
43
tests/docker/bullseye/Dockerfile
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
FROM debian:bullseye
|
||||||
|
|
||||||
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|
||||||
|
RUN apt update && apt upgrade -y
|
||||||
|
RUN apt install -y apt-utils
|
||||||
|
RUN apt autoremove -y
|
||||||
|
RUN rm -rf /var/cache/apt/archives/*
|
||||||
|
RUN apt install -y libccid \
|
||||||
|
libpcsclite-dev \
|
||||||
|
git \
|
||||||
|
autoconf \
|
||||||
|
pkg-config \
|
||||||
|
libtool \
|
||||||
|
help2man \
|
||||||
|
automake \
|
||||||
|
gcc \
|
||||||
|
make \
|
||||||
|
build-essential \
|
||||||
|
opensc \
|
||||||
|
python3 \
|
||||||
|
python3-pip \
|
||||||
|
swig \
|
||||||
|
cmake \
|
||||||
|
vsmartcard-vpcd \
|
||||||
|
libgcrypt-dev \
|
||||||
|
libssl-dev \
|
||||||
|
check \
|
||||||
|
gengetopt \
|
||||||
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
|
RUN pip3 install pytest pycvc cryptography pyscard
|
||||||
|
RUN git clone https://github.com/Yubico/yubico-piv-tool
|
||||||
|
WORKDIR /yubico-piv-tool
|
||||||
|
RUN git checkout tags/yubico-piv-tool-2.5.1
|
||||||
|
ADD tests/docker/jammy/yubico-piv-tool.patch /yubico-piv-tool/yubico-piv-tool.patch
|
||||||
|
RUN git apply yubico-piv-tool.patch
|
||||||
|
RUN mkdir build
|
||||||
|
WORKDIR /yubico-piv-tool/build
|
||||||
|
RUN cmake .. -DENABLE_HARDWARE_TESTS=1
|
||||||
|
RUN make -j`nproc`
|
||||||
|
RUN make install
|
||||||
|
WORKDIR /
|
||||||
|
RUN ldconfig
|
||||||
@@ -22,6 +22,20 @@ RUN apt install -y libccid \
|
|||||||
cmake \
|
cmake \
|
||||||
vsmartcard-vpcd \
|
vsmartcard-vpcd \
|
||||||
libgcrypt-dev \
|
libgcrypt-dev \
|
||||||
|
libssl-dev \
|
||||||
|
check \
|
||||||
|
gengetopt \
|
||||||
&& rm -rf /var/lib/apt/lists/*
|
&& rm -rf /var/lib/apt/lists/*
|
||||||
RUN pip3 install pytest pycvc cryptography pyscard
|
RUN pip3 install pytest pycvc cryptography pyscard
|
||||||
|
RUN git clone https://github.com/Yubico/yubico-piv-tool
|
||||||
|
WORKDIR /yubico-piv-tool
|
||||||
|
RUN git checkout tags/yubico-piv-tool-2.5.1
|
||||||
|
ADD tests/docker/jammy/yubico-piv-tool.patch /yubico-piv-tool/yubico-piv-tool.patch
|
||||||
|
RUN git apply yubico-piv-tool.patch
|
||||||
|
RUN mkdir build
|
||||||
|
WORKDIR /yubico-piv-tool/build
|
||||||
|
RUN cmake .. -DENABLE_HARDWARE_TESTS=1
|
||||||
|
RUN make -j`nproc`
|
||||||
|
RUN make install
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
|
RUN ldconfig
|
||||||
|
|||||||
68
tests/docker/jammy/yubico-piv-tool.patch
Normal file
68
tests/docker/jammy/yubico-piv-tool.patch
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
diff --git a/lib/tests/api.c b/lib/tests/api.c
|
||||||
|
index fb7c1a8..b569ec3 100644
|
||||||
|
--- a/lib/tests/api.c
|
||||||
|
+++ b/lib/tests/api.c
|
||||||
|
@@ -515,7 +515,7 @@ START_TEST(test_pin_policy_always) {
|
||||||
|
unsigned char rand[128] = {0};
|
||||||
|
|
||||||
|
size_t sig_len = sizeof(signature);
|
||||||
|
- size_t padlen = 256;
|
||||||
|
+ size_t padlen = 512;
|
||||||
|
unsigned int enc_len;
|
||||||
|
unsigned int data_len;
|
||||||
|
|
||||||
|
@@ -1009,8 +1009,8 @@ END_TEST
|
||||||
|
START_TEST(test_pin_cache) {
|
||||||
|
ykpiv_rc res;
|
||||||
|
ykpiv_state *local_state;
|
||||||
|
- unsigned char data[256] = {0};
|
||||||
|
- unsigned char data_in[256] = {0};
|
||||||
|
+ unsigned char data[512] = {0};
|
||||||
|
+ unsigned char data_in[512] = {0};
|
||||||
|
int len = sizeof(data);
|
||||||
|
size_t len2 = sizeof(data);
|
||||||
|
|
||||||
|
@@ -1028,17 +1028,17 @@ START_TEST(test_pin_cache) {
|
||||||
|
ck_assert_int_eq(res, YKPIV_OK);
|
||||||
|
|
||||||
|
// Verify decryption does not work without auth
|
||||||
|
- res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA2048, 0x9a);
|
||||||
|
+ res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA4096, 0x9a);
|
||||||
|
ck_assert_int_eq(res, YKPIV_AUTHENTICATION_ERROR);
|
||||||
|
|
||||||
|
// Verify decryption does work when authed
|
||||||
|
res = ykpiv_verify_select(g_state, "123456", 6, NULL, true);
|
||||||
|
ck_assert_int_eq(res, YKPIV_OK);
|
||||||
|
- res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA2048, 0x9a);
|
||||||
|
+ res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA4096, 0x9a);
|
||||||
|
ck_assert_int_eq(res, YKPIV_OK);
|
||||||
|
|
||||||
|
// Verify PIN policy allows continuing to decrypt without re-verifying
|
||||||
|
- res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA2048, 0x9a);
|
||||||
|
+ res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA4096, 0x9a);
|
||||||
|
ck_assert_int_eq(res, YKPIV_OK);
|
||||||
|
|
||||||
|
// Create a new ykpiv state, connect, and close it.
|
||||||
|
@@ -1059,7 +1059,7 @@ START_TEST(test_pin_cache) {
|
||||||
|
//
|
||||||
|
// Note that you can verify that this fails by rebuilding with
|
||||||
|
// DISABLE_PIN_CACHE set to 1.
|
||||||
|
- res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA2048, 0x9a);
|
||||||
|
+ res = ykpiv_decipher_data(g_state, data_in, (size_t)len, data, &len2, YKPIV_ALGO_RSA4096, 0x9a);
|
||||||
|
ck_assert_int_eq(res, YKPIV_OK);
|
||||||
|
}
|
||||||
|
END_TEST
|
||||||
|
diff --git a/tools/confirm.sh b/tools/confirm.sh
|
||||||
|
index 81c10ac..4ab15c5 100755
|
||||||
|
--- a/tools/confirm.sh
|
||||||
|
+++ b/tools/confirm.sh
|
||||||
|
@@ -20,7 +20,8 @@ echo "WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING WA
|
||||||
|
echo "******* ******* ******* ******* ******* ******* ******* ******* ******* ******* ******* ******* ******* ******* *******" >&0
|
||||||
|
echo >&0
|
||||||
|
echo -n "Are you SURE you wish to proceed? If so, type 'CONFIRM': " >&0
|
||||||
|
-
|
||||||
|
+echo "0"
|
||||||
|
+exit 0
|
||||||
|
read CONFIRM
|
||||||
|
if [[ "x$CONFIRM" != "xCONFIRM" ]]; then
|
||||||
|
echo "1"
|
||||||
@@ -46,10 +46,10 @@
|
|||||||
|
|
||||||
|
|
||||||
# default values, can be overridden by the environment
|
# default values, can be overridden by the environment
|
||||||
: ${MBEDTLS_DOCKER_GUEST:=jammy}
|
: ${MBEDTLS_DOCKER_GUEST:=bullseye}
|
||||||
|
|
||||||
|
|
||||||
DOCKER_IMAGE_TAG="pico-hsm-test:${MBEDTLS_DOCKER_GUEST}"
|
DOCKER_IMAGE_TAG="pico-openpgp-test:${MBEDTLS_DOCKER_GUEST}"
|
||||||
|
|
||||||
# Make sure docker is available
|
# Make sure docker is available
|
||||||
if ! which docker > /dev/null; then
|
if ! which docker > /dev/null; then
|
||||||
@@ -79,7 +79,7 @@ ${DOCKER} image build \
|
|||||||
--cache-from=${DOCKER_IMAGE_TAG} \
|
--cache-from=${DOCKER_IMAGE_TAG} \
|
||||||
--network host \
|
--network host \
|
||||||
--build-arg MAKEFLAGS_PARALLEL="-j ${NUM_PROC}" \
|
--build-arg MAKEFLAGS_PARALLEL="-j ${NUM_PROC}" \
|
||||||
tests/docker/${MBEDTLS_DOCKER_GUEST}
|
-f tests/docker/${MBEDTLS_DOCKER_GUEST}/Dockerfile .
|
||||||
|
|
||||||
run_in_docker()
|
run_in_docker()
|
||||||
{
|
{
|
||||||
|
|||||||
33
tests/scripts/attestation.sh
Executable file
33
tests/scripts/attestation.sh
Executable file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source ./tests/scripts/func.sh
|
||||||
|
|
||||||
|
echo -n " Fetch attestation certificate... "
|
||||||
|
piv read-cert -sf9 -o sf9.pem
|
||||||
|
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
algs=("RSA1024" "RSA2048" "ECCP256" "ECCP384")
|
||||||
|
slots=("9a" "9c" "9d" "9e" "82" "83" "84" "85" "86" "87" "88" "89" "8a" "8b" "8c" "8d" "8e" "8f" "90" "91" "92" "93" "94" "95")
|
||||||
|
for alg in ${algs[*]}; do
|
||||||
|
for slot in ${slots[*]}; do
|
||||||
|
echo " Test attestation with ${alg} in slot ${slot}"
|
||||||
|
echo -n " Keygen... "
|
||||||
|
gen_and_check $alg $slot && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " Fetch attesting certificate... "
|
||||||
|
piv attest -s$slot -o attestation.pem
|
||||||
|
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " OpenSSL verify attestation... "
|
||||||
|
e=$(openssl verify -CAfile sf9.pem attestation.pem 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q ": OK" <<< $e && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " Key deletion... "
|
||||||
|
delete_key $alg $slot && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -rf cert.pem
|
||||||
|
rm -rf sf9.pem
|
||||||
6
tests/scripts/cli-test.sh
Executable file
6
tests/scripts/cli-test.sh
Executable file
@@ -0,0 +1,6 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
chmod a+x tests/scripts/*.sh
|
||||||
|
|
||||||
|
echo "======== CLI Test suite ========"
|
||||||
|
./tests/scripts/yubico-piv-tool.sh
|
||||||
38
tests/scripts/func.sh
Executable file
38
tests/scripts/func.sh
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
OK="\033[32mok\033[0m"
|
||||||
|
FAIL="\033[31mfail\033[0m"
|
||||||
|
|
||||||
|
READER="u"
|
||||||
|
|
||||||
|
piv() {
|
||||||
|
yubico-piv-tool -r${READER} -a$@
|
||||||
|
}
|
||||||
|
|
||||||
|
gen_and_check() {
|
||||||
|
e=$(piv generate -s$2 -A$1 -opublic.pem 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q "Successfully generated a new private key" <<< $e && echo -n "." || exit $?
|
||||||
|
e=$(piv status 2>&1)
|
||||||
|
e=${e//$'\t'/}
|
||||||
|
e=${e//$'\n'/}
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q "Slot $2:Algorithm:$1" <<< $e && echo -n "." || exit $?
|
||||||
|
}
|
||||||
|
delete_key() {
|
||||||
|
piv delete-key -s$2 > /dev/null 2>&1
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
piv delete-cert -s$2 > /dev/null 2>&1
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
e=$(piv status 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
q=$(grep -q "Slot $2: Algorithm: $1" <<< $e)
|
||||||
|
test $? -eq 1 && echo -n "." || exit $?
|
||||||
|
rm -rf public.pem
|
||||||
|
}
|
||||||
|
gen_and_delete() {
|
||||||
|
gen_and_check $1 $2
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
delete_key $1 $2
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
}
|
||||||
12
tests/scripts/keygen.sh
Executable file
12
tests/scripts/keygen.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source ./tests/scripts/func.sh
|
||||||
|
|
||||||
|
algs=("RSA1024" "RSA2048" "ECCP256" "ECCP384")
|
||||||
|
slots=("9a" "9c" "9d" "9e" "82" "83" "84" "85" "86" "87" "88" "89" "8a" "8b" "8c" "8d" "8e" "8f" "90" "91" "92" "93" "94" "95")
|
||||||
|
for alg in ${algs[*]}; do
|
||||||
|
for slot in ${slots[*]}; do
|
||||||
|
echo -n " Test ${alg} in slot ${slot}... "
|
||||||
|
gen_and_delete ${alg} $slot && echo -e ".\t${OK}" || exit $?
|
||||||
|
done
|
||||||
|
done
|
||||||
46
tests/scripts/signatures.sh
Executable file
46
tests/scripts/signatures.sh
Executable file
@@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source ./tests/scripts/func.sh
|
||||||
|
|
||||||
|
algs=("RSA1024" "RSA2048" "ECCP256" "ECCP384")
|
||||||
|
slots=("9a" "9c" "9d" "9e" "82" "83" "84" "85" "86" "87" "88" "89" "8a" "8b" "8c" "8d" "8e" "8f" "90" "91" "92" "93" "94" "95")
|
||||||
|
for alg in ${algs[*]}; do
|
||||||
|
for slot in ${slots[*]}; do
|
||||||
|
echo " Test signature with ${alg} in slot ${slot}"
|
||||||
|
echo -n " Keygen... "
|
||||||
|
gen_and_check $alg $slot && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " Test request certificate... "
|
||||||
|
e=$(piv verify -arequest -P123456 -s$slot -S'/CN=bar/OU=test/O=example.com/' -ipublic.pem -ocert.pem 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q "Successfully verified PIN" <<< $e && echo -n "." || exit $?
|
||||||
|
grep -q "Successfully generated a certificate request" <<< $e && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " OpenSSL verify request... "
|
||||||
|
e=$(openssl req -verify -in cert.pem 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q " OK" <<< $e && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " Test self-signed certificate... "
|
||||||
|
e=$(piv verify -aselfsign -P123456 -s$slot -S'/CN=bar/OU=test/O=example.com/' -ipublic.pem -ocert.pem 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q "Successfully verified PIN" <<< $e && echo -n "." || exit $?
|
||||||
|
grep -q "Successfully generated a new self signed certificate" <<< $e && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " Test signature... "
|
||||||
|
e=$(piv verify-pin -atest-signature -s$slot -P123456 -icert.pem 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q "Successful" <<< $e && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " OpenSSL verify cert... "
|
||||||
|
e=$(openssl verify -CAfile cert.pem cert.pem 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q ": OK" <<< $e && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
echo -n " Key deletion... "
|
||||||
|
delete_key $alg $slot && echo -e ".\t${OK}" || exit $?
|
||||||
|
|
||||||
|
done
|
||||||
|
done
|
||||||
|
|
||||||
|
rm -rf cert.pem
|
||||||
10
tests/scripts/version.sh
Executable file
10
tests/scripts/version.sh
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source ./tests/scripts/func.sh
|
||||||
|
|
||||||
|
# Get version
|
||||||
|
echo -n " Test version... "
|
||||||
|
e=$(piv version 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q "Application version" <<< $e && echo -n "." || exit $?
|
||||||
|
grep -q " found" <<< $e && echo -e ".\t${OK}" || exit $?
|
||||||
17
tests/scripts/yubico-piv-test.sh
Executable file
17
tests/scripts/yubico-piv-test.sh
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source ./tests/scripts/func.sh
|
||||||
|
reset
|
||||||
|
test $? -eq 0 || exit $?
|
||||||
|
|
||||||
|
echo -n " Test PKCS11 tool..."
|
||||||
|
gen_and_check rsa:2048
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
e=$(pkcs11-tool --test -l --pin 648219 2>&1)
|
||||||
|
test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
grep -q "No errors" <<< $e && echo -n "." || exit $?
|
||||||
|
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1
|
||||||
|
test $? -eq 0 && echo -e ".\t${OK}" || exit $?
|
||||||
|
#e=$(pkcs11-tool --test-ec -l --pin 648219 --id 1 --key-type ec:secp256r1 2>&1)
|
||||||
|
#test $? -eq 0 && echo -n "." || exit $?
|
||||||
|
#grep -q "==> OK" <<< $e && echo -e ".\t${OK}" || exit $?
|
||||||
30
tests/scripts/yubico-piv-tool.sh
Executable file
30
tests/scripts/yubico-piv-tool.sh
Executable file
@@ -0,0 +1,30 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source ./tests/scripts/func.sh
|
||||||
|
echo "==== Test version ===="
|
||||||
|
./tests/scripts/version.sh
|
||||||
|
test $? -eq 0 || {
|
||||||
|
echo -e "\t${FAIL}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "==== Test asymmetric keygen ===="
|
||||||
|
./tests/scripts/keygen.sh
|
||||||
|
test $? -eq 0 || {
|
||||||
|
echo -e "\t${FAIL}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "==== Test self-signed certificates ===="
|
||||||
|
./tests/scripts/signatures.sh
|
||||||
|
test $? -eq 0 || {
|
||||||
|
echo -e "\t${FAIL}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "==== Test attestation ===="
|
||||||
|
./tests/scripts/attestation.sh
|
||||||
|
test $? -eq 0 || {
|
||||||
|
echo -e "\t${FAIL}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
@@ -1,7 +1,30 @@
|
|||||||
#!/bin/bash -eu
|
#!/bin/bash
|
||||||
|
|
||||||
|
OK="\t\033[32mok\033[0m"
|
||||||
|
FAIL="\t\033[31mfail\033[0m"
|
||||||
|
|
||||||
|
fail() {
|
||||||
|
echo -e "${FAIL}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo -n "Start PCSC..."
|
||||||
/usr/sbin/pcscd &
|
/usr/sbin/pcscd &
|
||||||
sleep 2
|
test $? -eq 0 && echo -e "${OK}" || {
|
||||||
rm -rf memory.flash
|
echo -e "${FAIL}"
|
||||||
./build_in_docker/pico_openpgp > /dev/null &
|
exit 1
|
||||||
|
}
|
||||||
|
sleep 1
|
||||||
|
rm -f memory.flash
|
||||||
|
echo -n "Start Pico OpenPGP..."
|
||||||
|
./build_in_docker/pico_openpgp > /dev/null 2>&1 &
|
||||||
|
test $? -eq 0 && echo -n "." || fail
|
||||||
|
sleep 1
|
||||||
|
ATR="3b:da:18:ff:81:b1:fe:75:1f:03:00:31:f5:73:c0:01:60:00:90:00:1c"
|
||||||
|
e=$(opensc-tool -an 2>&1)
|
||||||
|
grep -q "${ATR}" <<< $e && echo -n "." || fail
|
||||||
|
test $? -eq 0 && echo -e "${OK}" || fail
|
||||||
|
|
||||||
pytest tests -W ignore::DeprecationWarning
|
pytest tests -W ignore::DeprecationWarning
|
||||||
|
|
||||||
|
./tests/scripts/cli-test.sh
|
||||||
|
|||||||
Reference in New Issue
Block a user