Commit | Line | Data |
---|---|---|
e3534476 T |
1 | /* |
2 | * Copyright (C) 2012 Samsung Electronics Co., LTD | |
3 | * Copyright (C) 2012 The Android Open Source Project | |
4 | * | |
5 | * Licensed under the Apache License, Version 2.0 (the "License"); | |
6 | * you may not use this file except in compliance with the License. | |
7 | * You may obtain a copy of the License at | |
8 | * | |
9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
10 | * | |
11 | * Unless required by applicable law or agreed to in writing, software | |
12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
14 | * See the License for the specific language governing permissions and | |
15 | * limitations under the License. | |
16 | */ | |
17 | ||
18 | #include <errno.h> | |
19 | #include <string.h> | |
20 | #include <stdint.h> | |
21 | ||
22 | #include <hardware/hardware.h> | |
23 | #include <hardware/keymaster0.h> | |
24 | ||
25 | #include <openssl/evp.h> | |
26 | #include <openssl/bio.h> | |
27 | #include <openssl/rsa.h> | |
28 | #include <openssl/err.h> | |
29 | #include <openssl/x509.h> | |
30 | ||
491b09af | 31 | #include <keymaster/UniquePtr.h> |
e3534476 T |
32 | |
33 | #define LOG_TAG "ExynosKeyMaster" | |
34 | #include <cutils/log.h> | |
35 | ||
36 | #include <tlcTeeKeymaster_if.h> | |
37 | ||
38 | #define RSA_KEY_BUFFER_SIZE 1536 | |
39 | #define RSA_KEY_MAX_SIZE (2048 >> 3) | |
40 | ||
491b09af L |
41 | using keymaster::UniquePtr; |
42 | ||
e3534476 T |
43 | struct BIGNUM_Delete { |
44 | void operator()(BIGNUM* p) const { | |
45 | BN_free(p); | |
46 | } | |
47 | }; | |
48 | typedef UniquePtr<BIGNUM, BIGNUM_Delete> Unique_BIGNUM; | |
49 | ||
50 | struct EVP_PKEY_Delete { | |
51 | void operator()(EVP_PKEY* p) const { | |
52 | EVP_PKEY_free(p); | |
53 | } | |
54 | }; | |
55 | typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY; | |
56 | ||
57 | struct PKCS8_PRIV_KEY_INFO_Delete { | |
58 | void operator()(PKCS8_PRIV_KEY_INFO* p) const { | |
59 | PKCS8_PRIV_KEY_INFO_free(p); | |
60 | } | |
61 | }; | |
62 | typedef UniquePtr<PKCS8_PRIV_KEY_INFO, PKCS8_PRIV_KEY_INFO_Delete> Unique_PKCS8_PRIV_KEY_INFO; | |
63 | ||
64 | struct RSA_Delete { | |
65 | void operator()(RSA* p) const { | |
66 | RSA_free(p); | |
67 | } | |
68 | }; | |
69 | typedef UniquePtr<RSA, RSA_Delete> Unique_RSA; | |
70 | ||
71 | typedef UniquePtr<keymaster0_device_t> Unique_keymaster0_device_t; | |
72 | ||
73 | /** | |
74 | * Many OpenSSL APIs take ownership of an argument on success but don't free the argument | |
75 | * on failure. This means we need to tell our scoped pointers when we've transferred ownership, | |
76 | * without triggering a warning by not using the result of release(). | |
77 | */ | |
78 | #define OWNERSHIP_TRANSFERRED(obj) \ | |
79 | typeof (obj.release()) _dummy __attribute__((unused)) = obj.release() | |
80 | ||
81 | /* | |
82 | * Checks this thread's error queue and logs if necessary. | |
83 | */ | |
84 | static void logOpenSSLError(const char* location) { | |
85 | int error = ERR_get_error(); | |
86 | ||
87 | if (error != 0) { | |
88 | char message[256]; | |
89 | ERR_error_string_n(error, message, sizeof(message)); | |
90 | ALOGE("OpenSSL error in %s %d: %s", location, error, message); | |
91 | } | |
92 | ||
93 | ERR_clear_error(); | |
94 | ERR_remove_state(0); | |
95 | } | |
96 | ||
97 | static int exynos_km_generate_keypair(const keymaster0_device_t*, | |
98 | const keymaster_keypair_t key_type, const void* key_params, | |
99 | uint8_t** keyBlob, size_t* keyBlobLength) { | |
100 | teeResult_t ret = TEE_ERR_NONE; | |
101 | ||
102 | if (key_type != TYPE_RSA) { | |
103 | ALOGE("Unsupported key type %d", key_type); | |
104 | return -1; | |
105 | } else if (key_params == NULL) { | |
106 | ALOGE("key_params == null"); | |
107 | return -1; | |
108 | } | |
109 | ||
110 | keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params; | |
111 | ||
112 | if ((rsa_params->modulus_size != 512) && | |
113 | (rsa_params->modulus_size != 1024) && | |
114 | (rsa_params->modulus_size != 2048)) { | |
115 | ALOGE("key size(%d) is not supported\n", rsa_params->modulus_size); | |
116 | return -1; | |
117 | } | |
118 | ||
119 | UniquePtr<uint8_t> keyDataPtr(reinterpret_cast<uint8_t*>(malloc(RSA_KEY_BUFFER_SIZE))); | |
120 | if (keyDataPtr.get() == NULL) { | |
121 | ALOGE("memory allocation is failed"); | |
122 | return -1; | |
123 | } | |
124 | ||
125 | ret = TEE_RSAGenerateKeyPair(TEE_KEYPAIR_RSACRT, keyDataPtr.get(), RSA_KEY_BUFFER_SIZE, | |
126 | rsa_params->modulus_size, (uint32_t)rsa_params->public_exponent, | |
127 | (uint32_t *)keyBlobLength); | |
128 | if (ret != TEE_ERR_NONE) { | |
129 | ALOGE("TEE_RSAGenerateKeyPair() is failed: %d", ret); | |
130 | return -1; | |
131 | } | |
132 | ||
133 | *keyBlob = keyDataPtr.release(); | |
134 | ||
135 | return 0; | |
136 | } | |
137 | ||
138 | static int exynos_km_import_keypair(const keymaster0_device_t*, | |
139 | const uint8_t* key, const size_t key_length, | |
140 | uint8_t** key_blob, size_t* key_blob_length) { | |
141 | uint8_t kbuf[RSA_KEY_BUFFER_SIZE]; | |
142 | teeRsaKeyMeta_t metadata; | |
143 | uint32_t key_len = 0; | |
144 | BIGNUM *tmp = NULL; | |
145 | BN_CTX *ctx = NULL; | |
146 | teeResult_t ret = TEE_ERR_NONE; | |
147 | ||
148 | if (key == NULL) { | |
149 | ALOGE("input key == NULL"); | |
150 | return -1; | |
151 | } else if (key_blob == NULL || key_blob_length == NULL) { | |
152 | ALOGE("output key blob or length == NULL"); | |
153 | return -1; | |
154 | } | |
155 | ||
156 | /* decoding */ | |
157 | Unique_PKCS8_PRIV_KEY_INFO pkcs8(d2i_PKCS8_PRIV_KEY_INFO(NULL, &key, key_length)); | |
158 | if (pkcs8.get() == NULL) { | |
159 | logOpenSSLError("pkcs4.get"); | |
160 | return -1; | |
161 | } | |
162 | ||
163 | /* assign to EVP */ | |
164 | Unique_EVP_PKEY pkey(EVP_PKCS82PKEY(pkcs8.get())); | |
165 | if (pkey.get() == NULL) { | |
166 | logOpenSSLError("pkey.get"); | |
167 | return -1; | |
168 | } | |
169 | OWNERSHIP_TRANSFERRED(pkcs8); | |
170 | ||
171 | /* change key format */ | |
172 | Unique_RSA rsa(EVP_PKEY_get1_RSA(pkey.get())); | |
173 | if (rsa.get() == NULL) { | |
174 | logOpenSSLError("get rsa key format"); | |
175 | return -1; | |
176 | } | |
177 | ||
178 | if (BN_cmp(rsa->p, rsa->q) < 0) { | |
179 | /* p <-> q */ | |
180 | tmp = rsa->p; | |
181 | rsa->p = rsa->q; | |
182 | rsa->q = tmp; | |
183 | /* dp <-> dq */ | |
184 | tmp = rsa->dmp1; | |
185 | rsa->dmp1 = rsa->dmq1; | |
186 | rsa->dmq1 = tmp; | |
187 | /* calulate inverse of q mod p */ | |
188 | ctx = BN_CTX_new(); | |
189 | if (!BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx)) { | |
190 | ALOGE("Calculating inverse of q mod p is failed\n"); | |
191 | BN_CTX_free(ctx); | |
192 | return -1; | |
193 | } | |
194 | BN_CTX_free(ctx); | |
195 | } | |
196 | ||
197 | key_len += sizeof(metadata); | |
198 | ||
199 | metadata.lenpubmod = BN_bn2bin(rsa->n, kbuf + key_len); | |
200 | key_len += metadata.lenpubmod; | |
201 | if (metadata.lenpubmod == (512 >> 3)) | |
202 | metadata.keysize = TEE_RSA_KEY_SIZE_512; | |
203 | else if (metadata.lenpubmod == (1024 >> 3)) | |
204 | metadata.keysize = TEE_RSA_KEY_SIZE_1024; | |
205 | else if (metadata.lenpubmod == (2048 >> 3)) | |
206 | metadata.keysize = TEE_RSA_KEY_SIZE_2048; | |
207 | else { | |
208 | ALOGE("key size(%d) is not supported\n", metadata.lenpubmod << 3); | |
209 | return -1; | |
210 | } | |
211 | ||
212 | metadata.lenpubexp = BN_bn2bin(rsa->e, kbuf + key_len); | |
213 | key_len += metadata.lenpubexp; | |
214 | ||
215 | if ((rsa->p != NULL) && (rsa->q != NULL) && (rsa->dmp1 != NULL) && | |
216 | (rsa->dmq1 != NULL) && (rsa->iqmp != NULL)) | |
217 | { | |
218 | metadata.keytype = TEE_KEYPAIR_RSACRT; | |
219 | metadata.rsacrtpriv.lenp = BN_bn2bin(rsa->p, kbuf + key_len); | |
220 | key_len += metadata.rsacrtpriv.lenp; | |
221 | metadata.rsacrtpriv.lenq = BN_bn2bin(rsa->q, kbuf + key_len); | |
222 | key_len += metadata.rsacrtpriv.lenq; | |
223 | metadata.rsacrtpriv.lendp = BN_bn2bin(rsa->dmp1, kbuf + key_len); | |
224 | key_len += metadata.rsacrtpriv.lendp; | |
225 | metadata.rsacrtpriv.lendq = BN_bn2bin(rsa->dmq1, kbuf + key_len); | |
226 | key_len += metadata.rsacrtpriv.lendq; | |
227 | metadata.rsacrtpriv.lenqinv = BN_bn2bin(rsa->iqmp, kbuf + key_len); | |
228 | key_len += metadata.rsacrtpriv.lenqinv; | |
229 | } else { | |
230 | metadata.keytype = TEE_KEYPAIR_RSA; | |
231 | metadata.rsapriv.lenpriexp = BN_bn2bin(rsa->d, kbuf + key_len); | |
232 | key_len += metadata.rsapriv.lenpriexp; | |
233 | } | |
234 | ||
235 | metadata.rfu = 0; | |
236 | metadata.rfulen = 0; | |
237 | ||
238 | memcpy(kbuf, &metadata, sizeof(metadata)); | |
239 | ||
240 | UniquePtr<uint8_t> outPtr(reinterpret_cast<uint8_t*>(malloc(RSA_KEY_BUFFER_SIZE))); | |
241 | if (outPtr.get() == NULL) { | |
242 | ALOGE("memory allocation is failed"); | |
243 | return -1; | |
244 | } | |
245 | ||
246 | *key_blob_length = RSA_KEY_BUFFER_SIZE; | |
247 | ||
248 | ret = TEE_KeyImport(kbuf, key_len, outPtr.get(), (uint32_t *)key_blob_length); | |
249 | if (ret != TEE_ERR_NONE) { | |
250 | ALOGE("TEE_KeyImport() is failed: %d", ret); | |
251 | return -1; | |
252 | } | |
253 | ||
254 | *key_blob = outPtr.release(); | |
255 | ||
256 | return 0; | |
257 | } | |
258 | ||
259 | static int exynos_km_get_keypair_public(const struct keymaster0_device*, | |
260 | const uint8_t* key_blob, const size_t key_blob_length, | |
261 | uint8_t** x509_data, size_t* x509_data_length) { | |
262 | uint32_t bin_mod_len; | |
263 | uint32_t bin_exp_len; | |
264 | teeResult_t ret = TEE_ERR_NONE; | |
265 | ||
266 | if (x509_data == NULL || x509_data_length == NULL) { | |
267 | ALOGE("output public key buffer == NULL"); | |
268 | return -1; | |
269 | } | |
270 | ||
271 | UniquePtr<uint8_t> binModPtr(reinterpret_cast<uint8_t*>(malloc(RSA_KEY_MAX_SIZE))); | |
272 | if (binModPtr.get() == NULL) { | |
273 | ALOGE("memory allocation is failed"); | |
274 | return -1; | |
275 | } | |
276 | ||
277 | UniquePtr<uint8_t> binExpPtr(reinterpret_cast<uint8_t*>(malloc(sizeof(uint32_t)))); | |
278 | if (binExpPtr.get() == NULL) { | |
279 | ALOGE("memory allocation is failed"); | |
280 | return -1; | |
281 | } | |
282 | ||
283 | bin_mod_len = RSA_KEY_MAX_SIZE; | |
284 | bin_exp_len = sizeof(uint32_t); | |
285 | ||
286 | ret = TEE_GetPubKey(key_blob, key_blob_length, binModPtr.get(), &bin_mod_len, binExpPtr.get(), | |
287 | &bin_exp_len); | |
288 | if (ret != TEE_ERR_NONE) { | |
289 | ALOGE("TEE_GetPubKey() is failed: %d", ret); | |
290 | return -1; | |
291 | } | |
292 | ||
293 | Unique_BIGNUM bn_mod(BN_new()); | |
294 | if (bn_mod.get() == NULL) { | |
295 | ALOGE("memory allocation is failed"); | |
296 | return -1; | |
297 | } | |
298 | ||
299 | Unique_BIGNUM bn_exp(BN_new()); | |
300 | if (bn_exp.get() == NULL) { | |
301 | ALOGE("memory allocation is failed"); | |
302 | return -1; | |
303 | } | |
304 | ||
305 | BN_bin2bn(binModPtr.get(), bin_mod_len, bn_mod.get()); | |
306 | BN_bin2bn(binExpPtr.get(), bin_exp_len, bn_exp.get()); | |
307 | ||
308 | /* assign to RSA */ | |
309 | Unique_RSA rsa(RSA_new()); | |
310 | if (rsa.get() == NULL) { | |
311 | logOpenSSLError("rsa.get"); | |
312 | return -1; | |
313 | } | |
314 | ||
315 | RSA* rsa_tmp = rsa.get(); | |
316 | ||
317 | rsa_tmp->n = bn_mod.release(); | |
318 | rsa_tmp->e = bn_exp.release(); | |
319 | ||
320 | /* assign to EVP */ | |
321 | Unique_EVP_PKEY pkey(EVP_PKEY_new()); | |
322 | if (pkey.get() == NULL) { | |
323 | logOpenSSLError("allocate EVP_PKEY"); | |
324 | return -1; | |
325 | } | |
326 | ||
327 | if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) == 0) { | |
328 | logOpenSSLError("assing RSA to EVP_PKEY"); | |
329 | return -1; | |
330 | } | |
331 | OWNERSHIP_TRANSFERRED(rsa); | |
332 | ||
333 | /* change to x.509 format */ | |
334 | int len = i2d_PUBKEY(pkey.get(), NULL); | |
335 | if (len <= 0) { | |
336 | logOpenSSLError("i2d_PUBKEY"); | |
337 | return -1; | |
338 | } | |
339 | ||
340 | UniquePtr<uint8_t> key(static_cast<uint8_t*>(malloc(len))); | |
341 | if (key.get() == NULL) { | |
342 | ALOGE("Could not allocate memory for public key data"); | |
343 | return -1; | |
344 | } | |
345 | ||
346 | unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get()); | |
347 | if (i2d_PUBKEY(pkey.get(), &tmp) != len) { | |
348 | logOpenSSLError("Compare results"); | |
349 | return -1; | |
350 | } | |
351 | ||
352 | *x509_data_length = len; | |
353 | *x509_data = key.release(); | |
354 | ||
355 | return 0; | |
356 | } | |
357 | ||
358 | static int exynos_km_sign_data(const keymaster0_device_t*, | |
359 | const void* params, | |
360 | const uint8_t* keyBlob, const size_t keyBlobLength, | |
361 | const uint8_t* data, const size_t dataLength, | |
362 | uint8_t** signedData, size_t* signedDataLength) { | |
363 | teeResult_t ret = TEE_ERR_NONE; | |
364 | ||
365 | if (data == NULL) { | |
366 | ALOGE("input data to sign == NULL"); | |
367 | return -1; | |
368 | } else if (signedData == NULL || signedDataLength == NULL) { | |
369 | ALOGE("output signature buffer == NULL"); | |
370 | return -1; | |
371 | } | |
372 | ||
373 | keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params; | |
374 | if (sign_params->digest_type != DIGEST_NONE) { | |
375 | ALOGE("Cannot handle digest type %d", sign_params->digest_type); | |
376 | return -1; | |
377 | } else if (sign_params->padding_type != PADDING_NONE) { | |
378 | ALOGE("Cannot handle padding type %d", sign_params->padding_type); | |
379 | return -1; | |
380 | } | |
381 | ||
382 | UniquePtr<uint8_t> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(RSA_KEY_MAX_SIZE))); | |
383 | if (signedDataPtr.get() == NULL) { | |
384 | ALOGE("memory allocation is failed"); | |
385 | return -1; | |
386 | } | |
387 | ||
388 | *signedDataLength = RSA_KEY_MAX_SIZE; | |
389 | ||
390 | /* binder gives us read-only mappings we can't use with mobicore */ | |
391 | void *tmpData = malloc(dataLength); | |
392 | memcpy(tmpData, data, dataLength); | |
393 | ret = TEE_RSASign(keyBlob, keyBlobLength, (const uint8_t *)tmpData, dataLength, signedDataPtr.get(), | |
394 | (uint32_t *)signedDataLength, TEE_RSA_NODIGEST_NOPADDING); | |
395 | free(tmpData); | |
396 | if (ret != TEE_ERR_NONE) { | |
397 | ALOGE("TEE_RSASign() is failed: %d", ret); | |
398 | return -1; | |
399 | } | |
400 | ||
401 | *signedData = signedDataPtr.release(); | |
402 | ||
403 | return 0; | |
404 | } | |
405 | ||
406 | static int exynos_km_verify_data(const keymaster0_device_t*, | |
407 | const void* params, | |
408 | const uint8_t* keyBlob, const size_t keyBlobLength, | |
409 | const uint8_t* signedData, const size_t signedDataLength, | |
410 | const uint8_t* signature, const size_t signatureLength) { | |
411 | bool result; | |
412 | teeResult_t ret = TEE_ERR_NONE; | |
413 | ||
414 | if (signedData == NULL || signature == NULL) { | |
415 | ALOGE("data or signature buffers == NULL"); | |
416 | return -1; | |
417 | } | |
418 | ||
419 | keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params; | |
420 | if (sign_params->digest_type != DIGEST_NONE) { | |
421 | ALOGE("Cannot handle digest type %d", sign_params->digest_type); | |
422 | return -1; | |
423 | } else if (sign_params->padding_type != PADDING_NONE) { | |
424 | ALOGE("Cannot handle padding type %d", sign_params->padding_type); | |
425 | return -1; | |
426 | } else if (signatureLength != signedDataLength) { | |
427 | ALOGE("signed data length must be signature length"); | |
428 | return -1; | |
429 | } | |
430 | ||
431 | void *tmpSignedData = malloc(signedDataLength); | |
432 | memcpy(tmpSignedData, signedData, signedDataLength); | |
433 | void *tmpSig = malloc(signatureLength); | |
434 | memcpy(tmpSig, signature, signatureLength); | |
435 | ret = TEE_RSAVerify(keyBlob, keyBlobLength, (const uint8_t*)tmpSignedData, signedDataLength, (const uint8_t *)tmpSig, | |
436 | signatureLength, TEE_RSA_NODIGEST_NOPADDING, &result); | |
437 | free(tmpSignedData); | |
438 | free(tmpSig); | |
439 | if (ret != TEE_ERR_NONE) { | |
440 | ALOGE("TEE_RSAVerify() is failed: %d", ret); | |
441 | return -1; | |
442 | } | |
443 | ||
444 | return (result == true) ? 0 : -1; | |
445 | } | |
446 | ||
447 | /* Close an opened Exynos KM instance */ | |
448 | static int exynos_km_close(hw_device_t *dev) { | |
449 | free(dev); | |
450 | return 0; | |
451 | } | |
452 | ||
453 | /* | |
454 | * Generic device handling | |
455 | */ | |
456 | static int exynos_km_open(const hw_module_t* module, const char* name, | |
457 | hw_device_t** device) { | |
458 | if (strcmp(name, KEYSTORE_KEYMASTER) != 0) | |
459 | return -EINVAL; | |
460 | ||
461 | Unique_keymaster0_device_t dev(new keymaster0_device_t); | |
462 | if (dev.get() == NULL) | |
463 | return -ENOMEM; | |
464 | ||
465 | dev->common.tag = HARDWARE_DEVICE_TAG; | |
466 | dev->common.version = 1; | |
467 | dev->common.module = (struct hw_module_t*) module; | |
468 | dev->common.close = exynos_km_close; | |
469 | ||
470 | dev->flags = 0; | |
471 | ||
472 | dev->generate_keypair = exynos_km_generate_keypair; | |
473 | dev->import_keypair = exynos_km_import_keypair; | |
474 | dev->get_keypair_public = exynos_km_get_keypair_public; | |
475 | dev->delete_keypair = NULL; | |
476 | dev->delete_all = NULL; | |
477 | dev->sign_data = exynos_km_sign_data; | |
478 | dev->verify_data = exynos_km_verify_data; | |
479 | ||
480 | ERR_load_crypto_strings(); | |
481 | ERR_load_BIO_strings(); | |
482 | ||
483 | *device = reinterpret_cast<hw_device_t*>(dev.release()); | |
484 | ||
485 | return 0; | |
486 | } | |
487 | ||
488 | static struct hw_module_methods_t keystore_module_methods = { | |
741f6764 | 489 | .open = exynos_km_open, |
e3534476 T |
490 | }; |
491 | ||
492 | struct keystore_module HAL_MODULE_INFO_SYM | |
493 | __attribute__ ((visibility ("default"))) = { | |
741f6764 S |
494 | .common = { |
495 | .tag = HARDWARE_MODULE_TAG, | |
496 | .version_major = 1, | |
497 | .version_minor = 0, | |
498 | .id = KEYSTORE_HARDWARE_MODULE_ID, | |
499 | .name = "Keymaster Exynos HAL", | |
500 | .author = "Samsung S.LSI", | |
501 | .methods = &keystore_module_methods, | |
502 | .dso = 0, | |
503 | .reserved = {}, | |
e3534476 T |
504 | }, |
505 | }; |