blob: 4bc09952fccdedb8dbb17cb047e864966967eaf5 [file] [log] [blame]
Shashank Mittal64d04852014-08-28 15:02:46 -07001/*
vijay kumara89b9252015-12-10 16:10:03 +05302 * Copyright (c) 2014-2016, The Linux Foundation. All rights reserved.
Shashank Mittal64d04852014-08-28 15:02:46 -07003 *
4 * Redistribution and use in source and binary forms, with or without
Sridhar Parasuram8b792422015-07-05 11:38:13 -07005 * modification, are permitted provided that the following conditions are
6 * met:
Shashank Mittal64d04852014-08-28 15:02:46 -07007 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
Sridhar Parasuram8b792422015-07-05 11:38:13 -07009 * * Redistributions in binary form must reproduce the above
10 * copyright notice, this list of conditions and the following
11 * disclaimer in the documentation and/or other materials provided
12 * with the distribution.
13 * * Neither the name of The Linux Foundation nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16
17 * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
18 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
24 * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
26 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
27 * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Shashank Mittal64d04852014-08-28 15:02:46 -070028 */
29
30#include <stdlib.h>
Channagoud Kadabi1420b002015-01-13 14:48:12 -080031#include <stdint.h>
Shashank Mittal64d04852014-08-28 15:02:46 -070032#include <crypto_hash.h>
33#include <boot_verifier.h>
34#include <image_verify.h>
35#include <mmc.h>
36#include <oem_keystore.h>
37#include <openssl/asn1t.h>
38#include <openssl/x509.h>
39#include <partition_parser.h>
40#include <rsa.h>
41#include <string.h>
Channagoud Kadabi1420b002015-01-13 14:48:12 -080042#include <openssl/err.h>
Unnati Gandhi8a7cdfe2015-05-11 13:04:20 +053043#include <platform.h>
Sridhar Parasuram8b792422015-07-05 11:38:13 -070044#include <qseecom_lk_api.h>
45#include <secapp_loader.h>
46#include <target.h>
Channagoud Kadabi86b0c112016-03-16 19:23:16 -070047#include "bootimg.h"
Shashank Mittal64d04852014-08-28 15:02:46 -070048
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -070049#define ASN1_ENCODED_SHA256_SIZE 0x33
50#define ASN1_ENCODED_SHA256_OFFSET 0x13
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -070051#define ASN1_SIGNATURE_BUFFER_SZ mmc_page_size()
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -070052
Shashank Mittal64d04852014-08-28 15:02:46 -070053static KEYSTORE *oem_keystore;
54static KEYSTORE *user_keystore;
55static uint32_t dev_boot_state = RED;
Shashank Mittal64d04852014-08-28 15:02:46 -070056char KEYSTORE_PTN_NAME[] = "keystore";
Sridhar Parasuram8b792422015-07-05 11:38:13 -070057RSA *rsa_from_cert = NULL;
lijuangf214e222015-07-16 20:06:22 +080058unsigned char fp[EVP_MAX_MD_SIZE];
59uint32_t fp_size;
Channagoud Kadabi86b0c112016-03-16 19:23:16 -070060#if OSVERSION_IN_BOOTIMAGE
61km_boot_state_t boot_state_info;
62#endif
Shashank Mittal64d04852014-08-28 15:02:46 -070063
64ASN1_SEQUENCE(AUTH_ATTR) ={
65 ASN1_SIMPLE(AUTH_ATTR, target, ASN1_PRINTABLESTRING),
66 ASN1_SIMPLE(AUTH_ATTR, len, ASN1_INTEGER)
67} ASN1_SEQUENCE_END(AUTH_ATTR)
68IMPLEMENT_ASN1_FUNCTIONS(AUTH_ATTR)
69
70 ASN1_SEQUENCE(VERIFIED_BOOT_SIG) = {
71 ASN1_SIMPLE(VERIFIED_BOOT_SIG, version, ASN1_INTEGER),
Unnati Gandhi93334992015-02-25 19:38:38 +053072 ASN1_SIMPLE(VERIFIED_BOOT_SIG, certificate, X509),
Shashank Mittal64d04852014-08-28 15:02:46 -070073 ASN1_SIMPLE(VERIFIED_BOOT_SIG, algor, X509_ALGOR),
74 ASN1_SIMPLE(VERIFIED_BOOT_SIG, auth_attr, AUTH_ATTR),
75 ASN1_SIMPLE(VERIFIED_BOOT_SIG, sig, ASN1_OCTET_STRING)
76 } ASN1_SEQUENCE_END(VERIFIED_BOOT_SIG)
77IMPLEMENT_ASN1_FUNCTIONS(VERIFIED_BOOT_SIG)
78
79 ASN1_SEQUENCE(KEY) = {
80 ASN1_SIMPLE(KEY, algorithm_id, X509_ALGOR),
81 ASN1_SIMPLE(KEY, key_material, RSAPublicKey)
82 }ASN1_SEQUENCE_END(KEY)
83IMPLEMENT_ASN1_FUNCTIONS(KEY);
84
85ASN1_SEQUENCE(KEYBAG) = {
86 ASN1_SIMPLE(KEYBAG, mykey, KEY)
87}ASN1_SEQUENCE_END(KEYBAG)
88IMPLEMENT_ASN1_FUNCTIONS(KEYBAG)
89
90 ASN1_SEQUENCE(KEYSTORE_INNER) = {
91 ASN1_SIMPLE(KEYSTORE_INNER, version, ASN1_INTEGER),
92 ASN1_SIMPLE(KEYSTORE_INNER, mykeybag, KEYBAG)
93 } ASN1_SEQUENCE_END(KEYSTORE_INNER)
94IMPLEMENT_ASN1_FUNCTIONS(KEYSTORE_INNER)
95
96 ASN1_SEQUENCE(KEYSTORE) = {
97 ASN1_SIMPLE(KEYSTORE, version, ASN1_INTEGER),
98 ASN1_SIMPLE(KEYSTORE, mykeybag, KEYBAG),
99 ASN1_SIMPLE(KEYSTORE, sig, VERIFIED_BOOT_SIG)
100 } ASN1_SEQUENCE_END(KEYSTORE)
101IMPLEMENT_ASN1_FUNCTIONS(KEYSTORE)
102
P.V. Phani Kumarbbe8c8e2016-03-09 19:43:24 +0530103uint32_t read_der_message_length(unsigned char* input, unsigned sz)
Shashank Mittal64d04852014-08-28 15:02:46 -0700104{
105 uint32_t len = 0;
Gaurav Nebhwanic7313cc2015-12-15 22:25:04 +0530106 uint32_t pos = 0;
Shashank Mittal64d04852014-08-28 15:02:46 -0700107 uint8_t len_bytes = 1;
108
109 /* Check if input starts with Sequence id (0X30) */
Gaurav Nebhwanic7313cc2015-12-15 22:25:04 +0530110 if(sz < 3 || input[pos] != 0x30)
Shashank Mittal64d04852014-08-28 15:02:46 -0700111 return len;
112 pos++;
113
114 /* A length of 0xAABBCCDD in DER encoded messages would be sequence of
115 following octets 0xAA, 0xBB, 0XCC, 0XDD.
116
117 To read length - read each octet and shift left by 1 octect before
118 reading next octet.
119 */
120 /* check if short or long length form */
121 if(input[pos] & 0x80)
122 {
123 len_bytes = (input[pos] & ~(0x80));
124 pos++;
125 }
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700126
Shashank Mittal64d04852014-08-28 15:02:46 -0700127 while(len_bytes)
128 {
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700129 /* Shift len by 1 octet, make sure to check unsigned int overflow */
130 if (len <= (UINT_MAX >> 8))
131 len <<= 8;
132 else
133 {
134 dprintf(CRITICAL, "Error: Length exceeding max size of uintmax\n");
135 return 0;
136 }
Shashank Mittal64d04852014-08-28 15:02:46 -0700137
138 /* Read next octet */
Gaurav Nebhwanic7313cc2015-12-15 22:25:04 +0530139 if (pos < (uint32_t) ASN1_SIGNATURE_BUFFER_SZ && pos < sz)
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700140 len = len | input[pos];
141 else
142 {
143 dprintf(CRITICAL, "Error: Pos index exceeding the input buffer size\n");
144 return 0;
145 }
146
Shashank Mittal64d04852014-08-28 15:02:46 -0700147 pos++; len_bytes--;
148 }
149
150 /* Add number of octets representing sequence id and length */
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700151 if ((UINT_MAX - pos) > len)
152 len += pos;
153 else
154 {
155 dprintf(CRITICAL, "Error: Len overflows UINT_MAX value\n");
156 return 0;
157 }
Shashank Mittal64d04852014-08-28 15:02:46 -0700158
159 return len;
160}
161
Shashank Mittal64d04852014-08-28 15:02:46 -0700162static int add_attribute_to_img(unsigned char *ptr, AUTH_ATTR *input)
163{
164 return i2d_AUTH_ATTR(input, &ptr);
165}
166
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700167bool boot_verify_compare_sha256(unsigned char *image_ptr,
Shashank Mittal64d04852014-08-28 15:02:46 -0700168 unsigned int image_size, unsigned char *signature_ptr, RSA *rsa)
169{
170 int ret = -1;
171 bool auth = false;
172 unsigned char *plain_text = NULL;
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700173
174 /* The magic numbers here are drawn from the PKCS#1 standard and are the ASN.1
175 *encoding of the SHA256 object identifier that is required for a PKCS#1
176 * signature.*/
177 uint8_t digest[ASN1_ENCODED_SHA256_SIZE] = {0x30, 0x31, 0x30, 0x0d, 0x06,
178 0x09, 0x60, 0x86, 0x48, 0x01,
179 0x65, 0x03, 0x04, 0x02, 0x01,
180 0x05, 0x00, 0x04, 0x20};
Shashank Mittal64d04852014-08-28 15:02:46 -0700181
182 plain_text = (unsigned char *)calloc(sizeof(char), SIGNATURE_SIZE);
183 if (plain_text == NULL) {
184 dprintf(CRITICAL, "boot_verifier: Calloc failed during verification\n");
185 goto cleanup;
186 }
187
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700188 /* Calculate SHA256 of image and place it into the ASN.1 structure*/
Shashank Mittal64d04852014-08-28 15:02:46 -0700189 image_find_digest(image_ptr, image_size, CRYPTO_AUTH_ALG_SHA256,
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700190 digest + ASN1_ENCODED_SHA256_OFFSET);
Shashank Mittal64d04852014-08-28 15:02:46 -0700191
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700192 /* Find digest from the image. This performs the PKCS#1 padding checks up to
193 * but not including the ASN.1 OID and hash function check. The return value
194 * is not positive for a failure or the length of the part after the padding */
Shashank Mittal64d04852014-08-28 15:02:46 -0700195 ret = image_decrypt_signature_rsa(signature_ptr, plain_text, rsa);
196
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700197 /* Make sure the length returned from rsa decrypt is same as x509 signature format
198 * otherwise the signature is invalid and we fail
199 */
200 if (ret != ASN1_ENCODED_SHA256_SIZE)
201 {
202 dprintf(CRITICAL, "boot_verifier: Signature decrypt failed! Signature invalid = %d\n",
Shashank Mittal64d04852014-08-28 15:02:46 -0700203 ret);
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700204 goto cleanup;
205 }
206 /* So plain_text contains the ASN.1 encoded hash from the signature and
207 * digest contains the value that this should be for the image that we're
208 * verifying, so compare them.*/
Shashank Mittal64d04852014-08-28 15:02:46 -0700209
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700210 ret = memcmp(plain_text, digest, ASN1_ENCODED_SHA256_SIZE);
Shashank Mittal64d04852014-08-28 15:02:46 -0700211 if(ret == 0)
212 {
213 auth = true;
Sridhar Parasuramb27e47c2015-05-27 14:33:54 -0700214#ifdef TZ_SAVE_KERNEL_HASH
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700215 save_kernel_hash((unsigned char *) digest + ASN1_ENCODED_SHA256_OFFSET, CRYPTO_AUTH_ALG_SHA256);
Sridhar Parasuramb27e47c2015-05-27 14:33:54 -0700216#endif
Shashank Mittal64d04852014-08-28 15:02:46 -0700217 }
218
219cleanup:
220 if (plain_text != NULL)
221 free(plain_text);
222 EVP_cleanup();
223 CRYPTO_cleanup_all_ex_data();
224 ERR_remove_thread_state(NULL);
225 return auth;
226
227}
228
229static bool verify_image_with_sig(unsigned char* img_addr, uint32_t img_size,
230 char *pname, VERIFIED_BOOT_SIG *sig, KEYSTORE *ks)
231{
232 bool ret = false;
233 uint32_t len;
234 int shift_bytes;
235 RSA *rsa = NULL;
236 bool keystore_verification = false;
Sridhar Parasuram8b792422015-07-05 11:38:13 -0700237 EVP_PKEY* key = NULL;
vijay kumar9fe95642015-12-14 14:14:20 +0530238 int attr = 0;
Shashank Mittal64d04852014-08-28 15:02:46 -0700239
240 if(!strcmp(pname, "keystore"))
241 keystore_verification = true;
242
243 /* Verify target name */
244 if(strncmp((char*)(sig->auth_attr->target->data), pname,
245 sig->auth_attr->target->length) ||
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800246 (strlen(pname) != (unsigned long) sig->auth_attr->target->length))
Shashank Mittal64d04852014-08-28 15:02:46 -0700247 {
248 dprintf(CRITICAL,
249 "boot_verifier: verification failure due to target name mismatch\n");
250 goto verify_image_with_sig_error;
251 }
Shashank Mittal64d04852014-08-28 15:02:46 -0700252 /* Read image size from signature */
253 /* A len = 0xAABBCC (represented by 3 octets) would be stored in
254 len->data as 0X00CCBBAA and len->length as 3(octets).
255
256 To read len we need to left shift data to number of missing octets and
257 then change it to host long
258 */
259 len = *((uint32_t*)sig->auth_attr->len->data);
260 shift_bytes = sizeof(uint32_t) - sig->auth_attr->len->length;
261 if(shift_bytes > 0) {
262 len = len << (shift_bytes*8);
263 }
264 len = ntohl(len);
265
266 /* Verify image size*/
267 if(len != img_size)
268 {
269 dprintf(CRITICAL,
270 "boot_verifier: image length is different. (%d vs %d)\n",
271 len, img_size);
272 goto verify_image_with_sig_error;
273 }
274
275 /* append attribute to image */
276 if(!keystore_verification)
Sridhar Parasuram8b792422015-07-05 11:38:13 -0700277 {
278 // verifying a non keystore partition
vijay kumar9fe95642015-12-14 14:14:20 +0530279 attr = add_attribute_to_img((unsigned char*)(img_addr + img_size),
Shashank Mittal64d04852014-08-28 15:02:46 -0700280 sig->auth_attr);
vijay kumar9fe95642015-12-14 14:14:20 +0530281 if (img_size > (UINT_MAX - attr))
282 {
283 dprintf(CRITICAL,"Interger overflow detected\n");
284 ASSERT(0);
285 }
286 else img_size += attr;
Sridhar Parasuram8b792422015-07-05 11:38:13 -0700287 }
Shashank Mittal64d04852014-08-28 15:02:46 -0700288
289 /* compare SHA256SUM of image with value in signature */
290 if(ks != NULL)
Shashank Mittal64d04852014-08-28 15:02:46 -0700291 {
Sridhar Parasuram8b792422015-07-05 11:38:13 -0700292 // use rsa from keystore
293 rsa = ks->mykeybag->mykey->key_material;
294 }
295 else
296 {
297 dprintf(CRITICAL, "%s:%d: Keystore is null\n", __func__, __LINE__);
298 ASSERT(0);
299 }
300
301 // verify boot.img with rsa from oem keystore
302 if((ret = boot_verify_compare_sha256(img_addr, img_size,
303 (unsigned char*)sig->sig->data, rsa)))
304
305 {
306 dprintf(SPEW, "Verified boot.img with oem keystore\n");
307 boot_verify_send_event(BOOTIMG_KEYSTORE_VERIFICATION_PASS);
308 goto verify_image_with_sig_done;
309 }
310 else
311 {
312 dprintf(INFO, "Verification with oem keystore failed. Use embedded certificate for verification\n");
313 // get the public key from certificate in boot.img
314 if ((key = X509_get_pubkey(sig->certificate)))
315 {
316 // convert to rsa key format
317 dprintf(INFO, "RSA KEY found from the embedded certificate\n");
318 rsa = EVP_PKEY_get1_RSA(key);
319 rsa_from_cert = rsa;
320 }
321 else
322 {
323 dprintf(CRITICAL, "Unable to extract public key from certificate\n");
324 ASSERT(0);
325 }
326 }
327
328 // verify boot.img with rsa from embedded certificate
329 if ((ret = boot_verify_compare_sha256(img_addr, img_size,
330 (unsigned char*)sig->sig->data, rsa)))
331 {
332 dprintf(SPEW, "Verified boot.img with embedded certificate in boot image\n");
333 boot_verify_send_event(BOOTIMG_EMBEDDED_CERT_VERIFICATION_PASS);
334 goto verify_image_with_sig_done;
335 }
336 else
337 {
338 dprintf(INFO, "verified for red state\n");
339 boot_verify_send_event(BOOTIMG_VERIFICATION_FAIL);
340 goto verify_image_with_sig_done;
Shashank Mittal64d04852014-08-28 15:02:46 -0700341 }
342
343verify_image_with_sig_error:
Kishor PK5dac4312016-12-02 17:02:47 +0530344 boot_verify_send_event(BOOTIMG_VERIFICATION_FAIL);
Sridhar Parasuram8b792422015-07-05 11:38:13 -0700345verify_image_with_sig_done:
Shashank Mittal64d04852014-08-28 15:02:46 -0700346 return ret;
347}
348
349static int encode_inner_keystore(unsigned char *ptr, KEYSTORE *ks)
350{
351 int ret = 0;
352 KEYSTORE_INNER *ks_inner = KEYSTORE_INNER_new();
353 if (ks_inner == NULL)
354 return ret;
355 ASN1_INTEGER *tmp_version = ks_inner->version;
356 KEYBAG *tmp_mykeybag = ks_inner->mykeybag;
357
358 ks_inner->version = ks->version;
359 ks_inner->mykeybag = ks->mykeybag;
360 ret = i2d_KEYSTORE_INNER(ks_inner, &ptr);
361
362 ks_inner->version = tmp_version;
363 ks_inner->mykeybag = tmp_mykeybag;
364
365 if(ks_inner != NULL)
366 KEYSTORE_INNER_free(ks_inner);
367 return ret;
368}
369
370static bool verify_keystore(unsigned char * ks_addr, KEYSTORE *ks)
371{
372 bool ret = false;
373 unsigned char * ptr = ks_addr;
374 uint32_t inner_len = encode_inner_keystore(ptr, ks);
375 ret = verify_image_with_sig(ks_addr, inner_len, "keystore", ks->sig,
376 oem_keystore);
377 return ret;
378}
379
380static void read_oem_keystore()
381{
Shashank Mittale6797222014-09-19 18:58:43 -0700382 KEYSTORE *ks = NULL;
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700383 uint32_t len = sizeof(OEM_KEYSTORE);
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800384 const unsigned char *input = OEM_KEYSTORE;
Shashank Mittale6797222014-09-19 18:58:43 -0700385
Shashank Mittal64d04852014-08-28 15:02:46 -0700386 if(oem_keystore != NULL)
387 return;
388
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800389 ks = d2i_KEYSTORE(NULL, (const unsigned char **) &input, len);
Shashank Mittal64d04852014-08-28 15:02:46 -0700390 if(ks != NULL)
391 {
392 oem_keystore = ks;
393 user_keystore = ks;
394 }
395}
396
Shashank Mittal64d04852014-08-28 15:02:46 -0700397uint32_t boot_verify_keystore_init()
398{
399 /* Read OEM Keystore */
400 read_oem_keystore();
401
Shashank Mittal64d04852014-08-28 15:02:46 -0700402 return dev_boot_state;
403}
404
Channagoud Kadabi86b0c112016-03-16 19:23:16 -0700405#if OSVERSION_IN_BOOTIMAGE
406static void boot_verify_send_boot_state(km_boot_state_t *boot_state)
407{
408 km_get_version_req_t version_req;
409 km_get_version_rsp_t version_rsp;
410 int ret;
411 int app_handle = get_secapp_handle();
412 km_set_boot_state_req_t *bs_req = NULL;
413 km_set_boot_state_rsp_t boot_state_rsp;
414 uint8_t *boot_state_ptr;
415
416 version_req.cmd_id = KEYMASTER_GET_VERSION;
417 ret = qseecom_send_command(app_handle, (void*) &version_req, sizeof(version_req), (void*) &version_rsp, sizeof(version_rsp));
418 if (ret < 0 || version_rsp.status < 0)
419 {
420 dprintf(CRITICAL, "QSEEcom command for getting keymaster version returned error: %d\n", version_rsp.status);
421 ASSERT(0);
422 }
423
Mohamed Sunfeer9da93e52018-09-06 15:56:41 +0530424 if (version_rsp.major_version >= 0x2)
Channagoud Kadabi86b0c112016-03-16 19:23:16 -0700425 {
426 bs_req = malloc(sizeof(km_set_boot_state_req_t) + sizeof(km_boot_state_t));
427 ASSERT(bs_req);
428
429 boot_state_ptr = (uint8_t *) bs_req + sizeof(km_set_boot_state_req_t);
430 /* copy the boot state data */
431 memscpy(boot_state_ptr, sizeof(km_boot_state_t), &boot_state_info, sizeof(boot_state_info));
432
433 bs_req->cmd_id = KEYMASTER_SET_BOOT_STATE;
434 bs_req->version = 0x0;
435 bs_req->boot_state_offset = sizeof(km_set_boot_state_req_t);
436 bs_req->boot_state_size = sizeof(km_boot_state_t);
437
438 ret = qseecom_send_command(app_handle, (void *)bs_req, sizeof(*bs_req) + sizeof(km_boot_state_t), (void *) &boot_state_rsp, sizeof(boot_state_rsp));
439 if (ret < 0 || boot_state_rsp.status < 0)
440 {
441 dprintf(CRITICAL, "QSEEcom command for Sending boot state returned error: %d\n", boot_state_rsp.status);
442 free(bs_req);
443 ASSERT(0);
444 }
445 }
446
447 if (bs_req)
448 free(bs_req);
449}
450#endif
451
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700452bool send_rot_command(uint32_t is_unlocked)
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700453{
454 int ret = 0;
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700455 unsigned char *input = NULL;
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700456 char *rot_input = NULL;
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700457 unsigned int digest[9] = {0}, final_digest[8] = {0};
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700458 uint32_t auth_algo = CRYPTO_AUTH_ALG_SHA256;
459 uint32_t boot_device_state = boot_verify_get_state();
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700460 int app_handle = 0;
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700461 uint32_t len_oem_rsa = 0, len_from_cert = 0;
Monika Singh5a2f7de2018-03-16 16:57:44 +0530462 km_set_rot_req_t *read_req = NULL;
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700463 km_set_rot_rsp_t read_rsp;
464 app_handle = get_secapp_handle();
Monika Singh98257462018-06-06 11:28:49 +0530465 uint32_t version = 0;
466
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700467 int n = 0, e = 0;
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700468 switch (boot_device_state)
469 {
470 case GREEN:
471 // Locked device and boot.img verified against OEM keystore.
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700472 // Send hash of key from OEM KEYSTORE + Boot device state
473 n = BN_num_bytes(oem_keystore->mykeybag->mykey->key_material->n);
474 e = BN_num_bytes(oem_keystore->mykeybag->mykey->key_material->e);
vijay kumara89b9252015-12-10 16:10:03 +0530475 /*this assumes a valid acceptable range for RSA, including 4096 bits of modulo n. */
476 if (n<0 || n>1024)
477 {
478 dprintf(CRITICAL, "Invalid n value from key_material\n");
479 ASSERT(0);
480 }
481 /* e can assumes 3,5,17,257,65537 as valid values, which should be 1 byte long only, we accept 2 bytes or 16 bits long */
482 if( e < 0 || e >16)
483 {
484 dprintf(CRITICAL, "Invalid e value from key_material\n");
485 ASSERT(0);
486 }
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700487 len_oem_rsa = n + e;
488 if(!(input = malloc(len_oem_rsa)))
489 {
490 dprintf(CRITICAL, "Failed to allocate memory for ROT structure\n");
491 ASSERT(0);
492 }
493 BN_bn2bin(oem_keystore->mykeybag->mykey->key_material->n, input);
494 BN_bn2bin(oem_keystore->mykeybag->mykey->key_material->e, input+n);
495 hash_find((unsigned char *)input, len_oem_rsa, (unsigned char *) &digest, auth_algo);
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700496 digest[8] = is_unlocked;
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700497 break;
498 case YELLOW:
499 case RED:
500 // Locked device and boot.img passed (yellow) or failed (red) verification with the certificate embedded to the boot.img.
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700501 if (!rsa_from_cert)
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700502 {
503 dprintf(CRITICAL, "RSA is null from the embedded certificate\n");
504 ASSERT(0);
505 }
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700506 // Send hash of key from certificate in boot image + boot device state
507 n = BN_num_bytes(rsa_from_cert->n);
508 e = BN_num_bytes(rsa_from_cert->e);
vijay kumara89b9252015-12-10 16:10:03 +0530509 /*this assumes a valid acceptable range for RSA, including 4096 bits of modulo n. */
510 if (n<0 || n>1024)
511 {
512 dprintf(CRITICAL, "Invalid n value from rsa_from_cert\n");
513 ASSERT(0);
514 }
515 /* e can assumes 3,5,17,257,65537 as valid values, which should be 1 byte long only, we accept 2 bytes or 16 bits long */
516 if( e < 0 || e >16)
517 {
518 dprintf(CRITICAL, "Invalid e value from rsa_from_cert\n");
519 ASSERT(0);
520 }
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700521 len_from_cert = n + e;
522 if(!(input = malloc(len_from_cert)))
523 {
524 dprintf(CRITICAL, "Failed to allocate memory for ROT structure\n");
525 ASSERT(0);
526 }
527 BN_bn2bin(rsa_from_cert->n, input);
528 BN_bn2bin(rsa_from_cert->e, input+n);
529 hash_find((unsigned char *)input, len_from_cert, (unsigned char *) &digest, auth_algo);
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700530 digest[8] = is_unlocked;
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700531 break;
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700532 case ORANGE:
533 // Unlocked device and no verification done.
534 // Send the hash of boot device state
535 input = NULL;
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700536 digest[0] = is_unlocked;
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700537 break;
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700538 }
539
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700540 hash_find((unsigned char *) digest, sizeof(digest), (unsigned char *)&final_digest, auth_algo);
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700541 dprintf(SPEW, "Digest: ");
542 for(uint8_t i = 0; i < 8; i++)
543 dprintf(SPEW, "0x%x ", final_digest[i]);
544 dprintf(SPEW, "\n");
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700545 if(!(read_req = malloc(sizeof(km_set_rot_req_t) + sizeof(final_digest))))
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700546 {
547 dprintf(CRITICAL, "Failed to allocate memory for ROT structure\n");
548 ASSERT(0);
549 }
550
551 void *cpy_ptr = (uint8_t *) read_req + sizeof(km_set_rot_req_t);
552 // set ROT stucture
553 read_req->cmd_id = KEYMASTER_SET_ROT;
554 read_req->rot_ofset = (uint32_t) sizeof(km_set_rot_req_t);
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700555 read_req->rot_size = sizeof(final_digest);
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700556 // copy the digest
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700557 memcpy(cpy_ptr, (void *) &final_digest, sizeof(final_digest));
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700558 dprintf(SPEW, "Sending Root of Trust to trustzone: start\n");
559
Sridhar Parasuram96300dc2015-06-11 10:37:11 -0700560 ret = qseecom_send_command(app_handle, (void*) read_req, sizeof(km_set_rot_req_t) + sizeof(final_digest), (void*) &read_rsp, sizeof(read_rsp));
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700561 if (ret < 0 || read_rsp.status < 0)
562 {
563 dprintf(CRITICAL, "QSEEcom command for Sending Root of Trust returned error: %d\n", read_rsp.status);
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700564 if(input)
565 free(input);
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700566 free(read_req);
567 free(rot_input);
568 return false;
569 }
Channagoud Kadabi86b0c112016-03-16 19:23:16 -0700570
571#if OSVERSION_IN_BOOTIMAGE
572 boot_state_info.is_unlocked = is_unlocked;
573 boot_state_info.color = boot_verify_get_state();
574 memscpy(boot_state_info.public_key, sizeof(boot_state_info.public_key), digest, 32);
575 boot_verify_send_boot_state(&boot_state_info);
576#endif
Monika Singh98257462018-06-06 11:28:49 +0530577 if ( is_secure_boot_enable()
578 && (dev_boot_state != GREEN))
579 {
580 version = qseecom_get_version();
581 if(allow_set_fuse(version)) {
582 ret = set_tamper_fuse_cmd(HLOS_IMG_TAMPER_FUSE);
583 if (ret) {
584 ret = false;
585 goto err;
586 }
587 ret = set_tamper_fuse_cmd(HLOS_TAMPER_NOTIFY_FUSE);
588 if (ret) {
Monika Singh475a3952018-06-27 14:29:43 +0530589 dprintf(CRITICAL, "send_rot_command: set_tamper_fuse_cmd (TZ_HLOS_TAMPER_NOTIFY_FUSE) fails!\n");
Monika Singh98257462018-06-06 11:28:49 +0530590 ret = false;
591 goto err;
592 }
593 } else {
Monika Singh475a3952018-06-27 14:29:43 +0530594 dprintf(CRITICAL, "send_rot_command: TZ didn't support this feature! Version: major = %d, minor = %d, patch = %d\n", (version >> 22) & 0x3FF, (version >> 12) & 0x3FF, version & 0x3FF);
Monika Singh98257462018-06-06 11:28:49 +0530595 ret = false;
596 goto err;
597 }
598 }
599 dprintf(CRITICAL, "Sending Root of Trust to trustzone: end\n");
600 ret = true;
601err:
Sridhar Parasuram24fb3952015-08-26 20:25:59 -0700602 if(input)
603 free(input);
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700604 free(read_req);
605 free(rot_input);
Monika Singh98257462018-06-06 11:28:49 +0530606 return ret;
Sridhar Parasuram00bfedb2015-05-26 14:21:27 -0700607}
608
lijuangf214e222015-07-16 20:06:22 +0800609unsigned char* get_boot_fingerprint(unsigned int* buf_size)
610{
611 *buf_size = fp_size;
612
613 return fp;
614}
615
Monika Singh5a2f7de2018-03-16 16:57:44 +0530616bool boot_verify_image(unsigned char* img_addr, uint32_t img_size, char *pname,
617 uint32_t *bootstate)
Shashank Mittal64d04852014-08-28 15:02:46 -0700618{
619 bool ret = false;
lijuangf214e222015-07-16 20:06:22 +0800620 X509 *cert = NULL;
621 const EVP_MD *fp_type = NULL;
Shashank Mittal64d04852014-08-28 15:02:46 -0700622 VERIFIED_BOOT_SIG *sig = NULL;
623 unsigned char* sig_addr = (unsigned char*)(img_addr + img_size);
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700624 uint32_t sig_len = 0;
625 unsigned char *signature = NULL;
Shashank Mittal64d04852014-08-28 15:02:46 -0700626
627 if(dev_boot_state == ORANGE)
628 {
629 dprintf(INFO, "boot_verifier: Device is in ORANGE boot state.\n");
630 dprintf(INFO, "boot_verifier: Skipping boot verification.\n");
631 return false;
632 }
633
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700634 signature = malloc(ASN1_SIGNATURE_BUFFER_SZ);
635 ASSERT(signature);
636
637 /* Copy the signature from scratch memory to buffer */
638 memcpy(signature, sig_addr, ASN1_SIGNATURE_BUFFER_SZ);
Gaurav Nebhwanic7313cc2015-12-15 22:25:04 +0530639 sig_len = read_der_message_length(signature, ASN1_SIGNATURE_BUFFER_SZ);
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700640
Shashank Mittal64d04852014-08-28 15:02:46 -0700641 if(!sig_len)
642 {
Sridhar Parasuram8b792422015-07-05 11:38:13 -0700643 dprintf(CRITICAL, "boot_verifier: Error while reading signature length.\n");
Sridhar Parasuramf391ec92015-08-27 14:01:42 -0700644 ASSERT(0);
Shashank Mittal64d04852014-08-28 15:02:46 -0700645 }
646
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700647 if (sig_len > ASN1_SIGNATURE_BUFFER_SZ)
648 {
649 dprintf(CRITICAL, "boot_verifier: Signature length exceeds size signature buffer\n");
650 goto verify_image_error;
651 }
652
Channagoud Kadabicda7e9b2015-09-17 13:25:35 -0700653 if (sig_len > ASN1_SIGNATURE_BUFFER_SZ)
654 {
655 dprintf(CRITICAL, "boot_verifier: Signature length exceeds size signature buffer\n");
656 goto verify_image_error;
657 }
658
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800659 if((sig = d2i_VERIFIED_BOOT_SIG(NULL, (const unsigned char **) &sig_addr, sig_len)) == NULL)
Shashank Mittal64d04852014-08-28 15:02:46 -0700660 {
661 dprintf(CRITICAL,
662 "boot_verifier: verification failure due to target name mismatch\n");
Sridhar Parasuramf391ec92015-08-27 14:01:42 -0700663 ASSERT(0);
Shashank Mittal64d04852014-08-28 15:02:46 -0700664 }
665
lijuangf214e222015-07-16 20:06:22 +0800666 cert = sig->certificate;
667 fp_type = EVP_sha1();
668 if(!X509_digest(cert, fp_type, (unsigned char *)fp, &fp_size)) {
669 dprintf(INFO,"Fail to create certificate fingerprint.\n");
670 }
671
Shashank Mittal64d04852014-08-28 15:02:46 -0700672 ret = verify_image_with_sig(img_addr, img_size, pname, sig, user_keystore);
673
Shashank Mittal64d04852014-08-28 15:02:46 -0700674 if(sig != NULL)
675 VERIFIED_BOOT_SIG_free(sig);
Monika Singh0f7bfc82018-04-16 23:14:29 +0530676
Monika Singh5a2f7de2018-03-16 16:57:44 +0530677 if(bootstate == NULL)
678 goto verify_image_error;
Monika Singh0f7bfc82018-04-16 23:14:29 +0530679 *bootstate = dev_boot_state;
Monika Singh5a2f7de2018-03-16 16:57:44 +0530680
Channagoud Kadabibf6ce7d2015-09-17 13:25:35 -0700681verify_image_error:
682 free(signature);
Shashank Mittal64d04852014-08-28 15:02:46 -0700683 return ret;
684}
685
686void boot_verify_send_event(uint32_t event)
687{
688 switch(event)
689 {
690 case BOOT_INIT:
691 dev_boot_state = GREEN;
692 break;
Sridhar Parasuram8b792422015-07-05 11:38:13 -0700693 case BOOTIMG_KEYSTORE_VERIFICATION_PASS:
694 dev_boot_state = GREEN;
695 break;
696 case BOOTIMG_EMBEDDED_CERT_VERIFICATION_PASS:
Shashank Mittal64d04852014-08-28 15:02:46 -0700697 if(dev_boot_state == GREEN)
698 dev_boot_state = YELLOW;
699 break;
Sridhar Parasuram8b792422015-07-05 11:38:13 -0700700 case BOOTIMG_VERIFICATION_FAIL:
Shashank Mittal64d04852014-08-28 15:02:46 -0700701 if(dev_boot_state == GREEN || dev_boot_state == YELLOW)
702 dev_boot_state = RED;
703 break;
704 case DEV_UNLOCK:
705 dev_boot_state = ORANGE;
706 break;
707 case USER_DENIES:
708 if(dev_boot_state == YELLOW || dev_boot_state == ORANGE)
709 dev_boot_state = RED;
710 break;
711 }
712}
713
714uint32_t boot_verify_get_state()
715{
716 return dev_boot_state;
717}
718
719void boot_verify_print_state()
720{
721 switch(dev_boot_state)
722 {
723 case GREEN:
724 dprintf(INFO, "boot_verifier: Device is in GREEN boot state.\n");
725 break;
726 case ORANGE:
727 dprintf(INFO, "boot_verifier: Device is in ORANGE boot state.\n");
728 break;
729 case YELLOW:
730 dprintf(INFO, "boot_verifier: Device is in YELLOW boot state.\n");
731 break;
732 case RED:
Unnati Gandhi8a7cdfe2015-05-11 13:04:20 +0530733 display_fbcon_message("Security Error: This phone has been flashed with unauthorized software & is locked. Call your mobile operator for additional support.Please note that repair/return for this issue may have additional cost.\n");
734
Shashank Mittal64d04852014-08-28 15:02:46 -0700735 dprintf(INFO, "boot_verifier: Device is in RED boot state.\n");
736 break;
737 }
738}
739
Gaurav Nebhwanic7313cc2015-12-15 22:25:04 +0530740bool boot_verify_validate_keystore(unsigned char * user_addr, unsigned sz)
Shashank Mittal64d04852014-08-28 15:02:46 -0700741{
742 bool ret = false;
743 unsigned char *input = user_addr;
Shashank Mittale6797222014-09-19 18:58:43 -0700744 KEYSTORE *ks = NULL;
Gaurav Nebhwanic7313cc2015-12-15 22:25:04 +0530745 uint32_t len = read_der_message_length(input, sz);
mohamed sunfeer4fc5b962017-08-23 00:29:45 +0530746 if((!len) || (sz < len))
Shashank Mittale6797222014-09-19 18:58:43 -0700747 {
748 dprintf(CRITICAL, "boot_verifier: keystore length is invalid.\n");
749 return ret;
750 }
751
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800752 ks = d2i_KEYSTORE(NULL, (const unsigned char **)&input, len);
Shashank Mittal64d04852014-08-28 15:02:46 -0700753 if(ks != NULL)
754 {
755 ret = true;
756 }
757 return ret;
758}
759
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800760static bool check_list(const char **list, const char* entry)
Shashank Mittal64d04852014-08-28 15:02:46 -0700761{
Shashank Mittal64d04852014-08-28 15:02:46 -0700762 if(list == NULL || entry == NULL)
763 return false;
764
765 while(*list != NULL)
766 {
767 if(!strcmp(entry, *list))
768 return true;
769
770 list++;
771 }
772
773 return false;
774}
775
Channagoud Kadabi583ea4c2015-09-08 14:55:09 -0700776KEYSTORE *boot_gerity_get_oem_keystore()
777{
778 read_oem_keystore();
779 return oem_keystore;
780}
Brahmaji K708fc502017-08-07 21:08:04 +0530781
782#if OSVERSION_IN_BOOTIMAGE
783void set_os_version(unsigned char* img_addr)
784{
Mayank Grover3dcc95b2018-09-04 20:31:38 +0530785 boot_img_hdr *img_hdr = NULL;
Brahmaji K708fc502017-08-07 21:08:04 +0530786
787 /* Extract the os version and patch level */
788 if (img_addr) {
Mayank Grover3dcc95b2018-09-04 20:31:38 +0530789 img_hdr = (boot_img_hdr *)img_addr;
Brahmaji K708fc502017-08-07 21:08:04 +0530790 boot_state_info.system_version = (img_hdr->os_version & 0xFFFFF800) >> 11;
791 boot_state_info.system_security_level = (img_hdr->os_version & 0x7FF);
792 } else {
793 dprintf(CRITICAL, "Image address should not be NULL\n");
794 }
795}
796#else
797void set_os_version(unsigned char* img_addr)
798{
799 return;
800}
801#endif
Monika Singh0b15c022019-04-10 15:24:20 +0530802
803int set_verified_boot_hash (const char *vbh, size_t vbh_size)
804{
805 int ret = 0;
806 km_set_vbh_req_t vbh_req = {0};
807 km_set_vbh_rsp_t vbh_rsp = {0};
808 int app_handle = get_secapp_handle();
809
810 if (!vbh || vbh_size != sizeof (vbh_req.vbh)) {
811 dprintf(CRITICAL, "Vbh input params invalid\n");
812 ASSERT(0);
813 }
814 vbh_req.cmd_id = KEYMASTER_SET_VBH;
815 memscpy (vbh_req.vbh, sizeof(vbh_req.vbh), vbh, vbh_size);
816 ret = qseecom_send_command (app_handle, (void *)&vbh_req, sizeof (vbh_req), (void *)&vbh_rsp, sizeof (vbh_rsp));
817
818 if (ret != 0 || vbh_rsp.status != 0) {
819 dprintf(CRITICAL, "QSEEcom command for setting vbh returned error: %d\n",vbh_rsp.status);
820 if (ret == 0 && vbh_rsp.status == KM_ERROR_INVALID_TAG) {
821 dprintf(INFO, "VBH not supported in keymaster, continue boot\n");
822 return ret;
823 }
824 ASSERT(0);
825 }
826 return ret;
827}