From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id DB621A0503; Fri, 20 May 2022 18:09:59 +0200 (CEST) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 85E8C40222; Fri, 20 May 2022 18:09:59 +0200 (CEST) Received: from mga09.intel.com (mga09.intel.com [134.134.136.24]) by mails.dpdk.org (Postfix) with ESMTP id 5E00B40156 for ; Fri, 20 May 2022 18:09:57 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1653062997; x=1684598997; h=from:to:cc:subject:date:message-id:mime-version: content-transfer-encoding; bh=wKYo17j1Vz6dDxxng1V8dT6TjYfitjfKTYX5syCcH9c=; b=l2boxdAfv6g8tzzdhHia8kLDMwWOaSYLv6nYXpYzxe0Z94gaOY/Vos+G lht7tnlp5G8tRPRYopyZAJnne3mV+iaOZ4+weQHunYyVp8ro/u0bOv681 68OjZ1gljpXw66ACpeFvFmgYaDNLWGW6E+PY5ygYSn+D7JDJQfh7mn0vx zGV0Z2lUaEeLPeXsVJ01khl0G9AKZZGRrVK3+Jw98BYKRAXkpGltfd98T 39Wx7bujOoJAXzQ+9qq27IJeP53PWgZ2lFh5cxm/q48llPG6x87isOkz6 kEZVeUDozMI1O3NXHUj29UhjK/iLhcBBy3+k8O9TCc7shaLUFHV5U1wLK g==; X-IronPort-AV: E=McAfee;i="6400,9594,10353"; a="272355873" X-IronPort-AV: E=Sophos;i="5.91,239,1647327600"; d="scan'208";a="272355873" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga102.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 20 May 2022 09:06:35 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.91,239,1647327600"; d="scan'208";a="599290403" Received: from silpixa00400883.ir.intel.com ([10.243.23.50]) by orsmga008.jf.intel.com with ESMTP; 20 May 2022 09:06:33 -0700 From: Brian Dooley To: dev@dpdk.org Cc: gakhil@marvell.com, gmuthukrishn@marvell.com, Brian Dooley , Fan Zhang Subject: [RFC] examples/fips_validation: add fips 140-3 acvp aes-cbc test Date: Fri, 20 May 2022 16:05:53 +0000 Message-Id: <20220520160554.495317-1-brian.dooley@intel.com> X-Mailer: git-send-email 2.25.1 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org This RFC patch showcases an alternative approach to enable FIPS 140-3 support in the DPDK fips_validation sample application. The approach presented here takes advantage of an existing open source library, libacvp,(https://github.com/cisco/libacvp) to generate the parsed test cases instead of creating and maintaining a DPDK FIPS test file parser. In addition call back functions are added to the dpdk-fips_validation application to process the parsed test vectors and write back the results. This initial RFC patch contains the code to parse the FIPS 140-3 test files with libacvp library, and the AES-CBC test runner callback function implementation with most test types covered apart from MCT test. Although a different approach has been proposed (http://patches.dpdk.org/project/dpdk/list/?series=22738), it has the disadvantage of having to maintain the parsing code. For the sake of this RFC here is some information on how to modify and run a test case. The libacvp library can be installed by following the Building instructions in the README of the libacvp repo as linked above. An example test vector which we can call as our input.req: https://github.com/cisco/libacvp/blob/main/test/json/aes/aes.json The header acvVersion metadata at the start needs to been updated to the following: { "acvVersion": "1.0", "jwt": "NA", "url": "NA", "isSample": false, "vectorSetUrls": ["NA"] } With this RFC patch applied you can then run the dpdk-fips_validation as follows: ./dpdk-fips_validation --vdev=crypto_aesni_mb -- \ --req-file input.req --rsp-file output.rsp --acvp Please note the MCT tests in the input.req file will generate an incorrect result set as the IV update part has yet to be implemented. This will be addressed in next revision. Signed-off-by: Brian Dooley --- examples/fips_validation/fips_test_acvp.c | 183 +++++++++++++++++++++ examples/fips_validation/fips_validation.h | 34 ++++ examples/fips_validation/main.c | 59 ++++--- examples/fips_validation/meson.build | 9 + 4 files changed, 260 insertions(+), 25 deletions(-) create mode 100644 examples/fips_validation/fips_test_acvp.c diff --git a/examples/fips_validation/fips_test_acvp.c b/examples/fips_validation/fips_test_acvp.c new file mode 100644 index 0000000000..55f6b35a7d --- /dev/null +++ b/examples/fips_validation/fips_test_acvp.c @@ -0,0 +1,183 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2022 Intel Corporation + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include "fips_validation.h" + +#define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op)) + +static ACVP_RESULT logger(char *msg) +{ + printf("%s", msg); + return ACVP_SUCCESS; +} + +static int aes_cbc_handler(ACVP_TEST_CASE *test_case) +{ + ACVP_SYM_CIPHER_TC *tc; + struct rte_crypto_sym_xform xform = { 0 }; + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_cipher_xform *cipher_xform = &xform.cipher; + struct rte_crypto_sym_op *sym = env.op->sym; + struct fips_val val = {NULL, 0}; + uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF); + uint16_t n_deqd; + int ret; + + memset(&xform, 0, sizeof(xform)); + + tc = test_case->tc.symmetric; + + xform.type = RTE_CRYPTO_SYM_XFORM_CIPHER; + + cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC; + cipher_xform->op = (tc->direction == ACVP_SYM_CIPH_DIR_ENCRYPT) ? + RTE_CRYPTO_AEAD_OP_ENCRYPT : + RTE_CRYPTO_AEAD_OP_DECRYPT; + cipher_xform->key.data = tc->key; + /* Check support for 128 bit key*/ + if (tc->key_len % 8 == 0) + cipher_xform->key.length = 16; + else + cipher_xform->key.length = tc->key_len; + + if (cipher_xform->algo == RTE_CRYPTO_CIPHER_AES_CBC) { + cipher_xform->iv.length = tc->iv_len; + cipher_xform->iv.offset = IV_OFF; + } else { + cipher_xform->iv.length = 0; + cipher_xform->iv.offset = 0; + } + cap_idx.algo.cipher = cipher_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER; + + cap = rte_cryptodev_sym_capability_get(env.dev_id, &cap_idx); + if (!cap) { + RTE_LOG(ERR, USER1, "Failed to get capability for cdev %u\n", + env.dev_id); + return -EINVAL; + } + + if (rte_cryptodev_sym_capability_check_cipher(cap, + cipher_xform->key.length, + cipher_xform->iv.length) != 0) { + RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n", + info.device_name, cipher_xform->key.length, + cipher_xform->iv.length); + return -EPERM; + } + + env.sess = rte_cryptodev_sym_session_create(env.sess_mpool); + if (!env.sess) + return -ENOMEM; + + ret = rte_cryptodev_sym_session_init(env.dev_id, env.sess, &xform, + env.sess_priv_mpool); + if (ret < 0) { + RTE_LOG(ERR, PMD, "Error %i: Init session\n", ret); + return ret; + } + + if (env.op) + rte_crypto_op_free(env.op); + + env.op = rte_crypto_op_alloc(env.op_pool, + RTE_CRYPTO_OP_TYPE_SYMMETRIC); + if (!env.op) + ret = -ENOMEM; + + memcpy(iv, tc->iv, tc->iv_len); + + if (tc->direction == ACVP_SYM_CIPH_DIR_ENCRYPT) { + val.val = tc->pt; + val.len = tc->pt_len; + } else { /* Decrypt */ + val.val = tc->ct; + val.len = tc->ct_len; + } + + ret = prepare_data_mbufs(&val); + if (ret < 0) + return ret; + + if (tc->direction == ACVP_SYM_CIPH_DIR_ENCRYPT) { + sym->cipher.data.length = tc->pt_len; + } else { /* Decrypt */ + sym->cipher.data.length = tc->ct_len; + } + + rte_crypto_op_attach_sym_session(env.op, env.sess); + + sym->m_src = env.mbuf; + sym->cipher.data.offset = 0; + + if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) { + RTE_LOG(ERR, USER1, "Error: Failed enqueue\n"); + return ret = -1; + } + + do { + struct rte_crypto_op *deqd_op[1]; + + n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, deqd_op, + 1); + } while (n_deqd == 0); + + rte_cryptodev_sym_session_clear(env.dev_id, env.sess); + rte_cryptodev_sym_session_free(env.sess); + + val.val = NULL; + + ret = get_writeback_data(&val); + if (ret < 0) + return ret; + + if (tc->direction == ACVP_SYM_CIPH_DIR_ENCRYPT) { + memcpy(tc->ct, val.val, val.len); + tc->ct_len = val.len; + } else { /* Decrypt */ + memcpy(tc->pt, val.val, val.len); + tc->pt_len = val.len; + } + + return ret; +} + +int +fips_test_acvp_init(void **acvp_ctx) +{ + *acvp_ctx = NULL; + ACVP_RESULT acvp_ret = ACVP_SUCCESS; + + /* Create test session and enable CBC tests */ + acvp_ret = acvp_create_test_session((ACVP_CTX **)acvp_ctx, logger, + ACVP_LOG_LVL_INFO); + if (acvp_ret != ACVP_SUCCESS) + return acvp_ret; + + if (acvp_cap_sym_cipher_enable((ACVP_CTX *)*acvp_ctx, ACVP_AES_CBC, + &aes_cbc_handler) != ACVP_SUCCESS) + return acvp_ret; + + return ACVP_SUCCESS; +} + +void +fips_test_acvp(void *acvp_ctx, const char *req_file_path, + const char *rsp_file_path) +{ + /* Parse request file, run crypto tests and write out response file */ + acvp_run_vectors_from_file(acvp_ctx, req_file_path, rsp_file_path); +} diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h index aaadf01ba8..de831fd0aa 100644 --- a/examples/fips_validation/fips_validation.h +++ b/examples/fips_validation/fips_validation.h @@ -193,8 +193,31 @@ struct fips_test_interim_info { post_prcess_t kat_check; }; +struct cryptodev_fips_validate_env { + const char *req_path; + const char *rsp_path; + uint32_t is_path_folder; + uint8_t dev_id; + uint8_t dev_support_sgl; + uint16_t mbuf_data_room; + struct rte_mempool *mpool; + struct rte_mempool *sess_mpool; + struct rte_mempool *sess_priv_mpool; + struct rte_mempool *op_pool; + struct rte_mbuf *mbuf; + uint8_t *digest; + uint16_t digest_len; + struct rte_crypto_op *op; + struct rte_cryptodev_sym_session *sess; + uint16_t self_test; + struct fips_dev_broken_test_config *broken_test_config; + uint8_t is_acvp; + void *acvp_ctx; +}; + extern struct fips_test_vector vec; extern struct fips_test_interim_info info; +extern struct cryptodev_fips_validate_env env; int fips_test_init(const char *req_file_path, const char *rsp_file_path, @@ -289,4 +312,15 @@ int prepare_gcm_xform(struct rte_crypto_sym_xform *xform); int prepare_gmac_xform(struct rte_crypto_sym_xform *xform); +int prepare_data_mbufs(struct fips_val *val); + +int get_writeback_data(struct fips_val *val); + +__rte_weak void +fips_test_acvp(void *acvp_ctx, const char *req_file_path, + const char *rsp_file_path); + +__rte_weak int +fips_test_acvp_init(void **acvp_ctx); + #endif diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c index e06ae37567..54b45dcc1f 100644 --- a/examples/fips_validation/main.c +++ b/examples/fips_validation/main.c @@ -12,6 +12,8 @@ #include #include +#include + #include "fips_validation.h" #include "fips_dev_self_test.h" @@ -34,30 +36,13 @@ enum { OPT_CRYPTODEV_BK_ID_NUM, #define OPT_CRYPTODEV_BK_DIR_KEY "broken-test-dir" OPT_CRYPTODEV_BK_DIR_KEY_NUM, +#define OPT_CRYPTODEV_ACVP "acvp" + OPT_CRYPTODEV_ACVP_NUM, }; struct fips_test_vector vec; struct fips_test_interim_info info; - -struct cryptodev_fips_validate_env { - const char *req_path; - const char *rsp_path; - uint32_t is_path_folder; - uint8_t dev_id; - uint8_t dev_support_sgl; - uint16_t mbuf_data_room; - struct rte_mempool *mpool; - struct rte_mempool *sess_mpool; - struct rte_mempool *sess_priv_mpool; - struct rte_mempool *op_pool; - struct rte_mbuf *mbuf; - uint8_t *digest; - uint16_t digest_len; - struct rte_crypto_op *op; - struct rte_cryptodev_sym_session *sess; - uint16_t self_test; - struct fips_dev_broken_test_config *broken_test_config; -} env; +struct cryptodev_fips_validate_env env; static int cryptodev_fips_validate_app_int(void) @@ -79,6 +64,12 @@ cryptodev_fips_validate_app_int(void) } } + if (env.is_acvp) { + ret = fips_test_acvp_init(&env.acvp_ctx); + if (ret < 0) + return ret; + } + ret = rte_cryptodev_configure(env.dev_id, &conf); if (ret < 0) return ret; @@ -161,6 +152,7 @@ cryptodev_fips_validate_app_uninit(void) rte_mempool_free(env.sess_mpool); rte_mempool_free(env.sess_priv_mpool); rte_mempool_free(env.op_pool); + acvp_free_test_session(env.acvp_ctx); } static int @@ -218,11 +210,13 @@ cryptodev_fips_validate_usage(const char *prgname) " --%s: CRYPTODEV-ID-NAME\n" " --%s: self test indicator\n" " --%s: self broken test ID\n" - " --%s: self broken test direction\n", + " --%s: self broken test direction\n" + " --%s: acvp test indicator\n", prgname, OPT_REQ_FILE_PATH, OPT_RSP_FILE_PATH, OPT_FOLDER, OPT_MBUF_DATAROOM, def_mbuf_seg_size, OPT_CRYPTODEV, OPT_CRYPTODEV_ID, OPT_CRYPTODEV_ST, - OPT_CRYPTODEV_BK_ID, OPT_CRYPTODEV_BK_DIR_KEY); + OPT_CRYPTODEV_BK_ID, OPT_CRYPTODEV_BK_DIR_KEY, + OPT_CRYPTODEV_ACVP); } static int @@ -251,6 +245,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv) NULL, OPT_CRYPTODEV_BK_ID_NUM}, {OPT_CRYPTODEV_BK_DIR_KEY, required_argument, NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM}, + {OPT_CRYPTODEV_ACVP, no_argument, + NULL, OPT_CRYPTODEV_ACVP_NUM}, {NULL, 0, 0, 0} }; @@ -363,6 +359,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv) } break; + case OPT_CRYPTODEV_ACVP_NUM: + env.is_acvp = 1; + break; + default: cryptodev_fips_validate_usage(prgname); return -EINVAL; @@ -417,6 +417,11 @@ main(int argc, char *argv[]) if (!env.is_path_folder) { printf("Processing file %s... ", env.req_path); + if (env.is_acvp) { + fips_test_acvp(env.acvp_ctx, env.req_path, env.rsp_path); + printf("Done\n"); + goto exit; + } ret = fips_test_init(env.req_path, env.rsp_path, rte_cryptodev_name_get(env.dev_id)); if (ret < 0) { @@ -425,7 +430,6 @@ main(int argc, char *argv[]) goto exit; } - ret = fips_test_one_file(); if (ret < 0) { RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n", @@ -473,6 +477,11 @@ main(int argc, char *argv[]) printf("Processing file %s... ", req_path); + if (env.is_acvp) { + fips_test_acvp(env.acvp_ctx, env.req_path, env.rsp_path); + continue; + } + ret = fips_test_init(req_path, rsp_path, rte_cryptodev_name_get(env.dev_id)); if (ret < 0) { @@ -511,7 +520,7 @@ main(int argc, char *argv[]) struct fips_test_ops test_ops; -static int +int prepare_data_mbufs(struct fips_val *val) { struct rte_mbuf *m, *head = 0; @@ -1115,7 +1124,7 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform) return 0; } -static int +int get_writeback_data(struct fips_val *val) { struct rte_mbuf *m = env.mbuf; diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build index 7eef456318..03302fcc5a 100644 --- a/examples/fips_validation/meson.build +++ b/examples/fips_validation/meson.build @@ -19,5 +19,14 @@ sources = files( 'fips_validation_sha.c', 'fips_validation_xts.c', 'fips_dev_self_test.c', + 'fips_test_acvp.c', 'main.c', ) + +libacvp = cc.find_library('acvp', required: true) + +if not libacvp.found() + libacvp = false +endif + +ext_deps += libacvp -- 2.25.1