Merge RP1A.200123.001

Change-Id: Ibfa73fd7557ebaa4aa61105a5661d1036cf7b474
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 0d4f02e..0020cf2 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -25,6 +25,7 @@
 
 #include <algorithm>
 #include <map>
+#include <optional>
 #include <set>
 #include <sstream>
 #include <string>
@@ -92,8 +93,6 @@
 // Map user ids to key references
 std::map<userid_t, std::string> s_de_key_raw_refs;
 std::map<userid_t, std::string> s_ce_key_raw_refs;
-// TODO abolish this map, per b/26948053
-std::map<userid_t, KeyBuffer> s_ce_keys;
 
 }  // namespace
 
@@ -282,7 +281,6 @@
         ce_key = std::move(ephemeral_wrapped_key);
     }
     if (!install_data_key(ce_key, &ce_raw_ref)) return false;
-    s_ce_keys[user_id] = std::move(ce_key);
     s_ce_key_raw_refs[user_id] = ce_raw_ref;
     LOG(DEBUG) << "Installed ce key for user " << user_id;
     return true;
@@ -362,7 +360,6 @@
     }
     if (!install_data_key(de_key, &de_raw_ref)) return false;
     if (!install_data_key(ce_key, &ce_raw_ref)) return false;
-    s_ce_keys[user_id] = std::move(ce_key);
 
     s_de_key_raw_refs[user_id] = de_raw_ref;
     s_ce_key_raw_refs[user_id] = ce_raw_ref;
@@ -555,22 +552,6 @@
         drop_caches_if_needed();
     }
 
-    if(is_wrapped_key_supported()) {
-        KeyBuffer key;
-        key = s_ce_keys[user_id];
-
-        std::string keystr(key.data(), key.size());
-        Keymaster keymaster;
-
-        if (!keymaster) {
-            s_ce_keys.erase(user_id);
-            s_ce_key_raw_refs.erase(user_id);
-            return false;
-        }
-        keymaster.deleteKey(keystr);
-    }
-
-    s_ce_keys.erase(user_id);
     s_ce_key_raw_refs.erase(user_id);
     return success;
 }
@@ -644,6 +625,18 @@
     return true;
 }
 
+static std::optional<android::vold::KeyAuthentication> authentication_from_hex(
+        const std::string& token_hex, const std::string& secret_hex) {
+    std::string token, secret;
+    if (!parse_hex(token_hex, &token)) return std::optional<android::vold::KeyAuthentication>();
+    if (!parse_hex(secret_hex, &secret)) return std::optional<android::vold::KeyAuthentication>();
+    if (secret.empty()) {
+        return kEmptyAuthentication;
+    } else {
+        return android::vold::KeyAuthentication(token, secret);
+    }
+}
+
 static std::string volkey_path(const std::string& misc_path, const std::string& volume_uuid) {
     return misc_path + "/vold/volume_keys/" + volume_uuid + "/default";
 }
@@ -689,44 +682,42 @@
     return android::vold::destroyKey(path);
 }
 
