blob: 80d8215a61d194b032a8dc17788553449a8b22cd [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 Willden28e41472014-08-18 13:35:22 -060027#include "dsa_operation.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060028#include "google_keymaster.h"
29#include "google_keymaster_utils.h"
Shawn Willden4db3fbd2014-08-08 22:13:44 -060030#include "key_blob.h"
Shawn Willden1615f2e2014-08-13 10:37:40 -060031#include "rsa_operation.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060032
33namespace keymaster {
34
Shawn Willden1615f2e2014-08-13 10:37:40 -060035GoogleKeymaster::GoogleKeymaster(size_t operation_table_size)
36 : operation_table_(new OpTableEntry[operation_table_size]),
37 operation_table_size_(operation_table_size) {
38 if (operation_table_.get() == NULL)
39 operation_table_size_ = 0;
Shawn Willden39b970b2014-08-11 09:11:21 -060040}
41GoogleKeymaster::~GoogleKeymaster() {
Shawn Willden1615f2e2014-08-13 10:37:40 -060042 for (size_t i = 0; i < operation_table_size_; ++i)
43 if (operation_table_[i].operation != NULL)
44 delete operation_table_[i].operation;
Shawn Willden39b970b2014-08-11 09:11:21 -060045}
Shawn Willden128ffe02014-08-06 12:31:33 -060046
Shawn Willden28e41472014-08-18 13:35:22 -060047const uint32_t RSA_DEFAULT_KEY_SIZE = 2048;
48const uint32_t DSA_DEFAULT_KEY_SIZE = 2048;
49const uint64_t RSA_DEFAULT_EXPONENT = 65537;
Shawn Willden128ffe02014-08-06 12:31:33 -060050
Shawn Willden128ffe02014-08-06 12:31:33 -060051struct AE_CTX_Delete {
Shawn Willden802bb292014-08-18 10:46:29 -060052 void operator()(ae_ctx* ctx) const { ae_free(ctx); }
Shawn Willden128ffe02014-08-06 12:31:33 -060053};
54typedef UniquePtr<ae_ctx, AE_CTX_Delete> Unique_ae_ctx;
55
Shawn Willden128ffe02014-08-06 12:31:33 -060056keymaster_algorithm_t supported_algorithms[] = {
Shawn Willden28e41472014-08-18 13:35:22 -060057 KM_ALGORITHM_RSA, KM_ALGORITHM_DSA,
Shawn Willden128ffe02014-08-06 12:31:33 -060058};
59
60template <typename T>
61bool check_supported(keymaster_algorithm_t algorithm, SupportedResponse<T>* response) {
62 if (!array_contains(supported_algorithms, algorithm)) {
63 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
64 return false;
65 }
66 return true;
67}
68
69void
70GoogleKeymaster::SupportedAlgorithms(SupportedResponse<keymaster_algorithm_t>* response) const {
71 if (response == NULL)
72 return;
73 response->SetResults(supported_algorithms);
74}
75
76void
77GoogleKeymaster::SupportedBlockModes(keymaster_algorithm_t algorithm,
78 SupportedResponse<keymaster_block_mode_t>* response) const {
79 if (response == NULL || !check_supported(algorithm, response))
80 return;
81 response->error = KM_ERROR_OK;
82}
83
Shawn Willden28e41472014-08-18 13:35:22 -060084keymaster_padding_t supported_padding[] = {KM_PAD_NONE};
Shawn Willden128ffe02014-08-06 12:31:33 -060085void
86GoogleKeymaster::SupportedPaddingModes(keymaster_algorithm_t algorithm,
87 SupportedResponse<keymaster_padding_t>* response) const {
88 if (response == NULL || !check_supported(algorithm, response))
89 return;
90
91 response->error = KM_ERROR_OK;
92 switch (algorithm) {
93 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -060094 case KM_ALGORITHM_DSA:
95 response->SetResults(supported_padding);
Shawn Willden128ffe02014-08-06 12:31:33 -060096 break;
97 default:
98 response->results_length = 0;
99 break;
100 }
101}
102
Shawn Willden28e41472014-08-18 13:35:22 -0600103keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE};
Shawn Willden128ffe02014-08-06 12:31:33 -0600104void GoogleKeymaster::SupportedDigests(keymaster_algorithm_t algorithm,
105 SupportedResponse<keymaster_digest_t>* response) const {
106 if (response == NULL || !check_supported(algorithm, response))
107 return;
108
109 response->error = KM_ERROR_OK;
110 switch (algorithm) {
111 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600112 case KM_ALGORITHM_DSA:
113 response->SetResults(supported_digests);
Shawn Willden128ffe02014-08-06 12:31:33 -0600114 break;
115 default:
116 response->results_length = 0;
117 break;
118 }
119}
120
Shawn Willden28e41472014-08-18 13:35:22 -0600121keymaster_key_format_t supported_import_formats[] = {KM_KEY_FORMAT_PKCS8};
Shawn Willden128ffe02014-08-06 12:31:33 -0600122void
123GoogleKeymaster::SupportedImportFormats(keymaster_algorithm_t algorithm,
124 SupportedResponse<keymaster_key_format_t>* response) const {
125 if (response == NULL || !check_supported(algorithm, response))
126 return;
127
128 response->error = KM_ERROR_OK;
129 switch (algorithm) {
130 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600131 case KM_ALGORITHM_DSA:
132 response->SetResults(supported_import_formats);
Shawn Willden128ffe02014-08-06 12:31:33 -0600133 break;
134 default:
135 response->results_length = 0;
136 break;
137 }
138}
139
Shawn Willden28e41472014-08-18 13:35:22 -0600140keymaster_key_format_t supported_export_formats[] = {KM_KEY_FORMAT_X509};
Shawn Willden128ffe02014-08-06 12:31:33 -0600141void
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:
Shawn Willden28e41472014-08-18 13:35:22 -0600150 case KM_ALGORITHM_DSA:
151 response->SetResults(supported_export_formats);
Shawn Willden128ffe02014-08-06 12:31:33 -0600152 break;
153 default:
154 response->results_length = 0;
155 break;
156 }
157}
158
Shawn Willden128ffe02014-08-06 12:31:33 -0600159void GoogleKeymaster::GenerateKey(const GenerateKeyRequest& request,
160 GenerateKeyResponse* response) {
161 if (response == NULL)
162 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600163 response->error = KM_ERROR_UNKNOWN_ERROR;
Shawn Willden128ffe02014-08-06 12:31:33 -0600164
Shawn Willden76364712014-08-11 17:48:04 -0600165 if (!CopyAuthorizations(request.key_description, response))
166 return;
167
Shawn Willden39b970b2014-08-11 09:11:21 -0600168 AuthorizationSet hidden_auths;
Shawn Willden76364712014-08-11 17:48:04 -0600169 response->error = BuildHiddenAuthorizations(request.key_description, &hidden_auths);
170 if (response->error != KM_ERROR_OK)
Shawn Willden128ffe02014-08-06 12:31:33 -0600171 return;
172
173 keymaster_algorithm_t algorithm;
174 if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
175 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
176 return;
177 }
Shawn Willden28e41472014-08-18 13:35:22 -0600178
Shawn Willden128ffe02014-08-06 12:31:33 -0600179 switch (algorithm) {
180 case KM_ALGORITHM_RSA:
Shawn Willden39b970b2014-08-11 09:11:21 -0600181 if (!GenerateRsa(request.key_description, response, &hidden_auths))
Shawn Willden128ffe02014-08-06 12:31:33 -0600182 return;
183 break;
Shawn Willden28e41472014-08-18 13:35:22 -0600184 case KM_ALGORITHM_DSA:
185 if (!GenerateDsa(request.key_description, response, &hidden_auths))
186 return;
187 break;
Shawn Willden128ffe02014-08-06 12:31:33 -0600188 default:
189 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
190 return;
191 }
Shawn Willden1615f2e2014-08-13 10:37:40 -0600192
193 response->error = KM_ERROR_OK;
Shawn Willden128ffe02014-08-06 12:31:33 -0600194}
195
Shawn Willden76364712014-08-11 17:48:04 -0600196void GoogleKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
197 GetKeyCharacteristicsResponse* response) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600198 if (response == NULL)
199 return;
200 response->error = KM_ERROR_UNKNOWN_ERROR;
Shawn Willden76364712014-08-11 17:48:04 -0600201
Shawn Willden1615f2e2014-08-13 10:37:40 -0600202 UniquePtr<KeyBlob> blob(
203 LoadKeyBlob(request.key_blob, request.additional_params, &(response->error)));
204 if (blob.get() == NULL)
205 return;
206
207 response->enforced.Reinitialize(blob->enforced());
208 response->unenforced.Reinitialize(blob->unenforced());
209 response->error = KM_ERROR_OK;
210}
211
212void GoogleKeymaster::BeginOperation(const BeginOperationRequest& request,
213 BeginOperationResponse* response) {
214 if (response == NULL)
215 return;
216 response->error = KM_ERROR_UNKNOWN_ERROR;
217 response->op_handle = 0;
218
219 UniquePtr<KeyBlob> key(
220 LoadKeyBlob(request.key_blob, request.additional_params, &response->error));
221 if (key.get() == NULL)
222 return;
223
224 UniquePtr<Operation> operation;
225 switch (key->algorithm()) {
226 case KM_ALGORITHM_RSA:
227 operation.reset(new RsaOperation(request.purpose, *key));
228 break;
Shawn Willden5b41ca22014-08-18 14:29:14 -0600229 case KM_ALGORITHM_DSA:
230 operation.reset(new DsaOperation(request.purpose, *key));
231 break;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600232 default:
233 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
234 break;
235 }
236
237 if (operation.get() == NULL) {
Shawn Willden76364712014-08-11 17:48:04 -0600238 return;
239 }
Shawn Willden1615f2e2014-08-13 10:37:40 -0600240
241 response->error = operation->Begin();
242 if (response->error != KM_ERROR_OK)
243 return;
244
245 response->error = AddOperation(operation.release(), &response->op_handle);
246}
247
248void GoogleKeymaster::UpdateOperation(const UpdateOperationRequest& request,
249 UpdateOperationResponse* response) {
250 OpTableEntry* entry = FindOperation(request.op_handle);
251 if (entry == NULL) {
252 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
253 return;
254 }
255
256 response->error = entry->operation->Update(request.input, &response->output);
257 if (response->error != KM_ERROR_OK) {
258 // Any error invalidates the operation.
259 DeleteOperation(entry);
260 }
261}
262
Shawn Willden43e999e2014-08-13 13:29:50 -0600263void GoogleKeymaster::FinishOperation(const FinishOperationRequest& request,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600264 FinishOperationResponse* response) {
Shawn Willden43e999e2014-08-13 13:29:50 -0600265 OpTableEntry* entry = FindOperation(request.op_handle);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600266 if (entry == NULL) {
267 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
268 return;
269 }
270
Shawn Willden43e999e2014-08-13 13:29:50 -0600271 response->error = entry->operation->Finish(request.signature, &response->output);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600272 DeleteOperation(entry);
273}
274
275keymaster_error_t GoogleKeymaster::AbortOperation(const keymaster_operation_handle_t op_handle) {
276 OpTableEntry* entry = FindOperation(op_handle);
277 if (entry == NULL)
278 return KM_ERROR_INVALID_OPERATION_HANDLE;
279 DeleteOperation(entry);
280 return KM_ERROR_OK;
Shawn Willden76364712014-08-11 17:48:04 -0600281}
282
Shawn Willden39b970b2014-08-11 09:11:21 -0600283bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
284 AuthorizationSet* hidden_auths) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600285 uint64_t public_exponent = RSA_DEFAULT_EXPONENT;
286 if (!key_auths.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent))
Shawn Willden76364712014-08-11 17:48:04 -0600287 AddAuthorization(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600288
289 uint32_t key_size = RSA_DEFAULT_KEY_SIZE;
290 if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
Shawn Willden76364712014-08-11 17:48:04 -0600291 AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600292
Shawn Willden802bb292014-08-18 10:46:29 -0600293 UniquePtr<uint8_t[]> key_data;
294 size_t key_data_size;
295 keymaster_error_t error =
296 RsaOperation::Generate(public_exponent, key_size, &key_data, &key_data_size);
297 if (error != KM_ERROR_OK) {
298 response->error = error;
Shawn Willden128ffe02014-08-06 12:31:33 -0600299 return false;
300 }
301
Shawn Willden802bb292014-08-18 10:46:29 -0600302 return CreateKeyBlob(response, *hidden_auths, key_data.get(), key_data_size);
Shawn Willden39b970b2014-08-11 09:11:21 -0600303}
304
Shawn Willden28e41472014-08-18 13:35:22 -0600305template <keymaster_tag_t Tag>
306static void GetDsaParamData(const AuthorizationSet& auths, TypedTag<KM_BIGNUM, Tag> tag,
307 keymaster_blob_t* blob) {
308 if (!auths.GetTagValue(tag, blob))
309 blob->data = NULL;
310}
311
312bool GoogleKeymaster::GenerateDsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
313 AuthorizationSet* hidden_auths) {
314 keymaster_blob_t g_blob;
315 GetDsaParamData(key_auths, TAG_DSA_GENERATOR, &g_blob);
316 const uint8_t* original_g = g_blob.data;
317
318 keymaster_blob_t p_blob;
319 GetDsaParamData(key_auths, TAG_DSA_P, &p_blob);
320 const uint8_t* original_p = p_blob.data;
321
322 keymaster_blob_t q_blob;
323 GetDsaParamData(key_auths, TAG_DSA_Q, &q_blob);
324 const uint8_t* original_q = q_blob.data;
325
326 uint32_t key_size = DSA_DEFAULT_KEY_SIZE;
327 if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
328 AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response);
329
330 UniquePtr<uint8_t[]> key_data;
331 size_t key_data_size;
332 keymaster_error_t error =
333 DsaOperation::Generate(key_size, &g_blob, &p_blob, &q_blob, &key_data, &key_data_size);
334
335 // If any the original_* pointers are NULL, DsaOperation::Generate should have generated values
336 // for the corressponding blobs. We need to put them in the authorization set and clean up the
337 // allocated memory.
338 if (original_g == NULL && g_blob.data != NULL) {
339 if (!AddAuthorization(Authorization(TAG_DSA_GENERATOR, g_blob), response))
340 error = KM_ERROR_INVALID_DSA_PARAMS;
341 delete[] g_blob.data;
342 }
343 if (original_p == NULL && p_blob.data != NULL) {
344 if (!AddAuthorization(Authorization(TAG_DSA_P, p_blob), response))
345 error = KM_ERROR_INVALID_DSA_PARAMS;
346 delete[] p_blob.data;
347 }
348 if (original_q == NULL && q_blob.data != NULL) {
349 if (!AddAuthorization(Authorization(TAG_DSA_Q, q_blob), response))
350 error = KM_ERROR_INVALID_DSA_PARAMS;
351 delete[] q_blob.data;
352 }
353
354 if (error != KM_ERROR_OK) {
355 response->error = error;
356 return false;
357 }
358
359 return CreateKeyBlob(response, *hidden_auths, key_data.get(), key_data_size);
360}
361
Shawn Willden39b970b2014-08-11 09:11:21 -0600362bool GoogleKeymaster::CreateKeyBlob(GenerateKeyResponse* response,
363 const AuthorizationSet& hidden_auths, uint8_t* key_bytes,
364 size_t key_length) {
365 uint8_t nonce[KeyBlob::NONCE_LENGTH];
366 GenerateNonce(nonce, array_size(nonce));
367
368 keymaster_key_blob_t key_data = {key_bytes, key_length};
369 UniquePtr<KeyBlob> blob(new KeyBlob(response->enforced, response->unenforced, hidden_auths,
370 key_data, MasterKey(), nonce));
371 if (blob.get() == NULL) {
372 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
373 return false;
374 }
375
376 if (blob->error() != KM_ERROR_OK) {
377 return blob->error();
378 return false;
379 }
380
381 size_t size = blob->SerializedSize();
382 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
383 if (blob_bytes.get() == NULL) {
384 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
385 return false;
386 }
387 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
388 response->key_blob.key_material_size = size;
389 response->key_blob.key_material = blob_bytes.release();
390 return true;
Shawn Willden128ffe02014-08-06 12:31:33 -0600391}
392
Shawn Willden1615f2e2014-08-13 10:37:40 -0600393KeyBlob* GoogleKeymaster::LoadKeyBlob(const keymaster_key_blob_t& key,
394 const AuthorizationSet& client_params,
395 keymaster_error_t* error) {
396 AuthorizationSet hidden;
397 BuildHiddenAuthorizations(client_params, &hidden);
398 UniquePtr<KeyBlob> blob(new KeyBlob(key, hidden, MasterKey()));
399 if (blob.get() == NULL) {
400 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
401 return NULL;
402 } else if (blob->error() != KM_ERROR_OK) {
403 *error = blob->error();
404 return NULL;
405 }
406 return blob.release();
407}
408
Shawn Willden128ffe02014-08-06 12:31:33 -0600409static keymaster_error_t CheckAuthorizationSet(const AuthorizationSet& set) {
410 switch (set.is_valid()) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600411 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600412 return KM_ERROR_OK;
413 case AuthorizationSet::ALLOCATION_FAILURE:
414 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden128ffe02014-08-06 12:31:33 -0600415 case AuthorizationSet::MALFORMED_DATA:
416 return KM_ERROR_UNKNOWN_ERROR;
417 }
418 return KM_ERROR_OK;
419}
420
421bool GoogleKeymaster::CopyAuthorizations(const AuthorizationSet& key_description,
Shawn Willden76364712014-08-11 17:48:04 -0600422 GenerateKeyResponse* response) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600423 for (size_t i = 0; i < key_description.size(); ++i) {
424 switch (key_description[i].tag) {
425 case KM_TAG_ROOT_OF_TRUST:
426 case KM_TAG_CREATION_DATETIME:
427 case KM_TAG_ORIGIN:
428 response->error = KM_ERROR_INVALID_TAG;
429 return false;
430 case KM_TAG_ROLLBACK_RESISTANT:
431 response->error = KM_ERROR_UNSUPPORTED_TAG;
432 return false;
433 default:
Shawn Willden28e41472014-08-18 13:35:22 -0600434 if (!AddAuthorization(key_description[i], response))
435 return false;
Shawn Willden128ffe02014-08-06 12:31:33 -0600436 break;
437 }
438 }
439
Shawn Willden28e41472014-08-18 13:35:22 -0600440 if (!AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response) ||
441 !AddAuthorization(Authorization(TAG_ORIGIN, origin()), response))
442 return false;
Shawn Willden128ffe02014-08-06 12:31:33 -0600443
444 response->error = CheckAuthorizationSet(response->enforced);
445 if (response->error != KM_ERROR_OK)
446 return false;
447 response->error = CheckAuthorizationSet(response->unenforced);
448 if (response->error != KM_ERROR_OK)
449 return false;
450
451 return true;
452}
453
Shawn Willden76364712014-08-11 17:48:04 -0600454keymaster_error_t GoogleKeymaster::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600455 AuthorizationSet* hidden) {
Shawn Willden76364712014-08-11 17:48:04 -0600456 keymaster_blob_t entry;
457 if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
458 hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
459 if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
460 hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
461 hidden->push_back(RootOfTrustTag());
462
463 return CheckAuthorizationSet(*hidden);
464}
465
Shawn Willden28e41472014-08-18 13:35:22 -0600466bool GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
Shawn Willden76364712014-08-11 17:48:04 -0600467 GenerateKeyResponse* response) {
Shawn Willden39b970b2014-08-11 09:11:21 -0600468 switch (auth.tag) {
469 case KM_TAG_ROOT_OF_TRUST:
470 case KM_TAG_APPLICATION_ID:
471 case KM_TAG_APPLICATION_DATA:
Shawn Willden76364712014-08-11 17:48:04 -0600472 // Skip. We handle these tags separately.
Shawn Willden28e41472014-08-18 13:35:22 -0600473 return true;
Shawn Willden39b970b2014-08-11 09:11:21 -0600474 default:
475 if (is_enforced(auth.tag))
Shawn Willden28e41472014-08-18 13:35:22 -0600476 return response->enforced.push_back(auth);
Shawn Willden39b970b2014-08-11 09:11:21 -0600477 else
Shawn Willden28e41472014-08-18 13:35:22 -0600478 return response->unenforced.push_back(auth);
Shawn Willden39b970b2014-08-11 09:11:21 -0600479 }
Shawn Willden128ffe02014-08-06 12:31:33 -0600480}
481
Shawn Willden1615f2e2014-08-13 10:37:40 -0600482keymaster_error_t GoogleKeymaster::AddOperation(Operation* operation,
483 keymaster_operation_handle_t* op_handle) {
484 UniquePtr<Operation> op(operation);
485 if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) == 0)
486 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden802bb292014-08-18 10:46:29 -0600487 if (*op_handle == 0) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600488 // Statistically this is vanishingly unlikely, which means if it ever happens in practice,
489 // it indicates a broken RNG.
490 return KM_ERROR_UNKNOWN_ERROR;
491 }
492 for (size_t i = 0; i < operation_table_size_; ++i) {
493 if (operation_table_[i].operation == NULL) {
494 operation_table_[i].operation = op.release();
495 operation_table_[i].handle = *op_handle;
496 return KM_ERROR_OK;
497 }
498 }
499 return KM_ERROR_TOO_MANY_OPERATIONS;
500}
501
502GoogleKeymaster::OpTableEntry*
503GoogleKeymaster::FindOperation(keymaster_operation_handle_t op_handle) {
504 if (op_handle == 0)
505 return NULL;
506
507 for (size_t i = 0; i < operation_table_size_; ++i) {
508 if (operation_table_[i].handle == op_handle)
509 return operation_table_.get() + i;
510 }
511 return NULL;
512}
513
514void GoogleKeymaster::DeleteOperation(OpTableEntry* entry) {
515 delete entry->operation;
516 entry->operation = NULL;
517 entry->handle = 0;
518}
519
Shawn Willden128ffe02014-08-06 12:31:33 -0600520} // namespace keymaster