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

📄 random.c

📁 讲述linux的初始化过程
💻 C
📖 第 1 页 / 共 5 页
字号:
		wake_up_interruptible(&random_write_wait);	r->extract_count += nbytes;		ret = 0;	while (nbytes) {		/*		 * Check if we need to break out or reschedule....		 */		if ((flags & EXTRACT_ENTROPY_USER) && current->need_resched) {			if (signal_pending(current)) {				if (ret == 0)					ret = -ERESTARTSYS;				break;			}			schedule();		}		/* Hash the pool to get the output */		tmp[0] = 0x67452301;		tmp[1] = 0xefcdab89;		tmp[2] = 0x98badcfe;		tmp[3] = 0x10325476;#ifdef USE_SHA		tmp[4] = 0xc3d2e1f0;#endif		/*		 * As we hash the pool, we mix intermediate values of		 * the hash back into the pool.  This eliminates		 * backtracking attacks (where the attacker knows		 * the state of the pool plus the current outputs, and		 * attempts to find previous ouputs), unless the hash		 * function can be inverted.		 */		for (i = 0, x = 0; i < r->poolinfo.poolwords; i += 16, x+=2) {			HASH_TRANSFORM(tmp, r->pool+i);			add_entropy_words(r, &tmp[x%HASH_BUFFER_SIZE], 1);		}				/*		 * In case the hash function has some recognizable		 * output pattern, we fold it in half.		 */		for (i = 0; i <  HASH_BUFFER_SIZE/2; i++)			tmp[i] ^= tmp[i + (HASH_BUFFER_SIZE+1)/2];#if HASH_BUFFER_SIZE & 1	/* There's a middle word to deal with */		x = tmp[HASH_BUFFER_SIZE/2];		x ^= (x >> 16);		/* Fold it in half */		((__u16 *)tmp)[HASH_BUFFER_SIZE-1] = (__u16)x;#endif				/* Copy data to destination buffer */		i = MIN(nbytes, HASH_BUFFER_SIZE*sizeof(__u32)/2);		if (flags & EXTRACT_ENTROPY_USER) {			i -= copy_to_user(buf, (__u8 const *)tmp, i);			if (!i) {				ret = -EFAULT;				break;			}		} else			memcpy(buf, (__u8 const *)tmp, i);		nbytes -= i;		buf += i;		ret += i;		add_timer_randomness(&extract_timer_state, nbytes);	}	/* Wipe data just returned from memory */	memset(tmp, 0, sizeof(tmp));		return ret;}/* * This function is the exported kernel interface.  It returns some * number of good random numbers, suitable for seeding TCP sequence * numbers, etc. */void get_random_bytes(void *buf, int nbytes){	if (sec_random_state)  		extract_entropy(sec_random_state, (char *) buf, nbytes, 				EXTRACT_ENTROPY_SECONDARY);	else if (random_state)		extract_entropy(random_state, (char *) buf, nbytes, 0);	else		printk(KERN_NOTICE "get_random_bytes called before "				   "random driver initialization\n");}/********************************************************************* * * Functions to interface with Linux * *********************************************************************//* * Initialize the random pool with standard stuff. * * NOTE: This is an OS-dependent function. */static void init_std_data(struct entropy_store *r){	struct timeval 	tv;	__u32		words[2];	char 		*p;	int		i;	do_gettimeofday(&tv);	words[0] = tv.tv_sec;	words[1] = tv.tv_usec;	add_entropy_words(r, words, 2);	/*	 *	This doesn't lock system.utsname. However, we are generating	 *	entropy so a race with a name set here is fine.	 */	p = (char *) &system_utsname;	for (i = sizeof(system_utsname) / sizeof(words); i; i--) {		memcpy(words, p, sizeof(words));		add_entropy_words(r, words, sizeof(words)/4);		p += sizeof(words);	}}void __init rand_initialize(void){	int i;	if (create_entropy_store(DEFAULT_POOL_SIZE, &random_state))		return;		/* Error, return */	if (batch_entropy_init(BATCH_ENTROPY_SIZE, random_state))		return;		/* Error, return */	if (create_entropy_store(SECONDARY_POOL_SIZE, &sec_random_state))		return;		/* Error, return */	clear_entropy_store(random_state);	clear_entropy_store(sec_random_state);	init_std_data(random_state);#ifdef CONFIG_SYSCTL	sysctl_init_random(random_state);#endif	for (i = 0; i < NR_IRQS; i++)		irq_timer_state[i] = NULL;	for (i = 0; i < MAX_BLKDEV; i++)		blkdev_timer_state[i] = NULL;	memset(&keyboard_timer_state, 0, sizeof(struct timer_rand_state));	memset(&mouse_timer_state, 0, sizeof(struct timer_rand_state));	memset(&extract_timer_state, 0, sizeof(struct timer_rand_state));	extract_timer_state.dont_count_entropy = 1;}void rand_initialize_irq(int irq){	struct timer_rand_state *state;		if (irq >= NR_IRQS || irq_timer_state[irq])		return;	/*	 * If kmalloc returns null, we just won't use that entropy	 * source.	 */	state = kmalloc(sizeof(struct timer_rand_state), GFP_KERNEL);	if (state) {		memset(state, 0, sizeof(struct timer_rand_state));		irq_timer_state[irq] = state;	}}void rand_initialize_blkdev(int major, int mode){	struct timer_rand_state *state;		if (major >= MAX_BLKDEV || blkdev_timer_state[major])		return;	/*	 * If kmalloc returns null, we just won't use that entropy	 * source.	 */	state = kmalloc(sizeof(struct timer_rand_state), mode);	if (state) {		memset(state, 0, sizeof(struct timer_rand_state));		blkdev_timer_state[major] = state;	}}static ssize_trandom_read(struct file * file, char * buf, size_t nbytes, loff_t *ppos){	DECLARE_WAITQUEUE(wait, current);	ssize_t			n, retval = 0, count = 0;		if (nbytes == 0)		return 0;	add_wait_queue(&random_read_wait, &wait);	while (nbytes > 0) {		set_current_state(TASK_INTERRUPTIBLE);				n = nbytes;		if (n > SEC_XFER_SIZE)			n = SEC_XFER_SIZE;		if (n > random_state->entropy_count / 8)			n = random_state->entropy_count / 8;		if (n == 0) {			if (file->f_flags & O_NONBLOCK) {				retval = -EAGAIN;				break;			}			if (signal_pending(current)) {				retval = -ERESTARTSYS;				break;			}			schedule();			continue;		}		n = extract_entropy(sec_random_state, buf, n,				    EXTRACT_ENTROPY_USER |				    EXTRACT_ENTROPY_SECONDARY);		if (n < 0) {			retval = n;			break;		}		count += n;		buf += n;		nbytes -= n;		break;		/* This break makes the device work */				/* like a named pipe */	}	current->state = TASK_RUNNING;	remove_wait_queue(&random_read_wait, &wait);	/*	 * If we gave the user some bytes, update the access time.	 */	if (count != 0) {		UPDATE_ATIME(file->f_dentry->d_inode);	}		return (count ? count : retval);}static ssize_turandom_read(struct file * file, char * buf,		      size_t nbytes, loff_t *ppos){	return extract_entropy(sec_random_state, buf, nbytes,			       EXTRACT_ENTROPY_USER |			       EXTRACT_ENTROPY_SECONDARY);}static unsigned intrandom_poll(struct file *file, poll_table * wait){	unsigned int mask;	poll_wait(file, &random_read_wait, wait);	poll_wait(file, &random_write_wait, wait);	mask = 0;	if (random_state->entropy_count >= random_read_wakeup_thresh)		mask |= POLLIN | POLLRDNORM;	if (random_state->entropy_count < random_write_wakeup_thresh)		mask |= POLLOUT | POLLWRNORM;	return mask;}static ssize_trandom_write(struct file * file, const char * buffer,	     size_t count, loff_t *ppos){	int		ret = 0;	size_t		bytes;	__u32 		buf[16];	const char 	*p = buffer;	size_t		c = count;	while (c > 0) {		bytes = MIN(c, sizeof(buf));		bytes -= copy_from_user(&buf, p, bytes);		if (!bytes) {			ret = -EFAULT;			break;		}		c -= bytes;		p += bytes;		/* Convert bytes to words */		bytes = (bytes + 3) / sizeof(__u32);		add_entropy_words(random_state, buf, bytes);	}	if (p == buffer) {		return (ssize_t)ret;	} else {		file->f_dentry->d_inode->i_mtime = CURRENT_TIME;		mark_inode_dirty(file->f_dentry->d_inode);		return (ssize_t)(p - buffer);	}}static intrandom_ioctl(struct inode * inode, struct file * file,	     unsigned int cmd, unsigned long arg){	int *p, size, ent_count;	int retval;		switch (cmd) {	case RNDGETENTCNT:		ent_count = random_state->entropy_count;		if (put_user(ent_count, (int *) arg))			return -EFAULT;		return 0;	case RNDADDTOENTCNT:		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		if (get_user(ent_count, (int *) arg))			return -EFAULT;		credit_entropy_store(random_state, ent_count);		/*		 * Wake up waiting processes if we have enough		 * entropy.		 */		if (random_state->entropy_count >= random_read_wakeup_thresh)			wake_up_interruptible(&random_read_wait);		return 0;	case RNDGETPOOL:		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		p = (int *) arg;		ent_count = random_state->entropy_count;		if (put_user(ent_count, p++))			return -EFAULT;					if (get_user(size, p))			return -EFAULT;		if (put_user(random_state->poolinfo.poolwords, p++))			return -EFAULT;		if (size < 0)			return -EINVAL;		if (size > random_state->poolinfo.poolwords)			size = random_state->poolinfo.poolwords;		if (copy_to_user(p, random_state->pool, size*sizeof(__u32)))			return -EFAULT;		return 0;	case RNDADDENTROPY:		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		p = (int *) arg;		if (get_user(ent_count, p++))			return -EFAULT;		if (ent_count < 0)			return -EINVAL;		if (get_user(size, p++))			return -EFAULT;		retval = random_write(file, (const char *) p,				      size, &file->f_pos);		if (retval < 0)			return retval;		credit_entropy_store(random_state, ent_count);		/*		 * Wake up waiting processes if we have enough		 * entropy.		 */		if (random_state->entropy_count >= random_read_wakeup_thresh)			wake_up_interruptible(&random_read_wait);		return 0;	case RNDZAPENTCNT:		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		random_state->entropy_count = 0;		return 0;	case RNDCLEARPOOL:		/* Clear the entropy pool and associated counters. */		if (!capable(CAP_SYS_ADMIN))			return -EPERM;		clear_entropy_store(random_state);		init_std_data(random_state);		return 0;	default:		return -EINVAL;	}}struct file_operations random_fops = {	read:		random_read,	write:		random_write,	poll:		random_poll,	ioctl:		random_ioctl,};struct file_operations urandom_fops = {	read:		urandom_read,	write:		random_write,	ioctl:		random_ioctl,};/*************************************************************** * Random UUID interface *  * Used here for a Boot ID, but can be useful for other kernel  * drivers. ***************************************************************//* * Generate random UUID */void generate_random_uuid(unsigned char uuid_out[16]){	get_random_bytes(uuid_out, 16);	/* Set UUID version to 4 --- truely random generation */	uuid_out[6] = (uuid_out[6] & 0x0F) | 0x40;	/* Set the UUID variant to DCE */	uuid_out[8] = (uuid_out[8] & 0x3F) | 0x80;}/********************************************************************

⌨️ 快捷键说明

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