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