Line data Source code
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
48 56 : 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 56 : uint8_t *p;
54 56 : TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
55 :
56 56 : TMP_ALLOC(buffer, block_size);
57 :
58 56 : if (src != dst)
59 : {
60 85 : for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size)
61 : {
62 60 : f(ctx, block_size, dst, p);
63 60 : memxor(dst, src, block_size);
64 : }
65 : }
66 : else
67 : {
68 493 : for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size)
69 : {
70 462 : f(ctx, block_size, buffer, p);
71 462 : memxor(dst, buffer, block_size);
72 : }
73 : }
74 :
75 56 : if (p != iv)
76 46 : memcpy(iv, p, block_size);
77 :
78 56 : if (length)
79 : {
80 36 : f(ctx, block_size, buffer, iv);
81 36 : 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 56 : }
86 :
87 : /* Don't allocate any more space than this on the stack */
88 : #define CFB_BUFFER_LIMIT 512
89 :
90 : void
91 66 : 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 66 : if (src != dst)
97 : {
98 25 : size_t left = length % block_size;
99 :
100 25 : length -= left;
101 25 : if (length > 0)
102 : {
103 : /* Decrypt in ECB mode */
104 20 : f(ctx, block_size, dst, iv);
105 20 : f(ctx, length - block_size, dst + block_size, src);
106 20 : memcpy(iv, src + length - block_size, block_size);
107 20 : memxor(dst, src, length);
108 : }
109 :
110 25 : if (left > 0)
111 : {
112 15 : TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
113 15 : TMP_ALLOC(buffer, block_size);
114 :
115 15 : f(ctx, block_size, buffer, iv);
116 15 : 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 41 : TMP_DECL(buffer, uint8_t, CFB_BUFFER_LIMIT);
128 41 : TMP_DECL(initial_iv, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
129 :
130 41 : size_t buffer_size;
131 41 : size_t left;
132 :
133 41 : buffer_size = CFB_BUFFER_LIMIT - (CFB_BUFFER_LIMIT % block_size);
134 :
135 41 : TMP_ALLOC(buffer, buffer_size);
136 41 : TMP_ALLOC(initial_iv, block_size);
137 :
138 41 : left = length % block_size;
139 41 : length -= left;
140 :
141 85 : while (length > 0)
142 : {
143 44 : 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 44 : f(ctx, block_size, buffer, iv);
149 44 : f(ctx, part - block_size, buffer + block_size, dst);
150 44 : memcpy(iv, dst + part - block_size, block_size);
151 44 : memxor(dst, buffer, part);
152 :
153 44 : length -= part;
154 44 : dst += part;
155 : }
156 :
157 41 : if (left > 0)
158 : {
159 27 : f(ctx, block_size, buffer, iv);
160 27 : memxor(dst, buffer, left);
161 : }
162 : }
163 66 : }
164 :
165 : /* CFB-8 uses slight optimization: it encrypts or decrypts up to block_size
166 : * bytes and does memcpy/memxor afterwards */
167 : void
168 1080 : 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 1080 : TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
174 1080 : TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE);
175 1080 : TMP_ALLOC(buffer, block_size * 2);
176 1080 : TMP_ALLOC(outbuf, block_size);
177 1080 : uint8_t pos;
178 :
179 1080 : memcpy(buffer, iv, block_size);
180 1080 : pos = 0;
181 6480 : while (length)
182 : {
183 5400 : uint8_t t;
184 :
185 5400 : if (pos == block_size)
186 : {
187 60 : memcpy(buffer, buffer + block_size, block_size);
188 60 : pos = 0;
189 : }
190 :
191 5400 : f(ctx, block_size, outbuf, buffer + pos);
192 5400 : t = *(dst++) = *(src++) ^ outbuf[0];
193 5400 : buffer[pos + block_size] = t;
194 5400 : length--;
195 5400 : pos ++;
196 : }
197 1080 : memcpy(iv, buffer + pos, block_size);
198 1080 : }
199 :
200 : void
201 900 : 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 900 : TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
207 900 : TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2);
208 900 : TMP_ALLOC(buffer, block_size * 2);
209 900 : TMP_ALLOC(outbuf, block_size * 2);
210 900 : uint8_t i = 0;
211 :
212 900 : memcpy(buffer, iv, block_size);
213 900 : memcpy(buffer + block_size, src,
214 : length < block_size ? length : block_size);
215 :
216 1860 : while (length)
217 : {
218 :
219 5655 : for (i = 0; i < length && i < block_size; i++)
220 4695 : f(ctx, block_size, outbuf + i, buffer + i);
221 :
222 960 : memxor3(dst, src, outbuf, i);
223 :
224 960 : length -= i;
225 960 : src += i;
226 960 : dst += i;
227 :
228 960 : if (i == block_size)
229 : {
230 75 : memcpy(buffer, buffer + block_size, block_size);
231 75 : memcpy(buffer + block_size, src,
232 : length < block_size ? length : block_size);
233 : }
234 : }
235 :
236 900 : memcpy(iv, buffer + i, block_size);
237 900 : }
|