Implement SoftKeyguard

scrypt/openssl based implementation of Keyguard

Change-Id: Ib04fee3bb34d81bfdb659ab1a9f16efd0cbd630f
diff --git a/Android.mk b/Android.mk
index b82d90a..8f5dc03 100644
--- a/Android.mk
+++ b/Android.mk
@@ -22,7 +22,7 @@
 LOCAL_MODULE:= libkeyguard
 LOCAL_SRC_FILES := \
 	keyguard_messages.cpp \
-	google_keyguard.cpp
+	keyguard.cpp
 LOCAL_C_INCLUDES := \
 	$(LOCAL_PATH)/include
 LOCAL_CFLAGS = -Wall -Werror
@@ -30,3 +30,4 @@
 LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/include
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 include $(BUILD_SHARED_LIBRARY)
+
diff --git a/include/keyguard/keyguard.h b/include/keyguard/keyguard.h
index cae9d05..7e06c3e 100644
--- a/include/keyguard/keyguard.h
+++ b/include/keyguard/keyguard.h
@@ -14,11 +14,12 @@
  * limitations under the License.
  */
 
-#ifndef GOOGLE_KEYGUARD_H_
-#define GOOGLE_KEYGUARD_H_
+#ifndef KEYGUARD_H_
+#define KEYGUARD_H_
 
 #include <memory>
 #include <stdint.h>
+#include <UniquePtr.h>
 
 #include "keyguard_messages.h"
 
@@ -47,45 +48,94 @@
  * the ability to create/access keys and compute signatures. These are left up
  * to the platform-specific implementation.
  */
-class GoogleKeyguard {
+class Keyguard {
 public:
-    GoogleKeyguard() {}
-    virtual ~GoogleKeyguard();
+    Keyguard() {}
+    virtual ~Keyguard();
 
     void Enroll(const EnrollRequest &request, EnrollResponse *response);
     void Verify(const VerifyRequest &request, VerifyResponse *response);
 
 protected:
-    /**
-     * Generates a signed attestation of an authentication event.
-     * The format is consistent with that of AuthToken above.
-     */
-    std::unique_ptr<uint8_t> MintAuthToken(uint32_t user_id, size_t *length);
 
     // The following methods are intended to be implemented by concrete subclasses
 
     /**
-     * Retrieves the key used by GoogleKeyguard::MintAuthToken to sign the payload
+     * Retrieves the key used by Keyguard::MintAuthToken to sign the payload
      * of the AuthToken. This is not cached as is may have changed due to an event such
      * as a password change.
+     *
+     * Assigns the auth token to the auth_token_key UniquePtr, relinquishing ownership
+     * to the caller.
+     * Writes the length in bytes of the returned key to length if it is not null.
+     *
      */
-    virtual std::unique_ptr<uint8_t[]> GetAuthTokenKey() const = 0;
+    virtual void GetAuthTokenKey(UniquePtr<uint8_t> *auth_token_key, size_t *length)
+        const = 0;
+
+    /**
+     * Uses platform-specific routines to compute a signature on the provided password.
+     *
+     * This can be implemented as a simple pass-through to ComputeSignature, but is
+     * available in case handling for password signatures is different from general
+     * purpose signatures.
+     *
+     * Assigns the signature to the signature UniquePtr, relinquishing ownership
+     * to the caller.
+     * Writes the length in bytes of the returned key to signature_length if it is not null.
+     *
+     */
+    virtual void ComputePasswordSignature(const uint8_t *key, size_t key_length,
+            const uint8_t *password, size_t password_length, const uint8_t *salt,
+            size_t salt_length, UniquePtr<uint8_t> *signature, size_t *signature_length) const = 0;
+
+    /**
+     * Retrieves a unique, cryptographically randomly generated salt for use in password
+     * hashing.
+     *
+     * Assings the salt to the salt UniquePtr, relinquishing ownership to the caller
+     * Writes the length in bytes of the salt to salt_length if it is not null.
+     */
+    virtual void GetSalt(UniquePtr<uint8_t> *salt, size_t *salt_length) const = 0;
 
     /**
      * Uses platform-specific routines to compute a signature on the provided message.
-     * Returns a pointer to the signature, as well as the length in signature_length if
-     * it is not NULL.
+     *
+     * Assigns the signature to the signature UniquePtr, relinquishing ownership
+     * to the caller.
+     * Writes the length in bytes of the returned key to signature_length if it is not null.
      */
-    virtual std::unique_ptr<uint8_t> ComputeSignature(const uint8_t key[],
-            const uint8_t *message, const size_t length, size_t *signature_length) const = 0;
+    virtual void ComputeSignature(const uint8_t *key, size_t key_length,
+            const uint8_t *message, const size_t length, UniquePtr<uint8_t> *signature,
+            size_t *signature_length) const = 0;
 
     /**
      * The key used to sign and verify password data. This is different from the AuthTokenKey.
      * It can be cached in this member variable as Keyguard is its only consumer. It should at
      * no point leave Keyguard for any reason.
      */
-    std::unique_ptr<uint8_t[]> password_key_;
+    SizedBuffer password_key_;
+
+private:
+    /**
+     * Generates a signed attestation of an authentication event and assings
+     * to auth_token UniquePtr.
+     * The format is consistent with that of AuthToken above.
+     * Also returns the length in length if it is not null.
+     */
+    void MintAuthToken(uint32_t user_id, UniquePtr<uint8_t> *auth_token, size_t *length);
+
+    // Takes a salt/signature and their lengths and generates a pasword handle written
+    // into result.
+    void SerializeHandle(const uint8_t *salt, size_t salt_length, const uint8_t *signature,
+        size_t signataure_length, SizedBuffer &result);
+
+    // Takes a handle and generates pointers into the salt and password inside the handle and
+    // copies out the sizes of those buffers. Makes no allocations.
+    keyguard_error_t DeserializeHandle(const SizedBuffer *handle, uint8_t **salt,
+        size_t *salt_length, uint8_t **password, size_t *password_length);
+
 };
 }
 
