blob: 55220d178a52cfb204d6a0f55502585f90faa179 [file] [log] [blame]
Ajay Dudanifb5cdde2012-09-20 14:57:01 -07001/*
2 * Copyright (C) 2012 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License"); you
5 * may not use this file except in compliance with the License. You may
6 * 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
13 * implied. See the License for the specific language governing
14 * permissions and limitations under the License.
15 */
16
17#include <errno.h>
18#include <string.h>
19#include <stdint.h>
20
21#include <hardware/hardware.h>
22#include <hardware/keymaster.h>
23
24#include <openssl/evp.h>
25#include <openssl/bio.h>
26#include <openssl/rsa.h>
27#include <openssl/err.h>
28#include <openssl/x509.h>
29
30#include <utils/UniquePtr.h>
31#include <linux/ioctl.h>
32#include <linux/msm_ion.h>
33#include <sys/mman.h>
34
35#include <stdio.h>
36#include <stdlib.h>
37#include <stddef.h>
38#include <unistd.h>
39#include <dirent.h>
40#include <fcntl.h>
41
42#include <sys/types.h>
43#include <sys/stat.h>
44#include <dlfcn.h>
45
46#include "QSEEComAPI.h"
47#include "keymaster_qcom.h"
48
49// For debugging
50//#define LOG_NDEBUG 0
51
52#define LOG_TAG "QCOMKeyMaster"
53#include <cutils/log.h>
54struct qcom_km_ion_info_t {
55 int32_t ion_fd;
56 int32_t ifd_data_fd;
57 struct ion_handle_data ion_alloc_handle;
58 unsigned char * ion_sbuffer;
59 uint32_t sbuf_len;
60};
61
62struct qcom_keymaster_handle {
63 struct QSEECom_handle *qseecom;
64 void *libhandle;
Ajay Dudani0cd599c2013-04-22 15:10:32 -070065 int (*QSEECom_start_app)(struct QSEECom_handle ** handle, char* path,
66 char* appname, uint32_t size);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070067 int (*QSEECom_shutdown_app)(struct QSEECom_handle **handle);
68 int (*QSEECom_send_cmd)(struct QSEECom_handle* handle, void *cbuf,
69 uint32_t clen, void *rbuf, uint32_t rlen);
70 int (*QSEECom_send_modified_cmd)(struct QSEECom_handle* handle, void *cbuf,
71 uint32_t clen, void *rbuf, uint32_t rlen,
72 struct QSEECom_ion_fd_info *ihandle);
Ajay Dudanicccc0042013-06-11 11:42:15 -070073 int (*QSEECom_set_bandwidth)(struct QSEECom_handle* handle, bool high);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070074};
75typedef struct qcom_keymaster_handle qcom_keymaster_handle_t;
76
77struct EVP_PKEY_Delete {
78 void operator()(EVP_PKEY* p) const {
79 EVP_PKEY_free(p);
80 }
81};
82typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
83
84struct RSA_Delete {
85 void operator()(RSA* p) const {
86 RSA_free(p);
87 }
88};
89typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
90
91typedef UniquePtr<keymaster_device_t> Unique_keymaster_device_t;
92
93/**
94 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
95 * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
96 * without triggering a warning by not using the result of release().
97 */
98#define OWNERSHIP_TRANSFERRED(obj) \
99 typeof (obj.release()) _dummy __attribute__((unused)) = obj.release()
100
101static int qcom_km_get_keypair_public(const keymaster_device* dev,
102 const uint8_t* keyBlob, const size_t keyBlobLength,
103 uint8_t** x509_data, size_t* x509_data_length) {
104
105 struct qcom_km_key_blob * keyblob_ptr = (struct qcom_km_key_blob *)keyBlob;
106
107 if (x509_data == NULL || x509_data_length == NULL) {
108 ALOGE("Output public key buffer == NULL");
109 return -1;
110 }
111
112 if (keyBlob == NULL) {
113 ALOGE("Supplied key blob was NULL");
114 return -1;
115 }
116
117 // Should be large enough for keyblob data:
118 if (keyBlobLength < (sizeof(qcom_km_key_blob_t))) {
119 ALOGE("key blob appears to be truncated");
120 return -1;
121 }
122
123 if (keyblob_ptr->magic_num != KM_MAGIC_NUM) {
124 ALOGE("Cannot read key; it was not made by this keymaster");
125 return -1;
126 }
127
128 if (keyblob_ptr->public_exponent_size == 0 ) {
129 ALOGE("Key blob appears to have incorrect exponent length");
130 return -1;
131 }
132 if (keyblob_ptr->modulus_size == 0 ) {
133 ALOGE("Key blob appears to have incorrect modulus length");
134 return -1;
135 }
136
137 Unique_RSA rsa(RSA_new());
138 if (rsa.get() == NULL) {
139 ALOGE("Could not allocate RSA structure");
140 return -1;
141 }
142
143 rsa->n = BN_bin2bn(reinterpret_cast<const unsigned char*>(keyblob_ptr->modulus),
144 keyblob_ptr->modulus_size, NULL);
145 if (rsa->n == NULL) {
146 ALOGE("Failed to initialize modulus");
147 return -1;
148 }
149
150 rsa->e = BN_bin2bn(reinterpret_cast<const unsigned char*>(&keyblob_ptr->public_exponent),
151 keyblob_ptr->public_exponent_size, NULL);
152 if (rsa->e == NULL) {
153 ALOGE("Failed to initialize public exponent");
154 return -1;
155 }
156
157 Unique_EVP_PKEY pkey(EVP_PKEY_new());
158 if (pkey.get() == NULL) {
159 ALOGE("Could not allocate EVP_PKEY structure");
160 return -1;
161 }
162 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
163 ALOGE("Failed to assign rsa parameters \n");
164 return -1;
165 }
166 OWNERSHIP_TRANSFERRED(rsa);
167
168 int len = i2d_PUBKEY(pkey.get(), NULL);
169 if (len <= 0) {
170 ALOGE("Len returned is < 0 len = %d", len);
171 return -1;
172 }
173
174 UniquePtr<uint8_t> key(static_cast<uint8_t*>(malloc(len)));
175 if (key.get() == NULL) {
176 ALOGE("Could not allocate memory for public key data");
177 return -1;
178 }
179
180 unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get());
181 if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
182 ALOGE("Len 2 returned is < 0 len = %d", len);
183 return -1;
184 }
185 *x509_data_length = len;
186 *x509_data = key.release();
187
188 return 0;
189}
190
191static int32_t qcom_km_ION_memalloc(struct qcom_km_ion_info_t *handle,
192 uint32_t size)
193{
194 int32_t ret = 0;
195 int32_t iret = 0;
196 int32_t fd = 0;
197 unsigned char *v_addr;
198 struct ion_allocation_data ion_alloc_data;
199 int32_t ion_fd;
200 int32_t rc;
201 struct ion_fd_data ifd_data;
202 struct ion_handle_data handle_data;
203
204 /* open ION device for memory management
205 * O_DSYNC -> uncached memory
206 */
207 if(handle == NULL){
208 ALOGE("Error:: null handle received");
209 return -1;
210 }
211 ion_fd = open("/dev/ion", O_RDONLY | O_DSYNC);
212 if (ion_fd < 0) {
213 ALOGE("Error::Cannot open ION device");
214 return -1;
215 }
216 handle->ion_sbuffer = NULL;
217 handle->ifd_data_fd = 0;
218
219 /* Size of allocation */
220 ion_alloc_data.len = (size + 4095) & (~4095);
221
222 /* 4K aligned */
223 ion_alloc_data.align = 4096;
224
225 /* memory is allocated from EBI heap */
Ajay Dudani0cd599c2013-04-22 15:10:32 -0700226 ion_alloc_data.heap_mask= ION_HEAP(ION_QSECOM_HEAP_ID);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700227
228 /* Set the memory to be uncached */
Ajay Dudani0cd599c2013-04-22 15:10:32 -0700229 ion_alloc_data.flags = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700230
231 /* IOCTL call to ION for memory request */
232 rc = ioctl(ion_fd, ION_IOC_ALLOC, &ion_alloc_data);
233 if (rc) {
234 ret = -1;
235 goto alloc_fail;
236 }
237
238 if (ion_alloc_data.handle != NULL) {
239 ifd_data.handle = ion_alloc_data.handle;
240 } else {
241 ret = -1;
242 goto alloc_fail;
243 }
244 /* Call MAP ioctl to retrieve the ifd_data.fd file descriptor */
245 rc = ioctl(ion_fd, ION_IOC_MAP, &ifd_data);
246 if (rc) {
247 ret = -1;
248 goto ioctl_fail;
249 }
250
251 /* Make the ion mmap call */
252 v_addr = (unsigned char *)mmap(NULL, ion_alloc_data.len,
253 PROT_READ | PROT_WRITE,
254 MAP_SHARED, ifd_data.fd, 0);
255 if (v_addr == MAP_FAILED) {
256 ALOGE("Error::ION MMAP failed");
257 ret = -1;
258 goto map_fail;
259 }
260 handle->ion_fd = ion_fd;
261 handle->ifd_data_fd = ifd_data.fd;
262 handle->ion_sbuffer = v_addr;
263 handle->ion_alloc_handle.handle = ion_alloc_data.handle;
264 handle->sbuf_len = size;
265 return ret;
266
267map_fail:
268 if (handle->ion_sbuffer != NULL) {
269 iret = munmap(handle->ion_sbuffer, ion_alloc_data.len);
270 if (iret)
271 ALOGE("Error::Failed to unmap memory for load image. ret = %d", ret);
272 }
273
274ioctl_fail:
275 handle_data.handle = ion_alloc_data.handle;
276 if (handle->ifd_data_fd)
277 close(handle->ifd_data_fd);
278 iret = ioctl(ion_fd, ION_IOC_FREE, &handle_data);
279 if (iret) {
280 ALOGE("Error::ION FREE ioctl returned error = %d",iret);
281 }
282
283alloc_fail:
284 if (ion_fd > 0)
285 close(ion_fd);
286 return ret;
287}
288
289/** @brief: Deallocate ION memory
290 *
291 *
292 */
293static int32_t qcom_km_ion_dealloc(struct qcom_km_ion_info_t *handle)
294{
295 struct ion_handle_data handle_data;
296 int32_t ret = 0;
297
298 /* Deallocate the memory for the listener */
299 ret = munmap(handle->ion_sbuffer, (handle->sbuf_len + 4095) & (~4095));
300 if (ret) {
301 ALOGE("Error::Unmapping ION Buffer failed with ret = %d", ret);
302 }
303
304 handle_data.handle = handle->ion_alloc_handle.handle;
305 close(handle->ifd_data_fd);
306 ret = ioctl(handle->ion_fd, ION_IOC_FREE, &handle_data);
307 if (ret) {
308 ALOGE("Error::ION Memory FREE ioctl failed with ret = %d", ret);
309 }
310 close(handle->ion_fd);
311 return ret;
312}
313
314static int qcom_km_generate_keypair(const keymaster_device_t* dev,
315 const keymaster_keypair_t key_type, const void* key_params,
316 uint8_t** keyBlob, size_t* keyBlobLength) {
317
318 if (dev->context == NULL) {
319 ALOGE("qcom_km_generate_keypair: Context == NULL");
320 return -1;
321 }
322
323 if (key_type != TYPE_RSA) {
324 ALOGE("Unsupported key type %d", key_type);
325 return -1;
326 } else if (key_params == NULL) {
327 ALOGE("key_params == null");
328 return -1;
329 }
330 if (keyBlob == NULL || keyBlobLength == NULL) {
331 ALOGE("output key blob or length == NULL");
332 return -1;
333 }
334 keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params;
335
336 keymaster_gen_keypair_cmd_t *send_cmd = NULL;
337 keymaster_gen_keypair_resp_t *resp = NULL;
338 struct QSEECom_handle *handle = NULL;
339 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
340 int ret = 0;
341
342 handle = (struct QSEECom_handle *)(km_handle->qseecom);
343 send_cmd = (keymaster_gen_keypair_cmd_t *)handle->ion_sbuffer;
344 resp = (keymaster_gen_keypair_resp_t *)(handle->ion_sbuffer +
345 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)));
346 send_cmd->cmd_id = KEYMASTER_GENERATE_KEYPAIR;
347 send_cmd->key_type = key_type;
348 send_cmd->rsa_params.modulus_size = rsa_params->modulus_size;
349 send_cmd->rsa_params.public_exponent = rsa_params->public_exponent;
350 resp->status = KEYMASTER_FAILURE;
351 resp->key_blob_len = sizeof(qcom_km_key_blob_t);
352
Ajay Dudanicccc0042013-06-11 11:42:15 -0700353 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
354 if (ret < 0) {
355 ALOGE("Generate key command failed (unable to enable clks) ret =%d", ret);
356 return -1;
357 }
358
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700359 ret = (*km_handle->QSEECom_send_cmd)(handle, send_cmd,
360 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)), resp,
361 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_resp_t)));
362
Ajay Dudanicccc0042013-06-11 11:42:15 -0700363 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
364 ALOGE("Import key command: (unable to disable clks)");
365
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700366 if ( (ret < 0) || (resp->status < 0)) {
367 ALOGE("Generate key command failed resp->status = %d ret =%d", resp->status, ret);
368 return -1;
369 } else {
370 UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
371 if (keydata.get() == NULL) {
372 ALOGE("could not allocate memory for key blob");
373 return -1;
374 }
375 unsigned char* p = keydata.get();
376 memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
377 *keyBlob = keydata.release();
378 *keyBlobLength = resp->key_blob_len;
379 }
380 return 0;
381}
382
383static int qcom_km_import_keypair(const keymaster_device_t* dev,
384 const uint8_t* key, const size_t key_length,
385 uint8_t** keyBlob, size_t* keyBlobLength)
386{
387 if (dev->context == NULL) {
388 ALOGE("qcom_km_import_keypair: Context == NULL");
389 return -1;
390 }
391
392 if (key == NULL) {
393 ALOGE("Input key == NULL");
394 return -1;
395 } else if (keyBlob == NULL || keyBlobLength == NULL) {
396 ALOGE("Output key blob or length == NULL");
397 return -1;
398 }
399
400 struct QSEECom_ion_fd_info ion_fd_info;
401 struct qcom_km_ion_info_t ihandle;
402 int ret = 0;
403
404 ihandle.ion_fd = 0;
405 ihandle.ion_alloc_handle.handle = NULL;
406 if (qcom_km_ION_memalloc(&ihandle, QSEECOM_ALIGN(key_length)) < 0) {
407 ALOGE("ION allocation failed");
408 return -1;
409 }
410 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
411
412 /* Populate the send data structure */
413 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
414 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t);
415
416
417 struct QSEECom_handle *handle = NULL;
418 keymaster_import_keypair_cmd_t *send_cmd = NULL;
419 keymaster_import_keypair_resp_t *resp = NULL;
420 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
421
422 handle = (struct QSEECom_handle *)(km_handle->qseecom);
423 send_cmd = (keymaster_import_keypair_cmd_t *)handle->ion_sbuffer;
424 resp = (keymaster_import_keypair_resp_t *)(handle->ion_sbuffer +
425 QSEECOM_ALIGN(sizeof(keymaster_import_keypair_cmd_t)));
426 send_cmd->cmd_id = KEYMASTER_IMPORT_KEYPAIR;
427 send_cmd->pkcs8_key = (uint32_t)ihandle.ion_sbuffer;
428
429 memcpy((unsigned char *)ihandle.ion_sbuffer, key, key_length);
430
431 send_cmd->pkcs8_key_len = key_length;
432 resp->status = KEYMASTER_FAILURE;
433 resp->key_blob_len = sizeof(qcom_km_key_blob_t);
434
Ajay Dudanicccc0042013-06-11 11:42:15 -0700435 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
436 if (ret < 0) {
437 ALOGE("Import key command failed (unable to enable clks) ret =%d", ret);
438 qcom_km_ion_dealloc(&ihandle);
439 return -1;
440 }
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700441 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
442 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
443 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
444
Ajay Dudanicccc0042013-06-11 11:42:15 -0700445 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
446 ALOGE("Import key command: (unable to disable clks)");
447
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700448 if ( (ret < 0) || (resp->status < 0)) {
449 ALOGE("Import key command failed resp->status = %d ret =%d", resp->status, ret);
450 qcom_km_ion_dealloc(&ihandle);
451 return -1;
452 } else {
453 UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
454 if (keydata.get() == NULL) {
455 ALOGE("could not allocate memory for key blob");
456 return -1;
457 }
458 unsigned char* p = keydata.get();
459 memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
460 *keyBlob = keydata.release();
461 *keyBlobLength = resp->key_blob_len;
462
463 }
464 qcom_km_ion_dealloc(&ihandle);
465 return 0;
466}
467
468static int qcom_km_sign_data(const keymaster_device_t* dev,
469 const void* params,
470 const uint8_t* keyBlob, const size_t keyBlobLength,
471 const uint8_t* data, const size_t dataLength,
472 uint8_t** signedData, size_t* signedDataLength)
473{
474 if (dev->context == NULL) {
475 ALOGE("qcom_km_sign_data: Context == NULL");
476 return -1;
477 }
478 if (dataLength > KM_KEY_SIZE_MAX) {
479 ALOGE("Input data to be signed is too long %d bytes", dataLength);
480 return -1;
481 }
482 if (data == NULL) {
483 ALOGE("input data to sign == NULL");
484 return -1;
485 } else if (signedData == NULL || signedDataLength == NULL) {
486 ALOGE("Output signature buffer == NULL");
487 return -1;
488 }
489 keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
490 if (sign_params->digest_type != DIGEST_NONE) {
491 ALOGE("Cannot handle digest type %d", sign_params->digest_type);
492 return -1;
493 } else if (sign_params->padding_type != PADDING_NONE) {
494 ALOGE("Cannot handle padding type %d", sign_params->padding_type);
495 return -1;
496 }
497
498 struct QSEECom_handle *handle = NULL;
499 keymaster_sign_data_cmd_t *send_cmd = NULL;
500 keymaster_sign_data_resp_t *resp = NULL;
501 struct QSEECom_ion_fd_info ion_fd_info;
502 struct qcom_km_ion_info_t ihandle;
503 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
504 int ret = 0;
505
506 handle = (struct QSEECom_handle *)(km_handle->qseecom);
507 ihandle.ion_fd = 0;
508 ihandle.ion_alloc_handle.handle = NULL;
509 if (qcom_km_ION_memalloc(&ihandle, dataLength) < 0) {
510 ALOGE("ION allocation failed");
511 return -1;
512 }
513 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
514
515 /* Populate the send data structure */
516 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
517 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
518 sizeof(qcom_km_key_blob_t) + sizeof(keymaster_rsa_sign_params_t);
519
520 send_cmd = (keymaster_sign_data_cmd_t *)handle->ion_sbuffer;
521 resp = (keymaster_sign_data_resp_t *)(handle->ion_sbuffer +
522 QSEECOM_ALIGN(sizeof(keymaster_sign_data_cmd_t)));
523 send_cmd->cmd_id = KEYMASTER_SIGN_DATA ;
524 send_cmd->sign_param.digest_type = sign_params->digest_type;
525 send_cmd->sign_param.padding_type = sign_params->padding_type;
526 memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
527 memcpy((unsigned char *)ihandle.ion_sbuffer, data, dataLength);
528
529 send_cmd->data = (uint32_t)ihandle.ion_sbuffer;
530 send_cmd->dlen = dataLength;
531 resp->sig_len = KM_KEY_SIZE_MAX;
532 resp->status = KEYMASTER_FAILURE;
533
Ajay Dudanicccc0042013-06-11 11:42:15 -0700534 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
535 if (ret < 0) {
536 ALOGE("Sign data command failed (unable to enable clks) ret =%d", ret);
537 qcom_km_ion_dealloc(&ihandle);
538 return -1;
539 }
540
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700541 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
542 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
543 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
Ajay Dudanicccc0042013-06-11 11:42:15 -0700544
545 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
546 ALOGE("Sign data command: (unable to disable clks)");
547
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700548 if ( (ret < 0) || (resp->status < 0)) {
549 ALOGE("Sign data command failed resp->status = %d ret =%d", resp->status, ret);
550 qcom_km_ion_dealloc(&ihandle);
551 return -1;
552 } else {
553 UniquePtr<uint8_t> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(resp->sig_len)));
554 if (signedDataPtr.get() == NULL) {
555 ALOGE("Sign data memory allocation failed");
556 qcom_km_ion_dealloc(&ihandle);
557 return -1;
558 }
559 unsigned char* p = signedDataPtr.get();
560 memcpy(p, (unsigned char *)(&resp->signed_data), resp->sig_len);
561
562 *signedDataLength = resp->sig_len;
563 *signedData = signedDataPtr.release();
564 }
565 qcom_km_ion_dealloc(&ihandle);
566 return 0;
567}
568
569static int qcom_km_verify_data(const keymaster_device_t* dev,
570 const void* params,
571 const uint8_t* keyBlob, const size_t keyBlobLength,
572 const uint8_t* signedData, const size_t signedDataLength,
573 const uint8_t* signature, const size_t signatureLength)
574{
575 if (dev->context == NULL) {
576 ALOGE("qcom_km_verify_data: Context == NULL");
577 return -1;
578 }
579
580 if (signedData == NULL || signature == NULL) {
581 ALOGE("data or signature buffers == NULL");
582 return -1;
583 }
584
585 keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
586 if (sign_params->digest_type != DIGEST_NONE) {
587 ALOGE("Cannot handle digest type %d", sign_params->digest_type);
588 return -1;
589 } else if (sign_params->padding_type != PADDING_NONE) {
590 ALOGE("Cannot handle padding type %d", sign_params->padding_type);
591 return -1;
592 } else if (signatureLength != signedDataLength) {
593 ALOGE("signed data length must be signature length");
594 return -1;
595 }
596
597 struct QSEECom_handle *handle = NULL;
598 keymaster_verify_data_cmd_t *send_cmd = NULL;
599 keymaster_verify_data_resp_t *resp = NULL;
600
601 struct QSEECom_ion_fd_info ion_fd_info;
602 struct qcom_km_ion_info_t ihandle;
603 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
604 int ret = 0;
605
606 handle = (struct QSEECom_handle *)(km_handle->qseecom);
607 ihandle.ion_fd = 0;
608 ihandle.ion_alloc_handle.handle = NULL;
609 if (qcom_km_ION_memalloc(&ihandle, signedDataLength + signatureLength) <0) {
610 ALOGE("ION allocation failed");
611 return -1;
612 }
613 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
614
615 /* Populate the send data structure */
616 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
617 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
618 sizeof(qcom_km_key_blob_t ) + sizeof(keymaster_rsa_sign_params_t);
619
620 send_cmd = (keymaster_verify_data_cmd_t *)handle->ion_sbuffer;
621 resp = (keymaster_verify_data_resp_t *)((char *)handle->ion_sbuffer +
622 sizeof(keymaster_verify_data_cmd_t));
623 send_cmd->cmd_id = KEYMASTER_VERIFY_DATA ;
624 send_cmd->sign_param.digest_type = sign_params->digest_type;
625 send_cmd->sign_param.padding_type = sign_params->padding_type;
626 memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
627
628 send_cmd->signed_data = (uint32_t)ihandle.ion_sbuffer;
629 send_cmd->signed_dlen = signedDataLength;
630 memcpy((unsigned char *)ihandle.ion_sbuffer, signedData, signedDataLength);
631
632 send_cmd->signature = signedDataLength;
633 send_cmd->slen = signatureLength;
634 memcpy(((unsigned char *)ihandle.ion_sbuffer + signedDataLength),
635 signature, signatureLength);
636 resp->status = KEYMASTER_FAILURE;
Ajay Dudanicccc0042013-06-11 11:42:15 -0700637
638 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
639 if (ret < 0) {
640 ALOGE("Verify data command failed (unable to enable clks) ret =%d", ret);
641 qcom_km_ion_dealloc(&ihandle);
642 return -1;
643 }
644
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700645 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
646 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
647 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
648
Ajay Dudanicccc0042013-06-11 11:42:15 -0700649 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
650 ALOGE("Verify data command: (unable to disable clks)");
651
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700652 if ( (ret < 0) || (resp->status < 0)) {
653 ALOGE("Verify data command failed resp->status = %d ret =%d", resp->status, ret);
654 qcom_km_ion_dealloc(&ihandle);
655 return -1;
656 }
657 qcom_km_ion_dealloc(&ihandle);
658 return 0;
659}
660
661/* Close an opened OpenSSL instance */
662static int qcom_km_close(hw_device_t *dev)
663{
664 keymaster_device_t* km_dev = (keymaster_device_t *)dev;
665 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)km_dev->context;
666
667 if (km_handle->qseecom == NULL) {
668 ALOGE("Context == NULL");
669 return -1;
670 }
671 (*km_handle->QSEECom_shutdown_app)((struct QSEECom_handle **)&km_handle->qseecom);
672 free(km_dev->context);
673 free(dev);
674 return 0;
675}
676
677static int qcom_km_get_lib_sym(qcom_keymaster_handle_t* km_handle)
678{
679 km_handle->libhandle = dlopen("/system/lib/libQSEEComAPI.so", RTLD_NOW);
680 if ( km_handle->libhandle ) {
681 *(void **)(&km_handle->QSEECom_start_app) =
682 dlsym(km_handle->libhandle,"QSEECom_start_app");
683 if (km_handle->QSEECom_start_app == NULL) {
684 ALOGE("dlsym: Error Loading QSEECom_start_app");
685 dlclose(km_handle->libhandle );
686 km_handle->libhandle = NULL;
687 return -1;
688 }
689 *(void **)(&km_handle->QSEECom_shutdown_app) =
690 dlsym(km_handle->libhandle,"QSEECom_shutdown_app");
691 if (km_handle->QSEECom_shutdown_app == NULL) {
692 ALOGE("dlsym: Error Loading QSEECom_shutdown_app");
693 dlclose(km_handle->libhandle );
694 km_handle->libhandle = NULL;
695 return -1;
696 }
697 *(void **)(&km_handle->QSEECom_send_cmd) =
698 dlsym(km_handle->libhandle,"QSEECom_send_cmd");
699 if (km_handle->QSEECom_send_cmd == NULL) {
700 ALOGE("dlsym: Error Loading QSEECom_send_cmd");
701 dlclose(km_handle->libhandle );
702 km_handle->libhandle = NULL;
703 return -1;
704 }
705 *(void **)(&km_handle->QSEECom_send_modified_cmd) =
706 dlsym(km_handle->libhandle,"QSEECom_send_modified_cmd");
707 if (km_handle->QSEECom_send_modified_cmd == NULL) {
708 ALOGE("dlsym: Error Loading QSEECom_send_modified_cmd");
709 dlclose(km_handle->libhandle );
710 km_handle->libhandle = NULL;
711 return -1;
712 }
Ajay Dudanicccc0042013-06-11 11:42:15 -0700713 *(void **)(&km_handle->QSEECom_set_bandwidth) =
714 dlsym(km_handle->libhandle,"QSEECom_set_bandwidth");
715 if (km_handle->QSEECom_set_bandwidth == NULL) {
716 ALOGE("dlsym: Error Loading QSEECom_set_bandwidth");
717 dlclose(km_handle->libhandle );
718 km_handle->libhandle = NULL;
719 return -1;
720 }
721
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700722 } else {
723 ALOGE("failed to load qseecom library");
724 return -1;
725 }
726 return 0;
727}
728
729/*
730 * Generic device handling
731 */
732static int qcom_km_open(const hw_module_t* module, const char* name,
733 hw_device_t** device)
734{
735 int ret = 0;
736 qcom_keymaster_handle_t* km_handle;
737 if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
738 return -EINVAL;
739
740 km_handle = (qcom_keymaster_handle_t *)malloc(sizeof(qcom_keymaster_handle_t));
741 if (km_handle == NULL) {
742 ALOGE("Memalloc for keymaster handle failed");
743 return -1;
744 }
745 km_handle->qseecom = NULL;
746 km_handle->libhandle = NULL;
747 ret = qcom_km_get_lib_sym(km_handle);
748 if (ret) {
749 free(km_handle);
750 return -1;
751 }
752 Unique_keymaster_device_t dev(new keymaster_device_t);
753 if (dev.get() == NULL){
754 free(km_handle);
755 return -ENOMEM;
756 }
757 dev->context = (void *)km_handle;
758 ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
Ajay Dudani70789f22013-05-15 21:07:58 -0700759 "/vendor/firmware/keymaster", "keymaster", 4096*2);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700760 if (ret) {
761 ALOGE("Loading keymaster app failied");
762 free(km_handle);
763 return -1;
764 }
765 dev->common.tag = HARDWARE_DEVICE_TAG;
766 dev->common.version = 1;
767 dev->common.module = (struct hw_module_t*) module;
768 dev->common.close = qcom_km_close;
769 dev->flags = 0;
770
771 dev->generate_keypair = qcom_km_generate_keypair;
772 dev->import_keypair = qcom_km_import_keypair;
773 dev->get_keypair_public = qcom_km_get_keypair_public;
774 dev->delete_keypair = NULL;
775 dev->delete_all = NULL;
776 dev->sign_data = qcom_km_sign_data;
777 dev->verify_data = qcom_km_verify_data;
778
779 *device = reinterpret_cast<hw_device_t*>(dev.release());
780
781 return 0;
782}
783
784static struct hw_module_methods_t keystore_module_methods = {
785 open: qcom_km_open,
786};
787
788struct keystore_module HAL_MODULE_INFO_SYM
789__attribute__ ((visibility ("default"))) = {
790 common: {
791 tag: HARDWARE_MODULE_TAG,
792 version_major: 1,
793 version_minor: 0,
794 id: KEYSTORE_HARDWARE_MODULE_ID,
795 name: "Keymaster QCOM HAL",
796 author: "The Android Open Source Project",
797 methods: &keystore_module_methods,
798 dso: 0,
799 reserved: {},
800 },
801};