sec/
main.rs

1#![warn(missing_debug_implementations, missing_docs)]
2//! This crate is a work in progress but aims to be a cli tool to interact with twizzler security
3//! primitives
4
5use clap::Parser;
6use colog::default_builder;
7use log::LevelFilter;
8use twizzler::{
9    marker::BaseType,
10    object::{Object, ObjectBuilder, RawObject, TypedObject},
11};
12use twizzler_abi::{
13    object::Protections,
14    syscall::{ObjectCreate, sys_sctx_attach, sys_thread_set_active_sctx_id},
15};
16use twizzler_rt_abi::object::MapFlags;
17use twizzler_security::{
18    Cap, SecCtx, SecCtxFlags, SecureBuilderExt as _, SigningKey, SigningScheme,
19};
20
21mod args;
22use args::*;
23
24fn main() {
25    let mut builder = default_builder();
26    builder.filter_level(LevelFilter::Trace);
27    builder.init();
28
29    let args = CliArgs::parse();
30
31    match args.command {
32        Commands::Obj(commands) => match commands {
33            ObjCommands::Inspect(args) => {
34                if let Some(sec_ctx_id) = args.sec_ctx_id {
35                    let sec_ctx = SecCtx::try_from(sec_ctx_id).unwrap();
36                    sec_ctx
37                        .set_active()
38                        .expect("Failed to set sec_ctx to active");
39                    println!("activated SecCtx: {sec_ctx_id:#?}");
40                }
41
42                let target =
43                    Object::<MessageStoreObj>::map(args.obj_id, MapFlags::READ | MapFlags::WRITE)
44                        .unwrap();
45
46                let base = target.base();
47
48                let meta = target.meta_ptr();
49
50                unsafe {
51                    println!("{target:#?}\n{:#?}\n{base:#?}", *meta);
52                }
53            }
54
55            ObjCommands::Sealed(args) => {
56                // by default an object has empty permissions
57                let spec = ObjectCreate::new(
58                    Default::default(),
59                    Default::default(),
60                    Some(args.verifying_key_id),
61                    Default::default(),
62                    Protections::empty(),
63                );
64
65                println!("creating target object with spec: {:#?}", spec);
66
67                let builder = ObjectBuilder::new(spec);
68                let base = MessageStoreObj {
69                    _message: heapless::String::<256>::try_from(args.message.as_str())
70                        .expect("message was longer than 256 characters!!"),
71                };
72
73                let obj = {
74                    let s_key = Object::<SigningKey>::map(args.signing_key_id, MapFlags::READ)
75                        .expect("failed to map signing key object");
76                    builder
77                        // .build_secure(base, s_key.base(), args.sec_ctx_id)
78                        .build_secure(base, s_key.base())
79                        .expect("secure build should succeed")
80                };
81
82                unsafe {
83                    println!(
84                        "created Object with id: {:#?}\n{:#?}",
85                        obj.id(),
86                        // maybe have a method that gives an immutable copy of the metadata?
87                        *obj.base_ptr::<MessageStoreObj>()
88                    );
89                }
90            }
91            ObjCommands::New(args) => {
92                // by default an object has empty permissions
93                let spec = ObjectCreate::new(
94                    Default::default(),
95                    Default::default(),
96                    Some(args.verifying_key_id),
97                    Default::default(),
98                    Protections::READ | Protections::WRITE,
99                );
100
101                println!("creating target object with spec: {:#?}", spec);
102
103                let base = MessageStoreObj {
104                    _message: heapless::String::<256>::try_from(args.message.as_str())
105                        .expect("message was longer than 256 characters!!"),
106                };
107
108                let obj = ObjectBuilder::new(spec)
109                    .build(base)
110                    .expect("build should succeed");
111
112                unsafe {
113                    println!(
114                        "created Object with id: {:#?}\n{:#?}",
115                        obj.id(),
116                        // maybe have a method that gives an immutable copy of the metadata?
117                        *obj.meta_ptr()
118                    );
119                }
120            }
121        },
122        Commands::Key(KeyCommands::NewPair) => {
123            let (s_key, v_key) = SigningKey::new_keypair(&SigningScheme::Ecdsa, Default::default())
124                .expect("should have worked");
125
126            println!(
127                "Keypair created!\nSigning Key: {:#?}\nVerifying Key: {:#?}",
128                s_key.id(),
129                v_key.id()
130            );
131        }
132        Commands::Ctx(ctxcommands) => match ctxcommands {
133            CtxCommands::Add(addcommad) => match addcommad {
134                CtxAddCommands::Cap(args) => {
135                    if let Some(sec_ctx_id) = args.executing_ctx {
136                        let sec_ctx = SecCtx::try_from(sec_ctx_id).unwrap();
137                        sys_sctx_attach(sec_ctx.id()).unwrap();
138                        sys_thread_set_active_sctx_id(sec_ctx.id()).unwrap();
139                        println!("attached to SecCtx: {sec_ctx_id:#?}");
140                    }
141                    // map in signing key
142                    let s_key = Object::<SigningKey>::map(args.signing_key_id, MapFlags::READ)
143                        .expect("failed to map signing key object");
144
145                    let mut modifying_sec_ctx = SecCtx::try_from(args.modifying_ctx)
146                        .expect("failed to map modifying SecCtx");
147
148                    // create a new capability
149                    let cap = Cap::new(
150                        args.target_obj,
151                        args.modifying_ctx,
152                        Protections::all(),
153                        s_key.base(),
154                        Default::default(),
155                        Default::default(),
156                        Default::default(),
157                    )
158                    .unwrap();
159
160                    modifying_sec_ctx
161                        .insert_cap(cap.clone())
162                        .expect("Failed to insert capability!");
163
164                    println!("Inserted\n{cap:?}\ninto {:?}", modifying_sec_ctx.base());
165                }
166            },
167            CtxCommands::New(args) => {
168                let flags = if args.undetachable {
169                    SecCtxFlags::UNDETACHABLE
170                } else {
171                    SecCtxFlags::empty()
172                };
173
174                let sec_ctx = SecCtx::new(
175                    ObjectCreate::new(
176                        Default::default(),
177                        Default::default(),
178                        None,
179                        Default::default(),
180                        Protections::all(),
181                    ),
182                    Protections::all(),
183                    flags,
184                )
185                .unwrap();
186
187                let id = sec_ctx.id();
188
189                let base = sec_ctx.base();
190
191                println!("Created SecCtx: {id:#?}\n{base:#?}");
192            }
193
194            CtxCommands::Inspect(args) => {
195                let sec_ctx =
196                    SecCtx::try_from(args.sec_ctx_id).expect("unable to parse as valid sec_ctx");
197
198                println!("{:#?}", sec_ctx);
199            }
200        },
201    }
202}
203
204#[derive(Debug, Clone)]
205struct MessageStoreObj {
206    _message: heapless::String<256>,
207}
208
209impl BaseType for MessageStoreObj {
210    fn fingerprint() -> u64 {
211        11234
212    }
213}