1 /* cfb.c
2 
3    Cipher feedback mode.
4 
5    Copyright (C) 2015, 2017 Dmitry Eremin-Solenikov
6    Copyright (C) 2001, 2011 Niels Möller
7 
8    This file is part of GNU Nettle.
9 
10    GNU Nettle is free software: you can redistribute it and/or
11    modify it under the terms of either:
12 
13      * the GNU Lesser General Public License as published by the Free
14        Software Foundation; either version 3 of the License, or (at your
15        option) any later version.
16 
17    or
18 
19      * the GNU General Public License as published by the Free
20        Software Foundation; either version 2 of the License, or (at your
21        option) any later version.
22 
23    or both in parallel, as here.
24 
25    GNU Nettle is distributed in the hope that it will be useful,
26    but WITHOUT ANY WARRANTY; without even the implied warranty of
27    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
28    General Public License for more details.
29 
30    You should have received copies of the GNU General Public License and
31    the GNU Lesser General Public License along with this program.  If
32    not, see http://www.gnu.org/licenses/.
33 */
34 
35 #if HAVE_CONFIG_H
36 # include "config.h"
37 #endif
38 
39 #include <stdlib.h>
40 #include <string.h>
41 
42 #include "cfb.h"
43 
44 #include <nettle/memxor.h>
45 #include "nettle-alloca.h"
46 
47 void
cfb_encrypt(const void * ctx,nettle_cipher_func * f,size_t block_size,uint8_t * iv,size_t length,uint8_t * dst,const uint8_t * src)48 cfb_encrypt(const void *ctx, nettle_cipher_func *f,
49 	    size_t block_size, uint8_t *iv,
50 	    size_t length, uint8_t *dst,
51 	    const uint8_t *src)
52 {
53   uint8_t *p;
54   TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
55 
56   TMP_ALLOC(buffer, block_size);
57 
58   if (src != dst)
59     {
60       for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size)
61 	{
62 	  f(ctx, block_size, dst, p);
63 	  memxor(dst, src, block_size);
64 	}
65     }
66   else
67     {
68       for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size)
69 	{
70 	  f(ctx, block_size, buffer, p);
71 	  memxor(dst, buffer, block_size);
72 	}
73     }
74 
75   if (p != iv)
76     memcpy(iv, p, block_size);
77 
78   if (length)
79     {
80       f(ctx, block_size, buffer, iv);
81       memxor3(dst, buffer, src, length);
82       /* We do not care about updating IV here. This is the last call in
83        * message sequence and one has to set IV afterwards anyway */
84     }
85 }
86 
87 /* Don't allocate any more space than this on the stack */
88 #define CFB_BUFFER_LIMIT 512
89 
90 void
cfb_decrypt(const void * ctx,nettle_cipher_func * f,size_t block_size,uint8_t * iv,size_t length,uint8_t * dst,const uint8_t * src)91 cfb_decrypt(const void *ctx, nettle_cipher_func *f,
92 	    size_t block_size, uint8_t *iv,
93 	    size_t length, uint8_t *dst,
94 	    const uint8_t *src)
95 {
96   if (src != dst)
97     {
98       size_t left = length % block_size;
99 
100       length -= left;
101       if (length > 0)
102 	{
103 	  /* Decrypt in ECB mode */
104 	  f(ctx, block_size, dst, iv);
105 	  f(ctx, length - block_size, dst + block_size, src);
106 	  memcpy(iv, src + length - block_size, block_size);
107 	  memxor(dst, src, length);
108 	}
109 
110       if (left > 0)
111 	{
112 	  TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
113 	  TMP_ALLOC(buffer, block_size);
114 
115 	  f(ctx, block_size, buffer, iv);
116 	  memxor3(dst + length, src + length, buffer, left);
117 	}
118     }
119   else
120     {
121       /* For in-place CFB, we decrypt into a temporary buffer of size
122        * at most CFB_BUFFER_LIMIT, and process that amount of data at
123        * a time. */
124 
125       /* NOTE: We assume that block_size <= CFB_BUFFER_LIMIT */
126 
127       TMP_DECL(buffer, uint8_t, CFB_BUFFER_LIMIT);
128       TMP_DECL(initial_iv, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
129 
130       size_t buffer_size;
131       size_t left;
132 
133       buffer_size = CFB_BUFFER_LIMIT - (CFB_BUFFER_LIMIT % block_size);
134 
135       TMP_ALLOC(buffer, buffer_size);
136       TMP_ALLOC(initial_iv, block_size);
137 
138       left = length % block_size;
139       length -= left;
140 
141       while (length > 0)
142 	{
143 	  size_t part = length > buffer_size ? buffer_size : length;
144 
145 	  /* length is greater that zero and is divided by block_size, so it is
146 	   * not less than block_size. So does part */
147 
148 	  f(ctx, block_size, buffer, iv);
149 	  f(ctx, part - block_size, buffer + block_size, dst);
150 	  memcpy(iv, dst + part - block_size, block_size);
151 	  memxor(dst, buffer, part);
152 
153 	  length -= part;
154 	  dst += part;
155 	}
156 
157       if (left > 0)
158 	{
159 	  f(ctx, block_size, buffer, iv);
160 	  memxor(dst, buffer, left);
161 	}
162     }
163 }
164 
165 /* CFB-8 uses slight optimization: it encrypts or decrypts up to block_size
166  * bytes and does memcpy/memxor afterwards */
167 void
cfb8_encrypt(const void * ctx,nettle_cipher_func * f,size_t block_size,uint8_t * iv,size_t length,uint8_t * dst,const uint8_t * src)168 cfb8_encrypt(const void *ctx, nettle_cipher_func *f,
169 	     size_t block_size, uint8_t *iv,
170 	     size_t length, uint8_t *dst,
171 	     const uint8_t *src)
172 {
173   TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
174   TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
175   TMP_ALLOC(buffer, block_size * 2);
176   TMP_ALLOC(outbuf, block_size);
177   uint8_t pos;
178 
179   memcpy(buffer, iv, block_size);
180   pos = 0;
181   while (length)
182     {
183       uint8_t t;
184 
185       if (pos == block_size)
186 	{
187 	  memcpy(buffer, buffer + block_size, block_size);
188 	  pos = 0;
189 	}
190 
191       f(ctx, block_size, outbuf, buffer + pos);
192       t = *(dst++) = *(src++) ^ outbuf[0];
193       buffer[pos + block_size] = t;
194       length--;
195       pos ++;
196     }
197   memcpy(iv, buffer + pos, block_size);
198 }
199 
200 void
cfb8_decrypt(const void * ctx,nettle_cipher_func * f,size_t block_size,uint8_t * iv,size_t length,uint8_t * dst,const uint8_t * src)201 cfb8_decrypt(const void *ctx, nettle_cipher_func *f,
202 	     size_t block_size, uint8_t *iv,
203 	     size_t length, uint8_t *dst,
204 	     const uint8_t *src)
205 {
206   TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
207   TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
208   TMP_ALLOC(buffer, block_size * 2);
209   TMP_ALLOC(outbuf, block_size * 2);
210   uint8_t i = 0;
211 
212   memcpy(buffer, iv, block_size);
213   memcpy(buffer + block_size, src,
214 	 length < block_size ? length : block_size);
215 
216   while (length)
217     {
218 
219       for (i = 0; i < length && i < block_size; i++)
220 	f(ctx, block_size, outbuf + i, buffer + i);
221 
222       memxor3(dst, src, outbuf, i);
223 
224       length -= i;
225       src += i;
226       dst += i;
227 
228       if (i == block_size)
229 	{
230 	  memcpy(buffer, buffer + block_size, block_size);
231 	  memcpy(buffer + block_size, src,
232 		 length < block_size ? length : block_size);
233 	}
234     }
235 
236   memcpy(iv, buffer + i, block_size);
237 }
238