summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndres Morales <anmorales@google.com>2015-05-27 01:42:48 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-05-27 01:42:48 +0000
commit7577933d39d1cd83e8677ef4dc8670d8c5391a20 (patch)
tree7906bc0f61c49d67240cf1ac3db2a9c655ced280
parent256f5c65de28f51aabf7cefa1d0c5a1ef44e147b (diff)
parentaedf605d883b4ebade9c810eb39cbf5125a58c7d (diff)
downloadgatekeeper-7577933d39d1cd83e8677ef4dc8670d8c5391a20.tar.gz
am aedf605d: move throttling to GateKeeper layer
* commit 'aedf605d883b4ebade9c810eb39cbf5125a58c7d': move throttling to GateKeeper layer
-rw-r--r--gatekeeper.cpp145
-rw-r--r--gatekeeper_messages.cpp42
-rw-r--r--include/gatekeeper/gatekeeper.h64
-rw-r--r--include/gatekeeper/gatekeeper_messages.h11
-rw-r--r--include/gatekeeper/password_handle.h4
-rw-r--r--include/gatekeeper/soft_gatekeeper.h97
-rw-r--r--tests/Android.mk1
-rw-r--r--tests/gatekeeper_device_test.cpp7
-rw-r--r--tests/gatekeeper_test.cpp203
9 files changed, 249 insertions, 325 deletions
diff --git a/gatekeeper.cpp b/gatekeeper.cpp
index 77e14e2..20794b2 100644
--- a/gatekeeper.cpp
+++ b/gatekeeper.cpp
@@ -28,7 +28,8 @@ void GateKeeper::Enroll(const EnrollRequest &request, EnrollResponse *response)
return;
}
- secure_id_t user_id = 0;
+ secure_id_t user_id = 0;// todo: rename to policy
+ uint32_t uid = request.user_id;
if (request.password_handle.buffer.get() == NULL) {
// Password handle does not match what is stored, generate new SecureID
@@ -36,15 +37,51 @@ void GateKeeper::Enroll(const EnrollRequest &request, EnrollResponse *response)
} else {
password_handle_t *pw_handle =
reinterpret_cast<password_handle_t *>(request.password_handle.buffer.get());
- if (!DoVerify(pw_handle, request.enrolled_password)) {
- // incorrect old password
+
+ user_id = pw_handle->user_id;
+
+ uint64_t timestamp = GetMillisecondsSinceBoot();
+
+ bool throttle = true;
+ if (pw_handle->version == 0) {
+ // handle version is pre-throttling
+ throttle = false;
+ } else if (pw_handle->version != HANDLE_VERSION) {
response->error = ERROR_INVALID;
return;
}
- user_id = pw_handle->user_id;
+ uint32_t timeout = 0;
+ if (throttle) {
+ failure_record_t record;
+ if (!GetFailureRecord(uid, user_id, &record)) {
+ response->error = ERROR_UNKNOWN;
+ return;
+ }
+
+ if (ThrottleRequest(uid, user_id, timestamp, &record, response)) return;
+
+ if (!IncrementFailureRecord(uid, user_id, timestamp, &record)) {
+ response->error = ERROR_UNKNOWN;
+ return;
+ }
+
+ timeout = ComputeRetryTimeout(&record);
+ }
+
+ if (!DoVerify(pw_handle, request.enrolled_password)) {
+ // incorrect old password
+ if (throttle && timeout > 0) {
+ response->SetRetryTimeout(timeout);
+ } else {
+ response->error = ERROR_INVALID;
+ }
+ return;
+ }
}
+ ClearFailureRecord(uid, user_id);
+
salt_t salt;
GetRandom(&salt, sizeof(salt));
@@ -53,8 +90,8 @@ void GateKeeper::Enroll(const EnrollRequest &request, EnrollResponse *response)
SizedBuffer password_handle;
- if(!CreatePasswordHandle(&password_handle,
- salt, user_id, authenticator_id, request.provided_password.buffer.get(),
+ if (!CreatePasswordHandle(&password_handle,
+ salt, user_id, authenticator_id, HANDLE_VERSION, request.provided_password.buffer.get(),
request.provided_password.length)) {
response->error = ERROR_INVALID;
return;
@@ -74,40 +111,70 @@ void GateKeeper::Verify(const VerifyRequest &request, VerifyResponse *response)
password_handle_t *password_handle = reinterpret_cast<password_handle_t *>(
request.password_handle.buffer.get());
- // Sanity check
- if (password_handle->version != HANDLE_VERSION) {
+ bool throttle = true;
+ if (password_handle->version == 0) {
+ // handle version is pre-throttling
+ throttle = false;
+ response->request_reenroll = true;
+ } else if (password_handle->version != HANDLE_VERSION) {
response->error = ERROR_INVALID;
return;
}
secure_id_t user_id = password_handle->user_id;
secure_id_t authenticator_id = password_handle->authenticator_id;
+ uint32_t uid = request.user_id;
uint64_t timestamp = GetMillisecondsSinceBoot();
+ uint32_t timeout = 0;
+ if (throttle) {
+ failure_record_t record;
+ if (!GetFailureRecord(uid, user_id, &record)) {
+ response->error = ERROR_UNKNOWN;
+ return;
+ }
+
+ if (ThrottleRequest(uid, user_id, timestamp, &record, response)) return;
+
+ if (!IncrementFailureRecord(uid, user_id, timestamp, &record)) {
+ response->error = ERROR_UNKNOWN;
+ return;
+ }
+
+ timeout = ComputeRetryTimeout(&record);
+ }
+
if (DoVerify(password_handle, request.provided_password)) {
// Signature matches
SizedBuffer auth_token;
MintAuthToken(&auth_token.buffer, &auth_token.length, timestamp,
user_id, authenticator_id, request.challenge);
response->SetVerificationToken(&auth_token);
+ if (throttle) ClearFailureRecord(uid, user_id);
} else {
- response->error = ERROR_INVALID;
+ // compute the new timeout given the incremented record
+ if (throttle && timeout > 0) {
+ response->SetRetryTimeout(timeout);
+ } else {
+ response->error = ERROR_INVALID;
+ }
}
}
bool GateKeeper::CreatePasswordHandle(SizedBuffer *password_handle_buffer, salt_t salt,
- secure_id_t user_id, secure_id_t authenticator_id, const uint8_t *password,
+ secure_id_t user_id, secure_id_t authenticator_id, uint8_t handle_version, const uint8_t *password,
uint32_t password_length) {
password_handle_buffer->buffer.reset(new uint8_t[sizeof(password_handle_t)]);
password_handle_buffer->length = sizeof(password_handle_t);
password_handle_t *password_handle = reinterpret_cast<password_handle_t *>(
password_handle_buffer->buffer.get());
- password_handle->version = HANDLE_VERSION;
+ password_handle->version = handle_version;
password_handle->salt = salt;
password_handle->user_id = user_id;
password_handle->authenticator_id = authenticator_id;
+ password_handle->hardware_backed = IsHardwareBacked();
uint32_t metadata_length = sizeof(user_id) /* user id */
+ sizeof(authenticator_id) /* auth id */ + sizeof(HANDLE_VERSION) /* version */;
@@ -133,11 +200,15 @@ bool GateKeeper::DoVerify(const password_handle_t *expected_handle, const SizedB
SizedBuffer provided_handle;
if (!CreatePasswordHandle(&provided_handle, expected_handle->salt, expected_handle->user_id,
- expected_handle->authenticator_id, password.buffer.get(), password.length)) {
+ expected_handle->authenticator_id, expected_handle->version,
+ password.buffer.get(), password.length)) {
return false;
}
- return memcmp_s(provided_handle.buffer.get(), expected_handle, sizeof(*expected_handle)) == 0;
+ password_handle_t *generated_handle =
+ reinterpret_cast<password_handle_t *>(provided_handle.buffer.get());
+ return memcmp_s(generated_handle->signature, expected_handle->signature,
+ sizeof(expected_handle->signature)) == 0;
}
void GateKeeper::MintAuthToken(UniquePtr<uint8_t> *auth_token, uint32_t *length,
@@ -169,4 +240,52 @@ void GateKeeper::MintAuthToken(UniquePtr<uint8_t> *auth_token, uint32_t *length,
auth_token->reset(reinterpret_cast<uint8_t *>(token));
}
+uint32_t GateKeeper::ComputeRetryTimeout(const failure_record_t *record) {
+ if (record->failure_counter > 0 && record->failure_counter <= 10) {
+ if (record->failure_counter % 5 == 0) {
+ return 30000;
+ }
+ } else {
+ return 30000;
+ }
+ return 0;
+}
+
+bool GateKeeper::ThrottleRequest(uint32_t uid, secure_id_t user_id, uint64_t timestamp,
+ failure_record_t *record, GateKeeperMessage *response) {
+
+ uint64_t last_checked = record->last_checked_timestamp;
+ uint32_t timeout = ComputeRetryTimeout(record);
+
+ if (timeout > 0) {
+ // we have a pending timeout
+ if (timestamp < last_checked + timeout && timestamp > last_checked) {
+ // attempt before timeout expired, return remaining time
+ response->SetRetryTimeout(timeout - (timestamp - last_checked));
+ return true;
+ } else if (timestamp <= last_checked) {
+ // device was rebooted or timer reset, don't count as new failure but
+ // reset timeout
+ record->last_checked_timestamp = timestamp;
+ if (!WriteFailureRecord(uid, record)) {
+ response->error = ERROR_UNKNOWN;
+ return true;
+ }
+ response->SetRetryTimeout(timeout);
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool GateKeeper::IncrementFailureRecord(uint32_t uid, secure_id_t user_id, uint64_t timestamp,
+ failure_record_t *record) {
+ record->secure_user_id = user_id;
+ record->failure_counter++;
+ record->last_checked_timestamp = timestamp;
+
+ return WriteFailureRecord(uid, record);
}
+} // namespace gatekeeper
+
diff --git a/gatekeeper_messages.cpp b/gatekeeper_messages.cpp
index 4e5e833..c803666 100644
--- a/gatekeeper_messages.cpp
+++ b/gatekeeper_messages.cpp
@@ -65,9 +65,14 @@ static inline gatekeeper_error_t read_from_buffer(const uint8_t **buffer, const
uint32_t GateKeeperMessage::GetSerializedSize() const {
if (error == ERROR_NONE) {
- return 2 * sizeof(uint32_t) + nonErrorSerializedSize();
+ uint32_t size = sizeof(serial_header_t) + nonErrorSerializedSize();
+ return size;
} else {
- return sizeof(uint32_t);
+ uint32_t size = sizeof(serial_header_t);
+ if (error == ERROR_RETRY) {
+ size += sizeof(retry_timeout);
+ }
+ return size;
}
}
@@ -79,9 +84,14 @@ uint32_t GateKeeperMessage::Serialize(uint8_t *buffer, const uint8_t *end) const
serial_header_t *header = reinterpret_cast<serial_header_t *>(buffer);
if (error != ERROR_NONE) {
- if (buffer + sizeof(error) > end) return 0;
+ if (buffer + sizeof(serial_header_t) > end) return 0;
header->error = error;
- bytes_written += sizeof(error);
+ header->user_id = user_id;
+ bytes_written += sizeof(*header);
+ if (error == ERROR_RETRY) {
+ memcpy(buffer + sizeof(serial_header_t), &retry_timeout, sizeof(retry_timeout));
+ bytes_written += sizeof(retry_timeout);
+ }
} else {
if (buffer + sizeof(serial_header_t) + nonErrorSerializedSize() > end)
return 0;
@@ -103,11 +113,23 @@ gatekeeper_error_t GateKeeperMessage::Deserialize(const uint8_t *payload, const
error = nonErrorDeserialize(payload + sizeof(*header), end);
} else {
error = static_cast<gatekeeper_error_t>(header->error);
+ user_id = header->user_id;
+ if (error == ERROR_RETRY) {
+ if (payload + sizeof(serial_header_t) < end) {
+ memcpy(&retry_timeout, payload + sizeof(serial_header_t), sizeof(retry_timeout));
+ } else {
+ retry_timeout = 0;
+ }
+ }
}
return error;
}
+void GateKeeperMessage::SetRetryTimeout(uint32_t retry_timeout) {
+ this->retry_timeout = retry_timeout;
+ this->error = ERROR_RETRY;
+}
VerifyRequest::VerifyRequest(uint32_t user_id, uint64_t challenge,
SizedBuffer *enrolled_password_handle, SizedBuffer *provided_password_payload) {
@@ -173,6 +195,7 @@ VerifyResponse::VerifyResponse(uint32_t user_id, SizedBuffer *auth_token) {
this->user_id = user_id;
this->auth_token.buffer.reset(auth_token->buffer.release());
this->auth_token.length = auth_token->length;
+ this->request_reenroll = false;
}
VerifyResponse::VerifyResponse() {
@@ -191,11 +214,12 @@ void VerifyResponse::SetVerificationToken(SizedBuffer *auth_token) {
}
uint32_t VerifyResponse::nonErrorSerializedSize() const {
- return serialized_buffer_size(auth_token);
+ return serialized_buffer_size(auth_token) + sizeof(request_reenroll);
}
void VerifyResponse::nonErrorSerialize(uint8_t *buffer) const {
append_to_buffer(&buffer, &auth_token);
+ memcpy(buffer, &request_reenroll, sizeof(request_reenroll));
}
gatekeeper_error_t VerifyResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
@@ -203,7 +227,13 @@ gatekeeper_error_t VerifyResponse::nonErrorDeserialize(const uint8_t *payload, c
auth_token.buffer.reset();
}
- return read_from_buffer(&payload, end, &auth_token);
+ gatekeeper_error_t err = read_from_buffer(&payload, end, &auth_token);
+ if (err != ERROR_NONE) {
+ return err;
+ }
+
+ memcpy(&request_reenroll, payload, sizeof(request_reenroll));
+ return ERROR_NONE;
}
EnrollRequest::EnrollRequest(uint32_t user_id, SizedBuffer *password_handle,
diff --git a/include/gatekeeper/gatekeeper.h b/include/gatekeeper/gatekeeper.h
index 4a5edc0..33ffb9f 100644
--- a/include/gatekeeper/gatekeeper.h
+++ b/include/gatekeeper/gatekeeper.h
@@ -26,6 +26,12 @@
namespace gatekeeper {
+struct __attribute__((packed)) failure_record_t {
+ uint64_t secure_user_id;
+ uint64_t last_checked_timestamp;
+ uint32_t failure_counter;
+};
+
/**
* Base class for gatekeeper implementations. Provides all functionality except
* the ability to create/access keys and compute signatures. These are left up
@@ -108,6 +114,39 @@ protected:
*/
virtual uint64_t GetMillisecondsSinceBoot() const = 0;
+ /**
+ * Returns the value of the current failure record for the user.
+ * The failure record should be written to hardware-backed secure storage, such as
+ * RPMB.
+ *
+ * Returns true on success, false if failure record cannot be retrieved.
+ */
+ virtual bool GetFailureRecord(uint32_t uid, secure_id_t user_id, failure_record_t *record) = 0;
+
+ /**
+ * Clears the failure record for the current user. Returning the counter to 0, or deleting
+ * it entirely.
+ */
+ virtual void ClearFailureRecord(uint32_t uid, secure_id_t user_id) = 0;
+
+ /*
+ * Persists the provided failure record to secure, persistent storage.
+ * Returns true if record was successfully written.
+ */
+ virtual bool WriteFailureRecord(uint32_t uid, failure_record_t *record) = 0;
+
+ /**
+ * Computes the amount of time to throttle the user due to the current failure_record
+ * counter. An implementation is provided by the generic GateKeeper, but may be
+ * overriden.
+ */
+ virtual uint32_t ComputeRetryTimeout(const failure_record_t *record);
+
+ /**
+ * Returns whether the GateKeeper implementation is backed by hardware.
+ */
+ virtual bool IsHardwareBacked() const = 0;
+
private:
/**
* Generates a signed attestation of an authentication event and assings
@@ -127,8 +166,29 @@ private:
* Populates password_handle with the data provided and computes HMAC.
*/
bool CreatePasswordHandle(SizedBuffer *password_handle, salt_t salt,
- secure_id_t secure_id, secure_id_t authenticator_id, const uint8_t *password,
- uint32_t password_length);
+ secure_id_t secure_id, secure_id_t authenticator_id, uint8_t handle_version,
+ const uint8_t *password, uint32_t password_length);
+
+ /**
+ * Increments the counter on the current failure record for the provided user id.
+ * Sets the last_checked_timestamp to timestamp. Writes the updated record
+ * to *record if not null.
+ *
+ * Returns true if failure record was successfully incremented.
+ */
+ bool IncrementFailureRecord(uint32_t uid, secure_id_t user_id, uint64_t timestamp,
+ failure_record_t *record);
+
+ /**
+ * Determines whether the request is within the current throttle window.
+ *
+ * If the system timer has been reset due to a reboot or otherwise, resets
+ * the throttle window with a base at the current time.
+ *
+ * Returns true if the request is in the throttle window.
+ */
+ bool ThrottleRequest(uint32_t uid, secure_id_t user_id, uint64_t timestamp,
+ failure_record_t *record, GateKeeperMessage *response);
};
}
diff --git a/include/gatekeeper/gatekeeper_messages.h b/include/gatekeeper/gatekeeper_messages.h
index 0f89047..cea7e1c 100644
--- a/include/gatekeeper/gatekeeper_messages.h
+++ b/include/gatekeeper/gatekeeper_messages.h
@@ -32,6 +32,8 @@ const uint32_t VERIFY = 1;
typedef enum {
ERROR_NONE = 0,
ERROR_INVALID = 1,
+ ERROR_RETRY = 2,
+ ERROR_UNKNOWN = 3,
} gatekeeper_error_t;
struct SizedBuffer {
@@ -96,6 +98,13 @@ struct GateKeeperMessage {
gatekeeper_error_t Deserialize(const uint8_t *payload, const uint8_t *end);
/**
+ * Calls may fail due to throttling. If so, this sets a timeout in milliseconds
+ * for when the caller should attempt the call again. Additionally, sets the
+ * error to ERROR_RETRY.
+ */
+ void SetRetryTimeout(uint32_t retry_timeout);
+
+ /**
* The following methods are intended to be implemented by subclasses.
* They are hooks to serialize the elements specific to each particular
* specialization.
@@ -122,6 +131,7 @@ struct GateKeeperMessage {
gatekeeper_error_t error;
uint32_t user_id;
+ uint32_t retry_timeout;
};
struct VerifyRequest : public GateKeeperMessage {
@@ -154,6 +164,7 @@ struct VerifyResponse : public GateKeeperMessage {
virtual gatekeeper_error_t nonErrorDeserialize(const uint8_t *payload, const uint8_t *end);
SizedBuffer auth_token;
+ bool request_reenroll;
};
struct EnrollRequest : public GateKeeperMessage {
diff --git a/include/gatekeeper/password_handle.h b/include/gatekeeper/password_handle.h
index 9bf4cb2..3725f7c 100644
--- a/include/gatekeeper/password_handle.h
+++ b/include/gatekeeper/password_handle.h
@@ -25,7 +25,7 @@ typedef uint64_t salt_t;
* structure for easy serialization
* and deserialization of password handles.
*/
-static const uint8_t HANDLE_VERSION = 0;
+static const uint8_t HANDLE_VERSION = 1;
struct __attribute__ ((__packed__)) password_handle_t {
// fields included in signature
uint8_t version;
@@ -35,6 +35,8 @@ struct __attribute__ ((__packed__)) password_handle_t {
// fields not included in signature
salt_t salt;
uint8_t signature[32];
+
+ bool hardware_backed;
};
}
diff --git a/include/gatekeeper/soft_gatekeeper.h b/include/gatekeeper/soft_gatekeeper.h
deleted file mode 100644
index d4b4251..0000000
--- a/include/gatekeeper/soft_gatekeeper.h
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * Copyright 2015 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.
- *
- */
-
-#ifndef SOFT_GATEKEEPER_H_
-#define SOFT_GATEKEEPER_H_
-
-extern "C" {
-#include <openssl/rand.h>
-#include <crypto_scrypt.h>
-}
-
-#include <UniquePtr.h>
-#include <gatekeeper/gatekeeper.h>
-#include <iostream>
-
-namespace gatekeeper {
-
-
-class SoftGateKeeper : public GateKeeper {
-public:
- static const uint32_t SIGNATURE_LENGTH_BYTES = 32;
-
- // scrypt params
- static const uint64_t N = 16384;
- static const uint32_t r = 8;
- static const uint32_t p = 1;
-
- static const int MAX_UINT_32_CHARS = 11;
-
- SoftGateKeeper() {
- key_.reset(new uint8_t[SIGNATURE_LENGTH_BYTES]);
- memset(key_.get(), 0, SIGNATURE_LENGTH_BYTES);
- }
-
- virtual ~SoftGateKeeper() {
- }
-
- virtual bool GetAuthTokenKey(const uint8_t **auth_token_key,
- uint32_t *length) const {
- if (auth_token_key == NULL || length == NULL) return false;
- *auth_token_key = const_cast<const uint8_t *>(key_.get());
- *length = SIGNATURE_LENGTH_BYTES;
- return true;
- }
-
- virtual void GetPasswordKey(const uint8_t **password_key, uint32_t *length) {
- if (password_key == NULL || length == NULL) return;
- *password_key = const_cast<const uint8_t *>(key_.get());
- *length = SIGNATURE_LENGTH_BYTES;
- }
-
- virtual void ComputePasswordSignature(uint8_t *signature, uint32_t signature_length,
- const uint8_t *, uint32_t, const uint8_t *password,
- uint32_t password_length, salt_t salt) const {
- if (signature == NULL) return;
- crypto_scrypt(password, password_length, reinterpret_cast<uint8_t *>(&salt),
- sizeof(salt), N, r, p, signature, signature_length);
- }
-
- virtual void GetRandom(void *random, uint32_t requested_length) const {
- if (random == NULL) return;
- RAND_pseudo_bytes((uint8_t *) random, requested_length);
- }
-
- virtual void ComputeSignature(uint8_t *signature, uint32_t signature_length,
- const uint8_t *, uint32_t, const uint8_t *, const uint32_t) const {
- if (signature == NULL) return;
- memset(signature, 0, signature_length);
- }
-
- virtual uint64_t GetMillisecondsSinceBoot() const {
- struct timespec time;
- int res = clock_gettime(CLOCK_BOOTTIME, &time);
- if (res < 0) return 0;
- return (time.tv_sec * 1000) + (time.tv_nsec / 1000 / 1000);
- }
-private:
- UniquePtr<uint8_t> key_;
-};
-}
-
-#endif // SOFT_GATEKEEPER_H_
-
diff --git a/tests/Android.mk b/tests/Android.mk
index f1238af..203a524 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -25,6 +25,5 @@ LOCAL_STATIC_LIBRARIES := libscrypt_static
LOCAL_C_INCLUDES := external/scrypt/lib/crypto
LOCAL_SRC_FILES := \
gatekeeper_messages_test.cpp \
- gatekeeper_test.cpp \
gatekeeper_device_test.cpp
include $(BUILD_NATIVE_TEST)
diff --git a/tests/gatekeeper_device_test.cpp b/tests/gatekeeper_device_test.cpp
index 9f0d718..2c96941 100644
--- a/tests/gatekeeper_device_test.cpp
+++ b/tests/gatekeeper_device_test.cpp
@@ -63,8 +63,9 @@ TEST_F(GateKeeperDeviceTest, EnrollAndVerify) {
ASSERT_EQ(0, ret);
+ bool should_reenroll;
ret = device->verify(device, 0, 0, password_handle, password_handle_length,
- password_payload, password_len, &auth_token, &auth_token_len);
+ password_payload, password_len, &auth_token, &auth_token_len, &should_reenroll);
ASSERT_EQ(0, ret);
}
@@ -85,8 +86,10 @@ TEST_F(GateKeeperDeviceTest, EnrollAndVerifyBadPassword) {
password_payload[0] = 4;
+ bool should_reenroll;
ret = device->verify(device, 0, 0, password_handle, password_handle_length,
- password_payload, password_len, &auth_token, &auth_token_len);
+ password_payload, password_len, &auth_token, &auth_token_len,
+ &should_reenroll);
ASSERT_NE(0, ret);
ASSERT_EQ(NULL, auth_token);
diff --git a/tests/gatekeeper_test.cpp b/tests/gatekeeper_test.cpp
deleted file mode 100644
index c5e7087..0000000
--- a/tests/gatekeeper_test.cpp
+++ /dev/null
@@ -1,203 +0,0 @@
-/*
- * Copyright 2015 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 <gtest/gtest.h>
-#include <UniquePtr.h>
-#include <iostream>
-
-#include <gatekeeper/soft_gatekeeper.h>
-#include <hardware/hw_auth_token.h>
-
-using ::gatekeeper::SizedBuffer;
-using ::testing::Test;
-using ::gatekeeper::EnrollRequest;
-using ::gatekeeper::EnrollResponse;
-using ::gatekeeper::VerifyRequest;
-using ::gatekeeper::VerifyResponse;
-using ::gatekeeper::SoftGateKeeper;
-using ::gatekeeper::secure_id_t;
-
-static void do_enroll(SoftGateKeeper &gatekeeper, EnrollResponse *response) {
- SizedBuffer password;
-
- password.buffer.reset(new uint8_t[16]);
- password.length = 16;
- memset(password.buffer.get(), 0, 16);
- EnrollRequest request(0, NULL, &password, NULL);
-
- gatekeeper.Enroll(request, response);
-}
-
-TEST(GateKeeperTest, EnrollSuccess) {
- SoftGateKeeper gatekeeper;
- EnrollResponse response;
- do_enroll(gatekeeper, &response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
-}
-
-TEST(GateKeeperTest, EnrollBogusData) {
- SoftGateKeeper gatekeeper;
- SizedBuffer password;
- EnrollResponse response;
-
- EnrollRequest request(0, NULL, &password, NULL);
-
- gatekeeper.Enroll(request, &response);
-
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error);
-}
-
-TEST(GateKeeperTest, VerifySuccess) {
- SoftGateKeeper gatekeeper;
- SizedBuffer provided_password;
- EnrollResponse enroll_response;
-
- provided_password.buffer.reset(new uint8_t[16]);
- provided_password.length = 16;
- memset(provided_password.buffer.get(), 0, 16);
-
- do_enroll(gatekeeper, &enroll_response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
- VerifyRequest request(0, 1, &enroll_response.enrolled_password_handle,
- &provided_password);
- VerifyResponse response;
-
- gatekeeper.Verify(request, &response);
-
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
-
- hw_auth_token_t *auth_token =
- reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());
-
- ASSERT_EQ((uint32_t) HW_AUTH_PASSWORD, auth_token->authenticator_type);
- ASSERT_EQ((uint64_t) 1, auth_token->challenge);
- ASSERT_NE(~((uint32_t) 0), auth_token->timestamp);
- ASSERT_NE((uint64_t) 0, auth_token->user_id);
- ASSERT_NE((uint64_t) 0, auth_token->authenticator_id);
-}
-
-TEST(GateKeeperTest, TrustedReEnroll) {
- SoftGateKeeper gatekeeper;
- SizedBuffer provided_password;
- EnrollResponse enroll_response;
- SizedBuffer password_handle;
-
- // do_enroll enrolls an all 0 password
- provided_password.buffer.reset(new uint8_t[16]);
- provided_password.length = 16;
- memset(provided_password.buffer.get(), 0, 16);
- do_enroll(gatekeeper, &enroll_response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-
- // keep a copy of the handle
- password_handle.buffer.reset(new uint8_t[enroll_response.enrolled_password_handle.length]);
- password_handle.length = enroll_response.enrolled_password_handle.length;
- memcpy(password_handle.buffer.get(), enroll_response.enrolled_password_handle.buffer.get(),
- password_handle.length);
-
- // verify first password
- VerifyRequest request(0, 0, &enroll_response.enrolled_password_handle,
- &provided_password);
- VerifyResponse response;
- gatekeeper.Verify(request, &response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
- hw_auth_token_t *auth_token =
- reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());
-
- secure_id_t secure_id = auth_token->user_id;
-
- // enroll new password
- provided_password.buffer.reset(new uint8_t[16]);
- provided_password.length = 16;
- memset(provided_password.buffer.get(), 0, 16);
- SizedBuffer password;
- password.buffer.reset(new uint8_t[16]);
- memset(password.buffer.get(), 1, 16);
- password.length = 16;
- EnrollRequest enroll_request(0, &password_handle, &password, &provided_password);
- gatekeeper.Enroll(enroll_request, &enroll_response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-
- // verify new password
- password.buffer.reset(new uint8_t[16]);
- memset(password.buffer.get(), 1, 16);
- password.length = 16;
- VerifyRequest new_request(0, 0, &enroll_response.enrolled_password_handle,
- &password);
- gatekeeper.Verify(new_request, &response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
- ASSERT_EQ(secure_id,
- reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get())->user_id);
-}
-
-
-TEST(GateKeeperTest, UntrustedReEnroll) {
- SoftGateKeeper gatekeeper;
- SizedBuffer provided_password;
- EnrollResponse enroll_response;
-
- // do_enroll enrolls an all 0 password
- provided_password.buffer.reset(new uint8_t[16]);
- provided_password.length = 16;
- memset(provided_password.buffer.get(), 0, 16);
- do_enroll(gatekeeper, &enroll_response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-
- // verify first password
- VerifyRequest request(0, 0, &enroll_response.enrolled_password_handle,
- &provided_password);
- VerifyResponse response;
- gatekeeper.Verify(request, &response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
- hw_auth_token_t *auth_token =
- reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get());
-
- secure_id_t secure_id = auth_token->user_id;
-
- // enroll new password
- SizedBuffer password;
- password.buffer.reset(new uint8_t[16]);
- memset(password.buffer.get(), 1, 16);
- password.length = 16;
- EnrollRequest enroll_request(0, NULL, &password, NULL);
- gatekeeper.Enroll(enroll_request, &enroll_response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, enroll_response.error);
-
- // verify new password
- password.buffer.reset(new uint8_t[16]);
- memset(password.buffer.get(), 1, 16);
- password.length = 16;
- VerifyRequest new_request(0, 0, &enroll_response.enrolled_password_handle,
- &password);
- gatekeeper.Verify(new_request, &response);
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_NONE, response.error);
- ASSERT_NE(secure_id,
- reinterpret_cast<hw_auth_token_t *>(response.auth_token.buffer.get())->user_id);
-}
-
-
-TEST(GateKeeperTest, VerifyBogusData) {
- SoftGateKeeper gatekeeper;
- SizedBuffer provided_password;
- SizedBuffer password_handle;
- VerifyResponse response;
-
- VerifyRequest request(0, 0, &provided_password, &password_handle);
-
- gatekeeper.Verify(request, &response);
-
- ASSERT_EQ(::gatekeeper::gatekeeper_error_t::ERROR_INVALID, response.error);
-}