Add 0x0026a custom AES-128-CMAC secure bootloader, Week 11a notebook, and README links

This commit is contained in:
Kevin Thomas committed 2026-10-13 12:37:20 -04:00
1 parent b85aaf72d6
commit bec685d573
33 files changed
+3451

No files matched your search

@@ -0,0 +1,29 @@
/**
* @file aes_cmac.c
* @brief AES-128-CMAC primitives implemented on top of the SDK Mbed TLS.
* @author Kevin Thomas
* @date 2026
*
* MIT License
* Copyright (c) 2026 Kevin Thomas
*/
#include "mbedtls/cmac.h"
#include "mbedtls/cipher.h"
#include "aes_cmac.h"
int aes128_cmac(const uint8_t *key, const uint8_t *data, size_t len,
uint8_t *tag) {
const mbedtls_cipher_info_t *info;
info = mbedtls_cipher_info_from_type(MBEDTLS_CIPHER_AES_128_ECB);
if (info == NULL) return -1;
return mbedtls_cipher_cmac(info, key, 128, data, len, tag);
}
bool cmac_tags_equal(const uint8_t *a, const uint8_t *b) {
uint8_t diff = 0;
for (size_t i = 0; i < AES_BLOCK_SIZE; i++) {
diff |= (uint8_t)(a[i] ^ b[i]);
}
return diff == 0;
}
@@ -0,0 +1,33 @@
/**
* @file boot.c
* @brief Secure boot console and application handoff helpers.
* @author Kevin Thomas
* @date 2026
*
* MIT License
* Copyright (c) 2026 Kevin Thomas
*/
#include <stdio.h>
#include "pico/stdlib.h"
#include "boot.h"
#include "image.h"
void boot_init(void) {
stdio_init_all();
sleep_ms(2000);
printf("\n=== 0x0026a secure bootloader ===\n");
}
void boot_halt(const char *reason) {
printf("BOOT FAILED: %s\n", reason);
while (true) {
sleep_ms(500);
}
}
void boot_launch(const fw_manifest_t *manifest) {
printf("signature valid, entering app at 0x%08lx\n",
(unsigned long)manifest->app_base);
image_start(manifest->app_base);
}
@@ -0,0 +1,33 @@
/**
* @file image.c
* @brief Loads the application stack pointer and branches to its reset vector.
* @author Kevin Thomas
* @date 2026
*
* MIT License
* Copyright (c) 2026 Kevin Thomas
*/
#include "image.h"
/** @brief Application reset handler signature. */
typedef void (*image_entry_t)(void);
/**
* @brief Mask interrupts and point VTOR at the incoming image.
* @param base Vector table base address written to the VTOR register.
* @return void No return value.
*/
static void halt_irq_and_rebase(uint32_t base) {
__asm volatile ("cpsid i" ::: "memory");
*(volatile uint32_t *)0xE000ED08U = base;
}
void image_start(uint32_t vector_base) {
uint32_t *vectors = (uint32_t *)vector_base;
image_entry_t entry = (image_entry_t)vectors[1];
halt_irq_and_rebase(vector_base);
__asm volatile ("msr msp, %0" :: "r" (vectors[0]) : "memory");
__asm volatile ("dsb\n\tisb" ::: "memory");
entry();
}
@@ -0,0 +1,34 @@
/**
* @file main.c
* @brief Secure bootloader entry point (verify AES-128-CMAC, then boot).
* @author Kevin Thomas
* @date 2026
*
* MIT License
* Copyright (c) 2026 Kevin Thomas
*
* -----------------------------------------------------------------------------
*
* This file is deliberately thin: it only sequences the secure boot steps.
* The console setup, halt reporting, and application handoff live in boot.c;
* the CMAC verification (and its key) live in verify.c; the manifest lives in
* manifest.c; and the raw reset-vector jump lives in image.c.
*
* Flash map (2 MiB, RP2350 Pico 2):
* 0x10000000 bootloader image (this program)
* 0x1001F000 one-sector firmware manifest (magic, size, CMAC tag)
* 0x10020000 signed application image
*/
#include "manifest.h"
#include "boot.h"
#include "verify.h"
int main(void) {
fw_manifest_t manifest;
boot_init();
manifest_read(&manifest);
if (!manifest_is_valid(&manifest)) boot_halt("manifest invalid");
if (!verify_manifest(&manifest)) boot_halt("firmware signature invalid");
boot_launch(&manifest);
}
@@ -0,0 +1,23 @@
/**
* @file manifest.c
* @brief Reads and validates the firmware manifest from XIP flash.
* @author Kevin Thomas
* @date 2026
*
* MIT License
* Copyright (c) 2026 Kevin Thomas
*/
#include "flash_layout.h"
#include "manifest.h"
void manifest_read(fw_manifest_t *out) {
const fw_manifest_t *src = (const fw_manifest_t *)FW_MANIFEST_BASE;
*out = *src;
}
bool manifest_is_valid(const fw_manifest_t *manifest) {
if (manifest->magic != FW_MANIFEST_MAGIC) return false;
if (manifest->version != FW_MANIFEST_VERSION) return false;
return true;
}
@@ -0,0 +1,28 @@
/**
* @file verify.c
* @brief Firmware authenticity verification for the secure bootloader.
* @author Kevin Thomas
* @date 2026
*
* MIT License
* Copyright (c) 2026 Kevin Thomas
*/
#include <stdint.h>
#include "flash_layout.h"
#include "verify.h"
#include "aes_cmac.h"
/** @brief AES-128 key that authenticates the application image. */
static const uint8_t fw_key[FW_TAG_SIZE] = {
0x49, 0x72, 0x6F, 0x6E, 0x4E, 0x65, 0x74, 0x42,
0x6F, 0x6F, 0x74, 0x4B, 0x65, 0x79, 0x21, 0x21
};
bool verify_manifest(const fw_manifest_t *manifest) {
const uint8_t *base = (const uint8_t *)manifest->app_base;
uint8_t computed[FW_TAG_SIZE];
int rc = aes128_cmac(fw_key, base, manifest->app_size, computed);
if (rc != 0) return false;
return cmac_tags_equal(computed, manifest->tag);
}