blob: 8cb0a8cbdf6afe2960f04141107d37a6b5d0088e [file] [log] [blame]
Andres Moralesac808182015-02-26 14:11:04 -08001/*
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 Moralesb2abaa82015-03-03 09:09:18 -080016#include <UniquePtr.h>
Andres Moralesac808182015-02-26 14:11:04 -080017
Andres Morales7d0f0402015-03-19 18:02:55 -070018#include <gatekeeper/gatekeeper.h>
Andres Moralesac808182015-02-26 14:11:04 -080019
Andres Morales7d0f0402015-03-19 18:02:55 -070020namespace gatekeeper {
Andres Moralesac808182015-02-26 14:11:04 -080021
Andres Moralesedd3e3d2015-03-12 13:30:15 -070022/**
23 * Internal only structure for easy serialization
24 * and deserialization of password handles.
25 */
26static const uint8_t HANDLE_VERSION = 0;
27struct __attribute__ ((__packed__)) password_handle_t {
28 // fields included in signature
Andres Morales5d39a972015-03-23 14:54:01 -070029 uint8_t version;
Andres Moralesedd3e3d2015-03-12 13:30:15 -070030 secure_id_t user_id;
31 secure_id_t authenticator_id;
32
33 // fields not included in signature
34 salt_t salt;
35 uint8_t signature[32];
36};
Andres Moralesac808182015-02-26 14:11:04 -080037
Andres Morales7d0f0402015-03-19 18:02:55 -070038void GateKeeper::Enroll(const EnrollRequest &request, EnrollResponse *response) {
Andres Moralesac808182015-02-26 14:11:04 -080039 if (response == NULL) return;
40
Andres Moralesb2abaa82015-03-03 09:09:18 -080041 if (!request.provided_password.buffer.get()) {
Andres Morales7d0f0402015-03-19 18:02:55 -070042 response->error = ERROR_INVALID;
Andres Moralesac808182015-02-26 14:11:04 -080043 return;
44 }
Andres Moralesb2abaa82015-03-03 09:09:18 -080045
Andres Moralesedd3e3d2015-03-12 13:30:15 -070046 secure_id_t user_id = 0;
Andres Moralesb2abaa82015-03-03 09:09:18 -080047
Andres Moralesedd3e3d2015-03-12 13:30:15 -070048 if (request.password_handle.buffer.get() == NULL) {
49 // Password handle does not match what is stored, generate new SecureID
50 GetRandom(&user_id, sizeof(secure_id_t));
51 } else {
52 if (!ValidatePasswordFile(request.user_id, request.password_handle)) {
Andres Morales7d0f0402015-03-19 18:02:55 -070053 response->error = ERROR_INVALID;
Andres Moralesedd3e3d2015-03-12 13:30:15 -070054 return;
55 } else {
56 // Password handle matches password file
57 password_handle_t *pw_handle =
58 reinterpret_cast<password_handle_t *>(request.password_handle.buffer.get());
59 if (!DoVerify(pw_handle, request.enrolled_password)) {
60 // incorrect old password
Andres Morales7d0f0402015-03-19 18:02:55 -070061 response->error = ERROR_INVALID;
Andres Moralesedd3e3d2015-03-12 13:30:15 -070062 return;
63 }
Andres Moralesb2abaa82015-03-03 09:09:18 -080064
Andres Moralesedd3e3d2015-03-12 13:30:15 -070065 user_id = pw_handle->user_id;
66 }
67 }
68
69 salt_t salt;
70 GetRandom(&salt, sizeof(salt));
71
72 secure_id_t authenticator_id;
73 GetRandom(&authenticator_id, sizeof(authenticator_id));
74
75
76 SizedBuffer password_handle;
77 if(!CreatePasswordHandle(&password_handle,
78 salt, user_id, authenticator_id, request.provided_password.buffer.get(),
79 request.provided_password.length)) {
Andres Morales7d0f0402015-03-19 18:02:55 -070080 response->error = ERROR_INVALID;
Andres Moralesedd3e3d2015-03-12 13:30:15 -070081 return;
82 }
83
84
85 WritePasswordFile(request.user_id, password_handle);
86
87 response->SetEnrolledPasswordHandle(&password_handle);
Andres Moralesac808182015-02-26 14:11:04 -080088}
89
Andres Morales7d0f0402015-03-19 18:02:55 -070090void GateKeeper::Verify(const VerifyRequest &request, VerifyResponse *response) {
Andres Moralesac808182015-02-26 14:11:04 -080091 if (response == NULL) return;
92
Andres Moralesb2abaa82015-03-03 09:09:18 -080093 if (!request.provided_password.buffer.get() || !request.password_handle.buffer.get()) {
Andres Morales7d0f0402015-03-19 18:02:55 -070094 response->error = ERROR_INVALID;
Andres Moralesac808182015-02-26 14:11:04 -080095 return;
96 }
97
Andres Moralesedd3e3d2015-03-12 13:30:15 -070098 secure_id_t user_id, authenticator_id;
99 password_handle_t *password_handle = reinterpret_cast<password_handle_t *>(
100 request.password_handle.buffer.get());
Andres Moralesb2abaa82015-03-03 09:09:18 -0800101
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700102 // Sanity check
103 if (password_handle->version != HANDLE_VERSION) {
Andres Morales7d0f0402015-03-19 18:02:55 -0700104 response->error = ERROR_INVALID;
Andres Moralesb2abaa82015-03-03 09:09:18 -0800105 return;
106 }
107
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700108 if (!ValidatePasswordFile(request.user_id, request.password_handle)) {
109 // we don't allow access to keys if we can't validate the file.
110 // we must allow this case to support authentication before we decrypt
111 // /data, however.
112 user_id = 0;
113 authenticator_id = 0;
114 } else {
115 user_id = password_handle->user_id;
116 authenticator_id = password_handle->authenticator_id;
117 }
Andres Moralesb2abaa82015-03-03 09:09:18 -0800118
Andres Morales11c2a512015-03-23 10:10:44 -0700119 uint64_t timestamp = GetNanosecondsSinceBoot();
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700120
121 if (DoVerify(password_handle, request.provided_password)) {
Andres Moralesac808182015-02-26 14:11:04 -0800122 // Signature matches
123 SizedBuffer auth_token;
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700124 MintAuthToken(&auth_token.buffer, &auth_token.length, timestamp,
125 user_id, authenticator_id);
Andres Moralesac808182015-02-26 14:11:04 -0800126 response->SetVerificationToken(&auth_token);
127 } else {
Andres Morales7d0f0402015-03-19 18:02:55 -0700128 response->error = ERROR_INVALID;
Andres Moralesac808182015-02-26 14:11:04 -0800129 }
130}
131
Andres Morales7d0f0402015-03-19 18:02:55 -0700132bool GateKeeper::CreatePasswordHandle(SizedBuffer *password_handle_buffer, salt_t salt,
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700133 secure_id_t user_id, secure_id_t authenticator_id, const uint8_t *password,
134 size_t password_length) {
135 password_handle_buffer->buffer.reset(new uint8_t[sizeof(password_handle_t)]);
136 password_handle_buffer->length = sizeof(password_handle_t);
137
138 password_handle_t *password_handle = reinterpret_cast<password_handle_t *>(
139 password_handle_buffer->buffer.get());
140 password_handle->version = HANDLE_VERSION;
141 password_handle->salt = salt;
142 password_handle->user_id = user_id;
143 password_handle->authenticator_id = authenticator_id;
144
145 size_t metadata_length = sizeof(user_id) /* user id */
146 + sizeof(authenticator_id) /* auth id */ + sizeof(uint8_t) /* version */;
147 uint8_t to_sign[password_length + metadata_length];
148 memcpy(to_sign, &password_handle->version, metadata_length);
149 memcpy(to_sign + metadata_length, password, password_length);
150
Andres Moralesf10e2892015-03-23 12:03:56 -0700151 const uint8_t *password_key = NULL;
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700152 size_t password_key_length = 0;
153 GetPasswordKey(&password_key, &password_key_length);
154
Andres Moralesf10e2892015-03-23 12:03:56 -0700155 if (!password_key || password_key_length == 0) {
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700156 return false;
157 }
158
159 ComputePasswordSignature(password_handle->signature, sizeof(password_handle->signature),
Andres Moralesf10e2892015-03-23 12:03:56 -0700160 password_key, password_key_length, to_sign, sizeof(to_sign), salt);
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700161 return true;
162}
163
Andres Morales7d0f0402015-03-19 18:02:55 -0700164bool GateKeeper::DoVerify(const password_handle_t *expected_handle, const SizedBuffer &password) {
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700165 if (!password.buffer.get()) return false;
166
167 SizedBuffer provided_handle;
168 if (!CreatePasswordHandle(&provided_handle, expected_handle->salt, expected_handle->user_id,
169 expected_handle->authenticator_id, password.buffer.get(), password.length)) {
170 return false;
171 }
172
173 return memcmp_s(provided_handle.buffer.get(), expected_handle, sizeof(*expected_handle)) == 0;
174}
175
Andres Morales7d0f0402015-03-19 18:02:55 -0700176bool GateKeeper::ValidatePasswordFile(uint32_t uid, const SizedBuffer &provided_handle) {
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700177 SizedBuffer stored_handle;
178 ReadPasswordFile(uid, &stored_handle);
179
180 if (!stored_handle.buffer.get() || stored_handle.length == 0) return false;
181
182 // do we also verify the signature here?
183 return stored_handle.length == provided_handle.length &&
184 memcmp_s(stored_handle.buffer.get(), provided_handle.buffer.get(), stored_handle.length)
185 == 0;
186}
187
Andres Morales7d0f0402015-03-19 18:02:55 -0700188void GateKeeper::MintAuthToken(UniquePtr<uint8_t> *auth_token, size_t *length,
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700189 uint32_t timestamp, secure_id_t user_id, secure_id_t authenticator_id) {
Andres Moralesb2abaa82015-03-03 09:09:18 -0800190 if (auth_token == NULL) return;
191
192 AuthToken *token = new AuthToken;
Andres Moralesac808182015-02-26 14:11:04 -0800193 SizedBuffer serialized_auth_token;
194
Andres Morales5d39a972015-03-23 14:54:01 -0700195 token->auth_token_version = AUTH_TOKEN_VERSION;
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700196 token->root_secure_user_id = user_id;
197 token->auxiliary_secure_user_id = authenticator_id;
Andres Morales5d39a972015-03-23 14:54:01 -0700198 token->authenticator_id = 0;
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700199 token->timestamp = timestamp;
Andres Moralesac808182015-02-26 14:11:04 -0800200
Andres Moralesf10e2892015-03-23 12:03:56 -0700201 const uint8_t *auth_token_key = NULL;
202 size_t key_len = 0;
Andres Moralesb2abaa82015-03-03 09:09:18 -0800203 GetAuthTokenKey(&auth_token_key, &key_len);
204
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700205 size_t hash_len = (size_t)((uint8_t *)&token->hmac - (uint8_t *)token);
Andres Moralesf10e2892015-03-23 12:03:56 -0700206 ComputeSignature(token->hmac, sizeof(token->hmac), auth_token_key, key_len,
Andres Moralesedd3e3d2015-03-12 13:30:15 -0700207 reinterpret_cast<uint8_t *>(token), hash_len);
Andres Moralesac808182015-02-26 14:11:04 -0800208
Andres Moralesac808182015-02-26 14:11:04 -0800209 if (length != NULL) *length = sizeof(AuthToken);
Andres Moralesb2abaa82015-03-03 09:09:18 -0800210 auth_token->reset(reinterpret_cast<uint8_t *>(token));
Andres Moralesac808182015-02-26 14:11:04 -0800211}
Andres Moralesb2abaa82015-03-03 09:09:18 -0800212
Andres Moralesac808182015-02-26 14:11:04 -0800213}