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