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