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