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