Skip to content

Commit

Permalink
Make CMAC API more resistant to misuse
Browse files Browse the repository at this point in the history
Set 'finalised' flag only when finalisation happens,
not when we get a final 'empty' block.

Assert that if we have a non-empty message, we get
the final flag along with some data.
  • Loading branch information
ctz committed Apr 16, 2016
1 parent 851e813 commit b03c1ab
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 4 deletions.
12 changes: 8 additions & 4 deletions src/cmac.c
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ static void cmac_process_final_nopad(void *vctx, const uint8_t *block)
{
cf_cmac_stream *ctx = vctx;
cmac_process_final(ctx, block, ctx->cmac.B);
ctx->finalised = 1;
}

static void cmac_process_final_pad(void *vctx, const uint8_t *block)
{
cf_cmac_stream *ctx = vctx;
cmac_process_final(ctx, block, ctx->cmac.P);
ctx->finalised = 1;
}

void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len, int isfinal)
Expand All @@ -111,13 +113,15 @@ void cf_cmac_stream_update(cf_cmac_stream *ctx, const uint8_t *data, size_t len,

if (isfinal)
{
assert(!ctx->finalised);
ctx->finalised = 1;
int whole_number_of_blocks = ((len + ctx->used) & 0xf) == 0;
int empty_message = len == 0 && ctx->used == 0 && ctx->processed == 0;

assert(!ctx->finalised); /* finalised before? */
assert(len != 0 || empty_message); /* we can't be told we're done after the fact. */

/* If we have a whole number of blocks, and at least 1 block, we XOR in B.
* Otherwise, we need to pad and XOR in P. */
if (((len + ctx->used) & 0xf) == 0 &&
!(len == 0 && ctx->used == 0 && ctx->processed == 0))
if (whole_number_of_blocks && !empty_message)
final_fn = cmac_process_final_nopad;
else
needpad = 1;
Expand Down
5 changes: 5 additions & 0 deletions src/modes.h
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ void cf_cmac_sign(cf_cmac *ctx, const uint8_t *data, size_t bytes,
/* .. c:type:: cf_cmac_stream
* Stream interface to CMAC signing.
*
* Input data in arbitrary chunks using :c:func:`cf_cmac_stream_update`.
* The last bit of data must be signalled with the `isfinal` flag to
* that function, and the data cannot be zero length unless the whole
* message is empty.
*
* .. c:member:: cf_cmac_stream.cmac
* CMAC one-shot data.
*
Expand Down

0 comments on commit b03c1ab

Please # to comment.