twizzler_security/keys/
sign.rs1#[cfg(feature = "log")]
2use log::{debug, error};
3#[cfg(feature = "user")]
4use {
5 twizzler::{
6 marker::BaseType,
7 object::{Object, ObjectBuilder},
8 },
9 twizzler_abi::syscall::ObjectCreate,
10};
11
12const ECDSA_SECRET_KEY_LENGTH: usize = 32;
14
15use p256::ecdsa::{signature::Signer, Signature as EcdsaSignature, SigningKey as EcdsaSigningKey};
16use twizzler_rt_abi::error::TwzError;
17
18#[cfg(feature = "kernel")]
19use super::MAX_KEY_SIZE;
20use super::{KeyBuffer, Signature, VerifyingKey};
21use crate::{SecurityError, SigningScheme};
22
23#[derive(Clone, Debug, PartialEq, Eq)]
28pub struct SigningKey {
29 key: KeyBuffer,
31 pub scheme: SigningScheme,
33}
34
35impl SigningKey {
36 #[cfg(feature = "user")]
37 pub fn new_keypair(
39 scheme: &SigningScheme,
40 obj_create_spec: ObjectCreate,
41 ) -> Result<(Object<Self>, Object<VerifyingKey>), TwzError> {
42 use alloc::borrow::ToOwned;
43
44 #[cfg(feature = "user")]
45 use getrandom::getrandom;
46
47 #[cfg(feature = "log")]
48 debug!("Creating new signing key with scheme: {:?}", scheme);
49
50 let (signing_key, verifying_key): (SigningKey, VerifyingKey) = match scheme {
52 SigningScheme::Ecdsa => {
53 let mut rand_buf = [0_u8; ECDSA_SECRET_KEY_LENGTH];
54
55 if let Err(_e) = getrandom(&mut rand_buf) {
56 #[cfg(feature = "log")]
57 error!(
58 "Failed to initialize buffer with random bytes, terminating
59 key creation. Underlying error: {}",
60 _e
61 );
62
63 return Err(TwzError::Generic(
64 twizzler_rt_abi::error::GenericError::Internal,
65 ));
66 }
67
68 let Ok(ecdsa_signing_key) = EcdsaSigningKey::from_slice(&rand_buf) else {
69 #[cfg(feature = "log")]
70 error!("Failed to create ecdsa signing key from bytes");
71
72 return Err(TwzError::Generic(
73 twizzler_rt_abi::error::GenericError::Internal,
74 ));
75 };
76
77 let binding = ecdsa_signing_key.clone();
78
79 let ecdsa_verifying_key = binding.verifying_key().to_owned();
80
81 (ecdsa_signing_key.into(), ecdsa_verifying_key.into())
82 }
83 };
84
85 let s_object = ObjectBuilder::new(obj_create_spec.clone()).build(signing_key)?;
86 let v_object = ObjectBuilder::new(obj_create_spec).build(verifying_key)?;
87
88 return Ok((s_object, v_object));
89 }
90
91 #[cfg(feature = "kernel")]
92 pub fn new_kernel_keypair(
94 scheme: &SigningScheme,
95 random_bytes: [u8; MAX_KEY_SIZE],
96 ) -> Result<(SigningKey, VerifyingKey), TwzError> {
97 match scheme {
98 SigningScheme::Ecdsa => {
99 let Ok(ecdsa_signing_key) =
100 EcdsaSigningKey::from_slice(&random_bytes[0..ECDSA_SECRET_KEY_LENGTH])
101 else {
102 #[cfg(feature = "log")]
103 error!("Failed to create ecdsa signing key from bytes");
104
105 return Err(TwzError::Generic(
106 twizzler_rt_abi::error::GenericError::Internal,
107 ));
108 };
109
110 let binding = ecdsa_signing_key.clone();
111
112 let ecdsa_verifying_key = binding.verifying_key().clone();
113
114 Ok((ecdsa_signing_key.into(), ecdsa_verifying_key.into()))
115 }
116 }
117 }
118
119 pub fn from_slice(slice: &[u8], scheme: SigningScheme) -> Result<Self, SecurityError> {
121 match scheme {
122 SigningScheme::Ecdsa => {
123 let key = EcdsaSigningKey::from_slice(slice).map_err(|_e| {
127 #[cfg(feature = "log")]
128 error!(
129 "Unable to create EcdsaSigningKey from slice due to: {:#?}!",
130 _e
131 );
132 SecurityError::InvalidKey
133 })?;
134
135 let binding = key.to_bytes();
136
137 let key = KeyBuffer::from_slice(&binding)
138 .expect("The ECDSA key cannot fit in the currently configured MAX_KEY_SIZE");
139
140 Ok(Self {
141 key,
142 scheme: SigningScheme::Ecdsa,
143 })
144 }
145 }
146 }
147
148 pub fn as_bytes(&self) -> &[u8] {
150 self.key.as_slice()
151 }
152
153 pub fn sign(&self, msg: &[u8]) -> Result<Signature, SecurityError> {
155 match self.scheme {
156 SigningScheme::Ecdsa => {
157 let signing_key: EcdsaSigningKey = self.try_into()?;
158 let sig: EcdsaSignature = signing_key.sign(msg);
159 Ok(sig.into())
160 }
161 }
162 }
163}
164
165impl TryFrom<&SigningKey> for EcdsaSigningKey {
166 type Error = SecurityError;
167 fn try_from(value: &SigningKey) -> Result<Self, Self::Error> {
168 if value.scheme != SigningScheme::Ecdsa {
169 #[cfg(feature = "log")]
170 error!("Cannot convert SigningKey to EcdsaSigningKey due to scheme mismatch. SigningKey scheme: {:?}", value.scheme);
171 return Err(SecurityError::InvalidScheme);
172 }
173
174 Ok(EcdsaSigningKey::from_slice(value.as_bytes()).map_err(|_e| {
175 #[cfg(feature = "log")]
176 error!("Cannot build EcdsaSigningKey from slice due to: {:?}", _e);
177 SecurityError::InvalidKey
178 })?)
179 }
180}
181
182impl From<EcdsaSigningKey> for SigningKey {
183 fn from(value: EcdsaSigningKey) -> Self {
184 let binding = value.to_bytes();
185
186 let key = KeyBuffer::from_slice(binding.as_slice())
187 .expect("The ECDSA key cannot fit in the currently configured MAX_KEY_SIZE");
188
189 SigningKey {
190 key,
191 scheme: SigningScheme::Ecdsa,
192 }
193 }
194}
195
196#[cfg(feature = "user")]
197#[allow(unused_imports)]
198mod tests {
199
200 use twizzler_abi::{object::Protections, syscall::ObjectCreate};
201
202 extern crate test;
203
204 use test::Bencher;
205
206 use super::SigningKey;
207 use crate::SigningScheme;
208
209 #[test]
210 fn test_key_creation() {
211 let object_create_spec = ObjectCreate::new(
212 Default::default(),
213 Default::default(),
214 Default::default(),
215 Default::default(),
216 Protections::all(),
217 );
218 let (_skey, _vkey) = SigningKey::new_keypair(&SigningScheme::Ecdsa, object_create_spec)
219 .expect("keys should be generated properly");
220 }
221
222 #[test]
223 fn test_signing_and_verification() {
224 use twizzler::object::TypedObject;
225 let object_create_spec = ObjectCreate::new(
226 Default::default(),
227 Default::default(),
228 Default::default(),
229 Default::default(),
230 Protections::all(),
231 );
232
233 let (s_obj, v_obj) = SigningKey::new_keypair(&SigningScheme::Ecdsa, object_create_spec)
234 .expect("Keys should be generated properly");
235 let message = "deadbeef".as_bytes();
236
237 let sig = s_obj
238 .base()
239 .sign(message)
240 .expect("Signature should succeed");
241
242 v_obj
243 .base()
244 .verify(message, &sig)
245 .expect("Should be verified properly");
246 }
247
248 #[bench]
249 fn bench_keypair_creation(b: &mut Bencher) {
252 let object_create_spec = ObjectCreate::new(
253 Default::default(),
254 Default::default(),
255 Default::default(),
256 Default::default(),
257 Protections::all(),
258 );
259 b.iter(|| {
260 let (_skey, _vkey) =
261 SigningKey::new_keypair(&SigningScheme::Ecdsa, object_create_spec.clone())
262 .expect("Keys should be generated properly.");
263 });
264 }
265}
266
267#[cfg(feature = "user")]
268use twizzler::object::{MapFlags, ObjID, TypedObject};
269#[cfg(feature = "user")]
270impl TryFrom<ObjID> for SigningKey {
271 type Error = TwzError;
272 fn try_from(value: ObjID) -> Result<Self, Self::Error> {
273 let obj = Object::<SigningKey>::map(value, MapFlags::READ)?;
274 Ok(obj.base().clone())
275 }
276}
277
278#[cfg(feature = "user")]
279impl BaseType for SigningKey {
280 fn fingerprint() -> u64 {
281 return 6;
282 }
283}