Line data Source code
1 : /* cipher-ofb.c - Generic OFB mode implementation
2 : * Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003
3 : * 2005, 2007, 2008, 2009, 2011 Free Software Foundation, Inc.
4 : *
5 : * This file is part of Libgcrypt.
6 : *
7 : * Libgcrypt is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU Lesser general Public License as
9 : * published by the Free Software Foundation; either version 2.1 of
10 : * the License, or (at your option) any later version.
11 : *
12 : * Libgcrypt is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU Lesser General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU Lesser General Public
18 : * License along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : #include <config.h>
22 : #include <stdio.h>
23 : #include <stdlib.h>
24 : #include <string.h>
25 : #include <errno.h>
26 :
27 : #include "g10lib.h"
28 : #include "cipher.h"
29 : #include "bufhelp.h"
30 : #include "./cipher-internal.h"
31 :
32 :
33 : gcry_err_code_t
34 123734 : _gcry_cipher_ofb_encrypt (gcry_cipher_hd_t c,
35 : unsigned char *outbuf, size_t outbuflen,
36 : const unsigned char *inbuf, size_t inbuflen)
37 : {
38 : unsigned char *ivp;
39 123734 : gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
40 123734 : size_t blocksize = c->spec->blocksize;
41 : unsigned int burn, nburn;
42 :
43 : /* Tell compiler that we require a cipher with a 64bit or 128 bit block
44 : * length, to allow better optimization of this function. */
45 123734 : if (blocksize > 16 || blocksize < 8 || blocksize & (8 - 1))
46 0 : return GPG_ERR_INV_LENGTH;
47 :
48 123734 : if (outbuflen < inbuflen)
49 0 : return GPG_ERR_BUFFER_TOO_SHORT;
50 :
51 123734 : if ( inbuflen <= c->unused )
52 : {
53 : /* Short enough to be encoded by the remaining XOR mask. */
54 : /* XOR the input with the IV */
55 9552 : ivp = c->u_iv.iv + blocksize - c->unused;
56 9552 : buf_xor(outbuf, ivp, inbuf, inbuflen);
57 9552 : c->unused -= inbuflen;
58 9552 : return 0;
59 : }
60 :
61 114182 : burn = 0;
62 :
63 114182 : if( c->unused )
64 : {
65 17024 : inbuflen -= c->unused;
66 17024 : ivp = c->u_iv.iv + blocksize - c->unused;
67 17024 : buf_xor(outbuf, ivp, inbuf, c->unused);
68 17024 : outbuf += c->unused;
69 17024 : inbuf += c->unused;
70 17024 : c->unused = 0;
71 : }
72 :
73 : /* Now we can process complete blocks. */
74 11846008 : while ( inbuflen >= blocksize )
75 : {
76 : /* Encrypt the IV (and save the current one). */
77 11617644 : nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
78 11617644 : burn = nburn > burn ? nburn : burn;
79 11617644 : buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
80 11617644 : outbuf += blocksize;
81 11617644 : inbuf += blocksize;
82 11617644 : inbuflen -= blocksize;
83 : }
84 114182 : if ( inbuflen )
85 : { /* process the remaining bytes */
86 19504 : nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
87 19504 : burn = nburn > burn ? nburn : burn;
88 19504 : c->unused = blocksize;
89 19504 : c->unused -= inbuflen;
90 19504 : buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen);
91 19504 : outbuf += inbuflen;
92 19504 : inbuf += inbuflen;
93 19504 : inbuflen = 0;
94 : }
95 :
96 114182 : if (burn > 0)
97 87642 : _gcry_burn_stack (burn + 4 * sizeof(void *));
98 :
99 114182 : return 0;
100 : }
|