Beispiel #1
0
/* Bulk decryption of complete blocks in CBC mode.  This function is only
   intended for the bulk encryption feature of cipher.c. */
void
_gcry_blowfish_cbc_dec(void *context, unsigned char *iv, void *outbuf_arg,
		       const void *inbuf_arg, size_t nblocks)
{
  BLOWFISH_context *ctx = context;
  unsigned char *outbuf = outbuf_arg;
  const unsigned char *inbuf = inbuf_arg;
  unsigned char savebuf[BLOWFISH_BLOCKSIZE];
  int burn_stack_depth = (64) + 2 * BLOWFISH_BLOCKSIZE;

#ifdef USE_AMD64_ASM
  {
    if (nblocks >= 4)
      burn_stack_depth += 5 * sizeof(void*);

    /* Process data in 4 block chunks. */
    while (nblocks >= 4)
      {
        _gcry_blowfish_amd64_cbc_dec(ctx, outbuf, inbuf, iv);

        nblocks -= 4;
        outbuf += 4 * BLOWFISH_BLOCKSIZE;
        inbuf  += 4 * BLOWFISH_BLOCKSIZE;
      }

    /* Use generic code to handle smaller chunks... */
  }
#elif defined(USE_ARM_ASM)
  {
    /* Process data in 2 block chunks. */
    while (nblocks >= 2)
      {
        _gcry_blowfish_arm_cbc_dec(ctx, outbuf, inbuf, iv);

        nblocks -= 2;
        outbuf += 2 * BLOWFISH_BLOCKSIZE;
        inbuf  += 2 * BLOWFISH_BLOCKSIZE;
      }

    /* Use generic code to handle smaller chunks... */
  }
#endif

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

      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, BLOWFISH_BLOCKSIZE);
      inbuf += BLOWFISH_BLOCKSIZE;
      outbuf += BLOWFISH_BLOCKSIZE;
    }

  wipememory(savebuf, sizeof(savebuf));
  _gcry_burn_stack(burn_stack_depth);
}
Beispiel #2
0
gcry_err_code_t
_gcry_cipher_cbc_decrypt (gcry_cipher_hd_t c,
                          unsigned char *outbuf, size_t outbuflen,
                          const unsigned char *inbuf, size_t inbuflen)
{
  size_t n;
  int i;
  size_t blocksize = c->spec->blocksize;
  gcry_cipher_decrypt_t dec_fn = c->spec->decrypt;
  size_t nblocks = inbuflen / blocksize;
  unsigned int burn, nburn;

  /* Tell compiler that we require a cipher with a 64bit or 128 bit block
   * length, to allow better optimization of this function.  */
  if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
    return GPG_ERR_INV_LENGTH;

  if (outbuflen < inbuflen)
    return GPG_ERR_BUFFER_TOO_SHORT;

  if ((inbuflen % blocksize)
      && !(inbuflen > blocksize
           && (c->flags & GCRY_CIPHER_CBC_CTS)))
    return GPG_ERR_INV_LENGTH;

  burn = 0;

  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
    {
      nblocks--;
      if ((inbuflen % blocksize) == 0)
	nblocks--;
      buf_cpy (c->lastiv, c->u_iv.iv, blocksize);
    }

  if (c->bulk.cbc_dec)
    {
      c->bulk.cbc_dec (&c->context.c, c->u_iv.iv, outbuf, inbuf, nblocks);
      inbuf  += nblocks * blocksize;
      outbuf += nblocks * blocksize;
    }
  else
    {
      for (n=0; n < nblocks; n++ )
        {
          /* 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_n_copy_2(outbuf, c->lastiv, c->u_iv.iv, inbuf, blocksize);
          inbuf  += blocksize;
          outbuf += blocksize;
        }
    }

  if ((c->flags & GCRY_CIPHER_CBC_CTS) && inbuflen > blocksize)
    {
      size_t restbytes;

      if ((inbuflen % blocksize) == 0)
        restbytes = blocksize;
      else
        restbytes = inbuflen % blocksize;

      buf_cpy (c->lastiv, c->u_iv.iv, blocksize );         /* Save Cn-2. */
      buf_cpy (c->u_iv.iv, inbuf + blocksize, restbytes ); /* Save Cn. */

      nburn = dec_fn ( &c->context.c, outbuf, inbuf );
      burn = nburn > burn ? nburn : burn;
      buf_xor(outbuf, outbuf, c->u_iv.iv, restbytes);

      buf_cpy (outbuf + blocksize, outbuf, restbytes);
      for(i=restbytes; i < blocksize; i++)
        c->u_iv.iv[i] = outbuf[i];
      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? */
    }

  if (burn > 0)
    _gcry_burn_stack (burn + 4 * sizeof(void *));

  return 0;
}
Beispiel #3
0
/* Bulk decryption of complete blocks in CBC mode.  This function is only
   intended for the bulk encryption feature of cipher.c. */
void
_gcry_camellia_cbc_dec(void *context, unsigned char *iv,
                       void *outbuf_arg, const void *inbuf_arg,
                       size_t nblocks)
{
  CAMELLIA_context *ctx = context;
  unsigned char *outbuf = outbuf_arg;
  const unsigned char *inbuf = inbuf_arg;
  unsigned char savebuf[CAMELLIA_BLOCK_SIZE];
  int burn_stack_depth = CAMELLIA_decrypt_stack_burn_size;

#ifdef USE_AESNI_AVX2
  if (ctx->use_aesni_avx2)
    {
      int did_use_aesni_avx2 = 0;

      /* Process data in 32 block chunks. */
      while (nblocks >= 32)
        {
          _gcry_camellia_aesni_avx2_cbc_dec(ctx, outbuf, inbuf, iv);

          nblocks -= 32;
          outbuf += 32 * CAMELLIA_BLOCK_SIZE;
          inbuf  += 32 * CAMELLIA_BLOCK_SIZE;
          did_use_aesni_avx2 = 1;
        }

      if (did_use_aesni_avx2)
        {
          int avx2_burn_stack_depth = 32 * CAMELLIA_BLOCK_SIZE + 16 +
                                        2 * sizeof(void *) + ASM_EXTRA_STACK;;

          if (burn_stack_depth < avx2_burn_stack_depth)
            burn_stack_depth = avx2_burn_stack_depth;
        }

      /* Use generic code to handle smaller chunks... */
    }
#endif

#ifdef USE_AESNI_AVX
  if (ctx->use_aesni_avx)
    {
      int did_use_aesni_avx = 0;

      /* Process data in 16 block chunks. */
      while (nblocks >= 16)
        {
          _gcry_camellia_aesni_avx_cbc_dec(ctx, outbuf, inbuf, iv);

          nblocks -= 16;
          outbuf += 16 * CAMELLIA_BLOCK_SIZE;
          inbuf  += 16 * CAMELLIA_BLOCK_SIZE;
          did_use_aesni_avx = 1;
        }

      if (did_use_aesni_avx)
        {
          int avx_burn_stack_depth = 16 * CAMELLIA_BLOCK_SIZE +
                                       2 * sizeof(void *) + ASM_EXTRA_STACK;

          if (burn_stack_depth < avx_burn_stack_depth)
            burn_stack_depth = avx_burn_stack_depth;
        }

      /* Use generic code to handle smaller chunks... */
    }
#endif

  for ( ;nblocks; nblocks-- )
    {
      /* 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);

      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, CAMELLIA_BLOCK_SIZE);
      inbuf += CAMELLIA_BLOCK_SIZE;
      outbuf += CAMELLIA_BLOCK_SIZE;
    }

  wipememory(savebuf, sizeof(savebuf));
  _gcry_burn_stack(burn_stack_depth);
}
Beispiel #4
0
/* Bulk decryption of complete blocks in CBC mode.  This function is only
   intended for the bulk encryption feature of cipher.c. */
void
_gcry_serpent_cbc_dec(void *context, unsigned char *iv,
                      void *outbuf_arg, const void *inbuf_arg,
                      size_t nblocks)
{
  serpent_context_t *ctx = context;
  unsigned char *outbuf = outbuf_arg;
  const unsigned char *inbuf = inbuf_arg;
  unsigned char savebuf[sizeof(serpent_block_t)];
  int burn_stack_depth = 2 * sizeof (serpent_block_t);

#ifdef USE_AVX2
  if (ctx->use_avx2)
    {
      int did_use_avx2 = 0;

      /* Process data in 16 block chunks. */
      while (nblocks >= 16)
        {
          _gcry_serpent_avx2_cbc_dec(ctx, outbuf, inbuf, iv);

          nblocks -= 16;
          outbuf += 16 * sizeof(serpent_block_t);
          inbuf  += 16 * sizeof(serpent_block_t);
          did_use_avx2 = 1;
        }

      if (did_use_avx2)
        {
          /* serpent-avx2 assembly code does not use stack */
          if (nblocks == 0)
            burn_stack_depth = 0;
        }

      /* Use generic/sse2 code to handle smaller chunks... */
    }
#endif

#ifdef USE_SSE2
  {
    int did_use_sse2 = 0;

    /* Process data in 8 block chunks. */
    while (nblocks >= 8)
      {
        _gcry_serpent_sse2_cbc_dec(ctx, outbuf, inbuf, iv);

        nblocks -= 8;
        outbuf += 8 * sizeof(serpent_block_t);
        inbuf  += 8 * sizeof(serpent_block_t);
        did_use_sse2 = 1;
      }

    if (did_use_sse2)
      {
        /* serpent-sse2 assembly code does not use stack */
        if (nblocks == 0)
          burn_stack_depth = 0;
      }

    /* Use generic code to handle smaller chunks... */
  }
#endif

#ifdef USE_NEON
  if (ctx->use_neon)
    {
      int did_use_neon = 0;

      /* Process data in 8 block chunks. */
      while (nblocks >= 8)
        {
          _gcry_serpent_neon_cbc_dec(ctx, outbuf, inbuf, iv);

          nblocks -= 8;
          outbuf += 8 * sizeof(serpent_block_t);
          inbuf  += 8 * sizeof(serpent_block_t);
          did_use_neon = 1;
        }

      if (did_use_neon)
        {
          /* serpent-neon assembly code does not use stack */
          if (nblocks == 0)
            burn_stack_depth = 0;
        }

      /* Use generic code to handle smaller chunks... */
    }
#endif

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

      buf_xor_n_copy_2(outbuf, savebuf, iv, inbuf, sizeof(serpent_block_t));
      inbuf += sizeof(serpent_block_t);
      outbuf += sizeof(serpent_block_t);
    }

  wipememory(savebuf, sizeof(savebuf));
  _gcry_burn_stack(burn_stack_depth);
}