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://opensource.org/licenses/CDDL-1.0. 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 /* 23 * Copyright 2013 Saso Kiselkov. All rights reserved. 24 */ 25 26 #include <sys/modctl.h> 27 #include <sys/crypto/common.h> 28 #include <sys/crypto/spi.h> 29 #include <sys/strsun.h> 30 #include <sys/sysmacros.h> 31 #include <sys/systm.h> 32 #define SKEIN_MODULE_IMPL 33 #include <sys/skein.h> 34 35 /* 36 * Like the sha2 module, we create the skein module with two modlinkages: 37 * - modlmisc to allow direct calls to Skein_* API functions. 38 * - modlcrypto to integrate well into the Kernel Crypto Framework (KCF). 39 */ 40 static struct modlmisc modlmisc = { 41 &mod_miscops, 42 "Skein Message-Digest Algorithm" 43 }; 44 45 static struct modlcrypto modlcrypto = { 46 &mod_cryptoops, 47 "Skein Kernel SW Provider" 48 }; 49 50 static struct modlinkage modlinkage = { 51 MODREV_1, &modlmisc, &modlcrypto, NULL 52 }; 53 54 static crypto_mech_info_t skein_mech_info_tab[] = { 55 {CKM_SKEIN_256, SKEIN_256_MECH_INFO_TYPE, 56 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 57 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 58 {CKM_SKEIN_256_MAC, SKEIN_256_MAC_MECH_INFO_TYPE, 59 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX, 60 CRYPTO_KEYSIZE_UNIT_IN_BYTES}, 61 {CKM_SKEIN_512, SKEIN_512_MECH_INFO_TYPE, 62 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 63 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 64 {CKM_SKEIN_512_MAC, SKEIN_512_MAC_MECH_INFO_TYPE, 65 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX, 66 CRYPTO_KEYSIZE_UNIT_IN_BYTES}, 67 {CKM_SKEIN1024, SKEIN1024_MECH_INFO_TYPE, 68 CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC, 69 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS}, 70 {CKM_SKEIN1024_MAC, SKEIN1024_MAC_MECH_INFO_TYPE, 71 CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC, 1, INT_MAX, 72 CRYPTO_KEYSIZE_UNIT_IN_BYTES} 73 }; 74 75 static void skein_provider_status(crypto_provider_handle_t, uint_t *); 76 77 static crypto_control_ops_t skein_control_ops = { 78 skein_provider_status 79 }; 80 81 static int skein_digest_init(crypto_ctx_t *, crypto_mechanism_t *, 82 crypto_req_handle_t); 83 static int skein_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *, 84 crypto_req_handle_t); 85 static int skein_update(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 86 static int skein_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t); 87 static int skein_digest_atomic(crypto_provider_handle_t, crypto_session_id_t, 88 crypto_mechanism_t *, crypto_data_t *, crypto_data_t *, 89 crypto_req_handle_t); 90 91 static crypto_digest_ops_t skein_digest_ops = { 92 skein_digest_init, 93 skein_digest, 94 skein_update, 95 NULL, 96 skein_final, 97 skein_digest_atomic 98 }; 99 100 static int skein_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 101 crypto_spi_ctx_template_t, crypto_req_handle_t); 102 static int skein_mac_atomic(crypto_provider_handle_t, crypto_session_id_t, 103 crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *, 104 crypto_spi_ctx_template_t, crypto_req_handle_t); 105 106 static crypto_mac_ops_t skein_mac_ops = { 107 skein_mac_init, 108 NULL, 109 skein_update, /* using regular digest update is OK here */ 110 skein_final, /* using regular digest final is OK here */ 111 skein_mac_atomic, 112 NULL 113 }; 114 115 static int skein_create_ctx_template(crypto_provider_handle_t, 116 crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *, 117 size_t *, crypto_req_handle_t); 118 static int skein_free_context(crypto_ctx_t *); 119 120 static crypto_ctx_ops_t skein_ctx_ops = { 121 skein_create_ctx_template, 122 skein_free_context 123 }; 124 125 static crypto_ops_t skein_crypto_ops = { 126 &skein_control_ops, 127 &skein_digest_ops, 128 NULL, 129 &skein_mac_ops, 130 NULL, 131 NULL, 132 NULL, 133 NULL, 134 NULL, 135 NULL, 136 NULL, 137 NULL, 138 NULL, 139 &skein_ctx_ops, 140 NULL, 141 NULL, 142 NULL 143 }; 144 145 static crypto_provider_info_t skein_prov_info = { 146 CRYPTO_SPI_VERSION_4, 147 "Skein Software Provider", 148 CRYPTO_SW_PROVIDER, 149 {&modlinkage}, 150 NULL, 151 &skein_crypto_ops, 152 sizeof (skein_mech_info_tab) / sizeof (crypto_mech_info_t), 153 skein_mech_info_tab 154 }; 155 156 static crypto_kcf_provider_handle_t skein_prov_handle = 0; 157 158 typedef struct skein_ctx { 159 skein_mech_type_t sc_mech_type; 160 size_t sc_digest_bitlen; 161 union { 162 Skein_256_Ctxt_t sc_256; 163 Skein_512_Ctxt_t sc_512; 164 Skein1024_Ctxt_t sc_1024; 165 } sc_u; 166 } skein_ctx_t; 167 #define SKEIN_CTX(_ctx_) ((skein_ctx_t *)((_ctx_)->cc_provider_private)) 168 #define SKEIN_CTX_LVALUE(_ctx_) (_ctx_)->cc_provider_private 169 #define SKEIN_OP(_skein_ctx, _op, ...) \ 170 do { \ 171 skein_ctx_t *sc = (_skein_ctx); \ 172 switch (sc->sc_mech_type) { \ 173 case SKEIN_256_MECH_INFO_TYPE: \ 174 case SKEIN_256_MAC_MECH_INFO_TYPE: \ 175 (void) Skein_256_ ## _op(&sc->sc_u.sc_256, \ 176 __VA_ARGS__); \ 177 break; \ 178 case SKEIN_512_MECH_INFO_TYPE: \ 179 case SKEIN_512_MAC_MECH_INFO_TYPE: \ 180 (void) Skein_512_ ## _op(&sc->sc_u.sc_512, \ 181 __VA_ARGS__); \ 182 break; \ 183 case SKEIN1024_MECH_INFO_TYPE: \ 184 case SKEIN1024_MAC_MECH_INFO_TYPE: \ 185 (void) Skein1024_ ## _op(&sc->sc_u.sc_1024, \ 186 __VA_ARGS__); \ 187 break; \ 188 } \ 189 _NOTE(CONSTCOND) \ 190 } while (0) 191 192 static int 193 skein_get_digest_bitlen(const crypto_mechanism_t *mechanism, size_t *result) 194 { 195 if (mechanism->cm_param != NULL) { 196 /*LINTED(E_BAD_PTR_CAST_ALIGN)*/ 197 skein_param_t *param = (skein_param_t *)mechanism->cm_param; 198 199 if (mechanism->cm_param_len != sizeof (*param) || 200 param->sp_digest_bitlen == 0) { 201 return (CRYPTO_MECHANISM_PARAM_INVALID); 202 } 203 *result = param->sp_digest_bitlen; 204 } else { 205 switch (mechanism->cm_type) { 206 case SKEIN_256_MECH_INFO_TYPE: 207 *result = 256; 208 break; 209 case SKEIN_512_MECH_INFO_TYPE: 210 *result = 512; 211 break; 212 case SKEIN1024_MECH_INFO_TYPE: 213 *result = 1024; 214 break; 215 default: 216 return (CRYPTO_MECHANISM_INVALID); 217 } 218 } 219 return (CRYPTO_SUCCESS); 220 } 221 222 int 223 _init(void) 224 { 225 int error; 226 227 if ((error = mod_install(&modlinkage)) != 0) 228 return (error); 229 230 /* 231 * Try to register with KCF - failure shouldn't unload us, since we 232 * still may want to continue providing misc/skein functionality. 233 */ 234 (void) crypto_register_provider(&skein_prov_info, &skein_prov_handle); 235 236 return (0); 237 } 238 239 int 240 _info(struct modinfo *modinfop) 241 { 242 return (mod_info(&modlinkage, modinfop)); 243 } 244 245 /* 246 * KCF software provider control entry points. 247 */ 248 /* ARGSUSED */ 249 static void 250 skein_provider_status(crypto_provider_handle_t provider, uint_t *status) 251 { 252 *status = CRYPTO_PROVIDER_READY; 253 } 254 255 /* 256 * General Skein hashing helper functions. 257 */ 258 259 /* 260 * Performs an Update on a context with uio input data. 261 */ 262 static int 263 skein_digest_update_uio(skein_ctx_t *ctx, const crypto_data_t *data) 264 { 265 off_t offset = data->cd_offset; 266 size_t length = data->cd_length; 267 uint_t vec_idx; 268 size_t cur_len; 269 const uio_t *uio = data->cd_uio; 270 271 /* we support only kernel buffer */ 272 if (uio->uio_segflg != UIO_SYSSPACE) 273 return (CRYPTO_ARGUMENTS_BAD); 274 275 /* 276 * Jump to the first iovec containing data to be 277 * digested. 278 */ 279 for (vec_idx = 0; vec_idx < uio->uio_iovcnt && 280 offset >= uio->uio_iov[vec_idx].iov_len; 281 offset -= uio->uio_iov[vec_idx++].iov_len) 282 ; 283 if (vec_idx == uio->uio_iovcnt) { 284 /* 285 * The caller specified an offset that is larger than the 286 * total size of the buffers it provided. 287 */ 288 return (CRYPTO_DATA_LEN_RANGE); 289 } 290 291 /* 292 * Now do the digesting on the iovecs. 293 */ 294 while (vec_idx < uio->uio_iovcnt && length > 0) { 295 cur_len = MIN(uio->uio_iov[vec_idx].iov_len - offset, length); 296 SKEIN_OP(ctx, Update, (uint8_t *)uio->uio_iov[vec_idx].iov_base 297 + offset, cur_len); 298 length -= cur_len; 299 vec_idx++; 300 offset = 0; 301 } 302 303 if (vec_idx == uio->uio_iovcnt && length > 0) { 304 /* 305 * The end of the specified iovec's was reached but 306 * the length requested could not be processed, i.e. 307 * The caller requested to digest more data than it provided. 308 */ 309 return (CRYPTO_DATA_LEN_RANGE); 310 } 311 312 return (CRYPTO_SUCCESS); 313 } 314 315 /* 316 * Performs a Final on a context and writes to a uio digest output. 317 */ 318 static int 319 skein_digest_final_uio(skein_ctx_t *ctx, crypto_data_t *digest, 320 crypto_req_handle_t req) 321 { 322 off_t offset = digest->cd_offset; 323 uint_t vec_idx; 324 uio_t *uio = digest->cd_uio; 325 326 /* we support only kernel buffer */ 327 if (uio->uio_segflg != UIO_SYSSPACE) 328 return (CRYPTO_ARGUMENTS_BAD); 329 330 /* 331 * Jump to the first iovec containing ptr to the digest to be returned. 332 */ 333 for (vec_idx = 0; offset >= uio->uio_iov[vec_idx].iov_len && 334 vec_idx < uio->uio_iovcnt; 335 offset -= uio->uio_iov[vec_idx++].iov_len) 336 ; 337 if (vec_idx == uio->uio_iovcnt) { 338 /* 339 * The caller specified an offset that is larger than the 340 * total size of the buffers it provided. 341 */ 342 return (CRYPTO_DATA_LEN_RANGE); 343 } 344 if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <= 345 uio->uio_iov[vec_idx].iov_len) { 346 /* The computed digest will fit in the current iovec. */ 347 SKEIN_OP(ctx, Final, 348 (uchar_t *)uio->uio_iov[vec_idx].iov_base + offset); 349 } else { 350 uint8_t *digest_tmp; 351 off_t scratch_offset = 0; 352 size_t length = CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen); 353 size_t cur_len; 354 355 digest_tmp = kmem_alloc(CRYPTO_BITS2BYTES( 356 ctx->sc_digest_bitlen), crypto_kmflag(req)); 357 if (digest_tmp == NULL) 358 return (CRYPTO_HOST_MEMORY); 359 SKEIN_OP(ctx, Final, digest_tmp); 360 while (vec_idx < uio->uio_iovcnt && length > 0) { 361 cur_len = MIN(uio->uio_iov[vec_idx].iov_len - offset, 362 length); 363 bcopy(digest_tmp + scratch_offset, 364 uio->uio_iov[vec_idx].iov_base + offset, cur_len); 365 366 length -= cur_len; 367 vec_idx++; 368 scratch_offset += cur_len; 369 offset = 0; 370 } 371 kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen)); 372 373 if (vec_idx == uio->uio_iovcnt && length > 0) { 374 /* 375 * The end of the specified iovec's was reached but 376 * the length requested could not be processed, i.e. 377 * The caller requested to digest more data than it 378 * provided. 379 */ 380 return (CRYPTO_DATA_LEN_RANGE); 381 } 382 } 383 384 return (CRYPTO_SUCCESS); 385 } 386 387 /* 388 * Performs an Update on a context with mblk input data. 389 */ 390 static int 391 skein_digest_update_mblk(skein_ctx_t *ctx, crypto_data_t *data) 392 { 393 off_t offset = data->cd_offset; 394 size_t length = data->cd_length; 395 mblk_t *mp; 396 size_t cur_len; 397 398 /* Jump to the first mblk_t containing data to be digested. */ 399 for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); 400 offset -= MBLKL(mp), mp = mp->b_cont) 401 ; 402 if (mp == NULL) { 403 /* 404 * The caller specified an offset that is larger than the 405 * total size of the buffers it provided. 406 */ 407 return (CRYPTO_DATA_LEN_RANGE); 408 } 409 410 /* Now do the digesting on the mblk chain. */ 411 while (mp != NULL && length > 0) { 412 cur_len = MIN(MBLKL(mp) - offset, length); 413 SKEIN_OP(ctx, Update, mp->b_rptr + offset, cur_len); 414 length -= cur_len; 415 offset = 0; 416 mp = mp->b_cont; 417 } 418 419 if (mp == NULL && length > 0) { 420 /* 421 * The end of the mblk was reached but the length requested 422 * could not be processed, i.e. The caller requested 423 * to digest more data than it provided. 424 */ 425 return (CRYPTO_DATA_LEN_RANGE); 426 } 427 428 return (CRYPTO_SUCCESS); 429 } 430 431 /* 432 * Performs a Final on a context and writes to an mblk digest output. 433 */ 434 static int 435 skein_digest_final_mblk(skein_ctx_t *ctx, crypto_data_t *digest, 436 crypto_req_handle_t req) 437 { 438 off_t offset = digest->cd_offset; 439 mblk_t *mp; 440 441 /* Jump to the first mblk_t that will be used to store the digest. */ 442 for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp); 443 offset -= MBLKL(mp), mp = mp->b_cont) 444 ; 445 if (mp == NULL) { 446 /* caller specified offset is too large */ 447 return (CRYPTO_DATA_LEN_RANGE); 448 } 449 450 if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <= MBLKL(mp)) { 451 /* The digest will fit in the current mblk. */ 452 SKEIN_OP(ctx, Final, mp->b_rptr + offset); 453 } else { 454 /* Split the digest up between the individual buffers. */ 455 uint8_t *digest_tmp; 456 off_t scratch_offset = 0; 457 size_t length = CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen); 458 size_t cur_len; 459 460 digest_tmp = kmem_alloc(CRYPTO_BITS2BYTES( 461 ctx->sc_digest_bitlen), crypto_kmflag(req)); 462 if (digest_tmp == NULL) 463 return (CRYPTO_HOST_MEMORY); 464 SKEIN_OP(ctx, Final, digest_tmp); 465 while (mp != NULL && length > 0) { 466 cur_len = MIN(MBLKL(mp) - offset, length); 467 bcopy(digest_tmp + scratch_offset, 468 mp->b_rptr + offset, cur_len); 469 length -= cur_len; 470 mp = mp->b_cont; 471 scratch_offset += cur_len; 472 offset = 0; 473 } 474 kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen)); 475 if (mp == NULL && length > 0) { 476 /* digest too long to fit in the mblk buffers */ 477 return (CRYPTO_DATA_LEN_RANGE); 478 } 479 } 480 481 return (CRYPTO_SUCCESS); 482 } 483 484 /* 485 * KCF software provider digest entry points. 486 */ 487 488 /* 489 * Initializes a skein digest context to the configuration in `mechanism'. 490 * The mechanism cm_type must be one of SKEIN_*_MECH_INFO_TYPE. The cm_param 491 * field may contain a skein_param_t structure indicating the length of the 492 * digest the algorithm should produce. Otherwise the default output lengths 493 * are applied (32 bytes for Skein-256, 64 bytes for Skein-512 and 128 bytes 494 * for Skein-1024). 495 */ 496 static int 497 skein_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 498 crypto_req_handle_t req) 499 { 500 int error = CRYPTO_SUCCESS; 501 502 if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type)) 503 return (CRYPTO_MECHANISM_INVALID); 504 505 SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), 506 crypto_kmflag(req)); 507 if (SKEIN_CTX(ctx) == NULL) 508 return (CRYPTO_HOST_MEMORY); 509 510 SKEIN_CTX(ctx)->sc_mech_type = mechanism->cm_type; 511 error = skein_get_digest_bitlen(mechanism, 512 &SKEIN_CTX(ctx)->sc_digest_bitlen); 513 if (error != CRYPTO_SUCCESS) 514 goto errout; 515 SKEIN_OP(SKEIN_CTX(ctx), Init, SKEIN_CTX(ctx)->sc_digest_bitlen); 516 517 return (CRYPTO_SUCCESS); 518 errout: 519 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 520 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 521 SKEIN_CTX_LVALUE(ctx) = NULL; 522 return (error); 523 } 524 525 /* 526 * Executes a skein_update and skein_digest on a pre-initialized crypto 527 * context in a single step. See the documentation to these functions to 528 * see what to pass here. 529 */ 530 static int 531 skein_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, 532 crypto_req_handle_t req) 533 { 534 int error = CRYPTO_SUCCESS; 535 536 ASSERT(SKEIN_CTX(ctx) != NULL); 537 538 if (digest->cd_length < 539 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) { 540 digest->cd_length = 541 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); 542 return (CRYPTO_BUFFER_TOO_SMALL); 543 } 544 545 error = skein_update(ctx, data, req); 546 if (error != CRYPTO_SUCCESS) { 547 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 548 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 549 SKEIN_CTX_LVALUE(ctx) = NULL; 550 digest->cd_length = 0; 551 return (error); 552 } 553 error = skein_final(ctx, digest, req); 554 555 return (error); 556 } 557 558 /* 559 * Performs a skein Update with the input message in `data' (successive calls 560 * can push more data). This is used both for digest and MAC operation. 561 * Supported input data formats are raw, uio and mblk. 562 */ 563 /*ARGSUSED*/ 564 static int 565 skein_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) 566 { 567 int error = CRYPTO_SUCCESS; 568 569 ASSERT(SKEIN_CTX(ctx) != NULL); 570 571 switch (data->cd_format) { 572 case CRYPTO_DATA_RAW: 573 SKEIN_OP(SKEIN_CTX(ctx), Update, 574 (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 575 data->cd_length); 576 break; 577 case CRYPTO_DATA_UIO: 578 error = skein_digest_update_uio(SKEIN_CTX(ctx), data); 579 break; 580 case CRYPTO_DATA_MBLK: 581 error = skein_digest_update_mblk(SKEIN_CTX(ctx), data); 582 break; 583 default: 584 error = CRYPTO_ARGUMENTS_BAD; 585 } 586 587 return (error); 588 } 589 590 /* 591 * Performs a skein Final, writing the output to `digest'. This is used both 592 * for digest and MAC operation. 593 * Supported output digest formats are raw, uio and mblk. 594 */ 595 /*ARGSUSED*/ 596 static int 597 skein_final(crypto_ctx_t *ctx, crypto_data_t *digest, crypto_req_handle_t req) 598 { 599 int error = CRYPTO_SUCCESS; 600 601 ASSERT(SKEIN_CTX(ctx) != NULL); 602 603 if (digest->cd_length < 604 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) { 605 digest->cd_length = 606 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); 607 return (CRYPTO_BUFFER_TOO_SMALL); 608 } 609 610 switch (digest->cd_format) { 611 case CRYPTO_DATA_RAW: 612 SKEIN_OP(SKEIN_CTX(ctx), Final, 613 (uint8_t *)digest->cd_raw.iov_base + digest->cd_offset); 614 break; 615 case CRYPTO_DATA_UIO: 616 error = skein_digest_final_uio(SKEIN_CTX(ctx), digest, req); 617 break; 618 case CRYPTO_DATA_MBLK: 619 error = skein_digest_final_mblk(SKEIN_CTX(ctx), digest, req); 620 break; 621 default: 622 error = CRYPTO_ARGUMENTS_BAD; 623 } 624 625 if (error == CRYPTO_SUCCESS) 626 digest->cd_length = 627 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); 628 else 629 digest->cd_length = 0; 630 631 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 632 kmem_free(SKEIN_CTX(ctx), sizeof (*(SKEIN_CTX(ctx)))); 633 SKEIN_CTX_LVALUE(ctx) = NULL; 634 635 return (error); 636 } 637 638 /* 639 * Performs a full skein digest computation in a single call, configuring the 640 * algorithm according to `mechanism', reading the input to be digested from 641 * `data' and writing the output to `digest'. 642 * Supported input/output formats are raw, uio and mblk. 643 */ 644 /*ARGSUSED*/ 645 static int 646 skein_digest_atomic(crypto_provider_handle_t provider, 647 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 648 crypto_data_t *data, crypto_data_t *digest, crypto_req_handle_t req) 649 { 650 int error; 651 skein_ctx_t skein_ctx; 652 crypto_ctx_t ctx; 653 SKEIN_CTX_LVALUE(&ctx) = &skein_ctx; 654 655 /* Init */ 656 if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type)) 657 return (CRYPTO_MECHANISM_INVALID); 658 skein_ctx.sc_mech_type = mechanism->cm_type; 659 error = skein_get_digest_bitlen(mechanism, &skein_ctx.sc_digest_bitlen); 660 if (error != CRYPTO_SUCCESS) 661 goto out; 662 SKEIN_OP(&skein_ctx, Init, skein_ctx.sc_digest_bitlen); 663 664 if ((error = skein_update(&ctx, data, digest)) != CRYPTO_SUCCESS) 665 goto out; 666 if ((error = skein_final(&ctx, data, digest)) != CRYPTO_SUCCESS) 667 goto out; 668 669 out: 670 if (error == CRYPTO_SUCCESS) 671 digest->cd_length = 672 CRYPTO_BITS2BYTES(skein_ctx.sc_digest_bitlen); 673 else 674 digest->cd_length = 0; 675 bzero(&skein_ctx, sizeof (skein_ctx)); 676 677 return (error); 678 } 679 680 /* 681 * Helper function that builds a Skein MAC context from the provided 682 * mechanism and key. 683 */ 684 static int 685 skein_mac_ctx_build(skein_ctx_t *ctx, crypto_mechanism_t *mechanism, 686 crypto_key_t *key) 687 { 688 int error; 689 690 if (!VALID_SKEIN_MAC_MECH(mechanism->cm_type)) 691 return (CRYPTO_MECHANISM_INVALID); 692 if (key->ck_format != CRYPTO_KEY_RAW) 693 return (CRYPTO_ARGUMENTS_BAD); 694 ctx->sc_mech_type = mechanism->cm_type; 695 error = skein_get_digest_bitlen(mechanism, &ctx->sc_digest_bitlen); 696 if (error != CRYPTO_SUCCESS) 697 return (error); 698 SKEIN_OP(ctx, InitExt, ctx->sc_digest_bitlen, 0, key->ck_data, 699 CRYPTO_BITS2BYTES(key->ck_length)); 700 701 return (CRYPTO_SUCCESS); 702 } 703 704 /* 705 * KCF software provide mac entry points. 706 */ 707 /* 708 * Initializes a skein MAC context. You may pass a ctx_template, in which 709 * case the template will be reused to make initialization more efficient. 710 * Otherwise a new context will be constructed. The mechanism cm_type must 711 * be one of SKEIN_*_MAC_MECH_INFO_TYPE. Same as in skein_digest_init, you 712 * may pass a skein_param_t in cm_param to configure the length of the 713 * digest. The key must be in raw format. 714 */ 715 static int 716 skein_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 717 crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 718 crypto_req_handle_t req) 719 { 720 int error; 721 722 SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), 723 crypto_kmflag(req)); 724 if (SKEIN_CTX(ctx) == NULL) 725 return (CRYPTO_HOST_MEMORY); 726 727 if (ctx_template != NULL) { 728 bcopy(ctx_template, SKEIN_CTX(ctx), 729 sizeof (*SKEIN_CTX(ctx))); 730 } else { 731 error = skein_mac_ctx_build(SKEIN_CTX(ctx), mechanism, key); 732 if (error != CRYPTO_SUCCESS) 733 goto errout; 734 } 735 736 return (CRYPTO_SUCCESS); 737 errout: 738 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 739 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 740 return (error); 741 } 742 743 /* 744 * The MAC update and final calls are reused from the regular digest code. 745 */ 746 747 /*ARGSUSED*/ 748 /* 749 * Same as skein_digest_atomic, performs an atomic Skein MAC operation in 750 * one step. All the same properties apply to the arguments of this 751 * function as to those of the partial operations above. 752 */ 753 static int 754 skein_mac_atomic(crypto_provider_handle_t provider, 755 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 756 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 757 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 758 { 759 /* faux crypto context just for skein_digest_{update,final} */ 760 int error; 761 crypto_ctx_t ctx; 762 skein_ctx_t skein_ctx; 763 SKEIN_CTX_LVALUE(&ctx) = &skein_ctx; 764 765 if (ctx_template != NULL) { 766 bcopy(ctx_template, &skein_ctx, sizeof (skein_ctx)); 767 } else { 768 error = skein_mac_ctx_build(&skein_ctx, mechanism, key); 769 if (error != CRYPTO_SUCCESS) 770 goto errout; 771 } 772 773 if ((error = skein_update(&ctx, data, req)) != CRYPTO_SUCCESS) 774 goto errout; 775 if ((error = skein_final(&ctx, mac, req)) != CRYPTO_SUCCESS) 776 goto errout; 777 778 return (CRYPTO_SUCCESS); 779 errout: 780 bzero(&skein_ctx, sizeof (skein_ctx)); 781 return (error); 782 } 783 784 /* 785 * KCF software provider context management entry points. 786 */ 787 788 /* 789 * Constructs a context template for the Skein MAC algorithm. The same 790 * properties apply to the arguments of this function as to those of 791 * skein_mac_init. 792 */ 793 /*ARGSUSED*/ 794 static int 795 skein_create_ctx_template(crypto_provider_handle_t provider, 796 crypto_mechanism_t *mechanism, crypto_key_t *key, 797 crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size, 798 crypto_req_handle_t req) 799 { 800 int error; 801 skein_ctx_t *ctx_tmpl; 802 803 ctx_tmpl = kmem_alloc(sizeof (*ctx_tmpl), crypto_kmflag(req)); 804 if (ctx_tmpl == NULL) 805 return (CRYPTO_HOST_MEMORY); 806 error = skein_mac_ctx_build(ctx_tmpl, mechanism, key); 807 if (error != CRYPTO_SUCCESS) 808 goto errout; 809 *ctx_template = ctx_tmpl; 810 *ctx_template_size = sizeof (*ctx_tmpl); 811 812 return (CRYPTO_SUCCESS); 813 errout: 814 bzero(ctx_tmpl, sizeof (*ctx_tmpl)); 815 kmem_free(ctx_tmpl, sizeof (*ctx_tmpl)); 816 return (error); 817 } 818 819 /* 820 * Frees a skein context in a parent crypto context. 821 */ 822 static int 823 skein_free_context(crypto_ctx_t *ctx) 824 { 825 if (SKEIN_CTX(ctx) != NULL) { 826 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 827 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 828 SKEIN_CTX_LVALUE(ctx) = NULL; 829 } 830 831 return (CRYPTO_SUCCESS); 832 }