blob: e04a1e5c6d4af9bdb7fbd53f2c5d6d30f6c40b89 [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 Willdenffd790c2014-08-18 21:20:06 -060023#include <openssl/x509.h>
Shawn Willden128ffe02014-08-06 12:31:33 -060024
25#include <UniquePtr.h>
26
Shawn Willden3879f862014-08-06 14:40:48 -060027#include "ae.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060028#include "google_keymaster.h"
29#include "google_keymaster_utils.h"
Shawn Willdend67afae2014-08-19 12:36:27 -060030#include "key.h"
Shawn Willden4db3fbd2014-08-08 22:13:44 -060031#include "key_blob.h"
Shawn Willdend67afae2014-08-19 12:36:27 -060032#include "operation.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060033
34namespace keymaster {
35
Shawn Willden1615f2e2014-08-13 10:37:40 -060036GoogleKeymaster::GoogleKeymaster(size_t operation_table_size)
37 : operation_table_(new OpTableEntry[operation_table_size]),
38 operation_table_size_(operation_table_size) {
39 if (operation_table_.get() == NULL)
40 operation_table_size_ = 0;
Shawn Willden39b970b2014-08-11 09:11:21 -060041}
42GoogleKeymaster::~GoogleKeymaster() {
Shawn Willden1615f2e2014-08-13 10:37:40 -060043 for (size_t i = 0; i < operation_table_size_; ++i)
44 if (operation_table_[i].operation != NULL)
45 delete operation_table_[i].operation;
Shawn Willden39b970b2014-08-11 09:11:21 -060046}
Shawn Willden128ffe02014-08-06 12:31:33 -060047
Shawn Willden128ffe02014-08-06 12:31:33 -060048struct AE_CTX_Delete {
Shawn Willden802bb292014-08-18 10:46:29 -060049 void operator()(ae_ctx* ctx) const { ae_free(ctx); }
Shawn Willden128ffe02014-08-06 12:31:33 -060050};
51typedef UniquePtr<ae_ctx, AE_CTX_Delete> Unique_ae_ctx;
52
Shawn Willdenffd790c2014-08-18 21:20:06 -060053struct EVP_PKEY_Delete {
54 void operator()(EVP_PKEY* p) { EVP_PKEY_free(p); }
55};
56typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
57
58struct PKCS8_PRIV_KEY_INFO_Delete {
59 void operator()(PKCS8_PRIV_KEY_INFO* p) const { PKCS8_PRIV_KEY_INFO_free(p); }
60};
61typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO;
62
Shawn Willden128ffe02014-08-06 12:31:33 -060063keymaster_algorithm_t supported_algorithms[] = {
Shawn Willdenc3864dd2014-08-18 15:20:01 -060064 KM_ALGORITHM_RSA, KM_ALGORITHM_DSA, KM_ALGORITHM_ECDSA,
Shawn Willden128ffe02014-08-06 12:31:33 -060065};
66
67template <typename T>
68bool check_supported(keymaster_algorithm_t algorithm, SupportedResponse<T>* response) {
69 if (!array_contains(supported_algorithms, algorithm)) {
70 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
71 return false;
72 }
73 return true;
74}
75
76void
77GoogleKeymaster::SupportedAlgorithms(SupportedResponse<keymaster_algorithm_t>* response) const {
78 if (response == NULL)
79 return;
80 response->SetResults(supported_algorithms);
81}
82
83void
84GoogleKeymaster::SupportedBlockModes(keymaster_algorithm_t algorithm,
85 SupportedResponse<keymaster_block_mode_t>* response) const {
86 if (response == NULL || !check_supported(algorithm, response))
87 return;
88 response->error = KM_ERROR_OK;
89}
90
Shawn Willden28e41472014-08-18 13:35:22 -060091keymaster_padding_t supported_padding[] = {KM_PAD_NONE};
Shawn Willden128ffe02014-08-06 12:31:33 -060092void
93GoogleKeymaster::SupportedPaddingModes(keymaster_algorithm_t algorithm,
94 SupportedResponse<keymaster_padding_t>* response) const {
95 if (response == NULL || !check_supported(algorithm, response))
96 return;
97
98 response->error = KM_ERROR_OK;
99 switch (algorithm) {
100 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600101 case KM_ALGORITHM_DSA:
Shawn Willdenc3864dd2014-08-18 15:20:01 -0600102 case KM_ALGORITHM_ECDSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600103 response->SetResults(supported_padding);
Shawn Willden128ffe02014-08-06 12:31:33 -0600104 break;
105 default:
106 response->results_length = 0;
107 break;
108 }
109}
110
Shawn Willden28e41472014-08-18 13:35:22 -0600111keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE};
Shawn Willden128ffe02014-08-06 12:31:33 -0600112void GoogleKeymaster::SupportedDigests(keymaster_algorithm_t algorithm,
113 SupportedResponse<keymaster_digest_t>* response) const {
114 if (response == NULL || !check_supported(algorithm, response))
115 return;
116
117 response->error = KM_ERROR_OK;
118 switch (algorithm) {
119 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600120 case KM_ALGORITHM_DSA:
Shawn Willdenc3864dd2014-08-18 15:20:01 -0600121 case KM_ALGORITHM_ECDSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600122 response->SetResults(supported_digests);
Shawn Willden128ffe02014-08-06 12:31:33 -0600123 break;
124 default:
125 response->results_length = 0;
126 break;
127 }
128}
129
Shawn Willden28e41472014-08-18 13:35:22 -0600130keymaster_key_format_t supported_import_formats[] = {KM_KEY_FORMAT_PKCS8};
Shawn Willden128ffe02014-08-06 12:31:33 -0600131void
132GoogleKeymaster::SupportedImportFormats(keymaster_algorithm_t algorithm,
133 SupportedResponse<keymaster_key_format_t>* response) const {
134 if (response == NULL || !check_supported(algorithm, response))
135 return;
136
137 response->error = KM_ERROR_OK;
138 switch (algorithm) {
139 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600140 case KM_ALGORITHM_DSA:
Shawn Willdenc3864dd2014-08-18 15:20:01 -0600141 case KM_ALGORITHM_ECDSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600142 response->SetResults(supported_import_formats);
Shawn Willden128ffe02014-08-06 12:31:33 -0600143 break;
144 default:
145 response->results_length = 0;
146 break;
147 }
148}
149
Shawn Willden28e41472014-08-18 13:35:22 -0600150keymaster_key_format_t supported_export_formats[] = {KM_KEY_FORMAT_X509};
Shawn Willden128ffe02014-08-06 12:31:33 -0600151void
152GoogleKeymaster::SupportedExportFormats(keymaster_algorithm_t algorithm,
153 SupportedResponse<keymaster_key_format_t>* response) const {
154 if (response == NULL || !check_supported(algorithm, response))
155 return;
156
157 response->error = KM_ERROR_OK;
158 switch (algorithm) {
159 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600160 case KM_ALGORITHM_DSA:
Shawn Willdenc3864dd2014-08-18 15:20:01 -0600161 case KM_ALGORITHM_ECDSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600162 response->SetResults(supported_export_formats);
Shawn Willden128ffe02014-08-06 12:31:33 -0600163 break;
164 default:
165 response->results_length = 0;
166 break;
167 }
168}
169
Shawn Willden128ffe02014-08-06 12:31:33 -0600170void GoogleKeymaster::GenerateKey(const GenerateKeyRequest& request,
171 GenerateKeyResponse* response) {
172 if (response == NULL)
173 return;
Shawn Willden128ffe02014-08-06 12:31:33 -0600174
Shawn Willdend67afae2014-08-19 12:36:27 -0600175 UniquePtr<Key> key(Key::GenerateKey(request.key_description, &response->error));
Shawn Willden76364712014-08-11 17:48:04 -0600176 if (response->error != KM_ERROR_OK)
Shawn Willden128ffe02014-08-06 12:31:33 -0600177 return;
178
Shawn Willdend67afae2014-08-19 12:36:27 -0600179 if (!CopyAuthorizations(key->authorizations(), response))
Shawn Willden128ffe02014-08-06 12:31:33 -0600180 return;
Shawn Willden28e41472014-08-18 13:35:22 -0600181
Shawn Willdend67afae2014-08-19 12:36:27 -0600182 AuthorizationSet hidden_auths;
183 response->error = BuildHiddenAuthorizations(key->authorizations(), &hidden_auths);
184 if (response->error != KM_ERROR_OK)
Shawn Willden128ffe02014-08-06 12:31:33 -0600185 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600186
Shawn Willdend67afae2014-08-19 12:36:27 -0600187 UniquePtr<uint8_t[]> key_material;
188 size_t key_material_size;
189 response->error = key->key_material(&key_material, &key_material_size);
190 if (response->error != KM_ERROR_OK)
191 return;
192
193 response->error =
194 SerializeKeyToResponse(key_material.get(), key_material_size, hidden_auths, response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600195}
196
Shawn Willden76364712014-08-11 17:48:04 -0600197void GoogleKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
198 GetKeyCharacteristicsResponse* response) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600199 if (response == NULL)
200 return;
201 response->error = KM_ERROR_UNKNOWN_ERROR;
Shawn Willden76364712014-08-11 17:48:04 -0600202
Shawn Willden1615f2e2014-08-13 10:37:40 -0600203 UniquePtr<KeyBlob> blob(
204 LoadKeyBlob(request.key_blob, request.additional_params, &(response->error)));
205 if (blob.get() == NULL)
206 return;
207
208 response->enforced.Reinitialize(blob->enforced());
209 response->unenforced.Reinitialize(blob->unenforced());
210 response->error = KM_ERROR_OK;
211}
212
213void GoogleKeymaster::BeginOperation(const BeginOperationRequest& request,
214 BeginOperationResponse* response) {
215 if (response == NULL)
216 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600217 response->op_handle = 0;
218
Shawn Willdend67afae2014-08-19 12:36:27 -0600219 UniquePtr<Key> key(LoadKey(request.key_blob, request.additional_params, &response->error));
Shawn Willden1615f2e2014-08-13 10:37:40 -0600220 if (key.get() == NULL)
221 return;
222
Shawn Willdend67afae2014-08-19 12:36:27 -0600223 UniquePtr<Operation> operation(key->CreateOperation(request.purpose, &response->error));
224 if (operation.get() == NULL)
Shawn Willden76364712014-08-11 17:48:04 -0600225 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600226
227 response->error = operation->Begin();
228 if (response->error != KM_ERROR_OK)
229 return;
230
231 response->error = AddOperation(operation.release(), &response->op_handle);
232}
233
234void GoogleKeymaster::UpdateOperation(const UpdateOperationRequest& request,
235 UpdateOperationResponse* response) {
236 OpTableEntry* entry = FindOperation(request.op_handle);
237 if (entry == NULL) {
238 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
239 return;
240 }
241
242 response->error = entry->operation->Update(request.input, &response->output);
243 if (response->error != KM_ERROR_OK) {
244 // Any error invalidates the operation.
245 DeleteOperation(entry);
246 }
247}
248
Shawn Willden43e999e2014-08-13 13:29:50 -0600249void GoogleKeymaster::FinishOperation(const FinishOperationRequest& request,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600250 FinishOperationResponse* response) {
Shawn Willden43e999e2014-08-13 13:29:50 -0600251 OpTableEntry* entry = FindOperation(request.op_handle);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600252 if (entry == NULL) {
253 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
254 return;
255 }
256
Shawn Willden43e999e2014-08-13 13:29:50 -0600257 response->error = entry->operation->Finish(request.signature, &response->output);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600258 DeleteOperation(entry);
259}
260
261keymaster_error_t GoogleKeymaster::AbortOperation(const keymaster_operation_handle_t op_handle) {
262 OpTableEntry* entry = FindOperation(op_handle);
263 if (entry == NULL)
264 return KM_ERROR_INVALID_OPERATION_HANDLE;
265 DeleteOperation(entry);
266 return KM_ERROR_OK;
Shawn Willden76364712014-08-11 17:48:04 -0600267}
268
Shawn Willdenffd790c2014-08-18 21:20:06 -0600269bool GoogleKeymaster::is_supported_export_format(keymaster_key_format_t test_format) {
270 unsigned int index;
271 for (index = 0; index < array_length(supported_export_formats); index++) {
272 if (test_format == supported_export_formats[index]) {
273 return true;
274 }
275 }
276
277 return false;
278}
279
280bool GoogleKeymaster::is_supported_import_format(keymaster_key_format_t test_format) {
281 unsigned int index;
282 for (index = 0; index < array_length(supported_import_formats); index++) {
283 if (test_format == supported_import_formats[index]) {
284 return true;
285 }
286 }
287
288 return false;
289}
290
291void GoogleKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response) {
292 if (response == NULL)
293 return;
294
295 keymaster_error_t blob_error;
296 UniquePtr<KeyBlob> to_export(
297 LoadKeyBlob(request.key_blob, request.additional_params, &response->error));
298 if (to_export.get() == NULL)
299 return;
300
301 Unique_EVP_PKEY pkey(EVP_PKEY_new());
302 if (pkey.get() == NULL) {
303 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
304 return;
305 }
306
307 EVP_PKEY* pkey_tmp = pkey.get();
308 const uint8_t* km_tmp = to_export->key_material();
309 if (d2i_PrivateKey(EVP_PKEY_RSA, &pkey_tmp, &km_tmp, to_export->key_material_length()) ==
310 NULL) {
311 response->error = KM_ERROR_INVALID_KEY_BLOB;
312 return;
313 }
314
315 int len = i2d_PUBKEY(pkey.get(), NULL);
316 if (len <= 0) {
317 response->error = KM_ERROR_UNKNOWN_ERROR;
318 return;
319 }
320
321 UniquePtr<uint8_t[]> out_key(new uint8_t[len]);
322 if (out_key.get() == NULL) {
323 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
324 return;
325 }
326
327 uint8_t* tmp = out_key.get();
328 if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
329 fprintf(stderr, "i2d_pubkey(x, len) failed.\n");
330 response->error = KM_ERROR_INVALID_KEY_BLOB;
331
332 return;
333 }
334
335 response->key_data = out_key.release();
336 response->error = KM_ERROR_OK;
337}
338
339void GoogleKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response) {
340
341 if (request.key_data == NULL || request.key_data_length <= 0) {
342 response->error = KM_ERROR_INVALID_KEY_BLOB;
343 return;
344 }
345
346 if (!is_supported_export_format(request.key_format)) {
347 response->error = KM_ERROR_UNSUPPORTED_KEY_FORMAT;
348 return;
349 }
350
351 const uint8_t* key_data = request.key_data;
352 Unique_PKCS8_PRIV_KEY_INFO pkcs8(
353 d2i_PKCS8_PRIV_KEY_INFO(NULL, &key_data, request.key_data_length));
354 if (pkcs8.get() == NULL) {
355 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
356 return;
357 }
358
359 Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get()));
360 if (pkey.get() == NULL) {
361 response->error = KM_ERROR_INVALID_KEY_BLOB;
362 return;
363 }
364
365 int len = i2d_PrivateKey(pkey.get(), NULL);
366 if (len <= 0) {
367 response->error = KM_ERROR_INVALID_KEY_BLOB;
368 return;
369 }
370
371 UniquePtr<uint8_t[]> der_encoded_key(new uint8_t[len]);
372 if (der_encoded_key.get() == NULL) {
373 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
374 return;
375 }
376
377 uint8_t* tmp_der = der_encoded_key.get();
378 if (i2d_PrivateKey(pkey.get(), &tmp_der) != len) {
379 response->error = KM_ERROR_INVALID_KEY_BLOB;
380 return;
381 }
382
383 void* key_material = der_encoded_key.release();
384 response->SetKeyMaterial(key_material, len);
385
386 response->error = KM_ERROR_OK;
387}
388
Shawn Willdend67afae2014-08-19 12:36:27 -0600389keymaster_error_t GoogleKeymaster::SerializeKeyToResponse(uint8_t* key_bytes, size_t key_length,
390 const AuthorizationSet& hidden_auths,
391 GenerateKeyResponse* response) {
Shawn Willden39b970b2014-08-11 09:11:21 -0600392 uint8_t nonce[KeyBlob::NONCE_LENGTH];
393 GenerateNonce(nonce, array_size(nonce));
394
395 keymaster_key_blob_t key_data = {key_bytes, key_length};
396 UniquePtr<KeyBlob> blob(new KeyBlob(response->enforced, response->unenforced, hidden_auths,
397 key_data, MasterKey(), nonce));
Shawn Willdend67afae2014-08-19 12:36:27 -0600398 if (blob.get() == NULL)
399 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden39b970b2014-08-11 09:11:21 -0600400
Shawn Willdend67afae2014-08-19 12:36:27 -0600401 if (blob->error() != KM_ERROR_OK)
Shawn Willden39b970b2014-08-11 09:11:21 -0600402 return blob->error();
Shawn Willden39b970b2014-08-11 09:11:21 -0600403
404 size_t size = blob->SerializedSize();
405 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
Shawn Willdend67afae2014-08-19 12:36:27 -0600406 if (blob_bytes.get() == NULL)
407 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
408
Shawn Willden39b970b2014-08-11 09:11:21 -0600409 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
410 response->key_blob.key_material_size = size;
411 response->key_blob.key_material = blob_bytes.release();
Shawn Willdend67afae2014-08-19 12:36:27 -0600412
413 return KM_ERROR_OK;
414}
415
416Key* GoogleKeymaster::LoadKey(const keymaster_key_blob_t& key,
417 const AuthorizationSet& client_params, keymaster_error_t* error) {
418 UniquePtr<KeyBlob> blob(LoadKeyBlob(key, client_params, error));
419 if (*error != KM_ERROR_OK)
420 return NULL;
421 return Key::CreateKey(*blob, error);
Shawn Willden128ffe02014-08-06 12:31:33 -0600422}
423
Shawn Willden1615f2e2014-08-13 10:37:40 -0600424KeyBlob* GoogleKeymaster::LoadKeyBlob(const keymaster_key_blob_t& key,
425 const AuthorizationSet& client_params,
426 keymaster_error_t* error) {
427 AuthorizationSet hidden;
428 BuildHiddenAuthorizations(client_params, &hidden);
429 UniquePtr<KeyBlob> blob(new KeyBlob(key, hidden, MasterKey()));
430 if (blob.get() == NULL) {
431 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
432 return NULL;
433 } else if (blob->error() != KM_ERROR_OK) {
434 *error = blob->error();
435 return NULL;
436 }
Shawn Willdend67afae2014-08-19 12:36:27 -0600437 *error = KM_ERROR_OK;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600438 return blob.release();
439}
440
Shawn Willden128ffe02014-08-06 12:31:33 -0600441static keymaster_error_t CheckAuthorizationSet(const AuthorizationSet& set) {
442 switch (set.is_valid()) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600443 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600444 return KM_ERROR_OK;
445 case AuthorizationSet::ALLOCATION_FAILURE:
446 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden128ffe02014-08-06 12:31:33 -0600447 case AuthorizationSet::MALFORMED_DATA:
448 return KM_ERROR_UNKNOWN_ERROR;
449 }
450 return KM_ERROR_OK;
451}
452
453bool GoogleKeymaster::CopyAuthorizations(const AuthorizationSet& key_description,
Shawn Willden76364712014-08-11 17:48:04 -0600454 GenerateKeyResponse* response) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600455 for (size_t i = 0; i < key_description.size(); ++i) {
456 switch (key_description[i].tag) {
457 case KM_TAG_ROOT_OF_TRUST:
458 case KM_TAG_CREATION_DATETIME:
459 case KM_TAG_ORIGIN:
460 response->error = KM_ERROR_INVALID_TAG;
461 return false;
462 case KM_TAG_ROLLBACK_RESISTANT:
463 response->error = KM_ERROR_UNSUPPORTED_TAG;
464 return false;
465 default:
Shawn Willden28e41472014-08-18 13:35:22 -0600466 if (!AddAuthorization(key_description[i], response))
467 return false;
Shawn Willden128ffe02014-08-06 12:31:33 -0600468 break;
469 }
470 }
471
Shawn Willden28e41472014-08-18 13:35:22 -0600472 if (!AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response) ||
473 !AddAuthorization(Authorization(TAG_ORIGIN, origin()), response))
474 return false;
Shawn Willden128ffe02014-08-06 12:31:33 -0600475
476 response->error = CheckAuthorizationSet(response->enforced);
477 if (response->error != KM_ERROR_OK)
478 return false;
479 response->error = CheckAuthorizationSet(response->unenforced);
480 if (response->error != KM_ERROR_OK)
481 return false;
482
483 return true;
484}
485
Shawn Willden76364712014-08-11 17:48:04 -0600486keymaster_error_t GoogleKeymaster::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600487 AuthorizationSet* hidden) {
Shawn Willden76364712014-08-11 17:48:04 -0600488 keymaster_blob_t entry;
489 if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
490 hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
491 if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
492 hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
493 hidden->push_back(RootOfTrustTag());
494
495 return CheckAuthorizationSet(*hidden);
496}
497
Shawn Willden28e41472014-08-18 13:35:22 -0600498bool GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
Shawn Willden76364712014-08-11 17:48:04 -0600499 GenerateKeyResponse* response) {
Shawn Willden39b970b2014-08-11 09:11:21 -0600500 switch (auth.tag) {
501 case KM_TAG_ROOT_OF_TRUST:
502 case KM_TAG_APPLICATION_ID:
503 case KM_TAG_APPLICATION_DATA:
Shawn Willden76364712014-08-11 17:48:04 -0600504 // Skip. We handle these tags separately.
Shawn Willden28e41472014-08-18 13:35:22 -0600505 return true;
Shawn Willden39b970b2014-08-11 09:11:21 -0600506 default:
507 if (is_enforced(auth.tag))
Shawn Willden28e41472014-08-18 13:35:22 -0600508 return response->enforced.push_back(auth);
Shawn Willden39b970b2014-08-11 09:11:21 -0600509 else
Shawn Willden28e41472014-08-18 13:35:22 -0600510 return response->unenforced.push_back(auth);
Shawn Willden39b970b2014-08-11 09:11:21 -0600511 }
Shawn Willden128ffe02014-08-06 12:31:33 -0600512}
513
Shawn Willden1615f2e2014-08-13 10:37:40 -0600514keymaster_error_t GoogleKeymaster::AddOperation(Operation* operation,
515 keymaster_operation_handle_t* op_handle) {
516 UniquePtr<Operation> op(operation);
517 if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) == 0)
518 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden802bb292014-08-18 10:46:29 -0600519 if (*op_handle == 0) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600520 // Statistically this is vanishingly unlikely, which means if it ever happens in practice,
521 // it indicates a broken RNG.
522 return KM_ERROR_UNKNOWN_ERROR;
523 }
524 for (size_t i = 0; i < operation_table_size_; ++i) {
525 if (operation_table_[i].operation == NULL) {
526 operation_table_[i].operation = op.release();
527 operation_table_[i].handle = *op_handle;
528 return KM_ERROR_OK;
529 }
530 }
531 return KM_ERROR_TOO_MANY_OPERATIONS;
532}
533
534GoogleKeymaster::OpTableEntry*
535GoogleKeymaster::FindOperation(keymaster_operation_handle_t op_handle) {
536 if (op_handle == 0)
537 return NULL;
538
539 for (size_t i = 0; i < operation_table_size_; ++i) {
540 if (operation_table_[i].handle == op_handle)
541 return operation_table_.get() + i;
542 }
543 return NULL;
544}
545
546void GoogleKeymaster::DeleteOperation(OpTableEntry* entry) {
547 delete entry->operation;
548 entry->operation = NULL;
549 entry->handle = 0;
550}
551
Shawn Willden128ffe02014-08-06 12:31:33 -0600552} // namespace keymaster