Change error.rs to use generated types.
This patch also removes AidlResult form the error module.
The new version of the Keystore 2.0 AIDL spec requires that ResponseCode
and ErrorCode will be returned as service specific error, instead of the
Result type.
Test: keystore2_test
Change-Id: I6f730b282c84abc8be2e693e5d2c7053648d7588
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index 7016d06..338f37e 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -18,9 +18,10 @@
srcs: ["src/lib.rs"],
rustlibs: [
+ "libandroid_hardware_keymint",
"libandroid_security_keystore2",
"libanyhow",
- "libandroid_hardware_keymint",
+ "libbinder_rs",
"libkeystore_aidl_generated",
"libkeystore2_selinux",
"liblazy_static",
@@ -40,9 +41,10 @@
auto_gen_config: true,
rustlibs: [
"libandroid_logger",
+ "libandroid_hardware_keymint",
"libandroid_security_keystore2",
"libanyhow",
- "libandroid_hardware_keymint",
+ "libbinder_rs",
"libkeystore_aidl_generated",
"libkeystore2_selinux",
"liblazy_static",
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index a285bda..f4da749 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -31,35 +31,16 @@
//! context should be added every time an error is forwarded.
use std::cmp::PartialEq;
-use std::convert::From;
-use keystore_aidl_generated as aidl;
-use keystore_aidl_generated::ResponseCode as AidlRc;
+pub use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode as Ec;
+pub use android_security_keystore2::aidl::android::security::keystore2::ResponseCode as Rc;
+
+use android_hardware_keymint::aidl::android::hardware::keymint::ErrorCode::ErrorCode;
+use android_security_keystore2::aidl::android::security::keystore2::ResponseCode::ResponseCode;
use keystore2_selinux as selinux;
-pub use aidl::ResponseCode;
-
-/// AidlResult wraps the `android.security.keystore2.Result` generated from AIDL
-#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
-pub struct AidlResult(aidl::Result);
-
-impl AidlResult {
- /// Creates an instance of AidlResult indicating no error has occurred.
- pub fn ok() -> Self {
- Self(aidl::Result { rc: AidlRc::Ok, km_error_code: 0 })
- }
-
- /// Creates an instance of AidlResult indicating the given ResponseCode.
- pub fn rc(rc: AidlRc) -> Self {
- Self(aidl::Result { rc, km_error_code: 0 })
- }
-
- /// Creates an instance of AidlResult indicating the given KM ErrorCode.
- pub fn ec(ec: aidl::ErrorCode) -> Self {
- Self(aidl::Result { rc: AidlRc::KeymintErrorCode, km_error_code: ec })
- }
-}
+use android_security_keystore2::binder::{Result as BinderResult, Status as BinderStatus};
/// This is the main Keystore error type. It wraps the Keystore `ResponseCode` generated
/// from AIDL in the `Rc` variant and Keymint `ErrorCode` in the Km variant.
@@ -67,35 +48,21 @@
pub enum Error {
/// Wraps a Keystore `ResponseCode` as defined by the Keystore AIDL interface specification.
#[error("Error::Rc({0:?})")]
- Rc(AidlRc),
+ Rc(ResponseCode),
/// Wraps a Keymint `ErrorCode` as defined by the Keymint AIDL interface specification.
#[error("Error::Km({0:?})")]
- Km(aidl::ErrorCode), // TODO Keymint ErrorCode is a generated AIDL type.
+ Km(ErrorCode),
}
impl Error {
/// Short hand for `Error::Rc(ResponseCode::SystemError)`
pub fn sys() -> Self {
- Error::Rc(AidlRc::SystemError)
+ Error::Rc(Rc::SystemError)
}
/// Short hand for `Error::Rc(ResponseCode::PermissionDenied`
pub fn perm() -> Self {
- Error::Rc(AidlRc::PermissionDenied)
- }
-}
-
-impl From<anyhow::Error> for AidlResult {
- fn from(error: anyhow::Error) -> Self {
- let root_cause = error.root_cause();
- match root_cause.downcast_ref::<Error>() {
- Some(Error::Rc(rcode)) => AidlResult::rc(*rcode),
- Some(Error::Km(ec)) => AidlResult::ec(*ec),
- None => match root_cause.downcast_ref::<selinux::Error>() {
- Some(selinux::Error::PermissionDenied) => AidlResult::rc(AidlRc::PermissionDenied),
- _ => AidlResult::rc(AidlRc::SystemError),
- },
- }
+ Error::Rc(Rc::PermissionDenied)
}
}
@@ -129,14 +96,23 @@
///
/// aidl_result_ = map_or_log_err(loadKey(), |r| { some_side_effect(); AidlResult::rc(r) });
/// ```
-pub fn map_or_log_err<T>(
- result: anyhow::Result<T>,
- handle_ok: impl FnOnce(T) -> AidlResult,
-) -> AidlResult {
+pub fn map_or_log_err<T, U, F>(result: anyhow::Result<U>, handle_ok: F) -> BinderResult<T>
+where
+ F: FnOnce(U) -> BinderResult<T>,
+{
result.map_or_else(
|e| {
log::error!("{:?}", e);
- e.into()
+ let root_cause = e.root_cause();
+ let rc = match root_cause.downcast_ref::<Error>() {
+ Some(Error::Rc(rcode)) => *rcode,
+ Some(Error::Km(ec)) => *ec,
+ None => match root_cause.downcast_ref::<selinux::Error>() {
+ Some(selinux::Error::PermissionDenied) => Rc::PermissionDenied,
+ _ => Rc::SystemError,
+ },
+ };
+ Err(BinderStatus::new_service_specific_error(rc, None))
},
handle_ok,
)
@@ -145,16 +121,14 @@
#[cfg(test)]
pub mod tests {
- use anyhow::{anyhow, Context, Result};
-
- use super::aidl::ErrorCode;
use super::*;
+ use anyhow::{anyhow, Context};
- fn nested_nested_rc(rc: AidlRc) -> anyhow::Result<()> {
+ fn nested_nested_rc(rc: ResponseCode) -> anyhow::Result<()> {
Err(anyhow!(Error::Rc(rc))).context("nested nested rc")
}
- fn nested_rc(rc: AidlRc) -> anyhow::Result<()> {
+ fn nested_rc(rc: ResponseCode) -> anyhow::Result<()> {
nested_nested_rc(rc).context("nested rc")
}
@@ -166,11 +140,11 @@
nested_nested_ec(ec).context("nested ec")
}
- fn nested_nested_ok(rc: AidlRc) -> anyhow::Result<AidlRc> {
+ fn nested_nested_ok(rc: ResponseCode) -> anyhow::Result<ResponseCode> {
Ok(rc)
}
- fn nested_ok(rc: AidlRc) -> anyhow::Result<AidlRc> {
+ fn nested_ok(rc: ResponseCode) -> anyhow::Result<ResponseCode> {
nested_nested_ok(rc).context("nested ok")
}
@@ -203,90 +177,52 @@
.with_tag("keystore_error_tests")
.with_min_level(log::Level::Debug),
);
- // All Error::Rc(x) get mapped on aidl::Result{x, 0}
+ // All Error::Rc(x) get mapped on a service specific error
+ // code of x.
+ for rc in Rc::Ok..Rc::BackendBusy {
+ assert_eq!(
+ Result::<(), i32>::Err(rc),
+ map_or_log_err(nested_rc(rc), |_| Err(BinderStatus::ok()))
+ .map_err(|s| s.service_specific_error())
+ );
+ }
+
+ // All KeystoreKerror::Km(x) get mapped on a service
+ // specific error of x.
+ for ec in Ec::UNKNOWN_ERROR..Ec::ROOT_OF_TRUST_ALREADY_SET {
+ assert_eq!(
+ Result::<(), i32>::Err(ec),
+ map_or_log_err(nested_ec(ec), |_| Err(BinderStatus::ok()))
+ .map_err(|s| s.service_specific_error())
+ );
+ }
+
+ // selinux::Error::Perm() needs to be mapped to Rc::PermissionDenied
assert_eq!(
- AidlResult::rc(AidlRc::Ok),
- map_or_log_err(nested_rc(AidlRc::Ok), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::Locked),
- map_or_log_err(nested_rc(AidlRc::Locked), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::Uninitialized),
- map_or_log_err(nested_rc(AidlRc::Uninitialized), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::SystemError),
- map_or_log_err(nested_rc(AidlRc::SystemError), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::PermissionDenied),
- map_or_log_err(nested_rc(AidlRc::PermissionDenied), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::KeyNotFound),
- map_or_log_err(nested_rc(AidlRc::KeyNotFound), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::ValueCorrupted),
- map_or_log_err(nested_rc(AidlRc::ValueCorrupted), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::WrongPassword),
- map_or_log_err(nested_rc(AidlRc::WrongPassword), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::OpAuthNeeded),
- map_or_log_err(nested_rc(AidlRc::OpAuthNeeded), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::KeyPermanentlyInvalidated),
- map_or_log_err(nested_rc(AidlRc::KeyPermanentlyInvalidated), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::NoSuchSecurityLevel),
- map_or_log_err(nested_rc(AidlRc::NoSuchSecurityLevel), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::KeymintErrorCode),
- map_or_log_err(nested_rc(AidlRc::KeymintErrorCode), |_| AidlResult::ec(0))
- );
- assert_eq!(
- AidlResult::rc(AidlRc::BackendBusy),
- map_or_log_err(nested_rc(AidlRc::BackendBusy), |_| AidlResult::ec(0))
+ Result::<(), i32>::Err(Rc::PermissionDenied),
+ map_or_log_err(nested_selinux_perm(), |_| Err(BinderStatus::ok()))
+ .map_err(|s| s.service_specific_error())
);
- // All KeystoreKerror::Km(x) get mapped on
- // aidl::Result{AidlRc::KeymintErrorCode, x}
+ // All other errors get mapped on System Error.
assert_eq!(
- AidlResult::ec(-7),
- map_or_log_err(nested_ec(-7), |_| AidlResult::rc(AidlRc::SystemError))
- );
-
- // All other get mapped on System Error.
- assert_eq!(
- AidlResult::rc(AidlRc::SystemError),
- map_or_log_err(nested_other_error(), |_| AidlResult::ec(0))
+ Result::<(), i32>::Err(Rc::SystemError),
+ map_or_log_err(nested_other_error(), |_| Err(BinderStatus::ok()))
+ .map_err(|s| s.service_specific_error())
);
// Result::Ok variants get passed to the ok handler.
- assert_eq!(
- AidlResult::rc(AidlRc::OpAuthNeeded),
- map_or_log_err(nested_ok(AidlRc::OpAuthNeeded), AidlResult::rc)
- );
- assert_eq!(AidlResult::ok(), map_or_log_err(nested_ok(AidlRc::Ok), AidlResult::rc));
+ assert_eq!(Ok(Rc::OpAuthNeeded), map_or_log_err(nested_ok(Rc::OpAuthNeeded), Ok));
+ assert_eq!(Ok(Rc::Ok), map_or_log_err(nested_ok(Rc::Ok), Ok));
- // selinux::Error::Perm() needs to be mapped to AidlRc::PermissionDenied
- assert_eq!(
- AidlResult::rc(AidlRc::PermissionDenied),
- map_or_log_err(nested_selinux_perm(), |_| AidlResult::ec(0))
- );
Ok(())
}
//Helper function to test whether error cases are handled as expected.
- pub fn check_result_contains_error_string<T>(result: Result<T>, expected_error_string: &str) {
+ pub fn check_result_contains_error_string<T>(
+ result: anyhow::Result<T>,
+ expected_error_string: &str,
+ ) {
let error_str = format!(
"{:#?}",
result.err().unwrap_or_else(|| panic!("Expected the error: {}", expected_error_string))
diff --git a/keystore2/src/key_parameter.rs b/keystore2/src/key_parameter.rs
index 1eb5d41..5266c28 100644
--- a/keystore2/src/key_parameter.rs
+++ b/keystore2/src/key_parameter.rs
@@ -17,7 +17,7 @@
//! and the methods to work with KeyParameter.
use crate::error::Error as KeystoreError;
-use crate::error::ResponseCode;
+use crate::error::Rc;
pub use android_hardware_keymint::aidl::android::hardware::keymint::{
Algorithm, Algorithm::Algorithm as AlgorithmType, BlockMode,
BlockMode::BlockMode as BlockModeType, Digest, Digest::Digest as DigestType, EcCurve,
@@ -354,14 +354,14 @@
Tag::PURPOSE => {
let key_purpose: KeyPurposeType = data
.get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to read sql data for tag: PURPOSE.")?;
KeyParameterValue::KeyPurpose(key_purpose)
}
Tag::ALGORITHM => {
let algorithm: AlgorithmType = data
.get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to read sql data for tag: ALGORITHM.")?;
KeyParameterValue::Algorithm(algorithm)
}
@@ -373,21 +373,21 @@
Tag::BLOCK_MODE => {
let block_mode: BlockModeType = data
.get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to read sql data for tag: BLOCK_MODE.")?;
KeyParameterValue::BlockMode(block_mode)
}
Tag::DIGEST => {
let digest: DigestType = data
.get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to read sql data for tag: DIGEST.")?;
KeyParameterValue::Digest(digest)
}
Tag::PADDING => {
let padding: PaddingModeType = data
.get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to read sql data for tag: PADDING.")?;
KeyParameterValue::PaddingMode(padding)
}
@@ -400,7 +400,7 @@
Tag::EC_CURVE => {
let ec_curve: EcCurveType = data
.get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to read sql data for tag: EC_CURVE.")?;
KeyParameterValue::EcCurve(ec_curve)
}
@@ -455,7 +455,7 @@
Tag::USER_AUTH_TYPE => {
let user_auth_type: HardwareAuthenticatorTypeType = data
.get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to read sql data for tag: USER_AUTH_TYPE.")?;
KeyParameterValue::HardwareAuthenticatorType(user_auth_type)
}
@@ -486,7 +486,7 @@
Tag::ORIGIN => {
let origin: KeyOriginType = data
.get()
- .map_err(|_| KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ .map_err(|_| KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to read sql data for tag: ORIGIN.")?;
KeyParameterValue::KeyOrigin(origin)
}
@@ -598,7 +598,7 @@
KeyParameterValue::ConfirmationToken(confirmation_token)
}
_ => {
- return Err(KeystoreError::Rc(ResponseCode::ValueCorrupted))
+ return Err(KeystoreError::Rc(Rc::ValueCorrupted))
.context("Failed to decode Tag enum from value.")?
}
};