32 Commits
v2.2 ... v3.0

Author SHA1 Message Date
Pol Henarejos
4971a22a32 Update README.md
Fix headings
2024-11-10 19:01:10 +01:00
Pol Henarejos
3ed463cc97 Upgrade to version 3.0
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 18:57:19 +01:00
Pol Henarejos
4e6a9eaa4c Update README
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 18:56:55 +01:00
Pol Henarejos
79c69a6617 OTP key is used to mask the DEK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 18:56:46 +01:00
Pol Henarejos
21a9a731aa Upgrade Pico Keys SDK
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 18:14:24 +01:00
Pol Henarejos
9b2b2e822a Add compiler options for optimized build.s
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-09 00:38:39 +01:00
Pol Henarejos
4ba5e04080 Add PICO_PRODUCT.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-09 00:37:19 +01:00
Pol Henarejos
2747083672 Upgrade pico keys sdk.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-09 00:36:21 +01:00
Pol Henarejos
442caa2716 Fix macos alignment.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-10-01 13:29:25 +02:00
Pol Henarejos
e9f0b1b58c Update autobuild for local and esp32.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-10-01 09:33:22 +02:00
Pol Henarejos
f1f6800b60 Fix ESP32 support.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:42:52 +02:00
Pol Henarejos
20b5084eee Fix build
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:42:44 +02:00
Pol Henarejos
57e8d689fc Add sdkdefaults for esp32
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 19:26:26 +02:00
Pol Henarejos
e0779a49e7 Add error if a non-supported key is attempted to be imported.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-30 17:04:34 +02:00
Pol Henarejos
57e7fc38fb Update pico_sdk_import
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-24 00:45:53 +02:00
Pol Henarejos
f301601bcd Upgrade Pico Keys SDK to add support for OTP.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-16 19:41:15 +02:00
Pol Henarejos
3edf9bbf75 Add support for RP2350.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-30 13:33:56 +02:00
Pol Henarejos
cde8968068 Update to latest Pico Keys SDK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-30 13:25:01 +02:00
Pol Henarejos
c0b23a7cb3 Fix write offset.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-26 00:51:40 +02:00
Pol Henarejos
0322967865 Free x509 cert on finish.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 21:17:15 +02:00
Pol Henarejos
e8c62e5867 Use bullseye for tests.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 20:58:26 +02:00
Pol Henarejos
57a6458051 Fix unitialized var.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 20:58:14 +02:00
Pol Henarejos
6780eb3935 Fix select aid to new callback.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 20:57:56 +02:00
Pol Henarejos
ac33f5a026 Add bullseye dockerfile.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-25 20:46:09 +02:00
Pol Henarejos
1051690b79 Add support to ESP32.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-20 00:23:22 +02:00
Pol Henarejos
8a5c734c41 Fix TLV when returning the public key in get metadata.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 17:16:57 +02:00
Pol Henarejos
c09f96e956 Fix return error when missing metadata.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 17:06:58 +02:00
Pol Henarejos
c28852d0ea Fix return metadata for PIN/PUK.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 17:05:35 +02:00
Pol Henarejos
209cd389e5 Fix returning error code when no object is found on GET DATA.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 16:49:39 +02:00
Pol Henarejos
10c3389c51 Fix GET METADATA when ref is CARDMGM.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 16:48:14 +02:00
Pol Henarejos
197bf3c056 Add management support for YKMAN.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-13 16:34:10 +02:00
Pol Henarejos
3a4ca80970 Update VERSION to 2.2 2024-07-16 00:31:34 +02:00
19 changed files with 709 additions and 215 deletions

View File

