Skip to main content

max / everycycle

9.8 KB · 275 lines History Blame Raw
1 //! Sign and verify a synthetic report end-to-end.
2 //!
3 //! No GPU required. The fixture exercises:
4 //! 1. Canonical JSON is deterministic for a given payload.
5 //! 2. A signed `BoxReport` and `CardReport` verify.
6 //! 3. The card payload's `box_report` hash matches what
7 //! `box_payload_hash` derives from the box payload.
8 //! 4. Tampering with any signed field breaks verification.
9 //! 5. Key derivation, canonical encoding, and signature bytes match a
10 //! pinned fixture, so a format break cannot pass silently.
11
12 use everycycle_appraise::{
13 TenantKey, VerifyError, box_payload_hash, canonical_json, sign_box_report, sign_card_report,
14 verify_box_report, verify_card_report,
15 };
16 use everycycle_hal::{
17 BoxReport, BoxReportPayload, CapabilityVector, CardReportPayload, DeviceIdentity,
18 DriverBinding, HostIdentity, Interconnect, LaunchOverhead, Memory, PeerLink, Precision,
19 PrecisionThroughput, ProbeEnvironment, Signature, ThermalEnvelope,
20 };
21
22 const TENANT: &str = "tailoredmachines";
23 const SEED: [u8; 32] = [7u8; 32];
24 const REPORT_VERSION: &str = "1";
25 const PROBED_AT: &str = "2026-06-20T18:23:11Z";
26 const PROBE_SUITE: &str = "0.1.0";
27
28 fn box_payload() -> BoxReportPayload {
29 BoxReportPayload {
30 report_version: REPORT_VERSION.into(),
31 probed_at: PROBED_AT.into(),
32 host: HostIdentity {
33 hostname: "astra".into(),
34 dmi_string: Some("synthetic-dmi".into()),
35 cpu_model: "synthetic-cpu".into(),
36 },
37 present_devices: vec!["0000:01:00.0".into()],
38 driver_versions: vec![DriverBinding {
39 bus_address: "0000:01:00.0".into(),
40 driver_version: "580.126.18".into(),
41 }],
42 ambient_c: 24.5,
43 probe_suite_version: PROBE_SUITE.into(),
44 }
45 }
46
47 fn capability() -> CapabilityVector {
48 CapabilityVector {
49 identity: DeviceIdentity {
50 bus_address: "0000:01:00.0".into(),
51 pci_ids: "10de:2c05:0000:0000".into(),
52 vbios_hash: Some([0xab; 32]),
53 serial: None,
54 },
55 environment: ProbeEnvironment {
56 driver_version: "580.126.18".into(),
57 ambient_c: 24.5,
58 duration_s: 120.0,
59 probe_version: PROBE_SUITE.into(),
60 },
61 throughput: vec![
62 PrecisionThroughput {
63 precision: Precision::Fp16,
64 tops: 250.0,
65 matrix_engine: true,
66 },
67 PrecisionThroughput {
68 precision: Precision::Bf16,
69 tops: 250.0,
70 matrix_engine: true,
71 },
72 PrecisionThroughput {
73 precision: Precision::Fp8E4M3,
74 tops: 500.0,
75 matrix_engine: true,
76 },
77 PrecisionThroughput {
78 precision: Precision::Int8,
79 tops: 500.0,
80 matrix_engine: true,
81 },
82 ],
83 memory: Memory {
84 physical_bytes: 17_179_869_184,
85 usable_bytes: 16_000_000_000,
86 bandwidth_read_bps: 700.0e9,
87 bandwidth_write_bps: 680.0e9,
88 errors_observed: 0,
89 },
90 interconnect: Interconnect {
91 host_bps: 32.0e9,
92 peers: Vec::<PeerLink>::new(),
93 },
94 launch: LaunchOverhead {
95 null_launch_ns: 1_800.0,
96 memcpy_1mib_ns: 95_000.0,
97 },
98 thermal: ThermalEnvelope {
99 time_to_throttle_s: None,
100 throttled_ratio: 1.0,
101 sustained_power_w: 285.0,
102 },
103 }
104 }
105
106 #[test]
107 fn canonical_json_is_deterministic() {
108 let a = canonical_json(&box_payload()).unwrap();
109 let b = canonical_json(&box_payload()).unwrap();
110 assert_eq!(a, b);
111
112 let cap = capability();
113 let one = canonical_json(&cap).unwrap();
114 let two = canonical_json(&cap).unwrap();
115 assert_eq!(one, two);
116 }
117
118 #[test]
119 fn signed_round_trip() {
120 let key = TenantKey::from_seed(TENANT, SEED);
121 let box_payload = box_payload();
122 let box_hash = box_payload_hash(&box_payload).unwrap();
123
124 let box_report = sign_box_report(&key, box_payload).unwrap();
125 verify_box_report(&box_report).expect("box report verifies");
126
127 let card_payload = CardReportPayload {
128 report_version: REPORT_VERSION.into(),
129 probed_at: PROBED_AT.into(),
130 box_report: box_hash.clone(),
131 capability: capability(),
132 };
133 let card_report = sign_card_report(&key, card_payload).unwrap();
134 verify_card_report(&card_report).expect("card report verifies");
135
136 // The card report's box_report field matches the hash a verifier
137 // would re-derive from the box payload it was built against.
138 assert_eq!(card_report.payload.box_report, box_hash);
139 }
140
141 #[test]
142 fn tampered_payload_fails() {
143 let key = TenantKey::from_seed(TENANT, SEED);
144 let mut box_report = sign_box_report(&key, box_payload()).unwrap();
145 box_report.payload.ambient_c += 1.0;
146 assert!(matches!(
147 verify_box_report(&box_report),
148 Err(VerifyError::SignatureMismatch)
149 ));
150
151 let box_hash = box_payload_hash(&box_payload()).unwrap();
152 let mut card_report = sign_card_report(
153 &key,
154 CardReportPayload {
155 report_version: REPORT_VERSION.into(),
156 probed_at: PROBED_AT.into(),
157 box_report: box_hash,
158 capability: capability(),
159 },
160 )
161 .unwrap();
162 card_report.payload.capability.memory.usable_bytes -= 1;
163 assert!(matches!(
164 verify_card_report(&card_report),
165 Err(VerifyError::SignatureMismatch)
166 ));
167 }
168
169 #[test]
170 fn tampered_signature_fails() {
171 let key = TenantKey::from_seed(TENANT, SEED);
172 let mut box_report = sign_box_report(&key, box_payload()).unwrap();
173 // Flip a base64 character in the signature to a different valid one.
174 let s = &mut box_report.signature.sig;
175 let first = s.chars().next().unwrap();
176 let replacement = if first == 'A' { 'B' } else { 'A' };
177 s.replace_range(0..1, &replacement.to_string());
178 assert!(verify_box_report(&box_report).is_err());
179 }
180
181 /// Byte-level constants pinned from the fixture above. Every other test
182 /// in this file signs and verifies inside one process, so all of them
183 /// stay green if seed-to-key derivation, canonical encoding, or
184 /// signature encoding changes. These literals are the only thing that
185 /// notices.
186 ///
187 /// Regenerating them is never the fix for a failure here. A mismatch
188 /// means previously issued appraisals no longer verify, which is a
189 /// format break that needs a version bump, not a new constant.
190 mod pinned {
191 /// `TenantKey::from_seed(TENANT, SEED).pubkey_b64()`. Guards
192 /// seed-to-key derivation and the base64 alphabet.
193 pub(crate) const PUBKEY_B64: &str = "6kpsY+KcUgq+9VB7Ey7F+ZVHdq6+vnuSQh7qaRRG0iw=";
194
195 /// `canonical_json(&box_payload())`. Guards key ordering at every
196 /// level, compact separators, and float formatting.
197 pub(crate) const BOX_JSON: &str = r#"{"ambient_c":24.5,"driver_versions":[{"bus_address":"0000:01:00.0","driver_version":"580.126.18"}],"host":{"cpu_model":"synthetic-cpu","dmi_string":"synthetic-dmi","hostname":"astra"},"present_devices":["0000:01:00.0"],"probe_suite_version":"0.1.0","probed_at":"2026-06-20T18:23:11Z","report_version":"1"}"#;
198
199 /// `box_payload_hash(&box_payload())`. Guards the SHA-256 digest and
200 /// the lowercase hex encoding.
201 pub(crate) const BOX_HASH: &str =
202 "b875c714b30278ded37f8522bcec679565a97a723e30820e4f378e027e22799d";
203
204 /// Signature over `BOX_JSON`. Ed25519 nonces are derived from the
205 /// key and message (RFC 8032), so this is reproducible.
206 pub(crate) const BOX_SIG: &str =
207 "gBVK+hWaX5SkmjzgwvhhsyYb9CTSo0I7xf1394G3TEQddri8CexNzs198N10cAocMu98DSrvowIHlI9oveCFCQ==";
208
209 /// Signature over the card payload, which nests `CapabilityVector`
210 /// and so also covers enum-variant and nested-object encoding that
211 /// the box payload never exercises.
212 pub(crate) const CARD_SIG: &str =
213 "8Hwfz2Lf+CAsn8iU2AsNhwH0gyO192aAjAT4bCcaSUJiUyqQsdsiiXXMckMek5OF/7Ip+sv/X069dKImdHFVDg==";
214 }
215
216 #[test]
217 fn seed_derives_the_pinned_pubkey() {
218 let key = TenantKey::from_seed(TENANT, SEED);
219 assert_eq!(key.pubkey_b64(), pinned::PUBKEY_B64);
220 }
221
222 #[test]
223 fn box_payload_encodes_to_the_pinned_bytes() {
224 assert_eq!(canonical_json(&box_payload()).unwrap(), pinned::BOX_JSON);
225 assert_eq!(box_payload_hash(&box_payload()).unwrap(), pinned::BOX_HASH);
226 }
227
228 #[test]
229 fn signatures_match_the_pinned_fixture() {
230 let key = TenantKey::from_seed(TENANT, SEED);
231
232 let box_report = sign_box_report(&key, box_payload()).unwrap();
233 assert_eq!(box_report.signature.alg, "ed25519");
234 assert_eq!(box_report.signature.tenant_identity, TENANT);
235 assert_eq!(box_report.signature.tenant_pubkey, pinned::PUBKEY_B64);
236 assert_eq!(box_report.signature.sig, pinned::BOX_SIG);
237
238 let card_report = sign_card_report(
239 &key,
240 CardReportPayload {
241 report_version: REPORT_VERSION.into(),
242 probed_at: PROBED_AT.into(),
243 box_report: pinned::BOX_HASH.into(),
244 capability: capability(),
245 },
246 )
247 .unwrap();
248 assert_eq!(card_report.signature.sig, pinned::CARD_SIG);
249 }
250
251 /// A report carrying the pinned signature verifies without ever calling
252 /// the signing path, which is what an archived appraisal does.
253 #[test]
254 fn a_report_rebuilt_from_pinned_bytes_verifies() {
255 let report = BoxReport {
256 payload: box_payload(),
257 signature: Signature {
258 alg: "ed25519".into(),
259 tenant_identity: TENANT.into(),
260 tenant_pubkey: pinned::PUBKEY_B64.into(),
261 sig: pinned::BOX_SIG.into(),
262 },
263 };
264 verify_box_report(&report).expect("pinned signature still verifies");
265 }
266
267 #[test]
268 fn box_hash_changes_with_any_field() {
269 let baseline = box_payload_hash(&box_payload()).unwrap();
270 let mut tweaked = box_payload();
271 tweaked.ambient_c = 25.0;
272 let after = box_payload_hash(&tweaked).unwrap();
273 assert_ne!(baseline, after);
274 }
275