Print this page
6414175 kcf.conf's supportedlist not providing much usefulness

@@ -246,13 +246,13 @@
 
 
 /*
  * Get the provider type.  This function returns
  * - PROV_UEF_LIB if provname contains an absolute path name
- * - PROV_KEF_SOFT if provname is a base name only
+ * - PROV_KEF_SOFT if provname is a base name only (e.g., "aes").
  * - PROV_KEF_HARD if provname contains one slash only and the slash is not
- *      the 1st character.
+ *      the 1st character (e.g., "mca/0").
  * - PROV_BADNAME otherwise.
  */
 static int
 get_provider_type(char *provname)
 {

@@ -528,11 +528,11 @@
 }
 
 
 
 /*
- * The top level function for the list subcommand and options.
+ * The top level function for the "cryptoadm list" subcommand and options.
  */
 static int
 do_list(int argc, char **argv)
 {
         boolean_t       mflag = B_FALSE;

@@ -549,11 +549,11 @@
                 rc = list_simple_for_all(B_FALSE);
                 goto out;
         }
 
         /*
-         * [-v] [-m] [-p] [provider=<>] [mechanism=<>]
+         * cryptoadm list [-v] [-m] [-p] [provider=<>] [mechanism=<>]
          */
         if (argc > 5) {
                 usage();
                 return (rc);
         }

@@ -629,39 +629,41 @@
         } else if (prov->cp_type == PROV_BADNAME) {
                 usage();
                 rc = ERROR_USAGE;
                 goto out;
         } else { /* do the listing for a provider only */
+                char    *provname = prov->cp_name;
+
                 if (mflag || vflag) {
                         if (vflag)
                                 (void) printf(gettext("Provider: %s\n"),
-                                        prov->cp_name);
+                                    provname);
                         switch (prov->cp_type) {
                         case PROV_UEF_LIB:
-                                rc = list_mechlist_for_lib(prov->cp_name,
-                                        mecharglist, NULL, B_FALSE,
-                                        vflag, mflag);
+                                rc = list_mechlist_for_lib(provname,
+                                    mecharglist, NULL, B_FALSE, vflag, mflag);
                                 break;
                         case PROV_KEF_SOFT:
-                                rc = list_mechlist_for_soft(prov->cp_name);
+                                rc = list_mechlist_for_soft(provname,
+                                    NULL, NULL);
                                 break;
                         case PROV_KEF_HARD:
-                                rc = list_mechlist_for_hard(prov->cp_name);
+                                rc = list_mechlist_for_hard(provname);
                                 break;
                         default: /* should not come here */
                                 rc = FAILURE;
                                 break;
                         }
                 } else if (pflag) {
                         switch (prov->cp_type) {
                         case PROV_UEF_LIB:
-                                rc = list_policy_for_lib(prov->cp_name);
+                                rc = list_policy_for_lib(provname);
                                 break;
                         case PROV_KEF_SOFT:
                                 if (getzoneid() == GLOBAL_ZONEID) {
-                                        rc = list_policy_for_soft(
-                                            prov->cp_name);
+                                        rc = list_policy_for_soft(provname,
+                                            NULL, NULL);
                                 } else {
                                         /*
                                          * TRANSLATION_NOTE
                                          * "global" is keyword and not to
                                          * be translated.

@@ -674,11 +676,11 @@
                                 }
                                 break;
                         case PROV_KEF_HARD:
                                 if (getzoneid() == GLOBAL_ZONEID) {
                                         rc = list_policy_for_hard(
-                                            prov->cp_name);
+                                            provname, NULL, NULL, NULL);
                                 } else {
                                         /*
                                          * TRANSLATION_NOTE
                                          * "global" is keyword and not to
                                          * be translated.

@@ -711,11 +713,11 @@
         return (rc);
 }
 
 
 /*
- * The top level function for the disable subcommand.
+ * The top level function for the "cryptoadm disable" subcommand.
  */
 static int
 do_disable(int argc, char **argv)
 {
         cryptoadm_provider_t    *prov = NULL;

@@ -828,19 +830,20 @@
         return (rc);
 }
 
 
 /*
- * The top level function fo the enable subcommand.
+ * The top level function for the "cryptoadm enable" subcommand.
  */
 static int
 do_enable(int argc, char **argv)
 {
         cryptoadm_provider_t    *prov = NULL;
         int     rc = SUCCESS;
         char *alt_token = NULL, *alt_slot = NULL;
-        boolean_t use_default = B_FALSE, auto_key_migrate_flag = B_FALSE;
+        boolean_t               use_default = B_FALSE;
+        boolean_t               auto_key_migrate_flag = B_FALSE;
 
         if ((argc < 3) || (argc > 6)) {
                 usage();
                 return (ERROR_USAGE);
         }

@@ -942,11 +945,11 @@
 }
 
 
 
 /*
- * The top level function fo the install subcommand.
+ * The top level function for the "cryptoadm install" subcommand.
  */
 static int
 do_install(int argc, char **argv)
 {
         cryptoadm_provider_t    *prov = NULL;

@@ -1032,11 +1035,11 @@
 }
 
 
 
 /*
- * The top level function for the uninstall subcommand.
+ * The top level function for the "cryptoadm uninstall" subcommand.
  */
 static int
 do_uninstall(int argc, char **argv)
 {
         cryptoadm_provider_t    *prov = NULL;

@@ -1062,12 +1065,14 @@
                 return (FAILURE);
         }
 
         if (prov->cp_type == PROV_UEF_LIB) {
                 rc = uninstall_uef_lib(prov->cp_name);
+
         } else if (prov->cp_type == PROV_KEF_SOFT) {
                 if (getzoneid() == GLOBAL_ZONEID) {
+                        /* unload and remove from kcf.conf */
                         rc = uninstall_kef(prov->cp_name);
                 } else {
                         /*
                          * TRANSLATION_NOTE
                          * "uninstall" could be either a literal keyword and

@@ -1087,19 +1092,20 @@
         return (rc);
 }
 
 
 /*
- * The top level function for the unload subcommand.
+ * The top level function for the "cryptoadm unload" subcommand.
  */
 static int
 do_unload(int argc, char **argv)
 {
         cryptoadm_provider_t    *prov = NULL;
-        entry_t *pent;
-        boolean_t       is_active;
+        entry_t                 *pent = NULL;
+        boolean_t               in_kernel = B_FALSE;
         int rc = SUCCESS;
+        char                    *provname = NULL;
 
         if (argc != 3) {
                 usage();
                 return (ERROR_USAGE);
         }

@@ -1109,14 +1115,15 @@
         if (prov == NULL) {
                 cryptoerror(LOG_STDERR,
                     gettext("unable to determine provider name."));
                 goto out;
         }
+        provname = prov->cp_name;
         if (prov->cp_type != PROV_KEF_SOFT) {
                 cryptoerror(LOG_STDERR,
                     gettext("%s is not a valid kernel software provider."),
-                    prov->cp_name);
+                    provname);
                 rc = FAILURE;
                 goto out;
         }
 
         if (getzoneid() != GLOBAL_ZONEID) {

@@ -1131,69 +1138,79 @@
                     "is supported in the %2$s zone only"), "unload", "global");
                 rc = FAILURE;
                 goto out;
         }
 
-        /* Check if it is in the kcf.conf file first */
-        if ((pent = getent_kef(prov->cp_name)) == NULL) {
+        if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) {
+                cryptodebug("internal error");
+                rc = FAILURE;
+                goto out;
+        } else if (in_kernel == B_FALSE) {
                 cryptoerror(LOG_STDERR,
-                    gettext("provider %s does not exist."), prov->cp_name);
+                    gettext("provider %s is not loaded or does not exist."),
+                    provname);
                 rc = FAILURE;
                 goto out;
         }
-        free_entry(pent);
 
-        /* If it is unloaded already, return  */
-        if (check_active_for_soft(prov->cp_name, &is_active) == FAILURE) {
-                cryptodebug("internal error");
-                cryptoerror(LOG_STDERR,
-                    gettext("failed to unload %s."), prov->cp_name);
+        /* Get kcf.conf entry.  If none, build a new entry */
+        if ((pent = getent_kef(provname, NULL, NULL)) == NULL) {
+                if ((pent = create_entry(provname)) == NULL) {
+                        cryptoerror(LOG_STDERR, gettext("out of memory."));
                 rc = FAILURE;
                 goto out;
         }
+        }
 
-        if (is_active == B_FALSE) { /* unloaded already */
-                rc = SUCCESS;
-                goto out;
-        } else if (unload_kef_soft(prov->cp_name, B_TRUE) == FAILURE) {
+        /* If it is unloaded already, return  */
+        if (!pent->load) { /* unloaded already */
                 cryptoerror(LOG_STDERR,
-                    gettext("failed to unload %s."), prov->cp_name);
+                    gettext("failed to unload %s."), provname);
                 rc = FAILURE;
+                goto out;
+        } else if (unload_kef_soft(provname) != FAILURE) {
+                /* Mark as unloaded in kcf.conf */
+                pent->load = B_FALSE;
+                rc = update_kcfconf(pent, MODIFY_MODE);
         } else {
-                rc = SUCCESS;
+                cryptoerror(LOG_STDERR,
+                    gettext("failed to unload %s."), provname);
+                rc = FAILURE;
         }
 out:
         free(prov);
+        free_entry(pent);
         return (rc);
 }
 
 
 
 /*
- * The top level function for the refresh subcommand.
+ * The top level function for the "cryptoadm refresh" subcommand.
  */
 static int
 do_refresh(int argc)
 {
         if (argc != 2) {
                 usage();
                 return (ERROR_USAGE);
         }
 
+        if (getzoneid() == GLOBAL_ZONEID) {
+                return (refresh());
+        } else { /* non-global zone */
         /*
          * Note:  in non-global zone, this must silently return SUCCESS
          * due to integration with SMF, for "svcadm refresh cryptosvc"
          */
-        if (getzoneid() != GLOBAL_ZONEID)
                 return (SUCCESS);
-
-        return (refresh());
+        }
 }
 
 
 /*
- * The top level function for the start subcommand.
+ * The top level function for the "cryptoadm start" subcommand.
  */
 static int
 do_start(int argc)
 {
         int ret;

@@ -1209,11 +1226,11 @@
 
         return (start_daemon());
 }
 
 /*
- * The top level function for the stop subcommand.
+ * The top level function for the "cryptoadm stop" subcommand.
  */
 static int
 do_stop(int argc)
 {
         if (argc != 2) {

@@ -1225,38 +1242,32 @@
 }
 
 
 
 /*
- * List all the providers.
+ * Print a list all the the providers.
+ * Called for "cryptoadm list" or "cryptoadm list -v" (no -m or -p).
  */
 static int
 list_simple_for_all(boolean_t verbose)
 {
-        uentrylist_t    *pliblist;
-        uentrylist_t    *plibptr;
-        entrylist_t     *pdevlist_conf;
-        entrylist_t     *psoftlist_conf;
-        entrylist_t     *pdevlist_zone;
-        entrylist_t     *psoftlist_zone;
-        entrylist_t     *ptr;
+        uentrylist_t            *pliblist = NULL;
+        uentrylist_t            *plibptr = NULL;
+        entry_t                 *pent = NULL;
         crypto_get_dev_list_t   *pdevlist_kernel = NULL;
-        boolean_t       is_active;
-        int     ru = SUCCESS;
-        int     rs = SUCCESS;
-        int     rd = SUCCESS;
+        int                     rc = SUCCESS;
         int     i;
 
         /* get user-level providers */
         (void) printf(gettext("\nUser-level providers:\n"));
         if (get_pkcs11conf_info(&pliblist) != SUCCESS) {
                 cryptoerror(LOG_STDERR, gettext(
                     "failed to retrieve the list of user-level providers."));
-                ru = FAILURE;
+                rc = FAILURE;
         }
-        plibptr = pliblist;
-        while (plibptr != NULL) {
+
+        for (plibptr = pliblist; plibptr != NULL; plibptr = plibptr->next) {
                 if (strcmp(plibptr->puent->name, METASLOT_KEYWORD) != 0) {
                         (void) printf(gettext("Provider: %s\n"),
                             plibptr->puent->name);
                         if (verbose) {
                                 (void) list_mechlist_for_lib(

@@ -1263,63 +1274,69 @@
                                     plibptr->puent->name, mecharglist, NULL,
                                     B_FALSE, verbose, B_FALSE);
                                 (void) printf("\n");
                         }
                 }
-                plibptr = plibptr->next;
         }
         free_uentrylist(pliblist);
 
         /* get kernel software providers */
         (void) printf(gettext("\nKernel software providers:\n"));
 
         if (getzoneid() == GLOBAL_ZONEID) {
-                /* use kcf.conf for kernel software providers in global zone */
-                pdevlist_conf = NULL;
-                psoftlist_conf = NULL;
+                /* get kernel software providers from kernel ioctl */
+                crypto_get_soft_list_t          *psoftlist_kernel = NULL;
+                uint_t                          sl_soft_count;
+                char                            *psoftname;
+                entrylist_t                     *pdevlist_conf = NULL;
+                entrylist_t                     *psoftlist_conf = NULL;
 
-                if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) !=
-                    SUCCESS) {
-                        cryptoerror(LOG_STDERR,
-                            gettext("failed to retrieve the "
-                            "list of kernel software providers.\n"));
-                        rs = FAILURE;
-                }
+                if (get_soft_list(&psoftlist_kernel) == FAILURE) {
+                        cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
+                            "software provider list from kernel."));
+                        rc = FAILURE;
+                } else {
+                        sl_soft_count = psoftlist_kernel->sl_soft_count;
 
-                ptr = psoftlist_conf;
-                while (ptr != NULL) {
-                        if (check_active_for_soft(ptr->pent->name, &is_active)
+                        if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf)
                             == FAILURE) {
-                                rs = FAILURE;
-                                cryptoerror(LOG_STDERR, gettext("failed to "
-                                    "get the state of a kernel software "
-                                    "providers.\n"));
-                                break;
-                        }
-
-                        (void) printf("\t%s", ptr->pent->name);
-                        if (is_active == B_FALSE) {
-                                (void) printf(gettext(" (inactive)\n"));
+                                cryptoerror(LOG_ERR,
+                                    "failed to retrieve the providers' "
+                                    "information from file kcf.conf - %s.",
+                                    _PATH_KCF_CONF);
+                                free(psoftlist_kernel);
+                                rc = FAILURE;
                         } else {
-                                (void) printf("\n");
-                        }
-                        ptr = ptr->next;
-                }
 
+                                for (i = 0,
+                                    psoftname = psoftlist_kernel->sl_soft_names;
+                                    i < sl_soft_count;
+                                    ++i, psoftname += strlen(psoftname) + 1) {
+                                        pent = getent_kef(psoftname,
+                                            pdevlist_conf, psoftlist_conf);
+                                        (void) printf("\t%s%s\n", psoftname,
+                                            (pent == NULL) || (pent->load) ?
+                                            "" : gettext(" (inactive)"));
+                                }
                 free_entrylist(pdevlist_conf);
                 free_entrylist(psoftlist_conf);
+                        }
+                        free(psoftlist_kernel);
+                }
+
         } else {
                 /* kcf.conf not there in non-global zone, use /dev/cryptoadm */
-                pdevlist_zone = NULL;
-                psoftlist_zone = NULL;
+                entrylist_t     *pdevlist_zone = NULL;
+                entrylist_t     *psoftlist_zone = NULL;
+                entrylist_t     *ptr;
 
                 if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
                     SUCCESS) {
                         cryptoerror(LOG_STDERR,
                             gettext("failed to retrieve the "
                             "list of kernel software providers.\n"));
-                        rs = FAILURE;
+                        rc = FAILURE;
                 }
 
                 ptr = psoftlist_zone;
                 while (ptr != NULL) {
                         (void) printf("\t%s\n", ptr->pent->name);

@@ -1333,45 +1350,37 @@
         /* get kernel hardware providers */
         (void) printf(gettext("\nKernel hardware providers:\n"));
         if (get_dev_list(&pdevlist_kernel) == FAILURE) {
                 cryptoerror(LOG_STDERR, gettext("failed to retrieve "
                     "the list of kernel hardware providers.\n"));
-                rd = FAILURE;
+                rc = FAILURE;
         } else {
                 for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
                         (void) printf("\t%s/%d\n",
                             pdevlist_kernel->dl_devs[i].le_dev_name,
                             pdevlist_kernel->dl_devs[i].le_dev_instance);
                 }
         }
         free(pdevlist_kernel);
 
