blob: 9b97ff3439422e075bfb9e612b33f96417f4a2b4 [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 Willden128ffe02014-08-06 12:31:33 -060035GoogleKeymaster::GoogleKeymaster() {}
Shawn Willden128ffe02014-08-06 12:31:33 -060036GoogleKeymaster::~GoogleKeymaster() {}
37
38const int RSA_DEFAULT_KEY_SIZE = 2048;
39const int RSA_DEFAULT_EXPONENT = 65537;
40
Shawn Willden128ffe02014-08-06 12:31:33 -060041struct BIGNUM_Delete {
42 void operator()(BIGNUM* p) const { BN_free(p); }
43};
44typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM;
45
46struct RSA_Delete {
47 void operator()(RSA* p) const { RSA_free(p); }
48};
49typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
50
51struct EVP_PKEY_Delete {
52 void operator()(EVP_PKEY* p) const { EVP_PKEY_free(p); }
53};
54typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
55
56struct AE_CTX_Delete {
57 void operator()(ae_ctx* ctx) const { ae_free(ctx); }
58};
59typedef UniquePtr<ae_ctx, AE_CTX_Delete> Unique_ae_ctx;
60
61struct ByteArray_Delete {
62 void operator()(void* p) const { delete[] reinterpret_cast<uint8_t*>(p); }
63};
64
Shawn Willden128ffe02014-08-06 12:31:33 -060065/**
66 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument on
67 * failure. This means we need to tell our scoped pointers when we've transferred ownership, without
68 * triggering a warning by not using the result of release().
69 */
70template <typename T, typename Delete_T>
71inline void release_because_ownership_transferred(UniquePtr<T, Delete_T>& p) {
72 T* val __attribute__((unused)) = p.release();
73}
74
75keymaster_algorithm_t supported_algorithms[] = {
76 KM_ALGORITHM_RSA,
77};
78
79template <typename T>
80bool check_supported(keymaster_algorithm_t algorithm, SupportedResponse<T>* response) {
81 if (!array_contains(supported_algorithms, algorithm)) {
82 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
83 return false;
84 }
85 return true;
86}
87
88void
89GoogleKeymaster::SupportedAlgorithms(SupportedResponse<keymaster_algorithm_t>* response) const {
90 if (response == NULL)
91 return;
92 response->SetResults(supported_algorithms);
93}
94
95void
96GoogleKeymaster::SupportedBlockModes(keymaster_algorithm_t algorithm,
97 SupportedResponse<keymaster_block_mode_t>* response) const {
98 if (response == NULL || !check_supported(algorithm, response))
99 return;
100 response->error = KM_ERROR_OK;
101}
102
103keymaster_padding_t rsa_supported_padding[] = {KM_PAD_NONE};
104
105void
106GoogleKeymaster::SupportedPaddingModes(keymaster_algorithm_t algorithm,
107 SupportedResponse<keymaster_padding_t>* response) const {
108 if (response == NULL || !check_supported(algorithm, response))
109 return;
110
111 response->error = KM_ERROR_OK;
112 switch (algorithm) {
113 case KM_ALGORITHM_RSA:
114 response->SetResults(rsa_supported_padding);
115 break;
116 default:
117 response->results_length = 0;
118 break;
119 }
120}
121
122keymaster_digest_t rsa_supported_digests[] = {KM_DIGEST_NONE};
123void GoogleKeymaster::SupportedDigests(keymaster_algorithm_t algorithm,
124 SupportedResponse<keymaster_digest_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:
131 response->SetResults(rsa_supported_digests);
132 break;
133 default:
134 response->results_length = 0;
135 break;
136 }
137}
138
139keymaster_key_format_t rsa_supported_import_formats[] = {KM_KEY_FORMAT_PKCS8};
140void
141GoogleKeymaster::SupportedImportFormats(keymaster_algorithm_t algorithm,
142 SupportedResponse<keymaster_key_format_t>* response) const {
143 if (response == NULL || !check_supported(algorithm, response))
144 return;
145
146 response->error = KM_ERROR_OK;
147 switch (algorithm) {
148 case KM_ALGORITHM_RSA:
149 response->SetResults(rsa_supported_import_formats);
150 break;
151 default:
152 response->results_length = 0;
153 break;
154 }
155}
156
157keymaster_key_format_t rsa_supported_export_formats[] = {KM_KEY_FORMAT_X509};
158void
159GoogleKeymaster::SupportedExportFormats(keymaster_algorithm_t algorithm,
160 SupportedResponse<keymaster_key_format_t>* response) const {
161 if (response == NULL || !check_supported(algorithm, response))
162 return;
163
164 response->error = KM_ERROR_OK;
165 switch (algorithm) {
166 case KM_ALGORITHM_RSA:
167 response->SetResults(rsa_supported_export_formats);
168 break;
169 default:
170 response->results_length = 0;
171 break;
172 }
173}
174
175template <typename Message>
176void store_bignum(Message* message, void (Message::*set)(const void* value, size_t size),
177 BIGNUM* bignum) {
178 size_t bufsize = BN_num_bytes(bignum);
179 UniquePtr<uint8_t[]> buf(new uint8_t[bufsize]);
180 int bytes_written = BN_bn2bin(bignum, buf.get());
181 (message->*set)(buf.get(), bytes_written);
182}
183
Shawn Willden128ffe02014-08-06 12:31:33 -0600184void GoogleKeymaster::GenerateKey(const GenerateKeyRequest& request,
185 GenerateKeyResponse* response) {
186 if (response == NULL)
187 return;
188 response->error = KM_ERROR_OK;
189
190 if (!CopyAuthorizations(request.key_description, response))
191 return;
192
193 keymaster_algorithm_t algorithm;
194 if (!request.key_description.GetTagValue(TAG_ALGORITHM, &algorithm)) {
195 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
196 return;
197 }
198 switch (algorithm) {
199 case KM_ALGORITHM_RSA:
200 if (!GenerateRsa(request.key_description, response))
201 return;
202 break;
203 default:
204 response->error = KM_ERROR_UNSUPPORTED_ALGORITHM;
205 return;
206 }
207}
208
Shawn Willden128ffe02014-08-06 12:31:33 -0600209bool GoogleKeymaster::CreateKeyBlob(GenerateKeyResponse* response, uint8_t* key_bytes,
210 size_t key_length) {
Shawn Willden4db3fbd2014-08-08 22:13:44 -0600211 uint8_t nonce[KeyBlob::NONCE_LENGTH];
212 GenerateNonce(nonce, array_size(nonce));
213
214 keymaster_key_blob_t key_data = {key_bytes, key_length};
215 UniquePtr<KeyBlob> blob(
216 new KeyBlob(response->enforced, response->unenforced, key_data, MasterKey(), nonce));
Shawn Willden128ffe02014-08-06 12:31:33 -0600217 if (blob.get() == NULL) {
218 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
219 return false;
220 }
221
Shawn Willden4db3fbd2014-08-08 22:13:44 -0600222 if (blob->error() != KM_ERROR_OK) {
223 return blob->error();
Shawn Willden128ffe02014-08-06 12:31:33 -0600224 return false;
225 }
226
Shawn Willden4db3fbd2014-08-08 22:13:44 -0600227 size_t size = blob->SerializedSize();
228 UniquePtr<uint8_t[]> blob_bytes(new uint8_t[size]);
229 if (blob_bytes.get() == NULL) {
230 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
231 return false;
232 }
233 blob->Serialize(blob_bytes.get(), blob_bytes.get() + size);
234 response->key_blob.key_material_size = size;
235 response->key_blob.key_material = blob_bytes.release();
Shawn Willden128ffe02014-08-06 12:31:33 -0600236 return true;
237}
238
239bool GoogleKeymaster::GenerateRsa(const AuthorizationSet& key_auths,
240 GenerateKeyResponse* response) {
241 uint64_t public_exponent = RSA_DEFAULT_EXPONENT;
242 if (!key_auths.GetTagValue(TAG_RSA_PUBLIC_EXPONENT, &public_exponent))
243 AddAuthorization(Authorization(TAG_RSA_PUBLIC_EXPONENT, public_exponent), response);
244
245 uint32_t key_size = RSA_DEFAULT_KEY_SIZE;
246 if (!key_auths.GetTagValue(TAG_KEY_SIZE, &key_size))
247 AddAuthorization(Authorization(TAG_KEY_SIZE, key_size), response);
248
249 Unique_BIGNUM exponent(BN_new());
250 Unique_RSA rsa_key(RSA_new());
251 Unique_EVP_PKEY pkey(EVP_PKEY_new());
252 if (rsa_key.get() == NULL || pkey.get() == NULL) {
253 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
254 return false;
255 }
256
257 if (!BN_set_word(exponent.get(), public_exponent) ||
258 !RSA_generate_key_ex(rsa_key.get(), key_size, exponent.get(), NULL /* callback */)) {
259 response->error = KM_ERROR_UNKNOWN_ERROR;
260 return false;
261 }
262
263 if (!EVP_PKEY_assign_RSA(pkey.get(), rsa_key.get())) {
264 response->error = KM_ERROR_UNKNOWN_ERROR;
265 return false;
266 } else {
267 release_because_ownership_transferred(rsa_key);
268 }
269
270 int der_length = i2d_PrivateKey(pkey.get(), NULL);
271 if (der_length <= 0) {
272 response->error = KM_ERROR_UNKNOWN_ERROR;
273 return false;
274 }
275 UniquePtr<uint8_t[]> der_data(new uint8_t[der_length]);
276 if (der_data.get() == NULL) {
277 response->error = KM_ERROR_MEMORY_ALLOCATION_FAILED;
278 return false;
279 }
280
281 uint8_t* tmp = der_data.get();
282 i2d_PrivateKey(pkey.get(), &tmp);
283
284 return CreateKeyBlob(response, der_data.get(), der_length);
285}
286
287static keymaster_error_t CheckAuthorizationSet(const AuthorizationSet& set) {
288 switch (set.is_valid()) {
Shawn Willden58e1a542014-08-08 21:58:29 -0600289 case AuthorizationSet::OK:
Shawn Willden128ffe02014-08-06 12:31:33 -0600290 return KM_ERROR_OK;
291 case AuthorizationSet::ALLOCATION_FAILURE:
292 return KM_ERROR_MEMORY_ALLOCATION_FAILED;
293 case AuthorizationSet::BOUNDS_CHECKING_FAILURE:
294 case AuthorizationSet::MALFORMED_DATA:
295 return KM_ERROR_UNKNOWN_ERROR;
296 }
297 return KM_ERROR_OK;
298}
299
300bool GoogleKeymaster::CopyAuthorizations(const AuthorizationSet& key_description,
301 GenerateKeyResponse* response) {
302 for (size_t i = 0; i < key_description.size(); ++i) {
303 switch (key_description[i].tag) {
304 case KM_TAG_ROOT_OF_TRUST:
305 case KM_TAG_CREATION_DATETIME:
306 case KM_TAG_ORIGIN:
307 response->error = KM_ERROR_INVALID_TAG;
308 return false;
309 case KM_TAG_ROLLBACK_RESISTANT:
310 response->error = KM_ERROR_UNSUPPORTED_TAG;
311 return false;
312 default:
313 AddAuthorization(key_description[i], response);
314 break;
315 }
316 }
317
318 AddAuthorization(Authorization(TAG_CREATION_DATETIME, java_time(time(NULL))), response);
319 AddAuthorization(Authorization(TAG_ORIGIN, origin()), response);
320 AddAuthorization(Authorization(TAG_ROOT_OF_TRUST, "SW", 2), response);
321
322 response->error = CheckAuthorizationSet(response->enforced);
323 if (response->error != KM_ERROR_OK)
324 return false;
325 response->error = CheckAuthorizationSet(response->unenforced);
326 if (response->error != KM_ERROR_OK)
327 return false;
328
329 return true;
330}
331
332void GoogleKeymaster::AddAuthorization(const keymaster_key_param_t& auth,
333 GenerateKeyResponse* response) {
334 if (is_enforced(auth.tag))
335 response->enforced.push_back(auth);
336 else
337 response->unenforced.push_back(auth);
338}
339
340} // namespace keymaster