fw: Remove TK1_SYSCALL_REG_MGMT

Validate preload API access using the fixed, pre-calculated app digest
instead of letting an app register itself as a management app.
This commit is contained in:
Mikael Ågren 2025-03-25 16:02:33 +01:00
parent 5308544064
commit 0ece0c00f1
No known key found for this signature in database
GPG Key ID: E02DA3D397792C46
8 changed files with 30 additions and 120 deletions

View File

@ -21,11 +21,6 @@ int install_app(uint8_t secret_key[64])
uint8_t app_signature[64];
size_t app_size = sizeof(blink);
if (syscall(TK1_SYSCALL_REG_MGMT, 0, 0, 0) < 0) {
puts(IO_CDC, "couldn't register as mgmt\r\n");
return -1;
}
if (syscall(TK1_SYSCALL_PRELOAD_DELETE, 0, 0, 0) < 0) {
puts(IO_CDC, "couldn't delete preloaded app\r\n");
return -1;

View File

@ -16,6 +16,7 @@
#include "partition_table.h"
#include "preload_app.h"
#include "proto.h"
#include "mgmt_app.h"
#include "state.h"
#include "syscall_enable.h"
#include "resetinfo.h"
@ -42,19 +43,7 @@ static volatile struct reset *resetinfo = (volatile struct reset *)TK1_
struct partition_table part_table;
// Locked down what app can start from first flash slot to be exactly
// this size, producing this digest.
//
// To update this, compute the BLAKE2s digest of the app.bin and
// insert the size in bytes.
#define APP_SIZE_SLOT0 21684
// BLAKE2s digest of testloadapp.bin
const uint8_t allowed_app_digest[32] = {
0x3a, 0x34, 0x6f, 0x1f, 0xb7, 0x7f, 0xa6, 0x71, 0x9b, 0x69, 0x8,
0x36, 0xa0, 0x5, 0xe, 0x26, 0x48, 0x8d, 0xab, 0x6a, 0x51, 0xa6,
0xe1, 0x18, 0x53, 0xa3, 0x64, 0xc6, 0x5b, 0x42, 0x49, 0xb7,
};
// Context for the loading of a TKey program
struct context {
uint32_t left; // Bytes left to receive
@ -600,9 +589,8 @@ int main(void)
break;
}
if (ctx.flash_slot == 0) {
print_digest(allowed_app_digest);
if (!memeq(ctx.digest, allowed_app_digest, 32)) {
if (ctx.flash_slot != 1) {
if (mgmt_app_init(ctx.digest) != 0) {
puts(IO_CDC, "app not allowed!\r\n");
assert(1 == 2);
}

View File

@ -3,73 +3,34 @@
#include <tkey/lib.h>
#include <stdbool.h>
#include <stdint.h>
#include "mgmt_app.h"
#include "auth_app.h"
#include "partition_table.h"
/* Returns true if an management app is already registered */
static bool mgmt_app_registered(struct management_app_metadata *mgmt_table)
{
// Locked down what app can start from first flash slot to be exactly
// this size, producing this digest.
//
// To update this, compute the BLAKE2s digest of the app.bin
// BLAKE2s digest of testloadapp.bin
static const uint8_t allowed_app_digest[32] = {
0x88, 0x87, 0xf6, 0x2f, 0x71, 0x1c, 0x3f, 0xdb,
0x8c, 0xf7, 0x77, 0x9f, 0xeb, 0x5f, 0xb9, 0xd4,
0x2f, 0xfb, 0xdb, 0x1d, 0xf6, 0xdc, 0x62, 0xff,
0x91, 0x00, 0x1f, 0x5d, 0x98, 0xb3, 0x50, 0xd4,
};
static uint8_t current_app_digest[32];
if (mgmt_table->status == 0x00) {
/* No management app registered */
return false;
// TODO: Should we also check nonce, authentication digest for
// non-zero?
}
return true;
}
/* Authenticate an management app */
bool mgmt_app_authenticate(struct management_app_metadata *mgmt_table)
{
if (!mgmt_app_registered(mgmt_table)) {
return false;
}
return auth_app_authenticate(&mgmt_table->auth);
}
/* Register an management app, returns zero on success */
int mgmt_app_register(struct partition_table *part_table)
{
/* Check if the current app is the mgmt app */
if (mgmt_app_authenticate(&part_table->mgmt_app_data)) {
int mgmt_app_init(uint8_t app_digest[32]) {
if (memeq(app_digest, allowed_app_digest, 32)) {
memcpy_s(current_app_digest, sizeof(current_app_digest), app_digest, 32);
return 0;
}
/* Check if another management app is registered */
if (mgmt_app_registered(&part_table->mgmt_app_data)) {
return -1;
}
auth_app_create(&part_table->mgmt_app_data.auth);
part_table->mgmt_app_data.status = 0x01;
part_table_write(part_table);
return 0;
return -1;
}
/* Unregister the currently registered app, returns zero on success */
int mgmt_app_unregister(struct partition_table *part_table)
/* Authenticate an management app */
bool mgmt_app_authenticate(void)
{
/* Only the management app should be able to unregister itself */
if (!mgmt_app_authenticate(&part_table->mgmt_app_data)) {
return -1;
}
part_table->mgmt_app_data.status = 0;
memset(part_table->mgmt_app_data.auth.nonce, 0x00,
sizeof(part_table->mgmt_app_data.auth.nonce));
memset(part_table->mgmt_app_data.auth.authentication_digest, 0x00,
sizeof(part_table->mgmt_app_data.auth.authentication_digest));
part_table_write(part_table);
return 0;
return memeq(current_app_digest, allowed_app_digest, 32) != 0;
}

View File

@ -4,12 +4,10 @@
#ifndef MGMT_APP_H
#define MGMT_APP_H
#include "partition_table.h"
#include <stdbool.h>
#include <stdint.h>
bool mgmt_app_authenticate(struct management_app_metadata *mgmt_table);
int mgmt_app_register(struct partition_table *part_table);
int mgmt_app_unregister(struct partition_table *part_table);
int mgmt_app_init(uint8_t app_digest[32]);
bool mgmt_app_authenticate(void);
#endif

View File

@ -39,26 +39,14 @@
#define ADDR_PRE_LOADED_APP_0 (ADDR_PARTITION_TABLE + SIZE_PARTITION_TABLE)
#define SIZE_PRE_LOADED_APP 0x20000UL // 128KiB
// Pre-loaded app present and authenticated
#define PRE_LOADED_STATUS_AUTH 0x01
// Pre-loaded app present but not yet authenticated
#define PRE_LOADED_STATUS_PRESENT 0x02
#define ADDR_STORAGE_AREA (ADDR_PRE_LOADED_APP_0 + (N_PRELOADED_APP * SIZE_PRE_LOADED_APP))
#define SIZE_STORAGE_AREA 0x20000UL // 128KiB
#define N_STORAGE_AREA 4
#define EMPTY_AREA
/* Partition Table */
/*- Table header */
/* - 1 bytes Version */
/**/
/*- Management device app */
/* - Status. */
/* - 16 byte random nonce. */
/* - 16 byte authentication digest. */
/**/
/*- Pre-loaded device app 1 */
/* - 4 bytes length. */
/* - 32 bytes digest. */
@ -81,11 +69,6 @@ struct auth_metadata {
uint8_t authentication_digest[16];
} __attribute__((packed));
struct management_app_metadata {
uint8_t status;
struct auth_metadata auth;
} __attribute__((packed));
struct pre_loaded_app_metadata {
uint32_t size;
uint8_t digest[32];
@ -105,7 +88,6 @@ struct table_header {
struct partition_table {
struct table_header header;
struct management_app_metadata mgmt_app_data;
struct pre_loaded_app_metadata pre_app_data[N_PRELOADED_APP];
struct app_storage_area app_storage[N_STORAGE_AREA];
} __attribute__((packed));

View File

@ -56,7 +56,7 @@ int preload_store(struct partition_table *part_table, uint32_t offset,
uint8_t *data, size_t size, uint8_t to_slot)
{
/* Check if we are allowed to store */
if (!mgmt_app_authenticate(&part_table->mgmt_app_data)) {
if (!mgmt_app_authenticate()) {
return -3;
}
@ -88,7 +88,7 @@ int preload_store_finalize(struct partition_table *part_table, size_t app_size,
}
/* Check if we are allowed to store */
if (!mgmt_app_authenticate(&part_table->mgmt_app_data)) {
if (!mgmt_app_authenticate()) {
return -3;
}
@ -124,7 +124,7 @@ int preload_delete(struct partition_table *part_table, uint8_t slot)
}
/* Check if we are allowed to deleted */
if (!mgmt_app_authenticate(&part_table->mgmt_app_data)) {
if (!mgmt_app_authenticate()) {
return -3;
}

View File

@ -94,9 +94,6 @@ int32_t syscall_handler(uint32_t number, uint32_t arg1, uint32_t arg2,
case TK1_SYSCALL_PRELOAD_GET_DIGSIG:
return preload_get_digsig(&part_table, (uint8_t *)arg1, (uint8_t *)arg2, 1);
case TK1_SYSCALL_REG_MGMT:
return mgmt_app_register(&part_table);
default:
assert(1 == 2);
}

View File

@ -13,13 +13,6 @@ type PartTable struct {
Header struct {
Version uint8
}
ManagementAppData struct {
Status uint8
Auth struct {
Nonce [16]uint8
AuthDigest [16]uint8
}
}
PreLoadedAppData [2]struct {
Size uint32
Digest [32]uint8
@ -39,7 +32,7 @@ type PartTable struct {
type Flash struct {
Bitstream [0x20000]uint8
PartitionTable PartTable
PartitionTablePadding [64*1024 - 398]uint8
PartitionTablePadding [64*1024 - 365]uint8
PreLoadedApp0 [0x20000]uint8
PreLoadedApp1 [0x20000]uint8
AppStorage [4][0x20000]uint8
@ -93,10 +86,6 @@ func printPartTableJson(tbl PartTable) {
func printPartTableCondensed(tbl PartTable) {
fmt.Printf("Header\n")
fmt.Printf(" Version : %d\n", tbl.Header.Version)
fmt.Printf("Management App\n")
fmt.Printf(" Status : %d\n", tbl.ManagementAppData.Status)
fmt.Printf(" Auth.Nonce : %x\n", tbl.ManagementAppData.Auth.Nonce)
fmt.Printf(" Auth.AuthDigest : %x\n", tbl.ManagementAppData.Auth.AuthDigest)
for i, appData := range tbl.PreLoadedAppData {
fmt.Printf("Preloaded App %d\n", i)