kcf_dual.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
static int crypto_mac_decrypt_common(crypto_mechanism_t *,
/*
* to use are determined by the KCF dispatcher.
*/
int
{
/*
* First try to find a provider for the encryption mechanism, that
* is also capable of the MAC mechanism.
*/
int error;
/* pd is returned held on success */
return (error);
}
/*
* For SW providers, check the validity of the context template
* It is very rare that the generation number mis-matches, so
* is acceptable to fail here, and let the consumer recover by
* freeing this tmpl and create a new one for the key and new SW
* provider
* Warning! will need to change when multiple software providers
* per mechanism are supported.
*/
sizeof (kcf_dual_req_t));
/* Which one is the the old one ? */
return (CRYPTO_OLD_CTX_TEMPLATE);
}
}
}
if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
/* Need to emulate with 2 internal calls */
/* Allocate and initialize the MAC req for the callback */
return (CRYPTO_HOST_MEMORY);
}
/*
* Careful! we're wrapping-in mac_tmpl instead
* of an spi_mac_tmpl. The callback routine will
* have to validate mac_tmpl, and use the
* mac_ctx_tmpl, once it picks a MAC provider.
*/
}
}
} else {
}
switch (error) {
case CRYPTO_SUCCESS: {
/*
* The encryption step is done. Reuse the encr_req
* for submitting the MAC step.
*/
} else {
ct->dd_offset1;
}
&encr_req);
if (error != CRYPTO_QUEUED) {
}
break;
}
case CRYPTO_QUEUED:
break;
default:
/* Add pd to the linked list of providers tried. */
if (IS_RECOVERABLE(error)) {
goto retry;
}
}
return (error);
}
(prov_mac_mechid != CRYPTO_MECH_INVALID)) {
sizeof (kcf_dual_req_t));
/* Which one is the the old one ? */
return (CRYPTO_OLD_CTX_TEMPLATE);
}
}
}
/* The fast path for SW providers. */
/* careful! structs assignments */
lencr_mech = *encr_mech;
} else {
/* careful! structs assignments */
}
IS_RECOVERABLE(error)) {
/* Add pd to the linked list of providers tried. */
goto retry;
}
return (error);
}
/*
* to use are determined by the KCF dispatcher.
*/
/* ARGSUSED */
int
{
/*
* First try to find a provider for the encryption mechanism, that
* is also capable of the MAC mechanism.
*/
int error;
/* pd is returned held on success */
CHECK_RESTRICT(cr), 0);
return (error);
}
/*
* For SW providers, check the validity of the context template
* It is very rare that the generation number mis-matches, so
* is acceptable to fail here, and let the consumer recover by
* freeing this tmpl and create a new one for the key and new SW
* provider
* Warning! will need to change when multiple software providers
* per mechanism are supported.
*/
if (encr_kcf_context != NULL)
/* Which one is the the old one ? */
return (CRYPTO_OLD_CTX_TEMPLATE);
}
}
}
if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
/* Need to emulate with 2 internal calls */
/*
* We avoid code complexity by limiting the pure async.
* case to be done using only a SW provider.
* XXX - Redo the emulation code below so that we can
* remove this limitation.
*/
!= NULL))
goto retry;
if (encr_kcf_context != NULL)
return (CRYPTO_HOST_MEMORY);
}
if (encr_kcf_context != NULL)
return (CRYPTO_HOST_MEMORY);
}
}
/*
* Trade-off speed vs avoidance of code complexity and
* duplication:
* Could do all the combinations of fastpath / synch / asynch
* for the encryption and the mac steps. Early attempts
* showed the code grew wild and bug-prone, for little gain.
* Therefore, the adaptative asynch case is not implemented.
* It's either pure synchronous, or pure asynchronous.
* We still preserve a fastpath for the pure synchronous
* requests to SW providers.
*/
} else {
/*
* If we did the 'goto retry' then ctx may not
* be NULL. In general, we can't reuse another
* provider's context, so we free it now so
* we don't leak it.
*/
}
if (error == CRYPTO_SUCCESS) {
}
}
if (error != CRYPTO_SUCCESS) {
/* Can't be CRYPTO_QUEUED. return the failure */
if (encr_kcf_context != NULL)
return (error);
}
&mac_context, NULL);
if (error != CRYPTO_SUCCESS) {
/* Should this be an ASSERT() ? */
} else {
mac_kcf_context = (kcf_context_t *)
((crypto_ctx_t *)mac_context)->
}
return (error);
}
/* submit a pure asynchronous request. */
/* careful! structs assignments */
/*
* cmops->em_encr_mech.cm_type will be set when we get to
* kcf_emulate_dual() routine.
*/
/*
* cmops->em_mac_mech.cm_type will be set when we know the
* MAC provider.
*/
/*
* non-NULL ctx->kc_secondctx tells common_submit_request
* that this request uses separate cipher and MAC contexts.
* That function will set ctx->kc_secondctx to the new
* MAC context, once it gets one.
*/
}
return (error);
}
(prov_mac_mechid != CRYPTO_MECH_INVALID)) {
/* Which one is the the old one ? */
return (CRYPTO_OLD_CTX_TEMPLATE);
}
}
}
return (CRYPTO_HOST_MEMORY);
}
}
/* The fast path for SW providers. */
/* careful! structs assignments */
lencr_mech = *encr_mech;
KCF_SWFP_RHNDL(cr));
} else {
/* careful! structs assignments */
}
if ((IS_RECOVERABLE(error)) &&
goto retry;
} else
return (error);
}
/*
*/
/* ARGSUSED */
int
{
int error;
return (CRYPTO_INVALID_CONTEXT);
}
goto out;
}
/* First we submit the encryption request */
/*
* 'ct' is always not NULL.
* A NULL 'pt' means in-place.
*/
else
if (error != CRYPTO_SUCCESS)
goto out;
/*
* call mac_update when there is data to throw in
* the mix. Either an explicitly non-zero ct->dd_len2,
* or the last ciphertext portion.
*/
/*
* The previous encrypt step was an
* accumulation only and didn't produce any
* partial output
*/
goto out;
} else {
}
goto out;
}
/* submit a pure asynchronous request. */
goto out;
}
/* The fast path for SW providers. */
} else {
}
out:
return (error);
}
/*
*/
/* ARGSUSED */
{
int error;
return (CRYPTO_INVALID_CONTEXT);
}
return (CRYPTO_INVALID_CONTEXT);
}
/* Get the last chunk of ciphertext */
if (error != CRYPTO_SUCCESS) {
/*
* Needed here, because the caller of
* crypto_encrypt_mac_final() lost all
* refs to the mac_ctx.
*/
return (error);
}
if (error != CRYPTO_SUCCESS) {
return (error);
}
}
/* and finally, collect the MAC */
return (error);
}
/* submit a pure asynchronous request. */
return (error);
}
/* The fast path for SW providers. */
} else {
}
out:
/* Release the hold done in kcf_new_ctx() during init step. */
return (error);
}
/*
* is determined by the KCF dispatcher.
*/
int
{
}
/*
* is determined by the KCF dispatcher. 'mac' specifies the expected
* value for the MAC. The decryption is not performed if the computed
* MAC does not match the expected MAC.
*/
int
{
}
/*
* Called by both crypto_mac_decrypt() and crypto_mac_verify_decrypt().
* optionally verified if the MACs match before calling the decryption step.
*/
static int
{
/*
* First try to find a provider for the decryption mechanism, that
* is also capable of the MAC mechanism.
* We still favor optimizing the costlier decryption.
*/
int error;
/* pd is returned held on success */
return (CRYPTO_MECH_NOT_SUPPORTED);
}
/*
* For SW providers, check the validity of the context template
* It is very rare that the generation number mis-matches, so
* is acceptable to fail here, and let the consumer recover by
* freeing this tmpl and create a new one for the key and new SW
* provider
*/
sizeof (kcf_dual_req_t));
/* Which one is the the old one ? */
return (CRYPTO_OLD_CTX_TEMPLATE);
}
}
}
if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
/* Need to emulate with 2 internal calls */
/* Prepare the call_req to be submitted for the MAC step */
/*
* allocate, initialize and prepare the
* params for the next step only in the
* first pass (not on every retry).
*/
return (CRYPTO_HOST_MEMORY);
}
}
}
/* 'pd' is the decryption provider. */
if (do_verify)
else
switch (error) {
case CRYPTO_SUCCESS: {
} else {
ct->dd_offset1;
}
} else {
}
if (error != CRYPTO_QUEUED) {
}
break;
}
case CRYPTO_QUEUED:
break;
default:
if (IS_RECOVERABLE(error)) {
goto retry;
}
}
return (error);
}
(prov_mac_mechid != CRYPTO_MECH_INVALID)) {
sizeof (kcf_dual_req_t));
/* Which one is the the old one ? */
return (CRYPTO_OLD_CTX_TEMPLATE);
}
}
}
/* The fast path for SW providers. */
/* careful! structs assignments */
ldecr_mech = *decr_mech;
if (do_verify)
else
} else {
/* careful! structs assignments */
}
IS_RECOVERABLE(error)) {
/* Add pd to the linked list of providers tried. */
goto retry;
}
return (error);
}
/*
* use is determined by the KCF dispatcher.
*/
/* ARGSUSED */
int
{
/*
* First try to find a provider for the decryption mechanism, that
* is also capable of the MAC mechanism.
* We still favor optimizing the costlier decryption.
*/
int error;
/* pd is returned held on success */
CHECK_RESTRICT(cr), 0);
return (error);
}
/*
* For SW providers, check the validity of the context template
* It is very rare that the generation number mis-matches, so
* is acceptable to fail here, and let the consumer recover by
* freeing this tmpl and create a new one for the key and new SW
* provider
* Warning! will need to change when multiple software providers
* per mechanism are supported.
*/
if (decr_kcf_context != NULL)
/* Which one is the the old one ? */
return (CRYPTO_OLD_CTX_TEMPLATE);
}
}
}
if (prov_mac_mechid == CRYPTO_MECH_INVALID) {
/* Need to emulate with 2 internal calls */
/*
* We avoid code complexity by limiting the pure async.
* case to be done using only a SW provider.
* XXX - Redo the emulation code below so that we can
* remove this limitation.
*/
!= NULL))
goto retry;
if (decr_kcf_context != NULL)
return (CRYPTO_HOST_MEMORY);
}
if (decr_kcf_context != NULL)
return (CRYPTO_HOST_MEMORY);
}
}
/*
* Trade-off speed vs avoidance of code complexity and
* duplication:
* Could do all the combinations of fastpath / synch / asynch
* for the decryption and the mac steps. Early attempts
* showed the code grew wild and bug-prone, for little gain.
* Therefore, the adaptative asynch case is not implemented.
* It's either pure synchronous, or pure asynchronous.
* We still preserve a fastpath for the pure synchronous
* requests to SW providers.
*/
&mac_context, NULL);
if (error != CRYPTO_SUCCESS) {
/* Can't be CRYPTO_QUEUED. return the failure */
if (decr_kcf_context != NULL)
return (error);
}
} else {
/*
* If we did the 'goto retry' then ctx may not
* be NULL. In general, we can't reuse another
* provider's context, so we free it now so
* we don't leak it.
*/
}
if (error == CRYPTO_SUCCESS) {
}
}
if (error != CRYPTO_SUCCESS) {
/* Can't be CRYPTO_QUEUED. return the failure */
if (mac_kcf_context != NULL)
return (error);
}
mac_kcf_context = (kcf_context_t *)
((crypto_ctx_t *)mac_context)->
/*
* Here also, the mac context is second. The callback
* case can't overwrite the context returned to
* the caller.
*/
return (error);
}
/* submit a pure asynchronous request. */
/* careful! structs assignments */
/*
* mdops->md_decr_mech.cm_type will be set when we get to
* kcf_emulate_dual() routine.
*/
/*
* mdops->md_mac_mech.cm_type will be set when we know the
* MAC provider.
*/
/*
* non-NULL ctx->kc_secondctx tells common_submit_request
* that this request uses separate cipher and MAC contexts.
* That function will set the MAC context's kc_secondctx to
* this decrypt context.
*/
}
return (error);
}
(prov_mac_mechid != CRYPTO_MECH_INVALID)) {
/* Which one is the the old one ? */
return (CRYPTO_OLD_CTX_TEMPLATE);
}
}
}
return (CRYPTO_HOST_MEMORY);
}
}
/* The fast path for SW providers. */
/* careful! structs assignments */
ldecr_mech = *decr_mech;
KCF_SWFP_RHNDL(cr));
} else {
/* careful! structs assignments */
}
if ((IS_RECOVERABLE(error)) &&
goto retry;
} else
return (error);
}
/*
*/
/* ARGSUSED */
int
{
int error;
return (CRYPTO_INVALID_CONTEXT);
}
goto out;
}
/* First we submit the MAC request */
/*
* 'ct' is always not NULL.
*/
if (error != CRYPTO_SUCCESS)
goto out;
/* Decrypt a different length only when told so */
}
goto out;
}
/* submit a pure asynchronous request. */
goto out;
}
/* The fast path for SW providers. */
} else {
}
out:
return (error);
}
/*
*/
/* ARGSUSED */
int
{
int error;
return (CRYPTO_INVALID_CONTEXT);
}
goto out;
}
/* First we collect the MAC */
if (error != CRYPTO_SUCCESS) {
} else {
/* Get the last chunk of plaintext */
}
return (error);
}
/* submit a pure asynchronous request. */
return (error);
}
/* The fast path for SW providers. */
} else {
}
out:
/* Release the hold done in kcf_new_ctx() during init step. */
return (error);
}
/*
* the k-API.
*/
/* ARGSUSED */
int
{
/*
* RFE 4688647:
* core functions needed by ioctl interface missing from impl.h
*/
return (CRYPTO_NOT_SUPPORTED);
}
/*
* the k-API.
*/
/* ARGSUSED */
int
{
/*
* RFE 4688647:
* core functions needed by ioctl interface missing from impl.h
*/
return (CRYPTO_NOT_SUPPORTED);
}
/*
* the k-API.
*/
/* ARGSUSED */
int
{
/*
* RFE 4688647:
* core functions needed by ioctl interface missing from impl.h
*/
return (CRYPTO_NOT_SUPPORTED);
}
/*
* the k-API.
*/
/* ARGSUSED */
int
{
/*
* RFE 4688647:
* core functions needed by ioctl interface missing from impl.h
*/
return (CRYPTO_NOT_SUPPORTED);
}