AES: move look-up tables to .data section and unshare between processes

* cipher/rijndael-internal.h (ATTR_ALIGNED_64): New.
* cipher/rijndael-tables.h (encT): Move to 'enc_tables' structure.
(enc_tables): New structure for encryption table with counters before
and after.
(encT): New macro.
(dec_tables): Add counters before and after encryption table; Move
from .rodata to .data section.
(do_encrypt): Change 'encT' to 'enc_tables.T'.
(do_decrypt): Change '&dec_tables' to 'dec_tables.T'.
* cipher/cipher-gcm.c (prefetch_table): Make inline; Handle input
with length not multiple of 256.
(prefetch_enc, prefetch_dec): Modify pre- and post-table counters
to unshare look-up table pages between processes.
--

GnuPG-bug-id: 4541
Signed-off-by: Jussi Kivilinna <jussi.kivilinna@iki.fi>
_gcry_aes_cbc_dec (void *context, unsigned char *iv,
                   void *outbuf_arg, const void *inbuf_arg,
                   size_t nblocks)
{
  RIJNDAEL_context *ctx = context;
  unsigned char *outbuf = outbuf_arg;
  const unsigned char *inbuf = inbuf_arg;
  unsigned int burn_depth = 0;

  if (0)
    ;
#ifdef USE_AESNI
  else if (ctx->use_aesni)
    {
      _gcry_aes_aesni_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
      return;
    }
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
  else if (ctx->use_ssse3)
    {
      _gcry_aes_ssse3_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
      return;
    }
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
  else if (ctx->use_arm_ce)
    {
      _gcry_aes_armv8_ce_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
      return;
    }
#endif /*USE_ARM_CE*/
  else
    {
      unsigned char savebuf[BLOCKSIZE] ATTR_ALIGNED_16;
      rijndael_cryptfn_t decrypt_fn = ctx->decrypt_fn;

      check_decryption_preparation (ctx);

      if (ctx->prefetch_dec_fn)
        ctx->prefetch_dec_fn();

      for ( ;nblocks; nblocks-- )
        {
          /* INBUF is needed later and it may be identical to OUTBUF, so store
             the intermediate result to SAVEBUF.  */

          burn_depth = decrypt_fn (ctx, savebuf, inbuf);

          cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE);
          inbuf += BLOCKSIZE;
          outbuf += BLOCKSIZE;
        }

      wipememory(savebuf, sizeof(savebuf));
    }

  if (burn_depth)
    _gcry_burn_stack (burn_depth + 4 * sizeof(void *));
}

_gcry_aes_cbc_dec (void *context, unsigned char *iv,
                   void *outbuf_arg, const void *inbuf_arg,
                   size_t nblocks)
{
  RIJNDAEL_context *ctx = context;
  unsigned char *outbuf = outbuf_arg;
  const unsigned char *inbuf = inbuf_arg;
  unsigned int burn_depth = 0;

  if (0)
    ;
#ifdef USE_AESNI
  else if (ctx->use_aesni)
    {
      _gcry_aes_aesni_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
      return;
    }
#endif /*USE_AESNI*/
#ifdef USE_SSSE3
  else if (ctx->use_ssse3)
    {
      _gcry_aes_ssse3_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
      return;
    }
#endif /*USE_SSSE3*/
#ifdef USE_ARM_CE
  else if (ctx->use_arm_ce)
    {
      _gcry_aes_armv8_ce_cbc_dec (ctx, iv, outbuf, inbuf, nblocks);
      return;
    }
#endif /*USE_ARM_CE*/
  else
    {
      unsigned char savebuf[BLOCKSIZE] ATTR_ALIGNED_16;
      rijndael_cryptfn_t decrypt_fn = ctx->decrypt_fn;

      check_decryption_preparation (ctx);

      if (ctx->prefetch_dec_fn)
        ctx->prefetch_dec_fn();

      for ( ;nblocks; nblocks-- )
        {
          /* INBUF is needed later and it may be identical to OUTBUF, so store
             the intermediate result to SAVEBUF.  */

          burn_depth = decrypt_fn (ctx, savebuf, inbuf);

          cipher_block_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOCKSIZE);
          inbuf += BLOCKSIZE;
          outbuf += BLOCKSIZE;
        }

      wipememory(savebuf, sizeof(savebuf));
    }

  if (burn_depth)
    _gcry_burn_stack (burn_depth + 4 * sizeof(void *));
}
