Fix FSF address in license text according to
[platform/upstream/cryptsetup.git] / lib / crypto_backend / crypto_openssl.c
1 /*
2  * OPENSSL crypto backend implementation
3  *
4  * Copyright (C) 2010-2011, 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         log_dbg("OpenSSL crypto backend initialized.");
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 /* HASH */
67 int crypt_hash_size(const char *name)
68 {
69         const EVP_MD *hash_id = EVP_get_digestbyname(name);
70
71         if (!hash_id)
72                 return -EINVAL;
73
74         return EVP_MD_size(hash_id);
75 }
76
77 int crypt_hash_init(struct crypt_hash **ctx, const char *name)
78 {
79         struct crypt_hash *h;
80
81         h = malloc(sizeof(*h));
82         if (!h)
83                 return -ENOMEM;
84
85         h->hash_id = EVP_get_digestbyname(name);
86         if (!h->hash_id) {
87                 free(h);
88                 return -EINVAL;
89         }
90
91         if (EVP_DigestInit(&h->md, h->hash_id) != 1) {
92                 free(h);
93                 return -EINVAL;
94         }
95
96         h->hash_len = EVP_MD_size(h->hash_id);
97         *ctx = h;
98         return 0;
99 }
100
101 static int crypt_hash_restart(struct crypt_hash *ctx)
102 {
103         if (EVP_DigestInit(&ctx->md, ctx->hash_id) != 1)
104                 return -EINVAL;
105
106         return 0;
107 }
108
109 int crypt_hash_write(struct crypt_hash *ctx, const char *buffer, size_t length)
110 {
111         if (EVP_DigestUpdate(&ctx->md, buffer, length) != 1)
112                 return -EINVAL;
113
114         return 0;
115 }
116
117 int crypt_hash_final(struct crypt_hash *ctx, char *buffer, size_t length)
118 {
119         unsigned char tmp[EVP_MAX_MD_SIZE];
120         unsigned int tmp_len = 0;
121
122         if (length > (size_t)ctx->hash_len)
123                 return -EINVAL;
124
125         if (EVP_DigestFinal_ex(&ctx->md, tmp, &tmp_len) != 1)
126                 return -EINVAL;
127
128         memcpy(buffer, tmp, length);
129         memset(tmp, 0, sizeof(tmp));
130
131         if (tmp_len < length)
132                 return -EINVAL;
133
134         if (crypt_hash_restart(ctx))
135                 return -EINVAL;
136
137         return 0;
138 }
139
140 int crypt_hash_destroy(struct crypt_hash *ctx)
141 {
142         EVP_MD_CTX_cleanup(&ctx->md);
143         memset(ctx, 0, sizeof(*ctx));
144         free(ctx);
145         return 0;
146 }
147
148 /* HMAC */
149 int crypt_hmac_size(const char *name)
150 {
151         return crypt_hash_size(name);
152 }
153
154 int crypt_hmac_init(struct crypt_hmac **ctx, const char *name,
155                     const void *buffer, size_t length)
156 {
157         struct crypt_hmac *h;
158
159         h = malloc(sizeof(*h));
160         if (!h)
161                 return -ENOMEM;
162
163         h->hash_id = EVP_get_digestbyname(name);
164         if (!h->hash_id) {
165                 free(h);
166                 return -EINVAL;
167         }
168
169         HMAC_CTX_init(&h->md);
170         HMAC_Init_ex(&h->md, buffer, length, h->hash_id, NULL);
171
172         h->hash_len = EVP_MD_size(h->hash_id);
173         *ctx = h;
174         return 0;
175 }
176
177 static void crypt_hmac_restart(struct crypt_hmac *ctx)
178 {
179         HMAC_Init_ex(&ctx->md, NULL, 0, ctx->hash_id, NULL);
180 }
181
182 int crypt_hmac_write(struct crypt_hmac *ctx, const char *buffer, size_t length)
183 {
184         HMAC_Update(&ctx->md, (const unsigned char *)buffer, length);
185         return 0;
186 }
187
188 int crypt_hmac_final(struct crypt_hmac *ctx, char *buffer, size_t length)
189 {
190         unsigned char tmp[EVP_MAX_MD_SIZE];
191         unsigned int tmp_len = 0;
192
193         if (length > (size_t)ctx->hash_len)
194                 return -EINVAL;
195
196         HMAC_Final(&ctx->md, tmp, &tmp_len);
197
198         memcpy(buffer, tmp, length);
199         memset(tmp, 0, sizeof(tmp));
200
201         if (tmp_len < length)
202                 return -EINVAL;
203
204         crypt_hmac_restart(ctx);
205
206         return 0;
207 }
208
209 int crypt_hmac_destroy(struct crypt_hmac *ctx)
210 {
211         HMAC_CTX_cleanup(&ctx->md);
212         memset(ctx, 0, sizeof(*ctx));
213         free(ctx);
214         return 0;
215 }