[PATCH 5/7] cipher/bulkhelp: add functions for CTR/CBC/CFB/OCB bulk processing
Jussi Kivilinna
jussi.kivilinna at iki.fi
Sun Apr 24 20:40:23 CEST 2022
* cipher/bulkhelp.h (bulk_crypt_fn_t, bulk_ctr_enc_128)
(bulk_cbc_dec_128, bulk_cfb_dec_128, bulk_ocb_crypt_128)
(bulk_ocb_auth_128): New.
* cipher/sm4.c (_gcry_sm4_ctr_enc, _gcry_sm4_cbc_dec)
(_gcry_sm4_cfb_dec, _gcry_sm4_ocb_crypt, _gcry_sm4_ocb_auth): Switch
to use helper functions from 'bulkhelp.h'.
--
Signed-off-by: Jussi Kivilinna <jussi.kivilinna at iki.fi>
---
cipher/bulkhelp.h | 225 ++++++++++++++++++++++++++++++++++++++++++++++
cipher/sm4.c | 184 ++++++++-----------------------------
2 files changed, 260 insertions(+), 149 deletions(-)
diff --git a/cipher/bulkhelp.h b/cipher/bulkhelp.h
index 72668d42..c9ecaba6 100644
--- a/cipher/bulkhelp.h
+++ b/cipher/bulkhelp.h
@@ -32,6 +32,10 @@ typedef u64 ocb_L_uintptr_t;
typedef uintptr_t ocb_L_uintptr_t;
#endif
+typedef unsigned int (*bulk_crypt_fn_t) (const void *ctx, byte *out,
+ const byte *in,
+ unsigned int num_blks);
+
static inline ocb_L_uintptr_t *
bulk_ocb_prepare_L_pointers_array_blk32 (gcry_cipher_hd_t c,
@@ -100,4 +104,225 @@ bulk_ocb_prepare_L_pointers_array_blk8 (gcry_cipher_hd_t c,
}
+static inline unsigned int
+bulk_ctr_enc_128 (void *priv, bulk_crypt_fn_t crypt_fn, byte *outbuf,
+ const byte *inbuf, size_t nblocks, byte *ctr,
+ byte *tmpbuf, size_t tmpbuf_nblocks,
+ unsigned int *num_used_tmpblocks)
+{
+ unsigned int tmp_used = 16;
+ unsigned int burn_depth = 0;
+ unsigned int nburn;
+
+ while (nblocks >= 1)
+ {
+ size_t curr_blks = nblocks > tmpbuf_nblocks ? tmpbuf_nblocks : nblocks;
+ size_t i;
+
+ if (curr_blks * 16 > tmp_used)
+ tmp_used = curr_blks * 16;
+
+ cipher_block_cpy (tmpbuf + 0 * 16, ctr, 16);
+ for (i = 1; i < curr_blks; i++)
+ {
+ cipher_block_cpy (&tmpbuf[i * 16], ctr, 16);
+ cipher_block_add (&tmpbuf[i * 16], i, 16);
+ }
+ cipher_block_add (ctr, curr_blks, 16);
+
+ nburn = crypt_fn (priv, tmpbuf, tmpbuf, curr_blks);
+ burn_depth = nburn > burn_depth ? nburn : burn_depth;
+
+ for (i = 0; i < curr_blks; i++)
+ {
+ cipher_block_xor (outbuf, &tmpbuf[i * 16], inbuf, 16);
+ outbuf += 16;
+ inbuf += 16;
+ }
+
+ nblocks -= curr_blks;
+ }
+
+ *num_used_tmpblocks = tmp_used;
+ return burn_depth;
+}
+
+
+static inline unsigned int
+bulk_cbc_dec_128 (void *priv, bulk_crypt_fn_t crypt_fn, byte *outbuf,
+ const byte *inbuf, size_t nblocks, byte *iv,
+ byte *tmpbuf, size_t tmpbuf_nblocks,
+ unsigned int *num_used_tmpblocks)
+{
+ unsigned int tmp_used = 16;
+ unsigned int burn_depth = 0;
+ unsigned int nburn;
+
+ while (nblocks >= 1)
+ {
+ size_t curr_blks = nblocks > tmpbuf_nblocks ? tmpbuf_nblocks : nblocks;
+ size_t i;
+
+ if (curr_blks * 16 > tmp_used)
+ tmp_used = curr_blks * 16;
+
+ nburn = crypt_fn (priv, tmpbuf, inbuf, curr_blks);
+ burn_depth = nburn > burn_depth ? nburn : burn_depth;
+
+ for (i = 0; i < curr_blks; i++)
+ {
+ cipher_block_xor_n_copy_2(outbuf, &tmpbuf[i * 16], iv, inbuf, 16);
+ outbuf += 16;
+ inbuf += 16;
+ }
+
+ nblocks -= curr_blks;
+ }
+
+ *num_used_tmpblocks = tmp_used;
+ return burn_depth;
+}
+
+
+static inline unsigned int
+bulk_cfb_dec_128 (void *priv, bulk_crypt_fn_t crypt_fn, byte *outbuf,
+ const byte *inbuf, size_t nblocks, byte *iv,
+ byte *tmpbuf, size_t tmpbuf_nblocks,
+ unsigned int *num_used_tmpblocks)
+{
+ unsigned int tmp_used = 16;
+ unsigned int burn_depth = 0;
+ unsigned int nburn;
+
+ while (nblocks >= 1)
+ {
+ size_t curr_blks = nblocks > tmpbuf_nblocks ? tmpbuf_nblocks : nblocks;
+ size_t i;
+
+ if (curr_blks * 16 > tmp_used)
+ tmp_used = curr_blks * 16;
+
+ cipher_block_cpy (&tmpbuf[0 * 16], iv, 16);
+ if (curr_blks > 1)
+ memcpy (&tmpbuf[1 * 16], &inbuf[(1 - 1) * 16], 16 * curr_blks - 16);
+ cipher_block_cpy (iv, &inbuf[(curr_blks - 1) * 16], 16);
+
+ nburn = crypt_fn (priv, tmpbuf, tmpbuf, curr_blks);
+ burn_depth = nburn > burn_depth ? nburn : burn_depth;
+
+ for (i = 0; i < curr_blks; i++)
+ {
+ cipher_block_xor (outbuf, inbuf, &tmpbuf[i * 16], 16);
+ outbuf += 16;
+ inbuf += 16;
+ }
+
+ nblocks -= curr_blks;
+ }
+
+ *num_used_tmpblocks = tmp_used;
+ return burn_depth;
+}
+
+
+static inline unsigned int
+bulk_ocb_crypt_128 (gcry_cipher_hd_t c, void *priv, bulk_crypt_fn_t crypt_fn,
+ byte *outbuf, const byte *inbuf, size_t nblocks, u64 *blkn,
+ int encrypt, byte *tmpbuf, size_t tmpbuf_nblocks,
+ unsigned int *num_used_tmpblocks)
+{
+ unsigned int tmp_used = 16;
+ unsigned int burn_depth = 0;
+ unsigned int nburn;
+
+ while (nblocks >= 1)
+ {
+ size_t curr_blks = nblocks > tmpbuf_nblocks ? tmpbuf_nblocks : nblocks;
+ size_t i;
+
+ if (curr_blks * 16 > tmp_used)
+ tmp_used = curr_blks * 16;
+
+ for (i = 0; i < curr_blks; i++)
+ {
+ const unsigned char *l = ocb_get_l(c, ++*blkn);
+
+ /* Checksum_i = Checksum_{i-1} xor P_i */
+ if (encrypt)
+ cipher_block_xor_1(c->u_ctr.ctr, &inbuf[i * 16], 16);
+
+ /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+ cipher_block_xor_2dst (&tmpbuf[i * 16], c->u_iv.iv, l, 16);
+ cipher_block_xor (&outbuf[i * 16], &inbuf[i * 16],
+ c->u_iv.iv, 16);
+ }
+
+ /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
+ nburn = crypt_fn (priv, outbuf, outbuf, curr_blks);
+ burn_depth = nburn > burn_depth ? nburn : burn_depth;
+
+ for (i = 0; i < curr_blks; i++)
+ {
+ cipher_block_xor_1 (&outbuf[i * 16], &tmpbuf[i * 16], 16);
+
+ /* Checksum_i = Checksum_{i-1} xor P_i */
+ if (!encrypt)
+ cipher_block_xor_1(c->u_ctr.ctr, &outbuf[i * 16], 16);
+ }
+
+ outbuf += curr_blks * 16;
+ inbuf += curr_blks * 16;
+ nblocks -= curr_blks;
+ }
+
+ *num_used_tmpblocks = tmp_used;
+ return burn_depth;
+}
+
+
+static inline unsigned int
+bulk_ocb_auth_128 (gcry_cipher_hd_t c, void *priv, bulk_crypt_fn_t crypt_fn,
+ const byte *abuf, size_t nblocks, u64 *blkn, byte *tmpbuf,
+ size_t tmpbuf_nblocks, unsigned int *num_used_tmpblocks)
+{
+ unsigned int tmp_used = 16;
+ unsigned int burn_depth = 0;
+ unsigned int nburn;
+
+ while (nblocks >= 1)
+ {
+ size_t curr_blks = nblocks > tmpbuf_nblocks ? tmpbuf_nblocks : nblocks;
+ size_t i;
+
+ if (curr_blks * 16 > tmp_used)
+ tmp_used = curr_blks * 16;
+
+ for (i = 0; i < curr_blks; i++)
+ {
+ const unsigned char *l = ocb_get_l(c, ++*blkn);
+
+ /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
+ cipher_block_xor_2dst (&tmpbuf[i * 16],
+ c->u_mode.ocb.aad_offset, l, 16);
+ cipher_block_xor_1 (&tmpbuf[i * 16], &abuf[i * 16], 16);
+ }
+
+ /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
+ nburn = crypt_fn (priv, tmpbuf, tmpbuf, curr_blks);
+ burn_depth = nburn > burn_depth ? nburn : burn_depth;
+
+ for (i = 0; i < curr_blks; i++)
+ {
+ cipher_block_xor_1 (c->u_mode.ocb.aad_sum, &tmpbuf[i * 16], 16);
+ }
+
+ abuf += curr_blks * 16;
+ nblocks -= curr_blks;
+ }
+
+ *num_used_tmpblocks = tmp_used;
+ return burn_depth;
+}
+
+
#endif /*GCRYPT_BULKHELP_H*/
diff --git a/cipher/sm4.c b/cipher/sm4.c
index 0148365c..4815b184 100644
--- a/cipher/sm4.c
+++ b/cipher/sm4.c
@@ -748,36 +748,12 @@ _gcry_sm4_ctr_enc(void *context, unsigned char *ctr,
crypt_blk1_8_fn_t crypt_blk1_8 = sm4_get_crypt_blk1_8_fn(ctx);
byte tmpbuf[16 * 8];
unsigned int tmp_used = 16;
+ size_t nburn;
- /* Process remaining blocks. */
- while (nblocks)
- {
- size_t curr_blks = nblocks > 8 ? 8 : nblocks;
- size_t i;
-
- if (curr_blks * 16 > tmp_used)
- tmp_used = curr_blks * 16;
-
- cipher_block_cpy (tmpbuf + 0 * 16, ctr, 16);
- for (i = 1; i < curr_blks; i++)
- {
- cipher_block_cpy (&tmpbuf[i * 16], ctr, 16);
- cipher_block_add (&tmpbuf[i * 16], i, 16);
- }
- cipher_block_add (ctr, curr_blks, 16);
-
- burn_stack_depth = crypt_blk1_8 (ctx->rkey_enc, tmpbuf, tmpbuf,
- curr_blks);
-
- for (i = 0; i < curr_blks; i++)
- {
- cipher_block_xor (outbuf, &tmpbuf[i * 16], inbuf, 16);
- outbuf += 16;
- inbuf += 16;
- }
-
- nblocks -= curr_blks;
- }
+ nburn = bulk_ctr_enc_128(ctx->rkey_enc, crypt_blk1_8, outbuf, inbuf,
+ nblocks, ctr, tmpbuf, sizeof(tmpbuf) / 16,
+ &tmp_used);
+ burn_stack_depth = nburn > burn_stack_depth ? nburn : burn_stack_depth;
wipememory(tmpbuf, tmp_used);
}
@@ -866,33 +842,16 @@ _gcry_sm4_cbc_dec(void *context, unsigned char *iv,
if (nblocks)
{
crypt_blk1_8_fn_t crypt_blk1_8 = sm4_get_crypt_blk1_8_fn(ctx);
- unsigned char savebuf[16 * 8];
+ unsigned char tmpbuf[16 * 8];
unsigned int tmp_used = 16;
+ size_t nburn;
- /* Process remaining blocks. */
- while (nblocks)
- {
- size_t curr_blks = nblocks > 8 ? 8 : nblocks;
- size_t i;
-
- if (curr_blks * 16 > tmp_used)
- tmp_used = curr_blks * 16;
-
- burn_stack_depth = crypt_blk1_8 (ctx->rkey_dec, savebuf, inbuf,
- curr_blks);
+ nburn = bulk_cbc_dec_128(ctx->rkey_dec, crypt_blk1_8, outbuf, inbuf,
+ nblocks, iv, tmpbuf, sizeof(tmpbuf) / 16,
+ &tmp_used);
+ burn_stack_depth = nburn > burn_stack_depth ? nburn : burn_stack_depth;
- for (i = 0; i < curr_blks; i++)
- {
- cipher_block_xor_n_copy_2(outbuf, &savebuf[i * 16], iv, inbuf,
- 16);
- outbuf += 16;
- inbuf += 16;
- }
-
- nblocks -= curr_blks;
- }
-
- wipememory(savebuf, tmp_used);
+ wipememory(tmpbuf, tmp_used);
}
if (burn_stack_depth)
@@ -979,37 +938,16 @@ _gcry_sm4_cfb_dec(void *context, unsigned char *iv,
if (nblocks)
{
crypt_blk1_8_fn_t crypt_blk1_8 = sm4_get_crypt_blk1_8_fn(ctx);
- unsigned char ivbuf[16 * 8];
+ unsigned char tmpbuf[16 * 8];
unsigned int tmp_used = 16;
+ size_t nburn;
- /* Process remaining blocks. */
- while (nblocks)
- {
- size_t curr_blks = nblocks > 8 ? 8 : nblocks;
- size_t i;
-
- if (curr_blks * 16 > tmp_used)
- tmp_used = curr_blks * 16;
-
- cipher_block_cpy (&ivbuf[0 * 16], iv, 16);
- for (i = 1; i < curr_blks; i++)
- cipher_block_cpy (&ivbuf[i * 16], &inbuf[(i - 1) * 16], 16);
- cipher_block_cpy (iv, &inbuf[(i - 1) * 16], 16);
+ nburn = bulk_cfb_dec_128(ctx->rkey_enc, crypt_blk1_8, outbuf, inbuf,
+ nblocks, iv, tmpbuf, sizeof(tmpbuf) / 16,
+ &tmp_used);
+ burn_stack_depth = nburn > burn_stack_depth ? nburn : burn_stack_depth;
- burn_stack_depth = crypt_blk1_8 (ctx->rkey_enc, ivbuf, ivbuf,
- curr_blks);
-
- for (i = 0; i < curr_blks; i++)
- {
- cipher_block_xor (outbuf, inbuf, &ivbuf[i * 16], 16);
- outbuf += 16;
- inbuf += 16;
- }
-
- nblocks -= curr_blks;
- }
-
- wipememory(ivbuf, tmp_used);
+ wipememory(tmpbuf, tmp_used);
}
if (burn_stack_depth)
@@ -1089,51 +1027,19 @@ _gcry_sm4_ocb_crypt (gcry_cipher_hd_t c, void *outbuf_arg,
}
#endif
+ /* Process remaining blocks. */
if (nblocks)
{
crypt_blk1_8_fn_t crypt_blk1_8 = sm4_get_crypt_blk1_8_fn(ctx);
- const u32 *rk = encrypt ? ctx->rkey_enc : ctx->rkey_dec;
+ u32 *rk = encrypt ? ctx->rkey_enc : ctx->rkey_dec;
unsigned char tmpbuf[16 * 8];
unsigned int tmp_used = 16;
+ size_t nburn;
- while (nblocks)
- {
- size_t curr_blks = nblocks > 8 ? 8 : nblocks;
- size_t i;
-
- if (curr_blks * 16 > tmp_used)
- tmp_used = curr_blks * 16;
-
- for (i = 0; i < curr_blks; i++)
- {
- const unsigned char *l = ocb_get_l(c, ++blkn);
-
- /* Checksum_i = Checksum_{i-1} xor P_i */
- if (encrypt)
- cipher_block_xor_1(c->u_ctr.ctr, &inbuf[i * 16], 16);
-
- /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
- cipher_block_xor_2dst (&tmpbuf[i * 16], c->u_iv.iv, l, 16);
- cipher_block_xor (&outbuf[i * 16], &inbuf[i * 16],
- c->u_iv.iv, 16);
- }
-
- /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
- crypt_blk1_8 (rk, outbuf, outbuf, curr_blks);
-
- for (i = 0; i < curr_blks; i++)
- {
- cipher_block_xor_1 (&outbuf[i * 16], &tmpbuf[i * 16], 16);
-
- /* Checksum_i = Checksum_{i-1} xor P_i */
- if (!encrypt)
- cipher_block_xor_1(c->u_ctr.ctr, &outbuf[i * 16], 16);
- }
-
- outbuf += curr_blks * 16;
- inbuf += curr_blks * 16;
- nblocks -= curr_blks;
- }
+ nburn = bulk_ocb_crypt_128 (c, rk, crypt_blk1_8, outbuf, inbuf, nblocks,
+ &blkn, encrypt, tmpbuf, sizeof(tmpbuf) / 16,
+ &tmp_used);
+ burn_stack_depth = nburn > burn_stack_depth ? nburn : burn_stack_depth;
wipememory(tmpbuf, tmp_used);
}
@@ -1153,6 +1059,7 @@ _gcry_sm4_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks)
SM4_context *ctx = (void *)&c->context.c;
const unsigned char *abuf = abuf_arg;
u64 blkn = c->u_mode.ocb.aad_nblocks;
+ int burn_stack_depth = 0;
#ifdef USE_AESNI_AVX2
if (ctx->use_aesni_avx2)
@@ -1208,47 +1115,26 @@ _gcry_sm4_ocb_auth (gcry_cipher_hd_t c, const void *abuf_arg, size_t nblocks)
}
#endif
+ /* Process remaining blocks. */
if (nblocks)
{
crypt_blk1_8_fn_t crypt_blk1_8 = sm4_get_crypt_blk1_8_fn(ctx);
unsigned char tmpbuf[16 * 8];
unsigned int tmp_used = 16;
+ size_t nburn;
- while (nblocks)
- {
- size_t curr_blks = nblocks > 8 ? 8 : nblocks;
- size_t i;
-
- if (curr_blks * 16 > tmp_used)
- tmp_used = curr_blks * 16;
-
- for (i = 0; i < curr_blks; i++)
- {
- const unsigned char *l = ocb_get_l(c, ++blkn);
-
- /* Offset_i = Offset_{i-1} xor L_{ntz(i)} */
- cipher_block_xor_2dst (&tmpbuf[i * 16],
- c->u_mode.ocb.aad_offset, l, 16);
- cipher_block_xor_1 (&tmpbuf[i * 16], &abuf[i * 16], 16);
- }
-
- /* C_i = Offset_i xor ENCIPHER(K, P_i xor Offset_i) */
- crypt_blk1_8 (ctx->rkey_enc, tmpbuf, tmpbuf, curr_blks);
-
- for (i = 0; i < curr_blks; i++)
- {
- cipher_block_xor_1 (c->u_mode.ocb.aad_sum, &tmpbuf[i * 16], 16);
- }
-
- abuf += curr_blks * 16;
- nblocks -= curr_blks;
- }
+ nburn = bulk_ocb_auth_128 (c, ctx->rkey_enc, crypt_blk1_8, abuf, nblocks,
+ &blkn, tmpbuf, sizeof(tmpbuf) / 16, &tmp_used);
+ burn_stack_depth = nburn > burn_stack_depth ? nburn : burn_stack_depth;
wipememory(tmpbuf, tmp_used);
}
c->u_mode.ocb.aad_nblocks = blkn;
+ if (burn_stack_depth)
+ _gcry_burn_stack(burn_stack_depth);
+
return 0;
}
--
2.34.1
More information about the Gcrypt-devel
mailing list