/*
 * Returns the provider descriptor corresponding to the specified
 * device name and instance. A REFHOLD is done on the descriptor
 * before it is returned to the caller. It is the responsibility
 * of the caller to do a REFRELE once it is done with the provider
 * descriptor. Only hardware providers are returned by this function.
 */
kcf_provider_desc_t *
kcf_prov_tab_lookup_by_dev(char *name, uint_t instance)
{
	kcf_provider_desc_t *prov_desc;
	uint_t i;

	mutex_enter(&prov_tab_mutex);

	for (i = 0; i < KCF_MAX_PROVIDERS; i++) {
		if ((prov_desc = prov_tab[i]) != NULL &&
		    (!KCF_IS_PROV_REMOVED(prov_desc)) &&
		    prov_desc->pd_prov_type == CRYPTO_HW_PROVIDER) {
			ASSERT(prov_desc->pd_name != NULL);
			if (strncmp(prov_desc->pd_name, name,
			    MAXNAMELEN) == 0 &&
			    prov_desc->pd_instance == instance) {
				KCF_PROV_REFHOLD(prov_desc);
				mutex_exit(&prov_tab_mutex);
				return (prov_desc);
			}
		}
	}

	mutex_exit(&prov_tab_mutex);
	return (NULL);
}
Example #2
0
/*
 * We're done with this framework context, so free it. Note that freeing
 * framework context (kcf_context) frees the global context (crypto_ctx).
 *
 * The provider is responsible for freeing provider private context after a
 * final or single operation and resetting the cc_provider_private field
 * to NULL. It should do this before it notifies the framework of the
 * completion. We still need to call KCF_PROV_FREE_CONTEXT to handle cases
 * like crypto_cancel_ctx(9f).
 */
void
kcf_free_context(kcf_context_t *kcf_ctx)
{
	kcf_provider_desc_t *pd = kcf_ctx->kc_prov_desc;
	crypto_ctx_t *gctx = &kcf_ctx->kc_glbl_ctx;
	kcf_context_t *kcf_secondctx = kcf_ctx->kc_secondctx;

	/* Release the second context, if any */

	if (kcf_secondctx != NULL)
		KCF_CONTEXT_REFRELE(kcf_secondctx);

	if (gctx->cc_provider_private != NULL) {
		mutex_enter(&pd->pd_lock);
		if (!KCF_IS_PROV_REMOVED(pd)) {
			/*
			 * Increment the provider's internal refcnt so it
			 * doesn't unregister from the framework while
			 * we're calling the entry point.
			 */
			KCF_PROV_IREFHOLD(pd);
			mutex_exit(&pd->pd_lock);
			(void) KCF_PROV_FREE_CONTEXT(pd, gctx);
			KCF_PROV_IREFRELE(pd);
		} else {
			mutex_exit(&pd->pd_lock);
		}
	}

	/* kcf_ctx->kc_prov_desc has a hold on pd */
	KCF_PROV_REFRELE(kcf_ctx->kc_prov_desc);

	/* check if this context is shared with a software provider */
	if ((gctx->cc_flags & CRYPTO_INIT_OPSTATE) &&
	    kcf_ctx->kc_sw_prov_desc != NULL) {
		KCF_PROV_REFRELE(kcf_ctx->kc_sw_prov_desc);
	}

	kmem_cache_free(kcf_context_cache, kcf_ctx);
}