17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
572eff6e2Smcpowers * Common Development and Distribution License (the "License").
672eff6e2Smcpowers * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
217c478bd9Sstevel@tonic-gate /*
22*9b009fc1SValerie Bubb Fenwick * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate */
247c478bd9Sstevel@tonic-gate
257c478bd9Sstevel@tonic-gate #include <sys/errno.h>
267c478bd9Sstevel@tonic-gate #include <sys/types.h>
277c478bd9Sstevel@tonic-gate #include <sys/kmem.h>
287c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h>
29894b2776Smcpowers #include <sys/sysmacros.h>
307c478bd9Sstevel@tonic-gate #include <sys/crypto/common.h>
317c478bd9Sstevel@tonic-gate #include <sys/crypto/impl.h>
327c478bd9Sstevel@tonic-gate #include <sys/crypto/api.h>
337c478bd9Sstevel@tonic-gate #include <sys/crypto/spi.h>
347c478bd9Sstevel@tonic-gate #include <sys/crypto/sched_impl.h>
357c478bd9Sstevel@tonic-gate
36894b2776Smcpowers #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
37894b2776Smcpowers #define CRYPTO_DIGEST_OFFSET(f) offsetof(crypto_digest_ops_t, f)
38894b2776Smcpowers
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate * Message digest routines
417c478bd9Sstevel@tonic-gate */
427c478bd9Sstevel@tonic-gate
437c478bd9Sstevel@tonic-gate /*
447c478bd9Sstevel@tonic-gate * The following are the possible returned values common to all the routines
457c478bd9Sstevel@tonic-gate * below. The applicability of some of these return values depends on the
467c478bd9Sstevel@tonic-gate * presence of the arguments.
477c478bd9Sstevel@tonic-gate *
487c478bd9Sstevel@tonic-gate * CRYPTO_SUCCESS: The operation completed successfully.
497c478bd9Sstevel@tonic-gate * CRYPTO_QUEUED: A request was submitted successfully. The callback
507c478bd9Sstevel@tonic-gate * routine will be called when the operation is done.
517c478bd9Sstevel@tonic-gate * CRYPTO_MECHANISM_INVALID or CRYPTO_INVALID_MECH_PARAM
527c478bd9Sstevel@tonic-gate * for problems with the 'mech'.
537c478bd9Sstevel@tonic-gate * CRYPTO_INVALID_DATA for bogus 'data'
547c478bd9Sstevel@tonic-gate * CRYPTO_HOST_MEMORY for failure to allocate memory to handle this work.
557c478bd9Sstevel@tonic-gate * CRYPTO_INVALID_CONTEXT: Not a valid context.
567c478bd9Sstevel@tonic-gate * CRYPTO_BUSY: Cannot process the request now. Schedule a
577c478bd9Sstevel@tonic-gate * crypto_bufcall(), or try later.
587c478bd9Sstevel@tonic-gate * CRYPTO_NOT_SUPPORTED and CRYPTO_MECH_NOT_SUPPORTED:
597c478bd9Sstevel@tonic-gate * No provider is capable of a function or a mechanism.
607c478bd9Sstevel@tonic-gate */
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate * crypto_digest_prov()
657c478bd9Sstevel@tonic-gate *
667c478bd9Sstevel@tonic-gate * Arguments:
677c478bd9Sstevel@tonic-gate * pd: pointer to the descriptor of the provider to use for this
687c478bd9Sstevel@tonic-gate * operation.
697c478bd9Sstevel@tonic-gate * sid: provider session id.
707c478bd9Sstevel@tonic-gate * mech: crypto_mechanism_t pointer.
717c478bd9Sstevel@tonic-gate * mech_type is a valid value previously returned by
727c478bd9Sstevel@tonic-gate * crypto_mech2id();
737c478bd9Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends
747c478bd9Sstevel@tonic-gate * on the standard definition of the mechanism.
757c478bd9Sstevel@tonic-gate * data: The message to be digested.
767c478bd9Sstevel@tonic-gate * digest: Storage for the digest. The length needed depends on the
777c478bd9Sstevel@tonic-gate * mechanism.
787c478bd9Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info.
797c478bd9Sstevel@tonic-gate *
807c478bd9Sstevel@tonic-gate * Description:
817c478bd9Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the
827c478bd9Sstevel@tonic-gate * digesting operation of 'data' on the specified
837c478bd9Sstevel@tonic-gate * provider with the specified session.
847c478bd9Sstevel@tonic-gate * When complete and successful, 'digest' will contain the digest value.
857c478bd9Sstevel@tonic-gate * The caller should hold a reference on the specified provider
867c478bd9Sstevel@tonic-gate * descriptor before calling this function.
877c478bd9Sstevel@tonic-gate *
887c478bd9Sstevel@tonic-gate * Context:
897c478bd9Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'.
907c478bd9Sstevel@tonic-gate *
917c478bd9Sstevel@tonic-gate * Returns:
927c478bd9Sstevel@tonic-gate * See comment in the beginning of the file.
937c478bd9Sstevel@tonic-gate */
947c478bd9Sstevel@tonic-gate int
crypto_digest_prov(crypto_provider_t provider,crypto_session_id_t sid,crypto_mechanism_t * mech,crypto_data_t * data,crypto_data_t * digest,crypto_call_req_t * crq)95894b2776Smcpowers crypto_digest_prov(crypto_provider_t provider, crypto_session_id_t sid,
96894b2776Smcpowers crypto_mechanism_t *mech, crypto_data_t *data, crypto_data_t *digest,
97894b2776Smcpowers crypto_call_req_t *crq)
987c478bd9Sstevel@tonic-gate {
997c478bd9Sstevel@tonic-gate kcf_req_params_t params;
100894b2776Smcpowers kcf_provider_desc_t *pd = provider;
101894b2776Smcpowers kcf_provider_desc_t *real_provider = pd;
102894b2776Smcpowers int rv;
1037c478bd9Sstevel@tonic-gate
1047c478bd9Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd));
105894b2776Smcpowers
106894b2776Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
107436935a1SVladimir Kotal rv = kcf_get_hardware_provider(mech->cm_type, NULL,
108*9b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
109*9b009fc1SValerie Bubb Fenwick CRYPTO_FG_DIGEST_ATOMIC);
110894b2776Smcpowers
111894b2776Smcpowers if (rv != CRYPTO_SUCCESS)
112894b2776Smcpowers return (rv);
113894b2776Smcpowers }
1147c478bd9Sstevel@tonic-gate KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_ATOMIC, sid, mech, NULL,
1157c478bd9Sstevel@tonic-gate data, digest);
1167c478bd9Sstevel@tonic-gate
1177c478bd9Sstevel@tonic-gate /* no crypto context to carry between multiple parts. */
118894b2776Smcpowers rv = kcf_submit_request(real_provider, NULL, crq, ¶ms, B_FALSE);
119894b2776Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
120894b2776Smcpowers KCF_PROV_REFRELE(real_provider);
121894b2776Smcpowers
122894b2776Smcpowers return (rv);
1237c478bd9Sstevel@tonic-gate }
1247c478bd9Sstevel@tonic-gate
1257c478bd9Sstevel@tonic-gate /*
1267c478bd9Sstevel@tonic-gate * Same as crypto_digest_prov(), but relies on the KCF scheduler to
1277c478bd9Sstevel@tonic-gate * choose a provider. See crypto_digest_prov() comments for more information.
1287c478bd9Sstevel@tonic-gate */
1297c478bd9Sstevel@tonic-gate int
crypto_digest(crypto_mechanism_t * mech,crypto_data_t * data,crypto_data_t * digest,crypto_call_req_t * crq)1307c478bd9Sstevel@tonic-gate crypto_digest(crypto_mechanism_t *mech, crypto_data_t *data,
1317c478bd9Sstevel@tonic-gate crypto_data_t *digest, crypto_call_req_t *crq)
1327c478bd9Sstevel@tonic-gate {
1337c478bd9Sstevel@tonic-gate int error;
1347c478bd9Sstevel@tonic-gate kcf_provider_desc_t *pd;
1357c478bd9Sstevel@tonic-gate kcf_req_params_t params;
1367c478bd9Sstevel@tonic-gate kcf_prov_tried_t *list = NULL;
1377c478bd9Sstevel@tonic-gate
1387c478bd9Sstevel@tonic-gate retry:
1397c478bd9Sstevel@tonic-gate /* The pd is returned held */
140436935a1SVladimir Kotal if ((pd = kcf_get_mech_provider(mech->cm_type, NULL, NULL, &error,
141*9b009fc1SValerie Bubb Fenwick list, CRYPTO_FG_DIGEST_ATOMIC, data->cd_length)) == NULL) {
1427c478bd9Sstevel@tonic-gate if (list != NULL)
1437c478bd9Sstevel@tonic-gate kcf_free_triedlist(list);
1447c478bd9Sstevel@tonic-gate return (error);
1457c478bd9Sstevel@tonic-gate }
1467c478bd9Sstevel@tonic-gate
1477c478bd9Sstevel@tonic-gate /* The fast path for SW providers. */
1487c478bd9Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) {
1497c478bd9Sstevel@tonic-gate crypto_mechanism_t lmech;
1507c478bd9Sstevel@tonic-gate
1517c478bd9Sstevel@tonic-gate lmech = *mech;
1527c478bd9Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
1537c478bd9Sstevel@tonic-gate error = KCF_PROV_DIGEST_ATOMIC(pd, pd->pd_sid, &lmech, data,
1547c478bd9Sstevel@tonic-gate digest, KCF_SWFP_RHNDL(crq));
1557c478bd9Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error);
1567c478bd9Sstevel@tonic-gate } else {
157ba5f469cSkrishna if (pd->pd_prov_type == CRYPTO_HW_PROVIDER &&
158ba5f469cSkrishna (pd->pd_flags & CRYPTO_HASH_NO_UPDATE) &&
159ba5f469cSkrishna (data->cd_length > pd->pd_hash_limit)) {
160ba5f469cSkrishna error = CRYPTO_BUFFER_TOO_BIG;
161ba5f469cSkrishna } else {
162ba5f469cSkrishna KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_ATOMIC,
163ba5f469cSkrishna pd->pd_sid, mech, NULL, data, digest);
1647c478bd9Sstevel@tonic-gate
1657c478bd9Sstevel@tonic-gate /* no crypto context to carry between multiple parts. */
166ba5f469cSkrishna error = kcf_submit_request(pd, NULL, crq, ¶ms,
167ba5f469cSkrishna B_FALSE);
168ba5f469cSkrishna }
1697c478bd9Sstevel@tonic-gate }
1707c478bd9Sstevel@tonic-gate
1717c478bd9Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
1727c478bd9Sstevel@tonic-gate IS_RECOVERABLE(error)) {
1737c478bd9Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */
1747c478bd9Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
1757c478bd9Sstevel@tonic-gate goto retry;
1767c478bd9Sstevel@tonic-gate }
1777c478bd9Sstevel@tonic-gate
1787c478bd9Sstevel@tonic-gate if (list != NULL)
1797c478bd9Sstevel@tonic-gate kcf_free_triedlist(list);
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate KCF_PROV_REFRELE(pd);
1827c478bd9Sstevel@tonic-gate return (error);
1837c478bd9Sstevel@tonic-gate }
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate /*
1867c478bd9Sstevel@tonic-gate * crypto_digest_init_prov()
1877c478bd9Sstevel@tonic-gate *
1887c478bd9Sstevel@tonic-gate * pd: pointer to the descriptor of the provider to use for this
1897c478bd9Sstevel@tonic-gate * operation.
1907c478bd9Sstevel@tonic-gate * sid: provider session id.
1917c478bd9Sstevel@tonic-gate * mech: crypto_mechanism_t pointer.
1927c478bd9Sstevel@tonic-gate * mech_type is a valid value previously returned by
1937c478bd9Sstevel@tonic-gate * crypto_mech2id();
1947c478bd9Sstevel@tonic-gate * When the mech's parameter is not NULL, its definition depends
1957c478bd9Sstevel@tonic-gate * on the standard definition of the mechanism.
1967c478bd9Sstevel@tonic-gate * ctxp: Pointer to a crypto_context_t.
1977c478bd9Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info.
1987c478bd9Sstevel@tonic-gate *
1997c478bd9Sstevel@tonic-gate * Description:
2007c478bd9Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the
2017c478bd9Sstevel@tonic-gate * initialization of a message digest operation on the specified
2027c478bd9Sstevel@tonic-gate * provider with the specified session.
2037c478bd9Sstevel@tonic-gate * When complete and successful, 'ctxp' will contain a crypto_context_t
2047c478bd9Sstevel@tonic-gate * valid for later calls to digest_update() and digest_final().
2057c478bd9Sstevel@tonic-gate * The caller should hold a reference on the specified provider
2067c478bd9Sstevel@tonic-gate * descriptor before calling this function.
2077c478bd9Sstevel@tonic-gate */
2087c478bd9Sstevel@tonic-gate int
crypto_digest_init_prov(crypto_provider_t provider,crypto_session_id_t sid,crypto_mechanism_t * mech,crypto_context_t * ctxp,crypto_call_req_t * crq)209894b2776Smcpowers crypto_digest_init_prov(crypto_provider_t provider, crypto_session_id_t sid,
210894b2776Smcpowers crypto_mechanism_t *mech, crypto_context_t *ctxp, crypto_call_req_t *crq)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate int error;
2137c478bd9Sstevel@tonic-gate crypto_ctx_t *ctx;
2147c478bd9Sstevel@tonic-gate kcf_req_params_t params;
215894b2776Smcpowers kcf_provider_desc_t *pd = provider;
216894b2776Smcpowers kcf_provider_desc_t *real_provider = pd;
2177c478bd9Sstevel@tonic-gate
2187c478bd9Sstevel@tonic-gate ASSERT(KCF_PROV_REFHELD(pd));
2197c478bd9Sstevel@tonic-gate
220894b2776Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
221436935a1SVladimir Kotal error = kcf_get_hardware_provider(mech->cm_type, NULL,
222*9b009fc1SValerie Bubb Fenwick CRYPTO_MECH_INVALID, NULL, pd, &real_provider,
223*9b009fc1SValerie Bubb Fenwick CRYPTO_FG_DIGEST);
224894b2776Smcpowers
225894b2776Smcpowers if (error != CRYPTO_SUCCESS)
226894b2776Smcpowers return (error);
227894b2776Smcpowers }
228894b2776Smcpowers
229894b2776Smcpowers /* Allocate and initialize the canonical context */
230894b2776Smcpowers if ((ctx = kcf_new_ctx(crq, real_provider, sid)) == NULL) {
231894b2776Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
232894b2776Smcpowers KCF_PROV_REFRELE(real_provider);
2337c478bd9Sstevel@tonic-gate return (CRYPTO_HOST_MEMORY);
234894b2776Smcpowers }
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate /* The fast path for SW providers. */
2377c478bd9Sstevel@tonic-gate if (CHECK_FASTPATH(crq, pd)) {
2387c478bd9Sstevel@tonic-gate crypto_mechanism_t lmech;
2397c478bd9Sstevel@tonic-gate
2407c478bd9Sstevel@tonic-gate lmech = *mech;
241894b2776Smcpowers KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
242894b2776Smcpowers error = KCF_PROV_DIGEST_INIT(real_provider, ctx, &lmech,
2437c478bd9Sstevel@tonic-gate KCF_SWFP_RHNDL(crq));
2447c478bd9Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error);
2457c478bd9Sstevel@tonic-gate } else {
2467c478bd9Sstevel@tonic-gate KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_INIT, sid,
2477c478bd9Sstevel@tonic-gate mech, NULL, NULL, NULL);
248894b2776Smcpowers error = kcf_submit_request(real_provider, ctx, crq, ¶ms,
249894b2776Smcpowers B_FALSE);
2507c478bd9Sstevel@tonic-gate }
2517c478bd9Sstevel@tonic-gate
252894b2776Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
253894b2776Smcpowers KCF_PROV_REFRELE(real_provider);
254894b2776Smcpowers
2557c478bd9Sstevel@tonic-gate if ((error == CRYPTO_SUCCESS) || (error == CRYPTO_QUEUED))
2567c478bd9Sstevel@tonic-gate *ctxp = (crypto_context_t)ctx;
2577c478bd9Sstevel@tonic-gate else {
2587c478bd9Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx(). */
2597c478bd9Sstevel@tonic-gate KCF_CONTEXT_REFRELE((kcf_context_t *)ctx->cc_framework_private);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate return (error);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * Same as crypto_digest_init_prov(), but relies on the KCF scheduler
2687c478bd9Sstevel@tonic-gate * to choose a provider. See crypto_digest_init_prov() comments for
2697c478bd9Sstevel@tonic-gate * more information.
2707c478bd9Sstevel@tonic-gate */
2717c478bd9Sstevel@tonic-gate int
crypto_digest_init(crypto_mechanism_t * mech,crypto_context_t * ctxp,crypto_call_req_t * crq)2727c478bd9Sstevel@tonic-gate crypto_digest_init(crypto_mechanism_t *mech, crypto_context_t *ctxp,
2737c478bd9Sstevel@tonic-gate crypto_call_req_t *crq)
2747c478bd9Sstevel@tonic-gate {
2757c478bd9Sstevel@tonic-gate int error;
2767c478bd9Sstevel@tonic-gate kcf_provider_desc_t *pd;
2777c478bd9Sstevel@tonic-gate kcf_prov_tried_t *list = NULL;
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate retry:
2807c478bd9Sstevel@tonic-gate /* The pd is returned held */
281436935a1SVladimir Kotal if ((pd = kcf_get_mech_provider(mech->cm_type, NULL, NULL, &error,
282*9b009fc1SValerie Bubb Fenwick list, CRYPTO_FG_DIGEST, 0)) == NULL) {
2837c478bd9Sstevel@tonic-gate if (list != NULL)
2847c478bd9Sstevel@tonic-gate kcf_free_triedlist(list);
2857c478bd9Sstevel@tonic-gate return (error);
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate
288ba5f469cSkrishna if (pd->pd_prov_type == CRYPTO_HW_PROVIDER &&
289ba5f469cSkrishna (pd->pd_flags & CRYPTO_HASH_NO_UPDATE)) {
290ba5f469cSkrishna /*
291ba5f469cSkrishna * The hardware provider has limited digest support.
292ba5f469cSkrishna * So, we fallback early here to using a software provider.
293ba5f469cSkrishna *
294ba5f469cSkrishna * XXX - need to enhance to do the fallback later in
295ba5f469cSkrishna * crypto_digest_update() if the size of accumulated input data
296ba5f469cSkrishna * exceeds the maximum size digestable by hardware provider.
297ba5f469cSkrishna */
298ba5f469cSkrishna error = CRYPTO_BUFFER_TOO_BIG;
299ba5f469cSkrishna } else {
300ba5f469cSkrishna error = crypto_digest_init_prov(pd, pd->pd_sid,
301ba5f469cSkrishna mech, ctxp, crq);
302ba5f469cSkrishna }
3037c478bd9Sstevel@tonic-gate
3047c478bd9Sstevel@tonic-gate if (error != CRYPTO_SUCCESS && error != CRYPTO_QUEUED &&
3057c478bd9Sstevel@tonic-gate IS_RECOVERABLE(error)) {
3067c478bd9Sstevel@tonic-gate /* Add pd to the linked list of providers tried. */
3077c478bd9Sstevel@tonic-gate if (kcf_insert_triedlist(&list, pd, KCF_KMFLAG(crq)) != NULL)
3087c478bd9Sstevel@tonic-gate goto retry;
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate if (list != NULL)
3127c478bd9Sstevel@tonic-gate kcf_free_triedlist(list);
3137c478bd9Sstevel@tonic-gate KCF_PROV_REFRELE(pd);
3147c478bd9Sstevel@tonic-gate return (error);
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate /*
3187c478bd9Sstevel@tonic-gate * crypto_digest_update()
3197c478bd9Sstevel@tonic-gate *
3207c478bd9Sstevel@tonic-gate * Arguments:
3217c478bd9Sstevel@tonic-gate * context: A crypto_context_t initialized by digest_init().
3227c478bd9Sstevel@tonic-gate * data: The part of message to be digested.
3237c478bd9Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info.
3247c478bd9Sstevel@tonic-gate *
3257c478bd9Sstevel@tonic-gate * Description:
3267c478bd9Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs a
3277c478bd9Sstevel@tonic-gate * part of a message digest operation.
3287c478bd9Sstevel@tonic-gate *
3297c478bd9Sstevel@tonic-gate * Context:
3307c478bd9Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'.
3317c478bd9Sstevel@tonic-gate *
3327c478bd9Sstevel@tonic-gate * Returns:
3337c478bd9Sstevel@tonic-gate * See comment in the beginning of the file.
3347c478bd9Sstevel@tonic-gate */
3357c478bd9Sstevel@tonic-gate int
crypto_digest_update(crypto_context_t context,crypto_data_t * data,crypto_call_req_t * cr)3367c478bd9Sstevel@tonic-gate crypto_digest_update(crypto_context_t context, crypto_data_t *data,
3377c478bd9Sstevel@tonic-gate crypto_call_req_t *cr)
3387c478bd9Sstevel@tonic-gate {
3397c478bd9Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context;
3407c478bd9Sstevel@tonic-gate kcf_context_t *kcf_ctx;
3417c478bd9Sstevel@tonic-gate kcf_provider_desc_t *pd;
3427c478bd9Sstevel@tonic-gate int error;
3437c478bd9Sstevel@tonic-gate kcf_req_params_t params;
3447c478bd9Sstevel@tonic-gate
3457c478bd9Sstevel@tonic-gate if ((ctx == NULL) ||
3467c478bd9Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
3477c478bd9Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
3487c478bd9Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT);
3497c478bd9Sstevel@tonic-gate }
3507c478bd9Sstevel@tonic-gate
351894b2776Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
3527c478bd9Sstevel@tonic-gate
3537c478bd9Sstevel@tonic-gate /* The fast path for SW providers. */
3547c478bd9Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) {
3557c478bd9Sstevel@tonic-gate error = KCF_PROV_DIGEST_UPDATE(pd, ctx, data, NULL);
3567c478bd9Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error);
3577c478bd9Sstevel@tonic-gate } else {
358894b2776Smcpowers KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_UPDATE,
359894b2776Smcpowers ctx->cc_session, NULL, NULL, data, NULL);
3607c478bd9Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE);
3617c478bd9Sstevel@tonic-gate }
3627c478bd9Sstevel@tonic-gate
3637c478bd9Sstevel@tonic-gate return (error);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate
3667c478bd9Sstevel@tonic-gate /*
3677c478bd9Sstevel@tonic-gate * crypto_digest_final()
3687c478bd9Sstevel@tonic-gate *
3697c478bd9Sstevel@tonic-gate * Arguments:
3707c478bd9Sstevel@tonic-gate * context: A crypto_context_t initialized by digest_init().
3717c478bd9Sstevel@tonic-gate * digest: The storage for the digest.
3727c478bd9Sstevel@tonic-gate * cr: crypto_call_req_t calling conditions and call back info.
3737c478bd9Sstevel@tonic-gate *
3747c478bd9Sstevel@tonic-gate * Description:
3757c478bd9Sstevel@tonic-gate * Asynchronously submits a request for, or synchronously performs the
3767c478bd9Sstevel@tonic-gate * final part of a message digest operation.
3777c478bd9Sstevel@tonic-gate *
3787c478bd9Sstevel@tonic-gate * Context:
3797c478bd9Sstevel@tonic-gate * Process or interrupt, according to the semantics dictated by the 'cr'.
3807c478bd9Sstevel@tonic-gate *
3817c478bd9Sstevel@tonic-gate * Returns:
3827c478bd9Sstevel@tonic-gate * See comment in the beginning of the file.
3837c478bd9Sstevel@tonic-gate */
3847c478bd9Sstevel@tonic-gate int
crypto_digest_final(crypto_context_t context,crypto_data_t * digest,crypto_call_req_t * cr)3857c478bd9Sstevel@tonic-gate crypto_digest_final(crypto_context_t context, crypto_data_t *digest,
3867c478bd9Sstevel@tonic-gate crypto_call_req_t *cr)
3877c478bd9Sstevel@tonic-gate {
3887c478bd9Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context;
3897c478bd9Sstevel@tonic-gate kcf_context_t *kcf_ctx;
3907c478bd9Sstevel@tonic-gate kcf_provider_desc_t *pd;
3917c478bd9Sstevel@tonic-gate int error;
3927c478bd9Sstevel@tonic-gate kcf_req_params_t params;
3937c478bd9Sstevel@tonic-gate
3947c478bd9Sstevel@tonic-gate if ((ctx == NULL) ||
3957c478bd9Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
3967c478bd9Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
3977c478bd9Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT);
3987c478bd9Sstevel@tonic-gate }
3997c478bd9Sstevel@tonic-gate
400894b2776Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
4017c478bd9Sstevel@tonic-gate
4027c478bd9Sstevel@tonic-gate /* The fast path for SW providers. */
4037c478bd9Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) {
4047c478bd9Sstevel@tonic-gate error = KCF_PROV_DIGEST_FINAL(pd, ctx, digest, NULL);
4057c478bd9Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error);
4067c478bd9Sstevel@tonic-gate } else {
407894b2776Smcpowers KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_FINAL,
408894b2776Smcpowers ctx->cc_session, NULL, NULL, NULL, digest);
4097c478bd9Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE);
4107c478bd9Sstevel@tonic-gate }
4117c478bd9Sstevel@tonic-gate
4127c478bd9Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */
4137c478bd9Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
4147c478bd9Sstevel@tonic-gate return (error);
4157c478bd9Sstevel@tonic-gate }
4167c478bd9Sstevel@tonic-gate
4177c478bd9Sstevel@tonic-gate /*
4187c478bd9Sstevel@tonic-gate * Performs a digest update on the specified key. Note that there is
4197c478bd9Sstevel@tonic-gate * no k-API crypto_digest_key() equivalent of this function.
4207c478bd9Sstevel@tonic-gate */
4217c478bd9Sstevel@tonic-gate int
crypto_digest_key_prov(crypto_context_t context,crypto_key_t * key,crypto_call_req_t * cr)4227c478bd9Sstevel@tonic-gate crypto_digest_key_prov(crypto_context_t context, crypto_key_t *key,
4237c478bd9Sstevel@tonic-gate crypto_call_req_t *cr)
4247c478bd9Sstevel@tonic-gate {
4257c478bd9Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context;
4267c478bd9Sstevel@tonic-gate kcf_context_t *kcf_ctx;
4277c478bd9Sstevel@tonic-gate kcf_provider_desc_t *pd;
4287c478bd9Sstevel@tonic-gate int error;
4297c478bd9Sstevel@tonic-gate kcf_req_params_t params;
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate if ((ctx == NULL) ||
4327c478bd9Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
4337c478bd9Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
4347c478bd9Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT);
4357c478bd9Sstevel@tonic-gate }
4367c478bd9Sstevel@tonic-gate
437894b2776Smcpowers ASSERT(pd->pd_prov_type != CRYPTO_LOGICAL_PROVIDER);
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate /* The fast path for SW providers. */
4407c478bd9Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) {
4417c478bd9Sstevel@tonic-gate error = KCF_PROV_DIGEST_KEY(pd, ctx, key, NULL);
4427c478bd9Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error);
4437c478bd9Sstevel@tonic-gate } else {
4447c478bd9Sstevel@tonic-gate KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_DIGEST_KEY,
445894b2776Smcpowers ctx->cc_session, NULL, key, NULL, NULL);
4467c478bd9Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE);
4477c478bd9Sstevel@tonic-gate }
448894b2776Smcpowers
4497c478bd9Sstevel@tonic-gate return (error);
4507c478bd9Sstevel@tonic-gate }
4517c478bd9Sstevel@tonic-gate
4527c478bd9Sstevel@tonic-gate /*
4537c478bd9Sstevel@tonic-gate * See comments for crypto_digest_update() and crypto_digest_final().
4547c478bd9Sstevel@tonic-gate */
4557c478bd9Sstevel@tonic-gate int
crypto_digest_single(crypto_context_t context,crypto_data_t * data,crypto_data_t * digest,crypto_call_req_t * cr)4567c478bd9Sstevel@tonic-gate crypto_digest_single(crypto_context_t context, crypto_data_t *data,
4577c478bd9Sstevel@tonic-gate crypto_data_t *digest, crypto_call_req_t *cr)
4587c478bd9Sstevel@tonic-gate {
4597c478bd9Sstevel@tonic-gate crypto_ctx_t *ctx = (crypto_ctx_t *)context;
4607c478bd9Sstevel@tonic-gate kcf_context_t *kcf_ctx;
4617c478bd9Sstevel@tonic-gate kcf_provider_desc_t *pd;
4627c478bd9Sstevel@tonic-gate int error;
4637c478bd9Sstevel@tonic-gate kcf_req_params_t params;
4647c478bd9Sstevel@tonic-gate
4657c478bd9Sstevel@tonic-gate if ((ctx == NULL) ||
4667c478bd9Sstevel@tonic-gate ((kcf_ctx = (kcf_context_t *)ctx->cc_framework_private) == NULL) ||
4677c478bd9Sstevel@tonic-gate ((pd = kcf_ctx->kc_prov_desc) == NULL)) {
4687c478bd9Sstevel@tonic-gate return (CRYPTO_INVALID_CONTEXT);
4697c478bd9Sstevel@tonic-gate }
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate
4727c478bd9Sstevel@tonic-gate /* The fast path for SW providers. */
4737c478bd9Sstevel@tonic-gate if (CHECK_FASTPATH(cr, pd)) {
4747c478bd9Sstevel@tonic-gate error = KCF_PROV_DIGEST(pd, ctx, data, digest, NULL);
4757c478bd9Sstevel@tonic-gate KCF_PROV_INCRSTATS(pd, error);
4767c478bd9Sstevel@tonic-gate } else {
4777c478bd9Sstevel@tonic-gate KCF_WRAP_DIGEST_OPS_PARAMS(¶ms, KCF_OP_SINGLE, pd->pd_sid,
4787c478bd9Sstevel@tonic-gate NULL, NULL, data, digest);
4797c478bd9Sstevel@tonic-gate error = kcf_submit_request(pd, ctx, cr, ¶ms, B_FALSE);
4807c478bd9Sstevel@tonic-gate }
4817c478bd9Sstevel@tonic-gate
4827c478bd9Sstevel@tonic-gate /* Release the hold done in kcf_new_ctx() during init step. */
4837c478bd9Sstevel@tonic-gate KCF_CONTEXT_COND_RELEASE(error, kcf_ctx);
4847c478bd9Sstevel@tonic-gate return (error);
4857c478bd9Sstevel@tonic-gate }
486