144961713Sgirish /* 244961713Sgirish * CDDL HEADER START 344961713Sgirish * 444961713Sgirish * The contents of this file are subject to the terms of the 544961713Sgirish * Common Development and Distribution License (the "License"). 644961713Sgirish * You may not use this file except in compliance with the License. 744961713Sgirish * 844961713Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 944961713Sgirish * or http://www.opensolaris.org/os/licensing. 1044961713Sgirish * See the License for the specific language governing permissions 1144961713Sgirish * and limitations under the License. 1244961713Sgirish * 1344961713Sgirish * When distributing Covered Code, include this CDDL HEADER in each 1444961713Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 1544961713Sgirish * If applicable, add the following below this CDDL HEADER, with the 1644961713Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 1744961713Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 1844961713Sgirish * 1944961713Sgirish * CDDL HEADER END 2044961713Sgirish */ 2144961713Sgirish /* 2259ac0c16Sdavemq * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 2344961713Sgirish * Use is subject to license terms. 2444961713Sgirish */ 2544961713Sgirish 2644961713Sgirish #ifndef _SYS_N2RNG_H 2744961713Sgirish #define _SYS_N2RNG_H 2844961713Sgirish 2944961713Sgirish #pragma ident "%Z%%M% %I% %E% SMI" 3044961713Sgirish 3144961713Sgirish /* skip following stuff when included in n2rng_hcall.s */ 3244961713Sgirish #ifndef _ASM 3344961713Sgirish #include <sys/types.h> 3444961713Sgirish #include <sys/mutex.h> 3544961713Sgirish #include <sys/ksynch.h> 3644961713Sgirish #include <sys/sunddi.h> 3744961713Sgirish #include <sys/param.h> 3844961713Sgirish #include <sys/crypto/common.h> 3944961713Sgirish #include <sys/crypto/spi.h> 40*741c280dStwelke #include <sys/mdesc.h> 4144961713Sgirish 4244961713Sgirish #endif /* !_ASM */ 4344961713Sgirish 4444961713Sgirish #ifdef __cplusplus 4544961713Sgirish extern "C" { 4644961713Sgirish #endif 4744961713Sgirish 4844961713Sgirish #define HV_RNG_GET_DIAG_CONTROL 0x130 4944961713Sgirish #define HV_RNG_CTL_READ 0x131 5044961713Sgirish #define HV_RNG_CTL_WRITE 0x132 5144961713Sgirish #define HV_RNG_DATA_READ_DIAG 0x133 5244961713Sgirish #define HV_RNG_DATA_READ 0x134 5344961713Sgirish 5444961713Sgirish #define CTL_STATE_UNCONFIGURED 0 5544961713Sgirish #define CTL_STATE_CONFIGURED 1 5644961713Sgirish #define CTL_STATE_HEALTHCHECK 2 5744961713Sgirish #define CTL_STATE_ERROR 3 5844961713Sgirish 5944961713Sgirish #define NRNGCTL 4 6044961713Sgirish #define N2RNG_MAX_READ (128 * 1024) /* 128K bytes */ 6144961713Sgirish 6244961713Sgirish #define DRIVER "n2rng" 6344961713Sgirish #define N2RNG_MANUFACTURER_ID "SUNWn2rng" 6444961713Sgirish 65*741c280dStwelke #define N2RNG_BINDNAME_N2 "SUNW,n2-rng" 66*741c280dStwelke #define N2RNG_BINDNAME_VF "SUNW,vf-rng" 67*741c280dStwelke 68*741c280dStwelke #define N2RNG_MAX_RNGS 4 69*741c280dStwelke #define N2RNG_INVALID_ID (-1) 7044961713Sgirish 7144961713Sgirish #ifndef _ASM 7244961713Sgirish 73*741c280dStwelke typedef enum { 74*741c280dStwelke N2RNG_CPU_UNKNOWN, 75*741c280dStwelke N2RNG_CPU_N2, 76*741c280dStwelke N2RNG_CPU_VF 77*741c280dStwelke } n2rng_binding_t; 78*741c280dStwelke 7944961713Sgirish typedef union n2rngctl { 8044961713Sgirish uint64_t word; 8144961713Sgirish struct { 8244961713Sgirish uint64_t rnc_res : 39; 8344961713Sgirish uint64_t rnc_cnt : 16; 8444961713Sgirish uint64_t rnc_bypass : 1; 8544961713Sgirish uint64_t rnc_vcoctl : 2; 8644961713Sgirish uint64_t rnc_anlg_sel : 2; 8744961713Sgirish uint64_t rnc_mode : 1; 8844961713Sgirish uint64_t rnc_selbits : 3; 8944961713Sgirish } fields; 9044961713Sgirish } n2rng_ctl_t; 9144961713Sgirish 9244961713Sgirish typedef struct { 9344961713Sgirish n2rng_ctl_t ctlwds[NRNGCTL]; 9444961713Sgirish } n2rng_setup_t; 9544961713Sgirish 9644961713Sgirish #if defined(_KERNEL) 9744961713Sgirish 9844961713Sgirish /* 9944961713Sgirish * Our contiguous memory alignment requirement is 10044961713Sgirish * only for 8 bytes, however contig mem allocation 10144961713Sgirish * routines requirement minimum of 64. 10244961713Sgirish */ 10344961713Sgirish #define CONTIG_ALIGNMENT 64 104*741c280dStwelke 10544961713Sgirish /* 10644961713Sgirish * Returns 1 only if the address range of a variable of type type at 10744961713Sgirish * ptr falls entirely on one page. Based on page size of 4K. May 10844961713Sgirish * give some false negatives on larger page sizes. 10944961713Sgirish */ 11044961713Sgirish #define CONTIGUOUS(ptr, type) \ 11144961713Sgirish (((((uint64_t)(ptr)) ^ ((uint64_t)(ptr) + sizeof (type) -1)) \ 11244961713Sgirish & PAGEMASK) == 0) 11344961713Sgirish 11444961713Sgirish /* 11544961713Sgirish * The RNG hardware can send certain internal analog signals to an 11644961713Sgirish * external pin on the chip. Setting the rnc_anlg_sel bit to 11744961713Sgirish * N2RNG_NOANALOGOUT deselects all analog signals (perhaps selects 11844961713Sgirish * ground). Choosing any other value would aid an attacker with 11944961713Sgirish * physical access to the chip. 12044961713Sgirish */ 12144961713Sgirish #define N2RNG_NOANALOGOUT 0x2 12244961713Sgirish 12344961713Sgirish /* 12444961713Sgirish * There can only be N2_RNG_FIPS_INSTANCES concurrent RNG requsts from 12544961713Sgirish * the framework. Making this value large helps benchmarks. It 12644961713Sgirish * should probably come from a conf file, but for now it is hard 12744961713Sgirish * coded. The code computes i % N2RNG_FIPS_INSTANCES, which is more 12844961713Sgirish * efficient when N2RNG_FIPS_INSTANCES is a power of 2. 12944961713Sgirish */ 13044961713Sgirish #define N2RNG_FIPS_INSTANCES 8 13144961713Sgirish 13244961713Sgirish typedef struct fipsrandomstruct fipsrandomstruct_t; 13344961713Sgirish struct fipsrandomstruct { 13444961713Sgirish kmutex_t mtx; 13544961713Sgirish uint64_t entropyhunger; /* RNGs generated with no entropy */ 13644961713Sgirish uint32_t XKEY[6]; /* one extra word for getentropy */ 13744961713Sgirish }; 13844961713Sgirish 13944961713Sgirish typedef struct { 14044961713Sgirish /* 14144961713Sgirish * volatile, since it is not protected by a mutex. (That is 14244961713Sgirish * okay since it is operated on and accessed via atomic ops.) 14344961713Sgirish */ 14444961713Sgirish volatile unsigned int fips_round_robin_j; 14544961713Sgirish fipsrandomstruct_t fipsarray[N2RNG_FIPS_INSTANCES]; 14644961713Sgirish } fips_ensemble_t; 14744961713Sgirish 148*741c280dStwelke /* 149*741c280dStwelke * Device flags (n2rng_t.n_flags) 150*741c280dStwelke */ 151*741c280dStwelke #define N2RNG_CONTROL 0x00000001 152*741c280dStwelke #define N2RNG_FAILED 0x00000002 153*741c280dStwelke #define N2RNG_CONFIGURED 0x00000004 154*741c280dStwelke #define N2RNG_INITIALIZED 0x00000008 155*741c280dStwelke #define N2RNG_REGISTERED 0x00000010 156*741c280dStwelke 157*741c280dStwelke #define n2rng_setcontrol(n2rng) ((n2rng)->n_flags |= N2RNG_CONTROL) 158*741c280dStwelke #define n2rng_clrcontrol(n2rng) ((n2rng)->n_flags &= ~N2RNG_CONTROL) 159*741c280dStwelke #define n2rng_iscontrol(n2rng) ((n2rng)->n_flags & N2RNG_CONTROL) 160*741c280dStwelke 161*741c280dStwelke #define n2rng_setfailed(n2rng) ((n2rng)->n_flags |= N2RNG_FAILED) 162*741c280dStwelke #define n2rng_clrfailed(n2rng) ((n2rng)->n_flags &= ~N2RNG_FAILED) 163*741c280dStwelke #define n2rng_isfailed(n2rng) ((n2rng)->n_flags & N2RNG_FAILED) 164*741c280dStwelke 165*741c280dStwelke #define n2rng_setconfigured(n2rng) ((n2rng)->n_flags |= N2RNG_CONFIGURED) 166*741c280dStwelke #define n2rng_clrconfigured(n2rng) ((n2rng)->n_flags &= ~N2RNG_CONFIGURED) 167*741c280dStwelke #define n2rng_isconfigured(n2rng) ((n2rng)->n_flags & N2RNG_CONFIGURED) 168*741c280dStwelke 169*741c280dStwelke #define n2rng_setinitialized(n2rng) ((n2rng)->n_flags |= N2RNG_INITIALIZED) 170*741c280dStwelke #define n2rng_clrinitialized(n2rng) ((n2rng)->n_flags &= ~N2RNG_INITIALIZED) 171*741c280dStwelke #define n2rng_isinitialized(n2rng) ((n2rng)->n_flags & N2RNG_INITIALIZED) 172*741c280dStwelke 173*741c280dStwelke #define n2rng_setregistered(n2rng) ((n2rng)->n_flags |= N2RNG_REGISTERED) 174*741c280dStwelke #define n2rng_clrregistered(n2rng) ((n2rng)->n_flags &= ~N2RNG_REGISTERED) 175*741c280dStwelke #define n2rng_isregistered(n2rng) ((n2rng)->n_flags & N2RNG_REGISTERED) 17644961713Sgirish 17744961713Sgirish #define DS_RNGBYTES 0 17844961713Sgirish #define DS_RNGJOBS 1 17944961713Sgirish #define DS_RNGHEALTHCHECKS 2 18044961713Sgirish #define DS_MAX 3 18144961713Sgirish 18244961713Sgirish #define N2RNG_NOSC 3 18344961713Sgirish #define N2RNG_BIASBITS 2 18444961713Sgirish #define N2RNG_NBIASES (1 << N2RNG_BIASBITS) 18544961713Sgirish #define N2RNG_CTLOPS (N2RNG_OSC + 1) 18644961713Sgirish 187*741c280dStwelke #define N2RNG_PROP_NUM_UNITS "rng-#units" 188*741c280dStwelke #define SECOND 1000000 /* micro seconds */ 189*741c280dStwelke 19044961713Sgirish typedef struct { 19144961713Sgirish uint64_t numvals; 19244961713Sgirish uint64_t H1; /* in bits per bit << LOG_VAL_SCALE */ 19344961713Sgirish uint64_t H2; 19444961713Sgirish uint64_t Hinf; 19544961713Sgirish } n2rng_osc_perf_t; 19644961713Sgirish 19744961713Sgirish typedef n2rng_osc_perf_t n2rng_osc_perf_table_t[N2RNG_NOSC][N2RNG_NBIASES]; 19844961713Sgirish 199*741c280dStwelke typedef struct { 200*741c280dStwelke uint64_t bias; 201*741c280dStwelke uint64_t entropy; 202*741c280dStwelke } n2rng_bias_info_t; 203*741c280dStwelke 204*741c280dStwelke typedef struct { 205*741c280dStwelke n2rng_bias_info_t n_bias_info[N2RNG_NOSC]; 206*741c280dStwelke n2rng_osc_perf_table_t n_perftable; 207*741c280dStwelke n2rng_setup_t n_preferred_config; 208*741c280dStwelke uint64_t n_rng_state; /* as last known in this drvr. */ 209*741c280dStwelke } rng_entry_t; 210*741c280dStwelke 211*741c280dStwelke typedef struct { 212*741c280dStwelke int n_num_rngs; 213*741c280dStwelke int n_num_rngs_online; 214*741c280dStwelke rng_entry_t *n_rngs; 215*741c280dStwelke clock_t n_hc_secs; 216*741c280dStwelke uint64_t n_watchdog_cycles; 217*741c280dStwelke uint64_t n_accumulate_cycles; 218*741c280dStwelke } rng_ctl_data_t; 21944961713Sgirish 22044961713Sgirish typedef struct n2rng { 22144961713Sgirish kmutex_t n_lock; 22244961713Sgirish dev_info_t *n_dip; 22344961713Sgirish unsigned n_flags; /* dev state flags */ 224*741c280dStwelke uint_t n_hvapi_major_version; 225*741c280dStwelke uint_t n_hvapi_minor_version; 226*741c280dStwelke n2rng_binding_t n_binding; 227*741c280dStwelke char *n_binding_name; 228*741c280dStwelke rng_ctl_data_t *n_ctl_data; /* Only valid in ctl domain */ 22944961713Sgirish kstat_t *n_ksp; 23044961713Sgirish uint64_t n_stats[DS_MAX]; 23144961713Sgirish crypto_kcf_provider_handle_t n_prov; 23244961713Sgirish fips_ensemble_t n_frs; 233*741c280dStwelke timeout_id_t n_timeout_id; 234*741c280dStwelke md_t *n_mdp; 23544961713Sgirish uint64_t n_sticks_per_usec; 23659ac0c16Sdavemq ddi_taskq_t *n_taskq; 23744961713Sgirish } n2rng_t; 23844961713Sgirish 239*741c280dStwelke typedef kstat_named_t n2rng_kstat_bias_t[N2RNG_NOSC][N2RNG_NBIASES]; 24044961713Sgirish 24144961713Sgirish typedef struct n2rng_stat n2rng_stat_t; 24244961713Sgirish struct n2rng_stat { 24344961713Sgirish kstat_named_t ns_status; 24444961713Sgirish kstat_named_t ns_algs[DS_MAX]; 245*741c280dStwelke kstat_named_t ns_rngstate[N2RNG_MAX_RNGS]; 246*741c280dStwelke n2rng_kstat_bias_t ns_rngbias; 247*741c280dStwelke n2rng_kstat_bias_t ns_rngentropy; 24844961713Sgirish }; 24944961713Sgirish 25044961713Sgirish #define RNG_MODE_NORMAL 1 25144961713Sgirish #define RNG_MODE_DIAGNOSTIC 0 25244961713Sgirish 25344961713Sgirish #define RNG_DIAG_CHUNK_SIZE (N2RNG_MAX_READ / 8) /* as words */ 25444961713Sgirish #define RNG_MAX_DATA_READ_ATTEMPTS 100 25544961713Sgirish #define RNG_RETRY_HLCHK_USECS 100000 /* retry every .1 seconds */ 25644961713Sgirish 257*741c280dStwelke #define RNG_MAX_LOGIC_TEST_ATTEMPTS 3 258*741c280dStwelke #define RNG_MAX_BUSY_ATTEMPTS 100 259*741c280dStwelke #define RNG_MAX_BLOCK_ATTEMPTS 50000 260*741c280dStwelke #define RNG_RETRY_BUSY_DELAY 1 261*741c280dStwelke 262*741c280dStwelke #define RNG_DEFAULT_ACCUMULATE_CYCLES 2048 263*741c280dStwelke #define RNG_CFG_RETRY_SECS 60 /* seconds between cfg retries */ 264*741c280dStwelke 265*741c280dStwelke #define RNG_DEFAULT_HC_SECS 0 /* seconds between health checks */ 266*741c280dStwelke #define RNG_EXTRA_WATCHDOG_SECS 60 /* added to hc time for watchdog */ 267*741c280dStwelke 26844961713Sgirish #define LOG_ARG_SCALE 49 26944961713Sgirish #define LOG_VAL_SCALE 32 27044961713Sgirish 27144961713Sgirish void n2rng_sort(uint64_t *data, int log2_size); 272*741c280dStwelke int n2rng_noise_gen_preferred(n2rng_t *n2rng, int rngid); 273*741c280dStwelke int n2rng_config_test(n2rng_t *n2rng); 274*741c280dStwelke int n2rng_collect_diag_bits(n2rng_t *n2rng, int rngid, 275*741c280dStwelke n2rng_setup_t *collect_setupp, void *buffer, int numbytes, 276*741c280dStwelke n2rng_setup_t *exit_setupp, uint64_t exitstate); 27744961713Sgirish int n2rng_getentropy(n2rng_t *n2rng, void *buffer, size_t size); 27844961713Sgirish int n2rng_fips_random_init(n2rng_t *n2rng, fipsrandomstruct_t *frsp); 27944961713Sgirish void n2rng_fips_random_fini(fipsrandomstruct_t *frsp); 280*741c280dStwelke int n2rng_do_health_check(n2rng_t *n2rng, int rngid); 28144961713Sgirish void n2rng_renyi_entropy(uint64_t *buffer, int log2samples, 28244961713Sgirish n2rng_osc_perf_t *metricp); 283*741c280dStwelke uint64_t n2rng_read_ctl(n2rng_t *n2rng, int rngid, uint64_t ctlregs_pa, 284*741c280dStwelke uint64_t *state, uint64_t *tdelta, uint64_t *wdelta); 285*741c280dStwelke uint64_t n2rng_ctl_wait(n2rng_t *n2rng, int rngid); 286*741c280dStwelke uint64_t n2rng_ctl_write(n2rng_t *n2rng, int rngid, uint64_t ctlregs_pa, 287*741c280dStwelke uint64_t newstate, uint64_t wtimeout, uint64_t *tdelta); 288*741c280dStwelke uint64_t n2rng_data_read_diag(n2rng_t *n2rng, int rngid, uint64_t data_pa, 289*741c280dStwelke size_t datalen, uint64_t *tdelta); 290*741c280dStwelke uint64_t n2rng_check_ctl_access(n2rng_t *n2rng); 291*741c280dStwelke void n2rng_config_retry(n2rng_t *n2rng, clock_t seconds); 29244961713Sgirish 29344961713Sgirish #if defined(DEBUG) 29444961713Sgirish 29544961713Sgirish #define DWARN 0x00000001 29644961713Sgirish #define DMA_ARGS 0x00000002 29744961713Sgirish #define DMA_LDST 0x00000004 29844961713Sgirish #define DNCS_QTAIL 0x00000008 29944961713Sgirish #define DATTACH 0x00000010 300*741c280dStwelke #define DCFG 0x00000020 30144961713Sgirish #define DMOD 0x00000040 /* _init/_fini/_info/attach/detach */ 30244961713Sgirish #define DENTRY 0x00000080 /* crypto routine entry/exit points */ 303*741c280dStwelke #define DHEALTH 0x00000100 304*741c280dStwelke #define DCHATTY 0x00000200 305*741c280dStwelke #define DKCF 0x00000400 30644961713Sgirish #define DALL 0xFFFFFFFF 30744961713Sgirish 30844961713Sgirish #define DBG0 n2rng_dprintf 30944961713Sgirish #define DBG1 n2rng_dprintf 31044961713Sgirish #define DBG2 n2rng_dprintf 31144961713Sgirish #define DBG3 n2rng_dprintf 31244961713Sgirish #define DBG4 n2rng_dprintf 31344961713Sgirish #define DBG5 n2rng_dprintf 31444961713Sgirish #define DBG6 n2rng_dprintf 31544961713Sgirish #define DBGCALL(flag, func) { if (n2rng_dflagset(flag)) (void) func; } 31644961713Sgirish 31744961713Sgirish void n2rng_dprintf(n2rng_t *, int, const char *, ...); 31844961713Sgirish void n2rng_dumphex(void *, int); 31944961713Sgirish int n2rng_dflagset(int); 32044961713Sgirish 32144961713Sgirish #else /* !defined(DEBUG) */ 32244961713Sgirish 32344961713Sgirish #define DBG0(vca, lvl, fmt) 32444961713Sgirish #define DBG1(vca, lvl, fmt, arg1) 32544961713Sgirish #define DBG2(vca, lvl, fmt, arg1, arg2) 32644961713Sgirish #define DBG3(vca, lvl, fmt, arg1, arg2, arg3) 32744961713Sgirish #define DBG4(vca, lvl, fmt, arg1, arg2, arg3, arg4) 32844961713Sgirish #define DBG5(vca, lvl, fmt, arg1, arg2, arg3, arg4, arg5) 32944961713Sgirish #define DBG6(vca, lvl, fmt, arg1, arg2, arg3, arg4, arg5, arg6) 33044961713Sgirish #define DBGCALL(flag, func) 33144961713Sgirish 33244961713Sgirish #endif /* !defined(DEBUG) */ 33344961713Sgirish 33444961713Sgirish /* 335*741c280dStwelke * n2rng_kcf.c 336*741c280dStwelke */ 337*741c280dStwelke int n2rng_herr2kerr(uint64_t); 338*741c280dStwelke int n2rng_logic_test(n2rng_t *, int); 339*741c280dStwelke int n2rng_noise_gen_test_set(void); 340*741c280dStwelke int n2rng_init(n2rng_t *n2rng); 341*741c280dStwelke int n2rng_uninit(n2rng_t *n2rng); 342*741c280dStwelke int n2rng_register_provider(n2rng_t *n2rng); 343*741c280dStwelke int n2rng_unregister_provider(n2rng_t *n2rng); 344*741c280dStwelke void n2rng_failure(n2rng_t *n2rng); 345*741c280dStwelke void n2rng_unconfigured(n2rng_t *n2rng); 346*741c280dStwelke 347*741c280dStwelke /* 34844961713Sgirish * n2rng_debug.c 34944961713Sgirish */ 35044961713Sgirish void n2rng_error(n2rng_t *, const char *, ...); 35144961713Sgirish void n2rng_diperror(dev_info_t *, const char *, ...); 35244961713Sgirish void n2rng_dipverror(dev_info_t *, const char *, va_list); 35344961713Sgirish 35444961713Sgirish uint64_t hv_rng_get_diag_control(void); 355*741c280dStwelke uint64_t hv_rng_ctl_read(uint64_t ctlregs_pa, uint64_t *state, 35644961713Sgirish uint64_t *tdelta); 357*741c280dStwelke uint64_t hv_rng_ctl_read_v2(uint64_t ctlregs_pa, uint64_t rngid, 358*741c280dStwelke uint64_t *state, uint64_t *tdelta, uint64_t *wdelta, uint64_t *wstate); 35944961713Sgirish uint64_t hv_rng_ctl_write(uint64_t ctlregs_pa, 36044961713Sgirish uint64_t newstate, uint64_t wtimeout, uint64_t *tdelta); 361*741c280dStwelke uint64_t hv_rng_ctl_write_v2(uint64_t ctlregs_pa, 362*741c280dStwelke uint64_t newstate, uint64_t wtimeout, uint64_t rngid); 36344961713Sgirish uint64_t hv_rng_data_read_diag(uint64_t data_pa, 36444961713Sgirish size_t datalen, uint64_t *tdelta); 365*741c280dStwelke uint64_t hv_rng_data_read_diag_v2(uint64_t data_pa, 366*741c280dStwelke size_t datalen, uint64_t rngid, uint64_t *tdelta); 36744961713Sgirish uint64_t hv_rng_data_read(uint64_t data_pa, uint64_t *tdelta); 36844961713Sgirish 36944961713Sgirish #endif /* _KERNEL */ 37044961713Sgirish #endif /* !_ASM */ 37144961713Sgirish 37244961713Sgirish #ifdef __cplusplus 37344961713Sgirish } 37444961713Sgirish #endif 37544961713Sgirish 37644961713Sgirish #endif /* _SYS_N2RNG_H */ 377