Merge "Add |optional_suffix| to StartIteration()" into mnc-dev
diff --git a/fingerprintd/FingerprintDaemonProxy.cpp b/fingerprintd/FingerprintDaemonProxy.cpp
index a55f30a..4c8e478 100644
--- a/fingerprintd/FingerprintDaemonProxy.cpp
+++ b/fingerprintd/FingerprintDaemonProxy.cpp
@@ -160,8 +160,8 @@
 
 int32_t FingerprintDaemonProxy::setActiveGroup(int32_t groupId, const uint8_t* path,
         ssize_t pathlen) {
-    if (pathlen >= PATH_MAX) {
-        ALOGE("Path name is too long\n");
+    if (pathlen >= PATH_MAX || pathlen <= 0) {
+        ALOGE("Bad path length: %zd", pathlen);
         return -1;
     }
     // Convert to null-terminated string
@@ -170,7 +170,6 @@
     path_name[pathlen] = '\0';
     ALOG(LOG_VERBOSE, LOG_TAG, "setActiveGroup(%d, %s, %zu)", groupId, path_name, pathlen);
     return mDevice->set_active_group(mDevice, groupId, path_name);
-    return -1;
 }
 
 int64_t FingerprintDaemonProxy::openHal() {
diff --git a/gatekeeperd/SoftGateKeeper.h b/gatekeeperd/SoftGateKeeper.h
index e554411..75fe11d 100644
--- a/gatekeeperd/SoftGateKeeper.h
+++ b/gatekeeperd/SoftGateKeeper.h
@@ -20,6 +20,8 @@
 
 extern "C" {
 #include <openssl/rand.h>
+#include <openssl/sha.h>
+
 #include <crypto_scrypt.h>
 }
 
@@ -30,6 +32,10 @@
 
 namespace gatekeeper {
 
+struct fast_hash_t {
+    uint64_t salt;
+    uint8_t digest[SHA256_DIGEST_LENGTH];
+};
 
 class SoftGateKeeper : public GateKeeper {
 public:
@@ -125,9 +131,48 @@
         return true;
     }
 
+    fast_hash_t ComputeFastHash(const SizedBuffer &password, uint64_t salt) {
+        fast_hash_t fast_hash;
+        size_t digest_size = password.length + sizeof(salt);
+        std::unique_ptr<uint8_t[]> digest(new uint8_t[digest_size]);
+        memcpy(digest.get(), &salt, sizeof(salt));
+        memcpy(digest.get() + sizeof(salt), password.buffer.get(), password.length);
+
+        SHA256(digest.get(), digest_size, (uint8_t *) &fast_hash.digest);
+
+        fast_hash.salt = salt;
+        return fast_hash;
+    }
+
+    bool VerifyFast(const fast_hash_t &fast_hash, const SizedBuffer &password) {
+        fast_hash_t computed = ComputeFastHash(password, fast_hash.salt);
+        return memcmp(computed.digest, fast_hash.digest, SHA256_DIGEST_LENGTH) == 0;
+    }
+
+    bool DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) {
+        FastHashMap::const_iterator it = fast_hash_map_.find(expected_handle->user_id);
+        if (it != fast_hash_map_.end() && VerifyFast(it->second, password)) {
+            return true;
+        } else {
+            if (GateKeeper::DoVerify(expected_handle, password)) {
+                uint64_t salt;
+                GetRandom(&salt, sizeof(salt));
+                fast_hash_map_[expected_handle->user_id] = ComputeFastHash(password, salt);
+                return true;
+            }
+        }
+
+        return false;
+    }
+
 private:
+
+    typedef std::unordered_map<uint32_t, failure_record_t> FailureRecordMap;
+    typedef std::unordered_map<uint64_t, fast_hash_t> FastHashMap;
+
     UniquePtr<uint8_t[]> key_;
-    std::unordered_map<uint32_t, failure_record_t> failure_map_;
+    FailureRecordMap failure_map_;
+    FastHashMap fast_hash_map_;
 };
 }
 
diff --git a/gatekeeperd/SoftGateKeeperDevice.h b/gatekeeperd/SoftGateKeeperDevice.h
index 51a8511..3463c29 100644
--- a/gatekeeperd/SoftGateKeeperDevice.h
+++ b/gatekeeperd/SoftGateKeeperDevice.h
@@ -68,7 +68,7 @@
             const uint8_t *provided_password, uint32_t provided_password_length,
             uint8_t **auth_token, uint32_t *auth_token_length, bool *request_reenroll);
 private:
-    UniquePtr<GateKeeper> impl_;
+    UniquePtr<SoftGateKeeper> impl_;
 };
 
 } // namespace gatekeeper
diff --git a/gatekeeperd/gatekeeperd.cpp b/gatekeeperd/gatekeeperd.cpp
index c0f2279..f4f2cbf 100644
--- a/gatekeeperd/gatekeeperd.cpp
+++ b/gatekeeperd/gatekeeperd.cpp
@@ -31,6 +31,7 @@
 #include <binder/IServiceManager.h>
 #include <binder/PermissionCache.h>
 #include <utils/String16.h>
+#include <utils/Log.h>
 
 #include <keystore/IKeystoreService.h>
 #include <keystore/keystore.h> // For error code
@@ -57,6 +58,13 @@
             if (ret < 0)
                 LOG_ALWAYS_FATAL_IF(ret < 0, "Unable to open GateKeeper HAL");
         }
