DPDK patches and discussions
 help / color / mirror / Atom feed
* [PATCH v1 0/5] FIPS asymmetric validation
@ 2022-08-12 11:57 Gowrishankar Muthukrishnan
  2022-08-12 11:57 ` [PATCH v1 1/5] examples/fips_validation: fix parsing test group info Gowrishankar Muthukrishnan
                   ` (6 more replies)
  0 siblings, 7 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-08-12 11:57 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

This patch series adds support in fips_validation app to perform
asymmetric validation. To start with, RSA algorithm is used in
the evaluation. For the key value pairs which is multiprecision
in arithmetic, openssl library is used.

Gowrishankar Muthukrishnan (5):
  examples/fips_validation: fix parsing test group info
  examples/fips_validation: add interim parse writeback
  examples/fips_validation: add function to calculate SHA hash size
  examples/fips_validation: fix buffer size to parse JSON string
  examples/fips_validation: add asymmetric validation

 config/meson.build                            |   6 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |  18 +-
 examples/fips_validation/fips_validation.h    |  58 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 534 ++++++++++++++++++
 .../fips_validation/fips_validation_sha.c     |  39 +-
 examples/fips_validation/main.c               | 465 ++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 9 files changed, 1025 insertions(+), 110 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v1 1/5] examples/fips_validation: fix parsing test group info
  2022-08-12 11:57 [PATCH v1 0/5] FIPS asymmetric validation Gowrishankar Muthukrishnan
@ 2022-08-12 11:57 ` Gowrishankar Muthukrishnan
  2022-08-12 11:57 ` [PATCH v1 2/5] examples/fips_validation: add interim parse writeback Gowrishankar Muthukrishnan
                   ` (5 subsequent siblings)
  6 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-08-12 11:57 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

If a test group does not have expected key, it should not crash.
This patch fixes parsing test group info to continue further
when a key does not exist (as in asym tests).

Fixes: 58cc98801eb ("examples/fips_validation: add JSON parsing")

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 6c9f5e42a4..06aeffe495 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -488,6 +488,9 @@ fips_test_parse_one_json_group(void)
 		for (i = 0; info.interim_callbacks[i].key != NULL; i++) {
 			param = json_object_get(json_info.json_test_group,
 					info.interim_callbacks[i].key);
+			if (!param)
+				continue;
+
 			switch (json_typeof(param)) {
 			case JSON_STRING:
 				snprintf(json_value, 256, "%s", json_string_value(param));
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v1 2/5] examples/fips_validation: add interim parse writeback
  2022-08-12 11:57 [PATCH v1 0/5] FIPS asymmetric validation Gowrishankar Muthukrishnan
  2022-08-12 11:57 ` [PATCH v1 1/5] examples/fips_validation: fix parsing test group info Gowrishankar Muthukrishnan
@ 2022-08-12 11:57 ` Gowrishankar Muthukrishnan
  2022-08-12 11:57 ` [PATCH v1 3/5] examples/fips_validation: add function to calculate SHA hash size Gowrishankar Muthukrishnan
                   ` (4 subsequent siblings)
  6 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-08-12 11:57 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Asym tests need a callback to write interim info in expected output.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.c | 6 ++++++
 examples/fips_validation/fips_validation.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 06aeffe495..e755654cd0 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -512,6 +512,12 @@ fips_test_parse_one_json_group(void)
 			if (ret < 0)
 				return ret;
 		}
+
+		if (info.parse_interim_writeback) {
+			ret = info.parse_interim_writeback(NULL);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	return 0;
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index f42040f460..a6288e17e5 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -228,6 +228,7 @@ struct fips_test_interim_info {
 	const struct fips_test_callback *interim_callbacks;
 	const struct fips_test_callback *writeback_callbacks;
 
+	post_prcess_t parse_interim_writeback;
 	post_prcess_t parse_writeback;
 	post_prcess_t kat_check;
 };
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v1 3/5] examples/fips_validation: add function to calculate SHA hash size
  2022-08-12 11:57 [PATCH v1 0/5] FIPS asymmetric validation Gowrishankar Muthukrishnan
  2022-08-12 11:57 ` [PATCH v1 1/5] examples/fips_validation: fix parsing test group info Gowrishankar Muthukrishnan
  2022-08-12 11:57 ` [PATCH v1 2/5] examples/fips_validation: add interim parse writeback Gowrishankar Muthukrishnan
@ 2022-08-12 11:57 ` Gowrishankar Muthukrishnan
  2022-08-12 11:57 ` [PATCH v1 4/5] examples/fips_validation: fix buffer size to parse JSON string Gowrishankar Muthukrishnan
                   ` (3 subsequent siblings)
  6 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-08-12 11:57 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add function to calculate hash size for a given SHA hash algorithm.

Fixes: d5c247145c2 ("examples/fips_validation: add parsing for SHA")

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.h    |  3 ++
 .../fips_validation/fips_validation_sha.c     | 39 ++++++++++++-------
 2 files changed, 27 insertions(+), 15 deletions(-)

diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index a6288e17e5..4732341dd3 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -293,6 +293,9 @@ parse_test_sha_json_algorithm(void);
 int
 parse_test_sha_json_test_type(void);
 
+int
+parse_test_sha_hash_size(enum rte_crypto_auth_algorithm algo);
+
 int
 parse_test_tdes_json_init(void);
 #endif /* USE_JANSSON */
diff --git a/examples/fips_validation/fips_validation_sha.c b/examples/fips_validation/fips_validation_sha.c
index 75b073c15d..cac2a25e6c 100644
--- a/examples/fips_validation/fips_validation_sha.c
+++ b/examples/fips_validation/fips_validation_sha.c
@@ -33,6 +33,22 @@ struct plain_hash_size_conversion {
 		{"64", RTE_CRYPTO_AUTH_SHA512},
 };
 
+int
+parse_test_sha_hash_size(enum rte_crypto_auth_algorithm algo)
+{
+	int ret = -EINVAL;
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(phsc); i++) {
+		if (phsc[i].algo == algo) {
+			ret = atoi(phsc[i].str);
+			break;
+		}
+	}
+
+	return ret;
+}
+
 static int
 parse_interim_algo(__rte_unused const char *key,
 		char *text,
@@ -212,6 +228,7 @@ parse_test_sha_json_algorithm(void)
 	json_t *algorithm_object;
 	const char *algorithm_str;
 	uint32_t i;
+	int sz;
 
 	algorithm_object = json_object_get(json_info.json_vector_set, "algorithm");
 	algorithm_str = json_string_value(algorithm_object);
@@ -226,23 +243,15 @@ parse_test_sha_json_algorithm(void)
 	if (i == RTE_DIM(json_algorithms))
 		return -1;
 
-	for (i = 0; i < RTE_DIM(phsc); i++) {
-		if (info.interim_info.sha_data.algo == phsc[i].algo) {
-			vec.cipher_auth.digest.len = atoi(phsc[i].str);
-			free(vec.cipher_auth.digest.val);
-			vec.cipher_auth.digest.val = calloc(1, vec.cipher_auth.digest.len);
-			if (vec.cipher_auth.digest.val == NULL)
-				return -1;
-
-			break;
-		}
-	}
+	sz = parse_test_sha_hash_size(info.interim_info.sha_data.algo);
+	if (sz < 0)
+		return -1;
 
-	if (i == RTE_DIM(phsc)) {
-		free(vec.cipher_auth.digest.val);
-		vec.cipher_auth.digest.val = NULL;
+	free(vec.cipher_auth.digest.val);
+	vec.cipher_auth.digest.len = sz;
+	vec.cipher_auth.digest.val = calloc(1, sz);
+	if (vec.cipher_auth.digest.val == NULL)
 		return -1;
-	}
 
 	return 0;
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v1 4/5] examples/fips_validation: fix buffer size to parse JSON string
  2022-08-12 11:57 [PATCH v1 0/5] FIPS asymmetric validation Gowrishankar Muthukrishnan
                   ` (2 preceding siblings ...)
  2022-08-12 11:57 ` [PATCH v1 3/5] examples/fips_validation: add function to calculate SHA hash size Gowrishankar Muthukrishnan
@ 2022-08-12 11:57 ` Gowrishankar Muthukrishnan
  2022-08-12 11:57 ` [PATCH v1 5/5] examples/fips_validation: add asymmetric validation Gowrishankar Muthukrishnan
                   ` (2 subsequent siblings)
  6 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-08-12 11:57 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

In asym op, while parsing test interim info, existing buffer of size
256 bytes is not sufficient, hence setting it to maximum that a test
would need.

Fixes: 58cc98801eb ("examples/fips_validation: add JSON parsing")

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.c | 7 ++++---
 examples/fips_validation/fips_validation.h | 7 +++++++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index e755654cd0..be0634c3ac 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -484,7 +484,7 @@ fips_test_parse_one_json_group(void)
 	json_t *param;
 
 	if (info.interim_callbacks) {
-		char json_value[256];
+		char json_value[FIPS_TEST_JSON_BUF_LEN];
 		for (i = 0; info.interim_callbacks[i].key != NULL; i++) {
 			param = json_object_get(json_info.json_test_group,
 					info.interim_callbacks[i].key);
@@ -493,11 +493,12 @@ fips_test_parse_one_json_group(void)
 
 			switch (json_typeof(param)) {
 			case JSON_STRING:
-				snprintf(json_value, 256, "%s", json_string_value(param));
+				snprintf(json_value, sizeof(json_value), "%s",
+						 json_string_value(param));
 				break;
 
 			case JSON_INTEGER:
-				snprintf(json_value, 255, "%"JSON_INTEGER_FORMAT,
+				snprintf(json_value, sizeof(json_value), "%"JSON_INTEGER_FORMAT,
 						json_integer_value(param));
 				break;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 4732341dd3..926fe94563 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -183,6 +183,13 @@ struct xts_interim_data {
 };
 
 #ifdef USE_JANSSON
+/*
+ * Maximum length of buffer to hold any json string.
+ * Esp, in asym op, modulo bits decide char buffer size.
+ * max = (modulo / 4)
+ */
+#define FIPS_TEST_JSON_BUF_LEN (4096 / 4)
+
 struct fips_test_json_info {
 	/* Information used for reading from json */
 	json_t *json_root;
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [PATCH v1 5/5] examples/fips_validation: add asymmetric validation
  2022-08-12 11:57 [PATCH v1 0/5] FIPS asymmetric validation Gowrishankar Muthukrishnan
                   ` (3 preceding siblings ...)
  2022-08-12 11:57 ` [PATCH v1 4/5] examples/fips_validation: fix buffer size to parse JSON string Gowrishankar Muthukrishnan
@ 2022-08-12 11:57 ` Gowrishankar Muthukrishnan
  2022-09-23 16:29 ` [PATCH v1 0/5] FIPS " Dooley, Brian
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
  6 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-08-12 11:57 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add support for asymmetric crypto validation starting with RSA.
For the generation of crypto values which is multiprecision in
math, openssl library is used only for this purpose.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 config/meson.build                            |   6 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  47 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 534 ++++++++++++++++++
 examples/fips_validation/main.c               | 465 ++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 8 files changed, 977 insertions(+), 92 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

diff --git a/config/meson.build b/config/meson.build
index 7f7b6c92fd..ed21a8e470 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -226,6 +226,12 @@ if jansson_dep.found()
     dpdk_conf.set('RTE_HAS_JANSSON', 1)
 endif
 
+# check for openssl
+openssl_dep = dependency('openssl', required: false, method: 'pkg-config')
+if openssl_dep.found()
+    dpdk_conf.set('RTE_HAS_OPENSSL', 1)
+endif
+
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
 pcap_lib = is_windows ? 'wpcap' : 'pcap'
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index 33a8c97575..5e9ad2d006 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -66,6 +66,7 @@ ACVP
     * SHA (1, 256, 384, 512) - AFT, MCT
     * TDES-CBC - AFT, MCT
     * TDES-ECB - AFT, MCT
+    * RSA
 
 
 Application Information
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index be0634c3ac..5d485a2bd5 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -471,6 +471,8 @@ fips_test_parse_one_json_vector_set(void)
 	else if (strstr(algo_str, "TDES-CBC") ||
 		strstr(algo_str, "TDES-ECB"))
 		info.algo = FIPS_TEST_ALGO_TDES;
+	else if (strstr(algo_str, "RSA"))
+		info.algo = FIPS_TEST_ALGO_RSA;
 	else
 		return -EINVAL;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 926fe94563..d1ecaef3b4 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -42,6 +42,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_SHA,
+		FIPS_TEST_ALGO_RSA,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -55,6 +56,9 @@ enum file_types {
 enum fips_test_op {
 	FIPS_TEST_ENC_AUTH_GEN = 1,
 	FIPS_TEST_DEC_AUTH_VERIF,
+	FIPS_TEST_ASYM_KEYGEN,
+	FIPS_TEST_ASYM_SIGGEN,
+	FIPS_TEST_ASYM_SIGVER
 };
 
 #define MAX_LINE_PER_VECTOR            16
@@ -78,11 +82,22 @@ struct fips_test_vector {
 			struct fips_val aad;
 		} aead;
 	};
+	struct {
+		struct fips_val seed;
+		struct fips_val signature;
+		struct fips_val e;
+		struct fips_val n;
+		struct fips_val d;
+		struct fips_val p;
+		struct fips_val q;
+		struct fips_val dp;
+		struct fips_val dq;
+		struct fips_val qinv;
+	} rsa;
 
 	struct fips_val pt;
 	struct fips_val ct;
 	struct fips_val iv;
-
 	enum rte_crypto_op_status status;
 };
 
@@ -138,6 +153,12 @@ enum fips_sha_test_types {
 	SHA_MCT
 };
 
+enum fips_rsa_test_types {
+	RSA_AFT = 0,
+	RSA_GDT,
+	RSA_KAT
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -164,8 +185,9 @@ struct ccm_interim_data {
 };
 
 struct sha_interim_data {
-	enum fips_sha_test_types test_type;
+	/* keep algo always on top as it is also used in asym digest */
 	enum rte_crypto_auth_algorithm algo;
+	enum fips_sha_test_types test_type;
 };
 
 struct gcm_interim_data {
@@ -182,6 +204,14 @@ struct xts_interim_data {
 	enum xts_tweak_modes tweak_mode;
 };
 
+struct rsa_interim_data {
+	enum rte_crypto_auth_algorithm auth;
+	uint16_t modulo;
+	uint16_t saltlen;
+	enum rte_crypto_rsa_padding_type padding;
+	enum rte_crypto_rsa_priv_key_type privkey;
+};
+
 #ifdef USE_JANSSON
 /*
  * Maximum length of buffer to hold any json string.
@@ -227,6 +257,7 @@ struct fips_test_interim_info {
 		struct sha_interim_data sha_data;
 		struct gcm_interim_data gcm_data;
 		struct xts_interim_data xts_data;
+		struct rsa_interim_data rsa_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -305,6 +336,9 @@ parse_test_sha_hash_size(enum rte_crypto_auth_algorithm algo);
 
 int
 parse_test_tdes_json_init(void);
+
+int
+parse_test_rsa_json_init(void);
 #endif /* USE_JANSSON */
 
 int
@@ -366,11 +400,14 @@ update_info_vec(uint32_t count);
 
 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 *);
+typedef int (*fips_prepare_sym_xform_t)(struct rte_crypto_sym_xform *);
+typedef int (*fips_prepare_asym_xform_t)(struct rte_crypto_asym_xform *);
 
 struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
+	fips_prepare_sym_xform_t prepare_sym_xform;
+	fips_prepare_asym_xform_t prepare_asym_xform;
+	fips_prepare_op_t prepare_sym_op;
+	fips_prepare_op_t prepare_asym_op;
 	fips_test_one_case_t test;
 };
 
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index 6b3d158629..e76c38ffc8 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -80,12 +80,12 @@ parser_read_gcm_pt_len(const char *key, char *src,
 
 	if (vec.pt.len == 0) {
 		info.interim_info.gcm_data.is_gmac = 1;
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 	} else {
 		info.interim_info.gcm_data.is_gmac = 0;
-		test_ops.prepare_op = prepare_aead_op;
-		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_xform = prepare_gcm_xform;
 	}
 
 	return ret;
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
new file mode 100644
index 0000000000..8d7c1fd3cf
--- /dev/null
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -0,0 +1,534 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell.
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/random.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef USE_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#endif /* USE_OPENSSL */
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define TESTTYPE_JSON_STR	"testType"
+#define KEYFORMAT_JSON_STR	"keyFormat"
+#define SIGTYPE_JSON_STR "sigType"
+#define MOD_JSON_STR	"modulo"
+#define HASH_JSON_STR	"hashAlg"
+#define SALT_JSON_STR	"saltLen"
+#define E_JSON_STR	"e"
+#define N_JSON_STR	"n"
+
+#define SEED_JSON_STR	"seed"
+#define MSG_JSON_STR	"message"
+#define SIG_JSON_STR	"signature"
+
+#ifdef USE_JANSSON
+struct {
+	uint8_t type;
+	const char *desc;
+} rsa_test_types[] = {
+		{RSA_AFT, "AFT"},
+		{RSA_GDT, "GDT"},
+		{RSA_KAT, "KAT"},
+};
+
+struct {
+	enum rte_crypto_auth_algorithm auth;
+	const char *desc;
+} rsa_auth_algs[] = {
+		{RTE_CRYPTO_AUTH_SHA1, "SHA-1"},
+		{RTE_CRYPTO_AUTH_SHA256, "SHA2-224"},
+		{RTE_CRYPTO_AUTH_SHA256, "SHA2-256"},
+		{RTE_CRYPTO_AUTH_SHA384, "SHA2-384"},
+		{RTE_CRYPTO_AUTH_SHA512, "SHA2-512"},
+};
+
+struct {
+	enum rte_crypto_rsa_padding_type padding;
+	const char *desc;
+} rsa_padding_types[] = {
+		{RTE_CRYPTO_RSA_PADDING_NONE, "none"},
+		{RTE_CRYPTO_RSA_PADDING_PKCS1_5, "pkcs1v1.5"},
+		{RTE_CRYPTO_RSA_PADDING_OAEP, "oaep"},
+		{RTE_CRYPTO_RSA_PADDING_PSS, "pss"},
+};
+
+struct {
+	enum rte_crypto_rsa_priv_key_type privkey;
+	const char *desc;
+} rsa_privkey_types[] = {
+		{RTE_RSA_KEY_TYPE_EXP, "standard"},
+		{RTE_RSA_KEY_TYPE_QT, "crt"},
+};
+
+#ifdef USE_OPENSSL
+static int
+prepare_vec_rsa(void)
+{
+	BIGNUM *p = NULL, *q = NULL, *n = NULL, *d = NULL, *e = NULL;
+	BIGNUM *dp = NULL, *dq = NULL, *qinv = NULL;
+	BIGNUM *r0, *r1, *r2, *r3, *r4;
+	BIGNUM *m = NULL, *r = NULL;
+	int bits, ret = -1, i;
+	char modbuf[8], *buf;
+	BN_CTX *ctx = NULL;
+	unsigned long pid;
+
+	/* Seed PRNG */
+	if (vec.rsa.seed.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		RAND_seed((char *)info.one_line_text, strlen(info.one_line_text));
+	} else {
+		pid = getpid();
+		RAND_seed(&pid, sizeof(pid));
+	}
+
+	if (!RAND_status())
+		return -1;
+
+	/* Check if e is known already */
+	if (vec.rsa.e.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		ret = BN_hex2bn(&e, info.one_line_text);
+		if ((uint32_t)ret != strlen(info.one_line_text))
+			goto err;
+	}
+
+	/* BN context initialization */
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto err;
+
+	BN_CTX_start(ctx);
+	r0 = BN_CTX_get(ctx);
+	r1 = BN_CTX_get(ctx);
+	r2 = BN_CTX_get(ctx);
+	r3 = BN_CTX_get(ctx);
+	r4 = BN_CTX_get(ctx);
+	if (!r4)
+		goto err;
+
+	/* Calculate bit length for prime numbers */
+	m = BN_new();
+	if (!m)
+		goto err;
+
+	snprintf(modbuf, sizeof(modbuf), "%d", info.interim_info.rsa_data.modulo);
+	if (!BN_dec2bn(&m, modbuf))
+		goto err;
+
+	r = BN_new();
+	if (!r)
+		goto err;
+
+	if (!BN_rshift1(r, m))
+		goto err;
+
+	buf = BN_bn2dec(r);
+	bits = atoi(buf);
+
+	p = BN_new();
+	if (!p)
+		goto err;
+
+	q = BN_new();
+	if (!q)
+		goto err;
+
+	n = BN_new();
+	if (!n)
+		goto err;
+
+	d = BN_new();
+	if (!d)
+		goto err;
+
+	/* Generate p and q suitably for RSA */
+	for (i = 0; i < 10; i++) {
+		uint8_t j = 0;
+
+		if (!BN_generate_prime_ex(p, bits, 0, NULL, NULL, NULL))
+			goto err;
+
+		do {
+			RAND_add(&j, sizeof(j), 1);
+			if (!BN_generate_prime_ex(q, bits, 0, NULL, NULL, NULL))
+				goto err;
+
+		} while ((BN_cmp(p, q) == 0) && (j++ < 100));
+
+		if (j >= 100) {
+			RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate q", j);
+			goto err;
+		}
+
+		/* pq */
+		if (!BN_mul(n, p, q, ctx))
+			goto err;
+
+		/* p-1 */
+		if (!BN_sub(r1, p, BN_value_one()))
+			goto err;
+
+		/* q-1 */
+		if (!BN_sub(r2, q, BN_value_one()))
+			goto err;
+
+		/* (p-1 * q-1) */
+		if (!BN_mul(r0, r1, r2, ctx))
+			goto err;
+
+		/* gcd(p-1, q-1)*/
+		if (!BN_gcd(r3, r1, r2, ctx))
+			goto err;
+
+		/* lcm(p-1, q-1) */
+		if (!BN_div(r4, r, r0, r3, ctx))
+			goto err;
+
+		/* check if div and rem are non-zero */
+		if (!r4 || !r)
+			goto err;
+
+		/* 0 < e < lcm */
+		if (!e) {
+			int k = 0;
+
+			e = BN_new();
+			do {
+				RAND_add(&k, sizeof(k), 1);
+				if (!BN_rand(e, 32, 1, 1))
+					goto err;
+
+				if (!BN_gcd(r3, e, r4, ctx))
+					goto err;
+
+				if (BN_is_one(r3))
+					break;
+			} while (k++ < 10);
+
+			if (k >= 10) {
+				RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate e",
+					k);
+				goto err;
+			}
+		}
+
+		/* (de) mod lcm == 1 */
+		if (!BN_mod_inverse(d, e, r4, ctx))
+			goto err;
+
+		if (!BN_gcd(r3, r1, e, ctx))
+			goto err;
+
+		if (!BN_gcd(r4, r2, e, ctx))
+			goto err;
+
+		/* check if gcd(p-1, e) and gcd(q-1, e) are 1 */
+		if (BN_is_one(r3) && BN_is_one(r4))
+			break;
+	}
+
+	if (i >= 10) {
+		RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate p and q", i);
+		goto err;
+	}
+
+	/* d mod (p-1) */
+	dp = BN_new();
+	if (!dp)
+		goto err;
+
+	if (!BN_mod(dp, d, r1, ctx))
+		goto err;
+
+	/* d mod (q-1) */
+	dq = BN_new();
+	if (!dq)
+		goto err;
+
+	if (!BN_mod(dq, d, r2, ctx))
+		goto err;
+
+	/* modinv of q and p */
+	qinv = BN_new();
+	if (!qinv)
+		goto err;
+
+	if (!BN_mod_inverse(qinv, q, p, ctx))
+		goto err;
+
+	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
+	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
+	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
+	parse_uint8_hex_str("", BN_bn2hex(n), &vec.rsa.n);
+	parse_uint8_hex_str("", BN_bn2hex(d), &vec.rsa.d);
+	parse_uint8_hex_str("", BN_bn2hex(dp), &vec.rsa.dp);
+	parse_uint8_hex_str("", BN_bn2hex(dq), &vec.rsa.dq);
+	parse_uint8_hex_str("", BN_bn2hex(qinv), &vec.rsa.qinv);
+
+	ret = 0;
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(m);
+	BN_free(r);
+	BN_free(p);
+	BN_free(q);
+	BN_free(n);
+	BN_free(d);
+	BN_free(e);
+	return ret;
+}
+#else
+static int
+prepare_vec_rsa(void)
+{
+	/*
+	 * Generate RSA values.
+	 */
+	return -ENOTSUP;
+}
+#endif /* USE_OPENSSL */
+
+static int
+parse_test_rsa_json_interim_writeback(struct fips_val *val)
+{
+	RTE_SET_USED(val);
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		/* For siggen tests, RSA values can be created soon after
+		 * the test group data are parsed.
+		 */
+		if (vec.rsa.e.val) {
+			rte_free(vec.rsa.e.val);
+			vec.rsa.e.val = NULL;
+		}
+
+		if (prepare_vec_rsa() < 0)
+			return -1;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "e", obj);
+	}
+
+	return 0;
+}
+
+static int
+parse_test_rsa_json_writeback(struct fips_val *val)
+{
+	json_t *tcId;
+
+	RTE_SET_USED(val);
+
+	tcId = json_object_get(json_info.json_test_case, "tcId");
+
+	json_info.json_write_case = json_object();
+	json_object_set(json_info.json_write_case, "tcId", tcId);
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "seed", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "e", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.p);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "p", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.q);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "q", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.d);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "d", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "signature", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
+		else
+			json_object_set_new(json_info.json_write_case, "testPassed", json_false());
+	}
+
+	return 0;
+}
+
+static int
+parse_interim_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t i;
+
+	RTE_SET_USED(val);
+
+	if (strcmp(key, SIGTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_padding_types); i++)
+			if (strstr(src, rsa_padding_types[i].desc)) {
+				info.interim_info.rsa_data.padding = rsa_padding_types[i].padding;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_padding_types))
+			return -EINVAL;
+
+	}  else if (strcmp(key, MOD_JSON_STR) == 0) {
+		info.interim_info.rsa_data.modulo = atoi(src);
+	} else if (strcmp(key, HASH_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_auth_algs); i++)
+			if (strstr(src, rsa_auth_algs[i].desc)) {
+				info.interim_info.rsa_data.auth = rsa_auth_algs[i].auth;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_auth_algs))
+			return -EINVAL;
+
+	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
+		info.interim_info.rsa_data.saltlen = atoi(src);
+	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_test_types); i++)
+			if (strstr(src, rsa_test_types[i].desc)) {
+				info.parse_writeback = parse_test_rsa_json_writeback;
+				break;
+			}
+
+		if (!info.parse_writeback || i >= RTE_DIM(rsa_test_types))
+			return -EINVAL;
+
+	} else if (strcmp(key, KEYFORMAT_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_privkey_types); i++)
+			if (strstr(src, rsa_privkey_types[i].desc)) {
+				info.interim_info.rsa_data.privkey = rsa_privkey_types[i].privkey;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_privkey_types))
+			return -EINVAL;
+
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
+{
+	parse_uint8_hex_str(key, src, val);
+
+	/* For keygen tests, key "e" can be the end of input data
+	 * to generate RSA values.
+	 */
+	return prepare_vec_rsa();
+}
+
+struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{KEYFORMAT_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
+		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_keygen_json_vectors[] = {
+		{SEED_JSON_STR, parse_uint8_hex_str, &vec.rsa.seed},
+		{E_JSON_STR, parse_keygen_e_str, &vec.rsa.e},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_rsa_json_init(void)
+{
+	json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode");
+	const char *mode_str = json_string_value(mode_obj);
+
+	info.callbacks = NULL;
+	info.parse_writeback = NULL;
+	info.interim_callbacks = NULL;
+	info.parse_interim_writeback = NULL;
+
+	if (strcmp(mode_str, "keyGen") == 0) {
+		info.op = FIPS_TEST_ASYM_KEYGEN;
+		info.callbacks = rsa_keygen_json_vectors;
+		info.interim_callbacks = rsa_keygen_interim_json_vectors;
+	} else if (strcmp(mode_str, "sigGen") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGGEN;
+		info.callbacks = rsa_siggen_json_vectors;
+		info.interim_callbacks = rsa_siggen_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
+	} else if (strcmp(mode_str, "sigVer") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGVER;
+		info.callbacks = rsa_sigver_json_vectors;
+		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+#endif /* USE_JANSSON */
+
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 8babbb3298..d3b7bdad39 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -36,6 +36,8 @@ enum {
 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
 #define OPT_USE_JSON                "use-json"
 	OPT_USE_JSON_NUM,
+#define OPT_CRYPTODEV_ASYM          "asymmetric"
+	OPT_CRYPTODEV_ASYM_NUM,
 };
 
 struct fips_test_vector vec;
@@ -50,27 +52,133 @@ struct cryptodev_fips_validate_env {
 	const char *rsp_path;
 	uint32_t is_path_folder;
 	uint8_t dev_id;
-	uint8_t dev_support_sgl;
-	uint16_t mbuf_data_room;
 	struct rte_mempool *mpool;
-	struct rte_mempool *sess_mpool;
 	struct rte_mempool *sess_priv_mpool;
-	struct rte_mempool *op_pool;
+	struct fips_sym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_sym_session *sess;
+		struct rte_crypto_op *op;
+	} sym;
+	struct fips_asym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_asym_session *sess;
+		struct rte_crypto_op *op;
+	} asym;
+	struct rte_crypto_op *op;
+	uint8_t dev_support_sgl;
+	uint16_t mbuf_data_room;
 	struct rte_mbuf *mbuf;
 	uint8_t *digest;
 	uint16_t digest_len;
-	struct rte_crypto_op *op;
-	struct rte_cryptodev_sym_session *sess;
+	bool is_asym_test;
 	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
 static int
-cryptodev_fips_validate_app_int(void)
+cryptodev_fips_validate_app_sym_init(void)
+{
+	struct rte_cryptodev_info dev_info;
+	struct fips_sym_env *sym = &env.sym;
+	int ret;
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	ret = -ENOMEM;
+	sym->sess_mpool = rte_cryptodev_sym_session_pool_create(
+			"FIPS_SYM_SESS_MEMPOOL", 16, 0, 0, 0, rte_socket_id());
+	if (!sym->sess_mpool)
+		goto error_exit;
+
+	sym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_SYM_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!sym->op_pool)
+		goto error_exit;
+
+	sym->op = rte_crypto_op_alloc(sym->op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!sym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_sym_uninit(void)
+{
+	struct fips_sym_env *sym = &env.sym;
+
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(sym->op);
+	rte_cryptodev_sym_session_clear(env.dev_id, sym->sess);
+	rte_cryptodev_sym_session_free(sym->sess);
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_asym_init(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+	int ret;
+
+	ret = -ENOMEM;
+	asym->sess_mpool = rte_cryptodev_asym_session_pool_create(
+			"FIPS_ASYM_SESS_MEMPOOL", 16, 0, 0, rte_socket_id());
+	if (!asym->sess_mpool)
+		goto error_exit;
+
+	asym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_ASYM_POOL",
+			RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!asym->op_pool)
+		goto error_exit;
+
+	asym->op = rte_crypto_op_alloc(asym->op_pool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!asym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_asym_uninit(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+
+	rte_crypto_op_free(asym->op);
+	rte_cryptodev_asym_session_free(env.dev_id, asym->sess);
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_init(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
-	struct rte_cryptodev_info dev_info;
 	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
 			env.dev_id);
 	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
@@ -89,50 +197,30 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	rte_cryptodev_info_get(env.dev_id, &dev_info);
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
-		env.dev_support_sgl = 1;
-	else
-		env.dev_support_sgl = 0;
-
+	ret = -ENOMEM;
 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
 			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
 			env.mbuf_data_room, 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)
+	ret = cryptodev_fips_validate_app_sym_init();
+	if (ret < 0)
 		goto error_exit;
 
-	env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	if (!env.op)
-		goto error_exit;
+	if (env.is_asym_test) {
+		ret = cryptodev_fips_validate_app_asym_init();
+		if (ret < 0)
+			goto error_exit;
+	}
 
-	qp_conf.mp_session = env.sess_mpool;
+	qp_conf.mp_session = env.sym.sess_mpool;
 	qp_conf.mp_session_private = env.sess_priv_mpool;
 
 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
@@ -147,26 +235,21 @@ cryptodev_fips_validate_app_int(void)
 	return 0;
 
 error_exit:
-
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
 	rte_mempool_free(env.sess_priv_mpool);
-	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);
+	cryptodev_fips_validate_app_sym_uninit();
+
+	if (env.is_asym_test)
+		cryptodev_fips_validate_app_asym_uninit();
+
 	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
@@ -262,6 +345,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+		{OPT_CRYPTODEV_ASYM, no_argument,
+				NULL, OPT_CRYPTODEV_ASYM_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -374,6 +459,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			}
 			break;
 
+		case OPT_CRYPTODEV_ASYM_NUM:
+			env.is_asym_test = true;
+			break;
+
 		default:
 			cryptodev_fips_validate_usage(prgname);
 			return -EINVAL;
@@ -414,7 +503,7 @@ main(int argc, char *argv[])
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
 
-	ret = cryptodev_fips_validate_app_int();
+	ret = cryptodev_fips_validate_app_init();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
 		return -1;
@@ -653,7 +742,7 @@ prepare_cipher_op(void)
 		sym->cipher.data.length = vec.ct.len;
 	}
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	sym->m_src = env.mbuf;
 	sym->cipher.data.offset = 0;
@@ -701,7 +790,7 @@ prepare_auth_op(void)
 		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	return 0;
 }
@@ -757,7 +846,55 @@ prepare_aead_op(void)
 	sym->aead.aad.data = vec.aead.aad.val;
 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
+
+	return 0;
+}
+
+static int
+prepare_rsa_op(void)
+{
+	struct rte_crypto_asym_op *asym;
+	struct fips_val msg;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+
+	asym = env.op->asym;
+	asym->rsa.padding.type = info.interim_info.rsa_data.padding;
+	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
+
+	if (env.digest) {
+		msg.val = env.digest;
+		msg.len = env.digest_len;
+	} else {
+		msg.val = vec.pt.val;
+		msg.len = vec.pt.len;
+	}
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+
+		if (vec.rsa.signature.val)
+			rte_free(vec.rsa.signature.val);
+
+		vec.rsa.signature.val = rte_zmalloc(NULL, vec.rsa.n.len, 0);
+		vec.rsa.signature.len = vec.rsa.n.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = 0;
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = vec.rsa.signature.len;
+	} else {
+		RTE_LOG(ERR, USER1, "Invalid op %d\n", info.op);
+		return -EINVAL;
+	}
+
+	rte_crypto_op_attach_asym_session(env.op, env.asym.sess);
 
 	return 0;
 }
@@ -1145,6 +1282,88 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_rsa_xform(struct rte_crypto_asym_xform *xform)
+{
+	const struct rte_cryptodev_asymmetric_xform_capability *cap;
+	struct rte_cryptodev_asym_capability_idx cap_idx;
+	struct rte_cryptodev_info dev_info;
+
+	xform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	xform->next = NULL;
+
+	cap_idx.type = xform->xform_type;
+	cap = rte_cryptodev_asym_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;
+	}
+
+	xform->rsa.key_type = RTE_RSA_KEY_TYPE_QT;
+	switch (info.op) {
+	case FIPS_TEST_ASYM_SIGGEN:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_SIGN)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_SIGN);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_SIGVER:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_VERIFY)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_VERIFY);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_KEYGEN:
+		xform->rsa.key_type = info.interim_info.rsa_data.privkey;
+		break;
+	default:
+		break;
+	}
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	switch (xform->rsa.key_type) {
+	case RTE_RSA_KEY_TYPE_QT:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support QT key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.qt.p.data = vec.rsa.p.val;
+		xform->rsa.qt.p.length = vec.rsa.p.len;
+		xform->rsa.qt.q.data = vec.rsa.q.val;
+		xform->rsa.qt.q.length = vec.rsa.q.len;
+		xform->rsa.qt.dP.data = vec.rsa.dp.val;
+		xform->rsa.qt.dP.length = vec.rsa.dp.len;
+		xform->rsa.qt.dQ.data = vec.rsa.dq.val;
+		xform->rsa.qt.dQ.length = vec.rsa.dq.len;
+		xform->rsa.qt.qInv.data = vec.rsa.qinv.val;
+		xform->rsa.qt.qInv.length = vec.rsa.qinv.len;
+		break;
+	case RTE_RSA_KEY_TYPE_EXP:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support EXP key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.d.data = vec.rsa.d.val;
+		xform->rsa.d.length = vec.rsa.d.len;
+		break;
+	default:
+		break;
+	}
+
+	xform->rsa.e.data = vec.rsa.e.val;
+	xform->rsa.e.length = vec.rsa.e.len;
+	xform->rsa.n.data = vec.rsa.n.val;
+	xform->rsa.n.length = vec.rsa.n.len;
+	return 0;
+}
+
 static int
 get_writeback_data(struct fips_val *val)
 {
@@ -1191,29 +1410,29 @@ get_writeback_data(struct fips_val *val)
 }
 
 static int
-fips_run_test(void)
+fips_run_sym_test(void)
 {
 	struct rte_crypto_sym_xform xform = {0};
 	uint16_t n_deqd;
 	int ret;
 
-	ret = test_ops.prepare_xform(&xform);
+	ret = test_ops.prepare_sym_xform(&xform);
 	if (ret < 0)
 		return ret;
 
-	env.sess = rte_cryptodev_sym_session_create(env.sess_mpool);
-	if (!env.sess)
+	env.sym.sess = rte_cryptodev_sym_session_create(env.sym.sess_mpool);
+	if (!env.sym.sess)
 		return -ENOMEM;
 
 	ret = rte_cryptodev_sym_session_init(env.dev_id,
-			env.sess, &xform, env.sess_priv_mpool);
+			env.sym.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();
+	ret = test_ops.prepare_sym_op();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
 				ret);
@@ -1229,20 +1448,90 @@ fips_run_test(void)
 	do {
 		struct rte_crypto_op *deqd_op;
 
-		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
-				1);
+		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;
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sym.sess);
+	rte_cryptodev_sym_session_free(env.sym.sess);
+	env.sym.sess = NULL;
 
 	return ret;
 }
 
+static int
+fips_run_asym_test(void)
+{
+	struct rte_crypto_asym_xform xform = {0};
+	struct rte_crypto_asym_op *asym;
+	struct rte_crypto_op *deqd_op;
+	int ret;
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		RTE_SET_USED(asym);
+		ret = 0;
+		goto exit;
+	}
+
+	asym = env.op->asym;
+	ret = test_ops.prepare_asym_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	ret = rte_cryptodev_asym_session_create(env.dev_id, &xform,  env.asym.sess_mpool,
+			(void *)&env.asym.sess);
+	if (ret < 0)
+		return ret;
+
+	ret = test_ops.prepare_asym_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;
+	}
+
+	while (rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1) == 0)
+		rte_pause();
+
+	vec.status = env.op->status;
+
+ exit:
+	if (env.asym.sess)
+		rte_cryptodev_asym_session_free(env.dev_id, env.asym.sess);
+
+	env.asym.sess = NULL;
+	return ret;
+}
+
+static int
+fips_run_test(void)
+{
+	int ret;
+
+	env.op = env.sym.op;
+	if (env.is_asym_test) {
+		vec.cipher_auth.digest.len = parse_test_sha_hash_size(
+						info.interim_info.rsa_data.auth);
+		test_ops.prepare_sym_xform = prepare_sha_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		ret = fips_run_sym_test();
+		if (ret < 0)
+			return ret;
+	} else {
+		return fips_run_sym_test();
+	}
+
+	env.op = env.asym.op;
+	return fips_run_asym_test();
+}
+
 static int
 fips_generic_test(void)
 {
@@ -1265,9 +1554,11 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	ret = get_writeback_data(&val);
-	if (ret < 0)
-		return ret;
+	if (!env.is_asym_test) {
+		ret = get_writeback_data(&val);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1814,60 +2105,65 @@ init_test_ops(void)
 	switch (info.algo) {
 	case FIPS_TEST_ALGO_AES_CBC:
 	case FIPS_TEST_ALGO_AES:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform  = prepare_aes_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
 	case FIPS_TEST_ALGO_AES_XTS:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform = prepare_xts_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_xform = prepare_xts_xform;
+		test_ops.test = fips_generic_test;
+		break;
+	case FIPS_TEST_ALGO_RSA:
+		test_ops.prepare_asym_op = prepare_rsa_op;
+		test_ops.prepare_asym_xform = prepare_rsa_xform;
 		test_ops.test = fips_generic_test;
 		break;
 	default:
 		if (strstr(info.file_name, "TECB") ||
 				strstr(info.file_name, "TCBC")) {
 			info.algo = FIPS_TEST_ALGO_TDES;
-			test_ops.prepare_op = prepare_cipher_op;
-			test_ops.prepare_xform	= prepare_tdes_xform;
+			test_ops.prepare_sym_op = prepare_cipher_op;
+			test_ops.prepare_sym_xform = prepare_tdes_xform;
 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
 				test_ops.test = fips_mct_tdes_test;
 			else
@@ -2033,6 +2329,9 @@ fips_test_one_test_group(void)
 	case FIPS_TEST_ALGO_TDES:
 		ret = parse_test_tdes_json_init();
 		break;
+	case FIPS_TEST_ALGO_RSA:
+		ret = parse_test_rsa_json_init();
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 8bca26a095..d310093189 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -18,6 +18,7 @@ sources = files(
         'fips_validation_ccm.c',
         'fips_validation_sha.c',
         'fips_validation_xts.c',
+        'fips_validation_rsa.c',
         'fips_dev_self_test.c',
         'main.c',
 )
@@ -26,3 +27,8 @@ if dpdk_conf.has('RTE_HAS_JANSSON')
     ext_deps += jansson_dep
     cflags += '-DUSE_JANSSON'
 endif
+
+if dpdk_conf.has('RTE_HAS_OPENSSL')
+    ext_deps += openssl_dep
+    cflags += '-DUSE_OPENSSL'
+endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [PATCH v1 0/5] FIPS asymmetric validation
  2022-08-12 11:57 [PATCH v1 0/5] FIPS asymmetric validation Gowrishankar Muthukrishnan
                   ` (4 preceding siblings ...)
  2022-08-12 11:57 ` [PATCH v1 5/5] examples/fips_validation: add asymmetric validation Gowrishankar Muthukrishnan
@ 2022-09-23 16:29 ` Dooley, Brian
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
  6 siblings, 0 replies; 39+ messages in thread
From: Dooley, Brian @ 2022-09-23 16:29 UTC (permalink / raw)
  To: Gowrishankar Muthukrishnan, dev
  Cc: Anoob Joseph, Zhang, Roy Fan, Akhil Goyal, jerinj

> -----Original Message-----
> From: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
> Sent: Friday, August 12, 2022 12:57 PM
> To: dev@dpdk.org
> Cc: Anoob Joseph <anoobj@marvell.com>; Zhang, Roy Fan
> <roy.fan.zhang@intel.com>; Dooley, Brian <brian.dooley@intel.com>; Akhil
> Goyal <gakhil@marvell.com>; jerinj@marvell.com; Gowrishankar
> Muthukrishnan <gmuthukrishn@marvell.com>
> Subject: [PATCH v1 0/5] FIPS asymmetric validation
> 
> This patch series adds support in fips_validation app to perform asymmetric
> validation. To start with, RSA algorithm is used in the evaluation. For the key
> value pairs which is multiprecision in arithmetic, openssl library is used.
> 
> Gowrishankar Muthukrishnan (5):
>   examples/fips_validation: fix parsing test group info
>   examples/fips_validation: add interim parse writeback
>   examples/fips_validation: add function to calculate SHA hash size
>   examples/fips_validation: fix buffer size to parse JSON string
>   examples/fips_validation: add asymmetric validation
> 
>  config/meson.build                            |   6 +
>  doc/guides/sample_app_ug/fips_validation.rst  |   1 +
>  examples/fips_validation/fips_validation.c    |  18 +-
>  examples/fips_validation/fips_validation.h    |  58 +-
>  .../fips_validation/fips_validation_gcm.c     |   8 +-
>  .../fips_validation/fips_validation_rsa.c     | 534 ++++++++++++++++++
>  .../fips_validation/fips_validation_sha.c     |  39 +-
>  examples/fips_validation/main.c               | 465 ++++++++++++---
>  examples/fips_validation/meson.build          |   6 +
>  9 files changed, 1025 insertions(+), 110 deletions(-)  create mode 100644
> examples/fips_validation/fips_validation_rsa.c
> 
> --
> 2.25.1

Series-acked-by: Brian Dooley <brian.dooley@intel.com>

^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v2 0/7] FIPS asymmetric validation
  2022-08-12 11:57 [PATCH v1 0/5] FIPS asymmetric validation Gowrishankar Muthukrishnan
                   ` (5 preceding siblings ...)
  2022-09-23 16:29 ` [PATCH v1 0/5] FIPS " Dooley, Brian
@ 2022-09-27  7:26 ` Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 1/7] examples/fips_validation: fix parsing test group info Gowrishankar Muthukrishnan
                     ` (8 more replies)
  6 siblings, 9 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-09-27  7:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

This patch series adds support in fips_validation app to perform
asymmetric validation. To start with, RSA algorithm is used in
the evaluation. For the key value pairs which is multiprecision
in arithmetic, openssl library is used.

Changes:
 v2:
  - minor fixes in v1
  - addition of digest encoding for fips validation
  - addition of message randomization for fips conformance tests.

Gowrishankar Muthukrishnan (7):
  examples/fips_validation: fix parsing test group info
  examples/fips_validation: add interim parse writeback
  examples/fips_validation: add function to calculate SHA hash size
  examples/fips_validation: fix buffer size to parse JSON string
  examples/fips_validation: add asymmetric validation
  examples/fips_validation: encode digest with hash OID
  examples/fips_validation: randomize message for conformance test

 config/meson.build                            |   6 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |  18 +-
 examples/fips_validation/fips_validation.h    |  60 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
 .../fips_validation/fips_validation_sha.c     |  39 +-
 examples/fips_validation/main.c               | 542 ++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 9 files changed, 1200 insertions(+), 110 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v2 1/7] examples/fips_validation: fix parsing test group info
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
@ 2022-09-27  7:26   ` Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 2/7] examples/fips_validation: add interim parse writeback Gowrishankar Muthukrishnan
                     ` (7 subsequent siblings)
  8 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-09-27  7:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

If a test group does not have expected key, it should not crash.
This patch fixes parsing test group info to continue further
when a key does not exist (as in asym tests).

Fixes: 58cc98801eb ("examples/fips_validation: add JSON parsing")

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>
---
 examples/fips_validation/fips_validation.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 6c9f5e42a4..06aeffe495 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -488,6 +488,9 @@ fips_test_parse_one_json_group(void)
 		for (i = 0; info.interim_callbacks[i].key != NULL; i++) {
 			param = json_object_get(json_info.json_test_group,
 					info.interim_callbacks[i].key);
+			if (!param)
+				continue;
+
 			switch (json_typeof(param)) {
 			case JSON_STRING:
 				snprintf(json_value, 256, "%s", json_string_value(param));
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v2 2/7] examples/fips_validation: add interim parse writeback
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 1/7] examples/fips_validation: fix parsing test group info Gowrishankar Muthukrishnan
@ 2022-09-27  7:26   ` Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 3/7] examples/fips_validation: add function to calculate SHA hash size Gowrishankar Muthukrishnan
                     ` (6 subsequent siblings)
  8 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-09-27  7:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Asym tests need a callback to write interim info in expected output.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>
---
 examples/fips_validation/fips_validation.c | 6 ++++++
 examples/fips_validation/fips_validation.h | 1 +
 2 files changed, 7 insertions(+)

diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 06aeffe495..e755654cd0 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -512,6 +512,12 @@ fips_test_parse_one_json_group(void)
 			if (ret < 0)
 				return ret;
 		}
+
+		if (info.parse_interim_writeback) {
+			ret = info.parse_interim_writeback(NULL);
+			if (ret < 0)
+				return ret;
+		}
 	}
 
 	return 0;
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index f42040f460..a6288e17e5 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -228,6 +228,7 @@ struct fips_test_interim_info {
 	const struct fips_test_callback *interim_callbacks;
 	const struct fips_test_callback *writeback_callbacks;
 
+	post_prcess_t parse_interim_writeback;
 	post_prcess_t parse_writeback;
 	post_prcess_t kat_check;
 };
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v2 3/7] examples/fips_validation: add function to calculate SHA hash size
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 1/7] examples/fips_validation: fix parsing test group info Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 2/7] examples/fips_validation: add interim parse writeback Gowrishankar Muthukrishnan
@ 2022-09-27  7:26   ` Gowrishankar Muthukrishnan
  2022-10-07 17:52     ` Akhil Goyal
  2022-09-27  7:26   ` [v2 4/7] examples/fips_validation: fix buffer size to parse JSON string Gowrishankar Muthukrishnan
                     ` (5 subsequent siblings)
  8 siblings, 1 reply; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-09-27  7:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add function to calculate hash size for a given SHA hash algorithm.

Fixes: d5c247145c2 ("examples/fips_validation: add parsing for SHA")

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>

---
v2:
 - fixed include file
---
 examples/fips_validation/fips_validation.h    |  1 +
 .../fips_validation/fips_validation_sha.c     | 39 ++++++++++++-------
 2 files changed, 25 insertions(+), 15 deletions(-)

diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index a6288e17e5..6e5f2fce75 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -374,4 +374,5 @@ int prepare_gcm_xform(struct rte_crypto_sym_xform *xform);
 
 int prepare_gmac_xform(struct rte_crypto_sym_xform *xform);
 
+int parse_test_sha_hash_size(enum rte_crypto_auth_algorithm algo);
 #endif
diff --git a/examples/fips_validation/fips_validation_sha.c b/examples/fips_validation/fips_validation_sha.c
index 75b073c15d..cac2a25e6c 100644
--- a/examples/fips_validation/fips_validation_sha.c
+++ b/examples/fips_validation/fips_validation_sha.c
@@ -33,6 +33,22 @@ struct plain_hash_size_conversion {
 		{"64", RTE_CRYPTO_AUTH_SHA512},
 };
 
+int
+parse_test_sha_hash_size(enum rte_crypto_auth_algorithm algo)
+{
+	int ret = -EINVAL;
+	uint8_t i;
+
+	for (i = 0; i < RTE_DIM(phsc); i++) {
+		if (phsc[i].algo == algo) {
+			ret = atoi(phsc[i].str);
+			break;
+		}
+	}
+
+	return ret;
+}
+
 static int
 parse_interim_algo(__rte_unused const char *key,
 		char *text,
@@ -212,6 +228,7 @@ parse_test_sha_json_algorithm(void)
 	json_t *algorithm_object;
 	const char *algorithm_str;
 	uint32_t i;
+	int sz;
 
 	algorithm_object = json_object_get(json_info.json_vector_set, "algorithm");
 	algorithm_str = json_string_value(algorithm_object);
@@ -226,23 +243,15 @@ parse_test_sha_json_algorithm(void)
 	if (i == RTE_DIM(json_algorithms))
 		return -1;
 
-	for (i = 0; i < RTE_DIM(phsc); i++) {
-		if (info.interim_info.sha_data.algo == phsc[i].algo) {
-			vec.cipher_auth.digest.len = atoi(phsc[i].str);
-			free(vec.cipher_auth.digest.val);
-			vec.cipher_auth.digest.val = calloc(1, vec.cipher_auth.digest.len);
-			if (vec.cipher_auth.digest.val == NULL)
-				return -1;
-
-			break;
-		}
-	}
+	sz = parse_test_sha_hash_size(info.interim_info.sha_data.algo);
+	if (sz < 0)
+		return -1;
 
-	if (i == RTE_DIM(phsc)) {
-		free(vec.cipher_auth.digest.val);
-		vec.cipher_auth.digest.val = NULL;
+	free(vec.cipher_auth.digest.val);
+	vec.cipher_auth.digest.len = sz;
+	vec.cipher_auth.digest.val = calloc(1, sz);
+	if (vec.cipher_auth.digest.val == NULL)
 		return -1;
-	}
 
 	return 0;
 }
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v2 4/7] examples/fips_validation: fix buffer size to parse JSON string
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
                     ` (2 preceding siblings ...)
  2022-09-27  7:26   ` [v2 3/7] examples/fips_validation: add function to calculate SHA hash size Gowrishankar Muthukrishnan
@ 2022-09-27  7:26   ` Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 5/7] examples/fips_validation: add asymmetric validation Gowrishankar Muthukrishnan
                     ` (4 subsequent siblings)
  8 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-09-27  7:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

In asym op, while parsing test interim info, existing buffer of size
256 bytes is not sufficient, hence setting it to maximum that a test
would need.

Fixes: 58cc98801eb ("examples/fips_validation: add JSON parsing")

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>
---
 examples/fips_validation/fips_validation.c | 7 ++++---
 examples/fips_validation/fips_validation.h | 7 +++++++
 2 files changed, 11 insertions(+), 3 deletions(-)

diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index e755654cd0..be0634c3ac 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -484,7 +484,7 @@ fips_test_parse_one_json_group(void)
 	json_t *param;
 
 	if (info.interim_callbacks) {
-		char json_value[256];
+		char json_value[FIPS_TEST_JSON_BUF_LEN];
 		for (i = 0; info.interim_callbacks[i].key != NULL; i++) {
 			param = json_object_get(json_info.json_test_group,
 					info.interim_callbacks[i].key);
@@ -493,11 +493,12 @@ fips_test_parse_one_json_group(void)
 
 			switch (json_typeof(param)) {
 			case JSON_STRING:
-				snprintf(json_value, 256, "%s", json_string_value(param));
+				snprintf(json_value, sizeof(json_value), "%s",
+						 json_string_value(param));
 				break;
 
 			case JSON_INTEGER:
-				snprintf(json_value, 255, "%"JSON_INTEGER_FORMAT,
+				snprintf(json_value, sizeof(json_value), "%"JSON_INTEGER_FORMAT,
 						json_integer_value(param));
 				break;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 6e5f2fce75..43e5ffe4b0 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -183,6 +183,13 @@ struct xts_interim_data {
 };
 
 #ifdef USE_JANSSON
+/*
+ * Maximum length of buffer to hold any json string.
+ * Esp, in asym op, modulo bits decide char buffer size.
+ * max = (modulo / 4)
+ */
+#define FIPS_TEST_JSON_BUF_LEN (4096 / 4)
+
 struct fips_test_json_info {
 	/* Information used for reading from json */
 	json_t *json_root;
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v2 5/7] examples/fips_validation: add asymmetric validation
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
                     ` (3 preceding siblings ...)
  2022-09-27  7:26   ` [v2 4/7] examples/fips_validation: fix buffer size to parse JSON string Gowrishankar Muthukrishnan
@ 2022-09-27  7:26   ` Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 6/7] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
                     ` (3 subsequent siblings)
  8 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-09-27  7:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add support for asymmetric crypto validation starting with RSA.
For the generation of crypto values which is multiprecision in
math, openssl library is used only for this purpose.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>

--
v2:
 - improved handling priv key type.
---
 config/meson.build                            |   6 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  47 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 520 ++++++++++++++++++
 examples/fips_validation/main.c               | 464 +++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 8 files changed, 962 insertions(+), 92 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

diff --git a/config/meson.build b/config/meson.build
index 7f7b6c92fd..ed21a8e470 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -226,6 +226,12 @@ if jansson_dep.found()
     dpdk_conf.set('RTE_HAS_JANSSON', 1)
 endif
 
+# check for openssl
+openssl_dep = dependency('openssl', required: false, method: 'pkg-config')
+if openssl_dep.found()
+    dpdk_conf.set('RTE_HAS_OPENSSL', 1)
+endif
+
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
 pcap_lib = is_windows ? 'wpcap' : 'pcap'
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index 33a8c97575..5e9ad2d006 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -66,6 +66,7 @@ ACVP
     * SHA (1, 256, 384, 512) - AFT, MCT
     * TDES-CBC - AFT, MCT
     * TDES-ECB - AFT, MCT
+    * RSA
 
 
 Application Information
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index be0634c3ac..5d485a2bd5 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -471,6 +471,8 @@ fips_test_parse_one_json_vector_set(void)
 	else if (strstr(algo_str, "TDES-CBC") ||
 		strstr(algo_str, "TDES-ECB"))
 		info.algo = FIPS_TEST_ALGO_TDES;
+	else if (strstr(algo_str, "RSA"))
+		info.algo = FIPS_TEST_ALGO_RSA;
 	else
 		return -EINVAL;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 43e5ffe4b0..ed59322635 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -42,6 +42,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_SHA,
+		FIPS_TEST_ALGO_RSA,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -55,6 +56,9 @@ enum file_types {
 enum fips_test_op {
 	FIPS_TEST_ENC_AUTH_GEN = 1,
 	FIPS_TEST_DEC_AUTH_VERIF,
+	FIPS_TEST_ASYM_KEYGEN,
+	FIPS_TEST_ASYM_SIGGEN,
+	FIPS_TEST_ASYM_SIGVER
 };
 
 #define MAX_LINE_PER_VECTOR            16
@@ -78,11 +82,22 @@ struct fips_test_vector {
 			struct fips_val aad;
 		} aead;
 	};
+	struct {
+		struct fips_val seed;
+		struct fips_val signature;
+		struct fips_val e;
+		struct fips_val n;
+		struct fips_val d;
+		struct fips_val p;
+		struct fips_val q;
+		struct fips_val dp;
+		struct fips_val dq;
+		struct fips_val qinv;
+	} rsa;
 
 	struct fips_val pt;
 	struct fips_val ct;
 	struct fips_val iv;
-
 	enum rte_crypto_op_status status;
 };
 
@@ -138,6 +153,12 @@ enum fips_sha_test_types {
 	SHA_MCT
 };
 
+enum fips_rsa_test_types {
+	RSA_AFT = 0,
+	RSA_GDT,
+	RSA_KAT
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -164,8 +185,9 @@ struct ccm_interim_data {
 };
 
 struct sha_interim_data {
-	enum fips_sha_test_types test_type;
+	/* keep algo always on top as it is also used in asym digest */
 	enum rte_crypto_auth_algorithm algo;
+	enum fips_sha_test_types test_type;
 };
 
 struct gcm_interim_data {
@@ -182,6 +204,14 @@ struct xts_interim_data {
 	enum xts_tweak_modes tweak_mode;
 };
 
+struct rsa_interim_data {
+	enum rte_crypto_auth_algorithm auth;
+	uint16_t modulo;
+	uint16_t saltlen;
+	enum rte_crypto_rsa_padding_type padding;
+	enum rte_crypto_rsa_priv_key_type privkey;
+};
+
 #ifdef USE_JANSSON
 /*
  * Maximum length of buffer to hold any json string.
@@ -227,6 +257,7 @@ struct fips_test_interim_info {
 		struct sha_interim_data sha_data;
 		struct gcm_interim_data gcm_data;
 		struct xts_interim_data xts_data;
+		struct rsa_interim_data rsa_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -302,6 +333,9 @@ parse_test_sha_json_test_type(void);
 
 int
 parse_test_tdes_json_init(void);
+
+int
+parse_test_rsa_json_init(void);
 #endif /* USE_JANSSON */
 
 int
@@ -363,11 +397,14 @@ update_info_vec(uint32_t count);
 
 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 *);
+typedef int (*fips_prepare_sym_xform_t)(struct rte_crypto_sym_xform *);
+typedef int (*fips_prepare_asym_xform_t)(struct rte_crypto_asym_xform *);
 
 struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
+	fips_prepare_sym_xform_t prepare_sym_xform;
+	fips_prepare_asym_xform_t prepare_asym_xform;
+	fips_prepare_op_t prepare_sym_op;
+	fips_prepare_op_t prepare_asym_op;
 	fips_test_one_case_t test;
 };
 
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index 6b3d158629..e76c38ffc8 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -80,12 +80,12 @@ parser_read_gcm_pt_len(const char *key, char *src,
 
 	if (vec.pt.len == 0) {
 		info.interim_info.gcm_data.is_gmac = 1;
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 	} else {
 		info.interim_info.gcm_data.is_gmac = 0;
-		test_ops.prepare_op = prepare_aead_op;
-		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_xform = prepare_gcm_xform;
 	}
 
 	return ret;
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
new file mode 100644
index 0000000000..d3699f54d0
--- /dev/null
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -0,0 +1,520 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell.
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/random.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef USE_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#endif /* USE_OPENSSL */
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define TESTTYPE_JSON_STR	"testType"
+#define SIGTYPE_JSON_STR "sigType"
+#define MOD_JSON_STR	"modulo"
+#define HASH_JSON_STR	"hashAlg"
+#define SALT_JSON_STR	"saltLen"
+#define E_JSON_STR	"e"
+#define N_JSON_STR	"n"
+
+#define SEED_JSON_STR	"seed"
+#define MSG_JSON_STR	"message"
+#define SIG_JSON_STR	"signature"
+
+#ifdef USE_JANSSON
+struct {
+	uint8_t type;
+	const char *desc;
+} rsa_test_types[] = {
+		{RSA_AFT, "AFT"},
+		{RSA_GDT, "GDT"},
+		{RSA_KAT, "KAT"},
+};
+
+struct {
+	enum rte_crypto_auth_algorithm auth;
+	const char *desc;
+} rsa_auth_algs[] = {
+		{RTE_CRYPTO_AUTH_SHA1, "SHA-1"},
+		{RTE_CRYPTO_AUTH_SHA224, "SHA2-224"},
+		{RTE_CRYPTO_AUTH_SHA256, "SHA2-256"},
+		{RTE_CRYPTO_AUTH_SHA384, "SHA2-384"},
+		{RTE_CRYPTO_AUTH_SHA512, "SHA2-512"},
+};
+
+struct {
+	enum rte_crypto_rsa_padding_type padding;
+	const char *desc;
+} rsa_padding_types[] = {
+		{RTE_CRYPTO_RSA_PADDING_NONE, "none"},
+		{RTE_CRYPTO_RSA_PADDING_PKCS1_5, "pkcs1v1.5"},
+		{RTE_CRYPTO_RSA_PADDING_OAEP, "oaep"},
+		{RTE_CRYPTO_RSA_PADDING_PSS, "pss"},
+};
+
+#ifdef USE_OPENSSL
+static int
+prepare_vec_rsa(void)
+{
+	BIGNUM *p = NULL, *q = NULL, *n = NULL, *d = NULL, *e = NULL;
+	BIGNUM *dp = NULL, *dq = NULL, *qinv = NULL;
+	BIGNUM *r0, *r1, *r2, *r3, *r4;
+	BIGNUM *m = NULL, *r = NULL;
+	int bits, ret = -1, i;
+	char modbuf[8], *buf;
+	BN_CTX *ctx = NULL;
+	unsigned long pid;
+
+	/* Seed PRNG */
+	if (vec.rsa.seed.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		RAND_seed((char *)info.one_line_text, strlen(info.one_line_text));
+	} else {
+		pid = getpid();
+		RAND_seed(&pid, sizeof(pid));
+	}
+
+	if (!RAND_status())
+		return -1;
+
+	/* Check if e is known already */
+	if (vec.rsa.e.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		ret = BN_hex2bn(&e, info.one_line_text);
+		if ((uint32_t)ret != strlen(info.one_line_text))
+			goto err;
+	}
+
+	/* BN context initialization */
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto err;
+
+	BN_CTX_start(ctx);
+	r0 = BN_CTX_get(ctx);
+	r1 = BN_CTX_get(ctx);
+	r2 = BN_CTX_get(ctx);
+	r3 = BN_CTX_get(ctx);
+	r4 = BN_CTX_get(ctx);
+	if (!r4)
+		goto err;
+
+	/* Calculate bit length for prime numbers */
+	m = BN_new();
+	if (!m)
+		goto err;
+
+	snprintf(modbuf, sizeof(modbuf), "%d", info.interim_info.rsa_data.modulo);
+	if (!BN_dec2bn(&m, modbuf))
+		goto err;
+
+	r = BN_new();
+	if (!r)
+		goto err;
+
+	if (!BN_rshift1(r, m))
+		goto err;
+
+	buf = BN_bn2dec(r);
+	bits = atoi(buf);
+
+	p = BN_new();
+	if (!p)
+		goto err;
+
+	q = BN_new();
+	if (!q)
+		goto err;
+
+	n = BN_new();
+	if (!n)
+		goto err;
+
+	d = BN_new();
+	if (!d)
+		goto err;
+
+	/* Generate p and q suitably for RSA */
+	for (i = 0; i < 10; i++) {
+		uint8_t j = 0;
+
+		if (!BN_generate_prime_ex(p, bits, 0, NULL, NULL, NULL))
+			goto err;
+
+		do {
+			RAND_add(&j, sizeof(j), 1);
+			if (!BN_generate_prime_ex(q, bits, 0, NULL, NULL, NULL))
+				goto err;
+
+		} while ((BN_cmp(p, q) == 0) && (j++ < 100));
+
+		if (j >= 100) {
+			RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate q", j);
+			goto err;
+		}
+
+		/* pq */
+		if (!BN_mul(n, p, q, ctx))
+			goto err;
+
+		/* p-1 */
+		if (!BN_sub(r1, p, BN_value_one()))
+			goto err;
+
+		/* q-1 */
+		if (!BN_sub(r2, q, BN_value_one()))
+			goto err;
+
+		/* (p-1 * q-1) */
+		if (!BN_mul(r0, r1, r2, ctx))
+			goto err;
+
+		/* gcd(p-1, q-1)*/
+		if (!BN_gcd(r3, r1, r2, ctx))
+			goto err;
+
+		/* lcm(p-1, q-1) */
+		if (!BN_div(r4, r, r0, r3, ctx))
+			goto err;
+
+		/* check if div and rem are non-zero */
+		if (!r4 || !r)
+			goto err;
+
+		/* 0 < e < lcm */
+		if (!e) {
+			int k = 0;
+
+			e = BN_new();
+			do {
+				RAND_add(&k, sizeof(k), 1);
+				if (!BN_rand(e, 32, 1, 1))
+					goto err;
+
+				if (!BN_gcd(r3, e, r4, ctx))
+					goto err;
+
+				if (BN_is_one(r3))
+					break;
+			} while (k++ < 10);
+
+			if (k >= 10) {
+				RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate e",
+					k);
+				goto err;
+			}
+		}
+
+		/* (de) mod lcm == 1 */
+		if (!BN_mod_inverse(d, e, r4, ctx))
+			goto err;
+
+		if (!BN_gcd(r3, r1, e, ctx))
+			goto err;
+
+		if (!BN_gcd(r4, r2, e, ctx))
+			goto err;
+
+		/* check if gcd(p-1, e) and gcd(q-1, e) are 1 */
+		if (BN_is_one(r3) && BN_is_one(r4))
+			break;
+	}
+
+	if (i >= 10) {
+		RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate p and q", i);
+		goto err;
+	}
+
+	/* d mod (p-1) */
+	dp = BN_new();
+	if (!dp)
+		goto err;
+
+	if (!BN_mod(dp, d, r1, ctx))
+		goto err;
+
+	/* d mod (q-1) */
+	dq = BN_new();
+	if (!dq)
+		goto err;
+
+	if (!BN_mod(dq, d, r2, ctx))
+		goto err;
+
+	/* modinv of q and p */
+	qinv = BN_new();
+	if (!qinv)
+		goto err;
+
+	if (!BN_mod_inverse(qinv, q, p, ctx))
+		goto err;
+
+	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
+	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
+	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
+	parse_uint8_hex_str("", BN_bn2hex(n), &vec.rsa.n);
+	parse_uint8_hex_str("", BN_bn2hex(d), &vec.rsa.d);
+	parse_uint8_hex_str("", BN_bn2hex(dp), &vec.rsa.dp);
+	parse_uint8_hex_str("", BN_bn2hex(dq), &vec.rsa.dq);
+	parse_uint8_hex_str("", BN_bn2hex(qinv), &vec.rsa.qinv);
+
+	ret = 0;
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(m);
+	BN_free(r);
+	BN_free(p);
+	BN_free(q);
+	BN_free(n);
+	BN_free(d);
+	BN_free(e);
+	return ret;
+}
+#else
+static int
+prepare_vec_rsa(void)
+{
+	/*
+	 * Generate RSA values.
+	 */
+	return -ENOTSUP;
+}
+#endif /* USE_OPENSSL */
+
+static int
+parse_test_rsa_json_interim_writeback(struct fips_val *val)
+{
+	RTE_SET_USED(val);
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		/* For siggen tests, RSA values can be created soon after
+		 * the test group data are parsed.
+		 */
+		if (vec.rsa.e.val) {
+			rte_free(vec.rsa.e.val);
+			vec.rsa.e.val = NULL;
+		}
+
+		if (prepare_vec_rsa() < 0)
+			return -1;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "e", obj);
+	}
+
+	return 0;
+}
+
+static int
+parse_test_rsa_json_writeback(struct fips_val *val)
+{
+	json_t *tcId;
+
+	RTE_SET_USED(val);
+
+	tcId = json_object_get(json_info.json_test_case, "tcId");
+
+	json_info.json_write_case = json_object();
+	json_object_set(json_info.json_write_case, "tcId", tcId);
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "seed", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "e", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.p);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "p", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.q);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "q", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.d);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "d", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "signature", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
+		else
+			json_object_set_new(json_info.json_write_case, "testPassed", json_false());
+	}
+
+	return 0;
+}
+
+static int
+parse_interim_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t i;
+
+	RTE_SET_USED(val);
+
+	if (strcmp(key, SIGTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_padding_types); i++)
+			if (strstr(src, rsa_padding_types[i].desc)) {
+				info.interim_info.rsa_data.padding = rsa_padding_types[i].padding;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_padding_types))
+			return -EINVAL;
+
+	}  else if (strcmp(key, MOD_JSON_STR) == 0) {
+		info.interim_info.rsa_data.modulo = atoi(src);
+	} else if (strcmp(key, HASH_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_auth_algs); i++)
+			if (strstr(src, rsa_auth_algs[i].desc)) {
+				info.interim_info.rsa_data.auth = rsa_auth_algs[i].auth;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_auth_algs))
+			return -EINVAL;
+
+	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
+		info.interim_info.rsa_data.saltlen = atoi(src);
+	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_test_types); i++)
+			if (strstr(src, rsa_test_types[i].desc)) {
+				info.parse_writeback = parse_test_rsa_json_writeback;
+				break;
+			}
+
+		if (!info.parse_writeback || i >= RTE_DIM(rsa_test_types))
+			return -EINVAL;
+
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
+{
+	parse_uint8_hex_str(key, src, val);
+
+	/* For keygen tests, key "e" can be the end of input data
+	 * to generate RSA values.
+	 */
+	return prepare_vec_rsa();
+}
+
+struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
+		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_keygen_json_vectors[] = {
+		{SEED_JSON_STR, parse_uint8_hex_str, &vec.rsa.seed},
+		{E_JSON_STR, parse_keygen_e_str, &vec.rsa.e},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_rsa_json_init(void)
+{
+	json_t *keyfmt_obj = json_object_get(json_info.json_vector_set, "keyFormat");
+	json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode");
+	const char *keyfmt_str = json_string_value(keyfmt_obj);
+	const char *mode_str = json_string_value(mode_obj);
+
+	info.callbacks = NULL;
+	info.parse_writeback = NULL;
+	info.interim_callbacks = NULL;
+	info.parse_interim_writeback = NULL;
+
+	if (strcmp(mode_str, "keyGen") == 0) {
+		info.op = FIPS_TEST_ASYM_KEYGEN;
+		info.callbacks = rsa_keygen_json_vectors;
+		info.interim_callbacks = rsa_keygen_interim_json_vectors;
+	} else if (strcmp(mode_str, "sigGen") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGGEN;
+		info.callbacks = rsa_siggen_json_vectors;
+		info.interim_callbacks = rsa_siggen_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
+	} else if (strcmp(mode_str, "sigVer") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGVER;
+		info.callbacks = rsa_sigver_json_vectors;
+		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+	} else {
+		return -EINVAL;
+	}
+
+	info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_QT;
+	if (keyfmt_str != NULL && strcmp(keyfmt_str, "standard") == 0)
+		info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_EXP;
+
+	return 0;
+}
+#endif /* USE_JANSSON */
+
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 8babbb3298..ed86c10350 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -36,6 +36,8 @@ enum {
 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
 #define OPT_USE_JSON                "use-json"
 	OPT_USE_JSON_NUM,
+#define OPT_CRYPTODEV_ASYM          "asymmetric"
+	OPT_CRYPTODEV_ASYM_NUM,
 };
 
 struct fips_test_vector vec;
@@ -50,27 +52,133 @@ struct cryptodev_fips_validate_env {
 	const char *rsp_path;
 	uint32_t is_path_folder;
 	uint8_t dev_id;
-	uint8_t dev_support_sgl;
-	uint16_t mbuf_data_room;
 	struct rte_mempool *mpool;
-	struct rte_mempool *sess_mpool;
 	struct rte_mempool *sess_priv_mpool;
-	struct rte_mempool *op_pool;
+	struct fips_sym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_sym_session *sess;
+		struct rte_crypto_op *op;
+	} sym;
+	struct fips_asym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_asym_session *sess;
+		struct rte_crypto_op *op;
+	} asym;
+	struct rte_crypto_op *op;
+	uint8_t dev_support_sgl;
+	uint16_t mbuf_data_room;
 	struct rte_mbuf *mbuf;
 	uint8_t *digest;
 	uint16_t digest_len;
-	struct rte_crypto_op *op;
-	struct rte_cryptodev_sym_session *sess;
+	bool is_asym_test;
 	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
 static int
-cryptodev_fips_validate_app_int(void)
+cryptodev_fips_validate_app_sym_init(void)
+{
+	struct rte_cryptodev_info dev_info;
+	struct fips_sym_env *sym = &env.sym;
+	int ret;
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	ret = -ENOMEM;
+	sym->sess_mpool = rte_cryptodev_sym_session_pool_create(
+			"FIPS_SYM_SESS_MEMPOOL", 16, 0, 0, 0, rte_socket_id());
+	if (!sym->sess_mpool)
+		goto error_exit;
+
+	sym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_SYM_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!sym->op_pool)
+		goto error_exit;
+
+	sym->op = rte_crypto_op_alloc(sym->op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!sym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_sym_uninit(void)
+{
+	struct fips_sym_env *sym = &env.sym;
+
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(sym->op);
+	rte_cryptodev_sym_session_clear(env.dev_id, sym->sess);
+	rte_cryptodev_sym_session_free(sym->sess);
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_asym_init(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+	int ret;
+
+	ret = -ENOMEM;
+	asym->sess_mpool = rte_cryptodev_asym_session_pool_create(
+			"FIPS_ASYM_SESS_MEMPOOL", 16, 0, 0, rte_socket_id());
+	if (!asym->sess_mpool)
+		goto error_exit;
+
+	asym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_ASYM_POOL",
+			RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!asym->op_pool)
+		goto error_exit;
+
+	asym->op = rte_crypto_op_alloc(asym->op_pool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!asym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_asym_uninit(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+
+	rte_crypto_op_free(asym->op);
+	rte_cryptodev_asym_session_free(env.dev_id, asym->sess);
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_init(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL, NULL};
-	struct rte_cryptodev_info dev_info;
 	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
 			env.dev_id);
 	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
@@ -89,50 +197,30 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	rte_cryptodev_info_get(env.dev_id, &dev_info);
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
-		env.dev_support_sgl = 1;
-	else
-		env.dev_support_sgl = 0;
-
+	ret = -ENOMEM;
 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
 			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
 			env.mbuf_data_room, 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)
+	ret = cryptodev_fips_validate_app_sym_init();
+	if (ret < 0)
 		goto error_exit;
 
-	env.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	if (!env.op)
-		goto error_exit;
+	if (env.is_asym_test) {
+		ret = cryptodev_fips_validate_app_asym_init();
+		if (ret < 0)
+			goto error_exit;
+	}
 
-	qp_conf.mp_session = env.sess_mpool;
+	qp_conf.mp_session = env.sym.sess_mpool;
 	qp_conf.mp_session_private = env.sess_priv_mpool;
 
 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
@@ -147,26 +235,21 @@ cryptodev_fips_validate_app_int(void)
 	return 0;
 
 error_exit:
-
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
 	rte_mempool_free(env.sess_priv_mpool);
-	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);
+	cryptodev_fips_validate_app_sym_uninit();
+
+	if (env.is_asym_test)
+		cryptodev_fips_validate_app_asym_uninit();
+
 	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
@@ -262,6 +345,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+		{OPT_CRYPTODEV_ASYM, no_argument,
+				NULL, OPT_CRYPTODEV_ASYM_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -374,6 +459,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			}
 			break;
 
+		case OPT_CRYPTODEV_ASYM_NUM:
+			env.is_asym_test = true;
+			break;
+
 		default:
 			cryptodev_fips_validate_usage(prgname);
 			return -EINVAL;
@@ -414,7 +503,7 @@ main(int argc, char *argv[])
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
 
-	ret = cryptodev_fips_validate_app_int();
+	ret = cryptodev_fips_validate_app_init();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
 		return -1;
@@ -653,7 +742,7 @@ prepare_cipher_op(void)
 		sym->cipher.data.length = vec.ct.len;
 	}
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	sym->m_src = env.mbuf;
 	sym->cipher.data.offset = 0;
@@ -701,7 +790,7 @@ prepare_auth_op(void)
 		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	return 0;
 }
@@ -757,7 +846,55 @@ prepare_aead_op(void)
 	sym->aead.aad.data = vec.aead.aad.val;
 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
+
+	return 0;
+}
+
+static int
+prepare_rsa_op(void)
+{
+	struct rte_crypto_asym_op *asym;
+	struct fips_val msg;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+
+	asym = env.op->asym;
+	asym->rsa.padding.type = info.interim_info.rsa_data.padding;
+	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
+
+	if (env.digest) {
+		msg.val = env.digest;
+		msg.len = env.digest_len;
+	} else {
+		msg.val = vec.pt.val;
+		msg.len = vec.pt.len;
+	}
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+
+		if (vec.rsa.signature.val)
+			rte_free(vec.rsa.signature.val);
+
+		vec.rsa.signature.val = rte_zmalloc(NULL, vec.rsa.n.len, 0);
+		vec.rsa.signature.len = vec.rsa.n.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = 0;
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = vec.rsa.signature.len;
+	} else {
+		RTE_LOG(ERR, USER1, "Invalid op %d\n", info.op);
+		return -EINVAL;
+	}
+
+	rte_crypto_op_attach_asym_session(env.op, env.asym.sess);
 
 	return 0;
 }
@@ -1145,6 +1282,87 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_rsa_xform(struct rte_crypto_asym_xform *xform)
+{
+	const struct rte_cryptodev_asymmetric_xform_capability *cap;
+	struct rte_cryptodev_asym_capability_idx cap_idx;
+	struct rte_cryptodev_info dev_info;
+
+	xform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	xform->next = NULL;
+
+	cap_idx.type = xform->xform_type;
+	cap = rte_cryptodev_asym_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;
+	}
+
+	switch (info.op) {
+	case FIPS_TEST_ASYM_SIGGEN:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_SIGN)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_SIGN);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_SIGVER:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_VERIFY)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_VERIFY);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_KEYGEN:
+		break;
+	default:
+		break;
+	}
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	xform->rsa.key_type = info.interim_info.rsa_data.privkey;
+	switch (xform->rsa.key_type) {
+	case RTE_RSA_KEY_TYPE_QT:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support QT key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.qt.p.data = vec.rsa.p.val;
+		xform->rsa.qt.p.length = vec.rsa.p.len;
+		xform->rsa.qt.q.data = vec.rsa.q.val;
+		xform->rsa.qt.q.length = vec.rsa.q.len;
+		xform->rsa.qt.dP.data = vec.rsa.dp.val;
+		xform->rsa.qt.dP.length = vec.rsa.dp.len;
+		xform->rsa.qt.dQ.data = vec.rsa.dq.val;
+		xform->rsa.qt.dQ.length = vec.rsa.dq.len;
+		xform->rsa.qt.qInv.data = vec.rsa.qinv.val;
+		xform->rsa.qt.qInv.length = vec.rsa.qinv.len;
+		break;
+	case RTE_RSA_KEY_TYPE_EXP:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support EXP key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.d.data = vec.rsa.d.val;
+		xform->rsa.d.length = vec.rsa.d.len;
+		break;
+	default:
+		break;
+	}
+
+	xform->rsa.e.data = vec.rsa.e.val;
+	xform->rsa.e.length = vec.rsa.e.len;
+	xform->rsa.n.data = vec.rsa.n.val;
+	xform->rsa.n.length = vec.rsa.n.len;
+	return 0;
+}
+
 static int
 get_writeback_data(struct fips_val *val)
 {
@@ -1191,29 +1409,29 @@ get_writeback_data(struct fips_val *val)
 }
 
 static int
-fips_run_test(void)
+fips_run_sym_test(void)
 {
 	struct rte_crypto_sym_xform xform = {0};
 	uint16_t n_deqd;
 	int ret;
 
-	ret = test_ops.prepare_xform(&xform);
+	ret = test_ops.prepare_sym_xform(&xform);
 	if (ret < 0)
 		return ret;
 
-	env.sess = rte_cryptodev_sym_session_create(env.sess_mpool);
-	if (!env.sess)
+	env.sym.sess = rte_cryptodev_sym_session_create(env.sym.sess_mpool);
+	if (!env.sym.sess)
 		return -ENOMEM;
 
 	ret = rte_cryptodev_sym_session_init(env.dev_id,
-			env.sess, &xform, env.sess_priv_mpool);
+			env.sym.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();
+	ret = test_ops.prepare_sym_op();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
 				ret);
@@ -1229,20 +1447,90 @@ fips_run_test(void)
 	do {
 		struct rte_crypto_op *deqd_op;
 
-		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
-				1);
+		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;
+	rte_cryptodev_sym_session_clear(env.dev_id, env.sym.sess);
+	rte_cryptodev_sym_session_free(env.sym.sess);
+	env.sym.sess = NULL;
 
 	return ret;
 }
 
+static int
+fips_run_asym_test(void)
+{
+	struct rte_crypto_asym_xform xform = {0};
+	struct rte_crypto_asym_op *asym;
+	struct rte_crypto_op *deqd_op;
+	int ret;
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		RTE_SET_USED(asym);
+		ret = 0;
+		goto exit;
+	}
+
+	asym = env.op->asym;
+	ret = test_ops.prepare_asym_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	ret = rte_cryptodev_asym_session_create(env.dev_id, &xform,  env.asym.sess_mpool,
+			(void *)&env.asym.sess);
+	if (ret < 0)
+		return ret;
+
+	ret = test_ops.prepare_asym_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;
+	}
+
+	while (rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1) == 0)
+		rte_pause();
+
+	vec.status = env.op->status;
+
+ exit:
+	if (env.asym.sess)
+		rte_cryptodev_asym_session_free(env.dev_id, env.asym.sess);
+
+	env.asym.sess = NULL;
+	return ret;
+}
+
+static int
+fips_run_test(void)
+{
+	int ret;
+
+	env.op = env.sym.op;
+	if (env.is_asym_test) {
+		vec.cipher_auth.digest.len = parse_test_sha_hash_size(
+						info.interim_info.rsa_data.auth);
+		test_ops.prepare_sym_xform = prepare_sha_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		ret = fips_run_sym_test();
+		if (ret < 0)
+			return ret;
+	} else {
+		return fips_run_sym_test();
+	}
+
+	env.op = env.asym.op;
+	return fips_run_asym_test();
+}
+
 static int
 fips_generic_test(void)
 {
@@ -1265,9 +1553,11 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	ret = get_writeback_data(&val);
-	if (ret < 0)
-		return ret;
+	if (!env.is_asym_test) {
+		ret = get_writeback_data(&val);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1814,60 +2104,65 @@ init_test_ops(void)
 	switch (info.algo) {
 	case FIPS_TEST_ALGO_AES_CBC:
 	case FIPS_TEST_ALGO_AES:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform  = prepare_aes_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
 	case FIPS_TEST_ALGO_AES_XTS:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform = prepare_xts_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_xform = prepare_xts_xform;
+		test_ops.test = fips_generic_test;
+		break;
+	case FIPS_TEST_ALGO_RSA:
+		test_ops.prepare_asym_op = prepare_rsa_op;
+		test_ops.prepare_asym_xform = prepare_rsa_xform;
 		test_ops.test = fips_generic_test;
 		break;
 	default:
 		if (strstr(info.file_name, "TECB") ||
 				strstr(info.file_name, "TCBC")) {
 			info.algo = FIPS_TEST_ALGO_TDES;
-			test_ops.prepare_op = prepare_cipher_op;
-			test_ops.prepare_xform	= prepare_tdes_xform;
+			test_ops.prepare_sym_op = prepare_cipher_op;
+			test_ops.prepare_sym_xform = prepare_tdes_xform;
 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
 				test_ops.test = fips_mct_tdes_test;
 			else
@@ -2033,6 +2328,9 @@ fips_test_one_test_group(void)
 	case FIPS_TEST_ALGO_TDES:
 		ret = parse_test_tdes_json_init();
 		break;
+	case FIPS_TEST_ALGO_RSA:
+		ret = parse_test_rsa_json_init();
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 8bca26a095..d310093189 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -18,6 +18,7 @@ sources = files(
         'fips_validation_ccm.c',
         'fips_validation_sha.c',
         'fips_validation_xts.c',
+        'fips_validation_rsa.c',
         'fips_dev_self_test.c',
         'main.c',
 )
@@ -26,3 +27,8 @@ if dpdk_conf.has('RTE_HAS_JANSSON')
     ext_deps += jansson_dep
     cflags += '-DUSE_JANSSON'
 endif
+
+if dpdk_conf.has('RTE_HAS_OPENSSL')
+    ext_deps += openssl_dep
+    cflags += '-DUSE_OPENSSL'
+endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v2 6/7] examples/fips_validation: encode digest with hash OID
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
                     ` (4 preceding siblings ...)
  2022-09-27  7:26   ` [v2 5/7] examples/fips_validation: add asymmetric validation Gowrishankar Muthukrishnan
@ 2022-09-27  7:26   ` Gowrishankar Muthukrishnan
  2022-09-27  7:26   ` [v2 7/7] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
                     ` (2 subsequent siblings)
  8 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-09-27  7:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS RSA validation requires hash ddigest be encoded with ASN.1
value for digest info.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/main.c | 78 +++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index ed86c10350..cfa01eae20 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -851,6 +851,63 @@ prepare_aead_op(void)
 	return 0;
 }
 
+static int
+get_hash_oid(enum rte_crypto_auth_algorithm hash, uint8_t *buf)
+{
+	uint8_t id_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x03, 0x05, 0x00, 0x04,
+				  0x40};
+	uint8_t id_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x02, 0x05, 0x00, 0x04,
+				  0x30};
+	uint8_t id_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
+				  0x20};
+	uint8_t id_sha224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+				  0x1c};
+	uint8_t id_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+				0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+				0x00, 0x04, 0x14};
+	uint8_t *id = NULL;
+	int id_len = 0;
+
+	switch (hash) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		id = id_sha1;
+		id_len = sizeof(id_sha1);
+		break;
+	case RTE_CRYPTO_AUTH_SHA224:
+		id = id_sha224;
+		id_len = sizeof(id_sha224);
+		break;
+	case RTE_CRYPTO_AUTH_SHA256:
+		id = id_sha256;
+		id_len = sizeof(id_sha256);
+		break;
+	case RTE_CRYPTO_AUTH_SHA384:
+		id = id_sha384;
+		id_len = sizeof(id_sha384);
+		break;
+	case RTE_CRYPTO_AUTH_SHA512:
+		id = id_sha512;
+		id_len = sizeof(id_sha512);
+		break;
+	default:
+		id_len = -1;
+		break;
+	}
+
+	if (id != NULL)
+		rte_memcpy(buf, id, id_len);
+
+	return id_len;
+}
+
 static int
 prepare_rsa_op(void)
 {
@@ -864,6 +921,27 @@ prepare_rsa_op(void)
 	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
 
 	if (env.digest) {
+		if (asym->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_PKCS1_5) {
+			int b_len = 0;
+			uint8_t b[32];
+
+			b_len = get_hash_oid(asym->rsa.padding.hash, b);
+			if (b_len < 0) {
+				RTE_LOG(ERR, USER1, "Failed to get digest info for hash %d\n",
+					asym->rsa.padding.hash);
+				return -EINVAL;
+			}
+
+			if (b_len) {
+				msg.len = env.digest_len + b_len;
+				msg.val = rte_zmalloc(NULL, msg.len, 0);
+				rte_memcpy(msg.val, b, b_len);
+				rte_memcpy(msg.val + b_len, env.digest, env.digest_len);
+				rte_free(env.digest);
+				env.digest = msg.val;
+				env.digest_len = msg.len;
+			}
+		}
 		msg.val = env.digest;
 		msg.len = env.digest_len;
 	} else {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v2 7/7] examples/fips_validation: randomize message for conformance test
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
                     ` (5 preceding siblings ...)
  2022-09-27  7:26   ` [v2 6/7] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
@ 2022-09-27  7:26   ` Gowrishankar Muthukrishnan
  2022-10-07  9:52   ` [v2 0/7] FIPS asymmetric validation Akhil Goyal
  2022-10-11  9:26   ` [v3 0/3] " Gowrishankar Muthukrishnan
  8 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-09-27  7:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS conformance tests require randomizing message based on SP 800-106.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.h    |   4 +
 .../fips_validation/fips_validation_rsa.c     | 112 +++++++++++++++++-
 2 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index ed59322635..7cbbc1f084 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -210,6 +210,7 @@ struct rsa_interim_data {
 	uint16_t saltlen;
 	enum rte_crypto_rsa_padding_type padding;
 	enum rte_crypto_rsa_priv_key_type privkey;
+	uint8_t random_msg;
 };
 
 #ifdef USE_JANSSON
@@ -336,6 +337,9 @@ parse_test_tdes_json_init(void);
 
 int
 parse_test_rsa_json_init(void);
+
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand);
 #endif /* USE_JANSSON */
 
 int
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
index d3699f54d0..22c0faf3cb 100644
--- a/examples/fips_validation/fips_validation_rsa.c
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -19,11 +19,13 @@
 
 #include "fips_validation.h"
 
+#define CONFORMANCE_JSON_STR	"conformance"
 #define TESTTYPE_JSON_STR	"testType"
 #define SIGTYPE_JSON_STR "sigType"
 #define MOD_JSON_STR	"modulo"
 #define HASH_JSON_STR	"hashAlg"
 #define SALT_JSON_STR	"saltLen"
+#define RV_JSON_STR	"randomValue"
 #define E_JSON_STR	"e"
 #define N_JSON_STR	"n"
 
@@ -31,6 +33,10 @@
 #define MSG_JSON_STR	"message"
 #define SIG_JSON_STR	"signature"
 
+
+#define RV_BUF_LEN (1024/8)
+#define RV_BIT_LEN (256)
+
 #ifdef USE_JANSSON
 struct {
 	uint8_t type;
@@ -259,6 +265,13 @@ prepare_vec_rsa(void)
 	if (!BN_mod_inverse(qinv, q, p, ctx))
 		goto err;
 
+	if (info.interim_info.rsa_data.random_msg) {
+		if (!BN_generate_prime_ex(r, RV_BIT_LEN, 0, NULL, NULL, NULL))
+			goto err;
+
+		parse_uint8_hex_str("", BN_bn2hex(r), &vec.rsa.seed);
+	}
+
 	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
 	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
 	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
@@ -297,6 +310,11 @@ parse_test_rsa_json_interim_writeback(struct fips_val *val)
 {
 	RTE_SET_USED(val);
 
+	if (info.interim_info.rsa_data.random_msg) {
+		json_object_set_new(json_info.json_write_group, "conformance",
+							json_string("SP800-106"));
+	}
+
 	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
 		json_t *obj;
 
@@ -367,6 +385,14 @@ parse_test_rsa_json_writeback(struct fips_val *val)
 		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
 		obj = json_string(info.one_line_text);
 		json_object_set_new(json_info.json_write_case, "signature", obj);
+
+		if (info.interim_info.rsa_data.random_msg) {
+			writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+			obj = json_string(info.one_line_text);
+			json_object_set_new(json_info.json_write_case, "randomValue", obj);
+			json_object_set_new(json_info.json_write_case, "randomValueLen",
+				json_integer(vec.rsa.seed.len * 8));
+		}
 	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
 			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
@@ -406,6 +432,8 @@ parse_interim_str(const char *key, char *src, struct fips_val *val)
 		if (i >= RTE_DIM(rsa_auth_algs))
 			return -EINVAL;
 
+	}  else if (strcmp(key, CONFORMANCE_JSON_STR) == 0) {
+		info.interim_info.rsa_data.random_msg = 1;
 	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
 		info.interim_info.rsa_data.saltlen = atoi(src);
 	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
@@ -436,6 +464,83 @@ parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
 	return prepare_vec_rsa();
 }
 
+/*
+ * Message randomization function as per NIST SP 800-106.
+ */
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand)
+{
+	uint8_t m[FIPS_TEST_JSON_BUF_LEN], rv[RV_BUF_LEN];
+	uint32_t m_bitlen, rv_bitlen, count, remain, i, j;
+	uint16_t rv_len;
+
+	if (!msg->val || !rand->val || rand->len > RV_BUF_LEN
+		|| msg->len > FIPS_TEST_JSON_BUF_LEN)
+		return -EINVAL;
+
+	memset(rv, 0, sizeof(rv));
+	memcpy(rv, rand->val, rand->len);
+	rv_bitlen = rand->len * 8;
+	rv_len = rand->len;
+
+	memset(m, 0, sizeof(m));
+	memcpy(m, msg->val, msg->len);
+	m_bitlen = msg->len * 8;
+
+	if (m_bitlen >= (rv_bitlen - 1)) {
+		m[msg->len] = 0x80;
+		m_bitlen += 8;
+	} else {
+		m[msg->len] = 0x80;
+		m_bitlen += (rv_bitlen - m_bitlen - 8);
+	}
+
+	count = m_bitlen / rv_bitlen;
+	remain = m_bitlen % rv_bitlen;
+	for (i = 0; i < count * rv_len; i++)
+		m[i] ^= rv[i % rv_len];
+
+	for (j = 0; j < remain / 8; j++)
+		m[i + j] ^= rv[j];
+
+	m[i + j] = ((uint8_t *)&rv_bitlen)[0];
+	m[i + j + 1] = (((uint8_t *)&rv_bitlen)[1] >> 8) & 0xFF;
+
+	rte_free(msg->val);
+	msg->len = (rv_bitlen + m_bitlen + 16) / 8;
+	msg->val = rte_zmalloc(NULL, msg->len, 0);
+	if (!msg->val)
+		return -EPERM;
+
+	memcpy(msg->val, rv, rv_len);
+	memcpy(&msg->val[rv_len], m, (m_bitlen + 16) / 8);
+	return 0;
+}
+
+static int
+parse_siggen_message_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(val, &vec.rsa.seed);
+
+	return ret;
+}
+
+static int
+parse_sigver_randomvalue_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(&vec.pt, val);
+
+	return ret;
+}
+
 struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
@@ -447,6 +552,7 @@ struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
 		{NULL, NULL, NULL} /**< end pointer */
@@ -456,6 +562,7 @@ struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
 		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
@@ -470,13 +577,14 @@ struct fips_test_callback rsa_keygen_json_vectors[] = {
 };
 
 struct fips_test_callback rsa_siggen_json_vectors[] = {
-		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{MSG_JSON_STR, parse_siggen_message_str, &vec.pt},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
 struct fips_test_callback rsa_sigver_json_vectors[] = {
 		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
 		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{RV_JSON_STR, parse_sigver_randomvalue_str, &vec.rsa.seed},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -492,6 +600,7 @@ parse_test_rsa_json_init(void)
 	info.parse_writeback = NULL;
 	info.interim_callbacks = NULL;
 	info.parse_interim_writeback = NULL;
+	info.interim_info.rsa_data.random_msg = 0;
 
 	if (strcmp(mode_str, "keyGen") == 0) {
 		info.op = FIPS_TEST_ASYM_KEYGEN;
@@ -506,6 +615,7 @@ parse_test_rsa_json_init(void)
 		info.op = FIPS_TEST_ASYM_SIGVER;
 		info.callbacks = rsa_sigver_json_vectors;
 		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
 	} else {
 		return -EINVAL;
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [v2 0/7] FIPS asymmetric validation
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
                     ` (6 preceding siblings ...)
  2022-09-27  7:26   ` [v2 7/7] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
@ 2022-10-07  9:52   ` Akhil Goyal
  2022-10-11  9:26   ` [v3 0/3] " Gowrishankar Muthukrishnan
  8 siblings, 0 replies; 39+ messages in thread
From: Akhil Goyal @ 2022-10-07  9:52 UTC (permalink / raw)
  To: Gowrishankar Muthukrishnan, dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Jerin Jacob Kollanukkaran,
	Gowrishankar Muthukrishnan

> Subject: [v2 0/7] FIPS asymmetric validation
> 
> This patch series adds support in fips_validation app to perform
> asymmetric validation. To start with, RSA algorithm is used in
> the evaluation. For the key value pairs which is multiprecision
> in arithmetic, openssl library is used.
> 
> Changes:
>  v2:
>   - minor fixes in v1
>   - addition of digest encoding for fips validation
>   - addition of message randomization for fips conformance tests.
> 
> Gowrishankar Muthukrishnan (7):
>   examples/fips_validation: fix parsing test group info
>   examples/fips_validation: add interim parse writeback
>   examples/fips_validation: add function to calculate SHA hash size
>   examples/fips_validation: fix buffer size to parse JSON string

First 4 patches are applied to dpdk-next-crypto
Rest of the patches need a rebase due to the recent changes in session create APIs.
Please send the rest of the patches.

>   examples/fips_validation: add asymmetric validation
>   examples/fips_validation: encode digest with hash OID
>   examples/fips_validation: randomize message for conformance test
> 
>  config/meson.build                            |   6 +
>  doc/guides/sample_app_ug/fips_validation.rst  |   1 +
>  examples/fips_validation/fips_validation.c    |  18 +-
>  examples/fips_validation/fips_validation.h    |  60 +-
>  .../fips_validation/fips_validation_gcm.c     |   8 +-
>  .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
>  .../fips_validation/fips_validation_sha.c     |  39 +-
>  examples/fips_validation/main.c               | 542 ++++++++++++---
>  examples/fips_validation/meson.build          |   6 +
>  9 files changed, 1200 insertions(+), 110 deletions(-)
>  create mode 100644 examples/fips_validation/fips_validation_rsa.c
> 
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [v2 3/7] examples/fips_validation: add function to calculate SHA hash size
  2022-09-27  7:26   ` [v2 3/7] examples/fips_validation: add function to calculate SHA hash size Gowrishankar Muthukrishnan
@ 2022-10-07 17:52     ` Akhil Goyal
  0 siblings, 0 replies; 39+ messages in thread
From: Akhil Goyal @ 2022-10-07 17:52 UTC (permalink / raw)
  To: Gowrishankar Muthukrishnan, dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Jerin Jacob Kollanukkaran,
	Gowrishankar Muthukrishnan


> Subject: [v2 3/7] examples/fips_validation: add function to calculate SHA hash
> size
> 
> Add function to calculate hash size for a given SHA hash algorithm.
> 
> Fixes: d5c247145c2 ("examples/fips_validation: add parsing for SHA")
> 
> Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
> Acked-by: Brian Dooley <brian.dooley@intel.com>
> 
> ---
This patch caused a build failure for cross compile.

[713/820] Compiling C object 'examples/c590b3c@@dpdk-fips_validation@exe/fips_validation_fips_validation_sha.c.o'.
../examples/fips_validation/fips_validation_sha.c: In function 'parse_test_sha_hash_size':
../examples/fips_validation/fips_validation_sha.c:44:10: error: implicit declaration of function 'atoi' [-Wimplicit-function-declaration]
   44 |    ret = atoi(phsc[i].str);
      |          ^~~~
../examples/fips_validation/fips_validation_sha.c:44:10: error: nested extern declaration of 'atoi' [-Wnested-externs]


Added include file in fips_validation_sha.c
#include <stdlib.h>


> v2:
>  - fixed include file
> ---
>  examples/fips_validation/fips_validation.h    |  1 +
>  .../fips_validation/fips_validation_sha.c     | 39 ++++++++++++-------
>  2 files changed, 25 insertions(+), 15 deletions(-)
> 
> diff --git a/examples/fips_validation/fips_validation.h
> b/examples/fips_validation/fips_validation.h
> index a6288e17e5..6e5f2fce75 100644
> --- a/examples/fips_validation/fips_validation.h
> +++ b/examples/fips_validation/fips_validation.h
> @@ -374,4 +374,5 @@ int prepare_gcm_xform(struct rte_crypto_sym_xform
> *xform);
> 
>  int prepare_gmac_xform(struct rte_crypto_sym_xform *xform);
> 
> +int parse_test_sha_hash_size(enum rte_crypto_auth_algorithm algo);
>  #endif
> diff --git a/examples/fips_validation/fips_validation_sha.c
> b/examples/fips_validation/fips_validation_sha.c
> index 75b073c15d..cac2a25e6c 100644
> --- a/examples/fips_validation/fips_validation_sha.c
> +++ b/examples/fips_validation/fips_validation_sha.c
> @@ -33,6 +33,22 @@ struct plain_hash_size_conversion {
>  		{"64", RTE_CRYPTO_AUTH_SHA512},
>  };
> 
> +int
> +parse_test_sha_hash_size(enum rte_crypto_auth_algorithm algo)
> +{
> +	int ret = -EINVAL;
> +	uint8_t i;
> +
> +	for (i = 0; i < RTE_DIM(phsc); i++) {
> +		if (phsc[i].algo == algo) {
> +			ret = atoi(phsc[i].str);
> +			break;
> +		}
> +	}
> +
> +	return ret;
> +}
> +
>  static int
>  parse_interim_algo(__rte_unused const char *key,
>  		char *text,
> @@ -212,6 +228,7 @@ parse_test_sha_json_algorithm(void)
>  	json_t *algorithm_object;
>  	const char *algorithm_str;
>  	uint32_t i;
> +	int sz;
> 
>  	algorithm_object = json_object_get(json_info.json_vector_set,
> "algorithm");
>  	algorithm_str = json_string_value(algorithm_object);
> @@ -226,23 +243,15 @@ parse_test_sha_json_algorithm(void)
>  	if (i == RTE_DIM(json_algorithms))
>  		return -1;
> 
> -	for (i = 0; i < RTE_DIM(phsc); i++) {
> -		if (info.interim_info.sha_data.algo == phsc[i].algo) {
> -			vec.cipher_auth.digest.len = atoi(phsc[i].str);
> -			free(vec.cipher_auth.digest.val);
> -			vec.cipher_auth.digest.val = calloc(1,
> vec.cipher_auth.digest.len);
> -			if (vec.cipher_auth.digest.val == NULL)
> -				return -1;
> -
> -			break;
> -		}
> -	}
> +	sz = parse_test_sha_hash_size(info.interim_info.sha_data.algo);
> +	if (sz < 0)
> +		return -1;
> 
> -	if (i == RTE_DIM(phsc)) {
> -		free(vec.cipher_auth.digest.val);
> -		vec.cipher_auth.digest.val = NULL;
> +	free(vec.cipher_auth.digest.val);
> +	vec.cipher_auth.digest.len = sz;
> +	vec.cipher_auth.digest.val = calloc(1, sz);
> +	if (vec.cipher_auth.digest.val == NULL)
>  		return -1;
> -	}
> 
>  	return 0;
>  }
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v3 0/3] FIPS asymmetric validation
  2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
                     ` (7 preceding siblings ...)
  2022-10-07  9:52   ` [v2 0/7] FIPS asymmetric validation Akhil Goyal
@ 2022-10-11  9:26   ` Gowrishankar Muthukrishnan
  2022-10-11  9:26     ` [v3 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
                       ` (4 more replies)
  8 siblings, 5 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-11  9:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

This patch series adds support in fips_validation app to perform
asymmetric validation. To start with, RSA algorithm is used in
the evaluation. For the key value pairs which is multiprecision
in arithmetic, openssl library is used.

Changes:
 v3:
  - patches 5,6 and 7 in v2 are rebased and submitted here.
 v2:
  - minor fixes in v1
  - addition of digest encoding for fips validation
  - addition of message randomization for fips conformance tests.

Gowrishankar Muthukrishnan (3):
  examples/fips_validation: add asymmetric validation
  examples/fips_validation: encode digest with hash OID
  examples/fips_validation: randomize message for conformance test

 config/meson.build                            |   6 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  51 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
 examples/fips_validation/main.c               | 546 ++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 8 files changed, 1154 insertions(+), 96 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v3 1/3] examples/fips_validation: add asymmetric validation
  2022-10-11  9:26   ` [v3 0/3] " Gowrishankar Muthukrishnan
@ 2022-10-11  9:26     ` Gowrishankar Muthukrishnan
  2022-10-11  9:26     ` [v3 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
                       ` (3 subsequent siblings)
  4 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-11  9:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add support for asymmetric crypto validation starting with RSA.
For the generation of crypto values which is multiprecision in
math, openssl library is used only for this purpose.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>

--
v3:
 - rebased according to cryptodev session rework changes.
v2:
 - improved handling priv key type.
---
 config/meson.build                            |   6 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  47 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 520 ++++++++++++++++++
 examples/fips_validation/main.c               | 468 +++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 8 files changed, 962 insertions(+), 96 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

diff --git a/config/meson.build b/config/meson.build
index 0fc209db01..e82797d206 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -226,6 +226,12 @@ if jansson_dep.found()
     dpdk_conf.set('RTE_HAS_JANSSON', 1)
 endif
 
+# check for openssl
+openssl_dep = dependency('openssl', required: false, method: 'pkg-config')
+if openssl_dep.found()
+    dpdk_conf.set('RTE_HAS_OPENSSL', 1)
+endif
+
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
 pcap_lib = is_windows ? 'wpcap' : 'pcap'
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index 33a8c97575..5e9ad2d006 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -66,6 +66,7 @@ ACVP
     * SHA (1, 256, 384, 512) - AFT, MCT
     * TDES-CBC - AFT, MCT
     * TDES-ECB - AFT, MCT
+    * RSA
 
 
 Application Information
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index 363e17a6f3..2c47f9480b 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -473,6 +473,8 @@ fips_test_parse_one_json_vector_set(void)
 	else if (strstr(algo_str, "TDES-CBC") ||
 		strstr(algo_str, "TDES-ECB"))
 		info.algo = FIPS_TEST_ALGO_TDES;
+	else if (strstr(algo_str, "RSA"))
+		info.algo = FIPS_TEST_ALGO_RSA;
 	else
 		return -EINVAL;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 43e5ffe4b0..ed59322635 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -42,6 +42,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_SHA,
+		FIPS_TEST_ALGO_RSA,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -55,6 +56,9 @@ enum file_types {
 enum fips_test_op {
 	FIPS_TEST_ENC_AUTH_GEN = 1,
 	FIPS_TEST_DEC_AUTH_VERIF,
+	FIPS_TEST_ASYM_KEYGEN,
+	FIPS_TEST_ASYM_SIGGEN,
+	FIPS_TEST_ASYM_SIGVER
 };
 
 #define MAX_LINE_PER_VECTOR            16
@@ -78,11 +82,22 @@ struct fips_test_vector {
 			struct fips_val aad;
 		} aead;
 	};
+	struct {
+		struct fips_val seed;
+		struct fips_val signature;
+		struct fips_val e;
+		struct fips_val n;
+		struct fips_val d;
+		struct fips_val p;
+		struct fips_val q;
+		struct fips_val dp;
+		struct fips_val dq;
+		struct fips_val qinv;
+	} rsa;
 
 	struct fips_val pt;
 	struct fips_val ct;
 	struct fips_val iv;
-
 	enum rte_crypto_op_status status;
 };
 
@@ -138,6 +153,12 @@ enum fips_sha_test_types {
 	SHA_MCT
 };
 
+enum fips_rsa_test_types {
+	RSA_AFT = 0,
+	RSA_GDT,
+	RSA_KAT
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -164,8 +185,9 @@ struct ccm_interim_data {
 };
 
 struct sha_interim_data {
-	enum fips_sha_test_types test_type;
+	/* keep algo always on top as it is also used in asym digest */
 	enum rte_crypto_auth_algorithm algo;
+	enum fips_sha_test_types test_type;
 };
 
 struct gcm_interim_data {
@@ -182,6 +204,14 @@ struct xts_interim_data {
 	enum xts_tweak_modes tweak_mode;
 };
 
+struct rsa_interim_data {
+	enum rte_crypto_auth_algorithm auth;
+	uint16_t modulo;
+	uint16_t saltlen;
+	enum rte_crypto_rsa_padding_type padding;
+	enum rte_crypto_rsa_priv_key_type privkey;
+};
+
 #ifdef USE_JANSSON
 /*
  * Maximum length of buffer to hold any json string.
@@ -227,6 +257,7 @@ struct fips_test_interim_info {
 		struct sha_interim_data sha_data;
 		struct gcm_interim_data gcm_data;
 		struct xts_interim_data xts_data;
+		struct rsa_interim_data rsa_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -302,6 +333,9 @@ parse_test_sha_json_test_type(void);
 
 int
 parse_test_tdes_json_init(void);
+
+int
+parse_test_rsa_json_init(void);
 #endif /* USE_JANSSON */
 
 int
@@ -363,11 +397,14 @@ update_info_vec(uint32_t count);
 
 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 *);
+typedef int (*fips_prepare_sym_xform_t)(struct rte_crypto_sym_xform *);
+typedef int (*fips_prepare_asym_xform_t)(struct rte_crypto_asym_xform *);
 
 struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
+	fips_prepare_sym_xform_t prepare_sym_xform;
+	fips_prepare_asym_xform_t prepare_asym_xform;
+	fips_prepare_op_t prepare_sym_op;
+	fips_prepare_op_t prepare_asym_op;
 	fips_test_one_case_t test;
 };
 
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index db8208a5b6..1a2a71ae9f 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -81,12 +81,12 @@ parser_read_gcm_pt_len(const char *key, char *src,
 
 	if (vec.pt.len == 0) {
 		info.interim_info.gcm_data.is_gmac = 1;
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 	} else {
 		info.interim_info.gcm_data.is_gmac = 0;
-		test_ops.prepare_op = prepare_aead_op;
-		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_xform = prepare_gcm_xform;
 	}
 
 	return ret;
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
new file mode 100644
index 0000000000..d3699f54d0
--- /dev/null
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -0,0 +1,520 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell.
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/random.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef USE_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#endif /* USE_OPENSSL */
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define TESTTYPE_JSON_STR	"testType"
+#define SIGTYPE_JSON_STR "sigType"
+#define MOD_JSON_STR	"modulo"
+#define HASH_JSON_STR	"hashAlg"
+#define SALT_JSON_STR	"saltLen"
+#define E_JSON_STR	"e"
+#define N_JSON_STR	"n"
+
+#define SEED_JSON_STR	"seed"
+#define MSG_JSON_STR	"message"
+#define SIG_JSON_STR	"signature"
+
+#ifdef USE_JANSSON
+struct {
+	uint8_t type;
+	const char *desc;
+} rsa_test_types[] = {
+		{RSA_AFT, "AFT"},
+		{RSA_GDT, "GDT"},
+		{RSA_KAT, "KAT"},
+};
+
+struct {
+	enum rte_crypto_auth_algorithm auth;
+	const char *desc;
+} rsa_auth_algs[] = {
+		{RTE_CRYPTO_AUTH_SHA1, "SHA-1"},
+		{RTE_CRYPTO_AUTH_SHA224, "SHA2-224"},
+		{RTE_CRYPTO_AUTH_SHA256, "SHA2-256"},
+		{RTE_CRYPTO_AUTH_SHA384, "SHA2-384"},
+		{RTE_CRYPTO_AUTH_SHA512, "SHA2-512"},
+};
+
+struct {
+	enum rte_crypto_rsa_padding_type padding;
+	const char *desc;
+} rsa_padding_types[] = {
+		{RTE_CRYPTO_RSA_PADDING_NONE, "none"},
+		{RTE_CRYPTO_RSA_PADDING_PKCS1_5, "pkcs1v1.5"},
+		{RTE_CRYPTO_RSA_PADDING_OAEP, "oaep"},
+		{RTE_CRYPTO_RSA_PADDING_PSS, "pss"},
+};
+
+#ifdef USE_OPENSSL
+static int
+prepare_vec_rsa(void)
+{
+	BIGNUM *p = NULL, *q = NULL, *n = NULL, *d = NULL, *e = NULL;
+	BIGNUM *dp = NULL, *dq = NULL, *qinv = NULL;
+	BIGNUM *r0, *r1, *r2, *r3, *r4;
+	BIGNUM *m = NULL, *r = NULL;
+	int bits, ret = -1, i;
+	char modbuf[8], *buf;
+	BN_CTX *ctx = NULL;
+	unsigned long pid;
+
+	/* Seed PRNG */
+	if (vec.rsa.seed.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		RAND_seed((char *)info.one_line_text, strlen(info.one_line_text));
+	} else {
+		pid = getpid();
+		RAND_seed(&pid, sizeof(pid));
+	}
+
+	if (!RAND_status())
+		return -1;
+
+	/* Check if e is known already */
+	if (vec.rsa.e.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		ret = BN_hex2bn(&e, info.one_line_text);
+		if ((uint32_t)ret != strlen(info.one_line_text))
+			goto err;
+	}
+
+	/* BN context initialization */
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto err;
+
+	BN_CTX_start(ctx);
+	r0 = BN_CTX_get(ctx);
+	r1 = BN_CTX_get(ctx);
+	r2 = BN_CTX_get(ctx);
+	r3 = BN_CTX_get(ctx);
+	r4 = BN_CTX_get(ctx);
+	if (!r4)
+		goto err;
+
+	/* Calculate bit length for prime numbers */
+	m = BN_new();
+	if (!m)
+		goto err;
+
+	snprintf(modbuf, sizeof(modbuf), "%d", info.interim_info.rsa_data.modulo);
+	if (!BN_dec2bn(&m, modbuf))
+		goto err;
+
+	r = BN_new();
+	if (!r)
+		goto err;
+
+	if (!BN_rshift1(r, m))
+		goto err;
+
+	buf = BN_bn2dec(r);
+	bits = atoi(buf);
+
+	p = BN_new();
+	if (!p)
+		goto err;
+
+	q = BN_new();
+	if (!q)
+		goto err;
+
+	n = BN_new();
+	if (!n)
+		goto err;
+
+	d = BN_new();
+	if (!d)
+		goto err;
+
+	/* Generate p and q suitably for RSA */
+	for (i = 0; i < 10; i++) {
+		uint8_t j = 0;
+
+		if (!BN_generate_prime_ex(p, bits, 0, NULL, NULL, NULL))
+			goto err;
+
+		do {
+			RAND_add(&j, sizeof(j), 1);
+			if (!BN_generate_prime_ex(q, bits, 0, NULL, NULL, NULL))
+				goto err;
+
+		} while ((BN_cmp(p, q) == 0) && (j++ < 100));
+
+		if (j >= 100) {
+			RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate q", j);
+			goto err;
+		}
+
+		/* pq */
+		if (!BN_mul(n, p, q, ctx))
+			goto err;
+
+		/* p-1 */
+		if (!BN_sub(r1, p, BN_value_one()))
+			goto err;
+
+		/* q-1 */
+		if (!BN_sub(r2, q, BN_value_one()))
+			goto err;
+
+		/* (p-1 * q-1) */
+		if (!BN_mul(r0, r1, r2, ctx))
+			goto err;
+
+		/* gcd(p-1, q-1)*/
+		if (!BN_gcd(r3, r1, r2, ctx))
+			goto err;
+
+		/* lcm(p-1, q-1) */
+		if (!BN_div(r4, r, r0, r3, ctx))
+			goto err;
+
+		/* check if div and rem are non-zero */
+		if (!r4 || !r)
+			goto err;
+
+		/* 0 < e < lcm */
+		if (!e) {
+			int k = 0;
+
+			e = BN_new();
+			do {
+				RAND_add(&k, sizeof(k), 1);
+				if (!BN_rand(e, 32, 1, 1))
+					goto err;
+
+				if (!BN_gcd(r3, e, r4, ctx))
+					goto err;
+
+				if (BN_is_one(r3))
+					break;
+			} while (k++ < 10);
+
+			if (k >= 10) {
+				RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate e",
+					k);
+				goto err;
+			}
+		}
+
+		/* (de) mod lcm == 1 */
+		if (!BN_mod_inverse(d, e, r4, ctx))
+			goto err;
+
+		if (!BN_gcd(r3, r1, e, ctx))
+			goto err;
+
+		if (!BN_gcd(r4, r2, e, ctx))
+			goto err;
+
+		/* check if gcd(p-1, e) and gcd(q-1, e) are 1 */
+		if (BN_is_one(r3) && BN_is_one(r4))
+			break;
+	}
+
+	if (i >= 10) {
+		RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate p and q", i);
+		goto err;
+	}
+
+	/* d mod (p-1) */
+	dp = BN_new();
+	if (!dp)
+		goto err;
+
+	if (!BN_mod(dp, d, r1, ctx))
+		goto err;
+
+	/* d mod (q-1) */
+	dq = BN_new();
+	if (!dq)
+		goto err;
+
+	if (!BN_mod(dq, d, r2, ctx))
+		goto err;
+
+	/* modinv of q and p */
+	qinv = BN_new();
+	if (!qinv)
+		goto err;
+
+	if (!BN_mod_inverse(qinv, q, p, ctx))
+		goto err;
+
+	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
+	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
+	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
+	parse_uint8_hex_str("", BN_bn2hex(n), &vec.rsa.n);
+	parse_uint8_hex_str("", BN_bn2hex(d), &vec.rsa.d);
+	parse_uint8_hex_str("", BN_bn2hex(dp), &vec.rsa.dp);
+	parse_uint8_hex_str("", BN_bn2hex(dq), &vec.rsa.dq);
+	parse_uint8_hex_str("", BN_bn2hex(qinv), &vec.rsa.qinv);
+
+	ret = 0;
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(m);
+	BN_free(r);
+	BN_free(p);
+	BN_free(q);
+	BN_free(n);
+	BN_free(d);
+	BN_free(e);
+	return ret;
+}
+#else
+static int
+prepare_vec_rsa(void)
+{
+	/*
+	 * Generate RSA values.
+	 */
+	return -ENOTSUP;
+}
+#endif /* USE_OPENSSL */
+
+static int
+parse_test_rsa_json_interim_writeback(struct fips_val *val)
+{
+	RTE_SET_USED(val);
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		/* For siggen tests, RSA values can be created soon after
+		 * the test group data are parsed.
+		 */
+		if (vec.rsa.e.val) {
+			rte_free(vec.rsa.e.val);
+			vec.rsa.e.val = NULL;
+		}
+
+		if (prepare_vec_rsa() < 0)
+			return -1;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "e", obj);
+	}
+
+	return 0;
+}
+
+static int
+parse_test_rsa_json_writeback(struct fips_val *val)
+{
+	json_t *tcId;
+
+	RTE_SET_USED(val);
+
+	tcId = json_object_get(json_info.json_test_case, "tcId");
+
+	json_info.json_write_case = json_object();
+	json_object_set(json_info.json_write_case, "tcId", tcId);
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "seed", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "e", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.p);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "p", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.q);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "q", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.d);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "d", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "signature", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
+		else
+			json_object_set_new(json_info.json_write_case, "testPassed", json_false());
+	}
+
+	return 0;
+}
+
+static int
+parse_interim_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t i;
+
+	RTE_SET_USED(val);
+
+	if (strcmp(key, SIGTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_padding_types); i++)
+			if (strstr(src, rsa_padding_types[i].desc)) {
+				info.interim_info.rsa_data.padding = rsa_padding_types[i].padding;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_padding_types))
+			return -EINVAL;
+
+	}  else if (strcmp(key, MOD_JSON_STR) == 0) {
+		info.interim_info.rsa_data.modulo = atoi(src);
+	} else if (strcmp(key, HASH_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_auth_algs); i++)
+			if (strstr(src, rsa_auth_algs[i].desc)) {
+				info.interim_info.rsa_data.auth = rsa_auth_algs[i].auth;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_auth_algs))
+			return -EINVAL;
+
+	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
+		info.interim_info.rsa_data.saltlen = atoi(src);
+	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_test_types); i++)
+			if (strstr(src, rsa_test_types[i].desc)) {
+				info.parse_writeback = parse_test_rsa_json_writeback;
+				break;
+			}
+
+		if (!info.parse_writeback || i >= RTE_DIM(rsa_test_types))
+			return -EINVAL;
+
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
+{
+	parse_uint8_hex_str(key, src, val);
+
+	/* For keygen tests, key "e" can be the end of input data
+	 * to generate RSA values.
+	 */
+	return prepare_vec_rsa();
+}
+
+struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
+		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_keygen_json_vectors[] = {
+		{SEED_JSON_STR, parse_uint8_hex_str, &vec.rsa.seed},
+		{E_JSON_STR, parse_keygen_e_str, &vec.rsa.e},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_rsa_json_init(void)
+{
+	json_t *keyfmt_obj = json_object_get(json_info.json_vector_set, "keyFormat");
+	json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode");
+	const char *keyfmt_str = json_string_value(keyfmt_obj);
+	const char *mode_str = json_string_value(mode_obj);
+
+	info.callbacks = NULL;
+	info.parse_writeback = NULL;
+	info.interim_callbacks = NULL;
+	info.parse_interim_writeback = NULL;
+
+	if (strcmp(mode_str, "keyGen") == 0) {
+		info.op = FIPS_TEST_ASYM_KEYGEN;
+		info.callbacks = rsa_keygen_json_vectors;
+		info.interim_callbacks = rsa_keygen_interim_json_vectors;
+	} else if (strcmp(mode_str, "sigGen") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGGEN;
+		info.callbacks = rsa_siggen_json_vectors;
+		info.interim_callbacks = rsa_siggen_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
+	} else if (strcmp(mode_str, "sigVer") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGVER;
+		info.callbacks = rsa_sigver_json_vectors;
+		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+	} else {
+		return -EINVAL;
+	}
+
+	info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_QT;
+	if (keyfmt_str != NULL && strcmp(keyfmt_str, "standard") == 0)
+		info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_EXP;
+
+	return 0;
+}
+#endif /* USE_JANSSON */
+
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 10ea70530c..dbf9c6fce2 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -37,6 +37,8 @@ enum {
 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
 #define OPT_USE_JSON                "use-json"
 	OPT_USE_JSON_NUM,
+#define OPT_CRYPTODEV_ASYM          "asymmetric"
+	OPT_CRYPTODEV_ASYM_NUM,
 };
 
 struct fips_test_vector vec;
@@ -51,34 +53,140 @@ struct cryptodev_fips_validate_env {
 	const char *rsp_path;
 	uint32_t is_path_folder;
 	uint8_t dev_id;
+	struct rte_mempool *mpool;
+	struct fips_sym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_sym_session *sess;
+		struct rte_crypto_op *op;
+	} sym;
+	struct fips_asym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_asym_session *sess;
+		struct rte_crypto_op *op;
+	} asym;
+	struct rte_crypto_op *op;
 	uint8_t dev_support_sgl;
 	uint16_t mbuf_data_room;
-	struct rte_mempool *mpool;
-	struct rte_mempool *sess_mpool;
-	struct rte_mempool *op_pool;
 	struct rte_mbuf *mbuf;
 	uint8_t *digest;
 	uint16_t digest_len;
-	struct rte_crypto_op *op;
-	void *sess;
+	bool is_asym_test;
 	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
 static int
-cryptodev_fips_validate_app_int(void)
+cryptodev_fips_validate_app_sym_init(void)
+{
+	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
+							env.dev_id);
+	struct rte_cryptodev_info dev_info;
+	struct fips_sym_env *sym = &env.sym;
+	int ret;
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	ret = -ENOMEM;
+	sym->sess_mpool = rte_cryptodev_sym_session_pool_create(
+			"FIPS_SYM_SESS_MEMPOOL", 16, sess_sz, 0, 0, rte_socket_id());
+	if (!sym->sess_mpool)
+		goto error_exit;
+
+	sym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_SYM_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!sym->op_pool)
+		goto error_exit;
+
+	sym->op = rte_crypto_op_alloc(sym->op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!sym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_sym_uninit(void)
+{
+	struct fips_sym_env *sym = &env.sym;
+
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(sym->op);
+	rte_cryptodev_sym_session_free(env.dev_id, sym->sess);
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_asym_init(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+	int ret;
+
+	ret = -ENOMEM;
+	asym->sess_mpool = rte_cryptodev_asym_session_pool_create(
+			"FIPS_ASYM_SESS_MEMPOOL", 16, 0, 0, rte_socket_id());
+	if (!asym->sess_mpool)
+		goto error_exit;
+
+	asym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_ASYM_POOL",
+			RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!asym->op_pool)
+		goto error_exit;
+
+	asym->op = rte_crypto_op_alloc(asym->op_pool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!asym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_asym_uninit(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+
+	rte_crypto_op_free(asym->op);
+	rte_cryptodev_asym_session_free(env.dev_id, asym->sess);
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_init(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL};
-	struct rte_cryptodev_info dev_info;
-	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
-			env.dev_id);
 	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
 	int ret;
 
 	if (env.self_test) {
 		ret = fips_dev_self_test(env.dev_id, env.broken_test_config);
 		if (ret < 0) {
+			rte_cryptodev_stop(env.dev_id);
 			rte_cryptodev_close(env.dev_id);
 
 			return ret;
@@ -89,45 +197,24 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	rte_cryptodev_info_get(env.dev_id, &dev_info);
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
-		env.dev_support_sgl = 1;
-	else
-		env.dev_support_sgl = 0;
-
+	ret = -ENOMEM;
 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
 			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
 			env.mbuf_data_room, rte_socket_id());
 	if (!env.mpool)
 		return ret;
 
-	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
-			rte_socket_id());
+	ret = cryptodev_fips_validate_app_sym_init();
 	if (ret < 0)
-		return ret;
-
-	ret = -ENOMEM;
-
-	env.sess_mpool = rte_cryptodev_sym_session_pool_create(
-			"FIPS_SESS_MEMPOOL", 16, sess_sz, 0, 0,
-			rte_socket_id());
-	if (!env.sess_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.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	if (!env.op)
-		goto error_exit;
+	if (env.is_asym_test) {
+		ret = cryptodev_fips_validate_app_asym_init();
+		if (ret < 0)
+			goto error_exit;
+	}
 
-	qp_conf.mp_session = env.sess_mpool;
+	qp_conf.mp_session = env.sym.sess_mpool;
 
 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
 			rte_socket_id());
@@ -141,23 +228,21 @@ cryptodev_fips_validate_app_int(void)
 	return 0;
 
 error_exit:
-
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	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_free(env.dev_id, env.sess);
+	cryptodev_fips_validate_app_sym_uninit();
+
+	if (env.is_asym_test)
+		cryptodev_fips_validate_app_asym_uninit();
+
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	rte_mempool_free(env.op_pool);
+	rte_cryptodev_stop(env.dev_id);
+	rte_cryptodev_close(env.dev_id);
 }
 
 static int
@@ -253,6 +338,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+		{OPT_CRYPTODEV_ASYM, no_argument,
+				NULL, OPT_CRYPTODEV_ASYM_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -365,6 +452,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			}
 			break;
 
+		case OPT_CRYPTODEV_ASYM_NUM:
+			env.is_asym_test = true;
+			break;
+
 		default:
 			cryptodev_fips_validate_usage(prgname);
 			return -EINVAL;
@@ -405,7 +496,7 @@ main(int argc, char *argv[])
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
 
-	ret = cryptodev_fips_validate_app_int();
+	ret = cryptodev_fips_validate_app_init();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
 		return -1;
@@ -644,7 +735,7 @@ prepare_cipher_op(void)
 		sym->cipher.data.length = vec.ct.len;
 	}
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	sym->m_src = env.mbuf;
 	sym->cipher.data.offset = 0;
@@ -692,7 +783,7 @@ prepare_auth_op(void)
 		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	return 0;
 }
@@ -748,7 +839,55 @@ prepare_aead_op(void)
 	sym->aead.aad.data = vec.aead.aad.val;
 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
+
+	return 0;
+}
+
+static int
+prepare_rsa_op(void)
+{
+	struct rte_crypto_asym_op *asym;
+	struct fips_val msg;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+
+	asym = env.op->asym;
+	asym->rsa.padding.type = info.interim_info.rsa_data.padding;
+	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
+
+	if (env.digest) {
+		msg.val = env.digest;
+		msg.len = env.digest_len;
+	} else {
+		msg.val = vec.pt.val;
+		msg.len = vec.pt.len;
+	}
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+
+		if (vec.rsa.signature.val)
+			rte_free(vec.rsa.signature.val);
+
+		vec.rsa.signature.val = rte_zmalloc(NULL, vec.rsa.n.len, 0);
+		vec.rsa.signature.len = vec.rsa.n.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = 0;
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = vec.rsa.signature.len;
+	} else {
+		RTE_LOG(ERR, USER1, "Invalid op %d\n", info.op);
+		return -EINVAL;
+	}
+
+	rte_crypto_op_attach_asym_session(env.op, env.asym.sess);
 
 	return 0;
 }
@@ -1136,6 +1275,87 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_rsa_xform(struct rte_crypto_asym_xform *xform)
+{
+	const struct rte_cryptodev_asymmetric_xform_capability *cap;
+	struct rte_cryptodev_asym_capability_idx cap_idx;
+	struct rte_cryptodev_info dev_info;
+
+	xform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	xform->next = NULL;
+
+	cap_idx.type = xform->xform_type;
+	cap = rte_cryptodev_asym_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;
+	}
+
+	switch (info.op) {
+	case FIPS_TEST_ASYM_SIGGEN:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_SIGN)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_SIGN);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_SIGVER:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_VERIFY)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_VERIFY);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_KEYGEN:
+		break;
+	default:
+		break;
+	}
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	xform->rsa.key_type = info.interim_info.rsa_data.privkey;
+	switch (xform->rsa.key_type) {
+	case RTE_RSA_KEY_TYPE_QT:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support QT key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.qt.p.data = vec.rsa.p.val;
+		xform->rsa.qt.p.length = vec.rsa.p.len;
+		xform->rsa.qt.q.data = vec.rsa.q.val;
+		xform->rsa.qt.q.length = vec.rsa.q.len;
+		xform->rsa.qt.dP.data = vec.rsa.dp.val;
+		xform->rsa.qt.dP.length = vec.rsa.dp.len;
+		xform->rsa.qt.dQ.data = vec.rsa.dq.val;
+		xform->rsa.qt.dQ.length = vec.rsa.dq.len;
+		xform->rsa.qt.qInv.data = vec.rsa.qinv.val;
+		xform->rsa.qt.qInv.length = vec.rsa.qinv.len;
+		break;
+	case RTE_RSA_KEY_TYPE_EXP:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support EXP key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.d.data = vec.rsa.d.val;
+		xform->rsa.d.length = vec.rsa.d.len;
+		break;
+	default:
+		break;
+	}
+
+	xform->rsa.e.data = vec.rsa.e.val;
+	xform->rsa.e.length = vec.rsa.e.len;
+	xform->rsa.n.data = vec.rsa.n.val;
+	xform->rsa.n.length = vec.rsa.n.len;
+	return 0;
+}
+
 static int
 get_writeback_data(struct fips_val *val)
 {
@@ -1182,25 +1402,22 @@ get_writeback_data(struct fips_val *val)
 }
 
 static int
-fips_run_test(void)
+fips_run_sym_test(void)
 {
 	struct rte_crypto_sym_xform xform = {0};
 	uint16_t n_deqd;
 	int ret;
 
-	ret = test_ops.prepare_xform(&xform);
+	ret = test_ops.prepare_sym_xform(&xform);
 	if (ret < 0)
 		return ret;
 
-	env.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
-			env.sess_mpool);
-	if (!env.sess) {
-		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
-				ret);
-		goto exit;
-	}
+	env.sym.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
+						env.sym.sess_mpool);
+	if (!env.sym.sess)
+		return -ENOMEM;
 
-	ret = test_ops.prepare_op();
+	ret = test_ops.prepare_sym_op();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
 				ret);
@@ -1216,21 +1433,88 @@ fips_run_test(void)
 	do {
 		struct rte_crypto_op *deqd_op;
 
-		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
-				1);
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1);
 	} while (n_deqd == 0);
 
 	vec.status = env.op->status;
 
 exit:
-	if (env.sess) {
-		rte_cryptodev_sym_session_free(env.dev_id, env.sess);
-		env.sess = NULL;
+	rte_cryptodev_sym_session_free(env.dev_id, env.sym.sess);
+	env.sym.sess = NULL;
+	return ret;
+}
+
+static int
+fips_run_asym_test(void)
+{
+	struct rte_crypto_asym_xform xform = {0};
+	struct rte_crypto_asym_op *asym;
+	struct rte_crypto_op *deqd_op;
+	int ret;
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		RTE_SET_USED(asym);
+		ret = 0;
+		goto exit;
+	}
+
+	asym = env.op->asym;
+	ret = test_ops.prepare_asym_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	ret = rte_cryptodev_asym_session_create(env.dev_id, &xform, env.asym.sess_mpool,
+			(void *)&env.asym.sess);
+	if (ret < 0)
+		return ret;
+
+	ret = test_ops.prepare_asym_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;
 	}
 
+	while (rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1) == 0)
+		rte_pause();
+
+	vec.status = env.op->status;
+
+ exit:
+	if (env.asym.sess)
+		rte_cryptodev_asym_session_free(env.dev_id, env.asym.sess);
+
+	env.asym.sess = NULL;
 	return ret;
 }
 
+static int
+fips_run_test(void)
+{
+	int ret;
+
+	env.op = env.sym.op;
+	if (env.is_asym_test) {
+		vec.cipher_auth.digest.len = parse_test_sha_hash_size(
+						info.interim_info.rsa_data.auth);
+		test_ops.prepare_sym_xform = prepare_sha_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		ret = fips_run_sym_test();
+		if (ret < 0)
+			return ret;
+	} else {
+		return fips_run_sym_test();
+	}
+
+	env.op = env.asym.op;
+	return fips_run_asym_test();
+}
+
 static int
 fips_generic_test(void)
 {
@@ -1253,9 +1537,11 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	ret = get_writeback_data(&val);
-	if (ret < 0)
-		return ret;
+	if (!env.is_asym_test) {
+		ret = get_writeback_data(&val);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1804,60 +2090,65 @@ init_test_ops(void)
 	switch (info.algo) {
 	case FIPS_TEST_ALGO_AES_CBC:
 	case FIPS_TEST_ALGO_AES:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform  = prepare_aes_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
 	case FIPS_TEST_ALGO_AES_XTS:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform = prepare_xts_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_xform = prepare_xts_xform;
+		test_ops.test = fips_generic_test;
+		break;
+	case FIPS_TEST_ALGO_RSA:
+		test_ops.prepare_asym_op = prepare_rsa_op;
+		test_ops.prepare_asym_xform = prepare_rsa_xform;
 		test_ops.test = fips_generic_test;
 		break;
 	default:
 		if (strstr(info.file_name, "TECB") ||
 				strstr(info.file_name, "TCBC")) {
 			info.algo = FIPS_TEST_ALGO_TDES;
-			test_ops.prepare_op = prepare_cipher_op;
-			test_ops.prepare_xform	= prepare_tdes_xform;
+			test_ops.prepare_sym_op = prepare_cipher_op;
+			test_ops.prepare_sym_xform = prepare_tdes_xform;
 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
 				test_ops.test = fips_mct_tdes_test;
 			else
@@ -2023,6 +2314,9 @@ fips_test_one_test_group(void)
 	case FIPS_TEST_ALGO_TDES:
 		ret = parse_test_tdes_json_init();
 		break;
+	case FIPS_TEST_ALGO_RSA:
+		ret = parse_test_rsa_json_init();
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 8bca26a095..d310093189 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -18,6 +18,7 @@ sources = files(
         'fips_validation_ccm.c',
         'fips_validation_sha.c',
         'fips_validation_xts.c',
+        'fips_validation_rsa.c',
         'fips_dev_self_test.c',
         'main.c',
 )
@@ -26,3 +27,8 @@ if dpdk_conf.has('RTE_HAS_JANSSON')
     ext_deps += jansson_dep
     cflags += '-DUSE_JANSSON'
 endif
+
+if dpdk_conf.has('RTE_HAS_OPENSSL')
+    ext_deps += openssl_dep
+    cflags += '-DUSE_OPENSSL'
+endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v3 2/3] examples/fips_validation: encode digest with hash OID
  2022-10-11  9:26   ` [v3 0/3] " Gowrishankar Muthukrishnan
  2022-10-11  9:26     ` [v3 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
@ 2022-10-11  9:26     ` Gowrishankar Muthukrishnan
  2022-10-11  9:26     ` [v3 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
                       ` (2 subsequent siblings)
  4 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-11  9:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS RSA validation requires hash digest be encoded with ASN.1
value for digest info.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/main.c | 78 +++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index dbf9c6fce2..f8bb89b0ec 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -844,6 +844,63 @@ prepare_aead_op(void)
 	return 0;
 }
 
+static int
+get_hash_oid(enum rte_crypto_auth_algorithm hash, uint8_t *buf)
+{
+	uint8_t id_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x03, 0x05, 0x00, 0x04,
+				  0x40};
+	uint8_t id_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x02, 0x05, 0x00, 0x04,
+				  0x30};
+	uint8_t id_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
+				  0x20};
+	uint8_t id_sha224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+				  0x1c};
+	uint8_t id_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+				0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+				0x00, 0x04, 0x14};
+	uint8_t *id = NULL;
+	int id_len = 0;
+
+	switch (hash) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		id = id_sha1;
+		id_len = sizeof(id_sha1);
+		break;
+	case RTE_CRYPTO_AUTH_SHA224:
+		id = id_sha224;
+		id_len = sizeof(id_sha224);
+		break;
+	case RTE_CRYPTO_AUTH_SHA256:
+		id = id_sha256;
+		id_len = sizeof(id_sha256);
+		break;
+	case RTE_CRYPTO_AUTH_SHA384:
+		id = id_sha384;
+		id_len = sizeof(id_sha384);
+		break;
+	case RTE_CRYPTO_AUTH_SHA512:
+		id = id_sha512;
+		id_len = sizeof(id_sha512);
+		break;
+	default:
+		id_len = -1;
+		break;
+	}
+
+	if (id != NULL)
+		rte_memcpy(buf, id, id_len);
+
+	return id_len;
+}
+
 static int
 prepare_rsa_op(void)
 {
@@ -857,6 +914,27 @@ prepare_rsa_op(void)
 	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
 
 	if (env.digest) {
+		if (asym->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_PKCS1_5) {
+			int b_len = 0;
+			uint8_t b[32];
+
+			b_len = get_hash_oid(asym->rsa.padding.hash, b);
+			if (b_len < 0) {
+				RTE_LOG(ERR, USER1, "Failed to get digest info for hash %d\n",
+					asym->rsa.padding.hash);
+				return -EINVAL;
+			}
+
+			if (b_len) {
+				msg.len = env.digest_len + b_len;
+				msg.val = rte_zmalloc(NULL, msg.len, 0);
+				rte_memcpy(msg.val, b, b_len);
+				rte_memcpy(msg.val + b_len, env.digest, env.digest_len);
+				rte_free(env.digest);
+				env.digest = msg.val;
+				env.digest_len = msg.len;
+			}
+		}
 		msg.val = env.digest;
 		msg.len = env.digest_len;
 	} else {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v3 3/3] examples/fips_validation: randomize message for conformance test
  2022-10-11  9:26   ` [v3 0/3] " Gowrishankar Muthukrishnan
  2022-10-11  9:26     ` [v3 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
  2022-10-11  9:26     ` [v3 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
@ 2022-10-11  9:26     ` Gowrishankar Muthukrishnan
  2022-10-11 15:37     ` [v3 0/3] FIPS asymmetric validation Akhil Goyal
  2022-10-11 16:08     ` [v4 " Gowrishankar Muthukrishnan
  4 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-11  9:26 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS conformance tests require randomizing message based on SP 800-106.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.h    |   4 +
 .../fips_validation/fips_validation_rsa.c     | 112 +++++++++++++++++-
 2 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index ed59322635..7cbbc1f084 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -210,6 +210,7 @@ struct rsa_interim_data {
 	uint16_t saltlen;
 	enum rte_crypto_rsa_padding_type padding;
 	enum rte_crypto_rsa_priv_key_type privkey;
+	uint8_t random_msg;
 };
 
 #ifdef USE_JANSSON
@@ -336,6 +337,9 @@ parse_test_tdes_json_init(void);
 
 int
 parse_test_rsa_json_init(void);
+
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand);
 #endif /* USE_JANSSON */
 
 int
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
index d3699f54d0..22c0faf3cb 100644
--- a/examples/fips_validation/fips_validation_rsa.c
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -19,11 +19,13 @@
 
 #include "fips_validation.h"
 
+#define CONFORMANCE_JSON_STR	"conformance"
 #define TESTTYPE_JSON_STR	"testType"
 #define SIGTYPE_JSON_STR "sigType"
 #define MOD_JSON_STR	"modulo"
 #define HASH_JSON_STR	"hashAlg"
 #define SALT_JSON_STR	"saltLen"
+#define RV_JSON_STR	"randomValue"
 #define E_JSON_STR	"e"
 #define N_JSON_STR	"n"
 
@@ -31,6 +33,10 @@
 #define MSG_JSON_STR	"message"
 #define SIG_JSON_STR	"signature"
 
+
+#define RV_BUF_LEN (1024/8)
+#define RV_BIT_LEN (256)
+
 #ifdef USE_JANSSON
 struct {
 	uint8_t type;
@@ -259,6 +265,13 @@ prepare_vec_rsa(void)
 	if (!BN_mod_inverse(qinv, q, p, ctx))
 		goto err;
 
+	if (info.interim_info.rsa_data.random_msg) {
+		if (!BN_generate_prime_ex(r, RV_BIT_LEN, 0, NULL, NULL, NULL))
+			goto err;
+
+		parse_uint8_hex_str("", BN_bn2hex(r), &vec.rsa.seed);
+	}
+
 	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
 	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
 	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
@@ -297,6 +310,11 @@ parse_test_rsa_json_interim_writeback(struct fips_val *val)
 {
 	RTE_SET_USED(val);
 
+	if (info.interim_info.rsa_data.random_msg) {
+		json_object_set_new(json_info.json_write_group, "conformance",
+							json_string("SP800-106"));
+	}
+
 	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
 		json_t *obj;
 
@@ -367,6 +385,14 @@ parse_test_rsa_json_writeback(struct fips_val *val)
 		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
 		obj = json_string(info.one_line_text);
 		json_object_set_new(json_info.json_write_case, "signature", obj);
+
+		if (info.interim_info.rsa_data.random_msg) {
+			writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+			obj = json_string(info.one_line_text);
+			json_object_set_new(json_info.json_write_case, "randomValue", obj);
+			json_object_set_new(json_info.json_write_case, "randomValueLen",
+				json_integer(vec.rsa.seed.len * 8));
+		}
 	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
 			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
@@ -406,6 +432,8 @@ parse_interim_str(const char *key, char *src, struct fips_val *val)
 		if (i >= RTE_DIM(rsa_auth_algs))
 			return -EINVAL;
 
+	}  else if (strcmp(key, CONFORMANCE_JSON_STR) == 0) {
+		info.interim_info.rsa_data.random_msg = 1;
 	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
 		info.interim_info.rsa_data.saltlen = atoi(src);
 	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
@@ -436,6 +464,83 @@ parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
 	return prepare_vec_rsa();
 }
 
+/*
+ * Message randomization function as per NIST SP 800-106.
+ */
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand)
+{
+	uint8_t m[FIPS_TEST_JSON_BUF_LEN], rv[RV_BUF_LEN];
+	uint32_t m_bitlen, rv_bitlen, count, remain, i, j;
+	uint16_t rv_len;
+
+	if (!msg->val || !rand->val || rand->len > RV_BUF_LEN
+		|| msg->len > FIPS_TEST_JSON_BUF_LEN)
+		return -EINVAL;
+
+	memset(rv, 0, sizeof(rv));
+	memcpy(rv, rand->val, rand->len);
+	rv_bitlen = rand->len * 8;
+	rv_len = rand->len;
+
+	memset(m, 0, sizeof(m));
+	memcpy(m, msg->val, msg->len);
+	m_bitlen = msg->len * 8;
+
+	if (m_bitlen >= (rv_bitlen - 1)) {
+		m[msg->len] = 0x80;
+		m_bitlen += 8;
+	} else {
+		m[msg->len] = 0x80;
+		m_bitlen += (rv_bitlen - m_bitlen - 8);
+	}
+
+	count = m_bitlen / rv_bitlen;
+	remain = m_bitlen % rv_bitlen;
+	for (i = 0; i < count * rv_len; i++)
+		m[i] ^= rv[i % rv_len];
+
+	for (j = 0; j < remain / 8; j++)
+		m[i + j] ^= rv[j];
+
+	m[i + j] = ((uint8_t *)&rv_bitlen)[0];
+	m[i + j + 1] = (((uint8_t *)&rv_bitlen)[1] >> 8) & 0xFF;
+
+	rte_free(msg->val);
+	msg->len = (rv_bitlen + m_bitlen + 16) / 8;
+	msg->val = rte_zmalloc(NULL, msg->len, 0);
+	if (!msg->val)
+		return -EPERM;
+
+	memcpy(msg->val, rv, rv_len);
+	memcpy(&msg->val[rv_len], m, (m_bitlen + 16) / 8);
+	return 0;
+}
+
+static int
+parse_siggen_message_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(val, &vec.rsa.seed);
+
+	return ret;
+}
+
+static int
+parse_sigver_randomvalue_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(&vec.pt, val);
+
+	return ret;
+}
+
 struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
@@ -447,6 +552,7 @@ struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
 		{NULL, NULL, NULL} /**< end pointer */
@@ -456,6 +562,7 @@ struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
 		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
@@ -470,13 +577,14 @@ struct fips_test_callback rsa_keygen_json_vectors[] = {
 };
 
 struct fips_test_callback rsa_siggen_json_vectors[] = {
-		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{MSG_JSON_STR, parse_siggen_message_str, &vec.pt},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
 struct fips_test_callback rsa_sigver_json_vectors[] = {
 		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
 		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{RV_JSON_STR, parse_sigver_randomvalue_str, &vec.rsa.seed},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -492,6 +600,7 @@ parse_test_rsa_json_init(void)
 	info.parse_writeback = NULL;
 	info.interim_callbacks = NULL;
 	info.parse_interim_writeback = NULL;
+	info.interim_info.rsa_data.random_msg = 0;
 
 	if (strcmp(mode_str, "keyGen") == 0) {
 		info.op = FIPS_TEST_ASYM_KEYGEN;
@@ -506,6 +615,7 @@ parse_test_rsa_json_init(void)
 		info.op = FIPS_TEST_ASYM_SIGVER;
 		info.callbacks = rsa_sigver_json_vectors;
 		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
 	} else {
 		return -EINVAL;
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [v3 0/3] FIPS asymmetric validation
  2022-10-11  9:26   ` [v3 0/3] " Gowrishankar Muthukrishnan
                       ` (2 preceding siblings ...)
  2022-10-11  9:26     ` [v3 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
@ 2022-10-11 15:37     ` Akhil Goyal
  2022-10-11 16:08     ` [v4 " Gowrishankar Muthukrishnan
  4 siblings, 0 replies; 39+ messages in thread
From: Akhil Goyal @ 2022-10-11 15:37 UTC (permalink / raw)
  To: Gowrishankar Muthukrishnan, dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Jerin Jacob Kollanukkaran,
	Gowrishankar Muthukrishnan

> Subject: [v3 0/3] FIPS asymmetric validation
> 
> This patch series adds support in fips_validation app to perform
> asymmetric validation. To start with, RSA algorithm is used in
> the evaluation. For the key value pairs which is multiprecision
> in arithmetic, openssl library is used.
> 
> Changes:
>  v3:
>   - patches 5,6 and 7 in v2 are rebased and submitted here.

Rebase on latest next-crypto needed as GMAC and CTR are merged.

>  v2:
>   - minor fixes in v1
>   - addition of digest encoding for fips validation
>   - addition of message randomization for fips conformance tests.
> 
> Gowrishankar Muthukrishnan (3):
>   examples/fips_validation: add asymmetric validation
>   examples/fips_validation: encode digest with hash OID
>   examples/fips_validation: randomize message for conformance test
> 
>  config/meson.build                            |   6 +
>  doc/guides/sample_app_ug/fips_validation.rst  |   1 +
>  examples/fips_validation/fips_validation.c    |   2 +
>  examples/fips_validation/fips_validation.h    |  51 +-
>  .../fips_validation/fips_validation_gcm.c     |   8 +-
>  .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
>  examples/fips_validation/main.c               | 546 ++++++++++++---
>  examples/fips_validation/meson.build          |   6 +
>  8 files changed, 1154 insertions(+), 96 deletions(-)
>  create mode 100644 examples/fips_validation/fips_validation_rsa.c
> 
> --
> 2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v4 0/3] FIPS asymmetric validation
  2022-10-11  9:26   ` [v3 0/3] " Gowrishankar Muthukrishnan
                       ` (3 preceding siblings ...)
  2022-10-11 15:37     ` [v3 0/3] FIPS asymmetric validation Akhil Goyal
@ 2022-10-11 16:08     ` Gowrishankar Muthukrishnan
  2022-10-11 16:08       ` [v4 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
                         ` (3 more replies)
  4 siblings, 4 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-11 16:08 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

This patch series adds support in fips_validation app to perform
asymmetric validation. To start with, RSA algorithm is used in
the evaluation. For the key value pairs which is multiprecision
in arithmetic, openssl library is used.

Changes:
 v4:
  - AES GMAC callback fixes.
 v3:
  - patches 5,6 and 7 in v2 are rebased and submitted here.
 v2:
  - minor fixes in v1
  - addition of digest encoding for fips validation
  - addition of message randomization for fips conformance tests.

Gowrishankar Muthukrishnan (3):
  examples/fips_validation: add asymmetric validation
  examples/fips_validation: encode digest with hash OID
  examples/fips_validation: randomize message for conformance test

 config/meson.build                            |   6 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  51 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
 examples/fips_validation/main.c               | 550 ++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 8 files changed, 1156 insertions(+), 98 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v4 1/3] examples/fips_validation: add asymmetric validation
  2022-10-11 16:08     ` [v4 " Gowrishankar Muthukrishnan
@ 2022-10-11 16:08       ` Gowrishankar Muthukrishnan
  2022-10-11 16:08       ` [v4 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
                         ` (2 subsequent siblings)
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-11 16:08 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add support for asymmetric crypto validation starting with RSA.
For the generation of crypto values which is multiprecision in
math, openssl library is used only for this purpose.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>

--
v4:
 - AES GMAC callback fix.
v3:
 - rebased according to cryptodev session rework changes.
v2:
 - improved handling priv key type.
---
 config/meson.build                            |   6 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  47 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 520 ++++++++++++++++++
 examples/fips_validation/main.c               | 472 +++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 8 files changed, 964 insertions(+), 98 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

diff --git a/config/meson.build b/config/meson.build
index 0fc209db01..e82797d206 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -226,6 +226,12 @@ if jansson_dep.found()
     dpdk_conf.set('RTE_HAS_JANSSON', 1)
 endif
 
+# check for openssl
+openssl_dep = dependency('openssl', required: false, method: 'pkg-config')
+if openssl_dep.found()
+    dpdk_conf.set('RTE_HAS_OPENSSL', 1)
+endif
+
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
 pcap_lib = is_windows ? 'wpcap' : 'pcap'
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index e8929fdad4..2cf92483d7 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -68,6 +68,7 @@ ACVP
     * SHA (1, 256, 384, 512) - AFT, MCT
     * TDES-CBC - AFT, MCT
     * TDES-ECB - AFT, MCT
+    * RSA
 
 
 Application Information
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index dddfd3f9d8..3bb5937805 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -477,6 +477,8 @@ fips_test_parse_one_json_vector_set(void)
 	else if (strstr(algo_str, "TDES-CBC") ||
 		strstr(algo_str, "TDES-ECB"))
 		info.algo = FIPS_TEST_ALGO_TDES;
+	else if (strstr(algo_str, "RSA"))
+		info.algo = FIPS_TEST_ALGO_RSA;
 	else
 		return -EINVAL;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 182cff9a00..7c275403c7 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -44,6 +44,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_SHA,
+		FIPS_TEST_ALGO_RSA,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -57,6 +58,9 @@ enum file_types {
 enum fips_test_op {
 	FIPS_TEST_ENC_AUTH_GEN = 1,
 	FIPS_TEST_DEC_AUTH_VERIF,
+	FIPS_TEST_ASYM_KEYGEN,
+	FIPS_TEST_ASYM_SIGGEN,
+	FIPS_TEST_ASYM_SIGVER
 };
 
 #define MAX_LINE_PER_VECTOR            16
@@ -80,11 +84,22 @@ struct fips_test_vector {
 			struct fips_val aad;
 		} aead;
 	};
+	struct {
+		struct fips_val seed;
+		struct fips_val signature;
+		struct fips_val e;
+		struct fips_val n;
+		struct fips_val d;
+		struct fips_val p;
+		struct fips_val q;
+		struct fips_val dp;
+		struct fips_val dq;
+		struct fips_val qinv;
+	} rsa;
 
 	struct fips_val pt;
 	struct fips_val ct;
 	struct fips_val iv;
-
 	enum rte_crypto_op_status status;
 };
 
@@ -141,6 +156,12 @@ enum fips_sha_test_types {
 	SHA_MCT
 };
 
+enum fips_rsa_test_types {
+	RSA_AFT = 0,
+	RSA_GDT,
+	RSA_KAT
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -167,8 +188,9 @@ struct ccm_interim_data {
 };
 
 struct sha_interim_data {
-	enum fips_sha_test_types test_type;
+	/* keep algo always on top as it is also used in asym digest */
 	enum rte_crypto_auth_algorithm algo;
+	enum fips_sha_test_types test_type;
 };
 
 struct gcm_interim_data {
@@ -185,6 +207,14 @@ struct xts_interim_data {
 	enum xts_tweak_modes tweak_mode;
 };
 
+struct rsa_interim_data {
+	enum rte_crypto_auth_algorithm auth;
+	uint16_t modulo;
+	uint16_t saltlen;
+	enum rte_crypto_rsa_padding_type padding;
+	enum rte_crypto_rsa_priv_key_type privkey;
+};
+
 #ifdef USE_JANSSON
 /*
  * Maximum length of buffer to hold any json string.
@@ -230,6 +260,7 @@ struct fips_test_interim_info {
 		struct sha_interim_data sha_data;
 		struct gcm_interim_data gcm_data;
 		struct xts_interim_data xts_data;
+		struct rsa_interim_data rsa_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -305,6 +336,9 @@ parse_test_sha_json_test_type(void);
 
 int
 parse_test_tdes_json_init(void);
+
+int
+parse_test_rsa_json_init(void);
 #endif /* USE_JANSSON */
 
 int
@@ -366,11 +400,14 @@ update_info_vec(uint32_t count);
 
 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 *);
+typedef int (*fips_prepare_sym_xform_t)(struct rte_crypto_sym_xform *);
+typedef int (*fips_prepare_asym_xform_t)(struct rte_crypto_asym_xform *);
 
 struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
+	fips_prepare_sym_xform_t prepare_sym_xform;
+	fips_prepare_asym_xform_t prepare_asym_xform;
+	fips_prepare_op_t prepare_sym_op;
+	fips_prepare_op_t prepare_asym_op;
 	fips_test_one_case_t test;
 };
 
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index d6dfdd2443..1b141501f0 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -81,12 +81,12 @@ parser_read_gcm_pt_len(const char *key, char *src,
 
 	if (vec.pt.len == 0) {
 		info.interim_info.gcm_data.is_gmac = 1;
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 	} else {
 		info.interim_info.gcm_data.is_gmac = 0;
-		test_ops.prepare_op = prepare_aead_op;
-		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_xform = prepare_gcm_xform;
 	}
 
 	return ret;
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
new file mode 100644
index 0000000000..d3699f54d0
--- /dev/null
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -0,0 +1,520 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell.
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/random.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef USE_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#endif /* USE_OPENSSL */
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define TESTTYPE_JSON_STR	"testType"
+#define SIGTYPE_JSON_STR "sigType"
+#define MOD_JSON_STR	"modulo"
+#define HASH_JSON_STR	"hashAlg"
+#define SALT_JSON_STR	"saltLen"
+#define E_JSON_STR	"e"
+#define N_JSON_STR	"n"
+
+#define SEED_JSON_STR	"seed"
+#define MSG_JSON_STR	"message"
+#define SIG_JSON_STR	"signature"
+
+#ifdef USE_JANSSON
+struct {
+	uint8_t type;
+	const char *desc;
+} rsa_test_types[] = {
+		{RSA_AFT, "AFT"},
+		{RSA_GDT, "GDT"},
+		{RSA_KAT, "KAT"},
+};
+
+struct {
+	enum rte_crypto_auth_algorithm auth;
+	const char *desc;
+} rsa_auth_algs[] = {
+		{RTE_CRYPTO_AUTH_SHA1, "SHA-1"},
+		{RTE_CRYPTO_AUTH_SHA224, "SHA2-224"},
+		{RTE_CRYPTO_AUTH_SHA256, "SHA2-256"},
+		{RTE_CRYPTO_AUTH_SHA384, "SHA2-384"},
+		{RTE_CRYPTO_AUTH_SHA512, "SHA2-512"},
+};
+
+struct {
+	enum rte_crypto_rsa_padding_type padding;
+	const char *desc;
+} rsa_padding_types[] = {
+		{RTE_CRYPTO_RSA_PADDING_NONE, "none"},
+		{RTE_CRYPTO_RSA_PADDING_PKCS1_5, "pkcs1v1.5"},
+		{RTE_CRYPTO_RSA_PADDING_OAEP, "oaep"},
+		{RTE_CRYPTO_RSA_PADDING_PSS, "pss"},
+};
+
+#ifdef USE_OPENSSL
+static int
+prepare_vec_rsa(void)
+{
+	BIGNUM *p = NULL, *q = NULL, *n = NULL, *d = NULL, *e = NULL;
+	BIGNUM *dp = NULL, *dq = NULL, *qinv = NULL;
+	BIGNUM *r0, *r1, *r2, *r3, *r4;
+	BIGNUM *m = NULL, *r = NULL;
+	int bits, ret = -1, i;
+	char modbuf[8], *buf;
+	BN_CTX *ctx = NULL;
+	unsigned long pid;
+
+	/* Seed PRNG */
+	if (vec.rsa.seed.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		RAND_seed((char *)info.one_line_text, strlen(info.one_line_text));
+	} else {
+		pid = getpid();
+		RAND_seed(&pid, sizeof(pid));
+	}
+
+	if (!RAND_status())
+		return -1;
+
+	/* Check if e is known already */
+	if (vec.rsa.e.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		ret = BN_hex2bn(&e, info.one_line_text);
+		if ((uint32_t)ret != strlen(info.one_line_text))
+			goto err;
+	}
+
+	/* BN context initialization */
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto err;
+
+	BN_CTX_start(ctx);
+	r0 = BN_CTX_get(ctx);
+	r1 = BN_CTX_get(ctx);
+	r2 = BN_CTX_get(ctx);
+	r3 = BN_CTX_get(ctx);
+	r4 = BN_CTX_get(ctx);
+	if (!r4)
+		goto err;
+
+	/* Calculate bit length for prime numbers */
+	m = BN_new();
+	if (!m)
+		goto err;
+
+	snprintf(modbuf, sizeof(modbuf), "%d", info.interim_info.rsa_data.modulo);
+	if (!BN_dec2bn(&m, modbuf))
+		goto err;
+
+	r = BN_new();
+	if (!r)
+		goto err;
+
+	if (!BN_rshift1(r, m))
+		goto err;
+
+	buf = BN_bn2dec(r);
+	bits = atoi(buf);
+
+	p = BN_new();
+	if (!p)
+		goto err;
+
+	q = BN_new();
+	if (!q)
+		goto err;
+
+	n = BN_new();
+	if (!n)
+		goto err;
+
+	d = BN_new();
+	if (!d)
+		goto err;
+
+	/* Generate p and q suitably for RSA */
+	for (i = 0; i < 10; i++) {
+		uint8_t j = 0;
+
+		if (!BN_generate_prime_ex(p, bits, 0, NULL, NULL, NULL))
+			goto err;
+
+		do {
+			RAND_add(&j, sizeof(j), 1);
+			if (!BN_generate_prime_ex(q, bits, 0, NULL, NULL, NULL))
+				goto err;
+
+		} while ((BN_cmp(p, q) == 0) && (j++ < 100));
+
+		if (j >= 100) {
+			RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate q", j);
+			goto err;
+		}
+
+		/* pq */
+		if (!BN_mul(n, p, q, ctx))
+			goto err;
+
+		/* p-1 */
+		if (!BN_sub(r1, p, BN_value_one()))
+			goto err;
+
+		/* q-1 */
+		if (!BN_sub(r2, q, BN_value_one()))
+			goto err;
+
+		/* (p-1 * q-1) */
+		if (!BN_mul(r0, r1, r2, ctx))
+			goto err;
+
+		/* gcd(p-1, q-1)*/
+		if (!BN_gcd(r3, r1, r2, ctx))
+			goto err;
+
+		/* lcm(p-1, q-1) */
+		if (!BN_div(r4, r, r0, r3, ctx))
+			goto err;
+
+		/* check if div and rem are non-zero */
+		if (!r4 || !r)
+			goto err;
+
+		/* 0 < e < lcm */
+		if (!e) {
+			int k = 0;
+
+			e = BN_new();
+			do {
+				RAND_add(&k, sizeof(k), 1);
+				if (!BN_rand(e, 32, 1, 1))
+					goto err;
+
+				if (!BN_gcd(r3, e, r4, ctx))
+					goto err;
+
+				if (BN_is_one(r3))
+					break;
+			} while (k++ < 10);
+
+			if (k >= 10) {
+				RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate e",
+					k);
+				goto err;
+			}
+		}
+
+		/* (de) mod lcm == 1 */
+		if (!BN_mod_inverse(d, e, r4, ctx))
+			goto err;
+
+		if (!BN_gcd(r3, r1, e, ctx))
+			goto err;
+
+		if (!BN_gcd(r4, r2, e, ctx))
+			goto err;
+
+		/* check if gcd(p-1, e) and gcd(q-1, e) are 1 */
+		if (BN_is_one(r3) && BN_is_one(r4))
+			break;
+	}
+
+	if (i >= 10) {
+		RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate p and q", i);
+		goto err;
+	}
+
+	/* d mod (p-1) */
+	dp = BN_new();
+	if (!dp)
+		goto err;
+
+	if (!BN_mod(dp, d, r1, ctx))
+		goto err;
+
+	/* d mod (q-1) */
+	dq = BN_new();
+	if (!dq)
+		goto err;
+
+	if (!BN_mod(dq, d, r2, ctx))
+		goto err;
+
+	/* modinv of q and p */
+	qinv = BN_new();
+	if (!qinv)
+		goto err;
+
+	if (!BN_mod_inverse(qinv, q, p, ctx))
+		goto err;
+
+	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
+	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
+	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
+	parse_uint8_hex_str("", BN_bn2hex(n), &vec.rsa.n);
+	parse_uint8_hex_str("", BN_bn2hex(d), &vec.rsa.d);
+	parse_uint8_hex_str("", BN_bn2hex(dp), &vec.rsa.dp);
+	parse_uint8_hex_str("", BN_bn2hex(dq), &vec.rsa.dq);
+	parse_uint8_hex_str("", BN_bn2hex(qinv), &vec.rsa.qinv);
+
+	ret = 0;
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(m);
+	BN_free(r);
+	BN_free(p);
+	BN_free(q);
+	BN_free(n);
+	BN_free(d);
+	BN_free(e);
+	return ret;
+}
+#else
+static int
+prepare_vec_rsa(void)
+{
+	/*
+	 * Generate RSA values.
+	 */
+	return -ENOTSUP;
+}
+#endif /* USE_OPENSSL */
+
+static int
+parse_test_rsa_json_interim_writeback(struct fips_val *val)
+{
+	RTE_SET_USED(val);
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		/* For siggen tests, RSA values can be created soon after
+		 * the test group data are parsed.
+		 */
+		if (vec.rsa.e.val) {
+			rte_free(vec.rsa.e.val);
+			vec.rsa.e.val = NULL;
+		}
+
+		if (prepare_vec_rsa() < 0)
+			return -1;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "e", obj);
+	}
+
+	return 0;
+}
+
+static int
+parse_test_rsa_json_writeback(struct fips_val *val)
+{
+	json_t *tcId;
+
+	RTE_SET_USED(val);
+
+	tcId = json_object_get(json_info.json_test_case, "tcId");
+
+	json_info.json_write_case = json_object();
+	json_object_set(json_info.json_write_case, "tcId", tcId);
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "seed", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "e", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.p);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "p", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.q);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "q", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.d);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "d", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "signature", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
+		else
+			json_object_set_new(json_info.json_write_case, "testPassed", json_false());
+	}
+
+	return 0;
+}
+
+static int
+parse_interim_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t i;
+
+	RTE_SET_USED(val);
+
+	if (strcmp(key, SIGTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_padding_types); i++)
+			if (strstr(src, rsa_padding_types[i].desc)) {
+				info.interim_info.rsa_data.padding = rsa_padding_types[i].padding;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_padding_types))
+			return -EINVAL;
+
+	}  else if (strcmp(key, MOD_JSON_STR) == 0) {
+		info.interim_info.rsa_data.modulo = atoi(src);
+	} else if (strcmp(key, HASH_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_auth_algs); i++)
+			if (strstr(src, rsa_auth_algs[i].desc)) {
+				info.interim_info.rsa_data.auth = rsa_auth_algs[i].auth;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_auth_algs))
+			return -EINVAL;
+
+	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
+		info.interim_info.rsa_data.saltlen = atoi(src);
+	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_test_types); i++)
+			if (strstr(src, rsa_test_types[i].desc)) {
+				info.parse_writeback = parse_test_rsa_json_writeback;
+				break;
+			}
+
+		if (!info.parse_writeback || i >= RTE_DIM(rsa_test_types))
+			return -EINVAL;
+
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
+{
+	parse_uint8_hex_str(key, src, val);
+
+	/* For keygen tests, key "e" can be the end of input data
+	 * to generate RSA values.
+	 */
+	return prepare_vec_rsa();
+}
+
+struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
+		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_keygen_json_vectors[] = {
+		{SEED_JSON_STR, parse_uint8_hex_str, &vec.rsa.seed},
+		{E_JSON_STR, parse_keygen_e_str, &vec.rsa.e},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_rsa_json_init(void)
+{
+	json_t *keyfmt_obj = json_object_get(json_info.json_vector_set, "keyFormat");
+	json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode");
+	const char *keyfmt_str = json_string_value(keyfmt_obj);
+	const char *mode_str = json_string_value(mode_obj);
+
+	info.callbacks = NULL;
+	info.parse_writeback = NULL;
+	info.interim_callbacks = NULL;
+	info.parse_interim_writeback = NULL;
+
+	if (strcmp(mode_str, "keyGen") == 0) {
+		info.op = FIPS_TEST_ASYM_KEYGEN;
+		info.callbacks = rsa_keygen_json_vectors;
+		info.interim_callbacks = rsa_keygen_interim_json_vectors;
+	} else if (strcmp(mode_str, "sigGen") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGGEN;
+		info.callbacks = rsa_siggen_json_vectors;
+		info.interim_callbacks = rsa_siggen_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
+	} else if (strcmp(mode_str, "sigVer") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGVER;
+		info.callbacks = rsa_sigver_json_vectors;
+		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+	} else {
+		return -EINVAL;
+	}
+
+	info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_QT;
+	if (keyfmt_str != NULL && strcmp(keyfmt_str, "standard") == 0)
+		info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_EXP;
+
+	return 0;
+}
+#endif /* USE_JANSSON */
+
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 7b31579d04..538c0c98e2 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -37,6 +37,8 @@ enum {
 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
 #define OPT_USE_JSON                "use-json"
 	OPT_USE_JSON_NUM,
+#define OPT_CRYPTODEV_ASYM          "asymmetric"
+	OPT_CRYPTODEV_ASYM_NUM,
 };
 
 struct fips_test_vector vec;
@@ -51,34 +53,140 @@ struct cryptodev_fips_validate_env {
 	const char *rsp_path;
 	uint32_t is_path_folder;
 	uint8_t dev_id;
+	struct rte_mempool *mpool;
+	struct fips_sym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_sym_session *sess;
+		struct rte_crypto_op *op;
+	} sym;
+	struct fips_asym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_asym_session *sess;
+		struct rte_crypto_op *op;
+	} asym;
+	struct rte_crypto_op *op;
 	uint8_t dev_support_sgl;
 	uint16_t mbuf_data_room;
-	struct rte_mempool *mpool;
-	struct rte_mempool *sess_mpool;
-	struct rte_mempool *op_pool;
 	struct rte_mbuf *mbuf;
 	uint8_t *digest;
 	uint16_t digest_len;
-	struct rte_crypto_op *op;
-	void *sess;
+	bool is_asym_test;
 	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
 static int
-cryptodev_fips_validate_app_int(void)
+cryptodev_fips_validate_app_sym_init(void)
+{
+	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
+							env.dev_id);
+	struct rte_cryptodev_info dev_info;
+	struct fips_sym_env *sym = &env.sym;
+	int ret;
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	ret = -ENOMEM;
+	sym->sess_mpool = rte_cryptodev_sym_session_pool_create(
+			"FIPS_SYM_SESS_MEMPOOL", 16, sess_sz, 0, 0, rte_socket_id());
+	if (!sym->sess_mpool)
+		goto error_exit;
+
+	sym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_SYM_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!sym->op_pool)
+		goto error_exit;
+
+	sym->op = rte_crypto_op_alloc(sym->op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!sym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_sym_uninit(void)
+{
+	struct fips_sym_env *sym = &env.sym;
+
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(sym->op);
+	rte_cryptodev_sym_session_free(env.dev_id, sym->sess);
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_asym_init(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+	int ret;
+
+	ret = -ENOMEM;
+	asym->sess_mpool = rte_cryptodev_asym_session_pool_create(
+			"FIPS_ASYM_SESS_MEMPOOL", 16, 0, 0, rte_socket_id());
+	if (!asym->sess_mpool)
+		goto error_exit;
+
+	asym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_ASYM_POOL",
+			RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!asym->op_pool)
+		goto error_exit;
+
+	asym->op = rte_crypto_op_alloc(asym->op_pool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!asym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_asym_uninit(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+
+	rte_crypto_op_free(asym->op);
+	rte_cryptodev_asym_session_free(env.dev_id, asym->sess);
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_init(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL};
-	struct rte_cryptodev_info dev_info;
-	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
-			env.dev_id);
 	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
 	int ret;
 
 	if (env.self_test) {
 		ret = fips_dev_self_test(env.dev_id, env.broken_test_config);
 		if (ret < 0) {
+			rte_cryptodev_stop(env.dev_id);
 			rte_cryptodev_close(env.dev_id);
 
 			return ret;
@@ -89,45 +197,24 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	rte_cryptodev_info_get(env.dev_id, &dev_info);
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
-		env.dev_support_sgl = 1;
-	else
-		env.dev_support_sgl = 0;
-
+	ret = -ENOMEM;
 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
 			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
 			env.mbuf_data_room, rte_socket_id());
 	if (!env.mpool)
 		return ret;
 
-	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
-			rte_socket_id());
+	ret = cryptodev_fips_validate_app_sym_init();
 	if (ret < 0)
-		return ret;
-
-	ret = -ENOMEM;
-
-	env.sess_mpool = rte_cryptodev_sym_session_pool_create(
-			"FIPS_SESS_MEMPOOL", 16, sess_sz, 0, 0,
-			rte_socket_id());
-	if (!env.sess_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.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	if (!env.op)
-		goto error_exit;
+	if (env.is_asym_test) {
+		ret = cryptodev_fips_validate_app_asym_init();
+		if (ret < 0)
+			goto error_exit;
+	}
 
-	qp_conf.mp_session = env.sess_mpool;
+	qp_conf.mp_session = env.sym.sess_mpool;
 
 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
 			rte_socket_id());
@@ -141,23 +228,21 @@ cryptodev_fips_validate_app_int(void)
 	return 0;
 
 error_exit:
-
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	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_free(env.dev_id, env.sess);
+	cryptodev_fips_validate_app_sym_uninit();
+
+	if (env.is_asym_test)
+		cryptodev_fips_validate_app_asym_uninit();
+
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	rte_mempool_free(env.op_pool);
+	rte_cryptodev_stop(env.dev_id);
+	rte_cryptodev_close(env.dev_id);
 }
 
 static int
@@ -253,6 +338,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+		{OPT_CRYPTODEV_ASYM, no_argument,
+				NULL, OPT_CRYPTODEV_ASYM_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -365,6 +452,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			}
 			break;
 
+		case OPT_CRYPTODEV_ASYM_NUM:
+			env.is_asym_test = true;
+			break;
+
 		default:
 			cryptodev_fips_validate_usage(prgname);
 			return -EINVAL;
@@ -405,7 +496,7 @@ main(int argc, char *argv[])
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
 
-	ret = cryptodev_fips_validate_app_int();
+	ret = cryptodev_fips_validate_app_init();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
 		return -1;
@@ -644,7 +735,7 @@ prepare_cipher_op(void)
 		sym->cipher.data.length = vec.ct.len;
 	}
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	sym->m_src = env.mbuf;
 	sym->cipher.data.offset = 0;
@@ -707,7 +798,7 @@ prepare_auth_op(void)
 		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	return 0;
 }
@@ -763,7 +854,55 @@ prepare_aead_op(void)
 	sym->aead.aad.data = vec.aead.aad.val;
 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
+
+	return 0;
+}
+
+static int
+prepare_rsa_op(void)
+{
+	struct rte_crypto_asym_op *asym;
+	struct fips_val msg;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+
+	asym = env.op->asym;
+	asym->rsa.padding.type = info.interim_info.rsa_data.padding;
+	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
+
+	if (env.digest) {
+		msg.val = env.digest;
+		msg.len = env.digest_len;
+	} else {
+		msg.val = vec.pt.val;
+		msg.len = vec.pt.len;
+	}
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+
+		if (vec.rsa.signature.val)
+			rte_free(vec.rsa.signature.val);
+
+		vec.rsa.signature.val = rte_zmalloc(NULL, vec.rsa.n.len, 0);
+		vec.rsa.signature.len = vec.rsa.n.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = 0;
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = vec.rsa.signature.len;
+	} else {
+		RTE_LOG(ERR, USER1, "Invalid op %d\n", info.op);
+		return -EINVAL;
+	}
+
+	rte_crypto_op_attach_asym_session(env.op, env.asym.sess);
 
 	return 0;
 }
@@ -1154,6 +1293,87 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_rsa_xform(struct rte_crypto_asym_xform *xform)
+{
+	const struct rte_cryptodev_asymmetric_xform_capability *cap;
+	struct rte_cryptodev_asym_capability_idx cap_idx;
+	struct rte_cryptodev_info dev_info;
+
+	xform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	xform->next = NULL;
+
+	cap_idx.type = xform->xform_type;
+	cap = rte_cryptodev_asym_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;
+	}
+
+	switch (info.op) {
+	case FIPS_TEST_ASYM_SIGGEN:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_SIGN)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_SIGN);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_SIGVER:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_VERIFY)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_VERIFY);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_KEYGEN:
+		break;
+	default:
+		break;
+	}
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	xform->rsa.key_type = info.interim_info.rsa_data.privkey;
+	switch (xform->rsa.key_type) {
+	case RTE_RSA_KEY_TYPE_QT:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support QT key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.qt.p.data = vec.rsa.p.val;
+		xform->rsa.qt.p.length = vec.rsa.p.len;
+		xform->rsa.qt.q.data = vec.rsa.q.val;
+		xform->rsa.qt.q.length = vec.rsa.q.len;
+		xform->rsa.qt.dP.data = vec.rsa.dp.val;
+		xform->rsa.qt.dP.length = vec.rsa.dp.len;
+		xform->rsa.qt.dQ.data = vec.rsa.dq.val;
+		xform->rsa.qt.dQ.length = vec.rsa.dq.len;
+		xform->rsa.qt.qInv.data = vec.rsa.qinv.val;
+		xform->rsa.qt.qInv.length = vec.rsa.qinv.len;
+		break;
+	case RTE_RSA_KEY_TYPE_EXP:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support EXP key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.d.data = vec.rsa.d.val;
+		xform->rsa.d.length = vec.rsa.d.len;
+		break;
+	default:
+		break;
+	}
+
+	xform->rsa.e.data = vec.rsa.e.val;
+	xform->rsa.e.length = vec.rsa.e.len;
+	xform->rsa.n.data = vec.rsa.n.val;
+	xform->rsa.n.length = vec.rsa.n.len;
+	return 0;
+}
+
 static int
 get_writeback_data(struct fips_val *val)
 {
@@ -1200,25 +1420,22 @@ get_writeback_data(struct fips_val *val)
 }
 
 static int
-fips_run_test(void)
+fips_run_sym_test(void)
 {
 	struct rte_crypto_sym_xform xform = {0};
 	uint16_t n_deqd;
 	int ret;
 
-	ret = test_ops.prepare_xform(&xform);
+	ret = test_ops.prepare_sym_xform(&xform);
 	if (ret < 0)
 		return ret;
 
-	env.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
-			env.sess_mpool);
-	if (!env.sess) {
-		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
-				ret);
-		goto exit;
-	}
+	env.sym.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
+						env.sym.sess_mpool);
+	if (!env.sym.sess)
+		return -ENOMEM;
 
-	ret = test_ops.prepare_op();
+	ret = test_ops.prepare_sym_op();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
 				ret);
@@ -1234,21 +1451,88 @@ fips_run_test(void)
 	do {
 		struct rte_crypto_op *deqd_op;
 
-		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
-				1);
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1);
 	} while (n_deqd == 0);
 
 	vec.status = env.op->status;
 
 exit:
-	if (env.sess) {
-		rte_cryptodev_sym_session_free(env.dev_id, env.sess);
-		env.sess = NULL;
+	rte_cryptodev_sym_session_free(env.dev_id, env.sym.sess);
+	env.sym.sess = NULL;
+	return ret;
+}
+
+static int
+fips_run_asym_test(void)
+{
+	struct rte_crypto_asym_xform xform = {0};
+	struct rte_crypto_asym_op *asym;
+	struct rte_crypto_op *deqd_op;
+	int ret;
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		RTE_SET_USED(asym);
+		ret = 0;
+		goto exit;
+	}
+
+	asym = env.op->asym;
+	ret = test_ops.prepare_asym_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	ret = rte_cryptodev_asym_session_create(env.dev_id, &xform, env.asym.sess_mpool,
+			(void *)&env.asym.sess);
+	if (ret < 0)
+		return ret;
+
+	ret = test_ops.prepare_asym_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;
 	}
 
+	while (rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1) == 0)
+		rte_pause();
+
+	vec.status = env.op->status;
+
+ exit:
+	if (env.asym.sess)
+		rte_cryptodev_asym_session_free(env.dev_id, env.asym.sess);
+
+	env.asym.sess = NULL;
 	return ret;
 }
 
+static int
+fips_run_test(void)
+{
+	int ret;
+
+	env.op = env.sym.op;
+	if (env.is_asym_test) {
+		vec.cipher_auth.digest.len = parse_test_sha_hash_size(
+						info.interim_info.rsa_data.auth);
+		test_ops.prepare_sym_xform = prepare_sha_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		ret = fips_run_sym_test();
+		if (ret < 0)
+			return ret;
+	} else {
+		return fips_run_sym_test();
+	}
+
+	env.op = env.asym.op;
+	return fips_run_asym_test();
+}
+
 static int
 fips_generic_test(void)
 {
@@ -1271,9 +1555,11 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	ret = get_writeback_data(&val);
-	if (ret < 0)
-		return ret;
+	if (!env.is_asym_test) {
+		ret = get_writeback_data(&val);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1823,65 +2109,70 @@ init_test_ops(void)
 	case FIPS_TEST_ALGO_AES_CBC:
 	case FIPS_TEST_ALGO_AES_CTR:
 	case FIPS_TEST_ALGO_AES:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform  = prepare_aes_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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_GMAC:
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op= prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 		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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
 	case FIPS_TEST_ALGO_AES_XTS:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform = prepare_xts_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_xform = prepare_xts_xform;
+		test_ops.test = fips_generic_test;
+		break;
+	case FIPS_TEST_ALGO_RSA:
+		test_ops.prepare_asym_op = prepare_rsa_op;
+		test_ops.prepare_asym_xform = prepare_rsa_xform;
 		test_ops.test = fips_generic_test;
 		break;
 	default:
 		if (strstr(info.file_name, "TECB") ||
 				strstr(info.file_name, "TCBC")) {
 			info.algo = FIPS_TEST_ALGO_TDES;
-			test_ops.prepare_op = prepare_cipher_op;
-			test_ops.prepare_xform	= prepare_tdes_xform;
+			test_ops.prepare_sym_op = prepare_cipher_op;
+			test_ops.prepare_sym_xform = prepare_tdes_xform;
 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
 				test_ops.test = fips_mct_tdes_test;
 			else
@@ -2049,6 +2340,9 @@ fips_test_one_test_group(void)
 	case FIPS_TEST_ALGO_TDES:
 		ret = parse_test_tdes_json_init();
 		break;
+	case FIPS_TEST_ALGO_RSA:
+		ret = parse_test_rsa_json_init();
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 8bca26a095..d310093189 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -18,6 +18,7 @@ sources = files(
         'fips_validation_ccm.c',
         'fips_validation_sha.c',
         'fips_validation_xts.c',
+        'fips_validation_rsa.c',
         'fips_dev_self_test.c',
         'main.c',
 )
@@ -26,3 +27,8 @@ if dpdk_conf.has('RTE_HAS_JANSSON')
     ext_deps += jansson_dep
     cflags += '-DUSE_JANSSON'
 endif
+
+if dpdk_conf.has('RTE_HAS_OPENSSL')
+    ext_deps += openssl_dep
+    cflags += '-DUSE_OPENSSL'
+endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v4 2/3] examples/fips_validation: encode digest with hash OID
  2022-10-11 16:08     ` [v4 " Gowrishankar Muthukrishnan
  2022-10-11 16:08       ` [v4 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
@ 2022-10-11 16:08       ` Gowrishankar Muthukrishnan
  2022-10-11 16:08       ` [v4 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
  2022-10-12  3:56       ` [v5 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-11 16:08 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS RSA validation requires hash ddigest be encoded with ASN.1
value for digest info.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/main.c | 78 +++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 538c0c98e2..4af8d142e8 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -859,6 +859,63 @@ prepare_aead_op(void)
 	return 0;
 }
 
+static int
+get_hash_oid(enum rte_crypto_auth_algorithm hash, uint8_t *buf)
+{
+	uint8_t id_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x03, 0x05, 0x00, 0x04,
+				  0x40};
+	uint8_t id_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x02, 0x05, 0x00, 0x04,
+				  0x30};
+	uint8_t id_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
+				  0x20};
+	uint8_t id_sha224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+				  0x1c};
+	uint8_t id_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+				0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+				0x00, 0x04, 0x14};
+	uint8_t *id = NULL;
+	int id_len = 0;
+
+	switch (hash) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		id = id_sha1;
+		id_len = sizeof(id_sha1);
+		break;
+	case RTE_CRYPTO_AUTH_SHA224:
+		id = id_sha224;
+		id_len = sizeof(id_sha224);
+		break;
+	case RTE_CRYPTO_AUTH_SHA256:
+		id = id_sha256;
+		id_len = sizeof(id_sha256);
+		break;
+	case RTE_CRYPTO_AUTH_SHA384:
+		id = id_sha384;
+		id_len = sizeof(id_sha384);
+		break;
+	case RTE_CRYPTO_AUTH_SHA512:
+		id = id_sha512;
+		id_len = sizeof(id_sha512);
+		break;
+	default:
+		id_len = -1;
+		break;
+	}
+
+	if (id != NULL)
+		rte_memcpy(buf, id, id_len);
+
+	return id_len;
+}
+
 static int
 prepare_rsa_op(void)
 {
@@ -872,6 +929,27 @@ prepare_rsa_op(void)
 	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
 
 	if (env.digest) {
+		if (asym->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_PKCS1_5) {
+			int b_len = 0;
+			uint8_t b[32];
+
+			b_len = get_hash_oid(asym->rsa.padding.hash, b);
+			if (b_len < 0) {
+				RTE_LOG(ERR, USER1, "Failed to get digest info for hash %d\n",
+					asym->rsa.padding.hash);
+				return -EINVAL;
+			}
+
+			if (b_len) {
+				msg.len = env.digest_len + b_len;
+				msg.val = rte_zmalloc(NULL, msg.len, 0);
+				rte_memcpy(msg.val, b, b_len);
+				rte_memcpy(msg.val + b_len, env.digest, env.digest_len);
+				rte_free(env.digest);
+				env.digest = msg.val;
+				env.digest_len = msg.len;
+			}
+		}
 		msg.val = env.digest;
 		msg.len = env.digest_len;
 	} else {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v4 3/3] examples/fips_validation: randomize message for conformance test
  2022-10-11 16:08     ` [v4 " Gowrishankar Muthukrishnan
  2022-10-11 16:08       ` [v4 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
  2022-10-11 16:08       ` [v4 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
@ 2022-10-11 16:08       ` Gowrishankar Muthukrishnan
  2022-10-12  3:56       ` [v5 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-11 16:08 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Fan Zhang, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS conformance tests require randomizing message based on SP 800-106.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.h    |   4 +
 .../fips_validation/fips_validation_rsa.c     | 112 +++++++++++++++++-
 2 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 7c275403c7..eec9616462 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -213,6 +213,7 @@ struct rsa_interim_data {
 	uint16_t saltlen;
 	enum rte_crypto_rsa_padding_type padding;
 	enum rte_crypto_rsa_priv_key_type privkey;
+	uint8_t random_msg;
 };
 
 #ifdef USE_JANSSON
@@ -339,6 +340,9 @@ parse_test_tdes_json_init(void);
 
 int
 parse_test_rsa_json_init(void);
+
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand);
 #endif /* USE_JANSSON */
 
 int
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
index d3699f54d0..22c0faf3cb 100644
--- a/examples/fips_validation/fips_validation_rsa.c
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -19,11 +19,13 @@
 
 #include "fips_validation.h"
 
+#define CONFORMANCE_JSON_STR	"conformance"
 #define TESTTYPE_JSON_STR	"testType"
 #define SIGTYPE_JSON_STR "sigType"
 #define MOD_JSON_STR	"modulo"
 #define HASH_JSON_STR	"hashAlg"
 #define SALT_JSON_STR	"saltLen"
+#define RV_JSON_STR	"randomValue"
 #define E_JSON_STR	"e"
 #define N_JSON_STR	"n"
 
@@ -31,6 +33,10 @@
 #define MSG_JSON_STR	"message"
 #define SIG_JSON_STR	"signature"
 
+
+#define RV_BUF_LEN (1024/8)
+#define RV_BIT_LEN (256)
+
 #ifdef USE_JANSSON
 struct {
 	uint8_t type;
@@ -259,6 +265,13 @@ prepare_vec_rsa(void)
 	if (!BN_mod_inverse(qinv, q, p, ctx))
 		goto err;
 
+	if (info.interim_info.rsa_data.random_msg) {
+		if (!BN_generate_prime_ex(r, RV_BIT_LEN, 0, NULL, NULL, NULL))
+			goto err;
+
+		parse_uint8_hex_str("", BN_bn2hex(r), &vec.rsa.seed);
+	}
+
 	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
 	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
 	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
@@ -297,6 +310,11 @@ parse_test_rsa_json_interim_writeback(struct fips_val *val)
 {
 	RTE_SET_USED(val);
 
+	if (info.interim_info.rsa_data.random_msg) {
+		json_object_set_new(json_info.json_write_group, "conformance",
+							json_string("SP800-106"));
+	}
+
 	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
 		json_t *obj;
 
@@ -367,6 +385,14 @@ parse_test_rsa_json_writeback(struct fips_val *val)
 		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
 		obj = json_string(info.one_line_text);
 		json_object_set_new(json_info.json_write_case, "signature", obj);
+
+		if (info.interim_info.rsa_data.random_msg) {
+			writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+			obj = json_string(info.one_line_text);
+			json_object_set_new(json_info.json_write_case, "randomValue", obj);
+			json_object_set_new(json_info.json_write_case, "randomValueLen",
+				json_integer(vec.rsa.seed.len * 8));
+		}
 	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
 			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
@@ -406,6 +432,8 @@ parse_interim_str(const char *key, char *src, struct fips_val *val)
 		if (i >= RTE_DIM(rsa_auth_algs))
 			return -EINVAL;
 
+	}  else if (strcmp(key, CONFORMANCE_JSON_STR) == 0) {
+		info.interim_info.rsa_data.random_msg = 1;
 	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
 		info.interim_info.rsa_data.saltlen = atoi(src);
 	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
@@ -436,6 +464,83 @@ parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
 	return prepare_vec_rsa();
 }
 
+/*
+ * Message randomization function as per NIST SP 800-106.
+ */
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand)
+{
+	uint8_t m[FIPS_TEST_JSON_BUF_LEN], rv[RV_BUF_LEN];
+	uint32_t m_bitlen, rv_bitlen, count, remain, i, j;
+	uint16_t rv_len;
+
+	if (!msg->val || !rand->val || rand->len > RV_BUF_LEN
+		|| msg->len > FIPS_TEST_JSON_BUF_LEN)
+		return -EINVAL;
+
+	memset(rv, 0, sizeof(rv));
+	memcpy(rv, rand->val, rand->len);
+	rv_bitlen = rand->len * 8;
+	rv_len = rand->len;
+
+	memset(m, 0, sizeof(m));
+	memcpy(m, msg->val, msg->len);
+	m_bitlen = msg->len * 8;
+
+	if (m_bitlen >= (rv_bitlen - 1)) {
+		m[msg->len] = 0x80;
+		m_bitlen += 8;
+	} else {
+		m[msg->len] = 0x80;
+		m_bitlen += (rv_bitlen - m_bitlen - 8);
+	}
+
+	count = m_bitlen / rv_bitlen;
+	remain = m_bitlen % rv_bitlen;
+	for (i = 0; i < count * rv_len; i++)
+		m[i] ^= rv[i % rv_len];
+
+	for (j = 0; j < remain / 8; j++)
+		m[i + j] ^= rv[j];
+
+	m[i + j] = ((uint8_t *)&rv_bitlen)[0];
+	m[i + j + 1] = (((uint8_t *)&rv_bitlen)[1] >> 8) & 0xFF;
+
+	rte_free(msg->val);
+	msg->len = (rv_bitlen + m_bitlen + 16) / 8;
+	msg->val = rte_zmalloc(NULL, msg->len, 0);
+	if (!msg->val)
+		return -EPERM;
+
+	memcpy(msg->val, rv, rv_len);
+	memcpy(&msg->val[rv_len], m, (m_bitlen + 16) / 8);
+	return 0;
+}
+
+static int
+parse_siggen_message_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(val, &vec.rsa.seed);
+
+	return ret;
+}
+
+static int
+parse_sigver_randomvalue_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(&vec.pt, val);
+
+	return ret;
+}
+
 struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
@@ -447,6 +552,7 @@ struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
 		{NULL, NULL, NULL} /**< end pointer */
@@ -456,6 +562,7 @@ struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
 		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
@@ -470,13 +577,14 @@ struct fips_test_callback rsa_keygen_json_vectors[] = {
 };
 
 struct fips_test_callback rsa_siggen_json_vectors[] = {
-		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{MSG_JSON_STR, parse_siggen_message_str, &vec.pt},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
 struct fips_test_callback rsa_sigver_json_vectors[] = {
 		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
 		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{RV_JSON_STR, parse_sigver_randomvalue_str, &vec.rsa.seed},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -492,6 +600,7 @@ parse_test_rsa_json_init(void)
 	info.parse_writeback = NULL;
 	info.interim_callbacks = NULL;
 	info.parse_interim_writeback = NULL;
+	info.interim_info.rsa_data.random_msg = 0;
 
 	if (strcmp(mode_str, "keyGen") == 0) {
 		info.op = FIPS_TEST_ASYM_KEYGEN;
@@ -506,6 +615,7 @@ parse_test_rsa_json_init(void)
 		info.op = FIPS_TEST_ASYM_SIGVER;
 		info.callbacks = rsa_sigver_json_vectors;
 		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
 	} else {
 		return -EINVAL;
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v5 0/3] FIPS asymmetric validation
  2022-10-11 16:08     ` [v4 " Gowrishankar Muthukrishnan
                         ` (2 preceding siblings ...)
  2022-10-11 16:08       ` [v4 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
@ 2022-10-12  3:56       ` Gowrishankar Muthukrishnan
  2022-10-12  3:56         ` [v5 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
                           ` (3 more replies)
  3 siblings, 4 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  3:56 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

This patch series adds support in fips_validation app to perform
asymmetric validation. To start with, RSA algorithm is used in
the evaluation. For the key value pairs which is multiprecision
in arithmetic, openssl library is used.

Changes:
 v5:
  - Release notes.
 v4:
  - AES GMAC callback fixes.
 v3:
  - patches 5,6 and 7 in v2 are rebased and submitted here.
 v2:
  - minor fixes in v1
  - addition of digest encoding for fips validation
  - addition of message randomization for fips conformance tests.

Gowrishankar Muthukrishnan (3):
  examples/fips_validation: add asymmetric validation
  examples/fips_validation: encode digest with hash OID
  examples/fips_validation: randomize message for conformance test

 config/meson.build                            |   6 +
 doc/guides/rel_notes/release_22_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  51 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
 examples/fips_validation/main.c               | 550 ++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 9 files changed, 1161 insertions(+), 98 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v5 1/3] examples/fips_validation: add asymmetric validation
  2022-10-12  3:56       ` [v5 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
@ 2022-10-12  3:56         ` Gowrishankar Muthukrishnan
  2022-10-12  3:56         ` [v5 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
                           ` (2 subsequent siblings)
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  3:56 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add support for asymmetric crypto validation starting with RSA.
For the generation of crypto values which is multiprecision in
math, openssl library is used only for this purpose.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>

--
v5:
 - release notes.
v4:
 - AES GMAC callback fix.
v3:
 - rebased according to cryptodev session rework changes.
v2:
 - improved handling priv key type.
---
 config/meson.build                            |   6 +
 doc/guides/rel_notes/release_22_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  47 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 520 ++++++++++++++++++
 examples/fips_validation/main.c               | 472 +++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 9 files changed, 969 insertions(+), 98 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

diff --git a/config/meson.build b/config/meson.build
index 0fc209db01..e82797d206 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -226,6 +226,12 @@ if jansson_dep.found()
     dpdk_conf.set('RTE_HAS_JANSSON', 1)
 endif
 
+# check for openssl
+openssl_dep = dependency('openssl', required: false, method: 'pkg-config')
+if openssl_dep.found()
+    dpdk_conf.set('RTE_HAS_OPENSSL', 1)
+endif
+
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
 pcap_lib = is_windows ? 'wpcap' : 'pcap'
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index da69689c41..57351085ac 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -241,6 +241,11 @@ New Features
   Added support for lookaside sessions in event mode.
   See the :doc:`../sample_app_ug/ipsec_secgw` for more details.
 
+* **Updated fips_validation sample application.**
+
+  Added support for asymmetric crypto algorithms.
+  See the :doc:`../sample_app_ug/fips_validation` for more details.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index e8929fdad4..2cf92483d7 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -68,6 +68,7 @@ ACVP
     * SHA (1, 256, 384, 512) - AFT, MCT
     * TDES-CBC - AFT, MCT
     * TDES-ECB - AFT, MCT
+    * RSA
 
 
 Application Information
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index dddfd3f9d8..3bb5937805 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -477,6 +477,8 @@ fips_test_parse_one_json_vector_set(void)
 	else if (strstr(algo_str, "TDES-CBC") ||
 		strstr(algo_str, "TDES-ECB"))
 		info.algo = FIPS_TEST_ALGO_TDES;
+	else if (strstr(algo_str, "RSA"))
+		info.algo = FIPS_TEST_ALGO_RSA;
 	else
 		return -EINVAL;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 182cff9a00..7c275403c7 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -44,6 +44,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_SHA,
+		FIPS_TEST_ALGO_RSA,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -57,6 +58,9 @@ enum file_types {
 enum fips_test_op {
 	FIPS_TEST_ENC_AUTH_GEN = 1,
 	FIPS_TEST_DEC_AUTH_VERIF,
+	FIPS_TEST_ASYM_KEYGEN,
+	FIPS_TEST_ASYM_SIGGEN,
+	FIPS_TEST_ASYM_SIGVER
 };
 
 #define MAX_LINE_PER_VECTOR            16
@@ -80,11 +84,22 @@ struct fips_test_vector {
 			struct fips_val aad;
 		} aead;
 	};
+	struct {
+		struct fips_val seed;
+		struct fips_val signature;
+		struct fips_val e;
+		struct fips_val n;
+		struct fips_val d;
+		struct fips_val p;
+		struct fips_val q;
+		struct fips_val dp;
+		struct fips_val dq;
+		struct fips_val qinv;
+	} rsa;
 
 	struct fips_val pt;
 	struct fips_val ct;
 	struct fips_val iv;
-
 	enum rte_crypto_op_status status;
 };
 
@@ -141,6 +156,12 @@ enum fips_sha_test_types {
 	SHA_MCT
 };
 
+enum fips_rsa_test_types {
+	RSA_AFT = 0,
+	RSA_GDT,
+	RSA_KAT
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -167,8 +188,9 @@ struct ccm_interim_data {
 };
 
 struct sha_interim_data {
-	enum fips_sha_test_types test_type;
+	/* keep algo always on top as it is also used in asym digest */
 	enum rte_crypto_auth_algorithm algo;
+	enum fips_sha_test_types test_type;
 };
 
 struct gcm_interim_data {
@@ -185,6 +207,14 @@ struct xts_interim_data {
 	enum xts_tweak_modes tweak_mode;
 };
 
+struct rsa_interim_data {
+	enum rte_crypto_auth_algorithm auth;
+	uint16_t modulo;
+	uint16_t saltlen;
+	enum rte_crypto_rsa_padding_type padding;
+	enum rte_crypto_rsa_priv_key_type privkey;
+};
+
 #ifdef USE_JANSSON
 /*
  * Maximum length of buffer to hold any json string.
@@ -230,6 +260,7 @@ struct fips_test_interim_info {
 		struct sha_interim_data sha_data;
 		struct gcm_interim_data gcm_data;
 		struct xts_interim_data xts_data;
+		struct rsa_interim_data rsa_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -305,6 +336,9 @@ parse_test_sha_json_test_type(void);
 
 int
 parse_test_tdes_json_init(void);
+
+int
+parse_test_rsa_json_init(void);
 #endif /* USE_JANSSON */
 
 int
@@ -366,11 +400,14 @@ update_info_vec(uint32_t count);
 
 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 *);
+typedef int (*fips_prepare_sym_xform_t)(struct rte_crypto_sym_xform *);
+typedef int (*fips_prepare_asym_xform_t)(struct rte_crypto_asym_xform *);
 
 struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
+	fips_prepare_sym_xform_t prepare_sym_xform;
+	fips_prepare_asym_xform_t prepare_asym_xform;
+	fips_prepare_op_t prepare_sym_op;
+	fips_prepare_op_t prepare_asym_op;
 	fips_test_one_case_t test;
 };
 
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index d6dfdd2443..1b141501f0 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -81,12 +81,12 @@ parser_read_gcm_pt_len(const char *key, char *src,
 
 	if (vec.pt.len == 0) {
 		info.interim_info.gcm_data.is_gmac = 1;
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 	} else {
 		info.interim_info.gcm_data.is_gmac = 0;
-		test_ops.prepare_op = prepare_aead_op;
-		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_xform = prepare_gcm_xform;
 	}
 
 	return ret;
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
new file mode 100644
index 0000000000..d3699f54d0
--- /dev/null
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -0,0 +1,520 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell.
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/random.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef USE_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#endif /* USE_OPENSSL */
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define TESTTYPE_JSON_STR	"testType"
+#define SIGTYPE_JSON_STR "sigType"
+#define MOD_JSON_STR	"modulo"
+#define HASH_JSON_STR	"hashAlg"
+#define SALT_JSON_STR	"saltLen"
+#define E_JSON_STR	"e"
+#define N_JSON_STR	"n"
+
+#define SEED_JSON_STR	"seed"
+#define MSG_JSON_STR	"message"
+#define SIG_JSON_STR	"signature"
+
+#ifdef USE_JANSSON
+struct {
+	uint8_t type;
+	const char *desc;
+} rsa_test_types[] = {
+		{RSA_AFT, "AFT"},
+		{RSA_GDT, "GDT"},
+		{RSA_KAT, "KAT"},
+};
+
+struct {
+	enum rte_crypto_auth_algorithm auth;
+	const char *desc;
+} rsa_auth_algs[] = {
+		{RTE_CRYPTO_AUTH_SHA1, "SHA-1"},
+		{RTE_CRYPTO_AUTH_SHA224, "SHA2-224"},
+		{RTE_CRYPTO_AUTH_SHA256, "SHA2-256"},
+		{RTE_CRYPTO_AUTH_SHA384, "SHA2-384"},
+		{RTE_CRYPTO_AUTH_SHA512, "SHA2-512"},
+};
+
+struct {
+	enum rte_crypto_rsa_padding_type padding;
+	const char *desc;
+} rsa_padding_types[] = {
+		{RTE_CRYPTO_RSA_PADDING_NONE, "none"},
+		{RTE_CRYPTO_RSA_PADDING_PKCS1_5, "pkcs1v1.5"},
+		{RTE_CRYPTO_RSA_PADDING_OAEP, "oaep"},
+		{RTE_CRYPTO_RSA_PADDING_PSS, "pss"},
+};
+
+#ifdef USE_OPENSSL
+static int
+prepare_vec_rsa(void)
+{
+	BIGNUM *p = NULL, *q = NULL, *n = NULL, *d = NULL, *e = NULL;
+	BIGNUM *dp = NULL, *dq = NULL, *qinv = NULL;
+	BIGNUM *r0, *r1, *r2, *r3, *r4;
+	BIGNUM *m = NULL, *r = NULL;
+	int bits, ret = -1, i;
+	char modbuf[8], *buf;
+	BN_CTX *ctx = NULL;
+	unsigned long pid;
+
+	/* Seed PRNG */
+	if (vec.rsa.seed.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		RAND_seed((char *)info.one_line_text, strlen(info.one_line_text));
+	} else {
+		pid = getpid();
+		RAND_seed(&pid, sizeof(pid));
+	}
+
+	if (!RAND_status())
+		return -1;
+
+	/* Check if e is known already */
+	if (vec.rsa.e.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		ret = BN_hex2bn(&e, info.one_line_text);
+		if ((uint32_t)ret != strlen(info.one_line_text))
+			goto err;
+	}
+
+	/* BN context initialization */
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto err;
+
+	BN_CTX_start(ctx);
+	r0 = BN_CTX_get(ctx);
+	r1 = BN_CTX_get(ctx);
+	r2 = BN_CTX_get(ctx);
+	r3 = BN_CTX_get(ctx);
+	r4 = BN_CTX_get(ctx);
+	if (!r4)
+		goto err;
+
+	/* Calculate bit length for prime numbers */
+	m = BN_new();
+	if (!m)
+		goto err;
+
+	snprintf(modbuf, sizeof(modbuf), "%d", info.interim_info.rsa_data.modulo);
+	if (!BN_dec2bn(&m, modbuf))
+		goto err;
+
+	r = BN_new();
+	if (!r)
+		goto err;
+
+	if (!BN_rshift1(r, m))
+		goto err;
+
+	buf = BN_bn2dec(r);
+	bits = atoi(buf);
+
+	p = BN_new();
+	if (!p)
+		goto err;
+
+	q = BN_new();
+	if (!q)
+		goto err;
+
+	n = BN_new();
+	if (!n)
+		goto err;
+
+	d = BN_new();
+	if (!d)
+		goto err;
+
+	/* Generate p and q suitably for RSA */
+	for (i = 0; i < 10; i++) {
+		uint8_t j = 0;
+
+		if (!BN_generate_prime_ex(p, bits, 0, NULL, NULL, NULL))
+			goto err;
+
+		do {
+			RAND_add(&j, sizeof(j), 1);
+			if (!BN_generate_prime_ex(q, bits, 0, NULL, NULL, NULL))
+				goto err;
+
+		} while ((BN_cmp(p, q) == 0) && (j++ < 100));
+
+		if (j >= 100) {
+			RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate q", j);
+			goto err;
+		}
+
+		/* pq */
+		if (!BN_mul(n, p, q, ctx))
+			goto err;
+
+		/* p-1 */
+		if (!BN_sub(r1, p, BN_value_one()))
+			goto err;
+
+		/* q-1 */
+		if (!BN_sub(r2, q, BN_value_one()))
+			goto err;
+
+		/* (p-1 * q-1) */
+		if (!BN_mul(r0, r1, r2, ctx))
+			goto err;
+
+		/* gcd(p-1, q-1)*/
+		if (!BN_gcd(r3, r1, r2, ctx))
+			goto err;
+
+		/* lcm(p-1, q-1) */
+		if (!BN_div(r4, r, r0, r3, ctx))
+			goto err;
+
+		/* check if div and rem are non-zero */
+		if (!r4 || !r)
+			goto err;
+
+		/* 0 < e < lcm */
+		if (!e) {
+			int k = 0;
+
+			e = BN_new();
+			do {
+				RAND_add(&k, sizeof(k), 1);
+				if (!BN_rand(e, 32, 1, 1))
+					goto err;
+
+				if (!BN_gcd(r3, e, r4, ctx))
+					goto err;
+
+				if (BN_is_one(r3))
+					break;
+			} while (k++ < 10);
+
+			if (k >= 10) {
+				RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate e",
+					k);
+				goto err;
+			}
+		}
+
+		/* (de) mod lcm == 1 */
+		if (!BN_mod_inverse(d, e, r4, ctx))
+			goto err;
+
+		if (!BN_gcd(r3, r1, e, ctx))
+			goto err;
+
+		if (!BN_gcd(r4, r2, e, ctx))
+			goto err;
+
+		/* check if gcd(p-1, e) and gcd(q-1, e) are 1 */
+		if (BN_is_one(r3) && BN_is_one(r4))
+			break;
+	}
+
+	if (i >= 10) {
+		RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate p and q", i);
+		goto err;
+	}
+
+	/* d mod (p-1) */
+	dp = BN_new();
+	if (!dp)
+		goto err;
+
+	if (!BN_mod(dp, d, r1, ctx))
+		goto err;
+
+	/* d mod (q-1) */
+	dq = BN_new();
+	if (!dq)
+		goto err;
+
+	if (!BN_mod(dq, d, r2, ctx))
+		goto err;
+
+	/* modinv of q and p */
+	qinv = BN_new();
+	if (!qinv)
+		goto err;
+
+	if (!BN_mod_inverse(qinv, q, p, ctx))
+		goto err;
+
+	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
+	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
+	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
+	parse_uint8_hex_str("", BN_bn2hex(n), &vec.rsa.n);
+	parse_uint8_hex_str("", BN_bn2hex(d), &vec.rsa.d);
+	parse_uint8_hex_str("", BN_bn2hex(dp), &vec.rsa.dp);
+	parse_uint8_hex_str("", BN_bn2hex(dq), &vec.rsa.dq);
+	parse_uint8_hex_str("", BN_bn2hex(qinv), &vec.rsa.qinv);
+
+	ret = 0;
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(m);
+	BN_free(r);
+	BN_free(p);
+	BN_free(q);
+	BN_free(n);
+	BN_free(d);
+	BN_free(e);
+	return ret;
+}
+#else
+static int
+prepare_vec_rsa(void)
+{
+	/*
+	 * Generate RSA values.
+	 */
+	return -ENOTSUP;
+}
+#endif /* USE_OPENSSL */
+
+static int
+parse_test_rsa_json_interim_writeback(struct fips_val *val)
+{
+	RTE_SET_USED(val);
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		/* For siggen tests, RSA values can be created soon after
+		 * the test group data are parsed.
+		 */
+		if (vec.rsa.e.val) {
+			rte_free(vec.rsa.e.val);
+			vec.rsa.e.val = NULL;
+		}
+
+		if (prepare_vec_rsa() < 0)
+			return -1;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "e", obj);
+	}
+
+	return 0;
+}
+
+static int
+parse_test_rsa_json_writeback(struct fips_val *val)
+{
+	json_t *tcId;
+
+	RTE_SET_USED(val);
+
+	tcId = json_object_get(json_info.json_test_case, "tcId");
+
+	json_info.json_write_case = json_object();
+	json_object_set(json_info.json_write_case, "tcId", tcId);
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "seed", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "e", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.p);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "p", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.q);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "q", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.d);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "d", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "signature", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
+		else
+			json_object_set_new(json_info.json_write_case, "testPassed", json_false());
+	}
+
+	return 0;
+}
+
+static int
+parse_interim_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t i;
+
+	RTE_SET_USED(val);
+
+	if (strcmp(key, SIGTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_padding_types); i++)
+			if (strstr(src, rsa_padding_types[i].desc)) {
+				info.interim_info.rsa_data.padding = rsa_padding_types[i].padding;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_padding_types))
+			return -EINVAL;
+
+	}  else if (strcmp(key, MOD_JSON_STR) == 0) {
+		info.interim_info.rsa_data.modulo = atoi(src);
+	} else if (strcmp(key, HASH_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_auth_algs); i++)
+			if (strstr(src, rsa_auth_algs[i].desc)) {
+				info.interim_info.rsa_data.auth = rsa_auth_algs[i].auth;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_auth_algs))
+			return -EINVAL;
+
+	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
+		info.interim_info.rsa_data.saltlen = atoi(src);
+	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_test_types); i++)
+			if (strstr(src, rsa_test_types[i].desc)) {
+				info.parse_writeback = parse_test_rsa_json_writeback;
+				break;
+			}
+
+		if (!info.parse_writeback || i >= RTE_DIM(rsa_test_types))
+			return -EINVAL;
+
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
+{
+	parse_uint8_hex_str(key, src, val);
+
+	/* For keygen tests, key "e" can be the end of input data
+	 * to generate RSA values.
+	 */
+	return prepare_vec_rsa();
+}
+
+struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
+		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_keygen_json_vectors[] = {
+		{SEED_JSON_STR, parse_uint8_hex_str, &vec.rsa.seed},
+		{E_JSON_STR, parse_keygen_e_str, &vec.rsa.e},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_rsa_json_init(void)
+{
+	json_t *keyfmt_obj = json_object_get(json_info.json_vector_set, "keyFormat");
+	json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode");
+	const char *keyfmt_str = json_string_value(keyfmt_obj);
+	const char *mode_str = json_string_value(mode_obj);
+
+	info.callbacks = NULL;
+	info.parse_writeback = NULL;
+	info.interim_callbacks = NULL;
+	info.parse_interim_writeback = NULL;
+
+	if (strcmp(mode_str, "keyGen") == 0) {
+		info.op = FIPS_TEST_ASYM_KEYGEN;
+		info.callbacks = rsa_keygen_json_vectors;
+		info.interim_callbacks = rsa_keygen_interim_json_vectors;
+	} else if (strcmp(mode_str, "sigGen") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGGEN;
+		info.callbacks = rsa_siggen_json_vectors;
+		info.interim_callbacks = rsa_siggen_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
+	} else if (strcmp(mode_str, "sigVer") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGVER;
+		info.callbacks = rsa_sigver_json_vectors;
+		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+	} else {
+		return -EINVAL;
+	}
+
+	info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_QT;
+	if (keyfmt_str != NULL && strcmp(keyfmt_str, "standard") == 0)
+		info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_EXP;
+
+	return 0;
+}
+#endif /* USE_JANSSON */
+
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 7b31579d04..538c0c98e2 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -37,6 +37,8 @@ enum {
 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
 #define OPT_USE_JSON                "use-json"
 	OPT_USE_JSON_NUM,
+#define OPT_CRYPTODEV_ASYM          "asymmetric"
+	OPT_CRYPTODEV_ASYM_NUM,
 };
 
 struct fips_test_vector vec;
@@ -51,34 +53,140 @@ struct cryptodev_fips_validate_env {
 	const char *rsp_path;
 	uint32_t is_path_folder;
 	uint8_t dev_id;
+	struct rte_mempool *mpool;
+	struct fips_sym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_sym_session *sess;
+		struct rte_crypto_op *op;
+	} sym;
+	struct fips_asym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_asym_session *sess;
+		struct rte_crypto_op *op;
+	} asym;
+	struct rte_crypto_op *op;
 	uint8_t dev_support_sgl;
 	uint16_t mbuf_data_room;
-	struct rte_mempool *mpool;
-	struct rte_mempool *sess_mpool;
-	struct rte_mempool *op_pool;
 	struct rte_mbuf *mbuf;
 	uint8_t *digest;
 	uint16_t digest_len;
-	struct rte_crypto_op *op;
-	void *sess;
+	bool is_asym_test;
 	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
 static int
-cryptodev_fips_validate_app_int(void)
+cryptodev_fips_validate_app_sym_init(void)
+{
+	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
+							env.dev_id);
+	struct rte_cryptodev_info dev_info;
+	struct fips_sym_env *sym = &env.sym;
+	int ret;
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	ret = -ENOMEM;
+	sym->sess_mpool = rte_cryptodev_sym_session_pool_create(
+			"FIPS_SYM_SESS_MEMPOOL", 16, sess_sz, 0, 0, rte_socket_id());
+	if (!sym->sess_mpool)
+		goto error_exit;
+
+	sym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_SYM_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!sym->op_pool)
+		goto error_exit;
+
+	sym->op = rte_crypto_op_alloc(sym->op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!sym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_sym_uninit(void)
+{
+	struct fips_sym_env *sym = &env.sym;
+
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(sym->op);
+	rte_cryptodev_sym_session_free(env.dev_id, sym->sess);
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_asym_init(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+	int ret;
+
+	ret = -ENOMEM;
+	asym->sess_mpool = rte_cryptodev_asym_session_pool_create(
+			"FIPS_ASYM_SESS_MEMPOOL", 16, 0, 0, rte_socket_id());
+	if (!asym->sess_mpool)
+		goto error_exit;
+
+	asym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_ASYM_POOL",
+			RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!asym->op_pool)
+		goto error_exit;
+
+	asym->op = rte_crypto_op_alloc(asym->op_pool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!asym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_asym_uninit(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+
+	rte_crypto_op_free(asym->op);
+	rte_cryptodev_asym_session_free(env.dev_id, asym->sess);
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_init(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL};
-	struct rte_cryptodev_info dev_info;
-	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
-			env.dev_id);
 	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
 	int ret;
 
 	if (env.self_test) {
 		ret = fips_dev_self_test(env.dev_id, env.broken_test_config);
 		if (ret < 0) {
+			rte_cryptodev_stop(env.dev_id);
 			rte_cryptodev_close(env.dev_id);
 
 			return ret;
@@ -89,45 +197,24 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	rte_cryptodev_info_get(env.dev_id, &dev_info);
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
-		env.dev_support_sgl = 1;
-	else
-		env.dev_support_sgl = 0;
-
+	ret = -ENOMEM;
 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
 			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
 			env.mbuf_data_room, rte_socket_id());
 	if (!env.mpool)
 		return ret;
 
-	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
-			rte_socket_id());
+	ret = cryptodev_fips_validate_app_sym_init();
 	if (ret < 0)
-		return ret;
-
-	ret = -ENOMEM;
-
-	env.sess_mpool = rte_cryptodev_sym_session_pool_create(
-			"FIPS_SESS_MEMPOOL", 16, sess_sz, 0, 0,
-			rte_socket_id());
-	if (!env.sess_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.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	if (!env.op)
-		goto error_exit;
+	if (env.is_asym_test) {
+		ret = cryptodev_fips_validate_app_asym_init();
+		if (ret < 0)
+			goto error_exit;
+	}
 
-	qp_conf.mp_session = env.sess_mpool;
+	qp_conf.mp_session = env.sym.sess_mpool;
 
 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
 			rte_socket_id());
@@ -141,23 +228,21 @@ cryptodev_fips_validate_app_int(void)
 	return 0;
 
 error_exit:
-
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	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_free(env.dev_id, env.sess);
+	cryptodev_fips_validate_app_sym_uninit();
+
+	if (env.is_asym_test)
+		cryptodev_fips_validate_app_asym_uninit();
+
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	rte_mempool_free(env.op_pool);
+	rte_cryptodev_stop(env.dev_id);
+	rte_cryptodev_close(env.dev_id);
 }
 
 static int
@@ -253,6 +338,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+		{OPT_CRYPTODEV_ASYM, no_argument,
+				NULL, OPT_CRYPTODEV_ASYM_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -365,6 +452,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			}
 			break;
 
+		case OPT_CRYPTODEV_ASYM_NUM:
+			env.is_asym_test = true;
+			break;
+
 		default:
 			cryptodev_fips_validate_usage(prgname);
 			return -EINVAL;
@@ -405,7 +496,7 @@ main(int argc, char *argv[])
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
 
-	ret = cryptodev_fips_validate_app_int();
+	ret = cryptodev_fips_validate_app_init();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
 		return -1;
@@ -644,7 +735,7 @@ prepare_cipher_op(void)
 		sym->cipher.data.length = vec.ct.len;
 	}
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	sym->m_src = env.mbuf;
 	sym->cipher.data.offset = 0;
@@ -707,7 +798,7 @@ prepare_auth_op(void)
 		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	return 0;
 }
@@ -763,7 +854,55 @@ prepare_aead_op(void)
 	sym->aead.aad.data = vec.aead.aad.val;
 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
+
+	return 0;
+}
+
+static int
+prepare_rsa_op(void)
+{
+	struct rte_crypto_asym_op *asym;
+	struct fips_val msg;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+
+	asym = env.op->asym;
+	asym->rsa.padding.type = info.interim_info.rsa_data.padding;
+	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
+
+	if (env.digest) {
+		msg.val = env.digest;
+		msg.len = env.digest_len;
+	} else {
+		msg.val = vec.pt.val;
+		msg.len = vec.pt.len;
+	}
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+
+		if (vec.rsa.signature.val)
+			rte_free(vec.rsa.signature.val);
+
+		vec.rsa.signature.val = rte_zmalloc(NULL, vec.rsa.n.len, 0);
+		vec.rsa.signature.len = vec.rsa.n.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = 0;
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = vec.rsa.signature.len;
+	} else {
+		RTE_LOG(ERR, USER1, "Invalid op %d\n", info.op);
+		return -EINVAL;
+	}
+
+	rte_crypto_op_attach_asym_session(env.op, env.asym.sess);
 
 	return 0;
 }
@@ -1154,6 +1293,87 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_rsa_xform(struct rte_crypto_asym_xform *xform)
+{
+	const struct rte_cryptodev_asymmetric_xform_capability *cap;
+	struct rte_cryptodev_asym_capability_idx cap_idx;
+	struct rte_cryptodev_info dev_info;
+
+	xform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	xform->next = NULL;
+
+	cap_idx.type = xform->xform_type;
+	cap = rte_cryptodev_asym_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;
+	}
+
+	switch (info.op) {
+	case FIPS_TEST_ASYM_SIGGEN:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_SIGN)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_SIGN);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_SIGVER:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_VERIFY)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_VERIFY);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_KEYGEN:
+		break;
+	default:
+		break;
+	}
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	xform->rsa.key_type = info.interim_info.rsa_data.privkey;
+	switch (xform->rsa.key_type) {
+	case RTE_RSA_KEY_TYPE_QT:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support QT key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.qt.p.data = vec.rsa.p.val;
+		xform->rsa.qt.p.length = vec.rsa.p.len;
+		xform->rsa.qt.q.data = vec.rsa.q.val;
+		xform->rsa.qt.q.length = vec.rsa.q.len;
+		xform->rsa.qt.dP.data = vec.rsa.dp.val;
+		xform->rsa.qt.dP.length = vec.rsa.dp.len;
+		xform->rsa.qt.dQ.data = vec.rsa.dq.val;
+		xform->rsa.qt.dQ.length = vec.rsa.dq.len;
+		xform->rsa.qt.qInv.data = vec.rsa.qinv.val;
+		xform->rsa.qt.qInv.length = vec.rsa.qinv.len;
+		break;
+	case RTE_RSA_KEY_TYPE_EXP:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support EXP key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.d.data = vec.rsa.d.val;
+		xform->rsa.d.length = vec.rsa.d.len;
+		break;
+	default:
+		break;
+	}
+
+	xform->rsa.e.data = vec.rsa.e.val;
+	xform->rsa.e.length = vec.rsa.e.len;
+	xform->rsa.n.data = vec.rsa.n.val;
+	xform->rsa.n.length = vec.rsa.n.len;
+	return 0;
+}
+
 static int
 get_writeback_data(struct fips_val *val)
 {
@@ -1200,25 +1420,22 @@ get_writeback_data(struct fips_val *val)
 }
 
 static int
-fips_run_test(void)
+fips_run_sym_test(void)
 {
 	struct rte_crypto_sym_xform xform = {0};
 	uint16_t n_deqd;
 	int ret;
 
-	ret = test_ops.prepare_xform(&xform);
+	ret = test_ops.prepare_sym_xform(&xform);
 	if (ret < 0)
 		return ret;
 
-	env.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
-			env.sess_mpool);
-	if (!env.sess) {
-		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
-				ret);
-		goto exit;
-	}
+	env.sym.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
+						env.sym.sess_mpool);
+	if (!env.sym.sess)
+		return -ENOMEM;
 
-	ret = test_ops.prepare_op();
+	ret = test_ops.prepare_sym_op();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
 				ret);
@@ -1234,21 +1451,88 @@ fips_run_test(void)
 	do {
 		struct rte_crypto_op *deqd_op;
 
-		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
-				1);
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1);
 	} while (n_deqd == 0);
 
 	vec.status = env.op->status;
 
 exit:
-	if (env.sess) {
-		rte_cryptodev_sym_session_free(env.dev_id, env.sess);
-		env.sess = NULL;
+	rte_cryptodev_sym_session_free(env.dev_id, env.sym.sess);
+	env.sym.sess = NULL;
+	return ret;
+}
+
+static int
+fips_run_asym_test(void)
+{
+	struct rte_crypto_asym_xform xform = {0};
+	struct rte_crypto_asym_op *asym;
+	struct rte_crypto_op *deqd_op;
+	int ret;
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		RTE_SET_USED(asym);
+		ret = 0;
+		goto exit;
+	}
+
+	asym = env.op->asym;
+	ret = test_ops.prepare_asym_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	ret = rte_cryptodev_asym_session_create(env.dev_id, &xform, env.asym.sess_mpool,
+			(void *)&env.asym.sess);
+	if (ret < 0)
+		return ret;
+
+	ret = test_ops.prepare_asym_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;
 	}
 
+	while (rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1) == 0)
+		rte_pause();
+
+	vec.status = env.op->status;
+
+ exit:
+	if (env.asym.sess)
+		rte_cryptodev_asym_session_free(env.dev_id, env.asym.sess);
+
+	env.asym.sess = NULL;
 	return ret;
 }
 
+static int
+fips_run_test(void)
+{
+	int ret;
+
+	env.op = env.sym.op;
+	if (env.is_asym_test) {
+		vec.cipher_auth.digest.len = parse_test_sha_hash_size(
+						info.interim_info.rsa_data.auth);
+		test_ops.prepare_sym_xform = prepare_sha_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		ret = fips_run_sym_test();
+		if (ret < 0)
+			return ret;
+	} else {
+		return fips_run_sym_test();
+	}
+
+	env.op = env.asym.op;
+	return fips_run_asym_test();
+}
+
 static int
 fips_generic_test(void)
 {
@@ -1271,9 +1555,11 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	ret = get_writeback_data(&val);
-	if (ret < 0)
-		return ret;
+	if (!env.is_asym_test) {
+		ret = get_writeback_data(&val);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1823,65 +2109,70 @@ init_test_ops(void)
 	case FIPS_TEST_ALGO_AES_CBC:
 	case FIPS_TEST_ALGO_AES_CTR:
 	case FIPS_TEST_ALGO_AES:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform  = prepare_aes_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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_GMAC:
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op= prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 		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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
 	case FIPS_TEST_ALGO_AES_XTS:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform = prepare_xts_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_xform = prepare_xts_xform;
+		test_ops.test = fips_generic_test;
+		break;
+	case FIPS_TEST_ALGO_RSA:
+		test_ops.prepare_asym_op = prepare_rsa_op;
+		test_ops.prepare_asym_xform = prepare_rsa_xform;
 		test_ops.test = fips_generic_test;
 		break;
 	default:
 		if (strstr(info.file_name, "TECB") ||
 				strstr(info.file_name, "TCBC")) {
 			info.algo = FIPS_TEST_ALGO_TDES;
-			test_ops.prepare_op = prepare_cipher_op;
-			test_ops.prepare_xform	= prepare_tdes_xform;
+			test_ops.prepare_sym_op = prepare_cipher_op;
+			test_ops.prepare_sym_xform = prepare_tdes_xform;
 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
 				test_ops.test = fips_mct_tdes_test;
 			else
@@ -2049,6 +2340,9 @@ fips_test_one_test_group(void)
 	case FIPS_TEST_ALGO_TDES:
 		ret = parse_test_tdes_json_init();
 		break;
+	case FIPS_TEST_ALGO_RSA:
+		ret = parse_test_rsa_json_init();
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 8bca26a095..d310093189 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -18,6 +18,7 @@ sources = files(
         'fips_validation_ccm.c',
         'fips_validation_sha.c',
         'fips_validation_xts.c',
+        'fips_validation_rsa.c',
         'fips_dev_self_test.c',
         'main.c',
 )
@@ -26,3 +27,8 @@ if dpdk_conf.has('RTE_HAS_JANSSON')
     ext_deps += jansson_dep
     cflags += '-DUSE_JANSSON'
 endif
+
+if dpdk_conf.has('RTE_HAS_OPENSSL')
+    ext_deps += openssl_dep
+    cflags += '-DUSE_OPENSSL'
+endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v5 2/3] examples/fips_validation: encode digest with hash OID
  2022-10-12  3:56       ` [v5 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  2022-10-12  3:56         ` [v5 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
@ 2022-10-12  3:56         ` Gowrishankar Muthukrishnan
  2022-10-12  3:56         ` [v5 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
  2022-10-12  4:05         ` [v6 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  3:56 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS RSA validation requires hash ddigest be encoded with ASN.1
value for digest info.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/main.c | 78 +++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 538c0c98e2..4af8d142e8 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -859,6 +859,63 @@ prepare_aead_op(void)
 	return 0;
 }
 
+static int
+get_hash_oid(enum rte_crypto_auth_algorithm hash, uint8_t *buf)
+{
+	uint8_t id_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x03, 0x05, 0x00, 0x04,
+				  0x40};
+	uint8_t id_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x02, 0x05, 0x00, 0x04,
+				  0x30};
+	uint8_t id_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
+				  0x20};
+	uint8_t id_sha224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+				  0x1c};
+	uint8_t id_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+				0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+				0x00, 0x04, 0x14};
+	uint8_t *id = NULL;
+	int id_len = 0;
+
+	switch (hash) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		id = id_sha1;
+		id_len = sizeof(id_sha1);
+		break;
+	case RTE_CRYPTO_AUTH_SHA224:
+		id = id_sha224;
+		id_len = sizeof(id_sha224);
+		break;
+	case RTE_CRYPTO_AUTH_SHA256:
+		id = id_sha256;
+		id_len = sizeof(id_sha256);
+		break;
+	case RTE_CRYPTO_AUTH_SHA384:
+		id = id_sha384;
+		id_len = sizeof(id_sha384);
+		break;
+	case RTE_CRYPTO_AUTH_SHA512:
+		id = id_sha512;
+		id_len = sizeof(id_sha512);
+		break;
+	default:
+		id_len = -1;
+		break;
+	}
+
+	if (id != NULL)
+		rte_memcpy(buf, id, id_len);
+
+	return id_len;
+}
+
 static int
 prepare_rsa_op(void)
 {
@@ -872,6 +929,27 @@ prepare_rsa_op(void)
 	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
 
 	if (env.digest) {
+		if (asym->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_PKCS1_5) {
+			int b_len = 0;
+			uint8_t b[32];
+
+			b_len = get_hash_oid(asym->rsa.padding.hash, b);
+			if (b_len < 0) {
+				RTE_LOG(ERR, USER1, "Failed to get digest info for hash %d\n",
+					asym->rsa.padding.hash);
+				return -EINVAL;
+			}
+
+			if (b_len) {
+				msg.len = env.digest_len + b_len;
+				msg.val = rte_zmalloc(NULL, msg.len, 0);
+				rte_memcpy(msg.val, b, b_len);
+				rte_memcpy(msg.val + b_len, env.digest, env.digest_len);
+				rte_free(env.digest);
+				env.digest = msg.val;
+				env.digest_len = msg.len;
+			}
+		}
 		msg.val = env.digest;
 		msg.len = env.digest_len;
 	} else {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v5 3/3] examples/fips_validation: randomize message for conformance test
  2022-10-12  3:56       ` [v5 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  2022-10-12  3:56         ` [v5 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
  2022-10-12  3:56         ` [v5 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
@ 2022-10-12  3:56         ` Gowrishankar Muthukrishnan
  2022-10-12  4:05         ` [v6 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  3:56 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS conformance tests require randomizing message based on SP 800-106.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.h    |   4 +
 .../fips_validation/fips_validation_rsa.c     | 112 +++++++++++++++++-
 2 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 7c275403c7..eec9616462 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -213,6 +213,7 @@ struct rsa_interim_data {
 	uint16_t saltlen;
 	enum rte_crypto_rsa_padding_type padding;
 	enum rte_crypto_rsa_priv_key_type privkey;
+	uint8_t random_msg;
 };
 
 #ifdef USE_JANSSON
@@ -339,6 +340,9 @@ parse_test_tdes_json_init(void);
 
 int
 parse_test_rsa_json_init(void);
+
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand);
 #endif /* USE_JANSSON */
 
 int
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
index d3699f54d0..22c0faf3cb 100644
--- a/examples/fips_validation/fips_validation_rsa.c
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -19,11 +19,13 @@
 
 #include "fips_validation.h"
 
+#define CONFORMANCE_JSON_STR	"conformance"
 #define TESTTYPE_JSON_STR	"testType"
 #define SIGTYPE_JSON_STR "sigType"
 #define MOD_JSON_STR	"modulo"
 #define HASH_JSON_STR	"hashAlg"
 #define SALT_JSON_STR	"saltLen"
+#define RV_JSON_STR	"randomValue"
 #define E_JSON_STR	"e"
 #define N_JSON_STR	"n"
 
@@ -31,6 +33,10 @@
 #define MSG_JSON_STR	"message"
 #define SIG_JSON_STR	"signature"
 
+
+#define RV_BUF_LEN (1024/8)
+#define RV_BIT_LEN (256)
+
 #ifdef USE_JANSSON
 struct {
 	uint8_t type;
@@ -259,6 +265,13 @@ prepare_vec_rsa(void)
 	if (!BN_mod_inverse(qinv, q, p, ctx))
 		goto err;
 
+	if (info.interim_info.rsa_data.random_msg) {
+		if (!BN_generate_prime_ex(r, RV_BIT_LEN, 0, NULL, NULL, NULL))
+			goto err;
+
+		parse_uint8_hex_str("", BN_bn2hex(r), &vec.rsa.seed);
+	}
+
 	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
 	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
 	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
@@ -297,6 +310,11 @@ parse_test_rsa_json_interim_writeback(struct fips_val *val)
 {
 	RTE_SET_USED(val);
 
+	if (info.interim_info.rsa_data.random_msg) {
+		json_object_set_new(json_info.json_write_group, "conformance",
+							json_string("SP800-106"));
+	}
+
 	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
 		json_t *obj;
 
@@ -367,6 +385,14 @@ parse_test_rsa_json_writeback(struct fips_val *val)
 		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
 		obj = json_string(info.one_line_text);
 		json_object_set_new(json_info.json_write_case, "signature", obj);
+
+		if (info.interim_info.rsa_data.random_msg) {
+			writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+			obj = json_string(info.one_line_text);
+			json_object_set_new(json_info.json_write_case, "randomValue", obj);
+			json_object_set_new(json_info.json_write_case, "randomValueLen",
+				json_integer(vec.rsa.seed.len * 8));
+		}
 	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
 			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
@@ -406,6 +432,8 @@ parse_interim_str(const char *key, char *src, struct fips_val *val)
 		if (i >= RTE_DIM(rsa_auth_algs))
 			return -EINVAL;
 
+	}  else if (strcmp(key, CONFORMANCE_JSON_STR) == 0) {
+		info.interim_info.rsa_data.random_msg = 1;
 	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
 		info.interim_info.rsa_data.saltlen = atoi(src);
 	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
@@ -436,6 +464,83 @@ parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
 	return prepare_vec_rsa();
 }
 
+/*
+ * Message randomization function as per NIST SP 800-106.
+ */
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand)
+{
+	uint8_t m[FIPS_TEST_JSON_BUF_LEN], rv[RV_BUF_LEN];
+	uint32_t m_bitlen, rv_bitlen, count, remain, i, j;
+	uint16_t rv_len;
+
+	if (!msg->val || !rand->val || rand->len > RV_BUF_LEN
+		|| msg->len > FIPS_TEST_JSON_BUF_LEN)
+		return -EINVAL;
+
+	memset(rv, 0, sizeof(rv));
+	memcpy(rv, rand->val, rand->len);
+	rv_bitlen = rand->len * 8;
+	rv_len = rand->len;
+
+	memset(m, 0, sizeof(m));
+	memcpy(m, msg->val, msg->len);
+	m_bitlen = msg->len * 8;
+
+	if (m_bitlen >= (rv_bitlen - 1)) {
+		m[msg->len] = 0x80;
+		m_bitlen += 8;
+	} else {
+		m[msg->len] = 0x80;
+		m_bitlen += (rv_bitlen - m_bitlen - 8);
+	}
+
+	count = m_bitlen / rv_bitlen;
+	remain = m_bitlen % rv_bitlen;
+	for (i = 0; i < count * rv_len; i++)
+		m[i] ^= rv[i % rv_len];
+
+	for (j = 0; j < remain / 8; j++)
+		m[i + j] ^= rv[j];
+
+	m[i + j] = ((uint8_t *)&rv_bitlen)[0];
+	m[i + j + 1] = (((uint8_t *)&rv_bitlen)[1] >> 8) & 0xFF;
+
+	rte_free(msg->val);
+	msg->len = (rv_bitlen + m_bitlen + 16) / 8;
+	msg->val = rte_zmalloc(NULL, msg->len, 0);
+	if (!msg->val)
+		return -EPERM;
+
+	memcpy(msg->val, rv, rv_len);
+	memcpy(&msg->val[rv_len], m, (m_bitlen + 16) / 8);
+	return 0;
+}
+
+static int
+parse_siggen_message_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(val, &vec.rsa.seed);
+
+	return ret;
+}
+
+static int
+parse_sigver_randomvalue_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(&vec.pt, val);
+
+	return ret;
+}
+
 struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
@@ -447,6 +552,7 @@ struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
 		{NULL, NULL, NULL} /**< end pointer */
@@ -456,6 +562,7 @@ struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
 		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
@@ -470,13 +577,14 @@ struct fips_test_callback rsa_keygen_json_vectors[] = {
 };
 
 struct fips_test_callback rsa_siggen_json_vectors[] = {
-		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{MSG_JSON_STR, parse_siggen_message_str, &vec.pt},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
 struct fips_test_callback rsa_sigver_json_vectors[] = {
 		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
 		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{RV_JSON_STR, parse_sigver_randomvalue_str, &vec.rsa.seed},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -492,6 +600,7 @@ parse_test_rsa_json_init(void)
 	info.parse_writeback = NULL;
 	info.interim_callbacks = NULL;
 	info.parse_interim_writeback = NULL;
+	info.interim_info.rsa_data.random_msg = 0;
 
 	if (strcmp(mode_str, "keyGen") == 0) {
 		info.op = FIPS_TEST_ASYM_KEYGEN;
@@ -506,6 +615,7 @@ parse_test_rsa_json_init(void)
 		info.op = FIPS_TEST_ASYM_SIGVER;
 		info.callbacks = rsa_sigver_json_vectors;
 		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
 	} else {
 		return -EINVAL;
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v6 0/3] FIPS asymmetric validation
  2022-10-12  3:56       ` [v5 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
                           ` (2 preceding siblings ...)
  2022-10-12  3:56         ` [v5 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
@ 2022-10-12  4:05         ` Gowrishankar Muthukrishnan
  2022-10-12  4:05           ` [v6 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
                             ` (3 more replies)
  3 siblings, 4 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  4:05 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

This patch series adds support in fips_validation app to perform
asymmetric validation. To start with, RSA algorithm is used in
the evaluation. For the key value pairs which is multiprecision
in arithmetic, openssl library is used.

Changes:
 v6:
  - checkpatch related fix.
 v5:
  - Release notes.
 v4:
  - AES GMAC callback fixes.
 v3:
  - patches 5,6 and 7 in v2 are rebased and submitted here.
 v2:
  - minor fixes in v1
  - addition of digest encoding for fips validation
  - addition of message randomization for fips conformance tests.

Gowrishankar Muthukrishnan (3):
  examples/fips_validation: add asymmetric validation
  examples/fips_validation: encode digest with hash OID
  examples/fips_validation: randomize message for conformance test

 config/meson.build                            |   6 +
 doc/guides/rel_notes/release_22_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  51 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
 examples/fips_validation/main.c               | 550 ++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 9 files changed, 1161 insertions(+), 98 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v6 1/3] examples/fips_validation: add asymmetric validation
  2022-10-12  4:05         ` [v6 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
@ 2022-10-12  4:05           ` Gowrishankar Muthukrishnan
  2022-10-12  4:05           ` [v6 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
                             ` (2 subsequent siblings)
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  4:05 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add support for asymmetric crypto validation starting with RSA.
For the generation of crypto values which is multiprecision in
math, openssl library is used only for this purpose.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>

--
v6:
 - checpatch related fix.
v5:
 - release notes.
v4:
 - AES GMAC callback fix.
v3:
 - rebased according to cryptodev session rework changes.
v2:
 - improved handling priv key type.
---
 config/meson.build                            |   6 +
 doc/guides/rel_notes/release_22_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  47 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 520 ++++++++++++++++++
 examples/fips_validation/main.c               | 472 +++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 9 files changed, 969 insertions(+), 98 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

diff --git a/config/meson.build b/config/meson.build
index 0fc209db01..e82797d206 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -226,6 +226,12 @@ if jansson_dep.found()
     dpdk_conf.set('RTE_HAS_JANSSON', 1)
 endif
 
+# check for openssl
+openssl_dep = dependency('openssl', required: false, method: 'pkg-config')
+if openssl_dep.found()
+    dpdk_conf.set('RTE_HAS_OPENSSL', 1)
+endif
+
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
 pcap_lib = is_windows ? 'wpcap' : 'pcap'
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index da69689c41..57351085ac 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -241,6 +241,11 @@ New Features
   Added support for lookaside sessions in event mode.
   See the :doc:`../sample_app_ug/ipsec_secgw` for more details.
 
+* **Updated fips_validation sample application.**
+
+  Added support for asymmetric crypto algorithms.
+  See the :doc:`../sample_app_ug/fips_validation` for more details.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index e8929fdad4..2cf92483d7 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -68,6 +68,7 @@ ACVP
     * SHA (1, 256, 384, 512) - AFT, MCT
     * TDES-CBC - AFT, MCT
     * TDES-ECB - AFT, MCT
+    * RSA
 
 
 Application Information
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index dddfd3f9d8..3bb5937805 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -477,6 +477,8 @@ fips_test_parse_one_json_vector_set(void)
 	else if (strstr(algo_str, "TDES-CBC") ||
 		strstr(algo_str, "TDES-ECB"))
 		info.algo = FIPS_TEST_ALGO_TDES;
+	else if (strstr(algo_str, "RSA"))
+		info.algo = FIPS_TEST_ALGO_RSA;
 	else
 		return -EINVAL;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 182cff9a00..7c275403c7 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -44,6 +44,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_SHA,
+		FIPS_TEST_ALGO_RSA,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -57,6 +58,9 @@ enum file_types {
 enum fips_test_op {
 	FIPS_TEST_ENC_AUTH_GEN = 1,
 	FIPS_TEST_DEC_AUTH_VERIF,
+	FIPS_TEST_ASYM_KEYGEN,
+	FIPS_TEST_ASYM_SIGGEN,
+	FIPS_TEST_ASYM_SIGVER
 };
 
 #define MAX_LINE_PER_VECTOR            16
@@ -80,11 +84,22 @@ struct fips_test_vector {
 			struct fips_val aad;
 		} aead;
 	};
+	struct {
+		struct fips_val seed;
+		struct fips_val signature;
+		struct fips_val e;
+		struct fips_val n;
+		struct fips_val d;
+		struct fips_val p;
+		struct fips_val q;
+		struct fips_val dp;
+		struct fips_val dq;
+		struct fips_val qinv;
+	} rsa;
 
 	struct fips_val pt;
 	struct fips_val ct;
 	struct fips_val iv;
-
 	enum rte_crypto_op_status status;
 };
 
@@ -141,6 +156,12 @@ enum fips_sha_test_types {
 	SHA_MCT
 };
 
+enum fips_rsa_test_types {
+	RSA_AFT = 0,
+	RSA_GDT,
+	RSA_KAT
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -167,8 +188,9 @@ struct ccm_interim_data {
 };
 
 struct sha_interim_data {
-	enum fips_sha_test_types test_type;
+	/* keep algo always on top as it is also used in asym digest */
 	enum rte_crypto_auth_algorithm algo;
+	enum fips_sha_test_types test_type;
 };
 
 struct gcm_interim_data {
@@ -185,6 +207,14 @@ struct xts_interim_data {
 	enum xts_tweak_modes tweak_mode;
 };
 
+struct rsa_interim_data {
+	enum rte_crypto_auth_algorithm auth;
+	uint16_t modulo;
+	uint16_t saltlen;
+	enum rte_crypto_rsa_padding_type padding;
+	enum rte_crypto_rsa_priv_key_type privkey;
+};
+
 #ifdef USE_JANSSON
 /*
  * Maximum length of buffer to hold any json string.
@@ -230,6 +260,7 @@ struct fips_test_interim_info {
 		struct sha_interim_data sha_data;
 		struct gcm_interim_data gcm_data;
 		struct xts_interim_data xts_data;
+		struct rsa_interim_data rsa_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -305,6 +336,9 @@ parse_test_sha_json_test_type(void);
 
 int
 parse_test_tdes_json_init(void);
+
+int
+parse_test_rsa_json_init(void);
 #endif /* USE_JANSSON */
 
 int
@@ -366,11 +400,14 @@ update_info_vec(uint32_t count);
 
 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 *);
+typedef int (*fips_prepare_sym_xform_t)(struct rte_crypto_sym_xform *);
+typedef int (*fips_prepare_asym_xform_t)(struct rte_crypto_asym_xform *);
 
 struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
+	fips_prepare_sym_xform_t prepare_sym_xform;
+	fips_prepare_asym_xform_t prepare_asym_xform;
+	fips_prepare_op_t prepare_sym_op;
+	fips_prepare_op_t prepare_asym_op;
 	fips_test_one_case_t test;
 };
 
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index d6dfdd2443..1b141501f0 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -81,12 +81,12 @@ parser_read_gcm_pt_len(const char *key, char *src,
 
 	if (vec.pt.len == 0) {
 		info.interim_info.gcm_data.is_gmac = 1;
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 	} else {
 		info.interim_info.gcm_data.is_gmac = 0;
-		test_ops.prepare_op = prepare_aead_op;
-		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_xform = prepare_gcm_xform;
 	}
 
 	return ret;
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
new file mode 100644
index 0000000000..d3699f54d0
--- /dev/null
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -0,0 +1,520 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell.
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/random.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef USE_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#endif /* USE_OPENSSL */
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define TESTTYPE_JSON_STR	"testType"
+#define SIGTYPE_JSON_STR "sigType"
+#define MOD_JSON_STR	"modulo"
+#define HASH_JSON_STR	"hashAlg"
+#define SALT_JSON_STR	"saltLen"
+#define E_JSON_STR	"e"
+#define N_JSON_STR	"n"
+
+#define SEED_JSON_STR	"seed"
+#define MSG_JSON_STR	"message"
+#define SIG_JSON_STR	"signature"
+
+#ifdef USE_JANSSON
+struct {
+	uint8_t type;
+	const char *desc;
+} rsa_test_types[] = {
+		{RSA_AFT, "AFT"},
+		{RSA_GDT, "GDT"},
+		{RSA_KAT, "KAT"},
+};
+
+struct {
+	enum rte_crypto_auth_algorithm auth;
+	const char *desc;
+} rsa_auth_algs[] = {
+		{RTE_CRYPTO_AUTH_SHA1, "SHA-1"},
+		{RTE_CRYPTO_AUTH_SHA224, "SHA2-224"},
+		{RTE_CRYPTO_AUTH_SHA256, "SHA2-256"},
+		{RTE_CRYPTO_AUTH_SHA384, "SHA2-384"},
+		{RTE_CRYPTO_AUTH_SHA512, "SHA2-512"},
+};
+
+struct {
+	enum rte_crypto_rsa_padding_type padding;
+	const char *desc;
+} rsa_padding_types[] = {
+		{RTE_CRYPTO_RSA_PADDING_NONE, "none"},
+		{RTE_CRYPTO_RSA_PADDING_PKCS1_5, "pkcs1v1.5"},
+		{RTE_CRYPTO_RSA_PADDING_OAEP, "oaep"},
+		{RTE_CRYPTO_RSA_PADDING_PSS, "pss"},
+};
+
+#ifdef USE_OPENSSL
+static int
+prepare_vec_rsa(void)
+{
+	BIGNUM *p = NULL, *q = NULL, *n = NULL, *d = NULL, *e = NULL;
+	BIGNUM *dp = NULL, *dq = NULL, *qinv = NULL;
+	BIGNUM *r0, *r1, *r2, *r3, *r4;
+	BIGNUM *m = NULL, *r = NULL;
+	int bits, ret = -1, i;
+	char modbuf[8], *buf;
+	BN_CTX *ctx = NULL;
+	unsigned long pid;
+
+	/* Seed PRNG */
+	if (vec.rsa.seed.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		RAND_seed((char *)info.one_line_text, strlen(info.one_line_text));
+	} else {
+		pid = getpid();
+		RAND_seed(&pid, sizeof(pid));
+	}
+
+	if (!RAND_status())
+		return -1;
+
+	/* Check if e is known already */
+	if (vec.rsa.e.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		ret = BN_hex2bn(&e, info.one_line_text);
+		if ((uint32_t)ret != strlen(info.one_line_text))
+			goto err;
+	}
+
+	/* BN context initialization */
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto err;
+
+	BN_CTX_start(ctx);
+	r0 = BN_CTX_get(ctx);
+	r1 = BN_CTX_get(ctx);
+	r2 = BN_CTX_get(ctx);
+	r3 = BN_CTX_get(ctx);
+	r4 = BN_CTX_get(ctx);
+	if (!r4)
+		goto err;
+
+	/* Calculate bit length for prime numbers */
+	m = BN_new();
+	if (!m)
+		goto err;
+
+	snprintf(modbuf, sizeof(modbuf), "%d", info.interim_info.rsa_data.modulo);
+	if (!BN_dec2bn(&m, modbuf))
+		goto err;
+
+	r = BN_new();
+	if (!r)
+		goto err;
+
+	if (!BN_rshift1(r, m))
+		goto err;
+
+	buf = BN_bn2dec(r);
+	bits = atoi(buf);
+
+	p = BN_new();
+	if (!p)
+		goto err;
+
+	q = BN_new();
+	if (!q)
+		goto err;
+
+	n = BN_new();
+	if (!n)
+		goto err;
+
+	d = BN_new();
+	if (!d)
+		goto err;
+
+	/* Generate p and q suitably for RSA */
+	for (i = 0; i < 10; i++) {
+		uint8_t j = 0;
+
+		if (!BN_generate_prime_ex(p, bits, 0, NULL, NULL, NULL))
+			goto err;
+
+		do {
+			RAND_add(&j, sizeof(j), 1);
+			if (!BN_generate_prime_ex(q, bits, 0, NULL, NULL, NULL))
+				goto err;
+
+		} while ((BN_cmp(p, q) == 0) && (j++ < 100));
+
+		if (j >= 100) {
+			RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate q", j);
+			goto err;
+		}
+
+		/* pq */
+		if (!BN_mul(n, p, q, ctx))
+			goto err;
+
+		/* p-1 */
+		if (!BN_sub(r1, p, BN_value_one()))
+			goto err;
+
+		/* q-1 */
+		if (!BN_sub(r2, q, BN_value_one()))
+			goto err;
+
+		/* (p-1 * q-1) */
+		if (!BN_mul(r0, r1, r2, ctx))
+			goto err;
+
+		/* gcd(p-1, q-1)*/
+		if (!BN_gcd(r3, r1, r2, ctx))
+			goto err;
+
+		/* lcm(p-1, q-1) */
+		if (!BN_div(r4, r, r0, r3, ctx))
+			goto err;
+
+		/* check if div and rem are non-zero */
+		if (!r4 || !r)
+			goto err;
+
+		/* 0 < e < lcm */
+		if (!e) {
+			int k = 0;
+
+			e = BN_new();
+			do {
+				RAND_add(&k, sizeof(k), 1);
+				if (!BN_rand(e, 32, 1, 1))
+					goto err;
+
+				if (!BN_gcd(r3, e, r4, ctx))
+					goto err;
+
+				if (BN_is_one(r3))
+					break;
+			} while (k++ < 10);
+
+			if (k >= 10) {
+				RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate e",
+					k);
+				goto err;
+			}
+		}
+
+		/* (de) mod lcm == 1 */
+		if (!BN_mod_inverse(d, e, r4, ctx))
+			goto err;
+
+		if (!BN_gcd(r3, r1, e, ctx))
+			goto err;
+
+		if (!BN_gcd(r4, r2, e, ctx))
+			goto err;
+
+		/* check if gcd(p-1, e) and gcd(q-1, e) are 1 */
+		if (BN_is_one(r3) && BN_is_one(r4))
+			break;
+	}
+
+	if (i >= 10) {
+		RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate p and q", i);
+		goto err;
+	}
+
+	/* d mod (p-1) */
+	dp = BN_new();
+	if (!dp)
+		goto err;
+
+	if (!BN_mod(dp, d, r1, ctx))
+		goto err;
+
+	/* d mod (q-1) */
+	dq = BN_new();
+	if (!dq)
+		goto err;
+
+	if (!BN_mod(dq, d, r2, ctx))
+		goto err;
+
+	/* modinv of q and p */
+	qinv = BN_new();
+	if (!qinv)
+		goto err;
+
+	if (!BN_mod_inverse(qinv, q, p, ctx))
+		goto err;
+
+	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
+	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
+	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
+	parse_uint8_hex_str("", BN_bn2hex(n), &vec.rsa.n);
+	parse_uint8_hex_str("", BN_bn2hex(d), &vec.rsa.d);
+	parse_uint8_hex_str("", BN_bn2hex(dp), &vec.rsa.dp);
+	parse_uint8_hex_str("", BN_bn2hex(dq), &vec.rsa.dq);
+	parse_uint8_hex_str("", BN_bn2hex(qinv), &vec.rsa.qinv);
+
+	ret = 0;
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(m);
+	BN_free(r);
+	BN_free(p);
+	BN_free(q);
+	BN_free(n);
+	BN_free(d);
+	BN_free(e);
+	return ret;
+}
+#else
+static int
+prepare_vec_rsa(void)
+{
+	/*
+	 * Generate RSA values.
+	 */
+	return -ENOTSUP;
+}
+#endif /* USE_OPENSSL */
+
+static int
+parse_test_rsa_json_interim_writeback(struct fips_val *val)
+{
+	RTE_SET_USED(val);
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		/* For siggen tests, RSA values can be created soon after
+		 * the test group data are parsed.
+		 */
+		if (vec.rsa.e.val) {
+			rte_free(vec.rsa.e.val);
+			vec.rsa.e.val = NULL;
+		}
+
+		if (prepare_vec_rsa() < 0)
+			return -1;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "e", obj);
+	}
+
+	return 0;
+}
+
+static int
+parse_test_rsa_json_writeback(struct fips_val *val)
+{
+	json_t *tcId;
+
+	RTE_SET_USED(val);
+
+	tcId = json_object_get(json_info.json_test_case, "tcId");
+
+	json_info.json_write_case = json_object();
+	json_object_set(json_info.json_write_case, "tcId", tcId);
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "seed", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "e", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.p);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "p", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.q);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "q", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.d);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "d", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "signature", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
+		else
+			json_object_set_new(json_info.json_write_case, "testPassed", json_false());
+	}
+
+	return 0;
+}
+
+static int
+parse_interim_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t i;
+
+	RTE_SET_USED(val);
+
+	if (strcmp(key, SIGTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_padding_types); i++)
+			if (strstr(src, rsa_padding_types[i].desc)) {
+				info.interim_info.rsa_data.padding = rsa_padding_types[i].padding;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_padding_types))
+			return -EINVAL;
+
+	}  else if (strcmp(key, MOD_JSON_STR) == 0) {
+		info.interim_info.rsa_data.modulo = atoi(src);
+	} else if (strcmp(key, HASH_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_auth_algs); i++)
+			if (strstr(src, rsa_auth_algs[i].desc)) {
+				info.interim_info.rsa_data.auth = rsa_auth_algs[i].auth;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_auth_algs))
+			return -EINVAL;
+
+	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
+		info.interim_info.rsa_data.saltlen = atoi(src);
+	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_test_types); i++)
+			if (strstr(src, rsa_test_types[i].desc)) {
+				info.parse_writeback = parse_test_rsa_json_writeback;
+				break;
+			}
+
+		if (!info.parse_writeback || i >= RTE_DIM(rsa_test_types))
+			return -EINVAL;
+
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
+{
+	parse_uint8_hex_str(key, src, val);
+
+	/* For keygen tests, key "e" can be the end of input data
+	 * to generate RSA values.
+	 */
+	return prepare_vec_rsa();
+}
+
+struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
+		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_keygen_json_vectors[] = {
+		{SEED_JSON_STR, parse_uint8_hex_str, &vec.rsa.seed},
+		{E_JSON_STR, parse_keygen_e_str, &vec.rsa.e},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_rsa_json_init(void)
+{
+	json_t *keyfmt_obj = json_object_get(json_info.json_vector_set, "keyFormat");
+	json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode");
+	const char *keyfmt_str = json_string_value(keyfmt_obj);
+	const char *mode_str = json_string_value(mode_obj);
+
+	info.callbacks = NULL;
+	info.parse_writeback = NULL;
+	info.interim_callbacks = NULL;
+	info.parse_interim_writeback = NULL;
+
+	if (strcmp(mode_str, "keyGen") == 0) {
+		info.op = FIPS_TEST_ASYM_KEYGEN;
+		info.callbacks = rsa_keygen_json_vectors;
+		info.interim_callbacks = rsa_keygen_interim_json_vectors;
+	} else if (strcmp(mode_str, "sigGen") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGGEN;
+		info.callbacks = rsa_siggen_json_vectors;
+		info.interim_callbacks = rsa_siggen_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
+	} else if (strcmp(mode_str, "sigVer") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGVER;
+		info.callbacks = rsa_sigver_json_vectors;
+		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+	} else {
+		return -EINVAL;
+	}
+
+	info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_QT;
+	if (keyfmt_str != NULL && strcmp(keyfmt_str, "standard") == 0)
+		info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_EXP;
+
+	return 0;
+}
+#endif /* USE_JANSSON */
+
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 7b31579d04..23f020fd71 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -37,6 +37,8 @@ enum {
 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
 #define OPT_USE_JSON                "use-json"
 	OPT_USE_JSON_NUM,
+#define OPT_CRYPTODEV_ASYM          "asymmetric"
+	OPT_CRYPTODEV_ASYM_NUM,
 };
 
 struct fips_test_vector vec;
@@ -51,34 +53,140 @@ struct cryptodev_fips_validate_env {
 	const char *rsp_path;
 	uint32_t is_path_folder;
 	uint8_t dev_id;
+	struct rte_mempool *mpool;
+	struct fips_sym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_sym_session *sess;
+		struct rte_crypto_op *op;
+	} sym;
+	struct fips_asym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_asym_session *sess;
+		struct rte_crypto_op *op;
+	} asym;
+	struct rte_crypto_op *op;
 	uint8_t dev_support_sgl;
 	uint16_t mbuf_data_room;
-	struct rte_mempool *mpool;
-	struct rte_mempool *sess_mpool;
-	struct rte_mempool *op_pool;
 	struct rte_mbuf *mbuf;
 	uint8_t *digest;
 	uint16_t digest_len;
-	struct rte_crypto_op *op;
-	void *sess;
+	bool is_asym_test;
 	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
 static int
-cryptodev_fips_validate_app_int(void)
+cryptodev_fips_validate_app_sym_init(void)
+{
+	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
+							env.dev_id);
+	struct rte_cryptodev_info dev_info;
+	struct fips_sym_env *sym = &env.sym;
+	int ret;
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	ret = -ENOMEM;
+	sym->sess_mpool = rte_cryptodev_sym_session_pool_create(
+			"FIPS_SYM_SESS_MEMPOOL", 16, sess_sz, 0, 0, rte_socket_id());
+	if (!sym->sess_mpool)
+		goto error_exit;
+
+	sym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_SYM_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!sym->op_pool)
+		goto error_exit;
+
+	sym->op = rte_crypto_op_alloc(sym->op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!sym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_sym_uninit(void)
+{
+	struct fips_sym_env *sym = &env.sym;
+
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(sym->op);
+	rte_cryptodev_sym_session_free(env.dev_id, sym->sess);
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_asym_init(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+	int ret;
+
+	ret = -ENOMEM;
+	asym->sess_mpool = rte_cryptodev_asym_session_pool_create(
+			"FIPS_ASYM_SESS_MEMPOOL", 16, 0, 0, rte_socket_id());
+	if (!asym->sess_mpool)
+		goto error_exit;
+
+	asym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_ASYM_POOL",
+			RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!asym->op_pool)
+		goto error_exit;
+
+	asym->op = rte_crypto_op_alloc(asym->op_pool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!asym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_asym_uninit(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+
+	rte_crypto_op_free(asym->op);
+	rte_cryptodev_asym_session_free(env.dev_id, asym->sess);
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_init(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL};
-	struct rte_cryptodev_info dev_info;
-	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
-			env.dev_id);
 	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
 	int ret;
 
 	if (env.self_test) {
 		ret = fips_dev_self_test(env.dev_id, env.broken_test_config);
 		if (ret < 0) {
+			rte_cryptodev_stop(env.dev_id);
 			rte_cryptodev_close(env.dev_id);
 
 			return ret;
@@ -89,45 +197,24 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	rte_cryptodev_info_get(env.dev_id, &dev_info);
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
-		env.dev_support_sgl = 1;
-	else
-		env.dev_support_sgl = 0;
-
+	ret = -ENOMEM;
 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
 			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
 			env.mbuf_data_room, rte_socket_id());
 	if (!env.mpool)
 		return ret;
 
-	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
-			rte_socket_id());
+	ret = cryptodev_fips_validate_app_sym_init();
 	if (ret < 0)
-		return ret;
-
-	ret = -ENOMEM;
-
-	env.sess_mpool = rte_cryptodev_sym_session_pool_create(
-			"FIPS_SESS_MEMPOOL", 16, sess_sz, 0, 0,
-			rte_socket_id());
-	if (!env.sess_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.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	if (!env.op)
-		goto error_exit;
+	if (env.is_asym_test) {
+		ret = cryptodev_fips_validate_app_asym_init();
+		if (ret < 0)
+			goto error_exit;
+	}
 
-	qp_conf.mp_session = env.sess_mpool;
+	qp_conf.mp_session = env.sym.sess_mpool;
 
 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
 			rte_socket_id());
@@ -141,23 +228,21 @@ cryptodev_fips_validate_app_int(void)
 	return 0;
 
 error_exit:
-
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	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_free(env.dev_id, env.sess);
+	cryptodev_fips_validate_app_sym_uninit();
+
+	if (env.is_asym_test)
+		cryptodev_fips_validate_app_asym_uninit();
+
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	rte_mempool_free(env.op_pool);
+	rte_cryptodev_stop(env.dev_id);
+	rte_cryptodev_close(env.dev_id);
 }
 
 static int
@@ -253,6 +338,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+		{OPT_CRYPTODEV_ASYM, no_argument,
+				NULL, OPT_CRYPTODEV_ASYM_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -365,6 +452,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			}
 			break;
 
+		case OPT_CRYPTODEV_ASYM_NUM:
+			env.is_asym_test = true;
+			break;
+
 		default:
 			cryptodev_fips_validate_usage(prgname);
 			return -EINVAL;
@@ -405,7 +496,7 @@ main(int argc, char *argv[])
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
 
-	ret = cryptodev_fips_validate_app_int();
+	ret = cryptodev_fips_validate_app_init();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
 		return -1;
@@ -644,7 +735,7 @@ prepare_cipher_op(void)
 		sym->cipher.data.length = vec.ct.len;
 	}
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	sym->m_src = env.mbuf;
 	sym->cipher.data.offset = 0;
@@ -707,7 +798,7 @@ prepare_auth_op(void)
 		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	return 0;
 }
@@ -763,7 +854,55 @@ prepare_aead_op(void)
 	sym->aead.aad.data = vec.aead.aad.val;
 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
+
+	return 0;
+}
+
+static int
+prepare_rsa_op(void)
+{
+	struct rte_crypto_asym_op *asym;
+	struct fips_val msg;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+
+	asym = env.op->asym;
+	asym->rsa.padding.type = info.interim_info.rsa_data.padding;
+	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
+
+	if (env.digest) {
+		msg.val = env.digest;
+		msg.len = env.digest_len;
+	} else {
+		msg.val = vec.pt.val;
+		msg.len = vec.pt.len;
+	}
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+
+		if (vec.rsa.signature.val)
+			rte_free(vec.rsa.signature.val);
+
+		vec.rsa.signature.val = rte_zmalloc(NULL, vec.rsa.n.len, 0);
+		vec.rsa.signature.len = vec.rsa.n.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = 0;
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = vec.rsa.signature.len;
+	} else {
+		RTE_LOG(ERR, USER1, "Invalid op %d\n", info.op);
+		return -EINVAL;
+	}
+
+	rte_crypto_op_attach_asym_session(env.op, env.asym.sess);
 
 	return 0;
 }
@@ -1154,6 +1293,87 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_rsa_xform(struct rte_crypto_asym_xform *xform)
+{
+	const struct rte_cryptodev_asymmetric_xform_capability *cap;
+	struct rte_cryptodev_asym_capability_idx cap_idx;
+	struct rte_cryptodev_info dev_info;
+
+	xform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	xform->next = NULL;
+
+	cap_idx.type = xform->xform_type;
+	cap = rte_cryptodev_asym_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;
+	}
+
+	switch (info.op) {
+	case FIPS_TEST_ASYM_SIGGEN:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_SIGN)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_SIGN);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_SIGVER:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_VERIFY)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_VERIFY);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_KEYGEN:
+		break;
+	default:
+		break;
+	}
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	xform->rsa.key_type = info.interim_info.rsa_data.privkey;
+	switch (xform->rsa.key_type) {
+	case RTE_RSA_KEY_TYPE_QT:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support QT key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.qt.p.data = vec.rsa.p.val;
+		xform->rsa.qt.p.length = vec.rsa.p.len;
+		xform->rsa.qt.q.data = vec.rsa.q.val;
+		xform->rsa.qt.q.length = vec.rsa.q.len;
+		xform->rsa.qt.dP.data = vec.rsa.dp.val;
+		xform->rsa.qt.dP.length = vec.rsa.dp.len;
+		xform->rsa.qt.dQ.data = vec.rsa.dq.val;
+		xform->rsa.qt.dQ.length = vec.rsa.dq.len;
+		xform->rsa.qt.qInv.data = vec.rsa.qinv.val;
+		xform->rsa.qt.qInv.length = vec.rsa.qinv.len;
+		break;
+	case RTE_RSA_KEY_TYPE_EXP:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support EXP key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.d.data = vec.rsa.d.val;
+		xform->rsa.d.length = vec.rsa.d.len;
+		break;
+	default:
+		break;
+	}
+
+	xform->rsa.e.data = vec.rsa.e.val;
+	xform->rsa.e.length = vec.rsa.e.len;
+	xform->rsa.n.data = vec.rsa.n.val;
+	xform->rsa.n.length = vec.rsa.n.len;
+	return 0;
+}
+
 static int
 get_writeback_data(struct fips_val *val)
 {
@@ -1200,25 +1420,22 @@ get_writeback_data(struct fips_val *val)
 }
 
 static int
-fips_run_test(void)
+fips_run_sym_test(void)
 {
 	struct rte_crypto_sym_xform xform = {0};
 	uint16_t n_deqd;
 	int ret;
 
-	ret = test_ops.prepare_xform(&xform);
+	ret = test_ops.prepare_sym_xform(&xform);
 	if (ret < 0)
 		return ret;
 
-	env.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
-			env.sess_mpool);
-	if (!env.sess) {
-		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
-				ret);
-		goto exit;
-	}
+	env.sym.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
+						env.sym.sess_mpool);
+	if (!env.sym.sess)
+		return -ENOMEM;
 
-	ret = test_ops.prepare_op();
+	ret = test_ops.prepare_sym_op();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
 				ret);
@@ -1234,21 +1451,88 @@ fips_run_test(void)
 	do {
 		struct rte_crypto_op *deqd_op;
 
-		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
-				1);
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1);
 	} while (n_deqd == 0);
 
 	vec.status = env.op->status;
 
 exit:
-	if (env.sess) {
-		rte_cryptodev_sym_session_free(env.dev_id, env.sess);
-		env.sess = NULL;
+	rte_cryptodev_sym_session_free(env.dev_id, env.sym.sess);
+	env.sym.sess = NULL;
+	return ret;
+}
+
+static int
+fips_run_asym_test(void)
+{
+	struct rte_crypto_asym_xform xform = {0};
+	struct rte_crypto_asym_op *asym;
+	struct rte_crypto_op *deqd_op;
+	int ret;
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		RTE_SET_USED(asym);
+		ret = 0;
+		goto exit;
+	}
+
+	asym = env.op->asym;
+	ret = test_ops.prepare_asym_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	ret = rte_cryptodev_asym_session_create(env.dev_id, &xform, env.asym.sess_mpool,
+			(void *)&env.asym.sess);
+	if (ret < 0)
+		return ret;
+
+	ret = test_ops.prepare_asym_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;
 	}
 
+	while (rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1) == 0)
+		rte_pause();
+
+	vec.status = env.op->status;
+
+ exit:
+	if (env.asym.sess)
+		rte_cryptodev_asym_session_free(env.dev_id, env.asym.sess);
+
+	env.asym.sess = NULL;
 	return ret;
 }
 
+static int
+fips_run_test(void)
+{
+	int ret;
+
+	env.op = env.sym.op;
+	if (env.is_asym_test) {
+		vec.cipher_auth.digest.len = parse_test_sha_hash_size(
+						info.interim_info.rsa_data.auth);
+		test_ops.prepare_sym_xform = prepare_sha_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		ret = fips_run_sym_test();
+		if (ret < 0)
+			return ret;
+	} else {
+		return fips_run_sym_test();
+	}
+
+	env.op = env.asym.op;
+	return fips_run_asym_test();
+}
+
 static int
 fips_generic_test(void)
 {
@@ -1271,9 +1555,11 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	ret = get_writeback_data(&val);
-	if (ret < 0)
-		return ret;
+	if (!env.is_asym_test) {
+		ret = get_writeback_data(&val);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1823,65 +2109,70 @@ init_test_ops(void)
 	case FIPS_TEST_ALGO_AES_CBC:
 	case FIPS_TEST_ALGO_AES_CTR:
 	case FIPS_TEST_ALGO_AES:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform  = prepare_aes_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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_GMAC:
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 		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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
 	case FIPS_TEST_ALGO_AES_XTS:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform = prepare_xts_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_xform = prepare_xts_xform;
+		test_ops.test = fips_generic_test;
+		break;
+	case FIPS_TEST_ALGO_RSA:
+		test_ops.prepare_asym_op = prepare_rsa_op;
+		test_ops.prepare_asym_xform = prepare_rsa_xform;
 		test_ops.test = fips_generic_test;
 		break;
 	default:
 		if (strstr(info.file_name, "TECB") ||
 				strstr(info.file_name, "TCBC")) {
 			info.algo = FIPS_TEST_ALGO_TDES;
-			test_ops.prepare_op = prepare_cipher_op;
-			test_ops.prepare_xform	= prepare_tdes_xform;
+			test_ops.prepare_sym_op = prepare_cipher_op;
+			test_ops.prepare_sym_xform = prepare_tdes_xform;
 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
 				test_ops.test = fips_mct_tdes_test;
 			else
@@ -2049,6 +2340,9 @@ fips_test_one_test_group(void)
 	case FIPS_TEST_ALGO_TDES:
 		ret = parse_test_tdes_json_init();
 		break;
+	case FIPS_TEST_ALGO_RSA:
+		ret = parse_test_rsa_json_init();
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 8bca26a095..d310093189 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -18,6 +18,7 @@ sources = files(
         'fips_validation_ccm.c',
         'fips_validation_sha.c',
         'fips_validation_xts.c',
+        'fips_validation_rsa.c',
         'fips_dev_self_test.c',
         'main.c',
 )
@@ -26,3 +27,8 @@ if dpdk_conf.has('RTE_HAS_JANSSON')
     ext_deps += jansson_dep
     cflags += '-DUSE_JANSSON'
 endif
+
+if dpdk_conf.has('RTE_HAS_OPENSSL')
+    ext_deps += openssl_dep
+    cflags += '-DUSE_OPENSSL'
+endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v6 2/3] examples/fips_validation: encode digest with hash OID
  2022-10-12  4:05         ` [v6 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  2022-10-12  4:05           ` [v6 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
@ 2022-10-12  4:05           ` Gowrishankar Muthukrishnan
  2022-10-12  4:05           ` [v6 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
  2022-10-12  6:12           ` [v7 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  4:05 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS RSA validation requires hash ddigest be encoded with ASN.1
value for digest info.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/main.c | 78 +++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 23f020fd71..dc191bdb1b 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -859,6 +859,63 @@ prepare_aead_op(void)
 	return 0;
 }
 
+static int
+get_hash_oid(enum rte_crypto_auth_algorithm hash, uint8_t *buf)
+{
+	uint8_t id_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x03, 0x05, 0x00, 0x04,
+				  0x40};
+	uint8_t id_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x02, 0x05, 0x00, 0x04,
+				  0x30};
+	uint8_t id_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
+				  0x20};
+	uint8_t id_sha224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+				  0x1c};
+	uint8_t id_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+				0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+				0x00, 0x04, 0x14};
+	uint8_t *id = NULL;
+	int id_len = 0;
+
+	switch (hash) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		id = id_sha1;
+		id_len = sizeof(id_sha1);
+		break;
+	case RTE_CRYPTO_AUTH_SHA224:
+		id = id_sha224;
+		id_len = sizeof(id_sha224);
+		break;
+	case RTE_CRYPTO_AUTH_SHA256:
+		id = id_sha256;
+		id_len = sizeof(id_sha256);
+		break;
+	case RTE_CRYPTO_AUTH_SHA384:
+		id = id_sha384;
+		id_len = sizeof(id_sha384);
+		break;
+	case RTE_CRYPTO_AUTH_SHA512:
+		id = id_sha512;
+		id_len = sizeof(id_sha512);
+		break;
+	default:
+		id_len = -1;
+		break;
+	}
+
+	if (id != NULL)
+		rte_memcpy(buf, id, id_len);
+
+	return id_len;
+}
+
 static int
 prepare_rsa_op(void)
 {
@@ -872,6 +929,27 @@ prepare_rsa_op(void)
 	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
 
 	if (env.digest) {
+		if (asym->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_PKCS1_5) {
+			int b_len = 0;
+			uint8_t b[32];
+
+			b_len = get_hash_oid(asym->rsa.padding.hash, b);
+			if (b_len < 0) {
+				RTE_LOG(ERR, USER1, "Failed to get digest info for hash %d\n",
+					asym->rsa.padding.hash);
+				return -EINVAL;
+			}
+
+			if (b_len) {
+				msg.len = env.digest_len + b_len;
+				msg.val = rte_zmalloc(NULL, msg.len, 0);
+				rte_memcpy(msg.val, b, b_len);
+				rte_memcpy(msg.val + b_len, env.digest, env.digest_len);
+				rte_free(env.digest);
+				env.digest = msg.val;
+				env.digest_len = msg.len;
+			}
+		}
 		msg.val = env.digest;
 		msg.len = env.digest_len;
 	} else {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v6 3/3] examples/fips_validation: randomize message for conformance test
  2022-10-12  4:05         ` [v6 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  2022-10-12  4:05           ` [v6 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
  2022-10-12  4:05           ` [v6 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
@ 2022-10-12  4:05           ` Gowrishankar Muthukrishnan
  2022-10-12  6:12           ` [v7 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  4:05 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS conformance tests require randomizing message based on SP 800-106.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.h    |   4 +
 .../fips_validation/fips_validation_rsa.c     | 112 +++++++++++++++++-
 2 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 7c275403c7..eec9616462 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -213,6 +213,7 @@ struct rsa_interim_data {
 	uint16_t saltlen;
 	enum rte_crypto_rsa_padding_type padding;
 	enum rte_crypto_rsa_priv_key_type privkey;
+	uint8_t random_msg;
 };
 
 #ifdef USE_JANSSON
@@ -339,6 +340,9 @@ parse_test_tdes_json_init(void);
 
 int
 parse_test_rsa_json_init(void);
+
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand);
 #endif /* USE_JANSSON */
 
 int
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
index d3699f54d0..22c0faf3cb 100644
--- a/examples/fips_validation/fips_validation_rsa.c
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -19,11 +19,13 @@
 
 #include "fips_validation.h"
 
+#define CONFORMANCE_JSON_STR	"conformance"
 #define TESTTYPE_JSON_STR	"testType"
 #define SIGTYPE_JSON_STR "sigType"
 #define MOD_JSON_STR	"modulo"
 #define HASH_JSON_STR	"hashAlg"
 #define SALT_JSON_STR	"saltLen"
+#define RV_JSON_STR	"randomValue"
 #define E_JSON_STR	"e"
 #define N_JSON_STR	"n"
 
@@ -31,6 +33,10 @@
 #define MSG_JSON_STR	"message"
 #define SIG_JSON_STR	"signature"
 
+
+#define RV_BUF_LEN (1024/8)
+#define RV_BIT_LEN (256)
+
 #ifdef USE_JANSSON
 struct {
 	uint8_t type;
@@ -259,6 +265,13 @@ prepare_vec_rsa(void)
 	if (!BN_mod_inverse(qinv, q, p, ctx))
 		goto err;
 
+	if (info.interim_info.rsa_data.random_msg) {
+		if (!BN_generate_prime_ex(r, RV_BIT_LEN, 0, NULL, NULL, NULL))
+			goto err;
+
+		parse_uint8_hex_str("", BN_bn2hex(r), &vec.rsa.seed);
+	}
+
 	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
 	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
 	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
@@ -297,6 +310,11 @@ parse_test_rsa_json_interim_writeback(struct fips_val *val)
 {
 	RTE_SET_USED(val);
 
+	if (info.interim_info.rsa_data.random_msg) {
+		json_object_set_new(json_info.json_write_group, "conformance",
+							json_string("SP800-106"));
+	}
+
 	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
 		json_t *obj;
 
@@ -367,6 +385,14 @@ parse_test_rsa_json_writeback(struct fips_val *val)
 		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
 		obj = json_string(info.one_line_text);
 		json_object_set_new(json_info.json_write_case, "signature", obj);
+
+		if (info.interim_info.rsa_data.random_msg) {
+			writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+			obj = json_string(info.one_line_text);
+			json_object_set_new(json_info.json_write_case, "randomValue", obj);
+			json_object_set_new(json_info.json_write_case, "randomValueLen",
+				json_integer(vec.rsa.seed.len * 8));
+		}
 	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
 			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
@@ -406,6 +432,8 @@ parse_interim_str(const char *key, char *src, struct fips_val *val)
 		if (i >= RTE_DIM(rsa_auth_algs))
 			return -EINVAL;
 
+	}  else if (strcmp(key, CONFORMANCE_JSON_STR) == 0) {
+		info.interim_info.rsa_data.random_msg = 1;
 	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
 		info.interim_info.rsa_data.saltlen = atoi(src);
 	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
@@ -436,6 +464,83 @@ parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
 	return prepare_vec_rsa();
 }
 
+/*
+ * Message randomization function as per NIST SP 800-106.
+ */
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand)
+{
+	uint8_t m[FIPS_TEST_JSON_BUF_LEN], rv[RV_BUF_LEN];
+	uint32_t m_bitlen, rv_bitlen, count, remain, i, j;
+	uint16_t rv_len;
+
+	if (!msg->val || !rand->val || rand->len > RV_BUF_LEN
+		|| msg->len > FIPS_TEST_JSON_BUF_LEN)
+		return -EINVAL;
+
+	memset(rv, 0, sizeof(rv));
+	memcpy(rv, rand->val, rand->len);
+	rv_bitlen = rand->len * 8;
+	rv_len = rand->len;
+
+	memset(m, 0, sizeof(m));
+	memcpy(m, msg->val, msg->len);
+	m_bitlen = msg->len * 8;
+
+	if (m_bitlen >= (rv_bitlen - 1)) {
+		m[msg->len] = 0x80;
+		m_bitlen += 8;
+	} else {
+		m[msg->len] = 0x80;
+		m_bitlen += (rv_bitlen - m_bitlen - 8);
+	}
+
+	count = m_bitlen / rv_bitlen;
+	remain = m_bitlen % rv_bitlen;
+	for (i = 0; i < count * rv_len; i++)
+		m[i] ^= rv[i % rv_len];
+
+	for (j = 0; j < remain / 8; j++)
+		m[i + j] ^= rv[j];
+
+	m[i + j] = ((uint8_t *)&rv_bitlen)[0];
+	m[i + j + 1] = (((uint8_t *)&rv_bitlen)[1] >> 8) & 0xFF;
+
+	rte_free(msg->val);
+	msg->len = (rv_bitlen + m_bitlen + 16) / 8;
+	msg->val = rte_zmalloc(NULL, msg->len, 0);
+	if (!msg->val)
+		return -EPERM;
+
+	memcpy(msg->val, rv, rv_len);
+	memcpy(&msg->val[rv_len], m, (m_bitlen + 16) / 8);
+	return 0;
+}
+
+static int
+parse_siggen_message_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(val, &vec.rsa.seed);
+
+	return ret;
+}
+
+static int
+parse_sigver_randomvalue_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(&vec.pt, val);
+
+	return ret;
+}
+
 struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
@@ -447,6 +552,7 @@ struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
 		{NULL, NULL, NULL} /**< end pointer */
@@ -456,6 +562,7 @@ struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
 		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
@@ -470,13 +577,14 @@ struct fips_test_callback rsa_keygen_json_vectors[] = {
 };
 
 struct fips_test_callback rsa_siggen_json_vectors[] = {
-		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{MSG_JSON_STR, parse_siggen_message_str, &vec.pt},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
 struct fips_test_callback rsa_sigver_json_vectors[] = {
 		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
 		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{RV_JSON_STR, parse_sigver_randomvalue_str, &vec.rsa.seed},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -492,6 +600,7 @@ parse_test_rsa_json_init(void)
 	info.parse_writeback = NULL;
 	info.interim_callbacks = NULL;
 	info.parse_interim_writeback = NULL;
+	info.interim_info.rsa_data.random_msg = 0;
 
 	if (strcmp(mode_str, "keyGen") == 0) {
 		info.op = FIPS_TEST_ASYM_KEYGEN;
@@ -506,6 +615,7 @@ parse_test_rsa_json_init(void)
 		info.op = FIPS_TEST_ASYM_SIGVER;
 		info.callbacks = rsa_sigver_json_vectors;
 		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
 	} else {
 		return -EINVAL;
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v7 0/3] FIPS asymmetric validation
  2022-10-12  4:05         ` [v6 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
                             ` (2 preceding siblings ...)
  2022-10-12  4:05           ` [v6 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
@ 2022-10-12  6:12           ` Gowrishankar Muthukrishnan
  2022-10-12  6:12             ` [v7 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
                               ` (3 more replies)
  3 siblings, 4 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  6:12 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

This patch series adds support in fips_validation app to perform
asymmetric validation. To start with, RSA algorithm is used in
the evaluation. For the key value pairs which is multiprecision
in arithmetic, openssl library is used.

Changes:
 v7:
  - fix test to handle app parameter correctly.
 v6:
  - checkpatch related fix.
 v5:
  - Release notes.
 v4:
  - AES GMAC callback fixes.
 v3:
  - patches 5,6 and 7 in v2 are rebased and submitted here.
 v2:
  - minor fixes in v1
  - addition of digest encoding for fips validation
  - addition of message randomization for fips conformance tests.

Gowrishankar Muthukrishnan (3):
  examples/fips_validation: add asymmetric validation
  examples/fips_validation: encode digest with hash OID
  examples/fips_validation: randomize message for conformance test

 config/meson.build                            |   6 +
 doc/guides/rel_notes/release_22_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  51 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
 examples/fips_validation/main.c               | 556 +++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 9 files changed, 1167 insertions(+), 98 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v7 1/3] examples/fips_validation: add asymmetric validation
  2022-10-12  6:12           ` [v7 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
@ 2022-10-12  6:12             ` Gowrishankar Muthukrishnan
  2022-10-12  6:12             ` [v7 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
                               ` (2 subsequent siblings)
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  6:12 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

Add support for asymmetric crypto validation starting with RSA.
For the generation of crypto values which is multiprecision in
math, openssl library is used only for this purpose.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
Acked-by: Brian Dooley <brian.dooley@intel.com>

--
v7:
 - fix test to return error if not relevant.
v6:
 - checpatch related fix.
v5:
 - release notes.
v4:
 - AES GMAC callback fix.
v3:
 - rebased according to cryptodev session rework changes.
v2:
 - improved handling priv key type.

ch
---
 config/meson.build                            |   6 +
 doc/guides/rel_notes/release_22_11.rst        |   5 +
 doc/guides/sample_app_ug/fips_validation.rst  |   1 +
 examples/fips_validation/fips_validation.c    |   2 +
 examples/fips_validation/fips_validation.h    |  47 +-
 .../fips_validation/fips_validation_gcm.c     |   8 +-
 .../fips_validation/fips_validation_rsa.c     | 520 ++++++++++++++++++
 examples/fips_validation/main.c               | 478 +++++++++++++---
 examples/fips_validation/meson.build          |   6 +
 9 files changed, 975 insertions(+), 98 deletions(-)
 create mode 100644 examples/fips_validation/fips_validation_rsa.c

diff --git a/config/meson.build b/config/meson.build
index 0fc209db01..e82797d206 100644
--- a/config/meson.build
+++ b/config/meson.build
@@ -226,6 +226,12 @@ if jansson_dep.found()
     dpdk_conf.set('RTE_HAS_JANSSON', 1)
 endif
 
+# check for openssl
+openssl_dep = dependency('openssl', required: false, method: 'pkg-config')
+if openssl_dep.found()
+    dpdk_conf.set('RTE_HAS_OPENSSL', 1)
+endif
+
 # check for pcap
 pcap_dep = dependency('libpcap', required: false, method: 'pkg-config')
 pcap_lib = is_windows ? 'wpcap' : 'pcap'
diff --git a/doc/guides/rel_notes/release_22_11.rst b/doc/guides/rel_notes/release_22_11.rst
index da69689c41..57351085ac 100644
--- a/doc/guides/rel_notes/release_22_11.rst
+++ b/doc/guides/rel_notes/release_22_11.rst
@@ -241,6 +241,11 @@ New Features
   Added support for lookaside sessions in event mode.
   See the :doc:`../sample_app_ug/ipsec_secgw` for more details.
 
+* **Updated fips_validation sample application.**
+
+  Added support for asymmetric crypto algorithms.
+  See the :doc:`../sample_app_ug/fips_validation` for more details.
+
 
 Removed Items
 -------------
diff --git a/doc/guides/sample_app_ug/fips_validation.rst b/doc/guides/sample_app_ug/fips_validation.rst
index e8929fdad4..2cf92483d7 100644
--- a/doc/guides/sample_app_ug/fips_validation.rst
+++ b/doc/guides/sample_app_ug/fips_validation.rst
@@ -68,6 +68,7 @@ ACVP
     * SHA (1, 256, 384, 512) - AFT, MCT
     * TDES-CBC - AFT, MCT
     * TDES-ECB - AFT, MCT
+    * RSA
 
 
 Application Information
diff --git a/examples/fips_validation/fips_validation.c b/examples/fips_validation/fips_validation.c
index dddfd3f9d8..3bb5937805 100644
--- a/examples/fips_validation/fips_validation.c
+++ b/examples/fips_validation/fips_validation.c
@@ -477,6 +477,8 @@ fips_test_parse_one_json_vector_set(void)
 	else if (strstr(algo_str, "TDES-CBC") ||
 		strstr(algo_str, "TDES-ECB"))
 		info.algo = FIPS_TEST_ALGO_TDES;
+	else if (strstr(algo_str, "RSA"))
+		info.algo = FIPS_TEST_ALGO_RSA;
 	else
 		return -EINVAL;
 
diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 182cff9a00..7c275403c7 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -44,6 +44,7 @@ enum fips_test_algorithms {
 		FIPS_TEST_ALGO_HMAC,
 		FIPS_TEST_ALGO_TDES,
 		FIPS_TEST_ALGO_SHA,
+		FIPS_TEST_ALGO_RSA,
 		FIPS_TEST_ALGO_MAX
 };
 
@@ -57,6 +58,9 @@ enum file_types {
 enum fips_test_op {
 	FIPS_TEST_ENC_AUTH_GEN = 1,
 	FIPS_TEST_DEC_AUTH_VERIF,
+	FIPS_TEST_ASYM_KEYGEN,
+	FIPS_TEST_ASYM_SIGGEN,
+	FIPS_TEST_ASYM_SIGVER
 };
 
 #define MAX_LINE_PER_VECTOR            16
@@ -80,11 +84,22 @@ struct fips_test_vector {
 			struct fips_val aad;
 		} aead;
 	};
+	struct {
+		struct fips_val seed;
+		struct fips_val signature;
+		struct fips_val e;
+		struct fips_val n;
+		struct fips_val d;
+		struct fips_val p;
+		struct fips_val q;
+		struct fips_val dp;
+		struct fips_val dq;
+		struct fips_val qinv;
+	} rsa;
 
 	struct fips_val pt;
 	struct fips_val ct;
 	struct fips_val iv;
-
 	enum rte_crypto_op_status status;
 };
 
@@ -141,6 +156,12 @@ enum fips_sha_test_types {
 	SHA_MCT
 };
 
+enum fips_rsa_test_types {
+	RSA_AFT = 0,
+	RSA_GDT,
+	RSA_KAT
+};
+
 struct aesavs_interim_data {
 	enum fips_aesavs_test_types test_type;
 	uint32_t cipher_algo;
@@ -167,8 +188,9 @@ struct ccm_interim_data {
 };
 
 struct sha_interim_data {
-	enum fips_sha_test_types test_type;
+	/* keep algo always on top as it is also used in asym digest */
 	enum rte_crypto_auth_algorithm algo;
+	enum fips_sha_test_types test_type;
 };
 
 struct gcm_interim_data {
@@ -185,6 +207,14 @@ struct xts_interim_data {
 	enum xts_tweak_modes tweak_mode;
 };
 
+struct rsa_interim_data {
+	enum rte_crypto_auth_algorithm auth;
+	uint16_t modulo;
+	uint16_t saltlen;
+	enum rte_crypto_rsa_padding_type padding;
+	enum rte_crypto_rsa_priv_key_type privkey;
+};
+
 #ifdef USE_JANSSON
 /*
  * Maximum length of buffer to hold any json string.
@@ -230,6 +260,7 @@ struct fips_test_interim_info {
 		struct sha_interim_data sha_data;
 		struct gcm_interim_data gcm_data;
 		struct xts_interim_data xts_data;
+		struct rsa_interim_data rsa_data;
 	} interim_info;
 
 	enum fips_test_op op;
@@ -305,6 +336,9 @@ parse_test_sha_json_test_type(void);
 
 int
 parse_test_tdes_json_init(void);
+
+int
+parse_test_rsa_json_init(void);
 #endif /* USE_JANSSON */
 
 int
@@ -366,11 +400,14 @@ update_info_vec(uint32_t count);
 
 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 *);
+typedef int (*fips_prepare_sym_xform_t)(struct rte_crypto_sym_xform *);
+typedef int (*fips_prepare_asym_xform_t)(struct rte_crypto_asym_xform *);
 
 struct fips_test_ops {
-	fips_prepare_xform_t prepare_xform;
-	fips_prepare_op_t prepare_op;
+	fips_prepare_sym_xform_t prepare_sym_xform;
+	fips_prepare_asym_xform_t prepare_asym_xform;
+	fips_prepare_op_t prepare_sym_op;
+	fips_prepare_op_t prepare_asym_op;
 	fips_test_one_case_t test;
 };
 
diff --git a/examples/fips_validation/fips_validation_gcm.c b/examples/fips_validation/fips_validation_gcm.c
index d6dfdd2443..1b141501f0 100644
--- a/examples/fips_validation/fips_validation_gcm.c
+++ b/examples/fips_validation/fips_validation_gcm.c
@@ -81,12 +81,12 @@ parser_read_gcm_pt_len(const char *key, char *src,
 
 	if (vec.pt.len == 0) {
 		info.interim_info.gcm_data.is_gmac = 1;
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 	} else {
 		info.interim_info.gcm_data.is_gmac = 0;
-		test_ops.prepare_op = prepare_aead_op;
-		test_ops.prepare_xform = prepare_gcm_xform;
+		test_ops.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_xform = prepare_gcm_xform;
 	}
 
 	return ret;
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
new file mode 100644
index 0000000000..d3699f54d0
--- /dev/null
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -0,0 +1,520 @@
+/* SPDX-License-Identifier: BSD-3-Clause
+ * Copyright(C) 2022 Marvell.
+ */
+
+#include <string.h>
+#include <time.h>
+#include <stdio.h>
+#include <sys/random.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#ifdef USE_OPENSSL
+#include <openssl/bn.h>
+#include <openssl/rand.h>
+#endif /* USE_OPENSSL */
+
+#include <rte_cryptodev.h>
+#include <rte_malloc.h>
+
+#include "fips_validation.h"
+
+#define TESTTYPE_JSON_STR	"testType"
+#define SIGTYPE_JSON_STR "sigType"
+#define MOD_JSON_STR	"modulo"
+#define HASH_JSON_STR	"hashAlg"
+#define SALT_JSON_STR	"saltLen"
+#define E_JSON_STR	"e"
+#define N_JSON_STR	"n"
+
+#define SEED_JSON_STR	"seed"
+#define MSG_JSON_STR	"message"
+#define SIG_JSON_STR	"signature"
+
+#ifdef USE_JANSSON
+struct {
+	uint8_t type;
+	const char *desc;
+} rsa_test_types[] = {
+		{RSA_AFT, "AFT"},
+		{RSA_GDT, "GDT"},
+		{RSA_KAT, "KAT"},
+};
+
+struct {
+	enum rte_crypto_auth_algorithm auth;
+	const char *desc;
+} rsa_auth_algs[] = {
+		{RTE_CRYPTO_AUTH_SHA1, "SHA-1"},
+		{RTE_CRYPTO_AUTH_SHA224, "SHA2-224"},
+		{RTE_CRYPTO_AUTH_SHA256, "SHA2-256"},
+		{RTE_CRYPTO_AUTH_SHA384, "SHA2-384"},
+		{RTE_CRYPTO_AUTH_SHA512, "SHA2-512"},
+};
+
+struct {
+	enum rte_crypto_rsa_padding_type padding;
+	const char *desc;
+} rsa_padding_types[] = {
+		{RTE_CRYPTO_RSA_PADDING_NONE, "none"},
+		{RTE_CRYPTO_RSA_PADDING_PKCS1_5, "pkcs1v1.5"},
+		{RTE_CRYPTO_RSA_PADDING_OAEP, "oaep"},
+		{RTE_CRYPTO_RSA_PADDING_PSS, "pss"},
+};
+
+#ifdef USE_OPENSSL
+static int
+prepare_vec_rsa(void)
+{
+	BIGNUM *p = NULL, *q = NULL, *n = NULL, *d = NULL, *e = NULL;
+	BIGNUM *dp = NULL, *dq = NULL, *qinv = NULL;
+	BIGNUM *r0, *r1, *r2, *r3, *r4;
+	BIGNUM *m = NULL, *r = NULL;
+	int bits, ret = -1, i;
+	char modbuf[8], *buf;
+	BN_CTX *ctx = NULL;
+	unsigned long pid;
+
+	/* Seed PRNG */
+	if (vec.rsa.seed.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		RAND_seed((char *)info.one_line_text, strlen(info.one_line_text));
+	} else {
+		pid = getpid();
+		RAND_seed(&pid, sizeof(pid));
+	}
+
+	if (!RAND_status())
+		return -1;
+
+	/* Check if e is known already */
+	if (vec.rsa.e.val) {
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		ret = BN_hex2bn(&e, info.one_line_text);
+		if ((uint32_t)ret != strlen(info.one_line_text))
+			goto err;
+	}
+
+	/* BN context initialization */
+	ctx = BN_CTX_new();
+	if (!ctx)
+		goto err;
+
+	BN_CTX_start(ctx);
+	r0 = BN_CTX_get(ctx);
+	r1 = BN_CTX_get(ctx);
+	r2 = BN_CTX_get(ctx);
+	r3 = BN_CTX_get(ctx);
+	r4 = BN_CTX_get(ctx);
+	if (!r4)
+		goto err;
+
+	/* Calculate bit length for prime numbers */
+	m = BN_new();
+	if (!m)
+		goto err;
+
+	snprintf(modbuf, sizeof(modbuf), "%d", info.interim_info.rsa_data.modulo);
+	if (!BN_dec2bn(&m, modbuf))
+		goto err;
+
+	r = BN_new();
+	if (!r)
+		goto err;
+
+	if (!BN_rshift1(r, m))
+		goto err;
+
+	buf = BN_bn2dec(r);
+	bits = atoi(buf);
+
+	p = BN_new();
+	if (!p)
+		goto err;
+
+	q = BN_new();
+	if (!q)
+		goto err;
+
+	n = BN_new();
+	if (!n)
+		goto err;
+
+	d = BN_new();
+	if (!d)
+		goto err;
+
+	/* Generate p and q suitably for RSA */
+	for (i = 0; i < 10; i++) {
+		uint8_t j = 0;
+
+		if (!BN_generate_prime_ex(p, bits, 0, NULL, NULL, NULL))
+			goto err;
+
+		do {
+			RAND_add(&j, sizeof(j), 1);
+			if (!BN_generate_prime_ex(q, bits, 0, NULL, NULL, NULL))
+				goto err;
+
+		} while ((BN_cmp(p, q) == 0) && (j++ < 100));
+
+		if (j >= 100) {
+			RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate q", j);
+			goto err;
+		}
+
+		/* pq */
+		if (!BN_mul(n, p, q, ctx))
+			goto err;
+
+		/* p-1 */
+		if (!BN_sub(r1, p, BN_value_one()))
+			goto err;
+
+		/* q-1 */
+		if (!BN_sub(r2, q, BN_value_one()))
+			goto err;
+
+		/* (p-1 * q-1) */
+		if (!BN_mul(r0, r1, r2, ctx))
+			goto err;
+
+		/* gcd(p-1, q-1)*/
+		if (!BN_gcd(r3, r1, r2, ctx))
+			goto err;
+
+		/* lcm(p-1, q-1) */
+		if (!BN_div(r4, r, r0, r3, ctx))
+			goto err;
+
+		/* check if div and rem are non-zero */
+		if (!r4 || !r)
+			goto err;
+
+		/* 0 < e < lcm */
+		if (!e) {
+			int k = 0;
+
+			e = BN_new();
+			do {
+				RAND_add(&k, sizeof(k), 1);
+				if (!BN_rand(e, 32, 1, 1))
+					goto err;
+
+				if (!BN_gcd(r3, e, r4, ctx))
+					goto err;
+
+				if (BN_is_one(r3))
+					break;
+			} while (k++ < 10);
+
+			if (k >= 10) {
+				RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate e",
+					k);
+				goto err;
+			}
+		}
+
+		/* (de) mod lcm == 1 */
+		if (!BN_mod_inverse(d, e, r4, ctx))
+			goto err;
+
+		if (!BN_gcd(r3, r1, e, ctx))
+			goto err;
+
+		if (!BN_gcd(r4, r2, e, ctx))
+			goto err;
+
+		/* check if gcd(p-1, e) and gcd(q-1, e) are 1 */
+		if (BN_is_one(r3) && BN_is_one(r4))
+			break;
+	}
+
+	if (i >= 10) {
+		RTE_LOG(ERR, USER1, "Error: insufficient %d retries to generate p and q", i);
+		goto err;
+	}
+
+	/* d mod (p-1) */
+	dp = BN_new();
+	if (!dp)
+		goto err;
+
+	if (!BN_mod(dp, d, r1, ctx))
+		goto err;
+
+	/* d mod (q-1) */
+	dq = BN_new();
+	if (!dq)
+		goto err;
+
+	if (!BN_mod(dq, d, r2, ctx))
+		goto err;
+
+	/* modinv of q and p */
+	qinv = BN_new();
+	if (!qinv)
+		goto err;
+
+	if (!BN_mod_inverse(qinv, q, p, ctx))
+		goto err;
+
+	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
+	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
+	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
+	parse_uint8_hex_str("", BN_bn2hex(n), &vec.rsa.n);
+	parse_uint8_hex_str("", BN_bn2hex(d), &vec.rsa.d);
+	parse_uint8_hex_str("", BN_bn2hex(dp), &vec.rsa.dp);
+	parse_uint8_hex_str("", BN_bn2hex(dq), &vec.rsa.dq);
+	parse_uint8_hex_str("", BN_bn2hex(qinv), &vec.rsa.qinv);
+
+	ret = 0;
+err:
+	BN_CTX_end(ctx);
+	BN_CTX_free(ctx);
+	BN_free(m);
+	BN_free(r);
+	BN_free(p);
+	BN_free(q);
+	BN_free(n);
+	BN_free(d);
+	BN_free(e);
+	return ret;
+}
+#else
+static int
+prepare_vec_rsa(void)
+{
+	/*
+	 * Generate RSA values.
+	 */
+	return -ENOTSUP;
+}
+#endif /* USE_OPENSSL */
+
+static int
+parse_test_rsa_json_interim_writeback(struct fips_val *val)
+{
+	RTE_SET_USED(val);
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		/* For siggen tests, RSA values can be created soon after
+		 * the test group data are parsed.
+		 */
+		if (vec.rsa.e.val) {
+			rte_free(vec.rsa.e.val);
+			vec.rsa.e.val = NULL;
+		}
+
+		if (prepare_vec_rsa() < 0)
+			return -1;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_group, "e", obj);
+	}
+
+	return 0;
+}
+
+static int
+parse_test_rsa_json_writeback(struct fips_val *val)
+{
+	json_t *tcId;
+
+	RTE_SET_USED(val);
+
+	tcId = json_object_get(json_info.json_test_case, "tcId");
+
+	json_info.json_write_case = json_object();
+	json_object_set(json_info.json_write_case, "tcId", tcId);
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "seed", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.n);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "n", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.e);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "e", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.p);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "p", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.q);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "q", obj);
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.d);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "d", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		json_t *obj;
+
+		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
+		obj = json_string(info.one_line_text);
+		json_object_set_new(json_info.json_write_case, "signature", obj);
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
+			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
+		else
+			json_object_set_new(json_info.json_write_case, "testPassed", json_false());
+	}
+
+	return 0;
+}
+
+static int
+parse_interim_str(const char *key, char *src, struct fips_val *val)
+{
+	uint32_t i;
+
+	RTE_SET_USED(val);
+
+	if (strcmp(key, SIGTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_padding_types); i++)
+			if (strstr(src, rsa_padding_types[i].desc)) {
+				info.interim_info.rsa_data.padding = rsa_padding_types[i].padding;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_padding_types))
+			return -EINVAL;
+
+	}  else if (strcmp(key, MOD_JSON_STR) == 0) {
+		info.interim_info.rsa_data.modulo = atoi(src);
+	} else if (strcmp(key, HASH_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_auth_algs); i++)
+			if (strstr(src, rsa_auth_algs[i].desc)) {
+				info.interim_info.rsa_data.auth = rsa_auth_algs[i].auth;
+				break;
+			}
+
+		if (i >= RTE_DIM(rsa_auth_algs))
+			return -EINVAL;
+
+	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
+		info.interim_info.rsa_data.saltlen = atoi(src);
+	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
+		for (i = 0; i < RTE_DIM(rsa_test_types); i++)
+			if (strstr(src, rsa_test_types[i].desc)) {
+				info.parse_writeback = parse_test_rsa_json_writeback;
+				break;
+			}
+
+		if (!info.parse_writeback || i >= RTE_DIM(rsa_test_types))
+			return -EINVAL;
+
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int
+parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
+{
+	parse_uint8_hex_str(key, src, val);
+
+	/* For keygen tests, key "e" can be the end of input data
+	 * to generate RSA values.
+	 */
+	return prepare_vec_rsa();
+}
+
+struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
+		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
+		{MOD_JSON_STR, parse_interim_str, NULL},
+		{HASH_JSON_STR, parse_interim_str, NULL},
+		{SALT_JSON_STR, parse_interim_str, NULL},
+		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
+		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
+		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_keygen_json_vectors[] = {
+		{SEED_JSON_STR, parse_uint8_hex_str, &vec.rsa.seed},
+		{E_JSON_STR, parse_keygen_e_str, &vec.rsa.e},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_siggen_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+struct fips_test_callback rsa_sigver_json_vectors[] = {
+		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{NULL, NULL, NULL} /**< end pointer */
+};
+
+int
+parse_test_rsa_json_init(void)
+{
+	json_t *keyfmt_obj = json_object_get(json_info.json_vector_set, "keyFormat");
+	json_t *mode_obj = json_object_get(json_info.json_vector_set, "mode");
+	const char *keyfmt_str = json_string_value(keyfmt_obj);
+	const char *mode_str = json_string_value(mode_obj);
+
+	info.callbacks = NULL;
+	info.parse_writeback = NULL;
+	info.interim_callbacks = NULL;
+	info.parse_interim_writeback = NULL;
+
+	if (strcmp(mode_str, "keyGen") == 0) {
+		info.op = FIPS_TEST_ASYM_KEYGEN;
+		info.callbacks = rsa_keygen_json_vectors;
+		info.interim_callbacks = rsa_keygen_interim_json_vectors;
+	} else if (strcmp(mode_str, "sigGen") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGGEN;
+		info.callbacks = rsa_siggen_json_vectors;
+		info.interim_callbacks = rsa_siggen_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
+	} else if (strcmp(mode_str, "sigVer") == 0) {
+		info.op = FIPS_TEST_ASYM_SIGVER;
+		info.callbacks = rsa_sigver_json_vectors;
+		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+	} else {
+		return -EINVAL;
+	}
+
+	info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_QT;
+	if (keyfmt_str != NULL && strcmp(keyfmt_str, "standard") == 0)
+		info.interim_info.rsa_data.privkey = RTE_RSA_KEY_TYPE_EXP;
+
+	return 0;
+}
+#endif /* USE_JANSSON */
+
diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index 7b31579d04..b85409e056 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -37,6 +37,8 @@ enum {
 	OPT_CRYPTODEV_BK_DIR_KEY_NUM,
 #define OPT_USE_JSON                "use-json"
 	OPT_USE_JSON_NUM,
+#define OPT_CRYPTODEV_ASYM          "asymmetric"
+	OPT_CRYPTODEV_ASYM_NUM,
 };
 
 struct fips_test_vector vec;
@@ -51,34 +53,140 @@ struct cryptodev_fips_validate_env {
 	const char *rsp_path;
 	uint32_t is_path_folder;
 	uint8_t dev_id;
+	struct rte_mempool *mpool;
+	struct fips_sym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_sym_session *sess;
+		struct rte_crypto_op *op;
+	} sym;
+	struct fips_asym_env {
+		struct rte_mempool *sess_mpool;
+		struct rte_mempool *op_pool;
+		struct rte_cryptodev_asym_session *sess;
+		struct rte_crypto_op *op;
+	} asym;
+	struct rte_crypto_op *op;
 	uint8_t dev_support_sgl;
 	uint16_t mbuf_data_room;
-	struct rte_mempool *mpool;
-	struct rte_mempool *sess_mpool;
-	struct rte_mempool *op_pool;
 	struct rte_mbuf *mbuf;
 	uint8_t *digest;
 	uint16_t digest_len;
-	struct rte_crypto_op *op;
-	void *sess;
+	bool is_asym_test;
 	uint16_t self_test;
 	struct fips_dev_broken_test_config *broken_test_config;
 } env;
 
 static int
-cryptodev_fips_validate_app_int(void)
+cryptodev_fips_validate_app_sym_init(void)
+{
+	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
+							env.dev_id);
+	struct rte_cryptodev_info dev_info;
+	struct fips_sym_env *sym = &env.sym;
+	int ret;
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
+		env.dev_support_sgl = 1;
+	else
+		env.dev_support_sgl = 0;
+
+	ret = -ENOMEM;
+	sym->sess_mpool = rte_cryptodev_sym_session_pool_create(
+			"FIPS_SYM_SESS_MEMPOOL", 16, sess_sz, 0, 0, rte_socket_id());
+	if (!sym->sess_mpool)
+		goto error_exit;
+
+	sym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_SYM_POOL",
+			RTE_CRYPTO_OP_TYPE_SYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!sym->op_pool)
+		goto error_exit;
+
+	sym->op = rte_crypto_op_alloc(sym->op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
+	if (!sym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_sym_uninit(void)
+{
+	struct fips_sym_env *sym = &env.sym;
+
+	rte_pktmbuf_free(env.mbuf);
+	rte_crypto_op_free(sym->op);
+	rte_cryptodev_sym_session_free(env.dev_id, sym->sess);
+	rte_mempool_free(sym->sess_mpool);
+	rte_mempool_free(sym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_asym_init(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+	int ret;
+
+	ret = -ENOMEM;
+	asym->sess_mpool = rte_cryptodev_asym_session_pool_create(
+			"FIPS_ASYM_SESS_MEMPOOL", 16, 0, 0, rte_socket_id());
+	if (!asym->sess_mpool)
+		goto error_exit;
+
+	asym->op_pool = rte_crypto_op_pool_create(
+			"FIPS_OP_ASYM_POOL",
+			RTE_CRYPTO_OP_TYPE_ASYMMETRIC,
+			1, 0,
+			16,
+			rte_socket_id());
+	if (!asym->op_pool)
+		goto error_exit;
+
+	asym->op = rte_crypto_op_alloc(asym->op_pool, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+	if (!asym->op)
+		goto error_exit;
+
+	return 0;
+
+error_exit:
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+	return ret;
+}
+
+static void
+cryptodev_fips_validate_app_asym_uninit(void)
+{
+	struct fips_asym_env *asym = &env.asym;
+
+	rte_crypto_op_free(asym->op);
+	rte_cryptodev_asym_session_free(env.dev_id, asym->sess);
+	rte_mempool_free(asym->sess_mpool);
+	rte_mempool_free(asym->op_pool);
+}
+
+static int
+cryptodev_fips_validate_app_init(void)
 {
 	struct rte_cryptodev_config conf = {rte_socket_id(), 1, 0};
 	struct rte_cryptodev_qp_conf qp_conf = {128, NULL};
-	struct rte_cryptodev_info dev_info;
-	uint32_t sess_sz = rte_cryptodev_sym_get_private_session_size(
-			env.dev_id);
 	uint32_t nb_mbufs = UINT16_MAX / env.mbuf_data_room + 1;
 	int ret;
 
 	if (env.self_test) {
 		ret = fips_dev_self_test(env.dev_id, env.broken_test_config);
 		if (ret < 0) {
+			rte_cryptodev_stop(env.dev_id);
 			rte_cryptodev_close(env.dev_id);
 
 			return ret;
@@ -89,45 +197,24 @@ cryptodev_fips_validate_app_int(void)
 	if (ret < 0)
 		return ret;
 
-	rte_cryptodev_info_get(env.dev_id, &dev_info);
-	if (dev_info.feature_flags & RTE_CRYPTODEV_FF_IN_PLACE_SGL)
-		env.dev_support_sgl = 1;
-	else
-		env.dev_support_sgl = 0;
-
+	ret = -ENOMEM;
 	env.mpool = rte_pktmbuf_pool_create("FIPS_MEMPOOL", nb_mbufs,
 			0, 0, sizeof(struct rte_mbuf) + RTE_PKTMBUF_HEADROOM +
 			env.mbuf_data_room, rte_socket_id());
 	if (!env.mpool)
 		return ret;
 
-	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
-			rte_socket_id());
+	ret = cryptodev_fips_validate_app_sym_init();
 	if (ret < 0)
-		return ret;
-
-	ret = -ENOMEM;
-
-	env.sess_mpool = rte_cryptodev_sym_session_pool_create(
-			"FIPS_SESS_MEMPOOL", 16, sess_sz, 0, 0,
-			rte_socket_id());
-	if (!env.sess_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.op = rte_crypto_op_alloc(env.op_pool, RTE_CRYPTO_OP_TYPE_SYMMETRIC);
-	if (!env.op)
-		goto error_exit;
+	if (env.is_asym_test) {
+		ret = cryptodev_fips_validate_app_asym_init();
+		if (ret < 0)
+			goto error_exit;
+	}
 
-	qp_conf.mp_session = env.sess_mpool;
+	qp_conf.mp_session = env.sym.sess_mpool;
 
 	ret = rte_cryptodev_queue_pair_setup(env.dev_id, 0, &qp_conf,
 			rte_socket_id());
@@ -141,23 +228,21 @@ cryptodev_fips_validate_app_int(void)
 	return 0;
 
 error_exit:
-
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	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_free(env.dev_id, env.sess);
+	cryptodev_fips_validate_app_sym_uninit();
+
+	if (env.is_asym_test)
+		cryptodev_fips_validate_app_asym_uninit();
+
 	rte_mempool_free(env.mpool);
-	rte_mempool_free(env.sess_mpool);
-	rte_mempool_free(env.op_pool);
+	rte_cryptodev_stop(env.dev_id);
+	rte_cryptodev_close(env.dev_id);
 }
 
 static int
@@ -253,6 +338,8 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 				NULL, OPT_CRYPTODEV_BK_ID_NUM},
 		{OPT_CRYPTODEV_BK_DIR_KEY, required_argument,
 				NULL, OPT_CRYPTODEV_BK_DIR_KEY_NUM},
+		{OPT_CRYPTODEV_ASYM, no_argument,
+				NULL, OPT_CRYPTODEV_ASYM_NUM},
 		{NULL, 0, 0, 0}
 	};
 
@@ -365,6 +452,10 @@ cryptodev_fips_validate_parse_args(int argc, char **argv)
 			}
 			break;
 
+		case OPT_CRYPTODEV_ASYM_NUM:
+			env.is_asym_test = true;
+			break;
+
 		default:
 			cryptodev_fips_validate_usage(prgname);
 			return -EINVAL;
@@ -405,7 +496,7 @@ main(int argc, char *argv[])
 	if (ret < 0)
 		rte_exit(EXIT_FAILURE, "Failed to parse arguments!\n");
 
-	ret = cryptodev_fips_validate_app_int();
+	ret = cryptodev_fips_validate_app_init();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Failed init\n", ret);
 		return -1;
@@ -644,7 +735,7 @@ prepare_cipher_op(void)
 		sym->cipher.data.length = vec.ct.len;
 	}
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	sym->m_src = env.mbuf;
 	sym->cipher.data.offset = 0;
@@ -707,7 +798,7 @@ prepare_auth_op(void)
 		memcpy(env.digest, vec.cipher_auth.digest.val,
 				vec.cipher_auth.digest.len);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
 
 	return 0;
 }
@@ -763,7 +854,55 @@ prepare_aead_op(void)
 	sym->aead.aad.data = vec.aead.aad.val;
 	sym->aead.aad.phys_addr = rte_malloc_virt2iova(sym->aead.aad.data);
 
-	rte_crypto_op_attach_sym_session(env.op, env.sess);
+	rte_crypto_op_attach_sym_session(env.op, env.sym.sess);
+
+	return 0;
+}
+
+static int
+prepare_rsa_op(void)
+{
+	struct rte_crypto_asym_op *asym;
+	struct fips_val msg;
+
+	__rte_crypto_op_reset(env.op, RTE_CRYPTO_OP_TYPE_ASYMMETRIC);
+
+	asym = env.op->asym;
+	asym->rsa.padding.type = info.interim_info.rsa_data.padding;
+	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
+
+	if (env.digest) {
+		msg.val = env.digest;
+		msg.len = env.digest_len;
+	} else {
+		msg.val = vec.pt.val;
+		msg.len = vec.pt.len;
+	}
+
+	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_SIGN;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+
+		if (vec.rsa.signature.val)
+			rte_free(vec.rsa.signature.val);
+
+		vec.rsa.signature.val = rte_zmalloc(NULL, vec.rsa.n.len, 0);
+		vec.rsa.signature.len = vec.rsa.n.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = 0;
+	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
+		asym->rsa.op_type = RTE_CRYPTO_ASYM_OP_VERIFY;
+		asym->rsa.message.data = msg.val;
+		asym->rsa.message.length = msg.len;
+		asym->rsa.sign.data = vec.rsa.signature.val;
+		asym->rsa.sign.length = vec.rsa.signature.len;
+	} else {
+		RTE_LOG(ERR, USER1, "Invalid op %d\n", info.op);
+		return -EINVAL;
+	}
+
+	rte_crypto_op_attach_asym_session(env.op, env.asym.sess);
 
 	return 0;
 }
@@ -1154,6 +1293,87 @@ prepare_xts_xform(struct rte_crypto_sym_xform *xform)
 	return 0;
 }
 
+static int
+prepare_rsa_xform(struct rte_crypto_asym_xform *xform)
+{
+	const struct rte_cryptodev_asymmetric_xform_capability *cap;
+	struct rte_cryptodev_asym_capability_idx cap_idx;
+	struct rte_cryptodev_info dev_info;
+
+	xform->xform_type = RTE_CRYPTO_ASYM_XFORM_RSA;
+	xform->next = NULL;
+
+	cap_idx.type = xform->xform_type;
+	cap = rte_cryptodev_asym_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;
+	}
+
+	switch (info.op) {
+	case FIPS_TEST_ASYM_SIGGEN:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_SIGN)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_SIGN);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_SIGVER:
+		if (!rte_cryptodev_asym_xform_capability_check_optype(cap,
+			RTE_CRYPTO_ASYM_OP_VERIFY)) {
+			RTE_LOG(ERR, USER1, "PMD %s xform_op %u\n",
+				info.device_name, RTE_CRYPTO_ASYM_OP_VERIFY);
+			return -EPERM;
+		}
+		break;
+	case FIPS_TEST_ASYM_KEYGEN:
+		break;
+	default:
+		break;
+	}
+
+	rte_cryptodev_info_get(env.dev_id, &dev_info);
+	xform->rsa.key_type = info.interim_info.rsa_data.privkey;
+	switch (xform->rsa.key_type) {
+	case RTE_RSA_KEY_TYPE_QT:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_QT)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support QT key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.qt.p.data = vec.rsa.p.val;
+		xform->rsa.qt.p.length = vec.rsa.p.len;
+		xform->rsa.qt.q.data = vec.rsa.q.val;
+		xform->rsa.qt.q.length = vec.rsa.q.len;
+		xform->rsa.qt.dP.data = vec.rsa.dp.val;
+		xform->rsa.qt.dP.length = vec.rsa.dp.len;
+		xform->rsa.qt.dQ.data = vec.rsa.dq.val;
+		xform->rsa.qt.dQ.length = vec.rsa.dq.len;
+		xform->rsa.qt.qInv.data = vec.rsa.qinv.val;
+		xform->rsa.qt.qInv.length = vec.rsa.qinv.len;
+		break;
+	case RTE_RSA_KEY_TYPE_EXP:
+		if (!(dev_info.feature_flags & RTE_CRYPTODEV_FF_RSA_PRIV_OP_KEY_EXP)) {
+			RTE_LOG(ERR, USER1, "PMD %s does not support EXP key type\n",
+				info.device_name);
+			return -EPERM;
+		}
+		xform->rsa.d.data = vec.rsa.d.val;
+		xform->rsa.d.length = vec.rsa.d.len;
+		break;
+	default:
+		break;
+	}
+
+	xform->rsa.e.data = vec.rsa.e.val;
+	xform->rsa.e.length = vec.rsa.e.len;
+	xform->rsa.n.data = vec.rsa.n.val;
+	xform->rsa.n.length = vec.rsa.n.len;
+	return 0;
+}
+
 static int
 get_writeback_data(struct fips_val *val)
 {
@@ -1200,25 +1420,25 @@ get_writeback_data(struct fips_val *val)
 }
 
 static int
-fips_run_test(void)
+fips_run_sym_test(void)
 {
 	struct rte_crypto_sym_xform xform = {0};
 	uint16_t n_deqd;
 	int ret;
 
-	ret = test_ops.prepare_xform(&xform);
+	if (!test_ops.prepare_sym_xform || !test_ops.prepare_sym_op)
+		return -EINVAL;
+
+	ret = test_ops.prepare_sym_xform(&xform);
 	if (ret < 0)
 		return ret;
 
-	env.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
-			env.sess_mpool);
-	if (!env.sess) {
-		RTE_LOG(ERR, USER1, "Error %i: Init session\n",
-				ret);
-		goto exit;
-	}
+	env.sym.sess = rte_cryptodev_sym_session_create(env.dev_id, &xform,
+						env.sym.sess_mpool);
+	if (!env.sym.sess)
+		return -ENOMEM;
 
-	ret = test_ops.prepare_op();
+	ret = test_ops.prepare_sym_op();
 	if (ret < 0) {
 		RTE_LOG(ERR, USER1, "Error %i: Prepare op\n",
 				ret);
@@ -1234,21 +1454,91 @@ fips_run_test(void)
 	do {
 		struct rte_crypto_op *deqd_op;
 
-		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op,
-				1);
+		n_deqd = rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1);
 	} while (n_deqd == 0);
 
 	vec.status = env.op->status;
 
 exit:
-	if (env.sess) {
-		rte_cryptodev_sym_session_free(env.dev_id, env.sess);
-		env.sess = NULL;
+	rte_cryptodev_sym_session_free(env.dev_id, env.sym.sess);
+	env.sym.sess = NULL;
+	return ret;
+}
+
+static int
+fips_run_asym_test(void)
+{
+	struct rte_crypto_asym_xform xform = {0};
+	struct rte_crypto_asym_op *asym;
+	struct rte_crypto_op *deqd_op;
+	int ret;
+
+	if (info.op == FIPS_TEST_ASYM_KEYGEN) {
+		RTE_SET_USED(asym);
+		ret = 0;
+		goto exit;
+	}
+
+	if (!test_ops.prepare_asym_xform || !test_ops.prepare_asym_op)
+		return -EINVAL;
+
+	asym = env.op->asym;
+	ret = test_ops.prepare_asym_xform(&xform);
+	if (ret < 0)
+		return ret;
+
+	ret = rte_cryptodev_asym_session_create(env.dev_id, &xform, env.asym.sess_mpool,
+			(void *)&env.asym.sess);
+	if (ret < 0)
+		return ret;
+
+	ret = test_ops.prepare_asym_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;
+	}
+
+	while (rte_cryptodev_dequeue_burst(env.dev_id, 0, &deqd_op, 1) == 0)
+		rte_pause();
+
+	vec.status = env.op->status;
+
+ exit:
+	if (env.asym.sess)
+		rte_cryptodev_asym_session_free(env.dev_id, env.asym.sess);
+
+	env.asym.sess = NULL;
 	return ret;
 }
 
+static int
+fips_run_test(void)
+{
+	int ret;
+
+	env.op = env.sym.op;
+	if (env.is_asym_test) {
+		vec.cipher_auth.digest.len = parse_test_sha_hash_size(
+						info.interim_info.rsa_data.auth);
+		test_ops.prepare_sym_xform = prepare_sha_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		ret = fips_run_sym_test();
+		if (ret < 0)
+			return ret;
+	} else {
+		return fips_run_sym_test();
+	}
+
+	env.op = env.asym.op;
+	return fips_run_asym_test();
+}
+
 static int
 fips_generic_test(void)
 {
@@ -1271,9 +1561,11 @@ fips_generic_test(void)
 		return ret;
 	}
 
-	ret = get_writeback_data(&val);
-	if (ret < 0)
-		return ret;
+	if (!env.is_asym_test) {
+		ret = get_writeback_data(&val);
+		if (ret < 0)
+			return ret;
+	}
 
 	switch (info.file_type) {
 	case FIPS_TYPE_REQ:
@@ -1823,65 +2115,70 @@ init_test_ops(void)
 	case FIPS_TEST_ALGO_AES_CBC:
 	case FIPS_TEST_ALGO_AES_CTR:
 	case FIPS_TEST_ALGO_AES:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform  = prepare_aes_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_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_GMAC:
-		test_ops.prepare_op = prepare_auth_op;
-		test_ops.prepare_xform = prepare_gmac_xform;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_xform = prepare_gmac_xform;
 		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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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.prepare_sym_op = prepare_aead_op;
+		test_ops.prepare_sym_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;
+		test_ops.prepare_sym_op = prepare_auth_op;
+		test_ops.prepare_sym_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;
 	case FIPS_TEST_ALGO_AES_XTS:
-		test_ops.prepare_op = prepare_cipher_op;
-		test_ops.prepare_xform = prepare_xts_xform;
+		test_ops.prepare_sym_op = prepare_cipher_op;
+		test_ops.prepare_sym_xform = prepare_xts_xform;
+		test_ops.test = fips_generic_test;
+		break;
+	case FIPS_TEST_ALGO_RSA:
+		test_ops.prepare_asym_op = prepare_rsa_op;
+		test_ops.prepare_asym_xform = prepare_rsa_xform;
 		test_ops.test = fips_generic_test;
 		break;
 	default:
 		if (strstr(info.file_name, "TECB") ||
 				strstr(info.file_name, "TCBC")) {
 			info.algo = FIPS_TEST_ALGO_TDES;
-			test_ops.prepare_op = prepare_cipher_op;
-			test_ops.prepare_xform	= prepare_tdes_xform;
+			test_ops.prepare_sym_op = prepare_cipher_op;
+			test_ops.prepare_sym_xform = prepare_tdes_xform;
 			if (info.interim_info.tdes_data.test_type == TDES_MCT)
 				test_ops.test = fips_mct_tdes_test;
 			else
@@ -2049,6 +2346,9 @@ fips_test_one_test_group(void)
 	case FIPS_TEST_ALGO_TDES:
 		ret = parse_test_tdes_json_init();
 		break;
+	case FIPS_TEST_ALGO_RSA:
+		ret = parse_test_rsa_json_init();
+		break;
 	default:
 		return -EINVAL;
 	}
diff --git a/examples/fips_validation/meson.build b/examples/fips_validation/meson.build
index 8bca26a095..d310093189 100644
--- a/examples/fips_validation/meson.build
+++ b/examples/fips_validation/meson.build
@@ -18,6 +18,7 @@ sources = files(
         'fips_validation_ccm.c',
         'fips_validation_sha.c',
         'fips_validation_xts.c',
+        'fips_validation_rsa.c',
         'fips_dev_self_test.c',
         'main.c',
 )
@@ -26,3 +27,8 @@ if dpdk_conf.has('RTE_HAS_JANSSON')
     ext_deps += jansson_dep
     cflags += '-DUSE_JANSSON'
 endif
+
+if dpdk_conf.has('RTE_HAS_OPENSSL')
+    ext_deps += openssl_dep
+    cflags += '-DUSE_OPENSSL'
+endif
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v7 2/3] examples/fips_validation: encode digest with hash OID
  2022-10-12  6:12           ` [v7 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  2022-10-12  6:12             ` [v7 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
@ 2022-10-12  6:12             ` Gowrishankar Muthukrishnan
  2022-10-12  6:12             ` [v7 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
  2022-10-12 18:44             ` [v7 0/3] FIPS asymmetric validation Akhil Goyal
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  6:12 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS RSA validation requires hash ddigest be encoded with ASN.1
value for digest info.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/main.c | 78 +++++++++++++++++++++++++++++++++
 1 file changed, 78 insertions(+)

diff --git a/examples/fips_validation/main.c b/examples/fips_validation/main.c
index b85409e056..b1fa38bda7 100644
--- a/examples/fips_validation/main.c
+++ b/examples/fips_validation/main.c
@@ -859,6 +859,63 @@ prepare_aead_op(void)
 	return 0;
 }
 
+static int
+get_hash_oid(enum rte_crypto_auth_algorithm hash, uint8_t *buf)
+{
+	uint8_t id_sha512[] = {0x30, 0x51, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x03, 0x05, 0x00, 0x04,
+				  0x40};
+	uint8_t id_sha384[] = {0x30, 0x41, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x02, 0x05, 0x00, 0x04,
+				  0x30};
+	uint8_t id_sha256[] = {0x30, 0x31, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x01, 0x05, 0x00, 0x04,
+				  0x20};
+	uint8_t id_sha224[] = {0x30, 0x2d, 0x30, 0x0d, 0x06, 0x09,
+				  0x60, 0x86, 0x48, 0x01, 0x65, 0x03,
+				  0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
+				  0x1c};
+	uint8_t id_sha1[] = {0x30, 0x21, 0x30, 0x09, 0x06, 0x05,
+				0x2b, 0x0e, 0x03, 0x02, 0x1a, 0x05,
+				0x00, 0x04, 0x14};
+	uint8_t *id = NULL;
+	int id_len = 0;
+
+	switch (hash) {
+	case RTE_CRYPTO_AUTH_SHA1:
+		id = id_sha1;
+		id_len = sizeof(id_sha1);
+		break;
+	case RTE_CRYPTO_AUTH_SHA224:
+		id = id_sha224;
+		id_len = sizeof(id_sha224);
+		break;
+	case RTE_CRYPTO_AUTH_SHA256:
+		id = id_sha256;
+		id_len = sizeof(id_sha256);
+		break;
+	case RTE_CRYPTO_AUTH_SHA384:
+		id = id_sha384;
+		id_len = sizeof(id_sha384);
+		break;
+	case RTE_CRYPTO_AUTH_SHA512:
+		id = id_sha512;
+		id_len = sizeof(id_sha512);
+		break;
+	default:
+		id_len = -1;
+		break;
+	}
+
+	if (id != NULL)
+		rte_memcpy(buf, id, id_len);
+
+	return id_len;
+}
+
 static int
 prepare_rsa_op(void)
 {
@@ -872,6 +929,27 @@ prepare_rsa_op(void)
 	asym->rsa.padding.hash = info.interim_info.rsa_data.auth;
 
 	if (env.digest) {
+		if (asym->rsa.padding.type == RTE_CRYPTO_RSA_PADDING_PKCS1_5) {
+			int b_len = 0;
+			uint8_t b[32];
+
+			b_len = get_hash_oid(asym->rsa.padding.hash, b);
+			if (b_len < 0) {
+				RTE_LOG(ERR, USER1, "Failed to get digest info for hash %d\n",
+					asym->rsa.padding.hash);
+				return -EINVAL;
+			}
+
+			if (b_len) {
+				msg.len = env.digest_len + b_len;
+				msg.val = rte_zmalloc(NULL, msg.len, 0);
+				rte_memcpy(msg.val, b, b_len);
+				rte_memcpy(msg.val + b_len, env.digest, env.digest_len);
+				rte_free(env.digest);
+				env.digest = msg.val;
+				env.digest_len = msg.len;
+			}
+		}
 		msg.val = env.digest;
 		msg.len = env.digest_len;
 	} else {
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* [v7 3/3] examples/fips_validation: randomize message for conformance test
  2022-10-12  6:12           ` [v7 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
  2022-10-12  6:12             ` [v7 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
  2022-10-12  6:12             ` [v7 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
@ 2022-10-12  6:12             ` Gowrishankar Muthukrishnan
  2022-10-12 18:44             ` [v7 0/3] FIPS asymmetric validation Akhil Goyal
  3 siblings, 0 replies; 39+ messages in thread
From: Gowrishankar Muthukrishnan @ 2022-10-12  6:12 UTC (permalink / raw)
  To: dev
  Cc: Anoob Joseph, Brian Dooley, Akhil Goyal, jerinj,
	Gowrishankar Muthukrishnan

FIPS conformance tests require randomizing message based on SP 800-106.

Signed-off-by: Gowrishankar Muthukrishnan <gmuthukrishn@marvell.com>
---
 examples/fips_validation/fips_validation.h    |   4 +
 .../fips_validation/fips_validation_rsa.c     | 112 +++++++++++++++++-
 2 files changed, 115 insertions(+), 1 deletion(-)

diff --git a/examples/fips_validation/fips_validation.h b/examples/fips_validation/fips_validation.h
index 7c275403c7..eec9616462 100644
--- a/examples/fips_validation/fips_validation.h
+++ b/examples/fips_validation/fips_validation.h
@@ -213,6 +213,7 @@ struct rsa_interim_data {
 	uint16_t saltlen;
 	enum rte_crypto_rsa_padding_type padding;
 	enum rte_crypto_rsa_priv_key_type privkey;
+	uint8_t random_msg;
 };
 
 #ifdef USE_JANSSON
@@ -339,6 +340,9 @@ parse_test_tdes_json_init(void);
 
 int
 parse_test_rsa_json_init(void);
+
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand);
 #endif /* USE_JANSSON */
 
 int
diff --git a/examples/fips_validation/fips_validation_rsa.c b/examples/fips_validation/fips_validation_rsa.c
index d3699f54d0..22c0faf3cb 100644
--- a/examples/fips_validation/fips_validation_rsa.c
+++ b/examples/fips_validation/fips_validation_rsa.c
@@ -19,11 +19,13 @@
 
 #include "fips_validation.h"
 
+#define CONFORMANCE_JSON_STR	"conformance"
 #define TESTTYPE_JSON_STR	"testType"
 #define SIGTYPE_JSON_STR "sigType"
 #define MOD_JSON_STR	"modulo"
 #define HASH_JSON_STR	"hashAlg"
 #define SALT_JSON_STR	"saltLen"
+#define RV_JSON_STR	"randomValue"
 #define E_JSON_STR	"e"
 #define N_JSON_STR	"n"
 
@@ -31,6 +33,10 @@
 #define MSG_JSON_STR	"message"
 #define SIG_JSON_STR	"signature"
 
+
+#define RV_BUF_LEN (1024/8)
+#define RV_BIT_LEN (256)
+
 #ifdef USE_JANSSON
 struct {
 	uint8_t type;
@@ -259,6 +265,13 @@ prepare_vec_rsa(void)
 	if (!BN_mod_inverse(qinv, q, p, ctx))
 		goto err;
 
+	if (info.interim_info.rsa_data.random_msg) {
+		if (!BN_generate_prime_ex(r, RV_BIT_LEN, 0, NULL, NULL, NULL))
+			goto err;
+
+		parse_uint8_hex_str("", BN_bn2hex(r), &vec.rsa.seed);
+	}
+
 	parse_uint8_hex_str("", BN_bn2hex(e), &vec.rsa.e);
 	parse_uint8_hex_str("", BN_bn2hex(p), &vec.rsa.p);
 	parse_uint8_hex_str("", BN_bn2hex(q), &vec.rsa.q);
@@ -297,6 +310,11 @@ parse_test_rsa_json_interim_writeback(struct fips_val *val)
 {
 	RTE_SET_USED(val);
 
+	if (info.interim_info.rsa_data.random_msg) {
+		json_object_set_new(json_info.json_write_group, "conformance",
+							json_string("SP800-106"));
+	}
+
 	if (info.op == FIPS_TEST_ASYM_SIGGEN) {
 		json_t *obj;
 
@@ -367,6 +385,14 @@ parse_test_rsa_json_writeback(struct fips_val *val)
 		writeback_hex_str("", info.one_line_text, &vec.rsa.signature);
 		obj = json_string(info.one_line_text);
 		json_object_set_new(json_info.json_write_case, "signature", obj);
+
+		if (info.interim_info.rsa_data.random_msg) {
+			writeback_hex_str("", info.one_line_text, &vec.rsa.seed);
+			obj = json_string(info.one_line_text);
+			json_object_set_new(json_info.json_write_case, "randomValue", obj);
+			json_object_set_new(json_info.json_write_case, "randomValueLen",
+				json_integer(vec.rsa.seed.len * 8));
+		}
 	} else if (info.op == FIPS_TEST_ASYM_SIGVER) {
 		if (vec.status == RTE_CRYPTO_OP_STATUS_SUCCESS)
 			json_object_set_new(json_info.json_write_case, "testPassed", json_true());
@@ -406,6 +432,8 @@ parse_interim_str(const char *key, char *src, struct fips_val *val)
 		if (i >= RTE_DIM(rsa_auth_algs))
 			return -EINVAL;
 
+	}  else if (strcmp(key, CONFORMANCE_JSON_STR) == 0) {
+		info.interim_info.rsa_data.random_msg = 1;
 	}  else if (strcmp(key, SALT_JSON_STR) == 0) {
 		info.interim_info.rsa_data.saltlen = atoi(src);
 	} else if (strcmp(key, TESTTYPE_JSON_STR) == 0) {
@@ -436,6 +464,83 @@ parse_keygen_e_str(const char *key, char *src, struct fips_val *val)
 	return prepare_vec_rsa();
 }
 
+/*
+ * Message randomization function as per NIST SP 800-106.
+ */
+int
+fips_test_randomize_message(struct fips_val *msg, struct fips_val *rand)
+{
+	uint8_t m[FIPS_TEST_JSON_BUF_LEN], rv[RV_BUF_LEN];
+	uint32_t m_bitlen, rv_bitlen, count, remain, i, j;
+	uint16_t rv_len;
+
+	if (!msg->val || !rand->val || rand->len > RV_BUF_LEN
+		|| msg->len > FIPS_TEST_JSON_BUF_LEN)
+		return -EINVAL;
+
+	memset(rv, 0, sizeof(rv));
+	memcpy(rv, rand->val, rand->len);
+	rv_bitlen = rand->len * 8;
+	rv_len = rand->len;
+
+	memset(m, 0, sizeof(m));
+	memcpy(m, msg->val, msg->len);
+	m_bitlen = msg->len * 8;
+
+	if (m_bitlen >= (rv_bitlen - 1)) {
+		m[msg->len] = 0x80;
+		m_bitlen += 8;
+	} else {
+		m[msg->len] = 0x80;
+		m_bitlen += (rv_bitlen - m_bitlen - 8);
+	}
+
+	count = m_bitlen / rv_bitlen;
+	remain = m_bitlen % rv_bitlen;
+	for (i = 0; i < count * rv_len; i++)
+		m[i] ^= rv[i % rv_len];
+
+	for (j = 0; j < remain / 8; j++)
+		m[i + j] ^= rv[j];
+
+	m[i + j] = ((uint8_t *)&rv_bitlen)[0];
+	m[i + j + 1] = (((uint8_t *)&rv_bitlen)[1] >> 8) & 0xFF;
+
+	rte_free(msg->val);
+	msg->len = (rv_bitlen + m_bitlen + 16) / 8;
+	msg->val = rte_zmalloc(NULL, msg->len, 0);
+	if (!msg->val)
+		return -EPERM;
+
+	memcpy(msg->val, rv, rv_len);
+	memcpy(&msg->val[rv_len], m, (m_bitlen + 16) / 8);
+	return 0;
+}
+
+static int
+parse_siggen_message_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(val, &vec.rsa.seed);
+
+	return ret;
+}
+
+static int
+parse_sigver_randomvalue_str(const char *key, char *src, struct fips_val *val)
+{
+	int ret = 0;
+
+	parse_uint8_hex_str(key, src, val);
+	if (info.interim_info.rsa_data.random_msg)
+		ret = fips_test_randomize_message(&vec.pt, val);
+
+	return ret;
+}
+
 struct fips_test_callback rsa_keygen_interim_json_vectors[] = {
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
@@ -447,6 +552,7 @@ struct fips_test_callback rsa_siggen_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{TESTTYPE_JSON_STR, parse_interim_str, NULL},
 		{NULL, NULL, NULL} /**< end pointer */
@@ -456,6 +562,7 @@ struct fips_test_callback rsa_sigver_interim_json_vectors[] = {
 		{SIGTYPE_JSON_STR, parse_interim_str, NULL},
 		{MOD_JSON_STR, parse_interim_str, NULL},
 		{HASH_JSON_STR, parse_interim_str, NULL},
+		{CONFORMANCE_JSON_STR, parse_interim_str, NULL},
 		{SALT_JSON_STR, parse_interim_str, NULL},
 		{N_JSON_STR, parse_uint8_hex_str, &vec.rsa.n},
 		{E_JSON_STR, parse_uint8_hex_str, &vec.rsa.e},
@@ -470,13 +577,14 @@ struct fips_test_callback rsa_keygen_json_vectors[] = {
 };
 
 struct fips_test_callback rsa_siggen_json_vectors[] = {
-		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
+		{MSG_JSON_STR, parse_siggen_message_str, &vec.pt},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
 struct fips_test_callback rsa_sigver_json_vectors[] = {
 		{MSG_JSON_STR, parse_uint8_hex_str, &vec.pt},
 		{SIG_JSON_STR, parse_uint8_hex_str, &vec.rsa.signature},
+		{RV_JSON_STR, parse_sigver_randomvalue_str, &vec.rsa.seed},
 		{NULL, NULL, NULL} /**< end pointer */
 };
 
@@ -492,6 +600,7 @@ parse_test_rsa_json_init(void)
 	info.parse_writeback = NULL;
 	info.interim_callbacks = NULL;
 	info.parse_interim_writeback = NULL;
+	info.interim_info.rsa_data.random_msg = 0;
 
 	if (strcmp(mode_str, "keyGen") == 0) {
 		info.op = FIPS_TEST_ASYM_KEYGEN;
@@ -506,6 +615,7 @@ parse_test_rsa_json_init(void)
 		info.op = FIPS_TEST_ASYM_SIGVER;
 		info.callbacks = rsa_sigver_json_vectors;
 		info.interim_callbacks = rsa_sigver_interim_json_vectors;
+		info.parse_interim_writeback = parse_test_rsa_json_interim_writeback;
 	} else {
 		return -EINVAL;
 	}
-- 
2.25.1


^ permalink raw reply	[flat|nested] 39+ messages in thread

* RE: [v7 0/3] FIPS asymmetric validation
  2022-10-12  6:12           ` [v7 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
                               ` (2 preceding siblings ...)
  2022-10-12  6:12             ` [v7 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
@ 2022-10-12 18:44             ` Akhil Goyal
  3 siblings, 0 replies; 39+ messages in thread
From: Akhil Goyal @ 2022-10-12 18:44 UTC (permalink / raw)
  To: Gowrishankar Muthukrishnan, dev
  Cc: Anoob Joseph, Brian Dooley, Jerin Jacob Kollanukkaran,
	Gowrishankar Muthukrishnan

> Subject: [v7 0/3] FIPS asymmetric validation
> 
> This patch series adds support in fips_validation app to perform
> asymmetric validation. To start with, RSA algorithm is used in
> the evaluation. For the key value pairs which is multiprecision
> in arithmetic, openssl library is used.
> 
> Changes:
>  v7:
>   - fix test to handle app parameter correctly.
>  v6:
>   - checkpatch related fix.
>  v5:
>   - Release notes.
>  v4:
>   - AES GMAC callback fixes.
>  v3:
>   - patches 5,6 and 7 in v2 are rebased and submitted here.
>  v2:
>   - minor fixes in v1
>   - addition of digest encoding for fips validation
>   - addition of message randomization for fips conformance tests.
> 
> Gowrishankar Muthukrishnan (3):
>   examples/fips_validation: add asymmetric validation
>   examples/fips_validation: encode digest with hash OID
>   examples/fips_validation: randomize message for conformance test
> 
>  config/meson.build                            |   6 +
>  doc/guides/rel_notes/release_22_11.rst        |   5 +
>  doc/guides/sample_app_ug/fips_validation.rst  |   1 +
>  examples/fips_validation/fips_validation.c    |   2 +
>  examples/fips_validation/fips_validation.h    |  51 +-
>  .../fips_validation/fips_validation_gcm.c     |   8 +-
>  .../fips_validation/fips_validation_rsa.c     | 630 ++++++++++++++++++
>  examples/fips_validation/main.c               | 556 +++++++++++++---
>  examples/fips_validation/meson.build          |   6 +
>  9 files changed, 1167 insertions(+), 98 deletions(-)
>  create mode 100644 examples/fips_validation/fips_validation_rsa.c
> 
Applied to dpdk-next-crypto

Thanks.

^ permalink raw reply	[flat|nested] 39+ messages in thread

end of thread, other threads:[~2022-10-12 18:44 UTC | newest]

Thread overview: 39+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-08-12 11:57 [PATCH v1 0/5] FIPS asymmetric validation Gowrishankar Muthukrishnan
2022-08-12 11:57 ` [PATCH v1 1/5] examples/fips_validation: fix parsing test group info Gowrishankar Muthukrishnan
2022-08-12 11:57 ` [PATCH v1 2/5] examples/fips_validation: add interim parse writeback Gowrishankar Muthukrishnan
2022-08-12 11:57 ` [PATCH v1 3/5] examples/fips_validation: add function to calculate SHA hash size Gowrishankar Muthukrishnan
2022-08-12 11:57 ` [PATCH v1 4/5] examples/fips_validation: fix buffer size to parse JSON string Gowrishankar Muthukrishnan
2022-08-12 11:57 ` [PATCH v1 5/5] examples/fips_validation: add asymmetric validation Gowrishankar Muthukrishnan
2022-09-23 16:29 ` [PATCH v1 0/5] FIPS " Dooley, Brian
2022-09-27  7:26 ` [v2 0/7] " Gowrishankar Muthukrishnan
2022-09-27  7:26   ` [v2 1/7] examples/fips_validation: fix parsing test group info Gowrishankar Muthukrishnan
2022-09-27  7:26   ` [v2 2/7] examples/fips_validation: add interim parse writeback Gowrishankar Muthukrishnan
2022-09-27  7:26   ` [v2 3/7] examples/fips_validation: add function to calculate SHA hash size Gowrishankar Muthukrishnan
2022-10-07 17:52     ` Akhil Goyal
2022-09-27  7:26   ` [v2 4/7] examples/fips_validation: fix buffer size to parse JSON string Gowrishankar Muthukrishnan
2022-09-27  7:26   ` [v2 5/7] examples/fips_validation: add asymmetric validation Gowrishankar Muthukrishnan
2022-09-27  7:26   ` [v2 6/7] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
2022-09-27  7:26   ` [v2 7/7] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
2022-10-07  9:52   ` [v2 0/7] FIPS asymmetric validation Akhil Goyal
2022-10-11  9:26   ` [v3 0/3] " Gowrishankar Muthukrishnan
2022-10-11  9:26     ` [v3 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
2022-10-11  9:26     ` [v3 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
2022-10-11  9:26     ` [v3 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
2022-10-11 15:37     ` [v3 0/3] FIPS asymmetric validation Akhil Goyal
2022-10-11 16:08     ` [v4 " Gowrishankar Muthukrishnan
2022-10-11 16:08       ` [v4 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
2022-10-11 16:08       ` [v4 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
2022-10-11 16:08       ` [v4 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
2022-10-12  3:56       ` [v5 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
2022-10-12  3:56         ` [v5 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
2022-10-12  3:56         ` [v5 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
2022-10-12  3:56         ` [v5 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
2022-10-12  4:05         ` [v6 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
2022-10-12  4:05           ` [v6 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
2022-10-12  4:05           ` [v6 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
2022-10-12  4:05           ` [v6 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
2022-10-12  6:12           ` [v7 0/3] FIPS asymmetric validation Gowrishankar Muthukrishnan
2022-10-12  6:12             ` [v7 1/3] examples/fips_validation: add " Gowrishankar Muthukrishnan
2022-10-12  6:12             ` [v7 2/3] examples/fips_validation: encode digest with hash OID Gowrishankar Muthukrishnan
2022-10-12  6:12             ` [v7 3/3] examples/fips_validation: randomize message for conformance test Gowrishankar Muthukrishnan
2022-10-12 18:44             ` [v7 0/3] FIPS asymmetric validation Akhil Goyal

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).