blob: 58c9157484106d69ed57c8fd089a4758e542d6b3 [file] [log] [blame]
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301/*
2 * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 and
6 * only version 2 as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 */
13
14#include <sysupgrade.h>
15
16#define SBL_VERSION_FILE "sbl_version"
17#define TZ_VERSION_FILE "tz_version"
18#define HLOS_VERSION_FILE "hlos_version"
19#define APPSBL_VERSION_FILE "appsbl_version"
20#define RPM_VERSION_FILE "rpm_version"
21#define VERSION_FILE_BASENAME "/sys/devices/system/qfprom/qfprom0/"
22#define AUTHENTICATE_FILE "/sys/devices/system/qfprom/qfprom0/authenticate"
23#define TEMP_KERNEL_PATH "/tmp/tmp_kernel.bin"
24#define MAX_SBL_VERSION 11
25#define MAX_HLOS_VERSION 32
26#define MAX_TZ_VERSION 14
27#define MAX_APPSBL_VERSION 14
28#define MAX_RPM_VERSION 8
29#define HASH_P_FLAG 0x02200000
30#define TMP_FILE_DIR "/tmp/"
31#define CERT_SIZE 2048
32#define PRESENT 1
33#define MBN_HDR_SIZE 40
34#define SIG_SIZE 256
35#define NOT_PRESENT 0
36#define SIG_CERT_2_SIZE 4352
37#define SIG_CERT_3_SIZE 6400
38#define SBL_NAND_PREAMBLE 10240
39#define SBL_HDR_RESERVED 12
40#define UBI_EC_HDR_MAGIC 0x55424923
41#define UBI_VID_HDR_MAGIC 0x55424921
42
43#define ARRAY_SIZE(array) sizeof(array)/sizeof(array[0])
44
45struct image_section sections[] = {
46 {
47 .section_type = UBOOT_TYPE,
48 .type = "u-boot",
49 .max_version = MAX_APPSBL_VERSION,
50 .file = TMP_FILE_DIR,
51 .version_file = APPSBL_VERSION_FILE,
52 .is_present = NOT_PRESENT,
53 },
54 {
55 .section_type = HLOS_TYPE,
56 .type = "hlos",
57 .max_version = MAX_HLOS_VERSION,
58 .file = TMP_FILE_DIR,
59 .version_file = HLOS_VERSION_FILE,
60 .is_present = NOT_PRESENT,
61 },
62 {
63 .section_type = HLOS_TYPE,
64 .type = "ubi",
65 .tmp_file = TMP_FILE_DIR,
66 .pre_op = extract_kernel_binary,
67 .max_version = MAX_HLOS_VERSION,
68 .file = TEMP_KERNEL_PATH,
69 .version_file = HLOS_VERSION_FILE,
70 .is_present = NOT_PRESENT,
71 },
72 {
73 .section_type = TZ_TYPE,
74 .type = "tz",
75 .max_version = MAX_TZ_VERSION,
76 .file = TMP_FILE_DIR,
77 .version_file = TZ_VERSION_FILE,
78 .is_present = NOT_PRESENT,
79 },
80 {
81 .section_type = SBL_TYPE,
82 .type = "sbl1",
83 .max_version = MAX_SBL_VERSION,
84 .file = TMP_FILE_DIR,
85 .version_file = SBL_VERSION_FILE,
86 .is_present = NOT_PRESENT,
87 },
88 {
89 .section_type = SBL_TYPE,
90 .type = "sbl2",
91 .max_version = MAX_SBL_VERSION,
92 .file = TMP_FILE_DIR,
93 .version_file = SBL_VERSION_FILE,
94 .is_present = NOT_PRESENT,
95 },
96 {
97 .section_type = SBL_TYPE,
98 .type = "sbl3",
99 .max_version = MAX_SBL_VERSION,
100 .file = TMP_FILE_DIR,
101 .version_file = SBL_VERSION_FILE,
102 .is_present = NOT_PRESENT,
103 },
104 {
105 .section_type = RPM_TYPE,
106 .type = "rpm",
107 .max_version = MAX_RPM_VERSION,
108 .file = TMP_FILE_DIR,
109 .version_file = RPM_VERSION_FILE,
110 .is_present = NOT_PRESENT,
111 },
112};
113
114#define NO_OF_SECTIONS ARRAY_SIZE(sections)
115int src_size;
116
117int check_mbn_elf(struct image_section **sec)
118{
119 int fd = open((*sec)->file, O_RDONLY);
120 struct stat sb;
121 uint8_t *fp;
122 Elf32_Ehdr *elf;
123
124 if (fd < 0) {
125 perror((*sec)->file);
126 return 0;
127 }
128
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530129 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530130 if (fstat(fd, &sb) == -1) {
131 perror("fstat");
132 close(fd);
133 return 0;
134 }
135
136 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
137 if (fp == MAP_FAILED) {
138 perror("mmap");
139 close(fd);
140 return 0;
141 }
142
143 elf = (Elf32_Ehdr *)fp;
144 if (!strncmp((char *)&(elf->e_ident[1]), "ELF", 3)) {
pavipfb8e3072017-10-12 14:47:47 +0530145 /* EI_CLASS Check for 32/64-bit */
146 if( ((int)(elf->e_ident[4])) == 2) {
147 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
148 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
149 } else {
150 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
151 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
152 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530153 } else if (!strncmp((char *)&(((Elf32_Ehdr *)(fp + SBL_NAND_PREAMBLE))->e_ident[1]), "ELF", 3)) {
pavipfb8e3072017-10-12 14:47:47 +0530154 if( ((int)(elf->e_ident[4])) == 2) {
155 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
156 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
157 } else {
158 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
159 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
160 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530161 } else {
162 (*sec)->get_sw_id = get_sw_id_from_component_bin;
163 (*sec)->split_components = split_code_signature_cert_from_component_bin;
164 }
165
166 return 1;
167}
168
169int get_sections(void)
170{
171 DIR *dir = opendir(TMP_FILE_DIR);
172 struct dirent *file;
173 int i;
174 struct image_section *sec;
175
176 if (dir == NULL) {
177 printf("Error accessing the image directory\n");
178 return 0;
179 }
180
181 while ((file = readdir(dir)) != NULL) {
182 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
183 if (strstr(file->d_name, sec->type)) {
184 if (sec->pre_op) {
185 strncat(sec->tmp_file, file->d_name,
186 sizeof(sec->tmp_file));
187 if (!sec->pre_op(sec)) {
188 printf("Error extracting kernel from ubi\n");
189 return 0;
190 }
191 } else {
192 strncat(sec->file, file->d_name,
193 sizeof(sec->file));
194 }
195 if (!check_mbn_elf(&sec)) {
196 closedir(dir);
197 return 0;
198 }
199 if (!sec->get_sw_id(sec)) {
200 closedir(dir);
201 return 0;
202 }
203 get_local_image_version(sec);
204 sec->is_present = PRESENT;
205 break;
206 }
207 }
208 }
209 closedir(dir);
210 return 1;
211}
212
213/**
214 * is_authentication_check_enabled() - checks whether installed image is
215 * secure(1) or not(0)
216 *
217 */
218int is_authentication_check_enabled(void)
219{
220 int fd = open(AUTHENTICATE_FILE, O_RDONLY);
221 char authenticate_string[4];
222 int len;
223
224 if (fd == -1) {
225 perror(AUTHENTICATE_FILE);
226 return 0;
227 }
228
229 len = read(fd, authenticate_string, 1);
230 close(fd);
231
232 if (len > 0 && authenticate_string[0] == '0') {
233 return 0;
234 }
235
236 return 1;
237}
238
239/**
240 * get_local_image_version() check the version file & if it exists, read the
241 * value & save it into global variable local_version
242 *
243 */
244int get_local_image_version(struct image_section *section)
245{
246 int len, fd;
247 char local_version_string[16], version_file[64];
248 struct stat st;
249
250 snprintf(version_file, sizeof(version_file), "%s%s", VERSION_FILE_BASENAME, section->version_file);
251 fd = open(version_file, O_RDONLY);
252 if (fd == -1) {
253 perror(version_file);
254 return 0;
255 }
256
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530257 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530258 fstat(fd, &st);
259
260 len = st.st_size < sizeof(local_version_string) - 1 ? st.st_size :
261 sizeof(local_version_string) - 1;
262 if (read(fd, local_version_string, len) == -1) {
263 close(fd);
264 return 0;
265 }
266 local_version_string[len] = '\0';
267 close(fd);
268
269 section->local_version = atoi(local_version_string);
270 printf("Local image version:%s\n", local_version_string);
271
272 return 1;
273}
274
275/**
276 * set_local_image_version() update the version of the image by writing the version
277 * to the version file
278 *
279 */
280int set_local_image_version(struct image_section *section)
281{
282 int fd;
283 char version_string[16], version_file[64];
284 int len;
285
286 snprintf(version_file, sizeof(version_file), "%s%s", TMP_FILE_DIR, section->version_file);
287 fd = open(version_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
288 if (fd == -1) {
289 perror(version_file);
290 return 0;
291 }
292
293 len = snprintf(version_string, 8, "%d", section->img_version);
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530294 if (len < 0) {
295 printf("Error in formatting the version string");
296 return 0;
297 }
298
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530299 printf("Version to be updated:%s\n", version_string);
300 if (write(fd, version_string, len) == -1) {
301 printf("Error writing version to %s\n", version_file);
302 close(fd);
303 return 0;
304 }
305
306 close(fd);
307 return 1;
308}
309
310/**
311 * is_version_check_enabled() checks whether version check is
312 * enabled(non-zero value) or not
313 *
314 */
315int is_version_check_enabled()
316{
317 if (get_local_image_version(&sections[0]) != -1) {
318 printf("Returning 1 from is_version_check_enabled because local_version_string is non-ZERO\n");
319 return 1;
320 }
321
322 return 0;
323}
324
325char *find_value(char *buffer, char *search, int size)
326{
327 char *value = malloc(size * sizeof(char));
328 int i, j;
329
330 if (value == NULL) {
331 return NULL;
332 }
333
334 for (i = 0; i < CERT_SIZE; i++) {
335 for (j = 0; search[j] && (buffer[i + j] == search[j]); j++);
336 if (search[j] == '\0') {
337 strncpy(value, &buffer[i - size], size);
338 value[size - 1] = '\0';
339 return value;
340 }
341 }
342 free(value);
343 return NULL;
344}
345
346/**
347 * get_sw_id_from_component_bin() parses the MBN header & checks image size v/s
348 * code size. If both differ, it means signature & certificates are
349 * appended at end.
350 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
351 *
352 * @bin_file: struct image_section *
353 */
354int get_sw_id_from_component_bin(struct image_section *section)
355{
356 Mbn_Hdr *mbn_hdr;
357 int fd = open(section->file, O_RDONLY);
358 struct stat sb;
359 uint8_t *fp;
360 int cert_offset;
361 char *sw_version;
362 int sig_cert_size;
363
364 if (fd == -1) {
365 perror(section->file);
366 return 0;
367 }
368
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530369 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530370 if (fstat(fd, &sb) == -1) {
371 perror("fstat");
372 close(fd);
373 return 0;
374 }
375
376 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
377 if (fp == MAP_FAILED) {
378 perror("mmap");
379 close(fd);
380 return 0;
381 }
382
383 mbn_hdr = (Mbn_Hdr *)fp;
384 if (strstr(section->file, sections[4].type)) {
385 uint32_t preamble = sections[2].is_present ? SBL_NAND_PREAMBLE : 0;
386
387 mbn_hdr = (Mbn_Hdr *)(fp + preamble + SBL_HDR_RESERVED);
388 }
389 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
390 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
pavipfb8e3072017-10-12 14:47:47 +0530391 printf("WARNING: signature certificate size is different\n");
392 // ipq807x has certificate size as dynamic, hence ignore this check
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530393 }
394
395 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
396 printf("Image with version information\n");
397 sw_version = find_value((char *)(fp + cert_offset), "SW_ID", 17);
398 if (sw_version != NULL) {
399 sw_version[8] = '\0';
400 sscanf(sw_version, "%x", &section->img_version);
401 printf("SW ID:%d\n", section->img_version);
402 free(sw_version);
403 }
404
405 close(fd);
406 return 1;
407}
408
409int process_elf(char *bin_file, uint8_t **fp, Elf32_Ehdr **elf, Elf32_Phdr **phdr, Mbn_Hdr **mbn_hdr)
410{
411 int fd = open(bin_file, O_RDONLY);
412 struct stat sb;
413 int version = 0;
414 int i = 0;
415
416 if (fd < 0) {
417 perror(bin_file);
418 return 0;
419 }
420
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530421 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530422 if (fstat(fd, &sb) == -1) {
423 perror("fstat");
424 close(fd);
425 return 0;
426 }
427
428 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
429 if (*fp == MAP_FAILED) {
430 perror("mmap");
431 close(fd);
432 return 0;
433 }
434
435 *elf = (Elf32_Ehdr *)*fp;
436 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
437 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
438 *elf = (Elf32_Ehdr *)*fp;
439 }
440
441 *phdr = (Elf32_Phdr *)(*fp + (*elf)->e_phoff);
442 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
443 if ((*phdr)->p_flags == HASH_P_FLAG) {
444 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
445 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
446 version = 1;
447 break;
448 } else {
449 printf("Error: Image without version information\n");
450 close(fd);
451 return 0;
452 }
453 }
454 }
455
456 if (version != 1) {
457 printf("Error: Image without version information\n");
458 return 0;
459 }
460
461 close(fd);
462 return 1;
463}
464
pavipfb8e3072017-10-12 14:47:47 +0530465int process_elf64(char *bin_file, uint8_t **fp, Elf64_Ehdr **elf, Elf64_Phdr **phdr, Mbn_Hdr **mbn_hdr)
466{
467 struct stat sb;
468 int i, fd, version = 0;
469
470 fd = open(bin_file, O_RDONLY);
471 if (fd < 0) {
472 perror(bin_file);
473 return 0;
474 }
475
476 memset(&sb, 0, sizeof(struct stat));
477 if (fstat(fd, &sb) == -1) {
478 perror("fstat");
479 close(fd);
480 return 0;
481 }
482
483 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
484 if (*fp == MAP_FAILED) {
485 perror("mmap");
486 close(fd);
487 return 0;
488 }
489
490 *elf = (Elf64_Ehdr *)*fp;
491 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
492 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
493 *elf = (Elf64_Ehdr *)*fp;
494 }
495
496 *phdr = (Elf64_Phdr *)(*fp + (*elf)->e_phoff);
497 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
498 if ((*phdr)->p_flags == HASH_P_FLAG) {
499 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
500 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
501 version = 1;
502 break;
503 } else {
504 printf("Error: Image without version information\n");
505 close(fd);
506 return 0;
507 }
508 }
509 }
510
511 if (version != 1) {
512 printf("Error: Image without version information\n");
513 return 0;
514 }
515
516 close(fd);
517 return 1;
518}
519
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530520/**
521 * get_sw_id_from_component_bin_elf() parses the ELF header to get the MBN header
522 * of the hash table segment. Parses the MBN header of hash table segment & checks
523 * total size v/s actual component size. If both differ, it means signature &
524 * certificates are appended at end.
525 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
526 *
527 * @bin_file: struct image_section *
528 */
529int get_sw_id_from_component_bin_elf(struct image_section *section)
530{
531 Elf32_Ehdr *elf;
532 Elf32_Phdr *phdr;
533 Mbn_Hdr *mbn_hdr;
534 uint8_t *fp;
535 int cert_offset;
536 char *sw_version;
537
538 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
539 return 0;
540 }
541
542 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
543 printf("Image with version information\n");
544 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
545 if (sw_version) {
546 sw_version[8] = '\0';
547 sscanf(sw_version, "%x", &section->img_version);
548 printf("SW ID:%d\n", section->img_version);
549 free(sw_version);
550 }
551
552 return 1;
553}
554
pavipfb8e3072017-10-12 14:47:47 +0530555/**
556 * get_sw_id_from_component_bin_elf64() parses the ELF64 header to get the MBN header
557 * of the hash table segment. Parses the MBN header of hash table segment & checks
558 * total size v/s actual component size. If both differ, it means signature &
559 * certificates are appended at end.
560 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
561 *
562 32_Phdr *phdr;* @bin_file: struct image_section *
563 */
564int get_sw_id_from_component_bin_elf64(struct image_section *section)
565{
566 Elf64_Ehdr *elf;
567 Elf64_Phdr *phdr;
568 Mbn_Hdr *mbn_hdr;
569 uint8_t *fp;
570 int cert_offset;
571 char *sw_version;
572
573 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
574 return 0;
575 }
576
577 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + 40;
578 printf("Image with version information64\n");
579 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
580 if (sw_version) {
581 sw_version[8] = '\0';
582 sscanf(sw_version, "%x", &section->img_version);
583 printf("SW ID:%d\n", section->img_version);
584 free(sw_version);
585 }
586
587 return 1;
588}
589
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530590int find_mtd_part_size(void)
591{
592 char *mtdname = "kernel";
593 char prefix[] = "/dev/mtd";
594 char dev[PATH_MAX];
595 int i = -1, fd;
596 int vol_size;
597 int flag = 0;
598 char mtd_part[256];
599 FILE *fp = fopen("/proc/mtd", "r");
600 mtd_info_t mtd_dev_info;
601
602 if (fp == NULL) {
603 printf("Error finding mtd part\n");
604 return -1;
605 }
606
607 while (fgets(dev, sizeof(dev), fp)) {
608 if (strstr(dev, mtdname)) {
609 flag = 1;
610 break;
611 }
612 i++;
613 }
614 fclose(fp);
615
616 if (flag != 1) {
617 printf("%s block not found\n", mtdname);
618 return -1;
619 }
620
621 snprintf(mtd_part, sizeof(mtd_part), "%s%d", prefix, i);
622
623 fd = open(mtd_part, O_RDWR);
624 if (fd == -1) {
625 return -1;
626 }
627
628 if (ioctl(fd, MEMGETINFO, &mtd_dev_info) == -1) {
629 printf("Error getting block size\n");
630 close(fd);
631 return -1;
632 }
633
634 vol_size = mtd_dev_info.erasesize;
635 close(fd);
636
637 return vol_size;
638}
639
640/**
641 * In case of NAND image, Kernel image is ubinized & version information is
642 * part of Kernel image. Hence need to un-ubinize the image.
643 * To get the kernel image, Find the volume with volume id 0. Kernel image
644 * is fragmented and hence to assemble it to get complete image.
645 * In UBI image, first look for UBI#, which is magic number used to identify
646 * each eraseble block. Parse the UBI header, which starts with UBI# & get
647 * the VID(volume ID) header offset as well as Data offset.
648 * Traverse to VID header offset & check the volume ID. If it is ZERO, Kernel
649 * image is stored in this volume. Use Data offset to extract the Kernel image.
650 *
651 * @bin_file: struct image_section *
652 */
653int extract_kernel_binary(struct image_section *section)
654{
655 struct ubi_ec_hdr *ubi_ec;
656 struct ubi_vid_hdr *ubi_vol;
657 uint8_t *fp;
658 int fd, ofd, magic, data_size, vid_hdr_offset, data_offset;
659 struct stat sb;
660
661 fd = open(section->tmp_file, O_RDONLY);
662 if (fd < 0) {
663 perror(section->tmp_file);
664 return 0;
665 }
666
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530667 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530668 if (fstat(fd, &sb) == -1) {
669 perror("fstat");
670 close(fd);
671 return 0;
672 }
673
674 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
675 if (fp == MAP_FAILED) {
676 perror("mmap");
677 close(fd);
678 return 0;
679 }
680
681 ofd = open(section->file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
682 if (ofd == -1) {
683 perror(section->file);
684 close(fd);
685 return 0;
686 }
687
688 data_size = find_mtd_part_size();
689 if (data_size == -1) {
690 printf("Error finding data size\n");
691 return 0;
692 }
693
694 ubi_ec = (struct ubi_ec_hdr *)fp;
695 magic = be32_to_cpu(ubi_ec->magic);
696 while (magic == UBI_EC_HDR_MAGIC) {
697 vid_hdr_offset = be32_to_cpu(ubi_ec->vid_hdr_offset);
698 data_offset = be32_to_cpu(ubi_ec->data_offset);
699 ubi_vol = (struct ubi_vid_hdr *)((uint8_t *)ubi_ec + vid_hdr_offset);
700 magic = be32_to_cpu(ubi_vol->magic);
701 if (magic != UBI_VID_HDR_MAGIC) {
702 printf("Wrong ubi format\n");
703 close(ofd);
704 close(fd);
705 return 0;
706 }
707
708 if (ubi_vol->vol_id == 0) {
709 if (write(ofd, (void *)((uint8_t *)ubi_ec + data_offset), data_size) == -1) {
710 printf("Write error\n");
711 close(fd);
712 close(ofd);
713 return 0;
714 }
715 }
716 if ((int)ubi_vol->vol_id > 0) {
717 break;
718 }
719
720 ubi_ec = (struct ubi_ec_hdr *)((uint8_t *)ubi_ec + data_offset + data_size);
721 magic = be32_to_cpu(ubi_ec->magic);
722 }
723
724 close(ofd);
725 close(fd);
726 printf("Kernel extracted from ubi image\n");
727 return 1;
728}
729
730/**
731 * is_image_version_higher() iterates through each component and check
732 * versions against locally installed version.
733 * If newer component version is lower than locally insatlled image,
734 * abort the FW upgrade process.
735 *
736 * @img: char *
737 */
738int is_image_version_higher(void)
739{
740 int i;
741 for (i = 0; i < NO_OF_SECTIONS; i++) {
742 if (!sections[i].is_present) {
743 continue;
744 }
745
746 if (sections[i].local_version > sections[i].img_version) {
747 printf("Version of image %s (%d) is lower than minimal supported version(%d)\n",
748 sections[i].file,
749 sections[i].img_version,
750 sections[i].local_version);
751 return 0;
752 }
753
754 if (sections[i].img_version > sections[i].max_version) {
755 printf("Version of image %s (%d) is higher than maximum supported version(%d)\n",
756 sections[i].file,
757 sections[i].img_version,
758 sections[i].max_version);
759 }
760 }
761
762 return 1;
763}
764
765/**
766 * Update the version information file based on currently SW_ID being installed.
767 *
768 */
769int update_version(void)
770{
771 int i;
772 for (i = 0; i < NO_OF_SECTIONS; i++) {
773 if (!sections[i].is_present) {
774 continue;
775 }
776
777 if (set_local_image_version(&sections[i]) != 1) {
778 printf("Error updating version of %s\n", sections[i].file);
779 return 0;
780 }
781 }
782
783 return 1;
784}
785
786int check_image_version(void)
787{
788 if (is_version_check_enabled() == 0) {
789 printf("Version check is not enabled, upgrade to continue !!!\n");
790 return 1;
791 }
792
793 if (is_image_version_higher() == 0) {
794 printf("New image versions are lower than existing image, upgrade to STOP !!!\n");
795 return 0;
796 }
797
798 if (update_version() != 1) {
799 printf("Error while updating verison information\n");
800 return 0;
801 }
802 printf("Update completed!\n");
803
804 return 1;
805}
806
807/**
808 * split_code_signature_cert_from_component_bin splits the component
809 * binary by splitting into code(including MBN header), signature file &
810 * attenstation certificate.
811 *
812 * @bin_file: char *
813 * @src: char *
814 * @sig: char *
815 * @cert: char *
816 */
817int split_code_signature_cert_from_component_bin(struct image_section *section,
818 char **src, char **sig, char **cert)
819{
820 Mbn_Hdr *mbn_hdr;
821 int fd = open(section->file, O_RDONLY);
822 uint8_t *fp;
823 int sig_offset = 0;
824 int cert_offset = 0;
825 struct stat sb;
826 int sig_cert_size;
827
828 if (fd == -1) {
829 perror(section->file);
830 return 0;
831 }
832
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530833 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530834 if (fstat(fd, &sb) == -1) {
835 perror("fstat");
836 close(fd);
837 return 0;
838 }
839
840 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
841 if (fp == MAP_FAILED) {
842 perror("mmap");
843 close(fd);
844 return 0;
845 }
846
847 mbn_hdr = (Mbn_Hdr *)fp;
848 if (strstr(section->file, sections[4].type)) {
849 uint32_t preamble = sections[2].is_present ? SBL_NAND_PREAMBLE : 0;
850
851 mbn_hdr = (Mbn_Hdr *)(fp + preamble + SBL_HDR_RESERVED);
852 sig_offset = preamble + MBN_HDR_SIZE;
853 cert_offset = preamble + MBN_HDR_SIZE;
854 }
855 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
856 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
857 printf("Error: Image without version information\n");
858 close(fd);
859 return 0;
860 }
861 *src = malloc((mbn_hdr->code_size + 1) * sizeof(char));
862 if (*src == NULL) {
863 close(fd);
864 return 0;
865 }
866 memcpy(*src, fp, mbn_hdr->code_size);
867 src_size = mbn_hdr->code_size;
868 (*src)[mbn_hdr->code_size] = '\0';
869
870 sig_offset += mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
871 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
872 if (*sig == NULL) {
873 free(*src);
874 return 0;
875 }
876 memcpy(*sig, fp + sig_offset, SIG_SIZE);
877 (*sig)[SIG_SIZE] = '\0';
878
879 cert_offset += mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
880 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
881 if (*cert == NULL) {
882 free(*src);
883 free(*sig);
884 return 0;
885 }
886 memcpy(*cert, fp + cert_offset, CERT_SIZE);
887 (*cert)[CERT_SIZE] = '\0';
888
889 close(fd);
890 return 1;
891}
892
893/**
894 * split_code_signature_cert_from_component_bin_elf splits the component
895 * binary by splitting into code(including ELF header), signature file &
896 * attenstation certificate.
897 *
898 * @bin_file: char *
899 * @src: char *
900 * @sig: char *
901 * @cert: char *
902 */
903int split_code_signature_cert_from_component_bin_elf(struct image_section *section,
904 char **src, char **sig, char **cert)
905{
906 Elf32_Ehdr *elf;
907 Elf32_Phdr *phdr;
908 Mbn_Hdr *mbn_hdr;
909 uint8_t *fp;
910 int sig_offset;
911 int cert_offset;
912 int len;
913
914 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
915 return 0;
916 }
917
918 sig_offset = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
919 len = MBN_HDR_SIZE + sig_offset;
920 *src = malloc((len + 1) * sizeof(char));
921 if (*src == NULL) {
922 return 0;
923 }
924 memcpy(*src, fp + phdr->p_offset, len);
925 src_size = len;
926 (*src)[len] = '\0';
927
928 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
929 if (*sig == NULL) {
930 free(*src);
931 return 0;
932 }
933 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
934 (*sig)[SIG_SIZE] = '\0';
935
936 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
937 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
938 if (*cert == NULL) {
939 free(*src);
940 free(*sig);
941 return 0;
942 }
943 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
944 (*cert)[CERT_SIZE] = '\0';
945
946 return 1;
947}
948
949/**
pavipfb8e3072017-10-12 14:47:47 +0530950 * split_code_signature_cert_from_component_bin_elf64 splits the component
951 * binary by splitting into code(including ELF header), signature file &
952 * attenstation certificate.
953 *
954 * @bin_file: char *
955 * @src: char *
956 * @sig: char *
957 * @cert: char *
958 */
959int split_code_signature_cert_from_component_bin_elf64(struct image_section *section,
960 char **src, char **sig, char **cert)
961{
962 Elf64_Ehdr *elf;
963 Elf64_Phdr *phdr;
964 Mbn_Hdr *mbn_hdr;
965 uint8_t *fp;
966 int len, sig_offset, cert_offset;
967
968 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
969 return 0;
970 }
971
972 sig_offset = mbn_hdr->code_size + MBN_HDR_SIZE;
973 len = sig_offset;
974 *src = malloc((len + 1) * sizeof(char));
975 if (*src == NULL) {
976 return 0;
977 }
978
979 memcpy(*src, fp + phdr->p_offset, len);
980 src_size = len;
981 (*src)[len] = '\0';
982
983 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
984 if (*sig == NULL) {
985 free(*src);
986 return 0;
987 }
988
989 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
990 (*sig)[SIG_SIZE] = '\0';
991
992 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + MBN_HDR_SIZE;
993 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
994 if (*cert == NULL) {
995 free(*src);
996 free(*sig);
997 return 0;
998 }
999 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1000 (*cert)[CERT_SIZE] = '\0';
1001
1002 return 1;
1003}
1004
1005/**
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301006 * being used to calculate the image hash
1007 *
1008 */
1009#define SW_MASK 0x3636363636363636ull
1010
1011void generate_swid_ipad(char *sw_id, unsigned long long *swid_xor_ipad)
1012{
1013 unsigned long long int val;
1014
1015 val = strtoull(sw_id, NULL, 16);
1016 *swid_xor_ipad = val ^ SW_MASK;
1017
1018 printf("%llx\n", *swid_xor_ipad);
1019}
1020
1021/**
1022 * being used to calculate the image hash
1023 *
1024 */
1025#define HW_ID_MASK 0x5c5c5c5cull
1026#define OEM_ID_MASK 0x00005c5cull
1027#define OEM_MODEL_ID_MASK 0x00005c5cull
1028
1029void generate_hwid_opad(char *hw_id, char *oem_id, char *oem_model_id,
1030 unsigned long long *hwid_xor_opad)
1031{
1032 unsigned long long val;
1033
1034 val = strtoul(hw_id, NULL, 16);
1035 *hwid_xor_opad = ((val ^ HW_ID_MASK) << 32);
1036
1037 val = strtoul(oem_id, NULL, 16);
1038 *hwid_xor_opad |= ((val ^ OEM_ID_MASK) << 16);
1039
1040 val = strtoul(oem_model_id, NULL, 16);
1041 *hwid_xor_opad |= (val ^ OEM_MODEL_ID_MASK) & 0xffff;
1042
1043 printf("%llx\n", *hwid_xor_opad);
1044}
1045
1046int create_file(char *name, char *buffer, int size)
1047{
1048 int fd;
1049
1050 fd = open(name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1051 if (fd == -1) {
1052 perror(name);
1053 return 0;
1054 }
1055
1056 if (write(fd, buffer, size) == -1) {
1057 close(fd);
1058 return 0;
1059 }
1060
1061 close(fd);
1062 return 1;
1063}
1064
1065char *create_xor_ipad_opad(char *f_xor, unsigned long long *xor_buffer)
1066{
1067 int fd;
1068 char *file;
pavipfb8e3072017-10-12 14:47:47 +05301069 unsigned long long sw_id, sw_id_be;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301070
1071 file = mktemp(f_xor);
1072 fd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1073 if (fd == -1) {
1074 perror(file);
1075 return NULL;
1076 }
1077
pavipfb8e3072017-10-12 14:47:47 +05301078 sw_id = *xor_buffer;
1079 sw_id_be = htobe64(sw_id);
1080 write(fd, &sw_id_be, sizeof(sw_id_be));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301081 close(fd);
1082 return file;
1083}
1084
1085char *read_file(char *file_name)
1086{
1087 int fd;
1088 struct stat st;
1089 char *buffer;
1090
1091 fd = open(file_name, O_RDONLY);
1092 if (fd == -1) {
1093 perror(file_name);
1094 return NULL;
1095 }
1096
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +05301097 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301098 fstat(fd, &st);
1099 buffer = malloc(st.st_size * sizeof(buffer));
1100 if (buffer == NULL) {
1101 close(fd);
1102 return NULL;
1103 }
1104 if (read(fd, buffer, st.st_size) == -1) {
1105 close(fd);
1106 return NULL;
1107 }
1108
1109 close(fd);
1110 return buffer;
1111}
1112
1113int generate_hash(char *cert, char *sw_file, char *hw_file)
1114{
1115 unsigned long long swid_xor_ipad, hwid_xor_opad;
1116 char *tmp;
1117 char *sw_id_str = find_value(cert, "SW_ID", 17);
1118 char *hw_id_str = find_value(cert, "HW_ID", 9);
1119 char *oem_id_str = find_value(cert, "OEM_ID", 5);
1120 char *oem_model_id_str = find_value(cert, "MODEL_ID", 5);
1121 char f_sw_xor[] = "/tmp/swid_xor_XXXXXX";
1122 char f_hw_xor[] = "/tmp/hwid_xor_XXXXXX";
1123
1124 if (sw_id_str == NULL || hw_id_str == NULL || oem_id_str == NULL || oem_model_id_str == NULL) {
1125 if (sw_id_str != NULL) {
1126 free(sw_id_str);
1127 }
1128 if (hw_id_str != NULL) {
1129 free(hw_id_str);
1130 }
1131 if (oem_id_str != NULL) {
1132 free(oem_id_str);
1133 }
1134 if (oem_model_id_str != NULL) {
1135 free(oem_model_id_str);
1136 }
1137 return 0;
1138 }
1139 printf("sw_id=%s\thw_id=%s\t", sw_id_str, hw_id_str);
1140 printf("oem_id=%s\toem_model_id=%s\n", oem_id_str, oem_model_id_str);
1141
1142 generate_swid_ipad(sw_id_str, &swid_xor_ipad);
1143 tmp = create_xor_ipad_opad(f_sw_xor, &swid_xor_ipad);
1144 if (tmp == NULL) {
1145 free(sw_id_str);
1146 free(hw_id_str);
1147 free(oem_id_str);
1148 free(oem_model_id_str);
1149 return 0;
1150 }
1151 strncpy(sw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301152
1153 generate_hwid_opad(hw_id_str, oem_id_str, oem_model_id_str, &hwid_xor_opad);
1154 tmp = create_xor_ipad_opad(f_hw_xor, &hwid_xor_opad);
1155 if (tmp == NULL) {
1156 free(sw_id_str);
1157 free(hw_id_str);
1158 free(oem_id_str);
1159 free(oem_model_id_str);
1160 return 0;
1161 }
1162 strncpy(hw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301163
1164 free(sw_id_str);
1165 free(hw_id_str);
1166 free(oem_id_str);
1167 free(oem_model_id_str);
1168
1169 return 1;
1170}
1171
1172void remove_file(char *sw_file, char *hw_file, char *code_file, char *pub_file)
1173{
1174 remove(sw_file);
1175 remove(hw_file);
1176 remove(code_file);
1177 remove(pub_file);
1178 remove("src");
1179 remove("sig");
1180 remove("cert");
1181}
1182
1183/**
1184 * is_component_authenticated() usage the code, signature & public key retrieved
1185 * for each component.
1186 *
1187 * @src: char *
1188 * @sig: char *
1189 * @cert: char *
1190 */
1191int is_component_authenticated(char *src, char *sig, char *cert)
1192{
1193 char command[256];
1194 char *computed_hash;
1195 char *reference_hash;
1196 char pub_key[] = "/tmp/pub_keyXXXXXX", *pub_file;
1197 char code_hash[] = "/tmp/code_hash_XXXXXX", *code_file;
1198 char tmp_hash[] = "/tmp/tmp_hash_XXXXXX", *tmp_file;
1199 char f_computed_hash[] = "/tmp/computed_hash_XXXXXX", *computed_file;
1200 char f_reference_hash[] = "/tmp/reference_hash_XXXXXX", *reference_file;
1201 char sw_file[32],hw_file[32];
1202 int retval;
1203
1204 if (!create_file("src", src, src_size) || !create_file("sig", sig, SIG_SIZE) ||
1205 !create_file("cert", cert, CERT_SIZE)) {
1206 return 0;
1207 }
1208
1209 pub_file = mktemp(pub_key);
1210 snprintf(command, sizeof(command),
1211 "openssl x509 -in cert -pubkey -inform DER -noout > %s", pub_file);
1212 retval = system(command);
1213 if (retval != 0) {
1214 remove("src");
1215 remove("sig");
1216 remove("cert");
1217 printf("Error generating public key\n");
1218 return 0;
1219 }
1220
1221 retval = generate_hash(cert, sw_file, hw_file);
1222 if (retval == 0) {
1223 return 0;
1224 }
1225
1226 code_file = mktemp(code_hash);
1227 snprintf(command, sizeof(command),
1228 "openssl dgst -sha256 -binary -out %s src", code_file);
1229 retval = system(command);
1230 if (retval != 0) {
1231 remove_file(sw_file, hw_file, code_file, pub_file);
1232 printf("Error in openssl digest\n");
1233 return 0;
1234 }
1235
1236 tmp_file = mktemp(tmp_hash);
1237 snprintf(command, sizeof(command),
1238 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1239 sw_file, code_file, tmp_file);
1240 retval = system(command);
1241 if (retval != 0) {
1242 remove_file(sw_file, hw_file, code_file, pub_file);
1243 remove(tmp_file);
1244 printf("Error generating temp has\n");
1245 return 0;
1246 }
1247
1248 computed_file = mktemp(f_computed_hash);
1249 snprintf(command, sizeof(command),
1250 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1251 hw_file, tmp_file, computed_file);
1252 retval = system(command);
1253 if (retval != 0) {
1254 remove_file(sw_file, hw_file, code_file, pub_file);
1255 remove(tmp_file);
1256 remove(computed_file);
1257 printf("Error generating hash\n");
1258 return 0;
1259 }
1260
1261 reference_file = mktemp(f_reference_hash);
1262 snprintf(command, sizeof(command),
1263 "openssl rsautl -in sig -pubin -inkey %s -verify > %s",
1264 pub_file, reference_file);
1265 retval = system(command);
1266 if (retval != 0) {
1267 remove_file(sw_file, hw_file, code_file, pub_file);
1268 remove(tmp_file);
1269 remove(computed_file);
1270 remove(reference_file);
1271 printf("Error generating reference hash\n");
1272 return 0;
1273 }
1274
1275 computed_hash = read_file(computed_file);
1276 reference_hash = read_file(reference_file);
1277 if (computed_hash == NULL || reference_hash == NULL) {
1278 remove_file(sw_file, hw_file, code_file, pub_file);
1279 remove(tmp_file);
1280 remove(computed_file);
1281 remove(reference_file);
1282 free(computed_hash?computed_hash:reference_hash);
1283 return 0;
1284 }
1285
1286 remove_file(sw_file, hw_file, code_file, pub_file);
1287 remove(tmp_file);
1288 remove(computed_file);
1289 remove(reference_file);
1290 if (strcmp(computed_hash, reference_hash)) {
1291 free(computed_hash);
1292 free(reference_hash);
1293 return 1;
1294 }
1295 free(computed_hash);
1296 free(reference_hash);
1297 return 0;
1298}
1299
1300/**
1301 * is_image_authenticated() iterates through each component and check
1302 * whether individual component is authenticated. If not, abort the FW
1303 * upgrade process.
1304 *
1305 * @img: char *
1306 */
1307int is_image_authenticated(void)
1308{
1309 int i;
1310 char *src, *sig, *cert;
1311 for (i = 0; i < NO_OF_SECTIONS; i++) {
1312 if (!sections[i].is_present) {
1313 continue;
1314 }
1315 if (!sections[i].split_components(&sections[i], &src, &sig, &cert)) {
1316 printf("Error while splitting code/signature/Certificate from %s\n",
1317 sections[i].file);
1318 return 0;
1319 }
1320 if (!is_component_authenticated(src, sig, cert)) {
1321 printf("Error while authenticating %s\n", sections[i].file);
1322 return 0;
1323 }
1324 }
1325
1326 return 1;
1327}
1328
1329int do_board_upgrade_check(char *img)
1330{
1331 if (is_authentication_check_enabled()) {
1332 if (!get_sections()) {
1333 printf("Error: %s is not a signed image\n", img);
1334 return 1;
1335 }
1336
1337 if (!is_image_authenticated()) {
1338 printf("Error: \"%s\" couldn't be authenticated. Abort...\n", img);
1339 return 1;
1340 }
1341
1342 if (!check_image_version()) {
1343 printf("Error: \"%s\" couldn't be upgraded. Abort...\n", img);
1344 return 1;
1345 }
1346 }
1347
1348 return 0;
1349}