1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <sys/errno.h> 30 #include <sys/types.h> 31 #include <sys/kmem.h> 32 #include <sys/sysmacros.h> 33 #include <sys/crypto/common.h> 34 #include <sys/crypto/impl.h> 35 #include <sys/crypto/api.h> 36 #include <sys/crypto/spi.h> 37 #include <sys/crypto/sched_impl.h> 38 39 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f) 40 #define CRYPTO_MAC_OFFSET(f) offsetof(crypto_mac_ops_t, f) 41 42 /* 43 * Message authentication codes routines. 44 */ 45 46 /* 47 * The following are the possible returned values common to all the routines 48 * below. The applicability of some of these return values depends on the 49 * presence of the arguments. 50 * 51 * CRYPTO_SUCCESS: The operation completed successfully. 52 * CRYPTO_QUEUED: A request was submitted successfully. The callback 53 * routine will be called when the operation is done. 54 * CRYPTO_INVALID_MECH_NUMBER, CRYPTO_INVALID_MECH_PARAM, or 55 * CRYPTO_INVALID_MECH for problems with the 'mech'. 56 * CRYPTO_INVALID_DATA for bogus 'data' 57 * CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work. 58 * CRYPTO_INVALID_CONTEXT: Not a valid context. 59 * CRYPTO_BUSY: Cannot process the request now. Schedule a 60 * crypto_bufcall(), or try later. 61 * CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED: No provider is 62 * capable of a function or a mechanism. 63 * CRYPTO_INVALID_KEY: bogus 'key' argument. 64 * CRYPTO_INVALID_MAC: bogus 'mac' argument. 65 */ 66 67 /* 68 * crypto_mac_prov() 69 * 70 * Arguments: 71 * mech: crypto_mechanism_t pointer. 72 * mech_type is a valid value previously returned by 73 * crypto_mech2id(); 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 * data: The message to compute the MAC for. 78 * mac: Storage for the MAC. The length needed depends on the mechanism. 79 * tmpl: a crypto_ctx_template_t, opaque template of a context of a 80 * MAC with the 'mech' using 'key'. 'tmpl' is created by 81 * a previous call to crypto_create_ctx_template(). 82 * cr: crypto_call_req_t calling conditions and call back info. 83 * 84 * Description: 85 * Asynchronously submits a request for, or synchronously performs a 86 * single-part message authentication of 'data' with the mechanism 87 * 'mech', using * the key 'key', on the specified provider with 88 * the specified session id. 89 * When complete and successful, 'mac' will contain the message 90 * authentication code. 91 * 92 * Context: 93 * Process or interrupt, according to the semantics dictated by the 'crq'. 94 * 95 * Returns: 96 * See comment in the beginning of the file. 97 */ 98 int 99 crypto_mac_prov(crypto_provider_t provider, crypto_session_id_t sid, 100 crypto_mechanism_t *mech, crypto_data_t *data, crypto_key_t *key, 101 crypto_ctx_template_t tmpl, crypto_data_t *mac, crypto_call_req_t *crq) 102 { 103 kcf_req_params_t params; 104 kcf_provider_desc_t *pd = provider; 105 kcf_provider_desc_t *real_provider = pd; 106 int rv; 107 108 ASSERT(KCF_PROV_REFHELD(pd)); 109 110 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 111 rv = kcf_get_hardware_provider(mech->cm_type, 112 CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(mac_ops), 113 CRYPTO_MAC_OFFSET(mac_atomic), 114 CHECK_RESTRICT(crq), pd, &real_provider); 115 116 if (rv != CRYPTO_SUCCESS) 117 return (rv); 118 } 119 120 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, key, 121 data, mac, tmpl); 122 rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); 123 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 124 KCF_PROV_REFRELE(real_provider); 125 126 return (rv); 127 } 128 129 /* 130 * Same as crypto_mac_prov(), but relies on the KCF scheduler to choose 131 * a provider. See crypto_mac() comments for more information. 132 */ 133 int 134 crypto_mac(crypto_mechanism_t *mech, crypto_data_t *data, 135 crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac, 136 crypto_call_req_t *crq) 137 { 138 int error; 139 kcf_mech_entry_t *me; 140 kcf_req_params_t params; 141 kcf_provider_desc_t *pd; 142 kcf_ctx_template_t *ctx_tmpl; 143 crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 144 kcf_prov_tried_t *list = NULL; 145 146 retry: 147 /* The pd is returned held */ 148 if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 149 list, CRYPTO_FG_MAC_ATOMIC, CHECK_RESTRICT(crq), 150 data->cd_length)) == NULL) { 151 if (list != NULL) 152 kcf_free_triedlist(list); 153 return (error); 154 } 155 156 /* 157 * For SW providers, check the validity of the context template 158 * It is very rare that the generation number mis-matches, so 159 * is acceptable to fail here, and let the consumer recover by 160 * freeing this tmpl and create a new one for the key and new SW 161 * provider 162 */ 163 if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 164 ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 165 if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 166 if (list != NULL) 167 kcf_free_triedlist(list); 168 KCF_PROV_REFRELE(pd); 169 return (CRYPTO_OLD_CTX_TEMPLATE); 170 } else { 171 spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 172 } 173 } 174 175 /* The fast path for SW providers. */ 176 if (CHECK_FASTPATH(crq, pd)) { 177 crypto_mechanism_t lmech; 178 179 lmech = *mech; 180 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 181 182 error = KCF_PROV_MAC_ATOMIC(pd, pd->pd_sid, &lmech, key, data, 183 mac, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 184 KCF_PROV_INCRSTATS(pd, error); 185 } else { 186 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, pd->pd_sid, 187 mech, key, data, mac, spi_ctx_tmpl); 188 189 error = kcf_submit_request(pd, NULL, crq, ¶ms, 190 KCF_ISDUALREQ(crq)); 191 } 192 193 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 194 IS_RECOVERABLE(error)) { 195 /* Add pd to the linked list of providers tried. */ 196 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 197 goto retry; 198 } 199 200 if (list != NULL) 201 kcf_free_triedlist(list); 202 203 KCF_PROV_REFRELE(pd); 204 return (error); 205 } 206 207 /* 208 * Single part operation to compute the MAC corresponding to the specified 209 * 'data' and to verify that it matches the MAC specified by 'mac'. 210 * The other arguments are the same as the function crypto_mac_prov(). 211 */ 212 int 213 crypto_mac_verify_prov(crypto_provider_t provider, crypto_session_id_t sid, 214 crypto_mechanism_t *mech, crypto_data_t *data, crypto_key_t *key, 215 crypto_ctx_template_t tmpl, crypto_data_t *mac, crypto_call_req_t *crq) 216 { 217 kcf_req_params_t params; 218 kcf_provider_desc_t *pd = provider; 219 kcf_provider_desc_t *real_provider = pd; 220 int rv; 221 222 ASSERT(KCF_PROV_REFHELD(pd)); 223 224 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 225 rv = kcf_get_hardware_provider(mech->cm_type, 226 CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(mac_ops), 227 CRYPTO_MAC_OFFSET(mac_verify_atomic), 228 CHECK_RESTRICT(crq), pd, &real_provider); 229 230 if (rv != CRYPTO_SUCCESS) 231 return (rv); 232 } 233 234 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_MAC_VERIFY_ATOMIC, sid, mech, 235 key, data, mac, tmpl); 236 rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); 237 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 238 KCF_PROV_REFRELE(real_provider); 239 240 return (rv); 241 } 242 243 /* 244 * Same as crypto_mac_verify_prov(), but relies on the KCF scheduler to choose 245 * a provider. See crypto_mac_verify_prov() comments for more information. 246 */ 247 int 248 crypto_mac_verify(crypto_mechanism_t *mech, crypto_data_t *data, 249 crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac, 250 crypto_call_req_t *crq) 251 { 252 int error; 253 kcf_mech_entry_t *me; 254 kcf_req_params_t params; 255 kcf_provider_desc_t *pd; 256 kcf_ctx_template_t *ctx_tmpl; 257 crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 258 kcf_prov_tried_t *list = NULL; 259 260 retry: 261 /* The pd is returned held */ 262 if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 263 list, CRYPTO_FG_MAC_ATOMIC, CHECK_RESTRICT(crq), 264 data->cd_length)) == NULL) { 265 if (list != NULL) 266 kcf_free_triedlist(list); 267 return (error); 268 } 269 270 /* 271 * For SW providers, check the validity of the context template 272 * It is very rare that the generation number mis-matches, so 273 * is acceptable to fail here, and let the consumer recover by 274 * freeing this tmpl and create a new one for the key and new SW 275 * provider 276 */ 277 if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 278 ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 279 if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 280 if (list != NULL) 281 kcf_free_triedlist(list); 282 KCF_PROV_REFRELE(pd); 283 return (CRYPTO_OLD_CTX_TEMPLATE); 284 } else { 285 spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 286 } 287 } 288 289 /* The fast path for SW providers. */ 290 if (CHECK_FASTPATH(crq, pd)) { 291 crypto_mechanism_t lmech; 292 293 lmech = *mech; 294 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 295 296 error = KCF_PROV_MAC_VERIFY_ATOMIC(pd, pd->pd_sid, &lmech, key, 297 data, mac, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 298 KCF_PROV_INCRSTATS(pd, error); 299 } else { 300 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_MAC_VERIFY_ATOMIC, 301 pd->pd_sid, mech, key, data, mac, spi_ctx_tmpl); 302 303 error = kcf_submit_request(pd, NULL, crq, ¶ms, 304 KCF_ISDUALREQ(crq)); 305 } 306 307 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 308 IS_RECOVERABLE(error)) { 309 /* Add pd to the linked list of providers tried. */ 310 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 311 goto retry; 312 } 313 314 if (list != NULL) 315 kcf_free_triedlist(list); 316 317 KCF_PROV_REFRELE(pd); 318 return (error); 319 } 320 321 322 /* 323 * crypto_mac_init_prov() 324 * 325 * Arguments: 326 * pd: pointer to the descriptor of the provider to use for this 327 * operation. 328 * sid: provider session id. 329 * mech: crypto_mechanism_t pointer. 330 * mech_type is a valid value previously returned by 331 * crypto_mech2id(); 332 * When the mech's parameter is not NULL, its definition depends 333 * on the standard definition of the mechanism. 334 * key: pointer to a crypto_key_t structure. 335 * tmpl: a crypto_ctx_template_t, opaque template of a context of a 336 * MAC with the 'mech' using 'key'. 'tmpl' is created by 337 * a previous call to crypto_create_ctx_template(). 338 * ctxp: Pointer to a crypto_context_t. 339 * cr: crypto_call_req_t calling conditions and call back info. 340 * 341 * Description: 342 * Asynchronously submits a request for, or synchronously performs the 343 * initialization of a MAC operation on the specified provider with 344 * the specified session. 345 * When possible and applicable, will internally use the pre-computed MAC 346 * context from the context template, tmpl. 347 * When complete and successful, 'ctxp' will contain a crypto_context_t 348 * valid for later calls to mac_update() and mac_final(). 349 * The caller should hold a reference on the specified provider 350 * descriptor before calling this function. 351 * 352 * Context: 353 * Process or interrupt, according to the semantics dictated by the 'cr'. 354 * 355 * Returns: 356 * See comment in the beginning of the file. 357 */ 358 int 359 crypto_mac_init_prov(crypto_provider_t provider, crypto_session_id_t sid, 360 crypto_mechanism_t *mech, crypto_key_t *key, crypto_spi_ctx_template_t tmpl, 361 crypto_context_t *ctxp, crypto_call_req_t *crq) 362 { 363 int rv; 364 crypto_ctx_t *ctx; 365 kcf_req_params_t params; 366 kcf_provider_desc_t *pd = provider; 367 kcf_provider_desc_t *real_provider = pd; 368 369 ASSERT(KCF_PROV_REFHELD(pd)); 370 371 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 372 rv = kcf_get_hardware_provider(mech->cm_type, 373 CRYPTO_MECH_INVALID, CRYPTO_OPS_OFFSET(mac_ops), 374 CRYPTO_MAC_OFFSET(mac_init), 375 CHECK_RESTRICT(crq), pd, &real_provider); 376 377 if (rv != CRYPTO_SUCCESS) 378 return (rv); 379 } 380 381 /* Allocate and initialize the canonical context */ 382 if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) { 383 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 384 KCF_PROV_REFRELE(real_provider); 385 return (CRYPTO_HOST_MEMORY); 386 } 387 388 /* The fast path for SW providers. */ 389 if (CHECK_FASTPATH(crq, pd)) { 390 crypto_mechanism_t lmech; 391 392 lmech = *mech; 393 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech); 394 rv = KCF_PROV_MAC_INIT(real_provider, ctx, &lmech, key, tmpl, 395 KCF_SWFP_RHNDL(crq)); 396 KCF_PROV_INCRSTATS(pd, rv); 397 } else { 398 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, mech, key, 399 NULL, NULL, tmpl); 400 rv = kcf_submit_request(real_provider, ctx, crq, ¶ms, 401 B_FALSE); 402 } 403 404 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 405 KCF_PROV_REFRELE(real_provider); 406 407 if ((rv == CRYPTO_SUCCESS) || (rv == CRYPTO_QUEUED)) 408 *ctxp = (crypto_context_t)ctx; 409 else { 410 /* Release the hold done in kcf_new_ctx(). */ 411 KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 412 } 413 414 return (rv); 415 } 416 417 /* 418 * Same as crypto_mac_init_prov(), but relies on the KCF scheduler to 419 * choose a provider. See crypto_mac_init_prov() comments for more 420 * information. 421 */ 422 int 423 crypto_mac_init(crypto_mechanism_t *mech, crypto_key_t *key, 424 crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 425 crypto_call_req_t *crq) 426 { 427 int error; 428 kcf_mech_entry_t *me; 429 kcf_provider_desc_t *pd; 430 kcf_ctx_template_t *ctx_tmpl; 431 crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 432 kcf_prov_tried_t *list = NULL; 433 434 retry: 435 /* The pd is returned held */ 436 if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 437 list, CRYPTO_FG_MAC, CHECK_RESTRICT(crq), 0)) == NULL) { 438 if (list != NULL) 439 kcf_free_triedlist(list); 440 return (error); 441 } 442 443 /* 444 * For SW providers, check the validity of the context template 445 * It is very rare that the generation number mis-matches, so 446 * is acceptable to fail here, and let the consumer recover by 447 * freeing this tmpl and create a new one for the key and new SW 448 * provider 449 */ 450 451 if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 452 ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 453 if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 454 if (list != NULL) 455 kcf_free_triedlist(list); 456 KCF_PROV_REFRELE(pd); 457 return (CRYPTO_OLD_CTX_TEMPLATE); 458 } else { 459 spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 460 } 461 } 462 463 error = crypto_mac_init_prov(pd, pd->pd_sid, mech, key, spi_ctx_tmpl, 464 ctxp, crq); 465 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 466 IS_RECOVERABLE(error)) { 467 /* Add pd to the linked list of providers tried. */ 468 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 469 goto retry; 470 } 471 472 if (list != NULL) 473 kcf_free_triedlist(list); 474 475 KCF_PROV_REFRELE(pd); 476 return (error); 477 } 478 479 /* 480 * crypto_mac_update() 481 * 482 * Arguments: 483 * context: A crypto_context_t initialized by mac_init(). 484 * data: The message part to be MAC'ed 485 * cr: crypto_call_req_t calling conditions and call back info. 486 * 487 * Description: 488 * Asynchronously submits a request for, or synchronously performs a 489 * part of a MAC operation. 490 * 491 * Context: 492 * Process or interrupt, according to the semantics dictated by the 'cr'. 493 * 494 * Returns: 495 * See comment in the beginning of the file. 496 */ 497 int 498 crypto_mac_update(crypto_context_t context, crypto_data_t *data, 499 crypto_call_req_t *cr) 500 { 501 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 502 kcf_context_t *kcf_ctx; 503 kcf_provider_desc_t *pd; 504 kcf_req_params_t params; 505 int rv; 506 507 if ((ctx == NULL) || 508 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 509 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 510 return (CRYPTO_INVALID_CONTEXT); 511 } 512 513 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 514 KCF_PROV_REFHOLD(pd); 515 516 /* The fast path for SW providers. */ 517 if (CHECK_FASTPATH(cr, pd)) { 518 rv = KCF_PROV_MAC_UPDATE(pd, ctx, data, NULL); 519 KCF_PROV_INCRSTATS(pd, rv); 520 } else { 521 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_UPDATE, 522 ctx->cc_session, NULL, NULL, data, NULL, NULL); 523 rv = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 524 } 525 526 KCF_PROV_REFRELE(pd); 527 return (rv); 528 } 529 530 /* 531 * crypto_mac_final() 532 * 533 * Arguments: 534 * context: A crypto_context_t initialized by mac_init(). 535 * mac: Storage for the message authentication code. 536 * cr: crypto_call_req_t calling conditions and call back info. 537 * 538 * Description: 539 * Asynchronously submits a request for, or synchronously performs a 540 * part of a message authentication operation. 541 * 542 * Context: 543 * Process or interrupt, according to the semantics dictated by the 'cr'. 544 * 545 * Returns: 546 * See comment in the beginning of the file. 547 */ 548 int 549 crypto_mac_final(crypto_context_t context, crypto_data_t *mac, 550 crypto_call_req_t *cr) 551 { 552 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 553 kcf_context_t *kcf_ctx; 554 kcf_provider_desc_t *pd; 555 kcf_req_params_t params; 556 int rv; 557 558 if ((ctx == NULL) || 559 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 560 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 561 return (CRYPTO_INVALID_CONTEXT); 562 } 563 564 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 565 KCF_PROV_REFHOLD(pd); 566 567 /* The fast path for SW providers. */ 568 if (CHECK_FASTPATH(cr, pd)) { 569 rv = KCF_PROV_MAC_FINAL(pd, ctx, mac, NULL); 570 KCF_PROV_INCRSTATS(pd, rv); 571 } else { 572 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_FINAL, 573 ctx->cc_session, NULL, NULL, NULL, mac, NULL); 574 rv = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 575 } 576 577 KCF_PROV_REFRELE(pd); 578 /* Release the hold done in kcf_new_ctx() during init step. */ 579 KCF_CONTEXT_COND_RELEASE(rv, kcf_ctx); 580 return (rv); 581 } 582 583 /* 584 * See comments for crypto_mac_update() and crypto_mac_final(). 585 */ 586 int 587 crypto_mac_single(crypto_context_t context, crypto_data_t *data, 588 crypto_data_t *mac, crypto_call_req_t *cr) 589 { 590 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 591 kcf_context_t *kcf_ctx; 592 kcf_provider_desc_t *pd; 593 int error; 594 kcf_req_params_t params; 595 596 597 if ((ctx == NULL) || 598 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 599 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 600 return (CRYPTO_INVALID_CONTEXT); 601 } 602 603 KCF_PROV_REFHOLD(pd); 604 605 /* The fast path for SW providers. */ 606 if (CHECK_FASTPATH(cr, pd)) { 607 error = KCF_PROV_MAC(pd, ctx, data, mac, NULL); 608 KCF_PROV_INCRSTATS(pd, error); 609 } else { 610 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 611 NULL, NULL, data, mac, NULL); 612 error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 613 } 614 615 KCF_PROV_REFRELE(pd); 616 /* Release the hold done in kcf_new_ctx() during init step. */ 617 KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 618 return (error); 619 } 620