xtest: pkcs11: add hmac tests

Adds 1008 and 1009 testing hmac algorithms via
- C_SignInit()
- C_Sign()
- C_SignUpdate()
- C_SignFinal()
- C_VerifyInit()
- C_Verify()
- C_VerifyUpdate()
- C_VerifyFinal()

Co-developed-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Etienne Carriere <etienne.carriere@linaro.org>
Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org>
Reviewed-by: Ricardo Salveti <ricardo@foundries.io>
diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c
index c29f2fc..82a620e 100644
--- a/host/xtest/pkcs11_1000.c
+++ b/host/xtest/pkcs11_1000.c
@@ -14,6 +14,8 @@
 #include "xtest_test.h"
 #include "xtest_helpers.h"
 
+#include <regression_4000_data.h>
+
 /*
  * Some PKCS#11 object resources used in the tests
  */
@@ -41,6 +43,24 @@
 	CKM_AES_CTS,
 	(CK_BYTE_PTR)cktest_aes128_iv, sizeof(cktest_aes128_iv),
 };
+static CK_MECHANISM cktest_hmac_md5_mechanism = {
+	CKM_MD5_HMAC, NULL, 0,
+};
+static CK_MECHANISM cktest_hmac_sha1_mechanism = {
+	CKM_SHA_1_HMAC, NULL, 0,
+};
+static CK_MECHANISM cktest_hmac_sha224_mechanism = {
+	CKM_SHA224_HMAC, NULL, 0,
+};
+static CK_MECHANISM cktest_hmac_sha256_mechanism = {
+	CKM_SHA256_HMAC, NULL, 0,
+};
+static CK_MECHANISM cktest_hmac_sha384_mechanism = {
+	CKM_SHA384_HMAC, NULL, 0,
+};
+static CK_MECHANISM cktest_hmac_sha512_mechanism = {
+	CKM_SHA512_HMAC, NULL, 0,
+};
 
 /*
  * Util to find a slot on which to open a session
@@ -1463,3 +1483,407 @@
 }
 ADBG_CASE_DEFINE(pkcs11, 1007, xtest_pkcs11_test_1007,
 		"PKCS11: Check operations release at session closure");
+
+#define CK_MAC_KEY_HMAC(_type, _key_array) \
+	{								\
+		{ CKA_SIGN, 	&(CK_BBOOL){CK_TRUE},			\
+				sizeof(CK_BBOOL) },			\
+		{ CKA_VERIFY, 	&(CK_BBOOL){CK_TRUE},			\
+				sizeof(CK_BBOOL) },			\
+		{ CKA_CLASS,	&(CK_OBJECT_CLASS){CKO_SECRET_KEY},	\
+				sizeof(CK_OBJECT_CLASS) },		\
+		{ CKA_KEY_TYPE,	&(CK_KEY_TYPE){_type},			\
+				sizeof(CK_KEY_TYPE) },			\
+		{ CKA_VALUE,	(void *)(_key_array),			\
+				sizeof(_key_array) }			\
+	}
+
+static CK_ATTRIBUTE cktest_hmac_md5_key[] =
+	CK_MAC_KEY_HMAC(CKK_MD5_HMAC, mac_data_md5_key1);
+
+static CK_ATTRIBUTE cktest_hmac_sha1_key[] =
+	CK_MAC_KEY_HMAC(CKK_SHA_1_HMAC, mac_data_sha1_key1);
+
+static CK_ATTRIBUTE cktest_hmac_sha224_key[] =
+	CK_MAC_KEY_HMAC(CKK_SHA224_HMAC, mac_data_sha224_key1);
+
+static CK_ATTRIBUTE cktest_hmac_sha256_key1[] =
+	CK_MAC_KEY_HMAC(CKK_SHA256_HMAC, mac_data_sha256_key1);
+
+static CK_ATTRIBUTE cktest_hmac_sha256_key2[] =
+	CK_MAC_KEY_HMAC(CKK_SHA256_HMAC, mac_data_sha256_key2);
+
+static CK_ATTRIBUTE cktest_hmac_sha384_key[] =
+	CK_MAC_KEY_HMAC(CKK_SHA384_HMAC, mac_data_sha384_key1);
+
+static CK_ATTRIBUTE cktest_hmac_sha512_key[] =
+	CK_MAC_KEY_HMAC(CKK_SHA512_HMAC, mac_data_sha512_key1);
+
+struct mac_test {
+	CK_ATTRIBUTE_PTR attr_key;
+	CK_ULONG attr_count;
+	CK_MECHANISM_PTR mechanism;
+	size_t in_incr;
+	const uint8_t *in;
+	size_t in_len;
+	const uint8_t *out;
+	size_t out_len;
+	bool multiple_incr;
+};
+
+#define CKTEST_MAC_TEST(key, mecha, input_incr, input, output, incr) {	\
+		.attr_key = key,		\
+		.attr_count = ARRAY_SIZE(key),	\
+		.mechanism = mecha,		\
+		.in_incr = input_incr,		\
+		.in = input,				\
+		.in_len = ARRAY_SIZE(input),		\
+		.out = output,				\
+		.out_len = ARRAY_SIZE(output),		\
+		.multiple_incr = incr			\
+	}
+
+static const struct mac_test cktest_mac_cases[] = {
+	CKTEST_MAC_TEST(cktest_hmac_md5_key, &cktest_hmac_md5_mechanism,
+			4, mac_data_md5_in1, mac_data_md5_out1, false),
+	CKTEST_MAC_TEST(cktest_hmac_sha1_key, &cktest_hmac_sha1_mechanism,
+			5, mac_data_sha1_in1, mac_data_sha1_out1, false),
+	CKTEST_MAC_TEST(cktest_hmac_sha224_key, &cktest_hmac_sha224_mechanism,
+			8, mac_data_sha224_in1, mac_data_sha224_out1, false),
+	CKTEST_MAC_TEST(cktest_hmac_sha256_key1, &cktest_hmac_sha256_mechanism,
+			1, mac_data_sha256_in1, mac_data_sha256_out1, false),
+	CKTEST_MAC_TEST(cktest_hmac_sha256_key2, &cktest_hmac_sha256_mechanism,
+			7, mac_data_sha256_in2, mac_data_sha256_out2, false),
+	CKTEST_MAC_TEST(cktest_hmac_sha384_key, &cktest_hmac_sha384_mechanism,
+			11, mac_data_sha384_in1, mac_data_sha384_out1, false),
+	CKTEST_MAC_TEST(cktest_hmac_sha512_key, &cktest_hmac_sha512_mechanism,
+			13, mac_data_sha512_in1, mac_data_sha512_out1, false),
+};
+
+static void xtest_pkcs11_test_1008(ADBG_Case_t *c)
+{
+	CK_RV rv = CKR_GENERAL_ERROR;
+	CK_SLOT_ID slot = 0;
+	CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
+	CK_FLAGS session_flags = CKF_SERIAL_SESSION;
+	CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE;
+	uint8_t out[512] = { 0 };
+	CK_ULONG out_size = 0;
+	struct mac_test const *test = NULL;
+	size_t n = 0;
+
+	rv = init_lib_and_find_token_slot(&slot);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		return;
+
+	rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto err_close_lib;
+
+	for (n = 0; n < ARRAY_SIZE(cktest_mac_cases); n++) {
+
+		test = &cktest_mac_cases[n];
+		Do_ADBG_BeginSubCase(c, "Sign case %zu algo (%s)", n,
+				     ckm2str(test->mechanism->mechanism));
+
+		rv = C_CreateObject(session, test->attr_key, test->attr_count,
+				    &key_handle);
+		if (!ADBG_EXPECT_CK_OK(c, rv))
+			goto err;
+
+		/* Test signature in 1 step */
+		if (test->in != NULL) {
+			rv = C_SignInit(session, test->mechanism, key_handle);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_SignUpdate(session,
+					  (void *)test->in, test->in_len);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			/* Test too short buffer case */
+			out_size = 1;
+			rv = C_SignFinal(session, out, &out_size);
+			if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv))
+				goto err_destr_obj;
+
+			/*
+			 * Test NULL buffer case with size as 0
+			 * to get the out_size
+			 */
+			out_size = 0;
+			rv = C_SignFinal(session, NULL, &out_size);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			/* Get to full output */
+			memset(out, 0, out_size);
+			rv = C_SignFinal(session, out, &out_size);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			(void)ADBG_EXPECT_BUFFER(c, test->out,
+						 test->out_len,
+						 out, out_size);
+		}
+
+		/* Test 2 step update signature */
+		rv = C_SignInit(session, test->mechanism, key_handle);
+		if (!ADBG_EXPECT_CK_OK(c, rv))
+			goto err_destr_obj;
+
+		if (test->in != NULL) {
+			rv = C_SignUpdate(session,
+					  (void *)test->in, test->in_incr);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_SignUpdate(session,
+					  (void *)(test->in + test->in_incr),
+					  test->in_len - test->in_incr);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+		}
+
+		out_size = sizeof(out);
+		memset(out, 0, sizeof(out));
+
+		rv = C_SignFinal(session, out, &out_size);
+		if (!ADBG_EXPECT_CK_OK(c, rv))
+			goto err_destr_obj;
+
+		(void)ADBG_EXPECT_BUFFER(c, test->out,
+					 test->out_len, out, out_size);
+
+		/* Test 3 signature in one shot */
+		if (test->in != NULL) {
+			rv = C_SignInit(session, test->mechanism, key_handle);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			/* Test too short buffer case */
+			out_size = 1;
+			rv = C_Sign(session,(void *)test->in, test->in_len,
+				    out, &out_size);
+			if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv))
+				goto err_destr_obj;
+
+			/*
+			 * Test NULL buffer case with size as 0
+			 * to get the out_size
+			 */
+			out_size = 0;
+			rv = C_Sign(session, (void *)test->in, test->in_len,
+				    NULL, &out_size);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			/* Get to full output */
+			memset(out, 0, out_size);
+			rv = C_Sign(session,(void *)test->in, test->in_len,
+				    out, &out_size);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			(void)ADBG_EXPECT_BUFFER(c, test->out,
+						 test->out_len,
+						 out, out_size);
+		}
+
+		rv = C_DestroyObject(session, key_handle);
+		if (!ADBG_EXPECT_CK_OK(c, rv))
+			goto err;
+
+		Do_ADBG_EndSubCase(c, NULL);
+	}
+	goto out;
+
+err_destr_obj:
+	ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
+err:
+	Do_ADBG_EndSubCase(c, NULL);
+out:
+	ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
+err_close_lib:
+	ADBG_EXPECT_CK_OK(c, close_lib());
+}
+ADBG_CASE_DEFINE(pkcs11, 1008, xtest_pkcs11_test_1008,
+		 "PKCS11: Check Compliance of C_Sign - HMAC algorithms");
+
+static void xtest_pkcs11_test_1009(ADBG_Case_t *c)
+{
+	CK_RV rv = CKR_GENERAL_ERROR;
+	CK_SLOT_ID slot = 0;
+	CK_SESSION_HANDLE session = CK_INVALID_HANDLE;
+	CK_FLAGS session_flags = CKF_SERIAL_SESSION;
+	CK_OBJECT_HANDLE key_handle = CK_INVALID_HANDLE;
+	struct mac_test const *test = NULL;
+	size_t n = 0;
+
+	rv = init_lib_and_find_token_slot(&slot);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		return;
+
+	rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto err_close_lib;
+
+	for (n = 0; n < ARRAY_SIZE(cktest_mac_cases); n++) {
+
+		test = &cktest_mac_cases[n];
+		Do_ADBG_BeginSubCase(c, "Verify case %zu algo (%s)", n,
+				     ckm2str(test->mechanism->mechanism));
+
+		rv = C_CreateObject(session, test->attr_key, test->attr_count,
+				    &key_handle);
+		if (!ADBG_EXPECT_CK_OK(c, rv))
+			goto err;
+
+		/* Test Verification in 1 step */
+		if (test->in != NULL) {
+			rv = C_VerifyInit(session, test->mechanism, key_handle);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_VerifyUpdate(session, (void *)test->in,
+					    test->in_len);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_VerifyFinal(session,
+					   (void *)test->out, test->out_len);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+		}
+
+		/* Test 2 step update verification*/
+		rv = C_VerifyInit(session, test->mechanism, key_handle);
+		if (!ADBG_EXPECT_CK_OK(c, rv))
+			goto err_destr_obj;
+
+		if (test->in != NULL) {
+			rv = C_VerifyUpdate(session,
+					    (void *)test->in, test->in_incr);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_VerifyUpdate(session,
+					    (void *)(test->in + test->in_incr),
+					    test->in_len - test->in_incr);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+		}
+
+		rv = C_VerifyFinal(session, (void *)test->out, test->out_len);
+		if (!ADBG_EXPECT_CK_OK(c, rv))
+			goto err_destr_obj;
+
+		/* Error as Operation has already completed */
+		rv = C_Verify(session,
+			      (void *)test->in, test->in_len,
+			      (void *)test->out, test->out_len);
+		if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_NOT_INITIALIZED,
+					   rv))
+			goto err_destr_obj;
+
+		/* Test 3 verification in one shot */
+		if (test->in != NULL) {
+			rv = C_VerifyInit(session, test->mechanism, key_handle);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_Verify(session,
+				      (void *)test->in, test->in_len,
+				      (void *)test->out, test->out_len);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			/* Try calling Verify again */
+			rv = C_Verify(session,
+				      (void *)test->in, test->in_len,
+				      (void *)test->out, test->out_len);
+			if (!ADBG_EXPECT_CK_RESULT(c,
+						  CKR_OPERATION_NOT_INITIALIZED,
+						  rv))
+				goto err_destr_obj;
+		}
+
+		/*
+		 * Test 4 verification 
+		 * Error - Signature Length Range with C_VerifyFinal
+		 */
+		if (test->in != NULL) {
+			rv = C_VerifyInit(session, test->mechanism, key_handle);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_VerifyUpdate(session, (void *)test->in,
+					    test->in_len);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_VerifyFinal(session, (void *)test->out, 3);
+			if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE,
+						   rv))
+				goto err_destr_obj;
+		}
+
+		/*
+		 * Test 5 verification
+		 * Error - Signature Length Range with C_Verify
+		 */
+		if (test->in != NULL) {
+			rv = C_VerifyInit(session, test->mechanism, key_handle);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_Verify(session,
+				      (void *)test->in, test->in_len,
+				      (void *)test->out, 0);
+			if (!ADBG_EXPECT_CK_RESULT(c, CKR_SIGNATURE_LEN_RANGE,
+						   rv))
+				goto err_destr_obj;
+		}
+
+		/* Test 6 verification - Invalid Operation sequence */
+		if (test->in != NULL) {
+			rv = C_VerifyInit(session, test->mechanism, key_handle);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			rv = C_Verify(session,
+				      (void *)test->in, test->in_len,
+				      (void *)test->out, test->out_len);
+			if (!ADBG_EXPECT_CK_OK(c, rv))
+				goto err_destr_obj;
+
+			/* Init session has already terminated with C_Verify */
+			rv = C_VerifyUpdate(session, (void *)test->in,
+					    test->in_len);
+			if (!ADBG_EXPECT_CK_RESULT(c,
+						  CKR_OPERATION_NOT_INITIALIZED,
+						  rv))
+				goto err_destr_obj;
+		}
+
+		rv = C_DestroyObject(session, key_handle);
+		if (!ADBG_EXPECT_CK_OK(c, rv))
+			goto err;
+
+		Do_ADBG_EndSubCase(c, NULL);
+	}
+	goto out;
+
+err_destr_obj:
+	ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_handle));
+err:
+	Do_ADBG_EndSubCase(c, NULL);
+out:
+	ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
+err_close_lib:
+	ADBG_EXPECT_CK_OK(c, close_lib());
+}
+ADBG_CASE_DEFINE(pkcs11, 1009, xtest_pkcs11_test_1009,
+		 "PKCS11: Check Compliance of C_Verify - HMAC Algorithms");