diff options
author | Niels Möller <nisse@lysator.liu.se> | 2023-02-01 17:15:43 +0100 |
---|---|---|
committer | Niels Möller <nisse@lysator.liu.se> | 2023-02-06 20:27:58 +0100 |
commit | 2324714fddef77faec25ab95f8e52ae88fa8de73 (patch) | |
tree | 52708b503523bd9d58552e3554fecd1fea833d9e | |
parent | e5c2e63cf3c2b98d597f32dbb1cf5e9940c43a49 (diff) | |
download | nettle-2324714fddef77faec25ab95f8e52ae88fa8de73.tar.gz |
Optimizze ocb_update.
-rw-r--r-- | ocb.c | 115 |
1 files changed, 71 insertions, 44 deletions
@@ -130,51 +130,21 @@ ocb_set_nonce (struct ocb_ctx *ctx, ctx->data_count = ctx->message_count = 0; } -void -ocb_update (struct ocb_ctx *ctx, const struct ocb_key *key, - const void *cipher, nettle_cipher_func *f, - size_t length, const uint8_t *data) -{ - assert (ctx->message_count == 0); - - if (ctx->data_count == 0) - ctx->offset.u64[0] = ctx->offset.u64[1] = 0; - - for (; length >= OCB_BLOCK_SIZE; - length -= OCB_BLOCK_SIZE, data += OCB_BLOCK_SIZE) - { - union nettle_block16 block; - update_offset (key, &ctx->offset, ++ctx->data_count); - memxor3 (block.b, ctx->offset.b, data, OCB_BLOCK_SIZE); - f (cipher, OCB_BLOCK_SIZE, block.b, block.b); - block16_xor (&ctx->sum, &block); - } - if (length > 0) - { - union nettle_block16 block; - pad_block (&block, length, data); - block16_xor (&ctx->offset, &key->L[0]); - block16_xor (&block, &ctx->offset); - - f (cipher, OCB_BLOCK_SIZE, block.b, block.b); - block16_xor (&ctx->sum, &block); - } -} - static void -ocb_fill_n (struct ocb_ctx *ctx, const struct ocb_key *key, +ocb_fill_n (const struct ocb_key *key, + union nettle_block16 *offset, size_t count, size_t n, union nettle_block16 *o) { assert (n > 0); union nettle_block16 *prev; - if (ctx->message_count & 1) - prev = &ctx->offset; + if (count & 1) + prev = offset; else { /* Do a single block to align block count. */ - ++ctx->message_count; /* Always odd. */ - block16_xor (&ctx->offset, &key->L[2]); - block16_set (&o[0], &ctx->offset); + count++; /* Always odd. */ + block16_xor (offset, &key->L[2]); + block16_set (&o[0], offset); prev = o; n--; o++; } @@ -182,24 +152,78 @@ ocb_fill_n (struct ocb_ctx *ctx, const struct ocb_key *key, for (; n >= 2; n -= 2, o += 2) { size_t i; - ctx->message_count += 2; /* Always odd. */ + count += 2; /* Always odd. */ /* Based on trailing zeros of ctx->message_count - 1, the initial shift below discards a one bit. */ block16_mulx_be (&o[0], &key->L[2]); - for (i = ctx->message_count >> 1; !(i&1); i >>= 1) + for (i = count >> 1; !(i&1); i >>= 1) block16_mulx_be (&o[0], &o[0]); block16_xor (&o[0], prev); block16_xor3 (&o[1], &o[0], &key->L[2]); prev = &o[1]; } - block16_set(&ctx->offset, prev); + block16_set(offset, prev); if (n > 0) { - update_offset (key, &ctx->offset, ++ctx->message_count); - block16_set (o, &ctx->offset); + update_offset (key, offset, ++count); + block16_set (o, offset); + } +} + +void +ocb_update (struct ocb_ctx *ctx, const struct ocb_key *key, + const void *cipher, nettle_cipher_func *f, + size_t length, const uint8_t *data) +{ + union nettle_block16 block[OCB_MAX_BLOCKS]; + size_t n = length / OCB_BLOCK_SIZE; + assert (ctx->message_count == 0); + + if (ctx->data_count == 0) + ctx->offset.u64[0] = ctx->offset.u64[1] = 0; + + while (n > OCB_MAX_BLOCKS) + { + size_t blocks = OCB_MAX_BLOCKS - 1 + (ctx->data_count & 1); + size_t size, i; + ocb_fill_n (key, &ctx->offset, ctx->data_count, blocks, block); + ctx->data_count += blocks; + + size = blocks * OCB_BLOCK_SIZE; + memxor (block[0].b, data, size); + f (cipher, size, block[0].b, block[0].b); + for (i = 0; i < blocks; i++) + block16_xor(&ctx->sum, &block[i]); + + n -= blocks; data += size; + } + if (n > 0) + { + size_t size, i; + ocb_fill_n (key, &ctx->offset, ctx->data_count, n, block); + ctx->data_count += n; + + size = n * OCB_BLOCK_SIZE; + memxor (block[0].b, data, size); + f (cipher, size, block[0].b, block[0].b); + for (i = 0; i < n; i++) + block16_xor(&ctx->sum, &block[i]); + + data += size; + } + length &= 15; + if (length > 0) + { + union nettle_block16 block; + pad_block (&block, length, data); + block16_xor (&ctx->offset, &key->L[0]); + block16_xor (&block, &ctx->offset); + + f (cipher, OCB_BLOCK_SIZE, block.b, block.b); + block16_xor (&ctx->sum, &block); } } @@ -214,7 +238,8 @@ ocb_crypt_n (struct ocb_ctx *ctx, const struct ocb_key *key, while (n > OCB_MAX_BLOCKS) { size_t blocks = OCB_MAX_BLOCKS - 1 + (ctx->message_count & 1); - ocb_fill_n (ctx, key, blocks, o); + ocb_fill_n (key, &ctx->offset, ctx->message_count, blocks, o); + ctx->message_count += n; size = blocks * OCB_BLOCK_SIZE; memxor3 (block[0].b, o[0].b, src, size); @@ -223,7 +248,9 @@ ocb_crypt_n (struct ocb_ctx *ctx, const struct ocb_key *key, n -= blocks; src += size; dst -= size; } - ocb_fill_n (ctx, key, n, o); + ocb_fill_n (key, &ctx->offset, ctx->message_count, n, o); + ctx->message_count += n; + size = n * OCB_BLOCK_SIZE; memxor3 (block[0].b, o[0].b, src, size); f (cipher, size, block[0].b, block[0].b); |