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