11 Commits

Author SHA1 Message Date
Pol Henarejos
df949f3d45 Harden GitHub workflows
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-12 17:21:04 +02:00
Pol Henarejos
4d13107aac Fix mbedtls runtime link.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-11 22:07:57 +02:00
Pol Henarejos
be6bda1baa Fix build for 2040
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-11 16:48:14 +02:00
Pol Henarejos
ac2d839c15 Add board invariant trust zone.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-10 17:51:51 +02:00
Pol Henarejos
0982522447 Added trusted region.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-08 16:41:16 +02:00
Pol Henarejos
f7edfc916a Refactor HWRNG to be less blocking.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-08 12:08:57 +02:00
Pol Henarejos
0fd81c47d6 Refactor HWRNG to be less blocking.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-08 12:07:32 +02:00
Pol Henarejos
9ffcfb4beb Harden core-shared command/result state
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-01 13:38:36 +02:00
Pol Henarejos
3ccd6e827f Add cancel button event.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-01 01:43:25 +02:00
Pol Henarejos
a2044d697d Set persistent rpId, userName and userDisplay.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-01 00:22:18 +02:00
Pol Henarejos
659c04c837 Add slots for button signals.
Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
2026-06-01 00:15:22 +02:00
13 changed files with 68 additions and 20 deletions

View File

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

View File

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

View File

@@ -21,16 +21,22 @@ on:
- cron: '23 5 * * 4' - cron: '23 5 * * 4'
workflow_dispatch: workflow_dispatch:
permissions:
contents: read
jobs: jobs:
build: build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
contents: read
steps: steps:
- name: Checkout repository and submodules - name: Checkout repository and submodules
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
submodules: recursive submodules: recursive
persist-credentials: false
- name: Build in container - name: Build in container
run: ./tests/build-in-docker.sh run: ./tests/build-in-docker.sh
- name: Start emulation and test - name: Start emulation and test

View File

