blob: 15c36e22684fdd86b449f36b40fca72a265effd0 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Dirk Eibachfb605942017-02-22 16:07:23 +01002/*
3 * (C) Copyright 2016
4 * Mario Six, Guntermann & Drunck GmbH, mario.six@gdsys.cc
Dirk Eibachfb605942017-02-22 16:07:23 +01005 */
6
Simon Glassadaaa482019-11-14 12:57:43 -07007#include <command.h>
Simon Glass0af6e2d2019-08-01 09:46:52 -06008#include <env.h>
Miquel Raynal4c6759e2018-05-15 11:57:06 +02009#include <tpm-v1.h>
Dirk Eibachfb605942017-02-22 16:07:23 +010010#include <malloc.h>
11#include <linux/ctype.h>
12#include <asm/unaligned.h>
13
14#include "hre.h"
15
Simon Glass8ceca1d2018-11-18 14:22:27 -070016int flush_keys(struct udevice *tpm)
Dirk Eibachfb605942017-02-22 16:07:23 +010017{
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 */
Simon Glass3b8692a2021-02-06 14:23:36 -070025 err = tpm1_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
26 sizeof(buf));
Dirk Eibachfb605942017-02-22 16:07:23 +010027 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) {
Simon Glass3b8692a2021-02-06 14:23:36 -070032 err = tpm1_flush_specific(tpm, get_unaligned_be32(ptr),
33 TPM_RT_KEY);
Dirk Eibachfb605942017-02-22 16:07:23 +010034 if (err && err != TPM_KEY_OWNER_CONTROL)
35 return err;
36 }
37
38 return 0;
39}
40
41int 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
73int 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
108struct 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
Simon Glass8ceca1d2018-11-18 14:22:27 -0700127int load_and_run_keyprog(struct udevice *tpm)
Dirk Eibachfb605942017-02-22 16:07:23 +0100128{
129 char *cmd = NULL;
130 u8 *binprog = NULL;
131 char *hexprog;
132 struct key_program *prog;
133
Simon Glass64b723f2017-08-03 12:22:12 -0600134 cmd = env_get("loadkeyprogram");
Dirk Eibachfb605942017-02-22 16:07:23 +0100135
136 if (!cmd || run_command(cmd, 0))
137 return 1;
138
Simon Glass64b723f2017-08-03 12:22:12 -0600139 hexprog = env_get("keyprogram");
Dirk Eibachfb605942017-02-22 16:07:23 +0100140
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
Simon Glass8ceca1d2018-11-18 14:22:27 -0700150 if (hre_run_program(tpm, prog->code, prog->code_size)) {
Dirk Eibachfb605942017-02-22 16:07:23 +0100151 free(prog);
152 return 1;
153 }
154
155 printf("\nSD code ran successfully\n");
156
157 free(prog);
158
159 return 0;
160}