11694Sdarrenm /*
21694Sdarrenm * CDDL HEADER START
31694Sdarrenm *
41694Sdarrenm * The contents of this file are subject to the terms of the
51694Sdarrenm * Common Development and Distribution License (the "License").
61694Sdarrenm * You may not use this file except in compliance with the License.
71694Sdarrenm *
81694Sdarrenm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
91694Sdarrenm * or http://www.opensolaris.org/os/licensing.
101694Sdarrenm * See the License for the specific language governing permissions
111694Sdarrenm * and limitations under the License.
121694Sdarrenm *
131694Sdarrenm * When distributing Covered Code, include this CDDL HEADER in each
141694Sdarrenm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
151694Sdarrenm * If applicable, add the following below this CDDL HEADER, with the
161694Sdarrenm * fields enclosed by brackets "[]" replaced with your own identifying
171694Sdarrenm * information: Portions Copyright [yyyy] [name of copyright owner]
181694Sdarrenm *
191694Sdarrenm * CDDL HEADER END
201694Sdarrenm */
211694Sdarrenm
221694Sdarrenm /*
23*11751SAnthony.Scarpino@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
241694Sdarrenm * Use is subject to license terms.
251694Sdarrenm */
261694Sdarrenm
271694Sdarrenm #include <sys/modctl.h>
281694Sdarrenm #include <sys/cmn_err.h>
291694Sdarrenm #include <sys/crypto/common.h>
301694Sdarrenm #include <sys/crypto/spi.h>
311694Sdarrenm #include <sys/strsun.h>
321694Sdarrenm #include <sys/systm.h>
331694Sdarrenm #include <sys/sysmacros.h>
341694Sdarrenm #define _SHA2_IMPL
351694Sdarrenm #include <sys/sha2.h>
3610500SHai-May.Chao@Sun.COM #include <sha2/sha2_impl.h>
371694Sdarrenm
381694Sdarrenm /*
391694Sdarrenm * The sha2 module is created with two modlinkages:
401694Sdarrenm * - a modlmisc that allows consumers to directly call the entry points
411694Sdarrenm * SHA2Init, SHA2Update, and SHA2Final.
421694Sdarrenm * - a modlcrypto that allows the module to register with the Kernel
431694Sdarrenm * Cryptographic Framework (KCF) as a software provider for the SHA2
441694Sdarrenm * mechanisms.
451694Sdarrenm */
461694Sdarrenm
471694Sdarrenm static struct modlmisc modlmisc = {
481694Sdarrenm &mod_miscops,
491694Sdarrenm "SHA2 Message-Digest Algorithm"
501694Sdarrenm };
511694Sdarrenm
521694Sdarrenm static struct modlcrypto modlcrypto = {
531694Sdarrenm &mod_cryptoops,
545072Smcpowers "SHA2 Kernel SW Provider"
551694Sdarrenm };
561694Sdarrenm
571694Sdarrenm static struct modlinkage modlinkage = {
581694Sdarrenm MODREV_1, &modlmisc, &modlcrypto, NULL
591694Sdarrenm };
601694Sdarrenm
611694Sdarrenm /*
621694Sdarrenm * Macros to access the SHA2 or SHA2-HMAC contexts from a context passed
631694Sdarrenm * by KCF to one of the entry points.
641694Sdarrenm */
651694Sdarrenm
661694Sdarrenm #define PROV_SHA2_CTX(ctx) ((sha2_ctx_t *)(ctx)->cc_provider_private)
671694Sdarrenm #define PROV_SHA2_HMAC_CTX(ctx) ((sha2_hmac_ctx_t *)(ctx)->cc_provider_private)
681694Sdarrenm
691694Sdarrenm /* to extract the digest length passed as mechanism parameter */
701694Sdarrenm #define PROV_SHA2_GET_DIGEST_LEN(m, len) { \
711694Sdarrenm if (IS_P2ALIGNED((m)->cm_param, sizeof (ulong_t))) \
7211141Sopensolaris@drydog.com (len) = (uint32_t)*((ulong_t *)(void *)(m)->cm_param); \
731694Sdarrenm else { \
741694Sdarrenm ulong_t tmp_ulong; \
751694Sdarrenm bcopy((m)->cm_param, &tmp_ulong, sizeof (ulong_t)); \
761694Sdarrenm (len) = (uint32_t)tmp_ulong; \
771694Sdarrenm } \
781694Sdarrenm }
791694Sdarrenm
801694Sdarrenm #define PROV_SHA2_DIGEST_KEY(mech, ctx, key, len, digest) { \
811694Sdarrenm SHA2Init(mech, ctx); \
821694Sdarrenm SHA2Update(ctx, key, len); \
831694Sdarrenm SHA2Final(digest, ctx); \
841694Sdarrenm }
851694Sdarrenm
861694Sdarrenm /*
871694Sdarrenm * Mechanism info structure passed to KCF during registration.
881694Sdarrenm */
891694Sdarrenm static crypto_mech_info_t sha2_mech_info_tab[] = {
901694Sdarrenm /* SHA256 */
911694Sdarrenm {SUN_CKM_SHA256, SHA256_MECH_INFO_TYPE,
921694Sdarrenm CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
931694Sdarrenm 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
941694Sdarrenm /* SHA256-HMAC */
951694Sdarrenm {SUN_CKM_SHA256_HMAC, SHA256_HMAC_MECH_INFO_TYPE,
961694Sdarrenm CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
971694Sdarrenm SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
989364SVladimir.Kotal@Sun.COM CRYPTO_KEYSIZE_UNIT_IN_BYTES},
991694Sdarrenm /* SHA256-HMAC GENERAL */
1001694Sdarrenm {SUN_CKM_SHA256_HMAC_GENERAL, SHA256_HMAC_GEN_MECH_INFO_TYPE,
1011694Sdarrenm CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
1021694Sdarrenm SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
1039364SVladimir.Kotal@Sun.COM CRYPTO_KEYSIZE_UNIT_IN_BYTES},
1041694Sdarrenm /* SHA384 */
1051694Sdarrenm {SUN_CKM_SHA384, SHA384_MECH_INFO_TYPE,
1061694Sdarrenm CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
1071694Sdarrenm 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1081694Sdarrenm /* SHA384-HMAC */
1091694Sdarrenm {SUN_CKM_SHA384_HMAC, SHA384_HMAC_MECH_INFO_TYPE,
1101694Sdarrenm CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
1111694Sdarrenm SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
1129364SVladimir.Kotal@Sun.COM CRYPTO_KEYSIZE_UNIT_IN_BYTES},
1131694Sdarrenm /* SHA384-HMAC GENERAL */
1141694Sdarrenm {SUN_CKM_SHA384_HMAC_GENERAL, SHA384_HMAC_GEN_MECH_INFO_TYPE,
1151694Sdarrenm CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
1161694Sdarrenm SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
1179364SVladimir.Kotal@Sun.COM CRYPTO_KEYSIZE_UNIT_IN_BYTES},
1181694Sdarrenm /* SHA512 */
1191694Sdarrenm {SUN_CKM_SHA512, SHA512_MECH_INFO_TYPE,
1201694Sdarrenm CRYPTO_FG_DIGEST | CRYPTO_FG_DIGEST_ATOMIC,
1211694Sdarrenm 0, 0, CRYPTO_KEYSIZE_UNIT_IN_BITS},
1221694Sdarrenm /* SHA512-HMAC */
1231694Sdarrenm {SUN_CKM_SHA512_HMAC, SHA512_HMAC_MECH_INFO_TYPE,
1241694Sdarrenm CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
1251694Sdarrenm SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
1269364SVladimir.Kotal@Sun.COM CRYPTO_KEYSIZE_UNIT_IN_BYTES},
1271694Sdarrenm /* SHA512-HMAC GENERAL */
1281694Sdarrenm {SUN_CKM_SHA512_HMAC_GENERAL, SHA512_HMAC_GEN_MECH_INFO_TYPE,
1291694Sdarrenm CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC,
1301694Sdarrenm SHA2_HMAC_MIN_KEY_LEN, SHA2_HMAC_MAX_KEY_LEN,
1319364SVladimir.Kotal@Sun.COM CRYPTO_KEYSIZE_UNIT_IN_BYTES}
1321694Sdarrenm };
1331694Sdarrenm
1341694Sdarrenm static void sha2_provider_status(crypto_provider_handle_t, uint_t *);
1351694Sdarrenm
1361694Sdarrenm static crypto_control_ops_t sha2_control_ops = {
1371694Sdarrenm sha2_provider_status
1381694Sdarrenm };
1391694Sdarrenm
1401694Sdarrenm static int sha2_digest_init(crypto_ctx_t *, crypto_mechanism_t *,
1411694Sdarrenm crypto_req_handle_t);
1421694Sdarrenm static int sha2_digest(crypto_ctx_t *, crypto_data_t *, crypto_data_t *,
1431694Sdarrenm crypto_req_handle_t);
1441694Sdarrenm static int sha2_digest_update(crypto_ctx_t *, crypto_data_t *,
1451694Sdarrenm crypto_req_handle_t);
1461694Sdarrenm static int sha2_digest_final(crypto_ctx_t *, crypto_data_t *,
1471694Sdarrenm crypto_req_handle_t);
1481694Sdarrenm static int sha2_digest_atomic(crypto_provider_handle_t, crypto_session_id_t,
1491694Sdarrenm crypto_mechanism_t *, crypto_data_t *, crypto_data_t *,
1501694Sdarrenm crypto_req_handle_t);
1511694Sdarrenm
1521694Sdarrenm static crypto_digest_ops_t sha2_digest_ops = {
1531694Sdarrenm sha2_digest_init,
1541694Sdarrenm sha2_digest,
1551694Sdarrenm sha2_digest_update,
1561694Sdarrenm NULL,
1571694Sdarrenm sha2_digest_final,
1581694Sdarrenm sha2_digest_atomic
1591694Sdarrenm };
1601694Sdarrenm
1611694Sdarrenm static int sha2_mac_init(crypto_ctx_t *, crypto_mechanism_t *, crypto_key_t *,
1621694Sdarrenm crypto_spi_ctx_template_t, crypto_req_handle_t);
1631694Sdarrenm static int sha2_mac_update(crypto_ctx_t *, crypto_data_t *,
1641694Sdarrenm crypto_req_handle_t);
1651694Sdarrenm static int sha2_mac_final(crypto_ctx_t *, crypto_data_t *, crypto_req_handle_t);
1661694Sdarrenm static int sha2_mac_atomic(crypto_provider_handle_t, crypto_session_id_t,
1671694Sdarrenm crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
1681694Sdarrenm crypto_spi_ctx_template_t, crypto_req_handle_t);
1691694Sdarrenm static int sha2_mac_verify_atomic(crypto_provider_handle_t, crypto_session_id_t,
1701694Sdarrenm crypto_mechanism_t *, crypto_key_t *, crypto_data_t *, crypto_data_t *,
1711694Sdarrenm crypto_spi_ctx_template_t, crypto_req_handle_t);
1721694Sdarrenm
1731694Sdarrenm static crypto_mac_ops_t sha2_mac_ops = {
1741694Sdarrenm sha2_mac_init,
1751694Sdarrenm NULL,
1761694Sdarrenm sha2_mac_update,
1771694Sdarrenm sha2_mac_final,
1781694Sdarrenm sha2_mac_atomic,
1791694Sdarrenm sha2_mac_verify_atomic
1801694Sdarrenm };
1811694Sdarrenm
1821694Sdarrenm static int sha2_create_ctx_template(crypto_provider_handle_t,
1831694Sdarrenm crypto_mechanism_t *, crypto_key_t *, crypto_spi_ctx_template_t *,
1841694Sdarrenm size_t *, crypto_req_handle_t);
1851694Sdarrenm static int sha2_free_context(crypto_ctx_t *);
1861694Sdarrenm
1871694Sdarrenm static crypto_ctx_ops_t sha2_ctx_ops = {
1881694Sdarrenm sha2_create_ctx_template,
1891694Sdarrenm sha2_free_context
1901694Sdarrenm };
1911694Sdarrenm
19210732SAnthony.Scarpino@Sun.COM static void sha2_POST(int *);
19310732SAnthony.Scarpino@Sun.COM
19410732SAnthony.Scarpino@Sun.COM static crypto_fips140_ops_t sha2_fips140_ops = {
19510732SAnthony.Scarpino@Sun.COM sha2_POST
19610732SAnthony.Scarpino@Sun.COM };
19710732SAnthony.Scarpino@Sun.COM
1981694Sdarrenm static crypto_ops_t sha2_crypto_ops = {
1991694Sdarrenm &sha2_control_ops,
2001694Sdarrenm &sha2_digest_ops,
2011694Sdarrenm NULL,
2021694Sdarrenm &sha2_mac_ops,
2031694Sdarrenm NULL,
2041694Sdarrenm NULL,
2051694Sdarrenm NULL,
2061694Sdarrenm NULL,
2071694Sdarrenm NULL,
2081694Sdarrenm NULL,
2091694Sdarrenm NULL,
2101694Sdarrenm NULL,
2111694Sdarrenm NULL,
21210732SAnthony.Scarpino@Sun.COM &sha2_ctx_ops,
21310732SAnthony.Scarpino@Sun.COM NULL,
21410732SAnthony.Scarpino@Sun.COM NULL,
21510732SAnthony.Scarpino@Sun.COM &sha2_fips140_ops
2161694Sdarrenm };
2171694Sdarrenm
2181694Sdarrenm static crypto_provider_info_t sha2_prov_info = {
21910732SAnthony.Scarpino@Sun.COM CRYPTO_SPI_VERSION_4,
2201694Sdarrenm "SHA2 Software Provider",
2211694Sdarrenm CRYPTO_SW_PROVIDER,
2221694Sdarrenm {&modlinkage},
2231694Sdarrenm NULL,
2241694Sdarrenm &sha2_crypto_ops,
2251694Sdarrenm sizeof (sha2_mech_info_tab)/sizeof (crypto_mech_info_t),
2261694Sdarrenm sha2_mech_info_tab
2271694Sdarrenm };
2281694Sdarrenm
2291694Sdarrenm static crypto_kcf_provider_handle_t sha2_prov_handle = NULL;
2301694Sdarrenm
2311694Sdarrenm int
_init()2321694Sdarrenm _init()
2331694Sdarrenm {
2341694Sdarrenm int ret;
2351694Sdarrenm
2361694Sdarrenm if ((ret = mod_install(&modlinkage)) != 0)
2371694Sdarrenm return (ret);
2381694Sdarrenm
2391694Sdarrenm /*
240*11751SAnthony.Scarpino@Sun.COM * Register with KCF. If the registration fails, do not uninstall the
241*11751SAnthony.Scarpino@Sun.COM * module, since the functionality provided by misc/sha2 should still
242*11751SAnthony.Scarpino@Sun.COM * be available.
2431694Sdarrenm */
244*11751SAnthony.Scarpino@Sun.COM (void) crypto_register_provider(&sha2_prov_info, &sha2_prov_handle);
2451694Sdarrenm
2461694Sdarrenm return (0);
2471694Sdarrenm }
2481694Sdarrenm
2491694Sdarrenm int
_info(struct modinfo * modinfop)2501694Sdarrenm _info(struct modinfo *modinfop)
2511694Sdarrenm {
2521694Sdarrenm return (mod_info(&modlinkage, modinfop));
2531694Sdarrenm }
2541694Sdarrenm
2551694Sdarrenm /*
2561694Sdarrenm * KCF software provider control entry points.
2571694Sdarrenm */
2581694Sdarrenm /* ARGSUSED */
2591694Sdarrenm static void
sha2_provider_status(crypto_provider_handle_t provider,uint_t * status)2601694Sdarrenm sha2_provider_status(crypto_provider_handle_t provider, uint_t *status)
2611694Sdarrenm {
2621694Sdarrenm *status = CRYPTO_PROVIDER_READY;
2631694Sdarrenm }
2641694Sdarrenm
2651694Sdarrenm /*
2661694Sdarrenm * KCF software provider digest entry points.
2671694Sdarrenm */
2681694Sdarrenm
2691694Sdarrenm static int
sha2_digest_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_req_handle_t req)2701694Sdarrenm sha2_digest_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
2711694Sdarrenm crypto_req_handle_t req)
2721694Sdarrenm {
2731694Sdarrenm
2741694Sdarrenm /*
2751694Sdarrenm * Allocate and initialize SHA2 context.
2761694Sdarrenm */
2771694Sdarrenm ctx->cc_provider_private = kmem_alloc(sizeof (sha2_ctx_t),
2781694Sdarrenm crypto_kmflag(req));
2791694Sdarrenm if (ctx->cc_provider_private == NULL)
2801694Sdarrenm return (CRYPTO_HOST_MEMORY);
2811694Sdarrenm
2821694Sdarrenm PROV_SHA2_CTX(ctx)->sc_mech_type = mechanism->cm_type;
2831694Sdarrenm SHA2Init(mechanism->cm_type, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx);
2841694Sdarrenm
2851694Sdarrenm return (CRYPTO_SUCCESS);
2861694Sdarrenm }
2871694Sdarrenm
2881694Sdarrenm /*
2891694Sdarrenm * Helper SHA2 digest update function for uio data.
2901694Sdarrenm */
2911694Sdarrenm static int
sha2_digest_update_uio(SHA2_CTX * sha2_ctx,crypto_data_t * data)2921694Sdarrenm sha2_digest_update_uio(SHA2_CTX *sha2_ctx, crypto_data_t *data)
2931694Sdarrenm {
2941694Sdarrenm off_t offset = data->cd_offset;
2951694Sdarrenm size_t length = data->cd_length;
2961694Sdarrenm uint_t vec_idx;
2971694Sdarrenm size_t cur_len;
2981694Sdarrenm
2991694Sdarrenm /* we support only kernel buffer */
3001694Sdarrenm if (data->cd_uio->uio_segflg != UIO_SYSSPACE)
3011694Sdarrenm return (CRYPTO_ARGUMENTS_BAD);
3021694Sdarrenm
3031694Sdarrenm /*
3041694Sdarrenm * Jump to the first iovec containing data to be
3051694Sdarrenm * digested.
3061694Sdarrenm */
3071694Sdarrenm for (vec_idx = 0; vec_idx < data->cd_uio->uio_iovcnt &&
3081694Sdarrenm offset >= data->cd_uio->uio_iov[vec_idx].iov_len;
3095072Smcpowers offset -= data->cd_uio->uio_iov[vec_idx++].iov_len)
3105072Smcpowers ;
3111694Sdarrenm if (vec_idx == data->cd_uio->uio_iovcnt) {
3121694Sdarrenm /*
3131694Sdarrenm * The caller specified an offset that is larger than the
3141694Sdarrenm * total size of the buffers it provided.
3151694Sdarrenm */
3161694Sdarrenm return (CRYPTO_DATA_LEN_RANGE);
3171694Sdarrenm }
3181694Sdarrenm
3191694Sdarrenm /*
3201694Sdarrenm * Now do the digesting on the iovecs.
3211694Sdarrenm */
3221694Sdarrenm while (vec_idx < data->cd_uio->uio_iovcnt && length > 0) {
3231694Sdarrenm cur_len = MIN(data->cd_uio->uio_iov[vec_idx].iov_len -
3241694Sdarrenm offset, length);
3251694Sdarrenm
3261694Sdarrenm SHA2Update(sha2_ctx, (uint8_t *)data->cd_uio->
3271694Sdarrenm uio_iov[vec_idx].iov_base + offset, cur_len);
3281694Sdarrenm length -= cur_len;
3291694Sdarrenm vec_idx++;
3301694Sdarrenm offset = 0;
3311694Sdarrenm }
3321694Sdarrenm
3331694Sdarrenm if (vec_idx == data->cd_uio->uio_iovcnt && length > 0) {
3341694Sdarrenm /*
3351694Sdarrenm * The end of the specified iovec's was reached but
3361694Sdarrenm * the length requested could not be processed, i.e.
3371694Sdarrenm * The caller requested to digest more data than it provided.
3381694Sdarrenm */
3391694Sdarrenm return (CRYPTO_DATA_LEN_RANGE);
3401694Sdarrenm }
3411694Sdarrenm
3421694Sdarrenm return (CRYPTO_SUCCESS);
3431694Sdarrenm }
3441694Sdarrenm
3451694Sdarrenm /*
3461694Sdarrenm * Helper SHA2 digest final function for uio data.
3471694Sdarrenm * digest_len is the length of the desired digest. If digest_len
3481694Sdarrenm * is smaller than the default SHA2 digest length, the caller
3491694Sdarrenm * must pass a scratch buffer, digest_scratch, which must
3501694Sdarrenm * be at least the algorithm's digest length bytes.
3511694Sdarrenm */
3521694Sdarrenm static int
sha2_digest_final_uio(SHA2_CTX * sha2_ctx,crypto_data_t * digest,ulong_t digest_len,uchar_t * digest_scratch)3531694Sdarrenm sha2_digest_final_uio(SHA2_CTX *sha2_ctx, crypto_data_t *digest,
3541694Sdarrenm ulong_t digest_len, uchar_t *digest_scratch)
3551694Sdarrenm {
3561694Sdarrenm off_t offset = digest->cd_offset;
3571694Sdarrenm uint_t vec_idx;
3581694Sdarrenm
3591694Sdarrenm /* we support only kernel buffer */
3601694Sdarrenm if (digest->cd_uio->uio_segflg != UIO_SYSSPACE)
3611694Sdarrenm return (CRYPTO_ARGUMENTS_BAD);
3621694Sdarrenm
3631694Sdarrenm /*
3641694Sdarrenm * Jump to the first iovec containing ptr to the digest to
3651694Sdarrenm * be returned.
3661694Sdarrenm */
3671694Sdarrenm for (vec_idx = 0; offset >= digest->cd_uio->uio_iov[vec_idx].iov_len &&
3681694Sdarrenm vec_idx < digest->cd_uio->uio_iovcnt;
3695072Smcpowers offset -= digest->cd_uio->uio_iov[vec_idx++].iov_len)
3705072Smcpowers ;
3711694Sdarrenm if (vec_idx == digest->cd_uio->uio_iovcnt) {
3721694Sdarrenm /*
3731694Sdarrenm * The caller specified an offset that is
3741694Sdarrenm * larger than the total size of the buffers
3751694Sdarrenm * it provided.
3761694Sdarrenm */
3771694Sdarrenm return (CRYPTO_DATA_LEN_RANGE);
3781694Sdarrenm }
3791694Sdarrenm
3801694Sdarrenm if (offset + digest_len <=
3811694Sdarrenm digest->cd_uio->uio_iov[vec_idx].iov_len) {
3821694Sdarrenm /*
3831694Sdarrenm * The computed SHA2 digest will fit in the current
3841694Sdarrenm * iovec.
3851694Sdarrenm */
3861694Sdarrenm if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) &&
3871694Sdarrenm (digest_len != SHA256_DIGEST_LENGTH)) ||
3881694Sdarrenm ((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) &&
3895072Smcpowers (digest_len != SHA512_DIGEST_LENGTH))) {
3901694Sdarrenm /*
3911694Sdarrenm * The caller requested a short digest. Digest
3921694Sdarrenm * into a scratch buffer and return to
3931694Sdarrenm * the user only what was requested.
3941694Sdarrenm */
3951694Sdarrenm SHA2Final(digest_scratch, sha2_ctx);
3961694Sdarrenm
3971694Sdarrenm bcopy(digest_scratch, (uchar_t *)digest->
3981694Sdarrenm cd_uio->uio_iov[vec_idx].iov_base + offset,
3991694Sdarrenm digest_len);
4001694Sdarrenm } else {
4011694Sdarrenm SHA2Final((uchar_t *)digest->
4021694Sdarrenm cd_uio->uio_iov[vec_idx].iov_base + offset,
4031694Sdarrenm sha2_ctx);
4041694Sdarrenm
4051694Sdarrenm }
4061694Sdarrenm } else {
4071694Sdarrenm /*
4081694Sdarrenm * The computed digest will be crossing one or more iovec's.
4091694Sdarrenm * This is bad performance-wise but we need to support it.
4101694Sdarrenm * Allocate a small scratch buffer on the stack and
4111694Sdarrenm * copy it piece meal to the specified digest iovec's.
4121694Sdarrenm */
4131694Sdarrenm uchar_t digest_tmp[SHA512_DIGEST_LENGTH];
4141694Sdarrenm off_t scratch_offset = 0;
4151694Sdarrenm size_t length = digest_len;
4161694Sdarrenm size_t cur_len;
4171694Sdarrenm
4181694Sdarrenm SHA2Final(digest_tmp, sha2_ctx);
4191694Sdarrenm
4201694Sdarrenm while (vec_idx < digest->cd_uio->uio_iovcnt && length > 0) {
4211694Sdarrenm cur_len =
4221694Sdarrenm MIN(digest->cd_uio->uio_iov[vec_idx].iov_len -
4235072Smcpowers offset, length);
4241694Sdarrenm bcopy(digest_tmp + scratch_offset,
4251694Sdarrenm digest->cd_uio->uio_iov[vec_idx].iov_base + offset,
4261694Sdarrenm cur_len);
4271694Sdarrenm
4281694Sdarrenm length -= cur_len;
4291694Sdarrenm vec_idx++;
4301694Sdarrenm scratch_offset += cur_len;
4311694Sdarrenm offset = 0;
4321694Sdarrenm }
4331694Sdarrenm
4341694Sdarrenm if (vec_idx == digest->cd_uio->uio_iovcnt && length > 0) {
4351694Sdarrenm /*
4361694Sdarrenm * The end of the specified iovec's was reached but
4371694Sdarrenm * the length requested could not be processed, i.e.
4381694Sdarrenm * The caller requested to digest more data than it
4391694Sdarrenm * provided.
4401694Sdarrenm */
4411694Sdarrenm return (CRYPTO_DATA_LEN_RANGE);
4421694Sdarrenm }
4431694Sdarrenm }
4441694Sdarrenm
4451694Sdarrenm return (CRYPTO_SUCCESS);
4461694Sdarrenm }
4471694Sdarrenm
4481694Sdarrenm /*
4491694Sdarrenm * Helper SHA2 digest update for mblk's.
4501694Sdarrenm */
4511694Sdarrenm static int
sha2_digest_update_mblk(SHA2_CTX * sha2_ctx,crypto_data_t * data)4521694Sdarrenm sha2_digest_update_mblk(SHA2_CTX *sha2_ctx, crypto_data_t *data)
4531694Sdarrenm {
4541694Sdarrenm off_t offset = data->cd_offset;
4551694Sdarrenm size_t length = data->cd_length;
4561694Sdarrenm mblk_t *mp;
4571694Sdarrenm size_t cur_len;
4581694Sdarrenm
4591694Sdarrenm /*
4601694Sdarrenm * Jump to the first mblk_t containing data to be digested.
4611694Sdarrenm */
4621694Sdarrenm for (mp = data->cd_mp; mp != NULL && offset >= MBLKL(mp);
4635072Smcpowers offset -= MBLKL(mp), mp = mp->b_cont)
4645072Smcpowers ;
4651694Sdarrenm if (mp == NULL) {
4661694Sdarrenm /*
4671694Sdarrenm * The caller specified an offset that is larger than the
4681694Sdarrenm * total size of the buffers it provided.
4691694Sdarrenm */
4701694Sdarrenm return (CRYPTO_DATA_LEN_RANGE);
4711694Sdarrenm }
4721694Sdarrenm
4731694Sdarrenm /*
4741694Sdarrenm * Now do the digesting on the mblk chain.
4751694Sdarrenm */
4761694Sdarrenm while (mp != NULL && length > 0) {
4771694Sdarrenm cur_len = MIN(MBLKL(mp) - offset, length);
4781694Sdarrenm SHA2Update(sha2_ctx, mp->b_rptr + offset, cur_len);
4791694Sdarrenm length -= cur_len;
4801694Sdarrenm offset = 0;
4811694Sdarrenm mp = mp->b_cont;
4821694Sdarrenm }
4831694Sdarrenm
4841694Sdarrenm if (mp == NULL && length > 0) {
4851694Sdarrenm /*
4861694Sdarrenm * The end of the mblk was reached but the length requested
4871694Sdarrenm * could not be processed, i.e. The caller requested
4881694Sdarrenm * to digest more data than it provided.
4891694Sdarrenm */
4901694Sdarrenm return (CRYPTO_DATA_LEN_RANGE);
4911694Sdarrenm }
4921694Sdarrenm
4931694Sdarrenm return (CRYPTO_SUCCESS);
4941694Sdarrenm }
4951694Sdarrenm
4961694Sdarrenm /*
4971694Sdarrenm * Helper SHA2 digest final for mblk's.
4981694Sdarrenm * digest_len is the length of the desired digest. If digest_len
4991694Sdarrenm * is smaller than the default SHA2 digest length, the caller
5001694Sdarrenm * must pass a scratch buffer, digest_scratch, which must
5011694Sdarrenm * be at least the algorithm's digest length bytes.
5021694Sdarrenm */
5031694Sdarrenm static int
sha2_digest_final_mblk(SHA2_CTX * sha2_ctx,crypto_data_t * digest,ulong_t digest_len,uchar_t * digest_scratch)5041694Sdarrenm sha2_digest_final_mblk(SHA2_CTX *sha2_ctx, crypto_data_t *digest,
5051694Sdarrenm ulong_t digest_len, uchar_t *digest_scratch)
5061694Sdarrenm {
5071694Sdarrenm off_t offset = digest->cd_offset;
5081694Sdarrenm mblk_t *mp;
5091694Sdarrenm
5101694Sdarrenm /*
5111694Sdarrenm * Jump to the first mblk_t that will be used to store the digest.
5121694Sdarrenm */
5131694Sdarrenm for (mp = digest->cd_mp; mp != NULL && offset >= MBLKL(mp);
5145072Smcpowers offset -= MBLKL(mp), mp = mp->b_cont)
5155072Smcpowers ;
5161694Sdarrenm if (mp == NULL) {
5171694Sdarrenm /*
5181694Sdarrenm * The caller specified an offset that is larger than the
5191694Sdarrenm * total size of the buffers it provided.
5201694Sdarrenm */
5211694Sdarrenm return (CRYPTO_DATA_LEN_RANGE);
5221694Sdarrenm }
5231694Sdarrenm
5241694Sdarrenm if (offset + digest_len <= MBLKL(mp)) {
5251694Sdarrenm /*
5261694Sdarrenm * The computed SHA2 digest will fit in the current mblk.
5271694Sdarrenm * Do the SHA2Final() in-place.
5281694Sdarrenm */
5291694Sdarrenm if (((sha2_ctx->algotype <= SHA256_HMAC_GEN_MECH_INFO_TYPE) &&
5301694Sdarrenm (digest_len != SHA256_DIGEST_LENGTH)) ||
5311694Sdarrenm ((sha2_ctx->algotype > SHA256_HMAC_GEN_MECH_INFO_TYPE) &&
5325072Smcpowers (digest_len != SHA512_DIGEST_LENGTH))) {
5331694Sdarrenm /*
5341694Sdarrenm * The caller requested a short digest. Digest
5351694Sdarrenm * into a scratch buffer and return to
5361694Sdarrenm * the user only what was requested.
5371694Sdarrenm */
5381694Sdarrenm SHA2Final(digest_scratch, sha2_ctx);
5391694Sdarrenm bcopy(digest_scratch, mp->b_rptr + offset, digest_len);
5401694Sdarrenm } else {
5411694Sdarrenm SHA2Final(mp->b_rptr + offset, sha2_ctx);
5421694Sdarrenm }
5431694Sdarrenm } else {
5441694Sdarrenm /*
5451694Sdarrenm * The computed digest will be crossing one or more mblk's.
5461694Sdarrenm * This is bad performance-wise but we need to support it.
5471694Sdarrenm * Allocate a small scratch buffer on the stack and
5481694Sdarrenm * copy it piece meal to the specified digest iovec's.
5491694Sdarrenm */
5501694Sdarrenm uchar_t digest_tmp[SHA512_DIGEST_LENGTH];
5511694Sdarrenm off_t scratch_offset = 0;
5521694Sdarrenm size_t length = digest_len;
5531694Sdarrenm size_t cur_len;
5541694Sdarrenm
5551694Sdarrenm SHA2Final(digest_tmp, sha2_ctx);
5561694Sdarrenm
5571694Sdarrenm while (mp != NULL && length > 0) {
5581694Sdarrenm cur_len = MIN(MBLKL(mp) - offset, length);
5591694Sdarrenm bcopy(digest_tmp + scratch_offset,
5601694Sdarrenm mp->b_rptr + offset, cur_len);
5611694Sdarrenm
5621694Sdarrenm length -= cur_len;
5631694Sdarrenm mp = mp->b_cont;
5641694Sdarrenm scratch_offset += cur_len;
5651694Sdarrenm offset = 0;
5661694Sdarrenm }
5671694Sdarrenm
5681694Sdarrenm if (mp == NULL && length > 0) {
5691694Sdarrenm /*
5701694Sdarrenm * The end of the specified mblk was reached but
5711694Sdarrenm * the length requested could not be processed, i.e.
5721694Sdarrenm * The caller requested to digest more data than it
5731694Sdarrenm * provided.
5741694Sdarrenm */
5751694Sdarrenm return (CRYPTO_DATA_LEN_RANGE);
5761694Sdarrenm }
5771694Sdarrenm }
5781694Sdarrenm
5791694Sdarrenm return (CRYPTO_SUCCESS);
5801694Sdarrenm }
5811694Sdarrenm
5821694Sdarrenm /* ARGSUSED */
5831694Sdarrenm static int
sha2_digest(crypto_ctx_t * ctx,crypto_data_t * data,crypto_data_t * digest,crypto_req_handle_t req)5841694Sdarrenm sha2_digest(crypto_ctx_t *ctx, crypto_data_t *data, crypto_data_t *digest,
5851694Sdarrenm crypto_req_handle_t req)
5861694Sdarrenm {
5871694Sdarrenm int ret = CRYPTO_SUCCESS;
5881694Sdarrenm uint_t sha_digest_len;
5891694Sdarrenm
5901694Sdarrenm ASSERT(ctx->cc_provider_private != NULL);
5911694Sdarrenm
5921694Sdarrenm switch (PROV_SHA2_CTX(ctx)->sc_mech_type) {
5931694Sdarrenm case SHA256_MECH_INFO_TYPE:
5941694Sdarrenm sha_digest_len = SHA256_DIGEST_LENGTH;
5951694Sdarrenm break;
5961694Sdarrenm case SHA384_MECH_INFO_TYPE:
5971694Sdarrenm sha_digest_len = SHA384_DIGEST_LENGTH;
5981694Sdarrenm break;
5991694Sdarrenm case SHA512_MECH_INFO_TYPE:
6001694Sdarrenm sha_digest_len = SHA512_DIGEST_LENGTH;
6011694Sdarrenm break;
6021694Sdarrenm default:
6031694Sdarrenm return (CRYPTO_MECHANISM_INVALID);
6041694Sdarrenm }
6051694Sdarrenm
6061694Sdarrenm /*
6071694Sdarrenm * We need to just return the length needed to store the output.
6081694Sdarrenm * We should not destroy the context for the following cases.
6091694Sdarrenm */
6101694Sdarrenm if ((digest->cd_length == 0) ||
6111694Sdarrenm (digest->cd_length < sha_digest_len)) {
6121694Sdarrenm digest->cd_length = sha_digest_len;
6131694Sdarrenm return (CRYPTO_BUFFER_TOO_SMALL);
6141694Sdarrenm }
6151694Sdarrenm
6161694Sdarrenm /*
6171694Sdarrenm * Do the SHA2 update on the specified input data.
6181694Sdarrenm */
6191694Sdarrenm switch (data->cd_format) {
6201694Sdarrenm case CRYPTO_DATA_RAW:
6211694Sdarrenm SHA2Update(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
6221694Sdarrenm (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
6231694Sdarrenm data->cd_length);
6241694Sdarrenm break;
6251694Sdarrenm case CRYPTO_DATA_UIO:
6261694Sdarrenm ret = sha2_digest_update_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
6271694Sdarrenm data);
6281694Sdarrenm break;
6291694Sdarrenm case CRYPTO_DATA_MBLK:
6301694Sdarrenm ret = sha2_digest_update_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
6311694Sdarrenm data);
6321694Sdarrenm break;
6331694Sdarrenm default:
6341694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
6351694Sdarrenm }
6361694Sdarrenm
6371694Sdarrenm if (ret != CRYPTO_SUCCESS) {
6381694Sdarrenm /* the update failed, free context and bail */
6391694Sdarrenm kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t));
6401694Sdarrenm ctx->cc_provider_private = NULL;
6411694Sdarrenm digest->cd_length = 0;
6421694Sdarrenm return (ret);
6431694Sdarrenm }
6441694Sdarrenm
6451694Sdarrenm /*
6461694Sdarrenm * Do a SHA2 final, must be done separately since the digest
6471694Sdarrenm * type can be different than the input data type.
6481694Sdarrenm */
6491694Sdarrenm switch (digest->cd_format) {
6501694Sdarrenm case CRYPTO_DATA_RAW:
6511694Sdarrenm SHA2Final((unsigned char *)digest->cd_raw.iov_base +
6521694Sdarrenm digest->cd_offset, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx);
6531694Sdarrenm break;
6541694Sdarrenm case CRYPTO_DATA_UIO:
6551694Sdarrenm ret = sha2_digest_final_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
6561694Sdarrenm digest, sha_digest_len, NULL);
6571694Sdarrenm break;
6581694Sdarrenm case CRYPTO_DATA_MBLK:
6591694Sdarrenm ret = sha2_digest_final_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
6601694Sdarrenm digest, sha_digest_len, NULL);
6611694Sdarrenm break;
6621694Sdarrenm default:
6631694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
6641694Sdarrenm }
6651694Sdarrenm
6661694Sdarrenm /* all done, free context and return */
6671694Sdarrenm
6681694Sdarrenm if (ret == CRYPTO_SUCCESS)
6691694Sdarrenm digest->cd_length = sha_digest_len;
6701694Sdarrenm else
6711694Sdarrenm digest->cd_length = 0;
6721694Sdarrenm
6731694Sdarrenm kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t));
6741694Sdarrenm ctx->cc_provider_private = NULL;
6751694Sdarrenm return (ret);
6761694Sdarrenm }
6771694Sdarrenm
6781694Sdarrenm /* ARGSUSED */
6791694Sdarrenm static int
sha2_digest_update(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)6801694Sdarrenm sha2_digest_update(crypto_ctx_t *ctx, crypto_data_t *data,
6811694Sdarrenm crypto_req_handle_t req)
6821694Sdarrenm {
6831694Sdarrenm int ret = CRYPTO_SUCCESS;
6841694Sdarrenm
6851694Sdarrenm ASSERT(ctx->cc_provider_private != NULL);
6861694Sdarrenm
6871694Sdarrenm /*
6881694Sdarrenm * Do the SHA2 update on the specified input data.
6891694Sdarrenm */
6901694Sdarrenm switch (data->cd_format) {
6911694Sdarrenm case CRYPTO_DATA_RAW:
6921694Sdarrenm SHA2Update(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
6931694Sdarrenm (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
6941694Sdarrenm data->cd_length);
6951694Sdarrenm break;
6961694Sdarrenm case CRYPTO_DATA_UIO:
6971694Sdarrenm ret = sha2_digest_update_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
6981694Sdarrenm data);
6991694Sdarrenm break;
7001694Sdarrenm case CRYPTO_DATA_MBLK:
7011694Sdarrenm ret = sha2_digest_update_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
7021694Sdarrenm data);
7031694Sdarrenm break;
7041694Sdarrenm default:
7051694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
7061694Sdarrenm }
7071694Sdarrenm
7081694Sdarrenm return (ret);
7091694Sdarrenm }
7101694Sdarrenm
7111694Sdarrenm /* ARGSUSED */
7121694Sdarrenm static int
sha2_digest_final(crypto_ctx_t * ctx,crypto_data_t * digest,crypto_req_handle_t req)7131694Sdarrenm sha2_digest_final(crypto_ctx_t *ctx, crypto_data_t *digest,
7141694Sdarrenm crypto_req_handle_t req)
7151694Sdarrenm {
7161694Sdarrenm int ret = CRYPTO_SUCCESS;
7171694Sdarrenm uint_t sha_digest_len;
7181694Sdarrenm
7191694Sdarrenm ASSERT(ctx->cc_provider_private != NULL);
7201694Sdarrenm
7211694Sdarrenm switch (PROV_SHA2_CTX(ctx)->sc_mech_type) {
7221694Sdarrenm case SHA256_MECH_INFO_TYPE:
7231694Sdarrenm sha_digest_len = SHA256_DIGEST_LENGTH;
7241694Sdarrenm break;
7251694Sdarrenm case SHA384_MECH_INFO_TYPE:
7261694Sdarrenm sha_digest_len = SHA384_DIGEST_LENGTH;
7271694Sdarrenm break;
7281694Sdarrenm case SHA512_MECH_INFO_TYPE:
7291694Sdarrenm sha_digest_len = SHA512_DIGEST_LENGTH;
7301694Sdarrenm break;
7311694Sdarrenm default:
7321694Sdarrenm return (CRYPTO_MECHANISM_INVALID);
7331694Sdarrenm }
7341694Sdarrenm
7351694Sdarrenm /*
7361694Sdarrenm * We need to just return the length needed to store the output.
7371694Sdarrenm * We should not destroy the context for the following cases.
7381694Sdarrenm */
7391694Sdarrenm if ((digest->cd_length == 0) ||
7401694Sdarrenm (digest->cd_length < sha_digest_len)) {
7411694Sdarrenm digest->cd_length = sha_digest_len;
7421694Sdarrenm return (CRYPTO_BUFFER_TOO_SMALL);
7431694Sdarrenm }
7441694Sdarrenm
7451694Sdarrenm /*
7461694Sdarrenm * Do a SHA2 final.
7471694Sdarrenm */
7481694Sdarrenm switch (digest->cd_format) {
7491694Sdarrenm case CRYPTO_DATA_RAW:
7501694Sdarrenm SHA2Final((unsigned char *)digest->cd_raw.iov_base +
7511694Sdarrenm digest->cd_offset, &PROV_SHA2_CTX(ctx)->sc_sha2_ctx);
7521694Sdarrenm break;
7531694Sdarrenm case CRYPTO_DATA_UIO:
7541694Sdarrenm ret = sha2_digest_final_uio(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
7551694Sdarrenm digest, sha_digest_len, NULL);
7561694Sdarrenm break;
7571694Sdarrenm case CRYPTO_DATA_MBLK:
7581694Sdarrenm ret = sha2_digest_final_mblk(&PROV_SHA2_CTX(ctx)->sc_sha2_ctx,
7591694Sdarrenm digest, sha_digest_len, NULL);
7601694Sdarrenm break;
7611694Sdarrenm default:
7621694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
7631694Sdarrenm }
7641694Sdarrenm
7651694Sdarrenm /* all done, free context and return */
7661694Sdarrenm
7671694Sdarrenm if (ret == CRYPTO_SUCCESS)
7681694Sdarrenm digest->cd_length = sha_digest_len;
7691694Sdarrenm else
7701694Sdarrenm digest->cd_length = 0;
7711694Sdarrenm
7721694Sdarrenm kmem_free(ctx->cc_provider_private, sizeof (sha2_ctx_t));
7731694Sdarrenm ctx->cc_provider_private = NULL;
7741694Sdarrenm
7751694Sdarrenm return (ret);
7761694Sdarrenm }
7771694Sdarrenm
7781694Sdarrenm /* ARGSUSED */
7791694Sdarrenm static int
sha2_digest_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_data_t * data,crypto_data_t * digest,crypto_req_handle_t req)7801694Sdarrenm sha2_digest_atomic(crypto_provider_handle_t provider,
7811694Sdarrenm crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
7821694Sdarrenm crypto_data_t *data, crypto_data_t *digest,
7831694Sdarrenm crypto_req_handle_t req)
7841694Sdarrenm {
7851694Sdarrenm int ret = CRYPTO_SUCCESS;
7861694Sdarrenm SHA2_CTX sha2_ctx;
7871694Sdarrenm uint32_t sha_digest_len;
7881694Sdarrenm
7891694Sdarrenm /*
7901694Sdarrenm * Do the SHA inits.
7911694Sdarrenm */
7921694Sdarrenm
7931694Sdarrenm SHA2Init(mechanism->cm_type, &sha2_ctx);
7941694Sdarrenm
7951694Sdarrenm switch (data->cd_format) {
7961694Sdarrenm case CRYPTO_DATA_RAW:
7971694Sdarrenm SHA2Update(&sha2_ctx, (uint8_t *)data->
7981694Sdarrenm cd_raw.iov_base + data->cd_offset, data->cd_length);
7991694Sdarrenm break;
8001694Sdarrenm case CRYPTO_DATA_UIO:
8011694Sdarrenm ret = sha2_digest_update_uio(&sha2_ctx, data);
8021694Sdarrenm break;
8031694Sdarrenm case CRYPTO_DATA_MBLK:
8041694Sdarrenm ret = sha2_digest_update_mblk(&sha2_ctx, data);
8051694Sdarrenm break;
8061694Sdarrenm default:
8071694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
8081694Sdarrenm }
8091694Sdarrenm
8101694Sdarrenm /*
8111694Sdarrenm * Do the SHA updates on the specified input data.
8121694Sdarrenm */
8131694Sdarrenm
8141694Sdarrenm if (ret != CRYPTO_SUCCESS) {
8151694Sdarrenm /* the update failed, bail */
8161694Sdarrenm digest->cd_length = 0;
8171694Sdarrenm return (ret);
8181694Sdarrenm }
8191694Sdarrenm
8201694Sdarrenm if (mechanism->cm_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE)
8211694Sdarrenm sha_digest_len = SHA256_DIGEST_LENGTH;
8221694Sdarrenm else
8231694Sdarrenm sha_digest_len = SHA512_DIGEST_LENGTH;
8241694Sdarrenm
8251694Sdarrenm /*
8261694Sdarrenm * Do a SHA2 final, must be done separately since the digest
8271694Sdarrenm * type can be different than the input data type.
8281694Sdarrenm */
8291694Sdarrenm switch (digest->cd_format) {
8301694Sdarrenm case CRYPTO_DATA_RAW:
8311694Sdarrenm SHA2Final((unsigned char *)digest->cd_raw.iov_base +
8321694Sdarrenm digest->cd_offset, &sha2_ctx);
8331694Sdarrenm break;
8341694Sdarrenm case CRYPTO_DATA_UIO:
8351694Sdarrenm ret = sha2_digest_final_uio(&sha2_ctx, digest,
8361694Sdarrenm sha_digest_len, NULL);
8371694Sdarrenm break;
8381694Sdarrenm case CRYPTO_DATA_MBLK:
8391694Sdarrenm ret = sha2_digest_final_mblk(&sha2_ctx, digest,
8401694Sdarrenm sha_digest_len, NULL);
8411694Sdarrenm break;
8421694Sdarrenm default:
8431694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
8441694Sdarrenm }
8451694Sdarrenm
8461694Sdarrenm if (ret == CRYPTO_SUCCESS)
8471694Sdarrenm digest->cd_length = sha_digest_len;
8481694Sdarrenm else
8491694Sdarrenm digest->cd_length = 0;
8501694Sdarrenm
8511694Sdarrenm return (ret);
8521694Sdarrenm }
8531694Sdarrenm
8541694Sdarrenm /*
8551694Sdarrenm * KCF software provider mac entry points.
8561694Sdarrenm *
8571694Sdarrenm * SHA2 HMAC is: SHA2(key XOR opad, SHA2(key XOR ipad, text))
8581694Sdarrenm *
8591694Sdarrenm * Init:
8601694Sdarrenm * The initialization routine initializes what we denote
8611694Sdarrenm * as the inner and outer contexts by doing
8621694Sdarrenm * - for inner context: SHA2(key XOR ipad)
8631694Sdarrenm * - for outer context: SHA2(key XOR opad)
8641694Sdarrenm *
8651694Sdarrenm * Update:
8661694Sdarrenm * Each subsequent SHA2 HMAC update will result in an
8671694Sdarrenm * update of the inner context with the specified data.
8681694Sdarrenm *
8691694Sdarrenm * Final:
8701694Sdarrenm * The SHA2 HMAC final will do a SHA2 final operation on the
8711694Sdarrenm * inner context, and the resulting digest will be used
8721694Sdarrenm * as the data for an update on the outer context. Last
8731694Sdarrenm * but not least, a SHA2 final on the outer context will
8741694Sdarrenm * be performed to obtain the SHA2 HMAC digest to return
8751694Sdarrenm * to the user.
8761694Sdarrenm */
8771694Sdarrenm
8781694Sdarrenm /*
8791694Sdarrenm * Initialize a SHA2-HMAC context.
8801694Sdarrenm */
8811694Sdarrenm static void
sha2_mac_init_ctx(sha2_hmac_ctx_t * ctx,void * keyval,uint_t length_in_bytes)8821694Sdarrenm sha2_mac_init_ctx(sha2_hmac_ctx_t *ctx, void *keyval, uint_t length_in_bytes)
8831694Sdarrenm {
8841694Sdarrenm uint64_t ipad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)];
8851694Sdarrenm uint64_t opad[SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t)];
8861694Sdarrenm int i, block_size, blocks_per_int64;
8871694Sdarrenm
8881694Sdarrenm /* Determine the block size */
8891694Sdarrenm if (ctx->hc_mech_type <= SHA256_HMAC_GEN_MECH_INFO_TYPE) {
8901694Sdarrenm block_size = SHA256_HMAC_BLOCK_SIZE;
8911694Sdarrenm blocks_per_int64 = SHA256_HMAC_BLOCK_SIZE / sizeof (uint64_t);
8921694Sdarrenm } else {
8931694Sdarrenm block_size = SHA512_HMAC_BLOCK_SIZE;
8941694Sdarrenm blocks_per_int64 = SHA512_HMAC_BLOCK_SIZE / sizeof (uint64_t);
8951694Sdarrenm }
8961694Sdarrenm
8971694Sdarrenm (void) bzero(ipad, block_size);
8981694Sdarrenm (void) bzero(opad, block_size);
8991694Sdarrenm (void) bcopy(keyval, ipad, length_in_bytes);
9001694Sdarrenm (void) bcopy(keyval, opad, length_in_bytes);
9011694Sdarrenm
9021694Sdarrenm /* XOR key with ipad (0x36) and opad (0x5c) */
9031694Sdarrenm for (i = 0; i < blocks_per_int64; i ++) {
9041694Sdarrenm ipad[i] ^= 0x3636363636363636;
9051694Sdarrenm opad[i] ^= 0x5c5c5c5c5c5c5c5c;
9061694Sdarrenm }
9071694Sdarrenm
9081694Sdarrenm /* perform SHA2 on ipad */
9091694Sdarrenm SHA2Init(ctx->hc_mech_type, &ctx->hc_icontext);
9101694Sdarrenm SHA2Update(&ctx->hc_icontext, (uint8_t *)ipad, block_size);
9111694Sdarrenm
9121694Sdarrenm /* perform SHA2 on opad */
9131694Sdarrenm SHA2Init(ctx->hc_mech_type, &ctx->hc_ocontext);
9141694Sdarrenm SHA2Update(&ctx->hc_ocontext, (uint8_t *)opad, block_size);
9151694Sdarrenm
9161694Sdarrenm }
9171694Sdarrenm
9181694Sdarrenm /*
9191694Sdarrenm */
9201694Sdarrenm static int
sha2_mac_init(crypto_ctx_t * ctx,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)9211694Sdarrenm sha2_mac_init(crypto_ctx_t *ctx, crypto_mechanism_t *mechanism,
9221694Sdarrenm crypto_key_t *key, crypto_spi_ctx_template_t ctx_template,
9231694Sdarrenm crypto_req_handle_t req)
9241694Sdarrenm {
9251694Sdarrenm int ret = CRYPTO_SUCCESS;
9261694Sdarrenm uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
9271694Sdarrenm uint_t sha_digest_len, sha_hmac_block_size;
9281694Sdarrenm
9291694Sdarrenm /*
93011141Sopensolaris@drydog.com * Set the digest length and block size to values appropriate to the
9311694Sdarrenm * mechanism
9321694Sdarrenm */
9331694Sdarrenm switch (mechanism->cm_type) {
9341694Sdarrenm case SHA256_HMAC_MECH_INFO_TYPE:
9351694Sdarrenm case SHA256_HMAC_GEN_MECH_INFO_TYPE:
9361694Sdarrenm sha_digest_len = SHA256_DIGEST_LENGTH;
9371694Sdarrenm sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE;
9381694Sdarrenm break;
9391694Sdarrenm case SHA384_HMAC_MECH_INFO_TYPE:
9401694Sdarrenm case SHA384_HMAC_GEN_MECH_INFO_TYPE:
9411694Sdarrenm case SHA512_HMAC_MECH_INFO_TYPE:
9421694Sdarrenm case SHA512_HMAC_GEN_MECH_INFO_TYPE:
9431694Sdarrenm sha_digest_len = SHA512_DIGEST_LENGTH;
9441694Sdarrenm sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
9451694Sdarrenm break;
9461694Sdarrenm default:
9471694Sdarrenm return (CRYPTO_MECHANISM_INVALID);
9481694Sdarrenm }
9491694Sdarrenm
9501694Sdarrenm if (key->ck_format != CRYPTO_KEY_RAW)
9511694Sdarrenm return (CRYPTO_ARGUMENTS_BAD);
9521694Sdarrenm
9531694Sdarrenm ctx->cc_provider_private = kmem_alloc(sizeof (sha2_hmac_ctx_t),
9541694Sdarrenm crypto_kmflag(req));
9551694Sdarrenm if (ctx->cc_provider_private == NULL)
9561694Sdarrenm return (CRYPTO_HOST_MEMORY);
9571694Sdarrenm
9584072Skrishna PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type = mechanism->cm_type;
9591694Sdarrenm if (ctx_template != NULL) {
9601694Sdarrenm /* reuse context template */
9611694Sdarrenm bcopy(ctx_template, PROV_SHA2_HMAC_CTX(ctx),
9621694Sdarrenm sizeof (sha2_hmac_ctx_t));
9631694Sdarrenm } else {
9641694Sdarrenm /* no context template, compute context */
9651694Sdarrenm if (keylen_in_bytes > sha_hmac_block_size) {
9661694Sdarrenm uchar_t digested_key[SHA512_DIGEST_LENGTH];
9671694Sdarrenm sha2_hmac_ctx_t *hmac_ctx = ctx->cc_provider_private;
9681694Sdarrenm
9691694Sdarrenm /*
9701694Sdarrenm * Hash the passed-in key to get a smaller key.
9711694Sdarrenm * The inner context is used since it hasn't been
9721694Sdarrenm * initialized yet.
9731694Sdarrenm */
9741694Sdarrenm PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
9751694Sdarrenm &hmac_ctx->hc_icontext,
9761694Sdarrenm key->ck_data, keylen_in_bytes, digested_key);
9771694Sdarrenm sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx),
9781694Sdarrenm digested_key, sha_digest_len);
9791694Sdarrenm } else {
9801694Sdarrenm sha2_mac_init_ctx(PROV_SHA2_HMAC_CTX(ctx),
9811694Sdarrenm key->ck_data, keylen_in_bytes);
9821694Sdarrenm }
9831694Sdarrenm }
9841694Sdarrenm
9851694Sdarrenm /*
9861694Sdarrenm * Get the mechanism parameters, if applicable.
9871694Sdarrenm */
9881694Sdarrenm if (mechanism->cm_type % 3 == 2) {
9891694Sdarrenm if (mechanism->cm_param == NULL ||
9901694Sdarrenm mechanism->cm_param_len != sizeof (ulong_t))
9911694Sdarrenm ret = CRYPTO_MECHANISM_PARAM_INVALID;
9921694Sdarrenm PROV_SHA2_GET_DIGEST_LEN(mechanism,
9931694Sdarrenm PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len);
9941694Sdarrenm if (PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len > sha_digest_len)
9951694Sdarrenm ret = CRYPTO_MECHANISM_PARAM_INVALID;
9961694Sdarrenm }
9971694Sdarrenm
9981694Sdarrenm if (ret != CRYPTO_SUCCESS) {
9991694Sdarrenm bzero(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
10001694Sdarrenm kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
10011694Sdarrenm ctx->cc_provider_private = NULL;
10021694Sdarrenm }
10031694Sdarrenm
10041694Sdarrenm return (ret);
10051694Sdarrenm }
10061694Sdarrenm
10071694Sdarrenm /* ARGSUSED */
10081694Sdarrenm static int
sha2_mac_update(crypto_ctx_t * ctx,crypto_data_t * data,crypto_req_handle_t req)10091694Sdarrenm sha2_mac_update(crypto_ctx_t *ctx, crypto_data_t *data,
10101694Sdarrenm crypto_req_handle_t req)
10111694Sdarrenm {
10121694Sdarrenm int ret = CRYPTO_SUCCESS;
10131694Sdarrenm
10141694Sdarrenm ASSERT(ctx->cc_provider_private != NULL);
10151694Sdarrenm
10161694Sdarrenm /*
10171694Sdarrenm * Do a SHA2 update of the inner context using the specified
10181694Sdarrenm * data.
10191694Sdarrenm */
10201694Sdarrenm switch (data->cd_format) {
10211694Sdarrenm case CRYPTO_DATA_RAW:
10221694Sdarrenm SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_icontext,
10231694Sdarrenm (uint8_t *)data->cd_raw.iov_base + data->cd_offset,
10241694Sdarrenm data->cd_length);
10251694Sdarrenm break;
10261694Sdarrenm case CRYPTO_DATA_UIO:
10271694Sdarrenm ret = sha2_digest_update_uio(
10281694Sdarrenm &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data);
10291694Sdarrenm break;
10301694Sdarrenm case CRYPTO_DATA_MBLK:
10311694Sdarrenm ret = sha2_digest_update_mblk(
10321694Sdarrenm &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext, data);
10331694Sdarrenm break;
10341694Sdarrenm default:
10351694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
10361694Sdarrenm }
10371694Sdarrenm
10381694Sdarrenm return (ret);
10391694Sdarrenm }
10401694Sdarrenm
10411694Sdarrenm /* ARGSUSED */
10421694Sdarrenm static int
sha2_mac_final(crypto_ctx_t * ctx,crypto_data_t * mac,crypto_req_handle_t req)10431694Sdarrenm sha2_mac_final(crypto_ctx_t *ctx, crypto_data_t *mac, crypto_req_handle_t req)
10441694Sdarrenm {
10451694Sdarrenm int ret = CRYPTO_SUCCESS;
10461694Sdarrenm uchar_t digest[SHA512_DIGEST_LENGTH];
10471694Sdarrenm uint32_t digest_len, sha_digest_len;
10481694Sdarrenm
10491694Sdarrenm ASSERT(ctx->cc_provider_private != NULL);
10501694Sdarrenm
105111141Sopensolaris@drydog.com /* Set the digest lengths to values appropriate to the mechanism */
10521694Sdarrenm switch (PROV_SHA2_HMAC_CTX(ctx)->hc_mech_type) {
10531694Sdarrenm case SHA256_HMAC_MECH_INFO_TYPE:
10541694Sdarrenm sha_digest_len = digest_len = SHA256_DIGEST_LENGTH;
10551694Sdarrenm break;
10561694Sdarrenm case SHA384_HMAC_MECH_INFO_TYPE:
10574072Skrishna sha_digest_len = digest_len = SHA384_DIGEST_LENGTH;
10584072Skrishna break;
10591694Sdarrenm case SHA512_HMAC_MECH_INFO_TYPE:
10601694Sdarrenm sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
10611694Sdarrenm break;
10621694Sdarrenm case SHA256_HMAC_GEN_MECH_INFO_TYPE:
10631694Sdarrenm sha_digest_len = SHA256_DIGEST_LENGTH;
10641694Sdarrenm digest_len = PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len;
10651694Sdarrenm break;
10661694Sdarrenm case SHA384_HMAC_GEN_MECH_INFO_TYPE:
10671694Sdarrenm case SHA512_HMAC_GEN_MECH_INFO_TYPE:
10681694Sdarrenm sha_digest_len = SHA512_DIGEST_LENGTH;
10691694Sdarrenm digest_len = PROV_SHA2_HMAC_CTX(ctx)->hc_digest_len;
10701694Sdarrenm break;
10711694Sdarrenm }
10721694Sdarrenm
10731694Sdarrenm /*
10741694Sdarrenm * We need to just return the length needed to store the output.
10751694Sdarrenm * We should not destroy the context for the following cases.
10761694Sdarrenm */
10771694Sdarrenm if ((mac->cd_length == 0) || (mac->cd_length < digest_len)) {
10781694Sdarrenm mac->cd_length = digest_len;
10791694Sdarrenm return (CRYPTO_BUFFER_TOO_SMALL);
10801694Sdarrenm }
10811694Sdarrenm
10821694Sdarrenm /*
10831694Sdarrenm * Do a SHA2 final on the inner context.
10841694Sdarrenm */
10851694Sdarrenm SHA2Final(digest, &PROV_SHA2_HMAC_CTX(ctx)->hc_icontext);
10861694Sdarrenm
10871694Sdarrenm /*
10881694Sdarrenm * Do a SHA2 update on the outer context, feeding the inner
10891694Sdarrenm * digest as data.
10901694Sdarrenm */
10911694Sdarrenm SHA2Update(&PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, digest,
10921694Sdarrenm sha_digest_len);
10931694Sdarrenm
10941694Sdarrenm /*
10951694Sdarrenm * Do a SHA2 final on the outer context, storing the computing
10961694Sdarrenm * digest in the users buffer.
10971694Sdarrenm */
10981694Sdarrenm switch (mac->cd_format) {
10991694Sdarrenm case CRYPTO_DATA_RAW:
11001694Sdarrenm if (digest_len != sha_digest_len) {
11011694Sdarrenm /*
11021694Sdarrenm * The caller requested a short digest. Digest
11031694Sdarrenm * into a scratch buffer and return to
11041694Sdarrenm * the user only what was requested.
11051694Sdarrenm */
11061694Sdarrenm SHA2Final(digest,
11071694Sdarrenm &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext);
11081694Sdarrenm bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
11091694Sdarrenm mac->cd_offset, digest_len);
11101694Sdarrenm } else {
11111694Sdarrenm SHA2Final((unsigned char *)mac->cd_raw.iov_base +
11121694Sdarrenm mac->cd_offset,
11131694Sdarrenm &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext);
11141694Sdarrenm }
11151694Sdarrenm break;
11161694Sdarrenm case CRYPTO_DATA_UIO:
11171694Sdarrenm ret = sha2_digest_final_uio(
11181694Sdarrenm &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac,
11191694Sdarrenm digest_len, digest);
11201694Sdarrenm break;
11211694Sdarrenm case CRYPTO_DATA_MBLK:
11221694Sdarrenm ret = sha2_digest_final_mblk(
11231694Sdarrenm &PROV_SHA2_HMAC_CTX(ctx)->hc_ocontext, mac,
11241694Sdarrenm digest_len, digest);
11251694Sdarrenm break;
11261694Sdarrenm default:
11271694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
11281694Sdarrenm }
11291694Sdarrenm
11301694Sdarrenm if (ret == CRYPTO_SUCCESS)
11311694Sdarrenm mac->cd_length = digest_len;
11321694Sdarrenm else
11331694Sdarrenm mac->cd_length = 0;
11341694Sdarrenm
11354072Skrishna bzero(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
11361694Sdarrenm kmem_free(ctx->cc_provider_private, sizeof (sha2_hmac_ctx_t));
11371694Sdarrenm ctx->cc_provider_private = NULL;
11381694Sdarrenm
11391694Sdarrenm return (ret);
11401694Sdarrenm }
11411694Sdarrenm
11421694Sdarrenm #define SHA2_MAC_UPDATE(data, ctx, ret) { \
11431694Sdarrenm switch (data->cd_format) { \
11441694Sdarrenm case CRYPTO_DATA_RAW: \
11451694Sdarrenm SHA2Update(&(ctx).hc_icontext, \
11461694Sdarrenm (uint8_t *)data->cd_raw.iov_base + \
11471694Sdarrenm data->cd_offset, data->cd_length); \
11481694Sdarrenm break; \
11491694Sdarrenm case CRYPTO_DATA_UIO: \
11501694Sdarrenm ret = sha2_digest_update_uio(&(ctx).hc_icontext, data); \
11511694Sdarrenm break; \
11521694Sdarrenm case CRYPTO_DATA_MBLK: \
11531694Sdarrenm ret = sha2_digest_update_mblk(&(ctx).hc_icontext, \
11541694Sdarrenm data); \
11551694Sdarrenm break; \
11561694Sdarrenm default: \
11571694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD; \
11581694Sdarrenm } \
11591694Sdarrenm }
11601694Sdarrenm
11611694Sdarrenm /* ARGSUSED */
11621694Sdarrenm static int
sha2_mac_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * mac,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)11631694Sdarrenm sha2_mac_atomic(crypto_provider_handle_t provider,
11641694Sdarrenm crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
11651694Sdarrenm crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
11661694Sdarrenm crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
11671694Sdarrenm {
11681694Sdarrenm int ret = CRYPTO_SUCCESS;
11691694Sdarrenm uchar_t digest[SHA512_DIGEST_LENGTH];
11701694Sdarrenm sha2_hmac_ctx_t sha2_hmac_ctx;
11711694Sdarrenm uint32_t sha_digest_len, digest_len, sha_hmac_block_size;
11721694Sdarrenm uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
11731694Sdarrenm
11741694Sdarrenm /*
117511141Sopensolaris@drydog.com * Set the digest length and block size to values appropriate to the
11761694Sdarrenm * mechanism
11771694Sdarrenm */
11781694Sdarrenm switch (mechanism->cm_type) {
11791694Sdarrenm case SHA256_HMAC_MECH_INFO_TYPE:
11801694Sdarrenm case SHA256_HMAC_GEN_MECH_INFO_TYPE:
11811694Sdarrenm sha_digest_len = digest_len = SHA256_DIGEST_LENGTH;
11821694Sdarrenm sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE;
11831694Sdarrenm break;
11841694Sdarrenm case SHA384_HMAC_MECH_INFO_TYPE:
11851694Sdarrenm case SHA384_HMAC_GEN_MECH_INFO_TYPE:
11861694Sdarrenm case SHA512_HMAC_MECH_INFO_TYPE:
11871694Sdarrenm case SHA512_HMAC_GEN_MECH_INFO_TYPE:
11881694Sdarrenm sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
11891694Sdarrenm sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
11901694Sdarrenm break;
11911694Sdarrenm default:
11921694Sdarrenm return (CRYPTO_MECHANISM_INVALID);
11931694Sdarrenm }
11941694Sdarrenm
11951694Sdarrenm /* Add support for key by attributes (RFE 4706552) */
11961694Sdarrenm if (key->ck_format != CRYPTO_KEY_RAW)
11971694Sdarrenm return (CRYPTO_ARGUMENTS_BAD);
11981694Sdarrenm
11991694Sdarrenm if (ctx_template != NULL) {
12001694Sdarrenm /* reuse context template */
12011694Sdarrenm bcopy(ctx_template, &sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t));
12021694Sdarrenm } else {
12031694Sdarrenm sha2_hmac_ctx.hc_mech_type = mechanism->cm_type;
12041694Sdarrenm /* no context template, initialize context */
12051694Sdarrenm if (keylen_in_bytes > sha_hmac_block_size) {
12061694Sdarrenm /*
12071694Sdarrenm * Hash the passed-in key to get a smaller key.
12081694Sdarrenm * The inner context is used since it hasn't been
12091694Sdarrenm * initialized yet.
12101694Sdarrenm */
12111694Sdarrenm PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
12121694Sdarrenm &sha2_hmac_ctx.hc_icontext,
12131694Sdarrenm key->ck_data, keylen_in_bytes, digest);
12141694Sdarrenm sha2_mac_init_ctx(&sha2_hmac_ctx, digest,
12151694Sdarrenm sha_digest_len);
12161694Sdarrenm } else {
12171694Sdarrenm sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data,
12181694Sdarrenm keylen_in_bytes);
12191694Sdarrenm }
12201694Sdarrenm }
12211694Sdarrenm
12221694Sdarrenm /* get the mechanism parameters, if applicable */
12231694Sdarrenm if ((mechanism->cm_type % 3) == 2) {
12241694Sdarrenm if (mechanism->cm_param == NULL ||
12251694Sdarrenm mechanism->cm_param_len != sizeof (ulong_t)) {
12261694Sdarrenm ret = CRYPTO_MECHANISM_PARAM_INVALID;
12271694Sdarrenm goto bail;
12281694Sdarrenm }
12291694Sdarrenm PROV_SHA2_GET_DIGEST_LEN(mechanism, digest_len);
12301694Sdarrenm if (digest_len > sha_digest_len) {
12311694Sdarrenm ret = CRYPTO_MECHANISM_PARAM_INVALID;
12321694Sdarrenm goto bail;
12331694Sdarrenm }
12341694Sdarrenm }
12351694Sdarrenm
12361694Sdarrenm /* do a SHA2 update of the inner context using the specified data */
12371694Sdarrenm SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret);
12381694Sdarrenm if (ret != CRYPTO_SUCCESS)
12391694Sdarrenm /* the update failed, free context and bail */
12401694Sdarrenm goto bail;
12411694Sdarrenm
12421694Sdarrenm /*
12431694Sdarrenm * Do a SHA2 final on the inner context.
12441694Sdarrenm */
12451694Sdarrenm SHA2Final(digest, &sha2_hmac_ctx.hc_icontext);
12461694Sdarrenm
12471694Sdarrenm /*
12481694Sdarrenm * Do an SHA2 update on the outer context, feeding the inner
12491694Sdarrenm * digest as data.
12501694Sdarrenm *
12516126Sdanmcd * HMAC-SHA384 needs special handling as the outer hash needs only 48
12526126Sdanmcd * bytes of the inner hash value.
12531694Sdarrenm */
12541694Sdarrenm if (mechanism->cm_type == SHA384_HMAC_MECH_INFO_TYPE ||
12551694Sdarrenm mechanism->cm_type == SHA384_HMAC_GEN_MECH_INFO_TYPE)
12561694Sdarrenm SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest,
12571694Sdarrenm SHA384_DIGEST_LENGTH);
12581694Sdarrenm else
12591694Sdarrenm SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len);
12601694Sdarrenm
12611694Sdarrenm /*
12621694Sdarrenm * Do a SHA2 final on the outer context, storing the computed
12631694Sdarrenm * digest in the users buffer.
12641694Sdarrenm */
12651694Sdarrenm switch (mac->cd_format) {
12661694Sdarrenm case CRYPTO_DATA_RAW:
12671694Sdarrenm if (digest_len != sha_digest_len) {
12681694Sdarrenm /*
12691694Sdarrenm * The caller requested a short digest. Digest
12701694Sdarrenm * into a scratch buffer and return to
12711694Sdarrenm * the user only what was requested.
12721694Sdarrenm */
12731694Sdarrenm SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext);
12741694Sdarrenm bcopy(digest, (unsigned char *)mac->cd_raw.iov_base +
12751694Sdarrenm mac->cd_offset, digest_len);
12761694Sdarrenm } else {
12771694Sdarrenm SHA2Final((unsigned char *)mac->cd_raw.iov_base +
12781694Sdarrenm mac->cd_offset, &sha2_hmac_ctx.hc_ocontext);
12791694Sdarrenm }
12801694Sdarrenm break;
12811694Sdarrenm case CRYPTO_DATA_UIO:
12821694Sdarrenm ret = sha2_digest_final_uio(&sha2_hmac_ctx.hc_ocontext, mac,
12831694Sdarrenm digest_len, digest);
12841694Sdarrenm break;
12851694Sdarrenm case CRYPTO_DATA_MBLK:
12861694Sdarrenm ret = sha2_digest_final_mblk(&sha2_hmac_ctx.hc_ocontext, mac,
12871694Sdarrenm digest_len, digest);
12881694Sdarrenm break;
12891694Sdarrenm default:
12901694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
12911694Sdarrenm }
12921694Sdarrenm
12931694Sdarrenm if (ret == CRYPTO_SUCCESS) {
12941694Sdarrenm mac->cd_length = digest_len;
12951694Sdarrenm return (CRYPTO_SUCCESS);
12961694Sdarrenm }
12971694Sdarrenm bail:
12981694Sdarrenm bzero(&sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t));
12991694Sdarrenm mac->cd_length = 0;
13001694Sdarrenm return (ret);
13011694Sdarrenm }
13021694Sdarrenm
13031694Sdarrenm /* ARGSUSED */
13041694Sdarrenm static int
sha2_mac_verify_atomic(crypto_provider_handle_t provider,crypto_session_id_t session_id,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_data_t * data,crypto_data_t * mac,crypto_spi_ctx_template_t ctx_template,crypto_req_handle_t req)13051694Sdarrenm sha2_mac_verify_atomic(crypto_provider_handle_t provider,
13061694Sdarrenm crypto_session_id_t session_id, crypto_mechanism_t *mechanism,
13071694Sdarrenm crypto_key_t *key, crypto_data_t *data, crypto_data_t *mac,
13081694Sdarrenm crypto_spi_ctx_template_t ctx_template, crypto_req_handle_t req)
13091694Sdarrenm {
13101694Sdarrenm int ret = CRYPTO_SUCCESS;
13111694Sdarrenm uchar_t digest[SHA512_DIGEST_LENGTH];
13121694Sdarrenm sha2_hmac_ctx_t sha2_hmac_ctx;
13131694Sdarrenm uint32_t sha_digest_len, digest_len, sha_hmac_block_size;
13141694Sdarrenm uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
13151694Sdarrenm
13161694Sdarrenm /*
131711141Sopensolaris@drydog.com * Set the digest length and block size to values appropriate to the
13181694Sdarrenm * mechanism
13191694Sdarrenm */
13201694Sdarrenm switch (mechanism->cm_type) {
13211694Sdarrenm case SHA256_HMAC_MECH_INFO_TYPE:
13221694Sdarrenm case SHA256_HMAC_GEN_MECH_INFO_TYPE:
13231694Sdarrenm sha_digest_len = digest_len = SHA256_DIGEST_LENGTH;
13241694Sdarrenm sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE;
13251694Sdarrenm break;
13261694Sdarrenm case SHA384_HMAC_MECH_INFO_TYPE:
13271694Sdarrenm case SHA384_HMAC_GEN_MECH_INFO_TYPE:
13281694Sdarrenm case SHA512_HMAC_MECH_INFO_TYPE:
13291694Sdarrenm case SHA512_HMAC_GEN_MECH_INFO_TYPE:
13301694Sdarrenm sha_digest_len = digest_len = SHA512_DIGEST_LENGTH;
13311694Sdarrenm sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
13321694Sdarrenm break;
13331694Sdarrenm default:
13341694Sdarrenm return (CRYPTO_MECHANISM_INVALID);
13351694Sdarrenm }
13361694Sdarrenm
13371694Sdarrenm /* Add support for key by attributes (RFE 4706552) */
13381694Sdarrenm if (key->ck_format != CRYPTO_KEY_RAW)
13391694Sdarrenm return (CRYPTO_ARGUMENTS_BAD);
13401694Sdarrenm
13411694Sdarrenm if (ctx_template != NULL) {
13421694Sdarrenm /* reuse context template */
13431694Sdarrenm bcopy(ctx_template, &sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t));
13441694Sdarrenm } else {
13459456SMark.Powers@Sun.COM sha2_hmac_ctx.hc_mech_type = mechanism->cm_type;
13461694Sdarrenm /* no context template, initialize context */
13471694Sdarrenm if (keylen_in_bytes > sha_hmac_block_size) {
13481694Sdarrenm /*
13491694Sdarrenm * Hash the passed-in key to get a smaller key.
13501694Sdarrenm * The inner context is used since it hasn't been
13511694Sdarrenm * initialized yet.
13521694Sdarrenm */
13531694Sdarrenm PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
13541694Sdarrenm &sha2_hmac_ctx.hc_icontext,
13551694Sdarrenm key->ck_data, keylen_in_bytes, digest);
13561694Sdarrenm sha2_mac_init_ctx(&sha2_hmac_ctx, digest,
13571694Sdarrenm sha_digest_len);
13581694Sdarrenm } else {
13591694Sdarrenm sha2_mac_init_ctx(&sha2_hmac_ctx, key->ck_data,
13601694Sdarrenm keylen_in_bytes);
13611694Sdarrenm }
13621694Sdarrenm }
13631694Sdarrenm
13641694Sdarrenm /* get the mechanism parameters, if applicable */
13651694Sdarrenm if (mechanism->cm_type % 3 == 2) {
13661694Sdarrenm if (mechanism->cm_param == NULL ||
13671694Sdarrenm mechanism->cm_param_len != sizeof (ulong_t)) {
13681694Sdarrenm ret = CRYPTO_MECHANISM_PARAM_INVALID;
13691694Sdarrenm goto bail;
13701694Sdarrenm }
13711694Sdarrenm PROV_SHA2_GET_DIGEST_LEN(mechanism, digest_len);
13721694Sdarrenm if (digest_len > sha_digest_len) {
13731694Sdarrenm ret = CRYPTO_MECHANISM_PARAM_INVALID;
13741694Sdarrenm goto bail;
13751694Sdarrenm }
13761694Sdarrenm }
13771694Sdarrenm
13781694Sdarrenm if (mac->cd_length != digest_len) {
13791694Sdarrenm ret = CRYPTO_INVALID_MAC;
13801694Sdarrenm goto bail;
13811694Sdarrenm }
13821694Sdarrenm
13831694Sdarrenm /* do a SHA2 update of the inner context using the specified data */
13841694Sdarrenm SHA2_MAC_UPDATE(data, sha2_hmac_ctx, ret);
13851694Sdarrenm if (ret != CRYPTO_SUCCESS)
13861694Sdarrenm /* the update failed, free context and bail */
13871694Sdarrenm goto bail;
13881694Sdarrenm
13891694Sdarrenm /* do a SHA2 final on the inner context */
13901694Sdarrenm SHA2Final(digest, &sha2_hmac_ctx.hc_icontext);
13911694Sdarrenm
13921694Sdarrenm /*
13931694Sdarrenm * Do an SHA2 update on the outer context, feeding the inner
13941694Sdarrenm * digest as data.
13956126Sdanmcd *
13966126Sdanmcd * HMAC-SHA384 needs special handling as the outer hash needs only 48
13976126Sdanmcd * bytes of the inner hash value.
13981694Sdarrenm */
13996126Sdanmcd if (mechanism->cm_type == SHA384_HMAC_MECH_INFO_TYPE ||
14006126Sdanmcd mechanism->cm_type == SHA384_HMAC_GEN_MECH_INFO_TYPE)
14016126Sdanmcd SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest,
14026126Sdanmcd SHA384_DIGEST_LENGTH);
14036126Sdanmcd else
14046126Sdanmcd SHA2Update(&sha2_hmac_ctx.hc_ocontext, digest, sha_digest_len);
14051694Sdarrenm
14061694Sdarrenm /*
14071694Sdarrenm * Do a SHA2 final on the outer context, storing the computed
14081694Sdarrenm * digest in the users buffer.
14091694Sdarrenm */
14101694Sdarrenm SHA2Final(digest, &sha2_hmac_ctx.hc_ocontext);
14111694Sdarrenm
14121694Sdarrenm /*
14131694Sdarrenm * Compare the computed digest against the expected digest passed
14141694Sdarrenm * as argument.
14151694Sdarrenm */
14161694Sdarrenm
14171694Sdarrenm switch (mac->cd_format) {
14181694Sdarrenm
14191694Sdarrenm case CRYPTO_DATA_RAW:
14201694Sdarrenm if (bcmp(digest, (unsigned char *)mac->cd_raw.iov_base +
14211694Sdarrenm mac->cd_offset, digest_len) != 0)
14221694Sdarrenm ret = CRYPTO_INVALID_MAC;
14231694Sdarrenm break;
14241694Sdarrenm
14251694Sdarrenm case CRYPTO_DATA_UIO: {
14261694Sdarrenm off_t offset = mac->cd_offset;
14271694Sdarrenm uint_t vec_idx;
14281694Sdarrenm off_t scratch_offset = 0;
14291694Sdarrenm size_t length = digest_len;
14301694Sdarrenm size_t cur_len;
14311694Sdarrenm
14321694Sdarrenm /* we support only kernel buffer */
14331694Sdarrenm if (mac->cd_uio->uio_segflg != UIO_SYSSPACE)
14341694Sdarrenm return (CRYPTO_ARGUMENTS_BAD);
14351694Sdarrenm
14361694Sdarrenm /* jump to the first iovec containing the expected digest */
14371694Sdarrenm for (vec_idx = 0;
14381694Sdarrenm offset >= mac->cd_uio->uio_iov[vec_idx].iov_len &&
14391694Sdarrenm vec_idx < mac->cd_uio->uio_iovcnt;
14405072Smcpowers offset -= mac->cd_uio->uio_iov[vec_idx++].iov_len)
14415072Smcpowers ;
14421694Sdarrenm if (vec_idx == mac->cd_uio->uio_iovcnt) {
14431694Sdarrenm /*
14441694Sdarrenm * The caller specified an offset that is
14451694Sdarrenm * larger than the total size of the buffers
14461694Sdarrenm * it provided.
14471694Sdarrenm */
14481694Sdarrenm ret = CRYPTO_DATA_LEN_RANGE;
14491694Sdarrenm break;
14501694Sdarrenm }
14511694Sdarrenm
14521694Sdarrenm /* do the comparison of computed digest vs specified one */
14531694Sdarrenm while (vec_idx < mac->cd_uio->uio_iovcnt && length > 0) {
14541694Sdarrenm cur_len = MIN(mac->cd_uio->uio_iov[vec_idx].iov_len -
14551694Sdarrenm offset, length);
14561694Sdarrenm
14571694Sdarrenm if (bcmp(digest + scratch_offset,
14581694Sdarrenm mac->cd_uio->uio_iov[vec_idx].iov_base + offset,
14591694Sdarrenm cur_len) != 0) {
14601694Sdarrenm ret = CRYPTO_INVALID_MAC;
14611694Sdarrenm break;
14621694Sdarrenm }
14631694Sdarrenm
14641694Sdarrenm length -= cur_len;
14651694Sdarrenm vec_idx++;
14661694Sdarrenm scratch_offset += cur_len;
14671694Sdarrenm offset = 0;
14681694Sdarrenm }
14691694Sdarrenm break;
14701694Sdarrenm }
14711694Sdarrenm
14721694Sdarrenm case CRYPTO_DATA_MBLK: {
14731694Sdarrenm off_t offset = mac->cd_offset;
14741694Sdarrenm mblk_t *mp;
14751694Sdarrenm off_t scratch_offset = 0;
14761694Sdarrenm size_t length = digest_len;
14771694Sdarrenm size_t cur_len;
14781694Sdarrenm
14791694Sdarrenm /* jump to the first mblk_t containing the expected digest */
14801694Sdarrenm for (mp = mac->cd_mp; mp != NULL && offset >= MBLKL(mp);
14815072Smcpowers offset -= MBLKL(mp), mp = mp->b_cont)
14825072Smcpowers ;
14831694Sdarrenm if (mp == NULL) {
14841694Sdarrenm /*
14851694Sdarrenm * The caller specified an offset that is larger than
14861694Sdarrenm * the total size of the buffers it provided.
14871694Sdarrenm */
14881694Sdarrenm ret = CRYPTO_DATA_LEN_RANGE;
14891694Sdarrenm break;
14901694Sdarrenm }
14911694Sdarrenm
14921694Sdarrenm while (mp != NULL && length > 0) {
14931694Sdarrenm cur_len = MIN(MBLKL(mp) - offset, length);
14941694Sdarrenm if (bcmp(digest + scratch_offset,
14951694Sdarrenm mp->b_rptr + offset, cur_len) != 0) {
14961694Sdarrenm ret = CRYPTO_INVALID_MAC;
14971694Sdarrenm break;
14981694Sdarrenm }
14991694Sdarrenm
15001694Sdarrenm length -= cur_len;
15011694Sdarrenm mp = mp->b_cont;
15021694Sdarrenm scratch_offset += cur_len;
15031694Sdarrenm offset = 0;
15041694Sdarrenm }
15051694Sdarrenm break;
15061694Sdarrenm }
15071694Sdarrenm
15081694Sdarrenm default:
15091694Sdarrenm ret = CRYPTO_ARGUMENTS_BAD;
15101694Sdarrenm }
15111694Sdarrenm
15121694Sdarrenm return (ret);
15131694Sdarrenm bail:
15141694Sdarrenm bzero(&sha2_hmac_ctx, sizeof (sha2_hmac_ctx_t));
15151694Sdarrenm mac->cd_length = 0;
15161694Sdarrenm return (ret);
15171694Sdarrenm }
15181694Sdarrenm
15191694Sdarrenm /*
15201694Sdarrenm * KCF software provider context management entry points.
15211694Sdarrenm */
15221694Sdarrenm
15231694Sdarrenm /* ARGSUSED */
15241694Sdarrenm static int
sha2_create_ctx_template(crypto_provider_handle_t provider,crypto_mechanism_t * mechanism,crypto_key_t * key,crypto_spi_ctx_template_t * ctx_template,size_t * ctx_template_size,crypto_req_handle_t req)15251694Sdarrenm sha2_create_ctx_template(crypto_provider_handle_t provider,
15261694Sdarrenm crypto_mechanism_t *mechanism, crypto_key_t *key,
15271694Sdarrenm crypto_spi_ctx_template_t *ctx_template, size_t *ctx_template_size,
15281694Sdarrenm crypto_req_handle_t req)
15291694Sdarrenm {
15301694Sdarrenm sha2_hmac_ctx_t *sha2_hmac_ctx_tmpl;
15311694Sdarrenm uint_t keylen_in_bytes = CRYPTO_BITS2BYTES(key->ck_length);
15321694Sdarrenm uint32_t sha_digest_len, sha_hmac_block_size;
15331694Sdarrenm
15341694Sdarrenm /*
153511141Sopensolaris@drydog.com * Set the digest length and block size to values appropriate to the
15361694Sdarrenm * mechanism
15371694Sdarrenm */
15381694Sdarrenm switch (mechanism->cm_type) {
15391694Sdarrenm case SHA256_HMAC_MECH_INFO_TYPE:
15401694Sdarrenm case SHA256_HMAC_GEN_MECH_INFO_TYPE:
15411694Sdarrenm sha_digest_len = SHA256_DIGEST_LENGTH;
15421694Sdarrenm sha_hmac_block_size = SHA256_HMAC_BLOCK_SIZE;
15431694Sdarrenm break;
15441694Sdarrenm case SHA384_HMAC_MECH_INFO_TYPE:
15451694Sdarrenm case SHA384_HMAC_GEN_MECH_INFO_TYPE:
15461694Sdarrenm case SHA512_HMAC_MECH_INFO_TYPE:
15471694Sdarrenm case SHA512_HMAC_GEN_MECH_INFO_TYPE:
15481694Sdarrenm sha_digest_len = SHA512_DIGEST_LENGTH;
15491694Sdarrenm sha_hmac_block_size = SHA512_HMAC_BLOCK_SIZE;
15501694Sdarrenm break;
15511694Sdarrenm default:
15521694Sdarrenm return (CRYPTO_MECHANISM_INVALID);
15531694Sdarrenm }
15541694Sdarrenm
15551694Sdarrenm /* Add support for key by attributes (RFE 4706552) */
15561694Sdarrenm if (key->ck_format != CRYPTO_KEY_RAW)
15571694Sdarrenm return (CRYPTO_ARGUMENTS_BAD);
15581694Sdarrenm
15591694Sdarrenm /*
15601694Sdarrenm * Allocate and initialize SHA2 context.
15611694Sdarrenm */
15621694Sdarrenm sha2_hmac_ctx_tmpl = kmem_alloc(sizeof (sha2_hmac_ctx_t),
15631694Sdarrenm crypto_kmflag(req));
15641694Sdarrenm if (sha2_hmac_ctx_tmpl == NULL)
15651694Sdarrenm return (CRYPTO_HOST_MEMORY);
15661694Sdarrenm
15671694Sdarrenm sha2_hmac_ctx_tmpl->hc_mech_type = mechanism->cm_type;
15681694Sdarrenm
15691694Sdarrenm if (keylen_in_bytes > sha_hmac_block_size) {
15701694Sdarrenm uchar_t digested_key[SHA512_DIGEST_LENGTH];
15711694Sdarrenm
15721694Sdarrenm /*
15731694Sdarrenm * Hash the passed-in key to get a smaller key.
15741694Sdarrenm * The inner context is used since it hasn't been
15751694Sdarrenm * initialized yet.
15761694Sdarrenm */
15771694Sdarrenm PROV_SHA2_DIGEST_KEY(mechanism->cm_type / 3,
15781694Sdarrenm &sha2_hmac_ctx_tmpl->hc_icontext,
15791694Sdarrenm key->ck_data, keylen_in_bytes, digested_key);
15801694Sdarrenm sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, digested_key,
15811694Sdarrenm sha_digest_len);
15821694Sdarrenm } else {
15831694Sdarrenm sha2_mac_init_ctx(sha2_hmac_ctx_tmpl, key->ck_data,
15841694Sdarrenm keylen_in_bytes);
15851694Sdarrenm }
15861694Sdarrenm
15871694Sdarrenm *ctx_template = (crypto_spi_ctx_template_t)sha2_hmac_ctx_tmpl;
15881694Sdarrenm *ctx_template_size = sizeof (sha2_hmac_ctx_t);
15891694Sdarrenm
15901694Sdarrenm return (CRYPTO_SUCCESS);
15911694Sdarrenm }
15921694Sdarrenm
15931694Sdarrenm static int
sha2_free_context(crypto_ctx_t * ctx)15941694Sdarrenm sha2_free_context(crypto_ctx_t *ctx)
15951694Sdarrenm {
15961694Sdarrenm uint_t ctx_len;
15971694Sdarrenm
15981694Sdarrenm if (ctx->cc_provider_private == NULL)
15991694Sdarrenm return (CRYPTO_SUCCESS);
16001694Sdarrenm
16011694Sdarrenm /*
16021694Sdarrenm * We have to free either SHA2 or SHA2-HMAC contexts, which
16031694Sdarrenm * have different lengths.
16041694Sdarrenm *
16051694Sdarrenm * Note: Below is dependent on the mechanism ordering.
16061694Sdarrenm */
16071694Sdarrenm
16081694Sdarrenm if (PROV_SHA2_CTX(ctx)->sc_mech_type % 3 == 0)
16091694Sdarrenm ctx_len = sizeof (sha2_ctx_t);
16101694Sdarrenm else
16111694Sdarrenm ctx_len = sizeof (sha2_hmac_ctx_t);
16121694Sdarrenm
16131694Sdarrenm bzero(ctx->cc_provider_private, ctx_len);
16141694Sdarrenm kmem_free(ctx->cc_provider_private, ctx_len);
16151694Sdarrenm ctx->cc_provider_private = NULL;
16161694Sdarrenm
16171694Sdarrenm return (CRYPTO_SUCCESS);
16181694Sdarrenm }
161910500SHai-May.Chao@Sun.COM
162010500SHai-May.Chao@Sun.COM /*
162110500SHai-May.Chao@Sun.COM * SHA-2 Power-Up Self-Test
162210500SHai-May.Chao@Sun.COM */
162310500SHai-May.Chao@Sun.COM void
sha2_POST(int * rc)162410500SHai-May.Chao@Sun.COM sha2_POST(int *rc)
162510500SHai-May.Chao@Sun.COM {
162610500SHai-May.Chao@Sun.COM
162710500SHai-May.Chao@Sun.COM *rc = fips_sha2_post();
162810500SHai-May.Chao@Sun.COM
162910500SHai-May.Chao@Sun.COM }
1630