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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/errno.h>
26 #include <sys/types.h>
28 #include <sys/sysmacros.h>
29 #include <sys/crypto/common.h>
30 #include <sys/crypto/impl.h>
31 #include <sys/crypto/api.h>
32 #include <sys/crypto/spi.h>
33 #include <sys/crypto/sched_impl.h>
35 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
36 #define CRYPTO_CIPHER_OFFSET(f) offsetof(crypto_cipher_ops_t, f)
39 * Encryption and decryption routines.
43 * The following are the possible returned values common to all the routines
44 * below. The applicability of some of these return values depends on the
45 * presence of the arguments.
47 * CRYPTO_SUCCESS: The operation completed successfully.
48 * CRYPTO_QUEUED: A request was submitted successfully. The callback
49 * routine will be called when the operation is done.
50 * CRYPTO_INVALID_MECH_NUMBER, CRYPTO_INVALID_MECH_PARAM, or
51 * CRYPTO_INVALID_MECH for problems with the 'mech'.
52 * CRYPTO_INVALID_DATA for bogus 'data'
53 * CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work.
54 * CRYPTO_INVALID_CONTEXT: Not a valid context.
55 * CRYPTO_BUSY: Cannot process the request now. Schedule a
56 * crypto_bufcall(), or try later.
57 * CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED: No provider is
58 * capable of a function or a mechanism.
59 * CRYPTO_INVALID_KEY: bogus 'key' argument.
60 * CRYPTO_INVALID_PLAINTEXT: bogus 'plaintext' argument.
61 * CRYPTO_INVALID_CIPHERTEXT: bogus 'ciphertext' argument.
65 * crypto_cipher_init_prov()
69 * pd: provider descriptor
71 * mech: crypto_mechanism_t pointer.
72 * mech_type is a valid value previously returned by
74 * When the mech's parameter is not NULL, its definition depends
75 * on the standard definition of the mechanism.
76 * key: pointer to a crypto_key_t structure.
77 * tmpl: a crypto_ctx_template_t, opaque template of a context of an
78 * encryption or decryption with the 'mech' using 'key'.
79 * 'tmpl' is created by a previous call to
80 * crypto_create_ctx_template().
81 * ctxp: Pointer to a crypto_context_t.
82 * func: CRYPTO_FG_ENCRYPT or CRYPTO_FG_DECRYPT.
83 * cr: crypto_call_req_t calling conditions and call back info.
86 * This is a common function invoked internally by both
87 * crypto_encrypt_init() and crypto_decrypt_init().
88 * Asynchronously submits a request for, or synchronously performs the
89 * initialization of an encryption or a decryption operation.
90 * When possible and applicable, will internally use the pre-expanded key
91 * schedule from the context template, tmpl.
92 * When complete and successful, 'ctxp' will contain a crypto_context_t
93 * valid for later calls to encrypt_update() and encrypt_final(), or
94 * decrypt_update() and decrypt_final().
95 * The caller should hold a reference on the specified provider
96 * descriptor before calling this function.
99 * Process or interrupt, according to the semantics dictated by the 'cr'.
102 * See comment in the beginning of the file.
105 crypto_cipher_init_prov(crypto_provider_t provider
, crypto_session_id_t sid
,
106 crypto_mechanism_t
*mech
, crypto_key_t
*key
,
107 crypto_spi_ctx_template_t tmpl
, crypto_context_t
*ctxp
,
108 crypto_call_req_t
*crq
, crypto_func_group_t func
)
112 kcf_req_params_t params
;
113 kcf_provider_desc_t
*pd
= provider
;
114 kcf_provider_desc_t
*real_provider
= pd
;
116 ASSERT(KCF_PROV_REFHELD(pd
));
118 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
119 if (func
== CRYPTO_FG_ENCRYPT
) {
120 error
= kcf_get_hardware_provider(mech
->cm_type
, key
,
121 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
124 error
= kcf_get_hardware_provider(mech
->cm_type
, key
,
125 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
129 if (error
!= CRYPTO_SUCCESS
)
133 /* Allocate and initialize the canonical context */
134 if ((ctx
= kcf_new_ctx(crq
, real_provider
, sid
)) == NULL
) {
135 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
136 KCF_PROV_REFRELE(real_provider
);
137 return (CRYPTO_HOST_MEMORY
);
140 /* The fast path for SW providers. */
141 if (CHECK_FASTPATH(crq
, pd
)) {
142 crypto_mechanism_t lmech
;
145 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, real_provider
, &lmech
);
147 if (func
== CRYPTO_FG_ENCRYPT
)
148 error
= KCF_PROV_ENCRYPT_INIT(real_provider
, ctx
,
149 &lmech
, key
, tmpl
, KCF_SWFP_RHNDL(crq
));
151 ASSERT(func
== CRYPTO_FG_DECRYPT
);
153 error
= KCF_PROV_DECRYPT_INIT(real_provider
, ctx
,
154 &lmech
, key
, tmpl
, KCF_SWFP_RHNDL(crq
));
156 KCF_PROV_INCRSTATS(pd
, error
);
161 /* Check if context sharing is possible */
162 if (pd
->pd_prov_type
== CRYPTO_HW_PROVIDER
&&
163 key
->ck_format
== CRYPTO_KEY_RAW
&&
164 KCF_CAN_SHARE_OPSTATE(pd
, mech
->cm_type
)) {
165 kcf_context_t
*tctxp
= (kcf_context_t
*)ctx
;
166 kcf_provider_desc_t
*tpd
= NULL
;
167 crypto_mech_info_t
*sinfo
;
169 if ((kcf_get_sw_prov(mech
->cm_type
, &tpd
, &tctxp
->kc_mech
,
170 B_FALSE
) == CRYPTO_SUCCESS
)) {
173 sinfo
= &(KCF_TO_PROV_MECHINFO(tpd
, mech
->cm_type
));
175 * key->ck_length from the consumer is always in bits.
176 * We convert it to be in the same unit registered by
177 * the provider in order to do a comparison.
179 if (sinfo
->cm_mech_flags
& CRYPTO_KEYSIZE_UNIT_IN_BYTES
)
180 tlen
= CRYPTO_BITS2BYTES(key
->ck_length
);
182 tlen
= key
->ck_length
;
184 * Check if the software provider can support context
185 * sharing and support this key length.
187 if ((sinfo
->cm_mech_flags
& CRYPTO_CAN_SHARE_OPSTATE
) &&
188 (tlen
>= sinfo
->cm_min_key_length
) &&
189 (tlen
<= sinfo
->cm_max_key_length
)) {
190 ctx
->cc_flags
= CRYPTO_INIT_OPSTATE
;
191 tctxp
->kc_sw_prov_desc
= tpd
;
193 KCF_PROV_REFRELE(tpd
);
197 if (func
== CRYPTO_FG_ENCRYPT
) {
198 KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms
, KCF_OP_INIT
, sid
,
199 mech
, key
, NULL
, NULL
, tmpl
);
201 ASSERT(func
== CRYPTO_FG_DECRYPT
);
202 KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms
, KCF_OP_INIT
, sid
,
203 mech
, key
, NULL
, NULL
, tmpl
);
206 error
= kcf_submit_request(real_provider
, ctx
, crq
, ¶ms
,
209 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
210 KCF_PROV_REFRELE(real_provider
);
213 if ((error
== CRYPTO_SUCCESS
) || (error
== CRYPTO_QUEUED
))
214 *ctxp
= (crypto_context_t
)ctx
;
216 /* Release the hold done in kcf_new_ctx(). */
217 KCF_CONTEXT_REFRELE((kcf_context_t
*)ctx
->cc_framework_private
);
224 * Same as crypto_cipher_init_prov(), but relies on the scheduler to pick
225 * an appropriate provider. See crypto_cipher_init_prov() comments for more
229 crypto_cipher_init(crypto_mechanism_t
*mech
, crypto_key_t
*key
,
230 crypto_ctx_template_t tmpl
, crypto_context_t
*ctxp
,
231 crypto_call_req_t
*crq
, crypto_func_group_t func
)
234 kcf_mech_entry_t
*me
;
235 kcf_provider_desc_t
*pd
;
236 kcf_ctx_template_t
*ctx_tmpl
;
237 crypto_spi_ctx_template_t spi_ctx_tmpl
= NULL
;
238 kcf_prov_tried_t
*list
= NULL
;
241 /* pd is returned held */
242 if ((pd
= kcf_get_mech_provider(mech
->cm_type
, key
, &me
, &error
,
243 list
, func
, 0)) == NULL
) {
245 kcf_free_triedlist(list
);
250 * For SW providers, check the validity of the context template
251 * It is very rare that the generation number mis-matches, so
252 * is acceptable to fail here, and let the consumer recover by
253 * freeing this tmpl and create a new one for the key and new SW
256 if ((pd
->pd_prov_type
== CRYPTO_SW_PROVIDER
) &&
257 ((ctx_tmpl
= (kcf_ctx_template_t
*)tmpl
) != NULL
)) {
258 if (ctx_tmpl
->ct_generation
!= me
->me_gen_swprov
) {
260 kcf_free_triedlist(list
);
261 KCF_PROV_REFRELE(pd
);
262 return (CRYPTO_OLD_CTX_TEMPLATE
);
264 spi_ctx_tmpl
= ctx_tmpl
->ct_prov_tmpl
;
268 error
= crypto_cipher_init_prov(pd
, pd
->pd_sid
, mech
, key
,
269 spi_ctx_tmpl
, ctxp
, crq
, func
);
270 if (error
!= CRYPTO_SUCCESS
&& error
!= CRYPTO_QUEUED
&&
271 IS_RECOVERABLE(error
)) {
272 /* Add pd to the linked list of providers tried. */
273 if (kcf_insert_triedlist(&list
, pd
, KCF_KMFLAG(crq
)) != NULL
)
278 kcf_free_triedlist(list
);
280 KCF_PROV_REFRELE(pd
);
285 * crypto_encrypt_prov()
288 * pd: provider descriptor
290 * mech: crypto_mechanism_t pointer.
291 * mech_type is a valid value previously returned by
293 * When the mech's parameter is not NULL, its definition depends
294 * on the standard definition of the mechanism.
295 * key: pointer to a crypto_key_t structure.
296 * plaintext: The message to be encrypted
297 * ciphertext: Storage for the encrypted message. The length needed
298 * depends on the mechanism, and the plaintext's size.
299 * tmpl: a crypto_ctx_template_t, opaque template of a context of an
300 * encryption with the 'mech' using 'key'. 'tmpl' is created by
301 * a previous call to crypto_create_ctx_template().
302 * cr: crypto_call_req_t calling conditions and call back info.
305 * Asynchronously submits a request for, or synchronously performs a
306 * single-part encryption of 'plaintext' with the mechanism 'mech', using
308 * When complete and successful, 'ciphertext' will contain the encrypted
312 * Process or interrupt, according to the semantics dictated by the 'cr'.
315 * See comment in the beginning of the file.
318 crypto_encrypt_prov(crypto_provider_t provider
, crypto_session_id_t sid
,
319 crypto_mechanism_t
*mech
, crypto_data_t
*plaintext
, crypto_key_t
*key
,
320 crypto_ctx_template_t tmpl
, crypto_data_t
*ciphertext
,
321 crypto_call_req_t
*crq
)
323 kcf_req_params_t params
;
324 kcf_provider_desc_t
*pd
= provider
;
325 kcf_provider_desc_t
*real_provider
= pd
;
328 ASSERT(KCF_PROV_REFHELD(pd
));
330 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
331 error
= kcf_get_hardware_provider(mech
->cm_type
, key
,
332 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
333 CRYPTO_FG_ENCRYPT_ATOMIC
);
335 if (error
!= CRYPTO_SUCCESS
)
339 KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms
, KCF_OP_ATOMIC
, sid
, mech
, key
,
340 plaintext
, ciphertext
, tmpl
);
342 error
= kcf_submit_request(real_provider
, NULL
, crq
, ¶ms
, B_FALSE
);
343 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
344 KCF_PROV_REFRELE(real_provider
);
350 * Same as crypto_encrypt_prov(), but relies on the scheduler to pick
351 * a provider. See crypto_encrypt_prov() for more details.
354 crypto_encrypt(crypto_mechanism_t
*mech
, crypto_data_t
*plaintext
,
355 crypto_key_t
*key
, crypto_ctx_template_t tmpl
, crypto_data_t
*ciphertext
,
356 crypto_call_req_t
*crq
)
359 kcf_mech_entry_t
*me
;
360 kcf_req_params_t params
;
361 kcf_provider_desc_t
*pd
;
362 kcf_ctx_template_t
*ctx_tmpl
;
363 crypto_spi_ctx_template_t spi_ctx_tmpl
= NULL
;
364 kcf_prov_tried_t
*list
= NULL
;
367 /* pd is returned held */
368 if ((pd
= kcf_get_mech_provider(mech
->cm_type
, key
, &me
, &error
,
369 list
, CRYPTO_FG_ENCRYPT_ATOMIC
, plaintext
->cd_length
)) == NULL
) {
371 kcf_free_triedlist(list
);
376 * For SW providers, check the validity of the context template
377 * It is very rare that the generation number mis-matches, so
378 * is acceptable to fail here, and let the consumer recover by
379 * freeing this tmpl and create a new one for the key and new SW
382 if ((pd
->pd_prov_type
== CRYPTO_SW_PROVIDER
) &&
383 ((ctx_tmpl
= (kcf_ctx_template_t
*)tmpl
) != NULL
)) {
384 if (ctx_tmpl
->ct_generation
!= me
->me_gen_swprov
) {
386 kcf_free_triedlist(list
);
387 KCF_PROV_REFRELE(pd
);
388 return (CRYPTO_OLD_CTX_TEMPLATE
);
390 spi_ctx_tmpl
= ctx_tmpl
->ct_prov_tmpl
;
394 /* The fast path for SW providers. */
395 if (CHECK_FASTPATH(crq
, pd
)) {
396 crypto_mechanism_t lmech
;
399 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, pd
, &lmech
);
401 error
= KCF_PROV_ENCRYPT_ATOMIC(pd
, pd
->pd_sid
, &lmech
, key
,
402 plaintext
, ciphertext
, spi_ctx_tmpl
, KCF_SWFP_RHNDL(crq
));
403 KCF_PROV_INCRSTATS(pd
, error
);
405 KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms
, KCF_OP_ATOMIC
, pd
->pd_sid
,
406 mech
, key
, plaintext
, ciphertext
, spi_ctx_tmpl
);
407 error
= kcf_submit_request(pd
, NULL
, crq
, ¶ms
, B_FALSE
);
410 if (error
!= CRYPTO_SUCCESS
&& error
!= CRYPTO_QUEUED
&&
411 IS_RECOVERABLE(error
)) {
412 /* Add pd to the linked list of providers tried. */
413 if (kcf_insert_triedlist(&list
, pd
, KCF_KMFLAG(crq
)) != NULL
)
418 kcf_free_triedlist(list
);
420 KCF_PROV_REFRELE(pd
);
425 * crypto_encrypt_init_prov()
427 * Calls crypto_cipher_init_prov() to initialize an encryption operation.
430 crypto_encrypt_init_prov(crypto_provider_t pd
, crypto_session_id_t sid
,
431 crypto_mechanism_t
*mech
, crypto_key_t
*key
,
432 crypto_ctx_template_t tmpl
, crypto_context_t
*ctxp
,
433 crypto_call_req_t
*crq
)
435 return (crypto_cipher_init_prov(pd
, sid
, mech
, key
, tmpl
, ctxp
, crq
,
440 * crypto_encrypt_init()
442 * Calls crypto_cipher_init() to initialize an encryption operation
445 crypto_encrypt_init(crypto_mechanism_t
*mech
, crypto_key_t
*key
,
446 crypto_ctx_template_t tmpl
, crypto_context_t
*ctxp
,
447 crypto_call_req_t
*crq
)
449 return (crypto_cipher_init(mech
, key
, tmpl
, ctxp
, crq
,
454 * crypto_encrypt_update()
457 * context: A crypto_context_t initialized by encrypt_init().
458 * plaintext: The message part to be encrypted
459 * ciphertext: Storage for the encrypted message part.
460 * cr: crypto_call_req_t calling conditions and call back info.
463 * Asynchronously submits a request for, or synchronously performs a
464 * part of an encryption operation.
467 * Process or interrupt, according to the semantics dictated by the 'cr'.
470 * See comment in the beginning of the file.
473 crypto_encrypt_update(crypto_context_t context
, crypto_data_t
*plaintext
,
474 crypto_data_t
*ciphertext
, crypto_call_req_t
*cr
)
476 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
477 kcf_context_t
*kcf_ctx
;
478 kcf_provider_desc_t
*pd
;
480 kcf_req_params_t params
;
483 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
484 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
485 return (CRYPTO_INVALID_CONTEXT
);
488 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
490 /* The fast path for SW providers. */
491 if (CHECK_FASTPATH(cr
, pd
)) {
492 error
= KCF_PROV_ENCRYPT_UPDATE(pd
, ctx
, plaintext
,
494 KCF_PROV_INCRSTATS(pd
, error
);
498 /* Check if we should use a software provider for small jobs */
499 if ((ctx
->cc_flags
& CRYPTO_USE_OPSTATE
) && cr
== NULL
) {
500 if (plaintext
->cd_length
< kcf_ctx
->kc_mech
->me_threshold
&&
501 kcf_ctx
->kc_sw_prov_desc
!= NULL
&&
502 KCF_IS_PROV_USABLE(kcf_ctx
->kc_sw_prov_desc
)) {
503 pd
= kcf_ctx
->kc_sw_prov_desc
;
507 KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms
, KCF_OP_UPDATE
,
508 ctx
->cc_session
, NULL
, NULL
, plaintext
, ciphertext
, NULL
);
509 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
515 * crypto_encrypt_final()
518 * context: A crypto_context_t initialized by encrypt_init().
519 * ciphertext: Storage for the last part of encrypted message
520 * cr: crypto_call_req_t calling conditions and call back info.
523 * Asynchronously submits a request for, or synchronously performs the
524 * final part of an encryption operation.
527 * Process or interrupt, according to the semantics dictated by the 'cr'.
530 * See comment in the beginning of the file.
533 crypto_encrypt_final(crypto_context_t context
, crypto_data_t
*ciphertext
,
534 crypto_call_req_t
*cr
)
536 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
537 kcf_context_t
*kcf_ctx
;
538 kcf_provider_desc_t
*pd
;
540 kcf_req_params_t params
;
543 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
544 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
545 return (CRYPTO_INVALID_CONTEXT
);
548 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
550 /* The fast path for SW providers. */
551 if (CHECK_FASTPATH(cr
, pd
)) {
552 error
= KCF_PROV_ENCRYPT_FINAL(pd
, ctx
, ciphertext
, NULL
);
553 KCF_PROV_INCRSTATS(pd
, error
);
555 KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms
, KCF_OP_FINAL
,
556 ctx
->cc_session
, NULL
, NULL
, NULL
, ciphertext
, NULL
);
557 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
560 /* Release the hold done in kcf_new_ctx() during init step. */
561 KCF_CONTEXT_COND_RELEASE(error
, kcf_ctx
);
566 * crypto_decrypt_prov()
569 * pd: provider descriptor
571 * mech: crypto_mechanism_t pointer.
572 * mech_type is a valid value previously returned by
574 * When the mech's parameter is not NULL, its definition depends
575 * on the standard definition of the mechanism.
576 * key: pointer to a crypto_key_t structure.
577 * ciphertext: The message to be encrypted
578 * plaintext: Storage for the encrypted message. The length needed
579 * depends on the mechanism, and the plaintext's size.
580 * tmpl: a crypto_ctx_template_t, opaque template of a context of an
581 * encryption with the 'mech' using 'key'. 'tmpl' is created by
582 * a previous call to crypto_create_ctx_template().
583 * cr: crypto_call_req_t calling conditions and call back info.
586 * Asynchronously submits a request for, or synchronously performs a
587 * single-part decryption of 'ciphertext' with the mechanism 'mech', using
589 * When complete and successful, 'plaintext' will contain the decrypted
593 * Process or interrupt, according to the semantics dictated by the 'cr'.
596 * See comment in the beginning of the file.
599 crypto_decrypt_prov(crypto_provider_t provider
, crypto_session_id_t sid
,
600 crypto_mechanism_t
*mech
, crypto_data_t
*ciphertext
, crypto_key_t
*key
,
601 crypto_ctx_template_t tmpl
, crypto_data_t
*plaintext
,
602 crypto_call_req_t
*crq
)
604 kcf_req_params_t params
;
605 kcf_provider_desc_t
*pd
= provider
;
606 kcf_provider_desc_t
*real_provider
= pd
;
609 ASSERT(KCF_PROV_REFHELD(pd
));
611 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
612 rv
= kcf_get_hardware_provider(mech
->cm_type
, key
,
613 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
614 CRYPTO_FG_DECRYPT_ATOMIC
);
616 if (rv
!= CRYPTO_SUCCESS
)
620 KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms
, KCF_OP_ATOMIC
, sid
, mech
, key
,
621 ciphertext
, plaintext
, tmpl
);
623 rv
= kcf_submit_request(real_provider
, NULL
, crq
, ¶ms
, B_FALSE
);
624 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
625 KCF_PROV_REFRELE(real_provider
);
631 * Same as crypto_decrypt_prov(), but relies on the KCF scheduler to
632 * choose a provider. See crypto_decrypt_prov() comments for more
636 crypto_decrypt(crypto_mechanism_t
*mech
, crypto_data_t
*ciphertext
,
637 crypto_key_t
*key
, crypto_ctx_template_t tmpl
, crypto_data_t
*plaintext
,
638 crypto_call_req_t
*crq
)
641 kcf_mech_entry_t
*me
;
642 kcf_req_params_t params
;
643 kcf_provider_desc_t
*pd
;
644 kcf_ctx_template_t
*ctx_tmpl
;
645 crypto_spi_ctx_template_t spi_ctx_tmpl
= NULL
;
646 kcf_prov_tried_t
*list
= NULL
;
649 /* pd is returned held */
650 if ((pd
= kcf_get_mech_provider(mech
->cm_type
, key
, &me
, &error
,
651 list
, CRYPTO_FG_DECRYPT_ATOMIC
, ciphertext
->cd_length
)) == NULL
) {
653 kcf_free_triedlist(list
);
658 * For SW providers, check the validity of the context template
659 * It is very rare that the generation number mis-matches, so
660 * is acceptable to fail here, and let the consumer recover by
661 * freeing this tmpl and create a new one for the key and new SW
664 if ((pd
->pd_prov_type
== CRYPTO_SW_PROVIDER
) &&
665 ((ctx_tmpl
= (kcf_ctx_template_t
*)tmpl
) != NULL
)) {
666 if (ctx_tmpl
->ct_generation
!= me
->me_gen_swprov
) {
668 kcf_free_triedlist(list
);
669 KCF_PROV_REFRELE(pd
);
670 return (CRYPTO_OLD_CTX_TEMPLATE
);
672 spi_ctx_tmpl
= ctx_tmpl
->ct_prov_tmpl
;
676 /* The fast path for SW providers. */
677 if (CHECK_FASTPATH(crq
, pd
)) {
678 crypto_mechanism_t lmech
;
681 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, pd
, &lmech
);
683 error
= KCF_PROV_DECRYPT_ATOMIC(pd
, pd
->pd_sid
, &lmech
, key
,
684 ciphertext
, plaintext
, spi_ctx_tmpl
, KCF_SWFP_RHNDL(crq
));
685 KCF_PROV_INCRSTATS(pd
, error
);
687 KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms
, KCF_OP_ATOMIC
, pd
->pd_sid
,
688 mech
, key
, ciphertext
, plaintext
, spi_ctx_tmpl
);
689 error
= kcf_submit_request(pd
, NULL
, crq
, ¶ms
, B_FALSE
);
692 if (error
!= CRYPTO_SUCCESS
&& error
!= CRYPTO_QUEUED
&&
693 IS_RECOVERABLE(error
)) {
694 /* Add pd to the linked list of providers tried. */
695 if (kcf_insert_triedlist(&list
, pd
, KCF_KMFLAG(crq
)) != NULL
)
700 kcf_free_triedlist(list
);
702 KCF_PROV_REFRELE(pd
);
707 * crypto_decrypt_init_prov()
709 * Calls crypto_cipher_init_prov() to initialize a decryption operation
712 crypto_decrypt_init_prov(crypto_provider_t pd
, crypto_session_id_t sid
,
713 crypto_mechanism_t
*mech
, crypto_key_t
*key
,
714 crypto_ctx_template_t tmpl
, crypto_context_t
*ctxp
,
715 crypto_call_req_t
*crq
)
717 return (crypto_cipher_init_prov(pd
, sid
, mech
, key
, tmpl
, ctxp
, crq
,
722 * crypto_decrypt_init()
724 * Calls crypto_cipher_init() to initialize a decryption operation
727 crypto_decrypt_init(crypto_mechanism_t
*mech
, crypto_key_t
*key
,
728 crypto_ctx_template_t tmpl
, crypto_context_t
*ctxp
,
729 crypto_call_req_t
*crq
)
731 return (crypto_cipher_init(mech
, key
, tmpl
, ctxp
, crq
,
736 * crypto_decrypt_update()
739 * context: A crypto_context_t initialized by decrypt_init().
740 * ciphertext: The message part to be decrypted
741 * plaintext: Storage for the decrypted message part.
742 * cr: crypto_call_req_t calling conditions and call back info.
745 * Asynchronously submits a request for, or synchronously performs a
746 * part of an decryption operation.
749 * Process or interrupt, according to the semantics dictated by the 'cr'.
752 * See comment in the beginning of the file.
755 crypto_decrypt_update(crypto_context_t context
, crypto_data_t
*ciphertext
,
756 crypto_data_t
*plaintext
, crypto_call_req_t
*cr
)
758 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
759 kcf_context_t
*kcf_ctx
;
760 kcf_provider_desc_t
*pd
;
762 kcf_req_params_t params
;
765 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
766 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
767 return (CRYPTO_INVALID_CONTEXT
);
770 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
772 /* The fast path for SW providers. */
773 if (CHECK_FASTPATH(cr
, pd
)) {
774 error
= KCF_PROV_DECRYPT_UPDATE(pd
, ctx
, ciphertext
,
776 KCF_PROV_INCRSTATS(pd
, error
);
780 /* Check if we should use a software provider for small jobs */
781 if ((ctx
->cc_flags
& CRYPTO_USE_OPSTATE
) && cr
== NULL
) {
782 if (ciphertext
->cd_length
< kcf_ctx
->kc_mech
->me_threshold
&&
783 kcf_ctx
->kc_sw_prov_desc
!= NULL
&&
784 KCF_IS_PROV_USABLE(kcf_ctx
->kc_sw_prov_desc
)) {
785 pd
= kcf_ctx
->kc_sw_prov_desc
;
789 KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms
, KCF_OP_UPDATE
,
790 ctx
->cc_session
, NULL
, NULL
, ciphertext
, plaintext
, NULL
);
791 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
797 * crypto_decrypt_final()
800 * context: A crypto_context_t initialized by decrypt_init().
801 * plaintext: Storage for the last part of the decrypted message
802 * cr: crypto_call_req_t calling conditions and call back info.
805 * Asynchronously submits a request for, or synchronously performs the
806 * final part of a decryption operation.
809 * Process or interrupt, according to the semantics dictated by the 'cr'.
812 * See comment in the beginning of the file.
815 crypto_decrypt_final(crypto_context_t context
, crypto_data_t
*plaintext
,
816 crypto_call_req_t
*cr
)
818 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
819 kcf_context_t
*kcf_ctx
;
820 kcf_provider_desc_t
*pd
;
822 kcf_req_params_t params
;
825 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
826 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
827 return (CRYPTO_INVALID_CONTEXT
);
830 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
832 /* The fast path for SW providers. */
833 if (CHECK_FASTPATH(cr
, pd
)) {
834 error
= KCF_PROV_DECRYPT_FINAL(pd
, ctx
, plaintext
,
836 KCF_PROV_INCRSTATS(pd
, error
);
838 KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms
, KCF_OP_FINAL
,
839 ctx
->cc_session
, NULL
, NULL
, NULL
, plaintext
, NULL
);
840 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
843 /* Release the hold done in kcf_new_ctx() during init step. */
844 KCF_CONTEXT_COND_RELEASE(error
, kcf_ctx
);
849 * See comments for crypto_encrypt_update().
852 crypto_encrypt_single(crypto_context_t context
, crypto_data_t
*plaintext
,
853 crypto_data_t
*ciphertext
, crypto_call_req_t
*cr
)
855 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
856 kcf_context_t
*kcf_ctx
;
857 kcf_provider_desc_t
*pd
;
859 kcf_req_params_t params
;
862 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
863 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
864 return (CRYPTO_INVALID_CONTEXT
);
867 /* The fast path for SW providers. */
868 if (CHECK_FASTPATH(cr
, pd
)) {
869 error
= KCF_PROV_ENCRYPT(pd
, ctx
, plaintext
,
871 KCF_PROV_INCRSTATS(pd
, error
);
873 KCF_WRAP_ENCRYPT_OPS_PARAMS(¶ms
, KCF_OP_SINGLE
, pd
->pd_sid
,
874 NULL
, NULL
, plaintext
, ciphertext
, NULL
);
875 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
878 /* Release the hold done in kcf_new_ctx() during init step. */
879 KCF_CONTEXT_COND_RELEASE(error
, kcf_ctx
);
884 * See comments for crypto_decrypt_update().
887 crypto_decrypt_single(crypto_context_t context
, crypto_data_t
*ciphertext
,
888 crypto_data_t
*plaintext
, crypto_call_req_t
*cr
)
890 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
891 kcf_context_t
*kcf_ctx
;
892 kcf_provider_desc_t
*pd
;
894 kcf_req_params_t params
;
897 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
898 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
899 return (CRYPTO_INVALID_CONTEXT
);
902 /* The fast path for SW providers. */
903 if (CHECK_FASTPATH(cr
, pd
)) {
904 error
= KCF_PROV_DECRYPT(pd
, ctx
, ciphertext
,
906 KCF_PROV_INCRSTATS(pd
, error
);
908 KCF_WRAP_DECRYPT_OPS_PARAMS(¶ms
, KCF_OP_SINGLE
, pd
->pd_sid
,
909 NULL
, NULL
, ciphertext
, plaintext
, NULL
);
910 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
913 /* Release the hold done in kcf_new_ctx() during init step. */
914 KCF_CONTEXT_COND_RELEASE(error
, kcf_ctx
);