diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 21598af..005214e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -36,7 +36,7 @@ jobs: language: [ 'cpp', 'python' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - mode: [ 'pico', 'local' ] + mode: [ 'pico', 'esp32', 'local' ] steps: - name: Checkout repository @@ -44,7 +44,7 @@ jobs: # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL - uses: github/codeql-action/init@v2 + uses: github/codeql-action/init@v3 with: languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. @@ -71,4 +71,4 @@ jobs: ./workflows/autobuild.sh ${{ matrix.mode }} - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v2 + uses: github/codeql-action/analyze@v3 diff --git a/CMakeLists.txt b/CMakeLists.txt index d054d9e..a57b82e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,131 +1,129 @@ - # - # 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 . - # +# +# 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 . +# cmake_minimum_required(VERSION 3.13) if(ESP_PLATFORM) -set(EXTRA_COMPONENT_DIRS src pico-keys-sdk/src) -include($ENV{IDF_PATH}/tools/cmake/project.cmake) + set(EXTRA_COMPONENT_DIRS src pico-keys-sdk/src) + include($ENV{IDF_PATH}/tools/cmake/project.cmake) else() -if(ENABLE_EMULATION) -else() -include(pico_sdk_import.cmake) -endif() + if(NOT ENABLE_EMULATION) + include(pico_sdk_import.cmake) + endif() -project(pico_hsm C CXX ASM) + project(pico_hsm C CXX ASM) -set(CMAKE_C_STANDARD 11) -set(CMAKE_CXX_STANDARD 17) + set(CMAKE_C_STANDARD 11) + set(CMAKE_CXX_STANDARD 17) -if(NOT ENABLE_EMULATION) -pico_sdk_init() -endif() + if(NOT ENABLE_EMULATION) + pico_sdk_init() + endif() -if (NOT DEFINED __FOR_CI) - set(__FOR_CI 0) -endif() -if (__FOR_CI) - add_definitions(-D__FOR_CI) -endif() + if(NOT DEFINED __FOR_CI) + set(__FOR_CI 0) + endif() + if(__FOR_CI) + add_definitions(-D__FOR_CI) + endif() -add_executable(pico_hsm) + add_executable(pico_hsm) endif() set(SOURCES ${SOURCES} - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_select.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_list_keys.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_read_binary.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_verify.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_reset_retry.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_challenge.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_external_authenticate.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_mse.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_initialize.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_key_domain.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_key_wrap.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_keypair_gen.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_update_ef.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_delete_file.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_change_pin.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_key_gen.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_signature.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_key_unwrap.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_decrypt_asym.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_cipher_sym.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_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_pso.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_bip_slip.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cvc.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/files.c - ${CMAKE_CURRENT_LIST_DIR}/src/hsm/kek.c - - ) + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/sc_hsm.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_select.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_list_keys.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_read_binary.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_verify.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_reset_retry.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_challenge.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_external_authenticate.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_mse.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_key_domain.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_key_wrap.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_keypair_gen.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_update_ef.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_delete_file.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_change_pin.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_key_gen.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_signature.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_key_unwrap.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_decrypt_asym.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_cipher_sym.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_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_pso.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cmd_bip_slip.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/cvc.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/files.c + ${CMAKE_CURRENT_LIST_DIR}/src/hsm/kek.c +) set(USB_ITF_CCID 1) set(USB_ITF_WCID 1) include(pico-keys-sdk/pico_keys_sdk_import.cmake) + +SET_VERSION(ver_major ver_minor "${CMAKE_CURRENT_LIST_DIR}/src/hsm/version.h") + if(ESP_PLATFORM) project(pico_hsm) endif() set(INCLUDES ${INCLUDES} - ${CMAKE_CURRENT_LIST_DIR}/src/hsm - ) -if(NOT ESP_PLATFORM) -target_sources(pico_hsm PUBLIC ${SOURCES}) -target_include_directories(pico_hsm PUBLIC ${INCLUDES}) - -target_compile_options(pico_hsm PUBLIC - -Wall + ${CMAKE_CURRENT_LIST_DIR}/src/hsm ) -if (NOT MSVC) +if(NOT ESP_PLATFORM) + target_sources(pico_hsm PUBLIC ${SOURCES}) + target_include_directories(pico_hsm PUBLIC ${INCLUDES}) + target_compile_options(pico_hsm PUBLIC - -Werror + -Wall ) -endif() - -if(ENABLE_EMULATION) - if (NOT MSVC) - target_compile_options(pico_hsm PUBLIC - -fdata-sections - -ffunction-sections - ) - endif() - if(APPLE) - target_link_options(pico_hsm PUBLIC - -Wl,-dead_strip - ) - elseif(MSVC) + if(NOT MSVC) target_compile_options(pico_hsm PUBLIC - -WX + -Werror ) + endif() - target_link_libraries(pico_hsm PUBLIC wsock32 ws2_32 Bcrypt) - else() - target_link_options(pico_hsm PUBLIC - -Wl,--gc-sections + if(ENABLE_EMULATION) + if(NOT MSVC) + target_compile_options(pico_hsm PUBLIC + -fdata-sections + -ffunction-sections + ) + endif() + if(APPLE) + target_link_options(pico_hsm PUBLIC + -Wl,-dead_strip + ) + elseif(MSVC) + target_compile_options(pico_hsm PUBLIC + -WX ) - endif (APPLE) - target_link_libraries(pico_hsm PRIVATE pthread m) -else() -target_link_libraries(pico_hsm PRIVATE pico_keys_sdk pico_stdlib pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id pico_aon_timer tinyusb_device tinyusb_board) -endif() + target_link_libraries(pico_hsm PUBLIC wsock32 ws2_32 Bcrypt) + else() + target_link_options(pico_hsm PUBLIC + -Wl,--gc-sections + ) + endif(APPLE) + target_link_libraries(pico_hsm PRIVATE pthread m) + endif() endif() diff --git a/Dockerfile b/Dockerfile index ecb2f54..d3a37bc 100644 --- a/Dockerfile +++ b/Dockerfile @@ -18,7 +18,7 @@ WORKDIR /home/builduser VOLUME /home/builduser/release -ARG VERSION_PICO_SDK 1.4.0 +ARG VERSION_PICO_SDK 2.0.0 RUN mkdir -p /home/builduser/Devel/pico RUN cd /home/builduser/Devel/pico \ @@ -29,8 +29,8 @@ RUN cd /home/builduser/Devel/pico \ RUN pip install cryptography -ARG VERSION_MAJOR 2 -ARG VERSION_MINOR 6 +ARG VERSION_MAJOR 4 +ARG VERSION_MINOR 2 RUN cd /home/builduser \ && git clone https://github.com/polhenarejos/pico-hsm.git \ @@ -46,7 +46,7 @@ ENV PICO_SDK_PATH /home/builduser/Devel/pico/pico-sdk ARG USB_VID 0xfeff ARG USB_PID 0xfcfd -ARG PICO_BOARD waveshare_rp2040_zero +ARG PICO_BOARD waveshare_rp2040_zero RUN cd /home/builduser/pico-hsm \ && cd build_release \ diff --git a/README.md b/README.md index 83530d9..0a87357 100644 --- a/README.md +++ b/README.md @@ -138,6 +138,21 @@ Uses an MKEK to securely store all keys, encrypted with an ephemeral key derived ### > Hierarchical Deterministic Key Generation Supports BIP32 for asymmetric key derivation and SLIP10 for symmetric key derivation, enabling crypto wallet deployment with infinite key generation. Supports NIST 256 and Koblitz 256 curves for master key generation.[^4] +### > One Time Programming (OTP) Storage +The OTP securely stores the MKEK (Master Key Encryption Key) and Device Key permanently, making it inaccessible from external interfaces. This ensures that the key is protected against unauthorized access and tampering. + +### > Secure Boot +Secure Boot ensures only authenticated firmware can run on the device, verifying each firmware’s digital signature to block unauthorized code. + +### > Secure Lock +Secure Lock restricts the device to the manufacturer’s firmware only, locking out debug access and preventing any further boot key installations. + +### > Rescue Interface + A built-in rescue interface allows recovery of the device if it becomes unresponsive or undetectable. This feature provides a way to restore the device to operational status without compromising security. + + ### > LED Customization + The LED can be customized to reflect device status and user preferences, offering flexible color and brightness options for an enhanced user experience. + [^1]: PKCS11 modules (`pkcs11-tool` and `sc-tool`) do not support CMAC and key derivation. It must be processed through raw APDU command (`opensc-tool -s`). [^2]: Available via SCS3 tool. See [SCS3](/doc/scs3.md "SCS3") for more information. [^3]: Imports are available only if the Pico HSM is previously initialized with a DKEK and DKEK shares are available during the import process. @@ -147,33 +162,45 @@ Supports BIP32 for asymmetric key derivation and SLIP10 for symmetric key deriva Pico HSM also supports ESP32-S3 boards, which add secure storage, flash encryption and secure boot. ### > Dynamic VID/PID -Supports setting VID & PID on-the-fly. Use `pico-hsm-tool.py` for specify VID/PID values and reboot the device. +Supports setting VID & PID on-the-fly. Use `pico-hsm-tool.py` or [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner") for specify VID/PID values and reboot the device. -### > Rescue Pico HSM Tool -Pico HSM Tool implements a new CCID stack to rescue the Pico HSM in case it has wrong VID/PID values and it is not recognized by the OS. +### > Rescue Pico HSM Tool and Commissioner +Pico HSM Tool implements a new CCID stack to rescue the Pico HSM in case it has wrong VID/PID values and it is not recognized by the OS. It can be accessed through `pico-hsm-tool.py` or [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner"). ## Security considerations -All secret keys (both asymmetric and symmetric) are encrypted and stored in the flash memory of the Raspberry Pico. The DKEK, a 256-bit AES key, is used to protect these private and secret keys. Keys are only held in RAM during signature and decryption operations, and are loaded and cleared each time to avoid potential security vulnerabilities. +All secret keys (both asymmetric and symmetric) are encrypted and stored in the flash memory. The MKEK, a 256-bit AES key, is used to protect these private and secret keys. Keys are held in RAM only during signature and decryption operations, and are loaded and cleared each time to avoid potential security vulnerabilities. -The DKEK itself is encrypted using a doubly salted and hashed PIN, and the PIN is hashed in memory during sessions. This ensures that the PIN is never stored in plain text, either in flash memory or in RAM. However, if no secure channel is used, the PIN is transmitted in plain text from the host to the HSM. +The MKEK itself is encrypted using a doubly salted and hashed PIN, and the PIN is hashed in memory during sessions. This ensures that the PIN is never stored in plaintext, neither in flash memory nor in RAM. However, if no secure channel is used, the PIN may be transmitted in plaintext from the host to the HSM. + +DKEKs are used during the export and import of private/secret keys and are part of a Key Domain. A Key Domain is a set of secret/private keys that share the same DKEK. These are also shared by the custodians and are not specific to Pico HSM. Therefore, if a key does not belong to a Key Domain (and thus lacks a DKEK), it cannot be exported. In the event that the Pico is stolen, the private and secret key contents cannot be accessed without the PIN, even if the flash memory is dumped. +### RP2350 and ESP32-S3 +RP2350 and ESP32-S3 microcontrollers are equipped with advanced security features, including Secure Boot and Secure Lock, ensuring that firmware integrity and authenticity are tightly controlled. Both devices support the storage of the Master Key Encryption Key (MKEK) in an OTP (One-Time Programmable) memory region, making it permanently inaccessible for external access or tampering. This secure, non-volatile region guarantees that critical security keys are embedded into the hardware, preventing unauthorized access and supporting robust defenses against code injection or firmware modification. Together, Secure Boot and Secure Lock enforce firmware authentication, while the MKEK in OTP memory solidifies the foundation for secure operations. + +### Secure Boot +Secure Boot is a security feature that ensures that only trusted firmware, verified through digital signatures, can be loaded onto the device during the boot process. Once enabled, Secure Boot checks every piece of firmware against a cryptographic signature before execution, rejecting any unauthorized or modified code. This prevents malicious firmware from compromising the device’s operation and integrity. With Secure Boot activated, only firmware versions signed by a trusted authority, such as the device manufacturer, will be accepted, ensuring the device remains protected from unauthorized software modifications. **This is irreversible. Once enabled, it CANNOT be disabled.** + +**IMPORTANT:** For users wishing to develop and compile custom firmware, a private-public key pair is essential. Activating Secure Boot requires users to generate and manage their own unique private-public key pair. The public key from this pair must be embedded into the device to validate all firmware. Firmware will not boot without a proper digital signature from this key pair. This means that users must sign all future firmware versions with their private key and embed the public key in the device to ensure compatibility. + +### Secure Lock +Secure Lock builds on Secure Boot by imposing an even stricter security model. Once activated, Secure Lock prevents any further installation of new boot keys, effectively locking the device to only run firmware that is authorized by the device's primary vendor—in this case, Pico Keys. In addition to preventing additional keys, Secure Lock disables debugging interfaces and puts additional safeguards in place to resist tampering and intrusion attempts. This ensures that the device operates exclusively with the original vendor’s firmware and resists unauthorized access, making it highly secure against external threats. **This is irreversible. Once enabled, it CANNOT be disabled.** + +**IMPORTANT:** Activating Secure Lock not only enables Secure Boot but also invalidates all keys except the official Pico Key. This means that only firmware signed by Pico Key will be recognized, and custom code will no longer be allowed. Once enabled, the Pico Key device will run solely on the official firmware available on the website, with no option for generating or compiling new code for the device. + ## Download -**If you own an ESP32-S3 board, go to [ESP32 support](https://www.picokeys.com/esp32-support/) for further information.** +**If you own an ESP32-S3 board, go to [ESP32 Flasher](https://www.picokeys.com/esp32-flasher/) for flashing your Pico HSM.** -Please, go to the Release page and download the UF2 file for your board. +If you own a Raspberry Pico (RP2040 or RP2350), go to [Download page](https://www.picokeys.com/getting-started/), select your vendor and model and download the proper firmware; or go to [Release page](https://www.github.com/polhenarejos/pico-hsm/releases/) and download the UF2 file for your board. -Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you plan to use it with OpenSC or similar tools, you should modify Info.plist of CCID driver to add these VID/PID or use the [Pico Patcher tool](https://www.picokeys.com/pico-patcher/). - -Alternatively you can use the legacy VID/PID patcher as follows: -`./patch_vidpid.sh VID:PID input_hsm_file.uf2 output_hsm_file.uf2` +Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you plan to use it with OpenSC or similar tools, you should modify Info.plist of CCID driver to add these VID/PID or use the [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner"). You can use whatever VID/PID (i.e., 234b:0000 from FISJ), but remember that you are not authorized to distribute the binary with a VID/PID that you do not own. -Note that the pure-browser option [Pico Patcher tool](https://www.picokeys.com/pico-patcher/) is the most recommended. +Note that the pure-browser option [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner") is the most recommended. -## Build +## Build for Raspberry Pico Before building, ensure you have installed the toolchain for the Pico and the Pico SDK is properly located in your drive. ``` @@ -212,9 +239,9 @@ Independent from your Linux distribution or when using another OS that supports ``` sudo docker build \ - --build-arg VERSION_PICO_SDK=1.5.0 \ - --build-arg VERSION_MAJOR=3 \ - --build-arg VERSION_MINOR=4 \ + --build-arg VERSION_PICO_SDK=2.0.0 \ + --build-arg VERSION_MAJOR=5 \ + --build-arg VERSION_MINOR=0 \ --build-arg PICO_BOARD=waveshare_rp2040_zero \ --build-arg USB_VID=0xfeff \ --build-arg USB_PID=0xfcfd \ @@ -321,8 +348,7 @@ For advanced usage scenarios, refer to the documentation and examples provided. ### Important OpenSC relies on PCSC driver, which reads a list (`Info.plist`) that contains a pair of VID/PID of supported readers. In order to be detectable, you have several options: - Use `pico-hsm-tool.py` to modify VID/PID on-the-fly. -- Use the online [Pico Patcher tool](https://www.picokeys.com/pico-patcher/). -- Patch the UF2 binary (if you just downloaded from the [Release section](https://github.com/polhenarejos/pico-hsm/releases "Release section")) +- Use the pure-browser online [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner") that commissions the Pico Key on-the-fly without external tools. - Build and configure the project with the proper VID/PID with `USB_VID` and `USB_PID` parameters in `CMake` (see [Build section](#build "Build section")). Note that you cannot distribute the patched/compiled binary if you do not own the VID/PID or have an explicit authorization. ## Credits diff --git a/pico-keys-sdk b/pico-keys-sdk index 1bf323c..5a52afe 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 1bf323c36789e7c1a9273ca7ae5f3ad221fcbef5 +Subproject commit 5a52afe8267fc32293999955577b9158bc20bb34 diff --git a/pico_sdk_import.cmake b/pico_sdk_import.cmake index 28efe9e..a0721d0 100644 --- a/pico_sdk_import.cmake +++ b/pico_sdk_import.cmake @@ -18,9 +18,20 @@ if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_PATH} AND (NOT PICO_SDK_FETCH_FROM_GIT_P message("Using PICO_SDK_FETCH_FROM_GIT_PATH from environment ('${PICO_SDK_FETCH_FROM_GIT_PATH}')") endif () +if (DEFINED ENV{PICO_SDK_FETCH_FROM_GIT_TAG} AND (NOT PICO_SDK_FETCH_FROM_GIT_TAG)) + set(PICO_SDK_FETCH_FROM_GIT_TAG $ENV{PICO_SDK_FETCH_FROM_GIT_TAG}) + message("Using PICO_SDK_FETCH_FROM_GIT_TAG from environment ('${PICO_SDK_FETCH_FROM_GIT_TAG}')") +endif () + +if (PICO_SDK_FETCH_FROM_GIT AND NOT PICO_SDK_FETCH_FROM_GIT_TAG) + set(PICO_SDK_FETCH_FROM_GIT_TAG "master") + message("Using master as default value for PICO_SDK_FETCH_FROM_GIT_TAG") +endif() + set(PICO_SDK_PATH "${PICO_SDK_PATH}" CACHE PATH "Path to the Raspberry Pi Pico SDK") set(PICO_SDK_FETCH_FROM_GIT "${PICO_SDK_FETCH_FROM_GIT}" CACHE BOOL "Set to ON to fetch copy of SDK from git if not otherwise locatable") set(PICO_SDK_FETCH_FROM_GIT_PATH "${PICO_SDK_FETCH_FROM_GIT_PATH}" CACHE FILEPATH "location to download SDK") +set(PICO_SDK_FETCH_FROM_GIT_TAG "${PICO_SDK_FETCH_FROM_GIT_TAG}" CACHE FILEPATH "release tag for SDK") if (NOT PICO_SDK_PATH) if (PICO_SDK_FETCH_FROM_GIT) @@ -29,11 +40,22 @@ if (NOT PICO_SDK_PATH) if (PICO_SDK_FETCH_FROM_GIT_PATH) get_filename_component(FETCHCONTENT_BASE_DIR "${PICO_SDK_FETCH_FROM_GIT_PATH}" REALPATH BASE_DIR "${CMAKE_SOURCE_DIR}") endif () - FetchContent_Declare( - pico_sdk - GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk - GIT_TAG master - ) + # GIT_SUBMODULES_RECURSE was added in 3.17 + if (${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.17.0") + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + GIT_SUBMODULES_RECURSE FALSE + ) + else () + FetchContent_Declare( + pico_sdk + GIT_REPOSITORY https://github.com/raspberrypi/pico-sdk + GIT_TAG ${PICO_SDK_FETCH_FROM_GIT_TAG} + ) + endif () + if (NOT pico_sdk) message("Downloading Raspberry Pi Pico SDK") FetchContent_Populate(pico_sdk) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index fdfe143..e944bdf 100755 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -9,6 +9,7 @@ CONFIG_PARTITION_TABLE_FILENAME="pico-keys-sdk/config/esp32/partitions.csv" CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_WL_SECTOR_SIZE_512=y CONFIG_WL_SECTOR_MODE_PERF=y +COMPILER_OPTIMIZATION="Performance" CONFIG_MBEDTLS_CMAC_C=y CONFIG_MBEDTLS_CHACHA20_C=y diff --git a/src/hsm/cmd_bip_slip.c b/src/hsm/cmd_bip_slip.c index 20f271c..4d034c6 100644 --- a/src/hsm/cmd_bip_slip.c +++ b/src/hsm/cmd_bip_slip.c @@ -38,7 +38,7 @@ int node_derive_bip_child(const mbedtls_ecp_keypair *parent, mbedtls_mpi_init(&kchild); if (i[0] >= 0x80) { if (mbedtls_mpi_cmp_int(&parent->d, 0) == 0) { - return CCID_ERR_NULL_PARAM; + return PICOKEY_ERR_NULL_PARAM; } data[0] = 0x00; mbedtls_mpi_write_binary(&parent->d, data + 1, 32); @@ -72,19 +72,19 @@ int node_derive_bip_child(const mbedtls_ecp_keypair *parent, memcpy(cchild, iR, 32); mbedtls_mpi_free(&il); mbedtls_mpi_free(&kchild); - return CCID_OK; + return PICOKEY_OK; } 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_RIPEMD160), output, 32, output); - return CCID_OK; + return PICOKEY_OK; } 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), output, 32, output); - return CCID_OK; + return PICOKEY_OK; } int node_fingerprint_bip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) { @@ -98,7 +98,7 @@ int node_fingerprint_bip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) { sizeof(buffer)); sha256_ripemd160(buffer, sizeof(buffer), buffer); memcpy(fingerprint, buffer, 4); - return CCID_OK; + return PICOKEY_OK; } int node_fingerprint_slip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) { @@ -106,7 +106,7 @@ int node_fingerprint_slip(mbedtls_ecp_keypair *ctx, uint8_t fingerprint[4]) { mbedtls_mpi_write_binary(&ctx->d, buffer, sizeof(buffer)); sha256_ripemd160(buffer, sizeof(buffer), buffer); memcpy(fingerprint, buffer, 4); - return CCID_OK; + return PICOKEY_OK; } int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32], @@ -115,13 +115,13 @@ int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32], mbedtls_ecp_keypair_init(ctx); file_t *ef = search_file(EF_MASTER_SEED | mid); if (!file_has_data(ef)) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } memcpy(mkey, file_get_data(ef), sizeof(mkey)); int r = mkek_decrypt(mkey + 1, sizeof(mkey) - 1); - if (r != CCID_OK) { - return CCID_EXEC_ERROR; + if (r != PICOKEY_OK) { + return PICOKEY_EXEC_ERROR; } if (mkey[0] == 0x1 || mkey[0] == 0x2) { if (mkey[0] == 0x1) { @@ -131,7 +131,7 @@ 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); } else { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } mbedtls_mpi_read_binary(&ctx->d, mkey + 1, 32); @@ -143,7 +143,7 @@ int load_master_bip(uint16_t mid, mbedtls_ecp_keypair *ctx, uint8_t chain[32], memcpy(chain, mkey + 1, 32); } key_type[0] = mkey[0]; - return CCID_OK; + return PICOKEY_OK; } int node_derive_path(const uint8_t *path, @@ -166,16 +166,16 @@ int node_derive_path(const uint8_t *path, for (; walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data); node++) { if (tag == 0x02) { if ((node == 0 && tag_len != 1) || (node != 0 && tag_len != 4)) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (node == 0) { - if ((r = load_master_bip(tag_data[0], ctx, chain, key_type)) != CCID_OK) { + if ((r = load_master_bip(tag_data[0], ctx, chain, key_type)) != PICOKEY_OK) { return r; } } else if (node > 0) { node_fingerprint_bip(ctx, fingerprint); - if ((r = node_derive_bip_child(ctx, chain, tag_data, ctx, chain)) != CCID_OK) { + if ((r = node_derive_bip_child(ctx, chain, tag_data, ctx, chain)) != PICOKEY_OK) { return r; } memcpy(last_node, tag_data, 4); @@ -183,7 +183,7 @@ int node_derive_path(const uint8_t *path, } else if (tag == 0x04) { if (node == 0) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } else if (node > 0) { node_fingerprint_slip(ctx, fingerprint); @@ -202,7 +202,7 @@ int node_derive_path(const uint8_t *path, if (nodes) { *nodes = node; } - return CCID_OK; + return PICOKEY_OK; } int cmd_bip_slip() { @@ -253,11 +253,11 @@ int cmd_bip_slip() { mkey[0] = p1; file_t *ef = file_new(EF_MASTER_SEED | p2); int r = mkek_encrypt(mkey + 1, sizeof(mkey) - 1); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } r = file_put_data(ef, mkey, sizeof(mkey)); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } low_flash_available(); @@ -271,7 +271,7 @@ int cmd_bip_slip() { size_t olen = 0; int r = node_derive_path(apdu.data, (uint16_t)apdu.nc, &ctx, chain, fgpt, &nodes, last_node, &key_type); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); } @@ -317,7 +317,7 @@ int cmd_bip_slip() { &nodes, last_node, &hd_keytype); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecp_keypair_free(&hd_context); return SW_EXEC_ERROR(); } diff --git a/src/hsm/cmd_change_pin.c b/src/hsm/cmd_change_pin.c index 3af69e0..80a0dd9 100644 --- a/src/hsm/cmd_change_pin.c +++ b/src/hsm/cmd_change_pin.c @@ -42,7 +42,7 @@ int cmd_change_pin() { } uint8_t mkek[MKEK_SIZE]; r = load_mkek(mkek); //loads the MKEK with old pin - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } //encrypt MKEK with new pin @@ -57,7 +57,7 @@ int cmd_change_pin() { } r = store_mkek(mkek); release_mkek(mkek); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } uint8_t dhash[33]; diff --git a/src/hsm/cmd_decrypt_asym.c b/src/hsm/cmd_decrypt_asym.c index e893a23..840bb6c 100644 --- a/src/hsm/cmd_decrypt_asym.c +++ b/src/hsm/cmd_decrypt_asym.c @@ -48,9 +48,9 @@ int cmd_decrypt_asym() { mbedtls_rsa_set_padding(&ctx, MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); } int r = load_private_key_rsa(&ctx, ef); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); - if (r == CCID_VERIFICATION_FAILED) { + if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } return SW_EXEC_ERROR(); @@ -178,7 +178,7 @@ int cmd_decrypt_asym() { if (file_get_size(tf) == kdom_uid.len && memcmp(file_get_data(tf), kdom_uid.data, kdom_uid.len) == 0) { file_new(EF_DKEK + n); - if (store_dkek_key(n, res_APDU + 1) != CCID_OK) { + if (store_dkek_key(n, res_APDU + 1) != PICOKEY_OK) { return SW_EXEC_ERROR(); } mbedtls_platform_zeroize(res_APDU, 32); diff --git a/src/hsm/cmd_delete_file.c b/src/hsm/cmd_delete_file.c index 0919293..1ecbecb 100644 --- a/src/hsm/cmd_delete_file.c +++ b/src/hsm/cmd_delete_file.c @@ -38,7 +38,7 @@ int cmd_delete_file() { if (!authenticate_action(ef, ACL_OP_DELETE_SELF)) { return SW_SECURITY_STATUS_NOT_SATISFIED(); } - if (delete_file(ef) != CCID_OK) { + if (delete_file(ef) != PICOKEY_OK) { return SW_EXEC_ERROR(); } return SW_OK(); diff --git a/src/hsm/cmd_derive_asym.c b/src/hsm/cmd_derive_asym.c index 3d564ee..5d5437e 100644 --- a/src/hsm/cmd_derive_asym.c +++ b/src/hsm/cmd_derive_asym.c @@ -57,9 +57,9 @@ int cmd_derive_asym() { int r; r = load_private_key_ecdsa(&ctx, fkey); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); - if (r == CCID_VERIFICATION_FAILED) { + if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } return SW_EXEC_ERROR(); @@ -88,7 +88,7 @@ int cmd_derive_asym() { return SW_EXEC_ERROR(); } r = store_keys(&ctx, PICO_KEYS_KEY_EC, dest_id); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } diff --git a/src/hsm/cmd_extras.c b/src/hsm/cmd_extras.c index 290318a..f0b6d58 100644 --- a/src/hsm/cmd_extras.c +++ b/src/hsm/cmd_extras.c @@ -28,6 +28,19 @@ #include "kek.h" #include "mbedtls/hkdf.h" #include "mbedtls/chachapoly.h" +#ifdef PICO_RP2350 +#include "otp.h" +#endif + +#define CMD_DATETIME 0xA +#define CMD_DYNOPS 0x6 +#define CMD_SECURE_LOCK 0x3A +#define SECURE_LOCK_KEY_AGREEMENT 0x1 +#define SECURE_LOCK_ENABLE 0x2 +#define SECURE_LOCK_MASK 0x3 +#define SECURE_LOCK_DISABLE 0x4 +#define CMD_PHY 0x1B +#define CMD_OTP 0x4C int cmd_extras() { #ifndef ENABLE_EMULATION @@ -40,7 +53,7 @@ int cmd_extras() { if (wait_button_pressed() == true) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } - if (P1(apdu) == 0xA) { //datetime operations + if (P1(apdu) == CMD_DATETIME) { //datetime operations if (P2(apdu) != 0x0) { return SW_INCORRECT_P1P2(); } @@ -84,7 +97,7 @@ int cmd_extras() { #endif } } - else if (P1(apdu) == 0x6) { //dynamic options + else if (P1(apdu) == CMD_DYNOPS) { //dynamic options if (P2(apdu) != 0x0) { return SW_INCORRECT_P1P2(); } @@ -103,11 +116,11 @@ int cmd_extras() { low_flash_available(); } } - else if (P1(apdu) == 0x3A) { // secure lock + else if (P1(apdu) == CMD_SECURE_LOCK) { // secure lock if (apdu.nc == 0) { return SW_WRONG_LENGTH(); } - if (P2(apdu) == 0x01) { // Key Agreement + if (P2(apdu) == SECURE_LOCK_KEY_AGREEMENT) { // Key Agreement mbedtls_ecdh_context hkey; mbedtls_ecdh_init(&hkey); mbedtls_ecdh_setup(&hkey, MBEDTLS_ECP_DP_SECP256R1); @@ -143,7 +156,7 @@ int cmd_extras() { mse.init = true; res_APDU_size = (uint16_t)olen; } - else if (P2(apdu) == 0x02 || P2(apdu) == 0x03 || P2(apdu) == 0x04) { + else if (P2(apdu) == SECURE_LOCK_ENABLE || P2(apdu) == SECURE_LOCK_MASK || P2(apdu) == SECURE_LOCK_DISABLE) { if (mse.init == false) { return SW_COMMAND_NOT_ALLOWED(); } @@ -152,11 +165,11 @@ int cmd_extras() { if (ret != 0) { return SW_WRONG_DATA(); } - if (P2(apdu) == 0x02 || P2(apdu) == 0x04) { // Enable + if (P2(apdu) == SECURE_LOCK_ENABLE || P2(apdu) == SECURE_LOCK_DISABLE) { // Enable uint16_t opts = get_device_options(); uint8_t newopts[] = { opts >> 8, (opts & 0xff) }; - if ((P2(apdu) == 0x02 && !(opts & HSM_OPT_SECURE_LOCK)) || - (P2(apdu) == 0x04 && (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))) { uint16_t tfids[] = { EF_MKEK, EF_MKEK_SO }; for (int t = 0; t < sizeof(tfids) / sizeof(uint16_t); t++) { file_t *tf = search_file(tfids[t]); @@ -171,24 +184,24 @@ int cmd_extras() { } } } - if (P2(apdu) == 0x02) { + if (P2(apdu) == SECURE_LOCK_ENABLE) { newopts[0] |= HSM_OPT_SECURE_LOCK >> 8; } - else if (P2(apdu) == 0x04) { + else if (P2(apdu) == SECURE_LOCK_DISABLE) { newopts[0] &= ~HSM_OPT_SECURE_LOCK >> 8; } file_t *tf = search_file(EF_DEVOPS); file_put_data(tf, newopts, sizeof(newopts)); low_flash_available(); } - else if (P2(apdu) == 0x03) { + else if (P2(apdu) == SECURE_LOCK_MASK) { memcpy(mkek_mask, apdu.data, apdu.nc); has_mkek_mask = true; } } } #ifndef ENABLE_EMULATION - else if (P1(apdu) == 0x1B) { // Set PHY + else if (P1(apdu) == CMD_PHY) { // Set PHY if (apdu.nc == 0) { if (file_has_data(ef_phy)) { res_APDU_size = file_get_size(ef_phy); @@ -196,50 +209,84 @@ int cmd_extras() { } } else { - uint8_t tmp[PHY_MAX_SIZE]; - memset(tmp, 0, sizeof(tmp)); - uint16_t opts = 0; - if (file_has_data(ef_phy)) { - memcpy(tmp, file_get_data(ef_phy), MIN(sizeof(tmp), file_get_size(ef_phy))); - if (file_get_size(ef_phy) >= 8) { - opts = (tmp[PHY_OPTS] << 8) | tmp[PHY_OPTS + 1]; - } - } - if (P2(apdu) == PHY_VID) { // VIDPID + if (P2(apdu) == PHY_VIDPID) { // VIDPID if (apdu.nc != 4) { return SW_WRONG_LENGTH(); } - memcpy(tmp + PHY_VID, apdu.data, 4); - opts |= PHY_OPT_VPID; + phy_data.vid = (apdu.data[0] << 8) | apdu.data[1]; + phy_data.pid = (apdu.data[2] << 8) | apdu.data[3]; + phy_data.vidpid_present = true; } - else if (P2(apdu) == PHY_LED_GPIO || P2(apdu) == PHY_LED_MODE) { - if (apdu.nc != 1) { - return SW_WRONG_LENGTH(); - } - tmp[P2(apdu)] = apdu.data[0]; - if (P2(apdu) == PHY_LED_GPIO) { - opts |= PHY_OPT_GPIO; - } - else if (P2(apdu) == PHY_LED_MODE) { - opts |= PHY_OPT_LED; - } + 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(); } - uint16_t opt = (apdu.data[0] << 8) | apdu.data[1]; - opts = (opts & ~PHY_OPT_MASK) | (opt & PHY_OPT_MASK); + phy_data.opts = (apdu.data[0] << 8) | apdu.data[1]; } else { return SW_INCORRECT_P1P2(); } - tmp[PHY_OPTS] = opts >> 8; - tmp[PHY_OPTS + 1] = opts & 0xff; - file_put_data(ef_phy, tmp, sizeof(tmp)); + uint8_t tmp[PHY_MAX_SIZE]; + uint16_t tmp_len = 0; + memset(tmp, 0, sizeof(tmp)); + if (phy_serialize_data(&phy_data, tmp, &tmp_len) != PICOKEY_OK) { + return SW_EXEC_ERROR(); + } + file_put_data(ef_phy, tmp, tmp_len); low_flash_available(); } } +#endif +#if PICO_RP2350 + else if (P1(apdu) == CMD_OTP) { + if (apdu.nc < 2) { + return SW_WRONG_LENGTH(); + } + uint16_t row = (apdu.data[0] << 8) | apdu.data[1]; + 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 else { return SW_INCORRECT_P1P2(); diff --git a/src/hsm/cmd_general_authenticate.c b/src/hsm/cmd_general_authenticate.c index eb2b339..6f80464 100644 --- a/src/hsm/cmd_general_authenticate.c +++ b/src/hsm/cmd_general_authenticate.c @@ -47,7 +47,7 @@ int cmd_general_authenticate() { mbedtls_ecdsa_context ectx; mbedtls_ecdsa_init(&ectx); r = load_private_key_ecdsa(&ectx, fkey); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ectx); return SW_EXEC_ERROR(); } @@ -106,7 +106,7 @@ int cmd_general_authenticate() { r = sm_sign(t, pubkey_len + 16, res_APDU + res_APDU_size); free(t); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } res_APDU_size += 8; diff --git a/src/hsm/cmd_initialize.c b/src/hsm/cmd_initialize.c index e7f833c..eb61418 100644 --- a/src/hsm/cmd_initialize.c +++ b/src/hsm/cmd_initialize.c @@ -23,6 +23,7 @@ #include "version.h" #include "asn1.h" #include "cvc.h" +#include "otp.h" extern void scan_all(); @@ -132,10 +133,10 @@ int cmd_initialize() { release_mkek(mkek); return SW_EXEC_ERROR(); } - if (ret_mkek != CCID_OK) { + if (ret_mkek != PICOKEY_OK) { ret_mkek = load_mkek(mkek); //Try again with new PIN/SO-PIN just in case some is the same } - if (store_mkek(ret_mkek == CCID_OK ? mkek : NULL) != CCID_OK) { + if (store_mkek(ret_mkek == PICOKEY_OK ? mkek : NULL) != PICOKEY_OK) { release_mkek(mkek); return SW_EXEC_ERROR(); } @@ -143,31 +144,31 @@ int cmd_initialize() { if (dkeks) { if (*dkeks > 0) { uint16_t d = *dkeks; - if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != CCID_OK) { + if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) { return SW_EXEC_ERROR(); } } else { int r = save_dkek_key(0, random_bytes_get(32)); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } uint16_t d = 0x0101; - if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != CCID_OK) { + if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) { return SW_EXEC_ERROR(); } } } else { uint16_t d = 0x0000; - if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != CCID_OK) { + if (file_put_data(tf_kd, (const uint8_t *) &d, sizeof(d)) != PICOKEY_OK) { return SW_EXEC_ERROR(); } } if (kds) { uint8_t t[MAX_KEY_DOMAINS * 2], k = MIN(*kds, MAX_KEY_DOMAINS); memset(t, 0xff, 2 * k); - if (file_put_data(tf_kd, t, 2 * k) != CCID_OK) { + if (file_put_data(tf_kd, t, 2 * k) != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -179,59 +180,55 @@ int cmd_initialize() { return SW_EXEC_ERROR(); } int ret = 0; - if (ret_mkek != CCID_OK || !file_has_data(fdkey)) { + if (ret_mkek != PICOKEY_OK || !file_has_data(fdkey)) { mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_init(&ecdsa); mbedtls_ecp_group_id ec_id = MBEDTLS_ECP_DP_SECP256R1; - uint8_t index = 0, key_id = 0; - ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_gen, &index); + uint8_t key_id = 0; + if (otp_key_2) { + ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256K1, &ecdsa, otp_key_2, 32); + } + else { + ret = mbedtls_ecdsa_genkey(&ecdsa, ec_id, random_gen, NULL); + } if (ret != 0) { mbedtls_ecdsa_free(&ecdsa); return SW_EXEC_ERROR(); } ret = store_keys(&ecdsa, PICO_KEYS_KEY_EC, key_id); - if (ret != CCID_OK) { + if (ret != PICOKEY_OK) { mbedtls_ecdsa_free(&ecdsa); return SW_EXEC_ERROR(); } - size_t cvc_len = 0; - if ((cvc_len = asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) { + uint16_t ee_len = 0, term_len = 0; + if ((ee_len = asn1_cvc_aut(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, 4096, NULL, 0)) == 0) { mbedtls_ecdsa_free(&ecdsa); return SW_EXEC_ERROR(); } file_t *fpk = search_file(EF_EE_DEV); - ret = file_put_data(fpk, res_APDU, (uint16_t)cvc_len); + ret = file_put_data(fpk, res_APDU, ee_len); if (ret != 0) { mbedtls_ecdsa_free(&ecdsa); return SW_EXEC_ERROR(); } - if ((cvc_len = asn1_cvc_cert(&ecdsa, PICO_KEYS_KEY_EC, res_APDU, 4096, NULL, 0, true)) == 0) { + if ((term_len = asn1_cvc_cert(&ecdsa, PICO_KEYS_KEY_EC, res_APDU + ee_len, 4096 - ee_len, NULL, 0, true)) == 0) { mbedtls_ecdsa_free(&ecdsa); return SW_EXEC_ERROR(); } - memcpy(res_APDU + cvc_len, res_APDU, cvc_len); mbedtls_ecdsa_free(&ecdsa); fpk = search_file(EF_TERMCA); - ret = file_put_data(fpk, res_APDU, (uint16_t)(2 * cvc_len)); + ret = file_put_data(fpk, res_APDU, ee_len + term_len); if (ret != 0) { 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"; - uint16_t prkd_len = asn1_build_prkd_ecc(label, - (uint16_t)strlen((const char *) label), - keyid, - 20, - 256, - res_APDU, - 4096); + uint16_t prkd_len = asn1_build_prkd_ecc(label, (uint16_t)strlen((const char *) label), keyid, 20, 256, res_APDU, 4096); fpk = search_file(EF_PRKD_DEV); ret = file_put_data(fpk, res_APDU, prkd_len); - } if (ret != 0) { return SW_EXEC_ERROR(); diff --git a/src/hsm/cmd_key_domain.c b/src/hsm/cmd_key_domain.c index 3a69e51..b3149e1 100644 --- a/src/hsm/cmd_key_domain.c +++ b/src/hsm/cmd_key_domain.c @@ -72,8 +72,8 @@ int cmd_key_domain() { import_dkek_share(p2, apdu.data); if (++current_dkeks >= dkeks) { int r = save_dkek_key(p2, NULL); - if (r != CCID_OK) { - if (r == CCID_NO_LOGIN) { + if (r != PICOKEY_OK) { + if (r == PICOKEY_NO_LOGIN) { pending_save_dkek = p2; } else { @@ -86,7 +86,7 @@ int cmd_key_domain() { uint8_t t[MAX_KEY_DOMAINS * 2]; memcpy(t, kdata, tf_kd_size); t[2 * p2 + 1] = current_dkeks; - if (file_put_data(tf_kd, t, tf_kd_size) != CCID_OK) { + if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEY_OK) { return SW_EXEC_ERROR(); } low_flash_available(); @@ -129,17 +129,17 @@ int cmd_key_domain() { else if (p1 == 0x4) { t[2 * p2 + 1] = current_dkeks = 0; } - if (file_put_data(tf_kd, t, tf_kd_size) != CCID_OK) { + if (file_put_data(tf_kd, t, tf_kd_size) != PICOKEY_OK) { return SW_EXEC_ERROR(); } file_t *tf = NULL; if ((tf = search_file(EF_DKEK + p2))) { - if (delete_file(tf) != CCID_OK) { + if (delete_file(tf) != PICOKEY_OK) { return SW_EXEC_ERROR(); } } if (p1 == 0x3 && (tf = search_file(EF_XKEK + p2))) { - if (delete_file(tf) != CCID_OK) { + if (delete_file(tf) != PICOKEY_OK) { return SW_EXEC_ERROR(); } } diff --git a/src/hsm/cmd_key_gen.c b/src/hsm/cmd_key_gen.c index 9389cb7..fae498a 100644 --- a/src/hsm/cmd_key_gen.c +++ b/src/hsm/cmd_key_gen.c @@ -56,10 +56,10 @@ int cmd_key_gen() { aes_type = PICO_KEYS_KEY_AES_512; } r = store_keys(aes_key, aes_type, key_id); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } - if (find_and_store_meta_key(key_id) != CCID_OK) { + if (find_and_store_meta_key(key_id) != PICOKEY_OK) { return SW_EXEC_ERROR(); } low_flash_available(); diff --git a/src/hsm/cmd_key_unwrap.c b/src/hsm/cmd_key_unwrap.c index 3c2f5a5..579559c 100644 --- a/src/hsm/cmd_key_unwrap.c +++ b/src/hsm/cmd_key_unwrap.c @@ -51,8 +51,8 @@ int cmd_key_unwrap() { mbedtls_rsa_init(&ctx); do { r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len); - } while ((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); - if (r != CCID_OK) { + } while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -62,7 +62,7 @@ int cmd_key_unwrap() { return SW_EXEC_ERROR(); } mbedtls_rsa_free(&ctx); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -71,8 +71,8 @@ int cmd_key_unwrap() { mbedtls_ecdsa_init(&ctx); do { r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len); - } while ((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); - if (r != CCID_OK) { + } while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -82,7 +82,7 @@ int cmd_key_unwrap() { return SW_EXEC_ERROR(); } mbedtls_ecdsa_free(&ctx); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -97,8 +97,8 @@ int cmd_key_unwrap() { &key_size, &allowed, &allowed_len); - } while ((r == CCID_ERR_FILE_NOT_FOUND || r == CCID_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); - if (r != CCID_OK) { + } while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } if (key_size == 64) { @@ -117,7 +117,7 @@ int cmd_key_unwrap() { return SW_EXEC_ERROR(); } r = store_keys(aes_key, aes_type, key_id); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -136,7 +136,7 @@ int cmd_key_unwrap() { } r = meta_add((KEY_PREFIX << 8) | key_id, meta, meta_len); free(meta); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } } diff --git a/src/hsm/cmd_key_wrap.c b/src/hsm/cmd_key_wrap.c index 1244ed9..3825c72 100644 --- a/src/hsm/cmd_key_wrap.c +++ b/src/hsm/cmd_key_wrap.c @@ -60,9 +60,9 @@ int cmd_key_wrap() { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); r = load_private_key_rsa(&ctx, ef); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); - if (r == CCID_VERIFICATION_FAILED) { + if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } return SW_EXEC_ERROR(); @@ -74,9 +74,9 @@ int cmd_key_wrap() { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); r = load_private_key_ecdsa(&ctx, ef); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); - if (r == CCID_VERIFICATION_FAILED) { + if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } return SW_EXEC_ERROR(); @@ -110,7 +110,7 @@ int cmd_key_wrap() { 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)); } - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } res_APDU_size = wrap_len; diff --git a/src/hsm/cmd_keypair_gen.c b/src/hsm/cmd_keypair_gen.c index c0639c4..8890a90 100644 --- a/src/hsm/cmd_keypair_gen.c +++ b/src/hsm/cmd_keypair_gen.c @@ -63,7 +63,7 @@ int cmd_keypair_gen() { return SW_EXEC_ERROR(); } ret = store_keys(&rsa, PICO_KEYS_KEY_RSA, key_id); - if (ret != CCID_OK) { + if (ret != PICOKEY_OK) { mbedtls_rsa_free(&rsa); return SW_EXEC_ERROR(); } @@ -131,7 +131,7 @@ int cmd_keypair_gen() { } ret = store_keys(&ecdsa, PICO_KEYS_KEY_EC, key_id); mbedtls_ecdsa_free(&ecdsa); - if (ret != CCID_OK) { + if (ret != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -141,7 +141,7 @@ int cmd_keypair_gen() { else { return SW_WRONG_DATA(); } - if (find_and_store_meta_key(key_id) != CCID_OK) { + if (find_and_store_meta_key(key_id) != PICOKEY_OK) { return SW_EXEC_ERROR(); } file_t *fpk = file_new((EE_CERTIFICATE_PREFIX << 8) | key_id); diff --git a/src/hsm/cmd_mse.c b/src/hsm/cmd_mse.c index 1e6a5a4..0d279ff 100644 --- a/src/hsm/cmd_mse.c +++ b/src/hsm/cmd_mse.c @@ -51,7 +51,7 @@ int cmd_mse() { } else { if (p2 == 0xB6) { - if (puk_store_select_chr(tag_data) == CCID_OK) { + if (puk_store_select_chr(tag_data) == PICOKEY_OK) { return SW_OK(); } } diff --git a/src/hsm/cmd_pso.c b/src/hsm/cmd_pso.c index cbaec4d..56caa68 100644 --- a/src/hsm/cmd_pso.c +++ b/src/hsm/cmd_pso.c @@ -40,11 +40,11 @@ int cmd_pso() { apdu.nc += tlv_len; } int r = cvc_verify(apdu.data, (uint16_t)apdu.nc, current_puk->cvcert, current_puk->cvcert_len); - if (r != CCID_OK) { - if (r == CCID_WRONG_DATA) { + if (r != PICOKEY_OK) { + if (r == PICOKEY_WRONG_DATA) { return SW_DATA_INVALID(); } - else if (r == CCID_WRONG_SIGNATURE) { + else if (r == PICOKEY_WRONG_SIGNATURE) { return SW_CONDITIONS_NOT_SATISFIED(); } return SW_EXEC_ERROR(); @@ -56,7 +56,7 @@ int cmd_pso() { ca_ef = file_new(fid); 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), - false) != CCID_OK) { + false) != PICOKEY_OK) { return SW_FILE_FULL(); } diff --git a/src/hsm/cmd_reset_retry.c b/src/hsm/cmd_reset_retry.c index d17dc57..c5679c0 100644 --- a/src/hsm/cmd_reset_retry.c +++ b/src/hsm/cmd_reset_retry.c @@ -59,19 +59,19 @@ int cmd_reset_retry() { 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) != CCID_OK) { + if (pin_reset_retries(file_pin1, true) != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } uint8_t mkek[MKEK_SIZE]; int r = load_mkek(mkek); //loads the MKEK with SO pin - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } hash_multi(apdu.data + (apdu.nc - newpin_len), newpin_len, session_pin); has_session_pin = true; r = store_mkek(mkek); release_mkek(mkek); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } low_flash_available(); @@ -99,7 +99,7 @@ int cmd_reset_retry() { return SW_WRONG_LENGTH(); } } - if (pin_reset_retries(file_pin1, true) != CCID_OK) { + if (pin_reset_retries(file_pin1, true) != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } return SW_OK(); diff --git a/src/hsm/cmd_signature.c b/src/hsm/cmd_signature.c index fc9bf40..69fba07 100644 --- a/src/hsm/cmd_signature.c +++ b/src/hsm/cmd_signature.c @@ -82,17 +82,17 @@ int pkcs1_strip_digest_info_prefix(mbedtls_md_type_t *algorithm, *algorithm = digest_info_prefix[i].algorithm; } if (out_dat == NULL) { - return CCID_OK; + return PICOKEY_OK; } if (*out_len < hash_len) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } memmove(out_dat, in_dat + hdr_len, hash_len); *out_len = hash_len; - return CCID_OK; + return PICOKEY_OK; } } - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } //----- @@ -142,9 +142,9 @@ int cmd_signature() { mbedtls_rsa_init(&ctx); int r = load_private_key_rsa(&ctx, fkey); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); - if (r == CCID_VERIFICATION_FAILED) { + if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } return SW_EXEC_ERROR(); @@ -153,7 +153,7 @@ int cmd_signature() { if (p2 == ALGO_RSA_PKCS1) { //DigestInfo attached uint16_t nc = (uint16_t)apdu.nc; if (pkcs1_strip_digest_info_prefix(&md, apdu.data, (uint16_t)apdu.nc, apdu.data, - &nc) != CCID_OK) { //gets the MD algo id and strips it off + &nc) != PICOKEY_OK) { //gets the MD algo id and strips it off return SW_EXEC_ERROR(); } apdu.nc = nc; @@ -264,9 +264,9 @@ int cmd_signature() { md = MBEDTLS_MD_SHA512; } int r = load_private_key_ecdsa(&ctx, fkey); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); - if (r == CCID_VERIFICATION_FAILED) { + if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } return SW_EXEC_ERROR(); diff --git a/src/hsm/cmd_update_ef.c b/src/hsm/cmd_update_ef.c index 7eba19a..1134666 100644 --- a/src/hsm/cmd_update_ef.c +++ b/src/hsm/cmd_update_ef.c @@ -78,7 +78,7 @@ int cmd_update_ef() { } if (offset == 0) { int r = file_put_data(ef, data, data_len); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } } @@ -92,7 +92,7 @@ int cmd_update_ef() { memcpy(data_merge + offset, data, data_len); int r = file_put_data(ef, data_merge, offset + data_len); free(data_merge); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } } diff --git a/src/hsm/cvc.c b/src/hsm/cvc.c index 30a88a4..f91a043 100644 --- a/src/hsm/cvc.c +++ b/src/hsm/cvc.c @@ -328,7 +328,7 @@ uint16_t asn1_cvc_aut(void *rsa_ecdsa, } mbedtls_ecdsa_context ectx; mbedtls_ecdsa_init(&ectx); - if (load_private_key_ecdsa(&ectx, fkey) != CCID_OK) { + if (load_private_key_ecdsa(&ectx, fkey) != PICOKEY_OK) { mbedtls_ecdsa_free(&ectx); return 0; } @@ -692,12 +692,12 @@ int puk_verify(const uint8_t *sig, uint16_t puk_len = 0; const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len); if (!puk) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } uint16_t oid_len = 0; const uint8_t *oid = cvc_get_field(puk, puk_len, &oid_len, 0x6); if (!oid) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA uint16_t t81_len = 0, t82_len = 0; @@ -706,7 +706,7 @@ int puk_verify(const uint8_t *sig, &t81_len, 0x82); if (!t81 || !t82) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } mbedtls_rsa_context rsa; mbedtls_rsa_init(&rsa); @@ -734,32 +734,32 @@ int puk_verify(const uint8_t *sig, } if (md == MBEDTLS_MD_NONE) { mbedtls_rsa_free(&rsa); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } int r = mbedtls_mpi_read_binary(&rsa.N, t81, t81_len); if (r != 0) { mbedtls_rsa_free(&rsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } r = mbedtls_mpi_read_binary(&rsa.E, t82, t82_len); if (r != 0) { mbedtls_rsa_free(&rsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } r = mbedtls_rsa_complete(&rsa); if (r != 0) { mbedtls_rsa_free(&rsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } r = mbedtls_rsa_check_pubkey(&rsa); if (r != 0) { mbedtls_rsa_free(&rsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } r = mbedtls_rsa_pkcs1_verify(&rsa, md, (unsigned int)hash_len, hash, sig); mbedtls_rsa_free(&rsa); if (r != 0) { - return CCID_WRONG_SIGNATURE; + return PICOKEY_WRONG_SIGNATURE; } } else if (memcmp(oid, OID_ID_TA_ECDSA, 9) == 0) { //ECC @@ -780,34 +780,34 @@ int puk_verify(const uint8_t *sig, md = MBEDTLS_MD_SHA512; } if (md == MBEDTLS_MD_NONE) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } uint16_t t86_len = 0; const uint8_t *t86 = cvc_get_field(puk, puk_len, &t86_len, 0x86); if (!t86) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } mbedtls_ecp_group_id ec_id = cvc_inherite_ec_group(ca, ca_len); if (ec_id == MBEDTLS_ECP_DP_NONE) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_init(&ecdsa); int ret = mbedtls_ecp_group_load(&ecdsa.grp, ec_id); if (ret != 0) { mbedtls_ecdsa_free(&ecdsa); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } ret = mbedtls_ecp_point_read_binary(&ecdsa.grp, &ecdsa.Q, t86, t86_len); if (ret != 0) { mbedtls_ecdsa_free(&ecdsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } ret = mbedtls_ecp_check_pubkey(&ecdsa.grp, &ecdsa.Q); if (ret != 0) { mbedtls_ecdsa_free(&ecdsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } mbedtls_mpi r, s; mbedtls_mpi_init(&r); @@ -817,44 +817,44 @@ int puk_verify(const uint8_t *sig, mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_ecdsa_free(&ecdsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } ret = mbedtls_mpi_read_binary(&s, sig + sig_len / 2, sig_len / 2); if (ret != 0) { mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_ecdsa_free(&ecdsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } ret = mbedtls_ecdsa_verify(&ecdsa.grp, hash, hash_len, &ecdsa.Q, &r, &s); mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); mbedtls_ecdsa_free(&ecdsa); if (ret != 0) { - return CCID_WRONG_SIGNATURE; + return PICOKEY_WRONG_SIGNATURE; } } - return CCID_OK; + return PICOKEY_OK; } int cvc_verify(const uint8_t *cert, uint16_t cert_len, const uint8_t *ca, uint16_t ca_len) { uint16_t puk_len = 0; const uint8_t *puk = cvc_get_pub(ca, ca_len, &puk_len); if (!puk) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } 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 *cv_body = cvc_get_body(cert, cert_len, &cv_body_len); const uint8_t *sig = cvc_get_sig(cert, cert_len, &sig_len); if (!sig) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (!cv_body) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (!oid) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } mbedtls_md_type_t md = MBEDTLS_MD_NONE; if (memcmp(oid, OID_ID_TA_RSA, 9) == 0) { //RSA @@ -895,18 +895,18 @@ int cvc_verify(const uint8_t *cert, uint16_t cert_len, const uint8_t *ca, uint16 } } if (md == MBEDTLS_MD_NONE) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } 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 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); if (r != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } r = puk_verify(sig, sig_len, hash, hash_len, ca, ca_len); if (r != 0) { - return CCID_WRONG_SIGNATURE; + return PICOKEY_WRONG_SIGNATURE; } - return CCID_OK; + return PICOKEY_OK; } diff --git a/src/hsm/kek.c b/src/hsm/kek.c index b1bab61..b22de83 100644 --- a/src/hsm/kek.c +++ b/src/hsm/kek.c @@ -29,6 +29,7 @@ #include "mbedtls/ecdsa.h" #include "mbedtls/chachapoly.h" #include "files.h" +#include "otp.h" extern bool has_session_pin, has_session_sopin; extern uint8_t session_pin[32], session_sopin[32]; @@ -51,7 +52,7 @@ uint32_t crc32c(const uint8_t *buf, size_t len) { int load_mkek(uint8_t *mkek) { if (has_session_pin == false && has_session_sopin == false) { - return CCID_NO_LOGIN; + return PICOKEY_NO_LOGIN; } const uint8_t *pin = NULL; if (pin == NULL && has_session_pin == true) { @@ -69,23 +70,23 @@ int load_mkek(uint8_t *mkek) { } } if (pin == NULL) { //Should never happen - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } - if (has_mkek_mask) { - for (int i = 0; i < MKEK_KEY_SIZE; i++) { - MKEK_KEY(mkek)[i] ^= mkek_mask[i]; - } - } - int ret = - aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE); + int ret = aes_decrypt_cfb_256(pin, MKEK_IV(mkek), MKEK_KEY(mkek), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE); if (ret != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } if (crc32c(MKEK_KEY(mkek), MKEK_KEY_SIZE) != *(uint32_t *) MKEK_CHECKSUM(mkek)) { - return CCID_WRONG_DKEK; + return PICOKEY_WRONG_DKEK; } - return CCID_OK; + if (has_mkek_mask || otp_key_1) { + const uint8_t *mask = otp_key_1 ? otp_key_1 : mkek_mask; + for (int i = 0; i < MKEK_KEY_SIZE; i++) { + MKEK_KEY(mkek)[i] ^= mask[i]; + } + } + return PICOKEY_OK; } mse_t mse = { .init = false }; @@ -94,14 +95,7 @@ int mse_decrypt_ct(uint8_t *data, size_t len) { mbedtls_chachapoly_context chatx; mbedtls_chachapoly_init(&chatx); mbedtls_chachapoly_setkey(&chatx, mse.key_enc + 12); - int ret = mbedtls_chachapoly_auth_decrypt(&chatx, - len - 16, - mse.key_enc, - mse.Qpt, - 65, - data + len - 16, - data, - data); + int ret = mbedtls_chachapoly_auth_decrypt(&chatx, len - 16, mse.key_enc, mse.Qpt, 65, data + len - 16, data, data); mbedtls_chachapoly_free(&chatx); return ret; } @@ -109,7 +103,7 @@ int mse_decrypt_ct(uint8_t *data, size_t len) { int load_dkek(uint8_t id, uint8_t *dkek) { file_t *tf = search_file(EF_DKEK + id); if (!file_has_data(tf)) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE); return mkek_decrypt(dkek, DKEK_KEY_SIZE); @@ -121,7 +115,7 @@ void release_mkek(uint8_t *mkek) { int store_mkek(const uint8_t *mkek) { if (has_session_pin == false && has_session_sopin == false) { - return CCID_NO_LOGIN; + return PICOKEY_NO_LOGIN; } uint8_t tmp_mkek[MKEK_SIZE]; if (mkek == NULL) { @@ -139,12 +133,9 @@ int store_mkek(const uint8_t *mkek) { if (!tf) { release_mkek(tmp_mkek); release_mkek(tmp_mkek_pin); - return CCID_ERR_FILE_NOT_FOUND; + 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); + aes_encrypt_cfb_256(session_pin, MKEK_IV(tmp_mkek_pin), MKEK_KEY(tmp_mkek_pin), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE); file_put_data(tf, tmp_mkek_pin, MKEK_SIZE); release_mkek(tmp_mkek_pin); } @@ -155,32 +146,29 @@ int store_mkek(const uint8_t *mkek) { if (!tf) { release_mkek(tmp_mkek); release_mkek(tmp_mkek_sopin); - return CCID_ERR_FILE_NOT_FOUND; + 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); + aes_encrypt_cfb_256(session_sopin, MKEK_IV(tmp_mkek_sopin), MKEK_KEY(tmp_mkek_sopin), MKEK_KEY_SIZE + MKEK_KEY_CS_SIZE); file_put_data(tf, tmp_mkek_sopin, MKEK_SIZE); release_mkek(tmp_mkek_sopin); } low_flash_available(); release_mkek(tmp_mkek); - return CCID_OK; + return PICOKEY_OK; } int store_dkek_key(uint8_t id, uint8_t *dkek) { file_t *tf = search_file(EF_DKEK + id); if (!tf) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } int r = mkek_encrypt(dkek, DKEK_KEY_SIZE); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } file_put_data(tf, dkek, DKEK_KEY_SIZE); low_flash_available(); - return CCID_OK; + return PICOKEY_OK; } int save_dkek_key(uint8_t id, const uint8_t *key) { @@ -188,7 +176,7 @@ int save_dkek_key(uint8_t id, const uint8_t *key) { if (!key) { file_t *tf = search_file(EF_DKEK + id); if (!tf) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } memcpy(dkek, file_get_data(tf), DKEK_KEY_SIZE); } @@ -202,7 +190,7 @@ int import_dkek_share(uint8_t id, const uint8_t *share) { uint8_t tmp_dkek[DKEK_KEY_SIZE]; file_t *tf = search_file(EF_DKEK + id); if (!tf) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } memset(tmp_dkek, 0, sizeof(tmp_dkek)); if (file_get_size(tf) == DKEK_KEY_SIZE) { @@ -213,7 +201,7 @@ int import_dkek_share(uint8_t id, const uint8_t *share) { } file_put_data(tf, tmp_dkek, DKEK_KEY_SIZE); low_flash_available(); - return CCID_OK; + return PICOKEY_OK; } int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes @@ -221,45 +209,45 @@ int dkek_kcv(uint8_t id, uint8_t *kcv) { //kcv 8 bytes memset(kcv, 0, 8); memset(hsh, 0, sizeof(hsh)); int r = load_dkek(id, dkek); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } hash256(dkek, DKEK_KEY_SIZE, hsh); mbedtls_platform_zeroize(dkek, sizeof(dkek)); memcpy(kcv, hsh, 8); - return CCID_OK; + return PICOKEY_OK; } int dkek_kenc(uint8_t id, uint8_t *kenc) { //kenc 32 bytes uint8_t dkek[DKEK_KEY_SIZE + 4]; memset(kenc, 0, 32); int r = load_dkek(id, dkek); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x1", 4); hash256(dkek, sizeof(dkek), kenc); mbedtls_platform_zeroize(dkek, sizeof(dkek)); - return CCID_OK; + return PICOKEY_OK; } int dkek_kmac(uint8_t id, uint8_t *kmac) { //kmac 32 bytes uint8_t dkek[DKEK_KEY_SIZE + 4]; memset(kmac, 0, 32); int r = load_dkek(id, dkek); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } memcpy(dkek + DKEK_KEY_SIZE, "\x0\x0\x0\x2", 4); hash256(dkek, DKEK_KEY_SIZE + 4, kmac); mbedtls_platform_zeroize(dkek, sizeof(dkek)); - return CCID_OK; + return PICOKEY_OK; } int mkek_encrypt(uint8_t *data, uint16_t len) { int r; uint8_t mkek[MKEK_SIZE + 4]; - if ((r = load_mkek(mkek)) != CCID_OK) { + if ((r = load_mkek(mkek)) != PICOKEY_OK) { return r; } r = aes_encrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len); @@ -270,7 +258,7 @@ int mkek_encrypt(uint8_t *data, uint16_t len) { int mkek_decrypt(uint8_t *data, uint16_t len) { int r; uint8_t mkek[MKEK_SIZE + 4]; - if ((r = load_mkek(mkek)) != CCID_OK) { + if ((r = load_mkek(mkek)) != PICOKEY_OK) { return r; } r = aes_decrypt_cfb_256(MKEK_KEY(mkek), MKEK_IV(mkek), data, len); @@ -278,15 +266,9 @@ int mkek_decrypt(uint8_t *data, uint16_t len) { return r; } -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)) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } uint8_t kb[8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13]; //worst case: RSA-4096 (plus, 13 bytes padding) @@ -298,21 +280,21 @@ int dkek_encode_key(uint8_t id, uint8_t kenc[32]; memset(kenc, 0, sizeof(kenc)); r = dkek_kenc(id, kenc); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } uint8_t kcv[8]; memset(kcv, 0, sizeof(kcv)); r = dkek_kcv(id, kcv); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } uint8_t kmac[32]; memset(kmac, 0, sizeof(kmac)); r = dkek_kmac(id, kmac); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } @@ -331,10 +313,10 @@ int dkek_encode_key(uint8_t id, } if (kb_len != 16 && kb_len != 24 && kb_len != 32 && kb_len != 64) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (*out_len < 8 + 1 + 10 + 6 + (2 + 64 + 14) + 16) { // 14 bytes padding - return CCID_WRONG_LENGTH; + return PICOKEY_WRONG_LENGTH; } put_uint16_t(kb_len, kb + 8); @@ -346,7 +328,7 @@ int dkek_encode_key(uint8_t id, } else if (key_type & PICO_KEYS_KEY_RSA) { if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 4 + 2 * 4096 / 8 + 3 + 13) + 16) { //13 bytes pading - return CCID_WRONG_LENGTH; + return PICOKEY_WRONG_LENGTH; } mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx; kb_len = 0; @@ -367,7 +349,7 @@ int dkek_encode_key(uint8_t id, } else if (key_type & PICO_KEYS_KEY_EC) { if (*out_len < 8 + 1 + 12 + 6 + (8 + 2 * 8 + 9 * 66 + 2 + 4) + 16) { //4 bytes pading - return CCID_WRONG_LENGTH; + return PICOKEY_WRONG_LENGTH; } mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx; kb_len = 0; @@ -386,12 +368,7 @@ int dkek_encode_key(uint8_t id, kb_len += (uint16_t)mbedtls_mpi_size(&ecdsa->grp.N); 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); put_uint16_t((uint16_t)olen, kb + 8 + kb_len); kb_len += 2 + (uint16_t)olen; @@ -399,12 +376,7 @@ int dkek_encode_key(uint8_t id, mbedtls_mpi_write_binary(&ecdsa->d, kb + 8 + kb_len, 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); put_uint16_t((uint16_t)olen, kb + 8 + kb_len); kb_len += 2 + (uint16_t)olen; @@ -458,25 +430,20 @@ int dkek_encode_key(uint8_t id, kb[kb_len] = 0x80; } r = aes_encrypt(kenc, NULL, 256, PICO_KEYS_AES_MODE_CBC, kb, kb_len_pad); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } memcpy(out + *out_len, kb, kb_len_pad); *out_len += kb_len_pad; - r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), - kmac, - 256, - out, - *out_len, - out + *out_len); + r = mbedtls_cipher_cmac(mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_256_ECB), kmac, 256, out, *out_len, out + *out_len); *out_len += 16; if (r != 0) { return r; } - return CCID_OK; + return PICOKEY_OK; } int dkek_type_key(const uint8_t *in) { @@ -492,70 +459,59 @@ int dkek_type_key(const uint8_t *in) { return 0x0; } -int dkek_decode_key(uint8_t id, - void *key_ctx, - const uint8_t *in, - uint16_t in_len, - int *key_size_out, - uint8_t **allowed, - uint16_t *allowed_len) { +int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_len, int *key_size_out, uint8_t **allowed, uint16_t *allowed_len) { uint8_t kcv[8]; int r = 0; memset(kcv, 0, sizeof(kcv)); r = dkek_kcv(id, kcv); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } uint8_t kmac[32]; memset(kmac, 0, sizeof(kmac)); r = dkek_kmac(id, kmac); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } uint8_t kenc[32]; memset(kenc, 0, sizeof(kenc)); r = dkek_kenc(id, kenc); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } if (memcmp(kcv, in, 8) != 0) { - return CCID_WRONG_DKEK; + return PICOKEY_WRONG_DKEK; } 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) { - return CCID_WRONG_SIGNATURE; + return PICOKEY_WRONG_SIGNATURE; } if (memcmp(signature, in + in_len - 16, 16) != 0) { - return CCID_WRONG_SIGNATURE; + return PICOKEY_WRONG_SIGNATURE; } int key_type = in[8]; if (key_type != 5 && key_type != 6 && key_type != 12 && key_type != 15) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if ((key_type == 5 || key_type == 6) && memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x01\x02", 12) != 0) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (key_type == 12 && memcmp(in + 9, "\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03", 12) != 0) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (key_type == 15 && memcmp(in + 9, "\x00\x08\x60\x86\x48\x01\x65\x03\x04\x01", 10) != 0) { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } uint16_t ofs = 9; @@ -579,13 +535,13 @@ int dkek_decode_key(uint8_t id, ofs += len + 2; if ((in_len - 16 - ofs) % 16 != 0) { - return CCID_WRONG_PADDING; + return PICOKEY_WRONG_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)); memcpy(kb, in + ofs, in_len - 16 - ofs); r = aes_decrypt(kenc, NULL, 256, PICO_KEYS_AES_MODE_CBC, kb, in_len - 16 - ofs); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } @@ -602,14 +558,14 @@ int dkek_decode_key(uint8_t id, r = mbedtls_mpi_read_binary(&rsa->D, kb + ofs, len); ofs += len; if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } len = get_uint16_t(kb, ofs); ofs += 2; r = mbedtls_mpi_read_binary(&rsa->N, kb + ofs, len); ofs += len; if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } } else if (key_type == 6) { @@ -623,7 +579,7 @@ int dkek_decode_key(uint8_t id, r = mbedtls_mpi_read_binary(&rsa->P, kb + ofs, len); ofs += len; if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } //PQ @@ -633,7 +589,7 @@ int dkek_decode_key(uint8_t id, r = mbedtls_mpi_read_binary(&rsa->Q, kb + ofs, len); ofs += len; if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } //N len = get_uint16_t(kb, ofs); ofs += len + 2; @@ -643,33 +599,33 @@ int dkek_decode_key(uint8_t id, r = mbedtls_mpi_read_binary(&rsa->E, kb + ofs, len); ofs += len; if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (key_type == 5) { r = mbedtls_rsa_import(rsa, &rsa->N, NULL, NULL, &rsa->D, &rsa->E); if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } } else if (key_type == 6) { r = mbedtls_rsa_import(rsa, NULL, &rsa->P, &rsa->Q, NULL, &rsa->E); if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } } r = mbedtls_rsa_complete(rsa); if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } r = mbedtls_rsa_check_privkey(rsa); if (r != 0) { mbedtls_rsa_free(rsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } } else if (key_type == 12) { @@ -687,7 +643,7 @@ int dkek_decode_key(uint8_t id, mbedtls_ecp_group_id ec_id = ec_get_curve_from_prime(kb + ofs, len); if (ec_id == MBEDTLS_ECP_DP_NONE) { mbedtls_ecdsa_free(ecdsa); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } ofs += len; @@ -702,7 +658,7 @@ int dkek_decode_key(uint8_t id, r = mbedtls_ecp_read_key(ec_id, ecdsa, kb + ofs, len); if (r != 0) { mbedtls_ecdsa_free(ecdsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } ofs += len; @@ -713,17 +669,17 @@ int dkek_decode_key(uint8_t id, r = mbedtls_ecp_mul(&ecdsa->grp, &ecdsa->Q, &ecdsa->d, &ecdsa->grp.G, random_gen, NULL); if (r != 0) { mbedtls_ecdsa_free(ecdsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } } r = mbedtls_ecp_check_pub_priv(ecdsa, ecdsa, random_gen, NULL); if (r != 0) { mbedtls_ecdsa_free(ecdsa); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } } else if (key_type == 15) { memcpy(key_ctx, kb + ofs, key_size); } - return CCID_OK; + return PICOKEY_OK; } diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 5cf89cc..b41ab83 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -43,6 +43,8 @@ bool has_session_pin = false, has_session_sopin = false; const uint8_t *dev_name = NULL; uint16_t dev_name_len = 0; +uint8_t PICO_PRODUCT = 1; + static int sc_hsm_process_apdu(); static void init_sc_hsm(); @@ -85,7 +87,7 @@ int sc_hsm_select_aid(app_t *a, uint8_t force) { a->process_apdu = sc_hsm_process_apdu; a->unload = sc_hsm_unload; init_sc_hsm(); - return CCID_OK; + return PICOKEY_OK; } INITIALIZER( sc_hsm_ctor ) { @@ -178,10 +180,10 @@ uint8_t puk_status[MAX_PUK]; int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy) { if (data == NULL || data_len == 0) { - return CCID_ERR_NULL_PARAM; + return PICOKEY_ERR_NULL_PARAM; } if (puk_store_entries == MAX_PUK_STORE_ENTRIES) { - return CCID_ERR_MEMORY_FATAL; + return PICOKEY_ERR_MEMORY_FATAL; } puk_store[puk_store_entries].copied = copy; @@ -205,17 +207,17 @@ int add_cert_puk_store(const uint8_t *data, uint16_t data_len, bool copy) { &puk_store[puk_store_entries].puk_len); puk_store_entries++; - return CCID_OK; + return PICOKEY_OK; } int puk_store_select_chr(const uint8_t *chr) { for (int i = 0; i < puk_store_entries; i++) { if (memcmp(puk_store[i].chr, chr, puk_store[i].chr_len) == 0) { current_puk = &puk_store[i]; - return CCID_OK; + return PICOKEY_OK; } } - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } void reset_puk_store() { @@ -261,7 +263,7 @@ int sc_hsm_unload() { has_session_pin = has_session_sopin = false; isUserAuthenticated = false; sm_session_pin_len = 0; - return CCID_OK; + return PICOKEY_OK; } uint16_t get_device_options() { @@ -334,16 +336,16 @@ int parse_ef_dir(const file_t *f, int mode) { int pin_reset_retries(const file_t *pin, bool force) { if (!pin) { - return CCID_ERR_NULL_PARAM; + return PICOKEY_ERR_NULL_PARAM; } const file_t *max = search_file(pin->fid + 1); const file_t *act = search_file(pin->fid + 2); if (!max || !act) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } uint8_t retries = file_read_uint8(act); if (retries == 0 && force == false) { // blocked - return CCID_ERR_BLOCKED; + return PICOKEY_ERR_BLOCKED; } retries = file_read_uint8(max); int r = file_put_data((file_t *) act, &retries, sizeof(retries)); @@ -353,26 +355,26 @@ int pin_reset_retries(const file_t *pin, bool force) { int pin_wrong_retry(const file_t *pin) { if (!pin) { - return CCID_ERR_NULL_PARAM; + return PICOKEY_ERR_NULL_PARAM; } const file_t *act = search_file(pin->fid + 2); if (!act) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } uint8_t retries = file_read_uint8(act); if (retries > 0) { retries -= 1; int r = file_put_data((file_t *) act, &retries, sizeof(retries)); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } low_flash_available(); if (retries == 0) { - return CCID_ERR_BLOCKED; + return PICOKEY_ERR_BLOCKED; } return retries; } - return CCID_ERR_BLOCKED; + return PICOKEY_ERR_BLOCKED; } bool pka_enabled() { @@ -391,7 +393,7 @@ uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len) { if (is_secured_apdu() && sm_session_pin_len > 0 && pin == file_pin1) { if (len == sm_session_pin_len && memcmp(data, sm_session_pin, len) != 0) { int retries; - if ((retries = pin_wrong_retry(pin)) < CCID_OK) { + if ((retries = pin_wrong_retry(pin)) < PICOKEY_OK) { return SW_PIN_BLOCKED(); } return set_res_sw(0x63, 0xc0 | (uint8_t)retries); @@ -405,17 +407,17 @@ uint16_t check_pin(const file_t *pin, const uint8_t *data, uint16_t len) { } if (memcmp(file_get_data(pin) + 1, dhash, sizeof(dhash)) != 0) { int retries; - if ((retries = pin_wrong_retry(pin)) < CCID_OK) { + if ((retries = pin_wrong_retry(pin)) < PICOKEY_OK) { return SW_PIN_BLOCKED(); } return set_res_sw(0x63, 0xc0 | (uint8_t)retries); } } int r = pin_reset_retries(pin, false); - if (r == CCID_ERR_BLOCKED) { + if (r == PICOKEY_ERR_BLOCKED) { return SW_PIN_BLOCKED(); } - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } if (pka_enabled() == false) { @@ -552,18 +554,18 @@ int store_keys(void *key_ctx, int type, uint8_t key_id) { memcpy(kdata, key_ctx, key_size); } else { - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } file_t *fpk = file_new((KEY_PREFIX << 8) | key_id); if (!fpk) { - return CCID_ERR_MEMORY_FATAL; + return PICOKEY_ERR_MEMORY_FATAL; } r = mkek_encrypt(kdata, key_size); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } r = file_put_data(fpk, kdata, (uint16_t)key_size); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } char key_id_str[4] = {0}; @@ -580,7 +582,7 @@ int store_keys(void *key_ctx, int type, uint8_t key_id) { } } low_flash_available(); - return CCID_OK; + return PICOKEY_OK; } int find_and_store_meta_key(uint8_t key_id) { @@ -614,81 +616,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); free(meta); if (r != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } } - return CCID_OK; + return PICOKEY_OK; } int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { if (wait_button_pressed() == true) { // timeout - return CCID_VERIFICATION_FAILED; + return PICOKEY_VERIFICATION_FAILED; } uint16_t key_size = file_get_size(fkey); uint8_t kdata[4096 / 8]; memcpy(kdata, file_get_data(fkey), key_size); if (mkek_decrypt(kdata, key_size) != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) { mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (mbedtls_mpi_read_binary(&ctx->Q, kdata + key_size / 2, key_size / 2) != 0) { mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) { mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_rsa_free(ctx); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } if (mbedtls_rsa_import(ctx, NULL, &ctx->P, &ctx->Q, NULL, &ctx->E) != 0) { mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (mbedtls_rsa_complete(ctx) != 0) { mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (mbedtls_rsa_check_privkey(ctx) != 0) { mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } - return CCID_OK; + return PICOKEY_OK; } int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { if (wait_button_pressed() == true) { // timeout - return CCID_VERIFICATION_FAILED; + return PICOKEY_VERIFICATION_FAILED; } uint16_t key_size = file_get_size(fkey); uint8_t kdata[67]; // Worst case, 521 bit + 1byte memcpy(kdata, file_get_data(fkey), key_size); if (mkek_decrypt(kdata, key_size) != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } mbedtls_ecp_group_id gid = kdata[0]; int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1); if (r != 0) { mbedtls_platform_zeroize(kdata, sizeof(kdata)); mbedtls_ecdsa_free(ctx); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } mbedtls_platform_zeroize(kdata, sizeof(kdata)); r = mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL); if (r != 0) { mbedtls_ecdsa_free(ctx); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } - return CCID_OK; + return PICOKEY_OK; } #define INS_VERIFY 0x20 @@ -754,7 +756,7 @@ static const cmd_t cmds[] = { int sc_hsm_process_apdu() { int r = sm_unwrap(); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_DATA_INVALID(); } for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) { diff --git a/tests/scripts/func.sh b/tests/scripts/func.sh index 4a9b324..e081224 100755 --- a/tests/scripts/func.sh +++ b/tests/scripts/func.sh @@ -37,7 +37,7 @@ gen_and_delete() { test $? -eq 0 && echo -n "." || exit $? } reset() { - python3 tools/pico-hsm-tool.py --pin 648219 initialize --so-pin 57621880 --silent > /dev/null 2>&1 + python3 tools/pico-hsm-tool.py --pin 648219 initialize --so-pin 57621880 --silent --no-dev-cert > /dev/null 2>&1 test $? -eq 0 || exit $? } diff --git a/tests/scripts/sc_hsm_test.sh b/tests/scripts/sc_hsm_test.sh index 0885439..4a73ae5 100755 --- a/tests/scripts/sc_hsm_test.sh +++ b/tests/scripts/sc_hsm_test.sh @@ -14,7 +14,7 @@ test $? -eq 0 && echo -n "." || { echo -e "\t${FAIL}" exit 1 } -grep -q "338 tests performed" <<< $e && echo -n "." || { +grep -q "334 tests performed" <<< $e && echo -n "." || { echo -e "\t${FAIL}" exit 1 } diff --git a/tools/pico-hsm-patch-vidpid.sh b/tools/pico-hsm-patch-vidpid.sh deleted file mode 100755 index 3ca4414..0000000 --- a/tools/pico-hsm-patch-vidpid.sh +++ /dev/null @@ -1,94 +0,0 @@ -#!/bin/bash - -# -# 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 . -# - -VERSION_MAJOR="6" #Version of Pico Keys SDK -VERSION_MINOR="0" - -echo "----------------------------" -echo "VID/PID patcher for Pico HSM" -echo "----------------------------" -echo "" - -if [ "$#" -le 0 ]; then - echo "Usage: $0 VID:PID [input_uf2_file] [output_uf2_file]" - exit 1 -fi - -IFS=':' read -r -a ARR <<< "$1" - -if [ ${#ARR[@]} -ne 2 ]; then - echo "ERROR: Specify vendor and product ids as VID:PID (e.g., $0 CAFE:1234)" - exit 1 -fi - -VID=${ARR[0]} -PID=${ARR[1]} - -if [ ${#VID} -ne 4 ]; then - echo "ERROR: VID length must be 4 hexadecimal characters" - exit 1 -fi - -if [ ${#PID} -ne 4 ]; then - echo "ERROR: PID length must be 4 hexadecimal characters" - exit 1 -fi - -if ! [[ $VID =~ ^[0-9A-Fa-f]{1,}$ ]] ; then - echo "ERROR: VID must contain hexadecimal characters" - exit 1 -fi - -if ! [[ $PID =~ ^[0-9A-Fa-f]{1,}$ ]] ; then - echo "ERROR: PID must contain hexadecimal characters" - exit 1 -fi - -UF2_FILE_IF="hsm2040.uf2" -UF2_FILE_OF="$UF2_FILE_IF" - -if [ "$#" -ge 2 ]; then - UF2_FILE_IF="$2" - UF2_FILE_OF="$UF2_FILE_IF" -fi - -if [ "$#" -ge 3 ]; then - UF2_FILE_OF="$3" -fi - - -echo -n "Patching ${UF2_FILE_IF}... " - -if [[ ! -f "$UF2_FILE_IF" ]]; then - echo "ERROR: UF2 file ${UF2_FILE_IF} does not exist" - exit 1 -fi - -if [ "$UF2_FILE_IF" != "$UF2_FILE_OF" ]; then - cp -R $UF2_FILE_IF $UF2_FILE_OF -fi - -LITTLE_VID="\x${VID:2:2}\x${VID:0:2}" -LITTLE_PID="\x${PID:2:2}\x${PID:0:2}" - -perl -pi -e "s/\xff\xfe\xfd\xfc\x$VERSION_MINOR\x$VERSION_MAJOR\x01\x02\x03\x01/$LITTLE_VID$LITTLE_PID\x$VERSION_MINOR\x$VERSION_MAJOR\x01\x02\x03\x01/" $UF2_FILE_OF - -echo "Done!" -echo "" -echo "Patched file was saved in ${UF2_FILE_OF}" diff --git a/tools/pico-hsm-tool.py b/tools/pico-hsm-tool.py index 762481c..be8b8c0 100644 --- a/tools/pico-hsm-tool.py +++ b/tools/pico-hsm-tool.py @@ -57,6 +57,8 @@ from argparse import RawTextHelpFormatter pin = None +BOOTKEY = [225, 209, 107, 167, 100, 171, 215, 18, 212, 239, 110, 62, 221, 116, 78, 213, 99, 140, 38, 11, 119, 28, 249, 129, 81, 17, 11, 175, 172, 155, 200, 113] + def hexy(a): return [hex(i) for i in a] @@ -67,6 +69,7 @@ def parse_args(): parser.add_argument('--pin', help='PIN number') parser_init.add_argument('--so-pin', help='SO-PIN number') parser_init.add_argument('--silent', help='Confirms initialization silently.', action='store_true') + parser_init.add_argument('--no-dev-cert', help='Do not request a device certificate (it will use a self-signed certificate). Do not use if attestation is needed.', action='store_true', default=False) parser_attestate = subparser.add_parser('attestate', help='Generates an attestation report for a private key and verifies the private key was generated in the devices or outside.') parser_attestate.add_argument('-k', '--key', help='The private key index', metavar='KEY_ID') @@ -94,11 +97,15 @@ def parse_args(): parser_phy = subparser.add_parser('phy', help='Set PHY options.') subparser_phy = parser_phy.add_subparsers(title='commands', dest='subcommand', required=True) parser_phy_vp = subparser_phy.add_parser('vidpid', help='Sets VID/PID. Use VID:PID format (e.g. 1234:5678)') - parser_phy_ledn = subparser_phy.add_parser('led', help='Sets LED GPIO number.') + parser_phy_ledn = subparser_phy.add_parser('led_gpio', help='Sets LED GPIO number.') parser_phy_optwcid = subparser_phy.add_parser('wcid', help='Enable/Disable Web CCID interface.') parser_phy_vp.add_argument('value', help='Value of the PHY option.', metavar='VAL', nargs='?') parser_phy_ledn.add_argument('value', help='Value of the PHY option.', metavar='VAL', nargs='?') parser_phy_optwcid.add_argument('value', choices=['enable', 'disable'], help='Enable/Disable Web CCID interface.', nargs='?') + parser_phy_ledbtness = subparser_phy.add_parser('led_brightness', help='Sets LED max. brightness.') + parser_phy_ledbtness.add_argument('value', help='Value of the max. brightness.', metavar='VAL', nargs='?') + parser_phy_optdimm = subparser_phy.add_parser('led_dimmable', help='Enable/Disable LED dimming.') + parser_phy_optdimm.add_argument('value', choices=['enable', 'disable'], help='Enable/Disable LED dimming.', nargs='?') parser_secure = subparser.add_parser('secure', help='Manages security of Pico HSM.') subparser_secure = parser_secure.add_subparsers(title='commands', dest='subcommand', required=True) @@ -131,10 +138,17 @@ def parse_args(): parser_keygen = subparser.add_parser('keygen', help='Generates private keypair or secret key.') subparser_keygen = parser_keygen.add_subparsers(title='commands', dest='subcommand', required=True) parser_keygen_aes = subparser_keygen.add_parser('aes', help='Generates an AES key.') - parser_keygen_aes.add_argument('--size', help='Specifies the size of AES key [128, 192 or 256]',choices=[128, 192, 256], default=128, type=int) + parser_keygen_aes.add_argument('--size', help='Specifies the size of AES key [128, 192 or 256]', choices=[128, 192, 256], default=128, type=int) parser_keygen_x25519 = subparser_keygen.add_parser('x25519', help='Generates a private X25519 keypair.') parser_keygen_x448 = subparser_keygen.add_parser('x448', help='Generates a private X448 keypair.') + parser_otp = subparser.add_parser('otp', help='Read/write OTP values.') + parser_otp.add_argument('subcommand', choices=['read', 'write', 'secure_boot'], help='Read, write or enable Secure Boot', nargs='?') + parser_otp.add_argument('--row', help='OTP row (in HEX)', required='write' in sys.argv or 'read' in sys.argv) + parser_otp.add_argument('-d', '--data', help='Data to write (in HEX) [e.g. 0011223344556677889900AABBCCDDEEFF]', required='write' in sys.argv) + parser_otp.add_argument('--lock', help='Lock & protect (no other firmwares can be loaded)', action='store_true') + parser_otp.add_argument('--index', help='Bootkey index [0-3]', type=int, default=0, choices=[0, 1, 2, 3]) + args = parser.parse_args() return args @@ -204,24 +218,25 @@ def initialize(picohsm, args): so_pin = '57621880' picohsm.initialize(pin=pin, sopin=so_pin) - response = picohsm.get_contents(DOPrefixes.EE_CERTIFICATE_PREFIX, 0x00) + if (not args.no_dev_cert): + response = picohsm.get_contents(DOPrefixes.EE_CERTIFICATE_PREFIX, 0x00) - cert = bytearray(response) - Y = CVC().decode(cert).pubkey().find(0x86).data() - print(f'Public Point: {hexlify(Y).decode()}') + cert = bytearray(response) + Y = CVC().decode(cert).pubkey().find(0x86).data() + print(f'Public Point: {hexlify(Y).decode()}') - pbk = base64.urlsafe_b64encode(Y) - data = urllib.parse.urlencode({'pubkey': pbk}).encode() - j = get_pki_data('cvc', data=data) - print('Device name: '+j['devname']) - dataef = base64.urlsafe_b64decode( - j['cvcert']) + base64.urlsafe_b64decode(j['dvcert']) + base64.urlsafe_b64decode(j['cacert']) + pbk = base64.urlsafe_b64encode(Y) + data = urllib.parse.urlencode({'pubkey': pbk}).encode() + j = get_pki_data('cvc', data=data) + print('Device name: '+j['devname']) + dataef = base64.urlsafe_b64decode( + j['cvcert']) + base64.urlsafe_b64decode(j['dvcert']) + base64.urlsafe_b64decode(j['cacert']) - picohsm.select_file(0x2f02) - response = picohsm.put_contents(0x0000, data=dataef) + picohsm.select_file(0x2f02) + response = picohsm.put_contents(0x0000, data=dataef) - print('Certificate uploaded successfully!') - print('') + print('Certificate uploaded successfully!') + print('') print('Note that the device is initialized with a default PIN and ' 'configuration.') print('Now you can initialize the device as usual with your chosen PIN ' @@ -460,10 +475,15 @@ def phy(picohsm, args): sp = val.split(':') if (len(sp) != 2): print('ERROR: VID/PID have wrong format. Use VID:PID format (e.g. 1234:5678)') + return val = int(sp[0],16).to_bytes(2, 'big') + int(sp[1],16).to_bytes(2, 'big') - elif (args.subcommand == 'led'): + elif (args.subcommand in ['led_gpio', 'led_brightness']): + if (args.subcommand == 'led_brightness'): + if (int(val) > 15 or int(val) < 0): + print('ERROR: LED brightness must be between 0 and 15.') + return val = [int(val)] - elif (args.subcommand == 'wcid'): + elif (args.subcommand in ['wcid', 'led_dimmable']): val = val == 'enable' ret = picohsm.phy(args.subcommand, val) if (ret): @@ -471,8 +491,21 @@ def phy(picohsm, args): else: print('Command executed successfully. Please, restart your Pico Key.') +def otp(picohsm, args): + if (args.subcommand == 'read'): + row = int(args.row, 16) + ret = picohsm.otp(row=row) + print(f'OTP row {args.row}: {hexlify(ret).decode()}') + elif (args.subcommand == 'write'): + row = int(args.row, 16) + data = unhexlify(args.data) + picohsm.otp(row=row, data=data) + print(f'OTP row {args.row} written successfully.') + elif (args.subcommand == 'secure_boot'): + picohsm.secure_boot(BOOTKEY, bootkey_index=args.index, lock=args.lock) + def main(args): - sys.stderr.buffer.write(b'Pico HSM Tool v1.14\n') + sys.stderr.buffer.write(b'Pico HSM Tool v2.0\n') sys.stderr.buffer.write(b'Author: Pol Henarejos\n') sys.stderr.buffer.write(b'Report bugs to https://github.com/polhenarejos/pico-hsm/issues\n') sys.stderr.buffer.write(b'\n\n') @@ -499,7 +532,8 @@ def main(args): keygen(picohsm, args) elif (args.command == 'phy'): phy(picohsm, args) - + elif (args.command == 'otp'): + otp(picohsm, args) def run(): args = parse_args()