Skip to main content

ruvix_boot/
boot_loader.rs

1//! Main boot loader implementation.
2//!
3//! Orchestrates the five-stage boot sequence per ADR-087 Section 9.1.
4
5use crate::manifest::RvfManifest;
6use crate::signature::ML_DSA_65_PUBLIC_KEY_SIZE;
7use crate::stages::{Stage0Hardware, Stage1Verify, Stage2Create, Stage3Mount, Stage4Attest};
8use crate::witness_log::{WitnessLog, WitnessLogConfig};
9use crate::attestation::BootAttestation;
10use crate::capability_distribution::CapabilityDistribution;
11use ruvix_types::KernelError;
12use ruvix_cap::BootCapabilitySet;
13
14/// Boot stage enumeration.
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
16#[repr(u8)]
17pub enum BootStage {
18    /// Stage 0: Hardware initialization.
19    HardwareInit = 0,
20
21    /// Stage 1: RVF verification.
22    RvfVerify = 1,
23
24    /// Stage 2: Kernel object creation.
25    ObjectCreate = 2,
26
27    /// Stage 3: Component mount.
28    ComponentMount = 3,
29
30    /// Stage 4: First attestation.
31    FirstAttestation = 4,
32
33    /// Boot complete.
34    Complete = 5,
35}
36
37impl BootStage {
38    /// Returns the stage name.
39    #[inline]
40    #[must_use]
41    pub const fn as_str(&self) -> &'static str {
42        match self {
43            Self::HardwareInit => "Hardware Init",
44            Self::RvfVerify => "RVF Verify",
45            Self::ObjectCreate => "Object Create",
46            Self::ComponentMount => "Component Mount",
47            Self::FirstAttestation => "First Attestation",
48            Self::Complete => "Complete",
49        }
50    }
51}
52
53/// Boot loader configuration.
54#[derive(Debug, Clone)]
55pub struct BootConfig {
56    /// Boot public key for signature verification.
57    pub public_key: [u8; ML_DSA_65_PUBLIC_KEY_SIZE],
58
59    /// Witness log configuration.
60    pub witness_log_config: WitnessLogConfig,
61
62    /// Whether to enable verbose boot logging.
63    pub verbose: bool,
64
65    /// Platform identifier override (0 = auto-detect).
66    pub platform_id_override: u64,
67}
68
69impl Default for BootConfig {
70    fn default() -> Self {
71        Self {
72            public_key: [0u8; ML_DSA_65_PUBLIC_KEY_SIZE],
73            witness_log_config: WitnessLogConfig::default(),
74            verbose: false,
75            platform_id_override: 0,
76        }
77    }
78}
79
80/// Boot result containing all boot artifacts.
81#[derive(Debug)]
82pub struct BootResult {
83    /// Current boot stage.
84    pub stage: BootStage,
85
86    /// Hardware info from Stage 0.
87    pub hardware: Stage0Hardware,
88
89    /// Verified manifest from Stage 1.
90    pub manifest: Option<RvfManifest>,
91
92    /// Boot capabilities from Stage 2.
93    pub boot_capabilities: Option<BootCapabilitySet>,
94
95    /// Witness log from Stage 2.
96    pub witness_log: Option<WitnessLog>,
97
98    /// Capability distribution from Stage 3.
99    pub capability_distribution: Option<CapabilityDistribution>,
100
101    /// Boot attestation from Stage 4.
102    pub boot_attestation: Option<BootAttestation>,
103
104    /// Whether SEC-001 capability drop was performed.
105    pub sec001_capability_drop: bool,
106}
107
108impl BootResult {
109    /// Creates a new boot result.
110    #[must_use]
111    fn new() -> Self {
112        Self {
113            stage: BootStage::HardwareInit,
114            hardware: Stage0Hardware::new(),
115            manifest: None,
116            boot_capabilities: None,
117            witness_log: None,
118            capability_distribution: None,
119            boot_attestation: None,
120            sec001_capability_drop: false,
121        }
122    }
123}
124
125/// Main boot loader.
126///
127/// Orchestrates the five-stage boot sequence:
128/// - Stage 0: Hardware initialization
129/// - Stage 1: RVF manifest verification
130/// - Stage 2: Kernel object creation
131/// - Stage 3: Component mount + capability distribution
132/// - Stage 4: First attestation
133pub struct BootLoader {
134    /// Configuration.
135    config: BootConfig,
136
137    /// Boot result accumulator.
138    result: BootResult,
139
140    /// Stage handlers.
141    stage0: Stage0Hardware,
142    stage1: Stage1Verify,
143    stage2: Stage2Create,
144    stage3: Stage3Mount,
145    stage4: Stage4Attest,
146}
147
148impl BootLoader {
149    /// Creates a new boot loader with the given configuration.
150    #[must_use]
151    pub fn new(config: BootConfig) -> Self {
152        let mut stage1 = Stage1Verify::new();
153        stage1.set_public_key(&config.public_key);
154
155        Self {
156            config,
157            result: BootResult::new(),
158            stage0: Stage0Hardware::new(),
159            stage1,
160            stage2: Stage2Create::new(),
161            stage3: Stage3Mount::new(),
162            stage4: Stage4Attest::new(),
163        }
164    }
165
166    /// Creates a boot loader for testing (test keys, verbose).
167    #[cfg(test)]
168    #[must_use]
169    pub fn test_loader() -> Self {
170        let config = BootConfig {
171            public_key: [0u8; ML_DSA_65_PUBLIC_KEY_SIZE],
172            witness_log_config: WitnessLogConfig::default(),
173            verbose: true,
174            platform_id_override: 0,
175        };
176
177        Self::new(config)
178    }
179
180    /// Executes the full boot sequence.
181    ///
182    /// # Panics
183    ///
184    /// Panics if signature verification fails (SEC-001).
185    ///
186    /// # Errors
187    ///
188    /// Returns an error if any boot stage fails (except signature verification,
189    /// which panics per SEC-001).
190    pub fn boot(&mut self, manifest_bytes: &[u8], signature: &[u8]) -> Result<&BootResult, KernelError> {
191        // Stage 0: Hardware Init
192        self.execute_stage0()?;
193
194        // Stage 1: RVF Verify (panics on signature failure)
195        self.execute_stage1(manifest_bytes, signature)?;
196
197        // Stage 2: Object Create
198        self.execute_stage2()?;
199
200        // Stage 3: Component Mount
201        self.execute_stage3()?;
202
203        // Stage 4: First Attestation
204        self.execute_stage4()?;
205
206        self.result.stage = BootStage::Complete;
207
208        if self.config.verbose {
209            eprintln!("Boot complete");
210        }
211
212        Ok(&self.result)
213    }
214
215    /// Executes Stage 0: Hardware initialization.
216    fn execute_stage0(&mut self) -> Result<(), KernelError> {
217        if self.config.verbose {
218            eprintln!("Executing Stage 0: Hardware Init");
219        }
220
221        self.stage0.execute()?;
222        self.result.hardware = self.stage0.clone();
223        self.result.stage = BootStage::RvfVerify;
224
225        Ok(())
226    }
227
228    /// Executes Stage 1: RVF verification.
229    ///
230    /// # Panics
231    ///
232    /// Panics if signature verification fails (SEC-001).
233    fn execute_stage1(&mut self, manifest_bytes: &[u8], signature: &[u8]) -> Result<(), KernelError> {
234        if self.config.verbose {
235            eprintln!("Executing Stage 1: RVF Verify");
236        }
237
238        // This will panic on signature failure (SEC-001)
239        self.stage1.execute(manifest_bytes, signature)?;
240
241        self.result.manifest = self.stage1.manifest.clone();
242        self.result.stage = BootStage::ObjectCreate;
243
244        Ok(())
245    }
246
247    /// Executes Stage 2: Kernel object creation.
248    fn execute_stage2(&mut self) -> Result<(), KernelError> {
249        if self.config.verbose {
250            eprintln!("Executing Stage 2: Object Create");
251        }
252
253        let manifest = self.result.manifest.as_ref()
254            .ok_or(KernelError::InternalError)?;
255
256        let physical_memory = self.result.hardware.physical_memory_bytes;
257
258        self.stage2.execute(manifest, physical_memory)?;
259
260        self.result.boot_capabilities = self.stage2.boot_capabilities.clone();
261        self.result.witness_log = self.stage2.witness_log.take();
262        self.result.stage = BootStage::ComponentMount;
263
264        Ok(())
265    }
266
267    /// Executes Stage 3: Component mount + capability distribution.
268    fn execute_stage3(&mut self) -> Result<(), KernelError> {
269        if self.config.verbose {
270            eprintln!("Executing Stage 3: Component Mount");
271        }
272
273        let manifest = self.result.manifest.as_ref()
274            .ok_or(KernelError::InternalError)?;
275
276        let boot_caps = self.result.boot_capabilities.as_ref()
277            .ok_or(KernelError::InternalError)?;
278
279        self.stage3.execute(manifest, boot_caps)?;
280
281        self.result.capability_distribution = self.stage3.capability_distribution.clone();
282        self.result.sec001_capability_drop = self.stage3.capability_distribution
283            .as_ref()
284            .map(|d| d.root_dropped_to_minimum)
285            .unwrap_or(false);
286        self.result.stage = BootStage::FirstAttestation;
287
288        Ok(())
289    }
290
291    /// Executes Stage 4: First attestation.
292    fn execute_stage4(&mut self) -> Result<(), KernelError> {
293        if self.config.verbose {
294            eprintln!("Executing Stage 4: First Attestation");
295        }
296
297        let manifest = self.result.manifest.as_ref()
298            .ok_or(KernelError::InternalError)?;
299
300        let boot_caps = self.result.boot_capabilities.as_ref()
301            .ok_or(KernelError::InternalError)?;
302
303        let witness_log = self.result.witness_log.as_mut()
304            .ok_or(KernelError::InternalError)?;
305
306        self.stage4.execute(manifest, witness_log, boot_caps)?;
307
308        self.result.boot_attestation = self.stage4.attestation.clone();
309
310        Ok(())
311    }
312
313    /// Returns the current boot stage.
314    #[inline]
315    #[must_use]
316    pub fn current_stage(&self) -> BootStage {
317        self.result.stage
318    }
319
320    /// Returns the boot result (may be incomplete if boot failed).
321    #[inline]
322    #[must_use]
323    pub fn result(&self) -> &BootResult {
324        &self.result
325    }
326
327    /// Checks if SEC-001 capability drop was performed.
328    #[inline]
329    #[must_use]
330    pub fn sec001_compliant(&self) -> bool {
331        self.result.sec001_capability_drop
332    }
333}
334
335#[cfg(test)]
336mod tests {
337    use super::*;
338    use crate::signature::SIGNATURE_SIZE;
339
340    fn create_test_manifest() -> Vec<u8> {
341        let mut manifest = vec![0u8; 100];
342        manifest[0..4].copy_from_slice(b"RVF1");
343        manifest[4..6].copy_from_slice(&1u16.to_le_bytes());
344        manifest[6..8].copy_from_slice(&0u16.to_le_bytes());
345        manifest
346    }
347
348    fn create_test_signature(manifest: &[u8]) -> Vec<u8> {
349        use sha2::{Sha256, Digest};
350
351        let mut sig = vec![0u8; SIGNATURE_SIZE];
352        sig[0..4].copy_from_slice(b"TEST");
353
354        let mut hasher = Sha256::new();
355        hasher.update(manifest);
356        let hash = hasher.finalize();
357        sig[4..36].copy_from_slice(&hash);
358
359        sig
360    }
361
362    #[test]
363    fn test_boot_stage_ordering() {
364        assert!(BootStage::HardwareInit < BootStage::RvfVerify);
365        assert!(BootStage::RvfVerify < BootStage::ObjectCreate);
366        assert!(BootStage::ObjectCreate < BootStage::ComponentMount);
367        assert!(BootStage::ComponentMount < BootStage::FirstAttestation);
368        assert!(BootStage::FirstAttestation < BootStage::Complete);
369    }
370
371    #[test]
372    fn test_boot_config_default() {
373        let config = BootConfig::default();
374        assert_eq!(config.public_key, [0u8; ML_DSA_65_PUBLIC_KEY_SIZE]);
375        assert!(!config.verbose);
376    }
377
378    #[test]
379    fn test_full_boot_sequence() {
380        let mut loader = BootLoader::test_loader();
381
382        let manifest = create_test_manifest();
383        let signature = create_test_signature(&manifest);
384
385        let result = loader.boot(&manifest, &signature).unwrap();
386
387        assert_eq!(result.stage, BootStage::Complete);
388        assert!(result.manifest.is_some());
389        assert!(result.boot_capabilities.is_some());
390        assert!(result.witness_log.is_some());
391        assert!(result.boot_attestation.is_some());
392        assert!(result.sec001_capability_drop);
393    }
394
395    #[test]
396    fn test_boot_sec001_compliant() {
397        let mut loader = BootLoader::test_loader();
398
399        let manifest = create_test_manifest();
400        let signature = create_test_signature(&manifest);
401
402        loader.boot(&manifest, &signature).unwrap();
403
404        assert!(loader.sec001_compliant());
405    }
406
407    #[test]
408    fn test_boot_current_stage() {
409        let loader = BootLoader::test_loader();
410
411        // Initial stage should be HardwareInit
412        assert_eq!(loader.current_stage(), BootStage::HardwareInit);
413    }
414
415    #[test]
416    #[should_panic(expected = "Boot signature verification failed")]
417    fn test_boot_invalid_signature_panics() {
418        let mut loader = BootLoader::test_loader();
419
420        let manifest = create_test_manifest();
421        let wrong_manifest = b"wrong manifest";
422        let signature = create_test_signature(wrong_manifest);
423
424        // This should panic due to SEC-001
425        let _ = loader.boot(&manifest, &signature);
426    }
427
428    #[test]
429    fn test_boot_invalid_manifest() {
430        let mut loader = BootLoader::test_loader();
431
432        // Invalid manifest (wrong magic)
433        let manifest = b"XXXX";
434        let signature = vec![0u8; SIGNATURE_SIZE]; // All zeros is valid for test key
435
436        let result = loader.boot(manifest, &signature);
437
438        assert!(result.is_err());
439        assert_eq!(result.unwrap_err(), KernelError::InvalidManifest);
440    }
441}