38 Commits

Author SHA1 Message Date
Pol Henarejos
bddad2f837 Harden GitHub workflows
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-12 17:34:51 +02:00
Pol Henarejos
83b3273f51 Fix pico build
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-05-02 11:39:37 +02:00
Pol Henarejos
cf6be6c121 Use ecp keypair calc public instead.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-05-01 21:05:35 +02:00
Pol Henarejos
9865b697de Use dynamic dependence resolver.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-05-01 19:44:34 +02:00
Pol Henarejos
ded3694c95 Update sc_hsm.c
Fix header
2026-05-01 13:23:17 +02:00
Pol Henarejos
cb474f7ad3 Fix build
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-05-01 12:59:46 +02:00
Pol Henarejos
38a7d147b6 Upgrade PicoKeys SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-05-01 12:54:04 +02:00
Pol Henarejos
251b35dd9c Upgrade to v6.6
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-04-07 19:27:37 +02:00
Pol Henarejos
0eebdd330a Upgrade Pico Keys SDK 8.6 and Mbedtls v3.6.6
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-04-06 20:16:15 +02:00
Pol Henarejos
2a4ee5d42f Fix includes.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-04-06 20:16:11 +02:00
Pol Henarejos
d5b0a94ba4 Fix build for cyw43.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-28 20:32:46 +01:00
Pol Henarejos
504bb0fc05 Remove debugs.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-27 17:20:56 +01:00
Pol Henarejos
f1d927d4ef Add regression tests.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-26 19:07:16 +01:00
Pol Henarejos
1b322755a1 Do not include OTP FIDO in the CCID interface if not available.
Solves #125

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-20 14:35:32 +01:00
Pol Henarejos
e8a398f508 Update memory layout.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-20 13:31:23 +01:00
Pol Henarejos
5297e368d1 Sometimes sc-hsm-tool returns $?=1 despite it succeeds.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-20 13:31:05 +01:00
Pol Henarejos
7c8b39ff82 Update tests
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-20 01:20:46 +01:00
Pol Henarejos
254159d44d Allow access to EE_DEV.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-20 01:19:53 +01:00
Pol Henarejos
75c56bb2c7 Migrate PIN and MKEK to new system.
This new system is more robust, with derived keys by context and safe in case of flash/ram dumps.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-20 01:19:35 +01:00
Pol Henarejos
1f96fe619b Fix bounds on update ef.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-18 17:42:25 +01:00
Pol Henarejos
3af776ec26 Removed unused functions in extras.
Some of them are transfered to rescue interfaces. Others, like OTP, are supressed for security.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-18 16:57:49 +01:00
Pol Henarejos
54cba3efdf Remove session pin.
It is intended for bio features, not supported by Pico HSM.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-18 16:40:08 +01:00
Pol Henarejos
1ced9f6267 Check bounds on update ef.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-18 16:04:20 +01:00
Pol Henarejos
c14a12d9d1 Set ACL for all registers.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-18 16:03:39 +01:00
Pol Henarejos
bbbf28cb42 Fix ACL for static files.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-18 14:26:43 +01:00
Pol Henarejos
db9d6ef2f5 Do not allow reading private objects if not authenticated.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-18 13:21:14 +01:00
Pol Henarejos
983a5b7d10 Fix secp521r1 test with newer OpenSSL versions.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-18 13:19:20 +01:00
Pol Henarejos
839fb431c4 Add strict build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-09 11:02:47 +01:00
Pol Henarejos
cc0e4e43ca Fix MLKEM build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-07 17:54:59 +01:00
Pol Henarejos
7a12177745 Update memory layout.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-07 17:54:14 +01:00
Pol Henarejos
2874353804 Merge pull request #127 from ajkrj/patch-1
Update README.md
2026-03-07 17:24:01 +01:00
Pol Henarejos
64c4afb5d9 Small typos
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-07 17:19:20 +01:00
Pol Henarejos
aae66e7db3 Fix link with mbedtls in openssl backend.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-07 17:16:40 +01:00
Pol Henarejos
2d25ed9939 Fix strict non-prototype declaration warn.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-03-07 17:12:49 +01:00
Pol Henarejos
0ad7e3a610 Fix Secure boot enable.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-02-16 16:03:01 +01:00
Pol Henarejos
25889094e5 [BETA] Add support to Secure Boot in ESP32.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-02-07 14:32:31 +01:00
ajkrj
710f4324ad Update README.md 2026-02-05 20:08:14 +05:30
Pol Henarejos
b78c1485c1 Add support for HIGH/LOW ESP32 LED
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-02-04 23:45:14 +01:00
66 changed files with 1325 additions and 1342 deletions

View File

@@ -40,7 +40,9 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v3 uses: actions/checkout@v4
with:
persist-credentials: false
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL

View File

@@ -5,34 +5,49 @@ on:
- cron: '0 2 * * *' - cron: '0 2 * * *'
workflow_dispatch: workflow_dispatch:
permissions:
contents: write
jobs: jobs:
nightly: nightly:
name: Deploy nightly name: Deploy nightly
permissions:
contents: write
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
refs: [master, development] refs: [master, development]
runs-on: ubuntu-latest runs-on: ubuntu-latest
env:
SIGNING_KEY_PATH: ${{ github.workspace }}/../private.pem
steps: steps:
- name: Validate signing secret
run: |
test -n "${{ secrets.PRIVATE_KEY_B64 }}" || {
echo "PRIVATE_KEY_B64 is required for nightly signed releases." >&2
exit 1
}
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@v4 uses: actions/checkout@v4
with: with:
ref: ${{ matrix.refs }} ref: ${{ matrix.refs }}
submodules: 'recursive' submodules: 'recursive'
persist-credentials: false
- name: Restore private key - name: Restore private key
run: | run: |
echo "${{ secrets.PRIVATE_KEY_B64 }}" | base64 -d > private.pem echo "${{ secrets.PRIVATE_KEY_B64 }}" | base64 -d > "${SIGNING_KEY_PATH}"
chmod 600 private.pem chmod 600 "${SIGNING_KEY_PATH}"
- name : Build - name : Build
env: env:
PICO_SDK_PATH: ../pico-sdk PICO_SDK_PATH: ../pico-sdk
SECURE_BOOT_PKEY: ../private.pem SECURE_BOOT_PKEY: ${{ github.workspace }}/../private.pem
run: | run: |
./workflows/autobuild.sh pico ./workflows/autobuild.sh pico
./build_pico_hsm.sh --no-eddsa ./build_pico_hsm.sh --no-eddsa
./workflows/autobuild.sh esp32 ./workflows/autobuild.sh esp32
- name: Delete private key - name: Delete private key
run: rm private.pem if: always()
run: rm -f "${SIGNING_KEY_PATH}"
- name: Update nightly release - name: Update nightly release
uses: pyTooling/Actions/releaser@v6.7.0 uses: pyTooling/Actions/releaser@v6.7.0
with: with:

View File

@@ -21,14 +21,20 @@ on:
- cron: '23 5 * * 4' - cron: '23 5 * * 4'
workflow_dispatch: workflow_dispatch:
permissions:
contents: read
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
steps: steps:
- name: Checkout repository and submodules - name: Checkout repository and submodules
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
persist-credentials: false
- name: Build in container - name: Build in container
run: ./tests/build-in-docker.sh run: ./tests/build-in-docker.sh
- name: Export image - name: Export image
@@ -45,14 +51,17 @@ jobs:
test: test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
needs: build needs: build
permissions:
contents: read
strategy: strategy:
matrix: matrix:
suite: ["pkcs11", "pytest", "sc-hsm-pkcs11"] suite: ["pkcs11", "pytest", "sc-hsm-pkcs11"]
steps: steps:
- name: Checkout repository and submodules - name: Checkout repository and submodules
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
persist-credentials: false
- name: Retrieve saved image - name: Retrieve saved image
uses: actions/download-artifact@v4 uses: actions/download-artifact@v4
with: with:

View File

@@ -38,16 +38,16 @@ else()
set(__FOR_CI 0) set(__FOR_CI 0)
endif() endif()
if(__FOR_CI) if(__FOR_CI)
add_definitions(-D__FOR_CI) add_compile_definitions(__FOR_CI)
endif() endif()
add_executable(pico_hsm) add_executable(pico_hsm)
endif() endif()
set(USB_ITF_CCID 1) set(USB_ITF_CCID 1)
set(USB_ITF_WCID 1) set(USB_ITF_WCID 1)
include(pico-keys-sdk/pico_keys_sdk_import.cmake) include(pico-keys-sdk/picokeys_sdk_import.cmake)
if(NOT ESP_PLATFORM) if(NOT ESP_PLATFORM)
set(SOURCES ${PICO_KEYS_SOURCES}) set(SOURCES ${PICOKEYS_SOURCES})
endif() endif()
set(SOURCES ${SOURCES} set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c
@@ -74,7 +74,6 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_derive_asym.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_derive_asym.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_extras.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_extras.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_general_authenticate.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_general_authenticate.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_session_pin.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_puk_auth.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_puk_auth.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_pso.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_pso.c
${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_bip_slip.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_bip_slip.c
@@ -83,7 +82,7 @@ set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/hsm/kek.c ${CMAKE_CURRENT_LIST_DIR}/src/hsm/kek.c
) )
SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/hsm/version.h" 3) SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/hsm/version.h")
if(ESP_PLATFORM) if(ESP_PLATFORM)
project(pico_hsm) project(pico_hsm)
@@ -96,13 +95,23 @@ if(NOT ESP_PLATFORM)
target_sources(pico_hsm PUBLIC ${SOURCES}) target_sources(pico_hsm PUBLIC ${SOURCES})
target_include_directories(pico_hsm PUBLIC ${INCLUDES}) target_include_directories(pico_hsm PUBLIC ${INCLUDES})
target_compile_options(pico_hsm PUBLIC set(COMMON_COMPILE_OPTIONS
-Wall -Wall
) )
target_compile_options(pico_hsm PRIVATE ${COMMON_COMPILE_OPTIONS})
picokeys_apply_strict_flags(
SOURCES ${SOURCES}
FILTER_REGEX "/src/hsm/|/pico-keys-sdk/src/|/pico-keys-sdk/config/"
)
if(NOT MSVC) if(NOT MSVC)
target_compile_options(pico_hsm PUBLIC string(FIND ${CMAKE_C_COMPILER} ":" COMPILER_COLON)
-Werror if(${COMPILER_COLON} GREATER_EQUAL 0)
) target_compile_options(pico_hsm PRIVATE
-Wno-error=use-after-free
)
endif()
endif() endif()
if(ENABLE_EMULATION) if(ENABLE_EMULATION)
@@ -127,7 +136,11 @@ if(NOT ESP_PLATFORM)
-Wl,--gc-sections -Wl,--gc-sections
) )
endif(APPLE) endif(APPLE)
target_link_libraries(pico_hsm PRIVATE pico_keys_sdk pthread m mbedtls) set(PICO_HSM_EMU_LIBS picokeys_sdk pthread m)
if(NOT SKIP_MBEDTLS_FOR_OPENSSL_EMULATION)
list(APPEND PICO_HSM_EMU_LIBS mbedtls)
endif()
target_link_libraries(pico_hsm PRIVATE ${PICO_HSM_EMU_LIBS})
else() else()
pico_add_extra_outputs(${CMAKE_PROJECT_NAME}) pico_add_extra_outputs(${CMAKE_PROJECT_NAME})
endif() endif()

View File

@@ -195,8 +195,8 @@ Before building, ensure you have installed the toolchain for the Pico and the Pi
``` ```
git clone https://github.com/polhenarejos/pico-hsm git clone https://github.com/polhenarejos/pico-hsm
git submodule update --init --recursive
cd pico-hsm cd pico-hsm
git submodule update --init --recursive
mkdir build mkdir build
cd build cd build
PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678 PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678

View File

@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
VERSION_MAJOR="6" VERSION_MAJOR="6"
VERSION_MINOR="4" VERSION_MINOR="6"
SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}" SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}"
#if ! [[ -z "${GITHUB_SHA}" ]]; then #if ! [[ -z "${GITHUB_SHA}" ]]; then
# SUFFIX="${SUFFIX}.${GITHUB_SHA}" # SUFFIX="${SUFFIX}.${GITHUB_SHA}"

View File

@@ -9,6 +9,7 @@ CONFIG_TINYUSB_TASK_STACK_SIZE=16384
CONFIG_PARTITION_TABLE_CUSTOM=y CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="pico-keys-sdk/config/esp32/partitions.csv" CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="pico-keys-sdk/config/esp32/partitions.csv"
CONFIG_PARTITION_TABLE_FILENAME="pico-keys-sdk/config/esp32/partitions.csv" CONFIG_PARTITION_TABLE_FILENAME="pico-keys-sdk/config/esp32/partitions.csv"
CONFIG_PARTITION_TABLE_OFFSET=0x10000
CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y
CONFIG_ESPTOOLPY_FLASHMODE_QIO=y CONFIG_ESPTOOLPY_FLASHMODE_QIO=y
CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ_240=y

View File