@@ -34,9 +34,9 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next);
const uint8_t aaguid[16] = { 0x89, 0xFB, 0x94, 0xB7, 0x06, 0xC9, 0x36, 0x73, 0x9B, 0x7E, 0x30, 0x52, 0x6D, 0x96, 0x81, 0x45 }; // First 16 bytes of SHA256("Pico FIDO2") const uint8_t aaguid[16] = { 0x89, 0xFB, 0x94, 0xB7, 0x06, 0xC9, 0x36, 0x73, 0x9B, 0x7E, 0x30, 0x52, 0x6D, 0x96, 0x81, 0x45 }; // First 16 bytes of SHA256("Pico FIDO2")
const uint8_t *cbor_data = NULL; static const uint8_t *volatile cbor_data = NULL;
size_t cbor_len = 0; static volatile size_t cbor_len = 0;
uint8_t cbor_cmd = 0; static volatile uint8_t cbor_cmd = 0;
int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) { int cbor_parse(uint8_t cmd, const uint8_t *data, size_t len) {
if (len == 0 && cmd == CTAPHID_CBOR) { if (len == 0 && cmd == CTAPHID_CBOR) {
@@ -108,7 +108,10 @@ void *cbor_thread(void *arg) {
if (m == EV_EXIT) { if (m == EV_EXIT) {
break; break;
} }
apdu.sw = (uint16_t)cbor_parse(cbor_cmd, cbor_data, cbor_len); const uint8_t *data = (const uint8_t *)cbor_data;
size_t len = cbor_len;
uint8_t cmd = cbor_cmd;
apdu.sw = (uint16_t)cbor_parse(cmd, data, len);
if (apdu.sw == 0) { if (apdu.sw == 0) {
DEBUG_DATA(res_APDU, res_APDU_size); DEBUG_DATA(res_APDU, res_APDU_size);
} }

View File

@@ -32,6 +32,7 @@
#include "random.h" #include "random.h"
int cbor_get_assertion(const uint8_t *data, size_t len, bool next); int cbor_get_assertion(const uint8_t *data, size_t len, bool next);
extern char *rp_id, *user_name, *display_name;
bool residentx = false; bool residentx = false;
Credential credsx[MAX_CREDENTIAL_COUNT_IN_LIST] = { 0 }; Credential credsx[MAX_CREDENTIAL_COUNT_IN_LIST] = { 0 };
@@ -205,6 +206,9 @@ int cbor_get_assertion(const uint8_t *data, size_t len, bool next) {
if (rpId.present == false || clientDataHash.present == false) { if (rpId.present == false || clientDataHash.present == false) {
CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER); CBOR_ERROR(CTAP2_ERR_MISSING_PARAMETER);
} }
rp_id = rpId.data;
user_name = NULL;
display_name = NULL;
uint8_t flags = 0; uint8_t flags = 0;
uint8_t rp_id_hash[32] = {0}; uint8_t rp_id_hash[32] = {0};

View File

@@ -28,6 +28,8 @@
#include "random.h" #include "random.h"
#include "crypto_utils.h" #include "crypto_utils.h"
char *rp_id = NULL, *user_name = NULL, *display_name = NULL;
int cbor_make_credential(const uint8_t *data, size_t len) { int cbor_make_credential(const uint8_t *data, size_t len) {
CborParser parser; CborParser parser;
CborValue map; CborValue map;
@@ -192,6 +194,9 @@ int cbor_make_credential(const uint8_t *data, size_t len) {
} }
} }
CBOR_PARSE_MAP_END(map, 1); CBOR_PARSE_MAP_END(map, 1);
rp_id = rp.id.data;
user_name = user.parent.name.data;
display_name = user.displayName.data;
uint8_t flags = FIDO2_AUT_FLAG_AT; uint8_t flags = FIDO2_AUT_FLAG_AT;
uint8_t rp_id_hash[32] = {0}; uint8_t rp_id_hash[32] = {0};

View File

@@ -35,7 +35,7 @@ int cbor_reset(void) {
return CTAP2_ERR_NOT_ALLOWED; return CTAP2_ERR_NOT_ALLOWED;
} }
#endif #endif
if (wait_button_pressed() == true) { if (wait_button_pressed() > 0) {
return CTAP2_ERR_USER_ACTION_TIMEOUT; return CTAP2_ERR_USER_ACTION_TIMEOUT;
} }
#endif #endif

View File

@@ -20,9 +20,16 @@
#include "ctap2_cbor.h" #include "ctap2_cbor.h"
#include "ctap.h" #include "ctap.h"
extern char *rp_id, *user_name, *display_name;
int cbor_selection(void) { int cbor_selection(void) {
if (wait_button_pressed() == true) { rp_id = user_name = display_name = NULL;
int ret = wait_button_pressed() ;
if (ret == 1) {
return CTAP2_ERR_USER_ACTION_TIMEOUT; return CTAP2_ERR_USER_ACTION_TIMEOUT;
} }
else if (ret == 2) {
return CTAP2_ERR_OPERATION_DENIED;
}
return CTAP2_OK; return CTAP2_OK;
} }

View File

@@ -34,7 +34,7 @@ int cmd_authenticate(void) {
if (req->keyHandleLen < KEY_HANDLE_LEN) { if (req->keyHandleLen < KEY_HANDLE_LEN) {
return SW_INCORRECT_PARAMS(); return SW_INCORRECT_PARAMS();
} }
if (P1(apdu) == CTAP_AUTH_ENFORCE && wait_button_pressed() == true) { if (P1(apdu) == CTAP_AUTH_ENFORCE && wait_button_pressed() > 0) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
} }

View File

@@ -63,7 +63,7 @@ int cmd_register(void) {
if (apdu.nc != CTAP_APPID_SIZE + CTAP_CHAL_SIZE) { if (apdu.nc != CTAP_APPID_SIZE + CTAP_CHAL_SIZE) {
return SW_WRONG_LENGTH(); return SW_WRONG_LENGTH();
} }
if (wait_button_pressed() == true) { if (wait_button_pressed() > 0) {
return SW_CONDITIONS_NOT_SATISFIED(); return SW_CONDITIONS_NOT_SATISFIED();
} }
if (memcmp(req->appId, bogus_firefox, if (memcmp(req->appId, bogus_firefox,

View File

@@ -498,22 +498,28 @@ void init_fido(void) {
needs_power_cycle = false; needs_power_cycle = false;
} }
bool wait_button_pressed(void) { int wait_button_pressed(void) {
uint32_t val = EV_PRESS_BUTTON; uint32_t val = EV_PRESS_BUTTON;
#if defined(PICO_PLATFORM) || defined(ESP_PLATFORM) #if defined(PICO_PLATFORM) || defined(ESP_PLATFORM)
queue_try_add(&card_to_usb_q, &val); queue_try_add(&card_to_usb_q, &val);
do { do {
queue_remove_blocking(&usb_to_card_q, &val); queue_remove_blocking(&usb_to_card_q, &val);
} while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT); } while (val != EV_BUTTON_PRESSED && val != EV_BUTTON_TIMEOUT && val != EV_BUTTON_CANCELLED);
#endif #endif
return val == EV_BUTTON_TIMEOUT; if (val == EV_BUTTON_TIMEOUT) {
return 1;
}
else if (val == EV_BUTTON_CANCELLED) {
return 2;
}
return 0;
} }
uint32_t user_present_time_limit = 0; uint32_t user_present_time_limit = 0;
bool check_user_presence(void) { bool check_user_presence(void) {
if (user_present_time_limit == 0 || user_present_time_limit + TRANSPORT_TIME_LIMIT < board_millis()) { if (user_present_time_limit == 0 || user_present_time_limit + TRANSPORT_TIME_LIMIT < board_millis()) {
if (wait_button_pressed() == true) { //timeout if (wait_button_pressed() > 0) { //timeout
return false; return false;
} }
//user_present_time_limit = board_millis(); //user_present_time_limit = board_millis();

View File

@@ -41,7 +41,7 @@ extern int derive_key(const uint8_t *app_id,
int, int,
mbedtls_ecp_keypair *key); mbedtls_ecp_keypair *key);
extern int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecp_keypair *); extern int verify_key(const uint8_t *appId, const uint8_t *keyHandle, mbedtls_ecp_keypair *);
extern bool wait_button_pressed(void); extern int wait_button_pressed(void);
extern void init_fido(void); extern void init_fido(void);
extern void init_otp(void); extern void init_otp(void);
extern void scan_all(void); extern void scan_all(void);