411 lines
11 KiB
C
411 lines
11 KiB
C
/*
|
|
* Copyright 2009 Freescale Semiconductor, Inc. All rights reserved.
|
|
*/
|
|
|
|
/*
|
|
* The code contained herein is licensed under the GNU General Public
|
|
* License. You may obtain a copy of the GNU General Public License
|
|
* Version 2 or later at the following locations:
|
|
*
|
|
* http://www.opensource.org/licenses/gpl-license.html
|
|
* http://www.gnu.org/copyleft/gpl.html
|
|
*/
|
|
|
|
/*!
|
|
* @file dryice.c
|
|
* @brief Test code for DryIce support in FSL SHW API
|
|
*
|
|
* @ifnot STANDALONE
|
|
* @ingroup MXCSAHARA2_TEST
|
|
* @endif
|
|
*/
|
|
|
|
#include "api_tests.h"
|
|
|
|
static uint8_t input_data[] = {
|
|
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07
|
|
};
|
|
|
|
static uint8_t wrap_unwrap_key_a[] = {
|
|
0x01, 0x23, 0x45, 0x67,
|
|
0x01, 0x23, 0x45, 0x67,
|
|
0x76, 0x54, 0x32, 0x10,
|
|
0x76, 0x54, 0x32, 0x10,
|
|
0x08, 0x09, 0x0a, 0x0b,
|
|
0x0c, 0x0d, 0x0e, 0x0f
|
|
};
|
|
|
|
static uint8_t wrap_unwrap_input_a[] = {
|
|
0x00, 0x01, 0x02, 0x03,
|
|
0x04, 0x05, 0x06, 0x07,
|
|
0x08, 0x09, 0x0a, 0x0b,
|
|
0x0c, 0x0d, 0x0e, 0x0f
|
|
};
|
|
|
|
static uint8_t wrap_unwrap_output_a[] = {
|
|
0x1A, 0xB0, 0xA5, 0x21,
|
|
0xDA, 0x31, 0x3B, 0xD3,
|
|
0xE4, 0xB3, 0xFE, 0xB1,
|
|
0x37, 0x5A, 0xC9, 0xE1
|
|
};
|
|
|
|
static uint8_t wrap_unwrap_key_b[] = {
|
|
0x76, 0x54, 0x32, 0x10,
|
|
0x76, 0x54, 0x32, 0x10,
|
|
0x01, 0x23, 0x45, 0x67,
|
|
0x01, 0x23, 0x45, 0x67
|
|
};
|
|
|
|
static uint8_t wrap_unwrap_input_b[] = {
|
|
0x00, 0x01, 0x02, 0x03,
|
|
0x04, 0x05, 0x06, 0x07,
|
|
0x08, 0x09, 0x0a, 0x0b,
|
|
0x0c, 0x0d, 0x0e, 0x0f
|
|
};
|
|
|
|
static uint8_t wrap_unwrap_output_b[] = {
|
|
0xD5, 0x00, 0x22, 0x0E,
|
|
0x06, 0xF8, 0xAB, 0xC1,
|
|
0x50, 0x64, 0x33, 0x29,
|
|
0x10, 0x8C, 0xAC, 0x69
|
|
};
|
|
|
|
/*!
|
|
* Test that PK wrap/unwrap functions work correctly
|
|
*
|
|
* First encrypt some data with a known hardware key, then wrap the key.
|
|
* Next, load a different known key and encrypt some data with it, to ensure
|
|
* that the first key has been properly overwritten. Finally, unwrap the
|
|
* original key and encrypt some data again to verify that it has been restored
|
|
* properly.
|
|
*/
|
|
static void test_wrap_unwrap(fsl_shw_uco_t * my_ctx,
|
|
uint32_t * total_passed_count,
|
|
uint32_t * total_failed_count)
|
|
{
|
|
fsl_shw_sko_t program_key_a;
|
|
fsl_shw_sko_t program_key_b;
|
|
fsl_shw_sko_t program_key_a_unwrapped;
|
|
fsl_shw_scco_t ctx;
|
|
fsl_shw_return_t ret;
|
|
uint8_t output_a[sizeof(wrap_unwrap_input_a)];
|
|
uint8_t output_b[sizeof(wrap_unwrap_input_b)];
|
|
uint8_t output_c[sizeof(wrap_unwrap_input_a)];
|
|
uint8_t *wrapped_key_data = NULL;
|
|
int wrapped_key_size;
|
|
int passed = 0;
|
|
int failed = 0;
|
|
|
|
/* Initial control object */
|
|
fsl_shw_scco_init(&ctx, FSL_KEY_ALG_TDES, FSL_SYM_MODE_ECB);
|
|
|
|
/* Establish a known (plaintext) program key */
|
|
fsl_shw_sko_init_pf_key(&program_key_a, FSL_KEY_ALG_TDES,
|
|
FSL_SHW_PF_KEY_PRG);
|
|
|
|
fsl_shw_sko_set_key_length(&program_key_a, sizeof(wrap_unwrap_key_a));
|
|
fsl_shw_sko_set_user_id(&program_key_a, 0x123456);
|
|
ret = fsl_shw_establish_key(my_ctx, &program_key_a, FSL_KEY_WRAP_ACCEPT,
|
|
wrap_unwrap_key_a);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("First establish program key from plaintext failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Perform a known cipher operation with the key to ensure it functions
|
|
* correctly.
|
|
*/
|
|
ret = fsl_shw_symmetric_encrypt(my_ctx, &program_key_a, &ctx,
|
|
sizeof(wrap_unwrap_input_a),
|
|
wrap_unwrap_input_a, output_a);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("First symmetric encrypt in wrap/unwrap test failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
if (compare_result(wrap_unwrap_output_a, output_a,
|
|
sizeof(wrap_unwrap_output_a), "third enc output")) {
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Wrap the program key, and release it. */
|
|
fsl_shw_sko_calculate_wrapped_size(&program_key_a, &wrapped_key_size);
|
|
wrapped_key_data = malloc(wrapped_key_size + 1);
|
|
if (wrapped_key_data == NULL) {
|
|
printf("Failed to allocate memory to store wrapped key\n");
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
wrapped_key_data[wrapped_key_size] = 0x42;
|
|
fsl_shw_extract_key(my_ctx, &program_key_a, wrapped_key_data);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf("Extract program key failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
if (wrapped_key_data[wrapped_key_size] != 0x42) {
|
|
printf("Wrapped key buffer was overwritten\n");
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Release the program key */
|
|
fsl_shw_release_key(my_ctx, &program_key_a);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("First release (hardware) key in wrap/unwrap failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Establish a second known program key */
|
|
fsl_shw_sko_init_pf_key(&program_key_b, FSL_KEY_ALG_TDES,
|
|
FSL_SHW_PF_KEY_PRG);
|
|
|
|
fsl_shw_sko_set_key_length(&program_key_b, sizeof(wrap_unwrap_key_b));
|
|
fsl_shw_establish_key(my_ctx, &program_key_b, FSL_KEY_WRAP_ACCEPT,
|
|
wrap_unwrap_key_b);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("Second establish program key from plaintext failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Perform a known cipher operation with the key to ensure it functions
|
|
* correctly.
|
|
*/
|
|
ret = fsl_shw_symmetric_encrypt(my_ctx, &program_key_b, &ctx,
|
|
sizeof(wrap_unwrap_input_b),
|
|
wrap_unwrap_input_b, output_b);
|
|
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("Second symmetric encrypt in wrap/unwrap test failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
if (compare_result(wrap_unwrap_output_b, output_b,
|
|
sizeof(wrap_unwrap_output_b), "second enc output")) {
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Release the program key */
|
|
fsl_shw_release_key(my_ctx, &program_key_b);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("Second release (hardware) key in wrap/unwrap failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Establish (unwrap) the original program key */
|
|
fsl_shw_sko_init_pf_key(&program_key_a_unwrapped, FSL_KEY_ALG_TDES,
|
|
FSL_SHW_PF_KEY_PRG);
|
|
|
|
fsl_shw_sko_set_key_length(&program_key_a_unwrapped,
|
|
sizeof(wrap_unwrap_key_a));
|
|
fsl_shw_sko_set_user_id(&program_key_a_unwrapped, 0x123456);
|
|
fsl_shw_establish_key(my_ctx, &program_key_a_unwrapped,
|
|
FSL_KEY_WRAP_UNWRAP, wrapped_key_data);
|
|
|
|
/* Perform a known cipher operation with the key to ensure that it was
|
|
* unwrapped correctly.
|
|
*/
|
|
ret = fsl_shw_symmetric_encrypt(my_ctx, &program_key_a_unwrapped, &ctx,
|
|
sizeof(wrap_unwrap_input_a),
|
|
wrap_unwrap_input_a, output_c);
|
|
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("Third symmetric encrypt in wrap/unwrap test failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
if (compare_result(wrap_unwrap_output_a, output_c,
|
|
sizeof(wrap_unwrap_output_a), "third enc output")) {
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Release the program key */
|
|
fsl_shw_release_key(my_ctx, &program_key_a_unwrapped);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("Third release (hardware) key in wrap/unwrap failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
passed++;
|
|
printf("Hardware wrap/unwrap Passed\n");
|
|
out:
|
|
if (wrapped_key_data != NULL) {
|
|
free(wrapped_key_data);
|
|
}
|
|
|
|
*total_passed_count += passed;
|
|
*total_failed_count += failed;
|
|
return;
|
|
} /* end fn test_wrap_unwrap */
|
|
|
|
/*!
|
|
* Make sure that HW random key gets generated
|
|
*
|
|
* First encrypt some data with the random key, then regenerate the random key,
|
|
* then encrypt the same data again. The encrypted results should differ.
|
|
*/
|
|
static void test_pf_random(fsl_shw_uco_t * my_ctx,
|
|
uint32_t * total_passed_count,
|
|
uint32_t * total_failed_count)
|
|
{
|
|
fsl_shw_return_t ret;
|
|
fsl_shw_sko_t rnd_key;
|
|
fsl_shw_scco_t ctx;
|
|
uint8_t output1[sizeof(input_data)];
|
|
uint8_t output2[sizeof(input_data)];
|
|
int passed = 0;
|
|
int failed = 0;
|
|
|
|
/* Get a reference to the pf random key */
|
|
fsl_shw_sko_init_pf_key(&rnd_key, FSL_KEY_ALG_TDES,
|
|
FSL_SHW_PF_KEY_IIM_RND);
|
|
|
|
/* Initial control object */
|
|
fsl_shw_scco_init(&ctx, FSL_KEY_ALG_TDES, FSL_SYM_MODE_ECB);
|
|
|
|
/* Encrypt with the current random key */
|
|
ret = fsl_shw_symmetric_encrypt(my_ctx, &rnd_key, &ctx,
|
|
sizeof(input_data), input_data,
|
|
output1);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("First symmetric encrypt in HW random test failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
/* Set up a new random key */
|
|
if (0) {
|
|
printf("SKIPPING generation of HW random key\n");
|
|
} else {
|
|
ret = fsl_shw_gen_random_pf_key(my_ctx);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf("Error generating HW Random Key: %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
printf("Finished generation of HW random key\n");
|
|
}
|
|
|
|
/* Encrypt with the new random key */
|
|
ret = fsl_shw_symmetric_encrypt(my_ctx, &rnd_key, &ctx,
|
|
sizeof(input_data), input_data,
|
|
output2);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf
|
|
("Second symmetric encrypt in HW random test failed with %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
if (memcmp(output1, output2, sizeof(input_data)) == 0) {
|
|
printf("Random HW key did not appear to change\n");
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
passed++;
|
|
printf("Random HW key test passed\n");
|
|
|
|
out:
|
|
*total_passed_count += passed;
|
|
*total_failed_count += failed;
|
|
return;
|
|
} /* end fn test_pf_random */
|
|
|
|
/*!
|
|
* Make sure no error or events are returned from read_tamper_event()
|
|
*/
|
|
static void test_tamper(fsl_shw_uco_t * my_ctx, uint32_t * total_passed_count,
|
|
uint32_t * total_failed_count)
|
|
{
|
|
fsl_shw_return_t ret;
|
|
fsl_shw_tamper_t event = (fsl_shw_tamper_t) - 1;
|
|
uint64_t timestamp = 0;
|
|
int passed = 0;
|
|
int failed = 0;
|
|
|
|
/* Can we force a tamper event to appear??? */
|
|
|
|
ret = fsl_shw_read_tamper_event(my_ctx, &event, ×tamp);
|
|
if (ret != FSL_RETURN_OK_S) {
|
|
printf("fsl_shw_read_tamper_event returned with error: %s\n",
|
|
fsl_error_string(ret));
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
if (event != FSL_SHW_TAMPER_NONE) {
|
|
printf("What the hey? A tamper event? %d / %llu\n", event,
|
|
(unsigned long long)timestamp);
|
|
failed++;
|
|
goto out;
|
|
}
|
|
|
|
printf("Tamper Passed: No events\n");
|
|
passed++;
|
|
|
|
out:
|
|
*total_passed_count += passed;
|
|
*total_failed_count += failed;
|
|
return;
|
|
} /* end fn test_tamper */
|
|
|
|
/*!
|
|
* Entry point for dryice test module.
|
|
*
|
|
* Responsible for running other tests, as appropriate.
|
|
*/
|
|
void run_dryice(fsl_shw_uco_t * my_ctx, uint32_t * total_passed_count,
|
|
uint32_t * total_failed_count)
|
|
{
|
|
fsl_shw_pco_t *cap = fsl_shw_get_capabilities(my_ctx);
|
|
|
|
if ((cap == NULL)) {
|
|
printf("DryIce - Cap is null \n\n");
|
|
}
|
|
if (!fsl_shw_pco_check_pk_supported(cap)) {
|
|
printf("Skipping DryIced Tests\n\n");
|
|
goto out;
|
|
}
|
|
|
|
test_tamper(my_ctx, total_passed_count, total_failed_count);
|
|
|
|
test_pf_random(my_ctx, total_passed_count, total_failed_count);
|
|
|
|
test_wrap_unwrap(my_ctx, total_passed_count, total_failed_count);
|
|
|
|
out:
|
|
return;
|
|
}
|