xref: /titanic_50/usr/src/uts/common/crypto/api/kcf_miscapi.c (revision fa9e4066f08beec538e775443c5be79dd423fcab)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/sunddi.h>
31 #include <sys/disp.h>
32 #include <sys/modctl.h>
33 #include <sys/crypto/common.h>
34 #include <sys/crypto/api.h>
35 #include <sys/crypto/impl.h>
36 #include <sys/crypto/sched_impl.h>
37 
38 /* Miscellaneous exported entry points */
39 
40 /*
41  * All event subscribers are put on a list. kcf_notify_list_lock
42  * protects changes to this list.
43  *
44  * The following locking order is maintained in the code - The
45  * global kcf_notify_list_lock followed by the individual lock
46  * in a kcf_ntfy_elem structure (kn_lock).
47  */
48 kmutex_t		ntfy_list_lock;
49 kcondvar_t		ntfy_list_cv;   /* cv the service thread waits on */
50 static kcf_ntfy_elem_t *ntfy_list_head;
51 static kcf_ntfy_elem_t *ntfy_list_tail;
52 
53 /* count all the hardware and software providers */
54 #define	PROV_COUNT(me) \
55 	(((me)->me_sw_prov != NULL ? 1 : 0) + (me)->me_num_hwprov)
56 
57 /*
58  * crypto_mech2id()
59  *
60  * Arguments:
61  *	. mechname: A null-terminated string identifying the mechanism name.
62  *
63  * Description:
64  *	Walks the mechanisms tables, looking for an entry that matches the
65  *	mechname. Once it find it, it builds the 64-bit mech_type and returns
66  *	it.  If there are no hardware or software providers for the mechanism,
67  *	but there is an unloaded software provider, this routine will attempt
68  *	to load it.
69  *
70  * Context:
71  *	Process and interruption.
72  *
73  * Returns:
74  *	The unique mechanism identified by 'mechname', if found.
75  *	CRYPTO_MECH_INVALID otherwise.
76  */
77 crypto_mech_type_t
78 crypto_mech2id(char *mechname)
79 {
80 	return (crypto_mech2id_common(mechname, B_TRUE));
81 }
82 
83 /*
84  * crypto_get_mech_list()
85  *
86  * Arguments:
87  *	. countp: pointer to contain the number of mech names returned
88  *	. kmflag: memory allocation flag.
89  *
90  * Description:
91  *	Allocates an array of crypto_mech_name_t containing all the mechanisms
92  *	currently available on the system. Sets *countp with the number of
93  *	mechanism names returned.
94  *
95  *	We get a list of mech names which have a hardware provider by walking
96  *	all the mechanism tables. We merge them with mech names obtained from
97  *	the hint list. A mech name in the hint list is considered only if it
98  *	is not disabled for the provider. Note that the hint list contains only
99  *	software providers and the mech names supported by them.
100  *
101  * Context:
102  *	Process and interruption. kmflag should be KM_NOSLEEP when called
103  *	from an interruption context.
104  *
105  * Returns:
106  *	The array of the crypto_mech_t allocated.
107  *	NULL otherwise.
108  */
109 crypto_mech_name_t *
110 crypto_get_mech_list(uint_t *countp, int kmflag)
111 {
112 	uint_t count = 0, me_tab_size, i, j;
113 	kcf_ops_class_t cl;
114 	kcf_mech_entry_t *me, *me_tab;
115 	crypto_mech_name_t *mech_name_tab, *tmp_mech_name_tab;
116 	char *mech_name, *hint_mech, *end;
117 	kcf_soft_conf_entry_t *p;
118 	size_t n;
119 
120 	/*
121 	 * Count the maximum possible mechanisms that can come from the
122 	 * hint list.
123 	 */
124 	mutex_enter(&soft_config_mutex);
125 	p = soft_config_list;
126 	while (p != NULL) {
127 		count += p->ce_count;
128 		p = p->ce_next;
129 	}
130 	mutex_exit(&soft_config_mutex);
131 
132 	/* First let's count'em, for mem allocation */
133 	for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) {
134 		me_tab_size = kcf_mech_tabs_tab[cl].met_size;
135 		me_tab = kcf_mech_tabs_tab[cl].met_tab;
136 		for (i = 0; i < me_tab_size; i++) {
137 			me = &me_tab[i];
138 			mutex_enter(&(me->me_mutex));
139 			if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) {
140 				ASSERT(me->me_hw_prov_chain != NULL);
141 				count++;
142 			}
143 			mutex_exit(&(me->me_mutex));
144 		}
145 	}
146 
147 	/*
148 	 * Allocate a buffer to hold the mechanisms from
149 	 * mech tabs and mechanisms from the hint list.
150 	 */
151 	n = count * CRYPTO_MAX_MECH_NAME;
152 
153 again:
154 	count = 0;
155 	tmp_mech_name_tab = kmem_zalloc(n, kmflag);
156 	if (tmp_mech_name_tab == NULL) {
157 		*countp = 0;
158 		return (NULL);
159 	}
160 
161 	/*
162 	 * Second round, fill in the table
163 	 */
164 
165 	mech_name = (char *)tmp_mech_name_tab;
166 	end = mech_name + n;
167 
168 	for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) {
169 		me_tab_size = kcf_mech_tabs_tab[cl].met_size;
170 		me_tab = kcf_mech_tabs_tab[cl].met_tab;
171 		for (i = 0; i < me_tab_size; i++) {
172 			me = &me_tab[i];
173 			mutex_enter(&(me->me_mutex));
174 			if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) {
175 				ASSERT(me->me_hw_prov_chain != NULL);
176 				if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) {
177 					mutex_exit(&(me->me_mutex));
178 					kmem_free(tmp_mech_name_tab, n);
179 					n = n << 1;
180 					goto again;
181 				}
182 				(void) strncpy(mech_name, me->me_name,
183 				    CRYPTO_MAX_MECH_NAME);
184 
185 				mech_name += CRYPTO_MAX_MECH_NAME;
186 				count++;
187 			}
188 			mutex_exit(&(me->me_mutex));
189 		}
190 	}
191 
192 	/*
193 	 * Search tmp_mech_name_tab for each mechanism in the hint list. We
194 	 * have to add any new mechanisms found in the hint list. Note that we
195 	 * should not modload the providers here as it will be too early. It
196 	 * may be the case that the caller never uses a provider.
197 	 */
198 	mutex_enter(&soft_config_mutex);
199 	p = soft_config_list;
200 	while (p != NULL) {
201 		for (i = 0; i < p->ce_count; i++) {
202 			hint_mech = p->ce_mechs[i];
203 
204 			/* Do not consider the mechanism if it is disabled. */
205 			if (is_mech_disabled_byname(CRYPTO_SW_PROVIDER,
206 			    p->ce_name, 0, hint_mech))
207 				continue;
208 
209 			/*
210 			 * There may be duplicate mechanisms in the hint list.
211 			 * So, we need to search all the entries that have been
212 			 * added so far. That number would be count.
213 			 */
214 			for (j = 0; j < count; j++) {
215 				if (strcmp(hint_mech,
216 				    tmp_mech_name_tab[j]) == 0)
217 					break;
218 			}
219 
220 			if (j == count) {	/* This is a new one. Add it. */
221 				ASSERT((char *)&tmp_mech_name_tab[count] ==
222 				    mech_name);
223 				if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) {
224 					mutex_exit(&soft_config_mutex);
225 					kmem_free(tmp_mech_name_tab, n);
226 					n = n << 1;
227 					goto again;
228 				}
229 				(void) strncpy(tmp_mech_name_tab[count],
230 				    hint_mech, CRYPTO_MAX_MECH_NAME);
231 				mech_name += CRYPTO_MAX_MECH_NAME;
232 				count++;
233 			}
234 		}
235 		p = p->ce_next;
236 	}
237 	mutex_exit(&soft_config_mutex);
238 
239 	/*
240 	 * Check if we have consumed all of the space. We are done if
241 	 * this is the case.
242 	 */
243 	ASSERT(mech_name <= end);
244 	if (mech_name == end) {
245 		mech_name_tab = tmp_mech_name_tab;
246 		goto done;
247 	}
248 
249 	/*
250 	 * Allocate a buffer of the right size now that we have the
251 	 * correct count.
252 	 */
253 	mech_name_tab = kmem_zalloc(count * CRYPTO_MAX_MECH_NAME, kmflag);
254 	if (mech_name_tab == NULL) {
255 		kmem_free(tmp_mech_name_tab, n);
256 		*countp = 0;
257 		return (NULL);
258 	}
259 
260 	bcopy(tmp_mech_name_tab, mech_name_tab, count * CRYPTO_MAX_MECH_NAME);
261 	kmem_free(tmp_mech_name_tab, n);
262 
263 done:
264 	*countp = count;
265 	return (mech_name_tab);
266 }
267 
268 /*
269  * crypto_free_mech_list()
270  *
271  * Arguments:
272  *	. mech_names: An array of crypto_mech_name_t previously allocated by
273  *	  crypto_get_mech_list.
274  *	. count: the number of mech names in mech_names
275  *
276  * Description:
277  *	Frees the the mech_names array.
278  *
279  * Context:
280  *	Process and interruption.
281  */
282 void
283 crypto_free_mech_list(crypto_mech_name_t *mech_names, uint_t count)
284 {
285 	if ((mech_names != NULL) && (count > 0))
286 		kmem_free(mech_names, count * CRYPTO_MAX_MECH_NAME);
287 }
288 
289 /*
290  * crypto_notify_events()
291  *
292  * Arguments:
293  *	. nf: Callback function to invoke when event occurs.
294  *	. event_mask: Mask of events.
295  *
296  * Description:
297  *	Allocates a new element and inserts it in to the notification
298  *	list.
299  *
300  * Context:
301  *	Process context.
302  *
303  * Returns:
304  *	A handle is returned if the client is put on the notification list.
305  *	NULL is returned otherwise.
306  */
307 crypto_notify_handle_t
308 crypto_notify_events(crypto_notify_callback_t nf, uint32_t event_mask)
309 {
310 	kcf_ntfy_elem_t *nep;
311 	crypto_notify_handle_t hndl;
312 
313 	/*
314 	 * The only valid value for event_mask is CRYPTO_EVENT_PROVIDERS_CHANGE.
315 	 */
316 	if (nf == NULL || !(event_mask & CRYPTO_EVENT_PROVIDERS_CHANGE)) {
317 		return (NULL);
318 	}
319 
320 	nep = kmem_zalloc(sizeof (kcf_ntfy_elem_t), KM_SLEEP);
321 	mutex_init(&nep->kn_lock, NULL, MUTEX_DEFAULT, NULL);
322 	cv_init(&nep->kn_cv, NULL, CV_DEFAULT, NULL);
323 	nep->kn_state = NTFY_WAITING;
324 	nep->kn_func = nf;
325 	nep->kn_event_mask = event_mask;
326 
327 	mutex_enter(&ntfy_list_lock);
328 	if (ntfy_list_head == NULL) {
329 		ntfy_list_head = ntfy_list_tail = nep;
330 	} else {
331 		ntfy_list_tail->kn_next = nep;
332 		nep->kn_prev = ntfy_list_tail;
333 		ntfy_list_tail = nep;
334 	}
335 
336 	hndl = (crypto_notify_handle_t)nep;
337 	mutex_exit(&ntfy_list_lock);
338 
339 	return (hndl);
340 }
341 
342 /*
343  * crypto_unnotify_events()
344  *
345  * Arguments:
346  *	. hndl - Handle returned from an earlier crypto_notify_events().
347  *
348  * Description:
349  *	Removes the element specified by hndl from the notification list.
350  *	We wait for the notification routine to complete, if the routine
351  *	is currently being called. We also free the element.
352  *
353  * Context:
354  *	Process context.
355  */
356 void
357 crypto_unnotify_events(crypto_notify_handle_t hndl)
358 {
359 	kcf_ntfy_elem_t *nep = (kcf_ntfy_elem_t *)hndl;
360 
361 	if (hndl == NULL)
362 		return;
363 
364 retry:
365 	mutex_enter(&ntfy_list_lock);
366 	mutex_enter(&nep->kn_lock);
367 
368 	if (nep->kn_state == NTFY_WAITING) {
369 		kcf_ntfy_elem_t *nextp = nep->kn_next;
370 		kcf_ntfy_elem_t *prevp = nep->kn_prev;
371 
372 		if (nextp != NULL)
373 			nextp->kn_prev = prevp;
374 		else
375 			ntfy_list_tail = prevp;
376 
377 		if (prevp != NULL)
378 			prevp->kn_next = nextp;
379 		else
380 			ntfy_list_head = nextp;
381 	} else {
382 		ASSERT(nep->kn_state == NTFY_RUNNING);
383 
384 		/*
385 		 * We have to drop this lock as the client might call
386 		 * crypto_notify_events() in the callback routine resulting
387 		 * in a deadlock.
388 		 */
389 		mutex_exit(&ntfy_list_lock);
390 
391 		/*
392 		 * Another thread is working on this element. We will wait
393 		 * for that thread to signal us when done. No other thread
394 		 * will free this element. So, we can be sure it stays valid
395 		 * after the wait.
396 		 */
397 		while (nep->kn_state == NTFY_RUNNING)
398 			cv_wait(&nep->kn_cv, &nep->kn_lock);
399 		mutex_exit(&nep->kn_lock);
400 
401 		/*
402 		 * We have to remove the element from the notification list.
403 		 * So, start over and do the work (acquire locks etc.). This is
404 		 * safe (i.e. We won't be in this routine forever) as the
405 		 * CRYPTO_EVENT_PROVIDERS_CHANGE event does not happen
406 		 * frequently. We have to revisit this code if we
407 		 * add a new event that happens often.
408 		 */
409 		goto retry;
410 	}
411 
412 	mutex_exit(&nep->kn_lock);
413 
414 	/* Free the element */
415 	mutex_destroy(&nep->kn_lock);
416 	cv_destroy(&nep->kn_cv);
417 	kmem_free(nep, sizeof (kcf_ntfy_elem_t));
418 
419 	mutex_exit(&ntfy_list_lock);
420 }
421 
422 /*
423  * This routine is called from crypto_register_provider() and
424  * crypto_unregister_provider() with the CRYPTO_EVENT_PROVIDERS_CHANGE event.
425  *
426  * We walk the notification list and do the callbacks.
427  */
428 void
429 kcf_walk_ntfylist(uint32_t event, void *event_arg)
430 {
431 	kcf_ntfy_elem_t *nep;
432 	int nelem = 0;
433 
434 	mutex_enter(&ntfy_list_lock);
435 
436 	/*
437 	 * Count how many clients are on the notification list. We need
438 	 * this count to ensure that clients which joined the list after we
439 	 * have started this walk, are not wrongly notified.
440 	 */
441 	for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next)
442 		nelem++;
443 
444 	for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) {
445 		nelem--;
446 
447 		/*
448 		 * Check if this client is interested in the
449 		 * event.
450 		 */
451 		if (!(nep->kn_event_mask & event))
452 			continue;
453 
454 		mutex_enter(&nep->kn_lock);
455 		nep->kn_state = NTFY_RUNNING;
456 		mutex_exit(&nep->kn_lock);
457 		mutex_exit(&ntfy_list_lock);
458 
459 		/*
460 		 * We invoke the callback routine with no locks held. Another
461 		 * client could have joined the list meanwhile. This is fine
462 		 * as we maintain nelem as stated above. The NULL check in the
463 		 * for loop guards against shrinkage. Also, any callers of
464 		 * crypto_unnotify_events() at this point cv_wait till kn_state
465 		 * changes to NTFY_WAITING. Hence, nep is assured to be valid.
466 		 */
467 		(*nep->kn_func)(event, event_arg);
468 
469 		mutex_enter(&nep->kn_lock);
470 		nep->kn_state = NTFY_WAITING;
471 		cv_broadcast(&nep->kn_cv);
472 		mutex_exit(&nep->kn_lock);
473 
474 		mutex_enter(&ntfy_list_lock);
475 	}
476 
477 	mutex_exit(&ntfy_list_lock);
478 }
479 
480 /*
481  * crypto_key_check()
482  *
483  * Arguments:
484  *	. mech: the mechanism to check the key with.
485  *	. key: the key to check for validity and weakness.
486  *
487  * Description:
488  *	Checks the validity and strength of the key for the mechanism.
489  *	CRYPTO_KEY_REFERENCE is not supported for this routine.
490  *	If more than one provider is capable of key checking for the mechanism,
491  *	then run the key through them all.
492  *	A conservative approach is adopted here: New weak keys may be
493  *	discovered with more recent providers. If at least one provider is
494  *	not happy with a key, then it is no good.
495  *
496  * Context:
497  *	Process and interruption.
498  */
499 int
500 crypto_key_check(crypto_mechanism_t *mech, crypto_key_t *key)
501 {
502 	int error;
503 	kcf_mech_entry_t *me;
504 	kcf_provider_desc_t *pd;
505 	kcf_prov_mech_desc_t *prov_chain;
506 
507 	/* when mech is a valid mechanism, me will be its mech_entry */
508 	if ((mech == NULL) || (key == NULL) ||
509 	    (key->ck_format == CRYPTO_KEY_REFERENCE))
510 		return (CRYPTO_ARGUMENTS_BAD);
511 
512 	if ((error = kcf_get_mech_entry(mech->cm_type, &me)) != KCF_SUCCESS) {
513 		/* error is one of the KCF_INVALID_MECH_XXX's */
514 		return (CRYPTO_MECHANISM_INVALID);
515 	}
516 
517 	mutex_enter(&me->me_mutex);
518 
519 	/* First let the software provider check this key */
520 	if (me->me_sw_prov != NULL) {
521 		pd = me->me_sw_prov->pm_prov_desc;
522 		KCF_PROV_REFHOLD(pd);
523 
524 		if ((KCF_PROV_KEY_OPS(pd) != NULL) &&
525 		    (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) {
526 			crypto_mechanism_t lmech;
527 
528 			mutex_exit(&me->me_mutex);
529 			lmech = *mech;
530 			KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
531 			error = KCF_PROV_KEY_CHECK(pd, &lmech, key);
532 
533 			if (error != CRYPTO_SUCCESS) {
534 				KCF_PROV_REFRELE(pd);
535 				return (error);
536 			}
537 
538 			mutex_enter(&me->me_mutex);
539 		}
540 		KCF_PROV_REFRELE(pd);
541 	}
542 
543 	prov_chain = me->me_hw_prov_chain;
544 	while (prov_chain != NULL) {
545 		pd = prov_chain->pm_prov_desc;
546 		KCF_PROV_REFHOLD(pd);
547 
548 		if ((KCF_PROV_KEY_OPS(pd) != NULL) &&
549 		    (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) {
550 			crypto_mechanism_t lmech;
551 
552 			mutex_exit(&me->me_mutex);
553 			lmech = *mech;
554 			KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd,
555 			    &lmech);
556 			error = KCF_PROV_KEY_CHECK(pd, &lmech, key);
557 
558 			if (error != CRYPTO_SUCCESS) {
559 				KCF_PROV_REFRELE(pd);
560 				return (error);
561 			}
562 			mutex_enter(&me->me_mutex);
563 		}
564 		KCF_PROV_REFRELE(pd);
565 		prov_chain = prov_chain->pm_next;
566 	}
567 
568 	mutex_exit(&me->me_mutex);
569 
570 	/* All are happy with this key */
571 	return (CRYPTO_SUCCESS);
572 }
573 
574 /*
575  * Initialize the specified crypto_mechanism_info_t structure for
576  * the specified mechanism provider descriptor. Used by
577  * crypto_get_all_mech_info().
578  */
579 static void
580 init_mechanism_info(crypto_mechanism_info_t *mech_info,
581     kcf_prov_mech_desc_t *pmd)
582 {
583 	crypto_func_group_t fg = pmd->pm_mech_info.cm_func_group_mask;
584 
585 	/* min/max key sizes */
586 	mech_info->mi_keysize_unit =
587 	    pmd->pm_mech_info.cm_keysize_unit;
588 	mech_info->mi_min_key_size =
589 	    (size_t)pmd->pm_mech_info.cm_min_key_length;
590 	mech_info->mi_max_key_size =
591 	    (size_t)pmd->pm_mech_info.cm_max_key_length;
592 
593 	/* usage flag */
594 	mech_info->mi_usage = 0;
595 	if (fg & (CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC))
596 		mech_info->mi_usage |= CRYPTO_MECH_USAGE_ENCRYPT;
597 	if (fg & (CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC))
598 		mech_info->mi_usage |= CRYPTO_MECH_USAGE_DECRYPT;
599 	if (fg & (CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC))
600 		mech_info->mi_usage |= CRYPTO_MECH_USAGE_MAC;
601 }
602 
603 /*
604  * Return the mechanism info for the specified mechanism.
605  */
606 int
607 crypto_get_all_mech_info(crypto_mech_type_t mech_type,
608     crypto_mechanism_info_t **mech_infos, uint_t *num_mech_infos,
609     int km_flag)
610 {
611 	uint_t ninfos, cur_info;
612 	kcf_mech_entry_t *me;
613 	int rv;
614 	kcf_prov_mech_desc_t *hwp;
615 	crypto_mechanism_info_t *infos;
616 	size_t infos_size;
617 
618 	/* get to the mech entry corresponding to the specified mech type */
619 	if ((rv = kcf_get_mech_entry(mech_type, &me)) != CRYPTO_SUCCESS) {
620 		return (rv);
621 	}
622 
623 	/* compute the number of key size ranges to return */
624 	mutex_enter(&me->me_mutex);
625 again:
626 	ninfos = PROV_COUNT(me);
627 	mutex_exit(&me->me_mutex);
628 
629 	if (ninfos == 0) {
630 		infos = NULL;
631 		rv = CRYPTO_SUCCESS;
632 		goto bail;
633 	}
634 	infos_size = ninfos * sizeof (crypto_mechanism_info_t);
635 	infos = kmem_alloc(infos_size, km_flag);
636 	if (infos == NULL) {
637 		rv = CRYPTO_HOST_MEMORY;
638 		goto bail;
639 	}
640 
641 	mutex_enter(&me->me_mutex);
642 	if (ninfos != PROV_COUNT(me)) {
643 		kmem_free(infos, infos_size);
644 		goto again;
645 	}
646 
647 	/* populate array of crypto mechanism infos */
648 	cur_info = 0;
649 
650 	/* software provider, if present */
651 	if (me->me_sw_prov != NULL)
652 		init_mechanism_info(&infos[cur_info++], me->me_sw_prov);
653 
654 	/* hardware providers */
655 	for (hwp = me->me_hw_prov_chain; hwp != NULL; hwp = hwp->pm_next)
656 		init_mechanism_info(&infos[cur_info++], hwp);
657 
658 	mutex_exit(&me->me_mutex);
659 	ASSERT(cur_info == ninfos);
660 bail:
661 	*mech_infos = infos;
662 	*num_mech_infos = ninfos;
663 	return (rv);
664 }
665