blob: 771d609ccbdcd9663bbbe2c1d2d85c3e18be9350 [file] [log] [blame]
Hasini Gunasinghe12486362020-07-24 18:40:20 +00001// Copyright 2020, 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
Janis Danisevskise6efb242020-12-19 13:58:01 -080015//! Key parameters are declared by KeyMint to describe properties of keys and operations.
16//! During key generation and import, key parameters are used to characterize a key, its usage
17//! restrictions, and additional parameters for attestation. During the lifetime of the key,
18//! the key characteristics are expressed as set of key parameters. During cryptographic
19//! operations, clients may specify additional operation specific parameters.
20//! This module provides a Keystore 2.0 internal representation for key parameters and
21//! implements traits to convert it from and into KeyMint KeyParameters and store it in
22//! the SQLite database.
23//!
24//! ## Synopsis
25//!
26//! enum KeyParameterValue {
27//! Invalid,
28//! Algorithm(Algorithm),
29//! ...
30//! }
31//!
32//! impl KeyParameterValue {
33//! pub fn get_tag(&self) -> Tag;
34//! pub fn new_from_sql(tag: Tag, data: &SqlField) -> Result<Self>;
Janis Danisevskis6b00e252020-12-22 11:36:45 -080035//! pub fn new_from_tag_primitive_pair<T: Into<Primitive>>(tag: Tag, v: T)
36//! -> Result<Self, PrimitiveError>;
Janis Danisevskise6efb242020-12-19 13:58:01 -080037//! fn to_sql(&self) -> SqlResult<ToSqlOutput>
38//! }
39//!
40//! use ...::keymint::KeyParameter as KmKeyParameter;
41//! impl Into<KmKeyParameter> for KeyParameterValue {}
42//! impl From<KmKeyParameter> for KeyParameterValue {}
43//!
44//! ## Implementation
Janis Danisevskis6b00e252020-12-22 11:36:45 -080045//! Each of the six functions is implemented as match statement over each key parameter variant.
Janis Danisevskise6efb242020-12-19 13:58:01 -080046//! We bootstrap these function as well as the KeyParameterValue enum itself from a single list
47//! of key parameters, that needs to be kept in sync with the KeyMint AIDL specification.
48//!
49//! The list resembles an enum declaration with a few extra fields.
50//! enum KeyParameterValue {
51//! Invalid with tag INVALID and field Invalid,
52//! Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
53//! ...
54//! }
55//! The tag corresponds to the variant of the keymint::Tag, and the field corresponds to the
56//! variant of the keymint::KeyParameterValue union. There is no one to one mapping between
57//! tags and union fields, e.g., the values of both tags BOOT_PATCHLEVEL and VENDOR_PATCHLEVEL
58//! are stored in the Integer field.
59//!
60//! The macros interpreting them all follow a similar pattern and follow the following fragment
61//! naming scheme:
62//!
63//! Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
64//! $vname $(($vtype ))? with tag $tag_name and field $field_name,
65//!
66//! Further, KeyParameterValue appears in the macro as $enum_name.
67//! Note that $vtype is optional to accommodate variants like Invalid which don't wrap a value.
68//!
69//! In some cases $vtype is not part of the expansion, but we still have to modify the expansion
70//! depending on the presence of $vtype. In these cases we recurse through the list following the
71//! following pattern:
72//!
73//! (@<marker> <non repeating args>, [<out list>], [<in list>])
74//!
75//! These macros usually have four rules:
76//! * Two main recursive rules, of the form:
77//! (
78//! @<marker>
79//! <non repeating args>,
80//! [<out list>],
81//! [<one element pattern> <in tail>]
82//! ) => {
83//! macro!{@<marker> <non repeating args>, [<out list>
84//! <one element expansion>
85//! ], [<in tail>]}
86//! };
87//! They pop one element off the <in list> and add one expansion to the out list.
88//! The element expansion is kept on a separate line (or lines) for better readability.
89//! The two variants differ in whether or not $vtype is expected.
90//! * The termination condition which has an empty in list.
91//! * The public interface, which does not have @marker and calls itself with an empty out list.
Hasini Gunasinghe12486362020-07-24 18:40:20 +000092
Janis Danisevskis6b00e252020-12-22 11:36:45 -080093use std::convert::TryInto;
94
Janis Danisevskis030ba022021-05-26 11:15:30 -070095use crate::database::utils::SqlField;
Hasini Gunasingheaf993662020-07-24 18:40:20 +000096use crate::error::Error as KeystoreError;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070097use crate::error::ResponseCode;
98
Shawn Willden708744a2020-12-11 13:05:27 +000099pub use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700100 Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
101 HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800102 KeyParameter::KeyParameter as KmKeyParameter,
103 KeyParameterValue::KeyParameterValue as KmKeyParameterValue, KeyPurpose::KeyPurpose,
104 PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000105};
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700106use android_system_keystore2::aidl::android::system::keystore2::Authorization::Authorization;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000107use anyhow::{Context, Result};
Janis Danisevskis4522c2b2020-11-27 18:04:58 -0800108use rusqlite::types::{Null, ToSql, ToSqlOutput};
109use rusqlite::Result as SqlResult;
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000110
Janis Danisevskise6efb242020-12-19 13:58:01 -0800111/// This trait is used to associate a primitive to any type that can be stored inside a
112/// KeyParameterValue, especially the AIDL enum types, e.g., keymint::{Algorithm, Digest, ...}.
113/// This allows for simplifying the macro rules, e.g., for reading from the SQL database.
114/// An expression like `KeyParameterValue::Algorithm(row.get(0))` would not work because
115/// a type of `Algorithm` is expected which does not implement `FromSql` and we cannot
116/// implement it because we own neither the type nor the trait.
117/// With AssociatePrimitive we can write an expression
118/// `KeyParameter::Algorithm(<Algorithm>::from_primitive(row.get(0)))` to inform `get`
119/// about the expected primitive type that it can convert into. By implementing this
120/// trait for all inner types we can write a single rule to cover all cases (except where
121/// there is no wrapped type):
122/// `KeyParameterValue::$vname(<$vtype>::from_primitive(row.get(0)))`
123trait AssociatePrimitive {
124 type Primitive;
125
126 fn from_primitive(v: Self::Primitive) -> Self;
127 fn to_primitive(&self) -> Self::Primitive;
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000128}
129
Janis Danisevskise6efb242020-12-19 13:58:01 -0800130/// Associates the given type with i32. The macro assumes that the given type is actually a
131/// tuple struct wrapping i32, such as AIDL enum types.
132macro_rules! implement_associate_primitive_for_aidl_enum {
133 ($t:ty) => {
134 impl AssociatePrimitive for $t {
135 type Primitive = i32;
136
137 fn from_primitive(v: Self::Primitive) -> Self {
138 Self(v)
139 }
140 fn to_primitive(&self) -> Self::Primitive {
141 self.0
142 }
143 }
144 };
145}
146
147/// Associates the given type with itself.
148macro_rules! implement_associate_primitive_identity {
149 ($t:ty) => {
150 impl AssociatePrimitive for $t {
151 type Primitive = $t;
152
153 fn from_primitive(v: Self::Primitive) -> Self {
154 v
155 }
156 fn to_primitive(&self) -> Self::Primitive {
157 self.clone()
158 }
159 }
160 };
161}
162
163implement_associate_primitive_for_aidl_enum! {Algorithm}
164implement_associate_primitive_for_aidl_enum! {BlockMode}
165implement_associate_primitive_for_aidl_enum! {Digest}
166implement_associate_primitive_for_aidl_enum! {EcCurve}
167implement_associate_primitive_for_aidl_enum! {HardwareAuthenticatorType}
168implement_associate_primitive_for_aidl_enum! {KeyOrigin}
169implement_associate_primitive_for_aidl_enum! {KeyPurpose}
170implement_associate_primitive_for_aidl_enum! {PaddingMode}
171implement_associate_primitive_for_aidl_enum! {SecurityLevel}
172
173implement_associate_primitive_identity! {Vec<u8>}
174implement_associate_primitive_identity! {i64}
175implement_associate_primitive_identity! {i32}
176
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800177/// This enum allows passing a primitive value to `KeyParameterValue::new_from_tag_primitive_pair`
178/// Usually, it is not necessary to use this type directly because the function uses
179/// `Into<Primitive>` as a trait bound.
180pub enum Primitive {
181 /// Wraps an i64.
182 I64(i64),
183 /// Wraps an i32.
184 I32(i32),
185 /// Wraps a Vec<u8>.
186 Vec(Vec<u8>),
187}
188
189impl From<i64> for Primitive {
190 fn from(v: i64) -> Self {
191 Self::I64(v)
192 }
193}
194impl From<i32> for Primitive {
195 fn from(v: i32) -> Self {
196 Self::I32(v)
197 }
198}
199impl From<Vec<u8>> for Primitive {
200 fn from(v: Vec<u8>) -> Self {
201 Self::Vec(v)
202 }
203}
204
205/// This error is returned by `KeyParameterValue::new_from_tag_primitive_pair`.
206#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
207pub enum PrimitiveError {
208 /// Returned if this primitive is unsuitable for the given tag type.
209 #[error("Primitive does not match the expected tag type.")]
210 TypeMismatch,
211 /// Return if the tag type is unknown.
212 #[error("Unknown tag.")]
213 UnknownTag,
214}
215
216impl TryInto<i64> for Primitive {
217 type Error = PrimitiveError;
218
219 fn try_into(self) -> Result<i64, Self::Error> {
220 match self {
221 Self::I64(v) => Ok(v),
222 _ => Err(Self::Error::TypeMismatch),
223 }
224 }
225}
226impl TryInto<i32> for Primitive {
227 type Error = PrimitiveError;
228
229 fn try_into(self) -> Result<i32, Self::Error> {
230 match self {
231 Self::I32(v) => Ok(v),
232 _ => Err(Self::Error::TypeMismatch),
233 }
234 }
235}
236impl TryInto<Vec<u8>> for Primitive {
237 type Error = PrimitiveError;
238
239 fn try_into(self) -> Result<Vec<u8>, Self::Error> {
240 match self {
241 Self::Vec(v) => Ok(v),
242 _ => Err(Self::Error::TypeMismatch),
243 }
244 }
245}
246
247/// Expands the list of KeyParameterValue variants as follows:
248///
249/// Input:
250/// Invalid with tag INVALID and field Invalid,
251/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
252///
253/// Output:
254/// ```
255/// pub fn new_from_tag_primitive_pair<T: Into<Primitive>>(
256/// tag: Tag,
257/// v: T
258/// ) -> Result<KeyParameterValue, PrimitiveError> {
259/// let p: Primitive = v.into();
260/// Ok(match tag {
261/// Tag::INVALID => KeyParameterValue::Invalid,
262/// Tag::ALGORITHM => KeyParameterValue::Algorithm(
263/// <Algorithm>::from_primitive(p.try_into()?)
264/// ),
265/// _ => return Err(PrimitiveError::UnknownTag),
266/// })
267/// }
268/// ```
269macro_rules! implement_from_tag_primitive_pair {
270 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
271 /// Returns the an instance of $enum_name or an error if the given primitive does not match
272 /// the tag type or the tag is unknown.
273 pub fn new_from_tag_primitive_pair<T: Into<Primitive>>(
274 tag: Tag,
275 v: T
276 ) -> Result<$enum_name, PrimitiveError> {
277 let p: Primitive = v.into();
278 Ok(match tag {
279 $(Tag::$tag_name => $enum_name::$vname$((
280 <$vtype>::from_primitive(p.try_into()?)
281 ))?,)*
282 _ => return Err(PrimitiveError::UnknownTag),
283 })
284 }
285 };
286}
287
Janis Danisevskise6efb242020-12-19 13:58:01 -0800288/// Expands the list of KeyParameterValue variants as follows:
289///
290/// Input:
291/// pub enum KeyParameterValue {
292/// Invalid with tag INVALID and field Invalid,
293/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
294/// }
295///
296/// Output:
297/// ```
298/// pub enum KeyParameterValue {
299/// Invalid,
300/// Algorithm(Algorithm),
301/// }
302/// ```
303macro_rules! implement_enum {
304 (
305 $(#[$enum_meta:meta])*
306 $enum_vis:vis enum $enum_name:ident {
307 $($(#[$emeta:meta])* $vname:ident$(($vtype:ty))?),* $(,)?
308 }
309 ) => {
310 $(#[$enum_meta])*
311 $enum_vis enum $enum_name {
312 $(
313 $(#[$emeta])*
314 $vname$(($vtype))?
315 ),*
316 }
317 };
318}
319
320/// Expands the list of KeyParameterValue variants as follows:
321///
322/// Input:
323/// Invalid with tag INVALID and field Invalid,
324/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
325///
326/// Output:
327/// ```
328/// pub fn get_tag(&self) -> Tag {
329/// match self {
330/// KeyParameterValue::Invalid => Tag::INVALID,
331/// KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
332/// }
333/// }
334/// ```
335macro_rules! implement_get_tag {
336 (
337 @replace_type_spec
338 $enum_name:ident,
339 [$($out:tt)*],
340 [$vname:ident($vtype:ty) $tag_name:ident, $($in:tt)*]
341 ) => {
342 implement_get_tag!{@replace_type_spec $enum_name, [$($out)*
343 $enum_name::$vname(_) => Tag::$tag_name,
344 ], [$($in)*]}
345 };
346 (
347 @replace_type_spec
348 $enum_name:ident,
349 [$($out:tt)*],
350 [$vname:ident $tag_name:ident, $($in:tt)*]
351 ) => {
352 implement_get_tag!{@replace_type_spec $enum_name, [$($out)*
353 $enum_name::$vname => Tag::$tag_name,
354 ], [$($in)*]}
355 };
356 (@replace_type_spec $enum_name:ident, [$($out:tt)*], []) => {
357 /// Returns the tag of the given instance.
358 pub fn get_tag(&self) -> Tag {
359 match self {
360 $($out)*
361 }
362 }
363 };
364
365 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
366 implement_get_tag!{@replace_type_spec $enum_name, [], [$($vname$(($vtype))? $tag_name,)*]}
367 };
368}
369
370/// Expands the list of KeyParameterValue variants as follows:
371///
372/// Input:
373/// Invalid with tag INVALID and field Invalid,
374/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
375///
376/// Output:
377/// ```
378/// fn to_sql(&self) -> SqlResult<ToSqlOutput> {
379/// match self {
380/// KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
381/// KeyParameterValue::Algorithm(v) => Ok(ToSqlOutput::from(v.to_primitive())),
382/// }
383/// }
384/// ```
385macro_rules! implement_to_sql {
386 (
387 @replace_type_spec
388 $enum_name:ident,
389 [$($out:tt)*],
390 [$vname:ident($vtype:ty), $($in:tt)*]
391 ) => {
392 implement_to_sql!{@replace_type_spec $enum_name, [ $($out)*
393 $enum_name::$vname(v) => Ok(ToSqlOutput::from(v.to_primitive())),
394 ], [$($in)*]}
395 };
396 (
397 @replace_type_spec
398 $enum_name:ident,
399 [$($out:tt)*],
400 [$vname:ident, $($in:tt)*]
401 ) => {
402 implement_to_sql!{@replace_type_spec $enum_name, [ $($out)*
403 $enum_name::$vname => Ok(ToSqlOutput::from(Null)),
404 ], [$($in)*]}
405 };
406 (@replace_type_spec $enum_name:ident, [$($out:tt)*], []) => {
407 /// Converts $enum_name to be stored in a rusqlite database.
408 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
409 match self {
410 $($out)*
411 }
412 }
413 };
414
415
416 ($enum_name:ident; $($vname:ident$(($vtype:ty))?),*) => {
417 impl ToSql for $enum_name {
418 implement_to_sql!{@replace_type_spec $enum_name, [], [$($vname$(($vtype))?,)*]}
419 }
420
421 }
422}
423
424/// Expands the list of KeyParameterValue variants as follows:
425///
426/// Input:
427/// Invalid with tag INVALID and field Invalid,
428/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
429///
430/// Output:
431/// ```
432/// pub fn new_from_sql(
433/// tag: Tag,
434/// data: &SqlField,
435/// ) -> Result<Self> {
436/// Ok(match self {
437/// Tag::Invalid => KeyParameterValue::Invalid,
438/// Tag::ALGORITHM => {
439/// KeyParameterValue::Algorithm(<Algorithm>::from_primitive(data
440/// .get()
441/// .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
442/// .context(concat!("Failed to read sql data for tag: ", "ALGORITHM", "."))?
443/// ))
444/// },
445/// })
446/// }
447/// ```
448macro_rules! implement_new_from_sql {
449 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
450 /// Takes a tag and an SqlField and attempts to construct a KeyParameter value.
451 /// This function may fail if the parameter value cannot be extracted from the
452 /// database cell.
453 pub fn new_from_sql(
454 tag: Tag,
455 data: &SqlField,
456 ) -> Result<Self> {
457 Ok(match tag {
458 $(
459 Tag::$tag_name => {
460 $enum_name::$vname$((<$vtype>::from_primitive(data
461 .get()
462 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
463 .context(concat!(
464 "Failed to read sql data for tag: ",
465 stringify!($tag_name),
466 "."
467 ))?
468 )))?
469 },
470 )*
471 _ => $enum_name::Invalid,
472 })
473 }
474 };
475}
476
477/// This key parameter default is used during the conversion from KeyParameterValue
478/// to keymint::KeyParameterValue. Keystore's version does not have wrapped types
479/// for boolean tags and the tag Invalid. The AIDL version uses bool and integer
480/// variants respectively. This default function is invoked in these cases to
481/// homogenize the rules for boolean and invalid tags.
482/// The bool variant returns true because boolean parameters are implicitly true
483/// if present.
484trait KpDefault {
485 fn default() -> Self;
486}
487
488impl KpDefault for i32 {
489 fn default() -> Self {
490 0
491 }
492}
493
494impl KpDefault for bool {
495 fn default() -> Self {
496 true
497 }
498}
499
500/// Expands the list of KeyParameterValue variants as follows:
501///
502/// Input:
503/// Invalid with tag INVALID and field Invalid,
504/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
505///
506/// Output:
507/// ```
508/// impl From<KmKeyParameter> for KeyParameterValue {
509/// fn from(kp: KmKeyParameter) -> Self {
510/// match kp {
511/// KmKeyParameter { tag: Tag::INVALID, value: KmKeyParameterValue::Invalid(_) }
512/// => $enum_name::$vname,
513/// KmKeyParameter { tag: Tag::Algorithm, value: KmKeyParameterValue::Algorithm(v) }
514/// => $enum_name::Algorithm(v),
515/// _ => $enum_name::Invalid,
516/// }
517/// }
518/// }
519///
520/// impl Into<KmKeyParameter> for KeyParameterValue {
521/// fn into(self) -> KmKeyParameter {
522/// match self {
523/// KeyParameterValue::Invalid => KmKeyParameter {
524/// tag: Tag::INVALID,
525/// value: KmKeyParameterValue::Invalid(KpDefault::default())
526/// },
527/// KeyParameterValue::Algorithm(v) => KmKeyParameter {
528/// tag: Tag::ALGORITHM,
529/// value: KmKeyParameterValue::Algorithm(v)
530/// },
531/// }
532/// }
533/// }
534/// ```
535macro_rules! implement_try_from_to_km_parameter {
536 // The first three rules expand From<KmKeyParameter>.
537 (
538 @from
539 $enum_name:ident,
540 [$($out:tt)*],
541 [$vname:ident($vtype:ty) $tag_name:ident $field_name:ident, $($in:tt)*]
542 ) => {
543 implement_try_from_to_km_parameter!{@from $enum_name, [$($out)*
544 KmKeyParameter {
545 tag: Tag::$tag_name,
546 value: KmKeyParameterValue::$field_name(v)
547 } => $enum_name::$vname(v),
548 ], [$($in)*]
549 }};
550 (
551 @from
552 $enum_name:ident,
553 [$($out:tt)*],
554 [$vname:ident $tag_name:ident $field_name:ident, $($in:tt)*]
555 ) => {
556 implement_try_from_to_km_parameter!{@from $enum_name, [$($out)*
557 KmKeyParameter {
558 tag: Tag::$tag_name,
559 value: KmKeyParameterValue::$field_name(_)
560 } => $enum_name::$vname,
561 ], [$($in)*]
562 }};
563 (@from $enum_name:ident, [$($out:tt)*], []) => {
564 impl From<KmKeyParameter> for $enum_name {
565 fn from(kp: KmKeyParameter) -> Self {
566 match kp {
567 $($out)*
568 _ => $enum_name::Invalid,
569 }
570 }
571 }
572 };
573
574 // The next three rules expand Into<KmKeyParameter>.
575 (
576 @into
577 $enum_name:ident,
578 [$($out:tt)*],
579 [$vname:ident($vtype:ty) $tag_name:ident $field_name:ident, $($in:tt)*]
580 ) => {
581 implement_try_from_to_km_parameter!{@into $enum_name, [$($out)*
582 $enum_name::$vname(v) => KmKeyParameter {
583 tag: Tag::$tag_name,
584 value: KmKeyParameterValue::$field_name(v)
585 },
586 ], [$($in)*]
587 }};
588 (
589 @into
590 $enum_name:ident,
591 [$($out:tt)*],
592 [$vname:ident $tag_name:ident $field_name:ident, $($in:tt)*]
593 ) => {
594 implement_try_from_to_km_parameter!{@into $enum_name, [$($out)*
595 $enum_name::$vname => KmKeyParameter {
596 tag: Tag::$tag_name,
597 value: KmKeyParameterValue::$field_name(KpDefault::default())
598 },
599 ], [$($in)*]
600 }};
601 (@into $enum_name:ident, [$($out:tt)*], []) => {
Matthew Maurerb77a28d2021-05-07 16:08:20 -0700602 impl From<$enum_name> for KmKeyParameter {
603 fn from(x: $enum_name) -> Self {
604 match x {
Janis Danisevskise6efb242020-12-19 13:58:01 -0800605 $($out)*
606 }
607 }
608 }
609 };
610
611
612 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident $field_name:ident),*) => {
613 implement_try_from_to_km_parameter!(
614 @from $enum_name,
615 [],
616 [$($vname$(($vtype))? $tag_name $field_name,)*]
617 );
618 implement_try_from_to_km_parameter!(
619 @into $enum_name,
620 [],
621 [$($vname$(($vtype))? $tag_name $field_name,)*]
622 );
623 };
624}
625
626/// This is the top level macro. While the other macros do most of the heavy lifting, this takes
627/// the key parameter list and passes it on to the other macros to generate all of the conversion
628/// functions. In addition, it generates an important test vector for verifying that tag type of the
629/// keymint tag matches the associated keymint KeyParameterValue field.
630macro_rules! implement_key_parameter_value {
631 (
632 $(#[$enum_meta:meta])*
633 $enum_vis:vis enum $enum_name:ident {
634 $(
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800635 $(#[$($emeta:tt)+])*
636 $vname:ident$(($vtype:ty))?
Janis Danisevskise6efb242020-12-19 13:58:01 -0800637 ),* $(,)?
638 }
639 ) => {
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800640 implement_key_parameter_value!{
641 @extract_attr
642 $(#[$enum_meta])*
643 $enum_vis enum $enum_name {
644 []
645 [$(
646 [] [$(#[$($emeta)+])*]
647 $vname$(($vtype))?,
648 )*]
649 }
650 }
651 };
652
653 (
654 @extract_attr
655 $(#[$enum_meta:meta])*
656 $enum_vis:vis enum $enum_name:ident {
657 [$($out:tt)*]
658 [
659 [$(#[$mout:meta])*]
660 [
661 #[key_param(tag = $tag_name:ident, field = $field_name:ident)]
662 $(#[$($mtail:tt)+])*
663 ]
664 $vname:ident$(($vtype:ty))?,
665 $($tail:tt)*
666 ]
667 }
668 ) => {
669 implement_key_parameter_value!{
670 @extract_attr
671 $(#[$enum_meta])*
672 $enum_vis enum $enum_name {
673 [
674 $($out)*
675 $(#[$mout])*
676 $(#[$($mtail)+])*
677 $tag_name $field_name $vname$(($vtype))?,
678 ]
679 [$($tail)*]
680 }
681 }
682 };
683
684 (
685 @extract_attr
686 $(#[$enum_meta:meta])*
687 $enum_vis:vis enum $enum_name:ident {
688 [$($out:tt)*]
689 [
690 [$(#[$mout:meta])*]
691 [
692 #[$front:meta]
693 $(#[$($mtail:tt)+])*
694 ]
695 $vname:ident$(($vtype:ty))?,
696 $($tail:tt)*
697 ]
698 }
699 ) => {
700 implement_key_parameter_value!{
701 @extract_attr
702 $(#[$enum_meta])*
703 $enum_vis enum $enum_name {
704 [$($out)*]
705 [
706 [
707 $(#[$mout])*
708 #[$front]
709 ]
710 [$(#[$($mtail)+])*]
711 $vname$(($vtype))?,
712 $($tail)*
713 ]
714 }
715 }
716 };
717
718 (
719 @extract_attr
720 $(#[$enum_meta:meta])*
721 $enum_vis:vis enum $enum_name:ident {
722 [$($out:tt)*]
723 []
724 }
725 ) => {
726 implement_key_parameter_value!{
727 @spill
728 $(#[$enum_meta])*
729 $enum_vis enum $enum_name {
730 $($out)*
731 }
732 }
733 };
734
735 (
736 @spill
737 $(#[$enum_meta:meta])*
738 $enum_vis:vis enum $enum_name:ident {
739 $(
740 $(#[$emeta:meta])*
741 $tag_name:ident $field_name:ident $vname:ident$(($vtype:ty))?,
742 )*
743 }
744 ) => {
Janis Danisevskise6efb242020-12-19 13:58:01 -0800745 implement_enum!(
746 $(#[$enum_meta])*
747 $enum_vis enum $enum_name {
748 $(
749 $(#[$emeta])*
750 $vname$(($vtype))?
751 ),*
752 });
753
754 impl $enum_name {
755 implement_new_from_sql!($enum_name; $($vname$(($vtype))? $tag_name),*);
756 implement_get_tag!($enum_name; $($vname$(($vtype))? $tag_name),*);
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800757 implement_from_tag_primitive_pair!($enum_name; $($vname$(($vtype))? $tag_name),*);
Janis Danisevskise6efb242020-12-19 13:58:01 -0800758
759 #[cfg(test)]
760 fn make_field_matches_tag_type_test_vector() -> Vec<KmKeyParameter> {
761 vec![$(KmKeyParameter{
762 tag: Tag::$tag_name,
763 value: KmKeyParameterValue::$field_name(Default::default())}
764 ),*]
765 }
766 }
767
768 implement_try_from_to_km_parameter!(
769 $enum_name;
770 $($vname$(($vtype))? $tag_name $field_name),*
771 );
772
773 implement_to_sql!($enum_name; $($vname$(($vtype))?),*);
774 };
775}
776
777implement_key_parameter_value! {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000778/// KeyParameterValue holds a value corresponding to one of the Tags defined in
Shawn Willden525c0032021-03-29 13:58:33 +0000779/// the AIDL spec at hardware/interfaces/security/keymint
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700780#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000781pub enum KeyParameterValue {
782 /// Associated with Tag:INVALID
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800783 #[key_param(tag = INVALID, field = Invalid)]
784 Invalid,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000785 /// Set of purposes for which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800786 #[key_param(tag = PURPOSE, field = KeyPurpose)]
787 KeyPurpose(KeyPurpose),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000788 /// Cryptographic algorithm with which the key is used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800789 #[key_param(tag = ALGORITHM, field = Algorithm)]
790 Algorithm(Algorithm),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000791 /// Size of the key , in bits
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800792 #[key_param(tag = KEY_SIZE, field = Integer)]
793 KeySize(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000794 /// Block cipher mode(s) with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800795 #[key_param(tag = BLOCK_MODE, field = BlockMode)]
796 BlockMode(BlockMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000797 /// Digest algorithms that may be used with the key to perform signing and verification
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800798 #[key_param(tag = DIGEST, field = Digest)]
799 Digest(Digest),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000800 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800801 #[key_param(tag = PADDING, field = PaddingMode)]
802 PaddingMode(PaddingMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000803 /// Can the caller provide a nonce for nonce-requiring operations
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800804 #[key_param(tag = CALLER_NONCE, field = BoolValue)]
805 CallerNonce,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000806 /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800807 #[key_param(tag = MIN_MAC_LENGTH, field = Integer)]
808 MinMacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000809 /// The elliptic curve
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800810 #[key_param(tag = EC_CURVE, field = EcCurve)]
811 EcCurve(EcCurve),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000812 /// Value of the public exponent for an RSA key pair
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800813 #[key_param(tag = RSA_PUBLIC_EXPONENT, field = LongInteger)]
814 RSAPublicExponent(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000815 /// An attestation certificate for the generated key should contain an application-scoped
816 /// and time-bounded device-unique ID
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800817 #[key_param(tag = INCLUDE_UNIQUE_ID, field = BoolValue)]
818 IncludeUniqueID,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000819 //TODO: find out about this
820 // /// Necessary system environment conditions for the generated key to be used
821 // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000822 /// Only the boot loader can use the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800823 #[key_param(tag = BOOTLOADER_ONLY, field = BoolValue)]
824 BootLoaderOnly,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000825 /// When deleted, the key is guaranteed to be permanently deleted and unusable
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800826 #[key_param(tag = ROLLBACK_RESISTANCE, field = BoolValue)]
827 RollbackResistance,
Janis Danisevskis5c748212021-05-17 17:13:56 -0700828 /// The Key shall only be used during the early boot stage
829 #[key_param(tag = EARLY_BOOT_ONLY, field = BoolValue)]
830 EarlyBootOnly,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000831 /// The date and time at which the key becomes active
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800832 #[key_param(tag = ACTIVE_DATETIME, field = DateTime)]
833 ActiveDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000834 /// The date and time at which the key expires for signing and encryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800835 #[key_param(tag = ORIGINATION_EXPIRE_DATETIME, field = DateTime)]
836 OriginationExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000837 /// The date and time at which the key expires for verification and decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800838 #[key_param(tag = USAGE_EXPIRE_DATETIME, field = DateTime)]
839 UsageExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000840 /// Minimum amount of time that elapses between allowed operations
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800841 #[key_param(tag = MIN_SECONDS_BETWEEN_OPS, field = Integer)]
842 MinSecondsBetweenOps(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000843 /// Maximum number of times that a key may be used between system reboots
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800844 #[key_param(tag = MAX_USES_PER_BOOT, field = Integer)]
845 MaxUsesPerBoot(i32),
Qi Wub9433b52020-12-01 14:52:46 +0800846 /// The number of times that a limited use key can be used
847 #[key_param(tag = USAGE_COUNT_LIMIT, field = Integer)]
848 UsageCountLimit(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000849 /// ID of the Android user that is permitted to use the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800850 #[key_param(tag = USER_ID, field = Integer)]
851 UserID(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000852 /// A key may only be used under a particular secure user authentication state
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800853 #[key_param(tag = USER_SECURE_ID, field = LongInteger)]
854 UserSecureID(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000855 /// No authentication is required to use this key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800856 #[key_param(tag = NO_AUTH_REQUIRED, field = BoolValue)]
857 NoAuthRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000858 /// The types of user authenticators that may be used to authorize this key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800859 #[key_param(tag = USER_AUTH_TYPE, field = HardwareAuthenticatorType)]
860 HardwareAuthenticatorType(HardwareAuthenticatorType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000861 /// The time in seconds for which the key is authorized for use, after user authentication
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800862 #[key_param(tag = AUTH_TIMEOUT, field = Integer)]
863 AuthTimeout(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000864 /// The key may be used after authentication timeout if device is still on-body
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800865 #[key_param(tag = ALLOW_WHILE_ON_BODY, field = BoolValue)]
866 AllowWhileOnBody,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000867 /// The key must be unusable except when the user has provided proof of physical presence
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800868 #[key_param(tag = TRUSTED_USER_PRESENCE_REQUIRED, field = BoolValue)]
869 TrustedUserPresenceRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000870 /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
871 /// unless the user provides confirmation of the data to be signed
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800872 #[key_param(tag = TRUSTED_CONFIRMATION_REQUIRED, field = BoolValue)]
873 TrustedConfirmationRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000874 /// The key may only be used when the device is unlocked
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800875 #[key_param(tag = UNLOCKED_DEVICE_REQUIRED, field = BoolValue)]
876 UnlockedDeviceRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000877 /// When provided to generateKey or importKey, this tag specifies data
878 /// that is necessary during all uses of the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800879 #[key_param(tag = APPLICATION_ID, field = Blob)]
880 ApplicationID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000881 /// When provided to generateKey or importKey, this tag specifies data
882 /// that is necessary during all uses of the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800883 #[key_param(tag = APPLICATION_DATA, field = Blob)]
884 ApplicationData(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000885 /// Specifies the date and time the key was created
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800886 #[key_param(tag = CREATION_DATETIME, field = DateTime)]
887 CreationDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000888 /// Specifies where the key was created, if known
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800889 #[key_param(tag = ORIGIN, field = Origin)]
890 KeyOrigin(KeyOrigin),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000891 /// The key used by verified boot to validate the operating system booted
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800892 #[key_param(tag = ROOT_OF_TRUST, field = Blob)]
893 RootOfTrust(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000894 /// System OS version with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800895 #[key_param(tag = OS_VERSION, field = Integer)]
896 OSVersion(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000897 /// Specifies the system security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800898 #[key_param(tag = OS_PATCHLEVEL, field = Integer)]
899 OSPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000900 /// Specifies a unique, time-based identifier
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800901 #[key_param(tag = UNIQUE_ID, field = Blob)]
902 UniqueID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000903 /// Used to deliver a "challenge" value to the attestKey() method
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800904 #[key_param(tag = ATTESTATION_CHALLENGE, field = Blob)]
905 AttestationChallenge(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000906 /// The set of applications which may use a key, used only with attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800907 #[key_param(tag = ATTESTATION_APPLICATION_ID, field = Blob)]
908 AttestationApplicationID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000909 /// Provides the device's brand name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800910 #[key_param(tag = ATTESTATION_ID_BRAND, field = Blob)]
911 AttestationIdBrand(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000912 /// Provides the device's device name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800913 #[key_param(tag = ATTESTATION_ID_DEVICE, field = Blob)]
914 AttestationIdDevice(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000915 /// Provides the device's product name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800916 #[key_param(tag = ATTESTATION_ID_PRODUCT, field = Blob)]
917 AttestationIdProduct(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000918 /// Provides the device's serial number, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800919 #[key_param(tag = ATTESTATION_ID_SERIAL, field = Blob)]
920 AttestationIdSerial(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000921 /// Provides the IMEIs for all radios on the device, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800922 #[key_param(tag = ATTESTATION_ID_IMEI, field = Blob)]
923 AttestationIdIMEI(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000924 /// Provides the MEIDs for all radios on the device, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800925 #[key_param(tag = ATTESTATION_ID_MEID, field = Blob)]
926 AttestationIdMEID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000927 /// Provides the device's manufacturer name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800928 #[key_param(tag = ATTESTATION_ID_MANUFACTURER, field = Blob)]
929 AttestationIdManufacturer(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000930 /// Provides the device's model name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800931 #[key_param(tag = ATTESTATION_ID_MODEL, field = Blob)]
932 AttestationIdModel(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000933 /// Specifies the vendor image security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800934 #[key_param(tag = VENDOR_PATCHLEVEL, field = Integer)]
935 VendorPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000936 /// Specifies the boot image (kernel) security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800937 #[key_param(tag = BOOT_PATCHLEVEL, field = Integer)]
938 BootPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000939 /// Provides "associated data" for AES-GCM encryption or decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800940 #[key_param(tag = ASSOCIATED_DATA, field = Blob)]
941 AssociatedData(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000942 /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
943 /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800944 #[key_param(tag = NONCE, field = Blob)]
945 Nonce(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000946 /// Provides the requested length of a MAC or GCM authentication tag, in bits
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800947 #[key_param(tag = MAC_LENGTH, field = Integer)]
948 MacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000949 /// Specifies whether the device has been factory reset since the
950 /// last unique ID rotation. Used for key attestation
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800951 #[key_param(tag = RESET_SINCE_ID_ROTATION, field = BoolValue)]
952 ResetSinceIdRotation,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000953 /// Used to deliver a cryptographic token proving that the user
Janis Danisevskis2c084012021-01-31 22:23:17 -0800954 /// confirmed a signing request
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800955 #[key_param(tag = CONFIRMATION_TOKEN, field = Blob)]
956 ConfirmationToken(Vec<u8>),
Janis Danisevskis2c084012021-01-31 22:23:17 -0800957 /// Used to deliver the certificate serial number to the KeyMint instance
958 /// certificate generation.
959 #[key_param(tag = CERTIFICATE_SERIAL, field = Blob)]
960 CertificateSerial(Vec<u8>),
961 /// Used to deliver the certificate subject to the KeyMint instance
962 /// certificate generation. This must be DER encoded X509 name.
963 #[key_param(tag = CERTIFICATE_SUBJECT, field = Blob)]
964 CertificateSubject(Vec<u8>),
965 /// Used to deliver the not before date in milliseconds to KeyMint during key generation/import.
966 #[key_param(tag = CERTIFICATE_NOT_BEFORE, field = DateTime)]
967 CertificateNotBefore(i64),
968 /// Used to deliver the not after date in milliseconds to KeyMint during key generation/import.
969 #[key_param(tag = CERTIFICATE_NOT_AFTER, field = DateTime)]
970 CertificateNotAfter(i64),
Paul Crowley7c57bf12021-02-02 16:26:57 -0800971 /// Specifies a maximum boot level at which a key should function
972 #[key_param(tag = MAX_BOOT_LEVEL, field = Integer)]
973 MaxBootLevel(i32),
Janis Danisevskise6efb242020-12-19 13:58:01 -0800974}
975}
976
977impl From<&KmKeyParameter> for KeyParameterValue {
978 fn from(kp: &KmKeyParameter) -> Self {
979 kp.clone().into()
980 }
981}
982
983/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
984#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
985pub struct KeyParameter {
986 value: KeyParameterValue,
987 security_level: SecurityLevel,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000988}
989
990impl KeyParameter {
991 /// Create an instance of KeyParameter, given the value and the security level.
Janis Danisevskise6efb242020-12-19 13:58:01 -0800992 pub fn new(value: KeyParameterValue, security_level: SecurityLevel) -> Self {
993 KeyParameter { value, security_level }
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000994 }
995
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000996 /// Construct a KeyParameter from the data from a rusqlite row.
997 /// Note that following variants of KeyParameterValue should not be stored:
998 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
999 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
1000 /// This filtering is enforced at a higher level and here we support conversion for all the
1001 /// variants.
1002 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001003 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001004 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001005 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001006 ) -> Result<Self> {
Janis Danisevskise6efb242020-12-19 13:58:01 -08001007 Ok(Self {
1008 value: KeyParameterValue::new_from_sql(tag_val, data)?,
1009 security_level: security_level_val,
1010 })
1011 }
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001012
Janis Danisevskise6efb242020-12-19 13:58:01 -08001013 /// Get the KeyMint Tag of this this key parameter.
1014 pub fn get_tag(&self) -> Tag {
1015 self.value.get_tag()
1016 }
1017
1018 /// Returns key parameter value.
1019 pub fn key_parameter_value(&self) -> &KeyParameterValue {
1020 &self.value
1021 }
1022
1023 /// Returns the security level of this key parameter.
1024 pub fn security_level(&self) -> &SecurityLevel {
1025 &self.security_level
1026 }
1027
1028 /// An authorization is a KeyParameter with an associated security level that is used
1029 /// to convey the key characteristics to keystore clients. This function consumes
1030 /// an internal KeyParameter representation to produce the Authorization wire type.
1031 pub fn into_authorization(self) -> Authorization {
1032 Authorization { securityLevel: self.security_level, keyParameter: self.value.into() }
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001033 }
1034}
1035
Janis Danisevskise6efb242020-12-19 13:58:01 -08001036#[cfg(test)]
1037mod generated_key_parameter_tests {
1038 use super::*;
1039 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::TagType::TagType;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001040
Janis Danisevskise6efb242020-12-19 13:58:01 -08001041 fn get_field_by_tag_type(tag: Tag) -> KmKeyParameterValue {
1042 let tag_type = TagType((tag.0 as u32 & 0xF0000000) as i32);
1043 match tag {
1044 Tag::ALGORITHM => return KmKeyParameterValue::Algorithm(Default::default()),
1045 Tag::BLOCK_MODE => return KmKeyParameterValue::BlockMode(Default::default()),
1046 Tag::PADDING => return KmKeyParameterValue::PaddingMode(Default::default()),
1047 Tag::DIGEST => return KmKeyParameterValue::Digest(Default::default()),
1048 Tag::EC_CURVE => return KmKeyParameterValue::EcCurve(Default::default()),
1049 Tag::ORIGIN => return KmKeyParameterValue::Origin(Default::default()),
1050 Tag::PURPOSE => return KmKeyParameterValue::KeyPurpose(Default::default()),
1051 Tag::USER_AUTH_TYPE => {
1052 return KmKeyParameterValue::HardwareAuthenticatorType(Default::default())
1053 }
1054 Tag::HARDWARE_TYPE => return KmKeyParameterValue::SecurityLevel(Default::default()),
1055 _ => {}
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001056 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001057 match tag_type {
1058 TagType::INVALID => return KmKeyParameterValue::Invalid(Default::default()),
1059 TagType::ENUM | TagType::ENUM_REP => {}
1060 TagType::UINT | TagType::UINT_REP => {
1061 return KmKeyParameterValue::Integer(Default::default())
1062 }
1063 TagType::ULONG | TagType::ULONG_REP => {
1064 return KmKeyParameterValue::LongInteger(Default::default())
1065 }
1066 TagType::DATE => return KmKeyParameterValue::DateTime(Default::default()),
1067 TagType::BOOL => return KmKeyParameterValue::BoolValue(Default::default()),
1068 TagType::BIGNUM | TagType::BYTES => {
1069 return KmKeyParameterValue::Blob(Default::default())
1070 }
1071 _ => {}
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001072 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001073 panic!("Unknown tag/tag_type: {:?} {:?}", tag, tag_type);
1074 }
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001075
Janis Danisevskise6efb242020-12-19 13:58:01 -08001076 fn check_field_matches_tag_type(list_o_parameters: &[KmKeyParameter]) {
1077 for kp in list_o_parameters.iter() {
1078 match (&kp.value, get_field_by_tag_type(kp.tag)) {
1079 (&KmKeyParameterValue::Algorithm(_), KmKeyParameterValue::Algorithm(_))
1080 | (&KmKeyParameterValue::BlockMode(_), KmKeyParameterValue::BlockMode(_))
1081 | (&KmKeyParameterValue::PaddingMode(_), KmKeyParameterValue::PaddingMode(_))
1082 | (&KmKeyParameterValue::Digest(_), KmKeyParameterValue::Digest(_))
1083 | (&KmKeyParameterValue::EcCurve(_), KmKeyParameterValue::EcCurve(_))
1084 | (&KmKeyParameterValue::Origin(_), KmKeyParameterValue::Origin(_))
1085 | (&KmKeyParameterValue::KeyPurpose(_), KmKeyParameterValue::KeyPurpose(_))
1086 | (
1087 &KmKeyParameterValue::HardwareAuthenticatorType(_),
1088 KmKeyParameterValue::HardwareAuthenticatorType(_),
1089 )
1090 | (&KmKeyParameterValue::SecurityLevel(_), KmKeyParameterValue::SecurityLevel(_))
1091 | (&KmKeyParameterValue::Invalid(_), KmKeyParameterValue::Invalid(_))
1092 | (&KmKeyParameterValue::Integer(_), KmKeyParameterValue::Integer(_))
1093 | (&KmKeyParameterValue::LongInteger(_), KmKeyParameterValue::LongInteger(_))
1094 | (&KmKeyParameterValue::DateTime(_), KmKeyParameterValue::DateTime(_))
1095 | (&KmKeyParameterValue::BoolValue(_), KmKeyParameterValue::BoolValue(_))
1096 | (&KmKeyParameterValue::Blob(_), KmKeyParameterValue::Blob(_)) => {}
1097 (actual, expected) => panic!(
1098 "Tag {:?} associated with variant {:?} expected {:?}",
1099 kp.tag, actual, expected
1100 ),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001101 }
1102 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001103 }
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001104
Janis Danisevskise6efb242020-12-19 13:58:01 -08001105 #[test]
1106 fn key_parameter_value_field_matches_tag_type() {
1107 check_field_matches_tag_type(&KeyParameterValue::make_field_matches_tag_type_test_vector());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001108 }
1109}
1110
1111#[cfg(test)]
1112mod basic_tests {
1113 use crate::key_parameter::*;
1114
1115 // Test basic functionality of KeyParameter.
1116 #[test]
1117 fn test_key_parameter() {
1118 let key_parameter = KeyParameter::new(
1119 KeyParameterValue::Algorithm(Algorithm::RSA),
1120 SecurityLevel::STRONGBOX,
1121 );
1122
1123 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
1124
1125 assert_eq!(
1126 *key_parameter.key_parameter_value(),
1127 KeyParameterValue::Algorithm(Algorithm::RSA)
1128 );
1129
1130 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
1131 }
1132}
1133
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001134/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
1135/// data types and then tests 'to_sql' method for KeyParameters of those
1136/// different data types. The five different data types for KeyParameter values are:
1137/// i) enums of u32
1138/// ii) u32
1139/// iii) u64
1140/// iv) Vec<u8>
1141/// v) bool
1142#[cfg(test)]
1143mod storage_tests {
1144 use crate::error::*;
1145 use crate::key_parameter::*;
1146 use anyhow::Result;
1147 use rusqlite::types::ToSql;
1148 use rusqlite::{params, Connection, NO_PARAMS};
1149
1150 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
1151 /// from a database table row.
1152 #[test]
1153 fn test_new_from_sql_enum_i32() -> Result<()> {
1154 let db = init_db()?;
1155 insert_into_keyparameter(
1156 &db,
1157 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001158 Tag::ALGORITHM.0,
1159 &Algorithm::RSA.0,
1160 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001161 )?;
1162 let key_param = query_from_keyparameter(&db)?;
1163 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
1164 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
1165 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
1166 Ok(())
1167 }
1168
1169 /// Test initializing a KeyParameter (with key parameter value which is of i32)
1170 /// from a database table row.
1171 #[test]
1172 fn test_new_from_sql_i32() -> Result<()> {
1173 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001174 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001175 let key_param = query_from_keyparameter(&db)?;
1176 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
1177 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
1178 Ok(())
1179 }
1180
1181 /// Test initializing a KeyParameter (with key parameter value which is of i64)
1182 /// from a database table row.
1183 #[test]
1184 fn test_new_from_sql_i64() -> Result<()> {
1185 let db = init_db()?;
1186 // max value for i64, just to test corner cases
1187 insert_into_keyparameter(
1188 &db,
1189 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001190 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001191 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001192 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001193 )?;
1194 let key_param = query_from_keyparameter(&db)?;
1195 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
1196 assert_eq!(
1197 *key_param.key_parameter_value(),
1198 KeyParameterValue::RSAPublicExponent(i64::MAX)
1199 );
1200 Ok(())
1201 }
1202
1203 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1204 /// from a database table row.
1205 #[test]
1206 fn test_new_from_sql_bool() -> Result<()> {
1207 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001208 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001209 let key_param = query_from_keyparameter(&db)?;
1210 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1211 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1212 Ok(())
1213 }
1214
1215 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1216 /// from a database table row.
1217 #[test]
1218 fn test_new_from_sql_vec_u8() -> Result<()> {
1219 let db = init_db()?;
1220 let app_id = String::from("MyAppID");
1221 let app_id_bytes = app_id.into_bytes();
1222 insert_into_keyparameter(
1223 &db,
1224 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001225 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001226 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001227 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001228 )?;
1229 let key_param = query_from_keyparameter(&db)?;
1230 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1231 assert_eq!(
1232 *key_param.key_parameter_value(),
1233 KeyParameterValue::ApplicationID(app_id_bytes)
1234 );
1235 Ok(())
1236 }
1237
1238 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1239 /// in the database
1240 #[test]
1241 fn test_to_sql_enum_i32() -> Result<()> {
1242 let db = init_db()?;
1243 let kp = KeyParameter::new(
1244 KeyParameterValue::Algorithm(Algorithm::RSA),
1245 SecurityLevel::STRONGBOX,
1246 );
1247 store_keyparameter(&db, 1, &kp)?;
1248 let key_param = query_from_keyparameter(&db)?;
1249 assert_eq!(kp.get_tag(), key_param.get_tag());
1250 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1251 assert_eq!(kp.security_level(), key_param.security_level());
1252 Ok(())
1253 }
1254
1255 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1256 #[test]
1257 fn test_to_sql_i32() -> Result<()> {
1258 let db = init_db()?;
1259 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1260 store_keyparameter(&db, 1, &kp)?;
1261 let key_param = query_from_keyparameter(&db)?;
1262 assert_eq!(kp.get_tag(), key_param.get_tag());
1263 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1264 assert_eq!(kp.security_level(), key_param.security_level());
1265 Ok(())
1266 }
1267
1268 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1269 #[test]
1270 fn test_to_sql_i64() -> Result<()> {
1271 let db = init_db()?;
1272 // max value for i64, just to test corner cases
1273 let kp = KeyParameter::new(
1274 KeyParameterValue::RSAPublicExponent(i64::MAX),
1275 SecurityLevel::STRONGBOX,
1276 );
1277 store_keyparameter(&db, 1, &kp)?;
1278 let key_param = query_from_keyparameter(&db)?;
1279 assert_eq!(kp.get_tag(), key_param.get_tag());
1280 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1281 assert_eq!(kp.security_level(), key_param.security_level());
1282 Ok(())
1283 }
1284
1285 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1286 #[test]
1287 fn test_to_sql_vec_u8() -> Result<()> {
1288 let db = init_db()?;
1289 let kp = KeyParameter::new(
1290 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1291 SecurityLevel::STRONGBOX,
1292 );
1293 store_keyparameter(&db, 1, &kp)?;
1294 let key_param = query_from_keyparameter(&db)?;
1295 assert_eq!(kp.get_tag(), key_param.get_tag());
1296 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1297 assert_eq!(kp.security_level(), key_param.security_level());
1298 Ok(())
1299 }
1300
1301 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1302 #[test]
1303 fn test_to_sql_bool() -> Result<()> {
1304 let db = init_db()?;
1305 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1306 store_keyparameter(&db, 1, &kp)?;
1307 let key_param = query_from_keyparameter(&db)?;
1308 assert_eq!(kp.get_tag(), key_param.get_tag());
1309 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1310 assert_eq!(kp.security_level(), key_param.security_level());
1311 Ok(())
1312 }
1313
1314 #[test]
1315 /// Test Tag::Invalid
1316 fn test_invalid_tag() -> Result<()> {
1317 let db = init_db()?;
1318 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1319 let key_param = query_from_keyparameter(&db)?;
1320 assert_eq!(Tag::INVALID, key_param.get_tag());
1321 Ok(())
1322 }
1323
1324 #[test]
1325 fn test_non_existing_enum_variant() -> Result<()> {
1326 let db = init_db()?;
1327 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
Janis Danisevskise6efb242020-12-19 13:58:01 -08001328 let key_param = query_from_keyparameter(&db)?;
1329 assert_eq!(Tag::INVALID, key_param.get_tag());
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001330 Ok(())
1331 }
1332
1333 #[test]
1334 fn test_invalid_conversion_from_sql() -> Result<()> {
1335 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001336 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001337 tests::check_result_contains_error_string(
1338 query_from_keyparameter(&db),
1339 "Failed to read sql data for tag: ALGORITHM.",
1340 );
1341 Ok(())
1342 }
1343
1344 /// Helper method to init database table for key parameter
1345 fn init_db() -> Result<Connection> {
1346 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1347 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1348 .context("Failed to attach databases.")?;
1349 db.execute(
1350 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1351 keyentryid INTEGER,
1352 tag INTEGER,
1353 data ANY,
1354 security_level INTEGER);",
1355 NO_PARAMS,
1356 )
1357 .context("Failed to initialize \"keyparameter\" table.")?;
1358 Ok(db)
1359 }
1360
1361 /// Helper method to insert an entry into key parameter table, with individual parameters
1362 fn insert_into_keyparameter<T: ToSql>(
1363 db: &Connection,
1364 key_id: i64,
1365 tag: i32,
1366 value: &T,
1367 security_level: i32,
1368 ) -> Result<()> {
1369 db.execute(
1370 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001371 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001372 params![key_id, tag, *value, security_level],
1373 )?;
1374 Ok(())
1375 }
1376
1377 /// Helper method to store a key parameter instance.
1378 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1379 db.execute(
1380 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001381 VALUES(?, ?, ?, ?);",
1382 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001383 )?;
1384 Ok(())
1385 }
1386
1387 /// Helper method to query a row from keyparameter table
1388 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001389 let mut stmt =
1390 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001391 let mut rows = stmt.query(NO_PARAMS)?;
1392 let row = rows.next()?.unwrap();
Matthew Maurerb77a28d2021-05-07 16:08:20 -07001393 KeyParameter::new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001394 Tag(row.get(0)?),
Janis Danisevskis4522c2b2020-11-27 18:04:58 -08001395 &SqlField::new(1, row),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001396 SecurityLevel(row.get(2)?),
Matthew Maurerb77a28d2021-05-07 16:08:20 -07001397 )
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001398 }
1399}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001400
1401/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001402/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001403/// key parameter.
1404/// i) bool
1405/// ii) integer
1406/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001407/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001408#[cfg(test)]
1409mod wire_tests {
1410 use crate::key_parameter::*;
1411 /// unit tests for to conversions
1412 #[test]
1413 fn test_convert_to_wire_invalid() {
1414 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001415 assert_eq!(
1416 KmKeyParameter { tag: Tag::INVALID, value: KmKeyParameterValue::Invalid(0) },
1417 kp.value.into()
1418 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001419 }
1420 #[test]
1421 fn test_convert_to_wire_bool() {
1422 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001423 assert_eq!(
1424 KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) },
1425 kp.value.into()
1426 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001427 }
1428 #[test]
1429 fn test_convert_to_wire_integer() {
1430 let kp = KeyParameter::new(
1431 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1432 SecurityLevel::STRONGBOX,
1433 );
Janis Danisevskise6efb242020-12-19 13:58:01 -08001434 assert_eq!(
1435 KmKeyParameter {
1436 tag: Tag::PURPOSE,
1437 value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT)
1438 },
1439 kp.value.into()
1440 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001441 }
1442 #[test]
1443 fn test_convert_to_wire_long_integer() {
1444 let kp =
1445 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001446 assert_eq!(
1447 KmKeyParameter {
1448 tag: Tag::USER_SECURE_ID,
1449 value: KmKeyParameterValue::LongInteger(i64::MAX)
1450 },
1451 kp.value.into()
1452 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001453 }
1454 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001455 fn test_convert_to_wire_blob() {
1456 let kp = KeyParameter::new(
1457 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1458 SecurityLevel::STRONGBOX,
1459 );
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001460 assert_eq!(
Janis Danisevskise6efb242020-12-19 13:58:01 -08001461 KmKeyParameter {
1462 tag: Tag::CONFIRMATION_TOKEN,
1463 value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes())
1464 },
1465 kp.value.into()
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001466 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001467 }
1468
1469 /// unit tests for from conversion
1470 #[test]
1471 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001472 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001473 assert_eq!(KeyParameterValue::Invalid, aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001474 }
1475 #[test]
1476 fn test_convert_from_wire_bool() {
1477 let aidl_kp =
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001478 KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001479 assert_eq!(KeyParameterValue::CallerNonce, aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001480 }
1481 #[test]
1482 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001483 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001484 tag: Tag::PURPOSE,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001485 value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001486 };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001487 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001488 }
1489 #[test]
1490 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001491 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001492 tag: Tag::USER_SECURE_ID,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001493 value: KmKeyParameterValue::LongInteger(i64::MAX),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001494 };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001495 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001496 }
1497 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001498 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001499 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001500 tag: Tag::CONFIRMATION_TOKEN,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001501 value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001502 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001503 assert_eq!(
1504 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
Janis Danisevskise6efb242020-12-19 13:58:01 -08001505 aidl_kp.into()
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001506 );
1507 }
1508}