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 (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
23 */
24
25 #include <sys/types.h>
26 #include <sys/sunddi.h>
27 #include <sys/disp.h>
28 #include <sys/modctl.h>
29 #include <sys/sysmacros.h>
30 #include <sys/crypto/common.h>
31 #include <sys/crypto/api.h>
32 #include <sys/crypto/impl.h>
33 #include <sys/crypto/sched_impl.h>
34
35 #define isspace(ch) (((ch) == ' ') || ((ch) == '\r') || ((ch) == '\n') || \
36 ((ch) == '\t') || ((ch) == '\f'))
37
38 #define CRYPTO_OPS_OFFSET(f) offsetof(crypto_ops_t, co_##f)
39 #define CRYPTO_KEY_OFFSET(f) offsetof(crypto_key_ops_t, f)
40 #define CRYPTO_PROVIDER_OFFSET(f) \
41 offsetof(crypto_provider_management_ops_t, f)
42
43 /* Miscellaneous exported entry points */
44
45 /*
46 * All event subscribers are put on a list. kcf_notify_list_lock
47 * protects changes to this list.
48 *
49 * The following locking order is maintained in the code - The
50 * global kcf_notify_list_lock followed by the individual lock
51 * in a kcf_ntfy_elem structure (kn_lock).
52 */
53 kmutex_t ntfy_list_lock;
54 kcondvar_t ntfy_list_cv; /* cv the service thread waits on */
55 static kcf_ntfy_elem_t *ntfy_list_head;
56 static kcf_ntfy_elem_t *ntfy_list_tail;
57
58 /* count all the hardware and software providers */
59 #define PROV_COUNT(me) \
60 (((me)->me_sw_prov != NULL ? 1 : 0) + (me)->me_num_hwprov)
61
62 /*
63 * crypto_mech2id()
64 *
65 * Arguments:
66 * . mechname: A null-terminated string identifying the mechanism name.
67 *
68 * Description:
69 * Walks the mechanisms tables, looking for an entry that matches the
70 * mechname. Once it find it, it builds the 64-bit mech_type and returns
71 * it. If there are no hardware or software providers for the mechanism,
72 * but there is an unloaded software provider, this routine will attempt
73 * to load it.
74 *
75 * Context:
76 * Process and interruption.
77 *
78 * Returns:
79 * The unique mechanism identified by 'mechname', if found.
80 * CRYPTO_MECH_INVALID otherwise.
81 */
82 crypto_mech_type_t
crypto_mech2id(char * mechname)83 crypto_mech2id(char *mechname)
84 {
85 return (crypto_mech2id_common(mechname, B_TRUE));
86 }
87
88 /*
89 * crypto_get_mech_list()
90 *
91 * Arguments:
92 * . countp: pointer to contain the number of mech names returned
93 * . kmflag: memory allocation flag.
94 *
95 * Description:
96 * Allocates an array of crypto_mech_name_t containing all the mechanisms
97 * currently available on the system. Sets *countp with the number of
98 * mechanism names returned.
99 *
100 * We get a list of mech names which have a hardware provider by walking
101 * all the mechanism tables. We merge them with mech names obtained from
102 * the hint list. A mech name in the hint list is considered only if it
103 * is not disabled for the provider. Note that the hint list contains only
104 * software providers and the mech names supported by them.
105 *
106 * Context:
107 * Process and interruption. kmflag should be KM_NOSLEEP when called
108 * from an interruption context.
109 *
110 * Returns:
111 * The array of the crypto_mech_t allocated.
112 * NULL otherwise.
113 */
114 crypto_mech_name_t *
crypto_get_mech_list(uint_t * countp,int kmflag)115 crypto_get_mech_list(uint_t *countp, int kmflag)
116 {
117 uint_t count = 0, me_tab_size, i, j;
118 kcf_ops_class_t cl;
119 kcf_mech_entry_t *me, *me_tab;
120 crypto_mech_name_t *mech_name_tab, *tmp_mech_name_tab;
121 char *mech_name, *hint_mech, *end;
122 kcf_soft_conf_entry_t *p;
123 size_t n;
124 kcf_lock_withpad_t *mp;
125
126 /*
127 * Count the maximum possible mechanisms that can come from the
128 * hint list.
129 */
130 mutex_enter(&soft_config_mutex);
131 p = soft_config_list;
132 while (p != NULL) {
133 count += p->ce_count;
134 p = p->ce_next;
135 }
136 mutex_exit(&soft_config_mutex);
137
138 /* First let's count'em, for mem allocation */
139 for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) {
140 me_tab_size = kcf_mech_tabs_tab[cl].met_size;
141 me_tab = kcf_mech_tabs_tab[cl].met_tab;
142 for (i = 0; i < me_tab_size; i++) {
143 me = &me_tab[i];
144 mp = &me_mutexes[CPU_SEQID];
145 mutex_enter(&mp->kl_lock);
146 if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) {
147 ASSERT(me->me_hw_prov_chain != NULL);
148 count++;
149 }
150 mutex_exit(&mp->kl_lock);
151 }
152 }
153
154 /*
155 * Allocate a buffer to hold the mechanisms from
156 * mech tabs and mechanisms from the hint list.
157 */
158 n = count * CRYPTO_MAX_MECH_NAME;
159
160 again:
161 count = 0;
162 tmp_mech_name_tab = kmem_zalloc(n, kmflag);
163 if (tmp_mech_name_tab == NULL) {
164 *countp = 0;
165 return (NULL);
166 }
167
168 /*
169 * Second round, fill in the table
170 */
171
172 mech_name = (char *)tmp_mech_name_tab;
173 end = mech_name + n;
174
175 for (cl = KCF_FIRST_OPSCLASS; cl <= KCF_LAST_OPSCLASS; cl++) {
176 me_tab_size = kcf_mech_tabs_tab[cl].met_size;
177 me_tab = kcf_mech_tabs_tab[cl].met_tab;
178 for (i = 0; i < me_tab_size; i++) {
179 me = &me_tab[i];
180 mp = &me_mutexes[CPU_SEQID];
181 mutex_enter(&mp->kl_lock);
182 if ((me->me_name[0] != 0) && (me->me_num_hwprov >= 1)) {
183 ASSERT(me->me_hw_prov_chain != NULL);
184 if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) {
185 mutex_exit(&mp->kl_lock);
186 kmem_free(tmp_mech_name_tab, n);
187 n = n << 1;
188 goto again;
189 }
190 (void) strncpy(mech_name, me->me_name,
191 CRYPTO_MAX_MECH_NAME);
192
193 mech_name += CRYPTO_MAX_MECH_NAME;
194 count++;
195 }
196 mutex_exit(&mp->kl_lock);
197 }
198 }
199
200 /*
201 * Search tmp_mech_name_tab for each mechanism in the hint list. We
202 * have to add any new mechanisms found in the hint list. Note that we
203 * should not modload the providers here as it will be too early. It
204 * may be the case that the caller never uses a provider.
205 */
206 mutex_enter(&soft_config_mutex);
207 p = soft_config_list;
208 while (p != NULL) {
209 for (i = 0; i < p->ce_count; i++) {
210 hint_mech = p->ce_mechs[i];
211
212 /* Do not consider the mechanism if it is disabled. */
213 if (is_mech_disabled_byname(CRYPTO_SW_PROVIDER,
214 p->ce_name, 0, hint_mech))
215 continue;
216
217 /*
218 * There may be duplicate mechanisms in the hint list.
219 * So, we need to search all the entries that have been
220 * added so far. That number would be count.
221 */
222 for (j = 0; j < count; j++) {
223 if (strcmp(hint_mech,
224 tmp_mech_name_tab[j]) == 0)
225 break;
226 }
227
228 if (j == count) { /* This is a new one. Add it. */
229 ASSERT((char *)&tmp_mech_name_tab[count] ==
230 mech_name);
231 if ((mech_name + CRYPTO_MAX_MECH_NAME) > end) {
232 mutex_exit(&soft_config_mutex);
233 kmem_free(tmp_mech_name_tab, n);
234 n = n << 1;
235 goto again;
236 }
237 (void) strncpy(tmp_mech_name_tab[count],
238 hint_mech, CRYPTO_MAX_MECH_NAME);
239 mech_name += CRYPTO_MAX_MECH_NAME;
240 count++;
241 }
242 }
243 p = p->ce_next;
244 }
245 mutex_exit(&soft_config_mutex);
246
247 /*
248 * Check if we have consumed all of the space. We are done if
249 * this is the case.
250 */
251 ASSERT(mech_name <= end);
252 if (mech_name == end) {
253 mech_name_tab = tmp_mech_name_tab;
254 goto done;
255 }
256
257 /*
258 * Allocate a buffer of the right size now that we have the
259 * correct count.
260 */
261 mech_name_tab = kmem_zalloc(count * CRYPTO_MAX_MECH_NAME, kmflag);
262 if (mech_name_tab == NULL) {
263 kmem_free(tmp_mech_name_tab, n);
264 *countp = 0;
265 return (NULL);
266 }
267
268 bcopy(tmp_mech_name_tab, mech_name_tab, count * CRYPTO_MAX_MECH_NAME);
269 kmem_free(tmp_mech_name_tab, n);
270
271 done:
272 *countp = count;
273 return (mech_name_tab);
274 }
275
276 /*
277 * crypto_free_mech_list()
278 *
279 * Arguments:
280 * . mech_names: An array of crypto_mech_name_t previously allocated by
281 * crypto_get_mech_list.
282 * . count: the number of mech names in mech_names
283 *
284 * Description:
285 * Frees the the mech_names array.
286 *
287 * Context:
288 * Process and interruption.
289 */
290 void
crypto_free_mech_list(crypto_mech_name_t * mech_names,uint_t count)291 crypto_free_mech_list(crypto_mech_name_t *mech_names, uint_t count)
292 {
293 if ((mech_names != NULL) && (count > 0))
294 kmem_free(mech_names, count * CRYPTO_MAX_MECH_NAME);
295 }
296
297 /*
298 * crypto_notify_events()
299 *
300 * Arguments:
301 * . nf: Callback function to invoke when event occurs.
302 * . event_mask: Mask of events.
303 *
304 * Description:
305 * Allocates a new element and inserts it in to the notification
306 * list.
307 *
308 * Context:
309 * Process context.
310 *
311 * Returns:
312 * A handle is returned if the client is put on the notification list.
313 * NULL is returned otherwise.
314 */
315 crypto_notify_handle_t
crypto_notify_events(crypto_notify_callback_t nf,uint32_t event_mask)316 crypto_notify_events(crypto_notify_callback_t nf, uint32_t event_mask)
317 {
318 kcf_ntfy_elem_t *nep;
319 crypto_notify_handle_t hndl;
320
321 /* Check the input */
322 if (nf == NULL || !(event_mask & (CRYPTO_EVENT_MECHS_CHANGED |
323 CRYPTO_EVENT_PROVIDER_REGISTERED |
324 CRYPTO_EVENT_PROVIDER_UNREGISTERED))) {
325 return (NULL);
326 }
327
328 nep = kmem_zalloc(sizeof (kcf_ntfy_elem_t), KM_SLEEP);
329 mutex_init(&nep->kn_lock, NULL, MUTEX_DEFAULT, NULL);
330 cv_init(&nep->kn_cv, NULL, CV_DEFAULT, NULL);
331 nep->kn_state = NTFY_WAITING;
332 nep->kn_func = nf;
333 nep->kn_event_mask = event_mask;
334
335 mutex_enter(&ntfy_list_lock);
336 if (ntfy_list_head == NULL) {
337 ntfy_list_head = ntfy_list_tail = nep;
338 } else {
339 ntfy_list_tail->kn_next = nep;
340 nep->kn_prev = ntfy_list_tail;
341 ntfy_list_tail = nep;
342 }
343
344 hndl = (crypto_notify_handle_t)nep;
345 mutex_exit(&ntfy_list_lock);
346
347 return (hndl);
348 }
349
350 /*
351 * crypto_unnotify_events()
352 *
353 * Arguments:
354 * . hndl - Handle returned from an earlier crypto_notify_events().
355 *
356 * Description:
357 * Removes the element specified by hndl from the notification list.
358 * We wait for the notification routine to complete, if the routine
359 * is currently being called. We also free the element.
360 *
361 * Context:
362 * Process context.
363 */
364 void
crypto_unnotify_events(crypto_notify_handle_t hndl)365 crypto_unnotify_events(crypto_notify_handle_t hndl)
366 {
367 kcf_ntfy_elem_t *nep = (kcf_ntfy_elem_t *)hndl;
368
369 if (hndl == NULL)
370 return;
371
372 retry:
373 mutex_enter(&ntfy_list_lock);
374 mutex_enter(&nep->kn_lock);
375
376 if (nep->kn_state == NTFY_WAITING) {
377 kcf_ntfy_elem_t *nextp = nep->kn_next;
378 kcf_ntfy_elem_t *prevp = nep->kn_prev;
379
380 if (nextp != NULL)
381 nextp->kn_prev = prevp;
382 else
383 ntfy_list_tail = prevp;
384
385 if (prevp != NULL)
386 prevp->kn_next = nextp;
387 else
388 ntfy_list_head = nextp;
389 } else {
390 ASSERT(nep->kn_state == NTFY_RUNNING);
391
392 /*
393 * We have to drop this lock as the client might call
394 * crypto_notify_events() in the callback routine resulting
395 * in a deadlock.
396 */
397 mutex_exit(&ntfy_list_lock);
398
399 /*
400 * Another thread is working on this element. We will wait
401 * for that thread to signal us when done. No other thread
402 * will free this element. So, we can be sure it stays valid
403 * after the wait.
404 */
405 while (nep->kn_state == NTFY_RUNNING)
406 cv_wait(&nep->kn_cv, &nep->kn_lock);
407 mutex_exit(&nep->kn_lock);
408
409 /*
410 * We have to remove the element from the notification list.
411 * So, start over and do the work (acquire locks etc.). This is
412 * safe (i.e. We won't be in this routine forever) as the
413 * events do not happen frequently. We have to revisit this
414 * code if we add a new event that happens often.
415 */
416 goto retry;
417 }
418
419 mutex_exit(&nep->kn_lock);
420
421 /* Free the element */
422 mutex_destroy(&nep->kn_lock);
423 cv_destroy(&nep->kn_cv);
424 kmem_free(nep, sizeof (kcf_ntfy_elem_t));
425
426 mutex_exit(&ntfy_list_lock);
427 }
428
429 /*
430 * We walk the notification list and do the callbacks.
431 */
432 void
kcf_walk_ntfylist(uint32_t event,void * event_arg)433 kcf_walk_ntfylist(uint32_t event, void *event_arg)
434 {
435 kcf_ntfy_elem_t *nep;
436 int nelem = 0;
437
438 mutex_enter(&ntfy_list_lock);
439
440 /*
441 * Count how many clients are on the notification list. We need
442 * this count to ensure that clients which joined the list after we
443 * have started this walk, are not wrongly notified.
444 */
445 for (nep = ntfy_list_head; nep != NULL; nep = nep->kn_next)
446 nelem++;
447
448 for (nep = ntfy_list_head; (nep != NULL && nelem); nep = nep->kn_next) {
449 nelem--;
450
451 /*
452 * Check if this client is interested in the
453 * event.
454 */
455 if (!(nep->kn_event_mask & event))
456 continue;
457
458 mutex_enter(&nep->kn_lock);
459 nep->kn_state = NTFY_RUNNING;
460 mutex_exit(&nep->kn_lock);
461 mutex_exit(&ntfy_list_lock);
462
463 /*
464 * We invoke the callback routine with no locks held. Another
465 * client could have joined the list meanwhile. This is fine
466 * as we maintain nelem as stated above. The NULL check in the
467 * for loop guards against shrinkage. Also, any callers of
468 * crypto_unnotify_events() at this point cv_wait till kn_state
469 * changes to NTFY_WAITING. Hence, nep is assured to be valid.
470 */
471 (*nep->kn_func)(event, event_arg);
472
473 mutex_enter(&nep->kn_lock);
474 nep->kn_state = NTFY_WAITING;
475 cv_broadcast(&nep->kn_cv);
476 mutex_exit(&nep->kn_lock);
477
478 mutex_enter(&ntfy_list_lock);
479 }
480
481 mutex_exit(&ntfy_list_lock);
482 }
483
484 /*
485 * crypto_key_check()
486 *
487 * Arguments:
488 * . mech: the mechanism to check the key with.
489 * . key: the key to check for validity and weakness.
490 *
491 * Description:
492 * Checks the validity and strength of the key for the mechanism.
493 * CRYPTO_KEY_REFERENCE is not supported for this routine.
494 * If more than one provider is capable of key checking for the mechanism,
495 * then run the key through them all.
496 * A conservative approach is adopted here: New weak keys may be
497 * discovered with more recent providers. If at least one provider is
498 * not happy with a key, then it is no good.
499 *
500 * Context:
501 * Process and interruption.
502 */
503 int
crypto_key_check(crypto_mechanism_t * mech,crypto_key_t * key)504 crypto_key_check(crypto_mechanism_t *mech, crypto_key_t *key)
505 {
506 int error;
507 kcf_mech_entry_t *me;
508 kcf_provider_desc_t *pd;
509 kcf_prov_mech_desc_t *prov_chain;
510 kcf_lock_withpad_t *mp;
511
512 /* when mech is a valid mechanism, me will be its mech_entry */
513 if ((mech == NULL) || (key == NULL) ||
514 (key->ck_format == CRYPTO_KEY_REFERENCE))
515 return (CRYPTO_ARGUMENTS_BAD);
516
517 if ((error = kcf_get_mech_entry(mech->cm_type, &me)) != KCF_SUCCESS) {
518 /* error is one of the KCF_INVALID_MECH_XXX's */
519 return (CRYPTO_MECHANISM_INVALID);
520 }
521
522 mp = &me_mutexes[CPU_SEQID];
523 mutex_enter(&mp->kl_lock);
524
525 /* First let the software provider check this key */
526 if (me->me_sw_prov != NULL) {
527 pd = me->me_sw_prov->pm_prov_desc;
528 KCF_PROV_REFHOLD(pd);
529
530 if ((KCF_PROV_KEY_OPS(pd) != NULL) &&
531 (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) {
532 crypto_mechanism_t lmech;
533
534 mutex_exit(&mp->kl_lock);
535 lmech = *mech;
536 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd, &lmech);
537 error = KCF_PROV_KEY_CHECK(pd, &lmech, key);
538
539 if (error != CRYPTO_SUCCESS) {
540 KCF_PROV_REFRELE(pd);
541 return (error);
542 }
543
544 mutex_enter(&mp->kl_lock);
545 }
546 KCF_PROV_REFRELE(pd);
547 }
548
549 prov_chain = me->me_hw_prov_chain;
550 while (prov_chain != NULL) {
551 pd = prov_chain->pm_prov_desc;
552 KCF_PROV_REFHOLD(pd);
553
554 if ((KCF_PROV_KEY_OPS(pd) != NULL) &&
555 (KCF_PROV_KEY_OPS(pd)->key_check != NULL)) {
556 crypto_mechanism_t lmech;
557
558 mutex_exit(&mp->kl_lock);
559 lmech = *mech;
560 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, pd,
561 &lmech);
562 error = KCF_PROV_KEY_CHECK(pd, &lmech, key);
563
564 if (error != CRYPTO_SUCCESS) {
565 KCF_PROV_REFRELE(pd);
566 return (error);
567 }
568 mutex_enter(&mp->kl_lock);
569 }
570 KCF_PROV_REFRELE(pd);
571 prov_chain = prov_chain->pm_next;
572 }
573
574 mutex_exit(&mp->kl_lock);
575
576 /* All are happy with this key */
577 return (CRYPTO_SUCCESS);
578 }
579
580 int
crypto_key_check_prov(crypto_provider_t provider,crypto_mechanism_t * mech,crypto_key_t * key)581 crypto_key_check_prov(crypto_provider_t provider, crypto_mechanism_t *mech,
582 crypto_key_t *key)
583 {
584 kcf_provider_desc_t *pd = provider;
585 kcf_provider_desc_t *real_provider = pd;
586 crypto_mechanism_t lmech;
587 int rv;
588
589 ASSERT(KCF_PROV_REFHELD(pd));
590
591 if ((mech == NULL) || (key == NULL) ||
592 (key->ck_format == CRYPTO_KEY_REFERENCE))
593 return (CRYPTO_ARGUMENTS_BAD);
594
595 /* no logical providers currently support the key check */
596 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER) {
597 return (CRYPTO_NOT_SUPPORTED);
598 }
599
600 lmech = *mech;
601 KCF_SET_PROVIDER_MECHNUM(mech->cm_type, real_provider, &lmech);
602 rv = KCF_PROV_KEY_CHECK(real_provider, &lmech, key);
603 if (pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER)
604 KCF_PROV_REFRELE(real_provider);
605
606 return (rv);
607 }
608
609 /*
610 * Initialize the specified crypto_mechanism_info_t structure for
611 * the specified mechanism provider descriptor. Used by
612 * crypto_get_all_mech_info().
613 */
614 static void
init_mechanism_info(crypto_mechanism_info_t * mech_info,kcf_prov_mech_desc_t * pmd)615 init_mechanism_info(crypto_mechanism_info_t *mech_info,
616 kcf_prov_mech_desc_t *pmd)
617 {
618 crypto_func_group_t fg = pmd->pm_mech_info.cm_func_group_mask;
619
620 /* min/max key sizes */
621 mech_info->mi_keysize_unit = pmd->pm_mech_info.cm_mech_flags &
622 (CRYPTO_KEYSIZE_UNIT_IN_BITS | CRYPTO_KEYSIZE_UNIT_IN_BYTES);
623 mech_info->mi_min_key_size =
624 (size_t)pmd->pm_mech_info.cm_min_key_length;
625 mech_info->mi_max_key_size =
626 (size_t)pmd->pm_mech_info.cm_max_key_length;
627
628 /* usage flag */
629 mech_info->mi_usage = 0;
630 if (fg & (CRYPTO_FG_ENCRYPT | CRYPTO_FG_ENCRYPT_ATOMIC))
631 mech_info->mi_usage |= CRYPTO_MECH_USAGE_ENCRYPT;
632 if (fg & (CRYPTO_FG_DECRYPT | CRYPTO_FG_DECRYPT_ATOMIC))
633 mech_info->mi_usage |= CRYPTO_MECH_USAGE_DECRYPT;
634 if (fg & (CRYPTO_FG_MAC | CRYPTO_FG_MAC_ATOMIC))
635 mech_info->mi_usage |= CRYPTO_MECH_USAGE_MAC;
636 }
637
638 /*
639 * Return the mechanism info for the specified mechanism.
640 */
641 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)642 crypto_get_all_mech_info(crypto_mech_type_t mech_type,
643 crypto_mechanism_info_t **mech_infos, uint_t *num_mech_infos,
644 int km_flag)
645 {
646 uint_t ninfos, cur_info;
647 kcf_mech_entry_t *me;
648 int rv;
649 kcf_prov_mech_desc_t *hwp;
650 crypto_mechanism_info_t *infos;
651 size_t infos_size;
652 kcf_lock_withpad_t *mp;
653
654 /* get to the mech entry corresponding to the specified mech type */
655 if ((rv = kcf_get_mech_entry(mech_type, &me)) != CRYPTO_SUCCESS) {
656 return (rv);
657 }
658
659 /* compute the number of key size ranges to return */
660 mp = &me_mutexes[CPU_SEQID];
661 mutex_enter(&mp->kl_lock);
662 again:
663 ninfos = PROV_COUNT(me);
664 mutex_exit(&mp->kl_lock);
665
666 if (ninfos == 0) {
667 infos = NULL;
668 rv = CRYPTO_SUCCESS;
669 goto bail;
670 }
671 infos_size = ninfos * sizeof (crypto_mechanism_info_t);
672 infos = kmem_alloc(infos_size, km_flag);
673 if (infos == NULL) {
674 rv = CRYPTO_HOST_MEMORY;
675 goto bail;
676 }
677
678 mutex_enter(&mp->kl_lock);
679 if (ninfos != PROV_COUNT(me)) {
680 kmem_free(infos, infos_size);
681 goto again;
682 }
683
684 /* populate array of crypto mechanism infos */
685 cur_info = 0;
686
687 /* software provider, if present */
688 if (me->me_sw_prov != NULL)
689 init_mechanism_info(&infos[cur_info++], me->me_sw_prov);
690
691 /* hardware providers */
692 for (hwp = me->me_hw_prov_chain; hwp != NULL; hwp = hwp->pm_next)
693 init_mechanism_info(&infos[cur_info++], hwp);
694
695 mutex_exit(&mp->kl_lock);
696 ASSERT(cur_info == ninfos);
697 bail:
698 *mech_infos = infos;
699 *num_mech_infos = ninfos;
700 return (rv);
701 }
702
703 /*
704 * Frees the array of mechanism infos previously allocated by
705 * crypto_get_all_mech_info().
706 */
707 void
crypto_free_all_mech_info(crypto_mechanism_info_t * mech_infos,uint_t count)708 crypto_free_all_mech_info(crypto_mechanism_info_t *mech_infos, uint_t count)
709 {
710 if ((mech_infos != NULL) && (count > 0))
711 kmem_free(mech_infos, count * sizeof (crypto_mechanism_info_t));
712 }
713
714 /*
715 * memcmp_pad_max() is a specialized version of memcmp() which
716 * compares two pieces of data up to a maximum length. If the
717 * the two data match up the maximum length, they are considered
718 * matching. Trailing blanks do not cause the match to fail if
719 * one of the data is shorter.
720 *
721 * Examples of matches:
722 * "one" |
723 * "one " |
724 * ^maximum length
725 *
726 * "Number One | X" (X is beyond maximum length)
727 * "Number One " |
728 * ^maximum length
729 *
730 * Examples of mismatches:
731 * " one"
732 * "one"
733 *
734 * "Number One X|"
735 * "Number One |"
736 * ^maximum length
737 */
738 static int
memcmp_pad_max(void * d1,uint_t d1_len,void * d2,uint_t d2_len,uint_t max_sz)739 memcmp_pad_max(void *d1, uint_t d1_len, void *d2, uint_t d2_len, uint_t max_sz)
740 {
741 uint_t len, extra_len;
742 char *marker;
743
744 /* No point in comparing anything beyond max_sz */
745 if (d1_len > max_sz)
746 d1_len = max_sz;
747 if (d2_len > max_sz)
748 d2_len = max_sz;
749
750 /* Find shorter of the two data. */
751 if (d1_len <= d2_len) {
752 len = d1_len;
753 extra_len = d2_len;
754 marker = d2;
755 } else { /* d1_len > d2_len */
756 len = d2_len;
757 extra_len = d1_len;
758 marker = d1;
759 }
760
761 /* Have a match in the shortest length of data? */
762 if (memcmp(d1, d2, len) != 0)
763 /* CONSTCOND */
764 return (!0);
765
766 /* If the rest of longer data is nulls or blanks, call it a match. */
767 while (len < extra_len)
768 if (!isspace(marker[len++]))
769 /* CONSTCOND */
770 return (!0);
771 return (0);
772 }
773
774 /*
775 * Obtain ext info for specified provider and see if it matches.
776 */
777 static boolean_t
match_ext_info(kcf_provider_desc_t * pd,char * label,char * manuf,char * serial,crypto_provider_ext_info_t * ext_info)778 match_ext_info(kcf_provider_desc_t *pd, char *label, char *manuf, char *serial,
779 crypto_provider_ext_info_t *ext_info)
780 {
781 int rv;
782
783 rv = crypto_get_provinfo(pd, ext_info);
784 ASSERT(rv != CRYPTO_NOT_SUPPORTED);
785 if (rv != CRYPTO_SUCCESS)
786 return (B_FALSE);
787
788 if (memcmp_pad_max(ext_info->ei_label, CRYPTO_EXT_SIZE_LABEL,
789 label, strlen(label), CRYPTO_EXT_SIZE_LABEL))
790 return (B_FALSE);
791
792 if (manuf != NULL) {
793 if (memcmp_pad_max(ext_info->ei_manufacturerID,
794 CRYPTO_EXT_SIZE_MANUF, manuf, strlen(manuf),
795 CRYPTO_EXT_SIZE_MANUF))
796 return (B_FALSE);
797 }
798
799 if (serial != NULL) {
800 if (memcmp_pad_max(ext_info->ei_serial_number,
801 CRYPTO_EXT_SIZE_SERIAL, serial, strlen(serial),
802 CRYPTO_EXT_SIZE_SERIAL))
803 return (B_FALSE);
804 }
805 return (B_TRUE);
806 }
807
808 /*
809 * Find a provider based on its label, manufacturer ID, and serial number.
810 */
811 crypto_provider_t
crypto_get_provider(char * label,char * manuf,char * serial)812 crypto_get_provider(char *label, char *manuf, char *serial)
813 {
814 kcf_provider_desc_t **provider_array, *pd;
815 crypto_provider_ext_info_t *ext_info;
816 uint_t count;
817 int i;
818
819 /* manuf and serial are optional */
820 if (label == NULL)
821 return (NULL);
822
823 if (kcf_get_slot_list(&count, &provider_array, B_FALSE)
824 != CRYPTO_SUCCESS)
825 return (NULL);
826
827 if (count == 0)
828 return (NULL);
829
830 ext_info = kmem_zalloc(sizeof (crypto_provider_ext_info_t), KM_SLEEP);
831
832 for (i = 0; i < count; i++) {
833 pd = provider_array[i];
834 if (match_ext_info(pd, label, manuf, serial, ext_info)) {
835 KCF_PROV_REFHOLD(pd);
836 break;
837 }
838 }
839 if (i == count)
840 pd = NULL;
841
842 kcf_free_provider_tab(count, provider_array);
843 kmem_free(ext_info, sizeof (crypto_provider_ext_info_t));
844 return (pd);
845 }
846
847 /*
848 * Get the provider information given a provider handle. The caller
849 * needs to allocate the space for the argument, info.
850 */
851 int
crypto_get_provinfo(crypto_provider_t hndl,crypto_provider_ext_info_t * info)852 crypto_get_provinfo(crypto_provider_t hndl, crypto_provider_ext_info_t *info)
853 {
854 int rv;
855 kcf_req_params_t params;
856 kcf_provider_desc_t *pd;
857 kcf_provider_desc_t *real_provider;
858
859 pd = (kcf_provider_desc_t *)hndl;
860 rv = kcf_get_hardware_provider_nomech(
861 CRYPTO_OPS_OFFSET(provider_ops), CRYPTO_PROVIDER_OFFSET(ext_info),
862 pd, &real_provider);
863
864 if (rv == CRYPTO_SUCCESS && real_provider != NULL) {
865 ASSERT(real_provider == pd ||
866 pd->pd_prov_type == CRYPTO_LOGICAL_PROVIDER);
867 KCF_WRAP_PROVMGMT_OPS_PARAMS(¶ms, KCF_OP_MGMT_EXTINFO,
868 0, NULL, 0, NULL, 0, NULL, info, pd);
869 rv = kcf_submit_request(real_provider, NULL, NULL, ¶ms,
870 B_FALSE);
871 KCF_PROV_REFRELE(real_provider);
872 }
873
874 return (rv);
875 }
876
877 void
crypto_release_provider(crypto_provider_t provider)878 crypto_release_provider(crypto_provider_t provider)
879 {
880 KCF_PROV_REFRELE((kcf_provider_desc_t *)provider);
881 }
882