Skip to content

feat: openkal.random — entropy is not derivable from the other eight - #8

Merged
Sunrisepeak merged 5 commits into
mainfrom
feat/openkal-random
Aug 24, 2026
Merged

feat: openkal.random — entropy is not derivable from the other eight#8
Sunrisepeak merged 5 commits into
mainfrom
feat/openkal-random

Conversation

@Sunrisepeak

Copy link
Copy Markdown
Member

加一个接口的判据是「不加就实现不了」,而这一条满足它。

std::random_device 在这套体系上不可用,链条三层查到底,根在规范没有随机源接口。而现有九个接口一个都给不出熵:

  • time —— 时钟读数「对读源码的人不可预测,对攻击者可预测」。这句话是 openkal-musl/port/src/okm_start.cAT_RANDOM 凑数时自己写下的,并注明两者都不是安全属性。
  • fs —— kal_fs_open 只能相对 preopen 目录,开不了 /dev/urandom。⭐ 那是能力模型在工作,不是缺口。

⚠️ 绕过接口层直接发系统调用违反本规范存在的理由。两条都不行,于是层多一个接口。

⭐ 「宿主普遍有、裸机不一定有」正是 6.1 条的形状

后端 平台接口 有无
linux / macos / windows getrandom / getentropy / ProcessPrng
uefi EFI_RNG_PROTOCOL —— 可选协议 ⚠️
opensbi SBI 基础规范无 RNG 扩展

按 6.1 条不提供的实现让名字链接期缺席——与 openkal.fs 在 opensbi 上缺席同理,不需要任何新机制

⚠️ 没有 AVAILABLE 能力字

「有没有」由接口在场与否回答,不由能力字回答。定义 kal_random_props = 0 却不提供操作,会让程序越过链接器存在的意义——正是 openkal-opensbi@0.1.3 撤回的那件事。

声明检查 58/58;一致性套件加一节四条观察,含「两次填充不得相同」(⚠️ 2^-256 误报概率已写明)。

⭐ **加一个接口的判据是「不加就实现不了」,而这一条满足它。**

`std::random_device` 在这套体系上不可用,查到底是三层:

    std::random_device → libc++ 五条后端 → getentropy → musl getrandom()
    → syscall_cp(SYS_getrandom) → openkal-musl 无替代 → **规范无随机源接口**

⚠️ 而现有九个接口一个都给不出熵:

  · `time` —— 时钟读数「对读源码的人不可预测,对攻击者可预测」。
    这句话不是我写的,是 `openkal-musl/port/src/okm_start.c` 给 musl 的
    `AT_RANDOM` 凑 16 字节时**自己写下的**,并注明「在这个 port 上
    两者都不是安全属性」。给 allocator cookie 够用,给 random_device 不够。
  · `fs` —— `kal_fs_open` 只能相对 preopen 目录打开,开不了
    `/dev/urandom`。⭐ **那是能力模型在工作,不是缺口。**
  · 其余六个与熵无关。

⚠️ 而绕过接口层直接发系统调用违反本规范存在的理由。**两条都不行,
于是层多一个接口。**

── ⭐ 它「宿主普遍有、裸机不一定有」,正是 6.1 条的形状 ────

    linux/macos/windows   getrandom / getentropy / ProcessPrng   有
    uefi                  EFI_RNG_PROTOCOL —— **可选协议**        不一定
    opensbi               SBI 基础规范无 RNG 扩展                 无

按 6.1 条,不提供的实现让这些名字作为链接期定义缺席 —— 与 `openkal.fs`
在 opensbi 上缺席完全同理,**不需要任何新机制**。

── ⚠️ 没有 `AVAILABLE` 能力字,而这是设计 ──────────────

「有没有」由接口的**在场与否**回答(6.1),不由能力字回答。
一个不提供任何操作却定义 `kal_random_props = 0` 的后端,会让程序
越过链接器存在的意义 —— 这正是 `openkal-opensbi@0.1.3` 撤回的那件事。

两个位各有理由:`BLOCKING`(熵不足时可能等待,影响早期启动路径的程序)、
`HARDWARE`(直接来自硬件 RNG,影响信任模型而非接口行为)。

