1 // Copyright 2022, The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //     http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Utilities for handling legacy KeyMaster/KeyMint key blobs.
16 
17 use crate::tag::legacy::{consume_i32, consume_u32, consume_u8, consume_vec};
18 use crate::{
19     crypto, get_opt_tag_value, km_err, try_to_vec, vec_try_with_capacity, Error, FallibleAllocExt,
20 };
21 use alloc::vec::Vec;
22 use core::mem::size_of;
23 use kmr_wire::keymint::KeyParam;
24 
25 #[cfg(test)]
26 mod tests;
27 
28 /// Key blob version.
29 const KEY_BLOB_VERSION: u8 = 0;
30 
31 /// Hard-coded HMAC key used for keyblob authentication.
32 const HMAC_KEY: &[u8] = b"IntegrityAssuredBlob0\0";
33 
34 /// Format of encrypted key blob.
35 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
36 pub enum AuthEncryptedBlobFormat {
37     /// AES-OCB
38     AesOcb = 0,
39     /// AES-GCM encryption.
40     AesGcmWithSwEnforced = 1,
41     /// AES-GCM encryption including secure deletion secret.
42     AesGcmWithSecureDeletion = 2,
43     /// Versioned AES-GCM encryption.
44     AesGcmWithSwEnforcedVersioned = 3,
45     /// Versioned AES-GCM encryption including secure deletion secret.
46     AesGcmWithSecureDeletionVersioned = 4,
47 }
48 
49 impl AuthEncryptedBlobFormat {
50     /// Indicate whether this format requires secure deletion support.
requires_secure_deletion(&self) -> bool51     pub fn requires_secure_deletion(&self) -> bool {
52         matches!(self, Self::AesGcmWithSecureDeletion | Self::AesGcmWithSecureDeletionVersioned)
53     }
54     /// Indicate whether this format is versioned.
is_versioned(&self) -> bool55     pub fn is_versioned(&self) -> bool {
56         matches!(
57             self,
58             Self::AesGcmWithSwEnforcedVersioned | Self::AesGcmWithSecureDeletionVersioned
59         )
60     }
61 }
62 
63 /// Encrypted key blob, including key characteristics.
64 #[derive(Debug, PartialEq, Eq)]
65 pub struct EncryptedKeyBlob {
66     /// Format of the keyblob.
67     pub format: AuthEncryptedBlobFormat,
68     /// IV for encryption.
69     pub nonce: Vec<u8>,
70     /// Encrypted key material.
71     pub ciphertext: Vec<u8>,
72     /// Authenticated encryption tag.
73     pub tag: Vec<u8>,
74 
75     // The following two fields are preset iff `format.is_versioned()`
76     /// KDF version for the key.
77     pub kdf_version: Option<u32>,
78     /// Additional information for key derivation.
79     pub addl_info: Option<i32>,
80 
81     /// Hardware-enforced key characteristics.
82     pub hw_enforced: Vec<KeyParam>,
83     /// Software-enforced key characteristics.
84     pub sw_enforced: Vec<KeyParam>,
85     /// Secure deletion key slot.
86     pub key_slot: Option<u32>,
87 }
88 
89 impl EncryptedKeyBlob {
90     /// Serialize an [`EncryptedKeyBlob`].
serialize(&self) -> Result<Vec<u8>, Error>91     pub fn serialize(&self) -> Result<Vec<u8>, Error> {
92         let hw_enforced_data = crate::tag::legacy::serialize(&self.hw_enforced)?;
93         let sw_enforced_data = crate::tag::legacy::serialize(&self.sw_enforced)?;
94         let mut result = vec_try_with_capacity!(
95             size_of::<u8>()
96                 + size_of::<u32>()
97                 + self.nonce.len()
98                 + size_of::<u32>()
99                 + self.ciphertext.len()
100                 + size_of::<u32>()
101                 + self.tag.len()
102                 + hw_enforced_data.len()
103                 + sw_enforced_data.len()
104                 + size_of::<u32>()
105         )?;
106         result.push(self.format as u8);
107         result.extend_from_slice(&(self.nonce.len() as u32).to_ne_bytes());
108         result.extend_from_slice(&self.nonce);
109         result.extend_from_slice(&(self.ciphertext.len() as u32).to_ne_bytes());
110         result.extend_from_slice(&self.ciphertext);
111         result.extend_from_slice(&(self.tag.len() as u32).to_ne_bytes());
112         result.extend_from_slice(&self.tag);
113         if self.format.is_versioned() {
114             let kdf_version = self.kdf_version.ok_or_else(|| {
115                 km_err!(InvalidKeyBlob, "keyblob of format {:?} missing kdf_version", self.format)
116             })?;
117             let addl_info = self.addl_info.ok_or_else(|| {
118                 km_err!(InvalidKeyBlob, "keyblob of format {:?} missing addl_info", self.format)
119             })? as u32;
120             result.extend_from_slice(&kdf_version.to_ne_bytes());
121             result.extend_from_slice(&addl_info.to_ne_bytes());
122         }
123         result.extend_from_slice(&hw_enforced_data);
124         result.extend_from_slice(&sw_enforced_data);
125         if let Some(slot) = self.key_slot {
126             result.extend_from_slice(&slot.to_ne_bytes());
127         }
128         Ok(result)
129     }
130 
131     /// Parse a serialized [`KeyBlob`].
deserialize(mut data: &[u8]) -> Result<Self, Error>132     pub fn deserialize(mut data: &[u8]) -> Result<Self, Error> {
133         let format = match consume_u8(&mut data)? {
134             x if x == AuthEncryptedBlobFormat::AesOcb as u8 => AuthEncryptedBlobFormat::AesOcb,
135             x if x == AuthEncryptedBlobFormat::AesGcmWithSwEnforced as u8 => {
136                 AuthEncryptedBlobFormat::AesGcmWithSwEnforced
137             }
138             x if x == AuthEncryptedBlobFormat::AesGcmWithSecureDeletion as u8 => {
139                 AuthEncryptedBlobFormat::AesGcmWithSecureDeletion
140             }
141             x if x == AuthEncryptedBlobFormat::AesGcmWithSwEnforcedVersioned as u8 => {
142                 AuthEncryptedBlobFormat::AesGcmWithSwEnforcedVersioned
143             }
144             x if x == AuthEncryptedBlobFormat::AesGcmWithSecureDeletionVersioned as u8 => {
145                 AuthEncryptedBlobFormat::AesGcmWithSecureDeletionVersioned
146             }
147             x => return Err(km_err!(InvalidKeyBlob, "unexpected blob format {}", x)),
148         };
149 
150         let nonce = consume_vec(&mut data)?;
151         let ciphertext = consume_vec(&mut data)?;
152         let tag = consume_vec(&mut data)?;
153         let mut kdf_version = None;
154         let mut addl_info = None;
155         if format.is_versioned() {
156             kdf_version = Some(consume_u32(&mut data)?);
157             addl_info = Some(consume_i32(&mut data)?);
158         }
159         let hw_enforced = crate::tag::legacy::deserialize(&mut data)?;
160         let sw_enforced = crate::tag::legacy::deserialize(&mut data)?;
161 
162         let key_slot = match data.len() {
163             0 => None,
164             4 => Some(consume_u32(&mut data)?),
165             _ => return Err(km_err!(InvalidKeyBlob, "unexpected remaining length {}", data.len())),
166         };
167 
168         Ok(EncryptedKeyBlob {
169             format,
170             nonce,
171             ciphertext,
172             tag,
173             kdf_version,
174             addl_info,
175             hw_enforced,
176             sw_enforced,
177             key_slot,
178         })
179     }
180 }
181 
182 /// Plaintext key blob, with key characteristics.
183 #[derive(Debug, PartialEq, Eq)]
184 pub struct KeyBlob {
185     /// Raw key material.
186     pub key_material: Vec<u8>,
187     /// Hardware-enforced key characteristics.
188     pub hw_enforced: Vec<KeyParam>,
189     /// Software-enforced key characteristics.
190     pub sw_enforced: Vec<KeyParam>,
191 }
192 
193 impl KeyBlob {
194     /// Size (in bytes) of appended MAC.
195     pub const MAC_LEN: usize = 8;
196 
197     /// Serialize a [`KeyBlob`].
serialize<H: crypto::Hmac>( &self, hmac: &H, hidden: &[KeyParam], ) -> Result<Vec<u8>, crate::Error>198     pub fn serialize<H: crypto::Hmac>(
199         &self,
200         hmac: &H,
201         hidden: &[KeyParam],
202     ) -> Result<Vec<u8>, crate::Error> {
203         let hw_enforced_data = crate::tag::legacy::serialize(&self.hw_enforced)?;
204         let sw_enforced_data = crate::tag::legacy::serialize(&self.sw_enforced)?;
205         let mut result = vec_try_with_capacity!(
206             size_of::<u8>()
207                 + size_of::<u32>()
208                 + self.key_material.len()
209                 + hw_enforced_data.len()
210                 + sw_enforced_data.len()
211         )?;
212         result.push(KEY_BLOB_VERSION);
213         result.extend_from_slice(&(self.key_material.len() as u32).to_ne_bytes());
214         result.extend_from_slice(&self.key_material);
215         result.extend_from_slice(&hw_enforced_data);
216         result.extend_from_slice(&sw_enforced_data);
217         let mac = Self::compute_hmac(hmac, &result, hidden)?;
218         result.extend_from_slice(&mac);
219         Ok(result)
220     }
221 
222     /// Parse a serialized [`KeyBlob`].
deserialize<E: crypto::ConstTimeEq, H: crypto::Hmac>( hmac: &H, mut data: &[u8], hidden: &[KeyParam], comparator: E, ) -> Result<Self, Error>223     pub fn deserialize<E: crypto::ConstTimeEq, H: crypto::Hmac>(
224         hmac: &H,
225         mut data: &[u8],
226         hidden: &[KeyParam],
227         comparator: E,
228     ) -> Result<Self, Error> {
229         if data.len() < (Self::MAC_LEN + 4 + 4 + 4) {
230             return Err(km_err!(InvalidKeyBlob, "blob not long enough (len = {})", data.len()));
231         }
232 
233         // Check the HMAC in the last 8 bytes before doing anything else.
234         let mac = &data[data.len() - Self::MAC_LEN..];
235         let computed_mac = Self::compute_hmac(hmac, &data[..data.len() - Self::MAC_LEN], hidden)?;
236         if comparator.ne(mac, &computed_mac) {
237             return Err(km_err!(InvalidKeyBlob, "invalid key blob"));
238         }
239 
240         let version = consume_u8(&mut data)?;
241         if version != KEY_BLOB_VERSION {
242             return Err(km_err!(InvalidKeyBlob, "unexpected blob version {}", version));
243         }
244         let key_material = consume_vec(&mut data)?;
245         let hw_enforced = crate::tag::legacy::deserialize(&mut data)?;
246         let sw_enforced = crate::tag::legacy::deserialize(&mut data)?;
247 
248         // Should just be the (already-checked) MAC left.
249         let rest = &data[Self::MAC_LEN..];
250         if !rest.is_empty() {
251             return Err(km_err!(InvalidKeyBlob, "extra data (len {})", rest.len()));
252         }
253         Ok(KeyBlob { key_material, hw_enforced, sw_enforced })
254     }
255 
256     /// Compute the authentication HMAC for a KeyBlob. This is built as:
257     ///   HMAC-SHA256(HK, data || serialize(hidden))
258     /// with HK = b"IntegrityAssuredBlob0\0".
compute_hmac<H: crypto::Hmac>( hmac: &H, data: &[u8], hidden: &[KeyParam], ) -> Result<Vec<u8>, crate::Error>259     pub fn compute_hmac<H: crypto::Hmac>(
260         hmac: &H,
261         data: &[u8],
262         hidden: &[KeyParam],
263     ) -> Result<Vec<u8>, crate::Error> {
264         let hidden_data = crate::tag::legacy::serialize(hidden)?;
265         let mut op = hmac.begin(
266             crypto::hmac::Key(try_to_vec(HMAC_KEY)?).into(),
267             kmr_wire::keymint::Digest::Sha256,
268         )?;
269         op.update(data)?;
270         op.update(&hidden_data)?;
271         let mut tag = op.finish()?;
272         tag.truncate(Self::MAC_LEN);
273         Ok(tag)
274     }
275 }
276 
277 /// Build the parameters that are used as the hidden input to HMAC calculations:
278 /// - `ApplicationId(data)` if present
279 /// - `ApplicationData(data)` if present
280 /// - (repeated) `RootOfTrust(rot)` where `rot` is a hardcoded root of trust (expected to
281 ///   be the CBOR serialization of a `RootOfTrustInfo` instance).
hidden(params: &[KeyParam], rots: &[&[u8]]) -> Result<Vec<KeyParam>, Error>282 pub fn hidden(params: &[KeyParam], rots: &[&[u8]]) -> Result<Vec<KeyParam>, Error> {
283     let mut results = Vec::new();
284     if let Ok(Some(app_id)) = get_opt_tag_value!(params, ApplicationId) {
285         results.try_push(KeyParam::ApplicationId(try_to_vec(app_id)?))?;
286     }
287     if let Ok(Some(app_data)) = get_opt_tag_value!(params, ApplicationData) {
288         results.try_push(KeyParam::ApplicationData(try_to_vec(app_data)?))?;
289     }
290     for rot in rots {
291         results.try_push(KeyParam::RootOfTrust(try_to_vec(rot)?))?;
292     }
293     Ok(results)
294 }
295