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