xtest: pkcs11: Add tests for wrap/unwrap operations

Add test cases to test calling of:
- C_WrapKey
- C_UnwrapKey

Reviewed-by: Etienne Carriere <etienne.carriere@linaro.org>
Reviewed-by: Vesa Jääskeläinen <vesa.jaaskelainen@vaisala.com>
Signed-off-by: Ruchika Gupta <ruchika.gupta@linaro.org>
diff --git a/host/xtest/pkcs11_1000.c b/host/xtest/pkcs11_1000.c
index 6b3bf82..66a9ee3 100644
--- a/host/xtest/pkcs11_1000.c
+++ b/host/xtest/pkcs11_1000.c
@@ -3503,6 +3503,11 @@
 	if (!ADBG_EXPECT_CK_OK(c, rv))
 		goto close_session;
 
+	/*
+	 * All objects in this test are session objects hence released at
+	 * session closure on test completion.
+	 */
+
 	/* Generate a secret key object in rw session */
 	rv = C_GenerateKey(rw_session, &cktest_aes_keygen_mechanism,
 			   secret_key_template,
@@ -5458,3 +5463,639 @@
 }
 ADBG_CASE_DEFINE(pkcs11, 1019, xtest_pkcs11_test_1019,
 		 "PKCS11: Elliptic Curve key generation and signing");
