1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9271171e0SMartin Matuska * or https://opensource.org/licenses/CDDL-1.0. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy 22eda14cbcSMatt Macy /* 23eda14cbcSMatt Macy * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 24eda14cbcSMatt Macy * Use is subject to license terms. 25eda14cbcSMatt Macy */ 26eda14cbcSMatt Macy 27eda14cbcSMatt Macy #include <sys/zfs_context.h> 28eda14cbcSMatt Macy #include <sys/crypto/common.h> 29eda14cbcSMatt Macy #include <sys/crypto/spi.h> 30eda14cbcSMatt Macy #include <sys/crypto/icp.h> 31eda14cbcSMatt Macy #include <sys/sha2.h> 32eda14cbcSMatt Macy #include <sha2/sha2_impl.h> 33eda14cbcSMatt Macy 34eda14cbcSMatt Macy /* 35eda14cbcSMatt Macy * Macros to access the SHA2 or SHA2-HMAC contexts from a context passed 36eda14cbcSMatt Macy * by KCF to one of the entry points. 37eda14cbcSMatt Macy */ 38eda14cbcSMatt Macy 39eda14cbcSMatt Macy #define PROV_SHA2_CTX(ctx) ((sha2_ctx_t *)(ctx)->cc_provider_private) 40eda14cbcSMatt Macy #define PROV_SHA2_HMAC_CTX(ctx) ((sha2_hmac_ctx_t *)(ctx)->cc_provider_private) 41eda14cbcSMatt Macy 42eda14cbcSMatt Macy /* to extract the digest length passed as mechanism parameter */ 43eda14cbcSMatt Macy #define PROV_SHA2_GET_DIGEST_LEN(m, len) { \ 44eda14cbcSMatt Macy if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \ 45eda14cbcSMatt Macy (len) = (uint32_t)*((ulong_t *)(m)->cm_param); \ 46eda14cbcSMatt Macy else { \ 47eda14cbcSMatt Macy ulong_t tmp_ulong; \ 48da5137abSMartin Matuska memcpy(&tmp_ulong, (m)->cm_param, sizeof (ulong_t)); \ 49eda14cbcSMatt Macy (len) = (uint32_t)tmp_ulong; \ 50eda14cbcSMatt Macy } \ 51eda14cbcSMatt Macy } 52eda14cbcSMatt Macy 53eda14cbcSMatt Macy #define PROV_SHA2_DIGEST_KEY(mech, ctx, key, len, digest) { \ 54eda14cbcSMatt Macy SHA2Init(mech, ctx); \ 55eda14cbcSMatt Macy SHA2Update(ctx, key, len); \ 56eda14cbcSMatt Macy SHA2Final(digest, ctx); \ 57eda14cbcSMatt Macy } 58eda14cbcSMatt Macy 59eda14cbcSMatt Macy /* 60eda14cbcSMatt Macy * Mechanism info structure passed to KCF during registration. 61eda14cbcSMatt Macy */ 62e92ffd9bSMartin Matuska static const crypto_mech_info_t sha2_mech_info_tab[] = { 63eda14cbcSMatt Macy /* SHA512-HMAC */ 64eda14cbcSMatt Macy {SUN_CKM_SHA512_HMAC, SHA512_HMAC_MECH_INFO_TYPE, 65c03c5b1cSMartin Matuska CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC}, 66eda14cbcSMatt Macy }; 67eda14cbcSMatt Macy 68eda14cbcSMatt Macy static int sha2_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *, 69c03c5b1cSMartin Matuska crypto_spi_ctx_template_t); 70c03c5b1cSMartin Matuska static int sha2_mac_update(crypto_ctx_t *, crypto_data_t *); 71c03c5b1cSMartin Matuska static int sha2_mac_final(crypto_ctx_t *, crypto_data_t *); 72c03c5b1cSMartin Matuska static int sha2_mac_atomic(crypto_mechanism_t *, crypto_key_t *, 73c03c5b1cSMartin Matuska crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t); 74c03c5b1cSMartin Matuska static int sha2_mac_verify_atomic(crypto_mechanism_t *, crypto_key_t *, 75c03c5b1cSMartin Matuska crypto_data_t *, crypto_data_t *, crypto_spi_ctx_template_t); 76eda14cbcSMatt Macy 77e92ffd9bSMartin Matuska static const crypto_mac_ops_t sha2_mac_ops = { 78eda14cbcSMatt Macy .mac_init = sha2_mac_init, 79eda14cbcSMatt Macy .mac = NULL, 80eda14cbcSMatt Macy .mac_update = sha2_mac_update, 81eda14cbcSMatt Macy .mac_final = sha2_mac_final, 82eda14cbcSMatt Macy .mac_atomic = sha2_mac_atomic, 83eda14cbcSMatt Macy .mac_verify_atomic = sha2_mac_verify_atomic 84eda14cbcSMatt Macy }; 85eda14cbcSMatt Macy 86c03c5b1cSMartin Matuska static int sha2_create_ctx_template(crypto_mechanism_t *, crypto_key_t *, 87c03c5b1cSMartin Matuska crypto_spi_ctx_template_t *, size_t *); 88eda14cbcSMatt Macy static int sha2_free_context(crypto_ctx_t *); 89eda14cbcSMatt Macy 90e92ffd9bSMartin Matuska static const crypto_ctx_ops_t sha2_ctx_ops = { 91eda14cbcSMatt Macy .create_ctx_template = sha2_create_ctx_template, 92eda14cbcSMatt Macy .free_context = sha2_free_context 93eda14cbcSMatt Macy }; 94eda14cbcSMatt Macy 95c03c5b1cSMartin Matuska static const crypto_ops_t sha2_crypto_ops = { 96eda14cbcSMatt Macy NULL, 97eda14cbcSMatt Macy &sha2_mac_ops, 98c03c5b1cSMartin Matuska &sha2_ctx_ops, 99c03c5b1cSMartin Matuska }; 100eda14cbcSMatt Macy 101c03c5b1cSMartin Matuska static const crypto_provider_info_t sha2_prov_info = { 102eda14cbcSMatt Macy "SHA2 Software Provider", 103eda14cbcSMatt Macy &sha2_crypto_ops, 104eda14cbcSMatt Macy sizeof (sha2_mech_info_tab) / sizeof (crypto_mech_info_t), 105eda14cbcSMatt Macy sha2_mech_info_tab 106c03c5b1cSMartin Matuska }; 107eda14cbcSMatt Macy 108eda14cbcSMatt Macy static crypto_kcf_provider_handle_t sha2_prov_handle = 0; 109eda14cbcSMatt Macy 110eda14cbcSMatt Macy int 111eda14cbcSMatt Macy sha2_mod_init(void) 112eda14cbcSMatt Macy { 113eda14cbcSMatt Macy int ret; 114eda14cbcSMatt Macy 115eda14cbcSMatt Macy /* 116eda14cbcSMatt Macy * Register with KCF. If the registration fails, log an 117eda14cbcSMatt Macy * error but do not uninstall the module, since the functionality 118eda14cbcSMatt Macy * provided by misc/sha2 should still be available. 119eda14cbcSMatt Macy */ 120eda14cbcSMatt Macy if ((ret = crypto_register_provider(&sha2_prov_info, 121eda14cbcSMatt Macy &sha2_prov_handle)) != CRYPTO_SUCCESS) 122eda14cbcSMatt Macy cmn_err(CE_WARN, "sha2 _init: " 123eda14cbcSMatt Macy "crypto_register_provider() failed (0x%x)", ret); 124eda14cbcSMatt Macy 125eda14cbcSMatt Macy return (0); 126eda14cbcSMatt Macy } 127eda14cbcSMatt Macy 128eda14cbcSMatt Macy int 129eda14cbcSMatt Macy sha2_mod_fini(void) 130eda14cbcSMatt Macy { 131e92ffd9bSMartin Matuska int ret = 0; 132eda14cbcSMatt Macy 133eda14cbcSMatt Macy if (sha2_prov_handle != 0) { 134eda14cbcSMatt Macy if ((ret = crypto_unregister_provider(sha2_prov_handle)) != 135eda14cbcSMatt Macy CRYPTO_SUCCESS) { 136eda14cbcSMatt Macy cmn_err(CE_WARN, 137eda14cbcSMatt Macy "sha2 _fini: crypto_unregister_provider() " 138eda14cbcSMatt Macy "failed (0x%x)", ret); 139eda14cbcSMatt Macy return (EBUSY); 140eda14cbcSMatt Macy } 141eda14cbcSMatt Macy sha2_prov_handle = 0; 142eda14cbcSMatt Macy } 143eda14cbcSMatt Macy 144e92ffd9bSMartin Matuska return (ret); 145eda14cbcSMatt Macy } 146eda14cbcSMatt Macy 147eda14cbcSMatt Macy /* 148eda14cbcSMatt Macy * Helper SHA2 digest update function for uio data. 149eda14cbcSMatt Macy */ 150eda14cbcSMatt Macy static int 151eda14cbcSMatt Macy sha2_digest_update_uio(SHA2_CTX *sha2_ctx, crypto_data_t *data) 152eda14cbcSMatt Macy { 153eda14cbcSMatt Macy off_t offset = data->cd_offset; 154eda14cbcSMatt Macy size_t length = data->cd_length; 155eda14cbcSMatt Macy uint_t vec_idx = 0; 156eda14cbcSMatt Macy size_t cur_len; 157eda14cbcSMatt Macy 158eda14cbcSMatt Macy /* we support only kernel buffer */ 159184c1b94SMartin Matuska if (zfs_uio_segflg(data->cd_uio) != UIO_SYSSPACE) 160eda14cbcSMatt Macy return (CRYPTO_ARGUMENTS_BAD); 161eda14cbcSMatt Macy 162eda14cbcSMatt Macy /* 163eda14cbcSMatt Macy * Jump to the first iovec containing data to be 164eda14cbcSMatt Macy * digested. 165eda14cbcSMatt Macy */ 166184c1b94SMartin Matuska offset = zfs_uio_index_at_offset(data->cd_uio, offset, &vec_idx); 167184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(data->cd_uio)) { 168eda14cbcSMatt Macy /* 169eda14cbcSMatt Macy * The caller specified an offset that is larger than the 170eda14cbcSMatt Macy * total size of the buffers it provided. 171eda14cbcSMatt Macy */ 172eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE); 173eda14cbcSMatt Macy } 174eda14cbcSMatt Macy 175eda14cbcSMatt Macy /* 176eda14cbcSMatt Macy * Now do the digesting on the iovecs. 177eda14cbcSMatt Macy */ 178184c1b94SMartin Matuska while (vec_idx < zfs_uio_iovcnt(data->cd_uio) && length > 0) { 179184c1b94SMartin Matuska cur_len = MIN(zfs_uio_iovlen(data->cd_uio, vec_idx) - 180eda14cbcSMatt Macy offset, length); 181eda14cbcSMatt Macy 182184c1b94SMartin Matuska SHA2Update(sha2_ctx, (uint8_t *)zfs_uio_iovbase(data->cd_uio, 183eda14cbcSMatt Macy vec_idx) + offset, cur_len); 184eda14cbcSMatt Macy length -= cur_len; 185eda14cbcSMatt Macy vec_idx++; 186eda14cbcSMatt Macy offset = 0; 187eda14cbcSMatt Macy } 188eda14cbcSMatt Macy 189184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(data->cd_uio) && length > 0) { 190eda14cbcSMatt Macy /* 191eda14cbcSMatt Macy * The end of the specified iovec's was reached but 192eda14cbcSMatt Macy * the length requested could not be processed, i.e. 193eda14cbcSMatt Macy * The caller requested to digest more data than it provided. 194eda14cbcSMatt Macy */ 195eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE); 196eda14cbcSMatt Macy } 197eda14cbcSMatt Macy 198eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 199eda14cbcSMatt Macy } 200eda14cbcSMatt Macy 201eda14cbcSMatt Macy /* 202eda14cbcSMatt Macy * Helper SHA2 digest final function for uio data. 203eda14cbcSMatt Macy * digest_len is the length of the desired digest. If digest_len 204eda14cbcSMatt Macy * is smaller than the default SHA2 digest length, the caller 205eda14cbcSMatt Macy * must pass a scratch buffer, digest_scratch, which must 206eda14cbcSMatt Macy * be at least the algorithm's digest length bytes. 207eda14cbcSMatt Macy */ 208eda14cbcSMatt Macy static int 209eda14cbcSMatt Macy sha2_digest_final_uio(SHA2_CTX *sha2_ctx, crypto_data_t *digest, 210eda14cbcSMatt Macy ulong_t digest_len, uchar_t *digest_scratch) 211eda14cbcSMatt Macy { 212eda14cbcSMatt Macy off_t offset = digest->cd_offset; 213eda14cbcSMatt Macy uint_t vec_idx = 0; 214eda14cbcSMatt Macy 215eda14cbcSMatt Macy /* we support only kernel buffer */ 216184c1b94SMartin Matuska if (zfs_uio_segflg(digest->cd_uio) != UIO_SYSSPACE) 217eda14cbcSMatt Macy return (CRYPTO_ARGUMENTS_BAD); 218eda14cbcSMatt Macy 219eda14cbcSMatt Macy /* 220eda14cbcSMatt Macy * Jump to the first iovec containing ptr to the digest to 221eda14cbcSMatt Macy * be returned. 222eda14cbcSMatt Macy */ 223184c1b94SMartin Matuska offset = zfs_uio_index_at_offset(digest->cd_uio, offset, &vec_idx); 224184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(digest->cd_uio)) { 225eda14cbcSMatt Macy /* 226eda14cbcSMatt Macy * The caller specified an offset that is 227eda14cbcSMatt Macy * larger than the total size of the buffers 228eda14cbcSMatt Macy * it provided. 229eda14cbcSMatt Macy */ 230eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE); 231eda14cbcSMatt Macy } 232eda14cbcSMatt Macy 233eda14cbcSMatt Macy if (offset + digest_len <= 234184c1b94SMartin Matuska zfs_uio_iovlen(digest->cd_uio, vec_idx)) { 235eda14cbcSMatt Macy /* 236eda14cbcSMatt Macy * The computed SHA2 digest will fit in the current 237eda14cbcSMatt Macy * iovec. 238eda14cbcSMatt Macy */ 239*75e1fea6SMartin Matuska ASSERT3U(sha2_ctx->algotype, ==, SHA512_HMAC_MECH_INFO_TYPE); 240*75e1fea6SMartin Matuska if (digest_len != SHA512_DIGEST_LENGTH) { 241eda14cbcSMatt Macy /* 242eda14cbcSMatt Macy * The caller requested a short digest. Digest 243eda14cbcSMatt Macy * into a scratch buffer and return to 244eda14cbcSMatt Macy * the user only what was requested. 245eda14cbcSMatt Macy */ 246eda14cbcSMatt Macy SHA2Final(digest_scratch, sha2_ctx); 247eda14cbcSMatt Macy 248da5137abSMartin Matuska memcpy((uchar_t *) 249184c1b94SMartin Matuska zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset, 250da5137abSMartin Matuska digest_scratch, digest_len); 251eda14cbcSMatt Macy } else { 252184c1b94SMartin Matuska SHA2Final((uchar_t *)zfs_uio_iovbase(digest-> 253eda14cbcSMatt Macy cd_uio, vec_idx) + offset, 254eda14cbcSMatt Macy sha2_ctx); 255eda14cbcSMatt Macy 256eda14cbcSMatt Macy } 257eda14cbcSMatt Macy } else { 258eda14cbcSMatt Macy /* 259eda14cbcSMatt Macy * The computed digest will be crossing one or more iovec's. 260eda14cbcSMatt Macy * This is bad performance-wise but we need to support it. 261eda14cbcSMatt Macy * Allocate a small scratch buffer on the stack and 262eda14cbcSMatt Macy * copy it piece meal to the specified digest iovec's. 263eda14cbcSMatt Macy */ 264eda14cbcSMatt Macy uchar_t digest_tmp[SHA512_DIGEST_LENGTH]; 265eda14cbcSMatt Macy off_t scratch_offset = 0; 266eda14cbcSMatt Macy size_t length = digest_len; 267eda14cbcSMatt Macy size_t cur_len; 268eda14cbcSMatt Macy 269eda14cbcSMatt Macy SHA2Final(digest_tmp, sha2_ctx); 270eda14cbcSMatt Macy 271184c1b94SMartin Matuska while (vec_idx < zfs_uio_iovcnt(digest->cd_uio) && length > 0) { 272eda14cbcSMatt Macy cur_len = 273184c1b94SMartin Matuska MIN(zfs_uio_iovlen(digest->cd_uio, vec_idx) - 274eda14cbcSMatt Macy offset, length); 275da5137abSMartin Matuska memcpy( 276184c1b94SMartin Matuska zfs_uio_iovbase(digest->cd_uio, vec_idx) + offset, 277da5137abSMartin Matuska digest_tmp + scratch_offset, 278eda14cbcSMatt Macy cur_len); 279eda14cbcSMatt Macy 280eda14cbcSMatt Macy length -= cur_len; 281eda14cbcSMatt Macy vec_idx++; 282eda14cbcSMatt Macy scratch_offset += cur_len; 283eda14cbcSMatt Macy offset = 0; 284eda14cbcSMatt Macy } 285eda14cbcSMatt Macy 286184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(digest->cd_uio) && length > 0) { 287eda14cbcSMatt Macy /* 288eda14cbcSMatt Macy * The end of the specified iovec's was reached but 289eda14cbcSMatt Macy * the length requested could not be processed, i.e. 290eda14cbcSMatt Macy * The caller requested to digest more data than it 291eda14cbcSMatt Macy * provided. 292eda14cbcSMatt Macy */ 293eda14cbcSMatt Macy return (CRYPTO_DATA_LEN_RANGE); 294eda14cbcSMatt Macy } 295eda14cbcSMatt Macy } 296eda14cbcSMatt Macy 297eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 298eda14cbcSMatt Macy } 299eda14cbcSMatt Macy 300eda14cbcSMatt Macy /* 301eda14cbcSMatt Macy * KCF software provider mac entry points. 302eda14cbcSMatt Macy * 303eda14cbcSMatt Macy * SHA2 HMAC is: SHA2(key XOR opad, SHA2(key XOR ipad, text)) 304eda14cbcSMatt Macy * 305eda14cbcSMatt Macy * Init: 306eda14cbcSMatt Macy * The initialization routine initializes what we denote 307eda14cbcSMatt Macy * as the inner and outer contexts by doing 308eda14cbcSMatt Macy * - for inner context: SHA2(key XOR ipad) 309eda14cbcSMatt Macy * - for outer context: SHA2(key XOR opad) 310eda14cbcSMatt Macy * 311eda14cbcSMatt Macy * Update: 312eda14cbcSMatt Macy * Each subsequent SHA2 HMAC update will result in an 313eda14cbcSMatt Macy * update of the inner context with the specified data. 314eda14cbcSMatt Macy * 315eda14cbcSMatt Macy * Final: 316eda14cbcSMatt Macy * The SHA2 HMAC final will do a SHA2 final operation on the 317eda14cbcSMatt Macy * inner context, and the resulting digest will be used 318eda14cbcSMatt Macy * as the data for an update on the outer context. Last 319eda14cbcSMatt Macy * but not least, a SHA2 final on the outer context will 320eda14cbcSMatt Macy * be performed to obtain the SHA2 HMAC digest to return 321eda14cbcSMatt Macy * to the user. 322eda14cbcSMatt Macy */ 323eda14cbcSMatt Macy 324eda14cbcSMatt Macy /* 325eda14cbcSMatt Macy * Initialize a SHA2-HMAC context. 326eda14cbcSMatt Macy */ 327eda14cbcSMatt Macy static void 328eda14cbcSMatt Macy sha2_mac_init_ctx(sha2_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes) 329eda14cbcSMatt Macy { 330da5137abSMartin Matuska uint64_t ipad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)] = {0}; 331da5137abSMartin Matuska uint64_t opad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)] = {0}; 332eda14cbcSMatt Macy int i, block_size, blocks_per_int64; 333eda14cbcSMatt Macy 334eda14cbcSMatt Macy /* Determine the block size */ 335*75e1fea6SMartin Matuska ASSERT3U(ctx->hc_mech_type, ==, SHA512_HMAC_MECH_INFO_TYPE); 336eda14cbcSMatt Macy block_size = SHA512_HMAC_BLOCK_SIZE; 337eda14cbcSMatt Macy blocks_per_int64 = SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t); 338eda14cbcSMatt Macy 339da5137abSMartin Matuska (void) memset(ipad, 0, block_size); 340da5137abSMartin Matuska (void) memset(opad, 0, block_size); 341c03c5b1cSMartin Matuska 342c03c5b1cSMartin Matuska if (keyval != NULL) { 343da5137abSMartin Matuska (void) memcpy(ipad, keyval, length_in_bytes); 344da5137abSMartin Matuska (void) memcpy(opad, keyval, length_in_bytes); 345c03c5b1cSMartin Matuska } else { 346c03c5b1cSMartin Matuska ASSERT0(length_in_bytes); 347c03c5b1cSMartin Matuska } 348eda14cbcSMatt Macy 349eda14cbcSMatt Macy /* XOR key with ipad (0x36) and opad (0x5c) */ 350eda14cbcSMatt Macy for (i = 0; i < blocks_per_int64; i ++) { 351eda14cbcSMatt Macy ipad[i] ^= 0x3636363636363636; 352eda14cbcSMatt Macy opad[i] ^= 0x5c5c5c5c5c5c5c5c; 353eda14cbcSMatt Macy } 354eda14cbcSMatt Macy 355eda14cbcSMatt Macy /* perform SHA2 on ipad */ 356eda14cbcSMatt Macy SHA2Init(ctx->hc_mech_type, &ctx->hc_icontext); 357eda14cbcSMatt Macy SHA2Update(&ctx->hc_icontext, (uint8_t *)ipad, block_size); 358eda14cbcSMatt Macy 359eda14cbcSMatt Macy /* perform SHA2 on opad */ 360eda14cbcSMatt Macy SHA2Init(ctx->hc_mech_type, &ctx->hc_ocontext); 361eda14cbcSMatt Macy SHA2Update(&ctx->hc_ocontext, (uint8_t *)opad, block_size); 362eda14cbcSMatt Macy } 363eda14cbcSMatt Macy 364eda14cbcSMatt Macy /* 365eda14cbcSMatt Macy */ 366eda14cbcSMatt Macy static int 367eda14cbcSMatt Macy sha2_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism, 368c03c5b1cSMartin Matuska crypto_key_t *key, crypto_spi_ctx_template_t ctx_template) 369eda14cbcSMatt Macy { 370eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS; 371eda14cbcSMatt Macy uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 372eda14cbcSMatt Macy uint_t sha_digest_len, sha_hmac_block_size; 373eda14cbcSMatt Macy 374eda14cbcSMatt Macy /* 375eda14cbcSMatt Macy * Set the digest length and block size to values appropriate to the 376eda14cbcSMatt Macy * mechanism 377eda14cbcSMatt Macy */ 378eda14cbcSMatt Macy switch (mechanism->cm_type) { 379eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE: 380eda14cbcSMatt Macy sha_digest_len = SHA512_DIGEST_LENGTH; 381eda14cbcSMatt Macy sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 382eda14cbcSMatt Macy break; 383eda14cbcSMatt Macy default: 384eda14cbcSMatt Macy return (CRYPTO_MECHANISM_INVALID); 385eda14cbcSMatt Macy } 386eda14cbcSMatt Macy 387c03c5b1cSMartin Matuska ctx->cc_provider_private = 388c03c5b1cSMartin Matuska kmem_alloc(sizeof (sha2_hmac_ctx_t), KM_SLEEP); 389eda14cbcSMatt Macy if (ctx->cc_provider_private == NULL) 390eda14cbcSMatt Macy return (CRYPTO_HOST_MEMORY); 391eda14cbcSMatt Macy 392eda14cbcSMatt Macy PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type; 393eda14cbcSMatt Macy if (ctx_template != NULL) { 394eda14cbcSMatt Macy /* reuse context template */ 395da5137abSMartin Matuska memcpy(PROV_SHA2_HMAC_CTX(ctx), ctx_template, 396eda14cbcSMatt Macy sizeof (sha2_hmac_ctx_t)); 397eda14cbcSMatt Macy } else { 398eda14cbcSMatt Macy /* no context template, compute context */ 399eda14cbcSMatt Macy if (keylen_in_bytes > sha_hmac_block_size) { 400eda14cbcSMatt Macy uchar_t digested_key[SHA512_DIGEST_LENGTH]; 401eda14cbcSMatt Macy sha2_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private; 402eda14cbcSMatt Macy 403eda14cbcSMatt Macy /* 404eda14cbcSMatt Macy * Hash the passed-in key to get a smaller key. 405eda14cbcSMatt Macy * The inner context is used since it hasn't been 406eda14cbcSMatt Macy * initialized yet. 407eda14cbcSMatt Macy */ 408eda14cbcSMatt Macy PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 409eda14cbcSMatt Macy &hmac_ctx->hc_icontext, 410eda14cbcSMatt Macy key->ck_data, keylen_in_bytes, digested_key); 411eda14cbcSMatt Macy sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx), 412eda14cbcSMatt Macy digested_key, sha_digest_len); 413eda14cbcSMatt Macy } else { 414eda14cbcSMatt Macy sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx), 415eda14cbcSMatt Macy key->ck_data, keylen_in_bytes); 416eda14cbcSMatt Macy } 417eda14cbcSMatt Macy } 418eda14cbcSMatt Macy 419eda14cbcSMatt Macy if (ret != CRYPTO_SUCCESS) { 420da5137abSMartin Matuska memset(ctx->cc_provider_private, 0, sizeof (sha2_hmac_ctx_t)); 421eda14cbcSMatt Macy kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t)); 422eda14cbcSMatt Macy ctx->cc_provider_private = NULL; 423eda14cbcSMatt Macy } 424eda14cbcSMatt Macy 425eda14cbcSMatt Macy return (ret); 426eda14cbcSMatt Macy } 427eda14cbcSMatt Macy 428eda14cbcSMatt Macy static int 429c03c5b1cSMartin Matuska sha2_mac_update(crypto_ctx_t *ctx, crypto_data_t *data) 430eda14cbcSMatt Macy { 431eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS; 432eda14cbcSMatt Macy 433eda14cbcSMatt Macy ASSERT(ctx->cc_provider_private != NULL); 434eda14cbcSMatt Macy 435eda14cbcSMatt Macy /* 436eda14cbcSMatt Macy * Do a SHA2 update of the inner context using the specified 437eda14cbcSMatt Macy * data. 438eda14cbcSMatt Macy */ 439eda14cbcSMatt Macy switch (data->cd_format) { 440eda14cbcSMatt Macy case CRYPTO_DATA_RAW: 441eda14cbcSMatt Macy SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, 442eda14cbcSMatt Macy (uint8_t *)data->cd_raw.iov_base + data->cd_offset, 443eda14cbcSMatt Macy data->cd_length); 444eda14cbcSMatt Macy break; 445eda14cbcSMatt Macy case CRYPTO_DATA_UIO: 446eda14cbcSMatt Macy ret = sha2_digest_update_uio( 447eda14cbcSMatt Macy &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data); 448eda14cbcSMatt Macy break; 449eda14cbcSMatt Macy default: 450eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD; 451eda14cbcSMatt Macy } 452eda14cbcSMatt Macy 453eda14cbcSMatt Macy return (ret); 454eda14cbcSMatt Macy } 455eda14cbcSMatt Macy 456eda14cbcSMatt Macy static int 457c03c5b1cSMartin Matuska sha2_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac) 458eda14cbcSMatt Macy { 459eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS; 460eda14cbcSMatt Macy uchar_t digest[SHA512_DIGEST_LENGTH]; 461eda14cbcSMatt Macy uint32_t digest_len, sha_digest_len; 462eda14cbcSMatt Macy 463eda14cbcSMatt Macy ASSERT(ctx->cc_provider_private != NULL); 464eda14cbcSMatt Macy 465eda14cbcSMatt Macy /* Set the digest lengths to values appropriate to the mechanism */ 466eda14cbcSMatt Macy switch (PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type) { 467eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE: 468eda14cbcSMatt Macy sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 469eda14cbcSMatt Macy break; 470eda14cbcSMatt Macy default: 471eda14cbcSMatt Macy return (CRYPTO_ARGUMENTS_BAD); 472eda14cbcSMatt Macy } 473eda14cbcSMatt Macy 474eda14cbcSMatt Macy /* 475eda14cbcSMatt Macy * We need to just return the length needed to store the output. 476eda14cbcSMatt Macy * We should not destroy the context for the following cases. 477eda14cbcSMatt Macy */ 478eda14cbcSMatt Macy if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) { 479eda14cbcSMatt Macy mac->cd_length = digest_len; 480eda14cbcSMatt Macy return (CRYPTO_BUFFER_TOO_SMALL); 481eda14cbcSMatt Macy } 482eda14cbcSMatt Macy 483eda14cbcSMatt Macy /* 484eda14cbcSMatt Macy * Do a SHA2 final on the inner context. 485eda14cbcSMatt Macy */ 486eda14cbcSMatt Macy SHA2Final(digest, &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext); 487eda14cbcSMatt Macy 488eda14cbcSMatt Macy /* 489eda14cbcSMatt Macy * Do a SHA2 update on the outer context, feeding the inner 490eda14cbcSMatt Macy * digest as data. 491eda14cbcSMatt Macy */ 492eda14cbcSMatt Macy SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, digest, 493eda14cbcSMatt Macy sha_digest_len); 494eda14cbcSMatt Macy 495eda14cbcSMatt Macy /* 496eda14cbcSMatt Macy * Do a SHA2 final on the outer context, storing the computing 497eda14cbcSMatt Macy * digest in the users buffer. 498eda14cbcSMatt Macy */ 499eda14cbcSMatt Macy switch (mac->cd_format) { 500eda14cbcSMatt Macy case CRYPTO_DATA_RAW: 501eda14cbcSMatt Macy if (digest_len != sha_digest_len) { 502eda14cbcSMatt Macy /* 503eda14cbcSMatt Macy * The caller requested a short digest. Digest 504eda14cbcSMatt Macy * into a scratch buffer and return to 505eda14cbcSMatt Macy * the user only what was requested. 506eda14cbcSMatt Macy */ 507eda14cbcSMatt Macy SHA2Final(digest, 508eda14cbcSMatt Macy &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext); 509da5137abSMartin Matuska memcpy((unsigned char *)mac->cd_raw.iov_base + 510da5137abSMartin Matuska mac->cd_offset, digest, digest_len); 511eda14cbcSMatt Macy } else { 512eda14cbcSMatt Macy SHA2Final((unsigned char *)mac->cd_raw.iov_base + 513eda14cbcSMatt Macy mac->cd_offset, 514eda14cbcSMatt Macy &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext); 515eda14cbcSMatt Macy } 516eda14cbcSMatt Macy break; 517eda14cbcSMatt Macy case CRYPTO_DATA_UIO: 518eda14cbcSMatt Macy ret = sha2_digest_final_uio( 519eda14cbcSMatt Macy &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac, 520eda14cbcSMatt Macy digest_len, digest); 521eda14cbcSMatt Macy break; 522eda14cbcSMatt Macy default: 523eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD; 524eda14cbcSMatt Macy } 525eda14cbcSMatt Macy 526eda14cbcSMatt Macy if (ret == CRYPTO_SUCCESS) 527eda14cbcSMatt Macy mac->cd_length = digest_len; 528eda14cbcSMatt Macy else 529eda14cbcSMatt Macy mac->cd_length = 0; 530eda14cbcSMatt Macy 531da5137abSMartin Matuska memset(ctx->cc_provider_private, 0, sizeof (sha2_hmac_ctx_t)); 532eda14cbcSMatt Macy kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t)); 533eda14cbcSMatt Macy ctx->cc_provider_private = NULL; 534eda14cbcSMatt Macy 535eda14cbcSMatt Macy return (ret); 536eda14cbcSMatt Macy } 537eda14cbcSMatt Macy 538eda14cbcSMatt Macy #define SHA2_MAC_UPDATE(data, ctx, ret) { \ 539eda14cbcSMatt Macy switch (data->cd_format) { \ 540eda14cbcSMatt Macy case CRYPTO_DATA_RAW: \ 541eda14cbcSMatt Macy SHA2Update(&(ctx).hc_icontext, \ 542eda14cbcSMatt Macy (uint8_t *)data->cd_raw.iov_base + \ 543eda14cbcSMatt Macy data->cd_offset, data->cd_length); \ 544eda14cbcSMatt Macy break; \ 545eda14cbcSMatt Macy case CRYPTO_DATA_UIO: \ 546eda14cbcSMatt Macy ret = sha2_digest_update_uio(&(ctx).hc_icontext, data); \ 547eda14cbcSMatt Macy break; \ 548eda14cbcSMatt Macy default: \ 549eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD; \ 550eda14cbcSMatt Macy } \ 551eda14cbcSMatt Macy } 552eda14cbcSMatt Macy 553eda14cbcSMatt Macy static int 554c03c5b1cSMartin Matuska sha2_mac_atomic(crypto_mechanism_t *mechanism, 555eda14cbcSMatt Macy crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 556c03c5b1cSMartin Matuska crypto_spi_ctx_template_t ctx_template) 557eda14cbcSMatt Macy { 558eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS; 559eda14cbcSMatt Macy uchar_t digest[SHA512_DIGEST_LENGTH]; 560eda14cbcSMatt Macy sha2_hmac_ctx_t sha2_hmac_ctx; 561eda14cbcSMatt Macy uint32_t sha_digest_len, digest_len, sha_hmac_block_size; 562eda14cbcSMatt Macy uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 563eda14cbcSMatt Macy 564eda14cbcSMatt Macy /* 565eda14cbcSMatt Macy * Set the digest length and block size to values appropriate to the 566eda14cbcSMatt Macy * mechanism 567eda14cbcSMatt Macy */ 568eda14cbcSMatt Macy switch (mechanism->cm_type) { 569eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE: 570eda14cbcSMatt Macy sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 571eda14cbcSMatt Macy sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 572eda14cbcSMatt Macy break; 573eda14cbcSMatt Macy default: 574eda14cbcSMatt Macy return (CRYPTO_MECHANISM_INVALID); 575eda14cbcSMatt Macy } 576eda14cbcSMatt Macy 577eda14cbcSMatt Macy if (ctx_template != NULL) { 578eda14cbcSMatt Macy /* reuse context template */ 579da5137abSMartin Matuska memcpy(&sha2_hmac_ctx, ctx_template, sizeof (sha2_hmac_ctx_t)); 580eda14cbcSMatt Macy } else { 581eda14cbcSMatt Macy sha2_hmac_ctx.hc_mech_type = mechanism->cm_type; 582eda14cbcSMatt Macy /* no context template, initialize context */ 583eda14cbcSMatt Macy if (keylen_in_bytes > sha_hmac_block_size) { 584eda14cbcSMatt Macy /* 585eda14cbcSMatt Macy * Hash the passed-in key to get a smaller key. 586eda14cbcSMatt Macy * The inner context is used since it hasn't been 587eda14cbcSMatt Macy * initialized yet. 588eda14cbcSMatt Macy */ 589eda14cbcSMatt Macy PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 590eda14cbcSMatt Macy &sha2_hmac_ctx.hc_icontext, 591eda14cbcSMatt Macy key->ck_data, keylen_in_bytes, digest); 592eda14cbcSMatt Macy sha2_mac_init_ctx(&sha2_hmac_ctx, digest, 593eda14cbcSMatt Macy sha_digest_len); 594eda14cbcSMatt Macy } else { 595eda14cbcSMatt Macy sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data, 596eda14cbcSMatt Macy keylen_in_bytes); 597eda14cbcSMatt Macy } 598eda14cbcSMatt Macy } 599eda14cbcSMatt Macy 600eda14cbcSMatt Macy /* do a SHA2 update of the inner context using the specified data */ 601eda14cbcSMatt Macy SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret); 602eda14cbcSMatt Macy if (ret != CRYPTO_SUCCESS) 603eda14cbcSMatt Macy /* the update failed, free context and bail */ 604eda14cbcSMatt Macy goto bail; 605eda14cbcSMatt Macy 606eda14cbcSMatt Macy /* 607eda14cbcSMatt Macy * Do a SHA2 final on the inner context. 608eda14cbcSMatt Macy */ 609eda14cbcSMatt Macy SHA2Final(digest, &sha2_hmac_ctx.hc_icontext); 610eda14cbcSMatt Macy 611eda14cbcSMatt Macy /* 612eda14cbcSMatt Macy * Do an SHA2 update on the outer context, feeding the inner 613eda14cbcSMatt Macy * digest as data. 614eda14cbcSMatt Macy */ 615*75e1fea6SMartin Matuska ASSERT3U(mechanism->cm_type, ==, SHA512_HMAC_MECH_INFO_TYPE); 616eda14cbcSMatt Macy SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len); 617eda14cbcSMatt Macy 618eda14cbcSMatt Macy /* 619eda14cbcSMatt Macy * Do a SHA2 final on the outer context, storing the computed 620eda14cbcSMatt Macy * digest in the users buffer. 621eda14cbcSMatt Macy */ 622eda14cbcSMatt Macy switch (mac->cd_format) { 623eda14cbcSMatt Macy case CRYPTO_DATA_RAW: 624eda14cbcSMatt Macy if (digest_len != sha_digest_len) { 625eda14cbcSMatt Macy /* 626eda14cbcSMatt Macy * The caller requested a short digest. Digest 627eda14cbcSMatt Macy * into a scratch buffer and return to 628eda14cbcSMatt Macy * the user only what was requested. 629eda14cbcSMatt Macy */ 630eda14cbcSMatt Macy SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext); 631da5137abSMartin Matuska memcpy((unsigned char *)mac->cd_raw.iov_base + 632da5137abSMartin Matuska mac->cd_offset, digest, digest_len); 633eda14cbcSMatt Macy } else { 634eda14cbcSMatt Macy SHA2Final((unsigned char *)mac->cd_raw.iov_base + 635eda14cbcSMatt Macy mac->cd_offset, &sha2_hmac_ctx.hc_ocontext); 636eda14cbcSMatt Macy } 637eda14cbcSMatt Macy break; 638eda14cbcSMatt Macy case CRYPTO_DATA_UIO: 639eda14cbcSMatt Macy ret = sha2_digest_final_uio(&sha2_hmac_ctx.hc_ocontext, mac, 640eda14cbcSMatt Macy digest_len, digest); 641eda14cbcSMatt Macy break; 642eda14cbcSMatt Macy default: 643eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD; 644eda14cbcSMatt Macy } 645eda14cbcSMatt Macy 646eda14cbcSMatt Macy if (ret == CRYPTO_SUCCESS) { 647eda14cbcSMatt Macy mac->cd_length = digest_len; 648eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 649eda14cbcSMatt Macy } 650eda14cbcSMatt Macy bail: 651da5137abSMartin Matuska memset(&sha2_hmac_ctx, 0, sizeof (sha2_hmac_ctx_t)); 652eda14cbcSMatt Macy mac->cd_length = 0; 653eda14cbcSMatt Macy return (ret); 654eda14cbcSMatt Macy } 655eda14cbcSMatt Macy 656eda14cbcSMatt Macy static int 657c03c5b1cSMartin Matuska sha2_mac_verify_atomic(crypto_mechanism_t *mechanism, 658eda14cbcSMatt Macy crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac, 659c03c5b1cSMartin Matuska crypto_spi_ctx_template_t ctx_template) 660eda14cbcSMatt Macy { 661eda14cbcSMatt Macy int ret = CRYPTO_SUCCESS; 662eda14cbcSMatt Macy uchar_t digest[SHA512_DIGEST_LENGTH]; 663eda14cbcSMatt Macy sha2_hmac_ctx_t sha2_hmac_ctx; 664eda14cbcSMatt Macy uint32_t sha_digest_len, digest_len, sha_hmac_block_size; 665eda14cbcSMatt Macy uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 666eda14cbcSMatt Macy 667eda14cbcSMatt Macy /* 668eda14cbcSMatt Macy * Set the digest length and block size to values appropriate to the 669eda14cbcSMatt Macy * mechanism 670eda14cbcSMatt Macy */ 671eda14cbcSMatt Macy switch (mechanism->cm_type) { 672eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE: 673eda14cbcSMatt Macy sha_digest_len = digest_len = SHA512_DIGEST_LENGTH; 674eda14cbcSMatt Macy sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 675eda14cbcSMatt Macy break; 676eda14cbcSMatt Macy default: 677eda14cbcSMatt Macy return (CRYPTO_MECHANISM_INVALID); 678eda14cbcSMatt Macy } 679eda14cbcSMatt Macy 680eda14cbcSMatt Macy if (ctx_template != NULL) { 681eda14cbcSMatt Macy /* reuse context template */ 682da5137abSMartin Matuska memcpy(&sha2_hmac_ctx, ctx_template, sizeof (sha2_hmac_ctx_t)); 683eda14cbcSMatt Macy } else { 684eda14cbcSMatt Macy sha2_hmac_ctx.hc_mech_type = mechanism->cm_type; 685eda14cbcSMatt Macy /* no context template, initialize context */ 686eda14cbcSMatt Macy if (keylen_in_bytes > sha_hmac_block_size) { 687eda14cbcSMatt Macy /* 688eda14cbcSMatt Macy * Hash the passed-in key to get a smaller key. 689eda14cbcSMatt Macy * The inner context is used since it hasn't been 690eda14cbcSMatt Macy * initialized yet. 691eda14cbcSMatt Macy */ 692eda14cbcSMatt Macy PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 693eda14cbcSMatt Macy &sha2_hmac_ctx.hc_icontext, 694eda14cbcSMatt Macy key->ck_data, keylen_in_bytes, digest); 695eda14cbcSMatt Macy sha2_mac_init_ctx(&sha2_hmac_ctx, digest, 696eda14cbcSMatt Macy sha_digest_len); 697eda14cbcSMatt Macy } else { 698eda14cbcSMatt Macy sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data, 699eda14cbcSMatt Macy keylen_in_bytes); 700eda14cbcSMatt Macy } 701eda14cbcSMatt Macy } 702eda14cbcSMatt Macy 703eda14cbcSMatt Macy if (mac->cd_length != digest_len) { 704eda14cbcSMatt Macy ret = CRYPTO_INVALID_MAC; 705eda14cbcSMatt Macy goto bail; 706eda14cbcSMatt Macy } 707eda14cbcSMatt Macy 708eda14cbcSMatt Macy /* do a SHA2 update of the inner context using the specified data */ 709eda14cbcSMatt Macy SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret); 710eda14cbcSMatt Macy if (ret != CRYPTO_SUCCESS) 711eda14cbcSMatt Macy /* the update failed, free context and bail */ 712eda14cbcSMatt Macy goto bail; 713eda14cbcSMatt Macy 714eda14cbcSMatt Macy /* do a SHA2 final on the inner context */ 715eda14cbcSMatt Macy SHA2Final(digest, &sha2_hmac_ctx.hc_icontext); 716eda14cbcSMatt Macy 717eda14cbcSMatt Macy /* 718eda14cbcSMatt Macy * Do an SHA2 update on the outer context, feeding the inner 719eda14cbcSMatt Macy * digest as data. 720eda14cbcSMatt Macy */ 721*75e1fea6SMartin Matuska ASSERT3U(mechanism->cm_type, ==, SHA512_HMAC_MECH_INFO_TYPE); 722eda14cbcSMatt Macy SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len); 723eda14cbcSMatt Macy 724eda14cbcSMatt Macy /* 725eda14cbcSMatt Macy * Do a SHA2 final on the outer context, storing the computed 726eda14cbcSMatt Macy * digest in the users buffer. 727eda14cbcSMatt Macy */ 728eda14cbcSMatt Macy SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext); 729eda14cbcSMatt Macy 730eda14cbcSMatt Macy /* 731eda14cbcSMatt Macy * Compare the computed digest against the expected digest passed 732eda14cbcSMatt Macy * as argument. 733eda14cbcSMatt Macy */ 734eda14cbcSMatt Macy 735eda14cbcSMatt Macy switch (mac->cd_format) { 736eda14cbcSMatt Macy 737eda14cbcSMatt Macy case CRYPTO_DATA_RAW: 738da5137abSMartin Matuska if (memcmp(digest, (unsigned char *)mac->cd_raw.iov_base + 739eda14cbcSMatt Macy mac->cd_offset, digest_len) != 0) 740eda14cbcSMatt Macy ret = CRYPTO_INVALID_MAC; 741eda14cbcSMatt Macy break; 742eda14cbcSMatt Macy 743eda14cbcSMatt Macy case CRYPTO_DATA_UIO: { 744eda14cbcSMatt Macy off_t offset = mac->cd_offset; 745eda14cbcSMatt Macy uint_t vec_idx = 0; 746eda14cbcSMatt Macy off_t scratch_offset = 0; 747eda14cbcSMatt Macy size_t length = digest_len; 748eda14cbcSMatt Macy size_t cur_len; 749eda14cbcSMatt Macy 750eda14cbcSMatt Macy /* we support only kernel buffer */ 751184c1b94SMartin Matuska if (zfs_uio_segflg(mac->cd_uio) != UIO_SYSSPACE) 752eda14cbcSMatt Macy return (CRYPTO_ARGUMENTS_BAD); 753eda14cbcSMatt Macy 754eda14cbcSMatt Macy /* jump to the first iovec containing the expected digest */ 755184c1b94SMartin Matuska offset = zfs_uio_index_at_offset(mac->cd_uio, offset, &vec_idx); 756184c1b94SMartin Matuska if (vec_idx == zfs_uio_iovcnt(mac->cd_uio)) { 757eda14cbcSMatt Macy /* 758eda14cbcSMatt Macy * The caller specified an offset that is 759eda14cbcSMatt Macy * larger than the total size of the buffers 760eda14cbcSMatt Macy * it provided. 761eda14cbcSMatt Macy */ 762eda14cbcSMatt Macy ret = CRYPTO_DATA_LEN_RANGE; 763eda14cbcSMatt Macy break; 764eda14cbcSMatt Macy } 765eda14cbcSMatt Macy 766eda14cbcSMatt Macy /* do the comparison of computed digest vs specified one */ 767184c1b94SMartin Matuska while (vec_idx < zfs_uio_iovcnt(mac->cd_uio) && length > 0) { 768184c1b94SMartin Matuska cur_len = MIN(zfs_uio_iovlen(mac->cd_uio, vec_idx) - 769eda14cbcSMatt Macy offset, length); 770eda14cbcSMatt Macy 771da5137abSMartin Matuska if (memcmp(digest + scratch_offset, 772184c1b94SMartin Matuska zfs_uio_iovbase(mac->cd_uio, vec_idx) + offset, 773eda14cbcSMatt Macy cur_len) != 0) { 774eda14cbcSMatt Macy ret = CRYPTO_INVALID_MAC; 775eda14cbcSMatt Macy break; 776eda14cbcSMatt Macy } 777eda14cbcSMatt Macy 778eda14cbcSMatt Macy length -= cur_len; 779eda14cbcSMatt Macy vec_idx++; 780eda14cbcSMatt Macy scratch_offset += cur_len; 781eda14cbcSMatt Macy offset = 0; 782eda14cbcSMatt Macy } 783eda14cbcSMatt Macy break; 784eda14cbcSMatt Macy } 785eda14cbcSMatt Macy 786eda14cbcSMatt Macy default: 787eda14cbcSMatt Macy ret = CRYPTO_ARGUMENTS_BAD; 788eda14cbcSMatt Macy } 789eda14cbcSMatt Macy 790eda14cbcSMatt Macy return (ret); 791eda14cbcSMatt Macy bail: 792da5137abSMartin Matuska memset(&sha2_hmac_ctx, 0, sizeof (sha2_hmac_ctx_t)); 793eda14cbcSMatt Macy mac->cd_length = 0; 794eda14cbcSMatt Macy return (ret); 795eda14cbcSMatt Macy } 796eda14cbcSMatt Macy 797eda14cbcSMatt Macy /* 798eda14cbcSMatt Macy * KCF software provider context management entry points. 799eda14cbcSMatt Macy */ 800eda14cbcSMatt Macy 801eda14cbcSMatt Macy static int 802c03c5b1cSMartin Matuska sha2_create_ctx_template(crypto_mechanism_t *mechanism, crypto_key_t *key, 803c03c5b1cSMartin Matuska crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size) 804eda14cbcSMatt Macy { 805eda14cbcSMatt Macy sha2_hmac_ctx_t *sha2_hmac_ctx_tmpl; 806eda14cbcSMatt Macy uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length); 807eda14cbcSMatt Macy uint32_t sha_digest_len, sha_hmac_block_size; 808eda14cbcSMatt Macy 809eda14cbcSMatt Macy /* 810eda14cbcSMatt Macy * Set the digest length and block size to values appropriate to the 811eda14cbcSMatt Macy * mechanism 812eda14cbcSMatt Macy */ 813eda14cbcSMatt Macy switch (mechanism->cm_type) { 814eda14cbcSMatt Macy case SHA512_HMAC_MECH_INFO_TYPE: 815eda14cbcSMatt Macy sha_digest_len = SHA512_DIGEST_LENGTH; 816eda14cbcSMatt Macy sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE; 817eda14cbcSMatt Macy break; 818eda14cbcSMatt Macy default: 819eda14cbcSMatt Macy return (CRYPTO_MECHANISM_INVALID); 820eda14cbcSMatt Macy } 821eda14cbcSMatt Macy 822eda14cbcSMatt Macy /* 823eda14cbcSMatt Macy * Allocate and initialize SHA2 context. 824eda14cbcSMatt Macy */ 825c03c5b1cSMartin Matuska sha2_hmac_ctx_tmpl = kmem_alloc(sizeof (sha2_hmac_ctx_t), KM_SLEEP); 826eda14cbcSMatt Macy if (sha2_hmac_ctx_tmpl == NULL) 827eda14cbcSMatt Macy return (CRYPTO_HOST_MEMORY); 828eda14cbcSMatt Macy 829eda14cbcSMatt Macy sha2_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type; 830eda14cbcSMatt Macy 831eda14cbcSMatt Macy if (keylen_in_bytes > sha_hmac_block_size) { 832eda14cbcSMatt Macy uchar_t digested_key[SHA512_DIGEST_LENGTH]; 833eda14cbcSMatt Macy 834eda14cbcSMatt Macy /* 835eda14cbcSMatt Macy * Hash the passed-in key to get a smaller key. 836eda14cbcSMatt Macy * The inner context is used since it hasn't been 837eda14cbcSMatt Macy * initialized yet. 838eda14cbcSMatt Macy */ 839eda14cbcSMatt Macy PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3, 840eda14cbcSMatt Macy &sha2_hmac_ctx_tmpl->hc_icontext, 841eda14cbcSMatt Macy key->ck_data, keylen_in_bytes, digested_key); 842eda14cbcSMatt Macy sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, digested_key, 843eda14cbcSMatt Macy sha_digest_len); 844eda14cbcSMatt Macy } else { 845eda14cbcSMatt Macy sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, key->ck_data, 846eda14cbcSMatt Macy keylen_in_bytes); 847eda14cbcSMatt Macy } 848eda14cbcSMatt Macy 849eda14cbcSMatt Macy *ctx_template = (crypto_spi_ctx_template_t)sha2_hmac_ctx_tmpl; 850eda14cbcSMatt Macy *ctx_template_size = sizeof (sha2_hmac_ctx_t); 851eda14cbcSMatt Macy 852eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 853eda14cbcSMatt Macy } 854eda14cbcSMatt Macy 855eda14cbcSMatt Macy static int 856eda14cbcSMatt Macy sha2_free_context(crypto_ctx_t *ctx) 857eda14cbcSMatt Macy { 858eda14cbcSMatt Macy uint_t ctx_len; 859eda14cbcSMatt Macy 860eda14cbcSMatt Macy if (ctx->cc_provider_private == NULL) 861eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 862eda14cbcSMatt Macy 863*75e1fea6SMartin Matuska ASSERT3U(PROV_SHA2_CTX(ctx)->sc_mech_type, ==, 864*75e1fea6SMartin Matuska SHA512_HMAC_MECH_INFO_TYPE); 865eda14cbcSMatt Macy ctx_len = sizeof (sha2_hmac_ctx_t); 866eda14cbcSMatt Macy 867da5137abSMartin Matuska memset(ctx->cc_provider_private, 0, ctx_len); 868eda14cbcSMatt Macy kmem_free(ctx->cc_provider_private, ctx_len); 869eda14cbcSMatt Macy ctx->cc_provider_private = NULL; 870eda14cbcSMatt Macy 871eda14cbcSMatt Macy return (CRYPTO_SUCCESS); 872eda14cbcSMatt Macy } 873