⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 i810_rng.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 2 页
字号:
		printk (KERN_INFO PFX "entropy bits now %d\n", rng_entropy_sysctl);	} else {		printk (KERN_INFO PFX "ignoring invalid entropy setting (%d)\n",			rng_entropy_sysctl);	}out:	DPRINTK ("EXIT, returning 0\n");	return 0;}/* * rng_handle_sysctl_interval - handle a read or write of our timer interval len sysctl */static int rng_handle_sysctl_interval (ctl_table * table, int write, struct file *filp,				      void *buffer, size_t * lenp){	int timer_len_save, rc;	DPRINTK ("ENTER\n");	spin_lock_bh (&rng_lock);	rng_interval_sysctl = timer_len_save = rng_timer_len;	spin_unlock_bh (&rng_lock);	rc = proc_dointvec (table, write, filp, buffer, lenp);	if (rc)		return rc;	if (timer_len_save == rng_interval_sysctl)		goto out;	if ((rng_interval_sysctl > 0) &&    	    (rng_interval_sysctl < (HZ*86400))) {		spin_lock_bh (&rng_lock);		rng_timer_len = rng_interval_sysctl;		spin_unlock_bh (&rng_lock);		printk (KERN_INFO PFX "timer interval now %d\n", rng_interval_sysctl);	} else {		printk (KERN_INFO PFX "ignoring invalid timer interval (%d)\n",			rng_interval_sysctl);	}out:	DPRINTK ("EXIT, returning 0\n");	return 0;}/* * rng_sysctl - add or remove the rng sysctl */static void rng_sysctl (int add){#define DEV_I810_TIMER		1#define DEV_I810_ENTROPY	2#define DEV_I810_INTERVAL	3	/* Definition of the sysctl */	/* FIXME: use new field:value style of struct initialization */	static ctl_table rng_sysctls[] = {		{DEV_I810_TIMER,		/* ID */		 RNG_MODULE_NAME "_timer",	/* name in /proc */		 &rng_enabled_sysctl,		 sizeof (rng_enabled_sysctl),	/* data ptr, data size */		 0644,				/* mode */		 0,				/* child */		 rng_handle_sysctl_enable,	/* proc handler */		 0,				/* strategy */		 0,				/* proc control block */		 0, 0}		,		{DEV_I810_ENTROPY,		/* ID */		 RNG_MODULE_NAME "_entropy",	/* name in /proc */		 &rng_entropy_sysctl,		 sizeof (rng_entropy_sysctl),	/* data ptr, data size */		 0644,				/* mode */		 0,				/* child */		 rng_handle_sysctl_entropy,	/* proc handler */		 0,				/* strategy */		 0,				/* proc control block */		 0, 0}		,		{DEV_I810_INTERVAL,		/* ID */		 RNG_MODULE_NAME "_interval",	/* name in /proc */		 &rng_interval_sysctl,		 sizeof (rng_interval_sysctl),	/* data ptr, data size */		 0644,				/* mode */		 0,				/* child */		 rng_handle_sysctl_interval,	/* proc handler */		 0,				/* strategy */		 0,				/* proc control block */		 0, 0}		,		{0}	};	/* Define the parent file : /proc/sys/dev */	static ctl_table sysctls_root[] = {		{CTL_DEV,		 "dev",		 NULL, 0,		 0555,		 rng_sysctls},		{0}	};	static struct ctl_table_header *sysctls_root_header = NULL;	if (add) {		if (!sysctls_root_header)			sysctls_root_header = register_sysctl_table (sysctls_root, 0);	} else if (sysctls_root_header) {		unregister_sysctl_table (sysctls_root_header);		sysctls_root_header = NULL;	}}static int rng_dev_open (struct inode *inode, struct file *filp){	int rc = -EINVAL;	if ((filp->f_mode & FMODE_READ) == 0)		return rc;	if (filp->f_mode & FMODE_WRITE)		return rc;	/* wait for device to become free */	if (filp->f_flags & O_NONBLOCK) {		if (down_trylock (&rng_open_sem))			return -EAGAIN;	} else {		if (down_interruptible (&rng_open_sem))			return -ERESTARTSYS;	}	if (rng_enable (1)) {		rc = -EIO;		goto err_out;	}	return 0;err_out:	up (&rng_open_sem);	return rc;}static int rng_dev_release (struct inode *inode, struct file *filp){	rng_enable(0);	up (&rng_open_sem);	return 0;}static ssize_t rng_dev_read (struct file *filp, char *buf, size_t size,			     loff_t * offp){	int have_data;	u8 data = 0;	ssize_t ret = 0;	while (size) {		spin_lock_bh (&rng_lock);		have_data = 0;		if (rng_data_present ()) {			data = rng_data_read ();			have_data = 1;		}		spin_unlock_bh (&rng_lock);		if (have_data) {			if (put_user (data, buf++)) {				ret = ret ? : -EFAULT;				break;			}			size--;			ret++;		}		if (current->need_resched)			schedule ();		if (signal_pending (current))			return ret ? : -ERESTARTSYS;		if (filp->f_flags & O_NONBLOCK)			return ret ? : -EAGAIN;	}	return ret;}/* * rng_init_one - look for and attempt to init a single RNG */static int __init rng_init_one (struct pci_dev *dev){	int rc;	u8 hw_status;	DPRINTK ("ENTER\n");	if (pci_enable_device (dev))		return -EIO;	/* XXX currently fails, investigate who has our mem region */	if (request_mem_region (RNG_ADDR, RNG_ADDR_LEN, RNG_MODULE_NAME))		rng_have_mem_region = 1;	rng_mem = ioremap (RNG_ADDR, RNG_ADDR_LEN);	if (rng_mem == NULL) {		printk (KERN_ERR PFX "cannot ioremap RNG Memory\n");		DPRINTK ("EXIT, returning -EBUSY\n");		rc = -EBUSY;		goto err_out_free_res;	}	/* Check for Intel 82802 */	hw_status = rng_hwstatus ();	if ((hw_status & RNG_PRESENT) == 0) {		printk (KERN_ERR PFX "RNG not detected\n");		DPRINTK ("EXIT, returning -ENODEV\n");		rc = -ENODEV;		goto err_out_free_map;	}	if (rng_entropy < 0 || rng_entropy > RNG_MAX_ENTROPY)		rng_entropy = RNG_MAX_ENTROPY;	/* init core RNG timer, but do not add it */	init_timer (&rng_timer);	rng_timer.function = rng_timer_tick;	/* turn RNG h/w off, if it's on */	rc = rng_enable (0);	if (rc) {		printk (KERN_ERR PFX "cannot disable RNG, aborting\n");		goto err_out_free_map;	}	/* add sysctls */	rng_sysctl (1);	DPRINTK ("EXIT, returning 0\n");	return 0;err_out_free_map:	iounmap (rng_mem);err_out_free_res:	if (rng_have_mem_region)		release_mem_region (RNG_ADDR, RNG_ADDR_LEN);	return rc;}/* * Data for PCI driver interface * * This data only exists for exporting the supported * PCI ids via MODULE_DEVICE_TABLE.  We do not actually * register a pci_driver, because someone else might one day * want to register another driver on the same PCI id. */const static struct pci_device_id rng_pci_tbl[] __initdata = {	{ 0x8086, 0x2418, PCI_ANY_ID, PCI_ANY_ID, },	{ 0x8086, 0x2428, PCI_ANY_ID, PCI_ANY_ID, },	{ 0x8086, 0x1130, PCI_ANY_ID, PCI_ANY_ID, },	{ 0, },};MODULE_DEVICE_TABLE (pci, rng_pci_tbl);MODULE_AUTHOR("Jeff Garzik, Matt Sottek");MODULE_DESCRIPTION("Intel i8xx chipset Random Number Generator (RNG) driver");MODULE_PARM(rng_entropy, "1i");MODULE_PARM_DESC(rng_entropy, "Bits of entropy to add to random pool per RNG byte (range: 0-8, default 8)");static struct file_operations rng_chrdev_ops = {	owner:		THIS_MODULE,	open:		rng_dev_open,	release:	rng_dev_release,	read:		rng_dev_read,};static struct miscdevice rng_miscdev = {	RNG_MISCDEV_MINOR,	RNG_MODULE_NAME,	&rng_chrdev_ops,};/* * rng_init - initialize RNG module */static int __init rng_init (void){	int rc;	struct pci_dev *pdev;	DPRINTK ("ENTER\n");	init_MUTEX (&rng_open_sem);	pci_for_each_dev(pdev) {		if (pci_match_device (rng_pci_tbl, pdev) != NULL)			goto match;	}	DPRINTK ("EXIT, returning -ENODEV\n");	return -ENODEV;match:	rc = rng_init_one (pdev);	if (rc)		return rc;	rc = misc_register (&rng_miscdev);	if (rc) {		iounmap (rng_mem);		if (rng_have_mem_region)			release_mem_region (RNG_ADDR, RNG_ADDR_LEN);		DPRINTK ("EXIT, returning %d\n", rc);		return rc;	}	printk (KERN_INFO RNG_DRIVER_NAME " loaded\n");	rng_pdev = pdev;	DPRINTK ("EXIT, returning 0\n");	return 0;}/* * rng_init - shutdown RNG module */static void __exit rng_cleanup (void){	DPRINTK ("ENTER\n");	assert (rng_timer_enabled == 0);	assert (rng_hw_enabled == 0);	misc_deregister (&rng_miscdev);	rng_sysctl (0);	iounmap (rng_mem);	if (rng_have_mem_region)		release_mem_region (RNG_ADDR, RNG_ADDR_LEN);	DPRINTK ("EXIT\n");}module_init (rng_init);module_exit (rng_cleanup);/* These are the startup tests suggested by the FIPS 140-1 spec section*  4.11.1 (http://csrc.nist.gov/fips/fips1401.htm)*  The Monobit, Poker, Runs, and Long Runs tests are implemented below.*  This test is run at periodic intervals to verify*  data is sufficiently random. If the tests are failed the RNG module*  will no longer submit data to the entropy pool, but the tests will*  continue to run at the given interval. If at a later time the RNG*  passes all tests it will be re-enabled for the next period.*   The reason for this is that it is not unlikely that at some time*  during normal operation one of the tests will fail. This does not*  necessarily mean the RNG is not operating properly, it is just a*  statistically rare event. In that case we don't want to forever*  disable the RNG, we will just leave it disabled for the period of*  time until the tests are rerun and passed.**  For argument sake I tested /dev/urandom with these tests and it*  took 142,095 tries before I got a failure, and urandom isn't as*  random as random :)*/static int poker[16] = { 0, }, runs[12] = { 0, };static int ones = 0, rlength = -1, current_bit = 0, rng_test = 0;/* * rng_fips_test_store - store 8 bits of entropy in FIPS * 			 internal test data pool */static void rng_fips_test_store (int rng_data){	int j;	static int last_bit = 0;	DPRINTK ("ENTER, rng_data = %d\n", rng_data);	poker[rng_data >> 4]++;	poker[rng_data & 15]++;	/* Note in the loop below rlength is always one less than the actual	   run length. This makes things easier. */	last_bit = (rng_data & 128) >> 7;	for (j = 7; j >= 0; j--) {		ones += current_bit = (rng_data & 1 << j) >> j;		if (current_bit != last_bit) {			/* If runlength is 1-6 count it in correct bucket. 0's go in			   runs[0-5] 1's go in runs[6-11] hence the 6*current_bit below */			if (rlength < 5) {				runs[rlength +				     (6 * current_bit)]++;			} else {				runs[5 + (6 * current_bit)]++;			}			/* Check if we just failed longrun test */			if (rlength >= 33)				rng_test &= 8;			rlength = 0;			/* flip the current run type */			last_bit = current_bit;		} else {			rlength++;		}	}	DPRINTK ("EXIT\n");}/* * now that we have some data, run a FIPS test */static void rng_run_fips_test (void){	int j, i;	DPRINTK ("ENTER\n");	/* add in the last (possibly incomplete) run */	if (rlength < 5)		runs[rlength + (6 * current_bit)]++;	else {		runs[5 + (6 * current_bit)]++;		if (rlength >= 33)			rng_test &= 8;	}	/* Ones test */	if ((ones >= 10346) || (ones <= 9654))		rng_test &= 1;	/* Poker calcs */	for (i = 0, j = 0; i < 16; i++)		j += poker[i] * poker[i];	if ((j >= 1580457) || (j <= 1562821))		rng_test &= 2;	if ((runs[0] < 2267) || (runs[0] > 2733) ||	    (runs[1] < 1079) || (runs[1] > 1421) ||	    (runs[2] < 502) || (runs[2] > 748) ||	    (runs[3] < 223) || (runs[3] > 402) ||	    (runs[4] < 90) || (runs[4] > 223) ||	    (runs[5] < 90) || (runs[5] > 223) ||	    (runs[6] < 2267) || (runs[6] > 2733) ||	    (runs[7] < 1079) || (runs[7] > 1421) ||	    (runs[8] < 502) || (runs[8] > 748) ||	    (runs[9] < 223) || (runs[9] > 402) ||	    (runs[10] < 90) || (runs[10] > 223) ||	    (runs[11] < 90) || (runs[11] > 223)) {		rng_test &= 4;	}	rng_test = !rng_test;	DPRINTK ("FIPS test %sed\n", rng_test ? "pass" : "fail");	/* enable/disable RNG with results of the tests */	if (rng_test && !rng_trusted)		printk (KERN_WARNING PFX "FIPS test passed, enabling RNG\n");	else if (!rng_test && rng_trusted)		printk (KERN_WARNING PFX "FIPS test failed, disabling RNG\n");	rng_trusted = rng_test;	/* finally, clear out FIPS variables for start of next run */	memset (poker, 0, sizeof (poker));	memset (runs, 0, sizeof (runs));	ones = 0;	rlength = -1;	current_bit = 0;	rng_test = 0;	DPRINTK ("EXIT\n");}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -