blob: dda618729eeb34e066418e841212fc2072b26829 [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
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +053037#define SBL_HDR_SIZE 80
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053038#define SIG_SIZE 256
39#define NOT_PRESENT 0
40#define SIG_CERT_2_SIZE 4352
41#define SIG_CERT_3_SIZE 6400
42#define SBL_NAND_PREAMBLE 10240
43#define SBL_HDR_RESERVED 12
44#define UBI_EC_HDR_MAGIC 0x55424923
45#define UBI_VID_HDR_MAGIC 0x55424921
46
47#define ARRAY_SIZE(array) sizeof(array)/sizeof(array[0])
48
49struct image_section sections[] = {
50 {
51 .section_type = UBOOT_TYPE,
52 .type = "u-boot",
53 .max_version = MAX_APPSBL_VERSION,
54 .file = TMP_FILE_DIR,
55 .version_file = APPSBL_VERSION_FILE,
56 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053057 .img_code = "0x9"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053058 },
59 {
60 .section_type = HLOS_TYPE,
61 .type = "hlos",
62 .max_version = MAX_HLOS_VERSION,
63 .file = TMP_FILE_DIR,
64 .version_file = HLOS_VERSION_FILE,
65 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053066 .img_code = "0x17"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053067 },
68 {
69 .section_type = HLOS_TYPE,
70 .type = "ubi",
71 .tmp_file = TMP_FILE_DIR,
72 .pre_op = extract_kernel_binary,
73 .max_version = MAX_HLOS_VERSION,
74 .file = TEMP_KERNEL_PATH,
75 .version_file = HLOS_VERSION_FILE,
76 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053077 .img_code = "0x17"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053078 },
79 {
80 .section_type = TZ_TYPE,
81 .type = "tz",
82 .max_version = MAX_TZ_VERSION,
83 .file = TMP_FILE_DIR,
84 .version_file = TZ_VERSION_FILE,
85 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053086 .img_code = "0x7"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053087 },
88 {
89 .section_type = SBL_TYPE,
90 .type = "sbl1",
91 .max_version = MAX_SBL_VERSION,
92 .file = TMP_FILE_DIR,
93 .version_file = SBL_VERSION_FILE,
94 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053095 .img_code = "0x0"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053096 },
97 {
98 .section_type = SBL_TYPE,
99 .type = "sbl2",
100 .max_version = MAX_SBL_VERSION,
101 .file = TMP_FILE_DIR,
102 .version_file = SBL_VERSION_FILE,
103 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530104 .img_code = "0x5"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530105 },
106 {
107 .section_type = SBL_TYPE,
108 .type = "sbl3",
109 .max_version = MAX_SBL_VERSION,
110 .file = TMP_FILE_DIR,
111 .version_file = SBL_VERSION_FILE,
112 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530113 .img_code = "0x6"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530114 },
115 {
116 .section_type = RPM_TYPE,
117 .type = "rpm",
118 .max_version = MAX_RPM_VERSION,
119 .file = TMP_FILE_DIR,
120 .version_file = RPM_VERSION_FILE,
121 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530122 .img_code = "0xA"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530123 },
Pavithra Palanisamya3924182017-10-26 14:43:10 +0530124 {
125 .section_type = DEVCFG_TYPE,
126 .type = "devcfg",
127 .max_version = MAX_DEVCFG_VERSION,
128 .file = TMP_FILE_DIR,
129 .version_file = DEVCFG_VERSION_FILE,
130 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530131 .img_code = "0x5"
Pavithra Palanisamya3924182017-10-26 14:43:10 +0530132 },
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530133};
134
135#define NO_OF_SECTIONS ARRAY_SIZE(sections)
136int src_size;
137
138int check_mbn_elf(struct image_section **sec)
139{
140 int fd = open((*sec)->file, O_RDONLY);
141 struct stat sb;
142 uint8_t *fp;
143 Elf32_Ehdr *elf;
144
145 if (fd < 0) {
146 perror((*sec)->file);
147 return 0;
148 }
149
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530150 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530151 if (fstat(fd, &sb) == -1) {
152 perror("fstat");
153 close(fd);
154 return 0;
155 }
156
157 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
158 if (fp == MAP_FAILED) {
159 perror("mmap");
160 close(fd);
161 return 0;
162 }
163
164 elf = (Elf32_Ehdr *)fp;
165 if (!strncmp((char *)&(elf->e_ident[1]), "ELF", 3)) {
pavipfb8e3072017-10-12 14:47:47 +0530166 /* EI_CLASS Check for 32/64-bit */
167 if( ((int)(elf->e_ident[4])) == 2) {
168 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
169 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
170 } else {
171 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
172 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
173 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530174 } else if (!strncmp((char *)&(((Elf32_Ehdr *)(fp + SBL_NAND_PREAMBLE))->e_ident[1]), "ELF", 3)) {
pavipfb8e3072017-10-12 14:47:47 +0530175 if( ((int)(elf->e_ident[4])) == 2) {
176 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
177 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
178 } else {
179 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
180 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
181 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530182 } else {
183 (*sec)->get_sw_id = get_sw_id_from_component_bin;
184 (*sec)->split_components = split_code_signature_cert_from_component_bin;
185 }
186
187 return 1;
188}
189
190int get_sections(void)
191{
192 DIR *dir = opendir(TMP_FILE_DIR);
193 struct dirent *file;
194 int i;
195 struct image_section *sec;
196
197 if (dir == NULL) {
198 printf("Error accessing the image directory\n");
199 return 0;
200 }
201
202 while ((file = readdir(dir)) != NULL) {
203 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
Avinash Pandey745ead52018-03-02 12:51:26 +0530204 if (!strncmp(file->d_name, sec->type, strlen(sec->type))) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530205 if (sec->pre_op) {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530206 strlcat(sec->tmp_file, file->d_name,
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530207 sizeof(sec->tmp_file));
208 if (!sec->pre_op(sec)) {
209 printf("Error extracting kernel from ubi\n");
210 return 0;
211 }
212 } else {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530213 strlcat(sec->file, file->d_name,
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530214 sizeof(sec->file));
215 }
216 if (!check_mbn_elf(&sec)) {
217 closedir(dir);
218 return 0;
219 }
220 if (!sec->get_sw_id(sec)) {
221 closedir(dir);
222 return 0;
223 }
224 get_local_image_version(sec);
225 sec->is_present = PRESENT;
226 break;
227 }
228 }
229 }
230 closedir(dir);
231 return 1;
232}
233
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530234int load_sections(void)
235{
236 DIR *dir;
237 int i;
238 struct dirent *file;
239 struct image_section *sec;
240
241 dir = opendir(TMP_FILE_DIR);
242 if (dir == NULL) {
243 printf("Error accessing the %s image directory\n", TMP_FILE_DIR);
244 return 0;
245 }
246
247 while ((file = readdir(dir)) != NULL) {
248 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
Avinash Pandey745ead52018-03-02 12:51:26 +0530249 if (!strncmp(file->d_name, sec->type, strlen(sec->type))) {
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530250 if (sec->pre_op) {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530251 strlcat(sec->tmp_file, file->d_name,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530252 sizeof(sec->tmp_file));
253 if (!sec->pre_op(sec)) {
254 printf("Error extracting %s from ubi\n",
255 sec->tmp_file);
256 closedir(dir);
257 return 0;
258 }
259 } else {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530260 strlcat(sec->file, file->d_name,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530261 sizeof(sec->file));
262 }
263 sec->is_present = PRESENT;
264 break;
265 }
266 }
267 }
268 closedir(dir);
269 return 1;
270}
271
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530272/**
273 * is_authentication_check_enabled() - checks whether installed image is
274 * secure(1) or not(0)
275 *
276 */
277int is_authentication_check_enabled(void)
278{
279 int fd = open(AUTHENTICATE_FILE, O_RDONLY);
280 char authenticate_string[4];
281 int len;
282
283 if (fd == -1) {
284 perror(AUTHENTICATE_FILE);
285 return 0;
286 }
287
288 len = read(fd, authenticate_string, 1);
289 close(fd);
290
291 if (len > 0 && authenticate_string[0] == '0') {
292 return 0;
293 }
294
295 return 1;
296}
297
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530298int is_tz_authentication_enabled(void)
299{
300 struct stat sb;
301
302 if (stat(SEC_AUTHENTICATE_FILE, &sb) == -1) {
303 perror("stat");
304 return 0;
305 }
306 return 1;
307}
308
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530309/**
310 * get_local_image_version() check the version file & if it exists, read the
311 * value & save it into global variable local_version
312 *
313 */
314int get_local_image_version(struct image_section *section)
315{
316 int len, fd;
317 char local_version_string[16], version_file[64];
318 struct stat st;
319
320 snprintf(version_file, sizeof(version_file), "%s%s", VERSION_FILE_BASENAME, section->version_file);
321 fd = open(version_file, O_RDONLY);
322 if (fd == -1) {
323 perror(version_file);
324 return 0;
325 }
326
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530327 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530328 fstat(fd, &st);
329
330 len = st.st_size < sizeof(local_version_string) - 1 ? st.st_size :
331 sizeof(local_version_string) - 1;
332 if (read(fd, local_version_string, len) == -1) {
333 close(fd);
334 return 0;
335 }
336 local_version_string[len] = '\0';
337 close(fd);
338
339 section->local_version = atoi(local_version_string);
340 printf("Local image version:%s\n", local_version_string);
341
342 return 1;
343}
344
345/**
346 * set_local_image_version() update the version of the image by writing the version
347 * to the version file
348 *
349 */
350int set_local_image_version(struct image_section *section)
351{
352 int fd;
353 char version_string[16], version_file[64];
354 int len;
355
356 snprintf(version_file, sizeof(version_file), "%s%s", TMP_FILE_DIR, section->version_file);
357 fd = open(version_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
358 if (fd == -1) {
359 perror(version_file);
360 return 0;
361 }
362
363 len = snprintf(version_string, 8, "%d", section->img_version);
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530364 if (len < 0) {
365 printf("Error in formatting the version string");
366 return 0;
367 }
368
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530369 printf("Version to be updated:%s\n", version_string);
370 if (write(fd, version_string, len) == -1) {
371 printf("Error writing version to %s\n", version_file);
372 close(fd);
373 return 0;
374 }
375
376 close(fd);
377 return 1;
378}
379
380/**
381 * is_version_check_enabled() checks whether version check is
382 * enabled(non-zero value) or not
383 *
384 */
385int is_version_check_enabled()
386{
387 if (get_local_image_version(&sections[0]) != -1) {
388 printf("Returning 1 from is_version_check_enabled because local_version_string is non-ZERO\n");
389 return 1;
390 }
391
392 return 0;
393}
394
395char *find_value(char *buffer, char *search, int size)
396{
397 char *value = malloc(size * sizeof(char));
398 int i, j;
399
400 if (value == NULL) {
401 return NULL;
402 }
403
404 for (i = 0; i < CERT_SIZE; i++) {
405 for (j = 0; search[j] && (buffer[i + j] == search[j]); j++);
406 if (search[j] == '\0') {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530407 strlcpy(value, &buffer[i - size], size);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530408 value[size - 1] = '\0';
409 return value;
410 }
411 }
412 free(value);
413 return NULL;
414}
415
416/**
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530417 * check_nand_preamble() compares first 12 bytes of section with
418 * pre defined PREAMBLE value and returns 0 if both value matches
419 */
420int check_nand_preamble(uint8_t *mfp)
421{
422 char magic[12] = { 0xd1, 0xdc, 0x4b, 0x84,
423 0x34, 0x10, 0xd7, 0x73,
424 0x5a, 0x43, 0x0b, 0x7d };
425 return memcmp(magic, mfp, sizeof(magic));
426}
427
428/**
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530429 * get_sw_id_from_component_bin() parses the MBN header & checks image size v/s
430 * code size. If both differ, it means signature & certificates are
431 * appended at end.
432 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
433 *
434 * @bin_file: struct image_section *
435 */
436int get_sw_id_from_component_bin(struct image_section *section)
437{
438 Mbn_Hdr *mbn_hdr;
439 int fd = open(section->file, O_RDONLY);
440 struct stat sb;
441 uint8_t *fp;
442 int cert_offset;
443 char *sw_version;
444 int sig_cert_size;
445
446 if (fd == -1) {
447 perror(section->file);
448 return 0;
449 }
450
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530451 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530452 if (fstat(fd, &sb) == -1) {
453 perror("fstat");
454 close(fd);
455 return 0;
456 }
457
458 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
459 if (fp == MAP_FAILED) {
460 perror("mmap");
461 close(fd);
462 return 0;
463 }
464
465 mbn_hdr = (Mbn_Hdr *)fp;
466 if (strstr(section->file, sections[4].type)) {
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530467 uint32_t preamble = !check_nand_preamble(fp) ? SBL_NAND_PREAMBLE : 0;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530468 Sbl_Hdr *sbl_hdr = (Sbl_Hdr *)(fp + preamble);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530469
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530470 sig_cert_size = sbl_hdr->image_size - sbl_hdr->code_size;
471 cert_offset = preamble + sbl_hdr->cert_ptr - sbl_hdr->image_dest_ptr +
472 SBL_HDR_SIZE;
473 } else {
474 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
475 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530476 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530477 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
pavipfb8e3072017-10-12 14:47:47 +0530478 printf("WARNING: signature certificate size is different\n");
479 // ipq807x has certificate size as dynamic, hence ignore this check
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530480 }
481
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530482 printf("Image with version information\n");
483 sw_version = find_value((char *)(fp + cert_offset), "SW_ID", 17);
484 if (sw_version != NULL) {
485 sw_version[8] = '\0';
486 sscanf(sw_version, "%x", &section->img_version);
487 printf("SW ID:%d\n", section->img_version);
488 free(sw_version);
489 }
490
491 close(fd);
492 return 1;
493}
494
495int process_elf(char *bin_file, uint8_t **fp, Elf32_Ehdr **elf, Elf32_Phdr **phdr, Mbn_Hdr **mbn_hdr)
496{
497 int fd = open(bin_file, O_RDONLY);
498 struct stat sb;
499 int version = 0;
500 int i = 0;
501
502 if (fd < 0) {
503 perror(bin_file);
504 return 0;
505 }
506
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530507 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530508 if (fstat(fd, &sb) == -1) {
509 perror("fstat");
510 close(fd);
511 return 0;
512 }
513
514 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
515 if (*fp == MAP_FAILED) {
516 perror("mmap");
517 close(fd);
518 return 0;
519 }
520
521 *elf = (Elf32_Ehdr *)*fp;
522 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
523 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
524 *elf = (Elf32_Ehdr *)*fp;
525 }
526
527 *phdr = (Elf32_Phdr *)(*fp + (*elf)->e_phoff);
528 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
529 if ((*phdr)->p_flags == HASH_P_FLAG) {
530 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
531 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
532 version = 1;
533 break;
534 } else {
535 printf("Error: Image without version information\n");
536 close(fd);
537 return 0;
538 }
539 }
540 }
541
542 if (version != 1) {
543 printf("Error: Image without version information\n");
544 return 0;
545 }
546
547 close(fd);
548 return 1;
549}
550
pavipfb8e3072017-10-12 14:47:47 +0530551int process_elf64(char *bin_file, uint8_t **fp, Elf64_Ehdr **elf, Elf64_Phdr **phdr, Mbn_Hdr **mbn_hdr)
552{
553 struct stat sb;
554 int i, fd, version = 0;
555
556 fd = open(bin_file, O_RDONLY);
557 if (fd < 0) {
558 perror(bin_file);
559 return 0;
560 }
561
562 memset(&sb, 0, sizeof(struct stat));
563 if (fstat(fd, &sb) == -1) {
564 perror("fstat");
565 close(fd);
566 return 0;
567 }
568
569 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
570 if (*fp == MAP_FAILED) {
571 perror("mmap");
572 close(fd);
573 return 0;
574 }
575
576 *elf = (Elf64_Ehdr *)*fp;
577 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
578 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
579 *elf = (Elf64_Ehdr *)*fp;
580 }
581
582 *phdr = (Elf64_Phdr *)(*fp + (*elf)->e_phoff);
583 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
584 if ((*phdr)->p_flags == HASH_P_FLAG) {
585 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
586 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
587 version = 1;
588 break;
589 } else {
590 printf("Error: Image without version information\n");
591 close(fd);
592 return 0;
593 }
594 }
595 }
596
597 if (version != 1) {
598 printf("Error: Image without version information\n");
599 return 0;
600 }
601
602 close(fd);
603 return 1;
604}
605
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530606/**
607 * get_sw_id_from_component_bin_elf() parses the ELF header to get the MBN header
608 * of the hash table segment. Parses the MBN header of hash table segment & checks
609 * total size v/s actual component size. If both differ, it means signature &
610 * certificates are appended at end.
611 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
612 *
613 * @bin_file: struct image_section *
614 */
615int get_sw_id_from_component_bin_elf(struct image_section *section)
616{
617 Elf32_Ehdr *elf;
618 Elf32_Phdr *phdr;
619 Mbn_Hdr *mbn_hdr;
620 uint8_t *fp;
621 int cert_offset;
622 char *sw_version;
623
624 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
625 return 0;
626 }
627
628 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
629 printf("Image with version information\n");
630 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
631 if (sw_version) {
632 sw_version[8] = '\0';
633 sscanf(sw_version, "%x", &section->img_version);
634 printf("SW ID:%d\n", section->img_version);
635 free(sw_version);
636 }
637
638 return 1;
639}
640
pavipfb8e3072017-10-12 14:47:47 +0530641/**
642 * get_sw_id_from_component_bin_elf64() parses the ELF64 header to get the MBN header
643 * of the hash table segment. Parses the MBN header of hash table segment & checks
644 * total size v/s actual component size. If both differ, it means signature &
645 * certificates are appended at end.
646 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
647 *
648 32_Phdr *phdr;* @bin_file: struct image_section *
649 */
650int get_sw_id_from_component_bin_elf64(struct image_section *section)
651{
652 Elf64_Ehdr *elf;
653 Elf64_Phdr *phdr;
654 Mbn_Hdr *mbn_hdr;
655 uint8_t *fp;
656 int cert_offset;
657 char *sw_version;
658
659 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
660 return 0;
661 }
662
663 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + 40;
664 printf("Image with version information64\n");
665 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
666 if (sw_version) {
667 sw_version[8] = '\0';
668 sscanf(sw_version, "%x", &section->img_version);
669 printf("SW ID:%d\n", section->img_version);
670 free(sw_version);
671 }
672
673 return 1;
674}
675
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530676int find_mtd_part_size(void)
677{
678 char *mtdname = "kernel";
679 char prefix[] = "/dev/mtd";
680 char dev[PATH_MAX];
681 int i = -1, fd;
682 int vol_size;
683 int flag = 0;
684 char mtd_part[256];
685 FILE *fp = fopen("/proc/mtd", "r");
686 mtd_info_t mtd_dev_info;
687
688 if (fp == NULL) {
689 printf("Error finding mtd part\n");
690 return -1;
691 }
692
693 while (fgets(dev, sizeof(dev), fp)) {
694 if (strstr(dev, mtdname)) {
695 flag = 1;
696 break;
697 }
698 i++;
699 }
700 fclose(fp);
701
702 if (flag != 1) {
703 printf("%s block not found\n", mtdname);
704 return -1;
705 }
706
707 snprintf(mtd_part, sizeof(mtd_part), "%s%d", prefix, i);
708
709 fd = open(mtd_part, O_RDWR);
710 if (fd == -1) {
711 return -1;
712 }
713
714 if (ioctl(fd, MEMGETINFO, &mtd_dev_info) == -1) {
715 printf("Error getting block size\n");
716 close(fd);
717 return -1;
718 }
719
720 vol_size = mtd_dev_info.erasesize;
721 close(fd);
722
723 return vol_size;
724}
725
726/**
727 * In case of NAND image, Kernel image is ubinized & version information is
728 * part of Kernel image. Hence need to un-ubinize the image.
729 * To get the kernel image, Find the volume with volume id 0. Kernel image
730 * is fragmented and hence to assemble it to get complete image.
731 * In UBI image, first look for UBI#, which is magic number used to identify
732 * each eraseble block. Parse the UBI header, which starts with UBI# & get
733 * the VID(volume ID) header offset as well as Data offset.
734 * Traverse to VID header offset & check the volume ID. If it is ZERO, Kernel
735 * image is stored in this volume. Use Data offset to extract the Kernel image.
736 *
737 * @bin_file: struct image_section *
738 */
739int extract_kernel_binary(struct image_section *section)
740{
741 struct ubi_ec_hdr *ubi_ec;
742 struct ubi_vid_hdr *ubi_vol;
743 uint8_t *fp;
744 int fd, ofd, magic, data_size, vid_hdr_offset, data_offset;
745 struct stat sb;
746
747 fd = open(section->tmp_file, O_RDONLY);
748 if (fd < 0) {
749 perror(section->tmp_file);
750 return 0;
751 }
752
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530753 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530754 if (fstat(fd, &sb) == -1) {
755 perror("fstat");
756 close(fd);
757 return 0;
758 }
759
760 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
761 if (fp == MAP_FAILED) {
762 perror("mmap");
763 close(fd);
764 return 0;
765 }
766
767 ofd = open(section->file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
768 if (ofd == -1) {
769 perror(section->file);
770 close(fd);
771 return 0;
772 }
773
774 data_size = find_mtd_part_size();
775 if (data_size == -1) {
776 printf("Error finding data size\n");
777 return 0;
778 }
779
780 ubi_ec = (struct ubi_ec_hdr *)fp;
781 magic = be32_to_cpu(ubi_ec->magic);
782 while (magic == UBI_EC_HDR_MAGIC) {
783 vid_hdr_offset = be32_to_cpu(ubi_ec->vid_hdr_offset);
784 data_offset = be32_to_cpu(ubi_ec->data_offset);
785 ubi_vol = (struct ubi_vid_hdr *)((uint8_t *)ubi_ec + vid_hdr_offset);
786 magic = be32_to_cpu(ubi_vol->magic);
787 if (magic != UBI_VID_HDR_MAGIC) {
788 printf("Wrong ubi format\n");
789 close(ofd);
790 close(fd);
791 return 0;
792 }
793
794 if (ubi_vol->vol_id == 0) {
795 if (write(ofd, (void *)((uint8_t *)ubi_ec + data_offset), data_size) == -1) {
796 printf("Write error\n");
797 close(fd);
798 close(ofd);
799 return 0;
800 }
801 }
802 if ((int)ubi_vol->vol_id > 0) {
803 break;
804 }
805
806 ubi_ec = (struct ubi_ec_hdr *)((uint8_t *)ubi_ec + data_offset + data_size);
807 magic = be32_to_cpu(ubi_ec->magic);
808 }
809
810 close(ofd);
811 close(fd);
812 printf("Kernel extracted from ubi image\n");
813 return 1;
814}
815
816/**
817 * is_image_version_higher() iterates through each component and check
818 * versions against locally installed version.
819 * If newer component version is lower than locally insatlled image,
820 * abort the FW upgrade process.
821 *
822 * @img: char *
823 */
824int is_image_version_higher(void)
825{
826 int i;
827 for (i = 0; i < NO_OF_SECTIONS; i++) {
828 if (!sections[i].is_present) {
829 continue;
830 }
831
832 if (sections[i].local_version > sections[i].img_version) {
833 printf("Version of image %s (%d) is lower than minimal supported version(%d)\n",
834 sections[i].file,
835 sections[i].img_version,
836 sections[i].local_version);
837 return 0;
838 }
839
840 if (sections[i].img_version > sections[i].max_version) {
841 printf("Version of image %s (%d) is higher than maximum supported version(%d)\n",
842 sections[i].file,
843 sections[i].img_version,
844 sections[i].max_version);
845 }
846 }
847
848 return 1;
849}
850
851/**
852 * Update the version information file based on currently SW_ID being installed.
853 *
854 */
855int update_version(void)
856{
857 int i;
858 for (i = 0; i < NO_OF_SECTIONS; i++) {
859 if (!sections[i].is_present) {
860 continue;
861 }
862
863 if (set_local_image_version(&sections[i]) != 1) {
864 printf("Error updating version of %s\n", sections[i].file);
865 return 0;
866 }
867 }
868
869 return 1;
870}
871
872int check_image_version(void)
873{
874 if (is_version_check_enabled() == 0) {
875 printf("Version check is not enabled, upgrade to continue !!!\n");
876 return 1;
877 }
878
879 if (is_image_version_higher() == 0) {
880 printf("New image versions are lower than existing image, upgrade to STOP !!!\n");
881 return 0;
882 }
883
884 if (update_version() != 1) {
885 printf("Error while updating verison information\n");
886 return 0;
887 }
888 printf("Update completed!\n");
889
890 return 1;
891}
892
893/**
894 * split_code_signature_cert_from_component_bin splits the component
895 * binary by splitting into code(including MBN 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(struct image_section *section,
904 char **src, char **sig, char **cert)
905{
906 Mbn_Hdr *mbn_hdr;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530907 Sbl_Hdr *sbl_hdr;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530908 int fd = open(section->file, O_RDONLY);
909 uint8_t *fp;
910 int sig_offset = 0;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530911 int src_offset = 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530912 int cert_offset = 0;
913 struct stat sb;
914 int sig_cert_size;
915
916 if (fd == -1) {
917 perror(section->file);
918 return 0;
919 }
920
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530921 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530922 if (fstat(fd, &sb) == -1) {
923 perror("fstat");
924 close(fd);
925 return 0;
926 }
927
928 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
929 if (fp == MAP_FAILED) {
930 perror("mmap");
931 close(fd);
932 return 0;
933 }
934
935 mbn_hdr = (Mbn_Hdr *)fp;
936 if (strstr(section->file, sections[4].type)) {
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530937 uint32_t preamble = !check_nand_preamble(fp) ? SBL_NAND_PREAMBLE : 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530938
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530939 sbl_hdr = (Sbl_Hdr *)(fp + preamble);
940 src_offset = preamble;
941 sig_offset = preamble + sbl_hdr->sig_ptr - sbl_hdr->image_dest_ptr +
942 SBL_HDR_SIZE;
943 cert_offset = preamble + sbl_hdr->cert_ptr - sbl_hdr->image_dest_ptr +
944 SBL_HDR_SIZE;
945 sig_cert_size = sbl_hdr->image_size - sbl_hdr->code_size;
946 src_size = sbl_hdr->sig_ptr - sbl_hdr->image_dest_ptr + SBL_HDR_SIZE;
947 } else {
948 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
949 src_size = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
950 sig_offset += mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
951 cert_offset += mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530952 }
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530953
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530954 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
Avinash Pandey5432bb22018-02-23 19:32:16 +0530955 printf("WARNING: signature certificate size is different\n");
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530956 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530957 *src = malloc(src_size + 1);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530958 if (*src == NULL) {
959 close(fd);
960 return 0;
961 }
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530962 memcpy(*src, fp + src_offset, src_size);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530963 (*src)[src_size] = '\0';
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530964
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530965 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
966 if (*sig == NULL) {
967 free(*src);
968 return 0;
969 }
970 memcpy(*sig, fp + sig_offset, SIG_SIZE);
971 (*sig)[SIG_SIZE] = '\0';
972
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530973 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
974 if (*cert == NULL) {
975 free(*src);
976 free(*sig);
977 return 0;
978 }
979 memcpy(*cert, fp + cert_offset, CERT_SIZE);
980 (*cert)[CERT_SIZE] = '\0';
981
982 close(fd);
983 return 1;
984}
985
986/**
987 * split_code_signature_cert_from_component_bin_elf splits the component
988 * binary by splitting into code(including ELF header), signature file &
989 * attenstation certificate.
990 *
991 * @bin_file: char *
992 * @src: char *
993 * @sig: char *
994 * @cert: char *
995 */
996int split_code_signature_cert_from_component_bin_elf(struct image_section *section,
997 char **src, char **sig, char **cert)
998{
999 Elf32_Ehdr *elf;
1000 Elf32_Phdr *phdr;
1001 Mbn_Hdr *mbn_hdr;
1002 uint8_t *fp;
1003 int sig_offset;
1004 int cert_offset;
1005 int len;
1006
1007 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
1008 return 0;
1009 }
1010
1011 sig_offset = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301012 len = sig_offset;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301013 *src = malloc((len + 1) * sizeof(char));
1014 if (*src == NULL) {
1015 return 0;
1016 }
1017 memcpy(*src, fp + phdr->p_offset, len);
1018 src_size = len;
1019 (*src)[len] = '\0';
1020
1021 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
1022 if (*sig == NULL) {
1023 free(*src);
1024 return 0;
1025 }
1026 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
1027 (*sig)[SIG_SIZE] = '\0';
1028
1029 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
1030 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
1031 if (*cert == NULL) {
1032 free(*src);
1033 free(*sig);
1034 return 0;
1035 }
1036 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1037 (*cert)[CERT_SIZE] = '\0';
1038
1039 return 1;
1040}
1041
1042/**
pavipfb8e3072017-10-12 14:47:47 +05301043 * split_code_signature_cert_from_component_bin_elf64 splits the component
1044 * binary by splitting into code(including ELF header), signature file &
1045 * attenstation certificate.
1046 *
1047 * @bin_file: char *
1048 * @src: char *
1049 * @sig: char *
1050 * @cert: char *
1051 */
1052int split_code_signature_cert_from_component_bin_elf64(struct image_section *section,
1053 char **src, char **sig, char **cert)
1054{
1055 Elf64_Ehdr *elf;
1056 Elf64_Phdr *phdr;
1057 Mbn_Hdr *mbn_hdr;
1058 uint8_t *fp;
1059 int len, sig_offset, cert_offset;
1060
1061 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
1062 return 0;
1063 }
1064
1065 sig_offset = mbn_hdr->code_size + MBN_HDR_SIZE;
1066 len = sig_offset;
1067 *src = malloc((len + 1) * sizeof(char));
1068 if (*src == NULL) {
1069 return 0;
1070 }
1071
1072 memcpy(*src, fp + phdr->p_offset, len);
1073 src_size = len;
1074 (*src)[len] = '\0';
1075
1076 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
1077 if (*sig == NULL) {
1078 free(*src);
1079 return 0;
1080 }
1081
1082 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
1083 (*sig)[SIG_SIZE] = '\0';
1084
1085 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + MBN_HDR_SIZE;
1086 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
1087 if (*cert == NULL) {
1088 free(*src);
1089 free(*sig);
1090 return 0;
1091 }
1092 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1093 (*cert)[CERT_SIZE] = '\0';
1094
1095 return 1;
1096}
1097
1098/**
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301099 * being used to calculate the image hash
1100 *
1101 */
1102#define SW_MASK 0x3636363636363636ull
1103
1104void generate_swid_ipad(char *sw_id, unsigned long long *swid_xor_ipad)
1105{
1106 unsigned long long int val;
1107
1108 val = strtoull(sw_id, NULL, 16);
1109 *swid_xor_ipad = val ^ SW_MASK;
1110
1111 printf("%llx\n", *swid_xor_ipad);
1112}
1113
1114/**
1115 * being used to calculate the image hash
1116 *
1117 */
1118#define HW_ID_MASK 0x5c5c5c5cull
1119#define OEM_ID_MASK 0x00005c5cull
1120#define OEM_MODEL_ID_MASK 0x00005c5cull
1121
1122void generate_hwid_opad(char *hw_id, char *oem_id, char *oem_model_id,
1123 unsigned long long *hwid_xor_opad)
1124{
1125 unsigned long long val;
1126
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301127 val = strtoull(hw_id, NULL, 16);
1128 *hwid_xor_opad = (((val >> 32) ^ HW_ID_MASK) << 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301129
1130 val = strtoul(oem_id, NULL, 16);
1131 *hwid_xor_opad |= ((val ^ OEM_ID_MASK) << 16);
1132
1133 val = strtoul(oem_model_id, NULL, 16);
1134 *hwid_xor_opad |= (val ^ OEM_MODEL_ID_MASK) & 0xffff;
1135
1136 printf("%llx\n", *hwid_xor_opad);
1137}
1138
1139int create_file(char *name, char *buffer, int size)
1140{
1141 int fd;
1142
1143 fd = open(name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1144 if (fd == -1) {
1145 perror(name);
1146 return 0;
1147 }
1148
1149 if (write(fd, buffer, size) == -1) {
1150 close(fd);
1151 return 0;
1152 }
1153
1154 close(fd);
1155 return 1;
1156}
1157
1158char *create_xor_ipad_opad(char *f_xor, unsigned long long *xor_buffer)
1159{
1160 int fd;
1161 char *file;
pavipfb8e3072017-10-12 14:47:47 +05301162 unsigned long long sw_id, sw_id_be;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301163
1164 file = mktemp(f_xor);
1165 fd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1166 if (fd == -1) {
1167 perror(file);
1168 return NULL;
1169 }
1170
pavipfb8e3072017-10-12 14:47:47 +05301171 sw_id = *xor_buffer;
1172 sw_id_be = htobe64(sw_id);
1173 write(fd, &sw_id_be, sizeof(sw_id_be));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301174 close(fd);
1175 return file;
1176}
1177
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301178char *read_file(char *file_name, size_t *file_size)
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301179{
1180 int fd;
1181 struct stat st;
1182 char *buffer;
1183
1184 fd = open(file_name, O_RDONLY);
1185 if (fd == -1) {
1186 perror(file_name);
1187 return NULL;
1188 }
1189
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +05301190 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301191 fstat(fd, &st);
1192 buffer = malloc(st.st_size * sizeof(buffer));
1193 if (buffer == NULL) {
1194 close(fd);
1195 return NULL;
1196 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301197
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301198 if (read(fd, buffer, st.st_size) == -1) {
1199 close(fd);
1200 return NULL;
1201 }
1202
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301203 *file_size = (size_t) st.st_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301204 close(fd);
1205 return buffer;
1206}
1207
1208int generate_hash(char *cert, char *sw_file, char *hw_file)
1209{
1210 unsigned long long swid_xor_ipad, hwid_xor_opad;
1211 char *tmp;
1212 char *sw_id_str = find_value(cert, "SW_ID", 17);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301213 char *hw_id_str = find_value(cert, "HW_ID", 17);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301214 char *oem_id_str = find_value(cert, "OEM_ID", 5);
1215 char *oem_model_id_str = find_value(cert, "MODEL_ID", 5);
1216 char f_sw_xor[] = "/tmp/swid_xor_XXXXXX";
1217 char f_hw_xor[] = "/tmp/hwid_xor_XXXXXX";
1218
1219 if (sw_id_str == NULL || hw_id_str == NULL || oem_id_str == NULL || oem_model_id_str == NULL) {
1220 if (sw_id_str != NULL) {
1221 free(sw_id_str);
1222 }
1223 if (hw_id_str != NULL) {
1224 free(hw_id_str);
1225 }
1226 if (oem_id_str != NULL) {
1227 free(oem_id_str);
1228 }
1229 if (oem_model_id_str != NULL) {
1230 free(oem_model_id_str);
1231 }
1232 return 0;
1233 }
1234 printf("sw_id=%s\thw_id=%s\t", sw_id_str, hw_id_str);
1235 printf("oem_id=%s\toem_model_id=%s\n", oem_id_str, oem_model_id_str);
1236
1237 generate_swid_ipad(sw_id_str, &swid_xor_ipad);
1238 tmp = create_xor_ipad_opad(f_sw_xor, &swid_xor_ipad);
1239 if (tmp == NULL) {
1240 free(sw_id_str);
1241 free(hw_id_str);
1242 free(oem_id_str);
1243 free(oem_model_id_str);
1244 return 0;
1245 }
Avinash Pandey7eeddce2018-02-20 12:10:17 +05301246 strlcpy(sw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301247
1248 generate_hwid_opad(hw_id_str, oem_id_str, oem_model_id_str, &hwid_xor_opad);
1249 tmp = create_xor_ipad_opad(f_hw_xor, &hwid_xor_opad);
1250 if (tmp == NULL) {
1251 free(sw_id_str);
1252 free(hw_id_str);
1253 free(oem_id_str);
1254 free(oem_model_id_str);
1255 return 0;
1256 }
Avinash Pandey7eeddce2018-02-20 12:10:17 +05301257 strlcpy(hw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301258
1259 free(sw_id_str);
1260 free(hw_id_str);
1261 free(oem_id_str);
1262 free(oem_model_id_str);
1263
1264 return 1;
1265}
1266
1267void remove_file(char *sw_file, char *hw_file, char *code_file, char *pub_file)
1268{
1269 remove(sw_file);
1270 remove(hw_file);
1271 remove(code_file);
1272 remove(pub_file);
1273 remove("src");
1274 remove("sig");
1275 remove("cert");
1276}
1277
1278/**
1279 * is_component_authenticated() usage the code, signature & public key retrieved
1280 * for each component.
1281 *
1282 * @src: char *
1283 * @sig: char *
1284 * @cert: char *
1285 */
1286int is_component_authenticated(char *src, char *sig, char *cert)
1287{
1288 char command[256];
1289 char *computed_hash;
1290 char *reference_hash;
1291 char pub_key[] = "/tmp/pub_keyXXXXXX", *pub_file;
1292 char code_hash[] = "/tmp/code_hash_XXXXXX", *code_file;
1293 char tmp_hash[] = "/tmp/tmp_hash_XXXXXX", *tmp_file;
1294 char f_computed_hash[] = "/tmp/computed_hash_XXXXXX", *computed_file;
1295 char f_reference_hash[] = "/tmp/reference_hash_XXXXXX", *reference_file;
1296 char sw_file[32],hw_file[32];
1297 int retval;
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301298 size_t comp_hash_size, ref_hash_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301299
1300 if (!create_file("src", src, src_size) || !create_file("sig", sig, SIG_SIZE) ||
1301 !create_file("cert", cert, CERT_SIZE)) {
1302 return 0;
1303 }
1304
1305 pub_file = mktemp(pub_key);
1306 snprintf(command, sizeof(command),
1307 "openssl x509 -in cert -pubkey -inform DER -noout > %s", pub_file);
1308 retval = system(command);
1309 if (retval != 0) {
1310 remove("src");
1311 remove("sig");
1312 remove("cert");
1313 printf("Error generating public key\n");
1314 return 0;
1315 }
1316
1317 retval = generate_hash(cert, sw_file, hw_file);
1318 if (retval == 0) {
1319 return 0;
1320 }
1321
1322 code_file = mktemp(code_hash);
1323 snprintf(command, sizeof(command),
1324 "openssl dgst -sha256 -binary -out %s src", code_file);
1325 retval = system(command);
1326 if (retval != 0) {
1327 remove_file(sw_file, hw_file, code_file, pub_file);
1328 printf("Error in openssl digest\n");
1329 return 0;
1330 }
1331
1332 tmp_file = mktemp(tmp_hash);
1333 snprintf(command, sizeof(command),
1334 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1335 sw_file, code_file, tmp_file);
1336 retval = system(command);
1337 if (retval != 0) {
1338 remove_file(sw_file, hw_file, code_file, pub_file);
1339 remove(tmp_file);
1340 printf("Error generating temp has\n");
1341 return 0;
1342 }
1343
1344 computed_file = mktemp(f_computed_hash);
1345 snprintf(command, sizeof(command),
1346 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1347 hw_file, tmp_file, computed_file);
1348 retval = system(command);
1349 if (retval != 0) {
1350 remove_file(sw_file, hw_file, code_file, pub_file);
1351 remove(tmp_file);
1352 remove(computed_file);
1353 printf("Error generating hash\n");
1354 return 0;
1355 }
1356
1357 reference_file = mktemp(f_reference_hash);
1358 snprintf(command, sizeof(command),
1359 "openssl rsautl -in sig -pubin -inkey %s -verify > %s",
1360 pub_file, reference_file);
1361 retval = system(command);
1362 if (retval != 0) {
1363 remove_file(sw_file, hw_file, code_file, pub_file);
1364 remove(tmp_file);
1365 remove(computed_file);
1366 remove(reference_file);
1367 printf("Error generating reference hash\n");
1368 return 0;
1369 }
1370
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301371 computed_hash = read_file(computed_file, &comp_hash_size);
1372 reference_hash = read_file(reference_file, &ref_hash_size);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301373 if (computed_hash == NULL || reference_hash == NULL) {
1374 remove_file(sw_file, hw_file, code_file, pub_file);
1375 remove(tmp_file);
1376 remove(computed_file);
1377 remove(reference_file);
1378 free(computed_hash?computed_hash:reference_hash);
1379 return 0;
1380 }
1381
1382 remove_file(sw_file, hw_file, code_file, pub_file);
1383 remove(tmp_file);
1384 remove(computed_file);
1385 remove(reference_file);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301386 if (memcmp(computed_hash, reference_hash, ref_hash_size) ||
1387 (comp_hash_size != ref_hash_size)) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301388 free(computed_hash);
1389 free(reference_hash);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301390 printf("Error: Hash or file_size not equal\n");
1391 return 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301392 }
1393 free(computed_hash);
1394 free(reference_hash);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301395 return 1;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301396}
1397
1398/**
1399 * is_image_authenticated() iterates through each component and check
1400 * whether individual component is authenticated. If not, abort the FW
1401 * upgrade process.
1402 *
1403 * @img: char *
1404 */
1405int is_image_authenticated(void)
1406{
1407 int i;
1408 char *src, *sig, *cert;
1409 for (i = 0; i < NO_OF_SECTIONS; i++) {
1410 if (!sections[i].is_present) {
1411 continue;
1412 }
1413 if (!sections[i].split_components(&sections[i], &src, &sig, &cert)) {
1414 printf("Error while splitting code/signature/Certificate from %s\n",
1415 sections[i].file);
1416 return 0;
1417 }
1418 if (!is_component_authenticated(src, sig, cert)) {
1419 printf("Error while authenticating %s\n", sections[i].file);
1420 return 0;
1421 }
1422 }
1423
1424 return 1;
1425}
1426
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301427int sec_image_auth()
1428{
1429 int fd, i, len;
Avinash Pandeya14e1022018-03-09 12:16:45 +05301430 char *buf = NULL;
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301431
1432 fd = open(SEC_AUTHENTICATE_FILE, O_RDWR);
1433 if (-1 == fd) {
1434 perror(SEC_AUTHENTICATE_FILE);
1435 return 1;
1436 }
Avinash Pandeya14e1022018-03-09 12:16:45 +05301437 buf = (char*)malloc(SIG_SIZE);
1438 if (buf == NULL) {
1439 perror("Memory allocation failed\n");
1440 close(fd);
1441 return 1;
1442 }
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301443 for (i = 0; i < NO_OF_SECTIONS; i++) {
1444 if (!sections[i].is_present) {
1445 continue;
1446 }
1447
Avinash Pandeya14e1022018-03-09 12:16:45 +05301448 len = snprintf(buf, SIG_SIZE, "%s %s", sections[i].img_code, sections[i].file);
1449 if (len < 0 || len > SIG_SIZE) {
1450 perror("Array out of Index\n");
1451 free(buf);
1452 close(fd);
1453 return 1;
1454 }
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301455 if (write(fd, buf, len) != len) {
1456 perror("write");
Avinash Pandey37c8e792018-03-23 11:25:27 +05301457 printf("%s Image authentication failed\n", buf);
Avinash Pandeya14e1022018-03-09 12:16:45 +05301458 free(buf);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301459 close(fd);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301460 return 1;
1461 }
1462 }
1463 close(fd);
Avinash Pandeya14e1022018-03-09 12:16:45 +05301464 free(buf);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301465 return 0;
1466}
1467
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301468int do_board_upgrade_check(char *img)
1469{
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301470 if (is_tz_authentication_enabled()) {
1471 printf("TZ authentication enabled ...\n");
1472 if (!load_sections()) {
1473 printf("Error: Failed to load sections from image: %s\n", img);
1474 return 1;
1475 }
1476 return sec_image_auth();
1477 } else if (is_authentication_check_enabled()) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301478 if (!get_sections()) {
1479 printf("Error: %s is not a signed image\n", img);
1480 return 1;
1481 }
1482
1483 if (!is_image_authenticated()) {
1484 printf("Error: \"%s\" couldn't be authenticated. Abort...\n", img);
1485 return 1;
1486 }
1487
1488 if (!check_image_version()) {
1489 printf("Error: \"%s\" couldn't be upgraded. Abort...\n", img);
1490 return 1;
1491 }
1492 }
1493
1494 return 0;
1495}