1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #![no_std]
18 #![feature(allocator_api)]
19 
20 mod err;
21 
22 #[cfg(test)]
23 mod test;
24 
25 #[allow(non_upper_case_globals)]
26 #[allow(non_camel_case_types)]
27 #[allow(unused)]
28 #[allow(deref_nullptr)] // https://github.com/rust-lang/rust-bindgen/issues/1651
29 mod sys {
30     include!(env!("BINDGEN_INC_FILE"));
31 }
32 
33 pub use err::HwWskError;
34 pub use sys::HWWSK_MAX_MSG_SIZE;
35 
36 use core::mem;
37 use sys::*;
38 use tipc::{Deserialize, Handle, Serialize, Serializer};
39 use trusty_std::alloc::{TryAllocFrom, Vec};
40 
41 /// The command sent to the hwwsk service.
42 pub enum HwWskCmd {
43     /// Generate (or import) a persistent storage key.
44     ///
45     /// Result is wrapped using a device-unique key.
46     Generate(GenerateKeyReq),
47     /// Re-wrap a non-ephemeral wrapped key with ephemeral storage key.
48     ///
49     /// Result is a key that is only good for the current session.
50     Export(ExportKeyReq),
51 }
52 
53 /// A request to the hwwsk service.
54 pub struct HwWskReq {
55     hdr: hwwsk_req_hdr,
56     /// The command that is requested.
57     pub req: HwWskCmd,
58 }
59 
60 impl HwWskReq {
response_from(&self, status: u32, payload: Vec<u8>) -> HwWskResponse61     pub fn response_from(&self, status: u32, payload: Vec<u8>) -> HwWskResponse {
62         HwWskResponse { status, cmd: self.hdr.cmd | hwwsk_cmd_HWWSK_CMD_RESP as u32, payload }
63     }
64 }
65 
66 impl<'s> Serialize<'s> for HwWskReq {
serialize<'a: 's, S: Serializer<'s>>( &'a self, serializer: &mut S, ) -> Result<S::Ok, S::Error>67     fn serialize<'a: 's, S: Serializer<'s>>(
68         &'a self,
69         serializer: &mut S,
70     ) -> Result<S::Ok, S::Error> {
71         self.hdr.cmd.serialize(serializer)?;
72         self.hdr.flags.serialize(serializer)?;
73 
74         match &self.req {
75             HwWskCmd::Generate(g) => g.serialize(serializer),
76             HwWskCmd::Export(e) => e.serialize(serializer),
77         }
78     }
79 }
80 
81 impl Deserialize for HwWskReq {
82     type Error = HwWskError;
83     const MAX_SERIALIZED_SIZE: usize = HWWSK_MAX_MSG_SIZE as usize;
84 
deserialize(bytes: &[u8], handles: &mut [Option<Handle>]) -> Result<Self, Self::Error>85     fn deserialize(bytes: &[u8], handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> {
86         let header_size = mem::size_of::<hwwsk_req_hdr>();
87         if bytes.len() < header_size {
88             log::error!("response too small");
89             return Err(HwWskError::BadLen);
90         }
91         // SAFETY: We have validated that the buffer contains enough data to
92         // represent a hwwsk_req_hdr. The constructed lifetime here does not
93         // outlive the function and thus cannot outlive the lifetime of the
94         // buffer.
95         let hdr = unsafe { &*(bytes.as_ptr() as *const hwwsk_req_hdr) };
96 
97         let req = {
98             #[allow(non_upper_case_globals)]
99             match hdr.cmd as hwwsk_cmd {
100                 hwwsk_cmd_HWWSK_CMD_GENERATE_KEY => Ok(HwWskCmd::Generate(
101                     GenerateKeyReq::deserialize(&bytes[header_size..], handles)?,
102                 )),
103                 hwwsk_cmd_HWWSK_CMD_EXPORT_KEY => {
104                     Ok(HwWskCmd::Export(ExportKeyReq::deserialize(&bytes[header_size..], handles)?))
105                 }
106                 cmd => {
107                     log::error!("unrecognized command request: {:?}", cmd);
108                     Err(HwWskError::NotValid)
109                 }
110             }
111         }?;
112         Ok(Self { hdr: hwwsk_req_hdr { cmd: hdr.cmd, flags: hdr.flags }, req })
113     }
114 }
115 
116 /// Request to generate a persistent storage key. If the supplied key is empty,
117 /// a new key will be generated. Otherwise, the provided data will be
118 /// imported as a raw key.
119 pub struct GenerateKeyReq {
120     req: hwwsk_generate_key_req,
121     raw_key: Vec<u8>,
122 }
123 
124 impl<'s> Serialize<'s> for GenerateKeyReq {
serialize<'a: 's, S: Serializer<'s>>( &'a self, serializer: &mut S, ) -> Result<S::Ok, S::Error>125     fn serialize<'a: 's, S: Serializer<'s>>(
126         &'a self,
127         serializer: &mut S,
128     ) -> Result<S::Ok, S::Error> {
129         // SAFETY:
130         //  All serialized attributes are trivial types with
131         //  corresponding C representations
132         unsafe {
133             serializer.serialize_as_bytes(&self.req.key_size)?;
134             serializer.serialize_as_bytes(&self.req.key_flags)?;
135         }
136 
137         serializer.serialize_bytes(&self.raw_key)
138     }
139 }
140 
141 impl Deserialize for GenerateKeyReq {
142     type Error = HwWskError;
143     const MAX_SERIALIZED_SIZE: usize = HWWSK_MAX_MSG_SIZE as usize;
144 
deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error>145     fn deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> {
146         let header_size = mem::size_of::<hwwsk_generate_key_req>();
147         if bytes.len() < header_size {
148             log::error!("response too small");
149             return Err(HwWskError::BadLen);
150         }
151         // SAFETY: We have validated that the buffer contains enough data to
152         // represent a hwwsk_generate_key_req. The constructed lifetime here does not
153         // outlive the function and thus cannot outlive the lifetime of the
154         // buffer.
155         let hwwsk_generate_key_req { key_size, key_flags } =
156             unsafe { &*(bytes.as_ptr() as *const hwwsk_generate_key_req) };
157 
158         Ok(Self {
159             req: hwwsk_generate_key_req { key_size: *key_size, key_flags: *key_flags },
160             raw_key: Vec::try_alloc_from(&bytes[header_size..])?,
161         })
162     }
163 }
164 
165 /// A request to re-wrap a non-ephemeral key using an ephemeral storage key.
166 /// The resulting key is only good for the current session.
167 pub struct ExportKeyReq {
168     key_blob: Vec<u8>,
169 }
170 
171 impl<'s> Serialize<'s> for ExportKeyReq {
serialize<'a: 's, S: Serializer<'s>>( &'a self, serializer: &mut S, ) -> Result<S::Ok, S::Error>172     fn serialize<'a: 's, S: Serializer<'s>>(
173         &'a self,
174         serializer: &mut S,
175     ) -> Result<S::Ok, S::Error> {
176         serializer.serialize_bytes(&self.key_blob)
177     }
178 }
179 
180 impl Deserialize for ExportKeyReq {
181     type Error = HwWskError;
182     const MAX_SERIALIZED_SIZE: usize = HWWSK_MAX_MSG_SIZE as usize;
183 
deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error>184     fn deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> {
185         Ok(Self { key_blob: Vec::try_alloc_from(bytes)? })
186     }
187 }
188 
189 /// Response from hwwsk service.
190 pub struct HwWskResponse {
191     /// Sent command, acknowledged by service if successful.
192     cmd: u32,
193     /// Status of command result.
194     status: u32,
195     /// Response data.
196     payload: Vec<u8>,
197 }
198 
199 impl<'s> Serialize<'s> for HwWskResponse {
serialize<'a: 's, S: Serializer<'s>>( &'a self, serializer: &mut S, ) -> Result<S::Ok, S::Error>200     fn serialize<'a: 's, S: Serializer<'s>>(
201         &'a self,
202         serializer: &mut S,
203     ) -> Result<S::Ok, S::Error> {
204         // SAFETY:
205         //  All serialized attributes are trivial types with
206         //  corresponding C representations
207         unsafe {
208             serializer.serialize_as_bytes(&self.cmd)?;
209             serializer.serialize_as_bytes(&self.status)?;
210         }
211 
212         serializer.serialize_bytes(&self.payload)
213     }
214 }
215 
216 impl Deserialize for HwWskResponse {
217     type Error = HwWskError;
218     const MAX_SERIALIZED_SIZE: usize = HWWSK_MAX_MSG_SIZE as usize;
219 
deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error>220     fn deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> {
221         // response must at least contain cmd and status
222         let header_size = mem::size_of::<u32>() * 2;
223         if bytes.len() < header_size {
224             log::error!("response too small");
225             return Err(HwWskError::BadLen);
226         }
227         let (cmd_bytes, rest) = bytes.split_at(mem::size_of::<u32>());
228         let (status_bytes, payload_bytes) = rest.split_at(mem::size_of::<u32>());
229 
230         let status = u32::from_ne_bytes(status_bytes.try_into()?);
231         let cmd = u32::from_ne_bytes(cmd_bytes.try_into()?);
232 
233         let response_payload = Vec::try_alloc_from(payload_bytes)?;
234         Ok(Self { status, cmd, payload: response_payload })
235     }
236 }
237 
238 // TODO: consider trusty util for this across client implementations
validate_cmd(sent_cmd: &u32, recvd_cmd: &u32) -> Result<(), HwWskError>239 fn validate_cmd(sent_cmd: &u32, recvd_cmd: &u32) -> Result<(), HwWskError> {
240     let validated = *recvd_cmd == (sent_cmd | hwwsk_cmd_HWWSK_CMD_RESP as u32);
241     if !validated {
242         log::error!(
243             "unknown response cmd: {:?}/{:?}",
244             recvd_cmd,
245             (sent_cmd | hwwsk_cmd_HWWSK_CMD_RESP as u32)
246         );
247         return Err(HwWskError::InvalidCmdResponse);
248     }
249 
250     Ok(())
251 }
252 
253 /// A combination of flags can be passed to [`generate_key`].
254 pub struct KeyFlags {
255     flags: u32,
256 }
257 
258 impl KeyFlags {
new() -> Self259     pub fn new() -> Self {
260         Self { flags: 0 }
261     }
262 
263     /// Indicates that the resulting key must be rollback resistant.
rollback_resistance(mut self) -> Self264     pub fn rollback_resistance(mut self) -> Self {
265         self.flags |= hwwsk_key_flags_HWWSK_FLAGS_ROLLBACK_RESISTANCE as u32;
266         self
267     }
268 }
269 
270 /// Creates a new persistent key from provided raw key material.
271 ///
272 /// This routine creates a new hardware wrapped storage key by
273 /// either importing raw key material that's specified by the caller.
274 /// The resulting key is persistent and reusable across device reset.
275 ///
276 /// # Arguments
277 ///
278 /// * `session` - IPC channel to HWWSK service
279 /// * `buf` - buffer to store resulting key blob
280 /// * `key_size` - key size in bits
281 /// * `key_flags` - a combination of [`KeyFlags`] to specify any additional
282 ///     properties of the generated key
283 /// * `raw_key` - the buffer containing raw key data for import operation
284 ///
285 /// # Returns
286 ///
287 /// A truncated view into `buf` where the wrapped key data was populated.
288 ///
import_key<'a>( session: &Handle, buf: &'a mut [u8], key_size: usize, key_flags: KeyFlags, raw_key: &[u8], ) -> Result<&'a [u8], HwWskError>289 pub fn import_key<'a>(
290     session: &Handle,
291     buf: &'a mut [u8],
292     key_size: usize,
293     key_flags: KeyFlags,
294     raw_key: &[u8],
295 ) -> Result<&'a [u8], HwWskError> {
296     if raw_key.is_empty() {
297         return Err(HwWskError::BadLen);
298     }
299     create_key(session, buf, key_size, key_flags, raw_key)
300 }
301 
302 /// Creates a new persistent key.
303 ///
304 /// This routine creates a new hardware wrapped storage key by
305 /// generating a new random key The resulting key is persistent and
306 /// reusable across device reset.
307 ///
308 /// # Arguments
309 ///
310 /// * `session` - IPC channel to HWWSK service
311 /// * `buf` - buffer to store resulting key blob
312 /// * `key_size` - key size in bits
313 /// * `key_flags` - a combination of [`KeyFlags`] to specify any additional
314 ///     properties of the generated key
315 ///
316 /// # Returns
317 ///
318 /// A truncated view into `buf` where the wrapped key data was populated.
319 ///
generate_key<'a>( session: &Handle, buf: &'a mut [u8], key_size: usize, key_flags: KeyFlags, ) -> Result<&'a [u8], HwWskError>320 pub fn generate_key<'a>(
321     session: &Handle,
322     buf: &'a mut [u8],
323     key_size: usize,
324     key_flags: KeyFlags,
325 ) -> Result<&'a [u8], HwWskError> {
326     create_key(session, buf, key_size, key_flags, &[])
327 }
328 
create_key<'a>( session: &Handle, buf: &'a mut [u8], key_size: usize, key_flags: KeyFlags, raw_key: &[u8], ) -> Result<&'a [u8], HwWskError>329 fn create_key<'a>(
330     session: &Handle,
331     buf: &'a mut [u8],
332     key_size: usize,
333     key_flags: KeyFlags,
334     raw_key: &[u8],
335 ) -> Result<&'a [u8], HwWskError> {
336     let cmd = hwwsk_cmd_HWWSK_CMD_GENERATE_KEY as u32;
337     let req = HwWskReq {
338         hdr: hwwsk_req_hdr { cmd, flags: 0 },
339         req: HwWskCmd::Generate(GenerateKeyReq {
340             req: hwwsk_generate_key_req { key_size: key_size as u32, key_flags: key_flags.flags },
341             raw_key: Vec::try_alloc_from(raw_key)?,
342         }),
343     };
344 
345     session.send(&req)?;
346 
347     let resp_buf = &mut [0; HWWSK_MAX_MSG_SIZE as usize];
348     let response: HwWskResponse = session.recv(resp_buf)?;
349 
350     validate_cmd(&cmd, &response.cmd)?;
351     HwWskError::from_status(response.status)?;
352 
353     if buf.len() < response.payload.len() {
354         log::error!("response payload is too large to fit into the buffer");
355         return Err(HwWskError::BadLen);
356     }
357 
358     let res_buffer = &mut buf[..response.payload.len()];
359     res_buffer.copy_from_slice(&response.payload);
360 
361     Ok(res_buffer)
362 }
363 
364 /// Rewrap specified SK key with ESK.
365 ///
366 /// This routine rewraps a specified persistent SK key with an ephemeral
367 /// storage key (ESK). The resulting key is only good for the current
368 /// session.
369 ///
370 /// # Arguments
371 ///
372 /// * `session` - IPC channel to HWWSK service
373 /// * `buf` - buffer to store the resulting key blob
374 /// * `key_blob` - the key blob to unwrap
375 ///
376 /// # Returns
377 ///
378 /// A truncated view into `buf` where the rewrrapped key data was populated.
379 ///
export_key<'a>( session: &Handle, buf: &'a mut [u8], key_blob: &[u8], ) -> Result<&'a [u8], HwWskError>380 pub fn export_key<'a>(
381     session: &Handle,
382     buf: &'a mut [u8],
383     key_blob: &[u8],
384 ) -> Result<&'a [u8], HwWskError> {
385     let cmd = hwwsk_cmd_HWWSK_CMD_EXPORT_KEY as u32;
386     let req = HwWskReq {
387         hdr: hwwsk_req_hdr { cmd, flags: 0 },
388         req: HwWskCmd::Export(ExportKeyReq { key_blob: Vec::try_alloc_from(key_blob)? }),
389     };
390 
391     session.send(&req)?;
392 
393     let resp_buf = &mut [0; HWWSK_MAX_MSG_SIZE as usize];
394     let response: HwWskResponse = session.recv(resp_buf)?;
395 
396     validate_cmd(&cmd, &response.cmd)?;
397     HwWskError::from_status(response.status)?;
398 
399     if buf.len() < response.payload.len() {
400         log::error!("response payload is too large to fit into the buffer");
401         return Err(HwWskError::BadLen);
402     }
403 
404     let res_buffer = &mut buf[..response.payload.len()];
405     res_buffer.copy_from_slice(&response.payload);
406 
407     Ok(res_buffer)
408 }
409