@@ -27,101 +27,80 @@ const uint8_t *sym_seed = (const uint8_t *) "Symmetric key seed";
mbedtls_ecp_keypair hd_context = { 0 }; mbedtls_ecp_keypair hd_context = { 0 };
uint8_t hd_keytype = 0; uint8_t hd_keytype = 0;
int node_derive_bip_child(const mbedtls_ecp_keypair *parent, static int node_derive_bip_child(const mbedtls_ecp_keypair *parent, const uint8_t cpar[32], const uint8_t *i, mbedtls_ecp_keypair *child, uint8_t cchild[32]) {
const uint8_t cpar[32],
const uint8_t *i,
mbedtls_ecp_keypair *child,
uint8_t cchild[32]) {
uint8_t data[1 + 32 + 4], I[64], *iL = I, *iR = I + 32; uint8_t data[1 + 32 + 4], I[64], *iL = I, *iR = I + 32;
mbedtls_mpi il, kchild; mbedtls_mpi il, kchild;
mbedtls_mpi_init(&il); mbedtls_mpi_init(&il);
mbedtls_mpi_init(&kchild); mbedtls_mpi_init(&kchild);
if (i[0] >= 0x80) { if (i[0] >= 0x80) {
if (mbedtls_mpi_cmp_int(&parent->d, 0) == 0) { if (mbedtls_mpi_cmp_int(&parent->d, 0) == 0) {
return PICOKEY_ERR_NULL_PARAM; return PICOKEYS_ERR_NULL_PARAM;
} }
data[0] = 0x00; data[0] = 0x00;
mbedtls_mpi_write_binary(&parent->d, data + 1, 32); mbedtls_mpi_write_binary(&parent->d, data + 1, 32);
} }
else { else {
size_t olen = 0; size_t olen = 0;
mbedtls_ecp_point_write_binary(&parent->grp, mbedtls_ecp_point_write_binary(&parent->grp, &parent->Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, data, 33);
&parent->Q,
MBEDTLS_ECP_PF_COMPRESSED,
&olen,
data,
33);
} }
do { do {
memcpy(data + 33, i, 4); memcpy(data + 33, i, 4);
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), cpar, 32, data, sizeof(data), I);
cpar,
32,
data,
sizeof(data),
I);
mbedtls_mpi_read_binary(&il, iL, 32); mbedtls_mpi_read_binary(&il, iL, 32);
mbedtls_mpi_add_mpi(&kchild, &il, &parent->d); mbedtls_mpi_add_mpi(&kchild, &il, &parent->d);
mbedtls_mpi_mod_mpi(&kchild, &kchild, &parent->grp.N); mbedtls_mpi_mod_mpi(&kchild, &kchild, &parent->grp.N);
data[0] = 0x01; data[0] = 0x01;
memcpy(data + 1, iR, 32); memcpy(data + 1, iR, 32);
} while (mbedtls_mpi_cmp_mpi(&il, } while (mbedtls_mpi_cmp_mpi(&il, &parent->grp.N) != -1 || mbedtls_mpi_cmp_int(&kchild, 0) == 0);
&parent->grp.N) != -1 || mbedtls_mpi_cmp_int(&kchild, 0) == 0);
mbedtls_mpi_copy(&child->d, &kchild); mbedtls_mpi_copy(&child->d, &kchild);
mbedtls_ecp_mul(&child->grp, &child->Q, &child->d, &child->grp.G, random_gen, NULL); mbedtls_ecp_keypair_calc_public(child, random_fill_iterator, NULL);
memcpy(cchild, iR, 32); memcpy(cchild, iR, 32);
mbedtls_mpi_free(&il); mbedtls_mpi_free(&il);
mbedtls_mpi_free(&kchild); mbedtls_mpi_free(&kchild);
return PICOKEY_OK; return PICOKEYS_OK;
} }
int sha256_ripemd160(const uint8_t *buffer, size_t buffer_len, uint8_t *output) { static int sha256_ripemd160(const uint8_t *buffer, size_t buffer_len, uint8_t *output) {
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), buffer, buffer_len, output); mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), buffer, buffer_len, output);
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160), output, 32, output); mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_RIPEMD160), output, 32, output);
return PICOKEY_OK; return PICOKEYS_OK;
} }
int sha256_sha256(const uint8_t *buffer, size_t buffer_len, uint8_t *output) { static int sha256_sha256(const uint8_t *buffer, size_t buffer_len, uint8_t *output) {
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), buffer, buffer_len, output); mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), buffer, buffer_len, output);
mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), output, 32, output); mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), output, 32, output);
return PICOKEY_OK; return PICOKEYS_OK;
} }
int node_fingerprint_bip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) { static int node_fingerprint_bip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) {
size_t olen = 0; size_t olen = 0;
uint8_t buffer[33]; uint8_t buffer[33];
mbedtls_ecp_point_write_binary(&ctx->grp, mbedtls_ecp_point_write_binary(&ctx->grp, &ctx->Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, buffer, sizeof(buffer));
&ctx->Q,
MBEDTLS_ECP_PF_COMPRESSED,
&olen,
buffer,
sizeof(buffer));
sha256_ripemd160(buffer, sizeof(buffer), buffer); sha256_ripemd160(buffer, sizeof(buffer), buffer);
memcpy(fingerprint, buffer, 4); memcpy(fingerprint, buffer, 4);
return PICOKEY_OK; return PICOKEYS_OK;
} }
int node_fingerprint_slip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) { static int node_fingerprint_slip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) {
uint8_t buffer[32]; uint8_t buffer[32];
mbedtls_mpi_write_binary(&ctx->d, buffer, sizeof(buffer)); mbedtls_mpi_write_binary(&ctx->d, buffer, sizeof(buffer));
sha256_ripemd160(buffer, sizeof(buffer), buffer); sha256_ripemd160(buffer, sizeof(buffer), buffer);
memcpy(fingerprint, buffer, 4); memcpy(fingerprint, buffer, 4);
return PICOKEY_OK; return PICOKEYS_OK;
} }
int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32], static int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32], uint8_t key_type[1]) {
uint8_t key_type[1]) {
uint8_t mkey[65]; uint8_t mkey[65];
mbedtls_ecp_keypair_init(ctx); mbedtls_ecp_keypair_init(ctx);
file_t *ef = search_file(EF_MASTER_SEED | mid); file_t *ef = file_search(EF_MASTER_SEED | mid);
if (!file_has_data(ef)) { if (!file_has_data(ef)) {
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
memcpy(mkey, file_get_data(ef), sizeof(mkey)); memcpy(mkey, file_get_data(ef), sizeof(mkey));
int r = mkek_decrypt(mkey + 1, int r = mkek_decrypt(mkey + 1,
sizeof(mkey) - 1); sizeof(mkey) - 1);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
if (mkey[0] == 0x1 || mkey[0] == 0x2) { if (mkey[0] == 0x1 || mkey[0] == 0x2) {
if (mkey[0] == 0x1) { if (mkey[0] == 0x1) {
@@ -131,29 +110,22 @@ int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32],
mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1);
} }
else { else {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
mbedtls_mpi_read_binary(&ctx->d, mkey + 1, 32); mbedtls_mpi_read_binary(&ctx->d, mkey + 1, 32);
memcpy(chain, mkey + 33, 32); memcpy(chain, mkey + 33, 32);
mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL); mbedtls_ecp_keypair_calc_public(ctx, random_fill_iterator, NULL);
} }
else if (mkey[0] == 0x3) { else if (mkey[0] == 0x3) {
mbedtls_mpi_read_binary(&ctx->d, mkey + 33, 32); mbedtls_mpi_read_binary(&ctx->d, mkey + 33, 32);
memcpy(chain, mkey + 1, 32); memcpy(chain, mkey + 1, 32);
} }
key_type[0] = mkey[0]; key_type[0] = mkey[0];
return PICOKEY_OK; return PICOKEYS_OK;
} }
int node_derive_path(const uint8_t *path, static int node_derive_path(const uint8_t *path, uint16_t path_len, mbedtls_ecp_keypair *ctx, uint8_t chain[32], uint8_t fingerprint[4], uint8_t *nodes, uint8_t last_node[4], uint8_t key_type[1]) {
uint16_t path_len,
mbedtls_ecp_keypair *ctx,
uint8_t chain[32],
uint8_t fingerprint[4],
uint8_t *nodes,
uint8_t last_node[4],
uint8_t key_type[1]) {
uint8_t *tag_data = NULL, *p = NULL; uint8_t *tag_data = NULL, *p = NULL;
uint16_t tag_len = 0, tag = 0x0; uint16_t tag_len = 0, tag = 0x0;
uint8_t node = 0, N[64] = { 0 }; uint8_t node = 0, N[64] = { 0 };
@@ -166,16 +138,16 @@ int node_derive_path(const uint8_t *path,
for (; walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data); node++) { for (; walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data); node++) {
if (tag == 0x02) { if (tag == 0x02) {
if ((node == 0 && tag_len != 1) || (node != 0 && tag_len != 4)) { if ((node == 0 && tag_len != 1) || (node != 0 && tag_len != 4)) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (node == 0) { if (node == 0) {
if ((r = load_master_bip(tag_data[0], ctx, chain, key_type)) != PICOKEY_OK) { if ((r = load_master_bip(tag_data[0], ctx, chain, key_type)) != PICOKEYS_OK) {
return r; return r;
} }
} }
else if (node > 0) { else if (node > 0) {
node_fingerprint_bip(ctx, fingerprint); node_fingerprint_bip(ctx, fingerprint);
if ((r = node_derive_bip_child(ctx, chain, tag_data, ctx, chain)) != PICOKEY_OK) { if ((r = node_derive_bip_child(ctx, chain, tag_data, ctx, chain)) != PICOKEYS_OK) {
return r; return r;
} }
memcpy(last_node, tag_data, 4); memcpy(last_node, tag_data, 4);
@@ -183,17 +155,12 @@ int node_derive_path(const uint8_t *path,
} }
else if (tag == 0x04) { else if (tag == 0x04) {
if (node == 0) { if (node == 0) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
else if (node > 0) { else if (node > 0) {
node_fingerprint_slip(ctx, fingerprint); node_fingerprint_slip(ctx, fingerprint);
*(tag_data - 1) = 0; *(tag_data - 1) = 0;
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), chain, 32, tag_data - 1, tag_len + 1, N);
chain,
32,
tag_data - 1,
tag_len + 1,
N);
memcpy(chain, N, 32); memcpy(chain, N, 32);
mbedtls_mpi_read_binary(&ctx->d, N + 32, 32); mbedtls_mpi_read_binary(&ctx->d, N + 32, 32);
} }
@@ -202,10 +169,10 @@ int node_derive_path(const uint8_t *path,
if (nodes) { if (nodes) {
*nodes = node; *nodes = node;
} }
return PICOKEY_OK; return PICOKEYS_OK;
} }
int cmd_bip_slip() { int cmd_bip_slip(void) {
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
if (p1 == 0x1 || p1 == 0x2 || p1 == 0x3) { // Master generation (K1 and P1) if (p1 == 0x1 || p1 == 0x2 || p1 == 0x3) { // Master generation (K1 and P1)
if (p2 >= 10) { if (p2 >= 10) {
@@ -230,7 +197,7 @@ int cmd_bip_slip() {
} }
if (apdu.nc == 0) { if (apdu.nc == 0) {
seed_len = 64; seed_len = 64;
random_gen(NULL, seed, seed_len); random_fill_buffer(seed, seed_len);
} }
else { else {
seed_len = MIN((uint8_t)apdu.nc, 64); seed_len = MIN((uint8_t)apdu.nc, 64);
@@ -238,8 +205,7 @@ int cmd_bip_slip() {
} }
if (p1 == 0x1 || p1 == 0x2) { if (p1 == 0x1 || p1 == 0x2) {
do { do {
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key_seed, mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key_seed, strlen((char *) key_seed), seed, seed_len, seed);
strlen((char *) key_seed), seed, seed_len, seed);
mbedtls_mpi_read_binary(&il, seed, 32); mbedtls_mpi_read_binary(&il, seed, 32);
seed_len = 64; seed_len = 64;
} while (mbedtls_mpi_cmp_int(&il, 0) == 0 || mbedtls_mpi_cmp_mpi(&il, &grp.N) != -1); } while (mbedtls_mpi_cmp_int(&il, 0) == 0 || mbedtls_mpi_cmp_mpi(&il, &grp.N) != -1);
@@ -247,20 +213,19 @@ int cmd_bip_slip() {
mbedtls_mpi_free(&il); mbedtls_mpi_free(&il);
} }
else if (p1 == 0x3) { else if (p1 == 0x3) {
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key_seed, mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), key_seed, strlen((char *) key_seed), seed, seed_len, seed);
strlen((char *) key_seed), seed, seed_len, seed);
} }
mkey[0] = p1; mkey[0] = p1;
file_t *ef = file_new(EF_MASTER_SEED | p2); file_t *ef = file_new(EF_MASTER_SEED | p2);
int r = mkek_encrypt(mkey + 1, sizeof(mkey) - 1); int r = mkek_encrypt(mkey + 1, sizeof(mkey) - 1);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = file_put_data(ef, mkey, sizeof(mkey)); r = file_put_data(ef, mkey, sizeof(mkey));
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
low_flash_available(); flash_commit();
} }
else if (p1 == 0xA) { else if (p1 == 0xA) {
if (apdu.nc == 0) { if (apdu.nc == 0) {
@@ -271,7 +236,7 @@ int cmd_bip_slip() {
size_t olen = 0; size_t olen = 0;
int r = int r =
node_derive_path(apdu.data, (uint16_t)apdu.nc, &ctx, chain, fgpt, &nodes, last_node, &key_type); node_derive_path(apdu.data, (uint16_t)apdu.nc, &ctx, chain, fgpt, &nodes, last_node, &key_type);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
@@ -287,12 +252,7 @@ int cmd_bip_slip() {
if (key_type == 0x1 || key_type == 0x2) { if (key_type == 0x1 || key_type == 0x2) {
memcpy(res_APDU + res_APDU_size, chain, 32); memcpy(res_APDU + res_APDU_size, chain, 32);
res_APDU_size += 32; res_APDU_size += 32;
mbedtls_ecp_point_write_binary(&ctx.grp, mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_COMPRESSED, &olen, pubkey, sizeof(pubkey));
&ctx.Q,
MBEDTLS_ECP_PF_COMPRESSED,
&olen,
pubkey,
sizeof(pubkey));
memcpy(res_APDU + res_APDU_size, pubkey, olen); memcpy(res_APDU + res_APDU_size, pubkey, olen);
res_APDU_size += (uint16_t)olen; res_APDU_size += (uint16_t)olen;
} }
@@ -309,15 +269,8 @@ int cmd_bip_slip() {
} }
else if (p1 == 0x10) { else if (p1 == 0x10) {
uint8_t chain[32] = { 0 }, fgpt[4] = { 0 }, last_node[4] = { 0 }, nodes = 0; uint8_t chain[32] = { 0 }, fgpt[4] = { 0 }, last_node[4] = { 0 }, nodes = 0;
int r = node_derive_path(apdu.data, int r = node_derive_path(apdu.data, (uint16_t)apdu.nc, &hd_context, chain, fgpt, &nodes, last_node, &hd_keytype);
(uint16_t)apdu.nc, if (r != PICOKEYS_OK) {
&hd_context,
chain,
fgpt,
&nodes,
last_node,
&hd_keytype);
if (r != PICOKEY_OK) {
mbedtls_ecp_keypair_free(&hd_context); mbedtls_ecp_keypair_free(&hd_context);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }

View File

@@ -21,7 +21,7 @@
uint8_t challenge[256]; uint8_t challenge[256];
uint8_t challenge_len = 0; uint8_t challenge_len = 0;
int cmd_challenge() { int cmd_challenge(void) {
uint8_t *rb = (uint8_t *) random_bytes_get(apdu.ne); uint8_t *rb = (uint8_t *) random_bytes_get(apdu.ne);
if (!rb) { if (!rb) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();

View File

@@ -18,8 +18,9 @@
#include "crypto_utils.h" #include "crypto_utils.h"
#include "sc_hsm.h" #include "sc_hsm.h"
#include "kek.h" #include "kek.h"
#include "files.h"
int cmd_change_pin() { int cmd_change_pin(void) {
if (P1(apdu) == 0x0) { if (P1(apdu) == 0x0) {
if (P2(apdu) == 0x81 || P2(apdu) == 0x88) { if (P2(apdu) == 0x81 || P2(apdu) == 0x88) {
file_t *file_pin = NULL; file_t *file_pin = NULL;
@@ -42,29 +43,30 @@ int cmd_change_pin() {
} }
uint8_t mkek[MKEK_SIZE]; uint8_t mkek[MKEK_SIZE];
r = load_mkek(mkek); //loads the MKEK with old pin r = load_mkek(mkek); //loads the MKEK with old pin
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
//encrypt MKEK with new pin //encrypt MKEK with new pin
if (P2(apdu) == 0x81) { if (P2(apdu) == 0x81) {
hash_multi(apdu.data + pin_len, (uint16_t)(apdu.nc - pin_len), session_pin); pin_derive_session(apdu.data + pin_len, (uint16_t)(apdu.nc - pin_len), session_pin);
has_session_pin = true; has_session_pin = true;
} }
else if (P2(apdu) == 0x88) { else if (P2(apdu) == 0x88) {
hash_multi(apdu.data + pin_len, (uint16_t)(apdu.nc - pin_len), session_sopin); pin_derive_session(apdu.data + pin_len, (uint16_t)(apdu.nc - pin_len), session_sopin);
has_session_sopin = true; has_session_sopin = true;
} }
r = store_mkek(mkek); r = store_mkek(mkek);
release_mkek(mkek); release_mkek(mkek);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
uint8_t dhash[33]; uint8_t dhash[34];
dhash[0] = (uint8_t)apdu.nc - pin_len; dhash[0] = (uint8_t)apdu.nc - pin_len;
double_hash_pin(apdu.data + pin_len, (uint16_t)(apdu.nc - pin_len), dhash + 1); dhash[1] = 1; // Format
pin_derive_verifier(apdu.data + pin_len, (uint16_t)(apdu.nc - pin_len), dhash + 2);
file_put_data(file_pin, dhash, sizeof(dhash)); file_put_data(file_pin, dhash, sizeof(dhash));
low_flash_available(); flash_commit();
return SW_OK(); return SW_OK();
} }
} }

View File

@@ -77,11 +77,19 @@ static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
return 0; return 0;
} }
if ((ret = mbedtls_asn1_get_int(&p, end, (int *)keylen)) != 0) { int keylen_i = 0;
if ((ret = mbedtls_asn1_get_int(&p, end, &keylen_i)) != 0) {
if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret); return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT, ret);
} }
} }
else if (keylen_i < 0 || keylen_i > UINT16_MAX) {
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_PKCS5_INVALID_FORMAT,
MBEDTLS_ERR_ASN1_INVALID_LENGTH);
}
else {
*keylen = (uint16_t) keylen_i;
}
if (p == end) { if (p == end) {
return 0; return 0;
@@ -104,13 +112,13 @@ static int pkcs5_parse_pbkdf2_params(const mbedtls_asn1_buf *params,
} }
/* Taken from https://github.com/Mbed-TLS/mbedtls/issues/2335 */ /* Taken from https://github.com/Mbed-TLS/mbedtls/issues/2335 */
int mbedtls_ansi_x963_kdf(mbedtls_md_type_t md_type, static int mbedtls_ansi_x963_kdf(mbedtls_md_type_t md_type,
uint16_t input_len, uint16_t input_len,
uint8_t *input, uint8_t *input,
uint16_t shared_info_len, uint16_t shared_info_len,
uint8_t *shared_info, uint8_t *shared_info,
uint16_t output_len, uint16_t output_len,
uint8_t *output) { uint8_t *output) {
mbedtls_md_context_t md_ctx; mbedtls_md_context_t md_ctx;
const mbedtls_md_info_t *md_info = NULL; const mbedtls_md_info_t *md_info = NULL;
int hashlen = 0, exit_code = MBEDTLS_ERR_MD_BAD_INPUT_DATA; int hashlen = 0, exit_code = MBEDTLS_ERR_MD_BAD_INPUT_DATA;
@@ -128,7 +136,7 @@ int mbedtls_ansi_x963_kdf(mbedtls_md_type_t md_type,
return exit_code; return exit_code;
} }
if (input_len + shared_info_len + 4 >= (1ULL << 61) - 1) { if ((uint64_t) input_len + (uint64_t) shared_info_len + 4ULL >= (1ULL << 61) - 1) {
return exit_code; return exit_code;
} }
@@ -143,7 +151,7 @@ int mbedtls_ansi_x963_kdf(mbedtls_md_type_t md_type,
mbedtls_md_update(&md_ctx, input, input_len); mbedtls_md_update(&md_ctx, input, input_len);
//TODO: be careful with architecture little vs. big //TODO: be careful with architecture little vs. big
put_uint32_t_be(counter, counter_buf); put_uint32_be(counter, counter_buf);
mbedtls_md_update(&md_ctx, counter_buf, 4); mbedtls_md_update(&md_ctx, counter_buf, 4);
@@ -158,7 +166,7 @@ int mbedtls_ansi_x963_kdf(mbedtls_md_type_t md_type,
return 0; return 0;
} }
int cmd_cipher_sym() { int cmd_cipher_sym(void) {
uint8_t key_id = P1(apdu), algo = P2(apdu); uint8_t key_id = P1(apdu), algo = P2(apdu);
if (!isUserAuthenticated) { if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
@@ -166,7 +174,7 @@ int cmd_cipher_sym() {
if (wait_button_pressed() == true) { // timeout if (wait_button_pressed() == true) { // timeout
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
file_t *ef = search_file((KEY_PREFIX << 8) | key_id); file_t *ef = file_search((KEY_PREFIX << 8) | key_id);
if (hd_keytype == 0) { if (hd_keytype == 0) {
if (!ef) { if (!ef) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
@@ -196,12 +204,7 @@ int cmd_cipher_sym() {
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = mbedtls_aes_crypt_cbc(&aes, r = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, apdu.nc, tmp_iv, apdu.data, res_APDU);
MBEDTLS_AES_ENCRYPT,
apdu.nc,
tmp_iv,
apdu.data,
res_APDU);
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -213,12 +216,7 @@ int cmd_cipher_sym() {
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = mbedtls_aes_crypt_cbc(&aes, r = mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, apdu.nc, tmp_iv, apdu.data, res_APDU);
MBEDTLS_AES_DECRYPT,
apdu.nc,
tmp_iv,
apdu.data,
res_APDU);
mbedtls_aes_free(&aes); mbedtls_aes_free(&aes);
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -249,15 +247,7 @@ int cmd_cipher_sym() {
res_APDU_size = 16; res_APDU_size = 16;
} }
else if (algo == ALGO_AES_DERIVE) { else if (algo == ALGO_AES_DERIVE) {
int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), int r = mbedtls_hkdf(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), NULL, 0,kdata, key_size, apdu.data, apdu.nc, res_APDU, apdu.nc);
NULL,
0,
kdata,
key_size,
apdu.data,
apdu.nc,
res_APDU,
apdu.nc);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -286,24 +276,10 @@ int cmd_cipher_sym() {
mbedtls_chachapoly_init(&ctx); mbedtls_chachapoly_init(&ctx);
mbedtls_chachapoly_setkey(&ctx, kdata); mbedtls_chachapoly_setkey(&ctx, kdata);
if (algo == ALGO_EXT_CIPHER_ENCRYPT) { if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
r = mbedtls_chachapoly_encrypt_and_tag(&ctx, r = mbedtls_chachapoly_encrypt_and_tag(&ctx, enc.len, asn1_len(&iv) > 0 ? iv.data : tmp_iv, aad.data, aad.len, enc.data, res_APDU, res_APDU + enc.len);
enc.len,
asn1_len(&iv) > 0 ? iv.data : tmp_iv,
aad.data,
aad.len,
enc.data,
res_APDU,
res_APDU + enc.len);
} }
else if (algo == ALGO_EXT_CIPHER_DECRYPT) { else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
r = mbedtls_chachapoly_auth_decrypt(&ctx, r = mbedtls_chachapoly_auth_decrypt(&ctx,enc.len - 16, asn1_len(&iv) > 0 ? iv.data : tmp_iv, aad.data, aad.len, enc.data + enc.len - 16, enc.data, res_APDU);
enc.len - 16,
asn1_len(&iv) > 0 ? iv.data : tmp_iv,
aad.data,
aad.len,
enc.data + enc.len - 16,
enc.data,
res_APDU);
} }
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_chachapoly_free(&ctx); mbedtls_chachapoly_free(&ctx);
@@ -361,16 +337,7 @@ int cmd_cipher_sym() {
else if (memcmp(oid.data, OID_HKDF_SHA512, oid.len) == 0) { else if (memcmp(oid.data, OID_HKDF_SHA512, oid.len) == 0) {
md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
} }
int r = mbedtls_hkdf(md_info, int r = mbedtls_hkdf(md_info, iv.data, iv.len, kdata, key_size, enc.data, enc.len, res_APDU, apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : mbedtls_md_get_size(md_info));
iv.data,
iv.len,
kdata,
key_size,
enc.data,
enc.len,
res_APDU,
apdu.ne > 0 &&
apdu.ne < 65536 ? apdu.ne : mbedtls_md_get_size(md_info));
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -391,15 +358,7 @@ int cmd_cipher_sym() {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
r = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, r = mbedtls_pkcs5_pbkdf2_hmac_ext(md_type, kdata, key_size, salt.p, salt.len, iterations, keylen ? keylen : (apdu.ne > 0 && apdu.ne < 65536 ? apdu.ne : 32), res_APDU);
kdata,
key_size,
salt.p,
salt.len,
iterations,
keylen ? keylen : (apdu.ne > 0 &&
apdu.ne < 65536 ? apdu.ne : 32),
res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -434,13 +393,7 @@ int cmd_cipher_sym() {
else if (memcmp(enc.data, OID_HMAC_SHA512, enc.len) == 0) { else if (memcmp(enc.data, OID_HMAC_SHA512, enc.len) == 0) {
md_type = MBEDTLS_MD_SHA512; md_type = MBEDTLS_MD_SHA512;
} }
int r = mbedtls_ansi_x963_kdf(md_type, int r = mbedtls_ansi_x963_kdf(md_type, key_size, kdata, aad.len, aad.data, apdu.ne > 0 && apdu.ne < 65536 ? (uint16_t)apdu.ne : 32, res_APDU);
key_size,
kdata,
aad.len,
aad.data,
apdu.ne > 0 && apdu.ne < 65536 ? (uint16_t)apdu.ne : 32,
res_APDU);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
@@ -542,16 +495,7 @@ int cmd_cipher_sym() {
res_APDU_size = enc.len + 16; res_APDU_size = enc.len + 16;
} }
else if (algo == ALGO_EXT_CIPHER_DECRYPT) { else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
r = mbedtls_gcm_auth_decrypt(&gctx, r = mbedtls_gcm_auth_decrypt(&gctx, enc.len - 16, iv.data, iv.len, aad.data, aad.len, enc.data + enc.len - 16, 16, enc.data, res_APDU);
enc.len - 16,
iv.data,
iv.len,
aad.data,
aad.len,
enc.data + enc.len - 16,
16,
enc.data,
res_APDU);
res_APDU_size = enc.len - 16; res_APDU_size = enc.len - 16;
} }
mbedtls_gcm_free(&gctx); mbedtls_gcm_free(&gctx);
@@ -584,29 +528,11 @@ int cmd_cipher_sym() {
} }
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (algo == ALGO_EXT_CIPHER_ENCRYPT) { if (algo == ALGO_EXT_CIPHER_ENCRYPT) {
r = mbedtls_ccm_encrypt_and_tag(&gctx, r = mbedtls_ccm_encrypt_and_tag(&gctx, enc.len, iv.data, iv.len, aad.data,aad.len, enc.data, res_APDU, res_APDU + enc.len, 16);
enc.len,
iv.data,
iv.len,
aad.data,
aad.len,
enc.data,
res_APDU,
res_APDU + enc.len,
16);
res_APDU_size = enc.len + 16; res_APDU_size = enc.len + 16;
} }
else if (algo == ALGO_EXT_CIPHER_DECRYPT) { else if (algo == ALGO_EXT_CIPHER_DECRYPT) {
r = mbedtls_ccm_auth_decrypt(&gctx, r = mbedtls_ccm_auth_decrypt(&gctx, enc.len - 16, iv.data, iv.len, aad.data, aad.len, enc.data, res_APDU, enc.data + enc.len - 16, 16);
enc.len - 16,
iv.data,
iv.len,
aad.data,
aad.len,
enc.data,
res_APDU,
enc.data + enc.len - 16,
16);
res_APDU_size = enc.len - 16; res_APDU_size = enc.len - 16;
} }
mbedtls_ccm_free(&gctx); mbedtls_ccm_free(&gctx);
@@ -660,12 +586,7 @@ int cmd_cipher_sym() {
} }
key_size = 32; key_size = 32;
mbedtls_mpi_write_binary(&hd_context.d, kdata, key_size); mbedtls_mpi_write_binary(&hd_context.d, kdata, key_size);
r = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), r = mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA512), kdata, key_size,aad.data, aad.len, secret);
kdata,
key_size,
aad.data,
aad.len,
secret);
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();

View File

@@ -25,13 +25,13 @@
#include "random.h" #include "random.h"
#include "oid.h" #include "oid.h"
int cmd_decrypt_asym() { int cmd_decrypt_asym(void) {
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
if (!isUserAuthenticated) { if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
} }
file_t *ef = search_file((KEY_PREFIX << 8) | key_id); file_t *ef = file_search((KEY_PREFIX << 8) | key_id);
if (!ef) { if (!ef) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
@@ -48,9 +48,9 @@ int cmd_decrypt_asym() {
mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256);
} }
int r = load_private_key_rsa(&ctx, ef); int r = load_private_key_rsa(&ctx, ef);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
if (r == PICOKEY_VERIFICATION_FAILED) { if (r == PICOKEYS_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -61,13 +61,13 @@ int cmd_decrypt_asym() {
} }
if (p2 == ALGO_RSA_DECRYPT_PKCS1 || p2 == ALGO_RSA_DECRYPT_OEP) { if (p2 == ALGO_RSA_DECRYPT_PKCS1 || p2 == ALGO_RSA_DECRYPT_OEP) {
size_t olen = apdu.nc; size_t olen = apdu.nc;
r = mbedtls_rsa_pkcs1_decrypt(&ctx, random_gen, NULL, &olen, apdu.data, res_APDU, 512); r = mbedtls_rsa_pkcs1_decrypt(&ctx, random_fill_iterator, NULL, &olen, apdu.data, res_APDU, 512);
if (r == 0) { if (r == 0) {
res_APDU_size = (uint16_t)olen; res_APDU_size = (uint16_t)olen;
} }
} }
else { else {
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU); r = mbedtls_rsa_private(&ctx, random_fill_iterator, NULL, apdu.data, res_APDU);
if (r == 0) { if (r == 0) {
res_APDU_size = key_size; res_APDU_size = key_size;
} }
@@ -134,9 +134,7 @@ int cmd_decrypt_asym() {
// The SmartCard-HSM returns the point result of the DH operation // The SmartCard-HSM returns the point result of the DH operation
// with a leading '04' // with a leading '04'
res_APDU[0] = 0x04; res_APDU[0] = 0x04;
r = r = mbedtls_ecdh_calc_secret(&ctx, &olen, res_APDU + 1, MBEDTLS_ECP_MAX_BYTES, random_fill_iterator, NULL);
mbedtls_ecdh_calc_secret(&ctx, &olen, res_APDU + 1, MBEDTLS_ECP_MAX_BYTES, random_gen,
NULL);
mbedtls_ecdh_free(&ctx); mbedtls_ecdh_free(&ctx);
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -158,10 +156,7 @@ int cmd_decrypt_asym() {
while (walk_tlv(&ctxi, &p, &tag, &ctxo.len, &ctxo.data)) { while (walk_tlv(&ctxi, &p, &tag, &ctxo.len, &ctxo.data)) {
if (tag == 0x73) { if (tag == 0x73) {
asn1_ctx_t oid = {0}; asn1_ctx_t oid = {0};
if (asn1_find_tag(&ctxo, 0x6, &oid) == true && if (asn1_find_tag(&ctxo, 0x6, &oid) == true && oid.len == strlen(OID_ID_KEY_DOMAIN_UID) && memcmp(oid.data, OID_ID_KEY_DOMAIN_UID, strlen(OID_ID_KEY_DOMAIN_UID)) == 0) {
oid.len == strlen(OID_ID_KEY_DOMAIN_UID) &&
memcmp(oid.data, OID_ID_KEY_DOMAIN_UID,
strlen(OID_ID_KEY_DOMAIN_UID)) == 0) {
if (asn1_find_tag(&ctxo, 0x80, &kdom_uid) == false) { if (asn1_find_tag(&ctxo, 0x80, &kdom_uid) == false) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
@@ -173,12 +168,11 @@ int cmd_decrypt_asym() {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
for (uint8_t n = 0; n < MAX_KEY_DOMAINS; n++) { for (uint8_t n = 0; n < MAX_KEY_DOMAINS; n++) {
file_t *tf = search_file(EF_XKEK + n); file_t *tf = file_search(EF_XKEK + n);
if (tf) { if (tf) {
if (file_get_size(tf) == kdom_uid.len && if (file_get_size(tf) == kdom_uid.len && memcmp(file_get_data(tf), kdom_uid.data, kdom_uid.len) == 0) {
memcmp(file_get_data(tf), kdom_uid.data, kdom_uid.len) == 0) {
file_new(EF_DKEK + n); file_new(EF_DKEK + n);
if (store_dkek_key(n, res_APDU + 1) != PICOKEY_OK) { if (store_dkek_key(n, res_APDU + 1) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_platform_zeroize(res_APDU, 32); mbedtls_platform_zeroize(res_APDU, 32);

View File

@@ -17,7 +17,7 @@
#include "sc_hsm.h" #include "sc_hsm.h"
int cmd_delete_file() { int cmd_delete_file(void) {
file_t *ef = NULL; file_t *ef = NULL;
if (!isUserAuthenticated) { if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
@@ -25,20 +25,20 @@ int cmd_delete_file() {
if (apdu.nc == 0) { if (apdu.nc == 0) {
ef = currentEF; ef = currentEF;
if (!(ef = search_file(ef->fid))) { if (!(ef = file_search(ef->fid))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
else { else {
uint16_t fid = get_uint16_t_be(apdu.data); uint16_t fid = get_uint16_be(apdu.data);
if (!(ef = search_file(fid))) { if (!(ef = file_search(fid))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
if (!authenticate_action(ef, ACL_OP_DELETE_SELF)) { if (!file_authenticate_action(ef, ACL_OP_DELETE_SELF)) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
} }
if (delete_file(ef) != PICOKEY_OK) { if (file_delete(ef) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
return SW_OK(); return SW_OK();

View File

@@ -35,14 +35,14 @@ cleanup:
return ret; return ret;
} }
int cmd_derive_asym() { int cmd_derive_asym(void) {
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
uint8_t dest_id = P2(apdu); uint8_t dest_id = P2(apdu);
file_t *fkey; file_t *fkey;
if (!isUserAuthenticated) { if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
} }
if (!(fkey = search_file((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) { if (!(fkey = file_search((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false) { if (key_has_purpose(fkey, ALGO_EC_DERIVE) == false) {
@@ -57,9 +57,9 @@ int cmd_derive_asym() {
int r; int r;
r = load_private_key_ec(&ctx, fkey); r = load_private_key_ec(&ctx, fkey);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
if (r == PICOKEY_VERIFICATION_FAILED) { if (r == PICOKEYS_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -87,8 +87,8 @@ int cmd_derive_asym() {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = store_keys(&ctx, PICO_KEYS_KEY_EC, dest_id); r = store_keys(&ctx, PICOKEYS_KEY_EC, dest_id);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }

View File

@@ -24,7 +24,7 @@ extern file_t *ef_puk_aut;
extern uint8_t challenge[256]; extern uint8_t challenge[256];
extern uint8_t challenge_len; extern uint8_t challenge_len;
int cmd_external_authenticate() { int cmd_external_authenticate(void) {
if (P1(apdu) != 0x0 || P2(apdu) != 0x0) { if (P1(apdu) != 0x0 || P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
} }
@@ -34,7 +34,7 @@ int cmd_external_authenticate() {
if (apdu.nc == 0) { if (apdu.nc == 0) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
} }
file_t *ef_puk = search_file(EF_PUKAUT); file_t *ef_puk = file_search(EF_PUKAUT);
if (!file_has_data(ef_puk)) { if (!file_has_data(ef_puk)) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
@@ -44,13 +44,7 @@ int cmd_external_authenticate() {
memcpy(input, dev_name, dev_name_len); memcpy(input, dev_name, dev_name_len);
memcpy(input + dev_name_len, challenge, challenge_len); memcpy(input + dev_name_len, challenge, challenge_len);
hash256(input, dev_name_len + challenge_len, hash); hash256(input, dev_name_len + challenge_len, hash);
int r = int r = puk_verify(apdu.data, (uint16_t)apdu.nc, hash, 32, file_get_data(ef_puk_aut), file_get_size(ef_puk_aut));
puk_verify(apdu.data,
(uint16_t)apdu.nc,
hash,
32,
file_get_data(ef_puk_aut),
file_get_size(ef_puk_aut));
free(input); free(input);
if (r != 0) { if (r != 0) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();

View File

@@ -17,13 +17,6 @@
#include "sc_hsm.h" #include "sc_hsm.h"
#include "mbedtls/ecdh.h" #include "mbedtls/ecdh.h"
#ifdef PICO_PLATFORM
#include "pico/aon_timer.h"
#include "hardware/watchdog.h"
#else
#include <sys/time.h>
#include <time.h>
#endif
#include "files.h" #include "files.h"
#include "random.h" #include "random.h"
#include "kek.h" #include "kek.h"
@@ -45,7 +38,7 @@
#define CMD_OTP 0x4C #define CMD_OTP 0x4C
#define CMD_MEMORY 0x5 #define CMD_MEMORY 0x5
int cmd_extras() { int cmd_extras(void) {
int cmd = P1(apdu); int cmd = P1(apdu);
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
// Only allow change PHY without PIN // Only allow change PHY without PIN
@@ -57,50 +50,7 @@ int cmd_extras() {
if (wait_button_pressed() == true) { if (wait_button_pressed() == true) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
if (cmd == CMD_DATETIME) { //datetime operations if (cmd == CMD_DYNOPS) { //dynamic options
if (P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2();
}
if (apdu.nc == 0) {
#ifdef PICO_PLATFORM
struct timespec tv;
aon_timer_get_time(&tv);
#else
struct timeval tv;
gettimeofday(&tv, NULL);
#endif
struct tm *tm = localtime(&tv.tv_sec);
res_APDU_size += put_uint16_t_be(tm->tm_year + 1900, res_APDU);
res_APDU[res_APDU_size++] = tm->tm_mon;
res_APDU[res_APDU_size++] = tm->tm_mday;
res_APDU[res_APDU_size++] = tm->tm_wday;
res_APDU[res_APDU_size++] = tm->tm_hour;
res_APDU[res_APDU_size++] = tm->tm_min;
res_APDU[res_APDU_size++] = tm->tm_sec;
}
else {
if (apdu.nc != 8) {
return SW_WRONG_LENGTH();
}
struct tm tm;
tm.tm_year = get_uint16_t_be(apdu.data) - 1900;
tm.tm_mon = apdu.data[2];
tm.tm_mday = apdu.data[3];
tm.tm_wday = apdu.data[4];
tm.tm_hour = apdu.data[5];
tm.tm_min = apdu.data[6];
tm.tm_sec = apdu.data[7];
time_t tv_sec = mktime(&tm);
#ifdef PICO_PLATFORM
struct timespec tv = {.tv_sec = tv_sec, .tv_nsec = 0};
aon_timer_set_time(&tv);
#else
struct timeval tv = {.tv_sec = tv_sec, .tv_usec = 0};
settimeofday(&tv, NULL);
#endif
}
}
else if (cmd == CMD_DYNOPS) { //dynamic options
if (P2(apdu) != 0x0) { if (P2(apdu) != 0x0) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
} }
@@ -109,13 +59,13 @@ int cmd_extras() {
} }
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
if (apdu.nc == 0) { if (apdu.nc == 0) {
res_APDU_size += put_uint16_t_be(opts, res_APDU); res_APDU_size += put_uint16_be(opts, res_APDU);
} }
else { else {
uint8_t newopts[] = { apdu.data[0], (opts & 0xff) }; uint8_t newopts[] = { apdu.data[0], (opts & 0xff) };
file_t *tf = search_file(EF_DEVOPS); file_t *tf = file_search(EF_DEVOPS);
file_put_data(tf, newopts, sizeof(newopts)); file_put_data(tf, newopts, sizeof(newopts));
low_flash_available(); flash_commit();
} }
} }
else if (cmd == CMD_SECURE_LOCK) { // secure lock else if (cmd == CMD_SECURE_LOCK) { // secure lock
@@ -126,7 +76,7 @@ int cmd_extras() {
mbedtls_ecdh_context hkey; mbedtls_ecdh_context hkey;
mbedtls_ecdh_init(&hkey); mbedtls_ecdh_init(&hkey);
mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1); mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1);
int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_gen, NULL); int ret = mbedtls_ecdh_gen_public(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.d, &hkey.ctx.mbed_ecdh.Q, random_fill_iterator, NULL);
mbedtls_mpi_lset(&hkey.ctx.mbed_ecdh.Qp.Z, 1); mbedtls_mpi_lset(&hkey.ctx.mbed_ecdh.Qp.Z, 1);
ret = mbedtls_ecp_point_read_binary(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.Qp, apdu.data, apdu.nc); ret = mbedtls_ecp_point_read_binary(&hkey.ctx.mbed_ecdh.grp, &hkey.ctx.mbed_ecdh.Qp, apdu.data, apdu.nc);
if (ret != 0) { if (ret != 0) {
@@ -137,7 +87,7 @@ int cmd_extras() {
uint8_t buf[MBEDTLS_ECP_MAX_BYTES]; uint8_t buf[MBEDTLS_ECP_MAX_BYTES];
size_t olen = 0; size_t olen = 0;
ret = mbedtls_ecdh_calc_secret(&hkey, &olen, buf, MBEDTLS_ECP_MAX_BYTES, random_gen, NULL); ret = mbedtls_ecdh_calc_secret(&hkey, &olen, buf, MBEDTLS_ECP_MAX_BYTES, random_fill_iterator, NULL);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdh_free(&hkey); mbedtls_ecdh_free(&hkey);
mbedtls_platform_zeroize(buf, sizeof(buf)); mbedtls_platform_zeroize(buf, sizeof(buf));
@@ -172,8 +122,8 @@ int cmd_extras() {
if ((P2(apdu) == SECURE_LOCK_ENABLE && !(opts & HSM_OPT_SECURE_LOCK)) || if ((P2(apdu) == SECURE_LOCK_ENABLE && !(opts & HSM_OPT_SECURE_LOCK)) ||
(P2(apdu) == SECURE_LOCK_DISABLE && (opts & HSM_OPT_SECURE_LOCK))) { (P2(apdu) == SECURE_LOCK_DISABLE && (opts & HSM_OPT_SECURE_LOCK))) {
uint16_t tfids[] = { EF_MKEK, EF_MKEK_SO }; uint16_t tfids[] = { EF_MKEK, EF_MKEK_SO };
for (int t = 0; t < sizeof(tfids) / sizeof(uint16_t); t++) { for (size_t t = 0; t < sizeof(tfids) / sizeof(uint16_t); t++) {
file_t *tf = search_file(tfids[t]); file_t *tf = file_search(tfids[t]);
if (tf) { if (tf) {
uint8_t *tmp = (uint8_t *) calloc(1, file_get_size(tf)); uint8_t *tmp = (uint8_t *) calloc(1, file_get_size(tf));
memcpy(tmp, file_get_data(tf), file_get_size(tf)); memcpy(tmp, file_get_data(tf), file_get_size(tf));
@@ -191,9 +141,9 @@ int cmd_extras() {
else if (P2(apdu) == SECURE_LOCK_DISABLE) { else if (P2(apdu) == SECURE_LOCK_DISABLE) {
newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8; newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8;
} }
file_t *tf = search_file(EF_DEVOPS); file_t *tf = file_search(EF_DEVOPS);
file_put_data(tf, newopts, sizeof(newopts)); file_put_data(tf, newopts, sizeof(newopts));
low_flash_available(); flash_commit();
} }
else if (P2(apdu) == SECURE_LOCK_MASK && (opts & HSM_OPT_SECURE_LOCK)) { else if (P2(apdu) == SECURE_LOCK_MASK && (opts & HSM_OPT_SECURE_LOCK)) {
memcpy(mkek_mask, apdu.data, MKEK_KEY_SIZE); memcpy(mkek_mask, apdu.data, MKEK_KEY_SIZE);
@@ -201,106 +151,6 @@ int cmd_extras() {
} }
} }
} }
#ifndef ENABLE_EMULATION
else if (cmd == CMD_PHY) { // Set PHY
if (apdu.nc == 0) {
if (file_has_data(ef_phy)) {
res_APDU_size = file_get_size(ef_phy);
memcpy(res_APDU, file_get_data(ef_phy), res_APDU_size);
}
}
else {
if (P2(apdu) == PHY_VIDPID) { // VIDPID
if (apdu.nc != 4) {
return SW_WRONG_LENGTH();
}
phy_data.vid = get_uint16_t_be(apdu.data);
phy_data.pid = get_uint16_t_be(apdu.data + 2);
phy_data.vidpid_present = true;
}
else if (P2(apdu) == PHY_LED_GPIO) {
phy_data.led_gpio = apdu.data[0];
phy_data.led_gpio_present = true;
}
else if (P2(apdu) == PHY_LED_BTNESS) {
phy_data.led_brightness = apdu.data[0];
phy_data.led_brightness_present = true;
}
else if (P2(apdu) == PHY_OPTS) {
if (apdu.nc != 2) {
return SW_WRONG_LENGTH();
}
phy_data.opts = get_uint16_t_be(apdu.data);
}
else {
return SW_INCORRECT_P1P2();
}
if (phy_save() != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
}
#endif
#if PICO_RP2350
else if (cmd == CMD_OTP) {
if (apdu.nc < 2) {
return SW_WRONG_LENGTH();
}
uint16_t row = get_uint16_t_be(apdu.data);
bool israw = P2(apdu) == 0x1;
if (apdu.nc == 2) {
if (row > 0xbf && row < 0xf48) {
return SW_WRONG_DATA();
}
if (israw) {
memcpy(res_APDU, otp_buffer_raw(row), apdu.ne);
}
else {
memcpy(res_APDU, otp_buffer(row), apdu.ne);
}
res_APDU_size = apdu.ne;
}
else {
apdu.nc -= 2;
apdu.data += 2;
if (apdu.nc > 1024) {
return SW_WRONG_LENGTH();
}
if (apdu.nc % (israw ? 4 : 2)) {
return SW_WRONG_DATA();
}
uint8_t adata[1024] __attribute__((aligned(4)));
memcpy(adata, apdu.data, apdu.nc);
int ret = 0;
if (israw) {
ret = otp_write_data_raw(row, adata, apdu.nc);
}
else {
ret = otp_write_data(row, adata, apdu.nc);
}
if (ret != 0) {
return SW_EXEC_ERROR();
}
}
}
#endif
#ifdef PICO_PLATFORM
else if (cmd == CMD_REBOOT) {
if (apdu.nc != 0) {
return SW_WRONG_LENGTH();
}
watchdog_reboot(0, 0, 100);
}
#endif
else if (cmd == CMD_MEMORY) {
res_APDU_size = 0;
uint32_t free = flash_free_space(), total = flash_total_space(), used = flash_used_space(), nfiles = flash_num_files(), size = flash_size();
res_APDU_size += put_uint32_t_be(free, res_APDU + res_APDU_size);
res_APDU_size += put_uint32_t_be(used, res_APDU + res_APDU_size);
res_APDU_size += put_uint32_t_be(total, res_APDU + res_APDU_size);
res_APDU_size += put_uint32_t_be(nfiles, res_APDU + res_APDU_size);
res_APDU_size += put_uint32_t_be(size, res_APDU + res_APDU_size);
}
else { else {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
} }

View File

@@ -24,7 +24,7 @@
#include "files.h" #include "files.h"
#include "otp.h" #include "otp.h"
int cmd_general_authenticate() { int cmd_general_authenticate(void) {
if (P1(apdu) == 0x0 && P2(apdu) == 0x0) { if (P1(apdu) == 0x0 && P2(apdu) == 0x0) {
if (apdu.data[0] == 0x7C) { if (apdu.data[0] == 0x7C) {
int r = 0; int r = 0;
@@ -41,14 +41,14 @@ int cmd_general_authenticate() {
pubkey_len = tag_len + 1; pubkey_len = tag_len + 1;
} }
} }
file_t *fkey = search_file(EF_KEY_DEV); file_t *fkey = file_search(EF_KEY_DEV);
if (!fkey) { if (!fkey) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_ecp_keypair ectx; mbedtls_ecp_keypair ectx;
mbedtls_ecp_keypair_init(&ectx); mbedtls_ecp_keypair_init(&ectx);
r = load_private_key_ecdh(&ectx, fkey); r = load_private_key_ecdh(&ectx, fkey);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_ecp_keypair_free(&ectx); mbedtls_ecp_keypair_free(&ectx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
@@ -77,12 +77,7 @@ int cmd_general_authenticate() {
} }
size_t olen = 0; size_t olen = 0;
uint8_t derived[MBEDTLS_ECP_MAX_BYTES]; uint8_t derived[MBEDTLS_ECP_MAX_BYTES];
r = mbedtls_ecdh_calc_secret(&ctx, r = mbedtls_ecdh_calc_secret(&ctx, &olen, derived, MBEDTLS_ECP_MAX_BYTES, random_fill_iterator, NULL);
&olen,
derived,
MBEDTLS_ECP_MAX_BYTES,
random_gen,
NULL);
mbedtls_ecdh_free(&ctx); mbedtls_ecdh_free(&ctx);
if (r != 0) { if (r != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -110,7 +105,7 @@ int cmd_general_authenticate() {
r = sm_sign(t, pubkey_len + 16, res_APDU + res_APDU_size); r = sm_sign(t, pubkey_len + 16, res_APDU + res_APDU_size);
free(t); free(t);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
res_APDU_size += 8; res_APDU_size += 8;

View File

@@ -25,10 +25,8 @@
#include "cvc.h" #include "cvc.h"
#include "otp.h" #include "otp.h"
extern void scan_all();
extern char __StackLimit; extern char __StackLimit;
int heapLeft() { static int heapLeft(void) {
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM) #if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
char *p = malloc(256); // try to avoid undue fragmentation char *p = malloc(256); // try to avoid undue fragmentation
int left = &__StackLimit - p; int left = &__StackLimit - p;
@@ -39,8 +37,7 @@ int heapLeft() {
return left; return left;
} }
extern void reset_puk_store(); int cmd_initialize(void) {
int cmd_initialize() {
if (apdu.nc > 0) { if (apdu.nc > 0) {
uint8_t mkek[MKEK_SIZE]; uint8_t mkek[MKEK_SIZE];
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
@@ -48,7 +45,7 @@ int cmd_initialize() {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
} }
int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session int ret_mkek = load_mkek(mkek); //Try loading MKEK with previous session
initialize_flash(true); file_initialize_flash(true);
scan_all(); scan_all();
has_session_pin = has_session_sopin = has_mkek_mask = false; has_session_pin = has_session_sopin = has_mkek_mask = false;
uint16_t tag = 0x0; uint16_t tag = 0x0;
@@ -58,31 +55,33 @@ int cmd_initialize() {
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi); asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) { while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
if (tag == 0x80) { //options if (tag == 0x80) { //options
file_t *tf = search_file(EF_DEVOPS); file_t *tf = file_search(EF_DEVOPS);
file_put_data(tf, tag_data, tag_len); file_put_data(tf, tag_data, tag_len);
} }
else if (tag == 0x81) { //user pin else if (tag == 0x81) { //user pin
if (file_pin1 && file_pin1->data) { if (file_pin1 && file_pin1->data) {
uint8_t dhash[33]; uint8_t pin_data[34];
dhash[0] = (uint8_t)tag_len; pin_data[0] = (uint8_t)tag_len;
double_hash_pin(tag_data, tag_len, dhash + 1); pin_data[1] = 1; // Format
file_put_data(file_pin1, dhash, sizeof(dhash)); pin_derive_verifier(tag_data, tag_len, pin_data + 2);
hash_multi(tag_data, tag_len, session_pin); file_put_data(file_pin1, pin_data, sizeof(pin_data));
pin_derive_session(tag_data, tag_len, session_pin);
has_session_pin = true; has_session_pin = true;
} }
} }
else if (tag == 0x82) { //sopin pin else if (tag == 0x82) { //sopin pin
if (file_sopin && file_sopin->data) { if (file_sopin && file_sopin->data) {
uint8_t dhash[33]; uint8_t pin_data[34];
dhash[0] = (uint8_t)tag_len; pin_data[0] = (uint8_t)tag_len;
double_hash_pin(tag_data, tag_len, dhash + 1); pin_data[1] = 1; // Format
file_put_data(file_sopin, dhash, sizeof(dhash)); pin_derive_verifier(tag_data, tag_len, pin_data + 2);
hash_multi(tag_data, tag_len, session_sopin); file_put_data(file_sopin, pin_data, sizeof(pin_data));
pin_derive_session(tag_data, tag_len, session_sopin);
has_session_sopin = true; has_session_sopin = true;
} }
} }
else if (tag == 0x91) { //retries user pin else if (tag == 0x91) { //retries user pin
file_t *tf = search_file(EF_PIN1_MAX_RETRIES); file_t *tf = file_search(EF_PIN1_MAX_RETRIES);
if (tf && tf->data) { if (tf && tf->data) {
file_put_data(tf, tag_data, tag_len); file_put_data(tf, tag_data, tag_len);
} }
@@ -100,7 +99,7 @@ int cmd_initialize() {
file_put_data(tf, NULL, 0); file_put_data(tf, NULL, 0);
} }
else if (tag == 0x93) { else if (tag == 0x93) {
file_t *ef_puk = search_file(EF_PUKAUT); file_t *ef_puk = file_search(EF_PUKAUT);
if (!ef_puk) { if (!ef_puk) {
release_mkek(mkek); release_mkek(mkek);
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
@@ -132,15 +131,15 @@ int cmd_initialize() {
*/ */
} }
} }
file_t *tf_kd = search_file(EF_KEY_DOMAIN); file_t *tf_kd = file_search(EF_KEY_DOMAIN);
if (!tf_kd) { if (!tf_kd) {
release_mkek(mkek); release_mkek(mkek);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (ret_mkek != PICOKEY_OK) { if (ret_mkek != PICOKEYS_OK) {
ret_mkek = load_mkek(mkek); //Try again with new PIN/SO-PIN just in case some is the same ret_mkek = load_mkek(mkek); //Try again with new PIN/SO-PIN just in case some is the same
} }
if (store_mkek(ret_mkek == PICOKEY_OK ? mkek : NULL) != PICOKEY_OK) { if (store_mkek(ret_mkek == PICOKEYS_OK ? mkek : NULL) != PICOKEYS_OK) {
release_mkek(mkek); release_mkek(mkek);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
@@ -148,43 +147,43 @@ int cmd_initialize() {
if (dkeks) { if (dkeks) {
if (*dkeks > 0) { if (*dkeks > 0) {
uint16_t d = *dkeks; uint16_t d = *dkeks;
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) { if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
else { else {
int r = save_dkek_key(0, random_bytes_get(32)); int r = save_dkek_key(0, random_bytes_get(32));
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
uint16_t d = 0x0101; uint16_t d = 0x0101;
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) { if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
} }
else { else {
uint16_t d = 0x0000; uint16_t d = 0x0000;
if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) { if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
if (kds) { if (kds) {
uint8_t t[MAX_KEY_DOMAINS * 2], k = MIN(*kds, MAX_KEY_DOMAINS); uint8_t t[MAX_KEY_DOMAINS * 2], k = MIN(*kds, MAX_KEY_DOMAINS);
memset(t, 0xff, 2 * k); memset(t, 0xff, 2 * k);
if (file_put_data(tf_kd, t, 2 * k) != PICOKEY_OK) { if (file_put_data(tf_kd, t, 2 * k) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
/* When initialized, it has all credentials */ /* When initialized, it has all credentials */
isUserAuthenticated = true; isUserAuthenticated = true;
/* Create terminal private key */ /* Create terminal private key */
file_t *fdkey = search_file(EF_KEY_DEV); file_t *fdkey = file_search(EF_KEY_DEV);
if (!fdkey) { if (!fdkey) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
int ret = 0; int ret = 0;
if (ret_mkek != PICOKEY_OK || !file_has_data(fdkey)) { if (ret_mkek != PICOKEYS_OK || !file_has_data(fdkey)) {
mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa); mbedtls_ecdsa_init(&ecdsa);
mbedtls_ecp_group_id ec_id = MBEDTLS_ECP_DP_SECP256R1; mbedtls_ecp_group_id ec_id = MBEDTLS_ECP_DP_SECP256R1;
@@ -195,59 +194,63 @@ int cmd_initialize() {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
ret = mbedtls_ecp_mul(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, &ecdsa.grp.G, random_gen, NULL); ret = mbedtls_ecp_keypair_calc_public(&ecdsa, random_fill_iterator, NULL);
if (ret != 0) {
mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR();
}
} }
else { else {
ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_gen, NULL); ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_fill_iterator, NULL);
} }
if (ret != 0) { if (ret != 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
ret = store_keys(&ecdsa, PICO_KEYS_KEY_EC, key_id); ret = store_keys(&ecdsa, PICOKEYS_KEY_EC, key_id);
if (ret != PICOKEY_OK) { if (ret != PICOKEYS_OK) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
uint16_t ee_len = 0, term_len = 0; uint16_t ee_len = 0, term_len = 0;
if ((ee_len = asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) { if ((ee_len = asn1_cvc_aut(&ecdsa, PICOKEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
file_t *fpk = search_file(EF_EE_DEV); file_t *fpk = file_search(EF_EE_DEV);
ret = file_put_data(fpk, res_APDU, ee_len); ret = file_put_data(fpk, res_APDU, ee_len);
if (ret != 0) { if (ret != PICOKEYS_OK) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if ((term_len = asn1_cvc_cert(&ecdsa, PICO_KEYS_KEY_EC, res_APDU + ee_len, MAX_APDU_DATA - ee_len, NULL, 0, true)) == 0) { if ((term_len = asn1_cvc_cert(&ecdsa, PICOKEYS_KEY_EC, res_APDU + ee_len, MAX_APDU_DATA - ee_len, NULL, 0, true)) == 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
fpk = search_file(EF_TERMCA); fpk = file_search(EF_TERMCA);
ret = file_put_data(fpk, res_APDU, ee_len + term_len); ret = file_put_data(fpk, res_APDU, ee_len + term_len);
if (ret != 0) { if (ret != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
const uint8_t *keyid = (const uint8_t *) "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", const uint8_t *keyid = (const uint8_t *) "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0",
*label = (const uint8_t *) "ESPICOHSMTR"; *label = (const uint8_t *) "ESPICOHSMTR";
uint16_t prkd_len = asn1_build_prkd_ecc(label, (uint16_t)strlen((const char *) label), keyid, 20, 256, res_APDU, MAX_APDU_DATA); uint16_t prkd_len = asn1_build_prkd_ecc(label, (uint16_t)strlen((const char *) label), keyid, 20, 256, res_APDU, MAX_APDU_DATA);
fpk = search_file(EF_PRKD_DEV); fpk = file_search(EF_PRKD_DEV);
ret = file_put_data(fpk, res_APDU, prkd_len); ret = file_put_data(fpk, res_APDU, prkd_len);
} }
if (ret != 0) { if (ret != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
low_flash_available(); flash_commit();
reset_puk_store(); reset_puk_store();
} }
else { //free memory bytes request else { //free memory bytes request
int heap_left = heapLeft(); int heap_left = heapLeft();
res_APDU_size += put_uint32_t_be(heap_left, res_APDU); res_APDU_size += put_uint32_be(heap_left, res_APDU);
res_APDU[4] = 0; res_APDU[4] = 0;
res_APDU[5] = HSM_VERSION_MAJOR; res_APDU[5] = HSM_VERSION_MAJOR;
res_APDU[6] = HSM_VERSION_MINOR; res_APDU[6] = HSM_VERSION_MINOR;

View File

@@ -33,7 +33,7 @@ uint8_t get_key_domain(file_t *fkey) {
return 0x0; return 0x0;
} }
int cmd_key_domain() { int cmd_key_domain(void) {
//if (dkeks == 0) //if (dkeks == 0)
// return SW_COMMAND_NOT_ALLOWED(); // return SW_COMMAND_NOT_ALLOWED();
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
@@ -44,7 +44,7 @@ int cmd_key_domain() {
if (p2 >= MAX_KEY_DOMAINS) { if (p2 >= MAX_KEY_DOMAINS) {
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
} }
file_t *tf_kd = search_file(EF_KEY_DOMAIN); file_t *tf_kd = file_search(EF_KEY_DOMAIN);
if (!tf_kd) { if (!tf_kd) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
@@ -72,8 +72,8 @@ int cmd_key_domain() {
import_dkek_share(p2, apdu.data); import_dkek_share(p2, apdu.data);
if (++current_dkeks >= dkeks) { if (++current_dkeks >= dkeks) {
int r = save_dkek_key(p2, NULL); int r = save_dkek_key(p2, NULL);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
if (r == PICOKEY_NO_LOGIN) { if (r == PICOKEYS_NO_LOGIN) {
pending_save_dkek = p2; pending_save_dkek = p2;
} }
else { else {
@@ -86,13 +86,13 @@ int cmd_key_domain() {
uint8_t t[MAX_KEY_DOMAINS * 2]; uint8_t t[MAX_KEY_DOMAINS * 2];
memcpy(t, kdata, tf_kd_size); memcpy(t, kdata, tf_kd_size);
t[2 * p2 + 1] = current_dkeks; t[2 * p2 + 1] = current_dkeks;
if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEY_OK) { if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
low_flash_available(); flash_commit();
} }
else { else {
file_t *tf = search_file(EF_XKEK + p2); file_t *tf = file_search(EF_XKEK + p2);
if (current_dkeks == 0xff && !file_has_data(tf)) { //XKEK have always 0xff if (current_dkeks == 0xff && !file_has_data(tf)) { //XKEK have always 0xff
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
} }
@@ -104,7 +104,7 @@ int cmd_key_domain() {
} }
if (p1 == 0x3) { //if key domain is not empty, command is denied if (p1 == 0x3) { //if key domain is not empty, command is denied
for (uint16_t i = 1; i < 256; i++) { for (uint16_t i = 1; i < 256; i++) {
file_t *fkey = search_file(KEY_PREFIX << 8 | (uint8_t)i); file_t *fkey = file_search(KEY_PREFIX << 8 | (uint8_t)i);
if (get_key_domain(fkey) == p2) { if (get_key_domain(fkey) == p2) {
return SW_FILE_EXISTS(); return SW_FILE_EXISTS();
} }
@@ -129,21 +129,21 @@ int cmd_key_domain() {
else if (p1 == 0x4) { else if (p1 == 0x4) {
t[2 * p2 + 1] = current_dkeks = 0; t[2 * p2 + 1] = current_dkeks = 0;
} }
if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEY_OK) { if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
file_t *tf = NULL; file_t *tf = NULL;
if ((tf = search_file(EF_DKEK + p2))) { if ((tf = file_search(EF_DKEK + p2))) {
if (delete_file(tf) != PICOKEY_OK) { if (file_delete(tf) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
if (p1 == 0x3 && (tf = search_file(EF_XKEK + p2))) { if (p1 == 0x3 && (tf = file_search(EF_XKEK + p2))) {
if (delete_file(tf) != PICOKEY_OK) { if (file_delete(tf) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
low_flash_available(); flash_commit();
if (p1 == 0x3) { if (p1 == 0x3) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
} }
@@ -151,7 +151,7 @@ int cmd_key_domain() {
else if (p1 == 0x2) { //XKEK Key Domain creation else if (p1 == 0x2) { //XKEK Key Domain creation
if (apdu.nc > 0) { if (apdu.nc > 0) {
uint16_t pub_len = 0; uint16_t pub_len = 0;
file_t *fterm = search_file(EF_TERMCA); file_t *fterm = file_search(EF_TERMCA);
if (!fterm) { if (!fterm) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
@@ -190,7 +190,7 @@ int cmd_key_domain() {
t86 = cvc_get_field(pub, pub_len, &t86_len, 0x86); t86 = cvc_get_field(pub, pub_len, &t86_len, 0x86);
if (t86) { if (t86) {
file_put_data(tf, t86 + 1, (uint16_t)t86_len - 1); file_put_data(tf, t86 + 1, (uint16_t)t86_len - 1);
low_flash_available(); flash_commit();
} }
} }
} }
@@ -203,7 +203,7 @@ int cmd_key_domain() {
res_APDU[1] = dkeks > current_dkeks ? dkeks - current_dkeks : 0; res_APDU[1] = dkeks > current_dkeks ? dkeks - current_dkeks : 0;
dkek_kcv(p2, res_APDU + 2); dkek_kcv(p2, res_APDU + 2);
res_APDU_size = 2 + 8; res_APDU_size = 2 + 8;
file_t *tf = search_file(EF_XKEK + p2); file_t *tf = file_search(EF_XKEK + p2);
if (file_has_data(tf)) { if (file_has_data(tf)) {
memcpy(res_APDU + 10, file_get_data(tf), file_get_size(tf)); memcpy(res_APDU + 10, file_get_data(tf), file_get_size(tf));
res_APDU_size += file_get_size(tf); res_APDU_size += file_get_size(tf);

View File

@@ -19,7 +19,7 @@
#include "sc_hsm.h" #include "sc_hsm.h"
#include "random.h" #include "random.h"
int cmd_key_gen() { int cmd_key_gen(void) {
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
uint8_t key_size = 32; uint8_t key_size = 32;
@@ -44,24 +44,24 @@ int cmd_key_gen() {
memcpy(aes_key, random_bytes_get(key_size), key_size); memcpy(aes_key, random_bytes_get(key_size), key_size);
int aes_type = 0x0; int aes_type = 0x0;
if (key_size == 16) { if (key_size == 16) {
aes_type = PICO_KEYS_KEY_AES_128; aes_type = PICOKEYS_KEY_AES_128;
} }
else if (key_size == 24) { else if (key_size == 24) {
aes_type = PICO_KEYS_KEY_AES_192; aes_type = PICOKEYS_KEY_AES_192;
} }
else if (key_size == 32) { else if (key_size == 32) {
aes_type = PICO_KEYS_KEY_AES_256; aes_type = PICOKEYS_KEY_AES_256;
} }
else if (key_size == 64) { else if (key_size == 64) {
aes_type = PICO_KEYS_KEY_AES_512; aes_type = PICOKEYS_KEY_AES_512;
} }
r = store_keys(aes_key, aes_type, key_id); r = store_keys(aes_key, aes_type, key_id);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
if (find_and_store_meta_key(key_id) != PICOKEY_OK) { if (find_and_store_meta_key(key_id) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
low_flash_available(); flash_commit();
return SW_OK(); return SW_OK();
} }

View File

@@ -20,7 +20,7 @@
#include "kek.h" #include "kek.h"
#include "cvc.h" #include "cvc.h"
int cmd_key_unwrap() { int cmd_key_unwrap(void) {
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
int r = 0; int r = 0;
if (P2(apdu) != 0x93) { if (P2(apdu) != 0x93) {
@@ -32,7 +32,7 @@ int cmd_key_unwrap() {
uint8_t *data = apdu.data; uint8_t *data = apdu.data;
uint16_t data_len = apdu.nc; uint16_t data_len = apdu.nc;
if (data_len == 0) { // New style if (data_len == 0) { // New style
file_t *tef = search_file(0x2F10); file_t *tef = file_search(0x2F10);
if (!file_has_data(tef)) { if (!file_has_data(tef)) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
@@ -46,78 +46,72 @@ int cmd_key_unwrap() {
if (key_type == 0x0) { if (key_type == 0x0) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
} }
if (key_type & PICO_KEYS_KEY_RSA) { if (key_type & PICOKEYS_KEY_RSA) {
mbedtls_rsa_context ctx; mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx); mbedtls_rsa_init(&ctx);
do { do {
r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len); r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len);
} while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); } while ((r == PICOKEYS_ERR_FILE_NOT_FOUND || r == PICOKEYS_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = store_keys(&ctx, PICO_KEYS_KEY_RSA, key_id); r = store_keys(&ctx, PICOKEYS_KEY_RSA, key_id);
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) { if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICOKEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
else if (key_type & PICO_KEYS_KEY_EC) { else if (key_type & PICOKEYS_KEY_EC) {
mbedtls_ecp_keypair ctx; mbedtls_ecp_keypair ctx;
mbedtls_ecp_keypair_init(&ctx); mbedtls_ecp_keypair_init(&ctx);
do { do {
r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len); r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len);
} while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); } while ((r == PICOKEYS_ERR_FILE_NOT_FOUND || r == PICOKEYS_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = store_keys(&ctx, PICO_KEYS_KEY_EC, key_id); r = store_keys(&ctx, PICOKEYS_KEY_EC, key_id);
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) { if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICOKEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
else if (key_type & PICO_KEYS_KEY_AES) { else if (key_type & PICOKEYS_KEY_AES) {
uint8_t aes_key[64]; uint8_t aes_key[64];
int key_size = 0, aes_type = 0; int key_size = 0, aes_type = 0;
do { do {
r = dkek_decode_key((uint8_t)++kdom, r = dkek_decode_key((uint8_t)++kdom, aes_key, data, data_len, &key_size, &allowed, &allowed_len);
aes_key, } while ((r == PICOKEYS_ERR_FILE_NOT_FOUND || r == PICOKEYS_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
data, if (r != PICOKEYS_OK) {
data_len,
&key_size,
&allowed,
&allowed_len);
} while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS);
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (key_size == 64) { if (key_size == 64) {
aes_type = PICO_KEYS_KEY_AES_512; aes_type = PICOKEYS_KEY_AES_512;
} }
else if (key_size == 32) { else if (key_size == 32) {
aes_type = PICO_KEYS_KEY_AES_256; aes_type = PICOKEYS_KEY_AES_256;
} }
else if (key_size == 24) { else if (key_size == 24) {
aes_type = PICO_KEYS_KEY_AES_192; aes_type = PICOKEYS_KEY_AES_192;
} }
else if (key_size == 16) { else if (key_size == 16) {
aes_type = PICO_KEYS_KEY_AES_128; aes_type = PICOKEYS_KEY_AES_128;
} }
else { else {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = store_keys(aes_key, aes_type, key_id); r = store_keys(aes_key, aes_type, key_id);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
@@ -136,7 +130,7 @@ int cmd_key_unwrap() {
} }
r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len); r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len);
free(meta); free(meta);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
} }
@@ -148,6 +142,6 @@ int cmd_key_unwrap() {
} }
res_APDU_size = 0; res_APDU_size = 0;
} }
low_flash_available(); flash_commit();
return SW_OK(); return SW_OK();
} }

View File

@@ -21,9 +21,7 @@
#include "kek.h" #include "kek.h"
#include "files.h" #include "files.h"
extern uint8_t get_key_domain(file_t *fkey); int cmd_key_wrap(void) {
int cmd_key_wrap() {
int r = 0; int r = 0;
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
if (P2(apdu) != 0x92) { if (P2(apdu) != 0x92) {
@@ -32,7 +30,7 @@ int cmd_key_wrap() {
if (!isUserAuthenticated) { if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
} }
file_t *ef = search_file((KEY_PREFIX << 8) | key_id); file_t *ef = file_search((KEY_PREFIX << 8) | key_id);
if (!ef) { if (!ef) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
@@ -40,7 +38,7 @@ int cmd_key_wrap() {
if (kdom == 0xff) { if (kdom == 0xff) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
} }
file_t *tf_kd = search_file(EF_KEY_DOMAIN); file_t *tf_kd = file_search(EF_KEY_DOMAIN);
uint8_t *kdata = file_get_data(tf_kd), dkeks = kdata ? kdata[2 * kdom] : 0, uint8_t *kdata = file_get_data(tf_kd), dkeks = kdata ? kdata[2 * kdom] : 0,
current_dkeks = kdata ? kdata[2 * kdom + 1] : 0; current_dkeks = kdata ? kdata[2 * kdom + 1] : 0;
if (dkeks != current_dkeks || dkeks == 0 || dkeks == 0xff) { if (dkeks != current_dkeks || dkeks == 0 || dkeks == 0xff) {
@@ -49,7 +47,7 @@ int cmd_key_wrap() {
if (key_has_purpose(ef, ALGO_WRAP) == false) { if (key_has_purpose(ef, ALGO_WRAP) == false) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
} }
file_t *prkd = search_file((PRKD_PREFIX << 8) | key_id); file_t *prkd = file_search((PRKD_PREFIX << 8) | key_id);
if (!prkd) { if (!prkd) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
@@ -60,28 +58,28 @@ int cmd_key_wrap() {
mbedtls_rsa_context ctx; mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx); mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef); r = load_private_key_rsa(&ctx, ef);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
if (r == PICOKEY_VERIFICATION_FAILED) { if (r == PICOKEYS_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = dkek_encode_key(kdom, &ctx, PICO_KEYS_KEY_RSA, res_APDU, &wrap_len, meta_tag, tag_len); r = dkek_encode_key(kdom, &ctx, PICOKEYS_KEY_RSA, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
} }
else if (*dprkd == P15_KEYTYPE_ECC) { else if (*dprkd == P15_KEYTYPE_ECC) {
mbedtls_ecp_keypair ctx; mbedtls_ecp_keypair ctx;
mbedtls_ecp_keypair_init(&ctx); mbedtls_ecp_keypair_init(&ctx);
r = load_private_key_ec(&ctx, ef); r = load_private_key_ec(&ctx, ef);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
if (r == PICOKEY_VERIFICATION_FAILED) { if (r == PICOKEYS_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
r = dkek_encode_key(kdom, &ctx, PICO_KEYS_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len); r = dkek_encode_key(kdom, &ctx, PICOKEYS_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
} }
else if (*dprkd == P15_KEYTYPE_AES) { else if (*dprkd == P15_KEYTYPE_AES) {
@@ -90,27 +88,27 @@ int cmd_key_wrap() {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
uint16_t key_size = file_get_size(ef), aes_type = PICO_KEYS_KEY_AES; uint16_t key_size = file_get_size(ef), aes_type = PICOKEYS_KEY_AES;
memcpy(kdata_aes, file_get_data(ef), key_size); memcpy(kdata_aes, file_get_data(ef), key_size);
if (mkek_decrypt(kdata_aes, key_size) != 0) { if (mkek_decrypt(kdata_aes, key_size) != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (key_size == 64) { if (key_size == 64) {
aes_type = PICO_KEYS_KEY_AES_512; aes_type = PICOKEYS_KEY_AES_512;
} }
else if (key_size == 32) { else if (key_size == 32) {
aes_type = PICO_KEYS_KEY_AES_256; aes_type = PICOKEYS_KEY_AES_256;
} }
else if (key_size == 24) { else if (key_size == 24) {
aes_type = PICO_KEYS_KEY_AES_192; aes_type = PICOKEYS_KEY_AES_192;
} }
else if (key_size == 16) { else if (key_size == 16) {
aes_type = PICO_KEYS_KEY_AES_128; aes_type = PICOKEYS_KEY_AES_128;
} }
r = dkek_encode_key(kdom, kdata_aes, aes_type, res_APDU, &wrap_len, meta_tag, tag_len); r = dkek_encode_key(kdom, kdata_aes, aes_type, res_APDU, &wrap_len, meta_tag, tag_len);
mbedtls_platform_zeroize(kdata_aes, sizeof(kdata_aes)); mbedtls_platform_zeroize(kdata_aes, sizeof(kdata_aes));
} }
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
res_APDU_size = wrap_len; res_APDU_size = wrap_len;

View File

@@ -24,7 +24,7 @@
#include "random.h" #include "random.h"
#include "kek.h" #include "kek.h"
int cmd_keypair_gen() { int cmd_keypair_gen(void) {
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
if (!isUserAuthenticated) { if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
@@ -49,17 +49,16 @@ int cmd_keypair_gen() {
} }
mbedtls_rsa_context rsa; mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa); mbedtls_rsa_init(&rsa);
uint8_t index = 0; ret = mbedtls_rsa_gen_key(&rsa, random_fill_iterator, NULL, key_size, exponent);
ret = mbedtls_rsa_gen_key(&rsa, random_gen, &index, key_size, exponent);
if (ret != 0) { if (ret != 0) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&rsa, PICO_KEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) { if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&rsa, PICOKEYS_KEY_RSA, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
ret = store_keys(&rsa, PICO_KEYS_KEY_RSA, key_id); ret = store_keys(&rsa, PICOKEYS_KEY_RSA, key_id);
if (ret != PICOKEY_OK) { if (ret != PICOKEYS_OK) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
@@ -90,8 +89,7 @@ int cmd_keypair_gen() {
} }
mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa); mbedtls_ecdsa_init(&ecdsa);
uint8_t index = 0; ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_fill_iterator, NULL);
ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_gen, &index);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -107,12 +105,11 @@ int cmd_keypair_gen() {
if (a92.data[0] > MAX_KEY_DOMAINS) { if (a92.data[0] > MAX_KEY_DOMAINS) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
file_t *tf_xkek = search_file(EF_XKEK + a92.data[0]); file_t *tf_xkek = file_search(EF_XKEK + a92.data[0]);
if (!tf_xkek) { if (!tf_xkek) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
ext.len = 2 + 2 + (uint16_t)strlen(OID_ID_KEY_DOMAIN_UID) + 2 + file_get_size( ext.len = 2 + 2 + (uint16_t)strlen(OID_ID_KEY_DOMAIN_UID) + 2 + file_get_size(tf_xkek);
tf_xkek);
ext.data = (uint8_t *) calloc(1, ext.len); ext.data = (uint8_t *) calloc(1, ext.len);
uint8_t *pe = ext.data; uint8_t *pe = ext.data;
*pe++ = 0x73; *pe++ = 0x73;
@@ -127,7 +124,7 @@ int cmd_keypair_gen() {
} }
} }
} }
if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, ext.data, ext.len)) == 0) { if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ecdsa, PICOKEYS_KEY_EC, res_APDU, MAX_APDU_DATA, ext.data, ext.len)) == 0) {
if (ext.data) { if (ext.data) {
free(ext.data); free(ext.data);
} }
@@ -137,9 +134,9 @@ int cmd_keypair_gen() {
if (ext.data) { if (ext.data) {
free(ext.data); free(ext.data);
} }
ret = store_keys(&ecdsa, PICO_KEYS_KEY_EC, key_id); ret = store_keys(&ecdsa, PICOKEYS_KEY_EC, key_id);
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
if (ret != PICOKEY_OK) { if (ret != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
@@ -149,7 +146,7 @@ int cmd_keypair_gen() {
else { else {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
if (find_and_store_meta_key(key_id) != PICOKEY_OK) { if (find_and_store_meta_key(key_id) != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id); file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id);
@@ -160,6 +157,6 @@ int cmd_keypair_gen() {
if (apdu.ne == 0) { if (apdu.ne == 0) {
apdu.ne = res_APDU_size; apdu.ne = res_APDU_size;
} }
low_flash_available(); flash_commit();
return SW_OK(); return SW_OK();
} }

View File

@@ -18,14 +18,17 @@
#include "sc_hsm.h" #include "sc_hsm.h"
#include "files.h" #include "files.h"
int cmd_list_keys() { extern uint16_t dynamic_files;
extern file_t dynamic_file[];
int cmd_list_keys(void) {
/* First we send DEV private key */ /* First we send DEV private key */
/* Both below conditions should be always TRUE */ /* Both below conditions should be always TRUE */
if (search_file(EF_PRKD_DEV)) { if (file_search(EF_PRKD_DEV)) {
res_APDU_size += put_uint16_t_be(EF_PRKD_DEV, res_APDU + res_APDU_size); res_APDU_size += put_uint16_be(EF_PRKD_DEV, res_APDU + res_APDU_size);
} }
if (search_file(EF_KEY_DEV)) { if (file_search(EF_KEY_DEV)) {
res_APDU_size += put_uint16_t_be(EF_KEY_DEV, res_APDU + res_APDU_size); res_APDU_size += put_uint16_be(EF_KEY_DEV, res_APDU + res_APDU_size);
} }
//first CC //first CC
for (int i = 0; i < dynamic_files; i++) { for (int i = 0; i < dynamic_files; i++) {

View File

@@ -24,7 +24,7 @@
file_t *ef_puk_aut = NULL; file_t *ef_puk_aut = NULL;
int cmd_mse() { int cmd_mse(void) {
int p1 = P1(apdu); int p1 = P1(apdu);
int p2 = P2(apdu); int p2 = P2(apdu);
if (p2 != 0xA4 && p2 != 0xA6 && p2 != 0xAA && p2 != 0xB4 && p2 != 0xB6 && p2 != 0xB8) { if (p2 != 0xA4 && p2 != 0xA6 && p2 != 0xAA && p2 != 0xB4 && p2 != 0xB6 && p2 != 0xB8) {
@@ -51,13 +51,13 @@ int cmd_mse() {
} }
else { else {
if (p2 == 0xB6) { if (p2 == 0xB6) {
if (puk_store_select_chr(tag_data) == PICOKEY_OK) { if (puk_store_select_chr(tag_data) == PICOKEYS_OK) {
return SW_OK(); return SW_OK();
} }
} }
else if (p2 == 0xA4) { /* Aut */ else if (p2 == 0xA4) { /* Aut */
for (uint8_t i = 0; i < MAX_PUK; i++) { for (uint8_t i = 0; i < MAX_PUK; i++) {
file_t *ef = search_file(EF_PUK + i); file_t *ef = file_search(EF_PUK + i);
if (!ef) { if (!ef) {
break; break;
} }

View File

@@ -20,10 +20,9 @@
#include "asn1.h" #include "asn1.h"
#include "cvc.h" #include "cvc.h"
extern int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy);
extern PUK *current_puk; extern PUK *current_puk;
int cmd_pso() { int cmd_pso(void) {
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
if (p1 == 0x0 && (p2 == 0x92 || p2 == 0xAE || p2 == 0xBE)) { /* Verify certificate */ if (p1 == 0x0 && (p2 == 0x92 || p2 == 0xAE || p2 == 0xBE)) { /* Verify certificate */
if (apdu.nc == 0) { if (apdu.nc == 0) {
@@ -40,23 +39,22 @@ int cmd_pso() {
apdu.nc += tlv_len; apdu.nc += tlv_len;
} }
int r = cvc_verify(apdu.data, (uint16_t)apdu.nc, current_puk->cvcert, current_puk->cvcert_len); int r = cvc_verify(apdu.data, (uint16_t)apdu.nc, current_puk->cvcert, current_puk->cvcert_len);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
if (r == PICOKEY_WRONG_DATA) { if (r == PICOKEYS_WRONG_DATA) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
} }
else if (r == PICOKEY_WRONG_SIGNATURE) { else if (r == PICOKEYS_WRONG_SIGNATURE) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
for (uint8_t i = 0; i < 0xfe; i++) { for (uint8_t i = 0; i < 0xfe; i++) {
uint16_t fid = (CA_CERTIFICATE_PREFIX << 8) | i; uint16_t fid = (CA_CERTIFICATE_PREFIX << 8) | i;
file_t *ca_ef = search_file(fid); file_t *ca_ef = file_search(fid);
if (!ca_ef) { if (!ca_ef) {
ca_ef = file_new(fid); ca_ef = file_new(fid);
file_put_data(ca_ef, apdu.data, (uint16_t)apdu.nc); file_put_data(ca_ef, apdu.data, (uint16_t)apdu.nc);
if (add_cert_puk_store(file_get_data(ca_ef), file_get_size(ca_ef), if (add_cert_puk_store(file_get_data(ca_ef), file_get_size(ca_ef), false) != PICOKEYS_OK) {
false) != PICOKEY_OK) {
return SW_FILE_FULL(); return SW_FILE_FULL();
} }
@@ -126,30 +124,18 @@ int cmd_pso() {
} }
} }
file_t *cd_ef = file_new((CD_PREFIX << 8) | i); file_t *cd_ef = file_new((CD_PREFIX << 8) | i);
uint16_t cd_len = (uint16_t)asn1_build_cert_description(chr, uint16_t cd_len = (uint16_t)asn1_build_cert_description(chr, chr_len, puk_bin, puk_bin_len, fid, NULL, 0);
chr_len,
puk_bin,
puk_bin_len,
fid,
NULL,
0);
if (cd_len == 0) { if (cd_len == 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
uint8_t *buf = (uint8_t *) calloc(cd_len, sizeof(uint8_t)); uint8_t *buf = (uint8_t *) calloc(cd_len, sizeof(uint8_t));
r = (int)asn1_build_cert_description(chr, r = (int)asn1_build_cert_description(chr, chr_len, puk_bin, puk_bin_len, fid, buf, cd_len);
chr_len,
puk_bin,
puk_bin_len,
fid,
buf,
cd_len);
file_put_data(cd_ef, buf, cd_len); file_put_data(cd_ef, buf, cd_len);
free(buf); free(buf);
if (r == 0) { if (r == 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
low_flash_available(); flash_commit();
break; break;
} }
} }

View File

@@ -19,9 +19,9 @@
#include "files.h" #include "files.h"
#include "cvc.h" #include "cvc.h"
int cmd_puk_auth() { int cmd_puk_auth(void) {
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
file_t *ef_puk = search_file(EF_PUKAUT); file_t *ef_puk = file_search(EF_PUKAUT);
if (!file_has_data(ef_puk)) { if (!file_has_data(ef_puk)) {
if (apdu.nc > 0) { if (apdu.nc > 0) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
@@ -37,7 +37,7 @@ int cmd_puk_auth() {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
} }
for (uint8_t i = 0; i < puk_data[0]; i++) { for (uint8_t i = 0; i < puk_data[0]; i++) {
ef = search_file(EF_PUK + i); ef = file_search(EF_PUK + i);
if (!ef) { /* Never should not happen */ if (!ef) { /* Never should not happen */
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
@@ -56,13 +56,13 @@ int cmd_puk_auth() {
if (p2 >= puk_data[0]) { if (p2 >= puk_data[0]) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
} }
ef = search_file(EF_PUK + p2); ef = file_search(EF_PUK + p2);
if (!ef) { /* Never should not happen */ if (!ef) { /* Never should not happen */
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
} }
file_put_data(ef, apdu.data, (uint16_t)apdu.nc); file_put_data(ef, apdu.data, (uint16_t)apdu.nc);
low_flash_available(); flash_commit();
} }
else { else {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
@@ -72,7 +72,7 @@ int cmd_puk_auth() {
if (p2 >= puk_data[0]) { if (p2 >= puk_data[0]) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
} }
file_t *ef = search_file(EF_PUK + p2); file_t *ef = file_search(EF_PUK + p2);
if (!ef) { if (!ef) {
return SW_INCORRECT_P1P2(); return SW_INCORRECT_P1P2();
} }

View File

@@ -17,35 +17,37 @@
#include "sc_hsm.h" #include "sc_hsm.h"
int cmd_read_binary() { typedef int (*file_data_handler_t)(const file_t *f, int mode);
int cmd_read_binary(void) {
uint16_t offset = 0; uint16_t offset = 0;
uint8_t ins = INS(apdu), p1 = P1(apdu), p2 = P2(apdu); uint8_t ins = INS(apdu), p1 = P1(apdu), p2 = P2(apdu);
const file_t *ef = NULL; file_t *ef = NULL;
if ((ins & 0x1) == 0) { if ((ins & 0x1) == 0) {
if ((p1 & 0x80) != 0) { if ((p1 & 0x80) != 0) {
if (!(ef = search_file(p1 & 0x1f))) { if (!(ef = file_search(p1 & 0x1f))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
offset = p2; offset = p2;
} }
else { else {
offset = make_uint16_t_be(p1, p2) & 0x7fff; offset = make_uint16_be(p1, p2) & 0x7fff;
ef = currentEF; ef = currentEF;
} }
} }
else { else {
if (p1 == 0 && (p2 & 0xE0) == 0 && (p2 & 0x1f) != 0 && (p2 & 0x1f) != 0x1f) { if (p1 == 0 && (p2 & 0xE0) == 0 && (p2 & 0x1f) != 0 && (p2 & 0x1f) != 0x1f) {
if (!(ef = search_file(p2 & 0x1f))) { if (!(ef = file_search(p2 & 0x1f))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
else { else {
uint16_t file_id = make_uint16_t_be(p1, p2); // & 0x7fff; uint16_t file_id = make_uint16_be(p1, p2); // & 0x7fff;
if (file_id == 0x0) { if (file_id == 0x0) {
ef = currentEF; ef = currentEF;
} }
else if (!(ef = search_file(file_id))) { else if (!(ef = file_search(file_id))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
@@ -60,12 +62,28 @@ int cmd_read_binary() {
} }
} }
if ((ef->fid >> 8) == KEY_PREFIX || !authenticate_action(ef, ACL_OP_READ_SEARCH)) { if (ef == NULL) {
return SW_FILE_NOT_FOUND();
}
if (offset > 0x7fff) {
return SW_WRONG_P1P2();
}
if ((ef->fid >> 8) == PROT_DATA_PREFIX) {
memset(ef->acl, 0x90, sizeof(ef->acl)); //force PIN for protected data objects
}
if ((ef->fid >> 8) == KEY_PREFIX || !file_authenticate_action(ef, ACL_OP_READ_SEARCH)) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
} }
if (ef->data) { if (ef->data) {
if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) { if ((ef->type & FILE_DATA_FUNC) == FILE_DATA_FUNC) {
uint16_t data_len = (uint16_t)((int (*)(const file_t *, int))(ef->data))((const file_t *) ef, 1); //already copies content to res_APDU union {
uint8_t *data;
file_data_handler_t handler;
} data_func = { .data = ef->data };
uint16_t data_len = (uint16_t)data_func.handler((const file_t *) ef, 1); //already copies content to res_APDU
if (offset > data_len) { if (offset > data_len) {
return SW_WRONG_P1P2(); return SW_WRONG_P1P2();
} }

View File

@@ -18,8 +18,9 @@
#include "crypto_utils.h" #include "crypto_utils.h"
#include "sc_hsm.h" #include "sc_hsm.h"
#include "kek.h" #include "kek.h"
#include "files.h"
int cmd_reset_retry() { int cmd_reset_retry(void) {
if (P2(apdu) != 0x81) { if (P2(apdu) != 0x81) {
return SW_REFERENCE_NOT_FOUND(); return SW_REFERENCE_NOT_FOUND();
} }
@@ -55,26 +56,27 @@ int cmd_reset_retry() {
} }
newpin_len = (uint8_t)apdu.nc; newpin_len = (uint8_t)apdu.nc;
} }
uint8_t dhash[33]; if (pin_reset_retries(file_pin1, true) != PICOKEYS_OK) {
dhash[0] = newpin_len;
double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1);
file_put_data(file_pin1, dhash, sizeof(dhash));
if (pin_reset_retries(file_pin1, true) != PICOKEY_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
uint8_t mkek[MKEK_SIZE]; uint8_t mkek[MKEK_SIZE];
int r = load_mkek(mkek); //loads the MKEK with SO pin int r = load_mkek(mkek); //loads the MKEK with SO pin
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
hash_multi(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pin); pin_derive_session(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pin);
has_session_pin = true; has_session_pin = true;
r = store_mkek(mkek); r = store_mkek(mkek);
release_mkek(mkek); release_mkek(mkek);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
low_flash_available(); uint8_t dhash[34];
dhash[0] = newpin_len;
dhash[1] = 1; // Format
pin_derive_verifier(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 2);
file_put_data(file_pin1, dhash, sizeof(dhash));
flash_commit();
return SW_OK(); return SW_OK();
} }
else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) { else if (P1(apdu) == 0x1 || P1(apdu) == 0x3) {
@@ -99,7 +101,7 @@ int cmd_reset_retry() {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
} }
} }
if (pin_reset_retries(file_pin1, true) != PICOKEY_OK) { if (pin_reset_retries(file_pin1, true) != PICOKEYS_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
return SW_OK(); return SW_OK();

View File

@@ -16,8 +16,12 @@
*/ */
#include "sc_hsm.h" #include "sc_hsm.h"
#include "files.h"
#include "version.h" #include "version.h"
extern const file_t *file_openpgp;
extern const file_t *file_sc_hsm;
void select_file(file_t *pe) { void select_file(file_t *pe) {
if (!pe) { if (!pe) {
currentDF = (file_t *) MF; currentDF = (file_t *) MF;
@@ -36,7 +40,7 @@ void select_file(file_t *pe) {
} }
} }
int cmd_select() { int cmd_select(void) {
uint8_t p1 = P1(apdu); uint8_t p1 = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
file_t *pe = NULL; file_t *pe = NULL;
@@ -48,7 +52,7 @@ int cmd_select() {
//} //}
if (apdu.nc == 2) { if (apdu.nc == 2) {
fid = get_uint16_t_be(apdu.data); fid = get_uint16_be(apdu.data);
} }
//if ((fid & 0xff00) == (KEY_PREFIX << 8)) //if ((fid & 0xff00) == (KEY_PREFIX << 8))
@@ -63,7 +67,7 @@ int cmd_select() {
pfx == DCOD_PREFIX || pfx == DCOD_PREFIX ||
pfx == DATA_PREFIX || pfx == DATA_PREFIX ||
pfx == PROT_DATA_PREFIX) {*/ pfx == PROT_DATA_PREFIX) {*/
if (fid != 0x0 && !(pe = search_file(fid))) { if (fid != 0x0 && !(pe = file_search(fid))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
/*}*/ /*}*/
@@ -74,18 +78,18 @@ int cmd_select() {
//ac_fini(); //ac_fini();
} }
else if (apdu.nc == 2) { else if (apdu.nc == 2) {
if (!(pe = search_by_fid(fid, NULL, SPECIFY_ANY))) { if (!(pe = file_search_by_fid(fid, NULL, SPECIFY_ANY))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
} }
else if (p1 == 0x01) { //Select child DF - DF identifier else if (p1 == 0x01) { //Select child DF - DF identifier
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_DF))) { if (!(pe = file_search_by_fid(fid, currentDF, SPECIFY_DF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
else if (p1 == 0x02) { //Select EF under the current DF - EF identifier else if (p1 == 0x02) { //Select EF under the current DF - EF identifier
if (!(pe = search_by_fid(fid, currentDF, SPECIFY_EF))) { if (!(pe = file_search_by_fid(fid, currentDF, SPECIFY_EF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
@@ -95,7 +99,7 @@ int cmd_select() {
} }
} }
else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier else if (p1 == 0x04) { //Select by DF name - e.g., [truncated] application identifier
if (!(pe = search_by_name(apdu.data, (uint16_t)apdu.nc))) { if (!(pe = file_search_by_name(apdu.data, (uint16_t)apdu.nc))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
if (card_terminated) { if (card_terminated) {
@@ -103,23 +107,23 @@ int cmd_select() {
} }
} }
else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier else if (p1 == 0x08) { //Select from the MF - Path without the MF identifier
if (!(pe = search_by_path(apdu.data, (uint8_t)apdu.nc, MF))) { if (!(pe = file_search_by_path(apdu.data, (uint8_t)apdu.nc, MF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier else if (p1 == 0x09) { //Select from the current DF - Path without the current DF identifier
if (!(pe = search_by_path(apdu.data, (uint8_t)apdu.nc, currentDF))) { if (!(pe = file_search_by_path(apdu.data, (uint8_t)apdu.nc, currentDF))) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
} }
} }
if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) { if ((p2 & 0xfc) == 0x00 || (p2 & 0xfc) == 0x04) {
process_fci(pe, 0); file_process_fci(pe, 0);
if (pe == file_sc_hsm) { if (pe == file_sc_hsm) {
res_APDU[res_APDU_size++] = 0x85; res_APDU[res_APDU_size++] = 0x85;
res_APDU[res_APDU_size++] = 5; res_APDU[res_APDU_size++] = 5;
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
res_APDU_size += put_uint16_t_be(opts, res_APDU + res_APDU_size); res_APDU_size += put_uint16_be(opts, res_APDU + res_APDU_size);
res_APDU[res_APDU_size++] = 0xFF; res_APDU[res_APDU_size++] = 0xFF;
res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR; res_APDU[res_APDU_size++] = HSM_VERSION_MAJOR;
res_APDU[res_APDU_size++] = HSM_VERSION_MINOR; res_APDU[res_APDU_size++] = HSM_VERSION_MINOR;

View File

@@ -1,35 +0,0 @@
/*
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 "sc_hsm.h"
#include "random.h"
#include "eac.h"
int cmd_session_pin() {
if (P1(apdu) == 0x01 && P2(apdu) == 0x81) {
memcpy(sm_session_pin, random_bytes_get(8), 8);
sm_session_pin_len = 8;
memcpy(res_APDU, sm_session_pin, sm_session_pin_len);
res_APDU_size = sm_session_pin_len;
apdu.ne = sm_session_pin_len;
}
else {
return SW_INCORRECT_P1P2();
}
return SW_OK();
}

View File

@@ -72,11 +72,11 @@ static const struct digest_info_prefix {
{ MBEDTLS_MD_RIPEMD160, hdr_ripemd160, sizeof(hdr_ripemd160), 20 }, { MBEDTLS_MD_RIPEMD160, hdr_ripemd160, sizeof(hdr_ripemd160), 20 },
{ 0, NULL, 0, 0 } { 0, NULL, 0, 0 }
}; };
int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm, static int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm,
const uint8_t *in_dat, const uint8_t *in_dat,
uint16_t in_len, uint16_t in_len,
uint8_t *out_dat, uint8_t *out_dat,
uint16_t *out_len) { uint16_t *out_len) {
for (int i = 0; digest_info_prefix[i].algorithm != 0; i++) { for (int i = 0; digest_info_prefix[i].algorithm != 0; i++) {
uint16_t hdr_len = digest_info_prefix[i].hdr_len, hash_len = digest_info_prefix[i].hash_len; uint16_t hdr_len = digest_info_prefix[i].hdr_len, hash_len = digest_info_prefix[i].hash_len;
const uint8_t *hdr = digest_info_prefix[i].hdr; const uint8_t *hdr = digest_info_prefix[i].hdr;
@@ -85,21 +85,21 @@ int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm,
*algorithm = digest_info_prefix[i].algorithm; *algorithm = digest_info_prefix[i].algorithm;
} }
if (out_dat == NULL) { if (out_dat == NULL) {
return PICOKEY_OK; return PICOKEYS_OK;
} }
if (*out_len < hash_len) { if (*out_len < hash_len) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
memmove(out_dat, in_dat + hdr_len, hash_len); memmove(out_dat, in_dat + hdr_len, hash_len);
*out_len = hash_len; *out_len = hash_len;
return PICOKEY_OK; return PICOKEYS_OK;
} }
} }
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
//----- //-----
int cmd_signature() { int cmd_signature(void) {
uint8_t key_id = P1(apdu); uint8_t key_id = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);
mbedtls_md_type_t md = MBEDTLS_MD_NONE; mbedtls_md_type_t md = MBEDTLS_MD_NONE;
@@ -107,7 +107,7 @@ int cmd_signature() {
if (!isUserAuthenticated) { if (!isUserAuthenticated) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
} }
if (!(fkey = search_file((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) { if (!(fkey = file_search((KEY_PREFIX << 8) | key_id)) || !file_has_data(fkey)) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
if (get_key_counter(fkey) == 0) { if (get_key_counter(fkey) == 0) {
@@ -145,9 +145,9 @@ int cmd_signature() {
mbedtls_rsa_init(&ctx); mbedtls_rsa_init(&ctx);
int r = load_private_key_rsa(&ctx, fkey); int r = load_private_key_rsa(&ctx, fkey);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_rsa_free(&ctx); mbedtls_rsa_free(&ctx);
if (r == PICOKEY_VERIFICATION_FAILED) { if (r == PICOKEYS_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -156,7 +156,7 @@ int cmd_signature() {
if (p2 == ALGO_RSA_PKCS1) { //DigestInfo attached if (p2 == ALGO_RSA_PKCS1) { //DigestInfo attached
uint16_t nc = (uint16_t)apdu.nc; uint16_t nc = (uint16_t)apdu.nc;
if (pkcs1_strip_digest_info_prefix(&md, apdu.data, (uint16_t)apdu.nc, apdu.data, if (pkcs1_strip_digest_info_prefix(&md, apdu.data, (uint16_t)apdu.nc, apdu.data,
&nc) != PICOKEY_OK) { //gets the MD algo id and strips it off &nc) != PICOKEYS_OK) { //gets the MD algo id and strips it off
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
apdu.nc = nc; apdu.nc = nc;
@@ -214,11 +214,11 @@ int cmd_signature() {
if (apdu.nc < key_size) { //needs padding if (apdu.nc < key_size) { //needs padding
memset(apdu.data + apdu.nc, 0, key_size - apdu.nc); memset(apdu.data + apdu.nc, 0, key_size - apdu.nc);
} }
r = mbedtls_rsa_private(&ctx, random_gen, NULL, apdu.data, res_APDU); r = mbedtls_rsa_private(&ctx, random_fill_iterator, NULL, apdu.data, res_APDU);
} }
else { else {
uint8_t *signature = (uint8_t *) calloc(key_size, sizeof(uint8_t)); uint8_t *signature = (uint8_t *) calloc(key_size, sizeof(uint8_t));
r = mbedtls_rsa_pkcs1_sign(&ctx, random_gen, NULL, md, hash.len, hash.data, signature); r = mbedtls_rsa_pkcs1_sign(&ctx, random_fill_iterator, NULL, md, hash.len, hash.data, signature);
memcpy(res_APDU, signature, key_size); memcpy(res_APDU, signature, key_size);
free(signature); free(signature);
} }
@@ -267,9 +267,9 @@ int cmd_signature() {
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
} }
int r = load_private_key_ec(&ctx, fkey); int r = load_private_key_ec(&ctx, fkey);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
if (r == PICOKEY_VERIFICATION_FAILED) { if (r == PICOKEYS_VERIFICATION_FAILED) {
return SW_SECURE_MESSAGE_EXEC_ERROR(); return SW_SECURE_MESSAGE_EXEC_ERROR();
} }
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
@@ -278,13 +278,12 @@ int cmd_signature() {
uint8_t buf[MBEDTLS_ECDSA_MAX_LEN]; uint8_t buf[MBEDTLS_ECDSA_MAX_LEN];
#ifdef MBEDTLS_EDDSA_C #ifdef MBEDTLS_EDDSA_C
if (ctx.grp.id == MBEDTLS_ECP_DP_ED25519 || ctx.grp.id == MBEDTLS_ECP_DP_ED448) { if (ctx.grp.id == MBEDTLS_ECP_DP_ED25519 || ctx.grp.id == MBEDTLS_ECP_DP_ED448) {
r = mbedtls_eddsa_write_signature(&ctx, apdu.data, apdu.nc, buf, sizeof(buf), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL); r = mbedtls_eddsa_write_signature(&ctx, apdu.data, apdu.nc, buf, sizeof(buf), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_fill_iterator, NULL);
} }
else else
#endif #endif
{ {
r = mbedtls_ecdsa_write_signature(&ctx, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, r = mbedtls_ecdsa_write_signature(&ctx, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, &olen, random_fill_iterator, NULL);
&olen, random_gen, NULL);
} }
if (r != 0) { if (r != 0) {
mbedtls_ecp_keypair_free(&ctx); mbedtls_ecp_keypair_free(&ctx);
@@ -306,9 +305,7 @@ int cmd_signature() {
return SW_INCORRECT_PARAMS(); return SW_INCORRECT_PARAMS();
} }
md = MBEDTLS_MD_SHA256; md = MBEDTLS_MD_SHA256;
if (mbedtls_ecdsa_write_signature(&hd_context, md, apdu.data, apdu.nc, buf, if (mbedtls_ecdsa_write_signature(&hd_context, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, &olen, random_fill_iterator, NULL) != 0) {
MBEDTLS_ECDSA_MAX_LEN,
&olen, random_gen, NULL) != 0) {
mbedtls_ecp_keypair_free(&hd_context); mbedtls_ecp_keypair_free(&hd_context);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }

View File

@@ -18,9 +18,7 @@
#include "sc_hsm.h" #include "sc_hsm.h"
#include "asn1.h" #include "asn1.h"
extern void select_file(file_t *pe); int cmd_update_ef(void) {
int cmd_update_ef() {
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
uint16_t fid = (p1 << 8) | p2; uint16_t fid = (p1 << 8) | p2;
uint8_t *data = NULL; uint8_t *data = NULL;
@@ -42,7 +40,7 @@ int cmd_update_ef() {
} }
*/ */
if (ef && !authenticate_action(ef, ACL_OP_UPDATE_ERASE)) { if (ef && !file_authenticate_action(ef, ACL_OP_UPDATE_ERASE)) {
return SW_SECURITY_STATUS_NOT_SATISFIED(); return SW_SECURITY_STATUS_NOT_SATISFIED();
} }
@@ -72,13 +70,13 @@ int cmd_update_ef() {
if (fid == 0x0 && !ef) { if (fid == 0x0 && !ef) {
return SW_FILE_NOT_FOUND(); return SW_FILE_NOT_FOUND();
} }
else if (fid != 0x0 && !(ef = search_file(fid))) { //if does not exist, create it else if (fid != 0x0 && !(ef = file_search(fid))) { //if does not exist, create it
//return SW_FILE_NOT_FOUND(); //return SW_FILE_NOT_FOUND();
ef = file_new(fid); ef = file_new(fid);
} }
if (offset == 0) { if (offset == 0) {
int r = file_put_data(ef, data, data_len); int r = file_put_data(ef, data, data_len);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
} }
@@ -86,17 +84,20 @@ int cmd_update_ef() {
if (!file_has_data(ef)) { if (!file_has_data(ef)) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
} }
if (offset + data_len > 4032) {
return SW_WRONG_LENGTH();
}
uint8_t *data_merge = (uint8_t *) calloc(1, offset + data_len); uint8_t *data_merge = (uint8_t *) calloc(1, MAX(offset + data_len, file_get_size(ef)));
memcpy(data_merge, file_get_data(ef), offset); memcpy(data_merge, file_get_data(ef), file_get_size(ef));
memcpy(data_merge + offset, data, data_len); memcpy(data_merge + offset, data, data_len);
int r = file_put_data(ef, data_merge, offset + data_len); int r = file_put_data(ef, data_merge, offset + data_len);
free(data_merge); free(data_merge);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
} }
low_flash_available(); flash_commit();
} }
return SW_OK(); return SW_OK();
} }

View File

@@ -16,8 +16,9 @@
*/ */
#include "sc_hsm.h" #include "sc_hsm.h"
#include "files.h"
int cmd_verify() { int cmd_verify(void) {
uint8_t p1 = P1(apdu); uint8_t p1 = P1(apdu);
uint8_t p2 = P2(apdu); uint8_t p2 = P2(apdu);

View File

@@ -30,10 +30,7 @@
#include "mbedtls/eddsa.h" #include "mbedtls/eddsa.h"
#endif #endif
extern const uint8_t *dev_name; static uint16_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, uint16_t buf_len) {
extern uint16_t dev_name_len;
uint16_t asn1_cvc_public_key_rsa(mbedtls_rsa_context *rsa, uint8_t *buf, uint16_t buf_len) {
const uint8_t oid_rsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x01, 0x02 }; const uint8_t oid_rsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x01, 0x02 };
uint16_t n_size = (uint16_t)mbedtls_mpi_size(&rsa->N), e_size = (uint16_t)mbedtls_mpi_size(&rsa->E); uint16_t n_size = (uint16_t)mbedtls_mpi_size(&rsa->N), e_size = (uint16_t)mbedtls_mpi_size(&rsa->E);
uint16_t ntot_size = asn1_len_tag(0x81, n_size), etot_size = asn1_len_tag(0x82, e_size); uint16_t ntot_size = asn1_len_tag(0x81, n_size), etot_size = asn1_len_tag(0x82, e_size);
@@ -74,7 +71,7 @@ const uint8_t *pointA[] = {
"\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC",
}; };
uint16_t asn1_cvc_public_key_ecdsa(mbedtls_ecp_keypair *ecdsa, uint8_t *buf, uint16_t buf_len) { static uint16_t asn1_cvc_public_key_ecdsa(mbedtls_ecp_keypair *ecdsa, uint8_t *buf, uint16_t buf_len) {
uint8_t Y_buf[MBEDTLS_ECP_MAX_PT_LEN], G_buf[MBEDTLS_ECP_MAX_PT_LEN]; uint8_t Y_buf[MBEDTLS_ECP_MAX_PT_LEN], G_buf[MBEDTLS_ECP_MAX_PT_LEN];
const uint8_t oid_ecdsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03 }; const uint8_t oid_ecdsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03 };
const uint8_t oid_ri[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x05, 0x02, 0x03 }; const uint8_t oid_ri[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x05, 0x02, 0x03 };
@@ -167,18 +164,12 @@ uint16_t asn1_cvc_public_key_ecdsa(mbedtls_ecp_keypair *ecdsa, uint8_t *buf, uin
return tot_len; return tot_len;
} }
uint16_t asn1_cvc_cert_body(void *rsa_ecdsa, static uint16_t asn1_cvc_cert_body(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, uint16_t buf_len, const uint8_t *ext, uint16_t ext_len, bool full) {
uint8_t key_type,
uint8_t *buf,
uint16_t buf_len,
const uint8_t *ext,
uint16_t ext_len,
bool full) {
uint16_t pubkey_size = 0; uint16_t pubkey_size = 0;
if (key_type & PICO_KEYS_KEY_RSA) { if (key_type & PICOKEYS_KEY_RSA) {
pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0); pubkey_size = asn1_cvc_public_key_rsa(rsa_ecdsa, NULL, 0);
} }
else if (key_type & PICO_KEYS_KEY_EC) { else if (key_type & PICOKEYS_KEY_EC) {
pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0); pubkey_size = asn1_cvc_public_key_ecdsa(rsa_ecdsa, NULL, 0);
} }
uint16_t cpi_size = 4, ext_size = 0, role_size = 0, valid_size = 0; uint16_t cpi_size = 4, ext_size = 0, role_size = 0, valid_size = 0;
@@ -228,10 +219,10 @@ uint16_t asn1_cvc_cert_body(void *rsa_ecdsa,
//car //car
*p++ = 0x42; p += format_tlv_len(car.len, p); memcpy(p, car.data, car.len); p += car.len; *p++ = 0x42; p += format_tlv_len(car.len, p); memcpy(p, car.data, car.len); p += car.len;
//pubkey //pubkey
if (key_type & PICO_KEYS_KEY_RSA) { if (key_type & PICOKEYS_KEY_RSA) {
p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size); p += asn1_cvc_public_key_rsa(rsa_ecdsa, p, pubkey_size);
} }
else if (key_type & PICO_KEYS_KEY_EC) { else if (key_type & PICOKEYS_KEY_EC) {
p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size); p += asn1_cvc_public_key_ecdsa(rsa_ecdsa, p, pubkey_size);
} }
//chr //chr
@@ -264,18 +255,12 @@ uint16_t asn1_cvc_cert_body(void *rsa_ecdsa,
return tot_len; return tot_len;
} }
uint16_t asn1_cvc_cert(void *rsa_ecdsa, uint16_t asn1_cvc_cert(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, uint16_t buf_len, const uint8_t *ext, uint16_t ext_len, bool full) {
uint8_t key_type,
uint8_t *buf,
uint16_t buf_len,
const uint8_t *ext,
uint16_t ext_len,
bool full) {
uint16_t key_size = 0; uint16_t key_size = 0;
if (key_type & PICO_KEYS_KEY_RSA) { if (key_type & PICOKEYS_KEY_RSA) {
key_size = (uint16_t)mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N); key_size = (uint16_t)mbedtls_mpi_size(&((mbedtls_rsa_context *) rsa_ecdsa)->N);
} }
else if (key_type & PICO_KEYS_KEY_EC) { else if (key_type & PICOKEYS_KEY_EC) {
key_size = 2 * (int)((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *) rsa_ecdsa)->grp.id)->bit_size + 7) / 8); key_size = 2 * (int)((mbedtls_ecp_curve_info_from_grp_id(((mbedtls_ecdsa_context *) rsa_ecdsa)->grp.id)->bit_size + 7) / 8);
} }
uint16_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, full), sig_size = asn1_len_tag(0x5f37, key_size); uint16_t body_size = asn1_cvc_cert_body(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, full), sig_size = asn1_len_tag(0x5f37, key_size);
@@ -295,13 +280,13 @@ uint16_t asn1_cvc_cert(void *rsa_ecdsa,
hash256(body, body_size, hsh); hash256(body, body_size, hsh);
memcpy(p, "\x5F\x37", 2); p += 2; memcpy(p, "\x5F\x37", 2); p += 2;
p += format_tlv_len(key_size, p); p += format_tlv_len(key_size, p);
if (key_type & PICO_KEYS_KEY_RSA) { if (key_type & PICOKEYS_KEY_RSA) {
if (mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa_ecdsa, random_gen, NULL, MBEDTLS_MD_SHA256, 32, hsh, p) != 0) { if (mbedtls_rsa_rsassa_pkcs1_v15_sign(rsa_ecdsa, random_fill_iterator, NULL, MBEDTLS_MD_SHA256, 32, hsh, p) != 0) {
memset(p, 0, key_size); memset(p, 0, key_size);
} }
p += key_size; p += key_size;
} }
else if (key_type & PICO_KEYS_KEY_EC) { else if (key_type & PICOKEYS_KEY_EC) {
mbedtls_mpi r, s; mbedtls_mpi r, s;
int ret = 0; int ret = 0;
mbedtls_ecp_keypair *ecdsa = (mbedtls_ecp_keypair *) rsa_ecdsa; mbedtls_ecp_keypair *ecdsa = (mbedtls_ecp_keypair *) rsa_ecdsa;
@@ -309,12 +294,12 @@ uint16_t asn1_cvc_cert(void *rsa_ecdsa,
mbedtls_mpi_init(&s); mbedtls_mpi_init(&s);
#ifdef MBEDTLS_EDDSA_C #ifdef MBEDTLS_EDDSA_C
if (ecdsa->grp.id == MBEDTLS_ECP_DP_ED25519 || ecdsa->grp.id == MBEDTLS_ECP_DP_ED448) { if (ecdsa->grp.id == MBEDTLS_ECP_DP_ED25519 || ecdsa->grp.id == MBEDTLS_ECP_DP_ED448) {
ret = mbedtls_eddsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, body, body_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL); ret = mbedtls_eddsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, body, body_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_fill_iterator, NULL);
} }
else else
#endif #endif
{ {
ret = mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_gen, NULL); ret = mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_fill_iterator, NULL);
} }
if (ret == 0) { if (ret == 0) {
mbedtls_mpi_write_binary(&r, p, key_size / 2); p += key_size / 2; mbedtls_mpi_write_binary(&r, p, key_size / 2); p += key_size / 2;
@@ -330,23 +315,18 @@ uint16_t asn1_cvc_cert(void *rsa_ecdsa,
return (uint16_t)(p - buf); return (uint16_t)(p - buf);
} }
uint16_t asn1_cvc_aut(void *rsa_ecdsa, uint16_t asn1_cvc_aut(void *rsa_ecdsa, uint8_t key_type, uint8_t *buf, uint16_t buf_len, const uint8_t *ext, uint16_t ext_len) {
uint8_t key_type,
uint8_t *buf,
uint16_t buf_len,
const uint8_t *ext,
uint16_t ext_len) {
uint16_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, false); uint16_t cvcert_size = asn1_cvc_cert(rsa_ecdsa, key_type, NULL, 0, ext, ext_len, false);
uint16_t outcar_len = dev_name_len; uint16_t outcar_len = dev_name_len;
const uint8_t *outcar = dev_name; const uint8_t *outcar = dev_name;
uint16_t outcar_size = asn1_len_tag(0x42, outcar_len); uint16_t outcar_size = asn1_len_tag(0x42, outcar_len);
file_t *fkey = search_file(EF_KEY_DEV); file_t *fkey = file_search(EF_KEY_DEV);
if (!fkey) { if (!fkey) {
return 0; return 0;
} }
mbedtls_ecp_keypair ectx; mbedtls_ecp_keypair ectx;
mbedtls_ecp_keypair_init(&ectx); mbedtls_ecp_keypair_init(&ectx);
if (load_private_key_ec(&ectx, fkey) != PICOKEY_OK) { if (load_private_key_ec(&ectx, fkey) != PICOKEYS_OK) {
mbedtls_ecp_keypair_free(&ectx); mbedtls_ecp_keypair_free(&ectx);
return 0; return 0;
} }
@@ -374,14 +354,14 @@ uint16_t asn1_cvc_aut(void *rsa_ecdsa,
mbedtls_mpi_init(&s); mbedtls_mpi_init(&s);
#ifdef MBEDTLS_EDDSA_C #ifdef MBEDTLS_EDDSA_C
if (ectx.grp.id == MBEDTLS_ECP_DP_ED25519 || ectx.grp.id == MBEDTLS_ECP_DP_ED448) { if (ectx.grp.id == MBEDTLS_ECP_DP_ED25519 || ectx.grp.id == MBEDTLS_ECP_DP_ED448) {
ret = mbedtls_eddsa_sign(&ectx.grp, &r, &s, &ectx.d, body, cvcert_size + outcar_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL); ret = mbedtls_eddsa_sign(&ectx.grp, &r, &s, &ectx.d, body, cvcert_size + outcar_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_fill_iterator, NULL);
} }
else else
#endif #endif
{ {
uint8_t hsh[32]; uint8_t hsh[32];
hash256(body, cvcert_size + outcar_size, hsh); hash256(body, cvcert_size + outcar_size, hsh);
ret = mbedtls_ecdsa_sign(&ectx.grp, &r, &s, &ectx.d, hsh, sizeof(hsh), random_gen, NULL); ret = mbedtls_ecdsa_sign(&ectx.grp, &r, &s, &ectx.d, hsh, sizeof(hsh), random_fill_iterator, NULL);
} }
mbedtls_ecp_keypair_free(&ectx); mbedtls_ecp_keypair_free(&ectx);
if (ret != 0) { if (ret != 0) {
@@ -396,20 +376,11 @@ uint16_t asn1_cvc_aut(void *rsa_ecdsa,
return (uint16_t)(p - buf); return (uint16_t)(p - buf);
} }
uint16_t asn1_build_cert_description(const uint8_t *label, uint16_t asn1_build_cert_description(const uint8_t *label, uint16_t label_len, const uint8_t *puk, uint16_t puk_len, uint16_t fid, uint8_t *buf, uint16_t buf_len) {
uint16_t label_len,
const uint8_t *puk,
uint16_t puk_len,
uint16_t fid,
uint8_t *buf,
uint16_t buf_len) {
uint16_t opt_len = 2; uint16_t opt_len = 2;
uint16_t seq1_size = uint16_t seq1_size = asn1_len_tag(0x30, asn1_len_tag(0xC, label_len) + asn1_len_tag(0x3, opt_len));
asn1_len_tag(0x30, asn1_len_tag(0xC, label_len) + asn1_len_tag(0x3, opt_len));
uint16_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, 20)); /* SHA1 is 20 bytes length */ uint16_t seq2_size = asn1_len_tag(0x30, asn1_len_tag(0x4, 20)); /* SHA1 is 20 bytes length */
uint16_t seq3_size = uint16_t seq3_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t)))));
asn1_len_tag(0xA1,
asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, sizeof(uint16_t)))));
uint16_t tot_len = asn1_len_tag(0x30, seq1_size + seq2_size + seq3_size); uint16_t tot_len = asn1_len_tag(0x30, seq1_size + seq2_size + seq3_size);
if (buf_len == 0 || buf == NULL) { if (buf_len == 0 || buf == NULL) {
return tot_len; return tot_len;
@@ -447,32 +418,25 @@ uint16_t asn1_build_cert_description(const uint8_t *label,
p += format_tlv_len(asn1_len_tag(0x4, sizeof(uint16_t)), p); p += format_tlv_len(asn1_len_tag(0x4, sizeof(uint16_t)), p);
*p++ = 0x4; *p++ = 0x4;
p += format_tlv_len(sizeof(uint16_t), p); p += format_tlv_len(sizeof(uint16_t), p);
put_uint16_t_be(fid, p); p += sizeof(uint16_t); put_uint16_be(fid, p); p += sizeof(uint16_t);
return (uint16_t)(p - buf); return (uint16_t)(p - buf);
} }
uint16_t asn1_build_prkd_generic(const uint8_t *label, uint16_t asn1_build_prkd_generic(const uint8_t *label, uint16_t label_len, const uint8_t *keyid, uint16_t keyid_len, uint16_t keysize, int key_type, uint8_t *buf, uint16_t buf_len) {
uint16_t label_len,
const uint8_t *keyid,
uint16_t keyid_len,
uint16_t keysize,
int key_type,
uint8_t *buf,
uint16_t buf_len) {
uint16_t seq_len = 0; uint16_t seq_len = 0;
const uint8_t *seq = NULL; const uint8_t *seq = NULL;
uint8_t first_tag = 0x0; uint8_t first_tag = 0x0;
if (key_type & PICO_KEYS_KEY_EC) { if (key_type & PICOKEYS_KEY_EC) {
seq = (const uint8_t *)"\x07\x20\x80"; seq = (const uint8_t *)"\x07\x20\x80";
seq_len = 3; seq_len = 3;
first_tag = 0xA0; first_tag = 0xA0;
} }
else if (key_type & PICO_KEYS_KEY_RSA) { else if (key_type & PICOKEYS_KEY_RSA) {
seq = (const uint8_t *)"\x02\x74"; seq = (const uint8_t *)"\x02\x74";
seq_len = 2; seq_len = 2;
first_tag = 0x30; first_tag = 0x30;
} }
else if (key_type & PICO_KEYS_KEY_AES) { else if (key_type & PICOKEYS_KEY_AES) {
seq = (const uint8_t *)"\x07\xC0\x10"; seq = (const uint8_t *)"\x07\xC0\x10";
seq_len = 3; seq_len = 3;
first_tag = 0xA8; first_tag = 0xA8;
@@ -481,10 +445,10 @@ uint16_t asn1_build_prkd_generic(const uint8_t *label,
uint16_t seq2_size = uint16_t seq2_size =
asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len) + asn1_len_tag(0x3, seq_len)); asn1_len_tag(0x30, asn1_len_tag(0x4, keyid_len) + asn1_len_tag(0x3, seq_len));
uint16_t seq3_size = 0, seq4_size = 0; uint16_t seq3_size = 0, seq4_size = 0;
if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_KEY_RSA) { if (key_type & PICOKEYS_KEY_EC || key_type & PICOKEYS_KEY_RSA) {
seq4_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0)) + asn1_len_tag(0x2, 2))); seq4_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0)) + asn1_len_tag(0x2, 2)));
} }
else if (key_type & PICO_KEYS_KEY_AES) { else if (key_type & PICOKEYS_KEY_AES) {
seq3_size = asn1_len_tag(0xA0, asn1_len_tag(0x30, asn1_len_tag(0x2, 2))); seq3_size = asn1_len_tag(0xA0, asn1_len_tag(0x30, asn1_len_tag(0x2, 2)));
seq4_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0)))); seq4_size = asn1_len_tag(0xA1, asn1_len_tag(0x30, asn1_len_tag(0x30, asn1_len_tag(0x4, 0))));
} }
@@ -516,20 +480,20 @@ uint16_t asn1_build_prkd_generic(const uint8_t *label,
memcpy(p, seq, seq_len); p += seq_len; memcpy(p, seq, seq_len); p += seq_len;
//Seq 3 //Seq 3
if (key_type & PICO_KEYS_KEY_AES) { if (key_type & PICOKEYS_KEY_AES) {
*p++ = 0xA0; *p++ = 0xA0;
p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x2, 2)), p); p += format_tlv_len(asn1_len_tag(0x30, asn1_len_tag(0x2, 2)), p);
*p++ = 0x30; *p++ = 0x30;
p += format_tlv_len(asn1_len_tag(0x2, 2), p); p += format_tlv_len(asn1_len_tag(0x2, 2), p);
*p++ = 0x2; *p++ = 0x2;
p += format_tlv_len(2, p); p += format_tlv_len(2, p);
p += put_uint16_t_be(keysize, p); p += put_uint16_be(keysize, p);
} }
//Seq 4 //Seq 4
*p++ = 0xA1; *p++ = 0xA1;
uint16_t inseq4_len = asn1_len_tag(0x30, asn1_len_tag(0x4, 0)); uint16_t inseq4_len = asn1_len_tag(0x30, asn1_len_tag(0x4, 0));
if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_KEY_RSA) { if (key_type & PICOKEYS_KEY_EC || key_type & PICOKEYS_KEY_RSA) {
inseq4_len += asn1_len_tag(0x2, 2); inseq4_len += asn1_len_tag(0x2, 2);
} }
p += format_tlv_len(asn1_len_tag(0x30, inseq4_len), p); p += format_tlv_len(asn1_len_tag(0x30, inseq4_len), p);
@@ -539,63 +503,24 @@ uint16_t asn1_build_prkd_generic(const uint8_t *label,
p += format_tlv_len(asn1_len_tag(0x4, 0), p); p += format_tlv_len(asn1_len_tag(0x4, 0), p);
*p++ = 0x4; *p++ = 0x4;
p += format_tlv_len(0, p); p += format_tlv_len(0, p);
if (key_type & PICO_KEYS_KEY_EC || key_type & PICO_KEYS_KEY_RSA) { if (key_type & PICOKEYS_KEY_EC || key_type & PICOKEYS_KEY_RSA) {
*p++ = 0x2; *p++ = 0x2;
p += format_tlv_len(2, p); p += format_tlv_len(2, p);
p += put_uint16_t_be(keysize, p); p += put_uint16_be(keysize, p);
} }
return (uint16_t)(p - buf); return (uint16_t)(p - buf);
} }
uint16_t asn1_build_prkd_ecc(const uint8_t *label, uint16_t asn1_build_prkd_ecc(const uint8_t *label, uint16_t label_len, const uint8_t *keyid, uint16_t keyid_len, uint16_t keysize, uint8_t *buf, uint16_t buf_len) {
uint16_t label_len, return asn1_build_prkd_generic(label, label_len, keyid, keyid_len, keysize, PICOKEYS_KEY_EC, buf, buf_len);
const uint8_t *keyid,
uint16_t keyid_len,
uint16_t keysize,
uint8_t *buf,
uint16_t buf_len) {
return asn1_build_prkd_generic(label,
label_len,
keyid,
keyid_len,
keysize,
PICO_KEYS_KEY_EC,
buf,
buf_len);
} }
uint16_t asn1_build_prkd_rsa(const uint8_t *label, uint16_t asn1_build_prkd_rsa(const uint8_t *label, uint16_t label_len, const uint8_t *keyid, uint16_t keyid_len, uint16_t keysize, uint8_t *buf, uint16_t buf_len) {
uint16_t label_len, return asn1_build_prkd_generic(label, label_len, keyid, keyid_len, keysize, PICOKEYS_KEY_RSA, buf, buf_len);
const uint8_t *keyid,
uint16_t keyid_len,
uint16_t keysize,
uint8_t *buf,
uint16_t buf_len) {
return asn1_build_prkd_generic(label,
label_len,
keyid,
keyid_len,
keysize,
PICO_KEYS_KEY_RSA,
buf,
buf_len);
} }
uint16_t asn1_build_prkd_aes(const uint8_t *label, uint16_t asn1_build_prkd_aes(const uint8_t *label, uint16_t label_len, const uint8_t *keyid, uint16_t keyid_len, uint16_t keysize, uint8_t *buf, uint16_t buf_len) {
uint16_t label_len, return asn1_build_prkd_generic(label, label_len, keyid, keyid_len, keysize, PICOKEYS_KEY_AES, buf, buf_len);
const uint8_t *keyid,
uint16_t keyid_len,
uint16_t keysize,
uint8_t *buf,
uint16_t buf_len) {
return asn1_build_prkd_generic(label,
label_len,
keyid,
keyid_len,
keysize,
PICO_KEYS_KEY_AES,
buf,
buf_len);
} }
const uint8_t *cvc_get_field(const uint8_t *data, uint16_t len, uint16_t *olen, uint16_t tag) { const uint8_t *cvc_get_field(const uint8_t *data, uint16_t len, uint16_t *olen, uint16_t tag) {
@@ -611,7 +536,7 @@ const uint8_t *cvc_get_field(const uint8_t *data, uint16_t len, uint16_t *olen,
return ctxo.data; return ctxo.data;
} }
const uint8_t *cvc_get_body(const uint8_t *data, uint16_t len, uint16_t *olen) { static const uint8_t *cvc_get_body(const uint8_t *data, uint16_t len, uint16_t *olen) {
const uint8_t *bkdata = data; const uint8_t *bkdata = data;
if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) { /* Check for CSR */ if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) { /* Check for CSR */
data = bkdata; data = bkdata;
@@ -622,7 +547,7 @@ const uint8_t *cvc_get_body(const uint8_t *data, uint16_t len, uint16_t *olen) {
return NULL; return NULL;
} }
const uint8_t *cvc_get_sig(const uint8_t *data, uint16_t len, uint16_t *olen) { static const uint8_t *cvc_get_sig(const uint8_t *data, uint16_t len, uint16_t *olen) {
const uint8_t *bkdata = data; const uint8_t *bkdata = data;
if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) { /* Check for CSR */ if ((data = cvc_get_field(data, len, olen, 0x67)) == NULL) { /* Check for CSR */
data = bkdata; data = bkdata;
@@ -664,7 +589,7 @@ const uint8_t *cvc_get_ext(const uint8_t *data, uint16_t len, uint16_t *olen) {
extern PUK puk_store[MAX_PUK_STORE_ENTRIES]; extern PUK puk_store[MAX_PUK_STORE_ENTRIES];
extern int puk_store_entries; extern int puk_store_entries;
int puk_store_index(const uint8_t *chr, uint16_t chr_len) { static int puk_store_index(const uint8_t *chr, uint16_t chr_len) {
for (int i = 0; i < puk_store_entries; i++) { for (int i = 0; i < puk_store_entries; i++) {
if (memcmp(puk_store[i].chr, chr, chr_len) == 0) { if (memcmp(puk_store[i].chr, chr, chr_len) == 0) {
return i; return i;
@@ -706,30 +631,22 @@ mbedtls_ecp_group_id cvc_inherite_ec_group(const uint8_t *ca, uint16_t ca_len) {
return ec_get_curve_from_prime(t81, t81_len); return ec_get_curve_from_prime(t81, t81_len);
} }
int puk_verify(const uint8_t *sig, int puk_verify(const uint8_t *sig, uint16_t sig_len, const uint8_t *hash, uint16_t hash_len, const uint8_t *ca, uint16_t ca_len) {
uint16_t sig_len,
const uint8_t *hash,
uint16_t hash_len,
const uint8_t *ca,
uint16_t ca_len) {
uint16_t puk_len = 0; uint16_t puk_len = 0;
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len); const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
if (!puk) { if (!puk) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
uint16_t oid_len = 0; uint16_t oid_len = 0;
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6); const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
if (!oid) { if (!oid) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
uint16_t t81_len = 0, t82_len = 0; uint16_t t81_len = 0, t82_len = 0;
const uint8_t *t81 = cvc_get_field(puk, puk_len, &t81_len, 0x81), *t82 = cvc_get_field(puk, const uint8_t *t81 = cvc_get_field(puk, puk_len, &t81_len, 0x81), *t82 = cvc_get_field(puk, puk_len, &t81_len, 0x82);
puk_len,
&t81_len,
0x82);
if (!t81 || !t82) { if (!t81 || !t82) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
mbedtls_rsa_context rsa; mbedtls_rsa_context rsa;
mbedtls_rsa_init(&rsa); mbedtls_rsa_init(&rsa);
@@ -757,32 +674,32 @@ int puk_verify(const uint8_t *sig,
} }
if (md == MBEDTLS_MD_NONE) { if (md == MBEDTLS_MD_NONE) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
int r = mbedtls_mpi_read_binary(&rsa.N, t81, t81_len); int r = mbedtls_mpi_read_binary(&rsa.N, t81, t81_len);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
r = mbedtls_mpi_read_binary(&rsa.E, t82, t82_len); r = mbedtls_mpi_read_binary(&rsa.E, t82, t82_len);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
r = mbedtls_rsa_complete(&rsa); r = mbedtls_rsa_complete(&rsa);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
r = mbedtls_rsa_check_pubkey(&rsa); r = mbedtls_rsa_check_pubkey(&rsa);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
r = mbedtls_rsa_pkcs1_verify(&rsa, md, (unsigned int)hash_len, hash, sig); r = mbedtls_rsa_pkcs1_verify(&rsa, md, (unsigned int)hash_len, hash, sig);
mbedtls_rsa_free(&rsa); mbedtls_rsa_free(&rsa);
if (r != 0) { if (r != 0) {
return PICOKEY_WRONG_SIGNATURE; return PICOKEYS_WRONG_SIGNATURE;
} }
} }
else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC
@@ -803,34 +720,34 @@ int puk_verify(const uint8_t *sig,
md = MBEDTLS_MD_SHA512; md = MBEDTLS_MD_SHA512;
} }
if (md == MBEDTLS_MD_NONE) { if (md == MBEDTLS_MD_NONE) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
uint16_t t86_len = 0; uint16_t t86_len = 0;
const uint8_t *t86 = cvc_get_field(puk, puk_len, &t86_len, 0x86); const uint8_t *t86 = cvc_get_field(puk, puk_len, &t86_len, 0x86);
if (!t86) { if (!t86) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(ca, ca_len); mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(ca, ca_len);
if (ec_id == MBEDTLS_ECP_DP_NONE) { if (ec_id == MBEDTLS_ECP_DP_NONE) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_context ecdsa;
mbedtls_ecdsa_init(&ecdsa); mbedtls_ecdsa_init(&ecdsa);
int ret = mbedtls_ecp_group_load(&ecdsa.grp, ec_id); int ret = mbedtls_ecp_group_load(&ecdsa.grp, ec_id);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
ret = mbedtls_ecp_point_read_binary(&ecdsa.grp, &ecdsa.Q, t86, t86_len); ret = mbedtls_ecp_point_read_binary(&ecdsa.grp, &ecdsa.Q, t86, t86_len);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
ret = mbedtls_ecp_check_pubkey(&ecdsa.grp, &ecdsa.Q); ret = mbedtls_ecp_check_pubkey(&ecdsa.grp, &ecdsa.Q);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
mbedtls_mpi r, s; mbedtls_mpi r, s;
mbedtls_mpi_init(&r); mbedtls_mpi_init(&r);
@@ -840,44 +757,44 @@ int puk_verify(const uint8_t *sig,
mbedtls_mpi_free(&r); mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s); mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
ret = mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2); ret = mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2);
if (ret != 0) { if (ret != 0) {
mbedtls_mpi_free(&r); mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s); mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
ret = mbedtls_ecdsa_verify(&ecdsa.grp, hash, hash_len, &ecdsa.Q, &r, &s); ret = mbedtls_ecdsa_verify(&ecdsa.grp, hash, hash_len, &ecdsa.Q, &r, &s);
mbedtls_mpi_free(&r); mbedtls_mpi_free(&r);
mbedtls_mpi_free(&s); mbedtls_mpi_free(&s);
mbedtls_ecdsa_free(&ecdsa); mbedtls_ecdsa_free(&ecdsa);
if (ret != 0) { if (ret != 0) {
return PICOKEY_WRONG_SIGNATURE; return PICOKEYS_WRONG_SIGNATURE;
} }
} }
return PICOKEY_OK; return PICOKEYS_OK;
} }
int cvc_verify(const uint8_t *cert, uint16_t cert_len, const uint8_t *ca, uint16_t ca_len) { int cvc_verify(const uint8_t *cert, uint16_t cert_len, const uint8_t *ca, uint16_t ca_len) {
uint16_t puk_len = 0; uint16_t puk_len = 0;
const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len); const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len);
if (!puk) { if (!puk) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
uint16_t oid_len = 0, cv_body_len = 0, sig_len = 0; uint16_t oid_len = 0, cv_body_len = 0, sig_len = 0;
const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6); const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6);
const uint8_t *cv_body = cvc_get_body(cert, cert_len, &cv_body_len); const uint8_t *cv_body = cvc_get_body(cert, cert_len, &cv_body_len);
const uint8_t *sig = cvc_get_sig(cert, cert_len, &sig_len); const uint8_t *sig = cvc_get_sig(cert, cert_len, &sig_len);
if (!sig) { if (!sig) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (!cv_body) { if (!cv_body) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (!oid) { if (!oid) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
mbedtls_md_type_t md = MBEDTLS_MD_NONE; mbedtls_md_type_t md = MBEDTLS_MD_NONE;
if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA
@@ -918,18 +835,18 @@ int cvc_verify(const uint8_t *cert, uint16_t cert_len, const uint8_t *ca, uint16
} }
} }
if (md == MBEDTLS_MD_NONE) { if (md == MBEDTLS_MD_NONE) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md);
uint8_t hash[64], hash_len = mbedtls_md_get_size(md_info); uint8_t hash[64], hash_len = mbedtls_md_get_size(md_info);
uint8_t tlv_body = 2 + format_tlv_len(cv_body_len, NULL); uint8_t tlv_body = 2 + format_tlv_len(cv_body_len, NULL);
int r = mbedtls_md(md_info, cv_body - tlv_body, cv_body_len + tlv_body, hash); int r = mbedtls_md(md_info, cv_body - tlv_body, cv_body_len + tlv_body, hash);
if (r != 0) { if (r != 0) {
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
r = puk_verify(sig, sig_len, hash, hash_len, ca, ca_len); r = puk_verify(sig, sig_len, hash, hash_len, ca, ca_len);
if (r != 0) { if (r != 0) {
return PICOKEY_WRONG_SIGNATURE; return PICOKEYS_WRONG_SIGNATURE;
} }
return PICOKEY_OK; return PICOKEYS_OK;
} }

View File

@@ -22,88 +22,230 @@ extern int parse_token_info(const file_t *f, int mode);
extern int parse_ef_dir(const file_t *f, int mode); extern int parse_ef_dir(const file_t *f, int mode);
file_t file_entries[] = { file_t file_entries[] = {
/* 0 */ { .fid = 0x3f00, .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, /* 0 */ { .fid = 0x3f00, // MF
.ef_structure = 0, .acl = { 0 } }, // MF .parent = 0xff,
/* 1 */ { .fid = 0x2f00, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_ef_dir, .name = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.DIR .type = FILE_TYPE_DF,
/* 2 */ { .fid = 0x2f01, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.ATR .ef_structure = 0,
/* 3 */ { .fid = EF_TERMCA, .parent = 0, .name = NULL, .acl = ACL_ALL },
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, /* 1 */ { .fid = 0x2f00, //EF.DIR
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.GDO .parent = 0,
/* 4 */ { .fid = 0x2f03, .parent = 5, .name = NULL, .name = NULL,
.type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC, .data = (uint8_t *) parse_token_info, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.TokenInfo .data = (uint8_t *) parse_ef_dir,
/* 5 */ { .fid = 0x5015, .parent = 0, .name = NULL, .type = FILE_TYPE_DF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT,
.ef_structure = 0, .acl = { 0 } }, //DF.PKCS15 .acl = ACL_ALL },
/* 6 */ { .fid = 0x5031, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, /* 2 */ { .fid = 0x2f01, // EF.ATR
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.ODF .parent = 0,
/* 7 */ { .fid = 0x5032, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .name = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.TokenInfo .type = FILE_TYPE_WORKING_EF,
/* 8 */ { .fid = 0x5033, .parent = 0, .name = NULL, .type = FILE_TYPE_WORKING_EF, .data = NULL, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.UnusedSpace .ef_structure = FILE_EF_TRANSPARENT,
/* 9 */ { .fid = EF_PIN1, .parent = 5, .name = NULL, .acl = ACL_ALL },
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, /* 3 */ { .fid = EF_TERMCA, // EF.GDO
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //PIN (PIN1) .parent = 0,
/* 10 */ { .fid = EF_PIN1_MAX_RETRIES, .parent = 5, .name = NULL, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .type = FILE_TYPE_WORKING_EF | FILE_DATA_FLASH | FILE_PERSISTENT,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //max retries PIN (PIN1) .data = NULL,
/* 11 */ { .fid = EF_PIN1_RETRIES, .parent = 5, .name = NULL, .ef_structure = FILE_EF_TRANSPARENT,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .acl = ACL_ALL },
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //retries PIN (PIN1) /* 4 */ { .fid = 0x2f03, // EF.TokenInfo
/* 12 */ { .fid = EF_SOPIN, .parent = 5, .name = NULL, .parent = 5,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .name = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //PIN (SOPIN) .type = FILE_TYPE_WORKING_EF | FILE_DATA_FUNC,
/* 13 */ { .fid = EF_SOPIN_MAX_RETRIES, .parent = 5, .name = NULL, .data = (uint8_t *) parse_token_info,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //max retries PIN (SOPIN) .acl = ACL_ALL },
/* 14 */ { .fid = EF_SOPIN_RETRIES, .parent = 5, .name = NULL, /* 5 */ { .fid = 0x5015, // DF.PKCS15
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .parent = 0,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //retries PIN (SOPIN) .name = NULL,
/* 15 */ { .fid = EF_DEVOPS, .parent = 5, .name = NULL, .type = FILE_TYPE_DF,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Device options .ef_structure = 0,
/* 16 */ { .fid = EF_PRKDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .acl = ACL_ALL },
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.PrKDFs /* 6 */ { .fid = 0x5031, // EF.ODF
/* 17 */ { .fid = EF_PUKDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .parent = 5,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.PuKDFs .name = NULL,
/* 18 */ { .fid = EF_CDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .type = FILE_TYPE_WORKING_EF,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.CDFs .data = NULL,
/* 19 */ { .fid = EF_AODFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .ef_structure = FILE_EF_TRANSPARENT,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.AODFs .acl = ACL_ALL },
/* 20 */ { .fid = EF_DODFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, /* 7 */ { .fid = 0x5032, // EF.TokenInfo
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.DODFs .parent = 5,
/* 21 */ { .fid = EF_SKDFS, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF, .name = NULL,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, //EF.SKDFs .type = FILE_TYPE_WORKING_EF,
/* 22 */ { .fid = EF_KEY_DOMAIN, .parent = 5, .name = NULL, .data = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Key domain options .acl = ACL_ALL },
/* 23 */ { .fid = EF_META, .parent = 5, .name = NULL, /* 8 */ { .fid = 0x5033, // EF.UnusedSpace
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .parent = 0,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //EF.CDFs .name = NULL,
/* 24 */ { .fid = EF_PUKAUT, .parent = 5, .name = NULL, .type = FILE_TYPE_WORKING_EF,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH, .data = NULL, .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Public Key Authentication .ef_structure = FILE_EF_TRANSPARENT,
/* 25 */ { .fid = EF_KEY_DEV, .parent = 5, .name = NULL, .acl = ACL_ALL },
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, /* 9 */ { .fid = EF_PIN1, // PIN (PIN1)
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //Device Key .parent = 5,
/* 26 */ { .fid = EF_PRKD_DEV, .parent = 5, .name = NULL, .name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //PrKD Device .data = NULL,
/* 27 */ { .fid = EF_EE_DEV, .parent = 5, .name = NULL, .ef_structure = FILE_EF_TRANSPARENT,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .acl = ACL_NONE },
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //End Entity Certificate Device /* 10 */ { .fid = EF_PIN1_MAX_RETRIES, // max retries PIN (PIN1)
/* 28 */ { .fid = EF_MKEK, .parent = 5, .name = NULL, .parent = 5,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .name = NULL,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //MKEK .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
/* 29 */ { .fid = EF_MKEK_SO, .parent = 5, .name = NULL, .data = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT,
.ef_structure = FILE_EF_TRANSPARENT, .acl = { 0xff } }, //MKEK with SO-PIN .acl = ACL_NONE },
///* 30 */ { .fid = 0x0000, .parent = 0, .name = openpgpcard_aid, .type = FILE_TYPE_WORKING_EF, .data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = {0} }, /* 11 */ { .fid = EF_PIN1_RETRIES, // retries PIN (PIN1)
/* 31 */ { .fid = 0x0000, .parent = 5, .name = sc_hsm_aid, .type = FILE_TYPE_WORKING_EF, .parent = 5,
.data = NULL, .ef_structure = FILE_EF_TRANSPARENT, .acl = { 0 } }, .name = NULL,
/* 32 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL, .type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.ef_structure = 0, .acl = { 0 } } //end .data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 12 */ { .fid = EF_SOPIN, // PIN (SOPIN)
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 13 */ { .fid = EF_SOPIN_MAX_RETRIES, // max retries PIN (SOPIN)
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 14 */ { .fid = EF_SOPIN_RETRIES, // retries PIN (SOPIN)
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 15 */ { .fid = EF_DEVOPS, // Device options
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 16 */ { .fid = EF_PRKDFS, // EF.PrKDFs
.parent = 5,
.name = NULL,
.type = FILE_TYPE_WORKING_EF,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_ALL },
/* 17 */ { .fid = EF_PUKDFS, // EF.PuKDFs
.parent = 5,
.name = NULL,
.type = FILE_TYPE_WORKING_EF,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_ALL },
/* 18 */ { .fid = EF_CDFS, // EF.CDFs
.parent = 5,
.name = NULL,
.type = FILE_TYPE_WORKING_EF,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_ALL },
/* 19 */ { .fid = EF_AODFS, // EF.AODFs
.parent = 5,
.name = NULL,
.type = FILE_TYPE_WORKING_EF,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_ALL },
/* 20 */ { .fid = EF_DODFS, // EF.DODFs
.parent = 5,
.name = NULL,
.type = FILE_TYPE_WORKING_EF,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_ALL },
/* 21 */ { .fid = EF_SKDFS, // EF.SKDFs
.parent = 5,
.name = NULL,
.type = FILE_TYPE_WORKING_EF,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_ALL },
/* 22 */ { .fid = EF_KEY_DOMAIN, // Key domain options
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 23 */ { .fid = EF_META, // EF.CDFs
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 24 */ { .fid = EF_PUKAUT, // Public Key Authentication
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 25 */ { .fid = EF_KEY_DEV, // Device Key
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 26 */ { .fid = EF_PRKD_DEV, // PrKD Device
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_RO },
/* 27 */ { .fid = EF_EE_DEV, // End Entity Certificate Device
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_R_WP },
/* 28 */ { .fid = EF_MKEK, // MKEK
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 29 */ { .fid = EF_MKEK_SO, // MKEK with SO-PIN
.parent = 5,
.name = NULL,
.type = FILE_TYPE_INTERNAL_EF | FILE_DATA_FLASH | FILE_PERSISTENT,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_NONE },
/* 30 */ { .fid = 0x0000,
.parent = 5,
.name = sc_hsm_aid,
.type = FILE_TYPE_WORKING_EF,
.data = NULL,
.ef_structure = FILE_EF_TRANSPARENT,
.acl = ACL_ALL },
/* 31 */ { .fid = 0x0000, // end
.parent = 0xff,
.name = NULL,
.type = FILE_TYPE_NOT_KNOWN,
.data = NULL,
.ef_structure = 0,
.acl = { 0 } }
}; };
const file_t *MF = &file_entries[0]; const file_t *MF = &file_entries[0];

View File

@@ -31,13 +31,11 @@
#include "files.h" #include "files.h"
#include "otp.h" #include "otp.h"
extern bool has_session_pin, has_session_sopin;
extern uint8_t session_pin[32], session_sopin[32];
uint8_t mkek_mask[MKEK_KEY_SIZE]; uint8_t mkek_mask[MKEK_KEY_SIZE];
bool has_mkek_mask = false; bool has_mkek_mask = false;
uint8_t pending_save_dkek = 0xff; uint8_t pending_save_dkek = 0xff;
void mkek_masked(uint8_t *mkek, const uint8_t *mask) { static void mkek_masked(uint8_t *mkek, const uint8_t *mask) {
if (mask) { if (mask) {
for (int i = 0; i < MKEK_KEY_SIZE; i++) { for (int i = 0; i < MKEK_KEY_SIZE; i++) {
MKEK_KEY(mkek)[i] ^= mask[i]; MKEK_KEY(mkek)[i] ^= mask[i];
@@ -47,42 +45,66 @@ void mkek_masked(uint8_t *mkek, const uint8_t *mask) {
int load_mkek(uint8_t *mkek) { int load_mkek(uint8_t *mkek) {
if (has_session_pin == false && has_session_sopin == false) { if (has_session_pin == false && has_session_sopin == false) {
return PICOKEY_NO_LOGIN; return PICOKEYS_NO_LOGIN;
} }
file_t *ef = NULL;
const uint8_t *pin = NULL; const uint8_t *pin = NULL;
if (pin == NULL && has_session_pin == true) { if (pin == NULL && has_session_pin == true) {
file_t *tf = search_file(EF_MKEK); file_t *tf = file_search(EF_MKEK);
if (file_has_data(tf)) { if (file_has_data(tf)) {
memcpy(mkek, file_get_data(tf), MKEK_SIZE); ef = tf;
pin = session_pin; pin = session_pin;
} }
} }
if (pin == NULL && has_session_sopin == true) { if (pin == NULL && has_session_sopin == true) {
file_t *tf = search_file(EF_MKEK_SO); file_t *tf = file_search(EF_MKEK_SO);
if (file_has_data(tf)) { if (file_has_data(tf)) {
memcpy(mkek, file_get_data(tf), MKEK_SIZE); ef = tf;
pin = session_sopin; pin = session_sopin;
} }
} }
if (pin == NULL) { //Should never happen if (pin == NULL) { //Should never happen
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
if (has_mkek_mask) { uint16_t fid_size = file_get_size(ef);
mkek_masked(mkek, mkek_mask); if (fid_size == MKEK_SIZE_OLD) {
memcpy(mkek, file_get_data(ef), MKEK_SIZE_OLD);
if (has_mkek_mask) {
mkek_masked(mkek, mkek_mask);
}
int ret = aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE);
if (ret != 0) {
return PICOKEYS_EXEC_ERROR;
}
uint32_t mkek_checksum = 0;
memcpy(&mkek_checksum, MKEK_CHECKSUM(mkek), sizeof(mkek_checksum));
if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != mkek_checksum) {
return PICOKEYS_WRONG_DKEK;
}
if (otp_key_1) {
mkek_masked(mkek, otp_key_1);
}
} }
else if (fid_size == MKEK_FILE_SIZE) {
int ret = aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE); uint8_t format = *file_get_data(ef);
if (ret != 0) { if (format == 0x03) { // Format indicator
return PICOKEY_EXEC_ERROR; uint8_t tmp_key[MKEK_FILE_SIZE];
memcpy(tmp_key, file_get_data(ef), sizeof(tmp_key));
int ret = decrypt_with_aad(pin, tmp_key + 1, MKEK_FILE_SIZE - 1, 2, mkek);
mbedtls_platform_zeroize(tmp_key, sizeof(tmp_key));
if (ret != PICOKEYS_OK) {
return PICOKEYS_EXEC_ERROR;
}
}
else {
return PICOKEYS_EXEC_ERROR;
}
} }
if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != *(uint32_t *) MKEK_CHECKSUM(mkek)) { else {
return PICOKEY_WRONG_DKEK; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
if (otp_key_1) { return PICOKEYS_OK;
mkek_masked(mkek, otp_key_1);
}
return PICOKEY_OK;
} }
mse_t mse = { .init = false }; mse_t mse = { .init = false };
@@ -96,10 +118,10 @@ int mse_decrypt_ct(uint8_t *data, size_t len) {
return ret; return ret;
} }
int load_dkek(uint8_t id, uint8_t *dkek) { static int load_dkek(uint8_t id, uint8_t *dkek) {
file_t *tf = search_file(EF_DKEK + id); file_t *tf = file_search(EF_DKEK + id);
if (!file_has_data(tf)) { if (!file_has_data(tf)) {
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE); memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
return mkek_decrypt(dkek, DKEK_KEY_SIZE); return mkek_decrypt(dkek, DKEK_KEY_SIZE);
@@ -111,71 +133,55 @@ void release_mkek(uint8_t *mkek) {
int store_mkek(const uint8_t *mkek) { int store_mkek(const uint8_t *mkek) {
if (has_session_pin == false && has_session_sopin == false) { if (has_session_pin == false && has_session_sopin == false) {
return PICOKEY_NO_LOGIN; return PICOKEYS_NO_LOGIN;
} }
uint8_t tmp_mkek[MKEK_SIZE]; uint8_t tmp_mkek[MKEK_FILE_SIZE];
tmp_mkek[0] = 0x03; // Format indicator
if (mkek == NULL) { if (mkek == NULL) {
const uint8_t *rd = random_bytes_get(MKEK_IV_SIZE + MKEK_KEY_SIZE); mkek = random_bytes_get(MKEK_SIZE);
memcpy(tmp_mkek, rd, MKEK_IV_SIZE + MKEK_KEY_SIZE);
} }
else {
memcpy(tmp_mkek, mkek, MKEK_SIZE);
}
if (otp_key_1) {
mkek_masked(tmp_mkek, otp_key_1);
}
*(uint32_t *) MKEK_CHECKSUM(tmp_mkek) = crc32c(MKEK_KEY(tmp_mkek), MKEK_KEY_SIZE);
if (has_session_pin) { if (has_session_pin) {
uint8_t tmp_mkek_pin[MKEK_SIZE]; file_t *ef = file_search(EF_MKEK);
memcpy(tmp_mkek_pin, tmp_mkek, MKEK_SIZE); if (!ef) {
file_t *tf = search_file(EF_MKEK); return PICOKEYS_ERR_FILE_NOT_FOUND;
if (!tf) {
release_mkek(tmp_mkek);
release_mkek(tmp_mkek_pin);
return PICOKEY_ERR_FILE_NOT_FOUND;
} }
aes_encrypt_cfb_256(session_pin, MKEK_IV(tmp_mkek_pin), MKEK_KEY(tmp_mkek_pin), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE); encrypt_with_aad(session_pin, mkek, MKEK_SIZE, 2, tmp_mkek + 1);
file_put_data(tf, tmp_mkek_pin, MKEK_SIZE); file_put_data(ef, tmp_mkek, sizeof(tmp_mkek));
release_mkek(tmp_mkek_pin);
} }
if (has_session_sopin) { if (has_session_sopin) {
uint8_t tmp_mkek_sopin[MKEK_SIZE]; file_t *ef = file_search(EF_MKEK_SO);
memcpy(tmp_mkek_sopin, tmp_mkek, MKEK_SIZE); if (!ef) {
file_t *tf = search_file(EF_MKEK_SO); return PICOKEYS_ERR_FILE_NOT_FOUND;
if (!tf) {
release_mkek(tmp_mkek);
release_mkek(tmp_mkek_sopin);
return PICOKEY_ERR_FILE_NOT_FOUND;
} }
aes_encrypt_cfb_256(session_sopin, MKEK_IV(tmp_mkek_sopin), MKEK_KEY(tmp_mkek_sopin), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE); encrypt_with_aad(session_sopin, mkek, MKEK_SIZE, 2, tmp_mkek + 1);
file_put_data(tf, tmp_mkek_sopin, MKEK_SIZE); file_put_data(ef, tmp_mkek, sizeof(tmp_mkek));
release_mkek(tmp_mkek_sopin);
} }
low_flash_available(); flash_commit();
release_mkek(tmp_mkek); mbedtls_platform_zeroize(tmp_mkek, sizeof(tmp_mkek));
return PICOKEY_OK;
return PICOKEYS_OK;
} }
int store_dkek_key(uint8_t id, uint8_t *dkek) { int store_dkek_key(uint8_t id, uint8_t *dkek) {
file_t *tf = search_file(EF_DKEK + id); file_t *tf = file_search(EF_DKEK + id);
if (!tf) { if (!tf) {
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
int r = mkek_encrypt(dkek, DKEK_KEY_SIZE); int r = mkek_encrypt(dkek, DKEK_KEY_SIZE);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
file_put_data(tf, dkek, DKEK_KEY_SIZE); file_put_data(tf, dkek, DKEK_KEY_SIZE);
low_flash_available(); flash_commit();
return PICOKEY_OK; return PICOKEYS_OK;
} }
int save_dkek_key(uint8_t id, const uint8_t *key) { int save_dkek_key(uint8_t id, const uint8_t *key) {
uint8_t dkek[DKEK_KEY_SIZE]; uint8_t dkek[DKEK_KEY_SIZE];
if (!key) { if (!key) {
file_t *tf = search_file(EF_DKEK + id); file_t *tf = file_search(EF_DKEK + id);
if (!tf) { if (!tf) {
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE); memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE);
} }
@@ -187,9 +193,9 @@ int save_dkek_key(uint8_t id, const uint8_t *key) {
int import_dkek_share(uint8_t id, const uint8_t *share) { int import_dkek_share(uint8_t id, const uint8_t *share) {
uint8_t tmp_dkek[DKEK_KEY_SIZE]; uint8_t tmp_dkek[DKEK_KEY_SIZE];
file_t *tf = search_file(EF_DKEK + id); file_t *tf = file_search(EF_DKEK + id);
if (!tf) { if (!tf) {
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
memset(tmp_dkek, 0, sizeof(tmp_dkek)); memset(tmp_dkek, 0, sizeof(tmp_dkek));
if (file_get_size(tf) == DKEK_KEY_SIZE) { if (file_get_size(tf) == DKEK_KEY_SIZE) {
@@ -199,8 +205,8 @@ int import_dkek_share(uint8_t id, const uint8_t *share) {
tmp_dkek[i] ^= share[i]; tmp_dkek[i] ^= share[i];
} }
file_put_data(tf, tmp_dkek, DKEK_KEY_SIZE); file_put_data(tf, tmp_dkek, DKEK_KEY_SIZE);
low_flash_available(); flash_commit();
return PICOKEY_OK; return PICOKEYS_OK;
} }
int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes
@@ -208,45 +214,45 @@ int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes
memset(kcv, 0, 8); memset(kcv, 0, 8);
memset(hsh, 0, sizeof(hsh)); memset(hsh, 0, sizeof(hsh));
int r = load_dkek(id, dkek); int r = load_dkek(id, dkek);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
hash256(dkek, DKEK_KEY_SIZE, hsh); hash256(dkek, DKEK_KEY_SIZE, hsh);
mbedtls_platform_zeroize(dkek, sizeof(dkek)); mbedtls_platform_zeroize(dkek, sizeof(dkek));
memcpy(kcv, hsh, 8); memcpy(kcv, hsh, 8);
return PICOKEY_OK; return PICOKEYS_OK;
} }
int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes static int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes
uint8_t dkek[DKEK_KEY_SIZE + 4]; uint8_t dkek[DKEK_KEY_SIZE + 4];
memset(kenc, 0, 32); memset(kenc, 0, 32);
int r = load_dkek(id, dkek); int r = load_dkek(id, dkek);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4); memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4);
hash256(dkek, sizeof(dkek), kenc); hash256(dkek, sizeof(dkek), kenc);
mbedtls_platform_zeroize(dkek, sizeof(dkek)); mbedtls_platform_zeroize(dkek, sizeof(dkek));
return PICOKEY_OK; return PICOKEYS_OK;
} }
int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes static int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes
uint8_t dkek[DKEK_KEY_SIZE + 4]; uint8_t dkek[DKEK_KEY_SIZE + 4];
memset(kmac, 0, 32); memset(kmac, 0, 32);
int r = load_dkek(id, dkek); int r = load_dkek(id, dkek);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4); memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4);
hash256(dkek, DKEK_KEY_SIZE + 4, kmac); hash256(dkek, DKEK_KEY_SIZE + 4, kmac);
mbedtls_platform_zeroize(dkek, sizeof(dkek)); mbedtls_platform_zeroize(dkek, sizeof(dkek));
return PICOKEY_OK; return PICOKEYS_OK;
} }
int mkek_encrypt(uint8_t *data, uint16_t len) { int mkek_encrypt(uint8_t *data, uint16_t len) {
int r; int r;
uint8_t mkek[MKEK_SIZE + 4]; uint8_t mkek[MKEK_SIZE];
if ((r = load_mkek(mkek)) != PICOKEY_OK) { if ((r = load_mkek(mkek)) != PICOKEYS_OK) {
return r; return r;
} }
r = aes_encrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len); r = aes_encrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
@@ -256,8 +262,8 @@ int mkek_encrypt(uint8_t *data, uint16_t len) {
int mkek_decrypt(uint8_t *data, uint16_t len) { int mkek_decrypt(uint8_t *data, uint16_t len) {
int r; int r;
uint8_t mkek[MKEK_SIZE + 4]; uint8_t mkek[MKEK_SIZE];
if ((r = load_mkek(mkek)) != PICOKEY_OK) { if ((r = load_mkek(mkek)) != PICOKEYS_OK) {
return r; return r;
} }
r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len); r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len);
@@ -266,8 +272,8 @@ int mkek_decrypt(uint8_t *data, uint16_t len) {
} }
int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint16_t *out_len, const uint8_t *allowed, uint16_t allowed_len) { int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint16_t *out_len, const uint8_t *allowed, uint16_t allowed_len) {
if (!(key_type & PICO_KEYS_KEY_RSA) && !(key_type & PICO_KEYS_KEY_EC) && !(key_type & PICO_KEYS_KEY_AES)) { if (!(key_type & PICOKEYS_KEY_RSA) && !(key_type & PICOKEYS_KEY_EC) && !(key_type & PICOKEYS_KEY_AES)) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding) uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding)
@@ -279,104 +285,104 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
uint8_t kenc[32]; uint8_t kenc[32];
memset(kenc, 0, sizeof(kenc)); memset(kenc, 0, sizeof(kenc));
r = dkek_kenc(id, kenc); r = dkek_kenc(id, kenc);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
uint8_t kcv[8]; uint8_t kcv[8];
memset(kcv, 0, sizeof(kcv)); memset(kcv, 0, sizeof(kcv));
r = dkek_kcv(id, kcv); r = dkek_kcv(id, kcv);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
uint8_t kmac[32]; uint8_t kmac[32];
memset(kmac, 0, sizeof(kmac)); memset(kmac, 0, sizeof(kmac));
r = dkek_kmac(id, kmac); r = dkek_kmac(id, kmac);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
if (key_type & PICO_KEYS_KEY_AES) { if (key_type & PICOKEYS_KEY_AES) {
if (key_type & PICO_KEYS_KEY_AES_128) { if (key_type & PICOKEYS_KEY_AES_128) {
kb_len = 16; kb_len = 16;
} }
else if (key_type & PICO_KEYS_KEY_AES_192) { else if (key_type & PICOKEYS_KEY_AES_192) {
kb_len = 24; kb_len = 24;
} }
else if (key_type & PICO_KEYS_KEY_AES_256) { else if (key_type & PICOKEYS_KEY_AES_256) {
kb_len = 32; kb_len = 32;
} }
else if (key_type & PICO_KEYS_KEY_AES_512) { else if (key_type & PICOKEYS_KEY_AES_512) {
kb_len = 64; kb_len = 64;
} }
if (kb_len != 16 && kb_len != 24 && kb_len != 32 && kb_len != 64) { if (kb_len != 16 && kb_len != 24 && kb_len != 32 && kb_len != 64) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (*out_len < 8 + 1 + 10 + 6 + (2 + 64 + 14) + 16) { // 14 bytes padding if (*out_len < 8 + 1 + 10 + 6 + (2 + 64 + 14) + 16) { // 14 bytes padding
return PICOKEY_WRONG_LENGTH; return PICOKEYS_WRONG_LENGTH;
} }
put_uint16_t_be(kb_len, kb + 8); put_uint16_be(kb_len, kb + 8);
memcpy(kb + 10, key_ctx, kb_len); memcpy(kb + 10, key_ctx, kb_len);
kb_len += 2; kb_len += 2;
algo = (uint8_t *) "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8) algo = (uint8_t *) "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01"; //2.16.840.1.101.3.4.1 (2+8)
algo_len = 10; algo_len = 10;
} }
else if (key_type & PICO_KEYS_KEY_RSA) { else if (key_type & PICOKEYS_KEY_RSA) {
if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13) + 16) { //13 bytes pading if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13) + 16) { //13 bytes pading
return PICOKEY_WRONG_LENGTH; return PICOKEYS_WRONG_LENGTH;
} }
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx; mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
kb_len = 0; kb_len = 0;
kb_len += put_uint16_t_be((uint16_t)mbedtls_rsa_get_len(rsa) * 8, kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_rsa_get_len(rsa) * 8, kb + 8 + kb_len);
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&rsa->D), kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&rsa->D), kb + 8 + kb_len);
mbedtls_mpi_write_binary(&rsa->D, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->D)); mbedtls_mpi_write_binary(&rsa->D, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->D));
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->D); kb_len += (uint16_t)mbedtls_mpi_size(&rsa->D);
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&rsa->N), kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&rsa->N), kb + 8 + kb_len);
mbedtls_mpi_write_binary(&rsa->N, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->N)); mbedtls_mpi_write_binary(&rsa->N, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->N));
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->N); kb_len += (uint16_t)mbedtls_mpi_size(&rsa->N);
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&rsa->E), kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&rsa->E), kb + 8 + kb_len);
mbedtls_mpi_write_binary(&rsa->E, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->E)); mbedtls_mpi_write_binary(&rsa->E, kb + 8 + kb_len, mbedtls_mpi_size(&rsa->E));
kb_len += (uint16_t)mbedtls_mpi_size(&rsa->E); kb_len += (uint16_t)mbedtls_mpi_size(&rsa->E);
algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02"; algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02";
algo_len = 12; algo_len = 12;
} }
else if (key_type & PICO_KEYS_KEY_EC) { else if (key_type & PICOKEYS_KEY_EC) {
if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 8 + 9 * 66 + 2 + 4) + 16) { //4 bytes pading if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 8 + 9 * 66 + 2 + 4) + 16) { //4 bytes pading
return PICOKEY_WRONG_LENGTH; return PICOKEYS_WRONG_LENGTH;
} }
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx; mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
kb_len = 0; kb_len = 0;
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P) * 8, kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P) * 8, kb + 8 + kb_len);
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.A), kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.A), kb + 8 + kb_len);
mbedtls_mpi_write_binary(&ecdsa->grp.A, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.A)); mbedtls_mpi_write_binary(&ecdsa->grp.A, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.A));
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.A); kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.A);
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.B), kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.B), kb + 8 + kb_len);
mbedtls_mpi_write_binary(&ecdsa->grp.B, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.B)); mbedtls_mpi_write_binary(&ecdsa->grp.B, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.B));
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.B); kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.B);
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P), kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.P), kb + 8 + kb_len);
mbedtls_mpi_write_binary(&ecdsa->grp.P, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.P)); mbedtls_mpi_write_binary(&ecdsa->grp.P, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.P));
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.P); kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.P);
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.N), kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->grp.N), kb + 8 + kb_len);
mbedtls_mpi_write_binary(&ecdsa->grp.N, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.N)); mbedtls_mpi_write_binary(&ecdsa->grp.N, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->grp.N));
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.N); kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.N);
size_t olen = 0; size_t olen = 0;
mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, kb + 8 + kb_len + 2, sizeof(kb) - 8 - kb_len - 2); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, kb + 8 + kb_len + 2, sizeof(kb) - 8 - kb_len - 2);
kb_len += put_uint16_t_be((uint16_t)olen, kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)olen, kb + 8 + kb_len);
kb_len += (uint16_t)olen; kb_len += (uint16_t)olen;
kb_len += put_uint16_t_be((uint16_t)mbedtls_mpi_size(&ecdsa->d), kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)mbedtls_mpi_size(&ecdsa->d), kb + 8 + kb_len);
mbedtls_mpi_write_binary(&ecdsa->d, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->d)); mbedtls_mpi_write_binary(&ecdsa->d, kb + 8 + kb_len, mbedtls_mpi_size(&ecdsa->d));
kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->d); kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->d);
mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, kb + 8 + kb_len + 2, sizeof(kb) - 8 - kb_len - 2); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, kb + 8 + kb_len + 2, sizeof(kb) - 8 - kb_len - 2);
kb_len += put_uint16_t_be((uint16_t)olen, kb + 8 + kb_len); kb_len += put_uint16_be((uint16_t)olen, kb + 8 + kb_len);
kb_len += (uint16_t)olen; kb_len += (uint16_t)olen;
algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03"; algo = (uint8_t *) "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03";
@@ -388,13 +394,13 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
memcpy(out + *out_len, kcv, 8); memcpy(out + *out_len, kcv, 8);
*out_len += 8; *out_len += 8;
if (key_type & PICO_KEYS_KEY_AES) { if (key_type & PICOKEYS_KEY_AES) {
out[*out_len] = 15; out[*out_len] = 15;
} }
else if (key_type & PICO_KEYS_KEY_RSA) { else if (key_type & PICOKEYS_KEY_RSA) {
out[*out_len] = 5; out[*out_len] = 5;
} }
else if (key_type & PICO_KEYS_KEY_EC) { else if (key_type & PICOKEYS_KEY_EC) {
out[*out_len] = 12; out[*out_len] = 12;
} }
*out_len += 1; *out_len += 1;
@@ -408,7 +414,7 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
} }
if (allowed && allowed_len > 0) { if (allowed && allowed_len > 0) {
*out_len += put_uint16_t_be(allowed_len, out + *out_len); *out_len += put_uint16_be(allowed_len, out + *out_len);
memcpy(out + *out_len, allowed, allowed_len); memcpy(out + *out_len, allowed, allowed_len);
*out_len += allowed_len; *out_len += allowed_len;
} }
@@ -428,8 +434,8 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
if (kb_len < kb_len_pad) { if (kb_len < kb_len_pad) {
kb[kb_len] = 0x80; kb[kb_len] = 0x80;
} }
r = aes_encrypt(kenc, NULL, 256, PICO_KEYS_AES_MODE_CBC, kb, kb_len_pad); r = aes_encrypt(kenc, NULL, 256, PICOKEYS_AES_MODE_CBC, kb, kb_len_pad);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
@@ -442,18 +448,18 @@ int dkek_encode_key(uint8_t id, void *key_ctx, int key_type, uint8_t *out, uint1
if (r != 0) { if (r != 0) {
return r; return r;
} }
return PICOKEY_OK; return PICOKEYS_OK;
} }
int dkek_type_key(const uint8_t *in) { int dkek_type_key(const uint8_t *in) {
if (in[8] == 5 || in[8] == 6) { if (in[8] == 5 || in[8] == 6) {
return PICO_KEYS_KEY_RSA; return PICOKEYS_KEY_RSA;
} }
else if (in[8] == 12) { else if (in[8] == 12) {
return PICO_KEYS_KEY_EC; return PICOKEYS_KEY_EC;
} }
else if (in[8] == 15) { else if (in[8] == 15) {
return PICO_KEYS_KEY_AES; return PICOKEYS_KEY_AES;
} }
return 0x0; return 0x0;
} }
@@ -463,88 +469,88 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
int r = 0; int r = 0;
memset(kcv, 0, sizeof(kcv)); memset(kcv, 0, sizeof(kcv));
r = dkek_kcv(id, kcv); r = dkek_kcv(id, kcv);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
uint8_t kmac[32]; uint8_t kmac[32];
memset(kmac, 0, sizeof(kmac)); memset(kmac, 0, sizeof(kmac));
r = dkek_kmac(id, kmac); r = dkek_kmac(id, kmac);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
uint8_t kenc[32]; uint8_t kenc[32];
memset(kenc, 0, sizeof(kenc)); memset(kenc, 0, sizeof(kenc));
r = dkek_kenc(id, kenc); r = dkek_kenc(id, kenc);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
if (memcmp(kcv, in, 8) != 0) { if (memcmp(kcv, in, 8) != 0) {
return PICOKEY_WRONG_DKEK; return PICOKEYS_WRONG_DKEK;
} }
uint8_t signature[16]; uint8_t signature[16];
r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len - 16, signature); r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, in, in_len - 16, signature);
if (r != 0) { if (r != 0) {
return PICOKEY_WRONG_SIGNATURE; return PICOKEYS_WRONG_SIGNATURE;
} }
if (memcmp(signature, in + in_len - 16, 16) != 0) { if (memcmp(signature, in + in_len - 16, 16) != 0) {
return PICOKEY_WRONG_SIGNATURE; return PICOKEYS_WRONG_SIGNATURE;
} }
int key_type = in[8]; int key_type = in[8];
if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15) { if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if ((key_type == 5 || key_type == 6) && if ((key_type == 5 || key_type == 6) &&
memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0) { memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (key_type == 12 && if (key_type == 12 &&
memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) { memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (key_type == 15 && memcmp(in + 9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) { if (key_type == 15 && memcmp(in + 9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
uint16_t ofs = 9; uint16_t ofs = 9;
//OID //OID
uint16_t len = get_uint16_t_be(in + ofs); uint16_t len = get_uint16_be(in + ofs);
ofs += len + 2; ofs += len + 2;
//Allowed algorithms //Allowed algorithms
len = get_uint16_t_be(in + ofs); len = get_uint16_be(in + ofs);
*allowed = (uint8_t *) (in + ofs + 2); *allowed = (uint8_t *) (in + ofs + 2);
*allowed_len = len; *allowed_len = len;
ofs += len + 2; ofs += len + 2;
//Access conditions //Access conditions
len = get_uint16_t_be(in + ofs); len = get_uint16_be(in + ofs);
ofs += len + 2; ofs += len + 2;
//Key OID //Key OID
len = get_uint16_t_be(in + ofs); len = get_uint16_be(in + ofs);
ofs += len + 2; ofs += len + 2;
if ((in_len - 16 - ofs) % 16 != 0) { if ((in_len - 16 - ofs) % 16 != 0) {
return PICOKEY_WRONG_PADDING; return PICOKEYS_WRONG_PADDING;
} }
uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding) uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding)
memset(kb, 0, sizeof(kb)); memset(kb, 0, sizeof(kb));
memcpy(kb, in + ofs, in_len - 16 - ofs); memcpy(kb, in + ofs, in_len - 16 - ofs);
r = aes_decrypt(kenc, NULL, 256, PICO_KEYS_AES_MODE_CBC, kb, in_len - 16 - ofs); r = aes_decrypt(kenc, NULL, 256, PICOKEYS_AES_MODE_CBC, kb, in_len - 16 - ofs);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
int key_size = get_uint16_t_be(kb + 8); int key_size = get_uint16_be(kb + 8);
if (key_size_out) { if (key_size_out) {
*key_size_out = key_size; *key_size_out = key_size;
} }
@@ -553,78 +559,78 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx; mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
mbedtls_rsa_init(rsa); mbedtls_rsa_init(rsa);
if (key_type == 5) { if (key_type == 5) {
len = get_uint16_t_be(kb + ofs); ofs += 2; len = get_uint16_be(kb + ofs); ofs += 2;
r = mbedtls_mpi_read_binary(&rsa->D, kb + ofs, len); ofs += len; r = mbedtls_mpi_read_binary(&rsa->D, kb + ofs, len); ofs += len;
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
len = get_uint16_t_be(kb + ofs); ofs += 2; len = get_uint16_be(kb + ofs); ofs += 2;
r = mbedtls_mpi_read_binary(&rsa->N, kb + ofs, len); ofs += len; r = mbedtls_mpi_read_binary(&rsa->N, kb + ofs, len); ofs += len;
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
} }
else if (key_type == 6) { else if (key_type == 6) {
//DP-1 //DP-1
len = get_uint16_t_be(kb + ofs); ofs += len + 2; len = get_uint16_be(kb + ofs); ofs += len + 2;
//DQ-1 //DQ-1
len = get_uint16_t_be(kb + ofs); ofs += len + 2; len = get_uint16_be(kb + ofs); ofs += len + 2;
len = get_uint16_t_be(kb + ofs); ofs += 2; len = get_uint16_be(kb + ofs); ofs += 2;
r = mbedtls_mpi_read_binary(&rsa->P, kb + ofs, len); ofs += len; r = mbedtls_mpi_read_binary(&rsa->P, kb + ofs, len); ofs += len;
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
//PQ //PQ
len = get_uint16_t_be(kb + ofs); ofs += len + 2; len = get_uint16_be(kb + ofs); ofs += len + 2;
len = get_uint16_t_be(kb + ofs); ofs += 2; len = get_uint16_be(kb + ofs); ofs += 2;
r = mbedtls_mpi_read_binary(&rsa->Q, kb + ofs, len); ofs += len; r = mbedtls_mpi_read_binary(&rsa->Q, kb + ofs, len); ofs += len;
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
//N //N
len = get_uint16_t_be(kb + ofs); ofs += len + 2; len = get_uint16_be(kb + ofs); ofs += len + 2;
} }
len = get_uint16_t_be(kb + ofs); ofs += 2; len = get_uint16_be(kb + ofs); ofs += 2;
r = mbedtls_mpi_read_binary(&rsa->E, kb + ofs, len); ofs += len; r = mbedtls_mpi_read_binary(&rsa->E, kb + ofs, len); ofs += len;
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (key_type == 5) { if (key_type == 5) {
r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E); r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
} }
else if (key_type == 6) { else if (key_type == 6) {
r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E); r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
} }
r = mbedtls_rsa_complete(rsa); r = mbedtls_rsa_complete(rsa);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
r = mbedtls_rsa_check_privkey(rsa); r = mbedtls_rsa_check_privkey(rsa);
if (r != 0) { if (r != 0) {
mbedtls_rsa_free(rsa); mbedtls_rsa_free(rsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
} }
else if (key_type == 12) { else if (key_type == 12) {
@@ -632,25 +638,25 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
mbedtls_ecdsa_init(ecdsa); mbedtls_ecdsa_init(ecdsa);
//A //A
len = get_uint16_t_be(kb + ofs); ofs += len + 2; len = get_uint16_be(kb + ofs); ofs += len + 2;
//B //B
len = get_uint16_t_be(kb + ofs); ofs += len + 2; len = get_uint16_be(kb + ofs); ofs += len + 2;
//P //P
len = get_uint16_t_be(kb + ofs); ofs += 2; len = get_uint16_be(kb + ofs); ofs += 2;
mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb + ofs, len); mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb + ofs, len);
if (ec_id == MBEDTLS_ECP_DP_NONE) { if (ec_id == MBEDTLS_ECP_DP_NONE) {
mbedtls_ecdsa_free(ecdsa); mbedtls_ecdsa_free(ecdsa);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
ofs += len; ofs += len;
//N //N
len = get_uint16_t_be(kb + ofs); ofs += len + 2; len = get_uint16_be(kb + ofs); ofs += len + 2;
//G //G
len = get_uint16_t_be(kb + ofs); len = get_uint16_be(kb + ofs);
#ifdef MBEDTLS_EDDSA_C #ifdef MBEDTLS_EDDSA_C
if (ec_id == MBEDTLS_ECP_DP_CURVE25519 && kb[ofs + 2] != 0x09) { if (ec_id == MBEDTLS_ECP_DP_CURVE25519 && kb[ofs + 2] != 0x09) {
ec_id = MBEDTLS_ECP_DP_ED25519; ec_id = MBEDTLS_ECP_DP_ED25519;
@@ -662,40 +668,32 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le
ofs += len + 2; ofs += len + 2;
//d //d
len = get_uint16_t_be(kb + ofs); ofs += 2; len = get_uint16_be(kb + ofs); ofs += 2;
r = mbedtls_ecp_read_key(ec_id, ecdsa, kb + ofs, len); r = mbedtls_ecp_read_key(ec_id, ecdsa, kb + ofs, len);
if (r != 0) { if (r != 0) {
mbedtls_ecdsa_free(ecdsa); mbedtls_ecdsa_free(ecdsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
ofs += len; ofs += len;
//Q //Q
len = get_uint16_t_be(kb + ofs); ofs += 2; len = get_uint16_be(kb + ofs); ofs += 2;
r = mbedtls_ecp_point_read_binary(&ecdsa->grp, &ecdsa->Q, kb + ofs, len); r = mbedtls_ecp_point_read_binary(&ecdsa->grp, &ecdsa->Q, kb + ofs, len);
if (r != 0) { if (r != 0) {
#ifdef MBEDTLS_EDDSA_C r = mbedtls_ecp_keypair_calc_public(ecdsa, random_fill_iterator, NULL);
if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_EDWARDS) {
r = mbedtls_ecp_point_edwards(&ecdsa->grp, &ecdsa->Q, &ecdsa->d, random_gen, NULL);
}
else
#endif
{
r = mbedtls_ecp_mul(&ecdsa->grp, &ecdsa->Q, &ecdsa->d, &ecdsa->grp.G, random_gen, NULL);
}
if (r != 0) { if (r != 0) {
mbedtls_ecdsa_free(ecdsa); mbedtls_ecdsa_free(ecdsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
} }
r = mbedtls_ecp_check_pub_priv(ecdsa, ecdsa, random_gen, NULL); r = mbedtls_ecp_check_pub_priv(ecdsa, ecdsa, random_fill_iterator, NULL);
if (r != 0) { if (r != 0) {
mbedtls_ecdsa_free(ecdsa); mbedtls_ecdsa_free(ecdsa);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
} }
else if (key_type == 15) { else if (key_type == 15) {
memcpy(key_ctx, kb + ofs, key_size); memcpy(key_ctx, kb + ofs, key_size);
} }
return PICOKEY_OK; return PICOKEYS_OK;
} }

View File

@@ -28,27 +28,15 @@ extern int load_mkek(uint8_t *);
extern int store_mkek(const uint8_t *); extern int store_mkek(const uint8_t *);
extern int save_dkek_key(uint8_t, const uint8_t *key); extern int save_dkek_key(uint8_t, const uint8_t *key);
extern int store_dkek_key(uint8_t, uint8_t *); extern int store_dkek_key(uint8_t, uint8_t *);
extern void init_mkek(); extern void init_mkek(void);
extern void release_mkek(uint8_t *); extern void release_mkek(uint8_t *);
extern int import_dkek_share(uint8_t, const uint8_t *share); extern int import_dkek_share(uint8_t, const uint8_t *share);
extern int dkek_kcv(uint8_t, uint8_t *kcv); extern int dkek_kcv(uint8_t, uint8_t *kcv);
extern int mkek_encrypt(uint8_t *data, uint16_t len); extern int mkek_encrypt(uint8_t *data, uint16_t len);
extern int mkek_decrypt(uint8_t *data, uint16_t len); extern int mkek_decrypt(uint8_t *data, uint16_t len);
extern int dkek_encode_key(uint8_t, extern int dkek_encode_key(uint8_t, void *key_ctx, int key_type, uint8_t *out, uint16_t *out_len, const uint8_t *, uint16_t);
void *key_ctx,
int key_type,
uint8_t *out,
uint16_t *out_len,
const uint8_t *,
uint16_t);
extern int dkek_type_key(const uint8_t *in); extern int dkek_type_key(const uint8_t *in);
extern int dkek_decode_key(uint8_t, extern int dkek_decode_key(uint8_t, void *key_ctx, const uint8_t *in, uint16_t in_len, int *key_size_out, uint8_t **, uint16_t *);
void *key_ctx,
const uint8_t *in,
uint16_t in_len,
int *key_size_out,
uint8_t **,
uint16_t *);
#define MAX_DKEK_ENCODE_KEY_BUFFER (8 + 1 + 12 + 6 + (8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13) + 16) #define MAX_DKEK_ENCODE_KEY_BUFFER (8 + 1 + 12 + 6 + (8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13) + 16)
@@ -57,12 +45,15 @@ extern int dkek_decode_key(uint8_t,
#define MKEK_IV_SIZE (IV_SIZE) #define MKEK_IV_SIZE (IV_SIZE)
#define MKEK_KEY_SIZE (32) #define MKEK_KEY_SIZE (32)
#define MKEK_KEY_CS_SIZE (4) #define MKEK_KEY_CS_SIZE (4)
#define MKEK_SIZE (MKEK_IV_SIZE + MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE) #define MKEK_SIZE_OLD (MKEK_IV_SIZE + MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE)
#define MKEK_IV(p) (p) #define MKEK_IV(p) (p)
#define MKEK_KEY(p) (MKEK_IV(p) + MKEK_IV_SIZE) #define MKEK_KEY(p) (MKEK_IV(p) + MKEK_IV_SIZE)
#define MKEK_CHECKSUM(p) (MKEK_KEY(p) + MKEK_KEY_SIZE) #define MKEK_CHECKSUM(p) (MKEK_KEY(p) + MKEK_KEY_SIZE)
#define DKEK_KEY_SIZE (32) #define DKEK_KEY_SIZE (32)
#define MKEK_SIZE (MKEK_IV_SIZE + MKEK_KEY_SIZE)
#define MKEK_FILE_SIZE (1 + (12 + MKEK_SIZE + 16))
extern uint8_t mkek_mask[MKEK_KEY_SIZE]; extern uint8_t mkek_mask[MKEK_KEY_SIZE];
extern bool has_mkek_mask; extern bool has_mkek_mask;

View File

@@ -15,6 +15,9 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
#include <stdio.h>
#include "picokeys.h"
#include "serial.h"
#include "sc_hsm.h" #include "sc_hsm.h"
#include "files.h" #include "files.h"
#include "version.h" #include "version.h"
@@ -23,7 +26,6 @@
#include "eac.h" #include "eac.h"
#include "cvc.h" #include "cvc.h"
#include "asn1.h" #include "asn1.h"
#include "pico_keys.h"
#include "usb.h" #include "usb.h"
#include "random.h" #include "random.h"
#include "version.h" #include "version.h"
@@ -48,59 +50,33 @@ uint8_t PICO_PRODUCT = 1;
uint8_t PICO_VERSION_MAJOR = HSM_VERSION_MAJOR; uint8_t PICO_VERSION_MAJOR = HSM_VERSION_MAJOR;
uint8_t PICO_VERSION_MINOR = HSM_VERSION_MINOR; uint8_t PICO_VERSION_MINOR = HSM_VERSION_MINOR;
static int sc_hsm_process_apdu(); static int sc_hsm_process_apdu(void);
static void init_sc_hsm(); static void init_sc_hsm(void);
static int sc_hsm_unload(); static int sc_hsm_unload(void);
extern int cmd_select();
extern void select_file(file_t *pe);
extern int cmd_list_keys();
extern int cmd_read_binary();
extern int cmd_verify();
extern int cmd_reset_retry();
extern int cmd_challenge();
extern int cmd_external_authenticate();
extern int cmd_mse();
extern int cmd_initialize();
extern int cmd_key_domain();
extern int cmd_key_wrap();
extern int cmd_keypair_gen();
extern int cmd_update_ef();
extern int cmd_delete_file();
extern int cmd_change_pin();
extern int cmd_key_gen();
extern int cmd_signature();
extern int cmd_key_unwrap();
extern int cmd_decrypt_asym();
extern int cmd_cipher_sym();
extern int cmd_derive_asym();
extern int cmd_extras();
extern int cmd_general_authenticate();
extern int cmd_session_pin();
extern int cmd_puk_auth();
extern int cmd_pso();
extern int cmd_bip_slip();
extern const uint8_t *ccid_atr; extern const uint8_t *ccid_atr;
int sc_hsm_select_aid(app_t *a, uint8_t force) { static int sc_hsm_select_aid(app_t *a, uint8_t force) {
(void) force; (void) force;
a->process_apdu = sc_hsm_process_apdu; a->process_apdu = sc_hsm_process_apdu;
a->unload = sc_hsm_unload; a->unload = sc_hsm_unload;
init_sc_hsm(); init_sc_hsm();
return PICOKEY_OK; return PICOKEYS_OK;
}
int set_atr(void) {
ccid_atr = atr_sc_hsm;
return 0;
} }
INITIALIZER( sc_hsm_ctor ) { INITIALIZER( sc_hsm_ctor ) {
printf("INITIALIZER\n"); printf("INITIALIZER\n");
ccid_atr = atr_sc_hsm;
register_app(sc_hsm_select_aid, sc_hsm_aid); register_app(sc_hsm_select_aid, sc_hsm_aid);
} }
void scan_files() { static void scan_files(void) {
file_pin1 = search_file(EF_PIN1); file_pin1 = file_search(EF_PIN1);
if (file_pin1) { if (file_pin1) {
if (!file_pin1->data) { if (!file_pin1->data) {
printf("PIN1 is empty. Initializing with default password\n"); printf("PIN1 is empty. Initializing with default password\n");
@@ -111,7 +87,7 @@ void scan_files() {
else { else {
printf("FATAL ERROR: PIN1 not found in memory!\n"); printf("FATAL ERROR: PIN1 not found in memory!\n");
} }
file_sopin = search_file(EF_SOPIN); file_sopin = file_search(EF_SOPIN);
if (file_sopin) { if (file_sopin) {
if (!file_sopin->data) { if (!file_sopin->data) {
printf("SOPIN is empty. Initializing with default password\n"); printf("SOPIN is empty. Initializing with default password\n");
@@ -122,7 +98,7 @@ void scan_files() {
else { else {
printf("FATAL ERROR: SOPIN not found in memory!\n"); printf("FATAL ERROR: SOPIN not found in memory!\n");
} }
file_retries_pin1 = search_file(EF_PIN1_RETRIES); file_retries_pin1 = file_search(EF_PIN1_RETRIES);
if (file_retries_pin1) { if (file_retries_pin1) {
if (!file_retries_pin1->data) { if (!file_retries_pin1->data) {
printf("Retries PIN1 is empty. Initializing with default retriesr\n"); printf("Retries PIN1 is empty. Initializing with default retriesr\n");
@@ -133,7 +109,7 @@ void scan_files() {
else { else {
printf("FATAL ERROR: Retries PIN1 not found in memory!\n"); printf("FATAL ERROR: Retries PIN1 not found in memory!\n");
} }
file_retries_sopin = search_file(EF_SOPIN_RETRIES); file_retries_sopin = file_search(EF_SOPIN_RETRIES);
if (file_retries_sopin) { if (file_retries_sopin) {
if (!file_retries_sopin->data) { if (!file_retries_sopin->data) {
printf("Retries SOPIN is empty. Initializing with default retries\n"); printf("Retries SOPIN is empty. Initializing with default retries\n");
@@ -146,7 +122,7 @@ void scan_files() {
} }
file_t *tf = NULL; file_t *tf = NULL;
tf = search_file(EF_PIN1_MAX_RETRIES); tf = file_search(EF_PIN1_MAX_RETRIES);
if (tf) { if (tf) {
if (!tf->data) { if (!tf->data) {
printf("Max retries PIN1 is empty. Initializing with default max retriesr\n"); printf("Max retries PIN1 is empty. Initializing with default max retriesr\n");
@@ -157,7 +133,7 @@ void scan_files() {
else { else {
printf("FATAL ERROR: Max Retries PIN1 not found in memory!\n"); printf("FATAL ERROR: Max Retries PIN1 not found in memory!\n");
} }
tf = search_file(EF_SOPIN_MAX_RETRIES); tf = file_search(EF_SOPIN_MAX_RETRIES);
if (tf) { if (tf) {
if (!tf->data) { if (!tf->data) {
printf("Max Retries SOPIN is empty. Initializing with default max retries\n"); printf("Max Retries SOPIN is empty. Initializing with default max retries\n");
@@ -168,11 +144,11 @@ void scan_files() {
else { else {
printf("FATAL ERROR: Retries SOPIN not found in memory!\n"); printf("FATAL ERROR: Retries SOPIN not found in memory!\n");
} }
low_flash_available(); flash_commit();
} }
void scan_all() { void scan_all(void) {
scan_flash(); file_scan_flash();
scan_files(); scan_files();
} }
@@ -183,10 +159,10 @@ uint8_t puk_status[MAX_PUK];
int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy) { int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy) {
if (data == NULL || data_len == 0) { if (data == NULL || data_len == 0) {
return PICOKEY_ERR_NULL_PARAM; return PICOKEYS_ERR_NULL_PARAM;
} }
if (puk_store_entries == MAX_PUK_STORE_ENTRIES) { if (puk_store_entries == MAX_PUK_STORE_ENTRIES) {
return PICOKEY_ERR_MEMORY_FATAL; return PICOKEYS_ERR_MEMORY_FATAL;
} }
puk_store[puk_store_entries].copied = copy; puk_store[puk_store_entries].copied = copy;
@@ -210,20 +186,20 @@ int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy) {
&puk_store[puk_store_entries].puk_len); &puk_store[puk_store_entries].puk_len);
puk_store_entries++; puk_store_entries++;
return PICOKEY_OK; return PICOKEYS_OK;
} }
int puk_store_select_chr(const uint8_t *chr) { int puk_store_select_chr(const uint8_t *chr) {
for (int i = 0; i < puk_store_entries; i++) { for (int i = 0; i < puk_store_entries; i++) {
if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) { if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) {
current_puk = &puk_store[i]; current_puk = &puk_store[i];
return PICOKEY_OK; return PICOKEYS_OK;
} }
} }
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
void reset_puk_store() { void reset_puk_store(void) {
if (puk_store_entries > 0) { /* From previous session */ if (puk_store_entries > 0) { /* From previous session */
for (int i = 0; i < puk_store_entries; i++) { for (int i = 0; i < puk_store_entries; i++) {
if (puk_store[i].copied == true) { if (puk_store[i].copied == true) {
@@ -233,7 +209,7 @@ void reset_puk_store() {
} }
memset(puk_store, 0, sizeof(puk_store)); memset(puk_store, 0, sizeof(puk_store));
puk_store_entries = 0; puk_store_entries = 0;
file_t *fterm = search_file(EF_TERMCA); file_t *fterm = file_search(EF_TERMCA);
if (fterm) { if (fterm) {
uint8_t *p = NULL, *fterm_data = file_get_data(fterm), *pq = fterm_data; uint8_t *p = NULL, *fterm_data = file_get_data(fterm), *pq = fterm_data;
uint16_t fterm_data_len = file_get_size(fterm); uint16_t fterm_data_len = file_get_size(fterm);
@@ -245,7 +221,7 @@ void reset_puk_store() {
} }
} }
for (int i = 0; i < 0xfe; i++) { for (int i = 0; i < 0xfe; i++) {
file_t *ef = search_file((CA_CERTIFICATE_PREFIX << 8) | (uint8_t)i); file_t *ef = file_search((CA_CERTIFICATE_PREFIX << 8) | (uint8_t)i);
if (ef && file_get_size(ef) > 0) { if (ef && file_get_size(ef) > 0) {
add_cert_puk_store(file_get_data(ef), file_get_size(ef), false); add_cert_puk_store(file_get_data(ef), file_get_size(ef), false);
} }
@@ -254,7 +230,7 @@ void reset_puk_store() {
memset(puk_status, 0, sizeof(puk_status)); memset(puk_status, 0, sizeof(puk_status));
} }
void init_sc_hsm() { void init_sc_hsm(void) {
scan_all(); scan_all();
has_session_pin = has_session_sopin = false; has_session_pin = has_session_sopin = false;
isUserAuthenticated = false; isUserAuthenticated = false;
@@ -262,22 +238,21 @@ void init_sc_hsm() {
reset_puk_store(); reset_puk_store();
} }
int sc_hsm_unload() { int sc_hsm_unload(void) {
has_session_pin = has_session_sopin = false; has_session_pin = has_session_sopin = false;
isUserAuthenticated = false; isUserAuthenticated = false;
sm_session_pin_len = 0; return PICOKEYS_OK;
return PICOKEY_OK;
} }
uint16_t get_device_options() { uint16_t get_device_options(void) {
file_t *ef = search_file(EF_DEVOPS); file_t *ef = file_search(EF_DEVOPS);
if (file_has_data(ef)) { if (file_has_data(ef)) {
return get_uint16_t_be(file_get_data(ef)); return get_uint16_be(file_get_data(ef));
} }
return 0x0; return 0x0;
} }
bool wait_button_pressed() { bool wait_button_pressed(void) {
uint32_t val = EV_PRESS_BUTTON; uint32_t val = EV_PRESS_BUTTON;
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
uint16_t opts = get_device_options(); uint16_t opts = get_device_options();
@@ -294,11 +269,11 @@ bool wait_button_pressed() {
int parse_token_info(const file_t *f, int mode) { int parse_token_info(const file_t *f, int mode) {
(void)f; (void)f;
#ifdef __FOR_CI #ifdef __FOR_CI
char *label = "SmartCard-HSM"; const char *label = "SmartCard-HSM";
#else #else
char *label = "Pico-HSM"; const char *label = "Pico-HSM";
#endif #endif
char *manu = "Pol Henarejos"; const char *manu = "Pol Henarejos";
if (mode == 1) { if (mode == 1) {
uint8_t *p = res_APDU; uint8_t *p = res_APDU;
*p++ = 0x30; *p++ = 0x30;
@@ -321,9 +296,9 @@ int parse_token_info(const file_t *f, int mode) {
int parse_ef_dir(const file_t *f, int mode) { int parse_ef_dir(const file_t *f, int mode) {
(void)f; (void)f;
#ifdef __FOR_CI #ifdef __FOR_CI
char *label = "SmartCard-HSM"; const char *label = "SmartCard-HSM";
#else #else
char *label = "Pico-HSM"; const char *label = "Pico-HSM";
#endif #endif
if (mode == 1) { if (mode == 1) {
uint8_t *p = res_APDU; uint8_t *p = res_APDU;
@@ -339,49 +314,49 @@ int parse_ef_dir(const file_t *f, int mode) {
int pin_reset_retries(const file_t *pin, bool force) { int pin_reset_retries(const file_t *pin, bool force) {
if (!pin) { if (!pin) {
return PICOKEY_ERR_NULL_PARAM; return PICOKEYS_ERR_NULL_PARAM;
} }
const file_t *max = search_file(pin->fid + 1); const file_t *max = file_search(pin->fid + 1);
const file_t *act = search_file(pin->fid + 2); const file_t *act = file_search(pin->fid + 2);
if (!max || !act) { if (!max || !act) {
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
uint8_t retries = file_read_uint8(act); uint8_t retries = file_read_uint8(act);
if (retries == 0 && force == false) { // blocked if (retries == 0 && force == false) { // blocked
return PICOKEY_ERR_BLOCKED; return PICOKEYS_ERR_BLOCKED;
} }
retries = file_read_uint8(max); retries = file_read_uint8(max);
int r = file_put_data((file_t *) act, &retries, sizeof(retries)); int r = file_put_data((file_t *) act, &retries, sizeof(retries));
low_flash_available(); flash_commit();
return r; return r;
} }
int pin_wrong_retry(const file_t *pin) { int pin_wrong_retry(const file_t *pin) {
if (!pin) { if (!pin) {
return PICOKEY_ERR_NULL_PARAM; return PICOKEYS_ERR_NULL_PARAM;
} }
const file_t *act = search_file(pin->fid + 2); const file_t *act = file_search(pin->fid + 2);
if (!act) { if (!act) {
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEYS_ERR_FILE_NOT_FOUND;
} }
uint8_t retries = file_read_uint8(act); uint8_t retries = file_read_uint8(act);
if (retries > 0) { if (retries > 0) {
retries -= 1; retries -= 1;
int r = file_put_data((file_t *) act, &retries, sizeof(retries)); int r = file_put_data((file_t *) act, &retries, sizeof(retries));
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
low_flash_available(); flash_commit();
if (retries == 0) { if (retries == 0) {
return PICOKEY_ERR_BLOCKED; return PICOKEYS_ERR_BLOCKED;
} }
return retries; return retries;
} }
return PICOKEY_ERR_BLOCKED; return PICOKEYS_ERR_BLOCKED;
} }
bool pka_enabled() { bool pka_enabled(void) {
file_t *ef_puk = search_file(EF_PUKAUT); file_t *ef_puk = file_search(EF_PUKAUT);
return file_has_data(ef_puk) && file_read_uint8(ef_puk) > 0; return file_has_data(ef_puk) && file_read_uint8(ef_puk) > 0;
} }
@@ -393,45 +368,79 @@ uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len) {
isUserAuthenticated = false; isUserAuthenticated = false;
} }
has_session_pin = has_session_sopin = false; has_session_pin = has_session_sopin = false;
if (is_secured_apdu() && sm_session_pin_len > 0 && pin == file_pin1) { uint8_t dhash[32], off = 2;
if (len == sm_session_pin_len && memcmp(data, sm_session_pin, len) != 0) { if (sizeof(dhash) == file_get_size(pin) - 1) { // Old style
int retries; off = 1;
if ((retries = pin_wrong_retry(pin)) < PICOKEY_OK) { double_hash_pin(data, len, dhash);
return SW_PIN_BLOCKED(); }
} else if (sizeof(dhash) == file_get_size(pin) - 2) {
return set_res_sw(0x63, 0xc0 | (uint8_t)retries); pin_derive_verifier(data, len, dhash);
}
} }
else { else {
uint8_t dhash[32]; return SW_WRONG_DATA();
double_hash_pin(data, len, dhash); }
if (sizeof(dhash) != file_get_size(pin) - 1) { // 1 byte for pin len if (memcmp(file_get_data(pin) + off, dhash, sizeof(dhash)) != 0) {
return SW_CONDITIONS_NOT_SATISFIED(); int retries;
} if ((retries = pin_wrong_retry(pin)) < PICOKEYS_OK) {
if (memcmp(file_get_data(pin) + 1, dhash, sizeof(dhash)) != 0) { return SW_PIN_BLOCKED();
int retries;
if ((retries = pin_wrong_retry(pin)) < PICOKEY_OK) {
return SW_PIN_BLOCKED();
}
return set_res_sw(0x63, 0xc0 | (uint8_t)retries);
} }
return set_res_sw(0x63, 0xc0 | (uint8_t)retries);
} }
int r = pin_reset_retries(pin, false); int r = pin_reset_retries(pin, false);
if (r == PICOKEY_ERR_BLOCKED) { if (r == PICOKEYS_ERR_BLOCKED) {
return SW_PIN_BLOCKED(); return SW_PIN_BLOCKED();
} }
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_MEMORY_FAILURE(); return SW_MEMORY_FAILURE();
} }
if (off == 1) { // Upgrade PIN format
if (r != PICOKEYS_OK) {
return SW_MEMORY_FAILURE();
}
if (pin == file_pin1) {
hash_multi(data, len, session_pin);
has_session_pin = true;
}
else if (pin == file_sopin) {
hash_multi(data, len, session_sopin);
has_session_sopin = true;
}
uint8_t mkek[MKEK_SIZE_OLD]; // Old MKEK size, as it is encrypted with old PIN format
r = load_mkek(mkek); //loads the MKEK with old format
if (r != PICOKEYS_OK) {
return SW_MEMORY_FAILURE();
}
if (pin == file_pin1) {
pin_derive_session(data, len, session_pin);
}
else if (pin == file_sopin) {
pin_derive_session(data, len, session_sopin);
}
r = store_mkek(mkek); //stores the MKEK with new format
mbedtls_platform_zeroize(mkek, sizeof(mkek));
if (r != PICOKEYS_OK) {
return SW_MEMORY_FAILURE();
}
uint8_t pin_data[34];
pin_data[0] = len;
pin_data[1] = 1; // new format indicator
pin_derive_verifier(data, len, pin_data + 2);
r = file_put_data((file_t *) pin, pin_data, sizeof(pin_data));
if (r != PICOKEYS_OK) {
return SW_MEMORY_FAILURE();
}
flash_commit();
}
if (pka_enabled() == false) { if (pka_enabled() == false) {
isUserAuthenticated = true; isUserAuthenticated = true;
} }
if (pin == file_pin1) { if (pin == file_pin1) {
hash_multi(data, len, session_pin); pin_derive_session(data, len, session_pin);
has_session_pin = true; has_session_pin = true;
} }
else if (pin == file_sopin) { else if (pin == file_sopin) {
hash_multi(data, len, session_sopin); pin_derive_session(data, len, session_sopin);
has_session_sopin = true; has_session_sopin = true;
} }
if (pending_save_dkek != 0xff) { if (pending_save_dkek != 0xff) {
@@ -465,7 +474,7 @@ uint32_t get_key_counter(file_t *fkey) {
uint16_t tag_len = 0; uint16_t tag_len = 0;
const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len); const uint8_t *meta_tag = get_meta_tag(fkey, 0x90, &tag_len);
if (meta_tag) { if (meta_tag) {
return get_uint32_t_be(meta_tag); return get_uint32_be(meta_tag);
} }
return 0xffffffff; return 0xffffffff;
} }
@@ -501,15 +510,15 @@ uint32_t decrement_key_counter(file_t *fkey) {
asn1_ctx_init(meta_data, meta_size, &ctxi); asn1_ctx_init(meta_data, meta_size, &ctxi);
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) { while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
if (tag == 0x90) { // ofset tag if (tag == 0x90) { // ofset tag
uint32_t val = get_uint32_t_be(tag_data); uint32_t val = get_uint32_be(tag_data);
val--; val--;
put_uint32_t_be(val, tag_data); put_uint32_be(val, tag_data);
int r = meta_add(fkey->fid, cmeta, (uint16_t)meta_size); int r = meta_add(fkey->fid, cmeta, (uint16_t)meta_size);
free(cmeta); free(cmeta);
if (r != 0) { if (r != 0) {
return 0xffffffff; return 0xffffffff;
} }
low_flash_available(); flash_commit();
return val; return val;
} }
} }
@@ -523,52 +532,52 @@ int store_keys(void *key_ctx, int type, uint8_t key_id) {
int r = 0; int r = 0;
uint16_t key_size = 0; uint16_t key_size = 0;
uint8_t kdata[4096 / 8]; // worst case uint8_t kdata[4096 / 8]; // worst case
if (type & PICO_KEYS_KEY_RSA) { if (type & PICOKEYS_KEY_RSA) {
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx; mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
key_size = (uint16_t)mbedtls_mpi_size(&rsa->P) + (uint16_t)mbedtls_mpi_size(&rsa->Q); key_size = (uint16_t)mbedtls_mpi_size(&rsa->P) + (uint16_t)mbedtls_mpi_size(&rsa->Q);
mbedtls_mpi_write_binary(&rsa->P, kdata, key_size / 2); mbedtls_mpi_write_binary(&rsa->P, kdata, key_size / 2);
mbedtls_mpi_write_binary(&rsa->Q, kdata + key_size / 2, key_size / 2); mbedtls_mpi_write_binary(&rsa->Q, kdata + key_size / 2, key_size / 2);
} }
else if (type & PICO_KEYS_KEY_EC) { else if (type & PICOKEYS_KEY_EC) {
mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx; mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx;
size_t olen = 0; size_t olen = 0;
kdata[0] = ecdsa->grp.id & 0xff; kdata[0] = ecdsa->grp.id & 0xff;
mbedtls_ecp_write_key_ext(ecdsa, &olen, kdata + 1, sizeof(kdata) - 1); mbedtls_ecp_write_key_ext(ecdsa, &olen, kdata + 1, sizeof(kdata) - 1);
key_size = olen + 1; key_size = olen + 1;
} }
else if (type & PICO_KEYS_KEY_AES) { else if (type & PICOKEYS_KEY_AES) {
if (type == PICO_KEYS_KEY_AES_128) { if (type == PICOKEYS_KEY_AES_128) {
key_size = 16; key_size = 16;
} }
else if (type == PICO_KEYS_KEY_AES_192) { else if (type == PICOKEYS_KEY_AES_192) {
key_size = 24; key_size = 24;
} }
else if (type == PICO_KEYS_KEY_AES_256) { else if (type == PICOKEYS_KEY_AES_256) {
key_size = 32; key_size = 32;
} }
else if (type == PICO_KEYS_KEY_AES_512) { else if (type == PICOKEYS_KEY_AES_512) {
key_size = 64; key_size = 64;
} }
memcpy(kdata, key_ctx, key_size); memcpy(kdata, key_ctx, key_size);
} }
else { else {
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); file_t *fpk = file_new((KEY_PREFIX << 8) | key_id);
if (!fpk) { if (!fpk) {
return PICOKEY_ERR_MEMORY_FATAL; return PICOKEYS_ERR_MEMORY_FATAL;
} }
r = mkek_encrypt(kdata, key_size); r = mkek_encrypt(kdata, key_size);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
r = file_put_data(fpk, kdata, (uint16_t)key_size); r = file_put_data(fpk, kdata, (uint16_t)key_size);
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return r; return r;
} }
char key_id_str[4] = {0}; char key_id_str[4] = {0};
sprintf(key_id_str, "%u", key_id); sprintf(key_id_str, "%u", key_id);
if (type & PICO_KEYS_KEY_EC) { if (type & PICOKEYS_KEY_EC) {
key_size--; key_size--;
} }
uint16_t prkd_len = asn1_build_prkd_generic(NULL, 0, (uint8_t *)key_id_str, (uint16_t)strlen(key_id_str), key_size * 8, type, kdata, sizeof(kdata)); uint16_t prkd_len = asn1_build_prkd_generic(NULL, 0, (uint8_t *)key_id_str, (uint16_t)strlen(key_id_str), key_size * 8, type, kdata, sizeof(kdata));
@@ -579,8 +588,8 @@ int store_keys(void *key_ctx, int type, uint8_t key_id) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
} }
low_flash_available(); flash_commit();
return PICOKEY_OK; return PICOKEYS_OK;
} }
int find_and_store_meta_key(uint8_t key_id) { int find_and_store_meta_key(uint8_t key_id) {
@@ -614,89 +623,81 @@ int find_and_store_meta_key(uint8_t key_id) {
int r = meta_add((KEY_PREFIX << 8) | key_id, meta, (uint16_t)meta_size); int r = meta_add((KEY_PREFIX << 8) | key_id, meta, (uint16_t)meta_size);
free(meta); free(meta);
if (r != 0) { if (r != 0) {
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
} }
return PICOKEY_OK; return PICOKEYS_OK;
} }
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) {
if (wait_button_pressed() == true) { // timeout if (wait_button_pressed() == true) { // timeout
return PICOKEY_VERIFICATION_FAILED; return PICOKEYS_VERIFICATION_FAILED;
} }
uint16_t key_size = file_get_size(fkey); uint16_t key_size = file_get_size(fkey);
uint8_t kdata[4096 / 8]; uint8_t kdata[4096 / 8];
memcpy(kdata, file_get_data(fkey), key_size); memcpy(kdata, file_get_data(fkey), key_size);
if (mkek_decrypt(kdata, key_size) != 0) { if (mkek_decrypt(kdata, key_size) != 0) {
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) { if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_rsa_free(ctx); mbedtls_rsa_free(ctx);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (mbedtls_mpi_read_binary(&ctx->Q, kdata + key_size / 2, key_size / 2) != 0) { if (mbedtls_mpi_read_binary(&ctx->Q, kdata + key_size / 2, key_size / 2) != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_rsa_free(ctx); mbedtls_rsa_free(ctx);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) { if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_rsa_free(ctx); mbedtls_rsa_free(ctx);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
if (mbedtls_rsa_import(ctx, NULL, &ctx->P, &ctx->Q, NULL, &ctx->E) != 0) { if (mbedtls_rsa_import(ctx, NULL, &ctx->P, &ctx->Q, NULL, &ctx->E) != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_rsa_free(ctx); mbedtls_rsa_free(ctx);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (mbedtls_rsa_complete(ctx) != 0) { if (mbedtls_rsa_complete(ctx) != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_rsa_free(ctx); mbedtls_rsa_free(ctx);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
if (mbedtls_rsa_check_privkey(ctx) != 0) { if (mbedtls_rsa_check_privkey(ctx) != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_rsa_free(ctx); mbedtls_rsa_free(ctx);
return PICOKEY_WRONG_DATA; return PICOKEYS_WRONG_DATA;
} }
return PICOKEY_OK; return PICOKEYS_OK;
} }
int load_private_key_ec(mbedtls_ecp_keypair *ctx, file_t *fkey) { int load_private_key_ec(mbedtls_ecp_keypair *ctx, file_t *fkey) {
if (wait_button_pressed() == true) { // timeout if (wait_button_pressed() == true) { // timeout
return PICOKEY_VERIFICATION_FAILED; return PICOKEYS_VERIFICATION_FAILED;
} }
uint16_t key_size = file_get_size(fkey); uint16_t key_size = file_get_size(fkey);
uint8_t kdata[67]; // Worst case, 521 bit + 1byte uint8_t kdata[67]; // Worst case, 521 bit + 1byte
memcpy(kdata, file_get_data(fkey), key_size); memcpy(kdata, file_get_data(fkey), key_size);
if (mkek_decrypt(kdata, key_size) != 0) { if (mkek_decrypt(kdata, key_size) != 0) {
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
mbedtls_ecp_group_id gid = kdata[0]; mbedtls_ecp_group_id gid = kdata[0];
int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1); int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1);
if (r != 0) { if (r != 0) {
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
mbedtls_ecp_keypair_free(ctx); mbedtls_ecp_keypair_free(ctx);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_platform_zeroize(kdata, sizeof(kdata));
#ifdef MBEDTLS_EDDSA_C r = mbedtls_ecp_keypair_calc_public(ctx, random_fill_iterator, NULL);
if (gid == MBEDTLS_ECP_DP_ED25519 || gid == MBEDTLS_ECP_DP_ED448) {
r = mbedtls_ecp_point_edwards(&ctx->grp, &ctx->Q, &ctx->d, random_gen, NULL);
}
else
#endif
{
r = mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL);
}
if (r != 0) { if (r != 0) {
mbedtls_ecp_keypair_free(ctx); mbedtls_ecp_keypair_free(ctx);
return PICOKEY_EXEC_ERROR; return PICOKEYS_EXEC_ERROR;
} }
return PICOKEY_OK; return PICOKEYS_OK;
} }
int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey) { int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey) {
return load_private_key_ec(ctx, fkey); return load_private_key_ec(ctx, fkey);
@@ -714,7 +715,6 @@ int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey) {
#define INS_KEY_DOMAIN 0x52 #define INS_KEY_DOMAIN 0x52
#define INS_PUK_AUTH 0x54 #define INS_PUK_AUTH 0x54
#define INS_LIST_KEYS 0x58 #define INS_LIST_KEYS 0x58
#define INS_SESSION_PIN 0x5A
#define INS_DECRYPT_ASYM 0x62 #define INS_DECRYPT_ASYM 0x62
#define INS_EXTRAS 0x64 #define INS_EXTRAS 0x64
#define INS_SIGNATURE 0x68 #define INS_SIGNATURE 0x68
@@ -755,7 +755,6 @@ static const cmd_t cmds[] = {
{ INS_EXTRAS, cmd_extras }, { INS_EXTRAS, cmd_extras },
{ INS_MSE, cmd_mse }, { INS_MSE, cmd_mse },
{ INS_GENERAL_AUTHENTICATE, cmd_general_authenticate }, { INS_GENERAL_AUTHENTICATE, cmd_general_authenticate },
{ INS_SESSION_PIN, cmd_session_pin },
{ INS_PUK_AUTH, cmd_puk_auth }, { INS_PUK_AUTH, cmd_puk_auth },
{ INS_PSO, cmd_pso }, { INS_PSO, cmd_pso },
{ INS_EXTERNAL_AUTHENTICATE, cmd_external_authenticate }, { INS_EXTERNAL_AUTHENTICATE, cmd_external_authenticate },
@@ -763,10 +762,10 @@ static const cmd_t cmds[] = {
{ 0x00, 0x0 } { 0x00, 0x0 }
}; };
int sc_hsm_process_apdu() { int sc_hsm_process_apdu(void) {
uint32_t ne = apdu.ne; uint32_t ne = apdu.ne;
int r = sm_unwrap(); int r = sm_unwrap();
if (r != PICOKEY_OK) { if (r != PICOKEYS_OK) {
return SW_DATA_INVALID(); return SW_DATA_INVALID();
} }
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) { for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {

View File

@@ -19,11 +19,7 @@
#define _SC_HSM_H_ #define _SC_HSM_H_
#include <stdlib.h> #include <stdlib.h>
#ifndef ESP_PLATFORM
#include "common.h"
#else
#define MBEDTLS_ALLOW_PRIVATE_ACCESS #define MBEDTLS_ALLOW_PRIVATE_ACCESS
#endif
#include "mbedtls/rsa.h" #include "mbedtls/rsa.h"
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM) #if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
@@ -31,7 +27,7 @@
#endif #endif
#include "file.h" #include "file.h"
#include "apdu.h" #include "apdu.h"
#include "pico_keys.h" #include "picokeys.h"
#include "usb.h" #include "usb.h"
#define MAX_APDU_DATA (USB_BUFFER_SIZE - 20) #define MAX_APDU_DATA (USB_BUFFER_SIZE - 20)
@@ -82,8 +78,6 @@ extern const uint8_t sc_hsm_aid[];
#define HSM_OPT_RRC 0x0001 #define HSM_OPT_RRC 0x0001
#define HSM_OPT_TRANSPORT_PIN 0x0002 #define HSM_OPT_TRANSPORT_PIN 0x0002
#define HSM_OPT_SESSION_PIN 0x0004
#define HSM_OPT_SESSION_PIN_EXPL 0x000C
#define HSM_OPT_REPLACE_PKA 0x0008 #define HSM_OPT_REPLACE_PKA 0x0008
#define HSM_OPT_COMBINED_AUTH 0x0010 #define HSM_OPT_COMBINED_AUTH 0x0010
#define HSM_OPT_RRC_RESET_ONLY 0x0020 #define HSM_OPT_RRC_RESET_ONLY 0x0020
@@ -108,27 +102,59 @@ extern const uint8_t sc_hsm_aid[];
extern int pin_reset_retries(const file_t *pin, bool); extern int pin_reset_retries(const file_t *pin, bool);
extern int pin_wrong_retry(const file_t *pin); extern int pin_wrong_retry(const file_t *pin);
extern void select_file(file_t *pe);
extern void hash(const uint8_t *input, uint16_t len, uint8_t output[32]); extern void hash(const uint8_t *input, uint16_t len, uint8_t output[32]);
extern uint16_t get_device_options(); extern int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy);
extern int parse_token_info(const file_t *f, int mode);
extern int parse_ef_dir(const file_t *f, int mode);
extern void scan_all(void);
extern void reset_puk_store(void);
extern uint16_t get_device_options(void);
extern bool has_session_pin, has_session_sopin; extern bool has_session_pin, has_session_sopin;
extern uint8_t session_pin[32], session_sopin[32]; extern uint8_t session_pin[32], session_sopin[32];
extern uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len); extern uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len);
extern bool pka_enabled(); extern bool pka_enabled(void);
extern const uint8_t *dev_name; extern const uint8_t *dev_name;
extern uint16_t dev_name_len; extern uint16_t dev_name_len;
extern uint8_t puk_status[MAX_PUK]; extern uint8_t puk_status[MAX_PUK];
extern int puk_store_select_chr(const uint8_t *chr); extern int puk_store_select_chr(const uint8_t *chr);
extern int delete_file(file_t *ef);
extern const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, uint16_t *tag_len); extern const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, uint16_t *tag_len);
extern bool key_has_purpose(file_t *ef, uint8_t purpose); extern bool key_has_purpose(file_t *ef, uint8_t purpose);
extern int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey); extern int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey);
extern int load_private_key_ec(mbedtls_ecp_keypair *ctx, file_t *fkey); extern int load_private_key_ec(mbedtls_ecp_keypair *ctx, file_t *fkey);
extern int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey); extern int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey);
extern bool wait_button_pressed(); extern bool wait_button_pressed(void);
extern int store_keys(void *key_ctx, int type, uint8_t key_id); extern int store_keys(void *key_ctx, int type, uint8_t key_id);
extern int find_and_store_meta_key(uint8_t key_id); extern int find_and_store_meta_key(uint8_t key_id);
extern uint32_t get_key_counter(file_t *fkey); extern uint32_t get_key_counter(file_t *fkey);
extern uint32_t decrement_key_counter(file_t *fkey); extern uint32_t decrement_key_counter(file_t *fkey);
extern int cmd_select(void);
extern int cmd_list_keys(void);
extern int cmd_read_binary(void);
extern int cmd_verify(void);
extern int cmd_reset_retry(void);
extern int cmd_challenge(void);
extern int cmd_external_authenticate(void);
extern int cmd_mse(void);
extern int cmd_initialize(void);
extern int cmd_key_domain(void);
extern int cmd_key_wrap(void);
extern int cmd_keypair_gen(void);
extern int cmd_update_ef(void);
extern int cmd_delete_file(void);
extern int cmd_change_pin(void);
extern int cmd_key_gen(void);
extern int cmd_signature(void);
extern int cmd_key_unwrap(void);
extern int cmd_decrypt_asym(void);
extern int cmd_cipher_sym(void);
extern int cmd_derive_asym(void);
extern int cmd_extras(void);
extern int cmd_general_authenticate(void);
extern int cmd_puk_auth(void);
extern int cmd_pso(void);
extern int cmd_bip_slip(void);
extern uint8_t get_key_domain(file_t *fkey);
#endif #endif

View File

@@ -18,7 +18,7 @@
#ifndef __VERSION_H_ #ifndef __VERSION_H_
#define __VERSION_H_ #define __VERSION_H_
#define HSM_VERSION 0x0604 #define HSM_VERSION 0x0606
#define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff) #define HSM_VERSION_MAJOR ((HSM_VERSION >> 8) & 0xff)
#define HSM_VERSION_MINOR (HSM_VERSION & 0xff) #define HSM_VERSION_MINOR (HSM_VERSION & 0xff)

Binary file not shown.

View File

@@ -23,15 +23,15 @@ def test_select(device):
device.select_applet() device.select_applet()
def test_initialization(device): def test_initialization(device):
device.initialize(no_dev_cert=True) device.initialize()
def test_termca(device): def test_termca(device):
data = device.get_termca() data = device.get_termca()
assert(b'ESPICOHSMTR' == data['cv']['chr'][:11]) assert(b'ESPICOHSMTR' == data['dev']['chr'][:11])
assert(b'ESPICOHSMDV' == data['cv']['car'][:11] or b'ESPICOHSMTR' == data['cv']['car'][:11]) assert(b'ESPICOHSMDV' == data['dev']['car'][:11] or b'ESPICOHSMTR' == data['dev']['car'][:11])
assert(b'ESPICOHSMDV' == data['dv']['chr'][:11] or b'ESPICOHSMTR' == data['dv']['chr'][:11]) assert(b'ESPICOHSMDV' == data['dv']['chr'][:11] or b'ESPICOHSMTR' == data['dv']['chr'][:11])
assert(b'ESPICOHSMCA' == data['dv']['car'][:11] or b'ESPICOHSMTR' == data['dv']['car'][:11]) assert(b'ESPICOHSMCA' == data['dv']['car'][:11] or b'ESPICOHSMTR' == data['dv']['car'][:11])
assert(data['cv']['car'] == data['dv']['chr']) assert(data['dev']['car'] == data['dv']['chr'])
def test_get_version(device): def test_get_version(device):
version = device.get_version() version = device.get_version()

View File

@@ -27,7 +27,7 @@ KEY_DOMAINS = 3
TEST_KEY_DOMAIN = 1 TEST_KEY_DOMAIN = 1
def test_key_domains(device): def test_key_domains(device):
device.initialize(key_domains=KEY_DOMAINS, no_dev_cert=True) device.initialize(key_domains=KEY_DOMAINS)
for k in range(KEY_DOMAINS): for k in range(KEY_DOMAINS):
kd = device.get_key_domain(key_domain=k) kd = device.get_key_domain(key_domain=k)
assert('error' in kd) assert('error' in kd)

View File

@@ -23,7 +23,7 @@ from picohsm.const import DEFAULT_DKEK_SHARES, DEFAULT_PIN, DEFAULT_RETRIES
from const import DEFAULT_DKEK from const import DEFAULT_DKEK
def test_dkek(device): def test_dkek(device):
device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES)
device.login(DEFAULT_PIN) device.login(DEFAULT_PIN)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
assert('dkek' in resp) assert('dkek' in resp)

View File

@@ -24,16 +24,17 @@ from picohsm.const import DEFAULT_PIN, DEFAULT_RETRIES
WRONG_PIN = '112233' WRONG_PIN = '112233'
def test_pin_init_retries(device): def test_pin_init_retries(device):
device.initialize(retries=DEFAULT_RETRIES, no_dev_cert=True) device.initialize(retries=DEFAULT_RETRIES)
device.logout()
retries = device.get_login_retries() retries = device.get_login_retries()
assert(retries == DEFAULT_RETRIES) assert(retries == DEFAULT_RETRIES)
def test_pin_login(device): def test_pin_login(device):
device.initialize(retries=DEFAULT_RETRIES, no_dev_cert=True) device.initialize(retries=DEFAULT_RETRIES)
device.login(DEFAULT_PIN) device.login(DEFAULT_PIN)
def test_pin_retries(device): def test_pin_retries(device):
device.initialize(retries=DEFAULT_RETRIES, no_dev_cert=True) device.initialize(retries=DEFAULT_RETRIES)
device.login(DEFAULT_PIN) device.login(DEFAULT_PIN)
for ret in range(DEFAULT_RETRIES-1): for ret in range(DEFAULT_RETRIES-1):
@@ -45,7 +46,8 @@ def test_pin_retries(device):
device.login(WRONG_PIN) device.login(WRONG_PIN)
assert(e.value.sw == SWCodes.SW_PIN_BLOCKED) assert(e.value.sw == SWCodes.SW_PIN_BLOCKED)
device.initialize(retries=DEFAULT_RETRIES, no_dev_cert=True) device.initialize(retries=DEFAULT_RETRIES)
device.logout()
retries = device.get_login_retries() retries = device.get_login_retries()
assert(retries == DEFAULT_RETRIES) assert(retries == DEFAULT_RETRIES)

View File

@@ -0,0 +1,131 @@
"""
/*
* This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
"""
import pytest
from picokey import APDUResponse, SWCodes
from picohsm.DO import DOPrefixes
from picohsm.const import DEFAULT_PIN
def raw_send(device, command, cla=0x00, p1=0x00, p2=0x00, data=None, ne=None):
# Use low-level transport to avoid automatic PIN retry/login behavior.
return device._PicoHSM__card.send(command=command, cla=cla, p1=p1, p2=p2, data=data, ne=ne, codes=[])
def read_binary_raw(device, fid):
return raw_send(
device,
command=0xB1,
p1=(fid >> 8) & 0xFF,
p2=fid & 0xFF,
data=[0x54, 0x02, 0x00, 0x00],
ne=0,
)
def test_01_protected_data_requires_pin_for_read(device):
fid = (DOPrefixes.PROT_DATA_PREFIX << 8) | 0x01
payload = b"protected-regression"
device.initialize()
device.login(DEFAULT_PIN)
device.put_contents(p1=fid, data=payload)
device.logout()
with pytest.raises(APDUResponse) as e:
read_binary_raw(device, fid)
assert e.value.sw == SWCodes.SW_SECURITY_STATUS_NOT_SATISFIED
device.login(DEFAULT_PIN)
data, sw = read_binary_raw(device, fid)
assert sw == 0x9000
assert bytes(data) == payload
def test_02_static_sensitive_files_are_not_readable(device):
device.initialize()
device.logout()
for fid in (0x1081, 0x100E, 0x100A, 0x100B):
with pytest.raises(APDUResponse) as e:
read_binary_raw(device, fid)
assert e.value.sw == SWCodes.SW_SECURITY_STATUS_NOT_SATISFIED
def test_03_key_object_readout_is_blocked_even_when_authenticated(device):
# #3 depends on #2 class of bug: private key material must not be readable.
# KEY_PREFIX objects are blocked by policy for READ BINARY.
device.initialize()
device.logout()
with pytest.raises(APDUResponse) as e:
read_binary_raw(device, 0xCC00) # EF_KEY_DEV
assert e.value.sw in (SWCodes.SW_SECURITY_STATUS_NOT_SATISFIED, SWCodes.SW_FILE_NOT_FOUND)
device.login(DEFAULT_PIN)
with pytest.raises(APDUResponse) as e:
read_binary_raw(device, 0xCC00) # EF_KEY_DEV
assert e.value.sw in (SWCodes.SW_SECURITY_STATUS_NOT_SATISFIED, SWCodes.SW_FILE_NOT_FOUND)
def test_04_otp_extra_command_is_not_available(device):
# #4: OTP command path was removed.
device.initialize()
device.login(DEFAULT_PIN)
with pytest.raises(APDUResponse) as e:
raw_send(device, cla=0x80, command=0x64, p1=0x4C, p2=0x00, data=[0x00, 0x00])
assert e.value.sw == SWCodes.SW_INCORRECT_P1P2
def test_04_session_pin_instruction_removed(device):
with pytest.raises(APDUResponse) as e:
raw_send(device, command=0x5A, p1=0x01, p2=0x81)
assert e.value.sw1 == 0x6D and e.value.sw2 == 0x00
def test_06_update_ef_rejects_out_of_bounds_offset(device):
fid = (DOPrefixes.DATA_PREFIX << 8) | 0x10
device.initialize()
device.login(DEFAULT_PIN)
device.put_contents(p1=fid, data=b"0123456789abcdef")
# offset=4030, len=8 => 4038 (>4032) must be rejected.
data = [0x54, 0x02, 0x0F, 0xBE, 0x53, 0x08] + [0xAA] * 8
with pytest.raises(APDUResponse) as e:
raw_send(device, command=0xD7, p1=(fid >> 8) & 0xFF, p2=fid & 0xFF, data=data)
assert e.value.sw1 == 0x67 and e.value.sw2 == 0x00
def test_07_secure_messaging_requires_valid_mac(device):
device.initialize()
device.logout()
# GA must fail without an authenticated session.
with pytest.raises(APDUResponse) as e:
device.general_authentication()
assert e.value.sw1 == 0x64 and e.value.sw2 == 0x00
# After PIN verification, GA should be available and SM can be established.
device.login(DEFAULT_PIN)
device.general_authentication()
with pytest.raises(APDUResponse) as e:
raw_send(device, command=0x84, cla=0x0C, data=[0x97, 0x01, 0x10], ne=0)
assert e.value.sw1 == 0x69 and e.value.sw2 in (0x84, 0x87, 0x88)

View File

@@ -21,7 +21,7 @@ import pytest
from picohsm import KeyType, DOPrefixes from picohsm import KeyType, DOPrefixes
def test_gen_initialize(device): def test_gen_initialize(device):
device.initialize(no_dev_cert=True) device.initialize()
@pytest.mark.parametrize( @pytest.mark.parametrize(
"curve", ['secp192r1', 'secp256r1', 'secp384r1', 'secp521r1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1', 'secp192k1', 'secp256k1', 'curve25519', 'curve448', 'ed25519', 'ed448'] "curve", ['secp192r1', 'secp256r1', 'secp384r1', 'secp521r1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1', 'secp192k1', 'secp256k1', 'curve25519', 'curve448', 'ed25519', 'ed448']

View File

@@ -27,7 +27,7 @@ from picohsm.const import DEFAULT_RETRIES, DEFAULT_DKEK_SHARES
from const import DEFAULT_DKEK from const import DEFAULT_DKEK
def test_prepare_dkek(device): def test_prepare_dkek(device):
device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
kcv = hashlib.sha256(b'\x00'*32).digest()[:8] kcv = hashlib.sha256(b'\x00'*32).digest()[:8]

View File

@@ -25,7 +25,7 @@ from picohsm.const import DEFAULT_RETRIES, DEFAULT_DKEK_SHARES
from const import DEFAULT_DKEK from const import DEFAULT_DKEK
def test_prepare_dkek(device): def test_prepare_dkek(device):
device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
kcv = hashlib.sha256(b'\x00'*32).digest()[:8] kcv = hashlib.sha256(b'\x00'*32).digest()[:8]

View File

@@ -29,7 +29,7 @@ from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives import serialization
def test_initialize(device): def test_initialize(device):
device.initialize(key_domains=1, no_dev_cert=True) device.initialize(key_domains=1)
assert(device.get_key_domains() == 1) assert(device.get_key_domains() == 1)
device.set_key_domain(key_domain=0, total=2) device.set_key_domain(key_domain=0, total=2)

View File

@@ -27,7 +27,7 @@ from const import DEFAULT_DKEK
MESSAGE = b'a secret message' MESSAGE = b'a secret message'
def test_prepare_aes(device): def test_prepare_aes(device):
device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)

View File

@@ -31,7 +31,7 @@ MESSAGE = b'a secret message'
AAD = b'this is a tag for AAD' AAD = b'this is a tag for AAD'
def test_prepare_chachapoly(device): def test_prepare_chachapoly(device):
device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)

View File

@@ -29,7 +29,7 @@ MESSAGE = b'a secret message'
AAD = b'this is a tag for AAD' AAD = b'this is a tag for AAD'
def test_prepare_aes(device): def test_prepare_aes(device):
device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)

View File

@@ -28,7 +28,7 @@ from const import DEFAULT_DKEK
MESSAGE = b'a secret message' MESSAGE = b'a secret message'
def test_prepare_aes(device): def test_prepare_aes(device):
device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)

View File

@@ -29,7 +29,7 @@ from picohsm import DOPrefixes
INFO = b'info message' INFO = b'info message'
def test_prepare_kd(device): def test_prepare_kd(device):
device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)

View File

@@ -29,7 +29,7 @@ from picohsm import DOPrefixes
INFO = b'info message' INFO = b'info message'
def test_prepare_kd(device): def test_prepare_kd(device):
device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)

View File

@@ -29,7 +29,7 @@ from picohsm import DOPrefixes
INFO = b'shared message' INFO = b'shared message'
def test_prepare_kd(device): def test_prepare_kd(device):
device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)

View File

@@ -34,7 +34,7 @@ AUT_PUK = unhexlify('678201ed7f218201937f4e82014b5f290100421045535049434f48534d5
term_chr = CVC().decode(TERM_CERT).chr() term_chr = CVC().decode(TERM_CERT).chr()
def test_initialize(device): def test_initialize(device):
device.initialize(puk_auts=1, puk_min_auts=1, no_dev_cert=False) device.initialize(puk_auts=1, puk_min_auts=1)
device.logout() device.logout()
def test_register_puk(device): def test_register_puk(device):
@@ -102,7 +102,7 @@ def test_enumerate_puk_1(device):
assert(puks[0]['status'] == 0) assert(puks[0]['status'] == 0)
def test_enumerate_puk_2(device): def test_enumerate_puk_2(device):
device.initialize(puk_auts=2, puk_min_auts=1, no_dev_cert=True) device.initialize(puk_auts=2, puk_min_auts=1)
puks = device.enumerate_puk() puks = device.enumerate_puk()
assert(len(puks) == 2) assert(len(puks) == 2)
assert(puks[0]['status'] == -1) assert(puks[0]['status'] == -1)
@@ -115,7 +115,7 @@ def test_enumerate_puk_2(device):
assert(puks[1]['status'] == -1) assert(puks[1]['status'] == -1)
def test_register_more_puks(device): def test_register_more_puks(device):
device.initialize(puk_auts=2, puk_min_auts=1, no_dev_cert=True) device.initialize(puk_auts=2, puk_min_auts=1)
status = device.get_puk_status() status = device.get_puk_status()
assert(status == bytes([2,2,1,0])) assert(status == bytes([2,2,1,0]))
@@ -123,14 +123,14 @@ def test_register_more_puks(device):
assert(status == bytes([2,1,1,0])) assert(status == bytes([2,1,1,0]))
def test_is_pku(device): def test_is_pku(device):
device.initialize(puk_auts=1, puk_min_auts=1, no_dev_cert=True) device.initialize(puk_auts=1, puk_min_auts=1)
assert(device.is_puk() == True) assert(device.is_puk() == True)
device.initialize(no_dev_cert=True) device.initialize()
assert(device.is_puk() == False) assert(device.is_puk() == False)
def test_check_puk_key(device): def test_check_puk_key(device):
device.initialize(puk_auts=1, puk_min_auts=1, no_dev_cert=True) device.initialize(puk_auts=1, puk_min_auts=1)
status = device.check_puk_key(term_chr) status = device.check_puk_key(term_chr)
assert(status == -1) assert(status == -1)
@@ -140,7 +140,7 @@ def test_check_puk_key(device):
def test_register_puk_with_no_puk(device): def test_register_puk_with_no_puk(device):
device.initialize(no_dev_cert=True) device.initialize()
with pytest.raises(APDUResponse) as e: with pytest.raises(APDUResponse) as e:
device.register_puk(AUT_PUK, TERM_CERT, DICA_CERT) device.register_puk(AUT_PUK, TERM_CERT, DICA_CERT)
assert(e.value.sw == SWCodes.SW_FILE_NOT_FOUND) assert(e.value.sw == SWCodes.SW_FILE_NOT_FOUND)

View File

@@ -31,14 +31,10 @@ from picokey import APDUResponse, SWCodes
KDM = unhexlify(b'30820420060b2b0601040181c31f0402016181ed7f2181e97f4e81a25f290100421045535049434f48534d434130303030327f494f060a04007f00070202020203864104e66b473ec328caf39eaed840f9c7a4ba237e1dd19004861fa3f4f134bd2d5ea5f71c6c2e6321add4c8a7793ba41119c5783f48a5d9dfc0898d9ae9e7b14da8d65f201045535049434f48534d445630303030327f4c12060904007f000703010202530580000000045f25060205000400065f24060206000400065f3740a645594c6c338cd6bda6cad039cee54fd822b1011c0af1e4e3a2a6d03d43bdbb8be68a66a8757e7b1f963589bdd80d8e65de5055b722609041ec63f0498ddc8b6281e97f2181e57f4e819e5f290100421045535049434f48534d445630303030327f494f060a04007f000702020202038641043359f5234ce62e0eb80460046d8fd1aae018cc8b9e687b40aa2c047e352409b45153d1ad888e4e7e780a3b1fa8c69ca8998bd271c8849137149142e96816a5a45f201045535049434f48534d54524a5a58314a7f4c0e060904007f0007030102025301005f25060205010102085f24060206010102085f37409add1c1c8a05e7bc56a8bd846c9122d9214cc43c86b6952a961dce525d830a58130cbb275e9408af38dc16160f958d2b9ac6ac4f0f1b9b863284f00121d447ce638201f1678201ed7f218201937f4e82014b5f290100421045535049434f48534d54524a5a58314a7f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a78641049de55b50b921de72bbf740d3518905ff893e8208cfe8d144de34d79da3645d1c0cb551a19d6e6a5fee050e479a65d36fdf638af741e52dad4df9960b8ed443d18701015f201045535049434f48534d54524a5a58314a5f374099dede270b9a2def89a4d12dc0314e6289bd565808683f362e9f9ac9554ec5113bf7e412ecc386af12d2a9b43f27e54e10dfc6d8f2d6b618b1776459c13c0bec421045535049434f48534d54524a5a58314a5f3740459f6385f28a84f1c57f421a7f6cb4f1177084497321be94c87998c2e01af0202bab6984411cde1aab34e4e59cc27961b85855bae6340305281ff838253b0f3554404b6a2fe6947faa91f6ffa0d707cd4cbb43192935f561be137f4b3680304fc28b41210b671b8b033e06b4ad720010bcd36b92282844616261f944f3c4f67bfda5') KDM = unhexlify(b'30820420060b2b0601040181c31f0402016181ed7f2181e97f4e81a25f290100421045535049434f48534d434130303030327f494f060a04007f00070202020203864104e66b473ec328caf39eaed840f9c7a4ba237e1dd19004861fa3f4f134bd2d5ea5f71c6c2e6321add4c8a7793ba41119c5783f48a5d9dfc0898d9ae9e7b14da8d65f201045535049434f48534d445630303030327f4c12060904007f000703010202530580000000045f25060205000400065f24060206000400065f3740a645594c6c338cd6bda6cad039cee54fd822b1011c0af1e4e3a2a6d03d43bdbb8be68a66a8757e7b1f963589bdd80d8e65de5055b722609041ec63f0498ddc8b6281e97f2181e57f4e819e5f290100421045535049434f48534d445630303030327f494f060a04007f000702020202038641043359f5234ce62e0eb80460046d8fd1aae018cc8b9e687b40aa2c047e352409b45153d1ad888e4e7e780a3b1fa8c69ca8998bd271c8849137149142e96816a5a45f201045535049434f48534d54524a5a58314a7f4c0e060904007f0007030102025301005f25060205010102085f24060206010102085f37409add1c1c8a05e7bc56a8bd846c9122d9214cc43c86b6952a961dce525d830a58130cbb275e9408af38dc16160f958d2b9ac6ac4f0f1b9b863284f00121d447ce638201f1678201ed7f218201937f4e82014b5f290100421045535049434f48534d54524a5a58314a7f4982011d060a04007f000702020202038120a9fb57dba1eea9bc3e660a909d838d726e3bf623d52620282013481d1f6e537782207d5a0975fc2c3057eef67530417affe7fb8055c126dc5c6ce94a4b44f330b5d9832026dc5c6ce94a4b44f330b5d9bbd77cbf958416295cf7e1ce6bccdc18ff8c07b68441048bd2aeb9cb7e57cb2c4b482ffc81b7afb9de27e1e3bd23c23a4453bd9ace3262547ef835c3dac4fd97f8461a14611dc9c27745132ded8e545c1d54c72f0469978520a9fb57dba1eea9bc3e660a909d838d718c397aa3b561a6f7901e0e82974856a78641049de55b50b921de72bbf740d3518905ff893e8208cfe8d144de34d79da3645d1c0cb551a19d6e6a5fee050e479a65d36fdf638af741e52dad4df9960b8ed443d18701015f201045535049434f48534d54524a5a58314a5f374099dede270b9a2def89a4d12dc0314e6289bd565808683f362e9f9ac9554ec5113bf7e412ecc386af12d2a9b43f27e54e10dfc6d8f2d6b618b1776459c13c0bec421045535049434f48534d54524a5a58314a5f3740459f6385f28a84f1c57f421a7f6cb4f1177084497321be94c87998c2e01af0202bab6984411cde1aab34e4e59cc27961b85855bae6340305281ff838253b0f3554404b6a2fe6947faa91f6ffa0d707cd4cbb43192935f561be137f4b3680304fc28b41210b671b8b033e06b4ad720010bcd36b92282844616261f944f3c4f67bfda5')
def test_initialize(device): def test_initialize(device):
device.initialize(key_domains=1, no_dev_cert=True) device.initialize(key_domains=1)
device.logout() device.logout()
def test_create_xkek(device): def test_create_xkek(device):
with pytest.raises(APDUResponse) as e:
device.create_xkek(KDM)
assert(e.value.sw == SWCodes.SW_CONDITIONS_NOT_SATISFIED)
device.login() device.login()
kcv, did = device.create_xkek(KDM) kcv, did = device.create_xkek(KDM)
assert(kcv == b'\x00'*8) assert(kcv == b'\x00'*8)

View File

@@ -37,7 +37,7 @@ def sha256_sha256(data):
return hashlib.sha256(hashlib.sha256(data).digest()).digest() return hashlib.sha256(hashlib.sha256(data).digest()).digest()
def test_initialize(device): def test_initialize(device):
device.initialize(dkek_shares=DEFAULT_DKEK_SHARES, no_dev_cert=True) device.initialize(dkek_shares=DEFAULT_DKEK_SHARES)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)
resp = device.import_dkek(DEFAULT_DKEK) resp = device.import_dkek(DEFAULT_DKEK)

View File

@@ -49,7 +49,7 @@ for alg in ${algs[*]}; do
grep -q "Key ref[[:blank:]]*: 10" <<< $e && exit $? || echo -e ".\t${OK}" grep -q "Key ref[[:blank:]]*: 10" <<< $e && exit $? || echo -e ".\t${OK}"
echo -n " Unwrap key..." echo -n " Unwrap key..."
sc-hsm-tool --unwrap-key wrap-key.bin --key-reference 10 --pin 648219 --force > /dev/null 2>&1 sc-hsm-tool --unwrap-key wrap-key.bin --key-reference 10 --pin 648219 --force > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $? echo -n "." || exit $?
e=$(pkcs15-tool -D 2>&1) e=$(pkcs15-tool -D 2>&1)
grep -q "Key ref[[:blank:]]*: 10" <<< $e && echo -e ".\t${OK}" || exit $? grep -q "Key ref[[:blank:]]*: 10" <<< $e && echo -e ".\t${OK}" || exit $?
echo -n " Cleaning..." echo -n " Cleaning..."

View File

@@ -21,7 +21,7 @@ gen_and_check() {
glabel="EC_POINT 512 bits" glabel="EC_POINT 512 bits"
;; ;;
*"521"*) *"521"*)
glabel="EC_POINT 528 bits" glabel="EC_POINT 52"
;; ;;
*"rsa"*) *"rsa"*)
IFS=: read -r v1 bits <<< "$1" IFS=: read -r v1 bits <<< "$1"

View File

@@ -50,6 +50,13 @@ test $? -eq 0 || {
exit 1 exit 1
} }
echo "==== Test PKCS11 security regressions ===="
./tests/scripts/pkcs11_security_regressions.sh
test $? -eq 0 || {
echo -e "\t${FAIL}"
exit 1
}
echo "==== Test backup and restore ====" echo "==== Test backup and restore ===="
./tests/scripts/backup.sh ./tests/scripts/backup.sh
test $? -eq 0 || { test $? -eq 0 || {

View File

@@ -0,0 +1,56 @@
#!/bin/bash
source ./tests/scripts/func.sh
TMP_SIGN_DATA=".pkcs11_sec_reg_data"
TMP_PRIV_DATA=".pkcs11_sec_reg_priv_data"
TMP_SIG_OUT=".pkcs11_sec_reg.sig"
cleanup() {
rm -f "$TMP_SIGN_DATA" "$TMP_PRIV_DATA" "$TMP_SIG_OUT"
pkcs11-tool -l --pin 648219 --delete-object --type privkey --id 1 > /dev/null 2>&1 || true
pkcs11-tool -l --pin 648219 --delete-object --type data --label 'sec_priv_data' > /dev/null 2>&1 || true
}
trap cleanup EXIT
reset
test $? -eq 0 || exit $?
echo "security regression data" > "$TMP_SIGN_DATA"
echo -n " Security regression: private key operation requires login..."
pkcs11-tool -l --pin 648219 --keypairgen --key-type rsa:2048 --id 1 --label "SecRegression" > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(pkcs11-tool --id 1 --sign --mechanism RSA-PKCS -i "$TMP_SIGN_DATA" -o "$TMP_SIG_OUT" 2>&1)
test $? -ne 0 && echo -n "." || exit $?
(
grep -q "CKR_USER_NOT_LOGGED_IN" <<< "$e" ||
grep -q "CKR_PIN_REQUIRED" <<< "$e" ||
grep -q "util_getpass error" <<< "$e"
) && echo -e ".\t${OK}" || exit $?
echo -n " Security regression: private key material is not exportable..."
e=$(pkcs11-tool --read-object --type privkey --id 1 --pin 648219 2>&1)
test $? -eq 0 && echo -n "." || exit $?
(
grep -q "CKR_ATTRIBUTE_SENSITIVE" <<< "$e" ||
grep -q "CKR_ACTION_PROHIBITED" <<< "$e" ||
grep -q "reading private keys not (yet) supported" <<< "$e" ||
grep -q "error: object not found" <<< "$e"
) && echo -e ".\t${OK}" || exit $?
echo -n " Security regression: private data object cannot be read without login..."
echo "private data regression" > "$TMP_PRIV_DATA"
pkcs11-tool --pin 648219 --write-object "$TMP_PRIV_DATA" --type data --id 2 --label 'sec_priv_data' --private > /dev/null 2>&1
test $? -eq 0 && echo -n "." || exit $?
e=$(pkcs11-tool --read-object --type data --label 'sec_priv_data' 2>&1)
test $? -eq 1 && echo -n "." || exit $?
(
grep -q "error: object not found" <<< "$e" ||
grep -q "CKR_USER_NOT_LOGGED_IN" <<< "$e" ||
grep -q "CKR_PIN_REQUIRED" <<< "$e"
) && echo -n "." || exit $?
e=$(pkcs11-tool --read-object --type data --label 'sec_priv_data' --pin 648219 2>&1)
test $? -eq 0 && echo -n "." || exit $?
grep -q "private data regression" <<< "$e" && echo -e ".\t${OK}" || exit $?