Skip to content

Commit a3c0f67

Browse files
committed
Process LUKS keyslots in userspace through kernel crypto wrapper.
This allow LUKS handling without requiring root privilege. The dmcrypt device-mapper is used only for device activation now.
1 parent 6d4c2db commit a3c0f67

File tree

4 files changed

+370
-5
lines changed

4 files changed

+370
-5
lines changed

lib/crypto_backend/Makefile.am

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ noinst_LTLIBRARIES = libcrypto_backend.la
55
libcrypto_backend_la_CFLAGS = $(AM_CFLAGS) -Wall @CRYPTO_CFLAGS@
66

77
libcrypto_backend_la_SOURCES = crypto_backend.h \
8-
crypto_cipher_kernel.c pbkdf_check.c crc32.c
8+
crypto_cipher_kernel.c crypto_storage.c pbkdf_check.c crc32.c
99

1010
if CRYPTO_BACKEND_GCRYPT
1111
libcrypto_backend_la_SOURCES += crypto_gcrypt.c

lib/crypto_backend/crypto_backend.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct crypt_device;
2828
struct crypt_hash;
2929
struct crypt_hmac;
3030
struct crypt_cipher;
31+
struct crypt_storage;
3132

3233
int crypt_backend_init(struct crypt_device *ctx);
3334

@@ -91,4 +92,14 @@ int crypt_cipher_decrypt(struct crypt_cipher *ctx,
9192
const char *in, char *out, size_t length,
9293
const char *iv, size_t iv_length);
9394

