summaryrefslogblamecommitdiffstats
path: root/tests/qtest/aspeed_hace-test.c
blob: 09ee31545e415991631415e0f3df3d91a67772ea (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469




















































































































































































































































































































































































































































































                                                                                      
/*
 * QTest testcase for the ASPEED Hash and Crypto Engine
 *
 * SPDX-License-Identifier: GPL-2.0-or-later
 * Copyright 2021 IBM Corp.
 */

#include "qemu/osdep.h"

#include "libqos/libqtest.h"
#include "qemu-common.h"
#include "qemu/bitops.h"

#define HACE_CMD                 0x10
#define  HACE_SHA_BE_EN          BIT(3)
#define  HACE_MD5_LE_EN          BIT(2)
#define  HACE_ALGO_MD5           0
#define  HACE_ALGO_SHA1          BIT(5)
#define  HACE_ALGO_SHA224        BIT(6)
#define  HACE_ALGO_SHA256        (BIT(4) | BIT(6))
#define  HACE_ALGO_SHA512        (BIT(5) | BIT(6))
#define  HACE_ALGO_SHA384        (BIT(5) | BIT(6) | BIT(10))
#define  HACE_SG_EN              BIT(18)

#define HACE_STS                 0x1c
#define  HACE_RSA_ISR            BIT(13)
#define  HACE_CRYPTO_ISR         BIT(12)
#define  HACE_HASH_ISR           BIT(9)
#define  HACE_RSA_BUSY           BIT(2)
#define  HACE_CRYPTO_BUSY        BIT(1)
#define  HACE_HASH_BUSY          BIT(0)
#define HACE_HASH_SRC            0x20
#define HACE_HASH_DIGEST         0x24
#define HACE_HASH_KEY_BUFF       0x28
#define HACE_HASH_DATA_LEN       0x2c
#define HACE_HASH_CMD            0x30
/* Scatter-Gather Hash */
#define SG_LIST_LEN_LAST         BIT(31)
struct AspeedSgList {
        uint32_t len;
        uint32_t addr;
} __attribute__ ((__packed__));

/*
 * Test vector is the ascii "abc"
 *
 * Expected results were generated using command line utitiles:
 *
 *  echo -n -e 'abc' | dd of=/tmp/test
 *  for hash in sha512sum sha256sum md5sum; do $hash /tmp/test; done
 *
 */
static const uint8_t test_vector[] = {0x61, 0x62, 0x63};

static const uint8_t test_result_sha512[] = {
    0xdd, 0xaf, 0x35, 0xa1, 0x93, 0x61, 0x7a, 0xba, 0xcc, 0x41, 0x73, 0x49,
    0xae, 0x20, 0x41, 0x31, 0x12, 0xe6, 0xfa, 0x4e, 0x89, 0xa9, 0x7e, 0xa2,
    0x0a, 0x9e, 0xee, 0xe6, 0x4b, 0x55, 0xd3, 0x9a, 0x21, 0x92, 0x99, 0x2a,
    0x27, 0x4f, 0xc1, 0xa8, 0x36, 0xba, 0x3c, 0x23, 0xa3, 0xfe, 0xeb, 0xbd,
    0x45, 0x4d, 0x44, 0x23, 0x64, 0x3c, 0xe8, 0x0e, 0x2a, 0x9a, 0xc9, 0x4f,
    0xa5, 0x4c, 0xa4, 0x9f};

static const uint8_t test_result_sha256[] = {
    0xba, 0x78, 0x16, 0xbf, 0x8f, 0x01, 0xcf, 0xea, 0x41, 0x41, 0x40, 0xde,
    0x5d, 0xae, 0x22, 0x23, 0xb0, 0x03, 0x61, 0xa3, 0x96, 0x17, 0x7a, 0x9c,
    0xb4, 0x10, 0xff, 0x61, 0xf2, 0x00, 0x15, 0xad};

static const uint8_t test_result_md5[] = {
    0x90, 0x01, 0x50, 0x98, 0x3c, 0xd2, 0x4f, 0xb0, 0xd6, 0x96, 0x3f, 0x7d,
    0x28, 0xe1, 0x7f, 0x72};

/*
 * The Scatter-Gather Test vector is the ascii "abc" "def" "ghi", broken
 * into blocks of 3 characters as shown
 *
 * Expected results were generated using command line utitiles:
 *
 *  echo -n -e 'abcdefghijkl' | dd of=/tmp/test
 *  for hash in sha512sum sha256sum; do $hash /tmp/test; done
 *
 */
static const uint8_t test_vector_sg1[] = {0x61, 0x62, 0x63, 0x64, 0x65, 0x66};
static const uint8_t test_vector_sg2[] = {0x67, 0x68, 0x69};
static const uint8_t test_vector_sg3[] = {0x6a, 0x6b, 0x6c};

static const uint8_t test_result_sg_sha512[] = {
    0x17, 0x80, 0x7c, 0x72, 0x8e, 0xe3, 0xba, 0x35, 0xe7, 0xcf, 0x7a, 0xf8,
    0x23, 0x11, 0x6d, 0x26, 0xe4, 0x1e, 0x5d, 0x4d, 0x6c, 0x2f, 0xf1, 0xf3,
    0x72, 0x0d, 0x3d, 0x96, 0xaa, 0xcb, 0x6f, 0x69, 0xde, 0x64, 0x2e, 0x63,
    0xd5, 0xb7, 0x3f, 0xc3, 0x96, 0xc1, 0x2b, 0xe3, 0x8b, 0x2b, 0xd5, 0xd8,
    0x84, 0x25, 0x7c, 0x32, 0xc8, 0xf6, 0xd0, 0x85, 0x4a, 0xe6, 0xb5, 0x40,
    0xf8, 0x6d, 0xda, 0x2e};

static const uint8_t test_result_sg_sha256[] = {
    0xd6, 0x82, 0xed, 0x4c, 0xa4, 0xd9, 0x89, 0xc1, 0x34, 0xec, 0x94, 0xf1,
    0x55, 0x1e, 0x1e, 0xc5, 0x80, 0xdd, 0x6d, 0x5a, 0x6e, 0xcd, 0xe9, 0xf3,
    0xd3, 0x5e, 0x6e, 0x4a, 0x71, 0x7f, 0xbd, 0xe4};


static void write_regs(QTestState *s, uint32_t base, uint32_t src,
                       uint32_t length, uint32_t out, uint32_t method)
{
        qtest_writel(s, base + HACE_HASH_SRC, src);
        qtest_writel(s, base + HACE_HASH_DIGEST, out);
        qtest_writel(s, base + HACE_HASH_DATA_LEN, length);
        qtest_writel(s, base + HACE_HASH_CMD, HACE_SHA_BE_EN | method);
}

static void test_md5(const char *machine, const uint32_t base,
                     const uint32_t src_addr)

{
    QTestState *s = qtest_init(machine);

    uint32_t digest_addr = src_addr + 0x01000000;
    uint8_t digest[16] = {0};

    /* Check engine is idle, no busy or irq bits set */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Write test vector into memory */
    qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));

    write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_MD5);

    /* Check hash IRQ status is asserted */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);

    /* Clear IRQ status and check status is deasserted */
    qtest_writel(s, base + HACE_STS, 0x00000200);
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Read computed digest from memory */
    qtest_memread(s, digest_addr, digest, sizeof(digest));

    /* Check result of computation */
    g_assert_cmpmem(digest, sizeof(digest),
                    test_result_md5, sizeof(digest));

    qtest_quit(s);
}

