Landin library reference source

core/io/entropy.ldn

1--  Entropy: the system's source of random bytes, a concept beside the
2--  others and outside `world`, and a scripted one whose bytes a test
3--  gives.  A deterministic generator seeded from it is core/random's.
4
5import core/mem
6
7--- The system's source of unpredictable bytes, fit for seeding a
8--- generator or making a key.  `fill_random` fills all of `into` or fails
9--- `io_failed`, and after a failure what `into` holds is not to be used.
10--- It is a concept of its own, outside `world`, so a provider without a
11--- source, and a firmware image that never asks for one, carries none.
12public entropy: type = concept (provider: type)
13    --- Fill all of `into` with random bytes, or fail.
14    fill_random: (self: provider, into: []mut u8) -> none ! io_failed
15end entropy
16
17--- Fill all of `into` with random bytes from the provider, through
18--- `entropy` evidence.  On a hosted system they are the system's own,
19--- `getrandom` on Linux and `arc4random_buf` on Darwin and FreeBSD.
20public fill_random: (provider: type is entropy, host: provider,
21                     into: []mut u8) -> none ! io_failed =
22    try provider.fill_random(host, into)
23end fill_random
24
25--- Caller-owned state of scripted entropy: how many of its bytes it has
26--- given and how often it was asked.  Declare it `zeroed` and give it to
27--- `entropy_over`; it must outlive the handle, and may be read while the
28--- handle is in use.
29public entropy_space: type = struct
30    used: usize
31    requests: usize
32end entropy_space
33
34scripted_entropy_value: type = struct
35    state: ptr mut entropy_space
36    bytes: []u8
37end scripted_entropy_value
38
39--- Entropy whose bytes are the caller's, given in order, so a program
40--- that seeds itself from entropy runs the same way in every test: a
41--- provider of `entropy`.  A request for more than what is left of them
42--- fails `io_failed` and gives nothing, so a test can make the source run
43--- dry.  Copies share the state.
44public scripted_entropy: type = scripted_entropy_value
45
46--- Fill `state` for scripted entropy over `bytes`, which the handle lends;
47--- keep them alive while it is used.
48public entropy_over: (inout state: entropy_space, bytes: []u8)
49                     -> (host: scripted_entropy from state, bytes) =
50    state = (used: 0, requests: 0)
51    host = (state: addr state, bytes: bytes)
52end entropy_over
53
54scripted_fill: (self: scripted_entropy, into: []mut u8) -> none ! io_failed =
55    state: ptr mut entropy_space = self.state
56    inc state.val.requests
57    used: usize = state.val.used
58    given: []u8 = self.bytes
59    fail io_failed when used > lenof given or lenof into > lenof given - used
60    mem.copy(into, given[used..<used + lenof into]) else (problem)
61        _ = problem
62        fail io_failed
63    end
64    state.val.used = used + lenof into
65end scripted_fill
66
67scripted_entropy is entropy (fill_random: scripted_fill)