10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
51808Smcpowers * Common Development and Distribution License (the "License").
61808Smcpowers * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12304SValerie.Fenwick@Oracle.COM * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate #include <sys/types.h>
260Sstevel@tonic-gate #include <sys/sunddi.h>
270Sstevel@tonic-gate #include <sys/disp.h>
280Sstevel@tonic-gate #include <sys/modctl.h>
29904Smcpowers #include <sys/sysmacros.h>
300Sstevel@tonic-gate #include <sys/crypto/common.h>
310Sstevel@tonic-gate #include <sys/crypto/api.h>
320Sstevel@tonic-gate #include <sys/crypto/impl.h>
330Sstevel@tonic-gate #include <sys/crypto/sched_impl.h>
340Sstevel@tonic-gate
35904Smcpowers #define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \
36904Smcpowers ((ch) == '\t') || ((ch) == '\f'))
37904Smcpowers
38904Smcpowers #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
39904Smcpowers #define CRYPTO_KEY_OFFSET(f) offsetof(crypto_key_ops_t, f)
40904Smcpowers #define CRYPTO_PROVIDER_OFFSET(f) \
41904Smcpowers offsetof(crypto_provider_management_ops_t, f)
42904Smcpowers
430Sstevel@tonic-gate /* Miscellaneous exported entry points */
440Sstevel@tonic-gate
450Sstevel@tonic-gate /*
460Sstevel@tonic-gate * All event subscribers are put on a list. kcf_notify_list_lock
470Sstevel@tonic-gate * protects changes to this list.
480Sstevel@tonic-gate *
490Sstevel@tonic-gate * The following locking order is maintained in the code - The
500Sstevel@tonic-gate * global kcf_notify_list_lock followed by the individual lock
510Sstevel@tonic-gate * in a kcf_ntfy_elem structure (kn_lock).
520Sstevel@tonic-gate */
530Sstevel@tonic-gate kmutex_t ntfy_list_lock;
540Sstevel@tonic-gate kcondvar_t ntfy_list_cv; /* cv the service thread waits on */
550Sstevel@tonic-gate static kcf_ntfy_elem_t *ntfy_list_head;
560Sstevel@tonic-gate static kcf_ntfy_elem_t *ntfy_list_tail;
570Sstevel@tonic-gate
580Sstevel@tonic-gate /* count all the hardware and software providers */
590Sstevel@tonic-gate #define PROV_COUNT(me) \
600Sstevel@tonic-gate (((me)->me_sw_prov != NULL ? 1 : 0) + (me)->me_num_hwprov)
610Sstevel@tonic-gate
620Sstevel@tonic-gate /*
630Sstevel@tonic-gate * crypto_mech2id()
640Sstevel@tonic-gate *
650Sstevel@tonic-gate * Arguments:
660Sstevel@tonic-gate * . mechname: A null-terminated string identifying the mechanism name.
670Sstevel@tonic-gate *
680Sstevel@tonic-gate * Description:
690Sstevel@tonic-gate * Walks the mechanisms tables, looking for an entry that matches the
700Sstevel@tonic-gate * mechname. Once it find it, it builds the 64-bit mech_type and returns
710Sstevel@tonic-gate * it. If there are no hardware or software providers for the mechanism,
720Sstevel@tonic-gate * but there is an unloaded software provider, this routine will attempt
730Sstevel@tonic-gate * to load it.
740Sstevel@tonic-gate *
750Sstevel@tonic-gate * Context:
760Sstevel@tonic-gate * Process and interruption.
770Sstevel@tonic-gate *
780Sstevel@tonic-gate * Returns:
790Sstevel@tonic-gate * The unique mechanism identified by 'mechname', if found.
800Sstevel@tonic-gate * CRYPTO_MECH_INVALID otherwise.
810Sstevel@tonic-gate */
820Sstevel@tonic-gate crypto_mech_type_t
crypto_mech2id(char * mechname)830Sstevel@tonic-gate crypto_mech2id(char *mechname)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate return (crypto_mech2id_common(mechname, B_TRUE));
860Sstevel@tonic-gate }
870Sstevel@tonic-gate
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate * crypto_get_mech_list()
900Sstevel@tonic-gate *
910Sstevel@tonic-gate * Arguments:
920Sstevel@tonic-gate * . countp: pointer to contain the number of mech names returned
930Sstevel@tonic-gate * . kmflag: memory allocation flag.
940Sstevel@tonic-gate *
950Sstevel@tonic-gate * Description:
960Sstevel@tonic-gate * Allocates an array of crypto_mech_name_t containing all the mechanisms
970Sstevel@tonic-gate * currently available on the system. Sets *countp with the number of
980Sstevel@tonic-gate * mechanism names returned.
990Sstevel@tonic-gate *
1000Sstevel@tonic-gate * We get a list of mech names which have a hardware provider by walking
1010Sstevel@tonic-gate * all the mechanism tables. We merge them with mech names obtained from
1020Sstevel@tonic-gate * the hint list. A mech name in the hint list is considered only if it
1030Sstevel@tonic-gate * is not disabled for the provider. Note that the hint list contains only
1040Sstevel@tonic-gate * software providers and the mech names supported by them.
1050Sstevel@tonic-gate *
1060Sstevel@tonic-gate * Context:
1070Sstevel@tonic-gate * Process and interruption. kmflag should be KM_NOSLEEP when called
1080Sstevel@tonic-gate * from an interruption context.
1090Sstevel@tonic-gate *
1100Sstevel@tonic-gate * Returns:
1110Sstevel@tonic-gate * The array of the crypto_mech_t allocated.
1120Sstevel@tonic-gate * NULL otherwise.
1130Sstevel@tonic-gate */
1140Sstevel@tonic-gate crypto_mech_name_t *
crypto_get_mech_list(uint_t * countp,int kmflag)1150Sstevel@tonic-gate crypto_get_mech_list(uint_t *countp, int kmflag)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate uint_t count = 0, me_tab_size, i, j;
1180Sstevel@tonic-gate kcf_ops_class_t cl;
1190Sstevel@tonic-gate kcf_mech_entry_t *me, *me_tab;
1200Sstevel@tonic-gate crypto_mech_name_t *mech_name_tab, *tmp_mech_name_tab;
1210Sstevel@tonic-gate char *mech_name, *hint_mech, *end;
1220Sstevel@tonic-gate kcf_soft_conf_entry_t *p;
1230Sstevel@tonic-gate size_t n;
1249505SBhargava.Yenduri@Sun.COM kcf_lock_withpad_t *mp;
1250Sstevel@tonic-gate
1260Sstevel@tonic-gate /*
1270Sstevel@tonic-gate * Count the maximum possible mechanisms that can come from the
1280Sstevel@tonic-gate * hint list.
1290Sstevel@tonic-gate */
1300Sstevel@tonic-gate mutex_enter(&soft_config_mutex);
1310Sstevel@tonic-gate p = soft_config_list;
1320Sstevel@tonic-gate while (p != NULL) {
1330Sstevel@tonic-gate count += p->ce_count;
1340Sstevel@tonic-gate p = p->ce_next;
1350Sstevel@tonic-gate }
1360Sstevel@tonic-gate mutex_exit(&soft_config_mutex);
1370Sstevel@tonic-gate
1380Sstevel@tonic-gate /* First let's count'em, for mem allocation */
1390Sstevel@tonic-gate for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) {
1400Sstevel@tonic-gate me_tab_size = kcf_mech_tabs_tab[cl].met_size;
1410Sstevel@tonic-gate me_tab = kcf_mech_tabs_tab[cl].met_tab;
1420Sstevel@tonic-gate for (i = 0; i < me_tab_size; i++) {
1430Sstevel@tonic-gate me = &me_tab[i];
1449505SBhargava.Yenduri@Sun.COM mp = &me_mutexes[CPU_SEQID];
1459505SBhargava.Yenduri@Sun.COM mutex_enter(&mp->kl_lock);
1460Sstevel@tonic-gate if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) {
1470Sstevel@tonic-gate ASSERT(me->me_hw_prov_chain != NULL);
1480Sstevel@tonic-gate count++;
1490Sstevel@tonic-gate }
1509505SBhargava.Yenduri@Sun.COM mutex_exit(&mp->kl_lock);
1510Sstevel@tonic-gate }
1520Sstevel@tonic-gate }
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate /*
1550Sstevel@tonic-gate * Allocate a buffer to hold the mechanisms from
1560Sstevel@tonic-gate * mech tabs and mechanisms from the hint list.
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate n = count * CRYPTO_MAX_MECH_NAME;
1590Sstevel@tonic-gate
1600Sstevel@tonic-gate again:
1610Sstevel@tonic-gate count = 0;
1620Sstevel@tonic-gate tmp_mech_name_tab = kmem_zalloc(n, kmflag);
1630Sstevel@tonic-gate if (tmp_mech_name_tab == NULL) {
1640Sstevel@tonic-gate *countp = 0;
1650Sstevel@tonic-gate return (NULL);
1660Sstevel@tonic-gate }
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate * Second round, fill in the table
1700Sstevel@tonic-gate */
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate mech_name = (char *)tmp_mech_name_tab;
1730Sstevel@tonic-gate end = mech_name + n;
1740Sstevel@tonic-gate
1750Sstevel@tonic-gate for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) {
1760Sstevel@tonic-gate me_tab_size = kcf_mech_tabs_tab[cl].met_size;
1770Sstevel@tonic-gate me_tab = kcf_mech_tabs_tab[cl].met_tab;
1780Sstevel@tonic-gate for (i = 0; i < me_tab_size; i++) {
1790Sstevel@tonic-gate me = &me_tab[i];
1809505SBhargava.Yenduri@Sun.COM mp = &me_mutexes[CPU_SEQID];
1819505SBhargava.Yenduri@Sun.COM mutex_enter(&mp->kl_lock);
1820Sstevel@tonic-gate if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) {
1830Sstevel@tonic-gate ASSERT(me->me_hw_prov_chain != NULL);
1840Sstevel@tonic-gate if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) {
1859505SBhargava.Yenduri@Sun.COM mutex_exit(&mp->kl_lock);
1860Sstevel@tonic-gate kmem_free(tmp_mech_name_tab, n);
1870Sstevel@tonic-gate n = n << 1;
1880Sstevel@tonic-gate goto again;
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate (void) strncpy(mech_name, me->me_name,
1910Sstevel@tonic-gate CRYPTO_MAX_MECH_NAME);
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate mech_name += CRYPTO_MAX_MECH_NAME;
1940Sstevel@tonic-gate count++;
1950Sstevel@tonic-gate }
1969505SBhargava.Yenduri@Sun.COM mutex_exit(&mp->kl_lock);
1970Sstevel@tonic-gate }
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate
2000Sstevel@tonic-gate /*
2010Sstevel@tonic-gate * Search tmp_mech_name_tab for each mechanism in the hint list. We
2020Sstevel@tonic-gate * have to add any new mechanisms found in the hint list. Note that we
2030Sstevel@tonic-gate * should not modload the providers here as it will be too early. It
2040Sstevel@tonic-gate * may be the case that the caller never uses a provider.
2050Sstevel@tonic-gate */
2060Sstevel@tonic-gate mutex_enter(&soft_config_mutex);
2070Sstevel@tonic-gate p = soft_config_list;
2080Sstevel@tonic-gate while (p != NULL) {
2090Sstevel@tonic-gate for (i = 0; i < p->ce_count; i++) {
2100Sstevel@tonic-gate hint_mech = p->ce_mechs[i];
2110Sstevel@tonic-gate
2120Sstevel@tonic-gate /* Do not consider the mechanism if it is disabled. */
2130Sstevel@tonic-gate if (is_mech_disabled_byname(CRYPTO_SW_PROVIDER,
2140Sstevel@tonic-gate p->ce_name, 0, hint_mech))
2150Sstevel@tonic-gate continue;
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate /*
2180Sstevel@tonic-gate * There may be duplicate mechanisms in the hint list.
2190Sstevel@tonic-gate * So, we need to search all the entries that have been
2200Sstevel@tonic-gate * added so far. That number would be count.
2210Sstevel@tonic-gate */
2220Sstevel@tonic-gate for (j = 0; j < count; j++) {
2230Sstevel@tonic-gate if (strcmp(hint_mech,
2240Sstevel@tonic-gate tmp_mech_name_tab[j]) == 0)
2250Sstevel@tonic-gate break;
2260Sstevel@tonic-gate }
2270Sstevel@tonic-gate
2280Sstevel@tonic-gate if (j == count) { /* This is a new one. Add it. */
2290Sstevel@tonic-gate ASSERT((char *)&tmp_mech_name_tab[count] ==
2300Sstevel@tonic-gate mech_name);
2310Sstevel@tonic-gate if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) {
2320Sstevel@tonic-gate mutex_exit(&soft_config_mutex);
2330Sstevel@tonic-gate kmem_free(tmp_mech_name_tab, n);
2340Sstevel@tonic-gate n = n << 1;
2350Sstevel@tonic-gate goto again;
2360Sstevel@tonic-gate }
2370Sstevel@tonic-gate (void) strncpy(tmp_mech_name_tab[count],
2380Sstevel@tonic-gate hint_mech, CRYPTO_MAX_MECH_NAME);
2390Sstevel@tonic-gate mech_name += CRYPTO_MAX_MECH_NAME;
2400Sstevel@tonic-gate count++;
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate }
2430Sstevel@tonic-gate p = p->ce_next;
2440Sstevel@tonic-gate }
2450Sstevel@tonic-gate mutex_exit(&soft_config_mutex);
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate /*
2480Sstevel@tonic-gate * Check if we have consumed all of the space. We are done if
2490Sstevel@tonic-gate * this is the case.
2500Sstevel@tonic-gate */
2510Sstevel@tonic-gate ASSERT(mech_name <= end);
2520Sstevel@tonic-gate if (mech_name == end) {
2530Sstevel@tonic-gate mech_name_tab = tmp_mech_name_tab;
2540Sstevel@tonic-gate goto done;
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate /*
2580Sstevel@tonic-gate * Allocate a buffer of the right size now that we have the
2590Sstevel@tonic-gate * correct count.
2600Sstevel@tonic-gate */
2610Sstevel@tonic-gate mech_name_tab = kmem_zalloc(count * CRYPTO_MAX_MECH_NAME, kmflag);
2620Sstevel@tonic-gate if (mech_name_tab == NULL) {
2630Sstevel@tonic-gate kmem_free(tmp_mech_name_tab, n);
2640Sstevel@tonic-gate *countp = 0;
2650Sstevel@tonic-gate return (NULL);
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate bcopy(tmp_mech_name_tab, mech_name_tab, count * CRYPTO_MAX_MECH_NAME);
2690Sstevel@tonic-gate kmem_free(tmp_mech_name_tab, n);
2700Sstevel@tonic-gate
2710Sstevel@tonic-gate done:
2720Sstevel@tonic-gate *countp = count;
2730Sstevel@tonic-gate return (mech_name_tab);
2740Sstevel@tonic-gate }
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate * crypto_free_mech_list()
2780Sstevel@tonic-gate *
2790Sstevel@tonic-gate * Arguments:
2800Sstevel@tonic-gate * . mech_names: An array of crypto_mech_name_t previously allocated by
2810Sstevel@tonic-gate * crypto_get_mech_list.
2820Sstevel@tonic-gate * . count: the number of mech names in mech_names
2830Sstevel@tonic-gate *
2840Sstevel@tonic-gate * Description:
2850Sstevel@tonic-gate * Frees the the mech_names array.
2860Sstevel@tonic-gate *
2870Sstevel@tonic-gate * Context:
2880Sstevel@tonic-gate * Process and interruption.
2890Sstevel@tonic-gate */
2900Sstevel@tonic-gate void
crypto_free_mech_list(crypto_mech_name_t * mech_names,uint_t count)2910Sstevel@tonic-gate crypto_free_mech_list(crypto_mech_name_t *mech_names, uint_t count)
2920Sstevel@tonic-gate {
2930Sstevel@tonic-gate if ((mech_names != NULL) && (count > 0))
2940Sstevel@tonic-gate kmem_free(mech_names, count * CRYPTO_MAX_MECH_NAME);
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate /*
2980Sstevel@tonic-gate * crypto_notify_events()
2990Sstevel@tonic-gate *
3000Sstevel@tonic-gate * Arguments:
3010Sstevel@tonic-gate * . nf: Callback function to invoke when event occurs.
3020Sstevel@tonic-gate * . event_mask: Mask of events.
3030Sstevel@tonic-gate *
3040Sstevel@tonic-gate * Description:
3050Sstevel@tonic-gate * Allocates a new element and inserts it in to the notification
3060Sstevel@tonic-gate * list.
3070Sstevel@tonic-gate *
3080Sstevel@tonic-gate * Context:
3090Sstevel@tonic-gate * Process context.
3100Sstevel@tonic-gate *
3110Sstevel@tonic-gate * Returns:
3120Sstevel@tonic-gate * A handle is returned if the client is put on the notification list.
3130Sstevel@tonic-gate * NULL is returned otherwise.
3140Sstevel@tonic-gate */
3150Sstevel@tonic-gate crypto_notify_handle_t
crypto_notify_events(crypto_notify_callback_t nf,uint32_t event_mask)3160Sstevel@tonic-gate crypto_notify_events(crypto_notify_callback_t nf, uint32_t event_mask)
3170Sstevel@tonic-gate {
3180Sstevel@tonic-gate kcf_ntfy_elem_t *nep;
3190Sstevel@tonic-gate crypto_notify_handle_t hndl;
3200Sstevel@tonic-gate
3212800Skrishna /* Check the input */
3222800Skrishna if (nf == NULL || !(event_mask & (CRYPTO_EVENT_MECHS_CHANGED |
3232800Skrishna CRYPTO_EVENT_PROVIDER_REGISTERED |
3242800Skrishna CRYPTO_EVENT_PROVIDER_UNREGISTERED))) {
3250Sstevel@tonic-gate return (NULL);
3260Sstevel@tonic-gate }
3270Sstevel@tonic-gate
3280Sstevel@tonic-gate nep = kmem_zalloc(sizeof (kcf_ntfy_elem_t), KM_SLEEP);
3290Sstevel@tonic-gate mutex_init(&nep->kn_lock, NULL, MUTEX_DEFAULT, NULL);
3300Sstevel@tonic-gate cv_init(&nep->kn_cv, NULL, CV_DEFAULT, NULL);
3310Sstevel@tonic-gate nep->kn_state = NTFY_WAITING;
3320Sstevel@tonic-gate nep->kn_func = nf;
3330Sstevel@tonic-gate nep->kn_event_mask = event_mask;
3340Sstevel@tonic-gate
3350Sstevel@tonic-gate mutex_enter(&ntfy_list_lock);
3360Sstevel@tonic-gate if (ntfy_list_head == NULL) {
3370Sstevel@tonic-gate ntfy_list_head = ntfy_list_tail = nep;
3380Sstevel@tonic-gate } else {
3390Sstevel@tonic-gate ntfy_list_tail->kn_next = nep;
3400Sstevel@tonic-gate nep->kn_prev = ntfy_list_tail;
3410Sstevel@tonic-gate ntfy_list_tail = nep;
3420Sstevel@tonic-gate }
3430Sstevel@tonic-gate
3440Sstevel@tonic-gate hndl = (crypto_notify_handle_t)nep;
3450Sstevel@tonic-gate mutex_exit(&ntfy_list_lock);
3460Sstevel@tonic-gate
3470Sstevel@tonic-gate return (hndl);
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate /*
3510Sstevel@tonic-gate * crypto_unnotify_events()
3520Sstevel@tonic-gate *
3530Sstevel@tonic-gate * Arguments:
3540Sstevel@tonic-gate * . hndl - Handle returned from an earlier crypto_notify_events().
3550Sstevel@tonic-gate *
3560Sstevel@tonic-gate * Description:
3570Sstevel@tonic-gate * Removes the element specified by hndl from the notification list.
3580Sstevel@tonic-gate * We wait for the notification routine to complete, if the routine
3590Sstevel@tonic-gate * is currently being called. We also free the element.
3600Sstevel@tonic-gate *
3610Sstevel@tonic-gate * Context:
3620Sstevel@tonic-gate * Process context.
3630Sstevel@tonic-gate */
3640Sstevel@tonic-gate void
crypto_unnotify_events(crypto_notify_handle_t hndl)3650Sstevel@tonic-gate crypto_unnotify_events(crypto_notify_handle_t hndl)
3660Sstevel@tonic-gate {
3670Sstevel@tonic-gate kcf_ntfy_elem_t *nep = (kcf_ntfy_elem_t *)hndl;
3680Sstevel@tonic-gate
3690Sstevel@tonic-gate if (hndl == NULL)
3700Sstevel@tonic-gate return;
3710Sstevel@tonic-gate
3720Sstevel@tonic-gate retry:
3730Sstevel@tonic-gate mutex_enter(&ntfy_list_lock);
3740Sstevel@tonic-gate mutex_enter(&nep->kn_lock);
3750Sstevel@tonic-gate
3760Sstevel@tonic-gate if (nep->kn_state == NTFY_WAITING) {
3770Sstevel@tonic-gate kcf_ntfy_elem_t *nextp = nep->kn_next;
3780Sstevel@tonic-gate kcf_ntfy_elem_t *prevp = nep->kn_prev;
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate if (nextp != NULL)
3810Sstevel@tonic-gate nextp->kn_prev = prevp;
3820Sstevel@tonic-gate else
3830Sstevel@tonic-gate ntfy_list_tail = prevp;
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate if (prevp != NULL)
3860Sstevel@tonic-gate prevp->kn_next = nextp;
3870Sstevel@tonic-gate else
3880Sstevel@tonic-gate ntfy_list_head = nextp;
3890Sstevel@tonic-gate } else {
3900Sstevel@tonic-gate ASSERT(nep->kn_state == NTFY_RUNNING);
3910Sstevel@tonic-gate
3920Sstevel@tonic-gate /*
3930Sstevel@tonic-gate * We have to drop this lock as the client might call
3940Sstevel@tonic-gate * crypto_notify_events() in the callback routine resulting
3950Sstevel@tonic-gate * in a deadlock.
3960Sstevel@tonic-gate */
3970Sstevel@tonic-gate mutex_exit(&ntfy_list_lock);
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate /*
4000Sstevel@tonic-gate * Another thread is working on this element. We will wait
4010Sstevel@tonic-gate * for that thread to signal us when done. No other thread
4020Sstevel@tonic-gate * will free this element. So, we can be sure it stays valid
4030Sstevel@tonic-gate * after the wait.
4040Sstevel@tonic-gate */
4050Sstevel@tonic-gate while (nep->kn_state == NTFY_RUNNING)
4060Sstevel@tonic-gate cv_wait(&nep->kn_cv, &nep->kn_lock);
4070Sstevel@tonic-gate mutex_exit(&nep->kn_lock);
4080Sstevel@tonic-gate
4090Sstevel@tonic-gate /*
4100Sstevel@tonic-gate * We have to remove the element from the notification list.
4110Sstevel@tonic-gate * So, start over and do the work (acquire locks etc.). This is
4120Sstevel@tonic-gate * safe (i.e. We won't be in this routine forever) as the
4132800Skrishna * events do not happen frequently. We have to revisit this
4142800Skrishna * code if we add a new event that happens often.
4150Sstevel@tonic-gate */
4160Sstevel@tonic-gate goto retry;
4170Sstevel@tonic-gate }
4180Sstevel@tonic-gate
4190Sstevel@tonic-gate mutex_exit(&nep->kn_lock);
4200Sstevel@tonic-gate
4210Sstevel@tonic-gate /* Free the element */
4220Sstevel@tonic-gate mutex_destroy(&nep->kn_lock);
4230Sstevel@tonic-gate cv_destroy(&nep->kn_cv);
4240Sstevel@tonic-gate kmem_free(nep, sizeof (kcf_ntfy_elem_t));
4250Sstevel@tonic-gate
4260Sstevel@tonic-gate mutex_exit(&ntfy_list_lock);
4270Sstevel@tonic-gate }
4280Sstevel@tonic-gate
4290Sstevel@tonic-gate /*
4300Sstevel@tonic-gate * We walk the notification list and do the callbacks.
4310Sstevel@tonic-gate */
4320Sstevel@tonic-gate void
kcf_walk_ntfylist(uint32_t event,void * event_arg)4330Sstevel@tonic-gate kcf_walk_ntfylist(uint32_t event, void *event_arg)
4340Sstevel@tonic-gate {
4350Sstevel@tonic-gate kcf_ntfy_elem_t *nep;
4360Sstevel@tonic-gate int nelem = 0;
4370Sstevel@tonic-gate
4380Sstevel@tonic-gate mutex_enter(&ntfy_list_lock);
4390Sstevel@tonic-gate
4400Sstevel@tonic-gate /*
4410Sstevel@tonic-gate * Count how many clients are on the notification list. We need
4420Sstevel@tonic-gate * this count to ensure that clients which joined the list after we
4430Sstevel@tonic-gate * have started this walk, are not wrongly notified.
4440Sstevel@tonic-gate */
4450Sstevel@tonic-gate for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next)
4460Sstevel@tonic-gate nelem++;
4470Sstevel@tonic-gate
4480Sstevel@tonic-gate for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) {
4490Sstevel@tonic-gate nelem--;
4500Sstevel@tonic-gate
4510Sstevel@tonic-gate /*
4520Sstevel@tonic-gate * Check if this client is interested in the
4530Sstevel@tonic-gate * event.
4540Sstevel@tonic-gate */
4550Sstevel@tonic-gate if (!(nep->kn_event_mask & event))
4560Sstevel@tonic-gate continue;
4570Sstevel@tonic-gate
4580Sstevel@tonic-gate mutex_enter(&nep->kn_lock);
4590Sstevel@tonic-gate nep->kn_state = NTFY_RUNNING;
4600Sstevel@tonic-gate mutex_exit(&nep->kn_lock);
4610Sstevel@tonic-gate mutex_exit(&ntfy_list_lock);
4620Sstevel@tonic-gate
4630Sstevel@tonic-gate /*
4640Sstevel@tonic-gate * We invoke the callback routine with no locks held. Another
4650Sstevel@tonic-gate * client could have joined the list meanwhile. This is fine
4660Sstevel@tonic-gate * as we maintain nelem as stated above. The NULL check in the
4670Sstevel@tonic-gate * for loop guards against shrinkage. Also, any callers of
4680Sstevel@tonic-gate * crypto_unnotify_events() at this point cv_wait till kn_state
4690Sstevel@tonic-gate * changes to NTFY_WAITING. Hence, nep is assured to be valid.
4700Sstevel@tonic-gate */
4710Sstevel@tonic-gate (*nep->kn_func)(event, event_arg);
4720Sstevel@tonic-gate
4730Sstevel@tonic-gate mutex_enter(&nep->kn_lock);
4740Sstevel@tonic-gate nep->kn_state = NTFY_WAITING;
4750Sstevel@tonic-gate cv_broadcast(&nep->kn_cv);
4760Sstevel@tonic-gate mutex_exit(&nep->kn_lock);
4770Sstevel@tonic-gate
4780Sstevel@tonic-gate mutex_enter(&ntfy_list_lock);
4790Sstevel@tonic-gate }
4800Sstevel@tonic-gate
4810Sstevel@tonic-gate mutex_exit(&ntfy_list_lock);
4820Sstevel@tonic-gate }
4830Sstevel@tonic-gate
4840Sstevel@tonic-gate /*
4850Sstevel@tonic-gate * crypto_key_check()
4860Sstevel@tonic-gate *
4870Sstevel@tonic-gate * Arguments:
4880Sstevel@tonic-gate * . mech: the mechanism to check the key with.
4890Sstevel@tonic-gate * . key: the key to check for validity and weakness.
4900Sstevel@tonic-gate *
4910Sstevel@tonic-gate * Description:
4920Sstevel@tonic-gate * Checks the validity and strength of the key for the mechanism.
4930Sstevel@tonic-gate * CRYPTO_KEY_REFERENCE is not supported for this routine.
4940Sstevel@tonic-gate * If more than one provider is capable of key checking for the mechanism,
4950Sstevel@tonic-gate * then run the key through them all.
4960Sstevel@tonic-gate * A conservative approach is adopted here: New weak keys may be
4970Sstevel@tonic-gate * discovered with more recent providers. If at least one provider is
4980Sstevel@tonic-gate * not happy with a key, then it is no good.
4990Sstevel@tonic-gate *
5000Sstevel@tonic-gate * Context:
5010Sstevel@tonic-gate * Process and interruption.
5020Sstevel@tonic-gate */
5030Sstevel@tonic-gate int
crypto_key_check(crypto_mechanism_t * mech,crypto_key_t * key)5040Sstevel@tonic-gate crypto_key_check(crypto_mechanism_t *mech, crypto_key_t *key)
5050Sstevel@tonic-gate {
5060Sstevel@tonic-gate int error;
5070Sstevel@tonic-gate kcf_mech_entry_t *me;
5080Sstevel@tonic-gate kcf_provider_desc_t *pd;
5090Sstevel@tonic-gate kcf_prov_mech_desc_t *prov_chain;
5109505SBhargava.Yenduri@Sun.COM kcf_lock_withpad_t *mp;
5110Sstevel@tonic-gate
5120Sstevel@tonic-gate /* when mech is a valid mechanism, me will be its mech_entry */
5130Sstevel@tonic-gate if ((mech == NULL) || (key == NULL) ||
5140Sstevel@tonic-gate (key->ck_format == CRYPTO_KEY_REFERENCE))
5150Sstevel@tonic-gate return (CRYPTO_ARGUMENTS_BAD);
5160Sstevel@tonic-gate
5170Sstevel@tonic-gate if ((error = kcf_get_mech_entry(mech->cm_type, &me)) != KCF_SUCCESS) {
5180Sstevel@tonic-gate /* error is one of the KCF_INVALID_MECH_XXX's */
5190Sstevel@tonic-gate return (CRYPTO_MECHANISM_INVALID);
5200Sstevel@tonic-gate }
5210Sstevel@tonic-gate
5229505SBhargava.Yenduri@Sun.COM mp = &me_mutexes[CPU_SEQID];
5239505SBhargava.Yenduri@Sun.COM mutex_enter(&mp->kl_lock);
5240Sstevel@tonic-gate
5250Sstevel@tonic-gate /* First let the software provider check this key */
5260Sstevel@tonic-gate if (me->me_sw_prov != NULL) {
5270Sstevel@tonic-gate pd = me->me_sw_prov->pm_prov_desc;
5280Sstevel@tonic-gate KCF_PROV_REFHOLD(pd);
5290Sstevel@tonic-gate
5300Sstevel@tonic-gate if ((KCF_PROV_KEY_OPS(pd) != NULL) &&
5310Sstevel@tonic-gate (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) {
5320Sstevel@tonic-gate crypto_mechanism_t lmech;
5330Sstevel@tonic-gate
5349505SBhargava.Yenduri@Sun.COM mutex_exit(&mp->kl_lock);
5350Sstevel@tonic-gate lmech = *mech;
5360Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
5370Sstevel@tonic-gate error = KCF_PROV_KEY_CHECK(pd, &lmech, key);
5380Sstevel@tonic-gate
5390Sstevel@tonic-gate if (error != CRYPTO_SUCCESS) {
5400Sstevel@tonic-gate KCF_PROV_REFRELE(pd);
5410Sstevel@tonic-gate return (error);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate
5449505SBhargava.Yenduri@Sun.COM mutex_enter(&mp->kl_lock);
5450Sstevel@tonic-gate }
5460Sstevel@tonic-gate KCF_PROV_REFRELE(pd);
5470Sstevel@tonic-gate }
5480Sstevel@tonic-gate
5490Sstevel@tonic-gate prov_chain = me->me_hw_prov_chain;
5500Sstevel@tonic-gate while (prov_chain != NULL) {
5510Sstevel@tonic-gate pd = prov_chain->pm_prov_desc;
5520Sstevel@tonic-gate KCF_PROV_REFHOLD(pd);
5530Sstevel@tonic-gate
5540Sstevel@tonic-gate if ((KCF_PROV_KEY_OPS(pd) != NULL) &&
5550Sstevel@tonic-gate (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) {
5560Sstevel@tonic-gate crypto_mechanism_t lmech;
5570Sstevel@tonic-gate
5589505SBhargava.Yenduri@Sun.COM mutex_exit(&mp->kl_lock);
5590Sstevel@tonic-gate lmech = *mech;
5600Sstevel@tonic-gate KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd,
5610Sstevel@tonic-gate &lmech);
5620Sstevel@tonic-gate error = KCF_PROV_KEY_CHECK(pd, &lmech, key);
5630Sstevel@tonic-gate
5640Sstevel@tonic-gate if (error != CRYPTO_SUCCESS) {
5650Sstevel@tonic-gate KCF_PROV_REFRELE(pd);
5660Sstevel@tonic-gate return (error);
5670Sstevel@tonic-gate }
5689505SBhargava.Yenduri@Sun.COM mutex_enter(&mp->kl_lock);
5690Sstevel@tonic-gate }
5700Sstevel@tonic-gate KCF_PROV_REFRELE(pd);
5710Sstevel@tonic-gate prov_chain = prov_chain->pm_next;
5720Sstevel@tonic-gate }
5730Sstevel@tonic-gate
5749505SBhargava.Yenduri@Sun.COM mutex_exit(&mp->kl_lock);
5750Sstevel@tonic-gate
5760Sstevel@tonic-gate /* All are happy with this key */
5770Sstevel@tonic-gate return (CRYPTO_SUCCESS);
5780Sstevel@tonic-gate }
5790Sstevel@tonic-gate
580904Smcpowers int
crypto_key_check_prov(crypto_provider_t provider,crypto_mechanism_t * mech,crypto_key_t * key)581904Smcpowers crypto_key_check_prov(crypto_provider_t provider, crypto_mechanism_t *mech,
582904Smcpowers crypto_key_t *key)
583904Smcpowers {
584904Smcpowers kcf_provider_desc_t *pd = provider;
585904Smcpowers kcf_provider_desc_t *real_provider = pd;
586904Smcpowers crypto_mechanism_t lmech;
587904Smcpowers int rv;
588904Smcpowers
589904Smcpowers ASSERT(KCF_PROV_REFHELD(pd));
590904Smcpowers
591904Smcpowers if ((mech == NULL) || (key == NULL) ||
592904Smcpowers (key->ck_format == CRYPTO_KEY_REFERENCE))
593904Smcpowers return (CRYPTO_ARGUMENTS_BAD);
594904Smcpowers
5951808Smcpowers /* no logical providers currently support the key check */
596904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
5971808Smcpowers return (CRYPTO_NOT_SUPPORTED);
598904Smcpowers }
599904Smcpowers
600904Smcpowers lmech = *mech;
601904Smcpowers KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
602904Smcpowers rv = KCF_PROV_KEY_CHECK(real_provider, &lmech, key);
603904Smcpowers if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
604904Smcpowers KCF_PROV_REFRELE(real_provider);
605904Smcpowers
606904Smcpowers return (rv);
607904Smcpowers }
608904Smcpowers
6090Sstevel@tonic-gate /*
6100Sstevel@tonic-gate * Initialize the specified crypto_mechanism_info_t structure for
6110Sstevel@tonic-gate * the specified mechanism provider descriptor. Used by
6120Sstevel@tonic-gate * crypto_get_all_mech_info().
6130Sstevel@tonic-gate */
6140Sstevel@tonic-gate static void
init_mechanism_info(crypto_mechanism_info_t * mech_info,kcf_prov_mech_desc_t * pmd)6150Sstevel@tonic-gate init_mechanism_info(crypto_mechanism_info_t *mech_info,
6160Sstevel@tonic-gate kcf_prov_mech_desc_t *pmd)
6170Sstevel@tonic-gate {
6180Sstevel@tonic-gate crypto_func_group_t fg = pmd->pm_mech_info.cm_func_group_mask;
6190Sstevel@tonic-gate
6200Sstevel@tonic-gate /* min/max key sizes */
6213708Skrishna mech_info->mi_keysize_unit = pmd->pm_mech_info.cm_mech_flags &
6223708Skrishna (CRYPTO_KEYSIZE_UNIT_IN_BITS | CRYPTO_KEYSIZE_UNIT_IN_BYTES);
6230Sstevel@tonic-gate mech_info->mi_min_key_size =
6240Sstevel@tonic-gate (size_t)pmd->pm_mech_info.cm_min_key_length;
6250Sstevel@tonic-gate mech_info->mi_max_key_size =
6260Sstevel@tonic-gate (size_t)pmd->pm_mech_info.cm_max_key_length;
6270Sstevel@tonic-gate
6280Sstevel@tonic-gate /* usage flag */
6290Sstevel@tonic-gate mech_info->mi_usage = 0;
6300Sstevel@tonic-gate if (fg & (CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC))
6310Sstevel@tonic-gate mech_info->mi_usage |= CRYPTO_MECH_USAGE_ENCRYPT;
6320Sstevel@tonic-gate if (fg & (CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC))
6330Sstevel@tonic-gate mech_info->mi_usage |= CRYPTO_MECH_USAGE_DECRYPT;
6340Sstevel@tonic-gate if (fg & (CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC))
6350Sstevel@tonic-gate mech_info->mi_usage |= CRYPTO_MECH_USAGE_MAC;
6360Sstevel@tonic-gate }
6370Sstevel@tonic-gate
6380Sstevel@tonic-gate /*
6390Sstevel@tonic-gate * Return the mechanism info for the specified mechanism.
6400Sstevel@tonic-gate */
6410Sstevel@tonic-gate int
crypto_get_all_mech_info(crypto_mech_type_t mech_type,crypto_mechanism_info_t ** mech_infos,uint_t * num_mech_infos,int km_flag)6420Sstevel@tonic-gate crypto_get_all_mech_info(crypto_mech_type_t mech_type,
6430Sstevel@tonic-gate crypto_mechanism_info_t **mech_infos, uint_t *num_mech_infos,
6440Sstevel@tonic-gate int km_flag)
6450Sstevel@tonic-gate {
6460Sstevel@tonic-gate uint_t ninfos, cur_info;
6470Sstevel@tonic-gate kcf_mech_entry_t *me;
6480Sstevel@tonic-gate int rv;
6490Sstevel@tonic-gate kcf_prov_mech_desc_t *hwp;
6500Sstevel@tonic-gate crypto_mechanism_info_t *infos;
6510Sstevel@tonic-gate size_t infos_size;
6529505SBhargava.Yenduri@Sun.COM kcf_lock_withpad_t *mp;
6530Sstevel@tonic-gate
6540Sstevel@tonic-gate /* get to the mech entry corresponding to the specified mech type */
6550Sstevel@tonic-gate if ((rv = kcf_get_mech_entry(mech_type, &me)) != CRYPTO_SUCCESS) {
6560Sstevel@tonic-gate return (rv);
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate
6590Sstevel@tonic-gate /* compute the number of key size ranges to return */
6609505SBhargava.Yenduri@Sun.COM mp = &me_mutexes[CPU_SEQID];
6619505SBhargava.Yenduri@Sun.COM mutex_enter(&mp->kl_lock);
6620Sstevel@tonic-gate again:
6630Sstevel@tonic-gate ninfos = PROV_COUNT(me);
6649505SBhargava.Yenduri@Sun.COM mutex_exit(&mp->kl_lock);
6650Sstevel@tonic-gate
6660Sstevel@tonic-gate if (ninfos == 0) {
6670Sstevel@tonic-gate infos = NULL;
6680Sstevel@tonic-gate rv = CRYPTO_SUCCESS;
6690Sstevel@tonic-gate goto bail;
6700Sstevel@tonic-gate }
6710Sstevel@tonic-gate infos_size = ninfos * sizeof (crypto_mechanism_info_t);
6720Sstevel@tonic-gate infos = kmem_alloc(infos_size, km_flag);
6730Sstevel@tonic-gate if (infos == NULL) {
6740Sstevel@tonic-gate rv = CRYPTO_HOST_MEMORY;
6750Sstevel@tonic-gate goto bail;
6760Sstevel@tonic-gate }
6770Sstevel@tonic-gate
6789505SBhargava.Yenduri@Sun.COM mutex_enter(&mp->kl_lock);
6790Sstevel@tonic-gate if (ninfos != PROV_COUNT(me)) {
6800Sstevel@tonic-gate kmem_free(infos, infos_size);
6810Sstevel@tonic-gate goto again;
6820Sstevel@tonic-gate }
6830Sstevel@tonic-gate
6840Sstevel@tonic-gate /* populate array of crypto mechanism infos */
6850Sstevel@tonic-gate cur_info = 0;
6860Sstevel@tonic-gate
6870Sstevel@tonic-gate /* software provider, if present */
6880Sstevel@tonic-gate if (me->me_sw_prov != NULL)
6890Sstevel@tonic-gate init_mechanism_info(&infos[cur_info++], me->me_sw_prov);
6900Sstevel@tonic-gate
6910Sstevel@tonic-gate /* hardware providers */
6920Sstevel@tonic-gate for (hwp = me->me_hw_prov_chain; hwp != NULL; hwp = hwp->pm_next)
6930Sstevel@tonic-gate init_mechanism_info(&infos[cur_info++], hwp);
6940Sstevel@tonic-gate
6959505SBhargava.Yenduri@Sun.COM mutex_exit(&mp->kl_lock);
6960Sstevel@tonic-gate ASSERT(cur_info == ninfos);
6970Sstevel@tonic-gate bail:
6980Sstevel@tonic-gate *mech_infos = infos;
6990Sstevel@tonic-gate *num_mech_infos = ninfos;
7000Sstevel@tonic-gate return (rv);
7010Sstevel@tonic-gate }
702904Smcpowers
703904Smcpowers /*
7048313SDina.Nimeh@Sun.Com * Frees the array of mechanism infos previously allocated by
7058313SDina.Nimeh@Sun.Com * crypto_get_all_mech_info().
7068313SDina.Nimeh@Sun.Com */
7078313SDina.Nimeh@Sun.Com void
crypto_free_all_mech_info(crypto_mechanism_info_t * mech_infos,uint_t count)7088313SDina.Nimeh@Sun.Com crypto_free_all_mech_info(crypto_mechanism_info_t *mech_infos, uint_t count)
7098313SDina.Nimeh@Sun.Com {
7108313SDina.Nimeh@Sun.Com if ((mech_infos != NULL) && (count > 0))
7118313SDina.Nimeh@Sun.Com kmem_free(mech_infos, count * sizeof (crypto_mechanism_info_t));
7128313SDina.Nimeh@Sun.Com }
7138313SDina.Nimeh@Sun.Com
7148313SDina.Nimeh@Sun.Com /*
715904Smcpowers * memcmp_pad_max() is a specialized version of memcmp() which
716904Smcpowers * compares two pieces of data up to a maximum length. If the
717904Smcpowers * the two data match up the maximum length, they are considered
718904Smcpowers * matching. Trailing blanks do not cause the match to fail if
719904Smcpowers * one of the data is shorter.
720904Smcpowers *
721904Smcpowers * Examples of matches:
722904Smcpowers * "one" |
723904Smcpowers * "one " |
724904Smcpowers * ^maximum length
725904Smcpowers *
726904Smcpowers * "Number One | X" (X is beyond maximum length)
727904Smcpowers * "Number One " |
728904Smcpowers * ^maximum length
729904Smcpowers *
730904Smcpowers * Examples of mismatches:
731904Smcpowers * " one"
732904Smcpowers * "one"
733904Smcpowers *
734904Smcpowers * "Number One X|"
735904Smcpowers * "Number One |"
736904Smcpowers * ^maximum length
737904Smcpowers */
738904Smcpowers static int
memcmp_pad_max(void * d1,uint_t d1_len,void * d2,uint_t d2_len,uint_t max_sz)739904Smcpowers memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz)
740904Smcpowers {
741904Smcpowers uint_t len, extra_len;
742904Smcpowers char *marker;
743904Smcpowers
744904Smcpowers /* No point in comparing anything beyond max_sz */
745904Smcpowers if (d1_len > max_sz)
746904Smcpowers d1_len = max_sz;
747904Smcpowers if (d2_len > max_sz)
748904Smcpowers d2_len = max_sz;
749904Smcpowers
750904Smcpowers /* Find shorter of the two data. */
751904Smcpowers if (d1_len <= d2_len) {
752904Smcpowers len = d1_len;
753904Smcpowers extra_len = d2_len;
754904Smcpowers marker = d2;
755904Smcpowers } else { /* d1_len > d2_len */
756904Smcpowers len = d2_len;
757904Smcpowers extra_len = d1_len;
758904Smcpowers marker = d1;
759904Smcpowers }
760904Smcpowers
761904Smcpowers /* Have a match in the shortest length of data? */
762904Smcpowers if (memcmp(d1, d2, len) != 0)
763904Smcpowers /* CONSTCOND */
764904Smcpowers return (!0);
765904Smcpowers
766904Smcpowers /* If the rest of longer data is nulls or blanks, call it a match. */
767904Smcpowers while (len < extra_len)
768904Smcpowers if (!isspace(marker[len++]))
769904Smcpowers /* CONSTCOND */
770904Smcpowers return (!0);
771904Smcpowers return (0);
772904Smcpowers }
773904Smcpowers
774904Smcpowers /*
775904Smcpowers * Obtain ext info for specified provider and see if it matches.
776904Smcpowers */
777904Smcpowers static boolean_t
match_ext_info(kcf_provider_desc_t * pd,char * label,char * manuf,char * serial,crypto_provider_ext_info_t * ext_info)778904Smcpowers match_ext_info(kcf_provider_desc_t *pd, char *label, char *manuf, char *serial,
779904Smcpowers crypto_provider_ext_info_t *ext_info)
780904Smcpowers {
781904Smcpowers int rv;
782904Smcpowers
7832800Skrishna rv = crypto_get_provinfo(pd, ext_info);
7842800Skrishna ASSERT(rv != CRYPTO_NOT_SUPPORTED);
785904Smcpowers if (rv != CRYPTO_SUCCESS)
786904Smcpowers return (B_FALSE);
787904Smcpowers
788904Smcpowers if (memcmp_pad_max(ext_info->ei_label, CRYPTO_EXT_SIZE_LABEL,
789904Smcpowers label, strlen(label), CRYPTO_EXT_SIZE_LABEL))
790904Smcpowers return (B_FALSE);
791904Smcpowers
792904Smcpowers if (manuf != NULL) {
793904Smcpowers if (memcmp_pad_max(ext_info->ei_manufacturerID,
794904Smcpowers CRYPTO_EXT_SIZE_MANUF, manuf, strlen(manuf),
795904Smcpowers CRYPTO_EXT_SIZE_MANUF))
796904Smcpowers return (B_FALSE);
797904Smcpowers }
798904Smcpowers
799904Smcpowers if (serial != NULL) {
800904Smcpowers if (memcmp_pad_max(ext_info->ei_serial_number,
8012800Skrishna CRYPTO_EXT_SIZE_SERIAL, serial, strlen(serial),
802904Smcpowers CRYPTO_EXT_SIZE_SERIAL))
803904Smcpowers return (B_FALSE);
804904Smcpowers }
805904Smcpowers return (B_TRUE);
806904Smcpowers }
807904Smcpowers
808904Smcpowers /*
809904Smcpowers * Find a provider based on its label, manufacturer ID, and serial number.
810904Smcpowers */
811904Smcpowers crypto_provider_t
crypto_get_provider(char * label,char * manuf,char * serial)812904Smcpowers crypto_get_provider(char *label, char *manuf, char *serial)
813904Smcpowers {
814904Smcpowers kcf_provider_desc_t **provider_array, *pd;
815904Smcpowers crypto_provider_ext_info_t *ext_info;
816904Smcpowers uint_t count;
817904Smcpowers int i;
818904Smcpowers
819904Smcpowers /* manuf and serial are optional */
820904Smcpowers if (label == NULL)
821904Smcpowers return (NULL);
822904Smcpowers
823904Smcpowers if (kcf_get_slot_list(&count, &provider_array, B_FALSE)
824904Smcpowers != CRYPTO_SUCCESS)
825904Smcpowers return (NULL);
826904Smcpowers
827904Smcpowers if (count == 0)
828904Smcpowers return (NULL);
829904Smcpowers
830904Smcpowers ext_info = kmem_zalloc(sizeof (crypto_provider_ext_info_t), KM_SLEEP);
831904Smcpowers
832904Smcpowers for (i = 0; i < count; i++) {
833904Smcpowers pd = provider_array[i];
834904Smcpowers if (match_ext_info(pd, label, manuf, serial, ext_info)) {
835904Smcpowers KCF_PROV_REFHOLD(pd);
836904Smcpowers break;
837904Smcpowers }
838904Smcpowers }
839904Smcpowers if (i == count)
840904Smcpowers pd = NULL;
841904Smcpowers
842904Smcpowers kcf_free_provider_tab(count, provider_array);
843904Smcpowers kmem_free(ext_info, sizeof (crypto_provider_ext_info_t));
844904Smcpowers return (pd);
845904Smcpowers }
846904Smcpowers
8472800Skrishna /*
8482800Skrishna * Get the provider information given a provider handle. The caller
8492800Skrishna * needs to allocate the space for the argument, info.
8502800Skrishna */
8512800Skrishna int
crypto_get_provinfo(crypto_provider_t hndl,crypto_provider_ext_info_t * info)8522800Skrishna crypto_get_provinfo(crypto_provider_t hndl, crypto_provider_ext_info_t *info)
8532800Skrishna {
8542800Skrishna int rv;
8552800Skrishna kcf_req_params_t params;
8562800Skrishna kcf_provider_desc_t *pd;
8572800Skrishna kcf_provider_desc_t *real_provider;
8582800Skrishna
8592800Skrishna pd = (kcf_provider_desc_t *)hndl;
8602800Skrishna rv = kcf_get_hardware_provider_nomech(
8612800Skrishna CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info),
862*12304SValerie.Fenwick@Oracle.COM pd, &real_provider);
8632800Skrishna
8642800Skrishna if (rv == CRYPTO_SUCCESS && real_provider != NULL) {
8652800Skrishna ASSERT(real_provider == pd ||
8662800Skrishna pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
8672800Skrishna KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_EXTINFO,
8682800Skrishna 0, NULL, 0, NULL, 0, NULL, info, pd);
8692800Skrishna rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms,
8702800Skrishna B_FALSE);
8712800Skrishna KCF_PROV_REFRELE(real_provider);
8722800Skrishna }
8732800Skrishna
8742800Skrishna return (rv);
8752800Skrishna }
8762800Skrishna
877904Smcpowers void
crypto_release_provider(crypto_provider_t provider)878904Smcpowers crypto_release_provider(crypto_provider_t provider)
879904Smcpowers {
880904Smcpowers KCF_PROV_REFRELE((kcf_provider_desc_t *)provider);
881904Smcpowers }
882