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