fw: Add checksum to partition table

Refuse to boot if blake2s digest over the partition table does not match
digest stored on flash
This commit is contained in:
Mikael Ågren 2025-04-03 15:48:51 +02:00
parent 75dd726998
commit f24c7ea515
No known key found for this signature in database
GPG key ID: E02DA3D397792C46
11 changed files with 207 additions and 73 deletions

View file

@ -2,43 +2,67 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <stdint.h>
#include <tkey/assert.h>
#include <tkey/lib.h>
#include "blake2s/blake2s.h"
#include "flash.h"
#include "partition_table.h"
#include "proto.h"
int part_table_read(struct partition_table *part_table)
void part_digest(struct partition_table *part_table, uint8_t *out_digest, size_t out_len) {
blake2s_ctx b2s_ctx = {0};
int blake2err = 0;
uint8_t key[16] = {
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
};
blake2err = blake2s(out_digest, out_len,
key, sizeof(key), part_table, sizeof(struct partition_table), &b2s_ctx);
assert(blake2err == 0);
}
int part_table_read(struct partition_table_storage *storage)
{
// Read from flash, if it exists, otherwise create a new one.
flash_release_powerdown();
memset(part_table, 0x00, sizeof(*part_table));
memset(storage, 0x00, sizeof(*storage));
flash_read_data(ADDR_PARTITION_TABLE, (uint8_t *)part_table,
sizeof(*part_table));
flash_read_data(ADDR_PARTITION_TABLE, (uint8_t *)storage,
sizeof(*storage));
// TODO: Implement redundancy and consistency check
// TODO: Implement redundancy
if (part_table->header.version != PART_TABLE_VERSION) {
// Partition table is not ours. Make a new one, and store it.
memset(part_table, 0x00, sizeof(*part_table));
uint8_t check_digest[PART_DIGEST_SIZE];
part_digest(&storage->table, check_digest, sizeof(check_digest));
part_table->header.version = PART_TABLE_VERSION;
part_table_write(part_table);
if (!memeq(check_digest, storage->check_digest, sizeof(check_digest))) {
return -1;
}
// if (part_table->header.version != PART_TABLE_VERSION) {
// // Partition table is not ours. Make a new one, and store it.
// memset(part_table, 0x00, sizeof(*part_table));
// part_table->header.version = PART_TABLE_VERSION;
// part_table_write(part_table);
// }
// Now the partition table is synced between flash and RAM.
return 0;
}
int part_table_write(struct partition_table *part_table)
int part_table_write(struct partition_table_storage *storage)
{
part_digest(&storage->table, storage->check_digest, sizeof(storage->check_digest));
flash_sector_erase(ADDR_PARTITION_TABLE);
flash_write_data(ADDR_PARTITION_TABLE, (uint8_t *)part_table,
sizeof(*part_table));
flash_write_data(ADDR_PARTITION_TABLE, (uint8_t *)storage,
sizeof(*storage));
return 0;
}