diff --git a/test/common_plat/validation/api/crypto/crypto.h b/test/common_plat/validation/api/crypto/crypto.h
index c25cbb3..49ca512 100644
--- a/test/common_plat/validation/api/crypto/crypto.h
+++ b/test/common_plat/validation/api/crypto/crypto.h
@@ -22,10 +22,14 @@ 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_sha1(void);
-void crypto_test_alg_hmac_sha256(void);
-void crypto_test_alg_hmac_sha512(void);
+void crypto_test_gen_alg_hmac_md5(void);
+void crypto_test_check_alg_hmac_md5(void);
+void crypto_test_gen_alg_hmac_sha1(void);
+void crypto_test_check_alg_hmac_sha1(void);
+void crypto_test_gen_alg_hmac_sha256(void);
+void crypto_test_check_alg_hmac_sha256(void);
+void crypto_test_gen_alg_hmac_sha512(void);
+void crypto_test_check_alg_hmac_sha512(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 42149ac..9af7ba3 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);
@@ -453,6 +463,7 @@ void crypto_test_enc_alg_3des_cbc(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_3DES_CBC,
 			 iv,
 			 NULL,
@@ -488,6 +499,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],
@@ -527,6 +539,7 @@ void crypto_test_dec_alg_3des_cbc(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_3DES_CBC,
 			 iv,
 			 NULL,
@@ -564,6 +577,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],
@@ -610,6 +624,7 @@ void crypto_test_enc_alg_aes128_gcm(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_GCM,
 			 iv,
 			 NULL,
@@ -653,6 +668,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],
@@ -699,6 +715,7 @@ void crypto_test_dec_alg_aes128_gcm(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_GCM,
 			 iv,
 			 NULL,
@@ -743,6 +760,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],
@@ -790,6 +808,7 @@ void crypto_test_enc_alg_aes128_cbc(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_CBC,
 			 iv,
 			 NULL,
@@ -825,6 +844,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],
@@ -864,6 +884,7 @@ void crypto_test_dec_alg_aes128_cbc(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
 			 ODP_CIPHER_ALG_AES_CBC,
 			 iv,
 			 NULL,
@@ -901,6 +922,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],
@@ -927,7 +949,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 };
@@ -946,6 +968,7 @@ void crypto_test_alg_hmac_md5(void)
 			continue;
 
 		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
 			 ODP_CIPHER_ALG_NULL,
 			 iv,
 			 iv.data,
@@ -961,6 +984,59 @@ void crypto_test_alg_hmac_md5(void)
 	}
 }
 
+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,
+			 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);
+
+		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);
+	}
+}
+
 static int check_alg_hmac_sha256(void)
 {
 	return check_alg_support(ODP_CIPHER_ALG_NULL, ODP_AUTH_ALG_SHA256_HMAC);
@@ -973,7 +1049,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 };
@@ -994,6 +1070,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,
@@ -1006,6 +1123,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);
 	}
 }
 
@@ -1014,7 +1146,12 @@ static int check_alg_hmac_sha1(void)
 	return check_alg_support(ODP_CIPHER_ALG_NULL, ODP_AUTH_ALG_SHA1_HMAC);
 }
 
-void crypto_test_alg_hmac_sha1(void)
+void crypto_test_gen_alg_hmac_sha1(void)
+{
+	printf(" TEST NOT IMPLEMENTED YET ");
+}
+
+void crypto_test_check_alg_hmac_sha1(void)
 {
 	printf(" TEST NOT IMPLEMENTED YET ");
 }
@@ -1024,7 +1161,12 @@ static int check_alg_hmac_sha512(void)
 	return check_alg_support(ODP_CIPHER_ALG_NULL, ODP_AUTH_ALG_SHA512_HMAC);
 }
 
-void crypto_test_alg_hmac_sha512(void)
+void crypto_test_gen_alg_hmac_sha512(void)
+{
+	printf(" TEST NOT IMPLEMENTED YET ");
+}
+
+void crypto_test_check_alg_hmac_sha512(void)
 {
 	printf(" TEST NOT IMPLEMENTED YET ");
 }
@@ -1078,13 +1220,21 @@ 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_sha1,
+	ODP_TEST_INFO_CONDITIONAL(crypto_test_gen_alg_hmac_sha1,
 				  check_alg_hmac_sha1),
