1 // Copyright 2023, 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 //! Code for parsing software-backed keyblobs, as emitted by the C++ reference implementation of
16 //! KeyMint.
17 
18 use crate::error::Error;
19 use crate::ks_err;
20 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
21     Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
22     ErrorCode::ErrorCode, HardwareAuthenticatorType::HardwareAuthenticatorType,
23     KeyFormat::KeyFormat, KeyOrigin::KeyOrigin, KeyParameter::KeyParameter,
24     KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
25     Tag::Tag, TagType::TagType,
26 };
27 use anyhow::Result;
28 use keystore2_crypto::hmac_sha256;
29 use std::mem::size_of;
30 
31 /// Root of trust value.
32 const SOFTWARE_ROOT_OF_TRUST: &[u8] = b"SW";
33 
34 /// Error macro.
35 macro_rules! bloberr {
36     { $($arg:tt)+ } => {
37         anyhow::Error::new(Error::Km(ErrorCode::INVALID_KEY_BLOB)).context(ks_err!($($arg)+))
38     };
39 }
40 
41 /// Get the `KeyParameterValue` associated with a tag from a collection of `KeyParameter`s.
get_tag_value(params: &[KeyParameter], tag: Tag) -> Option<&KeyParameterValue>42 fn get_tag_value(params: &[KeyParameter], tag: Tag) -> Option<&KeyParameterValue> {
43     params.iter().find_map(|kp| if kp.tag == tag { Some(&kp.value) } else { None })
44 }
45 
46 /// Get the [`TagType`] for a [`Tag`].
tag_type(tag: &Tag) -> TagType47 fn tag_type(tag: &Tag) -> TagType {
48     TagType((tag.0 as u32 & 0xf0000000) as i32)
49 }
50 
51 /// Extract key material and combined key characteristics from a legacy authenticated keyblob.
export_key( data: &[u8], params: &[KeyParameter], ) -> Result<(KeyFormat, Vec<u8>, Vec<KeyParameter>)>52 pub fn export_key(
53     data: &[u8],
54     params: &[KeyParameter],
55 ) -> Result<(KeyFormat, Vec<u8>, Vec<KeyParameter>)> {
56     let hidden = hidden_params(params, &[SOFTWARE_ROOT_OF_TRUST]);
57     let KeyBlob { key_material, hw_enforced, sw_enforced } =
58         KeyBlob::new_from_serialized(data, &hidden)?;
59 
60     let mut combined = hw_enforced;
61     combined.extend_from_slice(&sw_enforced);
62 
63     let algo_val =
64         get_tag_value(&combined, Tag::ALGORITHM).ok_or_else(|| bloberr!("No algorithm found!"))?;
65 
66     let format = match algo_val {
67         KeyParameterValue::Algorithm(Algorithm::AES)
68         | KeyParameterValue::Algorithm(Algorithm::TRIPLE_DES)
69         | KeyParameterValue::Algorithm(Algorithm::HMAC) => KeyFormat::RAW,
70         KeyParameterValue::Algorithm(Algorithm::RSA)
71         | KeyParameterValue::Algorithm(Algorithm::EC) => KeyFormat::PKCS8,
72         _ => return Err(bloberr!("Unexpected algorithm {:?}", algo_val)),
73     };
74 
75     let key_material = match (format, algo_val) {
76         (KeyFormat::PKCS8, KeyParameterValue::Algorithm(Algorithm::EC)) => {
77             // Key material format depends on the curve.
78             let curve = get_tag_value(&combined, Tag::EC_CURVE)
79                 .ok_or_else(|| bloberr!("Failed to determine curve for EC key!"))?;
80             match curve {
81                 KeyParameterValue::EcCurve(EcCurve::CURVE_25519) => key_material,
82                 KeyParameterValue::EcCurve(EcCurve::P_224) => {
83                     pkcs8_wrap_nist_key(&key_material, EcCurve::P_224)?
84                 }
85                 KeyParameterValue::EcCurve(EcCurve::P_256) => {
86                     pkcs8_wrap_nist_key(&key_material, EcCurve::P_256)?
87                 }
88                 KeyParameterValue::EcCurve(EcCurve::P_384) => {
89                     pkcs8_wrap_nist_key(&key_material, EcCurve::P_384)?
90                 }
91                 KeyParameterValue::EcCurve(EcCurve::P_521) => {
92                     pkcs8_wrap_nist_key(&key_material, EcCurve::P_521)?
93                 }
94                 _ => {
95                     return Err(bloberr!("Unexpected EC curve {curve:?}"));
96                 }
97             }
98         }
99         (KeyFormat::RAW, _) => key_material,
100         (format, algo) => {
101             return Err(bloberr!(
102                 "Unsupported combination of {format:?} format for {algo:?} algorithm"
103             ));
104         }
105     };
106     Ok((format, key_material, combined))
107 }
108 
109 /// DER-encoded `AlgorithmIdentifier` for a P-224 key.
110 const DER_ALGORITHM_ID_P224: &[u8] = &[
111     0x30, 0x10, // SEQUENCE (AlgorithmIdentifier) {
112     0x06, 0x07, // OBJECT IDENTIFIER (algorithm)
113     0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, // 1.2.840.10045.2.1 (ecPublicKey)
114     0x06, 0x05, // OBJECT IDENTIFIER (param)
115     0x2b, 0x81, 0x04, 0x00, 0x21, //  1.3.132.0.33 (secp224r1) }
116 ];
117 
118 /// DER-encoded `AlgorithmIdentifier` for a P-256 key.
119 const DER_ALGORITHM_ID_P256: &[u8] = &[
120     0x30, 0x13, // SEQUENCE (AlgorithmIdentifier) {
121     0x06, 0x07, // OBJECT IDENTIFIER (algorithm)
122     0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, // 1.2.840.10045.2.1 (ecPublicKey)
123     0x06, 0x08, // OBJECT IDENTIFIER (param)
124     0x2a, 0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, //  1.2.840.10045.3.1.7 (secp256r1) }
125 ];
126 
127 /// DER-encoded `AlgorithmIdentifier` for a P-384 key.
128 const DER_ALGORITHM_ID_P384: &[u8] = &[
129     0x30, 0x10, // SEQUENCE (AlgorithmIdentifier) {
130     0x06, 0x07, // OBJECT IDENTIFIER (algorithm)
131     0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, // 1.2.840.10045.2.1 (ecPublicKey)
132     0x06, 0x05, // OBJECT IDENTIFIER (param)
133     0x2b, 0x81, 0x04, 0x00, 0x22, //  1.3.132.0.34 (secp384r1) }
134 ];
135 
136 /// DER-encoded `AlgorithmIdentifier` for a P-384 key.
137 const DER_ALGORITHM_ID_P521: &[u8] = &[
138     0x30, 0x10, // SEQUENCE (AlgorithmIdentifier) {
139     0x06, 0x07, // OBJECT IDENTIFIER (algorithm)
140     0x2a, 0x86, 0x48, 0xce, 0x3d, 0x02, 0x01, // 1.2.840.10045.2.1 (ecPublicKey)
141     0x06, 0x05, // OBJECT IDENTIFIER (param)
142     0x2b, 0x81, 0x04, 0x00, 0x23, //  1.3.132.0.35 (secp521r1) }
143 ];
144 
145 /// DER-encoded integer value zero.
146 const DER_VERSION_0: &[u8] = &[
147     0x02, // INTEGER
148     0x01, // len
149     0x00, // value 0
150 ];
151 
152 /// Given a NIST curve EC key in the form of a DER-encoded `ECPrivateKey`
153 /// (RFC 5915 s3), wrap it in a DER-encoded PKCS#8 format (RFC 5208 s5).
pkcs8_wrap_nist_key(nist_key: &[u8], curve: EcCurve) -> Result<Vec<u8>>154 fn pkcs8_wrap_nist_key(nist_key: &[u8], curve: EcCurve) -> Result<Vec<u8>> {
155     let der_alg_id = match curve {
156         EcCurve::P_224 => DER_ALGORITHM_ID_P224,
157         EcCurve::P_256 => DER_ALGORITHM_ID_P256,
158         EcCurve::P_384 => DER_ALGORITHM_ID_P384,
159         EcCurve::P_521 => DER_ALGORITHM_ID_P521,
160         _ => return Err(bloberr!("unknown curve {curve:?}")),
161     };
162 
163     // Output format is:
164     //
165     //    PrivateKeyInfo ::= SEQUENCE {
166     //        version                   INTEGER,
167     //        privateKeyAlgorithm       AlgorithmIdentifier,
168     //        privateKey                OCTET STRING,
169     //    }
170     //
171     // Start by building the OCTET STRING so we know its length.
172     let mut nist_key_octet_string = Vec::new();
173     nist_key_octet_string.push(0x04); // OCTET STRING
174     add_der_len(&mut nist_key_octet_string, nist_key.len())?;
175     nist_key_octet_string.extend_from_slice(nist_key);
176 
177     let mut buf = Vec::new();
178     buf.push(0x30); // SEQUENCE
179     add_der_len(&mut buf, DER_VERSION_0.len() + der_alg_id.len() + nist_key_octet_string.len())?;
180     buf.extend_from_slice(DER_VERSION_0);
181     buf.extend_from_slice(der_alg_id);
182     buf.extend_from_slice(&nist_key_octet_string);
183     Ok(buf)
184 }
185 
186 /// Append a DER-encoded length value to the given buffer.
add_der_len(buf: &mut Vec<u8>, len: usize) -> Result<()>187 fn add_der_len(buf: &mut Vec<u8>, len: usize) -> Result<()> {
188     if len <= 0x7f {
189         buf.push(len as u8)
190     } else if len <= 0xff {
191         buf.push(0x81); // One length octet to come
192         buf.push(len as u8);
193     } else if len <= 0xffff {
194         buf.push(0x82); // Two length octets to come
195         buf.push((len >> 8) as u8);
196         buf.push((len & 0xff) as u8);
197     } else {
198         return Err(bloberr!("Unsupported DER length {len}"));
199     }
200     Ok(())
201 }
202 
203 /// Plaintext key blob, with key characteristics.
204 #[derive(PartialEq, Eq)]
205 struct KeyBlob {
206     /// Raw key material.
207     key_material: Vec<u8>,
208     /// Hardware-enforced key characteristics.
209     hw_enforced: Vec<KeyParameter>,
210     /// Software-enforced key characteristics.
211     sw_enforced: Vec<KeyParameter>,
212 }
213 
214 impl KeyBlob {
215     /// Key blob version.
216     const KEY_BLOB_VERSION: u8 = 0;
217 
218     /// Hard-coded HMAC key used for keyblob authentication.
219     const LEGACY_HMAC_KEY: &'static [u8] = b"IntegrityAssuredBlob0\0";
220 
221     /// Size (in bytes) of appended MAC.
222     const MAC_LEN: usize = 8;
223 
224     /// Parse a serialized [`KeyBlob`].
new_from_serialized(mut data: &[u8], hidden: &[KeyParameter]) -> Result<Self>225     fn new_from_serialized(mut data: &[u8], hidden: &[KeyParameter]) -> Result<Self> {
226         // Keyblob needs to be at least long enough for:
227         // - version byte,
228         // - 4-byte len for key material
229         // - 4-byte len for hw_enforced params
230         // - 4-byte len for sw_enforced params
231         // - MAC tag.
232         if data.len() < (1 + 3 * size_of::<u32>() + Self::MAC_LEN) {
233             return Err(bloberr!("blob not long enough (len = {})", data.len()));
234         }
235 
236         // Check the HMAC in the last 8 bytes before doing anything else.
237         let mac = &data[data.len() - Self::MAC_LEN..];
238         let computed_mac = Self::compute_hmac(&data[..data.len() - Self::MAC_LEN], hidden)?;
239         if mac != computed_mac {
240             return Err(bloberr!("invalid key blob"));
241         }
242 
243         let version = consume_u8(&mut data)?;
244         if version != Self::KEY_BLOB_VERSION {
245             return Err(bloberr!("unexpected blob version {}", version));
246         }
247         let key_material = consume_vec(&mut data)?;
248         let hw_enforced = deserialize_params(&mut data)?;
249         let sw_enforced = deserialize_params(&mut data)?;
250 
251         // Should just be the (already-checked) MAC left.
252         let rest = &data[Self::MAC_LEN..];
253         if !rest.is_empty() {
254             return Err(bloberr!("extra data (len {})", rest.len()));
255         }
256         Ok(KeyBlob { key_material, hw_enforced, sw_enforced })
257     }
258 
259     /// Compute the authentication HMAC for a KeyBlob. This is built as:
260     ///   HMAC-SHA256(HK, data || serialize(hidden))
261     /// with HK = b"IntegrityAssuredBlob0\0".
compute_hmac(data: &[u8], hidden: &[KeyParameter]) -> Result<Vec<u8>>262     fn compute_hmac(data: &[u8], hidden: &[KeyParameter]) -> Result<Vec<u8>> {
263         let hidden_data = serialize_params(hidden)?;
264         let mut combined = data.to_vec();
265         combined.extend_from_slice(&hidden_data);
266         let mut tag = hmac_sha256(Self::LEGACY_HMAC_KEY, &combined)?;
267         tag.truncate(Self::MAC_LEN);
268         Ok(tag)
269     }
270 }
271 
272 /// Build the parameters that are used as the hidden input to HMAC calculations:
273 /// - `ApplicationId(data)` if present
274 /// - `ApplicationData(data)` if present
275 /// - (repeated) `RootOfTrust(rot)` where `rot` is a hardcoded piece of root of trust information.
hidden_params(params: &[KeyParameter], rots: &[&[u8]]) -> Vec<KeyParameter>276 fn hidden_params(params: &[KeyParameter], rots: &[&[u8]]) -> Vec<KeyParameter> {
277     let mut results = Vec::new();
278     if let Some(app_id) = get_tag_value(params, Tag::APPLICATION_ID) {
279         results.push(KeyParameter { tag: Tag::APPLICATION_ID, value: app_id.clone() });
280     }
281     if let Some(app_data) = get_tag_value(params, Tag::APPLICATION_DATA) {
282         results.push(KeyParameter { tag: Tag::APPLICATION_DATA, value: app_data.clone() });
283     }
284     for rot in rots {
285         results.push(KeyParameter {
286             tag: Tag::ROOT_OF_TRUST,
287             value: KeyParameterValue::Blob(rot.to_vec()),
288         });
289     }
290     results
291 }
292 
293 /// Retrieve a `u8` from the start of the given slice, if possible.
consume_u8(data: &mut &[u8]) -> Result<u8>294 fn consume_u8(data: &mut &[u8]) -> Result<u8> {
295     match data.first() {
296         Some(b) => {
297             *data = &(*data)[1..];
298             Ok(*b)
299         }
300         None => Err(bloberr!("failed to find 1 byte")),
301     }
302 }
303 
304 /// Move past a bool value from the start of the given slice, if possible.
305 /// Bool values should only be included if `true`, so fail if the value
306 /// is anything other than 1.
consume_bool(data: &mut &[u8]) -> Result<bool>307 fn consume_bool(data: &mut &[u8]) -> Result<bool> {
308     let b = consume_u8(data)?;
309     if b == 0x01 {
310         Ok(true)
311     } else {
312         Err(bloberr!("bool value other than 1 encountered"))
313     }
314 }
315 
316 /// Retrieve a (host-ordered) `u32` from the start of the given slice, if possible.
consume_u32(data: &mut &[u8]) -> Result<u32>317 fn consume_u32(data: &mut &[u8]) -> Result<u32> {
318     const LEN: usize = size_of::<u32>();
319     if data.len() < LEN {
320         return Err(bloberr!("failed to find {LEN} bytes"));
321     }
322     let chunk: [u8; LEN] = data[..LEN].try_into().unwrap(); // safe: just checked
323     *data = &(*data)[LEN..];
324     Ok(u32::from_ne_bytes(chunk))
325 }
326 
327 /// Retrieve a (host-ordered) `i32` from the start of the given slice, if possible.
consume_i32(data: &mut &[u8]) -> Result<i32>328 fn consume_i32(data: &mut &[u8]) -> Result<i32> {
329     const LEN: usize = size_of::<i32>();
330     if data.len() < LEN {
331         return Err(bloberr!("failed to find {LEN} bytes"));
332     }
333     let chunk: [u8; LEN] = data[..LEN].try_into().unwrap(); // safe: just checked
334     *data = &(*data)[4..];
335     Ok(i32::from_ne_bytes(chunk))
336 }
337 
338 /// Retrieve a (host-ordered) `i64` from the start of the given slice, if possible.
consume_i64(data: &mut &[u8]) -> Result<i64>339 fn consume_i64(data: &mut &[u8]) -> Result<i64> {
340     const LEN: usize = size_of::<i64>();
341     if data.len() < LEN {
342         return Err(bloberr!("failed to find {LEN} bytes"));
343     }
344     let chunk: [u8; LEN] = data[..LEN].try_into().unwrap(); // safe: just checked
345     *data = &(*data)[LEN..];
346     Ok(i64::from_ne_bytes(chunk))
347 }
348 
349 /// Retrieve a vector of bytes from the start of the given slice, if possible,
350 /// with the length of the data expected to appear as a host-ordered `u32` prefix.
consume_vec(data: &mut &[u8]) -> Result<Vec<u8>>351 fn consume_vec(data: &mut &[u8]) -> Result<Vec<u8>> {
352     let len = consume_u32(data)? as usize;
353     if len > data.len() {
354         return Err(bloberr!("failed to find {} bytes", len));
355     }
356     let result = data[..len].to_vec();
357     *data = &(*data)[len..];
358     Ok(result)
359 }
360 
361 /// Retrieve the contents of a tag of `TagType::Bytes`.  The `data` parameter holds
362 /// the as-yet unparsed data, and a length and offset are read from this (and consumed).
363 /// This length and offset refer to a location in the combined `blob_data`; however,
364 /// the offset is expected to be the next unconsumed chunk of `blob_data`, as indicated
365 /// by `next_blob_offset` (which itself is updated as a result of consuming the data).
consume_blob( data: &mut &[u8], next_blob_offset: &mut usize, blob_data: &[u8], ) -> Result<Vec<u8>>366 fn consume_blob(
367     data: &mut &[u8],
368     next_blob_offset: &mut usize,
369     blob_data: &[u8],
370 ) -> Result<Vec<u8>> {
371     let data_len = consume_u32(data)? as usize;
372     let data_offset = consume_u32(data)? as usize;
373     // Expect the blob data to come from the next offset in the initial blob chunk.
374     if data_offset != *next_blob_offset {
375         return Err(bloberr!("got blob offset {} instead of {}", data_offset, next_blob_offset));
376     }
377     if (data_offset + data_len) > blob_data.len() {
378         return Err(bloberr!(
379             "blob at offset [{}..{}+{}] goes beyond blob data size {}",
380             data_offset,
381             data_offset,
382             data_len,
383             blob_data.len(),
384         ));
385     }
386 
387     let slice = &blob_data[data_offset..data_offset + data_len];
388     *next_blob_offset += data_len;
389     Ok(slice.to_vec())
390 }
391 
392 /// Deserialize a collection of [`KeyParam`]s in legacy serialized format. The provided slice is
393 /// modified to contain the unconsumed part of the data.
deserialize_params(data: &mut &[u8]) -> Result<Vec<KeyParameter>>394 fn deserialize_params(data: &mut &[u8]) -> Result<Vec<KeyParameter>> {
395     let blob_data_size = consume_u32(data)? as usize;
396     if blob_data_size > data.len() {
397         return Err(bloberr!(
398             "blob data size {} bigger than data (len={})",
399             blob_data_size,
400             data.len()
401         ));
402     }
403 
404     let blob_data = &data[..blob_data_size];
405     let mut next_blob_offset = 0;
406 
407     // Move past the blob data.
408     *data = &data[blob_data_size..];
409 
410     let param_count = consume_u32(data)? as usize;
411     let param_size = consume_u32(data)? as usize;
412     if param_size > data.len() {
413         return Err(bloberr!(
414             "size mismatch 4+{}+4+4+{} > {}",
415             blob_data_size,
416             param_size,
417             data.len()
418         ));
419     }
420 
421     let mut results = Vec::new();
422     for _i in 0..param_count {
423         let tag_num = consume_u32(data)? as i32;
424         let tag = Tag(tag_num);
425         let value = match tag_type(&tag) {
426             TagType::INVALID => return Err(bloberr!("invalid tag {:?} encountered", tag)),
427             TagType::ENUM | TagType::ENUM_REP => {
428                 let val = consume_i32(data)?;
429                 match tag {
430                     Tag::ALGORITHM => KeyParameterValue::Algorithm(Algorithm(val)),
431                     Tag::BLOCK_MODE => KeyParameterValue::BlockMode(BlockMode(val)),
432                     Tag::PADDING => KeyParameterValue::PaddingMode(PaddingMode(val)),
433                     Tag::DIGEST | Tag::RSA_OAEP_MGF_DIGEST => {
434                         KeyParameterValue::Digest(Digest(val))
435                     }
436                     Tag::EC_CURVE => KeyParameterValue::EcCurve(EcCurve(val)),
437                     Tag::ORIGIN => KeyParameterValue::Origin(KeyOrigin(val)),
438                     Tag::PURPOSE => KeyParameterValue::KeyPurpose(KeyPurpose(val)),
439                     Tag::USER_AUTH_TYPE => {
440                         KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(val))
441                     }
442                     _ => KeyParameterValue::Integer(val),
443                 }
444             }
445             TagType::UINT | TagType::UINT_REP => KeyParameterValue::Integer(consume_i32(data)?),
446             TagType::ULONG | TagType::ULONG_REP => {
447                 KeyParameterValue::LongInteger(consume_i64(data)?)
448             }
449             TagType::DATE => KeyParameterValue::DateTime(consume_i64(data)?),
450             TagType::BOOL => KeyParameterValue::BoolValue(consume_bool(data)?),
451             TagType::BIGNUM | TagType::BYTES => {
452                 KeyParameterValue::Blob(consume_blob(data, &mut next_blob_offset, blob_data)?)
453             }
454             _ => return Err(bloberr!("unexpected tag type for {:?}", tag)),
455         };
456         results.push(KeyParameter { tag, value });
457     }
458 
459     Ok(results)
460 }
461 
462 /// Serialize a collection of [`KeyParameter`]s into a format that is compatible with previous
463 /// implementations:
464 ///
465 /// ```text
466 /// [0..4]              Size B of `TagType::Bytes` data, in host order.
467 /// [4..4+B]      (*)   Concatenated contents of each `TagType::Bytes` tag.
468 /// [4+B..4+B+4]        Count N of the number of parameters, in host order.
469 /// [8+B..8+B+4]        Size Z of encoded parameters.
470 /// [12+B..12+B+Z]      Serialized parameters one after another.
471 /// ```
472 ///
473 /// Individual parameters are serialized in the last chunk as:
474 ///
475 /// ```text
476 /// [0..4]              Tag number, in host order.
477 /// Followed by one of the following depending on the tag's `TagType`; all integers in host order:
478 ///   [4..5]            Bool value (`TagType::Bool`)
479 ///   [4..8]            i32 values (`TagType::Uint[Rep]`, `TagType::Enum[Rep]`)
480 ///   [4..12]           i64 values, in host order (`TagType::UlongRep`, `TagType::Date`)
481 ///   [4..8] + [8..12]  Size + offset of data in (*) above (`TagType::Bytes`, `TagType::Bignum`)
482 /// ```
serialize_params(params: &[KeyParameter]) -> Result<Vec<u8>>483 fn serialize_params(params: &[KeyParameter]) -> Result<Vec<u8>> {
484     // First 4 bytes are the length of the combined [`TagType::Bytes`] data; come back to set that
485     // in a moment.
486     let mut result = vec![0; 4];
487 
488     // Next append the contents of all of the [`TagType::Bytes`] data.
489     let mut blob_size = 0u32;
490     for param in params {
491         let tag_type = tag_type(&param.tag);
492         if let KeyParameterValue::Blob(v) = &param.value {
493             if tag_type != TagType::BIGNUM && tag_type != TagType::BYTES {
494                 return Err(bloberr!("unexpected tag type for tag {:?} with blob", param.tag));
495             }
496             result.extend_from_slice(v);
497             blob_size += v.len() as u32;
498         }
499     }
500     // Go back and fill in the combined blob length in native order at the start.
501     result[..4].clone_from_slice(&blob_size.to_ne_bytes());
502 
503     result.extend_from_slice(&(params.len() as u32).to_ne_bytes());
504 
505     let params_size_offset = result.len();
506     result.extend_from_slice(&[0u8; 4]); // placeholder for size of elements
507     let first_param_offset = result.len();
508     let mut blob_offset = 0u32;
509     for param in params {
510         result.extend_from_slice(&(param.tag.0 as u32).to_ne_bytes());
511         match &param.value {
512             KeyParameterValue::Invalid(_v) => {
513                 return Err(bloberr!("invalid tag found in {:?}", param))
514             }
515 
516             // Enum-holding variants.
517             KeyParameterValue::Algorithm(v) => {
518                 result.extend_from_slice(&(v.0 as u32).to_ne_bytes())
519             }
520             KeyParameterValue::BlockMode(v) => {
521                 result.extend_from_slice(&(v.0 as u32).to_ne_bytes())
522             }
523             KeyParameterValue::PaddingMode(v) => {
524                 result.extend_from_slice(&(v.0 as u32).to_ne_bytes())
525             }
526             KeyParameterValue::Digest(v) => result.extend_from_slice(&(v.0 as u32).to_ne_bytes()),
527             KeyParameterValue::EcCurve(v) => result.extend_from_slice(&(v.0 as u32).to_ne_bytes()),
528             KeyParameterValue::Origin(v) => result.extend_from_slice(&(v.0 as u32).to_ne_bytes()),
529             KeyParameterValue::KeyPurpose(v) => {
530                 result.extend_from_slice(&(v.0 as u32).to_ne_bytes())
531             }
532             KeyParameterValue::HardwareAuthenticatorType(v) => {
533                 result.extend_from_slice(&(v.0 as u32).to_ne_bytes())
534             }
535 
536             // Value-holding variants.
537             KeyParameterValue::Integer(v) => result.extend_from_slice(&(*v as u32).to_ne_bytes()),
538             KeyParameterValue::BoolValue(_v) => result.push(0x01u8),
539             KeyParameterValue::LongInteger(v) | KeyParameterValue::DateTime(v) => {
540                 result.extend_from_slice(&(*v as u64).to_ne_bytes())
541             }
542             KeyParameterValue::Blob(v) => {
543                 let blob_len = v.len() as u32;
544                 result.extend_from_slice(&blob_len.to_ne_bytes());
545                 result.extend_from_slice(&blob_offset.to_ne_bytes());
546                 blob_offset += blob_len;
547             }
548 
549             _ => return Err(bloberr!("unknown value found in {:?}", param)),
550         }
551     }
552     let serialized_size = (result.len() - first_param_offset) as u32;
553 
554     // Go back and fill in the total serialized size.
555     result[params_size_offset..params_size_offset + 4]
556         .clone_from_slice(&serialized_size.to_ne_bytes());
557     Ok(result)
558 }
559 
560 #[cfg(test)]
561 mod tests {
562     use super::*;
563     use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
564         Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
565         KeyOrigin::KeyOrigin, KeyParameter::KeyParameter,
566         KeyParameterValue::KeyParameterValue as KPV, KeyPurpose::KeyPurpose,
567         PaddingMode::PaddingMode, Tag::Tag,
568     };
569 
570     macro_rules! expect_err {
571         ($result:expr, $err_msg:expr) => {
572             assert!(
573                 $result.is_err(),
574                 "Expected error containing '{}', got success {:?}",
575                 $err_msg,
576                 $result
577             );
578             let err = $result.err();
579             assert!(
580                 format!("{:?}", err).contains($err_msg),
581                 "Unexpected error {:?}, doesn't contain '{}'",
582                 err,
583                 $err_msg
584             );
585         };
586     }
587 
588     #[test]
test_consume_u8()589     fn test_consume_u8() {
590         let buffer = [1, 2];
591         let mut data = &buffer[..];
592         assert_eq!(1u8, consume_u8(&mut data).unwrap());
593         assert_eq!(2u8, consume_u8(&mut data).unwrap());
594         let result = consume_u8(&mut data);
595         expect_err!(result, "failed to find 1 byte");
596     }
597 
598     #[test]
test_consume_u32()599     fn test_consume_u32() {
600         // All supported platforms are little-endian.
601         let buffer = [
602             0x01, 0x02, 0x03, 0x04, // little-endian u32
603             0x04, 0x03, 0x02, 0x01, // little-endian u32
604             0x11, 0x12, 0x13,
605         ];
606         let mut data = &buffer[..];
607         assert_eq!(0x04030201u32, consume_u32(&mut data).unwrap());
608         assert_eq!(0x01020304u32, consume_u32(&mut data).unwrap());
609         let result = consume_u32(&mut data);
610         expect_err!(result, "failed to find 4 bytes");
611     }
612 
613     #[test]
test_consume_i64()614     fn test_consume_i64() {
615         // All supported platforms are little-endian.
616         let buffer = [
617             0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, // little-endian i64
618             0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, // little-endian i64
619             0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
620         ];
621         let mut data = &buffer[..];
622         assert_eq!(0x0807060504030201i64, consume_i64(&mut data).unwrap());
623         assert_eq!(0x0102030405060708i64, consume_i64(&mut data).unwrap());
624         let result = consume_i64(&mut data);
625         expect_err!(result, "failed to find 8 bytes");
626     }
627 
628     #[test]
test_consume_vec()629     fn test_consume_vec() {
630         let buffer = [
631             0x01, 0x00, 0x00, 0x00, 0xaa, //
632             0x00, 0x00, 0x00, 0x00, //
633             0x01, 0x00, 0x00, 0x00, 0xbb, //
634             0x07, 0x00, 0x00, 0x00, 0xbb, // not enough data
635         ];
636         let mut data = &buffer[..];
637         assert_eq!(vec![0xaa], consume_vec(&mut data).unwrap());
638         assert_eq!(Vec::<u8>::new(), consume_vec(&mut data).unwrap());
639         assert_eq!(vec![0xbb], consume_vec(&mut data).unwrap());
640         let result = consume_vec(&mut data);
641         expect_err!(result, "failed to find 7 bytes");
642 
643         let buffer = [
644             0x01, 0x00, 0x00, //
645         ];
646         let mut data = &buffer[..];
647         let result = consume_vec(&mut data);
648         expect_err!(result, "failed to find 4 bytes");
649     }
650 
651     #[test]
test_key_new_from_serialized()652     fn test_key_new_from_serialized() {
653         let hidden = hidden_params(&[], &[SOFTWARE_ROOT_OF_TRUST]);
654         // Test data originally generated by instrumenting Cuttlefish C++ KeyMint while running VTS
655         // tests.
656         let tests = [
657             (
658                 concat!(
659                     "0010000000d43c2f04f948521b81bdbf001310f5920000000000000000000000",
660                     "00000000000c0000006400000002000010200000000300003080000000010000",
661                     "2000000000010000200100000004000020020000000600002001000000be0200",
662                     "1000000000c1020030b0ad0100c20200307b150300bd020060a8bb52407b0100",
663                     "00ce02003011643401cf020030000000003b06b13ae6ae6671",
664                 ),
665                 KeyBlob {
666                     key_material: hex::decode("d43c2f04f948521b81bdbf001310f592").unwrap(),
667                     hw_enforced: vec![],
668                     sw_enforced: vec![
669                         KeyParameter { tag: Tag::ALGORITHM, value: KPV::Algorithm(Algorithm::AES) },
670                         KeyParameter { tag: Tag::KEY_SIZE, value: KPV::Integer(128) },
671                         KeyParameter {
672                             tag: Tag::PURPOSE,
673                             value: KPV::KeyPurpose(KeyPurpose::ENCRYPT),
674                         },
675                         KeyParameter {
676                             tag: Tag::PURPOSE,
677                             value: KPV::KeyPurpose(KeyPurpose::DECRYPT),
678                         },
679                         KeyParameter {
680                             tag: Tag::BLOCK_MODE,
681                             value: KPV::BlockMode(BlockMode::CBC),
682                         },
683                         KeyParameter {
684                             tag: Tag::PADDING,
685                             value: KPV::PaddingMode(PaddingMode::NONE),
686                         },
687                         KeyParameter { tag: Tag::ORIGIN, value: KPV::Origin(KeyOrigin::GENERATED) },
688                         KeyParameter { tag: Tag::OS_VERSION, value: KPV::Integer(110000) },
689                         KeyParameter { tag: Tag::OS_PATCHLEVEL, value: KPV::Integer(202107) },
690                         KeyParameter {
691                             tag: Tag::CREATION_DATETIME,
692                             value: KPV::DateTime(1628871769000),
693                         },
694                         KeyParameter { tag: Tag::VENDOR_PATCHLEVEL, value: KPV::Integer(20210705) },
695                         KeyParameter { tag: Tag::BOOT_PATCHLEVEL, value: KPV::Integer(0) },
696                     ],
697                 },
698                 Some(KeyFormat::RAW),
699             ),
700             (
701                 concat!(
702                     "00df0000003081dc020101044200b6ce876b947e263d61b8e3998d50dc0afb6b",
703                     "a14e46ab7ca532fbe2a379b155d0a5bb99265402857b1601fb20be6c244bf654",
704                     "e9e79413cd503eae3d9cf68ed24f47a00706052b81040023a181890381860004",
705                     "006b840f0db0b12f074ab916c7773cfa7d42967c9e5b4fae09cf999f7e116d14",
706                     "0743bdd028db0a3fcc670e721b9f00bc7fb70aa401c7d6de6582fc26962a29b7",
707                     "45e30142e90685646661550344113aaf28bdee6cb02d19df1faab4398556a909",
708                     "7d6f64b95209601a549389a311231c6cce78354f2cdbc3a904abf70686f5f0c3",
709                     "b877984d000000000000000000000000000000000c0000006400000002000010",
710                     "030000000a000010030000000100002002000000010000200300000005000020",
711                     "000000000300003009020000be02001000000000c1020030b0ad0100c2020030",
712                     "7b150300bd02006018d352407b010000ce02003011643401cf02003000000000",
713                     "2f69002e55e9b0a3"
714                 ),
715                 KeyBlob {
716                     key_material: hex::decode(concat!(
717                         "3081dc020101044200b6ce876b947e263d61b8e3998d50dc0afb6ba14e46ab7c",
718                         "a532fbe2a379b155d0a5bb99265402857b1601fb20be6c244bf654e9e79413cd",
719                         "503eae3d9cf68ed24f47a00706052b81040023a181890381860004006b840f0d",
720                         "b0b12f074ab916c7773cfa7d42967c9e5b4fae09cf999f7e116d140743bdd028",
721                         "db0a3fcc670e721b9f00bc7fb70aa401c7d6de6582fc26962a29b745e30142e9",
722                         "0685646661550344113aaf28bdee6cb02d19df1faab4398556a9097d6f64b952",
723                         "09601a549389a311231c6cce78354f2cdbc3a904abf70686f5f0c3b877984d",
724                     ))
725                     .unwrap(),
726                     hw_enforced: vec![],
727                     sw_enforced: vec![
728                         KeyParameter { tag: Tag::ALGORITHM, value: KPV::Algorithm(Algorithm::EC) },
729                         KeyParameter { tag: Tag::EC_CURVE, value: KPV::EcCurve(EcCurve::P_521) },
730                         KeyParameter {
731                             tag: Tag::PURPOSE,
732                             value: KPV::KeyPurpose(KeyPurpose::SIGN),
733                         },
734                         KeyParameter {
735                             tag: Tag::PURPOSE,
736                             value: KPV::KeyPurpose(KeyPurpose::VERIFY),
737                         },
738                         KeyParameter { tag: Tag::DIGEST, value: KPV::Digest(Digest::NONE) },
739                         KeyParameter { tag: Tag::KEY_SIZE, value: KPV::Integer(521) },
740                         KeyParameter { tag: Tag::ORIGIN, value: KPV::Origin(KeyOrigin::GENERATED) },
741                         KeyParameter { tag: Tag::OS_VERSION, value: KPV::Integer(110000) },
742                         KeyParameter { tag: Tag::OS_PATCHLEVEL, value: KPV::Integer(202107) },
743                         KeyParameter {
744                             tag: Tag::CREATION_DATETIME,
745                             value: KPV::DateTime(1628871775000),
746                         },
747                         KeyParameter { tag: Tag::VENDOR_PATCHLEVEL, value: KPV::Integer(20210705) },
748                         KeyParameter { tag: Tag::BOOT_PATCHLEVEL, value: KPV::Integer(0) },
749                     ],
750                 },
751                 Some(KeyFormat::PKCS8),
752             ),
753             (
754                 concat!(
755                     "0037000000541d4c440223650d5f51753c1abd80c725034485551e874d62327c",
756                     "65f6247a057f1218bd6c8cd7d319103ddb823fc11fb6c2c7268b5acc00000000",
757                     "0000000000000000000000000c00000064000000020000108000000003000030",
758                     "b801000001000020020000000100002003000000050000200400000008000030",
759                     "00010000be02001000000000c1020030b0ad0100c20200307b150300bd020060",
760                     "00d752407b010000ce02003011643401cf0200300000000036e6986ffc45fbb0",
761                 ),
762                 KeyBlob {
763                     key_material: hex::decode(concat!(
764                         "541d4c440223650d5f51753c1abd80c725034485551e874d62327c65f6247a05",
765                         "7f1218bd6c8cd7d319103ddb823fc11fb6c2c7268b5acc"
766                     ))
767                     .unwrap(),
768                     hw_enforced: vec![],
769                     sw_enforced: vec![
770                         KeyParameter {
771                             tag: Tag::ALGORITHM,
772                             value: KPV::Algorithm(Algorithm::HMAC),
773                         },
774                         KeyParameter { tag: Tag::KEY_SIZE, value: KPV::Integer(440) },
775                         KeyParameter {
776                             tag: Tag::PURPOSE,
777                             value: KPV::KeyPurpose(KeyPurpose::SIGN),
778                         },
779                         KeyParameter {
780                             tag: Tag::PURPOSE,
781                             value: KPV::KeyPurpose(KeyPurpose::VERIFY),
782                         },
783                         KeyParameter { tag: Tag::DIGEST, value: KPV::Digest(Digest::SHA_2_256) },
784                         KeyParameter { tag: Tag::MIN_MAC_LENGTH, value: KPV::Integer(256) },
785                         KeyParameter { tag: Tag::ORIGIN, value: KPV::Origin(KeyOrigin::GENERATED) },
786                         KeyParameter { tag: Tag::OS_VERSION, value: KPV::Integer(110000) },
787                         KeyParameter { tag: Tag::OS_PATCHLEVEL, value: KPV::Integer(202107) },
788                         KeyParameter {
789                             tag: Tag::CREATION_DATETIME,
790                             value: KPV::DateTime(1628871776000),
791                         },
792                         KeyParameter { tag: Tag::VENDOR_PATCHLEVEL, value: KPV::Integer(20210705) },
793                         KeyParameter { tag: Tag::BOOT_PATCHLEVEL, value: KPV::Integer(0) },
794                     ],
795                 },
796                 Some(KeyFormat::RAW),
797             ),
798             (
799                 concat!(
800                     "00a8040000308204a40201000282010100bc47b5c71116766669b91fa747df87",
801                     "a1963df83956569d4ac232aeba8a246c0ec73bf606374a6d07f30c2162f97082",
802                     "825c7c6e482a2841dfeaec1429d84e52c54a6b2f760dec952c9c44a3c3a80f31",
803                     "c1ced84878edd4858059071c4d20d9ab0aae978bd68c1eb448e174a9736c3973",
804                     "6838151642eda8215107375865a99a57f29467c74c40f37b0221b93ec3f4f22d",
805                     "5337c8bf9245d56936196a92b1dea315ecce8785f9fa9b7d159ca207612cc0de",
806                     "b0957d61dbba5d9bd38784f4fecbf233b04e686a340528665ecd03db8e8a09b2",
807                     "540c84e45c4a99fb338b76bba7722856b5113341c349708937228f167d238ed8",
808                     "efb9cc19547dd620f6a90d95f07e50bfe102030100010282010002f91b69d9af",
809                     "59fe87421af9ba60f15c77f9c1c90effd6634332876f8ee5a116b126f55d3703",
810                     "8bf9f588ae20c8d951d842e35c9ef35a7822d3ebf72c0b7c3e229b289ae2e178",
811                     "a848e06d558c2e03d26871ee98a35f370d461ff1c4acc39d684de680a25ec88e",
812                     "e610260e406c400bdeb2893b2d0330cb483e662fa5abd24c2b82143e85dfe30a",
813                     "e7a31f8262da2903d882b35a34a26b699ff2d812bad4b126a0065ec0e101d73a",
814                     "e6f8b29a9144eb83f54940a371fc7416c2c0370df6a41cb5391f17ba33239e1b",
815                     "4217c8db50db5c6bf77ccf621354ecc652a4f7196054c254566fd7b3bc0f3817",
816                     "d9380b190bd382aaffa37785759f285194c11a188bccde0e2e2902818100fb23",
817                     "3335770c9f3cbd4b6ede5f12d03c449b1997bce06a8249bc3de99972fd0d0a63",
818                     "3f7790d1011bf5eedee16fa45a9107a910656ecaee364ce9edb4369843be71f2",
819                     "7a74852d6c7215a6cc60d9803bcac544922f806d8e5844e0ddd914bd78009490",
820                     "4c2856d2b944fade3fb1d67d4a33fb7663a9ab660ab372c2e4868a0f45990281",
821                     "8100bfecf2bb4012e880fd065a0b088f2d757af2878d3f1305f21ce7a7158458",
822                     "18e01181ff06b2f406239fc50808ce3dbe7b68ec01174913c0f237feb3c8c7eb",
823                     "0078b77fb5b8f214b72f6d3835b1a7ebe8b132feb6cb34ab09ce22b98160fc84",
824                     "20fcbf48d1eee49f874e902f049b206a61a095f0405a4935e7c5e49757ab7b57",
825                     "298902818100ec0049383e16f3716de5fc5b2677148efe5dceb02483b43399bd",
826                     "3765559994a9f3900eed7a7e9e8f3b0eee0e660eca392e3cb736cae612f39e55",
827                     "dad696d3821def10d1f8bbca52f5e6d8e7893ffbdcb491aafdc17bebf86f84d2",
828                     "d8480ed07a7bf9209d20ef6e79429489d4cb7768281a2f7e32ec1830fd6f6332",
829                     "38f521ba764902818100b2c3ce5751580b4e51df3fb175387f5c24b79040a4d6",
830                     "603c6265f70018b441ff3aef7d8e4cd2f480ec0906f1c4c0481304e8861f9d46",
831                     "93fa48e3a9abc362859eeb343e1c5507ac94b5439ce7ac04154a2fb886a4819b",
832                     "2a57e18a2e131b412ac4a09b004766959cdf357745f003e272aab3de02e2d5bc",
833                     "2af4ed75760858ab181902818061d19c2a8dcacde104b97f7c4fae11216157c1",
834                     "c0a258d882984d12383a73dc56fe2ac93512bb321df9706ecdb2f70a44c949c4",
835                     "340a9fae64a0646cf51f37c58c08bebde91667b3b2fa7c895f7983d4786c5526",
836                     "1941b3654533b0598383ebbcffcdf28b6cf13d376e3a70b49b14d8d06e8563a2",
837                     "47f56a337e3b9845b4f2b61356000000000000000000000000000000000d0000",
838                     "007000000002000010010000000300003000080000c800005001000100000000",
839                     "0001000020020000000100002003000000050000200000000006000020010000",
840                     "00be02001000000000c1020030b0ad0100c20200307b150300bd020060a8bb52",
841                     "407b010000ce02003011643401cf02003000000000544862e9c961e857",
842                 ),
843                 KeyBlob {
844                     key_material: hex::decode(concat!(
845                         "308204a40201000282010100bc47b5c71116766669b91fa747df87a1963df839",
846                         "56569d4ac232aeba8a246c0ec73bf606374a6d07f30c2162f97082825c7c6e48",
847                         "2a2841dfeaec1429d84e52c54a6b2f760dec952c9c44a3c3a80f31c1ced84878",
848                         "edd4858059071c4d20d9ab0aae978bd68c1eb448e174a9736c39736838151642",
849                         "eda8215107375865a99a57f29467c74c40f37b0221b93ec3f4f22d5337c8bf92",
850                         "45d56936196a92b1dea315ecce8785f9fa9b7d159ca207612cc0deb0957d61db",
851                         "ba5d9bd38784f4fecbf233b04e686a340528665ecd03db8e8a09b2540c84e45c",
852                         "4a99fb338b76bba7722856b5113341c349708937228f167d238ed8efb9cc1954",
853                         "7dd620f6a90d95f07e50bfe102030100010282010002f91b69d9af59fe87421a",
854                         "f9ba60f15c77f9c1c90effd6634332876f8ee5a116b126f55d37038bf9f588ae",
855                         "20c8d951d842e35c9ef35a7822d3ebf72c0b7c3e229b289ae2e178a848e06d55",
856                         "8c2e03d26871ee98a35f370d461ff1c4acc39d684de680a25ec88ee610260e40",
857                         "6c400bdeb2893b2d0330cb483e662fa5abd24c2b82143e85dfe30ae7a31f8262",
858                         "da2903d882b35a34a26b699ff2d812bad4b126a0065ec0e101d73ae6f8b29a91",
859                         "44eb83f54940a371fc7416c2c0370df6a41cb5391f17ba33239e1b4217c8db50",
860                         "db5c6bf77ccf621354ecc652a4f7196054c254566fd7b3bc0f3817d9380b190b",
861                         "d382aaffa37785759f285194c11a188bccde0e2e2902818100fb233335770c9f",
862                         "3cbd4b6ede5f12d03c449b1997bce06a8249bc3de99972fd0d0a633f7790d101",
863                         "1bf5eedee16fa45a9107a910656ecaee364ce9edb4369843be71f27a74852d6c",
864                         "7215a6cc60d9803bcac544922f806d8e5844e0ddd914bd780094904c2856d2b9",
865                         "44fade3fb1d67d4a33fb7663a9ab660ab372c2e4868a0f459902818100bfecf2",
866                         "bb4012e880fd065a0b088f2d757af2878d3f1305f21ce7a715845818e01181ff",
867                         "06b2f406239fc50808ce3dbe7b68ec01174913c0f237feb3c8c7eb0078b77fb5",
868                         "b8f214b72f6d3835b1a7ebe8b132feb6cb34ab09ce22b98160fc8420fcbf48d1",
869                         "eee49f874e902f049b206a61a095f0405a4935e7c5e49757ab7b572989028181",
870                         "00ec0049383e16f3716de5fc5b2677148efe5dceb02483b43399bd3765559994",
871                         "a9f3900eed7a7e9e8f3b0eee0e660eca392e3cb736cae612f39e55dad696d382",
872                         "1def10d1f8bbca52f5e6d8e7893ffbdcb491aafdc17bebf86f84d2d8480ed07a",
873                         "7bf9209d20ef6e79429489d4cb7768281a2f7e32ec1830fd6f633238f521ba76",
874                         "4902818100b2c3ce5751580b4e51df3fb175387f5c24b79040a4d6603c6265f7",
875                         "0018b441ff3aef7d8e4cd2f480ec0906f1c4c0481304e8861f9d4693fa48e3a9",
876                         "abc362859eeb343e1c5507ac94b5439ce7ac04154a2fb886a4819b2a57e18a2e",
877                         "131b412ac4a09b004766959cdf357745f003e272aab3de02e2d5bc2af4ed7576",
878                         "0858ab181902818061d19c2a8dcacde104b97f7c4fae11216157c1c0a258d882",
879                         "984d12383a73dc56fe2ac93512bb321df9706ecdb2f70a44c949c4340a9fae64",
880                         "a0646cf51f37c58c08bebde91667b3b2fa7c895f7983d4786c55261941b36545",
881                         "33b0598383ebbcffcdf28b6cf13d376e3a70b49b14d8d06e8563a247f56a337e",
882                         "3b9845b4f2b61356",
883                     ))
884                     .unwrap(),
885                     hw_enforced: vec![],
886                     sw_enforced: vec![
887                         KeyParameter { tag: Tag::ALGORITHM, value: KPV::Algorithm(Algorithm::RSA) },
888                         KeyParameter { tag: Tag::KEY_SIZE, value: KPV::Integer(2048) },
889                         KeyParameter {
890                             tag: Tag::RSA_PUBLIC_EXPONENT,
891                             value: KPV::LongInteger(65537),
892                         },
893                         KeyParameter {
894                             tag: Tag::PURPOSE,
895                             value: KPV::KeyPurpose(KeyPurpose::SIGN),
896                         },
897                         KeyParameter {
898                             tag: Tag::PURPOSE,
899                             value: KPV::KeyPurpose(KeyPurpose::VERIFY),
900                         },
901                         KeyParameter { tag: Tag::DIGEST, value: KPV::Digest(Digest::NONE) },
902                         KeyParameter {
903                             tag: Tag::PADDING,
904                             value: KPV::PaddingMode(PaddingMode::NONE),
905                         },
906                         KeyParameter { tag: Tag::ORIGIN, value: KPV::Origin(KeyOrigin::GENERATED) },
907                         KeyParameter { tag: Tag::OS_VERSION, value: KPV::Integer(110000) },
908                         KeyParameter { tag: Tag::OS_PATCHLEVEL, value: KPV::Integer(202107) },
909                         KeyParameter {
910                             tag: Tag::CREATION_DATETIME,
911                             value: KPV::DateTime(1628871769000),
912                         },
913                         KeyParameter { tag: Tag::VENDOR_PATCHLEVEL, value: KPV::Integer(20210705) },
914                         KeyParameter { tag: Tag::BOOT_PATCHLEVEL, value: KPV::Integer(0) },
915                     ],
916                 },
917                 // No support for RSA keys in export_key().
918                 None,
919             ),
920         ];
921 
922         for (input, want, want_format) in tests {
923             let input = hex::decode(input).unwrap();
924             let got = KeyBlob::new_from_serialized(&input, &hidden).expect("invalid keyblob!");
925             assert!(got == want);
926 
927             if let Some(want_format) = want_format {
928                 let (got_format, _key_material, params) =
929                     export_key(&input, &[]).expect("invalid keyblob!");
930                 assert_eq!(got_format, want_format);
931                 // All the test cases are software-only keys.
932                 assert_eq!(params, got.sw_enforced);
933             }
934         }
935     }
936 
937     #[test]
test_add_der_len()938     fn test_add_der_len() {
939         let tests = [
940             (0, "00"),
941             (1, "01"),
942             (126, "7e"),
943             (127, "7f"),
944             (128, "8180"),
945             (129, "8181"),
946             (255, "81ff"),
947             (256, "820100"),
948             (257, "820101"),
949             (65535, "82ffff"),
950         ];
951         for (input, want) in tests {
952             let mut got = Vec::new();
953             add_der_len(&mut got, input).unwrap();
954             assert_eq!(hex::encode(got), want, " for input length {input}");
955         }
956     }
957 
958     #[test]
test_pkcs8_wrap_key_p256()959     fn test_pkcs8_wrap_key_p256() {
960         // Key material taken from `ec_256_key` in
961         // hardware/interfaces/security/keymint/aidl/vts/function/KeyMintTest.cpp
962         let input = hex::decode(concat!(
963             "3025",   // SEQUENCE (ECPrivateKey)
964             "020101", // INTEGER length 1 value 1 (version)
965             "0420",   // OCTET STRING (privateKey)
966             "737c2ecd7b8d1940bf2930aa9b4ed3ff",
967             "941eed09366bc03299986481f3a4d859",
968         ))
969         .unwrap();
970         let want = hex::decode(concat!(
971             // RFC 5208 s5
972             "3041",             // SEQUENCE (PrivateKeyInfo) {
973             "020100",           // INTEGER length 1 value 0 (version)
974             "3013",             // SEQUENCE length 0x13 (AlgorithmIdentifier) {
975             "0607",             // OBJECT IDENTIFIER length 7 (algorithm)
976             "2a8648ce3d0201",   // 1.2.840.10045.2.1 (ecPublicKey)
977             "0608",             // OBJECT IDENTIFIER length 8 (param)
978             "2a8648ce3d030107", //  1.2.840.10045.3.1.7 (secp256r1)
979             // } end SEQUENCE (AlgorithmIdentifier)
980             "0427",   // OCTET STRING (privateKey) holding...
981             "3025",   // SEQUENCE (ECPrivateKey)
982             "020101", // INTEGER length 1 value 1 (version)
983             "0420",   // OCTET STRING length 0x20 (privateKey)
984             "737c2ecd7b8d1940bf2930aa9b4ed3ff",
985             "941eed09366bc03299986481f3a4d859",
986             // } end SEQUENCE (ECPrivateKey)
987             // } end SEQUENCE (PrivateKeyInfo)
988         ))
989         .unwrap();
990         let got = pkcs8_wrap_nist_key(&input, EcCurve::P_256).unwrap();
991         assert_eq!(hex::encode(got), hex::encode(want), " for input {}", hex::encode(input));
992     }
993 
994     #[test]
test_pkcs8_wrap_key_p521()995     fn test_pkcs8_wrap_key_p521() {
996         // Key material taken from `ec_521_key` in
997         // hardware/interfaces/security/keymint/aidl/vts/function/KeyMintTest.cpp
998         let input = hex::decode(concat!(
999             "3047",   // SEQUENCE length 0xd3 (ECPrivateKey)
1000             "020101", // INTEGER length 1 value 1 (version)
1001             "0442",   // OCTET STRING length 0x42 (privateKey)
1002             "0011458c586db5daa92afab03f4fe46a",
1003             "a9d9c3ce9a9b7a006a8384bec4c78e8e",
1004             "9d18d7d08b5bcfa0e53c75b064ad51c4",
1005             "49bae0258d54b94b1e885ded08ed4fb2",
1006             "5ce9",
1007             // } end SEQUENCE (ECPrivateKey)
1008         ))
1009         .unwrap();
1010         let want = hex::decode(concat!(
1011             // RFC 5208 s5
1012             "3060",           // SEQUENCE (PrivateKeyInfo) {
1013             "020100",         // INTEGER length 1 value 0 (version)
1014             "3010",           // SEQUENCE length 0x10 (AlgorithmIdentifier) {
1015             "0607",           // OBJECT IDENTIFIER length 7 (algorithm)
1016             "2a8648ce3d0201", // 1.2.840.10045.2.1 (ecPublicKey)
1017             "0605",           // OBJECT IDENTIFIER length 5 (param)
1018             "2b81040023",     //  1.3.132.0.35 (secp521r1)
1019             // } end SEQUENCE (AlgorithmIdentifier)
1020             "0449",   // OCTET STRING (privateKey) holding...
1021             "3047",   // SEQUENCE (ECPrivateKey)
1022             "020101", // INTEGER length 1 value 1 (version)
1023             "0442",   // OCTET STRING length 0x42 (privateKey)
1024             "0011458c586db5daa92afab03f4fe46a",
1025             "a9d9c3ce9a9b7a006a8384bec4c78e8e",
1026             "9d18d7d08b5bcfa0e53c75b064ad51c4",
1027             "49bae0258d54b94b1e885ded08ed4fb2",
1028             "5ce9",
1029             // } end SEQUENCE (ECPrivateKey)
1030             // } end SEQUENCE (PrivateKeyInfo)
1031         ))
1032         .unwrap();
1033         let got = pkcs8_wrap_nist_key(&input, EcCurve::P_521).unwrap();
1034         assert_eq!(hex::encode(got), hex::encode(want), " for input {}", hex::encode(input));
1035     }
1036 }
1037