-#endif // GOOGLE_KEYGUARD_H_
+#endif // KEYGUARD_H_
diff --git a/include/keyguard/keyguard_messages.h b/include/keyguard/keyguard_messages.h
index 59c9f04..5851d26 100644
--- a/include/keyguard/keyguard_messages.h
+++ b/include/keyguard/keyguard_messages.h
@@ -16,10 +16,11 @@
 #ifndef KEYGUARD_MESSAGES_H_
 #define KEYGUARD_MESSAGES_H_
 
-#include <memory>
 #include <stdint.h>
+#include <UniquePtr.h>
 
-#include "google_keyguard_utils.h"
+
+#include "keyguard_utils.h"
 /**
  * Message serialization objects for communicating with the hardware keyguard.
  */
@@ -30,20 +31,27 @@
     KG_ERROR_INVALID = 1,
 } keyguard_error_t;
 
-typedef struct {
-    std::unique_ptr<uint8_t> buffer;
+struct SizedBuffer {
+    SizedBuffer() {
+        length = 0;
+    }
+    SizedBuffer(uint8_t *buf, size_t len) {
+        buffer.reset(buf);
+        length = len;
+    }
+
+    UniquePtr<uint8_t> buffer;
     size_t length;
-} SizedBuffer;
+};
 
 /*
  * Abstract base class of all message objects. Handles serialization of common
  * elements like the error and user ID. Delegates specialized serialization
  * to protected pure virtual functions implemented by subclasses.
  */
