diff --git a/README.md b/README.md index e70c7e9..e4724e5 100644 --- a/README.md +++ b/README.md @@ -184,7 +184,14 @@ either a combination of the `--export-format-version B`, `--export-key-algorithm` and `--export-template` options, or using the `--export-header` option. For example: ``` -tr31-tool --kbpk AB2E09DB3EF0BA71E0CE6CD755C23A3B --export BF82DAC6A33DF92CE66E15B70E5DCEB6 --export-header B0128B1TX00N0300KS18FFFF00A0200001E00000KC0C000169E3KP0C00ECAD62 +tr31-tool --kbpk AB2E09DB3EF0BA71E0CE6CD755C23A3B --export BF82DAC6A33DF92CE66E15B70E5DCEB6 --export-header B0000B1TX00N0200KS18FFFF00A0200001E00000KC0C000169E3 +``` + +Individual optional blocks can also be added when exporting a TR-31 key block +by using the various `--export-opt-block-XX` functions, where `XX` is the +optional block identifier. For example: +``` +tr31-tool --kbpk AB2E09DB3EF0BA71E0CE6CD755C23A3B --export BF82DAC6A33DF92CE66E15B70E5DCEB6 --export-header B0000B1TX00N0000 --export-opt-block-KS FFFF00A0200001E00000 --export-opt-block-KC ``` Roadmap diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 5602b24..0afa7c9 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -702,11 +702,30 @@ if(TARGET tr31-tool AND BUILD_TESTING) PASS_REGULAR_EXPRESSION ${tr31_tool_test41_regex} ) + # test export header containing optional blocks and padding, but not adding additional optional blocks add_test(NAME tr31_tool_test42 COMMAND tr31-tool --kbpk 88E1AB2A2E3DD38C1FA039A536500CC8A87AB9D62DC92C01058FA79F44657DE6 --export 3F419E1CB7079442AA37474C2EFBF8B8 --export-header D1234M7HG00N0200HM0621PB0A5V5E8F ) set_tests_properties(tr31_tool_test42 PROPERTIES - PASS_REGULAR_EXPRESSION "^D0128M7HG00N0200HM0621PB0A5V5E8F" + PASS_REGULAR_EXPRESSION "^D0128M7HG00N0200HM0621PB0A5V5E8F" # note that optional block padding content is intentionally preserved + ) + + # test export header containing optional blocks and padding and also adding additional optional blocks + add_test(NAME tr31_tool_test43 + COMMAND tr31-tool --kbpk 88E1AB2A2E3DD38C1FA039A536500CC8A87AB9D62DC92C01058FA79F44657DE6 --export 3F419E1CB7079442AA37474C2EFBF8B8 --export-header D1234M7HG00N0200HM0621PB0A5V5E8F --export-opt-block-LB "MyKey" + ) + set_tests_properties(tr31_tool_test43 + PROPERTIES + PASS_REGULAR_EXPRESSION "^D0144M7HG00N0300HM0621LB09MyKeyPB11" + ) + + # test export header containing optional blocks but insufficient padding + add_test(NAME tr31_tool_test44 + COMMAND tr31-tool --kbpk 88E1AB2A2E3DD38C1FA039A536500CC8A87AB9D62DC92C01058FA79F44657DE6 --export 3F419E1CB7079442AA37474C2EFBF8B8 --export-header D1234M7HG00N0100HM0621 + ) + set_tests_properties(tr31_tool_test44 + PROPERTIES + PASS_REGULAR_EXPRESSION "^D0128M7HG00N0200HM0621PB0A" ) endif() diff --git a/src/tr31-tool.c b/src/tr31-tool.c index 03e6fae..b5e0578 100644 --- a/src/tr31-tool.c +++ b/src/tr31-tool.c @@ -96,7 +96,9 @@ static error_t argp_parser_helper(int key, char* arg, struct argp_state* state); static void* read_file(FILE* file, size_t* len); static int parse_hex(const char* hex, void* bin, size_t bin_len); static void print_hex(const void* buf, size_t length); +static void print_str(const void* buf, size_t length); static void print_str_with_quotes(const void* buf, size_t length); +static int tr31_init_from_header(const char* header, struct tr31_ctx_t* tr31_ctx); // argp option keys enum tr31_tool_option_keys_t { @@ -205,14 +207,14 @@ static error_t argp_parser_helper(int key, char* arg, struct argp_state* state) } else { // Copy argument - buf_len = strlen(arg) + 1; + buf_len = strlen(arg); buf = malloc(buf_len); memcpy(buf, arg, buf_len); } // Trim KEYBLOCK argument for (char* str = buf; buf_len; --buf_len) { - if (!isalnum(str[buf_len - 1])) { + if (!isgraph(str[buf_len - 1])) { str[buf_len - 1] = 0; } else { break; @@ -289,8 +291,8 @@ static error_t argp_parser_helper(int key, char* arg, struct argp_state* state) argp_error(state, "Export header must be at least 16 characters/bytes"); } for (size_t i = 0; i < strlen(arg); ++i) { - if (!isalnum(arg[i])) { - argp_error(state, "Export header must consist of alphanumeric characters (invalid character '%c' is not allowed)", arg[i]); + if (!isprint(arg[i])) { + argp_error(state, "Export header must consist of printable characters (invalid character '%c' is not allowed)", arg[i]); } } options->export_header = arg; @@ -383,8 +385,8 @@ static error_t argp_parser_helper(int key, char* arg, struct argp_state* state) argp_error(state, "Export optional block DA must be a multiple of 5 bytes"); } for (size_t i = 0; i < strlen(arg); ++i) { - if (!isprint(arg[i]) || isspace(arg[i])) { - argp_error(state, "Export header must consist of printable characters (invalid character '%c' is not allowed)", arg[i]); + if (!isalnum(arg[i])) { + argp_error(state, "Export optional block DA consist of alphanumeric characters (invalid character '%c' is not allowed)", arg[i]); } } options->export_opt_block_DA = arg; @@ -657,6 +659,117 @@ static void print_str_with_quotes(const void* buf, size_t length) printf("\""); } +static int tr31_init_from_header(const char* header, struct tr31_ctx_t* tr31_ctx) +{ + int r; + size_t header_len; + size_t enc_block_size; + size_t payload_and_authenticator_len; + char* padded_header = NULL; + size_t key_block_len; + + header_len = strlen(header); + if (header_len < 16) { + return TR31_ERROR_INVALID_LENGTH_FIELD; + } + + // determine encryption block size and payload+authenticator length + switch (header[0]) { + case 'A': + case 'C': + enc_block_size = 8; // DES block size + payload_and_authenticator_len = 32 + 8; + break; + + case 'B': + enc_block_size = 8; // DES block size + payload_and_authenticator_len = 32 + 16; + break; + + case 'D': + case 'E': + enc_block_size = 16; // AES block size + payload_and_authenticator_len = 48 + 16; + break; + + default: + return TR31_ERROR_UNSUPPORTED_VERSION; + } + + // ensure that header length is a multiple of encryption block size + // and add fake optional block padding if necessary + if (header_len & (enc_block_size-1)) { + unsigned int pb_len = 4; // minimum length of optional block PB + + if (header[12] != '0' || header[13] > '8') { + // only support single digit optional block counts below 9 for now + return TR31_ERROR_INVALID_NUMBER_OF_OPTIONAL_BLOCKS_FIELD; + } + + // compute required padding length + if ((header_len + pb_len) & (enc_block_size-1)) { // if further padding is required + pb_len = ((header_len + 4 + enc_block_size) & ~(enc_block_size-1)) - header_len; + } + + // sanity check + if (pb_len < 4 || pb_len > 15) { + return -1; + } + + // build new header + header_len = header_len + pb_len; + padded_header = malloc(header_len + 1); + snprintf( + padded_header, + header_len + 1, + "%sPB%02X%.*s", + header, + pb_len, + pb_len - 4, + "000000000000000" + ); + padded_header[13]++; // increment optional block count + header = padded_header; + } + + // determine fake key block length to allow parsing of header + key_block_len = header_len + payload_and_authenticator_len; + if (key_block_len > 9999) { + fprintf(stderr, "Export header too large\n"); + return TR31_ERROR_INVALID_LENGTH_FIELD; + } + + // build fake key block to allow parsing of header + char tmp_keyblock[key_block_len]; + memcpy(tmp_keyblock, header, header_len); + memset(tmp_keyblock + header_len, '0', sizeof(tmp_keyblock) - header_len); + + // fix length field to allow parsing of header + char tmp[5]; + snprintf(tmp, sizeof(tmp), "%04zu", sizeof(tmp_keyblock)); + memcpy(tmp_keyblock + 1, tmp, 4); + + // misuse TR-31 import function to parse header into TR-31 context object + r = tr31_import(tmp_keyblock, sizeof(tmp_keyblock), NULL, tr31_ctx); + if (r) { + return r; + } + + // cleanup padded header and remove fake optional block PB from context object + if (padded_header) { + free(padded_header); + if (tr31_ctx->opt_blocks_count) { + tr31_ctx->opt_blocks_count -= 1; + if (tr31_ctx->opt_blocks[tr31_ctx->opt_blocks_count].data) { + free(tr31_ctx->opt_blocks[tr31_ctx->opt_blocks_count].data); + tr31_ctx->opt_blocks[tr31_ctx->opt_blocks_count].data = NULL; + } + } + } + + return 0; +} + // TR-31 KBPK populating helper function static int populate_kbpk(const struct tr31_tool_options_t* options, unsigned int format_version, struct tr31_key_t* kbpk) { @@ -716,10 +829,10 @@ static int do_tr31_import(const struct tr31_tool_options_t* options) if (options->kbpk) { // if key block protection key was provided // parse and decrypt TR-31 key block - r = tr31_import(options->key_block, &kbpk, &tr31_ctx); + r = tr31_import(options->key_block, options->key_block_len, &kbpk, &tr31_ctx); } else { // else if no key block protection key was provided // parse TR-31 key block - r = tr31_import(options->key_block, NULL, &tr31_ctx); + r = tr31_import(options->key_block, options->key_block_len, NULL, &tr31_ctx); } // check for errors if (r) { @@ -947,7 +1060,10 @@ static int do_tr31_import(const struct tr31_tool_options_t* options) // cleanup tr31_key_release(&kbpk); - tr31_release(&tr31_ctx); + if (!ret) { + // only cleanup TR-31 context object if tr31_import() was successful + tr31_release(&tr31_ctx); + } return ret; } @@ -1003,7 +1119,7 @@ static int populate_tr31_from_template(const struct tr31_tool_options_t* options // populate TR-31 context object r = tr31_init(options->export_format_version, &key, tr31_ctx); if (r) { - fprintf(stderr, "tr31_init() failed; r=%d\n", r); + fprintf(stderr, "tr31_init() error %d: %s\n", r, tr31_get_error_string(r)); return 1; } @@ -1015,46 +1131,8 @@ static int populate_tr31_from_header(const struct tr31_tool_options_t* options, { int r; - // determine fake key block length to allow parsing of header - size_t export_header_len = strlen(options->export_header); - size_t tmp_key_block_len = export_header_len; - switch (options->export_header[0]) { - case 'A': - case 'C': - tmp_key_block_len += 32 + 8 + 1; - break; - - case 'B': - tmp_key_block_len += 32 + 16 + 1; - break; - - case 'D': - case 'E': - tmp_key_block_len += 48 + 16 + 1; - break; - - default: - fprintf(stderr, "Unsupported key block format version\n"); - return 1; - } - if (tmp_key_block_len > 9999) { - fprintf(stderr, "Export header too large\n"); - return 1; - } - - // build fake key block to allow parsing of header - char tmp_keyblock[tmp_key_block_len]; - memcpy(tmp_keyblock, options->export_header, export_header_len); - memset(tmp_keyblock + export_header_len, '0', sizeof(tmp_keyblock) - export_header_len - 1); - tmp_keyblock[sizeof(tmp_keyblock) - 1] = 0; - - // fix length field to allow parsing of header - char tmp[5]; - snprintf(tmp, sizeof(tmp), "%04zu", tmp_key_block_len - 1); - memcpy(tmp_keyblock + 1, tmp, 4); - - // misuse TR-31 import function to parse header into TR-31 context object - r = tr31_import(tmp_keyblock, NULL, tr31_ctx); + // parse export header + r = tr31_init_from_header(options->export_header, tr31_ctx); if (r) { fprintf(stderr, "Error while parsing export header; error %d: %s\n", r, tr31_get_error_string(r)); return 1; @@ -1063,7 +1141,7 @@ static int populate_tr31_from_header(const struct tr31_tool_options_t* options, // populate key data r = tr31_key_set_data(&tr31_ctx->key, options->export_key_buf, options->export_key_buf_len); if (r) { - fprintf(stderr, "tr31_key_set_data() failed; r=%d\n", r); + fprintf(stderr, "tr31_key_set_data() error %d: %s\n", r, tr31_get_error_string(r)); return 1; } diff --git a/src/tr31.c b/src/tr31.c index fde5440..3371ead 100644 --- a/src/tr31.c +++ b/src/tr31.c @@ -90,6 +90,29 @@ struct tr31_payload_t { #define TR31_MIN_PAYLOAD_LENGTH (DES_BLOCK_SIZE) #define TR31_MIN_KEY_BLOCK_LENGTH (sizeof(struct tr31_header_t) + TR31_MIN_PAYLOAD_LENGTH + 8) // Minimum TR-31 key block length: header + minimum payload + authenticator +// Internal processing state +struct tr31_state_t { + // flags used during processing + uint32_t flags; + + // encryption block size used for header length validation + unsigned int enc_block_size; + + // buffer containing: + // - verbatim header + // - binary (hex decoded) payload + // - binary (hex decoded) authenticator + size_t decoded_key_block_length; + void* decoded_key_block; + + // lengths and pointers for decoded key block buffer + size_t header_length; + size_t payload_length; + void* payload; + size_t authenticator_length; + void* authenticator; +}; + // helper functions static int dec_to_int(const char* str, size_t str_len); static void int_to_dec(unsigned int value, char* str, size_t str_len); @@ -107,14 +130,17 @@ static int tr31_opt_block_validate_hash_algorithm(uint8_t hash_algorithm); static int tr31_opt_block_parse(const void* ptr, size_t remaining_len, size_t* opt_block_len, struct tr31_opt_ctx_t* opt_ctx); static int tr31_opt_block_validate_iso8601(const char* ts_str, size_t ts_str_len); static int tr31_opt_block_export(const struct tr31_opt_ctx_t* opt_ctx, size_t remaining_len, size_t* opt_blk_len, void* ptr); -static int tr31_opt_block_export_PB(const struct tr31_ctx_t* ctx, size_t pb_len, struct tr31_opt_blk_t* opt_blk); -static int tr31_compute_final_lengths(struct tr31_ctx_t* ctx); -static int tr31_tdes_decrypt_verify_variant_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk); -static int tr31_tdes_encrypt_sign_variant_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk); -static int tr31_tdes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk); -static int tr31_tdes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk); -static int tr31_aes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk); -static int tr31_aes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk); +static int tr31_opt_block_export_PB(const struct tr31_state_t* state, size_t pb_len, struct tr31_opt_blk_t* opt_blk); +static int tr31_state_init(uint32_t flags, uint8_t version_id, struct tr31_state_t* state); +static int tr31_state_prepare_import(struct tr31_state_t* state, const void* key_block, size_t key_block_len, size_t header_len); +static int tr31_state_prepare_export(struct tr31_state_t* state, struct tr31_header_t* header, size_t header_len, size_t key_block_buf_len, const struct tr31_key_t* key); +static void tr31_state_release(struct tr31_state_t* state); +static int tr31_tdes_decrypt_verify_variant_binding(const struct tr31_state_t* state, const struct tr31_key_t* kbpk, struct tr31_key_t* key); +static int tr31_tdes_encrypt_sign_variant_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk); +static int tr31_tdes_decrypt_verify_derivation_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk, struct tr31_key_t* key); +static int tr31_tdes_encrypt_sign_derivation_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk); +static int tr31_aes_decrypt_verify_derivation_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk, struct tr31_key_t* key); +static int tr31_aes_encrypt_sign_derivation_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk); static int dec_to_int(const char* str, size_t str_len) { @@ -487,6 +513,7 @@ void tr31_key_release(struct tr31_key_t* key) crypto_cleanse(key->data, key->length); free(key->data); key->data = NULL; + key->kcv_len = 0; } } @@ -528,13 +555,9 @@ int tr31_key_set_data(struct tr31_key_t* key, const void* data, size_t length) return -1; } + // release existing key data tr31_key_release(key); - // copy key data - key->length = length; - key->data = calloc(1, key->length); - memcpy(key->data, data, key->length); - // update KCV key->kcv_len = 0; memset(&key->kcv, 0, sizeof(key->kcv)); @@ -542,28 +565,33 @@ int tr31_key_set_data(struct tr31_key_t* key, const void* data, size_t length) // use legacy KCV for TDES key // see ANSI X9.24-1:2017, 7.7.2 key->kcv_algorithm = TR31_OPT_BLOCK_KCV_LEGACY; - r = crypto_tdes_kcv_legacy(key->data, key->length, key->kcv); + r = crypto_tdes_kcv_legacy(data, length, key->kcv); if (r) { // failed to compute KCV return TR31_ERROR_KCV_NOT_AVAILABLE; } key->kcv_len = DES_KCV_SIZE_LEGACY; - return 0; } else if (key->algorithm == TR31_KEY_ALGORITHM_AES) { // use CMAC-based KCV for AES key // see ANSI X9.24-1:2017, 7.7.2 key->kcv_algorithm = TR31_OPT_BLOCK_KCV_CMAC; - r = crypto_aes_kcv(key->data, key->length, key->kcv); + r = crypto_aes_kcv(data, length, key->kcv); if (r) { // failed to compute KCV return TR31_ERROR_KCV_NOT_AVAILABLE; } key->kcv_len = AES_KCV_SIZE; - return 0; + + } else { + // key algorithm not suitable for KCV computation; continue } - // key algorithm not suitable for KCV computation; continue + // copy key data + key->length = length; + key->data = malloc(key->length); + memcpy(key->data, data, key->length); + return 0; } @@ -673,17 +701,44 @@ static struct tr31_opt_ctx_t* tr31_opt_block_alloc( ) { struct tr31_opt_ctx_t* opt_ctx; + bool opt_blk_pb_found = false; if (!ctx) { return NULL; } // repeated optional block IDs are not allowed + // and optional block PB must always be last // see ANSI X9.143:2021, 6.3.6 - opt_ctx = tr31_opt_block_find(ctx, id); - if (opt_ctx) { - // existing optional block found - return NULL; + for (size_t i = 0; i < ctx->opt_blocks_count; ++i) { + if (ctx->opt_blocks[i].id == id) { + // existing optional block found + return NULL; + } + + if (ctx->opt_blocks[i].id == TR31_OPT_BLOCK_PB) { + // optional block PB found + opt_blk_pb_found = true; + } + } + + // if optional block PB already exists, remove all instances + // NOTE: it will be recreated by tr31_export() + // NOTE: if no new optional blocks are added, PB is intentionally preserved + if (opt_blk_pb_found) { + for (size_t i = 0; i < ctx->opt_blocks_count; ++i) { + if (ctx->opt_blocks[i].id == TR31_OPT_BLOCK_PB) { + free(ctx->opt_blocks[i].data); + ctx->opt_blocks[i].data = NULL; + + ctx->opt_blocks_count -= 1; + if (i < ctx->opt_blocks_count) { + size_t remaining_count = ctx->opt_blocks_count - i; + size_t remaining_bytes = sizeof(*ctx->opt_blocks) * remaining_count; + memmove(&ctx->opt_blocks[i], &ctx->opt_blocks[i + 1], remaining_bytes); + } + } + } } // grow optional block array @@ -1770,29 +1825,43 @@ int tr31_opt_block_decode_WP( int tr31_import( const char* key_block, + size_t key_block_len, const struct tr31_key_t* kbpk, struct tr31_ctx_t* ctx ) { int r; - size_t key_block_len; const struct tr31_header_t* header; + struct tr31_state_t state; size_t opt_blk_len_total = 0; - unsigned int enc_block_size; const void* ptr; if (!key_block || !ctx) { return -1; } - key_block_len = strlen(key_block); - header = (const struct tr31_header_t*)key_block; - // validate minimum length if (key_block_len < TR31_MIN_KEY_BLOCK_LENGTH) { return TR31_ERROR_INVALID_LENGTH; } + // validate key block as printable ASCII (format PA) + r = tr31_validate_format_pa(key_block, key_block_len); + if (r) { + return TR31_ERROR_INVALID_KEY_BLOCK_STRING; + } + + // initialise processing state object + // this will populate: + // - state.enc_block_size + // - state.authenticator_length + header = (const struct tr31_header_t*)key_block; + r = tr31_state_init(0, header->version_id, &state); + if (r) { + // return error value as-is + return r; + } + // initialise TR-31 context object r = tr31_init(header->version_id, NULL, ctx); if (r) { @@ -1818,7 +1887,6 @@ int tr31_import( &ctx->key ); if (r) { - tr31_key_release(&ctx->key); // return error value as-is return r; } @@ -1863,82 +1931,33 @@ int tr31_import( ptr += opt_blk_len; } - // validate key block format version - // set associated authenticator length - // set encryption block size for header length validation - switch (ctx->version) { - case TR31_VERSION_A: - case TR31_VERSION_C: - ctx->authenticator_length = 4; // 4 bytes; 8 ASCII hex digits - enc_block_size = DES_BLOCK_SIZE; - break; - - case TR31_VERSION_B: - ctx->authenticator_length = 8; // 8 bytes; 16 ASCII hex digits - enc_block_size = DES_BLOCK_SIZE; - break; - - case TR31_VERSION_D: - ctx->authenticator_length = 16; // 16 bytes; 32 ASCII hex digits - enc_block_size = AES_BLOCK_SIZE; - break; - - case TR31_VERSION_E: - ctx->authenticator_length = 16; // 16 bytes; 32 ASCII hex digits - enc_block_size = AES_BLOCK_SIZE; - break; - - default: - // invalid format version - return -1; - } - // ANSI X9.143:2021, 6.3.6 (page 19) indicates that the padding block must // result in the total length of all optional blocks being a multiple of // the encryption block length. // ISO 20038:2017, A.2.1 (page 10) indicates that the total length of all // optional blocks must be a multiple of the encryption block size and // does not make an exception for format version E. - // So we'll use the encryption block size which is determined by the TR-31 - // format version. - if (opt_blk_len_total & (enc_block_size-1)) { - return TR31_ERROR_INVALID_OPTIONAL_BLOCK_DATA; - } - - // ensure that current pointer is valid for minimal payload and authenticator - if (ptr - (void*)header + TR31_MIN_PAYLOAD_LENGTH + (ctx->authenticator_length * 2) > key_block_len) { - r = TR31_ERROR_INVALID_LENGTH; + // So we'll use the encryption block size which is determined by the key + // block format version. + if (opt_blk_len_total & (state.enc_block_size-1)) { + r = TR31_ERROR_INVALID_OPTIONAL_BLOCK_PADDING; goto error; } - // update header data in context object - ctx->header_length = ptr - (void*)header; - ctx->header = (void*)header; - - // determine payload length - size_t key_block_payload_length = key_block_len - ctx->header_length - (ctx->authenticator_length * 2); - ctx->payload_length = key_block_payload_length / 2; - - // add payload data to context object - ctx->payload = calloc(1, ctx->payload_length); - r = hex_to_bin(ptr, key_block_payload_length, ctx->payload, ctx->payload_length); - if (r) { - r = TR31_ERROR_INVALID_PAYLOAD_FIELD; - goto error; - } - ptr += key_block_payload_length; - - // ensure that current point is valid for remaining authenticator - if (ptr - (void*)header + (ctx->authenticator_length * 2) != key_block_len) { - r = TR31_ERROR_INVALID_LENGTH; - goto error; - } - - // add authenticator to context object - ctx->authenticator = calloc(1, ctx->authenticator_length); - r = hex_to_bin(ptr, ctx->authenticator_length * 2, ctx->authenticator, ctx->authenticator_length); + // prepare state object for import processing + // this function requires: + // - state.authenticator_length + // and will: + // - validate that the payload and authenticator are hex encoded + // - populate remaining fields required by binding functions + r = tr31_state_prepare_import( + &state, + key_block, + ctx->length, + ptr - (void*)header + ); if (r) { - r = TR31_ERROR_INVALID_AUTHENTICATOR_FIELD; + // return error value as-is goto error; } @@ -1964,7 +1983,7 @@ int tr31_import( // not appear to indicate a minimum or maximum for key length // padding, and therefore this implementation only enforces the // cipher block size - if (ctx->payload_length & (DES_BLOCK_SIZE-1)) { + if (state.payload_length & (DES_BLOCK_SIZE-1)) { // payload length must be a multiple of TDES block size // for format version A, B, C r = TR31_ERROR_INVALID_KEY_LENGTH; @@ -1973,10 +1992,10 @@ int tr31_import( if (ctx->version == TR31_VERSION_A || ctx->version == TR31_VERSION_C) { // verify and decrypt payload - r = tr31_tdes_decrypt_verify_variant_binding(ctx, kbpk); + r = tr31_tdes_decrypt_verify_variant_binding(&state, kbpk, &ctx->key); } else if (ctx->version == TR31_VERSION_B) { // decrypt and verify payload - r = tr31_tdes_decrypt_verify_derivation_binding(ctx, kbpk); + r = tr31_tdes_decrypt_verify_derivation_binding(&state, kbpk, &ctx->key); } else { // invalid format version return -1; @@ -2018,7 +2037,7 @@ int tr31_import( // TR-31:2018 nor ISO 20038:2017 appear to indicate a minimum or // maximum for key length padding, and therefore this // implementation only enforces the cipher block size - if (ctx->payload_length & (AES_BLOCK_SIZE-1)) { + if (state.payload_length & (AES_BLOCK_SIZE-1)) { // payload length must be a multiple of AES block size // for format version D r = TR31_ERROR_INVALID_KEY_LENGTH; @@ -2026,7 +2045,7 @@ int tr31_import( } // decrypt and verify payload - r = tr31_aes_decrypt_verify_derivation_binding(ctx, kbpk); + r = tr31_aes_decrypt_verify_derivation_binding(&state, kbpk, &ctx->key); if (r) { // return error value as-is goto error; @@ -2069,7 +2088,7 @@ int tr31_import( } // decrypt and verify payload - r = tr31_aes_decrypt_verify_derivation_binding(ctx, kbpk); + r = tr31_aes_decrypt_verify_derivation_binding(&state, kbpk, &ctx->key); if (r) { // return error value as-is goto error; @@ -2115,65 +2134,48 @@ int tr31_import( error: tr31_release(ctx); exit: + tr31_state_release(&state); return r; } int tr31_export( - struct tr31_ctx_t* ctx, + const struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk, char* key_block, - size_t key_block_len + size_t key_block_buf_len ) { int r; + struct tr31_state_t state; struct tr31_header_t* header; size_t opt_blk_len_total = 0; - unsigned int enc_block_size; void* ptr; - if (!ctx || !kbpk || !key_block || !key_block_len) { + if (!ctx || !kbpk || !key_block || !key_block_buf_len) { return -1; } if (!ctx->key.data || !ctx->key.length) { return -2; } - // ensure space for null-termination - --key_block_len; - - // validate minimum length - if (key_block_len < TR31_MIN_KEY_BLOCK_LENGTH) { + // validate minimum length (+1 for null-termination) + if (key_block_buf_len < TR31_MIN_KEY_BLOCK_LENGTH + 1) { return TR31_ERROR_INVALID_LENGTH; } - memset(key_block, 0, key_block_len); - - // validate key block format version - // set encryption block size for header padding - switch (ctx->version) { - case TR31_VERSION_A: - case TR31_VERSION_C: - // supported - enc_block_size = DES_BLOCK_SIZE; - break; - case TR31_VERSION_B: - // supported - enc_block_size = DES_BLOCK_SIZE; - break; + // ensure null-termination + memset(key_block, 0, key_block_buf_len); + --key_block_buf_len; - case TR31_VERSION_D: - // supported - enc_block_size = AES_BLOCK_SIZE; - break; - - case TR31_VERSION_E: - // supported - enc_block_size = AES_BLOCK_SIZE; - break; - - default: - // unsupported - return TR31_ERROR_UNSUPPORTED_VERSION; + // initialise processing state object + // this will populate: + // - state.flags + // - state.enc_block_size + // - state.authenticator_length + r = tr31_state_init(ctx->export_flags, ctx->version, &state); + if (r) { + // return error value as-is + return r; } // populate key block header @@ -2261,7 +2263,7 @@ int tr31_export( size_t opt_blk_len; r = tr31_opt_block_export( &ctx->opt_blocks[i], - (void*)key_block + key_block_len - ptr, + (void*)key_block + key_block_buf_len - ptr, &opt_blk_len, ptr ); @@ -2285,21 +2287,21 @@ int tr31_export( // does not make an exception for format version E. // So we'll use the encryption block size which is determined by the TR-31 // format version. - if (opt_blk_len_total & (enc_block_size-1)) { + if (opt_blk_len_total & (state.enc_block_size-1)) { unsigned int pb_len = 4; // Minimum length of optional block PB // compute required padding length - if ((opt_blk_len_total + pb_len) & (enc_block_size-1)) { // if further padding is required - pb_len = ((opt_blk_len_total + 4 + enc_block_size) & ~(enc_block_size-1)) - opt_blk_len_total; + if ((opt_blk_len_total + pb_len) & (state.enc_block_size-1)) { // if further padding is required + pb_len = ((opt_blk_len_total + 4 + state.enc_block_size) & ~(state.enc_block_size-1)) - opt_blk_len_total; } - if (ptr + pb_len - (void*)header > key_block_len) { + if (ptr + pb_len - (void*)header > key_block_buf_len) { // optional block length exceeds total key block length return TR31_ERROR_INVALID_LENGTH; } // populate optional block PB - r = tr31_opt_block_export_PB(ctx, pb_len, ptr); + r = tr31_opt_block_export_PB(&state, pb_len, ptr); if (r) { // return error value as-is return r; @@ -2315,134 +2317,126 @@ int tr31_export( ptr += pb_len; } - // update header data in context object - ctx->header_length = ptr - (void*)header; - ctx->header = (void*)header; - - // determine final key block lengths, including key obfuscation padding - // this will populate these fields: - // - ctx->length - // - ctx->payload_length - // - ctx->authenticator_length - r = tr31_compute_final_lengths(ctx); + // prepare state object for export processing + // this function requires: + // - state.authenticator_length + // and will: + // - apply key obfuscation padding + // - encode wrapped key + // - update length in header + // - populate remaining state fields required by binding functions + r = tr31_state_prepare_export( + &state, + header, + ptr - (void*)header, + key_block_buf_len, + &ctx->key + ); if (r) { // return error value as-is return r; } - if (ctx->length > key_block_len) { - return TR31_ERROR_INVALID_LENGTH; - } - - // update key block length in header - int_to_dec(ctx->length, header->length, sizeof(header->length)); - - // free internal buffers that my be populated due to reuse of the context object - if (ctx->payload) { - free(ctx->payload); - ctx->payload = NULL; - } - if (ctx->authenticator) { - free(ctx->authenticator); - ctx->authenticator = NULL; - } switch (ctx->version) { case TR31_VERSION_A: case TR31_VERSION_C: // only allow TDES key block protection keys if (kbpk->algorithm != TR31_KEY_ALGORITHM_TDES) { - return TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM; + r = TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM; + goto error; } // encrypt and sign payload - // this will populate: - // ctx->payload - // ctx->authenticator - r = tr31_tdes_encrypt_sign_variant_binding(ctx, kbpk); + // this will write data into: + // - state.payload + // - state.authenticator + r = tr31_tdes_encrypt_sign_variant_binding(&state, kbpk); if (r) { // return error value as-is - return r; + goto error; } break; case TR31_VERSION_B: // only allow TDES key block protection keys if (kbpk->algorithm != TR31_KEY_ALGORITHM_TDES) { - return TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM; + r = TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM; + goto error; } // sign and encrypt payload - // this will populate: - // ctx->payload - // ctx->authenticator - r = tr31_tdes_encrypt_sign_derivation_binding(ctx, kbpk); + // this will write data into: + // - state.payload + // - state.authenticator + r = tr31_tdes_encrypt_sign_derivation_binding(&state, kbpk); if (r) { // return error value as-is - return r; + goto error; } break; case TR31_VERSION_D: // only allow AES key block protection keys if (kbpk->algorithm != TR31_KEY_ALGORITHM_AES) { - return TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM; + r = TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM; + goto error; } // sign and encrypt payload - // this will populate: - // ctx->payload - // ctx->authenticator - r = tr31_aes_encrypt_sign_derivation_binding(ctx, kbpk); + // this will write data into: + // - state.payload + // - state.authenticator + r = tr31_aes_encrypt_sign_derivation_binding(&state, kbpk); if (r) { // return error value as-is - return r; + goto error; } break; case TR31_VERSION_E: // only allow AES key block protection keys if (kbpk->algorithm != TR31_KEY_ALGORITHM_AES) { - return TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM; + r = TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM; + goto error; } // sign and encrypt payload - // this will populate: - // ctx->payload - // ctx->authenticator - r = tr31_aes_encrypt_sign_derivation_binding(ctx, kbpk); + // this will write data into: + // - state.payload + // - state.authenticator + r = tr31_aes_encrypt_sign_derivation_binding(&state, kbpk); if (r) { // return error value as-is - return r; + goto error; } break; default: // invalid format version - return -5; - } - - // ensure that encrypted payload and authenticator are available - if (!ctx->payload || !ctx->authenticator) { - // internal error - return -6; + r = -5; + goto error; } - // add payload to key block - r = bin_to_hex(ctx->payload, ctx->payload_length, ptr, key_block_len); + // add payload and authenticator to key block output + r = bin_to_hex( + state.payload, + state.payload_length + state.authenticator_length, + ptr, + key_block_buf_len - state.header_length + ); if (r) { // internal error - return -7; + r = -6; + goto error; } - ptr += (ctx->payload_length * 2); - // add authenticator to key block - r = bin_to_hex(ctx->authenticator, ctx->authenticator_length, ptr, key_block_len); - if (r) { - // internal error - return -8; - } + r = 0; + goto exit; - return 0; +error: +exit: + tr31_state_release(&state); + return r; } static int tr31_opt_block_parse( @@ -2720,7 +2714,7 @@ static int tr31_opt_block_export( } static int tr31_opt_block_export_PB( - const struct tr31_ctx_t* ctx, + const struct tr31_state_t* state, size_t pb_len, struct tr31_opt_blk_t* opt_blk ) @@ -2728,7 +2722,7 @@ static int tr31_opt_block_export_PB( opt_blk->id = htons(TR31_OPT_BLOCK_PB); int_to_hex(pb_len, opt_blk->length, sizeof(opt_blk->length)); - if ((ctx->export_flags & TR31_EXPORT_ZERO_OPT_BLOCK_PB) == 0) { + if ((state->flags & TR31_EXPORT_ZERO_OPT_BLOCK_PB) == 0) { // populate with random data and then transpose to the required range crypto_rand(opt_blk->data, pb_len - 4); } else { @@ -2765,22 +2759,112 @@ static int tr31_opt_block_export_PB( return 0; } -static int tr31_compute_final_lengths(struct tr31_ctx_t* ctx) +static int tr31_state_init(uint32_t flags, uint8_t version_id, struct tr31_state_t* state) +{ + memset(state, 0, sizeof(*state)); + state->flags = flags; + + // determine authenticator length and encryption block size + switch (version_id) { + case TR31_VERSION_A: + case TR31_VERSION_C: + state->enc_block_size = DES_BLOCK_SIZE; + state->authenticator_length = 4; // 4 bytes; 8 ASCII hex digits + break; + + case TR31_VERSION_B: + state->enc_block_size = DES_BLOCK_SIZE; + state->authenticator_length = 8; // 8 bytes; 16 ASCII hex digits + break; + + case TR31_VERSION_D: + state->enc_block_size = AES_BLOCK_SIZE; + state->authenticator_length = 16; // 16 bytes; 32 ASCII hex digits + break; + + case TR31_VERSION_E: + state->enc_block_size = AES_BLOCK_SIZE; + state->authenticator_length = 16; // 16 bytes; 32 ASCII hex digits + break; + + default: + return TR31_ERROR_UNSUPPORTED_VERSION; + } + + return 0; +} + +static int tr31_state_prepare_import( + struct tr31_state_t* state, + const void* key_block, + size_t key_block_len, + size_t header_len +) +{ + int r; + size_t authenticator_hex_length; + size_t payload_hex_length; + const void* ptr; + + // ensure that key block length is valid for minimal payload and authenticator + authenticator_hex_length = state->authenticator_length * 2; + if (header_len + TR31_MIN_PAYLOAD_LENGTH + authenticator_hex_length > key_block_len) { + return TR31_ERROR_INVALID_LENGTH; + } + + // populate various lengths + state->header_length = header_len; + payload_hex_length = key_block_len - state->header_length - authenticator_hex_length; + state->payload_length = payload_hex_length / 2; + + // prepare decoded key block buffer + state->decoded_key_block_length = state->header_length + state->payload_length + state->authenticator_length; + state->decoded_key_block = malloc(state->decoded_key_block_length); + memcpy(state->decoded_key_block, key_block, state->header_length); + + // decode payload + ptr = key_block + header_len; + state->payload = state->decoded_key_block + state->header_length; + r = hex_to_bin(ptr, payload_hex_length, state->payload, state->payload_length); + if (r) { + return TR31_ERROR_INVALID_PAYLOAD_FIELD; + } + + // decode authenticator + ptr += payload_hex_length; + state->authenticator = state->payload + state->payload_length; + r = hex_to_bin(ptr, authenticator_hex_length, state->authenticator, state->authenticator_length); + if (r) { + return TR31_ERROR_INVALID_AUTHENTICATOR_FIELD; + } + + return 0; +} + +static int tr31_state_prepare_export( + struct tr31_state_t* state, + struct tr31_header_t* header, + size_t header_len, + size_t key_block_buf_len, + const struct tr31_key_t* key +) { size_t padded_key_length; + size_t length; + struct tr31_payload_t* payload; // validate key length by algorithm // this ensures that key length cannot exceed padded key length - switch (ctx->key.algorithm) { + switch (key->algorithm) { case TR31_KEY_ALGORITHM_TDES: - if (ctx->key.length > 24) { + if (key->length > 24) { // invalid TDES key length return TR31_ERROR_INVALID_KEY_LENGTH; } break; case TR31_KEY_ALGORITHM_AES: - if (ctx->key.length > 32) { + if (key->length > 32) { // invalid AES key length return TR31_ERROR_INVALID_KEY_LENGTH; } @@ -2788,12 +2872,12 @@ static int tr31_compute_final_lengths(struct tr31_ctx_t* ctx) } // use key length as-is by default - padded_key_length = ctx->key.length; + padded_key_length = key->length; - if ((ctx->export_flags & TR31_EXPORT_NO_KEY_LENGTH_OBFUSCATION) == 0) { + if ((state->flags & TR31_EXPORT_NO_KEY_LENGTH_OBFUSCATION) == 0) { // apply key length obfuscation // see ANSI X9.143:2021, 5 and 6.1 - switch (ctx->key.algorithm) { + switch (key->algorithm) { case TR31_KEY_ALGORITHM_TDES: // use maximum TDES length padded_key_length = 24; @@ -2806,26 +2890,22 @@ static int tr31_compute_final_lengths(struct tr31_ctx_t* ctx) } } - switch (ctx->version) { + switch (header->version_id) { case TR31_VERSION_A: case TR31_VERSION_C: - ctx->payload_length = DES_CIPHERTEXT_LENGTH(sizeof(struct tr31_payload_t) + padded_key_length); - ctx->authenticator_length = 4; // 4 bytes; 8 ASCII hex digits + state->payload_length = DES_CIPHERTEXT_LENGTH(sizeof(struct tr31_payload_t) + padded_key_length); break; case TR31_VERSION_B: - ctx->payload_length = DES_CIPHERTEXT_LENGTH(sizeof(struct tr31_payload_t) + padded_key_length); - ctx->authenticator_length = 8; // 8 bytes; 16 ASCII hex digits + state->payload_length = DES_CIPHERTEXT_LENGTH(sizeof(struct tr31_payload_t) + padded_key_length); break; case TR31_VERSION_D: - ctx->payload_length = AES_CIPHERTEXT_LENGTH(sizeof(struct tr31_payload_t) + padded_key_length); - ctx->authenticator_length = 16; // 16 bytes; 32 ASCII hex digits + state->payload_length = AES_CIPHERTEXT_LENGTH(sizeof(struct tr31_payload_t) + padded_key_length); break; case TR31_VERSION_E: - ctx->payload_length = sizeof(struct tr31_payload_t) + padded_key_length; // no additional padding required - ctx->authenticator_length = 16; // 16 bytes; 32 ASCII hex digits + state->payload_length = sizeof(struct tr31_payload_t) + padded_key_length; // no additional padding required break; default: @@ -2833,30 +2913,55 @@ static int tr31_compute_final_lengths(struct tr31_ctx_t* ctx) return TR31_ERROR_UNSUPPORTED_VERSION; } - ctx->length = - + ctx->header_length - + (ctx->payload_length * 2) - + (ctx->authenticator_length * 2); + // populate key block length + state->header_length = header_len; + length = + + state->header_length + + (state->payload_length * 2) + + (state->authenticator_length * 2); + if (length > key_block_buf_len) { + return TR31_ERROR_INVALID_LENGTH; + } + int_to_dec(length, header->length, sizeof(header->length)); + + // prepare decoded key block buffer + state->decoded_key_block_length = state->header_length + state->payload_length + state->authenticator_length; + state->decoded_key_block = malloc(state->decoded_key_block_length); + memcpy(state->decoded_key_block, header, state->header_length); + state->payload = state->decoded_key_block + state->header_length; + state->authenticator = state->payload + state->payload_length; + + // encode wrapped key and apply key padding + payload = state->payload; + payload->length = htons(key->length * 8); // payload length is big endian and in bits, not bytes + memcpy(payload->data, key->data, key->length); + crypto_rand( + payload->data + key->length, + state->payload_length - sizeof(struct tr31_payload_t) - key->length + ); return 0; } -static int tr31_tdes_decrypt_verify_variant_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk) +static void tr31_state_release(struct tr31_state_t* state) +{ + if (state->decoded_key_block) { + // cleanse this buffer because it contains the cleartext key during + // derivation binding CMAC generation/verification + crypto_cleanse(state->decoded_key_block, state->decoded_key_block_length); + free(state->decoded_key_block); + } + memset(state, 0, sizeof(*state)); +} + +static int tr31_tdes_decrypt_verify_variant_binding(const struct tr31_state_t* state, const struct tr31_key_t* kbpk, struct tr31_key_t* key) { int r; uint8_t kbek[TDES3_KEY_SIZE]; uint8_t kbak[TDES3_KEY_SIZE]; + struct tr31_payload_t* decrypted_payload = NULL; size_t key_length; - // buffer for decryption - uint8_t decrypted_payload_buf[ctx->payload_length]; - struct tr31_payload_t* decrypted_payload = (struct tr31_payload_t*)decrypted_payload_buf; - - // buffer for MAC verification - uint8_t mac_input[ctx->header_length + ctx->payload_length]; - memcpy(mac_input, ctx->header, ctx->header_length); - memcpy(mac_input + ctx->header_length, ctx->payload, ctx->payload_length); - // output key block encryption key variant and key block authentication key variant r = tr31_tdes_kbpk_variant(kbpk->data, kbpk->length, kbek, kbak); if (r) { @@ -2865,29 +2970,50 @@ static int tr31_tdes_decrypt_verify_variant_binding(struct tr31_ctx_t* ctx, cons } // verify authenticator - r = tr31_tdes_verify_cbcmac(kbak, kbpk->length, mac_input, sizeof(mac_input), ctx->authenticator, ctx->authenticator_length); + r = tr31_tdes_verify_cbcmac( + kbak, + kbpk->length, + state->decoded_key_block, + state->header_length + state->payload_length, + state->authenticator, + state->authenticator_length + ); if (r) { r = TR31_ERROR_KEY_BLOCK_VERIFICATION_FAILED; goto error; } // decrypt key payload; note that the TR-31 header is used as the IV - r = crypto_tdes_decrypt(kbek, kbpk->length, ctx->header, ctx->payload, ctx->payload_length, decrypted_payload); + decrypted_payload = malloc(state->payload_length); + r = crypto_tdes_decrypt( + kbek, + kbpk->length, + state->decoded_key_block, + state->payload, + state->payload_length, + decrypted_payload + ); if (r) { // return error value as-is goto error; } // validate payload length field - key_length = ntohs(decrypted_payload->length) / 8; // payload length is big endian and in bits, not bytes - if (key_length > ctx->payload_length - 2) { + key_length = ntohs(decrypted_payload->length); // payload length is big endian and in bits, not bytes + if ((key_length & 0x7) != 0) { + // invalid key length is not a multiple of 8 bits + r = TR31_ERROR_INVALID_KEY_LENGTH; + goto error; + } + key_length /= 8; // convert to bytes + if (key_length > state->payload_length - 2) { // invalid key length relative to encrypted payload length r = TR31_ERROR_INVALID_KEY_LENGTH; goto error; } // extract key data - r = tr31_key_set_data(&ctx->key, decrypted_payload->data, key_length); + r = tr31_key_set_data(key, decrypted_payload->data, key_length); if (r) { // return error value as-is goto error; @@ -2902,38 +3028,21 @@ static int tr31_tdes_decrypt_verify_variant_binding(struct tr31_ctx_t* ctx, cons // cleanse sensitive buffers crypto_cleanse(kbek, sizeof(kbek)); crypto_cleanse(kbak, sizeof(kbak)); - crypto_cleanse(decrypted_payload_buf, sizeof(decrypted_payload_buf)); - crypto_cleanse(mac_input, sizeof(mac_input)); + if (decrypted_payload) { + crypto_cleanse(decrypted_payload, state->payload_length); + free(decrypted_payload); + } return r; } -static int tr31_tdes_encrypt_sign_variant_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk) +static int tr31_tdes_encrypt_sign_variant_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk) { int r; uint8_t kbek[TDES3_KEY_SIZE]; uint8_t kbak[TDES3_KEY_SIZE]; - - // add payload data to context object - ctx->payload = calloc(1, ctx->payload_length); - - // add authenticator to context object - ctx->authenticator = calloc(1, ctx->authenticator_length); - - // buffer for encrypted - uint8_t decrypted_payload_buf[ctx->payload_length]; - struct tr31_payload_t* decrypted_payload = (struct tr31_payload_t*)decrypted_payload_buf; - - // buffer for MAC generation - uint8_t mac_input[ctx->header_length + ctx->payload_length]; - - // populate payload key - decrypted_payload->length = htons(ctx->key.length * 8); // payload length is big endian and in bits, not bytes - memcpy(decrypted_payload->data, ctx->key.data, ctx->key.length); - crypto_rand( - decrypted_payload->data + ctx->key.length, - ctx->payload_length - sizeof(struct tr31_payload_t) - ctx->key.length - ); + uint8_t* encrypted_payload = NULL; + uint8_t mac[DES_CBCMAC_SIZE]; // output key block encryption key variant and key block authentication key variant r = tr31_tdes_kbpk_variant(kbpk->data, kbpk->length, kbek, kbak); @@ -2943,22 +3052,39 @@ static int tr31_tdes_encrypt_sign_variant_binding(struct tr31_ctx_t* ctx, const } // encrypt key payload; note that the TR-31 header is used as the IV - r = crypto_tdes_encrypt(kbek, kbpk->length, ctx->header, decrypted_payload, ctx->payload_length, ctx->payload); + encrypted_payload = malloc(state->payload_length); + r = crypto_tdes_encrypt( + kbek, + kbpk->length, + state->decoded_key_block, + state->payload, + state->payload_length, + encrypted_payload + ); if (r) { // return error value as-is goto error; } // generate authenticator - uint8_t mac[DES_CBCMAC_SIZE]; - memcpy(mac_input, ctx->header, ctx->header_length); - memcpy(mac_input + ctx->header_length, ctx->payload, ctx->payload_length); - r = crypto_tdes_cbcmac(kbak, kbpk->length, mac_input, sizeof(mac_input), mac); - if (r) { + memcpy(state->payload, encrypted_payload, state->payload_length); + r = crypto_tdes_cbcmac( + kbak, + kbpk->length, + state->decoded_key_block, + state->header_length + state->payload_length, + mac + ); + if (r > 0) { + // internal error + r = -10; + goto error; + } + if (r < 0) { // return error value as-is goto error; } - memcpy(ctx->authenticator, mac, ctx->authenticator_length); + memcpy(state->authenticator, mac, state->authenticator_length); // success r = 0; @@ -2969,25 +3095,23 @@ static int tr31_tdes_encrypt_sign_variant_binding(struct tr31_ctx_t* ctx, const // cleanse sensitive buffers crypto_cleanse(kbek, sizeof(kbek)); crypto_cleanse(kbak, sizeof(kbak)); - crypto_cleanse(decrypted_payload_buf, sizeof(decrypted_payload_buf)); - crypto_cleanse(mac_input, sizeof(mac_input)); + if (encrypted_payload) { + crypto_cleanse(encrypted_payload, state->payload_length); + free(encrypted_payload); + } crypto_cleanse(mac, sizeof(mac)); return r; } -static int tr31_tdes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk) +static int tr31_tdes_decrypt_verify_derivation_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk, struct tr31_key_t* key) { int r; uint8_t kbek[TDES3_KEY_SIZE]; uint8_t kbak[TDES3_KEY_SIZE]; + struct tr31_payload_t* decrypted_payload = NULL; size_t key_length; - // buffer for decryption and CMAC verification - uint8_t decrypted_key_block[ctx->header_length + ctx->payload_length]; - memcpy(decrypted_key_block, ctx->header, ctx->header_length); - struct tr31_payload_t* decrypted_payload = (struct tr31_payload_t*)(decrypted_key_block + ctx->header_length); - // derive key block encryption key and key block authentication key from key block protection key r = tr31_tdes_kbpk_derive(kbpk->data, kbpk->length, kbek, kbak); if (r) { @@ -2996,29 +3120,51 @@ static int tr31_tdes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, c } // decrypt key payload; note that the authenticator is used as the IV - r = crypto_tdes_decrypt(kbek, kbpk->length, ctx->authenticator, ctx->payload, ctx->payload_length, decrypted_payload); + decrypted_payload = malloc(state->payload_length); + r = crypto_tdes_decrypt( + kbek, + kbpk->length, + state->authenticator, + state->payload, + state->payload_length, + decrypted_payload + ); if (r) { // return error value as-is goto error; } // extract payload length field - key_length = ntohs(decrypted_payload->length) / 8; // payload length is big endian and in bits, not bytes - if (key_length > ctx->payload_length - 2) { + key_length = ntohs(decrypted_payload->length); // payload length is big endian and in bits, not bytes + if ((key_length & 0x7) != 0) { + // invalid key length is not a multiple of 8 bits + r = TR31_ERROR_INVALID_KEY_LENGTH; + goto error; + } + key_length /= 8; // convert to bytes + if (key_length > state->payload_length - 2) { // invalid key length relative to encrypted payload length r = TR31_ERROR_INVALID_KEY_LENGTH; goto error; } // verify authenticator - r = tr31_tdes_verify_cmac(kbak, kbpk->length, decrypted_key_block, sizeof(decrypted_key_block), ctx->authenticator, ctx->authenticator_length); + memcpy(state->payload, decrypted_payload, state->payload_length); + r = tr31_tdes_verify_cmac( + kbak, + kbpk->length, + state->decoded_key_block, + state->header_length + state->payload_length, + state->authenticator, + state->authenticator_length + ); if (r) { r = TR31_ERROR_KEY_BLOCK_VERIFICATION_FAILED; goto error; } // extract key data - r = tr31_key_set_data(&ctx->key, decrypted_payload->data, key_length); + r = tr31_key_set_data(key, decrypted_payload->data, key_length); if (r) { // return error value as-is goto error; @@ -3033,35 +3179,21 @@ static int tr31_tdes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, c // cleanse sensitive buffers crypto_cleanse(kbek, sizeof(kbek)); crypto_cleanse(kbak, sizeof(kbak)); - crypto_cleanse(decrypted_key_block, sizeof(decrypted_key_block)); + if (decrypted_payload) { + crypto_cleanse(decrypted_payload, state->payload_length); + free(decrypted_payload); + } return r; } -static int tr31_tdes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk) +static int tr31_tdes_encrypt_sign_derivation_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk) { int r; uint8_t kbek[TDES3_KEY_SIZE]; uint8_t kbak[TDES3_KEY_SIZE]; - - // add payload data to context object - ctx->payload = calloc(1, ctx->payload_length); - - // add authenticator to context object - ctx->authenticator = calloc(1, ctx->authenticator_length); - - // buffer for CMAC generation and encryption - uint8_t decrypted_key_block[ctx->header_length + ctx->payload_length]; - memcpy(decrypted_key_block, ctx->header, ctx->header_length); - struct tr31_payload_t* decrypted_payload = (struct tr31_payload_t*)(decrypted_key_block + ctx->header_length); - - // populate payload key - decrypted_payload->length = htons(ctx->key.length * 8); // payload length is big endian and in bits, not bytes - memcpy(decrypted_payload->data, ctx->key.data, ctx->key.length); - crypto_rand( - decrypted_payload->data + ctx->key.length, - ctx->payload_length - sizeof(struct tr31_payload_t) - ctx->key.length - ); + uint8_t cmac[DES_CMAC_SIZE]; + uint8_t* encrypted_payload = NULL; // derive key block encryption key and key block authentication key from key block protection key r = tr31_tdes_kbpk_derive(kbpk->data, kbpk->length, kbek, kbak); @@ -3071,20 +3203,39 @@ static int tr31_tdes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, con } // generate authenticator - uint8_t cmac[DES_CMAC_SIZE]; - r = crypto_tdes_cmac(kbak, kbpk->length, decrypted_key_block, sizeof(decrypted_key_block), cmac); - if (r) { + r = crypto_tdes_cmac( + kbak, + kbpk->length, + state->decoded_key_block, + state->header_length + state->payload_length, + cmac + ); + if (r > 0) { + // internal error + r = -10; + goto error; + } + if (r < 0) { // return error value as-is goto error; } - memcpy(ctx->authenticator, cmac, ctx->authenticator_length); + memcpy(state->authenticator, cmac, state->authenticator_length); // encrypt key payload; note that the authenticator is used as the IV - r = crypto_tdes_encrypt(kbek, kbpk->length, ctx->authenticator, decrypted_payload, ctx->payload_length, ctx->payload); + encrypted_payload = malloc(state->payload_length); + r = crypto_tdes_encrypt( + kbek, + kbpk->length, + state->authenticator, + state->payload, + state->payload_length, + encrypted_payload + ); if (r) { // return error value as-is goto error; } + memcpy(state->payload, encrypted_payload, state->payload_length); // success r = 0; @@ -3095,25 +3246,26 @@ static int tr31_tdes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, con // cleanse sensitive buffers crypto_cleanse(kbek, sizeof(kbek)); crypto_cleanse(kbak, sizeof(kbak)); - crypto_cleanse(decrypted_key_block, sizeof(decrypted_key_block)); + if (encrypted_payload) { + crypto_cleanse(encrypted_payload, state->payload_length); + free(encrypted_payload); + } crypto_cleanse(cmac, sizeof(cmac)); return r; } -static int tr31_aes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk) +static int tr31_aes_decrypt_verify_derivation_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk, struct tr31_key_t* key) { int r; uint8_t kbek[AES256_KEY_SIZE]; uint8_t kbak[AES256_KEY_SIZE]; + const struct tr31_header_t* header; + struct tr31_payload_t* decrypted_payload = NULL; size_t key_length; - // buffer for decryption and CMAC verification - uint8_t decrypted_key_block[ctx->header_length + ctx->payload_length]; - memcpy(decrypted_key_block, ctx->header, ctx->header_length); - struct tr31_payload_t* decrypted_payload = (struct tr31_payload_t*)(decrypted_key_block + ctx->header_length); - - if (ctx->version == TR31_VERSION_D) { + header = state->decoded_key_block; + if (header->version_id == TR31_VERSION_D) { // derive key block encryption key and key block authentication key from key block protection key // format version D uses CBC block mode r = tr31_aes_kbpk_derive(kbpk->data, kbpk->length, TR31_AES_MODE_CBC, kbek, kbak); @@ -3123,13 +3275,21 @@ static int tr31_aes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, co } // decrypt key payload; note that the authenticator is used as the IV - r = crypto_aes_decrypt(kbek, kbpk->length, ctx->authenticator, ctx->payload, ctx->payload_length, decrypted_payload); + decrypted_payload = malloc(state->payload_length); + r = crypto_aes_decrypt( + kbek, + kbpk->length, + state->authenticator, + state->payload, + state->payload_length, + decrypted_payload + ); if (r) { // return error value as-is goto error; } - } else if (ctx->version == TR31_VERSION_E) { + } else if (header->version_id == TR31_VERSION_E) { // derive key block encryption key and key block authentication key from key block protection key // format version E uses CTR block mode r = tr31_aes_kbpk_derive(kbpk->data, kbpk->length, TR31_AES_MODE_CTR, kbek, kbak); @@ -3139,7 +3299,15 @@ static int tr31_aes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, co } // decrypt key payload; note that the authenticator is used as the IV/nonce - r = crypto_aes_decrypt_ctr(kbek, kbpk->length, ctx->authenticator, ctx->payload, ctx->payload_length, decrypted_payload); + decrypted_payload = malloc(state->payload_length); + r = crypto_aes_decrypt_ctr( + kbek, + kbpk->length, + state->authenticator, + state->payload, + state->payload_length, + decrypted_payload + ); if (r) { // return error value as-is goto error; @@ -3151,22 +3319,36 @@ static int tr31_aes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, co } // extract payload length field - key_length = ntohs(decrypted_payload->length) / 8; // payload length is big endian and in bits, not bytes - if (key_length > ctx->payload_length - 2) { + key_length = ntohs(decrypted_payload->length); // payload length is big endian and in bits, not bytes + if ((key_length & 0x7) != 0) { + // invalid key length is not a multiple of 8 bits + r = TR31_ERROR_INVALID_KEY_LENGTH; + goto error; + } + key_length /= 8; // convert to bytes + if (key_length > state->payload_length - 2) { // invalid key length relative to encrypted payload length r = TR31_ERROR_INVALID_KEY_LENGTH; goto error; } // verify authenticator - r = tr31_aes_verify_cmac(kbak, kbpk->length, decrypted_key_block, sizeof(decrypted_key_block), ctx->authenticator, ctx->authenticator_length); + memcpy(state->payload, decrypted_payload, state->payload_length); + r = tr31_aes_verify_cmac( + kbak, + kbpk->length, + state->decoded_key_block, + state->header_length + state->payload_length, + state->authenticator, + state->authenticator_length + ); if (r) { r = TR31_ERROR_KEY_BLOCK_VERIFICATION_FAILED; goto error; } // extract key data - r = tr31_key_set_data(&ctx->key, decrypted_payload->data, key_length); + r = tr31_key_set_data(key, decrypted_payload->data, key_length); if (r) { // return error value as-is goto error; @@ -3181,38 +3363,25 @@ static int tr31_aes_decrypt_verify_derivation_binding(struct tr31_ctx_t* ctx, co // cleanse sensitive buffers crypto_cleanse(kbek, sizeof(kbek)); crypto_cleanse(kbak, sizeof(kbak)); - crypto_cleanse(decrypted_key_block, sizeof(decrypted_key_block)); + if (decrypted_payload) { + crypto_cleanse(decrypted_payload, state->payload_length); + free(decrypted_payload); + } return r; } -static int tr31_aes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk) +static int tr31_aes_encrypt_sign_derivation_binding(struct tr31_state_t* state, const struct tr31_key_t* kbpk) { int r; uint8_t kbek[AES256_KEY_SIZE]; uint8_t kbak[AES256_KEY_SIZE]; + const struct tr31_header_t* header; uint8_t cmac[AES_CMAC_SIZE]; + uint8_t* encrypted_payload = NULL; - // add payload data to context object - ctx->payload = calloc(1, ctx->payload_length); - - // add authenticator to context object - ctx->authenticator = calloc(1, ctx->authenticator_length); - - // buffer for CMAC generation and encryption - uint8_t decrypted_key_block[ctx->header_length + ctx->payload_length]; - memcpy(decrypted_key_block, ctx->header, ctx->header_length); - struct tr31_payload_t* decrypted_payload = (struct tr31_payload_t*)(decrypted_key_block + ctx->header_length); - - // populate payload key - decrypted_payload->length = htons(ctx->key.length * 8); // payload length is big endian and in bits, not bytes - memcpy(decrypted_payload->data, ctx->key.data, ctx->key.length); - crypto_rand( - decrypted_payload->data + ctx->key.length, - ctx->payload_length - sizeof(struct tr31_payload_t) - ctx->key.length - ); - - if (ctx->version == TR31_VERSION_D) { + header = state->decoded_key_block; + if (header->version_id == TR31_VERSION_D) { // derive key block encryption key and key block authentication key from key block protection key // format version D uses CBC block mode r = tr31_aes_kbpk_derive(kbpk->data, kbpk->length, TR31_AES_MODE_CBC, kbek, kbak); @@ -3222,21 +3391,36 @@ static int tr31_aes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, cons } // generate authenticator - r = crypto_aes_cmac(kbak, kbpk->length, decrypted_key_block, sizeof(decrypted_key_block), cmac); + r = crypto_aes_cmac( + kbak, + kbpk->length, + state->decoded_key_block, + state->header_length + state->payload_length, + cmac + ); if (r) { // return error value as-is goto error; } - memcpy(ctx->authenticator, cmac, ctx->authenticator_length); + memcpy(state->authenticator, cmac, state->authenticator_length); // encrypt key payload; note that the authenticator is used as the IV - r = crypto_aes_encrypt(kbek, kbpk->length, ctx->authenticator, decrypted_payload, ctx->payload_length, ctx->payload); + encrypted_payload = malloc(state->payload_length); + r = crypto_aes_encrypt( + kbek, + kbpk->length, + state->authenticator, + state->payload, + state->payload_length, + encrypted_payload + ); if (r) { // return error value as-is goto error; } + memcpy(state->payload, encrypted_payload, state->payload_length); - } else if (ctx->version == TR31_VERSION_E) { + } else if (header->version_id == TR31_VERSION_E) { // derive key block encryption key and key block authentication key from key block protection key // format version E uses CTR block mode r = tr31_aes_kbpk_derive(kbpk->data, kbpk->length, TR31_AES_MODE_CTR, kbek, kbak); @@ -3246,19 +3430,34 @@ static int tr31_aes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, cons } // generate authenticator - r = crypto_aes_cmac(kbak, kbpk->length, decrypted_key_block, sizeof(decrypted_key_block), cmac); + r = crypto_aes_cmac( + kbak, + kbpk->length, + state->decoded_key_block, + state->header_length + state->payload_length, + cmac + ); if (r) { // return error value as-is goto error; } - memcpy(ctx->authenticator, cmac, ctx->authenticator_length); + memcpy(state->authenticator, cmac, state->authenticator_length); // encrypt key payload; note that the authenticator is used as the IV/nonce - r = crypto_aes_encrypt_ctr(kbek, kbpk->length, ctx->authenticator, decrypted_payload, ctx->payload_length, ctx->payload); + encrypted_payload = malloc(state->payload_length); + r = crypto_aes_encrypt_ctr( + kbek, + kbpk->length, + state->authenticator, + state->payload, + state->payload_length, + encrypted_payload + ); if (r) { // return error value as-is goto error; } + memcpy(state->payload, encrypted_payload, state->payload_length); } else { // invalid format version @@ -3274,7 +3473,10 @@ static int tr31_aes_encrypt_sign_derivation_binding(struct tr31_ctx_t* ctx, cons // cleanse sensitive buffers crypto_cleanse(kbek, sizeof(kbek)); crypto_cleanse(kbak, sizeof(kbak)); - crypto_cleanse(decrypted_key_block, sizeof(decrypted_key_block)); + if (encrypted_payload) { + crypto_cleanse(encrypted_payload, state->payload_length); + free(encrypted_payload); + } crypto_cleanse(cmac, sizeof(cmac)); return r; @@ -3299,15 +3501,6 @@ void tr31_release(struct tr31_ctx_t* ctx) free(ctx->opt_blocks); ctx->opt_blocks = NULL; } - - if (ctx->payload) { - free(ctx->payload); - ctx->payload = NULL; - } - if (ctx->authenticator) { - free(ctx->authenticator); - ctx->authenticator = NULL; - } } const char* tr31_get_error_string(enum tr31_error_t error) @@ -3318,6 +3511,7 @@ const char* tr31_get_error_string(enum tr31_error_t error) switch (error) { case TR31_ERROR_INVALID_LENGTH: return "Invalid key block length"; + case TR31_ERROR_INVALID_KEY_BLOCK_STRING: return "Invalid key block string"; case TR31_ERROR_UNSUPPORTED_VERSION: return "Unsupported key block format version"; case TR31_ERROR_INVALID_LENGTH_FIELD: return "Invalid key block length field"; case TR31_ERROR_UNSUPPORTED_KEY_USAGE: return "Unsupported key usage"; @@ -3329,6 +3523,7 @@ const char* tr31_get_error_string(enum tr31_error_t error) case TR31_ERROR_DUPLICATE_OPTIONAL_BLOCK_ID: return "Duplicate optional block identifier"; case TR31_ERROR_INVALID_OPTIONAL_BLOCK_LENGTH: return "Invalid optional block length"; case TR31_ERROR_INVALID_OPTIONAL_BLOCK_DATA: return "Invalid optional block data"; + case TR31_ERROR_INVALID_OPTIONAL_BLOCK_PADDING: return "Invalid optional block padding"; case TR31_ERROR_INVALID_PAYLOAD_FIELD: return "Invalid payload data field"; case TR31_ERROR_INVALID_AUTHENTICATOR_FIELD: return "Invalid authenticator data field"; case TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM: return "Unsupported key block protection key algorithm"; diff --git a/src/tr31.h b/src/tr31.h index 79e03ba..f6803b8 100644 --- a/src/tr31.h +++ b/src/tr31.h @@ -267,28 +267,20 @@ struct tr31_opt_blk_wp_data_t { */ struct tr31_ctx_t { enum tr31_version_t version; ///< TR-31 key block format version - size_t length; ///< TR-31 key block length in bytes + size_t length; ///< TR-31 key block length in bytes (only populated by @ref tr31_import(), not @ref tr31_export()) struct tr31_key_t key; ///< TR-31 key object size_t opt_blocks_count; ///< TR-31 number of optional blocks struct tr31_opt_ctx_t* opt_blocks; ///< TR-31 optional block context objects - size_t header_length; ///< TR-31 header data length in bytes, including optional blocks - const void* header; ///< Pointer to TR-31 header data for internal use only. @warning For internal use only! - - size_t payload_length; ///< TR-31 payload data length in bytes - void* payload; ///< Decoded TR-31 payload data for internal use only. @warning For internal use only! - - size_t authenticator_length; ///< TR-31 authenticator data length in bytes - void* authenticator; ///< Decoded TR-31 authenticator data for internal use only. @warning For internal use only! - uint32_t export_flags; ///< Flags used during TR-31 export }; /// TR-31 library errors enum tr31_error_t { TR31_ERROR_INVALID_LENGTH = 1, ///< Invalid key block length + TR31_ERROR_INVALID_KEY_BLOCK_STRING, ///< Invalid key block string TR31_ERROR_UNSUPPORTED_VERSION, ///< Unsupported key block format version TR31_ERROR_INVALID_LENGTH_FIELD, ///< Invalid key block length field TR31_ERROR_UNSUPPORTED_KEY_USAGE, ///< Unsupported key usage @@ -300,6 +292,7 @@ enum tr31_error_t { TR31_ERROR_DUPLICATE_OPTIONAL_BLOCK_ID, ///< Duplicate optional block identifier TR31_ERROR_INVALID_OPTIONAL_BLOCK_LENGTH, ///< Invalid optional block length TR31_ERROR_INVALID_OPTIONAL_BLOCK_DATA, ///< Invalid optional block data + TR31_ERROR_INVALID_OPTIONAL_BLOCK_PADDING, ///< Invalid optional block padding TR31_ERROR_INVALID_PAYLOAD_FIELD, ///< Invalid payload data field TR31_ERROR_INVALID_AUTHENTICATOR_FIELD, ///< Invalid authenticator data field TR31_ERROR_UNSUPPORTED_KBPK_ALGORITHM, ///< Unsupported key block protection key algorithm @@ -873,13 +866,15 @@ int tr31_opt_block_decode_WP( * @note This function will populate a new TR-31 context object. * Use @ref tr31_release() to release internal resources when done. * - * @param key_block TR-31 key block. Null terminated. At least the header must be ASCII encoded. + * @param key_block TR-31 key block. Must contain printable ASCII characters. Null-termination not required. + * @param key_block_len Length of TR-31 key block in bytes, excluding null-termination. * @param kbpk TR-31 key block protection key. NULL if not available or decryption is not required. * @param ctx TR-31 context object output * @return Zero for success. Less than zero for internal error. Greater than zero for data error. See @ref tr31_error_t */ int tr31_import( const char* key_block, + size_t key_block_len, const struct tr31_key_t* kbpk, struct tr31_ctx_t* ctx ); @@ -891,15 +886,15 @@ int tr31_import( * * @param ctx TR-31 context object input * @param kbpk TR-31 key block protection key. - * @param key_block TR-31 key block output. Null terminated. At least the header will be ASCII encoded. - * @param key_block_len TR-31 key block output buffer length. + * @param key_block TR-31 key block output. Will contain printable ASCII characters and will be null-terminated. + * @param key_block_buf_len TR-31 key block output buffer length. * @return Zero for success. Less than zero for internal error. Greater than zero for data error. See @ref tr31_error_t */ int tr31_export( - struct tr31_ctx_t* ctx, + const struct tr31_ctx_t* ctx, const struct tr31_key_t* kbpk, char* key_block, - size_t key_block_len + size_t key_block_buf_len ); /** diff --git a/test/tr31_decode_test.c b/test/tr31_decode_test.c index 7290c82..4d93976 100644 --- a/test/tr31_decode_test.c +++ b/test/tr31_decode_test.c @@ -46,9 +46,9 @@ int main(void) // test key block decoding for format version B with optional block KS printf("Test 1 (Format version B with optional block KS)...\n"); - r = tr31_import(test1_tr31_ascii, NULL, &test_tr31); + r = tr31_import(test1_tr31_ascii, strlen(test1_tr31_ascii), NULL, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_B || @@ -62,11 +62,7 @@ int main(void) test_tr31.opt_blocks_count != 1 || test_tr31.opt_blocks == NULL || test_tr31.opt_blocks[0].id != TR31_OPT_BLOCK_KS || - test_tr31.opt_blocks[0].data == NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 8 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks[0].data == NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -98,9 +94,9 @@ int main(void) // test key block decoding for format version D containing TDES key printf("Test 2 (Format version D containing TDES key)...\n"); - r = tr31_import(test2_tr31_ascii, NULL, &test_tr31); + r = tr31_import(test2_tr31_ascii, strlen(test2_tr31_ascii), NULL, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -112,11 +108,7 @@ int main(void) test_tr31.key.key_version_str[0] != 0 || test_tr31.key.exportability != TR31_KEY_EXPORT_NONE || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 32 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -126,9 +118,9 @@ int main(void) // test key block decoding for format version D containing AES key printf("Test 3 (Format version D containing AES key)...\n"); - r = tr31_import(test3_tr31_ascii, NULL, &test_tr31); + r = tr31_import(test3_tr31_ascii, strlen(test3_tr31_ascii), NULL, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -140,11 +132,7 @@ int main(void) test_tr31.key.key_version_str[0] != 0 || test_tr31.key.exportability != TR31_KEY_EXPORT_NONE || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 48 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -154,9 +142,9 @@ int main(void) // test key block decoding for format version B with optional blocks KS, KC, and KP printf("Test 4 (Format version B with optional block KS, KC, KP)...\n"); - r = tr31_import(test4_tr31_ascii, NULL, &test_tr31); + r = tr31_import(test4_tr31_ascii, strlen(test4_tr31_ascii), NULL, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_B || @@ -174,11 +162,7 @@ int main(void) test_tr31.opt_blocks[1].id != TR31_OPT_BLOCK_KC || test_tr31.opt_blocks[1].data == NULL || test_tr31.opt_blocks[2].id != TR31_OPT_BLOCK_KP || - test_tr31.opt_blocks[2].data == NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 8 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks[2].data == NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; diff --git a/test/tr31_decrypt_test.c b/test/tr31_decrypt_test.c index ff745b9..fe311b6 100644 --- a/test/tr31_decrypt_test.c +++ b/test/tr31_decrypt_test.c @@ -225,9 +225,9 @@ int main(void) // test key block decryption for format version A printf("Test 1 (Basic format version A)...\n"); - r = tr31_import(test1_tr31_format_a, &test_kbpk, &test_tr31); + r = tr31_import(test1_tr31_format_a, strlen(test1_tr31_format_a), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_A || @@ -241,11 +241,7 @@ int main(void) test_tr31.key.length != sizeof(test1_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 4 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -265,9 +261,9 @@ int main(void) // test key block decryption for format version B printf("Test 1 (Basic format version B)...\n"); - r = tr31_import(test1_tr31_format_b, &test_kbpk, &test_tr31); + r = tr31_import(test1_tr31_format_b, strlen(test1_tr31_format_b), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_B || @@ -281,11 +277,7 @@ int main(void) test_tr31.key.length != sizeof(test1_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 8 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -305,9 +297,9 @@ int main(void) // test key block decryption for format version C printf("Test 1 (Basic format version C)...\n"); - r = tr31_import(test1_tr31_format_c, &test_kbpk, &test_tr31); + r = tr31_import(test1_tr31_format_c, strlen(test1_tr31_format_c), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_C || @@ -321,11 +313,7 @@ int main(void) test_tr31.key.length != sizeof(test1_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 4 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -351,9 +339,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test2_kbpk); test_kbpk.data = (void*)test2_kbpk; - r = tr31_import(test2_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test2_tr31_ascii, strlen(test2_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_A || @@ -367,11 +355,7 @@ int main(void) test_tr31.key.length != sizeof(test2_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 4 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -397,9 +381,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test3_kbpk); test_kbpk.data = (void*)test3_kbpk; - r = tr31_import(test3_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test3_tr31_ascii, strlen(test3_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_B || @@ -413,11 +397,7 @@ int main(void) test_tr31.key.length != sizeof(test3_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 8 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -443,9 +423,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test4_kbpk); test_kbpk.data = (void*)test4_kbpk; - r = tr31_import(test4_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test4_tr31_ascii, strlen(test4_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_C || @@ -461,11 +441,7 @@ int main(void) test_tr31.opt_blocks_count != 1 || test_tr31.opt_blocks == NULL || test_tr31.opt_blocks[0].id != TR31_OPT_BLOCK_KS || - test_tr31.opt_blocks[0].data == NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 4 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks[0].data == NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -513,9 +489,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test5_kbpk); test_kbpk.data = (void*)test5_kbpk; - r = tr31_import(test5_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test5_tr31_ascii, strlen(test5_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_B || @@ -531,11 +507,7 @@ int main(void) test_tr31.opt_blocks_count != 1 || test_tr31.opt_blocks == NULL || test_tr31.opt_blocks[0].id != TR31_OPT_BLOCK_KS || - test_tr31.opt_blocks[0].data == NULL || - test_tr31.payload_length != 24 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 8 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks[0].data == NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -583,9 +555,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test6_kbpk); test_kbpk.data = (void*)test6_kbpk; - r = tr31_import(test6_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test6_tr31_ascii, strlen(test6_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -599,11 +571,7 @@ int main(void) test_tr31.key.length != sizeof(test6_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 32 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -629,9 +597,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test7_kbpk); test_kbpk.data = (void*)test7_kbpk; - r = tr31_import(test7_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test7_tr31_ascii, strlen(test7_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -645,11 +613,7 @@ int main(void) test_tr31.key.length != sizeof(test7_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 32 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -675,9 +639,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test8_kbpk); test_kbpk.data = (void*)test8_kbpk; - r = tr31_import(test8_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test8_tr31_ascii, strlen(test8_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -691,11 +655,7 @@ int main(void) test_tr31.key.length != sizeof(test8_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 48 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -721,9 +681,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test9_kbpk); test_kbpk.data = (void*)test9_kbpk; - r = tr31_import(test9_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test9_tr31_ascii, strlen(test9_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_E || @@ -737,11 +697,7 @@ int main(void) test_tr31.key.length != sizeof(test9_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 18 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -767,9 +723,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test10_kbpk); test_kbpk.data = (void*)test10_kbpk; - r = tr31_import(test10_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test10_tr31_ascii, strlen(test10_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -783,11 +739,7 @@ int main(void) test_tr31.key.length != sizeof(test10_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 32 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -813,9 +765,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test11_kbpk); test_kbpk.data = (void*)test11_kbpk; - r = tr31_import(test11_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test11_tr31_ascii, strlen(test11_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -829,11 +781,7 @@ int main(void) test_tr31.key.length != sizeof(test11_tr31_key_verify) || test_tr31.key.data == NULL || test_tr31.opt_blocks_count != 0 || - test_tr31.opt_blocks != NULL || - test_tr31.payload_length != 48 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks != NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -859,9 +807,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test15_kbpk); test_kbpk.data = (void*)test15_kbpk; - r = tr31_import(test15_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test15_tr31_ascii, strlen(test15_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_C || @@ -877,11 +825,7 @@ int main(void) test_tr31.opt_blocks_count != 1 || test_tr31.opt_blocks == NULL || test_tr31.opt_blocks[0].id != TR31_OPT_BLOCK_KS || - test_tr31.opt_blocks[0].data == NULL || - test_tr31.payload_length != 32 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 4 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks[0].data == NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -929,9 +873,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test16_kbpk); test_kbpk.data = (void*)test16_kbpk; - r = tr31_import(test16_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test16_tr31_ascii, strlen(test16_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_B || @@ -947,11 +891,7 @@ int main(void) test_tr31.opt_blocks_count != 1 || test_tr31.opt_blocks == NULL || test_tr31.opt_blocks[0].id != TR31_OPT_BLOCK_KS || - test_tr31.opt_blocks[0].data == NULL || - test_tr31.payload_length != 32 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 8 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks[0].data == NULL ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -999,9 +939,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test17_kbpk); test_kbpk.data = (void*)test17_kbpk; - r = tr31_import(test17_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test17_tr31_ascii, strlen(test17_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -1022,11 +962,7 @@ int main(void) test_tr31.opt_blocks[2].id != TR31_OPT_BLOCK_TS || test_tr31.opt_blocks[2].data == NULL || memcmp(test_tr31.opt_blocks[2].data, test17_tr31_ts_verify, strlen(test17_tr31_ts_verify)) != 0 || - test_tr31.opt_blocks[3].id != TR31_OPT_BLOCK_PB || - test_tr31.payload_length != 1200 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks[3].id != TR31_OPT_BLOCK_PB ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; @@ -1082,9 +1018,9 @@ int main(void) test_kbpk.mode_of_use = TR31_KEY_MODE_OF_USE_ENC_DEC; test_kbpk.length = sizeof(test18_kbpk); test_kbpk.data = (void*)test18_kbpk; - r = tr31_import(test18_tr31_ascii, &test_kbpk, &test_tr31); + r = tr31_import(test18_tr31_ascii, strlen(test18_tr31_ascii), &test_kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.version != TR31_VERSION_D || @@ -1105,11 +1041,7 @@ int main(void) test_tr31.opt_blocks[2].id != TR31_OPT_BLOCK_TS || test_tr31.opt_blocks[2].data == NULL || memcmp(test_tr31.opt_blocks[2].data, test18_tr31_ts_verify, strlen(test18_tr31_ts_verify)) != 0 || - test_tr31.opt_blocks[3].id != TR31_OPT_BLOCK_PB || - test_tr31.payload_length != 128 || - test_tr31.payload == NULL || - test_tr31.authenticator_length != 16 || - test_tr31.authenticator == NULL + test_tr31.opt_blocks[3].id != TR31_OPT_BLOCK_PB ) { fprintf(stderr, "TR-31 context is incorrect\n"); r = 1; diff --git a/test/tr31_export_test.c b/test/tr31_export_test.c index b5e855a..8a6b808 100644 --- a/test/tr31_export_test.c +++ b/test/tr31_export_test.c @@ -803,7 +803,7 @@ int main(void) print_buf("kbpk", test[i].kbpk_data, test[i].kbpk_len); r = tr31_key_set_data(&test[i].kbpk, test[i].kbpk_data, test[i].kbpk_len); if (r) { - fprintf(stderr, "tr31_key_set_data() failed; r=%d\n", r); + fprintf(stderr, "tr31_key_set_data() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } @@ -811,14 +811,14 @@ int main(void) print_buf("key", test[i].key_data, test[i].key_len); r = tr31_key_set_data(&test[i].key, test[i].key_data, test[i].key_len); if (r) { - fprintf(stderr, "tr31_key_set_data() failed; r=%d\n", r); + fprintf(stderr, "tr31_key_set_data() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } // Prepare TR-31 context r = tr31_init(test[i].tr31_version, &test[i].key, &test_tr31); if (r) { - fprintf(stderr, "tr31_init() failed; r=%d\n", r); + fprintf(stderr, "tr31_init() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } test_tr31.export_flags = test[i].export_flags; @@ -831,29 +831,29 @@ int main(void) strlen(test[i].cert_base64[cert_idx]) ); if (r) { - fprintf(stderr, "tr31_opt_block_add_CT() failed; r=%d\n", r); - return 1; + fprintf(stderr, "tr31_opt_block_add_CT() error %d: %s\n", r, tr31_get_error_string(r)); + goto exit; } } } if (test[i].opt_blk_HM) { r = tr31_opt_block_add_HM(&test_tr31, test[i].opt_blk_HM); if (r) { - fprintf(stderr, "tr31_opt_block_add_HM() failed; r=%d\n", r); - return 1; + fprintf(stderr, "tr31_opt_block_add_HM() error %d: %s\n", r, tr31_get_error_string(r)); + goto exit; } } if (test[i].opt_blk_KC) { r = tr31_opt_block_add_KC(&test_tr31); if (r) { - fprintf(stderr, "tr31_opt_block_add_KC() failed; r=%d\n", r); + fprintf(stderr, "tr31_opt_block_add_KC() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } } if (test[i].opt_blk_KP) { r = tr31_opt_block_add_KP(&test_tr31); if (r) { - fprintf(stderr, "tr31_opt_block_add_KP() failed; r=%d\n", r); + fprintf(stderr, "tr31_opt_block_add_KP() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } } @@ -864,14 +864,14 @@ int main(void) test[i].ksn_len ); if (r) { - fprintf(stderr, "tr31_opt_block_add_KS() failed; r=%d\n", r); + fprintf(stderr, "tr31_opt_block_add_KS() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } } if (test[i].timestamp) { r = tr31_opt_block_add_TS(&test_tr31, test[i].timestamp); if (r) { - fprintf(stderr, "tr31_opt_block_add_TS() failed; r=%d\n", r); + fprintf(stderr, "tr31_opt_block_add_TS() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } } @@ -879,7 +879,7 @@ int main(void) // Export key block r = tr31_export(&test_tr31, &test[i].kbpk, key_block, sizeof(key_block)); if (r) { - fprintf(stderr, "tr31_export() failed; r=%d\n", r); + fprintf(stderr, "tr31_export() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } printf("TR-31: %s\n", key_block); @@ -907,9 +907,9 @@ int main(void) tr31_release(&test_tr31); // Import and decrypt key block - r = tr31_import(key_block, &test[i].kbpk, &test_tr31); + r = tr31_import(key_block, strlen(key_block), &test[i].kbpk, &test_tr31); if (r) { - fprintf(stderr, "tr31_import() failed; r=%d\n", r); + fprintf(stderr, "tr31_import() error %d: %s\n", r, tr31_get_error_string(r)); goto exit; } if (test_tr31.key.length != test[i].key_len ||