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 //! Trusty implementation of StorageKeyWrapper trait.
17 use alloc::vec::Vec;
18 use core::ffi::CStr;
19 use kmr_common::{
20     crypto,
21     crypto::{aes, Aes, KeyMaterial, OpaqueKeyMaterial, OpaqueOr},
22     get_bool_tag_value, get_opt_tag_value, get_tag_value, km_err, vec_try, vec_try_with_capacity,
23     Error,
24 };
25 use kmr_crypto_boring::aes::BoringAes;
26 use kmr_ta::device::StorageKeyWrapper;
27 use kmr_wire::{keymint, keymint::ErrorCode, KeySizeInBits};
28 use log::warn;
29 use tipc::Handle;
30 
31 /// TIPC port used for communication with the `hwwsk` service.
32 const HWWSK_PORT: &[u8] = b"com.android.trusty.hwwsk\0";
33 
34 /// Create a session for `hwwsk` communication.
hwwsk_session() -> Result<Handle, Error>35 fn hwwsk_session() -> Result<Handle, Error> {
36     let port = CStr::from_bytes_with_nul(HWWSK_PORT).expect("HWWSK_PORT was not null terminated");
37     Handle::connect(port)
38         .map_err(|e| km_err!(SecureHwCommunicationFailed, "failed to connect to hwwsk: {:?}", e))
39 }
40 
41 /// Storage key wrapper implementation for Trusty.
42 pub struct TrustyStorageKeyWrapper;
43 
44 impl StorageKeyWrapper for TrustyStorageKeyWrapper {
ephemeral_wrap(&self, key_material: &KeyMaterial) -> Result<Vec<u8>, Error>45     fn ephemeral_wrap(&self, key_material: &KeyMaterial) -> Result<Vec<u8>, Error> {
46         let wrapped_key = match key_material {
47             KeyMaterial::Aes(OpaqueOr::Opaque(key)) => key,
48             _ => {
49                 return Err(km_err!(
50                     UnsupportedAlgorithm,
51                     "only opaque AES storage keys are supported"
52                 ))
53             }
54         };
55         let key = &wrapped_key.0;
56         let session = hwwsk_session()?;
57         let buf = &mut [0u8; hwwsk::HWWSK_MAX_MSG_SIZE as usize];
58         let wrapped_key_buffer = hwwsk::export_key(&session, buf, key).map_err(|e| {
59             km_err!(SecureHwCommunicationFailed, "hwwsk failed to wrap key: {:?}", e)
60         })?;
61         let mut wrapped_key = vec_try_with_capacity!(wrapped_key_buffer.len())?;
62         wrapped_key.extend_from_slice(wrapped_key_buffer);
63         Ok(wrapped_key)
64     }
65 }
66 
67 /// Wrapper around `BoringAes` implementation that intercepts storage keys.
68 pub struct TrustyAes(BoringAes);
69 
70 impl Default for TrustyAes {
default() -> Self71     fn default() -> Self {
72         Self(BoringAes)
73     }
74 }
75 impl TrustyAes {
create_storage_key( &self, key: Option<aes::Key>, params: &[keymint::KeyParam], ) -> Result<crypto::KeyMaterial, Error>76     fn create_storage_key(
77         &self,
78         key: Option<aes::Key>,
79         params: &[keymint::KeyParam],
80     ) -> Result<crypto::KeyMaterial, Error> {
81         // Storage keys should not work for normal operations.  The TA code polices this by watching
82         // for `Tag::StorageKey`; also police here by rejecting keys that have a `Tag::BlockMode`
83         // attached.
84         if get_opt_tag_value!(params, BlockMode)?.is_some() {
85             return Err(km_err!(UnsupportedTag, "don't expect block mode on storage key"));
86         }
87         let key_size = get_tag_value!(params, KeySize, ErrorCode::UnsupportedTag)?;
88         let key_size = key_size.0 as usize;
89         let mut key_flags = hwwsk::KeyFlags::new();
90         let rollback_resistance = get_bool_tag_value!(params, RollbackResistance)?;
91         if rollback_resistance {
92             key_flags = key_flags.rollback_resistance();
93         };
94 
95         let session = hwwsk_session()?;
96         let mut buf = vec_try![0; hwwsk::HWWSK_MAX_MSG_SIZE as usize]?;
97         let key_material: Option<&[u8]> = match key.as_ref() {
98             None => None,
99             Some(aes_key) => Some(match aes_key {
100                 aes::Key::Aes128(key) => key,
101                 aes::Key::Aes192(key) => key,
102                 aes::Key::Aes256(key) => key,
103             }),
104         };
105         let mut result = match key_material {
106             None => hwwsk::generate_key(&session, &mut buf, key_size, key_flags),
107             Some(key) => hwwsk::import_key(&session, &mut buf, key_size, key_flags, key),
108         };
109         if result == Err(hwwsk::HwWskError::NotSupported) && rollback_resistance {
110             warn!("failed to generate rollback-resistant storage key, retrying without resistance");
111             key_flags = hwwsk::KeyFlags::new();
112             result = match key_material {
113                 None => hwwsk::generate_key(&session, &mut buf, key_size, key_flags),
114                 Some(key) => hwwsk::import_key(&session, &mut buf, key_size, key_flags, key),
115             };
116         }
117 
118         let wrapped_key_buffer =
119             result.map_err(|e| km_err!(UnknownError, "hwwsk failed to create key: {:?}", e))?;
120 
121         let mut wrapped_key = vec_try_with_capacity!(wrapped_key_buffer.len())?;
122         wrapped_key.extend_from_slice(wrapped_key_buffer);
123         Ok(crypto::KeyMaterial::Aes(OpaqueOr::Opaque(OpaqueKeyMaterial(wrapped_key))))
124     }
125 }
126 
127 impl Aes for TrustyAes {
generate_key( &self, rng: &mut dyn crypto::Rng, variant: aes::Variant, params: &[keymint::KeyParam], ) -> Result<crypto::KeyMaterial, Error>128     fn generate_key(
129         &self,
130         rng: &mut dyn crypto::Rng,
131         variant: aes::Variant,
132         params: &[keymint::KeyParam],
133     ) -> Result<crypto::KeyMaterial, Error> {
134         if !get_bool_tag_value!(params, StorageKey)? {
135             // For normal (non-storage) keys, pass on to BoringSSL implementation.
136             return self.0.generate_key(rng, variant, params);
137         }
138         self.create_storage_key(None, params)
139     }
140 
import_key( &self, data: &[u8], params: &[keymint::KeyParam], ) -> Result<(crypto::KeyMaterial, KeySizeInBits), Error>141     fn import_key(
142         &self,
143         data: &[u8],
144         params: &[keymint::KeyParam],
145     ) -> Result<(crypto::KeyMaterial, KeySizeInBits), Error> {
146         if !get_bool_tag_value!(params, StorageKey)? {
147             // For normal (non-storage) keys, pass on to BoringSSL implementation.
148             return self.0.import_key(data, params);
149         }
150 
151         let aes_key = aes::Key::new_from(data)?;
152         let key_size = aes_key.size();
153         Ok((self.create_storage_key(Some(aes_key), params)?, key_size))
154     }
155 
begin( &self, key: OpaqueOr<aes::Key>, mode: aes::CipherMode, dir: crypto::SymmetricOperation, ) -> Result<Box<dyn crypto::EmittingOperation>, Error>156     fn begin(
157         &self,
158         key: OpaqueOr<aes::Key>,
159         mode: aes::CipherMode,
160         dir: crypto::SymmetricOperation,
161     ) -> Result<Box<dyn crypto::EmittingOperation>, Error> {
162         match key {
163             OpaqueOr::Explicit(_) => self.0.begin(key, mode, dir),
164             OpaqueOr::Opaque(_) => {
165                 Err(km_err!(StorageKeyUnsupported, "attempt to use storage key"))
166             }
167         }
168     }
169 
begin_aead( &self, key: OpaqueOr<aes::Key>, mode: aes::GcmMode, dir: crypto::SymmetricOperation, ) -> Result<Box<dyn crypto::AadOperation>, Error>170     fn begin_aead(
171         &self,
172         key: OpaqueOr<aes::Key>,
173         mode: aes::GcmMode,
174         dir: crypto::SymmetricOperation,
175     ) -> Result<Box<dyn crypto::AadOperation>, Error> {
176         match key {
177             OpaqueOr::Explicit(_) => self.0.begin_aead(key, mode, dir),
178             OpaqueOr::Opaque(_) => {
179                 Err(km_err!(StorageKeyUnsupported, "attempt to use storage key"))
180             }
181         }
182     }
183 }
184 
185 // Not adding unit tests because we do not have a mock server on AOSP for hwwsk.
186