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(¶m.tag);
492 if let KeyParameterValue::Blob(v) = ¶m.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 ¶m.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