blob: b419bc64f6cfbd86d896d0d3eb5e4928c26cc5bf [file] [log] [blame]
//! Code for dealing with HAL-defined types, especially conversions to/from internal types.
//!
//! The internal code for KeyMint uses its own type definitions, not the HAL-defined autogenerated
//! types, for two reasons:
//!
//! - The auto-generated types impose a dependency on Binder which is not appropriate for
//! code being built for a secure environment.
//! - The auto-generated types are not idiomatic Rust, and have reduced type safety.
//!
//! This module includes code to convert between HAL types (re-used under `kmr_hal::hal`) and
//! internal types (under `kmr_common::wire`), via the [`Fromm`] / [`TryFromm`], [`Innto`] and
//! [`TryInnto`] traits (which are deliberately misspelled to avoid a clash with standard
//! traits -- see below).
//!
//! - Going from wire=>HAL is an infallible conversion, as the wire types are stricter.
//! - Going from HAL=>wire is often a fallible conversion, as there may be "enum" values
//! that are not in range.
//!
//! This module (and `kmr_common::wire`) must be kept in sync with the Android KeyMint HAL
//! definition.
#![allow(non_snake_case)]
use crate::binder;
use keymint::{KeyParameterValue::KeyParameterValue, Tag::Tag, TagType::TagType};
use kmr_common::{
crypto::rsa, crypto::KeySizeInBits, wire, wire::keymint::DateTime, wire::keymint::KeyParam,
};
use log::{error, warn};
use std::convert::TryFrom;
use std::ffi::CString;
pub use android_hardware_security_keymint::aidl::android::hardware::security::keymint;
pub use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock;
pub use android_hardware_security_sharedsecret::aidl::android::hardware::security::sharedsecret;
#[cfg(test)]
mod tests;
/// Emit a failure for a failed type conversion.
#[inline]
pub fn failed_conversion(_err: wire::ValueNotRecognized) -> binder::Status {
binder::Status::new_service_specific_error(
keymint::ErrorCode::ErrorCode::INVALID_ARGUMENT.0,
Some(&CString::new("conversion from HAL type to internal type failed").unwrap()),
)
}
/// Determine the tag type for a tag, based on the top 4 bits of the tag number.
pub fn tag_type(tag: Tag) -> TagType {
match ((tag.0 as u32) & 0xf0000000u32) as i32 {
x if x == TagType::ENUM.0 => TagType::ENUM,
x if x == TagType::ENUM_REP.0 => TagType::ENUM_REP,
x if x == TagType::UINT.0 => TagType::UINT,
x if x == TagType::UINT_REP.0 => TagType::UINT_REP,
x if x == TagType::ULONG.0 => TagType::ULONG,
x if x == TagType::DATE.0 => TagType::DATE,
x if x == TagType::BOOL.0 => TagType::BOOL,
x if x == TagType::BIGNUM.0 => TagType::BIGNUM,
x if x == TagType::BYTES.0 => TagType::BYTES,
x if x == TagType::ULONG_REP.0 => TagType::ULONG_REP,
_ => TagType::INVALID,
}
}
// Neither the `kmr_common::wire` types nor the `hal` types are local to this crate, which means
// that Rust's orphan rule means we cannot implement the standard conversion traits. So instead
// define our own equivalent conversion traits that are local, and for which we're allowed to
// provide implementations. Give them an odd name to avoid confusion with the standard traits.
/// Local equivalent of `From` trait, with a different name to avoid clashes.
pub trait Fromm<T>: Sized {
fn fromm(val: T) -> Self;
}
/// Local equivalent of `TryFrom` trait, with a different name to avoid clashes.
pub trait TryFromm<T>: Sized {
type Error;
fn try_fromm(val: T) -> Result<Self, Self::Error>;
}
/// Local equivalent of `Into` trait, with a different name to avoid clashes.
pub trait Innto<T> {
fn innto(self) -> T;
}
/// Local equivalent of `TryInto` trait, with a different name to avoid clashes.
pub trait TryInnto<T> {
type Error;
fn try_innto(self) -> Result<T, Self::Error>;
}
/// Blanket implementation of `Innto` from `Fromm`
impl<T, U> Innto<U> for T
where
U: Fromm<T>,
{
fn innto(self) -> U {
U::fromm(self)
}
}
/// Blanket implementation of `TryInnto` from `TryFromm`
impl<T, U> TryInnto<U> for T
where
U: TryFromm<T>,
{
type Error = U::Error;
fn try_innto(self) -> Result<U, Self::Error> {
U::try_fromm(self)
}
}
/// Blanket implementation of `Fromm<Vec<T>>` from `Fromm<T>`
impl<T, U> Fromm<Vec<T>> for Vec<U>
where
U: Fromm<T>,
{
fn fromm(val: Vec<T>) -> Vec<U> {
val.into_iter().map(|t| <U>::fromm(t)).collect()
}
}
// Conversions from `kmr_common::wire` types into the equivalent types in the auto-generated HAL
// code. These conversions are infallible, because the range of the `wire` types is strictly
// contained within the HAL types.
impl Fromm<wire::sharedsecret::SharedSecretParameters>
for sharedsecret::SharedSecretParameters::SharedSecretParameters
{
fn fromm(val: wire::sharedsecret::SharedSecretParameters) -> Self {
Self { seed: val.seed, nonce: val.nonce }
}
}
impl Fromm<wire::secureclock::Timestamp> for secureclock::Timestamp::Timestamp {
fn fromm(val: wire::secureclock::Timestamp) -> Self {
Self { milliSeconds: val.milliseconds }
}
}
impl Fromm<wire::secureclock::TimeStampToken> for secureclock::TimeStampToken::TimeStampToken {
fn fromm(val: wire::secureclock::TimeStampToken) -> Self {
Self { challenge: val.challenge, timestamp: val.timestamp.innto(), mac: val.mac }
}
}
impl Fromm<wire::keymint::Certificate> for keymint::Certificate::Certificate {
fn fromm(val: wire::keymint::Certificate) -> Self {
Self { encodedCertificate: val.encoded_certificate }
}
}
impl Fromm<wire::keymint::DeviceInfo> for keymint::DeviceInfo::DeviceInfo {
fn fromm(val: wire::keymint::DeviceInfo) -> Self {
Self { deviceInfo: val.device_info }
}
}
impl Fromm<wire::keymint::HardwareAuthToken> for keymint::HardwareAuthToken::HardwareAuthToken {
fn fromm(val: wire::keymint::HardwareAuthToken) -> Self {
Self {
challenge: val.challenge,
userId: val.user_id,
authenticatorId: val.authenticator_id,
authenticatorType: val.authenticator_type.innto(),
timestamp: val.timestamp.innto(),
mac: val.mac,
}
}
}
impl Fromm<wire::keymint::KeyCharacteristics> for keymint::KeyCharacteristics::KeyCharacteristics {
fn fromm(val: wire::keymint::KeyCharacteristics) -> Self {
Self {
securityLevel: val.security_level.innto(),
authorizations: val.authorizations.innto(),
}
}
}
impl Fromm<wire::keymint::KeyCreationResult> for keymint::KeyCreationResult::KeyCreationResult {
fn fromm(val: wire::keymint::KeyCreationResult) -> Self {
Self {
keyBlob: val.key_blob,
keyCharacteristics: val.key_characteristics.innto(),
certificateChain: val.certificate_chain.innto(),
}
}
}
impl Fromm<wire::keymint::KeyMintHardwareInfo>
for keymint::KeyMintHardwareInfo::KeyMintHardwareInfo
{
fn fromm(val: wire::keymint::KeyMintHardwareInfo) -> Self {
Self {
versionNumber: val.version_number,
securityLevel: val.security_level.innto(),
keyMintName: val.key_mint_name,
keyMintAuthorName: val.key_mint_author_name,
timestampTokenRequired: val.timestamp_token_required,
}
}
}
impl Fromm<wire::keymint::MacedPublicKey> for keymint::MacedPublicKey::MacedPublicKey {
fn fromm(val: wire::keymint::MacedPublicKey) -> Self {
Self { macedKey: val.maced_key }
}
}
impl Fromm<wire::keymint::ProtectedData> for keymint::ProtectedData::ProtectedData {
fn fromm(val: wire::keymint::ProtectedData) -> Self {
Self { protectedData: val.protected_data }
}
}
impl Fromm<wire::keymint::RpcHardwareInfo> for keymint::RpcHardwareInfo::RpcHardwareInfo {
fn fromm(val: wire::keymint::RpcHardwareInfo) -> Self {
Self {
versionNumber: val.version_number,
rpcAuthorName: val.rpc_author_name,
supportedEekCurve: val.supported_eek_curve as i32,
uniqueId: val.unique_id,
}
}
}
impl Fromm<wire::keymint::KeyParam> for keymint::KeyParameter::KeyParameter {
fn fromm(val: wire::keymint::KeyParam) -> Self {
let (tag, value) = match val {
// Enum-holding variants.
KeyParam::Purpose(v) => (Tag::PURPOSE, KeyParameterValue::KeyPurpose(v.innto())),
KeyParam::Algorithm(v) => (Tag::ALGORITHM, KeyParameterValue::Algorithm(v.innto())),
KeyParam::BlockMode(v) => (Tag::BLOCK_MODE, KeyParameterValue::BlockMode(v.innto())),
KeyParam::Digest(v) => (Tag::DIGEST, KeyParameterValue::Digest(v.innto())),
KeyParam::Padding(v) => (Tag::PADDING, KeyParameterValue::PaddingMode(v.innto())),
KeyParam::EcCurve(v) => (Tag::EC_CURVE, KeyParameterValue::EcCurve(v.innto())),
KeyParam::RsaOaepMgfDigest(v) => {
(Tag::RSA_OAEP_MGF_DIGEST, KeyParameterValue::Digest(v.innto()))
}
KeyParam::Origin(v) => (Tag::ORIGIN, KeyParameterValue::Origin(v.innto())),
// `u32`-holding variants.
KeyParam::KeySize(v) => (Tag::KEY_SIZE, KeyParameterValue::Integer(v.0 as i32)),
KeyParam::MinMacLength(v) => {
(Tag::MIN_MAC_LENGTH, KeyParameterValue::Integer(v as i32))
}
KeyParam::MaxUsesPerBoot(v) => {
(Tag::MAX_USES_PER_BOOT, KeyParameterValue::Integer(v as i32))
}
KeyParam::UsageCountLimit(v) => {
(Tag::USAGE_COUNT_LIMIT, KeyParameterValue::Integer(v as i32))
}
KeyParam::UserId(v) => (Tag::USER_ID, KeyParameterValue::Integer(v as i32)),
KeyParam::UserAuthType(v) => {
(Tag::USER_AUTH_TYPE, KeyParameterValue::Integer(v as i32))
}
KeyParam::AuthTimeout(v) => (Tag::AUTH_TIMEOUT, KeyParameterValue::Integer(v as i32)),
KeyParam::OsVersion(v) => (Tag::OS_VERSION, KeyParameterValue::Integer(v as i32)),
KeyParam::OsPatchlevel(v) => (Tag::OS_PATCHLEVEL, KeyParameterValue::Integer(v as i32)),
KeyParam::VendorPatchlevel(v) => {
(Tag::VENDOR_PATCHLEVEL, KeyParameterValue::Integer(v as i32))
}
KeyParam::BootPatchlevel(v) => {
(Tag::BOOT_PATCHLEVEL, KeyParameterValue::Integer(v as i32))
}
KeyParam::MacLength(v) => (Tag::MAC_LENGTH, KeyParameterValue::Integer(v as i32)),
KeyParam::MaxBootLevel(v) => {
(Tag::MAX_BOOT_LEVEL, KeyParameterValue::Integer(v as i32))
}
// `u64`-holding variants.
KeyParam::RsaPublicExponent(v) => {
(Tag::RSA_PUBLIC_EXPONENT, KeyParameterValue::LongInteger(v.0 as i64))
}
KeyParam::UserSecureId(v) => {
(Tag::USER_SECURE_ID, KeyParameterValue::LongInteger(v as i64))
}
// `true`-holding variants.
KeyParam::CallerNonce => (Tag::CALLER_NONCE, KeyParameterValue::BoolValue(true)),
KeyParam::IncludeUniqueId => {
(Tag::INCLUDE_UNIQUE_ID, KeyParameterValue::BoolValue(true))
}
KeyParam::BootloaderOnly => (Tag::BOOTLOADER_ONLY, KeyParameterValue::BoolValue(true)),
KeyParam::RollbackResistance => {
(Tag::ROLLBACK_RESISTANCE, KeyParameterValue::BoolValue(true))
}
KeyParam::EarlyBootOnly => (Tag::EARLY_BOOT_ONLY, KeyParameterValue::BoolValue(true)),
KeyParam::AllowWhileOnBody => {
(Tag::ALLOW_WHILE_ON_BODY, KeyParameterValue::BoolValue(true))
}
KeyParam::NoAuthRequired => (Tag::NO_AUTH_REQUIRED, KeyParameterValue::BoolValue(true)),
KeyParam::TrustedUserPresenceRequired => {
(Tag::TRUSTED_USER_PRESENCE_REQUIRED, KeyParameterValue::BoolValue(true))
}
KeyParam::TrustedConfirmationRequired => {
(Tag::TRUSTED_CONFIRMATION_REQUIRED, KeyParameterValue::BoolValue(true))
}
KeyParam::UnlockedDeviceRequired => {
(Tag::UNLOCKED_DEVICE_REQUIRED, KeyParameterValue::BoolValue(true))
}
KeyParam::DeviceUniqueAttestation => {
(Tag::DEVICE_UNIQUE_ATTESTATION, KeyParameterValue::BoolValue(true))
}
KeyParam::StorageKey => (Tag::STORAGE_KEY, KeyParameterValue::BoolValue(true)),
KeyParam::ResetSinceIdRotation => {
(Tag::RESET_SINCE_ID_ROTATION, KeyParameterValue::BoolValue(true))
}
// `DateTime`-holding variants.
KeyParam::ActiveDatetime(v) => {
(Tag::ACTIVE_DATETIME, KeyParameterValue::DateTime(v.ms_since_epoch))
}
KeyParam::OriginationExpireDatetime(v) => {
(Tag::ORIGINATION_EXPIRE_DATETIME, KeyParameterValue::DateTime(v.ms_since_epoch))
}
KeyParam::UsageExpireDatetime(v) => {
(Tag::USAGE_EXPIRE_DATETIME, KeyParameterValue::DateTime(v.ms_since_epoch))
}
KeyParam::CreationDatetime(v) => {
(Tag::CREATION_DATETIME, KeyParameterValue::DateTime(v.ms_since_epoch))
}
KeyParam::CertificateNotBefore(v) => {
(Tag::CERTIFICATE_NOT_BEFORE, KeyParameterValue::DateTime(v.ms_since_epoch))
}
KeyParam::CertificateNotAfter(v) => {
(Tag::CERTIFICATE_NOT_AFTER, KeyParameterValue::DateTime(v.ms_since_epoch))
}
// `Vec<u8>`-holding variants.
KeyParam::ApplicationId(v) => (Tag::APPLICATION_ID, KeyParameterValue::Blob(v)),
KeyParam::ApplicationData(v) => (Tag::APPLICATION_DATA, KeyParameterValue::Blob(v)),
KeyParam::AttestationChallenge(v) => {
(Tag::ATTESTATION_CHALLENGE, KeyParameterValue::Blob(v))
}
KeyParam::AttestationApplicationId(v) => {
(Tag::ATTESTATION_APPLICATION_ID, KeyParameterValue::Blob(v))
}
KeyParam::AttestationIdBrand(v) => {
(Tag::ATTESTATION_ID_BRAND, KeyParameterValue::Blob(v))
}
KeyParam::AttestationIdDevice(v) => {
(Tag::ATTESTATION_ID_DEVICE, KeyParameterValue::Blob(v))
}
KeyParam::AttestationIdProduct(v) => {
(Tag::ATTESTATION_ID_PRODUCT, KeyParameterValue::Blob(v))
}
KeyParam::AttestationIdSerial(v) => {
(Tag::ATTESTATION_ID_SERIAL, KeyParameterValue::Blob(v))
}
KeyParam::AttestationIdImei(v) => {
(Tag::ATTESTATION_ID_IMEI, KeyParameterValue::Blob(v))
}
KeyParam::AttestationIdMeid(v) => {
(Tag::ATTESTATION_ID_MEID, KeyParameterValue::Blob(v))
}
KeyParam::AttestationIdManufacturer(v) => {
(Tag::ATTESTATION_ID_MANUFACTURER, KeyParameterValue::Blob(v))
}
KeyParam::AttestationIdModel(v) => {
(Tag::ATTESTATION_ID_MODEL, KeyParameterValue::Blob(v))
}
KeyParam::Nonce(v) => (Tag::NONCE, KeyParameterValue::Blob(v)),
KeyParam::RootOfTrust(v) => (Tag::ROOT_OF_TRUST, KeyParameterValue::Blob(v)),
KeyParam::CertificateSerial(v) => (Tag::CERTIFICATE_SERIAL, KeyParameterValue::Blob(v)),
KeyParam::CertificateSubject(v) => {
(Tag::CERTIFICATE_SUBJECT, KeyParameterValue::Blob(v))
}
};
Self { tag, value }
}
}
// Conversions from auto-generated HAL types into the equivalent types from `kmr_common::wire`.
// These conversions are generally fallible, because the "enum" types generated for the HAL are
// actually `i32` values, which may contain invalid values.
impl Fromm<secureclock::TimeStampToken::TimeStampToken> for wire::secureclock::TimeStampToken {
fn fromm(val: secureclock::TimeStampToken::TimeStampToken) -> Self {
Self { challenge: val.challenge, timestamp: val.timestamp.innto(), mac: val.mac }
}
}
impl Fromm<secureclock::Timestamp::Timestamp> for wire::secureclock::Timestamp {
fn fromm(val: secureclock::Timestamp::Timestamp) -> Self {
Self { milliseconds: val.milliSeconds }
}
}
impl Fromm<sharedsecret::SharedSecretParameters::SharedSecretParameters>
for wire::sharedsecret::SharedSecretParameters
{
fn fromm(val: sharedsecret::SharedSecretParameters::SharedSecretParameters) -> Self {
Self { seed: val.seed, nonce: val.nonce }
}
}
impl TryFromm<keymint::AttestationKey::AttestationKey> for wire::keymint::AttestationKey {
type Error = wire::ValueNotRecognized;
fn try_fromm(val: keymint::AttestationKey::AttestationKey) -> Result<Self, Self::Error> {
Ok(Self {
key_blob: val.keyBlob,
attest_key_params: val
.attestKeyParams // Vec<KeyParameter>
.into_iter() // Iter<KeyParameter>
.filter_map(|p| (&p).try_innto().transpose())
.collect::<Result<Vec<KeyParam>, _>>()?,
issuer_subject_name: val.issuerSubjectName,
})
}
}
impl TryFromm<keymint::HardwareAuthToken::HardwareAuthToken> for wire::keymint::HardwareAuthToken {
type Error = wire::ValueNotRecognized;
fn try_fromm(val: keymint::HardwareAuthToken::HardwareAuthToken) -> Result<Self, Self::Error> {
Ok(Self {
challenge: val.challenge,
user_id: val.userId,
authenticator_id: val.authenticatorId,
authenticator_type: val.authenticatorType.try_innto()?,
timestamp: val.timestamp.innto(),
mac: val.mac,
})
}
}
impl Fromm<keymint::MacedPublicKey::MacedPublicKey> for wire::keymint::MacedPublicKey {
fn fromm(val: keymint::MacedPublicKey::MacedPublicKey) -> Self {
Self { maced_key: val.macedKey }
}
}
impl Fromm<&keymint::MacedPublicKey::MacedPublicKey> for wire::keymint::MacedPublicKey {
fn fromm(val: &keymint::MacedPublicKey::MacedPublicKey) -> Self {
Self { maced_key: val.macedKey.to_vec() }
}
}
macro_rules! value_of {
{
$val:expr, $variant:ident
} => {
if let keymint::KeyParameterValue::KeyParameterValue::$variant(v) = $val.value {
Ok(v)
} else {
Err(wire::ValueNotRecognized)
}
}
}
macro_rules! check_bool {
{
$val:expr
} => {
if let keymint::KeyParameterValue::KeyParameterValue::BoolValue(true) = $val.value {
Ok(())
} else {
Err(wire::ValueNotRecognized)
}
}
}
macro_rules! clone_blob {
{
$val:expr
} => {
if let keymint::KeyParameterValue::KeyParameterValue::Blob(b) = &$val.value {
Ok(b.clone())
} else {
Err(wire::ValueNotRecognized)
}
}
}
/// Converting a HAL `KeyParameter` to a wire `KeyParam` may fail (producing an `Err`) but may also
/// silently drop unknown tags (producing `Ok(None)`)
impl TryFromm<&keymint::KeyParameter::KeyParameter> for Option<KeyParam> {
type Error = wire::ValueNotRecognized;
fn try_fromm(val: &keymint::KeyParameter::KeyParameter) -> Result<Self, Self::Error> {
Ok(match val.tag {
// Enum-holding variants.
keymint::Tag::Tag::PURPOSE => {
Some(KeyParam::Purpose(value_of!(val, KeyPurpose)?.try_innto()?))
}
keymint::Tag::Tag::ALGORITHM => {
Some(KeyParam::Algorithm(value_of!(val, Algorithm)?.try_innto()?))
}
keymint::Tag::Tag::BLOCK_MODE => {
Some(KeyParam::BlockMode(value_of!(val, BlockMode)?.try_innto()?))
}
keymint::Tag::Tag::DIGEST => {
Some(KeyParam::Digest(value_of!(val, Digest)?.try_innto()?))
}
keymint::Tag::Tag::PADDING => {
Some(KeyParam::Padding(value_of!(val, PaddingMode)?.try_innto()?))
}
keymint::Tag::Tag::EC_CURVE => {
Some(KeyParam::EcCurve(value_of!(val, EcCurve)?.try_innto()?))
}
keymint::Tag::Tag::RSA_OAEP_MGF_DIGEST => {
Some(KeyParam::RsaOaepMgfDigest(value_of!(val, Digest)?.try_innto()?))
}
keymint::Tag::Tag::ORIGIN => {
Some(KeyParam::Origin(value_of!(val, Origin)?.try_innto()?))
}
// `u32`-holding variants.
keymint::Tag::Tag::KEY_SIZE => {
Some(KeyParam::KeySize(KeySizeInBits(value_of!(val, Integer)? as u32)))
}
keymint::Tag::Tag::MIN_MAC_LENGTH => {
Some(KeyParam::MinMacLength(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::MAX_USES_PER_BOOT => {
Some(KeyParam::MaxUsesPerBoot(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::USAGE_COUNT_LIMIT => {
Some(KeyParam::UsageCountLimit(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::USER_ID => Some(KeyParam::UserId(value_of!(val, Integer)? as u32)),
keymint::Tag::Tag::USER_AUTH_TYPE => {
Some(KeyParam::UserAuthType(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::AUTH_TIMEOUT => {
Some(KeyParam::AuthTimeout(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::OS_VERSION => {
Some(KeyParam::OsVersion(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::OS_PATCHLEVEL => {
Some(KeyParam::OsPatchlevel(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::VENDOR_PATCHLEVEL => {
Some(KeyParam::VendorPatchlevel(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::BOOT_PATCHLEVEL => {
Some(KeyParam::BootPatchlevel(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::MAC_LENGTH => {
Some(KeyParam::MacLength(value_of!(val, Integer)? as u32))
}
keymint::Tag::Tag::MAX_BOOT_LEVEL => {
Some(KeyParam::MaxBootLevel(value_of!(val, Integer)? as u32))
}
// `u64`-holding variants.
keymint::Tag::Tag::RSA_PUBLIC_EXPONENT => Some(KeyParam::RsaPublicExponent(
rsa::Exponent(value_of!(val, LongInteger)? as u64),
)),
keymint::Tag::Tag::USER_SECURE_ID => {
Some(KeyParam::UserSecureId(value_of!(val, LongInteger)? as u64))
}
// `bool`-holding variants; only `true` is allowed.
keymint::Tag::Tag::CALLER_NONCE => {
check_bool!(val)?;
Some(KeyParam::CallerNonce)
}
keymint::Tag::Tag::INCLUDE_UNIQUE_ID => {
check_bool!(val)?;
Some(KeyParam::IncludeUniqueId)
}
keymint::Tag::Tag::BOOTLOADER_ONLY => {
check_bool!(val)?;
Some(KeyParam::BootloaderOnly)
}
keymint::Tag::Tag::ROLLBACK_RESISTANCE => {
check_bool!(val)?;
Some(KeyParam::RollbackResistance)
}
keymint::Tag::Tag::EARLY_BOOT_ONLY => {
check_bool!(val)?;
Some(KeyParam::EarlyBootOnly)
}
keymint::Tag::Tag::NO_AUTH_REQUIRED => {
check_bool!(val)?;
Some(KeyParam::NoAuthRequired)
}
keymint::Tag::Tag::ALLOW_WHILE_ON_BODY => {
check_bool!(val)?;
Some(KeyParam::AllowWhileOnBody)
}
keymint::Tag::Tag::TRUSTED_USER_PRESENCE_REQUIRED => {
check_bool!(val)?;
Some(KeyParam::TrustedUserPresenceRequired)
}
keymint::Tag::Tag::TRUSTED_CONFIRMATION_REQUIRED => {
check_bool!(val)?;
Some(KeyParam::TrustedConfirmationRequired)
}
keymint::Tag::Tag::UNLOCKED_DEVICE_REQUIRED => {
check_bool!(val)?;
Some(KeyParam::UnlockedDeviceRequired)
}
keymint::Tag::Tag::DEVICE_UNIQUE_ATTESTATION => {
check_bool!(val)?;
Some(KeyParam::DeviceUniqueAttestation)
}
keymint::Tag::Tag::STORAGE_KEY => {
check_bool!(val)?;
Some(KeyParam::StorageKey)
}
keymint::Tag::Tag::RESET_SINCE_ID_ROTATION => {
check_bool!(val)?;
Some(KeyParam::ResetSinceIdRotation)
}
// `DateTime`-holding variants.
keymint::Tag::Tag::ACTIVE_DATETIME => Some(KeyParam::ActiveDatetime(DateTime {
ms_since_epoch: value_of!(val, DateTime)?,
})),
keymint::Tag::Tag::ORIGINATION_EXPIRE_DATETIME => {
Some(KeyParam::OriginationExpireDatetime(DateTime {
ms_since_epoch: value_of!(val, DateTime)?,
}))
}
keymint::Tag::Tag::USAGE_EXPIRE_DATETIME => {
Some(KeyParam::UsageExpireDatetime(DateTime {
ms_since_epoch: value_of!(val, DateTime)?,
}))
}
keymint::Tag::Tag::CREATION_DATETIME => Some(KeyParam::CreationDatetime(DateTime {
ms_since_epoch: value_of!(val, DateTime)?,
})),
keymint::Tag::Tag::CERTIFICATE_NOT_BEFORE => {
Some(KeyParam::CertificateNotBefore(DateTime {
ms_since_epoch: value_of!(val, DateTime)?,
}))
}
keymint::Tag::Tag::CERTIFICATE_NOT_AFTER => {
Some(KeyParam::CertificateNotAfter(DateTime {
ms_since_epoch: value_of!(val, DateTime)?,
}))
}
// `Vec<u8>`-holding variants.
keymint::Tag::Tag::APPLICATION_ID => Some(KeyParam::ApplicationId(clone_blob!(val)?)),
keymint::Tag::Tag::APPLICATION_DATA => {
Some(KeyParam::ApplicationData(clone_blob!(val)?))
}
keymint::Tag::Tag::ROOT_OF_TRUST => Some(KeyParam::RootOfTrust(clone_blob!(val)?)),
keymint::Tag::Tag::ATTESTATION_CHALLENGE => {
Some(KeyParam::AttestationChallenge(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_APPLICATION_ID => {
Some(KeyParam::AttestationApplicationId(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_ID_BRAND => {
Some(KeyParam::AttestationIdBrand(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_ID_DEVICE => {
Some(KeyParam::AttestationIdDevice(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_ID_PRODUCT => {
Some(KeyParam::AttestationIdProduct(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_ID_SERIAL => {
Some(KeyParam::AttestationIdSerial(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_ID_IMEI => {
Some(KeyParam::AttestationIdImei(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_ID_MEID => {
Some(KeyParam::AttestationIdMeid(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_ID_MANUFACTURER => {
Some(KeyParam::AttestationIdManufacturer(clone_blob!(val)?))
}
keymint::Tag::Tag::ATTESTATION_ID_MODEL => {
Some(KeyParam::AttestationIdModel(clone_blob!(val)?))
}
keymint::Tag::Tag::NONCE => Some(KeyParam::Nonce(clone_blob!(val)?)),
keymint::Tag::Tag::CERTIFICATE_SERIAL => {
Some(KeyParam::CertificateSerial(clone_blob!(val)?))
}
keymint::Tag::Tag::CERTIFICATE_SUBJECT => {
Some(KeyParam::CertificateSubject(clone_blob!(val)?))
}
// Unsupported variants
keymint::Tag::Tag::UNIQUE_ID
| keymint::Tag::Tag::HARDWARE_TYPE
| keymint::Tag::Tag::MIN_SECONDS_BETWEEN_OPS
| keymint::Tag::Tag::IDENTITY_CREDENTIAL_KEY
| keymint::Tag::Tag::ASSOCIATED_DATA
| keymint::Tag::Tag::CONFIRMATION_TOKEN => {
error!("Unsupported tag {:?} encountered", val.tag);
return Err(wire::ValueNotRecognized);
}
_ => {
warn!("Unknown tag {:?} silently dropped", val.tag);
None
}
})
}
}
/// Macro that emits conversion implementations for `wire` and HAL enums.
/// - The `hal::keymint` version of the enum is a newtype holding `i32`
/// - The `wire::keymint` version of the enum is an exhaustive enum with `[repr(i32)]`
macro_rules! enum_convert {
{
$wenum:ty => $henum:ty
} => {
impl Fromm<$wenum> for $henum {
fn fromm(val: $wenum) -> Self {
Self(val as i32)
}
}
impl TryFromm<$henum> for $wenum {
type Error = wire::ValueNotRecognized;
fn try_fromm(val: $henum) -> Result<Self, Self::Error> {
Self::try_from(val.0)
}
}
};
}
enum_convert! { wire::keymint::ErrorCode => keymint::ErrorCode::ErrorCode }
enum_convert! { wire::keymint::Algorithm => keymint::Algorithm::Algorithm }
enum_convert! { wire::keymint::BlockMode => keymint::BlockMode::BlockMode }
enum_convert! { wire::keymint::Digest => keymint::Digest::Digest }
enum_convert! { wire::keymint::EcCurve => keymint::EcCurve::EcCurve }
enum_convert! { wire::keymint::HardwareAuthenticatorType =>
keymint::HardwareAuthenticatorType::HardwareAuthenticatorType }
enum_convert! { wire::keymint::KeyFormat => keymint::KeyFormat::KeyFormat }
enum_convert! { wire::keymint::KeyOrigin => keymint::KeyOrigin::KeyOrigin }
enum_convert! { wire::keymint::KeyPurpose => keymint::KeyPurpose::KeyPurpose }
enum_convert! { wire::keymint::PaddingMode => keymint::PaddingMode::PaddingMode }
enum_convert! { wire::keymint::SecurityLevel => keymint::SecurityLevel::SecurityLevel }
enum_convert! { wire::keymint::Tag => keymint::Tag::Tag }
enum_convert! { wire::keymint::TagType => keymint::TagType::TagType }