Merge "Keystore 2.0: Revisit Key Parameters"
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
index 56c03aa..a19ba25 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -12,9 +12,81 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//! KeyParameter is used to express different characteristics of a key requested by the user
-//! and enforced by the OEMs. This module implements the internal representation of KeyParameter
-//! and the methods to work with KeyParameter.
+//! Key parameters are declared by KeyMint to describe properties of keys and operations.
+//! During key generation and import, key parameters are used to characterize a key, its usage
+//! restrictions, and additional parameters for attestation. During the lifetime of the key,
+//! the key characteristics are expressed as set of key parameters. During cryptographic
+//! operations, clients may specify additional operation specific parameters.
+//! This module provides a Keystore 2.0 internal representation for key parameters and
+//! implements traits to convert it from and into KeyMint KeyParameters and store it in
+//! the SQLite database.
+//!
+//! ## Synopsis
+//!
+//! enum KeyParameterValue {
+//! Invalid,
+//! Algorithm(Algorithm),
+//! ...
+//! }
+//!
+//! impl KeyParameterValue {
+//! pub fn get_tag(&self) -> Tag;
+//! pub fn new_from_sql(tag: Tag, data: &SqlField) -> Result<Self>;
+//! fn to_sql(&self) -> SqlResult<ToSqlOutput>
+//! }
+//!
+//! use ...::keymint::KeyParameter as KmKeyParameter;
+//! impl Into<KmKeyParameter> for KeyParameterValue {}
+//! impl From<KmKeyParameter> for KeyParameterValue {}
+//!
+//! ## Implementation
+//! Each of the five functions is implemented as match statement over each key parameter variant.
+//! We bootstrap these function as well as the KeyParameterValue enum itself from a single list
+//! of key parameters, that needs to be kept in sync with the KeyMint AIDL specification.
+//!
+//! The list resembles an enum declaration with a few extra fields.
+//! enum KeyParameterValue {
+//! Invalid with tag INVALID and field Invalid,
+//! Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
+//! ...
+//! }
+//! The tag corresponds to the variant of the keymint::Tag, and the field corresponds to the
+//! variant of the keymint::KeyParameterValue union. There is no one to one mapping between
+//! tags and union fields, e.g., the values of both tags BOOT_PATCHLEVEL and VENDOR_PATCHLEVEL
+//! are stored in the Integer field.
+//!
+//! The macros interpreting them all follow a similar pattern and follow the following fragment
+//! naming scheme:
+//!
+//! Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
+//! $vname $(($vtype ))? with tag $tag_name and field $field_name,
+//!
+//! Further, KeyParameterValue appears in the macro as $enum_name.
+//! Note that $vtype is optional to accommodate variants like Invalid which don't wrap a value.
+//!
+//! In some cases $vtype is not part of the expansion, but we still have to modify the expansion
+//! depending on the presence of $vtype. In these cases we recurse through the list following the
+//! following pattern:
+//!
+//! (@<marker> <non repeating args>, [<out list>], [<in list>])
+//!
+//! These macros usually have four rules:
+//! * Two main recursive rules, of the form:
+//! (
+//! @<marker>
+//! <non repeating args>,
+//! [<out list>],
+//! [<one element pattern> <in tail>]
+//! ) => {
+//! macro!{@<marker> <non repeating args>, [<out list>
+//! <one element expansion>
+//! ], [<in tail>]}
+//! };
+//! They pop one element off the <in list> and add one expansion to the out list.
+//! The element expansion is kept on a separate line (or lines) for better readability.
+//! The two variants differ in whether or not $vtype is expected.
+//! * The termination condition which has an empty in list.
+//! * The public interface, which does not have @marker and calls itself with an empty out list.
use crate::db_utils::SqlField;
use crate::error::Error as KeystoreError;
@@ -32,288 +104,598 @@
use rusqlite::types::{Null, ToSql, ToSqlOutput};
use rusqlite::Result as SqlResult;
-/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
-#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
-pub struct KeyParameter {
- key_parameter_value: KeyParameterValue,
- security_level: SecurityLevel,
+/// This trait is used to associate a primitive to any type that can be stored inside a
+/// KeyParameterValue, especially the AIDL enum types, e.g., keymint::{Algorithm, Digest, ...}.
+/// This allows for simplifying the macro rules, e.g., for reading from the SQL database.
+/// An expression like `KeyParameterValue::Algorithm(row.get(0))` would not work because
+/// a type of `Algorithm` is expected which does not implement `FromSql` and we cannot
+/// implement it because we own neither the type nor the trait.
+/// With AssociatePrimitive we can write an expression
+/// `KeyParameter::Algorithm(<Algorithm>::from_primitive(row.get(0)))` to inform `get`
+/// about the expected primitive type that it can convert into. By implementing this
+/// trait for all inner types we can write a single rule to cover all cases (except where
+/// there is no wrapped type):
+/// `KeyParameterValue::$vname(<$vtype>::from_primitive(row.get(0)))`
+trait AssociatePrimitive {
+ type Primitive;
+
+ fn from_primitive(v: Self::Primitive) -> Self;
+ fn to_primitive(&self) -> Self::Primitive;
}
+/// Associates the given type with i32. The macro assumes that the given type is actually a
+/// tuple struct wrapping i32, such as AIDL enum types.
+macro_rules! implement_associate_primitive_for_aidl_enum {
+ ($t:ty) => {
+ impl AssociatePrimitive for $t {
+ type Primitive = i32;
+
+ fn from_primitive(v: Self::Primitive) -> Self {
+ Self(v)
+ }
+ fn to_primitive(&self) -> Self::Primitive {
+ self.0
+ }
+ }
+ };
+}
+
+/// Associates the given type with itself.
+macro_rules! implement_associate_primitive_identity {
+ ($t:ty) => {
+ impl AssociatePrimitive for $t {
+ type Primitive = $t;
+
+ fn from_primitive(v: Self::Primitive) -> Self {
+ v
+ }
+ fn to_primitive(&self) -> Self::Primitive {
+ self.clone()
+ }
+ }
+ };
+}
+
+implement_associate_primitive_for_aidl_enum! {Algorithm}
+implement_associate_primitive_for_aidl_enum! {BlockMode}
+implement_associate_primitive_for_aidl_enum! {Digest}
+implement_associate_primitive_for_aidl_enum! {EcCurve}
+implement_associate_primitive_for_aidl_enum! {HardwareAuthenticatorType}
+implement_associate_primitive_for_aidl_enum! {KeyOrigin}
+implement_associate_primitive_for_aidl_enum! {KeyPurpose}
+implement_associate_primitive_for_aidl_enum! {PaddingMode}
+implement_associate_primitive_for_aidl_enum! {SecurityLevel}
+
+implement_associate_primitive_identity! {Vec<u8>}
+implement_associate_primitive_identity! {i64}
+implement_associate_primitive_identity! {i32}
+
+/// Expands the list of KeyParameterValue variants as follows:
+///
+/// Input:
+/// pub enum KeyParameterValue {
+/// Invalid with tag INVALID and field Invalid,
+/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
+/// }
+///
+/// Output:
+/// ```
+/// pub enum KeyParameterValue {
+/// Invalid,
+/// Algorithm(Algorithm),
+/// }
+/// ```
+macro_rules! implement_enum {
+ (
+ $(#[$enum_meta:meta])*
+ $enum_vis:vis enum $enum_name:ident {
+ $($(#[$emeta:meta])* $vname:ident$(($vtype:ty))?),* $(,)?
+ }
+ ) => {
+ $(#[$enum_meta])*
+ $enum_vis enum $enum_name {
+ $(
+ $(#[$emeta])*
+ $vname$(($vtype))?
+ ),*
+ }
+ };
+}
+
+/// Expands the list of KeyParameterValue variants as follows:
+///
+/// Input:
+/// Invalid with tag INVALID and field Invalid,
+/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
+///
+/// Output:
+/// ```
+/// pub fn get_tag(&self) -> Tag {
+/// match self {
+/// KeyParameterValue::Invalid => Tag::INVALID,
+/// KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
+/// }
+/// }
+/// ```
+macro_rules! implement_get_tag {
+ (
+ @replace_type_spec
+ $enum_name:ident,
+ [$($out:tt)*],
+ [$vname:ident($vtype:ty) $tag_name:ident, $($in:tt)*]
+ ) => {
+ implement_get_tag!{@replace_type_spec $enum_name, [$($out)*
+ $enum_name::$vname(_) => Tag::$tag_name,
+ ], [$($in)*]}
+ };
+ (
+ @replace_type_spec
+ $enum_name:ident,
+ [$($out:tt)*],
+ [$vname:ident $tag_name:ident, $($in:tt)*]
+ ) => {
+ implement_get_tag!{@replace_type_spec $enum_name, [$($out)*
+ $enum_name::$vname => Tag::$tag_name,
+ ], [$($in)*]}
+ };
+ (@replace_type_spec $enum_name:ident, [$($out:tt)*], []) => {
+ /// Returns the tag of the given instance.
+ pub fn get_tag(&self) -> Tag {
+ match self {
+ $($out)*
+ }
+ }
+ };
+
+ ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
+ implement_get_tag!{@replace_type_spec $enum_name, [], [$($vname$(($vtype))? $tag_name,)*]}
+ };
+}
+
+/// Expands the list of KeyParameterValue variants as follows:
+///
+/// Input:
+/// Invalid with tag INVALID and field Invalid,
+/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
+///
+/// Output:
+/// ```
+/// fn to_sql(&self) -> SqlResult<ToSqlOutput> {
+/// match self {
+/// KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
+/// KeyParameterValue::Algorithm(v) => Ok(ToSqlOutput::from(v.to_primitive())),
+/// }
+/// }
+/// ```
+macro_rules! implement_to_sql {
+ (
+ @replace_type_spec
+ $enum_name:ident,
+ [$($out:tt)*],
+ [$vname:ident($vtype:ty), $($in:tt)*]
+ ) => {
+ implement_to_sql!{@replace_type_spec $enum_name, [ $($out)*
+ $enum_name::$vname(v) => Ok(ToSqlOutput::from(v.to_primitive())),
+ ], [$($in)*]}
+ };
+ (
+ @replace_type_spec
+ $enum_name:ident,
+ [$($out:tt)*],
+ [$vname:ident, $($in:tt)*]
+ ) => {
+ implement_to_sql!{@replace_type_spec $enum_name, [ $($out)*
+ $enum_name::$vname => Ok(ToSqlOutput::from(Null)),
+ ], [$($in)*]}
+ };
+ (@replace_type_spec $enum_name:ident, [$($out:tt)*], []) => {
+ /// Converts $enum_name to be stored in a rusqlite database.
+ fn to_sql(&self) -> SqlResult<ToSqlOutput> {
+ match self {
+ $($out)*
+ }
+ }
+ };
+
+
+ ($enum_name:ident; $($vname:ident$(($vtype:ty))?),*) => {
+ impl ToSql for $enum_name {
+ implement_to_sql!{@replace_type_spec $enum_name, [], [$($vname$(($vtype))?,)*]}
+ }
+
+ }
+}
+
+/// Expands the list of KeyParameterValue variants as follows:
+///
+/// Input:
+/// Invalid with tag INVALID and field Invalid,
+/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
+///
+/// Output:
+/// ```
+/// pub fn new_from_sql(
+/// tag: Tag,
+/// data: &SqlField,
+/// ) -> Result<Self> {
+/// Ok(match self {
+/// Tag::Invalid => KeyParameterValue::Invalid,
+/// Tag::ALGORITHM => {
+/// KeyParameterValue::Algorithm(<Algorithm>::from_primitive(data
+/// .get()
+/// .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+/// .context(concat!("Failed to read sql data for tag: ", "ALGORITHM", "."))?
+/// ))
+/// },
+/// })
+/// }
+/// ```
+macro_rules! implement_new_from_sql {
+ ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident),*) => {
+ /// Takes a tag and an SqlField and attempts to construct a KeyParameter value.
+ /// This function may fail if the parameter value cannot be extracted from the
+ /// database cell.
+ pub fn new_from_sql(
+ tag: Tag,
+ data: &SqlField,
+ ) -> Result<Self> {
+ Ok(match tag {
+ $(
+ Tag::$tag_name => {
+ $enum_name::$vname$((<$vtype>::from_primitive(data
+ .get()
+ .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
+ .context(concat!(
+ "Failed to read sql data for tag: ",
+ stringify!($tag_name),
+ "."
+ ))?
+ )))?
+ },
+ )*
+ _ => $enum_name::Invalid,
+ })
+ }
+ };
+}
+
+/// This key parameter default is used during the conversion from KeyParameterValue
+/// to keymint::KeyParameterValue. Keystore's version does not have wrapped types
+/// for boolean tags and the tag Invalid. The AIDL version uses bool and integer
+/// variants respectively. This default function is invoked in these cases to
+/// homogenize the rules for boolean and invalid tags.
+/// The bool variant returns true because boolean parameters are implicitly true
+/// if present.
+trait KpDefault {
+ fn default() -> Self;
+}
+
+impl KpDefault for i32 {
+ fn default() -> Self {
+ 0
+ }
+}
+
+impl KpDefault for bool {
+ fn default() -> Self {
+ true
+ }
+}
+
+/// Expands the list of KeyParameterValue variants as follows:
+///
+/// Input:
+/// Invalid with tag INVALID and field Invalid,
+/// Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
+///
+/// Output:
+/// ```
+/// impl From<KmKeyParameter> for KeyParameterValue {
+/// fn from(kp: KmKeyParameter) -> Self {
+/// match kp {
+/// KmKeyParameter { tag: Tag::INVALID, value: KmKeyParameterValue::Invalid(_) }
+/// => $enum_name::$vname,
+/// KmKeyParameter { tag: Tag::Algorithm, value: KmKeyParameterValue::Algorithm(v) }
+/// => $enum_name::Algorithm(v),
+/// _ => $enum_name::Invalid,
+/// }
+/// }
+/// }
+///
+/// impl Into<KmKeyParameter> for KeyParameterValue {
+/// fn into(self) -> KmKeyParameter {
+/// match self {
+/// KeyParameterValue::Invalid => KmKeyParameter {
+/// tag: Tag::INVALID,
+/// value: KmKeyParameterValue::Invalid(KpDefault::default())
+/// },
+/// KeyParameterValue::Algorithm(v) => KmKeyParameter {
+/// tag: Tag::ALGORITHM,
+/// value: KmKeyParameterValue::Algorithm(v)
+/// },
+/// }
+/// }
+/// }
+/// ```
+macro_rules! implement_try_from_to_km_parameter {
+ // The first three rules expand From<KmKeyParameter>.
+ (
+ @from
+ $enum_name:ident,
+ [$($out:tt)*],
+ [$vname:ident($vtype:ty) $tag_name:ident $field_name:ident, $($in:tt)*]
+ ) => {
+ implement_try_from_to_km_parameter!{@from $enum_name, [$($out)*
+ KmKeyParameter {
+ tag: Tag::$tag_name,
+ value: KmKeyParameterValue::$field_name(v)
+ } => $enum_name::$vname(v),
+ ], [$($in)*]
+ }};
+ (
+ @from
+ $enum_name:ident,
+ [$($out:tt)*],
+ [$vname:ident $tag_name:ident $field_name:ident, $($in:tt)*]
+ ) => {
+ implement_try_from_to_km_parameter!{@from $enum_name, [$($out)*
+ KmKeyParameter {
+ tag: Tag::$tag_name,
+ value: KmKeyParameterValue::$field_name(_)
+ } => $enum_name::$vname,
+ ], [$($in)*]
+ }};
+ (@from $enum_name:ident, [$($out:tt)*], []) => {
+ impl From<KmKeyParameter> for $enum_name {
+ fn from(kp: KmKeyParameter) -> Self {
+ match kp {
+ $($out)*
+ _ => $enum_name::Invalid,
+ }
+ }
+ }
+ };
+
+ // The next three rules expand Into<KmKeyParameter>.
+ (
+ @into
+ $enum_name:ident,
+ [$($out:tt)*],
+ [$vname:ident($vtype:ty) $tag_name:ident $field_name:ident, $($in:tt)*]
+ ) => {
+ implement_try_from_to_km_parameter!{@into $enum_name, [$($out)*
+ $enum_name::$vname(v) => KmKeyParameter {
+ tag: Tag::$tag_name,
+ value: KmKeyParameterValue::$field_name(v)
+ },
+ ], [$($in)*]
+ }};
+ (
+ @into
+ $enum_name:ident,
+ [$($out:tt)*],
+ [$vname:ident $tag_name:ident $field_name:ident, $($in:tt)*]
+ ) => {
+ implement_try_from_to_km_parameter!{@into $enum_name, [$($out)*
+ $enum_name::$vname => KmKeyParameter {
+ tag: Tag::$tag_name,
+ value: KmKeyParameterValue::$field_name(KpDefault::default())
+ },
+ ], [$($in)*]
+ }};
+ (@into $enum_name:ident, [$($out:tt)*], []) => {
+ impl Into<KmKeyParameter> for $enum_name {
+ fn into(self) -> KmKeyParameter {
+ match self {
+ $($out)*
+ }
+ }
+ }
+ };
+
+
+ ($enum_name:ident; $($vname:ident$(($vtype:ty))? $tag_name:ident $field_name:ident),*) => {
+ implement_try_from_to_km_parameter!(
+ @from $enum_name,
+ [],
+ [$($vname$(($vtype))? $tag_name $field_name,)*]
+ );
+ implement_try_from_to_km_parameter!(
+ @into $enum_name,
+ [],
+ [$($vname$(($vtype))? $tag_name $field_name,)*]
+ );
+ };
+}
+
+/// This is the top level macro. While the other macros do most of the heavy lifting, this takes
+/// the key parameter list and passes it on to the other macros to generate all of the conversion
+/// functions. In addition, it generates an important test vector for verifying that tag type of the
+/// keymint tag matches the associated keymint KeyParameterValue field.
+macro_rules! implement_key_parameter_value {
+ (
+ $(#[$enum_meta:meta])*
+ $enum_vis:vis enum $enum_name:ident {
+ $(
+ $(#[$emeta:meta])*
+ $vname:ident$(($vtype:ty))? with tag $tag_name:ident and field $field_name:ident
+ ),* $(,)?
+ }
+ ) => {
+ implement_enum!(
+ $(#[$enum_meta])*
+ $enum_vis enum $enum_name {
+ $(
+ $(#[$emeta])*
+ $vname$(($vtype))?
+ ),*
+ });
+
+ impl $enum_name {
+ implement_new_from_sql!($enum_name; $($vname$(($vtype))? $tag_name),*);
+ implement_get_tag!($enum_name; $($vname$(($vtype))? $tag_name),*);
+
+ #[cfg(test)]
+ fn make_field_matches_tag_type_test_vector() -> Vec<KmKeyParameter> {
+ vec![$(KmKeyParameter{
+ tag: Tag::$tag_name,
+ value: KmKeyParameterValue::$field_name(Default::default())}
+ ),*]
+ }
+ }
+
+ implement_try_from_to_km_parameter!(
+ $enum_name;
+ $($vname$(($vtype))? $tag_name $field_name),*
+ );
+
+ implement_to_sql!($enum_name; $($vname$(($vtype))?),*);
+ };
+}
+
+implement_key_parameter_value! {
/// KeyParameterValue holds a value corresponding to one of the Tags defined in
/// the AIDL spec at hardware/interfaces/keymint
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
pub enum KeyParameterValue {
/// Associated with Tag:INVALID
- Invalid,
+ Invalid with tag INVALID and field Invalid,
/// Set of purposes for which the key may be used
- KeyPurpose(KeyPurpose),
+ KeyPurpose(KeyPurpose) with tag PURPOSE and field KeyPurpose,
/// Cryptographic algorithm with which the key is used
- Algorithm(Algorithm),
+ Algorithm(Algorithm) with tag ALGORITHM and field Algorithm,
/// Size of the key , in bits
- KeySize(i32),
+ KeySize(i32) with tag KEY_SIZE and field Integer,
/// Block cipher mode(s) with which the key may be used
- BlockMode(BlockMode),
+ BlockMode(BlockMode) with tag BLOCK_MODE and field BlockMode,
/// Digest algorithms that may be used with the key to perform signing and verification
- Digest(Digest),
+ Digest(Digest) with tag DIGEST and field Digest,
/// Padding modes that may be used with the key. Relevant to RSA, AES and 3DES keys.
- PaddingMode(PaddingMode),
+ PaddingMode(PaddingMode) with tag PADDING and field PaddingMode,
/// Can the caller provide a nonce for nonce-requiring operations
- CallerNonce,
+ CallerNonce with tag CALLER_NONCE and field BoolValue,
/// Minimum length of MAC for HMAC keys and AES keys that support GCM mode
- MinMacLength(i32),
+ MinMacLength(i32) with tag MIN_MAC_LENGTH and field Integer,
/// The elliptic curve
- EcCurve(EcCurve),
+ EcCurve(EcCurve) with tag EC_CURVE and field EcCurve,
/// Value of the public exponent for an RSA key pair
- RSAPublicExponent(i64),
+ RSAPublicExponent(i64) with tag RSA_PUBLIC_EXPONENT and field LongInteger,
/// An attestation certificate for the generated key should contain an application-scoped
/// and time-bounded device-unique ID
- IncludeUniqueID,
+ IncludeUniqueID with tag INCLUDE_UNIQUE_ID and field BoolValue,
//TODO: find out about this
// /// Necessary system environment conditions for the generated key to be used
// KeyBlobUsageRequirements(KeyBlobUsageRequirements),
/// Only the boot loader can use the key
- BootLoaderOnly,
+ BootLoaderOnly with tag BOOTLOADER_ONLY and field BoolValue,
/// When deleted, the key is guaranteed to be permanently deleted and unusable
- RollbackResistance,
+ RollbackResistance with tag ROLLBACK_RESISTANCE and field BoolValue,
/// The date and time at which the key becomes active
- ActiveDateTime(i64),
+ ActiveDateTime(i64) with tag ACTIVE_DATETIME and field DateTime,
/// The date and time at which the key expires for signing and encryption
- OriginationExpireDateTime(i64),
+ OriginationExpireDateTime(i64) with tag ORIGINATION_EXPIRE_DATETIME and field DateTime,
/// The date and time at which the key expires for verification and decryption
- UsageExpireDateTime(i64),
+ UsageExpireDateTime(i64) with tag USAGE_EXPIRE_DATETIME and field DateTime,
/// Minimum amount of time that elapses between allowed operations
- MinSecondsBetweenOps(i32),
+ MinSecondsBetweenOps(i32) with tag MIN_SECONDS_BETWEEN_OPS and field Integer,
/// Maximum number of times that a key may be used between system reboots
- MaxUsesPerBoot(i32),
+ MaxUsesPerBoot(i32) with tag MAX_USES_PER_BOOT and field Integer,
/// ID of the Android user that is permitted to use the key
- UserID(i32),
+ UserID(i32) with tag USER_ID and field Integer,
/// A key may only be used under a particular secure user authentication state
- UserSecureID(i64),
+ UserSecureID(i64) with tag USER_SECURE_ID and field LongInteger,
/// No authentication is required to use this key
- NoAuthRequired,
+ NoAuthRequired with tag NO_AUTH_REQUIRED and field BoolValue,
/// The types of user authenticators that may be used to authorize this key
- HardwareAuthenticatorType(HardwareAuthenticatorType),
+ HardwareAuthenticatorType(HardwareAuthenticatorType) with tag USER_AUTH_TYPE and field HardwareAuthenticatorType,
/// The time in seconds for which the key is authorized for use, after user authentication
- AuthTimeout(i32),
+ AuthTimeout(i32) with tag AUTH_TIMEOUT and field Integer,
/// The key may be used after authentication timeout if device is still on-body
- AllowWhileOnBody,
+ AllowWhileOnBody with tag ALLOW_WHILE_ON_BODY and field BoolValue,
/// The key must be unusable except when the user has provided proof of physical presence
- TrustedUserPresenceRequired,
+ TrustedUserPresenceRequired with tag TRUSTED_USER_PRESENCE_REQUIRED and field BoolValue,
/// Applicable to keys with KeyPurpose SIGN, and specifies that this key must not be usable
/// unless the user provides confirmation of the data to be signed
- TrustedConfirmationRequired,
+ TrustedConfirmationRequired with tag TRUSTED_CONFIRMATION_REQUIRED and field BoolValue,
/// The key may only be used when the device is unlocked
- UnlockedDeviceRequired,
+ UnlockedDeviceRequired with tag UNLOCKED_DEVICE_REQUIRED and field BoolValue,
/// When provided to generateKey or importKey, this tag specifies data
/// that is necessary during all uses of the key
- ApplicationID(Vec<u8>),
+ ApplicationID(Vec<u8>) with tag APPLICATION_ID and field Blob,
/// When provided to generateKey or importKey, this tag specifies data
/// that is necessary during all uses of the key
- ApplicationData(Vec<u8>),
+ ApplicationData(Vec<u8>) with tag APPLICATION_DATA and field Blob,
/// Specifies the date and time the key was created
- CreationDateTime(i64),
+ CreationDateTime(i64) with tag CREATION_DATETIME and field DateTime,
/// Specifies where the key was created, if known
- KeyOrigin(KeyOrigin),
+ KeyOrigin(KeyOrigin) with tag ORIGIN and field Origin,
/// The key used by verified boot to validate the operating system booted
- RootOfTrust(Vec<u8>),
+ RootOfTrust(Vec<u8>) with tag ROOT_OF_TRUST and field Blob,
/// System OS version with which the key may be used
- OSVersion(i32),
+ OSVersion(i32) with tag OS_VERSION and field Integer,
/// Specifies the system security patch level with which the key may be used
- OSPatchLevel(i32),
+ OSPatchLevel(i32) with tag OS_PATCHLEVEL and field Integer,
/// Specifies a unique, time-based identifier
- UniqueID(Vec<u8>),
+ UniqueID(Vec<u8>) with tag UNIQUE_ID and field Blob,
/// Used to deliver a "challenge" value to the attestKey() method
- AttestationChallenge(Vec<u8>),
+ AttestationChallenge(Vec<u8>) with tag ATTESTATION_CHALLENGE and field Blob,
/// The set of applications which may use a key, used only with attestKey()
- AttestationApplicationID(Vec<u8>),
+ AttestationApplicationID(Vec<u8>) with tag ATTESTATION_APPLICATION_ID and field Blob,
/// Provides the device's brand name, to attestKey()
- AttestationIdBrand(Vec<u8>),
+ AttestationIdBrand(Vec<u8>) with tag ATTESTATION_ID_BRAND and field Blob,
/// Provides the device's device name, to attestKey()
- AttestationIdDevice(Vec<u8>),
+ AttestationIdDevice(Vec<u8>) with tag ATTESTATION_ID_DEVICE and field Blob,
/// Provides the device's product name, to attestKey()
- AttestationIdProduct(Vec<u8>),
+ AttestationIdProduct(Vec<u8>) with tag ATTESTATION_ID_PRODUCT and field Blob,
/// Provides the device's serial number, to attestKey()
- AttestationIdSerial(Vec<u8>),
+ AttestationIdSerial(Vec<u8>) with tag ATTESTATION_ID_SERIAL and field Blob,
/// Provides the IMEIs for all radios on the device, to attestKey()
- AttestationIdIMEI(Vec<u8>),
+ AttestationIdIMEI(Vec<u8>) with tag ATTESTATION_ID_IMEI and field Blob,
/// Provides the MEIDs for all radios on the device, to attestKey()
- AttestationIdMEID(Vec<u8>),
+ AttestationIdMEID(Vec<u8>) with tag ATTESTATION_ID_MEID and field Blob,
/// Provides the device's manufacturer name, to attestKey()
- AttestationIdManufacturer(Vec<u8>),
+ AttestationIdManufacturer(Vec<u8>) with tag ATTESTATION_ID_MANUFACTURER and field Blob,
/// Provides the device's model name, to attestKey()
- AttestationIdModel(Vec<u8>),
+ AttestationIdModel(Vec<u8>) with tag ATTESTATION_ID_MODEL and field Blob,
/// Specifies the vendor image security patch level with which the key may be used
- VendorPatchLevel(i32),
+ VendorPatchLevel(i32) with tag VENDOR_PATCHLEVEL and field Integer,
/// Specifies the boot image (kernel) security patch level with which the key may be used
- BootPatchLevel(i32),
+ BootPatchLevel(i32) with tag BOOT_PATCHLEVEL and field Integer,
/// Provides "associated data" for AES-GCM encryption or decryption
- AssociatedData(Vec<u8>),
+ AssociatedData(Vec<u8>) with tag ASSOCIATED_DATA and field Blob,
/// Provides or returns a nonce or Initialization Vector (IV) for AES-GCM,
/// AES-CBC, AES-CTR, or 3DES-CBC encryption or decryption
- Nonce(Vec<u8>),
+ Nonce(Vec<u8>) with tag NONCE and field Blob,
/// Provides the requested length of a MAC or GCM authentication tag, in bits
- MacLength(i32),
+ MacLength(i32) with tag MAC_LENGTH and field Integer,
/// Specifies whether the device has been factory reset since the
/// last unique ID rotation. Used for key attestation
- ResetSinceIdRotation,
+ ResetSinceIdRotation with tag RESET_SINCE_ID_ROTATION and field BoolValue,
/// Used to deliver a cryptographic token proving that the user
/// confirmed a signing request
- ConfirmationToken(Vec<u8>),
+ ConfirmationToken(Vec<u8>) with tag CONFIRMATION_TOKEN and field Blob,
+}
+}
+
+impl From<&KmKeyParameter> for KeyParameterValue {
+ fn from(kp: &KmKeyParameter) -> Self {
+ kp.clone().into()
+ }
+}
+
+/// KeyParameter wraps the KeyParameterValue and the security level at which it is enforced.
+#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub struct KeyParameter {
+ value: KeyParameterValue,
+ security_level: SecurityLevel,
}
impl KeyParameter {
/// Create an instance of KeyParameter, given the value and the security level.
- pub fn new(key_parameter_value: KeyParameterValue, security_level: SecurityLevel) -> Self {
- KeyParameter { key_parameter_value, security_level }
+ pub fn new(value: KeyParameterValue, security_level: SecurityLevel) -> Self {
+ KeyParameter { value, security_level }
}
- /// Returns the tag given the KeyParameter instance.
- pub fn get_tag(&self) -> Tag {
- match self.key_parameter_value {
- KeyParameterValue::Invalid => Tag::INVALID,
- KeyParameterValue::KeyPurpose(_) => Tag::PURPOSE,
- KeyParameterValue::Algorithm(_) => Tag::ALGORITHM,
- KeyParameterValue::KeySize(_) => Tag::KEY_SIZE,
- KeyParameterValue::BlockMode(_) => Tag::BLOCK_MODE,
- KeyParameterValue::Digest(_) => Tag::DIGEST,
- KeyParameterValue::PaddingMode(_) => Tag::PADDING,
- KeyParameterValue::CallerNonce => Tag::CALLER_NONCE,
- KeyParameterValue::MinMacLength(_) => Tag::MIN_MAC_LENGTH,
- KeyParameterValue::EcCurve(_) => Tag::EC_CURVE,
- KeyParameterValue::RSAPublicExponent(_) => Tag::RSA_PUBLIC_EXPONENT,
- KeyParameterValue::IncludeUniqueID => Tag::INCLUDE_UNIQUE_ID,
- KeyParameterValue::BootLoaderOnly => Tag::BOOTLOADER_ONLY,
- KeyParameterValue::RollbackResistance => Tag::ROLLBACK_RESISTANCE,
- KeyParameterValue::ActiveDateTime(_) => Tag::ACTIVE_DATETIME,
- KeyParameterValue::OriginationExpireDateTime(_) => Tag::ORIGINATION_EXPIRE_DATETIME,
- KeyParameterValue::UsageExpireDateTime(_) => Tag::USAGE_EXPIRE_DATETIME,
- KeyParameterValue::MinSecondsBetweenOps(_) => Tag::MIN_SECONDS_BETWEEN_OPS,
- KeyParameterValue::MaxUsesPerBoot(_) => Tag::MAX_USES_PER_BOOT,
- KeyParameterValue::UserID(_) => Tag::USER_ID,
- KeyParameterValue::UserSecureID(_) => Tag::USER_SECURE_ID,
- KeyParameterValue::NoAuthRequired => Tag::NO_AUTH_REQUIRED,
- KeyParameterValue::HardwareAuthenticatorType(_) => Tag::USER_AUTH_TYPE,
- KeyParameterValue::AuthTimeout(_) => Tag::AUTH_TIMEOUT,
- KeyParameterValue::AllowWhileOnBody => Tag::ALLOW_WHILE_ON_BODY,
- KeyParameterValue::TrustedUserPresenceRequired => Tag::TRUSTED_USER_PRESENCE_REQUIRED,
- KeyParameterValue::TrustedConfirmationRequired => Tag::TRUSTED_CONFIRMATION_REQUIRED,
- KeyParameterValue::UnlockedDeviceRequired => Tag::UNLOCKED_DEVICE_REQUIRED,
- KeyParameterValue::ApplicationID(_) => Tag::APPLICATION_ID,
- KeyParameterValue::ApplicationData(_) => Tag::APPLICATION_DATA,
- KeyParameterValue::CreationDateTime(_) => Tag::CREATION_DATETIME,
- KeyParameterValue::KeyOrigin(_) => Tag::ORIGIN,
- KeyParameterValue::RootOfTrust(_) => Tag::ROOT_OF_TRUST,
- KeyParameterValue::OSVersion(_) => Tag::OS_VERSION,
- KeyParameterValue::OSPatchLevel(_) => Tag::OS_PATCHLEVEL,
- KeyParameterValue::UniqueID(_) => Tag::UNIQUE_ID,
- KeyParameterValue::AttestationChallenge(_) => Tag::ATTESTATION_CHALLENGE,
- KeyParameterValue::AttestationApplicationID(_) => Tag::ATTESTATION_APPLICATION_ID,
- KeyParameterValue::AttestationIdBrand(_) => Tag::ATTESTATION_ID_BRAND,
- KeyParameterValue::AttestationIdDevice(_) => Tag::ATTESTATION_ID_DEVICE,
- KeyParameterValue::AttestationIdProduct(_) => Tag::ATTESTATION_ID_PRODUCT,
- KeyParameterValue::AttestationIdSerial(_) => Tag::ATTESTATION_ID_SERIAL,
- KeyParameterValue::AttestationIdIMEI(_) => Tag::ATTESTATION_ID_IMEI,
- KeyParameterValue::AttestationIdMEID(_) => Tag::ATTESTATION_ID_MEID,
- KeyParameterValue::AttestationIdManufacturer(_) => Tag::ATTESTATION_ID_MANUFACTURER,
- KeyParameterValue::AttestationIdModel(_) => Tag::ATTESTATION_ID_MODEL,
- KeyParameterValue::VendorPatchLevel(_) => Tag::VENDOR_PATCHLEVEL,
- KeyParameterValue::BootPatchLevel(_) => Tag::BOOT_PATCHLEVEL,
- KeyParameterValue::AssociatedData(_) => Tag::ASSOCIATED_DATA,
- KeyParameterValue::Nonce(_) => Tag::NONCE,
- KeyParameterValue::MacLength(_) => Tag::MAC_LENGTH,
- KeyParameterValue::ResetSinceIdRotation => Tag::RESET_SINCE_ID_ROTATION,
- KeyParameterValue::ConfirmationToken(_) => Tag::CONFIRMATION_TOKEN,
- }
- }
-
- /// Returns key parameter value.
- pub fn key_parameter_value(&self) -> &KeyParameterValue {
- &self.key_parameter_value
- }
-
- /// Returns the security level of a KeyParameter.
- pub fn security_level(&self) -> &SecurityLevel {
- &self.security_level
- }
-
- /// An authorization is a KeyParameter with an associated security level that is used
- /// to convey the key characteristics to keystore clients. This function consumes
- /// an internal KeyParameter representation to produce the Authorization wire type.
- pub fn into_authorization(self) -> Authorization {
- Authorization {
- securityLevel: self.security_level,
- keyParameter: self.key_parameter_value.convert_to_wire(),
- }
- }
-}
-
-impl ToSql for KeyParameterValue {
- /// Converts KeyParameterValue to be stored in rusqlite database.
- /// Note that following variants of KeyParameterValue should not be stored:
- /// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
- /// Attestation*, AssociatedData, Nonce, MacLength, ResetSinceIdRotation, ConfirmationToken.
- /// This filtering is enforced at a higher level (i.e. enforcement module) and here we support
- /// conversion for all the variants, to keep error handling simple.
- fn to_sql(&self) -> SqlResult<ToSqlOutput> {
- match self {
- KeyParameterValue::Invalid => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::KeyPurpose(k) => Ok(ToSqlOutput::from(k.0 as u32)),
- KeyParameterValue::Algorithm(a) => Ok(ToSqlOutput::from(a.0 as u32)),
- KeyParameterValue::KeySize(k) => Ok(ToSqlOutput::from(*k)),
- KeyParameterValue::BlockMode(b) => Ok(ToSqlOutput::from(b.0 as u32)),
- KeyParameterValue::Digest(d) => Ok(ToSqlOutput::from(d.0 as u32)),
- KeyParameterValue::PaddingMode(p) => Ok(ToSqlOutput::from(p.0 as u32)),
- KeyParameterValue::CallerNonce => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::MinMacLength(m) => Ok(ToSqlOutput::from(*m)),
- KeyParameterValue::EcCurve(e) => Ok(ToSqlOutput::from(e.0 as u32)),
- KeyParameterValue::RSAPublicExponent(r) => Ok(ToSqlOutput::from(*r as i64)),
- KeyParameterValue::IncludeUniqueID => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::BootLoaderOnly => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::RollbackResistance => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::ActiveDateTime(a) => Ok(ToSqlOutput::from(*a as i64)),
- KeyParameterValue::OriginationExpireDateTime(o) => Ok(ToSqlOutput::from(*o as i64)),
- KeyParameterValue::UsageExpireDateTime(u) => Ok(ToSqlOutput::from(*u as i64)),
- KeyParameterValue::MinSecondsBetweenOps(m) => Ok(ToSqlOutput::from(*m)),
- KeyParameterValue::MaxUsesPerBoot(m) => Ok(ToSqlOutput::from(*m)),
- KeyParameterValue::UserID(u) => Ok(ToSqlOutput::from(*u)),
- KeyParameterValue::UserSecureID(u) => Ok(ToSqlOutput::from(*u as i64)),
- KeyParameterValue::NoAuthRequired => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::HardwareAuthenticatorType(h) => Ok(ToSqlOutput::from(h.0 as u32)),
- KeyParameterValue::AuthTimeout(m) => Ok(ToSqlOutput::from(*m)),
- KeyParameterValue::AllowWhileOnBody => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::TrustedUserPresenceRequired => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::TrustedConfirmationRequired => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::UnlockedDeviceRequired => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::ApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::ApplicationData(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::CreationDateTime(c) => Ok(ToSqlOutput::from(*c as i64)),
- KeyParameterValue::KeyOrigin(k) => Ok(ToSqlOutput::from(k.0 as u32)),
- KeyParameterValue::RootOfTrust(r) => Ok(ToSqlOutput::from(r.to_vec())),
- KeyParameterValue::OSVersion(o) => Ok(ToSqlOutput::from(*o)),
- KeyParameterValue::OSPatchLevel(o) => Ok(ToSqlOutput::from(*o)),
- KeyParameterValue::UniqueID(u) => Ok(ToSqlOutput::from(u.to_vec())),
- KeyParameterValue::AttestationChallenge(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationApplicationID(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationIdBrand(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationIdDevice(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationIdProduct(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationIdSerial(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationIdIMEI(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationIdMEID(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationIdManufacturer(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::AttestationIdModel(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::VendorPatchLevel(v) => Ok(ToSqlOutput::from(*v)),
- KeyParameterValue::BootPatchLevel(b) => Ok(ToSqlOutput::from(*b)),
- KeyParameterValue::AssociatedData(a) => Ok(ToSqlOutput::from(a.to_vec())),
- KeyParameterValue::Nonce(n) => Ok(ToSqlOutput::from(n.to_vec())),
- KeyParameterValue::MacLength(m) => Ok(ToSqlOutput::from(*m)),
- KeyParameterValue::ResetSinceIdRotation => Ok(ToSqlOutput::from(Null)),
- KeyParameterValue::ConfirmationToken(c) => Ok(ToSqlOutput::from(c.to_vec())),
- }
- }
-}
-
-impl KeyParameter {
/// Construct a KeyParameter from the data from a rusqlite row.
/// Note that following variants of KeyParameterValue should not be stored:
/// IncludeUniqueID, ApplicationID, ApplicationData, RootOfTrust, UniqueID,
@@ -325,569 +707,107 @@
data: &SqlField,
security_level_val: SecurityLevel,
) -> Result<Self> {
- let key_param_value = match tag_val {
- Tag::INVALID => KeyParameterValue::Invalid,
- Tag::PURPOSE => {
- let key_purpose: i32 = data
- .get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to read sql data for tag: PURPOSE.")?;
- KeyParameterValue::KeyPurpose(KeyPurpose(key_purpose))
- }
- Tag::ALGORITHM => {
- let algorithm: i32 = data
- .get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to read sql data for tag: ALGORITHM.")?;
- KeyParameterValue::Algorithm(Algorithm(algorithm))
- }
- Tag::KEY_SIZE => {
- let key_size: i32 =
- data.get().context("Failed to read sql data for tag: KEY_SIZE.")?;
- KeyParameterValue::KeySize(key_size)
- }
- Tag::BLOCK_MODE => {
- let block_mode: i32 = data
- .get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to read sql data for tag: BLOCK_MODE.")?;
- KeyParameterValue::BlockMode(BlockMode(block_mode))
- }
- Tag::DIGEST => {
- let digest: i32 = data
- .get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to read sql data for tag: DIGEST.")?;
- KeyParameterValue::Digest(Digest(digest))
- }
- Tag::PADDING => {
- let padding: i32 = data
- .get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to read sql data for tag: PADDING.")?;
- KeyParameterValue::PaddingMode(PaddingMode(padding))
- }
- Tag::CALLER_NONCE => KeyParameterValue::CallerNonce,
- Tag::MIN_MAC_LENGTH => {
- let min_mac_length: i32 =
- data.get().context("Failed to read sql data for tag: MIN_MAC_LENGTH.")?;
- KeyParameterValue::MinMacLength(min_mac_length)
- }
- Tag::EC_CURVE => {
- let ec_curve: i32 = data
- .get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to read sql data for tag: EC_CURVE.")?;
- KeyParameterValue::EcCurve(EcCurve(ec_curve))
- }
- Tag::RSA_PUBLIC_EXPONENT => {
- let rsa_pub_exponent: i64 =
- data.get().context("Failed to read sql data for tag: RSA_PUBLIC_EXPONENT.")?;
+ Ok(Self {
+ value: KeyParameterValue::new_from_sql(tag_val, data)?,
+ security_level: security_level_val,
+ })
+ }
- KeyParameterValue::RSAPublicExponent(rsa_pub_exponent)
- }
- Tag::INCLUDE_UNIQUE_ID => KeyParameterValue::IncludeUniqueID,
- Tag::BOOTLOADER_ONLY => KeyParameterValue::BootLoaderOnly,
- Tag::ROLLBACK_RESISTANCE => KeyParameterValue::RollbackResistance,
- Tag::ACTIVE_DATETIME => {
- let active_datetime: i64 =
- data.get().context("Failed to read sql data for tag: ACTIVE_DATETIME.")?;
- KeyParameterValue::ActiveDateTime(active_datetime)
- }
- Tag::ORIGINATION_EXPIRE_DATETIME => {
- let origination_expire_datetime: i64 = data
- .get()
- .context("Failed to read sql data for tag: ORIGINATION_EXPIRE_DATETIME.")?;
- KeyParameterValue::OriginationExpireDateTime(origination_expire_datetime)
- }
- Tag::USAGE_EXPIRE_DATETIME => {
- let usage_expire_datetime: i64 = data
- .get()
- .context("Failed to read sql data for tag: USAGE_EXPIRE_DATETIME.")?;
- KeyParameterValue::UsageExpireDateTime(usage_expire_datetime)
- }
- Tag::MIN_SECONDS_BETWEEN_OPS => {
- let min_secs_between_ops: i32 = data
- .get()
- .context("Failed to read sql data for tag: MIN_SECONDS_BETWEEN_OPS.")?;
- KeyParameterValue::MinSecondsBetweenOps(min_secs_between_ops)
- }
- Tag::MAX_USES_PER_BOOT => {
- let max_uses_per_boot: i32 =
- data.get().context("Failed to read sql data for tag: MAX_USES_PER_BOOT.")?;
- KeyParameterValue::MaxUsesPerBoot(max_uses_per_boot)
- }
- Tag::USER_ID => {
- let user_id: i32 =
- data.get().context("Failed to read sql data for tag: USER_ID.")?;
- KeyParameterValue::UserID(user_id)
- }
- Tag::USER_SECURE_ID => {
- let user_secure_id: i64 =
- data.get().context("Failed to read sql data for tag: USER_SECURE_ID.")?;
- KeyParameterValue::UserSecureID(user_secure_id)
- }
- Tag::NO_AUTH_REQUIRED => KeyParameterValue::NoAuthRequired,
- Tag::USER_AUTH_TYPE => {
- let user_auth_type: i32 = data
- .get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
- KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType(
- user_auth_type,
- ))
- }
- Tag::AUTH_TIMEOUT => {
- let auth_timeout: i32 =
- data.get().context("Failed to read sql data for tag: AUTH_TIMEOUT.")?;
- KeyParameterValue::AuthTimeout(auth_timeout)
- }
- Tag::ALLOW_WHILE_ON_BODY => KeyParameterValue::AllowWhileOnBody,
- Tag::TRUSTED_USER_PRESENCE_REQUIRED => KeyParameterValue::TrustedUserPresenceRequired,
- Tag::TRUSTED_CONFIRMATION_REQUIRED => KeyParameterValue::TrustedConfirmationRequired,
- Tag::UNLOCKED_DEVICE_REQUIRED => KeyParameterValue::UnlockedDeviceRequired,
- Tag::APPLICATION_ID => {
- let app_id: Vec<u8> =
- data.get().context("Failed to read sql data for tag: APPLICATION_ID.")?;
- KeyParameterValue::ApplicationID(app_id)
- }
- Tag::APPLICATION_DATA => {
- let app_data: Vec<u8> =
- data.get().context("Failed to read sql data for tag: APPLICATION_DATA.")?;
- KeyParameterValue::ApplicationData(app_data)
- }
- Tag::CREATION_DATETIME => {
- let creation_datetime: i64 =
- data.get().context("Failed to read sql data for tag: CREATION_DATETIME.")?;
- KeyParameterValue::CreationDateTime(creation_datetime)
- }
- Tag::ORIGIN => {
- let origin: i32 = data
- .get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to read sql data for tag: ORIGIN.")?;
- KeyParameterValue::KeyOrigin(KeyOrigin(origin))
- }
- Tag::ROOT_OF_TRUST => {
- let root_of_trust: Vec<u8> =
- data.get().context("Failed to read sql data for tag: ROOT_OF_TRUST.")?;
- KeyParameterValue::RootOfTrust(root_of_trust)
- }
- Tag::OS_VERSION => {
- let os_version: i32 =
- data.get().context("Failed to read sql data for tag: OS_VERSION.")?;
- KeyParameterValue::OSVersion(os_version)
- }
- Tag::OS_PATCHLEVEL => {
- let os_patch_level: i32 =
- data.get().context("Failed to read sql data for tag: OS_PATCHLEVEL.")?;
- KeyParameterValue::OSPatchLevel(os_patch_level)
- }
- Tag::UNIQUE_ID => {
- let unique_id: Vec<u8> =
- data.get().context("Failed to read sql data for tag: UNIQUE_ID.")?;
- KeyParameterValue::UniqueID(unique_id)
- }
- Tag::ATTESTATION_CHALLENGE => {
- let attestation_challenge: Vec<u8> = data
- .get()
- .context("Failed to read sql data for tag: ATTESTATION_CHALLENGE.")?;
- KeyParameterValue::AttestationChallenge(attestation_challenge)
- }
- Tag::ATTESTATION_APPLICATION_ID => {
- let attestation_app_id: Vec<u8> = data
- .get()
- .context("Failed to read sql data for tag: ATTESTATION_APPLICATION_ID.")?;
- KeyParameterValue::AttestationApplicationID(attestation_app_id)
- }
- Tag::ATTESTATION_ID_BRAND => {
- let attestation_id_brand: Vec<u8> =
- data.get().context("Failed to read sql data for tag: ATTESTATION_ID_BRAND.")?;
- KeyParameterValue::AttestationIdBrand(attestation_id_brand)
- }
- Tag::ATTESTATION_ID_DEVICE => {
- let attestation_id_device: Vec<u8> = data
- .get()
- .context("Failed to read sql data for tag: ATTESTATION_ID_DEVICE.")?;
- KeyParameterValue::AttestationIdDevice(attestation_id_device)
- }
- Tag::ATTESTATION_ID_PRODUCT => {
- let attestation_id_product: Vec<u8> = data
- .get()
- .context("Failed to read sql data for tag: ATTESTATION_ID_PRODUCT.")?;
- KeyParameterValue::AttestationIdProduct(attestation_id_product)
- }
- Tag::ATTESTATION_ID_SERIAL => {
- let attestation_id_serial: Vec<u8> = data
- .get()
- .context("Failed to read sql data for tag: ATTESTATION_ID_SERIAL.")?;
- KeyParameterValue::AttestationIdSerial(attestation_id_serial)
- }
- Tag::ATTESTATION_ID_IMEI => {
- let attestation_id_imei: Vec<u8> =
- data.get().context("Failed to read sql data for tag: ATTESTATION_ID_IMEI.")?;
- KeyParameterValue::AttestationIdIMEI(attestation_id_imei)
- }
- Tag::ATTESTATION_ID_MEID => {
- let attestation_id_meid: Vec<u8> =
- data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MEID.")?;
- KeyParameterValue::AttestationIdMEID(attestation_id_meid)
- }
- Tag::ATTESTATION_ID_MANUFACTURER => {
- let attestation_id_manufacturer: Vec<u8> = data
- .get()
- .context("Failed to read sql data for tag: ATTESTATION_ID_MANUFACTURER.")?;
- KeyParameterValue::AttestationIdManufacturer(attestation_id_manufacturer)
- }
- Tag::ATTESTATION_ID_MODEL => {
- let attestation_id_model: Vec<u8> =
- data.get().context("Failed to read sql data for tag: ATTESTATION_ID_MODEL.")?;
- KeyParameterValue::AttestationIdModel(attestation_id_model)
- }
- Tag::VENDOR_PATCHLEVEL => {
- let vendor_patch_level: i32 =
- data.get().context("Failed to read sql data for tag: VENDOR_PATCHLEVEL.")?;
- KeyParameterValue::VendorPatchLevel(vendor_patch_level)
- }
- Tag::BOOT_PATCHLEVEL => {
- let boot_patch_level: i32 =
- data.get().context("Failed to read sql data for tag: BOOT_PATCHLEVEL.")?;
- KeyParameterValue::BootPatchLevel(boot_patch_level)
- }
- Tag::ASSOCIATED_DATA => {
- let associated_data: Vec<u8> =
- data.get().context("Failed to read sql data for tag: ASSOCIATED_DATA.")?;
- KeyParameterValue::AssociatedData(associated_data)
- }
- Tag::NONCE => {
- let nonce: Vec<u8> =
- data.get().context("Failed to read sql data for tag: NONCE.")?;
- KeyParameterValue::Nonce(nonce)
- }
- Tag::MAC_LENGTH => {
- let mac_length: i32 =
- data.get().context("Failed to read sql data for tag: MAC_LENGTH.")?;
- KeyParameterValue::MacLength(mac_length)
- }
- Tag::RESET_SINCE_ID_ROTATION => KeyParameterValue::ResetSinceIdRotation,
- Tag::CONFIRMATION_TOKEN => {
- let confirmation_token: Vec<u8> =
- data.get().context("Failed to read sql data for tag: CONFIRMATION_TOKEN.")?;
- KeyParameterValue::ConfirmationToken(confirmation_token)
- }
- _ => {
- return Err(KeystoreError::Rc(ResponseCode::VALUE_CORRUPTED))
- .context("Failed to decode Tag enum from value.")?
- }
- };
- Ok(KeyParameter::new(key_param_value, security_level_val))
+ /// Get the KeyMint Tag of this this key parameter.
+ pub fn get_tag(&self) -> Tag {
+ self.value.get_tag()
+ }
+
+ /// Returns key parameter value.
+ pub fn key_parameter_value(&self) -> &KeyParameterValue {
+ &self.value
+ }
+
+ /// Returns the security level of this key parameter.
+ pub fn security_level(&self) -> &SecurityLevel {
+ &self.security_level
+ }
+
+ /// An authorization is a KeyParameter with an associated security level that is used
+ /// to convey the key characteristics to keystore clients. This function consumes
+ /// an internal KeyParameter representation to produce the Authorization wire type.
+ pub fn into_authorization(self) -> Authorization {
+ Authorization { securityLevel: self.security_level, keyParameter: self.value.into() }
}
}
-/// Macro rules for converting key parameter to/from wire type.
-/// This macro takes between three and four different pieces of information about each
-/// of the KeyParameterValue variants:
-/// 1. The KeyParameterValue variant name,
-/// 2. the tag name corresponding to the variant,
-/// 3. the field name in the KmKeyParameter struct, in which information about this variant is
-/// stored when converted, and
-/// 4. an optional enum type name when the nested value is of enum type.
-/// The macro takes a set of lines corresponding to each KeyParameterValue variant and generates
-/// the two conversion methods: convert_to_wire() and convert_from_wire().
-/// ## Example
-/// ```
-/// implement_key_parameter_conversion_to_from_wire! {
-/// Invalid, INVALID, na;
-/// KeyPurpose, PURPOSE, integer, KeyPurpose;
-/// CallerNonce, CALLER_NONCE, boolValue;
-/// UserSecureID, USER_SECURE_ID, longInteger;
-/// ApplicationID, APPLICATION_ID, blob;
-/// }
-/// ```
-/// expands to:
-/// ```
-/// pub fn convert_to_wire(self) -> KmKeyParameter {
-/// match self {
-/// KeyParameterValue::Invalid => KmKeyParameter {
-/// tag: Tag::INVALID,
-/// ..Default::default()
-/// },
-/// KeyParameterValue::KeyPurpose(v) => KmKeyParameter {
-/// tag: Tag::PURPOSE,
-/// integer: v.0,
-/// ..Default::default()
-/// },
-/// KeyParameterValue::CallerNonce => KmKeyParameter {
-/// tag: Tag::CALLER_NONCE,
-/// boolValue: true,
-/// ..Default::default()
-/// },
-/// KeyParameterValue::UserSecureID(v) => KmKeyParameter {
-/// tag: Tag::USER_SECURE_ID,
-/// longInteger: v,
-/// ..Default::default()
-/// },
-/// KeyParameterValue::ApplicationID(v) => KmKeyParameter {
-/// tag: Tag::APPLICATION_ID,
-/// blob: v,
-/// ..Default::default()
-/// },
-/// }
-/// }
-/// ```
-/// and
-/// ```
-/// pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
-/// match aidl_kp {
-/// KmKeyParameter {
-/// tag: Tag::INVALID,
-/// ..
-/// } => KeyParameterValue::Invalid,
-/// KmKeyParameter {
-/// tag: Tag::PURPOSE,
-/// integer: v,
-/// ..
-/// } => KeyParameterValue::KeyPurpose(KeyPurpose(v)),
-/// KmKeyParameter {
-/// tag: Tag::CALLER_NONCE,
-/// boolValue: true,
-/// ..
-/// } => KeyParameterValue::CallerNonce,
-/// KmKeyParameter {
-/// tag: Tag::USER_SECURE_ID,
-/// longInteger: v,
-/// ..
-/// } => KeyParameterValue::UserSecureID(v),
-/// KmKeyParameter {
-/// tag: Tag::APPLICATION_ID,
-/// blob: v,
-/// ..
-/// } => KeyParameterValue::ApplicationID(v),
-/// _ => KeyParameterValue::Invalid,
-/// }
-/// }
-///
-macro_rules! implement_key_parameter_conversion_to_from_wire {
- // There are three groups of rules in this macro.
- // 1. The first group contains the rule which acts as the public interface. It takes the input
- // given to this macro and prepares it to be given as input to the two groups of rules
- // mentioned below.
- // 2. The second group starts with the prefix @to and generates convert_to_wire() method.
- // 3. The third group starts with the prefix @from and generates convert_from_wire() method.
- //
- // Input to this macro is first handled by the first macro rule (belonging to the first
- // group above), which pre-processes the input such that rules in the other two groups
- // generate the code for the two methods, when called recursively.
- // Each of convert_to_wire() and convert_from_wire() methods are generated using a set of
- // four macro rules in the second two groups. These four rules intend to do the following
- // tasks respectively:
- // i) generates match arms related to Invalid KeyParameterValue variant.
- // ii) generates match arms related to boolValue field in KmKeyParameter struct.
- // iii) generates match arms related to all the other fields in KmKeyParameter struct.
- // iv) generates the method definition including the match arms generated from the above
- // three recursive macro rules.
+#[cfg(test)]
+mod generated_key_parameter_tests {
+ use super::*;
+ use android_hardware_security_keymint::aidl::android::hardware::security::keymint::TagType::TagType;
- // This rule is applied on the input given to the macro invocations from outside the macro.
- ($($variant:ident, $tag_name:ident, $field_name:ident $(,$enum_type:ident)?;)*) => {
- // pre-processes input to target the rules that generate convert_to_wire() method.
- implement_key_parameter_conversion_to_from_wire! {@to
- [], $($variant, $tag_name, $field_name;)*
+ fn get_field_by_tag_type(tag: Tag) -> KmKeyParameterValue {
+ let tag_type = TagType((tag.0 as u32 & 0xF0000000) as i32);
+ match tag {
+ Tag::ALGORITHM => return KmKeyParameterValue::Algorithm(Default::default()),
+ Tag::BLOCK_MODE => return KmKeyParameterValue::BlockMode(Default::default()),
+ Tag::PADDING => return KmKeyParameterValue::PaddingMode(Default::default()),
+ Tag::DIGEST => return KmKeyParameterValue::Digest(Default::default()),
+ Tag::EC_CURVE => return KmKeyParameterValue::EcCurve(Default::default()),
+ Tag::ORIGIN => return KmKeyParameterValue::Origin(Default::default()),
+ Tag::PURPOSE => return KmKeyParameterValue::KeyPurpose(Default::default()),
+ Tag::USER_AUTH_TYPE => {
+ return KmKeyParameterValue::HardwareAuthenticatorType(Default::default())
+ }
+ Tag::HARDWARE_TYPE => return KmKeyParameterValue::SecurityLevel(Default::default()),
+ _ => {}
}
- // pre-processes input to target the rules that generate convert_from_wire() method.
- implement_key_parameter_conversion_to_from_wire! {@from
- [], $($variant, $tag_name, $field_name;)*
+ match tag_type {
+ TagType::INVALID => return KmKeyParameterValue::Invalid(Default::default()),
+ TagType::ENUM | TagType::ENUM_REP => {}
+ TagType::UINT | TagType::UINT_REP => {
+ return KmKeyParameterValue::Integer(Default::default())
+ }
+ TagType::ULONG | TagType::ULONG_REP => {
+ return KmKeyParameterValue::LongInteger(Default::default())
+ }
+ TagType::DATE => return KmKeyParameterValue::DateTime(Default::default()),
+ TagType::BOOL => return KmKeyParameterValue::BoolValue(Default::default()),
+ TagType::BIGNUM | TagType::BYTES => {
+ return KmKeyParameterValue::Blob(Default::default())
+ }
+ _ => {}
}
- };
+ panic!("Unknown tag/tag_type: {:?} {:?}", tag, tag_type);
+ }
- // Following four rules (belonging to the aforementioned second group) generate
- // convert_to_wire() conversion method.
- // -----------------------------------------------------------------------
- // This rule handles Invalid variant.
- // On an input: `Invalid, INVALID, Invalid;` it generates a match arm like:
- // KeyParameterValue::Invalid => KmKeyParameter {
- // tag: Tag::INVALID,
- // value: KmKeyParameterValue::Invalid(0),
- // },
- (@to [$($out:tt)*], Invalid, INVALID, Invalid; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@to
- [$($out)*
- KeyParameterValue::Invalid => KmKeyParameter {
- tag: Tag::INVALID,
- value: KmKeyParameterValue::Invalid(0),
- },
- ], $($in)*
- }
- };
- // This rule handles all variants that correspond to bool values.
- // On an input like: `CallerNonce, CALLER_NONCE, BoolValue;` it generates
- // a match arm like:
- // KeyParameterValue::CallerNonce => KmKeyParameter {
- // tag: Tag::CALLER_NONCE,
- // value: KmKeyParameterValue::BoolValue(true),
- // },
- (@to [$($out:tt)*], $variant:ident, $tag_val:ident, BoolValue; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@to
- [$($out)*
- KeyParameterValue::$variant => KmKeyParameter {
- tag: Tag::$tag_val,
- value: KmKeyParameterValue::BoolValue(true),
- },
- ], $($in)*
- }
- };
- // This rule handles all variants that are neither invalid nor bool values nor enums
- // (i.e. all variants which correspond to integer, longInteger, and blob fields in
- // KmKeyParameter).
- // On an input like: `ConfirmationToken, CONFIRMATION_TOKEN, Blob;` it generates a match arm
- // like: KeyParameterValue::ConfirmationToken(v) => KmKeyParameter {
- // tag: Tag::CONFIRMATION_TOKEN,
- // value: KmKeyParameterValue::$field(v),
- // },
- (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@to
- [$($out)*
- KeyParameterValue::$variant(v) => KmKeyParameter {
- tag: Tag::$tag_val,
- value: KmKeyParameterValue::$field(v),
- },
- ], $($in)*
- }
- };
- // After all the match arms are generated by the above three rules, this rule combines them
- // into the convert_to_wire() method.
- (@to [$($out:tt)*], ) => {
- /// Conversion of key parameter to wire type
- pub fn convert_to_wire(self) -> KmKeyParameter {
- match self {
- $($out)*
+ fn check_field_matches_tag_type(list_o_parameters: &[KmKeyParameter]) {
+ for kp in list_o_parameters.iter() {
+ match (&kp.value, get_field_by_tag_type(kp.tag)) {
+ (&KmKeyParameterValue::Algorithm(_), KmKeyParameterValue::Algorithm(_))
+ | (&KmKeyParameterValue::BlockMode(_), KmKeyParameterValue::BlockMode(_))
+ | (&KmKeyParameterValue::PaddingMode(_), KmKeyParameterValue::PaddingMode(_))
+ | (&KmKeyParameterValue::Digest(_), KmKeyParameterValue::Digest(_))
+ | (&KmKeyParameterValue::EcCurve(_), KmKeyParameterValue::EcCurve(_))
+ | (&KmKeyParameterValue::Origin(_), KmKeyParameterValue::Origin(_))
+ | (&KmKeyParameterValue::KeyPurpose(_), KmKeyParameterValue::KeyPurpose(_))
+ | (
+ &KmKeyParameterValue::HardwareAuthenticatorType(_),
+ KmKeyParameterValue::HardwareAuthenticatorType(_),
+ )
+ | (&KmKeyParameterValue::SecurityLevel(_), KmKeyParameterValue::SecurityLevel(_))
+ | (&KmKeyParameterValue::Invalid(_), KmKeyParameterValue::Invalid(_))
+ | (&KmKeyParameterValue::Integer(_), KmKeyParameterValue::Integer(_))
+ | (&KmKeyParameterValue::LongInteger(_), KmKeyParameterValue::LongInteger(_))
+ | (&KmKeyParameterValue::DateTime(_), KmKeyParameterValue::DateTime(_))
+ | (&KmKeyParameterValue::BoolValue(_), KmKeyParameterValue::BoolValue(_))
+ | (&KmKeyParameterValue::Blob(_), KmKeyParameterValue::Blob(_)) => {}
+ (actual, expected) => panic!(
+ "Tag {:?} associated with variant {:?} expected {:?}",
+ kp.tag, actual, expected
+ ),
}
}
- };
+ }
- // Following four rules (belonging to the aforementioned third group) generate
- // convert_from_wire() conversion method.
- // ------------------------------------------------------------------------
- // This rule handles Invalid variant.
- // On an input: `Invalid, INVALID, Invalid;` it generates a match arm like:
- // KmKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
- (@from [$($out:tt)*], Invalid, INVALID, Invalid; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@from
- [$($out)*
- KmKeyParameter {
- tag: Tag::INVALID,
- ..
- } => KeyParameterValue::Invalid,
- ], $($in)*
- }
- };
- // This rule handles all variants that correspond to bool values.
- // On an input like: `CallerNonce, CALLER_NONCE, BoolValue;` it generates a match arm like:
- // KmKeyParameter {
- // tag: Tag::CALLER_NONCE,
- // boolValue: true,
- // ..
- // } => KeyParameterValue::CallerNonce,
- (@from [$($out:tt)*], $variant:ident, $tag_val:ident, BoolValue; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@from
- [$($out)*
- KmKeyParameter {
- tag: Tag::$tag_val,
- value: KmKeyParameterValue::BoolValue(true),
- } => KeyParameterValue::$variant,
- ], $($in)*
- }
- };
- // This rule handles all variants that are neither invalid nor bool values nor enums
- // (i.e. all variants which correspond to integer, longInteger, and blob fields in
- // KmKeyParameter).
- // On an input like: `ConfirmationToken, CONFIRMATION_TOKEN, Blob;` it generates a match arm
- // like:
- // KmKeyParameter {
- // tag: Tag::CONFIRMATION_TOKEN,
- // value: KmKeyParameterValue::Blob(v),
- // } => KeyParameterValue::ConfirmationToken(v),
- (@from [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
- implement_key_parameter_conversion_to_from_wire! {@from
- [$($out)*
- KmKeyParameter {
- tag: Tag::$tag_val,
- value: KmKeyParameterValue::$field(v),
- } => KeyParameterValue::$variant(v),
- ], $($in)*
- }
- };
- // After all the match arms are generated by the above three rules, this rule combines them
- // into the convert_from_wire() method.
- (@from [$($out:tt)*], ) => {
- /// Conversion of key parameter from wire type
- pub fn convert_from_wire(aidl_kp: KmKeyParameter) -> KeyParameterValue {
- match aidl_kp {
- $($out)*
- _ => KeyParameterValue::Invalid,
- }
- }
- };
-}
-
-impl KeyParameterValue {
- // Invoke the macro that generates the code for key parameter conversion to/from wire type
- // with all possible variants of KeyParameterValue. Each line corresponding to a variant
- // contains: variant identifier, tag value, and the related field name (i.e.
- // boolValue/integer/longInteger/blob) in the KmKeyParameter.
- implement_key_parameter_conversion_to_from_wire! {
- Invalid, INVALID, Invalid;
- KeyPurpose, PURPOSE, KeyPurpose;
- Algorithm, ALGORITHM, Algorithm;
- KeySize, KEY_SIZE, Integer;
- BlockMode, BLOCK_MODE, BlockMode;
- Digest, DIGEST, Digest;
- PaddingMode, PADDING, PaddingMode;
- CallerNonce, CALLER_NONCE, BoolValue;
- MinMacLength, MIN_MAC_LENGTH, Integer;
- EcCurve, EC_CURVE, EcCurve;
- RSAPublicExponent, RSA_PUBLIC_EXPONENT, LongInteger;
- IncludeUniqueID, INCLUDE_UNIQUE_ID, BoolValue;
- BootLoaderOnly, BOOTLOADER_ONLY, BoolValue;
- RollbackResistance, ROLLBACK_RESISTANCE, BoolValue;
- ActiveDateTime, ACTIVE_DATETIME, DateTime;
- OriginationExpireDateTime, ORIGINATION_EXPIRE_DATETIME, DateTime;
- UsageExpireDateTime, USAGE_EXPIRE_DATETIME, DateTime;
- MinSecondsBetweenOps, MIN_SECONDS_BETWEEN_OPS, Integer;
- MaxUsesPerBoot, MAX_USES_PER_BOOT, Integer;
- UserID, USER_ID, Integer;
- UserSecureID, USER_SECURE_ID, LongInteger;
- NoAuthRequired, NO_AUTH_REQUIRED, BoolValue;
- HardwareAuthenticatorType, USER_AUTH_TYPE, HardwareAuthenticatorType;
- AuthTimeout, AUTH_TIMEOUT, Integer;
- AllowWhileOnBody, ALLOW_WHILE_ON_BODY, BoolValue;
- TrustedUserPresenceRequired, TRUSTED_USER_PRESENCE_REQUIRED, BoolValue;
- TrustedConfirmationRequired, TRUSTED_CONFIRMATION_REQUIRED, BoolValue;
- UnlockedDeviceRequired, UNLOCKED_DEVICE_REQUIRED, BoolValue;
- ApplicationID, APPLICATION_ID, Blob;
- ApplicationData, APPLICATION_DATA, Blob;
- CreationDateTime, CREATION_DATETIME, DateTime;
- KeyOrigin, ORIGIN, Origin;
- RootOfTrust, ROOT_OF_TRUST, Blob;
- OSVersion, OS_VERSION, Integer;
- OSPatchLevel, OS_PATCHLEVEL, Integer;
- UniqueID, UNIQUE_ID, Blob;
- AttestationChallenge, ATTESTATION_CHALLENGE, Blob;
- AttestationApplicationID, ATTESTATION_APPLICATION_ID, Blob;
- AttestationIdBrand, ATTESTATION_ID_BRAND, Blob;
- AttestationIdDevice, ATTESTATION_ID_DEVICE, Blob;
- AttestationIdProduct, ATTESTATION_ID_PRODUCT, Blob;
- AttestationIdSerial, ATTESTATION_ID_SERIAL, Blob;
- AttestationIdIMEI, ATTESTATION_ID_IMEI, Blob;
- AttestationIdMEID, ATTESTATION_ID_MEID, Blob;
- AttestationIdManufacturer, ATTESTATION_ID_MANUFACTURER, Blob;
- AttestationIdModel, ATTESTATION_ID_MODEL, Blob;
- VendorPatchLevel, VENDOR_PATCHLEVEL, Integer;
- BootPatchLevel, BOOT_PATCHLEVEL, Integer;
- AssociatedData, ASSOCIATED_DATA, Blob;
- Nonce, NONCE, Blob;
- MacLength, MAC_LENGTH, Integer;
- ResetSinceIdRotation, RESET_SINCE_ID_ROTATION, BoolValue;
- ConfirmationToken, CONFIRMATION_TOKEN, Blob;
+ #[test]
+ fn key_parameter_value_field_matches_tag_type() {
+ check_field_matches_tag_type(&KeyParameterValue::make_field_matches_tag_type_test_vector());
}
}
@@ -1108,10 +1028,8 @@
fn test_non_existing_enum_variant() -> Result<()> {
let db = init_db()?;
insert_into_keyparameter(&db, 1, 100, &123, 1)?;
- tests::check_result_contains_error_string(
- query_from_keyparameter(&db),
- "Failed to decode Tag enum from value.",
- );
+ let key_param = query_from_keyparameter(&db)?;
+ assert_eq!(Tag::INVALID, key_param.get_tag());
Ok(())
}
@@ -1197,15 +1115,18 @@
#[test]
fn test_convert_to_wire_invalid() {
let kp = KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::STRONGBOX);
- let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
- assert_eq!(Tag::INVALID, actual.tag);
+ assert_eq!(
+ KmKeyParameter { tag: Tag::INVALID, value: KmKeyParameterValue::Invalid(0) },
+ kp.value.into()
+ );
}
#[test]
fn test_convert_to_wire_bool() {
let kp = KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::STRONGBOX);
- let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
- assert_eq!(Tag::CALLER_NONCE, actual.tag);
- assert_eq!(KmKeyParameterValue::BoolValue(true), actual.value);
+ assert_eq!(
+ KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) },
+ kp.value.into()
+ );
}
#[test]
fn test_convert_to_wire_integer() {
@@ -1213,17 +1134,25 @@
KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
SecurityLevel::STRONGBOX,
);
- let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
- assert_eq!(Tag::PURPOSE, actual.tag);
- assert_eq!(KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual.value);
+ assert_eq!(
+ KmKeyParameter {
+ tag: Tag::PURPOSE,
+ value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT)
+ },
+ kp.value.into()
+ );
}
#[test]
fn test_convert_to_wire_long_integer() {
let kp =
KeyParameter::new(KeyParameterValue::UserSecureID(i64::MAX), SecurityLevel::STRONGBOX);
- let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
- assert_eq!(Tag::USER_SECURE_ID, actual.tag);
- assert_eq!(KmKeyParameterValue::LongInteger(i64::MAX), actual.value);
+ assert_eq!(
+ KmKeyParameter {
+ tag: Tag::USER_SECURE_ID,
+ value: KmKeyParameterValue::LongInteger(i64::MAX)
+ },
+ kp.value.into()
+ );
}
#[test]
fn test_convert_to_wire_blob() {
@@ -1231,11 +1160,12 @@
KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
SecurityLevel::STRONGBOX,
);
- let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
- assert_eq!(Tag::CONFIRMATION_TOKEN, actual.tag);
assert_eq!(
- KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
- actual.value
+ KmKeyParameter {
+ tag: Tag::CONFIRMATION_TOKEN,
+ value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes())
+ },
+ kp.value.into()
);
}
@@ -1243,15 +1173,13 @@
#[test]
fn test_convert_from_wire_invalid() {
let aidl_kp = KmKeyParameter { tag: Tag::INVALID, ..Default::default() };
- let actual = KeyParameterValue::convert_from_wire(aidl_kp);
- assert_eq!(KeyParameterValue::Invalid, actual);
+ assert_eq!(KeyParameterValue::Invalid, aidl_kp.into());
}
#[test]
fn test_convert_from_wire_bool() {
let aidl_kp =
KmKeyParameter { tag: Tag::CALLER_NONCE, value: KmKeyParameterValue::BoolValue(true) };
- let actual = KeyParameterValue::convert_from_wire(aidl_kp);
- assert_eq!(KeyParameterValue::CallerNonce, actual);
+ assert_eq!(KeyParameterValue::CallerNonce, aidl_kp.into());
}
#[test]
fn test_convert_from_wire_integer() {
@@ -1259,8 +1187,7 @@
tag: Tag::PURPOSE,
value: KmKeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
};
- let actual = KeyParameterValue::convert_from_wire(aidl_kp);
- assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
+ assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), aidl_kp.into());
}
#[test]
fn test_convert_from_wire_long_integer() {
@@ -1268,8 +1195,7 @@
tag: Tag::USER_SECURE_ID,
value: KmKeyParameterValue::LongInteger(i64::MAX),
};
- let actual = KeyParameterValue::convert_from_wire(aidl_kp);
- assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
+ assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), aidl_kp.into());
}
#[test]
fn test_convert_from_wire_blob() {
@@ -1277,10 +1203,9 @@
tag: Tag::CONFIRMATION_TOKEN,
value: KmKeyParameterValue::Blob(String::from("ConfirmationToken").into_bytes()),
};
- let actual = KeyParameterValue::convert_from_wire(aidl_kp);
assert_eq!(
KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
- actual
+ aidl_kp.into()
);
}
}
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 7a6d6d7..d50f70e 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -19,9 +19,9 @@
//! This module implements utility functions used by the Keystore 2.0 service
//! implementation.
+use crate::error::Error;
use crate::permission;
use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
-use crate::{error::Error, key_parameter::KeyParameterValue};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
KeyCharacteristics::KeyCharacteristics, SecurityLevel::SecurityLevel,
};
@@ -119,17 +119,9 @@
key_characteristics
.hardwareEnforced
.into_iter()
- .map(|aidl_kp| {
- crate::key_parameter::KeyParameter::new(
- KeyParameterValue::convert_from_wire(aidl_kp),
- hw_security_level,
- )
- })
+ .map(|aidl_kp| crate::key_parameter::KeyParameter::new(aidl_kp.into(), hw_security_level))
.chain(key_characteristics.softwareEnforced.into_iter().map(|aidl_kp| {
- crate::key_parameter::KeyParameter::new(
- KeyParameterValue::convert_from_wire(aidl_kp),
- SecurityLevel::SOFTWARE,
- )
+ crate::key_parameter::KeyParameter::new(aidl_kp.into(), SecurityLevel::SOFTWARE)
}))
.collect()
}