Cover the AST2700 crypto engine, which drives 64-bit scatter-gather DMA and adds AES-GCM on top of the ECB/CBC/CTR modes shared with the AST2600. Add AES-128 and AES-256 GCM known-answer vectors (GCM specification / NIST SP 800-38D, no associated data) and a dedicated GCM runner that programs the tag buffer and reads the tag back, checking it after both encryption and decryption. Register the AST2700 with all four modes.
Signed-off-by: Jamin Lin <[email protected]> --- tests/qtest/aspeed-hace-utils.h | 1 + tests/qtest/aspeed-hace-utils.c | 159 +++++++++++++++++++++++++++++++- tests/qtest/ast2700-hace-test.c | 9 ++ 3 files changed, 168 insertions(+), 1 deletion(-) diff --git a/tests/qtest/aspeed-hace-utils.h b/tests/qtest/aspeed-hace-utils.h index 82b0b3f93d..a5601a3d65 100644 --- a/tests/qtest/aspeed-hace-utils.h +++ b/tests/qtest/aspeed-hace-utils.h @@ -86,6 +86,7 @@ enum { CRYPT_MODE_ECB = 1 << 0, CRYPT_MODE_CBC = 1 << 1, CRYPT_MODE_CTR = 1 << 2, + CRYPT_MODE_GCM = 1 << 3, }; /* diff --git a/tests/qtest/aspeed-hace-utils.c b/tests/qtest/aspeed-hace-utils.c index 0b91a4e61a..b421221c79 100644 --- a/tests/qtest/aspeed-hace-utils.c +++ b/tests/qtest/aspeed-hace-utils.c @@ -653,6 +653,8 @@ void aspeed_test_addresses(const char *machine, const uint32_t base, #define HACE_CRYPTO_CONTEXT 0x08 #define HACE_CRYPTO_DATA_LEN 0x0c #define HACE_CRYPTO_CMD 0x10 +#define HACE_CRYPTO_GCM_ADD_LEN 0x14 +#define HACE_CRYPTO_GCM_TAG 0x18 /* Crypto command bits */ #define HACE_CMD_ENCRYPT BIT(7) @@ -665,7 +667,9 @@ void aspeed_test_addresses(const char *machine, const uint32_t base, #define HACE_CMD_ECB (0x0 << 4) #define HACE_CMD_CBC (0x1 << 4) #define HACE_CMD_CTR (0x4 << 4) +#define HACE_CMD_GCM (0x5 << 4) #define HACE_CMD_AES128 (0x0 << 2) +#define HACE_CMD_AES256 (0x2 << 2) /* Context buffer layout: IV (DES at +8), key at +0x10 */ #define HACE_CTX_KEY_OFFSET 0x10 @@ -793,11 +797,66 @@ static const uint8_t tdes_ctr_ctext[8] = { static const uint8_t tdes_ctr_ivout[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +/* + * aes_gcm_tv_template[2] (AES-128) and [9] (AES-256), from the McGrew & Viega + * GCM spec (also NIST SP 800-38D), no AAD. Both cases share this plaintext/IV. + */ +static const uint8_t aes_gcm_ptext[64] = { + 0xd9, 0x31, 0x32, 0x25, 0xf8, 0x84, 0x06, 0xe5, + 0xa5, 0x59, 0x09, 0xc5, 0xaf, 0xf5, 0x26, 0x9a, + 0x86, 0xa7, 0xa9, 0x53, 0x15, 0x34, 0xf7, 0xda, + 0x2e, 0x4c, 0x30, 0x3d, 0x8a, 0x31, 0x8a, 0x72, + 0x1c, 0x3c, 0x0c, 0x95, 0x95, 0x68, 0x09, 0x53, + 0x2f, 0xcf, 0x0e, 0x24, 0x49, 0xa6, 0xb5, 0x25, + 0xb1, 0x6a, 0xed, 0xf5, 0xaa, 0x0d, 0xe6, 0x57, + 0xba, 0x63, 0x7b, 0x39, 0x1a, 0xaf, 0xd2, 0x55 }; +static const uint8_t aes_gcm_iv[12] = { + 0xca, 0xfe, 0xba, 0xbe, 0xfa, 0xce, 0xdb, 0xad, + 0xde, 0xca, 0xf8, 0x88 }; + +/* aes_gcm_tv_template[2] (AES-128) */ +static const uint8_t aes128_gcm_key[16] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }; +static const uint8_t aes128_gcm_ctext[64] = { + 0x42, 0x83, 0x1e, 0xc2, 0x21, 0x77, 0x74, 0x24, + 0x4b, 0x72, 0x21, 0xb7, 0x84, 0xd0, 0xd4, 0x9c, + 0xe3, 0xaa, 0x21, 0x2f, 0x2c, 0x02, 0xa4, 0xe0, + 0x35, 0xc1, 0x7e, 0x23, 0x29, 0xac, 0xa1, 0x2e, + 0x21, 0xd5, 0x14, 0xb2, 0x54, 0x66, 0x93, 0x1c, + 0x7d, 0x8f, 0x6a, 0x5a, 0xac, 0x84, 0xaa, 0x05, + 0x1b, 0xa3, 0x0b, 0x39, 0x6a, 0x0a, 0xac, 0x97, + 0x3d, 0x58, 0xe0, 0x91, 0x47, 0x3f, 0x59, 0x85 }; +static const uint8_t aes128_gcm_tag[16] = { + 0x4d, 0x5c, 0x2a, 0xf3, 0x27, 0xcd, 0x64, 0xa6, + 0x2c, 0xf3, 0x5a, 0xbd, 0x2b, 0xa6, 0xfa, 0xb4 }; + +/* aes_gcm_tv_template[9] (AES-256) */ +static const uint8_t aes256_gcm_key[32] = { + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08, + 0xfe, 0xff, 0xe9, 0x92, 0x86, 0x65, 0x73, 0x1c, + 0x6d, 0x6a, 0x8f, 0x94, 0x67, 0x30, 0x83, 0x08 }; +static const uint8_t aes256_gcm_ctext[64] = { + 0x52, 0x2d, 0xc1, 0xf0, 0x99, 0x56, 0x7d, 0x07, + 0xf4, 0x7f, 0x37, 0xa3, 0x2a, 0x84, 0x42, 0x7d, + 0x64, 0x3a, 0x8c, 0xdc, 0xbf, 0xe5, 0xc0, 0xc9, + 0x75, 0x98, 0xa2, 0xbd, 0x25, 0x55, 0xd1, 0xaa, + 0x8c, 0xb0, 0x8e, 0x48, 0x59, 0x0d, 0xbb, 0x3d, + 0xa7, 0xb0, 0x8b, 0x10, 0x56, 0x82, 0x88, 0x38, + 0xc5, 0xf6, 0x1e, 0x63, 0x93, 0xba, 0x7a, 0x0a, + 0xbc, 0xc9, 0xf6, 0x62, 0x89, 0x80, 0x15, 0xad }; +static const uint8_t aes256_gcm_tag[16] = { + 0xb0, 0x94, 0xda, 0xc5, 0xd9, 0x34, 0x71, 0xbd, + 0xec, 0x1a, 0x50, 0x22, 0x70, 0xe3, 0xcc, 0x6c }; + typedef struct CryptTest { const uint8_t *ptext; const uint8_t *ctext; /* expected context IV after encrypt, or NULL */ const uint8_t *iv_out; + /* expected GCM authentication tag, or NULL for non-AEAD modes */ + const uint8_t *tag; const uint8_t *key; const uint8_t *iv; const char *name; @@ -805,6 +864,7 @@ typedef struct CryptTest { uint32_t cmd; size_t keylen; size_t ivlen; + size_t taglen; size_t len; } CryptTest; @@ -906,6 +966,32 @@ static const CryptTest crypt_tests[] = { .iv_out = tdes_ctr_ivout, .len = sizeof(tdes_ctr_ptext), }, + { + .name = "aes128-gcm", + .cmd = HACE_CMD_AES128 | HACE_CMD_GCM, + .key = aes128_gcm_key, + .keylen = sizeof(aes128_gcm_key), + .iv = aes_gcm_iv, + .ivlen = sizeof(aes_gcm_iv), + .ptext = aes_gcm_ptext, + .ctext = aes128_gcm_ctext, + .tag = aes128_gcm_tag, + .taglen = sizeof(aes128_gcm_tag), + .len = sizeof(aes_gcm_ptext), + }, + { + .name = "aes256-gcm", + .cmd = HACE_CMD_AES256 | HACE_CMD_GCM, + .key = aes256_gcm_key, + .keylen = sizeof(aes256_gcm_key), + .iv = aes_gcm_iv, + .ivlen = sizeof(aes_gcm_iv), + .ptext = aes_gcm_ptext, + .ctext = aes256_gcm_ctext, + .tag = aes256_gcm_tag, + .taglen = sizeof(aes256_gcm_tag), + .len = sizeof(aes_gcm_ptext), + }, }; /* DRAM offsets for the crypto test source, destination and context buffers. */ @@ -923,6 +1009,8 @@ static const CryptTest crypt_tests[] = { */ #define CRYPT_SG_FRAGS 3 #define CRYPT_SG_FRAG_STRIDE 0x1000 +/* DRAM offset for the AES-GCM authentication tag write buffer. */ +#define CRYPT_OFF_TAG 0x60000 /* Describes one registered crypto test (qtest_add_data_func() data pointer). */ typedef struct AspeedCryptoTest { @@ -943,6 +1031,8 @@ static uint32_t crypt_mode_flag(uint32_t cmd) return CRYPT_MODE_CBC; case HACE_CMD_CTR: return CRYPT_MODE_CTR; + case HACE_CMD_GCM: + return CRYPT_MODE_GCM; default: return 0; } @@ -1088,6 +1178,47 @@ static void crypt_run_sg(QTestState *s, uint32_t base, uint64_t dram, crypt_gather_sg(s, dram, CRYPT_OFF_DST, out, t->len); } +/* + * Run one AES-GCM operation in scatter-gather mode: like crypt_run_sg() but + * also program the tag write buffer (HACE18) with no associated data, and read + * the authentication tag back into @out_tag. + */ +static void crypt_run_gcm(QTestState *s, uint32_t base, uint64_t dram, + const CryptTest *t, bool encrypt, uint8_t *out, + uint8_t *out_tag) +{ + const uint8_t *in = encrypt ? t->ptext : t->ctext; + uint64_t src_sg = dram + CRYPT_OFF_SRC_SG; + uint64_t dst_sg = dram + CRYPT_OFF_DST_SG; + uint64_t ctx = dram + CRYPT_OFF_CTX; + uint32_t cmd = t->cmd | HACE_CMD_ISR_EN | HACE_CMD_SRC_SG_CTRL | + HACE_CMD_DST_SG_CTRL; + + if (encrypt) { + cmd |= HACE_CMD_ENCRYPT; + } + + crypt_write_ctx(s, ctx, t); + crypt_make_sg(s, dram, CRYPT_OFF_SRC, src_sg, in, t->len); + crypt_make_sg(s, dram, CRYPT_OFF_DST, dst_sg, NULL, t->len); + + qtest_writel(s, base + HACE_CRYPTO_SRC, (uint32_t)src_sg); + qtest_writel(s, base + HACE_CRYPTO_DEST, (uint32_t)dst_sg); + qtest_writel(s, base + HACE_CRYPTO_CONTEXT, (uint32_t)ctx); + qtest_writel(s, base + HACE_CRYPTO_DATA_LEN, t->len); + qtest_writel(s, base + HACE_CRYPTO_GCM_ADD_LEN, 0); + qtest_writel(s, base + HACE_CRYPTO_GCM_TAG, + (uint32_t)(dram + CRYPT_OFF_TAG)); + qtest_writel(s, base + HACE_CRYPTO_CMD, cmd); + + g_assert_cmphex(qtest_readl(s, base + HACE_STS) & HACE_CRYPTO_ISR, ==, + HACE_CRYPTO_ISR); + qtest_writel(s, base + HACE_STS, HACE_CRYPTO_ISR); + + crypt_gather_sg(s, dram, CRYPT_OFF_DST, out, t->len); + qtest_memread(s, dram + CRYPT_OFF_TAG, out_tag, t->taglen); +} + static void aspeed_test_crypto(const void *data) { const AspeedCryptoTest *c = data; @@ -1124,6 +1255,29 @@ static void aspeed_test_crypto(const void *data) qtest_quit(s); } +static void aspeed_test_crypto_gcm(const void *data) +{ + const AspeedCryptoTest *c = data; + const CryptTest *t = &crypt_tests[c->index]; + QTestState *s = qtest_init(c->machine); + uint8_t out[64]; + uint8_t tag[16]; + + g_assert_cmpuint(t->len, <=, sizeof(out)); + + /* Encrypt: ptext -> ctext, then check the authentication tag. */ + crypt_run_gcm(s, c->base, c->dram, t, true, out, tag); + g_assert_cmpmem(out, t->len, t->ctext, t->len); + g_assert_cmpmem(tag, t->taglen, t->tag, t->taglen); + + /* Decrypt: ctext -> ptext, the recomputed tag must match. */ + crypt_run_gcm(s, c->base, c->dram, t, false, out, tag); + g_assert_cmpmem(out, t->len, t->ptext, t->len); + g_assert_cmpmem(tag, t->taglen, t->tag, t->taglen); + + qtest_quit(s); +} + void aspeed_add_crypto_tests(const char *prefix, const char *machine, uint32_t base, uint64_t dram, uint32_t modes, bool sg) @@ -1131,6 +1285,7 @@ void aspeed_add_crypto_tests(const char *prefix, const char *machine, int i; for (i = 0; i < ARRAY_SIZE(crypt_tests); i++) { + bool is_gcm = crypt_mode_flag(crypt_tests[i].cmd) == CRYPT_MODE_GCM; g_autofree char *path = NULL; AspeedCryptoTest *t; @@ -1146,7 +1301,9 @@ void aspeed_add_crypto_tests(const char *prefix, const char *machine, t->dram = dram; t->index = i; t->sg = sg; - qtest_add_data_func_full(path, t, aspeed_test_crypto, g_free); + qtest_add_data_func_full(path, t, + is_gcm ? aspeed_test_crypto_gcm : + aspeed_test_crypto, g_free); } } diff --git a/tests/qtest/ast2700-hace-test.c b/tests/qtest/ast2700-hace-test.c index 508a34dd6c..3f0217d635 100644 --- a/tests/qtest/ast2700-hace-test.c +++ b/tests/qtest/ast2700-hace-test.c @@ -94,5 +94,14 @@ int main(int argc, char **argv) qtest_add_func("ast2700/hace/sha384_accum", test_sha384_accum_ast2700); qtest_add_func("ast2700/hace/sha256_accum", test_sha256_accum_ast2700); + /* + * The AST2700 crypto engine uses scatter-gather with 64-bit DMA and adds + * AES-GCM on top of the ECB/CBC/CTR modes shared with the AST2600. + */ + aspeed_add_crypto_tests("ast2700", "-machine ast2700-evb", 0x12070000, + 0x400000000, + CRYPT_MODE_ECB | CRYPT_MODE_CBC | CRYPT_MODE_CTR | + CRYPT_MODE_GCM, true); + return g_test_run(); } -- 2.43.0
