1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24#include "qemu/osdep.h"
25#include "qapi/error.h"
26#include "crypto/secret.h"
27#include "hw/misc/xlnx-aes.h"
28
29static int xlnx_aes_k256_xtob(const char *xs, uint8_t key[32], Error **errp)
30{
31 unsigned i;
32
33 for (i = 0; i < 64; i += 2) {
34 unsigned k8;
35 int j;
36
37 for (k8 = 0, j = i; j < (i + 2); j++) {
38 gint x = g_ascii_xdigit_value(xs[j]);
39
40 if (x == -1) {
41 if (xs[j]) {
42 error_setg(errp, "Error - \"%.*s[%c: not a hex digit]%s\"",
43 j, xs, xs[j], &xs[j + 1]);
44 } else {
45 error_setg(errp, "Error - \"%s\": %d hex digits < 64",
46 xs, j);
47 }
48 return -1;
49 }
50
51 k8 = (k8 << 4) | (x & 15);
52 }
53
54 key[i / 2] = k8;
55 }
56
57 return 0;
58}
59
60static char *xlnx_aes_k256_get_secret(Object *obj, const char *id_prop,
61 Error **errp)
62{
63 Error *local_err = NULL;
64 char *secret_id, *data = NULL;
65 int rc = 0;
66
67
68 secret_id = object_property_get_str(obj, id_prop, NULL);
69 if (!secret_id) {
70 goto done;
71 }
72
73 data = qcrypto_secret_lookup_as_utf8(secret_id, &local_err);
74 if (data) {
75 data = g_strchomp(data);
76 goto done;
77 }
78
79
80
81
82
83
84 if (!local_err) {
85 error_setg(errp, "Secret id '%s' lookup failed: Unknown error",
86 secret_id);
87 rc = -1;
88 } else if (strncmp(error_get_pretty(local_err), "No secret with id", 17)) {
89 error_propagate(errp, local_err);
90 rc = -1;
91 } else {
92 error_free(local_err);
93 }
94
95 done:
96 g_free(secret_id);
97 if (!rc && !data) {
98 data = g_strdup("");
99 }
100
101 return data;
102}
103
104int xlnx_aes_k256_get_provided_i(Object *obj, const char *id_prop,
105 const char *given_default,
106 uint8_t key[32], Error **errp)
107{
108 static const char builtin_default[] =
109
110 "01234567" "89abcdef" "02468ace" "13579bdf"
111 "12345678" "9abcdef0" "2468ace0" "3579bdf1";
112
113 const char *xd;
114 char *data;
115 int rc;
116
117 assert(key != NULL);
118 assert(obj != NULL);
119 assert(id_prop != NULL);
120 assert(id_prop[0] != '\0');
121
122
123 if (!errp) {
124 errp = &error_abort;
125 }
126
127 data = xlnx_aes_k256_get_secret(obj, id_prop, errp);
128 if (!data) {
129 return -1;
130 }
131
132 xd = data;
133 if (!xd[0]) {
134 xd = given_default ? given_default : builtin_default;
135 }
136
137 rc = xlnx_aes_k256_xtob(xd, key, errp);
138 g_free(data);
139
140 return rc;
141}
142
143static uint32_t xlnx_calc_row_crc(uint32_t prev_crc, uint32_t data,
144 uint32_t addr)
145{
146
147 static const uint32_t crc_tab[128] = {
148 0x00000000, 0xe13b70f7, 0xc79a971f, 0x26a1e7e8,
149 0x8ad958cf, 0x6be22838, 0x4d43cfd0, 0xac78bf27,
150 0x105ec76f, 0xf165b798, 0xd7c45070, 0x36ff2087,
151 0x9a879fa0, 0x7bbcef57, 0x5d1d08bf, 0xbc267848,
152 0x20bd8ede, 0xc186fe29, 0xe72719c1, 0x061c6936,
153 0xaa64d611, 0x4b5fa6e6, 0x6dfe410e, 0x8cc531f9,
154 0x30e349b1, 0xd1d83946, 0xf779deae, 0x1642ae59,
155 0xba3a117e, 0x5b016189, 0x7da08661, 0x9c9bf696,
156 0x417b1dbc, 0xa0406d4b, 0x86e18aa3, 0x67dafa54,
157 0xcba24573, 0x2a993584, 0x0c38d26c, 0xed03a29b,
158 0x5125dad3, 0xb01eaa24, 0x96bf4dcc, 0x77843d3b,
159 0xdbfc821c, 0x3ac7f2eb, 0x1c661503, 0xfd5d65f4,
160 0x61c69362, 0x80fde395, 0xa65c047d, 0x4767748a,
161 0xeb1fcbad, 0x0a24bb5a, 0x2c855cb2, 0xcdbe2c45,
162 0x7198540d, 0x90a324fa, 0xb602c312, 0x5739b3e5,
163 0xfb410cc2, 0x1a7a7c35, 0x3cdb9bdd, 0xdde0eb2a,
164 0x82f63b78, 0x63cd4b8f, 0x456cac67, 0xa457dc90,
165 0x082f63b7, 0xe9141340, 0xcfb5f4a8, 0x2e8e845f,
166 0x92a8fc17, 0x73938ce0, 0x55326b08, 0xb4091bff,
167 0x1871a4d8, 0xf94ad42f, 0xdfeb33c7, 0x3ed04330,
168 0xa24bb5a6, 0x4370c551, 0x65d122b9, 0x84ea524e,
169 0x2892ed69, 0xc9a99d9e, 0xef087a76, 0x0e330a81,
170 0xb21572c9, 0x532e023e, 0x758fe5d6, 0x94b49521,
171 0x38cc2a06, 0xd9f75af1, 0xff56bd19, 0x1e6dcdee,
172 0xc38d26c4, 0x22b65633, 0x0417b1db, 0xe52cc12c,
173 0x49547e0b, 0xa86f0efc, 0x8ecee914, 0x6ff599e3,
174 0xd3d3e1ab, 0x32e8915c, 0x144976b4, 0xf5720643,
175 0x590ab964, 0xb831c993, 0x9e902e7b, 0x7fab5e8c,
176 0xe330a81a, 0x020bd8ed, 0x24aa3f05, 0xc5914ff2,
177 0x69e9f0d5, 0x88d28022, 0xae7367ca, 0x4f48173d,
178 0xf36e6f75, 0x12551f82, 0x34f4f86a, 0xd5cf889d,
179 0x79b737ba, 0x988c474d, 0xbe2da0a5, 0x5f16d052
180 };
181
182
183
184
185
186
187
188
189 uint32_t crc = prev_crc;
190 const unsigned rshf = 7;
191 const uint32_t im = (1 << rshf) - 1;
192 const uint32_t rm = (1 << (32 - rshf)) - 1;
193 const uint32_t i2 = (1 << 2) - 1;
194 const uint32_t r2 = (1 << 30) - 1;
195
196 unsigned j;
197 uint32_t i, r;
198 uint64_t w;
199
200 w = (uint64_t)(addr) << 32;
201 w |= data;
202
203
204 for (j = 0; j < 5; j++) {
205 r = rm & (crc >> rshf);
206 i = im & (crc ^ w);
207 crc = crc_tab[i] ^ r;
208
209 w >>= rshf;
210 }
211
212
213 r = r2 & (crc >> 2);
214 i = i2 & (crc ^ w);
215 crc = crc_tab[i << (rshf - 2)] ^ r;
216
217 return crc;
218}
219
220uint32_t xlnx_calc_crc(const uint32_t *data, unsigned data_length)
221{
222 uint32_t crc = 0;
223 unsigned i;
224
225 i = data_length;
226 while (i--) {
227 uint32_t addr = i + 1;
228
229 crc = xlnx_calc_row_crc(crc, data[i], addr);
230 }
231
232 return crc;
233}
234
235
236
237
238
239
240uint32_t xlnx_aes_k256_crc(const uint32_t *k256, unsigned zpad_cnt)
241{
242 uint32_t crc = 0;
243 unsigned k;
244
245
246
247
248
249 k = 8 + zpad_cnt;
250 while (k--) {
251 uint32_t data = k > 7 ? 0 : k256[k];
252 uint32_t addr = k + 1;
253
254 crc = xlnx_calc_row_crc(crc, data, addr);
255 }
256
257 return crc;
258}
259
260void xlnx_aes_k256_swap32_i(uint8_t dst[32], const uint8_t src[32])
261{
262
263
264
265
266
267
268
269
270
271
272 unsigned i;
273 const void *dp = dst, *sp = src;
274
275
276 if (dp != sp) {
277 const void *de = &dst[31];
278 const void *se = &src[31];
279
280 assert(de < sp || se < dp);
281 }
282
283 for (i = 0; i < 32; i += 4) {
284 uint32_t v;
285
286 v = ldl_be_p(&src[i]);
287 stl_he_p(&dst[i], v);
288 }
289}
290
291bool xlnx_aes_k256_is_zero_i(const uint8_t key[32])
292{
293 uint64_t q0, q1, q2, q3;
294
295 q0 = ldq_he_p(key);
296 q1 = ldq_he_p(key + 8);
297 q2 = ldq_he_p(key + 16);
298 q3 = ldq_he_p(key + 24);
299
300 return !(q0 | q1 | q2 | q3);
301}
302