xref: /titanic_52/usr/src/uts/common/crypto/io/blowfish.c (revision f44071f6cdb4ecb73e329fbef93e79bb9f23f7cf)
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 (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 /*
29  * Blowfish provider for the Kernel Cryptographic Framework (KCF)
30  */
31 
32 #include <sys/types.h>
33 #include <sys/systm.h>
34 #include <sys/modctl.h>
35 #include <sys/cmn_err.h>
36 #include <sys/ddi.h>
37 #include <sys/crypto/common.h>
38 #include <sys/crypto/spi.h>
39 #include <sys/sysmacros.h>
40 #include <sys/strsun.h>
41 #include <sys/note.h>
42 #include <blowfish_impl.h>
43 #include <blowfish_cbc_crypt.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"
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 	BLOWFISH_ECB_MECH_INFO_TYPE,		/* SUN_CKM_BLOWFISH_ECB */
66 	BLOWFISH_CBC_MECH_INFO_TYPE		/* SUN_CKM_BLOWFISH_CBC */
67 } blowfish_mech_type_t;
68 
69 
70 #define	BLOWFISH_COPY_BLOCK(src, dst) \
71 	(dst)[0] = (src)[0]; \
72 	(dst)[1] = (src)[1]; \
73 	(dst)[2] = (src)[2]; \
74 	(dst)[3] = (src)[3]; \
75 	(dst)[4] = (src)[4]; \
76 	(dst)[5] = (src)[5]; \
77 	(dst)[6] = (src)[6]; \
78 	(dst)[7] = (src)[7]
79 
80 #define	BLOWFISH_XOR_BLOCK(src, dst) \
81 	(dst)[0] ^= (src)[0]; \
82 	(dst)[1] ^= (src)[1]; \
83 	(dst)[2] ^= (src)[2]; \
84 	(dst)[3] ^= (src)[3]; \
85 	(dst)[4] ^= (src)[4]; \
86 	(dst)[5] ^= (src)[5]; \
87 	(dst)[6] ^= (src)[6]; \
88 	(dst)[7] ^= (src)[7]
89 
90 /*
91  * Mechanism info structure passed to KCF during registration.
92  */
93 
94 static crypto_mech_info_t blowfish_mech_info_tab[] = {
95 	/* BLOWFISH_ECB */
96 	{SUN_CKM_BLOWFISH_ECB, BLOWFISH_ECB_MECH_INFO_TYPE,
97 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
98 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
99 	    BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS},
100 	/* BLOWFISH_CBC */
101 	{SUN_CKM_BLOWFISH_CBC, BLOWFISH_CBC_MECH_INFO_TYPE,
102 	    CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC |
103 	    CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC,
104 	    BLOWFISH_MINBITS, BLOWFISH_MAXBITS, CRYPTO_KEYSIZE_UNIT_IN_BITS}
105 };
106 
107 #define	BLOWFISH_VALID_MECH(mech)				\
108 	(((mech)->cm_type == BLOWFISH_ECB_MECH_INFO_TYPE ||		\
109 	(mech)->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) ? 1 : 0)
110 
111 /* operations are in-place if the output buffer is NULL */
112 #define	BLOWFISH_ARG_INPLACE(input, output)			\
113 	if ((output) == NULL)					\
114 		(output) = (input);
115 
116 static void blowfish_provider_status(crypto_provider_handle_t, uint_t *);
117 
118 static crypto_control_ops_t blowfish_control_ops = {
119 	blowfish_provider_status
120 };
121 
122 static int blowfish_common_init(crypto_ctx_t *, crypto_mechanism_t *,
123     crypto_key_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
124 static int blowfish_common_init_ctx(blowfish_ctx_t *,
125     crypto_spi_ctx_template_t *, crypto_mechanism_t *, crypto_key_t *, int);
126 static int blowfish_encrypt_final(crypto_ctx_t *, crypto_data_t *,
127     crypto_req_handle_t);
128 static int blowfish_decrypt_final(crypto_ctx_t *, crypto_data_t *,
129     crypto_req_handle_t);
130 
131 static int blowfish_encrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
132     crypto_req_handle_t);
133 static int blowfish_encrypt_update(crypto_ctx_t *, crypto_data_t *,
134     crypto_data_t *, crypto_req_handle_t);
135 static int blowfish_encrypt_atomic(crypto_provider_handle_t,
136     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
137     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
138 
139 static int blowfish_decrypt(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
140     crypto_req_handle_t);
141 static int blowfish_decrypt_update(crypto_ctx_t *, crypto_data_t *,
142     crypto_data_t *, crypto_req_handle_t);
143 static int blowfish_decrypt_atomic(crypto_provider_handle_t,
144     crypto_session_id_t, crypto_mechanism_t *, crypto_key_t *, crypto_data_t *,
145     crypto_data_t *, crypto_spi_ctx_template_t, crypto_req_handle_t);
146 
147 static crypto_cipher_ops_t blowfish_cipher_ops = {
148 	blowfish_common_init,
149 	blowfish_encrypt,
150 	blowfish_encrypt_update,
151 	blowfish_encrypt_final,
152 	blowfish_encrypt_atomic,
153 	blowfish_common_init,
154 	blowfish_decrypt,
155 	blowfish_decrypt_update,
156 	blowfish_decrypt_final,
157 	blowfish_decrypt_atomic
158 };
159 
160 static int blowfish_create_ctx_template(crypto_provider_handle_t,
161     crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
162     size_t *, crypto_req_handle_t);
163 static int blowfish_free_context(crypto_ctx_t *);
164 
165 static crypto_ctx_ops_t blowfish_ctx_ops = {
166 	blowfish_create_ctx_template,
167 	blowfish_free_context
168 };
169 
170 static crypto_ops_t blowfish_crypto_ops = {
171 	&blowfish_control_ops,
172 	NULL,
173 	&blowfish_cipher_ops,
174 	NULL,
175 	NULL,
176 	NULL,
177 	NULL,
178 	NULL,
179 	NULL,
180 	NULL,
181 	NULL,
182 	NULL,
183 	NULL,
184 	&blowfish_ctx_ops
185 };
186 
187 static crypto_provider_info_t blowfish_prov_info = {
188 	CRYPTO_SPI_VERSION_1,
189 	"Blowfish Software Provider",
190 	CRYPTO_SW_PROVIDER,
191 	{&modlinkage},
192 	NULL,
193 	&blowfish_crypto_ops,
194 	sizeof (blowfish_mech_info_tab)/sizeof (crypto_mech_info_t),
195 	blowfish_mech_info_tab
196 };
197 
198 
199 static crypto_kcf_provider_handle_t blowfish_prov_handle = NULL;
200 
201 int
202 _init(void)
203 {
204 	int ret;
205 
206 	/*
207 	 * Register with KCF. If the registration fails, return error.
208 	 */
209 	if ((ret = crypto_register_provider(&blowfish_prov_info,
210 	    &blowfish_prov_handle)) != CRYPTO_SUCCESS) {
211 		cmn_err(CE_WARN, "%s _init: crypto_register_provider() "
212 		    "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret);
213 		return (EACCES);
214 	}
215 
216 	if ((ret = mod_install(&modlinkage)) != 0) {
217 		int rv;
218 
219 		ASSERT(blowfish_prov_handle != NULL);
220 		/* We should not return if the unregister returns busy. */
221 		while ((rv = crypto_unregister_provider(blowfish_prov_handle))
222 		    == CRYPTO_BUSY) {
223 			cmn_err(CE_WARN,
224 			    "%s _init: crypto_unregister_provider() "
225 			    "failed (0x%x). Retrying.",
226 			    CRYPTO_PROVIDER_NAME, rv);
227 			/* wait 10 seconds and try again */
228 			delay(10 * drv_usectohz(1000000));
229 		}
230 	}
231 
232 	return (ret);
233 }
234 
235 int
236 _fini(void)
237 {
238 	int ret;
239 
240 	/*
241 	 * Unregister from KCF if previous registration succeeded.
242 	 */
243 	if (blowfish_prov_handle != NULL) {
244 		if ((ret = crypto_unregister_provider(blowfish_prov_handle)) !=
245 		    CRYPTO_SUCCESS) {
246 			cmn_err(CE_WARN,
247 			    "%s _fini: crypto_unregister_provider() "
248 			    "failed (0x%x)", CRYPTO_PROVIDER_NAME, ret);
249 			return (EBUSY);
250 		}
251 		blowfish_prov_handle = NULL;
252 	}
253 
254 	return (mod_remove(&modlinkage));
255 }
256 
257 int
258 _info(struct modinfo *modinfop)
259 {
260 	return (mod_info(&modlinkage, modinfop));
261 }
262 
263 /*
264  * Initialize key schedules for blowfish
265  */
266 static int
267 init_keysched(crypto_key_t *key, void *keysched)
268 {
269 /* EXPORT DELETE START */
270 	/*
271 	 * Only keys by value are supported by this module.
272 	 */
273 	switch (key->ck_format) {
274 	case CRYPTO_KEY_RAW:
275 		if (key->ck_length < BLOWFISH_MINBITS ||
276 		    key->ck_length > BLOWFISH_MAXBITS) {
277 			return (CRYPTO_KEY_SIZE_RANGE);
278 		}
279 		break;
280 	default:
281 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
282 	}
283 
284 	blowfish_init_keysched(key->ck_data, key->ck_length, keysched);
285 /* EXPORT DELETE END */
286 	return (CRYPTO_SUCCESS);
287 }
288 
289 /*
290  * KCF software provider control entry points.
291  */
292 /* ARGSUSED */
293 static void
294 blowfish_provider_status(crypto_provider_handle_t provider, uint_t *status)
295 {
296 	*status = CRYPTO_PROVIDER_READY;
297 }
298 
299 /*
300  * KCF software provider encrypt entry points.
301  */
302 static int
303 blowfish_common_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
304     crypto_key_t *key, crypto_spi_ctx_template_t template,
305     crypto_req_handle_t req)
306 {
307 
308 /* EXPORT DELETE START */
309 
310 	blowfish_ctx_t *blowfish_ctx;
311 	int rv;
312 	int kmflag;
313 
314 	/*
315 	 * Only keys by value are supported by this module.
316 	 */
317 	if (key->ck_format != CRYPTO_KEY_RAW) {
318 		return (CRYPTO_KEY_TYPE_INCONSISTENT);
319 	}
320 
321 	if (!BLOWFISH_VALID_MECH(mechanism))
322 		return (CRYPTO_MECHANISM_INVALID);
323 
324 	if (mechanism->cm_param != NULL &&
325 	    mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
326 		return (CRYPTO_MECHANISM_PARAM_INVALID);
327 
328 	/*
329 	 * Allocate a blowfish context.
330 	 */
331 	kmflag = crypto_kmflag(req);
332 	blowfish_ctx = kmem_zalloc(sizeof (blowfish_ctx_t), kmflag);
333 	if (blowfish_ctx == NULL)
334 		return (CRYPTO_HOST_MEMORY);
335 
336 	rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism,
337 	    key, kmflag);
338 	if (rv != CRYPTO_SUCCESS) {
339 		kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t));
340 		return (rv);
341 	}
342 
343 	ctx->cc_provider_private = blowfish_ctx;
344 
345 /* EXPORT DELETE END */
346 
347 	return (CRYPTO_SUCCESS);
348 }
349 
350 /*
351  * Helper blowfish encrypt update function for iov input data.
352  */
353 static int
354 blowfish_cipher_update_iov(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input,
355     crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t,
356     crypto_data_t *))
357 {
358 	if (input->cd_miscdata != NULL) {
359 		if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) {
360 			/* LINTED: pointer alignment */
361 			blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata;
362 		} else {
363 			uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0];
364 			uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv;
365 
366 			BLOWFISH_COPY_BLOCK(miscdata8, iv8);
367 		}
368 	}
369 
370 	if (input->cd_raw.iov_len < input->cd_length)
371 		return (CRYPTO_ARGUMENTS_BAD);
372 
373 	return (cipher)(blowfish_ctx, input->cd_raw.iov_base + input->cd_offset,
374 	    input->cd_length, (input == output) ? NULL : output);
375 }
376 
377 /*
378  * Helper blowfish encrypt update function for uio input data.
379  */
380 static int
381 blowfish_cipher_update_uio(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input,
382     crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t,
383     crypto_data_t *))
384 {
385 	uio_t *uiop = input->cd_uio;
386 	off_t offset = input->cd_offset;
387 	size_t length = input->cd_length;
388 	uint_t vec_idx;
389 	size_t cur_len;
390 
391 	if (input->cd_miscdata != NULL) {
392 		if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) {
393 			/*LINTED: pointer alignment */
394 			blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata;
395 		} else {
396 			uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0];
397 			uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv;
398 
399 			BLOWFISH_COPY_BLOCK(miscdata8, iv8);
400 		}
401 	}
402 
403 	if (input->cd_uio->uio_segflg != UIO_SYSSPACE) {
404 		return (CRYPTO_ARGUMENTS_BAD);
405 	}
406 
407 	/*
408 	 * Jump to the first iovec containing data to be
409 	 * processed.
410 	 */
411 	for (vec_idx = 0; vec_idx < uiop->uio_iovcnt &&
412 	    offset >= uiop->uio_iov[vec_idx].iov_len;
413 	    offset -= uiop->uio_iov[vec_idx++].iov_len)
414 		;
415 	if (vec_idx == uiop->uio_iovcnt) {
416 		/*
417 		 * The caller specified an offset that is larger than the
418 		 * total size of the buffers it provided.
419 		 */
420 		return (CRYPTO_DATA_LEN_RANGE);
421 	}
422 
423 	/*
424 	 * Now process the iovecs.
425 	 */
426 	while (vec_idx < uiop->uio_iovcnt && length > 0) {
427 		cur_len = MIN(uiop->uio_iov[vec_idx].iov_len -
428 		    offset, length);
429 
430 		(cipher)(blowfish_ctx, uiop->uio_iov[vec_idx].iov_base +
431 		    offset, cur_len, (input == output) ? NULL : output);
432 
433 		length -= cur_len;
434 		vec_idx++;
435 		offset = 0;
436 	}
437 
438 	if (vec_idx == uiop->uio_iovcnt && length > 0) {
439 		/*
440 		 * The end of the specified iovec's was reached but
441 		 * the length requested could not be processed, i.e.
442 		 * The caller requested to digest more data than it provided.
443 		 */
444 
445 		return (CRYPTO_DATA_LEN_RANGE);
446 	}
447 
448 	return (CRYPTO_SUCCESS);
449 }
450 
451 /*
452  * Helper blowfish encrypt update function for mblk input data.
453  */
454 static int
455 blowfish_cipher_update_mp(blowfish_ctx_t *blowfish_ctx, crypto_data_t *input,
456     crypto_data_t *output, int (*cipher)(blowfish_ctx_t *, caddr_t, size_t,
457     crypto_data_t *))
458 {
459 	off_t offset = input->cd_offset;
460 	size_t length = input->cd_length;
461 	mblk_t *mp;
462 	size_t cur_len;
463 
464 	if (input->cd_miscdata != NULL) {
465 		if (IS_P2ALIGNED(input->cd_miscdata, sizeof (uint64_t))) {
466 			/*LINTED: pointer alignment */
467 			blowfish_ctx->bc_iv = *(uint64_t *)input->cd_miscdata;
468 		} else {
469 			uint8_t *miscdata8 = (uint8_t *)&input->cd_miscdata[0];
470 			uint8_t *iv8 = (uint8_t *)&blowfish_ctx->bc_iv;
471 
472 			BLOWFISH_COPY_BLOCK(miscdata8, iv8);
473 		}
474 	}
475 
476 	/*
477 	 * Jump to the first mblk_t containing data to be processed.
478 	 */
479 	for (mp = input->cd_mp; mp != NULL && offset >= MBLKL(mp);
480 	    offset -= MBLKL(mp), mp = mp->b_cont)
481 		;
482 	if (mp == NULL) {
483 		/*
484 		 * The caller specified an offset that is larger than the
485 		 * total size of the buffers it provided.
486 		 */
487 		return (CRYPTO_DATA_LEN_RANGE);
488 	}
489 
490 	/*
491 	 * Now do the processing on the mblk chain.
492 	 */
493 	while (mp != NULL && length > 0) {
494 		cur_len = MIN(MBLKL(mp) - offset, length);
495 		(cipher)(blowfish_ctx, (char *)(mp->b_rptr + offset), cur_len,
496 		    (input == output) ? NULL : output);
497 
498 		length -= cur_len;
499 		offset = 0;
500 		mp = mp->b_cont;
501 	}
502 
503 	if (mp == NULL && length > 0) {
504 		/*
505 		 * The end of the mblk was reached but the length requested
506 		 * could not be processed, i.e. The caller requested
507 		 * to digest more data than it provided.
508 		 */
509 		return (CRYPTO_DATA_LEN_RANGE);
510 	}
511 
512 	return (CRYPTO_SUCCESS);
513 }
514 
515 /* ARGSUSED */
516 static int
517 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
518     crypto_data_t *ciphertext, crypto_req_handle_t req)
519 {
520 	int ret;
521 
522 /* EXPORT DELETE START */
523 
524 	blowfish_ctx_t *blowfish_ctx;
525 
526 	/*
527 	 * Plaintext must be a multiple of blowfish block size.
528 	 * This test only works for non-padded mechanisms
529 	 * when blocksize is 2^N.
530 	 */
531 	if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
532 		return (CRYPTO_DATA_LEN_RANGE);
533 
534 	ASSERT(ctx->cc_provider_private != NULL);
535 	blowfish_ctx = ctx->cc_provider_private;
536 
537 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
538 
539 	/*
540 	 * We need to just return the length needed to store the output.
541 	 * We should not destroy the context for the following case.
542 	 */
543 	if (ciphertext->cd_length < plaintext->cd_length) {
544 		ciphertext->cd_length = plaintext->cd_length;
545 		return (CRYPTO_BUFFER_TOO_SMALL);
546 	}
547 
548 	/*
549 	 * Do an update on the specified input data.
550 	 */
551 	ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req);
552 	ASSERT(blowfish_ctx->bc_remainder_len  == 0);
553 	(void) blowfish_free_context(ctx);
554 
555 /* EXPORT DELETE END */
556 
557 	/* LINTED */
558 	return (ret);
559 }
560 
561 /* ARGSUSED */
562 static int
563 blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
564     crypto_data_t *plaintext, crypto_req_handle_t req)
565 {
566 	int ret;
567 
568 /* EXPORT DELETE START */
569 
570 	blowfish_ctx_t *blowfish_ctx;
571 
572 	/*
573 	 * Ciphertext 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 ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
578 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
579 
580 	ASSERT(ctx->cc_provider_private != NULL);
581 	blowfish_ctx = ctx->cc_provider_private;
582 
583 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
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 (plaintext->cd_length < ciphertext->cd_length) {
590 		plaintext->cd_length = ciphertext->cd_length;
591 		return (CRYPTO_BUFFER_TOO_SMALL);
592 	}
593 
594 	/*
595 	 * Do an update on the specified input data.
596 	 */
597 	ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, 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_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
610     crypto_data_t *ciphertext, crypto_req_handle_t req)
611 {
612 	off_t saved_offset;
613 	size_t saved_length, out_len;
614 	int ret = CRYPTO_SUCCESS;
615 
616 	ASSERT(ctx->cc_provider_private != NULL);
617 
618 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
619 
620 	/* compute number of bytes that will hold the ciphertext */
621 	out_len =
622 	    ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
623 	out_len += plaintext->cd_length;
624 	out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
625 
626 	/* return length needed to store the output */
627 	if (ciphertext->cd_length < out_len) {
628 		ciphertext->cd_length = out_len;
629 		return (CRYPTO_BUFFER_TOO_SMALL);
630 	}
631 
632 	saved_offset = ciphertext->cd_offset;
633 	saved_length = ciphertext->cd_length;
634 
635 	/*
636 	 * Do the blowfish update on the specified input data.
637 	 */
638 	switch (plaintext->cd_format) {
639 	case CRYPTO_DATA_RAW:
640 		ret = blowfish_cipher_update_iov(ctx->cc_provider_private,
641 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
642 		break;
643 	case CRYPTO_DATA_UIO:
644 		ret = blowfish_cipher_update_uio(ctx->cc_provider_private,
645 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
646 		break;
647 	case CRYPTO_DATA_MBLK:
648 		ret = blowfish_cipher_update_mp(ctx->cc_provider_private,
649 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
650 		break;
651 	default:
652 		ret = CRYPTO_ARGUMENTS_BAD;
653 	}
654 
655 	if (ret == CRYPTO_SUCCESS) {
656 		if (plaintext != ciphertext)
657 			ciphertext->cd_length =
658 			    ciphertext->cd_offset - saved_offset;
659 	} else {
660 		ciphertext->cd_length = saved_length;
661 	}
662 	ciphertext->cd_offset = saved_offset;
663 
664 	return (ret);
665 }
666 
667 /* ARGSUSED */
668 static int
669 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
670     crypto_data_t *plaintext, crypto_req_handle_t req)
671 {
672 	off_t saved_offset;
673 	size_t saved_length, out_len;
674 	int ret = CRYPTO_SUCCESS;
675 
676 	ASSERT(ctx->cc_provider_private != NULL);
677 
678 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
679 
680 	/* compute number of bytes that will hold the plaintext */
681 	out_len =
682 	    ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
683 	out_len += ciphertext->cd_length;
684 	out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
685 
686 	/* return length needed to store the output */
687 	if (plaintext->cd_length < out_len) {
688 		plaintext->cd_length = out_len;
689 		return (CRYPTO_BUFFER_TOO_SMALL);
690 	}
691 
692 	saved_offset = plaintext->cd_offset;
693 	saved_length = plaintext->cd_length;
694 
695 	/*
696 	 * Do the blowfish update on the specified input data.
697 	 */
698 	switch (ciphertext->cd_format) {
699 	case CRYPTO_DATA_RAW:
700 		ret = blowfish_cipher_update_iov(ctx->cc_provider_private,
701 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
702 		break;
703 	case CRYPTO_DATA_UIO:
704 		ret = blowfish_cipher_update_uio(ctx->cc_provider_private,
705 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
706 		break;
707 	case CRYPTO_DATA_MBLK:
708 		ret = blowfish_cipher_update_mp(ctx->cc_provider_private,
709 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
710 		break;
711 	default:
712 		ret = CRYPTO_ARGUMENTS_BAD;
713 	}
714 
715 	if (ret == CRYPTO_SUCCESS) {
716 		if (ciphertext != plaintext)
717 			plaintext->cd_length =
718 			    plaintext->cd_offset - saved_offset;
719 	} else {
720 		plaintext->cd_length = saved_length;
721 	}
722 	plaintext->cd_offset = saved_offset;
723 
724 	return (ret);
725 }
726 
727 /* ARGSUSED */
728 static int
729 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
730     crypto_req_handle_t req)
731 {
732 
733 /* EXPORT DELETE START */
734 
735 	blowfish_ctx_t *blowfish_ctx;
736 
737 	ASSERT(ctx->cc_provider_private != NULL);
738 	blowfish_ctx = ctx->cc_provider_private;
739 
740 	/*
741 	 * There must be no unprocessed data.
742 	 * This happens if the length of the last data is
743 	 * not a multiple of the BLOWFISH block length.
744 	 */
745 	if (blowfish_ctx->bc_remainder_len > 0)
746 		return (CRYPTO_DATA_LEN_RANGE);
747 
748 	(void) blowfish_free_context(ctx);
749 	data->cd_length = 0;
750 
751 /* EXPORT DELETE END */
752 
753 	return (CRYPTO_SUCCESS);
754 }
755 
756 /* ARGSUSED */
757 static int
758 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
759     crypto_req_handle_t req)
760 {
761 
762 /* EXPORT DELETE START */
763 
764 	blowfish_ctx_t *blowfish_ctx;
765 
766 	ASSERT(ctx->cc_provider_private != NULL);
767 	blowfish_ctx = ctx->cc_provider_private;
768 
769 	/*
770 	 * There must be no unprocessed ciphertext.
771 	 * This happens if the length of the last ciphertext is
772 	 * not a multiple of the BLOWFISH block length.
773 	 */
774 	if (blowfish_ctx->bc_remainder_len > 0)
775 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
776 
777 	(void) blowfish_free_context(ctx);
778 	data->cd_length = 0;
779 
780 /* EXPORT DELETE END */
781 
782 	return (CRYPTO_SUCCESS);
783 }
784 
785 /* ARGSUSED */
786 static int
787 blowfish_encrypt_atomic(crypto_provider_handle_t provider,
788     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
789     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
790     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
791 {
792 	blowfish_ctx_t blowfish_ctx;	/* on the stack */
793 	off_t saved_offset;
794 	size_t saved_length;
795 	int ret;
796 
797 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
798 
799 	/*
800 	 * Plaintext must be a multiple of blowfish block size.
801 	 * This test only works for non-padded mechanisms
802 	 * when blocksize is 2^N.
803 	 */
804 	if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
805 		return (CRYPTO_DATA_LEN_RANGE);
806 
807 	/* return length needed to store the output */
808 	if (ciphertext->cd_length < plaintext->cd_length) {
809 		ciphertext->cd_length = plaintext->cd_length;
810 		return (CRYPTO_BUFFER_TOO_SMALL);
811 	}
812 
813 	if (!BLOWFISH_VALID_MECH(mechanism))
814 		return (CRYPTO_MECHANISM_INVALID);
815 
816 	if (mechanism->cm_param_len != 0 &&
817 	    mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
818 		return (CRYPTO_MECHANISM_PARAM_INVALID);
819 
820 	bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
821 
822 	ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
823 	    key, crypto_kmflag(req));
824 	if (ret != CRYPTO_SUCCESS)
825 		return (ret);
826 
827 	saved_offset = ciphertext->cd_offset;
828 	saved_length = ciphertext->cd_length;
829 
830 	/*
831 	 * Do an update on the specified input data.
832 	 */
833 	switch (plaintext->cd_format) {
834 	case CRYPTO_DATA_RAW:
835 		ret = blowfish_cipher_update_iov(&blowfish_ctx,
836 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
837 		break;
838 	case CRYPTO_DATA_UIO:
839 		ret = blowfish_cipher_update_uio(&blowfish_ctx,
840 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
841 		break;
842 	case CRYPTO_DATA_MBLK:
843 		ret = blowfish_cipher_update_mp(&blowfish_ctx,
844 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks);
845 		break;
846 	default:
847 		ret = CRYPTO_ARGUMENTS_BAD;
848 	}
849 
850 	if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) {
851 		bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
852 		kmem_free(blowfish_ctx.bc_keysched,
853 		    blowfish_ctx.bc_keysched_len);
854 	}
855 
856 	if (ret == CRYPTO_SUCCESS) {
857 		ASSERT(blowfish_ctx.bc_remainder_len == 0);
858 		if (plaintext != ciphertext)
859 			ciphertext->cd_length =
860 			    ciphertext->cd_offset - saved_offset;
861 	} else {
862 		ciphertext->cd_length = saved_length;
863 	}
864 	ciphertext->cd_offset = saved_offset;
865 
866 	return (ret);
867 }
868 
869 /* ARGSUSED */
870 static int
871 blowfish_decrypt_atomic(crypto_provider_handle_t provider,
872     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
873     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
874     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
875 {
876 	blowfish_ctx_t blowfish_ctx;	/* on the stack */
877 	off_t saved_offset;
878 	size_t saved_length;
879 	int ret;
880 
881 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
882 
883 	/*
884 	 * Ciphertext must be a multiple of blowfish block size.
885 	 * This test only works for non-padded mechanisms
886 	 * when blocksize is 2^N.
887 	 */
888 	if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
889 		return (CRYPTO_DATA_LEN_RANGE);
890 
891 	/* return length needed to store the output */
892 	if (plaintext->cd_length < ciphertext->cd_length) {
893 		plaintext->cd_length = ciphertext->cd_length;
894 		return (CRYPTO_BUFFER_TOO_SMALL);
895 	}
896 
897 	if (!BLOWFISH_VALID_MECH(mechanism))
898 		return (CRYPTO_MECHANISM_INVALID);
899 
900 	if (mechanism->cm_param_len != 0 &&
901 	    mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
902 		return (CRYPTO_MECHANISM_PARAM_INVALID);
903 
904 	bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
905 
906 	ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
907 	    key, crypto_kmflag(req));
908 	if (ret != CRYPTO_SUCCESS)
909 		return (ret);
910 
911 	saved_offset = plaintext->cd_offset;
912 	saved_length = plaintext->cd_length;
913 
914 	/*
915 	 * Do an update on the specified input data.
916 	 */
917 	switch (ciphertext->cd_format) {
918 	case CRYPTO_DATA_RAW:
919 		ret = blowfish_cipher_update_iov(&blowfish_ctx,
920 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
921 		break;
922 	case CRYPTO_DATA_UIO:
923 		ret = blowfish_cipher_update_uio(&blowfish_ctx,
924 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
925 		break;
926 	case CRYPTO_DATA_MBLK:
927 		ret = blowfish_cipher_update_mp(&blowfish_ctx,
928 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks);
929 		break;
930 	default:
931 		ret = CRYPTO_ARGUMENTS_BAD;
932 	}
933 
934 	if (blowfish_ctx.bc_flags & BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) {
935 		bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
936 		kmem_free(blowfish_ctx.bc_keysched,
937 		    blowfish_ctx.bc_keysched_len);
938 	}
939 
940 	if (ret == CRYPTO_SUCCESS) {
941 		ASSERT(blowfish_ctx.bc_remainder_len == 0);
942 		if (ciphertext != plaintext)
943 			plaintext->cd_length =
944 			    plaintext->cd_offset - saved_offset;
945 	} else {
946 		plaintext->cd_length = saved_length;
947 	}
948 	plaintext->cd_offset = saved_offset;
949 
950 	return (ret);
951 }
952 
953 /*
954  * KCF software provider context template entry points.
955  */
956 /* ARGSUSED */
957 static int
958 blowfish_create_ctx_template(crypto_provider_handle_t provider,
959     crypto_mechanism_t *mechanism, crypto_key_t *key,
960     crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req)
961 {
962 
963 /* EXPORT DELETE START */
964 
965 	void *keysched;
966 	size_t size;
967 	int rv;
968 
969 	if (!BLOWFISH_VALID_MECH(mechanism))
970 		return (CRYPTO_MECHANISM_INVALID);
971 
972 	if ((keysched = blowfish_alloc_keysched(&size,
973 	    crypto_kmflag(req))) == NULL) {
974 		return (CRYPTO_HOST_MEMORY);
975 	}
976 
977 	/*
978 	 * Initialize key schedule.  Key length information is stored
979 	 * in the key.
980 	 */
981 	if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
982 		bzero(keysched, size);
983 		kmem_free(keysched, size);
984 		return (rv);
985 	}
986 
987 	*tmpl = keysched;
988 	*tmpl_size = size;
989 
990 /* EXPORT DELETE END */
991 
992 	return (CRYPTO_SUCCESS);
993 }
994 
995 /* ARGSUSED */
996 static int
997 blowfish_free_context(crypto_ctx_t *ctx)
998 {
999 	blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private;
1000 
1001 	if (blowfish_ctx != NULL) {
1002 		if (blowfish_ctx->bc_flags &
1003 		    BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE) {
1004 			ASSERT(blowfish_ctx->bc_keysched_len != 0);
1005 			bzero(blowfish_ctx->bc_keysched,
1006 			    blowfish_ctx->bc_keysched_len);
1007 			kmem_free(blowfish_ctx->bc_keysched,
1008 			    blowfish_ctx->bc_keysched_len);
1009 		}
1010 		kmem_free(blowfish_ctx, sizeof (blowfish_ctx_t));
1011 		ctx->cc_provider_private = NULL;
1012 	}
1013 
1014 	return (CRYPTO_SUCCESS);
1015 }
1016 
1017 /* ARGSUSED */
1018 static int
1019 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx,
1020     crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism,
1021     crypto_key_t *key, int kmflag)
1022 {
1023 	int rv = CRYPTO_SUCCESS;
1024 
1025 /* EXPORT DELETE START */
1026 
1027 	void *keysched;
1028 	size_t size;
1029 
1030 	if (template == NULL) {
1031 		if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL)
1032 			return (CRYPTO_HOST_MEMORY);
1033 		/*
1034 		 * Initialize key schedule.
1035 		 * Key length is stored in the key.
1036 		 */
1037 		if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS)
1038 			kmem_free(keysched, size);
1039 
1040 		blowfish_ctx->bc_flags = BLOWFISH_PROVIDER_OWNS_KEY_SCHEDULE;
1041 		blowfish_ctx->bc_keysched_len = size;
1042 	} else {
1043 		keysched = template;
1044 	}
1045 
1046 	if (mechanism->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) {
1047 		/*
1048 		 * Copy IV into BLOWFISH context.
1049 		 *
1050 		 * If cm_param == NULL then the IV comes from the
1051 		 * cd_miscdata field in the crypto_data structure.
1052 		 */
1053 		if (mechanism->cm_param != NULL) {
1054 			ASSERT(mechanism->cm_param_len == BLOWFISH_BLOCK_LEN);
1055 			if (IS_P2ALIGNED(mechanism->cm_param,
1056 			    sizeof (uint64_t))) {
1057 				/* LINTED: pointer alignment */
1058 				blowfish_ctx->bc_iv =
1059 				    *(uint64_t *)mechanism->cm_param;
1060 			} else {
1061 				uint8_t *iv8;
1062 				uint8_t *p8;
1063 				iv8 = (uint8_t *)&blowfish_ctx->bc_iv;
1064 				p8 = (uint8_t *)&mechanism->cm_param[0];
1065 
1066 				BLOWFISH_COPY_BLOCK(p8, iv8);
1067 			}
1068 		}
1069 
1070 		blowfish_ctx->bc_lastp = (uint8_t *)&blowfish_ctx->bc_iv;
1071 		blowfish_ctx->bc_flags |= BLOWFISH_CBC_MODE;
1072 	}
1073 	blowfish_ctx->bc_keysched = keysched;
1074 
1075 /* EXPORT DELETE END */
1076 
1077 	return (rv);
1078 }
1079