xref: /titanic_52/usr/src/uts/common/crypto/io/blowfish.c (revision 8475e04352e630e4bd0f59a283286ee2475a14ce)
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 2008 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 <modes/modes.h>
43 #include <blowfish/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"
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 	kmflag = crypto_kmflag(req);
329 	switch (mechanism->cm_type) {
330 	case BLOWFISH_ECB_MECH_INFO_TYPE:
331 		blowfish_ctx = ecb_alloc_ctx(kmflag);
332 		break;
333 	case BLOWFISH_CBC_MECH_INFO_TYPE:
334 		blowfish_ctx = cbc_alloc_ctx(kmflag);
335 		break;
336 	}
337 	if (blowfish_ctx == NULL)
338 		return (CRYPTO_HOST_MEMORY);
339 
340 	rv = blowfish_common_init_ctx(blowfish_ctx, template, mechanism,
341 	    key, kmflag);
342 	if (rv != CRYPTO_SUCCESS) {
343 		crypto_free_mode_ctx(blowfish_ctx);
344 		return (rv);
345 	}
346 
347 	ctx->cc_provider_private = blowfish_ctx;
348 
349 /* EXPORT DELETE END */
350 
351 	return (CRYPTO_SUCCESS);
352 }
353 
354 static void
355 blowfish_copy_block64(uint8_t *in, uint64_t *out)
356 {
357 	if (IS_P2ALIGNED(in, sizeof (uint64_t))) {
358 		/* LINTED: pointer alignment */
359 		out[0] = *(uint64_t *)&in[0];
360 	} else {
361 		uint8_t *iv8 = (uint8_t *)&out[0];
362 
363 		BLOWFISH_COPY_BLOCK(in, iv8);
364 	}
365 }
366 
367 /* ARGSUSED */
368 static int
369 blowfish_encrypt(crypto_ctx_t *ctx, crypto_data_t *plaintext,
370     crypto_data_t *ciphertext, crypto_req_handle_t req)
371 {
372 	int ret;
373 
374 /* EXPORT DELETE START */
375 
376 	blowfish_ctx_t *blowfish_ctx;
377 
378 	/*
379 	 * Plaintext must be a multiple of blowfish block size.
380 	 * This test only works for non-padded mechanisms
381 	 * when blocksize is 2^N.
382 	 */
383 	if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
384 		return (CRYPTO_DATA_LEN_RANGE);
385 
386 	ASSERT(ctx->cc_provider_private != NULL);
387 	blowfish_ctx = ctx->cc_provider_private;
388 
389 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
390 
391 	/*
392 	 * We need to just return the length needed to store the output.
393 	 * We should not destroy the context for the following case.
394 	 */
395 	if (ciphertext->cd_length < plaintext->cd_length) {
396 		ciphertext->cd_length = plaintext->cd_length;
397 		return (CRYPTO_BUFFER_TOO_SMALL);
398 	}
399 
400 	/*
401 	 * Do an update on the specified input data.
402 	 */
403 	ret = blowfish_encrypt_update(ctx, plaintext, ciphertext, req);
404 	ASSERT(blowfish_ctx->bc_remainder_len  == 0);
405 	(void) blowfish_free_context(ctx);
406 
407 /* EXPORT DELETE END */
408 
409 	/* LINTED */
410 	return (ret);
411 }
412 
413 /* ARGSUSED */
414 static int
415 blowfish_decrypt(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
416     crypto_data_t *plaintext, crypto_req_handle_t req)
417 {
418 	int ret;
419 
420 /* EXPORT DELETE START */
421 
422 	blowfish_ctx_t *blowfish_ctx;
423 
424 	/*
425 	 * Ciphertext must be a multiple of blowfish block size.
426 	 * This test only works for non-padded mechanisms
427 	 * when blocksize is 2^N.
428 	 */
429 	if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
430 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
431 
432 	ASSERT(ctx->cc_provider_private != NULL);
433 	blowfish_ctx = ctx->cc_provider_private;
434 
435 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
436 
437 	/*
438 	 * We need to just return the length needed to store the output.
439 	 * We should not destroy the context for the following case.
440 	 */
441 	if (plaintext->cd_length < ciphertext->cd_length) {
442 		plaintext->cd_length = ciphertext->cd_length;
443 		return (CRYPTO_BUFFER_TOO_SMALL);
444 	}
445 
446 	/*
447 	 * Do an update on the specified input data.
448 	 */
449 	ret = blowfish_decrypt_update(ctx, ciphertext, plaintext, req);
450 	ASSERT(blowfish_ctx->bc_remainder_len == 0);
451 	(void) blowfish_free_context(ctx);
452 
453 /* EXPORT DELETE END */
454 
455 	/* LINTED */
456 	return (ret);
457 }
458 
459 /* ARGSUSED */
460 static int
461 blowfish_encrypt_update(crypto_ctx_t *ctx, crypto_data_t *plaintext,
462     crypto_data_t *ciphertext, crypto_req_handle_t req)
463 {
464 	off_t saved_offset;
465 	size_t saved_length, out_len;
466 	int ret = CRYPTO_SUCCESS;
467 
468 	ASSERT(ctx->cc_provider_private != NULL);
469 
470 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
471 
472 	/* compute number of bytes that will hold the ciphertext */
473 	out_len =
474 	    ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
475 	out_len += plaintext->cd_length;
476 	out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
477 
478 	/* return length needed to store the output */
479 	if (ciphertext->cd_length < out_len) {
480 		ciphertext->cd_length = out_len;
481 		return (CRYPTO_BUFFER_TOO_SMALL);
482 	}
483 
484 	saved_offset = ciphertext->cd_offset;
485 	saved_length = ciphertext->cd_length;
486 
487 	/*
488 	 * Do the blowfish update on the specified input data.
489 	 */
490 	switch (plaintext->cd_format) {
491 	case CRYPTO_DATA_RAW:
492 		ret = crypto_update_iov(ctx->cc_provider_private,
493 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
494 		    blowfish_copy_block64);
495 		break;
496 	case CRYPTO_DATA_UIO:
497 		ret = crypto_update_uio(ctx->cc_provider_private,
498 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
499 		    blowfish_copy_block64);
500 		break;
501 	case CRYPTO_DATA_MBLK:
502 		ret = crypto_update_mp(ctx->cc_provider_private,
503 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
504 		    blowfish_copy_block64);
505 		break;
506 	default:
507 		ret = CRYPTO_ARGUMENTS_BAD;
508 	}
509 
510 	if (ret == CRYPTO_SUCCESS) {
511 		if (plaintext != ciphertext)
512 			ciphertext->cd_length =
513 			    ciphertext->cd_offset - saved_offset;
514 	} else {
515 		ciphertext->cd_length = saved_length;
516 	}
517 	ciphertext->cd_offset = saved_offset;
518 
519 	return (ret);
520 }
521 
522 /* ARGSUSED */
523 static int
524 blowfish_decrypt_update(crypto_ctx_t *ctx, crypto_data_t *ciphertext,
525     crypto_data_t *plaintext, crypto_req_handle_t req)
526 {
527 	off_t saved_offset;
528 	size_t saved_length, out_len;
529 	int ret = CRYPTO_SUCCESS;
530 
531 	ASSERT(ctx->cc_provider_private != NULL);
532 
533 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
534 
535 	/* compute number of bytes that will hold the plaintext */
536 	out_len =
537 	    ((blowfish_ctx_t *)ctx->cc_provider_private)->bc_remainder_len;
538 	out_len += ciphertext->cd_length;
539 	out_len &= ~(BLOWFISH_BLOCK_LEN - 1);
540 
541 	/* return length needed to store the output */
542 	if (plaintext->cd_length < out_len) {
543 		plaintext->cd_length = out_len;
544 		return (CRYPTO_BUFFER_TOO_SMALL);
545 	}
546 
547 	saved_offset = plaintext->cd_offset;
548 	saved_length = plaintext->cd_length;
549 
550 	/*
551 	 * Do the blowfish update on the specified input data.
552 	 */
553 	switch (ciphertext->cd_format) {
554 	case CRYPTO_DATA_RAW:
555 		ret = crypto_update_iov(ctx->cc_provider_private,
556 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
557 		    blowfish_copy_block64);
558 		break;
559 	case CRYPTO_DATA_UIO:
560 		ret = crypto_update_uio(ctx->cc_provider_private,
561 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
562 		    blowfish_copy_block64);
563 		break;
564 	case CRYPTO_DATA_MBLK:
565 		ret = crypto_update_mp(ctx->cc_provider_private,
566 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
567 		    blowfish_copy_block64);
568 		break;
569 	default:
570 		ret = CRYPTO_ARGUMENTS_BAD;
571 	}
572 
573 	if (ret == CRYPTO_SUCCESS) {
574 		if (ciphertext != plaintext)
575 			plaintext->cd_length =
576 			    plaintext->cd_offset - saved_offset;
577 	} else {
578 		plaintext->cd_length = saved_length;
579 	}
580 	plaintext->cd_offset = saved_offset;
581 
582 	return (ret);
583 }
584 
585 /* ARGSUSED */
586 static int
587 blowfish_encrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
588     crypto_req_handle_t req)
589 {
590 
591 /* EXPORT DELETE START */
592 
593 	blowfish_ctx_t *blowfish_ctx;
594 
595 	ASSERT(ctx->cc_provider_private != NULL);
596 	blowfish_ctx = ctx->cc_provider_private;
597 
598 	/*
599 	 * There must be no unprocessed data.
600 	 * This happens if the length of the last data is
601 	 * not a multiple of the BLOWFISH block length.
602 	 */
603 	if (blowfish_ctx->bc_remainder_len > 0)
604 		return (CRYPTO_DATA_LEN_RANGE);
605 
606 	(void) blowfish_free_context(ctx);
607 	data->cd_length = 0;
608 
609 /* EXPORT DELETE END */
610 
611 	return (CRYPTO_SUCCESS);
612 }
613 
614 /* ARGSUSED */
615 static int
616 blowfish_decrypt_final(crypto_ctx_t *ctx, crypto_data_t *data,
617     crypto_req_handle_t req)
618 {
619 
620 /* EXPORT DELETE START */
621 
622 	blowfish_ctx_t *blowfish_ctx;
623 
624 	ASSERT(ctx->cc_provider_private != NULL);
625 	blowfish_ctx = ctx->cc_provider_private;
626 
627 	/*
628 	 * There must be no unprocessed ciphertext.
629 	 * This happens if the length of the last ciphertext is
630 	 * not a multiple of the BLOWFISH block length.
631 	 */
632 	if (blowfish_ctx->bc_remainder_len > 0)
633 		return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE);
634 
635 	(void) blowfish_free_context(ctx);
636 	data->cd_length = 0;
637 
638 /* EXPORT DELETE END */
639 
640 	return (CRYPTO_SUCCESS);
641 }
642 
643 /* ARGSUSED */
644 static int
645 blowfish_encrypt_atomic(crypto_provider_handle_t provider,
646     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
647     crypto_key_t *key, crypto_data_t *plaintext, crypto_data_t *ciphertext,
648     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
649 {
650 	blowfish_ctx_t blowfish_ctx;	/* on the stack */
651 	off_t saved_offset;
652 	size_t saved_length;
653 	int ret;
654 
655 	BLOWFISH_ARG_INPLACE(plaintext, ciphertext);
656 
657 	/*
658 	 * Plaintext must be a multiple of blowfish block size.
659 	 * This test only works for non-padded mechanisms
660 	 * when blocksize is 2^N.
661 	 */
662 	if ((plaintext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
663 		return (CRYPTO_DATA_LEN_RANGE);
664 
665 	/* return length needed to store the output */
666 	if (ciphertext->cd_length < plaintext->cd_length) {
667 		ciphertext->cd_length = plaintext->cd_length;
668 		return (CRYPTO_BUFFER_TOO_SMALL);
669 	}
670 
671 	if (!BLOWFISH_VALID_MECH(mechanism))
672 		return (CRYPTO_MECHANISM_INVALID);
673 
674 	if (mechanism->cm_param_len != 0 &&
675 	    mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
676 		return (CRYPTO_MECHANISM_PARAM_INVALID);
677 
678 	bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
679 
680 	ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
681 	    key, crypto_kmflag(req));
682 	if (ret != CRYPTO_SUCCESS)
683 		return (ret);
684 
685 	saved_offset = ciphertext->cd_offset;
686 	saved_length = ciphertext->cd_length;
687 
688 	/*
689 	 * Do an update on the specified input data.
690 	 */
691 	switch (plaintext->cd_format) {
692 	case CRYPTO_DATA_RAW:
693 		ret = crypto_update_iov(&blowfish_ctx,
694 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
695 		    blowfish_copy_block64);
696 		break;
697 	case CRYPTO_DATA_UIO:
698 		ret = crypto_update_uio(&blowfish_ctx,
699 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
700 		    blowfish_copy_block64);
701 		break;
702 	case CRYPTO_DATA_MBLK:
703 		ret = crypto_update_mp((void *)&blowfish_ctx,
704 		    plaintext, ciphertext, blowfish_encrypt_contiguous_blocks,
705 		    blowfish_copy_block64);
706 		break;
707 	default:
708 		ret = CRYPTO_ARGUMENTS_BAD;
709 	}
710 
711 	if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
712 		bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
713 		kmem_free(blowfish_ctx.bc_keysched,
714 		    blowfish_ctx.bc_keysched_len);
715 	}
716 
717 	if (ret == CRYPTO_SUCCESS) {
718 		ASSERT(blowfish_ctx.bc_remainder_len == 0);
719 		if (plaintext != ciphertext)
720 			ciphertext->cd_length =
721 			    ciphertext->cd_offset - saved_offset;
722 	} else {
723 		ciphertext->cd_length = saved_length;
724 	}
725 	ciphertext->cd_offset = saved_offset;
726 
727 	return (ret);
728 }
729 
730 /* ARGSUSED */
731 static int
732 blowfish_decrypt_atomic(crypto_provider_handle_t provider,
733     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
734     crypto_key_t *key, crypto_data_t *ciphertext, crypto_data_t *plaintext,
735     crypto_spi_ctx_template_t template, crypto_req_handle_t req)
736 {
737 	blowfish_ctx_t blowfish_ctx;	/* on the stack */
738 	off_t saved_offset;
739 	size_t saved_length;
740 	int ret;
741 
742 	BLOWFISH_ARG_INPLACE(ciphertext, plaintext);
743 
744 	/*
745 	 * Ciphertext must be a multiple of blowfish block size.
746 	 * This test only works for non-padded mechanisms
747 	 * when blocksize is 2^N.
748 	 */
749 	if ((ciphertext->cd_length & (BLOWFISH_BLOCK_LEN - 1)) != 0)
750 		return (CRYPTO_DATA_LEN_RANGE);
751 
752 	/* return length needed to store the output */
753 	if (plaintext->cd_length < ciphertext->cd_length) {
754 		plaintext->cd_length = ciphertext->cd_length;
755 		return (CRYPTO_BUFFER_TOO_SMALL);
756 	}
757 
758 	if (!BLOWFISH_VALID_MECH(mechanism))
759 		return (CRYPTO_MECHANISM_INVALID);
760 
761 	if (mechanism->cm_param_len != 0 &&
762 	    mechanism->cm_param_len != BLOWFISH_BLOCK_LEN)
763 		return (CRYPTO_MECHANISM_PARAM_INVALID);
764 
765 	bzero(&blowfish_ctx, sizeof (blowfish_ctx_t));
766 
767 	ret = blowfish_common_init_ctx(&blowfish_ctx, template, mechanism,
768 	    key, crypto_kmflag(req));
769 	if (ret != CRYPTO_SUCCESS)
770 		return (ret);
771 
772 	saved_offset = plaintext->cd_offset;
773 	saved_length = plaintext->cd_length;
774 
775 	/*
776 	 * Do an update on the specified input data.
777 	 */
778 	switch (ciphertext->cd_format) {
779 	case CRYPTO_DATA_RAW:
780 		ret = crypto_update_iov(&blowfish_ctx,
781 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
782 		    blowfish_copy_block64);
783 		break;
784 	case CRYPTO_DATA_UIO:
785 		ret = crypto_update_uio(&blowfish_ctx,
786 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
787 		    blowfish_copy_block64);
788 		break;
789 	case CRYPTO_DATA_MBLK:
790 		ret = crypto_update_mp(&blowfish_ctx,
791 		    ciphertext, plaintext, blowfish_decrypt_contiguous_blocks,
792 		    blowfish_copy_block64);
793 		break;
794 	default:
795 		ret = CRYPTO_ARGUMENTS_BAD;
796 	}
797 
798 	if (blowfish_ctx.bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
799 		bzero(blowfish_ctx.bc_keysched, blowfish_ctx.bc_keysched_len);
800 		kmem_free(blowfish_ctx.bc_keysched,
801 		    blowfish_ctx.bc_keysched_len);
802 	}
803 
804 	if (ret == CRYPTO_SUCCESS) {
805 		ASSERT(blowfish_ctx.bc_remainder_len == 0);
806 		if (ciphertext != plaintext)
807 			plaintext->cd_length =
808 			    plaintext->cd_offset - saved_offset;
809 	} else {
810 		plaintext->cd_length = saved_length;
811 	}
812 	plaintext->cd_offset = saved_offset;
813 
814 	return (ret);
815 }
816 
817 /*
818  * KCF software provider context template entry points.
819  */
820 /* ARGSUSED */
821 static int
822 blowfish_create_ctx_template(crypto_provider_handle_t provider,
823     crypto_mechanism_t *mechanism, crypto_key_t *key,
824     crypto_spi_ctx_template_t *tmpl, size_t *tmpl_size, crypto_req_handle_t req)
825 {
826 
827 /* EXPORT DELETE START */
828 
829 	void *keysched;
830 	size_t size;
831 	int rv;
832 
833 	if (!BLOWFISH_VALID_MECH(mechanism))
834 		return (CRYPTO_MECHANISM_INVALID);
835 
836 	if ((keysched = blowfish_alloc_keysched(&size,
837 	    crypto_kmflag(req))) == NULL) {
838 		return (CRYPTO_HOST_MEMORY);
839 	}
840 
841 	/*
842 	 * Initialize key schedule.  Key length information is stored
843 	 * in the key.
844 	 */
845 	if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS) {
846 		bzero(keysched, size);
847 		kmem_free(keysched, size);
848 		return (rv);
849 	}
850 
851 	*tmpl = keysched;
852 	*tmpl_size = size;
853 
854 /* EXPORT DELETE END */
855 
856 	return (CRYPTO_SUCCESS);
857 }
858 
859 /* ARGSUSED */
860 static int
861 blowfish_free_context(crypto_ctx_t *ctx)
862 {
863 	blowfish_ctx_t *blowfish_ctx = ctx->cc_provider_private;
864 
865 	if (blowfish_ctx != NULL) {
866 		if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
867 			ASSERT(blowfish_ctx->bc_keysched_len != 0);
868 			bzero(blowfish_ctx->bc_keysched,
869 			    blowfish_ctx->bc_keysched_len);
870 			kmem_free(blowfish_ctx->bc_keysched,
871 			    blowfish_ctx->bc_keysched_len);
872 		}
873 		crypto_free_mode_ctx(blowfish_ctx);
874 		ctx->cc_provider_private = NULL;
875 	}
876 
877 	return (CRYPTO_SUCCESS);
878 }
879 
880 /* ARGSUSED */
881 static int
882 blowfish_common_init_ctx(blowfish_ctx_t *blowfish_ctx,
883     crypto_spi_ctx_template_t *template, crypto_mechanism_t *mechanism,
884     crypto_key_t *key, int kmflag)
885 {
886 	int rv = CRYPTO_SUCCESS;
887 
888 /* EXPORT DELETE START */
889 
890 	void *keysched;
891 	size_t size;
892 
893 	if (template == NULL) {
894 		if ((keysched = blowfish_alloc_keysched(&size, kmflag)) == NULL)
895 			return (CRYPTO_HOST_MEMORY);
896 		/*
897 		 * Initialize key schedule.
898 		 * Key length is stored in the key.
899 		 */
900 		if ((rv = init_keysched(key, keysched)) != CRYPTO_SUCCESS)
901 			kmem_free(keysched, size);
902 
903 		blowfish_ctx->bc_flags |= PROVIDER_OWNS_KEY_SCHEDULE;
904 		blowfish_ctx->bc_keysched_len = size;
905 	} else {
906 		keysched = template;
907 	}
908 	blowfish_ctx->bc_keysched = keysched;
909 
910 	switch (mechanism->cm_type) {
911 	case BLOWFISH_CBC_MECH_INFO_TYPE:
912 		rv = cbc_init_ctx((cbc_ctx_t *)blowfish_ctx,
913 		    mechanism->cm_param, mechanism->cm_param_len,
914 		    BLOWFISH_BLOCK_LEN, blowfish_copy_block64);
915 		break;
916 	case BLOWFISH_ECB_MECH_INFO_TYPE:
917 		blowfish_ctx->bc_flags |= ECB_MODE;
918 	}
919 
920 	if (rv != CRYPTO_SUCCESS) {
921 		if (blowfish_ctx->bc_flags & PROVIDER_OWNS_KEY_SCHEDULE) {
922 			bzero(keysched, size);
923 			kmem_free(keysched, size);
924 		}
925 	}
926 
927 /* EXPORT DELETE END */
928 
929 	return (rv);
930 }
931