Skip to content

Commit 6dd6316

Browse files
authored
feat: openkal.random on getentropy (#6)
* 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.
1 parent 2460cd2 commit 6dd6316

4 files changed

Lines changed: 49 additions & 2 deletions

File tree

.github/workflows/numbers.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ jobs:
4242
ftruncate truncate mmap lseek __getcwd getcwd \
4343
stat stat64 fstat fstat64 lstat lstat64 \
4444
fstatat fstatat64 getdirentries getdirentries64 \
45+
getentropy \
4546
bsdthread_terminate thread_selfid \
4647
open openat openat_nocancel renameat faccessat unlinkat \
4748
readlinkat mkdirat rmdir unlink mkdir rename access \

mcpp.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
namespace = "mcpplibs"
33
name = "openkal-macos"
4-
version = "0.3.3"
4+
version = "0.3.4"
55
description = "An implementation of openkal for macOS, written on the kernel's own calls. Its purpose is as much to test the specification as to be used."
66
license = "Apache-2.0"
77

@@ -18,7 +18,7 @@ authors = ["mcpplibs"]
1818
repo = "https://github.com/mcpplibs/openkal-macos"
1919

2020
[dependencies]
21-
openkal = "0.6.0"
21+
openkal = "0.7.0"
2222

2323
[build]
2424
# The flags are attached to this package's own sources rather than to the whole

src/random.cpp

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// openkal.random on this system --- getentropy(2).
2+
//
3+
// ⭐ THE NUMBER CAME FROM THE MACHINE, NOT FROM MEMORY. `.github/workflows/
4+
// numbers.yml` reads every number this implementation uses out of the SDK's own
5+
// `sys/syscall.h`, on both runners this repository targets, and both answered
6+
// `SYS_getentropy 500`. That workflow exists because a number recalled rather
7+
// than read is a number that is right until the day it is not.
8+
//
9+
// ⚠️ AND NOT `arc4random_buf`, WHICH IS WHAT libc++ WOULD REACH FOR HERE.
10+
// That name is in libSystem, and reaching into libSystem is what this backend
11+
// exists to avoid: it issues this kernel's calls directly, as the note in
12+
// `sys.h` records. `getentropy` is the call underneath.
13+
//
14+
// ⚠️ THE KERNEL CAPS A CALL AT 256 BYTES. That is this system's limit and not
15+
// this interface's, so the loop below turns it into the all-or-nothing
16+
// `kal_random_fill` promises.
17+
#include "sys.h"
18+
#include <openkal/random.h>
19+
20+
extern "C" int kal_random_fill(void* out, kal_uintptr len) {
21+
if (len == 0) return kal_ok;
22+
if (out == nullptr) return kal_err_invalid;
23+
24+
auto* p = static_cast<unsigned char*>(out);
25+
kal_uintptr filled = 0;
26+
while (filled < len) {
27+
const kal_uintptr chunk = (len - filled) > 256 ? 256 : (len - filled);
28+
const okm_long r = okm::sys(okm::nr_getentropy,
29+
reinterpret_cast<okm_long>(p + filled),
30+
static_cast<okm_long>(chunk), 0, 0);
31+
if (r < 0) {
32+
// ⚠️ The buffer is not restored, and the contract says it need not
33+
// be: a failed fill leaves it unspecified rather than unchanged.
34+
if (r == -4 /* EINTR */) continue;
35+
return kal_err_io;
36+
}
37+
filled += chunk;
38+
}
39+
return kal_ok;
40+
}
41+
42+
// Neither blocking nor hardware. This kernel's generator is seeded before a
43+
// process runs, so there is no wait to report; and whether the seed came from a
44+
// hardware source is not something this backend can observe.
45+
extern "C" const kal_uintptr kal_random_props = 0;

src/sys.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ enum : okm_long {
134134
nr_dup2 = 90, nr_fsync = 95, nr_gettimeofday = 116,
135135
nr_readv = 120, nr_writev = 121, nr_ftruncate = 201,
136136
nr_utimes = 138, nr_futimes = 139,
137+
nr_getentropy = 500,
137138
// This kernel has no call that reports the working directory --- the
138139
// measurement is in .github/workflows/numbers.yml, where SYS___getcwd is
139140
// absent from the system's own table. What it has instead is an enquiry

0 commit comments

Comments
 (0)