Merge "Allow CompOS to use DICE from C++"
diff --git a/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl b/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
index 50bfa19..8e347f0 100644
--- a/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
+++ b/keystore2/aidl/android/security/compat/IKeystoreCompatService.aidl
@@ -29,8 +29,17 @@
*/
interface IKeystoreCompatService {
/**
- * Return an implementation of IKeyMintDevice, that it implemented by Keystore 2.0 itself
- * by means of Keymaster 4.1 or lower.
+ * Return an implementation of IKeyMintDevice, that it implemented by Keystore 2.0 itself.
+ * The underlying implementation depends on the requested securityLevel:
+ * - TRUSTED_ENVIRONMENT or STRONGBOX: implementation is by means of a hardware-backed
+ * Keymaster 4.x instance. In this case, the returned device supports version 1 of
+ * the IKeyMintDevice interface, with some small omissions:
+ * - KeyPurpose::ATTEST_KEY is not supported (b/216437537)
+ * - Specification of the MGF1 digest for RSA-OAEP is not supported (b/216436980)
+ * - Specification of CERTIFICATE_{SUBJECT,SERIAL} is not supported for keys attested
+ * by hardware (b/216468666).
+ * - SOFTWARE: implementation is entirely software based. In this case, the returned device
+ * supports the current version of the IKeyMintDevice interface.
*/
IKeyMintDevice getKeyMintDevice (SecurityLevel securityLevel);
diff --git a/keystore2/src/authorization.rs b/keystore2/src/authorization.rs
index 81790af..8265dd0 100644
--- a/keystore2/src/authorization.rs
+++ b/keystore2/src/authorization.rs
@@ -16,7 +16,7 @@
use crate::error::Error as KeystoreError;
use crate::error::anyhow_error_to_cstring;
-use crate::globals::{ENFORCEMENTS, SUPER_KEY, DB, LEGACY_MIGRATOR};
+use crate::globals::{ENFORCEMENTS, SUPER_KEY, DB, LEGACY_IMPORTER};
use crate::permission::KeystorePerm;
use crate::super_key::UserState;
use crate::utils::{check_keystore_permission, watchdog as wd};
@@ -170,7 +170,7 @@
.with(|db| {
skm.unlock_and_get_user_state(
&mut db.borrow_mut(),
- &LEGACY_MIGRATOR,
+ &LEGACY_IMPORTER,
user_id as u32,
&password,
)
diff --git a/keystore2/src/crypto/Android.bp b/keystore2/src/crypto/Android.bp
index 76c02c5..c3f6f3c 100644
--- a/keystore2/src/crypto/Android.bp
+++ b/keystore2/src/crypto/Android.bp
@@ -62,6 +62,7 @@
shared_libs: ["libcrypto"],
bindgen_flags: [
"--size_t-is-usize",
+ "--allowlist-function", "hmacSha256",
"--allowlist-function", "randomBytes",
"--allowlist-function", "AES_gcm_encrypt",
"--allowlist-function", "AES_gcm_decrypt",
diff --git a/keystore2/src/crypto/crypto.cpp b/keystore2/src/crypto/crypto.cpp
index 5d360a1..34a9a40 100644
--- a/keystore2/src/crypto/crypto.cpp
+++ b/keystore2/src/crypto/crypto.cpp
@@ -25,6 +25,7 @@
#include <openssl/ecdh.h>
#include <openssl/evp.h>
#include <openssl/hkdf.h>
+#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/x509.h>
@@ -66,6 +67,14 @@
return cipher;
}
+bool hmacSha256(const uint8_t* key, size_t key_size, const uint8_t* msg, size_t msg_size,
+ uint8_t* out, size_t out_size) {
+ const EVP_MD* digest = EVP_sha256();
+ unsigned int actual_out_size = out_size;
+ uint8_t* p = HMAC(digest, key, key_size, msg, msg_size, out, &actual_out_size);
+ return (p != nullptr);
+}
+
bool randomBytes(uint8_t* out, size_t len) {
return RAND_bytes(out, len);
}
diff --git a/keystore2/src/crypto/crypto.hpp b/keystore2/src/crypto/crypto.hpp
index f841eb3..d66532f 100644
--- a/keystore2/src/crypto/crypto.hpp
+++ b/keystore2/src/crypto/crypto.hpp
@@ -22,6 +22,8 @@
#include <stddef.h>
extern "C" {
+ bool hmacSha256(const uint8_t* key, size_t key_size, const uint8_t* msg, size_t msg_size,
+ uint8_t* out, size_t out_size);
bool randomBytes(uint8_t* out, size_t len);
bool AES_gcm_encrypt(const uint8_t* in, uint8_t* out, size_t len,
const uint8_t* key, size_t key_size, const uint8_t* iv, uint8_t* tag);
diff --git a/keystore2/src/crypto/error.rs b/keystore2/src/crypto/error.rs
index c6476f9..48a2d4c 100644
--- a/keystore2/src/crypto/error.rs
+++ b/keystore2/src/crypto/error.rs
@@ -95,6 +95,10 @@
#[error("Failed to extract certificate subject.")]
ExtractSubjectFailed,
+ /// This is returned if the C implementation of hmacSha256 failed.
+ #[error("Failed to calculate HMAC-SHA256.")]
+ HmacSha256Failed,
+
/// Zvec error.
#[error(transparent)]
ZVec(#[from] zvec::Error),
diff --git a/keystore2/src/crypto/lib.rs b/keystore2/src/crypto/lib.rs
index 92da965..14bdf04 100644
--- a/keystore2/src/crypto/lib.rs
+++ b/keystore2/src/crypto/lib.rs
@@ -19,8 +19,8 @@
pub mod zvec;
pub use error::Error;
use keystore2_crypto_bindgen::{
- extractSubjectFromCertificate, generateKeyFromPassword, randomBytes, AES_gcm_decrypt,
- AES_gcm_encrypt, ECDHComputeKey, ECKEYGenerateKey, ECKEYMarshalPrivateKey,
+ extractSubjectFromCertificate, generateKeyFromPassword, hmacSha256, randomBytes,
+ AES_gcm_decrypt, AES_gcm_encrypt, ECDHComputeKey, ECKEYGenerateKey, ECKEYMarshalPrivateKey,
ECKEYParsePrivateKey, ECPOINTOct2Point, ECPOINTPoint2Oct, EC_KEY_free, EC_KEY_get0_public_key,
EC_POINT_free, HKDFExpand, HKDFExtract, EC_KEY, EC_MAX_BYTES, EC_POINT, EVP_MAX_MD_SIZE,
};
@@ -39,6 +39,8 @@
pub const AES_128_KEY_LENGTH: usize = 16;
/// Length of the expected salt for key from password generation.
pub const SALT_LENGTH: usize = 16;
+/// Length of an HMAC-SHA256 tag in bytes.
+pub const HMAC_SHA256_LEN: usize = 32;
/// Older versions of keystore produced IVs with four extra
/// ignored zero bytes at the end; recognise and trim those.
@@ -72,6 +74,21 @@
}
}
+/// Perform HMAC-SHA256.
+pub fn hmac_sha256(key: &[u8], msg: &[u8]) -> Result<Vec<u8>, Error> {
+ let mut tag = vec![0; HMAC_SHA256_LEN];
+ // Safety: The first two pairs of arguments must point to const buffers with
+ // size given by the second arg of the pair. The final pair of arguments
+ // must point to an output buffer with size given by the second arg of the
+ // pair.
+ match unsafe {
+ hmacSha256(key.as_ptr(), key.len(), msg.as_ptr(), msg.len(), tag.as_mut_ptr(), tag.len())
+ } {
+ true => Ok(tag),
+ false => Err(Error::HmacSha256Failed),
+ }
+}
+
/// Uses AES GCM to decipher a message given an initialization vector, aead tag, and key.
/// This function accepts 128 and 256-bit keys and uses AES128 and AES256 respectively based
/// on the key length.
@@ -565,4 +582,18 @@
assert_eq!(left_key, right_key);
Ok(())
}
+
+ #[test]
+ fn test_hmac_sha256() {
+ let key = b"This is the key";
+ let msg1 = b"This is a message";
+ let msg2 = b"This is another message";
+ let tag1a = hmac_sha256(key, msg1).unwrap();
+ assert_eq!(tag1a.len(), HMAC_SHA256_LEN);
+ let tag1b = hmac_sha256(key, msg1).unwrap();
+ assert_eq!(tag1a, tag1b);
+ let tag2 = hmac_sha256(key, msg2).unwrap();
+ assert_eq!(tag2.len(), HMAC_SHA256_LEN);
+ assert_ne!(tag1a, tag2);
+ }
}
diff --git a/keystore2/src/enforcements.rs b/keystore2/src/enforcements.rs
index ade4751..cb6a266 100644
--- a/keystore2/src/enforcements.rs
+++ b/keystore2/src/enforcements.rs
@@ -450,7 +450,7 @@
KeyParameterValue::Algorithm(Algorithm::RSA)
| KeyParameterValue::Algorithm(Algorithm::EC) => {
return Err(Error::Km(Ec::UNSUPPORTED_PURPOSE)).context(
- "In authorize_create: public operations on asymmetric keys are not
+ "In authorize_create: public operations on asymmetric keys are not \
supported.",
);
}
@@ -566,8 +566,7 @@
// if both NO_AUTH_REQUIRED and USER_SECURE_ID tags are present, return error
if !user_secure_ids.is_empty() && no_auth_required {
return Err(Error::Km(Ec::INVALID_KEY_BLOB)).context(
- "In authorize_create: key has both NO_AUTH_REQUIRED
- and USER_SECURE_ID tags.",
+ "In authorize_create: key has both NO_AUTH_REQUIRED and USER_SECURE_ID tags.",
);
}
@@ -576,8 +575,8 @@
|| (user_auth_type.is_none() && !user_secure_ids.is_empty())
{
return Err(Error::Km(Ec::KEY_USER_NOT_AUTHENTICATED)).context(
- "In authorize_create: Auth required, but either auth type or secure ids
- are not present.",
+ "In authorize_create: Auth required, but either auth type or secure ids \
+ are not present.",
);
}
@@ -587,8 +586,7 @@
&& op_params.iter().any(|kp| kp.tag == Tag::NONCE)
{
return Err(Error::Km(Ec::CALLER_NONCE_PROHIBITED)).context(
- "In authorize_create, NONCE is present,
- although CALLER_NONCE is not present",
+ "In authorize_create, NONCE is present, although CALLER_NONCE is not present",
);
}
diff --git a/keystore2/src/globals.rs b/keystore2/src/globals.rs
index 2819314..14b3601 100644
--- a/keystore2/src/globals.rs
+++ b/keystore2/src/globals.rs
@@ -18,7 +18,7 @@
use crate::gc::Gc;
use crate::legacy_blob::LegacyBlobLoader;
-use crate::legacy_migrator::LegacyMigrator;
+use crate::legacy_importer::LegacyImporter;
use crate::super_key::SuperKeyManager;
use crate::utils::watchdog as wd;
use crate::{async_task::AsyncTask, database::MonotonicRawTime};
@@ -27,6 +27,7 @@
database::Uuid,
error::{map_binder_status, map_binder_status_code, Error, ErrorCode},
};
+use crate::km_compat::{KeyMintV1, BacklevelKeyMintWrapper};
use crate::{enforcements::Enforcements, error::map_km_error};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
IKeyMintDevice::IKeyMintDevice, IRemotelyProvisionedComponent::IRemotelyProvisionedComponent,
@@ -175,8 +176,8 @@
pub static ref LEGACY_BLOB_LOADER: Arc<LegacyBlobLoader> = Arc::new(LegacyBlobLoader::new(
&DB_PATH.read().expect("Could not get the database path for legacy blob loader.")));
/// Legacy migrator. Atomically migrates legacy blobs to the database.
- pub static ref LEGACY_MIGRATOR: Arc<LegacyMigrator> =
- Arc::new(LegacyMigrator::new(Arc::new(Default::default())));
+ pub static ref LEGACY_IMPORTER: Arc<LegacyImporter> =
+ Arc::new(LegacyImporter::new(Arc::new(Default::default())));
/// Background thread which handles logging via statsd and logd
pub static ref LOGS_HANDLER: Arc<AsyncTask> = Default::default();
@@ -197,14 +198,15 @@
static KEYMINT_SERVICE_NAME: &str = "android.hardware.security.keymint.IKeyMintDevice";
-/// Make a new connection to a KeyMint device of the given security level.
-/// 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(
+/// Determine the service name for a KeyMint device of the given security level
+/// which implements at least the specified version of the `IKeyMintDevice`
+/// interface.
+fn keymint_service_name_by_version(
security_level: &SecurityLevel,
-) -> Result<(Strong<dyn IKeyMintDevice>, KeyMintHardwareInfo)> {
+ version: i32,
+) -> Result<Option<(i32, String)>> {
let keymint_instances =
- get_aidl_instances("android.hardware.security.keymint", 1, "IKeyMintDevice");
+ get_aidl_instances("android.hardware.security.keymint", version as usize, "IKeyMintDevice");
let service_name = match *security_level {
SecurityLevel::TRUSTED_ENVIRONMENT => {
@@ -222,12 +224,36 @@
}
}
_ => {
- return Err(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE))
- .context("In connect_keymint.")
+ return Err(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)).context(format!(
+ "In keymint_service_name_by_version: Trying to find keymint V{} for security level: {:?}",
+ version, security_level
+ ));
}
};
- let (keymint, hal_version) = if let Some(service_name) = service_name {
+ Ok(service_name.map(|service_name| (version, service_name)))
+}
+
+/// Make a new connection to a KeyMint device of the given security level.
+/// 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<(Strong<dyn IKeyMintDevice>, KeyMintHardwareInfo)> {
+ // Count down from the current interface version back to one in order to
+ // also find out the interface version -- an implementation of V2 will show
+ // up in the list of V1-capable devices, but not vice-versa.
+ let service_name = keymint_service_name_by_version(security_level, 2)
+ .and_then(|sl| {
+ if sl.is_none() {
+ keymint_service_name_by_version(security_level, 1)
+ } else {
+ Ok(sl)
+ }
+ })
+ .context("In connect_keymint.")?;
+
+ let (keymint, hal_version) = if let Some((version, service_name)) = service_name {
let km: Strong<dyn IKeyMintDevice> =
map_binder_status_code(binder::get_interface(&service_name))
.context("In connect_keymint: Trying to connect to genuine KeyMint service.")?;
@@ -235,11 +261,7 @@
// - V1 is 100
// - V2 is 200
// etc.
- let hal_version = km
- .getInterfaceVersion()
- .map(|v| v * 100i32)
- .context("In connect_keymint: Trying to determine KeyMint AIDL version")?;
- (km, Some(hal_version))
+ (km, Some(version * 100))
} else {
// This is a no-op if it was called before.
keystore2_km_compat::add_keymint_device_service();
@@ -260,6 +282,48 @@
)
};
+ // If the KeyMint device is back-level, use a wrapper that intercepts and
+ // emulates things that are not supported by the hardware.
+ let keymint = match hal_version {
+ Some(200) => {
+ // Current KeyMint version: use as-is.
+ log::info!(
+ "KeyMint device is current version ({:?}) for security level: {:?}",
+ hal_version,
+ security_level
+ );
+ keymint
+ }
+ Some(100) => {
+ // KeyMint v1: perform software emulation.
+ log::info!(
+ "Add emulation wrapper around {:?} device for security level: {:?}",
+ hal_version,
+ security_level
+ );
+ BacklevelKeyMintWrapper::wrap(KeyMintV1::new(*security_level), keymint)
+ .context("In connect_keymint: Trying to create V1 compatibility wrapper.")?
+ }
+ None => {
+ // Compatibility wrapper around a KeyMaster device: this roughly
+ // behaves like KeyMint V1 (e.g. it includes AGREE_KEY support,
+ // albeit in software.)
+ log::info!(
+ "Add emulation wrapper around Keymaster device for security level: {:?}",
+ security_level
+ );
+ BacklevelKeyMintWrapper::wrap(KeyMintV1::new(*security_level), keymint).context(
+ "In connect_keymint: Trying to create km_compat V1 compatibility wrapper .",
+ )?
+ }
+ _ => {
+ return Err(Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)).context(format!(
+ "In connect_keymint: unexpected hal_version {:?} for security level: {:?}",
+ hal_version, security_level
+ ))
+ }
+ };
+
let wp = wd::watch_millis("In connect_keymint: calling getHardwareInfo()", 500);
let mut hw_info = map_km_error(keymint.getHardwareInfo())
.context("In connect_keymint: Failed to get hardware info.")?;
diff --git a/keystore2/src/km_compat.rs b/keystore2/src/km_compat.rs
new file mode 100644
index 0000000..84855df
--- /dev/null
+++ b/keystore2/src/km_compat.rs
@@ -0,0 +1,579 @@
+// Copyright 2020, 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.
+
+//! Provide a wrapper around a KeyMint device that allows up-level features to
+//! be emulated on back-level devices.
+
+use crate::error::{map_binder_status, map_binder_status_code, map_or_log_err, Error, ErrorCode};
+use android_hardware_security_keymint::binder::{BinderFeatures, StatusCode, Strong};
+use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::TimeStampToken::TimeStampToken;
+use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
+ AttestationKey::AttestationKey, BeginResult::BeginResult, EcCurve::EcCurve,
+ HardwareAuthToken::HardwareAuthToken, IKeyMintDevice::BnKeyMintDevice,
+ IKeyMintDevice::IKeyMintDevice, KeyCharacteristics::KeyCharacteristics,
+ KeyCreationResult::KeyCreationResult, KeyFormat::KeyFormat,
+ KeyMintHardwareInfo::KeyMintHardwareInfo, KeyParameter::KeyParameter,
+ KeyParameterValue::KeyParameterValue, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
+ Tag::Tag,
+};
+use android_security_compat::aidl::android::security::compat::IKeystoreCompatService::IKeystoreCompatService;
+use anyhow::Context;
+use keystore2_crypto::{hmac_sha256, HMAC_SHA256_LEN};
+
+/// Key data associated with key generation/import.
+#[derive(Debug, PartialEq, Eq)]
+pub enum KeyImportData<'a> {
+ None,
+ Pkcs8(&'a [u8]),
+ Raw(&'a [u8]),
+}
+
+impl<'a> KeyImportData<'a> {
+ /// Translate import parameters into a `KeyImportData` instance.
+ fn new(key_format: KeyFormat, key_data: &'a [u8]) -> binder::Result<Self> {
+ match key_format {
+ KeyFormat::PKCS8 => Ok(KeyImportData::Pkcs8(key_data)),
+ KeyFormat::RAW => Ok(KeyImportData::Raw(key_data)),
+ _ => Err(binder::Status::new_service_specific_error(
+ ErrorCode::UNSUPPORTED_KEY_FORMAT.0,
+ None,
+ )),
+ }
+ }
+}
+
+/// A key blob that may be software-emulated or may be directly produced by an
+/// underlying device. In either variant the inner data is the keyblob itself,
+/// as seen by the relevant device.
+#[derive(Debug, PartialEq, Eq)]
+pub enum KeyBlob<'a> {
+ Raw(&'a [u8]),
+ Wrapped(&'a [u8]),
+}
+
+/// Trait for detecting that software emulation of a current-version KeyMint
+/// feature is required for a back-level KeyMint implementation.
+pub trait EmulationDetector: Send + Sync {
+ /// Indicate whether software emulation is required for key
+ /// generation/import using the provided parameters.
+ fn emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool;
+}
+
+const KEYBLOB_PREFIX: &[u8] = b"SoftKeyMintForV1Blob";
+const KEYBLOB_HMAC_KEY: &[u8] = b"SoftKeyMintForV1HMACKey";
+
+/// Wrap the provided keyblob:
+/// - prefix it with an identifier specific to this wrapper
+/// - suffix it with an HMAC tag, using the [`KEYBLOB_HMAC_KEY`] and `keyblob`.
+fn wrap_keyblob(keyblob: &[u8]) -> anyhow::Result<Vec<u8>> {
+ let mut result = Vec::with_capacity(KEYBLOB_PREFIX.len() + keyblob.len() + HMAC_SHA256_LEN);
+ result.extend_from_slice(KEYBLOB_PREFIX);
+ result.extend_from_slice(keyblob);
+ let tag = hmac_sha256(KEYBLOB_HMAC_KEY, keyblob)
+ .context("In wrap_keyblob, failed to calculate HMAC-SHA256")?;
+ result.extend_from_slice(&tag);
+ Ok(result)
+}
+
+/// Return an unwrapped version of the provided `keyblob`, which may or may
+/// not be associated with the software emulation.
+fn unwrap_keyblob(keyblob: &[u8]) -> KeyBlob {
+ if !keyblob.starts_with(KEYBLOB_PREFIX) {
+ return KeyBlob::Raw(keyblob);
+ }
+ let without_prefix = &keyblob[KEYBLOB_PREFIX.len()..];
+ if without_prefix.len() < HMAC_SHA256_LEN {
+ return KeyBlob::Raw(keyblob);
+ }
+ let (inner_keyblob, want_tag) = without_prefix.split_at(without_prefix.len() - HMAC_SHA256_LEN);
+ let got_tag = match hmac_sha256(KEYBLOB_HMAC_KEY, inner_keyblob) {
+ Ok(tag) => tag,
+ Err(e) => {
+ log::error!("Error calculating HMAC-SHA256 for keyblob unwrap: {:?}", e);
+ return KeyBlob::Raw(keyblob);
+ }
+ };
+ // Comparison does not need to be constant-time here.
+ if want_tag == got_tag {
+ KeyBlob::Wrapped(inner_keyblob)
+ } else {
+ KeyBlob::Raw(keyblob)
+ }
+}
+
+/// Wrapper around a real device that implements a back-level version of
+/// `IKeyMintDevice`
+pub struct BacklevelKeyMintWrapper<T: EmulationDetector> {
+ /// The `real` device implements some earlier version of `IKeyMintDevice`
+ real: Strong<dyn IKeyMintDevice>,
+ /// The `soft`ware device implements the current version of `IKeyMintDevice`
+ soft: Strong<dyn IKeyMintDevice>,
+ /// Detector for operations that are not supported by the earlier version of
+ /// `IKeyMintDevice`. Or possibly a large flightless bird, who can tell.
+ emu: T,
+}
+
+impl<T> BacklevelKeyMintWrapper<T>
+where
+ T: EmulationDetector + 'static,
+{
+ /// Create a wrapper around the provided back-level KeyMint device, so that
+ /// software emulation can be performed for any current-version features not
+ /// provided by the real device.
+ pub fn wrap(
+ emu: T,
+ real: Strong<dyn IKeyMintDevice>,
+ ) -> anyhow::Result<Strong<dyn IKeyMintDevice>> {
+ // 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 BacklevelKeyMintWrapper::wrap: Trying to connect to compat service.")?;
+ let soft =
+ map_binder_status(keystore_compat_service.getKeyMintDevice(SecurityLevel::SOFTWARE))
+ .map_err(|e| match e {
+ Error::BinderTransaction(StatusCode::NAME_NOT_FOUND) => {
+ Error::Km(ErrorCode::HARDWARE_TYPE_UNAVAILABLE)
+ }
+ e => e,
+ })
+ .context("In BacklevelKeyMintWrapper::wrap: Trying to get software device.")?;
+
+ Ok(BnKeyMintDevice::new_binder(
+ Self { real, soft, emu },
+ BinderFeatures { set_requesting_sid: true, ..BinderFeatures::default() },
+ ))
+ }
+}
+
+impl<T> binder::Interface for BacklevelKeyMintWrapper<T> where T: EmulationDetector {}
+
+impl<T> IKeyMintDevice for BacklevelKeyMintWrapper<T>
+where
+ T: EmulationDetector + 'static,
+{
+ // For methods that don't involve keyblobs, forward to either the real
+ // device, or to both real & emulated devices.
+ fn getHardwareInfo(&self) -> binder::Result<KeyMintHardwareInfo> {
+ self.real.getHardwareInfo()
+ }
+ fn addRngEntropy(&self, data: &[u8]) -> binder::Result<()> {
+ self.real.addRngEntropy(data)
+ }
+ fn deleteAllKeys(&self) -> binder::Result<()> {
+ self.real.deleteAllKeys()
+ }
+ fn destroyAttestationIds(&self) -> binder::Result<()> {
+ self.real.destroyAttestationIds()
+ }
+ fn deviceLocked(
+ &self,
+ password_only: bool,
+ timestamp_token: Option<&TimeStampToken>,
+ ) -> binder::Result<()> {
+ // Propagate to both real and software devices, but only pay attention
+ // to the result from the real device.
+ let _ = self.soft.deviceLocked(password_only, timestamp_token);
+ self.real.deviceLocked(password_only, timestamp_token)
+ }
+ fn earlyBootEnded(&self) -> binder::Result<()> {
+ // Propagate to both real and software devices, but only pay attention
+ // to the result from the real device.
+ let _ = self.soft.earlyBootEnded();
+ self.real.earlyBootEnded()
+ }
+
+ // For methods that emit keyblobs, check whether the underlying real device
+ // supports the relevant parameters, and forward to the appropriate device.
+ // If the emulated device is used, ensure that the created keyblob gets
+ // prefixed so we can recognize it in future.
+ fn generateKey(
+ &self,
+ key_params: &[KeyParameter],
+ attestation_key: Option<&AttestationKey>,
+ ) -> binder::Result<KeyCreationResult> {
+ if self.emu.emulation_required(key_params, &KeyImportData::None) {
+ let mut result = self.soft.generateKey(key_params, attestation_key)?;
+ result.keyBlob = map_or_log_err(wrap_keyblob(&result.keyBlob), Ok)?;
+ Ok(result)
+ } else {
+ self.real.generateKey(key_params, attestation_key)
+ }
+ }
+ fn importKey(
+ &self,
+ key_params: &[KeyParameter],
+ key_format: KeyFormat,
+ key_data: &[u8],
+ attestation_key: Option<&AttestationKey>,
+ ) -> binder::Result<KeyCreationResult> {
+ if self.emu.emulation_required(key_params, &KeyImportData::new(key_format, key_data)?) {
+ let mut result =
+ self.soft.importKey(key_params, key_format, key_data, attestation_key)?;
+ result.keyBlob = map_or_log_err(wrap_keyblob(&result.keyBlob), Ok)?;
+ Ok(result)
+ } else {
+ self.real.importKey(key_params, key_format, key_data, attestation_key)
+ }
+ }
+ fn importWrappedKey(
+ &self,
+ wrapped_key_data: &[u8],
+ wrapping_key_blob: &[u8],
+ masking_key: &[u8],
+ unwrapping_params: &[KeyParameter],
+ password_sid: i64,
+ biometric_sid: i64,
+ ) -> binder::Result<KeyCreationResult> {
+ // A wrapped key cannot be software-emulated, as the wrapping key is
+ // likely hardware-bound.
+ self.real.importWrappedKey(
+ wrapped_key_data,
+ wrapping_key_blob,
+ masking_key,
+ unwrapping_params,
+ password_sid,
+ biometric_sid,
+ )
+ }
+
+ // For methods that use keyblobs, determine which device to forward the
+ // operation to based on whether the keyblob is appropriately prefixed.
+ fn upgradeKey(
+ &self,
+ keyblob_to_upgrade: &[u8],
+ upgrade_params: &[KeyParameter],
+ ) -> binder::Result<Vec<u8>> {
+ match unwrap_keyblob(keyblob_to_upgrade) {
+ KeyBlob::Raw(keyblob) => self.real.upgradeKey(keyblob, upgrade_params),
+ KeyBlob::Wrapped(keyblob) => {
+ // Re-wrap the upgraded keyblob.
+ let upgraded_keyblob = self.soft.upgradeKey(keyblob, upgrade_params)?;
+ map_or_log_err(wrap_keyblob(&upgraded_keyblob), Ok)
+ }
+ }
+ }
+ fn deleteKey(&self, keyblob: &[u8]) -> binder::Result<()> {
+ match unwrap_keyblob(keyblob) {
+ KeyBlob::Raw(keyblob) => self.real.deleteKey(keyblob),
+ KeyBlob::Wrapped(keyblob) => {
+ // Forward to the software implementation for completeness, but
+ // this should always be a no-op.
+ self.soft.deleteKey(keyblob)
+ }
+ }
+ }
+ fn begin(
+ &self,
+ purpose: KeyPurpose,
+ keyblob: &[u8],
+ params: &[KeyParameter],
+ auth_token: Option<&HardwareAuthToken>,
+ ) -> binder::Result<BeginResult> {
+ match unwrap_keyblob(keyblob) {
+ KeyBlob::Raw(keyblob) => self.real.begin(purpose, keyblob, params, auth_token),
+ KeyBlob::Wrapped(keyblob) => self.soft.begin(purpose, keyblob, params, auth_token),
+ }
+ }
+ fn getKeyCharacteristics(
+ &self,
+ keyblob: &[u8],
+ app_id: &[u8],
+ app_data: &[u8],
+ ) -> binder::Result<Vec<KeyCharacteristics>> {
+ match unwrap_keyblob(keyblob) {
+ KeyBlob::Raw(keyblob) => self.real.getKeyCharacteristics(keyblob, app_id, app_data),
+ KeyBlob::Wrapped(keyblob) => self.soft.getKeyCharacteristics(keyblob, app_id, app_data),
+ }
+ }
+ fn convertStorageKeyToEphemeral(&self, storage_keyblob: &[u8]) -> binder::Result<Vec<u8>> {
+ // Storage keys should never be associated with a software emulated device.
+ self.real.convertStorageKeyToEphemeral(storage_keyblob)
+ }
+}
+
+/// Detector for current features that are not implemented by KeyMint V1.
+#[derive(Debug)]
+pub struct KeyMintV1 {
+ sec_level: SecurityLevel,
+}
+
+impl KeyMintV1 {
+ pub fn new(sec_level: SecurityLevel) -> Self {
+ Self { sec_level }
+ }
+}
+
+impl EmulationDetector for KeyMintV1 {
+ fn emulation_required(&self, params: &[KeyParameter], _import_data: &KeyImportData) -> bool {
+ // No current difference from KeyMint v1 for STRONGBOX (it doesn't
+ // support curve 25519).
+ if self.sec_level == SecurityLevel::STRONGBOX {
+ return false;
+ }
+
+ // KeyMint V1 does not support the use of curve 25519, so hunt for that
+ // in the parameters.
+ if params.iter().any(|p| {
+ p.tag == Tag::EC_CURVE && p.value == KeyParameterValue::EcCurve(EcCurve::CURVE_25519)
+ }) {
+ return true;
+ }
+ // In theory, if the `import_data` is `KeyImportData::Pkcs8` we could
+ // check the imported keymaterial for the Ed25519 / X25519 OIDs in the
+ // PKCS8 keydata, and use that to decide to route to software. However,
+ // the KeyMint spec doesn't require that so don't attempt to parse the
+ // key material here.
+ false
+ }
+}
+
+/// Detector for current features that are not implemented by KeyMaster, via the
+/// km_compat wrapper.
+#[derive(Debug)]
+pub struct Keymaster {
+ v1: KeyMintV1,
+}
+
+/// TODO(b/216434270): This could be used this to replace the emulation routing
+/// in the km_compat C++ code, and allow support for imported ECDH keys along
+/// the way. Would need to figure out what would happen to existing emulated
+/// keys though.
+#[allow(dead_code)]
+impl Keymaster {
+ pub fn new(sec_level: SecurityLevel) -> Self {
+ Self { v1: KeyMintV1::new(sec_level) }
+ }
+}
+
+impl EmulationDetector for Keymaster {
+ fn emulation_required(&self, params: &[KeyParameter], import_data: &KeyImportData) -> bool {
+ // The km_compat wrapper on top of Keymaster emulates the KeyMint V1
+ // interface, so any feature from > v1 needs to be emulated.
+ if self.v1.emulation_required(params, import_data) {
+ return true;
+ }
+
+ // Keymaster does not support ECDH (KeyPurpose::AGREE_KEY), so hunt for
+ // that in the parameters.
+ if params.iter().any(|p| {
+ p.tag == Tag::PURPOSE && p.value == KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY)
+ }) {
+ return true;
+ }
+ false
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_key_import_data() {
+ let data = vec![1, 2, 3];
+ assert_eq!(KeyImportData::new(KeyFormat::PKCS8, &data), Ok(KeyImportData::Pkcs8(&data)));
+ assert_eq!(KeyImportData::new(KeyFormat::RAW, &data), Ok(KeyImportData::Raw(&data)));
+ assert!(KeyImportData::new(KeyFormat::X509, &data).is_err());
+ }
+
+ #[test]
+ fn test_wrap_keyblob() {
+ let keyblob = vec![1, 2, 3];
+ let wrapped = wrap_keyblob(&keyblob).unwrap();
+ assert_eq!(&wrapped[..KEYBLOB_PREFIX.len()], KEYBLOB_PREFIX);
+ assert_eq!(&wrapped[KEYBLOB_PREFIX.len()..KEYBLOB_PREFIX.len() + keyblob.len()], &keyblob);
+ assert_eq!(unwrap_keyblob(&keyblob), KeyBlob::Raw(&keyblob));
+ assert_eq!(unwrap_keyblob(&wrapped), KeyBlob::Wrapped(&keyblob));
+
+ let mut corrupt_prefix = wrapped.clone();
+ corrupt_prefix[0] ^= 0x01;
+ assert_eq!(unwrap_keyblob(&corrupt_prefix), KeyBlob::Raw(&corrupt_prefix));
+
+ let mut corrupt_suffix = wrapped.clone();
+ corrupt_suffix[wrapped.len() - 1] ^= 0x01;
+ assert_eq!(unwrap_keyblob(&corrupt_suffix), KeyBlob::Raw(&corrupt_suffix));
+
+ let too_short = &wrapped[..wrapped.len() - 4];
+ assert_eq!(unwrap_keyblob(too_short), KeyBlob::Raw(too_short));
+ }
+
+ #[test]
+ fn test_keymintv1_emulation_required() {
+ let tests = vec![
+ (SecurityLevel::TRUSTED_ENVIRONMENT, vec![], false),
+ (
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
+ },
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::VERIFY),
+ },
+ ],
+ false,
+ ),
+ (
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ vec![KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
+ }],
+ false,
+ ),
+ (
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
+ },
+ KeyParameter {
+ tag: Tag::EC_CURVE,
+ value: KeyParameterValue::EcCurve(EcCurve::P_256),
+ },
+ ],
+ false,
+ ),
+ (
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
+ },
+ KeyParameter {
+ tag: Tag::EC_CURVE,
+ value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
+ },
+ ],
+ true,
+ ),
+ (
+ SecurityLevel::STRONGBOX,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
+ },
+ KeyParameter {
+ tag: Tag::EC_CURVE,
+ value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
+ },
+ ],
+ false,
+ ),
+ ];
+ for (sec_level, params, want) in tests {
+ let v1 = KeyMintV1::new(sec_level);
+ let got = v1.emulation_required(¶ms, &KeyImportData::None);
+ assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want);
+ }
+ }
+
+ #[test]
+ fn test_keymaster_emulation_required() {
+ let tests = vec![
+ (SecurityLevel::TRUSTED_ENVIRONMENT, vec![], false),
+ (
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
+ },
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::VERIFY),
+ },
+ ],
+ false,
+ ),
+ (
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ vec![KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
+ }],
+ true,
+ ),
+ (
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
+ },
+ KeyParameter {
+ tag: Tag::EC_CURVE,
+ value: KeyParameterValue::EcCurve(EcCurve::P_256),
+ },
+ ],
+ true,
+ ),
+ (
+ SecurityLevel::TRUSTED_ENVIRONMENT,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
+ },
+ KeyParameter {
+ tag: Tag::EC_CURVE,
+ value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
+ },
+ ],
+ true,
+ ),
+ (
+ SecurityLevel::STRONGBOX,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::AGREE_KEY),
+ },
+ KeyParameter {
+ tag: Tag::EC_CURVE,
+ value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
+ },
+ ],
+ true,
+ ),
+ (
+ SecurityLevel::STRONGBOX,
+ vec![
+ KeyParameter {
+ tag: Tag::PURPOSE,
+ value: KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
+ },
+ KeyParameter {
+ tag: Tag::EC_CURVE,
+ value: KeyParameterValue::EcCurve(EcCurve::CURVE_25519),
+ },
+ ],
+ false,
+ ),
+ ];
+ for (sec_level, params, want) in tests {
+ let v0 = Keymaster::new(sec_level);
+ let got = v0.emulation_required(¶ms, &KeyImportData::None);
+ assert_eq!(got, want, "emulation_required({:?})={}, want {}", params, got, want);
+ }
+ }
+}
diff --git a/keystore2/src/km_compat/km_compat.cpp b/keystore2/src/km_compat/km_compat.cpp
index bb60047..a6ca179 100644
--- a/keystore2/src/km_compat/km_compat.cpp
+++ b/keystore2/src/km_compat/km_compat.cpp
@@ -1391,14 +1391,33 @@
}
}
+std::shared_ptr<IKeyMintDevice> getSoftwareKeymintDevice() {
+ static std::mutex mutex;
+ static std::shared_ptr<IKeyMintDevice> swDevice;
+ std::lock_guard<std::mutex> lock(mutex);
+ if (!swDevice) {
+ swDevice.reset(CreateKeyMintDevice(KeyMintSecurityLevel::SOFTWARE));
+ }
+ return swDevice;
+}
+
std::shared_ptr<KeyMintDevice>
-KeyMintDevice::createKeyMintDevice(KeyMintSecurityLevel securityLevel) {
+KeyMintDevice::getWrappedKeymasterDevice(KeyMintSecurityLevel securityLevel) {
if (auto dev = getDevice(securityLevel)) {
return ndk::SharedRefBase::make<KeyMintDevice>(std::move(dev), securityLevel);
}
return {};
}
+std::shared_ptr<IKeyMintDevice>
+KeyMintDevice::createKeyMintDevice(KeyMintSecurityLevel securityLevel) {
+ if (securityLevel == KeyMintSecurityLevel::SOFTWARE) {
+ return getSoftwareKeymintDevice();
+ } else {
+ return getWrappedKeymasterDevice(securityLevel);
+ }
+}
+
std::shared_ptr<SharedSecret> SharedSecret::createSharedSecret(KeyMintSecurityLevel securityLevel) {
auto device = getDevice(securityLevel);
if (!device) {
diff --git a/keystore2/src/km_compat/km_compat.h b/keystore2/src/km_compat/km_compat.h
index 70c7b86..c07470d 100644
--- a/keystore2/src/km_compat/km_compat.h
+++ b/keystore2/src/km_compat/km_compat.h
@@ -84,7 +84,9 @@
public:
explicit KeyMintDevice(::android::sp<Keymaster>, KeyMintSecurityLevel);
- static std::shared_ptr<KeyMintDevice> createKeyMintDevice(KeyMintSecurityLevel securityLevel);
+ static std::shared_ptr<IKeyMintDevice> createKeyMintDevice(KeyMintSecurityLevel securityLevel);
+ static std::shared_ptr<KeyMintDevice>
+ getWrappedKeymasterDevice(KeyMintSecurityLevel securityLevel);
ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* _aidl_return) override;
ScopedAStatus addRngEntropy(const std::vector<uint8_t>& in_data) override;
diff --git a/keystore2/src/km_compat/slot_test.cpp b/keystore2/src/km_compat/slot_test.cpp
index 43f3bc6..3539c4d 100644
--- a/keystore2/src/km_compat/slot_test.cpp
+++ b/keystore2/src/km_compat/slot_test.cpp
@@ -73,7 +73,9 @@
TEST(SlotTest, TestSlots) {
static std::shared_ptr<KeyMintDevice> device =
- KeyMintDevice::createKeyMintDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
+ KeyMintDevice::getWrappedKeymasterDevice(SecurityLevel::TRUSTED_ENVIRONMENT);
+ ASSERT_NE(device.get(), nullptr);
+
device->setNumFreeSlots(NUM_SLOTS);
// A begin() that returns a failure should not use a slot.
diff --git a/keystore2/src/legacy_migrator.rs b/keystore2/src/legacy_importer.rs
similarity index 79%
rename from keystore2/src/legacy_migrator.rs
rename to keystore2/src/legacy_importer.rs
index 65f4b0b..3f37b14 100644
--- a/keystore2/src/legacy_migrator.rs
+++ b/keystore2/src/legacy_importer.rs
@@ -38,8 +38,8 @@
use std::sync::mpsc::channel;
use std::sync::{Arc, Mutex};
-/// Represents LegacyMigrator.
-pub struct LegacyMigrator {
+/// Represents LegacyImporter.
+pub struct LegacyImporter {
async_task: Arc<AsyncTask>,
initializer: Mutex<
Option<
@@ -51,19 +51,19 @@
>,
>,
/// This atomic is used for cheap interior mutability. It is intended to prevent
- /// expensive calls into the legacy migrator when the legacy database is empty.
+ /// expensive calls into the legacy importer when the legacy database is empty.
/// When transitioning from READY to EMPTY, spurious calls may occur for a brief period
/// of time. This is tolerable in favor of the common case.
state: AtomicU8,
}
#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
-struct RecentMigration {
+struct RecentImport {
uid: u32,
alias: String,
}
-impl RecentMigration {
+impl RecentImport {
fn new(uid: u32, alias: String) -> Self {
Self { uid, alias }
}
@@ -74,15 +74,15 @@
User(u32),
}
-struct LegacyMigratorState {
- recently_migrated: HashSet<RecentMigration>,
- recently_migrated_super_key: HashSet<u32>,
+struct LegacyImporterState {
+ recently_imported: HashSet<RecentImport>,
+ recently_imported_super_key: HashSet<u32>,
legacy_loader: Arc<LegacyBlobLoader>,
sec_level_to_km_uuid: HashMap<SecurityLevel, Uuid>,
db: KeystoreDB,
}
-impl LegacyMigrator {
+impl LegacyImporter {
const WIFI_NAMESPACE: i64 = 102;
const AID_WIFI: u32 = 1010;
@@ -90,7 +90,7 @@
const STATE_READY: u8 = 1;
const STATE_EMPTY: u8 = 2;
- /// Constructs a new LegacyMigrator using the given AsyncTask object as migration
+ /// Constructs a new LegacyImporter using the given AsyncTask object as import
/// worker.
pub fn new(async_task: Arc<AsyncTask>) -> Self {
Self {
@@ -100,7 +100,7 @@
}
}
- /// The legacy migrator must be initialized deferred, because keystore starts very early.
+ /// The legacy importer must be initialized deferred, because keystore starts very early.
/// At this time the data partition may not be mounted. So we cannot open database connections
/// until we get actual key load requests. This sets the function that the legacy loader
/// uses to connect to the database.
@@ -125,11 +125,11 @@
Ok(())
}
- /// This function is called by the migration requestor to check if it is worth
- /// making a migration request. It also transitions the state from UNINITIALIZED
+ /// This function is called by the import requestor to check if it is worth
+ /// making an import request. It also transitions the state from UNINITIALIZED
/// to READY or EMPTY on first use. The deferred initialization is necessary, because
/// Keystore 2.0 runs early during boot, where data may not yet be mounted.
- /// Returns Ok(STATE_READY) if a migration request is worth undertaking and
+ /// Returns Ok(STATE_READY) if an import request is worth undertaking and
/// Ok(STATE_EMPTY) if the database is empty. An error is returned if the loader
/// was not initialized and cannot be initialized.
fn check_state(&self) -> Result<u8> {
@@ -157,9 +157,9 @@
}
self.async_task.queue_hi(move |shelf| {
- shelf.get_or_put_with(|| LegacyMigratorState {
- recently_migrated: Default::default(),
- recently_migrated_super_key: Default::default(),
+ shelf.get_or_put_with(|| LegacyImporterState {
+ recently_imported: Default::default(),
+ recently_imported_super_key: Default::default(),
legacy_loader,
sec_level_to_km_uuid,
db,
@@ -189,14 +189,14 @@
);
}
(Self::STATE_READY, _) => return Ok(Self::STATE_READY),
- (s, _) => panic!("Unknown legacy migrator state. {} ", s),
+ (s, _) => panic!("Unknown legacy importer state. {} ", s),
}
}
}
/// List all aliases for uid in the legacy database.
pub fn list_uid(&self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
- let _wp = wd::watch_millis("LegacyMigrator::list_uid", 500);
+ let _wp = wd::watch_millis("LegacyImporter::list_uid", 500);
let uid = match (domain, namespace) {
(Domain::APP, namespace) => namespace as u32,
@@ -217,44 +217,44 @@
)
}
- /// Sends the given closure to the migrator thread for execution after calling check_state.
+ /// Sends the given closure to the importer thread for execution after calling check_state.
/// Returns None if the database was empty and the request was not executed.
- /// Otherwise returns Some with the result produced by the migration request.
+ /// Otherwise returns Some with the result produced by the import request.
/// The loader state may transition to STATE_EMPTY during the execution of this function.
fn do_serialized<F, T: Send + 'static>(&self, f: F) -> Option<Result<T>>
where
- F: FnOnce(&mut LegacyMigratorState) -> Result<T> + Send + 'static,
+ F: FnOnce(&mut LegacyImporterState) -> Result<T> + Send + 'static,
{
// Short circuit if the database is empty or not initialized (error case).
match self.check_state().context("In do_serialized: Checking state.") {
- Ok(LegacyMigrator::STATE_EMPTY) => return None,
- Ok(LegacyMigrator::STATE_READY) => {}
+ Ok(LegacyImporter::STATE_EMPTY) => return None,
+ Ok(LegacyImporter::STATE_READY) => {}
Err(e) => return Some(Err(e)),
- Ok(s) => panic!("Unknown legacy migrator state. {} ", s),
+ Ok(s) => panic!("Unknown legacy importer state. {} ", s),
}
// We have established that there may be a key in the legacy database.
- // Now we schedule a migration request.
+ // Now we schedule an import request.
let (sender, receiver) = channel();
self.async_task.queue_hi(move |shelf| {
- // Get the migrator state from the shelf.
- // There may not be a state. This can happen if this migration request was scheduled
+ // Get the importer state from the shelf.
+ // There may not be a state. This can happen if this import request was scheduled
// before a previous request established that the legacy database was empty
// and removed the state from the shelf. Since we know now that the database
// is empty, we can return None here.
- let (new_state, result) = if let Some(legacy_migrator_state) =
- shelf.get_downcast_mut::<LegacyMigratorState>()
+ let (new_state, result) = if let Some(legacy_importer_state) =
+ shelf.get_downcast_mut::<LegacyImporterState>()
{
- let result = f(legacy_migrator_state);
- (legacy_migrator_state.check_empty(), Some(result))
+ let result = f(legacy_importer_state);
+ (legacy_importer_state.check_empty(), Some(result))
} else {
(Self::STATE_EMPTY, None)
};
- // If the migration request determined that the database is now empty, we discard
+ // If the import request determined that the database is now empty, we discard
// the state from the shelf to free up the resources we won't need any longer.
if result.is_some() && new_state == Self::STATE_EMPTY {
- shelf.remove_downcast_ref::<LegacyMigratorState>();
+ shelf.remove_downcast_ref::<LegacyImporterState>();
}
// Send the result to the requester.
@@ -271,7 +271,7 @@
};
// We can only transition to EMPTY but never back.
- // The migrator never creates any legacy blobs.
+ // The importer never creates any legacy blobs.
if new_state == Self::STATE_EMPTY {
self.state.store(Self::STATE_EMPTY, Ordering::Relaxed)
}
@@ -280,10 +280,10 @@
}
/// Runs the key_accessor function and returns its result. If it returns an error and the
- /// root cause was KEY_NOT_FOUND, tries to migrate a key with the given parameters from
+ /// root cause was KEY_NOT_FOUND, tries to import a key with the given parameters from
/// the legacy database to the new database and runs the key_accessor function again if
- /// the migration request was successful.
- pub fn with_try_migrate<F, T>(
+ /// the import request was successful.
+ pub fn with_try_import<F, T>(
&self,
key: &KeyDescriptor,
caller_uid: u32,
@@ -292,7 +292,7 @@
where
F: Fn() -> Result<T>,
{
- let _wp = wd::watch_millis("LegacyMigrator::with_try_migrate", 500);
+ let _wp = wd::watch_millis("LegacyImporter::with_try_import", 500);
// Access the key and return on success.
match key_accessor() {
@@ -304,7 +304,7 @@
}
// Filter inputs. We can only load legacy app domain keys and some special rules due
- // to which we migrate keys transparently to an SELINUX domain.
+ // to which we import keys transparently to an SELINUX domain.
let uid = match key {
KeyDescriptor { domain: Domain::APP, alias: Some(_), .. } => caller_uid,
KeyDescriptor { domain: Domain::SELINUX, nspace, alias: Some(_), .. } => {
@@ -324,11 +324,11 @@
let key_clone = key.clone();
let result = self
- .do_serialized(move |migrator_state| migrator_state.check_and_migrate(uid, key_clone));
+ .do_serialized(move |importer_state| importer_state.check_and_import(uid, key_clone));
if let Some(result) = result {
result?;
- // After successful migration try again.
+ // After successful import try again.
key_accessor()
} else {
Err(Error::Rc(ResponseCode::KEY_NOT_FOUND)).context("Legacy database is empty.")
@@ -336,8 +336,8 @@
}
/// Calls key_accessor and returns the result on success. In the case of a KEY_NOT_FOUND error
- /// this function makes a migration request and on success retries the key_accessor.
- pub fn with_try_migrate_super_key<F, T>(
+ /// this function makes an import request and on success retries the key_accessor.
+ pub fn with_try_import_super_key<F, T>(
&self,
user_id: u32,
pw: &Password,
@@ -346,31 +346,31 @@
where
F: FnMut() -> Result<Option<T>>,
{
- let _wp = wd::watch_millis("LegacyMigrator::with_try_migrate_super_key", 500);
+ let _wp = wd::watch_millis("LegacyImporter::with_try_import_super_key", 500);
match key_accessor() {
Ok(Some(result)) => return Ok(Some(result)),
Ok(None) => {}
Err(e) => return Err(e),
}
- let pw = pw.try_clone().context("In with_try_migrate_super_key: Cloning password.")?;
- let result = self.do_serialized(move |migrator_state| {
- migrator_state.check_and_migrate_super_key(user_id, &pw)
+ let pw = pw.try_clone().context("In with_try_import_super_key: Cloning password.")?;
+ let result = self.do_serialized(move |importer_state| {
+ importer_state.check_and_import_super_key(user_id, &pw)
});
if let Some(result) = result {
result?;
- // After successful migration try again.
+ // After successful import try again.
key_accessor()
} else {
Ok(None)
}
}
- /// Deletes all keys belonging to the given namespace, migrating them into the database
+ /// Deletes all keys belonging to the given namespace, importing them into the database
/// for subsequent garbage collection if necessary.
pub fn bulk_delete_uid(&self, domain: Domain, nspace: i64) -> Result<()> {
- let _wp = wd::watch_millis("LegacyMigrator::bulk_delete_uid", 500);
+ let _wp = wd::watch_millis("LegacyImporter::bulk_delete_uid", 500);
let uid = match (domain, nspace) {
(Domain::APP, nspace) => nspace as u32,
@@ -379,24 +379,24 @@
_ => return Ok(()),
};
- let result = self.do_serialized(move |migrator_state| {
- migrator_state.bulk_delete(BulkDeleteRequest::Uid(uid), false)
+ let result = self.do_serialized(move |importer_state| {
+ importer_state.bulk_delete(BulkDeleteRequest::Uid(uid), false)
});
result.unwrap_or(Ok(()))
}
- /// Deletes all keys belonging to the given android user, migrating them into the database
+ /// Deletes all keys belonging to the given android user, importing them into the database
/// for subsequent garbage collection if necessary.
pub fn bulk_delete_user(
&self,
user_id: u32,
keep_non_super_encrypted_keys: bool,
) -> Result<()> {
- let _wp = wd::watch_millis("LegacyMigrator::bulk_delete_user", 500);
+ let _wp = wd::watch_millis("LegacyImporter::bulk_delete_user", 500);
- let result = self.do_serialized(move |migrator_state| {
- migrator_state
+ let result = self.do_serialized(move |importer_state| {
+ importer_state
.bulk_delete(BulkDeleteRequest::User(user_id), keep_non_super_encrypted_keys)
});
@@ -406,12 +406,12 @@
/// Queries the legacy database for the presence of a super key for the given user.
pub fn has_super_key(&self, user_id: u32) -> Result<bool> {
let result =
- self.do_serialized(move |migrator_state| migrator_state.has_super_key(user_id));
+ self.do_serialized(move |importer_state| importer_state.has_super_key(user_id));
result.unwrap_or(Ok(false))
}
}
-impl LegacyMigratorState {
+impl LegacyImporterState {
fn get_km_uuid(&self, is_strongbox: bool) -> Result<Uuid> {
let sec_level = if is_strongbox {
SecurityLevel::STRONGBOX
@@ -430,17 +430,17 @@
.context("In list_uid: Trying to list legacy entries.")
}
- /// This is a key migration request that must run in the migrator thread. This must
+ /// This is a key import request that must run in the importer thread. This must
/// be passed to do_serialized.
- fn check_and_migrate(&mut self, uid: u32, mut key: KeyDescriptor) -> Result<()> {
+ fn check_and_import(&mut self, uid: u32, mut key: KeyDescriptor) -> Result<()> {
let alias = key.alias.clone().ok_or_else(|| {
- anyhow::anyhow!(Error::sys()).context(concat!(
- "In check_and_migrate: Must be Some because ",
- "our caller must not have called us otherwise."
- ))
+ anyhow::anyhow!(Error::sys()).context(
+ "In check_and_import: Must be Some because \
+ our caller must not have called us otherwise.",
+ )
})?;
- if self.recently_migrated.contains(&RecentMigration::new(uid, alias.clone())) {
+ if self.recently_imported.contains(&RecentImport::new(uid, alias.clone())) {
return Ok(());
}
@@ -452,7 +452,7 @@
let (km_blob_params, user_cert, ca_cert) = self
.legacy_loader
.load_by_uid_alias(uid, &alias, None)
- .context("In check_and_migrate: Trying to load legacy blob.")?;
+ .context("In check_and_import: Trying to load legacy blob.")?;
let result = match km_blob_params {
Some((km_blob, params)) => {
let is_strongbox = km_blob.is_strongbox();
@@ -464,33 +464,33 @@
let super_key_id = match self
.db
.load_super_key(&USER_SUPER_KEY, user_id)
- .context("In check_and_migrate: Failed to load super key")?
+ .context("In check_and_import: Failed to load super key")?
{
Some((_, entry)) => entry.id(),
None => {
// This might be the first time we access the super key,
- // and it may not have been migrated. We cannot import
+ // and it may not have been imported. We cannot import
// the legacy super_key key now, because we need to reencrypt
// it which we cannot do if we are not unlocked, which we are
- // not because otherwise the key would have been migrated.
+ // not because otherwise the key would have been imported.
// We can check though if the key exists. If it does,
// we can return Locked. Otherwise, we can delete the
// key and return NotFound, because the key will never
// be unlocked again.
if self.legacy_loader.has_super_key(user_id) {
return Err(Error::Rc(ResponseCode::LOCKED)).context(concat!(
- "In check_and_migrate: Cannot migrate super key of this ",
+ "In check_and_import: Cannot import super key of this ",
"key while user is locked."
));
} else {
self.legacy_loader.remove_keystore_entry(uid, &alias).context(
concat!(
- "In check_and_migrate: ",
+ "In check_and_import: ",
"Trying to remove obsolete key."
),
)?;
return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND))
- .context("In check_and_migrate: Obsolete key.");
+ .context("In check_and_import: Obsolete key.");
}
}
};
@@ -505,18 +505,18 @@
BlobValue::Decrypted(data) => (LegacyBlob::ZVec(data), BlobMetaData::new()),
_ => {
return Err(Error::Rc(ResponseCode::KEY_NOT_FOUND))
- .context("In check_and_migrate: Legacy key has unexpected type.")
+ .context("In check_and_import: Legacy key has unexpected type.")
}
};
let km_uuid = self
.get_km_uuid(is_strongbox)
- .context("In check_and_migrate: Trying to get KM UUID")?;
+ .context("In check_and_import: Trying to get KM UUID")?;
blob_metadata.add(BlobMetaEntry::KmUuid(km_uuid));
let mut metadata = KeyMetaData::new();
let creation_date = DateTime::now()
- .context("In check_and_migrate: Trying to make creation time.")?;
+ .context("In check_and_import: Trying to make creation time.")?;
metadata.add(KeyMetaEntry::CreationDate(creation_date));
// Store legacy key in the database.
@@ -530,49 +530,49 @@
&metadata,
&km_uuid,
)
- .context("In check_and_migrate.")?;
+ .context("In check_and_import.")?;
Ok(())
}
None => {
if let Some(ca_cert) = ca_cert {
self.db
.store_new_certificate(&key, KeyType::Client, &ca_cert, &KEYSTORE_UUID)
- .context("In check_and_migrate: Failed to insert new certificate.")?;
+ .context("In check_and_import: Failed to insert new certificate.")?;
Ok(())
} else {
Err(Error::Rc(ResponseCode::KEY_NOT_FOUND))
- .context("In check_and_migrate: Legacy key not found.")
+ .context("In check_and_import: Legacy key not found.")
}
}
};
match result {
Ok(()) => {
- // Add the key to the migrated_keys list.
- self.recently_migrated.insert(RecentMigration::new(uid, alias.clone()));
+ // Add the key to the imported_keys list.
+ self.recently_imported.insert(RecentImport::new(uid, alias.clone()));
// Delete legacy key from the file system
self.legacy_loader
.remove_keystore_entry(uid, &alias)
- .context("In check_and_migrate: Trying to remove migrated key.")?;
+ .context("In check_and_import: Trying to remove imported key.")?;
Ok(())
}
Err(e) => Err(e),
}
}
- fn check_and_migrate_super_key(&mut self, user_id: u32, pw: &Password) -> Result<()> {
- if self.recently_migrated_super_key.contains(&user_id) {
+ fn check_and_import_super_key(&mut self, user_id: u32, pw: &Password) -> Result<()> {
+ if self.recently_imported_super_key.contains(&user_id) {
return Ok(());
}
if let Some(super_key) = self
.legacy_loader
.load_super_key(user_id, pw)
- .context("In check_and_migrate_super_key: Trying to load legacy super key.")?
+ .context("In check_and_import_super_key: Trying to load legacy super key.")?
{
let (blob, blob_metadata) =
crate::super_key::SuperKeyManager::encrypt_with_password(&super_key, pw)
- .context("In check_and_migrate_super_key: Trying to encrypt super key.")?;
+ .context("In check_and_import_super_key: Trying to encrypt super key.")?;
self.db
.store_super_key(
@@ -583,20 +583,20 @@
&KeyMetaData::new(),
)
.context(concat!(
- "In check_and_migrate_super_key: ",
+ "In check_and_import_super_key: ",
"Trying to insert legacy super_key into the database."
))?;
self.legacy_loader.remove_super_key(user_id);
- self.recently_migrated_super_key.insert(user_id);
+ self.recently_imported_super_key.insert(user_id);
Ok(())
} else {
Err(Error::Rc(ResponseCode::KEY_NOT_FOUND))
- .context("In check_and_migrate_super_key: No key found do migrate.")
+ .context("In check_and_import_super_key: No key found do import.")
}
}
- /// Key migrator request to be run by do_serialized.
- /// See LegacyMigrator::bulk_delete_uid and LegacyMigrator::bulk_delete_user.
+ /// Key importer request to be run by do_serialized.
+ /// See LegacyImporter::bulk_delete_uid and LegacyImporter::bulk_delete_user.
fn bulk_delete(
&mut self,
bulk_delete_request: BulkDeleteRequest,
@@ -695,21 +695,21 @@
self.legacy_loader
.remove_keystore_entry(uid, &alias)
- .context("In bulk_delete: Trying to remove migrated key.")?;
+ .context("In bulk_delete: Trying to remove imported key.")?;
}
Ok(())
}
fn has_super_key(&mut self, user_id: u32) -> Result<bool> {
- Ok(self.recently_migrated_super_key.contains(&user_id)
+ Ok(self.recently_imported_super_key.contains(&user_id)
|| self.legacy_loader.has_super_key(user_id))
}
fn check_empty(&self) -> u8 {
if self.legacy_loader.is_empty().unwrap_or(false) {
- LegacyMigrator::STATE_EMPTY
+ LegacyImporter::STATE_EMPTY
} else {
- LegacyMigrator::STATE_READY
+ LegacyImporter::STATE_READY
}
}
}
diff --git a/keystore2/src/lib.rs b/keystore2/src/lib.rs
index 134f707..4a23843 100644
--- a/keystore2/src/lib.rs
+++ b/keystore2/src/lib.rs
@@ -29,7 +29,7 @@
/// Internal Representation of Key Parameter and convenience functions.
pub mod key_parameter;
pub mod legacy_blob;
-pub mod legacy_migrator;
+pub mod legacy_importer;
pub mod maintenance;
pub mod metrics;
pub mod metrics_store;
@@ -45,6 +45,7 @@
mod attestation_key_utils;
mod audit_log;
mod gc;
+mod km_compat;
mod super_key;
#[cfg(feature = "watchdog")]
diff --git a/keystore2/src/maintenance.rs b/keystore2/src/maintenance.rs
index 9925e42..71f43d6 100644
--- a/keystore2/src/maintenance.rs
+++ b/keystore2/src/maintenance.rs
@@ -19,7 +19,7 @@
use crate::error::map_or_log_err;
use crate::error::Error;
use crate::globals::get_keymint_device;
-use crate::globals::{DB, LEGACY_MIGRATOR, SUPER_KEY};
+use crate::globals::{DB, LEGACY_IMPORTER, SUPER_KEY};
use crate::permission::{KeyPerm, KeystorePerm};
use crate::super_key::{SuperKeyManager, UserState};
use crate::utils::{
@@ -88,7 +88,7 @@
.with(|db| {
skm.reset_or_init_user_and_get_user_state(
&mut db.borrow_mut(),
- &LEGACY_MIGRATOR,
+ &LEGACY_IMPORTER,
user_id as u32,
password.as_ref(),
)
@@ -115,7 +115,7 @@
DB.with(|db| {
SUPER_KEY.write().unwrap().reset_user(
&mut db.borrow_mut(),
- &LEGACY_MIGRATOR,
+ &LEGACY_IMPORTER,
user_id as u32,
false,
)
@@ -130,7 +130,7 @@
// Permission check. Must return on error. Do not touch the '?'.
check_keystore_permission(KeystorePerm::ClearUID).context("In clear_namespace.")?;
- LEGACY_MIGRATOR
+ LEGACY_IMPORTER
.bulk_delete_uid(domain, nspace)
.context("In clear_namespace: Trying to delete legacy keys.")?;
DB.with(|db| db.borrow_mut().unbind_keys_for_namespace(domain, nspace))
@@ -148,7 +148,7 @@
.with(|db| {
SUPER_KEY.read().unwrap().get_user_state(
&mut db.borrow_mut(),
- &LEGACY_MIGRATOR,
+ &LEGACY_IMPORTER,
user_id as u32,
)
})
@@ -235,7 +235,7 @@
}
_ => {
return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
- "In migrate_key_namespace:
+ "In migrate_key_namespace: \
Source domain must be one of APP, SELINUX, or KEY_ID.",
)
}
@@ -249,15 +249,15 @@
}
_ => {
return Err(Error::Rc(ResponseCode::INVALID_ARGUMENT)).context(
- "In migrate_key_namespace:
+ "In migrate_key_namespace: \
Destination domain must be one of APP or SELINUX.",
)
}
};
DB.with(|db| {
- let (key_id_guard, _) = LEGACY_MIGRATOR
- .with_try_migrate(source, src_uid, || {
+ let (key_id_guard, _) = LEGACY_IMPORTER
+ .with_try_import(source, src_uid, || {
db.borrow_mut().load_key_entry(
source,
KeyType::Client,
diff --git a/keystore2/src/security_level.rs b/keystore2/src/security_level.rs
index 83f0bee..eefbc20 100644
--- a/keystore2/src/security_level.rs
+++ b/keystore2/src/security_level.rs
@@ -20,7 +20,7 @@
};
use crate::database::{CertificateInfo, KeyIdGuard};
use crate::error::{self, map_km_error, map_or_log_err, Error, ErrorCode};
-use crate::globals::{DB, ENFORCEMENTS, LEGACY_MIGRATOR, SUPER_KEY};
+use crate::globals::{DB, ENFORCEMENTS, LEGACY_IMPORTER, SUPER_KEY};
use crate::key_parameter::KeyParameter as KsKeyParam;
use crate::key_parameter::KeyParameterValue as KsKeyParamValue;
use crate::metrics_store::log_key_creation_event_stats;
@@ -164,7 +164,7 @@
.unwrap()
.handle_super_encryption_on_key_init(
&mut db,
- &LEGACY_MIGRATOR,
+ &LEGACY_IMPORTER,
&(key.domain),
&key_parameters,
flags,
@@ -245,7 +245,7 @@
_ => {
let (key_id_guard, mut key_entry) = DB
.with::<_, Result<(KeyIdGuard, KeyEntry)>>(|db| {
- LEGACY_MIGRATOR.with_try_migrate(key, caller_uid, || {
+ LEGACY_IMPORTER.with_try_import(key, caller_uid, || {
db.borrow_mut().load_key_entry(
key,
KeyType::Client,
@@ -723,7 +723,7 @@
let (wrapping_key_id_guard, mut wrapping_key_entry) = DB
.with(|db| {
- LEGACY_MIGRATOR.with_try_migrate(&key, caller_uid, || {
+ LEGACY_IMPORTER.with_try_import(&key, caller_uid, || {
db.borrow_mut().load_key_entry(
wrapping_key,
KeyType::Client,
diff --git a/keystore2/src/service.rs b/keystore2/src/service.rs
index 2725dc2..46bc8b0 100644
--- a/keystore2/src/service.rs
+++ b/keystore2/src/service.rs
@@ -26,7 +26,7 @@
};
use crate::{
database::Uuid,
- globals::{create_thread_local_db, DB, LEGACY_BLOB_LOADER, LEGACY_MIGRATOR},
+ globals::{create_thread_local_db, DB, LEGACY_BLOB_LOADER, LEGACY_IMPORTER},
};
use crate::{database::KEYSTORE_UUID, permission};
use crate::{
@@ -81,7 +81,7 @@
}
let uuid_by_sec_level = result.uuid_by_sec_level.clone();
- LEGACY_MIGRATOR
+ LEGACY_IMPORTER
.set_init(move || {
(create_thread_local_db(), uuid_by_sec_level, LEGACY_BLOB_LOADER.clone())
})
@@ -132,7 +132,7 @@
let caller_uid = ThreadState::get_calling_uid();
let (key_id_guard, mut key_entry) = DB
.with(|db| {
- LEGACY_MIGRATOR.with_try_migrate(key, caller_uid, || {
+ LEGACY_IMPORTER.with_try_import(key, caller_uid, || {
db.borrow_mut().load_key_entry(
key,
KeyType::Client,
@@ -183,7 +183,7 @@
) -> Result<()> {
let caller_uid = ThreadState::get_calling_uid();
DB.with::<_, Result<()>>(|db| {
- let entry = match LEGACY_MIGRATOR.with_try_migrate(key, caller_uid, || {
+ let entry = match LEGACY_IMPORTER.with_try_import(key, caller_uid, || {
db.borrow_mut().load_key_entry(
key,
KeyType::Client,
@@ -292,7 +292,7 @@
fn delete_key(&self, key: &KeyDescriptor) -> Result<()> {
let caller_uid = ThreadState::get_calling_uid();
DB.with(|db| {
- LEGACY_MIGRATOR.with_try_migrate(key, caller_uid, || {
+ LEGACY_IMPORTER.with_try_import(key, caller_uid, || {
db.borrow_mut().unbind_key(key, KeyType::Client, caller_uid, |k, av| {
check_key_permission(KeyPerm::Delete, k, &av).context("During delete_key.")
})
@@ -310,7 +310,7 @@
) -> Result<KeyDescriptor> {
let caller_uid = ThreadState::get_calling_uid();
DB.with(|db| {
- LEGACY_MIGRATOR.with_try_migrate(key, caller_uid, || {
+ LEGACY_IMPORTER.with_try_import(key, caller_uid, || {
db.borrow_mut().grant(
key,
caller_uid,
diff --git a/keystore2/src/super_key.rs b/keystore2/src/super_key.rs
index 6862011..2fb4991 100644
--- a/keystore2/src/super_key.rs
+++ b/keystore2/src/super_key.rs
@@ -26,7 +26,7 @@
error::ResponseCode,
key_parameter::{KeyParameter, KeyParameterValue},
legacy_blob::LegacyBlobLoader,
- legacy_migrator::LegacyMigrator,
+ legacy_importer::LegacyImporter,
raw_device::KeyMintDevice,
utils::watchdog as wd,
utils::AID_KEYSTORE,
@@ -507,7 +507,7 @@
fn super_key_exists_in_db_for_user(
&self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
user_id: UserId,
) -> Result<bool> {
let key_in_db = db
@@ -517,7 +517,7 @@
if key_in_db {
Ok(key_in_db)
} else {
- legacy_migrator
+ legacy_importer
.has_super_key(user_id)
.context("In super_key_exists_in_db_for_user: Trying to query legacy db.")
}
@@ -529,13 +529,13 @@
pub fn check_and_unlock_super_key(
&mut self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
user_id: UserId,
pw: &Password,
) -> Result<UserState> {
let alias = &USER_SUPER_KEY;
- let result = legacy_migrator
- .with_try_migrate_super_key(user_id, pw, || db.load_super_key(alias, user_id))
+ let result = legacy_importer
+ .with_try_import_super_key(user_id, pw, || db.load_super_key(alias, user_id))
.context("In check_and_unlock_super_key. Failed to load super key")?;
match result {
@@ -558,12 +558,12 @@
pub fn check_and_initialize_super_key(
&mut self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
user_id: UserId,
pw: Option<&Password>,
) -> Result<UserState> {
let super_key_exists_in_db = self
- .super_key_exists_in_db_for_user(db, legacy_migrator, user_id)
+ .super_key_exists_in_db_for_user(db, legacy_importer, user_id)
.context("In check_and_initialize_super_key. Failed to check if super key exists.")?;
if super_key_exists_in_db {
Ok(UserState::LskfLocked)
@@ -691,12 +691,12 @@
fn super_encrypt_on_key_init(
&self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
user_id: UserId,
key_blob: &[u8],
) -> Result<(Vec<u8>, BlobMetaData)> {
match self
- .get_user_state(db, legacy_migrator, user_id)
+ .get_user_state(db, legacy_importer, user_id)
.context("In super_encrypt. Failed to get user state.")?
{
UserState::LskfUnlocked(super_key) => {
@@ -737,7 +737,7 @@
pub fn handle_super_encryption_on_key_init(
&self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
domain: &Domain,
key_parameters: &[KeyParameter],
flags: Option<i32>,
@@ -747,7 +747,7 @@
match Enforcements::super_encryption_required(domain, key_parameters, flags) {
SuperEncryptionType::None => Ok((key_blob.to_vec(), BlobMetaData::new())),
SuperEncryptionType::LskfBound => self
- .super_encrypt_on_key_init(db, legacy_migrator, user_id, key_blob)
+ .super_encrypt_on_key_init(db, legacy_importer, user_id, key_blob)
.context(concat!(
"In handle_super_encryption_on_key_init. ",
"Failed to super encrypt with LskfBound key."
@@ -1086,11 +1086,11 @@
/// Returns the keystore locked state of the given user. It requires the thread local
/// keystore database and a reference to the legacy migrator because it may need to
- /// migrate the super key from the legacy blob database to the keystore database.
+ /// import the super key from the legacy blob database to the keystore database.
pub fn get_user_state(
&self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
user_id: UserId,
) -> Result<UserState> {
match self.get_per_boot_key_by_user_id(user_id) {
@@ -1099,7 +1099,7 @@
// Check if a super key exists in the database or legacy database.
// If so, return locked user state.
if self
- .super_key_exists_in_db_for_user(db, legacy_migrator, user_id)
+ .super_key_exists_in_db_for_user(db, legacy_importer, user_id)
.context("In get_user_state.")?
{
Ok(UserState::LskfLocked)
@@ -1123,7 +1123,7 @@
pub fn reset_or_init_user_and_get_user_state(
&mut self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
user_id: UserId,
password: Option<&Password>,
) -> Result<UserState> {
@@ -1131,7 +1131,7 @@
Some(_) if password.is_none() => {
// Transitioning to swiping, delete only the super key in database and cache,
// and super-encrypted keys in database (and in KM).
- self.reset_user(db, legacy_migrator, user_id, true).context(
+ self.reset_user(db, legacy_importer, user_id, true).context(
"In reset_or_init_user_and_get_user_state: Trying to delete keys from the db.",
)?;
// Lskf is now removed in Keystore.
@@ -1147,7 +1147,7 @@
// If so, return LskfLocked state.
// Otherwise, i) if the password is provided, initialize the super key and return
// LskfUnlocked state ii) if password is not provided, return Uninitialized state.
- self.check_and_initialize_super_key(db, legacy_migrator, user_id, password)
+ self.check_and_initialize_super_key(db, legacy_importer, user_id, password)
}
}
}
@@ -1158,7 +1158,7 @@
pub fn unlock_and_get_user_state(
&mut self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
user_id: UserId,
password: &Password,
) -> Result<UserState> {
@@ -1172,7 +1172,7 @@
// If not, return Uninitialized state.
// Otherwise, try to unlock the super key and if successful,
// return LskfUnlocked.
- self.check_and_unlock_super_key(db, legacy_migrator, user_id, password)
+ self.check_and_unlock_super_key(db, legacy_importer, user_id, password)
.context("In unlock_and_get_user_state. Failed to unlock super key.")
}
}
@@ -1184,12 +1184,12 @@
pub fn reset_user(
&mut self,
db: &mut KeystoreDB,
- legacy_migrator: &LegacyMigrator,
+ legacy_importer: &LegacyImporter,
user_id: UserId,
keep_non_super_encrypted_keys: bool,
) -> Result<()> {
// Mark keys created on behalf of the user as unreferenced.
- legacy_migrator
+ legacy_importer
.bulk_delete_user(user_id, keep_non_super_encrypted_keys)
.context("In reset_user: Trying to delete legacy keys.")?;
db.unbind_keys_for_user(user_id, keep_non_super_encrypted_keys)
diff --git a/keystore2/src/utils.rs b/keystore2/src/utils.rs
index 82e6700..c924bef 100644
--- a/keystore2/src/utils.rs
+++ b/keystore2/src/utils.rs
@@ -20,7 +20,7 @@
use crate::permission::{KeyPerm, KeyPermSet, KeystorePerm};
use crate::{
database::{KeyType, KeystoreDB},
- globals::LEGACY_MIGRATOR,
+ globals::LEGACY_IMPORTER,
};
use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
KeyCharacteristics::KeyCharacteristics, Tag::Tag,
@@ -211,7 +211,7 @@
) -> Result<Vec<KeyDescriptor>> {
let mut result = Vec::new();
result.append(
- &mut LEGACY_MIGRATOR
+ &mut LEGACY_IMPORTER
.list_uid(domain, namespace)
.context("In list_key_entries: Trying to list legacy keys.")?,
);