summaryrefslogtreecommitdiffstats
path: root/crypto/modes
diff options
context:
space:
mode:
authorAndy Polyakov <appro@openssl.org>2015-11-30 13:26:21 +0100
committerAndy Polyakov <appro@openssl.org>2015-12-02 10:48:38 +0100
commitb9e3d7e0f6678a991621cfbc4b11ace7860031a0 (patch)
treeb9a10761a46f7faeef8797c5e04fda8f2048380f /crypto/modes
parent338f5727c88b1ce44a802c5115707309d6316fc4 (diff)
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/modes')
-rw-r--r--crypto/modes/ocb128.c37
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);
}
/*