13156Sgirish /* 23156Sgirish * CDDL HEADER START 33156Sgirish * 43156Sgirish * The contents of this file are subject to the terms of the 53156Sgirish * Common Development and Distribution License (the "License"). 63156Sgirish * You may not use this file except in compliance with the License. 73156Sgirish * 83156Sgirish * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 93156Sgirish * or http://www.opensolaris.org/os/licensing. 103156Sgirish * See the License for the specific language governing permissions 113156Sgirish * and limitations under the License. 123156Sgirish * 133156Sgirish * When distributing Covered Code, include this CDDL HEADER in each 143156Sgirish * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 153156Sgirish * If applicable, add the following below this CDDL HEADER, with the 163156Sgirish * fields enclosed by brackets "[]" replaced with your own identifying 173156Sgirish * information: Portions Copyright [yyyy] [name of copyright owner] 183156Sgirish * 193156Sgirish * CDDL HEADER END 203156Sgirish */ 213156Sgirish /* 22*12929SMisaki.Miyashita@Oracle.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. 233156Sgirish */ 243156Sgirish 253156Sgirish #ifndef _SYS_N2RNG_H 263156Sgirish #define _SYS_N2RNG_H 273156Sgirish 283156Sgirish /* skip following stuff when included in n2rng_hcall.s */ 293156Sgirish #ifndef _ASM 303156Sgirish #include <sys/types.h> 313156Sgirish #include <sys/mutex.h> 323156Sgirish #include <sys/ksynch.h> 333156Sgirish #include <sys/sunddi.h> 343156Sgirish #include <sys/param.h> 353156Sgirish #include <sys/crypto/common.h> 363156Sgirish #include <sys/crypto/spi.h> 375650Stwelke #include <sys/mdesc.h> 383156Sgirish 393156Sgirish #endif /* !_ASM */ 403156Sgirish 413156Sgirish #ifdef __cplusplus 423156Sgirish extern "C" { 433156Sgirish #endif 443156Sgirish 453156Sgirish #define HV_RNG_GET_DIAG_CONTROL 0x130 463156Sgirish #define HV_RNG_CTL_READ 0x131 473156Sgirish #define HV_RNG_CTL_WRITE 0x132 483156Sgirish #define HV_RNG_DATA_READ_DIAG 0x133 493156Sgirish #define HV_RNG_DATA_READ 0x134 503156Sgirish 513156Sgirish #define CTL_STATE_UNCONFIGURED 0 523156Sgirish #define CTL_STATE_CONFIGURED 1 533156Sgirish #define CTL_STATE_HEALTHCHECK 2 543156Sgirish #define CTL_STATE_ERROR 3 553156Sgirish 563156Sgirish #define NRNGCTL 4 573156Sgirish #define N2RNG_MAX_READ (128 * 1024) /* 128K bytes */ 583156Sgirish 593156Sgirish #define DRIVER "n2rng" 603156Sgirish #define N2RNG_MANUFACTURER_ID "SUNWn2rng" 613156Sgirish 625650Stwelke #define N2RNG_BINDNAME_N2 "SUNW,n2-rng" 635650Stwelke #define N2RNG_BINDNAME_VF "SUNW,vf-rng" 6411304SJanie.Lu@Sun.COM #define N2RNG_BINDNAME_KT "SUNW,kt-rng" 655650Stwelke 665650Stwelke #define N2RNG_MAX_RNGS 4 675650Stwelke #define N2RNG_INVALID_ID (-1) 683156Sgirish 693156Sgirish #ifndef _ASM 703156Sgirish 715650Stwelke typedef enum { 725650Stwelke N2RNG_CPU_UNKNOWN, 735650Stwelke N2RNG_CPU_N2, 7411304SJanie.Lu@Sun.COM N2RNG_CPU_VF, 7511304SJanie.Lu@Sun.COM N2RNG_CPU_KT 765650Stwelke } n2rng_binding_t; 775650Stwelke 783156Sgirish typedef union n2rngctl { 793156Sgirish uint64_t word; 803156Sgirish struct { 813156Sgirish uint64_t rnc_res : 39; 823156Sgirish uint64_t rnc_cnt : 16; 833156Sgirish uint64_t rnc_bypass : 1; 843156Sgirish uint64_t rnc_vcoctl : 2; 853156Sgirish uint64_t rnc_anlg_sel : 2; 863156Sgirish uint64_t rnc_mode : 1; 873156Sgirish uint64_t rnc_selbits : 3; 883156Sgirish } fields; 893156Sgirish } n2rng_ctl_t; 903156Sgirish 913156Sgirish typedef struct { 923156Sgirish n2rng_ctl_t ctlwds[NRNGCTL]; 933156Sgirish } n2rng_setup_t; 943156Sgirish 953156Sgirish #if defined(_KERNEL) 963156Sgirish 973156Sgirish /* 983156Sgirish * Our contiguous memory alignment requirement is 993156Sgirish * only for 8 bytes, however contig mem allocation 1003156Sgirish * routines requirement minimum of 64. 1013156Sgirish */ 1023156Sgirish #define CONTIG_ALIGNMENT 64 1035650Stwelke 1043156Sgirish /* 1053156Sgirish * Returns 1 only if the address range of a variable of type type at 1063156Sgirish * ptr falls entirely on one page. Based on page size of 4K. May 1073156Sgirish * give some false negatives on larger page sizes. 1083156Sgirish */ 1093156Sgirish #define CONTIGUOUS(ptr, type) \ 1103156Sgirish (((((uint64_t)(ptr)) ^ ((uint64_t)(ptr) + sizeof (type) -1)) \ 1113156Sgirish & PAGEMASK) == 0) 1123156Sgirish 1133156Sgirish /* 1143156Sgirish * The RNG hardware can send certain internal analog signals to an 1153156Sgirish * external pin on the chip. Setting the rnc_anlg_sel bit to 1163156Sgirish * N2RNG_NOANALOGOUT deselects all analog signals (perhaps selects 1173156Sgirish * ground). Choosing any other value would aid an attacker with 1183156Sgirish * physical access to the chip. 1193156Sgirish */ 1203156Sgirish #define N2RNG_NOANALOGOUT 0x2 1213156Sgirish 1223156Sgirish /* 123*12929SMisaki.Miyashita@Oracle.COM * n2rng: config variable in the n2rng.conf file 124*12929SMisaki.Miyashita@Oracle.COM */ 125*12929SMisaki.Miyashita@Oracle.COM #define N2RNG_FIPS_STRING "n2rng-fips-140" 126*12929SMisaki.Miyashita@Oracle.COM 127*12929SMisaki.Miyashita@Oracle.COM /* 1283156Sgirish * There can only be N2_RNG_FIPS_INSTANCES concurrent RNG requsts from 1293156Sgirish * the framework. Making this value large helps benchmarks. It 1303156Sgirish * should probably come from a conf file, but for now it is hard 1313156Sgirish * coded. The code computes i % N2RNG_FIPS_INSTANCES, which is more 1323156Sgirish * efficient when N2RNG_FIPS_INSTANCES is a power of 2. 1333156Sgirish */ 1343156Sgirish #define N2RNG_FIPS_INSTANCES 8 1353156Sgirish 1363156Sgirish typedef struct fipsrandomstruct fipsrandomstruct_t; 1373156Sgirish struct fipsrandomstruct { 1383156Sgirish kmutex_t mtx; 1393156Sgirish uint64_t entropyhunger; /* RNGs generated with no entropy */ 1403156Sgirish uint32_t XKEY[6]; /* one extra word for getentropy */ 141*12929SMisaki.Miyashita@Oracle.COM uint32_t x_jminus1[5]; /* store the last output */ 1423156Sgirish }; 1433156Sgirish 1443156Sgirish typedef struct { 1453156Sgirish /* 1463156Sgirish * volatile, since it is not protected by a mutex. (That is 1473156Sgirish * okay since it is operated on and accessed via atomic ops.) 1483156Sgirish */ 1493156Sgirish volatile unsigned int fips_round_robin_j; 1503156Sgirish fipsrandomstruct_t fipsarray[N2RNG_FIPS_INSTANCES]; 1513156Sgirish } fips_ensemble_t; 1523156Sgirish 1535650Stwelke /* 1545650Stwelke * Device flags (n2rng_t.n_flags) 1555650Stwelke */ 1565650Stwelke #define N2RNG_CONTROL 0x00000001 1575650Stwelke #define N2RNG_FAILED 0x00000002 1585650Stwelke #define N2RNG_CONFIGURED 0x00000004 1595650Stwelke #define N2RNG_INITIALIZED 0x00000008 1605650Stwelke #define N2RNG_REGISTERED 0x00000010 1615650Stwelke 1625650Stwelke #define n2rng_setcontrol(n2rng) ((n2rng)->n_flags |= N2RNG_CONTROL) 1635650Stwelke #define n2rng_clrcontrol(n2rng) ((n2rng)->n_flags &= ~N2RNG_CONTROL) 1645650Stwelke #define n2rng_iscontrol(n2rng) ((n2rng)->n_flags & N2RNG_CONTROL) 1655650Stwelke 1665650Stwelke #define n2rng_setfailed(n2rng) ((n2rng)->n_flags |= N2RNG_FAILED) 1675650Stwelke #define n2rng_clrfailed(n2rng) ((n2rng)->n_flags &= ~N2RNG_FAILED) 1685650Stwelke #define n2rng_isfailed(n2rng) ((n2rng)->n_flags & N2RNG_FAILED) 1695650Stwelke 1705650Stwelke #define n2rng_setconfigured(n2rng) ((n2rng)->n_flags |= N2RNG_CONFIGURED) 1715650Stwelke #define n2rng_clrconfigured(n2rng) ((n2rng)->n_flags &= ~N2RNG_CONFIGURED) 1725650Stwelke #define n2rng_isconfigured(n2rng) ((n2rng)->n_flags & N2RNG_CONFIGURED) 1735650Stwelke 1745650Stwelke #define n2rng_setinitialized(n2rng) ((n2rng)->n_flags |= N2RNG_INITIALIZED) 1755650Stwelke #define n2rng_clrinitialized(n2rng) ((n2rng)->n_flags &= ~N2RNG_INITIALIZED) 1765650Stwelke #define n2rng_isinitialized(n2rng) ((n2rng)->n_flags & N2RNG_INITIALIZED) 1775650Stwelke 1785650Stwelke #define n2rng_setregistered(n2rng) ((n2rng)->n_flags |= N2RNG_REGISTERED) 1795650Stwelke #define n2rng_clrregistered(n2rng) ((n2rng)->n_flags &= ~N2RNG_REGISTERED) 1805650Stwelke #define n2rng_isregistered(n2rng) ((n2rng)->n_flags & N2RNG_REGISTERED) 1813156Sgirish 1823156Sgirish #define DS_RNGBYTES 0 1833156Sgirish #define DS_RNGJOBS 1 1843156Sgirish #define DS_RNGHEALTHCHECKS 2 1853156Sgirish #define DS_MAX 3 1863156Sgirish 1873156Sgirish #define N2RNG_NOSC 3 1883156Sgirish #define N2RNG_BIASBITS 2 1893156Sgirish #define N2RNG_NBIASES (1 << N2RNG_BIASBITS) 1903156Sgirish #define N2RNG_CTLOPS (N2RNG_OSC + 1) 1913156Sgirish 1925650Stwelke #define N2RNG_PROP_NUM_UNITS "rng-#units" 1935650Stwelke #define SECOND 1000000 /* micro seconds */ 1945650Stwelke 1953156Sgirish typedef struct { 1963156Sgirish uint64_t numvals; 1973156Sgirish uint64_t H1; /* in bits per bit << LOG_VAL_SCALE */ 1983156Sgirish uint64_t H2; 1993156Sgirish uint64_t Hinf; 2003156Sgirish } n2rng_osc_perf_t; 2013156Sgirish 2023156Sgirish typedef n2rng_osc_perf_t n2rng_osc_perf_table_t[N2RNG_NOSC][N2RNG_NBIASES]; 2033156Sgirish 2045650Stwelke typedef struct { 2055650Stwelke uint64_t bias; 2065650Stwelke uint64_t entropy; 2075650Stwelke } n2rng_bias_info_t; 2085650Stwelke 2095650Stwelke typedef struct { 2105650Stwelke n2rng_bias_info_t n_bias_info[N2RNG_NOSC]; 2115650Stwelke n2rng_osc_perf_table_t n_perftable; 2125650Stwelke n2rng_setup_t n_preferred_config; 2135650Stwelke uint64_t n_rng_state; /* as last known in this drvr. */ 2145650Stwelke } rng_entry_t; 2155650Stwelke 2165650Stwelke typedef struct { 2175650Stwelke int n_num_rngs; 2185650Stwelke int n_num_rngs_online; 2195650Stwelke rng_entry_t *n_rngs; 2205650Stwelke clock_t n_hc_secs; 2215650Stwelke uint64_t n_watchdog_cycles; 2225650Stwelke uint64_t n_accumulate_cycles; 2235650Stwelke } rng_ctl_data_t; 2243156Sgirish 2253156Sgirish typedef struct n2rng { 2263156Sgirish kmutex_t n_lock; 2273156Sgirish dev_info_t *n_dip; 2283156Sgirish unsigned n_flags; /* dev state flags */ 2295650Stwelke uint_t n_hvapi_major_version; 2305650Stwelke uint_t n_hvapi_minor_version; 2315650Stwelke n2rng_binding_t n_binding; 2325650Stwelke char *n_binding_name; 2335650Stwelke rng_ctl_data_t *n_ctl_data; /* Only valid in ctl domain */ 2343156Sgirish kstat_t *n_ksp; 2353156Sgirish uint64_t n_stats[DS_MAX]; 2363156Sgirish crypto_kcf_provider_handle_t n_prov; 2373156Sgirish fips_ensemble_t n_frs; 2385650Stwelke timeout_id_t n_timeout_id; 2395650Stwelke md_t *n_mdp; 2403156Sgirish uint64_t n_sticks_per_usec; 2414732Sdavemq ddi_taskq_t *n_taskq; 242*12929SMisaki.Miyashita@Oracle.COM boolean_t n_is_fips; 2433156Sgirish } n2rng_t; 2443156Sgirish 2459961SAn.Bui@Sun.COM typedef kstat_named_t n2rng_kstat_bias_t[N2RNG_MAX_RNGS][N2RNG_NOSC]; 2463156Sgirish 2473156Sgirish typedef struct n2rng_stat n2rng_stat_t; 2483156Sgirish struct n2rng_stat { 2493156Sgirish kstat_named_t ns_status; 2503156Sgirish kstat_named_t ns_algs[DS_MAX]; 2515650Stwelke kstat_named_t ns_rngstate[N2RNG_MAX_RNGS]; 2525650Stwelke n2rng_kstat_bias_t ns_rngbias; 2535650Stwelke n2rng_kstat_bias_t ns_rngentropy; 2543156Sgirish }; 2553156Sgirish 2565650Stwelke #define RNG_MODE_NORMAL 1 2575650Stwelke #define RNG_MODE_DIAGNOSTIC 0 2583156Sgirish 2595650Stwelke #define RNG_DIAG_CHUNK_SIZE (N2RNG_MAX_READ / 8) /* as words */ 2603156Sgirish #define RNG_MAX_DATA_READ_ATTEMPTS 100 2615650Stwelke #define RNG_RETRY_HLCHK_USECS 100000 /* retry every .1 seconds */ 2625650Stwelke 2635650Stwelke #define RNG_MAX_LOGIC_TEST_ATTEMPTS 3 2645650Stwelke #define RNG_MAX_BUSY_ATTEMPTS 100 2655650Stwelke #define RNG_MAX_BLOCK_ATTEMPTS 50000 2665650Stwelke #define RNG_RETRY_BUSY_DELAY 1 2673156Sgirish 2685650Stwelke #define RNG_DEFAULT_ACCUMULATE_CYCLES 2048 2695650Stwelke #define RNG_CFG_RETRY_SECS 60 /* seconds between cfg retries */ 2703156Sgirish 2715650Stwelke #define RNG_DEFAULT_HC_SECS 0 /* seconds between health checks */ 2725650Stwelke #define RNG_EXTRA_WATCHDOG_SECS 60 /* added to hc time for watchdog */ 2735650Stwelke 2745650Stwelke #define LOG_ARG_SCALE 49 2755650Stwelke #define LOG_VAL_SCALE 32 2763156Sgirish 2773156Sgirish void n2rng_sort(uint64_t *data, int log2_size); 2785650Stwelke int n2rng_noise_gen_preferred(n2rng_t *n2rng, int rngid); 2795650Stwelke int n2rng_config_test(n2rng_t *n2rng); 2805650Stwelke int n2rng_collect_diag_bits(n2rng_t *n2rng, int rngid, 2815650Stwelke n2rng_setup_t *collect_setupp, void *buffer, int numbytes, 2825650Stwelke n2rng_setup_t *exit_setupp, uint64_t exitstate); 2833156Sgirish int n2rng_getentropy(n2rng_t *n2rng, void *buffer, size_t size); 2843156Sgirish int n2rng_fips_random_init(n2rng_t *n2rng, fipsrandomstruct_t *frsp); 2853156Sgirish void n2rng_fips_random_fini(fipsrandomstruct_t *frsp); 2865650Stwelke int n2rng_do_health_check(n2rng_t *n2rng, int rngid); 2873156Sgirish void n2rng_renyi_entropy(uint64_t *buffer, int log2samples, 2883156Sgirish n2rng_osc_perf_t *metricp); 2895650Stwelke uint64_t n2rng_read_ctl(n2rng_t *n2rng, int rngid, uint64_t ctlregs_pa, 2905650Stwelke uint64_t *state, uint64_t *tdelta, uint64_t *wdelta); 2915650Stwelke uint64_t n2rng_ctl_wait(n2rng_t *n2rng, int rngid); 2925650Stwelke uint64_t n2rng_ctl_write(n2rng_t *n2rng, int rngid, uint64_t ctlregs_pa, 2935650Stwelke uint64_t newstate, uint64_t wtimeout, uint64_t *tdelta); 2945650Stwelke uint64_t n2rng_data_read_diag(n2rng_t *n2rng, int rngid, uint64_t data_pa, 2955650Stwelke size_t datalen, uint64_t *tdelta); 2965650Stwelke uint64_t n2rng_check_ctl_access(n2rng_t *n2rng); 2975650Stwelke void n2rng_config_retry(n2rng_t *n2rng, clock_t seconds); 2983156Sgirish 2993156Sgirish #if defined(DEBUG) 3003156Sgirish 3013156Sgirish #define DWARN 0x00000001 3023156Sgirish #define DMA_ARGS 0x00000002 3033156Sgirish #define DMA_LDST 0x00000004 3043156Sgirish #define DNCS_QTAIL 0x00000008 3053156Sgirish #define DATTACH 0x00000010 3065650Stwelke #define DCFG 0x00000020 3073156Sgirish #define DMOD 0x00000040 /* _init/_fini/_info/attach/detach */ 3083156Sgirish #define DENTRY 0x00000080 /* crypto routine entry/exit points */ 3095650Stwelke #define DHEALTH 0x00000100 3105650Stwelke #define DCHATTY 0x00000200 3115650Stwelke #define DKCF 0x00000400 3123156Sgirish #define DALL 0xFFFFFFFF 3133156Sgirish 3143156Sgirish #define DBG0 n2rng_dprintf 3153156Sgirish #define DBG1 n2rng_dprintf 3163156Sgirish #define DBG2 n2rng_dprintf 3173156Sgirish #define DBG3 n2rng_dprintf 3183156Sgirish #define DBG4 n2rng_dprintf 3193156Sgirish #define DBG5 n2rng_dprintf 3203156Sgirish #define DBG6 n2rng_dprintf 3213156Sgirish #define DBGCALL(flag, func) { if (n2rng_dflagset(flag)) (void) func; } 3223156Sgirish 3233156Sgirish void n2rng_dprintf(n2rng_t *, int, const char *, ...); 3243156Sgirish void n2rng_dumphex(void *, int); 3253156Sgirish int n2rng_dflagset(int); 3263156Sgirish 3273156Sgirish #else /* !defined(DEBUG) */ 3283156Sgirish 3293156Sgirish #define DBG0(vca, lvl, fmt) 3303156Sgirish #define DBG1(vca, lvl, fmt, arg1) 3313156Sgirish #define DBG2(vca, lvl, fmt, arg1, arg2) 3323156Sgirish #define DBG3(vca, lvl, fmt, arg1, arg2, arg3) 3333156Sgirish #define DBG4(vca, lvl, fmt, arg1, arg2, arg3, arg4) 3343156Sgirish #define DBG5(vca, lvl, fmt, arg1, arg2, arg3, arg4, arg5) 3353156Sgirish #define DBG6(vca, lvl, fmt, arg1, arg2, arg3, arg4, arg5, arg6) 3363156Sgirish #define DBGCALL(flag, func) 3373156Sgirish 3383156Sgirish #endif /* !defined(DEBUG) */ 3393156Sgirish 3403156Sgirish /* 3415650Stwelke * n2rng_kcf.c 3425650Stwelke */ 3435650Stwelke int n2rng_herr2kerr(uint64_t); 3445650Stwelke int n2rng_logic_test(n2rng_t *, int); 3455650Stwelke int n2rng_noise_gen_test_set(void); 3465650Stwelke int n2rng_init(n2rng_t *n2rng); 3475650Stwelke int n2rng_uninit(n2rng_t *n2rng); 3485650Stwelke int n2rng_register_provider(n2rng_t *n2rng); 3495650Stwelke int n2rng_unregister_provider(n2rng_t *n2rng); 3505650Stwelke void n2rng_failure(n2rng_t *n2rng); 3515650Stwelke void n2rng_unconfigured(n2rng_t *n2rng); 3525650Stwelke 3535650Stwelke /* 3543156Sgirish * n2rng_debug.c 3553156Sgirish */ 3565650Stwelke void n2rng_error(n2rng_t *, const char *, ...); 3575650Stwelke void n2rng_diperror(dev_info_t *, const char *, ...); 3585650Stwelke void n2rng_dipverror(dev_info_t *, const char *, va_list); 3593156Sgirish 3603156Sgirish uint64_t hv_rng_get_diag_control(void); 3615650Stwelke uint64_t hv_rng_ctl_read(uint64_t ctlregs_pa, uint64_t *state, 3623156Sgirish uint64_t *tdelta); 3635650Stwelke uint64_t hv_rng_ctl_read_v2(uint64_t ctlregs_pa, uint64_t rngid, 3645650Stwelke uint64_t *state, uint64_t *tdelta, uint64_t *wdelta, uint64_t *wstate); 3653156Sgirish uint64_t hv_rng_ctl_write(uint64_t ctlregs_pa, 3663156Sgirish uint64_t newstate, uint64_t wtimeout, uint64_t *tdelta); 3675650Stwelke uint64_t hv_rng_ctl_write_v2(uint64_t ctlregs_pa, 3685650Stwelke uint64_t newstate, uint64_t wtimeout, uint64_t rngid); 3693156Sgirish uint64_t hv_rng_data_read_diag(uint64_t data_pa, 3703156Sgirish size_t datalen, uint64_t *tdelta); 3715650Stwelke uint64_t hv_rng_data_read_diag_v2(uint64_t data_pa, 3725650Stwelke size_t datalen, uint64_t rngid, uint64_t *tdelta); 3733156Sgirish uint64_t hv_rng_data_read(uint64_t data_pa, uint64_t *tdelta); 3743156Sgirish 375*12929SMisaki.Miyashita@Oracle.COM /* 376*12929SMisaki.Miyashita@Oracle.COM * n2rng_post.c 377*12929SMisaki.Miyashita@Oracle.COM */ 378*12929SMisaki.Miyashita@Oracle.COM int n2rng_fips_rng_post(void); 379*12929SMisaki.Miyashita@Oracle.COM 3803156Sgirish #endif /* _KERNEL */ 3813156Sgirish #endif /* !_ASM */ 3823156Sgirish 3833156Sgirish #ifdef __cplusplus 3843156Sgirish } 3853156Sgirish #endif 3863156Sgirish 3873156Sgirish #endif /* _SYS_N2RNG_H */ 388