blob: 5d8541b2c9567d6a2d8730d6c48069071cd375ef [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 Willden128ffe02014-08-06 12:31:33 -060053keymaster_algorithm_t supported_algorithms[] = {
Shawn Willdenc3864dd2014-08-18 15:20:01 -060054 KM_ALGORITHM_RSA, KM_ALGORITHM_DSA, KM_ALGORITHM_ECDSA,
Shawn Willden128ffe02014-08-06 12:31:33 -060055};
56
57template <typename T>
58bool check_supported(keymaster_algorithm_t algorithm, SupportedResponse<T>* response) {
59 if (!array_contains(supported_algorithms, algorithm)) {
60 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
61 return false;
62 }
63 return true;
64}
65
66void
67GoogleKeymaster::SupportedAlgorithms(SupportedResponse<keymaster_algorithm_t>* response) const {
68 if (response == NULL)
69 return;
70 response->SetResults(supported_algorithms);
71}
72
73void
74GoogleKeymaster::SupportedBlockModes(keymaster_algorithm_t algorithm,
75 SupportedResponse<keymaster_block_mode_t>* response) const {
76 if (response == NULL || !check_supported(algorithm, response))
77 return;
78 response->error = KM_ERROR_OK;
79}
80
Shawn Willden28e41472014-08-18 13:35:22 -060081keymaster_padding_t supported_padding[] = {KM_PAD_NONE};
Shawn Willden128ffe02014-08-06 12:31:33 -060082void
83GoogleKeymaster::SupportedPaddingModes(keymaster_algorithm_t algorithm,
84 SupportedResponse<keymaster_padding_t>* response) const {
85 if (response == NULL || !check_supported(algorithm, response))
86 return;
87
88 response->error = KM_ERROR_OK;
89 switch (algorithm) {
90 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -060091 case KM_ALGORITHM_DSA:
Shawn Willdenc3864dd2014-08-18 15:20:01 -060092 case KM_ALGORITHM_ECDSA:
Shawn Willden28e41472014-08-18 13:35:22 -060093 response->SetResults(supported_padding);
Shawn Willden128ffe02014-08-06 12:31:33 -060094 break;
95 default:
96 response->results_length = 0;
97 break;
98 }
99}
100
Shawn Willden28e41472014-08-18 13:35:22 -0600101keymaster_digest_t supported_digests[] = {KM_DIGEST_NONE};
Shawn Willden128ffe02014-08-06 12:31:33 -0600102void GoogleKeymaster::SupportedDigests(keymaster_algorithm_t algorithm,
103 SupportedResponse<keymaster_digest_t>* response) const {
104 if (response == NULL || !check_supported(algorithm, response))
105 return;
106
107 response->error = KM_ERROR_OK;
108 switch (algorithm) {
109 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600110 case KM_ALGORITHM_DSA:
Shawn Willdenc3864dd2014-08-18 15:20:01 -0600111 case KM_ALGORITHM_ECDSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600112 response->SetResults(supported_digests);
Shawn Willden128ffe02014-08-06 12:31:33 -0600113 break;
114 default:
115 response->results_length = 0;
116 break;
117 }
118}
119
Shawn Willden28e41472014-08-18 13:35:22 -0600120keymaster_key_format_t supported_import_formats[] = {KM_KEY_FORMAT_PKCS8};
Shawn Willden128ffe02014-08-06 12:31:33 -0600121void
122GoogleKeymaster::SupportedImportFormats(keymaster_algorithm_t algorithm,
123 SupportedResponse<keymaster_key_format_t>* response) const {
124 if (response == NULL || !check_supported(algorithm, response))
125 return;
126
127 response->error = KM_ERROR_OK;
128 switch (algorithm) {
129 case KM_ALGORITHM_RSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600130 case KM_ALGORITHM_DSA:
Shawn Willdenc3864dd2014-08-18 15:20:01 -0600131 case KM_ALGORITHM_ECDSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600132 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:
Shawn Willdenc3864dd2014-08-18 15:20:01 -0600151 case KM_ALGORITHM_ECDSA:
Shawn Willden28e41472014-08-18 13:35:22 -0600152 response->SetResults(supported_export_formats);
Shawn Willden128ffe02014-08-06 12:31:33 -0600153 break;
154 default:
155 response->results_length = 0;
156 break;
157 }
158}
159
Shawn Willden128ffe02014-08-06 12:31:33 -0600160void GoogleKeymaster::GenerateKey(const GenerateKeyRequest& request,
161 GenerateKeyResponse* response) {
162 if (response == NULL)
163 return;
Shawn Willden128ffe02014-08-06 12:31:33 -0600164
Shawn Willdend67afae2014-08-19 12:36:27 -0600165 UniquePtr<Key> key(Key::GenerateKey(request.key_description, &response->error));
Shawn Willden76364712014-08-11 17:48:04 -0600166 if (response->error != KM_ERROR_OK)
Shawn Willden128ffe02014-08-06 12:31:33 -0600167 return;
168
Shawn Willden437fbd12014-08-20 11:59:49 -0600169 response->error = SerializeKey(key.get(), origin(), &response->key_blob, &response->enforced,
170 &response->unenforced);
Shawn Willden128ffe02014-08-06 12:31:33 -0600171}
172
Shawn Willden76364712014-08-11 17:48:04 -0600173void GoogleKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
174 GetKeyCharacteristicsResponse* response) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600175 if (response == NULL)
176 return;
177 response->error = KM_ERROR_UNKNOWN_ERROR;
Shawn Willden76364712014-08-11 17:48:04 -0600178
Shawn Willden1615f2e2014-08-13 10:37:40 -0600179 UniquePtr<KeyBlob> blob(
180 LoadKeyBlob(request.key_blob, request.additional_params, &(response->error)));
181 if (blob.get() == NULL)
182 return;
183
184 response->enforced.Reinitialize(blob->enforced());
185 response->unenforced.Reinitialize(blob->unenforced());
186 response->error = KM_ERROR_OK;
187}
188
189void GoogleKeymaster::BeginOperation(const BeginOperationRequest& request,
190 BeginOperationResponse* response) {
191 if (response == NULL)
192 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600193 response->op_handle = 0;
194
Shawn Willdend67afae2014-08-19 12:36:27 -0600195 UniquePtr<Key> key(LoadKey(request.key_blob, request.additional_params, &response->error));
Shawn Willden1615f2e2014-08-13 10:37:40 -0600196 if (key.get() == NULL)
197 return;
198
Shawn Willdend67afae2014-08-19 12:36:27 -0600199 UniquePtr<Operation> operation(key->CreateOperation(request.purpose, &response->error));
200 if (operation.get() == NULL)
Shawn Willden76364712014-08-11 17:48:04 -0600201 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600202
203 response->error = operation->Begin();
204 if (response->error != KM_ERROR_OK)
205 return;
206
207 response->error = AddOperation(operation.release(), &response->op_handle);
208}
209
210void GoogleKeymaster::UpdateOperation(const UpdateOperationRequest& request,
211 UpdateOperationResponse* response) {
212 OpTableEntry* entry = FindOperation(request.op_handle);
213 if (entry == NULL) {
214 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
215 return;
216 }
217
218 response->error = entry->operation->Update(request.input, &response->output);
219 if (response->error != KM_ERROR_OK) {
220 // Any error invalidates the operation.
221 DeleteOperation(entry);
222 }
223}
224
Shawn Willden43e999e2014-08-13 13:29:50 -0600225void GoogleKeymaster::FinishOperation(const FinishOperationRequest& request,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600226 FinishOperationResponse* response) {
Shawn Willden43e999e2014-08-13 13:29:50 -0600227 OpTableEntry* entry = FindOperation(request.op_handle);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600228 if (entry == NULL) {
229 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
230 return;
231 }
232
Shawn Willden43e999e2014-08-13 13:29:50 -0600233 response->error = entry->operation->Finish(request.signature, &response->output);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600234 DeleteOperation(entry);
235}
236
237keymaster_error_t GoogleKeymaster::AbortOperation(const keymaster_operation_handle_t op_handle) {
238 OpTableEntry* entry = FindOperation(op_handle);
239 if (entry == NULL)
240 return KM_ERROR_INVALID_OPERATION_HANDLE;
241 DeleteOperation(entry);
242 return KM_ERROR_OK;
Shawn Willden76364712014-08-11 17:48:04 -0600243}
244
Shawn Willdenffd790c2014-08-18 21:20:06 -0600245bool GoogleKeymaster::is_supported_export_format(keymaster_key_format_t test_format) {
246 unsigned int index;
247 for (index = 0; index < array_length(supported_export_formats); index++) {
248 if (test_format == supported_export_formats[index]) {
249 return true;
250 }
251 }
252
253 return false;
254}
255
256bool GoogleKeymaster::is_supported_import_format(keymaster_key_format_t test_format) {
257 unsigned int index;
258 for (index = 0; index < array_length(supported_import_formats); index++) {
259 if (test_format == supported_import_formats[index]) {
260 return true;
261 }
262 }
263
264 return false;
265}
266
267void GoogleKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response) {
268 if (response == NULL)
269 return;
270
271 keymaster_error_t blob_error;
Shawn Willdenf268d742014-08-19 15:36:26 -0600272 UniquePtr<Key> to_export(
273 LoadKey(request.key_blob, request.additional_params, &response->error));
Shawn Willdenffd790c2014-08-18 21:20:06 -0600274 if (to_export.get() == NULL)
275 return;
276
Shawn Willdenf268d742014-08-19 15:36:26 -0600277 UniquePtr<uint8_t[]> out_key;
278 size_t size;
279 response->error = to_export->formatted_key_material(request.key_format, &out_key, &size);
280 if (response->error == KM_ERROR_OK) {
281 response->key_data = out_key.release();
282 response->key_data_length = size;
Shawn Willdenffd790c2014-08-18 21:20:06 -0600283 }
Shawn Willdenffd790c2014-08-18 21:20:06 -0600284}
285
286void GoogleKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response) {
Shawn Willden437fbd12014-08-20 11:59:49 -0600287 if (response == NULL)
Shawn Willdenffd790c2014-08-18 21:20:06 -0600288 return;
Shawn Willdenffd790c2014-08-18 21:20:06 -0600289
Shawn Willden437fbd12014-08-20 11:59:49 -0600290 UniquePtr<Key> key(Key::ImportKey(request.key_description, request.key_format, request.key_data,
291 request.key_data_length, &response->error));
292 if (response->error != KM_ERROR_OK)
Shawn Willdenffd790c2014-08-18 21:20:06 -0600293 return;
Shawn Willdenffd790c2014-08-18 21:20:06 -0600294
Shawn Willden437fbd12014-08-20 11:59:49 -0600295 response->error = SerializeKey(key.get(), KM_ORIGIN_IMPORTED, &response->key_blob,
296 &response->enforced, &response->unenforced);
Shawn Willdenffd790c2014-08-18 21:20:06 -0600297}
298
Shawn Willden437fbd12014-08-20 11:59:49 -0600299keymaster_error_t GoogleKeymaster::SerializeKey(const Key* key, keymaster_key_origin_t origin,
300 keymaster_key_blob_t* keymaster_blob,
301 AuthorizationSet* enforced,
302 AuthorizationSet* unenforced) {
303
304 keymaster_error_t error;
305
306 error = SetAuthorizations(key->authorizations(), origin, enforced, unenforced);
307 if (error != KM_ERROR_OK)
308 return error;
309
310 AuthorizationSet hidden_auths;
311 error = BuildHiddenAuthorizations(key->authorizations(), &hidden_auths);
312 if (error != KM_ERROR_OK)
313 return error;
314
315 UniquePtr<uint8_t[]> key_material;
316 size_t key_material_size;
317 error = key->key_material(&key_material, &key_material_size);
318 if (error != KM_ERROR_OK)
319 return error;
320
Shawn Willden39b970b2014-08-11 09:11:21 -0600321 uint8_t nonce[KeyBlob::NONCE_LENGTH];
322 GenerateNonce(nonce, array_size(nonce));
323
Shawn Willden437fbd12014-08-20 11:59:49 -0600324 keymaster_key_blob_t key_data = {key_material.get(), key_material_size};
325 UniquePtr<KeyBlob> blob(
326 new KeyBlob(*enforced, *unenforced, hidden_auths, key_data, MasterKey(), nonce));
Shawn Willdend67afae2014-08-19 12:36:27 -0600327 if (blob.get() == NULL)
328 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdend67afae2014-08-19 12:36:27 -0600329 if (blob->error() != KM_ERROR_OK)
Shawn Willden39b970b2014-08-11 09:11:21 -0600330 return blob->error();
Shawn Willden39b970b2014-08-11 09:11:21 -0600331
332 size_t size = blob->SerializedSize();
333 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
Shawn Willdend67afae2014-08-19 12:36:27 -0600334 if (blob_bytes.get() == NULL)
335 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
336
Shawn Willden39b970b2014-08-11 09:11:21 -0600337 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
Shawn Willden437fbd12014-08-20 11:59:49 -0600338 keymaster_blob->key_material_size = size;
339 keymaster_blob->key_material = blob_bytes.release();
Shawn Willdend67afae2014-08-19 12:36:27 -0600340
341 return KM_ERROR_OK;
342}
343
344Key* GoogleKeymaster::LoadKey(const keymaster_key_blob_t& key,
345 const AuthorizationSet& client_params, keymaster_error_t* error) {
346 UniquePtr<KeyBlob> blob(LoadKeyBlob(key, client_params, error));
347 if (*error != KM_ERROR_OK)
348 return NULL;
349 return Key::CreateKey(*blob, error);
Shawn Willden128ffe02014-08-06 12:31:33 -0600350}
351
Shawn Willden1615f2e2014-08-13 10:37:40 -0600352KeyBlob* GoogleKeymaster::LoadKeyBlob(const keymaster_key_blob_t& key,
353 const AuthorizationSet& client_params,
354 keymaster_error_t* error) {
355 AuthorizationSet hidden;
356 BuildHiddenAuthorizations(client_params, &hidden);
357 UniquePtr<KeyBlob> blob(new KeyBlob(key, hidden, MasterKey()));
358 if (blob.get() == NULL) {
359 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
360 return NULL;
361 } else if (blob->error() != KM_ERROR_OK) {
362 *error = blob->error();
363 return NULL;
364 }
Shawn Willdend67afae2014-08-19 12:36:27 -0600365 *error = KM_ERROR_OK;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600366 return blob.release();
367}
368
Shawn Willden437fbd12014-08-20 11:59:49 -0600369static keymaster_error_t TranslateAuthorizationSetError(AuthorizationSet::Error err) {
370 switch (err) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600371 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600372 return KM_ERROR_OK;
373 case AuthorizationSet::ALLOCATION_FAILURE:
374 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden128ffe02014-08-06 12:31:33 -0600375 case AuthorizationSet::MALFORMED_DATA:
376 return KM_ERROR_UNKNOWN_ERROR;
377 }
378 return KM_ERROR_OK;
379}
380
Shawn Willden437fbd12014-08-20 11:59:49 -0600381keymaster_error_t GoogleKeymaster::SetAuthorizations(const AuthorizationSet& key_description,
382 keymaster_key_origin_t origin,
383 AuthorizationSet* enforced,
384 AuthorizationSet* unenforced) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600385 for (size_t i = 0; i < key_description.size(); ++i) {
386 switch (key_description[i].tag) {
Shawn Willden437fbd12014-08-20 11:59:49 -0600387 // These cannot be specified by the client.
Shawn Willden128ffe02014-08-06 12:31:33 -0600388 case KM_TAG_ROOT_OF_TRUST:
389 case KM_TAG_CREATION_DATETIME:
390 case KM_TAG_ORIGIN:
Shawn Willden437fbd12014-08-20 11:59:49 -0600391 return KM_ERROR_INVALID_TAG;
392
393 // These don't work.
Shawn Willden128ffe02014-08-06 12:31:33 -0600394 case KM_TAG_ROLLBACK_RESISTANT:
Shawn Willden437fbd12014-08-20 11:59:49 -0600395 return KM_ERROR_UNSUPPORTED_TAG;
396
397 // These are hidden.
398 case KM_TAG_APPLICATION_ID:
399 case KM_TAG_APPLICATION_DATA:
400 break;
401
402 // Everything else we just copy into the appropriate set.
Shawn Willden128ffe02014-08-06 12:31:33 -0600403 default:
Shawn Willden437fbd12014-08-20 11:59:49 -0600404 AddAuthorization(key_description[i], enforced, unenforced);
Shawn Willden128ffe02014-08-06 12:31:33 -0600405 break;
406 }
407 }
408
Shawn Willden437fbd12014-08-20 11:59:49 -0600409 AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), enforced,
410 unenforced);
411 AddAuthorization(Authorization(TAG_ORIGIN, origin), enforced, unenforced);
Shawn Willden128ffe02014-08-06 12:31:33 -0600412
Shawn Willden437fbd12014-08-20 11:59:49 -0600413 if (enforced->is_valid() != AuthorizationSet::OK)
414 return TranslateAuthorizationSetError(enforced->is_valid());
Shawn Willden128ffe02014-08-06 12:31:33 -0600415
Shawn Willden437fbd12014-08-20 11:59:49 -0600416 return TranslateAuthorizationSetError(unenforced->is_valid());
Shawn Willden128ffe02014-08-06 12:31:33 -0600417}
418
Shawn Willden76364712014-08-11 17:48:04 -0600419keymaster_error_t GoogleKeymaster::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600420 AuthorizationSet* hidden) {
Shawn Willden76364712014-08-11 17:48:04 -0600421 keymaster_blob_t entry;
422 if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
423 hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
424 if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
425 hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
426 hidden->push_back(RootOfTrustTag());
427
Shawn Willden437fbd12014-08-20 11:59:49 -0600428 return TranslateAuthorizationSetError(hidden->is_valid());
Shawn Willden76364712014-08-11 17:48:04 -0600429}
430
Shawn Willden437fbd12014-08-20 11:59:49 -0600431void GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
432 AuthorizationSet* enforced, AuthorizationSet* unenforced) {
433 if (is_enforced(auth.tag))
434 enforced->push_back(auth);
435 else
436 unenforced->push_back(auth);
Shawn Willden128ffe02014-08-06 12:31:33 -0600437}
438
Shawn Willden1615f2e2014-08-13 10:37:40 -0600439keymaster_error_t GoogleKeymaster::AddOperation(Operation* operation,
440 keymaster_operation_handle_t* op_handle) {
441 UniquePtr<Operation> op(operation);
442 if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) == 0)
443 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden802bb292014-08-18 10:46:29 -0600444 if (*op_handle == 0) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600445 // Statistically this is vanishingly unlikely, which means if it ever happens in practice,
446 // it indicates a broken RNG.
447 return KM_ERROR_UNKNOWN_ERROR;
448 }
449 for (size_t i = 0; i < operation_table_size_; ++i) {
450 if (operation_table_[i].operation == NULL) {
451 operation_table_[i].operation = op.release();
452 operation_table_[i].handle = *op_handle;
453 return KM_ERROR_OK;
454 }
455 }
456 return KM_ERROR_TOO_MANY_OPERATIONS;
457}
458
459GoogleKeymaster::OpTableEntry*
460GoogleKeymaster::FindOperation(keymaster_operation_handle_t op_handle) {
461 if (op_handle == 0)
462 return NULL;
463
464 for (size_t i = 0; i < operation_table_size_; ++i) {
465 if (operation_table_[i].handle == op_handle)
466 return operation_table_.get() + i;
467 }
468 return NULL;
469}
470
471void GoogleKeymaster::DeleteOperation(OpTableEntry* entry) {
472 delete entry->operation;
473 entry->operation = NULL;
474 entry->handle = 0;
475}
476
Shawn Willden128ffe02014-08-06 12:31:33 -0600477} // namespace keymaster