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 { 319 off_t offset = digest->cd_offset; 320 uint_t vec_idx; 321 uio_t *uio = digest->cd_uio; 322 323 /* we support only kernel buffer */ 324 if (uio->uio_segflg != UIO_SYSSPACE) 325 return (CRYPTO_ARGUMENTS_BAD); 326 327 /* 328 * Jump to the first iovec containing ptr to the digest to be returned. 329 */ 330 for (vec_idx = 0; offset >= uio->uio_iov[vec_idx].iov_len && 331 vec_idx < uio->uio_iovcnt; 332 offset -= uio->uio_iov[vec_idx++].iov_len) 333 ; 334 if (vec_idx == uio->uio_iovcnt) { 335 /* 336 * The caller specified an offset that is larger than the 337 * total size of the buffers it provided. 338 */ 339 return (CRYPTO_DATA_LEN_RANGE); 340 } 341 if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <= 342 uio->uio_iov[vec_idx].iov_len) { 343 /* The computed digest will fit in the current iovec. */ 344 SKEIN_OP(ctx, Final, 345 (uchar_t *)uio->uio_iov[vec_idx].iov_base + offset); 346 } else { 347 uint8_t *digest_tmp; 348 off_t scratch_offset = 0; 349 size_t length = CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen); 350 size_t cur_len; 351 352 digest_tmp = kmem_alloc(CRYPTO_BITS2BYTES( 353 ctx->sc_digest_bitlen), KM_NOSLEEP); 354 if (digest_tmp == NULL) 355 return (CRYPTO_HOST_MEMORY); 356 SKEIN_OP(ctx, Final, digest_tmp); 357 while (vec_idx < uio->uio_iovcnt && length > 0) { 358 cur_len = MIN(uio->uio_iov[vec_idx].iov_len - offset, 359 length); 360 bcopy(digest_tmp + scratch_offset, 361 uio->uio_iov[vec_idx].iov_base + offset, cur_len); 362 363 length -= cur_len; 364 vec_idx++; 365 scratch_offset += cur_len; 366 offset = 0; 367 } 368 kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen)); 369 370 if (vec_idx == uio->uio_iovcnt && length > 0) { 371 /* 372 * The end of the specified iovec's was reached but 373 * the length requested could not be processed, i.e. 374 * The caller requested to digest more data than it 375 * provided. 376 */ 377 return (CRYPTO_DATA_LEN_RANGE); 378 } 379 } 380 381 return (CRYPTO_SUCCESS); 382 } 383 384 /* 385 * Performs an Update on a context with mblk input data. 386 */ 387 static int 388 skein_digest_update_mblk(skein_ctx_t *ctx, crypto_data_t *data) 389 { 390 off_t offset = data->cd_offset; 391 size_t length = data->cd_length; 392 mblk_t *mp; 393 size_t cur_len; 394 395 /* Jump to the first mblk_t containing data to be digested. */ 396 for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp); 397 offset -= MBLKL(mp), mp = mp->b_cont) 398 ; 399 if (mp == NULL) { 400 /* 401 * The caller specified an offset that is larger than the 402 * total size of the buffers it provided. 403 */ 404 return (CRYPTO_DATA_LEN_RANGE); 405 } 406 407 /* Now do the digesting on the mblk chain. */ 408 while (mp != NULL && length > 0) { 409 cur_len = MIN(MBLKL(mp) - offset, length); 410 SKEIN_OP(ctx, Update, mp->b_rptr + offset, cur_len); 411 length -= cur_len; 412 offset = 0; 413 mp = mp->b_cont; 414 } 415 416 if (mp == NULL && length > 0) { 417 /* 418 * The end of the mblk was reached but the length requested 419 * could not be processed, i.e. The caller requested 420 * to digest more data than it provided. 421 */ 422 return (CRYPTO_DATA_LEN_RANGE); 423 } 424 425 return (CRYPTO_SUCCESS); 426 } 427 428 /* 429 * Performs a Final on a context and writes to an mblk digest output. 430 */ 431 static int 432 skein_digest_final_mblk(skein_ctx_t *ctx, crypto_data_t *digest) 433 { 434 off_t offset = digest->cd_offset; 435 mblk_t *mp; 436 437 /* Jump to the first mblk_t that will be used to store the digest. */ 438 for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp); 439 offset -= MBLKL(mp), mp = mp->b_cont) 440 ; 441 if (mp == NULL) { 442 /* caller specified offset is too large */ 443 return (CRYPTO_DATA_LEN_RANGE); 444 } 445 446 if (offset + CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen) <= MBLKL(mp)) { 447 /* The digest will fit in the current mblk. */ 448 SKEIN_OP(ctx, Final, mp->b_rptr + offset); 449 } else { 450 /* Split the digest up between the individual buffers. */ 451 uint8_t *digest_tmp; 452 off_t scratch_offset = 0; 453 size_t length = CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen); 454 size_t cur_len; 455 456 digest_tmp = kmem_alloc(CRYPTO_BITS2BYTES( 457 ctx->sc_digest_bitlen), KM_NOSLEEP); 458 if (digest_tmp == NULL) 459 return (CRYPTO_HOST_MEMORY); 460 SKEIN_OP(ctx, Final, digest_tmp); 461 while (mp != NULL && length > 0) { 462 cur_len = MIN(MBLKL(mp) - offset, length); 463 bcopy(digest_tmp + scratch_offset, 464 mp->b_rptr + offset, cur_len); 465 length -= cur_len; 466 mp = mp->b_cont; 467 scratch_offset += cur_len; 468 offset = 0; 469 } 470 kmem_free(digest_tmp, CRYPTO_BITS2BYTES(ctx->sc_digest_bitlen)); 471 if (mp == NULL && length > 0) { 472 /* digest too long to fit in the mblk buffers */ 473 return (CRYPTO_DATA_LEN_RANGE); 474 } 475 } 476 477 return (CRYPTO_SUCCESS); 478 } 479 480 /* 481 * KCF software provider digest entry points. 482 */ 483 484 /* 485 * Initializes a skein digest context to the configuration in `mechanism'. 486 * The mechanism cm_type must be one of SKEIN_*_MECH_INFO_TYPE. The cm_param 487 * field may contain a skein_param_t structure indicating the length of the 488 * digest the algorithm should produce. Otherwise the default output lengths 489 * are applied (32 bytes for Skein-256, 64 bytes for Skein-512 and 128 bytes 490 * for Skein-1024). 491 */ 492 static int 493 skein_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 494 crypto_req_handle_t req) 495 { 496 int error = CRYPTO_SUCCESS; 497 498 if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type)) 499 return (CRYPTO_MECHANISM_INVALID); 500 501 SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), 502 crypto_kmflag(req)); 503 if (SKEIN_CTX(ctx) == NULL) 504 return (CRYPTO_HOST_MEMORY); 505 506 SKEIN_CTX(ctx)->sc_mech_type = mechanism->cm_type; 507 error = skein_get_digest_bitlen(mechanism, 508 &SKEIN_CTX(ctx)->sc_digest_bitlen); 509 if (error != CRYPTO_SUCCESS) 510 goto errout; 511 SKEIN_OP(SKEIN_CTX(ctx), Init, SKEIN_CTX(ctx)->sc_digest_bitlen); 512 513 return (CRYPTO_SUCCESS); 514 errout: 515 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 516 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 517 SKEIN_CTX_LVALUE(ctx) = NULL; 518 return (error); 519 } 520 521 /* 522 * Executes a skein_update and skein_digest on a pre-initialized crypto 523 * context in a single step. See the documentation to these functions to 524 * see what to pass here. 525 */ 526 static int 527 skein_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest, 528 crypto_req_handle_t req) 529 { 530 int error = CRYPTO_SUCCESS; 531 532 ASSERT(SKEIN_CTX(ctx) != NULL); 533 534 if (digest->cd_length < 535 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) { 536 digest->cd_length = 537 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); 538 return (CRYPTO_BUFFER_TOO_SMALL); 539 } 540 541 error = skein_update(ctx, data, req); 542 if (error != CRYPTO_SUCCESS) { 543 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 544 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 545 SKEIN_CTX_LVALUE(ctx) = NULL; 546 digest->cd_length = 0; 547 return (error); 548 } 549 error = skein_final(ctx, digest, req); 550 551 return (error); 552 } 553 554 /* 555 * Performs a skein Update with the input message in `data' (successive calls 556 * can push more data). This is used both for digest and MAC operation. 557 * Supported input data formats are raw, uio and mblk. 558 */ 559 /*ARGSUSED*/ 560 static int 561 skein_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req) 562 { 563 int error = CRYPTO_SUCCESS; 564 565 ASSERT(SKEIN_CTX(ctx) != NULL); 566 567 switch (data->cd_format) { 568 case CRYPTO_DATA_RAW: 569 SKEIN_OP(SKEIN_CTX(ctx), Update, 570 (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 571 data->cd_length); 572 break; 573 case CRYPTO_DATA_UIO: 574 error = skein_digest_update_uio(SKEIN_CTX(ctx), data); 575 break; 576 case CRYPTO_DATA_MBLK: 577 error = skein_digest_update_mblk(SKEIN_CTX(ctx), data); 578 break; 579 default: 580 error = CRYPTO_ARGUMENTS_BAD; 581 } 582 583 return (error); 584 } 585 586 /* 587 * Performs a skein Final, writing the output to `digest'. This is used both 588 * for digest and MAC operation. 589 * Supported output digest formats are raw, uio and mblk. 590 */ 591 /*ARGSUSED*/ 592 static int 593 skein_final(crypto_ctx_t *ctx, crypto_data_t *digest, crypto_req_handle_t req) 594 { 595 int error = CRYPTO_SUCCESS; 596 597 ASSERT(SKEIN_CTX(ctx) != NULL); 598 599 if (digest->cd_length < 600 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen)) { 601 digest->cd_length = 602 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); 603 return (CRYPTO_BUFFER_TOO_SMALL); 604 } 605 606 switch (digest->cd_format) { 607 case CRYPTO_DATA_RAW: 608 SKEIN_OP(SKEIN_CTX(ctx), Final, 609 (uint8_t *)digest->cd_raw.iov_base + digest->cd_offset); 610 break; 611 case CRYPTO_DATA_UIO: 612 error = skein_digest_final_uio(SKEIN_CTX(ctx), digest); 613 break; 614 case CRYPTO_DATA_MBLK: 615 error = skein_digest_final_mblk(SKEIN_CTX(ctx), digest); 616 break; 617 default: 618 error = CRYPTO_ARGUMENTS_BAD; 619 } 620 621 if (error == CRYPTO_SUCCESS) 622 digest->cd_length = 623 CRYPTO_BITS2BYTES(SKEIN_CTX(ctx)->sc_digest_bitlen); 624 else 625 digest->cd_length = 0; 626 627 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 628 kmem_free(SKEIN_CTX(ctx), sizeof (*(SKEIN_CTX(ctx)))); 629 SKEIN_CTX_LVALUE(ctx) = NULL; 630 631 return (error); 632 } 633 634 /* 635 * Performs a full skein digest computation in a single call, configuring the 636 * algorithm according to `mechanism', reading the input to be digested from 637 * `data' and writing the output to `digest'. 638 * Supported input/output formats are raw, uio and mblk. 639 */ 640 /*ARGSUSED*/ 641 static int 642 skein_digest_atomic(crypto_provider_handle_t provider, 643 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 644 crypto_data_t *data, crypto_data_t *digest, crypto_req_handle_t req) 645 { 646 int error; 647 skein_ctx_t skein_ctx; 648 crypto_ctx_t ctx; 649 SKEIN_CTX_LVALUE(&ctx) = &skein_ctx; 650 651 /* Init */ 652 if (!VALID_SKEIN_DIGEST_MECH(mechanism->cm_type)) 653 return (CRYPTO_MECHANISM_INVALID); 654 skein_ctx.sc_mech_type = mechanism->cm_type; 655 error = skein_get_digest_bitlen(mechanism, &skein_ctx.sc_digest_bitlen); 656 if (error != CRYPTO_SUCCESS) 657 goto out; 658 SKEIN_OP(&skein_ctx, Init, skein_ctx.sc_digest_bitlen); 659 660 if ((error = skein_update(&ctx, data, digest)) != CRYPTO_SUCCESS) 661 goto out; 662 if ((error = skein_final(&ctx, data, digest)) != CRYPTO_SUCCESS) 663 goto out; 664 665 out: 666 if (error == CRYPTO_SUCCESS) 667 digest->cd_length = 668 CRYPTO_BITS2BYTES(skein_ctx.sc_digest_bitlen); 669 else 670 digest->cd_length = 0; 671 bzero(&skein_ctx, sizeof (skein_ctx)); 672 673 return (error); 674 } 675 676 /* 677 * Helper function that builds a Skein MAC context from the provided 678 * mechanism and key. 679 */ 680 static int 681 skein_mac_ctx_build(skein_ctx_t *ctx, crypto_mechanism_t *mechanism, 682 crypto_key_t *key) 683 { 684 int error; 685 686 if (!VALID_SKEIN_MAC_MECH(mechanism->cm_type)) 687 return (CRYPTO_MECHANISM_INVALID); 688 if (key->ck_format != CRYPTO_KEY_RAW) 689 return (CRYPTO_ARGUMENTS_BAD); 690 ctx->sc_mech_type = mechanism->cm_type; 691 error = skein_get_digest_bitlen(mechanism, &ctx->sc_digest_bitlen); 692 if (error != CRYPTO_SUCCESS) 693 return (error); 694 SKEIN_OP(ctx, InitExt, ctx->sc_digest_bitlen, 0, key->ck_data, 695 CRYPTO_BITS2BYTES(key->ck_length)); 696 697 return (CRYPTO_SUCCESS); 698 } 699 700 /* 701 * KCF software provide mac entry points. 702 */ 703 /* 704 * Initializes a skein MAC context. You may pass a ctx_template, in which 705 * case the template will be reused to make initialization more efficient. 706 * Otherwise a new context will be constructed. The mechanism cm_type must 707 * be one of SKEIN_*_MAC_MECH_INFO_TYPE. Same as in skein_digest_init, you 708 * may pass a skein_param_t in cm_param to configure the length of the 709 * digest. The key must be in raw format. 710 */ 711 static int 712 skein_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 713 crypto_key_t *key, crypto_spi_ctx_template_t ctx_template, 714 crypto_req_handle_t req) 715 { 716 int error; 717 718 SKEIN_CTX_LVALUE(ctx) = kmem_alloc(sizeof (*SKEIN_CTX(ctx)), 719 crypto_kmflag(req)); 720 if (SKEIN_CTX(ctx) == NULL) 721 return (CRYPTO_HOST_MEMORY); 722 723 if (ctx_template != NULL) { 724 bcopy(ctx_template, SKEIN_CTX(ctx), 725 sizeof (*SKEIN_CTX(ctx))); 726 } else { 727 error = skein_mac_ctx_build(SKEIN_CTX(ctx), mechanism, key); 728 if (error != CRYPTO_SUCCESS) 729 goto errout; 730 } 731 732 return (CRYPTO_SUCCESS); 733 errout: 734 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 735 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 736 return (error); 737 } 738 739 /* 740 * The MAC update and final calls are reused from the regular digest code. 741 */ 742 743 /*ARGSUSED*/ 744 /* 745 * Same as skein_digest_atomic, performs an atomic Skein MAC operation in 746 * one step. All the same properties apply to the arguments of this 747 * function as to those of the partial operations above. 748 */ 749 static int 750 skein_mac_atomic(crypto_provider_handle_t provider, 751 crypto_session_id_t session_id, crypto_mechanism_t *mechanism, 752 crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 753 crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req) 754 { 755 /* faux crypto context just for skein_digest_{update,final} */ 756 int error; 757 crypto_ctx_t ctx; 758 skein_ctx_t skein_ctx; 759 SKEIN_CTX_LVALUE(&ctx) = &skein_ctx; 760 761 if (ctx_template != NULL) { 762 bcopy(ctx_template, &skein_ctx, sizeof (skein_ctx)); 763 } else { 764 error = skein_mac_ctx_build(&skein_ctx, mechanism, key); 765 if (error != CRYPTO_SUCCESS) 766 goto errout; 767 } 768 769 if ((error = skein_update(&ctx, data, req)) != CRYPTO_SUCCESS) 770 goto errout; 771 if ((error = skein_final(&ctx, mac, req)) != CRYPTO_SUCCESS) 772 goto errout; 773 774 return (CRYPTO_SUCCESS); 775 errout: 776 bzero(&skein_ctx, sizeof (skein_ctx)); 777 return (error); 778 } 779 780 /* 781 * KCF software provider context management entry points. 782 */ 783 784 /* 785 * Constructs a context template for the Skein MAC algorithm. The same 786 * properties apply to the arguments of this function as to those of 787 * skein_mac_init. 788 */ 789 /*ARGSUSED*/ 790 static int 791 skein_create_ctx_template(crypto_provider_handle_t provider, 792 crypto_mechanism_t *mechanism, crypto_key_t *key, 793 crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size, 794 crypto_req_handle_t req) 795 { 796 int error; 797 skein_ctx_t *ctx_tmpl; 798 799 ctx_tmpl = kmem_alloc(sizeof (*ctx_tmpl), crypto_kmflag(req)); 800 if (ctx_tmpl == NULL) 801 return (CRYPTO_HOST_MEMORY); 802 error = skein_mac_ctx_build(ctx_tmpl, mechanism, key); 803 if (error != CRYPTO_SUCCESS) 804 goto errout; 805 *ctx_template = ctx_tmpl; 806 *ctx_template_size = sizeof (*ctx_tmpl); 807 808 return (CRYPTO_SUCCESS); 809 errout: 810 bzero(ctx_tmpl, sizeof (*ctx_tmpl)); 811 kmem_free(ctx_tmpl, sizeof (*ctx_tmpl)); 812 return (error); 813 } 814 815 /* 816 * Frees a skein context in a parent crypto context. 817 */ 818 static int 819 skein_free_context(crypto_ctx_t *ctx) 820 { 821 if (SKEIN_CTX(ctx) != NULL) { 822 bzero(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 823 kmem_free(SKEIN_CTX(ctx), sizeof (*SKEIN_CTX(ctx))); 824 SKEIN_CTX_LVALUE(ctx) = NULL; 825 } 826 827 return (CRYPTO_SUCCESS); 828 }