diff options
Diffstat (limited to 'src/seastar/dpdk/examples/fips_validation')
14 files changed, 5355 insertions, 0 deletions
diff --git a/src/seastar/dpdk/examples/fips_validation/Makefile b/src/seastar/dpdk/examples/fips_validation/Makefile new file mode 100644 index 000000000..e74252e27 --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/Makefile @@ -0,0 +1,77 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# binary name +APP = fips_validation + +# all source are stored in SRCS-y +SRCS-y := fips_validation.c +SRCS-y += fips_validation_aes.c +SRCS-y += fips_validation_hmac.c +SRCS-y += fips_validation_tdes.c +SRCS-y += fips_validation_gcm.c +SRCS-y += fips_validation_cmac.c +SRCS-y += fips_validation_ccm.c +SRCS-y += fips_validation_sha.c +SRCS-y += fips_dev_self_test.c +SRCS-y += main.c + +# Build using pkg-config variables if possible +$(shell pkg-config --exists libdpdk) +ifeq ($(.SHELLSTATUS),0) + +all: shared +.PHONY: shared static +shared: build/$(APP)-shared + ln -sf $(APP)-shared build/$(APP) +static: build/$(APP)-static + ln -sf $(APP)-static build/$(APP) + +PC_FILE := $(shell pkg-config --path libdpdk) +CFLAGS += -O3 $(shell pkg-config --cflags libdpdk) +LDFLAGS_SHARED = $(shell pkg-config --libs libdpdk) +LDFLAGS_STATIC = -Wl,-Bstatic $(shell pkg-config --static --libs libdpdk) + +build/$(APP)-shared: $(SRCS-y) Makefile $(PC_FILE) | build + $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_SHARED) + +build/$(APP)-static: $(SRCS-y) Makefile $(PC_FILE) | build + $(CC) $(CFLAGS) $(SRCS-y) -o $@ $(LDFLAGS) $(LDFLAGS_STATIC) + +build: + @mkdir -p $@ + +.PHONY: clean +clean: + rm -f build/$(APP) build/$(APP)-static build/$(APP)-shared + rmdir --ignore-fail-on-non-empty build + +else + +ifeq ($(RTE_SDK),) +$(error "Please define RTE_SDK environment variable") +endif + +# Default target, detect a build directory, by looking for a path with a .config +RTE_TARGET ?= $(notdir $(abspath $(dir $(firstword $(wildcard $(RTE_SDK)/*/.config))))) + +INC += $(sort $(wildcard *.h)) + +include $(RTE_SDK)/mk/rte.vars.mk + +CFLAGS += $(WERROR_FLAGS) + +# workaround for a gcc bug with noreturn attribute +# http://gcc.gnu.org/bugzilla/show_bug.cgi?id=12603 +ifeq ($(CONFIG_RTE_TOOLCHAIN_GCC),y) +CFLAGS_main.o += -Wno-return-type +endif + +CFLAGS += -DALLOW_EXPERIMENTAL_API +CFLAGS += -I$(SRCDIR) +CFLAGS += -O3 +CFLAGS += $(WERROR_FLAGS) + +include $(RTE_SDK)/mk/rte.extapp.mk + +endif diff --git a/src/seastar/dpdk/examples/fips_validation/fips_dev_self_test.c b/src/seastar/dpdk/examples/fips_validation/fips_dev_self_test.c new file mode 100644 index 000000000..df1c0e82e --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_dev_self_test.c @@ -0,0 +1,1719 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include <rte_cryptodev.h> +#include <rte_cryptodev_pmd.h> + +#include "fips_dev_self_test.h" + +#define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op)) + +#define FIPS_DEV_TEST_DATA_MAX_SIZE 8096 +#define AES_CCM_AAD_PAD_SIZE 18 + +struct fips_dev_self_test_vector { + const char *name; + enum rte_crypto_sym_xform_type operation_type; + + struct { + uint8_t data[64]; + uint16_t len; + } digest; + + struct { + uint8_t data[256]; + uint16_t len; + } key; + + struct { + uint8_t data[16]; + uint8_t len; + } iv; + + union { + struct { + enum rte_crypto_cipher_algorithm algo; + } cipher; + + struct { + enum rte_crypto_aead_algorithm algo; + struct { + uint8_t data[FIPS_DEV_TEST_DATA_MAX_SIZE]; + uint16_t len; + } aad; + } aead; + + struct { + enum rte_crypto_auth_algorithm algo; + } auth; + }; + + struct { + const uint8_t data[FIPS_DEV_TEST_DATA_MAX_SIZE]; + uint16_t len; + } input; + + struct { + uint8_t data[FIPS_DEV_TEST_DATA_MAX_SIZE]; + uint16_t len; + } output; +}; + +#define GET_MBUF_DATA(data, len, m) \ +do { \ + len = rte_pktmbuf_pkt_len(m); \ + data = rte_pktmbuf_mtod(m, uint8_t *); \ +} while (0) + + +/* <-- SHA-x HMAC --> */ +static struct fips_dev_self_test_vector +SELF_TEST_SHA1_HMAC_test_vector = { + .name = "SELF_TEST_SHA1_HMAC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_AUTH, + + .auth = { + .algo = RTE_CRYPTO_AUTH_SHA1_HMAC, + }, + .input = { + .data = { + 0xed, 0xb2, 0xba, 0x09, 0x99, 0x61, 0xd3, 0x8f, + 0xd0, 0xa0, 0xa6, 0xa2, 0x35, 0xd6, 0x12, 0x71, + 0xcb, 0x4d, 0x49, 0x3b, 0x64, 0xd9, 0xde, 0x13, + 0x5c, 0xbb, 0x1f, 0xe0, 0x86, 0xc4, 0xa4, 0xa7, + 0x67, 0xbe, 0x28, 0x0d, 0xa2, 0x07, 0x98, 0x17, + 0xb4, 0x7f, 0x6a, 0x35, 0xe1, 0xa4, 0x30, 0x7f, + 0x6e, 0xfc, 0x6d, 0x3e, 0x11, 0xb4, 0xa7, 0xae, + 0xa6, 0x86, 0xbd, 0x02, 0x23, 0xe0, 0x7b, 0xa9, + 0xce, 0x42, 0x6c, 0xd0, 0xae, 0xe7, 0xef, 0x28, + 0x3f, 0xa9, 0x8d, 0xe9, 0x6a, 0x1f, 0x8a, 0x17, + 0xb3, 0x08, 0xba, 0x04, 0xb5, 0xec, 0x96, 0x16, + 0xcb, 0x00, 0x8f, 0xca, 0x11, 0x4b, 0xa3, 0xf9, + 0x8b, 0x07, 0x2d, 0x5a, 0xa3, 0x4a, 0x01, 0x49, + 0xd9, 0xe5, 0xb8, 0xc6, 0xb6, 0x8c, 0x49, 0xc1, + 0x01, 0x38, 0xda, 0x95, 0x36, 0xca, 0xd5, 0xd2, + 0x34, 0xf1, 0x3d, 0x3f, 0x36, 0x4d, 0x43, 0x1f + }, + .len = 128, + }, + .key = { + .data = { + 0x8d, 0x8d, 0x15, 0xd8, 0xa9, 0x57, 0x9a, 0xdb, + 0x2d, 0x62 + }, + .len = 10, + }, + .digest = { + .data = { + 0x0c, 0x66, 0x2e, 0x47, 0x93, 0x93, 0x8c, 0xc3, + 0x7f, 0x3d, 0x51, 0xd2, 0xb4, 0x05, 0x48, 0xec, + 0x55, 0x91, 0x4f, 0x0d + }, + .len = 20, + }, +}; + +static struct fips_dev_self_test_vector +SELF_TEST_SHA224_HMAC_test_vector = { + .name = "SELF_TEST_SHA224_HMAC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_AUTH, + .auth = { + .algo = RTE_CRYPTO_AUTH_SHA224_HMAC, + }, + .input = { + .data = { + 0x41, 0x18, 0x43, 0xa2, 0x13, 0x87, 0x84, 0x6f, + 0x3b, 0x9e, 0xd5, 0xfc, 0x54, 0x5a, 0xca, 0xdf, + 0xa5, 0xb7, 0x03, 0x86, 0xf6, 0x2d, 0xa4, 0xd9, + 0xa2, 0x7b, 0x04, 0x1b, 0xee, 0xa3, 0xaa, 0x11, + 0x99, 0x36, 0x75, 0x67, 0xb4, 0xd1, 0x1a, 0x4f, + 0xb4, 0xe8, 0xd4, 0x6b, 0xc6, 0xc2, 0x56, 0xed, + 0x62, 0xc5, 0x05, 0xfd, 0x23, 0xf4, 0x64, 0x5b, + 0xd6, 0xb6, 0xcf, 0x45, 0xd1, 0xd9, 0x6d, 0x9b, + 0x86, 0xd6, 0x60, 0x41, 0x57, 0x57, 0x3e, 0xc5, + 0xac, 0xf6, 0xc5, 0x41, 0x43, 0x48, 0xca, 0x83, + 0xc8, 0x1a, 0x73, 0x6c, 0xa6, 0xfa, 0xa6, 0x96, + 0x1c, 0xfa, 0xc1, 0x39, 0x93, 0xb0, 0x8c, 0x50, + 0x2f, 0x81, 0x6c, 0xf7, 0xa4, 0x20, 0xd9, 0x18, + 0x4b, 0x51, 0x11, 0x46, 0x75, 0xf3, 0x0e, 0xe9, + 0xff, 0x3d, 0xb6, 0x9c, 0x26, 0x48, 0x53, 0xd3, + 0x9d, 0xcd, 0x42, 0xc1, 0xdd, 0x31, 0xef, 0x79 + + }, + .len = 128, + }, + .key = { + .data = { + 0x37, 0x14, 0x70, 0x78, 0x39, 0xda, 0xf7, 0x91, + 0x22, 0xc7, 0x82, 0x41, 0x63, 0x51, 0x38, 0x5e, + 0x88, 0xa8, 0x1d, 0x31, 0xc9, 0xf6, 0x41, 0xd8, + 0xdc, 0xe5, 0x38, 0xe9, 0x0e, 0x63, 0xc9, 0x58, + 0x92, 0xa2, 0xea, 0x9b, 0x19, 0x62, 0xed, 0x0b, + 0xa3, 0x72, 0xf4, 0x8e, 0x94, 0x74, 0xaa, 0x73, + 0x0a, 0xe2 + }, + .len = 50, + }, + .digest = { + .data = { + 0x33, 0xf1, 0x7a, 0xc8, 0xa5, 0xc6, 0xb5, 0x25, + 0xdb, 0x8b, 0x86, 0x44, 0xb6, 0xab + + }, + .len = 14, + }, +}; + + +static struct fips_dev_self_test_vector +SELF_TEST_SHA256_HMAC_test_vector = { + .name = "SELF_TEST_SHA256_HMAC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_AUTH, + .auth = { + .algo = RTE_CRYPTO_AUTH_SHA256_HMAC, + }, + .input = { + .data = { + 0x1c, 0x43, 0x96, 0xf7, 0xb7, 0xf9, 0x22, 0x8e, + 0x83, 0x2a, 0x13, 0x69, 0x20, 0x02, 0xba, 0x2a, + 0xff, 0x43, 0x9d, 0xcb, 0x7f, 0xdd, 0xbf, 0xd4, + 0x56, 0xc0, 0x22, 0xd1, 0x33, 0xee, 0x89, 0x03, + 0xa2, 0xd4, 0x82, 0x56, 0x2f, 0xda, 0xa4, 0x93, + 0xce, 0x39, 0x16, 0xd7, 0x7a, 0x0c, 0x51, 0x44, + 0x1d, 0xab, 0x26, 0xf6, 0xb0, 0x34, 0x02, 0x38, + 0xa3, 0x6a, 0x71, 0xf8, 0x7f, 0xc3, 0xe1, 0x79, + 0xca, 0xbc, 0xa9, 0x48, 0x2b, 0x70, 0x49, 0x71, + 0xce, 0x69, 0xf3, 0xf2, 0x0a, 0xb6, 0x4b, 0x70, + 0x41, 0x3d, 0x6c, 0x29, 0x08, 0x53, 0x2b, 0x2a, + 0x88, 0x8a, 0x9f, 0xc2, 0x24, 0xca, 0xe1, 0x36, + 0x5d, 0xa4, 0x10, 0xb6, 0xf2, 0xe2, 0x98, 0x90, + 0x4b, 0x63, 0xb4, 0xa4, 0x17, 0x26, 0x32, 0x18, + 0x35, 0xa4, 0x77, 0x4d, 0xd0, 0x63, 0xc2, 0x11, + 0xcf, 0xc8, 0xb5, 0x16, 0x6c, 0x2d, 0x11, 0xa2 + }, + .len = 128, + }, + .key = { + .data = { + 0x54, 0x48, 0x99, 0x8f, 0x9d, 0x8f, 0x98, 0x53, + 0x4a, 0xdd, 0xf0, 0xc8, 0xba, 0x63, 0x1c, 0x49, + 0x6b, 0xf8, 0xa8, 0x00, 0x6c, 0xbb, 0x46, 0xad, + 0x15, 0xfa, 0x1f, 0xa2, 0xf5, 0x53, 0x67, 0x12, + 0x0c, 0x19, 0x34, 0x8c, 0x3a, 0xfa, 0x90, 0xc3 + }, + .len = 40, + }, + .digest = { + .data = { + 0x7e, 0x8c, 0xba, 0x9d, 0xd9, 0xf0, 0x6e, 0xbd, + 0xd7, 0xf9, 0x2e, 0x0f, 0x1a, 0x67, 0xc7, 0xf4, + 0xdf, 0x52, 0x69, 0x3c, 0x21, 0x2b, 0xdd, 0x84, + 0xf6, 0x73, 0x70, 0xb3, 0x51, 0x53, 0x3c, 0x6c + }, + .len = 32, + }, +}; + +/* HMAC count=34 L=48 SHA384 GENERATE*/ +static struct fips_dev_self_test_vector +SELF_TEST_SHA384_HMAC_test_vector = { + .name = "SELF_TEST_SHA384_HMAC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_AUTH, + .auth = { + .algo = RTE_CRYPTO_AUTH_SHA384_HMAC, + }, + .input = { + .data = { + 0xf5, 0x10, 0x86, 0xfe, 0x78, 0x15, 0x0f, 0xe4, + 0x8b, 0xd1, 0x41, 0x5a, 0x47, 0x85, 0xac, 0xc0, + 0x5a, 0xb8, 0x0e, 0xf0, 0x0b, 0x29, 0x75, 0xce, + 0x78, 0x07, 0xa4, 0x21, 0x22, 0x64, 0xb8, 0xa1, + 0xac, 0xe8, 0x0b, 0x50, 0xe0, 0xc2, 0x59, 0x0e, + 0xf3, 0xe4, 0x21, 0x68, 0x0a, 0x70, 0x4e, 0xb2, + 0xfc, 0x6d, 0x17, 0x55, 0x5a, 0xbf, 0x24, 0x69, + 0xad, 0x56, 0xf2, 0x87, 0xfe, 0xa5, 0x78, 0xd8, + 0x9c, 0x56, 0x0b, 0x72, 0x19, 0x3c, 0x7f, 0xe5, + 0x96, 0x89, 0x8f, 0x10, 0x40, 0x41, 0x7e, 0x3a, + 0x1b, 0xee, 0xff, 0x5e, 0xff, 0x96, 0x53, 0xc5, + 0xe0, 0xea, 0xb1, 0xda, 0x52, 0xc0, 0xea, 0x3b, + 0x4b, 0xc3, 0x4d, 0x0c, 0x2b, 0x69, 0xc8, 0x90, + 0xfb, 0x26, 0x51, 0xfa, 0xf2, 0xe0, 0x84, 0x80, + 0x3e, 0xa2, 0x8e, 0xb2, 0x01, 0x94, 0x49, 0x0a, + 0x99, 0x2b, 0xa8, 0xc4, 0x24, 0x9d, 0x56, 0xef + }, + .len = 128, + }, + .key = { + .data = { + 0x91, 0x7a, 0x69, 0x8c, 0x82, 0xf4, 0x4f, 0x19, + 0x57, 0x3b, 0x64, 0x5c, 0x48, 0x79, 0xb8, 0x73, + 0x0b, 0x58, 0xdf, 0xf4, 0xed, 0xc6, 0xa0, 0xd3, + 0x21, 0xf5, 0xf1, 0x86, 0x58, 0xa5, 0x24, 0x66, + 0x92, 0xa5, 0x5b, 0x59, 0x33, 0x97, 0x41, 0xae, + 0x59, 0xf5, 0xfc, 0x48, 0x6d, 0x51, 0x5d, 0xff, + 0xf8, 0xe1 + }, + .len = 50, + }, + .digest = { + .data = { + 0x77, 0xbf, 0x56, 0x15, 0xec, 0x52, 0xf7, 0x06, + 0xca, 0x74, 0x64, 0x01, 0xe9, 0xfd, 0xe4, 0x3f, + 0x15, 0x60, 0x52, 0x37, 0xe5, 0x50, 0xb9, 0x3a, + 0x84, 0x72, 0xfd, 0x14, 0x4f, 0xc3, 0x9e, 0x5e, + 0xca, 0x0f, 0xe8, 0x90, 0x83, 0x88, 0x28, 0xa0 + }, + .len = 40, + }, +}; + +/* HMAC count=28 L=64 SHA512 GENERATE*/ +static struct fips_dev_self_test_vector +SELF_TEST_SHA512_HMAC_test_vector = { + .name = "SELF_TEST_SHA512_HMAC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_AUTH, + .auth = { + .algo = RTE_CRYPTO_AUTH_SHA512_HMAC, + }, + .input = { + .data = { + 0x0a, 0x33, 0x1c, 0xe2, 0x00, 0x89, 0xb2, 0x9e, + 0x94, 0xb2, 0xc5, 0xf5, 0x18, 0xc8, 0xdb, 0xea, + 0xd4, 0x04, 0x17, 0xa2, 0xa8, 0xd5, 0x00, 0x18, + 0xf3, 0x2f, 0x85, 0x12, 0xb3, 0x26, 0x3d, 0x54, + 0xed, 0xbb, 0xf3, 0x13, 0x4f, 0xf6, 0x61, 0xac, + 0x14, 0x35, 0x3c, 0x96, 0x28, 0xc3, 0x71, 0x95, + 0x8c, 0xac, 0xaf, 0x31, 0xfd, 0xd0, 0x25, 0x67, + 0xd0, 0x37, 0x8d, 0x9e, 0x21, 0xa4, 0x69, 0xdd, + 0x2c, 0x6d, 0x8c, 0x3a, 0xfb, 0x89, 0xdd, 0x96, + 0x42, 0xeb, 0x58, 0x87, 0x87, 0x0e, 0x55, 0x96, + 0x85, 0xd2, 0x0d, 0xab, 0xd3, 0x86, 0x5a, 0xc5, + 0xc1, 0x46, 0xbe, 0xee, 0x83, 0x87, 0xa7, 0x6f, + 0x91, 0xf0, 0xf1, 0x40, 0x4d, 0x6c, 0xad, 0xc2, + 0xe6, 0x7d, 0x21, 0xb0, 0x7d, 0xd3, 0x0f, 0x53, + 0x87, 0x1d, 0x3b, 0xf6, 0x73, 0x1f, 0x27, 0x9a, + 0x8c, 0x04, 0x21, 0xeb, 0x20, 0xf6, 0x7f, 0x72 + }, + .len = 128, + }, + .key = { + .data = { + 0x39, 0xb8, 0x77, 0xb8, 0xe8, 0x2e, 0xcb, 0xd9, + 0x74, 0x03, 0x25, 0x82, 0x8f, 0xaf, 0x67, 0x21, + 0xc1, 0x29, 0x04, 0x6e, 0xb0, 0x13, 0x61, 0x44, + 0xa0, 0x31, 0x82, 0xb1, 0x36, 0x20, 0xe2, 0x49, + 0x81, 0x45, 0xa2, 0xbf, 0x3b, 0x03, 0xe6, 0xb6, + 0x4b, 0x31, 0x7d, 0xd4, 0x8f, 0xcb, 0xc0, 0x18, + 0xd9, 0xe7, 0xbc, 0x6e, 0x37, 0xeb, 0x93, 0x81, + 0x78, 0xfe, 0x1f, 0xd1, 0xeb, 0xbc, 0xd9, 0x05, + 0x6a, 0x2e, 0xf9, 0x82, 0x97, 0xf9, 0xdf, 0x3c, + 0x66, 0xd5, 0xb2, 0xcc, 0xdc, 0x41, 0x47, 0xc4, + 0x16, 0x76, 0x44, 0x3f, 0x8c, 0x99, 0x85, 0xbc, + 0x97, 0x34, 0xbe, 0x2c, 0x31, 0xe7, 0x62, 0x49, + 0xfc, 0x5b, 0xc4, 0x2a + }, + .len = 100, + }, + .digest = { + .data = { + 0x97, 0x16, 0x8f, 0x55, 0x13, 0xc2, 0xe9, 0xbc, + 0x4b, 0xc5, 0x25, 0xce, 0x27, 0x03, 0x74, 0x0b, + 0xce, 0x1a, 0x06, 0xec, 0xfe, 0x99, 0xa5, 0x70, + 0xac, 0x66, 0xc8, 0x3e, 0xde, 0x96, 0x67, 0xcc, + 0x07, 0xed, 0xf6, 0x64, 0x61, 0x7c, 0xe5, 0x3c + }, + .len = 40, + }, +}; + +/* <-- AES CMAC --> */ +static struct fips_dev_self_test_vector +SELF_TEST_AES_CMAC_test_vector = { + .name = "SELF_TEST_AES_CMAC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_AUTH, + .auth = { + .algo = RTE_CRYPTO_AUTH_AES_CMAC, + }, + .input = { + .data = { + 0x57, 0x88, 0xf6, 0x1e, 0x02, 0x30, 0x47, 0x91, + 0xb5, 0x2f, 0x40, 0x05, 0x7a, 0xbb, 0x4e, 0x04, + 0x46, 0x40, 0x3e, 0xf3, 0x74, 0x02, 0x53, 0xdf, + 0x72, 0x05, 0x96, 0x79, 0xbb, 0x2a, 0x6e, 0x5e, + 0x05, 0x9a, 0x70, 0x9c, 0xbb + }, + .len = 37, + }, + .key = { + .data = { + 0x18, 0x42, 0x15, 0x14, 0x5d, 0xa4, 0x9d, 0xb4, + 0x17, 0xe8, 0xbd, 0xd5, 0x73, 0xd6, 0x28, 0x2d + }, + .len = 16, + }, + .digest = { + .data = { + 0x8d, 0xa8, 0xcc, 0xa9, 0xb3, 0x6f, 0x68, 0x57, + 0x1c, 0x6c, 0x0e, 0x40, 0xa3, 0xf4, 0x10 + }, + .len = 15, + }, +}; + +/* <-- AES CCM --> */ +static struct fips_dev_self_test_vector +SELF_TEST_AES128_CCM_test_vector = { + .name = "SELF_TEST_AES128_CCM_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_AEAD, + .iv = { + .data = { + 0x00, 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xB5, + 0x03, 0x97, 0x76, 0xE7, 0x0C + }, + .len = 13, + }, + .aead = { + .algo = RTE_CRYPTO_AEAD_AES_CCM, + .aad = { + .data = { + /* 18 bytes padding for AAD */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, + 0x08, 0x40, 0x0F, 0xD2, 0xE1, 0x28, 0xA5, 0x7C, + 0x50, 0x30, 0xF1, 0x84, 0x44, 0x08, 0xAB, 0xAE, + 0xA5, 0xB8, 0xFC, 0xBA, 0x00, 0x00 + }, + .len = 22, + }, + }, + .input = { + .data = { + 0xF8, 0xBA, 0x1A, 0x55, 0xD0, 0x2F, 0x85, 0xAE, + 0x96, 0x7B, 0xB6, 0x2F, 0xB6, 0xCD, 0xA8, 0xEB, + 0x7E, 0x78, 0xA0, 0x50 + }, + .len = 20, + }, + .key = { + .data = { + 0xC9, 0x7C, 0x1F, 0x67, 0xCE, 0x37, 0x11, 0x85, + 0x51, 0x4A, 0x8A, 0x19, 0xF2, 0xBD, 0xD5, 0x2F + }, + .len = 16, + }, + .output = { + .data = { + 0xF3, 0xD0, 0xA2, 0xFE, 0x9A, 0x3D, 0xBF, 0x23, + 0x42, 0xA6, 0x43, 0xE4, 0x32, 0x46, 0xE8, 0x0C, + 0x3C, 0x04, 0xD0, 0x19 + }, + .len = 20, + }, + .digest = { + .data = { + 0x78, 0x45, 0xCE, 0x0B, 0x16, 0xF9, 0x76, 0x23 + }, + .len = 8, + }, +}; + +/* <-- AES CBC --> */ +static struct fips_dev_self_test_vector +SELF_TEST_AES128_CBC_test_vector = { + .name = "SELF_TEST_AES128_CBC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + + .iv = { + .data = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }, + .len = 16, + }, + .cipher = { + .algo = RTE_CRYPTO_CIPHER_AES_CBC, + }, + .input = { + .data = { + 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C, + 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72, + 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77, + 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, + }, + .len = 32, + }, + .key = { + .data = { + 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, + 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A + }, + .len = 16, + }, + .output = { + .data = { + 0x8B, 0x4D, 0xDA, 0x1B, 0xCF, 0x04, 0xA0, 0x31, + 0xB4, 0xBF, 0xBD, 0x68, 0x43, 0x20, 0x7E, 0x76, + 0xB1, 0x96, 0x8B, 0xA2, 0x7C, 0xA2, 0x83, 0x9E, + 0x39, 0x5A, 0x2F, 0x7E, 0x92, 0xB4, 0x48, 0x1A, + }, + .len = 32, + }, +}; + +static struct fips_dev_self_test_vector +SELF_TEST_AES192_CBC_test_vector = { + .name = "SELF_TEST_AES192_CBC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + + .iv = { + .data = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }, + .len = 16, + }, + .cipher = { + .algo = RTE_CRYPTO_CIPHER_AES_CBC, + }, + .input = { + .data = { + 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C, + 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72, + 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77, + 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, + }, + .len = 32, + }, + .key = { + .data = { + 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, + 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A, + 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0 + }, + .len = 24, + }, + .output = { + .data = { + 0x45, 0xEE, 0x9A, 0xEA, 0x3C, 0x03, 0xFC, 0x4C, + 0x84, 0x36, 0xB0, 0xDA, 0xB0, 0xDC, 0xF3, 0x5B, + 0x75, 0xA7, 0xBE, 0x0E, 0xC0, 0x8D, 0x6C, 0xF8, + 0xC1, 0x0F, 0xD0, 0x35, 0x1D, 0x82, 0xAE, 0x7C, + }, + .len = 32, + }, +}; + +/* AES-256 CBC ENCRYPT*/ +static struct fips_dev_self_test_vector +SELF_TEST_AES256_CBC_test_vector = { + .name = "SELF_TEST_AES256_CBC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + + .iv = { + .data = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F + }, + .len = 16, + }, + .cipher = { + .algo = RTE_CRYPTO_CIPHER_AES_CBC, + }, + .input = { + .data = { + 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C, + 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72, + 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77, + 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, + }, + .len = 32, + }, + .key = { + .data = { + 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, + 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A, + 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0, + 0x37, 0x07, 0xB8, 0x23, 0xA2, 0xA3, 0xB5, 0x8D + }, + .len = 32, + }, + .output = { + .data = { + 0xF3, 0xDD, 0xF0, 0x0B, 0xFF, 0xA2, 0x6A, 0x04, + 0xBE, 0xDA, 0x52, 0xA6, 0xFE, 0x6B, 0xA6, 0xA7, + 0x48, 0x1D, 0x7D, 0x98, 0x65, 0xDB, 0xEF, 0x06, + 0x26, 0xB5, 0x8E, 0xEB, 0x05, 0x0E, 0x77, 0x98, + }, + .len = 32, + }, +}; + +/* DES-128 CBC ENCRYPT*/ +static struct fips_dev_self_test_vector +SELF_TEST_3DES_2KEY_CBC_test_vector = { + .name = "SELF_TEST_3DES_2KEY_CBC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + .iv = { + .data = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }, + .len = 8, + }, + .cipher = { + .algo = RTE_CRYPTO_CIPHER_3DES_CBC, + }, + .input = { + .data = { + 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C, + 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72, + 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77, + 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, + }, + .len = 32, + }, + .key = { + .data = { + 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, + 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A, + 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2 + }, + .len = 24, + }, + .output = { + .data = { + 0x28, 0x2a, 0xff, 0x15, 0x5c, 0xdf, 0xd9, 0x6b, + 0x54, 0xbc, 0x7b, 0xfb, 0xc5, 0x64, 0x4d, 0xdd, + 0x3e, 0xf2, 0x9e, 0xb7, 0x53, 0x65, 0x37, 0x05, + 0xe0, 0xdf, 0xae, 0xf7, 0xc9, 0x27, 0xe4, 0xec, + }, + .len = 32, + }, +}; + +static struct fips_dev_self_test_vector +SELF_TEST_3DES_3KEY_CBC_test_vector = { + .name = "SELF_TEST_3DES_3KEY_CBC_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + + .iv = { + .data = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 + }, + .len = 8, + }, + .cipher = { + .algo = RTE_CRYPTO_CIPHER_3DES_CBC, + }, + .input = { + .data = { + 0x57, 0x68, 0x61, 0x74, 0x20, 0x61, 0x20, 0x6C, + 0x6F, 0x75, 0x73, 0x79, 0x20, 0x65, 0x61, 0x72, + 0x74, 0x68, 0x21, 0x20, 0x48, 0x65, 0x20, 0x77, + 0x6F, 0x6E, 0x64, 0x65, 0x72, 0x65, 0x64, 0x20, + }, + .len = 32, + }, + .key = { + .data = { + 0xE4, 0x23, 0x33, 0x8A, 0x35, 0x64, 0x61, 0xE2, + 0x49, 0x03, 0xDD, 0xC6, 0xB8, 0xCA, 0x55, 0x7A, + 0xD4, 0xC3, 0xA3, 0xAA, 0x33, 0x62, 0x61, 0xE0 + }, + .len = 24, + }, + .output = { + .data = { + 0xd0, 0xc9, 0xdc, 0x51, 0x29, 0x97, 0x03, 0x64, + 0xcd, 0x22, 0xba, 0x3d, 0x2b, 0xbc, 0x21, 0x37, + 0x7b, 0x1e, 0x29, 0x23, 0xeb, 0x51, 0x6e, 0xac, + 0xbe, 0x5b, 0xd3, 0x67, 0xe0, 0x3f, 0xc3, 0xb5, + }, + .len = 32, + }, +}; + +/* <-- AES GCM --> */ +static struct fips_dev_self_test_vector +SELF_TEST_AES128_GCM_encrypt_test_vector = { + .name = "SELF_TEST_AES128_GCM_encrypt_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_AEAD, + + .iv = { + .data = { + 0x5a, 0xdb, 0x96, 0x09, 0xdb, 0xae, 0xb5, 0x8c, + 0xbd, 0x6e, 0x72, 0x75 + }, + .len = 12, + }, + .aead = { + .algo = RTE_CRYPTO_AEAD_AES_GCM, + .aad = { + .data = { + 0x88, 0x31, 0x9d, 0x6e, 0x1d, 0x3f, 0xfa, 0x5f, + 0x98, 0x71, 0x99, 0x16, 0x6c, 0x8a, 0x9b, 0x56, + 0xc2, 0xae, 0xba, 0x5a + }, + .len = 20, + }, + }, + .input = { + .data = { + 0x7c, 0x0e, 0x88, 0xc8, 0x88, 0x99, 0xa7, 0x79, + 0x22, 0x84, 0x65, 0x07, 0x47, 0x97, 0xcd, 0x4c, + 0x2e, 0x14, 0x98, 0xd2, 0x59, 0xb5, 0x43, 0x90, + 0xb8, 0x5e, 0x3e, 0xef, 0x1c, 0x02, 0xdf, 0x60, + 0xe7, 0x43, 0xf1, 0xb8, 0x40, 0x38, 0x2c, 0x4b, + 0xcc, 0xaf, 0x3b, 0xaf, 0xb4, 0xca, 0x84, 0x29, + 0xbe, 0xa0, 0x63 + }, + .len = 51, + }, + .key = { + .data = { + 0xfe, 0x47, 0xfc, 0xce, 0x5f, 0xc3, 0x26, 0x65, + 0xd2, 0xae, 0x39, 0x9e, 0x4e, 0xec, 0x72, 0xba + }, + .len = 16, + }, + .output = { + .data = { + 0x98, 0xf4, 0x82, 0x6f, 0x05, 0xa2, 0x65, 0xe6, + 0xdd, 0x2b, 0xe8, 0x2d, 0xb2, 0x41, 0xc0, 0xfb, + 0xbb, 0xf9, 0xff, 0xb1, 0xc1, 0x73, 0xaa, 0x83, + 0x96, 0x4b, 0x7c, 0xf5, 0x39, 0x30, 0x43, 0x73, + 0x63, 0x65, 0x25, 0x3d, 0xdb, 0xc5, 0xdb, 0x87, + 0x78, 0x37, 0x14, 0x95, 0xda, 0x76, 0xd2, 0x69, + 0xe5, 0xdb, 0x3e + }, + .len = 51, + }, + .digest = { + .data = { + 0x29, 0x1e, 0xf1, 0x98, 0x2e, 0x4d, 0xef, 0xed, + 0xaa, 0x22, 0x49, 0xf8, 0x98, 0x55, 0x6b, 0x47 + }, + .len = 16, + }, +}; + +static struct fips_dev_self_test_vector +SELF_TEST_AES192_GCM_encrypt_test_vector = { + .operation_type = RTE_CRYPTO_SYM_XFORM_AEAD, + .name = "SELF_TEST_AES192_GCM_encrypt_test_vector", + .iv = { + .data = { + 0x0b, 0xd4, 0x4f, 0xf4, 0xd2, 0x0c, 0x15, 0xd0, + 0x4f, 0xc6, 0x1e, 0xe7 + }, + .len = 12, + }, + .aead = { + .algo = RTE_CRYPTO_AEAD_AES_GCM, + .aad = { + .data = { + 0x9e, 0xa4, 0x2c, 0x50, 0xa7, 0xfd, 0xb8, 0x5e, + 0x14, 0x1a, 0xa0, 0x84, 0xb4, 0x6b, 0xde, 0x12 + }, + .len = 16, + }, + }, + .input = { + .data = { + 0x56, 0x7c, 0xcb, 0x3f, 0xa0, 0xdb, 0x89, 0x70, + 0x8a, 0xf3, 0xff, 0x2b, 0xb0, 0x29, 0xdd, 0xec, + 0x52, 0xc6, 0x69, 0x47, 0x58, 0x5d, 0x29, 0x1a, + 0x28, 0x56, 0x4b, 0xf5, 0x6d, 0xb7, 0x06, 0xf7 + }, + .len = 32, + }, + .key = { + .data = { + 0x0d, 0x4a, 0x90, 0x0d, 0x1b, 0x0b, 0xb5, 0xb7, + 0xbe, 0x24, 0x38, 0xc2, 0xba, 0x48, 0xfc, 0x45, + 0x13, 0x4c, 0xc1, 0x98, 0x10, 0x8c, 0xf8, 0x85 + }, + .len = 24, + }, + .output = { + .data = { + 0x2f, 0x8a, 0x42, 0xcd, 0x18, 0x3b, 0x03, 0x14, + 0xfd, 0x20, 0xa3, 0xd9, 0x7d, 0x9e, 0x0c, 0x52, + 0x17, 0xb0, 0xf0, 0x88, 0xd2, 0xca, 0x87, 0xa8, + 0x29, 0x0d, 0x4b, 0xae, 0x69, 0xad, 0x83, 0xf5 + }, + .len = 32, + }, + .digest = { + .data = { + 0xde, 0x41, 0x45, 0x92, 0xd7, 0x7f, 0x2f, 0x0b, + 0x50, 0xdf, 0x4a, 0xec, 0x71, 0x4f, 0xad, 0x43 + }, + .len = 16, + }, +}; + +static struct fips_dev_self_test_vector +SELF_TEST_AES256_GCM_encrypt_test_vector = { + .operation_type = RTE_CRYPTO_SYM_XFORM_AEAD, + .name = "SELF_TEST_AES256_GCM_encrypt_test_vector", + .iv = { + .data = { + 0x5c, 0x1b, 0x21, 0xc8, 0x99, 0x8e, 0xd6, 0x29, + 0x90, 0x06, 0xd3, 0xf9 + }, + .len = 12, + }, + .aead = { + .algo = RTE_CRYPTO_AEAD_AES_GCM, + .aad = { + .data = { + 0x22, 0xed, 0x23, 0x59, 0x46, 0x23, 0x5a, 0x85, + 0xa4, 0x5b, 0xc5, 0xfa, 0xd7, 0x14, 0x0b, 0xfa + }, + .len = 16, + }, + }, + .input = { + .data = { + 0xad, 0x42, 0x60, 0xe3, 0xcd, 0xc7, 0x6b, 0xcc, + 0x10, 0xc7, 0xb2, 0xc0, 0x6b, 0x80, 0xb3, 0xbe, + 0x94, 0x82, 0x58, 0xe5, 0xef, 0x20, 0xc5, 0x08, + 0xa8, 0x1f, 0x51, 0xe9, 0x6a, 0x51, 0x83, 0x88 + }, + .len = 32, + }, + .key = { + .data = { + 0x37, 0xcc, 0xdb, 0xa1, 0xd9, 0x29, 0xd6, 0x43, + 0x6c, 0x16, 0xbb, 0xa5, 0xb5, 0xff, 0x34, 0xde, + 0xec, 0x88, 0xed, 0x7d, 0xf3, 0xd1, 0x5d, 0x0f, + 0x4d, 0xdf, 0x80, 0xc0, 0xc7, 0x31, 0xee, 0x1f + }, + .len = 32, + }, + .output = { + .data = { + 0x3b, 0x33, 0x5f, 0x8b, 0x08, 0xd3, 0x3c, 0xcd, + 0xca, 0xd2, 0x28, 0xa7, 0x47, 0x00, 0xf1, 0x00, + 0x75, 0x42, 0xa4, 0xd1, 0xe7, 0xfc, 0x1e, 0xbe, + 0x3f, 0x44, 0x7f, 0xe7, 0x1a, 0xf2, 0x98, 0x16 + }, + .len = 32, + }, + .digest = { + .data = { + 0x1f, 0xbf, 0x49, 0xcc, 0x46, 0xf4, 0x58, 0xbf, + 0x6e, 0x88, 0xf6, 0x37, 0x09, 0x75, 0xe6, 0xd4 + }, + .len = 16, + }, +}; + + +/* <-- AES CTR --> */ +static struct fips_dev_self_test_vector +SELF_TEST_AES128_CTR_test_vector = { + .name = "SELF_TEST_AES128_CTR_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + + .iv = { + .data = { + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF + }, + .len = 16, + }, + .cipher = { + .algo = RTE_CRYPTO_CIPHER_AES_CTR, + }, + .input = { + .data = { + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + }, + .len = 32, + }, + .key = { + .data = { + 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C + }, + .len = 16, + }, + .output = { + .data = { + 0x87, 0x4D, 0x61, 0x91, 0xB6, 0x20, 0xE3, 0x26, + 0x1B, 0xEF, 0x68, 0x64, 0x99, 0x0D, 0xB6, 0xCE, + 0x98, 0x06, 0xF6, 0x6B, 0x79, 0x70, 0xFD, 0xFF, + 0x86, 0x17, 0x18, 0x7B, 0xB9, 0xFF, 0xFD, 0xFF, + }, + .len = 32, + }, +}; + +static struct fips_dev_self_test_vector +SELF_TEST_AES192_CTR_test_vector = { + .name = "SELF_TEST_AES192_CTR_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + + .iv = { + .data = { + 0x3F, 0x69, 0xA8, 0xCD, 0xE8, 0xF0, 0xEF, 0x40, + 0xB8, 0x7A, 0x4B, 0xED, 0x2B, 0xAF, 0xBF, 0x57 + }, + .len = 16, + }, + .cipher = { + .algo = RTE_CRYPTO_CIPHER_AES_CTR, + }, + .input = { + .data = { + 0x01, 0x0F, 0x10, 0x1F, 0x20, 0x1C, 0x0E, 0xB8, + 0xFB, 0x5C, 0xCD, 0xCC, 0x1F, 0xF9, 0xAF, 0x0B, + 0x95, 0x03, 0x74, 0x99, 0x49, 0xE7, 0x62, 0x55, + 0xDA, 0xEA, 0x13, 0x20, 0x1D, 0xC6, 0xCC, 0xCC, + }, + .len = 32, + }, + .key = { + .data = { + 0xCB, 0xC5, 0xED, 0x5B, 0xE7, 0x7C, 0xBD, 0x8C, + 0x50, 0xD9, 0x30, 0xF2, 0xB5, 0x6A, 0x0E, 0x5F, + 0xAA, 0xAE, 0xAD, 0xA2, 0x1F, 0x49, 0x52, 0xD4 + }, + .len = 24, + }, + .output = { + .data = { + 0x4A, 0x6C, 0xC8, 0xCC, 0x96, 0x2A, 0x13, 0x84, + 0x1C, 0x36, 0x88, 0xE9, 0xE5, 0x94, 0x70, 0xB2, + 0x14, 0x5B, 0x13, 0x80, 0xEA, 0xD8, 0x8D, 0x37, + 0xFD, 0x70, 0xA8, 0x83, 0xE8, 0x2B, 0x88, 0x1E, + }, + .len = 32, + }, +}; + +static struct fips_dev_self_test_vector +SELF_TEST_AES256_CTR_test_vector = { + .name = "SELF_TEST_AES256_CTR_test_vector", + .operation_type = RTE_CRYPTO_SYM_XFORM_CIPHER, + + .iv = { + .data = { + 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, + 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF + }, + .len = 16, + }, + .cipher = { + .algo = RTE_CRYPTO_CIPHER_AES_CTR, + }, + .input = { + .data = { + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + }, + .len = 32, + }, + .key = { + .data = { + 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 + }, + .len = 32, + }, + .output = { + .data = { + 0x60, 0x1E, 0xC3, 0x13, 0x77, 0x57, 0x89, 0xA5, + 0xB7, 0xA7, 0xF5, 0x04, 0xBB, 0xF3, 0xD2, 0x28, + 0xF4, 0x43, 0xE3, 0xCA, 0x4D, 0x62, 0xB5, 0x9A, + 0xCA, 0x84, 0xE9, 0x90, 0xCA, 0xCA, 0xF5, 0xC5, + }, + .len = 32, + }, +}; + + +struct fips_dev_self_test_vector +*self_test_vectors[] = { + &SELF_TEST_AES128_CBC_test_vector, + &SELF_TEST_AES192_CBC_test_vector, + &SELF_TEST_AES256_CBC_test_vector, + &SELF_TEST_3DES_2KEY_CBC_test_vector, + &SELF_TEST_3DES_3KEY_CBC_test_vector, + &SELF_TEST_AES128_CCM_test_vector, + &SELF_TEST_SHA1_HMAC_test_vector, + &SELF_TEST_SHA224_HMAC_test_vector, + &SELF_TEST_SHA256_HMAC_test_vector, + &SELF_TEST_SHA384_HMAC_test_vector, + &SELF_TEST_SHA512_HMAC_test_vector, + &SELF_TEST_AES_CMAC_test_vector, + &SELF_TEST_AES128_GCM_encrypt_test_vector, + &SELF_TEST_AES192_GCM_encrypt_test_vector, + &SELF_TEST_AES256_GCM_encrypt_test_vector, + &SELF_TEST_AES128_CTR_test_vector, + &SELF_TEST_AES192_CTR_test_vector, + &SELF_TEST_AES256_CTR_test_vector, +}; + +struct fips_dev_auto_test_env { + struct rte_mempool *mpool; + struct rte_mempool *op_pool; + struct rte_mempool *sess_pool; + struct rte_mempool *sess_priv_pool; + struct rte_mbuf *mbuf; + struct rte_crypto_op *op; +}; + +typedef int (*fips_dev_self_test_prepare_xform_t)(uint8_t, + struct rte_crypto_sym_xform *, + struct fips_dev_self_test_vector *, + uint32_t, uint8_t *, + uint32_t); + +typedef int (*fips_dev_self_test_prepare_op_t)(struct rte_crypto_op *, + struct rte_mbuf *, struct rte_cryptodev_sym_session *, + uint32_t, struct fips_dev_self_test_vector *); + +typedef int (*fips_dev_self_test_check_result_t)(struct rte_crypto_op *, + struct fips_dev_self_test_vector *, uint32_t); + +struct fips_dev_self_test_ops { + enum rte_crypto_sym_xform_type last_operation_type; + fips_dev_self_test_prepare_xform_t prepare_xform; + fips_dev_self_test_prepare_op_t prepare_op; + fips_dev_self_test_check_result_t check_result; +}; + +static int +prepare_cipher_xform(uint8_t dev_id, + struct rte_crypto_sym_xform *xform, + struct fips_dev_self_test_vector *vec, + uint32_t dir, + uint8_t *key, + uint32_t neg_test) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher; + + memset(xform, 0, sizeof(*xform)); + + /** negative test, key is xored */ + if (neg_test) { + uint32_t i; + + for (i = 0; i < vec->key.len; i++) + key[i] ^= vec->key.data[i]; + } else + memcpy(key, vec->key.data, vec->key.len); + + xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER; + + cipher_xform->algo = vec->cipher.algo; + cipher_xform->op = (dir == self_test_dir_enc_auth_gen) ? + RTE_CRYPTO_CIPHER_OP_ENCRYPT : + RTE_CRYPTO_CIPHER_OP_DECRYPT; + cipher_xform->key.data = key; + cipher_xform->key.length = vec->key.len; + cipher_xform->iv.length = vec->iv.len; + cipher_xform->iv.offset = IV_OFF; + + cap_idx.algo.cipher = cipher_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_CIPHER; + + cap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx); + if (!cap) { + RTE_LOG(ERR, PMD, "Failed to get capability for cdev %u\n", + dev_id); + return -EACCES; + } + + if (rte_cryptodev_sym_capability_check_cipher(cap, + cipher_xform->key.length, + cipher_xform->iv.length) != 0) { + RTE_LOG(ERR, PMD, "PMD %s key length %u IV length %u\n", + rte_cryptodev_name_get(dev_id), + cipher_xform->key.length, + cipher_xform->iv.length); + return -EACCES; + } + + return 0; +} + +static int +prepare_auth_xform(uint8_t dev_id, + struct rte_crypto_sym_xform *xform, + struct fips_dev_self_test_vector *vec, + uint32_t dir, + uint8_t *key, + uint32_t neg_test) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_auth_xform *auth_xform = &xform->auth; + + memset(xform, 0, sizeof(*xform)); + + /** negative test, key is xored */ + if (neg_test) { + uint32_t i; + + for (i = 0; i < vec->key.len; i++) + key[i] ^= vec->key.data[i]; + } else + memcpy(key, vec->key.data, vec->key.len); + + xform->type = RTE_CRYPTO_SYM_XFORM_AUTH; + + auth_xform->algo = vec->auth.algo; + auth_xform->op = (dir == self_test_dir_enc_auth_gen) ? + RTE_CRYPTO_AUTH_OP_GENERATE : + RTE_CRYPTO_AUTH_OP_VERIFY; + auth_xform->digest_length = vec->digest.len; + auth_xform->key.data = key; + auth_xform->key.length = vec->key.len; + + cap_idx.algo.auth = auth_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH; + + cap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx); + if (!cap) { + RTE_LOG(ERR, PMD, "Failed to get capability for cdev %u\n", + dev_id); + return -EACCES; + } + + if (rte_cryptodev_sym_capability_check_auth(cap, + auth_xform->key.length, + auth_xform->digest_length, 0) != 0) { + RTE_LOG(ERR, PMD, "PMD %s key length %u Digest length %u\n", + rte_cryptodev_name_get(dev_id), + auth_xform->key.length, + auth_xform->digest_length); + return -EACCES; + } + + return 0; +} + +static int +prepare_aead_xform(uint8_t dev_id, + struct rte_crypto_sym_xform *xform, + struct fips_dev_self_test_vector *vec, + uint32_t dir, + uint8_t *key, + uint32_t neg_test) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_aead_xform *aead_xform = &xform->aead; + + memset(xform, 0, sizeof(*xform)); + + /** negative test, key is xored */ + if (neg_test) { + uint32_t i; + + for (i = 0; i < vec->key.len; i++) + key[i] ^= vec->key.data[i]; + } else + memcpy(key, vec->key.data, vec->key.len); + + xform->type = RTE_CRYPTO_SYM_XFORM_AEAD; + + aead_xform->algo = vec->aead.algo; + aead_xform->op = (dir == self_test_dir_enc_auth_gen) ? + RTE_CRYPTO_AEAD_OP_ENCRYPT : + RTE_CRYPTO_AEAD_OP_DECRYPT; + aead_xform->aad_length = vec->aead.aad.len; + aead_xform->digest_length = vec->digest.len; + aead_xform->iv.offset = IV_OFF; + aead_xform->iv.length = vec->iv.len; + aead_xform->key.data = key; + aead_xform->key.length = vec->key.len; + + cap_idx.algo.aead = aead_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD; + + cap = rte_cryptodev_sym_capability_get(dev_id, &cap_idx); + if (!cap) { + RTE_LOG(ERR, PMD, "Failed to get capability for cdev %u\n", + dev_id); + return -EACCES; + } + + if (rte_cryptodev_sym_capability_check_aead(cap, + aead_xform->key.length, + aead_xform->digest_length, aead_xform->aad_length, + aead_xform->iv.length) != 0) { + RTE_LOG(ERR, PMD, + "PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n", + rte_cryptodev_name_get(dev_id), + aead_xform->key.length, + aead_xform->digest_length, + aead_xform->aad_length, + aead_xform->iv.length); + return -EACCES; + } + + return 0; +} + +static int +prepare_cipher_op(struct rte_crypto_op *op, + struct rte_mbuf *mbuf, + struct rte_cryptodev_sym_session *session, + uint32_t dir, + struct fips_dev_self_test_vector *vec) +{ + struct rte_crypto_sym_op *sym = op->sym; + uint8_t *iv = rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFF); + uint8_t *dst; + const uint8_t *src; + uint32_t len; + + if (dir == self_test_dir_enc_auth_gen) { + src = vec->input.data; + len = vec->input.len; + } else { + src = vec->output.data; + len = vec->output.len; + } + + sym->cipher.data.offset = 0; + memcpy(iv, vec->iv.data, vec->iv.len); + + dst = (uint8_t *)rte_pktmbuf_append(mbuf, len); + if (!dst) { + RTE_LOG(ERR, PMD, "Error %i: MBUF too small\n", -ENOMEM); + return -ENOMEM; + } + + memcpy(dst, src, len); + + sym->cipher.data.length = len; + + rte_crypto_op_attach_sym_session(op, session); + + return 0; +} + +static int +prepare_auth_op(struct rte_crypto_op *op, + struct rte_mbuf *mbuf, + struct rte_cryptodev_sym_session *session, + uint32_t dir, + struct fips_dev_self_test_vector *vec) +{ + struct rte_crypto_sym_op *sym = op->sym; + uint8_t *dst; + + if (vec->input.len + vec->digest.len > RTE_MBUF_MAX_NB_SEGS) { + RTE_LOG(ERR, PMD, "Error %i: Test data too long (%u).\n", + -ENOMEM, vec->input.len + vec->digest.len); + return -ENOMEM; + } + + sym->auth.data.offset = 0; + + dst = (uint8_t *)rte_pktmbuf_append(mbuf, vec->input.len + + vec->digest.len); + if (!dst) { + RTE_LOG(ERR, PMD, "Error %i: MBUF too small\n", -ENOMEM); + return -ENOMEM; + } + + memcpy(dst, vec->input.data, vec->input.len); + sym->auth.data.length = vec->input.len; + sym->auth.digest.data = dst + vec->input.len; + sym->auth.digest.phys_addr = rte_pktmbuf_iova_offset(mbuf, + vec->input.len); + + if (dir == self_test_dir_dec_auth_verify) + memcpy(dst + vec->input.len, vec->digest.data, vec->digest.len); + + rte_crypto_op_attach_sym_session(op, session); + + return 0; +} + +static int +prepare_aead_op(struct rte_crypto_op *op, + struct rte_mbuf *mbuf, + struct rte_cryptodev_sym_session *session, + uint32_t dir, + struct fips_dev_self_test_vector *vec) +{ + struct rte_crypto_sym_op *sym = op->sym; + uint8_t *iv = rte_crypto_op_ctod_offset(op, uint8_t *, IV_OFF); + uint8_t *dst; + const uint8_t *src; + uint32_t len; + + if (dir == self_test_dir_enc_auth_gen) { + len = vec->input.len; + src = vec->input.data; + } else { + len = vec->output.len; + src = vec->output.data; + } + + if (vec->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) + memcpy(iv + 1, vec->iv.data, vec->iv.len); + else + memcpy(iv, vec->iv.data, vec->iv.len); + + if (len + vec->digest.len > RTE_MBUF_MAX_NB_SEGS) { + RTE_LOG(ERR, PMD, "Error %i: Test data too long (%u).\n", + -ENOMEM, len + vec->digest.len); + return -ENOMEM; + } + + dst = (uint8_t *)rte_pktmbuf_append(mbuf, RTE_ALIGN_CEIL(len + + vec->digest.len, 16)); + if (!dst) { + RTE_LOG(ERR, PMD, "Error %i: MBUF too small\n", -ENOMEM); + return -ENOMEM; + } + + sym->m_src = mbuf; + sym->aead.data.length = len; + sym->aead.data.offset = 0; + memcpy(dst, src, len); + + sym->aead.digest.data = dst + vec->input.len; + sym->aead.digest.phys_addr = rte_pktmbuf_iova_offset(mbuf, + vec->input.len); + if (dir == self_test_dir_dec_auth_verify) + memcpy(sym->aead.digest.data, vec->digest.data, vec->digest.len); + + len = (vec->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) ? + (vec->aead.aad.len + AES_CCM_AAD_PAD_SIZE) : + vec->aead.aad.len; + + dst = rte_malloc(NULL, len, 16); + if (!dst) { + RTE_LOG(ERR, PMD, "Error %i: Not enough memory\n", -ENOMEM); + return -ENOMEM; + } + + sym->aead.aad.data = dst; + sym->aead.aad.phys_addr = rte_malloc_virt2iova(dst); + if (vec->aead.algo == RTE_CRYPTO_AEAD_AES_CCM) + memcpy(dst, vec->aead.aad.data, + vec->aead.aad.len + AES_CCM_AAD_PAD_SIZE); + else + memcpy(dst, vec->aead.aad.data, + vec->aead.aad.len); + + rte_crypto_op_attach_sym_session(op, session); + + return 0; +} + +static int +check_cipher_result(struct rte_crypto_op *op, + struct fips_dev_self_test_vector *vec, + uint32_t dir) +{ + struct rte_mbuf *mbuf = op->sym->m_src; + uint8_t *data; + const uint8_t *src; + uint32_t len, src_len; + int ret; + + if (dir == self_test_dir_enc_auth_gen) { + src = vec->output.data; + src_len = vec->output.len; + } else { + src = vec->input.data; + src_len = vec->input.len; + } + + GET_MBUF_DATA(data, len, mbuf); + if (!data && !len) + return -1; + + ret = memcmp(data, src, src_len); + if (ret != 0) + return -1; + + return 0; +} + +static int +check_auth_result(struct rte_crypto_op *op, + struct fips_dev_self_test_vector *vec, + uint32_t dir) +{ + struct rte_mbuf *mbuf = op->sym->m_src; + uint8_t *data; + uint32_t len; + int ret; + + GET_MBUF_DATA(data, len, mbuf); + if (!data && !len) + return -1; + + if (dir == self_test_dir_enc_auth_gen) { + data += vec->input.len; + ret = memcmp(data, vec->digest.data, vec->digest.len); + if (ret != 0) + return -1; + } + + return 0; +} + +static int +check_aead_result(struct rte_crypto_op *op, + struct fips_dev_self_test_vector *vec, + uint32_t dir) +{ + struct rte_mbuf *mbuf = op->sym->m_src; + uint8_t *data; + const uint8_t *src; + uint32_t len, src_len; + int ret; + + if (op->sym->aead.aad.data) + rte_free(op->sym->aead.aad.data); + + if (dir == self_test_dir_enc_auth_gen) { + src = vec->output.data; + src_len = vec->output.len; + } else { + src = vec->input.data; + src_len = vec->input.len; + } + + GET_MBUF_DATA(data, len, mbuf); + if (!data && !len) + return -1; + + ret = memcmp(data, src, src_len); + if (ret != 0) + return -1; + + if (dir == self_test_dir_enc_auth_gen) { + data += src_len; + ret = memcmp(data, vec->digest.data, vec->digest.len); + if (ret != 0) + return -1; + } + + return 0; +} + +static void +init_test_op(struct fips_dev_self_test_ops *test_ops, + struct fips_dev_self_test_vector *vec) +{ + if (test_ops->last_operation_type == vec->operation_type) + return; + + switch (vec->operation_type) { + case RTE_CRYPTO_SYM_XFORM_CIPHER: + test_ops->prepare_xform = prepare_cipher_xform; + test_ops->prepare_op = prepare_cipher_op; + test_ops->check_result = check_cipher_result; + break; + case RTE_CRYPTO_SYM_XFORM_AUTH: + test_ops->prepare_xform = prepare_auth_xform; + test_ops->prepare_op = prepare_auth_op; + test_ops->check_result = check_auth_result; + break; + case RTE_CRYPTO_SYM_XFORM_AEAD: + test_ops->prepare_xform = prepare_aead_xform; + test_ops->prepare_op = prepare_aead_op; + test_ops->check_result = check_aead_result; + break; + default: + break; + } + + test_ops->last_operation_type = vec->operation_type; +} + +static int +run_single_test(uint8_t dev_id, + struct fips_dev_self_test_vector *vec, + const struct fips_dev_self_test_ops *test_ops, + struct fips_dev_auto_test_env *env, + uint32_t dir, + uint32_t negative_test) +{ + struct rte_crypto_sym_xform xform; + struct rte_cryptodev_sym_session *sess; + uint16_t n_deqd; + uint8_t key[256]; + int ret; + + __rte_crypto_op_reset(env->op, RTE_CRYPTO_OP_TYPE_SYMMETRIC); + rte_pktmbuf_reset(env->mbuf); + env->op->sym->m_src = env->mbuf; + + ret = test_ops->prepare_xform(dev_id, &xform, vec, dir, key, + negative_test); + if (ret < 0) { + RTE_LOG(ERR, PMD, "Error %i: Prepare Xform\n", ret); + return ret; + } + + sess = rte_cryptodev_sym_session_create(env->sess_pool); + if (!sess) + return -ENOMEM; + + ret = rte_cryptodev_sym_session_init(dev_id, + sess, &xform, env->sess_priv_pool); + if (ret < 0) { + RTE_LOG(ERR, PMD, "Error %i: Init session\n", ret); + return ret; + } + + ret = test_ops->prepare_op(env->op, env->mbuf, sess, dir, vec); + if (ret < 0) { + RTE_LOG(ERR, PMD, "Error %i: Prepare op\n", ret); + return ret; + } + + if (rte_cryptodev_enqueue_burst(dev_id, 0, &env->op, 1) < 1) { + RTE_LOG(ERR, PMD, "Error: Failed enqueue\n"); + return ret; + } + + do { + struct rte_crypto_op *deqd_op; + + n_deqd = rte_cryptodev_dequeue_burst(dev_id, 0, &deqd_op, + 1); + } while (n_deqd == 0); + + rte_cryptodev_sym_session_clear(dev_id, sess); + rte_cryptodev_sym_session_free(sess); + + if (env->op->status != RTE_CRYPTO_OP_STATUS_SUCCESS) + return -1; + + return test_ops->check_result(env->op, vec, dir); +} + + +static void +fips_dev_auto_test_uninit(uint8_t dev_id, + struct fips_dev_auto_test_env *env) +{ + struct rte_cryptodev *dev = rte_cryptodev_pmd_get_dev(dev_id); + uint32_t i; + + if (!dev) + return; + + if (env->mbuf) + rte_pktmbuf_free(env->mbuf); + if (env->op) + rte_crypto_op_free(env->op); + if (env->mpool) + rte_mempool_free(env->mpool); + if (env->op_pool) + rte_mempool_free(env->op_pool); + if (env->sess_pool) + rte_mempool_free(env->sess_pool); + if (env->sess_priv_pool) + rte_mempool_free(env->sess_priv_pool); + + if (dev->data->dev_started) + rte_cryptodev_stop(dev_id); + + if (dev->data->nb_queue_pairs) { + for (i = 0; i < dev->data->nb_queue_pairs; i++) + (*dev->dev_ops->queue_pair_release)(dev, i); + dev->data->nb_queue_pairs = 0; + rte_free(dev->data->queue_pairs); + dev->data->queue_pairs = NULL; + } +} + +static int +fips_dev_auto_test_init(uint8_t dev_id, struct fips_dev_auto_test_env *env) +{ + struct rte_cryptodev_config conf = {rte_cryptodev_socket_id(dev_id), 1}; + struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL}; + uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(dev_id); + char name[128]; + int ret; + + ret = rte_cryptodev_configure(dev_id, &conf); + if (ret < 0) + return ret; + + memset(name, 0, 128); + snprintf(name, 128, "%s%u", "SELF_TEST_MEMPOOL", dev_id); + + memset(env, 0, sizeof(*env)); + + env->mpool = rte_pktmbuf_pool_create(name, 128, 0, 0, + UINT16_MAX, rte_cryptodev_socket_id(dev_id)); + if (!env->mpool) { + ret = -ENOMEM; + goto error_exit; + } + + memset(name, 0, 128); + snprintf(name, 128, "%s%u", "SELF_TEST_OP_POOL", dev_id); + + env->op_pool = rte_crypto_op_pool_create( + name, + RTE_CRYPTO_OP_TYPE_SYMMETRIC, + 16, 0, + 16, + rte_socket_id()); + if (!env->op_pool) { + ret = -ENOMEM; + goto error_exit; + } + + memset(name, 0, 128); + snprintf(name, 128, "%s%u", "SELF_TEST_SESS_POOL", dev_id); + + env->sess_pool = rte_cryptodev_sym_session_pool_create(name, + 128, 0, 0, 0, rte_cryptodev_socket_id(dev_id)); + if (!env->sess_pool) { + ret = -ENOMEM; + goto error_exit; + } + + memset(name, 0, 128); + snprintf(name, 128, "%s%u", "SELF_TEST_SESS_PRIV_POOL", dev_id); + + env->sess_priv_pool = rte_mempool_create(name, + 128, sess_sz, 0, 0, NULL, NULL, NULL, + NULL, rte_cryptodev_socket_id(dev_id), 0); + if (!env->sess_priv_pool) { + ret = -ENOMEM; + goto error_exit; + } + + qp_conf.mp_session = env->sess_pool; + qp_conf.mp_session_private = env->sess_priv_pool; + + ret = rte_cryptodev_queue_pair_setup(dev_id, 0, &qp_conf, + rte_cryptodev_socket_id(dev_id)); + if (ret < 0) + goto error_exit; + + env->mbuf = rte_pktmbuf_alloc(env->mpool); + if (!env->mbuf) { + ret = -ENOMEM; + goto error_exit; + } + + env->op = rte_crypto_op_alloc(env->op_pool, + RTE_CRYPTO_OP_TYPE_SYMMETRIC); + if (!env->op) { + ret = -ENOMEM; + goto error_exit; + } + + ret = rte_cryptodev_start(dev_id); + if (ret < 0) + goto error_exit; + + + return 0; + +error_exit: + + fips_dev_auto_test_uninit(dev_id, env); + + return ret; +} + +int +fips_dev_self_test(uint8_t dev_id, + struct fips_dev_broken_test_config *config) +{ + struct fips_dev_self_test_ops test_ops = {0}; + struct fips_dev_auto_test_env env; + uint32_t i, j, negative_test; + int ret; + + ret = fips_dev_auto_test_init(dev_id, &env); + if (ret < 0) { + RTE_LOG(ERR, PMD, "Failed to init self-test for PMD %u\n", + dev_id); + return ret; + } + + for (i = 0; i < RTE_DIM(self_test_vectors); i++) { + struct fips_dev_self_test_vector *vec = + self_test_vectors[i]; + + init_test_op(&test_ops, vec); + + for (j = 0; j < self_test_dir_max; j++) { + if (!config) + negative_test = 0; + else { + if ((config->expect_fail_test_idx == i) && + (config->expect_fail_dir == j)) + negative_test = 1; + else + negative_test = 0; + } + + RTE_LOG(INFO, PMD, "Testing (ID %u) %s %s%s...\n", + i, + vec->name, + j == self_test_dir_enc_auth_gen ? + "Encrypt" : "Decrypt", + negative_test ? " (Expect Fail)" : ""); + + ret = run_single_test(dev_id, vec, &test_ops, + &env, j, negative_test); + switch (ret) { + case 0: + if (!negative_test) + break; + ret = -1; + RTE_LOG(ERR, PMD, "PMD %u Failed test %s %s\n", + dev_id, vec->name, + j == self_test_dir_enc_auth_gen ? + "Encrypt" : "Decrypt"); + goto error_exit; + case -EACCES: + RTE_LOG(ERR, PMD, "Not supported by %s. Skip\n", + rte_cryptodev_name_get(dev_id)); + ret = 0; + break; + default: + RTE_LOG(ERR, PMD, "PMD %u Failed test %s %s\n", + dev_id, vec->name, + j == self_test_dir_enc_auth_gen ? + "Encrypt" : "Decrypt"); + goto error_exit; + } + } + } + +error_exit: + fips_dev_auto_test_uninit(dev_id, &env); + + if (ret == 0) { + RTE_LOG(INFO, PMD, "PMD %u finished self-test successfully\n", + dev_id); + } + + return ret; +} diff --git a/src/seastar/dpdk/examples/fips_validation/fips_dev_self_test.h b/src/seastar/dpdk/examples/fips_validation/fips_dev_self_test.h new file mode 100644 index 000000000..421599de1 --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_dev_self_test.h @@ -0,0 +1,25 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#ifndef _CRYPTO_PMD_SELF_TEST_H_ +#define _CRYPTO_PMD_SELF_TEST_H_ + +#include <rte_crypto_sym.h> + +enum fips_dev_self_test_dir { + self_test_dir_enc_auth_gen = 0, + self_test_dir_dec_auth_verify, + self_test_dir_max +}; + +struct fips_dev_broken_test_config { + uint32_t expect_fail_test_idx; + enum fips_dev_self_test_dir expect_fail_dir; +}; + +int +fips_dev_self_test(uint8_t dev_id, + struct fips_dev_broken_test_config *config); + +#endif /* _CRYPTO_PMD_SELF_TEST_H_ */ diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation.c b/src/seastar/dpdk/examples/fips_validation/fips_validation.c new file mode 100644 index 000000000..8d43b267e --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation.c @@ -0,0 +1,622 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <stdio.h> +#include <string.h> + +#include <rte_string_fns.h> +#include <rte_cryptodev.h> +#include <rte_malloc.h> + +#include "fips_validation.h" + +#define skip_white_spaces(pos) \ +({ \ + __typeof__(pos) _p = (pos); \ + for ( ; isspace(*_p); _p++) \ + ; \ + _p; \ +}) + +static int +get_file_line(void) +{ + FILE *fp = info.fp_rd; + char *line = info.one_line_text; + int ret; + uint32_t loc = 0; + + memset(line, 0, MAX_LINE_CHAR); + while ((ret = fgetc(fp)) != EOF) { + char c = (char)ret; + + if (loc >= MAX_LINE_CHAR - 1) + return -ENOMEM; + if (c == '\n') + break; + line[loc++] = c; + } + + if (ret == EOF) + return -EOF; + + return 0; +} + +int +fips_test_fetch_one_block(void) +{ + size_t size; + int ret = 0; + uint32_t i; + + for (i = 0; i < info.nb_vec_lines; i++) { + free(info.vec[i]); + info.vec[i] = NULL; + } + + i = 0; + do { + if (i >= MAX_LINE_PER_VECTOR) { + ret = -ENOMEM; + goto error_exit; + } + + ret = get_file_line(); + size = strlen(info.one_line_text); + if (size == 0) + break; + + info.vec[i] = calloc(1, size + 5); + if (info.vec[i] == NULL) + goto error_exit; + + strlcpy(info.vec[i], info.one_line_text, size + 1); + i++; + } while (ret == 0); + + info.nb_vec_lines = i; + + return ret; + +error_exit: + for (i = 0; i < MAX_LINE_PER_VECTOR; i++) + if (info.vec[i] != NULL) { + free(info.vec[i]); + info.vec[i] = NULL; + } + + info.nb_vec_lines = 0; + + return -ENOMEM; +} + +static int +fips_test_parse_header(void) +{ + uint32_t i; + char *tmp; + int ret; + int algo_parsed = 0; + time_t t = time(NULL); + struct tm *tm_now = localtime(&t); + + ret = fips_test_fetch_one_block(); + if (ret < 0) + return ret; + + for (i = 0; i < info.nb_vec_lines; i++) { + if (!algo_parsed) { + if (strstr(info.vec[i], "AESVS")) { + algo_parsed = 1; + info.algo = FIPS_TEST_ALGO_AES; + ret = parse_test_aes_init(); + if (ret < 0) + return ret; + } else if (strstr(info.vec[i], "GCM")) { + algo_parsed = 1; + info.algo = FIPS_TEST_ALGO_AES_GCM; + ret = parse_test_gcm_init(); + if (ret < 0) + return ret; + } else if (strstr(info.vec[i], "CMAC")) { + algo_parsed = 1; + info.algo = FIPS_TEST_ALGO_AES_CMAC; + ret = parse_test_cmac_init(); + if (ret < 0) + return 0; + } else if (strstr(info.vec[i], "CCM")) { + algo_parsed = 1; + info.algo = FIPS_TEST_ALGO_AES_CCM; + ret = parse_test_ccm_init(); + if (ret < 0) + return 0; + } else if (strstr(info.vec[i], "HMAC")) { + algo_parsed = 1; + info.algo = FIPS_TEST_ALGO_HMAC; + ret = parse_test_hmac_init(); + if (ret < 0) + return ret; + } else if (strstr(info.vec[i], "TDES")) { + algo_parsed = 1; + info.algo = FIPS_TEST_ALGO_TDES; + ret = parse_test_tdes_init(); + if (ret < 0) + return 0; + } else if (strstr(info.vec[i], "SHA-")) { + algo_parsed = 1; + info.algo = FIPS_TEST_ALGO_SHA; + ret = parse_test_sha_init(); + if (ret < 0) + return ret; + } + } + + tmp = strstr(info.vec[i], "# Config info for "); + if (tmp != NULL) { + fprintf(info.fp_wr, "%s%s\n", "# Config info for DPDK Cryptodev ", + info.device_name); + continue; + } + + tmp = strstr(info.vec[i], "# HMAC information for "); + if (tmp != NULL) { + fprintf(info.fp_wr, "%s%s\n", "# HMAC information for " + "DPDK Cryptodev ", + info.device_name); + continue; + } + + tmp = strstr(info.vec[i], "# Config Info for : "); + if (tmp != NULL) { + + fprintf(info.fp_wr, "%s%s\n", "# Config Info for DPDK Cryptodev : ", + info.device_name); + continue; + } + + tmp = strstr(info.vec[i], "# information for "); + if (tmp != NULL) { + + char tmp_output[128] = {0}; + + strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1); + + fprintf(info.fp_wr, "%s%s%s\n", tmp_output, + "information for DPDK Cryptodev ", + info.device_name); + continue; + } + + tmp = strstr(info.vec[i], " test information for "); + if (tmp != NULL) { + char tmp_output[128] = {0}; + + strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1); + + fprintf(info.fp_wr, "%s%s%s\n", tmp_output, + "test information for DPDK Cryptodev ", + info.device_name); + continue; + } + + tmp = strstr(info.vec[i], "\" information for \""); + if (tmp != NULL) { + char tmp_output[128] = {0}; + + strlcpy(tmp_output, info.vec[i], tmp - info.vec[i] + 1); + + fprintf(info.fp_wr, "%s%s%s\n", tmp_output, + "\" information for DPDK Cryptodev ", + info.device_name); + continue; + } + + if (i == info.nb_vec_lines - 1) { + /** update the time as current time, write to file */ + fprintf(info.fp_wr, "%s%s\n", "# Generated on ", + asctime(tm_now)); + continue; + } + + /* to this point, no field need to update, + * only copy to rsp file + */ + fprintf(info.fp_wr, "%s\n", info.vec[i]); + } + + return 0; +} + +static int +parse_file_type(const char *path) +{ + const char *tmp = path + strlen(path) - 3; + + if (strstr(tmp, REQ_FILE_PERFIX)) + info.file_type = FIPS_TYPE_REQ; + else if (strstr(tmp, RSP_FILE_PERFIX)) + info.file_type = FIPS_TYPE_RSP; + else if (strstr(path, FAX_FILE_PERFIX)) + info.file_type = FIPS_TYPE_FAX; + else + return -EINVAL; + + return 0; +} + +int +fips_test_init(const char *req_file_path, const char *rsp_file_path, + const char *device_name) +{ + if (strcmp(req_file_path, rsp_file_path) == 0) { + RTE_LOG(ERR, USER1, "File paths cannot be the same\n"); + return -EINVAL; + } + + fips_test_clear(); + + info.algo = FIPS_TEST_ALGO_MAX; + if (parse_file_type(req_file_path) < 0) { + RTE_LOG(ERR, USER1, "File %s type not supported\n", + req_file_path); + return -EINVAL; + } + + info.fp_rd = fopen(req_file_path, "r"); + if (!info.fp_rd) { + RTE_LOG(ERR, USER1, "Cannot open file %s\n", req_file_path); + return -EINVAL; + } + + info.fp_wr = fopen(rsp_file_path, "w"); + if (!info.fp_wr) { + RTE_LOG(ERR, USER1, "Cannot open file %s\n", rsp_file_path); + return -EINVAL; + } + + info.one_line_text = calloc(1, MAX_LINE_CHAR); + if (!info.one_line_text) { + RTE_LOG(ERR, USER1, "Insufficient memory\n"); + return -ENOMEM; + } + + strlcpy(info.device_name, device_name, sizeof(info.device_name)); + + if (fips_test_parse_header() < 0) { + RTE_LOG(ERR, USER1, "Failed parsing header\n"); + return -1; + } + + return 0; +} + +void +fips_test_clear(void) +{ + if (info.fp_rd) + fclose(info.fp_rd); + if (info.fp_wr) + fclose(info.fp_wr); + if (info.one_line_text) + free(info.one_line_text); + if (info.nb_vec_lines) { + uint32_t i; + + for (i = 0; i < info.nb_vec_lines; i++) + free(info.vec[i]); + } + + memset(&info, 0, sizeof(info)); +} + +int +fips_test_parse_one_case(void) +{ + uint32_t i, j = 0; + uint32_t is_interim = 0; + int ret; + + if (info.interim_callbacks) { + for (i = 0; i < info.nb_vec_lines; i++) { + for (j = 0; info.interim_callbacks[j].key != NULL; j++) + if (strstr(info.vec[i], + info.interim_callbacks[j].key)) { + is_interim = 1; + + ret = info.interim_callbacks[j].cb( + info.interim_callbacks[j].key, + info.vec[i], + info.interim_callbacks[j].val); + if (ret < 0) + return ret; + } + } + } + + if (is_interim) { + for (i = 0; i < info.nb_vec_lines; i++) + fprintf(info.fp_wr, "%s\n", info.vec[i]); + fprintf(info.fp_wr, "\n"); + return 1; + } + + for (i = 0; i < info.nb_vec_lines; i++) { + for (j = 0; info.callbacks[j].key != NULL; j++) + if (strstr(info.vec[i], info.callbacks[j].key)) { + ret = info.callbacks[j].cb( + info.callbacks[j].key, + info.vec[i], info.callbacks[j].val); + if (ret < 0) + return ret; + break; + } + } + + return 0; +} + +void +fips_test_write_one_case(void) +{ + uint32_t i; + + for (i = 0; i < info.nb_vec_lines; i++) + fprintf(info.fp_wr, "%s\n", info.vec[i]); +} + +static int +parser_read_uint64_hex(uint64_t *value, const char *p) +{ + char *next; + uint64_t val; + + p = skip_white_spaces(p); + + val = strtoul(p, &next, 16); + if (p == next) + return -EINVAL; + + p = skip_white_spaces(next); + if (*p != '\0') + return -EINVAL; + + *value = val; + return 0; +} + +int +parser_read_uint8_hex(uint8_t *value, const char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64_hex(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT8_MAX) + return -ERANGE; + + *value = val; + return 0; +} + +int +parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val) +{ + struct fips_val tmp_val = {0}; + uint32_t len = val->len; + int ret; + + if (len == 0) { + if (val->val != NULL) { + rte_free(val->val); + val->val = NULL; + } + + return 0; + } + + ret = parse_uint8_hex_str(key, src, &tmp_val); + if (ret < 0) + return ret; + + if (tmp_val.len == val->len) { + val->val = tmp_val.val; + return 0; + } + + if (tmp_val.len < val->len) { + rte_free(tmp_val.val); + return -EINVAL; + } + + val->val = rte_zmalloc(NULL, val->len, 0); + if (!val->val) { + rte_free(tmp_val.val); + memset(val, 0, sizeof(*val)); + return -ENOMEM; + } + + memcpy(val->val, tmp_val.val, val->len); + rte_free(tmp_val.val); + + return 0; +} + +int +parse_uint8_hex_str(const char *key, char *src, struct fips_val *val) +{ + uint32_t len, j; + + src += strlen(key); + + len = strlen(src) / 2; + + if (val->val) { + rte_free(val->val); + val->val = NULL; + } + + val->val = rte_zmalloc(NULL, len, 0); + if (!val->val) + return -ENOMEM; + + for (j = 0; j < len; j++) { + char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'}; + + if (parser_read_uint8_hex(&val->val[j], byte) < 0) { + rte_free(val->val); + memset(val, 0, sizeof(*val)); + return -EINVAL; + } + } + + val->len = len; + + return 0; +} + +int +parser_read_uint32_val(const char *key, char *src, struct fips_val *val) +{ + char *data = src + strlen(key); + size_t data_len = strlen(data); + int ret; + + if (data[data_len - 1] == ']') { + char *tmp_data = calloc(1, data_len + 1); + + if (tmp_data == NULL) + return -ENOMEM; + + strlcpy(tmp_data, data, data_len); + + ret = parser_read_uint32(&val->len, tmp_data); + + free(tmp_data); + } else + ret = parser_read_uint32(&val->len, data); + + return ret; +} + +int +parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val) +{ + int ret; + + ret = parser_read_uint32_val(key, src, val); + + if (ret < 0) + return ret; + + val->len /= 8; + + return 0; +} + +int +writeback_hex_str(const char *key, char *dst, struct fips_val *val) +{ + char *str = dst; + uint32_t len; + + str += strlen(key); + + for (len = 0; len < val->len; len++) + snprintf(str + len * 2, 255, "%02x", val->val[len]); + + return 0; +} + +static int +parser_read_uint64(uint64_t *value, const char *p) +{ + char *next; + uint64_t val; + + p = skip_white_spaces(p); + if (!isdigit(*p)) + return -EINVAL; + + val = strtoul(p, &next, 10); + if (p == next) + return -EINVAL; + + p = next; + switch (*p) { + case 'T': + val *= 1024ULL; + /* fall through */ + case 'G': + val *= 1024ULL; + /* fall through */ + case 'M': + val *= 1024ULL; + /* fall through */ + case 'k': + case 'K': + val *= 1024ULL; + p++; + break; + } + + p = skip_white_spaces(p); + if (*p != '\0') + return -EINVAL; + + *value = val; + return 0; +} + +int +parser_read_uint32(uint32_t *value, char *p) +{ + uint64_t val = 0; + int ret = parser_read_uint64(&val, p); + + if (ret < 0) + return ret; + + if (val > UINT32_MAX) + return -EINVAL; + + *value = val; + return 0; +} + +void +parse_write_hex_str(struct fips_val *src) +{ + writeback_hex_str("", info.one_line_text, src); + + fprintf(info.fp_wr, "%s\n", info.one_line_text); +} + +int +update_info_vec(uint32_t count) +{ + const struct fips_test_callback *cb; + uint32_t i, j; + + if (!info.writeback_callbacks) + return -1; + + cb = &info.writeback_callbacks[0]; + + snprintf(info.vec[0], strlen(info.vec[0]) + 4, "%s%u", cb->key, count); + + for (i = 1; i < info.nb_vec_lines; i++) { + for (j = 1; info.writeback_callbacks[j].key != NULL; j++) { + cb = &info.writeback_callbacks[j]; + if (strstr(info.vec[i], cb->key)) { + cb->cb(cb->key, info.vec[i], cb->val); + break; + } + } + } + + return 0; +} diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation.h b/src/seastar/dpdk/examples/fips_validation/fips_validation.h new file mode 100644 index 000000000..b604db9ec --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation.h @@ -0,0 +1,248 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#ifndef _FIPS_VALIDATION_H_ +#define _FIPS_VALIDATION_H_ + +#define FIPS_PARSE_ERR(fmt, args) \ + RTE_LOG(ERR, USER1, "FIPS parse error" ## fmt ## "\n", ## args) + +#define ERR_MSG_SIZE 128 +#define MAX_CASE_LINE 15 +#define MAX_LINE_CHAR 204800 /*< max number of characters per line */ +#define MAX_NB_TESTS 10240 +#define MAX_BUF_SIZE 2048 +#define MAX_STRING_SIZE 64 +#define MAX_DIGEST_SIZE 64 + +#define POSITIVE_TEST 0 +#define NEGATIVE_TEST -1 + +#define REQ_FILE_PERFIX "req" +#define RSP_FILE_PERFIX "rsp" +#define FAX_FILE_PERFIX "fax" + +enum fips_test_algorithms { + FIPS_TEST_ALGO_AES = 0, + FIPS_TEST_ALGO_AES_GCM, + FIPS_TEST_ALGO_AES_CMAC, + FIPS_TEST_ALGO_AES_CCM, + FIPS_TEST_ALGO_HMAC, + FIPS_TEST_ALGO_TDES, + FIPS_TEST_ALGO_SHA, + FIPS_TEST_ALGO_MAX +}; + +enum file_types { + FIPS_TYPE_REQ = 1, + FIPS_TYPE_FAX, + FIPS_TYPE_RSP +}; + +enum fips_test_op { + FIPS_TEST_ENC_AUTH_GEN = 1, + FIPS_TEST_DEC_AUTH_VERIF, +}; + +#define MAX_LINE_PER_VECTOR 16 + +struct fips_val { + uint8_t *val; + uint32_t len; +}; + +struct fips_test_vector { + union { + struct { + struct fips_val key; + struct fips_val digest; + struct fips_val auth_aad; + struct fips_val aad; + } cipher_auth; + struct { + struct fips_val key; + struct fips_val digest; + struct fips_val aad; + } aead; + }; + + struct fips_val pt; + struct fips_val ct; + struct fips_val iv; + + enum rte_crypto_op_status status; +}; + +typedef int (*post_prcess_t)(struct fips_val *val); + +typedef int (*parse_callback_t)(const char *key, char *text, + struct fips_val *val); + +struct fips_test_callback { + const char *key; + parse_callback_t cb; + struct fips_val *val; +}; + +enum fips_aesavs_test_types { + AESAVS_TYPE_GFXBOX = 1, + AESAVS_TYPE_KEYSBOX, + AESAVS_TYPE_VARKEY, + AESAVS_TYPE_VARTXT, + AESAVS_TYPE_MMT, + AESAVS_TYPE_MCT, +}; + +enum fips_tdes_test_types { + TDES_INVERSE_PERMUTATION = 0, + TDES_PERMUTATION, + TDES_SUBSTITUTION_TABLE, + TDES_VARIABLE_KEY, + TDES_VARIABLE_TEXT, + TDES_KAT, + TDES_MCT, /* Monte Carlo (Modes) Test */ + TDES_MMT /* Multi block Message Test */ +}; + +enum fips_ccm_test_types { + CCM_VADT = 1, /* Variable Associated Data Test */ + CCM_VPT, /* Variable Payload Test */ + CCM_VNT, /* Variable Nonce Test */ + CCM_VTT, /* Variable Tag Test */ + CCM_DVPT, /* Decryption-Verification Process Test */ +}; + +enum fips_sha_test_types { + SHA_KAT = 0, + SHA_MCT +}; + +struct aesavs_interim_data { + enum fips_aesavs_test_types test_type; + uint32_t cipher_algo; + uint32_t key_len; +}; + +struct hmac_interim_data { + enum rte_crypto_auth_algorithm algo; +}; + +struct tdes_interim_data { + enum fips_tdes_test_types test_type; + uint32_t nb_keys; +}; + +struct ccm_interim_data { + enum fips_ccm_test_types test_type; + uint32_t aad_len; + uint32_t pt_len; + uint32_t digest_len; + uint32_t key_len; + uint32_t iv_len; +}; + +struct sha_interim_data { + enum fips_sha_test_types test_type; + enum rte_crypto_auth_algorithm algo; +}; + +struct fips_test_interim_info { + FILE *fp_rd; + FILE *fp_wr; + enum file_types file_type; + enum fips_test_algorithms algo; + char *one_line_text; + char *vec[MAX_LINE_PER_VECTOR]; + uint32_t nb_vec_lines; + char device_name[MAX_STRING_SIZE]; + + union { + struct aesavs_interim_data aes_data; + struct hmac_interim_data hmac_data; + struct tdes_interim_data tdes_data; + struct ccm_interim_data ccm_data; + struct sha_interim_data sha_data; + } interim_info; + + enum fips_test_op op; + + const struct fips_test_callback *callbacks; + const struct fips_test_callback *interim_callbacks; + const struct fips_test_callback *writeback_callbacks; + + post_prcess_t parse_writeback; + post_prcess_t kat_check; +}; + +extern struct fips_test_vector vec; +extern struct fips_test_interim_info info; + +int +fips_test_init(const char *req_file_path, const char *rsp_file_path, + const char *device_name); + +void +fips_test_clear(void); + +int +fips_test_fetch_one_block(void); + +int +fips_test_parse_one_case(void); + +void +fips_test_write_one_case(void); + +int +parse_test_aes_init(void); + +int +parse_test_tdes_init(void); + +int +parse_test_hmac_init(void); + +int +parse_test_gcm_init(void); + +int +parse_test_cmac_init(void); + +int +parse_test_ccm_init(void); + +int +parse_test_sha_init(void); + +int +parser_read_uint8_hex(uint8_t *value, const char *p); + +int +parse_uint8_hex_str(const char *key, char *src, struct fips_val *val); + +int +parse_uint8_known_len_hex_str(const char *key, char *src, struct fips_val *val); + +int +parser_read_uint32_val(const char *key, char *src, struct fips_val *val); + +int +parser_read_uint32_bit_val(const char *key, char *src, struct fips_val *val); + +int +parser_read_uint32(uint32_t *value, char *p); + +int +parser_read_uint32_val(const char *key, char *src, struct fips_val *val); + +int +writeback_hex_str(const char *key, char *dst, struct fips_val *val); + +void +parse_write_hex_str(struct fips_val *src); + +int +update_info_vec(uint32_t count); + +#endif diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation_aes.c b/src/seastar/dpdk/examples/fips_validation/fips_validation_aes.c new file mode 100644 index 000000000..8cbc158eb --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation_aes.c @@ -0,0 +1,188 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <string.h> +#include <time.h> +#include <stdio.h> + +#include <rte_cryptodev.h> + +#include "fips_validation.h" + +#define MODE_STR "AESVS" +#define ALGO_STR "test data for " +#define OP_STR "State" +#define KEY_SIZE_STR "Key Length : " + + +#define COUNT_STR "COUNT = " +#define KEY_STR "KEY = " +#define IV_STR "IV = " +#define PT_STR "PLAINTEXT = " +#define CT_STR "CIPHERTEXT = " + +#define OP_ENC_STR "ENCRYPT" +#define OP_DEC_STR "DECRYPT" + +struct { + uint32_t type; + const char *desc; +} aes_test_types[] = { + {AESAVS_TYPE_GFXBOX, "GFSbox"}, + {AESAVS_TYPE_KEYSBOX, "KeySbox"}, + {AESAVS_TYPE_VARKEY, "VarKey"}, + {AESAVS_TYPE_VARTXT, "VarTxt"}, + {TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"}, + {TDES_VARIABLE_TEXT, "KAT"}, + {AESAVS_TYPE_MMT, "MMT"}, + {AESAVS_TYPE_MCT, "MCT"}, +}; + +struct aes_test_algo { + const char *name; + enum rte_crypto_cipher_algorithm algo; +} const algo_con[] = { + {"CBC", RTE_CRYPTO_CIPHER_AES_CBC}, +}; + +static int +parse_interim_enc_dec(const char *key, + __attribute__((__unused__)) char *text, + __attribute__((__unused__)) struct fips_val *val) +{ + if (strcmp(key, OP_ENC_STR) == 0) + info.op = FIPS_TEST_ENC_AUTH_GEN; + else if (strcmp(key, OP_DEC_STR) == 0) + info.op = FIPS_TEST_DEC_AUTH_VERIF; + else + return -1; + + return 0; +} + +struct fips_test_callback aes_tests_interim[] = { + {OP_ENC_STR, parse_interim_enc_dec, NULL}, + {OP_DEC_STR, parse_interim_enc_dec, NULL}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback aes_tests_vectors[] = { + {KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key}, + {IV_STR, parse_uint8_hex_str, &vec.iv}, + {PT_STR, parse_uint8_hex_str, &vec.pt}, + {CT_STR, parse_uint8_hex_str, &vec.ct}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback aes_tests_interim_vectors[] = { + {OP_ENC_STR, parse_interim_enc_dec, NULL}, + {OP_DEC_STR, parse_interim_enc_dec, NULL}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback aes_writeback_callbacks[] = { + /** First element is used to pass COUNT string */ + {COUNT_STR, NULL, NULL}, + {IV_STR, writeback_hex_str, &vec.iv}, + {KEY_STR, writeback_hex_str, &vec.cipher_auth.key}, + {PT_STR, writeback_hex_str, &vec.pt}, + {CT_STR, writeback_hex_str, &vec.ct}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +static int +parse_test_aes_writeback(struct fips_val *val) +{ + if (info.op == FIPS_TEST_ENC_AUTH_GEN) + fprintf(info.fp_wr, "%s", CT_STR); + else + fprintf(info.fp_wr, "%s", PT_STR); + + parse_write_hex_str(val); + + return 0; +} + +static int +rsp_test_aes_check(struct fips_val *val) +{ + struct fips_val *data; + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) + data = &vec.ct; + else + data = &vec.pt; + + if (memcmp(val->val, data->val, val->len) == 0) + fprintf(info.fp_wr, "Success\n"); + else + fprintf(info.fp_wr, "Failed\n"); + + return 0; +} + +int +parse_test_aes_init(void) +{ + char *tmp; + uint32_t i, j; + + for (i = 0; i < info.nb_vec_lines; i++) { + char *line = info.vec[i]; + + tmp = strstr(line, MODE_STR); + if (tmp) { + for (j = 0; j < RTE_DIM(aes_test_types); j++) + if (strstr(line, aes_test_types[j].desc)) { + info.interim_info.aes_data.test_type = + aes_test_types[j].type; + break; + } + + if (j >= RTE_DIM(aes_test_types)) + return -EINVAL; + + tmp = strstr(line, ALGO_STR); + if (!tmp) + return -EINVAL; + + tmp += strlen(ALGO_STR); + for (j = 0; j < RTE_DIM(algo_con); j++) + if (strcmp(algo_con[j].name, tmp) == 0) { + info.interim_info.aes_data.cipher_algo = + (uint32_t)algo_con[j].algo; + break; + } + if (j >= RTE_DIM(algo_con)) + return -EINVAL; + + continue; + } + + tmp = strstr(line, OP_STR); + if (tmp) + continue; + + tmp = strstr(line, KEY_SIZE_STR); + if (tmp) { + tmp += strlen(KEY_SIZE_STR); + if (parser_read_uint32 + (&info.interim_info.aes_data.key_len, + tmp) < 0) + return -EINVAL; + + info.interim_info.aes_data.key_len /= 8; + + continue; + } + } + + info.parse_writeback = parse_test_aes_writeback; + info.callbacks = aes_tests_vectors; + info.interim_callbacks = aes_tests_interim_vectors; + info.writeback_callbacks = aes_writeback_callbacks; + info.kat_check = rsp_test_aes_check; + + return 0; +} diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation_ccm.c b/src/seastar/dpdk/examples/fips_validation/fips_validation_ccm.c new file mode 100644 index 000000000..632999c1e --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation_ccm.c @@ -0,0 +1,272 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <stdio.h> +#include <string.h> + +#include <rte_string_fns.h> +#include <rte_cryptodev.h> +#include <rte_malloc.h> + +#include "fips_validation.h" + +#define DVPT_STR "CCM-DVPT" +#define VADT_STR "CCM-VADT" +#define VPT_STR "CCM-VPT" +#define VNT_STR "CCM-VNT" +#define VTT_STR "CCM-VTT" + +#define PARAM_PREFIX "[" +#define ALEN_PREFIX "Alen = " +#define PLEN_PREFIX "Plen = " +#define IVLEN_PREFIX "Nlen = " +#define DIGESTL_PREFIX "Tlen = " + +#define COUNT_STR "Count = " +#define KEY_STR "Key = " +#define IV_STR "Nonce = " +#define PT_STR "Payload = " +#define CT_STR "CT = " +#define AAD_STR "Adata = " +#define POS_NEG_STR "Result = " + +#define POS_KEYWORD "Pass" +#define NEG_KEYWORD "Fail" + +static int +parser_dvpt_interim(const char *key, char *src, struct fips_val *val) +{ + char *tmp, c, value[10]; + char num_pattern[] = "0123456789"; + int i = 0; + + memset(value, 0, 10); + + tmp = strstr(src, key); + if (!tmp) + return -1; + + tmp += strlen(key); + + c = tmp[0]; + + while (strchr(num_pattern, c) && i < 10) { + value[i++] = c; + c = tmp[i]; + } + + return parser_read_uint32_val("", value, val); +} + +static int +parse_dvpt_ct_hex_str(const char *key, char *src, struct fips_val *val) +{ + int ret; + + val->len = vec.pt.len; + + ret = parse_uint8_known_len_hex_str(key, src, val); + if (ret < 0) + return ret; + + src += strlen(key) + val->len * 2; + + ret = parse_uint8_known_len_hex_str("", src, &vec.aead.digest); + if (ret < 0) { + rte_free(val->val); + memset(val, 0, sizeof(*val)); + return ret; + } + + return 0; +} + +static int +parse_uint8_ccm_aad_str(const char *key, char *src, struct fips_val *val) +{ + uint32_t len = val->len, j; + + src += strlen(key); + + /* CCM aad requires 18 bytes padding before the real content */ + val->val = rte_zmalloc(NULL, len + 18, 0); + if (!val->val) + return -1; + + for (j = 0; j < len; j++) { + char byte[3] = {src[j * 2], src[j * 2 + 1], '\0'}; + + if (parser_read_uint8_hex(&val->val[j + 18], byte) < 0) { + rte_free(val->val); + memset(val, 0, sizeof(*val)); + return -EINVAL; + } + } + + return 0; +} + +struct fips_test_callback ccm_vnt_vec[] = { + {IV_STR, parse_uint8_known_len_hex_str, &vec.iv}, + {AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad}, + {PT_STR, parse_uint8_known_len_hex_str, &vec.pt}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_vnt_interim_vec[] = { + {ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad}, + {PLEN_PREFIX, parser_read_uint32_val, &vec.pt}, + {DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest}, + {IVLEN_PREFIX, parser_read_uint32_val, &vec.iv}, + {KEY_STR, parse_uint8_hex_str, &vec.aead.key}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_vtt_vec[] = { + {AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad}, + {PT_STR, parse_uint8_known_len_hex_str, &vec.pt}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_vtt_interim_vec[] = { + {ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad}, + {PLEN_PREFIX, parser_read_uint32_val, &vec.pt}, + {IVLEN_PREFIX, parser_read_uint32_val, &vec.iv}, + {DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest}, + {KEY_STR, parse_uint8_hex_str, &vec.aead.key}, + {IV_STR, parse_uint8_known_len_hex_str, &vec.iv}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_vadt_vec[] = { + {AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad}, + {PT_STR, parse_uint8_known_len_hex_str, &vec.pt}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_vadt_interim_vec[] = { + {PLEN_PREFIX, parser_read_uint32_val, &vec.pt}, + {IVLEN_PREFIX, parser_read_uint32_val, &vec.iv}, + {ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad}, + {DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest}, + {KEY_STR, parse_uint8_hex_str, &vec.aead.key}, + {IV_STR, parse_uint8_known_len_hex_str, &vec.iv}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_vpt_vec[] = { + {AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad}, + {PT_STR, parse_uint8_known_len_hex_str, &vec.pt}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_vpt_interim_vec[] = { + {ALEN_PREFIX, parser_read_uint32_val, &vec.aead.aad}, + {IVLEN_PREFIX, parser_read_uint32_val, &vec.iv}, + {DIGESTL_PREFIX, parser_read_uint32_val, &vec.aead.digest}, + {PLEN_PREFIX, parser_read_uint32_val, &vec.pt}, + {KEY_STR, parse_uint8_hex_str, &vec.aead.key}, + {IV_STR, parse_uint8_known_len_hex_str, &vec.iv}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_dvpt_vec[] = { + {IV_STR, parse_uint8_known_len_hex_str, &vec.iv}, + {AAD_STR, parse_uint8_ccm_aad_str, &vec.aead.aad}, + {CT_STR, parse_dvpt_ct_hex_str, &vec.ct}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback ccm_dvpt_interim_vec[] = { + {ALEN_PREFIX, parser_dvpt_interim, &vec.aead.aad}, + {PLEN_PREFIX, parser_dvpt_interim, &vec.pt}, + {IVLEN_PREFIX, parser_dvpt_interim, &vec.iv}, + {DIGESTL_PREFIX, parser_dvpt_interim, &vec.aead.digest}, + {KEY_STR, parse_uint8_hex_str, &vec.aead.key}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct ccm_test_types { + const char *str; + uint32_t type; + const struct fips_test_callback *cb; + const struct fips_test_callback *cb_interim; + enum fips_test_op op; +} ctt[] = { + {DVPT_STR, CCM_DVPT, ccm_dvpt_vec, ccm_dvpt_interim_vec, + FIPS_TEST_DEC_AUTH_VERIF}, + {VPT_STR, CCM_VPT, ccm_vpt_vec, ccm_vpt_interim_vec, + FIPS_TEST_ENC_AUTH_GEN}, + {VADT_STR, CCM_VADT, ccm_vadt_vec, ccm_vadt_interim_vec, + FIPS_TEST_ENC_AUTH_GEN}, + {VNT_STR, CCM_VNT, ccm_vnt_vec, ccm_vnt_interim_vec, + FIPS_TEST_ENC_AUTH_GEN}, + {VTT_STR, CCM_VTT, ccm_vtt_vec, ccm_vtt_interim_vec, + FIPS_TEST_ENC_AUTH_GEN}, +}; + +static int +parse_test_ccm_writeback(struct fips_val *val) +{ + struct fips_val tmp_val; + + switch (info.interim_info.ccm_data.test_type) { + case CCM_DVPT: + fprintf(info.fp_wr, "%s", POS_NEG_STR); + if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) { + fprintf(info.fp_wr, "%s\n", POS_KEYWORD); + fprintf(info.fp_wr, "%s", PT_STR); + + tmp_val.val = val->val; + tmp_val.len = vec.pt.len; + + if (tmp_val.len == 0) + fprintf(info.fp_wr, "00\n"); + else + parse_write_hex_str(&tmp_val); + } else + fprintf(info.fp_wr, "%s\n", NEG_KEYWORD); + + break; + + case CCM_VADT: + case CCM_VNT: + case CCM_VPT: + case CCM_VTT: + fprintf(info.fp_wr, "%s", CT_STR); + + parse_write_hex_str(val); + + break; + + } + + return 0; +} + +int +parse_test_ccm_init(void) +{ + + uint32_t i; + + for (i = 0; i < info.nb_vec_lines; i++) { + char *line = info.vec[i]; + uint32_t j; + + for (j = 0; j < RTE_DIM(ctt); j++) + if (strstr(line, ctt[j].str)) { + info.interim_info.ccm_data.test_type = + ctt[j].type; + info.callbacks = ctt[j].cb; + info.interim_callbacks = ctt[j].cb_interim; + info.op = ctt[j].op; + break; + } + } + + info.parse_writeback = parse_test_ccm_writeback; + + return 0; +} diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation_cmac.c b/src/seastar/dpdk/examples/fips_validation/fips_validation_cmac.c new file mode 100644 index 000000000..54c951ef8 --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation_cmac.c @@ -0,0 +1,116 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <string.h> +#include <time.h> +#include <stdio.h> +#include <rte_string_fns.h> + +#include <rte_cryptodev.h> + +#include "fips_validation.h" + +#define NEW_LINE_STR "#" +#define OP_STR "CMAC" + +#define ALGO_STR "Alg = " +#define MODE_STR "Mode = " + +#define COUNT_STR "Count = " +#define KLEN_STR "Klen = " +#define PTLEN_STR "Mlen = " +#define TAGLEN_STR "Tlen = " +#define KEY_STR "Key = " +#define PT_STR "Msg = " +#define TAG_STR "Mac = " + +#define GEN_STR "Generate" +#define VERIF_STR "Verify" + +#define POS_NEG_STR "Result = " +#define PASS_STR "P" +#define FAIL_STR "F" + +struct hash_algo_conversion { + const char *str; + enum fips_test_algorithms algo; +} cmac_algo[] = { + {"AES", FIPS_TEST_ALGO_AES_CMAC}, +}; + +static int +parse_test_cmac_writeback(struct fips_val *val) +{ + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + struct fips_val tmp_val = {val->val + vec.pt.len, + vec.cipher_auth.digest.len}; + + fprintf(info.fp_wr, "%s", TAG_STR); + parse_write_hex_str(&tmp_val); + } else { + fprintf(info.fp_wr, "%s", POS_NEG_STR); + + if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) + fprintf(info.fp_wr, "%s\n", PASS_STR); + else if (vec.status == RTE_CRYPTO_OP_STATUS_AUTH_FAILED) + fprintf(info.fp_wr, "%s\n", FAIL_STR); + else + fprintf(info.fp_wr, "Error\n"); + } + + return 0; +} + +struct fips_test_callback cmac_tests_vectors[] = { + {KLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key}, + {PTLEN_STR, parser_read_uint32_val, &vec.pt}, + {TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest}, + {KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key}, + {PT_STR, parse_uint8_known_len_hex_str, &vec.pt}, + {TAG_STR, parse_uint8_known_len_hex_str, + &vec.cipher_auth.digest}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +int +parse_test_cmac_init(void) +{ + char *tmp; + uint32_t i, j; + + for (i = 0; i < info.nb_vec_lines; i++) { + char *line = info.vec[i]; + + tmp = strstr(line, ALGO_STR); + if (!tmp) + continue; + + for (j = 0; j < RTE_DIM(cmac_algo); j++) { + if (!strstr(line, cmac_algo[j].str)) + continue; + + info.algo = cmac_algo[j].algo; + break; + } + + if (j == RTE_DIM(cmac_algo)) + return -EINVAL; + + tmp = strstr(line, MODE_STR); + if (!tmp) + return -1; + + if (strstr(tmp, GEN_STR)) + info.op = FIPS_TEST_ENC_AUTH_GEN; + else if (strstr(tmp, VERIF_STR)) + info.op = FIPS_TEST_DEC_AUTH_VERIF; + else + return -EINVAL; + } + + info.parse_writeback = parse_test_cmac_writeback; + info.callbacks = cmac_tests_vectors; + + return 0; +} diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation_gcm.c b/src/seastar/dpdk/examples/fips_validation/fips_validation_gcm.c new file mode 100644 index 000000000..0509b101a --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation_gcm.c @@ -0,0 +1,125 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <string.h> +#include <time.h> +#include <stdio.h> + +#include <rte_cryptodev.h> + +#include "fips_validation.h" + +#define NEW_LINE_STR "#" +#define OP_STR "GCM " + +#define PARAM_PREFIX "[" +#define KEYLEN_STR "Keylen = " +#define IVLEN_STR "IVlen = " +#define PTLEN_STR "PTlen = " +#define AADLEN_STR "AADlen = " +#define TAGLEN_STR "Taglen = " + +#define COUNT_STR "Count = " +#define KEY_STR "Key = " +#define IV_STR "IV = " +#define PT_STR "PT = " +#define CT_STR "CT = " +#define TAG_STR "Tag = " +#define AAD_STR "AAD = " + +#define OP_ENC_STR "Encrypt" +#define OP_DEC_STR "Decrypt" + +#define NEG_TEST_STR "FAIL" + +struct fips_test_callback gcm_dec_vectors[] = { + {KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.key}, + {IV_STR, parse_uint8_known_len_hex_str, &vec.iv}, + {CT_STR, parse_uint8_known_len_hex_str, &vec.ct}, + {AAD_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.aad}, + {TAG_STR, parse_uint8_known_len_hex_str, + &vec.cipher_auth.digest}, + {NULL, NULL, NULL} /**< end pointer */ +}; +struct fips_test_callback gcm_interim_vectors[] = { + {KEYLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.key}, + {IVLEN_STR, parser_read_uint32_bit_val, &vec.iv}, + {PTLEN_STR, parser_read_uint32_bit_val, &vec.pt}, + {AADLEN_STR, parser_read_uint32_bit_val, &vec.cipher_auth.aad}, + {TAGLEN_STR, parser_read_uint32_bit_val, + &vec.cipher_auth.digest}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback gcm_enc_vectors[] = { + {KEY_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.key}, + {IV_STR, parse_uint8_known_len_hex_str, &vec.iv}, + {PT_STR, parse_uint8_known_len_hex_str, &vec.pt}, + {AAD_STR, parse_uint8_known_len_hex_str, &vec.cipher_auth.aad}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +static int +parse_test_gcm_writeback(struct fips_val *val) +{ + struct fips_val tmp_val; + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + fprintf(info.fp_wr, "%s", CT_STR); + + tmp_val.val = val->val; + tmp_val.len = vec.pt.len; + + parse_write_hex_str(&tmp_val); + + fprintf(info.fp_wr, "%s", TAG_STR); + + tmp_val.val = val->val + vec.pt.len; + tmp_val.len = val->len - vec.pt.len; + + parse_write_hex_str(&tmp_val); + } else { + if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS) { + fprintf(info.fp_wr, "%s", PT_STR); + + tmp_val.val = val->val; + tmp_val.len = vec.pt.len; + + parse_write_hex_str(&tmp_val); + } else + fprintf(info.fp_wr, "%s\n", NEG_TEST_STR); + } + + return 0; +} + +int +parse_test_gcm_init(void) +{ + char *tmp; + uint32_t i; + + + for (i = 0; i < info.nb_vec_lines; i++) { + char *line = info.vec[i]; + + + tmp = strstr(line, OP_STR); + if (tmp) { + if (strstr(line, OP_ENC_STR)) { + info.op = FIPS_TEST_ENC_AUTH_GEN; + info.callbacks = gcm_enc_vectors; + } else if (strstr(line, OP_DEC_STR)) { + info.op = FIPS_TEST_DEC_AUTH_VERIF; + info.callbacks = gcm_dec_vectors; + } else + return -EINVAL; + } + } + + info.interim_callbacks = gcm_interim_vectors; + info.parse_writeback = parse_test_gcm_writeback; + + return 0; +} diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation_hmac.c b/src/seastar/dpdk/examples/fips_validation/fips_validation_hmac.c new file mode 100644 index 000000000..97ac7186e --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation_hmac.c @@ -0,0 +1,105 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <string.h> +#include <time.h> +#include <stdio.h> + +#include <rte_cryptodev.h> + +#include "fips_validation.h" + +#define ALGO_PREFIX "[L=" +#define KEYLEN_STR "Klen = " +#define TAGLEN_STR "Tlen = " + +#define COUNT_STR "Count = " +#define KEY_STR "Key = " +#define PT_STR "Msg = " +#define TAG_STR "Mac = " + +struct hash_size_conversion { + const char *str; + enum rte_crypto_auth_algorithm algo; +} hsc[] = { + {"20", RTE_CRYPTO_AUTH_SHA1_HMAC}, + {"28", RTE_CRYPTO_AUTH_SHA224_HMAC}, + {"32", RTE_CRYPTO_AUTH_SHA256_HMAC}, + {"48", RTE_CRYPTO_AUTH_SHA384_HMAC}, + {"64", RTE_CRYPTO_AUTH_SHA512_HMAC}, +}; + +static int +parse_interim_algo(__attribute__((__unused__)) const char *key, + char *text, + __attribute__((__unused__)) struct fips_val *val) +{ + + uint32_t i; + + for (i = 0; i < RTE_DIM(hsc); i++) { + if (strstr(text, hsc[i].str)) { + info.interim_info.hmac_data.algo = hsc[i].algo; + break; + } + } + + if (i == RTE_DIM(hsc)) + return -1; + + return 0; +} + +struct fips_test_callback hmac_tests_vectors[] = { + {KEYLEN_STR, parser_read_uint32_val, &vec.cipher_auth.key}, + {TAGLEN_STR, parser_read_uint32_val, &vec.cipher_auth.digest}, + {KEY_STR, parse_uint8_hex_str, &vec.cipher_auth.key}, + {PT_STR, parse_uint8_hex_str, &vec.pt}, + {TAG_STR, parse_uint8_hex_str, &vec.cipher_auth.digest}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback hmac_tests_interim_vectors[] = { + {ALGO_PREFIX, parse_interim_algo, NULL}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +static int +parse_test_hmac_writeback(struct fips_val *val) +{ + struct fips_val val_local; + + fprintf(info.fp_wr, "%s", TAG_STR); + + val_local.val = val->val + vec.pt.len; + val_local.len = vec.cipher_auth.digest.len; + + parse_write_hex_str(&val_local); + return 0; +} + +static int +rsp_test_hmac_check(struct fips_val *val) +{ + if (memcmp(val->val + vec.pt.len, vec.cipher_auth.digest.val, + vec.cipher_auth.digest.len) == 0) + fprintf(info.fp_wr, "Success\n"); + else + fprintf(info.fp_wr, "Failed\n"); + + return 0; +} + +int +parse_test_hmac_init(void) +{ + info.op = FIPS_TEST_ENC_AUTH_GEN; + info.parse_writeback = parse_test_hmac_writeback; + info.callbacks = hmac_tests_vectors; + info.interim_callbacks = hmac_tests_interim_vectors; + info.writeback_callbacks = NULL; + info.kat_check = rsp_test_hmac_check; + + return 0; +} diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation_sha.c b/src/seastar/dpdk/examples/fips_validation/fips_validation_sha.c new file mode 100644 index 000000000..2cca9cecc --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation_sha.c @@ -0,0 +1,110 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2019 Intel Corporation + */ + +#include <string.h> +#include <time.h> +#include <stdio.h> + +#include <rte_cryptodev.h> + +#include "fips_validation.h" + +#define ALGO_PREFIX "[L = " +#define MSGLEN_STR "Len = " +#define MSG_STR "Msg = " +#define MD_STR "MD = " +#define SEED_STR "Seed = " +#define MCT_STR "Monte" + +struct plain_hash_size_conversion { + const char *str; + enum rte_crypto_auth_algorithm algo; +} phsc[] = { + {"20", RTE_CRYPTO_AUTH_SHA1}, + {"28", RTE_CRYPTO_AUTH_SHA224}, + {"32", RTE_CRYPTO_AUTH_SHA256}, + {"48", RTE_CRYPTO_AUTH_SHA384}, + {"64", RTE_CRYPTO_AUTH_SHA512}, +}; + +static int +parse_interim_algo(__attribute__((__unused__)) const char *key, + char *text, + __attribute__((__unused__)) struct fips_val *val) +{ + uint32_t i; + + for (i = 0; i < RTE_DIM(phsc); i++) { + if (strstr(text, phsc[i].str)) { + info.interim_info.sha_data.algo = phsc[i].algo; + parser_read_uint32_val(ALGO_PREFIX, + text, &vec.cipher_auth.digest); + break; + } + } + + if (i == RTE_DIM(phsc)) + return -1; + + return 0; +} + +struct fips_test_callback sha_tests_vectors[] = { + {MSGLEN_STR, parser_read_uint32_bit_val, &vec.pt}, + {MSG_STR, parse_uint8_known_len_hex_str, &vec.pt}, + {SEED_STR, parse_uint8_hex_str, &vec.cipher_auth.digest}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback sha_tests_interim_vectors[] = { + {ALGO_PREFIX, parse_interim_algo, NULL}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +static int +parse_test_sha_writeback(struct fips_val *val) // ! +{ + struct fips_val val_local; + + fprintf(info.fp_wr, "%s", MD_STR); + + val_local.val = val->val + vec.pt.len; + val_local.len = vec.cipher_auth.digest.len; + + parse_write_hex_str(&val_local); + return 0; +} + +static int +rsp_test_sha_check(struct fips_val *val) +{ + if (memcmp(val->val + vec.pt.len, vec.cipher_auth.digest.val, + vec.cipher_auth.digest.len) == 0) + fprintf(info.fp_wr, "Success\n"); + else + fprintf(info.fp_wr, "Failed\n"); + + return 0; +} + +int +parse_test_sha_init(void) +{ + uint32_t i; + + info.interim_info.sha_data.test_type = SHA_KAT; + for (i = 0; i < info.nb_vec_lines; i++) { + char *line = info.vec[i]; + if (strstr(line, MCT_STR)) + info.interim_info.sha_data.test_type = SHA_MCT; + } + + info.op = FIPS_TEST_ENC_AUTH_GEN; + info.parse_writeback = parse_test_sha_writeback; + info.callbacks = sha_tests_vectors; + info.interim_callbacks = sha_tests_interim_vectors; + info.writeback_callbacks = NULL; + info.kat_check = rsp_test_sha_check; + return 0; +} diff --git a/src/seastar/dpdk/examples/fips_validation/fips_validation_tdes.c b/src/seastar/dpdk/examples/fips_validation/fips_validation_tdes.c new file mode 100644 index 000000000..15ee434e1 --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/fips_validation_tdes.c @@ -0,0 +1,264 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <string.h> +#include <stdio.h> + +#include <rte_malloc.h> +#include <rte_cryptodev.h> + +#include "fips_validation.h" + +#define NEW_LINE_STR "#" +#define TEST_TYPE_KEY " for CBC" +#define TEST_CBCI_KEY " for CBCI" + +#define ENC_STR "[ENCRYPT]" +#define DEC_STR "[DECRYPT]" + +#define COUNT_STR "COUNT = " +#define KEY1_STR "KEY1 = " +#define KEY2_STR "KEY2 = " +#define KEY3_STR "KEY3 = " + +#define KEYS_STR "KEYs = " +#define IV_STR "IV = " +#define PT_STR "PLAINTEXT = " +#define CT_STR "CIPHERTEXT = " +#define NK_STR "NumKeys = " + +#define SET_STR " = " + +#define PLAIN_TEXT 0 +#define CIPHER_TEXT 1 +#define KEY_TEXT 2 +#define IV_TEXT 3 + +#define DEVICE_STR "# Config Info for : " + +struct { + uint32_t type; + const char *desc; +} test_types[] = { + {TDES_INVERSE_PERMUTATION, "INVERSE PERMUTATION"}, + {TDES_PERMUTATION, "PERMUTATION OPERATION"}, + {TDES_SUBSTITUTION_TABLE, "SUBSTITUTION TABLE"}, + {TDES_VARIABLE_KEY, "VARIABLE KEY"}, + {TDES_VARIABLE_TEXT, "VARIABLE PLAINTEXT/CIPHERTEXT"}, + {TDES_VARIABLE_TEXT, "KAT"}, + {TDES_MCT, "Monte Carlo (Modes) Test"}, + {TDES_MMT, "Multi block Message Test"}, +}; + +static int +writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val); + +static int +parse_tdes_uint8_hex_str(const char *key, char *src, struct fips_val *val); + +static int +parse_tdes_interim(const char *key, + __attribute__((__unused__)) char *text, + struct fips_val *val); + +struct fips_test_callback tdes_tests_vectors[] = { + {KEYS_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key}, + {KEY1_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key}, + {KEY2_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key}, + {KEY3_STR, parse_tdes_uint8_hex_str, &vec.cipher_auth.key}, + {IV_STR, parse_uint8_hex_str, &vec.iv}, + {PT_STR, parse_uint8_hex_str, &vec.pt}, + {CT_STR, parse_uint8_hex_str, &vec.ct}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback tdes_tests_interim_vectors[] = { + {ENC_STR, parse_tdes_interim, NULL}, + {DEC_STR, parse_tdes_interim, NULL}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +struct fips_test_callback tdes_writeback_callbacks[] = { + /** First element is used to pass COUNT string */ + {COUNT_STR, NULL, NULL}, + {IV_STR, writeback_hex_str, &vec.iv}, + {KEY1_STR, writeback_tdes_hex_str, &vec.cipher_auth.key}, + {KEY2_STR, writeback_tdes_hex_str, &vec.cipher_auth.key}, + {KEY3_STR, writeback_tdes_hex_str, &vec.cipher_auth.key}, + {KEYS_STR, writeback_tdes_hex_str, &vec.cipher_auth.key}, + {PT_STR, writeback_hex_str, &vec.pt}, + {CT_STR, writeback_hex_str, &vec.ct}, + {NULL, NULL, NULL} /**< end pointer */ +}; + +static int +parse_tdes_interim(const char *key, + __attribute__((__unused__)) char *text, + __attribute__((__unused__)) struct fips_val *val) +{ + if (strstr(key, ENC_STR)) + info.op = FIPS_TEST_ENC_AUTH_GEN; + else if (strstr(key, DEC_STR)) + info.op = FIPS_TEST_DEC_AUTH_VERIF; + else if (strstr(NK_STR, "NumKeys = 1")) + info.interim_info.tdes_data.nb_keys = 1; + else if (strstr(NK_STR, "NumKeys = 2")) + info.interim_info.tdes_data.nb_keys = 2; + else if (strstr(NK_STR, "NumKeys = 3")) + info.interim_info.tdes_data.nb_keys = 3; + else + return -EINVAL; + + return 0; +} + +static int +parse_tdes_uint8_hex_str(const char *key, char *src, struct fips_val *val) +{ + uint8_t tmp_key[24] = {0}; + uint32_t len, i; + + src += strlen(key); + + len = strlen(src) / 2; + + if (val->val) { + memcpy(tmp_key, val->val, val->len); + rte_free(val->val); + } + + val->val = rte_zmalloc(NULL, 24, 0); + if (!val->val) + return -1; + + memcpy(val->val, tmp_key, 24); + + if (strstr(key, KEYS_STR)) { + for (i = 0; i < len; i++) { + char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'}; + + if (parser_read_uint8_hex(&val->val[i], byte) < 0) + goto error_exit; + } + + memcpy(val->val + 8, val->val, 8); + memcpy(val->val + 16, val->val, 8); + + } else if (strstr(key, KEY1_STR)) { + for (i = 0; i < len; i++) { + char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'}; + + if (parser_read_uint8_hex(&val->val[i], byte) < 0) + goto error_exit; + } + + if (info.interim_info.tdes_data.nb_keys == 2) + memcpy(val->val + 16, val->val, 8); + + } else if (strstr(key, KEY2_STR)) { + for (i = 0; i < len; i++) { + char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'}; + + if (parser_read_uint8_hex(&val->val[i + 8], byte) < 0) + goto error_exit; + } + + } else if (strstr(key, KEY3_STR)) { + for (i = 0; i < len; i++) { + char byte[3] = {src[i * 2], src[i * 2 + 1], '\0'}; + + if (parser_read_uint8_hex(&val->val[i + 16], byte) < 0) + goto error_exit; + } + } else + return -EINVAL; + + val->len = 24; + + return 0; + +error_exit: + rte_free(val->val); + memset(val, 0, sizeof(*val)); + return -EINVAL; +} + +static int +parse_test_tdes_writeback(struct fips_val *val) +{ + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) + fprintf(info.fp_wr, "%s", CT_STR); + else + fprintf(info.fp_wr, "%s", PT_STR); + + parse_write_hex_str(val); + + return 0; + +} + +static int +writeback_tdes_hex_str(const char *key, char *dst, struct fips_val *val) +{ + struct fips_val tmp_val = {0}; + + tmp_val.len = 8; + + if (strstr(key, KEY1_STR)) + tmp_val.val = val->val; + else if (strstr(key, KEY2_STR)) + tmp_val.val = val->val + 8; + else if (strstr(key, KEY3_STR)) + tmp_val.val = val->val + 16; + + return writeback_hex_str(key, dst, &tmp_val); +} + +static int +rsp_test_tdes_check(struct fips_val *val) +{ + struct fips_val *data; + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) + data = &vec.ct; + else + data = &vec.pt; + + if (memcmp(val->val, data->val, val->len) == 0) + fprintf(info.fp_wr, "Success\n"); + else + fprintf(info.fp_wr, "Failed\n"); + + return 0; +} + +int +parse_test_tdes_init(void) +{ + uint32_t i; + + for (i = 0; i < info.nb_vec_lines; i++) { + char *line = info.vec[i]; + uint32_t j; + + if (strstr(line, TEST_CBCI_KEY)) + return -EPERM; + + for (j = 0; j < RTE_DIM(test_types); j++) + if (strstr(line, test_types[j].desc)) { + info.interim_info.tdes_data.test_type = + test_types[j].type; + break; + } + } + + info.parse_writeback = parse_test_tdes_writeback; + info.callbacks = tdes_tests_vectors; + info.interim_callbacks = tdes_tests_interim_vectors; + info.writeback_callbacks = tdes_writeback_callbacks; + info.kat_check = rsp_test_tdes_check; + + return 0; +} diff --git a/src/seastar/dpdk/examples/fips_validation/main.c b/src/seastar/dpdk/examples/fips_validation/main.c new file mode 100644 index 000000000..aef45055e --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/main.c @@ -0,0 +1,1462 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2018 Intel Corporation + */ + +#include <sys/stat.h> +#include <getopt.h> +#include <dirent.h> + +#include <rte_cryptodev.h> +#include <rte_cryptodev_pmd.h> +#include <rte_mempool.h> +#include <rte_mbuf.h> +#include <rte_string_fns.h> + +#include "fips_validation.h" +#include "fips_dev_self_test.h" + +#define REQ_FILE_PATH_KEYWORD "req-file" +#define RSP_FILE_PATH_KEYWORD "rsp-file" +#define FOLDER_KEYWORD "path-is-folder" +#define CRYPTODEV_KEYWORD "cryptodev" +#define CRYPTODEV_ID_KEYWORD "cryptodev-id" +#define CRYPTODEV_ST_KEYWORD "self-test" +#define CRYPTODEV_BK_ID_KEYWORD "broken-test-id" +#define CRYPTODEV_BK_DIR_KEY "broken-test-dir" +#define CRYPTODEV_ENC_KEYWORD "enc" +#define CRYPTODEV_DEC_KEYWORD "dec" + +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; + uint32_t dev_id; + struct rte_mempool *mpool; + struct rte_mempool *sess_mpool; + struct rte_mempool *sess_priv_mpool; + struct rte_mempool *op_pool; + struct rte_mbuf *mbuf; + struct rte_crypto_op *op; + struct rte_cryptodev_sym_session *sess; + uint32_t self_test; + struct fips_dev_broken_test_config *broken_test_config; +} env; + +static int +cryptodev_fips_validate_app_int(void) +{ + struct rte_cryptodev_config conf = {rte_socket_id(), 1}; + struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL}; + uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size( + env.dev_id); + int ret; + + if (env.self_test) { + ret = fips_dev_self_test(env.dev_id, env.broken_test_config); + if (ret < 0) { + struct rte_cryptodev *cryptodev = + rte_cryptodev_pmd_get_dev(env.dev_id); + + rte_cryptodev_pmd_destroy(cryptodev); + + return ret; + } + } + + ret = rte_cryptodev_configure(env.dev_id, &conf); + if (ret < 0) + return ret; + + env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", 128, 0, 0, + UINT16_MAX, rte_socket_id()); + if (!env.mpool) + return ret; + + ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf, + rte_socket_id()); + if (ret < 0) + return ret; + + ret = -ENOMEM; + + env.sess_mpool = rte_cryptodev_sym_session_pool_create( + "FIPS_SESS_MEMPOOL", 16, 0, 0, 0, rte_socket_id()); + if (!env.sess_mpool) + goto error_exit; + + env.sess_priv_mpool = rte_mempool_create("FIPS_SESS_PRIV_MEMPOOL", + 16, sess_sz, 0, 0, NULL, NULL, NULL, + NULL, rte_socket_id(), 0); + if (!env.sess_priv_mpool) + goto error_exit; + + env.op_pool = rte_crypto_op_pool_create( + "FIPS_OP_POOL", + RTE_CRYPTO_OP_TYPE_SYMMETRIC, + 1, 0, + 16, + rte_socket_id()); + if (!env.op_pool) + goto error_exit; + + env.mbuf = rte_pktmbuf_alloc(env.mpool); + if (!env.mbuf) + goto error_exit; + + env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC); + if (!env.op) + goto error_exit; + + qp_conf.mp_session = env.sess_mpool; + qp_conf.mp_session_private = env.sess_priv_mpool; + + ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf, + rte_socket_id()); + if (ret < 0) + goto error_exit; + + return 0; + +error_exit: + + rte_mempool_free(env.mpool); + if (env.sess_mpool) + rte_mempool_free(env.sess_mpool); + if (env.sess_priv_mpool) + rte_mempool_free(env.sess_priv_mpool); + if (env.op_pool) + rte_mempool_free(env.op_pool); + + return ret; +} + +static void +cryptodev_fips_validate_app_uninit(void) +{ + rte_pktmbuf_free(env.mbuf); + rte_crypto_op_free(env.op); + rte_cryptodev_sym_session_clear(env.dev_id, env.sess); + rte_cryptodev_sym_session_free(env.sess); + rte_mempool_free(env.mpool); + rte_mempool_free(env.sess_mpool); + rte_mempool_free(env.sess_priv_mpool); + rte_mempool_free(env.op_pool); +} + +static int +fips_test_one_file(void); + +static int +parse_cryptodev_arg(char *arg) +{ + int id = rte_cryptodev_get_dev_id(arg); + + if (id < 0) { + RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev name %s\n", + id, arg); + return id; + } + + env.dev_id = (uint32_t)id; + + return 0; +} + +static int +parse_cryptodev_id_arg(char *arg) +{ + uint32_t cryptodev_id; + + if (parser_read_uint32(&cryptodev_id, arg) < 0) { + RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n", + -EINVAL, arg); + return -1; + } + + + if (!rte_cryptodev_pmd_is_valid_dev(cryptodev_id)) { + RTE_LOG(ERR, USER1, "Error %i: invalid cryptodev id %s\n", + cryptodev_id, arg); + return -1; + } + + env.dev_id = (uint32_t)cryptodev_id; + + return 0; +} + +static void +cryptodev_fips_validate_usage(const char *prgname) +{ + printf("%s [EAL options] --\n" + " --%s: REQUEST-FILE-PATH\n" + " --%s: RESPONSE-FILE-PATH\n" + " --%s: indicating both paths are folders\n" + " --%s: CRYPTODEV-NAME\n" + " --%s: CRYPTODEV-ID-NAME\n" + " --%s: self test indicator\n" + " --%s: self broken test ID\n" + " --%s: self broken test direction\n", + prgname, REQ_FILE_PATH_KEYWORD, RSP_FILE_PATH_KEYWORD, + FOLDER_KEYWORD, CRYPTODEV_KEYWORD, CRYPTODEV_ID_KEYWORD, + CRYPTODEV_ST_KEYWORD, CRYPTODEV_BK_ID_KEYWORD, + CRYPTODEV_BK_DIR_KEY); +} + +static int +cryptodev_fips_validate_parse_args(int argc, char **argv) +{ + int opt, ret; + char *prgname = argv[0]; + char **argvopt; + int option_index; + struct option lgopts[] = { + {REQ_FILE_PATH_KEYWORD, required_argument, 0, 0}, + {RSP_FILE_PATH_KEYWORD, required_argument, 0, 0}, + {FOLDER_KEYWORD, no_argument, 0, 0}, + {CRYPTODEV_KEYWORD, required_argument, 0, 0}, + {CRYPTODEV_ID_KEYWORD, required_argument, 0, 0}, + {CRYPTODEV_ST_KEYWORD, no_argument, 0, 0}, + {CRYPTODEV_BK_ID_KEYWORD, required_argument, 0, 0}, + {CRYPTODEV_BK_DIR_KEY, required_argument, 0, 0}, + {NULL, 0, 0, 0} + }; + + argvopt = argv; + + while ((opt = getopt_long(argc, argvopt, "s:", + lgopts, &option_index)) != EOF) { + + switch (opt) { + case 0: + if (strcmp(lgopts[option_index].name, + REQ_FILE_PATH_KEYWORD) == 0) + env.req_path = optarg; + else if (strcmp(lgopts[option_index].name, + RSP_FILE_PATH_KEYWORD) == 0) + env.rsp_path = optarg; + else if (strcmp(lgopts[option_index].name, + FOLDER_KEYWORD) == 0) + env.is_path_folder = 1; + else if (strcmp(lgopts[option_index].name, + CRYPTODEV_KEYWORD) == 0) { + ret = parse_cryptodev_arg(optarg); + if (ret < 0) { + cryptodev_fips_validate_usage(prgname); + return -EINVAL; + } + } else if (strcmp(lgopts[option_index].name, + CRYPTODEV_ID_KEYWORD) == 0) { + ret = parse_cryptodev_id_arg(optarg); + if (ret < 0) { + cryptodev_fips_validate_usage(prgname); + return -EINVAL; + } + } else if (strcmp(lgopts[option_index].name, + CRYPTODEV_ST_KEYWORD) == 0) { + env.self_test = 1; + } else if (strcmp(lgopts[option_index].name, + CRYPTODEV_BK_ID_KEYWORD) == 0) { + if (!env.broken_test_config) { + env.broken_test_config = rte_malloc( + NULL, + sizeof(*env.broken_test_config), + 0); + if (!env.broken_test_config) + return -ENOMEM; + + env.broken_test_config->expect_fail_dir = + self_test_dir_enc_auth_gen; + } + + if (parser_read_uint32( + &env.broken_test_config->expect_fail_test_idx, + optarg) < 0) { + rte_free(env.broken_test_config); + cryptodev_fips_validate_usage(prgname); + return -EINVAL; + } + } else if (strcmp(lgopts[option_index].name, + CRYPTODEV_BK_DIR_KEY) == 0) { + if (!env.broken_test_config) { + env.broken_test_config = rte_malloc( + NULL, + sizeof(*env.broken_test_config), + 0); + if (!env.broken_test_config) + return -ENOMEM; + + env.broken_test_config-> + expect_fail_test_idx = 0; + } + + if (strcmp(optarg, CRYPTODEV_ENC_KEYWORD) == 0) + env.broken_test_config->expect_fail_dir = + self_test_dir_enc_auth_gen; + else if (strcmp(optarg, CRYPTODEV_DEC_KEYWORD) + == 0) + env.broken_test_config->expect_fail_dir = + self_test_dir_dec_auth_verify; + else { + rte_free(env.broken_test_config); + cryptodev_fips_validate_usage(prgname); + return -EINVAL; + } + } else { + cryptodev_fips_validate_usage(prgname); + return -EINVAL; + } + break; + default: + return -1; + } + } + + if (env.req_path == NULL || env.rsp_path == NULL || + env.dev_id == UINT32_MAX) { + cryptodev_fips_validate_usage(prgname); + return -EINVAL; + } + + return 0; +} + +int +main(int argc, char *argv[]) +{ + int ret; + + ret = rte_eal_init(argc, argv); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret); + return -1; + } + + argc -= ret; + argv += ret; + + ret = cryptodev_fips_validate_parse_args(argc, argv); + if (ret < 0) + rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n"); + + ret = cryptodev_fips_validate_app_int(); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret); + return -1; + } + + if (!env.is_path_folder) { + printf("Processing file %s... ", env.req_path); + + ret = fips_test_init(env.req_path, env.rsp_path, + rte_cryptodev_name_get(env.dev_id)); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n", + ret, env.req_path); + goto exit; + } + + + ret = fips_test_one_file(); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n", + ret, env.req_path); + goto exit; + } + + printf("Done\n"); + + } else { + struct dirent *dir; + DIR *d_req, *d_rsp; + char req_path[1024]; + char rsp_path[1024]; + + d_req = opendir(env.req_path); + if (!d_req) { + RTE_LOG(ERR, USER1, "Error %i: Path %s not exist\n", + -EINVAL, env.req_path); + goto exit; + } + + d_rsp = opendir(env.rsp_path); + if (!d_rsp) { + ret = mkdir(env.rsp_path, 0700); + if (ret == 0) + d_rsp = opendir(env.rsp_path); + else { + RTE_LOG(ERR, USER1, "Error %i: Invalid %s\n", + -EINVAL, env.rsp_path); + goto exit; + } + } + closedir(d_rsp); + + while ((dir = readdir(d_req)) != NULL) { + if (strstr(dir->d_name, "req") == NULL) + continue; + + snprintf(req_path, 1023, "%s/%s", env.req_path, + dir->d_name); + snprintf(rsp_path, 1023, "%s/%s", env.rsp_path, + dir->d_name); + strlcpy(strstr(rsp_path, "req"), "rsp", 4); + + printf("Processing file %s... ", req_path); + + ret = fips_test_init(req_path, rsp_path, + rte_cryptodev_name_get(env.dev_id)); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n", + ret, req_path); + break; + } + + ret = fips_test_one_file(); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Failed test %s\n", + ret, req_path); + break; + } + + printf("Done\n"); + } + + closedir(d_req); + } + + +exit: + fips_test_clear(); + cryptodev_fips_validate_app_uninit(); + + return ret; + +} + +#define IV_OFF (sizeof(struct rte_crypto_op) + sizeof(struct rte_crypto_sym_op)) +#define CRYPTODEV_FIPS_MAX_RETRIES 16 + +typedef int (*fips_test_one_case_t)(void); +typedef int (*fips_prepare_op_t)(void); +typedef int (*fips_prepare_xform_t)(struct rte_crypto_sym_xform *); + +struct fips_test_ops { + fips_prepare_xform_t prepare_xform; + fips_prepare_op_t prepare_op; + fips_test_one_case_t test; +} test_ops; + +static int +prepare_cipher_op(void) +{ + struct rte_crypto_sym_op *sym = env.op->sym; + uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF); + + __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC); + rte_pktmbuf_reset(env.mbuf); + + sym->m_src = env.mbuf; + sym->cipher.data.offset = 0; + + memcpy(iv, vec.iv.val, vec.iv.len); + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + uint8_t *pt; + + if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) { + RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len); + return -EPERM; + } + + pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len); + + if (!pt) { + RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n", + -ENOMEM); + return -ENOMEM; + } + + memcpy(pt, vec.pt.val, vec.pt.len); + sym->cipher.data.length = vec.pt.len; + + } else { + uint8_t *ct; + + if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) { + RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len); + return -EPERM; + } + + ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len); + + if (!ct) { + RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n", + -ENOMEM); + return -ENOMEM; + } + + memcpy(ct, vec.ct.val, vec.ct.len); + sym->cipher.data.length = vec.ct.len; + } + + rte_crypto_op_attach_sym_session(env.op, env.sess); + + return 0; +} + +static int +prepare_auth_op(void) +{ + struct rte_crypto_sym_op *sym = env.op->sym; + + __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC); + rte_pktmbuf_reset(env.mbuf); + + sym->m_src = env.mbuf; + sym->auth.data.offset = 0; + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + uint8_t *pt; + + if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) { + RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len); + return -EPERM; + } + + pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.pt.len + + vec.cipher_auth.digest.len); + + if (!pt) { + RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n", + -ENOMEM); + return -ENOMEM; + } + + memcpy(pt, vec.pt.val, vec.pt.len); + sym->auth.data.length = vec.pt.len; + sym->auth.digest.data = pt + vec.pt.len; + sym->auth.digest.phys_addr = rte_pktmbuf_mtophys_offset( + env.mbuf, vec.pt.len); + + } else { + uint8_t *ct; + + if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) { + RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len); + return -EPERM; + } + + ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, + vec.ct.len + vec.cipher_auth.digest.len); + + if (!ct) { + RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n", + -ENOMEM); + return -ENOMEM; + } + + memcpy(ct, vec.ct.val, vec.ct.len); + sym->auth.data.length = vec.ct.len; + sym->auth.digest.data = vec.cipher_auth.digest.val; + sym->auth.digest.phys_addr = rte_malloc_virt2iova( + sym->auth.digest.data); + } + + rte_crypto_op_attach_sym_session(env.op, env.sess); + + return 0; +} + +static int +prepare_aead_op(void) +{ + struct rte_crypto_sym_op *sym = env.op->sym; + uint8_t *iv = rte_crypto_op_ctod_offset(env.op, uint8_t *, IV_OFF); + + __rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_SYMMETRIC); + rte_pktmbuf_reset(env.mbuf); + + if (info.algo == FIPS_TEST_ALGO_AES_CCM) + memcpy(iv + 1, vec.iv.val, vec.iv.len); + else + memcpy(iv, vec.iv.val, vec.iv.len); + + sym->m_src = env.mbuf; + sym->aead.data.offset = 0; + sym->aead.aad.data = vec.aead.aad.val; + sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data); + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + uint8_t *pt; + + if (vec.pt.len > RTE_MBUF_MAX_NB_SEGS) { + RTE_LOG(ERR, USER1, "PT len %u\n", vec.pt.len); + return -EPERM; + } + + pt = (uint8_t *)rte_pktmbuf_append(env.mbuf, + vec.pt.len + vec.aead.digest.len); + + if (!pt) { + RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n", + -ENOMEM); + return -ENOMEM; + } + + memcpy(pt, vec.pt.val, vec.pt.len); + sym->aead.data.length = vec.pt.len; + sym->aead.digest.data = pt + vec.pt.len; + sym->aead.digest.phys_addr = rte_pktmbuf_mtophys_offset( + env.mbuf, vec.pt.len); + } else { + uint8_t *ct; + + if (vec.ct.len > RTE_MBUF_MAX_NB_SEGS) { + RTE_LOG(ERR, USER1, "CT len %u\n", vec.ct.len); + return -EPERM; + } + + ct = (uint8_t *)rte_pktmbuf_append(env.mbuf, vec.ct.len); + + if (!ct) { + RTE_LOG(ERR, USER1, "Error %i: MBUF too small\n", + -ENOMEM); + return -ENOMEM; + } + + memcpy(ct, vec.ct.val, vec.ct.len); + sym->aead.data.length = vec.ct.len; + sym->aead.digest.data = vec.aead.digest.val; + sym->aead.digest.phys_addr = rte_malloc_virt2iova( + sym->aead.digest.data); + } + + rte_crypto_op_attach_sym_session(env.op, env.sess); + + return 0; +} + +static int +prepare_aes_xform(struct rte_crypto_sym_xform *xform) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher; + + xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER; + + cipher_xform->algo = RTE_CRYPTO_CIPHER_AES_CBC; + cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ? + RTE_CRYPTO_CIPHER_OP_ENCRYPT : + RTE_CRYPTO_CIPHER_OP_DECRYPT; + cipher_xform->key.data = vec.cipher_auth.key.val; + cipher_xform->key.length = vec.cipher_auth.key.len; + cipher_xform->iv.length = vec.iv.len; + cipher_xform->iv.offset = IV_OFF; + + cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_AES_CBC; + 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; + } + + return 0; +} + +static int +prepare_tdes_xform(struct rte_crypto_sym_xform *xform) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_cipher_xform *cipher_xform = &xform->cipher; + + xform->type = RTE_CRYPTO_SYM_XFORM_CIPHER; + + cipher_xform->algo = RTE_CRYPTO_CIPHER_3DES_CBC; + cipher_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ? + RTE_CRYPTO_CIPHER_OP_ENCRYPT : + RTE_CRYPTO_CIPHER_OP_DECRYPT; + cipher_xform->key.data = vec.cipher_auth.key.val; + cipher_xform->key.length = vec.cipher_auth.key.len; + cipher_xform->iv.length = vec.iv.len; + cipher_xform->iv.offset = IV_OFF; + + cap_idx.algo.cipher = RTE_CRYPTO_CIPHER_3DES_CBC; + 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; + } + + return 0; +} + +static int +prepare_hmac_xform(struct rte_crypto_sym_xform *xform) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_auth_xform *auth_xform = &xform->auth; + + xform->type = RTE_CRYPTO_SYM_XFORM_AUTH; + + auth_xform->algo = info.interim_info.hmac_data.algo; + auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE; + auth_xform->digest_length = vec.cipher_auth.digest.len; + auth_xform->key.data = vec.cipher_auth.key.val; + auth_xform->key.length = vec.cipher_auth.key.len; + + cap_idx.algo.auth = auth_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH; + + 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_auth(cap, + auth_xform->key.length, + auth_xform->digest_length, 0) != 0) { + RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n", + info.device_name, auth_xform->key.length, + auth_xform->digest_length); + return -EPERM; + } + + return 0; +} + +static int +prepare_gcm_xform(struct rte_crypto_sym_xform *xform) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_aead_xform *aead_xform = &xform->aead; + + xform->type = RTE_CRYPTO_SYM_XFORM_AEAD; + + aead_xform->algo = RTE_CRYPTO_AEAD_AES_GCM; + aead_xform->aad_length = vec.aead.aad.len; + aead_xform->digest_length = vec.aead.digest.len; + aead_xform->iv.offset = IV_OFF; + aead_xform->iv.length = vec.iv.len; + aead_xform->key.data = vec.aead.key.val; + aead_xform->key.length = vec.aead.key.len; + aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ? + RTE_CRYPTO_AEAD_OP_ENCRYPT : + RTE_CRYPTO_AEAD_OP_DECRYPT; + + cap_idx.algo.aead = aead_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD; + + 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_aead(cap, + aead_xform->key.length, + aead_xform->digest_length, aead_xform->aad_length, + aead_xform->iv.length) != 0) { + RTE_LOG(ERR, USER1, + "PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n", + info.device_name, aead_xform->key.length, + aead_xform->digest_length, + aead_xform->aad_length, + aead_xform->iv.length); + return -EPERM; + } + + return 0; +} + +static int +prepare_cmac_xform(struct rte_crypto_sym_xform *xform) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_auth_xform *auth_xform = &xform->auth; + + xform->type = RTE_CRYPTO_SYM_XFORM_AUTH; + + auth_xform->algo = RTE_CRYPTO_AUTH_AES_CMAC; + auth_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ? + RTE_CRYPTO_AUTH_OP_GENERATE : RTE_CRYPTO_AUTH_OP_VERIFY; + auth_xform->digest_length = vec.cipher_auth.digest.len; + auth_xform->key.data = vec.cipher_auth.key.val; + auth_xform->key.length = vec.cipher_auth.key.len; + + cap_idx.algo.auth = auth_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH; + + 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_auth(cap, + auth_xform->key.length, + auth_xform->digest_length, 0) != 0) { + RTE_LOG(ERR, USER1, "PMD %s key length %u IV length %u\n", + info.device_name, auth_xform->key.length, + auth_xform->digest_length); + return -EPERM; + } + + return 0; +} + +static int +prepare_ccm_xform(struct rte_crypto_sym_xform *xform) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_aead_xform *aead_xform = &xform->aead; + + xform->type = RTE_CRYPTO_SYM_XFORM_AEAD; + + aead_xform->algo = RTE_CRYPTO_AEAD_AES_CCM; + aead_xform->aad_length = vec.aead.aad.len; + aead_xform->digest_length = vec.aead.digest.len; + aead_xform->iv.offset = IV_OFF; + aead_xform->iv.length = vec.iv.len; + aead_xform->key.data = vec.aead.key.val; + aead_xform->key.length = vec.aead.key.len; + aead_xform->op = (info.op == FIPS_TEST_ENC_AUTH_GEN) ? + RTE_CRYPTO_AEAD_OP_ENCRYPT : + RTE_CRYPTO_AEAD_OP_DECRYPT; + + cap_idx.algo.aead = aead_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_AEAD; + + 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_aead(cap, + aead_xform->key.length, + aead_xform->digest_length, aead_xform->aad_length, + aead_xform->iv.length) != 0) { + RTE_LOG(ERR, USER1, + "PMD %s key_len %u tag_len %u aad_len %u iv_len %u\n", + info.device_name, aead_xform->key.length, + aead_xform->digest_length, + aead_xform->aad_length, + aead_xform->iv.length); + return -EPERM; + } + + return 0; +} + +static int +prepare_sha_xform(struct rte_crypto_sym_xform *xform) +{ + const struct rte_cryptodev_symmetric_capability *cap; + struct rte_cryptodev_sym_capability_idx cap_idx; + struct rte_crypto_auth_xform *auth_xform = &xform->auth; + + xform->type = RTE_CRYPTO_SYM_XFORM_AUTH; + + auth_xform->algo = info.interim_info.sha_data.algo; + auth_xform->op = RTE_CRYPTO_AUTH_OP_GENERATE; + auth_xform->digest_length = vec.cipher_auth.digest.len; + + cap_idx.algo.auth = auth_xform->algo; + cap_idx.type = RTE_CRYPTO_SYM_XFORM_AUTH; + + 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_auth(cap, + auth_xform->key.length, + auth_xform->digest_length, 0) != 0) { + RTE_LOG(ERR, USER1, "PMD %s key length %u digest length %u\n", + info.device_name, auth_xform->key.length, + auth_xform->digest_length); + return -EPERM; + } + + return 0; +} + +static void +get_writeback_data(struct fips_val *val) +{ + val->val = rte_pktmbuf_mtod(env.mbuf, uint8_t *); + val->len = rte_pktmbuf_pkt_len(env.mbuf); +} + +static int +fips_run_test(void) +{ + struct rte_crypto_sym_xform xform = {0}; + uint16_t n_deqd; + int ret; + + ret = test_ops.prepare_xform(&xform); + if (ret < 0) + return ret; + + 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, USER1, "Error %i: Init session\n", + ret); + goto exit; + } + + ret = test_ops.prepare_op(); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Prepare op\n", + ret); + goto exit; + } + + if (rte_cryptodev_enqueue_burst(env.dev_id, 0, &env.op, 1) < 1) { + RTE_LOG(ERR, USER1, "Error: Failed enqueue\n"); + ret = -1; + goto exit; + } + + do { + struct rte_crypto_op *deqd_op; + + n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, + 1); + } while (n_deqd == 0); + + vec.status = env.op->status; + +exit: + rte_cryptodev_sym_session_clear(env.dev_id, env.sess); + rte_cryptodev_sym_session_free(env.sess); + env.sess = NULL; + + return ret; +} + +static int +fips_generic_test(void) +{ + struct fips_val val; + int ret; + + fips_test_write_one_case(); + + ret = fips_run_test(); + if (ret < 0) { + if (ret == -EPERM) { + fprintf(info.fp_wr, "Bypass\n\n"); + return 0; + } + + return ret; + } + + get_writeback_data(&val); + + switch (info.file_type) { + case FIPS_TYPE_REQ: + case FIPS_TYPE_RSP: + if (info.parse_writeback == NULL) + return -EPERM; + ret = info.parse_writeback(&val); + if (ret < 0) + return ret; + break; + case FIPS_TYPE_FAX: + if (info.kat_check == NULL) + return -EPERM; + ret = info.kat_check(&val); + if (ret < 0) + return ret; + break; + } + + fprintf(info.fp_wr, "\n"); + + return 0; +} + +static int +fips_mct_tdes_test(void) +{ +#define TDES_BLOCK_SIZE 8 +#define TDES_EXTERN_ITER 400 +#define TDES_INTERN_ITER 10000 + struct fips_val val, val_key; + uint8_t prev_out[TDES_BLOCK_SIZE] = {0}; + uint8_t prev_prev_out[TDES_BLOCK_SIZE] = {0}; + uint8_t prev_in[TDES_BLOCK_SIZE] = {0}; + uint32_t i, j, k; + int ret; + + for (i = 0; i < TDES_EXTERN_ITER; i++) { + if (i != 0) + update_info_vec(i); + + fips_test_write_one_case(); + + for (j = 0; j < TDES_INTERN_ITER; j++) { + ret = fips_run_test(); + if (ret < 0) { + if (ret == -EPERM) { + fprintf(info.fp_wr, "Bypass\n"); + return 0; + } + + return ret; + } + + get_writeback_data(&val); + + if (info.op == FIPS_TEST_DEC_AUTH_VERIF) + memcpy(prev_in, vec.ct.val, TDES_BLOCK_SIZE); + + if (j == 0) { + memcpy(prev_out, val.val, TDES_BLOCK_SIZE); + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + memcpy(vec.pt.val, vec.iv.val, + TDES_BLOCK_SIZE); + memcpy(vec.iv.val, val.val, + TDES_BLOCK_SIZE); + } else { + memcpy(vec.iv.val, vec.ct.val, + TDES_BLOCK_SIZE); + memcpy(vec.ct.val, val.val, + TDES_BLOCK_SIZE); + } + continue; + } + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE); + memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE); + } else { + memcpy(vec.iv.val, vec.ct.val, TDES_BLOCK_SIZE); + memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE); + } + + if (j == TDES_INTERN_ITER - 1) + continue; + + memcpy(prev_out, val.val, TDES_BLOCK_SIZE); + + if (j == TDES_INTERN_ITER - 3) + memcpy(prev_prev_out, val.val, TDES_BLOCK_SIZE); + } + + info.parse_writeback(&val); + fprintf(info.fp_wr, "\n"); + + if (i == TDES_EXTERN_ITER - 1) + continue; + + /** update key */ + memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key)); + + if (info.interim_info.tdes_data.nb_keys == 0) { + if (memcmp(val_key.val, val_key.val + 8, 8) == 0) + info.interim_info.tdes_data.nb_keys = 1; + else if (memcmp(val_key.val, val_key.val + 16, 8) == 0) + info.interim_info.tdes_data.nb_keys = 2; + else + info.interim_info.tdes_data.nb_keys = 3; + + } + + for (k = 0; k < TDES_BLOCK_SIZE; k++) { + + switch (info.interim_info.tdes_data.nb_keys) { + case 3: + val_key.val[k] ^= val.val[k]; + val_key.val[k + 8] ^= prev_out[k]; + val_key.val[k + 16] ^= prev_prev_out[k]; + break; + case 2: + val_key.val[k] ^= val.val[k]; + val_key.val[k + 8] ^= prev_out[k]; + val_key.val[k + 16] ^= val.val[k]; + break; + default: /* case 1 */ + val_key.val[k] ^= val.val[k]; + val_key.val[k + 8] ^= val.val[k]; + val_key.val[k + 16] ^= val.val[k]; + break; + } + + } + + for (k = 0; k < 24; k++) + val_key.val[k] = (__builtin_popcount(val_key.val[k]) & + 0x1) ? + val_key.val[k] : (val_key.val[k] ^ 0x1); + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + memcpy(vec.iv.val, val.val, TDES_BLOCK_SIZE); + memcpy(vec.pt.val, prev_out, TDES_BLOCK_SIZE); + } else { + memcpy(vec.iv.val, prev_out, TDES_BLOCK_SIZE); + memcpy(vec.ct.val, val.val, TDES_BLOCK_SIZE); + } + } + + return 0; +} + +static int +fips_mct_aes_test(void) +{ +#define AES_BLOCK_SIZE 16 +#define AES_EXTERN_ITER 100 +#define AES_INTERN_ITER 1000 + struct fips_val val, val_key; + uint8_t prev_out[AES_BLOCK_SIZE] = {0}; + uint8_t prev_in[AES_BLOCK_SIZE] = {0}; + uint32_t i, j, k; + int ret; + + for (i = 0; i < AES_EXTERN_ITER; i++) { + if (i != 0) + update_info_vec(i); + + fips_test_write_one_case(); + + for (j = 0; j < AES_INTERN_ITER; j++) { + ret = fips_run_test(); + if (ret < 0) { + if (ret == -EPERM) { + fprintf(info.fp_wr, "Bypass\n"); + return 0; + } + + return ret; + } + + get_writeback_data(&val); + + if (info.op == FIPS_TEST_DEC_AUTH_VERIF) + memcpy(prev_in, vec.ct.val, AES_BLOCK_SIZE); + + if (j == 0) { + memcpy(prev_out, val.val, AES_BLOCK_SIZE); + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + memcpy(vec.pt.val, vec.iv.val, + AES_BLOCK_SIZE); + memcpy(vec.iv.val, val.val, + AES_BLOCK_SIZE); + } else { + memcpy(vec.ct.val, vec.iv.val, + AES_BLOCK_SIZE); + memcpy(vec.iv.val, prev_in, + AES_BLOCK_SIZE); + } + continue; + } + + if (info.op == FIPS_TEST_ENC_AUTH_GEN) { + memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE); + memcpy(vec.pt.val, prev_out, AES_BLOCK_SIZE); + } else { + memcpy(vec.iv.val, prev_in, AES_BLOCK_SIZE); + memcpy(vec.ct.val, prev_out, AES_BLOCK_SIZE); + } + + if (j == AES_INTERN_ITER - 1) + continue; + + memcpy(prev_out, val.val, AES_BLOCK_SIZE); + } + + info.parse_writeback(&val); + fprintf(info.fp_wr, "\n"); + + if (i == AES_EXTERN_ITER - 1) + continue; + + /** update key */ + memcpy(&val_key, &vec.cipher_auth.key, sizeof(val_key)); + for (k = 0; k < vec.cipher_auth.key.len; k++) { + switch (vec.cipher_auth.key.len) { + case 16: + val_key.val[k] ^= val.val[k]; + break; + case 24: + if (k < 8) + val_key.val[k] ^= prev_out[k + 8]; + else + val_key.val[k] ^= val.val[k - 8]; + break; + case 32: + if (k < 16) + val_key.val[k] ^= prev_out[k]; + else + val_key.val[k] ^= val.val[k - 16]; + break; + default: + return -1; + } + } + + if (info.op == FIPS_TEST_DEC_AUTH_VERIF) + memcpy(vec.iv.val, val.val, AES_BLOCK_SIZE); + } + + return 0; +} + +static int +fips_mct_sha_test(void) +{ +#define SHA_EXTERN_ITER 100 +#define SHA_INTERN_ITER 1000 +#define SHA_MD_BLOCK 3 + struct fips_val val, md[SHA_MD_BLOCK]; + char temp[MAX_DIGEST_SIZE*2]; + int ret; + uint32_t i, j; + + val.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0); + for (i = 0; i < SHA_MD_BLOCK; i++) + md[i].val = rte_malloc(NULL, (MAX_DIGEST_SIZE*2), 0); + + rte_free(vec.pt.val); + vec.pt.val = rte_malloc(NULL, (MAX_DIGEST_SIZE*SHA_MD_BLOCK), 0); + + fips_test_write_one_case(); + fprintf(info.fp_wr, "\n"); + + for (j = 0; j < SHA_EXTERN_ITER; j++) { + + memcpy(md[0].val, vec.cipher_auth.digest.val, + vec.cipher_auth.digest.len); + md[0].len = vec.cipher_auth.digest.len; + memcpy(md[1].val, vec.cipher_auth.digest.val, + vec.cipher_auth.digest.len); + md[1].len = vec.cipher_auth.digest.len; + memcpy(md[2].val, vec.cipher_auth.digest.val, + vec.cipher_auth.digest.len); + md[2].len = vec.cipher_auth.digest.len; + + for (i = 0; i < (SHA_INTERN_ITER); i++) { + + memcpy(vec.pt.val, md[0].val, + (size_t)md[0].len); + memcpy((vec.pt.val + md[0].len), md[1].val, + (size_t)md[1].len); + memcpy((vec.pt.val + md[0].len + md[1].len), + md[2].val, + (size_t)md[2].len); + vec.pt.len = md[0].len + md[1].len + md[2].len; + + ret = fips_run_test(); + if (ret < 0) { + if (ret == -EPERM) { + fprintf(info.fp_wr, "Bypass\n\n"); + return 0; + } + return ret; + } + + get_writeback_data(&val); + + memcpy(md[0].val, md[1].val, md[1].len); + md[0].len = md[1].len; + memcpy(md[1].val, md[2].val, md[2].len); + md[1].len = md[2].len; + + memcpy(md[2].val, (val.val + vec.pt.len), + vec.cipher_auth.digest.len); + md[2].len = vec.cipher_auth.digest.len; + } + + memcpy(vec.cipher_auth.digest.val, md[2].val, md[2].len); + vec.cipher_auth.digest.len = md[2].len; + + fprintf(info.fp_wr, "COUNT = %u\n", j); + + writeback_hex_str("", temp, &vec.cipher_auth.digest); + + fprintf(info.fp_wr, "MD = %s\n\n", temp); + } + + for (i = 0; i < (SHA_MD_BLOCK); i++) + rte_free(md[i].val); + + rte_free(vec.pt.val); + + return 0; +} + + +static int +init_test_ops(void) +{ + switch (info.algo) { + case FIPS_TEST_ALGO_AES: + test_ops.prepare_op = prepare_cipher_op; + test_ops.prepare_xform = prepare_aes_xform; + if (info.interim_info.aes_data.test_type == AESAVS_TYPE_MCT) + test_ops.test = fips_mct_aes_test; + else + test_ops.test = fips_generic_test; + break; + case FIPS_TEST_ALGO_HMAC: + test_ops.prepare_op = prepare_auth_op; + test_ops.prepare_xform = prepare_hmac_xform; + test_ops.test = fips_generic_test; + break; + case FIPS_TEST_ALGO_TDES: + test_ops.prepare_op = prepare_cipher_op; + test_ops.prepare_xform = prepare_tdes_xform; + if (info.interim_info.tdes_data.test_type == TDES_MCT) + test_ops.test = fips_mct_tdes_test; + else + test_ops.test = fips_generic_test; + break; + case FIPS_TEST_ALGO_AES_GCM: + test_ops.prepare_op = prepare_aead_op; + test_ops.prepare_xform = prepare_gcm_xform; + test_ops.test = fips_generic_test; + break; + case FIPS_TEST_ALGO_AES_CMAC: + test_ops.prepare_op = prepare_auth_op; + test_ops.prepare_xform = prepare_cmac_xform; + test_ops.test = fips_generic_test; + break; + case FIPS_TEST_ALGO_AES_CCM: + test_ops.prepare_op = prepare_aead_op; + test_ops.prepare_xform = prepare_ccm_xform; + test_ops.test = fips_generic_test; + break; + case FIPS_TEST_ALGO_SHA: + test_ops.prepare_op = prepare_auth_op; + test_ops.prepare_xform = prepare_sha_xform; + if (info.interim_info.sha_data.test_type == SHA_MCT) + test_ops.test = fips_mct_sha_test; + else + test_ops.test = fips_generic_test; + break; + default: + return -1; + } + + return 0; +} + +static void +print_test_block(void) +{ + uint32_t i; + + for (i = 0; i < info.nb_vec_lines; i++) + printf("%s\n", info.vec[i]); + + printf("\n"); +} + +static int +fips_test_one_file(void) +{ + int fetch_ret = 0, ret; + + + ret = init_test_ops(); + if (ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Init test op\n", ret); + return ret; + } + + while (ret >= 0 && fetch_ret == 0) { + fetch_ret = fips_test_fetch_one_block(); + if (fetch_ret < 0) { + RTE_LOG(ERR, USER1, "Error %i: Fetch block\n", + fetch_ret); + ret = fetch_ret; + goto error_one_case; + } + + if (info.nb_vec_lines == 0) { + if (fetch_ret == -EOF) + break; + + fprintf(info.fp_wr, "\n"); + continue; + } + + ret = fips_test_parse_one_case(); + switch (ret) { + case 0: + ret = test_ops.test(); + if (ret == 0) + break; + RTE_LOG(ERR, USER1, "Error %i: test block\n", + ret); + goto error_one_case; + case 1: + break; + default: + RTE_LOG(ERR, USER1, "Error %i: Parse block\n", + ret); + goto error_one_case; + } + + continue; +error_one_case: + print_test_block(); + } + + fips_test_clear(); + + return ret; + +} diff --git a/src/seastar/dpdk/examples/fips_validation/meson.build b/src/seastar/dpdk/examples/fips_validation/meson.build new file mode 100644 index 000000000..6dd63082c --- /dev/null +++ b/src/seastar/dpdk/examples/fips_validation/meson.build @@ -0,0 +1,22 @@ +# SPDX-License-Identifier: BSD-3-Clause +# Copyright(c) 2018 Intel Corporation + +# meson file, for building this example as part of a main DPDK build. +# +# To build this example as a standalone application with an already-installed +# DPDK instance, use 'make' + +deps += ['cryptodev'] +allow_experimental_apis = true +sources = files( + 'fips_validation_aes.c', + 'fips_validation.c', + 'fips_validation_hmac.c', + 'fips_validation_tdes.c', + 'fips_validation_gcm.c', + 'fips_validation_cmac.c', + 'fips_validation_ccm.c', + 'fips_validation_sha.c', + 'fips_dev_self_test.c', + 'main.c' +) |