blob: 3c0f7b545e140ac38ddb36764276ec7133a39017 [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
Andreas Gampe265133a2017-10-02 12:05:47 -070021#include <memory>
22
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070023#include <hardware/hardware.h>
Shawn Willden7ef26052015-02-24 10:42:38 -070024#include <hardware/keymaster0.h>
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070025
26#include <openssl/evp.h>
27#include <openssl/bio.h>
28#include <openssl/rsa.h>
29#include <openssl/err.h>
30#include <openssl/x509.h>
31
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070032#include <linux/ioctl.h>
33#include <linux/msm_ion.h>
34#include <sys/mman.h>
35
36#include <stdio.h>
37#include <stdlib.h>
38#include <stddef.h>
39#include <unistd.h>
40#include <dirent.h>
41#include <fcntl.h>
42
43#include <sys/types.h>
44#include <sys/stat.h>
45#include <dlfcn.h>
46
Jyoti Wadhwanic44fcfe2015-01-14 15:59:33 -080047#include <cutils/properties.h>
48
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070049#include "QSEEComAPI.h"
50#include "keymaster_qcom.h"
51
52// For debugging
53//#define LOG_NDEBUG 0
54
55#define LOG_TAG "QCOMKeyMaster"
Jyoti Wadhwanib3aa7852014-10-17 11:57:10 -070056#define UNUSED(x) (void)(x)
57#define KM_SB_LENGTH (4096 * 2)
Jyoti Wadhwanic44fcfe2015-01-14 15:59:33 -080058#define MAX_PROPERTY_GET_ATTEMPTS 60
59#define PROPERTY_GET_SLEEP_INTERVAL 1
Jyoti Wadhwanib3aa7852014-10-17 11:57:10 -070060
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070061#include <cutils/log.h>
62struct qcom_km_ion_info_t {
63 int32_t ion_fd;
64 int32_t ifd_data_fd;
65 struct ion_handle_data ion_alloc_handle;
66 unsigned char * ion_sbuffer;
67 uint32_t sbuf_len;
68};
69
70struct qcom_keymaster_handle {
71 struct QSEECom_handle *qseecom;
72 void *libhandle;
Jyoti Wadhwanib3aa7852014-10-17 11:57:10 -070073 int (*QSEECom_start_app)(struct QSEECom_handle ** handle, const char* path,
74 const char* appname, uint32_t size);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070075 int (*QSEECom_shutdown_app)(struct QSEECom_handle **handle);
76 int (*QSEECom_send_cmd)(struct QSEECom_handle* handle, void *cbuf,
77 uint32_t clen, void *rbuf, uint32_t rlen);
78 int (*QSEECom_send_modified_cmd)(struct QSEECom_handle* handle, void *cbuf,
79 uint32_t clen, void *rbuf, uint32_t rlen,
80 struct QSEECom_ion_fd_info *ihandle);
Ajay Dudanicccc0042013-06-11 11:42:15 -070081 int (*QSEECom_set_bandwidth)(struct QSEECom_handle* handle, bool high);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070082};
83typedef struct qcom_keymaster_handle qcom_keymaster_handle_t;
84
85struct EVP_PKEY_Delete {
86 void operator()(EVP_PKEY* p) const {
87 EVP_PKEY_free(p);
88 }
89};
Andreas Gampe265133a2017-10-02 12:05:47 -070090typedef std::unique_ptr<EVP_PKEY, EVP_PKEY_Delete> Unique_EVP_PKEY;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070091
92struct RSA_Delete {
93 void operator()(RSA* p) const {
94 RSA_free(p);
95 }
96};
Andreas Gampe265133a2017-10-02 12:05:47 -070097typedef std::unique_ptr<RSA, RSA_Delete> Unique_RSA;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -070098
Andreas Gampe265133a2017-10-02 12:05:47 -070099typedef std::unique_ptr<keymaster0_device_t> Unique_keymaster_device_t;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700100
101/**
102 * Many OpenSSL APIs take ownership of an argument on success but don't free the argument
103 * on failure. This means we need to tell our scoped pointers when we've transferred ownership,
104 * without triggering a warning by not using the result of release().
105 */
106#define OWNERSHIP_TRANSFERRED(obj) \
107 typeof (obj.release()) _dummy __attribute__((unused)) = obj.release()
108
Shawn Willden7ef26052015-02-24 10:42:38 -0700109static int qcom_km_get_keypair_public(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700110 const uint8_t* keyBlob, const size_t keyBlobLength,
111 uint8_t** x509_data, size_t* x509_data_length) {
112
113 struct qcom_km_key_blob * keyblob_ptr = (struct qcom_km_key_blob *)keyBlob;
114
Jyoti Wadhwanib3aa7852014-10-17 11:57:10 -0700115 UNUSED(dev);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700116 if (x509_data == NULL || x509_data_length == NULL) {
117 ALOGE("Output public key buffer == NULL");
118 return -1;
119 }
120
121 if (keyBlob == NULL) {
122 ALOGE("Supplied key blob was NULL");
123 return -1;
124 }
125
126 // Should be large enough for keyblob data:
127 if (keyBlobLength < (sizeof(qcom_km_key_blob_t))) {
128 ALOGE("key blob appears to be truncated");
129 return -1;
130 }
131
132 if (keyblob_ptr->magic_num != KM_MAGIC_NUM) {
133 ALOGE("Cannot read key; it was not made by this keymaster");
134 return -1;
135 }
136
137 if (keyblob_ptr->public_exponent_size == 0 ) {
138 ALOGE("Key blob appears to have incorrect exponent length");
139 return -1;
140 }
141 if (keyblob_ptr->modulus_size == 0 ) {
142 ALOGE("Key blob appears to have incorrect modulus length");
143 return -1;
144 }
145
146 Unique_RSA rsa(RSA_new());
147 if (rsa.get() == NULL) {
148 ALOGE("Could not allocate RSA structure");
149 return -1;
150 }
151
152 rsa->n = BN_bin2bn(reinterpret_cast<const unsigned char*>(keyblob_ptr->modulus),
153 keyblob_ptr->modulus_size, NULL);
154 if (rsa->n == NULL) {
155 ALOGE("Failed to initialize modulus");
156 return -1;
157 }
158
159 rsa->e = BN_bin2bn(reinterpret_cast<const unsigned char*>(&keyblob_ptr->public_exponent),
160 keyblob_ptr->public_exponent_size, NULL);
161 if (rsa->e == NULL) {
162 ALOGE("Failed to initialize public exponent");
163 return -1;
164 }
165
166 Unique_EVP_PKEY pkey(EVP_PKEY_new());
167 if (pkey.get() == NULL) {
168 ALOGE("Could not allocate EVP_PKEY structure");
169 return -1;
170 }
171 if (EVP_PKEY_assign_RSA(pkey.get(), rsa.get()) != 1) {
172 ALOGE("Failed to assign rsa parameters \n");
173 return -1;
174 }
175 OWNERSHIP_TRANSFERRED(rsa);
176
177 int len = i2d_PUBKEY(pkey.get(), NULL);
178 if (len <= 0) {
179 ALOGE("Len returned is < 0 len = %d", len);
180 return -1;
181 }
182
Andreas Gampe265133a2017-10-02 12:05:47 -0700183 std::unique_ptr<unsigned char[]> key(new unsigned char[len]);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700184 if (key.get() == NULL) {
185 ALOGE("Could not allocate memory for public key data");
186 return -1;
187 }
188
George Burgess IVc4cf1b22017-08-31 11:10:58 -0700189 unsigned char* tmp = key.get();
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700190 if (i2d_PUBKEY(pkey.get(), &tmp) != len) {
191 ALOGE("Len 2 returned is < 0 len = %d", len);
192 return -1;
193 }
194 *x509_data_length = len;
195 *x509_data = key.release();
196
197 return 0;
198}
199
200static int32_t qcom_km_ION_memalloc(struct qcom_km_ion_info_t *handle,
201 uint32_t size)
202{
203 int32_t ret = 0;
204 int32_t iret = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700205 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 Wadhwanib3aa7852014-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
Shawn Willden7ef26052015-02-24 10:42:38 -0700322static 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 {
Andreas Gampe265133a2017-10-02 12:05:47 -0700378 std::unique_ptr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700379 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
Shawn Willden7ef26052015-02-24 10:42:38 -0700391static 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 Wadhwanib3aa7852014-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 Wadhwanib3aa7852014-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 {
Andreas Gampe265133a2017-10-02 12:05:47 -0700461 std::unique_ptr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700462 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
Shawn Willden7ef26052015-02-24 10:42:38 -0700476static 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) {
Michael Bestas8111e092017-11-06 00:26:20 +0200487 ALOGE("Input data to be signed is too long %zu bytes", dataLength);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700488 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 Wadhwanib3aa7852014-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 Wadhwanib3aa7852014-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 {
Andreas Gampe265133a2017-10-02 12:05:47 -0700561 std::unique_ptr<uint8_t> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(resp->sig_len)));
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700562 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
Shawn Willden7ef26052015-02-24 10:42:38 -0700577static 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 Wadhwanib3aa7852014-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 Wadhwanib3aa7852014-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{
Shawn Willden7ef26052015-02-24 10:42:38 -0700672 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 Wadhwanic44fcfe2015-01-14 15:59:33 -0800744 unsigned int attempt_num = 0;
dianlujitaocfa17ea2019-10-08 14:52:16 +0800745#ifdef WAIT_FOR_QSEE
Jyoti Wadhwanic44fcfe2015-01-14 15:59:33 -0800746 char property_val[PROPERTY_VALUE_MAX] = {0};
myfluxi87d3a532015-11-04 00:46:09 +0100747#endif
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700748 qcom_keymaster_handle_t* km_handle;
749 if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
750 return -EINVAL;
751
752 km_handle = (qcom_keymaster_handle_t *)malloc(sizeof(qcom_keymaster_handle_t));
753 if (km_handle == NULL) {
754 ALOGE("Memalloc for keymaster handle failed");
755 return -1;
756 }
757 km_handle->qseecom = NULL;
758 km_handle->libhandle = NULL;
759 ret = qcom_km_get_lib_sym(km_handle);
760 if (ret) {
761 free(km_handle);
762 return -1;
763 }
Shawn Willden7ef26052015-02-24 10:42:38 -0700764 Unique_keymaster_device_t dev(new keymaster0_device_t);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700765 if (dev.get() == NULL){
766 free(km_handle);
767 return -ENOMEM;
768 }
769 dev->context = (void *)km_handle;
Jyoti Wadhwanic44fcfe2015-01-14 15:59:33 -0800770 while (attempt_num < MAX_PROPERTY_GET_ATTEMPTS)
771 {
dianlujitaocfa17ea2019-10-08 14:52:16 +0800772#ifdef WAIT_FOR_QSEE
Jyoti Wadhwanic44fcfe2015-01-14 15:59:33 -0800773 property_get("sys.keymaster.loaded", property_val, "");
774 if (strncmp(property_val, "true", sizeof(property_val)) == 0)
775 {
myfluxi87d3a532015-11-04 00:46:09 +0100776#endif
Jyoti Wadhwanic44fcfe2015-01-14 15:59:33 -0800777 ALOGD("keymaster app is loaded");
778 break;
dianlujitaocfa17ea2019-10-08 14:52:16 +0800779#ifdef WAIT_FOR_QSEE
Jyoti Wadhwanic44fcfe2015-01-14 15:59:33 -0800780 }
myfluxi87d3a532015-11-04 00:46:09 +0100781#endif
Jyoti Wadhwanic44fcfe2015-01-14 15:59:33 -0800782 if (attempt_num == 0)
783 ALOGE("keymaster app is not loaded, attempt number %d", attempt_num);
784 attempt_num++;
785 sleep(PROPERTY_GET_SLEEP_INTERVAL);
786 }
787 if (attempt_num == MAX_PROPERTY_GET_ATTEMPTS)
788 {
789 ALOGE("Keymaster app not loaded: Max attempts reached");
790 free(km_handle);
791 return -1;
792 }
793 ALOGD("keymaster app got loaded at attempt number %d", attempt_num);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700794 ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
Jyoti Wadhwanib3aa7852014-10-17 11:57:10 -0700795 "/vendor/firmware/keymaster", "keymaster", KM_SB_LENGTH);
796 if(ret)
797 ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
798 "/firmware/image", "keymaste", KM_SB_LENGTH);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700799 if (ret) {
Ian Rogers3b16dc72014-01-13 20:14:51 -0800800 ALOGE("Loading keymaster app failed");
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700801 free(km_handle);
802 return -1;
803 }
804 dev->common.tag = HARDWARE_DEVICE_TAG;
805 dev->common.version = 1;
806 dev->common.module = (struct hw_module_t*) module;
807 dev->common.close = qcom_km_close;
Geremy Condra5ca7ccb2014-04-17 16:10:40 -0700808 dev->flags = KEYMASTER_BLOBS_ARE_STANDALONE;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700809
810 dev->generate_keypair = qcom_km_generate_keypair;
811 dev->import_keypair = qcom_km_import_keypair;
812 dev->get_keypair_public = qcom_km_get_keypair_public;
813 dev->delete_keypair = NULL;
814 dev->delete_all = NULL;
815 dev->sign_data = qcom_km_sign_data;
816 dev->verify_data = qcom_km_verify_data;
817
818 *device = reinterpret_cast<hw_device_t*>(dev.release());
819
820 return 0;
821}
822
823static struct hw_module_methods_t keystore_module_methods = {
synergy dev328b6632013-11-06 18:43:39 -0800824 .open = qcom_km_open,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700825};
826
827struct keystore_module HAL_MODULE_INFO_SYM
828__attribute__ ((visibility ("default"))) = {
synergy dev328b6632013-11-06 18:43:39 -0800829 .common = {
830 .tag = HARDWARE_MODULE_TAG,
Paul Lawrencef4191b52014-05-06 13:59:38 -0700831 .module_api_version = QCOM_KEYMASTER_API_VERSION,
832 .hal_api_version = HARDWARE_HAL_API_VERSION,
synergy dev328b6632013-11-06 18:43:39 -0800833 .id = KEYSTORE_HARDWARE_MODULE_ID,
834 .name = "Keymaster QCOM HAL",
835 .author = "The Android Open Source Project",
836 .methods = &keystore_module_methods,
837 .dso = 0,
838 .reserved = {},
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700839 },
840};