Convert KeyParameter to wire type.
For communicating with keymint and SPI.
This CL also moves all test modules to the bottom of the file.
Bug: 167744352
Test: Unit tests
Change-Id: I085dbe68076ba361c4d89f63de87c3b2f05627bc
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
index ae3d774..f08031e 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -23,7 +23,8 @@
BlockMode::BlockMode as BlockModeType, Digest, Digest::Digest as DigestType, EcCurve,
EcCurve::EcCurve as EcCurveType, HardwareAuthenticatorType,
HardwareAuthenticatorType::HardwareAuthenticatorType as HardwareAuthenticatorTypeType,
- KeyOrigin, KeyOrigin::KeyOrigin as KeyOriginType, KeyPurpose,
+ KeyOrigin, KeyOrigin::KeyOrigin as KeyOriginType,
+ KeyParameter::KeyParameter as AidlKeyParameter, KeyPurpose,
KeyPurpose::KeyPurpose as KeyPurposeType, PaddingMode,
PaddingMode::PaddingMode as PaddingModeType, SecurityLevel,
SecurityLevel::SecurityLevel as SecurityLevelType, Tag, Tag::Tag as TagType,
@@ -237,29 +238,6 @@
}
}
-#[cfg(test)]
-mod basic_tests {
- use super::*;
-
- // Test basic functionality of KeyParameter.
- #[test]
- fn test_key_parameter() {
- let key_parameter = KeyParameter::new(
- KeyParameterValue::Algorithm(Algorithm::RSA),
- SecurityLevel::STRONGBOX,
- );
-
- assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
-
- assert_eq!(
- *key_parameter.key_parameter_value(),
- KeyParameterValue::Algorithm(Algorithm::RSA)
- );
-
- assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
- }
-}
-
/// This struct is defined to postpone converting rusqlite column value to the
/// appropriate key parameter value until we know the corresponding tag value.
/// Wraps the column index and a rusqlite row.
@@ -611,6 +589,353 @@
}
}
+/// Macro rules for converting key parameter to/from wire type.
+/// This macro takes three different pieces of information about each of the KeyParameterValue
+/// variants.
+/// 1. variant name
+/// 2. tag name corresponding to the variant
+/// 3. the field name in the AidlKeyParameter struct, in which information about this variant is
+/// stored when converted
+/// 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;
+/// CallerNonce, CALLER_NONCE, boolValue;
+/// UserSecureID, USER_SECURE_ID, longInteger;
+/// ApplicationID, APPLICATION_ID, blob;
+/// ActiveDateTime, ACTIVE_DATETIME, dateTime;
+/// }
+/// ```
+/// expands to:
+/// ```
+/// pub fn convert_to_wire(self) -> AidlKeyParameter {
+/// match self {
+/// KeyParameterValue::Invalid => AidlKeyParameter {
+/// tag: Tag::INVALID,
+/// ..Default::default()
+/// },
+/// KeyParameterValue::KeyPurpose(v) => AidlKeyParameter {
+/// tag: Tag::PURPOSE,
+/// integer: v,
+/// ..Default::default()
+/// },
+/// KeyParameterValue::CallerNonce => AidlKeyParameter {
+/// tag: Tag::CALLER_NONCE,
+/// boolValue: true,
+/// ..Default::default()
+/// },
+/// KeyParameterValue::UserSecureID(v) => AidlKeyParameter {
+/// tag: Tag::USER_SECURE_ID,
+/// longInteger: v,
+/// ..Default::default()
+/// },
+/// KeyParameterValue::ApplicationID(v) => AidlKeyParameter {
+/// tag: Tag::APPLICATION_ID,
+/// blob: v,
+/// ..Default::default()
+/// },
+/// KeyParameterValue::ActiveDateTime(v) => AidlKeyParameter {
+/// tag: Tag::ACTIVE_DATETIME,
+/// dateTime: v,
+/// ..Default::default()
+/// },
+/// }
+/// }
+/// ```
+/// and
+/// ```
+/// pub fn convert_from_wire(aidl_kp: AidlKeyParameter) -> KeyParameterValue {
+/// match aidl_kp {
+/// AidlKeyParameter {
+/// tag: Tag::INVALID,
+/// ..
+/// } => KeyParameterValue::Invalid,
+/// AidlKeyParameter {
+/// tag: Tag::PURPOSE,
+/// integer: v,
+/// ..
+/// } => KeyParameterValue::KeyPurpose(v),
+/// AidlKeyParameter {
+/// tag: Tag::CALLER_NONCE,
+/// boolValue: true,
+/// ..
+/// } => KeyParameterValue::CallerNonce,
+/// AidlKeyParameter {
+/// tag: Tag::USER_SECURE_ID,
+/// longInteger: v,
+/// ..
+/// } => KeyParameterValue::UserSecureID(v),
+/// AidlKeyParameter {
+/// tag: Tag::APPLICATION_ID,
+/// blob: v,
+/// ..
+/// } => KeyParameterValue::ApplicationID(v),
+/// AidlKeyParameter {
+/// tag: Tag::ACTIVE_DATETIME,
+/// dateTime: v,
+/// ..
+/// } => KeyParameterValue::ActiveDateTime(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 AidlKeyParameter struct.
+ // iii) generates match arms related to all the other fields in AidlKeyParameter struct.
+ // iv) generates the method definition including the match arms generated from the above
+ // three recursive macro rules.
+
+ // This rule is applied on the input given to the macro invocations from outside the macro.
+ ($($variant:ident, $tag_name:ident, $field_name: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;)*
+ }
+ // 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;)*
+ }
+ };
+
+ // 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, na;' it generates a match arm like:
+ // KeyParameterValue::Invalid => AidlKeyParameter {
+ // tag: Tag::INVALID,
+ // ..Default::default()
+ // },
+ (@to [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@to
+ [$($out)*
+ KeyParameterValue::Invalid => AidlKeyParameter {
+ tag: Tag::INVALID,
+ ..Default::default()
+ },
+ ], $($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 => AidlKeyParameter {
+ // tag: Tag::CALLER_NONCE,
+ // boolValue: true,
+ // ..Default::default()
+ // },
+ (@to [$($out:tt)*], $variant:ident, $tag_val:ident, boolValue; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@to
+ [$($out)*
+ KeyParameterValue::$variant => AidlKeyParameter {
+ tag: Tag::$tag_val,
+ boolValue: true,
+ ..Default::default()
+ },
+ ], $($in)*
+ }
+ };
+ // This rule handles all variants that are neither invalid nor bool values
+ // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
+ // AidlKeyParameter).
+ // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
+ // like: KeyParameterValue::ConfirmationToken(v) => AidlKeyParameter {
+ // tag: Tag::CONFIRMATION_TOKEN,
+ // blob: v,
+ // ..Default::default(),
+ // }
+ (@to [$($out:tt)*], $variant:ident, $tag_val:ident, $field:ident; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@to
+ [$($out)*
+ KeyParameterValue::$variant(v) => AidlKeyParameter {
+ tag: Tag::$tag_val,
+ $field: v,
+ ..Default::default()
+ },
+ ], $($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) -> AidlKeyParameter {
+ match self {
+ $($out)*
+ }
+ }
+ };
+
+ // 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, na;' it generates a match arm like:
+ // AidlKeyParameter { tag: Tag::INVALID, .. } => KeyParameterValue::Invalid,
+ (@from [$($out:tt)*], Invalid, INVALID, na; $($in:tt)*) => {
+ implement_key_parameter_conversion_to_from_wire! {@from
+ [$($out)*
+ AidlKeyParameter {
+ 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:
+ // AidlKeyParameter {
+ // 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)*
+ AidlKeyParameter {
+ tag: Tag::$tag_val,
+ boolValue: true,
+ ..
+ } => KeyParameterValue::$variant,
+ ], $($in)*
+ }
+ };
+ // This rule handles all variants that are neither invalid nor bool values
+ // (i.e. all variants which correspond to integer, longInteger, dateTime and blob fields in
+ // AidlKeyParameter).
+ // On an input like: 'ConfirmationToken, CONFIRMATION_TOKEN, blob;' it generates a match arm
+ // like:
+ // AidlKeyParameter {
+ // tag: Tag::CONFIRMATION_TOKEN,
+ // 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)*
+ AidlKeyParameter {
+ tag: Tag::$tag_val,
+ $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: AidlKeyParameter) -> 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/dateTime/blob) in the AidlKeyParameter.
+ implement_key_parameter_conversion_to_from_wire! {
+ Invalid, INVALID, na;
+ KeyPurpose, PURPOSE, integer;
+ Algorithm, ALGORITHM, integer;
+ KeySize, KEY_SIZE, integer;
+ BlockMode, BLOCK_MODE, integer;
+ Digest, DIGEST, integer;
+ PaddingMode, PADDING, integer;
+ CallerNonce, CALLER_NONCE, boolValue;
+ MinMacLength, MIN_MAC_LENGTH, integer;
+ EcCurve, EC_CURVE, integer;
+ 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, integer;
+ 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, integer;
+ 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;
+ }
+}
+
+#[cfg(test)]
+mod basic_tests {
+ use crate::key_parameter::*;
+
+ // Test basic functionality of KeyParameter.
+ #[test]
+ fn test_key_parameter() {
+ let key_parameter = KeyParameter::new(
+ KeyParameterValue::Algorithm(Algorithm::RSA),
+ SecurityLevel::STRONGBOX,
+ );
+
+ assert_eq!(key_parameter.get_tag(), Tag::ALGORITHM);
+
+ assert_eq!(
+ *key_parameter.key_parameter_value(),
+ KeyParameterValue::Algorithm(Algorithm::RSA)
+ );
+
+ assert_eq!(*key_parameter.security_level(), SecurityLevel::STRONGBOX);
+ }
+}
+
/// The storage_tests module first tests the 'new_from_sql' method for KeyParameters of different
/// data types and then tests 'to_sql' method for KeyParameters of those
/// different data types. The five different data types for KeyParameter values are:
@@ -877,3 +1202,126 @@
Ok(KeyParameter::new_from_sql(row.get(0)?, &SqlField(1, row), row.get(2)?)?)
}
}
+
+/// The wire_tests module tests the 'convert_to_wire' and 'convert_from_wire' methods for
+/// KeyParameter, for the five different types used in AidlKeyParameter, in addition to Invalid
+/// key parameter.
+/// i) bool
+/// ii) integer
+/// iii) longInteger
+/// iv) dateTime
+/// v) blob
+#[cfg(test)]
+mod wire_tests {
+ use crate::key_parameter::*;
+ /// unit tests for to conversions
+ #[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);
+ }
+ #[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!(true, actual.boolValue);
+ }
+ #[test]
+ fn test_convert_to_wire_integer() {
+ let kp = KeyParameter::new(
+ KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT),
+ SecurityLevel::STRONGBOX,
+ );
+ let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
+ assert_eq!(Tag::PURPOSE, actual.tag);
+ assert_eq!(KeyPurpose::ENCRYPT, actual.integer);
+ }
+ #[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!(i64::MAX, actual.longInteger);
+ }
+ #[test]
+ fn test_convert_to_wire_date_time() {
+ let kp = KeyParameter::new(
+ KeyParameterValue::ActiveDateTime(i64::MAX),
+ SecurityLevel::STRONGBOX,
+ );
+ let actual = KeyParameterValue::convert_to_wire(kp.key_parameter_value);
+ assert_eq!(Tag::ACTIVE_DATETIME, actual.tag);
+ assert_eq!(i64::MAX, actual.dateTime);
+ }
+ #[test]
+ fn test_convert_to_wire_blob() {
+ let kp = KeyParameter::new(
+ 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!(String::from("ConfirmationToken").into_bytes(), actual.blob);
+ }
+
+ /// unit tests for from conversion
+ #[test]
+ fn test_convert_from_wire_invalid() {
+ let aidl_kp = AidlKeyParameter { tag: Tag::INVALID, ..Default::default() };
+ let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+ assert_eq!(KeyParameterValue::Invalid, actual);
+ }
+ #[test]
+ fn test_convert_from_wire_bool() {
+ let aidl_kp =
+ AidlKeyParameter { tag: Tag::CALLER_NONCE, boolValue: true, ..Default::default() };
+ let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+ assert_eq!(KeyParameterValue::CallerNonce, actual);
+ }
+ #[test]
+ fn test_convert_from_wire_integer() {
+ let aidl_kp = AidlKeyParameter {
+ tag: Tag::PURPOSE,
+ integer: KeyPurpose::ENCRYPT,
+ ..Default::default()
+ };
+ let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+ assert_eq!(KeyParameterValue::KeyPurpose(KeyPurpose::ENCRYPT), actual);
+ }
+ #[test]
+ fn test_convert_from_wire_long_integer() {
+ let aidl_kp = AidlKeyParameter {
+ tag: Tag::USER_SECURE_ID,
+ longInteger: i64::MAX,
+ ..Default::default()
+ };
+ let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+ assert_eq!(KeyParameterValue::UserSecureID(i64::MAX), actual);
+ }
+ #[test]
+ fn test_convert_from_wire_date_time() {
+ let aidl_kp = AidlKeyParameter {
+ tag: Tag::ACTIVE_DATETIME,
+ dateTime: i64::MAX,
+ ..Default::default()
+ };
+ let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+ assert_eq!(KeyParameterValue::ActiveDateTime(i64::MAX), actual);
+ }
+ #[test]
+ fn test_convert_from_wire_blob() {
+ let aidl_kp = AidlKeyParameter {
+ tag: Tag::CONFIRMATION_TOKEN,
+ blob: String::from("ConfirmationToken").into_bytes(),
+ ..Default::default()
+ };
+ let actual = KeyParameterValue::convert_from_wire(aidl_kp);
+ assert_eq!(
+ KeyParameterValue::ConfirmationToken(String::from("ConfirmationToken").into_bytes()),
+ actual
+ );
+ }
+}