blob: 96cfbdace0143c2f53e070cdcb61518e5813369d [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 Willden128ffe02014-08-06 12:31:33 -060022#include <openssl/err.h>
Shawn Willden3879f862014-08-06 14:40:48 -060023#include <openssl/evp.h>
24#include <openssl/rsa.h>
Shawn Willden128ffe02014-08-06 12:31:33 -060025
26#include <UniquePtr.h>
27
Shawn Willden3879f862014-08-06 14:40:48 -060028#include "ae.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060029#include "google_keymaster.h"
30#include "google_keymaster_utils.h"
Shawn Willden4db3fbd2014-08-08 22:13:44 -060031#include "key_blob.h"
Shawn Willden128ffe02014-08-06 12:31:33 -060032
33namespace keymaster {
34
Shawn Willden39b970b2014-08-11 09:11:21 -060035GoogleKeymaster::GoogleKeymaster() {
36}
37GoogleKeymaster::~GoogleKeymaster() {
38}
Shawn Willden128ffe02014-08-06 12:31:33 -060039
40const int RSA_DEFAULT_KEY_SIZE = 2048;
41const int RSA_DEFAULT_EXPONENT = 65537;
42
Shawn Willden128ffe02014-08-06 12:31:33 -060043struct BIGNUM_Delete {
Shawn Willden39b970b2014-08-11 09:11:21 -060044 void operator()(BIGNUM* p) const {
45 BN_free(p);
46 }
Shawn Willden128ffe02014-08-06 12:31:33 -060047};
48typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
49
50struct RSA_Delete {
Shawn Willden39b970b2014-08-11 09:11:21 -060051 void operator()(RSA* p) const {
52 RSA_free(p);
53 }
Shawn Willden128ffe02014-08-06 12:31:33 -060054};
55typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
56
57struct EVP_PKEY_Delete {
Shawn Willden39b970b2014-08-11 09:11:21 -060058 void operator()(EVP_PKEY* p) const {
59 EVP_PKEY_free(p);
60 }
Shawn Willden128ffe02014-08-06 12:31:33 -060061};
62typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
63
64struct AE_CTX_Delete {
Shawn Willden39b970b2014-08-11 09:11:21 -060065 void operator()(ae_ctx* ctx) const {
66 ae_free(ctx);
67 }
Shawn Willden128ffe02014-08-06 12:31:33 -060068};
69typedef UniquePtr<ae_ctx, AE_CTX_Delete> Unique_ae_ctx;
70
71struct ByteArray_Delete {
Shawn Willden39b970b2014-08-11 09:11:21 -060072 void operator()(void* p) const {
73 delete[] reinterpret_cast<uint8_t*>(p);
74 }
Shawn Willden128ffe02014-08-06 12:31:33 -060075};
76
Shawn Willden128ffe02014-08-06 12:31:33 -060077/**
78 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument on
79 * failure. This means we need to tell our scoped pointers when we've transferred ownership, without
80 * triggering a warning by not using the result of release().
81 */
82template <typename T, typename Delete_T>
83inline void release_because_ownership_transferred(UniquePtr<T, Delete_T>& p) {
84 T* val __attribute__((unused)) = p.release();
85}
86
87keymaster_algorithm_t supported_algorithms[] = {
88 KM_ALGORITHM_RSA,
89};
90
91template <typename T>
92bool check_supported(keymaster_algorithm_t algorithm, SupportedResponse<T>* response) {
93 if (!array_contains(supported_algorithms, algorithm)) {
94 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
95 return false;
96 }
97 return true;
98}
99
100void
101GoogleKeymaster::SupportedAlgorithms(SupportedResponse<keymaster_algorithm_t>* response) const {
102 if (response == NULL)
103 return;
104 response->SetResults(supported_algorithms);
105}
106
107void
108GoogleKeymaster::SupportedBlockModes(keymaster_algorithm_t algorithm,
109 SupportedResponse<keymaster_block_mode_t>* response) const {
110 if (response == NULL || !check_supported(algorithm, response))
111 return;
112 response->error = KM_ERROR_OK;
113}
114
115keymaster_padding_t rsa_supported_padding[] = {KM_PAD_NONE};
116
117void
118GoogleKeymaster::SupportedPaddingModes(keymaster_algorithm_t algorithm,
119 SupportedResponse<keymaster_padding_t>* response) const {
120 if (response == NULL || !check_supported(algorithm, response))
121 return;
122
123 response->error = KM_ERROR_OK;
124 switch (algorithm) {
125 case KM_ALGORITHM_RSA:
126 response->SetResults(rsa_supported_padding);
127 break;
128 default:
129 response->results_length = 0;
130 break;
131 }
132}
133
134keymaster_digest_t rsa_supported_digests[] = {KM_DIGEST_NONE};
135void GoogleKeymaster::SupportedDigests(keymaster_algorithm_t algorithm,
136 SupportedResponse<keymaster_digest_t>* response) const {
137 if (response == NULL || !check_supported(algorithm, response))
138 return;
139
140 response->error = KM_ERROR_OK;
141 switch (algorithm) {
142 case KM_ALGORITHM_RSA:
143 response->SetResults(rsa_supported_digests);
144 break;
145 default:
146 response->results_length = 0;
147 break;
148 }
149}
150
151keymaster_key_format_t rsa_supported_import_formats[] = {KM_KEY_FORMAT_PKCS8};
152void
153GoogleKeymaster::SupportedImportFormats(keymaster_algorithm_t algorithm,
154 SupportedResponse<keymaster_key_format_t>* response) const {
155 if (response == NULL || !check_supported(algorithm, response))
156 return;
157
158 response->error = KM_ERROR_OK;
159 switch (algorithm) {
160 case KM_ALGORITHM_RSA:
161 response->SetResults(rsa_supported_import_formats);
162 break;
163 default:
164 response->results_length = 0;
165 break;
166 }
167}
168
169keymaster_key_format_t rsa_supported_export_formats[] = {KM_KEY_FORMAT_X509};
170void
171GoogleKeymaster::SupportedExportFormats(keymaster_algorithm_t algorithm,
172 SupportedResponse<keymaster_key_format_t>* response) const {
173 if (response == NULL || !check_supported(algorithm, response))
174 return;
175
176 response->error = KM_ERROR_OK;
177 switch (algorithm) {
178 case KM_ALGORITHM_RSA:
179 response->SetResults(rsa_supported_export_formats);
180 break;
181 default:
182 response->results_length = 0;
183 break;
184 }
185}
186
187template <typename Message>
188void store_bignum(Message* message, void (Message::*set)(const void* value, size_t size),
189 BIGNUM* bignum) {
190 size_t bufsize = BN_num_bytes(bignum);
191 UniquePtr<uint8_t[]> buf(new uint8_t[bufsize]);
192 int bytes_written = BN_bn2bin(bignum, buf.get());
193 (message->*set)(buf.get(), bytes_written);
194}
195
Shawn Willden128ffe02014-08-06 12:31:33 -0600196void GoogleKeymaster::GenerateKey(const GenerateKeyRequest& request,
197 GenerateKeyResponse* response) {
198 if (response == NULL)
199 return;
200 response->error = KM_ERROR_OK;
201
Shawn Willden76364712014-08-11 17:48:04 -0600202 if (!CopyAuthorizations(request.key_description, response))
203 return;
204
Shawn Willden39b970b2014-08-11 09:11:21 -0600205 AuthorizationSet hidden_auths;
Shawn Willden76364712014-08-11 17:48:04 -0600206 response->error = BuildHiddenAuthorizations(request.key_description, &hidden_auths);
207 if (response->error != KM_ERROR_OK)
Shawn Willden128ffe02014-08-06 12:31:33 -0600208 return;
209
210 keymaster_algorithm_t algorithm;
211 if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
212 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
213 return;
214 }
215 switch (algorithm) {
216 case KM_ALGORITHM_RSA:
Shawn Willden39b970b2014-08-11 09:11:21 -0600217 if (!GenerateRsa(request.key_description, response, &hidden_auths))
Shawn Willden128ffe02014-08-06 12:31:33 -0600218 return;
219 break;
220 default:
221 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
222 return;
223 }
224}
225
Shawn Willden76364712014-08-11 17:48:04 -0600226void GoogleKeymaster::GetKeyCharacteristics(const GetKeyCharacteristicsRequest& request,
227 GetKeyCharacteristicsResponse* response) {
228 AuthorizationSet hidden;
229 hidden.push_back(TAG_APPLICATION_ID, request.client_id.data, request.client_id.data_length);
230 if (request.app_data.data != NULL)
231 hidden.push_back(TAG_APPLICATION_DATA, request.app_data.data, request.app_data.data_length);
232 hidden.push_back(RootOfTrustTag());
233
234 KeyBlob blob(request.key_blob, hidden, MasterKey());
235 if (blob.error() != KM_ERROR_OK) {
236 response->error = blob.error();
237 return;
238 }
239 response->enforced.Reinitialize(blob.enforced());
240 response->unenforced.Reinitialize(blob.unenforced());
241 response->error = KM_ERROR_OK;
242}
243
Shawn Willden39b970b2014-08-11 09:11:21 -0600244bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
245 AuthorizationSet* hidden_auths) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600246 uint64_t public_exponent = RSA_DEFAULT_EXPONENT;
247 if (!key_auths.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent))
Shawn Willden76364712014-08-11 17:48:04 -0600248 AddAuthorization(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600249
250 uint32_t key_size = RSA_DEFAULT_KEY_SIZE;
251 if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
Shawn Willden76364712014-08-11 17:48:04 -0600252 AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600253
254 Unique_BIGNUM exponent(BN_new());
255 Unique_RSA rsa_key(RSA_new());
256 Unique_EVP_PKEY pkey(EVP_PKEY_new());
257 if (rsa_key.get() == NULL || pkey.get() == NULL) {
258 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
259 return false;
260 }
261
262 if (!BN_set_word(exponent.get(), public_exponent) ||
263 !RSA_generate_key_ex(rsa_key.get(), key_size, exponent.get(), NULL /* callback */)) {
264 response->error = KM_ERROR_UNKNOWN_ERROR;
265 return false;
266 }
267
268 if (!EVP_PKEY_assign_RSA(pkey.get(), rsa_key.get())) {
269 response->error = KM_ERROR_UNKNOWN_ERROR;
270 return false;
271 } else {
272 release_because_ownership_transferred(rsa_key);
273 }
274
275 int der_length = i2d_PrivateKey(pkey.get(), NULL);
276 if (der_length <= 0) {
277 response->error = KM_ERROR_UNKNOWN_ERROR;
278 return false;
279 }
280 UniquePtr<uint8_t[]> der_data(new uint8_t[der_length]);
281 if (der_data.get() == NULL) {
282 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
283 return false;
284 }
285
286 uint8_t* tmp = der_data.get();
287 i2d_PrivateKey(pkey.get(), &tmp);
288
Shawn Willden39b970b2014-08-11 09:11:21 -0600289 return CreateKeyBlob(response, *hidden_auths, der_data.get(), der_length);
290}
291
292bool GoogleKeymaster::CreateKeyBlob(GenerateKeyResponse* response,
293 const AuthorizationSet& hidden_auths, uint8_t* key_bytes,
294 size_t key_length) {
295 uint8_t nonce[KeyBlob::NONCE_LENGTH];
296 GenerateNonce(nonce, array_size(nonce));
297
298 keymaster_key_blob_t key_data = {key_bytes, key_length};
299 UniquePtr<KeyBlob> blob(new KeyBlob(response->enforced, response->unenforced, hidden_auths,
300 key_data, MasterKey(), nonce));
301 if (blob.get() == NULL) {
302 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
303 return false;
304 }
305
306 if (blob->error() != KM_ERROR_OK) {
307 return blob->error();
308 return false;
309 }
310
311 size_t size = blob->SerializedSize();
312 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
313 if (blob_bytes.get() == NULL) {
314 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
315 return false;
316 }
317 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
318 response->key_blob.key_material_size = size;
319 response->key_blob.key_material = blob_bytes.release();
320 return true;
Shawn Willden128ffe02014-08-06 12:31:33 -0600321}
322
323static keymaster_error_t CheckAuthorizationSet(const AuthorizationSet& set) {
324 switch (set.is_valid()) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600325 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600326 return KM_ERROR_OK;
327 case AuthorizationSet::ALLOCATION_FAILURE:
328 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden128ffe02014-08-06 12:31:33 -0600329 case AuthorizationSet::MALFORMED_DATA:
330 return KM_ERROR_UNKNOWN_ERROR;
331 }
332 return KM_ERROR_OK;
333}
334
335bool GoogleKeymaster::CopyAuthorizations(const AuthorizationSet& key_description,
Shawn Willden76364712014-08-11 17:48:04 -0600336 GenerateKeyResponse* response) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600337 for (size_t i = 0; i < key_description.size(); ++i) {
338 switch (key_description[i].tag) {
339 case KM_TAG_ROOT_OF_TRUST:
340 case KM_TAG_CREATION_DATETIME:
341 case KM_TAG_ORIGIN:
342 response->error = KM_ERROR_INVALID_TAG;
343 return false;
344 case KM_TAG_ROLLBACK_RESISTANT:
345 response->error = KM_ERROR_UNSUPPORTED_TAG;
346 return false;
347 default:
Shawn Willden76364712014-08-11 17:48:04 -0600348 AddAuthorization(key_description[i], response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600349 break;
350 }
351 }
352
Shawn Willden76364712014-08-11 17:48:04 -0600353 AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response);
354 AddAuthorization(Authorization(TAG_ORIGIN, origin()), response);
Shawn Willden128ffe02014-08-06 12:31:33 -0600355
356 response->error = CheckAuthorizationSet(response->enforced);
357 if (response->error != KM_ERROR_OK)
358 return false;
359 response->error = CheckAuthorizationSet(response->unenforced);
360 if (response->error != KM_ERROR_OK)
361 return false;
362
363 return true;
364}
365
Shawn Willden76364712014-08-11 17:48:04 -0600366keymaster_error_t GoogleKeymaster::BuildHiddenAuthorizations(const AuthorizationSet& input_set,
367 AuthorizationSet* hidden) {
368 keymaster_blob_t entry;
369 if (input_set.GetTagValue(TAG_APPLICATION_ID, &entry))
370 hidden->push_back(TAG_APPLICATION_ID, entry.data, entry.data_length);
371 if (input_set.GetTagValue(TAG_APPLICATION_DATA, &entry))
372 hidden->push_back(TAG_APPLICATION_DATA, entry.data, entry.data_length);
373 hidden->push_back(RootOfTrustTag());
374
375 return CheckAuthorizationSet(*hidden);
376}
377
Shawn Willden128ffe02014-08-06 12:31:33 -0600378void GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
Shawn Willden76364712014-08-11 17:48:04 -0600379 GenerateKeyResponse* response) {
Shawn Willden39b970b2014-08-11 09:11:21 -0600380 switch (auth.tag) {
381 case KM_TAG_ROOT_OF_TRUST:
382 case KM_TAG_APPLICATION_ID:
383 case KM_TAG_APPLICATION_DATA:
Shawn Willden76364712014-08-11 17:48:04 -0600384 // Skip. We handle these tags separately.
Shawn Willden39b970b2014-08-11 09:11:21 -0600385 break;
386 default:
387 if (is_enforced(auth.tag))
388 response->enforced.push_back(auth);
389 else
390 response->unenforced.push_back(auth);
391 break;
392 }
Shawn Willden128ffe02014-08-06 12:31:33 -0600393}
394
395} // namespace keymaster