xref: /titanic_52/usr/src/uts/common/crypto/io/blowfish.c (revision bdfc6d18da790deeec2e0eb09c625902defe2498)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Blowfish provider for the Kernel Cryptographic Framework (KCF)
31  */
32 
33 #include <sys/types.h>
34 #include <sys/systm.h>
35 #include <sys/modctl.h>
36 #include <sys/cmn_err.h>
37 #include <sys/ddi.h>
38 #include <sys/crypto/common.h>
39 #include <sys/crypto/spi.h>
40 #include <sys/sysmacros.h>
41 #include <sys/strsun.h>
42 #include <sys/note.h>
43 #include <blowfish_impl.h>
44 
45 extern struct mod_ops mod_cryptoops;
46 
47 /*
48  * Module linkage information for the kernel.
49  */
50 static struct modlcrypto modlcrypto = {
51 	&mod_cryptoops,
52 	"Blowfish Kernel SW Provider %I%"
53 };
54 
55 static struct modlinkage modlinkage = {
56 	MODREV_1,
57 	(void *)&modlcrypto,
58 	NULL
59 };
60 
61 /*
62  * CSPI information (entry points, provider info, etc.)
63  */
64 typedef enum blowfish_mech_type {
65 	BF_ECB_MECH_INFO_TYPE,		/* SUN_CKM_BF_ECB */
66 	BF_CBC_MECH_INFO_TYPE		/* SUN_CKM_BF_CBC */
67 } blowfish_mech_type_t;
68 
69 /*
70  * bc_keysched:		Pointer to key schedule.
71  *
72  * bc_keysched_len:	Length of the key schedule.
73  *
74  * bc_remainder:	This is for residual data, i.e. data that can't
75  *			be processed because there are too few bytes.
76  *			Must wait until more data arrives.
77  *
78  * bc_remainder_len:	Number of bytes in bc_remainder.
79  *
80  * bc_iv:		Scratch buffer that sometimes contains the IV.
81  *
82  * bc_lastblock:	Scratch buffer.
83  *
84  * bc_lastp:		Pointer to previous block of ciphertext.
85  *
86  * bc_copy_to:		Pointer to where encrypted residual data needs
87  *			to be copied.
88  *
89  * bc_flags:		BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE
90  *			When a context is freed, it is necessary
91  *			to know whether the key schedule was allocated
92  *			by the caller, or by blowfish_common_init().
93  *			If allocated by the latter, then it needs to be freed.
94  *
95  *			BLOWFISH_CBC_MODE
96  *			If flag is not set, the mode is BLOWFISH_ECB_MODE.
97  *
98  */
99 typedef struct blowfish_ctx {
100 	void *bc_keysched;
101 	size_t bc_keysched_len;
102 	uint64_t bc_iv;
103 	uint64_t bc_lastblock;
104 	uint64_t bc_remainder;
105 	size_t bc_remainder_len;
106 	uint8_t *bc_lastp;
107 	uint8_t *bc_copy_to;
108 	uint32_t bc_flags;
109 } blowfish_ctx_t;
110 
111 #define	BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE	0x00000001
112 #define	BLOWFISH_CBC_MODE			0x00000002
113 
114 #define	BLOWFISH_COPY_BLOCK(src, dst) \
115 	(dst)[0] = (src)[0]; \
116 	(dst)[1] = (src)[1]; \
117 	(dst)[2] = (src)[2]; \
118 	(dst)[3] = (src)[3]; \
119 	(dst)[4] = (src)[4]; \
120 	(dst)[5] = (src)[5]; \
121 	(dst)[6] = (src)[6]; \
122 	(dst)[7] = (src)[7]
123 
124 #define	BLOWFISH_XOR_BLOCK(src, dst) \
125 	(dst)[0] ^= (src)[0]; \
126 	(dst)[1] ^= (src)[1]; \
127 	(dst)[2] ^= (src)[2]; \
128 	(dst)[3] ^= (src)[3]; \
129 	(dst)[4] ^= (src)[4]; \
130 	(dst)[5] ^= (src)[5]; \
131 	(dst)[6] ^= (src)[6]; \
132 	(dst)[7] ^= (src)[7]
133 
134 /*
135  * Mechanism info structure passed to KCF during registration.
136  */
137 
138 static crypto_mech_info_t blowfish_mech_info_tab[] = {
139 	/* BLOWFISH_ECB */
140 	{SUN_CKM_BF_ECB, BF_ECB_MECH_INFO_TYPE,
141 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
142 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
143 	    BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS},
144 	/* BLOWFISH_CBC */
145 	{SUN_CKM_BF_CBC, BF_CBC_MECH_INFO_TYPE,
146 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
147 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
148 	    BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS}
149 };
150 
151 #define	BLOWFISH_VALID_MECH(mech)				\
152 	(((mech)->cm_type == BF_ECB_MECH_INFO_TYPE ||		\
153 	(mech)->cm_type == BF_CBC_MECH_INFO_TYPE) ? 1 : 0)
154 
155 /* operations are in-place if the output buffer is NULL */
156 #define	BLOWFISH_ARG_INPLACE(input, output)			\
157 	if ((output) == NULL)					\
158 		(output) = (input);
159 
160 static void blowfish_provider_status(crypto_provider_handle_t, uint_t *);
161 
162 static crypto_control_ops_t blowfish_control_ops = {
163 	blowfish_provider_status
164 };
165 
166 static int blowfish_common_init(crypto_ctx_t *, crypto_mechanism_t *,
167     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
168 static int blowfish_common_init_ctx(blowfish_ctx_t *,
169     crypto_spi_ctx_template_t *, crypto_mechanism_t *, crypto_key_t *, int);
170 static int blowfish_encrypt_final(crypto_ctx_t *, crypto_data_t *,
171     crypto_req_handle_t);
172 static int blowfish_decrypt_final(crypto_ctx_t *, crypto_data_t *,
173     crypto_req_handle_t);
174 
175 static int blowfish_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
176     crypto_req_handle_t);
177 static int blowfish_encrypt_update(crypto_ctx_t *, crypto_data_t *,
178     crypto_data_t *, crypto_req_handle_t);
179 static int blowfish_encrypt_atomic(crypto_provider_handle_t,
180     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
181     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
182 
183 static int blowfish_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
184     crypto_req_handle_t);
185 static int blowfish_decrypt_update(crypto_ctx_t *, crypto_data_t *,
186     crypto_data_t *, crypto_req_handle_t);
187 static int blowfish_decrypt_atomic(crypto_provider_handle_t,
188     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
189     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
190 
191 static crypto_cipher_ops_t blowfish_cipher_ops = {
192 	blowfish_common_init,
193 	blowfish_encrypt,
194 	blowfish_encrypt_update,
195 	blowfish_encrypt_final,
196 	blowfish_encrypt_atomic,
197 	blowfish_common_init,
198 	blowfish_decrypt,
199 	blowfish_decrypt_update,
200 	blowfish_decrypt_final,
201 	blowfish_decrypt_atomic
202 };
203 
204 static int blowfish_create_ctx_template(crypto_provider_handle_t,
205     crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
206     size_t *, crypto_req_handle_t);
207 static int blowfish_free_context(crypto_ctx_t *);
208 
209 static crypto_ctx_ops_t blowfish_ctx_ops = {
210 	blowfish_create_ctx_template,
211 	blowfish_free_context
212 };
213 
214 static crypto_ops_t blowfish_crypto_ops = {
215 	&blowfish_control_ops,
216 	NULL,
217 	&blowfish_cipher_ops,
218 	NULL,
219 	NULL,
220 	NULL,
221 	NULL,
222 	NULL,
223 	NULL,
224 	NULL,
225 	NULL,
226 	NULL,
227 	NULL,
228 	&blowfish_ctx_ops
229 };
230 
231 static crypto_provider_info_t blowfish_prov_info = {
232 	CRYPTO_SPI_VERSION_1,
233 	"Blowfish Software Provider",
234 	CRYPTO_SW_PROVIDER,
235 	{&modlinkage},
236 	NULL,
237 	&blowfish_crypto_ops,
238 	sizeof (blowfish_mech_info_tab)/sizeof (crypto_mech_info_t),
239 	blowfish_mech_info_tab
240 };
241 
242 static int blowfish_encrypt_contiguous_blocks(blowfish_ctx_t *, char *, size_t,
243     crypto_data_t *);
244 static int blowfish_decrypt_contiguous_blocks(blowfish_ctx_t *, char *, size_t,
245     crypto_data_t *);
246 
247 static crypto_kcf_provider_handle_t blowfish_prov_handle = NULL;
248 
249 int
250 _init(void)
251 {
252 	int ret;
253 
254 	/*
255 	 * Register with KCF. If the registration fails, return error.
256 	 */
257 	if ((ret = crypto_register_provider(&blowfish_prov_info,
258 	    &blowfish_prov_handle)) != CRYPTO_SUCCESS) {
259 		cmn_err(CE_WARN, "%s _init: crypto_register_provider() "
260 		    "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret);
261 		return (EACCES);
262 	}
263 
264 	if ((ret = mod_install(&modlinkage)) != 0) {
265 		int rv;
266 
267 		ASSERT(blowfish_prov_handle != NULL);
268 		/* We should not return if the unregister returns busy. */
269 		while ((rv = crypto_unregister_provider(blowfish_prov_handle))
270 		    == CRYPTO_BUSY) {
271 			cmn_err(CE_WARN,
272 			    "%s _init: crypto_unregister_provider() "
273 			    "failed (0x%x). Retrying.",
274 			    CRYPTO_PROVIDER_NAME, rv);
275 			/* wait 10 seconds and try again */
276 			delay(10 * drv_usectohz(1000000));
277 		}
278 	}
279 
280 	return (ret);
281 }
282 
283 int
284 _fini(void)
285 {
286 	int ret;
287 
288 	/*
289 	 * Unregister from KCF if previous registration succeeded.
290 	 */
291 	if (blowfish_prov_handle != NULL) {
292 		if ((ret = crypto_unregister_provider(blowfish_prov_handle)) !=
293 		    CRYPTO_SUCCESS) {
294 			cmn_err(CE_WARN,
295 			    "%s _fini: crypto_unregister_provider() "
296 			    "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret);
297 			return (EBUSY);
298 		}
299 		blowfish_prov_handle = NULL;
300 	}
301 
302 	return (mod_remove(&modlinkage));
303 }
304 
305 int
306 _info(struct modinfo *modinfop)
307 {
308 	return (mod_info(&modlinkage, modinfop));
309 }
310 
311 /*
312  * Initialize key schedules for blowfish
313  */
314 static int
315 init_keysched(crypto_key_t *key, void *keysched)
316 {
317 /* EXPORT DELETE START */
318 	/*
319 	 * Only keys by value are supported by this module.
320 	 */
321 	switch (key->ck_format) {
322 	case CRYPTO_KEY_RAW:
323 		if (key->ck_length < BLOWFISH_MINBITS ||
324 		    key->ck_length > BLOWFISH_MAXBITS) {
325 			return (CRYPTO_KEY_SIZE_RANGE);
326 		}
327 		break;
328 	default:
329 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
330 	}
331 
332 	blowfish_init_keysched(key->ck_data, key->ck_length, keysched);
333 /* EXPORT DELETE END */
334 	return (CRYPTO_SUCCESS);
335 }
336 
337 /*
338  * KCF software provider control entry points.
339  */
340 /* ARGSUSED */
341 static void
342 blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status)
343 {
344 	*status = CRYPTO_PROVIDER_READY;
345 }
346 
347 /*
348  * KCF software provider encrypt entry points.
349  */
350 static int
351 blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
352     crypto_key_t *key, crypto_spi_ctx_template_t template,
353     crypto_req_handle_t req)
354 {
355 
356 /* EXPORT DELETE START */
357 
358 	blowfish_ctx_t *blowfish_ctx;
359 	int rv;
360 	int kmflag;
361 
362 	/*
363 	 * Only keys by value are supported by this module.
364 	 */
365 	if (key->ck_format != CRYPTO_KEY_RAW) {
366 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
367 	}
368 
369 	if (!BLOWFISH_VALID_MECH(mechanism))
370 		return (CRYPTO_MECHANISM_INVALID);
371 
372 	if (mechanism->cm_param != NULL &&
373 	    mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
374 		return (CRYPTO_MECHANISM_PARAM_INVALID);
375 
376 	/*
377 	 * Allocate a blowfish context.
378 	 */
379 	kmflag = crypto_kmflag(req);
380 	blowfish_ctx = kmem_zalloc(sizeof (blowfish_ctx_t), kmflag);
381 	if (blowfish_ctx == NULL)
382 		return (CRYPTO_HOST_MEMORY);
383 
384 	rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism,
385 	    key, kmflag);
386 	if (rv != CRYPTO_SUCCESS) {
387 		kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t));
388 		return (rv);
389 	}
390 
391 	ctx->cc_provider_private = blowfish_ctx;
392 
393 /* EXPORT DELETE END */
394 
395 	return (CRYPTO_SUCCESS);
396 }
397 
398 /*
399  * Helper blowfish encrypt update function for iov input data.
400  */
401 static int
402 blowfish_cipher_update_iov(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input,
403     crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t,
404     crypto_data_t *))
405 {
406 	if (input->cd_miscdata != NULL) {
407 		if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) {
408 			/* LINTED: pointer alignment */
409 			blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata;
410 		} else {
411 			uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0];
412 			uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv;
413 
414 			BLOWFISH_COPY_BLOCK(miscdata8, iv8);
415 		}
416 	}
417 
418 	if (input->cd_raw.iov_len < input->cd_length)
419 		return (CRYPTO_ARGUMENTS_BAD);
420 
421 	return (cipher)(blowfish_ctx, input->cd_raw.iov_base + input->cd_offset,
422 	    input->cd_length, (input == output) ? NULL : output);
423 }
424 
425 /*
426  * Helper blowfish encrypt update function for uio input data.
427  */
428 static int
429 blowfish_cipher_update_uio(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input,
430     crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t,
431     crypto_data_t *))
432 {
433 	uio_t *uiop = input->cd_uio;
434 	off_t offset = input->cd_offset;
435 	size_t length = input->cd_length;
436 	uint_t vec_idx;
437 	size_t cur_len;
438 
439 	if (input->cd_miscdata != NULL) {
440 		if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) {
441 			/*LINTED: pointer alignment */
442 			blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata;
443 		} else {
444 			uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0];
445 			uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv;
446 
447 			BLOWFISH_COPY_BLOCK(miscdata8, iv8);
448 		}
449 	}
450 
451 	if (input->cd_uio->uio_segflg != UIO_SYSSPACE) {
452 		return (CRYPTO_ARGUMENTS_BAD);
453 	}
454 
455 	/*
456 	 * Jump to the first iovec containing data to be
457 	 * processed.
458 	 */
459 	for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
460 	    offset >= uiop->uio_iov[vec_idx].iov_len;
461 	    offset -= uiop->uio_iov[vec_idx++].iov_len);
462 	if (vec_idx == uiop->uio_iovcnt) {
463 		/*
464 		 * The caller specified an offset that is larger than the
465 		 * total size of the buffers it provided.
466 		 */
467 		return (CRYPTO_DATA_LEN_RANGE);
468 	}
469 
470 	/*
471 	 * Now process the iovecs.
472 	 */
473 	while (vec_idx < uiop->uio_iovcnt && length > 0) {
474 		cur_len = MIN(uiop->uio_iov[vec_idx].iov_len -
475 		    offset, length);
476 
477 		(cipher)(blowfish_ctx, uiop->uio_iov[vec_idx].iov_base +
478 		    offset, cur_len, (input == output) ? NULL : output);
479 
480 		length -= cur_len;
481 		vec_idx++;
482 		offset = 0;
483 	}
484 
485 	if (vec_idx == uiop->uio_iovcnt && length > 0) {
486 		/*
487 		 * The end of the specified iovec's was reached but
488 		 * the length requested could not be processed, i.e.
489 		 * The caller requested to digest more data than it provided.
490 		 */
491 
492 		return (CRYPTO_DATA_LEN_RANGE);
493 	}
494 
495 	return (CRYPTO_SUCCESS);
496 }
497 
498 /*
499  * Helper blowfish encrypt update function for mblk input data.
500  */
501 static int
502 blowfish_cipher_update_mp(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input,
503     crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t,
504     crypto_data_t *))
505 {
506 	off_t offset = input->cd_offset;
507 	size_t length = input->cd_length;
508 	mblk_t *mp;
509 	size_t cur_len;
510 
511 	if (input->cd_miscdata != NULL) {
512 		if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) {
513 			/*LINTED: pointer alignment */
514 			blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata;
515 		} else {
516 			uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0];
517 			uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv;
518 
519 			BLOWFISH_COPY_BLOCK(miscdata8, iv8);
520 		}
521 	}
522 
523 	/*
524 	 * Jump to the first mblk_t containing data to be processed.
525 	 */
526 	for (mp = input->cd_mp; mp != NULL && offset >= MBLKL(mp);
527 	    offset -= MBLKL(mp), mp = mp->b_cont);
528 	if (mp == NULL) {
529 		/*
530 		 * The caller specified an offset that is larger than the
531 		 * total size of the buffers it provided.
532 		 */
533 		return (CRYPTO_DATA_LEN_RANGE);
534 	}
535 
536 	/*
537 	 * Now do the processing on the mblk chain.
538 	 */
539 	while (mp != NULL && length > 0) {
540 		cur_len = MIN(MBLKL(mp) - offset, length);
541 		(cipher)(blowfish_ctx, (char *)(mp->b_rptr + offset), cur_len,
542 		    (input == output) ? NULL : output);
543 
544 		length -= cur_len;
545 		offset = 0;
546 		mp = mp->b_cont;
547 	}
548 
549 	if (mp == NULL && length > 0) {
550 		/*
551 		 * The end of the mblk was reached but the length requested
552 		 * could not be processed, i.e. The caller requested
553 		 * to digest more data than it provided.
554 		 */
555 		return (CRYPTO_DATA_LEN_RANGE);
556 	}
557 
558 	return (CRYPTO_SUCCESS);
559 }
560 
561 /* ARGSUSED */
562 static int
563 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
564     crypto_data_t *ciphertext, crypto_req_handle_t req)
565 {
566 	int ret;
567 
568 /* EXPORT DELETE START */
569 
570 	blowfish_ctx_t *blowfish_ctx;
571 
572 	/*
573 	 * Plaintext must be a multiple of blowfish block size.
574 	 * This test only works for non-padded mechanisms
575 	 * when blocksize is 2^N.
576 	 */
577 	if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
578 		return (CRYPTO_DATA_LEN_RANGE);
579 
580 	ASSERT(ctx->cc_provider_private != NULL);
581 	blowfish_ctx = ctx->cc_provider_private;
582 
583 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
584 
585 	/*
586 	 * We need to just return the length needed to store the output.
587 	 * We should not destroy the context for the following case.
588 	 */
589 	if (ciphertext->cd_length < plaintext->cd_length) {
590 		ciphertext->cd_length = plaintext->cd_length;
591 		return (CRYPTO_BUFFER_TOO_SMALL);
592 	}
593 
594 	/*
595 	 * Do an update on the specified input data.
596 	 */
597 	ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req);
598 	ASSERT(blowfish_ctx->bc_remainder_len  == 0);
599 	(void) blowfish_free_context(ctx);
600 
601 /* EXPORT DELETE END */
602 
603 	/* LINTED */
604 	return (ret);
605 }
606 
607 /* ARGSUSED */
608 static int
609 blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
610     crypto_data_t *plaintext, crypto_req_handle_t req)
611 {
612 	int ret;
613 
614 /* EXPORT DELETE START */
615 
616 	blowfish_ctx_t *blowfish_ctx;
617 
618 	/*
619 	 * Ciphertext must be a multiple of blowfish block size.
620 	 * This test only works for non-padded mechanisms
621 	 * when blocksize is 2^N.
622 	 */
623 	if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
624 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
625 
626 	ASSERT(ctx->cc_provider_private != NULL);
627 	blowfish_ctx = ctx->cc_provider_private;
628 
629 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
630 
631 	/*
632 	 * We need to just return the length needed to store the output.
633 	 * We should not destroy the context for the following case.
634 	 */
635 	if (plaintext->cd_length < ciphertext->cd_length) {
636 		plaintext->cd_length = ciphertext->cd_length;
637 		return (CRYPTO_BUFFER_TOO_SMALL);
638 	}
639 
640 	/*
641 	 * Do an update on the specified input data.
642 	 */
643 	ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req);
644 	ASSERT(blowfish_ctx->bc_remainder_len == 0);
645 	(void) blowfish_free_context(ctx);
646 
647 /* EXPORT DELETE END */
648 
649 	/* LINTED */
650 	return (ret);
651 }
652 
653 /* ARGSUSED */
654 static int
655 blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
656     crypto_data_t *ciphertext, crypto_req_handle_t req)
657 {
658 	off_t saved_offset;
659 	size_t saved_length, out_len;
660 	int ret = CRYPTO_SUCCESS;
661 
662 	ASSERT(ctx->cc_provider_private != NULL);
663 
664 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
665 
666 	/* compute number of bytes that will hold the ciphertext */
667 	out_len =
668 	    ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
669 	out_len += plaintext->cd_length;
670 	out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
671 
672 	/* return length needed to store the output */
673 	if (ciphertext->cd_length < out_len) {
674 		ciphertext->cd_length = out_len;
675 		return (CRYPTO_BUFFER_TOO_SMALL);
676 	}
677 
678 	saved_offset = ciphertext->cd_offset;
679 	saved_length = ciphertext->cd_length;
680 
681 	/*
682 	 * Do the blowfish update on the specified input data.
683 	 */
684 	switch (plaintext->cd_format) {
685 	case CRYPTO_DATA_RAW:
686 		ret = blowfish_cipher_update_iov(ctx->cc_provider_private,
687 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
688 		break;
689 	case CRYPTO_DATA_UIO:
690 		ret = blowfish_cipher_update_uio(ctx->cc_provider_private,
691 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
692 		break;
693 	case CRYPTO_DATA_MBLK:
694 		ret = blowfish_cipher_update_mp(ctx->cc_provider_private,
695 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
696 		break;
697 	default:
698 		ret = CRYPTO_ARGUMENTS_BAD;
699 	}
700 
701 	if (ret == CRYPTO_SUCCESS) {
702 		if (plaintext != ciphertext)
703 			ciphertext->cd_length =
704 			    ciphertext->cd_offset - saved_offset;
705 	} else {
706 		ciphertext->cd_length = saved_length;
707 	}
708 	ciphertext->cd_offset = saved_offset;
709 
710 	return (ret);
711 }
712 
713 /* ARGSUSED */
714 static int
715 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
716     crypto_data_t *plaintext, crypto_req_handle_t req)
717 {
718 	off_t saved_offset;
719 	size_t saved_length, out_len;
720 	int ret = CRYPTO_SUCCESS;
721 
722 	ASSERT(ctx->cc_provider_private != NULL);
723 
724 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
725 
726 	/* compute number of bytes that will hold the plaintext */
727 	out_len =
728 	    ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
729 	out_len += ciphertext->cd_length;
730 	out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
731 
732 	/* return length needed to store the output */
733 	if (plaintext->cd_length < out_len) {
734 		plaintext->cd_length = out_len;
735 		return (CRYPTO_BUFFER_TOO_SMALL);
736 	}
737 
738 	saved_offset = plaintext->cd_offset;
739 	saved_length = plaintext->cd_length;
740 
741 	/*
742 	 * Do the blowfish update on the specified input data.
743 	 */
744 	switch (ciphertext->cd_format) {
745 	case CRYPTO_DATA_RAW:
746 		ret = blowfish_cipher_update_iov(ctx->cc_provider_private,
747 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
748 		break;
749 	case CRYPTO_DATA_UIO:
750 		ret = blowfish_cipher_update_uio(ctx->cc_provider_private,
751 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
752 		break;
753 	case CRYPTO_DATA_MBLK:
754 		ret = blowfish_cipher_update_mp(ctx->cc_provider_private,
755 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
756 		break;
757 	default:
758 		ret = CRYPTO_ARGUMENTS_BAD;
759 	}
760 
761 	if (ret == CRYPTO_SUCCESS) {
762 		if (ciphertext != plaintext)
763 			plaintext->cd_length =
764 			    plaintext->cd_offset - saved_offset;
765 	} else {
766 		plaintext->cd_length = saved_length;
767 	}
768 	plaintext->cd_offset = saved_offset;
769 
770 	return (ret);
771 }
772 
773 /* ARGSUSED */
774 static int
775 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
776     crypto_req_handle_t req)
777 {
778 
779 /* EXPORT DELETE START */
780 
781 	blowfish_ctx_t *blowfish_ctx;
782 
783 	ASSERT(ctx->cc_provider_private != NULL);
784 	blowfish_ctx = ctx->cc_provider_private;
785 
786 	/*
787 	 * There must be no unprocessed data.
788 	 * This happens if the length of the last data is
789 	 * not a multiple of the BLOWFISH block length.
790 	 */
791 	if (blowfish_ctx->bc_remainder_len > 0)
792 		return (CRYPTO_DATA_LEN_RANGE);
793 
794 	(void) blowfish_free_context(ctx);
795 	data->cd_length = 0;
796 
797 /* EXPORT DELETE END */
798 
799 	return (CRYPTO_SUCCESS);
800 }
801 
802 /* ARGSUSED */
803 static int
804 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
805     crypto_req_handle_t req)
806 {
807 
808 /* EXPORT DELETE START */
809 
810 	blowfish_ctx_t *blowfish_ctx;
811 
812 	ASSERT(ctx->cc_provider_private != NULL);
813 	blowfish_ctx = ctx->cc_provider_private;
814 
815 	/*
816 	 * There must be no unprocessed ciphertext.
817 	 * This happens if the length of the last ciphertext is
818 	 * not a multiple of the BLOWFISH block length.
819 	 */
820 	if (blowfish_ctx->bc_remainder_len > 0)
821 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
822 
823 	(void) blowfish_free_context(ctx);
824 	data->cd_length = 0;
825 
826 /* EXPORT DELETE END */
827 
828 	return (CRYPTO_SUCCESS);
829 }
830 
831 /* ARGSUSED */
832 static int
833 blowfish_encrypt_atomic(crypto_provider_handle_t provider,
834     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
835     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
836     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
837 {
838 	blowfish_ctx_t blowfish_ctx;	/* on the stack */
839 	off_t saved_offset;
840 	size_t saved_length;
841 	int ret;
842 
843 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
844 
845 	/*
846 	 * Plaintext must be a multiple of blowfish block size.
847 	 * This test only works for non-padded mechanisms
848 	 * when blocksize is 2^N.
849 	 */
850 	if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
851 		return (CRYPTO_DATA_LEN_RANGE);
852 
853 	/* return length needed to store the output */
854 	if (ciphertext->cd_length < plaintext->cd_length) {
855 		ciphertext->cd_length = plaintext->cd_length;
856 		return (CRYPTO_BUFFER_TOO_SMALL);
857 	}
858 
859 	if (!BLOWFISH_VALID_MECH(mechanism))
860 		return (CRYPTO_MECHANISM_INVALID);
861 
862 	if (mechanism->cm_param_len != 0 &&
863 	    mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
864 		return (CRYPTO_MECHANISM_PARAM_INVALID);
865 
866 	bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
867 
868 	ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
869 	    key, crypto_kmflag(req));
870 	if (ret != CRYPTO_SUCCESS)
871 		return (ret);
872 
873 	saved_offset = ciphertext->cd_offset;
874 	saved_length = ciphertext->cd_length;
875 
876 	/*
877 	 * Do an update on the specified input data.
878 	 */
879 	switch (plaintext->cd_format) {
880 	case CRYPTO_DATA_RAW:
881 		ret = blowfish_cipher_update_iov(&blowfish_ctx,
882 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
883 		break;
884 	case CRYPTO_DATA_UIO:
885 		ret = blowfish_cipher_update_uio(&blowfish_ctx,
886 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
887 		break;
888 	case CRYPTO_DATA_MBLK:
889 		ret = blowfish_cipher_update_mp(&blowfish_ctx,
890 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
891 		break;
892 	default:
893 		ret = CRYPTO_ARGUMENTS_BAD;
894 	}
895 
896 	if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) {
897 		bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
898 		kmem_free(blowfish_ctx.bc_keysched,
899 		    blowfish_ctx.bc_keysched_len);
900 	}
901 
902 	if (ret == CRYPTO_SUCCESS) {
903 		ASSERT(blowfish_ctx.bc_remainder_len == 0);
904 		if (plaintext != ciphertext)
905 			ciphertext->cd_length =
906 			    ciphertext->cd_offset - saved_offset;
907 	} else {
908 		ciphertext->cd_length = saved_length;
909 	}
910 	ciphertext->cd_offset = saved_offset;
911 
912 	return (ret);
913 }
914 
915 /* ARGSUSED */
916 static int
917 blowfish_decrypt_atomic(crypto_provider_handle_t provider,
918     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
919     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
920     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
921 {
922 	blowfish_ctx_t blowfish_ctx;	/* on the stack */
923 	off_t saved_offset;
924 	size_t saved_length;
925 	int ret;
926 
927 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
928 
929 	/*
930 	 * Ciphertext must be a multiple of blowfish block size.
931 	 * This test only works for non-padded mechanisms
932 	 * when blocksize is 2^N.
933 	 */
934 	if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
935 		return (CRYPTO_DATA_LEN_RANGE);
936 
937 	/* return length needed to store the output */
938 	if (plaintext->cd_length < ciphertext->cd_length) {
939 		plaintext->cd_length = ciphertext->cd_length;
940 		return (CRYPTO_BUFFER_TOO_SMALL);
941 	}
942 
943 	if (!BLOWFISH_VALID_MECH(mechanism))
944 		return (CRYPTO_MECHANISM_INVALID);
945 
946 	if (mechanism->cm_param_len != 0 &&
947 	    mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
948 		return (CRYPTO_MECHANISM_PARAM_INVALID);
949 
950 	bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
951 
952 	ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
953 	    key, crypto_kmflag(req));
954 	if (ret != CRYPTO_SUCCESS)
955 		return (ret);
956 
957 	saved_offset = plaintext->cd_offset;
958 	saved_length = plaintext->cd_length;
959 
960 	/*
961 	 * Do an update on the specified input data.
962 	 */
963 	switch (ciphertext->cd_format) {
964 	case CRYPTO_DATA_RAW:
965 		ret = blowfish_cipher_update_iov(&blowfish_ctx,
966 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
967 		break;
968 	case CRYPTO_DATA_UIO:
969 		ret = blowfish_cipher_update_uio(&blowfish_ctx,
970 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
971 		break;
972 	case CRYPTO_DATA_MBLK:
973 		ret = blowfish_cipher_update_mp(&blowfish_ctx,
974 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
975 		break;
976 	default:
977 		ret = CRYPTO_ARGUMENTS_BAD;
978 	}
979 
980 	if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) {
981 		bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
982 		kmem_free(blowfish_ctx.bc_keysched,
983 		    blowfish_ctx.bc_keysched_len);
984 	}
985 
986 	if (ret == CRYPTO_SUCCESS) {
987 		ASSERT(blowfish_ctx.bc_remainder_len == 0);
988 		if (ciphertext != plaintext)
989 			plaintext->cd_length =
990 			    plaintext->cd_offset - saved_offset;
991 	} else {
992 		plaintext->cd_length = saved_length;
993 	}
994 	plaintext->cd_offset = saved_offset;
995 
996 	return (ret);
997 }
998 
999 /*
1000  * KCF software provider context template entry points.
1001  */
1002 /* ARGSUSED */
1003 static int
1004 blowfish_create_ctx_template(crypto_provider_handle_t provider,
1005     crypto_mechanism_t *mechanism, crypto_key_t *key,
1006     crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req)
1007 {
1008 
1009 /* EXPORT DELETE START */
1010 
1011 	void *keysched;
1012 	size_t size;
1013 	int rv;
1014 
1015 	if (!BLOWFISH_VALID_MECH(mechanism))
1016 		return (CRYPTO_MECHANISM_INVALID);
1017 
1018 	if ((keysched = blowfish_alloc_keysched(&size,
1019 	    crypto_kmflag(req))) == NULL) {
1020 		return (CRYPTO_HOST_MEMORY);
1021 	}
1022 
1023 	/*
1024 	 * Initialize key schedule.  Key length information is stored
1025 	 * in the key.
1026 	 */
1027 	if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
1028 		bzero(keysched, size);
1029 		kmem_free(keysched, size);
1030 		return (rv);
1031 	}
1032 
1033 	*tmpl = keysched;
1034 	*tmpl_size = size;
1035 
1036 /* EXPORT DELETE END */
1037 
1038 	return (CRYPTO_SUCCESS);
1039 }
1040 
1041 /* ARGSUSED */
1042 static int
1043 blowfish_free_context(crypto_ctx_t *ctx)
1044 {
1045 	blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private;
1046 
1047 	if (blowfish_ctx != NULL) {
1048 		if (blowfish_ctx->bc_flags &
1049 		    BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) {
1050 			ASSERT(blowfish_ctx->bc_keysched_len != 0);
1051 			bzero(blowfish_ctx->bc_keysched,
1052 			    blowfish_ctx->bc_keysched_len);
1053 			kmem_free(blowfish_ctx->bc_keysched,
1054 			    blowfish_ctx->bc_keysched_len);
1055 		}
1056 		kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t));
1057 		ctx->cc_provider_private = NULL;
1058 	}
1059 
1060 	return (CRYPTO_SUCCESS);
1061 }
1062 
1063 /*
1064  * Initialize by setting iov_or_mp to point to the current iovec or mp,
1065  * and by setting current_offset to an offset within the current iovec or mp .
1066  */
1067 static void
1068 blowfish_init_ptrs(crypto_data_t *out, void **iov_or_mp,
1069     offset_t *current_offset)
1070 {
1071 	offset_t offset;
1072 
1073 	switch (out->cd_format) {
1074 	case CRYPTO_DATA_RAW:
1075 		*current_offset = out->cd_offset;
1076 		break;
1077 
1078 	case CRYPTO_DATA_UIO: {
1079 		uio_t *uiop = out->cd_uio;
1080 		uint_t vec_idx;
1081 
1082 		offset = out->cd_offset;
1083 		for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
1084 		    offset >= uiop->uio_iov[vec_idx].iov_len;
1085 		    offset -= uiop->uio_iov[vec_idx++].iov_len);
1086 
1087 		*current_offset = offset;
1088 		*iov_or_mp = (void *)(uintptr_t)vec_idx;
1089 		break;
1090 	}
1091 
1092 	case CRYPTO_DATA_MBLK: {
1093 		mblk_t *mp;
1094 
1095 		offset = out->cd_offset;
1096 		for (mp = out->cd_mp; mp != NULL && offset >= MBLKL(mp);
1097 			offset -= MBLKL(mp), mp = mp->b_cont);
1098 
1099 		*current_offset = offset;
1100 		*iov_or_mp = mp;
1101 		break;
1102 
1103 	}
1104 	} /* end switch */
1105 }
1106 
1107 /*
1108  * Get pointers for where in the output to copy a block of encrypted or
1109  * decrypted data.  The iov_or_mp argument stores a pointer to the current
1110  * iovec or mp, and offset stores an offset into the current iovec or mp.
1111  */
1112 static void
1113 blowfish_get_ptrs(crypto_data_t *out, void **iov_or_mp,
1114     offset_t *current_offset, uint8_t **out_data_1, size_t *out_data_1_len,
1115     uint8_t **out_data_2)
1116 {
1117 	offset_t offset;
1118 
1119 	switch (out->cd_format) {
1120 	case CRYPTO_DATA_RAW: {
1121 		iovec_t *iov;
1122 
1123 		offset = *current_offset;
1124 		iov = &out->cd_raw;
1125 		if ((offset + BLOWFISH_BLOCK_LEN) <= iov->iov_len) {
1126 			/* one BLOWFISH block fits */
1127 			*out_data_1 = (uint8_t *)iov->iov_base + offset;
1128 			*out_data_1_len = BLOWFISH_BLOCK_LEN;
1129 			*out_data_2 = NULL;
1130 			*current_offset = offset + BLOWFISH_BLOCK_LEN;
1131 		}
1132 		break;
1133 	}
1134 
1135 	case CRYPTO_DATA_UIO: {
1136 		uio_t *uio = out->cd_uio;
1137 		iovec_t *iov;
1138 		offset_t offset;
1139 		uint_t vec_idx;
1140 		uint8_t *p;
1141 
1142 		offset = *current_offset;
1143 		vec_idx = (uint_t)(uintptr_t)(*iov_or_mp);
1144 		iov = &uio->uio_iov[vec_idx];
1145 		p = (uint8_t *)iov->iov_base + offset;
1146 		*out_data_1 = p;
1147 
1148 		if (offset + BLOWFISH_BLOCK_LEN <= iov->iov_len) {
1149 			/* can fit one BLOWFISH block into this iov */
1150 			*out_data_1_len = BLOWFISH_BLOCK_LEN;
1151 			*out_data_2 = NULL;
1152 			*current_offset = offset + BLOWFISH_BLOCK_LEN;
1153 		} else {
1154 			/* one BLOWFISH block spans two iovecs */
1155 			*out_data_1_len = iov->iov_len - offset;
1156 			if (vec_idx == uio->uio_iovcnt)
1157 				return;
1158 			vec_idx++;
1159 			iov = &uio->uio_iov[vec_idx];
1160 			*out_data_2 = (uint8_t *)iov->iov_base;
1161 			*current_offset = BLOWFISH_BLOCK_LEN - *out_data_1_len;
1162 		}
1163 		*iov_or_mp = (void *)(uintptr_t)vec_idx;
1164 		break;
1165 	}
1166 
1167 	case CRYPTO_DATA_MBLK: {
1168 		mblk_t *mp;
1169 		uint8_t *p;
1170 
1171 		offset = *current_offset;
1172 		mp = (mblk_t *)*iov_or_mp;
1173 		p = mp->b_rptr + offset;
1174 		*out_data_1 = p;
1175 		if ((p + BLOWFISH_BLOCK_LEN) <= mp->b_wptr) {
1176 			/* can fit one BLOWFISH block into this mblk */
1177 			*out_data_1_len = BLOWFISH_BLOCK_LEN;
1178 			*out_data_2 = NULL;
1179 			*current_offset = offset + BLOWFISH_BLOCK_LEN;
1180 		} else {
1181 			/* one BLOWFISH block spans two mblks */
1182 			*out_data_1_len = mp->b_wptr - p;
1183 			if ((mp = mp->b_cont) == NULL)
1184 				return;
1185 			*out_data_2 = mp->b_rptr;
1186 			*current_offset = BLOWFISH_BLOCK_LEN - *out_data_1_len;
1187 		}
1188 		*iov_or_mp = mp;
1189 		break;
1190 	}
1191 	} /* end switch */
1192 }
1193 
1194 /*
1195  * Encrypt multiple blocks of data.
1196  */
1197 static int
1198 blowfish_encrypt_contiguous_blocks(blowfish_ctx_t *ctx, char *data,
1199     size_t length, crypto_data_t *out)
1200 {
1201 /* EXPORT DELETE START */
1202 	size_t remainder = length;
1203 	size_t need;
1204 	uint8_t *datap = (uint8_t *)data;
1205 	uint8_t *blockp;
1206 	uint8_t *lastp;
1207 	uint32_t tmp[2];
1208 	void *iov_or_mp;
1209 	offset_t offset;
1210 	uint8_t *out_data_1;
1211 	uint8_t *out_data_2;
1212 	size_t out_data_1_len;
1213 
1214 	if (length + ctx->bc_remainder_len < BLOWFISH_BLOCK_LEN) {
1215 		/* accumulate bytes here and return */
1216 		bcopy(datap,
1217 		    (uint8_t *)&ctx->bc_remainder + ctx->bc_remainder_len,
1218 		    length);
1219 		ctx->bc_remainder_len += length;
1220 		ctx->bc_copy_to = datap;
1221 		return (0);
1222 	}
1223 
1224 	lastp = (uint8_t *)&ctx->bc_iv;
1225 	if (out != NULL)
1226 		blowfish_init_ptrs(out, &iov_or_mp, &offset);
1227 
1228 	do {
1229 		/* Unprocessed data from last call. */
1230 		if (ctx->bc_remainder_len > 0) {
1231 			need = BLOWFISH_BLOCK_LEN - ctx->bc_remainder_len;
1232 
1233 			if (need > remainder)
1234 				return (1);
1235 
1236 			bcopy(datap, &((uint8_t *)&ctx->bc_remainder)
1237 			    [ctx->bc_remainder_len], need);
1238 
1239 			blockp = (uint8_t *)&ctx->bc_remainder;
1240 		} else {
1241 			blockp = datap;
1242 		}
1243 
1244 		/* don't write on the plaintext */
1245 		if (out != NULL) {
1246 			if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) {
1247 				/* LINTED: pointer alignment */
1248 				tmp[0] = *(uint32_t *)blockp;
1249 				/* LINTED: pointer alignment */
1250 				tmp[1] = *(uint32_t *)&blockp[4];
1251 			} else {
1252 #ifdef _BIG_ENDIAN
1253 				tmp[0] = (((uint32_t)blockp[0] << 24) |
1254 				    ((uint32_t)blockp[1] << 16) |
1255 				    ((uint32_t)blockp[2] << 8) |
1256 				    (uint32_t)blockp[3]);
1257 
1258 				tmp[1] = (((uint32_t)blockp[4] << 24) |
1259 				    ((uint32_t)blockp[5] << 16) |
1260 				    ((uint32_t)blockp[6] << 8) |
1261 				    (uint32_t)blockp[7]);
1262 #else
1263 				tmp[0] = (((uint32_t)blockp[7] << 24) |
1264 				    ((uint32_t)blockp[6] << 16) |
1265 				    ((uint32_t)blockp[5] << 8) |
1266 				    (uint32_t)blockp[4]);
1267 
1268 				tmp[1] = (((uint32_t)blockp[3] << 24) |
1269 				    ((uint32_t)blockp[2] << 16) |
1270 				    ((uint32_t)blockp[1] << 8) |
1271 				    (uint32_t)blockp[0]);
1272 #endif /* _BIG_ENDIAN */
1273 			}
1274 			blockp = (uint8_t *)tmp;
1275 		}
1276 
1277 		if (ctx->bc_flags & BLOWFISH_CBC_MODE) {
1278 			/*
1279 			 * XOR the previous cipher block or IV with the
1280 			 * current clear block. Check for alignment.
1281 			 */
1282 			if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
1283 			    IS_P2ALIGNED(lastp, sizeof (uint32_t))) {
1284 				/* LINTED: pointer alignment */
1285 				*(uint32_t *)&blockp[0] ^=
1286 				/* LINTED: pointer alignment */
1287 				    *(uint32_t *)&lastp[0];
1288 				/* LINTED: pointer alignment */
1289 				*(uint32_t *)&blockp[4] ^=
1290 				/* LINTED: pointer alignment */
1291 				    *(uint32_t *)&lastp[4];
1292 			} else {
1293 				BLOWFISH_XOR_BLOCK(lastp, blockp);
1294 			}
1295 		}
1296 
1297 		if (out == NULL) {
1298 			blowfish_encrypt_block(ctx->bc_keysched, blockp,
1299 			    blockp);
1300 
1301 			ctx->bc_lastp = blockp;
1302 			lastp = blockp;
1303 
1304 			if (ctx->bc_remainder_len > 0) {
1305 				bcopy(blockp, ctx->bc_copy_to,
1306 				    ctx->bc_remainder_len);
1307 				bcopy(blockp + ctx->bc_remainder_len, datap,
1308 				    need);
1309 			}
1310 		} else {
1311 			blowfish_encrypt_block(ctx->bc_keysched, blockp, lastp);
1312 			blowfish_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
1313 			    &out_data_1_len, &out_data_2);
1314 
1315 			/* copy block to where it belongs */
1316 			bcopy(lastp, out_data_1, out_data_1_len);
1317 			if (out_data_2 != NULL) {
1318 				bcopy(lastp + out_data_1_len, out_data_2,
1319 				    BLOWFISH_BLOCK_LEN - out_data_1_len);
1320 			}
1321 
1322 			/* update offset */
1323 			out->cd_offset += BLOWFISH_BLOCK_LEN;
1324 		}
1325 
1326 		/* Update pointer to next block of data to be processed. */
1327 		if (ctx->bc_remainder_len != 0) {
1328 			datap += need;
1329 			ctx->bc_remainder_len = 0;
1330 		} else {
1331 			datap += BLOWFISH_BLOCK_LEN;
1332 		}
1333 
1334 		remainder = (size_t)&data[length] - (size_t)datap;
1335 
1336 		/* Incomplete last block. */
1337 		if (remainder > 0 && remainder < BLOWFISH_BLOCK_LEN) {
1338 			bcopy(datap, &ctx->bc_remainder, remainder);
1339 			ctx->bc_remainder_len = remainder;
1340 			ctx->bc_copy_to = datap;
1341 			goto out;
1342 		}
1343 		ctx->bc_copy_to = NULL;
1344 
1345 	} while (remainder > 0);
1346 
1347 out:
1348 	if (ctx->bc_lastp != NULL) {
1349 		if (IS_P2ALIGNED(ctx->bc_lastp, sizeof (uint32_t))) {
1350 			uint8_t *iv8 = (uint8_t *)&ctx->bc_iv;
1351 			uint8_t *last8 = (uint8_t *)ctx->bc_lastp;
1352 
1353 			/* LINTED: pointer alignment */
1354 			*(uint32_t *)iv8 = *(uint32_t *)last8;
1355 			/* LINTED: pointer alignment */
1356 			*(uint32_t *)&iv8[4] = *(uint32_t *)&last8[4];
1357 		} else {
1358 			uint8_t *iv8 = (uint8_t *)&ctx->bc_iv;
1359 			uint8_t *last8 = ctx->bc_lastp;
1360 
1361 			BLOWFISH_COPY_BLOCK(last8, iv8);
1362 		}
1363 		ctx->bc_lastp = (uint8_t *)&ctx->bc_iv;
1364 	}
1365 /* EXPORT DELETE END */
1366 
1367 	return (0);
1368 }
1369 
1370 #define	OTHER(a, ctx) \
1371 	(((a) == &(ctx)->bc_lastblock) ? &(ctx)->bc_iv : &(ctx)->bc_lastblock)
1372 
1373 static int
1374 blowfish_decrypt_contiguous_blocks(blowfish_ctx_t *ctx, char *data,
1375     size_t length, crypto_data_t *out)
1376 {
1377 /* EXPORT DELETE START */
1378 	size_t remainder = length;
1379 	size_t need;
1380 	uint8_t *datap = (uint8_t *)data;
1381 	uint8_t *blockp;
1382 	uint8_t *lastp;
1383 	uint32_t tmp[2];
1384 	void *iov_or_mp;
1385 	offset_t offset;
1386 	uint8_t *out_data_1;
1387 	uint8_t *out_data_2;
1388 	size_t out_data_1_len;
1389 
1390 	if (length + ctx->bc_remainder_len < BLOWFISH_BLOCK_LEN) {
1391 		/* accumulate bytes here and return */
1392 		bcopy(datap,
1393 		    (uint8_t *)&ctx->bc_remainder + ctx->bc_remainder_len,
1394 		    length);
1395 		ctx->bc_remainder_len += length;
1396 		ctx->bc_copy_to = datap;
1397 		return (0);
1398 	}
1399 
1400 	lastp = ctx->bc_lastp;
1401 	if (out != NULL)
1402 		blowfish_init_ptrs(out, &iov_or_mp, &offset);
1403 
1404 	do {
1405 		/* Unprocessed data from last call. */
1406 		if (ctx->bc_remainder_len > 0) {
1407 			need = BLOWFISH_BLOCK_LEN - ctx->bc_remainder_len;
1408 
1409 			if (need > remainder)
1410 				return (1);
1411 
1412 			bcopy(datap, &((uint8_t *)&ctx->bc_remainder)
1413 			    [ctx->bc_remainder_len], need);
1414 
1415 			blockp = (uint8_t *)&ctx->bc_remainder;
1416 		} else {
1417 			blockp = datap;
1418 		}
1419 
1420 		if (ctx->bc_flags & BLOWFISH_CBC_MODE) {
1421 
1422 			/* Save current ciphertext block */
1423 			if (IS_P2ALIGNED(blockp, sizeof (uint32_t))) {
1424 				uint32_t *tmp32;
1425 
1426 				/* LINTED: pointer alignment */
1427 				tmp32 = (uint32_t *)OTHER((uint64_t *)lastp,
1428 				    ctx);
1429 
1430 				/* LINTED: pointer alignment */
1431 				*tmp32++ = *(uint32_t *)blockp;
1432 				/* LINTED: pointer alignment */
1433 				*tmp32++ = *(uint32_t *)&blockp[4];
1434 			} else {
1435 				uint8_t *tmp8;
1436 				tmp8 = (uint8_t *)OTHER((uint64_t *)lastp, ctx);
1437 
1438 				BLOWFISH_COPY_BLOCK(blockp, tmp8);
1439 			}
1440 		}
1441 
1442 		if (out != NULL) {
1443 			blowfish_decrypt_block(ctx->bc_keysched, blockp,
1444 			    (uint8_t *)tmp);
1445 			blockp = (uint8_t *)tmp;
1446 		} else {
1447 			blowfish_decrypt_block(ctx->bc_keysched, blockp,
1448 			    blockp);
1449 		}
1450 
1451 		if (ctx->bc_flags & BLOWFISH_CBC_MODE) {
1452 			/*
1453 			 * XOR the previous cipher block or IV with the
1454 			 * currently decrypted block.  Check for alignment.
1455 			 */
1456 			if (IS_P2ALIGNED(blockp, sizeof (uint32_t)) &&
1457 			    IS_P2ALIGNED(lastp, sizeof (uint32_t))) {
1458 				/* LINTED: pointer alignment */
1459 				*(uint32_t *)blockp ^= *(uint32_t *)lastp;
1460 				/* LINTED: pointer alignment */
1461 				*(uint32_t *)&blockp[4] ^=
1462 				/* LINTED: pointer alignment */
1463 				    *(uint32_t *)&lastp[4];
1464 			} else {
1465 				BLOWFISH_XOR_BLOCK(lastp, blockp);
1466 			}
1467 
1468 			/* LINTED: pointer alignment */
1469 			lastp = (uint8_t *)OTHER((uint64_t *)lastp, ctx);
1470 		}
1471 
1472 		if (out != NULL) {
1473 			blowfish_get_ptrs(out, &iov_or_mp, &offset, &out_data_1,
1474 			    &out_data_1_len, &out_data_2);
1475 			/* copy temporary block to where it belongs */
1476 			bcopy(&tmp, out_data_1, out_data_1_len);
1477 			if (out_data_2 != NULL) {
1478 				bcopy((uint8_t *)&tmp + out_data_1_len,
1479 				    out_data_2,
1480 				    BLOWFISH_BLOCK_LEN - out_data_1_len);
1481 			}
1482 
1483 			/* update offset */
1484 			out->cd_offset += BLOWFISH_BLOCK_LEN;
1485 		} else if (ctx->bc_remainder_len > 0) {
1486 			/* copy temporary block to where it belongs */
1487 			bcopy(blockp, ctx->bc_copy_to, ctx->bc_remainder_len);
1488 			bcopy(blockp + ctx->bc_remainder_len, datap, need);
1489 		}
1490 
1491 		/* Update pointer to next block of data to be processed. */
1492 		if (ctx->bc_remainder_len != 0) {
1493 			datap += need;
1494 			ctx->bc_remainder_len = 0;
1495 		} else {
1496 			datap += BLOWFISH_BLOCK_LEN;
1497 		}
1498 
1499 		remainder = (size_t)&data[length] - (size_t)datap;
1500 
1501 		/* Incomplete last block. */
1502 		if (remainder > 0 && remainder < BLOWFISH_BLOCK_LEN) {
1503 			bcopy(datap, (uchar_t *)&ctx->bc_remainder, remainder);
1504 			ctx->bc_remainder_len = remainder;
1505 			ctx->bc_lastp = lastp;
1506 			ctx->bc_copy_to = datap;
1507 			return (0);
1508 		}
1509 		ctx->bc_copy_to = NULL;
1510 
1511 	} while (remainder > 0);
1512 
1513 	ctx->bc_lastp = lastp;
1514 /* EXPORT DELETE END */
1515 	return (0);
1516 }
1517 
1518 /* ARGSUSED */
1519 static int
1520 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx,
1521     crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism,
1522     crypto_key_t *key, int kmflag)
1523 {
1524 	int rv = CRYPTO_SUCCESS;
1525 
1526 /* EXPORT DELETE START */
1527 
1528 	void *keysched;
1529 	size_t size;
1530 
1531 	if (template == NULL) {
1532 		if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL)
1533 			return (CRYPTO_HOST_MEMORY);
1534 		/*
1535 		 * Initialize key schedule.
1536 		 * Key length is stored in the key.
1537 		 */
1538 		if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS)
1539 			kmem_free(keysched, size);
1540 
1541 		blowfish_ctx->bc_flags = BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE;
1542 		blowfish_ctx->bc_keysched_len = size;
1543 	} else {
1544 		keysched = template;
1545 	}
1546 
1547 	if (mechanism->cm_type == BF_CBC_MECH_INFO_TYPE) {
1548 		/*
1549 		 * Copy IV into BLOWFISH context.
1550 		 *
1551 		 * If cm_param == NULL then the IV comes from the
1552 		 * cd_miscdata field in the crypto_data structure.
1553 		 */
1554 		if (mechanism->cm_param != NULL) {
1555 			ASSERT(mechanism->cm_param_len == BLOWFISH_BLOCK_LEN);
1556 			if (IS_P2ALIGNED(mechanism->cm_param,
1557 			    sizeof (uint64_t))) {
1558 				/* LINTED: pointer alignment */
1559 				blowfish_ctx->bc_iv =
1560 				    *(uint64_t *)mechanism->cm_param;
1561 			} else {
1562 				uint8_t *iv8;
1563 				uint8_t *p8;
1564 				iv8 = (uint8_t *)&blowfish_ctx->bc_iv;
1565 				p8 = (uint8_t *)&mechanism->cm_param[0];
1566 
1567 				BLOWFISH_COPY_BLOCK(p8, iv8);
1568 			}
1569 		}
1570 
1571 		blowfish_ctx->bc_lastp = (uint8_t *)&blowfish_ctx->bc_iv;
1572 		blowfish_ctx->bc_flags |= BLOWFISH_CBC_MODE;
1573 	}
1574 	blowfish_ctx->bc_keysched = keysched;
1575 
1576 /* EXPORT DELETE END */
1577 
1578 	return (rv);
1579 }
1580