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 Change-Id: I9c5c547140e8b1bbffb9c1d215f75251f0f1354e
This commit is contained in:
parent
85705f6c86
commit
1e6a5f5106
3 changed files with 27 additions and 0 deletions
13
Keystore.cpp
13
Keystore.cpp
|
@ -230,5 +230,18 @@ void Keystore::earlyBootEnded() {
|
||||||
logKeystore2ExceptionIfPresent(rc, "earlyBootEnded");
|
logKeystore2ExceptionIfPresent(rc, "earlyBootEnded");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Keystore::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 vold
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
|
@ -126,6 +126,9 @@ class Keystore {
|
||||||
// be created or used.
|
// be created or used.
|
||||||
static void earlyBootEnded();
|
static void earlyBootEnded();
|
||||||
|
|
||||||
|
// Tell all Keymint devices to delete all rollback-protected keys.
|
||||||
|
static void deleteAllKeys();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::shared_ptr<ks2::IKeystoreSecurityLevel> securityLevel;
|
std::shared_ptr<ks2::IKeystoreSecurityLevel> securityLevel;
|
||||||
DISALLOW_COPY_AND_ASSIGN(Keystore);
|
DISALLOW_COPY_AND_ASSIGN(Keystore);
|
||||||
|
|
|
@ -113,6 +113,17 @@ static bool read_key(const std::string& metadata_key_dir, const KeyGeneration& g
|
||||||
auto dir = metadata_key_dir + "/key";
|
auto dir = metadata_key_dir + "/key";
|
||||||
LOG(DEBUG) << "metadata_key_dir/key: " << dir;
|
LOG(DEBUG) << "metadata_key_dir/key: " << dir;
|
||||||
if (!MkdirsSync(dir, 0700)) return false;
|
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";
|
||||||
|
Keystore::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";
|
auto temp = metadata_key_dir + "/tmp";
|
||||||
return retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key);
|
return retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue