summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Crowley <paulcrowley@google.com>2021-08-06 15:16:10 -0700
committer[6;7~ <paulcrowley@google.com>2021-08-11 10:43:58 -0700
commit0f74bd4811c506269c2139a40af1f66e75871cd8 (patch)
treeab7ce0cea7df54eec1f789dae6c6d86fd2f57289
parent2ddc1338d7a400c972cc2bc46b4aa9a377c22a1e (diff)
downloadvold-0f74bd4811c506269c2139a40af1f66e75871cd8.tar.gz
Detect factory reset and deleteAllKeys
Where metadata encryption is enabled, if there is no metadata encryption key present and we are generating one anew, then there has been a factory reset, and this is the first key to be generated. We then call deleteAllKeys to ensure data from before the factory reset is securely deleted. This shouldn't really be necessary; the factory reset call itself should be doing this. However there are currently three factory reset paths (settings, recovery, fastboot -w) and it is not clear that all three are doing this correctly on all devices. Obviously an attacker can prevent this code from being run by running a version of the OS that does not include this change; however, if the bootloader is locked, then keys will be version bound such that they will only work on locked devices with a sufficiently recent version of the OS. If every sufficiently recent signed version of the OS includes this change the attack is defeated. Bug: 187105270 Test: booted Cuttlefish twice, checked logs Ignore-AOSP-First: no merge path to this branch from AOSP. Merged-In: I9c5c547140e8b1bbffb9c1d215f75251f0f1354e Change-Id: I9c5c547140e8b1bbffb9c1d215f75251f0f1354e
-rw-r--r--Keymaster.cpp13
-rw-r--r--Keymaster.h3
-rw-r--r--MetadataCrypt.cpp11
3 files changed, 27 insertions, 0 deletions
diff --git a/Keymaster.cpp b/Keymaster.cpp
index 80386818..23145504 100644
--- a/Keymaster.cpp
+++ b/Keymaster.cpp
@@ -230,5 +230,18 @@ void Keymaster::earlyBootEnded() {
logKeystore2ExceptionIfPresent(rc, "earlyBootEnded");
}
+void Keymaster::deleteAllKeys() {
+ ::ndk::SpAIBinder binder(AServiceManager_getService(maintenance_service_name));
+ auto maint_service = ks2_maint::IKeystoreMaintenance::fromBinder(binder);
+
+ if (!maint_service) {
+ LOG(ERROR) << "Unable to connect to keystore2 maintenance service for deleteAllKeys";
+ return;
+ }
+
+ auto rc = maint_service->deleteAllKeys();
+ logKeystore2ExceptionIfPresent(rc, "deleteAllKeys");
+}
+
} // namespace vold
} // namespace android
diff --git a/Keymaster.h b/Keymaster.h
index 1100840b..47bf4a26 100644
--- a/Keymaster.h
+++ b/Keymaster.h
@@ -127,6 +127,9 @@ class Keymaster {
// be created or used.
static void earlyBootEnded();
+ // Tell all Keymint devices to delete all rollback-protected keys.
+ static void deleteAllKeys();
+
private:
std::shared_ptr<ks2::IKeystoreSecurityLevel> securityLevel;
DISALLOW_COPY_AND_ASSIGN(Keymaster);
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index dc50679e..9038e8d5 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -112,6 +112,17 @@ static bool read_key(const std::string& metadata_key_dir, const KeyGeneration& g
auto dir = metadata_key_dir + "/key";
LOG(DEBUG) << "metadata_key_dir/key: " << dir;
if (!MkdirsSync(dir, 0700)) return false;
+ if (!pathExists(dir)) {
+ auto delete_all = android::base::GetBoolProperty(
+ "ro.crypto.metadata_init_delete_all_keys.enabled", false);
+ if (delete_all) {
+ LOG(INFO) << "Metadata key does not exist, calling deleteAllKeys";
+ Keymaster::deleteAllKeys();
+ } else {
+ LOG(DEBUG) << "Metadata key does not exist but "
+ "ro.crypto.metadata_init_delete_all_keys.enabled is false";
+ }
+ }
auto temp = metadata_key_dir + "/tmp";
return retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key);
}