Files
Deshab-OS/CODE/UTSM/test/utsm_selftest.c
T
Linehu 1e74ee9fab feat: U5 land deterministic chacha20 KAT (RFC 8439 2.4.2)
- test/gen_chacha_kat.py emits KAT from RFC 8439 section 2.4.2 mapped to the impl's 64+64 counter/nonce layout; expected bytes cross-checked against pycryptodome (independent impl) and the official vector: 10f1e7e4d13b5915... byte-exact
- verdict: the 'intermittent chacha20 KAT FAIL' referenced in FUCK comments was a phantom — that test was never merged into this tree; the implementation itself matches RFC byte-for-byte
- selftest now runs KAT + page-MAC determinism checks at selftest=2; full SELFTEST PASS in QEMU (.build_tmp/qemu_serial_u5kat.log)
2026-10-02 15:24:15 +08:00

235 lines
9.2 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include <utsm/utsm.h>
#include <utsm/pckc.h>
#include <utsm/crypto.h>
#include <utsm/log.h>
#include <utsm/segment.h>
#include <utsm/arena.h>
#include <utsm/drr.h>
#include <utsm/sched_ext.h>
int memcmp(const void *a, const void *b, usize len);
usize strlen(const char *s);
/* selftest 与 LAPIC/PIT tick 竞态:tick 在别的任务上唤醒 sleeper 时
* 会向同一 runqueue 入队,破坏 pick_next 的确定性断言(偶发
* block/wake FAIL → arch_halt_forever)。临界区内关中断。 */
static u64 selftest_irq_save(void) {
u64 flags;
__asm__ volatile("pushfq; popq %0; cli" : "=r"(flags) :: "memory");
return flags;
}
static void selftest_irq_restore(u64 flags) {
__asm__ volatile("pushq %0; popfq" :: "r"(flags) : "memory");
}
int utsm_selftest_run(void) {
log_info("[UTSM] selftest enter");
/* utsm_process_context is ~8KB (256 capabilities × 32 bytes).
* Allocate from arena instead of stack to avoid kernel stack overflow. */
utsm_process_context *process = (utsm_process_context *)kmem_alloc(sizeof(utsm_process_context));
if (!process) {
log_error("[UTSM] selftest: failed to allocate process context");
return UTSM_ERR_NO_MEMORY;
}
utsm_process_create_test(process, 1);
utsm_capability cap;
int status = utsm_create_segment(process, UTSM_PAGE_SIZE, UTSM_SEG_F_READ | UTSM_SEG_F_WRITE | UTSM_SEG_F_STRONG_RECOVERY, &cap);
if (status != UTSM_OK) {
log_error("[UTSM] selftest create segment failed");
return status;
}
const char *message = "deshab utsm sealed memory selftest";
u64 len = strlen(message) + 1;
status = utsm_write(cap, 128, message, len);
if (status != UTSM_OK) {
log_error("[UTSM] selftest write failed");
return status;
}
log_info("[UTSM] selftest write ok");
utsm_segment_desc *desc = utsm_get_segment(cap.segment_slot);
if (!desc) {
return UTSM_ERR_INVALID;
}
if (memcmp(desc->cipher_base + 128, message, len) == 0) {
log_error("[UTSM] raw cipher equals plaintext");
return UTSM_ERR_INVALID;
}
log_info("[UTSM] raw cipher check ok");
char readback[64];
status = utsm_read(cap, 128, readback, len);
if (status != UTSM_OK) {
log_error("[UTSM] selftest read failed");
return status;
}
if (memcmp(readback, message, len) != 0) {
log_error("[UTSM] selftest read mismatch");
return UTSM_ERR_INVALID;
}
log_info("[UTSM] selftest read ok");
/* ==== U5: chacha20 KAT(RFC 8439 §2.4.2 官方向量)====
* 历史注:FUCK 注释曾提"并行会话 chacha20 KAT 间歇 FAIL"——该测试
* 从未合并进本树(幽灵缺陷)。本 KAT 为确定性官方向量,不依赖
* 硬件/时钟/随机数,PASS/FAIL 完全可复现。期望值由
* test/gen_chacha_kat.py 生成,并经 pycryptodome 独立对拍。 */
{
#include "chacha_kat.inc"
u8 ks[64];
utsm_chacha20_block(kat_key, kat_nonce, kat_counter, ks);
if (memcmp(ks, kat_expect, 64) != 0) {
log_error("[UTSM] selftest chacha20 KAT FAIL (RFC 8439 §2.4.2)");
return UTSM_ERR_INVALID;
}
log_info("[UTSM] selftest chacha20 KAT ok (RFC 8439 §2.4.2)");
/* page MAC 确定性:同输入同 MAC、跨页不同 MAC */
const u64 *rk = drr_get_root_key();
u64 m1 = utsm_page_mac(rk, 0, 0, 0, desc->cipher_base);
u64 m2 = utsm_page_mac(rk, 0, 0, 0, desc->cipher_base);
u64 m3 = utsm_page_mac(rk, 0, 1, 0, desc->cipher_base);
if (m1 != m2 || m1 == m3) {
log_error("[UTSM] selftest page MAC determinism FAIL");
return UTSM_ERR_INVALID;
}
log_info("[UTSM] selftest page MAC determinism ok");
}
/* ==== U4: 密文页 dump —— 串口输出密文/明文 hex 对照 ==== */
{
int dst = utrw_debug_dump_page(cap.segment_slot, 0, 128);
if (dst != UTSM_OK) {
log_error("[UTSM] selftest cipher dump failed");
return dst;
}
}
/* ==== U2: Slow Path 真分支(EPOCH 刷新 / KEY_MISS 重派生 / POISONED 拒绝) ==== */
{
/* 1) EPOCH 过期:伪造 stale cap(epoch=desc->key_epoch+1),slow path 应
* 返回 OK 并回传刷新后的 cap,重试 read 应成功且内容一致 */
utsm_capability stale = cap;
stale.epoch = (u32)desc->key_epoch + 1;
utsm_capability refreshed = stale;
status = utsm_slow_path(stale, UTSM_RIGHT_READ, 128, len,
UTSM_ERR_EPOCH, &refreshed);
if (status != UTSM_OK) {
log_error("[UTSM] selftest slow EPOCH recover failed");
return status;
}
char slow_rb[64];
status = utsm_read(refreshed, 128, slow_rb, len);
if (status != UTSM_OK || memcmp(slow_rb, message, len) != 0) {
log_error("[UTSM] selftest slow EPOCH retry read failed");
return (status == UTSM_OK) ? UTSM_ERR_INVALID : status;
}
log_info("[UTSM] selftest slow EPOCH ok");
/* 2) KEY_MISS:清掉该段 PCKC 缓存,slow path 重派生应返回 OK */
utsm_pckc_invalidate_slot(cap.segment_slot);
status = utsm_slow_path(refreshed, UTSM_RIGHT_READ, 128, len,
UTSM_ERR_KEY_MISS, 0);
if (status != UTSM_OK) {
log_error("[UTSM] selftest slow KEY_MISS recover failed");
return status;
}
status = utsm_read(refreshed, 128, slow_rb, len);
if (status != UTSM_OK || memcmp(slow_rb, message, len) != 0) {
log_error("[UTSM] selftest slow KEY_MISS retry read failed");
return (status == UTSM_OK) ? UTSM_ERR_INVALID : status;
}
log_info("[UTSM] selftest slow KEY_MISS ok");
/* 3) POISONED:不可恢复,原样返回;DRR fault 留痕不重启
* (selftest 场景 drr_report_fault 只计数,无 reboot 语义) */
status = utsm_slow_path(refreshed, UTSM_RIGHT_READ, 128, len,
UTSM_ERR_POISONED, 0);
if (status != UTSM_ERR_POISONED) {
log_error("[UTSM] selftest slow POISONED passthrough failed");
return UTSM_ERR_INVALID;
}
log_info("[UTSM] selftest slow POISONED ok");
}
/* ==== SCHED-1: O(1) runqueue 语义(合成 TCB,协作式,无 tick) ==== */
/* ==== SCHED-1 + SCHED-2: runqueue / block-wake(tick 竞态保护) ==== */
{
u64 st_flags = selftest_irq_save();
int rq_rc = utsm_sched_selftest_runqueue();
int bw_rc = (rq_rc == 0) ? utsm_sched_selftest_blockwake() : 0;
selftest_irq_restore(st_flags);
if (rq_rc != 0) {
log_error("[SCHED] selftest: runqueue O(1) FAIL");
return UTSM_ERR_INVALID;
}
log_info("[SCHED] selftest: runqueue O(1) PASS");
if (bw_rc != 0) {
log_error("[SCHED] selftest: block/wake FAIL");
return UTSM_ERR_INVALID;
}
log_info("[SCHED] selftest: block/wake PASS");
}
/* ==== DRR-1: 真实脏页快照 + 页级回滚 ====
* 写 P1 → 快照(捕获 P1 密文页)→ 写 P2 覆盖 → 回滚 → 读回 P1 */
{
const char *p1 = "P1-ROLLBACK-STATE-01";
const char *p2 = "P2-OVERWRITE-STATE-0";
u64 plen = strlen(p1) + 1;
status = utsm_write(cap, 512, p1, plen);
if (status != UTSM_OK) {
log_error("[DRR] selftest P1 write failed");
return status;
}
int snap = drr_ckpt_snapshot_dirty();
log_hex64("[DRR] ckpt snapshot pages=", (u64)(i64)snap);
if (snap < 1) {
log_error("[DRR] selftest snapshot failed");
return UTSM_ERR_INVALID;
}
drr_checkpoint_meta meta;
if (drr_checkpoint_recover(&meta) != 0 || meta.type != DRR_CKPT_DIRTY_PAGE ||
meta.dirty_page_count < 1) {
log_error("[DRR] selftest meta verify failed");
return UTSM_ERR_INVALID;
}
status = utsm_write(cap, 512, p2, plen);
if (status != UTSM_OK) {
log_error("[DRR] selftest P2 write failed");
return status;
}
int rb = drr_rollback_pages();
log_hex64("[DRR] rollback pages=", (u64)(i64)rb);
if (rb < 1) {
log_error("[DRR] selftest rollback failed");
return UTSM_ERR_INVALID;
}
status = utsm_read(cap, 512, readback, plen);
if (status != UTSM_OK || memcmp(readback, p1, plen) != 0) {
log_error("[DRR] rollback verify FAIL");
return UTSM_ERR_INVALID;
}
log_info("[DRR] rollback verify ok");
}
/* ==== DRR-2: 看门狗判定(dry-run:reboot 关闭,仅验证日志路径) ==== */
{
drr_set_reboot_enabled(0);
drr_watchdog_register(0xFFFFFEu, 2);
drr_heartbeat_tick();
drr_heartbeat_tick();
drr_heartbeat_tick(); /* 3 ticks > timeout 2 → 触发 */
drr_watchdog_check(); /* 期望 [DRR] FAULT: watchdog timeout */
drr_watchdog_unregister(0xFFFFFEu);
drr_set_reboot_enabled(1);
log_info("[DRR] watchdog selftest done");
}
return UTSM_OK;
}