Skip to content

Commit

Permalink
Fix output null-termination for tr31_export()
Browse files Browse the repository at this point in the history
Unfortunately tr31_export() had a silly bug whereby the last byte of the
provided key block output buffer would not be zero'd. Therefore, if the
provided buffer was exactly one byte longer than the created key block,
the resulting key block string would not be null-terminated.

Note that although tr31_import() has been refactored not to require
null-terminated key block input to make it more convenient for the
caller, it continues to be convenient for the caller that tr31_export()
null-terminates the key block output. This is such that the caller can
equally easily print the key block output or obtain its length using
strlen().

The key block buffer output length parameter has also been renamed to
key_block_buf_len to distinguish it from from the exact key block input
length expected in key_block_len.
  • Loading branch information
leonlynch committed Oct 14, 2023
1 parent 3e665ec commit 6d86e77
Show file tree
Hide file tree
Showing 2 changed files with 16 additions and 16 deletions.
26 changes: 13 additions & 13 deletions src/tr31.c
Original file line number Diff line number Diff line change
Expand Up @@ -1520,7 +1520,7 @@ int tr31_export(
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;
Expand All @@ -1529,21 +1529,21 @@ int tr31_export(
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);

// ensure null-termination
memset(key_block, 0, key_block_buf_len);
--key_block_buf_len;

// validate key block format version
// set encryption block size for header padding
Expand Down Expand Up @@ -1641,7 +1641,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
);
Expand Down Expand Up @@ -1673,7 +1673,7 @@ int tr31_export(
pb_len = ((opt_blk_len_total + 4 + enc_block_size) & ~(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;
}
Expand Down Expand Up @@ -1709,7 +1709,7 @@ int tr31_export(
// return error value as-is
return r;
}
if (ctx->length > key_block_len) {
if (ctx->length > key_block_buf_len) {
return TR31_ERROR_INVALID_LENGTH;
}

Expand Down Expand Up @@ -1808,15 +1808,15 @@ int tr31_export(
}

// add payload to key block
r = bin_to_hex(ctx->payload, ctx->payload_length, ptr, key_block_len);
r = bin_to_hex(ctx->payload, ctx->payload_length, ptr, key_block_buf_len);
if (r) {
// internal error
return -5;
}
ptr += (ctx->payload_length * 2);

// add authenticator to key block
r = bin_to_hex(ctx->authenticator, ctx->authenticator_length, ptr, key_block_len);
r = bin_to_hex(ctx->authenticator, ctx->authenticator_length, ptr, key_block_buf_len);
if (r) {
// internal error
return -6;
Expand Down
6 changes: 3 additions & 3 deletions src/tr31.h
Original file line number Diff line number Diff line change
Expand Up @@ -647,15 +647,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_key_t* kbpk,
char* key_block,
size_t key_block_len
size_t key_block_buf_len
);

/**
Expand Down

0 comments on commit 6d86e77

Please sign in to comment.