blob: 4819eebb64c1f9addadf5e8083a04796142180d5 [file] [log] [blame]
Shashank Mittal64d04852014-08-28 15:02:46 -07001/*
Channagoud Kadabi1420b002015-01-13 14:48:12 -08002 * Copyright (c) 2014-2015 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
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in
11 * the documentation and/or other materials provided with the
12 * distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
17 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
18 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
20 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
21 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
22 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
24 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <stdlib.h>
Channagoud Kadabi1420b002015-01-13 14:48:12 -080029#include <stdint.h>
Shashank Mittal64d04852014-08-28 15:02:46 -070030#include <crypto_hash.h>
31#include <boot_verifier.h>
32#include <image_verify.h>
33#include <mmc.h>
34#include <oem_keystore.h>
35#include <openssl/asn1t.h>
36#include <openssl/x509.h>
37#include <partition_parser.h>
38#include <rsa.h>
39#include <string.h>
Channagoud Kadabi1420b002015-01-13 14:48:12 -080040#include <openssl/err.h>
Shashank Mittal64d04852014-08-28 15:02:46 -070041
42static KEYSTORE *oem_keystore;
43static KEYSTORE *user_keystore;
44static uint32_t dev_boot_state = RED;
45BUF_DMA_ALIGN(keystore_buf, 4096);
46char KEYSTORE_PTN_NAME[] = "keystore";
47
Channagoud Kadabi1420b002015-01-13 14:48:12 -080048static const char *VERIFIED_FLASH_ALLOWED_PTN[] = {
Shashank Mittal64d04852014-08-28 15:02:46 -070049 "aboot",
50 "boot",
51 "recovery",
52 "system",
53 NULL };
54
55ASN1_SEQUENCE(AUTH_ATTR) ={
56 ASN1_SIMPLE(AUTH_ATTR, target, ASN1_PRINTABLESTRING),
57 ASN1_SIMPLE(AUTH_ATTR, len, ASN1_INTEGER)
58} ASN1_SEQUENCE_END(AUTH_ATTR)
59IMPLEMENT_ASN1_FUNCTIONS(AUTH_ATTR)
60
61 ASN1_SEQUENCE(VERIFIED_BOOT_SIG) = {
62 ASN1_SIMPLE(VERIFIED_BOOT_SIG, version, ASN1_INTEGER),
Unnati Gandhi93334992015-02-25 19:38:38 +053063 ASN1_SIMPLE(VERIFIED_BOOT_SIG, certificate, X509),
Shashank Mittal64d04852014-08-28 15:02:46 -070064 ASN1_SIMPLE(VERIFIED_BOOT_SIG, algor, X509_ALGOR),
65 ASN1_SIMPLE(VERIFIED_BOOT_SIG, auth_attr, AUTH_ATTR),
66 ASN1_SIMPLE(VERIFIED_BOOT_SIG, sig, ASN1_OCTET_STRING)
67 } ASN1_SEQUENCE_END(VERIFIED_BOOT_SIG)
68IMPLEMENT_ASN1_FUNCTIONS(VERIFIED_BOOT_SIG)
69
70 ASN1_SEQUENCE(KEY) = {
71 ASN1_SIMPLE(KEY, algorithm_id, X509_ALGOR),
72 ASN1_SIMPLE(KEY, key_material, RSAPublicKey)
73 }ASN1_SEQUENCE_END(KEY)
74IMPLEMENT_ASN1_FUNCTIONS(KEY);
75
76ASN1_SEQUENCE(KEYBAG) = {
77 ASN1_SIMPLE(KEYBAG, mykey, KEY)
78}ASN1_SEQUENCE_END(KEYBAG)
79IMPLEMENT_ASN1_FUNCTIONS(KEYBAG)
80
81 ASN1_SEQUENCE(KEYSTORE_INNER) = {
82 ASN1_SIMPLE(KEYSTORE_INNER, version, ASN1_INTEGER),
83 ASN1_SIMPLE(KEYSTORE_INNER, mykeybag, KEYBAG)
84 } ASN1_SEQUENCE_END(KEYSTORE_INNER)
85IMPLEMENT_ASN1_FUNCTIONS(KEYSTORE_INNER)
86
87 ASN1_SEQUENCE(KEYSTORE) = {
88 ASN1_SIMPLE(KEYSTORE, version, ASN1_INTEGER),
89 ASN1_SIMPLE(KEYSTORE, mykeybag, KEYBAG),
90 ASN1_SIMPLE(KEYSTORE, sig, VERIFIED_BOOT_SIG)
91 } ASN1_SEQUENCE_END(KEYSTORE)
92IMPLEMENT_ASN1_FUNCTIONS(KEYSTORE)
93
94static uint32_t read_der_message_length(unsigned char* input)
95{
96 uint32_t len = 0;
97 int pos = 0;
98 uint8_t len_bytes = 1;
99
100 /* Check if input starts with Sequence id (0X30) */
101 if(input[pos] != 0x30)
102 return len;
103 pos++;
104
105 /* A length of 0xAABBCCDD in DER encoded messages would be sequence of
106 following octets 0xAA, 0xBB, 0XCC, 0XDD.
107
108 To read length - read each octet and shift left by 1 octect before
109 reading next octet.
110 */
111 /* check if short or long length form */
112 if(input[pos] & 0x80)
113 {
114 len_bytes = (input[pos] & ~(0x80));
115 pos++;
116 }
117 while(len_bytes)
118 {
119 /* Shift len by 1 octet */
120 len = len << 8;
121
122 /* Read next octet */
123 len = len | input[pos];
124 pos++; len_bytes--;
125 }
126
127 /* Add number of octets representing sequence id and length */
128 len += pos;
129
130 return len;
131}
132
133static int verify_digest(unsigned char* input, unsigned char *digest, int hash_size)
134{
135 int ret = -1;
Shashank Mittale6797222014-09-19 18:58:43 -0700136 X509_SIG *sig = NULL;
Shashank Mittal64d04852014-08-28 15:02:46 -0700137 uint32_t len = read_der_message_length(input);
Shashank Mittale6797222014-09-19 18:58:43 -0700138 if(!len)
139 {
140 dprintf(CRITICAL, "boot_verifier: Signature length is invalid.\n");
141 return ret;
142 }
143
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800144 sig = d2i_X509_SIG(NULL, (const unsigned char **) &input, len);
Shashank Mittal64d04852014-08-28 15:02:46 -0700145 if(sig == NULL)
146 {
147 dprintf(CRITICAL, "boot_verifier: Reading digest failed\n");
148 return ret;
149 }
150
151 if(sig->digest->length != SHA256_SIZE)
152 {
153 dprintf(CRITICAL, "boot_verifier: Digest length error.\n");
154 goto verify_digest_error;
155 }
156
157 if(memcmp(sig->digest->data, digest, hash_size) == 0)
158 ret = 0;
159
160verify_digest_error:
161 if(sig != NULL)
162 X509_SIG_free(sig);
163
164 return ret;
165}
166
167static int add_attribute_to_img(unsigned char *ptr, AUTH_ATTR *input)
168{
169 return i2d_AUTH_ATTR(input, &ptr);
170}
171
172static bool boot_verify_compare_sha256(unsigned char *image_ptr,
173 unsigned int image_size, unsigned char *signature_ptr, RSA *rsa)
174{
175 int ret = -1;
176 bool auth = false;
177 unsigned char *plain_text = NULL;
178 unsigned int digest[8];
179
180 plain_text = (unsigned char *)calloc(sizeof(char), SIGNATURE_SIZE);
181 if (plain_text == NULL) {
182 dprintf(CRITICAL, "boot_verifier: Calloc failed during verification\n");
183 goto cleanup;
184 }
185
186 /* Calculate SHA256sum */
187 image_find_digest(image_ptr, image_size, CRYPTO_AUTH_ALG_SHA256,
188 (unsigned char *)&digest);
189
190 /* Find digest from the image */
191 ret = image_decrypt_signature_rsa(signature_ptr, plain_text, rsa);
192
193 dprintf(SPEW, "boot_verifier: Return of RSA_public_decrypt = %d\n",
194 ret);
195
196 ret = verify_digest(plain_text, (unsigned char*)digest, SHA256_SIZE);
197 if(ret == 0)
198 {
199 auth = true;
200 }
201
202cleanup:
203 if (plain_text != NULL)
204 free(plain_text);
205 EVP_cleanup();
206 CRYPTO_cleanup_all_ex_data();
207 ERR_remove_thread_state(NULL);
208 return auth;
209
210}
211
212static bool verify_image_with_sig(unsigned char* img_addr, uint32_t img_size,
213 char *pname, VERIFIED_BOOT_SIG *sig, KEYSTORE *ks)
214{
215 bool ret = false;
216 uint32_t len;
217 int shift_bytes;
218 RSA *rsa = NULL;
219 bool keystore_verification = false;
220
221 if(!strcmp(pname, "keystore"))
222 keystore_verification = true;
223
224 /* Verify target name */
225 if(strncmp((char*)(sig->auth_attr->target->data), pname,
226 sig->auth_attr->target->length) ||
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800227 (strlen(pname) != (unsigned long) sig->auth_attr->target->length))
Shashank Mittal64d04852014-08-28 15:02:46 -0700228 {
229 dprintf(CRITICAL,
230 "boot_verifier: verification failure due to target name mismatch\n");
231 goto verify_image_with_sig_error;
232 }
Shashank Mittal64d04852014-08-28 15:02:46 -0700233 /* Read image size from signature */
234 /* A len = 0xAABBCC (represented by 3 octets) would be stored in
235 len->data as 0X00CCBBAA and len->length as 3(octets).
236
237 To read len we need to left shift data to number of missing octets and
238 then change it to host long
239 */
240 len = *((uint32_t*)sig->auth_attr->len->data);
241 shift_bytes = sizeof(uint32_t) - sig->auth_attr->len->length;
242 if(shift_bytes > 0) {
243 len = len << (shift_bytes*8);
244 }
245 len = ntohl(len);
246
247 /* Verify image size*/
248 if(len != img_size)
249 {
250 dprintf(CRITICAL,
251 "boot_verifier: image length is different. (%d vs %d)\n",
252 len, img_size);
253 goto verify_image_with_sig_error;
254 }
255
256 /* append attribute to image */
257 if(!keystore_verification)
258 img_size += add_attribute_to_img((unsigned char*)(img_addr + img_size),
259 sig->auth_attr);
260
261 /* compare SHA256SUM of image with value in signature */
262 if(ks != NULL)
263 rsa = ks->mykeybag->mykey->key_material;
264
265 ret = boot_verify_compare_sha256(img_addr, img_size,
266 (unsigned char*)sig->sig->data, rsa);
267
268 if(!ret)
269 {
270 dprintf(CRITICAL,
271 "boot_verifier: Image verification failed.\n");
272 }
273
274verify_image_with_sig_error:
275 return ret;
276}
277
278static int encode_inner_keystore(unsigned char *ptr, KEYSTORE *ks)
279{
280 int ret = 0;
281 KEYSTORE_INNER *ks_inner = KEYSTORE_INNER_new();
282 if (ks_inner == NULL)
283 return ret;
284 ASN1_INTEGER *tmp_version = ks_inner->version;
285 KEYBAG *tmp_mykeybag = ks_inner->mykeybag;
286
287 ks_inner->version = ks->version;
288 ks_inner->mykeybag = ks->mykeybag;
289 ret = i2d_KEYSTORE_INNER(ks_inner, &ptr);
290
291 ks_inner->version = tmp_version;
292 ks_inner->mykeybag = tmp_mykeybag;
293
294 if(ks_inner != NULL)
295 KEYSTORE_INNER_free(ks_inner);
296 return ret;
297}
298
299static bool verify_keystore(unsigned char * ks_addr, KEYSTORE *ks)
300{
301 bool ret = false;
302 unsigned char * ptr = ks_addr;
303 uint32_t inner_len = encode_inner_keystore(ptr, ks);
304 ret = verify_image_with_sig(ks_addr, inner_len, "keystore", ks->sig,
305 oem_keystore);
306 return ret;
307}
308
309static void read_oem_keystore()
310{
Shashank Mittale6797222014-09-19 18:58:43 -0700311 KEYSTORE *ks = NULL;
312 uint32_t len = 0;
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800313 const unsigned char *input = OEM_KEYSTORE;
Shashank Mittale6797222014-09-19 18:58:43 -0700314
Shashank Mittal64d04852014-08-28 15:02:46 -0700315 if(oem_keystore != NULL)
316 return;
317
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800318 len = read_der_message_length((unsigned char *)input);
Shashank Mittale6797222014-09-19 18:58:43 -0700319 if(!len)
320 {
321 dprintf(CRITICAL, "boot_verifier: oem keystore length is invalid.\n");
322 return;
323 }
324
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800325 ks = d2i_KEYSTORE(NULL, (const unsigned char **) &input, len);
Shashank Mittal64d04852014-08-28 15:02:46 -0700326 if(ks != NULL)
327 {
328 oem_keystore = ks;
329 user_keystore = ks;
330 }
331}
332
333static int read_user_keystore_ptn()
334{
335 int index = INVALID_PTN;
336 unsigned long long ptn = 0;
337
338 index = partition_get_index(KEYSTORE_PTN_NAME);
339 ptn = partition_get_offset(index);
340 if(ptn == 0) {
341 dprintf(CRITICAL, "boot_verifier: No keystore partition found\n");
342 return -1;
343 }
344
345 if (mmc_read(ptn, (unsigned int *) keystore_buf, mmc_page_size())) {
346 dprintf(CRITICAL, "boot_verifier: Cannot read user keystore\n");
347 return -1;
348 }
349 return 0;
350}
351
352static void read_user_keystore(unsigned char *user_addr)
353{
354 unsigned char *input = user_addr;
Shashank Mittale6797222014-09-19 18:58:43 -0700355 KEYSTORE *ks = NULL;
Shashank Mittal64d04852014-08-28 15:02:46 -0700356 uint32_t len = read_der_message_length(input);
Shashank Mittale6797222014-09-19 18:58:43 -0700357 if(!len)
358 {
359 dprintf(CRITICAL, "boot_verifier: user keystore length is invalid.\n");
360 return;
361 }
362
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800363 ks = d2i_KEYSTORE(NULL, (const unsigned char **)&input, len);
Shashank Mittal64d04852014-08-28 15:02:46 -0700364 if(ks != NULL)
365 {
366 if(verify_keystore(user_addr, ks) == false)
367 {
368 dprintf(CRITICAL, "boot_verifier: Keystore verification failed!\n");
369 boot_verify_send_event(KEYSTORE_VERIFICATION_FAIL);
370 }
371 else
372 dprintf(CRITICAL, "boot_verifier: Keystore verification success!\n");
373 user_keystore = ks;
374 }
375 else
376 {
377 user_keystore = oem_keystore;
378 }
379}
380
381uint32_t boot_verify_keystore_init()
382{
383 /* Read OEM Keystore */
384 read_oem_keystore();
385
386 /* Read User Keystore */
387 if(!read_user_keystore_ptn())
388 read_user_keystore((unsigned char *)keystore_buf);
389 return dev_boot_state;
390}
391
392bool boot_verify_image(unsigned char* img_addr, uint32_t img_size, char *pname)
393{
394 bool ret = false;
395 VERIFIED_BOOT_SIG *sig = NULL;
396 unsigned char* sig_addr = (unsigned char*)(img_addr + img_size);
397 uint32_t sig_len = read_der_message_length(sig_addr);
398
399 if(dev_boot_state == ORANGE)
400 {
401 dprintf(INFO, "boot_verifier: Device is in ORANGE boot state.\n");
402 dprintf(INFO, "boot_verifier: Skipping boot verification.\n");
403 return false;
404 }
405
406 if(!sig_len)
407 {
408 dprintf(CRITICAL, "boot_verifier: Error while reading singature length.\n");
409 goto verify_image_error;
410 }
411
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800412 if((sig = d2i_VERIFIED_BOOT_SIG(NULL, (const unsigned char **) &sig_addr, sig_len)) == NULL)
Shashank Mittal64d04852014-08-28 15:02:46 -0700413 {
414 dprintf(CRITICAL,
415 "boot_verifier: verification failure due to target name mismatch\n");
416 goto verify_image_error;
417 }
418
419 ret = verify_image_with_sig(img_addr, img_size, pname, sig, user_keystore);
420
421verify_image_error:
422 if(sig != NULL)
423 VERIFIED_BOOT_SIG_free(sig);
424 if(!ret)
425 boot_verify_send_event(BOOT_VERIFICATION_FAIL);
426 return ret;
427}
428
429void boot_verify_send_event(uint32_t event)
430{
431 switch(event)
432 {
433 case BOOT_INIT:
434 dev_boot_state = GREEN;
435 break;
436 case KEYSTORE_VERIFICATION_FAIL:
437 if(dev_boot_state == GREEN)
438 dev_boot_state = YELLOW;
439 break;
440 case BOOT_VERIFICATION_FAIL:
441 if(dev_boot_state == GREEN || dev_boot_state == YELLOW)
442 dev_boot_state = RED;
443 break;
444 case DEV_UNLOCK:
445 dev_boot_state = ORANGE;
446 break;
447 case USER_DENIES:
448 if(dev_boot_state == YELLOW || dev_boot_state == ORANGE)
449 dev_boot_state = RED;
450 break;
451 }
452}
453
454uint32_t boot_verify_get_state()
455{
456 return dev_boot_state;
457}
458
459void boot_verify_print_state()
460{
461 switch(dev_boot_state)
462 {
463 case GREEN:
464 dprintf(INFO, "boot_verifier: Device is in GREEN boot state.\n");
465 break;
466 case ORANGE:
467 dprintf(INFO, "boot_verifier: Device is in ORANGE boot state.\n");
468 break;
469 case YELLOW:
470 dprintf(INFO, "boot_verifier: Device is in YELLOW boot state.\n");
471 break;
472 case RED:
473 dprintf(INFO, "boot_verifier: Device is in RED boot state.\n");
474 break;
475 }
476}
477
478bool boot_verify_validate_keystore(unsigned char * user_addr)
479{
480 bool ret = false;
481 unsigned char *input = user_addr;
Shashank Mittale6797222014-09-19 18:58:43 -0700482 KEYSTORE *ks = NULL;
Shashank Mittal64d04852014-08-28 15:02:46 -0700483 uint32_t len = read_der_message_length(input);
Shashank Mittale6797222014-09-19 18:58:43 -0700484 if(!len)
485 {
486 dprintf(CRITICAL, "boot_verifier: keystore length is invalid.\n");
487 return ret;
488 }
489
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800490 ks = d2i_KEYSTORE(NULL, (const unsigned char **)&input, len);
Shashank Mittal64d04852014-08-28 15:02:46 -0700491 if(ks != NULL)
492 {
493 ret = true;
494 }
495 return ret;
496}
497
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800498static bool check_list(const char **list, const char* entry)
Shashank Mittal64d04852014-08-28 15:02:46 -0700499{
Shashank Mittal64d04852014-08-28 15:02:46 -0700500 if(list == NULL || entry == NULL)
501 return false;
502
503 while(*list != NULL)
504 {
505 if(!strcmp(entry, *list))
506 return true;
507
508 list++;
509 }
510
511 return false;
512}
513
Channagoud Kadabi1420b002015-01-13 14:48:12 -0800514bool boot_verify_flash_allowed(const char * entry)
Shashank Mittal64d04852014-08-28 15:02:46 -0700515{
516 return check_list(VERIFIED_FLASH_ALLOWED_PTN, entry);
517}