-	ODP_TEST_INFO_CONDITIONAL(crypto_test_alg_hmac_sha256,
+	ODP_TEST_INFO_CONDITIONAL(crypto_test_check_alg_hmac_sha1,
+				  check_alg_hmac_sha1),
+	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_CONDITIONAL(crypto_test_alg_hmac_sha512,
+	ODP_TEST_INFO_CONDITIONAL(crypto_test_gen_alg_hmac_sha512,
+				  check_alg_hmac_sha512),
+	ODP_TEST_INFO_CONDITIONAL(crypto_test_check_alg_hmac_sha512,
 				  check_alg_hmac_sha512),
 	ODP_TEST_INFO_NULL,
 };

From e9d43a75b348fdaab2a5ab96802cd118101902c3 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/8] 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 10 (lumag:crypto-update)
 ** https://github.com/Linaro/odp/pull/10
 ** Patch: https://github.com/Linaro/odp/pull/10.patch
 ** Base sha: e91cf8bb39da24d2a7dbfbb328aa35d1c4cab4ea
 ** Merge commit sha: 2f5b8229a5006f9dffa717fb31aa784093b8ae76
 **/
 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 9af7ba3..e1fc6d4 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
@@ -1042,8 +1042,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 38b2909219f35033e35e951536ff00da7d4f8580 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 3/8] validation: crypto: add HMAC-SHA-1-96 test cases

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
---
/** Email created from pull request 10 (lumag:crypto-update)
 ** https://github.com/Linaro/odp/pull/10
 ** Patch: https://github.com/Linaro/odp/pull/10.patch
 ** Base sha: e91cf8bb39da24d2a7dbfbb328aa35d1c4cab4ea
 ** Merge commit sha: 2f5b8229a5006f9dffa717fb31aa784093b8ae76
 **/
 .../validation/api/crypto/odp_crypto_test_inp.c    | 99 +++++++++++++++++++++-
 .../validation/api/crypto/test_vectors.h           | 44 ++++++++++
 .../validation/api/crypto/test_vectors_len.h       |  6 ++
 3 files changed, 147 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 e1fc6d4..971d141 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
@@ -28,6 +28,8 @@ static const char *auth_alg_name(odp_auth_alg_t auth)
 		return "ODP_AUTH_ALG_NULL";
 	case ODP_AUTH_ALG_MD5_HMAC:
 		return "ODP_AUTH_ALG_MD5_HMAC";
+	case ODP_AUTH_ALG_SHA1_HMAC:
+		return "ODP_AUTH_ALG_SHA1_HMAC";
 	case ODP_AUTH_ALG_SHA256_HMAC:
 		return "ODP_AUTH_ALG_SHA256_HMAC";
 	case ODP_AUTH_ALG_AES_GCM:
@@ -129,9 +131,13 @@ static void alg_test(odp_crypto_op_t op,
 	if (auth_alg == ODP_AUTH_ALG_NULL &&
 	    !(capa.auths.bit.null))
 		rc = -1;
+	if (auth_alg == ODP_AUTH_ALG_SHA1_HMAC &&
+	    !(capa.auths.bit.sha1_hmac))
+		rc = -1;
 	if (auth_alg == ODP_AUTH_ALG_SHA256_HMAC &&
 	    !(capa.auths.bit.sha256_hmac))
 		rc = -1;
+		rc = -1;
 
 	CU_ASSERT(!rc);
 	CU_ASSERT((~capa.auths.all_bits & capa.hw_auths.all_bits) == 0);
@@ -1146,14 +1152,103 @@ static int check_alg_hmac_sha1(void)
 	return check_alg_support(ODP_CIPHER_ALG_NULL, ODP_AUTH_ALG_SHA1_HMAC);
 }
 
