From db53eb8ad86e58c3043830400b1de3154f15f7cd Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 30 Jun 2026 13:56:08 +0200 Subject: [PATCH] Add audit system. Signed-off-by: Pol Henarejos --- picokeys_sdk_import.cmake | 1 + src/apdu.h | 7 ++++ src/audit.c | 39 +++++++++++++++++++ src/audit.h | 64 ++++++++++++++++++++++++++++++++ src/main.c | 2 + src/plugin/picokeys_plugin_api.h | 16 ++++++-- src/plugin/plugin_loader.c | 26 ++++++++----- src/rescue.c | 25 +++++++++---- 8 files changed, 161 insertions(+), 19 deletions(-) create mode 100644 src/audit.c create mode 100644 src/audit.h diff --git a/picokeys_sdk_import.cmake b/picokeys_sdk_import.cmake index 1c33f43..78dfa11 100644 --- a/picokeys_sdk_import.cmake +++ b/picokeys_sdk_import.cmake @@ -342,6 +342,7 @@ list(APPEND PICOKEYS_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/button.c ${CMAKE_CURRENT_LIST_DIR}/src/led/led.c ${CMAKE_CURRENT_LIST_DIR}/src/signal.c + ${CMAKE_CURRENT_LIST_DIR}/src/audit.c ) if(ESP_PLATFORM) diff --git a/src/apdu.h b/src/apdu.h index f0c8375..5874f49 100644 --- a/src/apdu.h +++ b/src/apdu.h @@ -34,9 +34,16 @@ extern bool app_exists(const uint8_t *aid, size_t aid_len); extern int register_app(int (*)(app_t *, uint8_t), const uint8_t *); extern int select_app(const uint8_t *aid, size_t aid_len); +typedef enum { + CMD_FLAG_NONE = 0x00, + CMD_FLAG_AUDIT_LOG = 0x01, + CMD_FLAG_CRITICAL = 0x02, +} cmd_flags_t; + typedef struct cmd { uint8_t ins; int (*cmd_handler)(void); + cmd_flags_t flags; } cmd_t; extern uint8_t num_apps; diff --git a/src/audit.c b/src/audit.c new file mode 100644 index 0000000..9fd0fee --- /dev/null +++ b/src/audit.c @@ -0,0 +1,39 @@ +/* + * This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#include "picokeys.h" +#include "signal.h" +#include "audit.h" + +void audit_entry_set_current_event(uint16_t event) { + signal_audit_evt_data_t data = {.cmd = AUDIT_CMD_EVT, .value = event}; + signal_emit_param(SIGNAL_AUDIT_EVT, &data); +} + +void audit_log_current_entry_with_result(uint16_t result) { + signal_audit_evt_data_t data = {.cmd = AUDIT_CMD_LOG, .value = result}; + signal_emit_param(SIGNAL_AUDIT_EVT, &data); +} + +void audit_entry_set_current_flags(audit_entry_flags_t flags) { + signal_audit_evt_data_t data = {.cmd = AUDIT_CMD_SET_FLAGS, .value = flags}; + signal_emit_param(SIGNAL_AUDIT_EVT, &data); +} +void audit_entry_set_current_object(uint16_t object_id) { + signal_audit_evt_data_t data = {.cmd = AUDIT_CMD_SET_OBJECT, .value = object_id}; + signal_emit_param(SIGNAL_AUDIT_EVT, &data); +} diff --git a/src/audit.h b/src/audit.h new file mode 100644 index 0000000..a08a146 --- /dev/null +++ b/src/audit.h @@ -0,0 +1,64 @@ +/* + * This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +#ifndef _AUDIT_H_ +#define _AUDIT_H_ + +#include + +static const uint8_t SIGNAL_AUDIT_EVT = 10; +#define AUDIT_EVT_APP_EVT 0x8000 + +typedef enum { + AUDIT_EVT_LOG_READ = 0x0001, + AUDIT_EVT_LOG_CLEARED, + AUDIT_EVT_FIRMWARE_UPDATE, + AUDIT_EVT_INIT, + AUDIT_EVT_POWER_UP, + AUDIT_EVT_SET_RTC, +} audit_evt_t; + +typedef enum { + AUDIT_EF_SUCCESS = 0x0001, + AUDIT_EF_FAIL = 0x0002, + AUDIT_EF_DENIED = 0x0004, + + AUDIT_EF_USER = 0x0010, + AUDIT_EF_ADMIN = 0x0020, + + AUDIT_EF_CRITICAL = 0x0100, + AUDIT_EF_TIME_UNSYNCED = 0x0200, +} audit_entry_flags_t; + +typedef enum { + AUDIT_CMD_EVT = 1, + AUDIT_CMD_SET_OBJECT = 2, + AUDIT_CMD_SET_FLAGS = 3, + AUDIT_CMD_LOG = 4 +} audit_cmd_t; + +typedef struct { + audit_cmd_t cmd; + uint16_t value; +} signal_audit_evt_data_t; + +extern void audit_entry_set_current_event(uint16_t event); +extern void audit_entry_set_current_flags(audit_entry_flags_t flags); +extern void audit_entry_set_current_object(uint16_t object_id); +extern void audit_log_current_entry_with_result(uint16_t res); + +#endif // _AUDIT_H_ diff --git a/src/main.c b/src/main.c index bd9daf2..b59f923 100644 --- a/src/main.c +++ b/src/main.c @@ -42,6 +42,7 @@ #include "pico_time.h" #include "serial.h" #include "mbedtls/sha256.h" +#include "signal.h" app_t apps[16]; uint8_t num_apps = 0; @@ -222,6 +223,7 @@ int main(void) { #if defined(PICO_RP2350) || defined(ENABLE_EMULATION) plugin_init(); #endif + signal_emit(SIGNAL_INIT); #ifdef ESP_PLATFORM xTaskCreatePinnedToCore(core0_loop, "core0", 4096*ITF_TOTAL*2, NULL, CONFIG_TINYUSB_TASK_PRIORITY - 1, &hcore0, ESP32_CORE0); diff --git a/src/plugin/picokeys_plugin_api.h b/src/plugin/picokeys_plugin_api.h index 6e41ff5..d38644b 100644 --- a/src/plugin/picokeys_plugin_api.h +++ b/src/plugin/picokeys_plugin_api.h @@ -1,16 +1,25 @@ /* * This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk). - * Copyright (c) 2026 Pol Henarejos. + * Copyright (c) 2022 Pol Henarejos. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . */ #ifndef PICOKEYS_PLUGIN_API_H #define PICOKEYS_PLUGIN_API_H #include +#include "signal.h" #if defined(_WIN32) #define PICOKEYS_PLUGIN_EXPORT __declspec(dllexport) @@ -47,16 +56,17 @@ typedef struct pk_plugin_imports { uint32_t abi_version; uint32_t struct_size; int (*printf)(const char *fmt, ...); + int (*signal_add)(uint8_t code, signal_flag_t flags, signal_handler_t handler); } pk_plugin_imports_t; -typedef void (*pk_plugin_hello_fn)(const pk_plugin_imports_t *imports); +typedef void (*pk_plugin_init_fn)(const pk_plugin_imports_t *imports); typedef struct pk_plugin_header { uint32_t magic; uint32_t abi_version; uint32_t header_size; uint32_t image_size; - pk_plugin_hello_fn hello; + pk_plugin_init_fn init; } pk_plugin_header_t; void plugin_init(void); diff --git a/src/plugin/plugin_loader.c b/src/plugin/plugin_loader.c index c655478..3457d04 100644 --- a/src/plugin/plugin_loader.c +++ b/src/plugin/plugin_loader.c @@ -1,13 +1,22 @@ /* * This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk). - * Copyright (c) 2026 Pol Henarejos. + * Copyright (c) 2022 Pol Henarejos. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . */ #include "picokeys_plugin_api.h" +#include "signal.h" #include #include @@ -68,7 +77,7 @@ static const pk_plugin_header_t *pk_plugin_get_valid(void) { (unsigned long)plugin->abi_version, (unsigned long)plugin->header_size, (unsigned long)plugin->image_size, - (void *)plugin->hello); + (void *)plugin->init); if (plugin->magic != PICOKEYS_PLUGIN_MAGIC) { printf("Plugin rejected: bad magic\n"); return NULL; @@ -81,7 +90,7 @@ static const pk_plugin_header_t *pk_plugin_get_valid(void) { printf("Plugin rejected: short header\n"); return NULL; } - if (!plugin->hello) { + if (!plugin->init) { printf("Plugin rejected: missing entry point\n"); return NULL; } @@ -108,7 +117,7 @@ static const pk_plugin_header_t *pk_plugin_get_valid(void) { (unsigned long)plugin->abi_version, (unsigned long)plugin->header_size, (unsigned long)plugin->image_size, - (unsigned long)(uintptr_t)plugin->hello); + (unsigned long)(uintptr_t)plugin->init); if (plugin->magic != PICOKEYS_PLUGIN_MAGIC) { printf("Plugin rejected: bad magic\n"); return NULL; @@ -126,8 +135,8 @@ static const pk_plugin_header_t *pk_plugin_get_valid(void) { printf("Plugin rejected: bad image size\n"); return NULL; } - if (!plugin->hello || !pk_plugin_ptr_in_range((const void *)plugin->hello)) { - printf("Plugin rejected: hello pointer out of range\n"); + if (!plugin->init || !pk_plugin_ptr_in_range((const void *)plugin->init)) { + printf("Plugin rejected: init pointer out of range\n"); return NULL; } return plugin; @@ -145,8 +154,7 @@ void plugin_init(void) { .abi_version = PICOKEYS_PLUGIN_ABI_VERSION, .struct_size = sizeof(imports), .printf = printf, + .signal_add = signal_add, }; - printf("Calling plugin hello function\n"); - plugin->hello(&imports); - printf("Plugin hello function returned\n"); + plugin->init(&imports); } diff --git a/src/rescue.c b/src/rescue.c index 8b56aef..d6d1fa2 100644 --- a/src/rescue.c +++ b/src/rescue.c @@ -31,6 +31,7 @@ #include "random.h" #include "crypto_utils.h" #include "usb.h" +#include "audit.h" #ifdef PICO_PLATFORM extern char __flash_binary_start; @@ -257,6 +258,7 @@ static int cmd_write(void) { #endif } else if (p1 == 0x2) { // SET TIME + audit_entry_set_current_event(AUDIT_EVT_SET_RTC); time_t tv_sec = 0; if (p2 != 0x1 && p2 != 0x2) { return SW_INCORRECT_P1P2(); @@ -405,16 +407,17 @@ static int cmd_reboot_bootsel(void) { #define INS_REBOOT_BOOTSEL 0x1F static const cmd_t cmds[] = { - { INS_KEYDEV_SIGN, cmd_keydev_sign }, - { INS_WRITE, cmd_write }, + { INS_KEYDEV_SIGN, cmd_keydev_sign, CMD_FLAG_AUDIT_LOG }, + { INS_WRITE, cmd_write, CMD_FLAG_AUDIT_LOG | CMD_FLAG_CRITICAL }, #if defined(PICO_RP2350) || defined(ESP_PLATFORM) - { INS_SECURE, cmd_secure }, + { INS_SECURE, cmd_secure, CMD_FLAG_AUDIT_LOG | CMD_FLAG_CRITICAL }, #endif - { INS_READ, cmd_read }, + { INS_READ, cmd_read, CMD_FLAG_NONE }, #ifdef PICO_PLATFORM - { INS_REBOOT_BOOTSEL, cmd_reboot_bootsel }, + { INS_REBOOT_BOOTSEL, cmd_reboot_bootsel, CMD_FLAG_NONE }, #endif - { 0x00, 0x0 } + + { 0x00, 0x00, CMD_FLAG_NONE } // End of table }; static int rescue_process_apdu(void) { @@ -423,9 +426,17 @@ static int rescue_process_apdu(void) { } for (const cmd_t *cmd = cmds; cmd->ins != 0x00; cmd++) { if (cmd->ins == INS(apdu)) { + audit_entry_set_current_event(AUDIT_EVT_APP_EVT | INS(apdu)); + audit_entry_set_current_object(make_uint16_be(P1(apdu), P2(apdu))); int r = cmd->cmd_handler(); + if (cmd->flags & CMD_FLAG_AUDIT_LOG) { + if (cmd->flags & CMD_FLAG_CRITICAL) { + audit_entry_set_current_flags(AUDIT_EF_CRITICAL); + } + audit_log_current_entry_with_result(r); + } return r; } } return SW_INS_NOT_SUPPORTED(); -} +} \ No newline at end of file