Blame cipher/cipher-ofb.c

Packit 0680ba
/* cipher-ofb.c  - Generic OFB mode implementation
Packit 0680ba
 * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
Packit 0680ba
 *               2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
Packit 0680ba
 *
Packit 0680ba
 * This file is part of Libgcrypt.
Packit 0680ba
 *
Packit 0680ba
 * Libgcrypt is free software; you can redistribute it and/or modify
Packit 0680ba
 * it under the terms of the GNU Lesser general Public License as
Packit 0680ba
 * published by the Free Software Foundation; either version 2.1 of
Packit 0680ba
 * the License, or (at your option) any later version.
Packit 0680ba
 *
Packit 0680ba
 * Libgcrypt is distributed in the hope that it will be useful,
Packit 0680ba
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 0680ba
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit 0680ba
 * GNU Lesser General Public License for more details.
Packit 0680ba
 *
Packit 0680ba
 * You should have received a copy of the GNU Lesser General Public
Packit 0680ba
 * License along with this program; if not, see <http://www.gnu.org/licenses/>.
Packit 0680ba
 */
Packit 0680ba
Packit 0680ba
#include <config.h>
Packit 0680ba
#include <stdio.h>
Packit 0680ba
#include <stdlib.h>
Packit 0680ba
#include <string.h>
Packit 0680ba
#include <errno.h>
Packit 0680ba
Packit 0680ba
#include "g10lib.h"
Packit 0680ba
#include "cipher.h"
Packit 0680ba
#include "ath.h"
Packit 0680ba
#include "bufhelp.h"
Packit 0680ba
#include "./cipher-internal.h"
Packit 0680ba
Packit 0680ba
Packit 0680ba
gcry_err_code_t
Packit 0680ba
_gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
Packit 0680ba
                          unsigned char *outbuf, size_t outbuflen,
Packit 0680ba
                          const unsigned char *inbuf, size_t inbuflen)
Packit 0680ba
{
Packit 0680ba
  unsigned char *ivp;
Packit 0680ba
  gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
Packit 0680ba
  size_t blocksize = c->spec->blocksize;
Packit 0680ba
  unsigned int burn, nburn;
Packit 0680ba
Packit 0680ba
  if (outbuflen < inbuflen)
Packit 0680ba
    return GPG_ERR_BUFFER_TOO_SHORT;
Packit 0680ba
Packit 0680ba
  if ( inbuflen <= c->unused )
Packit 0680ba
    {
Packit 0680ba
      /* Short enough to be encoded by the remaining XOR mask. */
Packit 0680ba
      /* XOR the input with the IV */
Packit 0680ba
      ivp = c->u_iv.iv + blocksize - c->unused;
Packit 0680ba
      buf_xor(outbuf, ivp, inbuf, inbuflen);
Packit 0680ba
      c->unused -= inbuflen;
Packit 0680ba
      return 0;
Packit 0680ba
    }
Packit 0680ba
Packit 0680ba
  burn = 0;
Packit 0680ba
Packit 0680ba
  if( c->unused )
Packit 0680ba
    {
Packit 0680ba
      inbuflen -= c->unused;
Packit 0680ba
      ivp = c->u_iv.iv + blocksize - c->unused;
Packit 0680ba
      buf_xor(outbuf, ivp, inbuf, c->unused);
Packit 0680ba
      outbuf += c->unused;
Packit 0680ba
      inbuf += c->unused;
Packit 0680ba
      c->unused = 0;
Packit 0680ba
    }
Packit 0680ba
Packit 0680ba
  /* Now we can process complete blocks. */
Packit 0680ba
  while ( inbuflen >= blocksize )
Packit 0680ba
    {
Packit 0680ba
      /* Encrypt the IV (and save the current one). */
Packit 0680ba
      nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
Packit 0680ba
      burn = nburn > burn ? nburn : burn;
Packit 0680ba
      buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
Packit 0680ba
      outbuf += blocksize;
Packit 0680ba
      inbuf += blocksize;
Packit 0680ba
      inbuflen -= blocksize;
Packit 0680ba
    }
Packit 0680ba
  if ( inbuflen )
Packit 0680ba
    { /* process the remaining bytes */
Packit 0680ba
      nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
Packit 0680ba
      burn = nburn > burn ? nburn : burn;
Packit 0680ba
      c->unused = blocksize;
Packit 0680ba
      c->unused -= inbuflen;
Packit 0680ba
      buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen);
Packit 0680ba
      outbuf += inbuflen;
Packit 0680ba
      inbuf += inbuflen;
Packit 0680ba
      inbuflen = 0;
Packit 0680ba
    }
Packit 0680ba
Packit 0680ba
  if (burn > 0)
Packit 0680ba
    _gcry_burn_stack (burn + 4 * sizeof(void *));
Packit 0680ba
Packit 0680ba
  return 0;
Packit 0680ba
}