Add --enable-fips for linking with fipscheck library.
[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  *
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 static int crypto_backend_initialised = 0;
27
28 struct crypt_hash {
29         gcry_md_hd_t hd;
30         int hash_id;
31         int hash_len;
32 };
33
34 struct crypt_hmac {
35         gcry_md_hd_t hd;
36         int hash_id;
37         int hash_len;
38 };
39
40 int crypt_backend_init(struct crypt_device *ctx)
41 {
42         if (crypto_backend_initialised)
43                 return 0;
44
45         log_dbg("Initialising gcrypt crypto backend.");
46         crypt_fips_libcryptsetup_check(ctx);
47         if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
48                 if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
49                         return -ENOSYS;
50                 }
51
52 /* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
53  * it drops all privileges during secure memory initialisation.
54  * For now, the only workaround is to disable secure memory in gcrypt.
55  * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
56  * and it locks its memory space anyway.
57  */
58 #if 0
59                 log_dbg("Initializing crypto backend (secure memory disabled).");
60                 gcry_control (GCRYCTL_DISABLE_SECMEM);
61 #else
62
63                 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
64                 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
65                 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
66 #endif
67                 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
68         }
69
70         crypto_backend_initialised = 1;
71         return 0;
72 }
73
74 uint32_t crypt_backend_flags(void)
75 {
76         return 0;
77 }
78
79 /* HASH */
80 int crypt_hash_size(const char *name)
81 {
82         int hash_id;
83
84         assert(crypto_backend_initialised);
85
86         hash_id = gcry_md_map_name(name);
87         if (!hash_id)
88                 return -EINVAL;
89
90         return gcry_md_get_algo_dlen(hash_id);
91 }
92
93 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
94 {
95         struct crypt_hash *h;
96
97         assert(crypto_backend_initialised);
98
99         h = malloc(sizeof(*h));
100         if (!h)
101                 return -ENOMEM;
102
103         h->hash_id = gcry_md_map_name(name);
104         if (!h->hash_id) {
105                 free(h);
106                 return -EINVAL;
107         }
108
109         if (gcry_md_open(&h->hd, h->hash_id, 0)) {
110                 free(h);
111                 return -EINVAL;
112         }
113
114         h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
115         *ctx = h;
116         return 0;
117 }
118
119 static void crypt_hash_restart(struct crypt_hash *ctx)
120 {
121         gcry_md_reset(ctx->hd);
122 }
123
124 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
125 {
126         gcry_md_write(ctx->hd, buffer, length);
127         return 0;
128 }
129
130 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
131 {
132         unsigned char *hash;
133
134         if (length > (size_t)ctx->hash_len)
135                 return -EINVAL;
136
137         hash = gcry_md_read(ctx->hd, ctx->hash_id);
138         if (!hash)
139                 return -EINVAL;
140
141         memcpy(buffer, hash, length);
142         crypt_hash_restart(ctx);
143
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 static void crypt_hmac_restart(struct crypt_hmac *ctx)
195 {
196         gcry_md_reset(ctx->hd);
197 }
198
199 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
200 {
201         gcry_md_write(ctx->hd, buffer, length);
202         return 0;
203 }
204
205 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
206 {
207         unsigned char *hash;
208
209         if (length > (size_t)ctx->hash_len)
210                 return -EINVAL;
211
212         hash = gcry_md_read(ctx->hd, ctx->hash_id);
213         if (!hash)
214                 return -EINVAL;
215
216         memcpy(buffer, hash, length);
217         crypt_hmac_restart(ctx);
218
219         return 0;
220 }
221
222 int crypt_hmac_destroy(struct crypt_hmac *ctx)
223 {
224         gcry_md_close(ctx->hd);
225         memset(ctx, 0, sizeof(*ctx));
226         free(ctx);
227         return 0;
228 }