Merge "Ignore DE retrieveKey failure for non-user-0"
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index b4abc27..55c1709 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -57,16 +57,14 @@
 static const char* kCurrentVersion = "1";
 static const char* kRmPath = "/system/bin/rm";
 static const char* kSecdiscardPath = "/system/bin/secdiscard";
-static const char* kStretch_none = "none";
-static const char* kStretch_nopassword = "nopassword";
 static const char* kHashPrefix_secdiscardable = "Android secdiscardable SHA512";
 static const char* kHashPrefix_keygen = "Android key wrapping key generation SHA512";
 static const char* kFn_encrypted_key = "encrypted_key";
 static const char* kFn_keymaster_key_blob = "keymaster_key_blob";
 static const char* kFn_keymaster_key_blob_upgraded = "keymaster_key_blob_upgraded";
 static const char* kFn_secdiscardable = "secdiscardable";
-static const char* kFn_stretching = "stretching";
 static const char* kFn_version = "version";
+// Note: old key directories may contain a file named "stretching".
 
 namespace {
 
@@ -191,9 +189,13 @@
 }
 
 bool readSecdiscardable(const std::string& filename, std::string* hash) {
-    std::string secdiscardable;
-    if (!readFileToString(filename, &secdiscardable)) return false;
-    hashWithPrefix(kHashPrefix_secdiscardable, secdiscardable, hash);
+    if (pathExists(filename)) {
+        std::string secdiscardable;
+        if (!readFileToString(filename, &secdiscardable)) return false;
+        hashWithPrefix(kHashPrefix_secdiscardable, secdiscardable, hash);
+    } else {
+        *hash = "";
+    }
     return true;
 }
 
@@ -408,36 +410,9 @@
     return true;
 }
 
-static std::string getStretching(const KeyAuthentication& auth) {
-    if (auth.usesKeystore()) {
-        return kStretch_nopassword;
-    } else {
-        return kStretch_none;
-    }
-}
-
-static bool stretchSecret(const std::string& stretching, const std::string& secret,
-                          std::string* stretched) {
-    if (stretching == kStretch_nopassword) {
-        if (!secret.empty()) {
-            LOG(WARNING) << "Password present but stretching is nopassword";
-            // Continue anyway
-        }
-        stretched->clear();
-    } else if (stretching == kStretch_none) {
-        *stretched = secret;
-    } else {
-        LOG(ERROR) << "Unknown stretching type: " << stretching;
-        return false;
-    }
-    return true;
-}
-
-static bool generateAppId(const KeyAuthentication& auth, const std::string& stretching,
-                          const std::string& secdiscardable_hash, std::string* appId) {
-    std::string stretched;
-    if (!stretchSecret(stretching, auth.secret, &stretched)) return false;
-    *appId = secdiscardable_hash + stretched;
+static std::string generateAppId(const KeyAuthentication& auth,
+                                 const std::string& secdiscardable_hash) {
+    std::string appId = secdiscardable_hash + auth.secret;
 
     const std::lock_guard<std::mutex> scope_lock(storage_binding_info.guard);
     switch (storage_binding_info.state) {
@@ -445,14 +420,13 @@
             storage_binding_info.state = StorageBindingInfo::State::NOT_USED;
             break;
         case StorageBindingInfo::State::IN_USE:
-            appId->append(storage_binding_info.seed.begin(), storage_binding_info.seed.end());
+            appId.append(storage_binding_info.seed.begin(), storage_binding_info.seed.end());
             break;
         case StorageBindingInfo::State::NOT_USED:
             // noop
             break;
     }
-
-    return true;
+    return appId;
 }
 
 static void logOpensslError() {
@@ -563,9 +537,12 @@
 
 // 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.
+// |auth|) or with the given secret (if a secret is given in |auth|).  In the
+// former case, an attempt is made to make the key securely deletable.  In the
+// latter case, secure deletion is expected to be handled at a higher level.
+//
+// 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;
@@ -573,11 +550,10 @@
     }
     if (!writeStringToFile(kCurrentVersion, dir + "/" + kFn_version)) return false;
     std::string secdiscardable_hash;
-    if (!createSecdiscardable(dir + "/" + kFn_secdiscardable, &secdiscardable_hash)) return false;
-    std::string stretching = getStretching(auth);
-    if (!writeStringToFile(stretching, dir + "/" + kFn_stretching)) return false;
-    std::string appId;
-    if (!generateAppId(auth, stretching, secdiscardable_hash, &appId)) return false;
+    if (auth.usesKeystore() &&
+        !createSecdiscardable(dir + "/" + kFn_secdiscardable, &secdiscardable_hash))
+        return false;
+    std::string appId = generateAppId(auth, secdiscardable_hash);
     std::string encryptedKey;
     if (auth.usesKeystore()) {
         Keystore keystore;
@@ -629,10 +605,7 @@
     }
     std::string secdiscardable_hash;
     if (!readSecdiscardable(dir + "/" + kFn_secdiscardable, &secdiscardable_hash)) return false;
-    std::string stretching;
-    if (!readFileToString(dir + "/" + kFn_stretching, &stretching)) return false;
-    std::string appId;
-    if (!generateAppId(auth, stretching, secdiscardable_hash, &appId)) return false;
+    std::string appId = generateAppId(auth, secdiscardable_hash);
     std::string encryptedMessage;
     if (!readFileToString(dir + "/" + kFn_encrypted_key, &encryptedMessage)) return false;
     if (auth.usesKeystore()) {
diff --git a/Utils.cpp b/Utils.cpp
index 9e77a9e..23e8867 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1448,7 +1448,10 @@
 status_t AbortFuseConnections() {
     namespace fs = std::filesystem;
 
-    for (const auto& itEntry : fs::directory_iterator("/sys/fs/fuse/connections")) {
+    static constexpr const char* kFuseConnections = "/sys/fs/fuse/connections";
+
+    std::error_code ec;
+    for (const auto& itEntry : fs::directory_iterator(kFuseConnections, ec)) {
         std::string fsPath = itEntry.path().string() + "/filesystem";
         std::string fs;
 
@@ -1468,6 +1471,11 @@
         }
     }
 
+    if (ec) {
+        LOG(WARNING) << "Failed to iterate through " << kFuseConnections << ": "  << ec.message();
+        return -ec.value();
+    }
+
     return OK;
 }
 
diff --git a/secdiscard.cpp b/secdiscard.cpp
index b91f321..490e5a1 100644
--- a/secdiscard.cpp
+++ b/secdiscard.cpp
@@ -97,7 +97,7 @@
             TEMP_FAILURE_RETRY(open(target.c_str(), O_WRONLY | O_CLOEXEC, 0)));
         if (fd == -1) {
             LOG(ERROR) << "Secure discard open failed for: " << target;
-            return 0;
+            continue;
         }
         __u32 set = 1;
         ioctl(fd, F2FS_IOC_SET_PIN_FILE, &set);