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 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 
  27 #include <sys/modctl.h>
  28 #include <sys/cmn_err.h>
  29 #include <sys/note.h>
  30 #include <sys/crypto/common.h>
  31 #include <sys/crypto/spi.h>
  32 #include <sys/strsun.h>
  33 #include <sys/systm.h>
  34 #include <sys/sysmacros.h>
  35 
  36 #include <sys/sha1.h>
  37 #include <sha1/sha1_impl.h>
  38 
  39 /*
  40  * The sha1 module is created with two modlinkages:
  41  * - a modlmisc that allows consumers to directly call the entry points
  42  *   SHA1Init, SHA1Update, and SHA1Final.
  43  * - a modlcrypto that allows the module to register with the Kernel
  44  *   Cryptographic Framework (KCF) as a software provider for the SHA1
  45  *   mechanisms.
  46  */
  47 
  48 static struct modlmisc modlmisc = {
  49         &mod_miscops,
  50         "SHA1 Message-Digest Algorithm"
  51 };
  52 
  53 static struct modlcrypto modlcrypto = {
  54         &mod_cryptoops,
  55         "SHA1 Kernel SW Provider 1.1"
  56 };
  57 
  58 static struct modlinkage modlinkage = {
  59         MODREV_1, { &modlmisc, &modlcrypto, NULL }
  60 };
  61 
  62 
  63 /*
  64  * Macros to access the SHA1 or SHA1-HMAC contexts from a context passed
  65  * by KCF to one of the entry points.
  66  */
  67 
  68 #define PROV_SHA1_CTX(ctx)      ((sha1_ctx_t *)(ctx)->cc_provider_private)
  69 #define PROV_SHA1_HMAC_CTX(ctx) ((sha1_hmac_ctx_t *)(ctx)->cc_provider_private)
  70 
  71 /* to extract the digest length passed as mechanism parameter */
  72 #define PROV_SHA1_GET_DIGEST_LEN(m, len) {                              \
  73         if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t)))           \
  74                 (len) = (uint32_t)*((ulong_t *)(void *)mechanism->cm_param); \
  75         else {                                                          \
  76                 ulong_t tmp_ulong;                                      \
  77                 bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t));      \
  78                 (len) = (uint32_t)tmp_ulong;                            \
  79         }                                                               \
  80 }
  81 
  82 #define PROV_SHA1_DIGEST_KEY(ctx, key, len, digest) {   \
  83         SHA1Init(ctx);                                  \
  84         SHA1Update(ctx, key, len);                      \
  85         SHA1Final(digest, ctx);                         \
  86 }
  87 
  88 /*
  89  * Mechanism info structure passed to KCF during registration.
  90  */
  91 static crypto_mech_info_t sha1_mech_info_tab[] = {
  92         /* SHA1 */
  93         {SUN_CKM_SHA1, SHA1_MECH_INFO_TYPE,
  94             CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
  95             0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
  96         /* SHA1-HMAC */
  97         {SUN_CKM_SHA1_HMAC, SHA1_HMAC_MECH_INFO_TYPE,
  98             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
  99             SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN,
 100             CRYPTO_KEYSIZE_UNIT_IN_BYTES},
 101         /* SHA1-HMAC GENERAL */
 102         {SUN_CKM_SHA1_HMAC_GENERAL, SHA1_HMAC_GEN_MECH_INFO_TYPE,
 103             CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
 104             SHA1_HMAC_MIN_KEY_LEN, SHA1_HMAC_MAX_KEY_LEN,
 105             CRYPTO_KEYSIZE_UNIT_IN_BYTES}
 106 };
 107 
 108 static void sha1_provider_status(crypto_provider_handle_t, uint_t *);
 109 
 110 static crypto_control_ops_t sha1_control_ops = {
 111         sha1_provider_status
 112 };
 113 
 114 static int sha1_digest_init(crypto_ctx_t *, crypto_mechanism_t *,
 115     crypto_req_handle_t);
 116 static int sha1_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
 117     crypto_req_handle_t);
 118 static int sha1_digest_update(crypto_ctx_t *, crypto_data_t *,
 119     crypto_req_handle_t);
 120 static int sha1_digest_final(crypto_ctx_t *, crypto_data_t *,
 121     crypto_req_handle_t);
 122 static int sha1_digest_atomic(crypto_provider_handle_t, crypto_session_id_t,
 123     crypto_mechanism_t *, crypto_data_t *, crypto_data_t *,
 124     crypto_req_handle_t);
 125 
 126 static crypto_digest_ops_t sha1_digest_ops = {
 127         sha1_digest_init,
 128         sha1_digest,
 129         sha1_digest_update,
 130         NULL,
 131         sha1_digest_final,
 132         sha1_digest_atomic
 133 };
 134 
 135 static int sha1_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
 136     crypto_spi_ctx_template_t, crypto_req_handle_t);
 137 static int sha1_mac_update(crypto_ctx_t *, crypto_data_t *,
 138     crypto_req_handle_t);
 139 static int sha1_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t);
 140 static int sha1_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
 141     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
 142     crypto_spi_ctx_template_t, crypto_req_handle_t);
 143 static int sha1_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
 144     crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
 145     crypto_spi_ctx_template_t, crypto_req_handle_t);
 146 
 147 static crypto_mac_ops_t sha1_mac_ops = {
 148         sha1_mac_init,
 149         NULL,
 150         sha1_mac_update,
 151         sha1_mac_final,
 152         sha1_mac_atomic,
 153         sha1_mac_verify_atomic
 154 };
 155 
 156 static int sha1_create_ctx_template(crypto_provider_handle_t,
 157     crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
 158     size_t *, crypto_req_handle_t);
 159 static int sha1_free_context(crypto_ctx_t *);
 160 
 161 static crypto_ctx_ops_t sha1_ctx_ops = {
 162         sha1_create_ctx_template,
 163         sha1_free_context
 164 };
 165 
 166 static crypto_ops_t sha1_crypto_ops = {
 167         .co_control_ops = &sha1_control_ops,
 168         .co_digest_ops = &sha1_digest_ops,
 169         .co_mac_ops = &sha1_mac_ops,
 170         .co_ctx_ops = &sha1_ctx_ops
 171 };
 172 
 173 static crypto_provider_info_t sha1_prov_info = {{{{
 174         CRYPTO_SPI_VERSION_4,
 175         "SHA1 Software Provider",
 176         CRYPTO_SW_PROVIDER,
 177         {&modlinkage},
 178         NULL,
 179         &sha1_crypto_ops,
 180         sizeof (sha1_mech_info_tab)/sizeof (crypto_mech_info_t),
 181         sha1_mech_info_tab
 182 }}}};
 183 
 184 static crypto_kcf_provider_handle_t sha1_prov_handle = NULL;
 185 
 186 int
 187 _init()
 188 {
 189         int ret;
 190 
 191         if ((ret = mod_install(&modlinkage)) != 0)
 192                 return (ret);
 193 
 194         /*
 195          * Register with KCF. If the registration fails, log do not uninstall
 196          * the module, since the functionality provided by misc/sha1 should
 197          * still be available.
 198          */
 199         (void) crypto_register_provider(&sha1_prov_info, &sha1_prov_handle);
 200 
 201         return (0);
 202 }
 203 
 204 int
 205 _info(struct modinfo *modinfop)
 206 {
 207         return (mod_info(&modlinkage, modinfop));
 208 }
 209 
 210 /*
 211  * KCF software provider control entry points.
 212  */
 213 /* ARGSUSED */
 214 static void
 215 sha1_provider_status(crypto_provider_handle_t provider, uint_t *status)
 216 {
 217         *status = CRYPTO_PROVIDER_READY;
 218 }
 219 
 220 /*
 221  * KCF software provider digest entry points.
 222  */
 223 
 224 static int
 225 sha1_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 226     crypto_req_handle_t req)
 227 {
 228         if (mechanism->cm_type != SHA1_MECH_INFO_TYPE)
 229                 return (CRYPTO_MECHANISM_INVALID);
 230 
 231         /*
 232          * Allocate and initialize SHA1 context.
 233          */
 234         ctx->cc_provider_private = kmem_alloc(sizeof (sha1_ctx_t),
 235             crypto_kmflag(req));
 236         if (ctx->cc_provider_private == NULL)
 237                 return (CRYPTO_HOST_MEMORY);
 238 
 239         PROV_SHA1_CTX(ctx)->sc_mech_type = SHA1_MECH_INFO_TYPE;
 240         SHA1Init(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx);
 241 
 242         return (CRYPTO_SUCCESS);
 243 }
 244 
 245 /*
 246  * Helper SHA1 digest update function for uio data.
 247  */
 248 static int
 249 sha1_digest_update_uio(SHA1_CTX *sha1_ctx, crypto_data_t *data)
 250 {
 251         off_t offset = data->cd_offset;
 252         size_t length = data->cd_length;
 253         uint_t vec_idx;
 254         size_t cur_len;
 255 
 256         /* we support only kernel buffer */
 257         if (data->cd_uio->uio_segflg != UIO_SYSSPACE)
 258                 return (CRYPTO_ARGUMENTS_BAD);
 259 
 260         /*
 261          * Jump to the first iovec containing data to be
 262          * digested.
 263          */
 264         for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt &&
 265             offset >= data->cd_uio->uio_iov[vec_idx].iov_len;
 266             offset -= data->cd_uio->uio_iov[vec_idx++].iov_len)
 267                 ;
 268         if (vec_idx == data->cd_uio->uio_iovcnt) {
 269                 /*
 270                  * The caller specified an offset that is larger than the
 271                  * total size of the buffers it provided.
 272                  */
 273                 return (CRYPTO_DATA_LEN_RANGE);
 274         }
 275 
 276         /*
 277          * Now do the digesting on the iovecs.
 278          */
 279         while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) {
 280                 cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len -
 281                     offset, length);
 282 
 283                 SHA1Update(sha1_ctx,
 284                     (uint8_t *)data->cd_uio->uio_iov[vec_idx].iov_base + offset,
 285                     cur_len);
 286 
 287                 length -= cur_len;
 288                 vec_idx++;
 289                 offset = 0;
 290         }
 291 
 292         if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) {
 293                 /*
 294                  * The end of the specified iovec's was reached but
 295                  * the length requested could not be processed, i.e.
 296                  * The caller requested to digest more data than it provided.
 297                  */
 298                 return (CRYPTO_DATA_LEN_RANGE);
 299         }
 300 
 301         return (CRYPTO_SUCCESS);
 302 }
 303 
 304 /*
 305  * Helper SHA1 digest final function for uio data.
 306  * digest_len is the length of the desired digest. If digest_len
 307  * is smaller than the default SHA1 digest length, the caller
 308  * must pass a scratch buffer, digest_scratch, which must
 309  * be at least SHA1_DIGEST_LENGTH bytes.
 310  */
 311 static int
 312 sha1_digest_final_uio(SHA1_CTX *sha1_ctx, crypto_data_t *digest,
 313     ulong_t digest_len, uchar_t *digest_scratch)
 314 {
 315         off_t offset = digest->cd_offset;
 316         uint_t vec_idx;
 317 
 318         /* we support only kernel buffer */
 319         if (digest->cd_uio->uio_segflg != UIO_SYSSPACE)
 320                 return (CRYPTO_ARGUMENTS_BAD);
 321 
 322         /*
 323          * Jump to the first iovec containing ptr to the digest to
 324          * be returned.
 325          */
 326         for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len &&
 327             vec_idx < digest->cd_uio->uio_iovcnt;
 328             offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len)
 329                 ;
 330         if (vec_idx == digest->cd_uio->uio_iovcnt) {
 331                 /*
 332                  * The caller specified an offset that is
 333                  * larger than the total size of the buffers
 334                  * it provided.
 335                  */
 336                 return (CRYPTO_DATA_LEN_RANGE);
 337         }
 338 
 339         if (offset + digest_len <=
 340             digest->cd_uio->uio_iov[vec_idx].iov_len) {
 341                 /*
 342                  * The computed SHA1 digest will fit in the current
 343                  * iovec.
 344                  */
 345                 if (digest_len != SHA1_DIGEST_LENGTH) {
 346                         /*
 347                          * The caller requested a short digest. Digest
 348                          * into a scratch buffer and return to
 349                          * the user only what was requested.
 350                          */
 351                         SHA1Final(digest_scratch, sha1_ctx);
 352                         bcopy(digest_scratch, (uchar_t *)digest->
 353                             cd_uio->uio_iov[vec_idx].iov_base + offset,
 354                             digest_len);
 355                 } else {
 356                         SHA1Final((uchar_t *)digest->
 357                             cd_uio->uio_iov[vec_idx].iov_base + offset,
 358                             sha1_ctx);
 359                 }
 360         } else {
 361                 /*
 362                  * The computed digest will be crossing one or more iovec's.
 363                  * This is bad performance-wise but we need to support it.
 364                  * Allocate a small scratch buffer on the stack and
 365                  * copy it piece meal to the specified digest iovec's.
 366                  */
 367                 uchar_t digest_tmp[SHA1_DIGEST_LENGTH];
 368                 off_t scratch_offset = 0;
 369                 size_t length = digest_len;
 370                 size_t cur_len;
 371 
 372                 SHA1Final(digest_tmp, sha1_ctx);
 373 
 374                 while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) {
 375                         cur_len = MIN(digest->cd_uio->uio_iov[vec_idx].iov_len -
 376                             offset, length);
 377                         bcopy(digest_tmp + scratch_offset,
 378                             digest->cd_uio->uio_iov[vec_idx].iov_base + offset,
 379                             cur_len);
 380 
 381                         length -= cur_len;
 382                         vec_idx++;
 383                         scratch_offset += cur_len;
 384                         offset = 0;
 385                 }
 386 
 387                 if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) {
 388                         /*
 389                          * The end of the specified iovec's was reached but
 390                          * the length requested could not be processed, i.e.
 391                          * The caller requested to digest more data than it
 392                          * provided.
 393                          */
 394                         return (CRYPTO_DATA_LEN_RANGE);
 395                 }
 396         }
 397 
 398         return (CRYPTO_SUCCESS);
 399 }
 400 
 401 /*
 402  * Helper SHA1 digest update for mblk's.
 403  */
 404 static int
 405 sha1_digest_update_mblk(SHA1_CTX *sha1_ctx, crypto_data_t *data)
 406 {
 407         off_t offset = data->cd_offset;
 408         size_t length = data->cd_length;
 409         mblk_t *mp;
 410         size_t cur_len;
 411 
 412         /*
 413          * Jump to the first mblk_t containing data to be digested.
 414          */
 415         for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp);
 416             offset -= MBLKL(mp), mp = mp->b_cont)
 417                 ;
 418         if (mp == NULL) {
 419                 /*
 420                  * The caller specified an offset that is larger than the
 421                  * total size of the buffers it provided.
 422                  */
 423                 return (CRYPTO_DATA_LEN_RANGE);
 424         }
 425 
 426         /*
 427          * Now do the digesting on the mblk chain.
 428          */
 429         while (mp != NULL && length > 0) {
 430                 cur_len = MIN(MBLKL(mp) - offset, length);
 431                 SHA1Update(sha1_ctx, mp->b_rptr + offset, cur_len);
 432                 length -= cur_len;
 433                 offset = 0;
 434                 mp = mp->b_cont;
 435         }
 436 
 437         if (mp == NULL && length > 0) {
 438                 /*
 439                  * The end of the mblk was reached but the length requested
 440                  * could not be processed, i.e. The caller requested
 441                  * to digest more data than it provided.
 442                  */
 443                 return (CRYPTO_DATA_LEN_RANGE);
 444         }
 445 
 446         return (CRYPTO_SUCCESS);
 447 }
 448 
 449 /*
 450  * Helper SHA1 digest final for mblk's.
 451  * digest_len is the length of the desired digest. If digest_len
 452  * is smaller than the default SHA1 digest length, the caller
 453  * must pass a scratch buffer, digest_scratch, which must
 454  * be at least SHA1_DIGEST_LENGTH bytes.
 455  */
 456 static int
 457 sha1_digest_final_mblk(SHA1_CTX *sha1_ctx, crypto_data_t *digest,
 458     ulong_t digest_len, uchar_t *digest_scratch)
 459 {
 460         off_t offset = digest->cd_offset;
 461         mblk_t *mp;
 462 
 463         /*
 464          * Jump to the first mblk_t that will be used to store the digest.
 465          */
 466         for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp);
 467             offset -= MBLKL(mp), mp = mp->b_cont)
 468                 ;
 469         if (mp == NULL) {
 470                 /*
 471                  * The caller specified an offset that is larger than the
 472                  * total size of the buffers it provided.
 473                  */
 474                 return (CRYPTO_DATA_LEN_RANGE);
 475         }
 476 
 477         if (offset + digest_len <= MBLKL(mp)) {
 478                 /*
 479                  * The computed SHA1 digest will fit in the current mblk.
 480                  * Do the SHA1Final() in-place.
 481                  */
 482                 if (digest_len != SHA1_DIGEST_LENGTH) {
 483                         /*
 484                          * The caller requested a short digest. Digest
 485                          * into a scratch buffer and return to
 486                          * the user only what was requested.
 487                          */
 488                         SHA1Final(digest_scratch, sha1_ctx);
 489                         bcopy(digest_scratch, mp->b_rptr + offset, digest_len);
 490                 } else {
 491                         SHA1Final(mp->b_rptr + offset, sha1_ctx);
 492                 }
 493         } else {
 494                 /*
 495                  * The computed digest will be crossing one or more mblk's.
 496                  * This is bad performance-wise but we need to support it.
 497                  * Allocate a small scratch buffer on the stack and
 498                  * copy it piece meal to the specified digest iovec's.
 499                  */
 500                 uchar_t digest_tmp[SHA1_DIGEST_LENGTH];
 501                 off_t scratch_offset = 0;
 502                 size_t length = digest_len;
 503                 size_t cur_len;
 504 
 505                 SHA1Final(digest_tmp, sha1_ctx);
 506 
 507                 while (mp != NULL && length > 0) {
 508                         cur_len = MIN(MBLKL(mp) - offset, length);
 509                         bcopy(digest_tmp + scratch_offset,
 510                             mp->b_rptr + offset, cur_len);
 511 
 512                         length -= cur_len;
 513                         mp = mp->b_cont;
 514                         scratch_offset += cur_len;
 515                         offset = 0;
 516                 }
 517 
 518                 if (mp == NULL && length > 0) {
 519                         /*
 520                          * The end of the specified mblk was reached but
 521                          * the length requested could not be processed, i.e.
 522                          * The caller requested to digest more data than it
 523                          * provided.
 524                          */
 525                         return (CRYPTO_DATA_LEN_RANGE);
 526                 }
 527         }
 528 
 529         return (CRYPTO_SUCCESS);
 530 }
 531 
 532 /* ARGSUSED */
 533 static int
 534 sha1_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
 535     crypto_req_handle_t req)
 536 {
 537         int ret = CRYPTO_SUCCESS;
 538 
 539         ASSERT(ctx->cc_provider_private != NULL);
 540 
 541         /*
 542          * We need to just return the length needed to store the output.
 543          * We should not destroy the context for the following cases.
 544          */
 545         if ((digest->cd_length == 0) ||
 546             (digest->cd_length < SHA1_DIGEST_LENGTH)) {
 547                 digest->cd_length = SHA1_DIGEST_LENGTH;
 548                 return (CRYPTO_BUFFER_TOO_SMALL);
 549         }
 550 
 551         /*
 552          * Do the SHA1 update on the specified input data.
 553          */
 554         switch (data->cd_format) {
 555         case CRYPTO_DATA_RAW:
 556                 SHA1Update(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 557                     (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
 558                     data->cd_length);
 559                 break;
 560         case CRYPTO_DATA_UIO:
 561                 ret = sha1_digest_update_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 562                     data);
 563                 break;
 564         case CRYPTO_DATA_MBLK:
 565                 ret = sha1_digest_update_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 566                     data);
 567                 break;
 568         default:
 569                 ret = CRYPTO_ARGUMENTS_BAD;
 570         }
 571 
 572         if (ret != CRYPTO_SUCCESS) {
 573                 /* the update failed, free context and bail */
 574                 kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t));
 575                 ctx->cc_provider_private = NULL;
 576                 digest->cd_length = 0;
 577                 return (ret);
 578         }
 579 
 580         /*
 581          * Do a SHA1 final, must be done separately since the digest
 582          * type can be different than the input data type.
 583          */
 584         switch (digest->cd_format) {
 585         case CRYPTO_DATA_RAW:
 586                 SHA1Final((unsigned char *)digest->cd_raw.iov_base +
 587                     digest->cd_offset, &PROV_SHA1_CTX(ctx)->sc_sha1_ctx);
 588                 break;
 589         case CRYPTO_DATA_UIO:
 590                 ret = sha1_digest_final_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 591                     digest, SHA1_DIGEST_LENGTH, NULL);
 592                 break;
 593         case CRYPTO_DATA_MBLK:
 594                 ret = sha1_digest_final_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 595                     digest, SHA1_DIGEST_LENGTH, NULL);
 596                 break;
 597         default:
 598                 ret = CRYPTO_ARGUMENTS_BAD;
 599         }
 600 
 601         /* all done, free context and return */
 602 
 603         if (ret == CRYPTO_SUCCESS) {
 604                 digest->cd_length = SHA1_DIGEST_LENGTH;
 605         } else {
 606                 digest->cd_length = 0;
 607         }
 608 
 609         kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t));
 610         ctx->cc_provider_private = NULL;
 611         return (ret);
 612 }
 613 
 614 /* ARGSUSED */
 615 static int
 616 sha1_digest_update(crypto_ctx_t *ctx, crypto_data_t *data,
 617     crypto_req_handle_t req)
 618 {
 619         int ret = CRYPTO_SUCCESS;
 620 
 621         ASSERT(ctx->cc_provider_private != NULL);
 622 
 623         /*
 624          * Do the SHA1 update on the specified input data.
 625          */
 626         switch (data->cd_format) {
 627         case CRYPTO_DATA_RAW:
 628                 SHA1Update(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 629                     (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
 630                     data->cd_length);
 631                 break;
 632         case CRYPTO_DATA_UIO:
 633                 ret = sha1_digest_update_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 634                     data);
 635                 break;
 636         case CRYPTO_DATA_MBLK:
 637                 ret = sha1_digest_update_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 638                     data);
 639                 break;
 640         default:
 641                 ret = CRYPTO_ARGUMENTS_BAD;
 642         }
 643 
 644         return (ret);
 645 }
 646 
 647 /* ARGSUSED */
 648 static int
 649 sha1_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest,
 650     crypto_req_handle_t req)
 651 {
 652         int ret = CRYPTO_SUCCESS;
 653 
 654         ASSERT(ctx->cc_provider_private != NULL);
 655 
 656         /*
 657          * We need to just return the length needed to store the output.
 658          * We should not destroy the context for the following cases.
 659          */
 660         if ((digest->cd_length == 0) ||
 661             (digest->cd_length < SHA1_DIGEST_LENGTH)) {
 662                 digest->cd_length = SHA1_DIGEST_LENGTH;
 663                 return (CRYPTO_BUFFER_TOO_SMALL);
 664         }
 665 
 666         /*
 667          * Do a SHA1 final.
 668          */
 669         switch (digest->cd_format) {
 670         case CRYPTO_DATA_RAW:
 671                 SHA1Final((unsigned char *)digest->cd_raw.iov_base +
 672                     digest->cd_offset, &PROV_SHA1_CTX(ctx)->sc_sha1_ctx);
 673                 break;
 674         case CRYPTO_DATA_UIO:
 675                 ret = sha1_digest_final_uio(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 676                     digest, SHA1_DIGEST_LENGTH, NULL);
 677                 break;
 678         case CRYPTO_DATA_MBLK:
 679                 ret = sha1_digest_final_mblk(&PROV_SHA1_CTX(ctx)->sc_sha1_ctx,
 680                     digest, SHA1_DIGEST_LENGTH, NULL);
 681                 break;
 682         default:
 683                 ret = CRYPTO_ARGUMENTS_BAD;
 684         }
 685 
 686         /* all done, free context and return */
 687 
 688         if (ret == CRYPTO_SUCCESS) {
 689                 digest->cd_length = SHA1_DIGEST_LENGTH;
 690         } else {
 691                 digest->cd_length = 0;
 692         }
 693 
 694         kmem_free(ctx->cc_provider_private, sizeof (sha1_ctx_t));
 695         ctx->cc_provider_private = NULL;
 696 
 697         return (ret);
 698 }
 699 
 700 /* ARGSUSED */
 701 static int
 702 sha1_digest_atomic(crypto_provider_handle_t provider,
 703     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
 704     crypto_data_t *data, crypto_data_t *digest,
 705     crypto_req_handle_t req)
 706 {
 707         int ret = CRYPTO_SUCCESS;
 708         SHA1_CTX sha1_ctx;
 709 
 710         if (mechanism->cm_type != SHA1_MECH_INFO_TYPE)
 711                 return (CRYPTO_MECHANISM_INVALID);
 712 
 713         /*
 714          * Do the SHA1 init.
 715          */
 716         SHA1Init(&sha1_ctx);
 717 
 718         /*
 719          * Do the SHA1 update on the specified input data.
 720          */
 721         switch (data->cd_format) {
 722         case CRYPTO_DATA_RAW:
 723                 SHA1Update(&sha1_ctx,
 724                     (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
 725                     data->cd_length);
 726                 break;
 727         case CRYPTO_DATA_UIO:
 728                 ret = sha1_digest_update_uio(&sha1_ctx, data);
 729                 break;
 730         case CRYPTO_DATA_MBLK:
 731                 ret = sha1_digest_update_mblk(&sha1_ctx, data);
 732                 break;
 733         default:
 734                 ret = CRYPTO_ARGUMENTS_BAD;
 735         }
 736 
 737         if (ret != CRYPTO_SUCCESS) {
 738                 /* the update failed, bail */
 739                 digest->cd_length = 0;
 740                 return (ret);
 741         }
 742 
 743         /*
 744          * Do a SHA1 final, must be done separately since the digest
 745          * type can be different than the input data type.
 746          */
 747         switch (digest->cd_format) {
 748         case CRYPTO_DATA_RAW:
 749                 SHA1Final((unsigned char *)digest->cd_raw.iov_base +
 750                     digest->cd_offset, &sha1_ctx);
 751                 break;
 752         case CRYPTO_DATA_UIO:
 753                 ret = sha1_digest_final_uio(&sha1_ctx, digest,
 754                     SHA1_DIGEST_LENGTH, NULL);
 755                 break;
 756         case CRYPTO_DATA_MBLK:
 757                 ret = sha1_digest_final_mblk(&sha1_ctx, digest,
 758                     SHA1_DIGEST_LENGTH, NULL);
 759                 break;
 760         default:
 761                 ret = CRYPTO_ARGUMENTS_BAD;
 762         }
 763 
 764         if (ret == CRYPTO_SUCCESS) {
 765                 digest->cd_length = SHA1_DIGEST_LENGTH;
 766         } else {
 767                 digest->cd_length = 0;
 768         }
 769 
 770         return (ret);
 771 }
 772 
 773 /*
 774  * KCF software provider mac entry points.
 775  *
 776  * SHA1 HMAC is: SHA1(key XOR opad, SHA1(key XOR ipad, text))
 777  *
 778  * Init:
 779  * The initialization routine initializes what we denote
 780  * as the inner and outer contexts by doing
 781  * - for inner context: SHA1(key XOR ipad)
 782  * - for outer context: SHA1(key XOR opad)
 783  *
 784  * Update:
 785  * Each subsequent SHA1 HMAC update will result in an
 786  * update of the inner context with the specified data.
 787  *
 788  * Final:
 789  * The SHA1 HMAC final will do a SHA1 final operation on the
 790  * inner context, and the resulting digest will be used
 791  * as the data for an update on the outer context. Last
 792  * but not least, a SHA1 final on the outer context will
 793  * be performed to obtain the SHA1 HMAC digest to return
 794  * to the user.
 795  */
 796 
 797 /*
 798  * Initialize a SHA1-HMAC context.
 799  */
 800 static void
 801 sha1_mac_init_ctx(sha1_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
 802 {
 803         uint32_t ipad[SHA1_HMAC_INTS_PER_BLOCK];
 804         uint32_t opad[SHA1_HMAC_INTS_PER_BLOCK];
 805         uint_t i;
 806 
 807         bzero(ipad, SHA1_HMAC_BLOCK_SIZE);
 808         bzero(opad, SHA1_HMAC_BLOCK_SIZE);
 809 
 810         bcopy(keyval, ipad, length_in_bytes);
 811         bcopy(keyval, opad, length_in_bytes);
 812 
 813         /* XOR key with ipad (0x36) and opad (0x5c) */
 814         for (i = 0; i < SHA1_HMAC_INTS_PER_BLOCK; i++) {
 815                 ipad[i] ^= 0x36363636;
 816                 opad[i] ^= 0x5c5c5c5c;
 817         }
 818 
 819         /* perform SHA1 on ipad */
 820         SHA1Init(&ctx->hc_icontext);
 821         SHA1Update(&ctx->hc_icontext, (uint8_t *)ipad, SHA1_HMAC_BLOCK_SIZE);
 822 
 823         /* perform SHA1 on opad */
 824         SHA1Init(&ctx->hc_ocontext);
 825         SHA1Update(&ctx->hc_ocontext, (uint8_t *)opad, SHA1_HMAC_BLOCK_SIZE);
 826 }
 827 
 828 /*
 829  */
 830 static int
 831 sha1_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
 832     crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
 833     crypto_req_handle_t req)
 834 {
 835         int ret = CRYPTO_SUCCESS;
 836         uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
 837 
 838         if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE &&
 839             mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)
 840                 return (CRYPTO_MECHANISM_INVALID);
 841 
 842         /* Add support for key by attributes (RFE 4706552) */
 843         if (key->ck_format != CRYPTO_KEY_RAW)
 844                 return (CRYPTO_ARGUMENTS_BAD);
 845 
 846         ctx->cc_provider_private = kmem_alloc(sizeof (sha1_hmac_ctx_t),
 847             crypto_kmflag(req));
 848         if (ctx->cc_provider_private == NULL)
 849                 return (CRYPTO_HOST_MEMORY);
 850 
 851         if (ctx_template != NULL) {
 852                 /* reuse context template */
 853                 bcopy(ctx_template, PROV_SHA1_HMAC_CTX(ctx),
 854                     sizeof (sha1_hmac_ctx_t));
 855         } else {
 856                 /* no context template, compute context */
 857                 if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) {
 858                         uchar_t digested_key[SHA1_DIGEST_LENGTH];
 859                         sha1_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private;
 860 
 861                         /*
 862                          * Hash the passed-in key to get a smaller key.
 863                          * The inner context is used since it hasn't been
 864                          * initialized yet.
 865                          */
 866                         PROV_SHA1_DIGEST_KEY(&hmac_ctx->hc_icontext,
 867                             key->ck_data, keylen_in_bytes, digested_key);
 868                         sha1_mac_init_ctx(PROV_SHA1_HMAC_CTX(ctx),
 869                             digested_key, SHA1_DIGEST_LENGTH);
 870                 } else {
 871                         sha1_mac_init_ctx(PROV_SHA1_HMAC_CTX(ctx),
 872                             key->ck_data, keylen_in_bytes);
 873                 }
 874         }
 875 
 876         /*
 877          * Get the mechanism parameters, if applicable.
 878          */
 879         PROV_SHA1_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type;
 880         if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) {
 881                 if (mechanism->cm_param == NULL ||
 882                     mechanism->cm_param_len != sizeof (ulong_t))
 883                         ret = CRYPTO_MECHANISM_PARAM_INVALID;
 884                 PROV_SHA1_GET_DIGEST_LEN(mechanism,
 885                     PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len);
 886                 if (PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len >
 887                     SHA1_DIGEST_LENGTH)
 888                         ret = CRYPTO_MECHANISM_PARAM_INVALID;
 889         }
 890 
 891         if (ret != CRYPTO_SUCCESS) {
 892                 bzero(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t));
 893                 kmem_free(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t));
 894                 ctx->cc_provider_private = NULL;
 895         }
 896 
 897         return (ret);
 898 }
 899 
 900 /* ARGSUSED */
 901 static int
 902 sha1_mac_update(crypto_ctx_t *ctx, crypto_data_t *data, crypto_req_handle_t req)
 903 {
 904         int ret = CRYPTO_SUCCESS;
 905 
 906         ASSERT(ctx->cc_provider_private != NULL);
 907 
 908         /*
 909          * Do a SHA1 update of the inner context using the specified
 910          * data.
 911          */
 912         switch (data->cd_format) {
 913         case CRYPTO_DATA_RAW:
 914                 SHA1Update(&PROV_SHA1_HMAC_CTX(ctx)->hc_icontext,
 915                     (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
 916                     data->cd_length);
 917                 break;
 918         case CRYPTO_DATA_UIO:
 919                 ret = sha1_digest_update_uio(
 920                     &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, data);
 921                 break;
 922         case CRYPTO_DATA_MBLK:
 923                 ret = sha1_digest_update_mblk(
 924                     &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext, data);
 925                 break;
 926         default:
 927                 ret = CRYPTO_ARGUMENTS_BAD;
 928         }
 929 
 930         return (ret);
 931 }
 932 
 933 /* ARGSUSED */
 934 static int
 935 sha1_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
 936 {
 937         int ret = CRYPTO_SUCCESS;
 938         uchar_t digest[SHA1_DIGEST_LENGTH];
 939         uint32_t digest_len = SHA1_DIGEST_LENGTH;
 940 
 941         ASSERT(ctx->cc_provider_private != NULL);
 942 
 943         if (PROV_SHA1_HMAC_CTX(ctx)->hc_mech_type ==
 944             SHA1_HMAC_GEN_MECH_INFO_TYPE)
 945                 digest_len = PROV_SHA1_HMAC_CTX(ctx)->hc_digest_len;
 946 
 947         /*
 948          * We need to just return the length needed to store the output.
 949          * We should not destroy the context for the following cases.
 950          */
 951         if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) {
 952                 mac->cd_length = digest_len;
 953                 return (CRYPTO_BUFFER_TOO_SMALL);
 954         }
 955 
 956         /*
 957          * Do a SHA1 final on the inner context.
 958          */
 959         SHA1Final(digest, &PROV_SHA1_HMAC_CTX(ctx)->hc_icontext);
 960 
 961         /*
 962          * Do a SHA1 update on the outer context, feeding the inner
 963          * digest as data.
 964          */
 965         SHA1Update(&PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, digest,
 966             SHA1_DIGEST_LENGTH);
 967 
 968         /*
 969          * Do a SHA1 final on the outer context, storing the computing
 970          * digest in the users buffer.
 971          */
 972         switch (mac->cd_format) {
 973         case CRYPTO_DATA_RAW:
 974                 if (digest_len != SHA1_DIGEST_LENGTH) {
 975                         /*
 976                          * The caller requested a short digest. Digest
 977                          * into a scratch buffer and return to
 978                          * the user only what was requested.
 979                          */
 980                         SHA1Final(digest,
 981                             &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext);
 982                         bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
 983                             mac->cd_offset, digest_len);
 984                 } else {
 985                         SHA1Final((unsigned char *)mac->cd_raw.iov_base +
 986                             mac->cd_offset,
 987                             &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext);
 988                 }
 989                 break;
 990         case CRYPTO_DATA_UIO:
 991                 ret = sha1_digest_final_uio(
 992                     &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, mac,
 993                     digest_len, digest);
 994                 break;
 995         case CRYPTO_DATA_MBLK:
 996                 ret = sha1_digest_final_mblk(
 997                     &PROV_SHA1_HMAC_CTX(ctx)->hc_ocontext, mac,
 998                     digest_len, digest);
 999                 break;
1000         default:
1001                 ret = CRYPTO_ARGUMENTS_BAD;
1002         }
1003 
1004         if (ret == CRYPTO_SUCCESS) {
1005                 mac->cd_length = digest_len;
1006         } else {
1007                 mac->cd_length = 0;
1008         }
1009 
1010         bzero(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t));
1011         kmem_free(ctx->cc_provider_private, sizeof (sha1_hmac_ctx_t));
1012         ctx->cc_provider_private = NULL;
1013 
1014         return (ret);
1015 }
1016 
1017 #define SHA1_MAC_UPDATE(data, ctx, ret) {                               \
1018         switch (data->cd_format) {                                   \
1019         case CRYPTO_DATA_RAW:                                           \
1020                 SHA1Update(&(ctx).hc_icontext,                              \
1021                     (uint8_t *)data->cd_raw.iov_base +                       \
1022                     data->cd_offset, data->cd_length);                    \
1023                 break;                                                  \
1024         case CRYPTO_DATA_UIO:                                           \
1025                 ret = sha1_digest_update_uio(&(ctx).hc_icontext, data); \
1026                 break;                                                  \
1027         case CRYPTO_DATA_MBLK:                                          \
1028                 ret = sha1_digest_update_mblk(&(ctx).hc_icontext,   \
1029                     data);                                              \
1030                 break;                                                  \
1031         default:                                                        \
1032                 ret = CRYPTO_ARGUMENTS_BAD;                             \
1033         }                                                               \
1034 }
1035 
1036 /* ARGSUSED */
1037 static int
1038 sha1_mac_atomic(crypto_provider_handle_t provider,
1039     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1040     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1041     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1042 {
1043         int ret = CRYPTO_SUCCESS;
1044         uchar_t digest[SHA1_DIGEST_LENGTH];
1045         sha1_hmac_ctx_t sha1_hmac_ctx;
1046         uint32_t digest_len = SHA1_DIGEST_LENGTH;
1047         uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1048 
1049         if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE &&
1050             mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)
1051                 return (CRYPTO_MECHANISM_INVALID);
1052 
1053         /* Add support for key by attributes (RFE 4706552) */
1054         if (key->ck_format != CRYPTO_KEY_RAW)
1055                 return (CRYPTO_ARGUMENTS_BAD);
1056 
1057         if (ctx_template != NULL) {
1058                 /* reuse context template */
1059                 bcopy(ctx_template, &sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1060         } else {
1061                 /* no context template, initialize context */
1062                 if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) {
1063                         /*
1064                          * Hash the passed-in key to get a smaller key.
1065                          * The inner context is used since it hasn't been
1066                          * initialized yet.
1067                          */
1068                         PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx.hc_icontext,
1069                             key->ck_data, keylen_in_bytes, digest);
1070                         sha1_mac_init_ctx(&sha1_hmac_ctx, digest,
1071                             SHA1_DIGEST_LENGTH);
1072                 } else {
1073                         sha1_mac_init_ctx(&sha1_hmac_ctx, key->ck_data,
1074                             keylen_in_bytes);
1075                 }
1076         }
1077 
1078         /* get the mechanism parameters, if applicable */
1079         if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) {
1080                 if (mechanism->cm_param == NULL ||
1081                     mechanism->cm_param_len != sizeof (ulong_t)) {
1082                         ret = CRYPTO_MECHANISM_PARAM_INVALID;
1083                         goto bail;
1084                 }
1085                 PROV_SHA1_GET_DIGEST_LEN(mechanism, digest_len);
1086                 if (digest_len > SHA1_DIGEST_LENGTH) {
1087                         ret = CRYPTO_MECHANISM_PARAM_INVALID;
1088                         goto bail;
1089                 }
1090         }
1091 
1092         /* do a SHA1 update of the inner context using the specified data */
1093         SHA1_MAC_UPDATE(data, sha1_hmac_ctx, ret);
1094         if (ret != CRYPTO_SUCCESS)
1095                 /* the update failed, free context and bail */
1096                 goto bail;
1097 
1098         /*
1099          * Do a SHA1 final on the inner context.
1100          */
1101         SHA1Final(digest, &sha1_hmac_ctx.hc_icontext);
1102 
1103         /*
1104          * Do an SHA1 update on the outer context, feeding the inner
1105          * digest as data.
1106          */
1107         SHA1Update(&sha1_hmac_ctx.hc_ocontext, digest, SHA1_DIGEST_LENGTH);
1108 
1109         /*
1110          * Do a SHA1 final on the outer context, storing the computed
1111          * digest in the users buffer.
1112          */
1113         switch (mac->cd_format) {
1114         case CRYPTO_DATA_RAW:
1115                 if (digest_len != SHA1_DIGEST_LENGTH) {
1116                         /*
1117                          * The caller requested a short digest. Digest
1118                          * into a scratch buffer and return to
1119                          * the user only what was requested.
1120                          */
1121                         SHA1Final(digest, &sha1_hmac_ctx.hc_ocontext);
1122                         bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
1123                             mac->cd_offset, digest_len);
1124                 } else {
1125                         SHA1Final((unsigned char *)mac->cd_raw.iov_base +
1126                             mac->cd_offset, &sha1_hmac_ctx.hc_ocontext);
1127                 }
1128                 break;
1129         case CRYPTO_DATA_UIO:
1130                 ret = sha1_digest_final_uio(&sha1_hmac_ctx.hc_ocontext, mac,
1131                     digest_len, digest);
1132                 break;
1133         case CRYPTO_DATA_MBLK:
1134                 ret = sha1_digest_final_mblk(&sha1_hmac_ctx.hc_ocontext, mac,
1135                     digest_len, digest);
1136                 break;
1137         default:
1138                 ret = CRYPTO_ARGUMENTS_BAD;
1139         }
1140 
1141         if (ret == CRYPTO_SUCCESS) {
1142                 mac->cd_length = digest_len;
1143         } else {
1144                 mac->cd_length = 0;
1145         }
1146         /* Extra paranoia: zeroize the context on the stack */
1147         bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1148 
1149         return (ret);
1150 bail:
1151         bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1152         mac->cd_length = 0;
1153         return (ret);
1154 }
1155 
1156 /* ARGSUSED */
1157 static int
1158 sha1_mac_verify_atomic(crypto_provider_handle_t provider,
1159     crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
1160     crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
1161     crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
1162 {
1163         int ret = CRYPTO_SUCCESS;
1164         uchar_t digest[SHA1_DIGEST_LENGTH];
1165         sha1_hmac_ctx_t sha1_hmac_ctx;
1166         uint32_t digest_len = SHA1_DIGEST_LENGTH;
1167         uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1168 
1169         if (mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE &&
1170             mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)
1171                 return (CRYPTO_MECHANISM_INVALID);
1172 
1173         /* Add support for key by attributes (RFE 4706552) */
1174         if (key->ck_format != CRYPTO_KEY_RAW)
1175                 return (CRYPTO_ARGUMENTS_BAD);
1176 
1177         if (ctx_template != NULL) {
1178                 /* reuse context template */
1179                 bcopy(ctx_template, &sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1180         } else {
1181                 /* no context template, initialize context */
1182                 if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) {
1183                         /*
1184                          * Hash the passed-in key to get a smaller key.
1185                          * The inner context is used since it hasn't been
1186                          * initialized yet.
1187                          */
1188                         PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx.hc_icontext,
1189                             key->ck_data, keylen_in_bytes, digest);
1190                         sha1_mac_init_ctx(&sha1_hmac_ctx, digest,
1191                             SHA1_DIGEST_LENGTH);
1192                 } else {
1193                         sha1_mac_init_ctx(&sha1_hmac_ctx, key->ck_data,
1194                             keylen_in_bytes);
1195                 }
1196         }
1197 
1198         /* get the mechanism parameters, if applicable */
1199         if (mechanism->cm_type == SHA1_HMAC_GEN_MECH_INFO_TYPE) {
1200                 if (mechanism->cm_param == NULL ||
1201                     mechanism->cm_param_len != sizeof (ulong_t)) {
1202                         ret = CRYPTO_MECHANISM_PARAM_INVALID;
1203                         goto bail;
1204                 }
1205                 PROV_SHA1_GET_DIGEST_LEN(mechanism, digest_len);
1206                 if (digest_len > SHA1_DIGEST_LENGTH) {
1207                         ret = CRYPTO_MECHANISM_PARAM_INVALID;
1208                         goto bail;
1209                 }
1210         }
1211 
1212         if (mac->cd_length != digest_len) {
1213                 ret = CRYPTO_INVALID_MAC;
1214                 goto bail;
1215         }
1216 
1217         /* do a SHA1 update of the inner context using the specified data */
1218         SHA1_MAC_UPDATE(data, sha1_hmac_ctx, ret);
1219         if (ret != CRYPTO_SUCCESS)
1220                 /* the update failed, free context and bail */
1221                 goto bail;
1222 
1223         /* do a SHA1 final on the inner context */
1224         SHA1Final(digest, &sha1_hmac_ctx.hc_icontext);
1225 
1226         /*
1227          * Do an SHA1 update on the outer context, feeding the inner
1228          * digest as data.
1229          */
1230         SHA1Update(&sha1_hmac_ctx.hc_ocontext, digest, SHA1_DIGEST_LENGTH);
1231 
1232         /*
1233          * Do a SHA1 final on the outer context, storing the computed
1234          * digest in the users buffer.
1235          */
1236         SHA1Final(digest, &sha1_hmac_ctx.hc_ocontext);
1237 
1238         /*
1239          * Compare the computed digest against the expected digest passed
1240          * as argument.
1241          */
1242 
1243         switch (mac->cd_format) {
1244 
1245         case CRYPTO_DATA_RAW:
1246                 if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base +
1247                     mac->cd_offset, digest_len) != 0)
1248                         ret = CRYPTO_INVALID_MAC;
1249                 break;
1250 
1251         case CRYPTO_DATA_UIO: {
1252                 off_t offset = mac->cd_offset;
1253                 uint_t vec_idx;
1254                 off_t scratch_offset = 0;
1255                 size_t length = digest_len;
1256                 size_t cur_len;
1257 
1258                 /* we support only kernel buffer */
1259                 if (mac->cd_uio->uio_segflg != UIO_SYSSPACE)
1260                         return (CRYPTO_ARGUMENTS_BAD);
1261 
1262                 /* jump to the first iovec containing the expected digest */
1263                 for (vec_idx = 0;
1264                     offset >= mac->cd_uio->uio_iov[vec_idx].iov_len &&
1265                     vec_idx < mac->cd_uio->uio_iovcnt;
1266                     offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len)
1267                         ;
1268                 if (vec_idx == mac->cd_uio->uio_iovcnt) {
1269                         /*
1270                          * The caller specified an offset that is
1271                          * larger than the total size of the buffers
1272                          * it provided.
1273                          */
1274                         ret = CRYPTO_DATA_LEN_RANGE;
1275                         break;
1276                 }
1277 
1278                 /* do the comparison of computed digest vs specified one */
1279                 while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) {
1280                         cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len -
1281                             offset, length);
1282 
1283                         if (bcmp(digest + scratch_offset,
1284                             mac->cd_uio->uio_iov[vec_idx].iov_base + offset,
1285                             cur_len) != 0) {
1286                                 ret = CRYPTO_INVALID_MAC;
1287                                 break;
1288                         }
1289 
1290                         length -= cur_len;
1291                         vec_idx++;
1292                         scratch_offset += cur_len;
1293                         offset = 0;
1294                 }
1295                 break;
1296         }
1297 
1298         case CRYPTO_DATA_MBLK: {
1299                 off_t offset = mac->cd_offset;
1300                 mblk_t *mp;
1301                 off_t scratch_offset = 0;
1302                 size_t length = digest_len;
1303                 size_t cur_len;
1304 
1305                 /* jump to the first mblk_t containing the expected digest */
1306                 for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp);
1307                     offset -= MBLKL(mp), mp = mp->b_cont)
1308                         ;
1309                 if (mp == NULL) {
1310                         /*
1311                          * The caller specified an offset that is larger than
1312                          * the total size of the buffers it provided.
1313                          */
1314                         ret = CRYPTO_DATA_LEN_RANGE;
1315                         break;
1316                 }
1317 
1318                 while (mp != NULL && length > 0) {
1319                         cur_len = MIN(MBLKL(mp) - offset, length);
1320                         if (bcmp(digest + scratch_offset,
1321                             mp->b_rptr + offset, cur_len) != 0) {
1322                                 ret = CRYPTO_INVALID_MAC;
1323                                 break;
1324                         }
1325 
1326                         length -= cur_len;
1327                         mp = mp->b_cont;
1328                         scratch_offset += cur_len;
1329                         offset = 0;
1330                 }
1331                 break;
1332         }
1333 
1334         default:
1335                 ret = CRYPTO_ARGUMENTS_BAD;
1336         }
1337 
1338         bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1339         return (ret);
1340 bail:
1341         bzero(&sha1_hmac_ctx, sizeof (sha1_hmac_ctx_t));
1342         mac->cd_length = 0;
1343         return (ret);
1344 }
1345 
1346 /*
1347  * KCF software provider context management entry points.
1348  */
1349 
1350 /* ARGSUSED */
1351 static int
1352 sha1_create_ctx_template(crypto_provider_handle_t provider,
1353     crypto_mechanism_t *mechanism, crypto_key_t *key,
1354     crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size,
1355     crypto_req_handle_t req)
1356 {
1357         sha1_hmac_ctx_t *sha1_hmac_ctx_tmpl;
1358         uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
1359 
1360         if ((mechanism->cm_type != SHA1_HMAC_MECH_INFO_TYPE) &&
1361             (mechanism->cm_type != SHA1_HMAC_GEN_MECH_INFO_TYPE)) {
1362                 return (CRYPTO_MECHANISM_INVALID);
1363         }
1364 
1365         /* Add support for key by attributes (RFE 4706552) */
1366         if (key->ck_format != CRYPTO_KEY_RAW)
1367                 return (CRYPTO_ARGUMENTS_BAD);
1368 
1369         /*
1370          * Allocate and initialize SHA1 context.
1371          */
1372         sha1_hmac_ctx_tmpl = kmem_alloc(sizeof (sha1_hmac_ctx_t),
1373             crypto_kmflag(req));
1374         if (sha1_hmac_ctx_tmpl == NULL)
1375                 return (CRYPTO_HOST_MEMORY);
1376 
1377         if (keylen_in_bytes > SHA1_HMAC_BLOCK_SIZE) {
1378                 uchar_t digested_key[SHA1_DIGEST_LENGTH];
1379 
1380                 /*
1381                  * Hash the passed-in key to get a smaller key.
1382                  * The inner context is used since it hasn't been
1383                  * initialized yet.
1384                  */
1385                 PROV_SHA1_DIGEST_KEY(&sha1_hmac_ctx_tmpl->hc_icontext,
1386                     key->ck_data, keylen_in_bytes, digested_key);
1387                 sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, digested_key,
1388                     SHA1_DIGEST_LENGTH);
1389         } else {
1390                 sha1_mac_init_ctx(sha1_hmac_ctx_tmpl, key->ck_data,
1391                     keylen_in_bytes);
1392         }
1393 
1394         sha1_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type;
1395         *ctx_template = (crypto_spi_ctx_template_t)sha1_hmac_ctx_tmpl;
1396         *ctx_template_size = sizeof (sha1_hmac_ctx_t);
1397 
1398 
1399         return (CRYPTO_SUCCESS);
1400 }
1401 
1402 static int
1403 sha1_free_context(crypto_ctx_t *ctx)
1404 {
1405         uint_t ctx_len;
1406         sha1_mech_type_t mech_type;
1407 
1408         if (ctx->cc_provider_private == NULL)
1409                 return (CRYPTO_SUCCESS);
1410 
1411         /*
1412          * We have to free either SHA1 or SHA1-HMAC contexts, which
1413          * have different lengths.
1414          */
1415 
1416         mech_type = PROV_SHA1_CTX(ctx)->sc_mech_type;
1417         if (mech_type == SHA1_MECH_INFO_TYPE)
1418                 ctx_len = sizeof (sha1_ctx_t);
1419         else {
1420                 ASSERT(mech_type == SHA1_HMAC_MECH_INFO_TYPE ||
1421                     mech_type == SHA1_HMAC_GEN_MECH_INFO_TYPE);
1422                 ctx_len = sizeof (sha1_hmac_ctx_t);
1423         }
1424 
1425         bzero(ctx->cc_provider_private, ctx_len);
1426         kmem_free(ctx->cc_provider_private, ctx_len);
1427         ctx->cc_provider_private = NULL;
1428 
1429         return (CRYPTO_SUCCESS);
1430 }