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