blob: 74a9b231fe424a3fb6e64e8367323979f01782a4 [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
Jeff Vander Stoep46bbc612021-04-09 08:55:21 +020093#![allow(clippy::from_over_into, clippy::needless_question_mark)]
94
Janis Danisevskis6b00e252020-12-22 11:36:45 -080095use std::convert::TryInto;
96
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080097use crate::db_utils::SqlField;
Hasini Gunasingheaf993662020-07-24 18:40:20 +000098use crate::error::Error as KeystoreError;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070099use crate::error::ResponseCode;
100
Shawn Willden708744a2020-12-11 13:05:27 +0000101pub use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700102 Algorithm::Algorithm, BlockMode::BlockMode, Digest::Digest, EcCurve::EcCurve,
103 HardwareAuthenticatorType::HardwareAuthenticatorType, KeyOrigin::KeyOrigin,
Janis Danisevskis398e6be2020-12-17 09:29:25 -0800104 KeyParameter::KeyParameter as KmKeyParameter,
105 KeyParameterValue::KeyParameterValue as KmKeyParameterValue, KeyPurpose::KeyPurpose,
106 PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000107};
Janis Danisevskisa53c9cf2020-10-26 11:52:33 -0700108use android_system_keystore2::aidl::android::system::keystore2::Authorization::Authorization;
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000109use anyhow::{Context, Result};
Janis Danisevskis4522c2b2020-11-27 18:04:58 -0800110use rusqlite::types::{Null, ToSql, ToSqlOutput};
111use rusqlite::Result as SqlResult;
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000112
Janis Danisevskise6efb242020-12-19 13:58:01 -0800113/// This trait is used to associate a primitive to any type that can be stored inside a
114/// KeyParameterValue, especially the AIDL enum types, e.g., keymint::{Algorithm, Digest, ...}.
115/// This allows for simplifying the macro rules, e.g., for reading from the SQL database.
116/// An expression like `KeyParameterValue::Algorithm(row.get(0))` would not work because
117/// a type of `Algorithm` is expected which does not implement `FromSql` and we cannot
118/// implement it because we own neither the type nor the trait.
119/// With AssociatePrimitive we can write an expression
120/// `KeyParameter::Algorithm(<Algorithm>::from_primitive(row.get(0)))` to inform `get`
121/// about the expected primitive type that it can convert into. By implementing this
122/// trait for all inner types we can write a single rule to cover all cases (except where
123/// there is no wrapped type):
124/// `KeyParameterValue::$vname(<$vtype>::from_primitive(row.get(0)))`
125trait AssociatePrimitive {
126 type Primitive;
127
128 fn from_primitive(v: Self::Primitive) -> Self;
129 fn to_primitive(&self) -> Self::Primitive;
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000130}
131
Janis Danisevskise6efb242020-12-19 13:58:01 -0800132/// Associates the given type with i32. The macro assumes that the given type is actually a
133/// tuple struct wrapping i32, such as AIDL enum types.
134macro_rules! implement_associate_primitive_for_aidl_enum {
135 ($t:ty) => {
136 impl AssociatePrimitive for $t {
137 type Primitive = i32;
138
139 fn from_primitive(v: Self::Primitive) -> Self {
140 Self(v)
141 }
142 fn to_primitive(&self) -> Self::Primitive {
143 self.0
144 }
145 }
146 };
147}
148
149/// Associates the given type with itself.
150macro_rules! implement_associate_primitive_identity {
151 ($t:ty) => {
152 impl AssociatePrimitive for $t {
153 type Primitive = $t;
154
155 fn from_primitive(v: Self::Primitive) -> Self {
156 v
157 }
158 fn to_primitive(&self) -> Self::Primitive {
159 self.clone()
160 }
161 }
162 };
163}
164
165implement_associate_primitive_for_aidl_enum! {Algorithm}
166implement_associate_primitive_for_aidl_enum! {BlockMode}
167implement_associate_primitive_for_aidl_enum! {Digest}
168implement_associate_primitive_for_aidl_enum! {EcCurve}
169implement_associate_primitive_for_aidl_enum! {HardwareAuthenticatorType}
170implement_associate_primitive_for_aidl_enum! {KeyOrigin}
171implement_associate_primitive_for_aidl_enum! {KeyPurpose}
172implement_associate_primitive_for_aidl_enum! {PaddingMode}
173implement_associate_primitive_for_aidl_enum! {SecurityLevel}
174
175implement_associate_primitive_identity! {Vec<u8>}
176implement_associate_primitive_identity! {i64}
177implement_associate_primitive_identity! {i32}
178
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800179/// This enum allows passing a primitive value to `KeyParameterValue::new_from_tag_primitive_pair`
180/// Usually, it is not necessary to use this type directly because the function uses
181/// `Into<Primitive>` as a trait bound.
182pub enum Primitive {
183 /// Wraps an i64.
184 I64(i64),
185 /// Wraps an i32.
186 I32(i32),
187 /// Wraps a Vec<u8>.
188 Vec(Vec<u8>),
189}
190
191impl From<i64> for Primitive {
192 fn from(v: i64) -> Self {
193 Self::I64(v)
194 }
195}
196impl From<i32> for Primitive {
197 fn from(v: i32) -> Self {
198 Self::I32(v)
199 }
200}
201impl From<Vec<u8>> for Primitive {
202 fn from(v: Vec<u8>) -> Self {
203 Self::Vec(v)
204 }
205}
206
207/// This error is returned by `KeyParameterValue::new_from_tag_primitive_pair`.
208#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
209pub enum PrimitiveError {
210 /// Returned if this primitive is unsuitable for the given tag type.
211 #[error("Primitive does not match the expected tag type.")]
212 TypeMismatch,
213 /// Return if the tag type is unknown.
214 #[error("Unknown tag.")]
215 UnknownTag,
216}
217
218impl TryInto<i64> for Primitive {
219 type Error = PrimitiveError;
220
221 fn try_into(self) -> Result<i64, Self::Error> {
222 match self {
223 Self::I64(v) => Ok(v),
224 _ => Err(Self::Error::TypeMismatch),
225 }
226 }
227}
228impl TryInto<i32> for Primitive {
229 type Error = PrimitiveError;
230
231 fn try_into(self) -> Result<i32, Self::Error> {
232 match self {
233 Self::I32(v) => Ok(v),
234 _ => Err(Self::Error::TypeMismatch),
235 }
236 }
237}
238impl TryInto<Vec<u8>> for Primitive {
239 type Error = PrimitiveError;
240
241 fn try_into(self) -> Result<Vec<u8>, Self::Error> {
242 match self {
243 Self::Vec(v) => Ok(v),
244 _ => Err(Self::Error::TypeMismatch),
245 }
246 }
247}
248
249/// Expands the list of KeyParameterValue variants as follows:
250///
251/// Input:
252/// Invalid with tag INVALID and field Invalid,
253/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
254///
255/// Output:
256/// ```
257/// pub fn new_from_tag_primitive_pair<T: Into<Primitive>>(
258/// tag: Tag,
259/// v: T
260/// ) -> Result<KeyParameterValue, PrimitiveError> {
261/// let p: Primitive = v.into();
262/// Ok(match tag {
263/// Tag::INVALID => KeyParameterValue::Invalid,
264/// Tag::ALGORITHM => KeyParameterValue::Algorithm(
265/// <Algorithm>::from_primitive(p.try_into()?)
266/// ),
267/// _ => return Err(PrimitiveError::UnknownTag),
268/// })
269/// }
270/// ```
271macro_rules! implement_from_tag_primitive_pair {
272 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
273 /// Returns the an instance of $enum_name or an error if the given primitive does not match
274 /// the tag type or the tag is unknown.
275 pub fn new_from_tag_primitive_pair<T: Into<Primitive>>(
276 tag: Tag,
277 v: T
278 ) -> Result<$enum_name, PrimitiveError> {
279 let p: Primitive = v.into();
280 Ok(match tag {
281 $(Tag::$tag_name => $enum_name::$vname$((
282 <$vtype>::from_primitive(p.try_into()?)
283 ))?,)*
284 _ => return Err(PrimitiveError::UnknownTag),
285 })
286 }
287 };
288}
289
Janis Danisevskise6efb242020-12-19 13:58:01 -0800290/// Expands the list of KeyParameterValue variants as follows:
291///
292/// Input:
293/// pub enum KeyParameterValue {
294/// Invalid with tag INVALID and field Invalid,
295/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
296/// }
297///
298/// Output:
299/// ```
300/// pub enum KeyParameterValue {
301/// Invalid,
302/// Algorithm(Algorithm),
303/// }
304/// ```
305macro_rules! implement_enum {
306 (
307 $(#[$enum_meta:meta])*
308 $enum_vis:vis enum $enum_name:ident {
309 $($(#[$emeta:meta])* $vname:ident$(($vtype:ty))?),* $(,)?
310 }
311 ) => {
312 $(#[$enum_meta])*
313 $enum_vis enum $enum_name {
314 $(
315 $(#[$emeta])*
316 $vname$(($vtype))?
317 ),*
318 }
319 };
320}
321
322/// Expands the list of KeyParameterValue variants as follows:
323///
324/// Input:
325/// Invalid with tag INVALID and field Invalid,
326/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
327///
328/// Output:
329/// ```
330/// pub fn get_tag(&self) -> Tag {
331/// match self {
332/// KeyParameterValue::Invalid => Tag::INVALID,
333/// KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
334/// }
335/// }
336/// ```
337macro_rules! implement_get_tag {
338 (
339 @replace_type_spec
340 $enum_name:ident,
341 [$($out:tt)*],
342 [$vname:ident($vtype:ty) $tag_name:ident, $($in:tt)*]
343 ) => {
344 implement_get_tag!{@replace_type_spec $enum_name, [$($out)*
345 $enum_name::$vname(_) => Tag::$tag_name,
346 ], [$($in)*]}
347 };
348 (
349 @replace_type_spec
350 $enum_name:ident,
351 [$($out:tt)*],
352 [$vname:ident $tag_name:ident, $($in:tt)*]
353 ) => {
354 implement_get_tag!{@replace_type_spec $enum_name, [$($out)*
355 $enum_name::$vname => Tag::$tag_name,
356 ], [$($in)*]}
357 };
358 (@replace_type_spec $enum_name:ident, [$($out:tt)*], []) => {
359 /// Returns the tag of the given instance.
360 pub fn get_tag(&self) -> Tag {
361 match self {
362 $($out)*
363 }
364 }
365 };
366
367 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
368 implement_get_tag!{@replace_type_spec $enum_name, [], [$($vname$(($vtype))? $tag_name,)*]}
369 };
370}
371
372/// Expands the list of KeyParameterValue variants as follows:
373///
374/// Input:
375/// Invalid with tag INVALID and field Invalid,
376/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
377///
378/// Output:
379/// ```
380/// fn to_sql(&self) -> SqlResult<ToSqlOutput> {
381/// match self {
382/// KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
383/// KeyParameterValue::Algorithm(v) => Ok(ToSqlOutput::from(v.to_primitive())),
384/// }
385/// }
386/// ```
387macro_rules! implement_to_sql {
388 (
389 @replace_type_spec
390 $enum_name:ident,
391 [$($out:tt)*],
392 [$vname:ident($vtype:ty), $($in:tt)*]
393 ) => {
394 implement_to_sql!{@replace_type_spec $enum_name, [ $($out)*
395 $enum_name::$vname(v) => Ok(ToSqlOutput::from(v.to_primitive())),
396 ], [$($in)*]}
397 };
398 (
399 @replace_type_spec
400 $enum_name:ident,
401 [$($out:tt)*],
402 [$vname:ident, $($in:tt)*]
403 ) => {
404 implement_to_sql!{@replace_type_spec $enum_name, [ $($out)*
405 $enum_name::$vname => Ok(ToSqlOutput::from(Null)),
406 ], [$($in)*]}
407 };
408 (@replace_type_spec $enum_name:ident, [$($out:tt)*], []) => {
409 /// Converts $enum_name to be stored in a rusqlite database.
410 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
411 match self {
412 $($out)*
413 }
414 }
415 };
416
417
418 ($enum_name:ident; $($vname:ident$(($vtype:ty))?),*) => {
419 impl ToSql for $enum_name {
420 implement_to_sql!{@replace_type_spec $enum_name, [], [$($vname$(($vtype))?,)*]}
421 }
422
423 }
424}
425
426/// Expands the list of KeyParameterValue variants as follows:
427///
428/// Input:
429/// Invalid with tag INVALID and field Invalid,
430/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
431///
432/// Output:
433/// ```
434/// pub fn new_from_sql(
435/// tag: Tag,
436/// data: &SqlField,
437/// ) -> Result<Self> {
438/// Ok(match self {
439/// Tag::Invalid => KeyParameterValue::Invalid,
440/// Tag::ALGORITHM => {
441/// KeyParameterValue::Algorithm(<Algorithm>::from_primitive(data
442/// .get()
443/// .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
444/// .context(concat!("Failed to read sql data for tag: ", "ALGORITHM", "."))?
445/// ))
446/// },
447/// })
448/// }
449/// ```
450macro_rules! implement_new_from_sql {
451 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
452 /// Takes a tag and an SqlField and attempts to construct a KeyParameter value.
453 /// This function may fail if the parameter value cannot be extracted from the
454 /// database cell.
455 pub fn new_from_sql(
456 tag: Tag,
457 data: &SqlField,
458 ) -> Result<Self> {
459 Ok(match tag {
460 $(
461 Tag::$tag_name => {
462 $enum_name::$vname$((<$vtype>::from_primitive(data
463 .get()
464 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
465 .context(concat!(
466 "Failed to read sql data for tag: ",
467 stringify!($tag_name),
468 "."
469 ))?
470 )))?
471 },
472 )*
473 _ => $enum_name::Invalid,
474 })
475 }
476 };
477}
478
479/// This key parameter default is used during the conversion from KeyParameterValue
480/// to keymint::KeyParameterValue. Keystore's version does not have wrapped types
481/// for boolean tags and the tag Invalid. The AIDL version uses bool and integer
482/// variants respectively. This default function is invoked in these cases to
483/// homogenize the rules for boolean and invalid tags.
484/// The bool variant returns true because boolean parameters are implicitly true
485/// if present.
486trait KpDefault {
487 fn default() -> Self;
488}
489
490impl KpDefault for i32 {
491 fn default() -> Self {
492 0
493 }
494}
495
496impl KpDefault for bool {
497 fn default() -> Self {
498 true
499 }
500}
501
502/// Expands the list of KeyParameterValue variants as follows:
503///
504/// Input:
505/// Invalid with tag INVALID and field Invalid,
506/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
507///
508/// Output:
509/// ```
510/// impl From<KmKeyParameter> for KeyParameterValue {
511/// fn from(kp: KmKeyParameter) -> Self {
512/// match kp {
513/// KmKeyParameter { tag: Tag::INVALID, value: KmKeyParameterValue::Invalid(_) }
514/// => $enum_name::$vname,
515/// KmKeyParameter { tag: Tag::Algorithm, value: KmKeyParameterValue::Algorithm(v) }
516/// => $enum_name::Algorithm(v),
517/// _ => $enum_name::Invalid,
518/// }
519/// }
520/// }
521///
522/// impl Into<KmKeyParameter> for KeyParameterValue {
523/// fn into(self) -> KmKeyParameter {
524/// match self {
525/// KeyParameterValue::Invalid => KmKeyParameter {
526/// tag: Tag::INVALID,
527/// value: KmKeyParameterValue::Invalid(KpDefault::default())
528/// },
529/// KeyParameterValue::Algorithm(v) => KmKeyParameter {
530/// tag: Tag::ALGORITHM,
531/// value: KmKeyParameterValue::Algorithm(v)
532/// },
533/// }
534/// }
535/// }
536/// ```
537macro_rules! implement_try_from_to_km_parameter {
538 // The first three rules expand From<KmKeyParameter>.
539 (
540 @from
541 $enum_name:ident,
542 [$($out:tt)*],
543 [$vname:ident($vtype:ty) $tag_name:ident $field_name:ident, $($in:tt)*]
544 ) => {
545 implement_try_from_to_km_parameter!{@from $enum_name, [$($out)*
546 KmKeyParameter {
547 tag: Tag::$tag_name,
548 value: KmKeyParameterValue::$field_name(v)
549 } => $enum_name::$vname(v),
550 ], [$($in)*]
551 }};
552 (
553 @from
554 $enum_name:ident,
555 [$($out:tt)*],
556 [$vname:ident $tag_name:ident $field_name:ident, $($in:tt)*]
557 ) => {
558 implement_try_from_to_km_parameter!{@from $enum_name, [$($out)*
559 KmKeyParameter {
560 tag: Tag::$tag_name,
561 value: KmKeyParameterValue::$field_name(_)
562 } => $enum_name::$vname,
563 ], [$($in)*]
564 }};
565 (@from $enum_name:ident, [$($out:tt)*], []) => {
566 impl From<KmKeyParameter> for $enum_name {
567 fn from(kp: KmKeyParameter) -> Self {
568 match kp {
569 $($out)*
570 _ => $enum_name::Invalid,
571 }
572 }
573 }
574 };
575
576 // The next three rules expand Into<KmKeyParameter>.
577 (
578 @into
579 $enum_name:ident,
580 [$($out:tt)*],
581 [$vname:ident($vtype:ty) $tag_name:ident $field_name:ident, $($in:tt)*]
582 ) => {
583 implement_try_from_to_km_parameter!{@into $enum_name, [$($out)*
584 $enum_name::$vname(v) => KmKeyParameter {
585 tag: Tag::$tag_name,
586 value: KmKeyParameterValue::$field_name(v)
587 },
588 ], [$($in)*]
589 }};
590 (
591 @into
592 $enum_name:ident,
593 [$($out:tt)*],
594 [$vname:ident $tag_name:ident $field_name:ident, $($in:tt)*]
595 ) => {
596 implement_try_from_to_km_parameter!{@into $enum_name, [$($out)*
597 $enum_name::$vname => KmKeyParameter {
598 tag: Tag::$tag_name,
599 value: KmKeyParameterValue::$field_name(KpDefault::default())
600 },
601 ], [$($in)*]
602 }};
603 (@into $enum_name:ident, [$($out:tt)*], []) => {
604 impl Into<KmKeyParameter> for $enum_name {
605 fn into(self) -> KmKeyParameter {
606 match self {
607 $($out)*
608 }
609 }
610 }
611 };
612
613
614 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident $field_name:ident),*) => {
615 implement_try_from_to_km_parameter!(
616 @from $enum_name,
617 [],
618 [$($vname$(($vtype))? $tag_name $field_name,)*]
619 );
620 implement_try_from_to_km_parameter!(
621 @into $enum_name,
622 [],
623 [$($vname$(($vtype))? $tag_name $field_name,)*]
624 );
625 };
626}
627
628/// This is the top level macro. While the other macros do most of the heavy lifting, this takes
629/// the key parameter list and passes it on to the other macros to generate all of the conversion
630/// functions. In addition, it generates an important test vector for verifying that tag type of the
631/// keymint tag matches the associated keymint KeyParameterValue field.
632macro_rules! implement_key_parameter_value {
633 (
634 $(#[$enum_meta:meta])*
635 $enum_vis:vis enum $enum_name:ident {
636 $(
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800637 $(#[$($emeta:tt)+])*
638 $vname:ident$(($vtype:ty))?
Janis Danisevskise6efb242020-12-19 13:58:01 -0800639 ),* $(,)?
640 }
641 ) => {
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800642 implement_key_parameter_value!{
643 @extract_attr
644 $(#[$enum_meta])*
645 $enum_vis enum $enum_name {
646 []
647 [$(
648 [] [$(#[$($emeta)+])*]
649 $vname$(($vtype))?,
650 )*]
651 }
652 }
653 };
654
655 (
656 @extract_attr
657 $(#[$enum_meta:meta])*
658 $enum_vis:vis enum $enum_name:ident {
659 [$($out:tt)*]
660 [
661 [$(#[$mout:meta])*]
662 [
663 #[key_param(tag = $tag_name:ident, field = $field_name:ident)]
664 $(#[$($mtail:tt)+])*
665 ]
666 $vname:ident$(($vtype:ty))?,
667 $($tail:tt)*
668 ]
669 }
670 ) => {
671 implement_key_parameter_value!{
672 @extract_attr
673 $(#[$enum_meta])*
674 $enum_vis enum $enum_name {
675 [
676 $($out)*
677 $(#[$mout])*
678 $(#[$($mtail)+])*
679 $tag_name $field_name $vname$(($vtype))?,
680 ]
681 [$($tail)*]
682 }
683 }
684 };
685
686 (
687 @extract_attr
688 $(#[$enum_meta:meta])*
689 $enum_vis:vis enum $enum_name:ident {
690 [$($out:tt)*]
691 [
692 [$(#[$mout:meta])*]
693 [
694 #[$front:meta]
695 $(#[$($mtail:tt)+])*
696 ]
697 $vname:ident$(($vtype:ty))?,
698 $($tail:tt)*
699 ]
700 }
701 ) => {
702 implement_key_parameter_value!{
703 @extract_attr
704 $(#[$enum_meta])*
705 $enum_vis enum $enum_name {
706 [$($out)*]
707 [
708 [
709 $(#[$mout])*
710 #[$front]
711 ]
712 [$(#[$($mtail)+])*]
713 $vname$(($vtype))?,
714 $($tail)*
715 ]
716 }
717 }
718 };
719
720 (
721 @extract_attr
722 $(#[$enum_meta:meta])*
723 $enum_vis:vis enum $enum_name:ident {
724 [$($out:tt)*]
725 []
726 }
727 ) => {
728 implement_key_parameter_value!{
729 @spill
730 $(#[$enum_meta])*
731 $enum_vis enum $enum_name {
732 $($out)*
733 }
734 }
735 };
736
737 (
738 @spill
739 $(#[$enum_meta:meta])*
740 $enum_vis:vis enum $enum_name:ident {
741 $(
742 $(#[$emeta:meta])*
743 $tag_name:ident $field_name:ident $vname:ident$(($vtype:ty))?,
744 )*
745 }
746 ) => {
Janis Danisevskise6efb242020-12-19 13:58:01 -0800747 implement_enum!(
748 $(#[$enum_meta])*
749 $enum_vis enum $enum_name {
750 $(
751 $(#[$emeta])*
752 $vname$(($vtype))?
753 ),*
754 });
755
756 impl $enum_name {
757 implement_new_from_sql!($enum_name; $($vname$(($vtype))? $tag_name),*);
758 implement_get_tag!($enum_name; $($vname$(($vtype))? $tag_name),*);
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800759 implement_from_tag_primitive_pair!($enum_name; $($vname$(($vtype))? $tag_name),*);
Janis Danisevskise6efb242020-12-19 13:58:01 -0800760
761 #[cfg(test)]
762 fn make_field_matches_tag_type_test_vector() -> Vec<KmKeyParameter> {
763 vec![$(KmKeyParameter{
764 tag: Tag::$tag_name,
765 value: KmKeyParameterValue::$field_name(Default::default())}
766 ),*]
767 }
768 }
769
770 implement_try_from_to_km_parameter!(
771 $enum_name;
772 $($vname$(($vtype))? $tag_name $field_name),*
773 );
774
775 implement_to_sql!($enum_name; $($vname$(($vtype))?),*);
776 };
777}
778
779implement_key_parameter_value! {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000780/// KeyParameterValue holds a value corresponding to one of the Tags defined in
Shawn Willden525c0032021-03-29 13:58:33 +0000781/// the AIDL spec at hardware/interfaces/security/keymint
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700782#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000783pub enum KeyParameterValue {
784 /// Associated with Tag:INVALID
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800785 #[key_param(tag = INVALID, field = Invalid)]
786 Invalid,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000787 /// Set of purposes for which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800788 #[key_param(tag = PURPOSE, field = KeyPurpose)]
789 KeyPurpose(KeyPurpose),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000790 /// Cryptographic algorithm with which the key is used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800791 #[key_param(tag = ALGORITHM, field = Algorithm)]
792 Algorithm(Algorithm),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000793 /// Size of the key , in bits
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800794 #[key_param(tag = KEY_SIZE, field = Integer)]
795 KeySize(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000796 /// Block cipher mode(s) with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800797 #[key_param(tag = BLOCK_MODE, field = BlockMode)]
798 BlockMode(BlockMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000799 /// Digest algorithms that may be used with the key to perform signing and verification
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800800 #[key_param(tag = DIGEST, field = Digest)]
801 Digest(Digest),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000802 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800803 #[key_param(tag = PADDING, field = PaddingMode)]
804 PaddingMode(PaddingMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000805 /// Can the caller provide a nonce for nonce-requiring operations
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800806 #[key_param(tag = CALLER_NONCE, field = BoolValue)]
807 CallerNonce,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000808 /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800809 #[key_param(tag = MIN_MAC_LENGTH, field = Integer)]
810 MinMacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000811 /// The elliptic curve
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800812 #[key_param(tag = EC_CURVE, field = EcCurve)]
813 EcCurve(EcCurve),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000814 /// Value of the public exponent for an RSA key pair
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800815 #[key_param(tag = RSA_PUBLIC_EXPONENT, field = LongInteger)]
816 RSAPublicExponent(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000817 /// An attestation certificate for the generated key should contain an application-scoped
818 /// and time-bounded device-unique ID
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800819 #[key_param(tag = INCLUDE_UNIQUE_ID, field = BoolValue)]
820 IncludeUniqueID,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000821 //TODO: find out about this
822 // /// Necessary system environment conditions for the generated key to be used
823 // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000824 /// Only the boot loader can use the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800825 #[key_param(tag = BOOTLOADER_ONLY, field = BoolValue)]
826 BootLoaderOnly,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000827 /// When deleted, the key is guaranteed to be permanently deleted and unusable
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800828 #[key_param(tag = ROLLBACK_RESISTANCE, field = BoolValue)]
829 RollbackResistance,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000830 /// The date and time at which the key becomes active
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800831 #[key_param(tag = ACTIVE_DATETIME, field = DateTime)]
832 ActiveDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000833 /// The date and time at which the key expires for signing and encryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800834 #[key_param(tag = ORIGINATION_EXPIRE_DATETIME, field = DateTime)]
835 OriginationExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000836 /// The date and time at which the key expires for verification and decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800837 #[key_param(tag = USAGE_EXPIRE_DATETIME, field = DateTime)]
838 UsageExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000839 /// Minimum amount of time that elapses between allowed operations
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800840 #[key_param(tag = MIN_SECONDS_BETWEEN_OPS, field = Integer)]
841 MinSecondsBetweenOps(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000842 /// Maximum number of times that a key may be used between system reboots
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800843 #[key_param(tag = MAX_USES_PER_BOOT, field = Integer)]
844 MaxUsesPerBoot(i32),
Qi Wub9433b52020-12-01 14:52:46 +0800845 /// The number of times that a limited use key can be used
846 #[key_param(tag = USAGE_COUNT_LIMIT, field = Integer)]
847 UsageCountLimit(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000848 /// ID of the Android user that is permitted to use the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800849 #[key_param(tag = USER_ID, field = Integer)]
850 UserID(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000851 /// A key may only be used under a particular secure user authentication state
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800852 #[key_param(tag = USER_SECURE_ID, field = LongInteger)]
853 UserSecureID(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000854 /// No authentication is required to use this key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800855 #[key_param(tag = NO_AUTH_REQUIRED, field = BoolValue)]
856 NoAuthRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000857 /// The types of user authenticators that may be used to authorize this key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800858 #[key_param(tag = USER_AUTH_TYPE, field = HardwareAuthenticatorType)]
859 HardwareAuthenticatorType(HardwareAuthenticatorType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000860 /// The time in seconds for which the key is authorized for use, after user authentication
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800861 #[key_param(tag = AUTH_TIMEOUT, field = Integer)]
862 AuthTimeout(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000863 /// The key may be used after authentication timeout if device is still on-body
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800864 #[key_param(tag = ALLOW_WHILE_ON_BODY, field = BoolValue)]
865 AllowWhileOnBody,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000866 /// The key must be unusable except when the user has provided proof of physical presence
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800867 #[key_param(tag = TRUSTED_USER_PRESENCE_REQUIRED, field = BoolValue)]
868 TrustedUserPresenceRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000869 /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
870 /// unless the user provides confirmation of the data to be signed
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800871 #[key_param(tag = TRUSTED_CONFIRMATION_REQUIRED, field = BoolValue)]
872 TrustedConfirmationRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000873 /// The key may only be used when the device is unlocked
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800874 #[key_param(tag = UNLOCKED_DEVICE_REQUIRED, field = BoolValue)]
875 UnlockedDeviceRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000876 /// When provided to generateKey or importKey, this tag specifies data
877 /// that is necessary during all uses of the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800878 #[key_param(tag = APPLICATION_ID, field = Blob)]
879 ApplicationID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000880 /// When provided to generateKey or importKey, this tag specifies data
881 /// that is necessary during all uses of the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800882 #[key_param(tag = APPLICATION_DATA, field = Blob)]
883 ApplicationData(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000884 /// Specifies the date and time the key was created
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800885 #[key_param(tag = CREATION_DATETIME, field = DateTime)]
886 CreationDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000887 /// Specifies where the key was created, if known
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800888 #[key_param(tag = ORIGIN, field = Origin)]
889 KeyOrigin(KeyOrigin),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000890 /// The key used by verified boot to validate the operating system booted
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800891 #[key_param(tag = ROOT_OF_TRUST, field = Blob)]
892 RootOfTrust(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000893 /// System OS version with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800894 #[key_param(tag = OS_VERSION, field = Integer)]
895 OSVersion(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000896 /// Specifies the system security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800897 #[key_param(tag = OS_PATCHLEVEL, field = Integer)]
898 OSPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000899 /// Specifies a unique, time-based identifier
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800900 #[key_param(tag = UNIQUE_ID, field = Blob)]
901 UniqueID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000902 /// Used to deliver a "challenge" value to the attestKey() method
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800903 #[key_param(tag = ATTESTATION_CHALLENGE, field = Blob)]
904 AttestationChallenge(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000905 /// The set of applications which may use a key, used only with attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800906 #[key_param(tag = ATTESTATION_APPLICATION_ID, field = Blob)]
907 AttestationApplicationID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000908 /// Provides the device's brand name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800909 #[key_param(tag = ATTESTATION_ID_BRAND, field = Blob)]
910 AttestationIdBrand(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000911 /// Provides the device's device name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800912 #[key_param(tag = ATTESTATION_ID_DEVICE, field = Blob)]
913 AttestationIdDevice(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000914 /// Provides the device's product name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800915 #[key_param(tag = ATTESTATION_ID_PRODUCT, field = Blob)]
916 AttestationIdProduct(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000917 /// Provides the device's serial number, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800918 #[key_param(tag = ATTESTATION_ID_SERIAL, field = Blob)]
919 AttestationIdSerial(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000920 /// Provides the IMEIs for all radios on the device, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800921 #[key_param(tag = ATTESTATION_ID_IMEI, field = Blob)]
922 AttestationIdIMEI(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000923 /// Provides the MEIDs for all radios on the device, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800924 #[key_param(tag = ATTESTATION_ID_MEID, field = Blob)]
925 AttestationIdMEID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000926 /// Provides the device's manufacturer name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800927 #[key_param(tag = ATTESTATION_ID_MANUFACTURER, field = Blob)]
928 AttestationIdManufacturer(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000929 /// Provides the device's model name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800930 #[key_param(tag = ATTESTATION_ID_MODEL, field = Blob)]
931 AttestationIdModel(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000932 /// Specifies the vendor image security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800933 #[key_param(tag = VENDOR_PATCHLEVEL, field = Integer)]
934 VendorPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000935 /// Specifies the boot image (kernel) security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800936 #[key_param(tag = BOOT_PATCHLEVEL, field = Integer)]
937 BootPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000938 /// Provides "associated data" for AES-GCM encryption or decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800939 #[key_param(tag = ASSOCIATED_DATA, field = Blob)]
940 AssociatedData(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000941 /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
942 /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800943 #[key_param(tag = NONCE, field = Blob)]
944 Nonce(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000945 /// Provides the requested length of a MAC or GCM authentication tag, in bits
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800946 #[key_param(tag = MAC_LENGTH, field = Integer)]
947 MacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000948 /// Specifies whether the device has been factory reset since the
949 /// last unique ID rotation. Used for key attestation
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800950 #[key_param(tag = RESET_SINCE_ID_ROTATION, field = BoolValue)]
951 ResetSinceIdRotation,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000952 /// Used to deliver a cryptographic token proving that the user
Janis Danisevskis2c084012021-01-31 22:23:17 -0800953 /// confirmed a signing request
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800954 #[key_param(tag = CONFIRMATION_TOKEN, field = Blob)]
955 ConfirmationToken(Vec<u8>),
Janis Danisevskis2c084012021-01-31 22:23:17 -0800956 /// Used to deliver the certificate serial number to the KeyMint instance
957 /// certificate generation.
958 #[key_param(tag = CERTIFICATE_SERIAL, field = Blob)]
959 CertificateSerial(Vec<u8>),
960 /// Used to deliver the certificate subject to the KeyMint instance
961 /// certificate generation. This must be DER encoded X509 name.
962 #[key_param(tag = CERTIFICATE_SUBJECT, field = Blob)]
963 CertificateSubject(Vec<u8>),
964 /// Used to deliver the not before date in milliseconds to KeyMint during key generation/import.
965 #[key_param(tag = CERTIFICATE_NOT_BEFORE, field = DateTime)]
966 CertificateNotBefore(i64),
967 /// Used to deliver the not after date in milliseconds to KeyMint during key generation/import.
968 #[key_param(tag = CERTIFICATE_NOT_AFTER, field = DateTime)]
969 CertificateNotAfter(i64),
Paul Crowley7c57bf12021-02-02 16:26:57 -0800970 /// Specifies a maximum boot level at which a key should function
971 #[key_param(tag = MAX_BOOT_LEVEL, field = Integer)]
972 MaxBootLevel(i32),
Janis Danisevskise6efb242020-12-19 13:58:01 -0800973}
974}
975
976impl From<&KmKeyParameter> for KeyParameterValue {
977 fn from(kp: &KmKeyParameter) -> Self {
978 kp.clone().into()
979 }
980}
981
982/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
983#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
984pub struct KeyParameter {
985 value: KeyParameterValue,
986 security_level: SecurityLevel,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000987}
988
989impl KeyParameter {
990 /// Create an instance of KeyParameter, given the value and the security level.
Janis Danisevskise6efb242020-12-19 13:58:01 -0800991 pub fn new(value: KeyParameterValue, security_level: SecurityLevel) -> Self {
992 KeyParameter { value, security_level }
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000993 }
994
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000995 /// Construct a KeyParameter from the data from a rusqlite row.
996 /// Note that following variants of KeyParameterValue should not be stored:
997 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
998 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
999 /// This filtering is enforced at a higher level and here we support conversion for all the
1000 /// variants.
1001 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001002 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001003 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001004 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001005 ) -> Result<Self> {
Janis Danisevskise6efb242020-12-19 13:58:01 -08001006 Ok(Self {
1007 value: KeyParameterValue::new_from_sql(tag_val, data)?,
1008 security_level: security_level_val,
1009 })
1010 }
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001011
Janis Danisevskise6efb242020-12-19 13:58:01 -08001012 /// Get the KeyMint Tag of this this key parameter.
1013 pub fn get_tag(&self) -> Tag {
1014 self.value.get_tag()
1015 }
1016
1017 /// Returns key parameter value.
1018 pub fn key_parameter_value(&self) -> &KeyParameterValue {
1019 &self.value
1020 }
1021
1022 /// Returns the security level of this key parameter.
1023 pub fn security_level(&self) -> &SecurityLevel {
1024 &self.security_level
1025 }
1026
1027 /// An authorization is a KeyParameter with an associated security level that is used
1028 /// to convey the key characteristics to keystore clients. This function consumes
1029 /// an internal KeyParameter representation to produce the Authorization wire type.
1030 pub fn into_authorization(self) -> Authorization {
1031 Authorization { securityLevel: self.security_level, keyParameter: self.value.into() }
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001032 }
1033}
1034
Janis Danisevskise6efb242020-12-19 13:58:01 -08001035#[cfg(test)]
1036mod generated_key_parameter_tests {
1037 use super::*;
1038 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::TagType::TagType;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001039
Janis Danisevskise6efb242020-12-19 13:58:01 -08001040 fn get_field_by_tag_type(tag: Tag) -> KmKeyParameterValue {
1041 let tag_type = TagType((tag.0 as u32 & 0xF0000000) as i32);
1042 match tag {
1043 Tag::ALGORITHM => return KmKeyParameterValue::Algorithm(Default::default()),
1044 Tag::BLOCK_MODE => return KmKeyParameterValue::BlockMode(Default::default()),
1045 Tag::PADDING => return KmKeyParameterValue::PaddingMode(Default::default()),
1046 Tag::DIGEST => return KmKeyParameterValue::Digest(Default::default()),
1047 Tag::EC_CURVE => return KmKeyParameterValue::EcCurve(Default::default()),
1048 Tag::ORIGIN => return KmKeyParameterValue::Origin(Default::default()),
1049 Tag::PURPOSE => return KmKeyParameterValue::KeyPurpose(Default::default()),
1050 Tag::USER_AUTH_TYPE => {
1051 return KmKeyParameterValue::HardwareAuthenticatorType(Default::default())
1052 }
1053 Tag::HARDWARE_TYPE => return KmKeyParameterValue::SecurityLevel(Default::default()),
1054 _ => {}
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001055 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001056 match tag_type {
1057 TagType::INVALID => return KmKeyParameterValue::Invalid(Default::default()),
1058 TagType::ENUM | TagType::ENUM_REP => {}
1059 TagType::UINT | TagType::UINT_REP => {
1060 return KmKeyParameterValue::Integer(Default::default())
1061 }
1062 TagType::ULONG | TagType::ULONG_REP => {
1063 return KmKeyParameterValue::LongInteger(Default::default())
1064 }
1065 TagType::DATE => return KmKeyParameterValue::DateTime(Default::default()),
1066 TagType::BOOL => return KmKeyParameterValue::BoolValue(Default::default()),
1067 TagType::BIGNUM | TagType::BYTES => {
1068 return KmKeyParameterValue::Blob(Default::default())
1069 }
1070 _ => {}
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001071 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001072 panic!("Unknown tag/tag_type: {:?} {:?}", tag, tag_type);
1073 }
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001074
Janis Danisevskise6efb242020-12-19 13:58:01 -08001075 fn check_field_matches_tag_type(list_o_parameters: &[KmKeyParameter]) {
1076 for kp in list_o_parameters.iter() {
1077 match (&kp.value, get_field_by_tag_type(kp.tag)) {
1078 (&KmKeyParameterValue::Algorithm(_), KmKeyParameterValue::Algorithm(_))
1079 | (&KmKeyParameterValue::BlockMode(_), KmKeyParameterValue::BlockMode(_))
1080 | (&KmKeyParameterValue::PaddingMode(_), KmKeyParameterValue::PaddingMode(_))
1081 | (&KmKeyParameterValue::Digest(_), KmKeyParameterValue::Digest(_))
1082 | (&KmKeyParameterValue::EcCurve(_), KmKeyParameterValue::EcCurve(_))
1083 | (&KmKeyParameterValue::Origin(_), KmKeyParameterValue::Origin(_))
1084 | (&KmKeyParameterValue::KeyPurpose(_), KmKeyParameterValue::KeyPurpose(_))
1085 | (
1086 &KmKeyParameterValue::HardwareAuthenticatorType(_),
1087 KmKeyParameterValue::HardwareAuthenticatorType(_),
1088 )
1089 | (&KmKeyParameterValue::SecurityLevel(_), KmKeyParameterValue::SecurityLevel(_))
1090 | (&KmKeyParameterValue::Invalid(_), KmKeyParameterValue::Invalid(_))
1091 | (&KmKeyParameterValue::Integer(_), KmKeyParameterValue::Integer(_))
1092 | (&KmKeyParameterValue::LongInteger(_), KmKeyParameterValue::LongInteger(_))
1093 | (&KmKeyParameterValue::DateTime(_), KmKeyParameterValue::DateTime(_))
1094 | (&KmKeyParameterValue::BoolValue(_), KmKeyParameterValue::BoolValue(_))
1095 | (&KmKeyParameterValue::Blob(_), KmKeyParameterValue::Blob(_)) => {}
1096 (actual, expected) => panic!(
1097 "Tag {:?} associated with variant {:?} expected {:?}",
1098 kp.tag, actual, expected
1099 ),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001100 }
1101 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001102 }
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001103
Janis Danisevskise6efb242020-12-19 13:58:01 -08001104 #[test]
1105 fn key_parameter_value_field_matches_tag_type() {
1106 check_field_matches_tag_type(&KeyParameterValue::make_field_matches_tag_type_test_vector());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001107 }
1108}
1109
1110#[cfg(test)]
1111mod basic_tests {
1112 use crate::key_parameter::*;
1113
1114 // Test basic functionality of KeyParameter.
1115 #[test]
1116 fn test_key_parameter() {
1117 let key_parameter = KeyParameter::new(
1118 KeyParameterValue::Algorithm(Algorithm::RSA),
1119 SecurityLevel::STRONGBOX,
1120 );
1121
1122 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
1123
1124 assert_eq!(
1125 *key_parameter.key_parameter_value(),
1126 KeyParameterValue::Algorithm(Algorithm::RSA)
1127 );
1128
1129 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
1130 }
1131}
1132
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001133/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
1134/// data types and then tests 'to_sql' method for KeyParameters of those
1135/// different data types. The five different data types for KeyParameter values are:
1136/// i) enums of u32
1137/// ii) u32
1138/// iii) u64
1139/// iv) Vec<u8>
1140/// v) bool
1141#[cfg(test)]
1142mod storage_tests {
1143 use crate::error::*;
1144 use crate::key_parameter::*;
1145 use anyhow::Result;
1146 use rusqlite::types::ToSql;
1147 use rusqlite::{params, Connection, NO_PARAMS};
1148
1149 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
1150 /// from a database table row.
1151 #[test]
1152 fn test_new_from_sql_enum_i32() -> Result<()> {
1153 let db = init_db()?;
1154 insert_into_keyparameter(
1155 &db,
1156 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001157 Tag::ALGORITHM.0,
1158 &Algorithm::RSA.0,
1159 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001160 )?;
1161 let key_param = query_from_keyparameter(&db)?;
1162 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
1163 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
1164 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
1165 Ok(())
1166 }
1167
1168 /// Test initializing a KeyParameter (with key parameter value which is of i32)
1169 /// from a database table row.
1170 #[test]
1171 fn test_new_from_sql_i32() -> Result<()> {
1172 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001173 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001174 let key_param = query_from_keyparameter(&db)?;
1175 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
1176 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
1177 Ok(())
1178 }
1179
1180 /// Test initializing a KeyParameter (with key parameter value which is of i64)
1181 /// from a database table row.
1182 #[test]
1183 fn test_new_from_sql_i64() -> Result<()> {
1184 let db = init_db()?;
1185 // max value for i64, just to test corner cases
1186 insert_into_keyparameter(
1187 &db,
1188 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001189 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001190 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001191 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001192 )?;
1193 let key_param = query_from_keyparameter(&db)?;
1194 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
1195 assert_eq!(
1196 *key_param.key_parameter_value(),
1197 KeyParameterValue::RSAPublicExponent(i64::MAX)
1198 );
1199 Ok(())
1200 }
1201
1202 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1203 /// from a database table row.
1204 #[test]
1205 fn test_new_from_sql_bool() -> Result<()> {
1206 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001207 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001208 let key_param = query_from_keyparameter(&db)?;
1209 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1210 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1211 Ok(())
1212 }
1213
1214 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1215 /// from a database table row.
1216 #[test]
1217 fn test_new_from_sql_vec_u8() -> Result<()> {
1218 let db = init_db()?;
1219 let app_id = String::from("MyAppID");
1220 let app_id_bytes = app_id.into_bytes();
1221 insert_into_keyparameter(
1222 &db,
1223 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001224 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001225 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001226 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001227 )?;
1228 let key_param = query_from_keyparameter(&db)?;
1229 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1230 assert_eq!(
1231 *key_param.key_parameter_value(),
1232 KeyParameterValue::ApplicationID(app_id_bytes)
1233 );
1234 Ok(())
1235 }
1236
1237 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1238 /// in the database
1239 #[test]
1240 fn test_to_sql_enum_i32() -> Result<()> {
1241 let db = init_db()?;
1242 let kp = KeyParameter::new(
1243 KeyParameterValue::Algorithm(Algorithm::RSA),
1244 SecurityLevel::STRONGBOX,
1245 );
1246 store_keyparameter(&db, 1, &kp)?;
1247 let key_param = query_from_keyparameter(&db)?;
1248 assert_eq!(kp.get_tag(), key_param.get_tag());
1249 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1250 assert_eq!(kp.security_level(), key_param.security_level());
1251 Ok(())
1252 }
1253
1254 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1255 #[test]
1256 fn test_to_sql_i32() -> Result<()> {
1257 let db = init_db()?;
1258 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1259 store_keyparameter(&db, 1, &kp)?;
1260 let key_param = query_from_keyparameter(&db)?;
1261 assert_eq!(kp.get_tag(), key_param.get_tag());
1262 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1263 assert_eq!(kp.security_level(), key_param.security_level());
1264 Ok(())
1265 }
1266
1267 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1268 #[test]
1269 fn test_to_sql_i64() -> Result<()> {
1270 let db = init_db()?;
1271 // max value for i64, just to test corner cases
1272 let kp = KeyParameter::new(
1273 KeyParameterValue::RSAPublicExponent(i64::MAX),
1274 SecurityLevel::STRONGBOX,
1275 );
1276 store_keyparameter(&db, 1, &kp)?;
1277 let key_param = query_from_keyparameter(&db)?;
1278 assert_eq!(kp.get_tag(), key_param.get_tag());
1279 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1280 assert_eq!(kp.security_level(), key_param.security_level());
1281 Ok(())
1282 }
1283
1284 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1285 #[test]
1286 fn test_to_sql_vec_u8() -> Result<()> {
1287 let db = init_db()?;
1288 let kp = KeyParameter::new(
1289 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1290 SecurityLevel::STRONGBOX,
1291 );
1292 store_keyparameter(&db, 1, &kp)?;
1293 let key_param = query_from_keyparameter(&db)?;
1294 assert_eq!(kp.get_tag(), key_param.get_tag());
1295 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1296 assert_eq!(kp.security_level(), key_param.security_level());
1297 Ok(())
1298 }
1299
1300 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1301 #[test]
1302 fn test_to_sql_bool() -> Result<()> {
1303 let db = init_db()?;
1304 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1305 store_keyparameter(&db, 1, &kp)?;
1306 let key_param = query_from_keyparameter(&db)?;
1307 assert_eq!(kp.get_tag(), key_param.get_tag());
1308 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1309 assert_eq!(kp.security_level(), key_param.security_level());
1310 Ok(())
1311 }
1312
1313 #[test]
1314 /// Test Tag::Invalid
1315 fn test_invalid_tag() -> Result<()> {
1316 let db = init_db()?;
1317 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1318 let key_param = query_from_keyparameter(&db)?;
1319 assert_eq!(Tag::INVALID, key_param.get_tag());
1320 Ok(())
1321 }
1322
1323 #[test]
1324 fn test_non_existing_enum_variant() -> Result<()> {
1325 let db = init_db()?;
1326 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
Janis Danisevskise6efb242020-12-19 13:58:01 -08001327 let key_param = query_from_keyparameter(&db)?;
1328 assert_eq!(Tag::INVALID, key_param.get_tag());
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001329 Ok(())
1330 }
1331
1332 #[test]
1333 fn test_invalid_conversion_from_sql() -> Result<()> {
1334 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001335 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001336 tests::check_result_contains_error_string(
1337 query_from_keyparameter(&db),
1338 "Failed to read sql data for tag: ALGORITHM.",
1339 );
1340 Ok(())
1341 }
1342
1343 /// Helper method to init database table for key parameter
1344 fn init_db() -> Result<Connection> {
1345 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1346 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1347 .context("Failed to attach databases.")?;
1348 db.execute(
1349 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1350 keyentryid INTEGER,
1351 tag INTEGER,
1352 data ANY,
1353 security_level INTEGER);",
1354 NO_PARAMS,
1355 )
1356 .context("Failed to initialize \"keyparameter\" table.")?;
1357 Ok(db)
1358 }
1359
1360 /// Helper method to insert an entry into key parameter table, with individual parameters
1361 fn insert_into_keyparameter<T: ToSql>(
1362 db: &Connection,
1363 key_id: i64,
1364 tag: i32,
1365 value: &T,
1366 security_level: i32,
1367 ) -> Result<()> {
1368 db.execute(
1369 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001370 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001371 params![key_id, tag, *value, security_level],
1372 )?;
1373 Ok(())
1374 }
1375
1376 /// Helper method to store a key parameter instance.
1377 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1378 db.execute(
1379 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001380 VALUES(?, ?, ?, ?);",
1381 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001382 )?;
1383 Ok(())
1384 }
1385
1386 /// Helper method to query a row from keyparameter table
1387 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001388 let mut stmt =
1389 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001390 let mut rows = stmt.query(NO_PARAMS)?;
1391 let row = rows.next()?.unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001392 Ok(KeyParameter::new_from_sql(
1393 Tag(row.get(0)?),
Janis Danisevskis4522c2b2020-11-27 18:04:58 -08001394 &SqlField::new(1, row),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001395 SecurityLevel(row.get(2)?),
1396 )?)
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001397 }
1398}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001399
1400/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001401/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001402/// key parameter.
1403/// i) bool
1404/// ii) integer
1405/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001406/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001407#[cfg(test)]
1408mod wire_tests {
1409 use crate::key_parameter::*;
1410 /// unit tests for to conversions
1411 #[test]
1412 fn test_convert_to_wire_invalid() {
1413 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001414 assert_eq!(
1415 KmKeyParameter { tag: Tag::INVALID, value: KmKeyParameterValue::Invalid(0) },
1416 kp.value.into()
1417 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001418 }
1419 #[test]
1420 fn test_convert_to_wire_bool() {
1421 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001422 assert_eq!(
1423 KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) },
1424 kp.value.into()
1425 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001426 }
1427 #[test]
1428 fn test_convert_to_wire_integer() {
1429 let kp = KeyParameter::new(
1430 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1431 SecurityLevel::STRONGBOX,
1432 );
Janis Danisevskise6efb242020-12-19 13:58:01 -08001433 assert_eq!(
1434 KmKeyParameter {
1435 tag: Tag::PURPOSE,
1436 value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT)
1437 },
1438 kp.value.into()
1439 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001440 }
1441 #[test]
1442 fn test_convert_to_wire_long_integer() {
1443 let kp =
1444 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001445 assert_eq!(
1446 KmKeyParameter {
1447 tag: Tag::USER_SECURE_ID,
1448 value: KmKeyParameterValue::LongInteger(i64::MAX)
1449 },
1450 kp.value.into()
1451 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001452 }
1453 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001454 fn test_convert_to_wire_blob() {
1455 let kp = KeyParameter::new(
1456 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1457 SecurityLevel::STRONGBOX,
1458 );
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001459 assert_eq!(
Janis Danisevskise6efb242020-12-19 13:58:01 -08001460 KmKeyParameter {
1461 tag: Tag::CONFIRMATION_TOKEN,
1462 value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes())
1463 },
1464 kp.value.into()
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001465 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001466 }
1467
1468 /// unit tests for from conversion
1469 #[test]
1470 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001471 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001472 assert_eq!(KeyParameterValue::Invalid, aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001473 }
1474 #[test]
1475 fn test_convert_from_wire_bool() {
1476 let aidl_kp =
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001477 KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001478 assert_eq!(KeyParameterValue::CallerNonce, aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001479 }
1480 #[test]
1481 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001482 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001483 tag: Tag::PURPOSE,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001484 value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001485 };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001486 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001487 }
1488 #[test]
1489 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001490 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001491 tag: Tag::USER_SECURE_ID,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001492 value: KmKeyParameterValue::LongInteger(i64::MAX),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001493 };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001494 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001495 }
1496 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001497 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001498 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001499 tag: Tag::CONFIRMATION_TOKEN,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001500 value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001501 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001502 assert_eq!(
1503 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
Janis Danisevskise6efb242020-12-19 13:58:01 -08001504 aidl_kp.into()
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001505 );
1506 }
1507}