1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file contains the core framework routines for the 28 * kernel cryptographic framework. These routines are at the 29 * layer, between the kernel API/ioctls and the SPI. 30 */ 31 32 #include <sys/zfs_context.h> 33 #include <sys/crypto/common.h> 34 #include <sys/crypto/impl.h> 35 #include <sys/crypto/sched_impl.h> 36 #include <sys/crypto/api.h> 37 38 /* kmem caches used by the scheduler */ 39 static kmem_cache_t *kcf_context_cache; 40 41 /* 42 * Create a new context. 43 */ 44 crypto_ctx_t * 45 kcf_new_ctx(kcf_provider_desc_t *pd) 46 { 47 crypto_ctx_t *ctx; 48 kcf_context_t *kcf_ctx; 49 50 kcf_ctx = kmem_cache_alloc(kcf_context_cache, KM_SLEEP); 51 if (kcf_ctx == NULL) 52 return (NULL); 53 54 /* initialize the context for the consumer */ 55 kcf_ctx->kc_refcnt = 1; 56 KCF_PROV_REFHOLD(pd); 57 kcf_ctx->kc_prov_desc = pd; 58 kcf_ctx->kc_sw_prov_desc = NULL; 59 60 ctx = &kcf_ctx->kc_glbl_ctx; 61 ctx->cc_provider_private = NULL; 62 ctx->cc_framework_private = (void *)kcf_ctx; 63 64 return (ctx); 65 } 66 67 /* 68 * We're done with this framework context, so free it. Note that freeing 69 * framework context (kcf_context) frees the global context (crypto_ctx). 70 * 71 * The provider is responsible for freeing provider private context after a 72 * final or single operation and resetting the cc_provider_private field 73 * to NULL. It should do this before it notifies the framework of the 74 * completion. We still need to call KCF_PROV_FREE_CONTEXT to handle cases 75 * like crypto_cancel_ctx(9f). 76 */ 77 void 78 kcf_free_context(kcf_context_t *kcf_ctx) 79 { 80 kcf_provider_desc_t *pd = kcf_ctx->kc_prov_desc; 81 crypto_ctx_t *gctx = &kcf_ctx->kc_glbl_ctx; 82 83 if (gctx->cc_provider_private != NULL) { 84 mutex_enter(&pd->pd_lock); 85 if (!KCF_IS_PROV_REMOVED(pd)) { 86 /* 87 * Increment the provider's internal refcnt so it 88 * doesn't unregister from the framework while 89 * we're calling the entry point. 90 */ 91 KCF_PROV_IREFHOLD(pd); 92 mutex_exit(&pd->pd_lock); 93 (void) KCF_PROV_FREE_CONTEXT(pd, gctx); 94 KCF_PROV_IREFRELE(pd); 95 } else { 96 mutex_exit(&pd->pd_lock); 97 } 98 } 99 100 /* kcf_ctx->kc_prov_desc has a hold on pd */ 101 KCF_PROV_REFRELE(kcf_ctx->kc_prov_desc); 102 103 kmem_cache_free(kcf_context_cache, kcf_ctx); 104 } 105 106 /* 107 * kmem_cache_alloc constructor for kcf_context structure. 108 */ 109 static int 110 kcf_context_cache_constructor(void *buf, void *cdrarg, int kmflags) 111 { 112 (void) cdrarg, (void) kmflags; 113 kcf_context_t *kctx = (kcf_context_t *)buf; 114 115 kctx->kc_refcnt = 0; 116 117 return (0); 118 } 119 120 static void 121 kcf_context_cache_destructor(void *buf, void *cdrarg) 122 { 123 (void) cdrarg; 124 kcf_context_t *kctx = (kcf_context_t *)buf; 125 126 ASSERT(kctx->kc_refcnt == 0); 127 } 128 129 void 130 kcf_sched_destroy(void) 131 { 132 if (kcf_context_cache) 133 kmem_cache_destroy(kcf_context_cache); 134 } 135 136 /* 137 * Creates and initializes all the structures needed by the framework. 138 */ 139 void 140 kcf_sched_init(void) 141 { 142 /* 143 * Create all the kmem caches needed by the framework. We set the 144 * align argument to 64, to get a slab aligned to 64-byte as well as 145 * have the objects (cache_chunksize) to be a 64-byte multiple. 146 * This helps to avoid false sharing as this is the size of the 147 * CPU cache line. 148 */ 149 kcf_context_cache = kmem_cache_create("kcf_context_cache", 150 sizeof (struct kcf_context), 64, kcf_context_cache_constructor, 151 kcf_context_cache_destructor, NULL, NULL, NULL, 0); 152 } 153