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);
}