Merge "Add ROLLBACK_RESISTANCE tag to key usage" into sc-dev am: 8f19fd90e3
Original change: https://googleplex-android-review.googlesource.com/c/platform/system/vold/+/15534270
Change-Id: Ieaa3ce08c20df998a8141c77a7f771e40e1c6d0a
diff --git a/Android.bp b/Android.bp
index 84809a3..35f74bf 100644
--- a/Android.bp
+++ b/Android.bp
@@ -123,7 +123,7 @@
"KeyBuffer.cpp",
"KeyStorage.cpp",
"KeyUtil.cpp",
- "Keymaster.cpp",
+ "Keystore.cpp",
"Loop.cpp",
"MetadataCrypt.cpp",
"MoveStorage.cpp",
@@ -165,9 +165,9 @@
},
shared_libs: [
"android.hardware.health.storage@1.0",
- "android.hardware.health.storage-V1-ndk_platform",
- "android.system.keystore2-V1-ndk_platform",
- "android.security.maintenance-ndk_platform",
+ "android.hardware.health.storage-V1-ndk",
+ "android.system.keystore2-V1-ndk",
+ "android.security.maintenance-ndk",
"libbinder_ndk",
"libkeymint_support",
],
@@ -188,20 +188,18 @@
static_libs: ["libvold"],
init_rc: [
"vold.rc",
- "wait_for_keymaster.rc",
],
required: [
"mke2fs",
"vold_prepare_subdirs",
- "wait_for_keymaster",
],
shared_libs: [
"android.hardware.health.storage@1.0",
- "android.hardware.health.storage-V1-ndk_platform",
- "android.system.keystore2-V1-ndk_platform",
- "android.security.maintenance-ndk_platform",
+ "android.hardware.health.storage-V1-ndk",
+ "android.system.keystore2-V1-ndk",
+ "android.security.maintenance-ndk",
"libbinder_ndk",
"libkeymint_support",
],
@@ -222,11 +220,16 @@
name: "vdc",
defaults: ["vold_default_flags"],
- srcs: ["vdc.cpp"],
+ srcs: [
+ "vdc.cpp",
+ "Utils.cpp",
+ ],
shared_libs: [
"libbase",
"libbinder",
"libcutils",
+ "liblogwrap",
+ "libselinux",
"libutils",
],
static_libs: [
@@ -236,29 +239,6 @@
}
cc_binary {
- name: "wait_for_keymaster",
- defaults: ["vold_default_flags"],
-
- srcs: [
- "wait_for_keymaster.cpp",
- "Keymaster.cpp",
- ],
- shared_libs: [
- "libbase",
- "libbinder",
- "libbinder_ndk",
-
- "android.system.keystore2-V1-ndk_platform",
- "android.security.maintenance-ndk_platform",
- "libhardware",
- "libhardware_legacy",
- "libhidlbase",
- "libkeymint_support",
- "libutils",
- ],
-}
-
-cc_binary {
name: "secdiscard",
defaults: ["vold_default_flags"],
diff --git a/Devmapper.cpp b/Devmapper.cpp
index d55d92d..00fb4b3 100644
--- a/Devmapper.cpp
+++ b/Devmapper.cpp
@@ -94,8 +94,6 @@
PLOG(WARNING) << "Failed to destroy dm device named " << device.name();
}
}
- } else {
- LOG(DEBUG) << "Found unmanaged dm device named " << device.name();
}
}
return 0;
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 04def5c..017ffec 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -186,10 +186,7 @@
auto const current_path = get_ce_key_current_path(directory_path);
if (to_fix != current_path) {
LOG(DEBUG) << "Renaming " << to_fix << " to " << current_path;
- if (rename(to_fix.c_str(), current_path.c_str()) != 0) {
- PLOG(WARNING) << "Unable to rename " << to_fix << " to " << current_path;
- return;
- }
+ if (!android::vold::RenameKeyDir(to_fix, current_path)) return;
}
android::vold::FsyncDirectory(directory_path);
}
@@ -569,9 +566,12 @@
if (it != s_ephemeral_users.end()) {
s_ephemeral_users.erase(it);
} else {
- for (auto const path : get_ce_key_paths(get_ce_key_directory_path(user_id))) {
+ auto ce_path = get_ce_key_directory_path(user_id);
+ for (auto const path : get_ce_key_paths(ce_path)) {
success &= android::vold::destroyKey(path);
}
+ success &= destroy_dir(ce_path);
+
auto de_key_path = get_de_key_path(user_id);
if (android::vold::pathExists(de_key_path)) {
success &= android::vold::destroyKey(de_key_path);
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index 93c5c29..e84fe75 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -17,7 +17,7 @@
#include "KeyStorage.h"
#include "Checkpoint.h"
-#include "Keymaster.h"
+#include "Keystore.h"
#include "ScryptParameters.h"
#include "Utils.h"
@@ -123,51 +123,49 @@
SHA512_Final(reinterpret_cast<uint8_t*>(&(*res)[0]), &c);
}
-// Generates a keymaster key, using rollback resistance if supported.
-static bool generateKeymasterKey(Keymaster& keymaster,
- const km::AuthorizationSetBuilder& paramBuilder,
- std::string* key) {
+// Generates a keystore key, using rollback resistance if supported.
+static bool generateKeystoreKey(Keystore& keystore, const km::AuthorizationSetBuilder& paramBuilder,
+ std::string* key) {
auto paramsWithRollback = paramBuilder;
paramsWithRollback.Authorization(km::TAG_ROLLBACK_RESISTANCE);
- if (!keymaster.generateKey(paramsWithRollback, key)) {
- LOG(WARNING) << "Failed to generate rollback-resistant key. This is expected if keymaster "
+ if (!keystore.generateKey(paramsWithRollback, key)) {
+ LOG(WARNING) << "Failed to generate rollback-resistant key. This is expected if keystore "
"doesn't support rollback resistance. Falling back to "
"non-rollback-resistant key.";
- if (!keymaster.generateKey(paramBuilder, key)) return false;
+ if (!keystore.generateKey(paramBuilder, key)) return false;
}
return true;
}
-static bool generateKeyStorageKey(Keymaster& keymaster, const std::string& appId,
- std::string* key) {
+static bool generateKeyStorageKey(Keystore& keystore, const std::string& appId, std::string* key) {
auto paramBuilder = km::AuthorizationSetBuilder()
.AesEncryptionKey(AES_KEY_BYTES * 8)
.GcmModeMinMacLen(GCM_MAC_BYTES * 8)
.Authorization(km::TAG_APPLICATION_ID, appId)
.Authorization(km::TAG_NO_AUTH_REQUIRED);
LOG(DEBUG) << "Generating \"key storage\" key";
- return generateKeymasterKey(keymaster, paramBuilder, key);
+ return generateKeystoreKey(keystore, paramBuilder, key);
}
bool generateWrappedStorageKey(KeyBuffer* key) {
- Keymaster keymaster;
- if (!keymaster) return false;
+ Keystore keystore;
+ if (!keystore) return false;
std::string key_temp;
auto paramBuilder = km::AuthorizationSetBuilder().AesEncryptionKey(AES_KEY_BYTES * 8);
paramBuilder.Authorization(km::TAG_STORAGE_KEY);
- if (!generateKeymasterKey(keymaster, paramBuilder, &key_temp)) return false;
+ if (!generateKeystoreKey(keystore, paramBuilder, &key_temp)) return false;
*key = KeyBuffer(key_temp.size());
memcpy(reinterpret_cast<void*>(key->data()), key_temp.c_str(), key->size());
return true;
}
-bool exportWrappedStorageKey(const KeyBuffer& kmKey, KeyBuffer* key) {
- Keymaster keymaster;
- if (!keymaster) return false;
+bool exportWrappedStorageKey(const KeyBuffer& ksKey, KeyBuffer* key) {
+ Keystore keystore;
+ if (!keystore) return false;
std::string key_temp;
- if (!keymaster.exportKey(kmKey, &key_temp)) return false;
+ if (!keystore.exportKey(ksKey, &key_temp)) return false;
*key = KeyBuffer(key_temp.size());
memcpy(reinterpret_cast<void*>(key->data()), key_temp.c_str(), key->size());
return true;
@@ -213,14 +211,15 @@
static std::mutex key_upgrade_lock;
-// List of key directories that have had their Keymaster key upgraded during
+// List of key directories that have had their Keystore key upgraded during
// this boot and written to "keymaster_key_blob_upgraded", but replacing the old
// key was delayed due to an active checkpoint. Protected by key_upgrade_lock.
+// A directory can be in this list at most once.
static std::vector<std::string> key_dirs_to_commit;
// Replaces |dir|/keymaster_key_blob with |dir|/keymaster_key_blob_upgraded and
-// deletes the old key from Keymaster.
-static bool CommitUpgradedKey(Keymaster& keymaster, const std::string& dir) {
+// deletes the old key from Keystore.
+static bool CommitUpgradedKey(Keystore& keystore, const std::string& dir) {
auto blob_file = dir + "/" + kFn_keymaster_key_blob;
auto upgraded_blob_file = dir + "/" + kFn_keymaster_key_blob_upgraded;
@@ -231,13 +230,13 @@
PLOG(ERROR) << "Failed to rename " << upgraded_blob_file << " to " << blob_file;
return false;
}
- // Ensure that the rename is persisted before deleting the Keymaster key.
+ // Ensure that the rename is persisted before deleting the Keystore key.
if (!FsyncDirectory(dir)) return false;
- if (!keymaster || !keymaster.deleteKey(blob)) {
+ if (!keystore || !keystore.deleteKey(blob)) {
LOG(WARNING) << "Failed to delete old key " << blob_file
- << " from Keymaster; continuing anyway";
- // Continue on, but the space in Keymaster used by the old key won't be freed.
+ << " from Keystore; continuing anyway";
+ // Continue on, but the space in Keystore used by the old key won't be freed.
}
return true;
}
@@ -245,20 +244,20 @@
static void DeferredCommitKeys() {
android::base::WaitForProperty("vold.checkpoint_committed", "1");
LOG(INFO) << "Committing upgraded keys";
- Keymaster keymaster;
- if (!keymaster) {
- LOG(ERROR) << "Failed to open Keymaster; old keys won't be deleted from Keymaster";
- // Continue on, but the space in Keymaster used by the old keys won't be freed.
+ Keystore keystore;
+ if (!keystore) {
+ LOG(ERROR) << "Failed to open Keystore; old keys won't be deleted from Keystore";
+ // Continue on, but the space in Keystore used by the old keys won't be freed.
}
std::lock_guard<std::mutex> lock(key_upgrade_lock);
for (auto& dir : key_dirs_to_commit) {
LOG(INFO) << "Committing upgraded key " << dir;
- CommitUpgradedKey(keymaster, dir);
+ CommitUpgradedKey(keystore, dir);
}
key_dirs_to_commit.clear();
}
-// Returns true if the Keymaster key in |dir| has already been upgraded and is
+// Returns true if the Keystore key in |dir| has already been upgraded and is
// pending being committed. Assumes that key_upgrade_lock is held.
static bool IsKeyCommitPending(const std::string& dir) {
for (const auto& dir_to_commit : key_dirs_to_commit) {
@@ -267,8 +266,9 @@
return false;
}
-// Schedules the upgraded Keymaster key in |dir| to be committed later.
-// Assumes that key_upgrade_lock is held.
+// Schedules the upgraded Keystore key in |dir| to be committed later. Assumes
+// that key_upgrade_lock is held and that a commit isn't already pending for the
+// directory.
static void ScheduleKeyCommit(const std::string& dir) {
if (key_dirs_to_commit.empty()) std::thread(DeferredCommitKeys).detach();
key_dirs_to_commit.push_back(dir);
@@ -286,37 +286,41 @@
}
}
-// Renames a key directory. Also updates the deferred commit vector
-// (key_dirs_to_commit) appropriately.
-//
-// However, @old_name must be the path to the directory that was used to put that
-// directory into the deferred commit list in the first place (since this function
-// directly compares paths instead of using IsSameFile()).
-static bool RenameKeyDir(const std::string& old_name, const std::string& new_name) {
+bool RenameKeyDir(const std::string& old_name, const std::string& new_name) {
std::lock_guard<std::mutex> lock(key_upgrade_lock);
- if (rename(old_name.c_str(), new_name.c_str()) != 0) return false;
-
- // IsSameFile() doesn't work here since we just renamed @old_name.
- for (auto it = key_dirs_to_commit.begin(); it != key_dirs_to_commit.end(); it++) {
- if (*it == old_name) *it = new_name;
+ // Find the entry in key_dirs_to_commit (if any) for this directory so that
+ // we can update it if the rename succeeds. We don't allow duplicates in
+ // this list, so there can be at most one such entry.
+ auto it = key_dirs_to_commit.begin();
+ for (; it != key_dirs_to_commit.end(); it++) {
+ if (IsSameFile(old_name, *it)) break;
}
+
+ if (rename(old_name.c_str(), new_name.c_str()) != 0) {
+ PLOG(ERROR) << "Failed to rename key directory \"" << old_name << "\" to \"" << new_name
+ << "\"";
+ return false;
+ }
+
+ if (it != key_dirs_to_commit.end()) *it = new_name;
+
return true;
}
// Deletes a leftover upgraded key, if present. An upgraded key can be left
// over if an update failed, or if we rebooted before committing the key in a
// freak accident. Either way, we can re-upgrade the key if we need to.
-static void DeleteUpgradedKey(Keymaster& keymaster, const std::string& path) {
+static void DeleteUpgradedKey(Keystore& keystore, const std::string& path) {
if (pathExists(path)) {
LOG(DEBUG) << "Deleting leftover upgraded key " << path;
std::string blob;
if (!android::base::ReadFileToString(path, &blob)) {
LOG(WARNING) << "Failed to read leftover upgraded key " << path
<< "; continuing anyway";
- } else if (!keymaster.deleteKey(blob)) {
+ } else if (!keystore.deleteKey(blob)) {
LOG(WARNING) << "Failed to delete leftover upgraded key " << path
- << " from Keymaster; continuing anyway";
+ << " from Keystore; continuing anyway";
}
if (unlink(path.c_str()) != 0) {
LOG(WARNING) << "Failed to unlink leftover upgraded key " << path
@@ -325,11 +329,11 @@
}
}
-// Begins a Keymaster operation using the key stored in |dir|.
-static KeymasterOperation BeginKeymasterOp(Keymaster& keymaster, const std::string& dir,
- const km::AuthorizationSet& keyParams,
- const km::AuthorizationSet& opParams,
- km::AuthorizationSet* outParams) {
+// Begins a Keystore operation using the key stored in |dir|.
+static KeystoreOperation BeginKeystoreOp(Keystore& keystore, const std::string& dir,
+ const km::AuthorizationSet& keyParams,
+ const km::AuthorizationSet& opParams,
+ km::AuthorizationSet* outParams) {
km::AuthorizationSet inParams(keyParams);
inParams.append(opParams.begin(), opParams.end());
@@ -344,13 +348,13 @@
LOG(DEBUG)
<< blob_file
<< " was already upgraded and is waiting to be committed; using the upgraded blob";
- if (!readFileToString(upgraded_blob_file, &blob)) return KeymasterOperation();
+ if (!readFileToString(upgraded_blob_file, &blob)) return KeystoreOperation();
} else {
- DeleteUpgradedKey(keymaster, upgraded_blob_file);
- if (!readFileToString(blob_file, &blob)) return KeymasterOperation();
+ DeleteUpgradedKey(keystore, upgraded_blob_file);
+ if (!readFileToString(blob_file, &blob)) return KeystoreOperation();
}
- auto opHandle = keymaster.begin(blob, inParams, outParams);
+ auto opHandle = keystore.begin(blob, inParams, outParams);
if (!opHandle) return opHandle;
// If key blob wasn't upgraded, nothing left to do.
@@ -359,31 +363,31 @@
if (already_upgraded) {
LOG(ERROR) << "Unexpected case; already-upgraded key " << upgraded_blob_file
<< " still requires upgrade";
- return KeymasterOperation();
+ return KeystoreOperation();
}
LOG(INFO) << "Upgrading key: " << blob_file;
if (!writeStringToFile(*opHandle.getUpgradedBlob(), upgraded_blob_file))
- return KeymasterOperation();
+ return KeystoreOperation();
if (cp_needsCheckpoint()) {
LOG(INFO) << "Wrote upgraded key to " << upgraded_blob_file
<< "; delaying commit due to checkpoint";
ScheduleKeyCommit(dir);
} else {
- if (!CommitUpgradedKey(keymaster, dir)) return KeymasterOperation();
+ if (!CommitUpgradedKey(keystore, dir)) return KeystoreOperation();
LOG(INFO) << "Key upgraded: " << blob_file;
}
return opHandle;
}
-static bool encryptWithKeymasterKey(Keymaster& keymaster, const std::string& dir,
- const km::AuthorizationSet& keyParams,
- const KeyBuffer& message, std::string* ciphertext) {
+static bool encryptWithKeystoreKey(Keystore& keystore, const std::string& dir,
+ const km::AuthorizationSet& keyParams, const KeyBuffer& message,
+ std::string* ciphertext) {
km::AuthorizationSet opParams =
km::AuthorizationSetBuilder()
.Authorization(km::TAG_ROLLBACK_RESISTANCE)
.Authorization(km::TAG_PURPOSE, km::KeyPurpose::ENCRYPT);
km::AuthorizationSet outParams;
- auto opHandle = BeginKeymasterOp(keymaster, dir, keyParams, opParams, &outParams);
+ auto opHandle = BeginKeystoreOp(keystore, dir, keyParams, opParams, &outParams);
if (!opHandle) return false;
auto nonceBlob = outParams.GetTagValue(km::TAG_NONCE);
if (!nonceBlob) {
@@ -403,16 +407,16 @@
return true;
}
-static bool decryptWithKeymasterKey(Keymaster& keymaster, const std::string& dir,
- const km::AuthorizationSet& keyParams,
- const std::string& ciphertext, KeyBuffer* message) {
+static bool decryptWithKeystoreKey(Keystore& keystore, const std::string& dir,
+ const km::AuthorizationSet& keyParams,
+ const std::string& ciphertext, KeyBuffer* message) {
const std::string nonce = ciphertext.substr(0, GCM_NONCE_BYTES);
auto bodyAndMac = ciphertext.substr(GCM_NONCE_BYTES);
auto opParams = km::AuthorizationSetBuilder()
.Authorization(km::TAG_NONCE, nonce)
.Authorization(km::TAG_ROLLBACK_RESISTANCE)
.Authorization(km::TAG_PURPOSE, km::KeyPurpose::DECRYPT);
- auto opHandle = BeginKeymasterOp(keymaster, dir, keyParams, opParams, nullptr);
+ auto opHandle = BeginKeystoreOp(keystore, dir, keyParams, opParams, nullptr);
if (!opHandle) return false;
if (!opHandle.updateCompletely(bodyAndMac, message)) return false;
if (!opHandle.finish(nullptr)) return false;
@@ -420,7 +424,7 @@
}
static std::string getStretching(const KeyAuthentication& auth) {
- if (auth.usesKeymaster()) {
+ if (auth.usesKeystore()) {
return kStretch_nopassword;
} else {
return kStretch_none;
@@ -470,8 +474,8 @@
LOG(ERROR) << "Openssl error: " << ERR_get_error();
}
-static bool encryptWithoutKeymaster(const std::string& preKey, const KeyBuffer& plaintext,
- std::string* ciphertext) {
+static bool encryptWithoutKeystore(const std::string& preKey, const KeyBuffer& plaintext,
+ std::string* ciphertext) {
std::string key;
hashWithPrefix(kHashPrefix_keygen, preKey, &key);
key.resize(AES_KEY_BYTES);
@@ -520,8 +524,8 @@
return true;
}
-static bool decryptWithoutKeymaster(const std::string& preKey, const std::string& ciphertext,
- KeyBuffer* plaintext) {
+static bool decryptWithoutKeystore(const std::string& preKey, const std::string& ciphertext,
+ KeyBuffer* plaintext) {
if (ciphertext.size() < GCM_NONCE_BYTES + GCM_MAC_BYTES) {
LOG(ERROR) << "GCM ciphertext too small: " << ciphertext.size();
return false;
@@ -572,7 +576,12 @@
return true;
}
-bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBuffer& key) {
+// Creates a directory at the given path |dir| and stores |key| in it, in such a
+// way that it can only be retrieved via Keystore (if no secret is given in
+// |auth|) or with the given secret (if a secret is given in |auth|), and can be
+// securely deleted. If a storage binding seed has been set, then the storage
+// binding seed will be required to retrieve the key as well.
+static bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBuffer& key) {
if (TEMP_FAILURE_RETRY(mkdir(dir.c_str(), 0700)) == -1) {
PLOG(ERROR) << "key mkdir " << dir;
return false;
@@ -585,16 +594,16 @@
std::string appId;
if (!generateAppId(auth, stretching, secdiscardable_hash, &appId)) return false;
std::string encryptedKey;
- if (auth.usesKeymaster()) {
- Keymaster keymaster;
- if (!keymaster) return false;
- std::string kmKey;
- if (!generateKeyStorageKey(keymaster, appId, &kmKey)) return false;
- if (!writeStringToFile(kmKey, dir + "/" + kFn_keymaster_key_blob)) return false;
+ if (auth.usesKeystore()) {
+ Keystore keystore;
+ if (!keystore) return false;
+ std::string ksKey;
+ if (!generateKeyStorageKey(keystore, appId, &ksKey)) return false;
+ if (!writeStringToFile(ksKey, dir + "/" + kFn_keymaster_key_blob)) return false;
km::AuthorizationSet keyParams = beginParams(appId);
- if (!encryptWithKeymasterKey(keymaster, dir, keyParams, key, &encryptedKey)) return false;
+ if (!encryptWithKeystoreKey(keystore, dir, keyParams, key, &encryptedKey)) return false;
} else {
- if (!encryptWithoutKeymaster(appId, key, &encryptedKey)) return false;
+ if (!encryptWithoutKeystore(appId, key, &encryptedKey)) return false;
}
if (!writeStringToFile(encryptedKey, dir + "/" + kFn_encrypted_key)) return false;
if (!FsyncDirectory(dir)) return false;
@@ -613,10 +622,8 @@
}
if (!storeKey(tmp_path, auth, key)) return false;
- if (!RenameKeyDir(tmp_path, key_path)) {
- PLOG(ERROR) << "Unable to move new key to location: " << key_path;
- return false;
- }
+ if (!RenameKeyDir(tmp_path, key_path)) return false;
+
if (!FsyncParentDirectory(key_path)) return false;
LOG(DEBUG) << "Created key: " << key_path;
return true;
@@ -637,25 +644,24 @@
if (!generateAppId(auth, stretching, secdiscardable_hash, &appId)) return false;
std::string encryptedMessage;
if (!readFileToString(dir + "/" + kFn_encrypted_key, &encryptedMessage)) return false;
- if (auth.usesKeymaster()) {
- Keymaster keymaster;
- if (!keymaster) return false;
+ if (auth.usesKeystore()) {
+ Keystore keystore;
+ if (!keystore) return false;
km::AuthorizationSet keyParams = beginParams(appId);
- if (!decryptWithKeymasterKey(keymaster, dir, keyParams, encryptedMessage, key))
- return false;
+ if (!decryptWithKeystoreKey(keystore, dir, keyParams, encryptedMessage, key)) return false;
} else {
- if (!decryptWithoutKeymaster(appId, encryptedMessage, key)) return false;
+ if (!decryptWithoutKeystore(appId, encryptedMessage, key)) return false;
}
return true;
}
-static bool DeleteKeymasterKey(const std::string& blob_file) {
+static bool DeleteKeystoreKey(const std::string& blob_file) {
std::string blob;
if (!readFileToString(blob_file, &blob)) return false;
- Keymaster keymaster;
- if (!keymaster) return false;
- LOG(DEBUG) << "Deleting key " << blob_file << " from Keymaster";
- if (!keymaster.deleteKey(blob)) return false;
+ Keystore keystore;
+ if (!keystore) return false;
+ LOG(DEBUG) << "Deleting key " << blob_file << " from Keystore";
+ if (!keystore.deleteKey(blob)) return false;
return true;
}
@@ -691,7 +697,7 @@
for (auto& fn : {kFn_keymaster_key_blob, kFn_keymaster_key_blob_upgraded}) {
auto blob_file = dir + "/" + fn;
if (pathExists(blob_file)) {
- success &= DeleteKeymasterKey(blob_file);
+ success &= DeleteKeystoreKey(blob_file);
secdiscard_cmd.push_back(blob_file);
}
}
diff --git a/KeyStorage.h b/KeyStorage.h
index e318959..cc2f549 100644
--- a/KeyStorage.h
+++ b/KeyStorage.h
@@ -31,7 +31,7 @@
public:
KeyAuthentication(const std::string& s) : secret{s} {};
- bool usesKeymaster() const { return secret.empty(); };
+ bool usesKeystore() const { return secret.empty(); };
const std::string secret;
};
@@ -41,11 +41,9 @@
bool createSecdiscardable(const std::string& path, std::string* hash);
bool readSecdiscardable(const std::string& path, std::string* hash);
-// Create a directory at the named path, and store "key" in it,
-// in such a way that it can only be retrieved via Keymaster and
-// can be securely deleted.
-// It's safe to move/rename the directory after creation.
-bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBuffer& key);
+// Renames a key directory while also managing deferred commits appropriately.
+// This method should be used whenever a key directory needs to be moved/renamed.
+bool RenameKeyDir(const std::string& old_name, const std::string& new_name);
// Create a directory at the named path, and store "key" in it as storeKey
// This version creates the key in "tmp_path" then atomically renames "tmp_path"
@@ -63,10 +61,10 @@
bool runSecdiscardSingle(const std::string& file);
-// Generate wrapped storage key using keymaster. Uses STORAGE_KEY tag in keymaster.
+// Generate wrapped storage key using keystore. Uses STORAGE_KEY tag in keystore.
bool generateWrappedStorageKey(KeyBuffer* key);
-// Export the per-boot boot wrapped storage key using keymaster.
-bool exportWrappedStorageKey(const KeyBuffer& kmKey, KeyBuffer* key);
+// Export the per-boot boot wrapped storage key using keystore.
+bool exportWrappedStorageKey(const KeyBuffer& ksKey, KeyBuffer* key);
// Set a seed to be mixed into all key storage encryption keys.
bool setKeyStorageBindingSeed(const std::vector<uint8_t>& seed);
diff --git a/KeyUtil.cpp b/KeyUtil.cpp
index 886054e..2f9c876 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -36,6 +36,9 @@
namespace android {
namespace vold {
+using android::fscrypt::EncryptionOptions;
+using android::fscrypt::EncryptionPolicy;
+
const KeyGeneration neverGen() {
return KeyGeneration{0, false, false};
}
diff --git a/KeyUtil.h b/KeyUtil.h
index 73255a3..5940b8a 100644
--- a/KeyUtil.h
+++ b/KeyUtil.h
@@ -28,8 +28,6 @@
namespace android {
namespace vold {
-using namespace android::fscrypt;
-
// Description of how to generate a key when needed.
struct KeyGeneration {
size_t keysize;
@@ -63,8 +61,8 @@
//
// Returns %true on success, %false on failure. On success also sets *policy
// to the EncryptionPolicy used to refer to this key.
-bool installKey(const std::string& mountpoint, const EncryptionOptions& options,
- const KeyBuffer& key, EncryptionPolicy* policy);
+bool installKey(const std::string& mountpoint, const android::fscrypt::EncryptionOptions& options,
+ const KeyBuffer& key, android::fscrypt::EncryptionPolicy* policy);
// Evict a file-based encryption key from the kernel.
//
@@ -72,7 +70,7 @@
//
// If the kernel doesn't support the filesystem-level keyring, the caller is
// responsible for dropping caches.
-bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy);
+bool evictKey(const std::string& mountpoint, const android::fscrypt::EncryptionPolicy& policy);
// Retrieves the key from the named directory, or generates it if it doesn't
// exist.
@@ -82,7 +80,8 @@
// Re-installs a file-based encryption key of fscrypt-provisioning type from the
// global session keyring back into fs keyring of the mountpoint.
-bool reloadKeyFromSessionKeyring(const std::string& mountpoint, const EncryptionPolicy& policy);
+bool reloadKeyFromSessionKeyring(const std::string& mountpoint,
+ const android::fscrypt::EncryptionPolicy& policy);
} // namespace vold
} // namespace android
diff --git a/Keymaster.cpp b/Keystore.cpp
similarity index 88%
rename from Keymaster.cpp
rename to Keystore.cpp
index 2314550..a017d68 100644
--- a/Keymaster.cpp
+++ b/Keystore.cpp
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-#include "Keymaster.h"
+#include "Keystore.h"
#include <android-base/logging.h>
@@ -43,7 +43,7 @@
namespace ks2_maint = ::aidl::android::security::maintenance;
-KeymasterOperation::~KeymasterOperation() {
+KeystoreOperation::~KeystoreOperation() {
if (ks2Operation) ks2Operation->abort();
}
@@ -65,8 +65,8 @@
return true;
}
-bool KeymasterOperation::updateCompletely(const char* input, size_t inputLen,
- const std::function<void(const char*, size_t)> consumer) {
+bool KeystoreOperation::updateCompletely(const char* input, size_t inputLen,
+ const std::function<void(const char*, size_t)> consumer) {
if (!ks2Operation) return false;
while (inputLen != 0) {
@@ -87,7 +87,7 @@
return true;
}
-bool KeymasterOperation::finish(std::string* output) {
+bool KeystoreOperation::finish(std::string* output) {
std::optional<std::vector<uint8_t>> out_vec;
if (!ks2Operation) return false;
@@ -103,7 +103,7 @@
return true;
}
-Keymaster::Keymaster() {
+Keystore::Keystore() {
::ndk::SpAIBinder binder(AServiceManager_waitForService(keystore2_service_name));
auto keystore2Service = ks2::IKeystoreService::fromBinder(binder);
@@ -127,7 +127,7 @@
LOG(ERROR) << "Vold unable to get security level from keystore2.";
}
-bool Keymaster::generateKey(const km::AuthorizationSet& inParams, std::string* key) {
+bool Keystore::generateKey(const km::AuthorizationSet& inParams, std::string* key) {
ks2::KeyDescriptor in_key = {
.domain = ks2::Domain::BLOB,
.alias = std::nullopt,
@@ -150,14 +150,14 @@
return true;
}
-bool Keymaster::exportKey(const KeyBuffer& kmKey, std::string* key) {
+bool Keystore::exportKey(const KeyBuffer& ksKey, std::string* key) {
bool ret = false;
ks2::KeyDescriptor storageKey = {
.domain = ks2::Domain::BLOB,
.alias = std::nullopt,
.nspace = VOLD_NAMESPACE,
};
- storageKey.blob = std::make_optional<std::vector<uint8_t>>(kmKey.begin(), kmKey.end());
+ storageKey.blob = std::make_optional<std::vector<uint8_t>>(ksKey.begin(), ksKey.end());
ks2::EphemeralStorageKeyResponse ephemeral_key_response;
auto rc = securityLevel->convertStorageKeyToEphemeral(storageKey, &ephemeral_key_response);
@@ -175,7 +175,7 @@
return ret;
}
-bool Keymaster::deleteKey(const std::string& key) {
+bool Keystore::deleteKey(const std::string& key) {
ks2::KeyDescriptor keyDesc = {
.domain = ks2::Domain::BLOB,
.alias = std::nullopt,
@@ -188,8 +188,8 @@
return !logKeystore2ExceptionIfPresent(rc, "deleteKey");
}
-KeymasterOperation Keymaster::begin(const std::string& key, const km::AuthorizationSet& inParams,
- km::AuthorizationSet* outParams) {
+KeystoreOperation Keystore::begin(const std::string& key, const km::AuthorizationSet& inParams,
+ km::AuthorizationSet* outParams) {
ks2::KeyDescriptor keyDesc = {
.domain = ks2::Domain::BLOB,
.alias = std::nullopt,
@@ -202,22 +202,22 @@
auto rc = securityLevel->createOperation(keyDesc, inParams.vector_data(), true, &cor);
if (logKeystore2ExceptionIfPresent(rc, "createOperation")) {
if (rc.getExceptionCode() == EX_SERVICE_SPECIFIC)
- return KeymasterOperation((km::ErrorCode)rc.getServiceSpecificError());
+ return KeystoreOperation((km::ErrorCode)rc.getServiceSpecificError());
else
- return KeymasterOperation();
+ return KeystoreOperation();
}
if (!cor.iOperation) {
LOG(ERROR) << "keystore2 createOperation didn't return an operation";
- return KeymasterOperation();
+ return KeystoreOperation();
}
if (outParams && cor.parameters) *outParams = cor.parameters->keyParameter;
- return KeymasterOperation(cor.iOperation, cor.upgradedBlob);
+ return KeystoreOperation(cor.iOperation, cor.upgradedBlob);
}
-void Keymaster::earlyBootEnded() {
+void Keystore::earlyBootEnded() {
::ndk::SpAIBinder binder(AServiceManager_getService(maintenance_service_name));
auto maint_service = ks2_maint::IKeystoreMaintenance::fromBinder(binder);
@@ -230,7 +230,7 @@
logKeystore2ExceptionIfPresent(rc, "earlyBootEnded");
}
-void Keymaster::deleteAllKeys() {
+void Keystore::deleteAllKeys() {
::ndk::SpAIBinder binder(AServiceManager_getService(maintenance_service_name));
auto maint_service = ks2_maint::IKeystoreMaintenance::fromBinder(binder);
diff --git a/Keymaster.h b/Keystore.h
similarity index 81%
rename from Keymaster.h
rename to Keystore.h
index 47bf4a2..d8c488e 100644
--- a/Keymaster.h
+++ b/Keystore.h
@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-// TODO: Maybe "Keymaster" should be replaced with Keystore2 everywhere?
-#ifndef ANDROID_VOLD_KEYMASTER_H
-#define ANDROID_VOLD_KEYMASTER_H
+#ifndef ANDROID_VOLD_KEYSTORE_H
+#define ANDROID_VOLD_KEYSTORE_H
#include "KeyBuffer.h"
@@ -45,9 +44,9 @@
// ongoing Keystore2 operation. Aborts the operation
// in the destructor if it is unfinished. Methods log failures
// to LOG(ERROR).
-class KeymasterOperation {
+class KeystoreOperation {
public:
- ~KeymasterOperation();
+ ~KeystoreOperation();
// Is this instance valid? This is false if creation fails, and becomes
// false on finish or if an update fails.
explicit operator bool() const { return (bool)ks2Operation; }
@@ -66,11 +65,11 @@
// Finish and write the output to this string, unless pointer is null.
bool finish(std::string* output);
// Move constructor
- KeymasterOperation(KeymasterOperation&& rhs) { *this = std::move(rhs); }
+ KeystoreOperation(KeystoreOperation&& rhs) { *this = std::move(rhs); }
// Construct an object in an error state for error returns
- KeymasterOperation() { errorCode = km::ErrorCode::UNKNOWN_ERROR; }
+ KeystoreOperation() { errorCode = km::ErrorCode::UNKNOWN_ERROR; }
// Move Assignment
- KeymasterOperation& operator=(KeymasterOperation&& rhs) {
+ KeystoreOperation& operator=(KeystoreOperation&& rhs) {
ks2Operation = rhs.ks2Operation;
rhs.ks2Operation = nullptr;
@@ -84,8 +83,8 @@
}
private:
- KeymasterOperation(std::shared_ptr<ks2::IKeystoreOperation> ks2Op,
- std::optional<std::vector<uint8_t>> blob)
+ KeystoreOperation(std::shared_ptr<ks2::IKeystoreOperation> ks2Op,
+ std::optional<std::vector<uint8_t>> blob)
: ks2Operation{ks2Op}, errorCode{km::ErrorCode::OK} {
if (blob)
upgradedBlob = std::optional(std::string(blob->begin(), blob->end()));
@@ -93,7 +92,7 @@
upgradedBlob = std::nullopt;
}
- KeymasterOperation(km::ErrorCode errCode) : errorCode{errCode} {}
+ KeystoreOperation(km::ErrorCode errCode) : errorCode{errCode} {}
bool updateCompletely(const char* input, size_t inputLen,
const std::function<void(const char*, size_t)> consumer);
@@ -101,27 +100,27 @@
std::shared_ptr<ks2::IKeystoreOperation> ks2Operation;
std::optional<std::string> upgradedBlob;
km::ErrorCode errorCode;
- DISALLOW_COPY_AND_ASSIGN(KeymasterOperation);
- friend class Keymaster;
+ DISALLOW_COPY_AND_ASSIGN(KeystoreOperation);
+ friend class Keystore;
};
// Wrapper for keystore2 methods that vold uses.
-class Keymaster {
+class Keystore {
public:
- Keymaster();
+ Keystore();
// false if we failed to get a keystore2 security level.
explicit operator bool() { return (bool)securityLevel; }
// Generate a key using keystore2 from the given params.
bool generateKey(const km::AuthorizationSet& inParams, std::string* key);
// Exports a keystore2 key with STORAGE_KEY tag wrapped with a per-boot ephemeral key
- bool exportKey(const KeyBuffer& kmKey, std::string* key);
+ bool exportKey(const KeyBuffer& ksKey, std::string* key);
// If supported, permanently delete a key from the keymint device it belongs to.
bool deleteKey(const std::string& key);
// Begin a new cryptographic operation, collecting output parameters if pointer is non-null
- // If the key was upgraded as a result of a call to this method, the returned KeymasterOperation
+ // If the key was upgraded as a result of a call to this method, the returned KeystoreOperation
// also stores the upgraded key blob.
- KeymasterOperation begin(const std::string& key, const km::AuthorizationSet& inParams,
- km::AuthorizationSet* outParams);
+ KeystoreOperation begin(const std::string& key, const km::AuthorizationSet& inParams,
+ km::AuthorizationSet* outParams);
// Tell all Keymint devices that early boot has ended and early boot-only keys can no longer
// be created or used.
@@ -132,7 +131,7 @@
private:
std::shared_ptr<ks2::IKeystoreSecurityLevel> securityLevel;
- DISALLOW_COPY_AND_ASSIGN(Keymaster);
+ DISALLOW_COPY_AND_ASSIGN(Keystore);
};
} // namespace vold
diff --git a/Loop.cpp b/Loop.cpp
index 87f105d..4c86788 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -163,8 +163,6 @@
if (ioctl(fd.get(), LOOP_CLR_FD, 0) < 0) {
PLOG(WARNING) << "Failed to LOOP_CLR_FD " << path;
}
- } else {
- LOG(DEBUG) << "Found unmanaged loop device at " << path << " named " << id;
}
}
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index 9038e8d..277a908 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -38,7 +38,7 @@
#include "EncryptInplace.h"
#include "KeyStorage.h"
#include "KeyUtil.h"
-#include "Keymaster.h"
+#include "Keystore.h"
#include "Utils.h"
#include "VoldUtil.h"
#include "fs/Ext4.h"
@@ -49,6 +49,7 @@
using android::fs_mgr::FstabEntry;
using android::fs_mgr::GetEntryForMountPoint;
+using android::fscrypt::GetFirstApiLevel;
using android::vold::KeyBuffer;
using namespace android::dm;
@@ -117,7 +118,7 @@
"ro.crypto.metadata_init_delete_all_keys.enabled", false);
if (delete_all) {
LOG(INFO) << "Metadata key does not exist, calling deleteAllKeys";
- Keymaster::deleteAllKeys();
+ Keystore::deleteAllKeys();
} else {
LOG(DEBUG) << "Metadata key does not exist but "
"ro.crypto.metadata_init_delete_all_keys.enabled is false";
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index ef26fb6..cad92f5 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -35,7 +35,7 @@
#include "FsCrypt.h"
#include "IdleMaint.h"
#include "KeyStorage.h"
-#include "Keymaster.h"
+#include "Keystore.h"
#include "MetadataCrypt.h"
#include "MoveStorage.h"
#include "Process.h"
@@ -977,7 +977,7 @@
if (IgnoreEarlyBootEnded()) return Ok();
initializeIncFs();
- Keymaster::earlyBootEnded();
+ Keystore::earlyBootEnded();
return Ok();
}
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 2697f67..d299593 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -239,7 +239,7 @@
break;
}
case NetlinkEvent::Action::kChange: {
- LOG(DEBUG) << "Disk at " << major << ":" << minor << " changed";
+ LOG(VERBOSE) << "Disk at " << major << ":" << minor << " changed";
handleDiskChanged(device);
break;
}
diff --git a/cryptfs.cpp b/cryptfs.cpp
index 91235d2..f9d4ed4 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -22,7 +22,7 @@
#include "CryptoType.h"
#include "EncryptInplace.h"
#include "FsCrypt.h"
-#include "Keymaster.h"
+#include "Keystore.h"
#include "Process.h"
#include "ScryptParameters.h"
#include "Utils.h"
@@ -349,7 +349,7 @@
if (key_out_size) {
*key_out_size = 0;
}
- Keymaster dev;
+ Keystore dev;
if (!dev) {
LOG(ERROR) << "Failed to initiate keymaster session";
return -1;
@@ -395,7 +395,7 @@
return -1;
}
- Keymaster dev;
+ Keystore dev;
if (!dev) {
LOG(ERROR) << "Failed to initiate keymaster session";
return -1;
@@ -405,7 +405,7 @@
std::string key(reinterpret_cast<const char*>(ftr->keymaster_blob), ftr->keymaster_blob_size);
std::string input(reinterpret_cast<const char*>(object), object_size);
std::string output;
- KeymasterOperation op;
+ KeystoreOperation op;
auto paramBuilder = km::AuthorizationSetBuilder().NoDigestOrPadding().Authorization(
km::TAG_PURPOSE, km::KeyPurpose::SIGN);
@@ -1508,20 +1508,24 @@
[](const std::string& s1, const std::string& s2) {return s1.length() > s2.length(); });
for (std::string& mount_point : umount_points) {
- umount(mount_point.c_str());
- SLOGW("umount sub-directory mount %s\n", mount_point.c_str());
+ SLOGW("unmounting sub-directory mount %s\n", mount_point.c_str());
+ if (umount(mount_point.c_str()) != 0) {
+ SLOGE("unmounting %s failed: %s\n", mount_point.c_str(), strerror(errno));
+ }
}
}
static int wait_and_unmount(const char* mountpoint) {
int i, err, rc;
- // Subdirectory mount will cause a failure of umount.
- ensure_subdirectory_unmounted(mountpoint);
#define WAIT_UNMOUNT_COUNT 20
/* Now umount the tmpfs filesystem */
for (i = 0; i < WAIT_UNMOUNT_COUNT; i++) {
+ // Subdirectory mount will cause a failure of umount.
+ ensure_subdirectory_unmounted(mountpoint);
+
+ SLOGD("unmounting mount %s\n", mountpoint);
if (umount(mountpoint) == 0) {
break;
}
@@ -1530,10 +1534,12 @@
/* EINVAL is returned if the directory is not a mountpoint,
* i.e. there is no filesystem mounted there. So just get out.
*/
+ SLOGD("%s is not a mountpoint, nothing to do\n", mountpoint);
break;
}
err = errno;
+ SLOGW("unmounting mount %s failed: %s\n", mountpoint, strerror(err));
// If it's taking too long, kill the processes with open files.
//
@@ -1557,8 +1563,8 @@
SLOGD("unmounting %s succeeded\n", mountpoint);
rc = 0;
} else {
+ SLOGE("too many retries -- giving up unmounting %s\n", mountpoint);
android::vold::KillProcessesWithOpenFiles(mountpoint, 0);
- SLOGE("unmounting %s failed: %s\n", mountpoint, strerror(err));
rc = -1;
}
diff --git a/vdc.cpp b/vdc.cpp
index 47d98de..313ef55 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -28,6 +28,7 @@
#include <sys/types.h>
#include <sys/un.h>
+#include "Utils.h"
#include "android/os/IVold.h"
#include <android-base/logging.h>
@@ -37,6 +38,7 @@
#include <android-base/strings.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
+#include <utils/Errors.h>
#include <private/android_filesystem_config.h>
@@ -64,6 +66,26 @@
exit(ENOTTY);
}
+static void bindkeys(std::vector<std::string>& args, const android::sp<android::os::IVold>& vold) {
+ std::string raw_bytes;
+ const char* seed_value;
+
+ seed_value = getenv("SEED_VALUE");
+ if (seed_value == NULL) {
+ LOG(ERROR) << "Empty seed";
+ exit(EINVAL);
+ }
+
+ android::status_t status = android::vold::HexToStr(seed_value, raw_bytes);
+ if (status != android::OK) {
+ LOG(ERROR) << "Extraction of seed failed: " << status;
+ exit(status);
+ }
+
+ std::vector<uint8_t> seed{raw_bytes.begin(), raw_bytes.end()};
+ checkStatus(args, vold->setStorageBindingSeed(seed));
+}
+
int main(int argc, char** argv) {
setenv("ANDROID_LOG_TAGS", "*:v", 1);
if (getppid() == 1) {
@@ -106,6 +128,8 @@
checkStatus(args, vold->shutdown());
} else if (args[0] == "volume" && args[1] == "reset") {
checkStatus(args, vold->reset());
+ } else if (args[0] == "cryptfs" && args[1] == "bindkeys") {
+ bindkeys(args, vold);
} else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 4) {
checkStatus(args, vold->mountFstab(args[2], args[3]));
} else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 6) {
diff --git a/vold.rc b/vold.rc
index 93d8786..0252c2f 100644
--- a/vold.rc
+++ b/vold.rc
@@ -3,6 +3,6 @@
--fsck_context=u:r:fsck:s0 --fsck_untrusted_context=u:r:fsck_untrusted:s0
class core
ioprio be 2
- writepid /dev/cpuset/foreground/tasks
+ task_profiles ProcessCapacityHigh
shutdown critical
group root reserved_disk
diff --git a/wait_for_keymaster.cpp b/wait_for_keymaster.cpp
deleted file mode 100644
index bf26518..0000000
--- a/wait_for_keymaster.cpp
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2018 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 <android-base/logging.h>
-
-#include "Keymaster.h"
-
-int main(int argc, char** argv) {
- setenv("ANDROID_LOG_TAGS", "*:v", 1);
- if (getppid() == 1) {
- // If init is calling us then it's during boot and we should log to kmsg
- android::base::InitLogging(argv, &android::base::KernelLogger);
- } else {
- android::base::InitLogging(argv, &android::base::StderrLogger);
- }
- LOG(INFO) << "Waiting for Keymaster device";
- android::vold::Keymaster keymaster;
- LOG(INFO) << "Keymaster device ready";
- return 0;
-}
diff --git a/wait_for_keymaster.rc b/wait_for_keymaster.rc
deleted file mode 100644
index 9e83a93..0000000
--- a/wait_for_keymaster.rc
+++ /dev/null
@@ -1,5 +0,0 @@
-service wait_for_keymaster /system/bin/wait_for_keymaster
- user root
- group root system
- priority -20
- ioprio rt 0