-        if (ru == FAILURE || rs == FAILURE || rd == FAILURE) {
-                return (FAILURE);
-        } else {
-                return (SUCCESS);
-        }
+        return (rc);
 }
 
 
 
 /*
  * List all the providers. And for each provider, list the mechanism list.
+ * Called for "cryptoadm list -m" or "cryptoadm list -mv" .
  */
 static int
 list_mechlist_for_all(boolean_t verbose)
 {
-        crypto_get_dev_list_t   *pdevlist_kernel;
-        uentrylist_t    *pliblist;
-        uentrylist_t    *plibptr;
-        entrylist_t     *pdevlist_conf;
-        entrylist_t     *psoftlist_conf;
-        entrylist_t     *pdevlist_zone;
-        entrylist_t     *psoftlist_zone;
-        entrylist_t     *ptr;
-        mechlist_t      *pmechlist;
-        boolean_t       is_active;
+        crypto_get_dev_list_t   *pdevlist_kernel = NULL;
+        uentrylist_t            *pliblist = NULL;
+        uentrylist_t            *plibptr = NULL;
+        entry_t                 *pent = NULL;
+        mechlist_t              *pmechlist = NULL;
         char    provname[MAXNAMELEN];
         char    devname[MAXNAMELEN];
         int     inst_num;
         int     count;
         int     i;

@@ -1408,77 +1417,86 @@
         }
         free_uentrylist(pliblist);
 
         /* get kernel software providers */
         (void) printf(gettext("\nKernel software providers:\n"));
