Move get_key to common code, simplify verify flags.
[platform/upstream/cryptsetup.git] / lib / gcrypt.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <ctype.h>
4 #include <errno.h>
5 #include <gcrypt.h>
6
7 #include "libcryptsetup.h"
8 #include "internal.h"
9
10 #define MAX_DIGESTS             64
11 #define GCRYPT_REQ_VERSION      "1.1.42"
12
13 int init_crypto(struct crypt_device *ctx)
14 {
15         int r;
16
17         if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
18                 if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
19                         r = -ENOSYS;
20                         goto fail;
21                 }
22
23 /* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
24  * it drops all privileges during secure memory initialisation.
25  * For now, the only workaround is to disable secure memory in gcrypt.
26  * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
27  * and it locks its memory space anyway.
28  */
29 #if 0
30                 log_dbg("Initializing crypto backend (secure memory disabled).");
31                 gcry_control (GCRYCTL_DISABLE_SECMEM);
32 #else
33                 log_dbg("Initializing crypto backend (using secure memory).");
34                 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
35                 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
36                 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
37 #endif
38                 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
39         }
40
41         return 0;
42 fail:
43         log_err(ctx, _("Cannot initialize crypto backend.\n"));
44         return r;
45 }
46
47 static int gcrypt_hash(void *data, int size, char *key,
48                        int sizep, const char *passphrase)
49 {
50         gcry_md_hd_t md;
51         int algo = *((int *)data);
52         int len = gcry_md_get_algo_dlen(algo);
53         int round, i;
54
55         if (gcry_md_open(&md, algo, 0))
56                 return -1;
57
58         for(round = 0; size; round++) {
59                 /* hack from hashalot to avoid null bytes in key */
60                 for(i = 0; i < round; i++)
61                         gcry_md_write(md, "A", 1);
62
63                 gcry_md_write(md, passphrase, sizep);
64
65                 if (len > size)
66                         len = size;
67                 memcpy(key, gcry_md_read(md, algo), len);
68
69                 key += len;
70                 size -= len;
71                 if (size)
72                         gcry_md_reset(md);
73         }
74
75         gcry_md_close(md);
76         return 0;
77 }
78
79 static struct hash_type *gcrypt_get_hashes(void)
80 {
81         struct hash_type *hashes;
82         int size = MAX_DIGESTS;
83         int *list;
84         int i;
85         gcry_error_t r;
86
87         if (!gcry_check_version(GCRYPT_REQ_VERSION))
88                 return NULL;
89
90         list = (int *)malloc(sizeof(*list) * size);
91         if (!list)
92                 return NULL;
93
94         r = gcry_md_list(list, &size);
95         if (r || !size) {
96                 free(list);
97                 return NULL;
98         }
99
100         hashes = malloc(sizeof(*hashes) * (size + 1));
101         if (!hashes) {
102                 free(list);
103                 return NULL;
104         }
105
106         for(i = 0; i < size; i++) {
107                 hashes[i].name = NULL;
108                 hashes[i].private = NULL;
109         }
110
111         for(i = 0; i < size; i++) {
112                 char *p;
113
114                 hashes[i].name = strdup(gcry_md_algo_name(list[i]));
115                 if(!hashes[i].name)
116                         goto err;
117                 for(p = (char *)hashes[i].name; *p; p++)
118                         *p = tolower(*p);
119                 hashes[i].private = malloc(sizeof(int));
120                 if(!hashes[i].private)
121                         goto err;
122                 *((int *)hashes[i].private) = list[i];
123                 hashes[i].fn = gcrypt_hash;
124         }
125         hashes[i].name = NULL;
126         hashes[i].private = NULL;
127         hashes[i].fn = NULL;
128
129         free(list);
130
131         return hashes;
132
133 err:
134         free(list);
135         for(i = 0; i < size; i++) {
136                 free(hashes[i].name);
137                 free(hashes[i].private);
138         }
139         free(hashes);
140         return NULL;
141 }
142
143 static void gcrypt_free_hashes(struct hash_type *hashes)
144 {
145         struct hash_type *hash;
146
147         for(hash = hashes; hash->name; hash++) {
148                 free(hash->name);
149                 free(hash->private);
150         }
151
152         free(hashes);
153 }
154
155 struct hash_backend hash_gcrypt_backend = {
156         .name = "libgcrypt",
157         .get_hashes = gcrypt_get_hashes,
158         .free_hashes = gcrypt_free_hashes
159 };