twizzler_security/
builder_ext.rs

1use twizzler::{
2    error::TwzError,
3    marker::{BaseType, StoreCopy},
4    object::{Object, ObjectBuilder, RawObject},
5};
6use twizzler_abi::object::Protections;
7
8use super::SecCtx;
9use crate::{Cap, SigningKey};
10
11/// An extension trait for the ObjectBuilder from the
12/// `twizzler` crate that allows for the creation of objects
13/// that have restrained default permissions.
14///
15///
16/// We get around
17/// the write requirement by creating a capability before
18/// we write the base of the object.
19pub trait SecureBuilderExt<Base: BaseType + StoreCopy> {
20    /// Builds a "secure" object, one without `Protections::READ|Protections::Write` as its
21    /// `default_prots`.
22    ///
23    /// It achieves this by creating a capability for the object within the current security
24    /// context, and then writing to the object after that capability has been created.
25    fn build_secure(&self, base: Base, s_key: &SigningKey) -> Result<Object<Base>, TwzError>;
26}
27
28impl<Base> SecureBuilderExt<Base> for ObjectBuilder<Base>
29where
30    Base: BaseType + StoreCopy,
31{
32    fn build_secure(&self, base: Base, s_key: &SigningKey) -> Result<Object<Base>, TwzError> {
33        self.build_inplace(|tx| {
34            let mut curr_sec_ctx = SecCtx::active_ctx();
35            let cap = Cap::new(
36                tx.id(),
37                curr_sec_ctx.id(),
38                Protections::READ | Protections::WRITE,
39                s_key,
40                Default::default(),
41                Default::default(),
42                Default::default(),
43            )?;
44
45            curr_sec_ctx.insert_cap(cap)?;
46
47            // now we have permissions to write here!
48            tx.write(base)
49        })
50    }
51}
52
53#[cfg(feature = "user")]
54#[cfg(test)]
55mod tests {
56    use twizzler::{
57        marker::BaseType,
58        object::{ObjectBuilder, RawObject, TypedObject},
59    };
60    use twizzler_abi::{object::Protections, syscall::ObjectCreate};
61
62    use crate::{SigningKey, SigningScheme};
63
64    #[derive(Debug, Clone)]
65    struct MessageStoreObj {
66        message: heapless::String<256>,
67    }
68
69    impl BaseType for MessageStoreObj {
70        fn fingerprint() -> u64 {
71            11234
72        }
73    }
74    #[test]
75    fn build_sealed_object() {
76        use super::SecureBuilderExt as _;
77
78        let (s_key, v_key) = SigningKey::new_keypair(&SigningScheme::Ecdsa, Default::default())
79            .expect("should have worked");
80
81        let spec = ObjectCreate::new(
82            Default::default(),
83            Default::default(),
84            Some(v_key.id()),
85            Default::default(),
86            Protections::empty(),
87        );
88
89        let base = MessageStoreObj {
90            // message: args.message,
91            message: heapless::String::<256>::try_from("Hello")
92                .expect("message was longer than 256 characters!!"),
93        };
94
95        let obj = ObjectBuilder::new(spec)
96            .build_secure(base, s_key.base())
97            .expect("should have built successfully");
98
99        // our current thing should be able to read this just fine
100        let base_ptr = obj.base_ptr::<MessageStoreObj>();
101
102        unsafe { assert!((*base_ptr).message == "Hello") }
103    }
104}