blob: 291edc340df990e0d3938e788022925f3e0f0c33 [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>
Miquel Raynal4c6759e2018-05-15 11:57:06 +02008#include <tpm-v1.h>
Dirk Eibachfb605942017-02-22 16:07:23 +01009#include <malloc.h>
10#include <linux/ctype.h>
11#include <asm/unaligned.h>
12
13#include "hre.h"
14
Simon Glass8ceca1d2018-11-18 14:22:27 -070015int flush_keys(struct udevice *tpm)
Dirk Eibachfb605942017-02-22 16:07:23 +010016{
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 */
Simon Glass8ceca1d2018-11-18 14:22:27 -070024 err = tpm_get_capability(tpm, TPM_CAP_HANDLE, TPM_RT_KEY, buf,
25 sizeof(buf));
Dirk Eibachfb605942017-02-22 16:07:23 +010026 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) {
Simon Glass8ceca1d2018-11-18 14:22:27 -070031 err = tpm_flush_specific(tpm, get_unaligned_be32(ptr),
32 TPM_RT_KEY);
Dirk Eibachfb605942017-02-22 16:07:23 +010033 if (err && err != TPM_KEY_OWNER_CONTROL)
34 return err;
35 }
36
37 return 0;
38}
39
40int 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
72int 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
107struct 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
Simon Glass8ceca1d2018-11-18 14:22:27 -0700126int load_and_run_keyprog(struct udevice *tpm)
Dirk Eibachfb605942017-02-22 16:07:23 +0100127{
128 char *cmd = NULL;
129 u8 *binprog = NULL;
130 char *hexprog;
131 struct key_program *prog;
132
Simon Glass64b723f2017-08-03 12:22:12 -0600133 cmd = env_get("loadkeyprogram");
Dirk Eibachfb605942017-02-22 16:07:23 +0100134
135 if (!cmd || run_command(cmd, 0))
136 return 1;
137
Simon Glass64b723f2017-08-03 12:22:12 -0600138 hexprog = env_get("keyprogram");
Dirk Eibachfb605942017-02-22 16:07:23 +0100139
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
Simon Glass8ceca1d2018-11-18 14:22:27 -0700149 if (hre_run_program(tpm, prog->code, prog->code_size)) {
Dirk Eibachfb605942017-02-22 16:07:23 +0100150 free(prog);
151 return 1;
152 }
153
154 printf("\nSD code ran successfully\n");
155
156 free(prog);
157
158 return 0;
159}