Add version string to crypto backend.
[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 "crypto_backend.h"
34
35 static int crypto_backend_initialised = 0;
36
37 struct crypt_hash {
38         EVP_MD_CTX md;
39         const EVP_MD *hash_id;
40         int hash_len;
41 };
42
43 struct crypt_hmac {
44         HMAC_CTX md;
45         const EVP_MD *hash_id;
46         int hash_len;
47 };
48
49 int crypt_backend_init(struct crypt_device *ctx)
50 {
51         if (crypto_backend_initialised)
52                 return 0;
53
54         OpenSSL_add_all_digests();
55
56         crypto_backend_initialised = 1;
57         return 0;
58 }
59
60 uint32_t crypt_backend_flags(void)
61 {
62         return 0;
63 }
64
65 const char *crypt_backend_version(void)
66 {
67         return SSLeay_version(SSLEAY_VERSION);
68 }
69
70 /* HASH */
71 int crypt_hash_size(const char *name)
72 {
73         const EVP_MD *hash_id = EVP_get_digestbyname(name);
74
75         if (!hash_id)
76                 return -EINVAL;
77
78         return EVP_MD_size(hash_id);
79 }
80
81 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
82 {
83         struct crypt_hash *h;
84
85         h = malloc(sizeof(*h));
86         if (!h)
87                 return -ENOMEM;
88
89         h->hash_id = EVP_get_digestbyname(name);
90         if (!h->hash_id) {
91                 free(h);
92                 return -EINVAL;
93         }
94
95         if (EVP_DigestInit(&h->md, h->hash_id) != 1) {
96                 free(h);
97                 return -EINVAL;
98         }
99
100         h->hash_len = EVP_MD_size(h->hash_id);
101         *ctx = h;
102         return 0;
103 }
104
105 static int crypt_hash_restart(struct crypt_hash *ctx)
106 {
107         if (EVP_DigestInit(&ctx->md, ctx->hash_id) != 1)
108                 return -EINVAL;
109
110         return 0;
111 }
112
113 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
114 {
115         if (EVP_DigestUpdate(&ctx->md, buffer, length) != 1)
116                 return -EINVAL;
117
118         return 0;
119 }
120
121 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
122 {
123         unsigned char tmp[EVP_MAX_MD_SIZE];
124         unsigned int tmp_len = 0;
125
126         if (length > (size_t)ctx->hash_len)
127                 return -EINVAL;
128
129         if (EVP_DigestFinal_ex(&ctx->md, tmp, &tmp_len) != 1)
130                 return -EINVAL;
131
132         memcpy(buffer, tmp, length);
133         memset(tmp, 0, sizeof(tmp));
134
135         if (tmp_len < length)
136                 return -EINVAL;
137
138         if (crypt_hash_restart(ctx))
139                 return -EINVAL;
140
141         return 0;
142 }
143
144 int crypt_hash_destroy(struct crypt_hash *ctx)
145 {
146         EVP_MD_CTX_cleanup(&ctx->md);
147         memset(ctx, 0, sizeof(*ctx));
148         free(ctx);
149         return 0;
150 }
151
152 /* HMAC */
153 int crypt_hmac_size(const char *name)
154 {
155         return crypt_hash_size(name);
156 }
157
158 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
159                     const void *buffer, size_t length)
160 {
161         struct crypt_hmac *h;
162
163         h = malloc(sizeof(*h));
164         if (!h)
165                 return -ENOMEM;
166
167         h->hash_id = EVP_get_digestbyname(name);
168         if (!h->hash_id) {
169                 free(h);
170                 return -EINVAL;
171         }
172
173         HMAC_CTX_init(&h->md);
174         HMAC_Init_ex(&h->md, buffer, length, h->hash_id, NULL);
175
176         h->hash_len = EVP_MD_size(h->hash_id);
177         *ctx = h;
178         return 0;
179 }
180
181 static void crypt_hmac_restart(struct crypt_hmac *ctx)
182 {
183         HMAC_Init_ex(&ctx->md, NULL, 0, ctx->hash_id, NULL);
184 }
185
186 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
187 {
188         HMAC_Update(&ctx->md, (const unsigned char *)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 tmp[EVP_MAX_MD_SIZE];
195         unsigned int tmp_len = 0;
196
197         if (length > (size_t)ctx->hash_len)
198                 return -EINVAL;
199
200         HMAC_Final(&ctx->md, tmp, &tmp_len);
201
202         memcpy(buffer, tmp, length);
203         memset(tmp, 0, sizeof(tmp));
204
205         if (tmp_len < length)
206                 return -EINVAL;
207
208         crypt_hmac_restart(ctx);
209
210         return 0;
211 }
212
213 int crypt_hmac_destroy(struct crypt_hmac *ctx)
214 {
215         HMAC_CTX_cleanup(&ctx->md);
216         memset(ctx, 0, sizeof(*ctx));
217         free(ctx);
218         return 0;
219 }
220
221 /* RNG - N/A */
222 int crypt_backend_fips_rng(char *buffer, size_t length, int quality)
223 {
224         return -EINVAL;
225 }