95+
/* storage encryption wrappers */
96+
int crypt_storage_init(struct crypt_storage **ctx, uint64_t sector_start,
97+
const char *cipher, const char *cipher_mode,
98+
char *key, size_t key_length);
99+
int crypt_storage_destroy(struct crypt_storage *ctx);
100+
int crypt_storage_decrypt(struct crypt_storage *ctx, uint64_t sector,
101+
size_t count, char *buffer);
102+
int crypt_storage_encrypt(struct crypt_storage *ctx, uint64_t sector,
103+
size_t count, char *buffer);
104+
94105
#endif /* _CRYPTO_BACKEND_H */
Lines changed: 274 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,274 @@
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, 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 <string.h>
23+
#include <stdlib.h>
24+
#include <stdio.h>
25+
#include <errno.h>
26+
#include <unistd.h>
27+
#include "bitops.h"
28+
#include "crypto_backend.h"
29+
30+
#define SECTOR_SHIFT 9
31+
#define SECTOR_SIZE (1 << SECTOR_SHIFT)
32+
33+
/*
34+
* Internal IV helper
35+
* IV documentation: https://code.google.com/p/cryptsetup/wiki/DMCrypt
36+
*/
37+
struct crypt_sector_iv {
38+
enum { IV_NONE, IV_NULL, IV_PLAIN, IV_PLAIN64, IV_ESSIV, IV_BENBI } type;
39+
int iv_size;
40+
char *iv;
41+
struct crypt_cipher *essiv_cipher;
42+
int benbi_shift;
43+
};
44+
45+
/* Block encryption storage context */
46+
struct crypt_storage {
47+
uint64_t sector_start;
48+
struct crypt_cipher *cipher;
49+
struct crypt_sector_iv cipher_iv;
50+
};
51+
52+
static int int_log2(unsigned int x)
53+
{
54+
int r = 0;
55+
for (x >>= 1; x > 0; x >>= 1)
56+
r++;
57+
return r;
58+
}
59+
60+
static int crypt_sector_iv_init(struct crypt_sector_iv *ctx,
61+
const char *cipher_name, const char *iv_name,
62+
char *key, size_t key_length)
63+
{
64+
memset(ctx, 0, sizeof(*ctx));
65+
66+
if (!iv_name || !strcmp(cipher_name, "cipher_null")) {
67+
ctx->type = IV_NONE;
68+
ctx->iv_size = 0;
69+
return 0;
70+
} else if (!strncasecmp(iv_name, "null", 4)) {
71+
ctx->type = IV_NULL;
72+
} else if (!strncasecmp(iv_name, "plain64", 7)) {
73+
ctx->type = IV_PLAIN64;
74+
} else if (!strncasecmp(iv_name, "plain", 5)) {
75+
ctx->type = IV_PLAIN;
76+
} else if (!strncasecmp(iv_name, "essiv", 5)) {
77+
struct crypt_hash *h = NULL;
78+
char *hash_name = strchr(iv_name, ':');
79+
char tmp[256];
80+
int r;
81+
82+
if (!hash_name || crypt_hash_size(++hash_name) > sizeof(tmp))
83+
return -EINVAL;
84+
85+
if (crypt_hash_init(&h, hash_name))
86+
return -EINVAL;
87+
88+
crypt_hash_write(h, key, key_length);
89+
crypt_hash_final(h, tmp, crypt_hash_size(hash_name));
90+
crypt_hash_destroy(h);
91+
92+
r = crypt_cipher_init(&ctx->essiv_cipher, cipher_name, "ecb",
93+
tmp, crypt_hash_size(hash_name));
94+
memset(tmp, 0, sizeof(tmp));
95+
if (r)
96+
return r;
97+
98+
ctx->type = IV_ESSIV;
99+
} else if (!strncasecmp(iv_name, "benbi", 5)) {
100+
int log = int_log2(crypt_cipher_blocksize(cipher_name));
101+
if (log > SECTOR_SHIFT)
102+
return -EINVAL;
103+
104+
ctx->type = IV_BENBI;
105+
ctx->benbi_shift = SECTOR_SHIFT - log;
106+
} else
107+
return -EINVAL;
108+
109+
if (!ctx->iv_size)
110+
ctx->iv_size = crypt_cipher_blocksize(cipher_name);
111+
112+
ctx->iv = malloc(ctx->iv_size);
113+
if (!ctx->iv)
114+
return -ENOMEM;
115+
116+
return 0;
117+
}
118+
119+
static int crypt_sector_iv_generate(struct crypt_sector_iv *ctx, uint64_t sector)
120+
{
121+
uint64_t val;
122+
123+
switch (ctx->type) {
124+
case IV_NONE:
125+
break;
126+
case IV_NULL:
127+
memset(ctx->iv, 0, ctx->iv_size);
128+
break;
129+
case IV_PLAIN:
130+
memset(ctx->iv, 0, ctx->iv_size);
131+
*(uint32_t *)ctx->iv = cpu_to_le32(sector & 0xffffffff);
132+
break;
133+
case IV_PLAIN64:
134+
memset(ctx->iv, 0, ctx->iv_size);
135+
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
136+
break;
137+
case IV_ESSIV:
138+
memset(ctx->iv, 0, ctx->iv_size);
139+
*(uint64_t *)ctx->iv = cpu_to_le64(sector);
140+
return crypt_cipher_encrypt(ctx->essiv_cipher,
141+
ctx->iv, ctx->iv, ctx->iv_size, NULL, 0);
142+
break;
143+
case IV_BENBI:
144+
memset(ctx->iv, 0, ctx->iv_size);
145+
val = cpu_to_be64((sector << ctx->benbi_shift) + 1);
146+
memcpy(ctx->iv + ctx->iv_size - sizeof(val), &val, sizeof(val));
147+
break;
148+
default:
149+
return -EINVAL;
150+
}
151+
152+
return 0;
153+
}
154+
155+
static int crypt_sector_iv_destroy(struct crypt_sector_iv *ctx)
156+
{
157+
if (ctx->type == IV_ESSIV)
158+
crypt_cipher_destroy(ctx->essiv_cipher);
159+
160+
if (ctx->iv) {
161+
memset(ctx->iv, 0, ctx->iv_size);
162+
free(ctx->iv);
163+
}
164+
165+
memset(ctx, 0, sizeof(*ctx));
166+
return 0;
167+
}
168+
169+
/* Block encryption storage wrappers */
170+
171+
int crypt_storage_init(struct crypt_storage **ctx,
172+
uint64_t sector_start,
173+
const char *cipher,
174+
const char *cipher_mode,
175+
char *key, size_t key_length)
176+
{
177+
struct crypt_storage *s;
178+
char mode_name[64];
179+
char *cipher_iv = NULL;
180+
int r = -EIO;
181+
182+
s = malloc(sizeof(*s));
183+
if (!s)
184+
return -ENOMEM;
185+
memset(s, 0, sizeof(*s));
186+
187+
/* Remove IV if present */
188+
strncpy(mode_name, cipher_mode, sizeof(mode_name));
189+
mode_name[sizeof(mode_name) - 1] = 0;
190+
cipher_iv = strchr(mode_name, '-');
191+
if (cipher_iv) {
192+
*cipher_iv = '\0';
193+
cipher_iv++;
194+
}
195+
196+
r = crypt_cipher_init(&s->cipher, cipher, mode_name, key, key_length);
197+
if (r) {
198+
crypt_storage_destroy(s);
199+
return r;
200+
}
201+
202+
r = crypt_sector_iv_init(&s->cipher_iv, cipher, cipher_iv, key, key_length);
203+
if (r) {
204+
crypt_storage_destroy(s);
205+
return r;
206+
}
207+
208+
s->sector_start = sector_start;
209+
210+
*ctx = s;
211+
return 0;
212+
}
213+
214+
int crypt_storage_decrypt(struct crypt_storage *ctx,
215+
uint64_t sector, size_t count,
216+
char *buffer)
217+
{
218+
int i, r = 0;
219+
220+
for (i = 0; i < count; i++) {
221+
r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
222+
if (r)
223+
break;
224+
r = crypt_cipher_decrypt(ctx->cipher,
225+
&buffer[i * SECTOR_SIZE],
226+
&buffer[i * SECTOR_SIZE],
227+
SECTOR_SIZE,
228+
ctx->cipher_iv.iv,
229+
ctx->cipher_iv.iv_size);
230+
if (r)
231+
break;
232+
}
233+
234+
return r;
235+
}
236+
237+
int crypt_storage_encrypt(struct crypt_storage *ctx,
238+
uint64_t sector, size_t count,
239+
char *buffer)
240+
{
241+
int i, r = 0;
242+
243+
for (i = 0; i < count; i++) {
244+
r = crypt_sector_iv_generate(&ctx->cipher_iv, sector + i);
245+
if (r)
246+
break;
247+
r = crypt_cipher_encrypt(ctx->cipher,
248+
&buffer[i * SECTOR_SIZE],
249+
&buffer[i * SECTOR_SIZE],
250+
SECTOR_SIZE,
251+
ctx->cipher_iv.iv,
252+
ctx->cipher_iv.iv_size);
253+
if (r)
254+
break;
255+
}
256+
257+
return r;
258+
}
259+
260+
int crypt_storage_destroy(struct crypt_storage *ctx)
261+
{
262+
if (!ctx)
263+
return 0;
264+
265+
crypt_sector_iv_destroy(&ctx->cipher_iv);
266+
267+
if (ctx->cipher)
268+
crypt_cipher_destroy(ctx->cipher);
269+
270+
memset(ctx, 0, sizeof(*ctx));
271+
free(ctx);
272+
273+
return 0;
274+
}

0 commit comments

Comments
 (0)