+
+#define WRAPPED_TEST_KEY_SIZE	48
+
+static void xtest_pkcs11_test_1020(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 | CKF_RW_SESSION;
+	CK_OBJECT_HANDLE wrapping_key1 = CK_INVALID_HANDLE;
+	CK_OBJECT_HANDLE wrapping_key2 = CK_INVALID_HANDLE;
+	CK_OBJECT_HANDLE wrapping_key_inv = CK_INVALID_HANDLE;
+	CK_OBJECT_HANDLE key = CK_INVALID_HANDLE;
+	CK_OBJECT_HANDLE key_sz24 = CK_INVALID_HANDLE;
+	CK_OBJECT_HANDLE key_sens = CK_INVALID_HANDLE;
+	CK_OBJECT_HANDLE key_inv = CK_INVALID_HANDLE;
+	CK_OBJECT_HANDLE unwrapped_key = CK_INVALID_HANDLE;
+	CK_ATTRIBUTE set_w_unw_template[] = {
+		{ CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE set_wwt_template[] = {
+		{ CKA_WRAP_WITH_TRUSTED, &(CK_BBOOL){ CK_TRUE },
+		  sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE set_trusted_template[] = {
+		{ CKA_TRUSTED, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE wrap_template[] = {
+		{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE unwrap_template[] = {
+		{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE wrapping_key_template[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+		{ CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE wrapping_key_temp_w_indirect[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+		{ CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_WRAP_TEMPLATE, &wrap_template, sizeof(wrap_template) },
+		{ CKA_UNWRAP_TEMPLATE, &unwrap_template,
+		  sizeof(unwrap_template) },
+	};
+	CK_ATTRIBUTE unwrap_template2[] = {
+		{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
+		  sizeof(CK_OBJECT_CLASS) },
+		{ CKA_KEY_TYPE,	&(CK_KEY_TYPE){ CKK_AES }, sizeof(CK_KEY_TYPE) },
+		{ CKA_TOKEN, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+	};
+	CK_ATTRIBUTE wrapping_key_temp_w_indirect2[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+		{ CKA_WRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_UNWRAP, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_UNWRAP_TEMPLATE, &unwrap_template2,
+		  sizeof(unwrap_template2) },
+	};
+	CK_ATTRIBUTE wrapping_key_template_inv1[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+		{ CKA_WRAP, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE key_template[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+		{ CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE key_template_sens[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+		{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE key_template_inv1[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+		{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_FALSE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE key_sz24_template[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 24 }, sizeof(CK_ULONG) },
+		{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE new_key_template[] = {
+		{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
+		  sizeof(CK_OBJECT_CLASS) },
+		{ CKA_KEY_TYPE,	&(CK_KEY_TYPE){ CKK_GENERIC_SECRET },
+		  sizeof(CK_KEY_TYPE) },
+		{ CKA_ENCRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_DECRYPT, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_SENSITIVE, &(CK_BBOOL){ CK_FALSE}, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE new_key_template_sens[] = {
+		{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
+		  sizeof(CK_OBJECT_CLASS) },
+		{ CKA_KEY_TYPE,	&(CK_KEY_TYPE){ CKK_AES }, sizeof(CK_KEY_TYPE) },
+		{ CKA_EXTRACTABLE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+		{ CKA_SENSITIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE new_key_template2[] = {
+		{ CKA_DERIVE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE new_key_template3[] = {
+		{ CKA_VALUE_LEN, &(CK_ULONG){ 16 }, sizeof(CK_ULONG) },
+		{ CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_ATTRIBUTE new_key_template4[] = {
+		{ CKA_CLASS, &(CK_OBJECT_CLASS){ CKO_SECRET_KEY },
+		  sizeof(CK_OBJECT_CLASS) },
+		{ CKA_KEY_TYPE,	&(CK_KEY_TYPE){ CKK_GENERIC_SECRET },
+		  sizeof(CK_KEY_TYPE) },
+		{ CKA_PRIVATE, &(CK_BBOOL){ CK_TRUE }, sizeof(CK_BBOOL) },
+	};
+	CK_BBOOL g_extract = CK_FALSE;
+	CK_BBOOL g_sensitive = CK_TRUE;
+	CK_BBOOL g_nextract = CK_TRUE;
+	CK_BBOOL g_asensitive = CK_TRUE;
+	CK_BBOOL g_local = CK_TRUE;
+	CK_BBOOL g_token = CK_FALSE;
+	CK_BBOOL g_derive = CK_FALSE;
+	CK_OBJECT_CLASS g_class = CKO_VENDOR_DEFINED;
+	CK_KEY_TYPE g_key_type = CKK_VENDOR_DEFINED;
+	uint8_t g_val[WRAPPED_TEST_KEY_SIZE] = { 0 };
+	CK_ULONG key_len = 0;
+	uint8_t g_unwrapped_val[WRAPPED_TEST_KEY_SIZE] = { 0 };
+	CK_ULONG unwrapped_key_len = 0;
+	/* Keep last attribute as CKA_VALUE */
+	CK_ATTRIBUTE get_template_unwrapped[] = {
+		{ CKA_CLASS, &g_class, sizeof(CK_OBJECT_CLASS) },
+		{ CKA_KEY_TYPE,	&g_key_type, sizeof(CK_KEY_TYPE) },
+		{ CKA_EXTRACTABLE, &g_extract, sizeof(CK_BBOOL) },
+		{ CKA_SENSITIVE, &g_sensitive, sizeof(CK_BBOOL) },
+		{ CKA_NEVER_EXTRACTABLE, &g_nextract, sizeof(CK_BBOOL) },
+		{ CKA_ALWAYS_SENSITIVE, &g_asensitive, sizeof(CK_BBOOL) },
+		{ CKA_LOCAL, &g_local, sizeof(CK_BBOOL) },
+		{ CKA_TOKEN, &g_token, sizeof(CK_BBOOL) },
+		{ CKA_DERIVE, &g_derive, sizeof(CK_BBOOL) },
+		{ CKA_VALUE_LEN, &unwrapped_key_len,
+		  sizeof(unwrapped_key_len) },
+		{ CKA_VALUE, g_unwrapped_val, sizeof(g_unwrapped_val) },
+	};
+	CK_ATTRIBUTE get_template[] = {
+		{ CKA_VALUE_LEN, &key_len, sizeof(key_len) },
+		{ CKA_VALUE, g_val, sizeof(g_val) },
+	};
+	uint8_t buf[WRAPPED_TEST_KEY_SIZE] = { 0 };
+	CK_ULONG size = 0;
+
+	rv = init_lib_and_find_token_slot(&slot);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		return;
+
+	rv = init_test_token(slot);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto close_lib;
+
+	rv = init_user_test_token(slot);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto close_lib;
+
+	rv = C_OpenSession(slot, session_flags, NULL, 0, &session);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto close_lib;
+
+	/* Wrapping Key - AES Key */
+	rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
+			   wrapping_key_template,
+			   ARRAY_SIZE(wrapping_key_template), &wrapping_key1);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto close_session;
+
+	/* Key to be wrapped - AES key */
+	rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
+			   key_template, ARRAY_SIZE(key_template),
+			   &key);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto close_session;
+
+	Do_ADBG_BeginSubCase(c, "Test key wrap with AES ECB");
+
+	/*
+	 * Test NULL buffer and NULL out_size to verify bad argument processing
+	 */
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
+		       NULL, NULL);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_ARGUMENTS_BAD, rv))
+		goto out;
+
+	/*
+	 * Test NULL buffer case with size as 0 to get the out_size
+	 */
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
+		       NULL, &size);
+	if (!ADBG_EXPECT_CK_OK(c, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf)))
+		goto out;
+
+	/*
+	 * Test NULL buffer case with size non zero size to get the out_size
+	 */
+	size = 1;
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
+		       NULL, &size);
+	if (!ADBG_EXPECT_CK_OK(c, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf)))
+		goto out;
+
+	/* Test short buffer */
+	size = 12;
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
+		       buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, <=, sizeof(buf)))
+		goto out;
+
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
+		       buf, &size);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/*
+	 * Get the size of the original key which was wrapped in key_len.
+	 * This will be compared to the length of the key after unwrapping.
+	 */
+	rv = C_GetAttributeValue(session, key, get_template,
+				 ARRAY_SIZE(get_template));
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	Do_ADBG_EndSubCase(c, NULL);
+
+	Do_ADBG_BeginSubCase(c, "Test key unwrap with AES ECB");
+
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf,
+			 size, new_key_template, ARRAY_SIZE(new_key_template),
+			 &unwrapped_key);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/*
+	 * The key created after unwrapping should have CKA_LOCAL = FALSE,
+	 * CKA_ALWAYS_SENSITIVE and CKA_NEVER_EXTRACTABLE as FALSE.
+	 * Default value of CKA_EXTRACTABLE if not specified in the template
+	 * is TRUE. We have deliberately set CKA_SENSITIVE to false for
+	 * both original key and unwrapped_key. This is done to be able to
+	 * extract the value of keys and compare them. This is done mainly
+	 * for testing. In actual examples, we expect CKA_SENSITIVE of keys
+	 * to be wrapped to be TRUE.
+	 */
+	rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped,
+				 ARRAY_SIZE(get_template_unwrapped));
+	if (!ADBG_EXPECT_CK_OK(c, rv) ||
+	    !ADBG_EXPECT_BUFFER(c, g_unwrapped_val, unwrapped_key_len, g_val,
+				key_len) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==,
+					  CKK_GENERIC_SECRET) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE))
+		goto out;
+
+	rv = C_DestroyObject(session, unwrapped_key);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	Do_ADBG_EndSubCase(c, NULL);
+
+	Do_ADBG_BeginSubCase(c, "Invalid UnWrap cases");
+
+	/* Failure when unwrapping as a private session key */
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf,
+			 size, new_key_template4, ARRAY_SIZE(new_key_template4),
+			 &unwrapped_key);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
+		goto out;
+
+	/* Provide incomplete template */
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, buf,
+			 size, new_key_template2, ARRAY_SIZE(new_key_template2),
+			 &unwrapped_key);
+
+	/*
+	 * The error code can also be CKR_TEMPLATE_INCOMPLETE. The
+	 * current implementation returns CKR_TEMPLATE_INCONSISTENT
+	 */
+	if (!ADBG_EXPECT_TRUE(c, rv == CKR_TEMPLATE_INCOMPLETE ||
+				 rv == CKR_TEMPLATE_INCONSISTENT))
+		goto out;
+
+	/* Try unwrapping with a key without CKA_UNWRAP */
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, key, buf, size,
+			 new_key_template, ARRAY_SIZE(new_key_template),
+			 &unwrapped_key);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_UNWRAPPING_KEY_TYPE_INCONSISTENT, rv))
+		goto out;
+
+	Do_ADBG_EndSubCase(c, NULL);
+
+	Do_ADBG_BeginSubCase(c, "Invalid Wrap cases");
+
+	rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
+			   wrapping_key_template_inv1,
+			   ARRAY_SIZE(wrapping_key_template_inv1),
+			   &wrapping_key_inv);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/* Wrapping key used without CKA_WRAP set */
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key_inv,
+		       key, buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, rv))
+		goto out;
+
+	rv = C_DestroyObject(session, wrapping_key_inv);
+	ADBG_EXPECT_CK_OK(c, rv);
+
+	/* Use invalid wrapping key handle */
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key_inv,
+		       key, buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_HANDLE_INVALID, rv))
+		goto out;
+
+	/* CKA_EXTRACTABLE attribute of the key to be wrapped is CKA_FALSE */
+	rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
+			   key_template_inv1, ARRAY_SIZE(key_template_inv1),
+			   &key_inv);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
+		       key_inv, buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_UNEXTRACTABLE, rv))
+		goto out;
+
+	rv = C_DestroyObject(session, key_inv);
+	ADBG_EXPECT_CK_OK(c, rv);
+
+	/* Use invalid key handle */
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
+		       key_inv, buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_HANDLE_INVALID, rv))
+		goto out;
+
+	/* Try wrapping the wrapping key */
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
+		       wrapping_key1, buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_HANDLE_INVALID, rv))
+		goto out;
+
+	/* Use invalid mechanism */
+	rv = C_WrapKey(session, &cktest_hmac_md5_mechanism, wrapping_key1, key,
+		       buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_MECHANISM_INVALID, rv))
+		goto out;
+
+	/* Try wrapping when an operation is already active */
+	rv = C_EncryptInit(session, &cktest_aes_cbc_mechanism, key);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
+		       buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_OPERATION_ACTIVE, rv))
+		goto out;
+
+	rv = C_EncryptFinal(session, NULL, NULL);
+	/* Only check that the operation is no more active */
+	if (!ADBG_EXPECT_TRUE(c, rv != CKR_BUFFER_TOO_SMALL))
+		goto out;
+
+	/*
+	 * Try wrapping using CKK_GENERIC_SECRET when mechanism used is
+	 * AES_ECB. Generate a secret key object in rw session.
+	 */
+	rv = C_GenerateKey(session, &cktest_gensecret_keygen_mechanism,
+			   cktest_generate_gensecret_object_valid1,
+			   ARRAY_SIZE(cktest_generate_gensecret_object_valid1),
+			   &key_inv);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/* Make the Generic secret key wrapping/unwrapping key */
+	rv = C_SetAttributeValue(session, key_inv, set_w_unw_template,
+				 ARRAY_SIZE(set_w_unw_template));
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, key_inv, key, buf,
+		       &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_WRAPPING_KEY_TYPE_INCONSISTENT, rv))
+		goto out;
+
+	rv = C_DestroyObject(session, key_inv);
+	ADBG_EXPECT_CK_OK(c, rv);
+
+	Do_ADBG_EndSubCase(c, NULL);
+
+	Do_ADBG_BeginSubCase(c, "Wrap with different length key");
+
+	/* Generate Key of size 192 bits */
+	rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
+			   key_sz24_template, ARRAY_SIZE(key_sz24_template),
+			   &key_sz24);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	size = 0;
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
+		       key_sz24, buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32))
+		goto out;
+
+	size = 24;
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
+		       key_sz24, buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_BUFFER_TOO_SMALL, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32))
+		goto out;
+
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1,
+		       key_sz24, buf, &size);
+	if (!ADBG_EXPECT_CK_OK(c, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, size, ==, 32))
+		goto out;
+
+	Do_ADBG_EndSubCase(c, NULL);
+
+	Do_ADBG_BeginSubCase(c, "Test Wrap/Unwrap with indirect template");
+
+	/* Wrapping Key with indirect templates - AES Key */
+	rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
+			   wrapping_key_temp_w_indirect,
+			   ARRAY_SIZE(wrapping_key_temp_w_indirect),
+			   &wrapping_key2);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/*
+	 * Attribute mismatch with CKA_WRAP_TEMPLATE.
+	 * Error expected when wrapping a key whose template doesn't match with
+	 * the CKA_WRAP_TEMPLATE in the wrapping_key. In this example, the
+	 * CKA_WRAP_TEMPLATE expects CKA_SENSITIVE of the key to be wrapped to
+	 * be TRUE which is not the case here.
+	 */
+	size = sizeof(buf);
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, key,
+		       buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_HANDLE_INVALID, rv))
+		goto out;
+
+	/* Generate SENSITIVE Key */
+	rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
+			   key_template_sens, ARRAY_SIZE(key_template_sens),
+			   &key_sens);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2,
+		       key_sens, buf, &size);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/*
+	 * Unwrap to create key with SENSITIVE set as FALSE.
+	 * This should fail as indirect attribute CKA_UNWRAP_TEMPLATE restricts
+	 * creation of key with CKA_SENSITIVE as FALSE.
+	 */
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
+			 size, new_key_template, ARRAY_SIZE(new_key_template),
+			 &unwrapped_key);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_TEMPLATE_INCONSISTENT, rv))
+		goto out;
+
+	/* Unwrap a wrapped sensitive key to create a SENSITIVE key */
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
+			 size, new_key_template_sens,
+			 ARRAY_SIZE(new_key_template_sens), &unwrapped_key);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/*
+	 * Get the attributes of created. Skip last attribute in
+	 * get_template_wrapped as that is CKA_VALUE which would give an
+	 * error for a sensitive key
+	 */
+	rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped,
+				 ARRAY_SIZE(get_template_unwrapped) - 1);
+	if (!ADBG_EXPECT_CK_OK(c, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_TRUE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_TRUE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE))
+		goto out;
+
+	if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)) ||
+	    !ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, wrapping_key2)) ||
+	    !ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, key_sens)))
+		goto out;
+
+	/* Create wrapping key with indirect template specifying class & key */
+	rv = C_GenerateKey(session, &cktest_aes_keygen_mechanism,
+			   wrapping_key_temp_w_indirect2,
+			   ARRAY_SIZE(wrapping_key_temp_w_indirect2),
+			   &wrapping_key2);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	size = sizeof(buf);
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, key,
+		       buf, &size);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/* Use minimal new key template just specifying attribute of key */
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
+			 size, new_key_template2, ARRAY_SIZE(new_key_template2),
+			 &unwrapped_key);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped,
+				 ARRAY_SIZE(get_template_unwrapped) - 1);
+
+	/* Destroy created token object */
+	if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)))
+		goto out;
+
+	if (!ADBG_EXPECT_CK_OK(c, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_TRUE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_TRUE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE))
+		goto out;
+
+	/*
+	 * Unwrap with NULL template when CKA_UNWRAP_TEMPLATE has all
+	 * attributes to generate a key
+	 */
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
+			 size, NULL, 0, &unwrapped_key);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	rv = C_GetAttributeValue(session, unwrapped_key, get_template_unwrapped,
+				 ARRAY_SIZE(get_template_unwrapped) - 1);
+
+	/* Destroy created token object */
+	if (!ADBG_EXPECT_CK_OK(c, C_DestroyObject(session, unwrapped_key)))
+		goto out;
+
+	if (!ADBG_EXPECT_CK_OK(c, rv) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, unwrapped_key_len, ==, key_len) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_class, ==, CKO_SECRET_KEY) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_key_type, ==, CKK_AES) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_local, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_token, ==, CK_TRUE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_derive, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_sensitive, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_extract, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_asensitive, ==, CK_FALSE) ||
+	    !ADBG_EXPECT_COMPARE_UNSIGNED(c, g_nextract, ==, CK_FALSE)) {
+		goto out;
+	}
+
+	/* Unwrap and try create a Private token object */
+	rv = C_UnwrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key2, buf,
+			 size, new_key_template3, ARRAY_SIZE(new_key_template3),
+			 &unwrapped_key);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_USER_NOT_LOGGED_IN, rv))
+		goto out;
+
+	Do_ADBG_EndSubCase(c, NULL);
+
+	Do_ADBG_BeginSubCase(c, "Test usage of CKA_WRAP_WITH_TRUSTED");
+
+	/* Set Attribute WRAP_WITH_TRUSTED on the key */
+	rv = C_SetAttributeValue(session, key, set_wwt_template,
+				 ARRAY_SIZE(set_wwt_template));
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	/*
+	 * Try wrapping the key with attribute CKA_WRAP_WITH_TRUSTED with
+	 * normal wrapping key
+	 */
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
+		       buf, &size);
+	if (!ADBG_EXPECT_CK_RESULT(c, CKR_KEY_NOT_WRAPPABLE, rv))
+		goto out;
+
+	/* Login as SO in RW session */
+	rv = C_Login(session, CKU_SO, test_token_so_pin,
+		     sizeof(test_token_so_pin));
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+	rv = C_SetAttributeValue(session, wrapping_key1, set_trusted_template,
+				 ARRAY_SIZE(set_trusted_template));
+	if (!ADBG_EXPECT_CK_OK(c, rv) ||
+	    !ADBG_EXPECT_CK_OK(c, C_Logout(session)))
+		goto out;
+
+	rv = C_WrapKey(session, &cktest_aes_ecb_mechanism, wrapping_key1, key,
+		       buf, &size);
+	if (!ADBG_EXPECT_CK_OK(c, rv))
+		goto out;
+
+out:
+	Do_ADBG_EndSubCase(c, NULL);
+close_session:
+	ADBG_EXPECT_CK_OK(c, C_CloseSession(session));
+
+close_lib:
+	ADBG_EXPECT_CK_OK(c, close_lib());
+}
+ADBG_CASE_DEFINE(pkcs11, 1020, xtest_pkcs11_test_1020,
+		 "PKCS11: AES Key Wrap/UnWrap tests");