blob: cda181d7cf22dea57c16614533ca87e95e0319e3 [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 Willden98d9b922014-08-26 08:14:10 -060027#include <keymaster/google_keymaster.h>
28#include <keymaster/google_keymaster_utils.h>
29
Shawn Willden3879f862014-08-06 14:40:48 -060030#include "ae.h"
Shawn Willdend67afae2014-08-19 12:36:27 -060031#include "key.h"
Shawn Willdend67afae2014-08-19 12:36:27 -060032#include "operation.h"
Shawn Willden72014ad2014-09-17 13:04:10 -060033#include "unencrypted_key_blob.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060034
35namespace keymaster {
36
Shawn Willden2665e862014-11-24 14:46:21 -070037const uint8_t MAJOR_VER = 1;
38const uint8_t MINOR_VER = 0;
39const uint8_t SUBMINOR_VER = 0;
40
Shawn Willden2f3be362014-08-25 11:31:39 -060041GoogleKeymaster::GoogleKeymaster(size_t operation_table_size, Logger* logger)
Shawn Willden1615f2e2014-08-13 10:37:40 -060042 : operation_table_(new OpTableEntry[operation_table_size]),
Shawn Willden2f3be362014-08-25 11:31:39 -060043 operation_table_size_(operation_table_size), logger_(logger) {
Shawn Willden1615f2e2014-08-13 10:37:40 -060044 if (operation_table_.get() == NULL)
45 operation_table_size_ = 0;
Shawn Willden39b970b2014-08-11 09:11:21 -060046}
Shawn Willdena278f612014-12-23 11:22:21 -070047
Shawn Willden39b970b2014-08-11 09:11:21 -060048GoogleKeymaster::~GoogleKeymaster() {
Shawn Willden1615f2e2014-08-13 10:37:40 -060049 for (size_t i = 0; i < operation_table_size_; ++i)
50 if (operation_table_[i].operation != NULL)
51 delete operation_table_[i].operation;
Shawn Willden39b970b2014-08-11 09:11:21 -060052}
Shawn Willden128ffe02014-08-06 12:31:33 -060053
Shawn Willden128ffe02014-08-06 12:31:33 -060054struct AE_CTX_Delete {
Shawn Willden802bb292014-08-18 10:46:29 -060055 void operator()(ae_ctx* ctx) const { ae_free(ctx); }
Shawn Willden128ffe02014-08-06 12:31:33 -060056};
57typedef UniquePtr<ae_ctx, AE_CTX_Delete> Unique_ae_ctx;
58
Shawn Willden19fca882015-01-22 16:35:30 -070059// TODO(swillden): Unify support analysis. Right now, we have per-keytype methods that determine if
60// specific modes, padding, etc. are supported for that key type, and GoogleKeymaster also has
61// methods that return the same information. They'll get out of sync. Best to put the knowledge in
62// the keytypes and provide some mechanism for GoogleKeymaster to query the keytypes for the
63// information.
Shawn Willdena278f612014-12-23 11:22:21 -070064//
65// UPDATE: This TODO has been completed for supported algorithms. It still needs to be done for
66// modes, padding, etc. This will be done with a registry of operation factories.
Shawn Willden128ffe02014-08-06 12:31:33 -060067
68template <typename T>
69bool check_supported(keymaster_algorithm_t algorithm, SupportedResponse<T>* response) {
Shawn Willdena278f612014-12-23 11:22:21 -070070 if (KeyFactoryRegistry::Get(algorithm) == NULL) {
Shawn Willden128ffe02014-08-06 12:31:33 -060071 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
72 return false;
73 }
74 return true;
75}
76
Shawn Willden2665e862014-11-24 14:46:21 -070077void GoogleKeymaster::GetVersion(const GetVersionRequest&, GetVersionResponse* rsp) {
78 if (rsp == NULL)
79 return;
80
81 rsp->major_ver = MAJOR_VER;
82 rsp->minor_ver = MINOR_VER;
83 rsp->subminor_ver = SUBMINOR_VER;
84 rsp->error = KM_ERROR_OK;
85}
86
Shawn Willden3809b932014-12-02 06:59:46 -070087void GoogleKeymaster::SupportedAlgorithms(
88 SupportedResponse<keymaster_algorithm_t>* response) const {
Shawn Willden128ffe02014-08-06 12:31:33 -060089 if (response == NULL)
90 return;
Shawn Willdena278f612014-12-23 11:22:21 -070091
92 size_t factory_count = 0;
93 const KeyFactory** factories = KeyFactoryRegistry::GetAll(&factory_count);
94 assert(factories != NULL);
95 assert(factory_count > 0);
96
97 UniquePtr<keymaster_algorithm_t[]> algorithms(new keymaster_algorithm_t[factory_count]);
98 if (!algorithms.get()) {
99 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
100 return;
101 }
102
103 for (size_t i = 0; i < factory_count; ++i)
104 algorithms[i] = factories[i]->registry_key();
105
106 response->results = algorithms.release();
107 response->results_length = factory_count;
108 response->error = KM_ERROR_OK;
Shawn Willden128ffe02014-08-06 12:31:33 -0600109}
110
Shawn Willden63ac0432014-12-29 14:07:08 -0700111static OperationFactory* GetOperationFactory(keymaster_algorithm_t algorithm,
112 keymaster_purpose_t purpose,
113 keymaster_error_t* error) {
114 assert(error);
115 if (error)
116 *error = KM_ERROR_OK;
117
118 OperationFactory* factory =
119 OperationFactoryRegistry::Get(OperationFactory::KeyType(algorithm, purpose));
120 if (factory == NULL && error)
121 *error = KM_ERROR_UNSUPPORTED_PURPOSE;
122
123 return factory;
Shawn Willden128ffe02014-08-06 12:31:33 -0600124}
125
Shawn Willden63ac0432014-12-29 14:07:08 -0700126template <typename T>
127void GetSupported(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
128 const T* (OperationFactory::*get_supported_method)(size_t* count) const,
129 SupportedResponse<T>* response) {
130 if (response == NULL || !check_supported(algorithm, response))
131 return;
132
133 OperationFactory* factory = GetOperationFactory(algorithm, purpose, &response->error);
134 if (!factory) {
135 response->error = KM_ERROR_UNSUPPORTED_PURPOSE;
136 return;
137 }
138
139 size_t count;
140 const T* supported = (factory->*get_supported_method)(&count);
141 response->SetResults(supported, count);
142}
143
144void GoogleKeymaster::SupportedBlockModes(
145 keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
146 SupportedResponse<keymaster_block_mode_t>* response) const {
147 GetSupported(algorithm, purpose, &OperationFactory::SupportedBlockModes, response);
148}
Shawn Willden3809b932014-12-02 06:59:46 -0700149
150void GoogleKeymaster::SupportedPaddingModes(
Shawn Willden4200f212014-12-02 07:01:21 -0700151 keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
Shawn Willden3809b932014-12-02 06:59:46 -0700152 SupportedResponse<keymaster_padding_t>* response) const {
Shawn Willden63ac0432014-12-29 14:07:08 -0700153 GetSupported(algorithm, purpose, &OperationFactory::SupportedPaddingModes, response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600154}
155
Shawn Willden63ac0432014-12-29 14:07:08 -0700156void GoogleKeymaster::SupportedDigests(keymaster_algorithm_t algorithm, keymaster_purpose_t purpose,
Shawn Willden128ffe02014-08-06 12:31:33 -0600157 SupportedResponse<keymaster_digest_t>* response) const {
Shawn Willden63ac0432014-12-29 14:07:08 -0700158 GetSupported(algorithm, purpose, &OperationFactory::SupportedDigests, response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600159}
160
Shawn Willden3809b932014-12-02 06:59:46 -0700161void GoogleKeymaster::SupportedImportFormats(
162 keymaster_algorithm_t algorithm, SupportedResponse<keymaster_key_format_t>* response) const {
Shawn Willden128ffe02014-08-06 12:31:33 -0600163 if (response == NULL || !check_supported(algorithm, response))
164 return;
165
Shawn Willdena278f612014-12-23 11:22:21 -0700166 size_t count;
167 const keymaster_key_format_t* formats =
168 KeyFactoryRegistry::Get(algorithm)->SupportedImportFormats(&count);
169 response->SetResults(formats, count);
Shawn Willden128ffe02014-08-06 12:31:33 -0600170}
171
Shawn Willden3809b932014-12-02 06:59:46 -0700172void GoogleKeymaster::SupportedExportFormats(
173 keymaster_algorithm_t algorithm, SupportedResponse<keymaster_key_format_t>* response) const {
Shawn Willden128ffe02014-08-06 12:31:33 -0600174 if (response == NULL || !check_supported(algorithm, response))
175 return;
176
Shawn Willdena278f612014-12-23 11:22:21 -0700177 size_t count;
178 const keymaster_key_format_t* formats =
179 KeyFactoryRegistry::Get(algorithm)->SupportedExportFormats(&count);
180 response->SetResults(formats, count);
Shawn Willden128ffe02014-08-06 12:31:33 -0600181}
182
Shawn Willden128ffe02014-08-06 12:31:33 -0600183void GoogleKeymaster::GenerateKey(const GenerateKeyRequest& request,
184 GenerateKeyResponse* response) {
185 if (response == NULL)
186 return;
Shawn Willden128ffe02014-08-06 12:31:33 -0600187
Shawn Willdena278f612014-12-23 11:22:21 -0700188 keymaster_algorithm_t algorithm;
189 KeyFactory* factory = 0;
190 UniquePtr<Key> key;
191 if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm) ||
192 !(factory = KeyFactoryRegistry::Get(algorithm)))
193 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
194 else
195 key.reset(factory->GenerateKey(request.key_description, logger(), &response->error));
196
Shawn Willden76364712014-08-11 17:48:04 -0600197 if (response->error != KM_ERROR_OK)
Shawn Willden128ffe02014-08-06 12:31:33 -0600198 return;
199
Shawn Willden437fbd12014-08-20 11:59:49 -0600200 response->error = SerializeKey(key.get(), origin(), &response->key_blob, &response->enforced,
201 &response->unenforced);
Shawn Willden128ffe02014-08-06 12:31:33 -0600202}
203
Shawn Willden76364712014-08-11 17:48:04 -0600204void GoogleKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
205 GetKeyCharacteristicsResponse* response) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600206 if (response == NULL)
207 return;
208 response->error = KM_ERROR_UNKNOWN_ERROR;
Shawn Willden76364712014-08-11 17:48:04 -0600209
Shawn Willden1615f2e2014-08-13 10:37:40 -0600210 UniquePtr<KeyBlob> blob(
211 LoadKeyBlob(request.key_blob, request.additional_params, &(response->error)));
212 if (blob.get() == NULL)
213 return;
214
215 response->enforced.Reinitialize(blob->enforced());
216 response->unenforced.Reinitialize(blob->unenforced());
217 response->error = KM_ERROR_OK;
218}
219
220void GoogleKeymaster::BeginOperation(const BeginOperationRequest& request,
221 BeginOperationResponse* response) {
222 if (response == NULL)
223 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600224 response->op_handle = 0;
225
Shawn Willden63ac0432014-12-29 14:07:08 -0700226 keymaster_algorithm_t algorithm;
227 UniquePtr<Key> key(
228 LoadKey(request.key_blob, request.additional_params, &algorithm, &response->error));
Shawn Willden1615f2e2014-08-13 10:37:40 -0600229 if (key.get() == NULL)
230 return;
231
Shawn Willden63ac0432014-12-29 14:07:08 -0700232 OperationFactory::KeyType op_type(algorithm, request.purpose);
233 OperationFactory* factory = OperationFactoryRegistry::Get(op_type);
234 if (!factory) {
235 response->error = KM_ERROR_UNSUPPORTED_PURPOSE;
236 return;
237 }
238
239 UniquePtr<Operation> operation(factory->CreateOperation(*key, logger(), &response->error));
Shawn Willdend67afae2014-08-19 12:36:27 -0600240 if (operation.get() == NULL)
Shawn Willden76364712014-08-11 17:48:04 -0600241 return;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600242
Shawn Willden111edb32015-02-05 22:44:24 -0700243 response->output_params.Clear();
244 response->error = operation->Begin(request.additional_params, &response->output_params);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600245 if (response->error != KM_ERROR_OK)
246 return;
247
248 response->error = AddOperation(operation.release(), &response->op_handle);
249}
250
251void GoogleKeymaster::UpdateOperation(const UpdateOperationRequest& request,
252 UpdateOperationResponse* response) {
Shawn Willdend6cd7e32014-12-17 08:01:26 -0700253 if (response == NULL)
254 return;
255
Shawn Willden1615f2e2014-08-13 10:37:40 -0600256 OpTableEntry* entry = FindOperation(request.op_handle);
257 if (entry == NULL) {
258 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
259 return;
260 }
261
Shawn Willden6bfbff02015-02-06 19:48:24 -0700262 response->error = entry->operation->Update(request.additional_params, request.input,
263 &response->output, &response->input_consumed);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600264 if (response->error != KM_ERROR_OK) {
265 // Any error invalidates the operation.
266 DeleteOperation(entry);
267 }
268}
269
Shawn Willden43e999e2014-08-13 13:29:50 -0600270void GoogleKeymaster::FinishOperation(const FinishOperationRequest& request,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600271 FinishOperationResponse* response) {
Shawn Willdend6cd7e32014-12-17 08:01:26 -0700272 if (response == NULL)
273 return;
274
Shawn Willden43e999e2014-08-13 13:29:50 -0600275 OpTableEntry* entry = FindOperation(request.op_handle);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600276 if (entry == NULL) {
277 response->error = KM_ERROR_INVALID_OPERATION_HANDLE;
278 return;
279 }
280
Shawn Willden6bfbff02015-02-06 19:48:24 -0700281 response->error =
282 entry->operation->Finish(request.additional_params, request.signature, &response->output);
Shawn Willden1615f2e2014-08-13 10:37:40 -0600283 DeleteOperation(entry);
284}
285
286keymaster_error_t GoogleKeymaster::AbortOperation(const keymaster_operation_handle_t op_handle) {
287 OpTableEntry* entry = FindOperation(op_handle);
288 if (entry == NULL)
289 return KM_ERROR_INVALID_OPERATION_HANDLE;
Shawn Willden7ec74f92014-12-11 13:57:59 -0700290 keymaster_error_t error = entry->operation->Abort();
Shawn Willden1615f2e2014-08-13 10:37:40 -0600291 DeleteOperation(entry);
Shawn Willden7ec74f92014-12-11 13:57:59 -0700292 if (error != KM_ERROR_OK)
293 return error;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600294 return KM_ERROR_OK;
Shawn Willden76364712014-08-11 17:48:04 -0600295}
296
Shawn Willdenffd790c2014-08-18 21:20:06 -0600297void GoogleKeymaster::ExportKey(const ExportKeyRequest& request, ExportKeyResponse* response) {
298 if (response == NULL)
299 return;
300
Shawn Willden63ac0432014-12-29 14:07:08 -0700301 keymaster_algorithm_t algorithm;
Shawn Willdenf268d742014-08-19 15:36:26 -0600302 UniquePtr<Key> to_export(
Shawn Willden63ac0432014-12-29 14:07:08 -0700303 LoadKey(request.key_blob, request.additional_params, &algorithm, &response->error));
Shawn Willdenffd790c2014-08-18 21:20:06 -0600304 if (to_export.get() == NULL)
305 return;
306
Shawn Willdenf268d742014-08-19 15:36:26 -0600307 UniquePtr<uint8_t[]> out_key;
308 size_t size;
309 response->error = to_export->formatted_key_material(request.key_format, &out_key, &size);
310 if (response->error == KM_ERROR_OK) {
311 response->key_data = out_key.release();
312 response->key_data_length = size;
Shawn Willdenffd790c2014-08-18 21:20:06 -0600313 }
Shawn Willdenffd790c2014-08-18 21:20:06 -0600314}
315
316void GoogleKeymaster::ImportKey(const ImportKeyRequest& request, ImportKeyResponse* response) {
Shawn Willden437fbd12014-08-20 11:59:49 -0600317 if (response == NULL)
Shawn Willdenffd790c2014-08-18 21:20:06 -0600318 return;
Shawn Willdenffd790c2014-08-18 21:20:06 -0600319
Shawn Willdena278f612014-12-23 11:22:21 -0700320 keymaster_algorithm_t algorithm;
321 KeyFactory* factory = 0;
322 UniquePtr<Key> key;
323 if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm) ||
324 !(factory = KeyFactoryRegistry::Get(algorithm)))
325 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
326 else
327 key.reset(factory->ImportKey(request.key_description, request.key_format, request.key_data,
328 request.key_data_length, logger(), &response->error));
329
Shawn Willden437fbd12014-08-20 11:59:49 -0600330 if (response->error != KM_ERROR_OK)
Shawn Willdenffd790c2014-08-18 21:20:06 -0600331 return;
Shawn Willdenffd790c2014-08-18 21:20:06 -0600332
Shawn Willden437fbd12014-08-20 11:59:49 -0600333 response->error = SerializeKey(key.get(), KM_ORIGIN_IMPORTED, &response->key_blob,
334 &response->enforced, &response->unenforced);
Shawn Willdenffd790c2014-08-18 21:20:06 -0600335}
336
Shawn Willden437fbd12014-08-20 11:59:49 -0600337keymaster_error_t GoogleKeymaster::SerializeKey(const Key* key, keymaster_key_origin_t origin,
338 keymaster_key_blob_t* keymaster_blob,
339 AuthorizationSet* enforced,
340 AuthorizationSet* unenforced) {
Shawn Willden437fbd12014-08-20 11:59:49 -0600341 keymaster_error_t error;
342
343 error = SetAuthorizations(key->authorizations(), origin, enforced, unenforced);
344 if (error != KM_ERROR_OK)
345 return error;
346
347 AuthorizationSet hidden_auths;
348 error = BuildHiddenAuthorizations(key->authorizations(), &hidden_auths);
349 if (error != KM_ERROR_OK)
350 return error;
351
352 UniquePtr<uint8_t[]> key_material;
353 size_t key_material_size;
354 error = key->key_material(&key_material, &key_material_size);
355 if (error != KM_ERROR_OK)
356 return error;
357
Shawn Willden39b970b2014-08-11 09:11:21 -0600358 uint8_t nonce[KeyBlob::NONCE_LENGTH];
359 GenerateNonce(nonce, array_size(nonce));
360
Shawn Willden72014ad2014-09-17 13:04:10 -0600361 keymaster_key_blob_t master_key = MasterKey();
362 UniquePtr<KeyBlob> blob(new UnencryptedKeyBlob(
363 *enforced, *unenforced, hidden_auths, key_material.get(), key_material_size,
364 master_key.key_material, master_key.key_material_size, nonce));
Shawn Willdend67afae2014-08-19 12:36:27 -0600365 if (blob.get() == NULL)
366 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willdend67afae2014-08-19 12:36:27 -0600367 if (blob->error() != KM_ERROR_OK)
Shawn Willden39b970b2014-08-11 09:11:21 -0600368 return blob->error();
Shawn Willden39b970b2014-08-11 09:11:21 -0600369
370 size_t size = blob->SerializedSize();
371 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
Shawn Willdend67afae2014-08-19 12:36:27 -0600372 if (blob_bytes.get() == NULL)
373 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
374
Shawn Willden39b970b2014-08-11 09:11:21 -0600375 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
Shawn Willden437fbd12014-08-20 11:59:49 -0600376 keymaster_blob->key_material_size = size;
377 keymaster_blob->key_material = blob_bytes.release();
Shawn Willdend67afae2014-08-19 12:36:27 -0600378
379 return KM_ERROR_OK;
380}
381
382Key* GoogleKeymaster::LoadKey(const keymaster_key_blob_t& key,
Shawn Willden63ac0432014-12-29 14:07:08 -0700383 const AuthorizationSet& client_params,
384 keymaster_algorithm_t* algorithm, keymaster_error_t* error) {
Shawn Willden72014ad2014-09-17 13:04:10 -0600385 UniquePtr<UnencryptedKeyBlob> blob(LoadKeyBlob(key, client_params, error));
Shawn Willdend67afae2014-08-19 12:36:27 -0600386 if (*error != KM_ERROR_OK)
387 return NULL;
Shawn Willdena278f612014-12-23 11:22:21 -0700388
Shawn Willden63ac0432014-12-29 14:07:08 -0700389 *algorithm = blob->algorithm();
390
Shawn Willdena278f612014-12-23 11:22:21 -0700391 KeyFactory* factory = 0;
Shawn Willden63ac0432014-12-29 14:07:08 -0700392 if ((factory = KeyFactoryRegistry::Get(*algorithm)))
Shawn Willdena278f612014-12-23 11:22:21 -0700393 return factory->LoadKey(*blob, logger(), error);
394 *error = KM_ERROR_UNSUPPORTED_ALGORITHM;
395 return NULL;
Shawn Willden128ffe02014-08-06 12:31:33 -0600396}
397
Shawn Willden72014ad2014-09-17 13:04:10 -0600398UnencryptedKeyBlob* GoogleKeymaster::LoadKeyBlob(const keymaster_key_blob_t& key,
399 const AuthorizationSet& client_params,
400 keymaster_error_t* error) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600401 AuthorizationSet hidden;
402 BuildHiddenAuthorizations(client_params, &hidden);
Shawn Willden72014ad2014-09-17 13:04:10 -0600403 keymaster_key_blob_t master_key = MasterKey();
404 UniquePtr<UnencryptedKeyBlob> blob(
405 new UnencryptedKeyBlob(key, hidden, master_key.key_material, master_key.key_material_size));
Shawn Willden1615f2e2014-08-13 10:37:40 -0600406 if (blob.get() == NULL) {
407 *error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
408 return NULL;
409 } else if (blob->error() != KM_ERROR_OK) {
410 *error = blob->error();
411 return NULL;
412 }
Shawn Willdend67afae2014-08-19 12:36:27 -0600413 *error = KM_ERROR_OK;
Shawn Willden1615f2e2014-08-13 10:37:40 -0600414 return blob.release();
415}
416
Shawn Willden437fbd12014-08-20 11:59:49 -0600417static keymaster_error_t TranslateAuthorizationSetError(AuthorizationSet::Error err) {
418 switch (err) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600419 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600420 return KM_ERROR_OK;
421 case AuthorizationSet::ALLOCATION_FAILURE:
422 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden128ffe02014-08-06 12:31:33 -0600423 case AuthorizationSet::MALFORMED_DATA:
424 return KM_ERROR_UNKNOWN_ERROR;
425 }
426 return KM_ERROR_OK;
427}
428
Shawn Willden437fbd12014-08-20 11:59:49 -0600429keymaster_error_t GoogleKeymaster::SetAuthorizations(const AuthorizationSet& key_description,
430 keymaster_key_origin_t origin,
431 AuthorizationSet* enforced,
432 AuthorizationSet* unenforced) {
Shawn Willden941d1c42014-12-11 13:57:02 -0700433 enforced->Clear();
434 unenforced->Clear();
Shawn Willden128ffe02014-08-06 12:31:33 -0600435 for (size_t i = 0; i < key_description.size(); ++i) {
436 switch (key_description[i].tag) {
Shawn Willden437fbd12014-08-20 11:59:49 -0600437 // These cannot be specified by the client.
Shawn Willden128ffe02014-08-06 12:31:33 -0600438 case KM_TAG_ROOT_OF_TRUST:
Shawn Willden128ffe02014-08-06 12:31:33 -0600439 case KM_TAG_ORIGIN:
Shawn Willden437fbd12014-08-20 11:59:49 -0600440 return KM_ERROR_INVALID_TAG;
441
442 // These don't work.
Shawn Willden128ffe02014-08-06 12:31:33 -0600443 case KM_TAG_ROLLBACK_RESISTANT:
Shawn Willden437fbd12014-08-20 11:59:49 -0600444 return KM_ERROR_UNSUPPORTED_TAG;
445
446 // These are hidden.
447 case KM_TAG_APPLICATION_ID:
448 case KM_TAG_APPLICATION_DATA:
449 break;
450
451 // Everything else we just copy into the appropriate set.
Shawn Willden128ffe02014-08-06 12:31:33 -0600452 default:
Shawn Willden437fbd12014-08-20 11:59:49 -0600453 AddAuthorization(key_description[i], enforced, unenforced);
Shawn Willden128ffe02014-08-06 12:31:33 -0600454 break;
455 }
456 }
457
Shawn Willden437fbd12014-08-20 11:59:49 -0600458 AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), enforced,
459 unenforced);
460 AddAuthorization(Authorization(TAG_ORIGIN, origin), enforced, unenforced);
Shawn Willden128ffe02014-08-06 12:31:33 -0600461
Shawn Willden437fbd12014-08-20 11:59:49 -0600462 if (enforced->is_valid() != AuthorizationSet::OK)
463 return TranslateAuthorizationSetError(enforced->is_valid());
Shawn Willden128ffe02014-08-06 12:31:33 -0600464
Shawn Willden437fbd12014-08-20 11:59:49 -0600465 return TranslateAuthorizationSetError(unenforced->is_valid());
Shawn Willden128ffe02014-08-06 12:31:33 -0600466}
467
Shawn Willden76364712014-08-11 17:48:04 -0600468keymaster_error_t GoogleKeymaster::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
Shawn Willden1615f2e2014-08-13 10:37:40 -0600469 AuthorizationSet* hidden) {
Shawn Willden76364712014-08-11 17:48:04 -0600470 keymaster_blob_t entry;
471 if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
472 hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
473 if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
474 hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
475 hidden->push_back(RootOfTrustTag());
476
Shawn Willden437fbd12014-08-20 11:59:49 -0600477 return TranslateAuthorizationSetError(hidden->is_valid());
Shawn Willden76364712014-08-11 17:48:04 -0600478}
479
Shawn Willden437fbd12014-08-20 11:59:49 -0600480void GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
481 AuthorizationSet* enforced, AuthorizationSet* unenforced) {
482 if (is_enforced(auth.tag))
483 enforced->push_back(auth);
484 else
485 unenforced->push_back(auth);
Shawn Willden128ffe02014-08-06 12:31:33 -0600486}
487
Shawn Willden1615f2e2014-08-13 10:37:40 -0600488keymaster_error_t GoogleKeymaster::AddOperation(Operation* operation,
489 keymaster_operation_handle_t* op_handle) {
490 UniquePtr<Operation> op(operation);
491 if (RAND_bytes(reinterpret_cast<uint8_t*>(op_handle), sizeof(*op_handle)) == 0)
492 return KM_ERROR_UNKNOWN_ERROR;
Shawn Willden802bb292014-08-18 10:46:29 -0600493 if (*op_handle == 0) {
Shawn Willden1615f2e2014-08-13 10:37:40 -0600494 // Statistically this is vanishingly unlikely, which means if it ever happens in practice,
495 // it indicates a broken RNG.
496 return KM_ERROR_UNKNOWN_ERROR;
497 }
498 for (size_t i = 0; i < operation_table_size_; ++i) {
499 if (operation_table_[i].operation == NULL) {
500 operation_table_[i].operation = op.release();
501 operation_table_[i].handle = *op_handle;
502 return KM_ERROR_OK;
503 }
504 }
505 return KM_ERROR_TOO_MANY_OPERATIONS;
506}
507
508GoogleKeymaster::OpTableEntry*
509GoogleKeymaster::FindOperation(keymaster_operation_handle_t op_handle) {
510 if (op_handle == 0)
511 return NULL;
512
513 for (size_t i = 0; i < operation_table_size_; ++i) {
514 if (operation_table_[i].handle == op_handle)
515 return operation_table_.get() + i;
516 }
517 return NULL;
518}
519
520void GoogleKeymaster::DeleteOperation(OpTableEntry* entry) {
521 delete entry->operation;
522 entry->operation = NULL;
523 entry->handle = 0;
524}
525
Shawn Willden128ffe02014-08-06 12:31:33 -0600526} // namespace keymaster