/* * Display the policy information for a kernel software provider. * This implements part of the "cryptoadm list -p" command. * * Parameters phardlist and psoftlist are supplied by * getent_kef(). * If NULL, this function obtains it by calling get_kcfconf_info() * via getent_kef() internally. */ int list_policy_for_soft(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist) { int rc; entry_t *pent = NULL; mechlist_t *pmechlist = NULL; boolean_t has_random = B_FALSE; boolean_t has_mechs = B_FALSE; boolean_t in_kernel = B_FALSE; if (provname == NULL) { return (FAILURE); } if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { return (FAILURE); } else if (in_kernel == B_FALSE) { cryptoerror(LOG_STDERR, gettext("%s does not exist."), provname); return (FAILURE); } pent = getent_kef(provname, phardlist, psoftlist); rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist); if (rc == SUCCESS) { has_random = filter_mechlist(&pmechlist, RANDOM); if (pmechlist != NULL) { has_mechs = B_TRUE; free_mechlist(pmechlist); } } else { cryptoerror(LOG_STDERR, gettext( "failed to retrieve the mechanism list for %s."), provname); return (rc); } print_kef_policy(provname, pent, has_random, has_mechs); free_entry(pent); return (SUCCESS); }
/* * Display the mechanism list for a kernel software provider. * This implements part of the "cryptoadm list -m" command. * * Parameters phardlist and psoftlist are supplied by * get_soft_info(). * If NULL, this function obtains it by calling getent_kef() and * then get_kcfconf_info() via get_soft_info() internally. */ int list_mechlist_for_soft(char *provname, entrylist_t *phardlist, entrylist_t *psoftlist) { mechlist_t *pmechlist = NULL; int rc; if (provname == NULL) { return (FAILURE); } rc = get_soft_info(provname, &pmechlist, phardlist, psoftlist); if (rc == SUCCESS) { (void) filter_mechlist(&pmechlist, RANDOM); print_mechlist(provname, pmechlist); free_mechlist(pmechlist); } else { cryptoerror(LOG_STDERR, gettext( "failed to retrieve the mechanism list for %s."), provname); } return (rc); }
static int cryptoadm_ioctl(dev_t dev, int cmd, intptr_t arg, int mode, cred_t *c, int *rval) { int error; #define ARG ((caddr_t)arg) switch (cmd) { case CRYPTO_LOAD_DEV_DISABLED: case CRYPTO_LOAD_SOFT_DISABLED: case CRYPTO_LOAD_SOFT_CONFIG: case CRYPTO_UNLOAD_SOFT_MODULE: case CRYPTO_POOL_CREATE: case CRYPTO_POOL_WAIT: case CRYPTO_POOL_RUN: case CRYPTO_LOAD_DOOR: case CRYPTO_FIPS140_SET: if ((error = drv_priv(c)) != 0) return (error); default: break; } switch (cmd) { case CRYPTO_GET_DEV_LIST: return (get_dev_list(dev, ARG, mode, rval)); case CRYPTO_GET_DEV_INFO: return (get_dev_info(dev, ARG, mode, rval)); case CRYPTO_GET_SOFT_LIST: return (get_soft_list(dev, ARG, mode, rval)); case CRYPTO_GET_SOFT_INFO: return (get_soft_info(dev, ARG, mode, rval)); case CRYPTO_LOAD_DEV_DISABLED: return (load_dev_disabled(dev, ARG, mode, rval)); case CRYPTO_LOAD_SOFT_DISABLED: return (load_soft_disabled(dev, ARG, mode, rval)); case CRYPTO_LOAD_SOFT_CONFIG: return (load_soft_config(dev, ARG, mode, rval)); case CRYPTO_UNLOAD_SOFT_MODULE: return (unload_soft_module(dev, ARG, mode, rval)); case CRYPTO_POOL_CREATE: /* * The framework allocates and initializes the pool. * So, this is a no op. We are keeping this ioctl around * to be used for any future threadpool related work. */ if (audit_active) audit_cryptoadm(CRYPTO_POOL_CREATE, NULL, NULL, 0, 0, 0, 0); return (0); case CRYPTO_POOL_WAIT: { int nthrs = 0, err; if ((err = kcf_svc_wait(&nthrs)) == 0) { if (copyout((caddr_t)&nthrs, ARG, sizeof (int)) == -1) err = EFAULT; } if (audit_active) audit_cryptoadm(CRYPTO_POOL_WAIT, NULL, NULL, 0, 0, 0, err); return (err); } case CRYPTO_POOL_RUN: { int err; err = kcf_svc_do_run(); if (audit_active) audit_cryptoadm(CRYPTO_POOL_RUN, NULL, NULL, 0, 0, 0, err); return (err); } case CRYPTO_LOAD_DOOR: return (load_door(dev, ARG, mode, rval)); case CRYPTO_FIPS140_STATUS: return (fips140_actions(dev, ARG, mode, rval, cmd)); case CRYPTO_FIPS140_SET: { int err; err = fips140_actions(dev, ARG, mode, rval, cmd); if (audit_active) audit_cryptoadm(CRYPTO_FIPS140_SET, NULL, NULL, 0, 0, 0, err); return (err); } } return (EINVAL); }
/* * Disable a kernel software provider. * This implements the "cryptoadm disable" command for * kernel software providers. */ int disable_kef_software(char *provname, boolean_t rndflag, boolean_t allflag, mechlist_t *dislist) { crypto_load_soft_disabled_t *pload_soft_dis = NULL; mechlist_t *infolist = NULL; entry_t *pent = NULL; entrylist_t *phardlist = NULL; entrylist_t *psoftlist = NULL; boolean_t in_kernel = B_FALSE; int fd = -1; int rc = SUCCESS; if (provname == NULL) { return (FAILURE); } /* * Check if the kernel software provider is currently unloaded. * If it is unloaded, return FAILURE, because the disable subcommand * can not perform on inactive (unloaded) providers. */ if (check_kernel_for_soft(provname, NULL, &in_kernel) == FAILURE) { return (FAILURE); } else if (in_kernel == B_FALSE) { cryptoerror(LOG_STDERR, gettext("%s is not loaded or does not exist."), provname); return (FAILURE); } if (get_kcfconf_info(&phardlist, &psoftlist) == FAILURE) { cryptoerror(LOG_ERR, "failed to retrieve the providers' " "information from the configuration file - %s.", _PATH_KCF_CONF); return (FAILURE); } /* * Get the entry of this provider from the kcf.conf file, if any. * Otherwise, create a new kcf.conf entry for writing back to the file. */ pent = getent_kef(provname, phardlist, psoftlist); if (pent == NULL) { /* create a new entry */ pent = create_entry(provname); if (pent == NULL) { cryptodebug("out of memory."); rc = FAILURE; goto out; } } /* Get the mechanism list for the software provider from the kernel */ if (get_soft_info(provname, &infolist, phardlist, psoftlist) == FAILURE) { rc = FAILURE; goto out; } if ((infolist != NULL) && (infolist->name[0] != '\0')) { /* * Replace the supportedlist from kcf.conf with possibly * more-up-to-date list from the kernel. This is the case * for default software providers that had more mechanisms * added in the current version of the kernel. */ free_mechlist(pent->suplist); pent->suplist = infolist; } /* * kCF treats random as an internal mechanism. So, we need to * filter it from the mechanism list here, if we are NOT disabling * or enabling the random feature. Note that we map random feature at * cryptoadm(1M) level to the "random" mechanism in kCF. */ if (!rndflag) { (void) filter_mechlist(&infolist, RANDOM); } /* Calculate the new disabled list */ if (disable_mechs(&pent, infolist, allflag, dislist) == FAILURE) { rc = FAILURE; goto out; } /* Update the kcf.conf file with the updated entry */ if (update_kcfconf(pent, MODIFY_MODE) == FAILURE) { rc = FAILURE; goto out; } /* Setup argument to inform kernel about the new disabled list. */ if ((pload_soft_dis = setup_soft_dis(pent)) == NULL) { rc = FAILURE; goto out; } if ((fd = open(ADMIN_IOCTL_DEVICE, O_RDWR)) == -1) { cryptoerror(LOG_STDERR, gettext("failed to open %s for RW: %s"), ADMIN_IOCTL_DEVICE, strerror(errno)); rc = FAILURE; goto out; } /* Inform kernel about the new disabled list. */ if (ioctl(fd, CRYPTO_LOAD_SOFT_DISABLED, pload_soft_dis) == -1) { cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl failed: %s", strerror(errno)); rc = FAILURE; goto out; } if (pload_soft_dis->sd_return_value != CRYPTO_SUCCESS) { cryptodebug("CRYPTO_LOAD_SOFT_DISABLED ioctl return_value = " "%d", pload_soft_dis->sd_return_value); rc = FAILURE; goto out; } out: free_entrylist(phardlist); free_entrylist(psoftlist); free_mechlist(infolist); free_entry(pent); free(pload_soft_dis); if (fd != -1) (void) close(fd); return (rc); }