diff mbox series

[1/4] validation: crypto: add tests for checking message digests

Message ID 20170406113937.31264-1-maxim.uvarov@linaro.org
State New
Headers show
Series [1/4] validation: crypto: add tests for checking message digests | expand

Commit Message

Maxim Uvarov April 6, 2017, 11:39 a.m. UTC
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>


Currently ODP testsuite only verifies generation of digests. Let's also
verify that checking the digest actually works. Test that check function
will accept valid digest and that it will reject wrong digests.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>

---
/** Email created from pull request 11 (lumag:crypto-update-main)
 ** https://github.com/Linaro/odp/pull/11
 ** Patch: https://github.com/Linaro/odp/pull/11.patch
 ** Base sha: c7014b4848c276c17dcdddab103ce88b3eb29235
 ** Merge commit sha: fce85c94ae08a41d268938b7e8e0c6d1f67d24ea
 **/
 test/common_plat/validation/api/crypto/crypto.h    |   6 +-
 .../validation/api/crypto/odp_crypto_test_inp.c    | 150 ++++++++++++++++++++-
 2 files changed, 147 insertions(+), 9 deletions(-)
diff mbox series

Patch

diff --git a/test/common_plat/validation/api/crypto/crypto.h b/test/common_plat/validation/api/crypto/crypto.h
index 9b909aa..661fe5d 100644
--- a/test/common_plat/validation/api/crypto/crypto.h
+++ b/test/common_plat/validation/api/crypto/crypto.h
@@ -22,8 +22,10 @@  void crypto_test_enc_alg_aes128_gcm(void);
 void crypto_test_enc_alg_aes128_gcm_ovr_iv(void);
 void crypto_test_dec_alg_aes128_gcm(void);
 void crypto_test_dec_alg_aes128_gcm_ovr_iv(void);
-void crypto_test_alg_hmac_md5(void);
-void crypto_test_alg_hmac_sha256(void);
+void crypto_test_gen_alg_hmac_md5(void);
+void crypto_test_check_alg_hmac_md5(void);
+void crypto_test_gen_alg_hmac_sha256(void);
+void crypto_test_check_alg_hmac_sha256(void);
 
 /* test arrays: */
 extern odp_testinfo_t crypto_suite[];
