/* * 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; }