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 0 : _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 0 : gcry_cipher_encrypt_t enc_fn = c->spec->encrypt;
40 0 : size_t blocksize = c->spec->blocksize;
41 : unsigned int burn, nburn;
42 :
43 0 : if (outbuflen < inbuflen)
44 0 : return GPG_ERR_BUFFER_TOO_SHORT;
45 :
46 0 : if ( inbuflen <= c->unused )
47 : {
48 : /* Short enough to be encoded by the remaining XOR mask. */
49 : /* XOR the input with the IV */
50 0 : ivp = c->u_iv.iv + blocksize - c->unused;
51 0 : buf_xor(outbuf, ivp, inbuf, inbuflen);
52 0 : c->unused -= inbuflen;
53 0 : return 0;
54 : }
55 :
56 0 : burn = 0;
57 :
58 0 : if( c->unused )
59 : {
60 0 : inbuflen -= c->unused;
61 0 : ivp = c->u_iv.iv + blocksize - c->unused;
62 0 : buf_xor(outbuf, ivp, inbuf, c->unused);
63 0 : outbuf += c->unused;
64 0 : inbuf += c->unused;
65 0 : c->unused = 0;
66 : }
67 :
68 : /* Now we can process complete blocks. */
69 0 : while ( inbuflen >= blocksize )
70 : {
71 : /* Encrypt the IV (and save the current one). */
72 0 : nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
73 0 : burn = nburn > burn ? nburn : burn;
74 0 : buf_xor(outbuf, c->u_iv.iv, inbuf, blocksize);
75 0 : outbuf += blocksize;
76 0 : inbuf += blocksize;
77 0 : inbuflen -= blocksize;
78 : }
79 0 : if ( inbuflen )
80 : { /* process the remaining bytes */
81 0 : nburn = enc_fn ( &c->context.c, c->u_iv.iv, c->u_iv.iv );
82 0 : burn = nburn > burn ? nburn : burn;
83 0 : c->unused = blocksize;
84 0 : c->unused -= inbuflen;
85 0 : buf_xor(outbuf, c->u_iv.iv, inbuf, inbuflen);
86 0 : outbuf += inbuflen;
87 0 : inbuf += inbuflen;
88 0 : inbuflen = 0;
89 : }
90 :
91 0 : if (burn > 0)
92 0 : _gcry_burn_stack (burn + 4 * sizeof(void *));
93 :
94 0 : return 0;
95 : }
|