1
2
3
4
5
6
7#include <common.h>
8#include <asm/io.h>
9#include <asm/arch/hardware.h>
10#include <asm/arch/sys_proto.h>
11#include <u-boot/md5.h>
12#include <u-boot/rsa.h>
13#include <u-boot/rsa-mod-exp.h>
14#include <u-boot/sha256.h>
15#include <spi_flash.h>
16#include <zynqpl.h>
17#include <fpga.h>
18
19DECLARE_GLOBAL_DATA_PTR;
20
21#define ZYNQ_IMAGE_PHDR_OFFSET 0x09C
22#define ZYNQ_IMAGE_FSBL_LEN_OFFSET 0x040
23
24#define ZYNQ_PART_HDR_CHKSUM_WORD_COUNT 0x0F
25#define ZYNQ_PART_HDR_WORD_COUNT 0x10
26
27#define ZYNQ_EFUSE_RSA_ENABLE_MASK 0x400
28
29#define ZYNQ_ATTRIBUTE_PL_IMAGE_MASK 0x20
30#define ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK 0x7000
31#define ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK 0x8000
32#define ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK 0x30000
33
34#define ZYNQ_MAX_PARTITION_NUMBER 0xE
35
36#define ZYNQ_RSA_MODULAR_SIZE 256
37#define ZYNQ_RSA_MODULAR_EXT_SIZE 256
38#define ZYNQ_RSA_EXPO_SIZE 64
39#define ZYNQ_RSA_SPK_SIGNATURE_SIZE 256
40#define ZYNQ_RSA_PARTITION_SIGNATURE_SIZE 256
41#define ZYNQ_RSA_SIGNATURE_SIZE 0x6C0
42#define ZYNQ_RSA_HEADER_SIZE 4
43#define ZYNQ_RSA_MAGIC_WORD_SIZE 60
44#define ZYNQ_RSA_PART_OWNER_UBOOT 1
45#define ZYNQ_RSA_ALIGN_PPK_START 64
46
47#define WORD_LENGTH_SHIFT 2
48#define ZYNQ_MAXIMUM_IMAGE_WORD_LEN 0x40000000
49
50#define MD5_CHECKSUM_SIZE 16
51
52static u8 *ppkmodular;
53static u8 *ppkmodularex;
54static u32 ppkexp;
55
56struct partition_hdr {
57 u32 imagewordlen;
58 u32 datawordlen;
59 u32 partitionwordlen;
60 u32 loadaddr;
61 u32 execaddr;
62 u32 partitionstart;
63 u32 partitionattr;
64 u32 sectioncount;
65 u32 checksumoffset;
66 u32 pads1[1];
67 u32 acoffset;
68 u32 pads2[4];
69 u32 checksum;
70};
71
72struct zynq_rsa_public_key {
73 uint len;
74 uint32_t n0inv;
75 uint32_t *modulus;
76 uint32_t *rr;
77};
78
79struct partition_hdr part_hdr[ZYNQ_MAX_PARTITION_NUMBER];
80
81struct headerarray {
82 u32 fields[16];
83};
84
85struct zynq_rsa_public_key public_key;
86
87static u32 fsbl_len;
88
89
90
91
92static int zynq_islastpartition(struct headerarray *head)
93{
94 int index;
95
96 debug("zynq_islastpartition\n");
97 if (head->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != 0xFFFFFFFF)
98 return -1;
99
100 for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT - 1; index++) {
101 if (head->fields[index] != 0x0)
102 return -1;
103 }
104
105 return 0;
106}
107
108
109
110
111static int zynq_get_part_count(struct partition_hdr *part_hdr_info)
112{
113 u32 count = 0;
114 struct headerarray *hap;
115
116 debug("zynq_get_part_count\n");
117
118 for (count = 0; count < ZYNQ_MAX_PARTITION_NUMBER; count++) {
119 hap = (struct headerarray *)&part_hdr_info[count];
120 if (zynq_islastpartition(hap) != -1)
121 break;
122 }
123
124 return count;
125}
126
127
128
129
130static int zynq_get_partition_info(u32 image_base_addr)
131{
132 u32 parthdroffset;
133
134 fsbl_len = *((u32 *)(image_base_addr + ZYNQ_IMAGE_FSBL_LEN_OFFSET));
135
136 parthdroffset = *((u32 *)(image_base_addr + ZYNQ_IMAGE_PHDR_OFFSET));
137
138 parthdroffset += image_base_addr;
139
140 memcpy(&part_hdr[0], (u32 *)parthdroffset,
141 (sizeof(struct partition_hdr) * ZYNQ_MAX_PARTITION_NUMBER));
142
143 return 0;
144}
145
146
147
148
149static int zynq_validate_hdr(struct partition_hdr *header)
150{
151 struct headerarray *hap;
152 u32 index;
153 u32 checksum;
154
155 debug("zynq_validate_hdr\n");
156
157 hap = (struct headerarray *)header;
158
159 for (index = 0; index < ZYNQ_PART_HDR_WORD_COUNT; index++) {
160 if (hap->fields[index] != 0x0)
161 break;
162 }
163 if (index == ZYNQ_PART_HDR_WORD_COUNT)
164 return -1;
165
166 checksum = 0;
167 for (index = 0; index < ZYNQ_PART_HDR_CHKSUM_WORD_COUNT; index++)
168 checksum += hap->fields[index];
169
170 checksum ^= 0xFFFFFFFF;
171
172 if (hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT] != checksum) {
173 printf("Error: Checksum 0x%8.8x != 0x%8.8x\r\n",
174 checksum, hap->fields[ZYNQ_PART_HDR_CHKSUM_WORD_COUNT]);
175 return -1;
176 }
177
178 if (header->imagewordlen > ZYNQ_MAXIMUM_IMAGE_WORD_LEN) {
179 printf("INVALID_PARTITION_LENGTH\r\n");
180 return -1;
181 }
182
183 return 0;
184}
185
186
187
188
189
190
191static int zynq_validate_partition(u32 start_addr, u32 len, u32 chksum_off)
192{
193 u8 checksum[MD5_CHECKSUM_SIZE];
194 u8 calchecksum[MD5_CHECKSUM_SIZE];
195
196 memcpy(&checksum[0], (u32 *)chksum_off, MD5_CHECKSUM_SIZE);
197
198 md5_wd((u8 *)start_addr, len, &calchecksum[0], 0x10000);
199
200 if ((memcmp(checksum, calchecksum, MD5_CHECKSUM_SIZE)) != 0) {
201 printf("Error: Partition DataChecksum \r\n");
202 return -1;
203 }
204 return 0;
205}
206
207
208
209
210static void zynq_extract_ppk(void)
211{
212 u32 padsize;
213 u8 *ppkptr;
214
215 debug("zynq_extract_ppk\n");
216
217 ppkptr = (u8 *)(fsbl_len + 0xFFFC0000);
218 padsize = ((u32)ppkptr % ZYNQ_RSA_ALIGN_PPK_START);
219 if (padsize != 0)
220 ppkptr += (ZYNQ_RSA_ALIGN_PPK_START - padsize);
221
222 ppkptr += ZYNQ_RSA_HEADER_SIZE;
223
224 ppkptr += ZYNQ_RSA_MAGIC_WORD_SIZE;
225
226 ppkmodular = (u8 *)ppkptr;
227 ppkptr += ZYNQ_RSA_MODULAR_SIZE;
228 ppkmodularex = (u8 *)ppkptr;
229 ppkptr += ZYNQ_RSA_MODULAR_EXT_SIZE;
230 ppkexp = *(u32 *)ppkptr;
231}
232
233
234
235
236static u32 zynq_calc_inv(void)
237{
238 u32 modulus = public_key.modulus[0];
239 u32 tmp = 2;
240 u32 inverse;
241
242 inverse = modulus & 0x1;
243
244 while (tmp) {
245 inverse *= 2-modulus*inverse;
246 tmp *= tmp;
247 }
248
249 return -inverse;
250}
251
252
253
254
255static int zynq_pad_and_check(u8 *signature, u8 *hash)
256{
257 u8 padding[] = {0x30, 0x31, 0x30, 0x0D, 0x06, 0x09, 0x60, 0x86, 0x48,
258 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
259 0x20 };
260 u8 *pad_ptr = signature + 256;
261 u32 pad = 256 - 3 - 19 - 32;
262 u32 ii;
263
264
265 if (*--pad_ptr != 0x00 || *--pad_ptr != 0x01)
266 return -1;
267
268 for (ii = 0; ii < pad; ii++) {
269 if (*--pad_ptr != 0xFF)
270 return -1;
271 }
272
273 if (*--pad_ptr != 0x00)
274 return -1;
275
276 for (ii = 0; ii < sizeof(padding); ii++) {
277 if (*--pad_ptr != padding[ii])
278 return -1;
279 }
280
281 for (ii = 0; ii < 32; ii++) {
282 if (*--pad_ptr != hash[ii])
283 return -1;
284 }
285 return 0;
286}
287
288
289
290
291
292static int zynq_rsa_verify_key(const struct zynq_rsa_public_key *key,
293 const u8 *sig, const u32 sig_len, const u8 *hash)
294{
295 int status;
296
297 if ((!key) || (!sig) || (!hash))
298 return -1;
299
300 if (sig_len != (key->len * sizeof(uint32_t))) {
301 printf("Signature is of incorrect length %d\n", sig_len);
302 return -1;
303 }
304
305
306 if (sig_len > ZYNQ_RSA_SPK_SIGNATURE_SIZE) {
307 printf("Signature length %u exceeds maximum %d\n", sig_len,
308 ZYNQ_RSA_SPK_SIGNATURE_SIZE);
309 return -1;
310 }
311
312 u32 buf[sig_len / sizeof(uint32_t)];
313
314 memcpy(buf, sig, sig_len);
315
316 status = zynq_pow_mod((u32 *)key, buf);
317 if (status == -1)
318 return status;
319
320 status = zynq_pad_and_check((u8 *)buf, (u8 *)hash);
321 if (status == -1)
322 return status;
323 return 0;
324}
325
326
327
328
329static int zynq_authenticate_part(u8 *buffer, u32 size)
330{
331 u8 hash_signature[32];
332 u8 *spk_modular;
333 u8 *spk_modular_ex;
334 u8 *signature_ptr;
335 u32 status;
336
337 debug("zynq_authenticate_part\n");
338
339 signature_ptr = (u8 *)(buffer + size - ZYNQ_RSA_SIGNATURE_SIZE);
340
341 signature_ptr += ZYNQ_RSA_HEADER_SIZE;
342
343 signature_ptr += ZYNQ_RSA_MAGIC_WORD_SIZE;
344
345 ppkmodular = (u8 *)signature_ptr;
346 signature_ptr += ZYNQ_RSA_MODULAR_SIZE;
347 ppkmodularex = signature_ptr;
348 signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE;
349 signature_ptr += ZYNQ_RSA_EXPO_SIZE;
350
351 sha256_csum_wd((const unsigned char *)signature_ptr,
352 (ZYNQ_RSA_MODULAR_EXT_SIZE + ZYNQ_RSA_EXPO_SIZE +
353 ZYNQ_RSA_MODULAR_SIZE),
354 (unsigned char *)hash_signature, 0x1000);
355
356 spk_modular = (u8 *)signature_ptr;
357 signature_ptr += ZYNQ_RSA_MODULAR_SIZE;
358 spk_modular_ex = (u8 *)signature_ptr;
359 signature_ptr += ZYNQ_RSA_MODULAR_EXT_SIZE;
360 signature_ptr += ZYNQ_RSA_EXPO_SIZE;
361
362 public_key.len = ZYNQ_RSA_MODULAR_SIZE/sizeof(u32);
363 public_key.modulus = (u32 *)ppkmodular;
364 public_key.rr = (u32 *)ppkmodularex;
365 public_key.n0inv = zynq_calc_inv();
366
367 status = zynq_rsa_verify_key(&public_key, signature_ptr,
368 ZYNQ_RSA_SPK_SIGNATURE_SIZE, hash_signature);
369
370 if (status)
371 return status;
372
373 signature_ptr += ZYNQ_RSA_SPK_SIGNATURE_SIZE;
374
375 sha256_csum_wd((const unsigned char *)buffer,
376 (size - ZYNQ_RSA_PARTITION_SIGNATURE_SIZE),
377 (unsigned char *)hash_signature, 0x1000);
378
379 public_key.len = ZYNQ_RSA_MODULAR_SIZE/sizeof(u32);
380 public_key.modulus = (u32 *)spk_modular;
381 public_key.rr = (u32 *)spk_modular_ex;
382 public_key.n0inv = zynq_calc_inv();
383
384 status = zynq_rsa_verify_key(&public_key, (u8 *)signature_ptr,
385 ZYNQ_RSA_PARTITION_SIGNATURE_SIZE,
386 (u8 *)hash_signature);
387
388 if (status)
389 return status;
390
391 return 0;
392}
393
394
395
396
397
398static int do_zynq_verify_image(cmd_tbl_t *cmdtp, int flag, int argc,
399 char * const argv[])
400{
401 u32 silicon_ver;
402 u32 image_base_addr;
403 u32 status;
404 u32 partition_num;
405 u32 efuseval;
406 u32 srcaddr;
407 u32 size;
408 struct partition_hdr *hdr_ptr;
409 u32 part_data_len;
410 u32 part_img_len;
411 u32 part_attr;
412 u32 part_load_addr;
413 u32 part_dst_addr;
414 u32 part_chksum_offset;
415 u32 part_start_addr;
416 u32 part_total_size;
417 u32 partitioncount;
418 u8 encrypt_part_flag;
419 u8 part_chksum_flag;
420 u8 signed_part_flag;
421 char *endp;
422
423 if (argc < 2)
424 goto usage;
425
426 image_base_addr = simple_strtoul(argv[1], &endp, 16);
427 if (*argv[1] == 0 || *endp != 0)
428 return -1;
429
430 silicon_ver = zynq_get_silicon_version();
431
432
433 if (silicon_ver == 0 || silicon_ver == 1)
434 return -1;
435
436 status = zynq_get_partition_info(image_base_addr);
437 if (status == -1) {
438 printf("Get Partition Info Failed\n");
439 return status;
440 }
441
442
443 efuseval = readl(&efuse_base->status);
444 if (efuseval & ZYNQ_EFUSE_RSA_ENABLE_MASK)
445 zynq_extract_ppk();
446 else
447 return -1;
448
449 partitioncount = zynq_get_part_count(&part_hdr[0]);
450
451 if ((partitioncount <= 2) ||
452 (partitioncount > ZYNQ_MAX_PARTITION_NUMBER))
453 return -1;
454
455 partition_num = 0;
456
457 while (partition_num < partitioncount) {
458 if (((part_hdr[partition_num].partitionattr &
459 ZYNQ_ATTRIBUTE_RSA_PART_OWNER_MASK) >> 16) !=
460 ZYNQ_RSA_PART_OWNER_UBOOT) {
461 printf("UBOOT is not Owner for partition %d\r\n",
462 partition_num);
463 } else {
464 hdr_ptr = &part_hdr[partition_num];
465 status = zynq_validate_hdr(hdr_ptr);
466 if (status == -1)
467 return status;
468
469 part_data_len = hdr_ptr->datawordlen;
470 part_img_len = hdr_ptr->imagewordlen;
471 part_attr = hdr_ptr->partitionattr;
472 part_load_addr = hdr_ptr->loadaddr;
473 part_chksum_offset = hdr_ptr->checksumoffset;
474 part_start_addr = hdr_ptr->partitionstart;
475 part_total_size = hdr_ptr->partitionwordlen;
476
477 if (part_data_len != part_img_len) {
478 debug("Encrypted\r\n");
479 encrypt_part_flag = 1;
480 } else {
481 encrypt_part_flag = 0;
482 }
483
484 if (part_attr & ZYNQ_ATTRIBUTE_CHECKSUM_TYPE_MASK)
485 part_chksum_flag = 1;
486 else
487 part_chksum_flag = 0;
488
489 if (part_attr & ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK) {
490 debug("RSA Signed\r\n");
491 signed_part_flag = 1;
492 } else {
493 signed_part_flag = 0;
494 }
495
496 srcaddr = image_base_addr +
497 (part_start_addr << WORD_LENGTH_SHIFT);
498
499 if (part_attr & ZYNQ_ATTRIBUTE_RSA_PRESENT_MASK) {
500 signed_part_flag = 1;
501 size = part_total_size << WORD_LENGTH_SHIFT;
502 } else {
503 signed_part_flag = 0;
504 size = part_img_len;
505 }
506
507 if ((part_load_addr < gd->bd->bi_dram[0].start) &&
508 ((part_load_addr + part_data_len) >
509 (gd->bd->bi_dram[0].start +
510 gd->bd->bi_dram[0].size))) {
511 printf("INVALID_LOAD_ADDRESS_FAIL\r\n");
512 return -1;
513 }
514
515 if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK)
516 part_load_addr = srcaddr;
517 else
518 memcpy((u32 *)part_load_addr, (u32 *)srcaddr,
519 size);
520
521 if (!signed_part_flag && !part_chksum_flag) {
522 printf("Partition not signed & no chksum\n");
523 continue;
524 }
525
526 if (part_chksum_flag) {
527 part_chksum_offset = image_base_addr +
528 (part_chksum_offset <<
529 WORD_LENGTH_SHIFT);
530 status = zynq_validate_partition(part_load_addr,
531 (part_total_size <<
532 WORD_LENGTH_SHIFT),
533 part_chksum_offset);
534 if (status != 0) {
535 printf("PART_CHKSUM_FAIL\r\n");
536 return -1;
537 }
538 debug("Partition Validation Done\r\n");
539 }
540
541 if (signed_part_flag == 1) {
542 status = zynq_authenticate_part(
543 (u8 *)part_load_addr,
544 size);
545 if (status != 0) {
546 printf("AUTHENTICATION_FAIL\r\n");
547 return -1;
548 }
549 debug("Authentication Done\r\n");
550 }
551
552 if (encrypt_part_flag) {
553 debug("DECRYPTION \r\n");
554
555 part_dst_addr = part_load_addr;
556
557 if (part_attr & ZYNQ_ATTRIBUTE_PL_IMAGE_MASK)
558 part_dst_addr = 0xFFFFFFFF;
559
560 status = zynq_decrypt_load(part_load_addr,
561 part_img_len,
562 part_dst_addr,
563 part_data_len,
564 BIT_NONE);
565 if (status != 0) {
566 printf("DECRYPTION_FAIL\r\n");
567 return -1;
568 }
569 }
570 }
571 partition_num++;
572 }
573
574 return 0;
575
576usage:
577 return CMD_RET_USAGE;
578}
579
580#ifdef CONFIG_SYS_LONGHELP
581static char zynqrsa_help_text[] =
582"zynqrsa <baseaddr> - Verifies the authenticated and encrypted zynq images\n";
583#endif
584
585U_BOOT_CMD(
586 zynqrsa, 2, 0, do_zynq_verify_image,
587 "Zynq RSA verfication ", zynqrsa_help_text
588);
589