Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright 2015 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 16 | #include <time.h> |
| 17 | #include <iostream> |
| 18 | #include <iomanip> |
| 19 | #include <UniquePtr.h> |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 20 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 21 | #include <keyguard/keyguard.h> |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 22 | |
| 23 | namespace keyguard { |
| 24 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 25 | Keyguard::~Keyguard() { |
| 26 | if (password_key_.buffer.get()) { |
| 27 | memset_s(password_key_.buffer.get(), 0, password_key_.length); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 28 | } |
| 29 | } |
| 30 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 31 | void Keyguard::Enroll(const EnrollRequest &request, EnrollResponse *response) { |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 32 | if (response == NULL) return; |
| 33 | |
| 34 | SizedBuffer enrolled_password; |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 35 | if (!request.provided_password.buffer.get()) { |
| 36 | response->error = KG_ERROR_INVALID; |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 37 | return; |
| 38 | } |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 39 | |
| 40 | size_t salt_length; |
| 41 | UniquePtr<uint8_t> salt; |
| 42 | GetSalt(&salt, &salt_length); |
| 43 | |
| 44 | size_t signature_length; |
| 45 | UniquePtr<uint8_t> signature; |
| 46 | ComputePasswordSignature(password_key_.buffer.get(), |
| 47 | password_key_.length, request.provided_password.buffer.get(), |
| 48 | request.provided_password.length, salt.get(), salt_length, &signature, |
| 49 | &signature_length); |
| 50 | |
| 51 | SerializeHandle(salt.get(), salt_length, signature.get(), signature_length, enrolled_password); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 52 | response->SetEnrolledPasswordHandle(&enrolled_password); |
| 53 | } |
| 54 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 55 | void Keyguard::Verify(const VerifyRequest &request, VerifyResponse *response) { |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 56 | if (response == NULL) return; |
| 57 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 58 | if (!request.provided_password.buffer.get() || !request.password_handle.buffer.get()) { |
| 59 | response->error = KG_ERROR_INVALID; |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 60 | return; |
| 61 | } |
| 62 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 63 | size_t salt_length, signature_length; |
| 64 | uint8_t *salt, *signature; |
| 65 | keyguard_error_t error = DeserializeHandle( |
| 66 | &request.password_handle, &salt, &salt_length, &signature, &signature_length); |
| 67 | |
| 68 | if (error != KG_ERROR_OK) { |
| 69 | response->error = error; |
| 70 | return; |
| 71 | } |
| 72 | |
| 73 | size_t provided_password_signature_length; |
| 74 | UniquePtr<uint8_t> provided_password_signature; |
| 75 | ComputePasswordSignature(password_key_.buffer.get(), |
| 76 | password_key_.length, request.provided_password.buffer.get(), request.provided_password.length, |
| 77 | salt, salt_length, &provided_password_signature, &provided_password_signature_length); |
| 78 | |
| 79 | if (provided_password_signature_length == signature_length && |
| 80 | memcmp_s(signature, provided_password_signature.get(), signature_length) == 0) { |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 81 | // Signature matches |
| 82 | SizedBuffer auth_token; |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 83 | MintAuthToken(request.user_id, &auth_token.buffer, &auth_token.length); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 84 | response->SetVerificationToken(&auth_token); |
| 85 | } else { |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 86 | response->error = KG_ERROR_INVALID; |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 87 | } |
| 88 | } |
| 89 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 90 | void Keyguard::MintAuthToken(uint32_t user_id, UniquePtr<uint8_t> *auth_token, size_t *length) { |
| 91 | if (auth_token == NULL) return; |
| 92 | |
| 93 | AuthToken *token = new AuthToken; |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 94 | SizedBuffer serialized_auth_token; |
| 95 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 96 | struct timespec time; |
| 97 | clock_gettime(CLOCK_MONOTONIC_RAW, &time); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 98 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 99 | token->auth_token_size = sizeof(AuthToken) - |
| 100 | sizeof(token->auth_token_tag) - sizeof(token->auth_token_size); |
| 101 | token->user_id = user_id; |
| 102 | token->timestamp = static_cast<uint64_t>(time.tv_sec); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 103 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 104 | UniquePtr<uint8_t> auth_token_key; |
| 105 | size_t key_len; |
| 106 | GetAuthTokenKey(&auth_token_key, &key_len); |
| 107 | |
| 108 | size_t hash_len = (size_t)((uint8_t *)&token->hmac_tag - (uint8_t *)token); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 109 | size_t signature_len; |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 110 | UniquePtr<uint8_t> signature; |
| 111 | ComputeSignature(auth_token_key.get(), key_len, |
| 112 | reinterpret_cast<uint8_t *>(token), hash_len, &signature, &signature_len); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 113 | |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 114 | memset(&token->hmac, 0, sizeof(token->hmac)); |
| 115 | |
| 116 | memcpy(&token->hmac, signature.get(), signature_len > sizeof(token->hmac) |
| 117 | ? sizeof(token->hmac) : signature_len); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 118 | if (length != NULL) *length = sizeof(AuthToken); |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 119 | auth_token->reset(reinterpret_cast<uint8_t *>(token)); |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 120 | } |
Andres Morales | b2abaa8 | 2015-03-03 09:09:18 -0800 | [diff] [blame] | 121 | |
| 122 | void Keyguard::SerializeHandle(const uint8_t *salt, size_t salt_length, const uint8_t *signature, |
| 123 | size_t signature_length, SizedBuffer &result) { |
| 124 | const size_t buffer_len = 2 * sizeof(size_t) + salt_length + signature_length; |
| 125 | result.buffer.reset(new uint8_t[buffer_len]); |
| 126 | result.length = buffer_len; |
| 127 | uint8_t *buffer = result.buffer.get(); |
| 128 | memcpy(buffer, &salt_length, sizeof(salt_length)); |
| 129 | buffer += sizeof(salt_length); |
| 130 | memcpy(buffer, salt, salt_length); |
| 131 | buffer += salt_length; |
| 132 | memcpy(buffer, &signature_length, sizeof(signature_length)); |
| 133 | buffer += sizeof(signature_length); |
| 134 | memcpy(buffer, signature, signature_length); |
| 135 | } |
| 136 | |
| 137 | keyguard_error_t Keyguard::DeserializeHandle(const SizedBuffer *handle, uint8_t **salt, |
| 138 | size_t *salt_length, uint8_t **password, size_t *password_length) { |
| 139 | if (handle && handle->length > (2 * sizeof(size_t))) { |
| 140 | int read = 0; |
| 141 | uint8_t *buffer = handle->buffer.get(); |
| 142 | memcpy(salt_length, buffer, sizeof(*salt_length)); |
| 143 | read += sizeof(*salt_length); |
| 144 | if (read + *salt_length < handle->length) { |
| 145 | *salt = buffer + read; |
| 146 | read += *salt_length; |
| 147 | if (read + sizeof(*password_length) < handle->length) { |
| 148 | buffer += read; |
| 149 | memcpy(password_length, buffer, sizeof(*password_length)); |
| 150 | *password = buffer + sizeof(*password_length); |
| 151 | } else { |
| 152 | return KG_ERROR_INVALID; |
| 153 | } |
| 154 | } else { |
| 155 | return KG_ERROR_INVALID; |
| 156 | } |
| 157 | |
| 158 | return KG_ERROR_OK; |
| 159 | } |
| 160 | return KG_ERROR_INVALID; |
| 161 | } |
| 162 | |
Andres Morales | ac80818 | 2015-02-26 14:11:04 -0800 | [diff] [blame] | 163 | } |