-class KeyguardMessage {
-public:
-    KeyguardMessage() : error_(KG_ERROR_OK) {}
-    KeyguardMessage(keyguard_error_t error) : error_(error) {}
+struct KeyguardMessage {
+    KeyguardMessage() : error(KG_ERROR_OK) {}
+    KeyguardMessage(keyguard_error_t error) : error(error) {}
     virtual ~KeyguardMessage() {}
 
     /**
@@ -63,11 +71,6 @@
      */
     keyguard_error_t Deserialize(const uint8_t *payload, const uint8_t *end);
 
-    keyguard_error_t GetError() const { return error_; }
-    void SetError(const keyguard_error_t error) { error_ = error; }
-    uint32_t GetUserId() const { return user_id_; }
-
-protected:
     /**
      * The following methods are intended to be implemented by subclasses.
      * They are hooks to serialize the elements specific to each particular
@@ -84,21 +87,20 @@
      * the subclass specific data into it. The size of the buffer is exaclty
      * that returned by nonErrorSerializedSize() in bytes.
      */
-    virtual void nonErrorSerialize(uint8_t *buffer) const { }
+    virtual void nonErrorSerialize(uint8_t *) const { }
 
     /**
      * Deserializes subclass specific data from payload without reading past end.
      */
-    virtual keyguard_error_t nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
+    virtual keyguard_error_t nonErrorDeserialize(const uint8_t *, const uint8_t *) {
         return KG_ERROR_OK;
     }
 
-    keyguard_error_t error_;
-    uint32_t user_id_;
+    keyguard_error_t error;
+    uint32_t user_id;
 };
 
-class VerifyRequest : public KeyguardMessage {
-public:
+struct VerifyRequest : public KeyguardMessage {
     VerifyRequest(
             uint32_t user_id,
             SizedBuffer *enrolled_password_handle,
@@ -106,78 +108,53 @@
     VerifyRequest();
     ~VerifyRequest();
 
-    /**
-     * The currently enrolled password handle returned by Enroll.
-     */
-    const SizedBuffer *GetPasswordHandle() const { return &password_handle_; }
-
-    /**
-     * The password provided by the user to be verified against the password handle
-     * above.
-     */
-    const SizedBuffer *GetProvidedPassword() const { return &provided_password_; }
-
-protected:
     virtual size_t nonErrorSerializedSize() const;
     virtual void nonErrorSerialize(uint8_t *buffer) const;
     virtual keyguard_error_t nonErrorDeserialize(const uint8_t *payload, const uint8_t *end);
 
-private:
-    SizedBuffer password_handle_;
-    SizedBuffer provided_password_;
+    SizedBuffer password_handle;
+    SizedBuffer provided_password;
 };
 
-class VerifyResponse : public KeyguardMessage {
-public:
+struct VerifyResponse : public KeyguardMessage {
     VerifyResponse(uint32_t user_id, SizedBuffer *verification_token);
     VerifyResponse();
     ~VerifyResponse();
 
     void SetVerificationToken(SizedBuffer *verification_token);
-    const SizedBuffer *GetVerificationToken() const { return &verification_token_; }
 
-protected:
     virtual size_t nonErrorSerializedSize() const;
     virtual void nonErrorSerialize(uint8_t *buffer) const;
     virtual keyguard_error_t nonErrorDeserialize(const uint8_t *payload, const uint8_t *end);
 
-private:
-    SizedBuffer verification_token_;
+    SizedBuffer verification_token;
 };
 
-class EnrollRequest : public KeyguardMessage {
-public:
+struct EnrollRequest : public KeyguardMessage {
     EnrollRequest(uint32_t user_id, SizedBuffer *provided_password);
     EnrollRequest();
     ~EnrollRequest();
 
-
-    const SizedBuffer *GetProvidedPassword() const { return &provided_password_; }
-
-protected:
     virtual size_t nonErrorSerializedSize() const;
     virtual void nonErrorSerialize(uint8_t *buffer) const;
     virtual keyguard_error_t nonErrorDeserialize(const uint8_t *payload, const uint8_t *end);
-private:
-    SizedBuffer provided_password_;
+
+    SizedBuffer provided_password;
 };
 
-class EnrollResponse : public KeyguardMessage {
+struct EnrollResponse : public KeyguardMessage {
 public:
     EnrollResponse(uint32_t user_id, SizedBuffer *enrolled_password_handle);
     EnrollResponse();
     ~EnrollResponse();
 
-    void SetEnrolledPasswordHandle(SizedBuffer *password_handle);
-    const SizedBuffer *GetEnrolledPasswordHandle() const { return &enrolled_password_handle_; }
+    void SetEnrolledPasswordHandle(SizedBuffer *enrolled_password_handle);
 
-protected:
     virtual size_t nonErrorSerializedSize() const;
     virtual void nonErrorSerialize(uint8_t *buffer) const;
     virtual keyguard_error_t nonErrorDeserialize(const uint8_t *payload, const uint8_t *end);
 
-private:
-   SizedBuffer enrolled_password_handle_;
+   SizedBuffer enrolled_password_handle;
 };
 }
 
diff --git a/include/keyguard/soft_keyguard.h b/include/keyguard/soft_keyguard.h
new file mode 100644
index 0000000..52712af
--- /dev/null
+++ b/include/keyguard/soft_keyguard.h
@@ -0,0 +1,83 @@
+/*
+ * 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_KEYGUARD_H_
+#define SOFT_KEYGUARD_H_
+
+extern "C" {
+#include <openssl/rand.h>
+#include <crypto_scrypt.h>
+}
+
+#include <UniquePtr.h>
+#include <keyguard/keyguard.h>
+
+namespace keyguard {
+
+class SoftKeyguard : public Keyguard {
+public:
+    static const size_t SALT_LENGTH = 8;
+    static const size_t SIGNATURE_LENGTH = 16;
+
+    // scrypt params
+    static const uint64_t N = 16384;
+    static const uint32_t r = 8;
+    static const uint32_t p = 1;
+
+    SoftKeyguard() {
+        password_key_.buffer.reset();
+        password_key_.length = 0;
+    }
+
+    virtual void GetAuthTokenKey(UniquePtr<uint8_t> *,
+            size_t *length) const {
+        // No auth token key for SW impl
+        if (length != NULL) *length = 0;
+    }
+
+    virtual void ComputePasswordSignature(const uint8_t *, size_t,
+            const uint8_t *password, size_t password_length, const uint8_t *salt, size_t salt_length,
+            UniquePtr<uint8_t> *signature, size_t *signature_length) const {
+        if (signature == NULL) return;
+        uint8_t *signature_bytes = new uint8_t[SIGNATURE_LENGTH];
+        crypto_scrypt(password, password_length, salt, salt_length, N, r, p,
+                signature_bytes, SIGNATURE_LENGTH);
+        if (signature_length != NULL) *signature_length = SIGNATURE_LENGTH;
+        signature->reset(signature_bytes);
+    }
+
+    virtual void GetSalt(UniquePtr<uint8_t> *salt, size_t *salt_length) const {
+        if (salt == NULL) return;
+        uint8_t *salt_bytes = new uint8_t[SALT_LENGTH];
+        RAND_pseudo_bytes(salt_bytes, SALT_LENGTH);
+        if (salt_length != NULL) *salt_length = SALT_LENGTH;
+        salt->reset(salt_bytes);
+    }
+
+    virtual void ComputeSignature(const uint8_t *, size_t,
+                const uint8_t *, const size_t, UniquePtr<uint8_t> *signature,
+                size_t *signature_length) const {
+        if (signature == NULL) return;
+        if (signature_length != NULL) *signature_length = SIGNATURE_LENGTH;
+        uint8_t *result = new uint8_t[16];
+        memset(result, 0, 16);
+        signature->reset(result);
+    }
+
+};
+}
+#endif // SOFT_KEYGUARD_H_
diff --git a/keyguard.cpp b/keyguard.cpp
index 95cfc73..e435a3f 100644
--- a/keyguard.cpp
+++ b/keyguard.cpp
@@ -13,80 +13,151 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-#include <sys/time.h>
+#include <time.h>
+#include <iostream>
+#include <iomanip>
+#include <UniquePtr.h>
 
-#include <keyguard/google_keyguard.h>
+#include <keyguard/keyguard.h>
 
 namespace keyguard {
 
-GoogleKeyguard::~GoogleKeyguard() {
-    if (password_key_) {
-        memset_s(password_key_.get(), 0, sizeof(password_key_.get()) / sizeof(password_key_[0]));
+Keyguard::~Keyguard() {
+    if (password_key_.buffer.get()) {
+        memset_s(password_key_.buffer.get(), 0, password_key_.length);
     }
 }
 
-void GoogleKeyguard::Enroll(const EnrollRequest &request, EnrollResponse *response) {
+void Keyguard::Enroll(const EnrollRequest &request, EnrollResponse *response) {
     if (response == NULL) return;
 
     SizedBuffer enrolled_password;
-    const SizedBuffer *provided_password = request.GetProvidedPassword();
-    if (provided_password == NULL || !provided_password->buffer) {
-        response->SetError(KG_ERROR_INVALID);
+    if (!request.provided_password.buffer.get()) {
+        response->error = KG_ERROR_INVALID;
         return;
     }
-    enrolled_password.buffer = ComputeSignature(password_key_.get(),
-            provided_password->buffer.get(), provided_password->length, &enrolled_password.length);
+
+    size_t salt_length;
+    UniquePtr<uint8_t> salt;
+    GetSalt(&salt, &salt_length);
+
+    size_t signature_length;
+    UniquePtr<uint8_t> signature;
+    ComputePasswordSignature(password_key_.buffer.get(),
+                password_key_.length, request.provided_password.buffer.get(),
+                request.provided_password.length, salt.get(), salt_length, &signature,
+                &signature_length);
+
+    SerializeHandle(salt.get(), salt_length, signature.get(), signature_length, enrolled_password);
     response->SetEnrolledPasswordHandle(&enrolled_password);
 }
 
-void GoogleKeyguard::Verify(const VerifyRequest &request, VerifyResponse *response) {
+void Keyguard::Verify(const VerifyRequest &request, VerifyResponse *response) {
     if (response == NULL) return;
 
-    const SizedBuffer *enrolled_password = request.GetPasswordHandle();
-    const SizedBuffer *provided_password = request.GetProvidedPassword();
-
-
-    if (provided_password == NULL || !provided_password->buffer
-            || enrolled_password == NULL || !enrolled_password->buffer) {
-        response->SetError(KG_ERROR_INVALID);
+    if (!request.provided_password.buffer.get() || !request.password_handle.buffer.get()) {
+        response->error = KG_ERROR_INVALID;
         return;
     }
 
-    SizedBuffer signed_provided_password;
-    signed_provided_password.buffer = ComputeSignature(password_key_.get(),
-            provided_password->buffer.get(), provided_password->length,
-            &signed_provided_password.length);
-    if (memcmp_s(enrolled_password->buffer.get(), signed_provided_password.buffer.get(),
-                enrolled_password->length) == 0) {
+    size_t salt_length, signature_length;
+    uint8_t *salt, *signature;
+    keyguard_error_t error = DeserializeHandle(
+            &request.password_handle, &salt, &salt_length, &signature, &signature_length);
+
+    if (error != KG_ERROR_OK) {
+        response->error = error;
+        return;
+    }
+
+    size_t provided_password_signature_length;
+    UniquePtr<uint8_t> provided_password_signature;
+    ComputePasswordSignature(password_key_.buffer.get(),
+            password_key_.length, request.provided_password.buffer.get(), request.provided_password.length,
+            salt, salt_length, &provided_password_signature, &provided_password_signature_length);
+
+    if (provided_password_signature_length == signature_length &&
+            memcmp_s(signature, provided_password_signature.get(), signature_length) == 0) {
         // Signature matches
         SizedBuffer auth_token;
-        auth_token.buffer = MintAuthToken(request.GetUserId(), &auth_token.length);
+        MintAuthToken(request.user_id, &auth_token.buffer, &auth_token.length);
         response->SetVerificationToken(&auth_token);
     } else {
-        response->SetError(KG_ERROR_INVALID);
+        response->error = KG_ERROR_INVALID;
     }
 }
 
-std::unique_ptr<uint8_t> GoogleKeyguard::MintAuthToken(uint32_t user_id, size_t *length) {
-    AuthToken *auth_token = new AuthToken;
+void Keyguard::MintAuthToken(uint32_t user_id, UniquePtr<uint8_t> *auth_token, size_t *length) {
+    if (auth_token == NULL) return;
+
+    AuthToken *token = new AuthToken;
     SizedBuffer serialized_auth_token;
 
-    struct timeval time;
-    gettimeofday(&time, NULL);
+    struct timespec time;
+    clock_gettime(CLOCK_MONOTONIC_RAW, &time);
 
-    auth_token->auth_token_size = sizeof(AuthToken) -
-        sizeof(auth_token->auth_token_tag) - sizeof(auth_token->auth_token_size);
-    auth_token->user_id = user_id;
-    auth_token->timestamp = static_cast<uint64_t>(time.tv_sec);
+    token->auth_token_size = sizeof(AuthToken) -
+        sizeof(token->auth_token_tag) - sizeof(token->auth_token_size);
+    token->user_id = user_id;
+    token->timestamp = static_cast<uint64_t>(time.tv_sec);
 
-    size_t hash_len = (size_t)((uint8_t *)&auth_token->hmac_tag - (uint8_t *)auth_token);
+    UniquePtr<uint8_t> auth_token_key;
+    size_t key_len;
+    GetAuthTokenKey(&auth_token_key, &key_len);
+
+    size_t hash_len = (size_t)((uint8_t *)&token->hmac_tag - (uint8_t *)token);
     size_t signature_len;
-    std::unique_ptr<uint8_t> signature = ComputeSignature(GetAuthTokenKey().get(),
-            reinterpret_cast<uint8_t *>(auth_token), hash_len, &signature_len);
+    UniquePtr<uint8_t> signature;
+    ComputeSignature(auth_token_key.get(), key_len,
+            reinterpret_cast<uint8_t *>(token), hash_len, &signature, &signature_len);
 
-    memcpy(&auth_token->hmac, signature.get(), sizeof(auth_token->hmac));
+    memset(&token->hmac, 0, sizeof(token->hmac));
+
+    memcpy(&token->hmac, signature.get(), signature_len > sizeof(token->hmac)
+            ? sizeof(token->hmac) : signature_len);
     if (length != NULL) *length = sizeof(AuthToken);
-    std::unique_ptr<uint8_t> result(reinterpret_cast<uint8_t *>(auth_token));
-    return result;
+    auth_token->reset(reinterpret_cast<uint8_t *>(token));
 }
+
+void Keyguard::SerializeHandle(const uint8_t *salt, size_t salt_length, const uint8_t *signature,
+        size_t signature_length, SizedBuffer &result) {
+    const size_t buffer_len = 2 * sizeof(size_t) + salt_length + signature_length;
+    result.buffer.reset(new uint8_t[buffer_len]);
+    result.length = buffer_len;
+    uint8_t *buffer = result.buffer.get();
+    memcpy(buffer, &salt_length, sizeof(salt_length));
+    buffer += sizeof(salt_length);
+    memcpy(buffer, salt, salt_length);
+    buffer += salt_length;
+    memcpy(buffer, &signature_length, sizeof(signature_length));
+    buffer += sizeof(signature_length);
+    memcpy(buffer, signature, signature_length);
+}
+
+keyguard_error_t Keyguard::DeserializeHandle(const SizedBuffer *handle, uint8_t **salt,
+        size_t *salt_length, uint8_t **password, size_t *password_length) {
+    if (handle && handle->length > (2 * sizeof(size_t))) {
+        int read = 0;
+        uint8_t *buffer = handle->buffer.get();
+        memcpy(salt_length, buffer, sizeof(*salt_length));
+        read += sizeof(*salt_length);
+        if (read + *salt_length < handle->length) {
+            *salt = buffer + read;
+            read += *salt_length;
+            if (read + sizeof(*password_length) < handle->length) {
+                buffer += read;
+                memcpy(password_length, buffer, sizeof(*password_length));
+                *password = buffer + sizeof(*password_length);
+            } else {
+                return KG_ERROR_INVALID;
+            }
+        } else {
+            return KG_ERROR_INVALID;
+        }
+
+        return KG_ERROR_OK;
+    }
+    return KG_ERROR_INVALID;
+}
+
 }
diff --git a/keyguard_messages.cpp b/keyguard_messages.cpp
index 2b550c4..d7b90a7 100644
--- a/keyguard_messages.cpp
+++ b/keyguard_messages.cpp
@@ -54,7 +54,7 @@
 
 
 size_t KeyguardMessage::GetSerializedSize() const {
-    if (error_ == KG_ERROR_OK) {
+    if (error == KG_ERROR_OK) {
         return 2 * sizeof(uint32_t) + nonErrorSerializedSize();
     } else {
         return sizeof(uint32_t);
@@ -62,15 +62,15 @@
 }
 
 uint8_t *KeyguardMessage::Serialize() const {
-    if (error_ != KG_ERROR_OK) {
+    if (error != KG_ERROR_OK) {
         uint32_t *error_buf = new uint32_t;
-        *error_buf = static_cast<uint32_t>(error_);
+        *error_buf = static_cast<uint32_t>(error);
         return reinterpret_cast<uint8_t *>(error_buf);
     } else {
         uint8_t *buf = new uint8_t[2*sizeof(uint32_t) + nonErrorSerializedSize()];
-        uint32_t error_value = static_cast<uint32_t>(error_);
+        uint32_t error_value = static_cast<uint32_t>(error);
         memcpy(buf, &error_value, sizeof(uint32_t));
-        memcpy(buf + sizeof(uint32_t), &user_id_, sizeof(user_id_));
+        memcpy(buf + sizeof(uint32_t), &user_id, sizeof(user_id));
         nonErrorSerialize(buf + 2*sizeof(uint32_t));
         return buf;
     }
@@ -80,177 +80,177 @@
     uint32_t error_value;
     if (payload + sizeof(uint32_t) > end) return KG_ERROR_INVALID;
     memcpy(&error_value, payload, sizeof(uint32_t));
-    error_ = static_cast<keyguard_error_t>(error_value);
+    error = static_cast<keyguard_error_t>(error_value);
     payload += sizeof(uint32_t);
-    if (error_ == KG_ERROR_OK) {
+    if (error == KG_ERROR_OK) {
         if (payload == end) return KG_ERROR_INVALID;
-        user_id_ = *((uint32_t *) payload);
-        error_ = nonErrorDeserialize(payload + sizeof(uint32_t), end);
+        user_id = *((uint32_t *) payload);
+        error = nonErrorDeserialize(payload + sizeof(uint32_t), end);
     }
 
-    return error_;
+    return error;
 }
 
 
 VerifyRequest::VerifyRequest(uint32_t user_id, SizedBuffer *enrolled_password_handle,
         SizedBuffer *provided_password_payload) {
-    user_id_ = user_id;
-    password_handle_.buffer = std::move(enrolled_password_handle->buffer);
-    password_handle_.length = enrolled_password_handle->length;
-    provided_password_.buffer = std::move(provided_password_payload->buffer);
-    provided_password_.length = provided_password_payload->length;
+    this->user_id = user_id;
+    this->password_handle.buffer.reset(enrolled_password_handle->buffer.release());
+    this->password_handle.length = enrolled_password_handle->length;
+    this->provided_password.buffer.reset(provided_password_payload->buffer.release());
+    this->provided_password.length = provided_password_payload->length;
 }
 
 VerifyRequest::VerifyRequest() {
-    memset_s(&password_handle_, 0, sizeof(password_handle_));
-    memset_s(&provided_password_, 0, sizeof(provided_password_));
+    memset_s(&password_handle, 0, sizeof(password_handle));
+    memset_s(&provided_password, 0, sizeof(provided_password));
 }
 
 VerifyRequest::~VerifyRequest() {
-    if (password_handle_.buffer) {
-        password_handle_.buffer.reset();
+    if (password_handle.buffer.get()) {
+        password_handle.buffer.reset();
     }
 
-    if (provided_password_.buffer) {
-        memset_s(provided_password_.buffer.get(), 0, provided_password_.length);
-        provided_password_.buffer.reset();
+    if (provided_password.buffer.get()) {
+        memset_s(provided_password.buffer.get(), 0, provided_password.length);
+        provided_password.buffer.reset();
     }
 }
 
 size_t VerifyRequest::nonErrorSerializedSize() const {
-    return serialized_buffer_size(password_handle_) + serialized_buffer_size(provided_password_);
+    return serialized_buffer_size(password_handle) + serialized_buffer_size(provided_password);
 }
 
 void VerifyRequest::nonErrorSerialize(uint8_t *buffer) const {
-    append_to_buffer(&buffer, &password_handle_);
-    append_to_buffer(&buffer, &provided_password_);
+    append_to_buffer(&buffer, &password_handle);
+    append_to_buffer(&buffer, &provided_password);
 }
 
 keyguard_error_t VerifyRequest::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
     keyguard_error_t error = KG_ERROR_OK;
 
-    if (password_handle_.buffer) {
-        password_handle_.buffer.reset();
+    if (password_handle.buffer.get()) {
+        password_handle.buffer.reset();
     }
 
-    if (provided_password_.buffer) {
-        memset_s(provided_password_.buffer.get(), 0, provided_password_.length);
-        provided_password_.buffer.reset();
+    if (provided_password.buffer.get()) {
+        memset_s(provided_password.buffer.get(), 0, provided_password.length);
+        provided_password.buffer.reset();
     }
 
-    error = read_from_buffer(&payload, end, &password_handle_);
+    error = read_from_buffer(&payload, end, &password_handle);
     if (error != KG_ERROR_OK) return error;
 
-    return read_from_buffer(&payload, end, &provided_password_);
+    return read_from_buffer(&payload, end, &provided_password);
 
 }
 
 VerifyResponse::VerifyResponse(uint32_t user_id, SizedBuffer *verification_token) {
-    user_id_ = user_id;
-    verification_token_.buffer = std::move(verification_token->buffer);
-    verification_token_.length = verification_token->length;
+    this->user_id = user_id;
+    this->verification_token.buffer.reset(verification_token->buffer.release());
+    this->verification_token.length = verification_token->length;
 }
 
 VerifyResponse::VerifyResponse() {
-    memset_s(&verification_token_, 0, sizeof(verification_token_));
+    memset_s(&verification_token, 0, sizeof(verification_token));
 };
 
 VerifyResponse::~VerifyResponse() {
-    if (verification_token_.length > 0) {
-        verification_token_.buffer.reset();
+    if (verification_token.length > 0) {
+        verification_token.buffer.reset();
     }
 }
 
 void VerifyResponse::SetVerificationToken(SizedBuffer *verification_token) {
-    verification_token_.buffer = std::move(verification_token->buffer);
-    verification_token_.length = verification_token->length;
+    this->verification_token.buffer.reset(verification_token->buffer.release());
+    this->verification_token.length = verification_token->length;
 }
 
 size_t VerifyResponse::nonErrorSerializedSize() const {
-    return serialized_buffer_size(verification_token_);
+    return serialized_buffer_size(verification_token);
 }
 
 void VerifyResponse::nonErrorSerialize(uint8_t *buffer) const {
-    append_to_buffer(&buffer, &verification_token_);
+    append_to_buffer(&buffer, &verification_token);
 }
 
 keyguard_error_t VerifyResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
-    if (verification_token_.buffer) {
-        verification_token_.buffer.reset();
+    if (verification_token.buffer.get()) {
+        verification_token.buffer.reset();
     }
 
-    return read_from_buffer(&payload, end, &verification_token_);
+    return read_from_buffer(&payload, end, &verification_token);
 }
 
 EnrollRequest::EnrollRequest(uint32_t user_id, SizedBuffer *provided_password) {
-    user_id_ = user_id;
-    provided_password_.buffer = std::move(provided_password->buffer);
-    provided_password_.length = provided_password->length;
+    this->user_id = user_id;
+    this->provided_password.buffer.reset(provided_password->buffer.release());
+    this->provided_password.length = provided_password->length;
 }
 
 EnrollRequest::EnrollRequest() {
-    memset_s(&provided_password_, 0, sizeof(provided_password_));
+    memset_s(&provided_password, 0, sizeof(provided_password));
 }
 
 EnrollRequest::~EnrollRequest() {
-    if (provided_password_.buffer) {
-        memset_s(provided_password_.buffer.get(), 0, provided_password_.length);
-        provided_password_.buffer.reset();
+    if (provided_password.buffer.get()) {
+        memset_s(provided_password.buffer.get(), 0, provided_password.length);
+        provided_password.buffer.reset();
     }
 }
 
 size_t EnrollRequest::nonErrorSerializedSize() const {
-   return serialized_buffer_size(provided_password_);
+   return serialized_buffer_size(provided_password);
 }
 
 void EnrollRequest::nonErrorSerialize(uint8_t *buffer) const {
-    append_to_buffer(&buffer, &provided_password_);
+    append_to_buffer(&buffer, &provided_password);
 }
 
 keyguard_error_t EnrollRequest::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
-    if (provided_password_.buffer) {
-        memset_s(provided_password_.buffer.get(), 0, provided_password_.length);
-        provided_password_.buffer.reset();
+    if (provided_password.buffer.get()) {
+        memset_s(provided_password.buffer.get(), 0, provided_password.length);
+        provided_password.buffer.reset();
     }
 
-    return read_from_buffer(&payload, end, &provided_password_);
+    return read_from_buffer(&payload, end, &provided_password);
 }
 
 EnrollResponse::EnrollResponse(uint32_t user_id, SizedBuffer *enrolled_password_handle) {
-    user_id_ = user_id;
-    enrolled_password_handle_.buffer = std::move(enrolled_password_handle->buffer);
-    enrolled_password_handle_.length = enrolled_password_handle->length;
+    this->user_id = user_id;
+    this->enrolled_password_handle.buffer.reset(enrolled_password_handle->buffer.release());
+    this->enrolled_password_handle.length = enrolled_password_handle->length;
 }
 
 EnrollResponse::EnrollResponse() {
-    memset_s(&enrolled_password_handle_, 0, sizeof(enrolled_password_handle_));
+    memset_s(&enrolled_password_handle, 0, sizeof(enrolled_password_handle));
 }
 
 EnrollResponse::~EnrollResponse() {
-    if (enrolled_password_handle_.buffer) {
-        enrolled_password_handle_.buffer.reset();
+    if (enrolled_password_handle.buffer.get()) {
+        enrolled_password_handle.buffer.reset();
     }
 }
 
 void EnrollResponse::SetEnrolledPasswordHandle(SizedBuffer *enrolled_password_handle) {
-    enrolled_password_handle_.buffer = std::move(enrolled_password_handle->buffer);
-    enrolled_password_handle_.length = enrolled_password_handle->length;
+    this->enrolled_password_handle.buffer.reset(enrolled_password_handle->buffer.release());
+    this->enrolled_password_handle.length = enrolled_password_handle->length;
 }
 
 size_t EnrollResponse::nonErrorSerializedSize() const {
-    return serialized_buffer_size(enrolled_password_handle_);
+    return serialized_buffer_size(enrolled_password_handle);
 }
 
 void EnrollResponse::nonErrorSerialize(uint8_t *buffer) const {
-    append_to_buffer(&buffer, &enrolled_password_handle_);
+    append_to_buffer(&buffer, &enrolled_password_handle);
 }
 
 keyguard_error_t EnrollResponse::nonErrorDeserialize(const uint8_t *payload, const uint8_t *end) {
-    if (enrolled_password_handle_.buffer) {
-        enrolled_password_handle_.buffer.reset();
+    if (enrolled_password_handle.buffer.get()) {
+        enrolled_password_handle.buffer.reset();
     }
 
-    return read_from_buffer(&payload, end, &enrolled_password_handle_);
+    return read_from_buffer(&payload, end, &enrolled_password_handle);
 }
 
 };
diff --git a/tests/Android.mk b/tests/Android.mk
index 7b2f1f3..cca7038 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -20,7 +20,9 @@
 LOCAL_MODULE := keyguard-unit-tests
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 LOCAL_CFLAGS += -g -Wall -Werror -std=gnu++11 -Wno-missing-field-initializers
-LOCAL_SHARED_LIBRARIES += libkeyguard
+LOCAL_SHARED_LIBRARIES := libkeyguard libcrypto 
+LOCAL_STATIC_LIBRARIES := libscrypt_static
+LOCAL_C_INCLUDES := external/scrypt/lib/crypto
 LOCAL_SRC_FILES := \
 	keyguard_messages_test.cpp \
 	keyguard_test.cpp
diff --git a/tests/keyguard_messages_test.cpp b/tests/keyguard_messages_test.cpp
index dc579f7..10f81bd 100644
--- a/tests/keyguard_messages_test.cpp
+++ b/tests/keyguard_messages_test.cpp
@@ -58,12 +58,13 @@
     delete[] serialized_req;
 
     ASSERT_EQ(keyguard::keyguard_error_t::KG_ERROR_OK,
-            deserialized_req.GetError());
+            deserialized_req.error);
 
-    deserialized_password = deserialized_req.GetProvidedPassword();
-    ASSERT_EQ(USER_ID, deserialized_req.GetUserId());
+    deserialized_password = &deserialized_req.provided_password;
+    ASSERT_EQ(USER_ID, deserialized_req.user_id);
     ASSERT_EQ((uint32_t) password_size, deserialized_password->length);
-    ASSERT_EQ(0, memcmp(req.GetProvidedPassword()->buffer.get(), deserialized_password->buffer.get(), password_size));
+    ASSERT_EQ(0, memcmp(req.provided_password.buffer.get(), deserialized_password->buffer.get(), password_size));
+    delete provided_password;
 }
 
 TEST(RoundTripTest, EnrollResponse) {
@@ -78,12 +79,13 @@
     delete[] serialized_req;
 
     ASSERT_EQ(keyguard::keyguard_error_t::KG_ERROR_OK,
-            deserialized_req.GetError());
+            deserialized_req.error);
 
-    deserialized_password = deserialized_req.GetEnrolledPasswordHandle();
-    ASSERT_EQ(USER_ID, deserialized_req.GetUserId());
+    deserialized_password = &deserialized_req.enrolled_password_handle;
+    ASSERT_EQ(USER_ID, deserialized_req.user_id);
     ASSERT_EQ((uint32_t) password_size, deserialized_password->length);
-    ASSERT_EQ(0, memcmp(req.GetEnrolledPasswordHandle()->buffer.get(), deserialized_password->buffer.get(), password_size));
+    ASSERT_EQ(0, memcmp(req.enrolled_password_handle.buffer.get(),
+                deserialized_password->buffer.get(), password_size));
 }
 
 TEST(RoundTripTest, VerifyRequest) {
@@ -98,16 +100,18 @@
     deserialized_req.Deserialize(serialized_req, serialized_req + req.GetSerializedSize());
 
     ASSERT_EQ(keyguard::keyguard_error_t::KG_ERROR_OK,
-            deserialized_req.GetError());
+            deserialized_req.error);
 
-    ASSERT_EQ(USER_ID, deserialized_req.GetUserId());
-    deserialized_password = deserialized_req.GetProvidedPassword();
+    ASSERT_EQ(USER_ID, deserialized_req.user_id);
+    deserialized_password = &deserialized_req.password_handle;
     ASSERT_EQ((uint32_t) password_size, deserialized_password->length);
-    ASSERT_EQ(0, memcmp(req.GetProvidedPassword()->buffer.get(), deserialized_password->buffer.get(), password_size));
+    ASSERT_EQ(0, memcmp(req.provided_password.buffer.get(), deserialized_password->buffer.get(),
+                password_size));
 
-    deserialized_password = deserialized_req.GetPasswordHandle();
+    deserialized_password = &deserialized_req.password_handle;
     ASSERT_EQ((uint32_t) password_size, deserialized_password->length);
-    ASSERT_EQ(0, memcmp(req.GetPasswordHandle()->buffer.get(), deserialized_password->buffer.get(), password_size));
+    ASSERT_EQ(0, memcmp(req.password_handle.buffer.get(), deserialized_password->buffer.get(),
+                password_size));
 }
 
 TEST(RoundTripTest, VerifyResponse) {
@@ -122,12 +126,13 @@
     delete[] serialized_req;
 
     ASSERT_EQ(keyguard::keyguard_error_t::KG_ERROR_OK,
-            deserialized_req.GetError());
+            deserialized_req.error);
 
-    ASSERT_EQ(USER_ID, deserialized_req.GetUserId());
-    deserialized_password = deserialized_req.GetVerificationToken();
+    ASSERT_EQ(USER_ID, deserialized_req.user_id);
+    deserialized_password = &deserialized_req.verification_token;
     ASSERT_EQ((uint32_t) password_size, deserialized_password->length);
-    ASSERT_EQ(0, memcmp(req.GetVerificationToken()->buffer.get(), deserialized_password->buffer.get(), password_size));
+    ASSERT_EQ(0, memcmp(req.verification_token.buffer.get(), deserialized_password->buffer.get(),
+                password_size));
 }
 
 uint8_t msgbuf[] = {
diff --git a/tests/keyguard_test.cpp b/tests/keyguard_test.cpp
index 8b733df..4ee09ba 100644
--- a/tests/keyguard_test.cpp
+++ b/tests/keyguard_test.cpp
@@ -15,8 +15,9 @@
  */
 
 #include <gtest/gtest.h>
+#include <UniquePtr.h>
 
-#include <keyguard/google_keyguard.h>
+#include <keyguard/soft_keyguard.h>
 
 using ::keyguard::SizedBuffer;
 using ::testing::Test;
@@ -24,54 +25,29 @@
 using ::keyguard::EnrollResponse;
 using ::keyguard::VerifyRequest;
 using ::keyguard::VerifyResponse;
-using ::keyguard::GoogleKeyguard;
+using ::keyguard::SoftKeyguard;
 using ::keyguard::AuthToken;
 
-class FakeKeyguard : public GoogleKeyguard {
-public:
-    FakeKeyguard() {
-        password_key_ = std::unique_ptr<uint8_t[]>(new uint8_t[16] {
-                2, 34, 23, 43, 52, 25, 234, 22, 65, 24, 90,
-                48, 5, 52, 62, 12 });
-    }
-
-private:
-    std::unique_ptr<uint8_t[]> GetAuthTokenKey() const {
-        return std::unique_ptr<uint8_t[]>(new uint8_t[16] {
-                2, 34, 23, 43, 52, 25, 234, 22, 65, 24, 90,
-                48, 5, 52, 62, 12 });
-    }
-
-    std::unique_ptr<uint8_t> ComputeSignature(const uint8_t key[],
-            const uint8_t *message, const size_t length, size_t *signature_length) const {
-        const size_t signature_size = 16;
-        uint8_t *signature = new uint8_t[signature_size];
-        memset(signature, 0, signature_size);
-        size_t len = length >= signature_size ? signature_size : length;
-        memcpy(signature, message, len);
-        if (signature_length != NULL) *signature_length = len;
-        return std::unique_ptr<uint8_t>(signature);
-    }
-};
-
-TEST(KeyguardTest, EnrollSuccess) {
-    FakeKeyguard keyguard;
+static void do_enroll(SoftKeyguard &keyguard, EnrollResponse *response) {
     SizedBuffer password;
-    EnrollResponse response;
 
-    password.buffer = std::unique_ptr<uint8_t>(new uint8_t[16]);
+    password.buffer.reset(new uint8_t[16]);
     password.length = 16;
     memset(password.buffer.get(), 0, 16);
     EnrollRequest request(0, &password);
 
-    keyguard.Enroll(request, &response);
+    keyguard.Enroll(request, response);
+}
 
-    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.GetError());
-    ASSERT_EQ((size_t) 16, response.GetEnrolledPasswordHandle()->length);
+TEST(KeyguardTest, EnrollSuccess) {
+    SoftKeyguard keyguard;
+    EnrollResponse response;
+    do_enroll(keyguard, &response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.error);
 }
 
 TEST(KeyguardTest, EnrollBogusData) {
-    FakeKeyguard keyguard;
+    SoftKeyguard keyguard;
     SizedBuffer password;
     EnrollResponse response;
 
@@ -79,31 +55,30 @@
 
     keyguard.Enroll(request, &response);
 
-    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_INVALID, response.GetError());
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_INVALID, response.error);
 }
 
 TEST(KeyguardTest, VerifySuccess) {
-    FakeKeyguard keyguard;
+    SoftKeyguard keyguard;
     SizedBuffer provided_password;
-    SizedBuffer password_handle;
+    EnrollResponse enroll_response;
 
-    provided_password.buffer = std::unique_ptr<uint8_t>(new uint8_t[16]);
+    provided_password.buffer.reset(new uint8_t[16]);
     provided_password.length = 16;
     memset(provided_password.buffer.get(), 0, 16);
 
-    password_handle.buffer = std::unique_ptr<uint8_t>(new uint8_t[16]);
-    password_handle.length = 16;
-    memset(password_handle.buffer.get(), 0, 16);
-
-    VerifyRequest request(0, &password_handle, &provided_password);
+    do_enroll(keyguard, &enroll_response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, enroll_response.error);
+    VerifyRequest request(0, &enroll_response.enrolled_password_handle,
+            &provided_password);
     VerifyResponse response;
 
     keyguard.Verify(request, &response);
 
-    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.GetError());
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.error);
 
     AuthToken *auth_token =
-        reinterpret_cast<AuthToken *>(response.GetVerificationToken()->buffer.get());
+        reinterpret_cast<AuthToken *>(response.verification_token.buffer.get());
 
     ASSERT_EQ((uint8_t) 1, auth_token->auth_token_tag);
     ASSERT_EQ((uint8_t) 2, auth_token->user_id_tag);
@@ -115,7 +90,7 @@
 }
 
 TEST(KeyguardTest, VerifyBogusData) {
-    FakeKeyguard keyguard;
+    SoftKeyguard keyguard;
     SizedBuffer provided_password;
     SizedBuffer password_handle;
     VerifyResponse response;
@@ -124,5 +99,5 @@
 
     keyguard.Verify(request, &response);
 
-    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_INVALID, response.GetError());
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_INVALID, response.error);
 }