add SIDs and password storage support to Keyguard base

Change-Id: I2b1bb41a5e40e45e810f2bd299edb6b8765df9e6
diff --git a/tests/keyguard_device_test.cpp b/tests/keyguard_device_test.cpp
index 0bc7db9..b3f3b21 100644
--- a/tests/keyguard_device_test.cpp
+++ b/tests/keyguard_device_test.cpp
@@ -55,7 +55,7 @@
     size_t auth_token_len;
     int ret;
 
-    ret = device->enroll(device, 0, password_payload, password_len,
+    ret = device->enroll(device, 0, NULL, 0, NULL, 0,  password_payload, password_len,
             &password_handle, &password_handle_length);
 
     ASSERT_EQ(0, ret);
@@ -75,8 +75,8 @@
     size_t auth_token_len;
     int ret;
 
-    ret = device->enroll(device, 0, password_payload, password_len,
-            &password_handle, &password_handle_length);
+    ret = device->enroll(device, 0, NULL, 0, NULL, 0,  password_payload, password_len,
+             &password_handle, &password_handle_length);
 
     ASSERT_EQ(0, ret);
 
diff --git a/tests/keyguard_messages_test.cpp b/tests/keyguard_messages_test.cpp
index 10f81bd..fd70c07 100644
--- a/tests/keyguard_messages_test.cpp
+++ b/tests/keyguard_messages_test.cpp
@@ -46,12 +46,12 @@
     return result;
 }
 
-TEST(RoundTripTest, EnrollRequest) {
+TEST(RoundTripTest, EnrollRequestNullEnrolledNullHandle) {
     const size_t password_size = 512;
     SizedBuffer *provided_password = make_buffer(password_size);
     const SizedBuffer *deserialized_password;
     // create request, serialize, deserialize, and validate
-    EnrollRequest req(USER_ID, provided_password);
+    EnrollRequest req(USER_ID, NULL, provided_password, NULL);
     uint8_t *serialized_req = req.Serialize();
     EnrollRequest deserialized_req;
     deserialized_req.Deserialize(serialized_req, serialized_req + req.GetSerializedSize());
@@ -64,9 +64,74 @@
     ASSERT_EQ(USER_ID, deserialized_req.user_id);
     ASSERT_EQ((uint32_t) password_size, deserialized_password->length);
     ASSERT_EQ(0, memcmp(req.provided_password.buffer.get(), deserialized_password->buffer.get(), password_size));
+    ASSERT_EQ((size_t) 0, deserialized_req.enrolled_password.length);
+    ASSERT_EQ(NULL, deserialized_req.enrolled_password.buffer.get());
+    ASSERT_EQ((size_t) 0, deserialized_req.password_handle.length);
+    ASSERT_EQ(NULL, deserialized_req.password_handle.buffer.get());
     delete provided_password;
 }
 
+TEST(RoundTripTest, EnrollRequestEmptyEnrolledEmptyHandle) {
+    const size_t password_size = 512;
+    SizedBuffer *provided_password = make_buffer(password_size);
+    SizedBuffer enrolled;
+    SizedBuffer handle;
+    const SizedBuffer *deserialized_password;
+    // create request, serialize, deserialize, and validate
+    EnrollRequest req(USER_ID, &handle, provided_password, &enrolled);
+    uint8_t *serialized_req = req.Serialize();
+    EnrollRequest deserialized_req;
+    deserialized_req.Deserialize(serialized_req, serialized_req + req.GetSerializedSize());
+    delete[] serialized_req;
+
+    ASSERT_EQ(keyguard::keyguard_error_t::KG_ERROR_OK,
+            deserialized_req.error);
+
+    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.provided_password.buffer.get(), deserialized_password->buffer.get(), password_size));
+    ASSERT_EQ((size_t) 0, deserialized_req.enrolled_password.length);
+    ASSERT_EQ(NULL, deserialized_req.enrolled_password.buffer.get());
+    ASSERT_EQ((size_t) 0, deserialized_req.password_handle.length);
+    ASSERT_EQ(NULL, deserialized_req.password_handle.buffer.get());
+    delete provided_password;
+}
+
+TEST(RoundTripTest, EnrollRequestNonNullEnrolledOrHandle) {
+    const size_t password_size = 512;
+    SizedBuffer *provided_password = make_buffer(password_size);
+    SizedBuffer *enrolled_password = make_buffer(password_size);
+    SizedBuffer *password_handle = make_buffer(password_size);
+    const SizedBuffer *deserialized_password;
+    const SizedBuffer *deserialized_enrolled;
+    const SizedBuffer *deserialized_handle;
+    // create request, serialize, deserialize, and validate
+    EnrollRequest req(USER_ID, password_handle, provided_password, enrolled_password);
+    uint8_t *serialized_req = req.Serialize();
+    EnrollRequest deserialized_req;
+    deserialized_req.Deserialize(serialized_req, serialized_req + req.GetSerializedSize());
+    delete[] serialized_req;
+
+    ASSERT_EQ(keyguard::keyguard_error_t::KG_ERROR_OK,
+            deserialized_req.error);
+
+    deserialized_password = &deserialized_req.provided_password;
+    deserialized_enrolled = &deserialized_req.enrolled_password;
+    deserialized_handle = &deserialized_req.password_handle;
+    ASSERT_EQ(USER_ID, deserialized_req.user_id);
+    ASSERT_EQ((uint32_t) password_size, deserialized_password->length);
+    ASSERT_EQ(0, memcmp(req.provided_password.buffer.get(), deserialized_password->buffer.get(), password_size));
+    ASSERT_EQ((uint32_t) password_size, deserialized_enrolled->length);
+    ASSERT_EQ(0, memcmp(req.enrolled_password.buffer.get(), deserialized_enrolled->buffer.get(), password_size));
+    ASSERT_EQ((uint32_t) password_size, deserialized_handle->length);
+    ASSERT_EQ(0, memcmp(req.password_handle.buffer.get(), deserialized_handle->buffer.get(), password_size));
+    delete provided_password;
+    delete enrolled_password;
+    delete password_handle;
+}
+
+
 TEST(RoundTripTest, EnrollResponse) {
     const size_t password_size = 512;
     SizedBuffer *enrolled_password = make_buffer(password_size);
@@ -116,10 +181,10 @@
 
 TEST(RoundTripTest, VerifyResponse) {
     const size_t password_size = 512;
-    SizedBuffer *verification_token = make_buffer(password_size);
+    SizedBuffer *auth_token = make_buffer(password_size);
     const SizedBuffer *deserialized_password;
     // create request, serialize, deserialize, and validate
-    VerifyResponse req(USER_ID, verification_token);
+    VerifyResponse req(USER_ID, auth_token);
     uint8_t *serialized_req = req.Serialize();
     VerifyResponse deserialized_req;
     deserialized_req.Deserialize(serialized_req, serialized_req + req.GetSerializedSize());
@@ -129,9 +194,9 @@
             deserialized_req.error);
 
     ASSERT_EQ(USER_ID, deserialized_req.user_id);
-    deserialized_password = &deserialized_req.verification_token;
+    deserialized_password = &deserialized_req.auth_token;
     ASSERT_EQ((uint32_t) password_size, deserialized_password->length);
-    ASSERT_EQ(0, memcmp(req.verification_token.buffer.get(), deserialized_password->buffer.get(),
+    ASSERT_EQ(0, memcmp(req.auth_token.buffer.get(), deserialized_password->buffer.get(),
                 password_size));
 }
 
diff --git a/tests/keyguard_test.cpp b/tests/keyguard_test.cpp
index 4ee09ba..02a6c34 100644
--- a/tests/keyguard_test.cpp
+++ b/tests/keyguard_test.cpp
@@ -16,6 +16,7 @@
 
 #include <gtest/gtest.h>
 #include <UniquePtr.h>
+#include <iostream>
 
 #include <keyguard/soft_keyguard.h>
 
@@ -27,6 +28,33 @@
 using ::keyguard::VerifyResponse;
 using ::keyguard::SoftKeyguard;
 using ::keyguard::AuthToken;
+using ::keyguard::secure_id_t;
+
+class TestKeyguardFileIo : public ::keyguard::KeyguardFileIo {
+public:
+    TestKeyguardFileIo() {
+        bytes_.length = 0;
+    }
+
+    virtual void Write(const char *filename, const uint8_t *bytes, size_t length) {
+        bytes_.buffer.reset(new uint8_t[length]);
+        memcpy(bytes_.buffer.get(), bytes, length);
+        bytes_.length = length;
+    }
+
+    virtual size_t Read(const char *filename, UniquePtr<uint8_t> *bytes) const {
+        if (!bytes_.buffer.get() || bytes_.length == 0) {
+            bytes->reset();
+        } else {
+            bytes->reset(new uint8_t[bytes_.length]);
+            memcpy(bytes->get(), bytes_.buffer.get(), bytes_.length);
+        }
+
+        return bytes_.length;
+    }
+
+    SizedBuffer bytes_;
+};
 
 static void do_enroll(SoftKeyguard &keyguard, EnrollResponse *response) {
     SizedBuffer password;
@@ -34,24 +62,24 @@
     password.buffer.reset(new uint8_t[16]);
     password.length = 16;
     memset(password.buffer.get(), 0, 16);
-    EnrollRequest request(0, &password);
+    EnrollRequest request(0, NULL, &password, NULL);
 
     keyguard.Enroll(request, response);
 }
 
 TEST(KeyguardTest, EnrollSuccess) {
-    SoftKeyguard keyguard;
+    SoftKeyguard keyguard(new TestKeyguardFileIo());
     EnrollResponse response;
     do_enroll(keyguard, &response);
     ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.error);
 }
 
 TEST(KeyguardTest, EnrollBogusData) {
-    SoftKeyguard keyguard;
+    SoftKeyguard keyguard(new TestKeyguardFileIo());
     SizedBuffer password;
     EnrollResponse response;
 
-    EnrollRequest request(0, &password);
+    EnrollRequest request(0, NULL, &password, NULL);
 
     keyguard.Enroll(request, &response);
 
@@ -59,7 +87,7 @@
 }
 
 TEST(KeyguardTest, VerifySuccess) {
-    SoftKeyguard keyguard;
+    SoftKeyguard keyguard(new TestKeyguardFileIo());
     SizedBuffer provided_password;
     EnrollResponse enroll_response;
 
@@ -78,19 +106,144 @@
     ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.error);
 
     AuthToken *auth_token =
-        reinterpret_cast<AuthToken *>(response.verification_token.buffer.get());
+        reinterpret_cast<AuthToken *>(response.auth_token.buffer.get());
 
-    ASSERT_EQ((uint8_t) 1, auth_token->auth_token_tag);
-    ASSERT_EQ((uint8_t) 2, auth_token->user_id_tag);
-    ASSERT_EQ((uint8_t) 3, auth_token->authenticator_id_tag);
-    ASSERT_EQ((uint8_t) 4, auth_token->timestamp_tag);
-
-    ASSERT_EQ((uint32_t)0, auth_token->user_id);
-    ASSERT_EQ((uint32_t)0, auth_token->authenticator_id);
+    ASSERT_EQ((uint32_t) 0, auth_token->authenticator_id);
+    ASSERT_NE(~((uint32_t) 0), auth_token->timestamp);
+    ASSERT_NE((uint64_t) 0, auth_token->root_secure_user_id);
+    ASSERT_NE((uint64_t) 0, auth_token->auxiliary_secure_user_id);
 }
 
