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

📄 random.c

📁 powerpc内核mpc8241linux系统下char驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
		if (get_user(ent_count, (int *) arg))			return -EFAULT;		/*		 * Add i to entropy_count, limiting the result to be		 * between 0 and POOLBITS.		 */		if (ent_count < -random_state.entropy_count)			random_state.entropy_count = 0;		else if (ent_count > POOLBITS)			random_state.entropy_count = POOLBITS;		else {			random_state.entropy_count += ent_count;			if (random_state.entropy_count > POOLBITS)				random_state.entropy_count = POOLBITS;			if (random_state.entropy_count < 0)				random_state.entropy_count = 0;		}		/*		 * Wake up waiting processes if we have enough		 * entropy.		 */		if (random_state.entropy_count >= WAIT_INPUT_BITS)			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(POOLWORDS, p++))			return -EFAULT;		if (size < 0)			return -EINVAL;		if (size > POOLWORDS)			size = 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;		/*		 * Add ent_count to entropy_count, limiting the result to be		 * between 0 and POOLBITS.		 */		if (ent_count > POOLBITS)			random_state.entropy_count = POOLBITS;		else {			random_state.entropy_count += ent_count;			if (random_state.entropy_count > POOLBITS)				random_state.entropy_count = POOLBITS;			if (random_state.entropy_count < 0)				random_state.entropy_count = 0;		}		/*		 * Wake up waiting processes if we have enough		 * entropy.		 */		if (random_state.entropy_count >= WAIT_INPUT_BITS)			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;		rand_clear_pool();		return 0;	default:		return -EINVAL;	}}struct file_operations random_fops = {	NULL,		/* random_lseek */	random_read,	random_write,	NULL,		/* random_readdir */	random_poll,	/* random_poll */	random_ioctl,	NULL,		/* random_mmap */	NULL,		/* no special open code */	NULL,		/* flush */	NULL		/* no special release code */};struct file_operations urandom_fops = {	NULL,		/* unrandom_lseek */	random_read_unlimited,	random_write,	NULL,		/* urandom_readdir */	NULL,		/* urandom_poll */	random_ioctl,	NULL,		/* urandom_mmap */	NULL,		/* no special open code */	NULL,		/* flush */	NULL		/* no special release code */};/* * TCP initial sequence number picking.  This uses the random number * generator to pick an initial secret value.  This value is hashed * along with the TCP endpoint information to provide a unique * starting point for each pair of TCP endpoints.  This defeats * attacks which rely on guessing the initial TCP sequence number. * This algorithm was suggested by Steve Bellovin. * * Using a very strong hash was taking an appreciable amount of the total * TCP connection establishment time, so this is a weaker hash, * compensated for by changing the secret periodically. *//* F, G and H are basic MD4 functions: selection, majority, parity */#define F(x, y, z) ((z) ^ ((x) & ((y) ^ (z))))#define G(x, y, z) (((x) & (y)) + (((x) ^ (y)) & (z)))#define H(x, y, z) ((x) ^ (y) ^ (z))/* * The generic round function.  The application is so specific that * we don't bother protecting all the arguments with parens, as is generally * good macro practice, in favor of extra legibility. * Rotation is separate from addition to prevent recomputation */#define ROUND(f, a, b, c, d, x, s)	\	(a += f(b, c, d) + x, a = (a << s) | (a >> (32-s)))#define K1 0#define K2 013240474631UL#define K3 015666365641UL/* * Basic cut-down MD4 transform.  Returns only 32 bits of result. */static __u32 halfMD4Transform (__u32 const buf[4], __u32 const in[8]){	__u32	a = buf[0], b = buf[1], c = buf[2], d = buf[3];	/* Round 1 */	ROUND(F, a, b, c, d, in[0] + K1,  3);	ROUND(F, d, a, b, c, in[1] + K1,  7);	ROUND(F, c, d, a, b, in[2] + K1, 11);	ROUND(F, b, c, d, a, in[3] + K1, 19);	ROUND(F, a, b, c, d, in[4] + K1,  3);	ROUND(F, d, a, b, c, in[5] + K1,  7);	ROUND(F, c, d, a, b, in[6] + K1, 11);	ROUND(F, b, c, d, a, in[7] + K1, 19);	/* Round 2 */	ROUND(G, a, b, c, d, in[1] + K2,  3);	ROUND(G, d, a, b, c, in[3] + K2,  5);	ROUND(G, c, d, a, b, in[5] + K2,  9);	ROUND(G, b, c, d, a, in[7] + K2, 13);	ROUND(G, a, b, c, d, in[0] + K2,  3);	ROUND(G, d, a, b, c, in[2] + K2,  5);	ROUND(G, c, d, a, b, in[4] + K2,  9);	ROUND(G, b, c, d, a, in[6] + K2, 13);	/* Round 3 */	ROUND(H, a, b, c, d, in[3] + K3,  3);	ROUND(H, d, a, b, c, in[7] + K3,  9);	ROUND(H, c, d, a, b, in[2] + K3, 11);	ROUND(H, b, c, d, a, in[6] + K3, 15);	ROUND(H, a, b, c, d, in[1] + K3,  3);	ROUND(H, d, a, b, c, in[5] + K3,  9);	ROUND(H, c, d, a, b, in[0] + K3, 11);	ROUND(H, b, c, d, a, in[4] + K3, 15);	return buf[1] + b;	/* "most hashed" word */	/* Alternative: return sum of all words? */}#if 0	/* May be needed for IPv6 */static __u32 twothirdsMD4Transform (__u32 const buf[4], __u32 const in[12]){	__u32	a = buf[0], b = buf[1], c = buf[2], d = buf[3];	/* Round 1 */	ROUND(F, a, b, c, d, in[ 0] + K1,  3);	ROUND(F, d, a, b, c, in[ 1] + K1,  7);	ROUND(F, c, d, a, b, in[ 2] + K1, 11);	ROUND(F, b, c, d, a, in[ 3] + K1, 19);	ROUND(F, a, b, c, d, in[ 4] + K1,  3);	ROUND(F, d, a, b, c, in[ 5] + K1,  7);	ROUND(F, c, d, a, b, in[ 6] + K1, 11);	ROUND(F, b, c, d, a, in[ 7] + K1, 19);	ROUND(F, a, b, c, d, in[ 8] + K1,  3);	ROUND(F, d, a, b, c, in[ 9] + K1,  7);	ROUND(F, c, d, a, b, in[10] + K1, 11);	ROUND(F, b, c, d, a, in[11] + K1, 19);	/* Round 2 */	ROUND(G, a, b, c, d, in[ 1] + K2,  3);	ROUND(G, d, a, b, c, in[ 3] + K2,  5);	ROUND(G, c, d, a, b, in[ 5] + K2,  9);	ROUND(G, b, c, d, a, in[ 7] + K2, 13);	ROUND(G, a, b, c, d, in[ 9] + K2,  3);	ROUND(G, d, a, b, c, in[11] + K2,  5);	ROUND(G, c, d, a, b, in[ 0] + K2,  9);	ROUND(G, b, c, d, a, in[ 2] + K2, 13);	ROUND(G, a, b, c, d, in[ 4] + K2,  3);	ROUND(G, d, a, b, c, in[ 6] + K2,  5);	ROUND(G, c, d, a, b, in[ 8] + K2,  9);	ROUND(G, b, c, d, a, in[10] + K2, 13);	/* Round 3 */	ROUND(H, a, b, c, d, in[ 3] + K3,  3);	ROUND(H, d, a, b, c, in[ 7] + K3,  9);	ROUND(H, c, d, a, b, in[11] + K3, 11);	ROUND(H, b, c, d, a, in[ 2] + K3, 15);	ROUND(H, a, b, c, d, in[ 6] + K3,  3);	ROUND(H, d, a, b, c, in[10] + K3,  9);	ROUND(H, c, d, a, b, in[ 1] + K3, 11);	ROUND(H, b, c, d, a, in[ 5] + K3, 15);	ROUND(H, a, b, c, d, in[ 9] + K3,  3);	ROUND(H, d, a, b, c, in[ 0] + K3,  9);	ROUND(H, c, d, a, b, in[ 4] + K3, 11);	ROUND(H, b, c, d, a, in[ 8] + K3, 15);	return buf[1] + b;	/* "most hashed" word */	/* Alternative: return sum of all words? */}#endif#undef ROUND#undef F#undef G#undef H#undef K1#undef K2#undef K3/* This should not be decreased so low that ISNs wrap too fast. */#define REKEY_INTERVAL	300#define HASH_BITS 24__u32 secure_tcp_sequence_number(__u32 saddr, __u32 daddr,				 __u16 sport, __u16 dport){	static __u32	rekey_time = 0;	static __u32	count = 0;	static __u32	secret[12];	struct timeval 	tv;	__u32		seq;	/*	 * Pick a random secret every REKEY_INTERVAL seconds.	 */	do_gettimeofday(&tv);	/* We need the usecs below... */	if (!rekey_time || (tv.tv_sec - rekey_time) > REKEY_INTERVAL) {		rekey_time = tv.tv_sec;		/* First three words are overwritten below. */		get_random_bytes(&secret+3, sizeof(secret)-12);		count = (tv.tv_sec/REKEY_INTERVAL) << HASH_BITS;	}	/*	 *  Pick a unique starting offset for each TCP connection endpoints	 *  (saddr, daddr, sport, dport).	 *  Note that the words are placed into the first words to be	 *  mixed in with the halfMD4.  This is because the starting	 *  vector is also a random secret (at secret+8), and further	 *  hashing fixed data into it isn't going to improve anything,	 *  so we should get started with the variable data.	 */	secret[0]=saddr;	secret[1]=daddr;	secret[2]=(sport << 16) + dport;	seq = (halfMD4Transform(secret+8, secret) &	       ((1<<HASH_BITS)-1)) + count;	/*	 *	As close as possible to RFC 793, which	 *	suggests using a 250 kHz clock.	 *	Further reading shows this assumes 2 Mb/s networks.	 *	For 10 Mb/s Ethernet, a 1 MHz clock is appropriate.	 *	That's funny, Linux has one built in!  Use it!	 *	(Networks are faster now - should this be increased?)	 */	seq += tv.tv_usec + tv.tv_sec*1000000;#if 0	printk("init_seq(%lx, %lx, %d, %d) = %d\n",	       saddr, daddr, sport, dport, seq);#endif	return seq;}#ifdef CONFIG_SYN_COOKIES/* * Secure SYN cookie computation. This is the algorithm worked out by * Dan Bernstein and Eric Schenk. * * For linux I implement the 1 minute counter by looking at the jiffies clock. * The count is passed in as a parameter, so this code doesn't much care. */#define COOKIEBITS 24	/* Upper bits store count */#define COOKIEMASK (((__u32)1 << COOKIEBITS) - 1)static int	syncookie_init = 0;static __u32	syncookie_secret[2][16-3+HASH_BUFFER_SIZE];__u32 secure_tcp_syn_cookie(__u32 saddr, __u32 daddr, __u16 sport,		__u16 dport, __u32 sseq, __u32 count, __u32 data){	__u32 	tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];	__u32	seq;	/*	 * Pick two random secrets the first time we need a cookie.	 */	if (syncookie_init == 0) {		get_random_bytes(syncookie_secret, sizeof(syncookie_secret));		syncookie_init = 1;	}	/*	 * Compute the secure sequence number.	 * The output should be:   	 *   HASH(sec1,saddr,sport,daddr,dport,sec1) + sseq + (count * 2^24)	 *      + (HASH(sec2,saddr,sport,daddr,dport,count,sec2) % 2^24).	 * Where sseq is their sequence number and count increases every	 * minute by 1.	 * As an extra hack, we add a small "data" value that encodes the	 * MSS into the second hash value.	 */	memcpy(tmp+3, syncookie_secret[0], sizeof(syncookie_secret[0]));	tmp[0]=saddr;	tmp[1]=daddr;	tmp[2]=(sport << 16) + dport;	HASH_TRANSFORM(tmp+16, tmp);	seq = tmp[17] + sseq + (count << COOKIEBITS);	memcpy(tmp+3, syncookie_secret[1], sizeof(syncookie_secret[1]));	tmp[0]=saddr;	tmp[1]=daddr;	tmp[2]=(sport << 16) + dport;	tmp[3] = count;	/* minute counter */	HASH_TRANSFORM(tmp+16, tmp);	/* Add in the second hash and the data */	return seq + ((tmp[17] + data) & COOKIEMASK);}/* * This retrieves the small "data" value from the syncookie. * If the syncookie is bad, the data returned will be out of * range.  This must be checked by the caller. * * The count value used to generate the cookie must be within * "maxdiff" if the current (passed-in) "count".  The return value * is (__u32)-1 if this test fails. */__u32 check_tcp_syn_cookie(__u32 cookie, __u32 saddr, __u32 daddr, __u16 sport,		__u16 dport, __u32 sseq, __u32 count, __u32 maxdiff){	__u32 	tmp[16 + HASH_BUFFER_SIZE + HASH_EXTRA_SIZE];	__u32	diff;	if (syncookie_init == 0)		return (__u32)-1;	/* Well, duh! */	/* Strip away the layers from the cookie */	memcpy(tmp+3, syncookie_secret[0], sizeof(syncookie_secret[0]));	tmp[0]=saddr;	tmp[1]=daddr;	tmp[2]=(sport << 16) + dport;	HASH_TRANSFORM(tmp+16, tmp);	cookie -= tmp[17] + sseq;	/* Cookie is now reduced to (count * 2^24) ^ (hash % 2^24) */	diff = (count - (cookie >> COOKIEBITS)) & ((__u32)-1 >> COOKIEBITS);	if (diff >= maxdiff)		return (__u32)-1;	memcpy(tmp+3, syncookie_secret[1], sizeof(syncookie_secret[1]));	tmp[0] = saddr;	tmp[1] = daddr;	tmp[2] = (sport << 16) + dport;	tmp[3] = count - diff;	/* minute counter */	HASH_TRANSFORM(tmp+16, tmp);	return (cookie - tmp[17]) & COOKIEMASK;	/* Leaving the data behind */}#endif#ifdef RANDOM_BENCHMARK/* * This is so we can do some benchmarking of the random driver, to see * how much overhead add_timer_randomness really takes.  This only * works on a Pentium, since it depends on the timer clock... * * Note: the results of this benchmark as of this writing (5/27/96) * * On a Pentium, add_timer_randomness() takes between 150 and 1000 * clock cycles, with an average of around 600 clock cycles.  On a 75 * MHz Pentium, this translates to 2 to 13 microseconds, with an * average time of 8 microseconds.  This should be fast enough so we * can use add_timer_randomness() even with the fastest of interrupts... */static inline unsigned long long get_clock_cnt(void){	unsigned long low, high;	__asm__(".byte 0x0f,0x31" :"=a" (low), "=d" (high));	return (((unsigned long long) high << 32) | low); }__initfunc(static voidinitialize_benchmark(struct random_benchmark *bench,	             const char *descr, int unit)){	bench->times = 0;	bench->accum = 0;	bench->max = 0;	bench->min = 1 << 31;	bench->descr = descr;	bench->unit = unit;}static void begin_benchmark(struct random_benchmark *bench){#ifdef BENCHMARK_NOINT	save_flags(bench->flags); cli();#endif	bench->start_time = get_clock_cnt();}static void end_benchmark(struct random_benchmark *bench){	unsigned long ticks;		ticks = (unsigned long) (get_clock_cnt() - bench->start_time);#ifdef BENCHMARK_NOINT	restore_flags(bench->flags);#endif	if (ticks < bench->min)		bench->min = ticks;	if (ticks > bench->max)		bench->max = ticks;	bench->accum += ticks;	bench->times++;	if (bench->times == BENCHMARK_INTERVAL) {		printk("Random benchmark: %s %d: %lu min, %lu avg, "		       "%lu max\n", bench->descr, bench->unit, bench->min,		       bench->accum / BENCHMARK_INTERVAL, bench->max);		bench->times = 0;		bench->accum = 0;		bench->max = 0;		bench->min = 1 << 31;	}}	#endif /* RANDOM_BENCHMARK */

⌨️ 快捷键说明

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