Merge "Change error.rs to use generated types." am: 5061b81606
Original change: https://android-review.googlesource.com/c/platform/system/security/+/1398873
Change-Id: If8b97c7b5f1ca304fe629fc4d0bf3b663592e388
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.")?
}
};