+TEST(KeyguardTest, VerifyBadPwFile) {
+    TestKeyguardFileIo *fw = new TestKeyguardFileIo();
+    SoftKeyguard keyguard(fw);
+    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(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;
+    fw->bytes_.buffer.reset();
+    keyguard.Verify(request, &response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.error);
+
+    AuthToken *auth_token =
+        reinterpret_cast<AuthToken *>(response.auth_token.buffer.get());
+
+    ASSERT_EQ((uint32_t) 0, auth_token->authenticator_id);
+    ASSERT_NE(~((uint32_t) 0), auth_token->timestamp);
+    ASSERT_EQ((uint64_t) 0, auth_token->root_secure_user_id);
+    ASSERT_EQ((uint64_t) 0, auth_token->auxiliary_secure_user_id);
+}
+
+TEST(KeyguardTest, TrustedReEnroll) {
+    SoftKeyguard keyguard(new TestKeyguardFileIo());
+    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(keyguard, &enroll_response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, 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, &enroll_response.enrolled_password_handle,
+            &provided_password);
+    VerifyResponse response;
+    keyguard.Verify(request, &response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.error);
+    AuthToken *auth_token =
+        reinterpret_cast<AuthToken *>(response.auth_token.buffer.get());
+
+    secure_id_t secure_id = auth_token->root_secure_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);
+    keyguard.Enroll(enroll_request, &enroll_response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, 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, &enroll_response.enrolled_password_handle,
+            &password);
+    keyguard.Verify(new_request, &response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.error);
+    ASSERT_EQ(secure_id,
+        reinterpret_cast<AuthToken *>(response.auth_token.buffer.get())->root_secure_user_id);
+}
+
+
+TEST(KeyguardTest, UntrustedReEnroll) {
+    SoftKeyguard keyguard(new TestKeyguardFileIo());
+    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(keyguard, &enroll_response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, enroll_response.error);
+
+    // verify first password
+    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.error);
+    AuthToken *auth_token =
+        reinterpret_cast<AuthToken *>(response.auth_token.buffer.get());
+
+    secure_id_t secure_id = auth_token->root_secure_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);
+    keyguard.Enroll(enroll_request, &enroll_response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, 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, &enroll_response.enrolled_password_handle,
+            &password);
+    keyguard.Verify(new_request, &response);
+    ASSERT_EQ(::keyguard::keyguard_error_t::KG_ERROR_OK, response.error);
+    ASSERT_NE(secure_id,
+        reinterpret_cast<AuthToken *>(response.auth_token.buffer.get())->root_secure_user_id);
+}
+
+
 TEST(KeyguardTest, VerifyBogusData) {
-    SoftKeyguard keyguard;
+    SoftKeyguard keyguard(new TestKeyguardFileIo());
     SizedBuffer provided_password;
     SizedBuffer password_handle;
     VerifyResponse response;