File size: 6,033 Bytes
6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 42d913f 6900478 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 | #![no_std]
#![forbid(unsafe_code)]
//! BEHCS-1024 60-glyph hash-derived coordinate: Federation-1024's own `project_60d` and `sha256`.
//!
//! The two upstream functions are included byte-identical, so every tuple maps exactly as upstream.
//! A coordinate is an address, not source recovery.
/// The upstream source, byte-identical (federation-1024@dc1da1a9, `kernel/boot/src/hwinv.rs`).
mod hwinv {
include!("upstream/hwinv-tuple-cap.rs");
include!("upstream/hwinv-sha256-project-60d.rs");
pub(crate) const UPSTREAM_TUPLE_CAP: usize = TUPLE_CAP;
pub(crate) fn project(tuple: &[u8]) -> [u16; 60] {
project_60d(tuple)
}
}
/// Number of 10-bit glyph coordinates.
pub const DIMENSIONS: usize = 60;
/// Symbol indices range from 0 through 1023 inclusive.
pub const ALPHABET_SIZE: usize = 1024;
/// Upstream's `TUPLE_CAP`: "Input is bounded by `TUPLE_CAP`" (hwinv.rs:148).
pub const TUPLE_CAP: usize = hwinv::UPSTREAM_TUPLE_CAP;
/// 60 dimensions plus the digests upstream derives from them, stored without heap allocation.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Projection {
pub glyphs: [u16; DIMENSIONS],
/// Upstream SHA-256 of the 120 coordinate bytes (`device_pid_full` upstream).
pub coordinate_sha256: [u8; 32],
/// First eight bytes of `coordinate_sha256` (`device_pid` upstream); a short handle, not a signer.
pub host8: [u8; 8],
/// Upstream `sha256` of the tuple (`hw_tuple_pid_full` upstream).
pub source_sha256: [u8; 32],
}
impl Projection {
/// Canonical 60 * 2 bytes in big-endian glyph order.
pub fn coordinate_bytes(&self) -> [u8; 120] {
let mut bytes = [0u8; 120];
for (i, glyph) in self.glyphs.iter().enumerate() {
bytes[i * 2..i * 2 + 2].copy_from_slice(&glyph.to_be_bytes());
}
bytes
}
}
/// Upstream's projection plus the digests upstream's `emit_device_pid` derives from it.
pub fn project_60d(tuple: &[u8]) -> Projection {
let glyphs = hwinv::project(tuple);
let mut coord_bytes = [0u8; 120];
for (index, glyph) in glyphs.iter().enumerate() {
coord_bytes[index * 2..index * 2 + 2].copy_from_slice(&glyph.to_be_bytes());
}
let coordinate_sha256 = hwinv::sha256(&coord_bytes);
let mut host8 = [0u8; 8];
host8.copy_from_slice(&coordinate_sha256[..8]);
Projection {
glyphs,
coordinate_sha256,
host8,
source_sha256: hwinv::sha256(tuple),
}
}
#[cfg(test)]
mod tests {
extern crate std;
use self::std::fmt::Write as _;
use self::std::vec::Vec;
use super::*;
fn hex(bytes: &[u8]) -> std::string::String {
let mut out = std::string::String::with_capacity(bytes.len() * 2);
for b in bytes {
write!(&mut out, "{b:02x}").expect("in-memory write");
}
out
}
fn pattern(len: usize) -> Vec<u8> {
(0..len).map(|i| (i % 256) as u8).collect()
}
#[test]
fn sha256_standard_vectors() {
assert_eq!(hex(&hwinv::sha256(b"")), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
assert_eq!(hex(&hwinv::sha256(b"abc")), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
}
#[test]
fn independent_empty_reference_vector() {
let p = project_60d(b"");
assert_eq!(&p.glyphs[..10], &[831, 408, 169, 987, 87, 301, 61, 840, 631, 732]);
assert_eq!(hex(&p.coordinate_sha256), "a93505a95d0aace1fb6edc8b2e8d94581fdb49cdb0f961097a6d9ac9cc0102e7");
assert_eq!(&p.host8, &p.coordinate_sha256[..8]);
}
#[test]
fn independent_abc_reference_vector() {
let p = project_60d(b"abc");
assert_eq!(&p.glyphs[..10], &[813, 428, 103, 701, 206, 505, 788, 597, 191, 714]);
assert_eq!(hex(&p.coordinate_sha256), "ff504d90899902cd2ec8e0c075553f65c3116a8f6c1ad3fee6907f00edaff4d6");
assert_eq!(hex(&p.source_sha256), "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
}
#[test]
fn upstream_vector_508() {
let p = project_60d(&pattern(508));
assert_eq!(&p.glyphs[..10], &[902, 3, 689, 384, 304, 662, 46, 568, 144, 1004]);
assert_eq!(hex(&p.coordinate_sha256), "d9c002d12a4b667b1f4f8e351e38f35d4c731e566ebd51a09e367e23470dd943");
}
#[test]
fn upstream_vectors_509_to_512() {
// Vectors from independent_referee.py's model of upstream.
let expected = [
(509, [189, 526, 380, 507], "c8e0925819849fc411afe4c452e5da2c615949beaff0387114f93991604bb344"),
(510, [539, 52, 514, 404], "79a25f0c2fac953137c230cc5ee89d46207931efeaa62639906cb468ea71df1a"),
(511, [876, 847, 583, 217], "9bb6c8d92f63e1121fce300d6af9c9b7016bad1e4ac2f81d30e98e2be131290e"),
(512, [256, 476, 545, 523], "f0e02e6b285e3ad7d6d2414da9153f1f6a7f3668f2406dd7bcf59f1bb8e5a333"),
];
for (len, head, coordinate) in expected {
let tuple = pattern(len);
let p = project_60d(&tuple);
assert_eq!(&p.glyphs[..4], &head, "len {len}");
assert_eq!(hex(&p.coordinate_sha256), coordinate, "len {len}");
}
}
#[test]
fn upstream_vectors_beyond_tuple_cap() {
let at_cap = project_60d(&pattern(TUPLE_CAP));
for len in [513, 600, 1024] {
assert_eq!(project_60d(&pattern(len)), at_cap, "len {len}");
}
assert_eq!(
hex(&at_cap.source_sha256),
"110009dcee21620b166f3abfecb5eff7a873be729d1c2d53822e7acc5f34eb9b"
);
}
#[test]
fn deterministic_and_bounded_coordinates() {
let first = project_60d(b"bounded-test");
let second = project_60d(b"bounded-test");
assert_eq!(first, second);
assert!(first.glyphs.iter().all(|g| usize::from(*g) < ALPHABET_SIZE));
assert_eq!(first.coordinate_bytes().len(), DIMENSIONS * 2);
assert_ne!(first.source_sha256, first.coordinate_sha256);
assert_ne!(first, project_60d(b"bounded-tesu"));
}
}
|