+static bool fscrypt_rewrap_user_key(userid_t user_id, int serial,
+                                    const android::vold::KeyAuthentication& retrieve_auth,
+                                    const android::vold::KeyAuthentication& store_auth) {
+    if (s_ephemeral_users.count(user_id) != 0) return true;
+    auto const directory_path = get_ce_key_directory_path(user_id);
+    KeyBuffer ce_key;
+    std::string ce_key_current_path = get_ce_key_current_path(directory_path);
+    if (android::vold::retrieveKey(ce_key_current_path, retrieve_auth, &ce_key)) {
+        LOG(DEBUG) << "Successfully retrieved key";
+        // TODO(147732812): Remove this once Locksettingservice is fixed.
+        // Currently it calls fscrypt_clear_user_key_auth with a secret when lockscreen is
+        // changed from swipe to none or vice-versa
+    } else if (android::vold::retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) {
+        LOG(DEBUG) << "Successfully retrieved key with empty auth";
+    } else {
+        LOG(ERROR) << "Failed to retrieve key for user " << user_id;
+        return false;
+    }
+    auto const paths = get_ce_key_paths(directory_path);
+
+    std::string ce_key_path;
+    if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
+    if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, store_auth, ce_key))
+        return false;
+    if (!android::vold::FsyncDirectory(directory_path)) return false;
+    return true;
+}
+
 bool fscrypt_add_user_key_auth(userid_t user_id, int serial, const std::string& token_hex,
                                const std::string& secret_hex) {
     LOG(DEBUG) << "fscrypt_add_user_key_auth " << user_id << " serial=" << serial
                << " token_present=" << (token_hex != "!");
     if (!fscrypt_is_native()) return true;
-    if (s_ephemeral_users.count(user_id) != 0) return true;
-    std::string token, secret;
-    if (!parse_hex(token_hex, &token)) return false;
-    if (!parse_hex(secret_hex, &secret)) return false;
-    auto auth =
-        secret.empty() ? kEmptyAuthentication : android::vold::KeyAuthentication(token, secret);
-    auto const directory_path = get_ce_key_directory_path(user_id);
-    auto const paths = get_ce_key_paths(directory_path);
-
-    KeyBuffer ce_key;
-    if(is_wrapped_key_supported()) {
-        std::string ce_key_current_path = get_ce_key_current_path(directory_path);
-        if (android::vold::retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) {
-            LOG(DEBUG) << "Successfully retrieved key";
-        } else {
-            if (android::vold::retrieveKey(ce_key_current_path, auth, &ce_key)) {
-                LOG(DEBUG) << "Successfully retrieved key";
-            }
-        }
-    } else {
-        auto it = s_ce_keys.find(user_id);
-        if (it == s_ce_keys.end()) {
-            LOG(ERROR) << "Key not loaded into memory, can't change for user " << user_id;
-            return false;
-        }
-        ce_key = it->second;
-    }
-
-    std::string ce_key_path;
-    if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
-    if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, auth, ce_key)) return false;
-    if (!android::vold::FsyncDirectory(directory_path)) return false;
-    return true;
+    auto auth = authentication_from_hex(token_hex, secret_hex);
+    if (!auth) return false;
+    return fscrypt_rewrap_user_key(user_id, serial, kEmptyAuthentication, *auth);
 }
 
 bool fscrypt_clear_user_key_auth(userid_t user_id, int serial, const std::string& token_hex,
@@ -734,39 +725,9 @@
     LOG(DEBUG) << "fscrypt_clear_user_key_auth " << user_id << " serial=" << serial
                << " token_present=" << (token_hex != "!");
     if (!fscrypt_is_native()) return true;
-    if (s_ephemeral_users.count(user_id) != 0) return true;
-    std::string token, secret;
-
-    if (!parse_hex(token_hex, &token)) return false;
-    if (!parse_hex(secret_hex, &secret)) return false;
-
-    if (is_wrapped_key_supported()) {
-        auto const directory_path = get_ce_key_directory_path(user_id);
-        auto const paths = get_ce_key_paths(directory_path);
-
-        KeyBuffer ce_key;
-        std::string ce_key_current_path = get_ce_key_current_path(directory_path);
-
-        auto auth = android::vold::KeyAuthentication(token, secret);
-        /* Retrieve key while removing a pin. A secret is needed */
-        if (android::vold::retrieveKey(ce_key_current_path, auth, &ce_key)) {
-            LOG(DEBUG) << "Successfully retrieved key";
-        } else {
-            /* Retrieve key when going None to swipe and vice versa when a
-               synthetic password is present */
-            if (android::vold::retrieveKey(ce_key_current_path, kEmptyAuthentication, &ce_key)) {
-                LOG(DEBUG) << "Successfully retrieved key";
-            }
-        }
-
-        std::string ce_key_path;
-        if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
-        if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, kEmptyAuthentication, ce_key))
-            return false;
-    } else {
-        if(!fscrypt_add_user_key_auth(user_id, serial, "!", "!")) return false;
-    }
-    return true;
+    auto auth = authentication_from_hex(token_hex, secret_hex);
+    if (!auth) return false;
+    return fscrypt_rewrap_user_key(user_id, serial, *auth, kEmptyAuthentication);
 }
 
 bool fscrypt_fixate_newest_user_key_auth(userid_t user_id) {
@@ -793,11 +754,9 @@
             LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id;
             return true;
         }
-        std::string token, secret;
-        if (!parse_hex(token_hex, &token)) return false;
-        if (!parse_hex(secret_hex, &secret)) return false;
-        android::vold::KeyAuthentication auth(token, secret);
-        if (!read_and_install_user_ce_key(user_id, auth)) {
+        auto auth = authentication_from_hex(token_hex, secret_hex);
+        if (!auth) return false;
+        if (!read_and_install_user_ce_key(user_id, *auth)) {
             LOG(ERROR) << "Couldn't read key for " << user_id;
             return false;
         }