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_mech_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 #include <sys/zfs_context.h>
   27 #include <sys/crypto/common.h>
   28 #include <sys/crypto/api.h>
   29 #include <sys/crypto/impl.h>
   30 
   31 /* Cryptographic mechanisms tables and their access functions */
   32 
   33 /*
   34  * Internal numbers assigned to mechanisms are coded as follows:
   35  *
   36  * +----------------+----------------+
   37  * | mech. class    | mech. index    |
   38  * <--- 32-bits --->+<--- 32-bits --->
   39  *
   40  * the mech_class identifies the table the mechanism belongs to.
   41  * mech_index  is the index for that mechanism in the table.
   42  * A mechanism belongs to exactly 1 table.
   43  * The tables are:
   44  * . digest_mechs_tab[] for the msg digest mechs.
   45  * . cipher_mechs_tab[] for encrypt/decrypt and wrap/unwrap mechs.
   46  * . mac_mechs_tab[] for MAC mechs.
   47  * . sign_mechs_tab[] for sign & verify mechs.
   48  * . keyops_mechs_tab[] for key/key pair generation, and key derivation.
   49  * . misc_mechs_tab[] for mechs that don't belong to any of the above.
   50  *
   51  * There are no holes in the tables.
   52  */
   53 
   54 /*
   55  * Locking conventions:
   56  * --------------------
   57  * A mutex is associated with every entry of the tables.
   58  * The mutex is acquired whenever the entry is accessed for
   59  * 1) retrieving the mech_id (comparing the mech name)
   60  * 2) finding a provider for an xxx_init() or atomic operation.
   61  * 3) altering the mechs entry to add or remove a provider.
   62  *
   63  * In 2), after a provider is chosen, its prov_desc is held and the
   64  * entry's mutex must be dropped. The provider's working function (SPI) is
   65  * called outside the mech_entry's mutex.
   66  *
   67  * The number of providers for a particular mechanism is not expected to be
   68  * long enough to justify the cost of using rwlocks, so the per-mechanism
   69  * entry mutex won't be very *hot*.
   70  *
   71  */
   72 
   73                 /* Mechanisms tables */
   74 
   75 
   76 /* RFE 4687834 Will deal with the extensibility of these tables later */
   77 
   78 static kcf_mech_entry_t kcf_digest_mechs_tab[KCF_MAXDIGEST];
   79 static kcf_mech_entry_t kcf_cipher_mechs_tab[KCF_MAXCIPHER];
   80 static kcf_mech_entry_t kcf_mac_mechs_tab[KCF_MAXMAC];
   81 
   82 const kcf_mech_entry_tab_t kcf_mech_tabs_tab[KCF_LAST_OPSCLASS + 1] = {
   83         {0, NULL},                              /* No class zero */
   84         {KCF_MAXDIGEST, kcf_digest_mechs_tab},
   85         {KCF_MAXCIPHER, kcf_cipher_mechs_tab},
   86         {KCF_MAXMAC, kcf_mac_mechs_tab},
   87 };
   88 
   89 static avl_tree_t kcf_mech_hash;
   90 
   91 static int
   92 kcf_mech_hash_compar(const void *lhs, const void *rhs)
   93 {
   94         const kcf_mech_entry_t *l = lhs, *r = rhs;
   95         int cmp = strncmp(l->me_name, r->me_name, CRYPTO_MAX_MECH_NAME);
   96         return ((0 < cmp) - (cmp < 0));
   97 }
   98 
   99 void
  100 kcf_destroy_mech_tabs(void)
  101 {
  102         for (void *cookie = NULL; avl_destroy_nodes(&kcf_mech_hash, &cookie); )
  103                 ;
  104         avl_destroy(&kcf_mech_hash);
  105 }
  106 
  107 /*
  108  * kcf_init_mech_tabs()
  109  *
  110  * Called by the misc/kcf's _init() routine to initialize the tables
  111  * of mech_entry's.
  112  */
  113 void
  114 kcf_init_mech_tabs(void)
  115 {
  116         avl_create(&kcf_mech_hash, kcf_mech_hash_compar,
  117             sizeof (kcf_mech_entry_t), offsetof(kcf_mech_entry_t, me_node));
  118 }
  119 
  120 /*
  121  * kcf_create_mech_entry()
  122  *
  123  * Arguments:
  124  *      . The class of mechanism.
  125  *      . the name of the new mechanism.
  126  *
  127  * Description:
  128  *      Creates a new mech_entry for a mechanism not yet known to the
  129  *      framework.
  130  *      This routine is called by kcf_add_mech_provider, which is
  131  *      in turn invoked for each mechanism supported by a provider.
  132  *      The'class' argument depends on the crypto_func_group_t bitmask
  133  *      in the registering provider's mech_info struct for this mechanism.
  134  *      When there is ambiguity in the mapping between the crypto_func_group_t
  135  *      and a class (dual ops, ...) the KCF_MISC_CLASS should be used.
  136  *
  137  * Context:
  138  *      User context only.
  139  *
  140  * Returns:
  141  *      KCF_INVALID_MECH_CLASS or KCF_INVALID_MECH_NAME if the class or
  142  *      the mechname is bogus.
  143  *      KCF_MECH_TAB_FULL when there is no room left in the mech. tabs.
  144  *      KCF_SUCCESS otherwise.
  145  */
  146 static int
  147 kcf_create_mech_entry(kcf_ops_class_t class, const char *mechname)
  148 {
  149         if ((class < KCF_FIRST_OPSCLASS) || (class > KCF_LAST_OPSCLASS))
  150                 return (KCF_INVALID_MECH_CLASS);
  151 
  152         if ((mechname == NULL) || (mechname[0] == 0))
  153                 return (KCF_INVALID_MECH_NAME);
  154         /*
  155          * First check if the mechanism is already in one of the tables.
  156          * The mech_entry could be in another class.
  157          */
  158         avl_index_t where = 0;
  159         kcf_mech_entry_t tmptab;
  160         strlcpy(tmptab.me_name, mechname, CRYPTO_MAX_MECH_NAME);
  161         if (avl_find(&kcf_mech_hash, &tmptab, &where) != NULL)
  162                 return (KCF_SUCCESS);
  163         /* Now take the next unused mech entry in the class's tab */
  164         kcf_mech_entry_t *me_tab = kcf_mech_tabs_tab[class].met_tab;
  165         int size = kcf_mech_tabs_tab[class].met_size;
  166 
  167         for (int i = 0; i < size; ++i)
  168                 if (me_tab[i].me_name[0] == 0) {
  169                         /* Found an empty spot */
  170                         strlcpy(me_tab[i].me_name, mechname,
  171                             CRYPTO_MAX_MECH_NAME);
  172                         me_tab[i].me_mechid = KCF_MECHID(class, i);
  173 
  174                         /* Add the new mechanism to the hash table */
  175                         avl_insert(&kcf_mech_hash, &me_tab[i], where);
  176                         return (KCF_SUCCESS);
  177                 }
  178 
  179         return (KCF_MECH_TAB_FULL);
  180 }
  181 
  182 /*
  183  * kcf_add_mech_provider()
  184  *
  185  * Arguments:
  186  *      . An index in to  the provider mechanism array
  187  *      . A pointer to the provider descriptor
  188  *      . A storage for the kcf_prov_mech_desc_t the entry was added at.
  189  *
  190  * Description:
  191  *      Adds  a new provider of a mechanism to the mechanism's mech_entry
  192  *      chain.
  193  *
  194  * Context:
  195  *      User context only.
  196  *
  197  * Returns
  198  *      KCF_SUCCESS on success
  199  *      KCF_MECH_TAB_FULL otherwise.
  200  */
  201 int
  202 kcf_add_mech_provider(short mech_indx,
  203     kcf_provider_desc_t *prov_desc, kcf_prov_mech_desc_t **pmdpp)
  204 {
  205         int error;
  206         kcf_mech_entry_t *mech_entry = NULL;
  207         const crypto_mech_info_t *mech_info;
  208         crypto_mech_type_t kcf_mech_type;
  209         kcf_prov_mech_desc_t *prov_mech;
  210 
  211         mech_info = &prov_desc->pd_mechanisms[mech_indx];
  212 
  213         /*
  214          * A mechanism belongs to exactly one mechanism table.
  215          * Find the class corresponding to the function group flag of
  216          * the mechanism.
  217          */
  218         kcf_mech_type = crypto_mech2id(mech_info->cm_mech_name);
  219         if (kcf_mech_type == CRYPTO_MECH_INVALID) {
  220                 crypto_func_group_t fg = mech_info->cm_func_group_mask;
  221                 kcf_ops_class_t class;
  222 
  223                 if (fg & CRYPTO_FG_DIGEST || fg & CRYPTO_FG_DIGEST_ATOMIC)
  224                         class = KCF_DIGEST_CLASS;
  225                 else if (fg & CRYPTO_FG_ENCRYPT || fg & CRYPTO_FG_DECRYPT ||
  226                     fg & CRYPTO_FG_ENCRYPT_ATOMIC ||
  227                     fg & CRYPTO_FG_DECRYPT_ATOMIC)
  228                         class = KCF_CIPHER_CLASS;
  229                 else if (fg & CRYPTO_FG_MAC || fg & CRYPTO_FG_MAC_ATOMIC)
  230                         class = KCF_MAC_CLASS;
  231                 else
  232                         __builtin_unreachable();
  233 
  234                 /*
  235                  * Attempt to create a new mech_entry for the specified
  236                  * mechanism. kcf_create_mech_entry() can handle the case
  237                  * where such an entry already exists.
  238                  */
  239                 if ((error = kcf_create_mech_entry(class,
  240                     mech_info->cm_mech_name)) != KCF_SUCCESS) {
  241                         return (error);
  242                 }
  243                 /* get the KCF mech type that was assigned to the mechanism */
  244                 kcf_mech_type = crypto_mech2id(mech_info->cm_mech_name);
  245                 ASSERT(kcf_mech_type != CRYPTO_MECH_INVALID);
  246         }
  247 
  248         error = kcf_get_mech_entry(kcf_mech_type, &mech_entry);
  249         ASSERT(error == KCF_SUCCESS);
  250 
  251         /* allocate and initialize new kcf_prov_mech_desc */
  252         prov_mech = kmem_zalloc(sizeof (kcf_prov_mech_desc_t), KM_SLEEP);
  253         memcpy(&prov_mech->pm_mech_info, mech_info,
  254             sizeof (crypto_mech_info_t));
  255         prov_mech->pm_prov_desc = prov_desc;
  256         prov_desc->pd_mech_indx[KCF_MECH2CLASS(kcf_mech_type)]
  257             [KCF_MECH2INDEX(kcf_mech_type)] = mech_indx;
  258 
  259         KCF_PROV_REFHOLD(prov_desc);
  260         KCF_PROV_IREFHOLD(prov_desc);
  261 
  262         /*
  263          * Add new kcf_prov_mech_desc at the front of HW providers
  264          * chain.
  265          */
  266         if (mech_entry->me_sw_prov != NULL) {
  267                 /*
  268                  * There is already a provider for this mechanism.
  269                  * Since we allow only one provider per mechanism,
  270                  * report this condition.
  271                  */
  272                 cmn_err(CE_WARN, "The cryptographic provider "
  273                     "\"%s\" will not be used for %s. The provider "
  274                     "\"%s\" will be used for this mechanism "
  275                     "instead.", prov_desc->pd_description,
  276                     mech_info->cm_mech_name,
  277                     mech_entry->me_sw_prov->pm_prov_desc->
  278                     pd_description);
  279                 KCF_PROV_REFRELE(prov_desc);
  280                 kmem_free(prov_mech, sizeof (kcf_prov_mech_desc_t));
  281                 prov_mech = NULL;
  282         } else {
  283                 /*
  284                  * Set the provider as the provider for
  285                  * this mechanism.
  286                  */
  287                 mech_entry->me_sw_prov = prov_mech;
  288         }
  289 
  290         *pmdpp = prov_mech;
  291 
  292         return (KCF_SUCCESS);
  293 }
  294 
  295 /*
  296  * kcf_remove_mech_provider()
  297  *
  298  * Arguments:
  299  *      . mech_name: the name of the mechanism.
  300  *      . prov_desc: The provider descriptor
  301  *
  302  * Description:
  303  *      Removes a provider from chain of provider descriptors.
  304  *      The provider is made unavailable to kernel consumers for the specified
  305  *      mechanism.
  306  *
  307  * Context:
  308  *      User context only.
  309  */
  310 void
  311 kcf_remove_mech_provider(const char *mech_name, kcf_provider_desc_t *prov_desc)
  312 {
  313         crypto_mech_type_t mech_type;
  314         kcf_prov_mech_desc_t *prov_mech = NULL;
  315         kcf_mech_entry_t *mech_entry;
  316 
  317         /* get the KCF mech type that was assigned to the mechanism */
  318         if ((mech_type = crypto_mech2id(mech_name)) ==
  319             CRYPTO_MECH_INVALID) {
  320                 /*
  321                  * Provider was not allowed for this mech due to policy or
  322                  * configuration.
  323                  */
  324                 return;
  325         }
  326 
  327         /* get a ptr to the mech_entry that was created */
  328         if (kcf_get_mech_entry(mech_type, &mech_entry) != KCF_SUCCESS) {
  329                 /*
  330                  * Provider was not allowed for this mech due to policy or
  331                  * configuration.
  332                  */
  333                 return;
  334         }
  335 
  336         if (mech_entry->me_sw_prov == NULL ||
  337             mech_entry->me_sw_prov->pm_prov_desc != prov_desc) {
  338                 /* not the provider for this mechanism */
  339                 return;
  340         }
  341         prov_mech = mech_entry->me_sw_prov;
  342         mech_entry->me_sw_prov = NULL;
  343 
  344         /* free entry  */
  345         KCF_PROV_IREFRELE(prov_mech->pm_prov_desc);
  346         KCF_PROV_REFRELE(prov_mech->pm_prov_desc);
  347         kmem_free(prov_mech, sizeof (kcf_prov_mech_desc_t));
  348 }
  349 
  350 /*
  351  * kcf_get_mech_entry()
  352  *
  353  * Arguments:
  354  *      . The framework mechanism type
  355  *      . Storage for the mechanism entry
  356  *
  357  * Description:
  358  *      Retrieves the mechanism entry for the mech.
  359  *
  360  * Context:
  361  *      User and interrupt contexts.
  362  *
  363  * Returns:
  364  *      KCF_MECHANISM_XXX appropriate error code.
  365  *      KCF_SUCCESS otherwise.
  366  */
  367 int
  368 kcf_get_mech_entry(crypto_mech_type_t mech_type, kcf_mech_entry_t **mep)
  369 {
  370         kcf_ops_class_t         class;
  371         int                     index;
  372         const kcf_mech_entry_tab_t      *me_tab;
  373 
  374         ASSERT(mep != NULL);
  375 
  376         class = KCF_MECH2CLASS(mech_type);
  377 
  378         if ((class < KCF_FIRST_OPSCLASS) || (class > KCF_LAST_OPSCLASS)) {
  379                 /* the caller won't need to know it's an invalid class */
  380                 return (KCF_INVALID_MECH_NUMBER);
  381         }
  382 
  383         me_tab = &kcf_mech_tabs_tab[class];
  384         index = KCF_MECH2INDEX(mech_type);
  385 
  386         if ((index < 0) || (index >= me_tab->met_size)) {
  387                 return (KCF_INVALID_MECH_NUMBER);
  388         }
  389 
  390         *mep = &((me_tab->met_tab)[index]);
  391 
  392         return (KCF_SUCCESS);
  393 }
  394 
  395 /*
  396  * crypto_mech2id()
  397  *
  398  * Arguments:
  399  *      . mechname: A null-terminated string identifying the mechanism name.
  400  *
  401  * Description:
  402  *      Walks the mechanisms tables, looking for an entry that matches the
  403  *      mechname. Once it find it, it builds the 64-bit mech_type and returns
  404  *      it.
  405  *
  406  * Context:
  407  *      Process and interruption.
  408  *
  409  * Returns:
  410  *      The unique mechanism identified by 'mechname', if found.
  411  *      CRYPTO_MECH_INVALID otherwise.
  412  */
  413 /*
  414  * Lookup the hash table for an entry that matches the mechname.
  415  * If there are no providers for the mechanism,
  416  * but there is an unloaded provider, this routine will attempt
  417  * to load it.
  418  */
  419 crypto_mech_type_t
  420 crypto_mech2id(const char *mechname)
  421 {
  422         kcf_mech_entry_t tmptab, *found;
  423         strlcpy(tmptab.me_name, mechname, CRYPTO_MAX_MECH_NAME);
  424 
  425         if ((found = avl_find(&kcf_mech_hash, &tmptab, NULL))) {
  426                 ASSERT(found->me_mechid != CRYPTO_MECH_INVALID);
  427                 return (found->me_mechid);
  428         }
  429 
  430         return (CRYPTO_MECH_INVALID);
  431 }
  432 
  433 #if defined(_KERNEL)
  434 EXPORT_SYMBOL(crypto_mech2id);
  435 #endif

Cache object: 990fc8a97e1a99b4e48999e45e119224


[ 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.