The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/contrib/openzfs/module/icp/core/kcf_prov_tabs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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 https://opensource.org/licenses/CDDL-1.0.
   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 is part of the core Kernel Cryptographic Framework.
   28  * It implements the management of tables of Providers. Entries to
   29  * added and removed when cryptographic providers register with
   30  * and unregister from the framework, respectively. The KCF scheduler
   31  * and ioctl pseudo driver call this function to obtain the list
   32  * of available providers.
   33  *
   34  * The provider table is indexed by crypto_provider_id_t. Each
   35  * element of the table contains a pointer to a provider descriptor,
   36  * or NULL if the entry is free.
   37  *
   38  * This file also implements helper functions to allocate and free
   39  * provider descriptors.
   40  */
   41 
   42 #include <sys/zfs_context.h>
   43 #include <sys/crypto/common.h>
   44 #include <sys/crypto/impl.h>
   45 #include <sys/crypto/sched_impl.h>
   46 #include <sys/crypto/spi.h>
   47 
   48 #define KCF_MAX_PROVIDERS       8       /* max number of providers */
   49 
   50 /*
   51  * Prov_tab is an array of providers which is updated when
   52  * a crypto provider registers with kcf. The provider calls the
   53  * SPI routine, crypto_register_provider(), which in turn calls
   54  * kcf_prov_tab_add_provider().
   55  *
   56  * A provider unregisters by calling crypto_unregister_provider()
   57  * which triggers the removal of the prov_tab entry.
   58  * It also calls kcf_remove_mech_provider().
   59  *
   60  * prov_tab entries are not updated from kcf.conf or by cryptoadm(1M).
   61  */
   62 static kcf_provider_desc_t *prov_tab[KCF_MAX_PROVIDERS];
   63 static kmutex_t prov_tab_mutex; /* ensure exclusive access to the table */
   64 static uint_t prov_tab_num = 0; /* number of providers in table */
   65 
   66 void
   67 kcf_prov_tab_destroy(void)
   68 {
   69         mutex_destroy(&prov_tab_mutex);
   70 }
   71 
   72 /*
   73  * Initialize a mutex and the KCF providers table, prov_tab.
   74  * The providers table is dynamically allocated with KCF_MAX_PROVIDERS entries.
   75  * Called from kcf module _init().
   76  */
   77 void
   78 kcf_prov_tab_init(void)
   79 {
   80         mutex_init(&prov_tab_mutex, NULL, MUTEX_DEFAULT, NULL);
   81 }
   82 
   83 /*
   84  * Add a provider to the provider table. If no free entry can be found
   85  * for the new provider, returns CRYPTO_HOST_MEMORY. Otherwise, add
   86  * the provider to the table, initialize the pd_prov_id field
   87  * of the specified provider descriptor to the index in that table,
   88  * and return CRYPTO_SUCCESS. Note that a REFHOLD is done on the
   89  * provider when pointed to by a table entry.
   90  */
   91 int
   92 kcf_prov_tab_add_provider(kcf_provider_desc_t *prov_desc)
   93 {
   94         uint_t i;
   95 
   96         mutex_enter(&prov_tab_mutex);
   97 
   98         /* find free slot in providers table */
   99         for (i = 1; i < KCF_MAX_PROVIDERS && prov_tab[i] != NULL; i++)
  100                 ;
  101         if (i == KCF_MAX_PROVIDERS) {
  102                 /* ran out of providers entries */
  103                 mutex_exit(&prov_tab_mutex);
  104                 cmn_err(CE_WARN, "out of providers entries");
  105                 return (CRYPTO_HOST_MEMORY);
  106         }
  107 
  108         /* initialize entry */
  109         prov_tab[i] = prov_desc;
  110         KCF_PROV_REFHOLD(prov_desc);
  111         KCF_PROV_IREFHOLD(prov_desc);
  112         prov_tab_num++;
  113 
  114         mutex_exit(&prov_tab_mutex);
  115 
  116         /* update provider descriptor */
  117         prov_desc->pd_prov_id = i;
  118 
  119         /*
  120          * The KCF-private provider handle is defined as the internal
  121          * provider id.
  122          */
  123         prov_desc->pd_kcf_prov_handle =
  124             (crypto_kcf_provider_handle_t)prov_desc->pd_prov_id;
  125 
  126         return (CRYPTO_SUCCESS);
  127 }
  128 
  129 /*
  130  * Remove the provider specified by its id. A REFRELE is done on the
  131  * corresponding provider descriptor before this function returns.
  132  * Returns CRYPTO_UNKNOWN_PROVIDER if the provider id is not valid.
  133  */
  134 int
  135 kcf_prov_tab_rem_provider(crypto_provider_id_t prov_id)
  136 {
  137         kcf_provider_desc_t *prov_desc;
  138 
  139         /*
  140          * Validate provider id, since it can be specified by a 3rd-party
  141          * provider.
  142          */
  143 
  144         mutex_enter(&prov_tab_mutex);
  145         if (prov_id >= KCF_MAX_PROVIDERS ||
  146             ((prov_desc = prov_tab[prov_id]) == NULL)) {
  147                 mutex_exit(&prov_tab_mutex);
  148                 return (CRYPTO_INVALID_PROVIDER_ID);
  149         }
  150         mutex_exit(&prov_tab_mutex);
  151 
  152         /*
  153          * The provider id must remain valid until the associated provider
  154          * descriptor is freed. For this reason, we simply release our
  155          * reference to the descriptor here. When the reference count
  156          * reaches zero, kcf_free_provider_desc() will be invoked and
  157          * the associated entry in the providers table will be released
  158          * at that time.
  159          */
  160 
  161         KCF_PROV_IREFRELE(prov_desc);
  162         KCF_PROV_REFRELE(prov_desc);
  163 
  164         return (CRYPTO_SUCCESS);
  165 }
  166 
  167 /*
  168  * Returns the provider descriptor corresponding to the specified
  169  * provider id. A REFHOLD is done on the descriptor before it is
  170  * returned to the caller. It is the responsibility of the caller
  171  * to do a REFRELE once it is done with the provider descriptor.
  172  */
  173 kcf_provider_desc_t *
  174 kcf_prov_tab_lookup(crypto_provider_id_t prov_id)
  175 {
  176         kcf_provider_desc_t *prov_desc;
  177 
  178         mutex_enter(&prov_tab_mutex);
  179 
  180         prov_desc = prov_tab[prov_id];
  181 
  182         if (prov_desc == NULL) {
  183                 mutex_exit(&prov_tab_mutex);
  184                 return (NULL);
  185         }
  186 
  187         KCF_PROV_REFHOLD(prov_desc);
  188 
  189         mutex_exit(&prov_tab_mutex);
  190 
  191         return (prov_desc);
  192 }
  193 
  194 /*
  195  * Allocate a provider descriptor. mech_list_count specifies the
  196  * number of mechanisms supported by the providers, and is used
  197  * to allocate storage for the mechanism table.
  198  * This function may sleep while allocating memory, which is OK
  199  * since it is invoked from user context during provider registration.
  200  */
  201 kcf_provider_desc_t *
  202 kcf_alloc_provider_desc(void)
  203 {
  204         kcf_provider_desc_t *desc =
  205             kmem_zalloc(sizeof (kcf_provider_desc_t), KM_SLEEP);
  206 
  207         for (int i = 0; i < KCF_OPS_CLASSSIZE; i++)
  208                 for (int j = 0; j < KCF_MAXMECHTAB; j++)
  209                         desc->pd_mech_indx[i][j] = KCF_INVALID_INDX;
  210 
  211         desc->pd_prov_id = KCF_PROVID_INVALID;
  212         desc->pd_state = KCF_PROV_ALLOCATED;
  213 
  214         mutex_init(&desc->pd_lock, NULL, MUTEX_DEFAULT, NULL);
  215         cv_init(&desc->pd_remove_cv, NULL, CV_DEFAULT, NULL);
  216 
  217         return (desc);
  218 }
  219 
  220 /*
  221  * Called by KCF_PROV_REFRELE when a provider's reference count drops
  222  * to zero. We free the descriptor when the last reference is released.
  223  * However, for providers, we do not free it when there is an
  224  * unregister thread waiting. We signal that thread in this case and
  225  * that thread is responsible for freeing the descriptor.
  226  */
  227 void
  228 kcf_provider_zero_refcnt(kcf_provider_desc_t *desc)
  229 {
  230         mutex_enter(&desc->pd_lock);
  231         if (desc->pd_state == KCF_PROV_REMOVED ||
  232             desc->pd_state == KCF_PROV_DISABLED) {
  233                 desc->pd_state = KCF_PROV_FREED;
  234                 cv_broadcast(&desc->pd_remove_cv);
  235                 mutex_exit(&desc->pd_lock);
  236                 return;
  237         }
  238 
  239         mutex_exit(&desc->pd_lock);
  240         kcf_free_provider_desc(desc);
  241 }
  242 
  243 /*
  244  * Free a provider descriptor.
  245  */
  246 void
  247 kcf_free_provider_desc(kcf_provider_desc_t *desc)
  248 {
  249         if (desc == NULL)
  250                 return;
  251 
  252         mutex_enter(&prov_tab_mutex);
  253         if (desc->pd_prov_id != KCF_PROVID_INVALID) {
  254                 /* release the associated providers table entry */
  255                 ASSERT(prov_tab[desc->pd_prov_id] != NULL);
  256                 prov_tab[desc->pd_prov_id] = NULL;
  257                 prov_tab_num--;
  258         }
  259         mutex_exit(&prov_tab_mutex);
  260 
  261         /* free the kernel memory associated with the provider descriptor */
  262 
  263         mutex_destroy(&desc->pd_lock);
  264         cv_destroy(&desc->pd_remove_cv);
  265 
  266         kmem_free(desc, sizeof (kcf_provider_desc_t));
  267 }
  268 
  269 /*
  270  * Returns in the location pointed to by pd a pointer to the descriptor
  271  * for the provider for the specified mechanism.
  272  * The provider descriptor is returned held and it is the caller's
  273  * responsibility to release it when done. The mechanism entry
  274  * is returned if the optional argument mep is non NULL.
  275  *
  276  * Returns one of the CRYPTO_ * error codes on failure, and
  277  * CRYPTO_SUCCESS on success.
  278  */
  279 int
  280 kcf_get_sw_prov(crypto_mech_type_t mech_type, kcf_provider_desc_t **pd,
  281     kcf_mech_entry_t **mep, boolean_t log_warn)
  282 {
  283         kcf_mech_entry_t *me;
  284 
  285         /* get the mechanism entry for this mechanism */
  286         if (kcf_get_mech_entry(mech_type, &me) != KCF_SUCCESS)
  287                 return (CRYPTO_MECHANISM_INVALID);
  288 
  289         /* Get the provider for this mechanism. */
  290         if (me->me_sw_prov == NULL ||
  291             (*pd = me->me_sw_prov->pm_prov_desc) == NULL) {
  292                 /* no provider for this mechanism */
  293                 if (log_warn)
  294                         cmn_err(CE_WARN, "no provider for \"%s\"\n",
  295                             me->me_name);
  296                 return (CRYPTO_MECH_NOT_SUPPORTED);
  297         }
  298 
  299         KCF_PROV_REFHOLD(*pd);
  300 
  301         if (mep != NULL)
  302                 *mep = me;
  303 
  304         return (CRYPTO_SUCCESS);
  305 }

Cache object: 01605d8c4a7ad90b1f247171b9dc9a72


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.