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