diff options
author | Andy Polyakov <appro@openssl.org> | 2015-11-30 13:26:21 +0100 |
---|---|---|
committer | Andy Polyakov <appro@openssl.org> | 2015-12-02 10:48:38 +0100 |
commit | b9e3d7e0f6678a991621cfbc4b11ace7860031a0 (patch) | |
tree | b9a10761a46f7faeef8797c5e04fda8f2048380f /crypto | |
parent | 338f5727c88b1ce44a802c5115707309d6316fc4 (diff) | |
download | openssl-b9e3d7e0f6678a991621cfbc4b11ace7860031a0.tar.gz |
modes/ocb128.c: ocb_lookup_l to allow non-contiguous lookup
and CRYPTO_ocb128_encrypt to handle in==out.
Reviewed-by: Matt Caswell <matt@openssl.org>
Diffstat (limited to 'crypto')
-rw-r--r-- | crypto/modes/ocb128.c | 37 |
1 files changed, 29 insertions, 8 deletions
diff --git a/crypto/modes/ocb128.c b/crypto/modes/ocb128.c index 2685652d3f..5408d50df1 100644 --- a/crypto/modes/ocb128.c +++ b/crypto/modes/ocb128.c @@ -153,20 +153,34 @@ static void ocb_block_xor(const unsigned char *in1, */ static OCB_BLOCK *ocb_lookup_l(OCB128_CONTEXT *ctx, size_t idx) { - if (idx <= ctx->l_index) { + size_t l_index = ctx->l_index; + + if (idx <= l_index) { return ctx->l + idx; } /* We don't have it - so calculate it */ - ctx->l_index++; - if (ctx->l_index == ctx->max_l_index) { - ctx->max_l_index *= 2; + if (idx >= ctx->max_l_index) { + /* + * Each additional entry allows to process almost double as + * much data, so that in linear world the table will need to + * be expanded with smaller and smaller increments. Originally + * it was doubling in size, which was a waste. Growing it + * linearly is not formally optimal, but is simpler to implement. + * We grow table by minimally required 4*n that would accommodate + * the index. + */ + ctx->max_l_index += (idx - ctx->max_l_index + 4) & ~3; ctx->l = OPENSSL_realloc(ctx->l, ctx->max_l_index * sizeof(OCB_BLOCK)); if (!ctx->l) return NULL; } - ocb_double(ctx->l + (idx - 1), ctx->l + idx); + while (l_index <= idx) { + ocb_double(ctx->l + l_index, ctx->l + l_index + 1); + l_index++; + } + ctx->l_index = l_index; return ctx->l + idx; } @@ -228,7 +242,7 @@ int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec, { memset(ctx, 0, sizeof(*ctx)); ctx->l_index = 0; - ctx->max_l_index = 1; + ctx->max_l_index = 5; ctx->l = OPENSSL_malloc(ctx->max_l_index * 16); if (ctx->l == NULL) return 0; @@ -252,6 +266,13 @@ int CRYPTO_ocb128_init(OCB128_CONTEXT *ctx, void *keyenc, void *keydec, /* L_0 = double(L_$) */ ocb_double(&ctx->l_dollar, ctx->l); + /* L_{i} = double(L_{i-1}) */ + ocb_double(ctx->l, ctx->l+1); + ocb_double(ctx->l+1, ctx->l+2); + ocb_double(ctx->l+2, ctx->l+3); + ocb_double(ctx->l+3, ctx->l+4); + ctx->l_index = 4; /* enough to process up to 496 bytes */ + return 1; } @@ -424,13 +445,13 @@ int CRYPTO_ocb128_encrypt(OCB128_CONTEXT *ctx, /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */ inblock = (OCB_BLOCK *)(in + ((i - ctx->blocks_processed - 1) * 16)); ocb_block16_xor(&ctx->offset, inblock, &tmp1); + /* Checksum_i = Checksum_{i-1} xor P_i */ + ocb_block16_xor(&ctx->checksum, inblock, &ctx->checksum); ocb_encrypt(ctx, &tmp1, &tmp2, ctx->keyenc); outblock = (OCB_BLOCK *)(out + ((i - ctx->blocks_processed - 1) * 16)); ocb_block16_xor(&ctx->offset, &tmp2, outblock); - /* Checksum_i = Checksum_{i-1} xor P_i */ - ocb_block16_xor(&ctx->checksum, inblock, &ctx->checksum); } /* |