blob: 93c67e5a30e0a57f530ccbffa10e7af75c2775b7 [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;
229 default:
230 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
231 break;
232 }
233
234 if (operation.get() == NULL) {
Shawn Willden76364712014-08-11 17:48:04 -0600235 return;
236 }
Shawn Willden1615f2e2014-08-13 10:37:40 -0600237
238 response->error = operation->Begin();
239 if (response->error != KM_ERROR_OK)
240 return;
241
242 response->error = AddOperation(operation.release(), &response->op_handle);
243}
244
245void GoogleKeymaster::UpdateOperation(const UpdateOperationRequest& request,
246 UpdateOperationResponse* response) {
247 OpTableEntry* entry = FindOperation(request.op_handle);
248 if (entry == NULL) {
249 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
250 return;
251 }
252
253 response->error = entry->operation->Update(request.input, &response->output);
254 if (response->error != KM_ERROR_OK) {
255 // Any error invalidates the operation.
256 DeleteOperation(entry);
257 }
258}
259
Shawn Willden43e999e2014-08-13 13:29:50 -0600260void GoogleKeymaster::FinishOperation(const FinishOperationRequest& request,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600261 FinishOperationResponse* response) {
Shawn Willden43e999e2014-08-13 13:29:50 -0600262 OpTableEntry* entry = FindOperation(request.op_handle);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600263 if (entry == NULL) {
264 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
265 return;
266 }
267
Shawn Willden43e999e2014-08-13 13:29:50 -0600268 response->error = entry->operation->Finish(request.signature, &response->output);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600269 DeleteOperation(entry);
270}
271
272keymaster_error_t GoogleKeymaster::AbortOperation(const keymaster_operation_handle_t op_handle) {
273 OpTableEntry* entry = FindOperation(op_handle);
274 if (entry == NULL)
275 return KM_ERROR_INVALID_OPERATION_HANDLE;
276 DeleteOperation(entry);
277 return KM_ERROR_OK;
Shawn Willden76364712014-08-11 17:48:04 -0600278}
279
Shawn Willden39b970b2014-08-11 09:11:21 -0600280bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
281 AuthorizationSet* hidden_auths) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600282 uint64_t public_exponent = RSA_DEFAULT_EXPONENT;
283 if (!key_auths.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent))
Shawn Willden76364712014-08-11 17:48:04 -0600284 AddAuthorization(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600285
286 uint32_t key_size = RSA_DEFAULT_KEY_SIZE;
287 if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
Shawn Willden76364712014-08-11 17:48:04 -0600288 AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600289
Shawn Willden802bb292014-08-18 10:46:29 -0600290 UniquePtr<uint8_t[]> key_data;
291 size_t key_data_size;
292 keymaster_error_t error =
293 RsaOperation::Generate(public_exponent, key_size, &key_data, &key_data_size);
294 if (error != KM_ERROR_OK) {
295 response->error = error;
Shawn Willden128ffe02014-08-06 12:31:33 -0600296 return false;
297 }
298
Shawn Willden802bb292014-08-18 10:46:29 -0600299 return CreateKeyBlob(response, *hidden_auths, key_data.get(), key_data_size);
Shawn Willden39b970b2014-08-11 09:11:21 -0600300}
301
Shawn Willden28e41472014-08-18 13:35:22 -0600302template <keymaster_tag_t Tag>
303static void GetDsaParamData(const AuthorizationSet& auths, TypedTag<KM_BIGNUM, Tag> tag,
304 keymaster_blob_t* blob) {
305 if (!auths.GetTagValue(tag, blob))
306 blob->data = NULL;
307}
308
309bool GoogleKeymaster::GenerateDsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
310 AuthorizationSet* hidden_auths) {
311 keymaster_blob_t g_blob;
312 GetDsaParamData(key_auths, TAG_DSA_GENERATOR, &g_blob);
313 const uint8_t* original_g = g_blob.data;
314
315 keymaster_blob_t p_blob;
316 GetDsaParamData(key_auths, TAG_DSA_P, &p_blob);
317 const uint8_t* original_p = p_blob.data;
318
319 keymaster_blob_t q_blob;
320 GetDsaParamData(key_auths, TAG_DSA_Q, &q_blob);
321 const uint8_t* original_q = q_blob.data;
322
323 uint32_t key_size = DSA_DEFAULT_KEY_SIZE;
324 if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
325 AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response);
326
327 UniquePtr<uint8_t[]> key_data;
328 size_t key_data_size;
329 keymaster_error_t error =
330 DsaOperation::Generate(key_size, &g_blob, &p_blob, &q_blob, &key_data, &key_data_size);
331
332 // If any the original_* pointers are NULL, DsaOperation::Generate should have generated values
333 // for the corressponding blobs. We need to put them in the authorization set and clean up the
334 // allocated memory.
335 if (original_g == NULL && g_blob.data != NULL) {
336 if (!AddAuthorization(Authorization(TAG_DSA_GENERATOR, g_blob), response))
337 error = KM_ERROR_INVALID_DSA_PARAMS;
338 delete[] g_blob.data;
339 }
340 if (original_p == NULL && p_blob.data != NULL) {
341 if (!AddAuthorization(Authorization(TAG_DSA_P, p_blob), response))
342 error = KM_ERROR_INVALID_DSA_PARAMS;
343 delete[] p_blob.data;
344 }
345 if (original_q == NULL && q_blob.data != NULL) {
346 if (!AddAuthorization(Authorization(TAG_DSA_Q, q_blob), response))
347 error = KM_ERROR_INVALID_DSA_PARAMS;
348 delete[] q_blob.data;
349 }
350
351 if (error != KM_ERROR_OK) {
352 response->error = error;
353 return false;
354 }
355
356 return CreateKeyBlob(response, *hidden_auths, key_data.get(), key_data_size);
357}
358
Shawn Willden39b970b2014-08-11 09:11:21 -0600359bool GoogleKeymaster::CreateKeyBlob(GenerateKeyResponse* response,
360 const AuthorizationSet& hidden_auths, uint8_t* key_bytes,
361 size_t key_length) {
362 uint8_t nonce[KeyBlob::NONCE_LENGTH];
363 GenerateNonce(nonce, array_size(nonce));
364
365 keymaster_key_blob_t key_data = {key_bytes, key_length};
366 UniquePtr<KeyBlob> blob(new KeyBlob(response->enforced, response->unenforced, hidden_auths,
367 key_data, MasterKey(), nonce));
368 if (blob.get() == NULL) {
369 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
370 return false;
371 }
372
373 if (blob->error() != KM_ERROR_OK) {
374 return blob->error();
375 return false;
376 }
377
378 size_t size = blob->SerializedSize();
379 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
380 if (blob_bytes.get() == NULL) {
381 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
382 return false;
383 }
384 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
385 response->key_blob.key_material_size = size;
386 response->key_blob.key_material = blob_bytes.release();
387 return true;
Shawn Willden128ffe02014-08-06 12:31:33 -0600388}
389
Shawn Willden1615f2e2014-08-13 10:37:40 -0600390KeyBlob* GoogleKeymaster::LoadKeyBlob(const keymaster_key_blob_t& key,
391 const AuthorizationSet& client_params,
392 keymaster_error_t* error) {
393 AuthorizationSet hidden;
394 BuildHiddenAuthorizations(client_params, &hidden);
395 UniquePtr<KeyBlob> blob(new KeyBlob(key, hidden, MasterKey()));
396 if (blob.get() == NULL) {
397 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
398 return NULL;
399 } else if (blob->error() != KM_ERROR_OK) {
400 *error = blob->error();
401 return NULL;
402 }
403 return blob.release();
404}
405
Shawn Willden128ffe02014-08-06 12:31:33 -0600406static keymaster_error_t CheckAuthorizationSet(const AuthorizationSet& set) {
407 switch (set.is_valid()) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600408 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600409 return KM_ERROR_OK;
410 case AuthorizationSet::ALLOCATION_FAILURE:
411 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden128ffe02014-08-06 12:31:33 -0600412 case AuthorizationSet::MALFORMED_DATA:
413 return KM_ERROR_UNKNOWN_ERROR;
414 }
415 return KM_ERROR_OK;
416}
417
418bool GoogleKeymaster::CopyAuthorizations(const AuthorizationSet& key_description,
Shawn Willden76364712014-08-11 17:48:04 -0600419 GenerateKeyResponse* response) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600420 for (size_t i = 0; i < key_description.size(); ++i) {
421 switch (key_description[i].tag) {
422 case KM_TAG_ROOT_OF_TRUST:
423 case KM_TAG_CREATION_DATETIME:
424 case KM_TAG_ORIGIN:
425 response->error = KM_ERROR_INVALID_TAG;
426 return false;
427 case KM_TAG_ROLLBACK_RESISTANT:
428 response->error = KM_ERROR_UNSUPPORTED_TAG;
429 return false;
430 default:
Shawn Willden28e41472014-08-18 13:35:22 -0600431 if (!AddAuthorization(key_description[i], response))
432 return false;
Shawn Willden128ffe02014-08-06 12:31:33 -0600433 break;
434 }
435 }
436
Shawn Willden28e41472014-08-18 13:35:22 -0600437 if (!AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response) ||
438 !AddAuthorization(Authorization(TAG_ORIGIN, origin()), response))
439 return false;
Shawn Willden128ffe02014-08-06 12:31:33 -0600440
441 response->error = CheckAuthorizationSet(response->enforced);
442 if (response->error != KM_ERROR_OK)
443 return false;
444 response->error = CheckAuthorizationSet(response->unenforced);
445 if (response->error != KM_ERROR_OK)
446 return false;
447
448 return true;
449}
450
Shawn Willden76364712014-08-11 17:48:04 -0600451keymaster_error_t GoogleKeymaster::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600452 AuthorizationSet* hidden) {
Shawn Willden76364712014-08-11 17:48:04 -0600453 keymaster_blob_t entry;
454 if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
455 hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
456 if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
457 hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
458 hidden->push_back(RootOfTrustTag());
459
460 return CheckAuthorizationSet(*hidden);
461}
462
Shawn Willden28e41472014-08-18 13:35:22 -0600463bool GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
Shawn Willden76364712014-08-11 17:48:04 -0600464 GenerateKeyResponse* response) {
Shawn Willden39b970b2014-08-11 09:11:21 -0600465 switch (auth.tag) {
466 case KM_TAG_ROOT_OF_TRUST:
467 case KM_TAG_APPLICATION_ID:
468 case KM_TAG_APPLICATION_DATA:
Shawn Willden76364712014-08-11 17:48:04 -0600469 // Skip. We handle these tags separately.
Shawn Willden28e41472014-08-18 13:35:22 -0600470 return true;
Shawn Willden39b970b2014-08-11 09:11:21 -0600471 default:
472 if (is_enforced(auth.tag))
Shawn Willden28e41472014-08-18 13:35:22 -0600473 return response->enforced.push_back(auth);
Shawn Willden39b970b2014-08-11 09:11:21 -0600474 else
Shawn Willden28e41472014-08-18 13:35:22 -0600475 return response->unenforced.push_back(auth);
Shawn Willden39b970b2014-08-11 09:11:21 -0600476 }
Shawn Willden128ffe02014-08-06 12:31:33 -0600477}
478
Shawn Willden1615f2e2014-08-13 10:37:40 -0600479keymaster_error_t GoogleKeymaster::AddOperation(Operation* operation,
480 keymaster_operation_handle_t* op_handle) {
481 UniquePtr<Operation> op(operation);
482 if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) == 0)
483 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden802bb292014-08-18 10:46:29 -0600484 if (*op_handle == 0) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600485 // Statistically this is vanishingly unlikely, which means if it ever happens in practice,
486 // it indicates a broken RNG.
487 return KM_ERROR_UNKNOWN_ERROR;
488 }
489 for (size_t i = 0; i < operation_table_size_; ++i) {
490 if (operation_table_[i].operation == NULL) {
491 operation_table_[i].operation = op.release();
492 operation_table_[i].handle = *op_handle;
493 return KM_ERROR_OK;
494 }
495 }
496 return KM_ERROR_TOO_MANY_OPERATIONS;
497}
498
499GoogleKeymaster::OpTableEntry*
500GoogleKeymaster::FindOperation(keymaster_operation_handle_t op_handle) {
501 if (op_handle == 0)
502 return NULL;
503
504 for (size_t i = 0; i < operation_table_size_; ++i) {
505 if (operation_table_[i].handle == op_handle)
506 return operation_table_.get() + i;
507 }
508 return NULL;
509}
510
511void GoogleKeymaster::DeleteOperation(OpTableEntry* entry) {
512 delete entry->operation;
513 entry->operation = NULL;
514 entry->handle = 0;
515}
516
Shawn Willden128ffe02014-08-06 12:31:33 -0600517} // namespace keymaster