static void test_sha256(const char *machine, const uint32_t base,
                        const uint32_t src_addr)
{
    QTestState *s = qtest_init(machine);

    const uint32_t digest_addr = src_addr + 0x1000000;
    uint8_t digest[32] = {0};

    /* Check engine is idle, no busy or irq bits set */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Write test vector into memory */
    qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));

    write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_SHA256);

    /* Check hash IRQ status is asserted */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);

    /* Clear IRQ status and check status is deasserted */
    qtest_writel(s, base + HACE_STS, 0x00000200);
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Read computed digest from memory */
    qtest_memread(s, digest_addr, digest, sizeof(digest));

    /* Check result of computation */
    g_assert_cmpmem(digest, sizeof(digest),
                    test_result_sha256, sizeof(digest));

    qtest_quit(s);
}

static void test_sha512(const char *machine, const uint32_t base,
                        const uint32_t src_addr)
{
    QTestState *s = qtest_init(machine);

    const uint32_t digest_addr = src_addr + 0x1000000;
    uint8_t digest[64] = {0};

    /* Check engine is idle, no busy or irq bits set */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Write test vector into memory */
    qtest_memwrite(s, src_addr, test_vector, sizeof(test_vector));

    write_regs(s, base, src_addr, sizeof(test_vector), digest_addr, HACE_ALGO_SHA512);

    /* Check hash IRQ status is asserted */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);

    /* Clear IRQ status and check status is deasserted */
    qtest_writel(s, base + HACE_STS, 0x00000200);
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Read computed digest from memory */
    qtest_memread(s, digest_addr, digest, sizeof(digest));

    /* Check result of computation */
    g_assert_cmpmem(digest, sizeof(digest),
                    test_result_sha512, sizeof(digest));

    qtest_quit(s);
}

