1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * CDDL HEADER START 3*0Sstevel@tonic-gate * 4*0Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*0Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*0Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*0Sstevel@tonic-gate * with the License. 8*0Sstevel@tonic-gate * 9*0Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*0Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*0Sstevel@tonic-gate * See the License for the specific language governing permissions 12*0Sstevel@tonic-gate * and limitations under the License. 13*0Sstevel@tonic-gate * 14*0Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*0Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*0Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*0Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*0Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*0Sstevel@tonic-gate * 20*0Sstevel@tonic-gate * CDDL HEADER END 21*0Sstevel@tonic-gate */ 22*0Sstevel@tonic-gate /* 23*0Sstevel@tonic-gate * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24*0Sstevel@tonic-gate * Use is subject to license terms. 25*0Sstevel@tonic-gate */ 26*0Sstevel@tonic-gate 27*0Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*0Sstevel@tonic-gate 29*0Sstevel@tonic-gate #include <sys/errno.h> 30*0Sstevel@tonic-gate #include <sys/types.h> 31*0Sstevel@tonic-gate #include <sys/kmem.h> 32*0Sstevel@tonic-gate #include <sys/crypto/common.h> 33*0Sstevel@tonic-gate #include <sys/crypto/impl.h> 34*0Sstevel@tonic-gate #include <sys/crypto/api.h> 35*0Sstevel@tonic-gate #include <sys/crypto/spi.h> 36*0Sstevel@tonic-gate #include <sys/crypto/sched_impl.h> 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate /* 39*0Sstevel@tonic-gate * Sign entry points. 40*0Sstevel@tonic-gate */ 41*0Sstevel@tonic-gate 42*0Sstevel@tonic-gate /* 43*0Sstevel@tonic-gate * See comments for crypto_digest_init_prov(). 44*0Sstevel@tonic-gate */ 45*0Sstevel@tonic-gate int 46*0Sstevel@tonic-gate crypto_sign_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid, 47*0Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, crypto_ctx_template_t tmpl, 48*0Sstevel@tonic-gate crypto_context_t *ctxp, crypto_call_req_t *crq) 49*0Sstevel@tonic-gate { 50*0Sstevel@tonic-gate int error; 51*0Sstevel@tonic-gate crypto_ctx_t *ctx; 52*0Sstevel@tonic-gate kcf_req_params_t params; 53*0Sstevel@tonic-gate 54*0Sstevel@tonic-gate /* First, allocate and initialize the canonical context */ 55*0Sstevel@tonic-gate if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL) 56*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 57*0Sstevel@tonic-gate 58*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, mech, 59*0Sstevel@tonic-gate key, NULL, NULL, tmpl); 60*0Sstevel@tonic-gate 61*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, crq, ¶ms, B_FALSE); 62*0Sstevel@tonic-gate if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED)) 63*0Sstevel@tonic-gate *ctxp = (crypto_context_t)ctx; 64*0Sstevel@tonic-gate else { 65*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx(). */ 66*0Sstevel@tonic-gate KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 67*0Sstevel@tonic-gate } 68*0Sstevel@tonic-gate 69*0Sstevel@tonic-gate return (error); 70*0Sstevel@tonic-gate } 71*0Sstevel@tonic-gate 72*0Sstevel@tonic-gate int 73*0Sstevel@tonic-gate crypto_sign_init(crypto_mechanism_t *mech, crypto_key_t *key, 74*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_context_t *ctxp, crypto_call_req_t *crq) 75*0Sstevel@tonic-gate { 76*0Sstevel@tonic-gate int error; 77*0Sstevel@tonic-gate kcf_mech_entry_t *me; 78*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 79*0Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 80*0Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 81*0Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 82*0Sstevel@tonic-gate 83*0Sstevel@tonic-gate retry: 84*0Sstevel@tonic-gate /* The pd is returned held */ 85*0Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 86*0Sstevel@tonic-gate list, CRYPTO_FG_SIGN, CHECK_RESTRICT(crq), 0)) == NULL) { 87*0Sstevel@tonic-gate if (list != NULL) 88*0Sstevel@tonic-gate kcf_free_triedlist(list); 89*0Sstevel@tonic-gate return (error); 90*0Sstevel@tonic-gate } 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate /* 93*0Sstevel@tonic-gate * For SW providers, check the validity of the context template 94*0Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 95*0Sstevel@tonic-gate * it is acceptable to fail here, and let the consumer recover by 96*0Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 97*0Sstevel@tonic-gate * provider. 98*0Sstevel@tonic-gate */ 99*0Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 100*0Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 101*0Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 102*0Sstevel@tonic-gate if (list != NULL) 103*0Sstevel@tonic-gate kcf_free_triedlist(list); 104*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 105*0Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 106*0Sstevel@tonic-gate } else { 107*0Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 108*0Sstevel@tonic-gate } 109*0Sstevel@tonic-gate } 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate error = crypto_sign_init_prov(pd, pd->pd_sid, mech, key, spi_ctx_tmpl, 112*0Sstevel@tonic-gate ctxp, crq); 113*0Sstevel@tonic-gate 114*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 115*0Sstevel@tonic-gate IS_RECOVERABLE(error)) { 116*0Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 117*0Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 118*0Sstevel@tonic-gate goto retry; 119*0Sstevel@tonic-gate } 120*0Sstevel@tonic-gate 121*0Sstevel@tonic-gate if (list != NULL) 122*0Sstevel@tonic-gate kcf_free_triedlist(list); 123*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 124*0Sstevel@tonic-gate return (error); 125*0Sstevel@tonic-gate } 126*0Sstevel@tonic-gate 127*0Sstevel@tonic-gate int 128*0Sstevel@tonic-gate crypto_sign_single(crypto_context_t context, crypto_data_t *data, 129*0Sstevel@tonic-gate crypto_data_t *signature, crypto_call_req_t *cr) 130*0Sstevel@tonic-gate { 131*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 132*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 133*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 134*0Sstevel@tonic-gate int error; 135*0Sstevel@tonic-gate kcf_req_params_t params; 136*0Sstevel@tonic-gate 137*0Sstevel@tonic-gate if ((ctx == NULL) || 138*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 139*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 140*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 141*0Sstevel@tonic-gate } 142*0Sstevel@tonic-gate 143*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 144*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_SINGLE, 0, NULL, 145*0Sstevel@tonic-gate NULL, data, signature, NULL); 146*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 147*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 150*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 151*0Sstevel@tonic-gate return (error); 152*0Sstevel@tonic-gate } 153*0Sstevel@tonic-gate 154*0Sstevel@tonic-gate /* 155*0Sstevel@tonic-gate * See comments for crypto_digest_update(). 156*0Sstevel@tonic-gate */ 157*0Sstevel@tonic-gate int 158*0Sstevel@tonic-gate crypto_sign_update(crypto_context_t context, crypto_data_t *data, 159*0Sstevel@tonic-gate crypto_call_req_t *cr) 160*0Sstevel@tonic-gate { 161*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 162*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 163*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 164*0Sstevel@tonic-gate int error; 165*0Sstevel@tonic-gate kcf_req_params_t params; 166*0Sstevel@tonic-gate 167*0Sstevel@tonic-gate if ((ctx == NULL) || 168*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 169*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 170*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 171*0Sstevel@tonic-gate } 172*0Sstevel@tonic-gate 173*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 174*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_UPDATE, 0, NULL, 175*0Sstevel@tonic-gate NULL, data, NULL, NULL); 176*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 177*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate return (error); 180*0Sstevel@tonic-gate } 181*0Sstevel@tonic-gate 182*0Sstevel@tonic-gate /* 183*0Sstevel@tonic-gate * See comments for crypto_digest_final(). 184*0Sstevel@tonic-gate */ 185*0Sstevel@tonic-gate int 186*0Sstevel@tonic-gate crypto_sign_final(crypto_context_t context, crypto_data_t *signature, 187*0Sstevel@tonic-gate crypto_call_req_t *cr) 188*0Sstevel@tonic-gate { 189*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 190*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 191*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 192*0Sstevel@tonic-gate int error; 193*0Sstevel@tonic-gate kcf_req_params_t params; 194*0Sstevel@tonic-gate 195*0Sstevel@tonic-gate if ((ctx == NULL) || 196*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 197*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 198*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 199*0Sstevel@tonic-gate } 200*0Sstevel@tonic-gate 201*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 202*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_FINAL, 0, NULL, 203*0Sstevel@tonic-gate NULL, NULL, signature, NULL); 204*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 205*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 206*0Sstevel@tonic-gate 207*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 208*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 209*0Sstevel@tonic-gate return (error); 210*0Sstevel@tonic-gate } 211*0Sstevel@tonic-gate 212*0Sstevel@tonic-gate int 213*0Sstevel@tonic-gate crypto_sign_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid, 214*0Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, crypto_data_t *data, 215*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_data_t *signature, 216*0Sstevel@tonic-gate crypto_call_req_t *crq) 217*0Sstevel@tonic-gate { 218*0Sstevel@tonic-gate kcf_req_params_t params; 219*0Sstevel@tonic-gate 220*0Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 221*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, 222*0Sstevel@tonic-gate key, data, signature, tmpl); 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); 225*0Sstevel@tonic-gate } 226*0Sstevel@tonic-gate 227*0Sstevel@tonic-gate static int 228*0Sstevel@tonic-gate sign_sr_atomic_common(crypto_mechanism_t *mech, crypto_key_t *key, 229*0Sstevel@tonic-gate crypto_data_t *data, crypto_ctx_template_t tmpl, crypto_data_t *signature, 230*0Sstevel@tonic-gate crypto_call_req_t *crq, crypto_func_group_t fg) 231*0Sstevel@tonic-gate { 232*0Sstevel@tonic-gate int error; 233*0Sstevel@tonic-gate kcf_mech_entry_t *me; 234*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 235*0Sstevel@tonic-gate kcf_req_params_t params; 236*0Sstevel@tonic-gate kcf_prov_tried_t *list = NULL; 237*0Sstevel@tonic-gate kcf_ctx_template_t *ctx_tmpl; 238*0Sstevel@tonic-gate crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 239*0Sstevel@tonic-gate 240*0Sstevel@tonic-gate retry: 241*0Sstevel@tonic-gate /* The pd is returned held */ 242*0Sstevel@tonic-gate if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, list, fg, 243*0Sstevel@tonic-gate CHECK_RESTRICT(crq), data->cd_length)) == NULL) { 244*0Sstevel@tonic-gate if (list != NULL) 245*0Sstevel@tonic-gate kcf_free_triedlist(list); 246*0Sstevel@tonic-gate return (error); 247*0Sstevel@tonic-gate } 248*0Sstevel@tonic-gate 249*0Sstevel@tonic-gate /* 250*0Sstevel@tonic-gate * For SW providers, check the validity of the context template 251*0Sstevel@tonic-gate * It is very rare that the generation number mis-matches, so 252*0Sstevel@tonic-gate * it is acceptable to fail here, and let the consumer recover by 253*0Sstevel@tonic-gate * freeing this tmpl and create a new one for the key and new SW 254*0Sstevel@tonic-gate * provider. 255*0Sstevel@tonic-gate */ 256*0Sstevel@tonic-gate if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 257*0Sstevel@tonic-gate ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 258*0Sstevel@tonic-gate if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 259*0Sstevel@tonic-gate if (list != NULL) 260*0Sstevel@tonic-gate kcf_free_triedlist(list); 261*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 262*0Sstevel@tonic-gate return (CRYPTO_OLD_CTX_TEMPLATE); 263*0Sstevel@tonic-gate } else { 264*0Sstevel@tonic-gate spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 265*0Sstevel@tonic-gate } 266*0Sstevel@tonic-gate } 267*0Sstevel@tonic-gate 268*0Sstevel@tonic-gate /* The fast path for SW providers. */ 269*0Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) { 270*0Sstevel@tonic-gate crypto_mechanism_t lmech; 271*0Sstevel@tonic-gate 272*0Sstevel@tonic-gate lmech = *mech; 273*0Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 274*0Sstevel@tonic-gate if (fg == CRYPTO_FG_SIGN_ATOMIC) 275*0Sstevel@tonic-gate error = KCF_PROV_SIGN_ATOMIC(pd, pd->pd_sid, &lmech, 276*0Sstevel@tonic-gate key, data, spi_ctx_tmpl, signature, 277*0Sstevel@tonic-gate KCF_SWFP_RHNDL(crq)); 278*0Sstevel@tonic-gate else 279*0Sstevel@tonic-gate error = KCF_PROV_SIGN_RECOVER_ATOMIC(pd, pd->pd_sid, 280*0Sstevel@tonic-gate &lmech, key, data, spi_ctx_tmpl, signature, 281*0Sstevel@tonic-gate KCF_SWFP_RHNDL(crq)); 282*0Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error); 283*0Sstevel@tonic-gate } else { 284*0Sstevel@tonic-gate kcf_op_type_t op = ((fg == CRYPTO_FG_SIGN_ATOMIC) ? 285*0Sstevel@tonic-gate KCF_OP_ATOMIC : KCF_OP_SIGN_RECOVER_ATOMIC); 286*0Sstevel@tonic-gate 287*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, op, pd->pd_sid, 288*0Sstevel@tonic-gate mech, key, data, signature, spi_ctx_tmpl); 289*0Sstevel@tonic-gate 290*0Sstevel@tonic-gate /* no crypto context to carry between multiple parts. */ 291*0Sstevel@tonic-gate error = kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE); 292*0Sstevel@tonic-gate } 293*0Sstevel@tonic-gate 294*0Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 295*0Sstevel@tonic-gate IS_RECOVERABLE(error)) { 296*0Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */ 297*0Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 298*0Sstevel@tonic-gate goto retry; 299*0Sstevel@tonic-gate } 300*0Sstevel@tonic-gate 301*0Sstevel@tonic-gate if (list != NULL) 302*0Sstevel@tonic-gate kcf_free_triedlist(list); 303*0Sstevel@tonic-gate 304*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 305*0Sstevel@tonic-gate return (error); 306*0Sstevel@tonic-gate } 307*0Sstevel@tonic-gate 308*0Sstevel@tonic-gate int 309*0Sstevel@tonic-gate crypto_sign(crypto_mechanism_t *mech, crypto_key_t *key, crypto_data_t *data, 310*0Sstevel@tonic-gate crypto_ctx_template_t tmpl, crypto_data_t *signature, 311*0Sstevel@tonic-gate crypto_call_req_t *crq) 312*0Sstevel@tonic-gate { 313*0Sstevel@tonic-gate return (sign_sr_atomic_common(mech, key, data, tmpl, signature, crq, 314*0Sstevel@tonic-gate CRYPTO_FG_SIGN_ATOMIC)); 315*0Sstevel@tonic-gate } 316*0Sstevel@tonic-gate 317*0Sstevel@tonic-gate int 318*0Sstevel@tonic-gate crypto_sign_recover_prov(kcf_provider_desc_t *pd, 319*0Sstevel@tonic-gate crypto_session_id_t sid, crypto_mechanism_t *mech, crypto_key_t *key, 320*0Sstevel@tonic-gate crypto_data_t *data, crypto_ctx_template_t tmpl, crypto_data_t *signature, 321*0Sstevel@tonic-gate crypto_call_req_t *crq) 322*0Sstevel@tonic-gate { 323*0Sstevel@tonic-gate kcf_req_params_t params; 324*0Sstevel@tonic-gate 325*0Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd)); 326*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_SIGN_RECOVER_ATOMIC, sid, mech, 327*0Sstevel@tonic-gate key, data, signature, tmpl); 328*0Sstevel@tonic-gate 329*0Sstevel@tonic-gate return (kcf_submit_request(pd, NULL, crq, ¶ms, B_FALSE)); 330*0Sstevel@tonic-gate } 331*0Sstevel@tonic-gate 332*0Sstevel@tonic-gate int 333*0Sstevel@tonic-gate crypto_sign_recover(crypto_mechanism_t *mech, crypto_key_t *key, 334*0Sstevel@tonic-gate crypto_data_t *data, crypto_ctx_template_t tmpl, crypto_data_t *signature, 335*0Sstevel@tonic-gate crypto_call_req_t *crq) 336*0Sstevel@tonic-gate { 337*0Sstevel@tonic-gate return (sign_sr_atomic_common(mech, key, data, tmpl, signature, crq, 338*0Sstevel@tonic-gate CRYPTO_FG_SIGN_RECOVER_ATOMIC)); 339*0Sstevel@tonic-gate } 340*0Sstevel@tonic-gate 341*0Sstevel@tonic-gate int 342*0Sstevel@tonic-gate crypto_sign_recover_init_prov(kcf_provider_desc_t *pd, crypto_session_id_t sid, 343*0Sstevel@tonic-gate crypto_mechanism_t *mech, crypto_key_t *key, crypto_ctx_template_t tmpl, 344*0Sstevel@tonic-gate crypto_context_t *ctxp, crypto_call_req_t *crq) 345*0Sstevel@tonic-gate { 346*0Sstevel@tonic-gate int error; 347*0Sstevel@tonic-gate crypto_ctx_t *ctx; 348*0Sstevel@tonic-gate kcf_req_params_t params; 349*0Sstevel@tonic-gate 350*0Sstevel@tonic-gate /* First, allocate and initialize the canonical context */ 351*0Sstevel@tonic-gate if ((ctx = kcf_new_ctx(crq, pd, sid)) == NULL) 352*0Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY); 353*0Sstevel@tonic-gate 354*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_SIGN_RECOVER_INIT, sid, mech, 355*0Sstevel@tonic-gate key, NULL, NULL, tmpl); 356*0Sstevel@tonic-gate 357*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, crq, ¶ms, B_FALSE); 358*0Sstevel@tonic-gate if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED)) 359*0Sstevel@tonic-gate *ctxp = (crypto_context_t)ctx; 360*0Sstevel@tonic-gate else { 361*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx(). */ 362*0Sstevel@tonic-gate KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 363*0Sstevel@tonic-gate } 364*0Sstevel@tonic-gate 365*0Sstevel@tonic-gate return (error); 366*0Sstevel@tonic-gate } 367*0Sstevel@tonic-gate 368*0Sstevel@tonic-gate int 369*0Sstevel@tonic-gate crypto_sign_recover_single(crypto_context_t context, crypto_data_t *data, 370*0Sstevel@tonic-gate crypto_data_t *signature, crypto_call_req_t *cr) 371*0Sstevel@tonic-gate { 372*0Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context; 373*0Sstevel@tonic-gate kcf_context_t *kcf_ctx; 374*0Sstevel@tonic-gate kcf_provider_desc_t *pd; 375*0Sstevel@tonic-gate int error; 376*0Sstevel@tonic-gate kcf_req_params_t params; 377*0Sstevel@tonic-gate 378*0Sstevel@tonic-gate if ((ctx == NULL) || 379*0Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 380*0Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 381*0Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT); 382*0Sstevel@tonic-gate } 383*0Sstevel@tonic-gate 384*0Sstevel@tonic-gate KCF_PROV_REFHOLD(pd); 385*0Sstevel@tonic-gate KCF_WRAP_SIGN_OPS_PARAMS(¶ms, KCF_OP_SIGN_RECOVER, 0, NULL, 386*0Sstevel@tonic-gate NULL, data, signature, NULL); 387*0Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 388*0Sstevel@tonic-gate KCF_PROV_REFRELE(pd); 389*0Sstevel@tonic-gate 390*0Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */ 391*0Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 392*0Sstevel@tonic-gate return (error); 393*0Sstevel@tonic-gate } 394