blob: 2c1d0a9b7030c8013738c1263774e4f7e9857ca9 [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
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053047struct image_section sections[] = {
48 {
49 .section_type = UBOOT_TYPE,
50 .type = "u-boot",
51 .max_version = MAX_APPSBL_VERSION,
52 .file = TMP_FILE_DIR,
53 .version_file = APPSBL_VERSION_FILE,
54 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053055 .img_code = "0x9"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053056 },
57 {
58 .section_type = HLOS_TYPE,
59 .type = "hlos",
60 .max_version = MAX_HLOS_VERSION,
61 .file = TMP_FILE_DIR,
62 .version_file = HLOS_VERSION_FILE,
63 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053064 .img_code = "0x17"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053065 },
66 {
67 .section_type = HLOS_TYPE,
68 .type = "ubi",
69 .tmp_file = TMP_FILE_DIR,
70 .pre_op = extract_kernel_binary,
71 .max_version = MAX_HLOS_VERSION,
72 .file = TEMP_KERNEL_PATH,
73 .version_file = HLOS_VERSION_FILE,
74 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053075 .img_code = "0x17"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053076 },
77 {
78 .section_type = TZ_TYPE,
79 .type = "tz",
80 .max_version = MAX_TZ_VERSION,
81 .file = TMP_FILE_DIR,
82 .version_file = TZ_VERSION_FILE,
83 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053084 .img_code = "0x7"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053085 },
86 {
87 .section_type = SBL_TYPE,
88 .type = "sbl1",
89 .max_version = MAX_SBL_VERSION,
90 .file = TMP_FILE_DIR,
91 .version_file = SBL_VERSION_FILE,
92 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +053093 .img_code = "0x0"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +053094 },
95 {
96 .section_type = SBL_TYPE,
97 .type = "sbl2",
98 .max_version = MAX_SBL_VERSION,
99 .file = TMP_FILE_DIR,
100 .version_file = SBL_VERSION_FILE,
101 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530102 .img_code = "0x5"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530103 },
104 {
105 .section_type = SBL_TYPE,
106 .type = "sbl3",
107 .max_version = MAX_SBL_VERSION,
108 .file = TMP_FILE_DIR,
109 .version_file = SBL_VERSION_FILE,
110 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530111 .img_code = "0x6"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530112 },
113 {
114 .section_type = RPM_TYPE,
115 .type = "rpm",
116 .max_version = MAX_RPM_VERSION,
117 .file = TMP_FILE_DIR,
118 .version_file = RPM_VERSION_FILE,
119 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530120 .img_code = "0xA"
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530121 },
Pavithra Palanisamya3924182017-10-26 14:43:10 +0530122 {
123 .section_type = DEVCFG_TYPE,
124 .type = "devcfg",
125 .max_version = MAX_DEVCFG_VERSION,
126 .file = TMP_FILE_DIR,
127 .version_file = DEVCFG_VERSION_FILE,
128 .is_present = NOT_PRESENT,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530129 .img_code = "0x5"
Pavithra Palanisamya3924182017-10-26 14:43:10 +0530130 },
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530131};
132
Naresh Kumar Mehtaca8b1732019-04-01 14:24:07 +0530133#define NO_OF_SECTIONS ARRAY_SIZE(sections)
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530134int src_size;
135
136int check_mbn_elf(struct image_section **sec)
137{
138 int fd = open((*sec)->file, O_RDONLY);
139 struct stat sb;
140 uint8_t *fp;
141 Elf32_Ehdr *elf;
142
143 if (fd < 0) {
144 perror((*sec)->file);
145 return 0;
146 }
147
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530148 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530149 if (fstat(fd, &sb) == -1) {
150 perror("fstat");
151 close(fd);
152 return 0;
153 }
154
155 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
156 if (fp == MAP_FAILED) {
157 perror("mmap");
158 close(fd);
159 return 0;
160 }
161
162 elf = (Elf32_Ehdr *)fp;
163 if (!strncmp((char *)&(elf->e_ident[1]), "ELF", 3)) {
pavipfb8e3072017-10-12 14:47:47 +0530164 /* EI_CLASS Check for 32/64-bit */
165 if( ((int)(elf->e_ident[4])) == 2) {
166 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
167 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
168 } else {
169 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
170 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
171 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530172 } else if (!strncmp((char *)&(((Elf32_Ehdr *)(fp + SBL_NAND_PREAMBLE))->e_ident[1]), "ELF", 3)) {
pavipfb8e3072017-10-12 14:47:47 +0530173 if( ((int)(elf->e_ident[4])) == 2) {
174 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf64;
175 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf64;
176 } else {
177 (*sec)->get_sw_id = get_sw_id_from_component_bin_elf;
178 (*sec)->split_components = split_code_signature_cert_from_component_bin_elf;
179 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530180 } else {
181 (*sec)->get_sw_id = get_sw_id_from_component_bin;
182 (*sec)->split_components = split_code_signature_cert_from_component_bin;
183 }
184
185 return 1;
186}
187
188int get_sections(void)
189{
190 DIR *dir = opendir(TMP_FILE_DIR);
191 struct dirent *file;
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530192 int i,data_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530193 struct image_section *sec;
194
195 if (dir == NULL) {
196 printf("Error accessing the image directory\n");
197 return 0;
198 }
199
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530200 data_size = find_mtd_part_size();
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530201 while ((file = readdir(dir)) != NULL) {
202 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530203 /* Skip loading of ubi section if board is not from nand boot */
204 if (data_size == -1 && !strncmp(sec->type, "ubi", strlen("ubi")))
205 continue;
Avinash Pandey745ead52018-03-02 12:51:26 +0530206 if (!strncmp(file->d_name, sec->type, strlen(sec->type))) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530207 if (sec->pre_op) {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530208 strlcat(sec->tmp_file, file->d_name,
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530209 sizeof(sec->tmp_file));
210 if (!sec->pre_op(sec)) {
211 printf("Error extracting kernel from ubi\n");
212 return 0;
213 }
214 } else {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530215 strlcat(sec->file, file->d_name,
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530216 sizeof(sec->file));
217 }
218 if (!check_mbn_elf(&sec)) {
219 closedir(dir);
220 return 0;
221 }
222 if (!sec->get_sw_id(sec)) {
223 closedir(dir);
224 return 0;
225 }
226 get_local_image_version(sec);
227 sec->is_present = PRESENT;
228 break;
229 }
230 }
231 }
232 closedir(dir);
233 return 1;
234}
235
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530236int load_sections(void)
237{
238 DIR *dir;
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530239 int i,data_size;
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530240 struct dirent *file;
241 struct image_section *sec;
242
243 dir = opendir(TMP_FILE_DIR);
244 if (dir == NULL) {
245 printf("Error accessing the %s image directory\n", TMP_FILE_DIR);
246 return 0;
247 }
248
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530249 data_size = find_mtd_part_size();
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530250 while ((file = readdir(dir)) != NULL) {
251 for (i = 0, sec = &sections[0]; i < NO_OF_SECTIONS; i++, sec++) {
Avinash Pandey34ee85c2018-08-14 12:42:07 +0530252 /* Skip loading of ubi section if board is not from nand boot */
253 if (data_size == -1 && !strncmp(sec->type, "ubi", strlen("ubi")))
254 continue;
Avinash Pandey745ead52018-03-02 12:51:26 +0530255 if (!strncmp(file->d_name, sec->type, strlen(sec->type))) {
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530256 if (sec->pre_op) {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530257 strlcat(sec->tmp_file, file->d_name,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530258 sizeof(sec->tmp_file));
259 if (!sec->pre_op(sec)) {
260 printf("Error extracting %s from ubi\n",
261 sec->tmp_file);
262 closedir(dir);
263 return 0;
264 }
265 } else {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530266 strlcat(sec->file, file->d_name,
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530267 sizeof(sec->file));
268 }
269 sec->is_present = PRESENT;
270 break;
271 }
272 }
273 }
274 closedir(dir);
275 return 1;
276}
277
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530278/**
279 * is_authentication_check_enabled() - checks whether installed image is
280 * secure(1) or not(0)
281 *
282 */
283int is_authentication_check_enabled(void)
284{
285 int fd = open(AUTHENTICATE_FILE, O_RDONLY);
286 char authenticate_string[4];
287 int len;
288
289 if (fd == -1) {
290 perror(AUTHENTICATE_FILE);
291 return 0;
292 }
293
294 len = read(fd, authenticate_string, 1);
295 close(fd);
296
297 if (len > 0 && authenticate_string[0] == '0') {
298 return 0;
299 }
300
301 return 1;
302}
303
Avinash Pandeybcfcba72018-01-19 13:07:54 +0530304int is_tz_authentication_enabled(void)
305{
306 struct stat sb;
307
308 if (stat(SEC_AUTHENTICATE_FILE, &sb) == -1) {
309 perror("stat");
310 return 0;
311 }
312 return 1;
313}
314
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530315/**
316 * get_local_image_version() check the version file & if it exists, read the
317 * value & save it into global variable local_version
318 *
319 */
320int get_local_image_version(struct image_section *section)
321{
322 int len, fd;
323 char local_version_string[16], version_file[64];
324 struct stat st;
325
326 snprintf(version_file, sizeof(version_file), "%s%s", VERSION_FILE_BASENAME, section->version_file);
327 fd = open(version_file, O_RDONLY);
328 if (fd == -1) {
329 perror(version_file);
330 return 0;
331 }
332
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530333 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530334 fstat(fd, &st);
335
336 len = st.st_size < sizeof(local_version_string) - 1 ? st.st_size :
337 sizeof(local_version_string) - 1;
338 if (read(fd, local_version_string, len) == -1) {
339 close(fd);
340 return 0;
341 }
342 local_version_string[len] = '\0';
343 close(fd);
344
345 section->local_version = atoi(local_version_string);
346 printf("Local image version:%s\n", local_version_string);
347
348 return 1;
349}
350
351/**
352 * set_local_image_version() update the version of the image by writing the version
353 * to the version file
354 *
355 */
356int set_local_image_version(struct image_section *section)
357{
358 int fd;
359 char version_string[16], version_file[64];
360 int len;
361
362 snprintf(version_file, sizeof(version_file), "%s%s", TMP_FILE_DIR, section->version_file);
363 fd = open(version_file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
364 if (fd == -1) {
365 perror(version_file);
366 return 0;
367 }
368
369 len = snprintf(version_string, 8, "%d", section->img_version);
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530370 if (len < 0) {
371 printf("Error in formatting the version string");
372 return 0;
373 }
374
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530375 printf("Version to be updated:%s\n", version_string);
376 if (write(fd, version_string, len) == -1) {
377 printf("Error writing version to %s\n", version_file);
378 close(fd);
379 return 0;
380 }
381
382 close(fd);
383 return 1;
384}
385
386/**
387 * is_version_check_enabled() checks whether version check is
388 * enabled(non-zero value) or not
389 *
390 */
391int is_version_check_enabled()
392{
393 if (get_local_image_version(&sections[0]) != -1) {
394 printf("Returning 1 from is_version_check_enabled because local_version_string is non-ZERO\n");
395 return 1;
396 }
397
398 return 0;
399}
400
401char *find_value(char *buffer, char *search, int size)
402{
403 char *value = malloc(size * sizeof(char));
404 int i, j;
405
406 if (value == NULL) {
407 return NULL;
408 }
409
410 for (i = 0; i < CERT_SIZE; i++) {
411 for (j = 0; search[j] && (buffer[i + j] == search[j]); j++);
412 if (search[j] == '\0') {
Avinash Pandey7eeddce2018-02-20 12:10:17 +0530413 strlcpy(value, &buffer[i - size], size);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530414 value[size - 1] = '\0';
415 return value;
416 }
417 }
418 free(value);
419 return NULL;
420}
421
422/**
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530423 * check_nand_preamble() compares first 12 bytes of section with
424 * pre defined PREAMBLE value and returns 0 if both value matches
425 */
426int check_nand_preamble(uint8_t *mfp)
427{
428 char magic[12] = { 0xd1, 0xdc, 0x4b, 0x84,
429 0x34, 0x10, 0xd7, 0x73,
430 0x5a, 0x43, 0x0b, 0x7d };
431 return memcmp(magic, mfp, sizeof(magic));
432}
433
434/**
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530435 * get_sw_id_from_component_bin() parses the MBN header & checks image size v/s
436 * code size. If both differ, it means signature & certificates are
437 * appended at end.
438 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
439 *
440 * @bin_file: struct image_section *
441 */
442int get_sw_id_from_component_bin(struct image_section *section)
443{
444 Mbn_Hdr *mbn_hdr;
445 int fd = open(section->file, O_RDONLY);
446 struct stat sb;
447 uint8_t *fp;
448 int cert_offset;
449 char *sw_version;
450 int sig_cert_size;
451
452 if (fd == -1) {
453 perror(section->file);
454 return 0;
455 }
456
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530457 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530458 if (fstat(fd, &sb) == -1) {
459 perror("fstat");
460 close(fd);
461 return 0;
462 }
463
464 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
465 if (fp == MAP_FAILED) {
466 perror("mmap");
467 close(fd);
468 return 0;
469 }
470
471 mbn_hdr = (Mbn_Hdr *)fp;
472 if (strstr(section->file, sections[4].type)) {
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530473 uint32_t preamble = !check_nand_preamble(fp) ? SBL_NAND_PREAMBLE : 0;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530474 Sbl_Hdr *sbl_hdr = (Sbl_Hdr *)(fp + preamble);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530475
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530476 sig_cert_size = sbl_hdr->image_size - sbl_hdr->code_size;
477 cert_offset = preamble + sbl_hdr->cert_ptr - sbl_hdr->image_dest_ptr +
478 SBL_HDR_SIZE;
479 } else {
480 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
481 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530482 }
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530483 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
pavipfb8e3072017-10-12 14:47:47 +0530484 printf("WARNING: signature certificate size is different\n");
485 // ipq807x has certificate size as dynamic, hence ignore this check
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530486 }
487
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530488 printf("Image with version information\n");
489 sw_version = find_value((char *)(fp + cert_offset), "SW_ID", 17);
490 if (sw_version != NULL) {
491 sw_version[8] = '\0';
492 sscanf(sw_version, "%x", &section->img_version);
493 printf("SW ID:%d\n", section->img_version);
494 free(sw_version);
495 }
496
497 close(fd);
498 return 1;
499}
500
501int process_elf(char *bin_file, uint8_t **fp, Elf32_Ehdr **elf, Elf32_Phdr **phdr, Mbn_Hdr **mbn_hdr)
502{
503 int fd = open(bin_file, O_RDONLY);
504 struct stat sb;
505 int version = 0;
506 int i = 0;
507
508 if (fd < 0) {
509 perror(bin_file);
510 return 0;
511 }
512
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530513 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530514 if (fstat(fd, &sb) == -1) {
515 perror("fstat");
516 close(fd);
517 return 0;
518 }
519
520 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
521 if (*fp == MAP_FAILED) {
522 perror("mmap");
523 close(fd);
524 return 0;
525 }
526
527 *elf = (Elf32_Ehdr *)*fp;
528 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
529 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
530 *elf = (Elf32_Ehdr *)*fp;
531 }
532
533 *phdr = (Elf32_Phdr *)(*fp + (*elf)->e_phoff);
534 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
535 if ((*phdr)->p_flags == HASH_P_FLAG) {
536 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
537 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
538 version = 1;
539 break;
540 } else {
541 printf("Error: Image without version information\n");
542 close(fd);
543 return 0;
544 }
545 }
546 }
547
548 if (version != 1) {
549 printf("Error: Image without version information\n");
550 return 0;
551 }
552
553 close(fd);
554 return 1;
555}
556
pavipfb8e3072017-10-12 14:47:47 +0530557int process_elf64(char *bin_file, uint8_t **fp, Elf64_Ehdr **elf, Elf64_Phdr **phdr, Mbn_Hdr **mbn_hdr)
558{
559 struct stat sb;
560 int i, fd, version = 0;
561
562 fd = open(bin_file, O_RDONLY);
563 if (fd < 0) {
564 perror(bin_file);
565 return 0;
566 }
567
568 memset(&sb, 0, sizeof(struct stat));
569 if (fstat(fd, &sb) == -1) {
570 perror("fstat");
571 close(fd);
572 return 0;
573 }
574
575 *fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
576 if (*fp == MAP_FAILED) {
577 perror("mmap");
578 close(fd);
579 return 0;
580 }
581
582 *elf = (Elf64_Ehdr *)*fp;
583 while (strncmp((char *)&((*elf)->e_ident[1]), "ELF", 3)) {
584 *fp = (uint8_t *)((char *)(*fp) + SBL_NAND_PREAMBLE);
585 *elf = (Elf64_Ehdr *)*fp;
586 }
587
588 *phdr = (Elf64_Phdr *)(*fp + (*elf)->e_phoff);
589 for (i = 0; i < (*elf)->e_phnum; i++, (*phdr)++) {
590 if ((*phdr)->p_flags == HASH_P_FLAG) {
591 *mbn_hdr = (Mbn_Hdr *)(*fp + (*phdr)->p_offset);
592 if ((*mbn_hdr)->image_size != (*mbn_hdr)->code_size) {
593 version = 1;
594 break;
595 } else {
596 printf("Error: Image without version information\n");
597 close(fd);
598 return 0;
599 }
600 }
601 }
602
603 if (version != 1) {
604 printf("Error: Image without version information\n");
605 return 0;
606 }
607
608 close(fd);
609 return 1;
610}
611
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530612/**
613 * get_sw_id_from_component_bin_elf() parses the ELF header to get the MBN header
614 * of the hash table segment. Parses the MBN header of hash table segment & checks
615 * total size v/s actual component size. If both differ, it means signature &
616 * certificates are appended at end.
617 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
618 *
619 * @bin_file: struct image_section *
620 */
621int get_sw_id_from_component_bin_elf(struct image_section *section)
622{
623 Elf32_Ehdr *elf;
624 Elf32_Phdr *phdr;
625 Mbn_Hdr *mbn_hdr;
626 uint8_t *fp;
627 int cert_offset;
628 char *sw_version;
629
630 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
631 return 0;
632 }
633
634 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + 40;
635 printf("Image with version information\n");
636 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
637 if (sw_version) {
638 sw_version[8] = '\0';
639 sscanf(sw_version, "%x", &section->img_version);
640 printf("SW ID:%d\n", section->img_version);
641 free(sw_version);
642 }
643
644 return 1;
645}
646
pavipfb8e3072017-10-12 14:47:47 +0530647/**
648 * get_sw_id_from_component_bin_elf64() parses the ELF64 header to get the MBN header
649 * of the hash table segment. Parses the MBN header of hash table segment & checks
650 * total size v/s actual component size. If both differ, it means signature &
651 * certificates are appended at end.
652 * Extract the attestation certificate & read the Subject & retreive the SW_ID.
653 *
654 32_Phdr *phdr;* @bin_file: struct image_section *
655 */
656int get_sw_id_from_component_bin_elf64(struct image_section *section)
657{
658 Elf64_Ehdr *elf;
659 Elf64_Phdr *phdr;
660 Mbn_Hdr *mbn_hdr;
661 uint8_t *fp;
662 int cert_offset;
663 char *sw_version;
664
665 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
666 return 0;
667 }
668
669 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + 40;
670 printf("Image with version information64\n");
671 sw_version = find_value((char *)(fp + phdr->p_offset + cert_offset), "SW_ID", 17);
672 if (sw_version) {
673 sw_version[8] = '\0';
674 sscanf(sw_version, "%x", &section->img_version);
675 printf("SW ID:%d\n", section->img_version);
676 free(sw_version);
677 }
678
679 return 1;
680}
681
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530682int find_mtd_part_size(void)
683{
684 char *mtdname = "kernel";
685 char prefix[] = "/dev/mtd";
686 char dev[PATH_MAX];
687 int i = -1, fd;
688 int vol_size;
689 int flag = 0;
690 char mtd_part[256];
691 FILE *fp = fopen("/proc/mtd", "r");
692 mtd_info_t mtd_dev_info;
693
694 if (fp == NULL) {
695 printf("Error finding mtd part\n");
696 return -1;
697 }
698
699 while (fgets(dev, sizeof(dev), fp)) {
700 if (strstr(dev, mtdname)) {
701 flag = 1;
702 break;
703 }
704 i++;
705 }
706 fclose(fp);
707
708 if (flag != 1) {
709 printf("%s block not found\n", mtdname);
710 return -1;
711 }
712
713 snprintf(mtd_part, sizeof(mtd_part), "%s%d", prefix, i);
714
715 fd = open(mtd_part, O_RDWR);
716 if (fd == -1) {
717 return -1;
718 }
719
720 if (ioctl(fd, MEMGETINFO, &mtd_dev_info) == -1) {
721 printf("Error getting block size\n");
722 close(fd);
723 return -1;
724 }
725
726 vol_size = mtd_dev_info.erasesize;
727 close(fd);
728
729 return vol_size;
730}
731
732/**
733 * In case of NAND image, Kernel image is ubinized & version information is
734 * part of Kernel image. Hence need to un-ubinize the image.
735 * To get the kernel image, Find the volume with volume id 0. Kernel image
736 * is fragmented and hence to assemble it to get complete image.
737 * In UBI image, first look for UBI#, which is magic number used to identify
738 * each eraseble block. Parse the UBI header, which starts with UBI# & get
739 * the VID(volume ID) header offset as well as Data offset.
740 * Traverse to VID header offset & check the volume ID. If it is ZERO, Kernel
741 * image is stored in this volume. Use Data offset to extract the Kernel image.
742 *
743 * @bin_file: struct image_section *
744 */
745int extract_kernel_binary(struct image_section *section)
746{
747 struct ubi_ec_hdr *ubi_ec;
748 struct ubi_vid_hdr *ubi_vol;
749 uint8_t *fp;
750 int fd, ofd, magic, data_size, vid_hdr_offset, data_offset;
751 struct stat sb;
752
753 fd = open(section->tmp_file, O_RDONLY);
754 if (fd < 0) {
755 perror(section->tmp_file);
756 return 0;
757 }
758
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530759 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530760 if (fstat(fd, &sb) == -1) {
761 perror("fstat");
762 close(fd);
763 return 0;
764 }
765
766 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
767 if (fp == MAP_FAILED) {
768 perror("mmap");
769 close(fd);
770 return 0;
771 }
772
773 ofd = open(section->file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
774 if (ofd == -1) {
775 perror(section->file);
776 close(fd);
777 return 0;
778 }
779
780 data_size = find_mtd_part_size();
781 if (data_size == -1) {
782 printf("Error finding data size\n");
783 return 0;
784 }
785
786 ubi_ec = (struct ubi_ec_hdr *)fp;
787 magic = be32_to_cpu(ubi_ec->magic);
788 while (magic == UBI_EC_HDR_MAGIC) {
789 vid_hdr_offset = be32_to_cpu(ubi_ec->vid_hdr_offset);
790 data_offset = be32_to_cpu(ubi_ec->data_offset);
791 ubi_vol = (struct ubi_vid_hdr *)((uint8_t *)ubi_ec + vid_hdr_offset);
792 magic = be32_to_cpu(ubi_vol->magic);
793 if (magic != UBI_VID_HDR_MAGIC) {
794 printf("Wrong ubi format\n");
795 close(ofd);
796 close(fd);
797 return 0;
798 }
799
800 if (ubi_vol->vol_id == 0) {
801 if (write(ofd, (void *)((uint8_t *)ubi_ec + data_offset), data_size) == -1) {
802 printf("Write error\n");
803 close(fd);
804 close(ofd);
805 return 0;
806 }
807 }
808 if ((int)ubi_vol->vol_id > 0) {
809 break;
810 }
811
812 ubi_ec = (struct ubi_ec_hdr *)((uint8_t *)ubi_ec + data_offset + data_size);
813 magic = be32_to_cpu(ubi_ec->magic);
814 }
815
816 close(ofd);
817 close(fd);
818 printf("Kernel extracted from ubi image\n");
819 return 1;
820}
821
822/**
823 * is_image_version_higher() iterates through each component and check
824 * versions against locally installed version.
825 * If newer component version is lower than locally insatlled image,
826 * abort the FW upgrade process.
827 *
828 * @img: char *
829 */
830int is_image_version_higher(void)
831{
832 int i;
833 for (i = 0; i < NO_OF_SECTIONS; i++) {
834 if (!sections[i].is_present) {
835 continue;
836 }
837
838 if (sections[i].local_version > sections[i].img_version) {
839 printf("Version of image %s (%d) is lower than minimal supported version(%d)\n",
840 sections[i].file,
841 sections[i].img_version,
842 sections[i].local_version);
843 return 0;
844 }
845
846 if (sections[i].img_version > sections[i].max_version) {
847 printf("Version of image %s (%d) is higher than maximum supported version(%d)\n",
848 sections[i].file,
849 sections[i].img_version,
850 sections[i].max_version);
851 }
852 }
853
854 return 1;
855}
856
857/**
858 * Update the version information file based on currently SW_ID being installed.
859 *
860 */
861int update_version(void)
862{
863 int i;
864 for (i = 0; i < NO_OF_SECTIONS; i++) {
865 if (!sections[i].is_present) {
866 continue;
867 }
868
869 if (set_local_image_version(&sections[i]) != 1) {
870 printf("Error updating version of %s\n", sections[i].file);
871 return 0;
872 }
873 }
874
875 return 1;
876}
877
878int check_image_version(void)
879{
880 if (is_version_check_enabled() == 0) {
881 printf("Version check is not enabled, upgrade to continue !!!\n");
882 return 1;
883 }
884
885 if (is_image_version_higher() == 0) {
886 printf("New image versions are lower than existing image, upgrade to STOP !!!\n");
887 return 0;
888 }
889
890 if (update_version() != 1) {
891 printf("Error while updating verison information\n");
892 return 0;
893 }
894 printf("Update completed!\n");
895
896 return 1;
897}
898
899/**
900 * split_code_signature_cert_from_component_bin splits the component
901 * binary by splitting into code(including MBN header), signature file &
902 * attenstation certificate.
903 *
904 * @bin_file: char *
905 * @src: char *
906 * @sig: char *
907 * @cert: char *
908 */
909int split_code_signature_cert_from_component_bin(struct image_section *section,
910 char **src, char **sig, char **cert)
911{
912 Mbn_Hdr *mbn_hdr;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530913 Sbl_Hdr *sbl_hdr;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530914 int fd = open(section->file, O_RDONLY);
915 uint8_t *fp;
916 int sig_offset = 0;
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530917 int src_offset = 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530918 int cert_offset = 0;
919 struct stat sb;
920 int sig_cert_size;
921
922 if (fd == -1) {
923 perror(section->file);
924 return 0;
925 }
926
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +0530927 memset(&sb, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530928 if (fstat(fd, &sb) == -1) {
929 perror("fstat");
930 close(fd);
931 return 0;
932 }
933
934 fp = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
935 if (fp == MAP_FAILED) {
936 perror("mmap");
937 close(fd);
938 return 0;
939 }
940
941 mbn_hdr = (Mbn_Hdr *)fp;
942 if (strstr(section->file, sections[4].type)) {
Ram Chandra Jangir62928dc2018-02-01 16:23:46 +0530943 uint32_t preamble = !check_nand_preamble(fp) ? SBL_NAND_PREAMBLE : 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530944
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530945 sbl_hdr = (Sbl_Hdr *)(fp + preamble);
946 src_offset = preamble;
947 sig_offset = preamble + sbl_hdr->sig_ptr - sbl_hdr->image_dest_ptr +
948 SBL_HDR_SIZE;
949 cert_offset = preamble + sbl_hdr->cert_ptr - sbl_hdr->image_dest_ptr +
950 SBL_HDR_SIZE;
951 sig_cert_size = sbl_hdr->image_size - sbl_hdr->code_size;
952 src_size = sbl_hdr->sig_ptr - sbl_hdr->image_dest_ptr + SBL_HDR_SIZE;
953 } else {
954 sig_cert_size = mbn_hdr->image_size - mbn_hdr->code_size;
955 src_size = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
956 sig_offset += mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
957 cert_offset += mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530958 }
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530959
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530960 if (sig_cert_size != SIG_CERT_2_SIZE && sig_cert_size != SIG_CERT_3_SIZE) {
Avinash Pandey5432bb22018-02-23 19:32:16 +0530961 printf("WARNING: signature certificate size is different\n");
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530962 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530963 *src = malloc(src_size + 1);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530964 if (*src == NULL) {
965 close(fd);
966 return 0;
967 }
Ram Chandra Jangirf40cda92017-10-16 10:08:42 +0530968 memcpy(*src, fp + src_offset, src_size);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +0530969 (*src)[src_size] = '\0';
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530970
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530971 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
972 if (*sig == NULL) {
973 free(*src);
974 return 0;
975 }
976 memcpy(*sig, fp + sig_offset, SIG_SIZE);
977 (*sig)[SIG_SIZE] = '\0';
978
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +0530979 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
980 if (*cert == NULL) {
981 free(*src);
982 free(*sig);
983 return 0;
984 }
985 memcpy(*cert, fp + cert_offset, CERT_SIZE);
986 (*cert)[CERT_SIZE] = '\0';
987
988 close(fd);
989 return 1;
990}
991
992/**
993 * split_code_signature_cert_from_component_bin_elf splits the component
994 * binary by splitting into code(including ELF header), signature file &
995 * attenstation certificate.
996 *
997 * @bin_file: char *
998 * @src: char *
999 * @sig: char *
1000 * @cert: char *
1001 */
1002int split_code_signature_cert_from_component_bin_elf(struct image_section *section,
1003 char **src, char **sig, char **cert)
1004{
1005 Elf32_Ehdr *elf;
1006 Elf32_Phdr *phdr;
1007 Mbn_Hdr *mbn_hdr;
1008 uint8_t *fp;
1009 int sig_offset;
1010 int cert_offset;
1011 int len;
1012
1013 if (!process_elf(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
1014 return 0;
1015 }
1016
1017 sig_offset = mbn_hdr->sig_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301018 len = sig_offset;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301019 *src = malloc((len + 1) * sizeof(char));
1020 if (*src == NULL) {
1021 return 0;
1022 }
1023 memcpy(*src, fp + phdr->p_offset, len);
1024 src_size = len;
1025 (*src)[len] = '\0';
1026
1027 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
1028 if (*sig == NULL) {
1029 free(*src);
1030 return 0;
1031 }
1032 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
1033 (*sig)[SIG_SIZE] = '\0';
1034
1035 cert_offset = mbn_hdr->cert_ptr - mbn_hdr->image_dest_ptr + MBN_HDR_SIZE;
1036 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
1037 if (*cert == NULL) {
1038 free(*src);
1039 free(*sig);
1040 return 0;
1041 }
1042 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1043 (*cert)[CERT_SIZE] = '\0';
1044
1045 return 1;
1046}
1047
1048/**
pavipfb8e3072017-10-12 14:47:47 +05301049 * split_code_signature_cert_from_component_bin_elf64 splits the component
1050 * binary by splitting into code(including ELF header), signature file &
1051 * attenstation certificate.
1052 *
1053 * @bin_file: char *
1054 * @src: char *
1055 * @sig: char *
1056 * @cert: char *
1057 */
1058int split_code_signature_cert_from_component_bin_elf64(struct image_section *section,
1059 char **src, char **sig, char **cert)
1060{
1061 Elf64_Ehdr *elf;
1062 Elf64_Phdr *phdr;
1063 Mbn_Hdr *mbn_hdr;
1064 uint8_t *fp;
1065 int len, sig_offset, cert_offset;
1066
1067 if (!process_elf64(section->file, &fp, &elf, &phdr, &mbn_hdr)) {
1068 return 0;
1069 }
1070
1071 sig_offset = mbn_hdr->code_size + MBN_HDR_SIZE;
1072 len = sig_offset;
1073 *src = malloc((len + 1) * sizeof(char));
1074 if (*src == NULL) {
1075 return 0;
1076 }
1077
1078 memcpy(*src, fp + phdr->p_offset, len);
1079 src_size = len;
1080 (*src)[len] = '\0';
1081
1082 *sig = malloc((SIG_SIZE + 1) * sizeof(char));
1083 if (*sig == NULL) {
1084 free(*src);
1085 return 0;
1086 }
1087
1088 memcpy(*sig, fp + phdr->p_offset + sig_offset, SIG_SIZE);
1089 (*sig)[SIG_SIZE] = '\0';
1090
1091 cert_offset = mbn_hdr->code_size + mbn_hdr->sig_sz + MBN_HDR_SIZE;
1092 *cert = malloc((CERT_SIZE + 1) * sizeof(char));
1093 if (*cert == NULL) {
1094 free(*src);
1095 free(*sig);
1096 return 0;
1097 }
1098 memcpy(*cert, fp + phdr->p_offset + cert_offset, CERT_SIZE);
1099 (*cert)[CERT_SIZE] = '\0';
1100
1101 return 1;
1102}
1103
1104/**
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301105 * being used to calculate the image hash
1106 *
1107 */
1108#define SW_MASK 0x3636363636363636ull
1109
1110void generate_swid_ipad(char *sw_id, unsigned long long *swid_xor_ipad)
1111{
1112 unsigned long long int val;
1113
1114 val = strtoull(sw_id, NULL, 16);
1115 *swid_xor_ipad = val ^ SW_MASK;
1116
1117 printf("%llx\n", *swid_xor_ipad);
1118}
1119
1120/**
1121 * being used to calculate the image hash
1122 *
1123 */
1124#define HW_ID_MASK 0x5c5c5c5cull
1125#define OEM_ID_MASK 0x00005c5cull
1126#define OEM_MODEL_ID_MASK 0x00005c5cull
1127
1128void generate_hwid_opad(char *hw_id, char *oem_id, char *oem_model_id,
1129 unsigned long long *hwid_xor_opad)
1130{
1131 unsigned long long val;
1132
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301133 val = strtoull(hw_id, NULL, 16);
1134 *hwid_xor_opad = (((val >> 32) ^ HW_ID_MASK) << 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301135
1136 val = strtoul(oem_id, NULL, 16);
1137 *hwid_xor_opad |= ((val ^ OEM_ID_MASK) << 16);
1138
1139 val = strtoul(oem_model_id, NULL, 16);
1140 *hwid_xor_opad |= (val ^ OEM_MODEL_ID_MASK) & 0xffff;
1141
1142 printf("%llx\n", *hwid_xor_opad);
1143}
1144
1145int create_file(char *name, char *buffer, int size)
1146{
1147 int fd;
1148
1149 fd = open(name, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1150 if (fd == -1) {
1151 perror(name);
1152 return 0;
1153 }
1154
1155 if (write(fd, buffer, size) == -1) {
1156 close(fd);
1157 return 0;
1158 }
1159
1160 close(fd);
1161 return 1;
1162}
1163
1164char *create_xor_ipad_opad(char *f_xor, unsigned long long *xor_buffer)
1165{
1166 int fd;
1167 char *file;
pavipfb8e3072017-10-12 14:47:47 +05301168 unsigned long long sw_id, sw_id_be;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301169
1170 file = mktemp(f_xor);
1171 fd = open(file, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
1172 if (fd == -1) {
1173 perror(file);
1174 return NULL;
1175 }
1176
pavipfb8e3072017-10-12 14:47:47 +05301177 sw_id = *xor_buffer;
1178 sw_id_be = htobe64(sw_id);
1179 write(fd, &sw_id_be, sizeof(sw_id_be));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301180 close(fd);
1181 return file;
1182}
1183
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301184char *read_file(char *file_name, size_t *file_size)
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301185{
1186 int fd;
1187 struct stat st;
1188 char *buffer;
1189
1190 fd = open(file_name, O_RDONLY);
1191 if (fd == -1) {
1192 perror(file_name);
1193 return NULL;
1194 }
1195
Gokul Sriram Palanisamy767b4572017-09-01 16:02:50 +05301196 memset(&st, 0, sizeof(struct stat));
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301197 fstat(fd, &st);
1198 buffer = malloc(st.st_size * sizeof(buffer));
1199 if (buffer == NULL) {
1200 close(fd);
1201 return NULL;
1202 }
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301203
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301204 if (read(fd, buffer, st.st_size) == -1) {
1205 close(fd);
1206 return NULL;
1207 }
1208
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301209 *file_size = (size_t) st.st_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301210 close(fd);
1211 return buffer;
1212}
1213
1214int generate_hash(char *cert, char *sw_file, char *hw_file)
1215{
1216 unsigned long long swid_xor_ipad, hwid_xor_opad;
1217 char *tmp;
1218 char *sw_id_str = find_value(cert, "SW_ID", 17);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301219 char *hw_id_str = find_value(cert, "HW_ID", 17);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301220 char *oem_id_str = find_value(cert, "OEM_ID", 5);
1221 char *oem_model_id_str = find_value(cert, "MODEL_ID", 5);
1222 char f_sw_xor[] = "/tmp/swid_xor_XXXXXX";
1223 char f_hw_xor[] = "/tmp/hwid_xor_XXXXXX";
1224
1225 if (sw_id_str == NULL || hw_id_str == NULL || oem_id_str == NULL || oem_model_id_str == NULL) {
1226 if (sw_id_str != NULL) {
1227 free(sw_id_str);
1228 }
1229 if (hw_id_str != NULL) {
1230 free(hw_id_str);
1231 }
1232 if (oem_id_str != NULL) {
1233 free(oem_id_str);
1234 }
1235 if (oem_model_id_str != NULL) {
1236 free(oem_model_id_str);
1237 }
1238 return 0;
1239 }
1240 printf("sw_id=%s\thw_id=%s\t", sw_id_str, hw_id_str);
1241 printf("oem_id=%s\toem_model_id=%s\n", oem_id_str, oem_model_id_str);
1242
1243 generate_swid_ipad(sw_id_str, &swid_xor_ipad);
1244 tmp = create_xor_ipad_opad(f_sw_xor, &swid_xor_ipad);
1245 if (tmp == NULL) {
1246 free(sw_id_str);
1247 free(hw_id_str);
1248 free(oem_id_str);
1249 free(oem_model_id_str);
1250 return 0;
1251 }
Avinash Pandey7eeddce2018-02-20 12:10:17 +05301252 strlcpy(sw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301253
1254 generate_hwid_opad(hw_id_str, oem_id_str, oem_model_id_str, &hwid_xor_opad);
1255 tmp = create_xor_ipad_opad(f_hw_xor, &hwid_xor_opad);
1256 if (tmp == NULL) {
1257 free(sw_id_str);
1258 free(hw_id_str);
1259 free(oem_id_str);
1260 free(oem_model_id_str);
1261 return 0;
1262 }
Avinash Pandey7eeddce2018-02-20 12:10:17 +05301263 strlcpy(hw_file, tmp, 32);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301264
1265 free(sw_id_str);
1266 free(hw_id_str);
1267 free(oem_id_str);
1268 free(oem_model_id_str);
1269
1270 return 1;
1271}
1272
1273void remove_file(char *sw_file, char *hw_file, char *code_file, char *pub_file)
1274{
1275 remove(sw_file);
1276 remove(hw_file);
1277 remove(code_file);
1278 remove(pub_file);
1279 remove("src");
1280 remove("sig");
1281 remove("cert");
1282}
1283
1284/**
1285 * is_component_authenticated() usage the code, signature & public key retrieved
1286 * for each component.
1287 *
1288 * @src: char *
1289 * @sig: char *
1290 * @cert: char *
1291 */
1292int is_component_authenticated(char *src, char *sig, char *cert)
1293{
1294 char command[256];
1295 char *computed_hash;
1296 char *reference_hash;
1297 char pub_key[] = "/tmp/pub_keyXXXXXX", *pub_file;
1298 char code_hash[] = "/tmp/code_hash_XXXXXX", *code_file;
1299 char tmp_hash[] = "/tmp/tmp_hash_XXXXXX", *tmp_file;
1300 char f_computed_hash[] = "/tmp/computed_hash_XXXXXX", *computed_file;
1301 char f_reference_hash[] = "/tmp/reference_hash_XXXXXX", *reference_file;
1302 char sw_file[32],hw_file[32];
1303 int retval;
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301304 size_t comp_hash_size, ref_hash_size;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301305
1306 if (!create_file("src", src, src_size) || !create_file("sig", sig, SIG_SIZE) ||
1307 !create_file("cert", cert, CERT_SIZE)) {
1308 return 0;
1309 }
1310
1311 pub_file = mktemp(pub_key);
1312 snprintf(command, sizeof(command),
1313 "openssl x509 -in cert -pubkey -inform DER -noout > %s", pub_file);
1314 retval = system(command);
1315 if (retval != 0) {
1316 remove("src");
1317 remove("sig");
1318 remove("cert");
1319 printf("Error generating public key\n");
1320 return 0;
1321 }
1322
1323 retval = generate_hash(cert, sw_file, hw_file);
1324 if (retval == 0) {
1325 return 0;
1326 }
1327
1328 code_file = mktemp(code_hash);
1329 snprintf(command, sizeof(command),
1330 "openssl dgst -sha256 -binary -out %s src", code_file);
1331 retval = system(command);
1332 if (retval != 0) {
1333 remove_file(sw_file, hw_file, code_file, pub_file);
1334 printf("Error in openssl digest\n");
1335 return 0;
1336 }
1337
1338 tmp_file = mktemp(tmp_hash);
1339 snprintf(command, sizeof(command),
1340 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1341 sw_file, code_file, tmp_file);
1342 retval = system(command);
1343 if (retval != 0) {
1344 remove_file(sw_file, hw_file, code_file, pub_file);
1345 remove(tmp_file);
1346 printf("Error generating temp has\n");
1347 return 0;
1348 }
1349
1350 computed_file = mktemp(f_computed_hash);
1351 snprintf(command, sizeof(command),
1352 "cat %s %s | openssl dgst -sha256 -binary -out %s",
1353 hw_file, tmp_file, computed_file);
1354 retval = system(command);
1355 if (retval != 0) {
1356 remove_file(sw_file, hw_file, code_file, pub_file);
1357 remove(tmp_file);
1358 remove(computed_file);
1359 printf("Error generating hash\n");
1360 return 0;
1361 }
1362
1363 reference_file = mktemp(f_reference_hash);
1364 snprintf(command, sizeof(command),
1365 "openssl rsautl -in sig -pubin -inkey %s -verify > %s",
1366 pub_file, reference_file);
1367 retval = system(command);
1368 if (retval != 0) {
1369 remove_file(sw_file, hw_file, code_file, pub_file);
1370 remove(tmp_file);
1371 remove(computed_file);
1372 remove(reference_file);
1373 printf("Error generating reference hash\n");
1374 return 0;
1375 }
1376
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301377 computed_hash = read_file(computed_file, &comp_hash_size);
1378 reference_hash = read_file(reference_file, &ref_hash_size);
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301379 if (computed_hash == NULL || reference_hash == NULL) {
1380 remove_file(sw_file, hw_file, code_file, pub_file);
1381 remove(tmp_file);
1382 remove(computed_file);
1383 remove(reference_file);
1384 free(computed_hash?computed_hash:reference_hash);
1385 return 0;
1386 }
1387
1388 remove_file(sw_file, hw_file, code_file, pub_file);
1389 remove(tmp_file);
1390 remove(computed_file);
1391 remove(reference_file);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301392 if (memcmp(computed_hash, reference_hash, ref_hash_size) ||
1393 (comp_hash_size != ref_hash_size)) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301394 free(computed_hash);
1395 free(reference_hash);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301396 printf("Error: Hash or file_size not equal\n");
1397 return 0;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301398 }
1399 free(computed_hash);
1400 free(reference_hash);
Pavithra Palanisamy0e3043f2017-09-14 19:45:05 +05301401 return 1;
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301402}
1403
1404/**
1405 * is_image_authenticated() iterates through each component and check
1406 * whether individual component is authenticated. If not, abort the FW
1407 * upgrade process.
1408 *
1409 * @img: char *
1410 */
1411int is_image_authenticated(void)
1412{
1413 int i;
1414 char *src, *sig, *cert;
1415 for (i = 0; i < NO_OF_SECTIONS; i++) {
1416 if (!sections[i].is_present) {
1417 continue;
1418 }
1419 if (!sections[i].split_components(&sections[i], &src, &sig, &cert)) {
1420 printf("Error while splitting code/signature/Certificate from %s\n",
1421 sections[i].file);
1422 return 0;
1423 }
1424 if (!is_component_authenticated(src, sig, cert)) {
1425 printf("Error while authenticating %s\n", sections[i].file);
1426 return 0;
1427 }
1428 }
1429
1430 return 1;
1431}
1432
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301433int sec_image_auth()
1434{
1435 int fd, i, len;
Avinash Pandeya14e1022018-03-09 12:16:45 +05301436 char *buf = NULL;
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301437
1438 fd = open(SEC_AUTHENTICATE_FILE, O_RDWR);
1439 if (-1 == fd) {
1440 perror(SEC_AUTHENTICATE_FILE);
1441 return 1;
1442 }
Avinash Pandeya14e1022018-03-09 12:16:45 +05301443 buf = (char*)malloc(SIG_SIZE);
1444 if (buf == NULL) {
1445 perror("Memory allocation failed\n");
1446 close(fd);
1447 return 1;
1448 }
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301449 for (i = 0; i < NO_OF_SECTIONS; i++) {
1450 if (!sections[i].is_present) {
1451 continue;
1452 }
1453
Avinash Pandeya14e1022018-03-09 12:16:45 +05301454 len = snprintf(buf, SIG_SIZE, "%s %s", sections[i].img_code, sections[i].file);
1455 if (len < 0 || len > SIG_SIZE) {
1456 perror("Array out of Index\n");
1457 free(buf);
1458 close(fd);
1459 return 1;
1460 }
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301461 if (write(fd, buf, len) != len) {
1462 perror("write");
Avinash Pandey37c8e792018-03-23 11:25:27 +05301463 printf("%s Image authentication failed\n", buf);
Avinash Pandeya14e1022018-03-09 12:16:45 +05301464 free(buf);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301465 close(fd);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301466 return 1;
1467 }
1468 }
1469 close(fd);
Avinash Pandeya14e1022018-03-09 12:16:45 +05301470 free(buf);
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301471 return 0;
1472}
1473
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301474int do_board_upgrade_check(char *img)
1475{
Avinash Pandeybcfcba72018-01-19 13:07:54 +05301476 if (is_tz_authentication_enabled()) {
1477 printf("TZ authentication enabled ...\n");
1478 if (!load_sections()) {
1479 printf("Error: Failed to load sections from image: %s\n", img);
1480 return 1;
1481 }
1482 return sec_image_auth();
1483 } else if (is_authentication_check_enabled()) {
Sachin Sundar1ed5f5b2017-03-28 17:34:42 +05301484 if (!get_sections()) {
1485 printf("Error: %s is not a signed image\n", img);
1486 return 1;
1487 }
1488
1489 if (!is_image_authenticated()) {
1490 printf("Error: \"%s\" couldn't be authenticated. Abort...\n", img);
1491 return 1;
1492 }
1493
1494 if (!check_image_version()) {
1495 printf("Error: \"%s\" couldn't be upgraded. Abort...\n", img);
1496 return 1;
1497 }
1498 }
1499
1500 return 0;
1501}