1use crate::types::{CapId, CapPayload, Capability, Key, PolicyState, SealedTag, Time};
13
14#[derive(Debug, Clone)]
37pub struct KeyState {
38 pub(crate) current: Key,
42
43 pub(crate) epoch: u64,
47
48 pub(crate) previous: Option<Key>,
52
53 pub(crate) previous_epoch: Option<u64>,
57}
58
59impl KeyState {
60 pub fn initial(key: Key) -> Self {
64 KeyState {
65 current: key,
66 epoch: 0,
67 previous: None,
68 previous_epoch: None,
69 }
70 }
71
72 pub fn empty() -> Self {
76 KeyState {
77 current: Key::empty(),
78 epoch: 0,
79 previous: None,
80 previous_epoch: None,
81 }
82 }
83
84 pub fn rotate(&mut self, new_key: Key) {
94 self.previous = Some(self.current.clone());
95 self.previous_epoch = Some(self.epoch);
96 self.current = new_key;
97 self.epoch = self
101 .epoch
102 .checked_add(1)
103 .expect("key epoch overflow (unreachable in practice)");
104 }
105
106 pub fn rotated(&self, new_key: Key) -> Self {
110 KeyState {
111 current: new_key,
112 epoch: self
113 .epoch
114 .checked_add(1)
115 .expect("key epoch overflow (unreachable in practice)"),
116 previous: Some(self.current.clone()),
117 previous_epoch: Some(self.epoch),
118 }
119 }
120
121 #[inline]
123 pub fn current(&self) -> &Key {
124 &self.current
125 }
126
127 #[inline]
129 pub fn epoch(&self) -> u64 {
130 self.epoch
131 }
132
133 #[inline]
135 pub fn previous(&self) -> Option<&Key> {
136 self.previous.as_ref()
137 }
138
139 #[inline]
141 pub fn previous_epoch(&self) -> Option<u64> {
142 self.previous_epoch
143 }
144
145 pub fn epoch_valid(&self, cap_epoch: u64) -> bool {
149 if cap_epoch >= self.epoch {
151 return true;
152 }
153 match self.previous_epoch {
155 Some(prev_epoch) => cap_epoch >= prev_epoch,
156 None => false,
157 }
158 }
159
160 pub fn verify_seal(&self, payload: &CapPayload, tag: &SealedTag) -> bool {
170 if crate::crypto::verify_seal(&self.current, payload, tag) {
172 return true;
173 }
174 match &self.previous {
176 Some(prev_key) => crate::crypto::verify_seal(prev_key, payload, tag),
177 None => false,
178 }
179 }
180
181 pub fn verify_with_epoch(&self, payload: &CapPayload, tag: &SealedTag, cap_epoch: u64) -> bool {
185 self.epoch_valid(cap_epoch) && self.verify_seal(payload, tag)
186 }
187
188 pub fn clear_previous(&mut self) {
193 self.previous = None;
194 self.previous_epoch = None;
195 }
196}
197
198impl Default for KeyState {
199 fn default() -> Self {
200 KeyState::empty()
201 }
202}
203
204pub type CapTable = Vec<(CapId, Capability)>;
209
210#[derive(Debug, Clone, PartialEq, Eq)]
212pub enum KernelError {
213 CapNotFound(CapId),
215 CapIdExhausted,
217 CapIdCollision(CapId),
219 InvalidCapability(String),
221 CounterOverflow(&'static str),
223}
224
225impl std::fmt::Display for KernelError {
226 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
227 match self {
228 KernelError::CapNotFound(id) => write!(f, "Capability {id} not found"),
229 KernelError::CapIdExhausted => write!(f, "Capability ID space exhausted"),
230 KernelError::CapIdCollision(id) => write!(f, "Capability ID {id} already exists"),
231 KernelError::InvalidCapability(msg) => write!(f, "Invalid capability: {msg}"),
232 KernelError::CounterOverflow(name) => write!(f, "{name} counter overflow"),
233 }
234 }
235}
236
237impl std::error::Error for KernelError {}
238
239pub type ChildrenIndex = Vec<(CapId, Vec<CapId>)>;
244
245#[derive(Debug, Clone)]
257pub struct RevocationState {
258 pub(crate) caps: CapTable,
263
264 pub(crate) epoch: u64,
268
269 pub(crate) children_index: ChildrenIndex,
274}
275
276impl RevocationState {
277 pub fn empty() -> Self {
281 RevocationState {
282 caps: Vec::new(),
283 epoch: 0,
284 children_index: Vec::new(),
285 }
286 }
287
288 fn find_index(&self, cap_id: CapId) -> Option<usize> {
292 self.caps
293 .binary_search_by_key(&cap_id, |entry| entry.0)
294 .ok()
295 }
296
297 fn find_insert_pos(&self, cap_id: CapId) -> (usize, bool) {
304 match self.caps.binary_search_by_key(&cap_id, |entry| entry.0) {
305 Ok(pos) => (pos, true),
306 Err(pos) => (pos, false),
307 }
308 }
309
310 pub fn is_valid(&self, cap_id: CapId) -> bool {
317 self.find_index(cap_id)
318 .is_some_and(|idx| self.caps[idx].1.is_valid())
319 }
320
321 pub fn get(&self, cap_id: CapId) -> Option<&Capability> {
323 self.find_index(cap_id).map(|idx| &self.caps[idx].1)
324 }
325
326 #[allow(dead_code)] pub(crate) fn get_mut(&mut self, cap_id: CapId) -> Option<&mut Capability> {
329 self.find_index(cap_id).map(|idx| &mut self.caps[idx].1)
330 }
331
332 #[inline]
334 pub fn contains(&self, cap_id: CapId) -> bool {
335 self.find_index(cap_id).is_some()
336 }
337
338 pub fn revoke(&self, cap_id: CapId) -> Self {
345 let new_caps = self
346 .caps
347 .iter()
348 .map(|(id, cap)| {
349 if *id == cap_id {
350 let mut revoked_cap = cap.clone();
351 revoked_cap.revoke();
352 (*id, revoked_cap)
353 } else {
354 (*id, cap.clone())
355 }
356 })
357 .collect();
358 RevocationState {
359 caps: new_caps,
360 epoch: self.epoch,
361 children_index: self.children_index.clone(),
362 }
363 }
364
365 pub fn revoke_mut(&mut self, cap_id: CapId) -> Result<(), KernelError> {
371 match self.find_index(cap_id) {
372 Some(idx) => {
373 self.caps[idx].1.revoke();
374 Ok(())
375 }
376 None => Err(KernelError::CapNotFound(cap_id)),
377 }
378 }
379
380 pub fn has_ancestor(&self, cap_id: CapId, ancestor_id: CapId) -> bool {
386 self.has_ancestor_with_fuel(cap_id, ancestor_id, cap_id)
387 }
388
389 fn has_ancestor_with_fuel(&self, cap_id: CapId, ancestor_id: CapId, fuel: u128) -> bool {
391 if fuel == 0 {
392 return false;
393 }
394
395 match self.get(cap_id) {
396 None => false,
397 Some(cap) => match cap.parent() {
398 None => false,
399 Some(parent_id) => {
400 if parent_id == ancestor_id {
401 true
402 } else {
403 self.has_ancestor_with_fuel(parent_id, ancestor_id, fuel - 1)
404 }
405 }
406 },
407 }
408 }
409
410 pub fn in_revoke_set(&self, k: CapId, cap_id: CapId) -> bool {
414 k == cap_id || self.has_ancestor(k, cap_id)
415 }
416
417 pub fn revoke_transitive(&self, cap_id: CapId) -> Self {
423 let new_caps = self
424 .caps
425 .iter()
426 .map(|(k, cap)| {
427 if self.in_revoke_set(*k, cap_id) {
428 let mut revoked = cap.clone();
429 revoked.revoke();
430 (*k, revoked)
431 } else {
432 (*k, cap.clone())
433 }
434 })
435 .collect();
436 RevocationState {
437 caps: new_caps,
438 epoch: self.epoch,
439 children_index: self.children_index.clone(),
440 }
441 }
442
443 pub fn revoke_transitive_mut(&mut self, cap_id: CapId) {
445 let mut to_revoke = Vec::with_capacity(self.caps.len());
447 to_revoke.extend(
448 self.caps
449 .iter()
450 .enumerate()
451 .filter_map(|(i, (id, _))| self.in_revoke_set(*id, cap_id).then_some(i)),
452 );
453
454 for idx in to_revoke {
456 self.caps[idx].1.revoke();
457 }
458 }
459
460 pub fn insert(&self, cap: Capability) -> Result<Self, KernelError> {
473 let id = cap.id();
474 let parent = cap.parent();
475 let (pos, exists) = self.find_insert_pos(id);
476
477 if exists {
478 return Err(KernelError::CapIdCollision(id));
479 }
480
481 let mut new_caps = Vec::with_capacity(self.caps.len() + 1);
483 new_caps.extend_from_slice(&self.caps[..pos]);
484 new_caps.push((id, cap));
485 new_caps.extend_from_slice(&self.caps[pos..]);
486
487 let mut new_index = self.children_index.clone();
489 if let Some(parent_id) = parent {
490 Self::add_child_to_index(&mut new_index, parent_id, id);
491 }
492
493 Ok(RevocationState {
494 caps: new_caps,
495 epoch: self.epoch,
496 children_index: new_index,
497 })
498 }
499
500 pub fn insert_mut(&mut self, cap: Capability) -> Result<(), KernelError> {
508 let id = cap.id();
509 let parent = cap.parent();
510 let (pos, exists) = self.find_insert_pos(id);
511
512 if exists {
513 return Err(KernelError::CapIdCollision(id));
514 }
515
516 self.caps.insert(pos, (id, cap));
517
518 if let Some(parent_id) = parent {
520 Self::add_child_to_index(&mut self.children_index, parent_id, id);
521 }
522
523 Ok(())
524 }
525
526 fn collect_descendants(&self, cap_id: CapId) -> Vec<CapId> {
538 let mut queue: Vec<CapId> = Vec::with_capacity(self.caps.len().saturating_add(1));
539 let mut head: usize = 0;
540 let mut visited = std::collections::BTreeSet::new();
541 let mut collected: Vec<CapId> = Vec::new();
542
543 queue.push(cap_id);
544
545 while head < queue.len() {
546 let id = queue[head];
547 head += 1;
548
549 if !visited.insert(id) {
550 continue;
551 }
552
553 collected.push(id);
554 queue.extend(self.get_children(id).iter().copied());
555 }
556
557 collected
558 }
559
560 fn get_children(&self, parent_id: CapId) -> &[CapId] {
564 match self
565 .children_index
566 .binary_search_by_key(&parent_id, |entry| entry.0)
567 {
568 Ok(idx) => &self.children_index[idx].1,
569 Err(_) => &[],
570 }
571 }
572
573 fn add_child_to_index(index: &mut ChildrenIndex, parent_id: CapId, child_id: CapId) {
580 match index.binary_search_by_key(&parent_id, |entry| entry.0) {
581 Ok(idx) => {
582 index[idx].1.push(child_id);
583 }
584 Err(pos) => {
585 index.insert(pos, (parent_id, vec![child_id]));
586 }
587 }
588 }
589
590 pub fn revoke_transitive_fast(&self, cap_id: CapId) -> Self {
601 let mut to_revoke = self.collect_descendants(cap_id);
602 to_revoke.sort_unstable();
603
604 let new_caps = self
605 .caps
606 .iter()
607 .map(|(k, cap)| {
608 if to_revoke.binary_search(k).is_ok() {
609 let mut revoked = cap.clone();
610 revoked.revoke();
611 (*k, revoked)
612 } else {
613 (*k, cap.clone())
614 }
615 })
616 .collect();
617
618 RevocationState {
619 caps: new_caps,
620 epoch: self.epoch,
621 children_index: self.children_index.clone(),
622 }
623 }
624
625 pub fn revoke_transitive_fast_mut(&mut self, cap_id: CapId) -> Result<(), KernelError> {
631 if self.find_index(cap_id).is_none() {
632 return Err(KernelError::CapNotFound(cap_id));
633 }
634
635 let mut to_revoke = self.collect_descendants(cap_id);
636 to_revoke.sort_unstable();
637
638 for id in to_revoke {
639 if let Some(idx) = self.find_index(id) {
640 self.caps[idx].1.revoke();
641 }
642 }
643
644 Ok(())
645 }
646
647 #[inline]
649 pub fn epoch(&self) -> u64 {
650 self.epoch
651 }
652
653 #[inline]
655 pub fn cap_count(&self) -> usize {
656 self.caps.len()
657 }
658
659 pub fn valid_caps(&self) -> Vec<(CapId, Capability)> {
661 let mut result = Vec::with_capacity(self.caps.len());
663 let mut i = 0;
664 while i < self.caps.len() {
665 if self.caps[i].1.is_valid() {
666 result.push((self.caps[i].0, self.caps[i].1.clone()));
667 }
668 i += 1;
669 }
670 result
671 }
672
673 pub fn cap_ids(&self) -> Vec<CapId> {
675 let mut ids = Vec::with_capacity(self.caps.len());
676 let mut i = 0;
677 while i < self.caps.len() {
678 ids.push(self.caps[i].0);
679 i += 1;
680 }
681 ids
682 }
683
684 #[inline]
689 pub fn iter(&self) -> std::slice::Iter<'_, (CapId, Capability)> {
690 self.caps.iter()
691 }
692
693 pub fn any_valid_targeting(&self, target: crate::types::ResourceId) -> bool {
701 self.caps
702 .iter()
703 .any(|(_, cap)| cap.is_valid() && cap.target() == target)
704 }
705}
706
707impl Default for RevocationState {
708 fn default() -> Self {
709 RevocationState::empty()
710 }
711}
712
713#[derive(Debug, Clone)]
717pub struct KernelState {
718 pub(crate) key_state: KeyState,
722
723 pub(crate) policy: PolicyState,
727
728 pub(crate) revocation: RevocationState,
732
733 pub(crate) now: Time,
737
738 pub(crate) next_cap_id: CapId,
747}
748
749impl KernelState {
750 pub fn initial(key: Key, policy: PolicyState) -> Self {
754 KernelState {
755 key_state: KeyState::initial(key),
756 policy,
757 revocation: RevocationState::empty(),
758 now: 0,
759 next_cap_id: 0,
760 }
761 }
762
763 pub fn tick(&self) -> Result<Self, KernelError> {
771 let new_now = self
772 .now
773 .checked_add(1)
774 .ok_or(KernelError::CounterOverflow("time"))?;
775 Ok(KernelState {
776 key_state: self.key_state.clone(),
777 policy: self.policy.clone(),
778 revocation: self.revocation.clone(),
779 now: new_now,
780 next_cap_id: self.next_cap_id,
781 })
782 }
783
784 pub fn rotate_key(&mut self, new_key: Key) {
793 self.key_state.rotate(new_key);
794 }
795
796 pub fn with_rotated_key(&self, new_key: Key) -> Self {
798 KernelState {
799 key_state: self.key_state.rotated(new_key),
800 policy: self.policy.clone(),
801 revocation: self.revocation.clone(),
802 now: self.now,
803 next_cap_id: self.next_cap_id,
804 }
805 }
806
807 #[inline]
809 pub fn key_epoch(&self) -> u64 {
810 self.key_state.epoch()
811 }
812
813 #[inline]
815 pub fn key_state(&self) -> &KeyState {
816 &self.key_state
817 }
818
819 #[inline]
821 #[allow(dead_code)] pub(crate) fn key_state_mut(&mut self) -> &mut KeyState {
823 &mut self.key_state
824 }
825
826 pub fn verify_cap_seal(&self, cap: &Capability) -> bool {
830 self.key_state
831 .verify_with_epoch(&cap.payload(), cap.signature(), cap.epoch())
832 }
833
834 pub fn alloc_cap_id(&mut self) -> Result<CapId, KernelError> {
844 let id = self.next_cap_id;
845 self.next_cap_id = match self.next_cap_id.checked_add(1) {
846 Some(v) => v,
847 None => return Err(KernelError::CapIdExhausted),
848 };
849 Ok(id)
850 }
851
852 #[inline]
854 pub fn next_cap_id(&self) -> CapId {
855 self.next_cap_id
856 }
857
858 pub fn tick_checked(&mut self) -> Result<(), KernelError> {
864 self.now = self
865 .now
866 .checked_add(1)
867 .ok_or(KernelError::CounterOverflow("time"))?;
868 Ok(())
869 }
870
871 pub fn cap_not_revoked(&self, cap: &Capability) -> bool {
875 self.revocation.is_valid(cap.id())
876 }
877
878 #[inline]
880 pub fn now(&self) -> Time {
881 self.now
882 }
883
884 #[inline]
886 pub fn revocation(&self) -> &RevocationState {
887 &self.revocation
888 }
889
890 #[inline]
892 pub(crate) fn revocation_mut(&mut self) -> &mut RevocationState {
893 &mut self.revocation
894 }
895
896 #[inline]
898 pub fn policy(&self) -> &PolicyState {
899 &self.policy
900 }
901
902 #[inline]
904 #[allow(dead_code)] pub(crate) fn policy_mut(&mut self) -> &mut PolicyState {
906 &mut self.policy
907 }
908
909 #[inline]
913 #[allow(dead_code)] pub(crate) fn hmac_key(&self) -> &Key {
915 self.key_state.current()
916 }
917}
918
919impl Default for KernelState {
920 fn default() -> Self {
922 KernelState {
923 key_state: KeyState::empty(),
924 policy: PolicyState::default(),
925 revocation: RevocationState::empty(),
926 now: 0,
927 next_cap_id: 0,
928 }
929 }
930}
931
932use crate::types::{PluginId, ResourceId, SecurityLevel};
943
944#[derive(Debug, Clone, PartialEq, Eq)]
950pub struct PluginMeta {
951 pub level: SecurityLevel,
953 pub held_caps: Vec<CapId>,
955}
956
957impl PluginMeta {
958 pub fn empty() -> Self {
962 PluginMeta {
963 level: SecurityLevel::Public,
964 held_caps: Vec::new(),
965 }
966 }
967
968 pub fn grant_cap(&mut self, cap_id: CapId) {
973 match self.held_caps.binary_search(&cap_id) {
974 Ok(_) => {} Err(pos) => self.held_caps.insert(pos, cap_id),
976 }
977 }
978
979 pub fn revoke_cap(&mut self, cap_id: CapId) {
986 if let Ok(pos) = self.held_caps.binary_search(&cap_id) {
987 self.held_caps.remove(pos);
988 }
989 }
990
991 pub fn holds_cap(&self, cap_id: CapId) -> bool {
995 self.held_caps.binary_search(&cap_id).is_ok()
996 }
997}
998
999impl Default for PluginMeta {
1000 fn default() -> Self {
1001 PluginMeta::empty()
1002 }
1003}
1004
1005#[derive(Debug, Clone, PartialEq, Eq)]
1009pub struct ResourceMeta {
1010 pub level: SecurityLevel,
1012}
1013
1014impl ResourceMeta {
1015 pub fn empty() -> Self {
1019 ResourceMeta {
1020 level: SecurityLevel::Public,
1021 }
1022 }
1023}
1024
1025impl Default for ResourceMeta {
1026 fn default() -> Self {
1027 ResourceMeta::empty()
1028 }
1029}
1030
1031#[derive(Debug, Clone)]
1042pub struct KernelStateCore {
1043 pub(crate) key_state: KeyState,
1045 pub(crate) revocation: RevocationState,
1047 pub(crate) plugin_metas: Vec<(PluginId, PluginMeta)>,
1049 pub(crate) resource_metas: Vec<(ResourceId, ResourceMeta)>,
1051 pub(crate) now: Time,
1053 #[allow(dead_code)] pub(crate) next_cap_id: CapId,
1056}
1057
1058impl KernelStateCore {
1059 pub fn empty(hmac_key: Key) -> Self {
1063 KernelStateCore {
1064 key_state: KeyState::initial(hmac_key),
1065 revocation: RevocationState::empty(),
1066 plugin_metas: Vec::new(),
1067 resource_metas: Vec::new(),
1068 now: 0,
1069 next_cap_id: 0,
1070 }
1071 }
1072
1073 #[inline]
1077 pub fn hmac_key(&self) -> &Key {
1078 self.key_state.current()
1079 }
1080
1081 #[inline]
1083 pub fn key_state(&self) -> &KeyState {
1084 &self.key_state
1085 }
1086
1087 pub fn rotate_key(&mut self, new_key: Key) {
1089 self.key_state.rotate(new_key);
1090 }
1091
1092 pub fn verify_cap_seal(&self, cap: &Capability) -> bool {
1094 self.key_state
1095 .verify_with_epoch(&cap.payload(), cap.signature(), cap.epoch())
1096 }
1097
1098 pub fn get_plugin_meta(&self, pid: PluginId) -> PluginMeta {
1102 match self
1103 .plugin_metas
1104 .binary_search_by_key(&pid, |entry| entry.0)
1105 {
1106 Ok(idx) => self.plugin_metas[idx].1.clone(),
1107 Err(_) => PluginMeta::empty(),
1108 }
1109 }
1110
1111 pub fn set_plugin_meta(&mut self, pid: PluginId, mut meta: PluginMeta) {
1119 meta.held_caps.sort_unstable();
1120 meta.held_caps.dedup();
1121 match self
1122 .plugin_metas
1123 .binary_search_by_key(&pid, |entry| entry.0)
1124 {
1125 Ok(idx) => {
1126 self.plugin_metas[idx].1 = meta;
1127 }
1128 Err(pos) => {
1129 self.plugin_metas.insert(pos, (pid, meta));
1130 }
1131 }
1132 }
1133
1134 pub fn get_resource_meta(&self, rid: ResourceId) -> ResourceMeta {
1140 match self
1141 .resource_metas
1142 .binary_search_by_key(&rid, |entry| entry.0)
1143 {
1144 Ok(idx) => self.resource_metas[idx].1.clone(),
1145 Err(_) => ResourceMeta::empty(),
1146 }
1147 }
1148
1149 pub fn set_resource_meta(&mut self, rid: ResourceId, meta: ResourceMeta) {
1156 match self
1157 .resource_metas
1158 .binary_search_by_key(&rid, |entry| entry.0)
1159 {
1160 Ok(idx) => {
1161 self.resource_metas[idx].1 = meta;
1162 }
1163 Err(pos) => {
1164 self.resource_metas.insert(pos, (rid, meta));
1165 }
1166 }
1167 }
1168
1169 pub fn plugin_level(&self, pid: PluginId) -> SecurityLevel {
1175 self.get_plugin_meta(pid).level
1176 }
1177
1178 pub fn resource_level(&self, rid: ResourceId) -> SecurityLevel {
1182 self.get_resource_meta(rid).level
1183 }
1184
1185 pub fn plugin_holds(&self, pid: PluginId, cap_id: CapId) -> bool {
1189 self.plugin_metas
1190 .binary_search_by_key(&pid, |e| e.0)
1191 .ok()
1192 .is_some_and(|i| self.plugin_metas[i].1.holds_cap(cap_id))
1193 }
1194
1195 pub fn cap_is_valid(&self, cap_id: CapId) -> bool {
1199 self.revocation.is_valid(cap_id)
1200 }
1201
1202 pub fn now(&self) -> Time {
1204 self.now
1205 }
1206
1207 pub fn epoch(&self) -> u64 {
1209 self.revocation.epoch()
1210 }
1211}
1212
1213impl Default for KernelStateCore {
1214 fn default() -> Self {
1215 KernelStateCore::empty(Key::empty())
1216 }
1217}
1218
1219#[derive(Debug, Clone)]
1226pub enum KernelRequest {
1227 CapDelegate {
1230 new_cap: Capability,
1232 target: PluginId,
1234 },
1235 CapRevoke {
1237 cap_id: CapId,
1239 },
1240 SetPluginLevel {
1242 plugin_id: PluginId,
1244 level: SecurityLevel,
1246 },
1247 SetResourceLevel {
1249 resource_id: ResourceId,
1251 level: SecurityLevel,
1253 },
1254 Tick,
1256 RotateKey {
1261 new_key: Key,
1263 },
1264}
1265
1266pub type KernelResult = Result<KernelStateCore, KernelError>;
1270
1271pub fn kernel_dispatch(core: KernelStateCore, req: KernelRequest) -> KernelResult {
1283 match req {
1284 KernelRequest::CapDelegate { new_cap, target } => {
1285 dispatch_cap_delegate(core, new_cap, target)
1286 }
1287 KernelRequest::CapRevoke { cap_id } => dispatch_cap_revoke(core, cap_id),
1288 KernelRequest::SetPluginLevel { plugin_id, level } => {
1289 dispatch_set_plugin_level(core, plugin_id, level)
1290 }
1291 KernelRequest::SetResourceLevel { resource_id, level } => {
1292 dispatch_set_resource_level(core, resource_id, level)
1293 }
1294 KernelRequest::Tick => dispatch_tick(core),
1295 KernelRequest::RotateKey { new_key } => Ok(dispatch_rotate_key(core, new_key)),
1296 }
1297}
1298
1299fn dispatch_cap_delegate(
1303 mut core: KernelStateCore,
1304 new_cap: Capability,
1305 target: PluginId,
1306) -> KernelResult {
1307 if core.revocation.contains(new_cap.id()) {
1309 return Err(KernelError::CapIdCollision(new_cap.id()));
1310 }
1311
1312 let cap_id = new_cap.id();
1314 core.revocation.insert_mut(new_cap)?;
1315
1316 let mut target_meta = core.get_plugin_meta(target);
1318 target_meta.grant_cap(cap_id);
1319 core.set_plugin_meta(target, target_meta);
1320
1321 Ok(core)
1322}
1323
1324#[allow(clippy::unnecessary_wraps)] fn dispatch_cap_revoke(mut core: KernelStateCore, cap_id: CapId) -> KernelResult {
1329 core.revocation.revoke_transitive_fast_mut(cap_id)?;
1330 Ok(core)
1331}
1332
1333#[allow(clippy::unnecessary_wraps)] fn dispatch_set_plugin_level(
1338 mut core: KernelStateCore,
1339 plugin_id: PluginId,
1340 level: SecurityLevel,
1341) -> KernelResult {
1342 let mut meta = core.get_plugin_meta(plugin_id);
1343 meta.level = level;
1344 core.set_plugin_meta(plugin_id, meta);
1345 Ok(core)
1346}
1347
1348#[allow(clippy::unnecessary_wraps)] fn dispatch_set_resource_level(
1353 mut core: KernelStateCore,
1354 resource_id: ResourceId,
1355 level: SecurityLevel,
1356) -> KernelResult {
1357 let mut meta = core.get_resource_meta(resource_id);
1358 meta.level = level;
1359 core.set_resource_meta(resource_id, meta);
1360 Ok(core)
1361}
1362
1363fn dispatch_tick(mut core: KernelStateCore) -> Result<KernelStateCore, KernelError> {
1371 core.now = core
1372 .now
1373 .checked_add(1)
1374 .ok_or(KernelError::CounterOverflow("time"))?;
1375 Ok(core)
1376}
1377
1378fn dispatch_rotate_key(mut core: KernelStateCore, new_key: Key) -> KernelStateCore {
1388 core.key_state.rotate(new_key);
1389 core
1390}
1391
1392#[cfg(test)]
1393mod tests {
1394 use super::*;
1395 use crate::types::{Right, Rights, SealedTag};
1396
1397 fn make_test_cap(id: CapId, parent: Option<CapId>) -> Capability {
1398 Capability::new(
1399 id,
1400 1, 1, Rights::singleton(Right::Read),
1403 parent,
1404 0, SealedTag::empty(),
1406 )
1407 .expect("valid capability")
1408 }
1409
1410 #[test]
1411 fn test_revocation_state_empty() {
1412 let rs = RevocationState::empty();
1413 assert_eq!(rs.cap_count(), 0);
1414 assert_eq!(rs.epoch(), 0);
1415 assert!(!rs.is_valid(0));
1416 }
1417
1418 #[test]
1419 fn test_revocation_state_insert() {
1420 let mut rs = RevocationState::empty();
1421 let cap = make_test_cap(1, None);
1422 rs.insert_mut(cap).expect("insert should succeed");
1423
1424 assert_eq!(rs.cap_count(), 1);
1425 assert!(rs.contains(1));
1426 assert!(rs.is_valid(1));
1427 }
1428
1429 #[test]
1430 fn test_revocation_state_insert_collision() {
1431 let mut rs = RevocationState::empty();
1432 let cap1 = make_test_cap(1, None);
1433 rs.insert_mut(cap1).expect("first insert should succeed");
1434
1435 let cap2 = make_test_cap(1, None);
1436 let result = rs.insert_mut(cap2);
1437 assert!(matches!(result, Err(KernelError::CapIdCollision(1))));
1438 }
1439
1440 #[test]
1441 fn test_revocation_state_insert_sorted() {
1442 let mut rs = RevocationState::empty();
1443 rs.insert_mut(make_test_cap(5, None)).expect("insert 5");
1445 rs.insert_mut(make_test_cap(2, None)).expect("insert 2");
1446 rs.insert_mut(make_test_cap(8, None)).expect("insert 8");
1447 rs.insert_mut(make_test_cap(1, None)).expect("insert 1");
1448
1449 let ids = rs.cap_ids();
1451 assert_eq!(ids, vec![1, 2, 5, 8]);
1452 }
1453
1454 #[test]
1455 fn test_revocation_state_revoke() {
1456 let mut rs = RevocationState::empty();
1457 let cap = make_test_cap(1, None);
1458 rs.insert_mut(cap).expect("insert should succeed");
1459
1460 assert!(rs.is_valid(1));
1461 rs.revoke_mut(1).expect("revoke should succeed");
1462 assert!(!rs.is_valid(1));
1463 }
1464
1465 #[test]
1466 fn test_revocation_state_has_ancestor() {
1467 let mut rs = RevocationState::empty();
1468
1469 let cap1 = make_test_cap(1, None);
1471 let cap2 = make_test_cap(2, Some(1));
1472 let cap3 = make_test_cap(3, Some(2));
1473
1474 rs.insert_mut(cap1).expect("insert 1");
1475 rs.insert_mut(cap2).expect("insert 2");
1476 rs.insert_mut(cap3).expect("insert 3");
1477
1478 assert!(rs.has_ancestor(2, 1)); assert!(rs.has_ancestor(3, 2)); assert!(rs.has_ancestor(3, 1)); assert!(!rs.has_ancestor(1, 2)); assert!(!rs.has_ancestor(1, 3)); assert!(!rs.has_ancestor(2, 3)); }
1488
1489 #[test]
1490 fn test_revocation_state_revoke_transitive() {
1491 let mut rs = RevocationState::empty();
1492
1493 let cap1 = make_test_cap(1, None);
1495 let cap2 = make_test_cap(2, Some(1));
1496 let cap3 = make_test_cap(3, Some(2));
1497
1498 rs.insert_mut(cap1).expect("insert 1");
1499 rs.insert_mut(cap2).expect("insert 2");
1500 rs.insert_mut(cap3).expect("insert 3");
1501
1502 assert!(rs.is_valid(1));
1504 assert!(rs.is_valid(2));
1505 assert!(rs.is_valid(3));
1506
1507 rs.revoke_transitive_mut(1);
1509
1510 assert!(!rs.is_valid(1));
1511 assert!(!rs.is_valid(2));
1512 assert!(!rs.is_valid(3));
1513 }
1514
1515 #[test]
1516 fn test_revocation_state_revoke_transitive_partial() {
1517 let mut rs = RevocationState::empty();
1518
1519 let cap1 = make_test_cap(1, None);
1521 let cap2 = make_test_cap(2, Some(1));
1522 let cap3 = make_test_cap(3, Some(2));
1523
1524 rs.insert_mut(cap1).expect("insert 1");
1525 rs.insert_mut(cap2).expect("insert 2");
1526 rs.insert_mut(cap3).expect("insert 3");
1527
1528 rs.revoke_transitive_mut(2);
1530
1531 assert!(rs.is_valid(1)); assert!(!rs.is_valid(2)); assert!(!rs.is_valid(3)); }
1535
1536 #[test]
1537 fn test_kernel_state_initial() {
1538 let key = Key::empty();
1539 let policy = PolicyState::deny_all();
1540 let ks = KernelState::initial(key, policy);
1541
1542 assert_eq!(ks.now(), 0);
1543 assert_eq!(ks.revocation().cap_count(), 0);
1544 }
1545
1546 #[test]
1547 fn test_kernel_state_tick() {
1548 let mut ks = KernelState::default();
1549 assert_eq!(ks.now(), 0);
1550
1551 ks.tick_checked().expect("tick should succeed");
1552 assert_eq!(ks.now(), 1);
1553
1554 ks.tick_checked().expect("tick should succeed");
1555 assert_eq!(ks.now(), 2);
1556 }
1557
1558 #[test]
1559 fn test_kernel_state_cap_not_revoked() {
1560 let mut ks = KernelState::default();
1561 let cap = make_test_cap(1, None);
1562
1563 assert!(!ks.cap_not_revoked(&cap));
1565
1566 ks.revocation_mut()
1568 .insert_mut(cap.clone())
1569 .expect("insert should succeed");
1570 assert!(ks.cap_not_revoked(&cap));
1571
1572 ks.revocation_mut()
1574 .revoke_mut(1)
1575 .expect("revoke should succeed");
1576 assert!(!ks.cap_not_revoked(&cap));
1577 }
1578
1579 #[test]
1582 fn test_key_state_initial() {
1583 let key = Key::from_bytes([1u8; 32]);
1584 let ks = KeyState::initial(key.clone());
1585
1586 assert_eq!(ks.epoch(), 0);
1587 assert!(ks.previous().is_none());
1588 assert!(ks.previous_epoch().is_none());
1589 }
1590
1591 #[test]
1592 fn test_key_state_rotation() {
1593 let key1 = Key::from_bytes([1u8; 32]);
1594 let key2 = Key::from_bytes([2u8; 32]);
1595 let mut ks = KeyState::initial(key1.clone());
1596
1597 ks.rotate(key2.clone());
1599
1600 assert_eq!(ks.epoch(), 1);
1601 assert!(ks.previous().is_some());
1602 assert_eq!(ks.previous_epoch(), Some(0));
1603 assert_eq!(ks.current().as_bytes(), key2.as_bytes());
1605 assert_eq!(ks.previous().unwrap().as_bytes(), key1.as_bytes());
1607 }
1608
1609 #[test]
1610 fn test_key_state_epoch_valid() {
1611 let key1 = Key::from_bytes([1u8; 32]);
1612 let key2 = Key::from_bytes([2u8; 32]);
1613 let mut ks = KeyState::initial(key1);
1614
1615 assert!(ks.epoch_valid(0)); assert!(ks.epoch_valid(1)); ks.rotate(key2);
1621 assert!(ks.epoch_valid(1)); assert!(ks.epoch_valid(0)); assert!(ks.epoch_valid(2)); }
1625
1626 #[test]
1627 fn test_key_state_multiple_rotations() {
1628 let key1 = Key::from_bytes([1u8; 32]);
1629 let key2 = Key::from_bytes([2u8; 32]);
1630 let key3 = Key::from_bytes([3u8; 32]);
1631 let mut ks = KeyState::initial(key1.clone());
1632
1633 ks.rotate(key2.clone());
1635 assert_eq!(ks.epoch(), 1);
1636 assert_eq!(ks.previous_epoch(), Some(0));
1637
1638 ks.rotate(key3.clone());
1640 assert_eq!(ks.epoch(), 2);
1641 assert_eq!(ks.previous_epoch(), Some(1)); assert_eq!(ks.previous().unwrap().as_bytes(), key2.as_bytes());
1644 }
1645
1646 #[test]
1647 fn test_key_state_clear_previous() {
1648 let key1 = Key::from_bytes([1u8; 32]);
1649 let key2 = Key::from_bytes([2u8; 32]);
1650 let mut ks = KeyState::initial(key1);
1651
1652 ks.rotate(key2);
1653 assert!(ks.previous().is_some());
1654
1655 ks.clear_previous();
1656 assert!(ks.previous().is_none());
1657 assert!(ks.previous_epoch().is_none());
1658 assert_eq!(ks.epoch(), 1);
1660 }
1661
1662 #[test]
1663 fn test_kernel_state_rotate_key() {
1664 let key1 = Key::from_bytes([1u8; 32]);
1665 let key2 = Key::from_bytes([2u8; 32]);
1666 let mut ks = KernelState::initial(key1.clone(), PolicyState::deny_all());
1667
1668 assert_eq!(ks.key_epoch(), 0);
1669
1670 ks.rotate_key(key2.clone());
1671
1672 assert_eq!(ks.key_epoch(), 1);
1673 assert_eq!(ks.hmac_key().as_bytes(), key2.as_bytes());
1674 }
1675
1676 #[test]
1677 fn test_kernel_dispatch_rotate_key() {
1678 let key1 = Key::from_bytes([1u8; 32]);
1679 let key2 = Key::from_bytes([2u8; 32]);
1680 let core = KernelStateCore::empty(key1);
1681
1682 let result = kernel_dispatch(
1683 core,
1684 KernelRequest::RotateKey {
1685 new_key: key2.clone(),
1686 },
1687 );
1688 assert!(result.is_ok());
1689
1690 let new_core = result.unwrap();
1691 assert_eq!(new_core.key_state().epoch(), 1);
1692 assert_eq!(new_core.hmac_key().as_bytes(), key2.as_bytes());
1693 }
1694
1695 #[test]
1698 fn test_plugin_meta_grant_revoke_holds_empty() {
1699 let mut pm = PluginMeta::empty();
1700 assert!(!pm.holds_cap(0));
1701 assert!(!pm.holds_cap(u128::MAX));
1702
1703 pm.revoke_cap(42); assert!(pm.held_caps.is_empty());
1705 }
1706
1707 #[test]
1708 fn test_plugin_meta_grant_sorted_order() {
1709 let mut pm = PluginMeta::empty();
1710 pm.grant_cap(5);
1711 pm.grant_cap(1);
1712 pm.grant_cap(9);
1713 pm.grant_cap(3);
1714 assert_eq!(pm.held_caps, vec![1, 3, 5, 9]);
1715 }
1716
1717 #[test]
1718 fn test_plugin_meta_grant_dedup() {
1719 let mut pm = PluginMeta::empty();
1720 pm.grant_cap(3);
1721 pm.grant_cap(3);
1722 pm.grant_cap(3);
1723 assert_eq!(pm.held_caps, vec![3]);
1724 }
1725
1726 #[test]
1727 fn test_plugin_meta_revoke_first_middle_last() {
1728 let mut pm = PluginMeta::empty();
1729 pm.grant_cap(1);
1730 pm.grant_cap(5);
1731 pm.grant_cap(9);
1732
1733 pm.revoke_cap(1); assert_eq!(pm.held_caps, vec![5, 9]);
1735
1736 pm.grant_cap(1);
1737 pm.revoke_cap(5); assert_eq!(pm.held_caps, vec![1, 9]);
1739
1740 pm.grant_cap(5);
1741 pm.revoke_cap(9); assert_eq!(pm.held_caps, vec![1, 5]);
1743 }
1744
1745 #[test]
1746 fn test_set_plugin_meta_normalizes_unsorted_held_caps() {
1747 let mut core = KernelStateCore::empty(Key::empty());
1748 let meta = PluginMeta {
1749 level: SecurityLevel::Internal,
1750 held_caps: vec![9, 3, 5, 3, 1, 5], };
1752 core.set_plugin_meta(100, meta);
1753 let stored = core.get_plugin_meta(100);
1754 assert_eq!(stored.held_caps, vec![1, 3, 5, 9]); }
1756
1757 #[test]
1758 fn test_kernel_state_core_plugin_meta_upsert_edge_cases() {
1759 let mut core = KernelStateCore::empty(Key::empty());
1760
1761 core.set_plugin_meta(
1763 50,
1764 PluginMeta {
1765 level: SecurityLevel::Public,
1766 held_caps: vec![],
1767 },
1768 );
1769 assert_eq!(core.plugin_metas.len(), 1);
1770
1771 core.set_plugin_meta(
1773 10,
1774 PluginMeta {
1775 level: SecurityLevel::Internal,
1776 held_caps: vec![],
1777 },
1778 );
1779 assert_eq!(core.plugin_metas[0].0, 10);
1780
1781 core.set_plugin_meta(
1783 90,
1784 PluginMeta {
1785 level: SecurityLevel::Secret,
1786 held_caps: vec![],
1787 },
1788 );
1789 assert_eq!(core.plugin_metas[2].0, 90);
1790
1791 core.set_plugin_meta(
1793 30,
1794 PluginMeta {
1795 level: SecurityLevel::Confidential,
1796 held_caps: vec![],
1797 },
1798 );
1799 let ids: Vec<u128> = core.plugin_metas.iter().map(|(id, _)| *id).collect();
1800 assert_eq!(ids, vec![10, 30, 50, 90]);
1801
1802 core.set_plugin_meta(
1804 50,
1805 PluginMeta {
1806 level: SecurityLevel::Secret,
1807 held_caps: vec![1],
1808 },
1809 );
1810 assert_eq!(core.get_plugin_meta(50).level, SecurityLevel::Secret);
1811 assert_eq!(core.plugin_metas.len(), 4); }
1813
1814 #[test]
1815 fn test_kernel_state_core_resource_meta_upsert_edge_cases() {
1816 let mut core = KernelStateCore::empty(Key::empty());
1817
1818 core.set_resource_meta(
1820 5,
1821 ResourceMeta {
1822 level: SecurityLevel::Public,
1823 },
1824 );
1825 assert_eq!(core.resource_metas.len(), 1);
1826
1827 core.set_resource_meta(
1829 1,
1830 ResourceMeta {
1831 level: SecurityLevel::Internal,
1832 },
1833 );
1834 assert_eq!(core.resource_metas[0].0, 1);
1835
1836 core.set_resource_meta(
1838 5,
1839 ResourceMeta {
1840 level: SecurityLevel::Secret,
1841 },
1842 );
1843 assert_eq!(core.get_resource_meta(5).level, SecurityLevel::Secret);
1844 assert_eq!(core.resource_metas.len(), 2);
1845 }
1846
1847 #[test]
1848 fn test_revocation_state_single_element() {
1849 let mut rs = RevocationState::empty();
1850 rs.insert_mut(make_test_cap(42, None)).unwrap();
1851
1852 assert!(rs.is_valid(42));
1853 assert!(!rs.is_valid(41));
1854 assert!(!rs.is_valid(43));
1855 assert_eq!(rs.cap_count(), 1);
1856 }
1857
1858 #[test]
1859 fn test_revocation_state_insert_at_boundaries() {
1860 let mut rs = RevocationState::empty();
1861 rs.insert_mut(make_test_cap(100, None)).unwrap();
1863 rs.insert_mut(make_test_cap(1, None)).unwrap();
1864 rs.insert_mut(make_test_cap(50, None)).unwrap();
1865
1866 let ids = rs.cap_ids();
1867 assert_eq!(ids, vec![1, 50, 100]);
1868 }
1869}