xref: /qemu/tests/qtest/aspeed-hace-utils.c (revision a3e7f6d05d8bf38b0337fabc438d32c46948ccff)
1 /*
2  * QTest testcase for the ASPEED Hash and Crypto Engine
3  *
4  * SPDX-License-Identifier: GPL-2.0-or-later
5  * Copyright 2021 IBM Corp.
6  */
7 
8 #include "qemu/osdep.h"
9 #include "libqtest.h"
10 #include "qemu/bitops.h"
11 #include "aspeed-hace-utils.h"
12 
13 /*
14  * Test vector is the ascii "abc"
15  *
16  * Expected results were generated using command line utitiles:
17  *
18  *  echo -n -e 'abc' | dd of=/tmp/test
19  *  for hash in sha512sum sha256sum md5sum; do $hash /tmp/test; done
20  *
21  */
22 static const uint8_t test_vector[3] = {0x61, 0x62, 0x63};
23 
24 static const uint8_t test_result_sha512[64] = {
25     0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49,
26     0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
27     0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a,
28     0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
29     0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f,
30     0xa5, 0x4c, 0xa4, 0x9f};
31 
32 static const uint8_t test_result_sha256[32] = {
33     0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
34     0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
35     0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad};
36 
37 static const uint8_t test_result_md5[16] = {
38     0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d,
39     0x28, 0xe1, 0x7f, 0x72};
40 
41 /*
42  * The Scatter-Gather Test vector is the ascii "abc" "def" "ghi", broken
43  * into blocks of 3 characters as shown
44  *
45  * Expected results were generated using command line utitiles:
46  *
47  *  echo -n -e 'abcdefghijkl' | dd of=/tmp/test
48  *  for hash in sha512sum sha256sum; do $hash /tmp/test; done
49  *
50  */
51 static const uint8_t test_vector_sg1[6] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
52 static const uint8_t test_vector_sg2[3] = {0x67, 0x68, 0x69};
53 static const uint8_t test_vector_sg3[3] = {0x6a, 0x6b, 0x6c};
54 
55 static const uint8_t test_result_sg_sha512[64] = {
56     0x17, 0x80, 0x7c, 0x72, 0x8e, 0xe3, 0xba, 0x35, 0xe7, 0xcf, 0x7a, 0xf8,
57     0x23, 0x11, 0x6d, 0x26, 0xe4, 0x1e, 0x5d, 0x4d, 0x6c, 0x2f, 0xf1, 0xf3,
58     0x72, 0x0d, 0x3d, 0x96, 0xaa, 0xcb, 0x6f, 0x69, 0xde, 0x64, 0x2e, 0x63,
59     0xd5, 0xb7, 0x3f, 0xc3, 0x96, 0xc1, 0x2b, 0xe3, 0x8b, 0x2b, 0xd5, 0xd8,
60     0x84, 0x25, 0x7c, 0x32, 0xc8, 0xf6, 0xd0, 0x85, 0x4a, 0xe6, 0xb5, 0x40,
61     0xf8, 0x6d, 0xda, 0x2e};
62 
63 static const uint8_t test_result_sg_sha256[32] = {
64     0xd6, 0x82, 0xed, 0x4c, 0xa4, 0xd9, 0x89, 0xc1, 0x34, 0xec, 0x94, 0xf1,
65     0x55, 0x1e, 0x1e, 0xc5, 0x80, 0xdd, 0x6d, 0x5a, 0x6e, 0xcd, 0xe9, 0xf3,
66     0xd3, 0x5e, 0x6e, 0x4a, 0x71, 0x7f, 0xbd, 0xe4};
67 
68 /*
69  * The accumulative mode requires firmware to provide internal initial state
70  * and message padding (including length L at the end of padding).
71  *
72  * This test vector is a ascii text "abc" with padding message.
73  *
74  * Expected results were generated using command line utitiles:
75  *
76  *  echo -n -e 'abc' | dd of=/tmp/test
77  *  for hash in sha512sum sha256sum; do $hash /tmp/test; done
78  */
79 static const uint8_t test_vector_accum_512[128] = {
80     0x61, 0x62, 0x63, 0x80, 0x00, 0x00, 0x00, 0x00,
81     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
82     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
83     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
88     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
89     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
90     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
92     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
93     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18};
96 
97 static const uint8_t test_vector_accum_256[64] = {
98     0x61, 0x62, 0x63, 0x80, 0x00, 0x00, 0x00, 0x00,
99     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
103     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
104     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
105     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18};
106 
107 static const uint8_t test_result_accum_sha512[64] = {
108     0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49,
109     0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
110     0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a,
111     0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
112     0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f,
113     0xa5, 0x4c, 0xa4, 0x9f};
114 
115 static const uint8_t test_result_accum_sha256[32] = {
116     0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
117     0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
118     0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad};
119 
120 static void write_regs(QTestState *s, uint32_t base, uint32_t src,
121                        uint32_t length, uint32_t out, uint32_t method)
122 {
123         qtest_writel(s, base + HACE_HASH_SRC, src);
124         qtest_writel(s, base + HACE_HASH_DIGEST, out);
125         qtest_writel(s, base + HACE_HASH_DATA_LEN, length);
126         qtest_writel(s, base + HACE_HASH_CMD, HACE_SHA_BE_EN | method);
127 }
128 
129 void aspeed_test_md5(const char *machine, const uint32_t base,
130                      const uint32_t src_addr)
131 
132 {
133     QTestState *s = qtest_init(machine);
134 
135     uint32_t digest_addr = src_addr + 0x010000;
136     uint8_t digest[16] = {0};
137 
138     /* Check engine is idle, no busy or irq bits set */
139     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
140 
141     /* Write test vector into memory */
142     qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));
143 
144     write_regs(s, base, src_addr, sizeof(test_vector),
145                digest_addr, HACE_ALGO_MD5);
146 
147     /* Check hash IRQ status is asserted */
148     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
149 
150     /* Clear IRQ status and check status is deasserted */
151     qtest_writel(s, base + HACE_STS, 0x00000200);
152     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
153 
154     /* Read computed digest from memory */
155     qtest_memread(s, digest_addr, digest, sizeof(digest));
156 
157     /* Check result of computation */
158     g_assert_cmpmem(digest, sizeof(digest),
159                     test_result_md5, sizeof(digest));
160 
161     qtest_quit(s);
162 }
163 
164 void aspeed_test_sha256(const char *machine, const uint32_t base,
165                         const uint32_t src_addr)
166 {
167     QTestState *s = qtest_init(machine);
168 
169     const uint32_t digest_addr = src_addr + 0x10000;
170     uint8_t digest[32] = {0};
171 
172     /* Check engine is idle, no busy or irq bits set */
173     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
174 
175     /* Write test vector into memory */
176     qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));
177 
178     write_regs(s, base, src_addr, sizeof(test_vector), digest_addr,
179                HACE_ALGO_SHA256);
180 
181     /* Check hash IRQ status is asserted */
182     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
183 
184     /* Clear IRQ status and check status is deasserted */
185     qtest_writel(s, base + HACE_STS, 0x00000200);
186     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
187 
188     /* Read computed digest from memory */
189     qtest_memread(s, digest_addr, digest, sizeof(digest));
190 
191     /* Check result of computation */
192     g_assert_cmpmem(digest, sizeof(digest),
193                     test_result_sha256, sizeof(digest));
194 
195     qtest_quit(s);
196 }
197 
198 void aspeed_test_sha512(const char *machine, const uint32_t base,
199                         const uint32_t src_addr)
200 {
201     QTestState *s = qtest_init(machine);
202 
203     const uint32_t digest_addr = src_addr + 0x10000;
204     uint8_t digest[64] = {0};
205 
206     /* Check engine is idle, no busy or irq bits set */
207     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
208 
209     /* Write test vector into memory */
210     qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));
211 
212     write_regs(s, base, src_addr, sizeof(test_vector), digest_addr,
213                HACE_ALGO_SHA512);
214 
215     /* Check hash IRQ status is asserted */
216     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
217 
218     /* Clear IRQ status and check status is deasserted */
219     qtest_writel(s, base + HACE_STS, 0x00000200);
220     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
221 
222     /* Read computed digest from memory */
223     qtest_memread(s, digest_addr, digest, sizeof(digest));
224 
225     /* Check result of computation */
226     g_assert_cmpmem(digest, sizeof(digest),
227                     test_result_sha512, sizeof(digest));
228 
229     qtest_quit(s);
230 }
231 
232 void aspeed_test_sha256_sg(const char *machine, const uint32_t base,
233                            const uint32_t src_addr)
234 {
235     QTestState *s = qtest_init(machine);
236 
237     const uint32_t src_addr_1 = src_addr + 0x10000;
238     const uint32_t src_addr_2 = src_addr + 0x20000;
239     const uint32_t src_addr_3 = src_addr + 0x30000;
240     const uint32_t digest_addr = src_addr + 0x40000;
241     uint8_t digest[32] = {0};
242     struct AspeedSgList array[] = {
243         {  cpu_to_le32(sizeof(test_vector_sg1)),
244            cpu_to_le32(src_addr_1) },
245         {  cpu_to_le32(sizeof(test_vector_sg2)),
246            cpu_to_le32(src_addr_2) },
247         {  cpu_to_le32(sizeof(test_vector_sg3) | SG_LIST_LEN_LAST),
248            cpu_to_le32(src_addr_3) },
249     };
250 
251     /* Check engine is idle, no busy or irq bits set */
252     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
253 
254     /* Write test vector into memory */
255     qtest_memwrite(s, src_addr_1, test_vector_sg1, sizeof(test_vector_sg1));
256     qtest_memwrite(s, src_addr_2, test_vector_sg2, sizeof(test_vector_sg2));
257     qtest_memwrite(s, src_addr_3, test_vector_sg3, sizeof(test_vector_sg3));
258     qtest_memwrite(s, src_addr, array, sizeof(array));
259 
260     write_regs(s, base, src_addr,
261                (sizeof(test_vector_sg1)
262                 + sizeof(test_vector_sg2)
263                 + sizeof(test_vector_sg3)),
264                digest_addr, HACE_ALGO_SHA256 | HACE_SG_EN);
265 
266     /* Check hash IRQ status is asserted */
267     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
268 
269     /* Clear IRQ status and check status is deasserted */
270     qtest_writel(s, base + HACE_STS, 0x00000200);
271     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
272 
273     /* Read computed digest from memory */
274     qtest_memread(s, digest_addr, digest, sizeof(digest));
275 
276     /* Check result of computation */
277     g_assert_cmpmem(digest, sizeof(digest),
278                     test_result_sg_sha256, sizeof(digest));
279 
280     qtest_quit(s);
281 }
282 
283 void aspeed_test_sha512_sg(const char *machine, const uint32_t base,
284                            const uint32_t src_addr)
285 {
286     QTestState *s = qtest_init(machine);
287 
288     const uint32_t src_addr_1 = src_addr + 0x10000;
289     const uint32_t src_addr_2 = src_addr + 0x20000;
290     const uint32_t src_addr_3 = src_addr + 0x30000;
291     const uint32_t digest_addr = src_addr + 0x40000;
292     uint8_t digest[64] = {0};
293     struct AspeedSgList array[] = {
294         {  cpu_to_le32(sizeof(test_vector_sg1)),
295            cpu_to_le32(src_addr_1) },
296         {  cpu_to_le32(sizeof(test_vector_sg2)),
297            cpu_to_le32(src_addr_2) },
298         {  cpu_to_le32(sizeof(test_vector_sg3) | SG_LIST_LEN_LAST),
299            cpu_to_le32(src_addr_3) },
300     };
301 
302     /* Check engine is idle, no busy or irq bits set */
303     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
304 
305     /* Write test vector into memory */
306     qtest_memwrite(s, src_addr_1, test_vector_sg1, sizeof(test_vector_sg1));
307     qtest_memwrite(s, src_addr_2, test_vector_sg2, sizeof(test_vector_sg2));
308     qtest_memwrite(s, src_addr_3, test_vector_sg3, sizeof(test_vector_sg3));
309     qtest_memwrite(s, src_addr, array, sizeof(array));
310 
311     write_regs(s, base, src_addr,
312                (sizeof(test_vector_sg1)
313                 + sizeof(test_vector_sg2)
314                 + sizeof(test_vector_sg3)),
315                digest_addr, HACE_ALGO_SHA512 | HACE_SG_EN);
316 
317     /* Check hash IRQ status is asserted */
318     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
319 
320     /* Clear IRQ status and check status is deasserted */
321     qtest_writel(s, base + HACE_STS, 0x00000200);
322     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
323 
324     /* Read computed digest from memory */
325     qtest_memread(s, digest_addr, digest, sizeof(digest));
326 
327     /* Check result of computation */
328     g_assert_cmpmem(digest, sizeof(digest),
329                     test_result_sg_sha512, sizeof(digest));
330 
331     qtest_quit(s);
332 }
333 
334 void aspeed_test_sha256_accum(const char *machine, const uint32_t base,
335                               const uint32_t src_addr)
336 {
337     QTestState *s = qtest_init(machine);
338 
339     const uint32_t buffer_addr = src_addr + 0x10000;
340     const uint32_t digest_addr = src_addr + 0x40000;
341     uint8_t digest[32] = {0};
342     struct AspeedSgList array[] = {
343         {  cpu_to_le32(sizeof(test_vector_accum_256) | SG_LIST_LEN_LAST),
344            cpu_to_le32(buffer_addr) },
345     };
346 
347     /* Check engine is idle, no busy or irq bits set */
348     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
349 
350     /* Write test vector into memory */
351     qtest_memwrite(s, buffer_addr, test_vector_accum_256,
352                    sizeof(test_vector_accum_256));
353     qtest_memwrite(s, src_addr, array, sizeof(array));
354 
355     write_regs(s, base, src_addr, sizeof(test_vector_accum_256),
356                digest_addr, HACE_ALGO_SHA256 | HACE_SG_EN | HACE_ACCUM_EN);
357 
358     /* Check hash IRQ status is asserted */
359     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
360 
361     /* Clear IRQ status and check status is deasserted */
362     qtest_writel(s, base + HACE_STS, 0x00000200);
363     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
364 
365     /* Read computed digest from memory */
366     qtest_memread(s, digest_addr, digest, sizeof(digest));
367 
368     /* Check result of computation */
369     g_assert_cmpmem(digest, sizeof(digest),
370                     test_result_accum_sha256, sizeof(digest));
371 
372     qtest_quit(s);
373 }
374 
375 void aspeed_test_sha512_accum(const char *machine, const uint32_t base,
376                               const uint32_t src_addr)
377 {
378     QTestState *s = qtest_init(machine);
379 
380     const uint32_t buffer_addr = src_addr + 0x10000;
381     const uint32_t digest_addr = src_addr + 0x40000;
382     uint8_t digest[64] = {0};
383     struct AspeedSgList array[] = {
384         {  cpu_to_le32(sizeof(test_vector_accum_512) | SG_LIST_LEN_LAST),
385            cpu_to_le32(buffer_addr) },
386     };
387 
388     /* Check engine is idle, no busy or irq bits set */
389     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
390 
391     /* Write test vector into memory */
392     qtest_memwrite(s, buffer_addr, test_vector_accum_512,
393                    sizeof(test_vector_accum_512));
394     qtest_memwrite(s, src_addr, array, sizeof(array));
395 
396     write_regs(s, base, src_addr, sizeof(test_vector_accum_512),
397                digest_addr, HACE_ALGO_SHA512 | HACE_SG_EN | HACE_ACCUM_EN);
398 
399     /* Check hash IRQ status is asserted */
400     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);
401 
402     /* Clear IRQ status and check status is deasserted */
403     qtest_writel(s, base + HACE_STS, 0x00000200);
404     g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);
405 
406     /* Read computed digest from memory */
407     qtest_memread(s, digest_addr, digest, sizeof(digest));
408 
409     /* Check result of computation */
410     g_assert_cmpmem(digest, sizeof(digest),
411                     test_result_accum_sha512, sizeof(digest));
412 
413     qtest_quit(s);
414 }
415 
416 void aspeed_test_addresses(const char *machine, const uint32_t base,
417                            const struct AspeedMasks *expected)
418 {
419     QTestState *s = qtest_init(machine);
420 
421     /*
422      * Check command mode is zero, meaning engine is in direct access mode,
423      * as this affects the masking behavior of the HASH_SRC register.
424      */
425     g_assert_cmphex(qtest_readl(s, base + HACE_CMD), ==, 0);
426     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, 0);
427     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0);
428     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0);
429 
430 
431     /* Check that the address masking is correct */
432     qtest_writel(s, base + HACE_HASH_SRC, 0xffffffff);
433     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, expected->src);
434 
435     qtest_writel(s, base + HACE_HASH_DIGEST, 0xffffffff);
436     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==,
437                     expected->dest);
438 
439     qtest_writel(s, base + HACE_HASH_DATA_LEN, 0xffffffff);
440     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==,
441                     expected->len);
442 
443     /* Reset to zero */
444     qtest_writel(s, base + HACE_HASH_SRC, 0);
445     qtest_writel(s, base + HACE_HASH_DIGEST, 0);
446     qtest_writel(s, base + HACE_HASH_DATA_LEN, 0);
447 
448     /* Check that all bits are now zero */
449     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, 0);
450     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0);
451     g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0);
452 
453     qtest_quit(s);
454 }
455 
456