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/cmn_err.h>
29 #include <sys/sysmacros.h>
30 #include <sys/crypto/common.h>
31 #include <sys/crypto/impl.h>
32 #include <sys/crypto/api.h>
33 #include <sys/crypto/spi.h>
34 #include <sys/crypto/sched_impl.h>
36 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
37 #define CRYPTO_DIGEST_OFFSET(f) offsetof(crypto_digest_ops_t, f)
40 * Message digest routines
44 * The following are the possible returned values common to all the routines
45 * below. The applicability of some of these return values depends on the
46 * presence of the arguments.
48 * CRYPTO_SUCCESS: The operation completed successfully.
49 * CRYPTO_QUEUED: A request was submitted successfully. The callback
50 * routine will be called when the operation is done.
51 * CRYPTO_MECHANISM_INVALID or CRYPTO_INVALID_MECH_PARAM
52 * for problems with the 'mech'.
53 * CRYPTO_INVALID_DATA for bogus 'data'
54 * CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work.
55 * CRYPTO_INVALID_CONTEXT: Not a valid context.
56 * CRYPTO_BUSY: Cannot process the request now. Schedule a
57 * crypto_bufcall(), or try later.
58 * CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED:
59 * No provider is capable of a function or a mechanism.
64 * crypto_digest_prov()
67 * pd: pointer to the descriptor of the provider to use for this
69 * sid: provider session id.
70 * mech: crypto_mechanism_t pointer.
71 * mech_type is a valid value previously returned by
73 * When the mech's parameter is not NULL, its definition depends
74 * on the standard definition of the mechanism.
75 * data: The message to be digested.
76 * digest: Storage for the digest. The length needed depends on the
78 * cr: crypto_call_req_t calling conditions and call back info.
81 * Asynchronously submits a request for, or synchronously performs the
82 * digesting operation of 'data' on the specified
83 * provider with the specified session.
84 * When complete and successful, 'digest' will contain the digest value.
85 * The caller should hold a reference on the specified provider
86 * descriptor before calling this function.
89 * Process or interrupt, according to the semantics dictated by the 'cr'.
92 * See comment in the beginning of the file.
95 crypto_digest_prov(crypto_provider_t provider
, crypto_session_id_t sid
,
96 crypto_mechanism_t
*mech
, crypto_data_t
*data
, crypto_data_t
*digest
,
97 crypto_call_req_t
*crq
)
99 kcf_req_params_t params
;
100 kcf_provider_desc_t
*pd
= provider
;
101 kcf_provider_desc_t
*real_provider
= pd
;
104 ASSERT(KCF_PROV_REFHELD(pd
));
106 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
107 rv
= kcf_get_hardware_provider(mech
->cm_type
, NULL
,
108 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
109 CRYPTO_FG_DIGEST_ATOMIC
);
111 if (rv
!= CRYPTO_SUCCESS
)
114 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms
, KCF_OP_ATOMIC
, sid
, mech
, NULL
,
117 /* no crypto context to carry between multiple parts. */
118 rv
= kcf_submit_request(real_provider
, NULL
, crq
, ¶ms
, B_FALSE
);
119 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
120 KCF_PROV_REFRELE(real_provider
);
126 * Same as crypto_digest_prov(), but relies on the KCF scheduler to
127 * choose a provider. See crypto_digest_prov() comments for more information.
130 crypto_digest(crypto_mechanism_t
*mech
, crypto_data_t
*data
,
131 crypto_data_t
*digest
, crypto_call_req_t
*crq
)
134 kcf_provider_desc_t
*pd
;
135 kcf_req_params_t params
;
136 kcf_prov_tried_t
*list
= NULL
;
139 /* The pd is returned held */
140 if ((pd
= kcf_get_mech_provider(mech
->cm_type
, NULL
, NULL
, &error
,
141 list
, CRYPTO_FG_DIGEST_ATOMIC
, data
->cd_length
)) == NULL
) {
143 kcf_free_triedlist(list
);
147 /* The fast path for SW providers. */
148 if (CHECK_FASTPATH(crq
, pd
)) {
149 crypto_mechanism_t lmech
;
152 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, pd
, &lmech
);
153 error
= KCF_PROV_DIGEST_ATOMIC(pd
, pd
->pd_sid
, &lmech
, data
,
154 digest
, KCF_SWFP_RHNDL(crq
));
155 KCF_PROV_INCRSTATS(pd
, error
);
157 if (pd
->pd_prov_type
== CRYPTO_HW_PROVIDER
&&
158 (pd
->pd_flags
& CRYPTO_HASH_NO_UPDATE
) &&
159 (data
->cd_length
> pd
->pd_hash_limit
)) {
160 error
= CRYPTO_BUFFER_TOO_BIG
;
162 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms
, KCF_OP_ATOMIC
,
163 pd
->pd_sid
, mech
, NULL
, data
, digest
);
165 /* no crypto context to carry between multiple parts. */
166 error
= kcf_submit_request(pd
, NULL
, crq
, ¶ms
,
171 if (error
!= CRYPTO_SUCCESS
&& error
!= CRYPTO_QUEUED
&&
172 IS_RECOVERABLE(error
)) {
173 /* Add pd to the linked list of providers tried. */
174 if (kcf_insert_triedlist(&list
, pd
, KCF_KMFLAG(crq
)) != NULL
)
179 kcf_free_triedlist(list
);
181 KCF_PROV_REFRELE(pd
);
186 * crypto_digest_init_prov()
188 * pd: pointer to the descriptor of the provider to use for this
190 * sid: provider session id.
191 * mech: crypto_mechanism_t pointer.
192 * mech_type is a valid value previously returned by
194 * When the mech's parameter is not NULL, its definition depends
195 * on the standard definition of the mechanism.
196 * ctxp: Pointer to a crypto_context_t.
197 * cr: crypto_call_req_t calling conditions and call back info.
200 * Asynchronously submits a request for, or synchronously performs the
201 * initialization of a message digest operation on the specified
202 * provider with the specified session.
203 * When complete and successful, 'ctxp' will contain a crypto_context_t
204 * valid for later calls to digest_update() and digest_final().
205 * The caller should hold a reference on the specified provider
206 * descriptor before calling this function.
209 crypto_digest_init_prov(crypto_provider_t provider
, crypto_session_id_t sid
,
210 crypto_mechanism_t
*mech
, crypto_context_t
*ctxp
, crypto_call_req_t
*crq
)
214 kcf_req_params_t params
;
215 kcf_provider_desc_t
*pd
= provider
;
216 kcf_provider_desc_t
*real_provider
= pd
;
218 ASSERT(KCF_PROV_REFHELD(pd
));
220 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
221 error
= kcf_get_hardware_provider(mech
->cm_type
, NULL
,
222 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
225 if (error
!= CRYPTO_SUCCESS
)
229 /* Allocate and initialize the canonical context */
230 if ((ctx
= kcf_new_ctx(crq
, real_provider
, sid
)) == NULL
) {
231 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
232 KCF_PROV_REFRELE(real_provider
);
233 return (CRYPTO_HOST_MEMORY
);
236 /* The fast path for SW providers. */
237 if (CHECK_FASTPATH(crq
, pd
)) {
238 crypto_mechanism_t lmech
;
241 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, real_provider
, &lmech
);
242 error
= KCF_PROV_DIGEST_INIT(real_provider
, ctx
, &lmech
,
243 KCF_SWFP_RHNDL(crq
));
244 KCF_PROV_INCRSTATS(pd
, error
);
246 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms
, KCF_OP_INIT
, sid
,
247 mech
, NULL
, NULL
, NULL
);
248 error
= kcf_submit_request(real_provider
, ctx
, crq
, ¶ms
,
252 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
253 KCF_PROV_REFRELE(real_provider
);
255 if ((error
== CRYPTO_SUCCESS
) || (error
== CRYPTO_QUEUED
))
256 *ctxp
= (crypto_context_t
)ctx
;
258 /* Release the hold done in kcf_new_ctx(). */
259 KCF_CONTEXT_REFRELE((kcf_context_t
*)ctx
->cc_framework_private
);
267 * Same as crypto_digest_init_prov(), but relies on the KCF scheduler
268 * to choose a provider. See crypto_digest_init_prov() comments for
272 crypto_digest_init(crypto_mechanism_t
*mech
, crypto_context_t
*ctxp
,
273 crypto_call_req_t
*crq
)
276 kcf_provider_desc_t
*pd
;
277 kcf_prov_tried_t
*list
= NULL
;
280 /* The pd is returned held */
281 if ((pd
= kcf_get_mech_provider(mech
->cm_type
, NULL
, NULL
, &error
,
282 list
, CRYPTO_FG_DIGEST
, 0)) == NULL
) {
284 kcf_free_triedlist(list
);
288 if (pd
->pd_prov_type
== CRYPTO_HW_PROVIDER
&&
289 (pd
->pd_flags
& CRYPTO_HASH_NO_UPDATE
)) {
291 * The hardware provider has limited digest support.
292 * So, we fallback early here to using a software provider.
294 * XXX - need to enhance to do the fallback later in
295 * crypto_digest_update() if the size of accumulated input data
296 * exceeds the maximum size digestable by hardware provider.
298 error
= CRYPTO_BUFFER_TOO_BIG
;
300 error
= crypto_digest_init_prov(pd
, pd
->pd_sid
,
304 if (error
!= CRYPTO_SUCCESS
&& error
!= CRYPTO_QUEUED
&&
305 IS_RECOVERABLE(error
)) {
306 /* Add pd to the linked list of providers tried. */
307 if (kcf_insert_triedlist(&list
, pd
, KCF_KMFLAG(crq
)) != NULL
)
312 kcf_free_triedlist(list
);
313 KCF_PROV_REFRELE(pd
);
318 * crypto_digest_update()
321 * context: A crypto_context_t initialized by digest_init().
322 * data: The part of message to be digested.
323 * cr: crypto_call_req_t calling conditions and call back info.
326 * Asynchronously submits a request for, or synchronously performs a
327 * part of a message digest operation.
330 * Process or interrupt, according to the semantics dictated by the 'cr'.
333 * See comment in the beginning of the file.
336 crypto_digest_update(crypto_context_t context
, crypto_data_t
*data
,
337 crypto_call_req_t
*cr
)
339 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
340 kcf_context_t
*kcf_ctx
;
341 kcf_provider_desc_t
*pd
;
343 kcf_req_params_t params
;
346 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
347 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
348 return (CRYPTO_INVALID_CONTEXT
);
351 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
353 /* The fast path for SW providers. */
354 if (CHECK_FASTPATH(cr
, pd
)) {
355 error
= KCF_PROV_DIGEST_UPDATE(pd
, ctx
, data
, NULL
);
356 KCF_PROV_INCRSTATS(pd
, error
);
358 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms
, KCF_OP_UPDATE
,
359 ctx
->cc_session
, NULL
, NULL
, data
, NULL
);
360 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
367 * crypto_digest_final()
370 * context: A crypto_context_t initialized by digest_init().
371 * digest: The storage for the digest.
372 * cr: crypto_call_req_t calling conditions and call back info.
375 * Asynchronously submits a request for, or synchronously performs the
376 * final part of a message digest operation.
379 * Process or interrupt, according to the semantics dictated by the 'cr'.
382 * See comment in the beginning of the file.
385 crypto_digest_final(crypto_context_t context
, crypto_data_t
*digest
,
386 crypto_call_req_t
*cr
)
388 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
389 kcf_context_t
*kcf_ctx
;
390 kcf_provider_desc_t
*pd
;
392 kcf_req_params_t params
;
395 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
396 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
397 return (CRYPTO_INVALID_CONTEXT
);
400 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
402 /* The fast path for SW providers. */
403 if (CHECK_FASTPATH(cr
, pd
)) {
404 error
= KCF_PROV_DIGEST_FINAL(pd
, ctx
, digest
, NULL
);
405 KCF_PROV_INCRSTATS(pd
, error
);
407 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms
, KCF_OP_FINAL
,
408 ctx
->cc_session
, NULL
, NULL
, NULL
, digest
);
409 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
412 /* Release the hold done in kcf_new_ctx() during init step. */
413 KCF_CONTEXT_COND_RELEASE(error
, kcf_ctx
);
418 * Performs a digest update on the specified key. Note that there is
419 * no k-API crypto_digest_key() equivalent of this function.
422 crypto_digest_key_prov(crypto_context_t context
, crypto_key_t
*key
,
423 crypto_call_req_t
*cr
)
425 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
426 kcf_context_t
*kcf_ctx
;
427 kcf_provider_desc_t
*pd
;
429 kcf_req_params_t params
;
432 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
433 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
434 return (CRYPTO_INVALID_CONTEXT
);
437 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
439 /* The fast path for SW providers. */
440 if (CHECK_FASTPATH(cr
, pd
)) {
441 error
= KCF_PROV_DIGEST_KEY(pd
, ctx
, key
, NULL
);
442 KCF_PROV_INCRSTATS(pd
, error
);
444 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms
, KCF_OP_DIGEST_KEY
,
445 ctx
->cc_session
, NULL
, key
, NULL
, NULL
);
446 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
453 * See comments for crypto_digest_update() and crypto_digest_final().
456 crypto_digest_single(crypto_context_t context
, crypto_data_t
*data
,
457 crypto_data_t
*digest
, crypto_call_req_t
*cr
)
459 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
460 kcf_context_t
*kcf_ctx
;
461 kcf_provider_desc_t
*pd
;
463 kcf_req_params_t params
;
466 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
467 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
468 return (CRYPTO_INVALID_CONTEXT
);
472 /* The fast path for SW providers. */
473 if (CHECK_FASTPATH(cr
, pd
)) {
474 error
= KCF_PROV_DIGEST(pd
, ctx
, data
, digest
, NULL
);
475 KCF_PROV_INCRSTATS(pd
, error
);
477 KCF_WRAP_DIGEST_OPS_PARAMS(¶ms
, KCF_OP_SINGLE
, pd
->pd_sid
,
478 NULL
, NULL
, data
, digest
);
479 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
482 /* Release the hold done in kcf_new_ctx() during init step. */
483 KCF_CONTEXT_COND_RELEASE(error
, kcf_ctx
);