static void test_sha256_sg(const char *machine, const uint32_t base,
                        const uint32_t src_addr)
{
    QTestState *s = qtest_init(machine);

    const uint32_t src_addr_1 = src_addr + 0x1000000;
    const uint32_t src_addr_2 = src_addr + 0x2000000;
    const uint32_t src_addr_3 = src_addr + 0x3000000;
    const uint32_t digest_addr = src_addr + 0x4000000;
    uint8_t digest[32] = {0};
    struct AspeedSgList array[] = {
        {  cpu_to_le32(sizeof(test_vector_sg1)),
           cpu_to_le32(src_addr_1) },
        {  cpu_to_le32(sizeof(test_vector_sg2)),
           cpu_to_le32(src_addr_2) },
        {  cpu_to_le32(sizeof(test_vector_sg3) | SG_LIST_LEN_LAST),
           cpu_to_le32(src_addr_3) },
    };

    /* Check engine is idle, no busy or irq bits set */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Write test vector into memory */
    qtest_memwrite(s, src_addr_1, test_vector_sg1, sizeof(test_vector_sg1));
    qtest_memwrite(s, src_addr_2, test_vector_sg2, sizeof(test_vector_sg2));
    qtest_memwrite(s, src_addr_3, test_vector_sg3, sizeof(test_vector_sg3));
    qtest_memwrite(s, src_addr, array, sizeof(array));

    write_regs(s, base, src_addr,
               (sizeof(test_vector_sg1)
                + sizeof(test_vector_sg2)
                + sizeof(test_vector_sg3)),
               digest_addr, HACE_ALGO_SHA256 | HACE_SG_EN);

    /* Check hash IRQ status is asserted */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);

    /* Clear IRQ status and check status is deasserted */
    qtest_writel(s, base + HACE_STS, 0x00000200);
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Read computed digest from memory */
    qtest_memread(s, digest_addr, digest, sizeof(digest));

    /* Check result of computation */
    g_assert_cmpmem(digest, sizeof(digest),
                    test_result_sg_sha256, sizeof(digest));

    qtest_quit(s);
}

static void test_sha512_sg(const char *machine, const uint32_t base,
                        const uint32_t src_addr)
{
    QTestState *s = qtest_init(machine);

    const uint32_t src_addr_1 = src_addr + 0x1000000;
    const uint32_t src_addr_2 = src_addr + 0x2000000;
    const uint32_t src_addr_3 = src_addr + 0x3000000;
    const uint32_t digest_addr = src_addr + 0x4000000;
    uint8_t digest[64] = {0};
    struct AspeedSgList array[] = {
        {  cpu_to_le32(sizeof(test_vector_sg1)),
           cpu_to_le32(src_addr_1) },
        {  cpu_to_le32(sizeof(test_vector_sg2)),
           cpu_to_le32(src_addr_2) },
        {  cpu_to_le32(sizeof(test_vector_sg3) | SG_LIST_LEN_LAST),
           cpu_to_le32(src_addr_3) },
    };

    /* Check engine is idle, no busy or irq bits set */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Write test vector into memory */
    qtest_memwrite(s, src_addr_1, test_vector_sg1, sizeof(test_vector_sg1));
    qtest_memwrite(s, src_addr_2, test_vector_sg2, sizeof(test_vector_sg2));
    qtest_memwrite(s, src_addr_3, test_vector_sg3, sizeof(test_vector_sg3));
    qtest_memwrite(s, src_addr, array, sizeof(array));

    write_regs(s, base, src_addr,
               (sizeof(test_vector_sg1)
                + sizeof(test_vector_sg2)
                + sizeof(test_vector_sg3)),
               digest_addr, HACE_ALGO_SHA512 | HACE_SG_EN);

    /* Check hash IRQ status is asserted */
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0x00000200);

    /* Clear IRQ status and check status is deasserted */
    qtest_writel(s, base + HACE_STS, 0x00000200);
    g_assert_cmphex(qtest_readl(s, base + HACE_STS), ==, 0);

    /* Read computed digest from memory */
    qtest_memread(s, digest_addr, digest, sizeof(digest));

    /* Check result of computation */
    g_assert_cmpmem(digest, sizeof(digest),
                    test_result_sg_sha512, sizeof(digest));

    qtest_quit(s);
}

struct masks {
    uint32_t src;
    uint32_t dest;
    uint32_t len;
};

static const struct masks ast2600_masks = {
    .src  = 0x7fffffff,
    .dest = 0x7ffffff8,
    .len  = 0x0fffffff,
};