+
         /*
          * TRANSLATION_NOTE
          * Strictly for appearance's sake, this line should be as long as
          * the length of the translated text above.
          */
         (void) printf(gettext("==========================\n"));
         if (getzoneid() == GLOBAL_ZONEID) {
-                /* use kcf.conf for kernel software providers in global zone */
-                pdevlist_conf = NULL;
-                psoftlist_conf = NULL;
+                /* get kernel software providers from kernel ioctl */
+                crypto_get_soft_list_t          *psoftlist_kernel = NULL;
+                uint_t                          sl_soft_count;
+                char                            *psoftname;
+                int                             i;
+                entrylist_t                     *pdevlist_conf = NULL;
+                entrylist_t                     *psoftlist_conf = NULL;
 
-                if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) !=
-                    SUCCESS) {
-                        cryptoerror(LOG_STDERR, gettext("failed to retrieve "
-                            "the list of kernel software providers.\n"));
-                        rc = FAILURE;
+                if (get_soft_list(&psoftlist_kernel) == FAILURE) {
+                        cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
+                            "software provider list from kernel."));
+                        return (FAILURE);
                 }
+                sl_soft_count = psoftlist_kernel->sl_soft_count;
 
-                ptr = psoftlist_conf;
-                while (ptr != NULL) {
-                        if (check_active_for_soft(ptr->pent->name, &is_active)
-                            == SUCCESS) {
-                                if (is_active) {
-                                        rv = list_mechlist_for_soft(
-                                            ptr->pent->name);
+                if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf)
+                    == FAILURE) {
+                        cryptoerror(LOG_ERR,
+                            "failed to retrieve the providers' "
+                            "information from file kcf.conf - %s.",
+                            _PATH_KCF_CONF);
+                        free(psoftlist_kernel);
+                        return (FAILURE);
+                }
+
+                for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
+                    i < sl_soft_count;
+                    ++i, psoftname += strlen(psoftname) + 1) {
+                        pent = getent_kef(psoftname, pdevlist_conf,
+                            psoftlist_conf);
+                        if ((pent == NULL) || (pent->load)) {
+                                rv = list_mechlist_for_soft(psoftname,
+                                    NULL, NULL);
                                         if (rv == FAILURE) {
                                                 rc = FAILURE;
                                         }
                                 } else {
-                                        (void) printf(gettext(
-                                            "%s: (inactive)\n"),
-                                            ptr->pent->name);
+                                (void) printf(gettext("%s: (inactive)\n"),
+                                    psoftname);
                                 }
-                        } else {
-                                /* should not happen */
-                                (void) printf(gettext(
-                                    "%s: failed to get the mechanism list.\n"),
-                                    ptr->pent->name);
-                                rc = FAILURE;
                         }