@@ -35,6 +35,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', 'esp32', 'local' ]
steps:
- name: Checkout repository
@@ -66,7 +67,7 @@ jobs:
- run: |
echo "Run, Build Application using script"
./workflows/autobuild.sh
./workflows/autobuild.sh ${{ matrix.mode }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2

View File

@@ -1,80 +1,98 @@
#
# This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
# Copyright (c) 2022 Pol Henarejos.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
#
# This file is part of the Pico OpenPGP distribution (https://github.com/polhenarejos/pico-openpgp).
# Copyright (c) 2022 Pol Henarejos.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
cmake_minimum_required(VERSION 3.13)
if(ENABLE_EMULATION)
if(ESP_PLATFORM)
set(EXTRA_COMPONENT_DIRS src pico-keys-sdk/src)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
else()
include(pico_sdk_import.cmake)
if(ENABLE_EMULATION)
else()
include(pico_sdk_import.cmake)
endif()
project(pico_openpgp C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
if(ENABLE_EMULATION)
else()
pico_sdk_init()
endif()
add_executable(pico_openpgp)
endif()
project(pico_openpgp C CXX ASM)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
if(ENABLE_EMULATION)
else()
pico_sdk_init()
endif()
add_executable(pico_openpgp)
set(SOURCES ${SOURCES}
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/openpgp.c
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/files.c
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/piv.c
)
${CMAKE_CURRENT_LIST_DIR}/src/openpgp/management.c
)
set(USB_ITF_CCID 1)
set(USB_ITF_WCID 1)
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
if(ESP_PLATFORM)
project(pico_openpgp)
endif()
set(INCLUDES ${INCLUDES}
${CMAKE_CURRENT_LIST_DIR}/src/openpgp
)
set(USB_ITF_CCID 1)
include(pico-keys-sdk/pico_keys_sdk_import.cmake)
target_sources(pico_openpgp PUBLIC ${SOURCES})
target_include_directories(pico_openpgp PUBLIC ${INCLUDES})
target_compile_options(pico_openpgp PUBLIC
-Wall
-Werror
)
if(NOT ESP_PLATFORM)
target_sources(pico_openpgp PUBLIC ${SOURCES})
target_include_directories(pico_openpgp PUBLIC ${INCLUDES})
if(ENABLE_EMULATION)
target_compile_options(pico_openpgp PUBLIC
-fdata-sections
-ffunction-sections
target_compile_options(pico_openpgp PUBLIC
-Wall
)
if(APPLE)
target_link_options(pico_openpgp PUBLIC
-Wl,-dead_strip
)
else()
target_link_options(pico_openpgp PUBLIC
-Wl,--gc-sections
)
endif (APPLE)
else()
if(NOT MSVC)
target_compile_options(pico_openpgp PUBLIC
-Werror
)
endif()
pico_add_extra_outputs(pico_openpgp)
if(ENABLE_EMULATION)
if(NOT MSVC)
target_compile_options(pico_openpgp PUBLIC
-fdata-sections
-ffunction-sections
)
endif()
if(APPLE)
target_link_options(pico_openpgp PUBLIC
-Wl,-dead_strip
)
elseif(MSVC)
target_compile_options(pico_openpgp PUBLIC
-WX
)
#target_compile_definitions(pico_openpgp PRIVATE MBEDTLS_ECDSA_DETERMINISTIC=1)
target_link_libraries(pico_openpgp PRIVATE pico_keys_sdk pico_stdlib tinyusb_device tinyusb_board pico_multicore hardware_flash hardware_sync hardware_adc pico_unique_id hardware_rtc)
target_link_libraries(pico_openpgp PUBLIC wsock32 ws2_32 Bcrypt)
else()
target_link_options(pico_openpgp PUBLIC
-Wl,--gc-sections
)
endif(APPLE)
target_link_libraries(pico_openpgp PRIVATE pthread m)
endif()
endif()

View File

@@ -1,5 +1,5 @@
# Pico OpenPGP
This project aims at transforming your Raspberry Pico into a Smart Card with an OpenPGP applet integrated. The Pico works as a reader with an embedded OpenPGP card, like a USB card.
This project aims at transforming your Raspberry Pico or ESP32 microcontroller into a Smart Card with an OpenPGP applet integrated. The Pico works as a reader with an embedded OpenPGP card, like a USB card.
OpenPGP cards are used to manage PGP keys and do cryptographic operations, such as keypair generation, signing and asymmetric deciphering. Pico OpenPGP follows the [**OpenPGP 3.4.1** specifications](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf "**OpenPGP 3.4.1** specifications"), available at [GnuPG](http://gnupg.org "GnuPG").
@@ -29,6 +29,10 @@ Pico OpenPGP has implemented the following features:
- AES key generation.
- AES ciphering and deciphering.
- Cardholder certificates support.
- Secure Boot and Secure Lock in RP2350 and ESP32-S3 MCUs.
- One Time Programming to store the master key that encrypts all resident keys and seeds.
- Rescue interface to allow recovery of the device if it becomes unresponsive or undetectable.
- LED customization with Pico Commissioner.
All these features are compliant with the specification. Therefore, if you detect some behaviour that is not expected or it does not follow the rules of specs, please open an issue.
@@ -47,44 +51,71 @@ As a consequence, Pico OpenPGP is designed from zero. Well, not strictly from ze
Whilst Gnuk is OpenPGP 2.0 with small set of enhancements, Pico OpenPGP aims at being OpenPGP 3.4 compliant, with new features (not present in Gnuk), such as Manage Security Environment (MSE) or UIF.
## Security considerations
All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico. DEK is used as a 256 bit AES key to protect private and secret keys. Keys are never stored in RAM except for signature and decryption operations and only during the process. All keys (including DEK) are loaded and cleared every time to avoid potential security flaws.
All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico using a Device Encyrption Key (DEK). DEK is a 256 bit AES key used to protect private and secret keys. Keys are never stored in RAM except for signature and decryption operations and only during the process. All keys (including DEK) are loaded and cleared every time to avoid potential security flaws.
At the same time, DEK is encrypted with doubled salted and hashed PIN. Also, the PIN is hashed in memory during the session. Hence, PIN is never stored in plain text neither in flash nor in memory. Note that PIN is conveyed from the host to the Pico in plain text if no secure channel is provided.
At the same time, DEK is encrypted with doubled salted and hashed PIN. For RP2350 and ESP32-S3 microcontrollers it is masked by a secure device 32 bytes key. Also, the PIN is hashed in memory during the session. Hence, PIN is never stored in plain text neither in flash nor in memory. Note that PIN is conveyed from the host to the Pico in plain text if no secure channel is provided.
If the Pico is stolen the contents of private and secret keys cannot be read 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 Device Encryption Key (DEK) 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 DEK 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 devices 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 vendors 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
Please, go to the [Release page](https://github.com/polhenarejos/pico-openpgp/releases "Release page")) and download the UF2 file for your board.
**If you own an ESP32-S3 board, go to [ESP32 Flasher](https://www.picokeys.com/esp32-flasher/) for flashing your Pico OpenPGP.**
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-openpgp/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 are planning to use it with OpenSC or similar, 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.
```
git clone https://github.com/polhenarejos/pico-openpgp
git submodule update --init --recursive
cd pico-openpgp
mkdir build
cd build
PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678
make
```
Note that `PICO_BOARD`, `USB_VID` and `USB_PID` are optional. If not provided, `pico` board and VID/PID `FEFF:FCFD` will be used.
git clone https://github.com/polhenarejos/pico-openpgp
cd pico-openpgp
mkdir build
cd build
PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678
make
Additionally, you can pass the `VIDPID=value` parameter to build the firmware with a known VID/PID. The supported values are:
Note that PICO_BOARD, USB_VID and USB_PID are optional. If not provided, pico board and VID/PID FEFF:FCFD will be used.
- `NitroHSM`
- `NitroFIDO2`
- `NitroStart`
- `NitroPro`
- `Nitro3`
- `Yubikey5`
- `YubikeyNeo`
- `YubiHSM`
- `Gnuk`
- `GnuPG`
After make ends, the binary file pico_openpgp.uf2 will be generated. Put your pico board into loading mode, by pushing BOOTSEL button while pluging on, and copy the UF2 to the new fresh usb mass storage Pico device. Once copied, the pico mass storage will be disconnected automatically and the pico board will reset with the new firmware. A blinking led will indicate the device is ready to work.
After running `make`, the binary file `pico_openpgp.uf2` will be generated. To load this onto your Pico board:
1. Put the Pico board into loading mode by holding the `BOOTSEL` button while plugging it in.
2. Copy the `pico_openpgp.uf2` file to the new USB mass storage device that appears.
3. Once the file is copied, the Pico mass storage device will automatically disconnect, and the Pico board will reset with the new firmware.
4. A blinking LED will indicate that the device is ready to work.
## Operation time
### Keypair generation
Generating EC keys is almost instant. RSA keypair generation takes some time, specially for 3072 and 4096 bits.
### Keypair generation
Generating EC keys is almost instant. RSA keypair generation takes some time, specially for `3072` and `4096` bits.
| RSA key length (bits) | Average time (seconds) |
@@ -135,7 +166,9 @@ Pico OpenPGP relies on PKCS#15 structure to store and manipulate the internal fi
The way to communicate is exactly the same as with other cards, such as OpenPGP or similar.
### 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 must patch the UF2 binary (if you just downloaded from the [Release section](https://github.com/polhenarejos/pico-openpgp/releases "Release section")) or 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.
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 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
Pico OpenPGP uses the following libraries or portion of code:

View File

@@ -1 +1 @@
Version=2.0
Version=2.2

View File

@@ -1,45 +1,93 @@
#!/bin/bash
VERSION_MAJOR="2"
VERSION_MINOR="2"
VERSION_MAJOR="3"
VERSION_MINOR="0"
SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}"
#if ! [[ -z "${GITHUB_SHA}" ]]; then
# SUFFIX="${SUFFIX}.${GITHUB_SHA}"
#fi
rm -rf release/*
mkdir -p build_release
mkdir -p release
cd build_release
for board in adafruit_feather_rp2040 \
for board in 0xcb_helios \
adafruit_feather_rp2040_usb_host \
adafruit_feather_rp2040 \
adafruit_itsybitsy_rp2040 \
adafruit_kb2040 \
adafruit_macropad_rp2040 \
adafruit_qtpy_rp2040 \
adafruit_trinkey_qt2040 \
amethyst_fpga \
archi \
arduino_nano_rp2040_connect \
cytron_maker_pi_rp2040 \
datanoisetv_rp2040_dsp \
eetree_gamekit_rp2040 \
garatronic_pybstick26_rp2040 \
gen4_rp2350_24 \
gen4_rp2350_24ct \
gen4_rp2350_24t \
gen4_rp2350_28 \
gen4_rp2350_28ct \
gen4_rp2350_28t \
gen4_rp2350_32 \
gen4_rp2350_32ct \
gen4_rp2350_32t \
gen4_rp2350_35 \
gen4_rp2350_35ct \
gen4_rp2350_35t \
hellbender_2350A_devboard \
ilabs_challenger_rp2350_bconnect \
ilabs_challenger_rp2350_wifi_ble \
ilabs_opendec02 \
melopero_perpetuo_rp2350_lora \
melopero_shake_rp2040 \
metrotech_xerxes_rp2040 \
net8086_usb_interposer \
nullbits_bit_c_pro \
phyx_rick_tny_rp2350 \
pi-plates_micropi \
pico \
pico_w \
pico2 \
pimoroni_badger2040 \
pimoroni_interstate75 \
pimoroni_keybow2040 \
pimoroni_motor2040 \
pimoroni_pga2040 \
pimoroni_pga2350 \
pimoroni_pico_plus2_rp2350 \
pimoroni_picolipo_4mb \
pimoroni_picolipo_16mb \
pimoroni_picosystem \
pimoroni_plasma2040 \
pimoroni_plasma2350 \
pimoroni_servo2040 \
pimoroni_tiny2040 \
pimoroni_tiny2040_2mb \
pimoroni_tiny2350 \
pololu_3pi_2040_robot \
pololu_zumo_2040_robot \
seeed_xiao_rp2040 \
seeed_xiao_rp2350 \
solderparty_rp2040_stamp \
solderparty_rp2040_stamp_carrier \
solderparty_rp2040_stamp_round_carrier \
solderparty_rp2350_stamp_xl \
solderparty_rp2350_stamp \
sparkfun_micromod \
sparkfun_promicro \
sparkfun_promicro_rp2350 \
sparkfun_thingplus \
switchscience_picossci2_conta_base \
switchscience_picossci2_dev_board \
switchscience_picossci2_micro \
switchscience_picossci2_rp2350_breakout \
switchscience_picossci2_tiny \
tinycircuits_thumby_color_rp2350 \
vgaboard \
waveshare_rp2040_lcd_0.96 \
waveshare_rp2040_lcd_1.28 \
@@ -47,11 +95,14 @@ for board in adafruit_feather_rp2040 \
waveshare_rp2040_plus_4mb \
waveshare_rp2040_plus_16mb \
waveshare_rp2040_zero \
weact_studio_rp2040_2mb \
weact_studio_rp2040_4mb \
weact_studio_rp2040_8mb \
weact_studio_rp2040_16mb \
wiznet_w5100s_evb_pico
do
rm -rf *
PICO_SDK_PATH=../../pico-sdk cmake .. -DPICO_BOARD=$board
make -kj20
mv pico_openpgp.uf2 ../release/pico_openpgp_$board-$VERSION_MAJOR.$VERSION_MINOR.uf2
PICO_SDK_PATH="${PICO_SDK_PATH:-../../pico-sdk}" cmake .. -DPICO_BOARD=$board
make -j`nproc`
mv pico_openpgp.uf2 ../release/pico_openpgp_$board-$SUFFIX.uf2
done

View File

@@ -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)

55
sdkconfig.defaults Normal file
View File

@@ -0,0 +1,55 @@
# This file was generated using idf.py save-defconfig. It can be edited manually.
# Espressif IoT Development Framework (ESP-IDF) Project Minimal Configuration
#
IGNORE_UNKNOWN_FILES_FOR_MANAGED_COMPONENTS=1
CONFIG_TINYUSB=y
CONFIG_PARTITION_TABLE_CUSTOM=y
CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="pico-keys-sdk/config/esp32/partitions.csv"
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
CONFIG_MBEDTLS_POLY1305_C=y
CONFIG_MBEDTLS_CHACHAPOLY_C=y
CONFIG_MBEDTLS_HKDF_C=y
CONFIG_MBEDTLS_HARDWARE_ECC=y
CONFIG_MBEDTLS_HARDWARE_GCM=y
CONFIG_MBEDTLS_DES_C=y
# CONFIG_MBEDTLS_HARDWARE_MPI is not set
CONFIG_MBEDTLS_HARDWARE_SHA=y
CONFIG_MBEDTLS_HARDWARE_AES=y
# CONFIG_MBEDTLS_ROM_MD5 is not set
CONFIG_MBEDTLS_SHA512_C=y
CONFIG_MBEDTLS_TLS_DISABLED=y
# CONFIG_MBEDTLS_TLS_ENABLED is not set
# CONFIG_ESP_TLS_USE_DS_PERIPHERAL is not set
# CONFIG_ESP_WIFI_ENABLED is not set
# CONFIG_ESP_WIFI_MBEDTLS_CRYPTO is not set
# CONFIG_ESP_WIFI_MBEDTLS_TLS_CLIENT is not set
# CONFIG_WPA_MBEDTLS_CRYPTO is not set
# CONFIG_MBEDTLS_PSK_MODES is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_RSA is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA is not set
# CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA is not set
# CONFIG_MBEDTLS_SSL_RENEGOTIATION is not set
# CONFIG_MBEDTLS_SSL_PROTO_TLS1_2 is not set
# CONFIG_MBEDTLS_SSL_PROTO_GMTSSL1_1 is not set
# CONFIG_MBEDTLS_SSL_PROTO_DTLS is not set
# CONFIG_MBEDTLS_SSL_ALPN is not set
# CONFIG_MBEDTLS_CLIENT_SSL_SESSION_TICKETS is not set
# CONFIG_MBEDTLS_SERVER_SSL_SESSION_TICKETS is not set
# CONFIG_ESP32_WIFI_ENABLE_WPA3_SAE is not set
# CONFIG_ESP32_WIFI_ENABLE_WPA3_OWE_STA is not set
# CONFIG_ESP_WIFI_ENABLE_WPA3_SAE is not set
# CONFIG_ESP_WIFI_ENABLE_WPA3_OWE_STA is not set
CONFIG_ESP_COREDUMP_ENABLE_TO_UART=y

View File

@@ -0,0 +1,6 @@
idf_component_register(
SRCS ${SOURCES}
INCLUDE_DIRS . ../../pico-keys-sdk/src ../../pico-keys-sdk/src/fs ../../pico-keys-sdk/src/rng ../../pico-keys-sdk/src/usb
REQUIRES bootloader_support esp_partition esp_tinyusb zorxx__neopixel mbedtls efuse
)
idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON)

View File

@@ -161,4 +161,6 @@
#define EF_PIV_RETIRED19 0xc11f
#define EF_PIV_RETIRED20 0xc120
#define EF_DEV_CONF 0x1122
#endif

153
src/openpgp/management.c Normal file
View File

@@ -0,0 +1,153 @@
/*
* This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "pico_keys.h"
#include "apdu.h"
#include "version.h"
#include "files.h"
#include "asn1.h"
#include "management.h"
int man_process_apdu();
int man_unload();
const uint8_t man_aid[] = {
8,
0xa0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
};
extern void init_piv();
int man_select(app_t *a, uint8_t force) {
(void) force;
a->process_apdu = man_process_apdu;
a->unload = man_unload;
sprintf((char *) res_APDU, "%d.%d.0", PIV_VERSION_MAJOR, PIV_VERSION_MINOR);
res_APDU_size = strlen((char *) res_APDU);
apdu.ne = res_APDU_size;
init_piv();
return PICOKEY_OK;
}
INITIALIZER( man_ctor ) {
register_app(man_select, man_aid);
}
int man_unload() {
return PICOKEY_OK;
}
bool cap_supported(uint16_t cap) {
file_t *ef = search_dynamic_file(EF_DEV_CONF);
if (file_has_data(ef)) {
uint16_t tag = 0x0;
uint8_t *tag_data = NULL, *p = NULL;
uint16_t tag_len = 0;
asn1_ctx_t ctxi;
asn1_ctx_init(file_get_data(ef), file_get_size(ef), &ctxi);
while (walk_tlv(&ctxi, &p, &tag, &tag_len, &tag_data)) {
if (tag == TAG_USB_ENABLED) {
uint16_t ecaps = tag_data[0];
if (tag_len == 2) {
ecaps = (tag_data[0] << 8) | tag_data[1];
}
return ecaps & cap;
}
}
}
return true;
}
int man_get_config() {
file_t *ef = search_dynamic_file(EF_DEV_CONF);
res_APDU_size = 0;
res_APDU[res_APDU_size++] = 0; // Overall length. Filled later
res_APDU[res_APDU_size++] = TAG_USB_SUPPORTED;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = CAP_PIV | CAP_OPENPGP;
res_APDU[res_APDU_size++] = TAG_SERIAL;
res_APDU[res_APDU_size++] = 4;
memcpy(res_APDU + res_APDU_size, pico_serial.id, 4);
res_APDU_size += 4;
res_APDU[res_APDU_size++] = TAG_FORM_FACTOR;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 0x01;
res_APDU[res_APDU_size++] = TAG_VERSION;
res_APDU[res_APDU_size++] = 3;
res_APDU[res_APDU_size++] = PIV_VERSION_MAJOR;
res_APDU[res_APDU_size++] = PIV_VERSION_MINOR;
res_APDU[res_APDU_size++] = 0;
res_APDU[res_APDU_size++] = TAG_NFC_SUPPORTED;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 0x00;
if (!file_has_data(ef)) {
res_APDU[res_APDU_size++] = TAG_USB_ENABLED;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = CAP_PIV | CAP_OPENPGP;
res_APDU[res_APDU_size++] = TAG_DEVICE_FLAGS;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = FLAG_EJECT;
res_APDU[res_APDU_size++] = TAG_CONFIG_LOCK;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 0x00;
res_APDU[res_APDU_size++] = TAG_NFC_ENABLED;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 0x00;
}
else {
memcpy(res_APDU + res_APDU_size, file_get_data(ef), file_get_size(ef));
res_APDU_size += file_get_size(ef);
}
res_APDU[0] = res_APDU_size - 1;
return 0;
}
int cmd_read_config() {
man_get_config();
return SW_OK();
}
int cmd_write_config() {
if (apdu.data[0] != apdu.nc - 1) {
return SW_WRONG_DATA();
}
file_t *ef = file_new(EF_DEV_CONF);
file_put_data(ef, apdu.data + 1, apdu.nc - 1);
low_flash_available();
return SW_OK();
}
#define INS_READ_CONFIG 0x1D
#define INS_WRITE_CONFIG 0x1C
static const cmd_t cmds[] = {
{ INS_READ_CONFIG, cmd_read_config },
{ INS_WRITE_CONFIG, cmd_write_config },
{ 0x00, 0x0 }
};
int man_process_apdu() {
if (CLA(apdu) != 0x00) {
return SW_CLA_NOT_SUPPORTED();
}
for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) {
if (cmd->ins == INS(apdu)) {
int r = cmd->cmd_handler();
return r;
}
}
return SW_INS_NOT_SUPPORTED();
}

55
src/openpgp/management.h Normal file
View File

@@ -0,0 +1,55 @@
/*
* This file is part of the Pico FIDO distribution (https://github.com/polhenarejos/pico-fido).
* Copyright (c) 2022 Pol Henarejos.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _MANAGEMENT_H_
#define _MANAGEMENT_H_
#include <stdlib.h>
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#include "pico/stdlib.h"
#endif
#define TAG_USB_SUPPORTED 0x01
#define TAG_SERIAL 0x02
#define TAG_USB_ENABLED 0x03
#define TAG_FORM_FACTOR 0x04
#define TAG_VERSION 0x05
#define TAG_AUTO_EJECT_TIMEOUT 0x06
#define TAG_CHALRESP_TIMEOUT 0x07
#define TAG_DEVICE_FLAGS 0x08
#define TAG_APP_VERSIONS 0x09
#define TAG_CONFIG_LOCK 0x0A
#define TAG_UNLOCK 0x0B
#define TAG_REBOOT 0x0C
#define TAG_NFC_SUPPORTED 0x0D
#define TAG_NFC_ENABLED 0x0E
#define CAP_OTP 0x01
#define CAP_U2F 0x02
#define CAP_FIDO2 0x200
#define CAP_OATH 0x20
#define CAP_PIV 0x10
#define CAP_OPENPGP 0x08
#define CAP_HSMAUTH 0x100
#define FLAG_REMOTE_WAKEUP 0x40
#define FLAG_EJECT 0x80
extern bool cap_supported(uint16_t cap);
extern int man_get_config();
#endif //_MANAGEMENT_H

View File

@@ -15,7 +15,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ESP_PLATFORM
#include "esp_compat.h"
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#else
#include "common.h"
#endif
#include "openpgp.h"
#include "version.h"
#include "files.h"
@@ -27,6 +32,9 @@
#include "asn1.h"
#include "usb.h"
#include "ccid/ccid.h"
#include "otp.h"
uint8_t PICO_PRODUCT = 3;
bool has_pw1 = false;
bool has_pw2 = false;
@@ -58,7 +66,6 @@ char atr_openpgp[] = {
int openpgp_process_apdu();
extern uint32_t board_button_read(void);
static bool wait_button_pressed(uint16_t fid) {
@@ -166,11 +173,7 @@ void scan_files() {
file_t *ef;
if ((ef = search_by_fid(EF_FULL_AID, NULL, SPECIFY_ANY))) {
ef->data = openpgp_aid_full;
#ifndef ENABLE_EMULATION
pico_get_unique_board_id_string((char *) ef->data + 12, 4);
#else
memset((char *) ef->data + 12, 0, 4);
#endif
memcpy(ef->data + 12, pico_serial.id, 4);
}
bool reset_dek = false;
if ((ef = search_by_fid(EF_DEK, NULL, SPECIFY_ANY))) {
@@ -291,13 +294,13 @@ extern bool has_pwpiv;
extern uint8_t session_pwpiv[32];
int load_dek() {
if (!has_pw1 && !has_pw2 && !has_pw3 && !has_pwpiv) {
return CCID_NO_LOGIN;
return PICOKEY_NO_LOGIN;
}
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
if (!tf) {
return CCID_ERR_FILE_NOT_FOUND;
return PICOKEY_ERR_FILE_NOT_FOUND;
}
int r = CCID_OK;
int r = PICOKEY_OK;
if (has_pw1 || has_pw2) {
memcpy(dek, file_get_data(tf), IV_SIZE + 32);
r = aes_decrypt_cfb_256(session_pw1, dek, dek + IV_SIZE, 32);
@@ -313,9 +316,14 @@ int load_dek() {
r = aes_decrypt_cfb_256(session_pwpiv, dek, dek + IV_SIZE, 32);
}
if (r != 0) {
return CCID_EXEC_ERROR;
return PICOKEY_EXEC_ERROR;
}
return CCID_OK;
if (otp_key_1) {
for (int i = 0; i < 32; i++) {
dek[IV_SIZE + i] ^= otp_key_1[i];
}
}
return PICOKEY_OK;
}
void release_dek() {
@@ -324,7 +332,7 @@ void release_dek() {
int dek_encrypt(uint8_t *data, size_t len) {
int r;
if ((r = load_dek()) != CCID_OK) {
if ((r = load_dek()) != PICOKEY_OK) {
return r;
}
r = aes_encrypt_cfb_256(dek + IV_SIZE, dek, data, len);
@@ -334,7 +342,7 @@ int dek_encrypt(uint8_t *data, size_t len) {
int dek_decrypt(uint8_t *data, size_t len) {
int r;
if ((r = load_dek()) != CCID_OK) {
if ((r = load_dek()) != PICOKEY_OK) {
return r;
}
r = aes_decrypt_cfb_256(dek + IV_SIZE, dek, data, len);
@@ -360,12 +368,12 @@ int openpgp_unload() {
algo_aut = EF_ALGO_PRIV3;
pk_dec = EF_PK_DEC;
pk_aut = EF_PK_AUT;
return CCID_OK;
return PICOKEY_OK;
}
extern char __StackLimit;
int heapLeft() {
#ifndef ENABLE_EMULATION
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
char *p = malloc(256); // try to avoid undue fragmentation
int left = &__StackLimit - p;
free(p);
@@ -375,7 +383,8 @@ int heapLeft() {
return left;
}
int openpgp_select_aid(app_t *a) {
int openpgp_select_aid(app_t *a, uint8_t force) {
(void) force;
a->process_apdu = openpgp_process_apdu;
a->unload = openpgp_unload;
init_openpgp();
@@ -389,10 +398,10 @@ int openpgp_select_aid(app_t *a) {
res_APDU[res_APDU_size++] = ((heap_left >> 0) & 0xff);
res_APDU[1] += 8;
apdu.ne = res_APDU_size;
return CCID_OK;
return PICOKEY_OK;
}
void __attribute__((constructor)) openpgp_ctor() {
INITIALIZER( openpgp_ctor ) {
ccid_atr = (uint8_t *) atr_openpgp;
register_app(openpgp_select_aid, openpgp_aid);
}
@@ -478,32 +487,32 @@ int inc_sig_count() {
}
file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY);
if (!ef || !ef->data) {
return CCID_ERR_FILE_NOT_FOUND;
return PICOKEY_ERR_FILE_NOT_FOUND;
}
uint8_t *p = file_get_data(ef);
uint32_t counter = (p[0] << 16) | (p[1] << 8) | p[2];
counter++;
uint8_t q[3] = { (counter >> 16) & 0xff, (counter >> 8) & 0xff, counter & 0xff };
int r = file_put_data(ef, q, sizeof(q));
if (r != CCID_OK) {
return CCID_EXEC_ERROR;
if (r != PICOKEY_OK) {
return PICOKEY_EXEC_ERROR;
}
low_flash_available();
return CCID_OK;
return PICOKEY_OK;
}
int reset_sig_count() {
file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY);
if (!ef || !ef->data) {
return CCID_ERR_FILE_NOT_FOUND;
return PICOKEY_ERR_FILE_NOT_FOUND;
}
uint8_t q[3] = { 0 };
int r = file_put_data(ef, q, sizeof(q));
if (r != CCID_OK) {
return CCID_EXEC_ERROR;
if (r != PICOKEY_OK) {
return PICOKEY_EXEC_ERROR;
}
low_flash_available();
return CCID_OK;
return PICOKEY_OK;
}
int parse_sec_tpl(const file_t *f, int mode) {
@@ -850,21 +859,21 @@ static int cmd_get_data() {
int pin_reset_retries(const file_t *pin, bool force) {
if (!pin) {
return CCID_ERR_NULL_PARAM;
return PICOKEY_ERR_NULL_PARAM;
}
file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
file_t *pw_retries = search_by_fid(EF_PW_RETRIES, NULL, SPECIFY_EF);
if (!pw_status || !pw_retries) {
return CCID_ERR_FILE_NOT_FOUND;
return PICOKEY_ERR_FILE_NOT_FOUND;
}
if (3 + (pin->fid & 0xf) >= file_get_size(pw_status) || (pin->fid & 0xf) >= file_get_size(pw_retries)) {
return CCID_ERR_MEMORY_FATAL;
return PICOKEY_ERR_MEMORY_FATAL;
}
uint8_t p[64];
memcpy(p, file_get_data(pw_status), file_get_size(pw_status));
uint8_t retries = p[3 + (pin->fid & 0xf)];
if (retries == 0 && force == false) { //blocked
return CCID_ERR_BLOCKED;
return PICOKEY_ERR_BLOCKED;
}
uint8_t max_retries = file_get_data(pw_retries)[(pin->fid & 0xf)];
p[3 + (pin->fid & 0xf)] = max_retries;
@@ -875,27 +884,27 @@ 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;
}
file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF);
if (!pw_status) {
return CCID_ERR_FILE_NOT_FOUND;
return PICOKEY_ERR_FILE_NOT_FOUND;
}
uint8_t p[64];
memcpy(p, file_get_data(pw_status), file_get_size(pw_status));
if (p[3 + (pin->fid & 0xf)] > 0) {
p[3 + (pin->fid & 0xf)] -= 1;
int r = file_put_data(pw_status, p, file_get_size(pw_status));
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return r;
}
low_flash_available();
if (p[3 + (pin->fid & 0xf)] == 0) {
return CCID_ERR_BLOCKED;
return PICOKEY_ERR_BLOCKED;
}
return p[3 + (pin->fid & 0xf)];
}
return CCID_ERR_BLOCKED;
return PICOKEY_ERR_BLOCKED;
}
int check_pin(const file_t *pin, const uint8_t *data, size_t len) {
@@ -915,17 +924,17 @@ int check_pin(const file_t *pin, const uint8_t *data, size_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 | 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();
}
isUserAuthenticated = true;
@@ -1020,7 +1029,7 @@ static int cmd_put_data() {
int r = 0;
if (fid == EF_RC) {
has_rc = false;
if ((r = load_dek()) != CCID_OK) {
if ((r = load_dek()) != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
uint8_t dhash[33];
@@ -1042,7 +1051,7 @@ static int cmd_put_data() {
else {
r = file_put_data(ef, apdu.data, apdu.nc);
}
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_MEMORY_FAILURE();
}
low_flash_available();
@@ -1061,7 +1070,7 @@ static int cmd_change_pin() {
}
uint8_t pin_len = file_get_data(pw)[0];
uint16_t r = 0;
if ((r = load_dek()) != CCID_OK) {
if ((r = load_dek()) != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
r = check_pin(pw, apdu.data, pin_len);
@@ -1077,7 +1086,7 @@ static int cmd_change_pin() {
if (!tf) {
return SW_REFERENCE_NOT_FOUND();
}
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32];
uint8_t def[IV_SIZE + 32 + 32 + 32 + 32] = {0};
memcpy(def, file_get_data(tf), file_get_size(tf));
if (P2(apdu) == 0x81) {
hash_multi(apdu.data + pin_len, apdu.nc - pin_len, session_pw1);
@@ -1129,7 +1138,7 @@ static int cmd_reset_retry() {
newpin_len = apdu.nc;
}
int r = 0;
if ((r = load_dek()) != CCID_OK) {
if ((r = load_dek()) != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF);
@@ -1147,7 +1156,7 @@ static int cmd_reset_retry() {
dhash[0] = newpin_len;
double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1);
file_put_data(pw, dhash, sizeof(dhash));
if (pin_reset_retries(pw, true) != CCID_OK) {
if (pin_reset_retries(pw, true) != PICOKEY_OK) {
return SW_MEMORY_FAILURE();
}
low_flash_available();
@@ -1161,13 +1170,13 @@ int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek) {
uint8_t kdata[4096 / 8]; //worst
//if (!has_pw3)
// return CCID_NO_LOGIN;
// return PICOKEY_NO_LOGIN;
//file_t *pw3 = search_by_fid(EF_PW3, NULL, SPECIFY_EF);
//if (!pw3)
// return CCID_ERR_FILE_NOT_FOUND;
// return PICOKEY_ERR_FILE_NOT_FOUND;
file_t *ef = search_by_fid(key_id, NULL, SPECIFY_EF);
if (!ef) {
return CCID_ERR_FILE_NOT_FOUND;
return PICOKEY_ERR_FILE_NOT_FOUND;
}
if (type == ALGO_RSA) {
mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx;
@@ -1196,19 +1205,19 @@ int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek) {
}
if (use_kek) {
r = dek_encrypt(kdata, key_size);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return r;
}
}
//r = aes_encrypt_cfb_256(file_read(pw3->data+2), session_pw3, kdata, key_size);
//if (r != CCID_OK)
//if (r != PICOKEY_OK)
// return r;
r = file_put_data(ef, kdata, key_size);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return r;
}
low_flash_available();
return CCID_OK;
return PICOKEY_OK;
}
int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek) {
@@ -1216,33 +1225,33 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek) {
uint8_t kdata[4096 / 8];
memcpy(kdata, file_get_data(fkey), key_size);
if (use_dek && dek_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_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_rsa_free(ctx);
return CCID_WRONG_DATA;
return PICOKEY_WRONG_DATA;
}
if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) {
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_rsa_free(ctx);
return CCID_WRONG_DATA;
return PICOKEY_WRONG_DATA;
}
if (mbedtls_rsa_complete(ctx) != 0) {
mbedtls_rsa_free(ctx);
return CCID_WRONG_DATA;
return PICOKEY_WRONG_DATA;
}
if (mbedtls_rsa_check_privkey(ctx) != 0) {
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, bool use_dek) {
@@ -1250,30 +1259,30 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey, bool use_de
uint8_t kdata[67]; //Worst case, 521 bit + 1byte
memcpy(kdata, file_get_data(fkey), key_size);
if (use_dek && dek_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_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;
}
int load_aes_key(uint8_t *aes_key, file_t *fkey) {
int key_size = file_get_size(fkey);
memcpy(aes_key, file_get_data(fkey), key_size);
if (dek_decrypt(aes_key, key_size) != 0) {
return CCID_EXEC_ERROR;
return PICOKEY_EXEC_ERROR;
}
return CCID_OK;
return PICOKEY_OK;
}
mbedtls_ecp_group_id get_ec_group_id_from_attr(const uint8_t *algo, size_t algo_len) {
@@ -1358,7 +1367,7 @@ static int cmd_keypair_gen() {
}
uint16_t fid = 0x0;
int r = CCID_OK;
int r = PICOKEY_OK;
if (apdu.data[0] == 0xB6) {
fid = EF_PK_SIG;
}
@@ -1399,7 +1408,7 @@ static int cmd_keypair_gen() {
r = store_keys(&rsa, ALGO_RSA, fid, true);
make_rsa_response(&rsa);
mbedtls_rsa_free(&rsa);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
@@ -1420,7 +1429,7 @@ static int cmd_keypair_gen() {
r = store_keys(&ecdsa, algo[0], fid, true);
make_ecdsa_response(&ecdsa);
mbedtls_ecdsa_free(&ecdsa);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
@@ -1432,7 +1441,7 @@ static int cmd_keypair_gen() {
return SW_REFERENCE_NOT_FOUND();
}
r = file_put_data(pbef, res_APDU, res_APDU_size);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
if (fid == EF_PK_SIG) {
@@ -1446,7 +1455,7 @@ static int cmd_keypair_gen() {
memcpy(aes_key, random_bytes_get(key_size), key_size);
r = store_keys(aes_key, ALGO_AES_256, EF_AES_KEY, true);
/* if storing the key fails, we silently continue */
//if (r != CCID_OK)
//if (r != PICOKEY_OK)
// return SW_EXEC_ERROR();
}
low_flash_available();
@@ -1595,19 +1604,19 @@ static int cmd_pso() {
if (wait_button_pressed(pk_fid == EF_PK_SIG ? EF_UIF_SIG : EF_UIF_DEC) == true) {
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
int r = CCID_OK;
int r = PICOKEY_OK;
int key_size = file_get_size(ef);
if (is_aes) {
uint8_t aes_key[32];
r = load_aes_key(aes_key, ef);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
memset(aes_key, 0, sizeof(aes_key));
return SW_EXEC_ERROR();
}
if (P1(apdu) == 0x80 && P2(apdu) == 0x86) { //decipher
r = aes_decrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data + 1, apdu.nc - 1);
memset(aes_key, 0, sizeof(aes_key));
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
memcpy(res_APDU, apdu.data + 1, apdu.nc - 1);
@@ -1616,7 +1625,7 @@ static int cmd_pso() {
else if (P1(apdu) == 0x86 && P2(apdu) == 0x80) { //encipher
r = aes_encrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data, apdu.nc);
memset(aes_key, 0, sizeof(aes_key));
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
res_APDU[0] = 0x2;
@@ -1629,7 +1638,7 @@ static int cmd_pso() {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef, true);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1668,7 +1677,7 @@ static int cmd_pso() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef, true);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1793,12 +1802,12 @@ static int cmd_internal_aut() {
if (wait_button_pressed(EF_UIF_AUT) == true) {
return SW_SECURE_MESSAGE_EXEC_ERROR();
}
int r = CCID_OK;
int r = PICOKEY_OK;
if (algo[0] == ALGO_RSA) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef, true);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1814,7 +1823,7 @@ static int cmd_internal_aut() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef, true);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1987,7 +1996,7 @@ static int cmd_import_data() {
r = store_keys(&rsa, ALGO_RSA, fid, true);
make_rsa_response(&rsa);
mbedtls_rsa_free(&rsa);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
@@ -2020,10 +2029,13 @@ static int cmd_import_data() {
r = store_keys(&ecdsa, ALGO_ECDSA, fid, true);
make_ecdsa_response(&ecdsa);
mbedtls_ecdsa_free(&ecdsa);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
else {
return SW_FUNC_NOT_SUPPORTED();
}
if (fid == EF_PK_SIG) {
reset_sig_count();
}
@@ -2032,7 +2044,7 @@ static int cmd_import_data() {
return SW_REFERENCE_NOT_FOUND();
}
r = file_put_data(pbef, res_APDU, res_APDU_size);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
res_APDU_size = 0; //make_*_response sets a response. we need to overwrite

View File

@@ -19,7 +19,7 @@
#define __OPENPGP_H_
#include "stdlib.h"
#ifndef ENABLE_EMULATION
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
#include <pico/stdlib.h>
#endif

View File

@@ -15,7 +15,12 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef ESP_PLATFORM
#include "esp_compat.h"
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#else
#include "common.h"
#endif
#include "files.h"
#include "apdu.h"
#include "pico_keys.h"
@@ -23,9 +28,6 @@
#include "eac.h"
#include "crypto_utils.h"
#include "version.h"
#ifndef ENABLE_EMULATION
#include "pico/unique_id.h"
#endif
#include "asn1.h"
#include "mbedtls/aes.h"
#include "mbedtls/des.h"
@@ -70,10 +72,6 @@ uint8_t yk_aid[] = {
8,
0xA0, 0x00, 0x00, 0x05, 0x27, 0x20, 0x1, 0x1
};
uint8_t mgmt_aid[] = {
8,
0xA0, 0x00, 0x00, 0x05, 0x27, 0x47, 0x11, 0x17
};
bool has_pwpiv = false;
uint8_t session_pwpiv[32];
@@ -81,14 +79,8 @@ uint8_t session_pwpiv[32];
int piv_process_apdu();
static int get_serial() {
#ifndef ENABLE_EMULATION
pico_unique_board_id_t unique_id;
pico_get_unique_board_id(&unique_id);
uint32_t serial = (unique_id.id[0] & 0x7F) << 24 | unique_id.id[1] << 16 | unique_id.id[2] << 8 | unique_id.id[3];
uint32_t serial = (pico_serial.id[0] & 0x7F) << 24 | pico_serial.id[1] << 16 | pico_serial.id[2] << 8 | pico_serial.id[3];
return serial;
#else
return 0;
#endif
}
static int x509_create_cert(void *pk_ctx, uint8_t algo, uint8_t slot, bool attestation, uint8_t *buffer, size_t buffer_size) {
@@ -169,6 +161,7 @@ static int x509_create_cert(void *pk_ctx, uint8_t algo, uint8_t slot, bool attes
if (attestation) {
mbedtls_ecdsa_free(&actx);
}
mbedtls_x509write_crt_free(&ctx);
return ret;
}
@@ -277,7 +270,7 @@ void init_piv() {
}
int piv_unload() {
return CCID_OK;
return PICOKEY_OK;
}
void select_piv_aid() {
@@ -307,18 +300,18 @@ void select_piv_aid() {
res_APDU[res_APDU_size++] = 0x00;
}
int piv_select_aid(app_t *a) {
int piv_select_aid(app_t *a, uint8_t force) {
(void) force;
a->process_apdu = piv_process_apdu;
a->unload = piv_unload;
init_piv();
select_piv_aid();
return CCID_OK;
return PICOKEY_OK;
}
void __attribute__((constructor)) piv_ctor() {
INITIALIZER( piv_ctor ) {
register_app(piv_select_aid, piv_aid);
register_app(piv_select_aid, yk_aid);
register_app(piv_select_aid, mgmt_aid);
}
static int cmd_version() {
@@ -404,7 +397,7 @@ static int cmd_get_data() {
fid |= apdu.data[2 + lt];
}
if ((fid & 0xFFFF00) != 0x5FC100 && (fid & 0xFFFF) != EF_PIV_BITGT && (fid & 0xFFFF) != EF_PIV_DISCOVERY && (fid & 0xFFFF) != EF_PIV_ATTESTATION) {
return SW_REFERENCE_NOT_FOUND();
return SW_FILE_NOT_FOUND();
}
file_t *ef = NULL;
if ((ef = search_by_fid((uint16_t)(fid & 0xFFFF), NULL, SPECIFY_EF))) {
@@ -451,7 +444,7 @@ static int cmd_get_metadata() {
}
file_t *ef_key = search_by_fid(key_ref, NULL, SPECIFY_EF);
if (!file_has_data(ef_key)) {
return SW_MEMORY_FAILURE();
return SW_REFERENCE_NOT_FOUND();
}
if (key_ref != EF_PIV_PIN && key_ref != EF_PIV_PUK) {
int meta_len = 0;
@@ -470,11 +463,13 @@ static int cmd_get_metadata() {
res_APDU[res_APDU_size++] = meta[3];
if (meta[0] == PIV_ALGO_RSA1024 || meta[0] == PIV_ALGO_RSA2048 || meta[0] == PIV_ALGO_RSA3072 || meta[0] == PIV_ALGO_RSA4096 || meta[0] == PIV_ALGO_ECCP256 || meta[0] == PIV_ALGO_ECCP384) {
res_APDU[res_APDU_size++] = 0x4;
res_APDU[res_APDU_size++] = 0; // Filled later
uint8_t *pk = &res_APDU[res_APDU_size];
if (meta[0] == PIV_ALGO_RSA1024 || meta[0] == PIV_ALGO_RSA2048 || meta[0] == PIV_ALGO_RSA3072 || meta[0] == PIV_ALGO_RSA4096) {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
int r = load_private_key_rsa(&ctx, ef_key, false);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -493,7 +488,7 @@ static int cmd_get_metadata() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
int r = load_private_key_ecdsa(&ctx, ef_key, false);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -509,9 +504,26 @@ static int cmd_get_metadata() {
memcpy(res_APDU + res_APDU_size, pt, plen);
res_APDU_size += plen;
}
uint16_t pk_len = res_APDU_size - (pk - res_APDU);
if (pk_len > 255) {
memmove(pk + 2, pk, pk_len);
pk[-1] = 0x82;
pk[0] = pk_len >> 8;
pk[1] = pk_len & 0xff;
res_APDU_size += 2;
}
else if (pk_len > 127) {
memmove(pk + 1, pk, pk_len);
pk[-1] = 0x81;
pk[0] = pk_len;
res_APDU_size += 1;
}
else {
pk[-1] = pk_len;
}
}
}
if (key_ref == EF_PIV_PIN || key_ref == EF_PIV_PUK || key_ref == EF_PIV_KEY_MANAGEMENT) {
if (key_ref == EF_PIV_PIN || key_ref == EF_PIV_PUK || key_ref == EF_PIV_KEY_CARDMGM) {
uint8_t dhash[32];
int32_t eq = false;
if (key_ref == EF_PIV_PIN) {
@@ -522,7 +534,7 @@ static int cmd_get_metadata() {
double_hash_pin((const uint8_t *)"\x31\x32\x33\x34\x35\x36\x37\x38", 8, dhash);
eq = memcmp(dhash, file_get_data(ef_key) + 1, file_get_size(ef_key) - 1);
}
else if (key_ref == EF_PIV_KEY_MANAGEMENT) {
else if (key_ref == EF_PIV_KEY_CARDMGM) {
eq = memcmp("\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08\x01\x02\x03\x04\x05\x06\x07\x08", file_get_data(ef_key), file_get_size(ef_key));
}
res_APDU[res_APDU_size++] = 0x5;
@@ -534,8 +546,13 @@ static int cmd_get_metadata() {
return SW_REFERENCE_NOT_FOUND();
}
uint8_t retries = *(file_get_data(pw_status) + 3 + (key_ref & 0xf));
if (!(pw_status = search_by_fid(EF_PW_RETRIES, NULL, SPECIFY_EF))) {
return SW_REFERENCE_NOT_FOUND();
}
uint8_t total = *(file_get_data(pw_status) + (key_ref & 0xf));
res_APDU[res_APDU_size++] = 0x6;
res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = 2;
res_APDU[res_APDU_size++] = total;
res_APDU[res_APDU_size++] = retries;
}
}
@@ -673,7 +690,7 @@ static int cmd_authenticate() {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
int r = load_private_key_rsa(&ctx, ef_key, false);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -707,7 +724,7 @@ static int cmd_authenticate() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
int r = load_private_key_ecdsa(&ctx, ef_key, false);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -888,7 +905,7 @@ static int cmd_asym_keygen() {
file_put_data(ef, cert + sizeof(cert) - r, r);
r = store_keys(&rsa, ALGO_RSA, key_ref == 0x93 ? EF_PIV_KEY_RETIRED18 : key_ref, false);
mbedtls_rsa_free(&rsa);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
@@ -909,7 +926,7 @@ static int cmd_asym_keygen() {
file_put_data(ef, cert + sizeof(cert) - r, r);
r = store_keys(&ecdsa, ALGO_ECDSA, key_ref == 0x93 ? EF_PIV_KEY_RETIRED18 : key_ref, false);
mbedtls_ecdsa_free(&ecdsa);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
return SW_EXEC_ERROR();
}
}
@@ -1138,7 +1155,7 @@ static int cmd_attestation() {
mbedtls_rsa_context ctx;
mbedtls_rsa_init(&ctx);
r = load_private_key_rsa(&ctx, ef_key, false);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_rsa_free(&ctx);
return SW_EXEC_ERROR();
}
@@ -1149,7 +1166,7 @@ static int cmd_attestation() {
mbedtls_ecdsa_context ctx;
mbedtls_ecdsa_init(&ctx);
r = load_private_key_ecdsa(&ctx, ef_key, false);
if (r != CCID_OK) {
if (r != PICOKEY_OK) {
mbedtls_ecdsa_free(&ctx);
return SW_EXEC_ERROR();
}

View File

@@ -24,7 +24,7 @@
#define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff)
#define PIPGP_VERSION 0x0202
#define PIPGP_VERSION 0x0300
#define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff)
#define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff)

View File

@@ -0,0 +1,43 @@
FROM debian:bullseye
ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y
RUN apt install -y apt-utils
RUN apt autoremove -y
RUN rm -rf /var/cache/apt/archives/*
RUN apt install -y libccid \
libpcsclite-dev \
git \
autoconf \
pkg-config \
libtool \
help2man \
automake \
gcc \
make \
build-essential \
opensc \
python3 \
python3-pip \
swig \
cmake \
vsmartcard-vpcd \
libgcrypt-dev \
libssl-dev \
check \
gengetopt \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install pytest pycvc cryptography pyscard
RUN git clone https://github.com/Yubico/yubico-piv-tool
WORKDIR /yubico-piv-tool
RUN git checkout tags/yubico-piv-tool-2.5.1
ADD tests/docker/jammy/yubico-piv-tool.patch /yubico-piv-tool/yubico-piv-tool.patch
RUN git apply yubico-piv-tool.patch
RUN mkdir build
WORKDIR /yubico-piv-tool/build
RUN cmake .. -DENABLE_HARDWARE_TESTS=1
RUN make -j`nproc`
RUN make install
WORKDIR /
RUN ldconfig

View File

@@ -46,7 +46,7 @@
# default values, can be overridden by the environment
: ${MBEDTLS_DOCKER_GUEST:=jammy}
: ${MBEDTLS_DOCKER_GUEST:=bullseye}
DOCKER_IMAGE_TAG="pico-openpgp-test:${MBEDTLS_DOCKER_GUEST}"

View File

@@ -2,12 +2,38 @@
git submodule update --init --recursive
sudo apt update
if [[ $1 == "pico" ]]; then
sudo apt install -y cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib
git clone https://github.com/raspberrypi/pico-sdk
cd pico-sdk
git submodule update --init
cd ..
git clone https://github.com/raspberrypi/picotool
cd picotool
git submodule update --init
mkdir build
cd build
cmake -DPICO_SDK_PATH=../../pico-sdk ..
make -j`nproc`
sudo make install
cd ../..
mkdir build_pico
cd build_pico
cmake -DPICO_SDK_PATH=../pico-sdk ..
make
elif [[ $1 == "esp32" ]]; then
sudo apt install -y git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf
./install.sh esp32s3
. ./export.sh
cd ..
idf.py set-target esp32s3
idf.py all
else
mkdir build
cd build
cmake -DENABLE_EMULATION=1 ..
make
fi