9037ad673b602cdff88b2edfa187ffce12d04f3f
[platform/upstream/cryptsetup.git] / lib / crypto_backend / crypto_gcrypt.c
1 /*
2  * GCRYPT crypto backend implementation
3  *
4  * Copyright (C) 2010-2012, Red Hat, Inc. All rights reserved.
5  * Copyright (C) 2010-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 <stdio.h>
24 #include <errno.h>
25 #include <assert.h>
26 #include <gcrypt.h>
27 #include "crypto_backend.h"
28
29 static int crypto_backend_initialised = 0;
30 static int crypto_backend_secmem = 1;
31 static int crypto_backend_whirlpool_bug = -1;
32 static char version[64];
33
34 struct crypt_hash {
35         gcry_md_hd_t hd;
36         int hash_id;
37         int hash_len;
38 };
39
40 struct crypt_hmac {
41         gcry_md_hd_t hd;
42         int hash_id;
43         int hash_len;
44 };
45
46 /*
47  * Test for wrong Whirlpool variant,
48  * Ref: http://lists.gnupg.org/pipermail/gcrypt-devel/2014-January/002889.html
49  */
50 static void crypt_hash_test_whirlpool_bug(void)
51 {
52         struct crypt_hash *h;
53         char buf[2] = "\0\0", hash_out1[64], hash_out2[64];
54         int r;
55
56         if (crypto_backend_whirlpool_bug >= 0)
57                 return;
58
59         crypto_backend_whirlpool_bug = 0;
60         if (crypt_hash_init(&h, "whirlpool"))
61                 return;
62
63         /* One shot */
64         if ((r = crypt_hash_write(h, &buf[0], 2)) ||
65             (r = crypt_hash_final(h, hash_out1, 64))) {
66                 crypt_hash_destroy(h);
67                 return;
68         }
69
70         /* Split buf (crypt_hash_final resets hash state) */
71         if ((r = crypt_hash_write(h, &buf[0], 1)) ||
72             (r = crypt_hash_write(h, &buf[1], 1)) ||
73             (r = crypt_hash_final(h, hash_out2, 64))) {
74                 crypt_hash_destroy(h);
75                 return;
76         }
77
78         crypt_hash_destroy(h);
79
80         if (memcmp(hash_out1, hash_out2, 64))
81                 crypto_backend_whirlpool_bug = 1;
82 }
83
84 int crypt_backend_init(struct crypt_device *ctx)
85 {
86         if (crypto_backend_initialised)
87                 return 0;
88
89         if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
90                 if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
91                         return -ENOSYS;
92                 }
93
94 /* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
95  * it drops all privileges during secure memory initialisation.
96  * For now, the only workaround is to disable secure memory in gcrypt.
97  * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
98  * and it locks its memory space anyway.
99  */
100 #if 0
101                 gcry_control (GCRYCTL_DISABLE_SECMEM);
102                 crypto_backend_secmem = 0;
103 #else
104
105                 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
106                 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
107                 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
108 #endif
109                 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
110         }
111
112         crypto_backend_initialised = 1;
113         crypt_hash_test_whirlpool_bug();
114
115         snprintf(version, 64, "gcrypt %s%s%s",
116                  gcry_check_version(NULL),
117                  crypto_backend_secmem ? "" : ", secmem disabled",
118                  crypto_backend_whirlpool_bug > 0 ? ", flawed whirlpool" : ""
119                 );
120
121         return 0;
122 }
123
124 const char *crypt_backend_version(void)
125 {
126         return crypto_backend_initialised ? version : "";
127 }
128
129 uint32_t crypt_backend_flags(void)
130 {
131         return 0;
132 }
133
134 static const char *crypt_hash_compat_name(const char *name, unsigned int *flags)
135 {
136         const char *hash_name = name;
137
138         /* "whirlpool_gcryptbug" is out shortcut to flawed whirlpool
139          * in libgcrypt < 1.6.0 */
140         if (name && !strcasecmp(name, "whirlpool_gcryptbug")) {
141 #if GCRYPT_VERSION_NUMBER >= 0x010601
142                 if (flags)
143                         *flags |= GCRY_MD_FLAG_BUGEMU1;
144 #endif
145                 hash_name = "whirlpool";
146         }
147
148         return hash_name;
149 }
150
151 /* HASH */
152 int crypt_hash_size(const char *name)
153 {
154         int hash_id;
155
156         assert(crypto_backend_initialised);
157
158         hash_id = gcry_md_map_name(crypt_hash_compat_name(name, NULL));
159         if (!hash_id)
160                 return -EINVAL;
161
162         return gcry_md_get_algo_dlen(hash_id);
163 }
164
165 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
166 {
167         struct crypt_hash *h;
168         unsigned int flags = 0;
169
170         assert(crypto_backend_initialised);
171
172         h = malloc(sizeof(*h));
173         if (!h)
174                 return -ENOMEM;
175
176         h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
177         if (!h->hash_id) {
178                 free(h);
179                 return -EINVAL;
180         }
181
182         if (gcry_md_open(&h->hd, h->hash_id, flags)) {
183                 free(h);
184                 return -EINVAL;
185         }
186
187         h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
188         *ctx = h;
189         return 0;
190 }
191
192 static void crypt_hash_restart(struct crypt_hash *ctx)
193 {
194         gcry_md_reset(ctx->hd);
195 }
196
197 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
198 {
199         gcry_md_write(ctx->hd, buffer, length);
200         return 0;
201 }
202
203 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
204 {
205         unsigned char *hash;
206
207         if (length > (size_t)ctx->hash_len)
208                 return -EINVAL;
209
210         hash = gcry_md_read(ctx->hd, ctx->hash_id);
211         if (!hash)
212                 return -EINVAL;
213
214         memcpy(buffer, hash, length);
215         crypt_hash_restart(ctx);
216
217         return 0;
218 }
219
220 int crypt_hash_destroy(struct crypt_hash *ctx)
221 {
222         gcry_md_close(ctx->hd);
223         memset(ctx, 0, sizeof(*ctx));
224         free(ctx);
225         return 0;
226 }
227
228 /* HMAC */
229 int crypt_hmac_size(const char *name)
230 {
231         return crypt_hash_size(name);
232 }
233
234 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
235                     const void *buffer, size_t length)
236 {
237         struct crypt_hmac *h;
238         unsigned int flags = GCRY_MD_FLAG_HMAC;
239
240         assert(crypto_backend_initialised);
241
242         h = malloc(sizeof(*h));
243         if (!h)
244                 return -ENOMEM;
245
246         h->hash_id = gcry_md_map_name(crypt_hash_compat_name(name, &flags));
247         if (!h->hash_id) {
248                 free(h);
249                 return -EINVAL;
250         }
251
252         if (gcry_md_open(&h->hd, h->hash_id, flags)) {
253                 free(h);
254                 return -EINVAL;
255         }
256
257         if (gcry_md_setkey(h->hd, buffer, length)) {
258                 gcry_md_close(h->hd);
259                 free(h);
260                 return -EINVAL;
261         }
262
263         h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
264         *ctx = h;
265         return 0;
266 }
267
268 static void crypt_hmac_restart(struct crypt_hmac *ctx)
269 {
270         gcry_md_reset(ctx->hd);
271 }
272
273 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
274 {
275         gcry_md_write(ctx->hd, buffer, length);
276         return 0;
277 }
278
279 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
280 {
281         unsigned char *hash;
282
283         if (length > (size_t)ctx->hash_len)
284                 return -EINVAL;
285
286         hash = gcry_md_read(ctx->hd, ctx->hash_id);
287         if (!hash)
288                 return -EINVAL;
289
290         memcpy(buffer, hash, length);
291         crypt_hmac_restart(ctx);
292
293         return 0;
294 }
295
296 int crypt_hmac_destroy(struct crypt_hmac *ctx)
297 {
298         gcry_md_close(ctx->hd);
299         memset(ctx, 0, sizeof(*ctx));
300         free(ctx);
301         return 0;
302 }
303
304 /* RNG */
305 int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
306 {
307         switch(quality) {
308         case CRYPT_RND_NORMAL:
309                 gcry_randomize(buffer, length, GCRY_STRONG_RANDOM);
310                 break;
311         case CRYPT_RND_SALT:
312         case CRYPT_RND_KEY:
313         default:
314                 gcry_randomize(buffer, length, GCRY_VERY_STRONG_RANDOM);
315                 break;
316         }
317         return 0;
318 }
319
320 /* PBKDF */
321 int crypt_pbkdf(const char *kdf, const char *hash,
322                 const char *password, size_t password_length,
323                 const char *salt, size_t salt_length,
324                 char *key, size_t key_length,
325                 unsigned int iterations)
326 {
327         const char *hash_name = crypt_hash_compat_name(hash, NULL);
328
329 #if USE_INTERNAL_PBKDF2
330         if (!kdf || strncmp(kdf, "pbkdf2", 6))
331                 return -EINVAL;
332
333         return pkcs5_pbkdf2(hash_name, password, password_length, salt, salt_length,
334                             iterations, key_length, key, 0);
335
336 #else /* USE_INTERNAL_PBKDF2 */
337         int hash_id = gcry_md_map_name(hash_name);
338         int kdf_id;
339
340         if (!hash_id)
341                 return -EINVAL;
342
343         if (kdf && !strncmp(kdf, "pbkdf2", 6))
344                 kdf_id = GCRY_KDF_PBKDF2;
345         else
346                 return -EINVAL;
347
348         if (gcry_kdf_derive(password, password_length, kdf_id, hash_id,
349             salt, salt_length, iterations, key_length, key))
350                 return -EINVAL;
351
352         return 0;
353 #endif /* USE_INTERNAL_PBKDF2 */
354 }