+/* This test verifies the correctness of HMAC_SHA1 digest operation.
+ * The output check length is truncated to 12 bytes (96 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
+ * packet buffer as completion event buffer.
+ * */
 void crypto_test_gen_alg_hmac_sha1(void)
 {
-	printf(" TEST NOT IMPLEMENTED YET ");
+	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 };
+
+	unsigned int test_vec_num = (sizeof(hmac_sha1_reference_length) /
+				     sizeof(hmac_sha1_reference_length[0]));
+
+	unsigned int i;
+
+	for (i = 0; i < test_vec_num; i++) {
+		auth_key.data = hmac_sha1_reference_key[i];
+		auth_key.length = sizeof(hmac_sha1_reference_key[i]);
+
+		if (!check_auth_options(ODP_AUTH_ALG_SHA1_HMAC,
+					auth_key.length,
+					HMAC_SHA1_96_CHECK_LEN))
+			continue;
+
+		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_SHA1_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_sha1_reference_plaintext[i],
+			 hmac_sha1_reference_length[i],
+			 NULL, 0,
+			 hmac_sha1_reference_digest[i],
+			 HMAC_SHA1_96_CHECK_LEN);
+	}
 }
 
 void crypto_test_check_alg_hmac_sha1(void)
 {
-	printf(" TEST NOT IMPLEMENTED YET ");
+	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_SHA1_DIGEST_LEN];
+
+	unsigned int test_vec_num = (sizeof(hmac_sha1_reference_length) /
+				     sizeof(hmac_sha1_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_sha1_reference_key[i];
+		auth_key.length = sizeof(hmac_sha1_reference_key[i]);
+
+		if (!check_auth_options(ODP_AUTH_ALG_SHA1_HMAC,
+					auth_key.length,
+					HMAC_SHA1_96_CHECK_LEN))
+			continue;
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_SHA1_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_sha1_reference_plaintext[i],
+			 hmac_sha1_reference_length[i],
+			 NULL, 0,
+			 hmac_sha1_reference_digest[i],
+			 HMAC_SHA1_96_CHECK_LEN);
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 1,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_SHA1_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_sha1_reference_plaintext[i],
+			 hmac_sha1_reference_length[i],
+			 NULL, 0,
+			 wrong_digest,
+			 HMAC_SHA1_96_CHECK_LEN);
+	}
 }
 
 static int check_alg_hmac_sha512(void)
diff --git a/test/common_plat/validation/api/crypto/test_vectors.h b/test/common_plat/validation/api/crypto/test_vectors.h
index da4610f..ce4ca8f 100644
--- a/test/common_plat/validation/api/crypto/test_vectors.h
+++ b/test/common_plat/validation/api/crypto/test_vectors.h
@@ -350,4 +350,48 @@ static uint8_t hmac_sha256_reference_digest[][HMAC_SHA256_DIGEST_LEN] = {
 	  0x85, 0x4d, 0xb8, 0xeb, 0xd0, 0x91, 0x81, 0xa7 }
 };
 
+static uint8_t hmac_sha1_reference_key[][HMAC_SHA1_KEY_LEN] = {
+	{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	  0x0b, 0x0b, 0x0b, 0x0b },
+
+	/* "Jefe" */
+	{ 0x4a, 0x65, 0x66, 0x65 },
+
+	{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	  0xaa, 0xaa, 0xaa, 0xaa }
+};
+
+static uint32_t hmac_sha1_reference_length[] = { 8, 28, 50 };
+
+static uint8_t
+hmac_sha1_reference_plaintext[][HMAC_SHA1_MAX_DATA_LEN] = {
+	/* "Hi There" */
+	{ 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65},
+
+	/* what do ya want for nothing?*/
+	{ 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+	  0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
+	  0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+	  0x69, 0x6e, 0x67, 0x3f },
+
+	{ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd }
+};
+
+static uint8_t hmac_sha1_reference_digest[][HMAC_SHA1_DIGEST_LEN] = {
+	{ 0xb6, 0x17, 0x31, 0x86, 0x55, 0x05,
+	  0x72, 0x64, 0xe2, 0x8b, 0xc0, 0xb6 },
+
+	{ 0xef, 0xfc, 0xdf, 0x6a, 0xe5, 0xeb,
+	  0x2f, 0xa2, 0xd2, 0x74, 0x16, 0xd5 },
+
+	{ 0x12, 0x5d, 0x73, 0x42, 0xb9, 0xac,
+	  0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4 },
+};
+
 #endif
diff --git a/test/common_plat/validation/api/crypto/test_vectors_len.h b/test/common_plat/validation/api/crypto/test_vectors_len.h
index 4fbb5cd..609f430 100644
--- a/test/common_plat/validation/api/crypto/test_vectors_len.h
+++ b/test/common_plat/validation/api/crypto/test_vectors_len.h
@@ -35,4 +35,10 @@
 #define HMAC_SHA256_DIGEST_LEN     32
 #define HMAC_SHA256_128_CHECK_LEN  16
 
