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