]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/geom/eli/g_eli_crypto.c
Add the llvm-cov and llvm-profdata tools, when WITH_CLANG_EXTRAS is
[FreeBSD/FreeBSD.git] / sys / geom / eli / g_eli_crypto.c
1 /*-
2  * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include <sys/param.h>
31 #ifdef _KERNEL
32 #include <sys/systm.h>
33 #include <sys/kernel.h>
34 #include <sys/malloc.h>
35 #else
36 #include <stdint.h>
37 #include <string.h>
38 #include <strings.h>
39 #include <errno.h>
40 #include <assert.h>
41 #include <openssl/evp.h>
42 #define _OpenSSL_
43 #endif
44 #include <geom/eli/g_eli.h>
45
46 #ifdef _KERNEL
47 MALLOC_DECLARE(M_ELI);
48
49 static int
50 g_eli_crypto_done(struct cryptop *crp)
51 {
52
53         crp->crp_opaque = (void *)crp;
54         wakeup(crp);
55         return (0);
56 }
57
58 static int
59 g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
60     const u_char *key, size_t keysize)
61 {
62         struct cryptoini cri;
63         struct cryptop *crp;
64         struct cryptodesc *crd;
65         uint64_t sid;
66         u_char *p;
67         int error;
68
69         KASSERT(algo != CRYPTO_AES_XTS,
70             ("%s: CRYPTO_AES_XTS unexpected here", __func__));
71
72         bzero(&cri, sizeof(cri));
73         cri.cri_alg = algo;
74         cri.cri_key = __DECONST(void *, key);
75         cri.cri_klen = keysize;
76         error = crypto_newsession(&sid, &cri, CRYPTOCAP_F_SOFTWARE);
77         if (error != 0)
78                 return (error);
79         p = malloc(sizeof(*crp) + sizeof(*crd), M_ELI, M_NOWAIT | M_ZERO);
80         if (p == NULL) {
81                 crypto_freesession(sid);
82                 return (ENOMEM);
83         }
84         crp = (struct cryptop *)p;      p += sizeof(*crp);
85         crd = (struct cryptodesc *)p;   p += sizeof(*crd);
86
87         crd->crd_skip = 0;
88         crd->crd_len = datasize;
89         crd->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
90         if (enc)
91                 crd->crd_flags |= CRD_F_ENCRYPT;
92         crd->crd_alg = algo;
93         crd->crd_key = __DECONST(void *, key);
94         crd->crd_klen = keysize;
95         bzero(crd->crd_iv, sizeof(crd->crd_iv));
96         crd->crd_next = NULL;
97
98         crp->crp_sid = sid;
99         crp->crp_ilen = datasize;
100         crp->crp_olen = datasize;
101         crp->crp_opaque = NULL;
102         crp->crp_callback = g_eli_crypto_done;
103         crp->crp_buf = (void *)data;
104         crp->crp_flags = CRYPTO_F_CBIFSYNC;
105         crp->crp_desc = crd;
106
107         error = crypto_dispatch(crp);
108         if (error == 0) {
109                 while (crp->crp_opaque == NULL)
110                         tsleep(crp, PRIBIO, "geli", hz / 5);
111                 error = crp->crp_etype;
112         }
113
114         free(crp, M_ELI);
115         crypto_freesession(sid);
116         return (error);
117 }
118 #else   /* !_KERNEL */
119 static int
120 g_eli_crypto_cipher(u_int algo, int enc, u_char *data, size_t datasize,
121     const u_char *key, size_t keysize)
122 {
123         EVP_CIPHER_CTX ctx;
124         const EVP_CIPHER *type;
125         u_char iv[keysize];
126         int outsize;
127
128         assert(algo != CRYPTO_AES_XTS);
129
130         switch (algo) {
131         case CRYPTO_NULL_CBC:
132                 type = EVP_enc_null();
133                 break;
134         case CRYPTO_AES_CBC:
135                 switch (keysize) {
136                 case 128:
137                         type = EVP_aes_128_cbc();
138                         break;
139                 case 192:
140                         type = EVP_aes_192_cbc();
141                         break;
142                 case 256:
143                         type = EVP_aes_256_cbc();
144                         break;
145                 default:
146                         return (EINVAL);
147                 }
148                 break;
149         case CRYPTO_BLF_CBC:
150                 type = EVP_bf_cbc();
151                 break;
152 #ifndef OPENSSL_NO_CAMELLIA
153         case CRYPTO_CAMELLIA_CBC:
154                 switch (keysize) {
155                 case 128:
156                         type = EVP_camellia_128_cbc();
157                         break;
158                 case 192:
159                         type = EVP_camellia_192_cbc();
160                         break;
161                 case 256:
162                         type = EVP_camellia_256_cbc();
163                         break;
164                 default:
165                         return (EINVAL);
166                 }
167                 break;
168 #endif
169         case CRYPTO_3DES_CBC:
170                 type = EVP_des_ede3_cbc();
171                 break;
172         default:
173                 return (EINVAL);
174         }
175
176         EVP_CIPHER_CTX_init(&ctx);
177
178         EVP_CipherInit_ex(&ctx, type, NULL, NULL, NULL, enc);
179         EVP_CIPHER_CTX_set_key_length(&ctx, keysize / 8);
180         EVP_CIPHER_CTX_set_padding(&ctx, 0);
181         bzero(iv, sizeof(iv));
182         EVP_CipherInit_ex(&ctx, NULL, NULL, key, iv, enc);
183
184         if (EVP_CipherUpdate(&ctx, data, &outsize, data, datasize) == 0) {
185                 EVP_CIPHER_CTX_cleanup(&ctx);
186                 return (EINVAL);
187         }
188         assert(outsize == (int)datasize);
189
190         if (EVP_CipherFinal_ex(&ctx, data + outsize, &outsize) == 0) {
191                 EVP_CIPHER_CTX_cleanup(&ctx);
192                 return (EINVAL);
193         }
194         assert(outsize == 0);
195
196         EVP_CIPHER_CTX_cleanup(&ctx);
197         return (0);
198 }
199 #endif  /* !_KERNEL */
200
201 int
202 g_eli_crypto_encrypt(u_int algo, u_char *data, size_t datasize,
203     const u_char *key, size_t keysize)
204 {
205
206         /* We prefer AES-CBC for metadata protection. */
207         if (algo == CRYPTO_AES_XTS)
208                 algo = CRYPTO_AES_CBC;
209
210         return (g_eli_crypto_cipher(algo, 1, data, datasize, key, keysize));
211 }
212
213 int
214 g_eli_crypto_decrypt(u_int algo, u_char *data, size_t datasize,
215     const u_char *key, size_t keysize)
216 {
217
218         /* We prefer AES-CBC for metadata protection. */
219         if (algo == CRYPTO_AES_XTS)
220                 algo = CRYPTO_AES_CBC;
221
222         return (g_eli_crypto_cipher(algo, 0, data, datasize, key, keysize));
223 }
224
225 void
226 g_eli_crypto_hmac_init(struct hmac_ctx *ctx, const uint8_t *hkey,
227     size_t hkeylen)
228 {
229         u_char k_ipad[128], key[128];
230         SHA512_CTX lctx;
231         u_int i;
232
233         bzero(key, sizeof(key));
234         if (hkeylen == 0)
235                 ; /* do nothing */
236         else if (hkeylen <= 128)
237                 bcopy(hkey, key, hkeylen);
238         else {
239                 /* If key is longer than 128 bytes reset it to key = SHA512(key). */
240                 SHA512_Init(&lctx);
241                 SHA512_Update(&lctx, hkey, hkeylen);
242                 SHA512_Final(key, &lctx);
243         }
244
245         /* XOR key with ipad and opad values. */
246         for (i = 0; i < sizeof(key); i++) {
247                 k_ipad[i] = key[i] ^ 0x36;
248                 ctx->k_opad[i] = key[i] ^ 0x5c;
249         }
250         bzero(key, sizeof(key));
251         /* Perform inner SHA512. */
252         SHA512_Init(&ctx->shactx);
253         SHA512_Update(&ctx->shactx, k_ipad, sizeof(k_ipad));
254         bzero(k_ipad, sizeof(k_ipad));
255 }
256
257 void
258 g_eli_crypto_hmac_update(struct hmac_ctx *ctx, const uint8_t *data,
259     size_t datasize)
260 {
261
262         SHA512_Update(&ctx->shactx, data, datasize);
263 }
264
265 void
266 g_eli_crypto_hmac_final(struct hmac_ctx *ctx, uint8_t *md, size_t mdsize)
267 {
268         u_char digest[SHA512_MDLEN];
269         SHA512_CTX lctx;
270
271         SHA512_Final(digest, &ctx->shactx);
272         /* Perform outer SHA512. */
273         SHA512_Init(&lctx);
274         SHA512_Update(&lctx, ctx->k_opad, sizeof(ctx->k_opad));
275         bzero(ctx, sizeof(*ctx));
276         SHA512_Update(&lctx, digest, sizeof(digest));
277         SHA512_Final(digest, &lctx);
278         bzero(&lctx, sizeof(lctx));
279         /* mdsize == 0 means "Give me the whole hash!" */
280         if (mdsize == 0)
281                 mdsize = SHA512_MDLEN;
282         bcopy(digest, md, mdsize);
283         bzero(digest, sizeof(digest));
284 }
285
286 void
287 g_eli_crypto_hmac(const uint8_t *hkey, size_t hkeysize, const uint8_t *data,
288     size_t datasize, uint8_t *md, size_t mdsize)
289 {
290         struct hmac_ctx ctx;
291
292         g_eli_crypto_hmac_init(&ctx, hkey, hkeysize);
293         g_eli_crypto_hmac_update(&ctx, data, datasize);
294         g_eli_crypto_hmac_final(&ctx, md, mdsize);
295 }