blob: 42417ab03607f0ddae951f186ca7807c7a338db8 [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>
Brahmaji Ka0bf5a72015-09-02 20:45:10 +053022#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>
Jyoti Wadhwani79fc6602015-01-14 15:59:33 -080046#include <cutils/properties.h>
Kenny Roote4b25502013-09-11 14:43:06 -070047
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070048#include "QSEEComAPI.h"
49#include "keymaster_qcom.h"
50
51// For debugging
52//#define LOG_NDEBUG 0
53
54#define LOG_TAG "QCOMKeyMaster"
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -070055#define UNUSED(x) (void)(x)
56#define KM_SB_LENGTH (4096 * 2)
Jyoti Wadhwani79fc6602015-01-14 15:59:33 -080057#define MAX_PROPERTY_GET_ATTEMPTS 60
58#define PROPERTY_GET_SLEEP_INTERVAL 1
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -070059
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070060#include <cutils/log.h>
61struct qcom_km_ion_info_t {
62 int32_t ion_fd;
63 int32_t ifd_data_fd;
64 struct ion_handle_data ion_alloc_handle;
65 unsigned char * ion_sbuffer;
66 uint32_t sbuf_len;
67};
68
69struct qcom_keymaster_handle {
70 struct QSEECom_handle *qseecom;
71 void *libhandle;
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -070072 int (*QSEECom_start_app)(struct QSEECom_handle ** handle, const char* path,
73 const char* appname, uint32_t size);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070074 int (*QSEECom_shutdown_app)(struct QSEECom_handle **handle);
75 int (*QSEECom_send_cmd)(struct QSEECom_handle* handle, void *cbuf,
76 uint32_t clen, void *rbuf, uint32_t rlen);
77 int (*QSEECom_send_modified_cmd)(struct QSEECom_handle* handle, void *cbuf,
78 uint32_t clen, void *rbuf, uint32_t rlen,
79 struct QSEECom_ion_fd_info *ihandle);
Ajay Dudanicccc0042013-06-11 11:42:15 -070080 int (*QSEECom_set_bandwidth)(struct QSEECom_handle* handle, bool high);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070081};
82typedef struct qcom_keymaster_handle qcom_keymaster_handle_t;
83
84struct EVP_PKEY_Delete {
85 void operator()(EVP_PKEY* p) const {
86 EVP_PKEY_free(p);
87 }
88};
89typedef UniquePtr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
90
91struct RSA_Delete {
92 void operator()(RSA* p) const {
93 RSA_free(p);
94 }
95};
96typedef UniquePtr<RSA, RSA_Delete> Unique_RSA;
97
Brahmaji Ka0bf5a72015-09-02 20:45:10 +053098typedef UniquePtr<keymaster0_device_t> Unique_keymaster_device_t;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070099
100/**
101 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
102 * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
103 * without triggering a warning by not using the result of release().
104 */
105#define OWNERSHIP_TRANSFERRED(obj) \
106 typeof (obj.release()) _dummy __attribute__((unused)) = obj.release()
107
Brahmaji Ka0bf5a72015-09-02 20:45:10 +0530108static int qcom_km_get_keypair_public(const keymaster0_device* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700109 const uint8_t* keyBlob, const size_t keyBlobLength,
110 uint8_t** x509_data, size_t* x509_data_length) {
111
112 struct qcom_km_key_blob * keyblob_ptr = (struct qcom_km_key_blob *)keyBlob;
113
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700114 UNUSED(dev);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700115 if (x509_data == NULL || x509_data_length == NULL) {
116 ALOGE("Output public key buffer == NULL");
117 return -1;
118 }
119
120 if (keyBlob == NULL) {
121 ALOGE("Supplied key blob was NULL");
122 return -1;
123 }
124
125 // Should be large enough for keyblob data:
126 if (keyBlobLength < (sizeof(qcom_km_key_blob_t))) {
127 ALOGE("key blob appears to be truncated");
128 return -1;
129 }
130
131 if (keyblob_ptr->magic_num != KM_MAGIC_NUM) {
132 ALOGE("Cannot read key; it was not made by this keymaster");
133 return -1;
134 }
135
136 if (keyblob_ptr->public_exponent_size == 0 ) {
137 ALOGE("Key blob appears to have incorrect exponent length");
138 return -1;
139 }
140 if (keyblob_ptr->modulus_size == 0 ) {
141 ALOGE("Key blob appears to have incorrect modulus length");
142 return -1;
143 }
144
145 Unique_RSA rsa(RSA_new());
146 if (rsa.get() == NULL) {
147 ALOGE("Could not allocate RSA structure");
148 return -1;
149 }
150
151 rsa->n = BN_bin2bn(reinterpret_cast<const unsigned char*>(keyblob_ptr->modulus),
152 keyblob_ptr->modulus_size, NULL);
153 if (rsa->n == NULL) {
154 ALOGE("Failed to initialize modulus");
155 return -1;
156 }
157
158 rsa->e = BN_bin2bn(reinterpret_cast<const unsigned char*>(&keyblob_ptr->public_exponent),
159 keyblob_ptr->public_exponent_size, NULL);
160 if (rsa->e == NULL) {
161 ALOGE("Failed to initialize public exponent");
162 return -1;
163 }
164
165 Unique_EVP_PKEY pkey(EVP_PKEY_new());
166 if (pkey.get() == NULL) {
167 ALOGE("Could not allocate EVP_PKEY structure");
168 return -1;
169 }
170 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
171 ALOGE("Failed to assign rsa parameters \n");
172 return -1;
173 }
174 OWNERSHIP_TRANSFERRED(rsa);
175
176 int len = i2d_PUBKEY(pkey.get(), NULL);
177 if (len <= 0) {
178 ALOGE("Len returned is < 0 len = %d", len);
179 return -1;
180 }
181
182 UniquePtr<uint8_t> key(static_cast<uint8_t*>(malloc(len)));
183 if (key.get() == NULL) {
184 ALOGE("Could not allocate memory for public key data");
185 return -1;
186 }
187
188 unsigned char* tmp = reinterpret_cast<unsigned char*>(key.get());
189 if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
190 ALOGE("Len 2 returned is < 0 len = %d", len);
191 return -1;
192 }
193 *x509_data_length = len;
194 *x509_data = key.release();
195
196 return 0;
197}
198
199static int32_t qcom_km_ION_memalloc(struct qcom_km_ion_info_t *handle,
200 uint32_t size)
201{
202 int32_t ret = 0;
203 int32_t iret = 0;
204 int32_t fd = 0;
205 unsigned char *v_addr;
206 struct ion_allocation_data ion_alloc_data;
207 int32_t ion_fd;
208 int32_t rc;
209 struct ion_fd_data ifd_data;
210 struct ion_handle_data handle_data;
211
212 /* open ION device for memory management
213 * O_DSYNC -> uncached memory
214 */
215 if(handle == NULL){
216 ALOGE("Error:: null handle received");
217 return -1;
218 }
219 ion_fd = open("/dev/ion", O_RDONLY | O_DSYNC);
220 if (ion_fd < 0) {
221 ALOGE("Error::Cannot open ION device");
222 return -1;
223 }
224 handle->ion_sbuffer = NULL;
225 handle->ifd_data_fd = 0;
226
227 /* Size of allocation */
228 ion_alloc_data.len = (size + 4095) & (~4095);
229
230 /* 4K aligned */
231 ion_alloc_data.align = 4096;
232
233 /* memory is allocated from EBI heap */
Naveen Ramarajdf89f272014-06-03 11:28:00 -0700234 ion_alloc_data.ION_HEAP_MASK = ION_HEAP(ION_QSECOM_HEAP_ID);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700235
236 /* Set the memory to be uncached */
Ajay Dudani0cd599c2013-04-22 15:10:32 -0700237 ion_alloc_data.flags = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700238
239 /* IOCTL call to ION for memory request */
240 rc = ioctl(ion_fd, ION_IOC_ALLOC, &ion_alloc_data);
241 if (rc) {
242 ret = -1;
243 goto alloc_fail;
244 }
245
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700246 if (ion_alloc_data.handle) {
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700247 ifd_data.handle = ion_alloc_data.handle;
248 } else {
249 ret = -1;
250 goto alloc_fail;
251 }
252 /* Call MAP ioctl to retrieve the ifd_data.fd file descriptor */
253 rc = ioctl(ion_fd, ION_IOC_MAP, &ifd_data);
254 if (rc) {
255 ret = -1;
256 goto ioctl_fail;
257 }
258
259 /* Make the ion mmap call */
260 v_addr = (unsigned char *)mmap(NULL, ion_alloc_data.len,
261 PROT_READ | PROT_WRITE,
262 MAP_SHARED, ifd_data.fd, 0);
263 if (v_addr == MAP_FAILED) {
264 ALOGE("Error::ION MMAP failed");
265 ret = -1;
266 goto map_fail;
267 }
268 handle->ion_fd = ion_fd;
269 handle->ifd_data_fd = ifd_data.fd;
270 handle->ion_sbuffer = v_addr;
271 handle->ion_alloc_handle.handle = ion_alloc_data.handle;
272 handle->sbuf_len = size;
273 return ret;
274
275map_fail:
276 if (handle->ion_sbuffer != NULL) {
277 iret = munmap(handle->ion_sbuffer, ion_alloc_data.len);
278 if (iret)
279 ALOGE("Error::Failed to unmap memory for load image. ret = %d", ret);
280 }
281
282ioctl_fail:
283 handle_data.handle = ion_alloc_data.handle;
284 if (handle->ifd_data_fd)
285 close(handle->ifd_data_fd);
286 iret = ioctl(ion_fd, ION_IOC_FREE, &handle_data);
287 if (iret) {
288 ALOGE("Error::ION FREE ioctl returned error = %d",iret);
289 }
290
291alloc_fail:
292 if (ion_fd > 0)
293 close(ion_fd);
294 return ret;
295}
296
297/** @brief: Deallocate ION memory
298 *
299 *
300 */
301static int32_t qcom_km_ion_dealloc(struct qcom_km_ion_info_t *handle)
302{
303 struct ion_handle_data handle_data;
304 int32_t ret = 0;
305
306 /* Deallocate the memory for the listener */
307 ret = munmap(handle->ion_sbuffer, (handle->sbuf_len + 4095) & (~4095));
308 if (ret) {
309 ALOGE("Error::Unmapping ION Buffer failed with ret = %d", ret);
310 }
311
312 handle_data.handle = handle->ion_alloc_handle.handle;
313 close(handle->ifd_data_fd);
314 ret = ioctl(handle->ion_fd, ION_IOC_FREE, &handle_data);
315 if (ret) {
316 ALOGE("Error::ION Memory FREE ioctl failed with ret = %d", ret);
317 }
318 close(handle->ion_fd);
319 return ret;
320}
321
Brahmaji Ka0bf5a72015-09-02 20:45:10 +0530322static int qcom_km_generate_keypair(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700323 const keymaster_keypair_t key_type, const void* key_params,
324 uint8_t** keyBlob, size_t* keyBlobLength) {
325
326 if (dev->context == NULL) {
327 ALOGE("qcom_km_generate_keypair: Context == NULL");
328 return -1;
329 }
330
331 if (key_type != TYPE_RSA) {
332 ALOGE("Unsupported key type %d", key_type);
333 return -1;
334 } else if (key_params == NULL) {
335 ALOGE("key_params == null");
336 return -1;
337 }
338 if (keyBlob == NULL || keyBlobLength == NULL) {
339 ALOGE("output key blob or length == NULL");
340 return -1;
341 }
342 keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params;
343
344 keymaster_gen_keypair_cmd_t *send_cmd = NULL;
345 keymaster_gen_keypair_resp_t *resp = NULL;
346 struct QSEECom_handle *handle = NULL;
347 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
348 int ret = 0;
349
350 handle = (struct QSEECom_handle *)(km_handle->qseecom);
351 send_cmd = (keymaster_gen_keypair_cmd_t *)handle->ion_sbuffer;
352 resp = (keymaster_gen_keypair_resp_t *)(handle->ion_sbuffer +
353 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)));
354 send_cmd->cmd_id = KEYMASTER_GENERATE_KEYPAIR;
355 send_cmd->key_type = key_type;
356 send_cmd->rsa_params.modulus_size = rsa_params->modulus_size;
357 send_cmd->rsa_params.public_exponent = rsa_params->public_exponent;
358 resp->status = KEYMASTER_FAILURE;
359 resp->key_blob_len = sizeof(qcom_km_key_blob_t);
360
Ajay Dudanicccc0042013-06-11 11:42:15 -0700361 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
362 if (ret < 0) {
363 ALOGE("Generate key command failed (unable to enable clks) ret =%d", ret);
364 return -1;
365 }
366
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700367 ret = (*km_handle->QSEECom_send_cmd)(handle, send_cmd,
368 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)), resp,
369 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_resp_t)));
370
Ajay Dudanicccc0042013-06-11 11:42:15 -0700371 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
372 ALOGE("Import key command: (unable to disable clks)");
373
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700374 if ( (ret < 0) || (resp->status < 0)) {
375 ALOGE("Generate key command failed resp->status = %d ret =%d", resp->status, ret);
376 return -1;
377 } else {
378 UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
379 if (keydata.get() == NULL) {
380 ALOGE("could not allocate memory for key blob");
381 return -1;
382 }
383 unsigned char* p = keydata.get();
384 memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
385 *keyBlob = keydata.release();
386 *keyBlobLength = resp->key_blob_len;
387 }
388 return 0;
389}
390
Brahmaji Ka0bf5a72015-09-02 20:45:10 +0530391static int qcom_km_import_keypair(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700392 const uint8_t* key, const size_t key_length,
393 uint8_t** keyBlob, size_t* keyBlobLength)
394{
395 if (dev->context == NULL) {
396 ALOGE("qcom_km_import_keypair: Context == NULL");
397 return -1;
398 }
399
400 if (key == NULL) {
401 ALOGE("Input key == NULL");
402 return -1;
403 } else if (keyBlob == NULL || keyBlobLength == NULL) {
404 ALOGE("Output key blob or length == NULL");
405 return -1;
406 }
407
408 struct QSEECom_ion_fd_info ion_fd_info;
409 struct qcom_km_ion_info_t ihandle;
410 int ret = 0;
411
412 ihandle.ion_fd = 0;
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700413 ihandle.ion_alloc_handle.handle = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700414 if (qcom_km_ION_memalloc(&ihandle, QSEECOM_ALIGN(key_length)) < 0) {
415 ALOGE("ION allocation failed");
416 return -1;
417 }
418 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
419
420 /* Populate the send data structure */
421 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
422 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t);
423
424
425 struct QSEECom_handle *handle = NULL;
426 keymaster_import_keypair_cmd_t *send_cmd = NULL;
427 keymaster_import_keypair_resp_t *resp = NULL;
428 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
429
430 handle = (struct QSEECom_handle *)(km_handle->qseecom);
431 send_cmd = (keymaster_import_keypair_cmd_t *)handle->ion_sbuffer;
432 resp = (keymaster_import_keypair_resp_t *)(handle->ion_sbuffer +
433 QSEECOM_ALIGN(sizeof(keymaster_import_keypair_cmd_t)));
434 send_cmd->cmd_id = KEYMASTER_IMPORT_KEYPAIR;
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700435 send_cmd->pkcs8_key = (uint32_t)(uintptr_t)ihandle.ion_sbuffer;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700436
437 memcpy((unsigned char *)ihandle.ion_sbuffer, key, key_length);
438
439 send_cmd->pkcs8_key_len = key_length;
440 resp->status = KEYMASTER_FAILURE;
441 resp->key_blob_len = sizeof(qcom_km_key_blob_t);
442
Ajay Dudanicccc0042013-06-11 11:42:15 -0700443 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
444 if (ret < 0) {
445 ALOGE("Import key command failed (unable to enable clks) ret =%d", ret);
446 qcom_km_ion_dealloc(&ihandle);
447 return -1;
448 }
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700449 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
450 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
451 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
452
Ajay Dudanicccc0042013-06-11 11:42:15 -0700453 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
454 ALOGE("Import key command: (unable to disable clks)");
455
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700456 if ( (ret < 0) || (resp->status < 0)) {
457 ALOGE("Import key command failed resp->status = %d ret =%d", resp->status, ret);
458 qcom_km_ion_dealloc(&ihandle);
459 return -1;
460 } else {
461 UniquePtr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
462 if (keydata.get() == NULL) {
463 ALOGE("could not allocate memory for key blob");
464 return -1;
465 }
466 unsigned char* p = keydata.get();
467 memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
468 *keyBlob = keydata.release();
469 *keyBlobLength = resp->key_blob_len;
470
471 }
472 qcom_km_ion_dealloc(&ihandle);
473 return 0;
474}
475
Brahmaji Ka0bf5a72015-09-02 20:45:10 +0530476static int qcom_km_sign_data(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700477 const void* params,
478 const uint8_t* keyBlob, const size_t keyBlobLength,
479 const uint8_t* data, const size_t dataLength,
480 uint8_t** signedData, size_t* signedDataLength)
481{
482 if (dev->context == NULL) {
483 ALOGE("qcom_km_sign_data: Context == NULL");
484 return -1;
485 }
486 if (dataLength > KM_KEY_SIZE_MAX) {
487 ALOGE("Input data to be signed is too long %d bytes", dataLength);
488 return -1;
489 }
490 if (data == NULL) {
491 ALOGE("input data to sign == NULL");
492 return -1;
493 } else if (signedData == NULL || signedDataLength == NULL) {
494 ALOGE("Output signature buffer == NULL");
495 return -1;
496 }
497 keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
498 if (sign_params->digest_type != DIGEST_NONE) {
499 ALOGE("Cannot handle digest type %d", sign_params->digest_type);
500 return -1;
501 } else if (sign_params->padding_type != PADDING_NONE) {
502 ALOGE("Cannot handle padding type %d", sign_params->padding_type);
503 return -1;
504 }
505
506 struct QSEECom_handle *handle = NULL;
507 keymaster_sign_data_cmd_t *send_cmd = NULL;
508 keymaster_sign_data_resp_t *resp = NULL;
509 struct QSEECom_ion_fd_info ion_fd_info;
510 struct qcom_km_ion_info_t ihandle;
511 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
512 int ret = 0;
513
514 handle = (struct QSEECom_handle *)(km_handle->qseecom);
515 ihandle.ion_fd = 0;
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700516 ihandle.ion_alloc_handle.handle = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700517 if (qcom_km_ION_memalloc(&ihandle, dataLength) < 0) {
518 ALOGE("ION allocation failed");
519 return -1;
520 }
521 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
522
523 /* Populate the send data structure */
524 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
525 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
526 sizeof(qcom_km_key_blob_t) + sizeof(keymaster_rsa_sign_params_t);
527
528 send_cmd = (keymaster_sign_data_cmd_t *)handle->ion_sbuffer;
529 resp = (keymaster_sign_data_resp_t *)(handle->ion_sbuffer +
530 QSEECOM_ALIGN(sizeof(keymaster_sign_data_cmd_t)));
531 send_cmd->cmd_id = KEYMASTER_SIGN_DATA ;
532 send_cmd->sign_param.digest_type = sign_params->digest_type;
533 send_cmd->sign_param.padding_type = sign_params->padding_type;
534 memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
535 memcpy((unsigned char *)ihandle.ion_sbuffer, data, dataLength);
536
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700537 send_cmd->data = (uint32_t)(uintptr_t)ihandle.ion_sbuffer;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700538 send_cmd->dlen = dataLength;
539 resp->sig_len = KM_KEY_SIZE_MAX;
540 resp->status = KEYMASTER_FAILURE;
541
Ajay Dudanicccc0042013-06-11 11:42:15 -0700542 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
543 if (ret < 0) {
544 ALOGE("Sign data command failed (unable to enable clks) ret =%d", ret);
545 qcom_km_ion_dealloc(&ihandle);
546 return -1;
547 }
548
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700549 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
550 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
551 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
Ajay Dudanicccc0042013-06-11 11:42:15 -0700552
553 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
554 ALOGE("Sign data command: (unable to disable clks)");
555
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700556 if ( (ret < 0) || (resp->status < 0)) {
557 ALOGE("Sign data command failed resp->status = %d ret =%d", resp->status, ret);
558 qcom_km_ion_dealloc(&ihandle);
559 return -1;
560 } else {
561 UniquePtr<uint8_t> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(resp->sig_len)));
562 if (signedDataPtr.get() == NULL) {
563 ALOGE("Sign data memory allocation failed");
564 qcom_km_ion_dealloc(&ihandle);
565 return -1;
566 }
567 unsigned char* p = signedDataPtr.get();
568 memcpy(p, (unsigned char *)(&resp->signed_data), resp->sig_len);
569
570 *signedDataLength = resp->sig_len;
571 *signedData = signedDataPtr.release();
572 }
573 qcom_km_ion_dealloc(&ihandle);
574 return 0;
575}
576
Brahmaji Ka0bf5a72015-09-02 20:45:10 +0530577static int qcom_km_verify_data(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700578 const void* params,
579 const uint8_t* keyBlob, const size_t keyBlobLength,
580 const uint8_t* signedData, const size_t signedDataLength,
581 const uint8_t* signature, const size_t signatureLength)
582{
583 if (dev->context == NULL) {
584 ALOGE("qcom_km_verify_data: Context == NULL");
585 return -1;
586 }
587
588 if (signedData == NULL || signature == NULL) {
589 ALOGE("data or signature buffers == NULL");
590 return -1;
591 }
592
593 keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
594 if (sign_params->digest_type != DIGEST_NONE) {
595 ALOGE("Cannot handle digest type %d", sign_params->digest_type);
596 return -1;
597 } else if (sign_params->padding_type != PADDING_NONE) {
598 ALOGE("Cannot handle padding type %d", sign_params->padding_type);
599 return -1;
600 } else if (signatureLength != signedDataLength) {
601 ALOGE("signed data length must be signature length");
602 return -1;
603 }
604
605 struct QSEECom_handle *handle = NULL;
606 keymaster_verify_data_cmd_t *send_cmd = NULL;
607 keymaster_verify_data_resp_t *resp = NULL;
608
609 struct QSEECom_ion_fd_info ion_fd_info;
610 struct qcom_km_ion_info_t ihandle;
611 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
612 int ret = 0;
613
614 handle = (struct QSEECom_handle *)(km_handle->qseecom);
615 ihandle.ion_fd = 0;
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700616 ihandle.ion_alloc_handle.handle = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700617 if (qcom_km_ION_memalloc(&ihandle, signedDataLength + signatureLength) <0) {
618 ALOGE("ION allocation failed");
619 return -1;
620 }
621 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
622
623 /* Populate the send data structure */
624 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
625 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
626 sizeof(qcom_km_key_blob_t ) + sizeof(keymaster_rsa_sign_params_t);
627
628 send_cmd = (keymaster_verify_data_cmd_t *)handle->ion_sbuffer;
629 resp = (keymaster_verify_data_resp_t *)((char *)handle->ion_sbuffer +
630 sizeof(keymaster_verify_data_cmd_t));
631 send_cmd->cmd_id = KEYMASTER_VERIFY_DATA ;
632 send_cmd->sign_param.digest_type = sign_params->digest_type;
633 send_cmd->sign_param.padding_type = sign_params->padding_type;
634 memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
635
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700636 send_cmd->signed_data = (uint32_t)(uintptr_t)ihandle.ion_sbuffer;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700637 send_cmd->signed_dlen = signedDataLength;
638 memcpy((unsigned char *)ihandle.ion_sbuffer, signedData, signedDataLength);
639
640 send_cmd->signature = signedDataLength;
641 send_cmd->slen = signatureLength;
642 memcpy(((unsigned char *)ihandle.ion_sbuffer + signedDataLength),
643 signature, signatureLength);
644 resp->status = KEYMASTER_FAILURE;
Ajay Dudanicccc0042013-06-11 11:42:15 -0700645
646 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
647 if (ret < 0) {
648 ALOGE("Verify data command failed (unable to enable clks) ret =%d", ret);
649 qcom_km_ion_dealloc(&ihandle);
650 return -1;
651 }
652
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700653 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
654 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
655 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
656
Ajay Dudanicccc0042013-06-11 11:42:15 -0700657 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
658 ALOGE("Verify data command: (unable to disable clks)");
659
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700660 if ( (ret < 0) || (resp->status < 0)) {
661 ALOGE("Verify data command failed resp->status = %d ret =%d", resp->status, ret);
662 qcom_km_ion_dealloc(&ihandle);
663 return -1;
664 }
665 qcom_km_ion_dealloc(&ihandle);
666 return 0;
667}
668
669/* Close an opened OpenSSL instance */
670static int qcom_km_close(hw_device_t *dev)
671{
Brahmaji Ka0bf5a72015-09-02 20:45:10 +0530672 keymaster0_device_t* km_dev = (keymaster0_device_t *)dev;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700673 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)km_dev->context;
674
675 if (km_handle->qseecom == NULL) {
676 ALOGE("Context == NULL");
677 return -1;
678 }
679 (*km_handle->QSEECom_shutdown_app)((struct QSEECom_handle **)&km_handle->qseecom);
680 free(km_dev->context);
681 free(dev);
682 return 0;
683}
684
685static int qcom_km_get_lib_sym(qcom_keymaster_handle_t* km_handle)
686{
Mekala Natarajanf2ffd552014-06-04 16:10:26 -0700687 km_handle->libhandle = dlopen("libQSEEComAPI.so", RTLD_NOW);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700688 if ( km_handle->libhandle ) {
689 *(void **)(&km_handle->QSEECom_start_app) =
690 dlsym(km_handle->libhandle,"QSEECom_start_app");
691 if (km_handle->QSEECom_start_app == NULL) {
692 ALOGE("dlsym: Error Loading QSEECom_start_app");
693 dlclose(km_handle->libhandle );
694 km_handle->libhandle = NULL;
695 return -1;
696 }
697 *(void **)(&km_handle->QSEECom_shutdown_app) =
698 dlsym(km_handle->libhandle,"QSEECom_shutdown_app");
699 if (km_handle->QSEECom_shutdown_app == NULL) {
700 ALOGE("dlsym: Error Loading QSEECom_shutdown_app");
701 dlclose(km_handle->libhandle );
702 km_handle->libhandle = NULL;
703 return -1;
704 }
705 *(void **)(&km_handle->QSEECom_send_cmd) =
706 dlsym(km_handle->libhandle,"QSEECom_send_cmd");
707 if (km_handle->QSEECom_send_cmd == NULL) {
708 ALOGE("dlsym: Error Loading QSEECom_send_cmd");
709 dlclose(km_handle->libhandle );
710 km_handle->libhandle = NULL;
711 return -1;
712 }
713 *(void **)(&km_handle->QSEECom_send_modified_cmd) =
714 dlsym(km_handle->libhandle,"QSEECom_send_modified_cmd");
715 if (km_handle->QSEECom_send_modified_cmd == NULL) {
716 ALOGE("dlsym: Error Loading QSEECom_send_modified_cmd");
717 dlclose(km_handle->libhandle );
718 km_handle->libhandle = NULL;
719 return -1;
720 }
Ajay Dudanicccc0042013-06-11 11:42:15 -0700721 *(void **)(&km_handle->QSEECom_set_bandwidth) =
722 dlsym(km_handle->libhandle,"QSEECom_set_bandwidth");
723 if (km_handle->QSEECom_set_bandwidth == NULL) {
724 ALOGE("dlsym: Error Loading QSEECom_set_bandwidth");
725 dlclose(km_handle->libhandle );
726 km_handle->libhandle = NULL;
727 return -1;
728 }
729
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700730 } else {
731 ALOGE("failed to load qseecom library");
732 return -1;
733 }
734 return 0;
735}
736
737/*
738 * Generic device handling
739 */
740static int qcom_km_open(const hw_module_t* module, const char* name,
741 hw_device_t** device)
742{
743 int ret = 0;
Jyoti Wadhwani79fc6602015-01-14 15:59:33 -0800744 unsigned int attempt_num = 0;
745 char property_val[PROPERTY_VALUE_MAX] = {0};
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700746 qcom_keymaster_handle_t* km_handle;
747 if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
748 return -EINVAL;
749
750 km_handle = (qcom_keymaster_handle_t *)malloc(sizeof(qcom_keymaster_handle_t));
751 if (km_handle == NULL) {
752 ALOGE("Memalloc for keymaster handle failed");
753 return -1;
754 }
755 km_handle->qseecom = NULL;
756 km_handle->libhandle = NULL;
757 ret = qcom_km_get_lib_sym(km_handle);
758 if (ret) {
759 free(km_handle);
760 return -1;
761 }
Brahmaji Ka0bf5a72015-09-02 20:45:10 +0530762 Unique_keymaster_device_t dev(new keymaster0_device_t);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700763 if (dev.get() == NULL){
764 free(km_handle);
765 return -ENOMEM;
766 }
767 dev->context = (void *)km_handle;
Jyoti Wadhwani79fc6602015-01-14 15:59:33 -0800768 while (attempt_num < MAX_PROPERTY_GET_ATTEMPTS)
769 {
770 property_get("sys.keymaster.loaded", property_val, "");
771 if (strncmp(property_val, "true", sizeof(property_val)) == 0)
772 {
773 ALOGD("keymaster app is loaded");
774 break;
775 }
776 if (attempt_num == 0)
777 ALOGE("keymaster app is not loaded, attempt number %d", attempt_num);
778 attempt_num++;
779 sleep(PROPERTY_GET_SLEEP_INTERVAL);
780 }
781 if (attempt_num == MAX_PROPERTY_GET_ATTEMPTS)
782 {
783 ALOGE("Keymaster app not loaded: Max attempts reached");
784 free(km_handle);
785 return -1;
786 }
787 ALOGD("keymaster app got loaded at attempt number %d", attempt_num);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700788 ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
Jyoti Wadhwanif6953ac2014-10-17 11:57:10 -0700789 "/vendor/firmware/keymaster", "keymaster", KM_SB_LENGTH);
790 if(ret)
791 ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
792 "/firmware/image", "keymaste", KM_SB_LENGTH);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700793 if (ret) {
Ian Rogers3b16dc72014-01-13 20:14:51 -0800794 ALOGE("Loading keymaster app failed");
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700795 free(km_handle);
796 return -1;
797 }
798 dev->common.tag = HARDWARE_DEVICE_TAG;
799 dev->common.version = 1;
800 dev->common.module = (struct hw_module_t*) module;
801 dev->common.close = qcom_km_close;
Geremy Condra5ca7ccb2014-04-17 16:10:40 -0700802 dev->flags = KEYMASTER_BLOBS_ARE_STANDALONE;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700803
804 dev->generate_keypair = qcom_km_generate_keypair;
805 dev->import_keypair = qcom_km_import_keypair;
806 dev->get_keypair_public = qcom_km_get_keypair_public;
807 dev->delete_keypair = NULL;
808 dev->delete_all = NULL;
809 dev->sign_data = qcom_km_sign_data;
810 dev->verify_data = qcom_km_verify_data;
811
812 *device = reinterpret_cast<hw_device_t*>(dev.release());
813
814 return 0;
815}
816
817static struct hw_module_methods_t keystore_module_methods = {
synergy dev328b6632013-11-06 18:43:39 -0800818 .open = qcom_km_open,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700819};
820
821struct keystore_module HAL_MODULE_INFO_SYM
822__attribute__ ((visibility ("default"))) = {
synergy dev328b6632013-11-06 18:43:39 -0800823 .common = {
824 .tag = HARDWARE_MODULE_TAG,
Paul Lawrencef4191b52014-05-06 13:59:38 -0700825 .module_api_version = QCOM_KEYMASTER_API_VERSION,
826 .hal_api_version = HARDWARE_HAL_API_VERSION,
synergy dev328b6632013-11-06 18:43:39 -0800827 .id = KEYSTORE_HARDWARE_MODULE_ID,
828 .name = "Keymaster QCOM HAL",
829 .author = "The Android Open Source Project",
830 .methods = &keystore_module_methods,
831 .dso = 0,
832 .reserved = {},
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700833 },
834};