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