2 * Generic wrapper for storage encryption modes and Initial Vectors
3 * (reimplementation of some functions from Linux dm-crypt kernel)
5 * Copyright (C) 2014, Milan Broz
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.
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.
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.
25 #include "crypto_backend.h"
27 #define SECTOR_SHIFT 9
28 #define SECTOR_SIZE (1 << SECTOR_SHIFT)
32 * IV documentation: https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt
34 struct crypt_sector_iv {
35 enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI } type;
38 struct crypt_cipher *essiv_cipher;
42 /* Block encryption storage context */
43 struct crypt_storage {
44 uint64_t sector_start;
45 struct crypt_cipher *cipher;
46 struct crypt_sector_iv cipher_iv;
49 static int int_log2(unsigned int x)
52 for (x >>= 1; x > 0; x >>= 1)
57 static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
58 const char *cipher_name, const char *mode_name,
59 const char *iv_name, char *key, size_t key_length)
61 memset(ctx, 0, sizeof(*ctx));
63 ctx->iv_size = crypt_cipher_blocksize(cipher_name);
68 !strcmp(cipher_name, "cipher_null") ||
69 !strcmp(mode_name, "ecb")) {
73 } else if (!strcasecmp(iv_name, "null")) {
75 } else if (!strcasecmp(iv_name, "plain64")) {
76 ctx->type = IV_PLAIN64;
77 } else if (!strcasecmp(iv_name, "plain")) {
79 } else if (!strncasecmp(iv_name, "essiv:", 6)) {
80 struct crypt_hash *h = NULL;
81 char *hash_name = strchr(iv_name, ':');
89 hash_size = crypt_hash_size(++hash_name);
93 if ((unsigned)hash_size > sizeof(tmp))
96 if (crypt_hash_init(&h, hash_name))
99 r = crypt_hash_write(h, key, key_length);
101 crypt_hash_destroy(h);
105 r = crypt_hash_final(h, tmp, hash_size);
106 crypt_hash_destroy(h);
108 crypt_backend_memzero(tmp, sizeof(tmp));
112 r = crypt_cipher_init(&ctx->essiv_cipher, cipher_name, "ecb",
114 crypt_backend_memzero(tmp, sizeof(tmp));
118 ctx->type = IV_ESSIV;
119 } else if (!strncasecmp(iv_name, "benbi", 5)) {
120 int log = int_log2(ctx->iv_size);
121 if (log > SECTOR_SHIFT)
124 ctx->type = IV_BENBI;
125 ctx->benbi_shift = SECTOR_SHIFT - log;
129 ctx->iv = malloc(ctx->iv_size);
136 static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
144 memset(ctx->iv, 0, ctx->iv_size);
147 memset(ctx->iv, 0, ctx->iv_size);
148 *(uint32_t *)ctx->iv = cpu_to_le32(sector & 0xffffffff);
151 memset(ctx->iv, 0, ctx->iv_size);
152 *(uint64_t *)ctx->iv = cpu_to_le64(sector);
155 memset(ctx->iv, 0, ctx->iv_size);
156 *(uint64_t *)ctx->iv = cpu_to_le64(sector);
157 return crypt_cipher_encrypt(ctx->essiv_cipher,
158 ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
161 memset(ctx->iv, 0, ctx->iv_size);
162 val = cpu_to_be64((sector << ctx->benbi_shift) + 1);
163 memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
172 static int crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
174 if (ctx->type == IV_ESSIV)
175 crypt_cipher_destroy(ctx->essiv_cipher);
178 memset(ctx->iv, 0, ctx->iv_size);
182 memset(ctx, 0, sizeof(*ctx));
186 /* Block encryption storage wrappers */
188 int crypt_storage_init(struct crypt_storage **ctx,
189 uint64_t sector_start,
191 const char *cipher_mode,
192 char *key, size_t key_length)
194 struct crypt_storage *s;
196 char *cipher_iv = NULL;
199 s = malloc(sizeof(*s));
202 memset(s, 0, sizeof(*s));
204 /* Remove IV if present */
205 strncpy(mode_name, cipher_mode, sizeof(mode_name));
206 mode_name[sizeof(mode_name) - 1] = 0;
207 cipher_iv = strchr(mode_name, '-');
213 r = crypt_cipher_init(&s->cipher, cipher, mode_name, key, key_length);
215 crypt_storage_destroy(s);
219 r = crypt_sector_iv_init(&s->cipher_iv, cipher, mode_name, cipher_iv, key, key_length);
221 crypt_storage_destroy(s);
225 s->sector_start = sector_start;
231 int crypt_storage_decrypt(struct crypt_storage *ctx,
232 uint64_t sector, size_t count,
238 for (i = 0; i < count; i++) {
239 r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
242 r = crypt_cipher_decrypt(ctx->cipher,
243 &buffer[i * SECTOR_SIZE],
244 &buffer[i * SECTOR_SIZE],
247 ctx->cipher_iv.iv_size);
255 int crypt_storage_encrypt(struct crypt_storage *ctx,
256 uint64_t sector, size_t count,
262 for (i = 0; i < count; i++) {
263 r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
266 r = crypt_cipher_encrypt(ctx->cipher,
267 &buffer[i * SECTOR_SIZE],
268 &buffer[i * SECTOR_SIZE],
271 ctx->cipher_iv.iv_size);
279 int crypt_storage_destroy(struct crypt_storage *ctx)
284 crypt_sector_iv_destroy(&ctx->cipher_iv);
287 crypt_cipher_destroy(ctx->cipher);
289 memset(ctx, 0, sizeof(*ctx));