Merge changes I4a13082a,Iccaf0bff
* changes:
Keystore 2.0: add async_task::AsyncTask tests
Keystore 2.0: add async_task::Shelf tests
diff --git a/keystore2/Android.bp b/keystore2/Android.bp
index 812d5e6..aaa5659 100644
--- a/keystore2/Android.bp
+++ b/keystore2/Android.bp
@@ -42,6 +42,7 @@
"libkeystore2_crypto_rust",
"libkeystore2_km_compat",
"libkeystore2_selinux",
+ "libkeystore2_vintf_rust",
"liblazy_static",
"liblibc",
"liblibsqlite3_sys",
@@ -87,6 +88,7 @@
"libkeystore2_km_compat",
"libkeystore2_selinux",
"libkeystore2_test_utils",
+ "libkeystore2_vintf_rust",
"liblazy_static",
"liblibc",
"liblibsqlite3_sys",
diff --git a/keystore2/keystore2.rc b/keystore2/keystore2.rc
index c5fc72a..2d1f05a 100644
--- a/keystore2/keystore2.rc
+++ b/keystore2/keystore2.rc
@@ -8,13 +8,12 @@
# Start Keystore 2 conditionally
# TODO b/171563717 Remove when Keystore 2 migration is complete.
-on nonencrypted && property:persist.android.security.keystore2.enable=true
+on property:persist.android.security.keystore2.enable=true
enable keystore2
service keystore2 /system/bin/keystore2 /data/misc/keystore
- class main
+ class early_hal
user keystore
group keystore readproc log
writepid /dev/cpuset/foreground/tasks
- # TODO b/171563717 Remove when Keystore 2 migration is complete.
disabled
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 9668ee3..e1b41b5 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -35,6 +35,7 @@
use android_hardware_security_keymint::binder::{StatusCode, Strong};
use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
use anyhow::{Context, Result};
+use keystore2_vintf::get_aidl_instances;
use lazy_static::lazy_static;
use std::sync::{Arc, Mutex};
use std::{cell::RefCell, sync::Once};
@@ -175,38 +176,49 @@
/// If no native KeyMint device can be found this function also brings
/// up the compatibility service and attempts to connect to the legacy wrapper.
fn connect_keymint(security_level: &SecurityLevel) -> Result<(Asp, KeyMintHardwareInfo)> {
+ let keymint_instances =
+ get_aidl_instances("android.hardware.security.keymint", 1, "IKeyMintDevice");
+
let service_name = match *security_level {
- SecurityLevel::TRUSTED_ENVIRONMENT => format!("{}/default", KEYMINT_SERVICE_NAME),
- SecurityLevel::STRONGBOX => format!("{}/strongbox", KEYMINT_SERVICE_NAME),
+ SecurityLevel::TRUSTED_ENVIRONMENT => {
+ if keymint_instances.as_vec()?.iter().any(|instance| *instance == "default") {
+ Some(format!("{}/default", KEYMINT_SERVICE_NAME))
+ } else {
+ None
+ }
+ }
+ SecurityLevel::STRONGBOX => {
+ if keymint_instances.as_vec()?.iter().any(|instance| *instance == "strongbox") {
+ Some(format!("{}/strongbox", KEYMINT_SERVICE_NAME))
+ } else {
+ None
+ }
+ }
_ => {
return Err(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
.context("In connect_keymint.")
}
};
- let keymint = map_binder_status_code(binder::get_interface(&service_name))
- .context("In connect_keymint: Trying to connect to genuine KeyMint service.")
- .or_else(|e| {
- match e.root_cause().downcast_ref::<Error>() {
- Some(Error::BinderTransaction(StatusCode::NAME_NOT_FOUND)) => {
- // This is a no-op if it was called before.
- keystore2_km_compat::add_keymint_device_service();
+ let keymint = if let Some(service_name) = service_name {
+ map_binder_status_code(binder::get_interface(&service_name))
+ .context("In connect_keymint: Trying to connect to genuine KeyMint service.")
+ } else {
+ // This is a no-op if it was called before.
+ keystore2_km_compat::add_keymint_device_service();
- let keystore_compat_service: Strong<dyn IKeystoreCompatService> =
- map_binder_status_code(binder::get_interface("android.security.compat"))
- .context("In connect_keymint: Trying to connect to compat service.")?;
- map_binder_status(keystore_compat_service.getKeyMintDevice(*security_level))
- .map_err(|e| match e {
- Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
- Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
- }
- e => e,
- })
- .context("In connect_keymint: Trying to get Legacy wrapper.")
+ let keystore_compat_service: Strong<dyn IKeystoreCompatService> =
+ map_binder_status_code(binder::get_interface("android.security.compat"))
+ .context("In connect_keymint: Trying to connect to compat service.")?;
+ map_binder_status(keystore_compat_service.getKeyMintDevice(*security_level))
+ .map_err(|e| match e {
+ Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
+ Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
}
- _ => Err(e),
- }
- })?;
+ e => e,
+ })
+ .context("In connect_keymint: Trying to get Legacy wrapper.")
+ }?;
let hw_info = map_km_error(keymint.getHardwareInfo())
.context("In connect_keymint: Failed to get hardware info.")?;
@@ -250,33 +262,33 @@
/// If no native SecureClock device can be found brings up the compatibility service and attempts
/// to connect to the legacy wrapper.
fn connect_secureclock() -> Result<Asp> {
- let secureclock = map_binder_status_code(binder::get_interface(TIME_STAMP_SERVICE_NAME))
- .context("In connect_secureclock: Trying to connect to genuine secure clock service.")
- .or_else(|e| {
- match e.root_cause().downcast_ref::<Error>() {
- Some(Error::BinderTransaction(StatusCode::NAME_NOT_FOUND)) => {
- // This is a no-op if it was called before.
- keystore2_km_compat::add_keymint_device_service();
+ let secureclock_instances =
+ get_aidl_instances("android.hardware.security.secureclock", 1, "ISecureClock");
- let keystore_compat_service: Strong<dyn IKeystoreCompatService> =
- map_binder_status_code(binder::get_interface("android.security.compat"))
- .context(
- "In connect_secureclock: Trying to connect to compat service.",
- )?;
+ let secure_clock_available =
+ secureclock_instances.as_vec()?.iter().any(|instance| *instance == "default");
- // Legacy secure clock services were only implemented by TEE.
- map_binder_status(keystore_compat_service.getSecureClock())
- .map_err(|e| match e {
- Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
- Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
- }
- e => e,
- })
- .context("In connect_secureclock: Trying to get Legacy wrapper.")
+ let secureclock = if secure_clock_available {
+ map_binder_status_code(binder::get_interface(TIME_STAMP_SERVICE_NAME))
+ .context("In connect_secureclock: Trying to connect to genuine secure clock service.")
+ } else {
+ // This is a no-op if it was called before.
+ keystore2_km_compat::add_keymint_device_service();
+
+ let keystore_compat_service: Strong<dyn IKeystoreCompatService> =
+ map_binder_status_code(binder::get_interface("android.security.compat"))
+ .context("In connect_secureclock: Trying to connect to compat service.")?;
+
+ // Legacy secure clock services were only implemented by TEE.
+ map_binder_status(keystore_compat_service.getSecureClock())
+ .map_err(|e| match e {
+ Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
+ Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
}
- _ => Err(e),
- }
- })?;
+ e => e,
+ })
+ .context("In connect_secureclock: Trying to get Legacy wrapper.")
+ }?;
Ok(Asp::new(secureclock.as_binder()))
}
@@ -298,18 +310,28 @@
"android.hardware.security.keymint.IRemotelyProvisionedComponent";
fn connect_remotely_provisioned_component(security_level: &SecurityLevel) -> Result<Asp> {
+ let remotely_prov_instances =
+ get_aidl_instances("android.hardware.security.keymint", 1, "IRemotelyProvisionedComponent");
+
let service_name = match *security_level {
SecurityLevel::TRUSTED_ENVIRONMENT => {
- format!("{}/default", REMOTE_PROVISIONING_HAL_SERVICE_NAME)
+ if remotely_prov_instances.as_vec()?.iter().any(|instance| *instance == "default") {
+ Some(format!("{}/default", REMOTE_PROVISIONING_HAL_SERVICE_NAME))
+ } else {
+ None
+ }
}
- SecurityLevel::STRONGBOX => format!("{}/strongbox", REMOTE_PROVISIONING_HAL_SERVICE_NAME),
- _ => {
- // Given the integration of IRemotelyProvisionedComponent with KeyMint, it is reasonable
- // to return HARDWARE_TYPE_UNAVAILABLE as a Km error if it cannot be found.
- return Err(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
- .context("In connect_remotely_provisioned_component.");
+ SecurityLevel::STRONGBOX => {
+ if remotely_prov_instances.as_vec()?.iter().any(|instance| *instance == "strongbox") {
+ Some(format!("{}/strongbox", REMOTE_PROVISIONING_HAL_SERVICE_NAME))
+ } else {
+ None
+ }
}
- };
+ _ => None,
+ }
+ .ok_or(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
+ .context("In connect_remotely_provisioned_component.")?;
let rem_prov_hal: Strong<dyn IRemotelyProvisionedComponent> =
map_binder_status_code(binder::get_interface(&service_name))
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index b25cb0c..c506d8b 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -241,26 +241,31 @@
return static_cast<V4_0_KeyFormat>(kf);
}
-static V4_0_HardwareAuthToken convertAuthTokenToLegacy(const HardwareAuthToken& at) {
+static V4_0_HardwareAuthToken convertAuthTokenToLegacy(const std::optional<HardwareAuthToken>& at) {
+ if (!at) return {};
+
V4_0_HardwareAuthToken legacyAt;
- legacyAt.challenge = at.challenge;
- legacyAt.userId = at.userId;
- legacyAt.authenticatorId = at.authenticatorId;
+ legacyAt.challenge = at->challenge;
+ legacyAt.userId = at->userId;
+ legacyAt.authenticatorId = at->authenticatorId;
legacyAt.authenticatorType =
static_cast<::android::hardware::keymaster::V4_0::HardwareAuthenticatorType>(
- at.authenticatorType);
- legacyAt.timestamp = at.timestamp.milliSeconds;
- legacyAt.mac = at.mac;
+ at->authenticatorType);
+ legacyAt.timestamp = at->timestamp.milliSeconds;
+ legacyAt.mac = at->mac;
return legacyAt;
}
-static V4_0_VerificationToken convertTimestampTokenToLegacy(const TimeStampToken& tst) {
+static V4_0_VerificationToken
+convertTimestampTokenToLegacy(const std::optional<TimeStampToken>& tst) {
+ if (!tst) return {};
+
V4_0_VerificationToken legacyVt;
- legacyVt.challenge = tst.challenge;
- legacyVt.timestamp = tst.timestamp.milliSeconds;
+ legacyVt.challenge = tst->challenge;
+ legacyVt.timestamp = tst->timestamp.milliSeconds;
// Legacy verification tokens were always minted by TEE.
legacyVt.securityLevel = V4_0::SecurityLevel::TRUSTED_ENVIRONMENT;
- legacyVt.mac = tst.mac;
+ legacyVt.mac = tst->mac;
return legacyVt;
}
@@ -530,81 +535,85 @@
}
}
-ScopedAStatus KeyMintOperation::update(const std::optional<KeyParameterArray>& in_inParams,
- const std::optional<std::vector<uint8_t>>& in_input,
- const std::optional<HardwareAuthToken>& in_inAuthToken,
- const std::optional<TimeStampToken>& in_inTimeStampToken,
- std::optional<KeyParameterArray>* out_outParams,
- std::optional<ByteArray>* out_output,
- int32_t* _aidl_return) {
- std::vector<V4_0_KeyParameter> legacyParams;
- if (in_inParams.has_value()) {
- legacyParams = convertKeyParametersToLegacy(in_inParams.value().params);
- }
- auto input = in_input.value_or(std::vector<uint8_t>());
- V4_0_HardwareAuthToken authToken;
- if (in_inAuthToken.has_value()) {
- authToken = convertAuthTokenToLegacy(in_inAuthToken.value());
- }
- V4_0_VerificationToken verificationToken;
- if (in_inTimeStampToken.has_value()) {
- verificationToken = convertTimestampTokenToLegacy(in_inTimeStampToken.value());
- }
+ScopedAStatus KeyMintOperation::updateAad(const std::vector<uint8_t>& input,
+ const std::optional<HardwareAuthToken>& optAuthToken,
+ const std::optional<TimeStampToken>& optTimeStampToken) {
+ V4_0_HardwareAuthToken authToken = convertAuthTokenToLegacy(optAuthToken);
+ V4_0_VerificationToken verificationToken = convertTimestampTokenToLegacy(optTimeStampToken);
KMV1::ErrorCode errorCode;
auto result = mDevice->update(
- mOperationHandle, legacyParams, input, authToken, verificationToken,
- [&](V4_0_ErrorCode error, uint32_t inputConsumed,
- const hidl_vec<V4_0_KeyParameter>& outParams, const hidl_vec<uint8_t>& output) {
- errorCode = convert(error);
- out_outParams->emplace();
- out_outParams->value().params = convertKeyParametersFromLegacy(outParams);
- out_output->emplace();
- out_output->value().data = output;
- *_aidl_return = inputConsumed;
- });
+ mOperationHandle, {V4_0::makeKeyParameter(V4_0::TAG_ASSOCIATED_DATA, input)}, input,
+ authToken, verificationToken,
+ [&](V4_0_ErrorCode error, auto, auto, auto) { errorCode = convert(error); });
if (!result.isOk()) {
LOG(ERROR) << __func__ << " transaction failed. " << result.description();
errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
}
- if (errorCode != KMV1::ErrorCode::OK) {
- mOperationSlot.freeSlot();
- }
+ if (errorCode != KMV1::ErrorCode::OK) mOperationSlot.freeSlot();
+
return convertErrorCode(errorCode);
}
-ScopedAStatus KeyMintOperation::finish(const std::optional<KeyParameterArray>& in_inParams,
- const std::optional<std::vector<uint8_t>>& in_input,
- const std::optional<std::vector<uint8_t>>& in_inSignature,
- const std::optional<HardwareAuthToken>& in_authToken,
- const std::optional<TimeStampToken>& in_inTimeStampToken,
- std::optional<KeyParameterArray>* out_outParams,
- std::vector<uint8_t>* _aidl_return) {
- KMV1::ErrorCode errorCode;
- std::vector<V4_0_KeyParameter> legacyParams;
- if (in_inParams.has_value()) {
- legacyParams = convertKeyParametersToLegacy(in_inParams.value().params);
+ScopedAStatus KeyMintOperation::update(const std::vector<uint8_t>& input,
+ const std::optional<HardwareAuthToken>& optAuthToken,
+ const std::optional<TimeStampToken>& optTimeStampToken,
+ std::vector<uint8_t>* out_output) {
+ V4_0_HardwareAuthToken authToken = convertAuthTokenToLegacy(optAuthToken);
+ V4_0_VerificationToken verificationToken = convertTimestampTokenToLegacy(optTimeStampToken);
+
+ size_t inputPos = 0;
+ *out_output = {};
+ KMV1::ErrorCode errorCode = KMV1::ErrorCode::OK;
+
+ while (inputPos < input.size() && errorCode == KMV1::ErrorCode::OK) {
+ auto result =
+ mDevice->update(mOperationHandle, {} /* inParams */,
+ {input.begin() + inputPos, input.end()}, authToken, verificationToken,
+ [&](V4_0_ErrorCode error, uint32_t inputConsumed, auto /* outParams */,
+ const hidl_vec<uint8_t>& output) {
+ errorCode = convert(error);
+ out_output->insert(out_output->end(), output.begin(), output.end());
+ inputPos += inputConsumed;
+ });
+
+ if (!result.isOk()) {
+ LOG(ERROR) << __func__ << " transaction failed. " << result.description();
+ errorCode = KMV1::ErrorCode::UNKNOWN_ERROR;
+ }
}
+
+ if (errorCode != KMV1::ErrorCode::OK) mOperationSlot.freeSlot();
+
+ return convertErrorCode(errorCode);
+}
+
+ScopedAStatus
+KeyMintOperation::finish(const std::optional<std::vector<uint8_t>>& in_input,
+ const std::optional<std::vector<uint8_t>>& in_signature,
+ const std::optional<HardwareAuthToken>& in_authToken,
+ const std::optional<TimeStampToken>& in_timeStampToken,
+ const std::optional<std::vector<uint8_t>>& in_confirmationToken,
+ std::vector<uint8_t>* out_output) {
auto input = in_input.value_or(std::vector<uint8_t>());
- auto signature = in_inSignature.value_or(std::vector<uint8_t>());
- V4_0_HardwareAuthToken authToken;
- if (in_authToken.has_value()) {
- authToken = convertAuthTokenToLegacy(in_authToken.value());
+ auto signature = in_signature.value_or(std::vector<uint8_t>());
+ V4_0_HardwareAuthToken authToken = convertAuthTokenToLegacy(in_authToken);
+ V4_0_VerificationToken verificationToken = convertTimestampTokenToLegacy(in_timeStampToken);
+
+ std::vector<V4_0_KeyParameter> inParams;
+ if (in_confirmationToken) {
+ inParams.push_back(makeKeyParameter(V4_0::TAG_CONFIRMATION_TOKEN, *in_confirmationToken));
}
- V4_0_VerificationToken verificationToken;
- if (in_inTimeStampToken.has_value()) {
- verificationToken = convertTimestampTokenToLegacy(in_inTimeStampToken.value());
- }
+
+ KMV1::ErrorCode errorCode;
auto result = mDevice->finish(
- mOperationHandle, legacyParams, input, signature, authToken, verificationToken,
- [&](V4_0_ErrorCode error, const hidl_vec<V4_0_KeyParameter>& outParams,
- const hidl_vec<uint8_t>& output) {
+ mOperationHandle, {} /* inParams */, input, signature, authToken, verificationToken,
+ [&](V4_0_ErrorCode error, auto /* outParams */, const hidl_vec<uint8_t>& output) {
errorCode = convert(error);
- out_outParams->emplace();
- out_outParams->value().params = convertKeyParametersFromLegacy(outParams);
- *_aidl_return = output;
+ *out_output = output;
});
+
mOperationSlot.freeSlot();
if (!result.isOk()) {
LOG(ERROR) << __func__ << " transaction failed. " << result.description();
@@ -881,18 +890,14 @@
errorCode = toErrorCode(error);
return std::vector<uint8_t>();
}
- std::optional<KeyParameterArray> outParams;
- std::optional<ByteArray> outByte;
- int32_t status;
- error = beginResult.operation->update(std::nullopt, dataVec, std::nullopt, std::nullopt,
- &outParams, &outByte, &status);
- if (!error.isOk()) {
- errorCode = toErrorCode(error);
- return std::vector<uint8_t>();
- }
+
std::vector<uint8_t> result;
- error = beginResult.operation->finish(std::nullopt, std::nullopt, std::nullopt,
- std::nullopt, std::nullopt, &outParams, &result);
+ error = beginResult.operation->finish(dataVec, //
+ {} /* signature */, //
+ {} /* authToken */, //
+ {} /* timestampToken */, //
+ {} /* confirmationToken */, //
+ &result);
if (!error.isOk()) {
errorCode = toErrorCode(error);
return std::vector<uint8_t>();
diff --git a/keystore2/src/km_compat/km_compat.h b/keystore2/src/km_compat/km_compat.h
index 57a7bbd..bfd993a 100644
--- a/keystore2/src/km_compat/km_compat.h
+++ b/keystore2/src/km_compat/km_compat.h
@@ -30,7 +30,6 @@
using ::aidl::android::hardware::security::keymint::AttestationKey;
using ::aidl::android::hardware::security::keymint::BeginResult;
-using ::aidl::android::hardware::security::keymint::ByteArray;
using ::aidl::android::hardware::security::keymint::Certificate;
using ::aidl::android::hardware::security::keymint::HardwareAuthToken;
using ::aidl::android::hardware::security::keymint::KeyCharacteristics;
@@ -38,7 +37,6 @@
using ::aidl::android::hardware::security::keymint::KeyFormat;
using ::aidl::android::hardware::security::keymint::KeyMintHardwareInfo;
using ::aidl::android::hardware::security::keymint::KeyParameter;
-using ::aidl::android::hardware::security::keymint::KeyParameterArray;
using ::aidl::android::hardware::security::keymint::KeyPurpose;
using KeyMintSecurityLevel = ::aidl::android::hardware::security::keymint::SecurityLevel;
using V4_0_ErrorCode = ::android::hardware::keymaster::V4_0::ErrorCode;
@@ -142,19 +140,22 @@
: mDevice(device), mOperationHandle(operationHandle), mOperationSlot(slots, isActive) {}
~KeyMintOperation();
- ScopedAStatus update(const std::optional<KeyParameterArray>& in_inParams,
- const std::optional<std::vector<uint8_t>>& in_input,
- const std::optional<HardwareAuthToken>& in_inAuthToken,
- const std::optional<TimeStampToken>& in_inTimestampToken,
- std::optional<KeyParameterArray>* out_outParams,
- std::optional<ByteArray>* out_output, int32_t* _aidl_return);
- ScopedAStatus finish(const std::optional<KeyParameterArray>& in_inParams,
- const std::optional<std::vector<uint8_t>>& in_input,
- const std::optional<std::vector<uint8_t>>& in_inSignature,
- const std::optional<HardwareAuthToken>& in_authToken,
- const std::optional<TimeStampToken>& in_inTimestampToken,
- std::optional<KeyParameterArray>* out_outParams,
- std::vector<uint8_t>* _aidl_return);
+ ScopedAStatus updateAad(const std::vector<uint8_t>& input,
+ const std::optional<HardwareAuthToken>& authToken,
+ const std::optional<TimeStampToken>& timestampToken) override;
+
+ ScopedAStatus update(const std::vector<uint8_t>& input,
+ const std::optional<HardwareAuthToken>& authToken,
+ const std::optional<TimeStampToken>& timestampToken,
+ std::vector<uint8_t>* output) override;
+
+ ScopedAStatus finish(const std::optional<std::vector<uint8_t>>& input,
+ const std::optional<std::vector<uint8_t>>& signature,
+ const std::optional<HardwareAuthToken>& authToken,
+ const std::optional<TimeStampToken>& timeStampToken,
+ const std::optional<std::vector<uint8_t>>& confirmationToken,
+ std::vector<uint8_t>* output) override;
+
ScopedAStatus abort();
};
diff --git a/keystore2/src/km_compat/lib.rs b/keystore2/src/km_compat/lib.rs
index 22ddc31..6e27b5c 100644
--- a/keystore2/src/km_compat/lib.rs
+++ b/keystore2/src/km_compat/lib.rs
@@ -31,8 +31,8 @@
Algorithm::Algorithm, BeginResult::BeginResult, BlockMode::BlockMode, Digest::Digest,
ErrorCode::ErrorCode, HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::IKeyMintDevice,
KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat, KeyParameter::KeyParameter,
- KeyParameterArray::KeyParameterArray, KeyParameterValue::KeyParameterValue,
- KeyPurpose::KeyPurpose, PaddingMode::PaddingMode, SecurityLevel::SecurityLevel, Tag::Tag,
+ KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, PaddingMode::PaddingMode,
+ SecurityLevel::SecurityLevel, Tag::Tag,
};
use android_hardware_security_keymint::binder::{self, Strong};
use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
@@ -283,41 +283,53 @@
let begin_result = begin(legacy.as_ref(), &blob, KeyPurpose::ENCRYPT, None);
let operation = begin_result.operation.unwrap();
- let params = KeyParameterArray {
- params: vec![KeyParameter {
- tag: Tag::ASSOCIATED_DATA,
- value: KeyParameterValue::Blob(b"foobar".to_vec()),
- }],
- };
+
+ let update_aad_result = operation.updateAad(
+ &b"foobar".to_vec(),
+ None, /* authToken */
+ None, /* timestampToken */
+ );
+ assert!(update_aad_result.is_ok(), "{:?}", update_aad_result);
+
let message = [42; 128];
- let mut out_params = None;
- let result =
- operation.finish(Some(¶ms), Some(&message), None, None, None, &mut out_params);
+ let result = operation.finish(
+ Some(&message),
+ None, /* signature */
+ None, /* authToken */
+ None, /* timestampToken */
+ None, /* confirmationToken */
+ );
assert!(result.is_ok(), "{:?}", result);
let ciphertext = result.unwrap();
assert!(!ciphertext.is_empty());
- assert!(out_params.is_some());
let begin_result =
begin(legacy.as_ref(), &blob, KeyPurpose::DECRYPT, Some(begin_result.params));
+
let operation = begin_result.operation.unwrap();
- let mut out_params = None;
- let mut output = None;
+
+ let update_aad_result = operation.updateAad(
+ &b"foobar".to_vec(),
+ None, /* authToken */
+ None, /* timestampToken */
+ );
+ assert!(update_aad_result.is_ok(), "{:?}", update_aad_result);
+
let result = operation.update(
- Some(¶ms),
- Some(&ciphertext),
- None,
- None,
- &mut out_params,
- &mut output,
+ &ciphertext,
+ None, /* authToken */
+ None, /* timestampToken */
);
assert!(result.is_ok(), "{:?}", result);
- assert_eq!(result.unwrap(), message.len() as i32);
- assert!(output.is_some());
- assert_eq!(output.unwrap().data, message.to_vec());
- let result = operation.finish(Some(¶ms), None, None, None, None, &mut out_params);
+ assert_eq!(result.unwrap(), message);
+ let result = operation.finish(
+ None, /* input */
+ None, /* signature */
+ None, /* authToken */
+ None, /* timestampToken */
+ None, /* confirmationToken */
+ );
assert!(result.is_ok(), "{:?}", result);
- assert!(out_params.is_some());
}
#[test]
diff --git a/keystore2/src/km_compat/slot_test.cpp b/keystore2/src/km_compat/slot_test.cpp
index 37e7b36..43f3bc6 100644
--- a/keystore2/src/km_compat/slot_test.cpp
+++ b/keystore2/src/km_compat/slot_test.cpp
@@ -24,7 +24,6 @@
using ::aidl::android::hardware::security::keymint::Algorithm;
using ::aidl::android::hardware::security::keymint::BlockMode;
-using ::aidl::android::hardware::security::keymint::ByteArray;
using ::aidl::android::hardware::security::keymint::Certificate;
using ::aidl::android::hardware::security::keymint::Digest;
using ::aidl::android::hardware::security::keymint::ErrorCode;
@@ -100,18 +99,19 @@
// Calling finish should free up a slot.
auto last = operations.back();
operations.pop_back();
- std::optional<KeyParameterArray> kpa;
std::vector<uint8_t> byteVec;
- auto status = last->finish(std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt,
- &kpa, &byteVec);
+ auto status = last->finish(std::nullopt /* input */, std::nullopt /* signature */,
+ std::nullopt /* authToken */, std::nullopt /* timestampToken */,
+ std::nullopt /* confirmationToken */, &byteVec);
ASSERT_TRUE(status.isOk());
result = begin(device, true);
ASSERT_TRUE(std::holds_alternative<BeginResult>(result));
operations.push_back(std::get<BeginResult>(result).operation);
// Calling finish and abort on an already-finished operation should not free up another slot.
- status = last->finish(std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt,
- &kpa, &byteVec);
+ status = last->finish(std::nullopt /* input */, std::nullopt /* signature */,
+ std::nullopt /* authToken */, std::nullopt /* timestampToken */,
+ std::nullopt /* confirmationToken */, &byteVec);
ASSERT_TRUE(!status.isOk());
status = last->abort();
ASSERT_TRUE(!status.isOk());
@@ -130,8 +130,9 @@
operations.push_back(std::get<BeginResult>(result).operation);
// Calling finish and abort on an already-aborted operation should not free up another slot.
- status = last->finish(std::nullopt, std::nullopt, std::nullopt, std::nullopt, std::nullopt,
- &kpa, &byteVec);
+ status = last->finish(std::nullopt /* input */, std::nullopt /* signature */,
+ std::nullopt /* authToken */, std::nullopt /* timestampToken */,
+ std::nullopt /* confirmationToken */, &byteVec);
ASSERT_TRUE(!status.isOk());
status = last->abort();
ASSERT_TRUE(!status.isOk());
diff --git a/keystore2/src/operation.rs b/keystore2/src/operation.rs
index c98a76b..b6bb6ff 100644
--- a/keystore2/src/operation.rs
+++ b/keystore2/src/operation.rs
@@ -129,9 +129,7 @@
use crate::error::{map_km_error, map_or_log_err, Error, ErrorCode, ResponseCode};
use crate::utils::Asp;
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
- ByteArray::ByteArray, IKeyMintOperation::IKeyMintOperation,
- KeyParameter::KeyParameter as KmParam, KeyParameterArray::KeyParameterArray,
- KeyParameterValue::KeyParameterValue as KmParamValue, Tag::Tag,
+ IKeyMintOperation::IKeyMintOperation,
};
use android_system_keystore2::aidl::android::system::keystore2::{
IKeystoreOperation::BnKeystoreOperation, IKeystoreOperation::IKeystoreOperation,
@@ -325,16 +323,6 @@
Self::check_input_length(aad_input).context("In update_aad")?;
self.touch();
- let params = KeyParameterArray {
- params: vec![KmParam {
- tag: Tag::ASSOCIATED_DATA,
- value: KmParamValue::Blob(aad_input.into()),
- }],
- };
-
- let mut out_params: Option<KeyParameterArray> = None;
- let mut output: Option<ByteArray> = None;
-
let km_op: binder::public_api::Strong<dyn IKeyMintOperation> =
self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
@@ -347,14 +335,7 @@
self.update_outcome(
&mut *outcome,
- map_km_error(km_op.update(
- Some(¶ms),
- None,
- hat.as_ref(),
- tst.as_ref(),
- &mut out_params,
- &mut output,
- )),
+ map_km_error(km_op.updateAad(aad_input, hat.as_ref(), tst.as_ref())),
)
.context("In update_aad: KeyMint::update failed.")?;
@@ -368,8 +349,6 @@
Self::check_input_length(input).context("In update")?;
self.touch();
- let mut out_params: Option<KeyParameterArray> = None;
-
let km_op: binder::public_api::Strong<dyn IKeyMintOperation> =
self.km_op.get_interface().context("In update: Failed to get KeyMintOperation.")?;
@@ -380,39 +359,17 @@
.before_update()
.context("In update: Trying to get auth tokens.")?;
- let mut result: Option<Vec<u8>> = None;
- let mut consumed = 0usize;
- loop {
- let mut output: Option<ByteArray> = None;
- consumed += self
- .update_outcome(
- &mut *outcome,
- map_km_error(km_op.update(
- None,
- Some(&input[consumed..]),
- hat.as_ref(),
- tst.as_ref(),
- &mut out_params,
- &mut output,
- )),
- )
- .context("In update: KeyMint::update failed.")? as usize;
+ let output = self
+ .update_outcome(
+ &mut *outcome,
+ map_km_error(km_op.update(input, hat.as_ref(), tst.as_ref())),
+ )
+ .context("In update: KeyMint::update failed.")?;
- match (output, &mut result) {
- (Some(blob), None) => {
- if !blob.data.is_empty() {
- result = Some(blob.data)
- }
- }
- (Some(mut blob), Some(ref mut result)) => {
- result.append(&mut blob.data);
- }
- (None, _) => {}
- }
-
- if consumed == input.len() {
- return Ok(result);
- }
+ if output.is_empty() {
+ Ok(None)
+ } else {
+ Ok(Some(output))
}
}
@@ -425,8 +382,6 @@
}
self.touch();
- let mut out_params: Option<KeyParameterArray> = None;
-
let km_op: binder::public_api::Strong<dyn IKeyMintOperation> =
self.km_op.get_interface().context("In finish: Failed to get KeyMintOperation.")?;
@@ -437,23 +392,15 @@
.before_finish()
.context("In finish: Trying to get auth tokens.")?;
- let in_params = confirmation_token.map(|token| KeyParameterArray {
- params: vec![KmParam {
- tag: Tag::CONFIRMATION_TOKEN,
- value: KmParamValue::Blob(token),
- }],
- });
-
let output = self
.update_outcome(
&mut *outcome,
map_km_error(km_op.finish(
- in_params.as_ref(),
input,
signature,
hat.as_ref(),
tst.as_ref(),
- &mut out_params,
+ confirmation_token.as_deref(),
)),
)
.context("In finish: KeyMint::finish failed.")?;
diff --git a/keystore2/src/vintf/Android.bp b/keystore2/src/vintf/Android.bp
new file mode 100644
index 0000000..da7935a
--- /dev/null
+++ b/keystore2/src/vintf/Android.bp
@@ -0,0 +1,70 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+rust_library {
+ name: "libkeystore2_vintf_rust",
+ crate_name: "keystore2_vintf",
+ srcs: ["lib.rs"],
+ rustlibs: [
+ "libkeystore2_vintf_bindgen",
+ ],
+ shared_libs: [
+ "libkeystore2_vintf_cpp",
+ "libvintf",
+ ],
+}
+
+cc_library {
+ name: "libkeystore2_vintf_cpp",
+ srcs: [
+ "vintf.cpp",
+ ],
+ shared_libs: [
+ "libvintf",
+ ],
+}
+
+rust_bindgen {
+ name: "libkeystore2_vintf_bindgen",
+ wrapper_src: "vintf.hpp",
+ crate_name: "keystore2_vintf_bindgen",
+ source_stem: "bindings",
+ host_supported: true,
+ shared_libs: ["libvintf"],
+ bindgen_flags: [
+ "--size_t-is-usize",
+ "--whitelist-function", "getHalNames",
+ "--whitelist-function", "getHalNamesAndVersions",
+ "--whitelist-function", "getAidlInstances",
+ "--whitelist-function", "freeNames",
+ ],
+}
+
+rust_test {
+ name: "keystore2_vintf_test",
+ crate_name: "keystore2_vintf_test",
+ srcs: ["lib.rs"],
+ test_suites: ["general-tests"],
+ auto_gen_config: true,
+ rustlibs: [
+ "libkeystore2_vintf_bindgen",
+ ],
+ static_libs: [
+ "libkeystore2_vintf_cpp",
+ ],
+ shared_libs: [
+ "libc++",
+ "libvintf",
+ ],
+}
diff --git a/keystore2/src/vintf/lib.rs b/keystore2/src/vintf/lib.rs
new file mode 100644
index 0000000..c3d6d8a
--- /dev/null
+++ b/keystore2/src/vintf/lib.rs
@@ -0,0 +1,99 @@
+// Copyright 2021, The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+//! Bindings for getting the list of HALs.
+
+use keystore2_vintf_bindgen::{freeNames, getAidlInstances, getHalNames, getHalNamesAndVersions};
+use std::ffi::{CStr, CString};
+use std::os::raw::c_char;
+use std::str::Utf8Error;
+
+/// A struct that contains a list of HALs (optionally with version numbers).
+/// To use it, call as_vec to get a Vec view of the data it contains.
+pub struct HalNames {
+ data: *mut *mut c_char,
+ len: usize,
+}
+
+impl Drop for HalNames {
+ fn drop(&mut self) {
+ // Safety: The memory is allocated by our C shim so it must free it as well.
+ unsafe { freeNames(self.data, self.len) }
+ }
+}
+
+impl<'a> HalNames {
+ /// Get a Vec view of the list of HALs.
+ pub fn as_vec(&'a self) -> Result<Vec<&'a str>, Utf8Error> {
+ // Safety: self.data contains self.len C strings.
+ // The lifetimes ensure that the HalNames (and hence the strings) live
+ // at least as long as the returned vector.
+ unsafe { (0..self.len).map(|i| CStr::from_ptr(*self.data.add(i)).to_str()) }.collect()
+ }
+}
+
+/// Gets all HAL names.
+/// Note that this is not a zero-cost shim: it will make copies of the strings.
+pub fn get_hal_names() -> HalNames {
+ let mut len: usize = 0;
+ // Safety: We'll wrap this in HalNames to free the memory it allocates.
+ // It stores the size of the array it returns in len.
+ let raw_strs = unsafe { getHalNames(&mut len) };
+ HalNames { data: raw_strs, len }
+}
+
+/// Gets all HAL names and versions.
+/// Note that this is not a zero-cost shim: it will make copies of the strings.
+pub fn get_hal_names_and_versions() -> HalNames {
+ let mut len: usize = 0;
+ // Safety: We'll wrap this in HalNames to free the memory it allocates.
+ // It stores the size of the array it returns in len.
+ let raw_strs = unsafe { getHalNamesAndVersions(&mut len) };
+ HalNames { data: raw_strs, len }
+}
+
+/// Gets the instances of the given package, version, and interface tuple.
+/// Note that this is not a zero-cost shim: it will make copies of the strings.
+pub fn get_aidl_instances(package: &str, version: usize, interface_name: &str) -> HalNames {
+ let mut len: usize = 0;
+ let packages = CString::new(package).expect("Failed to make CString from package.");
+ let interface_name =
+ CString::new(interface_name).expect("Failed to make CString from interface_name.");
+ // Safety: We'll wrap this in HalNames to free the memory it allocates.
+ // It stores the size of the array it returns in len.
+ let raw_strs =
+ unsafe { getAidlInstances(&mut len, packages.as_ptr(), version, interface_name.as_ptr()) };
+ HalNames { data: raw_strs, len }
+}
+
+#[cfg(test)]
+mod tests {
+
+ use super::*;
+
+ #[test]
+ fn test() -> Result<(), Utf8Error> {
+ let result = get_hal_names();
+ let names = result.as_vec()?;
+ assert_ne!(names.len(), 0);
+
+ let result = get_hal_names_and_versions();
+ let names_and_versions = result.as_vec()?;
+ assert_ne!(names_and_versions.len(), 0);
+
+ assert!(names_and_versions.len() >= names.len());
+
+ Ok(())
+ }
+}
diff --git a/keystore2/src/vintf/vintf.cpp b/keystore2/src/vintf/vintf.cpp
new file mode 100644
index 0000000..dbdc046
--- /dev/null
+++ b/keystore2/src/vintf/vintf.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "vintf.hpp"
+
+#include <vintf/HalManifest.h>
+#include <vintf/VintfObject.h>
+
+// Converts a set<string> into a C-style array of C strings.
+static char** convert(const std::set<std::string>& names) {
+ char** ret = new char*[names.size()];
+ char** ptr = ret;
+ for (const auto& name : names) {
+ *(ptr++) = strdup(name.c_str());
+ }
+ return ret;
+}
+
+char** getHalNames(size_t* len) {
+ auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+ const auto names = manifest->getHalNames();
+ *len = names.size();
+ return convert(names);
+}
+
+char** getHalNamesAndVersions(size_t* len) {
+ auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+ const auto names = manifest->getHalNamesAndVersions();
+ *len = names.size();
+ return convert(names);
+}
+
+char** getAidlInstances(size_t* len, const char* package, size_t version,
+ const char* interfaceName) {
+ auto manifest = android::vintf::VintfObject::GetDeviceHalManifest();
+ const auto names = manifest->getAidlInstances(package, version, interfaceName);
+ *len = names.size();
+ return convert(names);
+}
+
+void freeNames(char** names, size_t len) {
+ for (int i = 0; i < len; i++) {
+ free(names[i]);
+ }
+ delete[] names;
+}
diff --git a/keystore2/src/vintf/vintf.hpp b/keystore2/src/vintf/vintf.hpp
new file mode 100644
index 0000000..75e80f6
--- /dev/null
+++ b/keystore2/src/vintf/vintf.hpp
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef __VINTF_H__
+#define __VINTF_H__
+
+#include <stddef.h>
+
+extern "C" {
+
+char** getHalNames(size_t* len);
+char** getHalNamesAndVersions(size_t* len);
+char** getAidlInstances(size_t* len, const char* package, size_t version,
+ const char* interfaceName);
+void freeNames(char** names, size_t len);
+}
+
+#endif // __VINTF_H__
diff --git a/ondevice-signing/Keymaster.cpp b/ondevice-signing/Keymaster.cpp
index 267dec8..6cfb565 100644
--- a/ondevice-signing/Keymaster.cpp
+++ b/ondevice-signing/Keymaster.cpp
@@ -66,6 +66,9 @@
}
}
+ if (devToUse == nullptr) {
+ LOG(WARNING) << "Didn't find a keymaster to use.";
+ }
mDevice = devToUse;
return mDevice != nullptr;
diff --git a/ondevice-signing/KeymasterSigningKey.cpp b/ondevice-signing/KeymasterSigningKey.cpp
index f35f92b..2b748e4 100644
--- a/ondevice-signing/KeymasterSigningKey.cpp
+++ b/ondevice-signing/KeymasterSigningKey.cpp
@@ -61,7 +61,11 @@
Result<void> KeymasterSigningKey::createSigningKey() {
KeymasterSigningKey signingKey;
- mKeymaster = Keymaster::getInstance();
+ auto keymaster = Keymaster::getInstance();
+ if (!keymaster.has_value()) {
+ return Error() << "Failed to initialize keymaster.";
+ }
+ mKeymaster = keymaster;
auto keyBlob = mKeymaster->createKey();
@@ -112,8 +116,12 @@
}
Result<void> KeymasterSigningKey::initializeFromKeyblob(const std::string& path) {
- mKeymaster = Keymaster::getInstance();
std::string keyBlobData;
+ auto keymaster = Keymaster::getInstance();
+ if (!keymaster.has_value()) {
+ return Error() << "Failed to initialize keymaster.";
+ }
+ mKeymaster = keymaster;
bool result = ReadFileToString(path, &keyBlobData);
if (!result) {