blob: a445da59cf16bd7c0f547a7f9a5e164daab93ac9 [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"
Pavithra Palanisamya3924182017-10-26 14:43:10 +053021#define DEVCFG_VERSION_FILE "devcfg_version"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053022#define VERSION_FILE_BASENAME "/sys/devices/system/qfprom/qfprom0/"
23#define AUTHENTICATE_FILE "/sys/devices/system/qfprom/qfprom0/authenticate"
Avinash Pandeybcfcba72018-01-19 13:07:54 +053024#define SEC_AUTHENTICATE_FILE "/sys/sec_upgrade/sec_auth"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053025#define TEMP_KERNEL_PATH "/tmp/tmp_kernel.bin"
26#define MAX_SBL_VERSION 11
27#define MAX_HLOS_VERSION 32
28#define MAX_TZ_VERSION 14
29#define MAX_APPSBL_VERSION 14
30#define MAX_RPM_VERSION 8
Pavithra Palanisamya3924182017-10-26 14:43:10 +053031#define MAX_DEVCFG_VERSION 11
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053032#define HASH_P_FLAG 0x02200000
33#define TMP_FILE_DIR "/tmp/"
34#define CERT_SIZE 2048
35#define PRESENT 1
36#define MBN_HDR_SIZE 40
37#define SIG_SIZE 256
38#define NOT_PRESENT 0
39#define SIG_CERT_2_SIZE 4352
40#define SIG_CERT_3_SIZE 6400
41#define SBL_NAND_PREAMBLE 10240
42#define SBL_HDR_RESERVED 12
43#define UBI_EC_HDR_MAGIC 0x55424923
44#define UBI_VID_HDR_MAGIC 0x55424921
45
46#define ARRAY_SIZE(array) sizeof(array)/sizeof(array[0])
47
48struct image_section sections[] = {
49 {
50 .section_type = UBOOT_TYPE,
51 .type = "u-boot",
52 .max_version = MAX_APPSBL_VERSION,
53 .file = TMP_FILE_DIR,
54 .version_file = APPSBL_VERSION_FILE,
55 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053056 .img_code = "0x9"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053057 },
58 {
59 .section_type = HLOS_TYPE,
60 .type = "hlos",
61 .max_version = MAX_HLOS_VERSION,
62 .file = TMP_FILE_DIR,
63 .version_file = HLOS_VERSION_FILE,
64 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053065 .img_code = "0x17"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053066 },
67 {
68 .section_type = HLOS_TYPE,
69 .type = "ubi",
70 .tmp_file = TMP_FILE_DIR,
71 .pre_op = extract_kernel_binary,
72 .max_version = MAX_HLOS_VERSION,
73 .file = TEMP_KERNEL_PATH,
74 .version_file = HLOS_VERSION_FILE,
75 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053076 .img_code = "0x17"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053077 },
78 {
79 .section_type = TZ_TYPE,
80 .type = "tz",
81 .max_version = MAX_TZ_VERSION,
82 .file = TMP_FILE_DIR,
83 .version_file = TZ_VERSION_FILE,
84 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053085 .img_code = "0x7"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053086 },
87 {
88 .section_type = SBL_TYPE,
89 .type = "sbl1",
90 .max_version = MAX_SBL_VERSION,
91 .file = TMP_FILE_DIR,
92 .version_file = SBL_VERSION_FILE,
93 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053094 .img_code = "0x0"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053095 },
96 {
97 .section_type = SBL_TYPE,
98 .type = "sbl2",
99 .max_version = MAX_SBL_VERSION,
100 .file = TMP_FILE_DIR,
101 .version_file = SBL_VERSION_FILE,
102 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530103 .img_code = "0x5"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530104 },
105 {
106 .section_type = SBL_TYPE,
107 .type = "sbl3",
108 .max_version = MAX_SBL_VERSION,
109 .file = TMP_FILE_DIR,
110 .version_file = SBL_VERSION_FILE,
111 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530112 .img_code = "0x6"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530113 },
114 {
115 .section_type = RPM_TYPE,
116 .type = "rpm",
117 .max_version = MAX_RPM_VERSION,
118 .file = TMP_FILE_DIR,
119 .version_file = RPM_VERSION_FILE,
120 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530121 .img_code = "0xA"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530122 },
Pavithra Palanisamya3924182017-10-26 14:43:10 +0530123 {
124 .section_type = DEVCFG_TYPE,
125 .type = "devcfg",
126 .max_version = MAX_DEVCFG_VERSION,
127 .file = TMP_FILE_DIR,
128 .version_file = DEVCFG_VERSION_FILE,
129 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530130 .img_code = "0x5"
Pavithra Palanisamya3924182017-10-26 14:43:10 +0530131 },
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530132};
133
134#define NO_OF_SECTIONS ARRAY_SIZE(sections)
135int src_size;
136
137int check_mbn_elf(struct image_section **sec)
138{
139 int fd = open((*sec)->file, O_RDONLY);
140 struct stat sb;
141 uint8_t *fp;
142 Elf32_Ehdr *elf;
143
144 if (fd < 0) {
145 perror((*sec)->file);
146 return 0;
147 }
148
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530149 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530150 if (fstat(fd, &sb) == -1) {
151 perror("fstat");
152 close(fd);
153 return 0;
154 }
155
156 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
157 if (fp == MAP_FAILED) {
158 perror("mmap");
159 close(fd);
160 return 0;
161 }
162
163 elf = (Elf32_Ehdr *)fp;
164 if (!strncmp((char *)&(elf->e_ident[1]), "ELF", 3)) {
pavipfb8e3072017-10-12 14:47:47 +0530165 /* EI_CLASS Check for 32/64-bit */
166 if( ((int)(elf->e_ident[4])) == 2) {
167 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
168 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
169 } else {
170 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
171 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
172 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530173 } else if (!strncmp((char *)&(((Elf32_Ehdr *)(fp + SBL_NAND_PREAMBLE))->e_ident[1]), "ELF", 3)) {
pavipfb8e3072017-10-12 14:47:47 +0530174 if( ((int)(elf->e_ident[4])) == 2) {
175 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
176 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
177 } else {
178 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
179 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
180 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530181 } else {
182 (*sec)->get_sw_id = get_sw_id_from_component_bin;
183 (*sec)->split_components = split_code_signature_cert_from_component_bin;
184 }
185
186 return 1;
187}
188
189int get_sections(void)
190{
191 DIR *dir = opendir(TMP_FILE_DIR);
192 struct dirent *file;
193 int i;
194 struct image_section *sec;
195
196 if (dir == NULL) {
197 printf("Error accessing the image directory\n");
198 return 0;
199 }
200
201 while ((file = readdir(dir)) != NULL) {
202 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
Avinash Pandey745ead52018-03-02 12:51:26 +0530203 if (!strncmp(file->d_name, sec->type, strlen(sec->type))) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530204 if (sec->pre_op) {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530205 strlcat(sec->tmp_file, file->d_name,
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530206 sizeof(sec->tmp_file));
207 if (!sec->pre_op(sec)) {
208 printf("Error extracting kernel from ubi\n");
209 return 0;
210 }
211 } else {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530212 strlcat(sec->file, file->d_name,
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530213 sizeof(sec->file));
214 }
215 if (!check_mbn_elf(&sec)) {
216 closedir(dir);
217 return 0;
218 }
219 if (!sec->get_sw_id(sec)) {
220 closedir(dir);
221 return 0;
222 }
223 get_local_image_version(sec);
224 sec->is_present = PRESENT;
225 break;
226 }
227 }
228 }
229 closedir(dir);
230 return 1;
231}
232
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530233int load_sections(void)
234{
235 DIR *dir;
236 int i;
237 struct dirent *file;
238 struct image_section *sec;
239
240 dir = opendir(TMP_FILE_DIR);
241 if (dir == NULL) {
242 printf("Error accessing the %s image directory\n", TMP_FILE_DIR);
243 return 0;
244 }
245
246 while ((file = readdir(dir)) != NULL) {
247 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
Avinash Pandey745ead52018-03-02 12:51:26 +0530248 if (!strncmp(file->d_name, sec->type, strlen(sec->type))) {
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530249 if (sec->pre_op) {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530250 strlcat(sec->tmp_file, file->d_name,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530251 sizeof(sec->tmp_file));
252 if (!sec->pre_op(sec)) {
253 printf("Error extracting %s from ubi\n",
254 sec->tmp_file);
255 closedir(dir);
256 return 0;
257 }
258 } else {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530259 strlcat(sec->file, file->d_name,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530260 sizeof(sec->file));
261 }
262 sec->is_present = PRESENT;
263 break;
264 }
265 }
266 }
267 closedir(dir);
268 return 1;
269}
270
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530271/**
272 * is_authentication_check_enabled() - checks whether installed image is
273 * secure(1) or not(0)
274 *
275 */
276int is_authentication_check_enabled(void)
277{
278 int fd = open(AUTHENTICATE_FILE, O_RDONLY);
279 char authenticate_string[4];
280 int len;
281
282 if (fd == -1) {
283 perror(AUTHENTICATE_FILE);
284 return 0;
285 }
286
287 len = read(fd, authenticate_string, 1);
288 close(fd);
289
290 if (len > 0 && authenticate_string[0] == '0') {
291 return 0;
292 }
293
294 return 1;
295}
296
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530297int is_tz_authentication_enabled(void)
298{
299 struct stat sb;
300
301 if (stat(SEC_AUTHENTICATE_FILE, &sb) == -1) {
302 perror("stat");
303 return 0;
304 }
305 return 1;
306}
307
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530308/**
309 * get_local_image_version() check the version file & if it exists, read the
310 * value & save it into global variable local_version
311 *
312 */
313int get_local_image_version(struct image_section *section)
314{
315 int len, fd;
316 char local_version_string[16], version_file[64];
317 struct stat st;
318
319 snprintf(version_file, sizeof(version_file), "%s%s", VERSION_FILE_BASENAME, section->version_file);
320 fd = open(version_file, O_RDONLY);
321 if (fd == -1) {
322 perror(version_file);
323 return 0;
324 }
325
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530326 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530327 fstat(fd, &st);
328
329 len = st.st_size < sizeof(local_version_string) - 1 ? st.st_size :
330 sizeof(local_version_string) - 1;
331 if (read(fd, local_version_string, len) == -1) {
332 close(fd);
333 return 0;
334 }
335 local_version_string[len] = '\0';
336 close(fd);
337
338 section->local_version = atoi(local_version_string);
339 printf("Local image version:%s\n", local_version_string);
340
341 return 1;
342}
343
344/**
345 * set_local_image_version() update the version of the image by writing the version
346 * to the version file
347 *
348 */
349int set_local_image_version(struct image_section *section)
350{
351 int fd;
352 char version_string[16], version_file[64];
353 int len;
354
355 snprintf(version_file, sizeof(version_file), "%s%s", TMP_FILE_DIR, section->version_file);
356 fd = open(version_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
357 if (fd == -1) {
358 perror(version_file);
359 return 0;
360 }
361
362 len = snprintf(version_string, 8, "%d", section->img_version);
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530363 if (len < 0) {
364 printf("Error in formatting the version string");
365 return 0;
366 }
367
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530368 printf("Version to be updated:%s\n", version_string);
369 if (write(fd, version_string, len) == -1) {
370 printf("Error writing version to %s\n", version_file);
371 close(fd);
372 return 0;
373 }
374
375 close(fd);
376 return 1;
377}
378
379/**
380 * is_version_check_enabled() checks whether version check is
381 * enabled(non-zero value) or not
382 *
383 */
384int is_version_check_enabled()
385{
386 if (get_local_image_version(&sections[0]) != -1) {
387 printf("Returning 1 from is_version_check_enabled because local_version_string is non-ZERO\n");
388 return 1;
389 }
390
391 return 0;
392}
393
394char *find_value(char *buffer, char *search, int size)
395{
396 char *value = malloc(size * sizeof(char));
397 int i, j;
398
399 if (value == NULL) {
400 return NULL;
401 }
402
403 for (i = 0; i < CERT_SIZE; i++) {
404 for (j = 0; search[j] && (buffer[i + j] == search[j]); j++);
405 if (search[j] == '\0') {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530406 strlcpy(value, &buffer[i - size], size);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530407 value[size - 1] = '\0';
408 return value;
409 }
410 }
411 free(value);
412 return NULL;
413}
414
415/**
416 * get_sw_id_from_component_bin() parses the MBN header & checks image size v/s
417 * code size. If both differ, it means signature & certificates are
418 * appended at end.
419 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
420 *
421 * @bin_file: struct image_section *
422 */
423int get_sw_id_from_component_bin(struct image_section *section)
424{
425 Mbn_Hdr *mbn_hdr;
426 int fd = open(section->file, O_RDONLY);
427 struct stat sb;
428 uint8_t *fp;
429 int cert_offset;
430 char *sw_version;
431 int sig_cert_size;
432
433 if (fd == -1) {
434 perror(section->file);
435 return 0;
436 }
437
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530438 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530439 if (fstat(fd, &sb) == -1) {
440 perror("fstat");
441 close(fd);
442 return 0;
443 }
444
445 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
446 if (fp == MAP_FAILED) {
447 perror("mmap");
448 close(fd);
449 return 0;
450 }
451
452 mbn_hdr = (Mbn_Hdr *)fp;
453 if (strstr(section->file, sections[4].type)) {
454 uint32_t preamble = sections[2].is_present ? SBL_NAND_PREAMBLE : 0;
455
456 mbn_hdr = (Mbn_Hdr *)(fp + preamble + SBL_HDR_RESERVED);
457 }
458 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
459 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
pavipfb8e3072017-10-12 14:47:47 +0530460 printf("WARNING: signature certificate size is different\n");
461 // ipq807x has certificate size as dynamic, hence ignore this check
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530462 }
463
464 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
465 printf("Image with version information\n");
466 sw_version = find_value((char *)(fp + cert_offset), "SW_ID", 17);
467 if (sw_version != NULL) {
468 sw_version[8] = '\0';
469 sscanf(sw_version, "%x", &section->img_version);
470 printf("SW ID:%d\n", section->img_version);
471 free(sw_version);
472 }
473
474 close(fd);
475 return 1;
476}
477
478int process_elf(char *bin_file, uint8_t **fp, Elf32_Ehdr **elf, Elf32_Phdr **phdr, Mbn_Hdr **mbn_hdr)
479{
480 int fd = open(bin_file, O_RDONLY);
481 struct stat sb;
482 int version = 0;
483 int i = 0;
484
485 if (fd < 0) {
486 perror(bin_file);
487 return 0;
488 }
489
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530490 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530491 if (fstat(fd, &sb) == -1) {
492 perror("fstat");
493 close(fd);
494 return 0;
495 }
496
497 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
498 if (*fp == MAP_FAILED) {
499 perror("mmap");
500 close(fd);
501 return 0;
502 }
503
504 *elf = (Elf32_Ehdr *)*fp;
505 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
506 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
507 *elf = (Elf32_Ehdr *)*fp;
508 }
509
510 *phdr = (Elf32_Phdr *)(*fp + (*elf)->e_phoff);
511 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
512 if ((*phdr)->p_flags == HASH_P_FLAG) {
513 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
514 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
515 version = 1;
516 break;
517 } else {
518 printf("Error: Image without version information\n");
519 close(fd);
520 return 0;
521 }
522 }
523 }
524
525 if (version != 1) {
526 printf("Error: Image without version information\n");
527 return 0;
528 }
529
530 close(fd);
531 return 1;
532}
533
pavipfb8e3072017-10-12 14:47:47 +0530534int process_elf64(char *bin_file, uint8_t **fp, Elf64_Ehdr **elf, Elf64_Phdr **phdr, Mbn_Hdr **mbn_hdr)
535{
536 struct stat sb;
537 int i, fd, version = 0;
538
539 fd = open(bin_file, O_RDONLY);
540 if (fd < 0) {
541 perror(bin_file);
542 return 0;
543 }
544
545 memset(&sb, 0, sizeof(struct stat));
546 if (fstat(fd, &sb) == -1) {
547 perror("fstat");
548 close(fd);
549 return 0;
550 }
551
552 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
553 if (*fp == MAP_FAILED) {
554 perror("mmap");
555 close(fd);
556 return 0;
557 }
558
559 *elf = (Elf64_Ehdr *)*fp;
560 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
561 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
562 *elf = (Elf64_Ehdr *)*fp;
563 }
564
565 *phdr = (Elf64_Phdr *)(*fp + (*elf)->e_phoff);
566 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
567 if ((*phdr)->p_flags == HASH_P_FLAG) {
568 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
569 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
570 version = 1;
571 break;
572 } else {
573 printf("Error: Image without version information\n");
574 close(fd);
575 return 0;
576 }
577 }
578 }
579
580 if (version != 1) {
581 printf("Error: Image without version information\n");
582 return 0;
583 }
584
585 close(fd);
586 return 1;
587}
588
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530589/**
590 * get_sw_id_from_component_bin_elf() parses the ELF header to get the MBN header
591 * of the hash table segment. Parses the MBN header of hash table segment & checks
592 * total size v/s actual component size. If both differ, it means signature &
593 * certificates are appended at end.
594 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
595 *
596 * @bin_file: struct image_section *
597 */
598int get_sw_id_from_component_bin_elf(struct image_section *section)
599{
600 Elf32_Ehdr *elf;
601 Elf32_Phdr *phdr;
602 Mbn_Hdr *mbn_hdr;
603 uint8_t *fp;
604 int cert_offset;
605 char *sw_version;
606
607 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
608 return 0;
609 }
610
611 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
612 printf("Image with version information\n");
613 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
614 if (sw_version) {
615 sw_version[8] = '\0';
616 sscanf(sw_version, "%x", &section->img_version);
617 printf("SW ID:%d\n", section->img_version);
618 free(sw_version);
619 }
620
621 return 1;
622}
623
pavipfb8e3072017-10-12 14:47:47 +0530624/**
625 * get_sw_id_from_component_bin_elf64() parses the ELF64 header to get the MBN header
626 * of the hash table segment. Parses the MBN header of hash table segment & checks
627 * total size v/s actual component size. If both differ, it means signature &
628 * certificates are appended at end.
629 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
630 *
631 32_Phdr *phdr;* @bin_file: struct image_section *
632 */
633int get_sw_id_from_component_bin_elf64(struct image_section *section)
634{
635 Elf64_Ehdr *elf;
636 Elf64_Phdr *phdr;
637 Mbn_Hdr *mbn_hdr;
638 uint8_t *fp;
639 int cert_offset;
640 char *sw_version;
641
642 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
643 return 0;
644 }
645
646 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + 40;
647 printf("Image with version information64\n");
648 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
649 if (sw_version) {
650 sw_version[8] = '\0';
651 sscanf(sw_version, "%x", &section->img_version);
652 printf("SW ID:%d\n", section->img_version);
653 free(sw_version);
654 }
655
656 return 1;
657}
658
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530659int find_mtd_part_size(void)
660{
661 char *mtdname = "kernel";
662 char prefix[] = "/dev/mtd";
663 char dev[PATH_MAX];
664 int i = -1, fd;
665 int vol_size;
666 int flag = 0;
667 char mtd_part[256];
668 FILE *fp = fopen("/proc/mtd", "r");
669 mtd_info_t mtd_dev_info;
670
671 if (fp == NULL) {
672 printf("Error finding mtd part\n");
673 return -1;
674 }
675
676 while (fgets(dev, sizeof(dev), fp)) {
677 if (strstr(dev, mtdname)) {
678 flag = 1;
679 break;
680 }
681 i++;
682 }
683 fclose(fp);
684
685 if (flag != 1) {
686 printf("%s block not found\n", mtdname);
687 return -1;
688 }
689
690 snprintf(mtd_part, sizeof(mtd_part), "%s%d", prefix, i);
691
692 fd = open(mtd_part, O_RDWR);
693 if (fd == -1) {
694 return -1;
695 }
696
697 if (ioctl(fd, MEMGETINFO, &mtd_dev_info) == -1) {
698 printf("Error getting block size\n");
699 close(fd);
700 return -1;
701 }
702
703 vol_size = mtd_dev_info.erasesize;
704 close(fd);
705
706 return vol_size;
707}
708
709/**
710 * In case of NAND image, Kernel image is ubinized & version information is
711 * part of Kernel image. Hence need to un-ubinize the image.
712 * To get the kernel image, Find the volume with volume id 0. Kernel image
713 * is fragmented and hence to assemble it to get complete image.
714 * In UBI image, first look for UBI#, which is magic number used to identify
715 * each eraseble block. Parse the UBI header, which starts with UBI# & get
716 * the VID(volume ID) header offset as well as Data offset.
717 * Traverse to VID header offset & check the volume ID. If it is ZERO, Kernel
718 * image is stored in this volume. Use Data offset to extract the Kernel image.
719 *
720 * @bin_file: struct image_section *
721 */
722int extract_kernel_binary(struct image_section *section)
723{
724 struct ubi_ec_hdr *ubi_ec;
725 struct ubi_vid_hdr *ubi_vol;
726 uint8_t *fp;
727 int fd, ofd, magic, data_size, vid_hdr_offset, data_offset;
728 struct stat sb;
729
730 fd = open(section->tmp_file, O_RDONLY);
731 if (fd < 0) {
732 perror(section->tmp_file);
733 return 0;
734 }
735
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530736 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530737 if (fstat(fd, &sb) == -1) {
738 perror("fstat");
739 close(fd);
740 return 0;
741 }
742
743 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
744 if (fp == MAP_FAILED) {
745 perror("mmap");
746 close(fd);
747 return 0;
748 }
749
750 ofd = open(section->file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
751 if (ofd == -1) {
752 perror(section->file);
753 close(fd);
754 return 0;
755 }
756
757 data_size = find_mtd_part_size();
758 if (data_size == -1) {
759 printf("Error finding data size\n");
760 return 0;
761 }
762
763 ubi_ec = (struct ubi_ec_hdr *)fp;
764 magic = be32_to_cpu(ubi_ec->magic);
765 while (magic == UBI_EC_HDR_MAGIC) {
766 vid_hdr_offset = be32_to_cpu(ubi_ec->vid_hdr_offset);
767 data_offset = be32_to_cpu(ubi_ec->data_offset);
768 ubi_vol = (struct ubi_vid_hdr *)((uint8_t *)ubi_ec + vid_hdr_offset);
769 magic = be32_to_cpu(ubi_vol->magic);
770 if (magic != UBI_VID_HDR_MAGIC) {
771 printf("Wrong ubi format\n");
772 close(ofd);
773 close(fd);
774 return 0;
775 }
776
777 if (ubi_vol->vol_id == 0) {
778 if (write(ofd, (void *)((uint8_t *)ubi_ec + data_offset), data_size) == -1) {
779 printf("Write error\n");
780 close(fd);
781 close(ofd);
782 return 0;
783 }
784 }
785 if ((int)ubi_vol->vol_id > 0) {
786 break;
787 }
788
789 ubi_ec = (struct ubi_ec_hdr *)((uint8_t *)ubi_ec + data_offset + data_size);
790 magic = be32_to_cpu(ubi_ec->magic);
791 }
792
793 close(ofd);
794 close(fd);
795 printf("Kernel extracted from ubi image\n");
796 return 1;
797}
798
799/**
800 * is_image_version_higher() iterates through each component and check
801 * versions against locally installed version.
802 * If newer component version is lower than locally insatlled image,
803 * abort the FW upgrade process.
804 *
805 * @img: char *
806 */
807int is_image_version_higher(void)
808{
809 int i;
810 for (i = 0; i < NO_OF_SECTIONS; i++) {
811 if (!sections[i].is_present) {
812 continue;
813 }
814
815 if (sections[i].local_version > sections[i].img_version) {
816 printf("Version of image %s (%d) is lower than minimal supported version(%d)\n",
817 sections[i].file,
818 sections[i].img_version,
819 sections[i].local_version);
820 return 0;
821 }
822
823 if (sections[i].img_version > sections[i].max_version) {
824 printf("Version of image %s (%d) is higher than maximum supported version(%d)\n",
825 sections[i].file,
826 sections[i].img_version,
827 sections[i].max_version);
828 }
829 }
830
831 return 1;
832}
833
834/**
835 * Update the version information file based on currently SW_ID being installed.
836 *
837 */
838int update_version(void)
839{
840 int i;
841 for (i = 0; i < NO_OF_SECTIONS; i++) {
842 if (!sections[i].is_present) {
843 continue;
844 }
845
846 if (set_local_image_version(&sections[i]) != 1) {
847 printf("Error updating version of %s\n", sections[i].file);
848 return 0;
849 }
850 }
851
852 return 1;
853}
854
855int check_image_version(void)
856{
857 if (is_version_check_enabled() == 0) {
858 printf("Version check is not enabled, upgrade to continue !!!\n");
859 return 1;
860 }
861
862 if (is_image_version_higher() == 0) {
863 printf("New image versions are lower than existing image, upgrade to STOP !!!\n");
864 return 0;
865 }
866
867 if (update_version() != 1) {
868 printf("Error while updating verison information\n");
869 return 0;
870 }
871 printf("Update completed!\n");
872
873 return 1;
874}
875
876/**
877 * split_code_signature_cert_from_component_bin splits the component
878 * binary by splitting into code(including MBN header), signature file &
879 * attenstation certificate.
880 *
881 * @bin_file: char *
882 * @src: char *
883 * @sig: char *
884 * @cert: char *
885 */
886int split_code_signature_cert_from_component_bin(struct image_section *section,
887 char **src, char **sig, char **cert)
888{
889 Mbn_Hdr *mbn_hdr;
890 int fd = open(section->file, O_RDONLY);
891 uint8_t *fp;
892 int sig_offset = 0;
893 int cert_offset = 0;
894 struct stat sb;
895 int sig_cert_size;
896
897 if (fd == -1) {
898 perror(section->file);
899 return 0;
900 }
901
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530902 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530903 if (fstat(fd, &sb) == -1) {
904 perror("fstat");
905 close(fd);
906 return 0;
907 }
908
909 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
910 if (fp == MAP_FAILED) {
911 perror("mmap");
912 close(fd);
913 return 0;
914 }
915
916 mbn_hdr = (Mbn_Hdr *)fp;
917 if (strstr(section->file, sections[4].type)) {
918 uint32_t preamble = sections[2].is_present ? SBL_NAND_PREAMBLE : 0;
919
920 mbn_hdr = (Mbn_Hdr *)(fp + preamble + SBL_HDR_RESERVED);
921 sig_offset = preamble + MBN_HDR_SIZE;
922 cert_offset = preamble + MBN_HDR_SIZE;
923 }
924 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
925 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
Avinash Pandey5432bb22018-02-23 19:32:16 +0530926 printf("WARNING: signature certificate size is different\n");
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530927 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530928 src_size = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
929 *src = malloc(src_size + 1);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530930 if (*src == NULL) {
931 close(fd);
932 return 0;
933 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530934 memcpy(*src, fp, src_size);
935 (*src)[src_size] = '\0';
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530936
937 sig_offset += mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
938 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
939 if (*sig == NULL) {
940 free(*src);
941 return 0;
942 }
943 memcpy(*sig, fp + sig_offset, SIG_SIZE);
944 (*sig)[SIG_SIZE] = '\0';
945
946 cert_offset += mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
947 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
948 if (*cert == NULL) {
949 free(*src);
950 free(*sig);
951 return 0;
952 }
953 memcpy(*cert, fp + cert_offset, CERT_SIZE);
954 (*cert)[CERT_SIZE] = '\0';
955
956 close(fd);
957 return 1;
958}
959
960/**
961 * split_code_signature_cert_from_component_bin_elf splits the component
962 * binary by splitting into code(including ELF header), signature file &
963 * attenstation certificate.
964 *
965 * @bin_file: char *
966 * @src: char *
967 * @sig: char *
968 * @cert: char *
969 */
970int split_code_signature_cert_from_component_bin_elf(struct image_section *section,
971 char **src, char **sig, char **cert)
972{
973 Elf32_Ehdr *elf;
974 Elf32_Phdr *phdr;
975 Mbn_Hdr *mbn_hdr;
976 uint8_t *fp;
977 int sig_offset;
978 int cert_offset;
979 int len;
980
981 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
982 return 0;
983 }
984
985 sig_offset = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530986 len = sig_offset;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530987 *src = malloc((len + 1) * sizeof(char));
988 if (*src == NULL) {
989 return 0;
990 }
991 memcpy(*src, fp + phdr->p_offset, len);
992 src_size = len;
993 (*src)[len] = '\0';
994
995 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
996 if (*sig == NULL) {
997 free(*src);
998 return 0;
999 }
1000 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
1001 (*sig)[SIG_SIZE] = '\0';
1002
1003 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
1004 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
1005 if (*cert == NULL) {
1006 free(*src);
1007 free(*sig);
1008 return 0;
1009 }
1010 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1011 (*cert)[CERT_SIZE] = '\0';
1012
1013 return 1;
1014}
1015
1016/**
pavipfb8e3072017-10-12 14:47:47 +05301017 * split_code_signature_cert_from_component_bin_elf64 splits the component
1018 * binary by splitting into code(including ELF header), signature file &
1019 * attenstation certificate.
1020 *
1021 * @bin_file: char *
1022 * @src: char *
1023 * @sig: char *
1024 * @cert: char *
1025 */
1026int split_code_signature_cert_from_component_bin_elf64(struct image_section *section,
1027 char **src, char **sig, char **cert)
1028{
1029 Elf64_Ehdr *elf;
1030 Elf64_Phdr *phdr;
1031 Mbn_Hdr *mbn_hdr;
1032 uint8_t *fp;
1033 int len, sig_offset, cert_offset;
1034
1035 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
1036 return 0;
1037 }
1038
1039 sig_offset = mbn_hdr->code_size + MBN_HDR_SIZE;
1040 len = sig_offset;
1041 *src = malloc((len + 1) * sizeof(char));
1042 if (*src == NULL) {
1043 return 0;
1044 }
1045
1046 memcpy(*src, fp + phdr->p_offset, len);
1047 src_size = len;
1048 (*src)[len] = '\0';
1049
1050 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
1051 if (*sig == NULL) {
1052 free(*src);
1053 return 0;
1054 }
1055
1056 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
1057 (*sig)[SIG_SIZE] = '\0';
1058
1059 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + MBN_HDR_SIZE;
1060 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
1061 if (*cert == NULL) {
1062 free(*src);
1063 free(*sig);
1064 return 0;
1065 }
1066 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1067 (*cert)[CERT_SIZE] = '\0';
1068
1069 return 1;
1070}
1071
1072/**
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301073 * being used to calculate the image hash
1074 *
1075 */
1076#define SW_MASK 0x3636363636363636ull
1077
1078void generate_swid_ipad(char *sw_id, unsigned long long *swid_xor_ipad)
1079{
1080 unsigned long long int val;
1081
1082 val = strtoull(sw_id, NULL, 16);
1083 *swid_xor_ipad = val ^ SW_MASK;
1084
1085 printf("%llx\n", *swid_xor_ipad);
1086}
1087
1088/**
1089 * being used to calculate the image hash
1090 *
1091 */
1092#define HW_ID_MASK 0x5c5c5c5cull
1093#define OEM_ID_MASK 0x00005c5cull
1094#define OEM_MODEL_ID_MASK 0x00005c5cull
1095
1096void generate_hwid_opad(char *hw_id, char *oem_id, char *oem_model_id,
1097 unsigned long long *hwid_xor_opad)
1098{
1099 unsigned long long val;
1100
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301101 val = strtoull(hw_id, NULL, 16);
1102 *hwid_xor_opad = (((val >> 32) ^ HW_ID_MASK) << 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301103
1104 val = strtoul(oem_id, NULL, 16);
1105 *hwid_xor_opad |= ((val ^ OEM_ID_MASK) << 16);
1106
1107 val = strtoul(oem_model_id, NULL, 16);
1108 *hwid_xor_opad |= (val ^ OEM_MODEL_ID_MASK) & 0xffff;
1109
1110 printf("%llx\n", *hwid_xor_opad);
1111}
1112
1113int create_file(char *name, char *buffer, int size)
1114{
1115 int fd;
1116
1117 fd = open(name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1118 if (fd == -1) {
1119 perror(name);
1120 return 0;
1121 }
1122
1123 if (write(fd, buffer, size) == -1) {
1124 close(fd);
1125 return 0;
1126 }
1127
1128 close(fd);
1129 return 1;
1130}
1131
1132char *create_xor_ipad_opad(char *f_xor, unsigned long long *xor_buffer)
1133{
1134 int fd;
1135 char *file;
pavipfb8e3072017-10-12 14:47:47 +05301136 unsigned long long sw_id, sw_id_be;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301137
1138 file = mktemp(f_xor);
1139 fd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1140 if (fd == -1) {
1141 perror(file);
1142 return NULL;
1143 }
1144
pavipfb8e3072017-10-12 14:47:47 +05301145 sw_id = *xor_buffer;
1146 sw_id_be = htobe64(sw_id);
1147 write(fd, &sw_id_be, sizeof(sw_id_be));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301148 close(fd);
1149 return file;
1150}
1151
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301152char *read_file(char *file_name, size_t *file_size)
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301153{
1154 int fd;
1155 struct stat st;
1156 char *buffer;
1157
1158 fd = open(file_name, O_RDONLY);
1159 if (fd == -1) {
1160 perror(file_name);
1161 return NULL;
1162 }
1163
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +05301164 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301165 fstat(fd, &st);
1166 buffer = malloc(st.st_size * sizeof(buffer));
1167 if (buffer == NULL) {
1168 close(fd);
1169 return NULL;
1170 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301171
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301172 if (read(fd, buffer, st.st_size) == -1) {
1173 close(fd);
1174 return NULL;
1175 }
1176
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301177 *file_size = (size_t) st.st_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301178 close(fd);
1179 return buffer;
1180}
1181
1182int generate_hash(char *cert, char *sw_file, char *hw_file)
1183{
1184 unsigned long long swid_xor_ipad, hwid_xor_opad;
1185 char *tmp;
1186 char *sw_id_str = find_value(cert, "SW_ID", 17);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301187 char *hw_id_str = find_value(cert, "HW_ID", 17);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301188 char *oem_id_str = find_value(cert, "OEM_ID", 5);
1189 char *oem_model_id_str = find_value(cert, "MODEL_ID", 5);
1190 char f_sw_xor[] = "/tmp/swid_xor_XXXXXX";
1191 char f_hw_xor[] = "/tmp/hwid_xor_XXXXXX";
1192
1193 if (sw_id_str == NULL || hw_id_str == NULL || oem_id_str == NULL || oem_model_id_str == NULL) {
1194 if (sw_id_str != NULL) {
1195 free(sw_id_str);
1196 }
1197 if (hw_id_str != NULL) {
1198 free(hw_id_str);
1199 }
1200 if (oem_id_str != NULL) {
1201 free(oem_id_str);
1202 }
1203 if (oem_model_id_str != NULL) {
1204 free(oem_model_id_str);
1205 }
1206 return 0;
1207 }
1208 printf("sw_id=%s\thw_id=%s\t", sw_id_str, hw_id_str);
1209 printf("oem_id=%s\toem_model_id=%s\n", oem_id_str, oem_model_id_str);
1210
1211 generate_swid_ipad(sw_id_str, &swid_xor_ipad);
1212 tmp = create_xor_ipad_opad(f_sw_xor, &swid_xor_ipad);
1213 if (tmp == NULL) {
1214 free(sw_id_str);
1215 free(hw_id_str);
1216 free(oem_id_str);
1217 free(oem_model_id_str);
1218 return 0;
1219 }
Avinash Pandey7eeddce2018-02-20 12:10:17 +05301220 strlcpy(sw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301221
1222 generate_hwid_opad(hw_id_str, oem_id_str, oem_model_id_str, &hwid_xor_opad);
1223 tmp = create_xor_ipad_opad(f_hw_xor, &hwid_xor_opad);
1224 if (tmp == NULL) {
1225 free(sw_id_str);
1226 free(hw_id_str);
1227 free(oem_id_str);
1228 free(oem_model_id_str);
1229 return 0;
1230 }
Avinash Pandey7eeddce2018-02-20 12:10:17 +05301231 strlcpy(hw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301232
1233 free(sw_id_str);
1234 free(hw_id_str);
1235 free(oem_id_str);
1236 free(oem_model_id_str);
1237
1238 return 1;
1239}
1240
1241void remove_file(char *sw_file, char *hw_file, char *code_file, char *pub_file)
1242{
1243 remove(sw_file);
1244 remove(hw_file);
1245 remove(code_file);
1246 remove(pub_file);
1247 remove("src");
1248 remove("sig");
1249 remove("cert");
1250}
1251
1252/**
1253 * is_component_authenticated() usage the code, signature & public key retrieved
1254 * for each component.
1255 *
1256 * @src: char *
1257 * @sig: char *
1258 * @cert: char *
1259 */
1260int is_component_authenticated(char *src, char *sig, char *cert)
1261{
1262 char command[256];
1263 char *computed_hash;
1264 char *reference_hash;
1265 char pub_key[] = "/tmp/pub_keyXXXXXX", *pub_file;
1266 char code_hash[] = "/tmp/code_hash_XXXXXX", *code_file;
1267 char tmp_hash[] = "/tmp/tmp_hash_XXXXXX", *tmp_file;
1268 char f_computed_hash[] = "/tmp/computed_hash_XXXXXX", *computed_file;
1269 char f_reference_hash[] = "/tmp/reference_hash_XXXXXX", *reference_file;
1270 char sw_file[32],hw_file[32];
1271 int retval;
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301272 size_t comp_hash_size, ref_hash_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301273
1274 if (!create_file("src", src, src_size) || !create_file("sig", sig, SIG_SIZE) ||
1275 !create_file("cert", cert, CERT_SIZE)) {
1276 return 0;
1277 }
1278
1279 pub_file = mktemp(pub_key);
1280 snprintf(command, sizeof(command),
1281 "openssl x509 -in cert -pubkey -inform DER -noout > %s", pub_file);
1282 retval = system(command);
1283 if (retval != 0) {
1284 remove("src");
1285 remove("sig");
1286 remove("cert");
1287 printf("Error generating public key\n");
1288 return 0;
1289 }
1290
1291 retval = generate_hash(cert, sw_file, hw_file);
1292 if (retval == 0) {
1293 return 0;
1294 }
1295
1296 code_file = mktemp(code_hash);
1297 snprintf(command, sizeof(command),
1298 "openssl dgst -sha256 -binary -out %s src", code_file);
1299 retval = system(command);
1300 if (retval != 0) {
1301 remove_file(sw_file, hw_file, code_file, pub_file);
1302 printf("Error in openssl digest\n");
1303 return 0;
1304 }
1305
1306 tmp_file = mktemp(tmp_hash);
1307 snprintf(command, sizeof(command),
1308 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1309 sw_file, code_file, tmp_file);
1310 retval = system(command);
1311 if (retval != 0) {
1312 remove_file(sw_file, hw_file, code_file, pub_file);
1313 remove(tmp_file);
1314 printf("Error generating temp has\n");
1315 return 0;
1316 }
1317
1318 computed_file = mktemp(f_computed_hash);
1319 snprintf(command, sizeof(command),
1320 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1321 hw_file, tmp_file, computed_file);
1322 retval = system(command);
1323 if (retval != 0) {
1324 remove_file(sw_file, hw_file, code_file, pub_file);
1325 remove(tmp_file);
1326 remove(computed_file);
1327 printf("Error generating hash\n");
1328 return 0;
1329 }
1330
1331 reference_file = mktemp(f_reference_hash);
1332 snprintf(command, sizeof(command),
1333 "openssl rsautl -in sig -pubin -inkey %s -verify > %s",
1334 pub_file, reference_file);
1335 retval = system(command);
1336 if (retval != 0) {
1337 remove_file(sw_file, hw_file, code_file, pub_file);
1338 remove(tmp_file);
1339 remove(computed_file);
1340 remove(reference_file);
1341 printf("Error generating reference hash\n");
1342 return 0;
1343 }
1344
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301345 computed_hash = read_file(computed_file, &comp_hash_size);
1346 reference_hash = read_file(reference_file, &ref_hash_size);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301347 if (computed_hash == NULL || reference_hash == NULL) {
1348 remove_file(sw_file, hw_file, code_file, pub_file);
1349 remove(tmp_file);
1350 remove(computed_file);
1351 remove(reference_file);
1352 free(computed_hash?computed_hash:reference_hash);
1353 return 0;
1354 }
1355
1356 remove_file(sw_file, hw_file, code_file, pub_file);
1357 remove(tmp_file);
1358 remove(computed_file);
1359 remove(reference_file);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301360 if (memcmp(computed_hash, reference_hash, ref_hash_size) ||
1361 (comp_hash_size != ref_hash_size)) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301362 free(computed_hash);
1363 free(reference_hash);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301364 printf("Error: Hash or file_size not equal\n");
1365 return 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301366 }
1367 free(computed_hash);
1368 free(reference_hash);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301369 return 1;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301370}
1371
1372/**
1373 * is_image_authenticated() iterates through each component and check
1374 * whether individual component is authenticated. If not, abort the FW
1375 * upgrade process.
1376 *
1377 * @img: char *
1378 */
1379int is_image_authenticated(void)
1380{
1381 int i;
1382 char *src, *sig, *cert;
1383 for (i = 0; i < NO_OF_SECTIONS; i++) {
1384 if (!sections[i].is_present) {
1385 continue;
1386 }
1387 if (!sections[i].split_components(&sections[i], &src, &sig, &cert)) {
1388 printf("Error while splitting code/signature/Certificate from %s\n",
1389 sections[i].file);
1390 return 0;
1391 }
1392 if (!is_component_authenticated(src, sig, cert)) {
1393 printf("Error while authenticating %s\n", sections[i].file);
1394 return 0;
1395 }
1396 }
1397
1398 return 1;
1399}
1400
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301401int sec_image_auth()
1402{
1403 int fd, i, len;
1404 char buf[256];
1405
1406 fd = open(SEC_AUTHENTICATE_FILE, O_RDWR);
1407 if (-1 == fd) {
1408 perror(SEC_AUTHENTICATE_FILE);
1409 return 1;
1410 }
1411
1412 for (i = 0; i < NO_OF_SECTIONS; i++) {
1413 if (!sections[i].is_present) {
1414 continue;
1415 }
1416
1417 len = snprintf(buf, sizeof(buf), "%s %s", sections[i].img_code, sections[i].file);
1418 if (write(fd, buf, len) != len) {
1419 perror("write");
1420 close(fd);
1421 printf("%s Image authentication failed\n", buf);
1422 return 1;
1423 }
1424 }
1425 close(fd);
1426 return 0;
1427}
1428
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301429int do_board_upgrade_check(char *img)
1430{
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301431 if (is_tz_authentication_enabled()) {
1432 printf("TZ authentication enabled ...\n");
1433 if (!load_sections()) {
1434 printf("Error: Failed to load sections from image: %s\n", img);
1435 return 1;
1436 }
1437 return sec_image_auth();
1438 } else if (is_authentication_check_enabled()) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301439 if (!get_sections()) {
1440 printf("Error: %s is not a signed image\n", img);
1441 return 1;
1442 }
1443
1444 if (!is_image_authenticated()) {
1445 printf("Error: \"%s\" couldn't be authenticated. Abort...\n", img);
1446 return 1;
1447 }
1448
1449 if (!check_image_version()) {
1450 printf("Error: \"%s\" couldn't be upgraded. Abort...\n", img);
1451 return 1;
1452 }
1453 }
1454
1455 return 0;
1456}