summaryrefslogtreecommitdiffstats
path: root/gatekeeperd
diff options
context:
space:
mode:
Diffstat (limited to 'gatekeeperd')
-rw-r--r--gatekeeperd/SoftGateKeeper.h47
-rw-r--r--gatekeeperd/SoftGateKeeperDevice.h2
-rw-r--r--gatekeeperd/gatekeeperd.cpp65
3 files changed, 106 insertions, 8 deletions
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 @@ extern "C" {
namespace gatekeeper {
+struct fast_hash_t {
+ uint64_t salt;
+ uint8_t digest[SHA256_DIGEST_LENGTH];
+};
class SoftGateKeeper : public GateKeeper {
public:
@@ -125,9 +131,48 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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 @@ public:
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> &) {