+/* HMAC-SHA1 */
+#define HMAC_SHA1_KEY_LEN        20
+#define HMAC_SHA1_MAX_DATA_LEN   128
+#define HMAC_SHA1_DIGEST_LEN     20
+#define HMAC_SHA1_96_CHECK_LEN   12
+
 #endif

From 23856401dfa13c25a1b624def2cc0d084694d567 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 4/8] validation: crypto: add HMAC-SHA-512 test cases

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
---
/** Email created from pull request 10 (lumag:crypto-update)
 ** https://github.com/Linaro/odp/pull/10
 ** Patch: https://github.com/Linaro/odp/pull/10.patch
 ** Base sha: e91cf8bb39da24d2a7dbfbb328aa35d1c4cab4ea
 ** Merge commit sha: 2f5b8229a5006f9dffa717fb31aa784093b8ae76
 **/
 .../validation/api/crypto/odp_crypto_test_inp.c    | 97 +++++++++++++++++++++-
 .../validation/api/crypto/test_vectors.h           | 50 +++++++++++
 .../validation/api/crypto/test_vectors_len.h       |  6 ++
 3 files changed, 151 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 971d141..5c6c081 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
@@ -32,6 +32,8 @@ static const char *auth_alg_name(odp_auth_alg_t auth)
 		return "ODP_AUTH_ALG_SHA1_HMAC";
 	case ODP_AUTH_ALG_SHA256_HMAC:
 		return "ODP_AUTH_ALG_SHA256_HMAC";
+	case ODP_AUTH_ALG_SHA512_HMAC:
+		return "ODP_AUTH_ALG_SHA512_HMAC";
 	case ODP_AUTH_ALG_AES_GCM:
 		return "ODP_AUTH_ALG_AES_GCM";
 	default:
@@ -137,6 +139,8 @@ static void alg_test(odp_crypto_op_t op,
 	if (auth_alg == ODP_AUTH_ALG_SHA256_HMAC &&
 	    !(capa.auths.bit.sha256_hmac))
 		rc = -1;
+	if (auth_alg == ODP_AUTH_ALG_SHA512_HMAC &&
+	    !(capa.auths.bit.sha512_hmac))
 		rc = -1;
 
 	CU_ASSERT(!rc);
@@ -1256,14 +1260,103 @@ static int check_alg_hmac_sha512(void)
 	return check_alg_support(ODP_CIPHER_ALG_NULL, ODP_AUTH_ALG_SHA512_HMAC);
 }
 
+/* This test verifies the correctness of HMAC_SHA512 digest operation.
+ * The output check length is truncated to 32 bytes (256 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
+ * packet buffer as completion event buffer.
+ * */
 void crypto_test_gen_alg_hmac_sha512(void)
 {
-	printf(" TEST NOT IMPLEMENTED YET ");
+	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 };
+
+	unsigned int test_vec_num = (sizeof(hmac_sha512_reference_length) /
+				     sizeof(hmac_sha512_reference_length[0]));
+
+	unsigned int i;
+
+	for (i = 0; i < test_vec_num; i++) {
+		auth_key.data = hmac_sha512_reference_key[i];
+		auth_key.length = sizeof(hmac_sha512_reference_key[i]);
+
+		if (!check_auth_options(ODP_AUTH_ALG_SHA512_HMAC,
+					auth_key.length,
+					HMAC_SHA512_256_CHECK_LEN))
+			continue;
+
+		alg_test(ODP_CRYPTO_OP_ENCODE,
+			 0,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_SHA512_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_sha512_reference_plaintext[i],
+			 hmac_sha512_reference_length[i],
+			 NULL, 0,
+			 hmac_sha512_reference_digest[i],
+			 HMAC_SHA512_256_CHECK_LEN);
+	}
 }
 
 void crypto_test_check_alg_hmac_sha512(void)
 {
-	printf(" TEST NOT IMPLEMENTED YET ");
+	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_SHA512_DIGEST_LEN];
+
+	unsigned int test_vec_num = (sizeof(hmac_sha512_reference_length) /
+				     sizeof(hmac_sha512_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_sha512_reference_key[i];
+		auth_key.length = sizeof(hmac_sha512_reference_key[i]);
+
+		if (!check_auth_options(ODP_AUTH_ALG_SHA512_HMAC,
+					auth_key.length,
+					HMAC_SHA512_256_CHECK_LEN))
+			continue;
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 0,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_SHA512_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_sha512_reference_plaintext[i],
+			 hmac_sha512_reference_length[i],
+			 NULL, 0,
+			 hmac_sha512_reference_digest[i],
+			 HMAC_SHA512_256_CHECK_LEN);
+
+		alg_test(ODP_CRYPTO_OP_DECODE,
+			 1,
+			 ODP_CIPHER_ALG_NULL,
+			 iv,
+			 iv.data,
+			 cipher_key,
+			 ODP_AUTH_ALG_SHA512_HMAC,
+			 auth_key,
+			 NULL, NULL,
+			 hmac_sha512_reference_plaintext[i],
+			 hmac_sha512_reference_length[i],
+			 NULL, 0,
+			 wrong_digest,
+			 HMAC_SHA512_256_CHECK_LEN);
+	}
 }
 
 int crypto_suite_sync_init(void)
