Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/fuzz.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ on:
jobs:
fuzz:
runs-on: ubuntu-latest
if: github.event.pull_request.draft != true
steps:
- uses: actions/checkout@v4

Expand Down
4 changes: 4 additions & 0 deletions .github/workflows/static-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ on:
jobs:
clang-format:
runs-on: ubuntu-latest
if: github.event.pull_request.draft != true
steps:
- uses: actions/checkout@v4

Expand All @@ -20,6 +21,7 @@ jobs:

cppcheck:
runs-on: ubuntu-latest
if: github.event.pull_request.draft != true
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -58,6 +60,7 @@ jobs:

clang-tidy:
runs-on: ubuntu-latest
if: github.event.pull_request.draft != true
steps:
- uses: actions/checkout@v4
with:
Expand Down Expand Up @@ -106,6 +109,7 @@ jobs:

scan-build:
runs-on: ubuntu-latest
if: github.event.pull_request.draft != true
steps:
- uses: actions/checkout@v4
with:
Expand Down
46 changes: 46 additions & 0 deletions main/frost_signer.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@
#include "crypto_asm.h"
#include "secresult.h"
#include "anti_glitch.h"
#include "ux_interface.h"
#include "esp_log.h"
#include <string.h>
#include <stdio.h>

#ifdef ESP_PLATFORM
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "esp_timer.h"
static uint32_t get_time_ms(void) {
return (uint32_t)(esp_timer_get_time() / 1000);
Expand All @@ -39,11 +42,25 @@ static uint32_t elapsed_ms(uint32_t start, uint32_t now) {
#define TAG "frost_signer"
#define MAX_SESSIONS 4
#define CONSUMED_SESSION_RING_SIZE 64
#define CONFIRM_TIMEOUT_MS 35000

static uint8_t consumed_sessions[CONSUMED_SESSION_RING_SIZE][SESSION_ID_LEN];
static uint8_t consumed_count = 0;
static uint8_t consumed_head = 0;

#ifdef ESP_PLATFORM
static SemaphoreHandle_t confirm_sem = NULL;
static bool confirm_result = false;

static void confirm_cb(bool approved, void *user_data) {
(void)user_data;
confirm_result = approved;
if (confirm_sem) {
xSemaphoreGive(confirm_sem);
}
}
#endif

static bool is_session_consumed(const uint8_t *session_id) {
uint8_t count =
(consumed_count < CONSUMED_SESSION_RING_SIZE) ? consumed_count : CONSUMED_SESSION_RING_SIZE;
Expand Down Expand Up @@ -420,6 +437,35 @@ void frost_sign(const char *group, const char *session_id_hex, const char *commi

ag_random_delay_us(100, 1000);

#ifdef ESP_PLATFORM
const ux_backend_t *ux = ux_get_backend();
if (ux && ux->confirm_transaction && ux->is_available && ux->is_available()) {
if (!confirm_sem) {
confirm_sem = xSemaphoreCreateBinary();
}
if (confirm_sem) {
ux_tx_info_t tx_info = {0};
strncpy(tx_info.destination, s->group, sizeof(tx_info.destination) - 1);
tx_info.threshold = s->frost_state.threshold;
tx_info.total_signers = s->frost_state.participants;
tx_info.policy_approved = true;

confirm_result = false;
ux->confirm_transaction(&tx_info, confirm_cb, NULL);

if (xSemaphoreTake(confirm_sem, pdMS_TO_TICKS(CONFIRM_TIMEOUT_MS)) != pdTRUE) {
PROTOCOL_ERROR(resp, resp->id, PROTOCOL_ERR_SIGN, "Confirmation timeout");
return;
}

if (!confirm_result) {
PROTOCOL_ERROR(resp, resp->id, PROTOCOL_ERR_SIGN, "User rejected signing");
return;
}
}
}
#endif

bool policy_snapshot = s->has_policy;
uint8_t policy_hash_snapshot[32];
memcpy(policy_hash_snapshot, s->policy_hash, 32);
Expand Down
48 changes: 48 additions & 0 deletions main/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,51 @@ static void handle_dkg_checkpoint(const rpc_request_t *req, rpc_response_t *resp
protocol_success(resp, req->id, "{\"ok\":true}");
}

static SemaphoreHandle_t ux_test_sem = NULL;
static bool ux_test_result = false;

static void ux_test_cb(bool approved, void *user_data) {
(void)user_data;
ux_test_result = approved;
if (ux_test_sem) {
xSemaphoreGive(ux_test_sem);
}
}

static void handle_ux_test(const rpc_request_t *req, rpc_response_t *resp) {
const ux_backend_t *ux = ux_get_backend();
if (!ux || !ux->confirm_transaction) {
PROTOCOL_ERROR(resp, req->id, -1, "No UX backend available");
return;
}

if (!ux_test_sem) {
ux_test_sem = xSemaphoreCreateBinary();
}

ux_tx_info_t tx_info = {
.amount_sats = 50000,
.fee_sats = 1200,
.threshold = 2,
.total_signers = 3,
.policy_approved = true,
};
strncpy(tx_info.destination, "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", sizeof(tx_info.destination) - 1);
strncpy(tx_info.destination_label, "Savings", sizeof(tx_info.destination_label) - 1);

ux_test_result = false;
ux->confirm_transaction(&tx_info, ux_test_cb, NULL);

if (xSemaphoreTake(ux_test_sem, pdMS_TO_TICKS(35000)) != pdTRUE) {
protocol_success(resp, req->id, "{\"result\":\"timeout\"}");
return;
}

char result[64];
snprintf(result, sizeof(result), "{\"result\":\"%s\"}", ux_test_result ? "approved" : "rejected");
protocol_success(resp, req->id, result);
}

static void handle_request(const rpc_request_t *req, rpc_response_t *resp) {
resp->id = req->id;
frost_signer_cleanup_stale();
Expand Down Expand Up @@ -378,6 +423,9 @@ static void handle_request(const rpc_request_t *req, rpc_response_t *resp) {
case RPC_METHOD_SESSION_LIST:
frost_session_list(resp);
break;
case RPC_METHOD_UX_TEST:
handle_ux_test(req, resp);
break;
default:
PROTOCOL_ERROR(resp, req->id, PROTOCOL_ERR_METHOD, "Method not found");
}
Expand Down
2 changes: 2 additions & 0 deletions main/protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ static rpc_method_t parse_method(const char *method) {
return RPC_METHOD_SESSION_RESUME;
if (strcmp(method, "frost_session_list") == 0)
return RPC_METHOD_SESSION_LIST;
if (strcmp(method, "ux_test") == 0)
return RPC_METHOD_UX_TEST;
return RPC_METHOD_UNKNOWN;
}

Expand Down
1 change: 1 addition & 0 deletions main/protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ typedef enum {
RPC_METHOD_EXPORT_SHARE,
RPC_METHOD_SESSION_RESUME,
RPC_METHOD_SESSION_LIST,
RPC_METHOD_UX_TEST,
RPC_METHOD_UNKNOWN
} rpc_method_t;

Expand Down
Loading