Files
LithosAnanke/kernel/tests/fakes.c
T
Claude d7b2f6bf54 fix(v4): the identity code wipes Zuse's seed after every drive it handles (#176, the identity code)
sk_v4_genesis never wiped its seed or its read-back; sk_v4_drive_arrived
never wiped the proxy's seed after her login; sk_v4_real_zuse_arrived wiped
the seed only on a match. (The logged-in Zuse's own key stays in g_zuse_seed,
by design.)

Option 1: the three use one buffer the identity module owns, g_seeds (seed,
then its read-back), and sk_v4_drive_arrived -- which every drive goes through,
and which alone calls the other two -- runs the drive's handling (now
handle_drive()) and then wipes it, whichever way it went.
sk_v4_identity_seeds() lets the host tests read it.

kernel/tests/test_sk_v4_identity.c, 10 checks, through the real drive-arrival
path: a fake xHCI controller marks a slot attach-pending, the identity code's
idle beat handles it, the real gpt.c reads the stick's table from the RAM disk;
the block layer, signatures, key mint, marker and console faked. Genesis; a
genesis not read back; the proxy logging in; a real Zuse named, then her stick
logging in. Against the code before the wipe: 5 failures (every case's seeds
left). Now: 0. The harness gains fake_disk_bind. Built for amd64, aarch64,
riscv64. #176 done with 2bac2ac8 (the mint).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017RzZgrf7V7Zk2iczBXDRbm
2026-11-12 18:20:09 +00:00

114 lines
4.1 KiB
C

/* SPDX-License-Identifier: LicenseRef-Starship-1.0
* Copyright (c) 2023-2026 Robert A. James
*/
/* fakes.c -- see fakes.h. */
#include "fakes.h"
#include <stdlib.h>
#include <string.h>
/* ---- the console ---- */
#define FAKE_LINES 256
#define FAKE_LINE 256
static char lines[FAKE_LINES][FAKE_LINE];
static unsigned n_lines;
void fake_console_reset(void) { n_lines = 0; }
unsigned fake_console_lines(void) { return n_lines; }
const char *fake_console_line(unsigned i) { return i < n_lines ? lines[i] : ""; }
int fake_console_said(const char *text)
{
unsigned i;
for (i = 0; i < n_lines; i++) if (strstr(lines[i], text)) return 1;
return 0;
}
static void take(const char *s)
{
if (n_lines < FAKE_LINES) {
strncpy(lines[n_lines], s, FAKE_LINE - 1);
lines[n_lines][FAKE_LINE - 1] = '\0';
n_lines++;
}
}
void console_println(const char *s) { take(s); }
void console_puts(const char *s) { take(s); }
void console_putc(char c) { (void)c; }
/* ---- the RNG ---- */
static uint32_t rng_state = 1u;
static int rng_fails;
void fake_rng_reset(void) { rng_state = 1u; rng_fails = 0; }
void fake_rng_fail(int fail) { rng_fails = fail; }
int rng_get_bytes(uint8_t *buf, size_t n)
{
size_t i;
if (rng_fails) return -1;
for (i = 0; i < n; i++) { rng_state = rng_state * 1103515245u + 12345u; buf[i] = (uint8_t)(rng_state >> 16); }
return 0;
}
/* ---- the disk ---- */
static int listed(const uint32_t *list, uint32_t n, uint32_t block)
{
uint32_t i;
for (i = 0; i < n; i++) if (list[i] == block) return 1;
return 0;
}
static int d_open(blkio_dev_t *dev, const blkio_params_t *p) { dev->state = p->opaque; return BLKIO_OK; }
static int d_close(blkio_dev_t *dev) { (void)dev; return BLKIO_OK; }
static int d_read(blkio_dev_t *dev, uint32_t fblock, void *dst)
{
fake_disk *d = (fake_disk *)dev->state;
if (fblock >= d->blocks) return BLKIO_EINVAL;
if (listed(d->fail_read, d->n_fail_read, fblock)) return BLKIO_EIO;
memcpy(dst, d->bytes + (size_t)fblock * BLKIO_FORTH_BLOCK_SIZE, BLKIO_FORTH_BLOCK_SIZE);
return BLKIO_OK;
}
static int d_write(blkio_dev_t *dev, uint32_t fblock, const void *src)
{
fake_disk *d = (fake_disk *)dev->state;
if (fblock >= d->blocks) return BLKIO_EINVAL;
if (listed(d->fail_write, d->n_fail_write, fblock)) return BLKIO_EIO;
memcpy(d->bytes + (size_t)fblock * BLKIO_FORTH_BLOCK_SIZE, src, BLKIO_FORTH_BLOCK_SIZE);
d->writes++;
return BLKIO_OK;
}
static int d_flush(blkio_dev_t *dev) { fake_disk *d = (fake_disk *)dev->state; d->flushes++; return d->fail_flush ? BLKIO_EIO : BLKIO_OK; }
static int d_info(blkio_dev_t *dev, blkio_info_t *out)
{
fake_disk *d = (fake_disk *)dev->state;
memset(out, 0, sizeof *out);
out->forth_block_size = BLKIO_FORTH_BLOCK_SIZE;
out->total_blocks = d->blocks;
out->phys_sector_size = 512u;
out->phys_size_bytes = (uint64_t)d->blocks * BLKIO_FORTH_BLOCK_SIZE;
return BLKIO_OK;
}
static const blkio_vtable_t fake_vt = { d_open, d_close, d_read, d_write, d_flush, d_info };
int fake_disk_open(blkio_dev_t *dev, fake_disk *d, uint32_t blocks)
{
blkio_params_t p;
memset(d, 0, sizeof *d);
d->bytes = (uint8_t *)calloc(blocks, BLKIO_FORTH_BLOCK_SIZE);
d->blocks = blocks;
if (!d->bytes) return BLKIO_EIO;
memset(&p, 0, sizeof p);
p.forth_block_size = BLKIO_FORTH_BLOCK_SIZE;
p.total_blocks = blocks;
p.opaque = d;
return blkio_open(dev, &fake_vt, &p);
}
int fake_disk_bind(blkio_dev_t *dev, fake_disk *d)
{
blkio_params_t p;
memset(&p, 0, sizeof p);
p.forth_block_size = BLKIO_FORTH_BLOCK_SIZE;
p.total_blocks = d->blocks;
p.opaque = d;
return blkio_open(dev, &fake_vt, &p);
}
void fake_disk_free(fake_disk *d) { free(d->bytes); d->bytes = 0; }
void fake_disk_fail_read(fake_disk *d, uint32_t block) { if (d->n_fail_read < FAKE_DISK_MAX_FAULTS) d->fail_read[d->n_fail_read++] = block; }
void fake_disk_fail_write(fake_disk *d, uint32_t block) { if (d->n_fail_write < FAKE_DISK_MAX_FAULTS) d->fail_write[d->n_fail_write++] = block; }
uint8_t *fake_disk_sector(fake_disk *d, uint64_t lba) { return d->bytes + (size_t)lba * 512u; }