diff --git a/picokeys_sdk_import.cmake b/picokeys_sdk_import.cmake
index d60da51..84cae21 100644
--- a/picokeys_sdk_import.cmake
+++ b/picokeys_sdk_import.cmake
@@ -116,10 +116,10 @@ else()
endif()
if(PICO_RP2350 OR ENABLE_EMULATION)
- set(PICOKEYS_PLUGIN_FLASH_BASE "0x10112000" CACHE STRING "XIP address where the premium plugin UF2 starts" FORCE)
- set(PICOKEYS_PLUGIN_FLASH_SIZE "0x000fa000" CACHE STRING "Maximum premium plugin size in bytes" FORCE)
- set(PICOKEYS_PLUGIN_RAM_BASE "0x2007c000" CACHE STRING "RAM base reserved for premium plugin mutable state" FORCE)
- set(PICOKEYS_PLUGIN_RAM_SIZE "0x00004000" CACHE STRING "Maximum premium plugin RAM usage in bytes" FORCE)
+ set(PICOKEYS_PLUGIN_FLASH_BASE "0x10112000" CACHE STRING "XIP address where the plugin UF2 starts" FORCE)
+ set(PICOKEYS_PLUGIN_FLASH_SIZE "0x000fa000" CACHE STRING "Maximum plugin size in bytes" FORCE)
+ set(PICOKEYS_PLUGIN_RAM_BASE "0x2007c000" CACHE STRING "RAM base reserved for plugin mutable state" FORCE)
+ set(PICOKEYS_PLUGIN_RAM_SIZE "0x00004000" CACHE STRING "Maximum plugin RAM usage in bytes" FORCE)
set(PICOKEYS_PLUGIN_DIR "" CACHE PATH "Optional external PicoKeys plugin source directory")
include(${CMAKE_CURRENT_LIST_DIR}/cmake/plugin.cmake)
endif()
@@ -344,7 +344,6 @@ 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 5874f49..c34a011 100644
--- a/src/apdu.h
+++ b/src/apdu.h
@@ -35,9 +35,9 @@ 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_FLAG_NONE = 0x00,
+ CMD_FLAG_NOTIFY_PLUGIN = 0x01,
+ CMD_FLAG_SECURITY_SENSITIVE = 0x02,
} cmd_flags_t;
typedef struct cmd {
diff --git a/src/audit.c b/src/audit.c
deleted file mode 100644
index 9fd0fee..0000000
--- a/src/audit.c
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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
deleted file mode 100644
index 6422949..0000000
--- a/src/audit.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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 = 11;
-#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 b59f923..dfc9d46 100644
--- a/src/main.c
+++ b/src/main.c
@@ -43,6 +43,9 @@
#include "serial.h"
#include "mbedtls/sha256.h"
#include "signal.h"
+#if defined(PICO_RP2350) || defined(ENABLE_EMULATION)
+#include "picokeys_plugin_api.h"
+#endif
app_t apps[16];
uint8_t num_apps = 0;
@@ -104,10 +107,6 @@ WEAK int picokey_init(void) {
}
-#if defined(PICO_RP2350) || defined(ENABLE_EMULATION)
-void plugin_init(void);
-#endif
-
void execute_tasks(void);
void execute_tasks(void) {
#if !defined(ENABLE_EMULATION) && !defined(ESP_PLATFORM)
diff --git a/src/plugin/core_plugin_region_assert.ld b/src/plugin/core_plugin_region_assert.ld
index 190852b..501d2db 100644
--- a/src/plugin/core_plugin_region_assert.ld
+++ b/src/plugin/core_plugin_region_assert.ld
@@ -1,11 +1,11 @@
ASSERT(!DEFINED(__picokeys_plugin_flash_base) || __flash_binary_end <= __picokeys_plugin_flash_base,
- "pico_fido flash image overlaps the premium plugin region")
+ "pico_fido flash image overlaps the plugin region")
ASSERT(!DEFINED(__picokeys_plugin_ram_base) || __end__ <= __picokeys_plugin_ram_base,
- "pico_fido RAM image overlaps the premium plugin RAM region")
+ "pico_fido RAM image overlaps the plugin RAM region")
ASSERT(!DEFINED(__picokeys_plugin_ram_base) || !DEFINED(__picokeys_plugin_ram_size) ||
((__picokeys_plugin_ram_base + __picokeys_plugin_ram_size) <= 0x20080000),
- "premium plugin RAM region exceeds RP2350 main RAM")
+ "plugin RAM region exceeds RP2350 main RAM")
__HeapLimit = DEFINED(__picokeys_plugin_ram_base) ? __picokeys_plugin_ram_base : __HeapLimit;
diff --git a/src/plugin/picokeys_plugin_api.h b/src/plugin/picokeys_plugin_api.h
index da45c03..1962c8a 100644
--- a/src/plugin/picokeys_plugin_api.h
+++ b/src/plugin/picokeys_plugin_api.h
@@ -43,7 +43,9 @@
#endif
#define PICOKEYS_PLUGIN_MAGIC 0x504b504cUL /* PKPL */
-#define PICOKEYS_PLUGIN_ABI_VERSION 5u
+#define PICOKEYS_PLUGIN_ABI_VERSION 1u
+
+#define PICOKEYS_PLUGIN_SIGNAL_EVENT 11u
#ifndef PICOKEYS_PLUGIN_FLASH_BASE
#define PICOKEYS_PLUGIN_FLASH_BASE 0x10112000UL
@@ -88,9 +90,47 @@ typedef struct pk_plugin_imports {
uint8_t *(*get_res_apdu)(void);
uint16_t (*get_res_apdu_size)(void);
void (*set_res_apdu_size)(uint16_t size);
+ uint8_t (*get_apdu_cla)(void);
+ uint8_t (*get_apdu_ins)(void);
+ uint8_t (*get_apdu_p1)(void);
+ uint8_t (*get_apdu_p2)(void);
+ const uint8_t *(*get_apdu_data)(void);
+ size_t (*get_apdu_data_size)(void);
+ uint16_t (*set_res_sw)(uint8_t sw1, uint8_t sw2);
+ void *(*file_search)(uint16_t fid);
+ void *(*file_new)(uint16_t fid);
+ int (*file_has_data)(const void *file);
+ const uint8_t *(*file_get_data)(const void *file);
+ uint16_t (*file_get_size)(const void *file);
+ int (*file_put_data)(void *file, const uint8_t *data, uint16_t len);
+ int (*file_delete)(void *file);
} pk_plugin_imports_t;
-typedef void (*pk_plugin_init_fn)(pk_plugin_imports_t *imports);
+typedef enum pk_plugin_event_type {
+ PK_PLUGIN_EVENT_COMMAND_COMPLETED = 1,
+} pk_plugin_event_type_t;
+
+#define PK_PLUGIN_EVENT_SOURCE_CORE 0x0000u
+
+typedef enum pk_plugin_event_flags {
+ PK_PLUGIN_EVENT_FLAG_NONE = 0,
+ PK_PLUGIN_EVENT_FLAG_SECURITY_SENSITIVE = 1u << 0,
+} pk_plugin_event_flags_t;
+
+typedef struct pk_plugin_event {
+ uint16_t type;
+ uint16_t source;
+ uint16_t command;
+ uint16_t object;
+ uint16_t flags;
+ uint16_t struct_size;
+ int32_t result;
+} pk_plugin_event_t;
+
+typedef void (*pk_plugin_init_fn)(const pk_plugin_imports_t *imports);
+typedef int (*pk_plugin_call_fn)(uint32_t hook, void *data);
+
+#define PK_PLUGIN_CALL_UNHANDLED (-1)
typedef struct pk_plugin_header {
uint32_t magic;
@@ -103,8 +143,39 @@ typedef struct pk_plugin_header {
uintptr_t bss_start;
uint32_t bss_size;
pk_plugin_init_fn init;
+ pk_plugin_call_fn call;
} pk_plugin_header_t;
+#if defined(PICO_RP2350) || defined(ENABLE_EMULATION)
void plugin_init(void);
+void pk_plugin_dispatch_event(const pk_plugin_event_t *event);
+int pk_plugin_call(uint32_t hook, void *data);
+#else
+static inline void pk_plugin_dispatch_event(const pk_plugin_event_t *event) {
+ (void)event;
+}
+static inline int pk_plugin_call(uint32_t hook, void *data) {
+ (void)hook;
+ (void)data;
+ return PK_PLUGIN_CALL_UNHANDLED;
+}
+#endif
+
+static inline void pk_plugin_notify_command(uint16_t source,
+ uint16_t command,
+ uint16_t object,
+ pk_plugin_event_flags_t flags,
+ int32_t result) {
+ const pk_plugin_event_t event = {
+ .type = PK_PLUGIN_EVENT_COMMAND_COMPLETED,
+ .source = source,
+ .command = command,
+ .object = object,
+ .flags = (uint16_t)flags,
+ .struct_size = sizeof(event),
+ .result = result,
+ };
+ pk_plugin_dispatch_event(&event);
+}
#endif
diff --git a/src/plugin/plugin_loader.c b/src/plugin/plugin_loader.c
index 8344578..728bd0b 100644
--- a/src/plugin/plugin_loader.c
+++ b/src/plugin/plugin_loader.c
@@ -30,6 +30,7 @@
#include
static pk_plugin_imports_t plugin_imports;
+static const pk_plugin_header_t *active_plugin;
_Static_assert(sizeof(pk_plugin_sha256_context_t) >= sizeof(mbedtls_sha256_context),
"pk_plugin_sha256_context_t too small for mbedtls_sha256_context");
@@ -86,6 +87,77 @@ static void pk_plugin_set_res_apdu_size(uint16_t size) {
apdu.rlen = size;
}
+static uint8_t pk_plugin_get_apdu_cla(void) {
+ return apdu.header ? CLA(apdu) : 0;
+}
+
+static uint8_t pk_plugin_get_apdu_ins(void) {
+ return apdu.header ? INS(apdu) : 0;
+}
+
+static uint8_t pk_plugin_get_apdu_p1(void) {
+ return apdu.header ? P1(apdu) : 0;
+}
+
+static uint8_t pk_plugin_get_apdu_p2(void) {
+ return apdu.header ? P2(apdu) : 0;
+}
+
+static const uint8_t *pk_plugin_get_apdu_data(void) {
+ return apdu.data;
+}
+
+static size_t pk_plugin_get_apdu_data_size(void) {
+ return apdu.nc;
+}
+
+static void *pk_plugin_file_search(uint16_t fid) {
+ return file_search(fid);
+}
+
+static void *pk_plugin_file_new(uint16_t fid) {
+ return file_new(fid);
+}
+
+static int pk_plugin_file_has_data(const void *file) {
+ return file_has_data((const file_t *)file) ? 1 : 0;
+}
+
+static const uint8_t *pk_plugin_file_get_data(const void *file) {
+ return file_get_data((const file_t *)file);
+}
+
+static uint16_t pk_plugin_file_get_size(const void *file) {
+ return file_get_size((const file_t *)file);
+}
+
+static int pk_plugin_file_put_data(void *file, const uint8_t *data, uint16_t len) {
+ return file_put_data((file_t *)file, data, len);
+}
+
+static int pk_plugin_file_delete(void *file) {
+ return file_delete((file_t *)file);
+}
+
+static int pk_plugin_has_call(const pk_plugin_header_t *plugin) {
+ return plugin &&
+ plugin->header_size >= offsetof(pk_plugin_header_t, call) + sizeof(plugin->call) &&
+ plugin->call;
+}
+
+void pk_plugin_dispatch_event(const pk_plugin_event_t *event) {
+ if (event) {
+ signal_emit_param(PICOKEYS_PLUGIN_SIGNAL_EVENT, (void *)event);
+ }
+}
+
+int pk_plugin_call(uint32_t hook, void *data) {
+ if (!pk_plugin_has_call(active_plugin)) {
+ return PK_PLUGIN_CALL_UNHANDLED;
+ }
+ return active_plugin->call(hook, data);
+}
+
#ifdef ENABLE_EMULATION
#ifdef _WIN32
#include
@@ -249,6 +321,11 @@ static const pk_plugin_header_t *pk_plugin_get_valid(void) {
printf("Plugin rejected: init pointer out of range\n");
return NULL;
}
+ if (plugin->header_size >= offsetof(pk_plugin_header_t, call) + sizeof(plugin->call) &&
+ plugin->call && !pk_plugin_ptr_in_range((const void *)plugin->call)) {
+ printf("Plugin rejected: call pointer out of range\n");
+ return NULL;
+ }
return plugin;
}
#endif
@@ -266,6 +343,7 @@ void plugin_init(void) {
}
#endif
+ active_plugin = plugin;
plugin_imports = (pk_plugin_imports_t){
.abi_version = PICOKEYS_PLUGIN_ABI_VERSION,
.struct_size = sizeof(plugin_imports),
@@ -289,6 +367,20 @@ void plugin_init(void) {
.get_res_apdu = pk_plugin_get_res_apdu,
.get_res_apdu_size = pk_plugin_get_res_apdu_size,
.set_res_apdu_size = pk_plugin_set_res_apdu_size,
+ .get_apdu_cla = pk_plugin_get_apdu_cla,
+ .get_apdu_ins = pk_plugin_get_apdu_ins,
+ .get_apdu_p1 = pk_plugin_get_apdu_p1,
+ .get_apdu_p2 = pk_plugin_get_apdu_p2,
+ .get_apdu_data = pk_plugin_get_apdu_data,
+ .get_apdu_data_size = pk_plugin_get_apdu_data_size,
+ .set_res_sw = set_res_sw,
+ .file_search = pk_plugin_file_search,
+ .file_new = pk_plugin_file_new,
+ .file_has_data = pk_plugin_file_has_data,
+ .file_get_data = pk_plugin_file_get_data,
+ .file_get_size = pk_plugin_file_get_size,
+ .file_put_data = pk_plugin_file_put_data,
+ .file_delete = pk_plugin_file_delete,
};
plugin->init(&plugin_imports);
}
diff --git a/src/rescue.c b/src/rescue.c
index 5ca0350..2d9df9e 100644
--- a/src/rescue.c
+++ b/src/rescue.c
@@ -31,7 +31,7 @@
#include "random.h"
#include "crypto_utils.h"
#include "usb.h"
-#include "audit.h"
+#include "picokeys_plugin_api.h"
#include "signal.h"
#ifdef PICO_PLATFORM
@@ -259,7 +259,6 @@ 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();
@@ -408,10 +407,10 @@ static int cmd_reboot_bootsel(void) {
#define INS_REBOOT_BOOTSEL 0x1F
static const cmd_t cmds[] = {
- { INS_KEYDEV_SIGN, cmd_keydev_sign, CMD_FLAG_AUDIT_LOG },
- { INS_WRITE, cmd_write, CMD_FLAG_AUDIT_LOG | CMD_FLAG_CRITICAL },
+ { INS_KEYDEV_SIGN, cmd_keydev_sign, CMD_FLAG_NOTIFY_PLUGIN },
+ { INS_WRITE, cmd_write, CMD_FLAG_NOTIFY_PLUGIN | CMD_FLAG_SECURITY_SENSITIVE },
#if defined(PICO_RP2350) || defined(ESP_PLATFORM)
- { INS_SECURE, cmd_secure, CMD_FLAG_AUDIT_LOG | CMD_FLAG_CRITICAL },
+ { INS_SECURE, cmd_secure, CMD_FLAG_NOTIFY_PLUGIN | CMD_FLAG_SECURITY_SENSITIVE },
#endif
{ INS_READ, cmd_read, CMD_FLAG_NONE },
#ifdef PICO_PLATFORM
@@ -427,21 +426,26 @@ 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);
+ if (cmd->flags & CMD_FLAG_NOTIFY_PLUGIN) {
+ pk_plugin_notify_command(
+ PK_PLUGIN_EVENT_SOURCE_CORE,
+ INS(apdu),
+ make_uint16_be(P1(apdu), P2(apdu)),
+ (cmd->flags & CMD_FLAG_SECURITY_SENSITIVE)
+ ? PK_PLUGIN_EVENT_FLAG_SECURITY_SENSITIVE
+ : PK_PLUGIN_EVENT_FLAG_NONE,
+ r);
}
return r;
}
}
int ret = signal_emit(SIGNAL_RESCUE_NOT_FOUND);
- if (ret != 0) {
+ if (ret == PICOKEYS_ERR_FILE_NOT_FOUND) {
return SW_INS_NOT_SUPPORTED();
}
+ if (ret != PICOKEYS_OK) {
+ return ret;
+ }
return SW_OK();
-}
\ No newline at end of file
+}