Add audit system.

Signed-off-by: Pol Henarejos <pol.henarejos@cttc.es>
This commit is contained in:
Pol Henarejos
2026-06-30 13:56:08 +02:00
parent 92c1aee421
commit db53eb8ad8
8 changed files with 161 additions and 19 deletions
+1
View File
@@ -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)
+7
View File
@@ -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;
+39
View File
@@ -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 <https://www.gnu.org/licenses/>.
*/
#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);
}
+64
View File
@@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef _AUDIT_H_
#define _AUDIT_H_
#include <stdint.h>
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_
+2
View File
@@ -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);
+13 -3
View File
@@ -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 <https://www.gnu.org/licenses/>.
*/
#ifndef PICOKEYS_PLUGIN_API_H
#define PICOKEYS_PLUGIN_API_H
#include <stdint.h>
#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);
+17 -9
View File
@@ -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 <https://www.gnu.org/licenses/>.
*/
#include "picokeys_plugin_api.h"
#include "signal.h"
#include <stddef.h>
#include <stdio.h>
@@ -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);
}
+18 -7
View File
@@ -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();
}
}