static const struct masks ast2500_masks = {
    .src  = 0x3fffffff,
    .dest = 0x3ffffff8,
    .len  = 0x0fffffff,
};

static const struct masks ast2400_masks = {
    .src  = 0x0fffffff,
    .dest = 0x0ffffff8,
    .len  = 0x0fffffff,
};

static void test_addresses(const char *machine, const uint32_t base,
                           const struct masks *expected)
{
    QTestState *s = qtest_init(machine);

    /*
     * Check command mode is zero, meaning engine is in direct access mode,
     * as this affects the masking behavior of the HASH_SRC register.
     */
    g_assert_cmphex(qtest_readl(s, base + HACE_CMD), ==, 0);
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, 0);
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0);
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0);


    /* Check that the address masking is correct */
    qtest_writel(s, base + HACE_HASH_SRC, 0xffffffff);
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, expected->src);

    qtest_writel(s, base + HACE_HASH_DIGEST, 0xffffffff);
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, expected->dest);

    qtest_writel(s, base + HACE_HASH_DATA_LEN, 0xffffffff);
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, expected->len);

    /* Reset to zero */
    qtest_writel(s, base + HACE_HASH_SRC, 0);
    qtest_writel(s, base + HACE_HASH_DIGEST, 0);
    qtest_writel(s, base + HACE_HASH_DATA_LEN, 0);

    /* Check that all bits are now zero */
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_SRC), ==, 0);
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DIGEST), ==, 0);
    g_assert_cmphex(qtest_readl(s, base + HACE_HASH_DATA_LEN), ==, 0);

    qtest_quit(s);
}

/* ast2600 */
static void test_md5_ast2600(void)
{
    test_md5("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
}

static void test_sha256_ast2600(void)
{
    test_sha256("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
}

static void test_sha256_sg_ast2600(void)
{
    test_sha256_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
}

static void test_sha512_ast2600(void)
{
    test_sha512("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
}

static void test_sha512_sg_ast2600(void)
{
    test_sha512_sg("-machine ast2600-evb", 0x1e6d0000, 0x80000000);
}

static void test_addresses_ast2600(void)
{
    test_addresses("-machine ast2600-evb", 0x1e6d0000, &ast2600_masks);
}

/* ast2500 */
static void test_md5_ast2500(void)
{
    test_md5("-machine ast2500-evb", 0x1e6e3000, 0x80000000);
}

static void test_sha256_ast2500(void)
{
    test_sha256("-machine ast2500-evb", 0x1e6e3000, 0x80000000);
}

static void test_sha512_ast2500(void)
{
    test_sha512("-machine ast2500-evb", 0x1e6e3000, 0x80000000);
}

static void test_addresses_ast2500(void)
{
    test_addresses("-machine ast2500-evb", 0x1e6e3000, &ast2500_masks);
}

/* ast2400 */
static void test_md5_ast2400(void)
{
    test_md5("-machine palmetto-bmc", 0x1e6e3000, 0x40000000);
}

static void test_sha256_ast2400(void)
{
    test_sha256("-machine palmetto-bmc", 0x1e6e3000, 0x40000000);
}

static void test_sha512_ast2400(void)
{
    test_sha512("-machine palmetto-bmc", 0x1e6e3000, 0x40000000);
}

static void test_addresses_ast2400(void)
{
    test_addresses("-machine palmetto-bmc", 0x1e6e3000, &ast2400_masks);
}

int main(int argc, char **argv)
{
    g_test_init(&argc, &argv, NULL);

    qtest_add_func("ast2600/hace/addresses", test_addresses_ast2600);
    qtest_add_func("ast2600/hace/sha512", test_sha512_ast2600);
    qtest_add_func("ast2600/hace/sha256", test_sha256_ast2600);
    qtest_add_func("ast2600/hace/md5", test_md5_ast2600);

    qtest_add_func("ast2600/hace/sha512_sg", test_sha512_sg_ast2600);
    qtest_add_func("ast2600/hace/sha256_sg", test_sha256_sg_ast2600);

    qtest_add_func("ast2500/hace/addresses", test_addresses_ast2500);
    qtest_add_func("ast2500/hace/sha512", test_sha512_ast2500);
    qtest_add_func("ast2500/hace/sha256", test_sha256_ast2500);
    qtest_add_func("ast2500/hace/md5", test_md5_ast2500);

    qtest_add_func("ast2400/hace/addresses", test_addresses_ast2400);
    qtest_add_func("ast2400/hace/sha512", test_sha512_ast2400);
    qtest_add_func("ast2400/hace/sha256", test_sha256_ast2400);
    qtest_add_func("ast2400/hace/md5", test_md5_ast2400);

    return g_test_run();
}