1 /* Copyright 2017 IBM Corp.
2  *
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * 	http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12  * implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <config.h>
18 
19 #include <errno.h>
20 #include <fcntl.h>
21 #include <getopt.h>
22 #include <limits.h>
23 #include <openssl/bn.h>
24 #include <openssl/ec.h>
25 #include <openssl/ecdsa.h>
26 #include <openssl/evp.h>
27 #include <openssl/opensslv.h>
28 #include <openssl/ossl_typ.h>
29 #include <openssl/pem.h>
30 #include <openssl/sha.h>
31 #include <stdbool.h>
32 #include <types.h>
33 #include <stdint.h>
34 #include <stdio.h>
35 #include <stdlib.h>
36 #include <string.h>
37 #include <sys/mman.h>
38 #include <sys/stat.h>
39 #include <sysexits.h>
40 #include <unistd.h>
41 
42 #include "ccan/endian/endian.h"
43 #include "ccan/short_types/short_types.h"
44 #include "container-utils.h"
45 #include "container.h"
46 
47 #define CONTAINER_HDR 0
48 #define PREFIX_HDR 1
49 #define SOFTWARE_HDR 2
50 
51 char *progname;
52 
53 bool verbose, debug;
54 int wrap = 100;
55 
56 void usage(int status);
57 
getPublicKeyRaw(ecc_key_t * pubkeyraw,char * filename)58 void getPublicKeyRaw(ecc_key_t *pubkeyraw, char *filename)
59 {
60 	EVP_PKEY* pkey;
61 	unsigned char pubkeyData[1 + 2 * EC_COORDBYTES];
62 
63 	FILE *fp = fopen(filename, "r");
64 	if (!fp)
65 		die(EX_NOINPUT, "Cannot open key file: %s: %s", filename, strerror(errno));
66 
67 	if ((pkey = PEM_read_PrivateKey(fp, NULL, NULL, NULL))) {
68 		debug_msg("File \"%s\" is a PEM private key", filename);
69 		fclose(fp);
70 	} else {
71 		fclose(fp);
72 		fp = fopen(filename, "r");
73 		if ((pkey = PEM_read_PUBKEY(fp, NULL, NULL, NULL))) {
74 			debug_msg("File \"%s\" is a PEM public key", filename);
75 		}
76 		fclose(fp);
77 	}
78 
79 	if (pkey) {
80 		EC_KEY *key;
81 		const EC_GROUP *ecgrp;
82 		const EC_POINT *ecpoint;
83 		BIGNUM *pubkeyBN;
84 
85 		key = EVP_PKEY_get1_EC_KEY(pkey);
86 		if (!key)
87 			die(EX_SOFTWARE, "%s", "Cannot EVP_PKEY_get1_EC_KEY");
88 
89 		ecgrp = EC_KEY_get0_group(key);
90 		if (!ecgrp)
91 			die(EX_SOFTWARE, "%s", "Cannot EC_KEY_get0_group");
92 
93 		ecpoint = EC_KEY_get0_public_key(key);
94 		if (!ecpoint)
95 			die(EX_SOFTWARE, "%s", "Cannot EC_KEY_get0_public_key");
96 
97 		pubkeyBN = EC_POINT_point2bn(ecgrp, ecpoint, POINT_CONVERSION_UNCOMPRESSED,
98 				NULL, NULL);
99 		BN_bn2bin(pubkeyBN, pubkeyData);
100 
101 		BN_free(pubkeyBN);
102 		EC_KEY_free(key);
103 		EVP_PKEY_free(pkey);
104 	}
105 	else {
106 		/* The file is not a public or private key in PEM format. So we check if
107 		 * it is a p521 pubkey in RAW format, in which case it will be 133 bytes
108 		 * with a leading byte of 0x04, indicating an uncompressed key. */
109 		int fdin, r;
110 		struct stat s;
111 		void *infile = NULL;
112 
113 		fdin = open(filename, O_RDONLY);
114 		if (fdin <= 0)
115 			die(EX_NOINPUT, "Cannot open key file: %s: %s", filename, strerror(errno));
116 
117 		r = fstat(fdin, &s);
118 		if (r != 0)
119 			die(EX_NOINPUT, "Cannot stat key file: %s", filename);
120 
121 		if (s.st_size == 1 + 2 * EC_COORDBYTES)
122 			infile = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
123 
124 		close(fdin);
125 
126 		if (!infile || (*(unsigned char*) infile != 0x04)) {
127 			die(EX_DATAERR,
128 					"File \"%s\" is not in expected format (private or public key in PEM, or public key RAW)",
129 					filename);
130 		}
131 		else
132 			debug_msg("File \"%s\" is a RAW public key", filename);
133 
134 		memcpy(pubkeyData, infile, sizeof(ecc_key_t) + 1);
135 		munmap(infile, s.st_size);
136 	}
137 
138 	// Remove the leading byte
139 	memcpy(*pubkeyraw, &pubkeyData[1], sizeof(ecc_key_t));
140 
141 	return;
142 }
143 
getSigRaw(ecc_signature_t * sigraw,char * filename)144 void getSigRaw(ecc_signature_t *sigraw, char *filename)
145 {
146 	int fdin;
147 	struct stat s;
148 	void *infile;
149 	int r;
150 	int rlen, roff, slen, soff;
151 	const BIGNUM *sr, *ss;
152 	unsigned char outbuf[2 * EC_COORDBYTES];
153 	ECDSA_SIG* signature;
154 
155 	fdin = open(filename, O_RDONLY);
156 	if (fdin <= 0)
157 		die(EX_NOINPUT, "Cannot open sig file: %s: %s", filename, strerror(errno));
158 
159 	r = fstat(fdin, &s);
160 	if (r != 0)
161 		die(EX_NOINPUT, "Cannot stat sig file: %s", filename);
162 
163 	infile = mmap(NULL, s.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
164 	if (!infile)
165 		die(EX_OSERR, "%s", "Cannot mmap file");
166 
167 	close(fdin);
168 
169 	if (s.st_size == 2 * EC_COORDBYTES) {
170 		/* The file is a p521 signature in RAW format. */
171 		debug_msg("File \"%s\" is a RAW signature", filename);
172 		memcpy(sigraw, infile, sizeof(ecc_signature_t));
173 	}
174 	else {
175 		/* Assume the file is a p521 signature in DER format.
176 		 * Convert the DER to a signature object, then extract the RAW. */
177 		debug_msg("File \"%s\" is a DER signature", filename);
178 
179 		signature = d2i_ECDSA_SIG(NULL,
180 					  (const unsigned char **) &infile, 7 + 2 * EC_COORDBYTES);
181 
182 		memset(&outbuf, 0, sizeof(outbuf));
183 
184 #if OPENSSL_VERSION_NUMBER >= 0x10100000L
185 		ECDSA_SIG_get0(signature, &sr, &ss);
186 #else
187 		sr = signature->r;
188 		ss = signature->s;
189 #endif
190 		rlen = BN_num_bytes(sr);
191 		roff = 66 - rlen;
192 		BN_bn2bin(sr, &outbuf[roff]);
193 
194 		slen = BN_num_bytes(ss);
195 		soff = 66 + (66 - slen);
196 		BN_bn2bin(ss, &outbuf[soff]);
197 
198 		memcpy(sigraw, outbuf, sizeof(ecc_signature_t));
199 
200 		ECDSA_SIG_free(signature);
201 	}
202 	munmap(infile, s.st_size);
203 	return;
204 }
205 
writeHdr(void * hdr,const char * outFile,int hdr_type)206 void writeHdr(void *hdr, const char *outFile, int hdr_type)
207 {
208 	int fdout;
209 	int r, hdr_sz;
210 	unsigned char md[SHA512_DIGEST_LENGTH];
211 
212 	switch (hdr_type) {
213 	case CONTAINER_HDR:
214 		hdr_sz = SECURE_BOOT_HEADERS_SIZE;
215 		break;
216 	case PREFIX_HDR:
217 		hdr_sz = sizeof(ROM_prefix_header_raw);
218 		SHA512(hdr, hdr_sz, md);
219 		verbose_print((char *) "PR header hash  = ", md, sizeof(md));
220 		break;
221 	case SOFTWARE_HDR:
222 		hdr_sz = sizeof(ROM_sw_header_raw);
223 		SHA512(hdr, hdr_sz, md);
224 		verbose_print((char *) "SW header hash  = ", md, sizeof(md));
225 		break;
226 	default:
227 		die(EX_SOFTWARE, "Unknown header type (%d)", hdr_type);
228 	}
229 
230 	fdout = open(outFile, O_WRONLY | O_CREAT | O_TRUNC,
231 			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
232 	if (fdout <= 0)
233 		die(EX_CANTCREAT, "Cannot create output file: %s", outFile);
234 
235 	r = write(fdout, (const void *) hdr, hdr_sz);
236 	close(fdout);
237 
238 	if (r < hdr_sz)
239 		die(EX_SOFTWARE, "Error writing header file (r = %d)", r);
240 
241 	debug_msg("Wrote %d bytes to %s", r, outFile);
242 
243 	return;
244 }
245 
usage(int status)246 __attribute__((__noreturn__)) void usage (int status)
247 {
248 	if (status != 0) {
249 		fprintf(stderr, "Try '%s --help' for more information.\n", progname);
250 	}
251 	else {
252 		printf("Usage: %s [options]\n", progname);
253 		printf(
254 			"\n"
255 			"Options:\n"
256 			" -h, --help              display this message and exit\n"
257 			" -v, --verbose           show verbose output\n"
258 			" -d, --debug             show additional debug output\n"
259 			" -w, --wrap              column to wrap long output in verbose mode\n"
260 			" -a, --hw_key_a          file containing HW key A key in PEM or RAW format\n"
261 			" -b, --hw_key_b          file containing HW key B key in PEM or RAW format\n"
262 			" -c, --hw_key_c          file containing HW key C key in PEM or RAW format\n"
263 			" -p, --sw_key_p          file containing SW key P key in PEM or RAW format\n"
264 			" -q, --sw_key_q          file containing SW key Q key in PEM or RAW format\n"
265 			" -r, --sw_key_r          file containing SW key R key in PEM or RAW format\n"
266 			" -A, --hw_sig_a          file containing HW key A signature in DER format\n"
267 			" -B, --hw_sig_b          file containing HW key B signature in DER format\n"
268 			" -C, --hw_sig_c          file containing HW key C signature in DER format\n"
269 			" -P, --sw_sig_p          file containing SW key P signature in DER format\n"
270 			" -Q, --sw_sig_q          file containing SW key Q signature in DER format\n"
271 			" -R, --sw_sig_r          file containing SW key R signature in DER format\n"
272 			" -l, --payload           file containing the payload to be signed\n"
273 			" -I, --imagefile         file to write containerized image (output)\n"
274 			" -o, --hw-cs-offset      code start offset for prefix header in hex\n"
275 			" -O, --sw-cs-offset      code start offset for software header in hex\n"
276 			" -f, --hw-flags          prefix header flags in hex\n"
277 			" -F, --sw-flags          software header flags in hex\n"
278 			" -L, --label             character field up to 8 bytes, written to SW header\n"
279 			"     --dumpPrefixHdr     file to dump Prefix header blob (to be signed)\n"
280 			"     --dumpSwHdr         file to dump Software header blob (to be signed)\n"
281 			"     --dumpContrHdr      file to dump full Container header (w/o payload)\n"
282 			"Note:\n"
283 			"- Keys A,B,C,P,Q,R must be valid p521 ECC keys. Keys may be provided as public\n"
284 			"  or private key in PEM format, or public key in uncompressed raw format.\n"
285 			"\n");
286 	};
287 	exit(status);
288 }
289 
290 static struct option const opts[] = {
291 	{ "help",             no_argument,       0,  'h' },
292 	{ "verbose",          no_argument,       0,  'v' },
293 	{ "debug",            no_argument,       0,  'd' },
294 	{ "wrap",             required_argument, 0,  'w' },
295 	{ "hw_key_a",         required_argument, 0,  'a' },
296 	{ "hw_key_b",         required_argument, 0,  'b' },
297 	{ "hw_key_c",         required_argument, 0,  'c' },
298 	{ "sw_key_p",         required_argument, 0,  'p' },
299 	{ "sw_key_q",         required_argument, 0,  'q' },
300 	{ "sw_key_r",         required_argument, 0,  'r' },
301 	{ "hw_sig_a",         required_argument, 0,  'A' },
302 	{ "hw_sig_b",         required_argument, 0,  'B' },
303 	{ "hw_sig_c",         required_argument, 0,  'C' },
304 	{ "sw_sig_p",         required_argument, 0,  'P' },
305 	{ "sw_sig_q",         required_argument, 0,  'Q' },
306 	{ "sw_sig_r",         required_argument, 0,  'R' },
307 	{ "payload",          required_argument, 0,  'l' },
308 	{ "imagefile",        required_argument, 0,  'I' },
309 	{ "hw-cs-offset",     required_argument, 0,  'o' },
310 	{ "sw-cs-offset",     required_argument, 0,  'O' },
311 	{ "hw-flags",         required_argument, 0,  'f' },
312 	{ "sw-flags",         required_argument, 0,  'F' },
313 	{ "label",            required_argument, 0,  'L' },
314 	{ "dumpPrefixHdr",    required_argument, 0,  128 },
315 	{ "dumpSwHdr",        required_argument, 0,  129 },
316 	{ "dumpContrHdr",     required_argument, 0,  130 },
317 	{ NULL, 0, NULL, 0 }
318 };
319 
320 static struct {
321 	char *hw_keyfn_a;
322 	char *hw_keyfn_b;
323 	char *hw_keyfn_c;
324 	char *sw_keyfn_p;
325 	char *sw_keyfn_q;
326 	char *sw_keyfn_r;
327 	char *hw_sigfn_a;
328 	char *hw_sigfn_b;
329 	char *hw_sigfn_c;
330 	char *sw_sigfn_p;
331 	char *sw_sigfn_q;
332 	char *sw_sigfn_r;
333 	char *imagefn;
334 	char *payloadfn;
335 	char *hw_cs_offset;
336 	char *sw_cs_offset;
337 	char *hw_flags;
338 	char *sw_flags;
339 	char *label;
340 	char *prhdrfn;
341 	char *swhdrfn;
342 	char *cthdrfn;
343 } params;
344 
345 
main(int argc,char * argv[])346 int main(int argc, char* argv[])
347 {
348 	int fdin, fdout;
349 	int indexptr;
350 	unsigned int size, offset;
351 	void *container = malloc(SECURE_BOOT_HEADERS_SIZE);
352 	char *buf = malloc(SECURE_BOOT_HEADERS_SIZE);
353 	struct stat payload_st;
354 	off_t l;
355 	void *infile;
356 	int r;
357 	uint32_t data;
358 	uint64_t data64;
359 	ROM_container_raw *c = (ROM_container_raw*) container;
360 	ROM_prefix_header_raw *ph;
361 	ROM_prefix_data_raw *pd;
362 	ROM_sw_header_raw *swh;
363 	ROM_sw_sig_raw *ssig;
364 
365 	unsigned char md[SHA512_DIGEST_LENGTH];
366 	void *p;
367 	ecc_key_t pubkeyraw;
368 	ecc_signature_t sigraw;
369 
370 	progname = strrchr(argv[0], '/');
371 	if (progname != NULL)
372 		++progname;
373 	else
374 		progname = argv[0];
375 
376 	memset(container, 0, SECURE_BOOT_HEADERS_SIZE);
377 
378 	while (1) {
379 		int opt;
380 		opt = getopt_long(argc, argv, "hvdw:a:b:c:p:q:r:A:B:C:P:Q:R:L:I:o:O:f:F:l:",
381 				opts, &indexptr);
382 		if (opt == -1)
383 			break;
384 
385 		switch (opt) {
386 		case 'h':
387 		case '?':
388 			usage(EX_OK);
389 			break;
390 		case 'v':
391 			verbose = true;
392 			break;
393 		case 'd':
394 			debug = true;
395 			break;
396 		case 'w':
397 			wrap = atoi(optarg);
398 			wrap = (wrap < 2) ? INT_MAX : wrap;
399 			break;
400 		case 'a':
401 			params.hw_keyfn_a = optarg;
402 			break;
403 		case 'b':
404 			params.hw_keyfn_b = optarg;
405 			break;
406 		case 'c':
407 			params.hw_keyfn_c = optarg;
408 			break;
409 		case 'p':
410 			params.sw_keyfn_p = optarg;
411 			break;
412 		case 'q':
413 			params.sw_keyfn_q = optarg;
414 			break;
415 		case 'r':
416 			params.sw_keyfn_r = optarg;
417 			break;
418 		case 'A':
419 			params.hw_sigfn_a = optarg;
420 			break;
421 		case 'B':
422 			params.hw_sigfn_b = optarg;
423 			break;
424 		case 'C':
425 			params.hw_sigfn_c = optarg;
426 			break;
427 		case 'P':
428 			params.sw_sigfn_p = optarg;
429 			break;
430 		case 'Q':
431 			params.sw_sigfn_q = optarg;
432 			break;
433 		case 'R':
434 			params.sw_sigfn_r = optarg;
435 			break;
436 		case 'l':
437 			params.payloadfn = optarg;
438 			break;
439 		case 'I':
440 			params.imagefn = optarg;
441 			break;
442 		case 'o':
443 			params.hw_cs_offset = optarg;
444 			break;
445 		case 'O':
446 			params.sw_cs_offset = optarg;
447 			break;
448 		case 'f':
449 			params.hw_flags = optarg;
450 			break;
451 		case 'F':
452 			params.sw_flags = optarg;
453 			break;
454 		case 'L':
455 			params.label = optarg;
456 			break;
457 		case 128:
458 			params.prhdrfn = optarg;
459 			break;
460 		case 129:
461 			params.swhdrfn = optarg;
462 			break;
463 		case 130:
464 			params.cthdrfn = optarg;
465 			break;
466 		default:
467 			usage(EX_USAGE);
468 		}
469 	}
470 
471 	fdin = open(params.payloadfn, O_RDONLY);
472 	if (fdin <= 0)
473 		die(EX_NOINPUT, "Cannot open payload file: %s", params.payloadfn);
474 
475 	r = fstat(fdin, &payload_st);
476 	if (r != 0)
477 		die(EX_NOINPUT, "Cannot stat payload file: %s", params.payloadfn);
478 
479 	infile = mmap(NULL, payload_st.st_size, PROT_READ, MAP_PRIVATE, fdin, 0);
480 	if (!infile)
481 		die(EX_OSERR, "%s", "Cannot mmap file");
482 
483 	fdout = open(params.imagefn, O_WRONLY | O_CREAT | O_TRUNC,
484 			S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
485 	if (fdout <= 0)
486 		die(EX_CANTCREAT, "Cannot create output file: %s", params.imagefn);
487 
488 	// Container creation starts here.
489 	c->magic_number = cpu_to_be32(ROM_MAGIC_NUMBER);
490 	c->version = cpu_to_be16(1);
491 	c->container_size = cpu_to_be64(SECURE_BOOT_HEADERS_SIZE + payload_st.st_size);
492 	c->target_hrmor = 0;
493 	c->stack_pointer = 0;
494 	memset(c->hw_pkey_a, 0, sizeof(ecc_key_t));
495 	memset(c->hw_pkey_b, 0, sizeof(ecc_key_t));
496 	memset(c->hw_pkey_c, 0, sizeof(ecc_key_t));
497 	if (params.hw_keyfn_a) {
498 		getPublicKeyRaw(&pubkeyraw, params.hw_keyfn_a);
499 		verbose_print((char *) "pubkey A = ", pubkeyraw, sizeof(pubkeyraw));
500 		memcpy(c->hw_pkey_a, pubkeyraw, sizeof(ecc_key_t));
501 	}
502 	if (params.hw_keyfn_b) {
503 		getPublicKeyRaw(&pubkeyraw, params.hw_keyfn_b);
504 		verbose_print((char *) "pubkey B = ", pubkeyraw, sizeof(pubkeyraw));
505 		memcpy(c->hw_pkey_b, pubkeyraw, sizeof(ecc_key_t));
506 	}
507 	if (params.hw_keyfn_c) {
508 		getPublicKeyRaw(&pubkeyraw, params.hw_keyfn_c);
509 		verbose_print((char *) "pubkey C = ", pubkeyraw, sizeof(pubkeyraw));
510 		memcpy(c->hw_pkey_c, pubkeyraw, sizeof(ecc_key_t));
511 	}
512 	p = SHA512(c->hw_pkey_a, sizeof(ecc_key_t) * 3, md);
513 	if (!p)
514 		die(EX_SOFTWARE, "%s", "Cannot get SHA512");
515 	verbose_print((char *) "HW keys hash = ", md, sizeof(md));
516 
517 	ph = container + sizeof(ROM_container_raw);
518 	ph->ver_alg.version = cpu_to_be16(1);
519 	ph->ver_alg.hash_alg = 1;
520 	ph->ver_alg.sig_alg = 1;
521 
522 	// Set code-start-offset.
523 	if (params.hw_cs_offset) {
524 		if (!isValidHex(params.hw_cs_offset, 4))
525 			die(EX_DATAERR, "%s",
526 					"Invalid input for hw-cs-offset, expecting a 4 byte hexadecimal value");
527 		sscanf(params.hw_cs_offset, "%lx", &data64);
528 		ph->code_start_offset = cpu_to_be64(data64);
529 		verbose_msg("hw-cs-offset = %#010lx", data64);
530 	} else {
531 		ph->code_start_offset = 0;
532 	}
533 	ph->reserved = 0;
534 
535 	// Set flags.
536 	if (params.hw_flags) {
537 		if (!isValidHex(params.hw_flags, 4))
538 			die(EX_DATAERR, "%s",
539 					"Invalid input for hw-flags, expecting a 4 byte hexadecimal value");
540 		sscanf(params.hw_flags, "%x", &data);
541 		ph->flags = cpu_to_be32(data);
542 		verbose_msg("hw-flags = %#010x", data);
543 	} else {
544 		ph->flags = cpu_to_be32(0x80000000);
545 	}
546 	memset(ph->payload_hash, 0, sizeof(sha2_hash_t));
547 	ph->ecid_count = 0;
548 
549 	pd = (ROM_prefix_data_raw*) ph->ecid;
550 	memset(pd->hw_sig_a, 0, sizeof(ecc_signature_t));
551 	memset(pd->hw_sig_b, 0, sizeof(ecc_signature_t));
552 	memset(pd->hw_sig_c, 0, sizeof(ecc_signature_t));
553 
554 	// Write the HW signatures.
555 	if (params.hw_sigfn_a) {
556 		getSigRaw(&sigraw, params.hw_sigfn_a);
557 		verbose_print((char *) "signature A = ", sigraw, sizeof(sigraw));
558 		memcpy(pd->hw_sig_a, sigraw, sizeof(ecc_key_t));
559 	}
560 	if (params.hw_sigfn_b) {
561 		getSigRaw(&sigraw, params.hw_sigfn_b);
562 		verbose_print((char *) "signature B = ", sigraw, sizeof(sigraw));
563 		memcpy(pd->hw_sig_b, sigraw, sizeof(ecc_key_t));
564 	}
565 	if (params.hw_sigfn_c) {
566 		getSigRaw(&sigraw, params.hw_sigfn_c);
567 		verbose_print((char *) "signature C = ", sigraw, sizeof(sigraw));
568 		memcpy(pd->hw_sig_c, sigraw, sizeof(ecc_key_t));
569 	}
570 	memset(pd->sw_pkey_p, 0, sizeof(ecc_key_t));
571 	memset(pd->sw_pkey_q, 0, sizeof(ecc_key_t));
572 	memset(pd->sw_pkey_r, 0, sizeof(ecc_key_t));
573 
574 	// Write the FW keys.
575 	if (params.sw_keyfn_p) {
576 		getPublicKeyRaw(&pubkeyraw, params.sw_keyfn_p);
577 		verbose_print((char *) "pubkey P = ", pubkeyraw, sizeof(pubkeyraw));
578 		memcpy(pd->sw_pkey_p, pubkeyraw, sizeof(ecc_key_t));
579 		ph->sw_key_count++;
580 	}
581 	if (params.sw_keyfn_q) {
582 		getPublicKeyRaw(&pubkeyraw, params.sw_keyfn_q);
583 		verbose_print((char *) "pubkey Q = ", pubkeyraw, sizeof(pubkeyraw));
584 		memcpy(pd->sw_pkey_q, pubkeyraw, sizeof(ecc_key_t));
585 		ph->sw_key_count++;
586 	}
587 	if (params.sw_keyfn_r) {
588 		getPublicKeyRaw(&pubkeyraw, params.sw_keyfn_r);
589 		verbose_print((char *) "pubkey R = ", pubkeyraw, sizeof(pubkeyraw));
590 		memcpy(pd->sw_pkey_r, pubkeyraw, sizeof(ecc_key_t));
591 		ph->sw_key_count++;
592 	}
593 	debug_msg("sw_key_count = %u", ph->sw_key_count);
594 	ph->payload_size = cpu_to_be64(ph->sw_key_count * sizeof(ecc_key_t));
595 
596 	// Calculate the SW keys hash.
597 	p = SHA512(pd->sw_pkey_p, sizeof(ecc_key_t) * ph->sw_key_count, md);
598 	if (!p)
599 		die(EX_SOFTWARE, "%s", "Cannot get SHA512");
600 	memcpy(ph->payload_hash, md, sizeof(sha2_hash_t));
601 	verbose_print((char *) "SW keys hash = ", md, sizeof(md));
602 
603 	// Dump the Prefix header.
604 	if (params.prhdrfn)
605 		writeHdr((void *) ph, params.prhdrfn, PREFIX_HDR);
606 
607 	swh = (ROM_sw_header_raw*) (((uint8_t*) pd) + sizeof(ecc_signature_t) * 3
608 			+ be64_to_cpu(ph->payload_size));
609 	swh->ver_alg.version = cpu_to_be16(1);
610 	swh->ver_alg.hash_alg = 1;
611 	swh->ver_alg.sig_alg = 1;
612 
613 	// Set code-start-offset.
614 	if (params.sw_cs_offset) {
615 		if (!isValidHex(params.sw_cs_offset, 4))
616 			die(EX_DATAERR, "%s",
617 					"Invalid input for sw-cs-offset, expecting a 4 byte hexadecimal value");
618 		sscanf(params.sw_cs_offset, "%lx", &data64);
619 		swh->code_start_offset = cpu_to_be64(data64);
620 		verbose_msg("sw-cs-offset = %#010lx", data64);
621 	} else {
622 		swh->code_start_offset = 0;
623 	}
624 	swh->reserved = 0;
625 
626 	// Add component ID (label).
627 	if (params.label) {
628 		if (!isValidAscii(params.label, 0))
629 			die(EX_DATAERR, "%s",
630 					"Invalid input for label, expecting a 8 char ASCII value");
631 		strncpy((char *) &swh->reserved, params.label, 8);
632 		verbose_msg("component ID (was reserved) = %.8s",
633 				(char * ) &swh->reserved);
634 	}
635 
636 	// Set flags.
637 	if (params.sw_flags) {
638 		if (!isValidHex(params.sw_flags, 4))
639 			die(EX_DATAERR, "%s",
640 					"Invalid input for sw-flags, expecting a 4 byte hexadecimal value");
641 		sscanf(params.sw_flags, "%x", &data);
642 		swh->flags = cpu_to_be32(data);
643 		verbose_msg("sw-flags = %#010x", data);
644 	} else {
645 		swh->flags = cpu_to_be32(0x00000000);
646 	}
647 	swh->reserved_0 = 0;
648 	swh->payload_size = cpu_to_be64(payload_st.st_size);
649 
650 	// Calculate the payload hash.
651 	p = SHA512(infile, payload_st.st_size, md);
652 	if (!p)
653 		die(EX_SOFTWARE, "%s", "Cannot get SHA512");
654 	memcpy(swh->payload_hash, md, sizeof(sha2_hash_t));
655 	verbose_print((char *) "Payload hash = ", md, sizeof(md));
656 
657 	// Dump the Software header.
658 	if (params.swhdrfn)
659 		writeHdr((void *) swh, params.swhdrfn, SOFTWARE_HDR);
660 
661 	ssig = (ROM_sw_sig_raw*) (((uint8_t*) swh) + sizeof(ROM_sw_header_raw));
662 	memset(ssig->sw_sig_p, 0, sizeof(ecc_signature_t));
663 	memset(ssig->sw_sig_q, 0, sizeof(ecc_signature_t));
664 	memset(ssig->sw_sig_r, 0, sizeof(ecc_signature_t));
665 
666 	// Write the HW signatures.
667 	if (params.sw_sigfn_p) {
668 		getSigRaw(&sigraw, params.sw_sigfn_p);
669 		verbose_print((char *) "signature P = ", sigraw, sizeof(sigraw));
670 		memcpy(ssig->sw_sig_p, sigraw, sizeof(ecc_key_t));
671 	}
672 	if (params.sw_sigfn_q) {
673 		getSigRaw(&sigraw, params.sw_sigfn_q);
674 		verbose_print((char *) "signature Q = ", sigraw, sizeof(sigraw));
675 		memcpy(ssig->sw_sig_q, sigraw, sizeof(ecc_key_t));
676 	}
677 	if (params.sw_sigfn_r) {
678 		getSigRaw(&sigraw, params.sw_sigfn_r);
679 		verbose_print((char *) "signature R = ", sigraw, sizeof(sigraw));
680 		memcpy(ssig->sw_sig_r, sigraw, sizeof(ecc_key_t));
681 	}
682 
683 	// Dump the full container header.
684 	if (params.cthdrfn)
685 		writeHdr((void *) c, params.cthdrfn, CONTAINER_HDR);
686 
687 	// Print container stats.
688 	size = (uint8_t*) ph - (uint8_t *) c;
689 	offset = (uint8_t*) c - (uint8_t *) c;
690 	verbose_msg("HW header size        = %4u (%#06x) at offset %4u (%#06x)",
691 			size, size, offset, offset);
692 	size = (uint8_t*) pd - (uint8_t *) ph;
693 	offset = (uint8_t*) ph - (uint8_t *) c;
694 	verbose_msg("Prefix header size    = %4u (%#06x) at offset %4u (%#06x)",
695 			size, size, offset, offset);
696 	size = (uint8_t*) swh - (uint8_t *) pd;
697 	offset = (uint8_t*) pd - (uint8_t *) c;
698 	verbose_msg("Prefix data size      = %4u (%#06x) at offset %4u (%#06x)",
699 			size, size, offset, offset);
700 	size = (uint8_t*) ssig - (uint8_t *) swh;
701 	offset = (uint8_t*) swh - (uint8_t *) c;
702 	verbose_msg("SW header size        = %4u (%#06x) at offset %4u (%#06x)",
703 			size, size, offset, offset);
704 	size = sizeof(ecc_key_t) * ph->sw_key_count;
705 	offset = (uint8_t*) ssig - (uint8_t *) c;
706 	verbose_msg("SW signature size     = %4u (%#06x) at offset %4u (%#06x)",
707 			size, size, offset, offset);
708 
709 	verbose_msg("TOTAL HEADER SIZE     = %4d (%#0x)", SECURE_BOOT_HEADERS_SIZE,
710 			SECURE_BOOT_HEADERS_SIZE);
711 	verbose_msg("PAYLOAD SIZE          = %4lu (%#0lx)",
712 			be64_to_cpu(swh->payload_size), be64_to_cpu(swh->payload_size));
713 	verbose_msg("TOTAL CONTAINER SIZE  = %4lu (%#0lx)",
714 			be64_to_cpu(c->container_size), be64_to_cpu(c->container_size));
715 
716 	// Write container.
717 	r = write(fdout, container, SECURE_BOOT_HEADERS_SIZE);
718 	if (r != 4096)
719 		die(EX_SOFTWARE, "Cannot write container (r = %d)", r);
720 	r = read(fdin, buf, payload_st.st_size % 4096);
721 	r = write(fdout, buf, payload_st.st_size % 4096);
722 	l = payload_st.st_size - payload_st.st_size % 4096;
723 	while (l) {
724 		r = read(fdin, buf, 4096);
725 		r = write(fdout, buf, 4096);
726 		l -= 4096;
727 	};
728 	close(fdin);
729 	close(fdout);
730 
731 	free(container);
732 	free(buf);
733 	return 0;
734 }
735