Add skeleton and implementation of various crypto backends
[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 <gcrypt.h>
23 #include "crypto_backend.h"
24
25 #define GCRYPT_REQ_VERSION "1.1.42"
26
27 struct crypt_hash {
28         gcry_md_hd_t hd;
29         int hash_id;
30         int hash_len;
31 };
32
33 struct crypt_hmac {
34         gcry_md_hd_t hd;
35         int hash_id;
36         int hash_len;
37 };
38
39 int crypt_backend_init(void)
40 {
41         log_dbg("Initialising gcrypt crypto backend.");
42         if (!gcry_control (GCRYCTL_INITIALIZATION_FINISHED_P)) {
43                 if (!gcry_check_version (GCRYPT_REQ_VERSION)) {
44                         return -ENOSYS;
45                 }
46
47 /* FIXME: If gcrypt compiled to support POSIX 1003.1e capabilities,
48  * it drops all privileges during secure memory initialisation.
49  * For now, the only workaround is to disable secure memory in gcrypt.
50  * cryptsetup always need at least cap_sys_admin privilege for dm-ioctl
51  * and it locks its memory space anyway.
52  */
53 #if 0
54                 log_dbg("Initializing crypto backend (secure memory disabled).");
55                 gcry_control (GCRYCTL_DISABLE_SECMEM);
56 #else
57
58                 gcry_control (GCRYCTL_SUSPEND_SECMEM_WARN);
59                 gcry_control (GCRYCTL_INIT_SECMEM, 16384, 0);
60                 gcry_control (GCRYCTL_RESUME_SECMEM_WARN);
61 #endif
62                 gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
63         }
64
65         return 0;
66 }
67
68 uint32_t crypt_backend_flags(void)
69 {
70         return 0;
71 }
72
73 /* HASH */
74 int crypt_hash_size(const char *name)
75 {
76         int hash_id = gcry_md_map_name(name);
77
78         if (!hash_id)
79                 return -EINVAL;
80
81         return gcry_md_get_algo_dlen(hash_id);
82 }
83
84 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
85 {
86         struct crypt_hash *h;
87
88         h = malloc(sizeof(*h));
89         if (!h)
90                 return -ENOMEM;
91
92         h->hash_id = gcry_md_map_name(name);
93         if (!h->hash_id) {
94                 free(h);
95                 return -EINVAL;
96         }
97
98         if (gcry_md_open(&h->hd, h->hash_id, 0)) {
99                 free(h);
100                 return -EINVAL;
101         }
102
103         h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
104         *ctx = h;
105         return 0;
106 }
107
108 int crypt_hash_restart(struct crypt_hash *ctx)
109 {
110         gcry_md_reset(ctx->hd);
111         return 0;
112 }
113
114 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
115 {
116         gcry_md_write(ctx->hd, buffer, length);
117         return 0;
118 }
119
120 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
121 {
122         unsigned char *hash;
123
124         if (length > ctx->hash_len)
125                 return -EINVAL;
126
127         hash = gcry_md_read(ctx->hd, ctx->hash_id);
128         if (!hash)
129                 return -EINVAL;
130
131         memcpy(buffer, hash, length);
132         return 0;
133 }
134
135 int crypt_hash_destroy(struct crypt_hash *ctx)
136 {
137         gcry_md_close(ctx->hd);
138         memset(ctx, 0, sizeof(*ctx));
139         free(ctx);
140         return 0;
141 }
142
143 /* HMAC */
144 int crypt_hmac_size(const char *name)
145 {
146         return crypt_hash_size(name);
147 }
148
149 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
150                     const void *buffer, size_t length)
151 {
152         struct crypt_hmac *h;
153
154         h = malloc(sizeof(*h));
155         if (!h)
156                 return -ENOMEM;
157
158         h->hash_id = gcry_md_map_name(name);
159         if (!h->hash_id) {
160                 free(h);
161                 return -EINVAL;
162         }
163
164         if (gcry_md_open(&h->hd, h->hash_id, GCRY_MD_FLAG_HMAC)) {
165                 free(h);
166                 return -EINVAL;
167         }
168
169         if (gcry_md_setkey(h->hd, buffer, length)) {
170                 gcry_md_close(h->hd);
171                 free(h);
172                 return -EINVAL;
173         }
174
175         h->hash_len = gcry_md_get_algo_dlen(h->hash_id);
176         *ctx = h;
177         return 0;
178 }
179
180 int crypt_hmac_restart(struct crypt_hmac *ctx)
181 {
182         gcry_md_reset(ctx->hd);
183         return 0;
184 }
185
186 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
187 {
188         gcry_md_write(ctx->hd, buffer, length);
189         return 0;
190 }
191
192 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
193 {
194         unsigned char *hash;
195
196         if (length > ctx->hash_len)
197                 return -EINVAL;
198
199         hash = gcry_md_read(ctx->hd, ctx->hash_id);
200         if (!hash)
201                 return -EINVAL;
202
203         memcpy(buffer, hash, length);
204         return 0;
205 }
206
207 int crypt_hmac_destroy(struct crypt_hmac *ctx)
208 {
209         gcry_md_close(ctx->hd);
210         memset(ctx, 0, sizeof(*ctx));
211         free(ctx);
212         return 0;
213 }