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