summaryrefslogtreecommitdiff
path: root/cipher
diff options
context:
space:
mode:
Diffstat (limited to 'cipher')
-rw-r--r--cipher/blowfish.c11
-rw-r--r--cipher/bufhelp.h104
-rw-r--r--cipher/camellia-glue.c11
-rw-r--r--cipher/cast5.c11
-rw-r--r--cipher/cipher-cbc.c53
-rw-r--r--cipher/cipher-ccm.c7
-rw-r--r--cipher/cipher-cfb.c24
-rw-r--r--cipher/cipher-ctr.c5
-rw-r--r--cipher/cipher-ofb.c20
-rw-r--r--cipher/cipher.c10
-rw-r--r--cipher/rijndael.c58
-rw-r--r--cipher/serpent.c11
-rw-r--r--cipher/twofish.c11
13 files changed, 188 insertions, 148 deletions
diff --git a/cipher/blowfish.c b/cipher/blowfish.c
index ed4e901d..3b6bf6b9 100644
--- a/cipher/blowfish.c
+++ b/cipher/blowfish.c
@@ -701,14 +701,11 @@ _gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
for ( ;nblocks; nblocks-- )
{
- /* We need to save INBUF away because it may be identical to
- OUTBUF. */
- memcpy(savebuf, inbuf, BLOWFISH_BLOCKSIZE);
+ /* INBUF is needed later and it may be identical to OUTBUF, so store
+ the intermediate result to SAVEBUF. */
+ do_decrypt_block (ctx, savebuf, inbuf);
- do_decrypt_block (ctx, outbuf, inbuf);
-
- buf_xor(outbuf, outbuf, iv, BLOWFISH_BLOCKSIZE);
- memcpy(iv, savebuf, BLOWFISH_BLOCKSIZE);
+ buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOWFISH_BLOCKSIZE);
inbuf += BLOWFISH_BLOCKSIZE;
outbuf += BLOWFISH_BLOCKSIZE;
}
diff --git a/cipher/bufhelp.h b/cipher/bufhelp.h
index 198d2868..dc39b46d 100644
--- a/cipher/bufhelp.h
+++ b/cipher/bufhelp.h
@@ -44,6 +44,45 @@
#endif
+/* Optimized function for small buffer copying */
+static inline void
+buf_cpy(void *_dst, const void *_src, size_t len)
+{
+#if __GNUC__ >= 4 && (defined(__x86_64__) || defined(__i386__))
+ /* For AMD64 and i386, memcpy is faster. */
+ memcpy(_dst, _src, len);
+#else
+ byte *dst = _dst;
+ const byte *src = _src;
+ uintptr_t *ldst;
+ const uintptr_t *lsrc;
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+ const unsigned int longmask = sizeof(uintptr_t) - 1;
+
+ /* Skip fast processing if buffers are unaligned. */
+ if (((uintptr_t)dst | (uintptr_t)src) & longmask)
+ goto do_bytes;
+#endif
+
+ ldst = (uintptr_t *)(void *)dst;
+ lsrc = (const uintptr_t *)(const void *)src;
+
+ for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t))
+ *ldst++ = *lsrc++;
+
+ dst = (byte *)ldst;
+ src = (const byte *)lsrc;
+
+#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
+do_bytes:
+#endif
+ /* Handle tail. */
+ for (; len; len--)
+ *dst++ = *src++;
+#endif /*__GNUC__ >= 4 && (__x86_64__ || __i386__)*/
+}
+
+
/* Optimized function for buffer xoring */
static inline void
buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
@@ -56,14 +95,9 @@ buf_xor(void *_dst, const void *_src1, const void *_src2, size_t len)
#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
const unsigned int longmask = sizeof(uintptr_t) - 1;
- /* Skip fast processing if alignment of buffers do not match. */
- if ((((uintptr_t)dst ^ (uintptr_t)src1) |
- ((uintptr_t)dst ^ (uintptr_t)src2)) & longmask)
+ /* Skip fast processing if buffers are unaligned. */
+ if (((uintptr_t)dst | (uintptr_t)src1 | (uintptr_t)src2) & longmask)
goto do_bytes;
-
- /* Handle unaligned head. */
- for (; len && ((uintptr_t)dst & longmask); len--)
- *dst++ = *src1++ ^ *src2++;
#endif
ldst = (uintptr_t *)(void *)dst;
@@ -99,14 +133,9 @@ buf_xor_2dst(void *_dst1, void *_dst2, const void *_src, size_t len)
#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
const unsigned int longmask = sizeof(uintptr_t) - 1;
- /* Skip fast processing if alignment of buffers do not match. */
- if ((((uintptr_t)src ^ (uintptr_t)dst1) |
- ((uintptr_t)src ^ (uintptr_t)dst2)) & longmask)
+ /* Skip fast processing if buffers are unaligned. */
+ if (((uintptr_t)src | (uintptr_t)dst1 | (uintptr_t)dst2) & longmask)
goto do_bytes;
-
- /* Handle unaligned head. */
- for (; len && ((uintptr_t)src & longmask); len--)
- *dst1++ = (*dst2++ ^= *src++);
#endif
ldst1 = (uintptr_t *)(void *)dst1;
@@ -130,48 +159,44 @@ do_bytes:
/* Optimized function for combined buffer xoring and copying. Used by mainly
- CFB mode decryption. */
+ CBC mode decryption. */
static inline void
-buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len)
+buf_xor_n_copy_2(void *_dst_xor, const void *_src_xor, void *_srcdst_cpy,
+ const void *_src_cpy, size_t len)
{
byte *dst_xor = _dst_xor;
byte *srcdst_cpy = _srcdst_cpy;
+ const byte *src_xor = _src_xor;
+ const byte *src_cpy = _src_cpy;
byte temp;
- const byte *src = _src;
uintptr_t *ldst_xor, *lsrcdst_cpy;
- const uintptr_t *lsrc;
+ const uintptr_t *lsrc_cpy, *lsrc_xor;
uintptr_t ltemp;
#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
const unsigned int longmask = sizeof(uintptr_t) - 1;
- /* Skip fast processing if alignment of buffers do not match. */
- if ((((uintptr_t)src ^ (uintptr_t)dst_xor) |
- ((uintptr_t)src ^ (uintptr_t)srcdst_cpy)) & longmask)
+ /* Skip fast processing if buffers are unaligned. */
+ if (((uintptr_t)src_cpy | (uintptr_t)src_xor | (uintptr_t)dst_xor |
+ (uintptr_t)srcdst_cpy) & longmask)
goto do_bytes;
-
- /* Handle unaligned head. */
- for (; len && ((uintptr_t)src & longmask); len--)
- {
- temp = *src++;
- *dst_xor++ = *srcdst_cpy ^ temp;
- *srcdst_cpy++ = temp;
- }
#endif
ldst_xor = (uintptr_t *)(void *)dst_xor;
+ lsrc_xor = (const uintptr_t *)(void *)src_xor;
lsrcdst_cpy = (uintptr_t *)(void *)srcdst_cpy;
- lsrc = (const uintptr_t *)(const void *)src;
+ lsrc_cpy = (const uintptr_t *)(const void *)src_cpy;
for (; len >= sizeof(uintptr_t); len -= sizeof(uintptr_t))
{
- ltemp = *lsrc++;
- *ldst_xor++ = *lsrcdst_cpy ^ ltemp;
+ ltemp = *lsrc_cpy++;
+ *ldst_xor++ = *lsrcdst_cpy ^ *lsrc_xor++;
*lsrcdst_cpy++ = ltemp;
}
dst_xor = (byte *)ldst_xor;
+ src_xor = (const byte *)lsrc_xor;
srcdst_cpy = (byte *)lsrcdst_cpy;
- src = (const byte *)lsrc;
+ src_cpy = (const byte *)lsrc_cpy;
#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
do_bytes:
@@ -179,13 +204,22 @@ do_bytes:
/* Handle tail. */
for (; len; len--)
{
- temp = *src++;
- *dst_xor++ = *srcdst_cpy ^ temp;
+ temp = *src_cpy++;
+ *dst_xor++ = *srcdst_cpy ^ *src_xor++;
*srcdst_cpy++ = temp;
}
}
+/* Optimized function for combined buffer xoring and copying. Used by mainly
+ CFB mode decryption. */
+static inline void
+buf_xor_n_copy(void *_dst_xor, void *_srcdst_cpy, const void *_src, size_t len)
+{
+ buf_xor_n_copy_2(_dst_xor, _src, _srcdst_cpy, _src, len);
+}
+
+
#ifndef BUFHELP_FAST_UNALIGNED_ACCESS
/* Functions for loading and storing unaligned u32 values of different
diff --git a/cipher/camellia-glue.c b/cipher/camellia-glue.c
index e6d40298..8c217a76 100644
--- a/cipher/camellia-glue.c
+++ b/cipher/camellia-glue.c
@@ -441,14 +441,11 @@ _gcry_camellia_cbc_dec(void *context, unsigned char *iv,
for ( ;nblocks; nblocks-- )
{
- /* We need to save INBUF away because it may be identical to
- OUTBUF. */
- memcpy(savebuf, inbuf, CAMELLIA_BLOCK_SIZE);
+ /* INBUF is needed later and it may be identical to OUTBUF, so store
+ the intermediate result to SAVEBUF. */
+ Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, savebuf);
- Camellia_DecryptBlock(ctx->keybitlength, inbuf, ctx->keytable, outbuf);
-
- buf_xor(outbuf, outbuf, iv, CAMELLIA_BLOCK_SIZE);
- memcpy(iv, savebuf, CAMELLIA_BLOCK_SIZE);
+ buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAMELLIA_BLOCK_SIZE);
inbuf += CAMELLIA_BLOCK_SIZE;
outbuf += CAMELLIA_BLOCK_SIZE;
}
diff --git a/cipher/cast5.c b/cipher/cast5.c
index 8c016d7c..0df7886d 100644
--- a/cipher/cast5.c
+++ b/cipher/cast5.c
@@ -678,14 +678,11 @@ _gcry_cast5_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
for ( ;nblocks; nblocks-- )
{
- /* We need to save INBUF away because it may be identical to
- OUTBUF. */
- memcpy(savebuf, inbuf, CAST5_BLOCKSIZE);
+ /* INBUF is needed later and it may be identical to OUTBUF, so store
+ the intermediate result to SAVEBUF. */
+ do_decrypt_block (ctx, savebuf, inbuf);
- do_decrypt_block (ctx, outbuf, inbuf);
-
- buf_xor(outbuf, outbuf, iv, CAST5_BLOCKSIZE);
- memcpy(iv, savebuf, CAST5_BLOCKSIZE);
+ buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAST5_BLOCKSIZE);
inbuf += CAST5_BLOCKSIZE;
outbuf += CAST5_BLOCKSIZE;
}
diff --git a/cipher/cipher-cbc.c b/cipher/cipher-cbc.c
index 523f5a69..4ad2ebd8 100644
--- a/cipher/cipher-cbc.c
+++ b/cipher/cipher-cbc.c
@@ -41,14 +41,15 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
unsigned char *ivp;
int i;
size_t blocksize = c->spec->blocksize;
+ gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
unsigned nblocks = inbuflen / blocksize;
unsigned int burn, nburn;
if (outbuflen < ((c->flags & GCRY_CIPHER_CBC_MAC)? blocksize : inbuflen))
return GPG_ERR_BUFFER_TOO_SHORT;
- if ((inbuflen % c->spec->blocksize)
- && !(inbuflen > c->spec->blocksize
+ if ((inbuflen % blocksize)
+ && !(inbuflen > blocksize
&& (c->flags & GCRY_CIPHER_CBC_CTS)))
return GPG_ERR_INV_LENGTH;
@@ -70,16 +71,21 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
}
else
{
+ ivp = c->u_iv.iv;
+
for (n=0; n < nblocks; n++ )
{
- buf_xor(outbuf, inbuf, c->u_iv.iv, blocksize);
- nburn = c->spec->encrypt ( &c->context.c, outbuf, outbuf );
+ buf_xor (outbuf, inbuf, ivp, blocksize);
+ nburn = enc_fn ( &c->context.c, outbuf, outbuf );
burn = nburn > burn ? nburn : burn;
- memcpy (c->u_iv.iv, outbuf, blocksize );
+ ivp = outbuf;
inbuf += blocksize;
if (!(c->flags & GCRY_CIPHER_CBC_MAC))
outbuf += blocksize;
}
+
+ if (ivp != c->u_iv.iv)
+ buf_cpy (c->u_iv.iv, ivp, blocksize );
}
if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
@@ -104,9 +110,9 @@ _gcry_cipher_cbc_encrypt (gcry_cipher_hd_t c,
for (; i < blocksize; i++)
outbuf[i] = 0 ^ *ivp++;
- nburn = c->spec->encrypt (&c->context.c, outbuf, outbuf);
+ nburn = enc_fn (&c->context.c, outbuf, outbuf);
burn = nburn > burn ? nburn : burn;
- memcpy (c->u_iv.iv, outbuf, blocksize);
+ buf_cpy (c->u_iv.iv, outbuf, blocksize);
}
if (burn > 0)
@@ -124,14 +130,15 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
unsigned int n;
int i;
size_t blocksize = c->spec->blocksize;
+ gcry_cipher_decrypt_t dec_fn = c->spec->decrypt;
unsigned int nblocks = inbuflen / blocksize;
unsigned int burn, nburn;
if (outbuflen < inbuflen)
return GPG_ERR_BUFFER_TOO_SHORT;
- if ((inbuflen % c->spec->blocksize)
- && !(inbuflen > c->spec->blocksize
+ if ((inbuflen % blocksize)
+ && !(inbuflen > blocksize
&& (c->flags & GCRY_CIPHER_CBC_CTS)))
return GPG_ERR_INV_LENGTH;
@@ -142,7 +149,7 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
nblocks--;
if ((inbuflen % blocksize) == 0)
nblocks--;
- memcpy (c->lastiv, c->u_iv.iv, blocksize);
+ buf_cpy (c->lastiv, c->u_iv.iv, blocksize);
}
if (c->bulk.cbc_dec)
@@ -155,16 +162,14 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
{
for (n=0; n < nblocks; n++ )
{
- /* Because outbuf and inbuf might be the same, we have to
- * save the original ciphertext block. We use LASTIV for
- * this here because it is not used otherwise. */
- memcpy (c->lastiv, inbuf, blocksize);
- nburn = c->spec->decrypt ( &c->context.c, outbuf, inbuf );
+ /* Because outbuf and inbuf might be the same, we must not overwrite
+ the original ciphertext block. We use LASTIV as intermediate
+ storage here because it is not used otherwise. */
+ nburn = dec_fn ( &c->context.c, c->lastiv, inbuf );
burn = nburn > burn ? nburn : burn;
- buf_xor(outbuf, outbuf, c->u_iv.iv, blocksize);
- memcpy(c->u_iv.iv, c->lastiv, blocksize );
- inbuf += c->spec->blocksize;
- outbuf += c->spec->blocksize;
+ buf_xor_n_copy_2(outbuf, c->lastiv, c->u_iv.iv, inbuf, blocksize);
+ inbuf += blocksize;
+ outbuf += blocksize;
}
}
@@ -177,17 +182,17 @@ _gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
else
restbytes = inbuflen % blocksize;
- memcpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */
- memcpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
+ buf_cpy (c->lastiv, c->u_iv.iv, blocksize ); /* Save Cn-2. */
+ buf_cpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */
- nburn = c->spec->decrypt ( &c->context.c, outbuf, inbuf );
+ nburn = dec_fn ( &c->context.c, outbuf, inbuf );
burn = nburn > burn ? nburn : burn;
buf_xor(outbuf, outbuf, c->u_iv.iv, restbytes);
- memcpy(outbuf + blocksize, outbuf, restbytes);
+ buf_cpy (outbuf + blocksize, outbuf, restbytes);
for(i=restbytes; i < blocksize; i++)
c->u_iv.iv[i] = outbuf[i];
- nburn = c->spec->decrypt (&c->context.c, outbuf, c->u_iv.iv);
+ nburn = dec_fn (&c->context.c, outbuf, c->u_iv.iv);
burn = nburn > burn ? nburn : burn;
buf_xor(outbuf, outbuf, c->lastiv, blocksize);
/* c->lastiv is now really lastlastiv, does this matter? */
diff --git a/cipher/cipher-ccm.c b/cipher/cipher-ccm.c
index 38752d5d..ebcbf1e9 100644
--- a/cipher/cipher-ccm.c
+++ b/cipher/cipher-ccm.c
@@ -40,6 +40,7 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen,
int do_padding)
{
const unsigned int blocksize = 16;
+ gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
unsigned char tmp[blocksize];
unsigned int burn = 0;
unsigned int unused = c->u_mode.ccm.mac_unused;
@@ -68,8 +69,7 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen,
{
/* Process one block from macbuf. */
buf_xor(c->u_iv.iv, c->u_iv.iv, c->u_mode.ccm.macbuf, blocksize);
- set_burn (burn, c->spec->encrypt ( &c->context.c, c->u_iv.iv,
- c->u_iv.iv ));
+ set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ));
unused = 0;
}
@@ -89,8 +89,7 @@ do_cbc_mac (gcry_cipher_hd_t c, const unsigned char *inbuf, size_t inlen,
{
buf_xor(c->u_iv.iv, c->u_iv.iv, inbuf, blocksize);
- set_burn (burn, c->spec->encrypt ( &c->context.c, c->u_iv.iv,
- c->u_iv.iv ));
+ set_burn (burn, enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv ));
inlen -= blocksize;
inbuf += blocksize;
diff --git a/cipher/cipher-cfb.c b/cipher/cipher-cfb.c
index 244f5fdd..610d0068 100644
--- a/cipher/cipher-cfb.c
+++ b/cipher/cipher-cfb.c
@@ -37,6 +37,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned char *ivp;
+ gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
size_t blocksize = c->spec->blocksize;
size_t blocksize_x_2 = blocksize + blocksize;
unsigned int burn, nburn;
@@ -48,7 +49,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
{
/* Short enough to be encoded by the remaining XOR mask. */
/* XOR the input with the IV and store input into IV. */
- ivp = c->u_iv.iv + c->spec->blocksize - c->unused;
+ ivp = c->u_iv.iv + blocksize - c->unused;
buf_xor_2dst(outbuf, ivp, inbuf, inbuflen);
c->unused -= inbuflen;
return 0;
@@ -83,7 +84,7 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
while ( inbuflen >= blocksize_x_2 )
{
/* Encrypt the IV. */
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
/* XOR the input with the IV and store input into IV. */
buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
@@ -96,8 +97,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
if ( inbuflen >= blocksize )
{
/* Save the current IV and then encrypt the IV. */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
/* XOR the input with the IV and store input into IV */
buf_xor_2dst(outbuf, c->u_iv.iv, inbuf, blocksize);
@@ -108,8 +109,8 @@ _gcry_cipher_cfb_encrypt (gcry_cipher_hd_t c,
if ( inbuflen )
{
/* Save the current IV and then encrypt the IV. */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
c->unused = blocksize;
/* Apply the XOR. */
@@ -133,6 +134,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned char *ivp;
+ gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
size_t blocksize = c->spec->blocksize;
size_t blocksize_x_2 = blocksize + blocksize;
unsigned int burn, nburn;
@@ -179,7 +181,7 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
while (inbuflen >= blocksize_x_2 )
{
/* Encrypt the IV. */
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
/* XOR the input with the IV and store input into IV. */
buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
@@ -192,8 +194,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
if (inbuflen >= blocksize )
{
/* Save the current IV and then encrypt the IV. */
- memcpy ( c->lastiv, c->u_iv.iv, blocksize);
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ buf_cpy ( c->lastiv, c->u_iv.iv, blocksize);
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
/* XOR the input with the IV and store input into IV */
buf_xor_n_copy(outbuf, c->u_iv.iv, inbuf, blocksize);
@@ -205,8 +207,8 @@ _gcry_cipher_cfb_decrypt (gcry_cipher_hd_t c,
if (inbuflen)
{
/* Save the current IV and then encrypt the IV. */
- memcpy ( c->lastiv, c->u_iv.iv, blocksize );
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ buf_cpy ( c->lastiv, c->u_iv.iv, blocksize );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
c->unused = blocksize;
/* Apply the XOR. */
diff --git a/cipher/cipher-ctr.c b/cipher/cipher-ctr.c
index fbc898f1..37a6a79e 100644
--- a/cipher/cipher-ctr.c
+++ b/cipher/cipher-ctr.c
@@ -38,6 +38,7 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
{
unsigned int n;
int i;
+ gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
unsigned int blocksize = c->spec->blocksize;
unsigned int nblocks;
unsigned int burn, nburn;
@@ -77,7 +78,7 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
unsigned char tmp[MAX_BLOCKSIZE];
do {
- nburn = c->spec->encrypt (&c->context.c, tmp, c->u_ctr.ctr);
+ nburn = enc_fn (&c->context.c, tmp, c->u_ctr.ctr);
burn = nburn > burn ? nburn : burn;
for (i = blocksize; i > 0; i--)
@@ -98,7 +99,7 @@ _gcry_cipher_ctr_encrypt (gcry_cipher_hd_t c,
/* Save the unused bytes of the counter. */
c->unused = blocksize - n;
if (c->unused)
- memcpy (c->lastiv+n, tmp+n, c->unused);
+ buf_cpy (c->lastiv+n, tmp+n, c->unused);
wipememory (tmp, sizeof tmp);
}
diff --git a/cipher/cipher-ofb.c b/cipher/cipher-ofb.c
index 3d9d54c3..333a7481 100644
--- a/cipher/cipher-ofb.c
+++ b/cipher/cipher-ofb.c
@@ -37,6 +37,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned char *ivp;
+ gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
size_t blocksize = c->spec->blocksize;
unsigned int burn, nburn;
@@ -47,7 +48,7 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
{
/* Short enough to be encoded by the remaining XOR mask. */
/* XOR the input with the IV */
- ivp = c->u_iv.iv + c->spec->blocksize - c->unused;
+ ivp = c->u_iv.iv + blocksize - c->unused;
buf_xor(outbuf, ivp, inbuf, inbuflen);
c->unused -= inbuflen;
return 0;
@@ -69,8 +70,8 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
while ( inbuflen >= blocksize )
{
/* Encrypt the IV (and save the current one). */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
outbuf += blocksize;
@@ -79,8 +80,8 @@ _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
}
if ( inbuflen )
{ /* process the remaining bytes */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
c->unused = blocksize;
c->unused -= inbuflen;
@@ -103,6 +104,7 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
const unsigned char *inbuf, unsigned int inbuflen)
{
unsigned char *ivp;
+ gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
size_t blocksize = c->spec->blocksize;
unsigned int burn, nburn;
@@ -134,8 +136,8 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
while ( inbuflen >= blocksize )
{
/* Encrypt the IV (and save the current one). */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
outbuf += blocksize;
@@ -145,8 +147,8 @@ _gcry_cipher_ofb_decrypt (gcry_cipher_hd_t c,
if ( inbuflen )
{ /* Process the remaining bytes. */
/* Encrypt the IV (and save the current one). */
- memcpy( c->lastiv, c->u_iv.iv, blocksize );
- nburn = c->spec->encrypt ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
+ buf_cpy( c->lastiv, c->u_iv.iv, blocksize );
+ nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
burn = nburn > burn ? nburn : burn;
c->unused = blocksize;
c->unused -= inbuflen;
diff --git a/cipher/cipher.c b/cipher/cipher.c
index 5214d26c..c0d1d0be 100644
--- a/cipher/cipher.c
+++ b/cipher/cipher.c
@@ -631,6 +631,7 @@ do_ecb_encrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, unsigned int outbuflen,
const unsigned char *inbuf, unsigned int inbuflen)
{
+ gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
unsigned int blocksize = c->spec->blocksize;
unsigned int n, nblocks;
unsigned int burn, nburn;
@@ -640,12 +641,12 @@ do_ecb_encrypt (gcry_cipher_hd_t c,
if ((inbuflen % blocksize))
return GPG_ERR_INV_LENGTH;
- nblocks = inbuflen / c->spec->blocksize;
+ nblocks = inbuflen / blocksize;
burn = 0;
for (n=0; n < nblocks; n++ )
{
- nburn = c->spec->encrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
+ nburn = enc_fn (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
burn = nburn > burn ? nburn : burn;
inbuf += blocksize;
outbuf += blocksize;
@@ -662,6 +663,7 @@ do_ecb_decrypt (gcry_cipher_hd_t c,
unsigned char *outbuf, unsigned int outbuflen,
const unsigned char *inbuf, unsigned int inbuflen)
{
+ gcry_cipher_decrypt_t dec_fn = c->spec->decrypt;
unsigned int blocksize = c->spec->blocksize;
unsigned int n, nblocks;
unsigned int burn, nburn;
@@ -671,12 +673,12 @@ do_ecb_decrypt (gcry_cipher_hd_t c,
if ((inbuflen % blocksize))
return GPG_ERR_INV_LENGTH;
- nblocks = inbuflen / c->spec->blocksize;
+ nblocks = inbuflen / blocksize;
burn = 0;
for (n=0; n < nblocks; n++ )
{
- nburn = c->spec->decrypt (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
+ nburn = dec_fn (&c->context.c, outbuf, (byte*)/*arggg*/inbuf);
burn = nburn > burn ? nburn : burn;
inbuf += blocksize;
outbuf += blocksize;
diff --git a/cipher/rijndael.c b/cipher/rijndael.c
index e9bb4f68..e8733c93 100644
--- a/cipher/rijndael.c
+++ b/cipher/rijndael.c
@@ -675,9 +675,9 @@ do_encrypt (const RIJNDAEL_context *ctx,
byte b[16] ATTR_ALIGNED_16;
} b;
- memcpy (a.a, ax, 16);
+ buf_cpy (a.a, ax, 16);
do_encrypt_aligned (ctx, b.b, a.a);
- memcpy (bx, b.b, 16);
+ buf_cpy (bx, b.b, 16);
}
else
#endif /*!USE_AMD64_ASM && !USE_ARM_ASM*/
@@ -1556,12 +1556,15 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv,
RIJNDAEL_context *ctx = context;
unsigned char *outbuf = outbuf_arg;
const unsigned char *inbuf = inbuf_arg;
+ unsigned char *last_iv;
#ifdef USE_AESNI
if (ctx->use_aesni)
aesni_prepare ();
#endif /*USE_AESNI*/
+ last_iv = iv;
+
for ( ;nblocks; nblocks-- )
{
if (0)
@@ -1576,24 +1579,17 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv,
"pxor %%xmm0, %%xmm1\n\t"
"movdqu %%xmm1, %[outbuf]\n\t"
: /* No output */
- : [iv] "m" (*iv),
+ : [iv] "m" (*last_iv),
[inbuf] "m" (*inbuf),
[outbuf] "m" (*outbuf)
: "memory" );
do_aesni (ctx, 0, outbuf, outbuf);
-
- asm volatile ("movdqu %[outbuf], %%xmm0\n\t"
- "movdqu %%xmm0, %[iv]\n\t"
- : /* No output */
- : [outbuf] "m" (*outbuf),
- [iv] "m" (*iv)
- : "memory" );
}
#endif /*USE_AESNI*/
else
{
- buf_xor(outbuf, inbuf, iv, BLOCKSIZE);
+ buf_xor(outbuf, inbuf, last_iv, BLOCKSIZE);
if (0)
;
@@ -1603,18 +1599,34 @@ _gcry_aes_cbc_enc (void *context, unsigned char *iv,
#endif /*USE_PADLOCK*/
else
do_encrypt (ctx, outbuf, outbuf );
-
- memcpy (iv, outbuf, BLOCKSIZE);
}
+ last_iv = outbuf;
inbuf += BLOCKSIZE;
if (!cbc_mac)
outbuf += BLOCKSIZE;
}
+ if (last_iv != iv)
+ {
+ if (0)
+ ;
+#ifdef USE_AESNI
+ else if (ctx->use_aesni)
+ asm volatile ("movdqu %[last], %%xmm0\n\t"
+ "movdqu %%xmm0, %[iv]\n\t"
+ : /* No output */
+ : [last] "m" (*last_iv),
+ [iv] "m" (*iv)
+ : "memory" );
+#endif /*USE_AESNI*/
+ else
+ buf_cpy (iv, last_iv, BLOCKSIZE);
+ }
+
#ifdef USE_AESNI
- if (ctx->use_aesni)
- aesni_cleanup ();
+ if (ctx->use_aesni)
+ aesni_cleanup ();
#endif /*USE_AESNI*/
_gcry_burn_stack (48 + 2*sizeof(int));
@@ -1810,9 +1822,9 @@ do_decrypt (RIJNDAEL_context *ctx, byte *bx, const byte *ax)
byte b[16] ATTR_ALIGNED_16;
} b;
- memcpy (a.a, ax, 16);
+ buf_cpy (a.a, ax, 16);
do_decrypt_aligned (ctx, b.b, a.a);
- memcpy (bx, b.b, 16);
+ buf_cpy (bx, b.b, 16);
}
else
#endif /*!USE_AMD64_ASM && !USE_ARM_ASM*/
@@ -2068,21 +2080,19 @@ _gcry_aes_cbc_dec (void *context, unsigned char *iv,
else
for ( ;nblocks; nblocks-- )
{
- /* We need to save INBUF away because it may be identical to
- OUTBUF. */
- memcpy (savebuf, inbuf, BLOCKSIZE);
+ /* INBUF is needed later and it may be identical to OUTBUF, so store
+ the intermediate result to SAVEBUF. */
if (0)
;
#ifdef USE_PADLOCK
else if (ctx->use_padlock)
- do_padlock (ctx, 1, outbuf, inbuf);
+ do_padlock (ctx, 1, savebuf, inbuf);
#endif /*USE_PADLOCK*/
else
- do_decrypt (ctx, outbuf, inbuf);
+ do_decrypt (ctx, savebuf, inbuf);
- buf_xor(outbuf, outbuf, iv, BLOCKSIZE);
- memcpy (iv, savebuf, BLOCKSIZE);
+ buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE);
inbuf += BLOCKSIZE;
outbuf += BLOCKSIZE;
}
diff --git a/cipher/serpent.c b/cipher/serpent.c
index c0898dcd..a8ee15f3 100644
--- a/cipher/serpent.c
+++ b/cipher/serpent.c
@@ -950,14 +950,11 @@ _gcry_serpent_cbc_dec(void *context, unsigned char *iv,
for ( ;nblocks; nblocks-- )
{
- /* We need to save INBUF away because it may be identical to
- OUTBUF. */
- memcpy(savebuf, inbuf, sizeof(serpent_block_t));
+ /* INBUF is needed later and it may be identical to OUTBUF, so store
+ the intermediate result to SAVEBUF. */
+ serpent_decrypt_internal (ctx, inbuf, savebuf);
- serpent_decrypt_internal (ctx, inbuf, outbuf);
-
- buf_xor(outbuf, outbuf, iv, sizeof(serpent_block_t));
- memcpy(iv, savebuf, sizeof(serpent_block_t));
+ buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, sizeof(serpent_block_t));
inbuf += sizeof(serpent_block_t);
outbuf += sizeof(serpent_block_t);
}
diff --git a/cipher/twofish.c b/cipher/twofish.c
index 086df76f..04081dbb 100644
--- a/cipher/twofish.c
+++ b/cipher/twofish.c
@@ -1055,16 +1055,13 @@ _gcry_twofish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
for ( ;nblocks; nblocks-- )
{
- /* We need to save INBUF away because it may be identical to
- OUTBUF. */
- memcpy(savebuf, inbuf, TWOFISH_BLOCKSIZE);
-
- burn = twofish_decrypt (ctx, outbuf, inbuf);
+ /* INBUF is needed later and it may be identical to OUTBUF, so store
+ the intermediate result to SAVEBUF. */
+ burn = twofish_decrypt (ctx, savebuf, inbuf);
if (burn > burn_stack_depth)
burn_stack_depth = burn;
- buf_xor(outbuf, outbuf, iv, TWOFISH_BLOCKSIZE);
- memcpy(iv, savebuf, TWOFISH_BLOCKSIZE);
+ buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, TWOFISH_BLOCKSIZE);
inbuf += TWOFISH_BLOCKSIZE;
outbuf += TWOFISH_BLOCKSIZE;
}