blob: b3dcf45e3b187092f0b5d82b7491edfe38d277d5 [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;
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700110use serde::de::Deserializer;
111use serde::ser::Serializer;
112use serde::{Deserialize, Serialize};
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000113
Janis Danisevskise6efb242020-12-19 13:58:01 -0800114/// This trait is used to associate a primitive to any type that can be stored inside a
115/// KeyParameterValue, especially the AIDL enum types, e.g., keymint::{Algorithm, Digest, ...}.
116/// This allows for simplifying the macro rules, e.g., for reading from the SQL database.
117/// An expression like `KeyParameterValue::Algorithm(row.get(0))` would not work because
118/// a type of `Algorithm` is expected which does not implement `FromSql` and we cannot
119/// implement it because we own neither the type nor the trait.
120/// With AssociatePrimitive we can write an expression
121/// `KeyParameter::Algorithm(<Algorithm>::from_primitive(row.get(0)))` to inform `get`
122/// about the expected primitive type that it can convert into. By implementing this
123/// trait for all inner types we can write a single rule to cover all cases (except where
124/// there is no wrapped type):
125/// `KeyParameterValue::$vname(<$vtype>::from_primitive(row.get(0)))`
126trait AssociatePrimitive {
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700127 type Primitive: Into<Primitive> + TryFrom<Primitive>;
Janis Danisevskise6efb242020-12-19 13:58:01 -0800128
129 fn from_primitive(v: Self::Primitive) -> Self;
130 fn to_primitive(&self) -> Self::Primitive;
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000131}
132
Janis Danisevskise6efb242020-12-19 13:58:01 -0800133/// Associates the given type with i32. The macro assumes that the given type is actually a
134/// tuple struct wrapping i32, such as AIDL enum types.
135macro_rules! implement_associate_primitive_for_aidl_enum {
136 ($t:ty) => {
137 impl AssociatePrimitive for $t {
138 type Primitive = i32;
139
140 fn from_primitive(v: Self::Primitive) -> Self {
141 Self(v)
142 }
143 fn to_primitive(&self) -> Self::Primitive {
144 self.0
145 }
146 }
147 };
148}
149
150/// Associates the given type with itself.
151macro_rules! implement_associate_primitive_identity {
152 ($t:ty) => {
153 impl AssociatePrimitive for $t {
154 type Primitive = $t;
155
156 fn from_primitive(v: Self::Primitive) -> Self {
157 v
158 }
159 fn to_primitive(&self) -> Self::Primitive {
160 self.clone()
161 }
162 }
163 };
164}
165
166implement_associate_primitive_for_aidl_enum! {Algorithm}
167implement_associate_primitive_for_aidl_enum! {BlockMode}
168implement_associate_primitive_for_aidl_enum! {Digest}
169implement_associate_primitive_for_aidl_enum! {EcCurve}
170implement_associate_primitive_for_aidl_enum! {HardwareAuthenticatorType}
171implement_associate_primitive_for_aidl_enum! {KeyOrigin}
172implement_associate_primitive_for_aidl_enum! {KeyPurpose}
173implement_associate_primitive_for_aidl_enum! {PaddingMode}
174implement_associate_primitive_for_aidl_enum! {SecurityLevel}
175
176implement_associate_primitive_identity! {Vec<u8>}
177implement_associate_primitive_identity! {i64}
178implement_associate_primitive_identity! {i32}
179
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800180/// This enum allows passing a primitive value to `KeyParameterValue::new_from_tag_primitive_pair`
181/// Usually, it is not necessary to use this type directly because the function uses
182/// `Into<Primitive>` as a trait bound.
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700183#[derive(Deserialize, Serialize)]
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800184pub enum Primitive {
185 /// Wraps an i64.
186 I64(i64),
187 /// Wraps an i32.
188 I32(i32),
189 /// Wraps a Vec<u8>.
190 Vec(Vec<u8>),
191}
192
193impl From<i64> for Primitive {
194 fn from(v: i64) -> Self {
195 Self::I64(v)
196 }
197}
198impl From<i32> for Primitive {
199 fn from(v: i32) -> Self {
200 Self::I32(v)
201 }
202}
203impl From<Vec<u8>> for Primitive {
204 fn from(v: Vec<u8>) -> Self {
205 Self::Vec(v)
206 }
207}
208
209/// This error is returned by `KeyParameterValue::new_from_tag_primitive_pair`.
210#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)]
211pub enum PrimitiveError {
212 /// Returned if this primitive is unsuitable for the given tag type.
213 #[error("Primitive does not match the expected tag type.")]
214 TypeMismatch,
215 /// Return if the tag type is unknown.
216 #[error("Unknown tag.")]
217 UnknownTag,
218}
219
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700220impl TryFrom<Primitive> for i64 {
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800221 type Error = PrimitiveError;
222
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700223 fn try_from(p: Primitive) -> Result<i64, Self::Error> {
224 match p {
225 Primitive::I64(v) => Ok(v),
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800226 _ => Err(Self::Error::TypeMismatch),
227 }
228 }
229}
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700230impl TryFrom<Primitive> for i32 {
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800231 type Error = PrimitiveError;
232
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700233 fn try_from(p: Primitive) -> Result<i32, Self::Error> {
234 match p {
235 Primitive::I32(v) => Ok(v),
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800236 _ => Err(Self::Error::TypeMismatch),
237 }
238 }
239}
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700240impl TryFrom<Primitive> for Vec<u8> {
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800241 type Error = PrimitiveError;
242
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700243 fn try_from(p: Primitive) -> Result<Vec<u8>, Self::Error> {
244 match p {
245 Primitive::Vec(v) => Ok(v),
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800246 _ => Err(Self::Error::TypeMismatch),
247 }
248 }
249}
250
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700251fn serialize_primitive<S, P>(v: &P, serializer: S) -> Result<S::Ok, S::Error>
252where
253 S: Serializer,
254 P: AssociatePrimitive,
255{
256 let primitive: Primitive = v.to_primitive().into();
257 primitive.serialize(serializer)
258}
259
260fn deserialize_primitive<'de, D, T>(deserializer: D) -> Result<T, D::Error>
261where
262 D: Deserializer<'de>,
263 T: AssociatePrimitive,
264{
265 let primitive: Primitive = serde::de::Deserialize::deserialize(deserializer)?;
266 Ok(T::from_primitive(
267 primitive.try_into().map_err(|_| serde::de::Error::custom("Type Mismatch"))?,
268 ))
269}
270
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800271/// Expands the list of KeyParameterValue variants as follows:
272///
273/// Input:
274/// Invalid with tag INVALID and field Invalid,
275/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
276///
277/// Output:
278/// ```
279/// pub fn new_from_tag_primitive_pair<T: Into<Primitive>>(
280/// tag: Tag,
281/// v: T
282/// ) -> Result<KeyParameterValue, PrimitiveError> {
283/// let p: Primitive = v.into();
284/// Ok(match tag {
285/// Tag::INVALID => KeyParameterValue::Invalid,
286/// Tag::ALGORITHM => KeyParameterValue::Algorithm(
287/// <Algorithm>::from_primitive(p.try_into()?)
288/// ),
289/// _ => return Err(PrimitiveError::UnknownTag),
290/// })
291/// }
292/// ```
293macro_rules! implement_from_tag_primitive_pair {
294 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
295 /// Returns the an instance of $enum_name or an error if the given primitive does not match
296 /// the tag type or the tag is unknown.
297 pub fn new_from_tag_primitive_pair<T: Into<Primitive>>(
298 tag: Tag,
299 v: T
300 ) -> Result<$enum_name, PrimitiveError> {
301 let p: Primitive = v.into();
302 Ok(match tag {
303 $(Tag::$tag_name => $enum_name::$vname$((
304 <$vtype>::from_primitive(p.try_into()?)
305 ))?,)*
306 _ => return Err(PrimitiveError::UnknownTag),
307 })
308 }
309 };
310}
311
Janis Danisevskise6efb242020-12-19 13:58:01 -0800312/// Expands the list of KeyParameterValue variants as follows:
313///
314/// Input:
315/// pub enum KeyParameterValue {
316/// Invalid with tag INVALID and field Invalid,
317/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
318/// }
319///
320/// Output:
321/// ```
322/// pub enum KeyParameterValue {
323/// Invalid,
324/// Algorithm(Algorithm),
325/// }
326/// ```
327macro_rules! implement_enum {
328 (
329 $(#[$enum_meta:meta])*
330 $enum_vis:vis enum $enum_name:ident {
331 $($(#[$emeta:meta])* $vname:ident$(($vtype:ty))?),* $(,)?
332 }
333 ) => {
334 $(#[$enum_meta])*
335 $enum_vis enum $enum_name {
336 $(
337 $(#[$emeta])*
338 $vname$(($vtype))?
339 ),*
340 }
341 };
342}
343
344/// Expands the list of KeyParameterValue variants as follows:
345///
346/// Input:
347/// Invalid with tag INVALID and field Invalid,
348/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
349///
350/// Output:
351/// ```
352/// pub fn get_tag(&self) -> Tag {
353/// match self {
354/// KeyParameterValue::Invalid => Tag::INVALID,
355/// KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
356/// }
357/// }
358/// ```
359macro_rules! implement_get_tag {
360 (
361 @replace_type_spec
362 $enum_name:ident,
363 [$($out:tt)*],
364 [$vname:ident($vtype:ty) $tag_name:ident, $($in:tt)*]
365 ) => {
366 implement_get_tag!{@replace_type_spec $enum_name, [$($out)*
367 $enum_name::$vname(_) => Tag::$tag_name,
368 ], [$($in)*]}
369 };
370 (
371 @replace_type_spec
372 $enum_name:ident,
373 [$($out:tt)*],
374 [$vname:ident $tag_name:ident, $($in:tt)*]
375 ) => {
376 implement_get_tag!{@replace_type_spec $enum_name, [$($out)*
377 $enum_name::$vname => Tag::$tag_name,
378 ], [$($in)*]}
379 };
380 (@replace_type_spec $enum_name:ident, [$($out:tt)*], []) => {
381 /// Returns the tag of the given instance.
382 pub fn get_tag(&self) -> Tag {
383 match self {
384 $($out)*
385 }
386 }
387 };
388
389 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
390 implement_get_tag!{@replace_type_spec $enum_name, [], [$($vname$(($vtype))? $tag_name,)*]}
391 };
392}
393
394/// Expands the list of KeyParameterValue variants as follows:
395///
396/// Input:
397/// Invalid with tag INVALID and field Invalid,
398/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
399///
400/// Output:
401/// ```
402/// fn to_sql(&self) -> SqlResult<ToSqlOutput> {
403/// match self {
404/// KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
405/// KeyParameterValue::Algorithm(v) => Ok(ToSqlOutput::from(v.to_primitive())),
406/// }
407/// }
408/// ```
409macro_rules! implement_to_sql {
410 (
411 @replace_type_spec
412 $enum_name:ident,
413 [$($out:tt)*],
414 [$vname:ident($vtype:ty), $($in:tt)*]
415 ) => {
416 implement_to_sql!{@replace_type_spec $enum_name, [ $($out)*
417 $enum_name::$vname(v) => Ok(ToSqlOutput::from(v.to_primitive())),
418 ], [$($in)*]}
419 };
420 (
421 @replace_type_spec
422 $enum_name:ident,
423 [$($out:tt)*],
424 [$vname:ident, $($in:tt)*]
425 ) => {
426 implement_to_sql!{@replace_type_spec $enum_name, [ $($out)*
427 $enum_name::$vname => Ok(ToSqlOutput::from(Null)),
428 ], [$($in)*]}
429 };
430 (@replace_type_spec $enum_name:ident, [$($out:tt)*], []) => {
431 /// Converts $enum_name to be stored in a rusqlite database.
432 fn to_sql(&self) -> SqlResult<ToSqlOutput> {
433 match self {
434 $($out)*
435 }
436 }
437 };
438
439
440 ($enum_name:ident; $($vname:ident$(($vtype:ty))?),*) => {
441 impl ToSql for $enum_name {
442 implement_to_sql!{@replace_type_spec $enum_name, [], [$($vname$(($vtype))?,)*]}
443 }
444
445 }
446}
447
448/// Expands the list of KeyParameterValue variants as follows:
449///
450/// Input:
451/// Invalid with tag INVALID and field Invalid,
452/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
453///
454/// Output:
455/// ```
456/// pub fn new_from_sql(
457/// tag: Tag,
458/// data: &SqlField,
459/// ) -> Result<Self> {
460/// Ok(match self {
461/// Tag::Invalid => KeyParameterValue::Invalid,
462/// Tag::ALGORITHM => {
463/// KeyParameterValue::Algorithm(<Algorithm>::from_primitive(data
464/// .get()
465/// .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
466/// .context(concat!("Failed to read sql data for tag: ", "ALGORITHM", "."))?
467/// ))
468/// },
469/// })
470/// }
471/// ```
472macro_rules! implement_new_from_sql {
473 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
474 /// Takes a tag and an SqlField and attempts to construct a KeyParameter value.
475 /// This function may fail if the parameter value cannot be extracted from the
476 /// database cell.
477 pub fn new_from_sql(
478 tag: Tag,
479 data: &SqlField,
480 ) -> Result<Self> {
481 Ok(match tag {
482 $(
483 Tag::$tag_name => {
484 $enum_name::$vname$((<$vtype>::from_primitive(data
485 .get()
486 .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
487 .context(concat!(
488 "Failed to read sql data for tag: ",
489 stringify!($tag_name),
490 "."
491 ))?
492 )))?
493 },
494 )*
495 _ => $enum_name::Invalid,
496 })
497 }
498 };
499}
500
501/// This key parameter default is used during the conversion from KeyParameterValue
502/// to keymint::KeyParameterValue. Keystore's version does not have wrapped types
503/// for boolean tags and the tag Invalid. The AIDL version uses bool and integer
504/// variants respectively. This default function is invoked in these cases to
505/// homogenize the rules for boolean and invalid tags.
506/// The bool variant returns true because boolean parameters are implicitly true
507/// if present.
508trait KpDefault {
509 fn default() -> Self;
510}
511
512impl KpDefault for i32 {
513 fn default() -> Self {
514 0
515 }
516}
517
518impl KpDefault for bool {
519 fn default() -> Self {
520 true
521 }
522}
523
524/// Expands the list of KeyParameterValue variants as follows:
525///
526/// Input:
527/// Invalid with tag INVALID and field Invalid,
528/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
529///
530/// Output:
531/// ```
532/// impl From<KmKeyParameter> for KeyParameterValue {
533/// fn from(kp: KmKeyParameter) -> Self {
534/// match kp {
535/// KmKeyParameter { tag: Tag::INVALID, value: KmKeyParameterValue::Invalid(_) }
536/// => $enum_name::$vname,
537/// KmKeyParameter { tag: Tag::Algorithm, value: KmKeyParameterValue::Algorithm(v) }
538/// => $enum_name::Algorithm(v),
539/// _ => $enum_name::Invalid,
540/// }
541/// }
542/// }
543///
544/// impl Into<KmKeyParameter> for KeyParameterValue {
545/// fn into(self) -> KmKeyParameter {
546/// match self {
547/// KeyParameterValue::Invalid => KmKeyParameter {
548/// tag: Tag::INVALID,
549/// value: KmKeyParameterValue::Invalid(KpDefault::default())
550/// },
551/// KeyParameterValue::Algorithm(v) => KmKeyParameter {
552/// tag: Tag::ALGORITHM,
553/// value: KmKeyParameterValue::Algorithm(v)
554/// },
555/// }
556/// }
557/// }
558/// ```
559macro_rules! implement_try_from_to_km_parameter {
560 // The first three rules expand From<KmKeyParameter>.
561 (
562 @from
563 $enum_name:ident,
564 [$($out:tt)*],
565 [$vname:ident($vtype:ty) $tag_name:ident $field_name:ident, $($in:tt)*]
566 ) => {
567 implement_try_from_to_km_parameter!{@from $enum_name, [$($out)*
568 KmKeyParameter {
569 tag: Tag::$tag_name,
570 value: KmKeyParameterValue::$field_name(v)
571 } => $enum_name::$vname(v),
572 ], [$($in)*]
573 }};
574 (
575 @from
576 $enum_name:ident,
577 [$($out:tt)*],
578 [$vname:ident $tag_name:ident $field_name:ident, $($in:tt)*]
579 ) => {
580 implement_try_from_to_km_parameter!{@from $enum_name, [$($out)*
581 KmKeyParameter {
582 tag: Tag::$tag_name,
583 value: KmKeyParameterValue::$field_name(_)
584 } => $enum_name::$vname,
585 ], [$($in)*]
586 }};
587 (@from $enum_name:ident, [$($out:tt)*], []) => {
588 impl From<KmKeyParameter> for $enum_name {
589 fn from(kp: KmKeyParameter) -> Self {
590 match kp {
591 $($out)*
592 _ => $enum_name::Invalid,
593 }
594 }
595 }
596 };
597
598 // The next three rules expand Into<KmKeyParameter>.
599 (
600 @into
601 $enum_name:ident,
602 [$($out:tt)*],
603 [$vname:ident($vtype:ty) $tag_name:ident $field_name:ident, $($in:tt)*]
604 ) => {
605 implement_try_from_to_km_parameter!{@into $enum_name, [$($out)*
606 $enum_name::$vname(v) => KmKeyParameter {
607 tag: Tag::$tag_name,
608 value: KmKeyParameterValue::$field_name(v)
609 },
610 ], [$($in)*]
611 }};
612 (
613 @into
614 $enum_name:ident,
615 [$($out:tt)*],
616 [$vname:ident $tag_name:ident $field_name:ident, $($in:tt)*]
617 ) => {
618 implement_try_from_to_km_parameter!{@into $enum_name, [$($out)*
619 $enum_name::$vname => KmKeyParameter {
620 tag: Tag::$tag_name,
621 value: KmKeyParameterValue::$field_name(KpDefault::default())
622 },
623 ], [$($in)*]
624 }};
625 (@into $enum_name:ident, [$($out:tt)*], []) => {
Matthew Maurerb77a28d2021-05-07 16:08:20 -0700626 impl From<$enum_name> for KmKeyParameter {
627 fn from(x: $enum_name) -> Self {
628 match x {
Janis Danisevskise6efb242020-12-19 13:58:01 -0800629 $($out)*
630 }
631 }
632 }
633 };
634
635
636 ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident $field_name:ident),*) => {
637 implement_try_from_to_km_parameter!(
638 @from $enum_name,
639 [],
640 [$($vname$(($vtype))? $tag_name $field_name,)*]
641 );
642 implement_try_from_to_km_parameter!(
643 @into $enum_name,
644 [],
645 [$($vname$(($vtype))? $tag_name $field_name,)*]
646 );
647 };
648}
649
650/// This is the top level macro. While the other macros do most of the heavy lifting, this takes
651/// the key parameter list and passes it on to the other macros to generate all of the conversion
652/// functions. In addition, it generates an important test vector for verifying that tag type of the
653/// keymint tag matches the associated keymint KeyParameterValue field.
654macro_rules! implement_key_parameter_value {
655 (
656 $(#[$enum_meta:meta])*
657 $enum_vis:vis enum $enum_name:ident {
658 $(
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800659 $(#[$($emeta:tt)+])*
660 $vname:ident$(($vtype:ty))?
Janis Danisevskise6efb242020-12-19 13:58:01 -0800661 ),* $(,)?
662 }
663 ) => {
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800664 implement_key_parameter_value!{
665 @extract_attr
666 $(#[$enum_meta])*
667 $enum_vis enum $enum_name {
668 []
669 [$(
670 [] [$(#[$($emeta)+])*]
671 $vname$(($vtype))?,
672 )*]
673 }
674 }
675 };
676
677 (
678 @extract_attr
679 $(#[$enum_meta:meta])*
680 $enum_vis:vis enum $enum_name:ident {
681 [$($out:tt)*]
682 [
683 [$(#[$mout:meta])*]
684 [
685 #[key_param(tag = $tag_name:ident, field = $field_name:ident)]
686 $(#[$($mtail:tt)+])*
687 ]
688 $vname:ident$(($vtype:ty))?,
689 $($tail:tt)*
690 ]
691 }
692 ) => {
693 implement_key_parameter_value!{
694 @extract_attr
695 $(#[$enum_meta])*
696 $enum_vis enum $enum_name {
697 [
698 $($out)*
699 $(#[$mout])*
700 $(#[$($mtail)+])*
701 $tag_name $field_name $vname$(($vtype))?,
702 ]
703 [$($tail)*]
704 }
705 }
706 };
707
708 (
709 @extract_attr
710 $(#[$enum_meta:meta])*
711 $enum_vis:vis enum $enum_name:ident {
712 [$($out:tt)*]
713 [
714 [$(#[$mout:meta])*]
715 [
716 #[$front:meta]
717 $(#[$($mtail:tt)+])*
718 ]
719 $vname:ident$(($vtype:ty))?,
720 $($tail:tt)*
721 ]
722 }
723 ) => {
724 implement_key_parameter_value!{
725 @extract_attr
726 $(#[$enum_meta])*
727 $enum_vis enum $enum_name {
728 [$($out)*]
729 [
730 [
731 $(#[$mout])*
732 #[$front]
733 ]
734 [$(#[$($mtail)+])*]
735 $vname$(($vtype))?,
736 $($tail)*
737 ]
738 }
739 }
740 };
741
742 (
743 @extract_attr
744 $(#[$enum_meta:meta])*
745 $enum_vis:vis enum $enum_name:ident {
746 [$($out:tt)*]
747 []
748 }
749 ) => {
750 implement_key_parameter_value!{
751 @spill
752 $(#[$enum_meta])*
753 $enum_vis enum $enum_name {
754 $($out)*
755 }
756 }
757 };
758
759 (
760 @spill
761 $(#[$enum_meta:meta])*
762 $enum_vis:vis enum $enum_name:ident {
763 $(
764 $(#[$emeta:meta])*
765 $tag_name:ident $field_name:ident $vname:ident$(($vtype:ty))?,
766 )*
767 }
768 ) => {
Janis Danisevskise6efb242020-12-19 13:58:01 -0800769 implement_enum!(
770 $(#[$enum_meta])*
771 $enum_vis enum $enum_name {
772 $(
773 $(#[$emeta])*
774 $vname$(($vtype))?
775 ),*
776 });
777
778 impl $enum_name {
779 implement_new_from_sql!($enum_name; $($vname$(($vtype))? $tag_name),*);
780 implement_get_tag!($enum_name; $($vname$(($vtype))? $tag_name),*);
Janis Danisevskis6b00e252020-12-22 11:36:45 -0800781 implement_from_tag_primitive_pair!($enum_name; $($vname$(($vtype))? $tag_name),*);
Janis Danisevskise6efb242020-12-19 13:58:01 -0800782
783 #[cfg(test)]
784 fn make_field_matches_tag_type_test_vector() -> Vec<KmKeyParameter> {
785 vec![$(KmKeyParameter{
786 tag: Tag::$tag_name,
787 value: KmKeyParameterValue::$field_name(Default::default())}
788 ),*]
789 }
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700790
791 #[cfg(test)]
792 fn make_key_parameter_defaults_vector() -> Vec<KeyParameter> {
793 vec![$(KeyParameter{
794 value: KeyParameterValue::$vname$((<$vtype as Default>::default()))?,
795 security_level: SecurityLevel(100),
796 }),*]
797 }
Janis Danisevskise6efb242020-12-19 13:58:01 -0800798 }
799
800 implement_try_from_to_km_parameter!(
801 $enum_name;
802 $($vname$(($vtype))? $tag_name $field_name),*
803 );
804
805 implement_to_sql!($enum_name; $($vname$(($vtype))?),*);
806 };
807}
808
809implement_key_parameter_value! {
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000810/// KeyParameterValue holds a value corresponding to one of the Tags defined in
Shawn Willden525c0032021-03-29 13:58:33 +0000811/// the AIDL spec at hardware/interfaces/security/keymint
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700812#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize)]
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000813pub enum KeyParameterValue {
814 /// Associated with Tag:INVALID
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800815 #[key_param(tag = INVALID, field = Invalid)]
816 Invalid,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000817 /// Set of purposes for which the key may be used
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700818 #[serde(deserialize_with = "deserialize_primitive")]
819 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800820 #[key_param(tag = PURPOSE, field = KeyPurpose)]
821 KeyPurpose(KeyPurpose),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000822 /// Cryptographic algorithm with which the key is used
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700823 #[serde(deserialize_with = "deserialize_primitive")]
824 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800825 #[key_param(tag = ALGORITHM, field = Algorithm)]
826 Algorithm(Algorithm),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000827 /// Size of the key , in bits
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800828 #[key_param(tag = KEY_SIZE, field = Integer)]
829 KeySize(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000830 /// Block cipher mode(s) with which the key may be used
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700831 #[serde(deserialize_with = "deserialize_primitive")]
832 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800833 #[key_param(tag = BLOCK_MODE, field = BlockMode)]
834 BlockMode(BlockMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000835 /// Digest algorithms that may be used with the key to perform signing and verification
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700836 #[serde(deserialize_with = "deserialize_primitive")]
837 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800838 #[key_param(tag = DIGEST, field = Digest)]
839 Digest(Digest),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000840 /// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700841 #[serde(deserialize_with = "deserialize_primitive")]
842 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800843 #[key_param(tag = PADDING, field = PaddingMode)]
844 PaddingMode(PaddingMode),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000845 /// Can the caller provide a nonce for nonce-requiring operations
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800846 #[key_param(tag = CALLER_NONCE, field = BoolValue)]
847 CallerNonce,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000848 /// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800849 #[key_param(tag = MIN_MAC_LENGTH, field = Integer)]
850 MinMacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000851 /// The elliptic curve
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700852 #[serde(deserialize_with = "deserialize_primitive")]
853 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800854 #[key_param(tag = EC_CURVE, field = EcCurve)]
855 EcCurve(EcCurve),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000856 /// Value of the public exponent for an RSA key pair
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800857 #[key_param(tag = RSA_PUBLIC_EXPONENT, field = LongInteger)]
858 RSAPublicExponent(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000859 /// An attestation certificate for the generated key should contain an application-scoped
860 /// and time-bounded device-unique ID
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800861 #[key_param(tag = INCLUDE_UNIQUE_ID, field = BoolValue)]
862 IncludeUniqueID,
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000863 //TODO: find out about this
864 // /// Necessary system environment conditions for the generated key to be used
865 // KeyBlobUsageRequirements(KeyBlobUsageRequirements),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000866 /// Only the boot loader can use the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800867 #[key_param(tag = BOOTLOADER_ONLY, field = BoolValue)]
868 BootLoaderOnly,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000869 /// When deleted, the key is guaranteed to be permanently deleted and unusable
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800870 #[key_param(tag = ROLLBACK_RESISTANCE, field = BoolValue)]
871 RollbackResistance,
Janis Danisevskis5c748212021-05-17 17:13:56 -0700872 /// The Key shall only be used during the early boot stage
873 #[key_param(tag = EARLY_BOOT_ONLY, field = BoolValue)]
874 EarlyBootOnly,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000875 /// The date and time at which the key becomes active
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800876 #[key_param(tag = ACTIVE_DATETIME, field = DateTime)]
877 ActiveDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000878 /// The date and time at which the key expires for signing and encryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800879 #[key_param(tag = ORIGINATION_EXPIRE_DATETIME, field = DateTime)]
880 OriginationExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000881 /// The date and time at which the key expires for verification and decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800882 #[key_param(tag = USAGE_EXPIRE_DATETIME, field = DateTime)]
883 UsageExpireDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000884 /// Minimum amount of time that elapses between allowed operations
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800885 #[key_param(tag = MIN_SECONDS_BETWEEN_OPS, field = Integer)]
886 MinSecondsBetweenOps(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000887 /// Maximum number of times that a key may be used between system reboots
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800888 #[key_param(tag = MAX_USES_PER_BOOT, field = Integer)]
889 MaxUsesPerBoot(i32),
Qi Wub9433b52020-12-01 14:52:46 +0800890 /// The number of times that a limited use key can be used
891 #[key_param(tag = USAGE_COUNT_LIMIT, field = Integer)]
892 UsageCountLimit(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000893 /// ID of the Android user that is permitted to use the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800894 #[key_param(tag = USER_ID, field = Integer)]
895 UserID(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000896 /// A key may only be used under a particular secure user authentication state
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800897 #[key_param(tag = USER_SECURE_ID, field = LongInteger)]
898 UserSecureID(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000899 /// No authentication is required to use this key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800900 #[key_param(tag = NO_AUTH_REQUIRED, field = BoolValue)]
901 NoAuthRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000902 /// The types of user authenticators that may be used to authorize this key
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700903 #[serde(deserialize_with = "deserialize_primitive")]
904 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800905 #[key_param(tag = USER_AUTH_TYPE, field = HardwareAuthenticatorType)]
906 HardwareAuthenticatorType(HardwareAuthenticatorType),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000907 /// The time in seconds for which the key is authorized for use, after user authentication
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800908 #[key_param(tag = AUTH_TIMEOUT, field = Integer)]
909 AuthTimeout(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000910 /// The key may be used after authentication timeout if device is still on-body
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800911 #[key_param(tag = ALLOW_WHILE_ON_BODY, field = BoolValue)]
912 AllowWhileOnBody,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000913 /// The key must be unusable except when the user has provided proof of physical presence
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800914 #[key_param(tag = TRUSTED_USER_PRESENCE_REQUIRED, field = BoolValue)]
915 TrustedUserPresenceRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000916 /// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
917 /// unless the user provides confirmation of the data to be signed
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800918 #[key_param(tag = TRUSTED_CONFIRMATION_REQUIRED, field = BoolValue)]
919 TrustedConfirmationRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000920 /// The key may only be used when the device is unlocked
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800921 #[key_param(tag = UNLOCKED_DEVICE_REQUIRED, field = BoolValue)]
922 UnlockedDeviceRequired,
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000923 /// When provided to generateKey or importKey, this tag specifies data
924 /// that is necessary during all uses of the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800925 #[key_param(tag = APPLICATION_ID, field = Blob)]
926 ApplicationID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000927 /// When provided to generateKey or importKey, this tag specifies data
928 /// that is necessary during all uses of the key
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800929 #[key_param(tag = APPLICATION_DATA, field = Blob)]
930 ApplicationData(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000931 /// Specifies the date and time the key was created
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800932 #[key_param(tag = CREATION_DATETIME, field = DateTime)]
933 CreationDateTime(i64),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000934 /// Specifies where the key was created, if known
Janis Danisevskis5d772ef2022-03-17 20:06:33 -0700935 #[serde(deserialize_with = "deserialize_primitive")]
936 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800937 #[key_param(tag = ORIGIN, field = Origin)]
938 KeyOrigin(KeyOrigin),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000939 /// The key used by verified boot to validate the operating system booted
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800940 #[key_param(tag = ROOT_OF_TRUST, field = Blob)]
941 RootOfTrust(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000942 /// System OS version with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800943 #[key_param(tag = OS_VERSION, field = Integer)]
944 OSVersion(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000945 /// Specifies the system security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800946 #[key_param(tag = OS_PATCHLEVEL, field = Integer)]
947 OSPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000948 /// Specifies a unique, time-based identifier
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800949 #[key_param(tag = UNIQUE_ID, field = Blob)]
950 UniqueID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000951 /// Used to deliver a "challenge" value to the attestKey() method
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800952 #[key_param(tag = ATTESTATION_CHALLENGE, field = Blob)]
953 AttestationChallenge(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000954 /// The set of applications which may use a key, used only with attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800955 #[key_param(tag = ATTESTATION_APPLICATION_ID, field = Blob)]
956 AttestationApplicationID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000957 /// Provides the device's brand name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800958 #[key_param(tag = ATTESTATION_ID_BRAND, field = Blob)]
959 AttestationIdBrand(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000960 /// Provides the device's device name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800961 #[key_param(tag = ATTESTATION_ID_DEVICE, field = Blob)]
962 AttestationIdDevice(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000963 /// Provides the device's product name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800964 #[key_param(tag = ATTESTATION_ID_PRODUCT, field = Blob)]
965 AttestationIdProduct(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000966 /// Provides the device's serial number, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800967 #[key_param(tag = ATTESTATION_ID_SERIAL, field = Blob)]
968 AttestationIdSerial(Vec<u8>),
Eran Messeri637259c2022-10-31 12:23:36 +0000969 /// Provides the primary IMEI for the device, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800970 #[key_param(tag = ATTESTATION_ID_IMEI, field = Blob)]
971 AttestationIdIMEI(Vec<u8>),
Eran Messeri637259c2022-10-31 12:23:36 +0000972 /// Provides a second IMEI for the device, to attestKey()
973 #[key_param(tag = ATTESTATION_ID_SECOND_IMEI, field = Blob)]
974 AttestationIdSecondIMEI(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000975 /// Provides the MEIDs for all radios on the device, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800976 #[key_param(tag = ATTESTATION_ID_MEID, field = Blob)]
977 AttestationIdMEID(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000978 /// Provides the device's manufacturer name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800979 #[key_param(tag = ATTESTATION_ID_MANUFACTURER, field = Blob)]
980 AttestationIdManufacturer(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000981 /// Provides the device's model name, to attestKey()
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800982 #[key_param(tag = ATTESTATION_ID_MODEL, field = Blob)]
983 AttestationIdModel(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000984 /// Specifies the vendor image security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800985 #[key_param(tag = VENDOR_PATCHLEVEL, field = Integer)]
986 VendorPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000987 /// Specifies the boot image (kernel) security patch level with which the key may be used
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800988 #[key_param(tag = BOOT_PATCHLEVEL, field = Integer)]
989 BootPatchLevel(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000990 /// Provides "associated data" for AES-GCM encryption or decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800991 #[key_param(tag = ASSOCIATED_DATA, field = Blob)]
992 AssociatedData(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000993 /// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
994 /// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800995 #[key_param(tag = NONCE, field = Blob)]
996 Nonce(Vec<u8>),
Hasini Gunasinghe12486362020-07-24 18:40:20 +0000997 /// Provides the requested length of a MAC or GCM authentication tag, in bits
Janis Danisevskis6f1bb562020-12-28 15:52:41 -0800998 #[key_param(tag = MAC_LENGTH, field = Integer)]
999 MacLength(i32),
Hasini Gunasinghe12486362020-07-24 18:40:20 +00001000 /// Specifies whether the device has been factory reset since the
1001 /// last unique ID rotation. Used for key attestation
Janis Danisevskis6f1bb562020-12-28 15:52:41 -08001002 #[key_param(tag = RESET_SINCE_ID_ROTATION, field = BoolValue)]
1003 ResetSinceIdRotation,
Hasini Gunasinghe12486362020-07-24 18:40:20 +00001004 /// Used to deliver a cryptographic token proving that the user
Janis Danisevskis2c084012021-01-31 22:23:17 -08001005 /// confirmed a signing request
Janis Danisevskis6f1bb562020-12-28 15:52:41 -08001006 #[key_param(tag = CONFIRMATION_TOKEN, field = Blob)]
1007 ConfirmationToken(Vec<u8>),
Janis Danisevskis2c084012021-01-31 22:23:17 -08001008 /// Used to deliver the certificate serial number to the KeyMint instance
1009 /// certificate generation.
1010 #[key_param(tag = CERTIFICATE_SERIAL, field = Blob)]
1011 CertificateSerial(Vec<u8>),
1012 /// Used to deliver the certificate subject to the KeyMint instance
1013 /// certificate generation. This must be DER encoded X509 name.
1014 #[key_param(tag = CERTIFICATE_SUBJECT, field = Blob)]
1015 CertificateSubject(Vec<u8>),
1016 /// Used to deliver the not before date in milliseconds to KeyMint during key generation/import.
1017 #[key_param(tag = CERTIFICATE_NOT_BEFORE, field = DateTime)]
1018 CertificateNotBefore(i64),
1019 /// Used to deliver the not after date in milliseconds to KeyMint during key generation/import.
1020 #[key_param(tag = CERTIFICATE_NOT_AFTER, field = DateTime)]
1021 CertificateNotAfter(i64),
Paul Crowley7c57bf12021-02-02 16:26:57 -08001022 /// Specifies a maximum boot level at which a key should function
1023 #[key_param(tag = MAX_BOOT_LEVEL, field = Integer)]
1024 MaxBootLevel(i32),
Janis Danisevskise6efb242020-12-19 13:58:01 -08001025}
1026}
1027
1028impl From<&KmKeyParameter> for KeyParameterValue {
1029 fn from(kp: &KmKeyParameter) -> Self {
1030 kp.clone().into()
1031 }
1032}
1033
1034/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
Janis Danisevskis5d772ef2022-03-17 20:06:33 -07001035#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Serialize, Deserialize)]
Janis Danisevskise6efb242020-12-19 13:58:01 -08001036pub struct KeyParameter {
1037 value: KeyParameterValue,
Janis Danisevskis5d772ef2022-03-17 20:06:33 -07001038 #[serde(deserialize_with = "deserialize_primitive")]
1039 #[serde(serialize_with = "serialize_primitive")]
Janis Danisevskise6efb242020-12-19 13:58:01 -08001040 security_level: SecurityLevel,
Hasini Gunasinghe12486362020-07-24 18:40:20 +00001041}
1042
1043impl KeyParameter {
1044 /// Create an instance of KeyParameter, given the value and the security level.
Janis Danisevskise6efb242020-12-19 13:58:01 -08001045 pub fn new(value: KeyParameterValue, security_level: SecurityLevel) -> Self {
1046 KeyParameter { value, security_level }
Hasini Gunasinghe12486362020-07-24 18:40:20 +00001047 }
1048
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001049 /// Construct a KeyParameter from the data from a rusqlite row.
1050 /// Note that following variants of KeyParameterValue should not be stored:
1051 /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
1052 /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
1053 /// This filtering is enforced at a higher level and here we support conversion for all the
1054 /// variants.
1055 pub fn new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001056 tag_val: Tag,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001057 data: &SqlField,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001058 security_level_val: SecurityLevel,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001059 ) -> Result<Self> {
Janis Danisevskise6efb242020-12-19 13:58:01 -08001060 Ok(Self {
1061 value: KeyParameterValue::new_from_sql(tag_val, data)?,
1062 security_level: security_level_val,
1063 })
1064 }
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001065
Janis Danisevskise6efb242020-12-19 13:58:01 -08001066 /// Get the KeyMint Tag of this this key parameter.
1067 pub fn get_tag(&self) -> Tag {
1068 self.value.get_tag()
1069 }
1070
1071 /// Returns key parameter value.
1072 pub fn key_parameter_value(&self) -> &KeyParameterValue {
1073 &self.value
1074 }
1075
1076 /// Returns the security level of this key parameter.
1077 pub fn security_level(&self) -> &SecurityLevel {
1078 &self.security_level
1079 }
1080
1081 /// An authorization is a KeyParameter with an associated security level that is used
1082 /// to convey the key characteristics to keystore clients. This function consumes
1083 /// an internal KeyParameter representation to produce the Authorization wire type.
1084 pub fn into_authorization(self) -> Authorization {
1085 Authorization { securityLevel: self.security_level, keyParameter: self.value.into() }
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001086 }
1087}
1088
Janis Danisevskise6efb242020-12-19 13:58:01 -08001089#[cfg(test)]
1090mod generated_key_parameter_tests {
1091 use super::*;
1092 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::TagType::TagType;
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001093
Janis Danisevskise6efb242020-12-19 13:58:01 -08001094 fn get_field_by_tag_type(tag: Tag) -> KmKeyParameterValue {
1095 let tag_type = TagType((tag.0 as u32 & 0xF0000000) as i32);
1096 match tag {
1097 Tag::ALGORITHM => return KmKeyParameterValue::Algorithm(Default::default()),
1098 Tag::BLOCK_MODE => return KmKeyParameterValue::BlockMode(Default::default()),
1099 Tag::PADDING => return KmKeyParameterValue::PaddingMode(Default::default()),
1100 Tag::DIGEST => return KmKeyParameterValue::Digest(Default::default()),
1101 Tag::EC_CURVE => return KmKeyParameterValue::EcCurve(Default::default()),
1102 Tag::ORIGIN => return KmKeyParameterValue::Origin(Default::default()),
1103 Tag::PURPOSE => return KmKeyParameterValue::KeyPurpose(Default::default()),
1104 Tag::USER_AUTH_TYPE => {
1105 return KmKeyParameterValue::HardwareAuthenticatorType(Default::default())
1106 }
1107 Tag::HARDWARE_TYPE => return KmKeyParameterValue::SecurityLevel(Default::default()),
1108 _ => {}
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001109 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001110 match tag_type {
1111 TagType::INVALID => return KmKeyParameterValue::Invalid(Default::default()),
1112 TagType::ENUM | TagType::ENUM_REP => {}
1113 TagType::UINT | TagType::UINT_REP => {
1114 return KmKeyParameterValue::Integer(Default::default())
1115 }
1116 TagType::ULONG | TagType::ULONG_REP => {
1117 return KmKeyParameterValue::LongInteger(Default::default())
1118 }
1119 TagType::DATE => return KmKeyParameterValue::DateTime(Default::default()),
1120 TagType::BOOL => return KmKeyParameterValue::BoolValue(Default::default()),
1121 TagType::BIGNUM | TagType::BYTES => {
1122 return KmKeyParameterValue::Blob(Default::default())
1123 }
1124 _ => {}
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001125 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001126 panic!("Unknown tag/tag_type: {:?} {:?}", tag, tag_type);
1127 }
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001128
Janis Danisevskise6efb242020-12-19 13:58:01 -08001129 fn check_field_matches_tag_type(list_o_parameters: &[KmKeyParameter]) {
1130 for kp in list_o_parameters.iter() {
1131 match (&kp.value, get_field_by_tag_type(kp.tag)) {
1132 (&KmKeyParameterValue::Algorithm(_), KmKeyParameterValue::Algorithm(_))
1133 | (&KmKeyParameterValue::BlockMode(_), KmKeyParameterValue::BlockMode(_))
1134 | (&KmKeyParameterValue::PaddingMode(_), KmKeyParameterValue::PaddingMode(_))
1135 | (&KmKeyParameterValue::Digest(_), KmKeyParameterValue::Digest(_))
1136 | (&KmKeyParameterValue::EcCurve(_), KmKeyParameterValue::EcCurve(_))
1137 | (&KmKeyParameterValue::Origin(_), KmKeyParameterValue::Origin(_))
1138 | (&KmKeyParameterValue::KeyPurpose(_), KmKeyParameterValue::KeyPurpose(_))
1139 | (
1140 &KmKeyParameterValue::HardwareAuthenticatorType(_),
1141 KmKeyParameterValue::HardwareAuthenticatorType(_),
1142 )
1143 | (&KmKeyParameterValue::SecurityLevel(_), KmKeyParameterValue::SecurityLevel(_))
1144 | (&KmKeyParameterValue::Invalid(_), KmKeyParameterValue::Invalid(_))
1145 | (&KmKeyParameterValue::Integer(_), KmKeyParameterValue::Integer(_))
1146 | (&KmKeyParameterValue::LongInteger(_), KmKeyParameterValue::LongInteger(_))
1147 | (&KmKeyParameterValue::DateTime(_), KmKeyParameterValue::DateTime(_))
1148 | (&KmKeyParameterValue::BoolValue(_), KmKeyParameterValue::BoolValue(_))
1149 | (&KmKeyParameterValue::Blob(_), KmKeyParameterValue::Blob(_)) => {}
1150 (actual, expected) => panic!(
1151 "Tag {:?} associated with variant {:?} expected {:?}",
1152 kp.tag, actual, expected
1153 ),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001154 }
1155 }
Janis Danisevskise6efb242020-12-19 13:58:01 -08001156 }
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001157
Janis Danisevskise6efb242020-12-19 13:58:01 -08001158 #[test]
1159 fn key_parameter_value_field_matches_tag_type() {
1160 check_field_matches_tag_type(&KeyParameterValue::make_field_matches_tag_type_test_vector());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001161 }
Janis Danisevskis5d772ef2022-03-17 20:06:33 -07001162
1163 #[test]
1164 fn key_parameter_serialization_test() {
1165 let params = KeyParameterValue::make_key_parameter_defaults_vector();
1166 let mut out_buffer: Vec<u8> = Default::default();
1167 serde_cbor::to_writer(&mut out_buffer, &params)
1168 .expect("Failed to serialize key parameters.");
1169 let deserialized_params: Vec<KeyParameter> =
1170 serde_cbor::from_reader(&mut out_buffer.as_slice())
1171 .expect("Failed to deserialize key parameters.");
1172 assert_eq!(params, deserialized_params);
1173 }
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001174}
1175
1176#[cfg(test)]
1177mod basic_tests {
1178 use crate::key_parameter::*;
1179
1180 // Test basic functionality of KeyParameter.
1181 #[test]
1182 fn test_key_parameter() {
1183 let key_parameter = KeyParameter::new(
1184 KeyParameterValue::Algorithm(Algorithm::RSA),
1185 SecurityLevel::STRONGBOX,
1186 );
1187
1188 assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
1189
1190 assert_eq!(
1191 *key_parameter.key_parameter_value(),
1192 KeyParameterValue::Algorithm(Algorithm::RSA)
1193 );
1194
1195 assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
1196 }
1197}
1198
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001199/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
1200/// data types and then tests 'to_sql' method for KeyParameters of those
1201/// different data types. The five different data types for KeyParameter values are:
1202/// i) enums of u32
1203/// ii) u32
1204/// iii) u64
1205/// iv) Vec<u8>
1206/// v) bool
1207#[cfg(test)]
1208mod storage_tests {
1209 use crate::error::*;
1210 use crate::key_parameter::*;
1211 use anyhow::Result;
1212 use rusqlite::types::ToSql;
1213 use rusqlite::{params, Connection, NO_PARAMS};
1214
1215 /// Test initializing a KeyParameter (with key parameter value corresponding to an enum of i32)
1216 /// from a database table row.
1217 #[test]
1218 fn test_new_from_sql_enum_i32() -> Result<()> {
1219 let db = init_db()?;
1220 insert_into_keyparameter(
1221 &db,
1222 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001223 Tag::ALGORITHM.0,
1224 &Algorithm::RSA.0,
1225 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001226 )?;
1227 let key_param = query_from_keyparameter(&db)?;
1228 assert_eq!(Tag::ALGORITHM, key_param.get_tag());
1229 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::Algorithm(Algorithm::RSA));
1230 assert_eq!(*key_param.security_level(), SecurityLevel::STRONGBOX);
1231 Ok(())
1232 }
1233
1234 /// Test initializing a KeyParameter (with key parameter value which is of i32)
1235 /// from a database table row.
1236 #[test]
1237 fn test_new_from_sql_i32() -> Result<()> {
1238 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001239 insert_into_keyparameter(&db, 1, Tag::KEY_SIZE.0, &1024, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001240 let key_param = query_from_keyparameter(&db)?;
1241 assert_eq!(Tag::KEY_SIZE, key_param.get_tag());
1242 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::KeySize(1024));
1243 Ok(())
1244 }
1245
1246 /// Test initializing a KeyParameter (with key parameter value which is of i64)
1247 /// from a database table row.
1248 #[test]
1249 fn test_new_from_sql_i64() -> Result<()> {
1250 let db = init_db()?;
1251 // max value for i64, just to test corner cases
1252 insert_into_keyparameter(
1253 &db,
1254 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001255 Tag::RSA_PUBLIC_EXPONENT.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001256 &(i64::MAX),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001257 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001258 )?;
1259 let key_param = query_from_keyparameter(&db)?;
1260 assert_eq!(Tag::RSA_PUBLIC_EXPONENT, key_param.get_tag());
1261 assert_eq!(
1262 *key_param.key_parameter_value(),
1263 KeyParameterValue::RSAPublicExponent(i64::MAX)
1264 );
1265 Ok(())
1266 }
1267
1268 /// Test initializing a KeyParameter (with key parameter value which is of bool)
1269 /// from a database table row.
1270 #[test]
1271 fn test_new_from_sql_bool() -> Result<()> {
1272 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001273 insert_into_keyparameter(&db, 1, Tag::CALLER_NONCE.0, &Null, SecurityLevel::STRONGBOX.0)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001274 let key_param = query_from_keyparameter(&db)?;
1275 assert_eq!(Tag::CALLER_NONCE, key_param.get_tag());
1276 assert_eq!(*key_param.key_parameter_value(), KeyParameterValue::CallerNonce);
1277 Ok(())
1278 }
1279
1280 /// Test initializing a KeyParameter (with key parameter value which is of Vec<u8>)
1281 /// from a database table row.
1282 #[test]
1283 fn test_new_from_sql_vec_u8() -> Result<()> {
1284 let db = init_db()?;
1285 let app_id = String::from("MyAppID");
1286 let app_id_bytes = app_id.into_bytes();
1287 insert_into_keyparameter(
1288 &db,
1289 1,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001290 Tag::APPLICATION_ID.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001291 &app_id_bytes,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001292 SecurityLevel::STRONGBOX.0,
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001293 )?;
1294 let key_param = query_from_keyparameter(&db)?;
1295 assert_eq!(Tag::APPLICATION_ID, key_param.get_tag());
1296 assert_eq!(
1297 *key_param.key_parameter_value(),
1298 KeyParameterValue::ApplicationID(app_id_bytes)
1299 );
1300 Ok(())
1301 }
1302
1303 /// Test storing a KeyParameter (with key parameter value which corresponds to an enum of i32)
1304 /// in the database
1305 #[test]
1306 fn test_to_sql_enum_i32() -> Result<()> {
1307 let db = init_db()?;
1308 let kp = KeyParameter::new(
1309 KeyParameterValue::Algorithm(Algorithm::RSA),
1310 SecurityLevel::STRONGBOX,
1311 );
1312 store_keyparameter(&db, 1, &kp)?;
1313 let key_param = query_from_keyparameter(&db)?;
1314 assert_eq!(kp.get_tag(), key_param.get_tag());
1315 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1316 assert_eq!(kp.security_level(), key_param.security_level());
1317 Ok(())
1318 }
1319
1320 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1321 #[test]
1322 fn test_to_sql_i32() -> Result<()> {
1323 let db = init_db()?;
1324 let kp = KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::STRONGBOX);
1325 store_keyparameter(&db, 1, &kp)?;
1326 let key_param = query_from_keyparameter(&db)?;
1327 assert_eq!(kp.get_tag(), key_param.get_tag());
1328 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1329 assert_eq!(kp.security_level(), key_param.security_level());
1330 Ok(())
1331 }
1332
1333 /// Test storing a KeyParameter (with key parameter value which is of i64) in the database
1334 #[test]
1335 fn test_to_sql_i64() -> Result<()> {
1336 let db = init_db()?;
1337 // max value for i64, just to test corner cases
1338 let kp = KeyParameter::new(
1339 KeyParameterValue::RSAPublicExponent(i64::MAX),
1340 SecurityLevel::STRONGBOX,
1341 );
1342 store_keyparameter(&db, 1, &kp)?;
1343 let key_param = query_from_keyparameter(&db)?;
1344 assert_eq!(kp.get_tag(), key_param.get_tag());
1345 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1346 assert_eq!(kp.security_level(), key_param.security_level());
1347 Ok(())
1348 }
1349
1350 /// Test storing a KeyParameter (with key parameter value which is of Vec<u8>) in the database
1351 #[test]
1352 fn test_to_sql_vec_u8() -> Result<()> {
1353 let db = init_db()?;
1354 let kp = KeyParameter::new(
1355 KeyParameterValue::ApplicationID(String::from("MyAppID").into_bytes()),
1356 SecurityLevel::STRONGBOX,
1357 );
1358 store_keyparameter(&db, 1, &kp)?;
1359 let key_param = query_from_keyparameter(&db)?;
1360 assert_eq!(kp.get_tag(), key_param.get_tag());
1361 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1362 assert_eq!(kp.security_level(), key_param.security_level());
1363 Ok(())
1364 }
1365
1366 /// Test storing a KeyParameter (with key parameter value which is of i32) in the database
1367 #[test]
1368 fn test_to_sql_bool() -> Result<()> {
1369 let db = init_db()?;
1370 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
1371 store_keyparameter(&db, 1, &kp)?;
1372 let key_param = query_from_keyparameter(&db)?;
1373 assert_eq!(kp.get_tag(), key_param.get_tag());
1374 assert_eq!(kp.key_parameter_value(), key_param.key_parameter_value());
1375 assert_eq!(kp.security_level(), key_param.security_level());
1376 Ok(())
1377 }
1378
1379 #[test]
1380 /// Test Tag::Invalid
1381 fn test_invalid_tag() -> Result<()> {
1382 let db = init_db()?;
1383 insert_into_keyparameter(&db, 1, 0, &123, 1)?;
1384 let key_param = query_from_keyparameter(&db)?;
1385 assert_eq!(Tag::INVALID, key_param.get_tag());
1386 Ok(())
1387 }
1388
1389 #[test]
1390 fn test_non_existing_enum_variant() -> Result<()> {
1391 let db = init_db()?;
1392 insert_into_keyparameter(&db, 1, 100, &123, 1)?;
Janis Danisevskise6efb242020-12-19 13:58:01 -08001393 let key_param = query_from_keyparameter(&db)?;
1394 assert_eq!(Tag::INVALID, key_param.get_tag());
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001395 Ok(())
1396 }
1397
1398 #[test]
1399 fn test_invalid_conversion_from_sql() -> Result<()> {
1400 let db = init_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001401 insert_into_keyparameter(&db, 1, Tag::ALGORITHM.0, &Null, 1)?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001402 tests::check_result_contains_error_string(
1403 query_from_keyparameter(&db),
1404 "Failed to read sql data for tag: ALGORITHM.",
1405 );
1406 Ok(())
1407 }
1408
1409 /// Helper method to init database table for key parameter
1410 fn init_db() -> Result<Connection> {
1411 let db = Connection::open_in_memory().context("Failed to initialize sqlite connection.")?;
1412 db.execute("ATTACH DATABASE ? as 'persistent';", params![""])
1413 .context("Failed to attach databases.")?;
1414 db.execute(
1415 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
1416 keyentryid INTEGER,
1417 tag INTEGER,
1418 data ANY,
1419 security_level INTEGER);",
1420 NO_PARAMS,
1421 )
1422 .context("Failed to initialize \"keyparameter\" table.")?;
1423 Ok(db)
1424 }
1425
1426 /// Helper method to insert an entry into key parameter table, with individual parameters
1427 fn insert_into_keyparameter<T: ToSql>(
1428 db: &Connection,
1429 key_id: i64,
1430 tag: i32,
1431 value: &T,
1432 security_level: i32,
1433 ) -> Result<()> {
1434 db.execute(
1435 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001436 VALUES(?, ?, ?, ?);",
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001437 params![key_id, tag, *value, security_level],
1438 )?;
1439 Ok(())
1440 }
1441
1442 /// Helper method to store a key parameter instance.
1443 fn store_keyparameter(db: &Connection, key_id: i64, kp: &KeyParameter) -> Result<()> {
1444 db.execute(
1445 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001446 VALUES(?, ?, ?, ?);",
1447 params![key_id, kp.get_tag().0, kp.key_parameter_value(), kp.security_level().0],
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001448 )?;
1449 Ok(())
1450 }
1451
1452 /// Helper method to query a row from keyparameter table
1453 fn query_from_keyparameter(db: &Connection) -> Result<KeyParameter> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001454 let mut stmt =
1455 db.prepare("SELECT tag, data, security_level FROM persistent.keyparameter")?;
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001456 let mut rows = stmt.query(NO_PARAMS)?;
1457 let row = rows.next()?.unwrap();
Matthew Maurerb77a28d2021-05-07 16:08:20 -07001458 KeyParameter::new_from_sql(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001459 Tag(row.get(0)?),
Janis Danisevskis4522c2b2020-11-27 18:04:58 -08001460 &SqlField::new(1, row),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001461 SecurityLevel(row.get(2)?),
Matthew Maurerb77a28d2021-05-07 16:08:20 -07001462 )
Hasini Gunasingheaf993662020-07-24 18:40:20 +00001463 }
1464}
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001465
1466/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
Janis Danisevskis85d47932020-10-23 16:12:59 -07001467/// KeyParameter, for the four different types used in KmKeyParameter, in addition to Invalid
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001468/// key parameter.
1469/// i) bool
1470/// ii) integer
1471/// iii) longInteger
Janis Danisevskis85d47932020-10-23 16:12:59 -07001472/// iv) blob
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001473#[cfg(test)]
1474mod wire_tests {
1475 use crate::key_parameter::*;
1476 /// unit tests for to conversions
1477 #[test]
1478 fn test_convert_to_wire_invalid() {
1479 let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001480 assert_eq!(
1481 KmKeyParameter { tag: Tag::INVALID, value: KmKeyParameterValue::Invalid(0) },
1482 kp.value.into()
1483 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001484 }
1485 #[test]
1486 fn test_convert_to_wire_bool() {
1487 let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001488 assert_eq!(
1489 KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) },
1490 kp.value.into()
1491 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001492 }
1493 #[test]
1494 fn test_convert_to_wire_integer() {
1495 let kp = KeyParameter::new(
1496 KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
1497 SecurityLevel::STRONGBOX,
1498 );
Janis Danisevskise6efb242020-12-19 13:58:01 -08001499 assert_eq!(
1500 KmKeyParameter {
1501 tag: Tag::PURPOSE,
1502 value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT)
1503 },
1504 kp.value.into()
1505 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001506 }
1507 #[test]
1508 fn test_convert_to_wire_long_integer() {
1509 let kp =
1510 KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
Janis Danisevskise6efb242020-12-19 13:58:01 -08001511 assert_eq!(
1512 KmKeyParameter {
1513 tag: Tag::USER_SECURE_ID,
1514 value: KmKeyParameterValue::LongInteger(i64::MAX)
1515 },
1516 kp.value.into()
1517 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001518 }
1519 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001520 fn test_convert_to_wire_blob() {
1521 let kp = KeyParameter::new(
1522 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
1523 SecurityLevel::STRONGBOX,
1524 );
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001525 assert_eq!(
Janis Danisevskise6efb242020-12-19 13:58:01 -08001526 KmKeyParameter {
1527 tag: Tag::CONFIRMATION_TOKEN,
1528 value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes())
1529 },
1530 kp.value.into()
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001531 );
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001532 }
1533
1534 /// unit tests for from conversion
1535 #[test]
1536 fn test_convert_from_wire_invalid() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001537 let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001538 assert_eq!(KeyParameterValue::Invalid, aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001539 }
1540 #[test]
1541 fn test_convert_from_wire_bool() {
1542 let aidl_kp =
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001543 KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001544 assert_eq!(KeyParameterValue::CallerNonce, aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001545 }
1546 #[test]
1547 fn test_convert_from_wire_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001548 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001549 tag: Tag::PURPOSE,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001550 value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001551 };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001552 assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001553 }
1554 #[test]
1555 fn test_convert_from_wire_long_integer() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001556 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001557 tag: Tag::USER_SECURE_ID,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001558 value: KmKeyParameterValue::LongInteger(i64::MAX),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001559 };
Janis Danisevskise6efb242020-12-19 13:58:01 -08001560 assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), aidl_kp.into());
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001561 }
1562 #[test]
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001563 fn test_convert_from_wire_blob() {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001564 let aidl_kp = KmKeyParameter {
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001565 tag: Tag::CONFIRMATION_TOKEN,
Janis Danisevskis398e6be2020-12-17 09:29:25 -08001566 value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001567 };
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001568 assert_eq!(
1569 KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
Janis Danisevskise6efb242020-12-19 13:58:01 -08001570 aidl_kp.into()
Hasini Gunasinghe3eb77c22020-08-28 15:45:06 +00001571 );
1572 }
1573}