meta-digi/meta-digi-dey/recipes-digi/dey-examples/files/sahara_test/wrap.c

731 lines
20 KiB
C

/*
* Copyright 2005-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 wrap.c
* @brief Test code for Wrapped (Black) Key support in FSL SHW API
*
* This file contains vectors and code to test fsl_shw_establish_key(),
* fsl_shw_extract_key(), fsl_shw_release_key(), and the functions associated
* with the Secret Key Object.
*
* @ifnot STANDALONE
* @ingroup MXCSAHARA2_TEST
* @endif
*/
#include "api_tests.h"
/*! Key for Known Answer test */
static const unsigned char known_key[] = {
0x2C, 0x82, 0x96, 0xE0, 0x2E, 0x5F, 0x5C, 0x19,
0xAA, 0x29, 0xA6, 0xCF, 0x97, 0x05, 0x5C, 0xD2,
0xA8, 0xEC, 0xE4, 0x1D, 0xAC, 0x47, 0x7B, 0x6F
};
/*! Plaintext for Known Answer test */
static unsigned char known_plaintext[] = {
0x0F, 0xEB, 0x9B, 0x5C, 0x22, 0x0B, 0xA5, 0x13,
0x5D, 0x0F, 0x55, 0x06, 0xC7, 0xD6, 0x75, 0xAF,
0x76, 0x20, 0x1A, 0x91, 0x78, 0x31, 0x75, 0x94,
0x67, 0xB7, 0x3D, 0x23, 0x90, 0xEC, 0x4E, 0x4F,
0x84, 0x55, 0xB0, 0xED, 0x4B, 0x81, 0x70, 0x85,
0x1D, 0xB1, 0xD5, 0x48, 0x85, 0x7A, 0x13, 0x40,
0x76, 0x74, 0x7C, 0x92, 0x97, 0x75, 0xB3, 0x14,
0xA7, 0xE5, 0x02, 0x4F, 0xB4, 0x2F, 0x1E, 0x03
};
/*! Result of encrypting Known plaintext with 24-byte TDES key in ECB mode. */
static const unsigned char TDES_known_ciphertext[] = {
0x79, 0xA2, 0xCB, 0x79, 0x43, 0x66, 0x07, 0x61,
0xB6, 0x53, 0xEF, 0x8B, 0xD9, 0x6C, 0xD6, 0x45,
0xF4, 0xEF, 0x29, 0x4F, 0x37, 0x07, 0x5F, 0x2B,
0xBE, 0xE9, 0x5E, 0x6A, 0x27, 0x29, 0x02, 0x45,
0x22, 0x7F, 0x80, 0x16, 0xFF, 0x21, 0x83, 0xB4,
0x19, 0x80, 0xED, 0x66, 0x37, 0x28, 0x8E, 0xA0,
0xEA, 0x7F, 0x3A, 0x96, 0x37, 0xE2, 0x07, 0x24,
0x87, 0x42, 0x35, 0xCB, 0x11, 0xDE, 0xEB, 0xC3
};
/*! Result of encrypting Known plaintext with 15-byte ARC4 key. */
static const unsigned char ARC4_known_ciphertext[] = {
0x38, 0xeb, 0x67, 0x0a, 0x6b, 0x26, 0x2b, 0x6f,
0x40, 0x15, 0x42, 0x04, 0x2f, 0xee, 0x48, 0x9a,
0x78, 0x75, 0x22, 0xba, 0x70, 0x20, 0xec, 0x78,
0x89, 0x60, 0x3c, 0xd9, 0xf9, 0x97, 0x6e, 0x0f,
0x2f, 0xad, 0xe0, 0x02, 0xc5, 0x7e, 0xfd, 0xc3,
0x3a, 0x93, 0x74, 0xb3, 0x5f, 0xdb, 0xd0, 0xdf,
0xe2, 0xbc, 0x7c, 0x24, 0xa3, 0xe0, 0xde, 0x78,
0x11, 0x08, 0x25, 0x02, 0xae, 0xea, 0x04, 0x17
};
/*! Key for software keys test */
static uint8_t software_key_data[] = {
0x01, 0x23, 0x45, 0x67, 0x01, 0x23, 0x45, 0x67,
0x76, 0x54, 0x32, 0x10, 0x76, 0x54, 0x32, 0x10,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e
};
#define KEY_OWNER_ID 0x42
#define SECRET_KEY_SIZE 7
#define SECRET_KEY_ALGORITHM FSL_KEY_ALG_ARC4
#define KNOWN_ARC4_KEY_SIZE 15
#define KNOWN_ARC4_KEY_ALGORITHM FSL_KEY_ALG_ARC4
#define KNOWN_TDES_KEY_SIZE 24
#define KNOWN_TDES_KEY_ALGORITHM FSL_KEY_ALG_TDES
/*!
* Helper function to set values in Secret Key and
* Symmetric Cipher Context objects according to the
* key algorithm and key length passed in.
*/
static void init_key_and_sym_ctx(fsl_shw_key_alg_t key_alg,
unsigned key_len,
fsl_shw_sko_t * key_info,
fsl_shw_scco_t * sym_ctx)
{
fsl_shw_sko_init(key_info, key_alg);
fsl_shw_sko_set_key_length(key_info, key_len);
if ((key_alg == FSL_KEY_ALG_TDES) || (key_alg == FSL_KEY_ALG_DES)) {
fsl_shw_sko_set_flags(key_info, FSL_SKO_KEY_IGNORE_PARITY);
fsl_shw_scco_init(sym_ctx, key_alg, FSL_SYM_MODE_ECB);
} else {
fsl_shw_scco_init(sym_ctx, key_alg, FSL_SYM_MODE_STREAM);
}
fsl_shw_scco_set_flags(sym_ctx, FSL_SYM_CTX_INIT);
return;
}
/*!
* Establish a generated key and then verify that encryptiong and
* decryption both work on it. As a side effect, leave encrypted
* value in the calling argument.
*/
static int create_key(fsl_shw_uco_t * my_ctx, fsl_shw_sko_t * key_info,
fsl_shw_scco_t * sym_ctx, const uint8_t * plaintext,
uint32_t len, uint8_t * encrypt_output)
{
int passed = 0;
fsl_shw_return_t code;
uint8_t *decrypt_output = malloc(2 * len);
if (decrypt_output != NULL) {
code =
fsl_shw_establish_key(my_ctx, key_info, FSL_KEY_WRAP_CREATE,
NULL);
if (code != FSL_RETURN_OK_S) {
printf("fsl_shw_establish_key(CREATE) returned: %s\n",
fsl_error_string(code));
} else {
memset(encrypt_output, 0, len);
/* Encrypt an arbitrary vector. Try to decrypt to same value. */
code =
fsl_shw_symmetric_encrypt(my_ctx, key_info, sym_ctx,
len, plaintext,
encrypt_output);
if (code != FSL_RETURN_OK_S) {
printf
("fsl_shw_symmetric_encrypt() returned: %s\n",
fsl_error_string(code));
} else {
memset(decrypt_output, 0, len);
code =
fsl_shw_symmetric_decrypt(my_ctx, key_info,
sym_ctx, len,
encrypt_output,
decrypt_output);
if (code != FSL_RETURN_OK_S) {
printf
("fsl_shw_symmetric_decrypt() returned: %s\n",
fsl_error_string(code));
} else {
if (!compare_result
(plaintext, decrypt_output, len,
"decrypted plaintext")) {
passed = 1;
}
}
}
}
}
/* Clean up any allocated memory */
if (decrypt_output) {
free(decrypt_output);
}
return passed;
}
/*!
* Wrap a key and then unwrap it. Use it to decrypt a message, then verify
* that the message matches the expected message.
*/
static int extract_reestablish_key(fsl_shw_uco_t * my_ctx,
uint32_t ownerid, uint32_t handle,
fsl_shw_scco_t * sym_ctx,
const uint8_t * ciphertext,
const uint8_t * expected_plaintext,
uint32_t len)
{
int passed = 0;
uint8_t *blob = NULL;
uint32_t blob_length;
fsl_shw_sko_t old_key_info; /* existing, established key info */
fsl_shw_sko_t new_key_info; /* to-be-unwrapped key info */
fsl_shw_return_t code;
uint32_t key_len = SECRET_KEY_SIZE;
fsl_shw_key_alg_t key_alg = SECRET_KEY_ALGORITHM;
uint8_t *decrypt_output = malloc(2 * len);
init_key_and_sym_ctx(key_alg, key_len, &old_key_info, sym_ctx);
fsl_shw_sko_set_established_info(&old_key_info, ownerid, handle);
fsl_shw_sko_calculate_wrapped_size(&old_key_info, &blob_length);
blob = malloc(blob_length + 1);
if (decrypt_output != NULL) {
memset(blob, 0, blob_length);
blob[blob_length] = 0x42;
code = fsl_shw_extract_key(my_ctx, &old_key_info, blob);
if (code != FSL_RETURN_OK_S) {
fsl_shw_return_t err_err;
printf("fsl_shw_extract_key() returned: %s\n",
fsl_error_string(code));
err_err = fsl_shw_release_key(my_ctx, &old_key_info);
if (err_err != 0) {
printf
("Warning: could not release key with handle 0x%x: %s\n",
handle, fsl_error_string(err_err));
}
} else {
if (blob[blob_length] != 0x42) {
printf("Wrapped key buffer was overwritten\n");
goto out;
}
init_key_and_sym_ctx(key_alg, key_len, &new_key_info,
sym_ctx);
fsl_shw_sko_set_user_id(&new_key_info, KEY_OWNER_ID);
code = fsl_shw_establish_key(my_ctx, &new_key_info,
FSL_KEY_WRAP_UNWRAP, blob);
if (code != FSL_RETURN_OK_S) {
printf
("fsl_shw_establish_key(UNWRAP) returned: %s\n",
fsl_error_string(code));
} else {
fsl_shw_return_t err_err;
/* Try to decrypt what had been done with previous
incarnation. */
memset(decrypt_output, 0, len);
code =
fsl_shw_symmetric_decrypt(my_ctx,
&new_key_info,
sym_ctx, len,
ciphertext,
decrypt_output);
if (code != FSL_RETURN_OK_S) {
printf
("fsl_shw_symmetric_decrypt() returned: %s\n",
fsl_error_string(code));
} else {
if (!compare_result
(expected_plaintext, decrypt_output,
len, "decrypted plaintext")) {
passed = 1;
}
}
err_err =
fsl_shw_release_key(my_ctx, &new_key_info);
if (err_err != 0) {
printf
("Warning: could not release key with handle 0x%x: "
"%s\n", handle,
fsl_error_string(err_err));
}
}
}
}
out:
/* Clean up any allocated memory */
if (decrypt_output) {
free(decrypt_output);
}
if (blob) {
free(blob);
}
return passed;
}
/*!
* Test that software (user retrievable) key functions work correctly.
*
* Establish a known key, read it out to verify that it can be read, wrap and
* unwrap it, then verify that the unwrapped key can also be read.
*/
static void test_software_key(fsl_shw_uco_t * my_ctx,
uint32_t * total_passed_count,
uint32_t * total_failed_count)
{
fsl_shw_sko_t software_key;
fsl_shw_sko_t unwrap_key;
fsl_shw_return_t ret;
uint8_t software_key_read[sizeof(software_key_data)];
uint8_t unwrap_key_read[sizeof(software_key_data)];
uint8_t *wrapped_key_data = NULL;
int wrapped_key_size;
int passed = 0;
int failed = 0;
/* Establish a known software key */
fsl_shw_sko_init(&software_key, FSL_KEY_ALG_TDES);
fsl_shw_sko_set_key_length(&software_key, sizeof(software_key_data));
fsl_shw_sko_set_user_id(&software_key, 0x123456);
fsl_shw_sko_set_flags(&software_key, FSL_SKO_KEY_SW_KEY);
ret = fsl_shw_establish_key(my_ctx, &software_key, FSL_KEY_WRAP_ACCEPT,
software_key_data);
if (ret != FSL_RETURN_OK_S) {
printf("Establish software key from plaintext failed with %s\n",
fsl_error_string(ret));
failed++;
goto out;
}
/* Read the key value out */
ret = fsl_shw_read_key(my_ctx, &software_key, software_key_read);
if (ret != FSL_RETURN_OK_S) {
printf("Read software key failed with %s\n",
fsl_error_string(ret));
failed++;
goto out;
}
if (compare_result(software_key_data, software_key_read,
sizeof(software_key_data), "read key value")) {
failed++;
goto out;
}
/* Wrap the software key */
fsl_shw_sko_calculate_wrapped_size(&software_key, &wrapped_key_size);
/* Note: Double the calculated size to work around an error in
* fsl_shw_sko_calculate_wrapped_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, &software_key, wrapped_key_data);
if (ret != FSL_RETURN_OK_S) {
printf("Extract software 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;
}
/* Try to re-establish the software key */
fsl_shw_sko_init(&unwrap_key, FSL_KEY_ALG_TDES);
fsl_shw_sko_set_key_length(&unwrap_key, sizeof(software_key_data));
fsl_shw_sko_set_user_id(&unwrap_key, 0x123456);
fsl_shw_sko_set_flags(&unwrap_key, FSL_SKO_KEY_SW_KEY);
fsl_shw_establish_key(my_ctx, &unwrap_key, FSL_KEY_WRAP_UNWRAP,
wrapped_key_data);
if (ret != FSL_RETURN_OK_S) {
printf("Unwrap software key failed with %s\n",
fsl_error_string(ret));
failed++;
goto out;
}
/* Read the key value out */
ret = fsl_shw_read_key(my_ctx, &unwrap_key, unwrap_key_read);
printf("Read unwrapped software key return value %d\n", ret);
if (ret != FSL_RETURN_OK_S) {
printf("Read unwrapped software key failed with %s\n",
fsl_error_string(ret));
failed++;
goto out;
}
if (compare_result(software_key_data, unwrap_key_read,
sizeof(software_key_data),
"read unwrapped key value")) {
failed++;
goto out;
}
/* Release the unwrapped software key */
fsl_shw_release_key(my_ctx, &unwrap_key);
if (ret != FSL_RETURN_OK_S) {
printf("Release of unwrapped software key with %s\n",
fsl_error_string(ret));
failed++;
goto out;
}
passed++;
printf("Software key Passed\n");
out:
if (wrapped_key_data != NULL) {
free(wrapped_key_data);
}
*total_passed_count += passed;
*total_failed_count += failed;
return;
} /* end fn test_software_key */
/*!
* Test Key-Wrapping routines.
*/
void run_wrap(fsl_shw_uco_t * my_ctx, uint32_t * total_passed_count,
uint32_t * total_failed_count)
{
fsl_shw_sko_t key_info;
fsl_shw_scco_t *sym_ctx = NULL;
fsl_shw_return_t code;
uint8_t *encrypt_input = NULL;
uint8_t *decrypt_input = NULL;
uint8_t *encrypt_output = NULL;
uint8_t *decrypt_output = NULL;
uint8_t *blob = NULL;
uint32_t blob_length;
int passed_count = 0;
int failed_count = 0;
uint32_t handle;
int passed = 0;
int testno = 1;
int i;
fsl_shw_pco_t *cap = fsl_shw_get_capabilities(my_ctx);
uint32_t key_len = SECRET_KEY_SIZE;
fsl_shw_key_alg_t key_alg = SECRET_KEY_ALGORITHM;
if ((cap == NULL) || !fsl_shw_pco_check_black_key_supported(cap)) {
printf("Skipping Wrapped / Black Key Tests\n\n");
goto out;
}
if (fsl_shw_pco_check_sw_keys_supported(cap)) {
printf("Testing Software Keys.\n\n");
test_software_key(my_ctx, total_passed_count,
total_failed_count);
} else {
printf("Software Keys not supported, skipping.\n\n");
}
if (fsl_shw_pco_check_pk_supported(cap)) {
/* If the PK (program key) capability is detected, infer that this is
* running on a Dry Ice platform, and skip all the wrapping tests
* except the software key tests. */
printf
("Dry Ice platform detected, skipping non-software key Key Tests\n");
goto out;
}
/* Allocate memory for temporary objects */
sym_ctx = malloc(sizeof(*sym_ctx));
encrypt_input = malloc(sizeof(known_plaintext));
decrypt_input = malloc(sizeof(known_plaintext));
encrypt_output = malloc(2 * sizeof(known_plaintext));
decrypt_output = malloc(2 * sizeof(known_plaintext));
if ((sym_ctx == NULL) ||(encrypt_output == NULL) || (decrypt_output == NULL)
|| (encrypt_input == NULL) || (decrypt_input == NULL)
|| (sym_ctx == NULL)) {
printf
("Memory allocation problems. Skipping wrapped Key Tests\n");
*total_failed_count += 6;
goto out;
}
memcpy(encrypt_input, known_plaintext, sizeof(known_plaintext));
/* for test, fill with garbage */
memset(&key_info, 0x2d, sizeof(key_info));
memset(sym_ctx, 0x51, sizeof(*sym_ctx));
init_key_and_sym_ctx(key_alg, key_len, &key_info, sym_ctx);
fsl_shw_sko_set_user_id(&key_info, KEY_OWNER_ID);
printf
("Secret Key Test %d: Generate and use a random %d-byte RED"
" key\n", testno, key_len);
passed = create_key(my_ctx, &key_info, sym_ctx,
encrypt_input, sizeof(known_plaintext),
encrypt_output);
printf("Secret Key Test %d: %s\n\n", testno++,
passed ? "passed" : "failed");
if (passed) {
passed_count++;
} else {
failed_count++;
}
printf("Secret Key Test %d: Extract and Re-establish RED key\n",
testno);
fsl_shw_sko_get_established_info(&key_info, &handle);
passed = extract_reestablish_key(my_ctx, KEY_OWNER_ID, handle,
sym_ctx, encrypt_output,
encrypt_input,
sizeof(known_plaintext));
printf("Secret Key Test %d: %s\n\n", testno++,
passed ? "passed" : "failed");
if (passed) {
passed_count++;
} else {
failed_count++;
}
/* Now run tests with Known Key values of two different lengths. */
/* First time through is with ARC4 key */
key_len = KNOWN_ARC4_KEY_SIZE;
key_alg = KNOWN_ARC4_KEY_ALGORITHM;
for (i = 0; i < 2; i++) {
/* fill with garbage */
memset(&key_info, 0x2c, sizeof(key_info));
memset(sym_ctx, 0x51, sizeof(sym_ctx));
init_key_and_sym_ctx(key_alg, key_len, &key_info,
sym_ctx);
fsl_shw_sko_set_user_id(&key_info, KEY_OWNER_ID);
if (key_alg == FSL_KEY_ALG_TDES) {
memcpy(decrypt_input, TDES_known_ciphertext,
sizeof(known_plaintext));
} else {
memcpy(decrypt_input, ARC4_known_ciphertext,
sizeof(known_plaintext));
}
printf
("Secret Key Test %d: Establish a known %u-byte RED key\n",
testno, key_len);
passed = 0;
code = fsl_shw_establish_key(my_ctx, &key_info,
FSL_KEY_WRAP_ACCEPT,
known_key);
if (code != FSL_RETURN_OK_S) {
printf
("fsl_shw_establish_key(ACCEPT) returned: %s\n",
fsl_error_string(code));
} else {
memset(encrypt_output, 0,
sizeof(known_plaintext));
code =
fsl_shw_symmetric_encrypt(my_ctx, &key_info,
sym_ctx,
sizeof
(known_plaintext),
encrypt_input,
encrypt_output);
if (code != FSL_RETURN_OK_S) {
printf
("fsl_shw_symmetric_encrypt() returned: %s\n",
fsl_error_string(code));
} else {
if (!compare_result
(decrypt_input, encrypt_output,
sizeof(known_plaintext),
"encrypted ciphertext")) {
passed = 1;
}
}
}
printf("Secret Key Test %d: %s\n\n", testno++,
passed ? "passed" : "failed");
if (passed) {
passed_count++;
} else {
failed_count++;
}
printf
("Secret Key Test %d: Re-establish known %u-byte RED key\n",
testno, key_len);
passed = 0;
fsl_shw_sko_calculate_wrapped_size(&key_info,
&blob_length);
blob = malloc(blob_length + 1);
if (blob == NULL) {
printf("Allocation failed; aborting test\n");
} else {
blob[blob_length] = 0x42;
code =
fsl_shw_extract_key(my_ctx, &key_info,
blob);
if (code != FSL_RETURN_OK_S) {
fsl_shw_return_t err_err;
printf
("fsl_shw_extract_key() returned: %s\n",
fsl_error_string(code));
fsl_shw_sko_get_established_info
(&key_info, &handle);
err_err =
fsl_shw_release_key(my_ctx,
&key_info);
if (err_err != 0) {
printf
("Warning: could not release key with handle "
"0x%x: %s\n", handle,
fsl_error_string(err_err));
}
} else {
if (blob[blob_length] != 0x42) {
printf
("Wrapped key buffer was overwritten\n");
goto done;
}
if (key_alg == FSL_KEY_ALG_ARC4) {
fsl_shw_scco_init(sym_ctx,
key_alg,
FSL_SYM_MODE_STREAM);
fsl_shw_scco_set_flags(sym_ctx,
FSL_SYM_CTX_INIT);
} else {
if ((key_alg ==
FSL_KEY_ALG_TDES)
|| (key_alg ==
FSL_KEY_ALG_DES)) {
fsl_shw_sko_set_flags
(&key_info,
FSL_SKO_KEY_IGNORE_PARITY);
}
fsl_shw_scco_init(sym_ctx,
key_alg,
FSL_SYM_MODE_ECB);
}
fsl_shw_sko_set_user_id(&key_info,
KEY_OWNER_ID);
code =
fsl_shw_establish_key(my_ctx,
&key_info,
FSL_KEY_WRAP_UNWRAP,
blob);
if (code != FSL_RETURN_OK_S) {
printf
("fsl_shw_establish_key(UNWRAP) returned: %s\n",
fsl_error_string(code));
} else {
/* Try to decrypt what had been done with previous
incarnation. */
memset(decrypt_output, 0,
sizeof(known_plaintext));
code =
fsl_shw_symmetric_decrypt
(my_ctx, &key_info, sym_ctx,
sizeof(known_plaintext),
decrypt_input,
decrypt_output);
if (code != FSL_RETURN_OK_S) {
printf
("fsl_shw_symmetric_decrypt() returned:"
" %s\n",
fsl_error_string
(code));
} else {
if (!compare_result
(known_plaintext,
decrypt_output,
sizeof
(known_plaintext),
"decrypted plaintext"))
{
passed = 1;
}
}
fsl_shw_release_key(my_ctx,
&key_info);
}
}
}
done:
printf("Secret Key Test %d: %s\n\n", testno++,
passed ? "passed" : "failed");
if (passed) {
passed_count++;
} else {
failed_count++;
}
/* Next time through use TDES key */
key_len = KNOWN_TDES_KEY_SIZE;
key_alg = KNOWN_TDES_KEY_ALGORITHM;
} /* for i ... */
out:
printf("wrap: %d tests passed, %d tests failed\n",
passed_count, failed_count);
*total_passed_count += passed_count;
*total_failed_count += failed_count;
/* Clean up any allocated memory */
if (encrypt_input) {
free(encrypt_input);
}
if (decrypt_input) {
free(decrypt_input);
}
if (encrypt_output) {
free(encrypt_output);
}
if (decrypt_output) {
free(decrypt_output);
}
if (blob) {
free(blob);
}
return;
}