~ubuntu-branches/debian/jessie/cryptsetup/jessie

« back to all changes in this revision

Viewing changes to lib/crypto_backend/crypto_storage.c

  • Committer: Package Import Robot
  • Author(s): Jonas Meurer
  • Date: 2014-03-04 20:14:07 UTC
  • mfrom: (0.2.13)
  • Revision ID: package-import@ubuntu.com-20140304201407-8cn7znmyssyrgduu
Tags: 2:1.6.6-1
* new upsream version 1.6.6.
* add versioned dependency on cryptsetup-bin to cryptsetup. (closes: #747670)
* change versioned build-depends on automake to >= 1.12 to reflect upstream
  requirements. Thanks to Joel Johnson. (closes: #740688)
* build and link against libgcrypt20 (>= 1.6.1). Add note about whirlpool
  bug in older libgcrypt releases and how to deal with it to debian/NEWS.
* add systemd support to askpass. Thanks to David Härdeman for the patch.
  (closes: #742600, #755074)
* fix initramfs cryptroot hook to not include modules unconditionally. Thanks
  to Dmitrijs Ledkovs for bugreport and patch. (closes: #714104)
* fix decrypt_keyctl script to ask again in case of wrong passphrase. Thanks
  to Dmitriy Matrosov for bugreport and patch. (closes: #748368)
* incorporate changes from ubuntu package:
  - don't hardcode paths to udevadm and udevsettle.
  - restore terminal settings in askpass.c. (closes: #714942)
  - migrate upstart jobs to new names.

Show diffs side-by-side

added added

removed removed

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