xref: /illumos-gate/usr/src/cmd/mdb/common/modules/crypto/impl.c (revision 4df55fde49134f9735f84011f23a767c75e393c7)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * mdb dcmds for selected structures from
28  * usr/src/uts/common/sys/crypto/impl.h
29  */
30 #include <stdio.h>
31 #include <sys/mdb_modapi.h>
32 #include <sys/modctl.h>
33 #include <sys/types.h>
34 #include <sys/crypto/api.h>
35 #include <sys/crypto/common.h>
36 #include <sys/crypto/impl.h>
37 #include "crypto_cmds.h"
38 
39 static const char *prov_states[] = {
40 	"none",
41 	"KCF_PROV_ALLOCATED",
42 	"KCF_PROV_UNVERIFIED",
43 	"KCF_PROV_VERIFICATION_FAILED",
44 	"KCF_PROV_READY",
45 	"KCF_PROV_BUSY",
46 	"KCF_PROV_FAILED",
47 	"KCF_PROV_DISABLED",
48 	"KCF_PROV_UNREGISTERING",
49 	"KCF_PROV_UNREGISTERED"
50 };
51 
52 /*ARGSUSED*/
53 int
54 kcf_provider_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
55 {
56 	kcf_provider_desc_t desc;
57 	kcf_provider_desc_t *ptr;
58 	char string[MAXNAMELEN + 1];
59 	int i, j;
60 	crypto_mech_info_t *mech_pointer;
61 	kcf_prov_cpu_t stats;
62 	uint64_t dtotal, ftotal, btotal;
63 	int holdcnt, jobcnt;
64 
65 	if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC)
66 		return (DCMD_USAGE);
67 	ptr = (kcf_provider_desc_t *)addr;
68 
69 #ifdef DEBUG
70 	mdb_printf("DEBUG: reading kcf_provider_desc at %p\n", ptr);
71 #endif
72 
73 	if (mdb_vread(&desc, sizeof (kcf_provider_desc_t), (uintptr_t)ptr)
74 	    == -1) {
75 		mdb_warn("cannot read at address %p", (uintptr_t)ptr);
76 		return (DCMD_ERR);
77 	}
78 	mdb_printf("%<b>kcf_provider_desc at %p%</b>\n", ptr);
79 
80 	switch (desc.pd_prov_type) {
81 	case CRYPTO_HW_PROVIDER:
82 		mdb_printf("pd_prov_type:\t\tCRYPTO_HW_PROVIDER\n");
83 		break;
84 	case CRYPTO_SW_PROVIDER:
85 		mdb_printf("pd_prov_type:\t\tCRYPTO_SW_PROVIDER\n");
86 		break;
87 	case CRYPTO_LOGICAL_PROVIDER:
88 		mdb_printf("pd_prov_type:\t\tCRYPTO_LOGICAL_PROVIDER\n");
89 		break;
90 	default:
91 		mdb_printf("bad pd_prov_type:\t%d\n", desc.pd_prov_type);
92 	}
93 
94 	mdb_printf("pd_prov_id:\t\t%u\n", desc.pd_prov_id);
95 	if (desc.pd_description == NULL)
96 		mdb_printf("pd_description:\t\tNULL\n");
97 	else if (mdb_readstr(string, MAXNAMELEN + 1,
98 	    (uintptr_t)desc.pd_description) == -1) {
99 		mdb_warn("cannot read %p", desc.pd_description);
100 	} else
101 		mdb_printf("pd_description:\t\t%s\n", string);
102 
103 	mdb_printf("pd_sid:\t\t\t%u\n", desc.pd_sid);
104 	mdb_printf("pd_taskq:\t\t%p\n", desc.pd_taskq);
105 	mdb_printf("pd_nbins:\t\t%u\n", desc.pd_nbins);
106 	mdb_printf("pd_percpu_bins:\t\t%p\n", desc.pd_percpu_bins);
107 
108 	dtotal = ftotal = btotal = 0;
109 	holdcnt = jobcnt = 0;
110 	for (i = 0; i < desc.pd_nbins; i++) {
111 		if (mdb_vread(&stats, sizeof (kcf_prov_cpu_t),
112 		    (uintptr_t)(desc.pd_percpu_bins + i)) == -1) {
113 			mdb_warn("cannot read addr %p",
114 			    desc.pd_percpu_bins + i);
115 			return (DCMD_ERR);
116 		}
117 
118 		holdcnt += stats.kp_holdcnt;
119 		jobcnt += stats.kp_jobcnt;
120 		dtotal += stats.kp_ndispatches;
121 		ftotal += stats.kp_nfails;
122 		btotal += stats.kp_nbusy_rval;
123 	}
124 	mdb_inc_indent(4);
125 	mdb_printf("total kp_holdcnt:\t\t%d\n", holdcnt);
126 	mdb_printf("total kp_jobcnt:\t\t%u\n", jobcnt);
127 	mdb_printf("total kp_ndispatches:\t%llu\n", dtotal);
128 	mdb_printf("total kp_nfails:\t\t%llu\n", ftotal);
129 	mdb_printf("total kp_nbusy_rval:\t%llu\n", btotal);
130 	mdb_dec_indent(4);
131 
132 	mdb_printf("pd_prov_handle:\t\t%p\n", desc.pd_prov_handle);
133 	mdb_printf("pd_kcf_prov_handle:\t%u\n", desc.pd_kcf_prov_handle);
134 
135 	mdb_printf("pd_ops_vector:\t\t%p\n", desc.pd_ops_vector);
136 	mdb_printf("pd_mech_list_count:\t%u\n", desc.pd_mech_list_count);
137 	/* mechanisms */
138 	mdb_inc_indent(4);
139 	for (i = 0; i < desc.pd_mech_list_count; i++) {
140 		mech_pointer = desc.pd_mechanisms + i;
141 		mdb_call_dcmd("crypto_mech_info",
142 		    (uintptr_t)mech_pointer, DCMD_ADDRSPEC, 0, NULL);
143 	}
144 	mdb_dec_indent(4);
145 	mdb_printf("pd_mech_indx:\n");
146 	mdb_inc_indent(8);
147 	for (i = 0; i < KCF_OPS_CLASSSIZE; i++) {
148 		for (j = 0; j < KCF_MAXMECHTAB; j++) {
149 			if (desc.pd_mech_indx[i][j] == KCF_INVALID_INDX)
150 				mdb_printf("N ");
151 			else
152 				mdb_printf("%u ", desc.pd_mech_indx[i][j]);
153 		}
154 		mdb_printf("\n");
155 	}
156 	mdb_dec_indent(8);
157 
158 	if (desc.pd_name == NULL)
159 		mdb_printf("pd_name:\t\t NULL\n");
160 	else if (mdb_readstr(string, MAXNAMELEN + 1, (uintptr_t)desc.pd_name)
161 	    == -1)
162 		mdb_warn("could not read pd_name from %X\n", desc.pd_name);
163 	else
164 		mdb_printf("pd_name:\t\t%s\n", string);
165 
166 	mdb_printf("pd_instance:\t\t%u\n", desc.pd_instance);
167 	mdb_printf("pd_module_id:\t\t%d\n", desc.pd_module_id);
168 	mdb_printf("pd_mctlp:\t\t%p\n", desc.pd_mctlp);
169 	mdb_printf("pd_lock:\t\t%p\n", desc.pd_lock);
170 	if (desc.pd_state < KCF_PROV_ALLOCATED ||
171 	    desc.pd_state > KCF_PROV_UNREGISTERED)
172 		mdb_printf("pd_state is invalid:\t%d\n", desc.pd_state);
173 	else
174 		mdb_printf("pd_state:\t%s\n", prov_states[desc.pd_state]);
175 	mdb_printf("pd_provider_list:\t%p\n", desc.pd_provider_list);
176 
177 	mdb_printf("pd_resume_cv:\t\t%hd\n", desc.pd_resume_cv._opaque);
178 	mdb_printf("pd_flags:\t\t%s %s %s %s %s %s\n",
179 	    (desc.pd_flags & CRYPTO_HIDE_PROVIDER) ?
180 	    "CRYPTO_HIDE_PROVIDER" : " ",
181 	    (desc.pd_flags & CRYPTO_HASH_NO_UPDATE) ?
182 	    "CRYPTO_HASH_NO_UPDATE" : " ",
183 	    (desc.pd_flags & CRYPTO_HMAC_NO_UPDATE) ?
184 	    "CRYPTO_HMAC_NO_UPDATE" : " ",
185 	    (desc.pd_flags & CRYPTO_SYNCHRONOUS) ?
186 	    "CRYPTO_SYNCHRONOUS" : " ",
187 	    (desc.pd_flags & KCF_LPROV_MEMBER) ?
188 	    "KCF_LPROV_MEMBER" : " ",
189 	    (desc.pd_flags & KCF_PROV_RESTRICTED) ?
190 	    "KCF_PROV_RESTRICTED" : " ");
191 	if (desc.pd_flags & CRYPTO_HASH_NO_UPDATE)
192 		mdb_printf("pd_hash_limit:\t\t%u\n", desc.pd_hash_limit);
193 	if (desc.pd_flags & CRYPTO_HMAC_NO_UPDATE)
194 		mdb_printf("pd_hmac_limit:\t\t%u\n", desc.pd_hmac_limit);
195 
196 	mdb_printf("pd_kstat:\t\t%p\n", desc.pd_kstat);
197 
198 	return (DCMD_OK);
199 }
200 
201 #define	GOT_NONE	(-2)
202 
203 /*ARGSUSED*/
204 int
205 prov_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
206 {
207 	kcf_provider_desc_t **tab;
208 	kcf_provider_desc_t desc;
209 	kcf_provider_desc_t *ptr;
210 	uint_t prov_tab_max;
211 	int i;
212 	int gotzero = GOT_NONE;
213 	char string[MAXNAMELEN + 1];
214 
215 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
216 		return (DCMD_USAGE);
217 	} else if (mdb_readsym(&ptr, sizeof (void *), "prov_tab")
218 	    == -1) {
219 		mdb_warn("cannot read prov_tab");
220 		return (DCMD_ERR);
221 
222 	} else if (mdb_readvar(&prov_tab_max, "prov_tab_max") == -1) {
223 		mdb_warn("cannot read prov_tab_max");
224 		return (DCMD_ERR);
225 	}
226 	mdb_printf("%<b>prov_tab = %p%</b>\n", ptr);
227 	tab = mdb_zalloc(prov_tab_max * sizeof (kcf_provider_desc_t *),
228 	    UM_SLEEP| UM_GC);
229 
230 #ifdef DEBUG
231 	mdb_printf("DEBUG: tab = %p, prov_tab_max = %d\n", tab, prov_tab_max);
232 #endif
233 
234 	if (mdb_vread(tab, prov_tab_max * sizeof (kcf_provider_desc_t *),
235 	    (uintptr_t)ptr) == -1) {
236 		mdb_warn("cannot read prov_tab");
237 		return (DCMD_ERR);
238 	}
239 #ifdef DEBUG
240 	mdb_printf("DEBUG: got past mdb_vread of tab\n");
241 	mdb_printf("DEBUG: *tab = %p\n", *tab);
242 #endif
243 	for (i = 0;  i <  prov_tab_max; i++) {
244 		/* save space, only print range for long list of nulls */
245 		if (tab[i] == NULL) {
246 			if (gotzero == GOT_NONE) {
247 				mdb_printf("prov_tab[%d", i);
248 				gotzero = i;
249 			}
250 		} else {
251 			/* first non-null in awhile, print index of prev null */
252 			if (gotzero != GOT_NONE) {
253 				if (gotzero == (i - 1))
254 					mdb_printf("] = NULL\n", i - 1);
255 				else
256 					mdb_printf(" - %d] = NULL\n", i - 1);
257 				gotzero = GOT_NONE;
258 			}
259 			/* interesting value, print it */
260 			mdb_printf("prov_tab[%d] = %p ", i, tab[i]);
261 
262 			if (mdb_vread(&desc, sizeof (kcf_provider_desc_t),
263 			    (uintptr_t)tab[i]) == -1) {
264 				mdb_warn("cannot read at address %p",
265 				    (uintptr_t)tab[i]);
266 				return (DCMD_ERR);
267 			}
268 
269 			(void) mdb_readstr(string, MAXNAMELEN + 1,
270 			    (uintptr_t)desc.pd_name);
271 			mdb_printf("(%s\t%s)\n", string,
272 			    prov_states[desc.pd_state]);
273 		}
274 	}
275 	/* if we've printed the first of many nulls but left the brace open */
276 	if ((i > 0) && (tab[i-1] == NULL)) {
277 		if (gotzero == GOT_NONE)
278 			mdb_printf("] = NULL\n");
279 		else
280 			mdb_printf(" - %d] = NULL\n", i - 1);
281 	}
282 
283 	return (DCMD_OK);
284 }
285 
286 /*ARGSUSED*/
287 int
288 policy_tab(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
289 {
290 	kcf_policy_desc_t **tab;
291 	kcf_policy_desc_t *ptr;
292 	uint_t policy_tab_max;
293 	int num, i;
294 	int gotzero = GOT_NONE;
295 
296 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
297 		return (DCMD_USAGE);
298 	} else if (mdb_readsym(&ptr, sizeof (void *), "policy_tab")
299 	    == -1) {
300 		mdb_warn("cannot read policy_tab");
301 		return (DCMD_ERR);
302 
303 	} else if (mdb_readvar(&policy_tab_max, "policy_tab_max") == -1) {
304 		mdb_warn("cannot read policy_tab_max");
305 		return (DCMD_ERR);
306 	}
307 
308 	/* get the current number of descriptors in the table */
309 	if (mdb_readvar(&num, "policy_tab_num") == -1) {
310 		mdb_warn("cannot read policy_tab_num");
311 		return (DCMD_ERR);
312 	}
313 	mdb_printf("%<b>policy_tab = %p%</b> \tpolicy_tab_num = %d\n",
314 	    ptr, num);
315 
316 	tab = mdb_zalloc(policy_tab_max * sizeof (kcf_policy_desc_t *),
317 	    UM_SLEEP| UM_GC);
318 
319 	if (mdb_vread(tab, policy_tab_max * sizeof (kcf_policy_desc_t *),
320 	    (uintptr_t)ptr) == -1) {
321 		mdb_warn("cannot read policy_tab");
322 		return (DCMD_ERR);
323 	}
324 #ifdef DEBUG
325 	mdb_printf("DEBUG: got past mdb_vread of tab\n");
326 	mdb_printf("DEBUG: *tab = %p\n", *tab);
327 #endif
328 	for (i = 0;  i < policy_tab_max; i++) {
329 		/* save space, only print range for long list of nulls */
330 		if (tab[i] == NULL) {
331 			if (gotzero == GOT_NONE) {
332 				mdb_printf("policy_tab[%d", i);
333 				gotzero = i;
334 			}
335 		} else {
336 			/* first non-null in awhile, print index of prev null */
337 			if (gotzero != GOT_NONE) {
338 				if (gotzero == (i - 1))
339 					mdb_printf("] = NULL\n", i - 1);
340 				else
341 					mdb_printf(" - %d] = NULL\n", i - 1);
342 				gotzero = GOT_NONE;
343 			}
344 			/* interesting value, print it */
345 			mdb_printf("policy_tab[%d] = %p\n", i, tab[i]);
346 		}
347 	}
348 	/* if we've printed the first of many nulls but left the brace open */
349 	if ((i > 0) && (tab[i-1] == NULL)) {
350 		if (gotzero == GOT_NONE)
351 			mdb_printf("] = NULL\n");
352 		else
353 			mdb_printf(" - %d] = NULL\n", i - 1);
354 	}
355 
356 	return (DCMD_OK);
357 }
358 
359 static void
360 prt_mechs(int count, crypto_mech_name_t *mechs)
361 {
362 	int i;
363 	char name[CRYPTO_MAX_MECH_NAME + 1];
364 	char name2[CRYPTO_MAX_MECH_NAME + 3];
365 
366 	for (i = 0; i < count; i++) {
367 		if (mdb_readstr(name, CRYPTO_MAX_MECH_NAME,
368 		    (uintptr_t)((char *)mechs)) == -1)
369 			continue;
370 		/* put in quotes */
371 		(void) mdb_snprintf(name2, sizeof (name2), "\"%s\"", name);
372 		/* yes, length is 32, but then it will wrap */
373 		/* this shorter size formats nicely for most cases */
374 		mdb_printf("mechs[%d]=%-28s", i, name2);
375 		mdb_printf("%s", i%2 ? "\n" : "  "); /* 2-columns */
376 		mechs++;
377 	}
378 }
379 
380 /* ARGSUSED2 */
381 static int
382 prt_soft_conf_entry(kcf_soft_conf_entry_t *addr, kcf_soft_conf_entry_t *entry,
383     void *cbdata)
384 {
385 	char name[MAXNAMELEN + 1];
386 
387 	mdb_printf("\n%<b>kcf_soft_conf_entry_t at %p:%</b>\n", addr);
388 	mdb_printf("ce_next: %p", entry->ce_next);
389 
390 	if (entry->ce_name == NULL)
391 		mdb_printf("\tce_name: NULL\n");
392 	else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)entry->ce_name)
393 	    == -1)
394 		mdb_printf("could not read ce_name from %p\n",
395 		    entry->ce_name);
396 	else
397 		mdb_printf("\tce_name: %s\n", name);
398 
399 	mdb_printf("ce_count: %d\n", entry->ce_count);
400 	prt_mechs(entry->ce_count, entry->ce_mechs);
401 	return (WALK_NEXT);
402 }
403 
404 int
405 soft_conf_walk_init(mdb_walk_state_t *wsp)
406 {
407 	uintptr_t *soft;
408 
409 	if (mdb_readsym(&soft, sizeof (kcf_soft_conf_entry_t *),
410 	    "soft_config_list") == -1) {
411 		mdb_warn("failed to find 'soft_config_list'");
412 		return (WALK_ERR);
413 	}
414 	wsp->walk_addr = (uintptr_t)soft;
415 	wsp->walk_data = mdb_alloc(sizeof (kcf_soft_conf_entry_t), UM_SLEEP);
416 	wsp->walk_callback = (mdb_walk_cb_t)prt_soft_conf_entry;
417 	return (WALK_NEXT);
418 }
419 
420 /*
421  * At each step, read a kcf_soft_conf_entry_t into our private storage, then
422  * invoke the callback function.  We terminate when we reach a NULL ce_next
423  * pointer.
424  */
425 int
426 soft_conf_walk_step(mdb_walk_state_t *wsp)
427 {
428 	int status;
429 
430 	if (wsp->walk_addr == NULL)	/* then we're done */
431 		return (WALK_DONE);
432 #ifdef DEBUG
433 	else
434 		mdb_printf("DEBUG: wsp->walk_addr == %p\n", wsp->walk_addr);
435 #endif
436 
437 	if (mdb_vread(wsp->walk_data, sizeof (kcf_soft_conf_entry_t),
438 	    wsp->walk_addr) == -1) {
439 		mdb_warn("failed to read kcf_soft_conf_entry at %p",
440 		    wsp->walk_addr);
441 		return (WALK_DONE);
442 	}
443 
444 	status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data,
445 	    wsp->walk_cbdata);
446 
447 	wsp->walk_addr =
448 	    (uintptr_t)(((kcf_soft_conf_entry_t *)wsp->walk_data)->ce_next);
449 	return (status);
450 }
451 
452 /*
453  * The walker's fini function is invoked at the end of each walk.  Since we
454  * dynamically allocated a kcf_soft_conf_entry_t in soft_conf_walk_init,
455  * we must free it now.
456  */
457 void
458 soft_conf_walk_fini(mdb_walk_state_t *wsp)
459 {
460 #ifdef	DEBUG
461 	mdb_printf("...end of kcf_soft_conf_entry walk\n");
462 #endif
463 	mdb_free(wsp->walk_data, sizeof (kcf_soft_conf_entry_t));
464 }
465 /* ARGSUSED2 */
466 int
467 kcf_soft_conf_entry(uintptr_t addr, uint_t flags, int argc,
468     const mdb_arg_t *argv)
469 {
470 	kcf_soft_conf_entry_t entry;
471 	kcf_soft_conf_entry_t *ptr;
472 
473 	if ((flags & DCMD_ADDRSPEC) == DCMD_ADDRSPEC) {
474 		if (addr == NULL) 	/* not allowed with DCMD_ADDRSPEC */
475 			return (DCMD_USAGE);
476 		else
477 			ptr = (kcf_soft_conf_entry_t *)addr;
478 	} else if (mdb_readsym(&ptr, sizeof (void *), "soft_config_list")
479 	    == -1) {
480 		mdb_warn("cannot read soft_config_list");
481 		return (DCMD_ERR);
482 	} else
483 		mdb_printf("soft_config_list = %p\n", ptr);
484 
485 	if (ptr == NULL)
486 		return (DCMD_OK);
487 
488 	if (mdb_vread(&entry, sizeof (kcf_soft_conf_entry_t), (uintptr_t)ptr)
489 	    == -1) {
490 		mdb_warn("cannot read at address %p", (uintptr_t)ptr);
491 		return (DCMD_ERR);
492 	}
493 
494 	/* this could change in the future to have more than one ret val */
495 	if (prt_soft_conf_entry(ptr, &entry, NULL) != WALK_ERR)
496 		return (DCMD_OK);
497 	return (DCMD_ERR);
498 }
499 
500 /* ARGSUSED1 */
501 int
502 kcf_policy_desc(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
503 {
504 	kcf_policy_desc_t  desc;
505 	char name[MAXNAMELEN + 1];
506 
507 
508 	if ((flags & DCMD_ADDRSPEC) != DCMD_ADDRSPEC)
509 		return (DCMD_USAGE);
510 
511 	if (mdb_vread(&desc, sizeof (kcf_policy_desc_t), (uintptr_t)addr)
512 	    == -1) {
513 		mdb_warn("Could not read kcf_policy_desc_t at %p\n", addr);
514 		return (DCMD_ERR);
515 	}
516 	mdb_printf("pd_prov_type:  %s",
517 	    desc.pd_prov_type == CRYPTO_HW_PROVIDER ? "CRYPTO_HW_PROVIDER" :
518 	    "CRYPTO_SW_PROVIDER");
519 
520 	if (desc.pd_name == NULL)
521 		mdb_printf("\tpd_name: NULL\n");
522 	else if (mdb_readstr(name, MAXNAMELEN, (uintptr_t)desc.pd_name)
523 	    == -1)
524 		mdb_printf("could not read pd_name from %p\n",
525 		    desc.pd_name);
526 	else
527 		mdb_printf("\tpd_name: %s\n", name);
528 
529 	mdb_printf("pd_instance: %d ", desc.pd_instance);
530 	mdb_printf("\t\tpd_refcnt: %d\n", desc.pd_refcnt);
531 	mdb_printf("pd_mutex: %p", desc.pd_mutex);
532 	mdb_printf("\t\tpd_disabled_count: %d", desc.pd_disabled_count);
533 	mdb_printf("\npd_disabled_mechs:\n");
534 	mdb_inc_indent(4);
535 	prt_mechs(desc.pd_disabled_count, desc.pd_disabled_mechs);
536 	mdb_dec_indent(4);
537 	return (DCMD_OK);
538 }
539