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