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 if (pd->pd_prov_type == CRYPTO_HW_PROVIDER && 185 (pd->pd_flags & CRYPTO_HASH_NO_UPDATE) && 186 (data->cd_length > pd->pd_hash_limit)) { 187 /* 188 * XXX - We need a check to see if this is indeed 189 * a HMAC. So far, all kernel clients use 190 * this interface only for HMAC. So, this is fine 191 * for now. 192 */ 193 error = CRYPTO_BUFFER_TOO_BIG; 194 } else { 195 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, 196 pd->pd_sid, mech, key, data, mac, spi_ctx_tmpl); 197 198 error = kcf_submit_request(pd, NULL, crq, ¶ms, 199 KCF_ISDUALREQ(crq)); 200 } 201 } 202 203 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 204 IS_RECOVERABLE(error)) { 205 /* Add pd to the linked list of providers tried. */ 206 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 207 goto retry; 208 } 209 210 if (list != NULL) 211 kcf_free_triedlist(list); 212 213 KCF_PROV_REFRELE(pd); 214 return (error); 215 } 216 217 /* 218 * Single part operation to compute the MAC corresponding to the specified 219 * 'data' and to verify that it matches the MAC specified by 'mac'. 220 * The other arguments are the same as the function crypto_mac_prov(). 221 */ 222 int 223 crypto_mac_verify_prov(crypto_provider_t provider, crypto_session_id_t sid, 224 crypto_mechanism_t *mech, crypto_data_t *data, crypto_key_t *key, 225 crypto_ctx_template_t tmpl, crypto_data_t *mac, crypto_call_req_t *crq) 226 { 227 kcf_req_params_t params; 228 kcf_provider_desc_t *pd = provider; 229 kcf_provider_desc_t *real_provider = pd; 230 int rv; 231 232 ASSERT(KCF_PROV_REFHELD(pd)); 233 234 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 235 rv = kcf_get_hardware_provider(mech->cm_type, 236 CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 237 &real_provider, CRYPTO_FG_MAC_ATOMIC); 238 239 if (rv != CRYPTO_SUCCESS) 240 return (rv); 241 } 242 243 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_MAC_VERIFY_ATOMIC, sid, mech, 244 key, data, mac, tmpl); 245 rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE); 246 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 247 KCF_PROV_REFRELE(real_provider); 248 249 return (rv); 250 } 251 252 /* 253 * Same as crypto_mac_verify_prov(), but relies on the KCF scheduler to choose 254 * a provider. See crypto_mac_verify_prov() comments for more information. 255 */ 256 int 257 crypto_mac_verify(crypto_mechanism_t *mech, crypto_data_t *data, 258 crypto_key_t *key, crypto_ctx_template_t tmpl, crypto_data_t *mac, 259 crypto_call_req_t *crq) 260 { 261 int error; 262 kcf_mech_entry_t *me; 263 kcf_req_params_t params; 264 kcf_provider_desc_t *pd; 265 kcf_ctx_template_t *ctx_tmpl; 266 crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 267 kcf_prov_tried_t *list = NULL; 268 269 retry: 270 /* The pd is returned held */ 271 if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 272 list, CRYPTO_FG_MAC_ATOMIC, CHECK_RESTRICT(crq), 273 data->cd_length)) == NULL) { 274 if (list != NULL) 275 kcf_free_triedlist(list); 276 return (error); 277 } 278 279 /* 280 * For SW providers, check the validity of the context template 281 * It is very rare that the generation number mis-matches, so 282 * is acceptable to fail here, and let the consumer recover by 283 * freeing this tmpl and create a new one for the key and new SW 284 * provider 285 */ 286 if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 287 ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 288 if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 289 if (list != NULL) 290 kcf_free_triedlist(list); 291 KCF_PROV_REFRELE(pd); 292 return (CRYPTO_OLD_CTX_TEMPLATE); 293 } else { 294 spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 295 } 296 } 297 298 /* The fast path for SW providers. */ 299 if (CHECK_FASTPATH(crq, pd)) { 300 crypto_mechanism_t lmech; 301 302 lmech = *mech; 303 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech); 304 305 error = KCF_PROV_MAC_VERIFY_ATOMIC(pd, pd->pd_sid, &lmech, key, 306 data, mac, spi_ctx_tmpl, KCF_SWFP_RHNDL(crq)); 307 KCF_PROV_INCRSTATS(pd, error); 308 } else { 309 if (pd->pd_prov_type == CRYPTO_HW_PROVIDER && 310 (pd->pd_flags & CRYPTO_HASH_NO_UPDATE) && 311 (data->cd_length > pd->pd_hash_limit)) { 312 /* see comments in crypto_mac() */ 313 error = CRYPTO_BUFFER_TOO_BIG; 314 } else { 315 KCF_WRAP_MAC_OPS_PARAMS(¶ms, 316 KCF_OP_MAC_VERIFY_ATOMIC, pd->pd_sid, mech, 317 key, data, mac, spi_ctx_tmpl); 318 319 error = kcf_submit_request(pd, NULL, crq, ¶ms, 320 KCF_ISDUALREQ(crq)); 321 } 322 } 323 324 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 325 IS_RECOVERABLE(error)) { 326 /* Add pd to the linked list of providers tried. */ 327 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 328 goto retry; 329 } 330 331 if (list != NULL) 332 kcf_free_triedlist(list); 333 334 KCF_PROV_REFRELE(pd); 335 return (error); 336 } 337 338 339 /* 340 * crypto_mac_init_prov() 341 * 342 * Arguments: 343 * pd: pointer to the descriptor of the provider to use for this 344 * operation. 345 * sid: provider session id. 346 * mech: crypto_mechanism_t pointer. 347 * mech_type is a valid value previously returned by 348 * crypto_mech2id(); 349 * When the mech's parameter is not NULL, its definition depends 350 * on the standard definition of the mechanism. 351 * key: pointer to a crypto_key_t structure. 352 * tmpl: a crypto_ctx_template_t, opaque template of a context of a 353 * MAC with the 'mech' using 'key'. 'tmpl' is created by 354 * a previous call to crypto_create_ctx_template(). 355 * ctxp: Pointer to a crypto_context_t. 356 * cr: crypto_call_req_t calling conditions and call back info. 357 * 358 * Description: 359 * Asynchronously submits a request for, or synchronously performs the 360 * initialization of a MAC operation on the specified provider with 361 * the specified session. 362 * When possible and applicable, will internally use the pre-computed MAC 363 * context from the context template, tmpl. 364 * When complete and successful, 'ctxp' will contain a crypto_context_t 365 * valid for later calls to mac_update() and mac_final(). 366 * The caller should hold a reference on the specified provider 367 * descriptor before calling this function. 368 * 369 * Context: 370 * Process or interrupt, according to the semantics dictated by the 'cr'. 371 * 372 * Returns: 373 * See comment in the beginning of the file. 374 */ 375 int 376 crypto_mac_init_prov(crypto_provider_t provider, crypto_session_id_t sid, 377 crypto_mechanism_t *mech, crypto_key_t *key, crypto_spi_ctx_template_t tmpl, 378 crypto_context_t *ctxp, crypto_call_req_t *crq) 379 { 380 int rv; 381 crypto_ctx_t *ctx; 382 kcf_req_params_t params; 383 kcf_provider_desc_t *pd = provider; 384 kcf_provider_desc_t *real_provider = pd; 385 386 ASSERT(KCF_PROV_REFHELD(pd)); 387 388 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { 389 rv = kcf_get_hardware_provider(mech->cm_type, 390 CRYPTO_MECH_INVALID, CHECK_RESTRICT(crq), pd, 391 &real_provider, CRYPTO_FG_MAC); 392 393 if (rv != CRYPTO_SUCCESS) 394 return (rv); 395 } 396 397 /* Allocate and initialize the canonical context */ 398 if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) { 399 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 400 KCF_PROV_REFRELE(real_provider); 401 return (CRYPTO_HOST_MEMORY); 402 } 403 404 /* The fast path for SW providers. */ 405 if (CHECK_FASTPATH(crq, pd)) { 406 crypto_mechanism_t lmech; 407 408 lmech = *mech; 409 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech); 410 rv = KCF_PROV_MAC_INIT(real_provider, ctx, &lmech, key, tmpl, 411 KCF_SWFP_RHNDL(crq)); 412 KCF_PROV_INCRSTATS(pd, rv); 413 } else { 414 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_INIT, sid, mech, key, 415 NULL, NULL, tmpl); 416 rv = kcf_submit_request(real_provider, ctx, crq, ¶ms, 417 B_FALSE); 418 } 419 420 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) 421 KCF_PROV_REFRELE(real_provider); 422 423 if ((rv == CRYPTO_SUCCESS) || (rv == CRYPTO_QUEUED)) 424 *ctxp = (crypto_context_t)ctx; 425 else { 426 /* Release the hold done in kcf_new_ctx(). */ 427 KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private); 428 } 429 430 return (rv); 431 } 432 433 /* 434 * Same as crypto_mac_init_prov(), but relies on the KCF scheduler to 435 * choose a provider. See crypto_mac_init_prov() comments for more 436 * information. 437 */ 438 int 439 crypto_mac_init(crypto_mechanism_t *mech, crypto_key_t *key, 440 crypto_ctx_template_t tmpl, crypto_context_t *ctxp, 441 crypto_call_req_t *crq) 442 { 443 int error; 444 kcf_mech_entry_t *me; 445 kcf_provider_desc_t *pd; 446 kcf_ctx_template_t *ctx_tmpl; 447 crypto_spi_ctx_template_t spi_ctx_tmpl = NULL; 448 kcf_prov_tried_t *list = NULL; 449 450 retry: 451 /* The pd is returned held */ 452 if ((pd = kcf_get_mech_provider(mech->cm_type, &me, &error, 453 list, CRYPTO_FG_MAC, CHECK_RESTRICT(crq), 0)) == NULL) { 454 if (list != NULL) 455 kcf_free_triedlist(list); 456 return (error); 457 } 458 459 /* 460 * For SW providers, check the validity of the context template 461 * It is very rare that the generation number mis-matches, so 462 * is acceptable to fail here, and let the consumer recover by 463 * freeing this tmpl and create a new one for the key and new SW 464 * provider 465 */ 466 467 if ((pd->pd_prov_type == CRYPTO_SW_PROVIDER) && 468 ((ctx_tmpl = (kcf_ctx_template_t *)tmpl) != NULL)) { 469 if (ctx_tmpl->ct_generation != me->me_gen_swprov) { 470 if (list != NULL) 471 kcf_free_triedlist(list); 472 KCF_PROV_REFRELE(pd); 473 return (CRYPTO_OLD_CTX_TEMPLATE); 474 } else { 475 spi_ctx_tmpl = ctx_tmpl->ct_prov_tmpl; 476 } 477 } 478 479 if (pd->pd_prov_type == CRYPTO_HW_PROVIDER && 480 (pd->pd_flags & CRYPTO_HASH_NO_UPDATE)) { 481 /* 482 * The hardware provider has limited HMAC support. 483 * So, we fallback early here to using a software provider. 484 * 485 * XXX - need to enhance to do the fallback later in 486 * crypto_mac_update() if the size of accumulated input data 487 * exceeds the maximum size digestable by hardware provider. 488 */ 489 error = CRYPTO_BUFFER_TOO_BIG; 490 } else { 491 error = crypto_mac_init_prov(pd, pd->pd_sid, mech, key, 492 spi_ctx_tmpl, ctxp, crq); 493 } 494 if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED && 495 IS_RECOVERABLE(error)) { 496 /* Add pd to the linked list of providers tried. */ 497 if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL) 498 goto retry; 499 } 500 501 if (list != NULL) 502 kcf_free_triedlist(list); 503 504 KCF_PROV_REFRELE(pd); 505 return (error); 506 } 507 508 /* 509 * crypto_mac_update() 510 * 511 * Arguments: 512 * context: A crypto_context_t initialized by mac_init(). 513 * data: The message part to be MAC'ed 514 * cr: crypto_call_req_t calling conditions and call back info. 515 * 516 * Description: 517 * Asynchronously submits a request for, or synchronously performs a 518 * part of a MAC operation. 519 * 520 * Context: 521 * Process or interrupt, according to the semantics dictated by the 'cr'. 522 * 523 * Returns: 524 * See comment in the beginning of the file. 525 */ 526 int 527 crypto_mac_update(crypto_context_t context, crypto_data_t *data, 528 crypto_call_req_t *cr) 529 { 530 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 531 kcf_context_t *kcf_ctx; 532 kcf_provider_desc_t *pd; 533 kcf_req_params_t params; 534 int rv; 535 536 if ((ctx == NULL) || 537 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 538 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 539 return (CRYPTO_INVALID_CONTEXT); 540 } 541 542 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 543 544 /* The fast path for SW providers. */ 545 if (CHECK_FASTPATH(cr, pd)) { 546 rv = KCF_PROV_MAC_UPDATE(pd, ctx, data, NULL); 547 KCF_PROV_INCRSTATS(pd, rv); 548 } else { 549 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_UPDATE, 550 ctx->cc_session, NULL, NULL, data, NULL, NULL); 551 rv = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 552 } 553 554 return (rv); 555 } 556 557 /* 558 * crypto_mac_final() 559 * 560 * Arguments: 561 * context: A crypto_context_t initialized by mac_init(). 562 * mac: Storage for the message authentication code. 563 * cr: crypto_call_req_t calling conditions and call back info. 564 * 565 * Description: 566 * Asynchronously submits a request for, or synchronously performs a 567 * part of a message authentication operation. 568 * 569 * Context: 570 * Process or interrupt, according to the semantics dictated by the 'cr'. 571 * 572 * Returns: 573 * See comment in the beginning of the file. 574 */ 575 int 576 crypto_mac_final(crypto_context_t context, crypto_data_t *mac, 577 crypto_call_req_t *cr) 578 { 579 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 580 kcf_context_t *kcf_ctx; 581 kcf_provider_desc_t *pd; 582 kcf_req_params_t params; 583 int rv; 584 585 if ((ctx == NULL) || 586 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 587 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 588 return (CRYPTO_INVALID_CONTEXT); 589 } 590 591 ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER); 592 593 /* The fast path for SW providers. */ 594 if (CHECK_FASTPATH(cr, pd)) { 595 rv = KCF_PROV_MAC_FINAL(pd, ctx, mac, NULL); 596 KCF_PROV_INCRSTATS(pd, rv); 597 } else { 598 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_FINAL, 599 ctx->cc_session, NULL, NULL, NULL, mac, NULL); 600 rv = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 601 } 602 603 /* Release the hold done in kcf_new_ctx() during init step. */ 604 KCF_CONTEXT_COND_RELEASE(rv, kcf_ctx); 605 return (rv); 606 } 607 608 /* 609 * See comments for crypto_mac_update() and crypto_mac_final(). 610 */ 611 int 612 crypto_mac_single(crypto_context_t context, crypto_data_t *data, 613 crypto_data_t *mac, crypto_call_req_t *cr) 614 { 615 crypto_ctx_t *ctx = (crypto_ctx_t *)context; 616 kcf_context_t *kcf_ctx; 617 kcf_provider_desc_t *pd; 618 int error; 619 kcf_req_params_t params; 620 621 622 if ((ctx == NULL) || 623 ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) || 624 ((pd = kcf_ctx->kc_prov_desc) == NULL)) { 625 return (CRYPTO_INVALID_CONTEXT); 626 } 627 628 629 /* The fast path for SW providers. */ 630 if (CHECK_FASTPATH(cr, pd)) { 631 error = KCF_PROV_MAC(pd, ctx, data, mac, NULL); 632 KCF_PROV_INCRSTATS(pd, error); 633 } else { 634 KCF_WRAP_MAC_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid, 635 NULL, NULL, data, mac, NULL); 636 error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE); 637 } 638 639 /* Release the hold done in kcf_new_ctx() during init step. */ 640 KCF_CONTEXT_COND_RELEASE(error, kcf_ctx); 641 return (error); 642 } 643