── 无部分成功 ────────────────────────────────────

要么每个字节都填,要么一个都不填。一个必须循环的调用者要区分
「短读」与「没有更多熵」,而后者不是本接口的状态:一个环境要么有源、
要么不提供本接口。`kal_err_again` 是「源暂时为空」(刚启动、池未播种),
不是「本环境没有源」。

一致性套件加一节四条观察,含「两次填充不得相同」——
⚠️ 该条以 2^-256 概率误报,把概率写出来比省掉好。

声明检查 58/58 通过。
…id why

我把 `random` 放进 `hosted`,于是一致性套件对每一个尚未实现它的后端
**链接失败**:

    lld-link: error: undefined symbol: kal_random_fill

⚠️ 而 `optional` 那段注释早就写着这件事:「a feature set that required every
optional interface would make optional mean nothing, **and the report would be
a link failure rather than an observation that did not hold**」。

⭐ `random` 与 `exec` 同形:宿主平台普遍提供,裸机只在板子有源时提供,
两者都不是偏离(6.1 条)。一个要求它的集合把「被允许的选择」变成了构建错误。

SPEC.md 的接口表同步改为 optional。
第 156 行那张表列出每个接口的模块名与头文件名,我加接口时漏了它。
⚠️ 一张只列了八个而接口有九个的表,读者会当成「这个接口没有模块」。
新增 `openkal.random` 是加法而非破坏:既有八个接口的名字、签名与语义
一字未动,而 6.1 条已经规定「实现不提供的接口作为链接期定义缺席」,
所以一个尚未实现它的后端**仍然是 0.7 的合规实现**。

⚠️ 次版本号而非补丁号:一致性套件的 `optional` 集合多了一项,
一个自称提供全部可选接口的实现因此要多提供一个。
标题与第 48 行的 "Version 0.6" 改为 0.7。

⚠️ 第 340 行**不改** —— 那句 "Every declaration of version 0.6 already
satisfies it" 是**历史陈述**,讲某条款当时为何没有让版本前进。
把它一起替换会把一句关于过去的记录改成一句关于现在的假话。
@Sunrisepeak
Sunrisepeak merged commit 9d3598b into main Aug 24, 2026
40 of 48 checks passed
Sunrisepeak added a commit to mcpplibs/openkal-macos that referenced this pull request Aug 24, 2026
* deps: follow openkal 0.7.0

