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