+
+        if (mark_cold_boot()) {
+            ALOGI("cold boot: clearing state");
+            if (device != NULL && device->delete_all_users != NULL) {
+                device->delete_all_users(device);
+            }
+        }
     }
 
     virtual ~GateKeeperProxy() {
@@ -75,6 +83,20 @@
         close(fd);
     }
 
+    bool mark_cold_boot() {
+        const char *filename = ".coldboot";
+        if (access(filename, F_OK) == -1) {
+            int fd = open(filename, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR);
+            if (fd < 0) {
+                ALOGE("could not open file: %s : %s", filename, strerror(errno));
+                return false;
+            }
+            close(fd);
+            return true;
+        }
+        return false;
+    }
+
     void maybe_store_sid(uint32_t uid, uint64_t sid) {
         char filename[21];
         sprintf(filename, "%u", uid);
@@ -119,8 +141,19 @@
 
         int ret;
         if (device) {
-            ret = device->enroll(device, uid,
-                    current_password_handle, current_password_handle_length,
+            const gatekeeper::password_handle_t *handle =
+                    reinterpret_cast<const gatekeeper::password_handle_t *>(current_password_handle);
+
+            if (handle != NULL && !handle->hardware_backed) {
+                // handle is being re-enrolled from a software version. HAL probably won't accept
+                // the handle as valid, so we nullify it and enroll from scratch
+                current_password_handle = NULL;
+                current_password_handle_length = 0;
+                current_password = NULL;
+                current_password_length = 0;
+            }
+
+            ret = device->enroll(device, uid, current_password_handle, current_password_handle_length,
                     current_password, current_password_length,
                     desired_password, desired_password_length,
                     enrolled_password_handle, enrolled_password_handle_length);
@@ -174,10 +207,26 @@
 
         int ret;
         if (device) {
-            ret = device->verify(device, uid, challenge,
-                enrolled_password_handle, enrolled_password_handle_length,
-                provided_password, provided_password_length, auth_token, auth_token_length,
-                request_reenroll);
+            const gatekeeper::password_handle_t *handle =
+                    reinterpret_cast<const gatekeeper::password_handle_t *>(enrolled_password_handle);
+            if (handle->hardware_backed) {
+                ret = device->verify(device, uid, challenge,
+                    enrolled_password_handle, enrolled_password_handle_length,
+                    provided_password, provided_password_length, auth_token, auth_token_length,
+                    request_reenroll);
+            } else {
+                // upgrade scenario, a HAL has been added to this device where there was none before
+                SoftGateKeeperDevice soft_dev;
+                ret = soft_dev.verify(uid, challenge,
+                    enrolled_password_handle, enrolled_password_handle_length,
+                    provided_password, provided_password_length, auth_token, auth_token_length,
+                    request_reenroll);
+
+                if (ret == 0) {
+                    // success! re-enroll with HAL
+                    *request_reenroll = true;
+                }
+            }
         } else {
             ret = soft_device->verify(uid, challenge,
                 enrolled_password_handle, enrolled_password_handle_length,
@@ -221,6 +270,10 @@
             return;
         }
         clear_sid(uid);
+
+        if (device != NULL && device->delete_user != NULL) {
+            device->delete_user(device, uid);
+        }
     }
 
     virtual status_t dump(int fd, const Vector<String16> &) {
diff --git a/gatekeeperd/tests/gatekeeper_test.cpp b/gatekeeperd/tests/gatekeeper_test.cpp
index 15b2b69..c504f92 100644
--- a/gatekeeperd/tests/gatekeeper_test.cpp
+++ b/gatekeeperd/tests/gatekeeper_test.cpp
@@ -14,9 +14,11 @@
  * limitations under the License.
  */
 
+#include <arpa/inet.h>
+#include <iostream>
+
 #include <gtest/gtest.h>
 #include <UniquePtr.h>
-#include <iostream>
 
 #include <hardware/hw_auth_token.h>
 
diff --git a/libcutils/sched_policy.c b/libcutils/sched_policy.c
index a7ff85e..cf50ba7 100644
--- a/libcutils/sched_policy.c
+++ b/libcutils/sched_policy.c
@@ -269,10 +269,7 @@
             return -errno;
     }
 
-    // we do both setting of cpuset and setting of cgroup
-    // ensures that backgrounded apps are actually deprioritized
-    // including on core 0
-    return set_sched_policy(tid, policy);
+    return 0;
 #endif
 }
 
diff --git a/rootdir/init.rc b/rootdir/init.rc
index acca097..17e2153 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -270,7 +270,10 @@
     # create basic filesystem structure
     mkdir /data/misc 01771 system misc
     mkdir /data/misc/adb 02750 system shell
-    mkdir /data/misc/bluedroid 0770 bluetooth net_bt_stack
+    mkdir /data/misc/bluedroid 02770 bluetooth net_bt_stack
+    # Fix the access permissions and group ownership for 'bt_config.conf'
+    chmod 0660 /data/misc/bluedroid/bt_config.conf
+    chown bluetooth net_bt_stack /data/misc/bluedroid/bt_config.conf
     mkdir /data/misc/bluetooth 0770 system system
     mkdir /data/misc/keystore 0700 keystore keystore
     mkdir /data/misc/gatekeeper 0700 system system