diff --git a/test/common_plat/validation/api/crypto/test_vectors.h b/test/common_plat/validation/api/crypto/test_vectors.h
index ce4ca8f..4fddbc4 100644
--- a/test/common_plat/validation/api/crypto/test_vectors.h
+++ b/test/common_plat/validation/api/crypto/test_vectors.h
@@ -394,4 +394,54 @@ static uint8_t hmac_sha1_reference_digest[][HMAC_SHA1_DIGEST_LEN] = {
 	  0x11, 0xcd, 0x91, 0xa3, 0x9a, 0xf4 },
 };
 
+static uint8_t hmac_sha512_reference_key[][HMAC_SHA512_KEY_LEN] = {
+	{ 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	  0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
+	  0x0b, 0x0b, 0x0b, 0x0b },
+
+	/* "Jefe" */
+	{ 0x4a, 0x65, 0x66, 0x65 },
+
+	{ 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	  0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
+	  0xaa, 0xaa, 0xaa, 0xaa }
+};
+
+static uint32_t hmac_sha512_reference_length[] = { 8, 28, 50 };
+
+static uint8_t
+hmac_sha512_reference_plaintext[][HMAC_SHA512_MAX_DATA_LEN] = {
+	/* "Hi There" */
+	{ 0x48, 0x69, 0x20, 0x54, 0x68, 0x65, 0x72, 0x65},
+
+	/* what do ya want for nothing?*/
+	{ 0x77, 0x68, 0x61, 0x74, 0x20, 0x64, 0x6f, 0x20,
+	  0x79, 0x61, 0x20, 0x77, 0x61, 0x6e, 0x74, 0x20,
+	  0x66, 0x6f, 0x72, 0x20, 0x6e, 0x6f, 0x74, 0x68,
+	  0x69, 0x6e, 0x67, 0x3f },
+
+	{ 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
+	  0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd }
+};
+
+static uint8_t hmac_sha512_reference_digest[][HMAC_SHA512_DIGEST_LEN] = {
+	{ 0x87, 0xaa, 0x7c, 0xde, 0xa5, 0xef, 0x61, 0x9d,
+	  0x4f, 0xf0, 0xb4, 0x24, 0x1a, 0x1d, 0x6c, 0xb0,
+	  0x23, 0x79, 0xf4, 0xe2, 0xce, 0x4e, 0xc2, 0x78,
+	  0x7a, 0xd0, 0xb3, 0x05, 0x45, 0xe1, 0x7c, 0xde },
+
+	{ 0x16, 0x4b, 0x7a, 0x7b, 0xfc, 0xf8, 0x19, 0xe2,
+	  0xe3, 0x95, 0xfb, 0xe7, 0x3b, 0x56, 0xe0, 0xa3,
+	  0x87, 0xbd, 0x64, 0x22, 0x2e, 0x83, 0x1f, 0xd6,
+	  0x10, 0x27, 0x0c, 0xd7, 0xea, 0x25, 0x05, 0x54 },
+
+	{ 0xfa, 0x73, 0xb0, 0x08, 0x9d, 0x56, 0xa2, 0x84,
+	  0xef, 0xb0, 0xf0, 0x75, 0x6c, 0x89, 0x0b, 0xe9,
+	  0xb1, 0xb5, 0xdb, 0xdd, 0x8e, 0xe8, 0x1a, 0x36,
+	  0x55, 0xf8, 0x3e, 0x33, 0xb2, 0x27, 0x9d, 0x39 }
+};
+
 #endif
