]> git.sur5r.net Git - u-boot/blob - board/gdsys/a38x/keyprogram.c
SPDX: Convert all of our single license tags to Linux Kernel style
[u-boot] / board / gdsys / a38x / keyprogram.c
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.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(void)
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_CAP_HANDLE, TPM_RT_KEY, buf, sizeof(buf));
25         if (err)
26                 return -1;
27         key_count = get_unaligned_be16(buf);
28         ptr = buf + 2;
29         for (i = 0; i < key_count; ++i, ptr += 4) {
30                 err = tpm_flush_specific(get_unaligned_be32(ptr), TPM_RT_KEY);
31                 if (err && err != TPM_KEY_OWNER_CONTROL)
32                         return err;
33         }
34
35         return 0;
36 }
37
38 int decode_hexstr(char *hexstr, u8 **result)
39 {
40         int len = strlen(hexstr);
41         int bytes = len / 2;
42         int i;
43         u8 acc = 0;
44
45         if (len % 2 == 1)
46                 return 1;
47
48         *result = (u8 *)malloc(bytes);
49
50         for (i = 0; i < len; i++) {
51                 char cur = tolower(hexstr[i]);
52                 u8 val;
53
54                 if ((cur >= 'a' && cur <= 'f') || (cur >= '0' && cur <= '9')) {
55                         val = cur - (cur > '9' ? 87 : 48);
56
57                         if (i % 2 == 0)
58                                 acc = 16 * val;
59                         else
60                                 (*result)[i / 2] = acc + val;
61                 } else {
62                         free(*result);
63                         return 1;
64                 }
65         }
66
67         return 0;
68 }
69
70 int extract_subprogram(u8 **progdata, u32 expected_magic,
71                        struct key_program **result)
72 {
73         struct key_program *prog = *result;
74         u32 magic, code_crc, code_size;
75
76         magic = get_unaligned_be32(*progdata);
77         code_crc = get_unaligned_be32(*progdata + 4);
78         code_size = get_unaligned_be32(*progdata + 8);
79
80         *progdata += 12;
81
82         if (magic != expected_magic)
83                 return -1;
84
85         *result = malloc(sizeof(struct key_program) + code_size);
86
87         if (!*result)
88                 return -1;
89
90         prog->magic = magic;
91         prog->code_crc = code_crc;
92         prog->code_size = code_size;
93         memcpy(prog->code, *progdata, code_size);
94
95         *progdata += code_size;
96
97         if (hre_verify_program(prog)) {
98                 free(prog);
99                 return -1;
100         }
101
102         return 0;
103 }
104
105 struct key_program *parse_and_check_keyprog(u8 *progdata)
106 {
107         struct key_program *result = NULL, *hmac = NULL;
108
109         /* Part 1: Load key program */
110
111         if (extract_subprogram(&progdata, MAGIC_KEY_PROGRAM, &result))
112                 return NULL;
113
114         /* Part 2: Load hmac program */
115
116         if (extract_subprogram(&progdata, MAGIC_HMAC, &hmac))
117                 return NULL;
118
119         free(hmac);
120
121         return result;
122 }
123
124 int load_and_run_keyprog(void)
125 {
126         char *cmd = NULL;
127         u8 *binprog = NULL;
128         char *hexprog;
129         struct key_program *prog;
130
131         cmd = env_get("loadkeyprogram");
132
133         if (!cmd || run_command(cmd, 0))
134                 return 1;
135
136         hexprog = env_get("keyprogram");
137
138         if (decode_hexstr(hexprog, &binprog))
139                 return 1;
140
141         prog = parse_and_check_keyprog(binprog);
142         free(binprog);
143
144         if (!prog)
145                 return 1;
146
147         if (hre_run_program(prog->code, prog->code_size)) {
148                 free(prog);
149                 return 1;
150         }
151
152         printf("\nSD code ran successfully\n");
153
154         free(prog);
155
156         return 0;
157 }