blob: 890dc7dbf0b166b0b75d95b2c660ed9e274fbee3 [file] [log] [blame]
Shawn Willden128ffe02014-08-06 12:31:33 -06001/*
2 * Copyright 2014 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 */
16
17#include <assert.h>
18#include <string.h>
19
Shawn Willden4db3fbd2014-08-08 22:13:44 -060020#include <cstddef>
21
Shawn Willden1615f2e2014-08-13 10:37:40 -060022#include <openssl/rand.h>
Shawn Willden128ffe02014-08-06 12:31:33 -060023
24#include <UniquePtr.h>
25
Shawn Willden3879f862014-08-06 14:40:48 -060026#include "ae.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060027#include "google_keymaster.h"
28#include "google_keymaster_utils.h"
Shawn Willden4db3fbd2014-08-08 22:13:44 -060029#include "key_blob.h"
Shawn Willden1615f2e2014-08-13 10:37:40 -060030#include "rsa_operation.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060031
32namespace keymaster {
33
Shawn Willden1615f2e2014-08-13 10:37:40 -060034GoogleKeymaster::GoogleKeymaster(size_t operation_table_size)
35 : operation_table_(new OpTableEntry[operation_table_size]),
36 operation_table_size_(operation_table_size) {
37 if (operation_table_.get() == NULL)
38 operation_table_size_ = 0;
Shawn Willden39b970b2014-08-11 09:11:21 -060039}
40GoogleKeymaster::~GoogleKeymaster() {
Shawn Willden1615f2e2014-08-13 10:37:40 -060041 for (size_t i = 0; i < operation_table_size_; ++i)
42 if (operation_table_[i].operation != NULL)
43 delete operation_table_[i].operation;
Shawn Willden39b970b2014-08-11 09:11:21 -060044}
Shawn Willden128ffe02014-08-06 12:31:33 -060045
46const int RSA_DEFAULT_KEY_SIZE = 2048;
47const int RSA_DEFAULT_EXPONENT = 65537;
48
Shawn Willden128ffe02014-08-06 12:31:33 -060049struct AE_CTX_Delete {
Shawn Willden802bb292014-08-18 10:46:29 -060050 void operator()(ae_ctx* ctx) const { ae_free(ctx); }
Shawn Willden128ffe02014-08-06 12:31:33 -060051};
52typedef UniquePtr<ae_ctx, AE_CTX_Delete> Unique_ae_ctx;
53
54struct ByteArray_Delete {
Shawn Willden802bb292014-08-18 10:46:29 -060055 void operator()(void* p) const { delete[] reinterpret_cast<uint8_t*>(p); }
Shawn Willden128ffe02014-08-06 12:31:33 -060056};
57
Shawn Willden128ffe02014-08-06 12:31:33 -060058keymaster_algorithm_t supported_algorithms[] = {
59 KM_ALGORITHM_RSA,
60};
61
62template <typename T>
63bool check_supported(keymaster_algorithm_t algorithm, SupportedResponse<T>* response) {
64 if (!array_contains(supported_algorithms, algorithm)) {
65 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
66 return false;
67 }
68 return true;
69}
70
71void
72GoogleKeymaster::SupportedAlgorithms(SupportedResponse<keymaster_algorithm_t>* response) const {
73 if (response == NULL)
74 return;
75 response->SetResults(supported_algorithms);
76}
77
78void
79GoogleKeymaster::SupportedBlockModes(keymaster_algorithm_t algorithm,
80 SupportedResponse<keymaster_block_mode_t>* response) const {
81 if (response == NULL || !check_supported(algorithm, response))
82 return;
83 response->error = KM_ERROR_OK;
84}
85
86keymaster_padding_t rsa_supported_padding[] = {KM_PAD_NONE};
87
88void
89GoogleKeymaster::SupportedPaddingModes(keymaster_algorithm_t algorithm,
90 SupportedResponse<keymaster_padding_t>* response) const {
91 if (response == NULL || !check_supported(algorithm, response))
92 return;
93
94 response->error = KM_ERROR_OK;
95 switch (algorithm) {
96 case KM_ALGORITHM_RSA:
97 response->SetResults(rsa_supported_padding);
98 break;
99 default:
100 response->results_length = 0;
101 break;
102 }
103}
104
105keymaster_digest_t rsa_supported_digests[] = {KM_DIGEST_NONE};
106void GoogleKeymaster::SupportedDigests(keymaster_algorithm_t algorithm,
107 SupportedResponse<keymaster_digest_t>* response) const {
108 if (response == NULL || !check_supported(algorithm, response))
109 return;
110
111 response->error = KM_ERROR_OK;
112 switch (algorithm) {
113 case KM_ALGORITHM_RSA:
114 response->SetResults(rsa_supported_digests);
115 break;
116 default:
117 response->results_length = 0;
118 break;
119 }
120}
121
122keymaster_key_format_t rsa_supported_import_formats[] = {KM_KEY_FORMAT_PKCS8};
123void
124GoogleKeymaster::SupportedImportFormats(keymaster_algorithm_t algorithm,
125 SupportedResponse<keymaster_key_format_t>* response) const {
126 if (response == NULL || !check_supported(algorithm, response))
127 return;
128
129 response->error = KM_ERROR_OK;
130 switch (algorithm) {
131 case KM_ALGORITHM_RSA:
132 response->SetResults(rsa_supported_import_formats);
133 break;
134 default:
135 response->results_length = 0;
136 break;
137 }
138}
139
140keymaster_key_format_t rsa_supported_export_formats[] = {KM_KEY_FORMAT_X509};
141void
142GoogleKeymaster::SupportedExportFormats(keymaster_algorithm_t algorithm,
143 SupportedResponse<keymaster_key_format_t>* response) const {
144 if (response == NULL || !check_supported(algorithm, response))
145 return;
146
147 response->error = KM_ERROR_OK;
148 switch (algorithm) {
149 case KM_ALGORITHM_RSA:
150 response->SetResults(rsa_supported_export_formats);
151 break;
152 default:
153 response->results_length = 0;
154 break;
155 }
156}
157
Shawn Willden128ffe02014-08-06 12:31:33 -0600158void GoogleKeymaster::GenerateKey(const GenerateKeyRequest& request,
159 GenerateKeyResponse* response) {
160 if (response == NULL)
161 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600162 response->error = KM_ERROR_UNKNOWN_ERROR;
Shawn Willden128ffe02014-08-06 12:31:33 -0600163
Shawn Willden76364712014-08-11 17:48:04 -0600164 if (!CopyAuthorizations(request.key_description, response))
165 return;
166
Shawn Willden39b970b2014-08-11 09:11:21 -0600167 AuthorizationSet hidden_auths;
Shawn Willden76364712014-08-11 17:48:04 -0600168 response->error = BuildHiddenAuthorizations(request.key_description, &hidden_auths);
169 if (response->error != KM_ERROR_OK)
Shawn Willden128ffe02014-08-06 12:31:33 -0600170 return;
171
172 keymaster_algorithm_t algorithm;
173 if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
174 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
175 return;
176 }
177 switch (algorithm) {
178 case KM_ALGORITHM_RSA:
Shawn Willden39b970b2014-08-11 09:11:21 -0600179 if (!GenerateRsa(request.key_description, response, &hidden_auths))
Shawn Willden128ffe02014-08-06 12:31:33 -0600180 return;
181 break;
182 default:
183 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
184 return;
185 }
Shawn Willden1615f2e2014-08-13 10:37:40 -0600186
187 response->error = KM_ERROR_OK;
Shawn Willden128ffe02014-08-06 12:31:33 -0600188}
189
Shawn Willden76364712014-08-11 17:48:04 -0600190void GoogleKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
191 GetKeyCharacteristicsResponse* response) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600192 if (response == NULL)
193 return;
194 response->error = KM_ERROR_UNKNOWN_ERROR;
Shawn Willden76364712014-08-11 17:48:04 -0600195
Shawn Willden1615f2e2014-08-13 10:37:40 -0600196 UniquePtr<KeyBlob> blob(
197 LoadKeyBlob(request.key_blob, request.additional_params, &(response->error)));
198 if (blob.get() == NULL)
199 return;
200
201 response->enforced.Reinitialize(blob->enforced());
202 response->unenforced.Reinitialize(blob->unenforced());
203 response->error = KM_ERROR_OK;
204}
205
206void GoogleKeymaster::BeginOperation(const BeginOperationRequest& request,
207 BeginOperationResponse* response) {
208 if (response == NULL)
209 return;
210 response->error = KM_ERROR_UNKNOWN_ERROR;
211 response->op_handle = 0;
212
213 UniquePtr<KeyBlob> key(
214 LoadKeyBlob(request.key_blob, request.additional_params, &response->error));
215 if (key.get() == NULL)
216 return;
217
218 UniquePtr<Operation> operation;
219 switch (key->algorithm()) {
220 case KM_ALGORITHM_RSA:
221 operation.reset(new RsaOperation(request.purpose, *key));
222 break;
223 default:
224 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
225 break;
226 }
227
228 if (operation.get() == NULL) {
Shawn Willden76364712014-08-11 17:48:04 -0600229 return;
230 }
Shawn Willden1615f2e2014-08-13 10:37:40 -0600231
232 response->error = operation->Begin();
233 if (response->error != KM_ERROR_OK)
234 return;
235
236 response->error = AddOperation(operation.release(), &response->op_handle);
237}
238
239void GoogleKeymaster::UpdateOperation(const UpdateOperationRequest& request,
240 UpdateOperationResponse* response) {
241 OpTableEntry* entry = FindOperation(request.op_handle);
242 if (entry == NULL) {
243 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
244 return;
245 }
246
247 response->error = entry->operation->Update(request.input, &response->output);
248 if (response->error != KM_ERROR_OK) {
249 // Any error invalidates the operation.
250 DeleteOperation(entry);
251 }
252}
253
Shawn Willden43e999e2014-08-13 13:29:50 -0600254void GoogleKeymaster::FinishOperation(const FinishOperationRequest& request,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600255 FinishOperationResponse* response) {
Shawn Willden43e999e2014-08-13 13:29:50 -0600256 OpTableEntry* entry = FindOperation(request.op_handle);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600257 if (entry == NULL) {
258 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
259 return;
260 }
261
Shawn Willden43e999e2014-08-13 13:29:50 -0600262 response->error = entry->operation->Finish(request.signature, &response->output);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600263 DeleteOperation(entry);
264}
265
266keymaster_error_t GoogleKeymaster::AbortOperation(const keymaster_operation_handle_t op_handle) {
267 OpTableEntry* entry = FindOperation(op_handle);
268 if (entry == NULL)
269 return KM_ERROR_INVALID_OPERATION_HANDLE;
270 DeleteOperation(entry);
271 return KM_ERROR_OK;
Shawn Willden76364712014-08-11 17:48:04 -0600272}
273
Shawn Willden39b970b2014-08-11 09:11:21 -0600274bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
275 AuthorizationSet* hidden_auths) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600276 uint64_t public_exponent = RSA_DEFAULT_EXPONENT;
277 if (!key_auths.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent))
Shawn Willden76364712014-08-11 17:48:04 -0600278 AddAuthorization(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600279
280 uint32_t key_size = RSA_DEFAULT_KEY_SIZE;
281 if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
Shawn Willden76364712014-08-11 17:48:04 -0600282 AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600283
Shawn Willden802bb292014-08-18 10:46:29 -0600284 UniquePtr<uint8_t[]> key_data;
285 size_t key_data_size;
286 keymaster_error_t error =
287 RsaOperation::Generate(public_exponent, key_size, &key_data, &key_data_size);
288 if (error != KM_ERROR_OK) {
289 response->error = error;
Shawn Willden128ffe02014-08-06 12:31:33 -0600290 return false;
291 }
292
Shawn Willden802bb292014-08-18 10:46:29 -0600293 return CreateKeyBlob(response, *hidden_auths, key_data.get(), key_data_size);
Shawn Willden39b970b2014-08-11 09:11:21 -0600294}
295
296bool GoogleKeymaster::CreateKeyBlob(GenerateKeyResponse* response,
297 const AuthorizationSet& hidden_auths, uint8_t* key_bytes,
298 size_t key_length) {
299 uint8_t nonce[KeyBlob::NONCE_LENGTH];
300 GenerateNonce(nonce, array_size(nonce));
301
302 keymaster_key_blob_t key_data = {key_bytes, key_length};
303 UniquePtr<KeyBlob> blob(new KeyBlob(response->enforced, response->unenforced, hidden_auths,
304 key_data, MasterKey(), nonce));
305 if (blob.get() == NULL) {
306 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
307 return false;
308 }
309
310 if (blob->error() != KM_ERROR_OK) {
311 return blob->error();
312 return false;
313 }
314
315 size_t size = blob->SerializedSize();
316 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
317 if (blob_bytes.get() == NULL) {
318 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
319 return false;
320 }
321 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
322 response->key_blob.key_material_size = size;
323 response->key_blob.key_material = blob_bytes.release();
324 return true;
Shawn Willden128ffe02014-08-06 12:31:33 -0600325}
326
Shawn Willden1615f2e2014-08-13 10:37:40 -0600327KeyBlob* GoogleKeymaster::LoadKeyBlob(const keymaster_key_blob_t& key,
328 const AuthorizationSet& client_params,
329 keymaster_error_t* error) {
330 AuthorizationSet hidden;
331 BuildHiddenAuthorizations(client_params, &hidden);
332 UniquePtr<KeyBlob> blob(new KeyBlob(key, hidden, MasterKey()));
333 if (blob.get() == NULL) {
334 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
335 return NULL;
336 } else if (blob->error() != KM_ERROR_OK) {
337 *error = blob->error();
338 return NULL;
339 }
340 return blob.release();
341}
342
Shawn Willden128ffe02014-08-06 12:31:33 -0600343static keymaster_error_t CheckAuthorizationSet(const AuthorizationSet& set) {
344 switch (set.is_valid()) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600345 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600346 return KM_ERROR_OK;
347 case AuthorizationSet::ALLOCATION_FAILURE:
348 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden128ffe02014-08-06 12:31:33 -0600349 case AuthorizationSet::MALFORMED_DATA:
350 return KM_ERROR_UNKNOWN_ERROR;
351 }
352 return KM_ERROR_OK;
353}
354
355bool GoogleKeymaster::CopyAuthorizations(const AuthorizationSet& key_description,
Shawn Willden76364712014-08-11 17:48:04 -0600356 GenerateKeyResponse* response) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600357 for (size_t i = 0; i < key_description.size(); ++i) {
358 switch (key_description[i].tag) {
359 case KM_TAG_ROOT_OF_TRUST:
360 case KM_TAG_CREATION_DATETIME:
361 case KM_TAG_ORIGIN:
362 response->error = KM_ERROR_INVALID_TAG;
363 return false;
364 case KM_TAG_ROLLBACK_RESISTANT:
365 response->error = KM_ERROR_UNSUPPORTED_TAG;
366 return false;
367 default:
Shawn Willden76364712014-08-11 17:48:04 -0600368 AddAuthorization(key_description[i], response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600369 break;
370 }
371 }
372
Shawn Willden76364712014-08-11 17:48:04 -0600373 AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response);
374 AddAuthorization(Authorization(TAG_ORIGIN, origin()), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600375
376 response->error = CheckAuthorizationSet(response->enforced);
377 if (response->error != KM_ERROR_OK)
378 return false;
379 response->error = CheckAuthorizationSet(response->unenforced);
380 if (response->error != KM_ERROR_OK)
381 return false;
382
383 return true;
384}
385
Shawn Willden76364712014-08-11 17:48:04 -0600386keymaster_error_t GoogleKeymaster::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600387 AuthorizationSet* hidden) {
Shawn Willden76364712014-08-11 17:48:04 -0600388 keymaster_blob_t entry;
389 if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
390 hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
391 if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
392 hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
393 hidden->push_back(RootOfTrustTag());
394
395 return CheckAuthorizationSet(*hidden);
396}
397
Shawn Willden128ffe02014-08-06 12:31:33 -0600398void GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
Shawn Willden76364712014-08-11 17:48:04 -0600399 GenerateKeyResponse* response) {
Shawn Willden39b970b2014-08-11 09:11:21 -0600400 switch (auth.tag) {
401 case KM_TAG_ROOT_OF_TRUST:
402 case KM_TAG_APPLICATION_ID:
403 case KM_TAG_APPLICATION_DATA:
Shawn Willden76364712014-08-11 17:48:04 -0600404 // Skip. We handle these tags separately.
Shawn Willden39b970b2014-08-11 09:11:21 -0600405 break;
406 default:
407 if (is_enforced(auth.tag))
408 response->enforced.push_back(auth);
409 else
410 response->unenforced.push_back(auth);
411 break;
412 }
Shawn Willden128ffe02014-08-06 12:31:33 -0600413}
414
Shawn Willden1615f2e2014-08-13 10:37:40 -0600415keymaster_error_t GoogleKeymaster::AddOperation(Operation* operation,
416 keymaster_operation_handle_t* op_handle) {
417 UniquePtr<Operation> op(operation);
418 if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) == 0)
419 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden802bb292014-08-18 10:46:29 -0600420 if (*op_handle == 0) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600421 // Statistically this is vanishingly unlikely, which means if it ever happens in practice,
422 // it indicates a broken RNG.
423 return KM_ERROR_UNKNOWN_ERROR;
424 }
425 for (size_t i = 0; i < operation_table_size_; ++i) {
426 if (operation_table_[i].operation == NULL) {
427 operation_table_[i].operation = op.release();
428 operation_table_[i].handle = *op_handle;
429 return KM_ERROR_OK;
430 }
431 }
432 return KM_ERROR_TOO_MANY_OPERATIONS;
433}
434
435GoogleKeymaster::OpTableEntry*
436GoogleKeymaster::FindOperation(keymaster_operation_handle_t op_handle) {
437 if (op_handle == 0)
438 return NULL;
439
440 for (size_t i = 0; i < operation_table_size_; ++i) {
441 if (operation_table_[i].handle == op_handle)
442 return operation_table_.get() + i;
443 }
444 return NULL;
445}
446
447void GoogleKeymaster::DeleteOperation(OpTableEntry* entry) {
448 delete entry->operation;
449 entry->operation = NULL;
450 entry->handle = 0;
451}
452
Shawn Willden128ffe02014-08-06 12:31:33 -0600453} // namespace keymaster