blob: db4362671221f7e741956737435929f4df5413ee [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 Wadhwani391a41f2015-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 Wadhwanicc1f7c02014-10-17 11:57:10 -070056#define UNUSED(x) (void)(x)
57#define KM_SB_LENGTH (4096 * 2)
Jyoti Wadhwani391a41f2015-01-14 15:59:33 -080058#define MAX_PROPERTY_GET_ATTEMPTS 60
59#define PROPERTY_GET_SLEEP_INTERVAL 1
Jyoti Wadhwanicc1f7c02014-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 Wadhwanicc1f7c02014-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 Wadhwanicc1f7c02014-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;
205 int32_t fd = 0;
206 unsigned char *v_addr;
207 struct ion_allocation_data ion_alloc_data;
208 int32_t ion_fd;
209 int32_t rc;
210 struct ion_fd_data ifd_data;
211 struct ion_handle_data handle_data;
212
213 /* open ION device for memory management
214 * O_DSYNC -> uncached memory
215 */
216 if(handle == NULL){
217 ALOGE("Error:: null handle received");
218 return -1;
219 }
220 ion_fd = open("/dev/ion", O_RDONLY | O_DSYNC);
221 if (ion_fd < 0) {
222 ALOGE("Error::Cannot open ION device");
223 return -1;
224 }
225 handle->ion_sbuffer = NULL;
226 handle->ifd_data_fd = 0;
227
228 /* Size of allocation */
229 ion_alloc_data.len = (size + 4095) & (~4095);
230
231 /* 4K aligned */
232 ion_alloc_data.align = 4096;
233
234 /* memory is allocated from EBI heap */
Naveen Ramarajdf89f272014-06-03 11:28:00 -0700235 ion_alloc_data.ION_HEAP_MASK = ION_HEAP(ION_QSECOM_HEAP_ID);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700236
237 /* Set the memory to be uncached */
Ajay Dudani0cd599c2013-04-22 15:10:32 -0700238 ion_alloc_data.flags = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700239
240 /* IOCTL call to ION for memory request */
241 rc = ioctl(ion_fd, ION_IOC_ALLOC, &ion_alloc_data);
242 if (rc) {
243 ret = -1;
244 goto alloc_fail;
245 }
246
Jyoti Wadhwanicc1f7c02014-10-17 11:57:10 -0700247 if (ion_alloc_data.handle) {
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700248 ifd_data.handle = ion_alloc_data.handle;
249 } else {
250 ret = -1;
251 goto alloc_fail;
252 }
253 /* Call MAP ioctl to retrieve the ifd_data.fd file descriptor */
254 rc = ioctl(ion_fd, ION_IOC_MAP, &ifd_data);
255 if (rc) {
256 ret = -1;
257 goto ioctl_fail;
258 }
259
260 /* Make the ion mmap call */
261 v_addr = (unsigned char *)mmap(NULL, ion_alloc_data.len,
262 PROT_READ | PROT_WRITE,
263 MAP_SHARED, ifd_data.fd, 0);
264 if (v_addr == MAP_FAILED) {
265 ALOGE("Error::ION MMAP failed");
266 ret = -1;
267 goto map_fail;
268 }
269 handle->ion_fd = ion_fd;
270 handle->ifd_data_fd = ifd_data.fd;
271 handle->ion_sbuffer = v_addr;
272 handle->ion_alloc_handle.handle = ion_alloc_data.handle;
273 handle->sbuf_len = size;
274 return ret;
275
276map_fail:
277 if (handle->ion_sbuffer != NULL) {
278 iret = munmap(handle->ion_sbuffer, ion_alloc_data.len);
279 if (iret)
280 ALOGE("Error::Failed to unmap memory for load image. ret = %d", ret);
281 }
282
283ioctl_fail:
284 handle_data.handle = ion_alloc_data.handle;
285 if (handle->ifd_data_fd)
286 close(handle->ifd_data_fd);
287 iret = ioctl(ion_fd, ION_IOC_FREE, &handle_data);
288 if (iret) {
289 ALOGE("Error::ION FREE ioctl returned error = %d",iret);
290 }
291
292alloc_fail:
293 if (ion_fd > 0)
294 close(ion_fd);
295 return ret;
296}
297
298/** @brief: Deallocate ION memory
299 *
300 *
301 */
302static int32_t qcom_km_ion_dealloc(struct qcom_km_ion_info_t *handle)
303{
304 struct ion_handle_data handle_data;
305 int32_t ret = 0;
306
307 /* Deallocate the memory for the listener */
308 ret = munmap(handle->ion_sbuffer, (handle->sbuf_len + 4095) & (~4095));
309 if (ret) {
310 ALOGE("Error::Unmapping ION Buffer failed with ret = %d", ret);
311 }
312
313 handle_data.handle = handle->ion_alloc_handle.handle;
314 close(handle->ifd_data_fd);
315 ret = ioctl(handle->ion_fd, ION_IOC_FREE, &handle_data);
316 if (ret) {
317 ALOGE("Error::ION Memory FREE ioctl failed with ret = %d", ret);
318 }
319 close(handle->ion_fd);
320 return ret;
321}
322
Shawn Willden7ef26052015-02-24 10:42:38 -0700323static int qcom_km_generate_keypair(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700324 const keymaster_keypair_t key_type, const void* key_params,
325 uint8_t** keyBlob, size_t* keyBlobLength) {
326
327 if (dev->context == NULL) {
328 ALOGE("qcom_km_generate_keypair: Context == NULL");
329 return -1;
330 }
331
332 if (key_type != TYPE_RSA) {
333 ALOGE("Unsupported key type %d", key_type);
334 return -1;
335 } else if (key_params == NULL) {
336 ALOGE("key_params == null");
337 return -1;
338 }
339 if (keyBlob == NULL || keyBlobLength == NULL) {
340 ALOGE("output key blob or length == NULL");
341 return -1;
342 }
343 keymaster_rsa_keygen_params_t* rsa_params = (keymaster_rsa_keygen_params_t*) key_params;
344
345 keymaster_gen_keypair_cmd_t *send_cmd = NULL;
346 keymaster_gen_keypair_resp_t *resp = NULL;
347 struct QSEECom_handle *handle = NULL;
348 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
349 int ret = 0;
350
351 handle = (struct QSEECom_handle *)(km_handle->qseecom);
352 send_cmd = (keymaster_gen_keypair_cmd_t *)handle->ion_sbuffer;
353 resp = (keymaster_gen_keypair_resp_t *)(handle->ion_sbuffer +
354 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)));
355 send_cmd->cmd_id = KEYMASTER_GENERATE_KEYPAIR;
356 send_cmd->key_type = key_type;
357 send_cmd->rsa_params.modulus_size = rsa_params->modulus_size;
358 send_cmd->rsa_params.public_exponent = rsa_params->public_exponent;
359 resp->status = KEYMASTER_FAILURE;
360 resp->key_blob_len = sizeof(qcom_km_key_blob_t);
361
Ajay Dudanicccc0042013-06-11 11:42:15 -0700362 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
363 if (ret < 0) {
364 ALOGE("Generate key command failed (unable to enable clks) ret =%d", ret);
365 return -1;
366 }
367
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700368 ret = (*km_handle->QSEECom_send_cmd)(handle, send_cmd,
369 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_cmd_t)), resp,
370 QSEECOM_ALIGN(sizeof(keymaster_gen_keypair_resp_t)));
371
Ajay Dudanicccc0042013-06-11 11:42:15 -0700372 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
373 ALOGE("Import key command: (unable to disable clks)");
374
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700375 if ( (ret < 0) || (resp->status < 0)) {
376 ALOGE("Generate key command failed resp->status = %d ret =%d", resp->status, ret);
377 return -1;
378 } else {
Andreas Gampe265133a2017-10-02 12:05:47 -0700379 std::unique_ptr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700380 if (keydata.get() == NULL) {
381 ALOGE("could not allocate memory for key blob");
382 return -1;
383 }
384 unsigned char* p = keydata.get();
385 memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
386 *keyBlob = keydata.release();
387 *keyBlobLength = resp->key_blob_len;
388 }
389 return 0;
390}
391
Shawn Willden7ef26052015-02-24 10:42:38 -0700392static int qcom_km_import_keypair(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700393 const uint8_t* key, const size_t key_length,
394 uint8_t** keyBlob, size_t* keyBlobLength)
395{
396 if (dev->context == NULL) {
397 ALOGE("qcom_km_import_keypair: Context == NULL");
398 return -1;
399 }
400
401 if (key == NULL) {
402 ALOGE("Input key == NULL");
403 return -1;
404 } else if (keyBlob == NULL || keyBlobLength == NULL) {
405 ALOGE("Output key blob or length == NULL");
406 return -1;
407 }
408
409 struct QSEECom_ion_fd_info ion_fd_info;
410 struct qcom_km_ion_info_t ihandle;
411 int ret = 0;
412
413 ihandle.ion_fd = 0;
Jyoti Wadhwanicc1f7c02014-10-17 11:57:10 -0700414 ihandle.ion_alloc_handle.handle = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700415 if (qcom_km_ION_memalloc(&ihandle, QSEECOM_ALIGN(key_length)) < 0) {
416 ALOGE("ION allocation failed");
417 return -1;
418 }
419 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
420
421 /* Populate the send data structure */
422 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
423 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t);
424
425
426 struct QSEECom_handle *handle = NULL;
427 keymaster_import_keypair_cmd_t *send_cmd = NULL;
428 keymaster_import_keypair_resp_t *resp = NULL;
429 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
430
431 handle = (struct QSEECom_handle *)(km_handle->qseecom);
432 send_cmd = (keymaster_import_keypair_cmd_t *)handle->ion_sbuffer;
433 resp = (keymaster_import_keypair_resp_t *)(handle->ion_sbuffer +
434 QSEECOM_ALIGN(sizeof(keymaster_import_keypair_cmd_t)));
435 send_cmd->cmd_id = KEYMASTER_IMPORT_KEYPAIR;
Jyoti Wadhwanicc1f7c02014-10-17 11:57:10 -0700436 send_cmd->pkcs8_key = (uint32_t)(uintptr_t)ihandle.ion_sbuffer;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700437
438 memcpy((unsigned char *)ihandle.ion_sbuffer, key, key_length);
439
440 send_cmd->pkcs8_key_len = key_length;
441 resp->status = KEYMASTER_FAILURE;
442 resp->key_blob_len = sizeof(qcom_km_key_blob_t);
443
Ajay Dudanicccc0042013-06-11 11:42:15 -0700444 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
445 if (ret < 0) {
446 ALOGE("Import key command failed (unable to enable clks) ret =%d", ret);
447 qcom_km_ion_dealloc(&ihandle);
448 return -1;
449 }
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700450 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
451 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
452 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
453
Ajay Dudanicccc0042013-06-11 11:42:15 -0700454 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
455 ALOGE("Import key command: (unable to disable clks)");
456
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700457 if ( (ret < 0) || (resp->status < 0)) {
458 ALOGE("Import key command failed resp->status = %d ret =%d", resp->status, ret);
459 qcom_km_ion_dealloc(&ihandle);
460 return -1;
461 } else {
Andreas Gampe265133a2017-10-02 12:05:47 -0700462 std::unique_ptr<unsigned char[]> keydata(new unsigned char[resp->key_blob_len]);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700463 if (keydata.get() == NULL) {
464 ALOGE("could not allocate memory for key blob");
465 return -1;
466 }
467 unsigned char* p = keydata.get();
468 memcpy(p, (unsigned char *)(&resp->key_blob), resp->key_blob_len);
469 *keyBlob = keydata.release();
470 *keyBlobLength = resp->key_blob_len;
471
472 }
473 qcom_km_ion_dealloc(&ihandle);
474 return 0;
475}
476
Shawn Willden7ef26052015-02-24 10:42:38 -0700477static int qcom_km_sign_data(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700478 const void* params,
479 const uint8_t* keyBlob, const size_t keyBlobLength,
480 const uint8_t* data, const size_t dataLength,
481 uint8_t** signedData, size_t* signedDataLength)
482{
483 if (dev->context == NULL) {
484 ALOGE("qcom_km_sign_data: Context == NULL");
485 return -1;
486 }
487 if (dataLength > KM_KEY_SIZE_MAX) {
488 ALOGE("Input data to be signed is too long %d bytes", dataLength);
489 return -1;
490 }
491 if (data == NULL) {
492 ALOGE("input data to sign == NULL");
493 return -1;
494 } else if (signedData == NULL || signedDataLength == NULL) {
495 ALOGE("Output signature buffer == NULL");
496 return -1;
497 }
498 keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
499 if (sign_params->digest_type != DIGEST_NONE) {
500 ALOGE("Cannot handle digest type %d", sign_params->digest_type);
501 return -1;
502 } else if (sign_params->padding_type != PADDING_NONE) {
503 ALOGE("Cannot handle padding type %d", sign_params->padding_type);
504 return -1;
505 }
506
507 struct QSEECom_handle *handle = NULL;
508 keymaster_sign_data_cmd_t *send_cmd = NULL;
509 keymaster_sign_data_resp_t *resp = NULL;
510 struct QSEECom_ion_fd_info ion_fd_info;
511 struct qcom_km_ion_info_t ihandle;
512 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
513 int ret = 0;
514
515 handle = (struct QSEECom_handle *)(km_handle->qseecom);
516 ihandle.ion_fd = 0;
Jyoti Wadhwanicc1f7c02014-10-17 11:57:10 -0700517 ihandle.ion_alloc_handle.handle = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700518 if (qcom_km_ION_memalloc(&ihandle, dataLength) < 0) {
519 ALOGE("ION allocation failed");
520 return -1;
521 }
522 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
523
524 /* Populate the send data structure */
525 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
526 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
527 sizeof(qcom_km_key_blob_t) + sizeof(keymaster_rsa_sign_params_t);
528
529 send_cmd = (keymaster_sign_data_cmd_t *)handle->ion_sbuffer;
530 resp = (keymaster_sign_data_resp_t *)(handle->ion_sbuffer +
531 QSEECOM_ALIGN(sizeof(keymaster_sign_data_cmd_t)));
532 send_cmd->cmd_id = KEYMASTER_SIGN_DATA ;
533 send_cmd->sign_param.digest_type = sign_params->digest_type;
534 send_cmd->sign_param.padding_type = sign_params->padding_type;
535 memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
536 memcpy((unsigned char *)ihandle.ion_sbuffer, data, dataLength);
537
Jyoti Wadhwanicc1f7c02014-10-17 11:57:10 -0700538 send_cmd->data = (uint32_t)(uintptr_t)ihandle.ion_sbuffer;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700539 send_cmd->dlen = dataLength;
540 resp->sig_len = KM_KEY_SIZE_MAX;
541 resp->status = KEYMASTER_FAILURE;
542
Ajay Dudanicccc0042013-06-11 11:42:15 -0700543 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
544 if (ret < 0) {
545 ALOGE("Sign data command failed (unable to enable clks) ret =%d", ret);
546 qcom_km_ion_dealloc(&ihandle);
547 return -1;
548 }
549
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700550 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
551 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
552 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
Ajay Dudanicccc0042013-06-11 11:42:15 -0700553
554 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
555 ALOGE("Sign data command: (unable to disable clks)");
556
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700557 if ( (ret < 0) || (resp->status < 0)) {
558 ALOGE("Sign data command failed resp->status = %d ret =%d", resp->status, ret);
559 qcom_km_ion_dealloc(&ihandle);
560 return -1;
561 } else {
Andreas Gampe265133a2017-10-02 12:05:47 -0700562 std::unique_ptr<uint8_t> signedDataPtr(reinterpret_cast<uint8_t*>(malloc(resp->sig_len)));
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700563 if (signedDataPtr.get() == NULL) {
564 ALOGE("Sign data memory allocation failed");
565 qcom_km_ion_dealloc(&ihandle);
566 return -1;
567 }
568 unsigned char* p = signedDataPtr.get();
569 memcpy(p, (unsigned char *)(&resp->signed_data), resp->sig_len);
570
571 *signedDataLength = resp->sig_len;
572 *signedData = signedDataPtr.release();
573 }
574 qcom_km_ion_dealloc(&ihandle);
575 return 0;
576}
577
Shawn Willden7ef26052015-02-24 10:42:38 -0700578static int qcom_km_verify_data(const keymaster0_device_t* dev,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700579 const void* params,
580 const uint8_t* keyBlob, const size_t keyBlobLength,
581 const uint8_t* signedData, const size_t signedDataLength,
582 const uint8_t* signature, const size_t signatureLength)
583{
584 if (dev->context == NULL) {
585 ALOGE("qcom_km_verify_data: Context == NULL");
586 return -1;
587 }
588
589 if (signedData == NULL || signature == NULL) {
590 ALOGE("data or signature buffers == NULL");
591 return -1;
592 }
593
594 keymaster_rsa_sign_params_t* sign_params = (keymaster_rsa_sign_params_t*) params;
595 if (sign_params->digest_type != DIGEST_NONE) {
596 ALOGE("Cannot handle digest type %d", sign_params->digest_type);
597 return -1;
598 } else if (sign_params->padding_type != PADDING_NONE) {
599 ALOGE("Cannot handle padding type %d", sign_params->padding_type);
600 return -1;
601 } else if (signatureLength != signedDataLength) {
602 ALOGE("signed data length must be signature length");
603 return -1;
604 }
605
606 struct QSEECom_handle *handle = NULL;
607 keymaster_verify_data_cmd_t *send_cmd = NULL;
608 keymaster_verify_data_resp_t *resp = NULL;
609
610 struct QSEECom_ion_fd_info ion_fd_info;
611 struct qcom_km_ion_info_t ihandle;
612 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)dev->context;
613 int ret = 0;
614
615 handle = (struct QSEECom_handle *)(km_handle->qseecom);
616 ihandle.ion_fd = 0;
Jyoti Wadhwanicc1f7c02014-10-17 11:57:10 -0700617 ihandle.ion_alloc_handle.handle = 0;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700618 if (qcom_km_ION_memalloc(&ihandle, signedDataLength + signatureLength) <0) {
619 ALOGE("ION allocation failed");
620 return -1;
621 }
622 memset(&ion_fd_info, 0, sizeof(struct QSEECom_ion_fd_info));
623
624 /* Populate the send data structure */
625 ion_fd_info.data[0].fd = ihandle.ifd_data_fd;
626 ion_fd_info.data[0].cmd_buf_offset = sizeof(enum keymaster_cmd_t) +
627 sizeof(qcom_km_key_blob_t ) + sizeof(keymaster_rsa_sign_params_t);
628
629 send_cmd = (keymaster_verify_data_cmd_t *)handle->ion_sbuffer;
630 resp = (keymaster_verify_data_resp_t *)((char *)handle->ion_sbuffer +
631 sizeof(keymaster_verify_data_cmd_t));
632 send_cmd->cmd_id = KEYMASTER_VERIFY_DATA ;
633 send_cmd->sign_param.digest_type = sign_params->digest_type;
634 send_cmd->sign_param.padding_type = sign_params->padding_type;
635 memcpy((unsigned char *)(&send_cmd->key_blob), keyBlob, keyBlobLength);
636
Jyoti Wadhwanicc1f7c02014-10-17 11:57:10 -0700637 send_cmd->signed_data = (uint32_t)(uintptr_t)ihandle.ion_sbuffer;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700638 send_cmd->signed_dlen = signedDataLength;
639 memcpy((unsigned char *)ihandle.ion_sbuffer, signedData, signedDataLength);
640
641 send_cmd->signature = signedDataLength;
642 send_cmd->slen = signatureLength;
643 memcpy(((unsigned char *)ihandle.ion_sbuffer + signedDataLength),
644 signature, signatureLength);
645 resp->status = KEYMASTER_FAILURE;
Ajay Dudanicccc0042013-06-11 11:42:15 -0700646
647 ret = (*km_handle->QSEECom_set_bandwidth)(handle, true);
648 if (ret < 0) {
649 ALOGE("Verify data command failed (unable to enable clks) ret =%d", ret);
650 qcom_km_ion_dealloc(&ihandle);
651 return -1;
652 }
653
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700654 ret = (*km_handle->QSEECom_send_modified_cmd)(handle, send_cmd,
655 QSEECOM_ALIGN(sizeof(*send_cmd)), resp,
656 QSEECOM_ALIGN(sizeof(*resp)), &ion_fd_info);
657
Ajay Dudanicccc0042013-06-11 11:42:15 -0700658 if((*km_handle->QSEECom_set_bandwidth)(handle, false))
659 ALOGE("Verify data command: (unable to disable clks)");
660
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700661 if ( (ret < 0) || (resp->status < 0)) {
662 ALOGE("Verify data command failed resp->status = %d ret =%d", resp->status, ret);
663 qcom_km_ion_dealloc(&ihandle);
664 return -1;
665 }
666 qcom_km_ion_dealloc(&ihandle);
667 return 0;
668}
669
670/* Close an opened OpenSSL instance */
671static int qcom_km_close(hw_device_t *dev)
672{
Shawn Willden7ef26052015-02-24 10:42:38 -0700673 keymaster0_device_t* km_dev = (keymaster0_device_t *)dev;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700674 struct qcom_keymaster_handle *km_handle =(struct qcom_keymaster_handle *)km_dev->context;
675
676 if (km_handle->qseecom == NULL) {
677 ALOGE("Context == NULL");
678 return -1;
679 }
680 (*km_handle->QSEECom_shutdown_app)((struct QSEECom_handle **)&km_handle->qseecom);
681 free(km_dev->context);
682 free(dev);
683 return 0;
684}
685
686static int qcom_km_get_lib_sym(qcom_keymaster_handle_t* km_handle)
687{
Mekala Natarajanf2ffd552014-06-04 16:10:26 -0700688 km_handle->libhandle = dlopen("libQSEEComAPI.so", RTLD_NOW);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700689 if ( km_handle->libhandle ) {
690 *(void **)(&km_handle->QSEECom_start_app) =
691 dlsym(km_handle->libhandle,"QSEECom_start_app");
692 if (km_handle->QSEECom_start_app == NULL) {
693 ALOGE("dlsym: Error Loading QSEECom_start_app");
694 dlclose(km_handle->libhandle );
695 km_handle->libhandle = NULL;
696 return -1;
697 }
698 *(void **)(&km_handle->QSEECom_shutdown_app) =
699 dlsym(km_handle->libhandle,"QSEECom_shutdown_app");
700 if (km_handle->QSEECom_shutdown_app == NULL) {
701 ALOGE("dlsym: Error Loading QSEECom_shutdown_app");
702 dlclose(km_handle->libhandle );
703 km_handle->libhandle = NULL;
704 return -1;
705 }
706 *(void **)(&km_handle->QSEECom_send_cmd) =
707 dlsym(km_handle->libhandle,"QSEECom_send_cmd");
708 if (km_handle->QSEECom_send_cmd == NULL) {
709 ALOGE("dlsym: Error Loading QSEECom_send_cmd");
710 dlclose(km_handle->libhandle );
711 km_handle->libhandle = NULL;
712 return -1;
713 }
714 *(void **)(&km_handle->QSEECom_send_modified_cmd) =
715 dlsym(km_handle->libhandle,"QSEECom_send_modified_cmd");
716 if (km_handle->QSEECom_send_modified_cmd == NULL) {
717 ALOGE("dlsym: Error Loading QSEECom_send_modified_cmd");
718 dlclose(km_handle->libhandle );
719 km_handle->libhandle = NULL;
720 return -1;
721 }
Ajay Dudanicccc0042013-06-11 11:42:15 -0700722 *(void **)(&km_handle->QSEECom_set_bandwidth) =
723 dlsym(km_handle->libhandle,"QSEECom_set_bandwidth");
724 if (km_handle->QSEECom_set_bandwidth == NULL) {
725 ALOGE("dlsym: Error Loading QSEECom_set_bandwidth");
726 dlclose(km_handle->libhandle );
727 km_handle->libhandle = NULL;
728 return -1;
729 }
730
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700731 } else {
732 ALOGE("failed to load qseecom library");
733 return -1;
734 }
735 return 0;
736}
737
738/*
739 * Generic device handling
740 */
741static int qcom_km_open(const hw_module_t* module, const char* name,
742 hw_device_t** device)
743{
744 int ret = 0;
Jyoti Wadhwani391a41f2015-01-14 15:59:33 -0800745 unsigned int attempt_num = 0;
myfluxi10d15002015-11-04 00:46:09 +0100746#ifndef SKIP_WAITING_FOR_QSEE
Jyoti Wadhwani391a41f2015-01-14 15:59:33 -0800747 char property_val[PROPERTY_VALUE_MAX] = {0};
myfluxi10d15002015-11-04 00:46:09 +0100748#endif
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700749 qcom_keymaster_handle_t* km_handle;
750 if (strcmp(name, KEYSTORE_KEYMASTER) != 0)
751 return -EINVAL;
752
753 km_handle = (qcom_keymaster_handle_t *)malloc(sizeof(qcom_keymaster_handle_t));
754 if (km_handle == NULL) {
755 ALOGE("Memalloc for keymaster handle failed");
756 return -1;
757 }
758 km_handle->qseecom = NULL;
759 km_handle->libhandle = NULL;
760 ret = qcom_km_get_lib_sym(km_handle);
761 if (ret) {
762 free(km_handle);
763 return -1;
764 }
Shawn Willden7ef26052015-02-24 10:42:38 -0700765 Unique_keymaster_device_t dev(new keymaster0_device_t);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700766 if (dev.get() == NULL){
767 free(km_handle);
768 return -ENOMEM;
769 }
770 dev->context = (void *)km_handle;
Jyoti Wadhwani391a41f2015-01-14 15:59:33 -0800771 while (attempt_num < MAX_PROPERTY_GET_ATTEMPTS)
772 {
myfluxi10d15002015-11-04 00:46:09 +0100773#ifndef SKIP_WAITING_FOR_QSEE
Jyoti Wadhwani391a41f2015-01-14 15:59:33 -0800774 property_get("sys.keymaster.loaded", property_val, "");
775 if (strncmp(property_val, "true", sizeof(property_val)) == 0)
776 {
myfluxi10d15002015-11-04 00:46:09 +0100777#endif
Jyoti Wadhwani391a41f2015-01-14 15:59:33 -0800778 ALOGD("keymaster app is loaded");
779 break;
myfluxi10d15002015-11-04 00:46:09 +0100780#ifndef SKIP_WAITING_FOR_QSEE
Jyoti Wadhwani391a41f2015-01-14 15:59:33 -0800781 }
myfluxi10d15002015-11-04 00:46:09 +0100782#endif
Jyoti Wadhwani391a41f2015-01-14 15:59:33 -0800783 if (attempt_num == 0)
784 ALOGE("keymaster app is not loaded, attempt number %d", attempt_num);
785 attempt_num++;
786 sleep(PROPERTY_GET_SLEEP_INTERVAL);
787 }
788 if (attempt_num == MAX_PROPERTY_GET_ATTEMPTS)
789 {
790 ALOGE("Keymaster app not loaded: Max attempts reached");
791 free(km_handle);
792 return -1;
793 }
794 ALOGD("keymaster app got loaded at attempt number %d", attempt_num);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700795 ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
Jyoti Wadhwanicc1f7c02014-10-17 11:57:10 -0700796 "/vendor/firmware/keymaster", "keymaster", KM_SB_LENGTH);
797 if(ret)
798 ret = (*km_handle->QSEECom_start_app)((struct QSEECom_handle **)&km_handle->qseecom,
799 "/firmware/image", "keymaste", KM_SB_LENGTH);
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700800 if (ret) {
Ian Rogers3b16dc72014-01-13 20:14:51 -0800801 ALOGE("Loading keymaster app failed");
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700802 free(km_handle);
803 return -1;
804 }
805 dev->common.tag = HARDWARE_DEVICE_TAG;
806 dev->common.version = 1;
807 dev->common.module = (struct hw_module_t*) module;
808 dev->common.close = qcom_km_close;
Geremy Condra5ca7ccb2014-04-17 16:10:40 -0700809 dev->flags = KEYMASTER_BLOBS_ARE_STANDALONE;
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700810
811 dev->generate_keypair = qcom_km_generate_keypair;
812 dev->import_keypair = qcom_km_import_keypair;
813 dev->get_keypair_public = qcom_km_get_keypair_public;
814 dev->delete_keypair = NULL;
815 dev->delete_all = NULL;
816 dev->sign_data = qcom_km_sign_data;
817 dev->verify_data = qcom_km_verify_data;
818
819 *device = reinterpret_cast<hw_device_t*>(dev.release());
820
821 return 0;
822}
823
824static struct hw_module_methods_t keystore_module_methods = {
synergy dev328b6632013-11-06 18:43:39 -0800825 .open = qcom_km_open,
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700826};
827
828struct keystore_module HAL_MODULE_INFO_SYM
829__attribute__ ((visibility ("default"))) = {
synergy dev328b6632013-11-06 18:43:39 -0800830 .common = {
831 .tag = HARDWARE_MODULE_TAG,
Paul Lawrencef4191b52014-05-06 13:59:38 -0700832 .module_api_version = QCOM_KEYMASTER_API_VERSION,
833 .hal_api_version = HARDWARE_HAL_API_VERSION,
synergy dev328b6632013-11-06 18:43:39 -0800834 .id = KEYSTORE_HARDWARE_MODULE_ID,
835 .name = "Keymaster QCOM HAL",
836 .author = "The Android Open Source Project",
837 .methods = &keystore_module_methods,
838 .dso = 0,
839 .reserved = {},
Ajay Dudanifb5cdde2012-09-20 14:57:01 -0700840 },
841};