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_VERIFY_OFFSET(f) offsetof(crypto_verify_ops_t, f)
39 * Verify entry points.
43 * See comments for crypto_digest_init_prov().
46 crypto_verify_init_prov(crypto_provider_t provider
, crypto_session_id_t sid
,
47 crypto_mechanism_t
*mech
, crypto_key_t
*key
, crypto_ctx_template_t tmpl
,
48 crypto_context_t
*ctxp
, crypto_call_req_t
*crq
)
52 kcf_req_params_t params
;
53 kcf_provider_desc_t
*pd
= provider
;
54 kcf_provider_desc_t
*real_provider
= pd
;
56 ASSERT(KCF_PROV_REFHELD(pd
));
58 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
59 rv
= kcf_get_hardware_provider(mech
->cm_type
, key
,
60 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
63 if (rv
!= CRYPTO_SUCCESS
)
67 /* Allocate and initialize the canonical context */
68 if ((ctx
= kcf_new_ctx(crq
, real_provider
, sid
)) == NULL
) {
69 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
70 KCF_PROV_REFRELE(real_provider
);
71 return (CRYPTO_HOST_MEMORY
);
74 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, KCF_OP_INIT
, sid
, mech
,
75 key
, NULL
, NULL
, tmpl
);
76 rv
= kcf_submit_request(real_provider
, ctx
, crq
, ¶ms
, B_FALSE
);
77 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
78 KCF_PROV_REFRELE(real_provider
);
80 if ((rv
== CRYPTO_SUCCESS
) || (rv
== CRYPTO_QUEUED
))
81 *ctxp
= (crypto_context_t
)ctx
;
83 /* Release the hold done in kcf_new_ctx(). */
84 KCF_CONTEXT_REFRELE((kcf_context_t
*)ctx
->cc_framework_private
);
92 crypto_verify_init(crypto_mechanism_t
*mech
, crypto_key_t
*key
,
93 crypto_ctx_template_t tmpl
, crypto_context_t
*ctxp
, crypto_call_req_t
*crq
)
97 kcf_provider_desc_t
*pd
;
98 kcf_prov_tried_t
*list
= NULL
;
99 kcf_ctx_template_t
*ctx_tmpl
;
100 crypto_spi_ctx_template_t spi_ctx_tmpl
= NULL
;
103 /* The pd is returned held */
104 if ((pd
= kcf_get_mech_provider(mech
->cm_type
, key
, &me
, &error
,
105 list
, CRYPTO_FG_VERIFY
, 0)) == NULL
) {
107 kcf_free_triedlist(list
);
112 * For SW providers, check the validity of the context template
113 * It is very rare that the generation number mis-matches, so
114 * it is acceptable to fail here, and let the consumer recover by
115 * freeing this tmpl and create a new one for the key and new SW
118 if ((pd
->pd_prov_type
== CRYPTO_SW_PROVIDER
) &&
119 ((ctx_tmpl
= (kcf_ctx_template_t
*)tmpl
) != NULL
)) {
120 if (ctx_tmpl
->ct_generation
!= me
->me_gen_swprov
) {
122 kcf_free_triedlist(list
);
123 KCF_PROV_REFRELE(pd
);
124 return (CRYPTO_OLD_CTX_TEMPLATE
);
126 spi_ctx_tmpl
= ctx_tmpl
->ct_prov_tmpl
;
130 error
= crypto_verify_init_prov(pd
, pd
->pd_sid
, mech
, key
, spi_ctx_tmpl
,
133 if (error
!= CRYPTO_SUCCESS
&& error
!= CRYPTO_QUEUED
&&
134 IS_RECOVERABLE(error
)) {
135 /* Add pd to the linked list of providers tried. */
136 if (kcf_insert_triedlist(&list
, pd
, KCF_KMFLAG(crq
)) != NULL
)
141 kcf_free_triedlist(list
);
142 KCF_PROV_REFRELE(pd
);
147 crypto_verify_single(crypto_context_t context
, crypto_data_t
*data
,
148 crypto_data_t
*signature
, crypto_call_req_t
*cr
)
150 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
151 kcf_context_t
*kcf_ctx
;
152 kcf_provider_desc_t
*pd
;
154 kcf_req_params_t params
;
157 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
158 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
159 return (CRYPTO_INVALID_CONTEXT
);
162 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, KCF_OP_SINGLE
, 0, NULL
,
163 NULL
, data
, signature
, NULL
);
164 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
166 /* Release the hold done in kcf_new_ctx() during init step. */
167 KCF_CONTEXT_COND_RELEASE(error
, kcf_ctx
);
172 * See comments for crypto_digest_update().
175 crypto_verify_update(crypto_context_t context
, crypto_data_t
*data
,
176 crypto_call_req_t
*cr
)
179 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
180 kcf_context_t
*kcf_ctx
;
181 kcf_provider_desc_t
*pd
;
182 kcf_req_params_t params
;
186 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
187 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
188 return (CRYPTO_INVALID_CONTEXT
);
191 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
192 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, KCF_OP_UPDATE
, ctx
->cc_session
,
193 NULL
, NULL
, data
, NULL
, NULL
);
194 rv
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
200 * See comments for crypto_digest_final().
203 crypto_verify_final(crypto_context_t context
, crypto_data_t
*signature
,
204 crypto_call_req_t
*cr
)
206 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
207 kcf_context_t
*kcf_ctx
;
208 kcf_provider_desc_t
*pd
;
209 kcf_req_params_t params
;
213 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
214 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
215 return (CRYPTO_INVALID_CONTEXT
);
218 ASSERT(pd
->pd_prov_type
!= CRYPTO_LOGICAL_PROVIDER
);
219 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, KCF_OP_FINAL
, ctx
->cc_session
,
220 NULL
, NULL
, NULL
, signature
, NULL
);
221 rv
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
223 /* Release the hold done in kcf_new_ctx() during init step. */
224 KCF_CONTEXT_COND_RELEASE(rv
, kcf_ctx
);
229 crypto_verify_prov(crypto_provider_t provider
, crypto_session_id_t sid
,
230 crypto_mechanism_t
*mech
, crypto_key_t
*key
, crypto_data_t
*data
,
231 crypto_ctx_template_t tmpl
, crypto_data_t
*signature
,
232 crypto_call_req_t
*crq
)
234 kcf_req_params_t params
;
235 kcf_provider_desc_t
*pd
= provider
;
236 kcf_provider_desc_t
*real_provider
= pd
;
239 ASSERT(KCF_PROV_REFHELD(pd
));
241 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
242 rv
= kcf_get_hardware_provider(mech
->cm_type
, key
,
243 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
244 CRYPTO_FG_VERIFY_ATOMIC
);
246 if (rv
!= CRYPTO_SUCCESS
)
249 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, KCF_OP_ATOMIC
, sid
, mech
,
250 key
, data
, signature
, tmpl
);
251 rv
= kcf_submit_request(real_provider
, NULL
, crq
, ¶ms
, B_FALSE
);
252 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
253 KCF_PROV_REFRELE(real_provider
);
259 verify_vr_atomic_common(crypto_mechanism_t
*mech
, crypto_key_t
*key
,
260 crypto_data_t
*data
, crypto_ctx_template_t tmpl
, crypto_data_t
*signature
,
261 crypto_call_req_t
*crq
, crypto_func_group_t fg
)
264 kcf_mech_entry_t
*me
;
265 kcf_provider_desc_t
*pd
;
266 kcf_req_params_t params
;
267 kcf_prov_tried_t
*list
= NULL
;
268 kcf_ctx_template_t
*ctx_tmpl
;
269 crypto_spi_ctx_template_t spi_ctx_tmpl
= NULL
;
272 /* The pd is returned held */
273 if ((pd
= kcf_get_mech_provider(mech
->cm_type
, key
, &me
, &error
,
274 list
, fg
, data
->cd_length
)) == NULL
) {
276 kcf_free_triedlist(list
);
281 * For SW providers, check the validity of the context template
282 * It is very rare that the generation number mis-matches, so
283 * it is acceptable to fail here, and let the consumer recover by
284 * freeing this tmpl and create a new one for the key and new SW
287 if ((pd
->pd_prov_type
== CRYPTO_SW_PROVIDER
) &&
288 ((ctx_tmpl
= (kcf_ctx_template_t
*)tmpl
) != NULL
)) {
289 if (ctx_tmpl
->ct_generation
!= me
->me_gen_swprov
) {
291 kcf_free_triedlist(list
);
292 KCF_PROV_REFRELE(pd
);
293 return (CRYPTO_OLD_CTX_TEMPLATE
);
295 spi_ctx_tmpl
= ctx_tmpl
->ct_prov_tmpl
;
299 /* The fast path for SW providers. */
300 if (CHECK_FASTPATH(crq
, pd
)) {
301 crypto_mechanism_t lmech
;
304 KCF_SET_PROVIDER_MECHNUM(mech
->cm_type
, pd
, &lmech
);
305 if (fg
== CRYPTO_FG_VERIFY_ATOMIC
)
306 error
= KCF_PROV_VERIFY_ATOMIC(pd
, pd
->pd_sid
, &lmech
,
307 key
, data
, spi_ctx_tmpl
, signature
,
308 KCF_SWFP_RHNDL(crq
));
310 /* Note: The argument order is different from above */
311 error
= KCF_PROV_VERIFY_RECOVER_ATOMIC(pd
, pd
->pd_sid
,
312 &lmech
, key
, signature
, spi_ctx_tmpl
, data
,
313 KCF_SWFP_RHNDL(crq
));
314 KCF_PROV_INCRSTATS(pd
, error
);
316 kcf_op_type_t op
= ((fg
== CRYPTO_FG_VERIFY_ATOMIC
) ?
317 KCF_OP_ATOMIC
: KCF_OP_VERIFY_RECOVER_ATOMIC
);
319 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, op
, pd
->pd_sid
,
320 mech
, key
, data
, signature
, spi_ctx_tmpl
);
322 /* no crypto context to carry between multiple parts. */
323 error
= kcf_submit_request(pd
, NULL
, crq
, ¶ms
, B_FALSE
);
326 if (error
!= CRYPTO_SUCCESS
&& error
!= CRYPTO_QUEUED
&&
327 IS_RECOVERABLE(error
)) {
328 /* Add pd to the linked list of providers tried. */
329 if (kcf_insert_triedlist(&list
, pd
, KCF_KMFLAG(crq
)) != NULL
)
334 kcf_free_triedlist(list
);
336 KCF_PROV_REFRELE(pd
);
341 crypto_verify(crypto_mechanism_t
*mech
, crypto_key_t
*key
, crypto_data_t
*data
,
342 crypto_ctx_template_t tmpl
, crypto_data_t
*signature
,
343 crypto_call_req_t
*crq
)
345 return (verify_vr_atomic_common(mech
, key
, data
, tmpl
, signature
, crq
,
346 CRYPTO_FG_VERIFY_ATOMIC
));
350 crypto_verify_recover_prov(crypto_provider_t provider
, crypto_session_id_t sid
,
351 crypto_mechanism_t
*mech
, crypto_key_t
*key
, crypto_data_t
*signature
,
352 crypto_ctx_template_t tmpl
, crypto_data_t
*data
, crypto_call_req_t
*crq
)
354 kcf_req_params_t params
;
355 kcf_provider_desc_t
*pd
= provider
;
356 kcf_provider_desc_t
*real_provider
= pd
;
359 ASSERT(KCF_PROV_REFHELD(pd
));
361 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
362 rv
= kcf_get_hardware_provider(mech
->cm_type
, key
,
363 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
364 CRYPTO_FG_VERIFY_RECOVER_ATOMIC
);
366 if (rv
!= CRYPTO_SUCCESS
)
369 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, KCF_OP_VERIFY_RECOVER_ATOMIC
,
370 sid
, mech
, key
, data
, signature
, tmpl
);
371 rv
= kcf_submit_request(real_provider
, NULL
, crq
, ¶ms
, B_FALSE
);
372 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
373 KCF_PROV_REFRELE(real_provider
);
379 crypto_verify_recover(crypto_mechanism_t
*mech
, crypto_key_t
*key
,
380 crypto_data_t
*signature
, crypto_ctx_template_t tmpl
, crypto_data_t
*data
,
381 crypto_call_req_t
*crq
)
383 return (verify_vr_atomic_common(mech
, key
, data
, tmpl
, signature
, crq
,
384 CRYPTO_FG_VERIFY_RECOVER_ATOMIC
));
388 crypto_verify_recover_init_prov(crypto_provider_t provider
,
389 crypto_session_id_t sid
, crypto_mechanism_t
*mech
, crypto_key_t
*key
,
390 crypto_ctx_template_t tmpl
, crypto_context_t
*ctxp
, crypto_call_req_t
*crq
)
394 kcf_req_params_t params
;
395 kcf_provider_desc_t
*pd
= provider
;
396 kcf_provider_desc_t
*real_provider
= pd
;
398 ASSERT(KCF_PROV_REFHELD(pd
));
400 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
) {
401 rv
= kcf_get_hardware_provider(mech
->cm_type
, key
,
402 CRYPTO_MECH_INVALID
, NULL
, pd
, &real_provider
,
403 CRYPTO_FG_VERIFY_RECOVER
);
405 if (rv
!= CRYPTO_SUCCESS
)
409 /* Allocate and initialize the canonical context */
410 if ((ctx
= kcf_new_ctx(crq
, real_provider
, sid
)) == NULL
) {
411 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
412 KCF_PROV_REFRELE(real_provider
);
413 return (CRYPTO_HOST_MEMORY
);
416 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, KCF_OP_VERIFY_RECOVER_INIT
,
417 sid
, mech
, key
, NULL
, NULL
, tmpl
);
418 rv
= kcf_submit_request(real_provider
, ctx
, crq
, ¶ms
, B_FALSE
);
419 if (pd
->pd_prov_type
== CRYPTO_LOGICAL_PROVIDER
)
420 KCF_PROV_REFRELE(real_provider
);
422 if ((rv
== CRYPTO_SUCCESS
) || (rv
== CRYPTO_QUEUED
))
423 *ctxp
= (crypto_context_t
)ctx
;
425 /* Release the hold done in kcf_new_ctx(). */
426 KCF_CONTEXT_REFRELE((kcf_context_t
*)ctx
->cc_framework_private
);
433 crypto_verify_recover_single(crypto_context_t context
, crypto_data_t
*signature
,
434 crypto_data_t
*data
, crypto_call_req_t
*cr
)
436 crypto_ctx_t
*ctx
= (crypto_ctx_t
*)context
;
437 kcf_context_t
*kcf_ctx
;
438 kcf_provider_desc_t
*pd
;
440 kcf_req_params_t params
;
443 ((kcf_ctx
= (kcf_context_t
*)ctx
->cc_framework_private
) == NULL
) ||
444 ((pd
= kcf_ctx
->kc_prov_desc
) == NULL
)) {
445 return (CRYPTO_INVALID_CONTEXT
);
448 KCF_WRAP_VERIFY_OPS_PARAMS(¶ms
, KCF_OP_VERIFY_RECOVER
, 0, NULL
,
449 NULL
, data
, signature
, NULL
);
450 error
= kcf_submit_request(pd
, ctx
, cr
, ¶ms
, B_FALSE
);
452 /* Release the hold done in kcf_new_ctx() during init step. */
453 KCF_CONTEXT_COND_RELEASE(error
, kcf_ctx
);