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.
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.
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]
22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Blowfish provider for the Kernel Cryptographic Framework (KCF)
30 #include <sys/types.h>
31 #include <sys/systm.h>
32 #include <sys/modctl.h>
33 #include <sys/cmn_err.h>
35 #include <sys/crypto/common.h>
36 #include <sys/crypto/spi.h>
37 #include <sys/sysmacros.h>
38 #include <sys/strsun.h>
40 #include <modes/modes.h>
41 #include <blowfish/blowfish_impl.h>
43 extern struct mod_ops mod_cryptoops
;
46 * Module linkage information for the kernel.
48 static struct modlcrypto modlcrypto
= {
50 "Blowfish Kernel SW Provider"
53 static struct modlinkage modlinkage
= {
60 * CSPI information (entry points, provider info, etc.)
62 typedef enum blowfish_mech_type
{
63 BLOWFISH_ECB_MECH_INFO_TYPE
, /* SUN_CKM_BLOWFISH_ECB */
64 BLOWFISH_CBC_MECH_INFO_TYPE
/* SUN_CKM_BLOWFISH_CBC */
65 } blowfish_mech_type_t
;
68 #define BLOWFISH_COPY_BLOCK(src, dst) \
69 (dst)[0] = (src)[0]; \
70 (dst)[1] = (src)[1]; \
71 (dst)[2] = (src)[2]; \
72 (dst)[3] = (src)[3]; \
73 (dst)[4] = (src)[4]; \
74 (dst)[5] = (src)[5]; \
75 (dst)[6] = (src)[6]; \
78 #define BLOWFISH_XOR_BLOCK(src, dst) \
79 (dst)[0] ^= (src)[0]; \
80 (dst)[1] ^= (src)[1]; \
81 (dst)[2] ^= (src)[2]; \
82 (dst)[3] ^= (src)[3]; \
83 (dst)[4] ^= (src)[4]; \
84 (dst)[5] ^= (src)[5]; \
85 (dst)[6] ^= (src)[6]; \
89 * Mechanism info structure passed to KCF during registration.
92 static crypto_mech_info_t blowfish_mech_info_tab
[] = {
94 {SUN_CKM_BLOWFISH_ECB
, BLOWFISH_ECB_MECH_INFO_TYPE
,
95 CRYPTO_FG_ENCRYPT
| CRYPTO_FG_ENCRYPT_ATOMIC
|
96 CRYPTO_FG_DECRYPT
| CRYPTO_FG_DECRYPT_ATOMIC
,
97 BLOWFISH_MINBITS
, BLOWFISH_MAXBITS
, CRYPTO_KEYSIZE_UNIT_IN_BITS
},
99 {SUN_CKM_BLOWFISH_CBC
, BLOWFISH_CBC_MECH_INFO_TYPE
,
100 CRYPTO_FG_ENCRYPT
| CRYPTO_FG_ENCRYPT_ATOMIC
|
101 CRYPTO_FG_DECRYPT
| CRYPTO_FG_DECRYPT_ATOMIC
,
102 BLOWFISH_MINBITS
, BLOWFISH_MAXBITS
, CRYPTO_KEYSIZE_UNIT_IN_BITS
}
105 #define BLOWFISH_VALID_MECH(mech) \
106 (((mech)->cm_type == BLOWFISH_ECB_MECH_INFO_TYPE || \
107 (mech)->cm_type == BLOWFISH_CBC_MECH_INFO_TYPE) ? 1 : 0)
109 /* operations are in-place if the output buffer is NULL */
110 #define BLOWFISH_ARG_INPLACE(input, output) \
111 if ((output) == NULL) \
114 static void blowfish_provider_status(crypto_provider_handle_t
, uint_t
*);
116 static crypto_control_ops_t blowfish_control_ops
= {
117 blowfish_provider_status
120 static int blowfish_common_init(crypto_ctx_t
*, crypto_mechanism_t
*,
121 crypto_key_t
*, crypto_spi_ctx_template_t
, crypto_req_handle_t
);
122 static int blowfish_common_init_ctx(blowfish_ctx_t
*,
123 crypto_spi_ctx_template_t
*, crypto_mechanism_t
*, crypto_key_t
*, int);
124 static int blowfish_encrypt_final(crypto_ctx_t
*, crypto_data_t
*,
125 crypto_req_handle_t
);
126 static int blowfish_decrypt_final(crypto_ctx_t
*, crypto_data_t
*,
127 crypto_req_handle_t
);
129 static int blowfish_encrypt(crypto_ctx_t
*, crypto_data_t
*, crypto_data_t
*,
130 crypto_req_handle_t
);
131 static int blowfish_encrypt_update(crypto_ctx_t
*, crypto_data_t
*,
132 crypto_data_t
*, crypto_req_handle_t
);
133 static int blowfish_encrypt_atomic(crypto_provider_handle_t
,
134 crypto_session_id_t
, crypto_mechanism_t
*, crypto_key_t
*, crypto_data_t
*,
135 crypto_data_t
*, crypto_spi_ctx_template_t
, crypto_req_handle_t
);
137 static int blowfish_decrypt(crypto_ctx_t
*, crypto_data_t
*, crypto_data_t
*,
138 crypto_req_handle_t
);
139 static int blowfish_decrypt_update(crypto_ctx_t
*, crypto_data_t
*,
140 crypto_data_t
*, crypto_req_handle_t
);
141 static int blowfish_decrypt_atomic(crypto_provider_handle_t
,
142 crypto_session_id_t
, crypto_mechanism_t
*, crypto_key_t
*, crypto_data_t
*,
143 crypto_data_t
*, crypto_spi_ctx_template_t
, crypto_req_handle_t
);
145 static crypto_cipher_ops_t blowfish_cipher_ops
= {
146 blowfish_common_init
,
148 blowfish_encrypt_update
,
149 blowfish_encrypt_final
,
150 blowfish_encrypt_atomic
,
151 blowfish_common_init
,
153 blowfish_decrypt_update
,
154 blowfish_decrypt_final
,
155 blowfish_decrypt_atomic
158 static int blowfish_create_ctx_template(crypto_provider_handle_t
,
159 crypto_mechanism_t
*, crypto_key_t
*, crypto_spi_ctx_template_t
*,
160 size_t *, crypto_req_handle_t
);
161 static int blowfish_free_context(crypto_ctx_t
*);
163 static crypto_ctx_ops_t blowfish_ctx_ops
= {
164 blowfish_create_ctx_template
,
165 blowfish_free_context
168 static crypto_ops_t blowfish_crypto_ops
= {
169 &blowfish_control_ops
,
171 &blowfish_cipher_ops
,
185 static crypto_provider_info_t blowfish_prov_info
= {
186 CRYPTO_SPI_VERSION_1
,
187 "Blowfish Software Provider",
191 &blowfish_crypto_ops
,
192 sizeof (blowfish_mech_info_tab
)/sizeof (crypto_mech_info_t
),
193 blowfish_mech_info_tab
197 static crypto_kcf_provider_handle_t blowfish_prov_handle
= 0;
204 if ((ret
= mod_install(&modlinkage
)) != 0)
207 /* Register with KCF. If the registration fails, remove the module. */
208 if (crypto_register_provider(&blowfish_prov_info
,
209 &blowfish_prov_handle
)) {
210 (void) mod_remove(&modlinkage
);
220 /* Unregister from KCF if module is registered */
221 if (blowfish_prov_handle
!= 0) {
222 if (crypto_unregister_provider(blowfish_prov_handle
))
225 blowfish_prov_handle
= 0;
228 return (mod_remove(&modlinkage
));
232 _info(struct modinfo
*modinfop
)
234 return (mod_info(&modlinkage
, modinfop
));
238 * Initialize key schedules for blowfish
241 init_keysched(crypto_key_t
*key
, void *keysched
)
244 * Only keys by value are supported by this module.
246 switch (key
->ck_format
) {
248 if (key
->ck_length
< BLOWFISH_MINBITS
||
249 key
->ck_length
> BLOWFISH_MAXBITS
) {
250 return (CRYPTO_KEY_SIZE_RANGE
);
254 return (CRYPTO_KEY_TYPE_INCONSISTENT
);
257 blowfish_init_keysched(key
->ck_data
, key
->ck_length
, keysched
);
258 return (CRYPTO_SUCCESS
);
262 * KCF software provider control entry points.
266 blowfish_provider_status(crypto_provider_handle_t provider
, uint_t
*status
)
268 *status
= CRYPTO_PROVIDER_READY
;
272 * KCF software provider encrypt entry points.
275 blowfish_common_init(crypto_ctx_t
*ctx
, crypto_mechanism_t
*mechanism
,
276 crypto_key_t
*key
, crypto_spi_ctx_template_t
template,
277 crypto_req_handle_t req
)
279 blowfish_ctx_t
*blowfish_ctx
;
284 * Only keys by value are supported by this module.
286 if (key
->ck_format
!= CRYPTO_KEY_RAW
) {
287 return (CRYPTO_KEY_TYPE_INCONSISTENT
);
290 if (!BLOWFISH_VALID_MECH(mechanism
))
291 return (CRYPTO_MECHANISM_INVALID
);
293 if (mechanism
->cm_param
!= NULL
&&
294 mechanism
->cm_param_len
!= BLOWFISH_BLOCK_LEN
)
295 return (CRYPTO_MECHANISM_PARAM_INVALID
);
297 kmflag
= crypto_kmflag(req
);
298 switch (mechanism
->cm_type
) {
299 case BLOWFISH_ECB_MECH_INFO_TYPE
:
300 blowfish_ctx
= ecb_alloc_ctx(kmflag
);
302 case BLOWFISH_CBC_MECH_INFO_TYPE
:
303 blowfish_ctx
= cbc_alloc_ctx(kmflag
);
306 if (blowfish_ctx
== NULL
)
307 return (CRYPTO_HOST_MEMORY
);
309 rv
= blowfish_common_init_ctx(blowfish_ctx
, template, mechanism
,
311 if (rv
!= CRYPTO_SUCCESS
) {
312 crypto_free_mode_ctx(blowfish_ctx
);
316 ctx
->cc_provider_private
= blowfish_ctx
;
318 return (CRYPTO_SUCCESS
);
322 blowfish_copy_block64(uint8_t *in
, uint64_t *out
)
324 if (IS_P2ALIGNED(in
, sizeof (uint64_t))) {
325 /* LINTED: pointer alignment */
326 out
[0] = *(uint64_t *)&in
[0];
328 uint8_t *iv8
= (uint8_t *)&out
[0];
330 BLOWFISH_COPY_BLOCK(in
, iv8
);
336 blowfish_encrypt(crypto_ctx_t
*ctx
, crypto_data_t
*plaintext
,
337 crypto_data_t
*ciphertext
, crypto_req_handle_t req
)
341 blowfish_ctx_t
*blowfish_ctx
;
344 * Plaintext must be a multiple of blowfish block size.
345 * This test only works for non-padded mechanisms
346 * when blocksize is 2^N.
348 if ((plaintext
->cd_length
& (BLOWFISH_BLOCK_LEN
- 1)) != 0)
349 return (CRYPTO_DATA_LEN_RANGE
);
351 ASSERT(ctx
->cc_provider_private
!= NULL
);
352 blowfish_ctx
= ctx
->cc_provider_private
;
354 BLOWFISH_ARG_INPLACE(plaintext
, ciphertext
);
357 * We need to just return the length needed to store the output.
358 * We should not destroy the context for the following case.
360 if (ciphertext
->cd_length
< plaintext
->cd_length
) {
361 ciphertext
->cd_length
= plaintext
->cd_length
;
362 return (CRYPTO_BUFFER_TOO_SMALL
);
366 * Do an update on the specified input data.
368 ret
= blowfish_encrypt_update(ctx
, plaintext
, ciphertext
, req
);
369 ASSERT(blowfish_ctx
->bc_remainder_len
== 0);
370 (void) blowfish_free_context(ctx
);
378 blowfish_decrypt(crypto_ctx_t
*ctx
, crypto_data_t
*ciphertext
,
379 crypto_data_t
*plaintext
, crypto_req_handle_t req
)
383 blowfish_ctx_t
*blowfish_ctx
;
386 * Ciphertext must be a multiple of blowfish block size.
387 * This test only works for non-padded mechanisms
388 * when blocksize is 2^N.
390 if ((ciphertext
->cd_length
& (BLOWFISH_BLOCK_LEN
- 1)) != 0)
391 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE
);
393 ASSERT(ctx
->cc_provider_private
!= NULL
);
394 blowfish_ctx
= ctx
->cc_provider_private
;
396 BLOWFISH_ARG_INPLACE(ciphertext
, plaintext
);
399 * We need to just return the length needed to store the output.
400 * We should not destroy the context for the following case.
402 if (plaintext
->cd_length
< ciphertext
->cd_length
) {
403 plaintext
->cd_length
= ciphertext
->cd_length
;
404 return (CRYPTO_BUFFER_TOO_SMALL
);
408 * Do an update on the specified input data.
410 ret
= blowfish_decrypt_update(ctx
, ciphertext
, plaintext
, req
);
411 ASSERT(blowfish_ctx
->bc_remainder_len
== 0);
412 (void) blowfish_free_context(ctx
);
420 blowfish_encrypt_update(crypto_ctx_t
*ctx
, crypto_data_t
*plaintext
,
421 crypto_data_t
*ciphertext
, crypto_req_handle_t req
)
424 size_t saved_length
, out_len
;
425 int ret
= CRYPTO_SUCCESS
;
427 ASSERT(ctx
->cc_provider_private
!= NULL
);
429 BLOWFISH_ARG_INPLACE(plaintext
, ciphertext
);
431 /* compute number of bytes that will hold the ciphertext */
433 ((blowfish_ctx_t
*)ctx
->cc_provider_private
)->bc_remainder_len
;
434 out_len
+= plaintext
->cd_length
;
435 out_len
&= ~(BLOWFISH_BLOCK_LEN
- 1);
437 /* return length needed to store the output */
438 if (ciphertext
->cd_length
< out_len
) {
439 ciphertext
->cd_length
= out_len
;
440 return (CRYPTO_BUFFER_TOO_SMALL
);
443 saved_offset
= ciphertext
->cd_offset
;
444 saved_length
= ciphertext
->cd_length
;
447 * Do the blowfish update on the specified input data.
449 switch (plaintext
->cd_format
) {
450 case CRYPTO_DATA_RAW
:
451 ret
= crypto_update_iov(ctx
->cc_provider_private
,
452 plaintext
, ciphertext
, blowfish_encrypt_contiguous_blocks
,
453 blowfish_copy_block64
);
455 case CRYPTO_DATA_UIO
:
456 ret
= crypto_update_uio(ctx
->cc_provider_private
,
457 plaintext
, ciphertext
, blowfish_encrypt_contiguous_blocks
,
458 blowfish_copy_block64
);
460 case CRYPTO_DATA_MBLK
:
461 ret
= crypto_update_mp(ctx
->cc_provider_private
,
462 plaintext
, ciphertext
, blowfish_encrypt_contiguous_blocks
,
463 blowfish_copy_block64
);
466 ret
= CRYPTO_ARGUMENTS_BAD
;
469 if (ret
== CRYPTO_SUCCESS
) {
470 if (plaintext
!= ciphertext
)
471 ciphertext
->cd_length
=
472 ciphertext
->cd_offset
- saved_offset
;
474 ciphertext
->cd_length
= saved_length
;
476 ciphertext
->cd_offset
= saved_offset
;
483 blowfish_decrypt_update(crypto_ctx_t
*ctx
, crypto_data_t
*ciphertext
,
484 crypto_data_t
*plaintext
, crypto_req_handle_t req
)
487 size_t saved_length
, out_len
;
488 int ret
= CRYPTO_SUCCESS
;
490 ASSERT(ctx
->cc_provider_private
!= NULL
);
492 BLOWFISH_ARG_INPLACE(ciphertext
, plaintext
);
494 /* compute number of bytes that will hold the plaintext */
496 ((blowfish_ctx_t
*)ctx
->cc_provider_private
)->bc_remainder_len
;
497 out_len
+= ciphertext
->cd_length
;
498 out_len
&= ~(BLOWFISH_BLOCK_LEN
- 1);
500 /* return length needed to store the output */
501 if (plaintext
->cd_length
< out_len
) {
502 plaintext
->cd_length
= out_len
;
503 return (CRYPTO_BUFFER_TOO_SMALL
);
506 saved_offset
= plaintext
->cd_offset
;
507 saved_length
= plaintext
->cd_length
;
510 * Do the blowfish update on the specified input data.
512 switch (ciphertext
->cd_format
) {
513 case CRYPTO_DATA_RAW
:
514 ret
= crypto_update_iov(ctx
->cc_provider_private
,
515 ciphertext
, plaintext
, blowfish_decrypt_contiguous_blocks
,
516 blowfish_copy_block64
);
518 case CRYPTO_DATA_UIO
:
519 ret
= crypto_update_uio(ctx
->cc_provider_private
,
520 ciphertext
, plaintext
, blowfish_decrypt_contiguous_blocks
,
521 blowfish_copy_block64
);
523 case CRYPTO_DATA_MBLK
:
524 ret
= crypto_update_mp(ctx
->cc_provider_private
,
525 ciphertext
, plaintext
, blowfish_decrypt_contiguous_blocks
,
526 blowfish_copy_block64
);
529 ret
= CRYPTO_ARGUMENTS_BAD
;
532 if (ret
== CRYPTO_SUCCESS
) {
533 if (ciphertext
!= plaintext
)
534 plaintext
->cd_length
=
535 plaintext
->cd_offset
- saved_offset
;
537 plaintext
->cd_length
= saved_length
;
539 plaintext
->cd_offset
= saved_offset
;
546 blowfish_encrypt_final(crypto_ctx_t
*ctx
, crypto_data_t
*data
,
547 crypto_req_handle_t req
)
549 blowfish_ctx_t
*blowfish_ctx
;
551 ASSERT(ctx
->cc_provider_private
!= NULL
);
552 blowfish_ctx
= ctx
->cc_provider_private
;
555 * There must be no unprocessed data.
556 * This happens if the length of the last data is
557 * not a multiple of the BLOWFISH block length.
559 if (blowfish_ctx
->bc_remainder_len
> 0)
560 return (CRYPTO_DATA_LEN_RANGE
);
562 (void) blowfish_free_context(ctx
);
565 return (CRYPTO_SUCCESS
);
570 blowfish_decrypt_final(crypto_ctx_t
*ctx
, crypto_data_t
*data
,
571 crypto_req_handle_t req
)
573 blowfish_ctx_t
*blowfish_ctx
;
575 ASSERT(ctx
->cc_provider_private
!= NULL
);
576 blowfish_ctx
= ctx
->cc_provider_private
;
579 * There must be no unprocessed ciphertext.
580 * This happens if the length of the last ciphertext is
581 * not a multiple of the BLOWFISH block length.
583 if (blowfish_ctx
->bc_remainder_len
> 0)
584 return (CRYPTO_ENCRYPTED_DATA_LEN_RANGE
);
586 (void) blowfish_free_context(ctx
);
589 return (CRYPTO_SUCCESS
);
594 blowfish_encrypt_atomic(crypto_provider_handle_t provider
,
595 crypto_session_id_t session_id
, crypto_mechanism_t
*mechanism
,
596 crypto_key_t
*key
, crypto_data_t
*plaintext
, crypto_data_t
*ciphertext
,
597 crypto_spi_ctx_template_t
template, crypto_req_handle_t req
)
599 blowfish_ctx_t blowfish_ctx
; /* on the stack */
604 BLOWFISH_ARG_INPLACE(plaintext
, ciphertext
);
607 * Plaintext must be a multiple of blowfish block size.
608 * This test only works for non-padded mechanisms
609 * when blocksize is 2^N.
611 if ((plaintext
->cd_length
& (BLOWFISH_BLOCK_LEN
- 1)) != 0)
612 return (CRYPTO_DATA_LEN_RANGE
);
614 /* return length needed to store the output */
615 if (ciphertext
->cd_length
< plaintext
->cd_length
) {
616 ciphertext
->cd_length
= plaintext
->cd_length
;
617 return (CRYPTO_BUFFER_TOO_SMALL
);
620 if (!BLOWFISH_VALID_MECH(mechanism
))
621 return (CRYPTO_MECHANISM_INVALID
);
623 if (mechanism
->cm_param_len
!= 0 &&
624 mechanism
->cm_param_len
!= BLOWFISH_BLOCK_LEN
)
625 return (CRYPTO_MECHANISM_PARAM_INVALID
);
627 bzero(&blowfish_ctx
, sizeof (blowfish_ctx_t
));
629 ret
= blowfish_common_init_ctx(&blowfish_ctx
, template, mechanism
,
630 key
, crypto_kmflag(req
));
631 if (ret
!= CRYPTO_SUCCESS
)
634 saved_offset
= ciphertext
->cd_offset
;
635 saved_length
= ciphertext
->cd_length
;
638 * Do an update on the specified input data.
640 switch (plaintext
->cd_format
) {
641 case CRYPTO_DATA_RAW
:
642 ret
= crypto_update_iov(&blowfish_ctx
,
643 plaintext
, ciphertext
, blowfish_encrypt_contiguous_blocks
,
644 blowfish_copy_block64
);
646 case CRYPTO_DATA_UIO
:
647 ret
= crypto_update_uio(&blowfish_ctx
,
648 plaintext
, ciphertext
, blowfish_encrypt_contiguous_blocks
,
649 blowfish_copy_block64
);
651 case CRYPTO_DATA_MBLK
:
652 ret
= crypto_update_mp((void *)&blowfish_ctx
,
653 plaintext
, ciphertext
, blowfish_encrypt_contiguous_blocks
,
654 blowfish_copy_block64
);
657 ret
= CRYPTO_ARGUMENTS_BAD
;
660 if (blowfish_ctx
.bc_flags
& PROVIDER_OWNS_KEY_SCHEDULE
) {
661 bzero(blowfish_ctx
.bc_keysched
, blowfish_ctx
.bc_keysched_len
);
662 kmem_free(blowfish_ctx
.bc_keysched
,
663 blowfish_ctx
.bc_keysched_len
);
666 if (ret
== CRYPTO_SUCCESS
) {
667 ASSERT(blowfish_ctx
.bc_remainder_len
== 0);
668 if (plaintext
!= ciphertext
)
669 ciphertext
->cd_length
=
670 ciphertext
->cd_offset
- saved_offset
;
672 ciphertext
->cd_length
= saved_length
;
674 ciphertext
->cd_offset
= saved_offset
;
681 blowfish_decrypt_atomic(crypto_provider_handle_t provider
,
682 crypto_session_id_t session_id
, crypto_mechanism_t
*mechanism
,
683 crypto_key_t
*key
, crypto_data_t
*ciphertext
, crypto_data_t
*plaintext
,
684 crypto_spi_ctx_template_t
template, crypto_req_handle_t req
)
686 blowfish_ctx_t blowfish_ctx
; /* on the stack */
691 BLOWFISH_ARG_INPLACE(ciphertext
, plaintext
);
694 * Ciphertext must be a multiple of blowfish block size.
695 * This test only works for non-padded mechanisms
696 * when blocksize is 2^N.
698 if ((ciphertext
->cd_length
& (BLOWFISH_BLOCK_LEN
- 1)) != 0)
699 return (CRYPTO_DATA_LEN_RANGE
);
701 /* return length needed to store the output */
702 if (plaintext
->cd_length
< ciphertext
->cd_length
) {
703 plaintext
->cd_length
= ciphertext
->cd_length
;
704 return (CRYPTO_BUFFER_TOO_SMALL
);
707 if (!BLOWFISH_VALID_MECH(mechanism
))
708 return (CRYPTO_MECHANISM_INVALID
);
710 if (mechanism
->cm_param_len
!= 0 &&
711 mechanism
->cm_param_len
!= BLOWFISH_BLOCK_LEN
)
712 return (CRYPTO_MECHANISM_PARAM_INVALID
);
714 bzero(&blowfish_ctx
, sizeof (blowfish_ctx_t
));
716 ret
= blowfish_common_init_ctx(&blowfish_ctx
, template, mechanism
,
717 key
, crypto_kmflag(req
));
718 if (ret
!= CRYPTO_SUCCESS
)
721 saved_offset
= plaintext
->cd_offset
;
722 saved_length
= plaintext
->cd_length
;
725 * Do an update on the specified input data.
727 switch (ciphertext
->cd_format
) {
728 case CRYPTO_DATA_RAW
:
729 ret
= crypto_update_iov(&blowfish_ctx
,
730 ciphertext
, plaintext
, blowfish_decrypt_contiguous_blocks
,
731 blowfish_copy_block64
);
733 case CRYPTO_DATA_UIO
:
734 ret
= crypto_update_uio(&blowfish_ctx
,
735 ciphertext
, plaintext
, blowfish_decrypt_contiguous_blocks
,
736 blowfish_copy_block64
);
738 case CRYPTO_DATA_MBLK
:
739 ret
= crypto_update_mp(&blowfish_ctx
,
740 ciphertext
, plaintext
, blowfish_decrypt_contiguous_blocks
,
741 blowfish_copy_block64
);
744 ret
= CRYPTO_ARGUMENTS_BAD
;
747 if (blowfish_ctx
.bc_flags
& PROVIDER_OWNS_KEY_SCHEDULE
) {
748 bzero(blowfish_ctx
.bc_keysched
, blowfish_ctx
.bc_keysched_len
);
749 kmem_free(blowfish_ctx
.bc_keysched
,
750 blowfish_ctx
.bc_keysched_len
);
753 if (ret
== CRYPTO_SUCCESS
) {
754 ASSERT(blowfish_ctx
.bc_remainder_len
== 0);
755 if (ciphertext
!= plaintext
)
756 plaintext
->cd_length
=
757 plaintext
->cd_offset
- saved_offset
;
759 plaintext
->cd_length
= saved_length
;
761 plaintext
->cd_offset
= saved_offset
;
767 * KCF software provider context template entry points.
771 blowfish_create_ctx_template(crypto_provider_handle_t provider
,
772 crypto_mechanism_t
*mechanism
, crypto_key_t
*key
,
773 crypto_spi_ctx_template_t
*tmpl
, size_t *tmpl_size
, crypto_req_handle_t req
)
779 if (!BLOWFISH_VALID_MECH(mechanism
))
780 return (CRYPTO_MECHANISM_INVALID
);
782 if ((keysched
= blowfish_alloc_keysched(&size
,
783 crypto_kmflag(req
))) == NULL
) {
784 return (CRYPTO_HOST_MEMORY
);
788 * Initialize key schedule. Key length information is stored
791 if ((rv
= init_keysched(key
, keysched
)) != CRYPTO_SUCCESS
) {
792 bzero(keysched
, size
);
793 kmem_free(keysched
, size
);
800 return (CRYPTO_SUCCESS
);
805 blowfish_free_context(crypto_ctx_t
*ctx
)
807 blowfish_ctx_t
*blowfish_ctx
= ctx
->cc_provider_private
;
809 if (blowfish_ctx
!= NULL
) {
810 if (blowfish_ctx
->bc_flags
& PROVIDER_OWNS_KEY_SCHEDULE
) {
811 ASSERT(blowfish_ctx
->bc_keysched_len
!= 0);
812 bzero(blowfish_ctx
->bc_keysched
,
813 blowfish_ctx
->bc_keysched_len
);
814 kmem_free(blowfish_ctx
->bc_keysched
,
815 blowfish_ctx
->bc_keysched_len
);
817 crypto_free_mode_ctx(blowfish_ctx
);
818 ctx
->cc_provider_private
= NULL
;
821 return (CRYPTO_SUCCESS
);
826 blowfish_common_init_ctx(blowfish_ctx_t
*blowfish_ctx
,
827 crypto_spi_ctx_template_t
*template, crypto_mechanism_t
*mechanism
,
828 crypto_key_t
*key
, int kmflag
)
830 int rv
= CRYPTO_SUCCESS
;
835 if (template == NULL
) {
836 if ((keysched
= blowfish_alloc_keysched(&size
, kmflag
)) == NULL
)
837 return (CRYPTO_HOST_MEMORY
);
839 * Initialize key schedule.
840 * Key length is stored in the key.
842 if ((rv
= init_keysched(key
, keysched
)) != CRYPTO_SUCCESS
)
843 kmem_free(keysched
, size
);
845 blowfish_ctx
->bc_flags
|= PROVIDER_OWNS_KEY_SCHEDULE
;
846 blowfish_ctx
->bc_keysched_len
= size
;
850 blowfish_ctx
->bc_keysched
= keysched
;
852 switch (mechanism
->cm_type
) {
853 case BLOWFISH_CBC_MECH_INFO_TYPE
:
854 rv
= cbc_init_ctx((cbc_ctx_t
*)blowfish_ctx
,
855 mechanism
->cm_param
, mechanism
->cm_param_len
,
856 BLOWFISH_BLOCK_LEN
, blowfish_copy_block64
);
858 case BLOWFISH_ECB_MECH_INFO_TYPE
:
859 blowfish_ctx
->bc_flags
|= ECB_MODE
;
862 if (rv
!= CRYPTO_SUCCESS
) {
863 if (blowfish_ctx
->bc_flags
& PROVIDER_OWNS_KEY_SCHEDULE
) {
864 bzero(keysched
, size
);
865 kmem_free(keysched
, size
);