Line | Count | Source (jump to first uncovered line) |
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 <assert.h> |
40 | | #include <stdlib.h> |
41 | | #include <string.h> |
42 | | |
43 | | #include "cfb.h" |
44 | | |
45 | | #include "memxor.h" |
46 | | #include "nettle-internal.h" |
47 | | |
48 | | void |
49 | | cfb_encrypt(const void *ctx, nettle_cipher_func *f, |
50 | | size_t block_size, uint8_t *iv, |
51 | | size_t length, uint8_t *dst, |
52 | | const uint8_t *src) |
53 | 0 | { |
54 | 0 | uint8_t *p; |
55 | 0 | TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE); |
56 | |
|
57 | 0 | TMP_ALLOC(buffer, block_size); |
58 | |
|
59 | 0 | if (src != dst) |
60 | 0 | { |
61 | 0 | for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size) |
62 | 0 | { |
63 | 0 | f(ctx, block_size, dst, p); |
64 | 0 | memxor(dst, src, block_size); |
65 | 0 | } |
66 | 0 | } |
67 | 0 | else |
68 | 0 | { |
69 | 0 | for (p = iv; length >= block_size; p = dst, dst += block_size, src += block_size, length -= block_size) |
70 | 0 | { |
71 | 0 | f(ctx, block_size, buffer, p); |
72 | 0 | memxor(dst, buffer, block_size); |
73 | 0 | } |
74 | 0 | } |
75 | |
|
76 | 0 | if (p != iv) |
77 | 0 | memcpy(iv, p, block_size); |
78 | |
|
79 | 0 | if (length) |
80 | 0 | { |
81 | 0 | f(ctx, block_size, buffer, iv); |
82 | 0 | memxor3(dst, buffer, src, length); |
83 | | /* We do not care about updating IV here. This is the last call in |
84 | | * message sequence and one has to set IV afterwards anyway */ |
85 | 0 | } |
86 | 0 | } |
87 | | |
88 | | /* Don't allocate any more space than this on the stack */ |
89 | 0 | #define CFB_BUFFER_LIMIT 512 |
90 | | |
91 | | void |
92 | | cfb_decrypt(const void *ctx, nettle_cipher_func *f, |
93 | | size_t block_size, uint8_t *iv, |
94 | | size_t length, uint8_t *dst, |
95 | | const uint8_t *src) |
96 | 0 | { |
97 | 0 | if (src != dst) |
98 | 0 | { |
99 | 0 | size_t left = length % block_size; |
100 | |
|
101 | 0 | length -= left; |
102 | 0 | if (length > 0) |
103 | 0 | { |
104 | | /* Decrypt in ECB mode */ |
105 | 0 | f(ctx, block_size, dst, iv); |
106 | 0 | f(ctx, length - block_size, dst + block_size, src); |
107 | 0 | memcpy(iv, src + length - block_size, block_size); |
108 | 0 | memxor(dst, src, length); |
109 | 0 | } |
110 | |
|
111 | 0 | if (left > 0) |
112 | 0 | { |
113 | 0 | TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE); |
114 | 0 | TMP_ALLOC(buffer, block_size); |
115 | |
|
116 | 0 | f(ctx, block_size, buffer, iv); |
117 | 0 | memxor3(dst + length, src + length, buffer, left); |
118 | 0 | } |
119 | 0 | } |
120 | 0 | else |
121 | 0 | { |
122 | | /* For in-place CFB, we decrypt into a temporary buffer of size |
123 | | * at most CFB_BUFFER_LIMIT, and process that amount of data at |
124 | | * a time. */ |
125 | | |
126 | | /* NOTE: We assume that block_size <= CFB_BUFFER_LIMIT */ |
127 | |
|
128 | 0 | TMP_DECL(buffer, uint8_t, CFB_BUFFER_LIMIT); |
129 | 0 | TMP_DECL(initial_iv, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE); |
130 | |
|
131 | 0 | size_t buffer_size; |
132 | 0 | size_t left; |
133 | |
|
134 | 0 | buffer_size = CFB_BUFFER_LIMIT - (CFB_BUFFER_LIMIT % block_size); |
135 | |
|
136 | 0 | TMP_ALLOC(buffer, buffer_size); |
137 | 0 | TMP_ALLOC(initial_iv, block_size); |
138 | |
|
139 | 0 | left = length % block_size; |
140 | 0 | length -= left; |
141 | |
|
142 | 0 | while (length > 0) |
143 | 0 | { |
144 | 0 | size_t part = length > buffer_size ? buffer_size : length; |
145 | | |
146 | | /* length is greater that zero and is divided by block_size, so it is |
147 | | * not less than block_size. So does part */ |
148 | |
|
149 | 0 | f(ctx, block_size, buffer, iv); |
150 | 0 | f(ctx, part - block_size, buffer + block_size, dst); |
151 | 0 | memcpy(iv, dst + part - block_size, block_size); |
152 | 0 | memxor(dst, buffer, part); |
153 | |
|
154 | 0 | length -= part; |
155 | 0 | dst += part; |
156 | 0 | } |
157 | |
|
158 | 0 | if (left > 0) |
159 | 0 | { |
160 | 0 | f(ctx, block_size, buffer, iv); |
161 | 0 | memxor(dst, buffer, left); |
162 | 0 | } |
163 | 0 | } |
164 | 0 | } |
165 | | |
166 | | /* CFB-8 uses slight optimization: it encrypts or decrypts up to block_size |
167 | | * bytes and does memcpy/memxor afterwards */ |
168 | | void |
169 | | cfb8_encrypt(const void *ctx, nettle_cipher_func *f, |
170 | | size_t block_size, uint8_t *iv, |
171 | | size_t length, uint8_t *dst, |
172 | | const uint8_t *src) |
173 | 0 | { |
174 | 0 | TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2); |
175 | 0 | TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE); |
176 | 0 | TMP_ALLOC(buffer, block_size * 2); |
177 | 0 | TMP_ALLOC(outbuf, block_size); |
178 | 0 | uint8_t pos; |
179 | |
|
180 | 0 | memcpy(buffer, iv, block_size); |
181 | 0 | pos = 0; |
182 | 0 | while (length) |
183 | 0 | { |
184 | 0 | uint8_t t; |
185 | |
|
186 | 0 | if (pos == block_size) |
187 | 0 | { |
188 | 0 | memcpy(buffer, buffer + block_size, block_size); |
189 | 0 | pos = 0; |
190 | 0 | } |
191 | |
|
192 | 0 | f(ctx, block_size, outbuf, buffer + pos); |
193 | 0 | t = *(dst++) = *(src++) ^ outbuf[0]; |
194 | 0 | buffer[pos + block_size] = t; |
195 | 0 | length--; |
196 | 0 | pos ++; |
197 | 0 | } |
198 | 0 | memcpy(iv, buffer + pos, block_size); |
199 | 0 | } |
200 | | |
201 | | void |
202 | | cfb8_decrypt(const void *ctx, nettle_cipher_func *f, |
203 | | size_t block_size, uint8_t *iv, |
204 | | size_t length, uint8_t *dst, |
205 | | const uint8_t *src) |
206 | 0 | { |
207 | 0 | TMP_DECL(buffer, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2); |
208 | 0 | TMP_DECL(outbuf, uint8_t, NETTLE_MAX_CIPHER_BLOCK_SIZE * 2); |
209 | 0 | TMP_ALLOC(buffer, block_size * 2); |
210 | 0 | TMP_ALLOC(outbuf, block_size * 2); |
211 | 0 | uint8_t i = 0; |
212 | |
|
213 | 0 | memcpy(buffer, iv, block_size); |
214 | 0 | memcpy(buffer + block_size, src, |
215 | 0 | length < block_size ? length : block_size); |
216 | |
|
217 | 0 | while (length) |
218 | 0 | { |
219 | |
|
220 | 0 | for (i = 0; i < length && i < block_size; i++) |
221 | 0 | f(ctx, block_size, outbuf + i, buffer + i); |
222 | |
|
223 | 0 | memxor3(dst, src, outbuf, i); |
224 | |
|
225 | 0 | length -= i; |
226 | 0 | src += i; |
227 | 0 | dst += i; |
228 | |
|
229 | 0 | if (i == block_size) |
230 | 0 | { |
231 | 0 | memcpy(buffer, buffer + block_size, block_size); |
232 | 0 | memcpy(buffer + block_size, src, |
233 | 0 | length < block_size ? length : block_size); |
234 | 0 | } |
235 | 0 | } |
236 | |
|
237 | 0 | memcpy(iv, buffer + i, block_size); |
238 | 0 | } |