Implement SoftKeyguard
scrypt/openssl based implementation of Keyguard
Change-Id: Ib04fee3bb34d81bfdb659ab1a9f16efd0cbd630f
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;
+}
+
}