diff --git a/test/common_plat/validation/api/crypto/test_vectors_len.h b/test/common_plat/validation/api/crypto/test_vectors_len.h
index 609f430..3b25ea9 100644
--- a/test/common_plat/validation/api/crypto/test_vectors_len.h
+++ b/test/common_plat/validation/api/crypto/test_vectors_len.h
@@ -41,4 +41,10 @@
 #define HMAC_SHA1_DIGEST_LEN     20
 #define HMAC_SHA1_96_CHECK_LEN   12
 
+/* HMAC-SHA512 */
+#define HMAC_SHA512_KEY_LEN        64
+#define HMAC_SHA512_MAX_DATA_LEN   128
+#define HMAC_SHA512_DIGEST_LEN     64
+#define HMAC_SHA512_256_CHECK_LEN  32
+
 #endif

From 0ece890722d21f74fe8f19aa50bd8779fc7fc308 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 5/8] 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 10 (lumag:crypto-update)
 ** https://github.com/Linaro/odp/pull/10
 ** Patch: https://github.com/Linaro/odp/pull/10.patch
 ** Base sha: e91cf8bb39da24d2a7dbfbb328aa35d1c4cab4ea
 ** Merge commit sha: 2f5b8229a5006f9dffa717fb31aa784093b8ae76
 **/
 .../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 2ba504b..4d59b82 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;
 }
@@ -816,12 +738,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 e35131d66c425f184263fb33b6c9e81d4a6daa17 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 6/8] 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 10 (lumag:crypto-update)
 ** https://github.com/Linaro/odp/pull/10
 ** Patch: https://github.com/Linaro/odp/pull/10.patch
 ** Base sha: e91cf8bb39da24d2a7dbfbb328aa35d1c4cab4ea
 ** Merge commit sha: 2f5b8229a5006f9dffa717fb31aa784093b8ae76
 **/
 .../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 4d59b82..ad4d169 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;
 }
@@ -701,12 +572,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 */
@@ -778,9 +649,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;

From 95fb678e923aa0d32512905ad4f321f33d69bc5e Mon Sep 17 00:00:00 2001
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
Date: Wed, 8 Mar 2017 11:40:51 +0300
Subject: [PATCH 7/8] linux-generic: crypto: add SHA-1 authentication support

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
---
/** Email created from pull request 10 (lumag:crypto-update)
 ** https://github.com/Linaro/odp/pull/10
 ** Patch: https://github.com/Linaro/odp/pull/10.patch
 ** Base sha: e91cf8bb39da24d2a7dbfbb328aa35d1c4cab4ea
 ** Merge commit sha: 2f5b8229a5006f9dffa717fb31aa784093b8ae76
 **/
 platform/linux-generic/odp_crypto.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index ad4d169..6663e48 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -54,6 +54,9 @@ static const odp_crypto_cipher_capability_t cipher_capa_aes_gcm[] = {
 static const odp_crypto_auth_capability_t auth_capa_md5_hmac[] = {
 {.digest_len = 12, .key_len = 16, .aad_len = {.min = 0, .max = 0, .inc = 0} } };
 
+static const odp_crypto_auth_capability_t auth_capa_sha1_hmac[] = {
+{.digest_len = 12, .key_len = 20, .aad_len = {.min = 0, .max = 0, .inc = 0} } };
+
 static const odp_crypto_auth_capability_t auth_capa_sha256_hmac[] = {
 {.digest_len = 16, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} } };
 
@@ -432,7 +435,7 @@ int odp_crypto_capability(odp_crypto_capability_t *capa)
 
 	capa->auths.bit.null         = 1;
 	capa->auths.bit.md5_hmac     = 1;
-	capa->auths.bit.sha1_hmac    = 0;
+	capa->auths.bit.sha1_hmac    = 1;
 	capa->auths.bit.sha256_hmac  = 1;
 	capa->auths.bit.sha512_hmac  = 0;
 	capa->auths.bit.aes_gcm      = 1;
