1 /*
2 * Copyright (c) 2005-2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
3 * Copyright (c) 2018 Sean Eric Fagan <sef@ixsystems.com>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * Portions of this file are derived from sys/geom/eli/g_eli_hmac.c
28 */
29
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
32
33 #include <sys/types.h>
34 #include <sys/errno.h>
35
36 #ifdef _KERNEL
37 #include <sys/libkern.h>
38 #include <sys/malloc.h>
39 #include <sys/sysctl.h>
40 #include <opencrypto/cryptodev.h>
41 #include <opencrypto/xform.h>
42 #else
43 #include <strings.h>
44 #endif
45
46 #include <sys/zio_crypt.h>
47 #include <sys/fs/zfs.h>
48 #include <sys/zio.h>
49
50 #include <sys/freebsd_crypto.h>
51
52 #define SHA512_HMAC_BLOCK_SIZE 128
53
54 static int crypt_sessions = 0;
55 SYSCTL_DECL(_vfs_zfs);
56 SYSCTL_INT(_vfs_zfs, OID_AUTO, crypt_sessions, CTLFLAG_RD,
57 &crypt_sessions, 0, "Number of cryptographic sessions created");
58
59 void
crypto_mac_init(struct hmac_ctx * ctx,const crypto_key_t * c_key)60 crypto_mac_init(struct hmac_ctx *ctx, const crypto_key_t *c_key)
61 {
62 uint8_t k_ipad[SHA512_HMAC_BLOCK_SIZE],
63 k_opad[SHA512_HMAC_BLOCK_SIZE],
64 key[SHA512_HMAC_BLOCK_SIZE];
65 SHA512_CTX lctx;
66 int i;
67 size_t cl_bytes = CRYPTO_BITS2BYTES(c_key->ck_length);
68
69 /*
70 * This code is based on the similar code in geom/eli/g_eli_hmac.c
71 */
72 explicit_bzero(key, sizeof (key));
73 if (c_key->ck_length == 0)
74 /* do nothing */;
75 else if (cl_bytes <= SHA512_HMAC_BLOCK_SIZE)
76 bcopy(c_key->ck_data, key, cl_bytes);
77 else {
78 /*
79 * If key is longer than 128 bytes reset it to
80 * key = SHA512(key).
81 */
82 SHA512_Init(&lctx);
83 SHA512_Update(&lctx, c_key->ck_data, cl_bytes);
84 SHA512_Final(key, &lctx);
85 }
86
87 /* XOR key with ipad and opad values. */
88 for (i = 0; i < sizeof (key); i++) {
89 k_ipad[i] = key[i] ^ 0x36;
90 k_opad[i] = key[i] ^ 0x5c;
91 }
92 explicit_bzero(key, sizeof (key));
93
94 /* Start inner SHA512. */
95 SHA512_Init(&ctx->innerctx);
96 SHA512_Update(&ctx->innerctx, k_ipad, sizeof (k_ipad));
97 explicit_bzero(k_ipad, sizeof (k_ipad));
98 /* Start outer SHA512. */
99 SHA512_Init(&ctx->outerctx);
100 SHA512_Update(&ctx->outerctx, k_opad, sizeof (k_opad));
101 explicit_bzero(k_opad, sizeof (k_opad));
102 }
103
104 void
crypto_mac_update(struct hmac_ctx * ctx,const void * data,size_t datasize)105 crypto_mac_update(struct hmac_ctx *ctx, const void *data, size_t datasize)
106 {
107 SHA512_Update(&ctx->innerctx, data, datasize);
108 }
109
110 void
crypto_mac_final(struct hmac_ctx * ctx,void * md,size_t mdsize)111 crypto_mac_final(struct hmac_ctx *ctx, void *md, size_t mdsize)
112 {
113 uint8_t digest[SHA512_DIGEST_LENGTH];
114
115 /* Complete inner hash */
116 SHA512_Final(digest, &ctx->innerctx);
117
118 /* Complete outer hash */
119 SHA512_Update(&ctx->outerctx, digest, sizeof (digest));
120 SHA512_Final(digest, &ctx->outerctx);
121
122 explicit_bzero(ctx, sizeof (*ctx));
123 /* mdsize == 0 means "Give me the whole hash!" */
124 if (mdsize == 0)
125 mdsize = SHA512_DIGEST_LENGTH;
126 bcopy(digest, md, mdsize);
127 explicit_bzero(digest, sizeof (digest));
128 }
129
130 void
crypto_mac(const crypto_key_t * key,const void * in_data,size_t in_data_size,void * out_data,size_t out_data_size)131 crypto_mac(const crypto_key_t *key, const void *in_data, size_t in_data_size,
132 void *out_data, size_t out_data_size)
133 {
134 struct hmac_ctx ctx;
135
136 crypto_mac_init(&ctx, key);
137 crypto_mac_update(&ctx, in_data, in_data_size);
138 crypto_mac_final(&ctx, out_data, out_data_size);
139 }
140
141 static int
freebsd_zfs_crypt_done(struct cryptop * crp)142 freebsd_zfs_crypt_done(struct cryptop *crp)
143 {
144 freebsd_crypt_session_t *ses;
145
146 ses = crp->crp_opaque;
147 mtx_lock(&ses->fs_lock);
148 ses->fs_done = true;
149 mtx_unlock(&ses->fs_lock);
150 wakeup(crp);
151 return (0);
152 }
153
154 static int
freebsd_zfs_crypt_done_sync(struct cryptop * crp)155 freebsd_zfs_crypt_done_sync(struct cryptop *crp)
156 {
157
158 return (0);
159 }
160
161 void
freebsd_crypt_freesession(freebsd_crypt_session_t * sess)162 freebsd_crypt_freesession(freebsd_crypt_session_t *sess)
163 {
164 mtx_destroy(&sess->fs_lock);
165 crypto_freesession(sess->fs_sid);
166 explicit_bzero(sess, sizeof (*sess));
167 }
168
169 static int
zfs_crypto_dispatch(freebsd_crypt_session_t * session,struct cryptop * crp)170 zfs_crypto_dispatch(freebsd_crypt_session_t *session, struct cryptop *crp)
171 {
172 int error;
173
174 crp->crp_opaque = session;
175 for (;;) {
176 #if __FreeBSD_version < 1400004
177 boolean_t async = ((crypto_ses2caps(crp->crp_session) &
178 CRYPTOCAP_F_SYNC) == 0);
179 #else
180 boolean_t async = !CRYPTO_SESS_SYNC(crp->crp_session);
181 #endif
182 crp->crp_callback = async ? freebsd_zfs_crypt_done :
183 freebsd_zfs_crypt_done_sync;
184 error = crypto_dispatch(crp);
185 if (error == 0) {
186 if (async) {
187 mtx_lock(&session->fs_lock);
188 while (session->fs_done == false) {
189 msleep(crp, &session->fs_lock, 0,
190 "zfs_crypto", 0);
191 }
192 mtx_unlock(&session->fs_lock);
193 }
194 error = crp->crp_etype;
195 }
196
197 if (error == ENOMEM) {
198 pause("zcrnomem", 1);
199 } else if (error != EAGAIN) {
200 break;
201 }
202 crp->crp_etype = 0;
203 crp->crp_flags &= ~CRYPTO_F_DONE;
204 session->fs_done = false;
205 #if __FreeBSD_version < 1300087
206 /*
207 * Session ID changed, so we should record that,
208 * and try again
209 */
210 session->fs_sid = crp->crp_session;
211 #endif
212 }
213 return (error);
214 }
215 static void
freebsd_crypt_uio_debug_log(boolean_t encrypt,freebsd_crypt_session_t * input_sessionp,struct zio_crypt_info * c_info,zfs_uio_t * data_uio,crypto_key_t * key,uint8_t * ivbuf,size_t datalen,size_t auth_len)216 freebsd_crypt_uio_debug_log(boolean_t encrypt,
217 freebsd_crypt_session_t *input_sessionp,
218 struct zio_crypt_info *c_info,
219 zfs_uio_t *data_uio,
220 crypto_key_t *key,
221 uint8_t *ivbuf,
222 size_t datalen,
223 size_t auth_len)
224 {
225 #ifdef FCRYPTO_DEBUG
226 struct cryptodesc *crd;
227 uint8_t *p = NULL;
228 size_t total = 0;
229
230 printf("%s(%s, %p, { %s, %d, %d, %s }, %p, { %d, %p, %u }, "
231 "%p, %u, %u)\n",
232 __FUNCTION__, encrypt ? "encrypt" : "decrypt", input_sessionp,
233 c_info->ci_algname, c_info->ci_crypt_type,
234 (unsigned int)c_info->ci_keylen, c_info->ci_name,
235 data_uio, key->ck_format, key->ck_data,
236 (unsigned int)key->ck_length,
237 ivbuf, (unsigned int)datalen, (unsigned int)auth_len);
238 printf("\tkey = { ");
239 for (int i = 0; i < key->ck_length / 8; i++) {
240 uint8_t *b = (uint8_t *)key->ck_data;
241 printf("%02x ", b[i]);
242 }
243 printf("}\n");
244 for (int i = 0; i < zfs_uio_iovcnt(data_uio); i++) {
245 printf("\tiovec #%d: <%p, %u>\n", i,
246 zfs_uio_iovbase(data_uio, i),
247 (unsigned int)zfs_uio_iovlen(data_uio, i));
248 total += zfs_uio_iovlen(data_uio, i);
249 }
250 zfs_uio_resid(data_uio) = total;
251 #endif
252 }
253 /*
254 * Create a new cryptographic session. This should
255 * happen every time the key changes (including when
256 * it's first loaded).
257 */
258 #if __FreeBSD_version >= 1300087
259 int
freebsd_crypt_newsession(freebsd_crypt_session_t * sessp,struct zio_crypt_info * c_info,crypto_key_t * key)260 freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
261 struct zio_crypt_info *c_info, crypto_key_t *key)
262 {
263 struct crypto_session_params csp;
264 int error = 0;
265
266 #ifdef FCRYPTO_DEBUG
267 printf("%s(%p, { %s, %d, %d, %s }, { %d, %p, %u })\n",
268 __FUNCTION__, sessp,
269 c_info->ci_algname, c_info->ci_crypt_type,
270 (unsigned int)c_info->ci_keylen, c_info->ci_name,
271 key->ck_format, key->ck_data, (unsigned int)key->ck_length);
272 printf("\tkey = { ");
273 for (int i = 0; i < key->ck_length / 8; i++) {
274 uint8_t *b = (uint8_t *)key->ck_data;
275 printf("%02x ", b[i]);
276 }
277 printf("}\n");
278 #endif
279 bzero(&csp, sizeof (csp));
280 csp.csp_mode = CSP_MODE_AEAD;
281 csp.csp_cipher_key = key->ck_data;
282 csp.csp_cipher_klen = key->ck_length / 8;
283 switch (c_info->ci_crypt_type) {
284 case ZC_TYPE_GCM:
285 csp.csp_cipher_alg = CRYPTO_AES_NIST_GCM_16;
286 csp.csp_ivlen = AES_GCM_IV_LEN;
287 switch (key->ck_length/8) {
288 case AES_128_GMAC_KEY_LEN:
289 case AES_192_GMAC_KEY_LEN:
290 case AES_256_GMAC_KEY_LEN:
291 break;
292 default:
293 error = EINVAL;
294 goto bad;
295 }
296 break;
297 case ZC_TYPE_CCM:
298 csp.csp_cipher_alg = CRYPTO_AES_CCM_16;
299 csp.csp_ivlen = AES_CCM_IV_LEN;
300 switch (key->ck_length/8) {
301 case AES_128_CBC_MAC_KEY_LEN:
302 case AES_192_CBC_MAC_KEY_LEN:
303 case AES_256_CBC_MAC_KEY_LEN:
304 break;
305 default:
306 error = EINVAL;
307 goto bad;
308 break;
309 }
310 break;
311 default:
312 error = ENOTSUP;
313 goto bad;
314 }
315
316 /*
317 * Disable the use of hardware drivers on FreeBSD 13 and later since
318 * common crypto offload drivers impose constraints on AES-GCM AAD
319 * lengths that make them unusable for ZFS, and we currently do not have
320 * a mechanism to fall back to a software driver for requests not
321 * handled by a hardware driver.
322 *
323 * On 12 we continue to permit the use of hardware drivers since
324 * CPU-accelerated drivers such as aesni(4) register themselves as
325 * hardware drivers.
326 */
327 error = crypto_newsession(&sessp->fs_sid, &csp, CRYPTOCAP_F_SOFTWARE);
328 mtx_init(&sessp->fs_lock, "FreeBSD Cryptographic Session Lock",
329 NULL, MTX_DEF);
330 crypt_sessions++;
331 bad:
332 #ifdef FCRYPTO_DEBUG
333 if (error)
334 printf("%s: returning error %d\n", __FUNCTION__, error);
335 #endif
336 return (error);
337 }
338
339 int
freebsd_crypt_uio(boolean_t encrypt,freebsd_crypt_session_t * input_sessionp,struct zio_crypt_info * c_info,zfs_uio_t * data_uio,crypto_key_t * key,uint8_t * ivbuf,size_t datalen,size_t auth_len)340 freebsd_crypt_uio(boolean_t encrypt,
341 freebsd_crypt_session_t *input_sessionp,
342 struct zio_crypt_info *c_info,
343 zfs_uio_t *data_uio,
344 crypto_key_t *key,
345 uint8_t *ivbuf,
346 size_t datalen,
347 size_t auth_len)
348 {
349 struct cryptop *crp;
350 freebsd_crypt_session_t *session = NULL;
351 int error = 0;
352 size_t total = 0;
353
354 freebsd_crypt_uio_debug_log(encrypt, input_sessionp, c_info, data_uio,
355 key, ivbuf, datalen, auth_len);
356 for (int i = 0; i < zfs_uio_iovcnt(data_uio); i++)
357 total += zfs_uio_iovlen(data_uio, i);
358 zfs_uio_resid(data_uio) = total;
359 if (input_sessionp == NULL) {
360 session = kmem_zalloc(sizeof (*session), KM_SLEEP);
361 error = freebsd_crypt_newsession(session, c_info, key);
362 if (error)
363 goto out;
364 } else
365 session = input_sessionp;
366
367 crp = crypto_getreq(session->fs_sid, M_WAITOK);
368 if (encrypt) {
369 crp->crp_op = CRYPTO_OP_ENCRYPT |
370 CRYPTO_OP_COMPUTE_DIGEST;
371 } else {
372 crp->crp_op = CRYPTO_OP_DECRYPT |
373 CRYPTO_OP_VERIFY_DIGEST;
374 }
375 crp->crp_flags = CRYPTO_F_CBIFSYNC | CRYPTO_F_IV_SEPARATE;
376 crypto_use_uio(crp, GET_UIO_STRUCT(data_uio));
377
378 crp->crp_aad_start = 0;
379 crp->crp_aad_length = auth_len;
380 crp->crp_payload_start = auth_len;
381 crp->crp_payload_length = datalen;
382 crp->crp_digest_start = auth_len + datalen;
383
384 bcopy(ivbuf, crp->crp_iv, ZIO_DATA_IV_LEN);
385 error = zfs_crypto_dispatch(session, crp);
386 crypto_freereq(crp);
387 out:
388 #ifdef FCRYPTO_DEBUG
389 if (error)
390 printf("%s: returning error %d\n", __FUNCTION__, error);
391 #endif
392 if (input_sessionp == NULL) {
393 freebsd_crypt_freesession(session);
394 kmem_free(session, sizeof (*session));
395 }
396 return (error);
397 }
398
399 #else
400 int
freebsd_crypt_newsession(freebsd_crypt_session_t * sessp,struct zio_crypt_info * c_info,crypto_key_t * key)401 freebsd_crypt_newsession(freebsd_crypt_session_t *sessp,
402 struct zio_crypt_info *c_info, crypto_key_t *key)
403 {
404 struct cryptoini cria, crie, *crip;
405 struct enc_xform *xform;
406 struct auth_hash *xauth;
407 int error = 0;
408 crypto_session_t sid;
409
410 #ifdef FCRYPTO_DEBUG
411 printf("%s(%p, { %s, %d, %d, %s }, { %d, %p, %u })\n",
412 __FUNCTION__, sessp,
413 c_info->ci_algname, c_info->ci_crypt_type,
414 (unsigned int)c_info->ci_keylen, c_info->ci_name,
415 key->ck_format, key->ck_data, (unsigned int)key->ck_length);
416 printf("\tkey = { ");
417 for (int i = 0; i < key->ck_length / 8; i++) {
418 uint8_t *b = (uint8_t *)key->ck_data;
419 printf("%02x ", b[i]);
420 }
421 printf("}\n");
422 #endif
423 switch (c_info->ci_crypt_type) {
424 case ZC_TYPE_GCM:
425 xform = &enc_xform_aes_nist_gcm;
426 switch (key->ck_length/8) {
427 case AES_128_GMAC_KEY_LEN:
428 xauth = &auth_hash_nist_gmac_aes_128;
429 break;
430 case AES_192_GMAC_KEY_LEN:
431 xauth = &auth_hash_nist_gmac_aes_192;
432 break;
433 case AES_256_GMAC_KEY_LEN:
434 xauth = &auth_hash_nist_gmac_aes_256;
435 break;
436 default:
437 error = EINVAL;
438 goto bad;
439 }
440 break;
441 case ZC_TYPE_CCM:
442 xform = &enc_xform_ccm;
443 switch (key->ck_length/8) {
444 case AES_128_CBC_MAC_KEY_LEN:
445 xauth = &auth_hash_ccm_cbc_mac_128;
446 break;
447 case AES_192_CBC_MAC_KEY_LEN:
448 xauth = &auth_hash_ccm_cbc_mac_192;
449 break;
450 case AES_256_CBC_MAC_KEY_LEN:
451 xauth = &auth_hash_ccm_cbc_mac_256;
452 break;
453 default:
454 error = EINVAL;
455 goto bad;
456 break;
457 }
458 break;
459 default:
460 error = ENOTSUP;
461 goto bad;
462 }
463 #ifdef FCRYPTO_DEBUG
464 printf("%s(%d): Using crypt %s (key length %u [%u bytes]), "
465 "auth %s (key length %d)\n",
466 __FUNCTION__, __LINE__,
467 xform->name, (unsigned int)key->ck_length,
468 (unsigned int)key->ck_length/8,
469 xauth->name, xauth->keysize);
470 #endif
471
472 bzero(&crie, sizeof (crie));
473 bzero(&cria, sizeof (cria));
474
475 crie.cri_alg = xform->type;
476 crie.cri_key = key->ck_data;
477 crie.cri_klen = key->ck_length;
478
479 cria.cri_alg = xauth->type;
480 cria.cri_key = key->ck_data;
481 cria.cri_klen = key->ck_length;
482
483 cria.cri_next = &crie;
484 crie.cri_next = NULL;
485 crip = &cria;
486 // Everything else is bzero'd
487
488 error = crypto_newsession(&sid, crip,
489 CRYPTOCAP_F_HARDWARE | CRYPTOCAP_F_SOFTWARE);
490 if (error != 0) {
491 printf("%s(%d): crypto_newsession failed with %d\n",
492 __FUNCTION__, __LINE__, error);
493 goto bad;
494 }
495 sessp->fs_sid = sid;
496 mtx_init(&sessp->fs_lock, "FreeBSD Cryptographic Session Lock",
497 NULL, MTX_DEF);
498 crypt_sessions++;
499 bad:
500 return (error);
501 }
502
503 /*
504 * The meat of encryption/decryption.
505 * If sessp is NULL, then it will create a
506 * temporary cryptographic session, and release
507 * it when done.
508 */
509 int
freebsd_crypt_uio(boolean_t encrypt,freebsd_crypt_session_t * input_sessionp,struct zio_crypt_info * c_info,zfs_uio_t * data_uio,crypto_key_t * key,uint8_t * ivbuf,size_t datalen,size_t auth_len)510 freebsd_crypt_uio(boolean_t encrypt,
511 freebsd_crypt_session_t *input_sessionp,
512 struct zio_crypt_info *c_info,
513 zfs_uio_t *data_uio,
514 crypto_key_t *key,
515 uint8_t *ivbuf,
516 size_t datalen,
517 size_t auth_len)
518 {
519 struct cryptop *crp;
520 struct cryptodesc *enc_desc, *auth_desc;
521 struct enc_xform *xform;
522 struct auth_hash *xauth;
523 freebsd_crypt_session_t *session = NULL;
524 int error;
525
526 freebsd_crypt_uio_debug_log(encrypt, input_sessionp, c_info, data_uio,
527 key, ivbuf, datalen, auth_len);
528 switch (c_info->ci_crypt_type) {
529 case ZC_TYPE_GCM:
530 xform = &enc_xform_aes_nist_gcm;
531 switch (key->ck_length/8) {
532 case AES_128_GMAC_KEY_LEN:
533 xauth = &auth_hash_nist_gmac_aes_128;
534 break;
535 case AES_192_GMAC_KEY_LEN:
536 xauth = &auth_hash_nist_gmac_aes_192;
537 break;
538 case AES_256_GMAC_KEY_LEN:
539 xauth = &auth_hash_nist_gmac_aes_256;
540 break;
541 default:
542 error = EINVAL;
543 goto bad;
544 }
545 break;
546 case ZC_TYPE_CCM:
547 xform = &enc_xform_ccm;
548 switch (key->ck_length/8) {
549 case AES_128_CBC_MAC_KEY_LEN:
550 xauth = &auth_hash_ccm_cbc_mac_128;
551 break;
552 case AES_192_CBC_MAC_KEY_LEN:
553 xauth = &auth_hash_ccm_cbc_mac_192;
554 break;
555 case AES_256_CBC_MAC_KEY_LEN:
556 xauth = &auth_hash_ccm_cbc_mac_256;
557 break;
558 default:
559 error = EINVAL;
560 goto bad;
561 break;
562 }
563 break;
564 default:
565 error = ENOTSUP;
566 goto bad;
567 }
568
569 #ifdef FCRYPTO_DEBUG
570 printf("%s(%d): Using crypt %s (key length %u [%u bytes]), "
571 "auth %s (key length %d)\n",
572 __FUNCTION__, __LINE__,
573 xform->name, (unsigned int)key->ck_length,
574 (unsigned int)key->ck_length/8,
575 xauth->name, xauth->keysize);
576 #endif
577
578 if (input_sessionp == NULL) {
579 session = kmem_zalloc(sizeof (*session), KM_SLEEP);
580 error = freebsd_crypt_newsession(session, c_info, key);
581 if (error)
582 goto out;
583 } else
584 session = input_sessionp;
585
586 crp = crypto_getreq(2);
587 if (crp == NULL) {
588 error = ENOMEM;
589 goto bad;
590 }
591
592 auth_desc = crp->crp_desc;
593 enc_desc = auth_desc->crd_next;
594
595 crp->crp_session = session->fs_sid;
596 crp->crp_ilen = auth_len + datalen;
597 crp->crp_buf = (void*)GET_UIO_STRUCT(data_uio);
598 crp->crp_flags = CRYPTO_F_IOV | CRYPTO_F_CBIFSYNC;
599
600 auth_desc->crd_skip = 0;
601 auth_desc->crd_len = auth_len;
602 auth_desc->crd_inject = auth_len + datalen;
603 auth_desc->crd_alg = xauth->type;
604 #ifdef FCRYPTO_DEBUG
605 printf("%s: auth: skip = %u, len = %u, inject = %u\n",
606 __FUNCTION__, auth_desc->crd_skip, auth_desc->crd_len,
607 auth_desc->crd_inject);
608 #endif
609
610 enc_desc->crd_skip = auth_len;
611 enc_desc->crd_len = datalen;
612 enc_desc->crd_inject = auth_len;
613 enc_desc->crd_alg = xform->type;
614 enc_desc->crd_flags = CRD_F_IV_EXPLICIT | CRD_F_IV_PRESENT;
615 bcopy(ivbuf, enc_desc->crd_iv, ZIO_DATA_IV_LEN);
616 enc_desc->crd_next = NULL;
617
618 #ifdef FCRYPTO_DEBUG
619 printf("%s: enc: skip = %u, len = %u, inject = %u\n",
620 __FUNCTION__, enc_desc->crd_skip, enc_desc->crd_len,
621 enc_desc->crd_inject);
622 #endif
623
624 if (encrypt)
625 enc_desc->crd_flags |= CRD_F_ENCRYPT;
626
627 error = zfs_crypto_dispatch(session, crp);
628 crypto_freereq(crp);
629 out:
630 if (input_sessionp == NULL) {
631 freebsd_crypt_freesession(session);
632 kmem_free(session, sizeof (*session));
633 }
634 bad:
635 #ifdef FCRYPTO_DEBUG
636 if (error)
637 printf("%s: returning error %d\n", __FUNCTION__, error);
638 #endif
639 return (error);
640 }
641 #endif
642