xref: /OK3568_Linux_fs/u-boot/board/gdsys/a38x/keyprogram.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * (C) Copyright 2016
3*4882a593Smuzhiyun  * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * SPDX-License-Identifier:    GPL-2.0+
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <common.h>
9*4882a593Smuzhiyun #include <tpm.h>
10*4882a593Smuzhiyun #include <malloc.h>
11*4882a593Smuzhiyun #include <linux/ctype.h>
12*4882a593Smuzhiyun #include <asm/unaligned.h>
13*4882a593Smuzhiyun 
14*4882a593Smuzhiyun #include "hre.h"
15*4882a593Smuzhiyun 
flush_keys(void)16*4882a593Smuzhiyun int flush_keys(void)
17*4882a593Smuzhiyun {
18*4882a593Smuzhiyun 	u16 key_count;
19*4882a593Smuzhiyun 	u8 buf[288];
20*4882a593Smuzhiyun 	u8 *ptr;
21*4882a593Smuzhiyun 	u32 err;
22*4882a593Smuzhiyun 	uint i;
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun 	/* fetch list of already loaded keys in the TPM */
25*4882a593Smuzhiyun 	err = tpm_get_capability(TPM_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
26*4882a593Smuzhiyun 	if (err)
27*4882a593Smuzhiyun 		return -1;
28*4882a593Smuzhiyun 	key_count = get_unaligned_be16(buf);
29*4882a593Smuzhiyun 	ptr = buf + 2;
30*4882a593Smuzhiyun 	for (i = 0; i < key_count; ++i, ptr += 4) {
31*4882a593Smuzhiyun 		err = tpm_flush_specific(get_unaligned_be32(ptr), TPM_RT_KEY);
32*4882a593Smuzhiyun 		if (err && err != TPM_KEY_OWNER_CONTROL)
33*4882a593Smuzhiyun 			return err;
34*4882a593Smuzhiyun 	}
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun 	return 0;
37*4882a593Smuzhiyun }
38*4882a593Smuzhiyun 
decode_hexstr(char * hexstr,u8 ** result)39*4882a593Smuzhiyun int decode_hexstr(char *hexstr, u8 **result)
40*4882a593Smuzhiyun {
41*4882a593Smuzhiyun 	int len = strlen(hexstr);
42*4882a593Smuzhiyun 	int bytes = len / 2;
43*4882a593Smuzhiyun 	int i;
44*4882a593Smuzhiyun 	u8 acc = 0;
45*4882a593Smuzhiyun 
46*4882a593Smuzhiyun 	if (len % 2 == 1)
47*4882a593Smuzhiyun 		return 1;
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	*result = (u8 *)malloc(bytes);
50*4882a593Smuzhiyun 
51*4882a593Smuzhiyun 	for (i = 0; i < len; i++) {
52*4882a593Smuzhiyun 		char cur = tolower(hexstr[i]);
53*4882a593Smuzhiyun 		u8 val;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 		if ((cur >= 'a' && cur <= 'f') || (cur >= '0' && cur <= '9')) {
56*4882a593Smuzhiyun 			val = cur - (cur > '9' ? 87 : 48);
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 			if (i % 2 == 0)
59*4882a593Smuzhiyun 				acc = 16 * val;
60*4882a593Smuzhiyun 			else
61*4882a593Smuzhiyun 				(*result)[i / 2] = acc + val;
62*4882a593Smuzhiyun 		} else {
63*4882a593Smuzhiyun 			free(*result);
64*4882a593Smuzhiyun 			return 1;
65*4882a593Smuzhiyun 		}
66*4882a593Smuzhiyun 	}
67*4882a593Smuzhiyun 
68*4882a593Smuzhiyun 	return 0;
69*4882a593Smuzhiyun }
70*4882a593Smuzhiyun 
extract_subprogram(u8 ** progdata,u32 expected_magic,struct key_program ** result)71*4882a593Smuzhiyun int extract_subprogram(u8 **progdata, u32 expected_magic,
72*4882a593Smuzhiyun 		       struct key_program **result)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun 	struct key_program *prog = *result;
75*4882a593Smuzhiyun 	u32 magic, code_crc, code_size;
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun 	magic = get_unaligned_be32(*progdata);
78*4882a593Smuzhiyun 	code_crc = get_unaligned_be32(*progdata + 4);
79*4882a593Smuzhiyun 	code_size = get_unaligned_be32(*progdata + 8);
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun 	*progdata += 12;
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun 	if (magic != expected_magic)
84*4882a593Smuzhiyun 		return -1;
85*4882a593Smuzhiyun 
86*4882a593Smuzhiyun 	*result = malloc(sizeof(struct key_program) + code_size);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	if (!*result)
89*4882a593Smuzhiyun 		return -1;
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	prog->magic = magic;
92*4882a593Smuzhiyun 	prog->code_crc = code_crc;
93*4882a593Smuzhiyun 	prog->code_size = code_size;
94*4882a593Smuzhiyun 	memcpy(prog->code, *progdata, code_size);
95*4882a593Smuzhiyun 
96*4882a593Smuzhiyun 	*progdata += code_size;
97*4882a593Smuzhiyun 
98*4882a593Smuzhiyun 	if (hre_verify_program(prog)) {
99*4882a593Smuzhiyun 		free(prog);
100*4882a593Smuzhiyun 		return -1;
101*4882a593Smuzhiyun 	}
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun 	return 0;
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun 
parse_and_check_keyprog(u8 * progdata)106*4882a593Smuzhiyun struct key_program *parse_and_check_keyprog(u8 *progdata)
107*4882a593Smuzhiyun {
108*4882a593Smuzhiyun 	struct key_program *result = NULL, *hmac = NULL;
109*4882a593Smuzhiyun 
110*4882a593Smuzhiyun 	/* Part 1: Load key program */
111*4882a593Smuzhiyun 
112*4882a593Smuzhiyun 	if (extract_subprogram(&progdata, MAGIC_KEY_PROGRAM, &result))
113*4882a593Smuzhiyun 		return NULL;
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun 	/* Part 2: Load hmac program */
116*4882a593Smuzhiyun 
117*4882a593Smuzhiyun 	if (extract_subprogram(&progdata, MAGIC_HMAC, &hmac))
118*4882a593Smuzhiyun 		return NULL;
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	free(hmac);
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun 	return result;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun 
load_and_run_keyprog(void)125*4882a593Smuzhiyun int load_and_run_keyprog(void)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun 	char *cmd = NULL;
128*4882a593Smuzhiyun 	u8 *binprog = NULL;
129*4882a593Smuzhiyun 	char *hexprog;
130*4882a593Smuzhiyun 	struct key_program *prog;
131*4882a593Smuzhiyun 
132*4882a593Smuzhiyun 	cmd = env_get("loadkeyprogram");
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun 	if (!cmd || run_command(cmd, 0))
135*4882a593Smuzhiyun 		return 1;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun 	hexprog = env_get("keyprogram");
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun 	if (decode_hexstr(hexprog, &binprog))
140*4882a593Smuzhiyun 		return 1;
141*4882a593Smuzhiyun 
142*4882a593Smuzhiyun 	prog = parse_and_check_keyprog(binprog);
143*4882a593Smuzhiyun 	free(binprog);
144*4882a593Smuzhiyun 
145*4882a593Smuzhiyun 	if (!prog)
146*4882a593Smuzhiyun 		return 1;
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	if (hre_run_program(prog->code, prog->code_size)) {
149*4882a593Smuzhiyun 		free(prog);
150*4882a593Smuzhiyun 		return 1;
151*4882a593Smuzhiyun 	}
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	printf("\nSD code ran successfully\n");
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	free(prog);
156*4882a593Smuzhiyun 
157*4882a593Smuzhiyun 	return 0;
158*4882a593Smuzhiyun }
159