@@ -506,6 +509,10 @@ int odp_crypto_auth_capability(odp_auth_alg_t auth,
 		src = auth_capa_md5_hmac;
 		num = sizeof(auth_capa_md5_hmac) / size;
 		break;
+	case ODP_AUTH_ALG_SHA1_HMAC:
+		src = auth_capa_sha1_hmac;
+		num = sizeof(auth_capa_sha1_hmac) / size;
+		break;
 	case ODP_AUTH_ALG_SHA256_HMAC:
 		src = auth_capa_sha256_hmac;
 		num = sizeof(auth_capa_sha256_hmac) / size;
@@ -611,6 +618,9 @@ odp_crypto_session_create(odp_crypto_session_param_t *param,
 	case ODP_AUTH_ALG_MD5_96:
 		rc = process_auth_param(session, 96, 16, EVP_md5());
 		break;
+	case ODP_AUTH_ALG_SHA1_HMAC:
+		rc = process_auth_param(session, 96, 20, EVP_sha1());
+		break;
 	case ODP_AUTH_ALG_SHA256_HMAC:
 	     /* deprecated */
 	case ODP_AUTH_ALG_SHA256_128:

From 1e10cfe1f819b9e14464263de8e823b9942f8a20 Mon Sep 17 00:00:00 2001
From: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
Date: Wed, 8 Mar 2017 11:40:51 +0300
Subject: [PATCH 8/8] linux-generic: crypto: add HMAC-SHA-512 authentication
 support

Signed-off-by: Dmitry Eremin-Solenikov <dmitry.ereminsolenikov@linaro.org>
---
/** Email created from pull request 10 (lumag:crypto-update)
 ** https://github.com/Linaro/odp/pull/10
 ** Patch: https://github.com/Linaro/odp/pull/10.patch
 ** Base sha: e91cf8bb39da24d2a7dbfbb328aa35d1c4cab4ea
 ** Merge commit sha: 2f5b8229a5006f9dffa717fb31aa784093b8ae76
 **/
 platform/linux-generic/odp_crypto.c | 12 +++++++++++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/platform/linux-generic/odp_crypto.c b/platform/linux-generic/odp_crypto.c
index 6663e48..9ce98a1 100644
--- a/platform/linux-generic/odp_crypto.c
+++ b/platform/linux-generic/odp_crypto.c
@@ -60,6 +60,9 @@ static const odp_crypto_auth_capability_t auth_capa_sha1_hmac[] = {
 static const odp_crypto_auth_capability_t auth_capa_sha256_hmac[] = {
 {.digest_len = 16, .key_len = 32, .aad_len = {.min = 0, .max = 0, .inc = 0} } };
 
+static const odp_crypto_auth_capability_t auth_capa_sha512_hmac[] = {
+{.digest_len = 32, .key_len = 64, .aad_len = {.min = 0, .max = 0, .inc = 0} } };
+
 static const odp_crypto_auth_capability_t auth_capa_aes_gcm[] = {
 {.digest_len = 16, .key_len = 0, .aad_len = {.min = 8, .max = 12, .inc = 4} } };
 
@@ -437,7 +440,7 @@ int odp_crypto_capability(odp_crypto_capability_t *capa)
 	capa->auths.bit.md5_hmac     = 1;
 	capa->auths.bit.sha1_hmac    = 1;
 	capa->auths.bit.sha256_hmac  = 1;
-	capa->auths.bit.sha512_hmac  = 0;
+	capa->auths.bit.sha512_hmac  = 1;
 	capa->auths.bit.aes_gcm      = 1;
 
 	/* Deprecated */
@@ -517,6 +520,10 @@ int odp_crypto_auth_capability(odp_auth_alg_t auth,
 		src = auth_capa_sha256_hmac;
 		num = sizeof(auth_capa_sha256_hmac) / size;
 		break;
+	case ODP_AUTH_ALG_SHA512_HMAC:
+		src = auth_capa_sha512_hmac;
+		num = sizeof(auth_capa_sha512_hmac) / size;
+		break;
 	case ODP_AUTH_ALG_AES_GCM:
 		src = auth_capa_aes_gcm;
 		num = sizeof(auth_capa_aes_gcm) / size;
@@ -626,6 +633,9 @@ odp_crypto_session_create(odp_crypto_session_param_t *param,
 	case ODP_AUTH_ALG_SHA256_128:
 		rc = process_auth_param(session, 128, 32, EVP_sha256());
 		break;
+	case ODP_AUTH_ALG_SHA512_HMAC:
+		rc = process_auth_param(session, 256, 64, EVP_sha512());
+		break;
 	case ODP_AUTH_ALG_AES_GCM:
 	     /* deprecated */
 	case ODP_AUTH_ALG_AES128_GCM:
