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