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