xref: /illumos-gate/usr/src/uts/sun4v/sys/n2rng.h (revision a3175730a459223fb8f26a2915aa0a31f6b36f98)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #ifndef	_SYS_N2RNG_H
27 #define	_SYS_N2RNG_H
28 
29 #pragma ident	"%Z%%M%	%I%	%E% SMI"
30 
31 /* skip following stuff when included in n2rng_hcall.s */
32 #ifndef _ASM
33 #include <sys/types.h>
34 #include <sys/mutex.h>
35 #include <sys/ksynch.h>
36 #include <sys/sunddi.h>
37 #include <sys/param.h>
38 #include <sys/crypto/common.h>
39 #include <sys/crypto/spi.h>
40 
41 #endif /* !_ASM */
42 
43 #ifdef	__cplusplus
44 extern "C" {
45 #endif
46 
47 /*
48  * RNG HV API version definitions.
49  */
50 #define	RNG_MAJOR_VER		1
51 #define	RNG_MINOR_VER		0
52 
53 #define	HV_RNG_GET_DIAG_CONTROL	0x130
54 #define	HV_RNG_CTL_READ		0x131
55 #define	HV_RNG_CTL_WRITE	0x132
56 #define	HV_RNG_DATA_READ_DIAG	0x133
57 #define	HV_RNG_DATA_READ	0x134
58 
59 #define	CTL_STATE_UNCONFIGURED	0
60 #define	CTL_STATE_CONFIGURED	1
61 #define	CTL_STATE_HEALTHCHECK	2
62 #define	CTL_STATE_ERROR		3
63 
64 #define	NRNGCTL			4
65 #define	N2RNG_MAX_READ		(128 * 1024)	/* 128K bytes */
66 
67 #define	DRIVER			"n2rng"
68 #define	N2RNG_MANUFACTURER_ID	"SUNWn2rng"
69 
70 
71 #ifndef _ASM
72 
73 typedef union n2rngctl {
74 	uint64_t	word;
75 	struct {
76 		uint64_t rnc_res : 39;
77 		uint64_t rnc_cnt : 16;
78 		uint64_t rnc_bypass : 1;
79 		uint64_t rnc_vcoctl : 2;
80 		uint64_t rnc_anlg_sel : 2;
81 		uint64_t rnc_mode : 1;
82 		uint64_t rnc_selbits : 3;
83 	} fields;
84 } n2rng_ctl_t;
85 
86 typedef struct {
87 	n2rng_ctl_t ctlwds[NRNGCTL];
88 } n2rng_setup_t;
89 
90 #if defined(_KERNEL)
91 
92 /*
93  * Our contiguous memory alignment requirement is
94  * only for 8 bytes, however contig mem allocation
95  * routines requirement minimum of 64.
96  */
97 #define	CONTIG_ALIGNMENT	64
98 /*
99  * Returns 1 only if the address range of a variable of type type at
100  * ptr falls entirely on one page.  Based on page size of 4K.  May
101  * give some false negatives on larger page sizes.
102  */
103 #define	CONTIGUOUS(ptr, type)	\
104 	(((((uint64_t)(ptr)) ^ ((uint64_t)(ptr) + sizeof (type) -1))	\
105 	& PAGEMASK) == 0)
106 
107 /*
108  * The RNG hardware can send certain internal analog signals to an
109  * external pin on the chip.  Setting the rnc_anlg_sel bit to
110  * N2RNG_NOANALOGOUT deselects all analog signals (perhaps selects
111  * ground).  Choosing any other value would aid an attacker with
112  * physical access to the chip.
113  */
114 #define	N2RNG_NOANALOGOUT	0x2
115 
116 /*
117  * There can only be N2_RNG_FIPS_INSTANCES concurrent RNG requsts from
118  * the framework.  Making this value large helps benchmarks.  It
119  * should probably come from a conf file, but for now it is hard
120  * coded.  The code computes i % N2RNG_FIPS_INSTANCES, which is more
121  * efficient when N2RNG_FIPS_INSTANCES is a power of 2.
122  */
123 #define	N2RNG_FIPS_INSTANCES 8
124 
125 typedef struct fipsrandomstruct fipsrandomstruct_t;
126 struct fipsrandomstruct {
127 	kmutex_t	mtx;
128 	uint64_t	entropyhunger;  /* RNGs generated with no entropy */
129 	uint32_t	XKEY[6]; /* one extra word for getentropy */
130 };
131 
132 typedef struct {
133 	/*
134 	 * volatile, since it is not protected by a mutex.  (That is
135 	 * okay since it is operated on and accessed via atomic ops.)
136 	 */
137 	volatile unsigned int	fips_round_robin_j;
138 	fipsrandomstruct_t	fipsarray[N2RNG_FIPS_INSTANCES];
139 } fips_ensemble_t;
140 
141 #define	N2RNG_FAILED		0x1 /* for n_flags; used by kstat */
142 
143 #define	DS_RNGBYTES		0
144 #define	DS_RNGJOBS		1
145 #define	DS_RNGHEALTHCHECKS	2
146 #define	DS_MAX			3
147 
148 #define	N2RNG_NOSC		3
149 #define	N2RNG_BIASBITS		2
150 #define	N2RNG_NBIASES		(1 << N2RNG_BIASBITS)
151 #define	N2RNG_CTLOPS		(N2RNG_OSC + 1)
152 
153 typedef struct {
154 	uint64_t	numvals;
155 	uint64_t	H1;	/* in bits per bit << LOG_VAL_SCALE */
156 	uint64_t	H2;
157 	uint64_t	Hinf;
158 } n2rng_osc_perf_t;
159 
160 typedef n2rng_osc_perf_t n2rng_osc_perf_table_t[N2RNG_NOSC][N2RNG_NBIASES];
161 
162 
163 typedef struct n2rng {
164 	kmutex_t		n_lock;
165 	dev_info_t		*n_dip;
166 	minor_t			n_minor;
167 	unsigned		n_flags;	/* dev state flags */
168 	kstat_t			*n_ksp;
169 	uint64_t		n_stats[DS_MAX];
170 	crypto_kcf_provider_handle_t	n_prov;
171 	fips_ensemble_t		n_frs;
172 	n2rng_osc_perf_table_t	n_perftable;
173 	n2rng_setup_t		n_preferred_config;
174 	kmutex_t		n_health_check_mutex;
175 	time_t			n_last_health_time;
176 	uint64_t		n_rng_state; /* as last known in this drvr. */
177 	uint64_t		n_sticks_per_usec;
178 	uint64_t		n_anlg_settle_cycles;
179 	ddi_taskq_t		*n_taskq;
180 } n2rng_t;
181 
182 
183 typedef struct n2rng_stat n2rng_stat_t;
184 struct n2rng_stat {
185 	kstat_named_t		ns_status;
186 	kstat_named_t		ns_algs[DS_MAX];
187 };
188 
189 #define	RNG_MODE_NORMAL		1
190 #define	RNG_MODE_DIAGNOSTIC	0
191 
192 #define	RNG_CTL_SETTLE_NS	2000000	/* nanoseconds */
193 #define	RNG_DIAG_CHUNK_SIZE	(N2RNG_MAX_READ / 8)	/* as words */
194 #define	RNG_MAX_DATA_READ_ATTEMPTS	100
195 #define	RNG_DEFAULT_ACCUMULATE_CYCLES	4000
196 #define	RNG_RETRY_HLCHK_USECS	100000 /* retry every .1 seconds */
197 
198 #define	LOG_ARG_SCALE		49
199 #define	LOG_VAL_SCALE		32
200 
201 
202 void n2rng_sort(uint64_t *data, int log2_size);
203 int n2rng_noise_gen_preferred(n2rng_t *n2rng);
204 int n2rng_check_set(n2rng_t *n2rng);
205 int n2rng_collect_diag_bits(n2rng_t *n2rng, n2rng_setup_t *collect_setupp,
206     void *buffer, int numbytes, n2rng_setup_t *exit_setupp,
207     uint64_t exitstate);
208 int n2rng_getentropy(n2rng_t *n2rng, void *buffer, size_t size);
209 int n2rng_fips_random_init(n2rng_t *n2rng, fipsrandomstruct_t *frsp);
210 void n2rng_fips_random_fini(fipsrandomstruct_t *frsp);
211 int n2rng_do_health_check(n2rng_t *n2rng);
212 void n2rng_renyi_entropy(uint64_t *buffer, int log2samples,
213     n2rng_osc_perf_t *metricp);
214 
215 
216 
217 
218 #if defined(DEBUG)
219 
220 #define	DWARN		0x00000001
221 #define	DMA_ARGS	0x00000002
222 #define	DMA_LDST	0x00000004
223 #define	DNCS_QTAIL	0x00000008
224 #define	DATTACH		0x00000010
225 #define	DMOD		0x00000040  /* _init/_fini/_info/attach/detach */
226 #define	DENTRY		0x00000080  /* crypto routine entry/exit points */
227 #define	DCHATTY		0x00000100
228 #define	DALL		0xFFFFFFFF
229 
230 #define	DBG0	n2rng_dprintf
231 #define	DBG1	n2rng_dprintf
232 #define	DBG2	n2rng_dprintf
233 #define	DBG3	n2rng_dprintf
234 #define	DBG4	n2rng_dprintf
235 #define	DBG5	n2rng_dprintf
236 #define	DBG6	n2rng_dprintf
237 #define	DBGCALL(flag, func)	{ if (n2rng_dflagset(flag)) (void) func; }
238 
239 void	n2rng_dprintf(n2rng_t *, int, const char *, ...);
240 void	n2rng_dumphex(void *, int);
241 int	n2rng_dflagset(int);
242 
243 #else	/* !defined(DEBUG) */
244 
245 #define	DBG0(vca, lvl, fmt)
246 #define	DBG1(vca, lvl, fmt, arg1)
247 #define	DBG2(vca, lvl, fmt, arg1, arg2)
248 #define	DBG3(vca, lvl, fmt, arg1, arg2, arg3)
249 #define	DBG4(vca, lvl, fmt, arg1, arg2, arg3, arg4)
250 #define	DBG5(vca, lvl, fmt, arg1, arg2, arg3, arg4, arg5)
251 #define	DBG6(vca, lvl, fmt, arg1, arg2, arg3, arg4, arg5, arg6)
252 #define	DBGCALL(flag, func)
253 
254 #endif	/* !defined(DEBUG) */
255 
256 /*
257  * n2rng_debug.c
258  */
259 void	n2rng_error(n2rng_t *, const char *, ...);
260 void	n2rng_diperror(dev_info_t *, const char *, ...);
261 void	n2rng_dipverror(dev_info_t *, const char *, va_list);
262 
263 uint64_t hv_rng_get_diag_control(void);
264 uint64_t hv_rng_read_ctl(uint64_t ctlregs_pa, uint64_t *state,
265     uint64_t *tdelta);
266 uint64_t hv_rng_ctl_write(uint64_t ctlregs_pa,
267     uint64_t newstate, uint64_t wtimeout, uint64_t *tdelta);
268 uint64_t hv_rng_data_read_diag(uint64_t data_pa,
269     size_t  datalen, uint64_t *tdelta);
270 uint64_t hv_rng_data_read(uint64_t data_pa, uint64_t *tdelta);
271 
272 #endif /* _KERNEL */
273 #endif /* !_ASM */
274 
275 #ifdef	__cplusplus
276 }
277 #endif
278 
279 #endif	/* _SYS_N2RNG_H */
280