veridian_kernel/pkg/format/signature.rs
1//! Package signature structures
2//!
3//! Handles serialization and deserialization of cryptographic signatures
4//! used for package verification. Supports dual-signature scheme with
5//! Ed25519 (classical) and Dilithium/ML-DSA (post-quantum) signatures.
6//!
7//! Also defines the signature policy, trust levels, and trusted key ring
8//! used by the package manager during installation to decide whether a
9//! package's cryptographic signatures are acceptable.
10
11use alloc::vec::Vec;
12
13// ============================================================================
14// Trust Levels
15// ============================================================================
16
17/// Trust level assigned to a signing key.
18///
19/// Levels are ordered: `Untrusted < Community < Developer < Core`.
20/// The package manager's [`SignaturePolicy`] specifies a minimum trust level
21/// that the signing key must meet for installation to proceed.
22#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, PartialOrd, Ord)]
23#[repr(u8)]
24pub enum TrustLevel {
25 /// Key is not trusted (default for unknown keys)
26 #[default]
27 Untrusted = 0,
28 /// Community-contributed key (third-party packages)
29 Community = 1,
30 /// Verified developer key
31 Developer = 2,
32 /// Core OS key (kernel, base system)
33 Core = 3,
34}
35
36// ============================================================================
37// Signature Policy
38// ============================================================================
39
40/// Policy controlling how the package manager enforces signature verification.
41///
42/// # Examples
43///
44/// ```ignore
45/// // Production: require both Ed25519 and Dilithium, minimum Developer trust
46/// let policy = SignaturePolicy::production();
47///
48/// // Development: skip all signature checks
49/// let policy = SignaturePolicy::development();
50/// ```
51#[derive(Debug, Clone)]
52pub struct SignaturePolicy {
53 /// When `true`, packages must have a valid Ed25519 signature from a
54 /// trusted key. When `false`, signature verification is skipped entirely.
55 pub require_signatures: bool,
56 /// Minimum trust level the signing key must have.
57 pub minimum_trust_level: TrustLevel,
58 /// When `true`, require a valid post-quantum (Dilithium/ML-DSA) signature
59 /// in addition to the Ed25519 signature.
60 pub require_post_quantum: bool,
61}
62
63impl SignaturePolicy {
64 /// Production policy: require Ed25519 signatures at Developer trust level.
65 /// Post-quantum (Dilithium) is optional until ecosystem matures.
66 pub fn production() -> Self {
67 Self {
68 require_signatures: true,
69 minimum_trust_level: TrustLevel::Developer,
70 require_post_quantum: false,
71 }
72 }
73
74 /// Development policy: no signature requirements.
75 pub fn development() -> Self {
76 Self {
77 require_signatures: false,
78 minimum_trust_level: TrustLevel::Untrusted,
79 require_post_quantum: false,
80 }
81 }
82}
83
84impl Default for SignaturePolicy {
85 fn default() -> Self {
86 Self::production()
87 }
88}
89
90// ============================================================================
91// Trusted Key Ring
92// ============================================================================
93
94/// A trusted Ed25519 public key with its SHA-256 fingerprint and trust level.
95#[derive(Debug, Clone)]
96pub struct TrustedKey {
97 /// Ed25519 public key (32 bytes)
98 pub public_key: [u8; 32],
99 /// SHA-256 fingerprint of `public_key` for human-readable identification
100 pub fingerprint: [u8; 32],
101 /// Trust level assigned to this key
102 pub trust_level: TrustLevel,
103}
104
105/// Collection of trusted Ed25519 signing keys.
106///
107/// The package manager iterates over these keys when verifying a package
108/// signature, accepting the first key whose Ed25519 verification succeeds.
109#[derive(Debug, Clone)]
110pub struct TrustedKeyRing {
111 keys: Vec<TrustedKey>,
112}
113
114impl TrustedKeyRing {
115 /// Create an empty key ring.
116 pub fn new() -> Self {
117 Self { keys: Vec::new() }
118 }
119
120 /// Create a key ring pre-populated with the built-in test key.
121 ///
122 /// The built-in key is a deterministic test key for development.
123 /// Production builds MUST replace this with keys from a real key ceremony.
124 pub fn with_builtin_keys() -> Self {
125 let mut ring = Self::new();
126
127 // Deterministic test key derived from "VeridianOS-PKG-KEY"
128 let mut pk = [0u8; 32];
129 let seed: &[u8; 18] = b"VeridianOS-PKG-KEY";
130 for (i, byte) in pk.iter_mut().enumerate() {
131 *byte = seed[i % seed.len()].wrapping_add(i as u8);
132 }
133
134 let fp = crate::crypto::hash::sha256(&pk);
135 ring.add_key(TrustedKey {
136 public_key: pk,
137 fingerprint: *fp.as_bytes(),
138 trust_level: TrustLevel::Core,
139 });
140
141 ring
142 }
143
144 /// Add a trusted key to the ring.
145 pub fn add_key(&mut self, key: TrustedKey) {
146 self.keys.push(key);
147 }
148
149 /// Find the first key whose public key bytes match.
150 pub fn find_key(&self, public_key: &[u8; 32]) -> Option<&TrustedKey> {
151 self.keys.iter().find(|k| &k.public_key == public_key)
152 }
153
154 /// Find a key by its SHA-256 fingerprint.
155 pub fn find_by_fingerprint(&self, fingerprint: &[u8; 32]) -> Option<&TrustedKey> {
156 self.keys.iter().find(|k| &k.fingerprint == fingerprint)
157 }
158
159 /// Remove keys matching the given fingerprint.
160 pub fn remove_key(&mut self, fingerprint: &[u8; 32]) {
161 self.keys.retain(|k| &k.fingerprint != fingerprint);
162 }
163
164 /// Iterate over all trusted keys.
165 pub fn keys(&self) -> &[TrustedKey] {
166 &self.keys
167 }
168}
169
170impl Default for TrustedKeyRing {
171 fn default() -> Self {
172 Self::new()
173 }
174}
175
176// ============================================================================
177// Package Signatures (serialization)
178// ============================================================================
179
180/// Package signature section
181#[derive(Debug)]
182pub struct PackageSignatures {
183 /// Ed25519 signature (64 bytes)
184 pub ed25519_sig: [u8; 64],
185 /// Dilithium signature (variable size)
186 pub dilithium_sig: Vec<u8>,
187}
188
189impl PackageSignatures {
190 /// Serialize signatures to bytes
191 pub fn to_bytes(&self) -> Vec<u8> {
192 let mut bytes = Vec::new();
193
194 // Ed25519 signature
195 bytes.extend_from_slice(&self.ed25519_sig);
196
197 // Dilithium signature length (u32)
198 let dil_len = self.dilithium_sig.len() as u32;
199 bytes.extend_from_slice(&dil_len.to_le_bytes());
200
201 // Dilithium signature
202 bytes.extend_from_slice(&self.dilithium_sig);
203
204 bytes
205 }
206
207 /// Deserialize signatures from bytes
208 pub fn from_bytes(data: &[u8]) -> Result<Self, crate::error::KernelError> {
209 if data.len() < 68 {
210 // 64 (Ed25519) + 4 (length)
211 return Err(crate::error::KernelError::InvalidArgument {
212 name: "signature_data",
213 value: "data too short (need >= 68 bytes)",
214 });
215 }
216
217 // Extract Ed25519 signature
218 let mut ed25519_sig = [0u8; 64];
219 ed25519_sig.copy_from_slice(&data[0..64]);
220
221 // Extract Dilithium signature length
222 let dil_len = u32::from_le_bytes([data[64], data[65], data[66], data[67]]) as usize;
223
224 if data.len() < 68 + dil_len {
225 return Err(crate::error::KernelError::InvalidArgument {
226 name: "signature_data",
227 value: "invalid Dilithium signature length",
228 });
229 }
230
231 // Extract Dilithium signature
232 let dilithium_sig = data[68..68 + dil_len].to_vec();
233
234 Ok(Self {
235 ed25519_sig,
236 dilithium_sig,
237 })
238 }
239}