Skip to main content

ruvix_boot/
stages.rs

1//! Boot stage implementations (ADR-087 Section 9.1).
2//!
3//! The kernel boot follows a five-stage process:
4//!
5//! | Stage | Name | Description |
6//! |-------|------|-------------|
7//! | **0** | Hardware Init | Platform-specific initialization (mocked in Phase A) |
8//! | **1** | RVF Verify | Parse manifest + ML-DSA-65 signature verification |
9//! | **2** | Object Create | Create root task, regions, queues, witness log |
10//! | **3** | Component Mount | Mount components + distribute capabilities |
11//! | **4** | First Attestation | Boot attestation to witness log |
12
13use crate::manifest::RvfManifest;
14use crate::signature::SignatureVerifier;
15use crate::witness_log::{WitnessLog, WitnessLogConfig};
16use crate::capability_distribution::CapabilityDistribution;
17use crate::attestation::BootAttestation;
18use ruvix_types::{KernelError, RegionHandle, TaskHandle};
19use ruvix_cap::BootCapabilitySet;
20
21/// Stage 0: Hardware initialization.
22///
23/// In Phase A (Linux-hosted), this is a no-op.
24/// In Phase B (bare metal), this would:
25/// - Initialize CPU/MMU
26/// - Set up interrupt vectors
27/// - Initialize memory controller
28/// - Enable UART for diagnostics
29#[derive(Debug, Clone)]
30pub struct Stage0Hardware {
31    /// Whether hardware initialization completed.
32    pub initialized: bool,
33
34    /// Platform identifier.
35    pub platform_id: u64,
36
37    /// Total physical memory in bytes.
38    pub physical_memory_bytes: u64,
39
40    /// CPU frequency in Hz.
41    pub cpu_frequency_hz: u64,
42}
43
44impl Stage0Hardware {
45    /// Creates a new Stage 0 handler.
46    #[must_use]
47    pub fn new() -> Self {
48        Self {
49            initialized: false,
50            platform_id: 0,
51            physical_memory_bytes: 0,
52            cpu_frequency_hz: 0,
53        }
54    }
55
56    /// Executes Stage 0 hardware initialization.
57    ///
58    /// # Phase A (Linux-hosted)
59    ///
60    /// Returns mock hardware information.
61    ///
62    /// # Phase B (bare metal)
63    ///
64    /// Performs actual hardware initialization.
65    pub fn execute(&mut self) -> Result<(), KernelError> {
66        #[cfg(feature = "verbose")]
67        eprintln!("Stage 0: Hardware initialization (Phase A mock)");
68
69        // Phase A: Mock hardware info
70        self.platform_id = 0x5255_5649_585F_4131; // "RUVIX_A1"
71        self.physical_memory_bytes = 1024 * 1024 * 1024; // 1 GiB mock
72        self.cpu_frequency_hz = 1_000_000_000; // 1 GHz mock
73
74        self.initialized = true;
75
76        #[cfg(feature = "verbose")]
77        eprintln!(
78            "  Platform: 0x{:016X}, Memory: {} MiB, CPU: {} MHz",
79            self.platform_id,
80            self.physical_memory_bytes / (1024 * 1024),
81            self.cpu_frequency_hz / 1_000_000
82        );
83
84        Ok(())
85    }
86}
87
88impl Default for Stage0Hardware {
89    fn default() -> Self {
90        Self::new()
91    }
92}
93
94/// Stage 1: RVF manifest parse + signature verification.
95///
96/// **SECURITY CRITICAL (SEC-001)**: Signature verification failure
97/// causes immediate PANIC with no fallback boot path.
98pub struct Stage1Verify {
99    /// The verified manifest (set after successful verification).
100    pub manifest: Option<RvfManifest>,
101
102    /// Signature verifier.
103    verifier: Option<SignatureVerifier>,
104}
105
106impl Stage1Verify {
107    /// Creates a new Stage 1 handler.
108    #[must_use]
109    pub fn new() -> Self {
110        Self {
111            manifest: None,
112            verifier: None,
113        }
114    }
115
116    /// Sets the public key for signature verification.
117    pub fn set_public_key(&mut self, public_key: &[u8]) {
118        self.verifier = Some(SignatureVerifier::new(public_key));
119    }
120
121    /// Executes Stage 1 manifest verification.
122    ///
123    /// # Panics
124    ///
125    /// Panics if signature verification fails (SEC-001).
126    ///
127    /// # Errors
128    ///
129    /// Returns `KernelError::InvalidManifest` if manifest parsing fails.
130    pub fn execute(&mut self, manifest_bytes: &[u8], signature: &[u8]) -> Result<(), KernelError> {
131        #[cfg(feature = "verbose")]
132        eprintln!("Stage 1: RVF manifest verification");
133
134        // Verify signature (panics on failure per SEC-001)
135        let verifier = self.verifier.as_ref().ok_or(KernelError::InternalError)?;
136        verifier.verify_boot_signature(manifest_bytes, signature);
137
138        #[cfg(feature = "verbose")]
139        eprintln!("  Signature verified (ML-DSA-65)");
140
141        // Parse manifest
142        let manifest = RvfManifest::parse(manifest_bytes)?;
143
144        #[cfg(feature = "verbose")]
145        eprintln!(
146            "  Manifest parsed: {} components, {} regions",
147            manifest.component_graph.component_count(),
148            manifest.memory_schema.region_count()
149        );
150
151        // Validate manifest
152        if !manifest.validate() {
153            return Err(KernelError::InvalidManifest);
154        }
155
156        #[cfg(feature = "verbose")]
157        eprintln!("  Manifest validated");
158
159        self.manifest = Some(manifest);
160        Ok(())
161    }
162}
163
164impl Default for Stage1Verify {
165    fn default() -> Self {
166        Self::new()
167    }
168}
169
170/// Stage 2: Kernel object creation.
171///
172/// Creates:
173/// - Root task
174/// - Memory regions per manifest schema
175/// - Queues per manifest wiring
176/// - Witness log region
177pub struct Stage2Create {
178    /// Root task handle.
179    pub root_task: Option<TaskHandle>,
180
181    /// Created region handles.
182    pub regions: [Option<RegionHandle>; 256],
183    /// Number of active regions in the array.
184    pub region_count: usize,
185
186    /// Witness log handle.
187    pub witness_log: Option<WitnessLog>,
188
189    /// Initial capability set for root task.
190    pub boot_capabilities: Option<BootCapabilitySet>,
191}
192
193impl Stage2Create {
194    /// Creates a new Stage 2 handler.
195    #[must_use]
196    pub fn new() -> Self {
197        Self {
198            root_task: None,
199            regions: [None; 256],
200            region_count: 0,
201            witness_log: None,
202            boot_capabilities: None,
203        }
204    }
205
206    /// Executes Stage 2 kernel object creation.
207    ///
208    /// # Errors
209    ///
210    /// Returns an error if object creation fails (e.g., out of memory).
211    pub fn execute(
212        &mut self,
213        manifest: &RvfManifest,
214        _physical_memory_bytes: u64,
215    ) -> Result<(), KernelError> {
216        #[cfg(feature = "verbose")]
217        eprintln!("Stage 2: Kernel object creation");
218
219        // Create root task
220        let root_task_id = 1u32;
221        self.root_task = Some(TaskHandle::new(root_task_id, 0));
222
223        #[cfg(feature = "verbose")]
224        eprintln!("  Created root task: {:?}", self.root_task);
225
226        // Create regions per manifest
227        self.create_regions(manifest)?;
228
229        // Create witness log
230        let witness_config = WitnessLogConfig::from_policy(&manifest.witness_log_policy);
231        self.witness_log = Some(WitnessLog::new(witness_config));
232
233        #[cfg(feature = "verbose")]
234        eprintln!("  Created witness log");
235
236        // Create initial capability set
237        let mut boot_caps = BootCapabilitySet::new();
238        boot_caps.set_root_task(root_task_id as u64);
239        boot_caps.add_memory_region(0x1000, 0); // Physical memory
240        boot_caps.set_witness_log(0x2000);
241        boot_caps.set_timer(0x3000);
242        boot_caps.set_interrupt_queue(0x4000, u64::MAX);
243
244        // Add RVF package capability
245        boot_caps.set_rvf_package(
246            0x5000,
247            u64::from_le_bytes(manifest.content_hash[0..8].try_into().unwrap()),
248        );
249
250        #[cfg(feature = "verbose")]
251        eprintln!("  Created {} initial capabilities", boot_caps.total_count());
252
253        self.boot_capabilities = Some(boot_caps);
254
255        Ok(())
256    }
257
258    fn create_regions(&mut self, manifest: &RvfManifest) -> Result<(), KernelError> {
259        let count = manifest.memory_schema.region_count();
260
261        #[cfg(feature = "verbose")]
262        eprintln!("  Creating {} regions from manifest", count);
263
264        // Phase A: Create mock region handles
265        for i in 0..count {
266            if i >= 256 {
267                return Err(KernelError::LimitExceeded);
268            }
269
270            self.regions[i] = Some(RegionHandle::new(0x1000 + i as u32, 0));
271            self.region_count += 1;
272        }
273
274        Ok(())
275    }
276}
277
278impl Default for Stage2Create {
279    fn default() -> Self {
280        Self::new()
281    }
282}
283
284/// Stage 3: Component mount + capability distribution.
285///
286/// This stage:
287/// - Mounts WASM components
288/// - Distributes capabilities per manifest
289/// - Connects queues per wiring
290/// - Spawns initial tasks per WIT entry points
291/// - **Drops root task to minimum capability set (SEC-001)**
292pub struct Stage3Mount {
293    /// Number of components mounted.
294    pub components_mounted: usize,
295
296    /// Number of queues connected.
297    pub queues_connected: usize,
298
299    /// Number of tasks spawned.
300    pub tasks_spawned: usize,
301
302    /// Capability distribution result.
303    pub capability_distribution: Option<CapabilityDistribution>,
304}
305
306impl Stage3Mount {
307    /// Creates a new Stage 3 handler.
308    #[must_use]
309    pub fn new() -> Self {
310        Self {
311            components_mounted: 0,
312            queues_connected: 0,
313            tasks_spawned: 0,
314            capability_distribution: None,
315        }
316    }
317
318    /// Executes Stage 3 component mounting.
319    ///
320    /// # SEC-001 Compliance
321    ///
322    /// After this stage, the root task's capability set is reduced to
323    /// the minimum required for operation (no longer has full physical
324    /// memory access).
325    pub fn execute(
326        &mut self,
327        manifest: &RvfManifest,
328        boot_capabilities: &BootCapabilitySet,
329    ) -> Result<(), KernelError> {
330        #[cfg(feature = "verbose")]
331        eprintln!("Stage 3: Component mount + capability distribution");
332
333        // Mount components
334        self.mount_components(manifest)?;
335
336        // Connect queues
337        self.connect_queues(manifest)?;
338
339        // Distribute capabilities
340        self.distribute_capabilities(manifest, boot_capabilities)?;
341
342        // SEC-001: Drop root task to minimum capability set
343        self.drop_root_capabilities()?;
344
345        Ok(())
346    }
347
348    fn mount_components(&mut self, manifest: &RvfManifest) -> Result<(), KernelError> {
349        let count = manifest.component_graph.component_count();
350
351        #[cfg(feature = "verbose")]
352        eprintln!("  Mounting {} components", count);
353
354        // Phase A: Mock component mounting
355        self.components_mounted = count;
356
357        Ok(())
358    }
359
360    fn connect_queues(&mut self, manifest: &RvfManifest) -> Result<(), KernelError> {
361        let count = manifest.component_graph.wiring_count();
362
363        #[cfg(feature = "verbose")]
364        eprintln!("  Connecting {} queues", count);
365
366        // Phase A: Mock queue connection
367        self.queues_connected = count;
368
369        Ok(())
370    }
371
372    fn distribute_capabilities(
373        &mut self,
374        manifest: &RvfManifest,
375        boot_capabilities: &BootCapabilitySet,
376    ) -> Result<(), KernelError> {
377        #[cfg(feature = "verbose")]
378        eprintln!("  Distributing capabilities per manifest");
379
380        let distribution = CapabilityDistribution::from_manifest(manifest, boot_capabilities)?;
381        self.capability_distribution = Some(distribution);
382
383        Ok(())
384    }
385
386    fn drop_root_capabilities(&mut self) -> Result<(), KernelError> {
387        #[cfg(feature = "verbose")]
388        eprintln!("  SEC-001: Dropping root task to minimum capability set");
389
390        // In a real implementation, this would:
391        // 1. Identify the minimum capability set needed by root task
392        // 2. Revoke all other capabilities from root task
393        // 3. Ensure root task cannot re-escalate
394
395        // Phase A: Just mark that we did it
396        if let Some(ref mut dist) = self.capability_distribution {
397            dist.root_dropped_to_minimum = true;
398        }
399
400        Ok(())
401    }
402}
403
404impl Default for Stage3Mount {
405    fn default() -> Self {
406        Self::new()
407    }
408}
409
410/// Stage 4: First attestation (boot attestation to witness log).
411///
412/// Records the initial boot attestation containing:
413/// - RVF package hash
414/// - Capability table hash
415/// - Region layout hash
416/// - Timestamp
417pub struct Stage4Attest {
418    /// Boot attestation entry.
419    pub attestation: Option<BootAttestation>,
420
421    /// Whether attestation was written to witness log.
422    pub attested: bool,
423}
424
425impl Stage4Attest {
426    /// Creates a new Stage 4 handler.
427    #[must_use]
428    pub fn new() -> Self {
429        Self {
430            attestation: None,
431            attested: false,
432        }
433    }
434
435    /// Executes Stage 4 boot attestation.
436    pub fn execute(
437        &mut self,
438        manifest: &RvfManifest,
439        witness_log: &mut WitnessLog,
440        boot_capabilities: &BootCapabilitySet,
441    ) -> Result<(), KernelError> {
442        #[cfg(feature = "verbose")]
443        eprintln!("Stage 4: First attestation");
444
445        // Create boot attestation
446        let attestation = BootAttestation::new(
447            manifest.content_hash,
448            Self::hash_capability_table(boot_capabilities),
449            Self::hash_region_layout(manifest),
450            Self::get_timestamp(),
451        );
452
453        #[cfg(feature = "verbose")]
454        eprintln!("  Boot attestation created");
455
456        // Write to witness log
457        witness_log.append_boot_attestation(&attestation)?;
458
459        #[cfg(feature = "verbose")]
460        eprintln!("  Boot attestation written to witness log");
461
462        self.attestation = Some(attestation);
463        self.attested = true;
464
465        Ok(())
466    }
467
468    fn hash_capability_table(caps: &BootCapabilitySet) -> [u8; 32] {
469        use sha2::{Sha256, Digest};
470
471        let mut hasher = Sha256::new();
472
473        for cap in caps.iter() {
474            hasher.update(&cap.object_id.to_le_bytes());
475            hasher.update(&[cap.object_type as u8]);
476            hasher.update(&cap.rights.bits().to_le_bytes());
477            hasher.update(&cap.badge.to_le_bytes());
478        }
479
480        let result = hasher.finalize();
481        let mut hash = [0u8; 32];
482        hash.copy_from_slice(&result);
483        hash
484    }
485
486    fn hash_region_layout(manifest: &RvfManifest) -> [u8; 32] {
487        use sha2::{Sha256, Digest};
488
489        let mut hasher = Sha256::new();
490
491        hasher.update(&manifest.memory_schema.total_memory_required.to_le_bytes());
492        hasher.update(&(manifest.memory_schema.region_count() as u32).to_le_bytes());
493
494        let result = hasher.finalize();
495        let mut hash = [0u8; 32];
496        hash.copy_from_slice(&result);
497        hash
498    }
499
500    fn get_timestamp() -> u64 {
501        #[cfg(feature = "std")]
502        {
503            use std::time::{SystemTime, UNIX_EPOCH};
504            SystemTime::now()
505                .duration_since(UNIX_EPOCH)
506                .map(|d| d.as_nanos() as u64)
507                .unwrap_or(0)
508        }
509        #[cfg(not(feature = "std"))]
510        {
511            0 // No timestamp in no_std without a timer
512        }
513    }
514}
515
516impl Default for Stage4Attest {
517    fn default() -> Self {
518        Self::new()
519    }
520}
521
522#[cfg(test)]
523mod tests {
524    use super::*;
525
526    #[test]
527    fn test_stage0_hardware_init() {
528        let mut stage = Stage0Hardware::new();
529        assert!(!stage.initialized);
530
531        stage.execute().unwrap();
532
533        assert!(stage.initialized);
534        assert!(stage.physical_memory_bytes > 0);
535        assert!(stage.cpu_frequency_hz > 0);
536    }
537
538    #[test]
539    fn test_stage1_needs_public_key() {
540        let mut stage = Stage1Verify::new();
541        let manifest = b"test";
542        let signature = [0u8; 3309];
543
544        // Should fail without public key
545        let result = stage.execute(manifest, &signature);
546        assert!(result.is_err());
547    }
548
549    #[test]
550    fn test_stage2_creates_objects() {
551        let mut stage = Stage2Create::new();
552
553        // Create minimal valid manifest
554        let mut manifest_bytes = vec![0u8; 100];
555        manifest_bytes[0..4].copy_from_slice(b"RVF1");
556        manifest_bytes[4..6].copy_from_slice(&1u16.to_le_bytes()); // major
557        manifest_bytes[6..8].copy_from_slice(&0u16.to_le_bytes()); // minor
558
559        let manifest = RvfManifest::parse(&manifest_bytes).unwrap();
560        let physical_memory = 1024 * 1024 * 1024;
561
562        stage.execute(&manifest, physical_memory).unwrap();
563
564        assert!(stage.root_task.is_some());
565        assert!(stage.witness_log.is_some());
566        assert!(stage.boot_capabilities.is_some());
567    }
568
569    #[test]
570    fn test_stage3_sec001_capability_drop() {
571        let mut stage = Stage3Mount::new();
572
573        // Create minimal manifest
574        let mut manifest_bytes = vec![0u8; 100];
575        manifest_bytes[0..4].copy_from_slice(b"RVF1");
576        manifest_bytes[4..6].copy_from_slice(&1u16.to_le_bytes());
577
578        let manifest = RvfManifest::parse(&manifest_bytes).unwrap();
579        let boot_caps = BootCapabilitySet::minimal(1);
580
581        stage.execute(&manifest, &boot_caps).unwrap();
582
583        // Verify SEC-001: root capability drop occurred
584        assert!(stage.capability_distribution.is_some());
585        assert!(stage.capability_distribution.as_ref().unwrap().root_dropped_to_minimum);
586    }
587
588    #[test]
589    fn test_stage4_attestation() {
590        let mut stage = Stage4Attest::new();
591
592        // Create minimal manifest
593        let mut manifest_bytes = vec![0u8; 100];
594        manifest_bytes[0..4].copy_from_slice(b"RVF1");
595        manifest_bytes[4..6].copy_from_slice(&1u16.to_le_bytes());
596
597        let manifest = RvfManifest::parse(&manifest_bytes).unwrap();
598        let boot_caps = BootCapabilitySet::minimal(1);
599        let mut witness_log = WitnessLog::new(WitnessLogConfig::default());
600
601        stage.execute(&manifest, &mut witness_log, &boot_caps).unwrap();
602
603        assert!(stage.attested);
604        assert!(stage.attestation.is_some());
605    }
606}