Prevent to initialise backends twice.
[platform/upstream/cryptsetup.git] / lib / crypto_backend / crypto_gcrypt.c
1 /*
2  * GCRYPT crypto backend implementation
3  *
4  * Copyright (C) 2010 Red Hat, Inc. All rights reserved.
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * version 2 as published by the Free Software Foundation.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <string.h>
21 #include <errno.h>
22 #include <assert.h>
23 #include <gcrypt.h>
24 #include "crypto_backend.h"
25
26 #define GCRYPT_REQ_VERSION "1.1.42"
27
28 static int crypto_backend_initialised = 0;
29
30 struct crypt_hash {
31         gcry_md_hd_t hd;
32         int hash_id;
33         int hash_len;
34 };
35
36 struct crypt_hmac {
37         gcry_md_hd_t hd;
38         int hash_id;
39         int hash_len;
40 };
41
42 int crypt_backend_init(void)
43 {
44         if (crypto_backend_initialised)
45                 return 0;
46
47         log_dbg("Initialising gcrypt crypto backend.");
48         if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
49                 if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
50                         return -ENOSYS;
51                 }
52
53 /* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
54  * it drops all privileges during secure memory initialisation.
55  * For now, the only workaround is to disable secure memory in gcrypt.
56  * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
57  * and it locks its memory space anyway.
58  */
59 #if 0
60                 log_dbg("Initializing crypto backend (secure memory disabled).");
61                 gcry_control (GCRYCTL_DISABLE_SECMEM);
62 #else
63
64                 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
65                 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
66                 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
67 #endif
68                 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
69         }
70
71         crypto_backend_initialised = 1;
72         return 0;
73 }
74
75 uint32_t crypt_backend_flags(void)
76 {
77         return 0;
78 }
79
80 /* HASH */
81 int crypt_hash_size(const char *name)
82 {
83         int hash_id;
84
85         assert(crypto_backend_initialised);
86
87         hash_id = gcry_md_map_name(name);
88         if (!hash_id)
89                 return -EINVAL;
90
91         return gcry_md_get_algo_dlen(hash_id);
92 }
93
94 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
95 {
96         struct crypt_hash *h;
97
98         assert(crypto_backend_initialised);
99
100         h = malloc(sizeof(*h));
101         if (!h)
102                 return -ENOMEM;
103
104         h->hash_id = gcry_md_map_name(name);
105         if (!h->hash_id) {
106                 free(h);
107                 return -EINVAL;
108         }
109
110         if (gcry_md_open(&h->hd, h->hash_id, 0)) {
111                 free(h);
112                 return -EINVAL;
113         }
114
115         h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
116         *ctx = h;
117         return 0;
118 }
119
120 int crypt_hash_restart(struct crypt_hash *ctx)
121 {
122         gcry_md_reset(ctx->hd);
123         return 0;
124 }
125
126 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
127 {
128         gcry_md_write(ctx->hd, buffer, length);
129         return 0;
130 }
131
132 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
133 {
134         unsigned char *hash;
135
136         if (length > ctx->hash_len)
137                 return -EINVAL;
138
139         hash = gcry_md_read(ctx->hd, ctx->hash_id);
140         if (!hash)
141                 return -EINVAL;
142
143         memcpy(buffer, hash, length);
144         return 0;
145 }
146
147 int crypt_hash_destroy(struct crypt_hash *ctx)
148 {
149         gcry_md_close(ctx->hd);
150         memset(ctx, 0, sizeof(*ctx));
151         free(ctx);
152         return 0;
153 }
154
155 /* HMAC */
156 int crypt_hmac_size(const char *name)
157 {
158         return crypt_hash_size(name);
159 }
160
161 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
162                     const void *buffer, size_t length)
163 {
164         struct crypt_hmac *h;
165
166         assert(crypto_backend_initialised);
167
168         h = malloc(sizeof(*h));
169         if (!h)
170                 return -ENOMEM;
171
172         h->hash_id = gcry_md_map_name(name);
173         if (!h->hash_id) {
174                 free(h);
175                 return -EINVAL;
176         }
177
178         if (gcry_md_open(&h->hd, h->hash_id, GCRY_MD_FLAG_HMAC)) {
179                 free(h);
180                 return -EINVAL;
181         }
182
183         if (gcry_md_setkey(h->hd, buffer, length)) {
184                 gcry_md_close(h->hd);
185                 free(h);
186                 return -EINVAL;
187         }
188
189         h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
190         *ctx = h;
191         return 0;
192 }
193
194 int crypt_hmac_restart(struct crypt_hmac *ctx)
195 {
196         gcry_md_reset(ctx->hd);
197         return 0;
198 }
199
200 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
201 {
202         gcry_md_write(ctx->hd, buffer, length);
203         return 0;
204 }
205
206 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
207 {
208         unsigned char *hash;
209
210         if (length > ctx->hash_len)
211                 return -EINVAL;
212
213         hash = gcry_md_read(ctx->hd, ctx->hash_id);
214         if (!hash)
215                 return -EINVAL;
216
217         memcpy(buffer, hash, length);
218         return 0;
219 }
220
221 int crypt_hmac_destroy(struct crypt_hmac *ctx)
222 {
223         gcry_md_close(ctx->hd);
224         memset(ctx, 0, sizeof(*ctx));
225         free(ctx);
226         return 0;
227 }