规范新增 `openkal.random`(mcpplibs/openkal#8),版本升到 0.7.0。

⚠️ CI 有一道版本同步门,而它的诊断说明了为什么必须一起改:

    this is openkal 0.7.0 and this implementation is written against
    openkal 0.6.0. Nothing is wrong with either; they are not in step.

⭐ 本包**不提供** `openkal.random`,而那不是偏离 —— 6.1 条规定实现提供一个
接口是全有或全无,不提供的接口作为链接期定义缺席。这里跟随的只是规范版本,
不是接口集合。

* feat: openkal.random on getentropy(2)

⭐ **号来自机器,不来自记忆。** `.github/workflows/numbers.yml` 从 SDK 自己的
`sys/syscall.h` 读出本实现用到的每一个号,在本仓库针对的两个 runner 上都读,
而两者都答 `SYS_getentropy 500`。那个 workflow 存在的理由正是:
一个凭记忆写下的号,在它出错的那天之前一直是对的。

⚠️ **不用 `arc4random_buf`**,虽然 libc++ 在这个系统上默认会去找它。
那个名字在 libSystem 里,而伸手进 libSystem 正是本后端要避免的 ——
它直接发这个内核的调用,`sys.h` 的注释记着这一点。`getentropy` 是底下那一层。

⚠️ **这个内核单次上限 256 字节。** 那是这个系统的限制而不是本接口的,
所以循环把它变成 `kal_random_fill` 承诺的「全有或全无」。

失败时缓冲区不恢复 —— 契约如此:失败的填充留下未指定内容而非原内容。

* release: 0.3.4

The branch carried 0.3.3, which is the version on `main` and the version
already in the index. Following openkal 0.7.0 changes what this package
declares, and on two of these repositories it also adds an interface, so
the content behind that number is no longer the content published under
it.

openkal takes a minor bump for a new interface and an implementation
following it takes a patch bump --- the shape of 0.5.2 → 0.6.0 with
0.5.2 → 0.5.3 beneath it.
Sunrisepeak added a commit to mcpplibs/openkal-opensbi that referenced this pull request Aug 24, 2026
* deps: follow openkal 0.7.0

规范新增 `openkal.random`(mcpplibs/openkal#8),版本升到 0.7.0。

⚠️ CI 有一道版本同步门,而它的诊断说明了为什么必须一起改:

    this is openkal 0.7.0 and this implementation is written against
    openkal 0.6.0. Nothing is wrong with either; they are not in step.

⭐ 本包**不提供** `openkal.random`,而那不是偏离 —— 6.1 条规定实现提供一个
接口是全有或全无,不提供的接口作为链接期定义缺席。这里跟随的只是规范版本,
不是接口集合。

* release: 0.1.5

The branch carried 0.1.4, which is the version on `main` and the version
already in the index. Following openkal 0.7.0 changes what this package
declares, and on two of these repositories it also adds an interface, so
the content behind that number is no longer the content published under
it.

openkal takes a minor bump for a new interface and an implementation
following it takes a patch bump --- the shape of 0.5.2 → 0.6.0 with
0.5.2 → 0.5.3 beneath it.

* fix(ci): one specification in the graph, and follow the branch under test

Two failures, both quiet until this change made them loud.

The example asked for openkal 0.6.0 while the package it links asks for
0.7.0, so both were resolved and the engine fell back to mangling one
copy's module names to let them coexist:

    Downloading mcpplibs.openkal v0.6.0
    Downloading mcpplibs.openkal v0.7.0
    Mangled openkal.abort v0.6.0 ↔ v0.7.0 → …__v0_7_0__mcpp (cross-major fallback)

Mangling stages the sources under `target/.mangled/` and, by design,
leaves headers where they are. This package's sources reach `sbi.h` as a
quoted include beside them, which the staged copy has no path to:

    src/time.cpp:44:10: fatal error: 'sbi.h' file not found

Naming one specification removes the fallback and the example builds
against what the package is written for. The engine gap it exposed is
real and is being fixed separately; nothing here depends on that.

`OPENKAL_BRANCH` was `feat/openkal-closure`, a branch merged long before,
so every run since had been cloning a stale specification and reporting
on it. It now follows the branch under test where one of that name
exists, and says which it used.
Sunrisepeak added a commit to mcpplibs/openkal-uefi that referenced this pull request Aug 24, 2026
* deps: follow openkal 0.7.0

规范新增 `openkal.random`(mcpplibs/openkal#8),版本升到 0.7.0。

⚠️ CI 有一道版本同步门,而它的诊断说明了为什么必须一起改:

    this is openkal 0.7.0 and this implementation is written against
    openkal 0.6.0. Nothing is wrong with either; they are not in step.

⭐ 本包**不提供** `openkal.random`,而那不是偏离 —— 6.1 条规定实现提供一个
接口是全有或全无,不提供的接口作为链接期定义缺席。这里跟随的只是规范版本,
不是接口集合。

* release: 0.1.3

The branch carried 0.1.2, which is the version on `main` and the version
already in the index. Following openkal 0.7.0 changes what this package
declares, and on two of these repositories it also adds an interface, so
the content behind that number is no longer the content published under
it.

openkal takes a minor bump for a new interface and an implementation
following it takes a patch bump --- the shape of 0.5.2 → 0.6.0 with
0.5.2 → 0.5.3 beneath it.

* fix(ci): one specification in the graph

The example asked for openkal 0.6.0 while the package it links asks for
0.7.0. Both were resolved, the engine fell back to mangling one copy's
module names so they could coexist, and mangling stages sources without
the headers beside them:

    src/kal.cpp:32:10: fatal error: uefi.h: No such file or directory

Naming one specification removes the fallback.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant