95 Commits
v6.2 ... v6.6

Author SHA1 Message Date
Pol Henarejos
cfe1321d62 Upgrade to v6.6
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-10 18:37:48 +02:00
Pol Henarejos
2cbea57c86 Update build script to automatize EdDSA builds.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-10 18:37:09 +02:00
Pol Henarejos
b6bf2e6c66 Do not update CFG_FLAGS if slot is ChalResp.
Fixes #142

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-10 16:23:20 +02:00
Pol Henarejos
3212f95915 Fixes update OTP when LT_CHAL is enabled.
Fixes #141.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-08 18:59:50 +02:00
Pol Henarejos
21b12a7bff Define MCU for emulation.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-08 18:58:49 +02:00
Pol Henarejos
c8dbc213a0 Fix EPNUM counting for ESP32. It fixes the problem of not sending KB.
Fixes #130 #138.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-04-06 18:32:33 +02:00
Pol Henarejos
0a2ee6523f Build all boards with secure boot pkey.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-31 00:53:44 +02:00
Pol Henarejos
c3ea413592 Do not return extensions if they are not requested OR are false.
Fixes #136

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-30 19:32:25 +02:00
Pol Henarejos
64f371e6e5 Despite it is described in the spec 2.1, do not return epAtt if is false, return only when it's true. It fixes a bug with Firefox and Linux that blocked the possibility to make credentials.
Fixes #129.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-30 18:13:58 +02:00
Pol Henarejos
fdd4afb993 CTAP_RESP should be 0ed before sending.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-30 18:12:18 +02:00
Pol Henarejos
fef46dc1c5 OATH Rename requires security validation.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-23 23:55:50 +01:00
Pol Henarejos
23a45ac297 Rename returns error if new credential name is equal to previous.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-23 23:51:21 +01:00
Pol Henarejos
b152ff15a8 Fix challenge length calculation for LT64.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-23 23:27:52 +01:00
Pol Henarejos
751fcf0538 Fix HMAC-SHA1 calculation.
Fixes #127.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-23 23:13:21 +01:00
Pol Henarejos
4e4c28a479 Fix CONFIG_TOUCH status report.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-23 22:44:35 +01:00
Pol Henarejos
23b60beb2e When OTP interface is disabled, it also disables KEYBOARD interface to avoid incompatibilities with smart phones.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-22 23:26:19 +01:00
Pol Henarejos
37d7d7faeb OTP can flow through FIDO interface as a report type 3.
Fixes #123.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-19 19:05:06 +01:00
Pol Henarejos
49c0179ccf Fix swap files.
When a dynamic file is deleted, all scoped references to other dynamic files are invalidated.

Fixes #124

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-19 13:33:35 +01:00
Pol Henarejos
eacb8a040c Increase config_seq on swap and update.
Fixes #124.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-19 11:07:02 +01:00
Pol Henarejos
cb99b8f401 Fix emulation build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-19 01:28:07 +01:00
Pol Henarejos
94f8d5f65f Add support for Require Touch in ChalResp OTP slots.
Fixes #123 #104

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-19 01:22:14 +01:00
Pol Henarejos
38d332f450 Restore led mode when finishing button press.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-19 01:19:24 +01:00
Pol Henarejos
c67f5e3a1f Fix Pico Commissioner when new fields are added. It breaks backward compatibility but ensures forward.
Fixes #118.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-17 11:39:27 +01:00
Pol Henarejos
bfb8a4cb20 Only send secp256k1 if explicitly enabled.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-11 19:28:22 +01:00
Pol Henarejos
0f5a24c9b6 Fix encoding get info with variable curves.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-11 19:19:28 +01:00
Pol Henarejos
dd207bd031 Fix emulation build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-11 19:11:49 +01:00
Pol Henarejos
6069cf949b ES256K1 is disabled by default for compatibility. It can be enabled via Pico Commissioner.
Fixes #109.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-11 19:05:28 +01:00
Pol Henarejos
297c34914b Do not report EDDSA on get info if not supported.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-11 15:19:49 +01:00
Pol Henarejos
529a12e7a3 Only pin to core in ESP32-S3 since it is multicore.
Fixes #100

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-03-07 19:37:06 +01:00
Pol Henarejos
bdbdd92be8 Enable alwaysUv if pin is set and alwaysUv is a device options or there's current Uv in memory. It will force the prompt of a PIN.
Fixes #113.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-24 12:02:03 +01:00
Pol Henarejos
3807e23914 Fix silent authentication with resident keys.
It requires a new silent format, so silent credentials must be reissued.

Related with #113.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-23 22:03:06 +01:00
Pol Henarejos
ce7d3ea72f Silent credential shall be mixed with RP.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-23 20:22:47 +01:00
Pol Henarejos
eb857df3e1 Fix build name.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-23 00:56:27 +01:00
Pol Henarejos
2842944d90 Fix commissioned values for LED.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-23 00:49:56 +01:00
Pol Henarejos
7be92f5331 Fix autobuild.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 19:57:08 +01:00
Pol Henarejos
403b26b60a Build EDDSA tests by default.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 19:07:10 +01:00
Pol Henarejos
b91ece8ec3 Add EDDSA support as a conditional build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 19:00:44 +01:00
Pol Henarejos
d54bc1b0f3 Fix ESP32 build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 18:59:44 +01:00
Pol Henarejos
e2dbbe2cc3 Merge branch 'eddsa' into development 2025-02-21 18:11:43 +01:00
Pol Henarejos
8aa9d1c5a3 Fix cyw43 build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 17:28:39 +01:00
Pol Henarejos
2d2814cefc Fix emulation build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 17:08:37 +01:00
Pol Henarejos
89a9d013f0 Build cyw43 driver with RP2350.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-21 17:02:26 +01:00
Pol Henarejos
964184cd9f Upgrade to v6.4
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 20:15:06 +01:00
Pol Henarejos
3969fd5136 Upgrade to v6.4
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 15:15:16 +01:00
Pol Henarejos
01b197d8ec Fix led driver build for Pimoroni.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 15:14:42 +01:00
Pol Henarejos
8f7b52a387 Fix rename board name.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 14:34:18 +01:00
Pol Henarejos
565ceb7dc4 Take led_driver on build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 14:33:37 +01:00
Pol Henarejos
b7590b12d1 Enable fastest supported clock.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 13:36:11 +01:00
Pol Henarejos
d8da775218 Add file & line to debug info.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 11:43:56 +01:00
Pol Henarejos
13c7ade20d Add support for older PCSC.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 11:19:28 +01:00
Pol Henarejos
d925e89127 Add support for ESP32-S2 build.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 11:17:58 +01:00
Pol Henarejos
7a1131cb1a Modify build script to build all supported boards.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 10:58:59 +01:00
Pol Henarejos
d169f001b6 Upgrade to Pico SDK 2.1.1
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-19 10:58:43 +01:00
Pol Henarejos
250de29c3c Added support for OATH rename.
Fixes #107.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-17 19:54:56 +01:00
Pol Henarejos
7c4a020dc1 Merge PR #7 & #8 from @imkuang.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-09 19:18:31 +01:00
Pol Henarejos
88063d5d6d Added tests for silent authentication.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-08 15:01:25 +01:00
Pol Henarejos
f43bc9701f Added support for silent authentication.
Fixes #91.

It requires FIDO22 credential protocol, meaning that old credentials have to be reissued.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-02-08 15:00:12 +01:00
Pol Henarejos
353d782970 Fix OTP command issues in Linux.
Fixes #96.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-31 12:01:29 +01:00
Pol Henarejos
cdd2f486aa Added phy_save() and phy_load() to save and load PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 17:09:47 +01:00
Pol Henarejos
a381e94dda Added phy_save() and phy_load() to save and load PHY.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 17:07:03 +01:00
Pol Henarejos
e78ec82435 Do not init PHY on modifying a single value.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 16:58:49 +01:00
Pol Henarejos
584d2f3b33 Add option to keep the LED steady.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 16:27:45 +01:00
Pol Henarejos
18676990cb Fix USB keyboard descriptor in Windows.
Fixes #97.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-29 13:22:21 +01:00
Pol Henarejos
ed9c46ded0 Fix slot deletion.
Fixes #89.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-19 19:55:16 +01:00
Pol Henarejos
d6a060f214 Upgrade to v6.2
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2025-01-15 15:38:55 +01:00
Pol Henarejos
c443dec4a0 Upgrade to version 6.0
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-11-10 01:50:22 +01:00
Pol Henarejos
8ae4ab5af4 Upgrade to version 5.12
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-09-02 20:21:58 +02:00
Pol Henarejos
d2c25b69bc Merge branch 'main' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2024-08-20 10:18:08 +02:00
Pol Henarejos
21765a6f10 Move pico-keys-sdk pointer.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-11-21 13:10:58 +01:00
Pol Henarejos
eb2c92bc5c Merge branch 'development' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-11-21 13:01:10 +01:00
Pol Henarejos
233c5a7c7d Merge branch 'development' into eddsa 2023-09-18 09:33:56 +02:00
Pol Henarejos
3b4ac12d0f Merge branch 'development' into eddsa 2023-09-18 09:02:26 +02:00
Pol Henarejos
7c5bab8b05 Merge branch 'development' into eddsa 2023-09-18 01:38:39 +02:00
Pol Henarejos
21035d649d Upgrade to version 5.7
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-18 01:38:31 +02:00
Pol Henarejos
abe91823c0 Build firmwares with -eddsa1 suffix.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-17 19:29:54 +02:00
Pol Henarejos
91e049b997 Merge branch 'development' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-09-17 19:28:41 +02:00
Pol Henarejos
8836902dc1 Merge branch 'development' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-22 15:32:10 +02:00
Pol Henarejos
a019b54d69 Merge branch 'development' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-22 13:27:35 +02:00
Pol Henarejos
3adb1a8422 Merge branch 'development' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-21 19:12:51 +02:00
Pol Henarejos
95a9fe4214 Added flow triggering for eddsa branch.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-18 16:49:58 +02:00
Pol Henarejos
8af7cac57a Added authentication tests with EdDSA.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-18 16:48:12 +02:00
Pol Henarejos
7997eefdc8 Fixed EdDSA signature encapsulation.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-18 16:46:55 +02:00
Pol Henarejos
e18f841a34 Fix Edwards load key.
It did not compute the correct public point.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-18 16:46:37 +02:00
Pol Henarejos
73b51cabfc Merge branch 'development' into eddsa 2023-08-18 14:10:58 +02:00
Pol Henarejos
ad3b2bbe4b Added EdDSA credential creation test.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-18 13:07:52 +02:00
Pol Henarejos
b9ad8f4745 Merge branch 'development' into eddsa 2023-08-18 13:07:13 +02:00
Pol Henarejos
8242dc8d80 Merge branch 'development' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-18 12:44:52 +02:00
Pol Henarejos
2f6e4d5568 Upgraded COSE key functions to accept EDDSA.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-17 01:40:22 +02:00
Pol Henarejos
911dab031e Merge branch 'development' into eddsa
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-17 01:36:35 +02:00
Pol Henarejos
3a71275bc8 Add EDDSA algorithm in get_info.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-16 18:06:29 +02:00
Pol Henarejos
9f1e879efe Fix OTP applet selection.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-16 17:32:17 +02:00
Pol Henarejos
57bf97196d Updated readme.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-16 14:48:44 +02:00
Pol Henarejos
e8c8ce4d15 Adding support for EdDSA with Ed25519 curve.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-16 14:47:34 +02:00
Pol Henarejos
69d618cc6b Point to proper EdDSA branch.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-16 13:13:58 +02:00
Pol Henarejos
e057f17180 Using Pico HSM SDK EdDSA branch.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2023-08-16 13:07:01 +02:00
28 changed files with 700 additions and 406 deletions

View File

@@ -13,10 +13,10 @@ name: "CodeQL"
on: on:
push: push:
branches: [ "main", "development" ] branches: [ "main", "development", "eddsa" ]
pull_request: pull_request:
# The branches below must be a subset of the branches above # The branches below must be a subset of the branches above
branches: [ "main", "development" ] branches: [ "main", "development", "eddsa" ]
schedule: schedule:
- cron: '23 5 * * 4' - cron: '23 5 * * 4'
workflow_dispatch: workflow_dispatch:
@@ -36,7 +36,7 @@ jobs:
language: [ 'cpp', 'python' ] language: [ 'cpp', 'python' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
mode: [ 'pico', 'esp32', 'local' ] mode: [ 'pico', 'local' ]
steps: steps:
- name: Checkout repository - name: Checkout repository

View File

@@ -24,7 +24,7 @@ jobs:
PICO_SDK_PATH: ../pico-sdk PICO_SDK_PATH: ../pico-sdk
run: | run: |
./workflows/autobuild.sh pico ./workflows/autobuild.sh pico
./build_pico_fido.sh ./build_pico_fido.sh --no-eddsa
./workflows/autobuild.sh esp32 ./workflows/autobuild.sh esp32
- name: Update nightly release - name: Update nightly release
uses: pyTooling/Actions/releaser@main uses: pyTooling/Actions/releaser@main

View File

@@ -13,10 +13,10 @@ name: "Emulation and test"
on: on:
push: push:
branches: [ "main", "development" ] branches: [ "main", "development", "eddsa" ]
pull_request: pull_request:
# The branches below must be a subset of the branches above # The branches below must be a subset of the branches above
branches: [ "main", "development" ] branches: [ "main", "development", "eddsa" ]
schedule: schedule:
- cron: '23 5 * * 4' - cron: '23 5 * * 4'
workflow_dispatch: workflow_dispatch:

View File

@@ -26,6 +26,7 @@ else()
if(ENABLE_EMULATION) if(ENABLE_EMULATION)
else() else()
set(PICO_USE_FASTEST_SUPPORTED_CLOCK 1)
include(pico_sdk_import.cmake) include(pico_sdk_import.cmake)
endif() endif()

View File

@@ -13,8 +13,8 @@ Pico FIDO includes the following features:
- User verification with PIN - User verification with PIN
- Discoverable credentials (resident keys) - Discoverable credentials (resident keys)
- Credential management - Credential management
- ECDSA authentication - ECDSA and EDDSA authentication
- Support for SECP256R1, SECP384R1, SECP521R1, and SECP256K1 curves - Support for SECP256R1, SECP384R1, SECP521R1, SECP256K1 and Ed25519 curves
- App registration and login - App registration and login
- Device selection - Device selection
- Support for vendor configuration - Support for vendor configuration

View File

@@ -1,108 +1,47 @@
#!/bin/bash #!/bin/bash
VERSION_MAJOR="6" VERSION_MAJOR="6"
VERSION_MINOR="2" VERSION_MINOR="6"
NO_EDDSA=0
SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}" SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}"
#if ! [[ -z "${GITHUB_SHA}" ]]; then #if ! [[ -z "${GITHUB_SHA}" ]]; then
# SUFFIX="${SUFFIX}.${GITHUB_SHA}" # SUFFIX="${SUFFIX}.${GITHUB_SHA}"
#fi #fi
rm -rf release/* if [[ $1 == "--no-eddsa" ]]; then
NO_EDDSA=1
echo "Skipping EDDSA build"
fi
mkdir -p build_release mkdir -p build_release
mkdir -p release mkdir -p release
mkdir -p release_eddsa
rm -rf -- release/*
if [[ $NO_EDDSA -eq 0 ]]; then
rm -rf -- release_eddsa/*
fi
cd build_release cd build_release
for board in 0xcb_helios \ PICO_SDK_PATH="${PICO_SDK_PATH:-../../pico-sdk}"
adafruit_feather_rp2040_usb_host \ board_dir=${PICO_SDK_PATH}/src/boards/include/boards
adafruit_feather_rp2040 \ for board in "$board_dir"/*
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 \
waveshare_rp2040_one \
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 do
rm -rf * board_name="$(basename -- "$board" .h)"
PICO_SDK_PATH="${PICO_SDK_PATH:-../../pico-sdk}" cmake .. -DPICO_BOARD=$board rm -rf -- ./*
PICO_SDK_PATH="${PICO_SDK_PATH}" cmake .. -DPICO_BOARD=$board_name -DSECURE_BOOT_PKEY=../../ec_private_key.pem
make -j`nproc` make -j`nproc`
mv pico_fido.uf2 ../release/pico_fido_$board-$SUFFIX.uf2 mv pico_fido.uf2 ../release/pico_fido_$board_name-$SUFFIX.uf2
done done
# Build with EDDSA
if [[ $NO_EDDSA -eq 0 ]]; then
for board in "$board_dir"/*
do
board_name="$(basename -- "$board" .h)"
rm -rf -- ./*
PICO_SDK_PATH="${PICO_SDK_PATH}" cmake .. -DPICO_BOARD=$board_name -DSECURE_BOOT_PKEY=../../ec_private_key.pem -DENABLE_EDDSA=1
make -j`nproc`
mv pico_fido.uf2 ../release/pico_fido_$board_name-$SUFFIX-eddsa1.uf2
done
fi

View File

@@ -117,7 +117,7 @@ void cbor_thread(void) {
} }
apdu.sw = cbor_parse(cbor_cmd, cbor_data, cbor_len); apdu.sw = cbor_parse(cbor_cmd, cbor_data, cbor_len);
if (apdu.sw == 0) { if (apdu.sw == 0) {
DEBUG_DATA(res_APDU + 1, res_APDU_size); DEBUG_DATA(res_APDU, res_APDU_size);
} }
else { else {
if (apdu.sw >= CTAP1_ERR_INVALID_CHANNEL) { if (apdu.sw >= CTAP1_ERR_INVALID_CHANNEL) {
@@ -210,6 +210,11 @@ CborError COSE_key(mbedtls_ecp_keypair *key, CborEncoder *mapEncoderParent,
else if (key->grp.id == MBEDTLS_ECP_DP_CURVE25519) { else if (key->grp.id == MBEDTLS_ECP_DP_CURVE25519) {
alg = FIDO2_ALG_ECDH_ES_HKDF_256; alg = FIDO2_ALG_ECDH_ES_HKDF_256;
} }
#ifdef MBEDTLS_EDDSA_C
else if (key->grp.id == MBEDTLS_ECP_DP_ED25519) {
alg = FIDO2_ALG_EDDSA;
}
#endif
return COSE_key_params(crv, alg, &key->grp, &key->Q, mapEncoderParent, mapEncoder); return COSE_key_params(crv, alg, &key->grp, &key->Q, mapEncoderParent, mapEncoder);
} }
CborError COSE_key_shared(mbedtls_ecdh_context *key, CborError COSE_key_shared(mbedtls_ecdh_context *key,

View File

@@ -246,14 +246,9 @@ int cbor_config(const uint8_t *data, size_t len) {
else { else {
CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION); CBOR_ERROR(CTAP2_ERR_UNSUPPORTED_OPTION);
} }
uint8_t tmp[PHY_MAX_SIZE]; if (phy_save() != PICOKEY_OK) {
uint16_t tmp_len = 0;
memset(tmp, 0, sizeof(tmp));
if (phy_serialize_data(&phy_data, tmp, &tmp_len) != PICOKEY_OK) {
CBOR_ERROR(CTAP2_ERR_PROCESSING); CBOR_ERROR(CTAP2_ERR_PROCESSING);
} }
file_put_data(ef_phy, tmp, tmp_len);
low_flash_available();
} }
#endif #endif
else { else {

View File

@@ -243,11 +243,11 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED); CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED);
} }
mbedtls_ecdsa_context key; mbedtls_ecp_keypair key;
mbedtls_ecdsa_init(&key); mbedtls_ecp_keypair_init(&key);
if (fido_load_key((int)cred.curve, cred.id.data, &key) != 0) { if (fido_load_key((int)cred.curve, cred.id.data, &key) != 0) {
credential_free(&cred); credential_free(&cred);
mbedtls_ecdsa_free(&key); mbedtls_ecp_keypair_free(&key);
CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED); CBOR_ERROR(CTAP2_ERR_NOT_ALLOWED);
} }
@@ -335,7 +335,7 @@ int cbor_cred_mgmt(const uint8_t *data, size_t len) {
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, false)); CBOR_CHECK(cbor_encode_boolean(&mapEncoder, false));
} }
credential_free(&cred); credential_free(&cred);
mbedtls_ecdsa_free(&key); mbedtls_ecp_keypair_free(&key);
} }
else if (subcommand == 0x06) { else if (subcommand == 0x06) {
if (credentialId.id.present == false) { if (credentialId.id.present == false) {

View File

@@ -93,7 +93,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
Credential creds[MAX_CREDENTIAL_COUNT_IN_LIST] = { 0 }; Credential creds[MAX_CREDENTIAL_COUNT_IN_LIST] = { 0 };
size_t allowList_len = 0, creds_len = 0; size_t allowList_len = 0, creds_len = 0;
uint8_t *aut_data = NULL; uint8_t *aut_data = NULL;
bool asserted = false, up = true, uv = false; bool asserted = false, up = false, uv = false;
int64_t kty = 2, alg = 0, crv = 0; int64_t kty = 2, alg = 0, crv = 0;
CborByteString kax = { 0 }, kay = { 0 }, salt_enc = { 0 }, salt_auth = { 0 }; CborByteString kax = { 0 }, kay = { 0 }, salt_enc = { 0 }, salt_auth = { 0 };
const bool *credBlob = NULL; const bool *credBlob = NULL;
@@ -235,6 +235,12 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
if (options.uv == ptrue) { //4.3 if (options.uv == ptrue) { //4.3
CBOR_ERROR(CTAP2_ERR_INVALID_OPTION); CBOR_ERROR(CTAP2_ERR_INVALID_OPTION);
} }
if (options.uv == NULL || pinUvAuthParam.present == true) {
uv = false;
}
else {
uv = *options.uv;
}
//if (options.up != NULL) { //4.5 //if (options.up != NULL) { //4.5
// CBOR_ERROR(CTAP2_ERR_INVALID_OPTION); // CBOR_ERROR(CTAP2_ERR_INVALID_OPTION);
//} //}
@@ -243,12 +249,12 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
} }
//else if (options.up == NULL) //5.7 //else if (options.up == NULL) //5.7
//rup = ptrue; //rup = ptrue;
if (options.uv != NULL) {
uv = *options.uv;
}
if (options.up != NULL) { if (options.up != NULL) {
up = *options.up; up = *options.up;
} }
else {
up = true;
}
} }
if (pinUvAuthParam.present == true) { //6.1 if (pinUvAuthParam.present == true) { //6.1
@@ -279,6 +285,8 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
} }
} }
bool silent = (up == false && uv == false);
if (allowList_len > 0) { if (allowList_len > 0) {
for (size_t e = 0; e < allowList_len; e++) { for (size_t e = 0; e < allowList_len; e++) {
if (allowList[e].type.present == false || allowList[e].id.present == false) { if (allowList[e].type.present == false || allowList[e].id.present == false) {
@@ -288,11 +296,27 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
continue; continue;
} }
if (credential_load(allowList[e].id.data, allowList[e].id.len, rp_id_hash, &creds[creds_len]) != 0) { if (credential_load(allowList[e].id.data, allowList[e].id.len, rp_id_hash, &creds[creds_len]) != 0) {
CBOR_FREE_BYTE_STRING(allowList[e].id);
credential_free(&creds[creds_len]); credential_free(&creds[creds_len]);
} }
else { else {
creds_len++; creds_len++;
silent = false; // If we are able to load a credential, we are not silent
// Even we provide allowList, we need to check if the credential is resident
if (!resident) {
for (int i = 0; i < MAX_RESIDENT_CREDENTIALS && creds_len < MAX_CREDENTIAL_COUNT_IN_LIST; i++) {
file_t *ef = search_dynamic_file((uint16_t)(EF_CRED + i));
if (!file_has_data(ef) || memcmp(file_get_data(ef), rp_id_hash, 32) != 0) {
continue;
}
if (memcmp(file_get_data(ef) + 32, allowList[e].id.data, allowList[e].id.len) == 0) {
resident = true;
break;
}
}
if (resident) {
break;
}
}
} }
} }
} }
@@ -308,6 +332,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
} }
else { else {
creds_len++; creds_len++;
silent = false; // If we are able to load a credential, we are not silent
} }
} }
resident = true; resident = true;
@@ -342,15 +367,32 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
} }
} }
if (numberOfCredentials == 0) { if (numberOfCredentials == 0) {
CBOR_ERROR(CTAP2_ERR_NO_CREDENTIALS); if (silent && allowList_len > 0) {
for (size_t e = 0; e < allowList_len; e++) {
if (allowList[e].type.present == false || allowList[e].id.present == false) {
CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER);
}
if (strcmp(allowList[e].type.data, "public-key") != 0) {
continue;
}
if (credential_verify(allowList[e].id.data, allowList[e].id.len, rp_id_hash, true) == 0) {
numberOfCredentials++;
}
}
}
if (numberOfCredentials == 0) {
CBOR_ERROR(CTAP2_ERR_NO_CREDENTIALS);
}
} }
for (int i = 0; i < numberOfCredentials; i++) { if (!silent) {
for (int j = i + 1; j < numberOfCredentials; j++) { for (int i = 0; i < numberOfCredentials; i++) {
if (creds[j].creation > creds[i].creation) { for (int j = i + 1; j < numberOfCredentials; j++) {
Credential tmp = creds[j]; if (creds[j].creation > creds[i].creation) {
creds[j] = creds[i]; Credential tmp = creds[j];
creds[i] = tmp; creds[j] = creds[i];
creds[i] = tmp;
}
} }
} }
} }
@@ -380,8 +422,8 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
CBOR_ERROR(CTAP2_ERR_INVALID_OPTION); CBOR_ERROR(CTAP2_ERR_INVALID_OPTION);
} }
if (up == false && uv == false) { if (silent && !resident) {
selcred = &creds[0]; // Silent authentication, do nothing
} }
else { else {
selcred = &creds[0]; selcred = &creds[0];
@@ -410,106 +452,110 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
int ret = 0; int ret = 0;
uint8_t largeBlobKey[32] = {0}; uint8_t largeBlobKey[32] = {0};
if (extensions.largeBlobKey == ptrue && selcred->extensions.largeBlobKey == ptrue) { if (selcred) {
ret = credential_derive_large_blob_key(selcred->id.data, selcred->id.len, largeBlobKey); if (extensions.largeBlobKey == ptrue && selcred->extensions.largeBlobKey == ptrue) {
if (ret != 0) { ret = credential_derive_large_blob_key(selcred->id.data, selcred->id.len, largeBlobKey);
CBOR_ERROR(CTAP2_ERR_PROCESSING); if (ret != 0) {
CBOR_ERROR(CTAP2_ERR_PROCESSING);
}
} }
} }
size_t ext_len = 0; size_t ext_len = 0;
uint8_t ext[512] = {0}; uint8_t ext[512] = {0};
if (extensions.present == true) { if (selcred && extensions.present == true) {
cbor_encoder_init(&encoder, ext, sizeof(ext), 0); cbor_encoder_init(&encoder, ext, sizeof(ext), 0);
int l = 0; int l = 0;
if (options.up == pfalse) { if (options.up == pfalse) {
extensions.hmac_secret = NULL; extensions.hmac_secret = NULL;
} }
if (extensions.hmac_secret != NULL) { if (extensions.hmac_secret == ptrue) {
l++; l++;
} }
if (credBlob == ptrue) { if (credBlob == ptrue) {
l++; l++;
} }
if (extensions.thirdPartyPayment != NULL) { if (extensions.thirdPartyPayment == ptrue) {
l++; l++;
} }
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, l)); if (l > 0) {
if (credBlob == ptrue) { CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, l));
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "credBlob")); if (credBlob == ptrue) {
if (selcred->extensions.credBlob.present == true) { CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "credBlob"));
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, selcred->extensions.credBlob.data, if (selcred->extensions.credBlob.present == true) {
selcred->extensions.credBlob.len)); CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, selcred->extensions.credBlob.data,
selcred->extensions.credBlob.len));
}
else {
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, NULL, 0));
}
} }
else { if (extensions.hmac_secret == ptrue) {
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, NULL, 0));
}
}
if (extensions.hmac_secret != NULL) {
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "hmac-secret")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "hmac-secret"));
uint8_t sharedSecret[64] = {0}; uint8_t sharedSecret[64] = {0};
mbedtls_ecp_point Qp; mbedtls_ecp_point Qp;
mbedtls_ecp_point_init(&Qp); mbedtls_ecp_point_init(&Qp);
mbedtls_mpi_lset(&Qp.Z, 1); mbedtls_mpi_lset(&Qp.Z, 1);
if (mbedtls_mpi_read_binary(&Qp.X, kax.data, kax.len) != 0) { if (mbedtls_mpi_read_binary(&Qp.X, kax.data, kax.len) != 0) {
mbedtls_ecp_point_free(&Qp);
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
if (mbedtls_mpi_read_binary(&Qp.Y, kay.data, kay.len) != 0) {
mbedtls_ecp_point_free(&Qp);
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
ret = ecdh((uint8_t)hmacSecretPinUvAuthProtocol, &Qp, sharedSecret);
mbedtls_ecp_point_free(&Qp); mbedtls_ecp_point_free(&Qp);
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER); if (ret != 0) {
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
if (verify((uint8_t)hmacSecretPinUvAuthProtocol, sharedSecret, salt_enc.data, (uint16_t)salt_enc.len, salt_auth.data) != 0) {
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
CBOR_ERROR(CTAP2_ERR_EXTENSION_FIRST);
}
uint8_t salt_dec[64] = {0}, poff = ((uint8_t)hmacSecretPinUvAuthProtocol - 1) * IV_SIZE;
ret = decrypt((uint8_t)hmacSecretPinUvAuthProtocol, sharedSecret, salt_enc.data, (uint16_t)salt_enc.len, salt_dec);
if (ret != 0) {
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
uint8_t cred_random[64] = {0}, *crd = NULL;
ret = credential_derive_hmac_key(selcred->id.data, selcred->id.len, cred_random);
if (ret != 0) {
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
if (flags & FIDO2_AUT_FLAG_UV) {
crd = cred_random + 32;
}
else {
crd = cred_random;
}
uint8_t out1[64] = {0}, hmac_res[80] = {0};
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), crd, 32, salt_dec, 32, out1);
if ((uint8_t)salt_enc.len == 64 + poff) {
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), crd, 32, salt_dec + 32, 32, out1 + 32);
}
encrypt((uint8_t)hmacSecretPinUvAuthProtocol, sharedSecret, out1, (uint16_t)(salt_enc.len - poff), hmac_res);
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, hmac_res, salt_enc.len));
} }
if (mbedtls_mpi_read_binary(&Qp.Y, kay.data, kay.len) != 0) { if (extensions.thirdPartyPayment == ptrue) {
mbedtls_ecp_point_free(&Qp); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "thirdPartyPayment"));
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER); if (selcred->extensions.thirdPartyPayment == ptrue) {
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, true));
}
else {
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, false));
}
} }
ret = ecdh((uint8_t)hmacSecretPinUvAuthProtocol, &Qp, sharedSecret);
mbedtls_ecp_point_free(&Qp);
if (ret != 0) {
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
if (verify((uint8_t)hmacSecretPinUvAuthProtocol, sharedSecret, salt_enc.data, (uint16_t)salt_enc.len, salt_auth.data) != 0) {
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
CBOR_ERROR(CTAP2_ERR_EXTENSION_FIRST);
}
uint8_t salt_dec[64] = {0}, poff = ((uint8_t)hmacSecretPinUvAuthProtocol - 1) * IV_SIZE;
ret = decrypt((uint8_t)hmacSecretPinUvAuthProtocol, sharedSecret, salt_enc.data, (uint16_t)salt_enc.len, salt_dec);
if (ret != 0) {
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
uint8_t cred_random[64] = {0}, *crd = NULL;
ret = credential_derive_hmac_key(selcred->id.data, selcred->id.len, cred_random);
if (ret != 0) {
mbedtls_platform_zeroize(sharedSecret, sizeof(sharedSecret));
CBOR_ERROR(CTAP1_ERR_INVALID_PARAMETER);
}
if (flags & FIDO2_AUT_FLAG_UV) {
crd = cred_random + 32;
}
else {
crd = cred_random;
}
uint8_t out1[64] = {0}, hmac_res[80] = {0};
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), crd, 32, salt_dec, 32, out1);
if ((uint8_t)salt_enc.len == 64 + poff) {
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), crd, 32, salt_dec + 32, 32, out1 + 32);
}
encrypt((uint8_t)hmacSecretPinUvAuthProtocol, sharedSecret, out1, (uint16_t)(salt_enc.len - poff), hmac_res);
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, hmac_res, salt_enc.len));
}
if (extensions.thirdPartyPayment != NULL) {
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "thirdPartyPayment"));
if (selcred->extensions.thirdPartyPayment == ptrue) {
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, true));
}
else {
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, false));
}
}
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder)); CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
ext_len = cbor_encoder_get_buffer_size(&encoder, ext); ext_len = cbor_encoder_get_buffer_size(&encoder, ext);
flags |= FIDO2_AUT_FLAG_ED; flags |= FIDO2_AUT_FLAG_ED;
}
} }
uint32_t ctr = get_sign_counter(); uint32_t ctr = get_sign_counter();
@@ -528,34 +574,56 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
memcpy(pa, clientDataHash.data, clientDataHash.len); memcpy(pa, clientDataHash.data, clientDataHash.len);
uint8_t hash[64] = {0}, sig[MBEDTLS_ECDSA_MAX_LEN] = {0}; uint8_t hash[64] = {0}, sig[MBEDTLS_ECDSA_MAX_LEN] = {0};
const mbedtls_md_info_t *md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); const mbedtls_md_info_t *md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
mbedtls_ecdsa_context ekey; mbedtls_ecp_keypair ekey;
mbedtls_ecdsa_init(&ekey); mbedtls_ecp_keypair_init(&ekey);
ret = fido_load_key((int)selcred->curve, selcred->id.data, &ekey);
if (ret != 0) {
if (derive_key(rp_id_hash, false, selcred->id.data, MBEDTLS_ECP_DP_SECP256R1, &ekey) != 0) {
mbedtls_ecdsa_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER);
}
}
if (ekey.grp.id == MBEDTLS_ECP_DP_SECP384R1) {
md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
}
else if (ekey.grp.id == MBEDTLS_ECP_DP_SECP521R1) {
md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
}
ret = mbedtls_md(md, aut_data, aut_data_len + clientDataHash.len, hash);
size_t olen = 0; size_t olen = 0;
ret = mbedtls_ecdsa_write_signature(&ekey, mbedtls_md_get_type(md), hash, mbedtls_md_get_size(md), sig, sizeof(sig), &olen, random_gen, NULL); if (selcred) {
mbedtls_ecdsa_free(&ekey); ret = fido_load_key((int)selcred->curve, selcred->id.data, &ekey);
if (ret != 0) {
if (derive_key(rp_id_hash, false, selcred->id.data, MBEDTLS_ECP_DP_SECP256R1, &ekey) != 0) {
mbedtls_ecp_keypair_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER);
}
}
if (ekey.grp.id == MBEDTLS_ECP_DP_SECP384R1) {
md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA384);
}
else if (ekey.grp.id == MBEDTLS_ECP_DP_SECP521R1) {
md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
}
#ifdef MBEDTLS_EDDSA_C
else if (ekey.grp.id == MBEDTLS_ECP_DP_ED25519) {
md = NULL;
}
#endif
if (md != NULL) {
ret = mbedtls_md(md, aut_data, aut_data_len + clientDataHash.len, hash);
ret = mbedtls_ecdsa_write_signature(&ekey, mbedtls_md_get_type(md), hash, mbedtls_md_get_size(md), sig, sizeof(sig), &olen, random_gen, NULL);
}
#ifdef MBEDTLS_EDDSA_C
else {
ret = mbedtls_eddsa_write_signature(&ekey, aut_data, aut_data_len + clientDataHash.len, sig, sizeof(sig), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
}
#endif
}
else {
// Bogus signature
olen = 64;
memset(sig, 0x0B, olen);
}
mbedtls_ecp_keypair_free(&ekey);
if (ret != 0) {
CBOR_ERROR(CTAP2_ERR_PROCESSING);
}
uint8_t lfields = 3; uint8_t lfields = 3;
if (selcred->opts.present == true && selcred->opts.rk == ptrue) { if (selcred && selcred->opts.present == true && selcred->opts.rk == ptrue) {
lfields++; lfields++;
} }
if (numberOfCredentials > 1 && next == false) { if (numberOfCredentials > 1 && next == false && (!resident || allowList_len <= 1)) {
lfields++; lfields++;
} }
if (extensions.largeBlobKey == ptrue && selcred->extensions.largeBlobKey == ptrue) { if (selcred && extensions.largeBlobKey == ptrue && selcred->extensions.largeBlobKey == ptrue) {
lfields++; lfields++;
} }
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0); cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
@@ -564,7 +632,12 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01));
CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &mapEncoder2, 2)); CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &mapEncoder2, 2));
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "id")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "id"));
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder2, selcred->id.data, selcred->id.len)); if (selcred) {
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder2, selcred->id.data, selcred->id.len));
}
else {
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder2, (uint8_t *)"\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01\x00\x01", 16));
}
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "type")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "type"));
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "public-key")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder2, "public-key"));
CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &mapEncoder2)); CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &mapEncoder2));
@@ -574,7 +647,7 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x03)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x03));
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, sig, olen)); CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, sig, olen));
if (selcred->opts.present == true && selcred->opts.rk == ptrue) { if (selcred && selcred->opts.present == true && selcred->opts.rk == ptrue) {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04));
uint8_t lu = 1; uint8_t lu = 1;
if (numberOfCredentials > 1 && allowList_len == 0) { if (numberOfCredentials > 1 && allowList_len == 0) {
@@ -601,11 +674,11 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
} }
CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &mapEncoder2)); CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &mapEncoder2));
} }
if (numberOfCredentials > 1 && next == false) { if (numberOfCredentials > 1 && next == false && (!resident || allowList_len <= 1)) {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x05)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x05));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, numberOfCredentials)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, numberOfCredentials));
} }
if (extensions.largeBlobKey == ptrue && selcred->extensions.largeBlobKey == ptrue) { if (selcred && extensions.largeBlobKey == ptrue && selcred->extensions.largeBlobKey == ptrue) {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x07)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x07));
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, largeBlobKey, sizeof(largeBlobKey))); CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, largeBlobKey, sizeof(largeBlobKey)));
} }

View File

@@ -50,11 +50,18 @@ int cbor_get_info() {
CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, aaguid, sizeof(aaguid))); CBOR_CHECK(cbor_encode_byte_string(&mapEncoder, aaguid, sizeof(aaguid)));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04));
CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &arrayEncoder, 8)); CBOR_CHECK(cbor_encoder_create_map(&mapEncoder, &arrayEncoder, 9));
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "ep")); CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "ep"));
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, get_opts() & FIDO2_OPT_EA)); CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, get_opts() & FIDO2_OPT_EA));
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "rk")); CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "rk"));
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true)); CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "alwaysUv"));
if (file_has_data(ef_pin) && (get_opts() & FIDO2_OPT_AUV || !getUserVerifiedFlagValue())) {
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
}
else {
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, false));
}
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "credMgmt")); CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "credMgmt"));
CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true)); CBOR_CHECK(cbor_encode_boolean(&arrayEncoder, true));
CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "authnrCfg")); CBOR_CHECK(cbor_encode_text_stringz(&arrayEncoder, "authnrCfg"));
@@ -90,11 +97,33 @@ int cbor_get_info() {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, MAX_CRED_ID_LENGTH)); // MAX_CRED_ID_MAX_LENGTH CBOR_CHECK(cbor_encode_uint(&mapEncoder, MAX_CRED_ID_LENGTH)); // MAX_CRED_ID_MAX_LENGTH
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0A)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0A));
CBOR_CHECK(cbor_encoder_create_array(&mapEncoder, &arrayEncoder, 4));
uint8_t curves = 3;
#ifdef MBEDTLS_EDDSA_C
curves++;
#endif
#ifndef ENABLE_EMULATION
if (phy_data.enabled_curves & PHY_CURVE_SECP256K1) {
#endif
curves++;
#ifndef ENABLE_EMULATION
}
#endif
CBOR_CHECK(cbor_encoder_create_array(&mapEncoder, &arrayEncoder, curves));
CBOR_CHECK(COSE_public_key(FIDO2_ALG_ES256, &arrayEncoder, &mapEncoder2)); CBOR_CHECK(COSE_public_key(FIDO2_ALG_ES256, &arrayEncoder, &mapEncoder2));
#ifdef MBEDTLS_EDDSA_C
CBOR_CHECK(COSE_public_key(FIDO2_ALG_EDDSA, &arrayEncoder, &mapEncoder2));
#endif
CBOR_CHECK(COSE_public_key(FIDO2_ALG_ES384, &arrayEncoder, &mapEncoder2)); CBOR_CHECK(COSE_public_key(FIDO2_ALG_ES384, &arrayEncoder, &mapEncoder2));
CBOR_CHECK(COSE_public_key(FIDO2_ALG_ES512, &arrayEncoder, &mapEncoder2)); CBOR_CHECK(COSE_public_key(FIDO2_ALG_ES512, &arrayEncoder, &mapEncoder2));
CBOR_CHECK(COSE_public_key(FIDO2_ALG_ES256K, &arrayEncoder, &mapEncoder2)); #ifndef ENABLE_EMULATION
if (phy_data.enabled_curves & PHY_CURVE_SECP256K1) {
#endif
CBOR_CHECK(COSE_public_key(FIDO2_ALG_ES256K, &arrayEncoder, &mapEncoder2));
#ifndef ENABLE_EMULATION
}
#endif
CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &arrayEncoder)); CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &arrayEncoder));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0B)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x0B));

View File

@@ -217,11 +217,22 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
curve = FIDO2_CURVE_P521; curve = FIDO2_CURVE_P521;
} }
} }
else if (pubKeyCredParams[i].alg == FIDO2_ALG_ES256K) { else if (pubKeyCredParams[i].alg == FIDO2_ALG_ES256K
#ifndef ENABLE_EMULATION
&& (phy_data.enabled_curves & PHY_CURVE_SECP256K1)
#endif
) {
if (curve <= 0) { if (curve <= 0) {
curve = FIDO2_CURVE_P256K1; curve = FIDO2_CURVE_P256K1;
} }
} }
#ifdef MBEDTLS_EDDSA_C
else if (pubKeyCredParams[i].alg == FIDO2_ALG_EDDSA) {
if (curve <= 0) {
curve = FIDO2_CURVE_ED25519;
}
}
#endif
else if (pubKeyCredParams[i].alg <= FIDO2_ALG_RS256 && pubKeyCredParams[i].alg >= FIDO2_ALG_RS512) { else if (pubKeyCredParams[i].alg <= FIDO2_ALG_RS256 && pubKeyCredParams[i].alg >= FIDO2_ALG_RS512) {
// pass // pass
} }
@@ -337,13 +348,13 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
cbor_encoder_init(&encoder, ext, sizeof(ext), 0); cbor_encoder_init(&encoder, ext, sizeof(ext), 0);
int l = 0; int l = 0;
uint8_t minPinLen = 0; uint8_t minPinLen = 0;
if (extensions.hmac_secret != NULL) { if (extensions.hmac_secret == ptrue) {
l++; l++;
} }
if (extensions.credProtect != 0) { if (extensions.credProtect != 0) {
l++; l++;
} }
if (extensions.minPinLength != NULL) { if (extensions.minPinLength == ptrue) {
file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF); file_t *ef_minpin = search_by_fid(EF_MINPINLEN, NULL, SPECIFY_EF);
if (file_has_data(ef_minpin)) { if (file_has_data(ef_minpin)) {
uint8_t *minpin_data = file_get_data(ef_minpin); uint8_t *minpin_data = file_get_data(ef_minpin);
@@ -361,40 +372,42 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
if (extensions.credBlob.present == true) { if (extensions.credBlob.present == true) {
l++; l++;
} }
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, l)); if (l > 0) {
if (extensions.credBlob.present == true) { CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, l));
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "credBlob")); if (extensions.credBlob.present == true) {
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, extensions.credBlob.len < MAX_CREDBLOB_LENGTH)); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "credBlob"));
} CBOR_CHECK(cbor_encode_boolean(&mapEncoder, extensions.credBlob.len < MAX_CREDBLOB_LENGTH));
if (extensions.credProtect != 0) { }
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "credProtect")); if (extensions.credProtect != 0) {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, extensions.credProtect)); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "credProtect"));
} CBOR_CHECK(cbor_encode_uint(&mapEncoder, extensions.credProtect));
if (extensions.hmac_secret != NULL) { }
if (extensions.hmac_secret == ptrue) {
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "hmac-secret")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "hmac-secret"));
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, *extensions.hmac_secret)); CBOR_CHECK(cbor_encode_boolean(&mapEncoder, true));
} }
if (minPinLen > 0) { if (minPinLen > 0) {
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "minPinLength")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "minPinLength"));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, minPinLen)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, minPinLen));
} }
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder)); CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
ext_len = cbor_encoder_get_buffer_size(&encoder, ext); ext_len = cbor_encoder_get_buffer_size(&encoder, ext);
flags |= FIDO2_AUT_FLAG_ED; flags |= FIDO2_AUT_FLAG_ED;
}
} }
mbedtls_ecdsa_context ekey; mbedtls_ecp_keypair ekey;
mbedtls_ecdsa_init(&ekey); mbedtls_ecp_keypair_init(&ekey);
int ret = fido_load_key(curve, cred_id, &ekey); int ret = fido_load_key(curve, cred_id, &ekey);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdsa_free(&ekey); mbedtls_ecp_keypair_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER); CBOR_ERROR(CTAP1_ERR_OTHER);
} }
const mbedtls_ecp_curve_info *cinfo = mbedtls_ecp_curve_info_from_grp_id(ekey.grp.id); const mbedtls_ecp_curve_info *cinfo = mbedtls_ecp_curve_info_from_grp_id(ekey.grp.id);
if (cinfo == NULL) { if (cinfo == NULL) {
mbedtls_ecdsa_free(&ekey); mbedtls_ecp_keypair_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER); CBOR_ERROR(CTAP1_ERR_OTHER);
} }
size_t olen = 0; size_t olen = 0;
@@ -416,7 +429,7 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
memcpy(pa, cbor_buf, rs); pa += (uint16_t)rs; memcpy(pa, cbor_buf, rs); pa += (uint16_t)rs;
memcpy(pa, ext, ext_len); pa += (uint16_t)ext_len; memcpy(pa, ext, ext_len); pa += (uint16_t)ext_len;
if ((size_t)(pa - aut_data) != aut_data_len) { if ((size_t)(pa - aut_data) != aut_data_len) {
mbedtls_ecdsa_free(&ekey); mbedtls_ecp_keypair_free(&ekey);
CBOR_ERROR(CTAP1_ERR_OTHER); CBOR_ERROR(CTAP1_ERR_OTHER);
} }
@@ -429,12 +442,19 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
else if (ekey.grp.id == MBEDTLS_ECP_DP_SECP521R1) { else if (ekey.grp.id == MBEDTLS_ECP_DP_SECP521R1) {
md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
} }
ret = mbedtls_md(md, aut_data, aut_data_len + clientDataHash.len, hash); #ifdef MBEDTLS_EDDSA_C
else if (ekey.grp.id == MBEDTLS_ECP_DP_ED25519) {
md = NULL;
}
#endif
if (md != NULL) {
ret = mbedtls_md(md, aut_data, aut_data_len + clientDataHash.len, hash);
}
bool self_attestation = true; bool self_attestation = true;
if (enterpriseAttestation == 2 || (ka && ka->use_self_attestation == pfalse)) { if (enterpriseAttestation == 2 || (ka && ka->use_self_attestation == pfalse)) {
mbedtls_ecdsa_free(&ekey); mbedtls_ecp_keypair_free(&ekey);
mbedtls_ecdsa_init(&ekey); mbedtls_ecp_keypair_init(&ekey);
uint8_t key[32] = {0}; uint8_t key[32] = {0};
if (load_keydev(key) != 0) { if (load_keydev(key) != 0) {
CBOR_ERROR(CTAP1_ERR_OTHER); CBOR_ERROR(CTAP1_ERR_OTHER);
@@ -444,8 +464,18 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
self_attestation = false; self_attestation = false;
} }
ret = mbedtls_ecdsa_write_signature(&ekey, mbedtls_md_get_type(md), hash, mbedtls_md_get_size(md), sig, sizeof(sig), &olen, random_gen, NULL); if (md != NULL) {
mbedtls_ecdsa_free(&ekey); ret = mbedtls_ecdsa_write_signature(&ekey, mbedtls_md_get_type(md), hash, mbedtls_md_get_size(md), sig, sizeof(sig), &olen, random_gen, NULL);
}
#ifdef MBEDTLS_EDDSA_C
else {
ret = mbedtls_eddsa_write_signature(&ekey, aut_data, aut_data_len + clientDataHash.len, sig, sizeof(sig), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL);
}
#endif
mbedtls_ecp_keypair_free(&ekey);
if (ret != 0) {
CBOR_ERROR(CTAP2_ERR_PROCESSING);
}
if (user.id.len > 0 && user.parent.name.len > 0 && user.displayName.len > 0) { if (user.id.len > 0 && user.parent.name.len > 0 && user.displayName.len > 0) {
if (memcmp(user.parent.name.data, "+pico", 5) == 0) { if (memcmp(user.parent.name.data, "+pico", 5) == 0) {
@@ -455,14 +485,13 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
if (memcmp(p, "CommissionProfile", 17) == 0) { if (memcmp(p, "CommissionProfile", 17) == 0) {
ret = phy_unserialize_data(user.id.data, user.id.len, &phy_data); ret = phy_unserialize_data(user.id.data, user.id.len, &phy_data);
if (ret == PICOKEY_OK) { if (ret == PICOKEY_OK) {
file_put_data(ef_phy, user.id.data, user.id.len); ret = phy_save();
} }
} }
#endif #endif
if (ret != 0) { if (ret != PICOKEY_OK) {
CBOR_ERROR(CTAP2_ERR_PROCESSING); CBOR_ERROR(CTAP2_ERR_PROCESSING);
} }
low_flash_available();
} }
} }
@@ -475,7 +504,14 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
} }
cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0); cbor_encoder_init(&encoder, ctap_resp->init.data + 1, CTAP_MAX_CBOR_PAYLOAD, 0);
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, extensions.largeBlobKey == ptrue && options.rk == ptrue ? 5 : 4)); uint8_t lparams = 3;
if (enterpriseAttestation == 2) {
lparams++;
}
if (extensions.largeBlobKey == ptrue && options.rk == ptrue) {
lparams++;
}
CBOR_CHECK(cbor_encoder_create_map(&encoder, &mapEncoder, lparams));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x01));
CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "packed")); CBOR_CHECK(cbor_encode_text_stringz(&mapEncoder, "packed"));
@@ -504,8 +540,10 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
} }
CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &mapEncoder2)); CBOR_CHECK(cbor_encoder_close_container(&mapEncoder, &mapEncoder2));
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04)); if (enterpriseAttestation == 2) {
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, enterpriseAttestation == 2)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x04));
CBOR_CHECK(cbor_encode_boolean(&mapEncoder, true));
}
if (extensions.largeBlobKey == ptrue && options.rk == ptrue) { if (extensions.largeBlobKey == ptrue && options.rk == ptrue) {
CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x05)); CBOR_CHECK(cbor_encode_uint(&mapEncoder, 0x05));

View File

@@ -38,29 +38,29 @@ int cmd_authenticate() {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
} }
mbedtls_ecdsa_context key; mbedtls_ecp_keypair key;
mbedtls_ecdsa_init(&key); mbedtls_ecp_keypair_init(&key);
int ret = 0; int ret = 0;
uint8_t *tmp_kh = (uint8_t *) calloc(1, req->keyHandleLen); uint8_t *tmp_kh = (uint8_t *) calloc(1, req->keyHandleLen);
memcpy(tmp_kh, req->keyHandle, req->keyHandleLen); memcpy(tmp_kh, req->keyHandle, req->keyHandleLen);
if (credential_verify(tmp_kh, req->keyHandleLen, req->appId) == 0) { if (credential_verify(tmp_kh, req->keyHandleLen, req->appId, false) == 0) {
ret = fido_load_key(FIDO2_CURVE_P256, req->keyHandle, &key); ret = fido_load_key(FIDO2_CURVE_P256, req->keyHandle, &key);
} }
else { else {
ret = derive_key(req->appId, false, req->keyHandle, MBEDTLS_ECP_DP_SECP256R1, &key); ret = derive_key(req->appId, false, req->keyHandle, MBEDTLS_ECP_DP_SECP256R1, &key);
if (verify_key(req->appId, req->keyHandle, &key) != 0) { if (verify_key(req->appId, req->keyHandle, &key) != 0) {
mbedtls_ecdsa_free(&key); mbedtls_ecp_keypair_free(&key);
free(tmp_kh); free(tmp_kh);
return SW_INCORRECT_PARAMS(); return SW_INCORRECT_PARAMS();
} }
} }
free(tmp_kh); free(tmp_kh);
if (ret != PICOKEY_OK) { if (ret != PICOKEY_OK) {
mbedtls_ecdsa_free(&key); mbedtls_ecp_keypair_free(&key);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
if (P1(apdu) == CTAP_AUTH_CHECK_ONLY) { if (P1(apdu) == CTAP_AUTH_CHECK_ONLY) {
mbedtls_ecdsa_free(&key); mbedtls_ecp_keypair_free(&key);
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
} }
resp->flags = 0; resp->flags = 0;
@@ -74,12 +74,12 @@ int cmd_authenticate() {
memcpy(sig_base + CTAP_APPID_SIZE + 1 + 4, req->chal, CTAP_CHAL_SIZE); memcpy(sig_base + CTAP_APPID_SIZE + 1 + 4, req->chal, CTAP_CHAL_SIZE);
ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), sig_base, sizeof(sig_base), hash); ret = mbedtls_md(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), sig_base, sizeof(sig_base), hash);
if (ret != 0) { if (ret != 0) {
mbedtls_ecdsa_free(&key); mbedtls_ecp_keypair_free(&key);
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }
size_t olen = 0; size_t olen = 0;
ret = mbedtls_ecdsa_write_signature(&key, MBEDTLS_MD_SHA256, hash, 32, (uint8_t *) resp->sig, CTAP_MAX_EC_SIG_SIZE, &olen, random_gen, NULL); ret = mbedtls_ecdsa_write_signature(&key, MBEDTLS_MD_SHA256, hash, 32, (uint8_t *) resp->sig, CTAP_MAX_EC_SIG_SIZE, &olen, random_gen, NULL);
mbedtls_ecdsa_free(&key); mbedtls_ecp_keypair_free(&key);
if (ret != 0) { if (ret != 0) {
return SW_EXEC_ERROR(); return SW_EXEC_ERROR();
} }

View File

@@ -27,22 +27,59 @@
#include "random.h" #include "random.h"
#include "files.h" #include "files.h"
#include "pico_keys.h" #include "pico_keys.h"
#include "otp.h"
int credential_derive_chacha_key(uint8_t *outk); int credential_derive_chacha_key(uint8_t *outk, const uint8_t *);
int credential_verify(uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash) { static int credential_silent_tag(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash, uint8_t *outk) {
mbedtls_sha256_context ctx;
mbedtls_sha256_init(&ctx);
mbedtls_sha256_starts(&ctx, 0);
if (otp_key_1) {
mbedtls_sha256_update(&ctx, otp_key_1, 32);
}
else {
mbedtls_sha256_update(&ctx, pico_serial.id, sizeof(pico_serial.id));
}
mbedtls_sha256_update(&ctx, rp_id_hash, 32);
mbedtls_sha256_finish(&ctx, outk);
mbedtls_sha256_free(&ctx);
return mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), outk, 32, cred_id, cred_id_len - CRED_SILENT_TAG_LEN, outk);
}
int credential_verify(uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash, bool silent) {
if (cred_id_len < 4 + 12 + 16) { if (cred_id_len < 4 + 12 + 16) {
return -1; return -1;
} }
uint8_t key[32], *iv = cred_id + 4, *cipher = cred_id + 4 + 12, uint8_t key[32] = {0}, *iv = cred_id + CRED_PROTO_LEN, *cipher = cred_id + CRED_PROTO_LEN + CRED_IV_LEN,
*tag = cred_id + cred_id_len - 16; *tag = cred_id + cred_id_len - CRED_TAG_LEN;
memset(key, 0, sizeof(key)); cred_proto_t proto = CRED_PROTO_21;
credential_derive_chacha_key(key); if (memcmp(cred_id, CRED_PROTO_22_S, CRED_PROTO_LEN) == 0) { // New format
mbedtls_chachapoly_context chatx; tag = cred_id + cred_id_len - CRED_SILENT_TAG_LEN - CRED_TAG_LEN;
mbedtls_chachapoly_init(&chatx); proto = CRED_PROTO_22;
mbedtls_chachapoly_setkey(&chatx, key); }
int ret = mbedtls_chachapoly_auth_decrypt(&chatx, cred_id_len - (4 + 12 + 16), iv, rp_id_hash, 32, tag, cipher, cipher); int ret = 0;
mbedtls_chachapoly_free(&chatx); if (!silent) {
int hdr_len = CRED_PROTO_LEN + CRED_IV_LEN + CRED_TAG_LEN;
if (proto == CRED_PROTO_22) {
hdr_len += CRED_SILENT_TAG_LEN;
}
credential_derive_chacha_key(key, cred_id);
mbedtls_chachapoly_context chatx;
mbedtls_chachapoly_init(&chatx);
mbedtls_chachapoly_setkey(&chatx, key);
ret = mbedtls_chachapoly_auth_decrypt(&chatx, cred_id_len - hdr_len, iv, rp_id_hash, 32, tag, cipher, cipher);
mbedtls_chachapoly_free(&chatx);
}
else {
if (proto <= CRED_PROTO_21) {
return -1;
}
uint8_t outk[32];
ret = credential_silent_tag(cred_id, cred_id_len, rp_id_hash, outk);
ret = memcmp(outk, cred_id + cred_id_len - CRED_SILENT_TAG_LEN, CRED_SILENT_TAG_LEN);
}
return ret; return ret;
} }
@@ -113,25 +150,25 @@ int credential_create(CborCharString *rpId,
} }
CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder)); CBOR_CHECK(cbor_encoder_close_container(&encoder, &mapEncoder));
size_t rs = cbor_encoder_get_buffer_size(&encoder, cred_id); size_t rs = cbor_encoder_get_buffer_size(&encoder, cred_id);
*cred_id_len = 4 + 12 + rs + 16; *cred_id_len = CRED_PROTO_LEN + CRED_IV_LEN + rs + CRED_TAG_LEN + CRED_SILENT_TAG_LEN;
uint8_t key[32]; uint8_t key[32] = {0};
memset(key, 0, sizeof(key)); credential_derive_chacha_key(key, (const uint8_t *)CRED_PROTO);
credential_derive_chacha_key(key); uint8_t iv[CRED_IV_LEN] = {0};
uint8_t iv[12];
random_gen(NULL, iv, sizeof(iv)); random_gen(NULL, iv, sizeof(iv));
mbedtls_chachapoly_context chatx; mbedtls_chachapoly_context chatx;
mbedtls_chachapoly_init(&chatx); mbedtls_chachapoly_init(&chatx);
mbedtls_chachapoly_setkey(&chatx, key); mbedtls_chachapoly_setkey(&chatx, key);
int ret = mbedtls_chachapoly_encrypt_and_tag(&chatx, rs, iv, rp_id_hash, 32, int ret = mbedtls_chachapoly_encrypt_and_tag(&chatx, rs, iv, rp_id_hash, 32,
cred_id + 4 + 12, cred_id + CRED_PROTO_LEN + CRED_IV_LEN,
cred_id + 4 + 12, cred_id + CRED_PROTO_LEN + CRED_IV_LEN,
cred_id + 4 + 12 + rs); cred_id + CRED_PROTO_LEN + CRED_IV_LEN + rs);
mbedtls_chachapoly_free(&chatx); mbedtls_chachapoly_free(&chatx);
if (ret != 0) { if (ret != 0) {
CBOR_ERROR(CTAP1_ERR_OTHER); CBOR_ERROR(CTAP1_ERR_OTHER);
} }
memcpy(cred_id, CRED_PROTO, 4); memcpy(cred_id, CRED_PROTO, CRED_PROTO_LEN);
memcpy(cred_id + 4, iv, 12); memcpy(cred_id + CRED_PROTO_LEN, iv, CRED_IV_LEN);
credential_silent_tag(cred_id, *cred_id_len, rp_id_hash, cred_id + CRED_PROTO_LEN + CRED_IV_LEN + rs + CRED_TAG_LEN);
err: err:
if (error != CborNoError) { if (error != CborNoError) {
@@ -152,7 +189,7 @@ int credential_load(const uint8_t *cred_id, size_t cred_id_len, const uint8_t *r
} }
memset(cred, 0, sizeof(Credential)); memset(cred, 0, sizeof(Credential));
memcpy(copy_cred_id, cred_id, cred_id_len); memcpy(copy_cred_id, cred_id, cred_id_len);
ret = credential_verify(copy_cred_id, cred_id_len, rp_id_hash); ret = credential_verify(copy_cred_id, cred_id_len, rp_id_hash, false);
if (ret != 0) { // U2F? if (ret != 0) { // U2F?
if (cred_id_len != KEY_HANDLE_LEN || verify_key(rp_id_hash, cred_id, NULL) != 0) { if (cred_id_len != KEY_HANDLE_LEN || verify_key(rp_id_hash, cred_id, NULL) != 0) {
CBOR_ERROR(CTAP2_ERR_INVALID_CREDENTIAL); CBOR_ERROR(CTAP2_ERR_INVALID_CREDENTIAL);
@@ -350,13 +387,13 @@ int credential_derive_hmac_key(const uint8_t *cred_id, size_t cred_id_len, uint8
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA512);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "SLIP-0022", 9, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "SLIP-0022", 9, outk);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) CRED_PROTO, 4, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) cred_id, CRED_PROTO_LEN, outk);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "hmac-secret", 11, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "hmac-secret", 11, outk);
mbedtls_md_hmac(md_info, outk, 32, cred_id, cred_id_len, outk); mbedtls_md_hmac(md_info, outk, 32, cred_id, cred_id_len, outk);
return 0; return 0;
} }
int credential_derive_chacha_key(uint8_t *outk) { int credential_derive_chacha_key(uint8_t *outk, const uint8_t *proto) {
memset(outk, 0, 32); memset(outk, 0, 32);
int r = 0; int r = 0;
if ((r = load_keydev(outk)) != 0) { if ((r = load_keydev(outk)) != 0) {
@@ -365,7 +402,7 @@ int credential_derive_chacha_key(uint8_t *outk) {
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "SLIP-0022", 9, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "SLIP-0022", 9, outk);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) CRED_PROTO, 4, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) (proto ? proto : (const uint8_t *)CRED_PROTO), CRED_PROTO_LEN, outk);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "Encryption key", 14, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "Encryption key", 14, outk);
return 0; return 0;
} }
@@ -379,7 +416,7 @@ int credential_derive_large_blob_key(const uint8_t *cred_id, size_t cred_id_len,
const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "SLIP-0022", 9, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "SLIP-0022", 9, outk);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) CRED_PROTO, 4, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) cred_id, CRED_PROTO_LEN, outk);
mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "largeBlobKey", 12, outk); mbedtls_md_hmac(md_info, outk, 32, (uint8_t *) "largeBlobKey", 12, outk);
mbedtls_md_hmac(md_info, outk, 32, cred_id, cred_id_len, outk); mbedtls_md_hmac(md_info, outk, 32, cred_id, cred_id_len, outk);
return 0; return 0;

View File

@@ -56,9 +56,23 @@ typedef struct Credential {
#define CRED_PROT_UV_OPTIONAL_WITH_LIST 0x02 #define CRED_PROT_UV_OPTIONAL_WITH_LIST 0x02
#define CRED_PROT_UV_REQUIRED 0x03 #define CRED_PROT_UV_REQUIRED 0x03
#define CRED_PROTO "\xf1\xd0\x02\x01" #define CRED_PROTO_21_S "\xf1\xd0\x02\x01"
#define CRED_PROTO_22_S "\xf1\xd0\x02\x02"
extern int credential_verify(uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash); #define CRED_PROTO CRED_PROTO_22_S
#define CRED_PROTO_LEN 4
#define CRED_IV_LEN 12
#define CRED_TAG_LEN 16
#define CRED_SILENT_TAG_LEN 16
typedef enum
{
CRED_PROTO_21 = 0x01,
CRED_PROTO_22 = 0x02,
} cred_proto_t;
extern int credential_verify(uint8_t *cred_id, size_t cred_id_len, const uint8_t *rp_id_hash, bool silent);
extern int credential_create(CborCharString *rpId, extern int credential_create(CborCharString *rpId,
CborByteString *userId, CborByteString *userId,
CborCharString *userName, CborCharString *userName,

View File

@@ -112,6 +112,14 @@ mbedtls_ecp_group_id fido_curve_to_mbedtls(int curve) {
else if (curve == FIDO2_CURVE_X448) { else if (curve == FIDO2_CURVE_X448) {
return MBEDTLS_ECP_DP_CURVE448; return MBEDTLS_ECP_DP_CURVE448;
} }
#ifdef MBEDTLS_EDDSA_C
else if (curve == FIDO2_CURVE_ED25519) {
return MBEDTLS_ECP_DP_ED25519;
}
else if (curve == FIDO2_CURVE_ED448) {
return MBEDTLS_ECP_DP_ED448;
}
#endif
return MBEDTLS_ECP_DP_NONE; return MBEDTLS_ECP_DP_NONE;
} }
int mbedtls_curve_to_fido(mbedtls_ecp_group_id id) { int mbedtls_curve_to_fido(mbedtls_ecp_group_id id) {
@@ -133,10 +141,18 @@ int mbedtls_curve_to_fido(mbedtls_ecp_group_id id) {
else if (id == MBEDTLS_ECP_DP_CURVE448) { else if (id == MBEDTLS_ECP_DP_CURVE448) {
return FIDO2_CURVE_X448; return FIDO2_CURVE_X448;
} }
#ifdef MBEDTLS_EDDSA_C
else if (id == MBEDTLS_ECP_DP_ED25519) {
return FIDO2_CURVE_ED25519;
}
else if (id == MBEDTLS_ECP_DP_ED448) {
return FIDO2_CURVE_ED448;
}
#endif
return 0; return 0;
} }
int fido_load_key(int curve, const uint8_t *cred_id, mbedtls_ecdsa_context *key) { int fido_load_key(int curve, const uint8_t *cred_id, mbedtls_ecp_keypair *key) {
mbedtls_ecp_group_id mbedtls_curve = fido_curve_to_mbedtls(curve); mbedtls_ecp_group_id mbedtls_curve = fido_curve_to_mbedtls(curve);
if (mbedtls_curve == MBEDTLS_ECP_DP_NONE) { if (mbedtls_curve == MBEDTLS_ECP_DP_NONE) {
return CTAP2_ERR_UNSUPPORTED_ALGORITHM; return CTAP2_ERR_UNSUPPORTED_ALGORITHM;
@@ -202,7 +218,7 @@ int load_keydev(uint8_t *key) {
return PICOKEY_OK; return PICOKEY_OK;
} }
int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecdsa_context *key) { int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecp_keypair *key) {
for (int i = 0; i < KEY_PATH_ENTRIES; i++) { for (int i = 0; i < KEY_PATH_ENTRIES; i++) {
uint32_t k = *(uint32_t *) &keyHandle[i * sizeof(uint32_t)]; uint32_t k = *(uint32_t *) &keyHandle[i * sizeof(uint32_t)];
if (!(k & 0x80000000)) { if (!(k & 0x80000000)) {
@@ -235,7 +251,7 @@ int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecdsa_con
return memcmp(keyHandle + KEY_PATH_LEN, hmac, sizeof(hmac)); return memcmp(keyHandle + KEY_PATH_LEN, hmac, sizeof(hmac));
} }
int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int curve, mbedtls_ecdsa_context *key) { int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int curve, mbedtls_ecp_keypair *key) {
uint8_t outk[67] = { 0 }; //SECP521R1 key is 66 bytes length uint8_t outk[67] = { 0 }; //SECP521R1 key is 66 bytes length
int r = 0; int r = 0;
memset(outk, 0, sizeof(outk)); memset(outk, 0, sizeof(outk));
@@ -280,6 +296,11 @@ int derive_key(const uint8_t *app_id, bool new_key, uint8_t *key_handle, int cur
if (r != 0) { if (r != 0) {
return r; return r;
} }
#ifdef MBEDTLS_EDDSA_C
if (curve == MBEDTLS_ECP_DP_ED25519) {
return mbedtls_ecp_point_edwards(&key->grp, &key->Q, &key->d, random_gen, NULL);
}
#endif
return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G, random_gen, NULL); return mbedtls_ecp_mul(&key->grp, &key->Q, &key->d, &key->grp.G, random_gen, NULL);
} }
mbedtls_platform_zeroize(outk, sizeof(outk)); mbedtls_platform_zeroize(outk, sizeof(outk));

View File

@@ -28,6 +28,9 @@
#endif #endif
#include "mbedtls/ecdsa.h" #include "mbedtls/ecdsa.h"
#ifdef MBEDTLS_EDDSA_C
#include "mbedtls/eddsa.h"
#endif
#ifndef ENABLE_EMULATION #ifndef ENABLE_EMULATION
#include "hid/ctap_hid.h" #include "hid/ctap_hid.h"
#else #else
@@ -45,13 +48,13 @@ extern int derive_key(const uint8_t *app_id,
bool new_key, bool new_key,
uint8_t *key_handle, uint8_t *key_handle,
int, int,
mbedtls_ecdsa_context *key); mbedtls_ecp_keypair *key);
extern int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecdsa_context *); extern int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecp_keypair *);
extern bool wait_button_pressed(); extern bool wait_button_pressed();
extern void init_fido(); extern void init_fido();
extern mbedtls_ecp_group_id fido_curve_to_mbedtls(int curve); extern mbedtls_ecp_group_id fido_curve_to_mbedtls(int curve);
extern int mbedtls_curve_to_fido(mbedtls_ecp_group_id id); extern int mbedtls_curve_to_fido(mbedtls_ecp_group_id id);
extern int fido_load_key(int curve, const uint8_t *cred_id, mbedtls_ecdsa_context *key); extern int fido_load_key(int curve, const uint8_t *cred_id, mbedtls_ecp_keypair *key);
extern int load_keydev(uint8_t *key); extern int load_keydev(uint8_t *key);
extern int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, uint16_t in_len, uint8_t *out); extern int encrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, uint16_t in_len, uint8_t *out);
extern int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, uint16_t in_len, uint8_t *out); extern int decrypt(uint8_t protocol, const uint8_t *key, const uint8_t *in, uint16_t in_len, uint8_t *out);
@@ -82,6 +85,7 @@ extern int ecdh(uint8_t protocol, const mbedtls_ecp_point *Q, uint8_t *sharedSec
#define FIDO2_AUT_FLAG_ED 0x80 #define FIDO2_AUT_FLAG_ED 0x80
#define FIDO2_OPT_EA 0x01 // Enterprise Attestation #define FIDO2_OPT_EA 0x01 // Enterprise Attestation
#define FIDO2_OPT_AUV 0x02 // User Verification
#define MAX_PIN_RETRIES 8 #define MAX_PIN_RETRIES 8
extern bool getUserPresentFlagValue(); extern bool getUserPresentFlagValue();

View File

@@ -97,8 +97,21 @@ int man_get_config() {
if (!file_has_data(ef)) { if (!file_has_data(ef)) {
res_APDU[res_APDU_size++] = TAG_USB_ENABLED; res_APDU[res_APDU_size++] = TAG_USB_ENABLED;
res_APDU[res_APDU_size++] = 2; res_APDU[res_APDU_size++] = 2;
res_APDU[res_APDU_size++] = CAP_FIDO2 >> 8; uint16_t caps = 0;
res_APDU[res_APDU_size++] = CAP_OTP | CAP_U2F | CAP_OATH; if (cap_supported(CAP_FIDO2)) {
caps |= CAP_FIDO2;
}
if (cap_supported(CAP_OTP)) {
caps |= CAP_OTP;
}
if (cap_supported(CAP_U2F)) {
caps |= CAP_U2F;
}
if (cap_supported(CAP_OATH)) {
caps |= CAP_OATH;
}
res_APDU[res_APDU_size++] = caps >> 8;
res_APDU[res_APDU_size++] = caps & 0xFF;
res_APDU[res_APDU_size++] = TAG_DEVICE_FLAGS; res_APDU[res_APDU_size++] = TAG_DEVICE_FLAGS;
res_APDU[res_APDU_size++] = 1; res_APDU[res_APDU_size++] = 1;
res_APDU[res_APDU_size++] = FLAG_EJECT; res_APDU[res_APDU_size++] = FLAG_EJECT;
@@ -126,6 +139,15 @@ int cmd_write_config() {
file_t *ef = file_new(EF_DEV_CONF); file_t *ef = file_new(EF_DEV_CONF);
file_put_data(ef, apdu.data + 1, (uint16_t)(apdu.nc - 1)); file_put_data(ef, apdu.data + 1, (uint16_t)(apdu.nc - 1));
low_flash_available(); low_flash_available();
#ifndef ENABLE_EMULATION
if (cap_supported(CAP_OTP)) {
phy_data.enabled_usb_itf |= PHY_USB_ITF_KB;
}
else {
phy_data.enabled_usb_itf &= ~PHY_USB_ITF_KB;
}
phy_save();
#endif
return SW_OK(); return SW_OK();
} }

View File

@@ -584,10 +584,53 @@ int cmd_verify_hotp() {
return SW_OK(); return SW_OK();
} }
int cmd_rename() {
asn1_ctx_t ctxi, name = { 0 }, new_name = { 0 };
if (validated == false) {
return SW_SECURITY_STATUS_NOT_SATISFIED();
}
if (apdu.data[0] != TAG_NAME) {
return SW_WRONG_DATA();
}
asn1_ctx_init(apdu.data, (uint16_t)apdu.nc, &ctxi);
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) {
return SW_WRONG_DATA();
}
asn1_ctx_init(name.data + name.len, (uint16_t)(apdu.nc - (name.data + name.len - apdu.data)), &ctxi);
if (asn1_find_tag(&ctxi, TAG_NAME, &new_name) == false) {
return SW_WRONG_DATA();
}
if (memcmp(name.data, new_name.data, name.len) == 0) {
return SW_WRONG_DATA();
}
file_t *ef = find_oath_cred(name.data, name.len);
if (file_has_data(ef) == false) {
return SW_DATA_INVALID();
}
uint8_t *fdata = file_get_data(ef);
uint16_t fsize = file_get_size(ef);
asn1_ctx_init(fdata, fsize, &ctxi);
if (asn1_find_tag(&ctxi, TAG_NAME, &name) == false) {
return SW_WRONG_DATA();
}
uint8_t *new_data = (uint8_t *) calloc(sizeof(uint8_t), fsize + new_name.len - name.len);
memcpy(new_data, fdata, name.data - fdata);
*(new_data + (name.data - fdata) - 1) = new_name.len;
memcpy(new_data + (name.data - fdata), new_name.data, new_name.len);
memcpy(new_data + (name.data - fdata) + new_name.len, name.data + name.len, fsize - (name.data + name.len - fdata));
file_put_data(ef, new_data, fsize + new_name.len - name.len);
low_flash_available();
free(new_data);
return SW_OK();
}
#define INS_PUT 0x01 #define INS_PUT 0x01
#define INS_DELETE 0x02 #define INS_DELETE 0x02
#define INS_SET_CODE 0x03 #define INS_SET_CODE 0x03
#define INS_RESET 0x04 #define INS_RESET 0x04
#define INS_RENAME 0x05
#define INS_LIST 0xa1 #define INS_LIST 0xa1
#define INS_CALCULATE 0xa2 #define INS_CALCULATE 0xa2
#define INS_VALIDATE 0xa3 #define INS_VALIDATE 0xa3
@@ -603,6 +646,7 @@ static const cmd_t cmds[] = {
{ INS_DELETE, cmd_delete }, { INS_DELETE, cmd_delete },
{ INS_SET_CODE, cmd_set_code }, { INS_SET_CODE, cmd_set_code },
{ INS_RESET, cmd_reset }, { INS_RESET, cmd_reset },
{ INS_RENAME, cmd_rename },
{ INS_LIST, cmd_list }, { INS_LIST, cmd_list },
{ INS_VALIDATE, cmd_validate }, { INS_VALIDATE, cmd_validate },
{ INS_CALCULATE, cmd_calculate }, { INS_CALCULATE, cmd_calculate },

View File

@@ -111,7 +111,7 @@ typedef struct otp_config {
}) otp_config_t; }) otp_config_t;
#define otp_config_size sizeof(otp_config_t) #define otp_config_size sizeof(otp_config_t)
uint16_t otp_status(); uint16_t otp_status(bool is_otp);
int otp_process_apdu(); int otp_process_apdu();
int otp_unload(); int otp_unload();
@@ -140,10 +140,7 @@ int otp_select(app_t *a, uint8_t force) {
else { else {
config_seq = 0; config_seq = 0;
} }
otp_status(); otp_status(false);
memmove(res_APDU, res_APDU + 1, 6);
res_APDU_size = 6;
apdu.ne = res_APDU_size;
return PICOKEY_OK; return PICOKEY_OK;
} }
return PICOKEY_ERR_FILE_NOT_FOUND; return PICOKEY_ERR_FILE_NOT_FOUND;
@@ -339,22 +336,47 @@ int otp_unload() {
return PICOKEY_OK; return PICOKEY_OK;
} }
uint16_t otp_status() { uint8_t status_byte = 0x0;
uint16_t otp_status(bool is_otp) {
if (scanned == false) { if (scanned == false) {
scan_all(); scan_all();
scanned = true; scanned = true;
} }
res_APDU_size = 0; res_APDU_size = 0;
res_APDU[1] = PICO_FIDO_VERSION_MAJOR; if (is_otp) {
res_APDU[2] = PICO_FIDO_VERSION_MINOR; res_APDU_size++;
res_APDU[3] = 0; }
res_APDU[4] = config_seq; res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MAJOR;
res_APDU[5] = (CONFIG2_TOUCH | CONFIG1_TOUCH) | res_APDU[res_APDU_size++] = PICO_FIDO_VERSION_MINOR;
(file_has_data(search_dynamic_file(EF_OTP_SLOT1)) ? CONFIG1_VALID : res_APDU[res_APDU_size++] = 0;
0x00) | res_APDU[res_APDU_size++] = config_seq;
(file_has_data(search_dynamic_file(EF_OTP_SLOT2)) ? CONFIG2_VALID : uint8_t opts = 0;
0x00); file_t *ef = search_dynamic_file(EF_OTP_SLOT1);
res_APDU[6] = 0; if (file_has_data(ef)) {
opts |= CONFIG1_VALID;
otp_config_t *otp_config = (otp_config_t *) file_get_data(ef);
if (!(otp_config->tkt_flags & CHAL_RESP) || otp_config->cfg_flags & CHAL_BTN_TRIG) {
opts |= CONFIG1_TOUCH;
}
}
ef = search_dynamic_file(EF_OTP_SLOT2);
if (file_has_data(ef)) {
opts |= CONFIG2_VALID;
otp_config_t *otp_config = (otp_config_t *) file_get_data(ef);
if (!(otp_config->tkt_flags & CHAL_RESP) || otp_config->cfg_flags & CHAL_BTN_TRIG) {
opts |= CONFIG2_TOUCH;
}
}
res_APDU[res_APDU_size++] = opts;
res_APDU[res_APDU_size++] = 0;
res_APDU[res_APDU_size++] = status_byte;
if (is_otp) {
res_APDU_size = 0;
}
else {
apdu.ne = res_APDU_size;
}
return SW_OK(); return SW_OK();
} }
@@ -363,6 +385,7 @@ bool check_crc(const otp_config_t *data) {
return crc == 0xF0B8; return crc == 0xF0B8;
} }
bool _is_otp = false;
int cmd_otp() { int cmd_otp() {
uint8_t p1 = P1(apdu), p2 = P2(apdu); uint8_t p1 = P1(apdu), p2 = P2(apdu);
if (p2 != 0x00) { if (p2 != 0x00) {
@@ -386,18 +409,15 @@ int cmd_otp() {
file_put_data(ef, apdu.data, otp_config_size + 8); file_put_data(ef, apdu.data, otp_config_size + 8);
low_flash_available(); low_flash_available();
config_seq++; config_seq++;
return otp_status(); return otp_status(_is_otp);
} }
} }
// Delete slot // Delete slot
delete_file(ef); delete_file(ef);
if (!file_has_data(search_dynamic_file(EF_OTP_SLOT1)) && config_seq++;
!file_has_data(search_dynamic_file(EF_OTP_SLOT2))) { return otp_status(_is_otp);
config_seq = 0;
}
return otp_status();
} }
else if (p1 == 0x04 || p1 == 0x05) { else if (p1 == 0x04 || p1 == 0x05) { // Update slot
otp_config_t *odata = (otp_config_t *) apdu.data; otp_config_t *odata = (otp_config_t *) apdu.data;
if (odata->rfu[0] != 0 || odata->rfu[1] != 0 || check_crc(odata) == false) { if (odata->rfu[0] != 0 || odata->rfu[1] != 0 || check_crc(odata) == false) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
@@ -414,13 +434,20 @@ int cmd_otp() {
(odata->ext_flags & EXTFLAG_UPDATE_MASK); (odata->ext_flags & EXTFLAG_UPDATE_MASK);
odata->tkt_flags = (otpc->tkt_flags & ~TKTFLAG_UPDATE_MASK) | odata->tkt_flags = (otpc->tkt_flags & ~TKTFLAG_UPDATE_MASK) |
(odata->tkt_flags & TKTFLAG_UPDATE_MASK); (odata->tkt_flags & TKTFLAG_UPDATE_MASK);
odata->cfg_flags = (otpc->cfg_flags & ~CFGFLAG_UPDATE_MASK) | if (!(otpc->tkt_flags & CHAL_RESP)) {
(odata->cfg_flags & CFGFLAG_UPDATE_MASK); odata->cfg_flags = (otpc->cfg_flags & ~CFGFLAG_UPDATE_MASK) |
(odata->cfg_flags & CFGFLAG_UPDATE_MASK);
}
else {
odata->cfg_flags = otpc->cfg_flags;
}
file_put_data(ef, apdu.data, otp_config_size); file_put_data(ef, apdu.data, otp_config_size);
low_flash_available(); low_flash_available();
config_seq++;
} }
return otp_status(_is_otp);
} }
else if (p1 == 0x06) { else if (p1 == 0x06) { // Swap slots
uint8_t tmp[otp_config_size + 8]; uint8_t tmp[otp_config_size + 8];
bool ef1_data = false; bool ef1_data = false;
file_t *ef1 = file_new(EF_OTP_SLOT1); file_t *ef1 = file_new(EF_OTP_SLOT1);
@@ -434,6 +461,8 @@ int cmd_otp() {
} }
else { else {
delete_file(ef1); delete_file(ef1);
// When a dynamic file is deleted, existing referenes are invalidated
ef2 = file_new(EF_OTP_SLOT2);
} }
if (ef1_data) { if (ef1_data) {
file_put_data(ef2, tmp, sizeof(tmp)); file_put_data(ef2, tmp, sizeof(tmp));
@@ -442,34 +471,60 @@ int cmd_otp() {
delete_file(ef2); delete_file(ef2);
} }
low_flash_available(); low_flash_available();
config_seq++;
return otp_status(_is_otp);
} }
else if (p1 == 0x10) { else if (p1 == 0x10) {
memcpy(res_APDU, pico_serial.id, 4); memcpy(res_APDU, pico_serial.id, 4);
res_APDU_size = 4; res_APDU_size = 4;
} }
else if (p1 == 0x13) { else if (p1 == 0x13) { // Get config
man_get_config(); man_get_config();
} }
else if (p1 == 0x30 || p1 == 0x38 || p1 == 0x20 || p1 == 0x28) { else if (p1 == 0x30 || p1 == 0x38 || p1 == 0x20 || p1 == 0x28) { // Calculate OTP
file_t *ef = search_dynamic_file(p1 == 0x30 || p1 == 0x20 ? EF_OTP_SLOT1 : EF_OTP_SLOT2); file_t *ef = search_dynamic_file(p1 == 0x30 || p1 == 0x20 ? EF_OTP_SLOT1 : EF_OTP_SLOT2);
if (file_has_data(ef)) { if (file_has_data(ef)) {
otp_config_t *otp_config = (otp_config_t *) file_get_data(ef); otp_config_t *otp_config = (otp_config_t *) file_get_data(ef);
if (!(otp_config->cfg_flags & CHAL_YUBICO && otp_config->tkt_flags & CHAL_RESP)) { if (!(otp_config->tkt_flags & CHAL_RESP)) {
return SW_WRONG_DATA(); return SW_WRONG_DATA();
} }
int ret = 0; int ret = 0;
#ifndef ENABLE_EMULATION
uint8_t *rdata_bk = apdu.rdata;
if (otp_config->cfg_flags & CHAL_BTN_TRIG) {
status_byte = 0x20;
otp_status(_is_otp);
if (wait_button() == true) {
status_byte = 0x00;
otp_status(_is_otp);
return SW_CONDITIONS_NOT_SATISFIED();
}
status_byte = 0x10;
apdu.rdata = rdata_bk;
}
#endif
if (p1 == 0x30 || p1 == 0x38) { if (p1 == 0x30 || p1 == 0x38) {
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), if (!(otp_config->cfg_flags & CHAL_HMAC)) {
otp_config->aes_key, return SW_WRONG_DATA();
KEY_SIZE, }
apdu.data, uint8_t aes_key[KEY_SIZE + UID_SIZE];
8, memcpy(aes_key, otp_config->aes_key, KEY_SIZE);
res_APDU); memcpy(aes_key + KEY_SIZE, otp_config->uid, UID_SIZE);
uint8_t chal_len = 64;
if (otp_config->cfg_flags & HMAC_LT64) {
while (chal_len > 0 && apdu.data[63] == apdu.data[chal_len - 1]) {
chal_len--;
}
}
mbedtls_md_hmac(mbedtls_md_info_from_type(MBEDTLS_MD_SHA1), aes_key, sizeof(aes_key), apdu.data, chal_len, res_APDU);
if (ret == 0) { if (ret == 0) {
res_APDU_size = 20; res_APDU_size = 20;
} }
} }
else if (p1 == 0x20 || p1 == 0x28) { else if (p1 == 0x20 || p1 == 0x28) {
if (!(otp_config->cfg_flags & CHAL_YUBICO)) {
return SW_WRONG_DATA();
}
uint8_t challenge[16]; uint8_t challenge[16];
memcpy(challenge, apdu.data, 6); memcpy(challenge, apdu.data, 6);
memcpy(challenge + 6, pico_serial_str, 10); memcpy(challenge + 6, pico_serial_str, 10);
@@ -482,6 +537,9 @@ int cmd_otp() {
res_APDU_size = 16; res_APDU_size = 16;
} }
} }
if (ret == 0) {
status_byte = 0x00;
}
} }
} }
return SW_OK(); return SW_OK();
@@ -530,49 +588,45 @@ int otp_send_frame(uint8_t *frame, size_t frame_len) {
return 0; return 0;
} }
int otp_hid_set_report_cb(uint8_t itf, int otp_hid_set_report_cb(uint8_t itf, uint8_t report_id, hid_report_type_t report_type, uint8_t const *buffer, uint16_t bufsize) {
uint8_t report_id, if (report_type == 3) {
hid_report_type_t report_type, DEBUG_PAYLOAD(buffer, bufsize);
uint8_t const *buffer, if (buffer[7] == 0xFF) { // reset
uint16_t bufsize) *get_send_buffer_size(ITF_KEYBOARD) = 0;
{ otp_curr_seq = otp_exp_seq = 0;
if (itf == ITF_KEYBOARD) { memset(otp_frame_tx, 0, sizeof(otp_frame_tx));
if (report_type == 3) { }
DEBUG_PAYLOAD(buffer, bufsize); else if (buffer[7] & 0x80) { // a frame
if (buffer[7] == 0xFF) { // reset uint8_t rseq = buffer[7] & 0x1F;
*get_send_buffer_size(ITF_KEYBOARD) = 0; if (rseq < 10) {
otp_curr_seq = otp_exp_seq = 0; if (rseq == 0) {
memset(otp_frame_tx, 0, sizeof(otp_frame_tx)); memset(otp_frame_rx, 0, sizeof(otp_frame_rx));
} }
else if (buffer[7] & 0x80) { // a frame memcpy(otp_frame_rx + rseq * 7, buffer, 7);
uint8_t rseq = buffer[7] & 0x1F; if (rseq == 9) {
if (rseq < 10) { DEBUG_DATA(otp_frame_rx, sizeof(otp_frame_rx));
if (rseq == 0) { DEBUG_PAYLOAD(otp_frame_rx, sizeof(otp_frame_rx));
memset(otp_frame_rx, 0, sizeof(otp_frame_rx)); uint16_t residual_crc = calculate_crc(otp_frame_rx, 64), rcrc = get_uint16_t_le(otp_frame_rx + 65);
uint8_t slot_id = otp_frame_rx[64];
if (residual_crc == rcrc) {
uint8_t hdr[5];
apdu.header = hdr;
apdu.data = otp_frame_rx;
apdu.nc = 64;
apdu.rdata = otp_frame_tx;
apdu.header[0] = 0;
apdu.header[1] = 0x01;
apdu.header[2] = slot_id;
apdu.header[3] = 0;
_is_otp = true;
int ret = otp_process_apdu();
if (ret == 0x9000 && res_APDU_size > 0) {
otp_send_frame(apdu.rdata, apdu.rlen);
}
_is_otp = false;
} }
memcpy(otp_frame_rx + rseq * 7, buffer, 7); else {
if (rseq == 9) { printf("[OTP] Bad CRC!\n");
DEBUG_DATA(otp_frame_rx, sizeof(otp_frame_rx));
uint16_t residual_crc = calculate_crc(otp_frame_rx, 64), rcrc = get_uint16_t_le(otp_frame_rx + 65);
uint8_t slot_id = otp_frame_rx[64];
if (residual_crc == rcrc) {
uint8_t hdr[5];
apdu.header = hdr;
apdu.data = otp_frame_rx;
apdu.nc = 64;
apdu.rdata = otp_frame_tx;
apdu.header[0] = 0;
apdu.header[1] = 0x01;
apdu.header[2] = slot_id;
apdu.header[3] = 0;
int ret = otp_process_apdu();
if (ret == 0x9000 && res_APDU_size > 0) {
otp_send_frame(apdu.rdata, apdu.rlen);
}
}
else {
printf("[OTP] Bad CRC!\n");
}
} }
} }
} }
@@ -610,7 +664,8 @@ uint16_t otp_hid_get_report_cb(uint8_t itf,
} }
else { else {
res_APDU = buffer; res_APDU = buffer;
otp_status(); otp_status(true);
DEBUG_DATA(buffer, 8);
} }
return reqlen; return reqlen;

View File

@@ -18,7 +18,7 @@
#ifndef __VERSION_H_ #ifndef __VERSION_H_
#define __VERSION_H_ #define __VERSION_H_
#define PICO_FIDO_VERSION 0x0602 #define PICO_FIDO_VERSION 0x0606
#define PICO_FIDO_VERSION_MAJOR ((PICO_FIDO_VERSION >> 8) & 0xff) #define PICO_FIDO_VERSION_MAJOR ((PICO_FIDO_VERSION >> 8) & 0xff)
#define PICO_FIDO_VERSION_MINOR (PICO_FIDO_VERSION & 0xff) #define PICO_FIDO_VERSION_MINOR (PICO_FIDO_VERSION & 0xff)

View File

@@ -3,5 +3,5 @@
source tests/docker_env.sh source tests/docker_env.sh
#run_in_docker rm -rf CMakeFiles #run_in_docker rm -rf CMakeFiles
run_in_docker mkdir -p build_in_docker run_in_docker mkdir -p build_in_docker
run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 .. run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 -DENABLE_EDDSA=1 ..
run_in_docker -w "$PWD/build_in_docker" make -j ${NUM_PROC} run_in_docker -w "$PWD/build_in_docker" make -j ${NUM_PROC}

View File

@@ -19,7 +19,7 @@
from fido2.client import CtapError from fido2.client import CtapError
from fido2.cose import ES256, ES384, ES512 from fido2.cose import ES256, ES384, ES512, EdDSA
import fido2.features import fido2.features
fido2.features.webauthn_json_mapping.enabled = False fido2.features.webauthn_json_mapping.enabled = False
from utils import ES256K from utils import ES256K
@@ -124,7 +124,7 @@ def test_bad_type_pubKeyCredParams(device):
device.doMC(key_params=["wrong"]) device.doMC(key_params=["wrong"])
@pytest.mark.parametrize( @pytest.mark.parametrize(
"alg", [ES256.ALGORITHM, ES384.ALGORITHM, ES512.ALGORITHM, ES256K.ALGORITHM] "alg", [ES256.ALGORITHM, ES384.ALGORITHM, ES512.ALGORITHM, ES256K.ALGORITHM, EdDSA.ALGORITHM]
) )
def test_algorithms(device, info, alg): def test_algorithms(device, info, alg):
if ({'alg': alg, 'type': 'public-key'} in info.algorithms): if ({'alg': alg, 'type': 'public-key'} in info.algorithms):

View File

@@ -19,7 +19,7 @@
from fido2.client import CtapError from fido2.client import CtapError
from fido2.cose import ES256, ES384, ES512 from fido2.cose import ES256, ES384, ES512, EdDSA
from utils import verify, ES256K from utils import verify, ES256K
import pytest import pytest
@@ -49,7 +49,7 @@ def test_empty_allowList(device):
assert e.value.code == CtapError.ERR.NO_CREDENTIALS assert e.value.code == CtapError.ERR.NO_CREDENTIALS
@pytest.mark.parametrize( @pytest.mark.parametrize(
"alg", [ES256.ALGORITHM, ES384.ALGORITHM, ES512.ALGORITHM, ES256K.ALGORITHM] "alg", [ES256.ALGORITHM, ES384.ALGORITHM, ES512.ALGORITHM, ES256K.ALGORITHM, EdDSA.ALGORITHM]
) )
def test_algorithms(device, info, alg): def test_algorithms(device, info, alg):
if ({'alg': alg, 'type': 'public-key'} in info.algorithms): if ({'alg': alg, 'type': 'public-key'} in info.algorithms):
@@ -213,11 +213,19 @@ def test_allow_list_missing_id(device, MCRes):
] ]
) )
def test_user_presence_option_false(device, MCRes): def test_silent_ok(device, MCRes):
res = device.GA(options={"up": False}, allow_list=[ res = device.GA(options={"up": False}, allow_list=[
{"id": MCRes['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"} {"id": MCRes['res'].attestation_object.auth_data.credential_data.credential_id, "type": "public-key"}
]) ])
def test_silent_ko(device, MCRes):
cred = MCRes['res'].attestation_object.auth_data.credential_data.credential_id + b'\x00'
with pytest.raises(CtapError) as e:
res = device.GA(options={"up": False}, allow_list=[
{"id": cred, "type": "public-key"}
])
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
def test_credential_resets(device, MCRes, GARes): def test_credential_resets(device, MCRes, GARes):
device.reset() device.reset()
with pytest.raises(CtapError) as e: with pytest.raises(CtapError) as e:

View File

@@ -57,9 +57,8 @@ def test_with_allow_list_after_reset(device, MCRes_DC, GARes_DC):
device.reset() device.reset()
with pytest.raises(CtapError) as e: # It returns a silent authentication
ga_res = device.doGA(allow_list=allow_list) ga_res = device.doGA(allow_list=allow_list)
assert e.value.code == CtapError.ERR.NO_CREDENTIALS
@@ -255,5 +254,5 @@ def test_returned_credential(device):
device.GNA() device.GNA()
# the returned credential should have user id in it # the returned credential should have user id in it
print(ga_res) #print(ga_res)
assert 'id' in ga_res.user and len(ga_res.user["id"]) > 0 #assert 'id' in ga_res.user and len(ga_res.user["id"]) > 0

View File

@@ -69,7 +69,7 @@ def test_minpin(SetMinPin, MCMinPin):
def test_minpin_bad_rpid(SetMinPinWrongRpid, MCMinPin): def test_minpin_bad_rpid(SetMinPinWrongRpid, MCMinPin):
assert not MCMinPin.auth_data.extensions assert not MCMinPin.auth_data.extensions
assert "minPinLength" not in MCMinPin.auth_data.extensions #assert "minPinLength" not in MCMinPin.auth_data.extensions
def test_setminpin(device, SetMinPin, MCMinPin): def test_setminpin(device, SetMinPin, MCMinPin):
cfg = FidoConfig(device) cfg = FidoConfig(device)

View File

@@ -7,7 +7,7 @@ if [[ $1 == "pico" ]]; then
sudo apt install -y cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib 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 git clone https://github.com/raspberrypi/pico-sdk
cd pico-sdk cd pico-sdk
git checkout tags/2.1.0 git checkout tags/2.1.1
git submodule update --init git submodule update --init
cd .. cd ..
git clone https://github.com/raspberrypi/picotool git clone https://github.com/raspberrypi/picotool
@@ -37,6 +37,16 @@ mkdir -p release
cd build cd build
esptool.py --chip ESP32-S3 merge_bin -o ../release/pico_fido_esp32-s3.bin @flash_args esptool.py --chip ESP32-S3 merge_bin -o ../release/pico_fido_esp32-s3.bin @flash_args
cd .. cd ..
cd esp-idf
./install.sh esp32s2
. ./export.sh
cd ..
idf.py set-target esp32s2
idf.py all
mkdir -p release
cd build
esptool.py --chip ESP32-S2 merge_bin -o ../release/pico_fido_esp32-s2.bin @flash_args
cd ..
else else
mkdir build mkdir build
cd build cd build