2577b1880425a581563c6ea645e49da653f5dbf3
[platform/upstream/cryptsetup.git] / lib / crypto_backend / crypto_openssl.c
1 /*
2  * OPENSSL 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  * In addition, as a special exception, the copyright holders give
20  * permission to link the code of portions of this program with the
21  * OpenSSL library under certain conditions as described in each
22  * individual source file, and distribute linked combinations
23  * including the two.
24  *
25  * You must obey the GNU General Public License in all respects
26  * for all of the code used other than OpenSSL.
27  */
28
29 #include <string.h>
30 #include <errno.h>
31 #include <openssl/evp.h>
32 #include <openssl/hmac.h>
33 #include <openssl/rand.h>
34 #include "crypto_backend.h"
35
36 static int crypto_backend_initialised = 0;
37
38 struct crypt_hash {
39         EVP_MD_CTX md;
40         const EVP_MD *hash_id;
41         int hash_len;
42 };
43
44 struct crypt_hmac {
45         HMAC_CTX md;
46         const EVP_MD *hash_id;
47         int hash_len;
48 };
49
50 int crypt_backend_init(struct crypt_device *ctx)
51 {
52         if (crypto_backend_initialised)
53                 return 0;
54
55         OpenSSL_add_all_algorithms();
56
57         crypto_backend_initialised = 1;
58         return 0;
59 }
60
61 uint32_t crypt_backend_flags(void)
62 {
63         return 0;
64 }
65
66 const char *crypt_backend_version(void)
67 {
68         return SSLeay_version(SSLEAY_VERSION);
69 }
70
71 /* HASH */
72 int crypt_hash_size(const char *name)
73 {
74         const EVP_MD *hash_id = EVP_get_digestbyname(name);
75
76         if (!hash_id)
77                 return -EINVAL;
78
79         return EVP_MD_size(hash_id);
80 }
81
82 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
83 {
84         struct crypt_hash *h;
85
86         h = malloc(sizeof(*h));
87         if (!h)
88                 return -ENOMEM;
89
90         h->hash_id = EVP_get_digestbyname(name);
91         if (!h->hash_id) {
92                 free(h);
93                 return -EINVAL;
94         }
95
96         if (EVP_DigestInit(&h->md, h->hash_id) != 1) {
97                 free(h);
98                 return -EINVAL;
99         }
100
101         h->hash_len = EVP_MD_size(h->hash_id);
102         *ctx = h;
103         return 0;
104 }
105
106 static int crypt_hash_restart(struct crypt_hash *ctx)
107 {
108         if (EVP_DigestInit(&ctx->md, ctx->hash_id) != 1)
109                 return -EINVAL;
110
111         return 0;
112 }
113
114 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
115 {
116         if (EVP_DigestUpdate(&ctx->md, buffer, length) != 1)
117                 return -EINVAL;
118
119         return 0;
120 }
121
122 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
123 {
124         unsigned char tmp[EVP_MAX_MD_SIZE];
125         unsigned int tmp_len = 0;
126
127         if (length > (size_t)ctx->hash_len)
128                 return -EINVAL;
129
130         if (EVP_DigestFinal_ex(&ctx->md, tmp, &tmp_len) != 1)
131                 return -EINVAL;
132
133         memcpy(buffer, tmp, length);
134         memset(tmp, 0, sizeof(tmp));
135
136         if (tmp_len < length)
137                 return -EINVAL;
138
139         if (crypt_hash_restart(ctx))
140                 return -EINVAL;
141
142         return 0;
143 }
144
145 int crypt_hash_destroy(struct crypt_hash *ctx)
146 {
147         EVP_MD_CTX_cleanup(&ctx->md);
148         memset(ctx, 0, sizeof(*ctx));
149         free(ctx);
150         return 0;
151 }
152
153 /* HMAC */
154 int crypt_hmac_size(const char *name)
155 {
156         return crypt_hash_size(name);
157 }
158
159 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
160                     const void *buffer, size_t length)
161 {
162         struct crypt_hmac *h;
163
164         h = malloc(sizeof(*h));
165         if (!h)
166                 return -ENOMEM;
167
168         h->hash_id = EVP_get_digestbyname(name);
169         if (!h->hash_id) {
170                 free(h);
171                 return -EINVAL;
172         }
173
174         HMAC_CTX_init(&h->md);
175         HMAC_Init_ex(&h->md, buffer, length, h->hash_id, NULL);
176
177         h->hash_len = EVP_MD_size(h->hash_id);
178         *ctx = h;
179         return 0;
180 }
181
182 static void crypt_hmac_restart(struct crypt_hmac *ctx)
183 {
184         HMAC_Init_ex(&ctx->md, NULL, 0, ctx->hash_id, NULL);
185 }
186
187 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
188 {
189         HMAC_Update(&ctx->md, (const unsigned char *)buffer, length);
190         return 0;
191 }
192
193 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
194 {
195         unsigned char tmp[EVP_MAX_MD_SIZE];
196         unsigned int tmp_len = 0;
197
198         if (length > (size_t)ctx->hash_len)
199                 return -EINVAL;
200
201         HMAC_Final(&ctx->md, tmp, &tmp_len);
202
203         memcpy(buffer, tmp, length);
204         memset(tmp, 0, sizeof(tmp));
205
206         if (tmp_len < length)
207                 return -EINVAL;
208
209         crypt_hmac_restart(ctx);
210
211         return 0;
212 }
213
214 int crypt_hmac_destroy(struct crypt_hmac *ctx)
215 {
216         HMAC_CTX_cleanup(&ctx->md);
217         memset(ctx, 0, sizeof(*ctx));
218         free(ctx);
219         return 0;
220 }
221
222 /* RNG */
223 int crypt_backend_rng(char *buffer, size_t length, int quality, int fips)
224 {
225         if (fips)
226                 return -EINVAL;
227
228         if (RAND_bytes((unsigned char *)buffer, length) != 1)
229                 return -EINVAL;
230
231         return 0;
232 }
233
234 /* PBKDF */
235 int crypt_pbkdf(const char *kdf, const char *hash,
236                 const char *password, size_t password_length,
237                 const char *salt, size_t salt_length,
238                 char *key, size_t key_length,
239                 unsigned int iterations)
240 {
241         const EVP_MD *hash_id;
242
243         if (!kdf || strncmp(kdf, "pbkdf2", 6))
244                 return -EINVAL;
245
246         hash_id = EVP_get_digestbyname(hash);
247         if (!hash_id)
248                 return -EINVAL;
249
250         if (!PKCS5_PBKDF2_HMAC(password, (int)password_length,
251             (unsigned char *)salt, (int)salt_length,
252             (int)iterations, hash_id, (int)key_length, (unsigned char *)key))
253                 return -EINVAL;
254
255         return 0;
256 }