static void kcf_change_mechs(kcf_provider_desc_t *provider, uint_t count, crypto_mech_name_t *array, crypto_event_change_t direction) { crypto_notify_event_change_t ec; crypto_mech_info_t *mi; kcf_prov_mech_desc_t *pmd; char *mech; int i, j, n; ASSERT(direction == CRYPTO_EVENT_CHANGE_ADDED || direction == CRYPTO_EVENT_CHANGE_REMOVED); if (provider == NULL) { /* * Nothing to add or remove from the tables since * the provider isn't registered. */ return; } for (i = 0; i < count; i++) { if (array[i][0] == '\0') continue; mech = &array[i][0]; n = provider->pd_mech_list_count; for (j = 0; j < n; j++) { mi = &provider->pd_mechanisms[j]; if (strncmp(mi->cm_mech_name, mech, CRYPTO_MAX_MECH_NAME) == 0) break; } if (j == n) continue; switch (direction) { case CRYPTO_EVENT_CHANGE_ADDED: (void) kcf_add_mech_provider(mi, provider, &pmd); break; case CRYPTO_EVENT_CHANGE_REMOVED: kcf_remove_mech_provider(mech, provider); break; } /* Inform interested clients of the event */ ec.ec_provider_type = provider->pd_prov_type; ec.ec_change = direction; (void) strncpy(ec.ec_mech_name, mech, CRYPTO_MAX_MECH_NAME); kcf_walk_ntfylist(CRYPTO_EVENT_PROVIDERS_CHANGE, &ec); } }
/* * Process the mechanism info structures specified by the provider * during registration. A NULL crypto_provider_info_t indicates * an already initialized provider descriptor. * * Mechanisms are not added to the kernel's mechanism table if the * provider is a logical provider. * * Returns CRYPTO_SUCCESS on success, CRYPTO_ARGUMENTS if one * of the specified mechanisms was malformed, or CRYPTO_HOST_MEMORY * if the table of mechanisms is full. */ static int init_prov_mechs(crypto_provider_info_t *info, kcf_provider_desc_t *desc) { uint_t mech_idx; uint_t cleanup_idx; int err = CRYPTO_SUCCESS; kcf_prov_mech_desc_t *pmd; int desc_use_count = 0; int mcount = desc->pd_mech_list_count; if (desc->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) { if (info != NULL) { ASSERT(info->pi_mechanisms != NULL); bcopy(info->pi_mechanisms, desc->pd_mechanisms, sizeof (crypto_mech_info_t) * mcount); } return (CRYPTO_SUCCESS); } /* * Copy the mechanism list from the provider info to the provider * descriptor. desc->pd_mechanisms has an extra crypto_mech_info_t * element if the provider has random_ops since we keep an internal * mechanism, SUN_RANDOM, in this case. */ if (info != NULL) { if (info->pi_ops_vector->co_random_ops != NULL) { crypto_mech_info_t *rand_mi; /* * Need the following check as it is possible to have * a provider that implements just random_ops and has * pi_mechanisms == NULL. */ if (info->pi_mechanisms != NULL) { bcopy(info->pi_mechanisms, desc->pd_mechanisms, sizeof (crypto_mech_info_t) * (mcount - 1)); } rand_mi = &desc->pd_mechanisms[mcount - 1]; bzero(rand_mi, sizeof (crypto_mech_info_t)); (void) strncpy(rand_mi->cm_mech_name, SUN_RANDOM, CRYPTO_MAX_MECH_NAME); rand_mi->cm_func_group_mask = CRYPTO_FG_RANDOM; } else { ASSERT(info->pi_mechanisms != NULL); bcopy(info->pi_mechanisms, desc->pd_mechanisms, sizeof (crypto_mech_info_t) * mcount); } } /* * For each mechanism support by the provider, add the provider * to the corresponding KCF mechanism mech_entry chain. */ for (mech_idx = 0; mech_idx < desc->pd_mech_list_count; mech_idx++) { crypto_mech_info_t *mi = &desc->pd_mechanisms[mech_idx]; if ((mi->cm_mech_flags & CRYPTO_KEYSIZE_UNIT_IN_BITS) && (mi->cm_mech_flags & CRYPTO_KEYSIZE_UNIT_IN_BYTES)) { err = CRYPTO_ARGUMENTS_BAD; break; } if (desc->pd_flags & CRYPTO_HASH_NO_UPDATE && mi->cm_func_group_mask & CRYPTO_FG_DIGEST) { /* * We ask the provider to specify the limit * per hash mechanism. But, in practice, a * hardware limitation means all hash mechanisms * will have the same maximum size allowed for * input data. So, we make it a per provider * limit to keep it simple. */ if (mi->cm_max_input_length == 0) { err = CRYPTO_ARGUMENTS_BAD; break; } else { desc->pd_hash_limit = mi->cm_max_input_length; } } if ((err = kcf_add_mech_provider(mech_idx, desc, &pmd)) != KCF_SUCCESS) break; if (pmd == NULL) continue; /* The provider will be used for this mechanism */ desc_use_count++; } /* * Don't allow multiple software providers with disabled mechanisms * to register. Subsequent enabling of mechanisms will result in * an unsupported configuration, i.e. multiple software providers * per mechanism. */ if (desc_use_count == 0 && desc->pd_prov_type == CRYPTO_SW_PROVIDER) return (CRYPTO_ARGUMENTS_BAD); if (err == KCF_SUCCESS) return (CRYPTO_SUCCESS); /* * An error occurred while adding the mechanism, cleanup * and bail. */ for (cleanup_idx = 0; cleanup_idx < mech_idx; cleanup_idx++) { kcf_remove_mech_provider( desc->pd_mechanisms[cleanup_idx].cm_mech_name, desc); } if (err == KCF_MECH_TAB_FULL) return (CRYPTO_HOST_MEMORY); return (CRYPTO_ARGUMENTS_BAD); }