"Fossies" - the Fresh Open Source Software Archive 
Member "cryptsetup-2.4.3/lib/crypto_backend/crypto_storage.c" (13 Jan 2022, 8140 Bytes) of package /linux/misc/cryptsetup-2.4.3.tar.xz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "crypto_storage.c" see the
Fossies "Dox" file reference documentation and the last
Fossies "Diffs" side-by-side code changes report:
2.3.6_vs_2.4.0.
1 /*
2 * Generic wrapper for storage encryption modes and Initial Vectors
3 * (reimplementation of some functions from Linux dm-crypt kernel)
4 *
5 * Copyright (C) 2014-2021 Milan Broz
6 *
7 * This file is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This file 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 GNU
15 * 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 file; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22 #include <stdlib.h>
23 #include <errno.h>
24 #include <strings.h>
25 #include "bitops.h"
26 #include "crypto_backend.h"
27
28 #define SECTOR_SHIFT 9
29
30 /*
31 * Internal IV helper
32 * IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
33 */
34 struct crypt_sector_iv {
35 enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI, IV_PLAIN64BE, IV_EBOIV } type;
36 int iv_size;
37 char *iv;
38 struct crypt_cipher *cipher;
39 int shift;
40 };
41
42 /* Block encryption storage context */
43 struct crypt_storage {
44 size_t sector_size;
45 unsigned iv_shift;
46 struct crypt_cipher *cipher;
47 struct crypt_sector_iv cipher_iv;
48 };
49
50 static int int_log2(unsigned int x)
51 {
52 int r = 0;
53 for (x >>= 1; x > 0; x >>= 1)
54 r++;
55 return r;
56 }
57
58 static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
59 const char *cipher_name, const char *mode_name,
60 const char *iv_name, const void *key, size_t key_length,
61 size_t sector_size)
62 {
63 int r;
64
65 memset(ctx, 0, sizeof(*ctx));
66
67 ctx->iv_size = crypt_cipher_ivsize(cipher_name, mode_name);
68 if (ctx->iv_size < 0 || (strcmp(mode_name, "ecb") && ctx->iv_size < 8))
69 return -ENOENT;
70
71 if (!strcmp(cipher_name, "cipher_null") ||
72 !strcmp(mode_name, "ecb")) {
73 if (iv_name)
74 return -EINVAL;
75 ctx->type = IV_NONE;
76 ctx->iv_size = 0;
77 return 0;
78 } else if (!iv_name) {
79 return -EINVAL;
80 } else if (!strcasecmp(iv_name, "null")) {
81 ctx->type = IV_NULL;
82 } else if (!strcasecmp(iv_name, "plain64")) {
83 ctx->type = IV_PLAIN64;
84 } else if (!strcasecmp(iv_name, "plain64be")) {
85 ctx->type = IV_PLAIN64BE;
86 } else if (!strcasecmp(iv_name, "plain")) {
87 ctx->type = IV_PLAIN;
88 } else if (!strncasecmp(iv_name, "essiv:", 6)) {
89 struct crypt_hash *h = NULL;
90 char *hash_name = strchr(iv_name, ':');
91 int hash_size;
92 char tmp[256];
93
94 if (!hash_name)
95 return -EINVAL;
96
97 hash_size = crypt_hash_size(++hash_name);
98 if (hash_size < 0)
99 return -ENOENT;
100
101 if ((unsigned)hash_size > sizeof(tmp))
102 return -EINVAL;
103
104 if (crypt_hash_init(&h, hash_name))
105 return -EINVAL;
106
107 r = crypt_hash_write(h, key, key_length);
108 if (r) {
109 crypt_hash_destroy(h);
110 return r;
111 }
112
113 r = crypt_hash_final(h, tmp, hash_size);
114 crypt_hash_destroy(h);
115 if (r) {
116 crypt_backend_memzero(tmp, sizeof(tmp));
117 return r;
118 }
119
120 r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
121 tmp, hash_size);
122 crypt_backend_memzero(tmp, sizeof(tmp));
123 if (r)
124 return r;
125
126 ctx->type = IV_ESSIV;
127 } else if (!strncasecmp(iv_name, "benbi", 5)) {
128 int log = int_log2(ctx->iv_size);
129 if (log > SECTOR_SHIFT)
130 return -EINVAL;
131
132 ctx->type = IV_BENBI;
133 ctx->shift = SECTOR_SHIFT - log;
134 } else if (!strncasecmp(iv_name, "eboiv", 5)) {
135 r = crypt_cipher_init(&ctx->cipher, cipher_name, "ecb",
136 key, key_length);
137 if (r)
138 return r;
139
140 ctx->type = IV_EBOIV;
141 ctx->shift = int_log2(sector_size);
142 } else
143 return -ENOENT;
144
145 ctx->iv = malloc(ctx->iv_size);
146 if (!ctx->iv)
147 return -ENOMEM;
148
149 return 0;
150 }
151
152 static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
153 {
154 uint64_t val;
155
156 switch (ctx->type) {
157 case IV_NONE:
158 break;
159 case IV_NULL:
160 memset(ctx->iv, 0, ctx->iv_size);
161 break;
162 case IV_PLAIN:
163 memset(ctx->iv, 0, ctx->iv_size);
164 *(uint32_t *)ctx->iv = cpu_to_le32(sector & 0xffffffff);
165 break;
166 case IV_PLAIN64:
167 memset(ctx->iv, 0, ctx->iv_size);
168 *(uint64_t *)ctx->iv = cpu_to_le64(sector);
169 break;
170 case IV_PLAIN64BE:
171 memset(ctx->iv, 0, ctx->iv_size);
172 *(uint64_t *)&ctx->iv[ctx->iv_size - sizeof(uint64_t)] = cpu_to_be64(sector);
173 break;
174 case IV_ESSIV:
175 memset(ctx->iv, 0, ctx->iv_size);
176 *(uint64_t *)ctx->iv = cpu_to_le64(sector);
177 return crypt_cipher_encrypt(ctx->cipher,
178 ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
179 break;
180 case IV_BENBI:
181 memset(ctx->iv, 0, ctx->iv_size);
182 val = cpu_to_be64((sector << ctx->shift) + 1);
183 memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
184 break;
185 case IV_EBOIV:
186 memset(ctx->iv, 0, ctx->iv_size);
187 *(uint64_t *)ctx->iv = cpu_to_le64(sector << ctx->shift);
188 return crypt_cipher_encrypt(ctx->cipher,
189 ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
190 break;
191 default:
192 return -EINVAL;
193 }
194
195 return 0;
196 }
197
198 static void crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
199 {
200 if (ctx->type == IV_ESSIV || ctx->type == IV_EBOIV)
201 crypt_cipher_destroy(ctx->cipher);
202
203 if (ctx->iv) {
204 memset(ctx->iv, 0, ctx->iv_size);
205 free(ctx->iv);
206 }
207
208 memset(ctx, 0, sizeof(*ctx));
209 }
210
211 /* Block encryption storage wrappers */
212
213 int crypt_storage_init(struct crypt_storage **ctx,
214 size_t sector_size,
215 const char *cipher,
216 const char *cipher_mode,
217 const void *key, size_t key_length,
218 bool large_iv)
219 {
220 struct crypt_storage *s;
221 char mode_name[64];
222 char *cipher_iv = NULL;
223 int r = -EIO;
224
225 if (sector_size < (1 << SECTOR_SHIFT) ||
226 sector_size > (1 << (SECTOR_SHIFT + 3)) ||
227 sector_size & (sector_size - 1))
228 return -EINVAL;
229
230 s = malloc(sizeof(*s));
231 if (!s)
232 return -ENOMEM;
233 memset(s, 0, sizeof(*s));
234
235 /* Remove IV if present */
236 strncpy(mode_name, cipher_mode, sizeof(mode_name));
237 mode_name[sizeof(mode_name) - 1] = 0;
238 cipher_iv = strchr(mode_name, '-');
239 if (cipher_iv) {
240 *cipher_iv = '\0';
241 cipher_iv++;
242 }
243
244 r = crypt_cipher_init(&s->cipher, cipher, mode_name, key, key_length);
245 if (r) {
246 crypt_storage_destroy(s);
247 return r;
248 }
249
250 r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length, sector_size);
251 if (r) {
252 crypt_storage_destroy(s);
253 return r;
254 }
255
256 s->sector_size = sector_size;
257 s->iv_shift = large_iv ? int_log2(sector_size) - SECTOR_SHIFT : 0;
258
259 *ctx = s;
260 return 0;
261 }
262
263 int crypt_storage_decrypt(struct crypt_storage *ctx,
264 uint64_t iv_offset,
265 uint64_t length, char *buffer)
266 {
267 uint64_t i;
268 int r = 0;
269
270 if (length & (ctx->sector_size - 1))
271 return -EINVAL;
272
273 if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
274 return -EINVAL;
275
276 for (i = 0; i < length; i += ctx->sector_size) {
277 r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
278 if (r)
279 break;
280 r = crypt_cipher_decrypt(ctx->cipher,
281 &buffer[i],
282 &buffer[i],
283 ctx->sector_size,
284 ctx->cipher_iv.iv,
285 ctx->cipher_iv.iv_size);
286 if (r)
287 break;
288 }
289
290 return r;
291 }
292
293 int crypt_storage_encrypt(struct crypt_storage *ctx,
294 uint64_t iv_offset,
295 uint64_t length, char *buffer)
296 {
297 uint64_t i;
298 int r = 0;
299
300 if (length & (ctx->sector_size - 1))
301 return -EINVAL;
302
303 if (iv_offset & ((ctx->sector_size >> SECTOR_SHIFT) - 1))
304 return -EINVAL;
305
306 for (i = 0; i < length; i += ctx->sector_size) {
307 r = crypt_sector_iv_generate(&ctx->cipher_iv, (iv_offset + (i >> SECTOR_SHIFT)) >> ctx->iv_shift);
308 if (r)
309 break;
310 r = crypt_cipher_encrypt(ctx->cipher,
311 &buffer[i],
312 &buffer[i],
313 ctx->sector_size,
314 ctx->cipher_iv.iv,
315 ctx->cipher_iv.iv_size);
316 if (r)
317 break;
318 }
319
320 return r;
321 }
322
323 void crypt_storage_destroy(struct crypt_storage *ctx)
324 {
325 if (!ctx)
326 return;
327
328 crypt_sector_iv_destroy(&ctx->cipher_iv);
329
330 if (ctx->cipher)
331 crypt_cipher_destroy(ctx->cipher);
332
333 memset(ctx, 0, sizeof(*ctx));
334 free(ctx);
335 }
336
337 bool crypt_storage_kernel_only(struct crypt_storage *ctx)
338 {
339 return crypt_cipher_kernel_only(ctx->cipher);
340 }