mirror of
https://github.com/polhenarejos/pico-openpgp.git
synced 2026-05-31 10:31:24 +02:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d9193129c7 | ||
|
|
402c92ea83 | ||
|
|
ac1e3af410 | ||
|
|
5a7f1dd781 | ||
|
|
a0f8d67821 | ||
|
|
757a000f77 | ||
|
|
4fba684a24 | ||
|
|
0b7beeec8c | ||
|
|
1f037da326 | ||
|
|
ffbdef14b6 | ||
|
|
ad59aa8c1a | ||
|
|
fcca95715e | ||
|
|
704df76499 | ||
|
|
e6cc190c4f | ||
|
|
615737807a | ||
|
|
e563bb3379 | ||
|
|
374cff588c | ||
|
|
ca8d81fd20 | ||
|
|
5d71e69c1d | ||
|
|
75691b6a42 | ||
|
|
811f33e282 | ||
|
|
90b62f067d |
@@ -17,6 +17,8 @@
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
option(OPENPGP_TEST_INIT_LEGACY_PIN "Bootstrap legacy PIN/DEK format for migration tests" OFF)
|
||||
|
||||
set(USB_VID 0x2E8A)
|
||||
set(USB_PID 0x10FF)
|
||||
|
||||
@@ -76,7 +78,7 @@ set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/defs.c
|
||||
)
|
||||
|
||||
SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/openpgp/version.h" 3)
|
||||
SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/openpgp/version.h")
|
||||
|
||||
if(ESP_PLATFORM)
|
||||
project(pico_openpgp)
|
||||
@@ -88,14 +90,27 @@ set(INCLUDES ${INCLUDES}
|
||||
if(NOT ESP_PLATFORM)
|
||||
target_sources(pico_openpgp PUBLIC ${SOURCES})
|
||||
target_include_directories(pico_openpgp PUBLIC ${INCLUDES})
|
||||
if(OPENPGP_TEST_INIT_LEGACY_PIN)
|
||||
target_compile_definitions(pico_openpgp PRIVATE OPENPGP_TEST_INIT_LEGACY_PIN=1)
|
||||
endif()
|
||||
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
set(COMMON_COMPILE_OPTIONS
|
||||
-Wall
|
||||
)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(pico_openpgp PUBLIC
|
||||
-Werror
|
||||
target_compile_options(pico_openpgp PRIVATE ${COMMON_COMPILE_OPTIONS})
|
||||
|
||||
pico_keys_apply_strict_flags(
|
||||
SOURCES ${SOURCES}
|
||||
FILTER_REGEX "/src/openpgp/|/pico-keys-sdk/src/|/pico-keys-sdk/config/"
|
||||
)
|
||||
|
||||
if(NOT MSVC)
|
||||
string(FIND ${CMAKE_C_COMPILER} ":" COMPILER_COLON)
|
||||
if(${COMPILER_COLON} GREATER_EQUAL 0)
|
||||
target_compile_options(pico_openpgp PRIVATE
|
||||
-Wno-error=use-after-free
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMULATION)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION_MAJOR="4"
|
||||
VERSION_MINOR="4"
|
||||
VERSION_MINOR="6"
|
||||
SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}"
|
||||
#if ! [[ -z "${GITHUB_SHA}" ]]; then
|
||||
# SUFFIX="${SUFFIX}.${GITHUB_SHA}"
|
||||
|
||||
Submodule pico-keys-sdk updated: 6f996c67c2...44ee025416
@@ -3,4 +3,7 @@ idf_component_register(
|
||||
INCLUDE_DIRS .
|
||||
REQUIRES mbedtls efuse pico-keys-sdk
|
||||
)
|
||||
if(OPENPGP_TEST_INIT_LEGACY_PIN)
|
||||
target_compile_definitions(${COMPONENT_LIB} PRIVATE OPENPGP_TEST_INIT_LEGACY_PIN=1)
|
||||
endif()
|
||||
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON)
|
||||
|
||||
@@ -17,6 +17,6 @@
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_activate_file() {
|
||||
int cmd_activate_file(void) {
|
||||
return SW_OK();
|
||||
}
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "openpgp.h"
|
||||
#include "random.h"
|
||||
|
||||
int cmd_challenge() {
|
||||
int cmd_challenge(void) {
|
||||
uint8_t *rb = (uint8_t *) random_bytes_get(apdu.ne);
|
||||
if (!rb) {
|
||||
return SW_WRONG_LENGTH();
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "openpgp.h"
|
||||
#include "otp.h"
|
||||
|
||||
int cmd_change_pin() {
|
||||
int cmd_change_pin(void) {
|
||||
if (P1(apdu) != 0x0) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
@@ -37,33 +37,34 @@ int cmd_change_pin() {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
|
||||
if (otp_key_1) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
dek[IV_SIZE + i] ^= otp_key_1[i];
|
||||
}
|
||||
}
|
||||
uint8_t dhash[33];
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = apdu.nc - pin_len;
|
||||
double_hash_pin(apdu.data + pin_len, apdu.nc - pin_len, dhash + 1);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(apdu.data + pin_len, apdu.nc - pin_len, dhash + 2);
|
||||
file_put_data(pw, dhash, sizeof(dhash));
|
||||
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (P2(apdu) == 0x81) {
|
||||
file_t *tf = search_by_fid(EF_DEK_PW1, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32] = {0};
|
||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||
if (P2(apdu) == 0x81) {
|
||||
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw1);
|
||||
memcpy(def + IV_SIZE, dek + IV_SIZE, 32);
|
||||
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
|
||||
uint8_t def[DEK_FILE_SIZE];
|
||||
def[0] = 0x3;
|
||||
pin_derive_session(apdu.data + pin_len, apdu.nc - pin_len, session_pw1);
|
||||
encrypt_with_aad(session_pw1, dek, DEK_SIZE, PIN_KDF_DEFAULT_VERSION, def + 1);
|
||||
r = file_put_data(tf, def, sizeof(def));
|
||||
}
|
||||
else if (P2(apdu) == 0x83) {
|
||||
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw3);
|
||||
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
|
||||
aes_encrypt_cfb_256(session_pw3, def, def + IV_SIZE + 32 + 32, 32);
|
||||
file_t *tf = search_by_fid(EF_DEK_PW3, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t def[DEK_FILE_SIZE];
|
||||
def[0] = 0x3;
|
||||
pin_derive_session(apdu.data + pin_len, apdu.nc - pin_len, session_pw3);
|
||||
encrypt_with_aad(session_pw3, dek, DEK_SIZE, PIN_KDF_DEFAULT_VERSION, def + 1);
|
||||
r = file_put_data(tf, def, sizeof(def));
|
||||
}
|
||||
file_put_data(tf, def, sizeof(def));
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
extern bool is_gpg;
|
||||
|
||||
int cmd_get_data() {
|
||||
int cmd_get_data(void) {
|
||||
if (apdu.nc > 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
@@ -29,10 +29,20 @@ int cmd_get_data() {
|
||||
if (!(ef = search_by_fid(fid, NULL, SPECIFY_EF))) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!authenticate_action(ef, ACL_OP_READ_SEARCH)) {
|
||||
if (fid == EF_PRIV_DO_3) {
|
||||
if (!has_pw2 && !has_pw3) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (currentEF && (currentEF->fid & 0x1FF0) == (fid & 0x1FF0)) { //previously selected
|
||||
}
|
||||
else if (fid == EF_PRIV_DO_4) {
|
||||
if (!has_pw3) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
}
|
||||
else if (!authenticate_action(ef, ACL_OP_READ_SEARCH)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (currentEF && currentEF->fid == fid) { // previously selected same EF
|
||||
ef = currentEF;
|
||||
}
|
||||
else {
|
||||
@@ -44,6 +54,7 @@ int cmd_get_data() {
|
||||
}
|
||||
uint16_t fids[] = { 1, fid };
|
||||
uint16_t data_len = parse_do(fids, 1);
|
||||
if (!(ef->type & FILE_DATA_FLASH)) {
|
||||
uint8_t *p = NULL;
|
||||
uint16_t tg = 0;
|
||||
uint16_t tg_len = 0;
|
||||
@@ -63,6 +74,7 @@ int cmd_get_data() {
|
||||
res_APDU_size -= dec;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (is_gpg == false) {
|
||||
uint8_t off = 2;
|
||||
if (P1(apdu) > 0x0) {
|
||||
@@ -103,7 +115,7 @@ int cmd_get_data() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_get_next_data() {
|
||||
int cmd_get_next_data(void) {
|
||||
file_t *ef = NULL;
|
||||
if (apdu.nc > 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
@@ -128,3 +140,10 @@ int cmd_get_next_data() {
|
||||
select_file(ef);
|
||||
return cmd_get_data();
|
||||
}
|
||||
|
||||
int cmd_get_bulk_data(void) {
|
||||
if (apdu.nc < 3) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
return bulk_cmd(cmd_get_data);
|
||||
}
|
||||
|
||||
@@ -18,14 +18,12 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_compat.h"
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#else
|
||||
#include "common.h"
|
||||
#endif
|
||||
#include "openpgp.h"
|
||||
#include "random.h"
|
||||
#include "do.h"
|
||||
|
||||
uint16_t tag_len(uint8_t **data) {
|
||||
static uint16_t tag_len(uint8_t **data) {
|
||||
size_t len = *(*data)++;
|
||||
if (len == 0x82) {
|
||||
len = *(*data)++ << 8;
|
||||
@@ -37,7 +35,7 @@ uint16_t tag_len(uint8_t **data) {
|
||||
return len;
|
||||
}
|
||||
|
||||
int cmd_import_data() {
|
||||
int cmd_import_data(void) {
|
||||
file_t *ef = NULL;
|
||||
uint16_t fid = 0x0;
|
||||
if (P1(apdu) != 0x3F || P2(apdu) != 0xFF) {
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "openpgp.h"
|
||||
#include "do.h"
|
||||
|
||||
int cmd_internal_aut() {
|
||||
int cmd_internal_aut(void) {
|
||||
if (P1(apdu) != 0x00 || P2(apdu) != 0x00) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "do.h"
|
||||
#include "random.h"
|
||||
|
||||
int cmd_keypair_gen() {
|
||||
int cmd_keypair_gen(void) {
|
||||
if (P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_mse() {
|
||||
int cmd_mse(void) {
|
||||
if (P1(apdu) != 0x41 || (P2(apdu) != 0xA4 && P2(apdu) != 0xB8)) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_compat.h"
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#else
|
||||
#include "common.h"
|
||||
#endif
|
||||
#include "openpgp.h"
|
||||
#include "do.h"
|
||||
@@ -27,7 +25,7 @@
|
||||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/asn1.h"
|
||||
|
||||
int cmd_pso() {
|
||||
int cmd_pso(void) {
|
||||
uint16_t algo_fid = 0x0, pk_fid = 0x0;
|
||||
bool is_aes = false;
|
||||
if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) {
|
||||
@@ -70,7 +68,7 @@ int cmd_pso() {
|
||||
return SW_SECURE_MESSAGE_EXEC_ERROR();
|
||||
}
|
||||
int r = PICOKEY_OK;
|
||||
int key_size = file_get_size(ef);
|
||||
size_t key_size = file_get_size(ef);
|
||||
if (is_aes) {
|
||||
uint8_t aes_key[32];
|
||||
r = load_aes_key(aes_key, ef);
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_put_data() {
|
||||
int cmd_put_data(void) {
|
||||
uint16_t fid = (P1(apdu) << 8) | P2(apdu);
|
||||
file_t *ef;
|
||||
if (fid == EF_RESET_CODE) {
|
||||
@@ -32,34 +32,42 @@ int cmd_put_data() {
|
||||
if (!authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if ((fid == EF_PRIV_DO_1 || fid == EF_PRIV_DO_3) && (!has_pw2 && !has_pw3)) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (!(fid == EF_PRIV_DO_1 || fid == EF_PRIV_DO_3) && !has_pw3) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
if (fid == EF_PW_STATUS) {
|
||||
fid = EF_PW_PRIV;
|
||||
apdu.nc = 4; //we silently ommit the reset parameters
|
||||
}
|
||||
if (currentEF && (currentEF->fid & 0x1FF0) == (fid & 0x1FF0)) { //previously selected
|
||||
if (currentEF && currentEF->fid == fid) { // previously selected same EF
|
||||
ef = currentEF;
|
||||
}
|
||||
if (apdu.nc > 0 && (ef->type & FILE_DATA_FLASH)) {
|
||||
if (ef->type & FILE_DATA_FLASH) {
|
||||
int r = 0;
|
||||
if (apdu.nc > 0) {
|
||||
if (fid == EF_RC) {
|
||||
has_rc = false;
|
||||
if ((r = load_dek()) != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
uint8_t dhash[33];
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = apdu.nc;
|
||||
double_hash_pin(apdu.data, apdu.nc, dhash + 1);
|
||||
r = file_put_data(ef, dhash, sizeof(dhash));
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(apdu.data, apdu.nc, dhash + 2);
|
||||
file_put_data(ef, dhash, sizeof(dhash));
|
||||
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
|
||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||
hash_multi(apdu.data, apdu.nc, session_rc);
|
||||
memcpy(def + IV_SIZE + 32, dek + IV_SIZE, 32);
|
||||
aes_encrypt_cfb_256(session_rc, def, def + IV_SIZE + 32, 32);
|
||||
|
||||
uint8_t def[DEK_FILE_SIZE];
|
||||
def[0] = 0x3;
|
||||
pin_derive_session(apdu.data, apdu.nc, session_rc);
|
||||
encrypt_with_aad(session_rc, dek, DEK_SIZE, PIN_KDF_DEFAULT_VERSION, def + 1);
|
||||
r = file_put_data(tf, def, sizeof(def));
|
||||
}
|
||||
else {
|
||||
@@ -70,5 +78,9 @@ int cmd_put_data() {
|
||||
}
|
||||
low_flash_available();
|
||||
}
|
||||
else {
|
||||
delete_file(ef);
|
||||
}
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "openpgp.h"
|
||||
#include "otp.h"
|
||||
|
||||
int cmd_reset_retry() {
|
||||
int cmd_reset_retry(void) {
|
||||
if (P2(apdu) != 0x81) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
@@ -44,7 +44,7 @@ int cmd_reset_retry() {
|
||||
}
|
||||
newpin_len = apdu.nc - pin_len;
|
||||
has_rc = true;
|
||||
hash_multi(apdu.data, pin_len, session_rc);
|
||||
pin_derive_session(apdu.data, pin_len, session_rc);
|
||||
has_pw1 = has_pw3 = false;
|
||||
isUserAuthenticated = false;
|
||||
}
|
||||
@@ -58,25 +58,20 @@ int cmd_reset_retry() {
|
||||
if ((r = load_dek()) != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
file_t *tf = search_by_fid(EF_DEK_PW1, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (otp_key_1) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
dek[IV_SIZE + i] ^= otp_key_1[i];
|
||||
}
|
||||
}
|
||||
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
|
||||
memcpy(def, file_get_data(tf), file_get_size(tf));
|
||||
hash_multi(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pw1);
|
||||
memcpy(def + IV_SIZE, dek + IV_SIZE, 32);
|
||||
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
|
||||
uint8_t def[DEK_FILE_SIZE];
|
||||
def[0] = 0x03;
|
||||
pin_derive_session(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pw1);
|
||||
encrypt_with_aad(session_pw1, dek, DEK_SIZE, PIN_KDF_DEFAULT_VERSION, def + 1);
|
||||
r = file_put_data(tf, def, sizeof(def));
|
||||
|
||||
uint8_t dhash[33];
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = newpin_len;
|
||||
double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 2);
|
||||
file_put_data(pw, dhash, sizeof(dhash));
|
||||
if (pin_reset_retries(pw, true) != PICOKEY_OK) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_select() {
|
||||
int cmd_select(void) {
|
||||
uint8_t p1 = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
file_t *pe = NULL;
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_select_data() {
|
||||
int cmd_select_data(void) {
|
||||
file_t *ef = NULL;
|
||||
uint16_t fid = 0x0;
|
||||
if (P2(apdu) != 0x4) {
|
||||
@@ -26,7 +26,7 @@ int cmd_select_data() {
|
||||
if (apdu.data[0] != 0x60) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (apdu.nc != apdu.data[1] + 2 || apdu.nc < 5) {
|
||||
if (apdu.nc != (uint32_t) apdu.data[1] + 2u || apdu.nc < 5u) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
if (apdu.data[2] != 0x5C) {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_terminate_df() {
|
||||
int cmd_terminate_df(void) {
|
||||
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
#include "openpgp.h"
|
||||
|
||||
int cmd_verify() {
|
||||
int cmd_verify(void) {
|
||||
uint8_t p1 = P1(apdu);
|
||||
uint8_t p2 = P2(apdu);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#include "openpgp.h"
|
||||
#include "version.h"
|
||||
|
||||
int cmd_version_openpgp() {
|
||||
int cmd_version_openpgp(void) {
|
||||
res_APDU[res_APDU_size++] = PIPGP_VERSION_MAJOR;
|
||||
res_APDU[res_APDU_size++] = PIPGP_VERSION_MINOR;
|
||||
res_APDU[res_APDU_size++] = 0x0;
|
||||
|
||||
@@ -18,6 +18,20 @@
|
||||
#include "openpgp.h"
|
||||
#include "asn1.h"
|
||||
|
||||
int parse_trium(uint16_t fid, uint8_t num, size_t size);
|
||||
int parse_ch_data(const file_t *f, int mode);
|
||||
int parse_sec_tpl(const file_t *f, int mode);
|
||||
int parse_ch_cert(const file_t *f, int mode);
|
||||
int parse_fp(const file_t *f, int mode);
|
||||
int parse_cafp(const file_t *f, int mode);
|
||||
int parse_ts(const file_t *f, int mode);
|
||||
int parse_keyinfo(const file_t *f, int mode);
|
||||
int parse_pw_status(const file_t *f, int mode);
|
||||
int parse_algo(const uint8_t *algo, uint16_t tag);
|
||||
int parse_algoinfo(const file_t *f, int mode);
|
||||
int parse_app_data(const file_t *f, int mode);
|
||||
int parse_discrete_do(const file_t *f, int mode);
|
||||
|
||||
int parse_do(uint16_t *fids, int mode) {
|
||||
int len = 0;
|
||||
file_t *ef;
|
||||
@@ -25,7 +39,9 @@ int parse_do(uint16_t *fids, int mode) {
|
||||
if ((ef = search_by_fid(fids[i + 1], NULL, SPECIFY_EF))) {
|
||||
uint16_t data_len;
|
||||
if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
|
||||
data_len = ((int (*)(const file_t *, int))(ef->data))((const file_t *) ef, mode);
|
||||
int (*file_data_func)(const file_t *, int) = NULL;
|
||||
memcpy(&file_data_func, &ef->data, sizeof(file_data_func));
|
||||
data_len = file_data_func(ef, mode);
|
||||
}
|
||||
else {
|
||||
data_len = file_get_size(ef);
|
||||
@@ -69,6 +85,7 @@ int parse_trium(uint16_t fid, uint8_t num, size_t size) {
|
||||
}
|
||||
|
||||
int parse_ch_data(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
uint16_t fids[] = {
|
||||
3,
|
||||
EF_CH_NAME, EF_LANG_PREF, EF_SEX,
|
||||
@@ -85,6 +102,8 @@ int parse_ch_data(const file_t *f, int mode) {
|
||||
}
|
||||
|
||||
int parse_sec_tpl(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
(void) mode;
|
||||
res_APDU[res_APDU_size++] = EF_SEC_TPL & 0xff;
|
||||
res_APDU[res_APDU_size++] = 5;
|
||||
file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY);
|
||||
@@ -98,28 +117,38 @@ int parse_sec_tpl(const file_t *f, int mode) {
|
||||
}
|
||||
|
||||
int parse_ch_cert(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
(void) mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_fp(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
(void) mode;
|
||||
res_APDU[res_APDU_size++] = EF_FP & 0xff;
|
||||
res_APDU[res_APDU_size++] = 60;
|
||||
return parse_trium(EF_FP_SIG, 3, 20) + 2;
|
||||
}
|
||||
|
||||
int parse_cafp(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
(void) mode;
|
||||
res_APDU[res_APDU_size++] = EF_CA_FP & 0xff;
|
||||
res_APDU[res_APDU_size++] = 60;
|
||||
return parse_trium(EF_FP_CA1, 3, 20) + 2;
|
||||
}
|
||||
|
||||
int parse_ts(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
(void) mode;
|
||||
res_APDU[res_APDU_size++] = EF_TS_ALL & 0xff;
|
||||
res_APDU[res_APDU_size++] = 12;
|
||||
return parse_trium(EF_TS_SIG, 3, 4) + 2;
|
||||
}
|
||||
|
||||
int parse_keyinfo(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
(void) mode;
|
||||
int init_len = res_APDU_size;
|
||||
if (res_APDU_size > 0) {
|
||||
res_APDU[res_APDU_size++] = EF_KEY_INFO & 0xff;
|
||||
@@ -155,6 +184,8 @@ int parse_keyinfo(const file_t *f, int mode) {
|
||||
}
|
||||
|
||||
int parse_pw_status(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
(void) mode;
|
||||
file_t *ef;
|
||||
int init_len = res_APDU_size;
|
||||
if (res_APDU_size > 0) {
|
||||
@@ -278,6 +309,7 @@ int parse_algo(const uint8_t *algo, uint16_t tag) {
|
||||
}
|
||||
|
||||
int parse_algoinfo(const file_t *f, int mode) {
|
||||
(void) mode;
|
||||
int datalen = 0;
|
||||
if (f->fid == EF_ALGO_INFO) {
|
||||
res_APDU[res_APDU_size++] = EF_ALGO_INFO & 0xff;
|
||||
@@ -356,6 +388,7 @@ int parse_algoinfo(const file_t *f, int mode) {
|
||||
}
|
||||
|
||||
int parse_app_data(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
uint16_t fids[] = {
|
||||
6,
|
||||
EF_FULL_AID, EF_HIST_BYTES, EF_EXLEN_INFO, EF_GFM, EF_DISCRETE_DO, EF_KEY_INFO
|
||||
@@ -372,6 +405,7 @@ int parse_app_data(const file_t *f, int mode) {
|
||||
}
|
||||
|
||||
int parse_discrete_do(const file_t *f, int mode) {
|
||||
(void) f;
|
||||
uint16_t fids[] = {
|
||||
11,
|
||||
EF_EXT_CAP, EF_ALGO_SIG, EF_ALGO_DEC, EF_ALGO_AUT, EF_PW_STATUS, EF_FP, EF_CA_FP, EF_TS_ALL,
|
||||
|
||||
@@ -20,13 +20,6 @@
|
||||
extern const uint8_t openpgp_aid[];
|
||||
extern const uint8_t openpgp_aid_full[];
|
||||
|
||||
#define ACL_NONE { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }
|
||||
#define ACL_ALL { 0 }
|
||||
#define ACL_RO { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00 }
|
||||
#define ACL_RW { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00 }
|
||||
#define ACL_R_WP { 0xff, 0xff, 0xff, 0xff, 0x90, 0x90, 0x00 }
|
||||
#define ACL_WP { 0xff, 0xff, 0xff, 0xff, 0x90, 0x90, 0xff }
|
||||
|
||||
extern int parse_ch_data(const file_t *f, int mode);
|
||||
extern int parse_sec_tpl(const file_t *f, int mode);
|
||||
extern int parse_ch_cert(const file_t *f, int mode);
|
||||
@@ -55,12 +48,12 @@ uint8_t historical_bytes[] = {
|
||||
|
||||
uint8_t extended_capabilities[] = {
|
||||
10, 0,
|
||||
0x77, /*
|
||||
0x7f, /*
|
||||
* No Secure Messaging supported
|
||||
* GET CHALLENGE supported
|
||||
* Key import supported
|
||||
* PW status byte can be put
|
||||
* No private_use_DO
|
||||
* private_use_DO
|
||||
* Algorithm attrs are changable
|
||||
* ENC/DEC with AES
|
||||
* KDF-DO available
|
||||
@@ -68,7 +61,7 @@ uint8_t extended_capabilities[] = {
|
||||
0, /* Secure Messaging Algorithm: N/A (TDES=0, AES=1) */
|
||||
0x00, 128, /* Max size of GET CHALLENGE */
|
||||
0x08, 0x00, /* max. length of cardholder certificate (2KiB) */
|
||||
0x00, 0xff,
|
||||
0x08, 0x00, /* max. length of private DO (2KiB) */
|
||||
0x00, 0x1
|
||||
};
|
||||
|
||||
@@ -114,7 +107,7 @@ file_t file_entries[] = {
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
|
||||
/* 10 */ { .fid = EF_CH_CERT, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_ch_cert,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
/* 11 */ { .fid = EF_EXLEN_INFO, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF,
|
||||
.data = exlen_info, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
|
||||
/* 12 */ { .fid = EF_GFM, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF,
|
||||
@@ -250,236 +243,263 @@ file_t file_entries[] = {
|
||||
/* 56 */ { .fid = EF_CH_3, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.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,
|
||||
/* 57 */ { .fid = EF_DEK_PW1, .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,
|
||||
/* 58 */ { .fid = EF_DEK_RC, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
|
||||
/* 59 */ { .fid = EF_DEK_PW3, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
|
||||
// ** PIV ** //
|
||||
/* 60 */ { .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 },
|
||||
/* 61 */ { .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 },
|
||||
/* 62 */ { .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 },
|
||||
/* 63 */ { .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 },
|
||||
/* 64 */ { .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 },
|
||||
/* 65 */ { .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 },
|
||||
/* 66 */ { .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 },
|
||||
/* 67 */ { .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 },
|
||||
/* 68 */ { .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 },
|
||||
/* 69 */ { .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 },
|
||||
/* 70 */ { .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 },
|
||||
/* 71 */ { .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 },
|
||||
/* 72 */ { .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 },
|
||||
/* 73 */ { .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 },
|
||||
/* 74 */ { .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 },
|
||||
/* 75 */ { .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 },
|
||||
/* 76 */ { .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 },
|
||||
/* 77 */ { .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 },
|
||||
/* 78 */ { .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 },
|
||||
/* 79 */ { .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 },
|
||||
/* 80 */ { .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 },
|
||||
/* 81 */ { .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 },
|
||||
/* 82 */ { .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 },
|
||||
/* 83 */ { .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 },
|
||||
/* 84 */ { .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 },
|
||||
/* 85 */ { .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 },
|
||||
/* 86 */ { .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 },
|
||||
/* 87 */ { .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 },
|
||||
/* 88 */ { .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 },
|
||||
/* 89 */ { .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 },
|
||||
/* 90 */ { .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 },
|
||||
/* 91 */ { .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 },
|
||||
/* 92 */ { .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 },
|
||||
/* 93 */ { .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 },
|
||||
/* 94 */ { .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 },
|
||||
/* 95 */ { .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 },
|
||||
/* 96 */ { .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 },
|
||||
/* 97 */ { .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 },
|
||||
/* 98 */ { .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 },
|
||||
/* 99 */ { .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 },
|
||||
/* 100 */ { .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 },
|
||||
/* 101 */ { .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 },
|
||||
/* 102 */ { .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 },
|
||||
/* 103 */ { .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 },
|
||||
/* 104 */ { .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 },
|
||||
/* 105 */ { .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 },
|
||||
/* 106 */ { .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 },
|
||||
/* 107 */ { .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 },
|
||||
/* 108 */ { .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 },
|
||||
/* 109 */ { .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 },
|
||||
/* 110 */ { .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 },
|
||||
/* 111 */ { .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 },
|
||||
/* 112 */ { .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 },
|
||||
/* 113 */ { .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 },
|
||||
/* 114 */ { .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 },
|
||||
/* 115 */ { .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 },
|
||||
/* 116 */ { .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 },
|
||||
/* 117 */ { .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 },
|
||||
/* 118 */ { .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 },
|
||||
/* 119 */ { .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 },
|
||||
/* 120 */ { .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 },
|
||||
/* 121 */ { .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 },
|
||||
/* 122 */ { .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 },
|
||||
/* 123 */ { .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 },
|
||||
/* 124 */ { .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 },
|
||||
/* 125 */ { .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 },
|
||||
/* 126 */ { .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 },
|
||||
/* 127 */ { .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 },
|
||||
/* 128 */ { .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 },
|
||||
/* 129 */ { .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 },
|
||||
/* 130 */ { .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 },
|
||||
/* 131 */ { .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 },
|
||||
/* 132 */ { .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 },
|
||||
/* 133 */ { .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 },
|
||||
/* 134 */ { .fid = EF_PRIV_DO_1, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
/* 135 */ { .fid = EF_PRIV_DO_2, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
/* 136 */ { .fid = EF_PRIV_DO_3, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||
/* 137 */ { .fid = EF_PRIV_DO_4, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_WP },
|
||||
/* 138 */ { .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 },
|
||||
/* 139 */ { .fid = EF_PW_STATUS, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_R_WP },
|
||||
/* 140 */ { .fid = EF_DEK_PWPIV, .parent = 0, .name = NULL,
|
||||
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL,
|
||||
.ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_NONE },
|
||||
|
||||
/* 132 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
|
||||
/* 141 */ { .fid = 0x0000, .parent = 0, .name = openpgp_aid, .type = FILE_TYPE_WORKING_EF,
|
||||
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = ACL_RO },
|
||||
/* 133 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL,
|
||||
/* 142 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL,
|
||||
.ef_structure = 0, .acl = ACL_NONE } //end
|
||||
};
|
||||
|
||||
|
||||
@@ -36,6 +36,10 @@
|
||||
#define EF_PB_DEC 0x10d5
|
||||
#define EF_PB_AUT 0x10d6
|
||||
#define EF_DEK 0x1099
|
||||
#define EF_DEK_PW1 0x109a
|
||||
#define EF_DEK_RC 0x109b
|
||||
#define EF_DEK_PW3 0x109c
|
||||
#define EF_DEK_PWPIV 0x109d
|
||||
#define EF_CH_1 0x1f21
|
||||
#define EF_CH_2 0x1f22
|
||||
#define EF_CH_3 0x1f23
|
||||
@@ -163,4 +167,9 @@
|
||||
|
||||
#define EF_DEV_CONF 0x1122
|
||||
|
||||
#define EF_PRIV_DO_1 0x0101
|
||||
#define EF_PRIV_DO_2 0x0102
|
||||
#define EF_PRIV_DO_3 0x0103
|
||||
#define EF_PRIV_DO_4 0x0104
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,16 +24,16 @@
|
||||
|
||||
bool is_gpg = true;
|
||||
|
||||
int man_process_apdu();
|
||||
int man_unload();
|
||||
static int man_process_apdu(void);
|
||||
static int man_unload(void);
|
||||
|
||||
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) {
|
||||
extern void init_piv(void);
|
||||
static int man_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
a->process_apdu = man_process_apdu;
|
||||
a->unload = man_unload;
|
||||
@@ -49,7 +49,7 @@ INITIALIZER( man_ctor ) {
|
||||
register_app(man_select, man_aid);
|
||||
}
|
||||
|
||||
int man_unload() {
|
||||
static int man_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ bool cap_supported(uint16_t cap) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int man_get_config() {
|
||||
int man_get_config(void) {
|
||||
file_t *ef = search_dynamic_file(EF_DEV_CONF);
|
||||
res_APDU_size = 0;
|
||||
res_APDU[res_APDU_size++] = 0; // Overall length. Filled later
|
||||
@@ -118,12 +118,12 @@ int man_get_config() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cmd_read_config() {
|
||||
static int cmd_read_config(void) {
|
||||
man_get_config();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_write_config() {
|
||||
static int cmd_write_config(void) {
|
||||
if (apdu.data[0] != apdu.nc - 1) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
@@ -142,7 +142,7 @@ static const cmd_t cmds[] = {
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int man_process_apdu() {
|
||||
static int man_process_apdu(void) {
|
||||
if (CLA(apdu) != 0x00) {
|
||||
return SW_CLA_NOT_SUPPORTED();
|
||||
}
|
||||
|
||||
@@ -50,6 +50,6 @@
|
||||
#define FLAG_EJECT 0x80
|
||||
|
||||
extern bool cap_supported(uint16_t cap);
|
||||
extern int man_get_config();
|
||||
extern int man_get_config(void);
|
||||
|
||||
#endif //_MANAGEMENT_H
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_compat.h"
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#else
|
||||
#include "common.h"
|
||||
#endif
|
||||
#include "openpgp.h"
|
||||
#include "version.h"
|
||||
@@ -41,7 +39,7 @@ bool has_rc = false;
|
||||
uint8_t session_pw1[32];
|
||||
uint8_t session_rc[32];
|
||||
uint8_t session_pw3[32];
|
||||
uint8_t dek[IV_SIZE + 32];
|
||||
uint8_t dek[DEK_SIZE];
|
||||
uint16_t algo_dec = EF_ALGO_PRIV2, algo_aut = EF_ALGO_PRIV3, pk_dec = EF_PK_DEC, pk_aut = EF_PK_AUT;
|
||||
|
||||
uint8_t openpgp_aid[] = {
|
||||
@@ -61,7 +59,7 @@ char atr_openpgp[] = {
|
||||
0x60, 0x00, 0x90, 0x00, 0x1c
|
||||
};
|
||||
|
||||
int openpgp_process_apdu();
|
||||
int openpgp_process_apdu(void);
|
||||
|
||||
extern uint32_t board_button_read(void);
|
||||
|
||||
@@ -75,6 +73,8 @@ bool wait_button_pressed_fid(uint16_t fid) {
|
||||
queue_remove_blocking(&usb_to_card_q, &val);
|
||||
}while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT);
|
||||
}
|
||||
#else
|
||||
(void) fid;
|
||||
#endif
|
||||
return val == EV_BUTTON_TIMEOUT;
|
||||
}
|
||||
@@ -97,7 +97,7 @@ void select_file(file_t *pe) {
|
||||
}
|
||||
}
|
||||
|
||||
void scan_files_openpgp() {
|
||||
void scan_files_openpgp(void) {
|
||||
scan_flash();
|
||||
file_t *ef;
|
||||
if ((ef = search_by_fid(EF_FULL_AID, NULL, SPECIFY_ANY))) {
|
||||
@@ -105,17 +105,20 @@ void scan_files_openpgp() {
|
||||
memcpy(ef->data + 12, pico_serial.id, 4);
|
||||
}
|
||||
bool reset_dek = false;
|
||||
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY))) {
|
||||
if (!ef->data) {
|
||||
printf("DEK is empty\r\n");
|
||||
const uint8_t def1[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
|
||||
bool bootstrap_legacy = false;
|
||||
file_t *ef_dek = search_by_fid(EF_DEK, NULL, SPECIFY_ANY), *ef_dek_pw1 = search_by_fid(EF_DEK_PW1, NULL, SPECIFY_ANY), *ef_dek_rc = search_by_fid(EF_DEK_RC, NULL, SPECIFY_ANY), *ef_dek_pw3 = search_by_fid(EF_DEK_PW3, NULL, SPECIFY_ANY);
|
||||
if (!file_has_data(ef_dek_pw1) && !file_has_data(ef_dek_rc) && !file_has_data(ef_dek_pw3) && !file_has_data(ef_dek)) {
|
||||
printf("DEK are empty\r\n");
|
||||
const uint8_t *random_dek = random_bytes_get(DEK_SIZE);
|
||||
const uint8_t def1[6] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36};
|
||||
const uint8_t def3[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38 };
|
||||
#ifdef OPENPGP_TEST_INIT_LEGACY_PIN
|
||||
/* Test hook: bootstrap legacy PIN+DEK format to validate runtime migration paths. */
|
||||
|
||||
uint8_t def[IV_SIZE + 32 + 32 + 32];
|
||||
const uint8_t *dek = random_bytes_get(IV_SIZE + 32);
|
||||
memcpy(def, dek, IV_SIZE + 32);
|
||||
memcpy(def + IV_SIZE + 32, dek + IV_SIZE, 32);
|
||||
memcpy(def + IV_SIZE + 32 + 32, dek + IV_SIZE, 32);
|
||||
memcpy(def, random_dek, IV_SIZE + 32);
|
||||
memcpy(def + IV_SIZE + 32, random_dek + IV_SIZE, 32);
|
||||
memcpy(def + IV_SIZE + 32 + 32, random_dek + IV_SIZE, 32);
|
||||
hash_multi(def1, sizeof(def1), session_pw1);
|
||||
aes_encrypt_cfb_256(session_pw1, def, def + IV_SIZE, 32);
|
||||
memset(session_pw1, 0, sizeof(session_pw1));
|
||||
@@ -124,42 +127,82 @@ void scan_files_openpgp() {
|
||||
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);
|
||||
memset(session_pw3, 0, sizeof(session_pw3));
|
||||
file_put_data(ef, def, sizeof(def));
|
||||
file_put_data(ef_dek, def, sizeof(def));
|
||||
bootstrap_legacy = true;
|
||||
#else
|
||||
uint8_t def[DEK_FILE_SIZE];
|
||||
def[0] = 0x3; // Format
|
||||
|
||||
pin_derive_session(def1, sizeof(def1), session_pw1);
|
||||
encrypt_with_aad(session_pw1, random_dek, DEK_SIZE, PIN_KDF_DEFAULT_VERSION, def + 1);
|
||||
mbedtls_platform_zeroize(session_pw1, sizeof(session_pw1));
|
||||
file_put_data(ef_dek_pw1, def, sizeof(def));
|
||||
|
||||
pin_derive_session(def3, sizeof(def3), session_pw3);
|
||||
encrypt_with_aad(session_pw3, random_dek, DEK_SIZE, PIN_KDF_DEFAULT_VERSION, def + 1);
|
||||
mbedtls_platform_zeroize(session_pw3, sizeof(session_pw3));
|
||||
file_put_data(ef_dek_rc, def, sizeof(def));
|
||||
file_put_data(ef_dek_pw3, def, sizeof(def));
|
||||
#endif
|
||||
|
||||
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];
|
||||
uint8_t dhash[34];
|
||||
if (bootstrap_legacy) {
|
||||
dhash[0] = sizeof(def);
|
||||
double_hash_pin(def, sizeof(def), dhash + 1);
|
||||
file_put_data(ef, dhash, 33);
|
||||
}
|
||||
else {
|
||||
dhash[0] = sizeof(def);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(def, sizeof(def), dhash + 2);
|
||||
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];
|
||||
uint8_t dhash[34];
|
||||
if (bootstrap_legacy) {
|
||||
dhash[0] = sizeof(def);
|
||||
double_hash_pin(def, sizeof(def), dhash + 1);
|
||||
file_put_data(ef, dhash, 33);
|
||||
}
|
||||
else {
|
||||
dhash[0] = sizeof(def);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(def, sizeof(def), dhash + 2);
|
||||
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];
|
||||
uint8_t dhash[34];
|
||||
if (bootstrap_legacy) {
|
||||
dhash[0] = sizeof(def);
|
||||
double_hash_pin(def, sizeof(def), dhash + 1);
|
||||
file_put_data(ef, dhash, 33);
|
||||
}
|
||||
else {
|
||||
dhash[0] = sizeof(def);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(def, sizeof(def), dhash + 2);
|
||||
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");
|
||||
@@ -219,44 +262,87 @@ void scan_files_openpgp() {
|
||||
low_flash_available();
|
||||
}
|
||||
|
||||
void release_dek() {
|
||||
static void release_dek(void) {
|
||||
memset(dek, 0, sizeof(dek));
|
||||
}
|
||||
|
||||
extern bool has_pwpiv;
|
||||
extern uint8_t session_pwpiv[32];
|
||||
int load_dek() {
|
||||
int load_dek(void) {
|
||||
if (!has_pw1 && !has_pw2 && !has_pw3 && !has_pwpiv) {
|
||||
return PICOKEY_NO_LOGIN;
|
||||
}
|
||||
int r = PICOKEY_OK;
|
||||
|
||||
if (has_pw1 || has_pw2) {
|
||||
file_t *ef_dek_pw1 = search_file(EF_DEK_PW1);
|
||||
if (file_has_data(ef_dek_pw1)) {
|
||||
uint8_t *ef_data = file_get_data(ef_dek_pw1);
|
||||
if (ef_data[0] == 0x3) { // Format
|
||||
r = decrypt_with_aad(session_pw1, ef_data + 1, DEK_AAD_SIZE, PIN_KDF_DEFAULT_VERSION, dek);
|
||||
}
|
||||
else {
|
||||
return PICOKEY_ERR_NULL_PARAM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
int r = PICOKEY_OK;
|
||||
if (has_pw1 || has_pw2) {
|
||||
|
||||
memcpy(dek, file_get_data(tf), IV_SIZE + 32);
|
||||
r = aes_decrypt_cfb_256(session_pw1, dek, dek + IV_SIZE, 32);
|
||||
}
|
||||
}
|
||||
else if (has_pw3) {
|
||||
file_t *ef_dek_pw3 = search_file(EF_DEK_PW3);
|
||||
if (file_has_data(ef_dek_pw3)) {
|
||||
uint8_t *ef_data = file_get_data(ef_dek_pw3);
|
||||
if (ef_data[0] == 0x3) { // Format
|
||||
r = decrypt_with_aad(session_pw3, ef_data + 1, DEK_AAD_SIZE, PIN_KDF_DEFAULT_VERSION, dek);
|
||||
}
|
||||
else {
|
||||
return PICOKEY_ERR_NULL_PARAM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
memcpy(dek, file_get_data(tf), IV_SIZE);
|
||||
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);
|
||||
}
|
||||
}
|
||||
else if (has_pwpiv) {
|
||||
file_t *ef_dek_pwpiv = search_file(EF_DEK_PWPIV);
|
||||
if (file_has_data(ef_dek_pwpiv)) {
|
||||
uint8_t *ef_data = file_get_data(ef_dek_pwpiv);
|
||||
if (ef_data[0] == 0x3) { // Format
|
||||
r = decrypt_with_aad(session_pwpiv, ef_data + 1, DEK_AAD_SIZE, PIN_KDF_DEFAULT_VERSION, dek);
|
||||
}
|
||||
else {
|
||||
return PICOKEY_ERR_NULL_PARAM;
|
||||
}
|
||||
}
|
||||
else {
|
||||
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (!tf) {
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
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) {
|
||||
release_dek();
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
}
|
||||
if (otp_key_1) {
|
||||
for (int i = 0; i < 32; i++) {
|
||||
dek[IV_SIZE + i] ^= otp_key_1[i];
|
||||
}
|
||||
}
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
@@ -280,9 +366,9 @@ int dek_decrypt(uint8_t *data, size_t len) {
|
||||
return r;
|
||||
}
|
||||
|
||||
void init_openpgp() {
|
||||
static void init_openpgp(void) {
|
||||
isUserAuthenticated = false;
|
||||
has_pw1 = has_pw3 = false;
|
||||
has_pw1 = has_pw2 = has_pw3 = false;
|
||||
algo_dec = EF_ALGO_PRIV2;
|
||||
algo_aut = EF_ALGO_PRIV3;
|
||||
pk_dec = EF_PK_DEC;
|
||||
@@ -291,9 +377,9 @@ void init_openpgp() {
|
||||
//cmd_select();
|
||||
}
|
||||
|
||||
int openpgp_unload() {
|
||||
static int openpgp_unload(void) {
|
||||
isUserAuthenticated = false;
|
||||
has_pw1 = has_pw3 = false;
|
||||
has_pw1 = has_pw2 = has_pw3 = false;
|
||||
algo_dec = EF_ALGO_PRIV2;
|
||||
algo_aut = EF_ALGO_PRIV3;
|
||||
pk_dec = EF_PK_DEC;
|
||||
@@ -302,7 +388,7 @@ int openpgp_unload() {
|
||||
}
|
||||
|
||||
extern char __StackLimit;
|
||||
int heapLeft() {
|
||||
static int heapLeft(void) {
|
||||
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
|
||||
char *p = malloc(256); // try to avoid undue fragmentation
|
||||
int left = &__StackLimit - p;
|
||||
@@ -313,7 +399,7 @@ int heapLeft() {
|
||||
return left;
|
||||
}
|
||||
|
||||
int openpgp_select_aid(app_t *a, uint8_t force) {
|
||||
static int openpgp_select_aid(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
a->process_apdu = openpgp_process_apdu;
|
||||
a->unload = openpgp_unload;
|
||||
@@ -361,7 +447,7 @@ int pin_reset_retries(const file_t *pin, bool force) {
|
||||
return r;
|
||||
}
|
||||
|
||||
int pin_wrong_retry(const file_t *pin) {
|
||||
static int pin_wrong_retry(const file_t *pin) {
|
||||
if (!pin) {
|
||||
return PICOKEY_ERR_NULL_PARAM;
|
||||
}
|
||||
@@ -387,21 +473,24 @@ int pin_wrong_retry(const file_t *pin) {
|
||||
}
|
||||
|
||||
int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
|
||||
if (!pin) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
if (!pin->data) {
|
||||
if (!file_has_data(pin)) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
}
|
||||
isUserAuthenticated = false;
|
||||
//has_pw1 = has_pw3 = false;
|
||||
|
||||
uint8_t dhash[32];
|
||||
uint8_t dhash[32], off = 2;
|
||||
if (file_get_size(pin) == 33) {
|
||||
off = 1;
|
||||
double_hash_pin(data, len, dhash);
|
||||
if (sizeof(dhash) != file_get_size(pin) - 1) { //1 byte for pin len
|
||||
}
|
||||
else {
|
||||
pin_derive_verifier(data, len, dhash);
|
||||
}
|
||||
if (sizeof(dhash) != file_get_size(pin) - off) { //1 byte for pin len and 1 byte for format
|
||||
return SW_CONDITIONS_NOT_SATISFIED();
|
||||
}
|
||||
if (memcmp(file_get_data(pin) + 1, dhash, sizeof(dhash)) != 0) {
|
||||
if (memcmp(file_get_data(pin) + off, dhash, sizeof(dhash)) != 0) {
|
||||
int retries;
|
||||
if ((retries = pin_wrong_retry(pin)) < PICOKEY_OK) {
|
||||
return SW_PIN_BLOCKED();
|
||||
@@ -416,6 +505,75 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
if (off == 1) {
|
||||
uint8_t pin_data[34], *pin_sp = NULL;
|
||||
pin_data[0] = len;
|
||||
pin_data[1] = 0x1; // Format
|
||||
pin_derive_verifier(data, len, pin_data + 2);
|
||||
file_put_data((file_t *)pin, pin_data, sizeof(pin_data));
|
||||
has_pw1 = has_pw2 = has_pw3 = false;
|
||||
|
||||
if (pin->fid == EF_PW1) {
|
||||
if (P2(apdu) == 0x81) {
|
||||
has_pw1 = true;
|
||||
}
|
||||
else {
|
||||
has_pw2 = true;
|
||||
}
|
||||
pin_sp = session_pw1;
|
||||
}
|
||||
else if (pin->fid == EF_PW3) {
|
||||
has_pw3 = true;
|
||||
pin_sp = session_pw3;
|
||||
}
|
||||
else if (pin->fid == EF_PIV_PIN) {
|
||||
has_pwpiv = true;
|
||||
pin_sp = session_pwpiv;
|
||||
}
|
||||
if (pin_sp) {
|
||||
hash_multi(data, len, pin_sp);
|
||||
r = load_dek();
|
||||
if (r != PICOKEY_OK) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
uint8_t old_data[DEK_FILE_SIZE_OLD], ef_data[DEK_FILE_SIZE];
|
||||
file_t *ef_dek_pw = NULL;
|
||||
if (has_pw1 || has_pw2) {
|
||||
ef_dek_pw = search_by_fid(EF_DEK_PW1, NULL, SPECIFY_EF);
|
||||
}
|
||||
else if (has_pw3) {
|
||||
ef_dek_pw = search_by_fid(EF_DEK_PW3, NULL, SPECIFY_EF);
|
||||
}
|
||||
else if (has_pwpiv) {
|
||||
ef_dek_pw = search_by_fid(EF_DEK_PWPIV, NULL, SPECIFY_EF);
|
||||
}
|
||||
if (!ef_dek_pw) {
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
ef_data[0] = 0x3; // Format
|
||||
pin_derive_session(data, len, pin_sp);
|
||||
encrypt_with_aad(pin_sp, dek, DEK_SIZE, PIN_KDF_DEFAULT_VERSION, ef_data + 1);
|
||||
file_put_data(ef_dek_pw, ef_data, sizeof(ef_data));
|
||||
|
||||
file_t *ef_dek = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
|
||||
if (!ef_dek) {
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
memcpy(old_data, file_get_data(ef_dek), sizeof(old_data));
|
||||
if (has_pw1 || has_pw2) {
|
||||
memset(old_data + IV_SIZE, 0, 32);
|
||||
}
|
||||
else if (has_pw3) {
|
||||
memset(old_data + IV_SIZE + 32 + 32, 0, 32);
|
||||
}
|
||||
else if (has_pwpiv) {
|
||||
memset(old_data + IV_SIZE + 32 + 32 + 32, 0, 32);
|
||||
}
|
||||
file_put_data(ef_dek, old_data, sizeof(old_data));
|
||||
low_flash_available();
|
||||
}
|
||||
has_pw1 = has_pw2 = has_pw3 = false;
|
||||
}
|
||||
isUserAuthenticated = true;
|
||||
if (pin->fid == EF_PW1) {
|
||||
if (P2(apdu) == 0x81) {
|
||||
@@ -424,16 +582,16 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
|
||||
else {
|
||||
has_pw2 = true;
|
||||
}
|
||||
hash_multi(data, len, session_pw1);
|
||||
pin_derive_session(data, len, session_pw1);
|
||||
}
|
||||
else if (pin->fid == EF_PW3) {
|
||||
has_pw3 = true;
|
||||
hash_multi(data, len, session_pw3);
|
||||
pin_derive_session(data, len, session_pw3);
|
||||
}
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int inc_sig_count() {
|
||||
int inc_sig_count(void) {
|
||||
file_t *pw_status;
|
||||
if (!(pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF)) || !pw_status->data) {
|
||||
return SW_REFERENCE_NOT_FOUND();
|
||||
@@ -457,7 +615,7 @@ int inc_sig_count() {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
int reset_sig_count() {
|
||||
int reset_sig_count(void) {
|
||||
file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY);
|
||||
if (!ef || !ef->data) {
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
@@ -656,12 +814,7 @@ void make_rsa_response(mbedtls_rsa_context *rsa) {
|
||||
void make_ecdsa_response(mbedtls_ecp_keypair *ecdsa) {
|
||||
uint8_t pt[MBEDTLS_ECP_MAX_PT_LEN];
|
||||
size_t plen = 0;
|
||||
mbedtls_ecp_point_write_binary(&ecdsa->grp,
|
||||
&ecdsa->Q,
|
||||
MBEDTLS_ECP_PF_UNCOMPRESSED,
|
||||
&plen,
|
||||
pt,
|
||||
sizeof(pt));
|
||||
mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &plen, pt, sizeof(pt));
|
||||
res_APDU[res_APDU_size++] = 0x7f;
|
||||
res_APDU[res_APDU_size++] = 0x49;
|
||||
if (plen >= 128) {
|
||||
@@ -677,17 +830,13 @@ void make_ecdsa_response(mbedtls_ecp_keypair *ecdsa) {
|
||||
res_APDU_size += plen;
|
||||
}
|
||||
|
||||
int rsa_sign(mbedtls_rsa_context *ctx,
|
||||
const uint8_t *data,
|
||||
size_t data_len,
|
||||
uint8_t *out,
|
||||
size_t *out_len) {
|
||||
int rsa_sign(mbedtls_rsa_context *ctx, const uint8_t *data, size_t data_len, uint8_t *out, size_t *out_len) {
|
||||
uint8_t *d = (uint8_t *) data, *end = d + data_len, *hsh = NULL;
|
||||
size_t seq_len = 0, hash_len = 0;
|
||||
int key_size = ctx->len, r = 0;
|
||||
size_t key_size = ctx->len;
|
||||
int r = 0;
|
||||
mbedtls_md_type_t md = MBEDTLS_MD_NONE;
|
||||
if (mbedtls_asn1_get_tag(&d, end, &seq_len,
|
||||
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0) {
|
||||
if (mbedtls_asn1_get_tag(&d, end, &seq_len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE) == 0) {
|
||||
mbedtls_asn1_buf mdb;
|
||||
r = mbedtls_asn1_get_alg_null(&d, end, &mdb);
|
||||
if (r == 0) {
|
||||
@@ -746,11 +895,7 @@ int rsa_sign(mbedtls_rsa_context *ctx,
|
||||
return r;
|
||||
}
|
||||
|
||||
int ecdsa_sign(mbedtls_ecp_keypair *ctx,
|
||||
const uint8_t *data,
|
||||
size_t data_len,
|
||||
uint8_t *out,
|
||||
size_t *out_len) {
|
||||
int ecdsa_sign(mbedtls_ecp_keypair *ctx, const uint8_t *data, size_t data_len, uint8_t *out, size_t *out_len) {
|
||||
|
||||
int r = 0;
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
@@ -776,24 +921,6 @@ int ecdsa_sign(mbedtls_ecp_keypair *ctx,
|
||||
return r;
|
||||
}
|
||||
|
||||
extern int cmd_select();
|
||||
extern int cmd_get_data();
|
||||
extern int cmd_get_next_data();
|
||||
extern int cmd_put_data();
|
||||
extern int cmd_verify();
|
||||
extern int cmd_select_data();
|
||||
extern int cmd_version_openpgp();
|
||||
extern int cmd_import_data();
|
||||
extern int cmd_change_pin();
|
||||
extern int cmd_mse();
|
||||
extern int cmd_internal_aut();
|
||||
extern int cmd_challenge();
|
||||
extern int cmd_activate_file();
|
||||
extern int cmd_terminate_df();
|
||||
extern int cmd_pso();
|
||||
extern int cmd_keypair_gen();
|
||||
extern int cmd_reset_retry();
|
||||
|
||||
#define INS_VERIFY 0x20
|
||||
#define INS_MSE 0x22
|
||||
#define INS_CHANGE_PIN 0x24
|
||||
@@ -807,6 +934,7 @@ extern int cmd_reset_retry();
|
||||
#define INS_SELECT_DATA 0xA5
|
||||
#define INS_GET_DATA 0xCA
|
||||
#define INS_GET_NEXT_DATA 0xCC
|
||||
#define INS_GET_BULK_DATA 0xCE
|
||||
#define INS_PUT_DATA 0xDA
|
||||
#define INS_IMPORT_DATA 0xDB
|
||||
#define INS_TERMINATE_DF 0xE6
|
||||
@@ -830,10 +958,11 @@ static const cmd_t cmds[] = {
|
||||
{ INS_VERSION, cmd_version_openpgp },
|
||||
{ INS_SELECT_DATA, cmd_select_data },
|
||||
{ INS_GET_NEXT_DATA, cmd_get_next_data },
|
||||
{ 0x00, 0x0 }
|
||||
{ INS_GET_BULK_DATA, cmd_get_bulk_data },
|
||||
{ 0x00, NULL }
|
||||
};
|
||||
|
||||
int openpgp_process_apdu() {
|
||||
int openpgp_process_apdu(void) {
|
||||
sm_unwrap();
|
||||
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
|
||||
if (cmd->ins == INS(apdu)) {
|
||||
|
||||
@@ -67,16 +67,41 @@ extern int pin_reset_retries(const file_t *pin, bool force);
|
||||
|
||||
extern void select_file(file_t *pe);
|
||||
extern int parse_do(uint16_t *fids, int mode);
|
||||
extern int load_dek();
|
||||
extern int load_dek(void);
|
||||
extern int check_pin(const file_t *pin, const uint8_t *data, size_t len);
|
||||
extern mbedtls_ecp_group_id get_ec_group_id_from_attr(const uint8_t *algo, size_t algo_len);
|
||||
extern int reset_sig_count();
|
||||
extern int reset_sig_count(void);
|
||||
extern uint16_t algo_dec, algo_aut, pk_dec, pk_aut;
|
||||
extern bool wait_button_pressed_fid(uint16_t fid);
|
||||
extern void scan_files_openpgp();
|
||||
extern void scan_files_openpgp(void);
|
||||
extern int load_aes_key(uint8_t *aes_key, file_t *fkey);
|
||||
extern int inc_sig_count();
|
||||
extern int inc_sig_count(void);
|
||||
extern int dek_encrypt(uint8_t *data, size_t len);
|
||||
extern int dek_decrypt(uint8_t *data, size_t len);
|
||||
|
||||
int cmd_select(void);
|
||||
int cmd_get_data(void);
|
||||
int cmd_get_next_data(void);
|
||||
int cmd_put_data(void);
|
||||
int cmd_verify(void);
|
||||
int cmd_select_data(void);
|
||||
int cmd_version_openpgp(void);
|
||||
int cmd_import_data(void);
|
||||
int cmd_change_pin(void);
|
||||
int cmd_mse(void);
|
||||
int cmd_internal_aut(void);
|
||||
int cmd_challenge(void);
|
||||
int cmd_activate_file(void);
|
||||
int cmd_terminate_df(void);
|
||||
int cmd_pso(void);
|
||||
int cmd_keypair_gen(void);
|
||||
int cmd_reset_retry(void);
|
||||
int cmd_get_bulk_data(void);
|
||||
|
||||
#define DEK_SIZE (IV_SIZE + 32)
|
||||
#define DEK_AAD_SIZE (PIN_KDF_SIZE(DEK_SIZE))
|
||||
#define DEK_FILE_SIZE (1 + DEK_AAD_SIZE)
|
||||
|
||||
#define DEK_FILE_SIZE_OLD (IV_SIZE + 32 + 32 + 32 + 32)
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
#ifdef ESP_PLATFORM
|
||||
#include "esp_compat.h"
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#else
|
||||
#include "common.h"
|
||||
#endif
|
||||
#include "files.h"
|
||||
#include "apdu.h"
|
||||
@@ -76,9 +74,11 @@ uint8_t yk_aid[] = {
|
||||
bool has_pwpiv = false;
|
||||
uint8_t session_pwpiv[32];
|
||||
|
||||
int piv_process_apdu();
|
||||
int piv_process_apdu(void);
|
||||
void init_piv(void);
|
||||
int piv_parse_discovery(const file_t *ef);
|
||||
|
||||
static int get_serial() {
|
||||
static int get_serial(void) {
|
||||
uint32_t serial = (pico_serial.id[0] & 0x7F) << 24 | pico_serial.id[1] << 16 | pico_serial.id[2] << 8 | pico_serial.id[3];
|
||||
return serial;
|
||||
}
|
||||
@@ -116,15 +116,15 @@ static int x509_create_cert(void *pk_ctx, uint8_t algo, uint8_t slot, bool attes
|
||||
mbedtls_x509write_crt_set_issuer_key(&ctx, &ikey);
|
||||
uint8_t ver[] = {PIV_VERSION_MAJOR, PIV_VERSION_MINOR, 0};
|
||||
mbedtls_x509write_crt_set_extension(&ctx, "\x2B\x06\x01\x04\x01\x82\xC4\x0A\x03\x03", 10, 0, ver, sizeof(ver));
|
||||
uint32_t serial = get_serial();
|
||||
mbedtls_x509write_crt_set_extension(&ctx, "\x2B\x06\x01\x04\x01\x82\xC4\x0A\x03\x07", 10, 0, (const uint8_t *)&serial, sizeof(serial));
|
||||
uint32_t device_serial = get_serial();
|
||||
mbedtls_x509write_crt_set_extension(&ctx, "\x2B\x06\x01\x04\x01\x82\xC4\x0A\x03\x07", 10, 0, (const uint8_t *)&device_serial, sizeof(device_serial));
|
||||
int meta_len = 0;
|
||||
uint8_t *meta;
|
||||
if ((meta_len = meta_find(slot, &meta)) >= 0) {
|
||||
mbedtls_x509write_crt_set_extension(&ctx, "\x2B\x06\x01\x04\x01\x82\xC4\x0A\x03\x08", 10, 0, &meta[1], 2);
|
||||
}
|
||||
uint8_t v = 1;
|
||||
mbedtls_x509write_crt_set_extension(&ctx, "\x2B\x06\x01\x04\x01\x82\xC4\x0A\x03\x09", 10, 0, &v, sizeof(serial));
|
||||
mbedtls_x509write_crt_set_extension(&ctx, "\x2B\x06\x01\x04\x01\x82\xC4\x0A\x03\x09", 10, 0, &v, sizeof(v));
|
||||
}
|
||||
else {
|
||||
uint8_t wslot = slot;
|
||||
@@ -153,9 +153,7 @@ static int x509_create_cert(void *pk_ctx, uint8_t algo, uint8_t slot, bool attes
|
||||
}
|
||||
mbedtls_x509write_crt_set_subject_key_identifier(&ctx);
|
||||
mbedtls_x509write_crt_set_authority_key_identifier(&ctx);
|
||||
mbedtls_x509write_crt_set_key_usage(&ctx,
|
||||
MBEDTLS_X509_KU_DIGITAL_SIGNATURE |
|
||||
MBEDTLS_X509_KU_KEY_CERT_SIGN);
|
||||
mbedtls_x509write_crt_set_key_usage(&ctx, MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN);
|
||||
int ret = mbedtls_x509write_crt_der(&ctx, buffer, buffer_size, random_gen, NULL);
|
||||
/* skey cannot be freed, as it is freed later */
|
||||
if (attestation) {
|
||||
@@ -165,7 +163,7 @@ static int x509_create_cert(void *pk_ctx, uint8_t algo, uint8_t slot, bool attes
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void scan_files_piv() {
|
||||
static void scan_files_piv(void) {
|
||||
scan_flash();
|
||||
file_t *ef = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_EF);
|
||||
if ((ef = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_ANY))) {
|
||||
@@ -197,42 +195,35 @@ static void scan_files_piv() {
|
||||
}
|
||||
}
|
||||
bool reset_dek = false;
|
||||
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY))) {
|
||||
if (file_get_size(ef) == 0 || file_get_size(ef) == IV_SIZE+32*3) {
|
||||
printf("DEK is empty or older\r\n");
|
||||
const uint8_t defpin[6] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
|
||||
const uint8_t *dek = random_bytes_get(IV_SIZE + 32);
|
||||
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
|
||||
if (file_get_size(ef) > 0) {
|
||||
memcpy(def, file_get_data(ef), file_get_size(ef));
|
||||
}
|
||||
else {
|
||||
memcpy(def, dek, IV_SIZE);
|
||||
}
|
||||
memcpy(def + IV_SIZE + 32*3, dek + IV_SIZE, 32);
|
||||
hash_multi(defpin, sizeof(defpin), session_pwpiv);
|
||||
aes_encrypt_cfb_256(session_pwpiv, def, def + IV_SIZE + 32*3, 32);
|
||||
if ((ef = search_by_fid(EF_DEK_PWPIV, NULL, SPECIFY_ANY)) && !file_has_data(ef)) {
|
||||
printf("DEK PIV is empty or older\r\n");
|
||||
const uint8_t defpin[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36 };
|
||||
const uint8_t *random_dek = random_bytes_get(IV_SIZE + 32);
|
||||
|
||||
uint8_t def[DEK_FILE_SIZE];
|
||||
def[0] = 0x3; // Format
|
||||
|
||||
pin_derive_session(defpin, sizeof(defpin), session_pwpiv);
|
||||
encrypt_with_aad(session_pwpiv, random_dek, DEK_SIZE, PIN_KDF_DEFAULT_VERSION, def + 1);
|
||||
mbedtls_platform_zeroize(session_pwpiv, sizeof(session_pwpiv));
|
||||
file_put_data(ef, def, sizeof(def));
|
||||
|
||||
has_pwpiv = true;
|
||||
uint8_t *key = (uint8_t *)"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08";
|
||||
file_t *ef = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_ANY);
|
||||
file_put_data(ef, key, 24);
|
||||
file_t *ef_cardmgm = search_by_fid(EF_PIV_KEY_CARDMGM, NULL, SPECIFY_ANY);
|
||||
file_put_data(ef_cardmgm, key, 24);
|
||||
uint8_t meta[] = { PIV_ALGO_AES192, PINPOLICY_ALWAYS, TOUCHPOLICY_ALWAYS };
|
||||
meta_add(EF_PIV_KEY_CARDMGM, meta, sizeof(meta));
|
||||
has_pwpiv = false;
|
||||
memset(session_pwpiv, 0, sizeof(session_pwpiv));
|
||||
|
||||
reset_dek = true;
|
||||
}
|
||||
}
|
||||
if ((ef = search_by_fid(EF_PIV_PIN, NULL, SPECIFY_ANY))) {
|
||||
if (!ef->data || reset_dek) {
|
||||
printf("PIV PIN is empty. Initializing with default password\r\n");
|
||||
const uint8_t def[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0xFF, 0xFF };
|
||||
uint8_t dhash[33];
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = sizeof(def);
|
||||
double_hash_pin(def, sizeof(def), dhash + 1);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(def, sizeof(def), dhash + 2);
|
||||
file_put_data(ef, dhash, sizeof(dhash));
|
||||
}
|
||||
}
|
||||
@@ -240,9 +231,10 @@ static void scan_files_piv() {
|
||||
if (!ef->data) {
|
||||
printf("PIV PUK 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];
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = sizeof(def);
|
||||
double_hash_pin(def, sizeof(def), dhash + 1);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(def, sizeof(def), dhash + 2);
|
||||
file_put_data(ef, dhash, sizeof(dhash));
|
||||
}
|
||||
}
|
||||
@@ -263,17 +255,17 @@ static void scan_files_piv() {
|
||||
low_flash_available();
|
||||
}
|
||||
|
||||
void init_piv() {
|
||||
void init_piv(void) {
|
||||
scan_files_piv();
|
||||
has_pwpiv = false;
|
||||
// cmd_select();
|
||||
}
|
||||
|
||||
int piv_unload() {
|
||||
static int piv_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
void select_piv_aid() {
|
||||
static void select_piv_aid(void) {
|
||||
res_APDU[res_APDU_size++] = 0x61;
|
||||
res_APDU[res_APDU_size++] = 0; //filled later
|
||||
res_APDU[res_APDU_size++] = 0x4F;
|
||||
@@ -300,7 +292,7 @@ void select_piv_aid() {
|
||||
res_APDU[res_APDU_size++] = 0x00;
|
||||
}
|
||||
|
||||
int piv_select_aid(app_t *a, uint8_t force) {
|
||||
static int piv_select_aid(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
a->process_apdu = piv_process_apdu;
|
||||
a->unload = piv_unload;
|
||||
@@ -314,14 +306,14 @@ INITIALIZER( piv_ctor ) {
|
||||
register_app(piv_select_aid, yk_aid);
|
||||
}
|
||||
|
||||
static int cmd_version() {
|
||||
static int cmd_version(void) {
|
||||
res_APDU[res_APDU_size++] = PIV_VERSION_MAJOR;
|
||||
res_APDU[res_APDU_size++] = PIV_VERSION_MINOR;
|
||||
res_APDU[res_APDU_size++] = 0x0;
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_select() {
|
||||
static int cmd_piv_select(void) {
|
||||
if (P2(apdu) != 0x1) {
|
||||
return SW_WRONG_P1P2();
|
||||
}
|
||||
@@ -332,12 +324,13 @@ static int cmd_select() {
|
||||
}
|
||||
|
||||
int piv_parse_discovery(const file_t *ef) {
|
||||
(void) ef;
|
||||
memcpy(res_APDU, "\x7E\x12\x4F\x0B\xA0\x00\x00\x03\x08\x00\x00\x10\x00\x01\x00\x5F\x2F\x02\x40\x10", 20);
|
||||
res_APDU_size = 20;
|
||||
return res_APDU_size;
|
||||
}
|
||||
|
||||
static int cmd_get_serial() {
|
||||
static int cmd_get_serial(void) {
|
||||
uint32_t serial = get_serial();
|
||||
res_APDU[res_APDU_size++] = serial >> 24;
|
||||
res_APDU[res_APDU_size++] = serial >> 16;
|
||||
@@ -346,8 +339,7 @@ static int cmd_get_serial() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
extern int check_pin(const file_t *pin, const uint8_t *data, size_t len);
|
||||
static int cmd_verify() {
|
||||
static int cmd_piv_verify(void) {
|
||||
uint8_t key_ref = P2(apdu);
|
||||
if (P1(apdu) != 0x00 && P1(apdu) != 0xFF) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
@@ -384,7 +376,7 @@ static int cmd_verify() {
|
||||
return set_res_sw(0x63, 0xc0 | retries);
|
||||
}
|
||||
|
||||
static int cmd_get_data() {
|
||||
static int cmd_piv_get_data(void) {
|
||||
if (P1(apdu) != 0x3F || P2(apdu) != 0xFF) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -404,7 +396,9 @@ static int cmd_get_data() {
|
||||
uint16_t data_len = 0;
|
||||
res_APDU_size = 2; // Minimum: TAG+LEN
|
||||
if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
|
||||
data_len = ((int (*)(const file_t *))(ef->data))((const file_t *) ef);
|
||||
int (*file_data_func)(const file_t *) = NULL;
|
||||
memcpy(&file_data_func, &ef->data, sizeof(file_data_func));
|
||||
data_len = file_data_func(ef);
|
||||
}
|
||||
else {
|
||||
if (ef->data) {
|
||||
@@ -430,7 +424,7 @@ static int cmd_get_data() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_get_metadata() {
|
||||
static int cmd_get_metadata(void) {
|
||||
if (P1(apdu) != 0x00) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -529,15 +523,16 @@ static int cmd_get_metadata() {
|
||||
uint8_t dhash[32];
|
||||
int32_t eq = 0;
|
||||
if (key_ref == EF_PIV_PIN) {
|
||||
double_hash_pin((const uint8_t *)"\x31\x32\x33\x34\x35\x36\xFF\xFF", 8, dhash);
|
||||
pin_derive_verifier((const uint8_t *)"\x31\x32\x33\x34\x35\x36\xFF\xFF", 8, dhash);
|
||||
eq = memcmp(dhash, file_get_data(ef_key) + 1, file_get_size(ef_key) - 1);
|
||||
}
|
||||
else if (key_ref == EF_PIV_PUK) {
|
||||
double_hash_pin((const uint8_t *)"\x31\x32\x33\x34\x35\x36\x37\x38", 8, dhash);
|
||||
pin_derive_verifier((const uint8_t *)"\x31\x32\x33\x34\x35\x36\x37\x38", 8, dhash);
|
||||
eq = memcmp(dhash, file_get_data(ef_key) + 1, file_get_size(ef_key) - 1);
|
||||
}
|
||||
else if (key_ref == EF_PIV_KEY_CARDMGM) {
|
||||
eq = memcmp("\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08", file_get_data(ef_key), file_get_size(ef_key));
|
||||
pin_derive_verifier((const uint8_t *)"\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08", 24, dhash);
|
||||
eq = memcmp(dhash, file_get_data(ef_key), file_get_size(ef_key));
|
||||
}
|
||||
res_APDU[res_APDU_size++] = 0x5;
|
||||
res_APDU[res_APDU_size++] = 1;
|
||||
@@ -563,7 +558,7 @@ static int cmd_get_metadata() {
|
||||
uint8_t challenge[16];
|
||||
bool has_challenge = false;
|
||||
bool has_mgm = false;
|
||||
static int cmd_authenticate() {
|
||||
static int cmd_authenticate(void) {
|
||||
uint8_t algo = P1(apdu), key_ref = P2(apdu);
|
||||
if (apdu.nc == 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
@@ -840,7 +835,7 @@ static int cmd_authenticate() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_asym_keygen() {
|
||||
static int cmd_asym_keygen(void) {
|
||||
uint8_t key_ref = P2(apdu);
|
||||
if (apdu.nc == 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
@@ -947,7 +942,7 @@ static int cmd_asym_keygen() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_put_data() {
|
||||
static int cmd_piv_put_data(void) {
|
||||
if (P1(apdu) != 0x3F || P2(apdu) != 0xFF) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -976,7 +971,7 @@ static int cmd_put_data() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_set_mgmkey() {
|
||||
static int cmd_set_mgmkey(void) {
|
||||
if (P1(apdu) != 0xFF) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -1012,7 +1007,7 @@ static int cmd_set_mgmkey() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_move_key() {
|
||||
static int cmd_move_key(void) {
|
||||
if (apdu.nc != 0) {
|
||||
return SW_WRONG_LENGTH();
|
||||
}
|
||||
@@ -1020,6 +1015,9 @@ static int cmd_move_key() {
|
||||
if ((!IS_KEY(to) && to != 0xFF) || !IS_KEY(from)) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
if (IS_RETIRED(from) && IS_ACTIVE(to)) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
if (from == 0x93) {
|
||||
from = EF_PIV_KEY_RETIRED18;
|
||||
}
|
||||
@@ -1030,15 +1028,91 @@ static int cmd_move_key() {
|
||||
if (!(efs = search_by_fid(from, NULL, SPECIFY_EF)) || (!(efd = search_by_fid(to, NULL, SPECIFY_EF)) && to != 0xFF)) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
uint16_t cert_from_fid = 0;
|
||||
uint16_t cert_to_fid = 0;
|
||||
if (from == EF_PIV_KEY_AUTHENTICATION) {
|
||||
cert_from_fid = EF_PIV_AUTHENTICATION;
|
||||
}
|
||||
else if (from == EF_PIV_KEY_SIGNATURE) {
|
||||
cert_from_fid = EF_PIV_SIGNATURE;
|
||||
}
|
||||
else if (from == EF_PIV_KEY_KEYMGM) {
|
||||
cert_from_fid = EF_PIV_KEY_MANAGEMENT;
|
||||
}
|
||||
else if (from == EF_PIV_KEY_CARDAUTH) {
|
||||
cert_from_fid = EF_PIV_CARD_AUTH;
|
||||
}
|
||||
else if (from == EF_PIV_KEY_RETIRED18) {
|
||||
cert_from_fid = EF_PIV_RETIRED18;
|
||||
}
|
||||
else {
|
||||
cert_from_fid = from + 0xC08B;
|
||||
}
|
||||
if (to != 0xFF) {
|
||||
if (to == EF_PIV_KEY_AUTHENTICATION) {
|
||||
cert_to_fid = EF_PIV_AUTHENTICATION;
|
||||
}
|
||||
else if (to == EF_PIV_KEY_SIGNATURE) {
|
||||
cert_to_fid = EF_PIV_SIGNATURE;
|
||||
}
|
||||
else if (to == EF_PIV_KEY_KEYMGM) {
|
||||
cert_to_fid = EF_PIV_KEY_MANAGEMENT;
|
||||
}
|
||||
else if (to == EF_PIV_KEY_CARDAUTH) {
|
||||
cert_to_fid = EF_PIV_CARD_AUTH;
|
||||
}
|
||||
else if (to == EF_PIV_KEY_RETIRED18) {
|
||||
cert_to_fid = EF_PIV_RETIRED18;
|
||||
}
|
||||
else {
|
||||
cert_to_fid = to + 0xC08B;
|
||||
}
|
||||
}
|
||||
|
||||
if (to != 0xFF) {
|
||||
file_put_data(efd, file_get_data(efs), file_get_size(efs));
|
||||
}
|
||||
|
||||
file_t *ef_cert_from = search_by_fid(cert_from_fid, NULL, SPECIFY_EF);
|
||||
if (to != 0xFF) {
|
||||
file_t *ef_cert_to = search_by_fid(cert_to_fid, NULL, SPECIFY_EF);
|
||||
if (!ef_cert_to) {
|
||||
return SW_FILE_NOT_FOUND();
|
||||
}
|
||||
if (file_has_data(ef_cert_from)) {
|
||||
file_put_data(ef_cert_to, file_get_data(ef_cert_from), file_get_size(ef_cert_from));
|
||||
}
|
||||
else {
|
||||
flash_clear_file(ef_cert_to);
|
||||
}
|
||||
}
|
||||
if (ef_cert_from) {
|
||||
flash_clear_file(ef_cert_from);
|
||||
}
|
||||
|
||||
uint8_t *meta_src = NULL;
|
||||
int meta_len = meta_find(from, &meta_src);
|
||||
if (to != 0xFF) {
|
||||
if (meta_len > 0 && meta_src != NULL) {
|
||||
uint8_t *meta_copy = (uint8_t *)calloc(1, (size_t)meta_len);
|
||||
if (!meta_copy) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
}
|
||||
memcpy(meta_copy, meta_src, (size_t)meta_len);
|
||||
meta_add(to, meta_copy, (uint16_t)meta_len);
|
||||
free(meta_copy);
|
||||
}
|
||||
else {
|
||||
meta_delete(to);
|
||||
}
|
||||
}
|
||||
meta_delete(from);
|
||||
flash_clear_file(efs);
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_change_pin() {
|
||||
static int cmd_piv_change_pin(void) {
|
||||
uint8_t pin_ref = P2(apdu);
|
||||
if (P1(apdu) != 0x0 || (pin_ref != 0x80 && pin_ref != 0x81)) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
@@ -1052,15 +1126,17 @@ static int cmd_change_pin() {
|
||||
if (ret != 0x9000) {
|
||||
return ret;
|
||||
}
|
||||
uint8_t dhash[33];
|
||||
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = pin_len;
|
||||
double_hash_pin(apdu.data + pin_data[0], pin_len, dhash + 1);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(apdu.data + pin_data[0], pin_len, dhash + 2);
|
||||
file_put_data(ef, dhash, sizeof(dhash));
|
||||
low_flash_available();
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_reset_retry() {
|
||||
static int cmd_piv_reset_retry(void) {
|
||||
if (P1(apdu) != 0x0 || P2(apdu) != 0x80) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -1073,9 +1149,10 @@ static int cmd_reset_retry() {
|
||||
if (ret != 0x9000) {
|
||||
return ret;
|
||||
}
|
||||
uint8_t dhash[33];
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = pin_len;
|
||||
double_hash_pin(apdu.data + puk_data[0], pin_len, dhash + 1);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(apdu.data + puk_data[0], pin_len, dhash + 2);
|
||||
ef = search_by_fid(EF_PIV_PIN, NULL, SPECIFY_ANY);
|
||||
file_put_data(ef, dhash, sizeof(dhash));
|
||||
pin_reset_retries(ef, true);
|
||||
@@ -1083,7 +1160,7 @@ static int cmd_reset_retry() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_set_retries() {
|
||||
static int cmd_set_retries(void) {
|
||||
file_t *ef = search_by_fid(EF_PW_RETRIES, NULL, SPECIFY_ANY);
|
||||
if (!ef) {
|
||||
return SW_MEMORY_FAILURE();
|
||||
@@ -1097,16 +1174,19 @@ static int cmd_set_retries() {
|
||||
|
||||
ef = search_by_fid(EF_PIV_PIN, NULL, SPECIFY_ANY);
|
||||
const uint8_t def_pin[8] = { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0xFF, 0xFF };
|
||||
uint8_t dhash[33];
|
||||
|
||||
uint8_t dhash[34];
|
||||
dhash[0] = sizeof(def_pin);
|
||||
double_hash_pin(def_pin, sizeof(def_pin), dhash + 1);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(def_pin, sizeof(def_pin), dhash + 2);
|
||||
file_put_data(ef, dhash, sizeof(dhash));
|
||||
pin_reset_retries(ef, true);
|
||||
|
||||
ef = search_by_fid(EF_PIV_PUK, NULL, SPECIFY_ANY);
|
||||
const uint8_t def_puk[8] = {0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38};
|
||||
dhash[0] = sizeof(def_puk);
|
||||
double_hash_pin(def_puk, sizeof(def_puk), dhash + 1);
|
||||
dhash[1] = 0x1; // Format
|
||||
pin_derive_verifier(def_puk, sizeof(def_puk), dhash + 2);
|
||||
file_put_data(ef, dhash, sizeof(dhash));
|
||||
pin_reset_retries(ef, true);
|
||||
|
||||
@@ -1114,7 +1194,7 @@ static int cmd_set_retries() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_reset() {
|
||||
static int cmd_reset(void) {
|
||||
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -1133,7 +1213,7 @@ static int cmd_reset() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_attestation() {
|
||||
static int cmd_attestation(void) {
|
||||
uint8_t key_ref = P1(apdu);
|
||||
if (P2(apdu) != 0x00) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
@@ -1154,6 +1234,7 @@ static int cmd_attestation() {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
int r = 0;
|
||||
uint8_t abuf[2048];
|
||||
if (meta[0] == PIV_ALGO_RSA1024 || meta[0] == PIV_ALGO_RSA2048) {
|
||||
mbedtls_rsa_context ctx;
|
||||
mbedtls_rsa_init(&ctx);
|
||||
@@ -1162,7 +1243,7 @@ static int cmd_attestation() {
|
||||
mbedtls_rsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = x509_create_cert(&ctx, meta[0], key_ref, true, res_APDU, 2048);
|
||||
r = x509_create_cert(&ctx, meta[0], key_ref, true, abuf, sizeof(abuf));
|
||||
mbedtls_rsa_free(&ctx);
|
||||
}
|
||||
else if (meta[0] == PIV_ALGO_ECCP256 || meta[0] == PIV_ALGO_ECCP384) {
|
||||
@@ -1173,7 +1254,7 @@ static int cmd_attestation() {
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
r = x509_create_cert(&ctx, meta[0], key_ref, true, res_APDU, 2048);
|
||||
r = x509_create_cert(&ctx, meta[0], key_ref, true, abuf, sizeof(abuf));
|
||||
mbedtls_ecdsa_free(&ctx);
|
||||
}
|
||||
else {
|
||||
@@ -1182,12 +1263,12 @@ static int cmd_attestation() {
|
||||
if (r <= 0) {
|
||||
return SW_EXEC_ERROR();
|
||||
}
|
||||
memmove(res_APDU, res_APDU + 2048 - r, r);
|
||||
memcpy(res_APDU, abuf + sizeof(abuf) - r, r);
|
||||
res_APDU_size = r;
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
static int cmd_import_asym() {
|
||||
static int cmd_import_asym(void) {
|
||||
uint8_t algo = P1(apdu), key_ref = P2(apdu);
|
||||
if (key_ref != EF_PIV_KEY_AUTHENTICATION && key_ref != EF_PIV_KEY_SIGNATURE && key_ref != EF_PIV_KEY_KEYMGM && key_ref != EF_PIV_KEY_CARDAUTH && !(key_ref >= EF_PIV_KEY_RETIRED1 && key_ref <= EF_PIV_KEY_RETIRED20)) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
@@ -1301,18 +1382,18 @@ static int cmd_import_asym() {
|
||||
|
||||
static const cmd_t cmds[] = {
|
||||
{ INS_VERSION, cmd_version },
|
||||
{ INS_SELECT, cmd_select },
|
||||
{ INS_SELECT, cmd_piv_select },
|
||||
{ INS_YK_SERIAL, cmd_get_serial },
|
||||
{ INS_VERIFY, cmd_verify },
|
||||
{ INS_GET_DATA, cmd_get_data },
|
||||
{ INS_VERIFY, cmd_piv_verify },
|
||||
{ INS_GET_DATA, cmd_piv_get_data },
|
||||
{ INS_GET_METADATA, cmd_get_metadata },
|
||||
{ INS_AUTHENTICATE, cmd_authenticate },
|
||||
{ INS_ASYM_KEYGEN, cmd_asym_keygen },
|
||||
{ INS_PUT_DATA, cmd_put_data },
|
||||
{ INS_PUT_DATA, cmd_piv_put_data },
|
||||
{ INS_SET_MGMKEY, cmd_set_mgmkey },
|
||||
{ INS_MOVE_KEY, cmd_move_key },
|
||||
{ INS_CHANGE_PIN, cmd_change_pin },
|
||||
{ INS_RESET_RETRY, cmd_reset_retry },
|
||||
{ INS_CHANGE_PIN, cmd_piv_change_pin },
|
||||
{ INS_RESET_RETRY, cmd_piv_reset_retry },
|
||||
{ INS_SET_RETRIES, cmd_set_retries },
|
||||
{ INS_RESET, cmd_reset },
|
||||
{ INS_ATTESTATION, cmd_attestation },
|
||||
@@ -1320,7 +1401,7 @@ static const cmd_t cmds[] = {
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int piv_process_apdu() {
|
||||
int piv_process_apdu(void) {
|
||||
sm_unwrap();
|
||||
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
|
||||
if (cmd->ins == INS(apdu)) {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
#define PIV_VERSION_MINOR (PIV_VERSION & 0xff)
|
||||
|
||||
|
||||
#define PIPGP_VERSION 0x0404
|
||||
#define PIPGP_VERSION 0x0406
|
||||
|
||||
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
|
||||
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
source tests/docker_env.sh
|
||||
#run_in_docker rm -rf CMakeFiles
|
||||
run_in_docker mkdir -p build_in_docker
|
||||
run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 -DENABLE_EDDSA=1 ..
|
||||
run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 -DENABLE_EDDSA=1 -DOPENPGP_TEST_INIT_LEGACY_PIN=ON ..
|
||||
run_in_docker -w "$PWD/build_in_docker" make -j ${NUM_PROC}
|
||||
|
||||
@@ -201,7 +201,7 @@ def test_extended_capabilities(card):
|
||||
pytest.skip("Yubikey returns 6B00 when no key")
|
||||
else:
|
||||
a = get_data_object(card, 0xc0)
|
||||
assert a == None or match(b'[\x70\x74\x75\x77]\x00\x00.[\x00\x08]\x00\x00\xff[\x00\x01][\x00\x01]', a)
|
||||
assert a == None or match(b'[\x70\x7F\x75\x77]\x00\x00.[\x00\x08]\x00\x08\x00[\x00\x01][\x00\x01]', a)
|
||||
|
||||
def test_key_attributes_1(card):
|
||||
if card.is_yubikey:
|
||||
|
||||
@@ -28,6 +28,26 @@ from card_const import *
|
||||
from constants_for_test import *
|
||||
import pytest
|
||||
|
||||
PRIVATE_DO_0101 = (0x01, 0x01)
|
||||
PRIVATE_DO_0102 = (0x01, 0x02)
|
||||
PRIVATE_DO_0103 = (0x01, 0x03)
|
||||
PRIVATE_DO_0104 = (0x01, 0x04)
|
||||
|
||||
|
||||
def _assert_sw(e, sw_list):
|
||||
sw = e.args[0]
|
||||
assert sw in sw_list
|
||||
|
||||
|
||||
def _expect_security_error(callable_):
|
||||
try:
|
||||
callable_()
|
||||
except ValueError as e:
|
||||
_assert_sw(e, ["6982", "6985"])
|
||||
return
|
||||
assert False
|
||||
|
||||
|
||||
class Test_Card_Personalize_Card_2(object):
|
||||
def test_verify_pw3_0(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
@@ -202,3 +222,112 @@ class Test_Card_Personalize_Card_2(object):
|
||||
def test_verify_pw3_2(self, card):
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
|
||||
def test_private_do_0101_write_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0101[0], PRIVATE_DO_0101[1], b"priv0101_pw3_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0101_write_fail_with_pw1_81(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
_expect_security_error(
|
||||
lambda: card.cmd_put_data(PRIVATE_DO_0101[0], PRIVATE_DO_0101[1], b"priv0101_pw1_81")
|
||||
)
|
||||
|
||||
def test_private_do_0101_write_ok_with_pw1_82(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0101[0], PRIVATE_DO_0101[1], b"priv0101_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0101_read_always(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
data = get_data_object(card, 0x0101)
|
||||
assert data == b"priv0101_ok" or data == b"priv0101_pw3_ok"
|
||||
|
||||
def test_private_do_0102_write_fail_with_pw1(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
_expect_security_error(
|
||||
lambda: card.cmd_put_data(PRIVATE_DO_0102[0], PRIVATE_DO_0102[1], b"priv0102_pw1")
|
||||
)
|
||||
|
||||
def test_private_do_0102_write_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0102[0], PRIVATE_DO_0102[1], b"priv0102_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0102_read_always(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
data = get_data_object(card, 0x0102)
|
||||
assert data == b"priv0102_ok"
|
||||
|
||||
def test_private_do_0103_read_fail_without_auth(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
_expect_security_error(lambda: get_data_object(card, 0x0103))
|
||||
|
||||
def test_private_do_0103_read_fail_with_pw1_81(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(1, PW1_TEST4)
|
||||
assert v
|
||||
_expect_security_error(lambda: get_data_object(card, 0x0103))
|
||||
|
||||
def test_private_do_0103_write_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0103[0], PRIVATE_DO_0103[1], b"priv0103_pw3_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0103_read_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
data = get_data_object(card, 0x0103)
|
||||
assert data == b"priv0103_pw3_ok"
|
||||
|
||||
def test_private_do_0103_write_ok_with_pw1_82(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0103[0], PRIVATE_DO_0103[1], b"priv0103_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0103_read_ok_with_pw1_82(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
data = get_data_object(card, 0x0103)
|
||||
assert data == b"priv0103_ok"
|
||||
|
||||
def test_private_do_0104_read_fail_without_auth(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
_expect_security_error(lambda: get_data_object(card, 0x0104))
|
||||
|
||||
def test_private_do_0104_read_fail_with_pw1(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(2, PW1_TEST4)
|
||||
assert v
|
||||
_expect_security_error(lambda: get_data_object(card, 0x0104))
|
||||
|
||||
def test_private_do_0104_write_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
r = card.cmd_put_data(PRIVATE_DO_0104[0], PRIVATE_DO_0104[1], b"priv0104_ok")
|
||||
assert r
|
||||
|
||||
def test_private_do_0104_read_ok_with_pw3(self, card):
|
||||
card.cmd_select_openpgp()
|
||||
v = card.verify(3, PW3_TEST0)
|
||||
assert v
|
||||
data = get_data_object(card, 0x0104)
|
||||
assert data == b"priv0104_ok"
|
||||
|
||||
Reference in New Issue
Block a user