blob: 36419dedd5fd908c7f24da8a76eeffc28bf2e564 [file] [log] [blame]
/*
* Copyright (c) 2019, Arm Limited. All rights reserved.
*
* SPDX-License-Identifier: BSD-3-Clause
*
*/
#if DOMAIN_NS == 1
#include <string.h>
#else
#include "secure_fw/core/tfm_memory_utils.h"
#endif
#include "crypto_tests_common.h"
void psa_key_interface_test(const psa_key_type_t key_type,
struct test_result_t *ret)
{
psa_status_t status = PSA_SUCCESS;
uint32_t i = 0;
const psa_key_slot_t slot = TEST_KEY_SLOT;
const uint8_t data[] = "THIS IS MY KEY1";
psa_key_type_t type = PSA_KEY_TYPE_NONE;
size_t bits = 0;
uint8_t exported_data[sizeof(data)] = {0};
size_t exported_data_size = 0;
psa_key_policy_t policy;
/* Setup the key policy */
psa_key_policy_init(&policy);
psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_EXPORT, 0);
status = psa_set_key_policy(slot, &policy);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
status = psa_import_key(slot, key_type, data, sizeof(data));
if (status != PSA_SUCCESS) {
TEST_FAIL("Error importing a key");
return;
}
status = psa_get_key_information(slot, &type, &bits);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error getting key metadata");
return;
}
if (bits != BIT_SIZE_TEST_KEY) {
TEST_FAIL("The number of key bits is different from expected");
return;
}
if (type != PSA_KEY_TYPE_AES) {
TEST_FAIL("The type of the key is different from expected");
return;
}
status = psa_export_key(slot,
exported_data,
sizeof(data),
&exported_data_size);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error exporting a key");
return;
}
if (exported_data_size != BYTE_SIZE_TEST_KEY) {
TEST_FAIL("Number of bytes of exported key different from expected");
return;
}
/* Check that the exported key is the same as the imported one */
for (i=0; i<exported_data_size; i++) {
if (exported_data[i] != data[i]) {
TEST_FAIL("Exported key doesn't match the imported key");
return;
}
}
status = psa_destroy_key(slot);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error destroying the key");
return;
}
status = psa_get_key_information(slot, &type, &bits);
if (status != PSA_ERROR_EMPTY_SLOT) {
TEST_FAIL("Key slot should be empty now");
return;
}
ret->val = TEST_PASSED;
}
void psa_cipher_test(const psa_key_type_t key_type,
const psa_algorithm_t alg,
struct test_result_t *ret)
{
psa_cipher_operation_t handle, handle_dec;
psa_status_t status = PSA_SUCCESS;
const psa_key_slot_t slot = TEST_KEY_SLOT;
const uint8_t data[] = "THIS IS MY KEY1";
psa_key_type_t type = PSA_KEY_TYPE_NONE;
size_t bits = 0;
const size_t iv_length = PSA_BLOCK_CIPHER_BLOCK_SIZE(key_type);
const uint8_t iv[] = "012345678901234";
const uint8_t plain_text[BYTE_SIZE_CHUNK] = "Sixteen bytes!!";
uint8_t decrypted_data[ENC_DEC_BUFFER_SIZE] = {0};
size_t output_length = 0, total_output_length = 0;
uint8_t encrypted_data[ENC_DEC_BUFFER_SIZE] = {0};
uint32_t comp_result;
psa_key_policy_t policy;
psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
uint32_t i;
/* Setup the key policy */
psa_key_policy_init(&policy);
psa_key_policy_set_usage(&policy, usage, alg);
status = psa_set_key_policy(slot, &policy);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
ret->val = TEST_PASSED;
/* Import a key on slot 0 */
status = psa_import_key(slot, key_type, data, sizeof(data));
if (status != PSA_SUCCESS) {
TEST_FAIL("Error importing a key");
return;
}
status = psa_get_key_information(slot, &type, &bits);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error getting key metadata");
goto destroy_key;
}
if (bits != BIT_SIZE_TEST_KEY) {
TEST_FAIL("The number of key bits is different from expected");
goto destroy_key;
}
if (type != key_type) {
TEST_FAIL("The type of the key is different from expected");
goto destroy_key;
}
/* Setup the encryption object */
status = psa_cipher_encrypt_setup(&handle, slot, alg);
if (status != PSA_SUCCESS) {
if (status == PSA_ERROR_NOT_SUPPORTED) {
TEST_FAIL("Algorithm NOT SUPPORTED by the implementation");
} else {
TEST_FAIL("Error setting up cipher operation object");
}
goto destroy_key;
}
/* Set the IV */
status = psa_cipher_set_iv(&handle, iv, iv_length);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error setting the IV on the cypher operation object");
status = psa_cipher_abort(&handle);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
/* Encrypt one chunk of information */
status = psa_cipher_update(&handle, plain_text, BYTE_SIZE_CHUNK,
encrypted_data, ENC_DEC_BUFFER_SIZE,
&output_length);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error encrypting one chunk of information");
status = psa_cipher_abort(&handle);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
if (output_length != BYTE_SIZE_CHUNK) {
TEST_FAIL("Expected encrypted data length is different from expected");
status = psa_cipher_abort(&handle);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
/* Finalise the cipher operation */
status = psa_cipher_finish(&handle, &encrypted_data[output_length],
ENC_DEC_BUFFER_SIZE - output_length,
&output_length);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error finalising the cipher operation");
status = psa_cipher_abort(&handle);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
if (output_length != 0) {
TEST_FAIL("Unexpected output length after finalisation");
goto destroy_key;
}
/* Setup the decryption object */
if (alg == PSA_ALG_CFB_BASE) {
/* In CFB mode the object is always in encryption mode */
status = psa_cipher_encrypt_setup(&handle_dec, slot, alg);
} else {
status = psa_cipher_decrypt_setup(&handle_dec, slot, alg);
}
if (status != PSA_SUCCESS) {
TEST_FAIL("Error setting up cipher operation object");
goto destroy_key;
}
/* Set the IV for decryption */
if (alg == PSA_ALG_CFB_BASE) {
/* In CFB mode the object is in encryption mode, so follow the
* encryption flow.
*/
status = psa_cipher_set_iv(&handle_dec, iv, iv_length);
} else {
status = psa_cipher_update(&handle_dec, iv, iv_length,
encrypted_data, ENC_DEC_BUFFER_SIZE,
&output_length);
}
if (status != PSA_SUCCESS) {
TEST_FAIL("Error setting the IV for decryption");
status = psa_cipher_abort(&handle_dec);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
if (alg != PSA_ALG_CFB_BASE) {
if (output_length != 0) {
TEST_FAIL("Expected output length is different from expected");
status = psa_cipher_abort(&handle_dec);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
}
/* Decrypt */
for (i = 0; i < ENC_DEC_BUFFER_SIZE; i += BYTE_SIZE_CHUNK) {
status = psa_cipher_update(&handle_dec,
(encrypted_data + i), BYTE_SIZE_CHUNK,
(decrypted_data + total_output_length),
(ENC_DEC_BUFFER_SIZE - total_output_length),
&output_length);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error during decryption");
status = psa_cipher_abort(&handle_dec);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
total_output_length += output_length;
}
#if DOMAIN_NS == 1U
/* Check that the plain text matches the decrypted data */
comp_result = memcmp(plain_text, decrypted_data, sizeof(plain_text));
#else
comp_result = tfm_memcmp(plain_text, decrypted_data, sizeof(plain_text));
#endif
if (comp_result != 0) {
TEST_FAIL("Decrypted data doesn't match with plain text");
status = psa_cipher_abort(&handle_dec);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
/* Finalise the cipher operation for decryption (destroys decrypted data) */
status = psa_cipher_finish(&handle_dec, decrypted_data, BYTE_SIZE_CHUNK,
&output_length);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error finalising the cipher operation");
status = psa_cipher_abort(&handle_dec);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error aborting the operation");
}
goto destroy_key;
}
total_output_length += output_length;
/* Check that the decrypted length is equal to the original length */
if (total_output_length != ENC_DEC_BUFFER_SIZE) {
TEST_FAIL("After finalising, unexpected decrypted length");
goto destroy_key;
}
destroy_key:
/* Destroy the key on slot 0 */
status = psa_destroy_key(slot);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error destroying a key");
}
}
void psa_invalid_cipher_test(const psa_key_type_t key_type,
const psa_algorithm_t alg,
const size_t key_size,
struct test_result_t *ret)
{
psa_status_t status;
psa_cipher_operation_t handle;
const psa_key_slot_t slot = TEST_KEY_SLOT;
uint8_t data[TEST_MAX_KEY_LENGTH];
psa_key_policy_t policy;
psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
/* Setup the key policy */
psa_key_policy_init(&policy);
psa_key_policy_set_usage(&policy, usage, alg);
status = psa_set_key_policy(slot, &policy);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
#if DOMAIN_NS == 1U
/* Fill the key data */
(void)memset(data, 'A', key_size);
#else
(void)tfm_memset(data, 'A', key_size);
#endif
/* Import a key to slot 0 */
status = psa_import_key(slot, key_type, data, key_size);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error importing a key");
return;
}
/* Setup the encryption object */
status = psa_cipher_encrypt_setup(&handle, slot, alg);
if (status == PSA_SUCCESS) {
TEST_FAIL("Should not successfully setup an invalid cipher");
psa_destroy_key(slot);
return;
}
/* Destroy the key in slot 0 */
status = psa_destroy_key(slot);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error destroying a key");
return;
}
ret->val = TEST_PASSED;
}
/*
* \brief This is the list of algorithms supported by the current
* configuration of the crypto engine used by the crypto
* service. In case the crypto engine default capabilities
* is changed, this list needs to be updated accordingly
*/
static const psa_algorithm_t hash_alg[] = {
PSA_ALG_SHA_1,
PSA_ALG_SHA_224,
PSA_ALG_SHA_256,
PSA_ALG_SHA_384,
PSA_ALG_SHA_512,
PSA_ALG_MD5,
PSA_ALG_RIPEMD160,
PSA_ALG_MD2,
PSA_ALG_MD4
};
static const uint8_t hash_val[][PSA_HASH_SIZE(PSA_ALG_SHA_512)] = {
{0x56, 0x4A, 0x0E, 0x35, 0xF1, 0xC7, 0xBC, 0xD0, /*!< SHA-1 */
0x7D, 0xCF, 0xB1, 0xBC, 0xC9, 0x16, 0xFA, 0x2E,
0xF5, 0xBE, 0x96, 0xB2},
{0x00, 0xD2, 0x90, 0xE2, 0x0E, 0x4E, 0xC1, 0x7E, /*!< SHA-224 */
0x7A, 0x95, 0xF5, 0x10, 0x5C, 0x76, 0x74, 0x04,
0x6E, 0xB5, 0x56, 0x5E, 0xE5, 0xE7, 0xBA, 0x15,
0x6C, 0x23, 0x47, 0xF3},
{0x6B, 0x22, 0x09, 0x2A, 0x37, 0x1E, 0xF5, 0x14, /*!< SHA-256 */
0xF7, 0x39, 0x4D, 0xCF, 0xAD, 0x4D, 0x17, 0x46,
0x66, 0xCB, 0x33, 0xA0, 0x39, 0xD8, 0x41, 0x4E,
0xF1, 0x2A, 0xD3, 0x4D, 0x69, 0xC3, 0xB5, 0x3E},
{0x64, 0x79, 0x11, 0xBB, 0x47, 0x4E, 0x47, 0x59, /*!< SHA-384 */
0x3E, 0x4D, 0xBC, 0x60, 0xA5, 0xF9, 0xBF, 0x9C,
0xC0, 0xBA, 0x55, 0x0F, 0x93, 0xCA, 0x72, 0xDF,
0x57, 0x1E, 0x50, 0x56, 0xF9, 0x4A, 0x01, 0xD6,
0xA5, 0x6F, 0xF7, 0x62, 0x34, 0x4F, 0x48, 0xFD,
0x9D, 0x15, 0x07, 0x42, 0xB7, 0x72, 0x94, 0xB8},
{0xB4, 0x1C, 0xA3, 0x6C, 0xA9, 0x67, 0x1D, 0xAD, /*!< SHA-512 */
0x34, 0x1F, 0xBE, 0x1B, 0x83, 0xC4, 0x40, 0x2A,
0x47, 0x42, 0x79, 0xBB, 0x21, 0xCA, 0xF0, 0x60,
0xE4, 0xD2, 0x6E, 0x9B, 0x70, 0x12, 0x34, 0x3F,
0x55, 0x2C, 0x09, 0x31, 0x0A, 0x5B, 0x40, 0x21,
0x01, 0xA8, 0x3B, 0x58, 0xE7, 0x48, 0x13, 0x1A,
0x7E, 0xCD, 0xE1, 0xD2, 0x46, 0x10, 0x58, 0x34,
0x49, 0x14, 0x4B, 0xAA, 0x89, 0xA9, 0xF5, 0xB1},
{0x63, 0xFC, 0x11, 0x88, 0xB7, 0x03, 0xDD, 0xD5, /*!< MD-5 */
0x36, 0xB9, 0x2F, 0xD6, 0x9E, 0x91, 0x96, 0xF8},
{0xF5, 0x8E, 0xB3, 0xCB, 0xE5, 0xF0, 0x3B, 0xC5, /*!< RIPEMD-160 */
0x7C, 0x45, 0xE2, 0x49, 0xAA, 0x66, 0xC6, 0x5A,
0x47, 0xEA, 0x34, 0x91},
{0x7E, 0x28, 0x13, 0xAE, 0x98, 0xBD, 0x38, 0x6C, /*!< MD-2 */
0xDC, 0x8C, 0xF8, 0x04, 0xC6, 0x58, 0xA9, 0x69},
{0xA0, 0xB9, 0x82, 0x4E, 0xE0, 0x74, 0x4F, 0x1E, /*!< MD-4 */
0xA4, 0x7F, 0xA3, 0xDF, 0xD0, 0x0D, 0x97, 0xEB},
};
void psa_hash_test(const psa_algorithm_t alg,
struct test_result_t *ret)
{
const char *msg[] = {"This is my test message, ",
"please generate a hash for this."};
const size_t msg_size[] = {25, 32}; /* Length in bytes of msg[0], msg[1] */
const uint32_t msg_num = sizeof(msg)/sizeof(msg[0]);
uint32_t idx;
psa_status_t status;
psa_hash_operation_t handle;
/* Setup the hash object for the desired hash*/
status = psa_hash_setup(&handle, alg);
if (status != PSA_SUCCESS) {
if (status == PSA_ERROR_NOT_SUPPORTED) {
TEST_FAIL("Algorithm NOT SUPPORTED by the implementation");
return;
}
TEST_FAIL("Error setting up hash operation object");
return;
}
/* Update object with all the chunks of message */
for (idx=0; idx<msg_num; idx++) {
status = psa_hash_update(&handle,
(const uint8_t *)msg[idx],msg_size[idx]);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error updating the hash operation object");
return;
}
}
/* Cycle until idx points to the correct index in the algorithm table */
for (idx=0; hash_alg[idx] != alg; idx++);
/* Finalise and verify that the hash is as expected */
status = psa_hash_verify(&handle, &(hash_val[idx][0]), PSA_HASH_SIZE(alg));
if (status != PSA_SUCCESS) {
TEST_FAIL("Error verifying the hash operation object");
return;
}
ret->val = TEST_PASSED;
}
static const uint8_t hmac_val[][PSA_HASH_SIZE(PSA_ALG_SHA_512)] = {
{0x0d, 0xa6, 0x9d, 0x02, 0x43, 0x17, 0x3e, 0x7e, /*!< SHA-1 */
0xe7, 0x3b, 0xc6, 0xa9, 0x51, 0x06, 0x8a, 0xea,
0x12, 0xb0, 0xa7, 0x1d},
{0xc1, 0x9f, 0x19, 0xac, 0x05, 0x65, 0x5f, 0x02, /*!< SHA-224 */
0x1b, 0x64, 0x32, 0xd9, 0xb1, 0x49, 0xba, 0x75,
0x05, 0x60, 0x52, 0x4e, 0x78, 0xfa, 0x61, 0xc9,
0x37, 0x5d, 0x7f, 0x58},
{0x94, 0x37, 0xbe, 0xb5, 0x7f, 0x7c, 0x5c, 0xb0, /*!< SHA-256 */
0x0a, 0x92, 0x4d, 0xd3, 0xba, 0x7e, 0xb1, 0x1a,
0xdb, 0xa2, 0x25, 0xb2, 0x82, 0x8e, 0xdf, 0xbb,
0x61, 0xbf, 0x91, 0x1d, 0x28, 0x23, 0x4a, 0x04},
{0x94, 0x21, 0x9b, 0xc3, 0xd5, 0xed, 0xe6, 0xee, /*!< SHA-384 */
0x42, 0x10, 0x5a, 0x58, 0xa4, 0x4d, 0x67, 0x87,
0x16, 0xa2, 0xa7, 0x6c, 0x2e, 0xc5, 0x85, 0xb7,
0x6a, 0x4c, 0x90, 0xb2, 0x73, 0xee, 0x58, 0x3c,
0x59, 0x16, 0x67, 0xf3, 0x6f, 0x30, 0x99, 0x1c,
0x2a, 0xf7, 0xb1, 0x5f, 0x45, 0x83, 0xf5, 0x9f},
{0x8f, 0x76, 0xef, 0x12, 0x0b, 0x92, 0xc2, 0x06, /*!< SHA-512 */
0xce, 0x01, 0x18, 0x75, 0x84, 0x96, 0xd9, 0x6f,
0x23, 0x88, 0xd4, 0xf8, 0xcf, 0x79, 0xf8, 0xcf,
0x27, 0x12, 0x9f, 0xa6, 0x7e, 0x87, 0x9a, 0x68,
0xee, 0xe2, 0xe7, 0x1d, 0x4b, 0xf2, 0x87, 0xc0,
0x05, 0x6a, 0xbd, 0x7f, 0x9d, 0xff, 0xaa, 0xf3,
0x9a, 0x1c, 0xb7, 0xb7, 0xbd, 0x03, 0x61, 0xa3,
0xa9, 0x6a, 0x5d, 0xb2, 0x81, 0xe1, 0x6f, 0x1f},
{0x26, 0xfb, 0x68, 0xd2, 0x28, 0x17, 0xc2, 0x9c, /*!< MD-5 */
0xbe, 0xed, 0x95, 0x16, 0x82, 0xb0, 0xd8, 0x99},
{0x5c, 0xd9, 0x49, 0xc8, 0x66, 0x7a, 0xfa, 0x79, /*!< RIPEMD-160 */
0xa8, 0x88, 0x2e, 0x53, 0xf4, 0xee, 0xc0, 0x2d,
0x1e, 0xf0, 0x80, 0x25},
{0x0c, 0x8c, 0x8c, 0x16, 0x49, 0x92, 0x76, 0xf1, /*!< MD-2 */
0xc4, 0xcc, 0xdc, 0x9f, 0x7c, 0xb2, 0xeb, 0x87},
{0x44, 0xdf, 0x1b, 0x97, 0xe9, 0xe8, 0xd3, 0xb0, /*!< MD-4 */
0xe8, 0x8d, 0xad, 0xdb, 0x86, 0xab, 0xa6, 0xc6},
};
static const uint8_t long_key_hmac_val[PSA_HASH_SIZE(PSA_ALG_SHA_1)] = {
0xb5, 0x06, 0x7b, 0x9a, 0xb9, 0xe7, 0x47, 0x3c, /*!< SHA-1 */
0x2d, 0x44, 0x46, 0x1f, 0x4a, 0xbd, 0x22, 0x53,
0x9c, 0x05, 0x34, 0x34
};
void psa_mac_test(const psa_algorithm_t alg,
uint8_t use_long_key,
struct test_result_t *ret)
{
const char *msg[] = {"This is my test message, ",
"please generate a hmac for this."};
const size_t msg_size[] = {25, 32}; /* Length in bytes of msg[0], msg[1] */
const uint32_t msg_num = sizeof(msg)/sizeof(msg[0]);
uint32_t idx;
const psa_key_slot_t slot = TEST_KEY_SLOT;
const uint8_t data[] = "THIS IS MY KEY1";
const uint8_t long_data[] = "THIS IS MY UNCOMMONLY LONG KEY1";
psa_key_type_t type = PSA_KEY_TYPE_NONE;
size_t bits = 0;
size_t bit_size_test_key = 0;
psa_status_t status;
psa_mac_operation_t handle;
psa_key_policy_t policy;
psa_key_usage_t usage = PSA_KEY_USAGE_VERIFY;
/* Setup the key policy */
psa_key_policy_init(&policy);
psa_key_policy_set_usage(&policy, usage, alg);
status = psa_set_key_policy(slot, &policy);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
ret->val = TEST_PASSED;
/* Import key on slot 0 */
if (use_long_key == 1) {
status = psa_import_key(slot,
PSA_KEY_TYPE_HMAC,
long_data,
sizeof(long_data));
} else {
status = psa_import_key(slot, PSA_KEY_TYPE_HMAC, data, sizeof(data));
}
if (status != PSA_SUCCESS) {
TEST_FAIL("Error importing a key");
return;
}
status = psa_get_key_information(slot, &type, &bits);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error getting key metadata");
goto destroy_key_mac;
}
if (use_long_key == 1) {
bit_size_test_key = BIT_SIZE_TEST_LONG_KEY;
} else {
bit_size_test_key = BIT_SIZE_TEST_KEY;
}
if (bits != bit_size_test_key) {
TEST_FAIL("The number of key bits is different from expected");
goto destroy_key_mac;
}
if (type != PSA_KEY_TYPE_HMAC) {
TEST_FAIL("The type of the key is different from expected");
goto destroy_key_mac;
}
/* Setup the mac object for hmac */
status = psa_mac_verify_setup(&handle, slot, alg);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error setting up mac operation object");
goto destroy_key_mac;
}
/* Update object with all the chunks of message */
for (idx=0; idx<msg_num; idx++) {
status = psa_mac_update(&handle,
(const uint8_t *)msg[idx],
msg_size[idx]);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error during mac operation");
goto destroy_key_mac;
}
}
/* Cycle until idx points to the correct index in the algorithm table */
for (idx=0; hash_alg[idx] != PSA_ALG_HMAC_HASH(alg); idx++);
/* Finalise and verify the mac value */
if (use_long_key == 1) {
status = psa_mac_verify_finish(&handle,
&(long_key_hmac_val[0]),
PSA_HASH_SIZE(PSA_ALG_HMAC_HASH(alg)));
} else {
status = psa_mac_verify_finish(&handle,
&(hmac_val[idx][0]),
PSA_HASH_SIZE(PSA_ALG_HMAC_HASH(alg)));
}
if (status != PSA_SUCCESS) {
TEST_FAIL("Error during finalising the mac operation");
goto destroy_key_mac;
}
destroy_key_mac:
/* Destroy the key */
status = psa_destroy_key(slot);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error destroying the key");
}
}
void psa_aead_test(const psa_key_type_t key_type,
const psa_algorithm_t alg,
struct test_result_t *ret)
{
const psa_key_slot_t slot = TEST_KEY_SLOT;
const size_t nonce_length = 12;
const uint8_t nonce[] = "01234567890";
const uint8_t plain_text[BYTE_SIZE_CHUNK] = "Sixteen bytes!!";
const uint8_t associated_data[ASSOCIATED_DATA_SIZE] =
"This is associated data";
uint8_t encrypted_data[ENC_DEC_BUFFER_SIZE] = {0};
size_t encrypted_data_length = 0, decrypted_data_length = 0;
uint8_t decrypted_data[ENC_DEC_BUFFER_SIZE] = {0};
psa_status_t status;
const uint8_t data[] = "THIS IS MY KEY1";
psa_key_type_t type = PSA_KEY_TYPE_NONE;
size_t bits = 0;
uint32_t comp_result;
psa_key_policy_t policy;
psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
/* Setup the key policy */
psa_key_policy_init(&policy);
psa_key_policy_set_usage(&policy, usage, alg);
status = psa_set_key_policy(slot, &policy);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
ret->val = TEST_PASSED;
/* Import a key on slot 0 */
status = psa_import_key(slot, key_type, data, sizeof(data));
if (status != PSA_SUCCESS) {
TEST_FAIL("Error importing a key");
return;
}
status = psa_get_key_information(slot, &type, &bits);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error getting key metadata");
goto destroy_key_aead;
}
if (bits != BIT_SIZE_TEST_KEY) {
TEST_FAIL("The number of key bits is different from expected");
goto destroy_key_aead;
}
if (type != key_type) {
TEST_FAIL("The type of the key is different from expected");
goto destroy_key_aead;
}
/* Perform AEAD encryption */
status = psa_aead_encrypt(slot, alg, nonce, nonce_length,
associated_data,
sizeof(associated_data),
plain_text,
sizeof(plain_text),
encrypted_data,
sizeof(encrypted_data),
&encrypted_data_length );
if (status != PSA_SUCCESS) {
if (status == PSA_ERROR_NOT_SUPPORTED) {
TEST_FAIL("Algorithm NOT SUPPORTED by the implementation");
goto destroy_key_aead;
}
TEST_FAIL("Error performing AEAD encryption");
goto destroy_key_aead;
}
if (sizeof(plain_text) != (encrypted_data_length-PSA_AEAD_TAG_SIZE(alg))) {
TEST_FAIL("Encrypted data length is different than expected");
goto destroy_key_aead;
}
/* Perform AEAD decryption */
status = psa_aead_decrypt(slot, alg, nonce, nonce_length,
associated_data,
sizeof(associated_data),
encrypted_data,
encrypted_data_length,
decrypted_data,
sizeof(decrypted_data),
&decrypted_data_length );
if (status != PSA_SUCCESS) {
if (status == PSA_ERROR_NOT_SUPPORTED) {
TEST_FAIL("Algorithm NOT SUPPORTED by the implementation");
} else {
TEST_FAIL("Error performing AEAD decryption");
}
goto destroy_key_aead;
}
if (sizeof(plain_text) != decrypted_data_length) {
TEST_FAIL("Decrypted data length is different from plain text");
goto destroy_key_aead;
}
#if DOMAIN_NS == 1U
/* Check that the decrypted data is the same as the original data */
comp_result = memcmp(plain_text, decrypted_data, sizeof(plain_text));
#else
comp_result = tfm_memcmp(plain_text, decrypted_data, sizeof(plain_text));
#endif
if (comp_result != 0) {
TEST_FAIL("Decrypted data doesn't match with plain text");
goto destroy_key_aead;
}
destroy_key_aead:
/* Destroy the key on slot 0 */
status = psa_destroy_key(slot);
if (status != PSA_SUCCESS) {
TEST_FAIL("Error destroying a key");
}
}
void psa_invalid_key_length_test(struct test_result_t *ret)
{
psa_status_t status;
psa_key_policy_t policy;
const psa_key_slot_t slot = TEST_KEY_SLOT;
const uint8_t data[19] = {0};
/* Setup the key policy */
psa_key_policy_init(&policy);
psa_key_policy_set_usage(&policy, PSA_KEY_USAGE_ENCRYPT, PSA_ALG_CBC_BASE);
status = psa_set_key_policy(slot, &policy);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
/* DES does not support 152-bit keys */
status = psa_import_key(slot, PSA_KEY_TYPE_DES, data, sizeof(data));
if (status != PSA_ERROR_NOT_SUPPORTED) {
TEST_FAIL("Should not successfully import with an invalid key length");
return;
}
}
void psa_policy_key_interface_test(struct test_result_t *ret)
{
psa_status_t status;
psa_algorithm_t alg = PSA_ALG_CBC_BASE;
psa_algorithm_t alg_out;
psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE;
psa_key_lifetime_t lifetime_out;
psa_key_policy_t policy;
psa_key_policy_t policy_out;
psa_key_slot_t slot = TEST_KEY_SLOT;
psa_key_usage_t usage = PSA_KEY_USAGE_EXPORT;
psa_key_usage_t usage_out;
/* Initialise the key policy */
psa_key_policy_init(&policy);
/* Verify that initialised policy forbids all usage */
usage_out = psa_key_policy_get_usage(&policy);
if (usage_out != 0) {
TEST_FAIL("Unexpected usage value");
return;
}
alg_out = psa_key_policy_get_algorithm(&policy);
if (alg_out != 0) {
TEST_FAIL("Unexpected algorithm value");
return;
}
/* Set the key policy values */
psa_key_policy_set_usage(&policy, usage, alg);
/* Check that the key policy has the correct usage */
usage_out = psa_key_policy_get_usage(&policy);
if (usage_out != usage) {
TEST_FAIL("Unexpected usage value");
return;
}
/* Check that the key policy has the correct algorithm */
alg_out = psa_key_policy_get_algorithm(&policy);
if (alg_out != alg) {
TEST_FAIL("Unexpected algorithm value");
return;
}
/* Set the key policy for the key slot */
status = psa_set_key_policy(slot, &policy);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
/* Check the key slot has the correct key policy */
status = psa_get_key_policy(slot, &policy_out);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to get key policy");
return;
}
usage_out = psa_key_policy_get_usage(&policy_out);
if (usage_out != usage) {
TEST_FAIL("Unexpected usage value");
return;
}
alg_out = psa_key_policy_get_algorithm(&policy_out);
if (alg_out != alg) {
TEST_FAIL("Unexpected algorithm value");
return;
}
/* Set the key lifetime for the key slot */
status = psa_set_key_lifetime(slot, lifetime);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key lifetime");
return;
}
/* Check the key slot has the correct key lifetime */
status = psa_get_key_lifetime(slot, &lifetime_out);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to get key lifetime");
return;
}
if (lifetime_out != lifetime) {
TEST_FAIL("Unexpected key lifetime value");
return;
}
ret->val = TEST_PASSED;
}
void psa_policy_invalid_policy_usage_test(struct test_result_t *ret)
{
psa_status_t status;
psa_algorithm_t alg = PSA_ALG_CBC_BASE;
psa_cipher_operation_t handle;
psa_key_lifetime_t lifetime = PSA_KEY_LIFETIME_VOLATILE;
psa_key_policy_t policy;
psa_key_slot_t slot = TEST_KEY_SLOT;
psa_key_usage_t usage = (PSA_KEY_USAGE_ENCRYPT | PSA_KEY_USAGE_DECRYPT);
size_t data_len;
const uint8_t data[] = "THIS IS MY KEY1";
uint8_t data_out[sizeof(data)];
ret->val = TEST_PASSED;
/* Setup the key policy */
psa_key_policy_init(&policy);
psa_key_policy_set_usage(&policy, usage, alg);
status = psa_set_key_policy(slot, &policy);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key policy");
return;
}
/* Set the key lifetime for the key slot */
status = psa_set_key_lifetime(slot, lifetime);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to set key lifetime");
return;
}
/* Import a key to the slot for which policy has been set */
status = psa_import_key(slot, PSA_KEY_TYPE_AES, data, sizeof(data));
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to import a key");
return;
}
/* Setup a cipher permitted by the key policy */
status = psa_cipher_encrypt_setup(&handle, slot, alg);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to setup cipher operation");
goto destroy_key;
}
status = psa_cipher_abort(&handle);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to abort cipher operation");
goto destroy_key;
}
/* Attempt to setup a cipher with an alg not permitted by the policy */
status = psa_cipher_encrypt_setup(&handle, slot, PSA_ALG_CFB_BASE);
if (status != PSA_ERROR_NOT_PERMITTED) {
TEST_FAIL("Was able to setup cipher operation with wrong alg");
goto destroy_key;
}
/* Attempt to export the key, which is forbidden by the key policy */
status = psa_export_key(slot, data_out, sizeof(data_out), &data_len);
if (status != PSA_ERROR_NOT_PERMITTED) {
TEST_FAIL("Should not be able to export key without correct usage");
goto destroy_key;
}
destroy_key:
status = psa_destroy_key(slot);
if (status != PSA_SUCCESS) {
TEST_FAIL("Failed to destroy key");
}
}