blob: 8723cb126cbbdfd1bed97bfbba1e23b19422de14 [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 Willden39b970b2014-08-11 09:11:21 -0600202 AuthorizationSet hidden_auths;
203 if (!CopyAuthorizations(request.key_description, response, &hidden_auths))
Shawn Willden128ffe02014-08-06 12:31:33 -0600204 return;
205
206 keymaster_algorithm_t algorithm;
207 if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
208 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
209 return;
210 }
211 switch (algorithm) {
212 case KM_ALGORITHM_RSA:
Shawn Willden39b970b2014-08-11 09:11:21 -0600213 if (!GenerateRsa(request.key_description, response, &hidden_auths))
Shawn Willden128ffe02014-08-06 12:31:33 -0600214 return;
215 break;
216 default:
217 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
218 return;
219 }
220}
221
Shawn Willden39b970b2014-08-11 09:11:21 -0600222bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths, GenerateKeyResponse* response,
223 AuthorizationSet* hidden_auths) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600224 uint64_t public_exponent = RSA_DEFAULT_EXPONENT;
225 if (!key_auths.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent))
Shawn Willden39b970b2014-08-11 09:11:21 -0600226 AddAuthorization(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent), response,
227 hidden_auths);
Shawn Willden128ffe02014-08-06 12:31:33 -0600228
229 uint32_t key_size = RSA_DEFAULT_KEY_SIZE;
230 if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
Shawn Willden39b970b2014-08-11 09:11:21 -0600231 AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response, hidden_auths);
Shawn Willden128ffe02014-08-06 12:31:33 -0600232
233 Unique_BIGNUM exponent(BN_new());
234 Unique_RSA rsa_key(RSA_new());
235 Unique_EVP_PKEY pkey(EVP_PKEY_new());
236 if (rsa_key.get() == NULL || pkey.get() == NULL) {
237 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
238 return false;
239 }
240
241 if (!BN_set_word(exponent.get(), public_exponent) ||
242 !RSA_generate_key_ex(rsa_key.get(), key_size, exponent.get(), NULL /* callback */)) {
243 response->error = KM_ERROR_UNKNOWN_ERROR;
244 return false;
245 }
246
247 if (!EVP_PKEY_assign_RSA(pkey.get(), rsa_key.get())) {
248 response->error = KM_ERROR_UNKNOWN_ERROR;
249 return false;
250 } else {
251 release_because_ownership_transferred(rsa_key);
252 }
253
254 int der_length = i2d_PrivateKey(pkey.get(), NULL);
255 if (der_length <= 0) {
256 response->error = KM_ERROR_UNKNOWN_ERROR;
257 return false;
258 }
259 UniquePtr<uint8_t[]> der_data(new uint8_t[der_length]);
260 if (der_data.get() == NULL) {
261 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
262 return false;
263 }
264
265 uint8_t* tmp = der_data.get();
266 i2d_PrivateKey(pkey.get(), &tmp);
267
Shawn Willden39b970b2014-08-11 09:11:21 -0600268 return CreateKeyBlob(response, *hidden_auths, der_data.get(), der_length);
269}
270
271bool GoogleKeymaster::CreateKeyBlob(GenerateKeyResponse* response,
272 const AuthorizationSet& hidden_auths, uint8_t* key_bytes,
273 size_t key_length) {
274 uint8_t nonce[KeyBlob::NONCE_LENGTH];
275 GenerateNonce(nonce, array_size(nonce));
276
277 keymaster_key_blob_t key_data = {key_bytes, key_length};
278 UniquePtr<KeyBlob> blob(new KeyBlob(response->enforced, response->unenforced, hidden_auths,
279 key_data, MasterKey(), nonce));
280 if (blob.get() == NULL) {
281 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
282 return false;
283 }
284
285 if (blob->error() != KM_ERROR_OK) {
286 return blob->error();
287 return false;
288 }
289
290 size_t size = blob->SerializedSize();
291 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
292 if (blob_bytes.get() == NULL) {
293 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
294 return false;
295 }
296 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
297 response->key_blob.key_material_size = size;
298 response->key_blob.key_material = blob_bytes.release();
299 return true;
Shawn Willden128ffe02014-08-06 12:31:33 -0600300}
301
302static keymaster_error_t CheckAuthorizationSet(const AuthorizationSet& set) {
303 switch (set.is_valid()) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600304 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600305 return KM_ERROR_OK;
306 case AuthorizationSet::ALLOCATION_FAILURE:
307 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
Shawn Willden128ffe02014-08-06 12:31:33 -0600308 case AuthorizationSet::MALFORMED_DATA:
309 return KM_ERROR_UNKNOWN_ERROR;
310 }
311 return KM_ERROR_OK;
312}
313
314bool GoogleKeymaster::CopyAuthorizations(const AuthorizationSet& key_description,
Shawn Willden39b970b2014-08-11 09:11:21 -0600315 GenerateKeyResponse* response,
316 AuthorizationSet* hidden_auths) {
Shawn Willden128ffe02014-08-06 12:31:33 -0600317 for (size_t i = 0; i < key_description.size(); ++i) {
318 switch (key_description[i].tag) {
319 case KM_TAG_ROOT_OF_TRUST:
320 case KM_TAG_CREATION_DATETIME:
321 case KM_TAG_ORIGIN:
322 response->error = KM_ERROR_INVALID_TAG;
323 return false;
324 case KM_TAG_ROLLBACK_RESISTANT:
325 response->error = KM_ERROR_UNSUPPORTED_TAG;
326 return false;
327 default:
Shawn Willden39b970b2014-08-11 09:11:21 -0600328 AddAuthorization(key_description[i], response, hidden_auths);
Shawn Willden128ffe02014-08-06 12:31:33 -0600329 break;
330 }
331 }
332
Shawn Willden39b970b2014-08-11 09:11:21 -0600333 AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response,
334 hidden_auths);
335 AddAuthorization(Authorization(TAG_ORIGIN, origin()), response, hidden_auths);
336 AddAuthorization(Authorization(TAG_ROOT_OF_TRUST, "SW", 2), response, hidden_auths);
Shawn Willden128ffe02014-08-06 12:31:33 -0600337
338 response->error = CheckAuthorizationSet(response->enforced);
339 if (response->error != KM_ERROR_OK)
340 return false;
341 response->error = CheckAuthorizationSet(response->unenforced);
342 if (response->error != KM_ERROR_OK)
343 return false;
Shawn Willden39b970b2014-08-11 09:11:21 -0600344 response->error = CheckAuthorizationSet(*hidden_auths);
345 if (response->error != KM_ERROR_OK)
346 return false;
Shawn Willden128ffe02014-08-06 12:31:33 -0600347
348 return true;
349}
350
351void GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
Shawn Willden39b970b2014-08-11 09:11:21 -0600352 GenerateKeyResponse* response,
353 AuthorizationSet* hidden_auths) {
354 switch (auth.tag) {
355 case KM_TAG_ROOT_OF_TRUST:
356 case KM_TAG_APPLICATION_ID:
357 case KM_TAG_APPLICATION_DATA:
358 hidden_auths->push_back(auth);
359 break;
360 default:
361 if (is_enforced(auth.tag))
362 response->enforced.push_back(auth);
363 else
364 response->unenforced.push_back(auth);
365 break;
366 }
Shawn Willden128ffe02014-08-06 12:31:33 -0600367}
368
369} // namespace keymaster