mirror of
https://github.com/polhenarejos/pico-fido
synced 2026-06-04 20:09:07 +02:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
39b9dbb8d6 | ||
|
|
b66a80eb01 | ||
|
|
ca15206e77 | ||
|
|
ec10becbef | ||
|
|
b88e52971f | ||
|
|
f658ef6eab | ||
|
|
4e7c40b2bd | ||
|
|
f4487a1ff4 | ||
|
|
edf6a697ba | ||
|
|
24978a5476 | ||
|
|
1795f5c330 | ||
|
|
8d81e2eb24 | ||
|
|
ab3ddf4e23 | ||
|
|
d8ccf9bd28 | ||
|
|
0e1512a135 | ||
|
|
ac0462525a | ||
|
|
bb20a75ef4 | ||
|
|
8d709cf745 |
288
CMakeLists.txt
288
CMakeLists.txt
@@ -1,19 +1,19 @@
|
||||
#
|
||||
# This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
|
||||
# Copyright (c) 2022 Pol Henarejos.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
#
|
||||
# This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
|
||||
# Copyright (c) 2022 Pol Henarejos.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, version 3.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
# General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
@@ -21,51 +21,64 @@ set(USB_VID 0x2E8A)
|
||||
set(USB_PID 0x10FE)
|
||||
|
||||
if(ESP_PLATFORM)
|
||||
set(DENABLE_POWER_ON_RESET 0)
|
||||
set(EXTRA_COMPONENT_DIRS pico-keys-sdk/config/esp32/components src/fido)
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
if(NOT DEFINED ENABLE_POWER_ON_RESET)
|
||||
set(ENABLE_POWER_ON_RESET 0)
|
||||
endif()
|
||||
if(NOT DEFINED ENABLE_PQC)
|
||||
set(ENABLE_PQC 0)
|
||||
endif()
|
||||
set(EXTRA_COMPONENT_DIRS
|
||||
src/fido
|
||||
pico-keys-sdk/config/esp32/components/pico-keys-sdk
|
||||
pico-keys-sdk/config/esp32/components/tinycbor
|
||||
)
|
||||
if(ENABLE_PQC)
|
||||
list(APPEND EXTRA_COMPONENT_DIRS
|
||||
pico-keys-sdk/config/esp32/components/mlkem512
|
||||
pico-keys-sdk/config/esp32/components/mlkem768
|
||||
pico-keys-sdk/config/esp32/components/mlkem1024
|
||||
)
|
||||
endif()
|
||||
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
|
||||
else()
|
||||
if(NOT ENABLE_EMULATION)
|
||||
set(PICO_USE_FASTEST_SUPPORTED_CLOCK 1)
|
||||
include(pico_sdk_import.cmake)
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMULATION)
|
||||
else()
|
||||
set(PICO_USE_FASTEST_SUPPORTED_CLOCK 1)
|
||||
include(pico_sdk_import.cmake)
|
||||
project(pico_fido C CXX ASM)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_executable(pico_fido)
|
||||
endif()
|
||||
|
||||
project(pico_fido C CXX ASM)
|
||||
|
||||
set(CMAKE_C_STANDARD 11)
|
||||
set(CMAKE_CXX_STANDARD 17)
|
||||
|
||||
add_executable(pico_fido)
|
||||
endif()
|
||||
include(pico-keys-sdk/cmake/options.cmake)
|
||||
|
||||
option(ENABLE_POWER_ON_RESET "Enable/disable power cycle on reset" ON)
|
||||
if(ENABLE_POWER_ON_RESET)
|
||||
add_definitions(-DENABLE_POWER_ON_RESET=1)
|
||||
message(STATUS "Power cycle on reset: \t enabled")
|
||||
else()
|
||||
add_definitions(-DENABLE_POWER_ON_RESET=0)
|
||||
message(STATUS "Power cycle on reset: \t disabled")
|
||||
endif(ENABLE_POWER_ON_RESET)
|
||||
configure_bool_option(
|
||||
ENABLE_POWER_ON_RESET
|
||||
ENABLE_POWER_ON_RESET
|
||||
"Power cycle on reset: \t enabled"
|
||||
"Power cycle on reset: \t disabled"
|
||||
)
|
||||
|
||||
option(ENABLE_OATH_APP "Enable/disable OATH application" ON)
|
||||
if(ENABLE_OATH_APP)
|
||||
add_definitions(-DENABLE_OATH_APP=1)
|
||||
message(STATUS "OATH Application: \t\t enabled")
|
||||
else()
|
||||
add_definitions(-DENABLE_OATH_APP=0)
|
||||
message(STATUS "OATH Application: \t\t disabled")
|
||||
endif(ENABLE_OATH_APP)
|
||||
configure_bool_option(
|
||||
ENABLE_OATH_APP
|
||||
ENABLE_OATH_APP
|
||||
"OATH Application: \t\t enabled"
|
||||
"OATH Application: \t\t disabled"
|
||||
)
|
||||
|
||||
option(ENABLE_OTP_APP "Enable/disable OTP application" ON)
|
||||
if(ENABLE_OTP_APP)
|
||||
add_definitions(-DENABLE_OTP_APP=1)
|
||||
message(STATUS "OTP Application: \t\t enabled")
|
||||
else()
|
||||
add_definitions(-DENABLE_OTP_APP=0)
|
||||
message(STATUS "OTP Application: \t\t disabled")
|
||||
endif(ENABLE_OTP_APP)
|
||||
configure_bool_option(
|
||||
ENABLE_OTP_APP
|
||||
ENABLE_OTP_APP
|
||||
"OTP Application: \t\t enabled"
|
||||
"OTP Application: \t\t disabled"
|
||||
)
|
||||
|
||||
if(ENABLE_OTP_APP OR ENABLE_OATH_APP)
|
||||
set(USB_ITF_CCID 1)
|
||||
@@ -81,92 +94,121 @@ if(NOT ESP_PLATFORM)
|
||||
set(SOURCES ${PICO_KEYS_SOURCES})
|
||||
endif()
|
||||
|
||||
set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/fido.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/files.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/kek.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cmd_register.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cmd_authenticate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cmd_version.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_reset.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_get_info.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_make_credential.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/known_apps.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_client_pin.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/credential.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_get_assertion.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_selection.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_cred_mgmt.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_config.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_vendor.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_large_blobs.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/management.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/defs.c
|
||||
)
|
||||
if (${ENABLE_OATH_APP})
|
||||
set(SOURCES ${SOURCES}
|
||||
list(APPEND SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/fido.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/files.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cmd_register.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cmd_authenticate.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cmd_version.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_reset.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_get_info.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_make_credential.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/known_apps.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_client_pin.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/credential.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_get_assertion.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_selection.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_cred_mgmt.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_config.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_vendor.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/cbor_large_blobs.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/management.c
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/defs.c
|
||||
)
|
||||
|
||||
if(ENABLE_OATH_APP)
|
||||
list(APPEND SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/oath.c
|
||||
)
|
||||
endif()
|
||||
if (${ENABLE_OTP_APP})
|
||||
set(SOURCES ${SOURCES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/otp.c
|
||||
)
|
||||
)
|
||||
endif()
|
||||
|
||||
SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/fido/version.h" 3)
|
||||
if(ENABLE_OTP_APP)
|
||||
list(APPEND SOURCES
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido/otp.c
|
||||
)
|
||||
endif()
|
||||
|
||||
SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/fido/version.h")
|
||||
if(ESP_PLATFORM)
|
||||
project(pico_fido)
|
||||
endif()
|
||||
|
||||
set(INCLUDES ${INCLUDES}
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido
|
||||
)
|
||||
${CMAKE_CURRENT_LIST_DIR}/src/fido
|
||||
)
|
||||
|
||||
if(NOT ESP_PLATFORM)
|
||||
target_sources(pico_fido PUBLIC ${SOURCES})
|
||||
target_include_directories(pico_fido PUBLIC ${INCLUDES})
|
||||
target_sources(pico_fido PUBLIC ${SOURCES})
|
||||
target_include_directories(pico_fido PUBLIC ${INCLUDES})
|
||||
|
||||
target_compile_options(pico_fido PUBLIC
|
||||
-Wall
|
||||
set(COMMON_COMPILE_OPTIONS
|
||||
-Wall
|
||||
)
|
||||
if (NOT MSVC)
|
||||
target_compile_options(pico_fido PUBLIC
|
||||
-Werror
|
||||
target_compile_options(pico_fido PRIVATE ${COMMON_COMPILE_OPTIONS})
|
||||
|
||||
pico_keys_apply_strict_flags(
|
||||
SOURCES ${SOURCES}
|
||||
FILTER_REGEX "/src/fido/|/pico-keys-sdk/src/|/pico-keys-sdk/config/"
|
||||
)
|
||||
|
||||
string(FIND ${CMAKE_C_COMPILER} ":" COMPILER_COLON)
|
||||
if (${COMPILER_COLON} GREATER_EQUAL 0)
|
||||
target_compile_options(pico_fido PUBLIC
|
||||
-Wno-error=use-after-free
|
||||
)
|
||||
endif()
|
||||
endif(NOT MSVC)
|
||||
|
||||
if(ENABLE_EMULATION)
|
||||
if(NOT MSVC)
|
||||
target_compile_options(pico_fido PUBLIC
|
||||
-fdata-sections
|
||||
-ffunction-sections
|
||||
string(FIND ${CMAKE_C_COMPILER} ":" COMPILER_COLON)
|
||||
if(${COMPILER_COLON} GREATER_EQUAL 0)
|
||||
target_compile_options(pico_fido PRIVATE
|
||||
-Wno-error=use-after-free
|
||||
)
|
||||
endif(NOT MSVC)
|
||||
if(APPLE)
|
||||
target_link_options(pico_fido PUBLIC
|
||||
-Wl,-dead_strip
|
||||
)
|
||||
if(DEBUG_APDU)
|
||||
target_compile_options(pico_fido PUBLIC
|
||||
-fsanitize=address -g -O1 -fno-omit-frame-pointer)
|
||||
target_link_options(pico_fido PUBLIC
|
||||
-fsanitize=address -g -O1 -fno-omit-frame-pointer)
|
||||
endif()
|
||||
else()
|
||||
target_link_options(pico_fido PUBLIC
|
||||
-Wl,--gc-sections
|
||||
endif()
|
||||
|
||||
if(ENABLE_EMULATION)
|
||||
if(NOT MSVC)
|
||||
set(EMULATION_NON_MSVC_COMPILE_OPTIONS
|
||||
-fdata-sections
|
||||
-ffunction-sections
|
||||
)
|
||||
endif (APPLE)
|
||||
target_link_libraries(pico_fido PRIVATE pico_keys_sdk mbedtls pthread m)
|
||||
else()
|
||||
target_link_libraries(pico_fido PRIVATE pico_keys_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id pico_aon_timer tinyusb_device tinyusb_board)
|
||||
pico_add_extra_outputs(${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
target_compile_options(pico_fido PRIVATE ${EMULATION_NON_MSVC_COMPILE_OPTIONS})
|
||||
endif()
|
||||
|
||||
if(APPLE)
|
||||
set(EMULATION_APPLE_LINK_OPTIONS
|
||||
-Wl,-dead_strip
|
||||
)
|
||||
target_link_options(pico_fido PRIVATE ${EMULATION_APPLE_LINK_OPTIONS})
|
||||
|
||||
if(DEBUG_APDU)
|
||||
set(DEBUG_APDU_SANITIZER_OPTIONS
|
||||
-fsanitize=address
|
||||
-g
|
||||
-O1
|
||||
-fno-omit-frame-pointer
|
||||
)
|
||||
target_compile_options(pico_fido PRIVATE ${DEBUG_APDU_SANITIZER_OPTIONS})
|
||||
target_link_options(pico_fido PRIVATE ${DEBUG_APDU_SANITIZER_OPTIONS})
|
||||
endif()
|
||||
else()
|
||||
set(EMULATION_NON_APPLE_LINK_OPTIONS
|
||||
-Wl,--gc-sections
|
||||
)
|
||||
target_link_options(pico_fido PRIVATE ${EMULATION_NON_APPLE_LINK_OPTIONS})
|
||||
endif()
|
||||
|
||||
target_link_libraries(pico_fido PRIVATE pico_keys_sdk mbedtls pthread m)
|
||||
else()
|
||||
target_link_libraries(
|
||||
pico_fido
|
||||
PRIVATE
|
||||
pico_keys_sdk
|
||||
pico_stdlib
|
||||
pico_multicore
|
||||
hardware_flash
|
||||
hardware_sync
|
||||
hardware_adc
|
||||
pico_unique_id
|
||||
pico_aon_timer
|
||||
tinyusb_device
|
||||
tinyusb_board
|
||||
)
|
||||
pico_add_extra_outputs(${CMAKE_PROJECT_NAME})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/bin/bash
|
||||
|
||||
VERSION_MAJOR="7"
|
||||
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
@@ -30,20 +30,7 @@
|
||||
|
||||
const bool _btrue = true, _bfalse = false;
|
||||
|
||||
int cbor_reset();
|
||||
int cbor_get_info();
|
||||
int cbor_make_credential(const uint8_t *data, size_t len);
|
||||
int cbor_client_pin(const uint8_t *data, size_t len);
|
||||
int cbor_get_assertion(const uint8_t *data, size_t len, bool next);
|
||||
int cbor_get_next_assertion(const uint8_t *data, size_t len);
|
||||
int cbor_selection();
|
||||
int cbor_cred_mgmt(const uint8_t *data, size_t len);
|
||||
int cbor_config(const uint8_t *data, size_t len);
|
||||
int cbor_vendor(const uint8_t *data, size_t len);
|
||||
int cbor_large_blobs(const uint8_t *data, size_t len);
|
||||
extern void reset_gna_state();
|
||||
|
||||
extern int cmd_read_config();
|
||||
|
||||
const uint8_t aaguid[16] = { 0x89, 0xFB, 0x94, 0xB7, 0x06, 0xC9, 0x36, 0x73, 0x9B, 0x7E, 0x30, 0x52, 0x6D, 0x96, 0x81, 0x45 }; // First 16 bytes of SHA256("Pico FIDO2")
|
||||
|
||||
@@ -98,7 +85,7 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
return cbor_vendor(data, len);
|
||||
}
|
||||
else if (cmd == 0xC2) {
|
||||
if (cmd_read_config() == 0x9000) {
|
||||
if (man_get_config() == 0) {
|
||||
memmove(res_APDU-1, res_APDU, res_APDU_size);
|
||||
res_APDU_size -= 1;
|
||||
return 0;
|
||||
@@ -108,6 +95,7 @@ int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
return CTAP1_ERR_INVALID_CMD;
|
||||
}
|
||||
|
||||
void *cbor_thread(void *arg) __attribute__((unused));
|
||||
void *cbor_thread(void *arg) {
|
||||
(void)arg;
|
||||
card_init_core1();
|
||||
@@ -152,7 +140,7 @@ int cbor_process(uint8_t last_cmd, const uint8_t *data, size_t len) {
|
||||
return 2; // CBOR processing
|
||||
}
|
||||
|
||||
CborError COSE_key_params(int crv, int alg, mbedtls_ecp_group *grp, mbedtls_ecp_point *Q, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder) {
|
||||
static CborError COSE_key_params(int crv, int alg, mbedtls_ecp_group *grp, mbedtls_ecp_point *Q, CborEncoder *mapEncoderParent, CborEncoder *mapEncoder) {
|
||||
CborError error = CborNoError;
|
||||
int kty = 1;
|
||||
if (crv == FIDO2_CURVE_P256 || crv == FIDO2_CURVE_P384 || crv == FIDO2_CURVE_P521 ||
|
||||
|
||||
@@ -16,11 +16,6 @@
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#ifndef ESP_PLATFORM
|
||||
#include "common.h"
|
||||
#else
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#endif
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/ecdh.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
@@ -37,16 +32,14 @@
|
||||
#include "random.h"
|
||||
#include "crypto_utils.h"
|
||||
#include "apdu.h"
|
||||
#include "kek.h"
|
||||
|
||||
uint32_t usage_timer = 0, initial_usage_time_limit = 0;
|
||||
uint32_t max_usage_time_period = 600 * 1000;
|
||||
bool needs_power_cycle = false;
|
||||
static mbedtls_ecdh_context hkey;
|
||||
static bool hkey_init = false;
|
||||
extern int encrypt_keydev_f1(const uint8_t keydev[32]);
|
||||
|
||||
int beginUsingPinUvAuthToken(bool userIsPresent) {
|
||||
static int beginUsingPinUvAuthToken(bool userIsPresent) {
|
||||
paut.user_present = userIsPresent;
|
||||
paut.user_verified = true;
|
||||
initial_usage_time_limit = board_millis();
|
||||
@@ -55,25 +48,25 @@ int beginUsingPinUvAuthToken(bool userIsPresent) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
void clearUserPresentFlag() {
|
||||
void clearUserPresentFlag(void) {
|
||||
if (paut.in_use == true) {
|
||||
paut.user_present = false;
|
||||
}
|
||||
}
|
||||
|
||||
void clearUserVerifiedFlag() {
|
||||
void clearUserVerifiedFlag(void) {
|
||||
if (paut.in_use == true) {
|
||||
paut.user_verified = false;
|
||||
}
|
||||
}
|
||||
|
||||
void clearPinUvAuthTokenPermissionsExceptLbw() {
|
||||
void clearPinUvAuthTokenPermissionsExceptLbw(void) {
|
||||
if (paut.in_use == true) {
|
||||
paut.permissions = CTAP_PERMISSION_LBW;
|
||||
}
|
||||
}
|
||||
|
||||
void stopUsingPinUvAuthToken() {
|
||||
static void stopUsingPinUvAuthToken(void) {
|
||||
paut.permissions = 0;
|
||||
usage_timer = 0;
|
||||
paut.in_use = false;
|
||||
@@ -84,21 +77,21 @@ void stopUsingPinUvAuthToken() {
|
||||
user_present_time_limit = 0;
|
||||
}
|
||||
|
||||
bool getUserPresentFlagValue() {
|
||||
bool getUserPresentFlagValue(void) {
|
||||
if (paut.in_use != true) {
|
||||
paut.user_present = false;
|
||||
}
|
||||
return paut.user_present;
|
||||
}
|
||||
|
||||
bool getUserVerifiedFlagValue() {
|
||||
bool getUserVerifiedFlagValue(void) {
|
||||
if (paut.in_use != true) {
|
||||
paut.user_verified = false;
|
||||
}
|
||||
return paut.user_verified;
|
||||
}
|
||||
|
||||
int regenerate() {
|
||||
static int regenerate(void) {
|
||||
if (hkey_init == true) {
|
||||
mbedtls_ecdh_free(&hkey);
|
||||
}
|
||||
@@ -114,7 +107,7 @@ int regenerate() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int kdf(uint8_t protocol, const mbedtls_mpi *z, uint8_t *sharedSecret) {
|
||||
static int kdf(uint8_t protocol, const mbedtls_mpi *z, uint8_t *sharedSecret) {
|
||||
int ret = 0;
|
||||
uint8_t buf[32];
|
||||
ret = mbedtls_mpi_write_binary(z, buf, sizeof(buf));
|
||||
@@ -144,7 +137,7 @@ int ecdh(uint8_t protocol, const mbedtls_ecp_point *Q, uint8_t *sharedSecret) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
void resetAuthToken(bool persistent) {
|
||||
static void resetAuthToken(bool persistent) {
|
||||
uint16_t fid = EF_AUTHTOKEN;
|
||||
if (persistent) {
|
||||
fid = EF_PAUTHTOKEN;
|
||||
@@ -156,7 +149,7 @@ void resetAuthToken(bool persistent) {
|
||||
low_flash_available();
|
||||
}
|
||||
|
||||
int resetPinUvAuthToken() {
|
||||
int resetPinUvAuthToken(void) {
|
||||
resetAuthToken(false);
|
||||
paut.permissions = 0;
|
||||
paut.data = file_get_data(ef_authtoken);
|
||||
@@ -164,7 +157,7 @@ int resetPinUvAuthToken() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resetPersistentPinUvAuthToken() {
|
||||
int resetPersistentPinUvAuthToken(void) {
|
||||
resetAuthToken(true);
|
||||
file_t *ef_pauthtoken = search_by_fid(EF_PAUTHTOKEN, NULL, SPECIFY_EF);
|
||||
ppaut.permissions = 0;
|
||||
@@ -200,7 +193,7 @@ int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, uint16_t in
|
||||
return -1;
|
||||
}
|
||||
|
||||
int authenticate(uint8_t protocol, const uint8_t *key, const uint8_t *data, size_t len, uint8_t *sign) {
|
||||
static int __attribute__((unused)) authenticate(uint8_t protocol, const uint8_t *key, const uint8_t *data, size_t len, uint8_t *sign) {
|
||||
uint8_t hmac[32];
|
||||
int ret =
|
||||
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), key, 32, data, len, hmac);
|
||||
@@ -236,16 +229,16 @@ int verify(uint8_t protocol, const uint8_t *key, const uint8_t *data, uint16_t l
|
||||
return -1;
|
||||
}
|
||||
|
||||
int initialize() {
|
||||
static int initialize(void) {
|
||||
regenerate();
|
||||
return resetPinUvAuthToken();
|
||||
}
|
||||
|
||||
int getPublicKey() {
|
||||
static int __attribute__((unused)) getPublicKey(void) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pinUvAuthTokenUsageTimerObserver() {
|
||||
static int __attribute__((unused)) pinUvAuthTokenUsageTimerObserver(void) {
|
||||
if (usage_timer == 0) {
|
||||
return -1;
|
||||
}
|
||||
@@ -266,11 +259,11 @@ int pinUvAuthTokenUsageTimerObserver() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int check_keydev_encrypted(const uint8_t pin_token[32]) {
|
||||
static int check_keydev_encrypted(const uint8_t pin_token[32]) {
|
||||
if (file_get_data(ef_keydev) && *file_get_data(ef_keydev) == 0x01) {
|
||||
uint8_t tmp_keydev[61];
|
||||
tmp_keydev[0] = 0x02; // Change format to encrypted
|
||||
encrypt_with_aad(pin_token, file_get_data(ef_keydev) + 1, 32, tmp_keydev + 1);
|
||||
tmp_keydev[0] = 0x03; // Change format to encrypted
|
||||
encrypt_with_aad(pin_token, file_get_data(ef_keydev) + 1, 32, 2, tmp_keydev + 1);
|
||||
file_put_data(ef_keydev, tmp_keydev, sizeof(tmp_keydev));
|
||||
mbedtls_platform_zeroize(tmp_keydev, sizeof(tmp_keydev));
|
||||
low_flash_available();
|
||||
|
||||
@@ -31,9 +31,6 @@
|
||||
|
||||
extern uint8_t keydev_dec[32];
|
||||
extern bool has_keydev_dec;
|
||||
extern void resetPersistentPinUvAuthToken();
|
||||
extern void resetPinUvAuthToken();
|
||||
|
||||
int cbor_config(const uint8_t *data, size_t len) {
|
||||
CborParser parser;
|
||||
CborValue map;
|
||||
|
||||
@@ -42,7 +42,7 @@ uint32_t timerx = 0;
|
||||
uint8_t *datax = NULL;
|
||||
size_t lenx = 0;
|
||||
|
||||
void reset_gna_state() {
|
||||
void reset_gna_state(void) {
|
||||
for (int i = 0; i < MAX_CREDENTIAL_COUNT_IN_LIST; i++) {
|
||||
credential_free(&credsx[i]);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include "apdu.h"
|
||||
#include "version.h"
|
||||
|
||||
int cbor_get_info() {
|
||||
int cbor_get_info(void) {
|
||||
CborEncoder encoder, mapEncoder, arrayEncoder, mapEncoder2;
|
||||
CborError error = CborNoError;
|
||||
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "pico_keys.h"
|
||||
#include "file.h"
|
||||
#include "fido.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "ctap.h"
|
||||
#if defined(PICO_PLATFORM)
|
||||
#include "bsp/board.h"
|
||||
@@ -27,9 +28,7 @@
|
||||
#endif
|
||||
#include "fs/phy.h"
|
||||
|
||||
extern void scan_all();
|
||||
|
||||
int cbor_reset() {
|
||||
int cbor_reset(void) {
|
||||
#ifndef ENABLE_EMULATION
|
||||
#if defined(ENABLE_POWER_ON_RESET) && ENABLE_POWER_ON_RESET == 1
|
||||
if (!(phy_data.opts & PHY_OPT_DISABLE_POWER_RESET) && board_millis() > 10000) {
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "fido.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "ctap.h"
|
||||
|
||||
int cbor_selection() {
|
||||
int cbor_selection(void) {
|
||||
if (wait_button_pressed() == true) {
|
||||
return CTAP2_ERR_USER_ACTION_TIMEOUT;
|
||||
}
|
||||
|
||||
@@ -42,7 +42,7 @@ int mse_decrypt_ct(uint8_t *data, size_t len) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
static int cbor_vendor_generic(uint8_t cmd, const uint8_t *data, size_t len) {
|
||||
CborParser parser;
|
||||
CborValue map;
|
||||
CborError error = CborNoError;
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "files.h"
|
||||
#include "credential.h"
|
||||
|
||||
int cmd_authenticate() {
|
||||
int cmd_authenticate(void) {
|
||||
CTAP_AUTHENTICATE_REQ *req = (CTAP_AUTHENTICATE_REQ *) apdu.data;
|
||||
CTAP_AUTHENTICATE_RESP *resp = (CTAP_AUTHENTICATE_RESP *) res_APDU;
|
||||
//if (scan_files_fido(true) != PICOKEY_OK)
|
||||
|
||||
@@ -29,10 +29,10 @@ const uint8_t u2f_aid[] = {
|
||||
0xA0, 0x00, 0x00, 0x05, 0x27, 0x10, 0x02
|
||||
};
|
||||
|
||||
int u2f_unload();
|
||||
int u2f_process_apdu();
|
||||
static int u2f_unload(void);
|
||||
static int u2f_process_apdu(void);
|
||||
|
||||
int u2f_select(app_t *a, uint8_t force) {
|
||||
static int u2f_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
if (cap_supported(CAP_U2F)) {
|
||||
a->process_apdu = u2f_process_apdu;
|
||||
@@ -46,15 +46,14 @@ INITIALIZER ( u2f_ctor ) {
|
||||
register_app(u2f_select, u2f_aid);
|
||||
}
|
||||
|
||||
int u2f_unload() {
|
||||
int u2f_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
const uint8_t *bogus_firefox = (const uint8_t *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00";
|
||||
const uint8_t *bogus_chrome = (const uint8_t *) "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
|
||||
|
||||
extern int ctap_error(uint8_t error);
|
||||
int cmd_register() {
|
||||
int cmd_register(void) {
|
||||
CTAP_REGISTER_REQ *req = (CTAP_REGISTER_REQ *) apdu.data;
|
||||
CTAP_REGISTER_RESP *resp = (CTAP_REGISTER_RESP *) res_APDU;
|
||||
resp->registerId = CTAP_REGISTER_ID;
|
||||
@@ -116,10 +115,6 @@ int cmd_register() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
extern int cmd_register();
|
||||
extern int cmd_authenticate();
|
||||
extern int cmd_version();
|
||||
|
||||
static const cmd_t cmds[] = {
|
||||
{ CTAP_REGISTER, cmd_register },
|
||||
{ CTAP_AUTHENTICATE, cmd_authenticate },
|
||||
@@ -127,7 +122,7 @@ static const cmd_t cmds[] = {
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int u2f_process_apdu() {
|
||||
int u2f_process_apdu(void) {
|
||||
if (CLA(apdu) != 0x00) {
|
||||
return SW_CLA_NOT_SUPPORTED();
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
|
||||
#include "apdu.h"
|
||||
#include "pico_keys.h"
|
||||
#include "fido.h"
|
||||
|
||||
int cmd_version() {
|
||||
int cmd_version(void) {
|
||||
memcpy(res_APDU, "U2F_V2", strlen("U2F_V2"));
|
||||
res_APDU_size = (uint16_t)strlen("U2F_V2");
|
||||
return SW_OK();
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "files.h"
|
||||
#include "otp.h"
|
||||
|
||||
extern bool has_set_rtc();
|
||||
int credential_derive_chacha_key(uint8_t *outk, const uint8_t *);
|
||||
|
||||
static int credential_silent_tag(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash, uint8_t *outk) {
|
||||
|
||||
@@ -129,8 +129,7 @@ typedef struct {
|
||||
#define CTAP_VENDOR_MSE 0x02
|
||||
#define CTAP_VENDOR_UNLOCK 0x03
|
||||
#define CTAP_VENDOR_EA 0x04
|
||||
#define CTAP_VENDOR_PHY_OPTS 0x05
|
||||
#define CTAP_VENDOR_MEMORY 0x06
|
||||
#define CTAP_VENDOR_ADMIN_PIN 0x08
|
||||
|
||||
#define CTAP_PERMISSION_MC 0x01 // MakeCredential
|
||||
#define CTAP_PERMISSION_GA 0x02 // GetAssertion
|
||||
|
||||
@@ -19,16 +19,23 @@
|
||||
#define _CTAP2_CBOR_H_
|
||||
|
||||
#include "cbor.h"
|
||||
#ifndef ESP_PLATFORM
|
||||
#include "common.h"
|
||||
#else
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#endif
|
||||
#include "mbedtls/ecp.h"
|
||||
#include "mbedtls/ecdh.h"
|
||||
|
||||
extern uint8_t *driver_prepare_response();
|
||||
extern uint8_t *driver_prepare_response(void);
|
||||
extern void driver_exec_finished(size_t size_next);
|
||||
extern int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len);
|
||||
extern int cbor_get_info(void);
|
||||
extern int cbor_reset(void);
|
||||
extern int cbor_make_credential(const uint8_t *data, size_t len);
|
||||
extern int cbor_client_pin(const uint8_t *data, size_t len);
|
||||
extern int cbor_selection(void);
|
||||
extern int cbor_get_next_assertion(const uint8_t *data, size_t len);
|
||||
extern int cbor_cred_mgmt(const uint8_t *data, size_t len);
|
||||
extern int cbor_config(const uint8_t *data, size_t len);
|
||||
extern int cbor_large_blobs(const uint8_t *data, size_t len);
|
||||
extern int cbor_vendor(const uint8_t *data, size_t len);
|
||||
extern void reset_gna_state(void);
|
||||
extern int cbor_process(uint8_t, const uint8_t *data, size_t len);
|
||||
extern const uint8_t aaguid[16];
|
||||
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "fido.h"
|
||||
#include "kek.h"
|
||||
#include "apdu.h"
|
||||
#include "ctap.h"
|
||||
#include "files.h"
|
||||
@@ -34,12 +33,12 @@
|
||||
#include <math.h>
|
||||
#include "management.h"
|
||||
#include "hid/ctap_hid.h"
|
||||
#include "ctap2_cbor.h"
|
||||
#include "version.h"
|
||||
#include "crypto_utils.h"
|
||||
#include "otp.h"
|
||||
|
||||
int fido_process_apdu();
|
||||
int fido_unload();
|
||||
static int fido_unload(void);
|
||||
|
||||
pinUvAuthToken_t paut = { 0 };
|
||||
persistentPinUvAuthToken_t ppaut = { 0 };
|
||||
@@ -64,14 +63,14 @@ const uint8_t atr_fido[] = {
|
||||
0x75, 0x62, 0x69, 0x4b, 0x65, 0x79, 0x40
|
||||
};
|
||||
|
||||
uint8_t fido_get_version_major() {
|
||||
static uint8_t fido_get_version_major(void) {
|
||||
return PICO_FIDO_VERSION_MAJOR;
|
||||
}
|
||||
uint8_t fido_get_version_minor() {
|
||||
static uint8_t fido_get_version_minor(void) {
|
||||
return PICO_FIDO_VERSION_MINOR;
|
||||
}
|
||||
|
||||
int fido_select(app_t *a, uint8_t force) {
|
||||
static int fido_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
if (cap_supported(CAP_FIDO2)) {
|
||||
a->process_apdu = fido_process_apdu;
|
||||
@@ -81,8 +80,8 @@ int fido_select(app_t *a, uint8_t force) {
|
||||
return PICOKEY_ERR_FILE_NOT_FOUND;
|
||||
}
|
||||
|
||||
extern uint8_t (*get_version_major)();
|
||||
extern uint8_t (*get_version_minor)();
|
||||
extern uint8_t (*get_version_major)(void);
|
||||
extern uint8_t (*get_version_minor)(void);
|
||||
|
||||
INITIALIZER ( fido_ctor ) {
|
||||
#if defined(USB_ITF_CCID) || defined(ENABLE_EMULATION)
|
||||
@@ -94,7 +93,7 @@ INITIALIZER ( fido_ctor ) {
|
||||
register_app(fido_select, fido_aid_backup);
|
||||
}
|
||||
|
||||
int fido_unload() {
|
||||
static int fido_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
@@ -150,7 +149,7 @@ int mbedtls_curve_to_fido(mbedtls_ecp_group_id id) {
|
||||
return FIDO2_CURVE_P256K1;
|
||||
}
|
||||
else if (id == MBEDTLS_ECP_DP_CURVE25519) {
|
||||
return MBEDTLS_ECP_DP_CURVE25519;
|
||||
return FIDO2_CURVE_X25519;
|
||||
}
|
||||
else if (id == MBEDTLS_ECP_DP_CURVE448) {
|
||||
return FIDO2_CURVE_X448;
|
||||
@@ -173,14 +172,18 @@ int fido_load_key(int curve, const uint8_t *cred_id, mbedtls_ecp_keypair *key) {
|
||||
}
|
||||
uint8_t key_path[KEY_PATH_LEN];
|
||||
memcpy(key_path, cred_id, KEY_PATH_LEN);
|
||||
*(uint32_t *) key_path = 0x80000000 | 10022;
|
||||
uint32_t key_path_first = 0x80000000u | 10022u;
|
||||
memcpy(key_path, &key_path_first, sizeof(key_path_first));
|
||||
for (size_t i = 1; i < KEY_PATH_ENTRIES; i++) {
|
||||
*(uint32_t *) (key_path + i * sizeof(uint32_t)) |= 0x80000000;
|
||||
uint32_t part = 0;
|
||||
memcpy(&part, key_path + i * sizeof(uint32_t), sizeof(part));
|
||||
part |= 0x80000000u;
|
||||
memcpy(key_path + i * sizeof(uint32_t), &part, sizeof(part));
|
||||
}
|
||||
return derive_key(NULL, false, key_path, mbedtls_curve, key);
|
||||
}
|
||||
|
||||
int x509_create_cert(mbedtls_ecdsa_context *ecdsa, uint8_t *buffer, size_t buffer_size) {
|
||||
static int x509_create_cert(mbedtls_ecdsa_context *ecdsa, uint8_t *buffer, size_t buffer_size) {
|
||||
mbedtls_x509write_cert ctx;
|
||||
mbedtls_x509write_crt_init(&ctx);
|
||||
mbedtls_x509write_crt_set_version(&ctx, MBEDTLS_X509_CRT_VERSION_3);
|
||||
@@ -222,23 +225,31 @@ int load_keydev(uint8_t key[32]) {
|
||||
uint16_t fid_size = file_get_size(ef_keydev);
|
||||
if (fid_size == 32) {
|
||||
memcpy(key, file_get_data(ef_keydev), 32);
|
||||
if (mkek_decrypt(key, 32) != PICOKEY_OK) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
}
|
||||
if (otp_key_1 && aes_decrypt(otp_key_1, NULL, 32 * 8, PICO_KEYS_AES_MODE_CBC, key, 32) != PICOKEY_OK) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
}
|
||||
}
|
||||
else if (fid_size == 33 || fid_size == 61) {
|
||||
uint8_t format = *file_get_data(ef_keydev);
|
||||
if (format == 0x01 || format == 0x02) { // Format indicator
|
||||
if (format == 0x02) {
|
||||
uint8_t tmp_key[61];
|
||||
if (format == 0x01 || format == 0x02 || format == 0x03) { // Format indicator
|
||||
if (format == 0x02 || format == 0x03) {
|
||||
uint8_t tmp_key[61], version = format == 0x03 ? 2 : 1;
|
||||
memcpy(tmp_key, file_get_data(ef_keydev), sizeof(tmp_key));
|
||||
int ret = decrypt_with_aad(session_pin, tmp_key + 1, 60, key);
|
||||
int ret = decrypt_with_aad(session_pin, tmp_key + 1, 60, version, key);
|
||||
if (ret != PICOKEY_OK) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
}
|
||||
if (format == 0x02) {
|
||||
tmp_key[0] = 0x03;
|
||||
ret = encrypt_with_aad(session_pin, key, 32, 2, tmp_key + 1);
|
||||
if (ret != PICOKEY_OK) {
|
||||
mbedtls_platform_zeroize(tmp_key, sizeof(tmp_key));
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
}
|
||||
file_put_data(ef_keydev, tmp_key, sizeof(tmp_key));
|
||||
low_flash_available();
|
||||
}
|
||||
mbedtls_platform_zeroize(tmp_key, sizeof(tmp_key));
|
||||
}
|
||||
else {
|
||||
memcpy(key, file_get_data(ef_keydev) + 1, 32);
|
||||
@@ -260,7 +271,8 @@ int load_keydev(uint8_t key[32]) {
|
||||
|
||||
int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecp_keypair *key) {
|
||||
for (size_t i = 0; i < KEY_PATH_ENTRIES; i++) {
|
||||
uint32_t k = *(uint32_t *) &keyHandle[i * sizeof(uint32_t)];
|
||||
uint32_t k = 0;
|
||||
memcpy(&k, &keyHandle[i * sizeof(uint32_t)], sizeof(k));
|
||||
if (!(k & 0x80000000)) {
|
||||
return -1;
|
||||
}
|
||||
@@ -331,7 +343,7 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur
|
||||
if (cinfo->bit_size % 8 != 0) {
|
||||
outk[0] >>= 8 - (cinfo->bit_size % 8);
|
||||
}
|
||||
r = mbedtls_ecp_read_key(curve, key, outk, (size_t)ceil((float) cinfo->bit_size / 8));
|
||||
r = mbedtls_ecp_read_key(curve, key, outk, (size_t)((cinfo->bit_size + 7) / 8));
|
||||
mbedtls_platform_zeroize(outk, sizeof(outk));
|
||||
if (r != 0) {
|
||||
return r;
|
||||
@@ -364,10 +376,9 @@ int encrypt_keydev_f1(const uint8_t keydev[32]) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
int scan_files_fido() {
|
||||
int scan_files_fido(void) {
|
||||
ef_keydev = search_by_fid(EF_KEY_DEV, NULL, SPECIFY_EF);
|
||||
ef_keydev_enc = search_by_fid(EF_KEY_DEV_ENC, NULL, SPECIFY_EF);
|
||||
ef_mkek = search_by_fid(EF_MKEK, NULL, SPECIFY_EF);
|
||||
if (ef_keydev) {
|
||||
if (!file_has_data(ef_keydev) && !file_has_data(ef_keydev_enc)) {
|
||||
printf("KEY DEVICE is empty. Generating SECP256R1 curve...");
|
||||
@@ -442,6 +453,7 @@ int scan_files_fido() {
|
||||
printf("FATAL ERROR: Global counter not found in memory!\r\n");
|
||||
}
|
||||
ef_pin = search_by_fid(EF_PIN, NULL, SPECIFY_EF);
|
||||
ef_pin_admin = search_by_fid(EF_PIN_ADMIN, NULL, SPECIFY_EF);
|
||||
ef_authtoken = search_by_fid(EF_AUTHTOKEN, NULL, SPECIFY_EF);
|
||||
if (ef_authtoken) {
|
||||
if (!file_has_data(ef_authtoken)) {
|
||||
@@ -477,14 +489,13 @@ int scan_files_fido() {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
void scan_all() {
|
||||
void scan_all(void) {
|
||||
scan_flash();
|
||||
scan_files_fido();
|
||||
}
|
||||
|
||||
extern void init_otp();
|
||||
extern bool needs_power_cycle;
|
||||
void init_fido() {
|
||||
void init_fido(void) {
|
||||
scan_all();
|
||||
#ifdef ENABLE_OTP_APP
|
||||
init_otp();
|
||||
@@ -492,7 +503,7 @@ void init_fido() {
|
||||
needs_power_cycle = false;
|
||||
}
|
||||
|
||||
bool wait_button_pressed() {
|
||||
bool wait_button_pressed(void) {
|
||||
uint32_t val = EV_PRESS_BUTTON;
|
||||
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
|
||||
queue_try_add(&card_to_usb_q, &val);
|
||||
@@ -505,7 +516,7 @@ bool wait_button_pressed() {
|
||||
|
||||
uint32_t user_present_time_limit = 0;
|
||||
|
||||
bool check_user_presence() {
|
||||
bool check_user_presence(void) {
|
||||
if (user_present_time_limit == 0 || user_present_time_limit + TRANSPORT_TIME_LIMIT < board_millis()) {
|
||||
if (wait_button_pressed() == true) { //timeout
|
||||
return false;
|
||||
@@ -515,12 +526,12 @@ bool check_user_presence() {
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t get_sign_counter() {
|
||||
uint32_t get_sign_counter(void) {
|
||||
uint8_t *caddr = file_get_data(ef_counter);
|
||||
return get_uint32_t_le(caddr);
|
||||
}
|
||||
|
||||
uint8_t get_opts() {
|
||||
uint8_t get_opts(void) {
|
||||
file_t *ef = search_by_fid(EF_OPTS, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef)) {
|
||||
return *file_get_data(ef);
|
||||
@@ -534,16 +545,9 @@ void set_opts(uint8_t opts) {
|
||||
low_flash_available();
|
||||
}
|
||||
|
||||
extern int cmd_register();
|
||||
extern int cmd_authenticate();
|
||||
extern int cmd_version();
|
||||
extern int cbor_parse(int, uint8_t *, size_t);
|
||||
extern int cbor_vendor(const uint8_t *data, size_t len);
|
||||
extern void driver_init_hid();
|
||||
|
||||
#define CTAP_CBOR 0x10
|
||||
|
||||
int cmd_vendor() {
|
||||
static int cmd_vendor(void) {
|
||||
uint8_t *old_buf = res_APDU;
|
||||
driver_init_hid();
|
||||
int ret = cbor_vendor(apdu.data, apdu.nc);
|
||||
@@ -556,7 +560,7 @@ int cmd_vendor() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_cbor() {
|
||||
static int cmd_cbor(void) {
|
||||
uint8_t *old_buf = res_APDU;
|
||||
driver_init_hid();
|
||||
int ret = cbor_parse(0x90, apdu.data, apdu.nc);
|
||||
@@ -578,7 +582,7 @@ static const cmd_t cmds[] = {
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int fido_process_apdu() {
|
||||
int fido_process_apdu(void) {
|
||||
if (CLA(apdu) != 0x00 && CLA(apdu) != 0x80) {
|
||||
return SW_CLA_NOT_SUPPORTED();
|
||||
}
|
||||
|
||||
@@ -21,11 +21,6 @@
|
||||
#if defined(PICO_PLATFORM)
|
||||
#include "pico/stdlib.h"
|
||||
#endif
|
||||
#ifndef ESP_PLATFORM
|
||||
#include "common.h"
|
||||
#else
|
||||
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
|
||||
#endif
|
||||
|
||||
#include "mbedtls/ecdsa.h"
|
||||
#ifdef MBEDTLS_EDDSA_C
|
||||
@@ -39,15 +34,17 @@
|
||||
#define SHA256_DIGEST_LENGTH (32)
|
||||
#define KEY_HANDLE_LEN (KEY_PATH_LEN + SHA256_DIGEST_LENGTH)
|
||||
|
||||
extern int scan_files_fido();
|
||||
extern int scan_files_fido(void);
|
||||
extern int derive_key(const uint8_t *app_id,
|
||||
bool new_key,
|
||||
uint8_t *key_handle,
|
||||
int,
|
||||
mbedtls_ecp_keypair *key);
|
||||
extern int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecp_keypair *);
|
||||
extern bool wait_button_pressed();
|
||||
extern void init_fido();
|
||||
extern bool wait_button_pressed(void);
|
||||
extern void init_fido(void);
|
||||
extern void init_otp(void);
|
||||
extern void scan_all(void);
|
||||
extern mbedtls_ecp_group_id fido_curve_to_mbedtls(int curve);
|
||||
extern int mbedtls_curve_to_fido(mbedtls_ecp_group_id id);
|
||||
extern int fido_load_key(int curve, const uint8_t *cred_id, mbedtls_ecp_keypair *key);
|
||||
@@ -95,14 +92,14 @@ extern int ecdh(uint8_t protocol, const mbedtls_ecp_point *Q, uint8_t *sharedSec
|
||||
#define FIDO2_OPT_AUV 0x02 // User Verification
|
||||
|
||||
#define MAX_PIN_RETRIES 8
|
||||
extern bool getUserPresentFlagValue();
|
||||
extern bool getUserVerifiedFlagValue();
|
||||
extern void clearUserPresentFlag();
|
||||
extern void clearUserVerifiedFlag();
|
||||
extern void clearPinUvAuthTokenPermissionsExceptLbw();
|
||||
extern void send_keepalive();
|
||||
extern uint32_t get_sign_counter();
|
||||
extern uint8_t get_opts();
|
||||
extern bool getUserPresentFlagValue(void);
|
||||
extern bool getUserVerifiedFlagValue(void);
|
||||
extern void clearUserPresentFlag(void);
|
||||
extern void clearUserVerifiedFlag(void);
|
||||
extern void clearPinUvAuthTokenPermissionsExceptLbw(void);
|
||||
extern void send_keepalive(void);
|
||||
extern uint32_t get_sign_counter(void);
|
||||
extern uint8_t get_opts(void);
|
||||
extern void set_opts(uint8_t);
|
||||
#define MAX_CREDENTIAL_COUNT_IN_LIST 16
|
||||
#define MAX_CRED_ID_LENGTH 1024
|
||||
@@ -123,7 +120,19 @@ extern const known_app_t *find_app_by_rp_id_hash(const uint8_t *rp_id_hash);
|
||||
|
||||
#define TRANSPORT_TIME_LIMIT (30 * 1000) //USB
|
||||
|
||||
bool check_user_presence();
|
||||
bool check_user_presence(void);
|
||||
int fido_process_apdu(void);
|
||||
int cmd_register(void);
|
||||
int cmd_authenticate(void);
|
||||
int cmd_version(void);
|
||||
int calculate_oath(uint8_t truncate,
|
||||
const uint8_t *key,
|
||||
size_t key_len,
|
||||
const uint8_t *chal,
|
||||
size_t chal_len);
|
||||
int encrypt_keydev_f1(const uint8_t keydev[32]);
|
||||
int resetPinUvAuthToken(void);
|
||||
int resetPersistentPinUvAuthToken(void);
|
||||
|
||||
typedef struct pinUvAuthToken {
|
||||
uint8_t *data;
|
||||
|
||||
@@ -21,7 +21,6 @@ file_t file_entries[] = {
|
||||
{ .fid = 0x3f00, .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = 0, .acl = { 0 } }, // MF
|
||||
{ .fid = EF_KEY_DEV, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // Device Key
|
||||
{ .fid = EF_KEY_DEV_ENC, .parent = 0, .name = NULL,.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // Device Key Enc
|
||||
{ .fid = EF_MKEK, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // MKEK
|
||||
{ .fid = EF_EE_DEV, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // End Entity Certificate Device
|
||||
{ .fid = EF_EE_DEV_EA, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // End Entity Enterprise Attestation Certificate
|
||||
{ .fid = EF_COUNTER, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // Global counter
|
||||
@@ -32,6 +31,7 @@ file_t file_entries[] = {
|
||||
{ .fid = EF_OPTS, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // Global options
|
||||
{ .fid = EF_LARGEBLOB, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // Large Blob
|
||||
{ .fid = EF_OTP_PIN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } },
|
||||
{ .fid = EF_PIN_ADMIN, .parent = 0, .name = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, // ADMIN PIN
|
||||
{ .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL, .ef_structure = 0, .acl = { 0 } } //end
|
||||
};
|
||||
|
||||
@@ -41,7 +41,7 @@ file_t *ef_keydev = NULL;
|
||||
file_t *ef_certdev = NULL;
|
||||
file_t *ef_counter = NULL;
|
||||
file_t *ef_pin = NULL;
|
||||
file_t *ef_pin_admin = NULL;
|
||||
file_t *ef_authtoken = NULL;
|
||||
file_t *ef_keydev_enc = NULL;
|
||||
file_t *ef_largeblob = NULL;
|
||||
file_t *ef_mkek = NULL;
|
||||
|
||||
@@ -22,12 +22,12 @@
|
||||
|
||||
#define EF_KEY_DEV 0xCC00
|
||||
#define EF_KEY_DEV_ENC 0xCC01
|
||||
#define EF_MKEK 0xCC0F
|
||||
#define EF_EE_DEV 0xCE00
|
||||
#define EF_EE_DEV_EA 0xCE01
|
||||
#define EF_COUNTER 0xC000
|
||||
#define EF_OPTS 0xC001
|
||||
#define EF_PIN 0x1080
|
||||
#define EF_PIN_ADMIN 0x1084
|
||||
#define EF_AUTHTOKEN 0x1090
|
||||
#define EF_PAUTHTOKEN 0x1091
|
||||
#define EF_MINPINLEN 0x1100
|
||||
@@ -48,9 +48,9 @@ extern file_t *ef_keydev;
|
||||
extern file_t *ef_certdev;
|
||||
extern file_t *ef_counter;
|
||||
extern file_t *ef_pin;
|
||||
extern file_t *ef_pin_admin;
|
||||
extern file_t *ef_authtoken;
|
||||
extern file_t *ef_keydev_enc;
|
||||
extern file_t *ef_largeblob;
|
||||
extern file_t *ef_mkek;
|
||||
|
||||
#endif //_FILES_H_
|
||||
|
||||
@@ -1,84 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Pico Fido distribution (https://github.com/polhenarejos/pico-fido).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "pico_keys.h"
|
||||
#include "fido.h"
|
||||
#include "stdlib.h"
|
||||
#if defined(PICO_PLATFORM)
|
||||
#include "pico/stdlib.h"
|
||||
#endif
|
||||
#include "kek.h"
|
||||
#include "crypto_utils.h"
|
||||
#include "random.h"
|
||||
#include "mbedtls/md.h"
|
||||
#include "mbedtls/cmac.h"
|
||||
#include "mbedtls/rsa.h"
|
||||
#include "mbedtls/ecdsa.h"
|
||||
#include "mbedtls/chachapoly.h"
|
||||
#include "files.h"
|
||||
#include "otp.h"
|
||||
|
||||
extern uint8_t session_pin[32];
|
||||
uint8_t mkek_mask[MKEK_KEY_SIZE];
|
||||
bool has_mkek_mask = false;
|
||||
|
||||
void mkek_masked(uint8_t *mkek, const uint8_t *mask) {
|
||||
if (mask) {
|
||||
for (int i = 0; i < MKEK_KEY_SIZE; i++) {
|
||||
MKEK_KEY(mkek)[i] ^= mask[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int load_mkek(uint8_t *mkek) {
|
||||
file_t *tf = search_file(EF_MKEK);
|
||||
if (file_has_data(tf)) {
|
||||
memcpy(mkek, file_get_data(tf), MKEK_SIZE);
|
||||
}
|
||||
|
||||
if (has_mkek_mask) {
|
||||
mkek_masked(mkek, mkek_mask);
|
||||
}
|
||||
if (file_get_size(tf) == MKEK_SIZE) {
|
||||
int ret = aes_decrypt_cfb_256(session_pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE);
|
||||
if (ret != 0) {
|
||||
return PICOKEY_EXEC_ERROR;
|
||||
}
|
||||
if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != *(uint32_t *) MKEK_CHECKSUM(mkek)) {
|
||||
return PICOKEY_WRONG_DKEK;
|
||||
}
|
||||
if (otp_key_1) {
|
||||
mkek_masked(mkek, otp_key_1);
|
||||
}
|
||||
}
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
void release_mkek(uint8_t *mkek) {
|
||||
mbedtls_platform_zeroize(mkek, MKEK_SIZE);
|
||||
}
|
||||
|
||||
int mkek_decrypt(uint8_t *data, uint16_t len) {
|
||||
int r;
|
||||
uint8_t mkek[MKEK_SIZE + 4];
|
||||
if ((r = load_mkek(mkek)) != PICOKEY_OK) {
|
||||
return r;
|
||||
}
|
||||
r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
|
||||
release_mkek(mkek);
|
||||
return r;
|
||||
}
|
||||
@@ -1,46 +0,0 @@
|
||||
/*
|
||||
* This file is part of the Pico Fido distribution (https://github.com/polhenarejos/pico-fido).
|
||||
* Copyright (c) 2022 Pol Henarejos.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, version 3.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef _KEK_H_
|
||||
#define _KEK_H_
|
||||
|
||||
#include "crypto_utils.h"
|
||||
#if defined(ENABLE_EMULATION) || defined(ESP_PLATFORM)
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
|
||||
extern int load_mkek(uint8_t *);
|
||||
extern int store_mkek(const uint8_t *);
|
||||
extern void init_mkek();
|
||||
extern void release_mkek(uint8_t *);
|
||||
extern int mkek_encrypt(uint8_t *data, uint16_t len);
|
||||
extern int mkek_decrypt(uint8_t *data, uint16_t len);
|
||||
|
||||
#define MKEK_IV_SIZE (IV_SIZE)
|
||||
#define MKEK_KEY_SIZE (32)
|
||||
#define MKEK_KEY_CS_SIZE (4)
|
||||
#define MKEK_SIZE (MKEK_IV_SIZE + MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE)
|
||||
#define MKEK_IV(p) (p)
|
||||
#define MKEK_KEY(p) (MKEK_IV(p) + MKEK_IV_SIZE)
|
||||
#define MKEK_CHECKSUM(p) (MKEK_KEY(p) + MKEK_KEY_SIZE)
|
||||
#define DKEK_KEY_SIZE (32)
|
||||
|
||||
extern uint8_t mkek_mask[MKEK_KEY_SIZE];
|
||||
extern bool has_mkek_mask;
|
||||
|
||||
#endif
|
||||
@@ -25,16 +25,14 @@
|
||||
|
||||
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 scan_all();
|
||||
extern void init_otp();
|
||||
int man_select(app_t *a, uint8_t force) {
|
||||
static int man_select(app_t *a, uint8_t force) {
|
||||
a->process_apdu = man_process_apdu;
|
||||
a->unload = man_unload;
|
||||
sprintf((char *) res_APDU, "%d.%d.0", PICO_FIDO_VERSION_MAJOR, PICO_FIDO_VERSION_MINOR);
|
||||
@@ -54,7 +52,7 @@ INITIALIZER ( man_ctor ) {
|
||||
register_app(man_select, man_aid);
|
||||
}
|
||||
|
||||
int man_unload() {
|
||||
static int man_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
@@ -88,7 +86,7 @@ static uint8_t _piv_aid[] = {
|
||||
0xA0, 0x00, 0x00, 0x03, 0x8,
|
||||
};
|
||||
|
||||
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
|
||||
@@ -155,12 +153,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();
|
||||
}
|
||||
@@ -179,8 +177,8 @@ int cmd_write_config() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
extern int cbor_reset();
|
||||
int cmd_factory_reset() {
|
||||
extern int cbor_reset(void);
|
||||
static int cmd_factory_reset(void) {
|
||||
cbor_reset();
|
||||
return SW_OK();
|
||||
}
|
||||
@@ -196,7 +194,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
|
||||
|
||||
@@ -24,7 +24,6 @@
|
||||
#include "asn1.h"
|
||||
#include "crypto_utils.h"
|
||||
#include "management.h"
|
||||
extern bool is_nk;
|
||||
|
||||
#define MAX_OATH_CRED 255
|
||||
#define CHALLENGE_LEN 8
|
||||
@@ -63,8 +62,8 @@ extern bool is_nk;
|
||||
#define PROP_TOUCH 0x02
|
||||
#define PROP_PIN 0x03
|
||||
|
||||
int oath_process_apdu();
|
||||
int oath_unload();
|
||||
static int oath_process_apdu(void);
|
||||
static int oath_unload(void);
|
||||
|
||||
static bool validated = true;
|
||||
static uint8_t challenge[CHALLENGE_LEN] = { 0 };
|
||||
@@ -74,7 +73,7 @@ const uint8_t oath_aid[] = {
|
||||
0xa0, 0x00, 0x00, 0x05, 0x27, 0x21, 0x01
|
||||
};
|
||||
|
||||
int oath_select(app_t *a, uint8_t force) {
|
||||
static int oath_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
if (cap_supported(CAP_OATH)) {
|
||||
a->process_apdu = oath_process_apdu;
|
||||
@@ -121,11 +120,11 @@ INITIALIZER ( oath_ctor ) {
|
||||
register_app(oath_select, oath_aid);
|
||||
}
|
||||
|
||||
int oath_unload() {
|
||||
static int oath_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
file_t *find_oath_cred(const uint8_t *name, size_t name_len) {
|
||||
static file_t *find_oath_cred(const uint8_t *name, size_t name_len) {
|
||||
for (int i = 0; i < MAX_OATH_CRED; i++) {
|
||||
file_t *ef = search_dynamic_file((uint16_t)(EF_OATH_CRED + i));
|
||||
asn1_ctx_t ctxi, ef_tag = { 0 };
|
||||
@@ -137,7 +136,7 @@ file_t *find_oath_cred(const uint8_t *name, size_t name_len) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cmd_put() {
|
||||
static int cmd_put(void) {
|
||||
if (validated == false) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
@@ -185,7 +184,7 @@ int cmd_put() {
|
||||
}
|
||||
|
||||
|
||||
int cmd_delete() {
|
||||
static int cmd_delete(void) {
|
||||
if (validated == false) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
@@ -202,7 +201,7 @@ int cmd_delete() {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
}
|
||||
|
||||
const mbedtls_md_info_t *get_oath_md_info(uint8_t alg) {
|
||||
static const mbedtls_md_info_t *get_oath_md_info(uint8_t alg) {
|
||||
if ((alg & ALG_MASK) == ALG_HMAC_SHA1) {
|
||||
return mbedtls_md_info_from_type(MBEDTLS_MD_SHA1);
|
||||
}
|
||||
@@ -215,7 +214,7 @@ const mbedtls_md_info_t *get_oath_md_info(uint8_t alg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int cmd_set_code() {
|
||||
static int cmd_set_code(void) {
|
||||
if (validated == false) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
@@ -261,7 +260,7 @@ int cmd_set_code() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_reset() {
|
||||
static int cmd_reset(void) {
|
||||
if (P1(apdu) != 0xde || P2(apdu) != 0xad) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -278,7 +277,7 @@ int cmd_reset() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_list() {
|
||||
static int cmd_list(void) {
|
||||
if (validated == false) {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
@@ -310,7 +309,7 @@ int cmd_list() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_validate() {
|
||||
static int cmd_validate(void) {
|
||||
asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, resp = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (asn1_find_tag(&ctxi, TAG_CHALLENGE, &chal) == false) {
|
||||
@@ -380,7 +379,7 @@ int calculate_oath(uint8_t truncate, const uint8_t *key, size_t key_len, const u
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
int cmd_calculate() {
|
||||
static int cmd_calculate(void) {
|
||||
if (P2(apdu) != 0x0 && P2(apdu) != 0x1) {
|
||||
return SW_INCORRECT_P1P2();
|
||||
}
|
||||
@@ -435,7 +434,7 @@ int cmd_calculate() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_calculate_all() {
|
||||
static int cmd_calculate_all(void) {
|
||||
asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }, prop = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
if (P2(apdu) != 0x0 && P2(apdu) != 0x1) {
|
||||
@@ -485,11 +484,11 @@ int cmd_calculate_all() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_send_remaining() {
|
||||
static int cmd_send_remaining(void) {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_set_otp_pin() {
|
||||
static int cmd_set_otp_pin(void) {
|
||||
uint8_t hsh[33] = { 0 };
|
||||
file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
if (file_has_data(ef_otp_pin)) {
|
||||
@@ -507,7 +506,7 @@ int cmd_set_otp_pin() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_change_otp_pin() {
|
||||
static int cmd_change_otp_pin(void) {
|
||||
uint8_t hsh[33] = { 0 };
|
||||
file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
if (!file_has_data(ef_otp_pin)) {
|
||||
@@ -532,7 +531,7 @@ int cmd_change_otp_pin() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_verify_otp_pin() {
|
||||
static int cmd_verify_otp_pin(void) {
|
||||
uint8_t hsh[33] = { 0 }, data_hsh[33];
|
||||
file_t *ef_otp_pin = search_by_fid(EF_OTP_PIN, NULL, SPECIFY_EF);
|
||||
if (!file_has_data(ef_otp_pin)) {
|
||||
@@ -561,7 +560,7 @@ int cmd_verify_otp_pin() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_verify_hotp() {
|
||||
static int cmd_verify_hotp(void) {
|
||||
asn1_ctx_t ctxi, key = { 0 }, chal = { 0 }, name = { 0 }, code = { 0 };
|
||||
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
|
||||
uint32_t code_int = 0;
|
||||
@@ -607,7 +606,7 @@ int cmd_verify_hotp() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_rename() {
|
||||
static int cmd_rename(void) {
|
||||
asn1_ctx_t ctxi, name = { 0 }, new_name = { 0 };
|
||||
|
||||
if (validated == false) {
|
||||
@@ -625,7 +624,7 @@ int cmd_rename() {
|
||||
if (asn1_find_tag(&ctxi, TAG_NAME, &new_name) == false) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
if (memcmp(name.data, new_name.data, name.len) == 0) {
|
||||
if (name.len == new_name.len && memcmp(name.data, new_name.data, name.len) == 0) {
|
||||
return SW_WRONG_DATA();
|
||||
}
|
||||
file_t *ef = find_oath_cred(name.data, name.len);
|
||||
@@ -649,7 +648,7 @@ int cmd_rename() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
int cmd_get_credential() {
|
||||
static int cmd_get_credential(void) {
|
||||
asn1_ctx_t ctxi, name = { 0 };
|
||||
if (apdu.nc < 3) {
|
||||
return SW_INCORRECT_PARAMS();
|
||||
@@ -731,7 +730,7 @@ static const cmd_t cmds[] = {
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int oath_process_apdu() {
|
||||
static int oath_process_apdu(void) {
|
||||
if (CLA(apdu) != 0x00) {
|
||||
return SW_CLA_NOT_SUPPORTED();
|
||||
}
|
||||
|
||||
@@ -28,8 +28,15 @@
|
||||
#include "bsp/board.h"
|
||||
#endif
|
||||
#ifdef ENABLE_EMULATION
|
||||
void add_keyboard_buffer(const uint8_t *buf, size_t len, bool press_enter) {}
|
||||
void append_keyboard_buffer(const uint8_t *buf, size_t len) {}
|
||||
void add_keyboard_buffer(const uint8_t *buf, size_t len, bool press_enter) {
|
||||
(void)buf;
|
||||
(void)len;
|
||||
(void)press_enter;
|
||||
}
|
||||
void append_keyboard_buffer(const uint8_t *buf, size_t len) {
|
||||
(void)buf;
|
||||
(void)len;
|
||||
}
|
||||
#else
|
||||
#include "tusb.h"
|
||||
#endif
|
||||
@@ -119,22 +126,21 @@ typedef struct otp_config {
|
||||
}) otp_config_t;
|
||||
|
||||
#define otp_config_size sizeof(otp_config_t)
|
||||
uint16_t otp_status(bool is_otp);
|
||||
|
||||
int otp_process_apdu();
|
||||
int otp_unload();
|
||||
static uint16_t otp_status(bool is_otp);
|
||||
static int otp_process_apdu(void);
|
||||
static int otp_unload(void);
|
||||
|
||||
extern int (*hid_set_report_cb)(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t);
|
||||
extern uint16_t (*hid_get_report_cb)(uint8_t, uint8_t, hid_report_type_t, uint8_t *, uint16_t);
|
||||
int otp_hid_set_report_cb(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t);
|
||||
uint16_t otp_hid_get_report_cb(uint8_t, uint8_t, hid_report_type_t, uint8_t *, uint16_t);
|
||||
static int otp_hid_set_report_cb(uint8_t, uint8_t, hid_report_type_t, uint8_t const *, uint16_t);
|
||||
static uint16_t otp_hid_get_report_cb(uint8_t, uint8_t, hid_report_type_t, uint8_t *, uint16_t);
|
||||
|
||||
const uint8_t otp_aid[] = {
|
||||
7,
|
||||
0xa0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x01
|
||||
};
|
||||
|
||||
int otp_select(app_t *a, uint8_t force) {
|
||||
static int otp_select(app_t *a, uint8_t force) {
|
||||
(void) force;
|
||||
if (cap_supported(CAP_OTP)) {
|
||||
a->process_apdu = otp_process_apdu;
|
||||
@@ -154,7 +160,7 @@ int otp_select(app_t *a, uint8_t force) {
|
||||
|
||||
uint8_t modhex_tab[] =
|
||||
{ 'c', 'b', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'n', 'r', 't', 'u', 'v' };
|
||||
int encode_modhex(const uint8_t *in, size_t len, uint8_t *out) {
|
||||
static int encode_modhex(const uint8_t *in, size_t len, uint8_t *out) {
|
||||
for (size_t l = 0; l < len; l++) {
|
||||
*out++ = modhex_tab[in[l] >> 4];
|
||||
*out++ = modhex_tab[in[l] & 0xf];
|
||||
@@ -162,8 +168,7 @@ int encode_modhex(const uint8_t *in, size_t len, uint8_t *out) {
|
||||
return 0;
|
||||
}
|
||||
static bool scanned = false;
|
||||
extern void scan_all();
|
||||
void init_otp() {
|
||||
void init_otp(void) {
|
||||
if (scanned == false) {
|
||||
scan_all();
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
@@ -185,13 +190,7 @@ void init_otp() {
|
||||
low_flash_available();
|
||||
}
|
||||
}
|
||||
extern int calculate_oath(uint8_t truncate,
|
||||
const uint8_t *key,
|
||||
size_t key_len,
|
||||
const uint8_t *chal,
|
||||
size_t chal_len);
|
||||
|
||||
uint16_t calculate_crc(const uint8_t *data, size_t data_len) {
|
||||
static uint16_t calculate_crc(const uint8_t *data, size_t data_len) {
|
||||
uint16_t crc = 0xFFFF;
|
||||
for (size_t idx = 0; idx < data_len; idx++) {
|
||||
crc ^= data[idx];
|
||||
@@ -207,7 +206,7 @@ uint16_t calculate_crc(const uint8_t *data, size_t data_len) {
|
||||
}
|
||||
|
||||
static uint8_t session_counter[2] = { 0 };
|
||||
int otp_button_pressed(uint8_t slot) {
|
||||
static int otp_button_pressed(uint8_t slot) {
|
||||
init_otp();
|
||||
if (!cap_supported(CAP_OTP)) {
|
||||
return 3;
|
||||
@@ -334,12 +333,12 @@ INITIALIZER( otp_ctor ) {
|
||||
hid_get_report_cb = otp_hid_get_report_cb;
|
||||
}
|
||||
|
||||
int otp_unload() {
|
||||
static int otp_unload(void) {
|
||||
return PICOKEY_OK;
|
||||
}
|
||||
|
||||
uint8_t status_byte = 0x0;
|
||||
uint16_t otp_status_ext() {
|
||||
static uint16_t otp_status_ext(void) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
file_t *ef = search_dynamic_file(EF_OTP_SLOT1 + i);
|
||||
if (file_has_data(ef)) {
|
||||
@@ -372,7 +371,7 @@ uint16_t otp_status_ext() {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
uint16_t otp_status(bool is_otp) {
|
||||
static uint16_t otp_status(bool is_otp) {
|
||||
if (scanned == false) {
|
||||
scan_all();
|
||||
scanned = true;
|
||||
@@ -415,13 +414,13 @@ uint16_t otp_status(bool is_otp) {
|
||||
return SW_OK();
|
||||
}
|
||||
|
||||
bool check_crc(const otp_config_t *data) {
|
||||
static bool check_crc(const otp_config_t *data) {
|
||||
uint16_t crc = calculate_crc((const uint8_t *) data, otp_config_size);
|
||||
return crc == 0xF0B8;
|
||||
}
|
||||
|
||||
bool _is_otp = false;
|
||||
int cmd_otp() {
|
||||
static int cmd_otp(void) {
|
||||
uint8_t p1 = P1(apdu), p2 = P2(apdu);
|
||||
if (p1 == 0x01 || p1 == 0x03) { // Configure slot
|
||||
otp_config_t *odata = (otp_config_t *) apdu.data;
|
||||
@@ -436,7 +435,7 @@ int cmd_otp() {
|
||||
return SW_SECURITY_STATUS_NOT_SATISFIED();
|
||||
}
|
||||
}
|
||||
for (int c = 0; c < otp_config_size; c++) {
|
||||
for (size_t c = 0; c < otp_config_size; c++) {
|
||||
if (apdu.data[c] != 0) {
|
||||
if (odata->rfu[0] != 0 || odata->rfu[1] != 0 || check_crc(odata) == false) {
|
||||
return SW_WRONG_DATA();
|
||||
@@ -608,7 +607,7 @@ static const cmd_t cmds[] = {
|
||||
{ 0x00, 0x0 }
|
||||
};
|
||||
|
||||
int otp_process_apdu() {
|
||||
static int otp_process_apdu(void) {
|
||||
if (CLA(apdu) != 0x00) {
|
||||
return SW_CLA_NOT_SUPPORTED();
|
||||
}
|
||||
@@ -628,9 +627,7 @@ uint8_t otp_frame_tx[70] = {0};
|
||||
uint8_t otp_exp_seq = 0, otp_curr_seq = 0;
|
||||
uint8_t otp_header[4] = {0};
|
||||
|
||||
extern uint16_t *get_send_buffer_size(uint8_t itf);
|
||||
|
||||
int otp_send_frame(uint8_t *frame, size_t frame_len) {
|
||||
static int otp_send_frame(uint8_t *frame, size_t frame_len) {
|
||||
uint16_t crc = calculate_crc(frame, frame_len);
|
||||
frame_len += put_uint16_t_le(~crc, frame + frame_len);
|
||||
*get_send_buffer_size(ITF_KEYBOARD) = frame_len;
|
||||
@@ -642,7 +639,10 @@ int otp_send_frame(uint8_t *frame, size_t frame_len) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int otp_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) {
|
||||
static int otp_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) {
|
||||
(void)itf;
|
||||
(void)report_id;
|
||||
(void)bufsize;
|
||||
if (report_type == 3) {
|
||||
DEBUG_PAYLOAD(buffer, bufsize);
|
||||
if (buffer[7] == 0xFF) { // reset
|
||||
@@ -690,11 +690,11 @@ int otp_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t repo
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t otp_hid_get_report_cb(uint8_t itf,
|
||||
uint8_t report_id,
|
||||
hid_report_type_t report_type,
|
||||
uint8_t *buffer,
|
||||
uint16_t reqlen) {
|
||||
static uint16_t otp_hid_get_report_cb(uint8_t itf,
|
||||
uint8_t report_id,
|
||||
hid_report_type_t report_type,
|
||||
uint8_t *buffer,
|
||||
uint16_t reqlen) {
|
||||
// TODO not Implemented
|
||||
(void) itf;
|
||||
(void) report_id;
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#ifndef __VERSION_H_
|
||||
#define __VERSION_H_
|
||||
|
||||
#define PICO_FIDO_VERSION 0x0704
|
||||
#define PICO_FIDO_VERSION 0x0706
|
||||
|
||||
#define PICO_FIDO_VERSION_MAJOR ((PICO_FIDO_VERSION >> 8) & 0xff)
|
||||
#define PICO_FIDO_VERSION_MINOR (PICO_FIDO_VERSION & 0xff)
|
||||
|
||||
@@ -25,6 +25,7 @@ INS_PUT = 0x01
|
||||
INS_DELETE = 0x02
|
||||
INS_SET_CODE = 0x03
|
||||
INS_RESET = 0x04
|
||||
INS_RENAME = 0x05
|
||||
INS_LIST = 0xa1
|
||||
INS_CALCULATE = 0xa2
|
||||
INS_VALIDATE = 0xa3
|
||||
@@ -89,6 +90,24 @@ def test_life(reset_oath):
|
||||
resp = list_apdu(reset_oath)
|
||||
assert(len(resp) == 0)
|
||||
|
||||
|
||||
def test_rename_prefix_extension(reset_oath):
|
||||
old_name = b"30/test"
|
||||
new_name = b"30/test2"
|
||||
key = list(bytes(b"foo bar"))
|
||||
|
||||
put_data = [TAG_NAME, len(old_name)] + list(old_name)
|
||||
put_data += [TAG_KEY, len(key) + 2, TYPE_TOTP | ALG_SHA1, 6] + key
|
||||
send_apdu(reset_oath, INS_PUT, p1=0, p2=0, data=put_data)
|
||||
|
||||
rename_data = [TAG_NAME, len(old_name)] + list(old_name)
|
||||
rename_data += [TAG_NAME, len(new_name)] + list(new_name)
|
||||
send_apdu(reset_oath, INS_RENAME, p1=0, p2=0, data=rename_data)
|
||||
|
||||
resp = list_apdu(reset_oath)
|
||||
exp = [TAG_NAME_LIST, len(new_name) + 1, TYPE_TOTP | ALG_SHA1] + list(new_name)
|
||||
assert resp == exp
|
||||
|
||||
def test_overwrite(reset_oath):
|
||||
data = data_name + data_key
|
||||
resp = send_apdu(reset_oath, INS_PUT, p1=0, p2=0, data=list(data))
|
||||
|
||||
Reference in New Issue
Block a user