-                        ptr = ptr->next;
-                }
 
+                free(psoftlist_kernel);
                 free_entrylist(pdevlist_conf);
                 free_entrylist(psoftlist_conf);
+
         } else {
                 /* kcf.conf not there in non-global zone, use /dev/cryptoadm */
-                pdevlist_zone = NULL;
-                psoftlist_zone = NULL;
+                entrylist_t     *pdevlist_zone = NULL;
+                entrylist_t     *psoftlist_zone = NULL;
+                entrylist_t     *ptr;
 
                 if (get_admindev_info(&pdevlist_zone, &psoftlist_zone) !=
                     SUCCESS) {
                         cryptoerror(LOG_STDERR, gettext("failed to retrieve "
                             "the list of kernel software providers.\n"));
                         rc = FAILURE;
                 }
 
-                ptr = psoftlist_zone;
-                while (ptr != NULL) {
-                        rv = list_mechlist_for_soft(ptr->pent->name);
+                for (ptr = psoftlist_zone; ptr != NULL; ptr = ptr->next) {
+                        rv = list_mechlist_for_soft(ptr->pent->name,
+                            pdevlist_zone, psoftlist_zone);
                         if (rv == FAILURE) {
                                 (void) printf(gettext(
                                     "%s: failed to get the mechanism list.\n"),
                                     ptr->pent->name);
                                 rc = FAILURE;
                         }
-                        ptr = ptr->next;
                 }
 
                 free_entrylist(pdevlist_zone);
                 free_entrylist(psoftlist_zone);
         }

@@ -1520,22 +1538,22 @@
 }
 
 
 /*
  * List all the providers. And for each provider, list the policy information.
+ * Called for "cryptoadm list -p".
  */
 static int
 list_policy_for_all(void)
 {
-        crypto_get_dev_list_t   *pdevlist_kernel;
-        uentrylist_t    *pliblist;
-        uentrylist_t    *plibptr;
-        entrylist_t     *pdevlist_conf;
-        entrylist_t     *psoftlist_conf;
-        entrylist_t     *ptr;
-        entrylist_t     *phead;
-        boolean_t       found;
+        crypto_get_dev_list_t   *pdevlist_kernel = NULL;
+        uentrylist_t            *pliblist = NULL;
+        entrylist_t             *pdevlist_conf = NULL;
+        entrylist_t             *psoftlist_conf = NULL;
+        entrylist_t             *ptr = NULL;
+        entrylist_t             *phead = NULL;
+        boolean_t               found = B_FALSE;
         char    provname[MAXNAMELEN];
         int     i;
         int     rc = SUCCESS;
 
         /* Get user-level providers */

@@ -1547,12 +1565,14 @@
          */
         (void) printf(gettext("=====================\n"));
         if (get_pkcs11conf_info(&pliblist) == FAILURE) {
                 cryptoerror(LOG_STDERR, gettext("failed to retrieve "
                     "the list of user-level providers.\n"));
+                rc = FAILURE;
         } else {
-                plibptr = pliblist;
+                uentrylist_t    *plibptr = pliblist;
+
                 while (plibptr != NULL) {
                         /* skip metaslot entry */
                         if (strcmp(plibptr->puent->name,
                             METASLOT_KEYWORD) != 0) {
                                 if (print_uef_policy(plibptr->puent)

@@ -1572,31 +1592,34 @@
          * Strictly for appearance's sake, this line should be as long as
          * the length of the translated text above.
          */
         (void) printf(gettext("==========================\n"));
 
-        /* Get all entries from the kcf.conf file */
-        pdevlist_conf = NULL;
+        /* Get all entries from the kernel */
         if (getzoneid() == GLOBAL_ZONEID) {
-                /* use kcf.conf for kernel software providers in global zone */
-                psoftlist_conf = NULL;
+                /* get kernel software providers from kernel ioctl */
+                crypto_get_soft_list_t          *psoftlist_kernel = NULL;
+                uint_t                          sl_soft_count;
+                char                            *psoftname;
+                int                             i;
 
-                if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) ==
-                    FAILURE) {
-                        cryptoerror(LOG_STDERR, gettext(
-                            "failed to retrieve the list of kernel "
-                            "providers.\n"));
-                        return (FAILURE);
-                }
+                if (get_soft_list(&psoftlist_kernel) == FAILURE) {
+                        cryptoerror(LOG_ERR, gettext("Failed to retrieve the "
+                            "software provider list from kernel."));
+                        rc = FAILURE;
+                } else {
+                        sl_soft_count = psoftlist_kernel->sl_soft_count;
 
-                ptr = psoftlist_conf;
-                while (ptr != NULL) {
-                        (void) list_policy_for_soft(ptr->pent->name);
-                        ptr = ptr->next;
+                        for (i = 0, psoftname = psoftlist_kernel->sl_soft_names;
+                            i < sl_soft_count;
+                            ++i, psoftname += strlen(psoftname) + 1) {
+                                (void) list_policy_for_soft(psoftname,
+                                    pdevlist_conf, psoftlist_conf);
                 }
+                        free(psoftlist_kernel);
+                }
 
-                free_entrylist(psoftlist_conf);
         } else {
                 /* kcf.conf not there in non-global zone, no policy info */
 
                 /*
                  * TRANSLATION_NOTE

@@ -1629,14 +1652,21 @@
 
         /* Get the hardware provider list from kernel */
         if (get_dev_list(&pdevlist_kernel) != SUCCESS) {
                 cryptoerror(LOG_STDERR, gettext(
                     "failed to retrieve the list of hardware providers.\n"));
-                free_entrylist(pdevlist_conf);
                 return (FAILURE);
         }
 
+        if (get_kcfconf_info(&pdevlist_conf, &psoftlist_conf) == FAILURE) {
+                cryptoerror(LOG_ERR, "failed to retrieve the providers' "
+                    "information from file kcf.conf - %s.",
+                    _PATH_KCF_CONF);
+                return (FAILURE);
+        }
+
+
         /*
          * For each hardware provider from kernel, check if it has an entry
          * in the config file.  If it has an entry, print out the policy from
          * config file and remove the entry from the hardware provider list
          * of the config file.  If it does not have an entry in the config

@@ -1645,10 +1675,11 @@
          */
         for (i = 0; i < pdevlist_kernel->dl_dev_count; i++) {
                 (void) snprintf(provname, sizeof (provname), "%s/%d",
                     pdevlist_kernel->dl_devs[i].le_dev_name,
                     pdevlist_kernel->dl_devs[i].le_dev_instance);
+
                 found = B_FALSE;
                 phead = ptr = pdevlist_conf;
                 while (!found && ptr) {
                         if (strcmp(ptr->pent->name, provname) == 0) {
                                 found = B_TRUE;

@@ -1657,34 +1688,35 @@
                                 ptr = ptr->next;
                         }
                 }
 
                 if (found) {
-                        (void) list_policy_for_hard(ptr->pent->name);
+                        (void) list_policy_for_hard(ptr->pent->name,
+                            pdevlist_conf, psoftlist_conf, pdevlist_kernel);
                         if (phead == ptr) {
                                 pdevlist_conf = pdevlist_conf->next;
                         } else {
                                 phead->next = ptr->next;
                         }
                         free_entry(ptr->pent);
                         free(ptr);
                 } else {
-                        (void) list_policy_for_hard(provname);
+                        (void) list_policy_for_hard(provname, pdevlist_conf,
+                            psoftlist_conf, pdevlist_kernel);
                 }
         }
 
         /*
          * If there are still entries left in the pdevlist_conf list from
          * the config file, these providers must have been detached.
          * Should print out their policy information also.
          */
-        ptr = pdevlist_conf;
-        while (ptr != NULL) {
-                print_kef_policy(ptr->pent, B_FALSE, B_TRUE);
-                ptr = ptr->next;
+        for (ptr = pdevlist_conf; ptr != NULL; ptr = ptr->next) {
+                print_kef_policy(ptr->pent->name, ptr->pent, B_FALSE, B_TRUE);
         }
 
         free_entrylist(pdevlist_conf);
+        free_entrylist(psoftlist_conf);
         free(pdevlist_kernel);
 
         return (rc);
 }