blob: 683b4a2a85aa2b2f48030a092ff5f4a714d4635a [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
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070030#include <linux/ioctl.h>
31#include <linux/msm_ion.h>
32#include <sys/mman.h>
33
34#include <stdio.h>
35#include <stdlib.h>
36#include <stddef.h>
37#include <unistd.h>
38#include <dirent.h>
39#include <fcntl.h>
40
41#include <sys/types.h>
42#include <sys/stat.h>
43#include <dlfcn.h>
44
Kenny Roote4b25502013-09-11 14:43:06 -070045#include <UniquePtr.h>
46
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070047#include "QSEEComAPI.h"
48#include "keymaster_qcom.h"
49
50// For debugging
51//#define LOG_NDEBUG 0
52
53#define LOG_TAG "QCOMKeyMaster"
54#include <cutils/log.h>
55struct qcom_km_ion_info_t {
56 int32_t ion_fd;
57 int32_t ifd_data_fd;
58 struct ion_handle_data ion_alloc_handle;
59 unsigned char * ion_sbuffer;
60 uint32_t sbuf_len;
61};
62
63struct qcom_keymaster_handle {
64 struct QSEECom_handle *qseecom;
65 void *libhandle;
Ajay Dudani0cd599c2013-04-22 15:10:32 -070066 int (*QSEECom_start_app)(struct QSEECom_handle ** handle, char* path,
67 char* appname, uint32_t size);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070068 int (*QSEECom_shutdown_app)(struct QSEECom_handle **handle);
69 int (*QSEECom_send_cmd)(struct QSEECom_handle* handle, void *cbuf,
70 uint32_t clen, void *rbuf, uint32_t rlen);
71 int (*QSEECom_send_modified_cmd)(struct QSEECom_handle* handle, void *cbuf,
72 uint32_t clen, void *rbuf, uint32_t rlen,
73 struct QSEECom_ion_fd_info *ihandle);
74};
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
353 ret = (*km_handle->QSEECom_send_cmd)(handle, send_cmd,
354 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)), resp,
355 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_resp_t)));
356
357 if ( (ret < 0) || (resp->status < 0)) {
358 ALOGE("Generate key command failed resp->status = %d ret =%d", resp->status, ret);
359 return -1;
360 } else {
361 UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
362 if (keydata.get() == NULL) {
363 ALOGE("could not allocate memory for key blob");
364 return -1;
365 }
366 unsigned char* p = keydata.get();
367 memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
368 *keyBlob = keydata.release();
369 *keyBlobLength = resp->key_blob_len;
370 }
371 return 0;
372}
373
374static int qcom_km_import_keypair(const keymaster_device_t* dev,
375 const uint8_t* key, const size_t key_length,
376 uint8_t** keyBlob, size_t* keyBlobLength)
377{
378 if (dev->context == NULL) {
379 ALOGE("qcom_km_import_keypair: Context == NULL");
380 return -1;
381 }
382
383 if (key == NULL) {
384 ALOGE("Input key == NULL");
385 return -1;
386 } else if (keyBlob == NULL || keyBlobLength == NULL) {
387 ALOGE("Output key blob or length == NULL");
388 return -1;
389 }
390
391 struct QSEECom_ion_fd_info ion_fd_info;
392 struct qcom_km_ion_info_t ihandle;
393 int ret = 0;
394
395 ihandle.ion_fd = 0;
396 ihandle.ion_alloc_handle.handle = NULL;
397 if (qcom_km_ION_memalloc(&ihandle, QSEECOM_ALIGN(key_length)) < 0) {
398 ALOGE("ION allocation failed");
399 return -1;
400 }
401 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
402
403 /* Populate the send data structure */
404 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
405 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t);
406
407
408 struct QSEECom_handle *handle = NULL;
409 keymaster_import_keypair_cmd_t *send_cmd = NULL;
410 keymaster_import_keypair_resp_t *resp = NULL;
411 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
412
413 handle = (struct QSEECom_handle *)(km_handle->qseecom);
414 send_cmd = (keymaster_import_keypair_cmd_t *)handle->ion_sbuffer;
415 resp = (keymaster_import_keypair_resp_t *)(handle->ion_sbuffer +
416 QSEECOM_ALIGN(sizeof(keymaster_import_keypair_cmd_t)));
417 send_cmd->cmd_id = KEYMASTER_IMPORT_KEYPAIR;
418 send_cmd->pkcs8_key = (uint32_t)ihandle.ion_sbuffer;
419
420 memcpy((unsigned char *)ihandle.ion_sbuffer, key, key_length);
421
422 send_cmd->pkcs8_key_len = key_length;
423 resp->status = KEYMASTER_FAILURE;
424 resp->key_blob_len = sizeof(qcom_km_key_blob_t);
425
426 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
427 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
428 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
429
430 if ( (ret < 0) || (resp->status < 0)) {
431 ALOGE("Import key command failed resp->status = %d ret =%d", resp->status, ret);
432 qcom_km_ion_dealloc(&ihandle);
433 return -1;
434 } else {
435 UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
436 if (keydata.get() == NULL) {
437 ALOGE("could not allocate memory for key blob");
438 return -1;
439 }
440 unsigned char* p = keydata.get();
441 memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
442 *keyBlob = keydata.release();
443 *keyBlobLength = resp->key_blob_len;
444
445 }
446 qcom_km_ion_dealloc(&ihandle);
447 return 0;
448}
449
450static int qcom_km_sign_data(const keymaster_device_t* dev,
451 const void* params,
452 const uint8_t* keyBlob, const size_t keyBlobLength,
453 const uint8_t* data, const size_t dataLength,
454 uint8_t** signedData, size_t* signedDataLength)
455{
456 if (dev->context == NULL) {
457 ALOGE("qcom_km_sign_data: Context == NULL");
458 return -1;
459 }
460 if (dataLength > KM_KEY_SIZE_MAX) {
461 ALOGE("Input data to be signed is too long %d bytes", dataLength);
462 return -1;
463 }
464 if (data == NULL) {
465 ALOGE("input data to sign == NULL");
466 return -1;
467 } else if (signedData == NULL || signedDataLength == NULL) {
468 ALOGE("Output signature buffer == NULL");
469 return -1;
470 }
471 keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
472 if (sign_params->digest_type != DIGEST_NONE) {
473 ALOGE("Cannot handle digest type %d", sign_params->digest_type);
474 return -1;
475 } else if (sign_params->padding_type != PADDING_NONE) {
476 ALOGE("Cannot handle padding type %d", sign_params->padding_type);
477 return -1;
478 }
479
480 struct QSEECom_handle *handle = NULL;
481 keymaster_sign_data_cmd_t *send_cmd = NULL;
482 keymaster_sign_data_resp_t *resp = NULL;
483 struct QSEECom_ion_fd_info ion_fd_info;
484 struct qcom_km_ion_info_t ihandle;
485 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
486 int ret = 0;
487
488 handle = (struct QSEECom_handle *)(km_handle->qseecom);
489 ihandle.ion_fd = 0;
490 ihandle.ion_alloc_handle.handle = NULL;
491 if (qcom_km_ION_memalloc(&ihandle, dataLength) < 0) {
492 ALOGE("ION allocation failed");
493 return -1;
494 }
495 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
496
497 /* Populate the send data structure */
498 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
499 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
500 sizeof(qcom_km_key_blob_t) + sizeof(keymaster_rsa_sign_params_t);
501
502 send_cmd = (keymaster_sign_data_cmd_t *)handle->ion_sbuffer;
503 resp = (keymaster_sign_data_resp_t *)(handle->ion_sbuffer +
504 QSEECOM_ALIGN(sizeof(keymaster_sign_data_cmd_t)));
505 send_cmd->cmd_id = KEYMASTER_SIGN_DATA ;
506 send_cmd->sign_param.digest_type = sign_params->digest_type;
507 send_cmd->sign_param.padding_type = sign_params->padding_type;
508 memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
509 memcpy((unsigned char *)ihandle.ion_sbuffer, data, dataLength);
510
511 send_cmd->data = (uint32_t)ihandle.ion_sbuffer;
512 send_cmd->dlen = dataLength;
513 resp->sig_len = KM_KEY_SIZE_MAX;
514 resp->status = KEYMASTER_FAILURE;
515
516 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
517 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
518 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
519 if ( (ret < 0) || (resp->status < 0)) {
520 ALOGE("Sign data command failed resp->status = %d ret =%d", resp->status, ret);
521 qcom_km_ion_dealloc(&ihandle);
522 return -1;
523 } else {
524 UniquePtr<uint8_t> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(resp->sig_len)));
525 if (signedDataPtr.get() == NULL) {
526 ALOGE("Sign data memory allocation failed");
527 qcom_km_ion_dealloc(&ihandle);
528 return -1;
529 }
530 unsigned char* p = signedDataPtr.get();
531 memcpy(p, (unsigned char *)(&resp->signed_data), resp->sig_len);
532
533 *signedDataLength = resp->sig_len;
534 *signedData = signedDataPtr.release();
535 }
536 qcom_km_ion_dealloc(&ihandle);
537 return 0;
538}
539
540static int qcom_km_verify_data(const keymaster_device_t* dev,
541 const void* params,
542 const uint8_t* keyBlob, const size_t keyBlobLength,
543 const uint8_t* signedData, const size_t signedDataLength,
544 const uint8_t* signature, const size_t signatureLength)
545{
546 if (dev->context == NULL) {
547 ALOGE("qcom_km_verify_data: Context == NULL");
548 return -1;
549 }
550
551 if (signedData == NULL || signature == NULL) {
552 ALOGE("data or signature buffers == NULL");
553 return -1;
554 }
555
556 keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
557 if (sign_params->digest_type != DIGEST_NONE) {
558 ALOGE("Cannot handle digest type %d", sign_params->digest_type);
559 return -1;
560 } else if (sign_params->padding_type != PADDING_NONE) {
561 ALOGE("Cannot handle padding type %d", sign_params->padding_type);
562 return -1;
563 } else if (signatureLength != signedDataLength) {
564 ALOGE("signed data length must be signature length");
565 return -1;
566 }
567
568 struct QSEECom_handle *handle = NULL;
569 keymaster_verify_data_cmd_t *send_cmd = NULL;
570 keymaster_verify_data_resp_t *resp = NULL;
571
572 struct QSEECom_ion_fd_info ion_fd_info;
573 struct qcom_km_ion_info_t ihandle;
574 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
575 int ret = 0;
576
577 handle = (struct QSEECom_handle *)(km_handle->qseecom);
578 ihandle.ion_fd = 0;
579 ihandle.ion_alloc_handle.handle = NULL;
580 if (qcom_km_ION_memalloc(&ihandle, signedDataLength + signatureLength) <0) {
581 ALOGE("ION allocation failed");
582 return -1;
583 }
584 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
585
586 /* Populate the send data structure */
587 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
588 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
589 sizeof(qcom_km_key_blob_t ) + sizeof(keymaster_rsa_sign_params_t);
590
591 send_cmd = (keymaster_verify_data_cmd_t *)handle->ion_sbuffer;
592 resp = (keymaster_verify_data_resp_t *)((char *)handle->ion_sbuffer +
593 sizeof(keymaster_verify_data_cmd_t));
594 send_cmd->cmd_id = KEYMASTER_VERIFY_DATA ;
595 send_cmd->sign_param.digest_type = sign_params->digest_type;
596 send_cmd->sign_param.padding_type = sign_params->padding_type;
597 memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
598
599 send_cmd->signed_data = (uint32_t)ihandle.ion_sbuffer;
600 send_cmd->signed_dlen = signedDataLength;
601 memcpy((unsigned char *)ihandle.ion_sbuffer, signedData, signedDataLength);
602
603 send_cmd->signature = signedDataLength;
604 send_cmd->slen = signatureLength;
605 memcpy(((unsigned char *)ihandle.ion_sbuffer + signedDataLength),
606 signature, signatureLength);
607 resp->status = KEYMASTER_FAILURE;
608 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
609 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
610 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
611
612 if ( (ret < 0) || (resp->status < 0)) {
613 ALOGE("Verify data command failed resp->status = %d ret =%d", resp->status, ret);
614 qcom_km_ion_dealloc(&ihandle);
615 return -1;
616 }
617 qcom_km_ion_dealloc(&ihandle);
618 return 0;
619}
620
621/* Close an opened OpenSSL instance */
622static int qcom_km_close(hw_device_t *dev)
623{
624 keymaster_device_t* km_dev = (keymaster_device_t *)dev;
625 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)km_dev->context;
626
627 if (km_handle->qseecom == NULL) {
628 ALOGE("Context == NULL");
629 return -1;
630 }
631 (*km_handle->QSEECom_shutdown_app)((struct QSEECom_handle **)&km_handle->qseecom);
632 free(km_dev->context);
633 free(dev);
634 return 0;
635}
636
637static int qcom_km_get_lib_sym(qcom_keymaster_handle_t* km_handle)
638{
639 km_handle->libhandle = dlopen("/system/lib/libQSEEComAPI.so", RTLD_NOW);
640 if ( km_handle->libhandle ) {
641 *(void **)(&km_handle->QSEECom_start_app) =
642 dlsym(km_handle->libhandle,"QSEECom_start_app");
643 if (km_handle->QSEECom_start_app == NULL) {
644 ALOGE("dlsym: Error Loading QSEECom_start_app");
645 dlclose(km_handle->libhandle );
646 km_handle->libhandle = NULL;
647 return -1;
648 }
649 *(void **)(&km_handle->QSEECom_shutdown_app) =
650 dlsym(km_handle->libhandle,"QSEECom_shutdown_app");
651 if (km_handle->QSEECom_shutdown_app == NULL) {
652 ALOGE("dlsym: Error Loading QSEECom_shutdown_app");
653 dlclose(km_handle->libhandle );
654 km_handle->libhandle = NULL;
655 return -1;
656 }
657 *(void **)(&km_handle->QSEECom_send_cmd) =
658 dlsym(km_handle->libhandle,"QSEECom_send_cmd");
659 if (km_handle->QSEECom_send_cmd == NULL) {
660 ALOGE("dlsym: Error Loading QSEECom_send_cmd");
661 dlclose(km_handle->libhandle );
662 km_handle->libhandle = NULL;
663 return -1;
664 }
665 *(void **)(&km_handle->QSEECom_send_modified_cmd) =
666 dlsym(km_handle->libhandle,"QSEECom_send_modified_cmd");
667 if (km_handle->QSEECom_send_modified_cmd == NULL) {
668 ALOGE("dlsym: Error Loading QSEECom_send_modified_cmd");
669 dlclose(km_handle->libhandle );
670 km_handle->libhandle = NULL;
671 return -1;
672 }
673 } else {
674 ALOGE("failed to load qseecom library");
675 return -1;
676 }
677 return 0;
678}
679
680/*
681 * Generic device handling
682 */
683static int qcom_km_open(const hw_module_t* module, const char* name,
684 hw_device_t** device)
685{
686 int ret = 0;
687 qcom_keymaster_handle_t* km_handle;
688 if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
689 return -EINVAL;
690
691 km_handle = (qcom_keymaster_handle_t *)malloc(sizeof(qcom_keymaster_handle_t));
692 if (km_handle == NULL) {
693 ALOGE("Memalloc for keymaster handle failed");
694 return -1;
695 }
696 km_handle->qseecom = NULL;
697 km_handle->libhandle = NULL;
698 ret = qcom_km_get_lib_sym(km_handle);
699 if (ret) {
700 free(km_handle);
701 return -1;
702 }
703 Unique_keymaster_device_t dev(new keymaster_device_t);
704 if (dev.get() == NULL){
705 free(km_handle);
706 return -ENOMEM;
707 }
708 dev->context = (void *)km_handle;
709 ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
Ajay Dudani70789f22013-05-15 21:07:58 -0700710 "/vendor/firmware/keymaster", "keymaster", 4096*2);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700711 if (ret) {
712 ALOGE("Loading keymaster app failied");
713 free(km_handle);
714 return -1;
715 }
716 dev->common.tag = HARDWARE_DEVICE_TAG;
717 dev->common.version = 1;
718 dev->common.module = (struct hw_module_t*) module;
719 dev->common.close = qcom_km_close;
720 dev->flags = 0;
721
722 dev->generate_keypair = qcom_km_generate_keypair;
723 dev->import_keypair = qcom_km_import_keypair;
724 dev->get_keypair_public = qcom_km_get_keypair_public;
725 dev->delete_keypair = NULL;
726 dev->delete_all = NULL;
727 dev->sign_data = qcom_km_sign_data;
728 dev->verify_data = qcom_km_verify_data;
729
730 *device = reinterpret_cast<hw_device_t*>(dev.release());
731
732 return 0;
733}
734
735static struct hw_module_methods_t keystore_module_methods = {
736 open: qcom_km_open,
737};
738
739struct keystore_module HAL_MODULE_INFO_SYM
740__attribute__ ((visibility ("default"))) = {
741 common: {
742 tag: HARDWARE_MODULE_TAG,
743 version_major: 1,
744 version_minor: 0,
745 id: KEYSTORE_HARDWARE_MODULE_ID,
746 name: "Keymaster QCOM HAL",
747 author: "The Android Open Source Project",
748 methods: &keystore_module_methods,
749 dso: 0,
750 reserved: {},
751 },
752};