blob: bb0fdee32b2ddcdc3ac184460f643f714e9cf00d [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;
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530194 int i,data_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530195 struct image_section *sec;
196
197 if (dir == NULL) {
198 printf("Error accessing the image directory\n");
199 return 0;
200 }
201
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530202 data_size = find_mtd_part_size();
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530203 while ((file = readdir(dir)) != NULL) {
204 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530205 /* Skip loading of ubi section if board is not from nand boot */
206 if (data_size == -1 && !strncmp(sec->type, "ubi", strlen("ubi")))
207 continue;
Avinash Pandey745ead52018-03-02 12:51:26 +0530208 if (!strncmp(file->d_name, sec->type, strlen(sec->type))) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530209 if (sec->pre_op) {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530210 strlcat(sec->tmp_file, file->d_name,
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530211 sizeof(sec->tmp_file));
212 if (!sec->pre_op(sec)) {
213 printf("Error extracting kernel from ubi\n");
214 return 0;
215 }
216 } else {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530217 strlcat(sec->file, file->d_name,
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530218 sizeof(sec->file));
219 }
220 if (!check_mbn_elf(&sec)) {
221 closedir(dir);
222 return 0;
223 }
224 if (!sec->get_sw_id(sec)) {
225 closedir(dir);
226 return 0;
227 }
228 get_local_image_version(sec);
229 sec->is_present = PRESENT;
230 break;
231 }
232 }
233 }
234 closedir(dir);
235 return 1;
236}
237
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530238int load_sections(void)
239{
240 DIR *dir;
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530241 int i,data_size;
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530242 struct dirent *file;
243 struct image_section *sec;
244
245 dir = opendir(TMP_FILE_DIR);
246 if (dir == NULL) {
247 printf("Error accessing the %s image directory\n", TMP_FILE_DIR);
248 return 0;
249 }
250
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530251 data_size = find_mtd_part_size();
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530252 while ((file = readdir(dir)) != NULL) {
253 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530254 /* Skip loading of ubi section if board is not from nand boot */
255 if (data_size == -1 && !strncmp(sec->type, "ubi", strlen("ubi")))
256 continue;
Avinash Pandey745ead52018-03-02 12:51:26 +0530257 if (!strncmp(file->d_name, sec->type, strlen(sec->type))) {
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530258 if (sec->pre_op) {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530259 strlcat(sec->tmp_file, file->d_name,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530260 sizeof(sec->tmp_file));
261 if (!sec->pre_op(sec)) {
262 printf("Error extracting %s from ubi\n",
263 sec->tmp_file);
264 closedir(dir);
265 return 0;
266 }
267 } else {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530268 strlcat(sec->file, file->d_name,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530269 sizeof(sec->file));
270 }
271 sec->is_present = PRESENT;
272 break;
273 }
274 }
275 }
276 closedir(dir);
277 return 1;
278}
279
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530280/**
281 * is_authentication_check_enabled() - checks whether installed image is
282 * secure(1) or not(0)
283 *
284 */
285int is_authentication_check_enabled(void)
286{
287 int fd = open(AUTHENTICATE_FILE, O_RDONLY);
288 char authenticate_string[4];
289 int len;
290
291 if (fd == -1) {
292 perror(AUTHENTICATE_FILE);
293 return 0;
294 }
295
296 len = read(fd, authenticate_string, 1);
297 close(fd);
298
299 if (len > 0 && authenticate_string[0] == '0') {
300 return 0;
301 }
302
303 return 1;
304}
305
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530306int is_tz_authentication_enabled(void)
307{
308 struct stat sb;
309
310 if (stat(SEC_AUTHENTICATE_FILE, &sb) == -1) {
311 perror("stat");
312 return 0;
313 }
314 return 1;
315}
316
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530317/**
318 * get_local_image_version() check the version file & if it exists, read the
319 * value & save it into global variable local_version
320 *
321 */
322int get_local_image_version(struct image_section *section)
323{
324 int len, fd;
325 char local_version_string[16], version_file[64];
326 struct stat st;
327
328 snprintf(version_file, sizeof(version_file), "%s%s", VERSION_FILE_BASENAME, section->version_file);
329 fd = open(version_file, O_RDONLY);
330 if (fd == -1) {
331 perror(version_file);
332 return 0;
333 }
334
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530335 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530336 fstat(fd, &st);
337
338 len = st.st_size < sizeof(local_version_string) - 1 ? st.st_size :
339 sizeof(local_version_string) - 1;
340 if (read(fd, local_version_string, len) == -1) {
341 close(fd);
342 return 0;
343 }
344 local_version_string[len] = '\0';
345 close(fd);
346
347 section->local_version = atoi(local_version_string);
348 printf("Local image version:%s\n", local_version_string);
349
350 return 1;
351}
352
353/**
354 * set_local_image_version() update the version of the image by writing the version
355 * to the version file
356 *
357 */
358int set_local_image_version(struct image_section *section)
359{
360 int fd;
361 char version_string[16], version_file[64];
362 int len;
363
364 snprintf(version_file, sizeof(version_file), "%s%s", TMP_FILE_DIR, section->version_file);
365 fd = open(version_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
366 if (fd == -1) {
367 perror(version_file);
368 return 0;
369 }
370
371 len = snprintf(version_string, 8, "%d", section->img_version);
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530372 if (len < 0) {
373 printf("Error in formatting the version string");
374 return 0;
375 }
376
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530377 printf("Version to be updated:%s\n", version_string);
378 if (write(fd, version_string, len) == -1) {
379 printf("Error writing version to %s\n", version_file);
380 close(fd);
381 return 0;
382 }
383
384 close(fd);
385 return 1;
386}
387
388/**
389 * is_version_check_enabled() checks whether version check is
390 * enabled(non-zero value) or not
391 *
392 */
393int is_version_check_enabled()
394{
395 if (get_local_image_version(&sections[0]) != -1) {
396 printf("Returning 1 from is_version_check_enabled because local_version_string is non-ZERO\n");
397 return 1;
398 }
399
400 return 0;
401}
402
403char *find_value(char *buffer, char *search, int size)
404{
405 char *value = malloc(size * sizeof(char));
406 int i, j;
407
408 if (value == NULL) {
409 return NULL;
410 }
411
412 for (i = 0; i < CERT_SIZE; i++) {
413 for (j = 0; search[j] && (buffer[i + j] == search[j]); j++);
414 if (search[j] == '\0') {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530415 strlcpy(value, &buffer[i - size], size);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530416 value[size - 1] = '\0';
417 return value;
418 }
419 }
420 free(value);
421 return NULL;
422}
423
424/**
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530425 * check_nand_preamble() compares first 12 bytes of section with
426 * pre defined PREAMBLE value and returns 0 if both value matches
427 */
428int check_nand_preamble(uint8_t *mfp)
429{
430 char magic[12] = { 0xd1, 0xdc, 0x4b, 0x84,
431 0x34, 0x10, 0xd7, 0x73,
432 0x5a, 0x43, 0x0b, 0x7d };
433 return memcmp(magic, mfp, sizeof(magic));
434}
435
436/**
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530437 * get_sw_id_from_component_bin() parses the MBN header & checks image size v/s
438 * code size. If both differ, it means signature & certificates are
439 * appended at end.
440 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
441 *
442 * @bin_file: struct image_section *
443 */
444int get_sw_id_from_component_bin(struct image_section *section)
445{
446 Mbn_Hdr *mbn_hdr;
447 int fd = open(section->file, O_RDONLY);
448 struct stat sb;
449 uint8_t *fp;
450 int cert_offset;
451 char *sw_version;
452 int sig_cert_size;
453
454 if (fd == -1) {
455 perror(section->file);
456 return 0;
457 }
458
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530459 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530460 if (fstat(fd, &sb) == -1) {
461 perror("fstat");
462 close(fd);
463 return 0;
464 }
465
466 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
467 if (fp == MAP_FAILED) {
468 perror("mmap");
469 close(fd);
470 return 0;
471 }
472
473 mbn_hdr = (Mbn_Hdr *)fp;
474 if (strstr(section->file, sections[4].type)) {
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530475 uint32_t preamble = !check_nand_preamble(fp) ? SBL_NAND_PREAMBLE : 0;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530476 Sbl_Hdr *sbl_hdr = (Sbl_Hdr *)(fp + preamble);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530477
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530478 sig_cert_size = sbl_hdr->image_size - sbl_hdr->code_size;
479 cert_offset = preamble + sbl_hdr->cert_ptr - sbl_hdr->image_dest_ptr +
480 SBL_HDR_SIZE;
481 } else {
482 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
483 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530484 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530485 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
pavipfb8e3072017-10-12 14:47:47 +0530486 printf("WARNING: signature certificate size is different\n");
487 // ipq807x has certificate size as dynamic, hence ignore this check
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530488 }
489
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530490 printf("Image with version information\n");
491 sw_version = find_value((char *)(fp + cert_offset), "SW_ID", 17);
492 if (sw_version != NULL) {
493 sw_version[8] = '\0';
494 sscanf(sw_version, "%x", &section->img_version);
495 printf("SW ID:%d\n", section->img_version);
496 free(sw_version);
497 }
498
499 close(fd);
500 return 1;
501}
502
503int process_elf(char *bin_file, uint8_t **fp, Elf32_Ehdr **elf, Elf32_Phdr **phdr, Mbn_Hdr **mbn_hdr)
504{
505 int fd = open(bin_file, O_RDONLY);
506 struct stat sb;
507 int version = 0;
508 int i = 0;
509
510 if (fd < 0) {
511 perror(bin_file);
512 return 0;
513 }
514
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530515 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530516 if (fstat(fd, &sb) == -1) {
517 perror("fstat");
518 close(fd);
519 return 0;
520 }
521
522 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
523 if (*fp == MAP_FAILED) {
524 perror("mmap");
525 close(fd);
526 return 0;
527 }
528
529 *elf = (Elf32_Ehdr *)*fp;
530 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
531 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
532 *elf = (Elf32_Ehdr *)*fp;
533 }
534
535 *phdr = (Elf32_Phdr *)(*fp + (*elf)->e_phoff);
536 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
537 if ((*phdr)->p_flags == HASH_P_FLAG) {
538 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
539 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
540 version = 1;
541 break;
542 } else {
543 printf("Error: Image without version information\n");
544 close(fd);
545 return 0;
546 }
547 }
548 }
549
550 if (version != 1) {
551 printf("Error: Image without version information\n");
552 return 0;
553 }
554
555 close(fd);
556 return 1;
557}
558
pavipfb8e3072017-10-12 14:47:47 +0530559int process_elf64(char *bin_file, uint8_t **fp, Elf64_Ehdr **elf, Elf64_Phdr **phdr, Mbn_Hdr **mbn_hdr)
560{
561 struct stat sb;
562 int i, fd, version = 0;
563
564 fd = open(bin_file, O_RDONLY);
565 if (fd < 0) {
566 perror(bin_file);
567 return 0;
568 }
569
570 memset(&sb, 0, sizeof(struct stat));
571 if (fstat(fd, &sb) == -1) {
572 perror("fstat");
573 close(fd);
574 return 0;
575 }
576
577 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
578 if (*fp == MAP_FAILED) {
579 perror("mmap");
580 close(fd);
581 return 0;
582 }
583
584 *elf = (Elf64_Ehdr *)*fp;
585 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
586 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
587 *elf = (Elf64_Ehdr *)*fp;
588 }
589
590 *phdr = (Elf64_Phdr *)(*fp + (*elf)->e_phoff);
591 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
592 if ((*phdr)->p_flags == HASH_P_FLAG) {
593 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
594 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
595 version = 1;
596 break;
597 } else {
598 printf("Error: Image without version information\n");
599 close(fd);
600 return 0;
601 }
602 }
603 }
604
605 if (version != 1) {
606 printf("Error: Image without version information\n");
607 return 0;
608 }
609
610 close(fd);
611 return 1;
612}
613
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530614/**
615 * get_sw_id_from_component_bin_elf() parses the ELF header to get the MBN header
616 * of the hash table segment. Parses the MBN header of hash table segment & checks
617 * total size v/s actual component size. If both differ, it means signature &
618 * certificates are appended at end.
619 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
620 *
621 * @bin_file: struct image_section *
622 */
623int get_sw_id_from_component_bin_elf(struct image_section *section)
624{
625 Elf32_Ehdr *elf;
626 Elf32_Phdr *phdr;
627 Mbn_Hdr *mbn_hdr;
628 uint8_t *fp;
629 int cert_offset;
630 char *sw_version;
631
632 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
633 return 0;
634 }
635
636 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
637 printf("Image with version information\n");
638 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
639 if (sw_version) {
640 sw_version[8] = '\0';
641 sscanf(sw_version, "%x", &section->img_version);
642 printf("SW ID:%d\n", section->img_version);
643 free(sw_version);
644 }
645
646 return 1;
647}
648
pavipfb8e3072017-10-12 14:47:47 +0530649/**
650 * get_sw_id_from_component_bin_elf64() parses the ELF64 header to get the MBN header
651 * of the hash table segment. Parses the MBN header of hash table segment & checks
652 * total size v/s actual component size. If both differ, it means signature &
653 * certificates are appended at end.
654 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
655 *
656 32_Phdr *phdr;* @bin_file: struct image_section *
657 */
658int get_sw_id_from_component_bin_elf64(struct image_section *section)
659{
660 Elf64_Ehdr *elf;
661 Elf64_Phdr *phdr;
662 Mbn_Hdr *mbn_hdr;
663 uint8_t *fp;
664 int cert_offset;
665 char *sw_version;
666
667 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
668 return 0;
669 }
670
671 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + 40;
672 printf("Image with version information64\n");
673 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
674 if (sw_version) {
675 sw_version[8] = '\0';
676 sscanf(sw_version, "%x", &section->img_version);
677 printf("SW ID:%d\n", section->img_version);
678 free(sw_version);
679 }
680
681 return 1;
682}
683
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530684int find_mtd_part_size(void)
685{
686 char *mtdname = "kernel";
687 char prefix[] = "/dev/mtd";
688 char dev[PATH_MAX];
689 int i = -1, fd;
690 int vol_size;
691 int flag = 0;
692 char mtd_part[256];
693 FILE *fp = fopen("/proc/mtd", "r");
694 mtd_info_t mtd_dev_info;
695
696 if (fp == NULL) {
697 printf("Error finding mtd part\n");
698 return -1;
699 }
700
701 while (fgets(dev, sizeof(dev), fp)) {
702 if (strstr(dev, mtdname)) {
703 flag = 1;
704 break;
705 }
706 i++;
707 }
708 fclose(fp);
709
710 if (flag != 1) {
711 printf("%s block not found\n", mtdname);
712 return -1;
713 }
714
715 snprintf(mtd_part, sizeof(mtd_part), "%s%d", prefix, i);
716
717 fd = open(mtd_part, O_RDWR);
718 if (fd == -1) {
719 return -1;
720 }
721
722 if (ioctl(fd, MEMGETINFO, &mtd_dev_info) == -1) {
723 printf("Error getting block size\n");
724 close(fd);
725 return -1;
726 }
727
728 vol_size = mtd_dev_info.erasesize;
729 close(fd);
730
731 return vol_size;
732}
733
734/**
735 * In case of NAND image, Kernel image is ubinized & version information is
736 * part of Kernel image. Hence need to un-ubinize the image.
737 * To get the kernel image, Find the volume with volume id 0. Kernel image
738 * is fragmented and hence to assemble it to get complete image.
739 * In UBI image, first look for UBI#, which is magic number used to identify
740 * each eraseble block. Parse the UBI header, which starts with UBI# & get
741 * the VID(volume ID) header offset as well as Data offset.
742 * Traverse to VID header offset & check the volume ID. If it is ZERO, Kernel
743 * image is stored in this volume. Use Data offset to extract the Kernel image.
744 *
745 * @bin_file: struct image_section *
746 */
747int extract_kernel_binary(struct image_section *section)
748{
749 struct ubi_ec_hdr *ubi_ec;
750 struct ubi_vid_hdr *ubi_vol;
751 uint8_t *fp;
752 int fd, ofd, magic, data_size, vid_hdr_offset, data_offset;
753 struct stat sb;
754
755 fd = open(section->tmp_file, O_RDONLY);
756 if (fd < 0) {
757 perror(section->tmp_file);
758 return 0;
759 }
760
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530761 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530762 if (fstat(fd, &sb) == -1) {
763 perror("fstat");
764 close(fd);
765 return 0;
766 }
767
768 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
769 if (fp == MAP_FAILED) {
770 perror("mmap");
771 close(fd);
772 return 0;
773 }
774
775 ofd = open(section->file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
776 if (ofd == -1) {
777 perror(section->file);
778 close(fd);
779 return 0;
780 }
781
782 data_size = find_mtd_part_size();
783 if (data_size == -1) {
784 printf("Error finding data size\n");
785 return 0;
786 }
787
788 ubi_ec = (struct ubi_ec_hdr *)fp;
789 magic = be32_to_cpu(ubi_ec->magic);
790 while (magic == UBI_EC_HDR_MAGIC) {
791 vid_hdr_offset = be32_to_cpu(ubi_ec->vid_hdr_offset);
792 data_offset = be32_to_cpu(ubi_ec->data_offset);
793 ubi_vol = (struct ubi_vid_hdr *)((uint8_t *)ubi_ec + vid_hdr_offset);
794 magic = be32_to_cpu(ubi_vol->magic);
795 if (magic != UBI_VID_HDR_MAGIC) {
796 printf("Wrong ubi format\n");
797 close(ofd);
798 close(fd);
799 return 0;
800 }
801
802 if (ubi_vol->vol_id == 0) {
803 if (write(ofd, (void *)((uint8_t *)ubi_ec + data_offset), data_size) == -1) {
804 printf("Write error\n");
805 close(fd);
806 close(ofd);
807 return 0;
808 }
809 }
810 if ((int)ubi_vol->vol_id > 0) {
811 break;
812 }
813
814 ubi_ec = (struct ubi_ec_hdr *)((uint8_t *)ubi_ec + data_offset + data_size);
815 magic = be32_to_cpu(ubi_ec->magic);
816 }
817
818 close(ofd);
819 close(fd);
820 printf("Kernel extracted from ubi image\n");
821 return 1;
822}
823
824/**
825 * is_image_version_higher() iterates through each component and check
826 * versions against locally installed version.
827 * If newer component version is lower than locally insatlled image,
828 * abort the FW upgrade process.
829 *
830 * @img: char *
831 */
832int is_image_version_higher(void)
833{
834 int i;
835 for (i = 0; i < NO_OF_SECTIONS; i++) {
836 if (!sections[i].is_present) {
837 continue;
838 }
839
840 if (sections[i].local_version > sections[i].img_version) {
841 printf("Version of image %s (%d) is lower than minimal supported version(%d)\n",
842 sections[i].file,
843 sections[i].img_version,
844 sections[i].local_version);
845 return 0;
846 }
847
848 if (sections[i].img_version > sections[i].max_version) {
849 printf("Version of image %s (%d) is higher than maximum supported version(%d)\n",
850 sections[i].file,
851 sections[i].img_version,
852 sections[i].max_version);
853 }
854 }
855
856 return 1;
857}
858
859/**
860 * Update the version information file based on currently SW_ID being installed.
861 *
862 */
863int update_version(void)
864{
865 int i;
866 for (i = 0; i < NO_OF_SECTIONS; i++) {
867 if (!sections[i].is_present) {
868 continue;
869 }
870
871 if (set_local_image_version(&sections[i]) != 1) {
872 printf("Error updating version of %s\n", sections[i].file);
873 return 0;
874 }
875 }
876
877 return 1;
878}
879
880int check_image_version(void)
881{
882 if (is_version_check_enabled() == 0) {
883 printf("Version check is not enabled, upgrade to continue !!!\n");
884 return 1;
885 }
886
887 if (is_image_version_higher() == 0) {
888 printf("New image versions are lower than existing image, upgrade to STOP !!!\n");
889 return 0;
890 }
891
892 if (update_version() != 1) {
893 printf("Error while updating verison information\n");
894 return 0;
895 }
896 printf("Update completed!\n");
897
898 return 1;
899}
900
901/**
902 * split_code_signature_cert_from_component_bin splits the component
903 * binary by splitting into code(including MBN header), signature file &
904 * attenstation certificate.
905 *
906 * @bin_file: char *
907 * @src: char *
908 * @sig: char *
909 * @cert: char *
910 */
911int split_code_signature_cert_from_component_bin(struct image_section *section,
912 char **src, char **sig, char **cert)
913{
914 Mbn_Hdr *mbn_hdr;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530915 Sbl_Hdr *sbl_hdr;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530916 int fd = open(section->file, O_RDONLY);
917 uint8_t *fp;
918 int sig_offset = 0;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530919 int src_offset = 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530920 int cert_offset = 0;
921 struct stat sb;
922 int sig_cert_size;
923
924 if (fd == -1) {
925 perror(section->file);
926 return 0;
927 }
928
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530929 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530930 if (fstat(fd, &sb) == -1) {
931 perror("fstat");
932 close(fd);
933 return 0;
934 }
935
936 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
937 if (fp == MAP_FAILED) {
938 perror("mmap");
939 close(fd);
940 return 0;
941 }
942
943 mbn_hdr = (Mbn_Hdr *)fp;
944 if (strstr(section->file, sections[4].type)) {
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530945 uint32_t preamble = !check_nand_preamble(fp) ? SBL_NAND_PREAMBLE : 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530946
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530947 sbl_hdr = (Sbl_Hdr *)(fp + preamble);
948 src_offset = preamble;
949 sig_offset = preamble + sbl_hdr->sig_ptr - sbl_hdr->image_dest_ptr +
950 SBL_HDR_SIZE;
951 cert_offset = preamble + sbl_hdr->cert_ptr - sbl_hdr->image_dest_ptr +
952 SBL_HDR_SIZE;
953 sig_cert_size = sbl_hdr->image_size - sbl_hdr->code_size;
954 src_size = sbl_hdr->sig_ptr - sbl_hdr->image_dest_ptr + SBL_HDR_SIZE;
955 } else {
956 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
957 src_size = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
958 sig_offset += mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
959 cert_offset += mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530960 }
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530961
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530962 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
Avinash Pandey5432bb22018-02-23 19:32:16 +0530963 printf("WARNING: signature certificate size is different\n");
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530964 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530965 *src = malloc(src_size + 1);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530966 if (*src == NULL) {
967 close(fd);
968 return 0;
969 }
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530970 memcpy(*src, fp + src_offset, src_size);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530971 (*src)[src_size] = '\0';
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530972
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530973 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
974 if (*sig == NULL) {
975 free(*src);
976 return 0;
977 }
978 memcpy(*sig, fp + sig_offset, SIG_SIZE);
979 (*sig)[SIG_SIZE] = '\0';
980
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530981 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
982 if (*cert == NULL) {
983 free(*src);
984 free(*sig);
985 return 0;
986 }
987 memcpy(*cert, fp + cert_offset, CERT_SIZE);
988 (*cert)[CERT_SIZE] = '\0';
989
990 close(fd);
991 return 1;
992}
993
994/**
995 * split_code_signature_cert_from_component_bin_elf splits the component
996 * binary by splitting into code(including ELF header), signature file &
997 * attenstation certificate.
998 *
999 * @bin_file: char *
1000 * @src: char *
1001 * @sig: char *
1002 * @cert: char *
1003 */
1004int split_code_signature_cert_from_component_bin_elf(struct image_section *section,
1005 char **src, char **sig, char **cert)
1006{
1007 Elf32_Ehdr *elf;
1008 Elf32_Phdr *phdr;
1009 Mbn_Hdr *mbn_hdr;
1010 uint8_t *fp;
1011 int sig_offset;
1012 int cert_offset;
1013 int len;
1014
1015 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
1016 return 0;
1017 }
1018
1019 sig_offset = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301020 len = sig_offset;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301021 *src = malloc((len + 1) * sizeof(char));
1022 if (*src == NULL) {
1023 return 0;
1024 }
1025 memcpy(*src, fp + phdr->p_offset, len);
1026 src_size = len;
1027 (*src)[len] = '\0';
1028
1029 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
1030 if (*sig == NULL) {
1031 free(*src);
1032 return 0;
1033 }
1034 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
1035 (*sig)[SIG_SIZE] = '\0';
1036
1037 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
1038 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
1039 if (*cert == NULL) {
1040 free(*src);
1041 free(*sig);
1042 return 0;
1043 }
1044 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1045 (*cert)[CERT_SIZE] = '\0';
1046
1047 return 1;
1048}
1049
1050/**
pavipfb8e3072017-10-12 14:47:47 +05301051 * split_code_signature_cert_from_component_bin_elf64 splits the component
1052 * binary by splitting into code(including ELF header), signature file &
1053 * attenstation certificate.
1054 *
1055 * @bin_file: char *
1056 * @src: char *
1057 * @sig: char *
1058 * @cert: char *
1059 */
1060int split_code_signature_cert_from_component_bin_elf64(struct image_section *section,
1061 char **src, char **sig, char **cert)
1062{
1063 Elf64_Ehdr *elf;
1064 Elf64_Phdr *phdr;
1065 Mbn_Hdr *mbn_hdr;
1066 uint8_t *fp;
1067 int len, sig_offset, cert_offset;
1068
1069 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
1070 return 0;
1071 }
1072
1073 sig_offset = mbn_hdr->code_size + MBN_HDR_SIZE;
1074 len = sig_offset;
1075 *src = malloc((len + 1) * sizeof(char));
1076 if (*src == NULL) {
1077 return 0;
1078 }
1079
1080 memcpy(*src, fp + phdr->p_offset, len);
1081 src_size = len;
1082 (*src)[len] = '\0';
1083
1084 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
1085 if (*sig == NULL) {
1086 free(*src);
1087 return 0;
1088 }
1089
1090 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
1091 (*sig)[SIG_SIZE] = '\0';
1092
1093 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + MBN_HDR_SIZE;
1094 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
1095 if (*cert == NULL) {
1096 free(*src);
1097 free(*sig);
1098 return 0;
1099 }
1100 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1101 (*cert)[CERT_SIZE] = '\0';
1102
1103 return 1;
1104}
1105
1106/**
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301107 * being used to calculate the image hash
1108 *
1109 */
1110#define SW_MASK 0x3636363636363636ull
1111
1112void generate_swid_ipad(char *sw_id, unsigned long long *swid_xor_ipad)
1113{
1114 unsigned long long int val;
1115
1116 val = strtoull(sw_id, NULL, 16);
1117 *swid_xor_ipad = val ^ SW_MASK;
1118
1119 printf("%llx\n", *swid_xor_ipad);
1120}
1121
1122/**
1123 * being used to calculate the image hash
1124 *
1125 */
1126#define HW_ID_MASK 0x5c5c5c5cull
1127#define OEM_ID_MASK 0x00005c5cull
1128#define OEM_MODEL_ID_MASK 0x00005c5cull
1129
1130void generate_hwid_opad(char *hw_id, char *oem_id, char *oem_model_id,
1131 unsigned long long *hwid_xor_opad)
1132{
1133 unsigned long long val;
1134
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301135 val = strtoull(hw_id, NULL, 16);
1136 *hwid_xor_opad = (((val >> 32) ^ HW_ID_MASK) << 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301137
1138 val = strtoul(oem_id, NULL, 16);
1139 *hwid_xor_opad |= ((val ^ OEM_ID_MASK) << 16);
1140
1141 val = strtoul(oem_model_id, NULL, 16);
1142 *hwid_xor_opad |= (val ^ OEM_MODEL_ID_MASK) & 0xffff;
1143
1144 printf("%llx\n", *hwid_xor_opad);
1145}
1146
1147int create_file(char *name, char *buffer, int size)
1148{
1149 int fd;
1150
1151 fd = open(name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1152 if (fd == -1) {
1153 perror(name);
1154 return 0;
1155 }
1156
1157 if (write(fd, buffer, size) == -1) {
1158 close(fd);
1159 return 0;
1160 }
1161
1162 close(fd);
1163 return 1;
1164}
1165
1166char *create_xor_ipad_opad(char *f_xor, unsigned long long *xor_buffer)
1167{
1168 int fd;
1169 char *file;
pavipfb8e3072017-10-12 14:47:47 +05301170 unsigned long long sw_id, sw_id_be;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301171
1172 file = mktemp(f_xor);
1173 fd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1174 if (fd == -1) {
1175 perror(file);
1176 return NULL;
1177 }
1178
pavipfb8e3072017-10-12 14:47:47 +05301179 sw_id = *xor_buffer;
1180 sw_id_be = htobe64(sw_id);
1181 write(fd, &sw_id_be, sizeof(sw_id_be));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301182 close(fd);
1183 return file;
1184}
1185
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301186char *read_file(char *file_name, size_t *file_size)
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301187{
1188 int fd;
1189 struct stat st;
1190 char *buffer;
1191
1192 fd = open(file_name, O_RDONLY);
1193 if (fd == -1) {
1194 perror(file_name);
1195 return NULL;
1196 }
1197
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +05301198 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301199 fstat(fd, &st);
1200 buffer = malloc(st.st_size * sizeof(buffer));
1201 if (buffer == NULL) {
1202 close(fd);
1203 return NULL;
1204 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301205
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301206 if (read(fd, buffer, st.st_size) == -1) {
1207 close(fd);
1208 return NULL;
1209 }
1210
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301211 *file_size = (size_t) st.st_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301212 close(fd);
1213 return buffer;
1214}
1215
1216int generate_hash(char *cert, char *sw_file, char *hw_file)
1217{
1218 unsigned long long swid_xor_ipad, hwid_xor_opad;
1219 char *tmp;
1220 char *sw_id_str = find_value(cert, "SW_ID", 17);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301221 char *hw_id_str = find_value(cert, "HW_ID", 17);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301222 char *oem_id_str = find_value(cert, "OEM_ID", 5);
1223 char *oem_model_id_str = find_value(cert, "MODEL_ID", 5);
1224 char f_sw_xor[] = "/tmp/swid_xor_XXXXXX";
1225 char f_hw_xor[] = "/tmp/hwid_xor_XXXXXX";
1226
1227 if (sw_id_str == NULL || hw_id_str == NULL || oem_id_str == NULL || oem_model_id_str == NULL) {
1228 if (sw_id_str != NULL) {
1229 free(sw_id_str);
1230 }
1231 if (hw_id_str != NULL) {
1232 free(hw_id_str);
1233 }
1234 if (oem_id_str != NULL) {
1235 free(oem_id_str);
1236 }
1237 if (oem_model_id_str != NULL) {
1238 free(oem_model_id_str);
1239 }
1240 return 0;
1241 }
1242 printf("sw_id=%s\thw_id=%s\t", sw_id_str, hw_id_str);
1243 printf("oem_id=%s\toem_model_id=%s\n", oem_id_str, oem_model_id_str);
1244
1245 generate_swid_ipad(sw_id_str, &swid_xor_ipad);
1246 tmp = create_xor_ipad_opad(f_sw_xor, &swid_xor_ipad);
1247 if (tmp == NULL) {
1248 free(sw_id_str);
1249 free(hw_id_str);
1250 free(oem_id_str);
1251 free(oem_model_id_str);
1252 return 0;
1253 }
Avinash Pandey7eeddce2018-02-20 12:10:17 +05301254 strlcpy(sw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301255
1256 generate_hwid_opad(hw_id_str, oem_id_str, oem_model_id_str, &hwid_xor_opad);
1257 tmp = create_xor_ipad_opad(f_hw_xor, &hwid_xor_opad);
1258 if (tmp == NULL) {
1259 free(sw_id_str);
1260 free(hw_id_str);
1261 free(oem_id_str);
1262 free(oem_model_id_str);
1263 return 0;
1264 }
Avinash Pandey7eeddce2018-02-20 12:10:17 +05301265 strlcpy(hw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301266
1267 free(sw_id_str);
1268 free(hw_id_str);
1269 free(oem_id_str);
1270 free(oem_model_id_str);
1271
1272 return 1;
1273}
1274
1275void remove_file(char *sw_file, char *hw_file, char *code_file, char *pub_file)
1276{
1277 remove(sw_file);
1278 remove(hw_file);
1279 remove(code_file);
1280 remove(pub_file);
1281 remove("src");
1282 remove("sig");
1283 remove("cert");
1284}
1285
1286/**
1287 * is_component_authenticated() usage the code, signature & public key retrieved
1288 * for each component.
1289 *
1290 * @src: char *
1291 * @sig: char *
1292 * @cert: char *
1293 */
1294int is_component_authenticated(char *src, char *sig, char *cert)
1295{
1296 char command[256];
1297 char *computed_hash;
1298 char *reference_hash;
1299 char pub_key[] = "/tmp/pub_keyXXXXXX", *pub_file;
1300 char code_hash[] = "/tmp/code_hash_XXXXXX", *code_file;
1301 char tmp_hash[] = "/tmp/tmp_hash_XXXXXX", *tmp_file;
1302 char f_computed_hash[] = "/tmp/computed_hash_XXXXXX", *computed_file;
1303 char f_reference_hash[] = "/tmp/reference_hash_XXXXXX", *reference_file;
1304 char sw_file[32],hw_file[32];
1305 int retval;
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301306 size_t comp_hash_size, ref_hash_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301307
1308 if (!create_file("src", src, src_size) || !create_file("sig", sig, SIG_SIZE) ||
1309 !create_file("cert", cert, CERT_SIZE)) {
1310 return 0;
1311 }
1312
1313 pub_file = mktemp(pub_key);
1314 snprintf(command, sizeof(command),
1315 "openssl x509 -in cert -pubkey -inform DER -noout > %s", pub_file);
1316 retval = system(command);
1317 if (retval != 0) {
1318 remove("src");
1319 remove("sig");
1320 remove("cert");
1321 printf("Error generating public key\n");
1322 return 0;
1323 }
1324
1325 retval = generate_hash(cert, sw_file, hw_file);
1326 if (retval == 0) {
1327 return 0;
1328 }
1329
1330 code_file = mktemp(code_hash);
1331 snprintf(command, sizeof(command),
1332 "openssl dgst -sha256 -binary -out %s src", code_file);
1333 retval = system(command);
1334 if (retval != 0) {
1335 remove_file(sw_file, hw_file, code_file, pub_file);
1336 printf("Error in openssl digest\n");
1337 return 0;
1338 }
1339
1340 tmp_file = mktemp(tmp_hash);
1341 snprintf(command, sizeof(command),
1342 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1343 sw_file, code_file, tmp_file);
1344 retval = system(command);
1345 if (retval != 0) {
1346 remove_file(sw_file, hw_file, code_file, pub_file);
1347 remove(tmp_file);
1348 printf("Error generating temp has\n");
1349 return 0;
1350 }
1351
1352 computed_file = mktemp(f_computed_hash);
1353 snprintf(command, sizeof(command),
1354 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1355 hw_file, tmp_file, computed_file);
1356 retval = system(command);
1357 if (retval != 0) {
1358 remove_file(sw_file, hw_file, code_file, pub_file);
1359 remove(tmp_file);
1360 remove(computed_file);
1361 printf("Error generating hash\n");
1362 return 0;
1363 }
1364
1365 reference_file = mktemp(f_reference_hash);
1366 snprintf(command, sizeof(command),
1367 "openssl rsautl -in sig -pubin -inkey %s -verify > %s",
1368 pub_file, reference_file);
1369 retval = system(command);
1370 if (retval != 0) {
1371 remove_file(sw_file, hw_file, code_file, pub_file);
1372 remove(tmp_file);
1373 remove(computed_file);
1374 remove(reference_file);
1375 printf("Error generating reference hash\n");
1376 return 0;
1377 }
1378
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301379 computed_hash = read_file(computed_file, &comp_hash_size);
1380 reference_hash = read_file(reference_file, &ref_hash_size);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301381 if (computed_hash == NULL || reference_hash == NULL) {
1382 remove_file(sw_file, hw_file, code_file, pub_file);
1383 remove(tmp_file);
1384 remove(computed_file);
1385 remove(reference_file);
1386 free(computed_hash?computed_hash:reference_hash);
1387 return 0;
1388 }
1389
1390 remove_file(sw_file, hw_file, code_file, pub_file);
1391 remove(tmp_file);
1392 remove(computed_file);
1393 remove(reference_file);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301394 if (memcmp(computed_hash, reference_hash, ref_hash_size) ||
1395 (comp_hash_size != ref_hash_size)) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301396 free(computed_hash);
1397 free(reference_hash);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301398 printf("Error: Hash or file_size not equal\n");
1399 return 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301400 }
1401 free(computed_hash);
1402 free(reference_hash);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301403 return 1;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301404}
1405
1406/**
1407 * is_image_authenticated() iterates through each component and check
1408 * whether individual component is authenticated. If not, abort the FW
1409 * upgrade process.
1410 *
1411 * @img: char *
1412 */
1413int is_image_authenticated(void)
1414{
1415 int i;
1416 char *src, *sig, *cert;
1417 for (i = 0; i < NO_OF_SECTIONS; i++) {
1418 if (!sections[i].is_present) {
1419 continue;
1420 }
1421 if (!sections[i].split_components(&sections[i], &src, &sig, &cert)) {
1422 printf("Error while splitting code/signature/Certificate from %s\n",
1423 sections[i].file);
1424 return 0;
1425 }
1426 if (!is_component_authenticated(src, sig, cert)) {
1427 printf("Error while authenticating %s\n", sections[i].file);
1428 return 0;
1429 }
1430 }
1431
1432 return 1;
1433}
1434
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301435int sec_image_auth()
1436{
1437 int fd, i, len;
Avinash Pandeya14e1022018-03-09 12:16:45 +05301438 char *buf = NULL;
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301439
1440 fd = open(SEC_AUTHENTICATE_FILE, O_RDWR);
1441 if (-1 == fd) {
1442 perror(SEC_AUTHENTICATE_FILE);
1443 return 1;
1444 }
Avinash Pandeya14e1022018-03-09 12:16:45 +05301445 buf = (char*)malloc(SIG_SIZE);
1446 if (buf == NULL) {
1447 perror("Memory allocation failed\n");
1448 close(fd);
1449 return 1;
1450 }
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301451 for (i = 0; i < NO_OF_SECTIONS; i++) {
1452 if (!sections[i].is_present) {
1453 continue;
1454 }
1455
Avinash Pandeya14e1022018-03-09 12:16:45 +05301456 len = snprintf(buf, SIG_SIZE, "%s %s", sections[i].img_code, sections[i].file);
1457 if (len < 0 || len > SIG_SIZE) {
1458 perror("Array out of Index\n");
1459 free(buf);
1460 close(fd);
1461 return 1;
1462 }
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301463 if (write(fd, buf, len) != len) {
1464 perror("write");
Avinash Pandey37c8e792018-03-23 11:25:27 +05301465 printf("%s Image authentication failed\n", buf);
Avinash Pandeya14e1022018-03-09 12:16:45 +05301466 free(buf);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301467 close(fd);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301468 return 1;
1469 }
1470 }
1471 close(fd);
Avinash Pandeya14e1022018-03-09 12:16:45 +05301472 free(buf);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301473 return 0;
1474}
1475
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301476int do_board_upgrade_check(char *img)
1477{
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301478 if (is_tz_authentication_enabled()) {
1479 printf("TZ authentication enabled ...\n");
1480 if (!load_sections()) {
1481 printf("Error: Failed to load sections from image: %s\n", img);
1482 return 1;
1483 }
1484 return sec_image_auth();
1485 } else if (is_authentication_check_enabled()) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301486 if (!get_sections()) {
1487 printf("Error: %s is not a signed image\n", img);
1488 return 1;
1489 }
1490
1491 if (!is_image_authenticated()) {
1492 printf("Error: \"%s\" couldn't be authenticated. Abort...\n", img);
1493 return 1;
1494 }
1495
1496 if (!check_image_version()) {
1497 printf("Error: \"%s\" couldn't be upgraded. Abort...\n", img);
1498 return 1;
1499 }
1500 }
1501
1502 return 0;
1503}