Merge "Include challenge in test_rkpd_attestation_key_upgrade" into main
diff --git a/diced/TEST_MAPPING b/diced/TEST_MAPPING
index 2f6be00..7628d25 100644
--- a/diced/TEST_MAPPING
+++ b/diced/TEST_MAPPING
@@ -15,5 +15,10 @@
{
"name": "libdiced_sample_inputs.integration_test"
}
+ ],
+ "postsubmit": [
+ {
+ "name": "libdiced_sample_inputs_nostd.integration_test"
+ }
]
}
diff --git a/diced/open_dice/Android.bp b/diced/open_dice/Android.bp
index b87be7f..745b86e 100644
--- a/diced/open_dice/Android.bp
+++ b/diced/open_dice/Android.bp
@@ -17,12 +17,16 @@
"libopen_dice_cbor_bindgen_nostd",
"libzeroize_nostd",
],
+ features: [
+ "alloc",
+ ],
whole_static_libs: [
"libopen_dice_cbor",
"libcrypto_baremetal",
],
visibility: [
"//packages/modules/Virtualization:__subpackages__",
+ "//system/security/diced/sample_inputs",
],
}
@@ -36,6 +40,7 @@
"libzeroize",
],
features: [
+ "alloc",
"std",
],
shared_libs: [
diff --git a/diced/open_dice/src/lib.rs b/diced/open_dice/src/lib.rs
index 6d082b8..83ae07f 100644
--- a/diced/open_dice/src/lib.rs
+++ b/diced/open_dice/src/lib.rs
@@ -17,6 +17,9 @@
#![cfg_attr(not(feature = "std"), no_std)]
+#[cfg(feature = "alloc")]
+extern crate alloc;
+
#[cfg(not(feature = "std"))]
extern crate core as std;
@@ -24,7 +27,7 @@
mod dice;
mod error;
mod ops;
-#[cfg(feature = "std")]
+#[cfg(feature = "alloc")]
mod retry;
pub use bcc::{
@@ -38,7 +41,7 @@
};
pub use error::{DiceError, Result};
pub use ops::{generate_certificate, hash, kdf, keypair_from_seed, sign, verify};
-#[cfg(feature = "std")]
+#[cfg(feature = "alloc")]
pub use retry::{
retry_bcc_format_config_descriptor, retry_bcc_main_flow, retry_dice_main_flow,
retry_generate_certificate, OwnedDiceArtifacts,
diff --git a/diced/open_dice/src/retry.rs b/diced/open_dice/src/retry.rs
index 84ca5f5..a6303bd 100644
--- a/diced/open_dice/src/retry.rs
+++ b/diced/open_dice/src/retry.rs
@@ -23,6 +23,8 @@
};
use crate::error::{DiceError, Result};
use crate::ops::generate_certificate;
+#[cfg(feature = "alloc")]
+use alloc::vec::Vec;
/// Artifacts stores a set of dice artifacts comprising CDI_ATTEST, CDI_SEAL,
/// and the BCC formatted attestation certificate chain.
diff --git a/diced/sample_inputs/Android.bp b/diced/sample_inputs/Android.bp
index cf6ef5f..e66d436 100644
--- a/diced/sample_inputs/Android.bp
+++ b/diced/sample_inputs/Android.bp
@@ -21,25 +21,61 @@
default_applicable_licenses: ["system_security_license"],
}
-rust_library {
- name: "libdiced_sample_inputs",
+rust_defaults {
+ name: "libdiced_sample_inputs_defaults",
crate_name: "diced_sample_inputs",
srcs: ["src/lib.rs"],
+}
+
+rust_library {
+ name: "libdiced_sample_inputs",
+ defaults: ["libdiced_sample_inputs_defaults"],
+ features: [
+ "std",
+ ],
rustlibs: [
- "libanyhow",
"libciborium",
"libcoset",
"libdiced_open_dice",
+ "liblog_rust",
],
}
+rust_library_rlib {
+ name: "libdiced_sample_inputs_nostd",
+ defaults: ["libdiced_sample_inputs_defaults"],
+ rustlibs: [
+ "libciborium_nostd",
+ "libcoset_nostd",
+ "libdiced_open_dice_nostd",
+ "liblog_rust_nostd",
+ ],
+ visibility: [
+ "//packages/modules/Virtualization:__subpackages__",
+ ],
+}
+
+rust_defaults {
+ name: "libdiced_sample_inputs_test_defaults",
+ crate_name: "diced_sample_inputs_test",
+ srcs: ["tests/*.rs"],
+ test_suites: ["general-tests"],
+}
+
rust_test {
name: "libdiced_sample_inputs.integration_test",
- crate_name: "diced_sample_inputs_test",
- srcs: ["tests/*.rs"],
- test_suites: ["general-tests"],
+ defaults: ["libdiced_sample_inputs_test_defaults"],
rustlibs: [
"libdiced_open_dice",
"libdiced_sample_inputs",
],
}
+
+rust_test {
+ name: "libdiced_sample_inputs_nostd.integration_test",
+ defaults: ["libdiced_sample_inputs_test_defaults"],
+ rustlibs: [
+ "libdiced_open_dice_nostd",
+ "libdiced_sample_inputs_nostd",
+ ],
+}
diff --git a/diced/sample_inputs/src/lib.rs b/diced/sample_inputs/src/lib.rs
index ebbfd29..9d6deca 100644
--- a/diced/sample_inputs/src/lib.rs
+++ b/diced/sample_inputs/src/lib.rs
@@ -17,6 +17,10 @@
//! Provides a set of sample inputs for a DICE chain and CDI values derived
//! from it.
+#![cfg_attr(not(feature = "std"), no_std)]
+
+extern crate alloc;
+
mod sample_inputs;
pub use sample_inputs::make_sample_bcc_and_cdis;
diff --git a/diced/sample_inputs/src/sample_inputs.rs b/diced/sample_inputs/src/sample_inputs.rs
index 6ad15cd..54f551b 100644
--- a/diced/sample_inputs/src/sample_inputs.rs
+++ b/diced/sample_inputs/src/sample_inputs.rs
@@ -15,15 +15,17 @@
//! This module provides a set of sample input values for a DICE chain, a sample UDS,
//! as well as tuple of CDIs and BCC derived thereof.
-use anyhow::{anyhow, Context, Result};
+use alloc::vec;
+use alloc::vec::Vec;
use ciborium::{de, ser, value::Value};
+use core::ffi::CStr;
use coset::{iana, Algorithm, AsCborValue, CoseKey, KeyOperation, KeyType, Label};
use diced_open_dice::{
derive_cdi_private_key_seed, keypair_from_seed, retry_bcc_format_config_descriptor,
- retry_bcc_main_flow, retry_dice_main_flow, Config, DiceArtifacts, DiceConfigValues, DiceMode,
- InputValues, OwnedDiceArtifacts, CDI_SIZE, HASH_SIZE, HIDDEN_SIZE,
+ retry_bcc_main_flow, retry_dice_main_flow, Config, DiceArtifacts, DiceConfigValues, DiceError,
+ DiceMode, InputValues, OwnedDiceArtifacts, Result, CDI_SIZE, HASH_SIZE, HIDDEN_SIZE,
};
-use std::ffi::CStr;
+use log::error;
/// Sample UDS used to perform the root dice flow by `make_sample_bcc_and_cdis`.
const UDS: &[u8; CDI_SIZE] = &[
@@ -88,8 +90,10 @@
],
..Default::default()
};
- key.to_cbor_value()
- .map_err(|e| anyhow!(format!("Failed to serialize the key to CBOR data. Error: {e}")))
+ key.to_cbor_value().map_err(|e| {
+ error!("Failed to serialize the key to CBOR data: {e}");
+ DiceError::InvalidInput
+ })
}
/// Makes a DICE chain (BCC) from the sample input.
@@ -97,12 +101,16 @@
/// The DICE chain is of the following format:
/// public key derived from UDS -> ABL certificate -> AVB certificate -> Android certificate
pub fn make_sample_bcc_and_cdis() -> Result<OwnedDiceArtifacts> {
- let private_key_seed = derive_cdi_private_key_seed(UDS)
- .context("In make_sample_bcc_and_cdis: Trying to derive private key seed.")?;
+ let private_key_seed = derive_cdi_private_key_seed(UDS).map_err(|e| {
+ error!("In make_sample_bcc_and_cdis: Trying to derive private key seed. Error: {e}");
+ e
+ })?;
// Gets the root public key in DICE chain (BCC).
- let (public_key, _) = keypair_from_seed(private_key_seed.as_array())
- .context("In make_sample_bcc_and_cids: Failed to generate key pair.")?;
+ let (public_key, _) = keypair_from_seed(private_key_seed.as_array()).map_err(|e| {
+ error!("In make_sample_bcc_and_cids: Failed to generate key pair. Error: {e}");
+ e
+ })?;
let ed25519_public_key_value = ed25519_public_key_to_cbor_value(&public_key)?;
// Gets the ABL certificate to as the root certificate of DICE chain.
@@ -120,14 +128,22 @@
DiceMode::kDiceModeNormal,
HIDDEN_ABL,
);
- let (cdi_values, cert) = retry_dice_main_flow(UDS, UDS, &input_values)
- .context("In make_sample_bcc_and_cdis: Trying to run first main flow.")?;
+ let (cdi_values, cert) = retry_dice_main_flow(UDS, UDS, &input_values).map_err(|e| {
+ error!("In make_sample_bcc_and_cdis: Trying to run first main flow. Error: {e}");
+ e
+ })?;
let bcc_value = Value::Array(vec![
ed25519_public_key_value,
- de::from_reader(&cert[..]).context("Deserialize root DICE certificate failed")?,
+ de::from_reader(&cert[..]).map_err(|e| {
+ error!("Deserialize root DICE certificate failed: {e}");
+ DiceError::InvalidInput
+ })?,
]);
let mut bcc: Vec<u8> = vec![];
- ser::into_writer(&bcc_value, &mut bcc)?;
+ ser::into_writer(&bcc_value, &mut bcc).map_err(|e| {
+ error!("Serialize BCC failed: {e}");
+ DiceError::InvalidInput
+ })?;
// Appends AVB certificate to DICE chain.
let config_values = DiceConfigValues {
@@ -146,7 +162,12 @@
);
let dice_artifacts =
retry_bcc_main_flow(&cdi_values.cdi_attest, &cdi_values.cdi_seal, &bcc, &input_values)
- .context("In make_sample_bcc_and_cdis: Trying to run first bcc main flow.")?;
+ .map_err(|e| {
+ error!(
+ "In make_sample_bcc_and_cdis: Trying to run first bcc main flow. Error: {e}"
+ );
+ e
+ })?;
// Appends Android certificate to DICE chain.
let config_values = DiceConfigValues {
@@ -166,8 +187,14 @@
retry_bcc_main_flow(
dice_artifacts.cdi_attest(),
dice_artifacts.cdi_seal(),
- dice_artifacts.bcc().ok_or_else(|| anyhow!("bcc is none"))?,
+ dice_artifacts.bcc().ok_or_else(|| {
+ error!("bcc is none");
+ DiceError::InvalidInput
+ })?,
&input_values,
)
- .context("In make_sample_bcc_and_cdis: Trying to run second bcc main flow.")
+ .map_err(|e| {
+ error!("In make_sample_bcc_and_cdis: Trying to run second bcc main flow. Error: {e}");
+ e
+ })
}
diff --git a/keystore2/src/error.rs b/keystore2/src/error.rs
index d6ae0ce..1a048b6 100644
--- a/keystore2/src/error.rs
+++ b/keystore2/src/error.rs
@@ -13,22 +13,19 @@
// limitations under the License.
//! Keystore error provides convenience methods and types for Keystore error handling.
-//! Clients of Keystore expect one of two error codes, i.e., a Keystore ResponseCode as
-//! defined by the Keystore AIDL interface, or a Keymint ErrorCode as defined by
-//! the Keymint HAL specification.
-//! This crate provides `Error` which can wrap both. It is to be used
-//! internally by Keystore to diagnose error conditions that need to be reported to
-//! the client. To report the error condition to the client the Keystore AIDL
-//! interface defines a wire type `Result` which is distinctly different from Rust's
-//! `enum Result<T,E>`.
//!
-//! This crate provides the convenience method `map_or_log_err` to convert `anyhow::Error`
-//! into this wire type. In addition to handling the conversion of `Error`
-//! to the `Result` wire type it handles any other error by mapping it to
-//! `ResponseCode::SYSTEM_ERROR` and logs any error condition.
+//! Here are some important types and helper functions:
//!
-//! Keystore functions should use `anyhow::Result` to return error conditions, and
-//! context should be added every time an error is forwarded.
+//! `Error` type encapsulate Keystore, Keymint, and Binder errors. It is used internally by
+//! Keystore to diagnose error conditions that need to be reported to the client.
+//!
+//! `SerializedError` is used send error codes on the wire.
+//!
+//! `map_or_log_err` is a convenience method used to convert `anyhow::Error` into `SerializedError`
+//! wire type.
+//!
+//! Keystore functions should use `anyhow::Result` to return error conditions, and context should
+//! be added every time an error is forwarded.
pub use android_hardware_security_keymint::aidl::android::hardware::security::keymint::ErrorCode::ErrorCode;
pub use android_system_keystore2::aidl::android::system::keystore2::ResponseCode::ResponseCode;
@@ -126,14 +123,6 @@
///
/// All error conditions get logged by this function, except for KEY_NOT_FOUND error.
///
-/// All `Error::Rc(x)` and `Error::Km(x)` variants get mapped onto a service specific error
-/// code of x. This is possible because KeyMint `ErrorCode` errors are always negative and
-/// `ResponseCode` codes are always positive.
-/// `selinux::Error::PermissionDenied` is mapped on `ResponseCode::PERMISSION_DENIED`.
-///
-/// All non `Error` error conditions and the Error::Binder variant get mapped onto
-/// ResponseCode::SYSTEM_ERROR`.
-///
/// `handle_ok` will be called if `result` is `Ok(value)` where `value` will be passed
/// as argument to `handle_ok`. `handle_ok` must generate a `BinderResult<T>`, but it
/// typically returns Ok(value).
@@ -200,9 +189,9 @@
result.map_or_else(
|e| {
let e = map_err(e);
- let rc = get_error_code(&e);
+ let rc = anyhow_error_to_serialized_error(&e);
Err(BinderStatus::new_service_specific_error(
- rc,
+ rc.0,
anyhow_error_to_cstring(&e).as_deref(),
))
},
@@ -210,21 +199,42 @@
)
}
-/// Returns the error code given a reference to the error
-pub fn get_error_code(e: &anyhow::Error) -> i32 {
+/// This type is used to send error codes on the wire.
+///
+/// Errors are squashed into one number space using following rules:
+/// - All Keystore and Keymint errors codes are identity mapped. It's possible because by
+/// convention Keystore `ResponseCode` errors are positive, and Keymint `ErrorCode` errors are
+/// negative.
+/// - `selinux::Error::PermissionDenied` is mapped to `ResponseCode::PERMISSION_DENIED`.
+/// - All other error conditions, e.g. Binder errors, are mapped to `ResponseCode::SYSTEM_ERROR`.
+///
+/// The type should be used to forward all error codes to clients of Keystore AIDL interface and to
+/// metrics events.
+#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
+pub struct SerializedError(pub i32);
+
+/// Returns a SerializedError given a reference to Error.
+pub fn error_to_serialized_error(e: &Error) -> SerializedError {
+ match e {
+ Error::Rc(rcode) => SerializedError(rcode.0),
+ Error::Km(ec) => SerializedError(ec.0),
+ // Binder errors are reported as system error.
+ Error::Binder(_, _) | Error::BinderTransaction(_) => {
+ SerializedError(ResponseCode::SYSTEM_ERROR.0)
+ }
+ }
+}
+
+/// Returns a SerializedError given a reference to anyhow::Error.
+pub fn anyhow_error_to_serialized_error(e: &anyhow::Error) -> SerializedError {
let root_cause = e.root_cause();
match root_cause.downcast_ref::<Error>() {
- Some(Error::Rc(rcode)) => rcode.0,
- Some(Error::Km(ec)) => ec.0,
- // If an Error::Binder reaches this stage we report a system error.
- // The exception code and possible service specific error will be
- // printed in the error log above.
- Some(Error::Binder(_, _)) | Some(Error::BinderTransaction(_)) => {
- ResponseCode::SYSTEM_ERROR.0
- }
+ Some(e) => error_to_serialized_error(e),
None => match root_cause.downcast_ref::<selinux::Error>() {
- Some(selinux::Error::PermissionDenied) => ResponseCode::PERMISSION_DENIED.0,
- _ => ResponseCode::SYSTEM_ERROR.0,
+ Some(selinux::Error::PermissionDenied) => {
+ SerializedError(ResponseCode::PERMISSION_DENIED.0)
+ }
+ _ => SerializedError(ResponseCode::SYSTEM_ERROR.0),
},
}
}
diff --git a/keystore2/src/metrics_store.rs b/keystore2/src/metrics_store.rs
index 5d311f0..6dca74a 100644
--- a/keystore2/src/metrics_store.rs
+++ b/keystore2/src/metrics_store.rs
@@ -17,7 +17,7 @@
//! stores them in an in-memory store.
//! 2. Returns the collected metrics when requested by the statsd proxy.
-use crate::error::get_error_code;
+use crate::error::anyhow_error_to_serialized_error;
use crate::globals::DB;
use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
use crate::ks_err;
@@ -202,7 +202,7 @@
};
if let Err(ref e) = result {
- key_creation_with_general_info.error_code = get_error_code(e);
+ key_creation_with_general_info.error_code = anyhow_error_to_serialized_error(e).0;
}
key_creation_with_auth_info.security_level = process_security_level(sec_level);
diff --git a/keystore2/src/operation.rs b/keystore2/src/operation.rs
index 2034a8a..eabc1ab 100644
--- a/keystore2/src/operation.rs
+++ b/keystore2/src/operation.rs
@@ -126,7 +126,10 @@
//! Either way, we have to revaluate the pruning scores.
use crate::enforcements::AuthInfo;
-use crate::error::{map_err_with, map_km_error, map_or_log_err, Error, ErrorCode, ResponseCode};
+use crate::error::{
+ error_to_serialized_error, map_err_with, map_km_error, map_or_log_err, Error, ErrorCode,
+ ResponseCode, SerializedError,
+};
use crate::ks_err;
use crate::metrics_store::log_key_operation_event_stats;
use crate::utils::watchdog as wd;
@@ -162,7 +165,7 @@
/// Operation is pruned.
Pruned,
/// Operation is failed with the error code.
- ErrorCode(ErrorCode),
+ ErrorCode(SerializedError),
}
/// Operation bundles all of the operation related resources and tracks the operation's
@@ -305,8 +308,7 @@
err: Result<T, Error>,
) -> Result<T, Error> {
match &err {
- Err(Error::Km(e)) => *locked_outcome = Outcome::ErrorCode(*e),
- Err(_) => *locked_outcome = Outcome::ErrorCode(ErrorCode::UNKNOWN_ERROR),
+ Err(e) => *locked_outcome = Outcome::ErrorCode(error_to_serialized_error(e)),
Ok(_) => (),
}
err