Merge changes I47a0f80e,I675cc9d6,Ic49c4515
* changes:
Specialize the KM context to use encrypted key blobs
Pass a VM secret to KeyMint from microdroid_manager
Strip out unused parts of keymint
diff --git a/microdroid/keymint/Android.bp b/microdroid/keymint/Android.bp
index 5a87145..6d651b9 100644
--- a/microdroid/keymint/Android.bp
+++ b/microdroid/keymint/Android.bp
@@ -25,6 +25,7 @@
"libkeymint",
"liblog",
"libpuresoftkeymasterdevice",
+ "libsoft_attestation_cert",
"libutils",
],
local_include_dirs: [
@@ -32,6 +33,7 @@
],
srcs: [
"MicrodroidKeyMintDevice.cpp",
+ "MicrodroidKeymasterContext.cpp",
"service.cpp",
],
}
diff --git a/microdroid/keymint/MicrodroidKeyMintDevice.cpp b/microdroid/keymint/MicrodroidKeyMintDevice.cpp
index 62d6942..c2f01f2 100644
--- a/microdroid/keymint/MicrodroidKeyMintDevice.cpp
+++ b/microdroid/keymint/MicrodroidKeyMintDevice.cpp
@@ -17,14 +17,16 @@
#define LOG_TAG "android.hardware.security.keymint-impl"
#include "MicrodroidKeyMintDevice.h"
+#include <AndroidKeyMintOperation.h>
+#include <KeyMintUtils.h>
#include <aidl/android/hardware/security/keymint/ErrorCode.h>
#include <android-base/logging.h>
#include <keymaster/android_keymaster.h>
#include <keymaster/contexts/pure_soft_keymaster_context.h>
#include <keymaster/keymaster_configuration.h>
-#include "AndroidKeyMintOperation.h"
-#include "KeyMintUtils.h"
+#include "MicrodroidKeyMintDevice.h"
+#include "MicrodroidKeymasterContext.h"
namespace aidl::android::hardware::security::keymint {
@@ -41,26 +43,11 @@
namespace {
-vector<KeyCharacteristics> convertKeyCharacteristics(SecurityLevel keyMintSecurityLevel,
- const AuthorizationSet& requestParams,
+vector<KeyCharacteristics> convertKeyCharacteristics(const AuthorizationSet& requestParams,
const AuthorizationSet& sw_enforced,
const AuthorizationSet& hw_enforced,
bool include_keystore_enforced = true) {
- KeyCharacteristics keyMintEnforced{keyMintSecurityLevel, {}};
-
- if (keyMintSecurityLevel != SecurityLevel::SOFTWARE) {
- // We're pretending to be TRUSTED_ENVIRONMENT or STRONGBOX.
- keyMintEnforced.authorizations = kmParamSet2Aidl(hw_enforced);
- if (include_keystore_enforced) {
- // Put all the software authorizations in the keystore list.
- KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE,
- kmParamSet2Aidl(sw_enforced)};
- return {std::move(keyMintEnforced), std::move(keystoreEnforced)};
- } else {
- return {std::move(keyMintEnforced)};
- }
- }
-
+ KeyCharacteristics keyMintEnforced{SecurityLevel::SOFTWARE, {}};
KeyCharacteristics keystoreEnforced{SecurityLevel::KEYSTORE, {}};
CHECK(hw_enforced.empty()) << "Hardware-enforced list is non-empty for pure SW KeyMint";
@@ -210,26 +197,22 @@
constexpr size_t kOperationTableSize = 16;
-MicrodroidKeyMintDevice::MicrodroidKeyMintDevice(SecurityLevel securityLevel)
+MicrodroidKeyMintDevice::MicrodroidKeyMintDevice(::keymaster::KeymasterKeyBlob& rootKey)
: impl_(new ::keymaster::AndroidKeymaster(
[&]() -> auto {
- auto context =
- new PureSoftKeymasterContext(KmVersion::KEYMINT_1,
- static_cast<keymaster_security_level_t>(
- securityLevel));
+ auto context = new MicrodroidKeymasterContext(KmVersion::KEYMINT_1, rootKey);
context->SetSystemVersion(::keymaster::GetOsVersion(),
::keymaster::GetOsPatchlevel());
return context;
}(),
- kOperationTableSize)),
- securityLevel_(securityLevel) {}
+ kOperationTableSize)) {}
MicrodroidKeyMintDevice::~MicrodroidKeyMintDevice() {}
ScopedAStatus MicrodroidKeyMintDevice::getHardwareInfo(KeyMintHardwareInfo* info) {
info->versionNumber = 1;
- info->securityLevel = securityLevel_;
- info->keyMintName = "FakeKeyMintDevice";
+ info->securityLevel = SecurityLevel::SOFTWARE;
+ info->keyMintName = "MicrodroidKeyMintDevice";
info->keyMintAuthorName = "Google";
info->timestampTokenRequired = false;
return ScopedAStatus::ok();
@@ -280,7 +263,7 @@
creationResult->keyBlob = kmBlob2vector(response.key_blob);
creationResult->keyCharacteristics =
- convertKeyCharacteristics(securityLevel_, request.key_description, response.unenforced,
+ convertKeyCharacteristics(request.key_description, response.unenforced,
response.enforced);
creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
return ScopedAStatus::ok();
@@ -312,7 +295,7 @@
creationResult->keyBlob = kmBlob2vector(response.key_blob);
creationResult->keyCharacteristics =
- convertKeyCharacteristics(securityLevel_, request.key_description, response.unenforced,
+ convertKeyCharacteristics(request.key_description, response.unenforced,
response.enforced);
creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
@@ -320,12 +303,9 @@
}
ScopedAStatus MicrodroidKeyMintDevice::importWrappedKey(
- const vector<uint8_t>& wrappedKeyData, //
- const vector<uint8_t>& wrappingKeyBlob, //
- const vector<uint8_t>& maskingKey, //
- const vector<KeyParameter>& unwrappingParams, //
- int64_t passwordSid, int64_t biometricSid, //
- KeyCreationResult* creationResult) {
+ const vector<uint8_t>& wrappedKeyData, const vector<uint8_t>& wrappingKeyBlob,
+ const vector<uint8_t>& maskingKey, const vector<KeyParameter>& unwrappingParams,
+ int64_t passwordSid, int64_t biometricSid, KeyCreationResult* creationResult) {
ImportWrappedKeyRequest request(impl_->message_version());
request.SetWrappedMaterial(wrappedKeyData.data(), wrappedKeyData.size());
request.SetWrappingMaterial(wrappingKeyBlob.data(), wrappingKeyBlob.size());
@@ -343,8 +323,8 @@
creationResult->keyBlob = kmBlob2vector(response.key_blob);
creationResult->keyCharacteristics =
- convertKeyCharacteristics(securityLevel_, request.additional_params,
- response.unenforced, response.enforced);
+ convertKeyCharacteristics(request.additional_params, response.unenforced,
+ response.enforced);
creationResult->certificateChain = convertCertificateChain(response.certificate_chain);
return ScopedAStatus::ok();
@@ -368,23 +348,14 @@
return ScopedAStatus::ok();
}
-ScopedAStatus MicrodroidKeyMintDevice::deleteKey(const vector<uint8_t>& keyBlob) {
- DeleteKeyRequest request(impl_->message_version());
- request.SetKeyMaterial(keyBlob.data(), keyBlob.size());
-
- DeleteKeyResponse response(impl_->message_version());
- impl_->DeleteKey(request, &response);
-
- return kmError2ScopedAStatus(response.error);
+ScopedAStatus MicrodroidKeyMintDevice::deleteKey(const vector<uint8_t>&) {
+ // There's nothing to be done to delete software key blobs.
+ return kmError2ScopedAStatus(KM_ERROR_OK);
}
ScopedAStatus MicrodroidKeyMintDevice::deleteAllKeys() {
// There's nothing to be done to delete software key blobs.
- DeleteAllKeysRequest request(impl_->message_version());
- DeleteAllKeysResponse response(impl_->message_version());
- impl_->DeleteAllKeys(request, &response);
-
- return kmError2ScopedAStatus(response.error);
+ return kmError2ScopedAStatus(KM_ERROR_OK);
}
ScopedAStatus MicrodroidKeyMintDevice::destroyAttestationIds() {
@@ -420,21 +391,13 @@
}
ScopedAStatus MicrodroidKeyMintDevice::deviceLocked(
- bool passwordOnly, const std::optional<secureclock::TimeStampToken>& timestampToken) {
- DeviceLockedRequest request(impl_->message_version());
- request.passwordOnly = passwordOnly;
- if (timestampToken.has_value()) {
- request.token.challenge = timestampToken->challenge;
- request.token.mac = {timestampToken->mac.data(), timestampToken->mac.size()};
- request.token.timestamp = timestampToken->timestamp.milliSeconds;
- }
- DeviceLockedResponse response = impl_->DeviceLocked(request);
- return kmError2ScopedAStatus(response.error);
+ bool, const std::optional<secureclock::TimeStampToken>&) {
+ // Microdroid doesn't yet have a concept of a locked device.
+ return kmError2ScopedAStatus(KM_ERROR_OK);
}
ScopedAStatus MicrodroidKeyMintDevice::earlyBootEnded() {
- EarlyBootEndedResponse response = impl_->EarlyBootEnded();
- return kmError2ScopedAStatus(response.error);
+ return kmError2ScopedAStatus(KM_ERROR_UNIMPLEMENTED);
}
ScopedAStatus MicrodroidKeyMintDevice::convertStorageKeyToEphemeral(
@@ -458,15 +421,11 @@
}
AuthorizationSet emptySet;
- *keyCharacteristics = convertKeyCharacteristics(securityLevel_, emptySet, response.unenforced,
- response.enforced,
- /* include_keystore_enforced = */ false);
+ *keyCharacteristics =
+ convertKeyCharacteristics(emptySet, response.unenforced, response.enforced,
+ /* include_keystore_enforced = */ false);
return ScopedAStatus::ok();
}
-IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel) {
- return ::new MicrodroidKeyMintDevice(securityLevel);
-}
-
} // namespace aidl::android::hardware::security::keymint
diff --git a/microdroid/keymint/MicrodroidKeymasterContext.cpp b/microdroid/keymint/MicrodroidKeymasterContext.cpp
new file mode 100644
index 0000000..b5440f3
--- /dev/null
+++ b/microdroid/keymint/MicrodroidKeymasterContext.cpp
@@ -0,0 +1,146 @@
+/*
+ * 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.
+ */
+
+#include "MicrodroidKeymasterContext.h"
+
+#include <android-base/logging.h>
+#include <keymaster/key.h>
+#include <keymaster/key_blob_utils/auth_encrypted_key_blob.h>
+#include <keymaster/key_blob_utils/software_keyblobs.h>
+
+using namespace ::keymaster;
+
+// This value is used for the ROOT_OF_TRUST tag which is only used in
+// attestation records which aren't supported in this implementation so a
+// constant doesn't cause any hard. MicroDroid SoftWare root-of-trust.
+static uint8_t SWROT[] = {'M', 'D', 'S', 'W'};
+static const KeymasterBlob microdroidSoftwareRootOfTrust(SWROT);
+
+keymaster_error_t MicrodroidKeymasterContext::CreateKeyBlob(const AuthorizationSet& key_description,
+ keymaster_key_origin_t origin,
+ const KeymasterKeyBlob& key_material,
+ KeymasterKeyBlob* blob,
+ AuthorizationSet* hw_enforced,
+ AuthorizationSet* sw_enforced) const {
+ keymaster_error_t error;
+
+ if (key_description.GetTagValue(TAG_ROLLBACK_RESISTANCE)) {
+ return KM_ERROR_ROLLBACK_RESISTANCE_UNAVAILABLE;
+ }
+
+ error = SetKeyBlobAuthorizations(key_description, origin, os_version_, os_patchlevel_,
+ hw_enforced, sw_enforced);
+ if (error != KM_ERROR_OK) return error;
+
+ AuthorizationSet hidden;
+ error = BuildHiddenAuthorizations(key_description, &hidden, microdroidSoftwareRootOfTrust);
+ if (error != KM_ERROR_OK) return error;
+
+ CHECK(hw_enforced->empty());
+
+ // Note that the authorizations included in the blob are not encrypted. This
+ // doesn't pose a problem for the current applications but may be a
+ // candidate for hardening.
+ auto encrypted_key = EncryptKey(key_material, AES_GCM_WITH_SW_ENFORCED, *hw_enforced,
+ *sw_enforced, hidden, root_key_, random_, &error);
+ if (error != KM_ERROR_OK) return error;
+
+ *blob = SerializeAuthEncryptedBlob(encrypted_key, *hw_enforced, *sw_enforced, &error);
+ return error;
+}
+
+keymaster_error_t MicrodroidKeymasterContext::ParseKeyBlob(
+ const KeymasterKeyBlob& blob, const AuthorizationSet& additional_params,
+ UniquePtr<Key>* key) const {
+ keymaster_error_t error;
+
+ AuthorizationSet hidden;
+ error = BuildHiddenAuthorizations(additional_params, &hidden, microdroidSoftwareRootOfTrust);
+ if (error != KM_ERROR_OK) return error;
+
+ auto deserialized_key = DeserializeAuthEncryptedBlob(blob, &error);
+ if (error != KM_ERROR_OK) return error;
+
+ keymaster_algorithm_t algorithm;
+ if (!deserialized_key.sw_enforced.GetTagValue(TAG_ALGORITHM, &algorithm)) {
+ return KM_ERROR_INVALID_ARGUMENT;
+ }
+
+ auto key_material = DecryptKey(deserialized_key, hidden, root_key_, &error);
+ if (error != KM_ERROR_OK) return error;
+
+ auto factory = GetKeyFactory(algorithm);
+ return factory->LoadKey(move(key_material), additional_params,
+ move(deserialized_key.hw_enforced), move(deserialized_key.sw_enforced),
+ key);
+}
+
+static bool UpgradeIntegerTag(keymaster_tag_t tag, uint32_t value, AuthorizationSet* set) {
+ int index = set->find(tag);
+ if (index == -1) {
+ keymaster_key_param_t param;
+ param.tag = tag;
+ param.integer = value;
+ set->push_back(param);
+ return true;
+ }
+
+ if (set->params[index].integer > value) return false;
+
+ if (set->params[index].integer != value) {
+ set->params[index].integer = value;
+ }
+ return true;
+}
+
+keymaster_error_t MicrodroidKeymasterContext::UpgradeKeyBlob(const KeymasterKeyBlob& key_to_upgrade,
+ const AuthorizationSet& upgrade_params,
+ KeymasterKeyBlob* upgraded_key) const {
+ UniquePtr<Key> key;
+ keymaster_error_t error = ParseKeyBlob(key_to_upgrade, upgrade_params, &key);
+ if (error != KM_ERROR_OK) return error;
+
+ if (os_version_ == 0) {
+ // We need to allow "upgrading" OS version to zero, to support upgrading from proper
+ // numbered releases to unnumbered development and preview releases.
+
+ int key_os_version_pos = key->sw_enforced().find(TAG_OS_VERSION);
+ if (key_os_version_pos != -1) {
+ uint32_t key_os_version = key->sw_enforced()[key_os_version_pos].integer;
+ if (key_os_version != 0) {
+ key->sw_enforced()[key_os_version_pos].integer = os_version_;
+ }
+ }
+ }
+
+ if (!UpgradeIntegerTag(TAG_OS_VERSION, os_version_, &key->sw_enforced()) ||
+ !UpgradeIntegerTag(TAG_OS_PATCHLEVEL, os_patchlevel_, &key->sw_enforced()))
+ // One of the version fields would have been a downgrade. Not allowed.
+ return KM_ERROR_INVALID_ARGUMENT;
+
+ AuthorizationSet hidden;
+ error = BuildHiddenAuthorizations(upgrade_params, &hidden, microdroidSoftwareRootOfTrust);
+ if (error != KM_ERROR_OK) return error;
+
+ auto encrypted_key =
+ EncryptKey(key->key_material(), AES_GCM_WITH_SW_ENFORCED, key->hw_enforced(),
+ key->sw_enforced(), hidden, root_key_, random_, &error);
+ if (error != KM_ERROR_OK) return error;
+
+ *upgraded_key = SerializeAuthEncryptedBlob(encrypted_key, key->hw_enforced(),
+ key->sw_enforced(), &error);
+ return error;
+}
diff --git a/microdroid/keymint/include/MicrodroidKeyMintDevice.h b/microdroid/keymint/include/MicrodroidKeyMintDevice.h
index 34d09bf..dec7baa 100644
--- a/microdroid/keymint/include/MicrodroidKeyMintDevice.h
+++ b/microdroid/keymint/include/MicrodroidKeyMintDevice.h
@@ -19,6 +19,7 @@
#include <aidl/android/hardware/security/keymint/BnKeyMintDevice.h>
#include <aidl/android/hardware/security/keymint/BnKeyMintOperation.h>
#include <aidl/android/hardware/security/keymint/HardwareAuthToken.h>
+#include <keymaster/android_keymaster_utils.h>
namespace keymaster {
class AndroidKeymaster;
@@ -34,7 +35,7 @@
class MicrodroidKeyMintDevice : public BnKeyMintDevice {
public:
- explicit MicrodroidKeyMintDevice(SecurityLevel securityLevel);
+ explicit MicrodroidKeyMintDevice(::keymaster::KeymasterKeyBlob& rootKey);
virtual ~MicrodroidKeyMintDevice();
ScopedAStatus getHardwareInfo(KeyMintHardwareInfo* info) override;
@@ -85,9 +86,6 @@
protected:
std::shared_ptr<::keymaster::AndroidKeymaster> impl_;
- SecurityLevel securityLevel_;
};
-IKeyMintDevice* CreateKeyMintDevice(SecurityLevel securityLevel);
-
} // namespace aidl::android::hardware::security::keymint
diff --git a/microdroid/keymint/include/MicrodroidKeymasterContext.h b/microdroid/keymint/include/MicrodroidKeymasterContext.h
new file mode 100644
index 0000000..636d240
--- /dev/null
+++ b/microdroid/keymint/include/MicrodroidKeymasterContext.h
@@ -0,0 +1,44 @@
+/*
+ * 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.
+ */
+
+#include <keymaster/contexts/pure_soft_keymaster_context.h>
+#include <keymaster/km_openssl/software_random_source.h>
+
+class MicrodroidKeymasterContext : public ::keymaster::PureSoftKeymasterContext {
+public:
+ explicit MicrodroidKeymasterContext(::keymaster::KmVersion version,
+ ::keymaster::KeymasterKeyBlob& root_key)
+ : PureSoftKeymasterContext(version, KM_SECURITY_LEVEL_SOFTWARE), root_key_(root_key) {}
+
+ keymaster_error_t CreateKeyBlob(const ::keymaster::AuthorizationSet& auths,
+ keymaster_key_origin_t origin,
+ const ::keymaster::KeymasterKeyBlob& key_material,
+ ::keymaster::KeymasterKeyBlob* blob,
+ ::keymaster::AuthorizationSet* hw_enforced,
+ ::keymaster::AuthorizationSet* sw_enforced) const override;
+
+ keymaster_error_t ParseKeyBlob(const ::keymaster::KeymasterKeyBlob& blob,
+ const ::keymaster::AuthorizationSet& additional_params,
+ ::keymaster::UniquePtr<::keymaster::Key>* key) const override;
+
+ keymaster_error_t UpgradeKeyBlob(const ::keymaster::KeymasterKeyBlob& key_to_upgrade,
+ const ::keymaster::AuthorizationSet& upgrade_params,
+ ::keymaster::KeymasterKeyBlob* upgraded_key) const override;
+
+private:
+ ::keymaster::SoftwareRandomSource random_;
+ ::keymaster::KeymasterKeyBlob root_key_;
+};
diff --git a/microdroid/keymint/service.cpp b/microdroid/keymint/service.cpp
index 2cdad0f..5fc0bd2 100644
--- a/microdroid/keymint/service.cpp
+++ b/microdroid/keymint/service.cpp
@@ -18,23 +18,91 @@
#include <AndroidKeyMintDevice.h>
#include <android-base/logging.h>
+#include <android-base/properties.h>
+#include <android-base/result.h>
#include <android/binder_manager.h>
#include <android/binder_process.h>
+#include <keymaster/android_keymaster_utils.h>
+#include <keymaster/mem.h>
#include <keymaster/soft_keymaster_logger.h>
+#include <openssl/digest.h>
+#include <openssl/hkdf.h>
+#include <openssl/is_boringssl.h>
+#include <openssl/sha.h>
#include "MicrodroidKeyMintDevice.h"
using aidl::android::hardware::security::keymint::MicrodroidKeyMintDevice;
using aidl::android::hardware::security::keymint::SecurityLevel;
+using android::base::Error;
+using android::base::GetProperty;
+using android::base::Result;
+
+using keymaster::KeymasterBlob;
+using keymaster::KeymasterKeyBlob;
+using keymaster::memset_s;
+
+namespace {
+
+template <typename T, class... Args>
+std::shared_ptr<T> addService(Args&&... args) {
+ std::shared_ptr<T> ser = ndk::SharedRefBase::make<T>(std::forward<Args>(args)...);
+ auto instanceName = std::string(T::descriptor) + "/default";
+ LOG(INFO) << "adding keymint service instance: " << instanceName;
+ binder_status_t status =
+ AServiceManager_addService(ser->asBinder().get(), instanceName.c_str());
+ CHECK(status == STATUS_OK);
+ return ser;
+}
+
+Result<KeymasterKeyBlob> getRootKey() {
+ const std::string prop = "ro.vmsecret.keymint";
+ const std::chrono::seconds timeout(15);
+ while (!android::base::WaitForPropertyCreation(prop, timeout)) {
+ LOG(WARNING) << "waited " << timeout.count() << "seconds for " << prop
+ << ", still waiting...";
+ }
+
+ // In a small effort to avoid spreading the secret around too widely in
+ // memory, move the secert into a buffer that will wipe itself and clear
+ // the original string.
+ std::string secretProp = GetProperty(prop, "");
+ KeymasterBlob secret(reinterpret_cast<const uint8_t*>(secretProp.data()), secretProp.size());
+ memset_s(secretProp.data(), 0, secretProp.size());
+ if (secret.size() < 64u) return Error() << "secret is too small";
+
+ // Derive the root key from the secret to avoid getting locked into using
+ // the secret directly.
+ KeymasterKeyBlob rootKey(SHA512_DIGEST_LENGTH);
+ const uint8_t kRootKeyIkm[] = "keymint_root_key";
+ const uint8_t* kNoSalt = nullptr;
+ const size_t kNoSaltLen = 0;
+ if (!HKDF(rootKey.writable_data(), rootKey.size(), EVP_sha512(), (uint8_t*)secret.begin(),
+ secret.size(), kNoSalt, kNoSaltLen, kRootKeyIkm, sizeof(kRootKeyIkm))) {
+ return Error() << "Failed to derive a key";
+ }
+ if (rootKey.size() < 64u) return Error() << "root key is too small";
+
+ LOG(INFO) << "root key obtained";
+ return rootKey;
+}
+
+} // namespace
+
int main() {
+ auto rootKey = getRootKey();
+ if (!rootKey.ok()) {
+ LOG(FATAL) << "Failed to get root key: " << rootKey.error();
+ }
+
// Zero threads seems like a useless pool, but below we'll join this thread
// to it, increasing the pool size to 1.
ABinderProcess_setThreadPoolMaxThreadCount(0);
// Add Keymint Service
std::shared_ptr<MicrodroidKeyMintDevice> keyMint =
- ndk::SharedRefBase::make<MicrodroidKeyMintDevice>(SecurityLevel::SOFTWARE);
+ ndk::SharedRefBase::make<MicrodroidKeyMintDevice>(*rootKey);
auto instanceName = std::string(MicrodroidKeyMintDevice::descriptor) + "/default";
LOG(INFO) << "adding keymint service instance: " << instanceName;
binder_status_t status =
diff --git a/microdroid/sepolicy/system/private/domain.te b/microdroid/sepolicy/system/private/domain.te
index 54423ec..da811ed 100644
--- a/microdroid/sepolicy/system/private/domain.te
+++ b/microdroid/sepolicy/system/private/domain.te
@@ -218,7 +218,7 @@
# workaround for supressing property accesses.
# TODO: remove these
-set_prop(domain, property_type)
+set_prop(domain, property_type -vmsecret_keymint_prop)
# auditallow { domain -init } property_type:property_service set;
# auditallow { domain -init } property_type:file rw_file_perms;
diff --git a/microdroid/sepolicy/system/private/microdroid_manager.te b/microdroid/sepolicy/system/private/microdroid_manager.te
index 781a5e1..074024f 100644
--- a/microdroid/sepolicy/system/private/microdroid_manager.te
+++ b/microdroid/sepolicy/system/private/microdroid_manager.te
@@ -23,6 +23,9 @@
# Let microdroid_manager kernel-log.
allow microdroid_manager kmsg_device:chr_file w_file_perms;
+# Let microdroid_manager initialize the derived VM secrets.
+set_prop(microdroid_manager, vmsecret_keymint_prop);
+
# Let microdroid_manager read a config file from /mnt/apk (fusefs)
# TODO(b/188400186) remove the below two rules
userdebug_or_eng(`
diff --git a/microdroid/sepolicy/system/private/property.te b/microdroid/sepolicy/system/private/property.te
new file mode 100644
index 0000000..d3d413e
--- /dev/null
+++ b/microdroid/sepolicy/system/private/property.te
@@ -0,0 +1,16 @@
+###
+### Neverallow rules
+###
+
+neverallow {
+ domain
+ -init
+ -microdroid_manager
+} vmsecret_keymint_prop:property_service set;
+
+neverallow {
+ domain
+ -init
+ -microdroid_manager
+ -hal_keymint_server
+} vmsecret_keymint_prop:file no_rw_file_perms;
diff --git a/microdroid/sepolicy/system/private/property_contexts b/microdroid/sepolicy/system/private/property_contexts
index deeb840..c8be9d9 100644
--- a/microdroid/sepolicy/system/private/property_contexts
+++ b/microdroid/sepolicy/system/private/property_contexts
@@ -50,6 +50,8 @@
ro.build.fingerprint u:object_r:fingerprint_prop:s0 exact string
+ro.vmsecret.keymint u:object_r:vmsecret_keymint_prop:s0 exact string
+
hwservicemanager.ready u:object_r:hwservicemanager_prop:s0 exact bool
apexd.status u:object_r:apexd_prop:s0 exact enum starting activated ready
diff --git a/microdroid/sepolicy/system/public/property.te b/microdroid/sepolicy/system/public/property.te
index 2f3255b..f5dc758 100644
--- a/microdroid/sepolicy/system/public/property.te
+++ b/microdroid/sepolicy/system/public/property.te
@@ -30,6 +30,7 @@
type shell_prop, property_type;
type usb_control_prop, property_type;
type vendor_default_prop, property_type;
+type vmsecret_keymint_prop, property_type;
allow property_type tmpfs:filesystem associate;
diff --git a/microdroid/sepolicy/vendor/hal_keymint_default.te b/microdroid/sepolicy/vendor/hal_keymint_default.te
index 9ddd787..359ca60 100644
--- a/microdroid/sepolicy/vendor/hal_keymint_default.te
+++ b/microdroid/sepolicy/vendor/hal_keymint_default.te
@@ -9,3 +9,5 @@
allow logd hal_keymint_default:dir search;
allow logd hal_keymint_default:file { getattr open read };
+
+get_prop(hal_keymint_default, vmsecret_keymint_prop);
diff --git a/microdroid_manager/Android.bp b/microdroid_manager/Android.bp
index 15c439b..902b5da 100644
--- a/microdroid_manager/Android.bp
+++ b/microdroid_manager/Android.bp
@@ -12,6 +12,7 @@
"libanyhow",
"libkernlog",
"libkeystore2_system_property-rust",
+ "liblibc",
"liblog_rust",
"libmicrodroid_metadata",
"libmicrodroid_payload_config",
diff --git a/microdroid_manager/src/main.rs b/microdroid_manager/src/main.rs
index d88ba1a..1506142 100644
--- a/microdroid_manager/src/main.rs
+++ b/microdroid_manager/src/main.rs
@@ -19,7 +19,7 @@
use anyhow::{anyhow, bail, Result};
use keystore2_system_property::PropertyWatcher;
-use log::{error, info};
+use log::{error, info, warn};
use microdroid_payload_config::{Task, TaskType, VmPayloadConfig};
use std::fs::{self, File};
use std::os::unix::io::{FromRawFd, IntoRawFd};
@@ -39,6 +39,11 @@
if !metadata.payload_config_path.is_empty() {
let config = load_config(Path::new(&metadata.payload_config_path))?;
+ let fake_secret = "This is a placeholder for a value that is derived from the images that are loaded in the VM.";
+ if let Err(err) = keystore2_system_property::write("ro.vmsecret.keymint", fake_secret) {
+ warn!("failed to set ro.vmsecret.keymint: {}", err);
+ }
+
// TODO(jooyung): wait until sys.boot_completed?
if let Some(main_task) = &config.task {
exec_task(main_task).map_err(|e| {