XXXX introduce drv_sectohz

   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 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Core KCF (Kernel Cryptographic Framework). This file implements
  28  * the cryptoadm entry points.
  29  */
  30 
  31 #include <sys/systm.h>
  32 #include <sys/errno.h>
  33 #include <sys/cmn_err.h>
  34 #include <sys/rwlock.h>
  35 #include <sys/kmem.h>
  36 #include <sys/modctl.h>
  37 #include <sys/sunddi.h>
  38 #include <sys/door.h>
  39 #include <sys/crypto/common.h>
  40 #include <sys/crypto/api.h>
  41 #include <sys/crypto/spi.h>
  42 #include <sys/crypto/impl.h>
  43 #include <sys/crypto/sched_impl.h>
  44 
  45 /* protects the the soft_config_list. */
  46 kmutex_t soft_config_mutex;
  47 
  48 /*
  49  * This linked list contains software configuration entries.
  50  * The initial list is just software providers loaded by kcf_soft_config_init().
  51  * Additional entries may appear for both hardware and software providers
  52  * from kcf.conf.  These come from "cryptoadm start", which reads file kcf.conf
  53  * and updates this table using the CRYPTO_LOAD_SOFT_CONFIG ioctl.
  54  * Further cryptoadm commands modify this file and update this table with ioctl.
  55  * This list is protected by the soft_config_mutex.
  56  */
  57 kcf_soft_conf_entry_t *soft_config_list;
  58 
  59 static int add_soft_config(char *, uint_t, crypto_mech_name_t *);
  60 static int dup_mech_names(kcf_provider_desc_t *, crypto_mech_name_t **,
  61     uint_t *, int);
  62 static void free_soft_config_entry(kcf_soft_conf_entry_t *);
  63 
  64 #define KCF_MAX_CONFIG_ENTRIES 512 /* maximum entries in soft_config_list */
  65 
  66 #if DEBUG
  67 extern int kcf_frmwrk_debug;
  68 static void kcf_soft_config_dump(char *message);
  69 #endif /* DEBUG */
  70 
  71 /*
  72  * Count and return the number of mechanisms in an array of crypto_mech_name_t
  73  * (excluding final NUL-character string element).
  74  */
  75 static int
  76 count_mechanisms(crypto_mech_name_t mechs[]) {
  77         int     count;
  78         for (count = 0; mechs[count][0] != '\0'; ++count);
  79         return (count);
  80 }
  81 
  82 /*
  83  * Initialize a mutex and populate soft_config_list with default entries
  84  * of kernel software providers.
  85  * Called from kcf module _init().
  86  */
  87 void
  88 kcf_soft_config_init(void)
  89 {
  90         typedef struct {
  91                 char                    *name;
  92                 crypto_mech_name_t      *mechs;
  93         } initial_soft_config_entry_t;
  94 
  95         /*
  96          * This provides initial default values to soft_config_list.
  97          * It is equivalent to these lines in /etc/crypto/kcf.conf
  98          * (without line breaks and indenting):
  99          *
 100          * # /etc/crypto/kcf.conf
 101          * des:supportedlist=CKM_DES_CBC,CKM_DES_ECB,CKM_DES3_CBC,CKM_DES3_ECB
 102          * aes:supportedlist=CKM_AES_ECB,CKM_AES_CBC,CKM_AES_CTR,CKM_AES_CCM,\
 103          * CKM_AES_GCM,CKM_AES_GMAC
 104          * arcfour:supportedlist=CKM_RC4
 105          * blowfish:supportedlist=CKM_BLOWFISH_ECB,CKM_BLOWFISH_CBC
 106          * ecc:supportedlist=CKM_EC_KEY_PAIR_GEN,CKM_ECDH1_DERIVE,CKM_ECDSA,\
 107          * CKM_ECDSA_SHA1
 108          * sha1:supportedlist=CKM_SHA_1,CKM_SHA_1_HMAC_GENERAL,CKM_SHA_1_HMAC
 109          * sha2:supportedlist=CKM_SHA256,CKM_SHA256_HMAC,\
 110          * CKM_SHA256_HMAC_GENERAL,CKM_SHA384,CKM_SHA384_HMAC,\
 111          * CKM_SHA384_HMAC_GENERAL,CKM_SHA512,CKM_SHA512_HMAC,\
 112          * CKM_SHA512_HMAC_GENERAL
 113          * md4:supportedlist=CKM_MD4
 114          * md5:supportedlist=CKM_MD5,CKM_MD5_HMAC_GENERAL,CKM_MD5_HMAC
 115          * rsa:supportedlist=CKM_RSA_PKCS,CKM_RSA_X_509,CKM_MD5_RSA_PKCS,\
 116          * CKM_SHA1_RSA_PKCS,CKM_SHA256_RSA_PKCS,CKM_SHA384_RSA_PKCS,\
 117          * CKM_SHA512_RSA_PKCS
 118          * swrand:supportedlist=random
 119          *
 120          * WARNING: If you add a new kernel crypto provider or mechanism,
 121          * you must update these structures.
 122          *
 123          * 1. To add a new mechanism to a provider add the string to the
 124          * appropriate array below and comment above.
 125          *
 126          * 2. To add a new provider, create a new *_mechs array listing the
 127          * provider's mechanism(s) and a new comment line above.
 128          * Add the new *_mechs array to initial_soft_config_entry[].
 129          *
 130          * 3. If appropriate (that is the new mechanism is needed before
 131          * cryptosvc runs), add to kcf_init_mech_tabs() in kcf_mech_tabs.c.
 132          */
 133         static crypto_mech_name_t       des_mechs[] = {
 134             "CKM_DES_CBC", "CKM_DES_ECB", "CKM_DES3_CBC", "CKM_DES3_ECB", ""};
 135         static crypto_mech_name_t       aes_mechs[] = {
 136             "CKM_AES_ECB", "CKM_AES_CBC", "CKM_AES_CTR", "CKM_AES_CCM",
 137             "CKM_AES_GCM", "CKM_AES_GMAC", ""};
 138         static crypto_mech_name_t       arcfour_mechs[] = {
 139             "CKM_RC4", ""};
 140         static crypto_mech_name_t       blowfish_mechs[] = {
 141             "CKM_BLOWFISH_ECB", "CKM_BLOWFISH_CBC", ""};
 142         static crypto_mech_name_t       ecc_mechs[] = {
 143             "CKM_EC_KEY_PAIR_GEN", "CKM_ECDH1_DERIVE", "CKM_ECDSA",
 144             "CKM_ECDSA_SHA1", ""};
 145         static crypto_mech_name_t       sha1_mechs[] = {
 146             "CKM_SHA_1", "CKM_SHA_1_HMAC_GENERAL", "CKM_SHA_1_HMAC", ""};
 147         static crypto_mech_name_t       sha2_mechs[] = {
 148             "CKM_SHA256", "CKM_SHA256_HMAC", "CKM_SHA256_HMAC_GENERAL",
 149             "CKM_SHA384", "CKM_SHA384_HMAC", "CKM_SHA384_HMAC_GENERAL",
 150             "CKM_SHA512", "CKM_SHA512_HMAC", "CKM_SHA512_HMAC_GENERAL", ""};
 151         static crypto_mech_name_t       md4_mechs[] = {
 152             "CKM_MD4", ""};
 153         static crypto_mech_name_t       md5_mechs[] = {
 154             "CKM_MD5", "CKM_MD5_HMAC_GENERAL", "CKM_MD5_HMAC", ""};
 155         static crypto_mech_name_t       rsa_mechs[] = {
 156             "CKM_RSA_PKCS", "CKM_RSA_X_509", "CKM_MD5_RSA_PKCS",
 157             "CKM_SHA1_RSA_PKCS", "CKM_SHA256_RSA_PKCS", "CKM_SHA384_RSA_PKCS",
 158             "CKM_SHA512_RSA_PKCS", ""};
 159         static crypto_mech_name_t       swrand_mechs[] = {
 160             "random", NULL};
 161         static initial_soft_config_entry_t
 162             initial_soft_config_entry[] = {
 163                 "des", des_mechs,
 164                 "aes", aes_mechs,
 165                 "arcfour", arcfour_mechs,
 166                 "blowfish", blowfish_mechs,
 167                 "ecc", ecc_mechs,
 168                 "sha1", sha1_mechs,
 169                 "sha2", sha2_mechs,
 170                 "md4", md4_mechs,
 171                 "md5", md5_mechs,
 172                 "rsa", rsa_mechs,
 173                 "swrand", swrand_mechs
 174         };
 175         const int       initial_soft_config_entries =
 176             sizeof (initial_soft_config_entry)
 177             / sizeof (initial_soft_config_entry_t);
 178         int             i;
 179 
 180         mutex_init(&soft_config_mutex, NULL, MUTEX_DRIVER, NULL);
 181 
 182         /*
 183          * Initialize soft_config_list with default providers.
 184          * Populate the linked list backwards so the first entry appears first.
 185          */
 186         for (i = initial_soft_config_entries - 1; i >= 0; --i) {
 187                 initial_soft_config_entry_t *p = &initial_soft_config_entry[i];
 188                 crypto_mech_name_t      *mechsp;
 189                 uint_t                  alloc_size;
 190                 int                     mech_count, r;
 191 
 192                 /* allocate/initialize memory for mechanism list */
 193                 mech_count = count_mechanisms(p->mechs);
 194                 alloc_size = mech_count * CRYPTO_MAX_MECH_NAME;
 195                 mechsp = kmem_alloc(alloc_size, KM_SLEEP);
 196                 bcopy(p->mechs, mechsp, alloc_size);
 197 
 198                 r = add_soft_config(p->name, mech_count, mechsp);
 199                 if (r != 0)
 200                         cmn_err(CE_WARN,
 201                             "add_soft_config(%s) failed; returned %d\n",
 202                             p->name, r);
 203         }
 204 #if DEBUG
 205         if (kcf_frmwrk_debug >= 1)
 206                 kcf_soft_config_dump("kcf_soft_config_init");
 207 #endif /* DEBUG */
 208 }
 209 
 210 
 211 #if DEBUG
 212 /*
 213  * Dump soft_config_list, containing a list of kernel software providers
 214  * and (optionally) hardware providers, with updates from kcf.conf.
 215  * Dump mechanism lists too if kcf_frmwrk_debug is >= 2.
 216  */
 217 static void
 218 kcf_soft_config_dump(char *message)
 219 {
 220         kcf_soft_conf_entry_t   *p;
 221         uint_t                  i;
 222 
 223         mutex_enter(&soft_config_mutex);
 224         printf("Soft provider config list soft_config_list: %s\n",
 225             message != NULL ? message : "");
 226 
 227         for (p = soft_config_list; p != NULL; p = p->ce_next) {
 228                 printf("ce_name: %s, %d ce_mechs\n", p->ce_name, p->ce_count);
 229                 if (kcf_frmwrk_debug >= 2) {
 230                         printf("\tce_mechs: ");
 231                         for (i = 0; i < p->ce_count; i++) {
 232                                 printf("%s ", p->ce_mechs[i]);
 233                         }
 234                         printf("\n");
 235                 }
 236         }
 237         printf("(end of soft_config_list)\n");
 238 
 239         mutex_exit(&soft_config_mutex);
 240 }
 241 #endif /* DEBUG */
 242 
 243 
 244 /*
 245  * Utility routine to identify the providers to filter out and
 246  * present only one provider. This happens when a hardware provider
 247  * registers multiple units of the same device instance.
 248  *
 249  * Called from crypto_get_dev_list().
 250  */
 251 static void
 252 filter_providers(uint_t count, kcf_provider_desc_t **provider_array,
 253         char *skip_providers, int *mech_counts, int *new_count)
 254 {
 255         int i, j;
 256         kcf_provider_desc_t *prov1, *prov2;
 257         int n = 0;
 258 
 259         for (i = 0; i < count; i++) {
 260                 if (skip_providers[i] == 1)
 261                         continue;
 262 
 263                 prov1 = provider_array[i];
 264                 mech_counts[i] = prov1->pd_mech_list_count;
 265                 for (j = i + 1; j < count; j++) {
 266                         prov2 = provider_array[j];
 267                         if (strncmp(prov1->pd_name, prov2->pd_name,
 268                             MAXNAMELEN) == 0 &&
 269                             prov1->pd_instance == prov2->pd_instance) {
 270                                 skip_providers[j] = 1;
 271                                 mech_counts[i] += prov2->pd_mech_list_count;
 272                         }
 273                 }
 274                 n++;
 275         }
 276 
 277         *new_count = n;
 278 }
 279 
 280 
 281 /*
 282  * Return a list of kernel hardware providers and a count of each
 283  * provider's supported mechanisms.
 284  * Called from the CRYPTO_GET_DEV_LIST ioctl.
 285  */
 286 int
 287 crypto_get_dev_list(uint_t *count, crypto_dev_list_entry_t **array)
 288 {
 289         kcf_provider_desc_t **provider_array;
 290         kcf_provider_desc_t *pd;
 291         crypto_dev_list_entry_t *p;
 292         size_t skip_providers_size, mech_counts_size;
 293         char *skip_providers;
 294         uint_t provider_count;
 295         int rval, i, j, new_count, *mech_counts;
 296 
 297         /*
 298          * Take snapshot of provider table returning only hardware providers
 299          * that are in a usable state. Logical providers not included.
 300          */
 301         rval = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
 302             NULL, 0, B_FALSE);
 303         if (rval != CRYPTO_SUCCESS)
 304                 return (rval);
 305 
 306         if (provider_count == 0) {
 307                 *array = NULL;
 308                 *count = 0;
 309                 return (CRYPTO_SUCCESS);
 310         }
 311 
 312         skip_providers_size = provider_count * sizeof (char);
 313         mech_counts_size = provider_count * sizeof (int);
 314 
 315         skip_providers = kmem_zalloc(skip_providers_size, KM_SLEEP);
 316         mech_counts = kmem_zalloc(mech_counts_size, KM_SLEEP);
 317         filter_providers(provider_count, provider_array, skip_providers,
 318             mech_counts, &new_count);
 319 
 320         p = kmem_alloc(new_count * sizeof (crypto_dev_list_entry_t), KM_SLEEP);
 321         for (i = 0, j = 0; i < provider_count; i++) {
 322                 if (skip_providers[i] == 1) {
 323                         ASSERT(mech_counts[i] == 0);
 324                         continue;
 325                 }
 326                 pd = provider_array[i];
 327                 p[j].le_mechanism_count = mech_counts[i];
 328                 p[j].le_dev_instance = pd->pd_instance;
 329                 (void) strncpy(p[j].le_dev_name, pd->pd_name, MAXNAMELEN);
 330                 j++;
 331         }
 332 
 333         kcf_free_provider_tab(provider_count, provider_array);
 334         kmem_free(skip_providers, skip_providers_size);
 335         kmem_free(mech_counts, mech_counts_size);
 336 
 337         *array = p;
 338         *count = new_count;
 339         return (CRYPTO_SUCCESS);
 340 }
 341 
 342 /*
 343  * Return a buffer containing the null terminated names of software providers
 344  * loaded by CRYPTO_LOAD_SOFT_CONFIG.
 345  * Called from the CRYPTO_GET_SOFT_LIST ioctl.
 346  */
 347 int
 348 crypto_get_soft_list(uint_t *count, char **array, size_t *len)
 349 {
 350         char *names = NULL, *namep, *end;
 351         kcf_soft_conf_entry_t *p;
 352         uint_t n = 0, cnt = 0, final_count = 0;
 353         size_t name_len, final_size = 0;
 354 
 355         /* first estimate */
 356         mutex_enter(&soft_config_mutex);
 357         for (p = soft_config_list; p != NULL; p = p->ce_next) {
 358                 n += strlen(p->ce_name) + 1;
 359                 cnt++;
 360         }
 361         mutex_exit(&soft_config_mutex);
 362 
 363         if (cnt == 0)
 364                 goto out;
 365 
 366 again:
 367         namep = names = kmem_alloc(n, KM_SLEEP);
 368         end = names + n;
 369         final_size = 0;
 370         final_count = 0;
 371 
 372         mutex_enter(&soft_config_mutex);
 373         for (p = soft_config_list; p != NULL; p = p->ce_next) {
 374                 name_len = strlen(p->ce_name) + 1;
 375                 /* check for enough space */
 376                 if ((namep + name_len) > end) {
 377                         mutex_exit(&soft_config_mutex);
 378                         kmem_free(names, n);
 379                         n = n << 1;
 380                         goto again;
 381                 }
 382                 (void) strcpy(namep, p->ce_name);
 383                 namep += name_len;
 384                 final_size += name_len;
 385                 final_count++;
 386         }
 387         mutex_exit(&soft_config_mutex);
 388 
 389         ASSERT(final_size <= n);
 390 
 391         /* check if buffer we allocated is too large */
 392         if (final_size < n) {
 393                 char *final_buffer;
 394 
 395                 final_buffer = kmem_alloc(final_size, KM_SLEEP);
 396                 bcopy(names, final_buffer, final_size);
 397                 kmem_free(names, n);
 398                 names = final_buffer;
 399         }
 400 out:
 401         *array = names;
 402         *count = final_count;
 403         *len = final_size;
 404         return (CRYPTO_SUCCESS);
 405 }
 406 
 407 /*
 408  * Check if a mechanism name is already in a mechanism name array
 409  * Called by crypto_get_dev_info().
 410  */
 411 static boolean_t
 412 duplicate(char *name, crypto_mech_name_t *array, int count)
 413 {
 414         int i;
 415 
 416         for (i = 0; i < count; i++) {
 417                 if (strncmp(name, &array[i][0],
 418                     sizeof (crypto_mech_name_t)) == 0)
 419                         return (B_TRUE);
 420         }
 421         return (B_FALSE);
 422 }
 423 
 424 /*
 425  * Return a list of kernel hardware providers for a given name and instance.
 426  * For each entry, also return a list of their supported mechanisms.
 427  * Called from the CRYPTO_GET_DEV_INFO ioctl.
 428  */
 429 int
 430 crypto_get_dev_info(char *name, uint_t instance, uint_t *count,
 431     crypto_mech_name_t **array)
 432 {
 433         int rv;
 434         crypto_mech_name_t *mech_names, *resized_array;
 435         int i, j, k = 0, max_count;
 436         uint_t provider_count;
 437         kcf_provider_desc_t **provider_array;
 438         kcf_provider_desc_t *pd;
 439 
 440         /*
 441          * Get provider table entries matching name and instance
 442          * for hardware providers that are in a usable state.
 443          * Logical providers not included. NULL name matches
 444          * all hardware providers.
 445          */
 446         rv = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
 447             name, instance, B_FALSE);
 448         if (rv != CRYPTO_SUCCESS)
 449                 return (rv);
 450 
 451         if (provider_count == 0)
 452                 return (CRYPTO_ARGUMENTS_BAD);
 453 
 454         /* Count all mechanisms supported by all providers */
 455         max_count = 0;
 456         for (i = 0; i < provider_count; i++)
 457                 max_count += provider_array[i]->pd_mech_list_count;
 458 
 459         if (max_count == 0) {
 460                 mech_names = NULL;
 461                 goto out;
 462         }
 463 
 464         /* Allocate space and copy mech names */
 465         mech_names = kmem_alloc(max_count * sizeof (crypto_mech_name_t),
 466             KM_SLEEP);
 467 
 468         k = 0;
 469         for (i = 0; i < provider_count; i++) {
 470                 pd = provider_array[i];
 471                 for (j = 0; j < pd->pd_mech_list_count; j++) {
 472                         /* check for duplicate */
 473                         if (duplicate(&pd->pd_mechanisms[j].cm_mech_name[0],
 474                             mech_names, k))
 475                                 continue;
 476                         bcopy(&pd->pd_mechanisms[j].cm_mech_name[0],
 477                             &mech_names[k][0], sizeof (crypto_mech_name_t));
 478                         k++;
 479                 }
 480         }
 481 
 482         /* resize */
 483         if (k != max_count) {
 484                 resized_array =
 485                     kmem_alloc(k * sizeof (crypto_mech_name_t), KM_SLEEP);
 486                 bcopy(mech_names, resized_array,
 487                     k * sizeof (crypto_mech_name_t));
 488                 kmem_free(mech_names,
 489                     max_count * sizeof (crypto_mech_name_t));
 490                 mech_names = resized_array;
 491         }
 492 
 493 out:
 494         kcf_free_provider_tab(provider_count, provider_array);
 495         *count = k;
 496         *array = mech_names;
 497 
 498         return (CRYPTO_SUCCESS);
 499 }
 500 
 501 /*
 502  * Given a kernel software provider name, return a list of mechanisms
 503  * it supports.
 504  * Called from the CRYPTO_GET_SOFT_INFO ioctl.
 505  */
 506 int
 507 crypto_get_soft_info(caddr_t name, uint_t *count, crypto_mech_name_t **array)
 508 {
 509         ddi_modhandle_t modh = NULL;
 510         kcf_provider_desc_t *provider;
 511         int rv;
 512 
 513         provider = kcf_prov_tab_lookup_by_name(name);
 514         if (provider == NULL) {
 515                 char *tmp;
 516                 int name_len;
 517 
 518                 /* strlen("crypto/") + NULL terminator == 8 */
 519                 name_len = strlen(name);
 520                 tmp = kmem_alloc(name_len + 8, KM_SLEEP);
 521                 bcopy("crypto/", tmp, 7);
 522                 bcopy(name, &tmp[7], name_len);
 523                 tmp[name_len + 7] = '\0';
 524 
 525                 modh = ddi_modopen(tmp, KRTLD_MODE_FIRST, NULL);
 526                 kmem_free(tmp, name_len + 8);
 527 
 528                 if (modh == NULL) {
 529                         return (CRYPTO_ARGUMENTS_BAD);
 530                 }
 531 
 532                 provider = kcf_prov_tab_lookup_by_name(name);
 533                 if (provider == NULL) {
 534                         return (CRYPTO_ARGUMENTS_BAD);
 535                 }
 536         }
 537 
 538         rv = dup_mech_names(provider, array, count, KM_SLEEP);
 539         KCF_PROV_REFRELE(provider);
 540         if (modh != NULL)
 541                 (void) ddi_modclose(modh);
 542         return (rv);
 543 }
 544 
 545 
 546 /*
 547  * Change the mechanism list for a provider.
 548  * If "direction" is CRYPTO_MECH_ADDED, add new mechanisms.
 549  * If "direction" is CRYPTO_MECH_REMOVED, remove the mechanism list.
 550  * Called from crypto_load_dev_disabled().
 551  */
 552 static void
 553 kcf_change_mechs(kcf_provider_desc_t *provider, uint_t count,
 554     crypto_mech_name_t *array, crypto_event_change_t direction)
 555 {
 556         crypto_notify_event_change_t ec;
 557         crypto_mech_info_t *mi;
 558         kcf_prov_mech_desc_t *pmd;
 559         char *mech;
 560         int i, j, n;
 561 
 562         ASSERT(direction == CRYPTO_MECH_ADDED ||
 563             direction == CRYPTO_MECH_REMOVED);
 564 
 565         if (provider == NULL) {
 566                 /*
 567                  * Nothing to add or remove from the tables since
 568                  * the provider isn't registered.
 569                  */
 570                 return;
 571         }
 572 
 573         for (i = 0; i < count; i++) {
 574                 if (array[i][0] == '\0')
 575                         continue;
 576 
 577                 mech = &array[i][0];
 578 
 579                 n = provider->pd_mech_list_count;
 580                 for (j = 0; j < n; j++) {
 581                         mi = &provider->pd_mechanisms[j];
 582                         if (strncmp(mi->cm_mech_name, mech,
 583                             CRYPTO_MAX_MECH_NAME) == 0)
 584                                 break;
 585                 }
 586                 if (j == n)
 587                         continue;
 588 
 589                 switch (direction) {
 590                 case CRYPTO_MECH_ADDED:
 591                         (void) kcf_add_mech_provider(j, provider, &pmd);
 592                         break;
 593 
 594                 case CRYPTO_MECH_REMOVED:
 595                         kcf_remove_mech_provider(mech, provider);
 596                         break;
 597                 }
 598 
 599                 /* Inform interested clients of the event */
 600                 ec.ec_provider_type = provider->pd_prov_type;
 601                 ec.ec_change = direction;
 602 
 603                 (void) strncpy(ec.ec_mech_name, mech, CRYPTO_MAX_MECH_NAME);
 604                 kcf_walk_ntfylist(CRYPTO_EVENT_MECHS_CHANGED, &ec);
 605         }
 606 }
 607 
 608 /*
 609  * If a mech name in the second array (prev_array) is also in the
 610  * first array, then a NULL character is written into the first byte
 611  * of the mech name in the second array.  This effectively removes
 612  * the mech name from the second array.
 613  */
 614 static void
 615 kcf_compare_mechs(uint_t count, crypto_mech_name_t *array, uint_t prev_count,
 616     crypto_mech_name_t *prev_array)
 617 {
 618         int i, j;
 619 
 620         for (i = 0; i < prev_count; i++) {
 621                 for (j = 0; j < count; j++) {
 622                         if (strncmp(&prev_array[i][0], &array[j][0],
 623                             CRYPTO_MAX_MECH_NAME) == 0) {
 624                                 prev_array[i][0] = '\0';
 625                         }
 626                 }
 627         }
 628 }
 629 
 630 /*
 631  * Called from CRYPTO_LOAD_DEV_DISABLED ioctl.
 632  * If new_count is 0, then completely remove the entry.
 633  */
 634 int
 635 crypto_load_dev_disabled(char *name, uint_t instance, uint_t new_count,
 636     crypto_mech_name_t *new_array)
 637 {
 638         kcf_provider_desc_t *provider = NULL;
 639         kcf_provider_desc_t **provider_array;
 640         crypto_mech_name_t *prev_array;
 641         uint_t provider_count, prev_count;
 642         int i, rv = CRYPTO_SUCCESS;
 643 
 644         /*
 645          * Remove the policy entry if new_count is 0, otherwise put disabled
 646          * mechanisms into policy table.
 647          */
 648         if (new_count == 0) {
 649                 kcf_policy_remove_by_dev(name, instance, &prev_count,
 650                     &prev_array);
 651         } else if ((rv = kcf_policy_load_dev_disabled(name, instance, new_count,
 652             new_array, &prev_count, &prev_array)) != CRYPTO_SUCCESS) {
 653                 return (rv);
 654         }
 655 
 656         /*
 657          * Get provider table entries matching name and instance
 658          * for providers that are are in a usable or unverified state.
 659          */
 660         rv = kcf_get_hw_prov_tab(&provider_count, &provider_array, KM_SLEEP,
 661             name, instance, B_TRUE);
 662         if (rv != CRYPTO_SUCCESS)
 663                 return (rv);
 664 
 665         for (i = 0; i < provider_count; i++) {
 666                 provider = provider_array[i];
 667 
 668                 /* previously disabled mechanisms may become enabled */
 669                 if (prev_array != NULL) {
 670                         kcf_compare_mechs(new_count, new_array,
 671                             prev_count, prev_array);
 672                         kcf_change_mechs(provider, prev_count, prev_array,
 673                             CRYPTO_MECH_ADDED);
 674                 }
 675 
 676                 kcf_change_mechs(provider, new_count, new_array,
 677                     CRYPTO_MECH_REMOVED);
 678         }
 679 
 680         kcf_free_provider_tab(provider_count, provider_array);
 681         crypto_free_mech_list(prev_array, prev_count);
 682         return (rv);
 683 }
 684 
 685 /*
 686  * Called from CRYPTO_LOAD_SOFT_DISABLED ioctl.
 687  * If new_count is 0, then completely remove the entry.
 688  */
 689 int
 690 crypto_load_soft_disabled(char *name, uint_t new_count,
 691     crypto_mech_name_t *new_array)
 692 {
 693         kcf_provider_desc_t *provider = NULL;
 694         crypto_mech_name_t *prev_array;
 695         uint_t prev_count = 0;
 696         int rv;
 697 
 698         provider = kcf_prov_tab_lookup_by_name(name);
 699         if (provider != NULL) {
 700                 mutex_enter(&provider->pd_lock);
 701                 /*
 702                  * Check if any other thread is disabling or removing
 703                  * this provider. We return if this is the case.
 704                  */
 705                 if (provider->pd_state >= KCF_PROV_DISABLED) {
 706                         mutex_exit(&provider->pd_lock);
 707                         KCF_PROV_REFRELE(provider);
 708                         return (CRYPTO_BUSY);
 709                 }
 710                 provider->pd_state = KCF_PROV_DISABLED;
 711                 mutex_exit(&provider->pd_lock);
 712 
 713                 undo_register_provider(provider, B_TRUE);
 714                 KCF_PROV_REFRELE(provider);
 715                 if (provider->pd_kstat != NULL)
 716                         KCF_PROV_REFRELE(provider);
 717 
 718                 /* Wait till the existing requests complete. */
 719                 while (kcf_get_refcnt(provider, B_TRUE) > 0) {
 720                         /* wait 1 second and try again. */
 721                         delay(1 * drv_usectohz(1000000));
 722                 }
 723         }
 724 
 725         if (new_count == 0) {
 726                 kcf_policy_remove_by_name(name, &prev_count, &prev_array);
 727                 crypto_free_mech_list(prev_array, prev_count);
 728                 rv = CRYPTO_SUCCESS;
 729                 goto out;
 730         }
 731 
 732         /* put disabled mechanisms into policy table */
 733         if ((rv = kcf_policy_load_soft_disabled(name, new_count, new_array,
 734             &prev_count, &prev_array)) == CRYPTO_SUCCESS) {
 735                 crypto_free_mech_list(prev_array, prev_count);
 736         }
 737 
 738 out:
 739         if (provider != NULL) {
 740                 redo_register_provider(provider);
 741                 if (provider->pd_kstat != NULL)
 742                         KCF_PROV_REFHOLD(provider);
 743                 mutex_enter(&provider->pd_lock);
 744                 provider->pd_state = KCF_PROV_READY;
 745                 mutex_exit(&provider->pd_lock);
 746         } else if (rv == CRYPTO_SUCCESS) {
 747                 /*
 748                  * There are some cases where it is useful to kCF clients
 749                  * to have a provider whose mechanism is enabled now to be
 750                  * available. So, we attempt to load it here.
 751                  *
 752                  * The check, new_count < prev_count, ensures that we do this
 753                  * only in the case where a mechanism(s) is now enabled.
 754                  * This check assumes that enable and disable are separate
 755                  * administrative actions and are not done in a single action.
 756                  */
 757                 if ((new_count < prev_count) &&
 758                     (modload("crypto", name) != -1)) {
 759                         struct modctl *mcp;
 760                         boolean_t load_again = B_FALSE;
 761 
 762                         if ((mcp = mod_hold_by_name(name)) != NULL) {
 763                                 mcp->mod_loadflags |= MOD_NOAUTOUNLOAD;
 764 
 765                                 /* memory pressure may have unloaded module */
 766                                 if (!mcp->mod_installed)
 767                                         load_again = B_TRUE;
 768                                 mod_release_mod(mcp);
 769 
 770                                 if (load_again)
 771                                         (void) modload("crypto", name);
 772                         }
 773                 }
 774         }
 775 
 776         return (rv);
 777 }
 778 
 779 /* called from the CRYPTO_LOAD_SOFT_CONFIG ioctl */
 780 int
 781 crypto_load_soft_config(caddr_t name, uint_t count, crypto_mech_name_t *array)
 782 {
 783         return (add_soft_config(name, count, array));
 784 }
 785 
 786 /*
 787  * Unload a kernel software crypto module.
 788  * Called from the CRYPTO_UNLOAD_SOFT_MODULE ioctl.
 789  */
 790 int
 791 crypto_unload_soft_module(caddr_t name)
 792 {
 793         int error;
 794         modid_t id;
 795         kcf_provider_desc_t *provider;
 796         struct modctl *mcp;
 797 
 798         /* verify that 'name' refers to a registered crypto provider */
 799         if ((provider = kcf_prov_tab_lookup_by_name(name)) == NULL)
 800                 return (CRYPTO_UNKNOWN_PROVIDER);
 801 
 802         /*
 803          * We save the module id and release the reference. We need to
 804          * do this as modunload() calls unregister which waits for the
 805          * refcnt to drop to zero.
 806          */
 807         id = provider->pd_module_id;
 808         KCF_PROV_REFRELE(provider);
 809 
 810         if ((mcp = mod_hold_by_name(name)) != NULL) {
 811                 mcp->mod_loadflags &= ~(MOD_NOAUTOUNLOAD);
 812                 mod_release_mod(mcp);
 813         }
 814 
 815         if ((error = modunload(id)) != 0) {
 816                 return (error == EBUSY ? CRYPTO_BUSY : CRYPTO_FAILED);
 817         }
 818 
 819         return (CRYPTO_SUCCESS);
 820 }
 821 
 822 /*
 823  * Free the list of kernel hardware crypto providers.
 824  * Called by get_dev_list() for the CRYPTO_GET_DEV_LIST ioctl.
 825  */
 826 void
 827 crypto_free_dev_list(crypto_dev_list_entry_t *array, uint_t count)
 828 {
 829         if (count == 0 || array == NULL)
 830                 return;
 831 
 832         kmem_free(array, count * sizeof (crypto_dev_list_entry_t));
 833 }
 834 
 835 /*
 836  * Returns duplicate array of mechanisms.  The array is allocated and
 837  * must be freed by the caller.
 838  */
 839 static int
 840 dup_mech_names(kcf_provider_desc_t *provider, crypto_mech_name_t **array,
 841     uint_t *count, int kmflag)
 842 {
 843         crypto_mech_name_t *mech_names;
 844         uint_t n;
 845         uint_t i;
 846 
 847         if ((n = provider->pd_mech_list_count) == 0) {
 848                 *count = 0;
 849                 *array = NULL;
 850                 return (CRYPTO_SUCCESS);
 851         }
 852 
 853         mech_names = kmem_alloc(n * sizeof (crypto_mech_name_t), kmflag);
 854         if (mech_names == NULL)
 855                 return (CRYPTO_HOST_MEMORY);
 856 
 857         for (i = 0; i < n; i++) {
 858                 bcopy(&provider->pd_mechanisms[i].cm_mech_name[0],
 859                     &mech_names[i][0], sizeof (crypto_mech_name_t));
 860         }
 861 
 862         *count = n;
 863         *array = mech_names;
 864         return (CRYPTO_SUCCESS);
 865 }
 866 
 867 /*
 868  * Returns B_TRUE if the specified mechanism is disabled, B_FALSE otherwise.
 869  */
 870 boolean_t
 871 is_mech_disabled_byname(crypto_provider_type_t prov_type, char *pd_name,
 872     uint_t pd_instance, crypto_mech_name_t mech_name)
 873 {
 874         kcf_policy_desc_t *policy;
 875         uint_t i;
 876 
 877         ASSERT(prov_type == CRYPTO_SW_PROVIDER ||
 878             prov_type == CRYPTO_HW_PROVIDER);
 879 
 880         switch (prov_type) {
 881         case CRYPTO_SW_PROVIDER:
 882                 policy = kcf_policy_lookup_by_name(pd_name);
 883                 /* no policy for provider - so mechanism can't be disabled */
 884                 if (policy == NULL)
 885                         return (B_FALSE);
 886                 break;
 887 
 888         case CRYPTO_HW_PROVIDER:
 889                 policy = kcf_policy_lookup_by_dev(pd_name, pd_instance);
 890                 /* no policy for provider - so mechanism can't be disabled */
 891                 if (policy == NULL)
 892                         return (B_FALSE);
 893                 break;
 894         }
 895 
 896         mutex_enter(&policy->pd_mutex);
 897         for (i = 0; i < policy->pd_disabled_count; i ++) {
 898                 if (strncmp(mech_name, &policy->pd_disabled_mechs[i][0],
 899                     CRYPTO_MAX_MECH_NAME) == 0) {
 900                         mutex_exit(&policy->pd_mutex);
 901                         KCF_POLICY_REFRELE(policy);
 902                         return (B_TRUE);
 903                 }
 904         }
 905         mutex_exit(&policy->pd_mutex);
 906         KCF_POLICY_REFRELE(policy);
 907         return (B_FALSE);
 908 }
 909 
 910 /*
 911  * Returns B_TRUE if the specified mechanism is disabled, B_FALSE otherwise.
 912  *
 913  * This is a wrapper routine around is_mech_disabled_byname() above and
 914  * takes a pointer kcf_provider_desc structure as argument.
 915  */
 916 boolean_t
 917 is_mech_disabled(kcf_provider_desc_t *provider, crypto_mech_name_t name)
 918 {
 919         kcf_provider_list_t *e;
 920         kcf_provider_desc_t *pd;
 921         boolean_t found = B_FALSE;
 922         uint_t count, i;
 923 
 924         if (provider->pd_prov_type != CRYPTO_LOGICAL_PROVIDER) {
 925                 return (is_mech_disabled_byname(provider->pd_prov_type,
 926                     provider->pd_name, provider->pd_instance, name));
 927         }
 928 
 929         /*
 930          * Lock the logical provider just in case one of its hardware
 931          * provider members unregisters.
 932          */
 933         mutex_enter(&provider->pd_lock);
 934         for (e = provider->pd_provider_list; e != NULL; e = e->pl_next) {
 935 
 936                 pd = e->pl_provider;
 937                 ASSERT(pd->pd_prov_type == CRYPTO_HW_PROVIDER);
 938 
 939                 /* find out if mechanism is offered by hw provider */
 940                 count = pd->pd_mech_list_count;
 941                 for (i = 0; i < count; i++) {
 942                         if (strncmp(&pd->pd_mechanisms[i].cm_mech_name[0],
 943                             name, MAXNAMELEN) == 0) {
 944                                 break;
 945                         }
 946                 }
 947                 if (i == count)
 948                         continue;
 949 
 950                 found = !is_mech_disabled_byname(pd->pd_prov_type,
 951                     pd->pd_name, pd->pd_instance, name);
 952 
 953                 if (found)
 954                         break;
 955         }
 956         mutex_exit(&provider->pd_lock);
 957         /*
 958          * If we found the mechanism, then it means it is still enabled for
 959          * at least one hardware provider, so the mech can't be disabled
 960          * for the logical provider.
 961          */
 962         return (!found);
 963 }
 964 
 965 /*
 966  * Builds array of permitted mechanisms.  The array is allocated and
 967  * must be freed by the caller.
 968  */
 969 int
 970 crypto_build_permitted_mech_names(kcf_provider_desc_t *provider,
 971     crypto_mech_name_t **array, uint_t *count, int kmflag)
 972 {
 973         crypto_mech_name_t *mech_names, *p;
 974         uint_t i;
 975         uint_t scnt = provider->pd_mech_list_count;
 976         uint_t dcnt = 0;
 977 
 978         /*
 979          * Compute number of 'permitted mechanisms', which is
 980          * 'supported mechanisms' - 'disabled mechanisms'.
 981          */
 982         for (i = 0; i < scnt; i++) {
 983                 if (is_mech_disabled(provider,
 984                     &provider->pd_mechanisms[i].cm_mech_name[0])) {
 985                         dcnt++;
 986                 }
 987         }
 988 
 989         /* all supported mechanisms have been disabled */
 990         if (scnt == dcnt) {
 991                 *count = 0;
 992                 *array = NULL;
 993                 return (CRYPTO_SUCCESS);
 994         }
 995 
 996         mech_names = kmem_alloc((scnt - dcnt) * sizeof (crypto_mech_name_t),
 997             kmflag);
 998         if (mech_names == NULL)
 999                 return (CRYPTO_HOST_MEMORY);
1000 
1001         /* build array of permitted mechanisms */
1002         for (i = 0, p = mech_names; i < scnt; i++) {
1003                 if (!is_mech_disabled(provider,
1004                     &provider->pd_mechanisms[i].cm_mech_name[0])) {
1005                         bcopy(&provider->pd_mechanisms[i].cm_mech_name[0],
1006                             p++, sizeof (crypto_mech_name_t));
1007                 }
1008         }
1009 
1010         *count = scnt - dcnt;
1011         *array = mech_names;
1012         return (CRYPTO_SUCCESS);
1013 }
1014 
1015 /*
1016  * Free memory for elements in a kcf_soft_config_entry_t.  This entry must
1017  * have been previously removed from the soft_config_list linked list.
1018  */
1019 static void
1020 free_soft_config_entry(kcf_soft_conf_entry_t *p)
1021 {
1022         kmem_free(p->ce_name, strlen(p->ce_name) + 1);
1023         crypto_free_mech_list(p->ce_mechs, p->ce_count);
1024         kmem_free(p, sizeof (kcf_soft_conf_entry_t));
1025 }
1026 
1027 /*
1028  * Store configuration information for software providers in a linked list.
1029  * If the list already contains an entry for the specified provider
1030  * and the specified mechanism list has at least one mechanism, then
1031  * the mechanism list for the provider is updated. If the mechanism list
1032  * is empty, the entry for the provider is removed.
1033  *
1034  * Called from kcf_soft_config_init() (to initially populate the list
1035  * with default kernel providers) and from crypto_load_soft_config() for
1036  * the CRYPTO_LOAD_SOFT_CONFIG ioctl (for third-party kernel modules).
1037  *
1038  * Important note: the array argument must be allocated memory
1039  * since it is consumed in soft_config_list.
1040  *
1041  * Parameters:
1042  * name         Provider name to add or remove.
1043  * count        Number of mechanisms to add.
1044  *              If 0, then remove provider from the list (instead of add).
1045  * array        An array of "count" mechanism names (use only if count > 0).
1046  */
1047 static int
1048 add_soft_config(char *name, uint_t count, crypto_mech_name_t *array)
1049 {
1050         static uint_t soft_config_count = 0;
1051         kcf_soft_conf_entry_t *prev = NULL, *entry = NULL, *new_entry, *p;
1052         size_t name_len;
1053 
1054         /*
1055          * Allocate storage for a new entry.
1056          * Free later if an entry already exists.
1057          */
1058         name_len = strlen(name) + 1;
1059         new_entry = kmem_zalloc(sizeof (kcf_soft_conf_entry_t), KM_SLEEP);
1060         new_entry->ce_name = kmem_alloc(name_len, KM_SLEEP);
1061         (void) strcpy(new_entry->ce_name, name);
1062 
1063         mutex_enter(&soft_config_mutex);
1064 
1065         /* Search to see if provider already in soft_config_list */
1066         for (p = soft_config_list; p != NULL; p = p->ce_next) {
1067                 if (strncmp(name, p->ce_name, MAXNAMELEN) == 0) { /* found */
1068                         entry = p;
1069                         break;
1070                 }
1071                 prev = p;
1072         }
1073 
1074         if (entry == NULL) { /* new provider (not in soft_config_list) */
1075                 if (count == 0) { /* free memory--no entry exists to remove */
1076                         mutex_exit(&soft_config_mutex);
1077                         kmem_free(new_entry->ce_name, name_len);
1078                         kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1079                         return (CRYPTO_SUCCESS);
1080                 }
1081 
1082                 if (soft_config_count > KCF_MAX_CONFIG_ENTRIES) { /* full */
1083                         mutex_exit(&soft_config_mutex);
1084                         kmem_free(new_entry->ce_name, name_len);
1085                         kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1086                         cmn_err(CE_WARN, "out of soft_config_list entries");
1087                         return (CRYPTO_FAILED);
1088                 }
1089 
1090                 /* add new provider to head of list */
1091                 new_entry->ce_next = soft_config_list;
1092                 soft_config_list = new_entry;
1093                 soft_config_count++;
1094                 entry = new_entry;
1095 
1096         } else { /* mechanism already in soft_config_list */
1097                 kmem_free(new_entry->ce_name, name_len);
1098                 kmem_free(new_entry, sizeof (kcf_soft_conf_entry_t));
1099         }
1100 
1101         if (count == 0) { /* remove provider entry from soft_config_list */
1102                 if (prev == NULL) {
1103                         /* entry to remove is at the head of the list */
1104                         soft_config_list = entry->ce_next;
1105                 } else {
1106                         prev->ce_next = entry->ce_next;
1107                 }
1108                 soft_config_count--;
1109                 mutex_exit(&soft_config_mutex);
1110 
1111                 /* free entry */
1112                 free_soft_config_entry(entry);
1113 
1114         } else { /* add provider entry to soft_config_list */
1115                 /*
1116                  * Don't replace a mechanism list if it's already present.
1117                  * This is because the default entries for Software providers
1118                  * are more up-to-date than possibly stale entries in kcf.conf.
1119                  * If an entry is to be deleted, the proper way to do it is
1120                  * to add it to the disablelist (with cryptoadm(1M)),
1121                  * instead of removing it from the supportedlist.
1122                  */
1123                 if (entry->ce_mechs == NULL) { /* add new mechanisms */
1124                         entry->ce_mechs = array;
1125                         entry->ce_count = count;
1126                         mutex_exit(&soft_config_mutex);
1127                 } else { /* ignore replacement mechanism list */
1128                         mutex_exit(&soft_config_mutex);
1129                         crypto_free_mech_list(array, count);
1130                 }
1131         }
1132 
1133         return (CRYPTO_SUCCESS);
1134 }
1135 
1136 /*
1137  * This function removes a module entry from the soft_config_list.
1138  *
1139  * This comes in handy if FIPS 140 is enabled, but fails to validate.  At
1140  * which point when the kernel reports its' supported modules, it shows only
1141  * those that are not within the boundary
1142  */
1143 void
1144 remove_soft_config(char *name)
1145 {
1146         kcf_soft_conf_entry_t *p, *entry = NULL, *prev = NULL;
1147 
1148         mutex_enter(&soft_config_mutex);
1149         /* Search for provider in soft_config_list */
1150         for (p = soft_config_list; p != NULL; p = p->ce_next) {
1151                 if (strncmp(name, p->ce_name, MAXNAMELEN) == 0) {
1152                         entry = p;
1153                         break;
1154                 }
1155                 prev = p;
1156         }
1157 
1158         if (prev == NULL) {
1159                 /* entry to remove is at the head of the list */
1160                 soft_config_list = entry->ce_next;
1161         } else {
1162                 prev->ce_next = entry->ce_next;
1163         }
1164 
1165         mutex_exit(&soft_config_mutex);
1166 
1167         /* free entry */
1168         free_soft_config_entry(entry);
1169 }
1170 
1171 /*
1172  * This routine searches the soft_config_list for the first entry that
1173  * has the specified mechanism in its mechanism list.  If found,
1174  * a buffer containing the name of the software module that implements
1175  * the mechanism is allocated and stored in 'name'.
1176  */
1177 int
1178 get_sw_provider_for_mech(crypto_mech_name_t mech, char **name)
1179 {
1180         kcf_soft_conf_entry_t *p, *next;
1181         char tmp_name[MAXNAMELEN];
1182         size_t name_len = 0;
1183         int i;
1184 
1185         mutex_enter(&soft_config_mutex);
1186         p = soft_config_list;
1187         while (p != NULL) {
1188                 next = p->ce_next;
1189                 for (i = 0; i < p->ce_count; i++) {
1190                         if (strncmp(mech, &p->ce_mechs[i][0],
1191                             CRYPTO_MAX_MECH_NAME) == 0) {
1192                                 name_len = strlen(p->ce_name) + 1;
1193                                 bcopy(p->ce_name, tmp_name, name_len);
1194                                 break;
1195                         }
1196                 }
1197                 p = next;
1198         }
1199         mutex_exit(&soft_config_mutex);
1200 
1201         if (name_len == 0)
1202                 return (CRYPTO_FAILED);
1203 
1204         *name = kmem_alloc(name_len, KM_SLEEP);
1205         bcopy(tmp_name, *name, name_len);
1206         return (CRYPTO_SUCCESS);
1207 }
--- EOF ---