diff --git a/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c b/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c
index 43ddb2f..0909741 100644
--- a/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c
+++ b/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c
@@ -65,6 +65,7 @@  static const char *cipher_alg_name(odp_cipher_alg_t cipher)
  * buffer can be used.
  * */
 static void alg_test(odp_crypto_op_t op,
+		     odp_bool_t should_fail,
 		     odp_cipher_alg_t cipher_alg,
 		     odp_crypto_iv_t ses_iv,
 		     uint8_t *op_iv_ptr,
@@ -239,6 +240,10 @@  static void alg_test(odp_crypto_op_t op,
 		op_params.override_iv_ptr = op_iv_ptr;
 
 	op_params.hash_result_offset = plaintext_len;
+	if (0 != digest_len) {
+		memcpy(data_addr + op_params.hash_result_offset,
+		       digest, digest_len);
+	}
 
 	rc = odp_crypto_operation(&op_params, &posted, &result);
 	if (rc < 0) {
@@ -259,8 +264,15 @@  static void alg_test(odp_crypto_op_t op,
 		odp_crypto_compl_free(compl_event);
 	}
 
-	CU_ASSERT(result.ok);
 	CU_ASSERT(result.pkt == pkt);
+	CU_ASSERT(result.ctx == (void *)0xdeadbeef);
+
+	if (should_fail) {
+		CU_ASSERT(!result.ok);
+		goto cleanup;
+	}
+
+	CU_ASSERT(result.ok);
 
 	if (cipher_alg != ODP_CIPHER_ALG_NULL)
 		CU_ASSERT(!memcmp(data_addr, ciphertext, ciphertext_len));
@@ -268,8 +280,6 @@  static void alg_test(odp_crypto_op_t op,
 	if (op == ODP_CRYPTO_OP_ENCODE && auth_alg != ODP_AUTH_ALG_NULL)
 		CU_ASSERT(!memcmp(data_addr + op_params.hash_result_offset,
 				  digest, digest_len));
-
-	CU_ASSERT(result.ctx == (void *)0xdeadbeef);
 cleanup:
 	rc = odp_crypto_session_destroy(session);
 	CU_ASSERT(!rc);
@@ -445,6 +455,7 @@  void crypto_test_enc_alg_3des_cbc(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_3DES_CBC,
 			 iv,
 			 NULL,
@@ -480,6 +491,7 @@  void crypto_test_enc_alg_3des_cbc_ovr_iv(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_3DES_CBC,
 			 iv,
 			 tdes_cbc_reference_iv[i],
@@ -519,6 +531,7 @@  void crypto_test_dec_alg_3des_cbc(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_3DES_CBC,
 			 iv,
 			 NULL,
@@ -556,6 +569,7 @@  void crypto_test_dec_alg_3des_cbc_ovr_iv(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_3DES_CBC,
 			 iv,
 			 tdes_cbc_reference_iv[i],
@@ -602,6 +616,7 @@  void crypto_test_enc_alg_aes128_gcm(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_GCM,
 			 iv,
 			 NULL,
@@ -645,6 +660,7 @@  void crypto_test_enc_alg_aes128_gcm_ovr_iv(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_GCM,
 			 iv,
 			 aes128_gcm_reference_iv[i],
@@ -691,6 +707,7 @@  void crypto_test_dec_alg_aes128_gcm(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_GCM,
 			 iv,
 			 NULL,
@@ -735,6 +752,7 @@  void crypto_test_dec_alg_aes128_gcm_ovr_iv(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_GCM,
 			 iv,
 			 aes128_gcm_reference_iv[i],
@@ -782,6 +800,7 @@  void crypto_test_enc_alg_aes128_cbc(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_CBC,
 			 iv,
 			 NULL,
@@ -817,6 +836,7 @@  void crypto_test_enc_alg_aes128_cbc_ovr_iv(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_CBC,
 			 iv,
 			 aes128_cbc_reference_iv[i],
@@ -856,6 +876,7 @@  void crypto_test_dec_alg_aes128_cbc(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_CBC,
 			 iv,
 			 NULL,
@@ -893,6 +914,7 @@  void crypto_test_dec_alg_aes128_cbc_ovr_iv(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_CBC,
 			 iv,
 			 aes128_cbc_reference_iv[i],
@@ -919,7 +941,7 @@  static int check_alg_hmac_md5(void)
  * In addition the test verifies if the implementation can use the
  * packet buffer as completion event buffer.
  * */
-void crypto_test_alg_hmac_md5(void)
+void crypto_test_gen_alg_hmac_md5(void)
 {
 	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
 			 auth_key   = { .data = NULL, .length = 0 };
@@ -938,6 +960,45 @@  void crypto_test_alg_hmac_md5(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_MD5_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_md5_reference_plaintext[i],
+			 hmac_md5_reference_length[i],
+			 NULL, 0,
+			 hmac_md5_reference_digest[i],
+			 HMAC_MD5_96_CHECK_LEN);
+	}
+}
+
+void crypto_test_check_alg_hmac_md5(void)
+{
+	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+			 auth_key   = { .data = NULL, .length = 0 };
+	odp_crypto_iv_t iv = { .data = NULL, .length = 0 };
+	uint8_t wrong_digest[HMAC_MD5_DIGEST_LEN];
+
+	unsigned int test_vec_num = (sizeof(hmac_md5_reference_length) /
+				     sizeof(hmac_md5_reference_length[0]));
+	unsigned int i;
+
+	memset(wrong_digest, 0xa5, sizeof(wrong_digest));
+
+	for (i = 0; i < test_vec_num; i++) {
+		auth_key.data = hmac_md5_reference_key[i];
+		auth_key.length = sizeof(hmac_md5_reference_key[i]);
+
+		if (!check_auth_options(ODP_AUTH_ALG_MD5_HMAC, auth_key.length,
+					HMAC_MD5_96_CHECK_LEN))
+			continue;
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_NULL,
 			 iv,
 			 iv.data,
@@ -950,6 +1011,21 @@  void crypto_test_alg_hmac_md5(void)
 			 NULL, 0,
 			 hmac_md5_reference_digest[i],
 			 HMAC_MD5_96_CHECK_LEN);
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 1,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_MD5_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_md5_reference_plaintext[i],
+			 hmac_md5_reference_length[i],
+			 NULL, 0,
+			 wrong_digest,
+			 HMAC_MD5_96_CHECK_LEN);
 	}
 }
 
@@ -965,7 +1041,7 @@  static int check_alg_hmac_sha256(void)
  * In addition the test verifies if the implementation can use the
  * packet buffer as completion event buffer.
  * */
-void crypto_test_alg_hmac_sha256(void)
+void crypto_test_gen_alg_hmac_sha256(void)
 {
 	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
 			 auth_key   = { .data = NULL, .length = 0 };
@@ -986,6 +1062,47 @@  void crypto_test_alg_hmac_sha256(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_SHA256_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_sha256_reference_plaintext[i],
+			 hmac_sha256_reference_length[i],
+			 NULL, 0,
+			 hmac_sha256_reference_digest[i],
+			 HMAC_SHA256_128_CHECK_LEN);
+	}
+}
+
+void crypto_test_check_alg_hmac_sha256(void)
+{
+	odp_crypto_key_t cipher_key = { .data = NULL, .length = 0 },
+			 auth_key   = { .data = NULL, .length = 0 };
+	odp_crypto_iv_t iv = { .data = NULL, .length = 0 };
+	uint8_t wrong_digest[HMAC_SHA256_DIGEST_LEN];
+
+	unsigned int test_vec_num = (sizeof(hmac_sha256_reference_length) /
+				     sizeof(hmac_sha256_reference_length[0]));
+
+	unsigned int i;
+
+	memset(wrong_digest, 0xa5, sizeof(wrong_digest));
+
+	for (i = 0; i < test_vec_num; i++) {
+		auth_key.data = hmac_sha256_reference_key[i];
+		auth_key.length = sizeof(hmac_sha256_reference_key[i]);
+
+		if (!check_auth_options(ODP_AUTH_ALG_SHA256_HMAC,
+					auth_key.length,
+					HMAC_SHA256_128_CHECK_LEN))
+			continue;
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_NULL,
 			 iv,
 			 iv.data,
@@ -998,6 +1115,21 @@  void crypto_test_alg_hmac_sha256(void)
 			 NULL, 0,
 			 hmac_sha256_reference_digest[i],
 			 HMAC_SHA256_128_CHECK_LEN);
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 1,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_SHA256_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_sha256_reference_plaintext[i],
+			 hmac_sha256_reference_length[i],
+			 NULL, 0,
+			 wrong_digest,
+			 HMAC_SHA256_128_CHECK_LEN);
 	}
 }
 
@@ -1050,9 +1182,13 @@  odp_testinfo_t crypto_suite[] = {
 				  check_alg_aes_gcm),
 	ODP_TEST_INFO_CONDITIONAL(crypto_test_dec_alg_aes128_gcm_ovr_iv,
 				  check_alg_aes_gcm),
-	ODP_TEST_INFO_CONDITIONAL(crypto_test_alg_hmac_md5,
+	ODP_TEST_INFO_CONDITIONAL(crypto_test_gen_alg_hmac_md5,
+				  check_alg_hmac_md5),
+	ODP_TEST_INFO_CONDITIONAL(crypto_test_check_alg_hmac_md5,
 				  check_alg_hmac_md5),
-	ODP_TEST_INFO_CONDITIONAL(crypto_test_alg_hmac_sha256,
+	ODP_TEST_INFO_CONDITIONAL(crypto_test_gen_alg_hmac_sha256,
+				  check_alg_hmac_sha256),
+	ODP_TEST_INFO_CONDITIONAL(crypto_test_check_alg_hmac_sha256,
 				  check_alg_hmac_sha256),
 	ODP_TEST_INFO_NULL,
 };

From 778192fa715728f34c6736769c2fde91962a1ec1 Mon Sep 17 00:00:00 2001
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
Date: Wed, 8 Mar 2017 11:22:13 +0300
Subject: [PATCH 2/4] validation: crypto: correct comment for HMAC-SHA-256
 tests

Comment for HMAC-SHA-256 tests talks about HMAC-MD5 and respective
lengths. Correct it to mention SHA-256 and proper digest lengths.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
---
/** Email created from pull request 11 (lumag:crypto-update-main)
 ** https://github.com/Linaro/odp/pull/11
 ** Patch: https://github.com/Linaro/odp/pull/11.patch
 ** Base sha: c7014b4848c276c17dcdddab103ce88b3eb29235
 ** Merge commit sha: fce85c94ae08a41d268938b7e8e0c6d1f67d24ea
 **/
 test/common_plat/validation/api/crypto/odp_crypto_test_inp.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c b/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c
index 0909741..a415f5c 100644
--- a/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c
+++ b/test/common_plat/validation/api/crypto/odp_crypto_test_inp.c
@@ -1034,8 +1034,8 @@  static int check_alg_hmac_sha256(void)
 	return check_alg_support(ODP_CIPHER_ALG_NULL, ODP_AUTH_ALG_SHA256_HMAC);
 }
 
-/* This test verifies the correctness of HMAC_MD5 digest operation.
- * The output check length is truncated to 12 bytes (96 bits) as
+/* This test verifies the correctness of HMAC_SHA256 digest operation.
+ * The output check length is truncated to 16 bytes (128 bits) as
  * returned by the crypto operation API call.
  * Note that hash digest is a one-way operation.
  * In addition the test verifies if the implementation can use the

From 7b5b9a1ffc53499c3cc344d62d41cc936542f73d Mon Sep 17 00:00:00 2001
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
Date: Wed, 8 Mar 2017 05:08:00 +0300
Subject: [PATCH 3/4] linux-generic: crypto: unify auth code

Authentication code contains similar functions. Instead of replicating
them further (e.g. for SHA-1 or SHA-3) factor out common code blocks,
moving all difference to session data.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
---
/** Email created from pull request 11 (lumag:crypto-update-main)
 ** https://github.com/Linaro/odp/pull/11
 ** Patch: https://github.com/Linaro/odp/pull/11.patch
 ** Base sha: c7014b4848c276c17dcdddab103ce88b3eb29235
 ** Merge commit sha: fce85c94ae08a41d268938b7e8e0c6d1f67d24ea
 **/
 .../linux-generic/include/odp_crypto_internal.h    |  14 +--
 platform/linux-generic/odp_crypto.c                | 126 ++++-----------------
 2 files changed, 28 insertions(+), 112 deletions(-)

diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h
index f85b76e..515cefa 100644
--- a/platform/linux-generic/include/odp_crypto_internal.h
+++ b/platform/linux-generic/include/odp_crypto_internal.h
@@ -60,16 +60,10 @@  struct odp_crypto_generic_session {
 	} cipher;
 
 	struct {
-		union {
-			struct {
-				uint8_t  key[16];
-				uint32_t bytes;
-			} md5;
-			struct {
-				uint8_t  key[32];
-				uint32_t bytes;
-			} sha256;
-		} data;
+		uint8_t  key[EVP_MAX_KEY_LENGTH];
+		uint32_t key_length;
+		uint32_t bytes;
+		const EVP_MD *evp_md;
 		crypto_func_t func;
 	} auth;
 };
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index 54b222f..d9b26c0 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -110,8 +110,8 @@  null_crypto_routine(odp_crypto_op_param_t *param ODP_UNUSED,
 }
 
 static
-odp_crypto_alg_err_t md5_gen(odp_crypto_op_param_t *param,
-			     odp_crypto_generic_session_t *session)
+odp_crypto_alg_err_t auth_gen(odp_crypto_op_param_t *param,
+			      odp_crypto_generic_session_t *session)
 {
 	uint8_t *data  = odp_packet_data(param->out_pkt);
 	uint8_t *icv   = data;
@@ -123,94 +123,28 @@  odp_crypto_alg_err_t md5_gen(odp_crypto_op_param_t *param,
 	icv  += param->hash_result_offset;
 
 	/* Hash it */
-	HMAC(EVP_md5(),
-	     session->auth.data.md5.key,
-	     16,
+	HMAC(session->auth.evp_md,
+	     session->auth.key,
+	     session->auth.key_length,
 	     data,
 	     len,
 	     hash,
 	     NULL);
 
 	/* Copy to the output location */
-	memcpy(icv, hash, session->auth.data.md5.bytes);
+	memcpy(icv, hash, session->auth.bytes);
 
 	return ODP_CRYPTO_ALG_ERR_NONE;
 }
 
 static
-odp_crypto_alg_err_t md5_check(odp_crypto_op_param_t *param,
-			       odp_crypto_generic_session_t *session)
-{
-	uint8_t *data  = odp_packet_data(param->out_pkt);
-	uint8_t *icv   = data;
-	uint32_t len   = param->auth_range.length;
-	uint32_t bytes = session->auth.data.md5.bytes;
-	uint8_t  hash_in[EVP_MAX_MD_SIZE];
-	uint8_t  hash_out[EVP_MAX_MD_SIZE];
-
-	/* Adjust pointer for beginning of area to auth */
-	data += param->auth_range.offset;
-	icv  += param->hash_result_offset;
-
-	/* Copy current value out and clear it before authentication */
-	memset(hash_in, 0, sizeof(hash_in));
-	memcpy(hash_in, icv, bytes);
-	memset(icv, 0, bytes);
-	memset(hash_out, 0, sizeof(hash_out));
-
-	/* Hash it */
-	HMAC(EVP_md5(),
-	     session->auth.data.md5.key,
-	     16,
-	     data,
-	     len,
-	     hash_out,
-	     NULL);
-
-	/* Verify match */
-	if (0 != memcmp(hash_in, hash_out, bytes))
-		return ODP_CRYPTO_ALG_ERR_ICV_CHECK;
-
-	/* Matched */
-	return ODP_CRYPTO_ALG_ERR_NONE;
-}
-
-static
-odp_crypto_alg_err_t sha256_gen(odp_crypto_op_param_t *param,
+odp_crypto_alg_err_t auth_check(odp_crypto_op_param_t *param,
 				odp_crypto_generic_session_t *session)
 {
 	uint8_t *data  = odp_packet_data(param->out_pkt);
 	uint8_t *icv   = data;
 	uint32_t len   = param->auth_range.length;
-	uint8_t  hash[EVP_MAX_MD_SIZE];
-
-	/* Adjust pointer for beginning of area to auth */
-	data += param->auth_range.offset;
-	icv  += param->hash_result_offset;
-
-	/* Hash it */
-	HMAC(EVP_sha256(),
-	     session->auth.data.sha256.key,
-	     32,
-	     data,
-	     len,
-	     hash,
-	     NULL);
-
-	/* Copy to the output location */
-	memcpy(icv, hash, session->auth.data.sha256.bytes);
-
-	return ODP_CRYPTO_ALG_ERR_NONE;
-}
-
-static
-odp_crypto_alg_err_t sha256_check(odp_crypto_op_param_t *param,
-				  odp_crypto_generic_session_t *session)
-{
-	uint8_t *data  = odp_packet_data(param->out_pkt);
-	uint8_t *icv   = data;
-	uint32_t len   = param->auth_range.length;
-	uint32_t bytes = session->auth.data.sha256.bytes;
+	uint32_t bytes = session->auth.bytes;
 	uint8_t  hash_in[EVP_MAX_MD_SIZE];
 	uint8_t  hash_out[EVP_MAX_MD_SIZE];
 
@@ -225,9 +159,9 @@  odp_crypto_alg_err_t sha256_check(odp_crypto_op_param_t *param,
 	memset(hash_out, 0, sizeof(hash_out));
 
 	/* Hash it */
-	HMAC(EVP_sha256(),
-	     session->auth.data.sha256.key,
-	     32,
+	HMAC(session->auth.evp_md,
+	     session->auth.key,
+	     session->auth.key_length,
 	     data,
 	     len,
 	     hash_out,
@@ -587,38 +521,26 @@  static int process_des_param(odp_crypto_generic_session_t *session)
 	return 0;
 }
 
-static int process_md5_param(odp_crypto_generic_session_t *session,
-			     uint32_t bits)
+static int process_auth_param(odp_crypto_generic_session_t *session,
+			      uint32_t bits,
+			      uint32_t key_length,
+			      const EVP_MD *evp_md)
 {
 	/* Set function */
 	if (ODP_CRYPTO_OP_ENCODE == session->p.op)
-		session->auth.func = md5_gen;
+		session->auth.func = auth_gen;
 	else
-		session->auth.func = md5_check;
-
-	/* Number of valid bytes */
-	session->auth.data.md5.bytes = bits / 8;
-
-	/* Convert keys */
-	memcpy(session->auth.data.md5.key, session->p.auth_key.data, 16);
-
-	return 0;
-}
+		session->auth.func = auth_check;
 
-static int process_sha256_param(odp_crypto_generic_session_t *session,
-				uint32_t bits)
-{
-	/* Set function */
-	if (ODP_CRYPTO_OP_ENCODE == session->p.op)
-		session->auth.func = sha256_gen;
-	else
-		session->auth.func = sha256_check;
+	session->auth.evp_md = evp_md;
 
 	/* Number of valid bytes */
-	session->auth.data.sha256.bytes = bits / 8;
+	session->auth.bytes = bits / 8;
 
 	/* Convert keys */
-	memcpy(session->auth.data.sha256.key, session->p.auth_key.data, 32);
+	session->auth.key_length = key_length;
+	memcpy(session->auth.key, session->p.auth_key.data,
+	       session->auth.key_length);
 
 	return 0;
 }
@@ -814,12 +736,12 @@  odp_crypto_session_create(odp_crypto_session_param_t *param,
 	case ODP_AUTH_ALG_MD5_HMAC:
 	     /* deprecated */
 	case ODP_AUTH_ALG_MD5_96:
-		rc = process_md5_param(session, 96);
+		rc = process_auth_param(session, 96, 16, EVP_md5());
 		break;
 	case ODP_AUTH_ALG_SHA256_HMAC:
 	     /* deprecated */
 	case ODP_AUTH_ALG_SHA256_128:
-		rc = process_sha256_param(session, 128);
+		rc = process_auth_param(session, 128, 32, EVP_sha256());
 		break;
 	case ODP_AUTH_ALG_AES_GCM:
 	     /* deprecated */

From 9b1d5f564e6eb0c19635240a0b5907975c3f0870 Mon Sep 17 00:00:00 2001
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
Date: Wed, 8 Mar 2017 10:38:09 +0300
Subject: [PATCH 4/4] linux-generic: crypto: switch to EVP interface for cipher
 algorithms

Switch AES-CBC and 3DES-CBC to use generic (EVP) interface instad of low
level interface (as recommended by OpenSSL documentation). This allows
to use the same code path for all non-AEAD ciphers. The only AEAD cipher
(AES-GCM) already uses EVP interface. Generalization of that code can
happen if there will be more AEAD ciphers.

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
---
/** Email created from pull request 11 (lumag:crypto-update-main)
 ** https://github.com/Linaro/odp/pull/11
 ** Patch: https://github.com/Linaro/odp/pull/11.patch
 ** Base sha: c7014b4848c276c17dcdddab103ce88b3eb29235
 ** Merge commit sha: fce85c94ae08a41d268938b7e8e0c6d1f67d24ea
 **/
 .../linux-generic/include/odp_crypto_internal.h    |  16 +-
 platform/linux-generic/odp_crypto.c                | 232 +++++----------------
 2 files changed, 52 insertions(+), 196 deletions(-)

diff --git a/platform/linux-generic/include/odp_crypto_internal.h b/platform/linux-generic/include/odp_crypto_internal.h
index 515cefa..033fa6d 100644
--- a/platform/linux-generic/include/odp_crypto_internal.h
+++ b/platform/linux-generic/include/odp_crypto_internal.h
@@ -11,8 +11,6 @@ 
 extern "C" {
 #endif
 
-#include <openssl/des.h>
-#include <openssl/aes.h>
 #include <openssl/evp.h>
 
 #define MAX_IV_LEN      64
@@ -43,19 +41,7 @@  struct odp_crypto_generic_session {
 		/* Copy of session IV data */
 		uint8_t iv_data[MAX_IV_LEN];
 
-		union {
-			struct {
-				DES_key_schedule ks1;
-				DES_key_schedule ks2;
-				DES_key_schedule ks3;
-			} des;
-			struct {
-				AES_KEY key;
-			} aes;
-			struct {
-				EVP_CIPHER_CTX *ctx;
-			} aes_gcm;
-		} data;
+		EVP_CIPHER_CTX ctx;
 		crypto_func_t func;
 	} cipher;
 
diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index d9b26c0..c8aee1d 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -176,90 +176,6 @@  odp_crypto_alg_err_t auth_check(odp_crypto_op_param_t *param,
 }
 
 static
-odp_crypto_alg_err_t aes_encrypt(odp_crypto_op_param_t *param,
-				 odp_crypto_generic_session_t *session)
-{
-	uint8_t *data  = odp_packet_data(param->out_pkt);
-	uint32_t len   = param->cipher_range.length;
-	unsigned char iv_enc[AES_BLOCK_SIZE];
-	void *iv_ptr;
-
-	if (param->override_iv_ptr)
-		iv_ptr = param->override_iv_ptr;
-	else if (session->p.iv.data)
-		iv_ptr = session->cipher.iv_data;
-	else
-		return ODP_CRYPTO_ALG_ERR_IV_INVALID;
-
-	/*
-	 * Create a copy of the IV.  The DES library modifies IV
-	 * and if we are processing packets on parallel threads
-	 * we could get corruption.
-	 */
-	memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE);
-
-	/* Adjust pointer for beginning of area to cipher */
-	data += param->cipher_range.offset;
-	/* Encrypt it */
-	AES_cbc_encrypt(data, data, len, &session->cipher.data.aes.key,
-			iv_enc, AES_ENCRYPT);
-
-	return ODP_CRYPTO_ALG_ERR_NONE;
-}
-
-static
-odp_crypto_alg_err_t aes_decrypt(odp_crypto_op_param_t *param,
-				 odp_crypto_generic_session_t *session)
-{
-	uint8_t *data  = odp_packet_data(param->out_pkt);
-	uint32_t len   = param->cipher_range.length;
-	unsigned char iv_enc[AES_BLOCK_SIZE];
-	void *iv_ptr;
-
-	if (param->override_iv_ptr)
-		iv_ptr = param->override_iv_ptr;
-	else if (session->p.iv.data)
-		iv_ptr = session->cipher.iv_data;
-	else
-		return ODP_CRYPTO_ALG_ERR_IV_INVALID;
-
-	/*
-	 * Create a copy of the IV.  The DES library modifies IV
-	 * and if we are processing packets on parallel threads
-	 * we could get corruption.
-	 */
-	memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE);
-
-	/* Adjust pointer for beginning of area to cipher */
-	data += param->cipher_range.offset;
-	/* Encrypt it */
-	AES_cbc_encrypt(data, data, len, &session->cipher.data.aes.key,
-			iv_enc, AES_DECRYPT);
-
-	return ODP_CRYPTO_ALG_ERR_NONE;
-}
-
-static int process_aes_param(odp_crypto_generic_session_t *session)
-{
-	/* Verify IV len is either 0 or 16 */
-	if (!((0 == session->p.iv.length) || (16 == session->p.iv.length)))
-		return -1;
-
-	/* Set function */
-	if (ODP_CRYPTO_OP_ENCODE == session->p.op) {
-		session->cipher.func = aes_encrypt;
-		AES_set_encrypt_key(session->p.cipher_key.data, 128,
-				    &session->cipher.data.aes.key);
-	} else {
-		session->cipher.func = aes_decrypt;
-		AES_set_decrypt_key(session->p.cipher_key.data, 128,
-				    &session->cipher.data.aes.key);
-	}
-
-	return 0;
-}
-
-static
 odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param,
 				     odp_crypto_generic_session_t *session)
 {
@@ -269,7 +185,6 @@  odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param,
 	uint8_t *aad_tail = data + param->cipher_range.offset +
 		param->cipher_range.length;
 	uint32_t auth_len = param->auth_range.length;
-	unsigned char iv_enc[AES_BLOCK_SIZE];
 	void *iv_ptr;
 	uint8_t *tag = data + param->hash_result_offset;
 
@@ -286,21 +201,14 @@  odp_crypto_alg_err_t aes_gcm_encrypt(odp_crypto_op_param_t *param,
 	    param->cipher_range.offset + plain_len)
 		return ODP_CRYPTO_ALG_ERR_DATA_SIZE;
 
-	/*
-	 * Create a copy of the IV.  The DES library modifies IV
-	 * and if we are processing packets on parallel threads
-	 * we could get corruption.
-	 */
-	memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE);
-
 	/* Adjust pointer for beginning of area to cipher/auth */
 	uint8_t *plaindata = data + param->cipher_range.offset;
 
 	/* Encrypt it */
-	EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx;
+	EVP_CIPHER_CTX *ctx = &session->cipher.ctx;
 	int cipher_len = 0;
 
-	EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_enc);
+	EVP_EncryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr);
 
 	/* Authenticate header data (if any) without encrypting them */
 	if (aad_head < plaindata) {
@@ -334,7 +242,6 @@  odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param,
 	uint8_t *aad_tail = data + param->cipher_range.offset +
 		param->cipher_range.length;
 	uint32_t auth_len = param->auth_range.length;
-	unsigned char iv_enc[AES_BLOCK_SIZE];
 	void *iv_ptr;
 	uint8_t *tag   = data + param->hash_result_offset;
 
@@ -351,20 +258,13 @@  odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param,
 	    param->cipher_range.offset + cipher_len)
 		return ODP_CRYPTO_ALG_ERR_DATA_SIZE;
 
-	/*
-	 * Create a copy of the IV.  The DES library modifies IV
-	 * and if we are processing packets on parallel threads
-	 * we could get corruption.
-	 */
-	memcpy(iv_enc, iv_ptr, AES_BLOCK_SIZE);
-
 	/* Adjust pointer for beginning of area to cipher/auth */
 	uint8_t *cipherdata = data + param->cipher_range.offset;
 	/* Encrypt it */
-	EVP_CIPHER_CTX *ctx = session->cipher.data.aes_gcm.ctx;
+	EVP_CIPHER_CTX *ctx = &session->cipher.ctx;
 	int plain_len = 0;
 
-	EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_enc);
+	EVP_DecryptInit_ex(ctx, NULL, NULL, NULL, iv_ptr);
 
 	EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, 16, tag);
 
@@ -392,14 +292,15 @@  odp_crypto_alg_err_t aes_gcm_decrypt(odp_crypto_op_param_t *param,
 
 static int process_aes_gcm_param(odp_crypto_generic_session_t *session)
 {
+	EVP_CIPHER_CTX *ctx = &session->cipher.ctx;
+
+	EVP_CIPHER_CTX_init(ctx);
+
 	/* Verify Key len is 16 */
 	if (session->p.cipher_key.length != 16)
 		return -1;
 
 	/* Set function */
-	EVP_CIPHER_CTX *ctx =
-		session->cipher.data.aes_gcm.ctx = EVP_CIPHER_CTX_new();
-
 	if (ODP_CRYPTO_OP_ENCODE == session->p.op) {
 		session->cipher.func = aes_gcm_encrypt;
 		EVP_EncryptInit_ex(ctx, EVP_aes_128_gcm(), NULL, NULL, NULL);
@@ -422,13 +323,14 @@  static int process_aes_gcm_param(odp_crypto_generic_session_t *session)
 }
 
 static
-odp_crypto_alg_err_t des_encrypt(odp_crypto_op_param_t *param,
-				 odp_crypto_generic_session_t *session)
+odp_crypto_alg_err_t cipher_crypt(odp_crypto_op_param_t *param,
+				  odp_crypto_generic_session_t *session)
 {
 	uint8_t *data  = odp_packet_data(param->out_pkt);
 	uint32_t len   = param->cipher_range.length;
-	DES_cblock iv;
 	void *iv_ptr;
+	int cipher_len = 0;
+	int rc;
 
 	if (param->override_iv_ptr)
 		iv_ptr = param->override_iv_ptr;
@@ -437,86 +339,55 @@  odp_crypto_alg_err_t des_encrypt(odp_crypto_op_param_t *param,
 	else
 		return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
-	/*
-	 * Create a copy of the IV.  The DES library modifies IV
-	 * and if we are processing packets on parallel threads
-	 * we could get corruption.
-	 */
-	memcpy(iv, iv_ptr, sizeof(iv));
-
-	/* Adjust pointer for beginning of area to cipher */
-	data += param->cipher_range.offset;
-	/* Encrypt it */
-	DES_ede3_cbc_encrypt(data,
-			     data,
-			     len,
-			     &session->cipher.data.des.ks1,
-			     &session->cipher.data.des.ks2,
-			     &session->cipher.data.des.ks3,
-			     &iv,
-			     1);
-
-	return ODP_CRYPTO_ALG_ERR_NONE;
-}
-
-static
-odp_crypto_alg_err_t des_decrypt(odp_crypto_op_param_t *param,
-				 odp_crypto_generic_session_t *session)
-{
-	uint8_t *data  = odp_packet_data(param->out_pkt);
-	uint32_t len   = param->cipher_range.length;
-	DES_cblock iv;
-	void *iv_ptr;
-
-	if (param->override_iv_ptr)
-		iv_ptr = param->override_iv_ptr;
-	else if (session->p.iv.data)
-		iv_ptr = session->cipher.iv_data;
-	else
+	rc = EVP_CipherInit_ex(&session->cipher.ctx,
+			       NULL, NULL, NULL, iv_ptr, -1);
+	if (odp_unlikely(1 != rc))
 		return ODP_CRYPTO_ALG_ERR_IV_INVALID;
 
-	/*
-	 * Create a copy of the IV.  The DES library modifies IV
-	 * and if we are processing packets on parallel threads
-	 * we could get corruption.
-	 */
-	memcpy(iv, iv_ptr, sizeof(iv));
-
 	/* Adjust pointer for beginning of area to cipher */
 	data += param->cipher_range.offset;
 
-	/* Decrypt it */
-	DES_ede3_cbc_encrypt(data,
-			     data,
-			     len,
-			     &session->cipher.data.des.ks1,
-			     &session->cipher.data.des.ks2,
-			     &session->cipher.data.des.ks3,
-			     &iv,
-			     0);
+	/* En/Decrypt it */
+	EVP_CipherUpdate(&session->cipher.ctx,
+			 data,
+			 &cipher_len,
+			 data,
+			 len);
+
+	EVP_CipherFinal_ex(&session->cipher.ctx,
+			   data + cipher_len,
+			   &cipher_len);
 
 	return ODP_CRYPTO_ALG_ERR_NONE;
 }
 
-static int process_des_param(odp_crypto_generic_session_t *session)
+static int process_cipher_param(odp_crypto_generic_session_t *session,
+				const EVP_CIPHER *cipher)
 {
+	int rc;
+
+	/* Verify Key len is 16 */
+	if ((uint32_t)EVP_CIPHER_key_length(cipher) !=
+			session->p.cipher_key.length)
+		return -1;
+
 	/* Verify IV len is either 0 or 8 */
-	if (!((0 == session->p.iv.length) || (8 == session->p.iv.length)))
+	if (!((0 == session->p.iv.length) ||
+	      ((uint32_t)EVP_CIPHER_iv_length(cipher) == session->p.iv.length)))
 		return -1;
 
 	/* Set function */
-	if (ODP_CRYPTO_OP_ENCODE == session->p.op)
-		session->cipher.func = des_encrypt;
-	else
-		session->cipher.func = des_decrypt;
-
-	/* Convert keys */
-	DES_set_key((DES_cblock *)&session->p.cipher_key.data[0],
-		    &session->cipher.data.des.ks1);
-	DES_set_key((DES_cblock *)&session->p.cipher_key.data[8],
-		    &session->cipher.data.des.ks2);
-	DES_set_key((DES_cblock *)&session->p.cipher_key.data[16],
-		    &session->cipher.data.des.ks3);
+	session->cipher.func = cipher_crypt;
+
+	EVP_CIPHER_CTX_init(&session->cipher.ctx);
+	rc = EVP_CipherInit_ex(&session->cipher.ctx,
+			       cipher,
+			       NULL,
+			       session->p.cipher_key.data,
+			       NULL,
+			       (ODP_CRYPTO_OP_ENCODE == session->p.op) ? 1 : 0);
+	if (odp_unlikely(1 != rc))
+		return -1;
 
 	return 0;
 }
@@ -699,12 +570,12 @@  odp_crypto_session_create(odp_crypto_session_param_t *param,
 		break;
 	case ODP_CIPHER_ALG_DES:
 	case ODP_CIPHER_ALG_3DES_CBC:
-		rc = process_des_param(session);
+		rc = process_cipher_param(session, EVP_des_ede3_cbc());
 		break;
 	case ODP_CIPHER_ALG_AES_CBC:
 	     /* deprecated */
 	case ODP_CIPHER_ALG_AES128_CBC:
-		rc = process_aes_param(session);
+		rc = process_cipher_param(session, EVP_aes_128_cbc());
 		break;
 	case ODP_CIPHER_ALG_AES_GCM:
 	     /* deprecated */
@@ -776,9 +647,8 @@  int odp_crypto_session_destroy(odp_crypto_session_t session)
 	odp_crypto_generic_session_t *generic;
 
 	generic = (odp_crypto_generic_session_t *)(intptr_t)session;
-	if (generic->p.cipher_alg == ODP_CIPHER_ALG_AES128_GCM ||
-	    generic->p.cipher_alg == ODP_CIPHER_ALG_AES_GCM)
-		EVP_CIPHER_CTX_free(generic->cipher.data.aes_gcm.ctx);
+	if (ODP_CIPHER_ALG_NULL != generic->p.cipher_alg)
+		EVP_CIPHER_CTX_cleanup(&generic->cipher.ctx);
 	memset(generic, 0, sizeof(*generic));
 	free_session(generic);
 	return 0;