move throttling to GateKeeper layer

throttling is done in SW now, move directly into gatekeeper
to harden against root brute force attacks.

Bug:21118563
Change-Id: Ie8b22a9e1e6702c9f2007dc7f31e19a1c0fa1696
diff --git a/gatekeeper.cpp b/gatekeeper.cpp
index 77e14e2..20794b2 100644
--- a/gatekeeper.cpp
+++ b/gatekeeper.cpp
@@ -28,7 +28,8 @@
         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 @@
     } 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 @@
 
 
     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 @@
     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 @@
 
     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 @@
     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 @@
 
 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 @@
 
     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 @@
         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 @@
     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 @@
 }
 
 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 @@
         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 @@
      */
     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 @@
      * 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 @@
 typedef enum {
     ERROR_NONE = 0,
     ERROR_INVALID = 1,
+    ERROR_RETRY = 2,
+    ERROR_UNKNOWN = 3,
 } gatekeeper_error_t;
 
 struct SizedBuffer {
@@ -96,6 +98,13 @@
     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 @@
 
     gatekeeper_error_t error;
     uint32_t user_id;
+    uint32_t retry_timeout;
 };
 
 struct VerifyRequest : public GateKeeperMessage {
@@ -154,6 +164,7 @@
     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 @@
  * 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 @@
     // 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_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 @@
 
     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 @@
 
     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);
-}