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

📄 prandom.c

📁 DHCP服务器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
}/*  * This function takes the input data does the selection of data specified * by the hash control block. * The step varialbe in the work sturcture determines which 1/step bytes * are used,  * */static intdo_hash(dst_work *work, prand_hash *hash, const u_char *input, unsigned size){	const u_char *tmp = input;	u_char *tp, *abuf = (u_char *)0;	int i, n;	unsigned needed, avail, dig, cnt = size;	unsigned tmp_size = 0;	if (cnt <= 0 || input == NULL)		return (0);	if (hash->step > 1) {	/* if using subset of input data */		tmp_size = size / hash->step + 2;		abuf = tp = malloc(tmp_size);		tmp = tp;		for (cnt = 0, i = hash->curr; i < size; i += hash->step, cnt++)			*(tp++) = input[i];		/* calcutate the starting point in the next input set */		hash->curr = (hash->step - (i - size)) % hash->step;	}	/* digest the data in block sizes */	for (n = 0; n < cnt; n += needed) {		avail = (cnt - n);		needed = hash->block - hash->digested;		dig = (avail < needed) ? avail : needed;		dst_sign_data(SIG_MODE_UPDATE, hash->key, &hash->ctx, 			      &tmp[n], dig, NULL, 0);		hash->digested += dig;		if (hash->digested >= hash->block)			force_hash(work, hash);		if (work->needed < work->filled) {			if (abuf) 				SAFE_FREE2(abuf, tmp_size);			return (1);		}	}	if (tmp_size > 0)		SAFE_FREE2(abuf, tmp_size);	return (0);}/* * Copy data from INPUT for length SIZE into the work-block TMP. * If we fill the work-block, digest it; then, * if work-block needs more data, keep filling with the rest of the input. */static intmy_digest(dst_work *work, const u_char *input, unsigned size){	int i, full = 0;	static unsigned counter;		counter += size;	/* first do each one of the hashes */	for (i = 0; i < DST_NUM_HASHES && full == 0; i++) 		full = do_hash(work, work->hash[i], input, size) +		       do_hash(work, work->hash[i], (u_char *) &counter, 				sizeof(counter));/*  * if enough data has be generated do final operation on all hashes  *  that have enough date for that  */	for (i = 0; full && (i < DST_NUM_HASHES); i++)		force_hash(work, work->hash[i]);	return (full);}/* * this function gets some semi random data and sets that as an HMAC key * If we get a valid key this function returns that key initalized * otherwise it returns NULL; */static prand_hash *get_hmac_key(int step, int block){	u_char *buff;	int temp = 0, n = 0;	unsigned size = 70;	DST_KEY *new_key = NULL;	prand_hash *new = NULL;	/* use key that is larger than  digest algorithms (64) for key size */	buff = malloc(size);	if (buff == NULL)		return (NULL);	/* do not memset the allocated memory to get random bytes there */	/* time of day is somewhat random  expecialy in the last bytes */	gettimeofday((struct timeval *) &buff[n], NULL);	n += sizeof(struct timeval);/* get some semi random stuff in here stir it with micro seconds */	if (n < size) {		temp = dst_s_quick_random((int) buff[n - 1]);		memcpy(&buff[n], &temp, sizeof(temp));		n += sizeof(temp);	}/* get the pid of this process and its parent */	if (n < size) {		temp = (int) getpid();		memcpy(&buff[n], &temp, sizeof(temp));		n += sizeof(temp);	}	if (n < size) {		temp = (int) getppid();		memcpy(&buff[n], &temp, sizeof(temp));		n += sizeof(temp);	}/* get the user ID */	if (n < size) {		temp = (int) getuid();		memcpy(&buff[n], &temp, sizeof(temp));		n += sizeof(temp);	}#ifndef GET_HOST_ID_MISSING	if (n < size) {		temp = (int) gethostid();		memcpy(&buff[n], &temp, sizeof(temp));		n += sizeof(temp);	}#endif/* get some more random data */	if (n < size) {		temp = dst_s_quick_random((int) buff[n - 1]);		memcpy(&buff[n], &temp, sizeof(temp));		n += sizeof(temp);	}/* covert this into a HMAC key */	new_key = dst_buffer_to_key("", KEY_HMAC_MD5, 0, 0, buff, size);	SAFE_FREE(buff);/* get the control structure */	if ((new = malloc(sizeof(prand_hash))) == NULL)		return (NULL);	new->digested = new->curr = 0;	new->step = step;	new->block = block;	new->key = new_key;	if (dst_sign_data(SIG_MODE_INIT, new_key, &new->ctx, NULL, 0, NULL, 0))		return (NULL);	return (new);}/*  * own_random()  * This function goes out and from various sources tries to generate enough * semi random data that a hash function can generate a random data.  * This function will iterate between the two main random source sources,  *  information from programs and directores in random order.  * This function return the number of bytes added to the random output buffer.  */static unsignedown_random(dst_work *work){	int dir = 0, b;	int bytes, n, cmd = 0, dig = 0;	int start =0;/*  * now get the initial seed to put into the quick random function from  * the address of the work structure  */	bytes = (int) getpid();/* * proceed while needed  */	while (work->filled < work->needed) {		EREPORT(("own_random r %08x b %6d t %6d f %6d\n",			 ran_val, bytes, work->in_temp, work->filled));/* pick a random number in the range of 0..7 based on that random number * perform some operations that yield random data */		start = work->filled;		n = (dst_s_quick_random(bytes) >> DST_SHIFT) & 0x07;		switch (n) {		    case 0:		    case 3:			if (sizeof(cmds) > 2 *sizeof(*cmds)) {				b = unix_cmd(work);				cmd += b;			}			break;		    case 1:		    case 7:			if (sizeof(dirs) > 2 *sizeof(*dirs)) {				b = do_ls(work);				dir += b;			}			break;		    case 4:		    case 5:			/* retry getting data from /dev/random */			b = get_dev_random(&work->output[work->filled], 					   work->needed - work->filled);			if (b > 0)				work->filled += b;			break;		    case 6:			if (sizeof(files) > 2 * sizeof(*files)) {				b = digest_file(work);				dig += b;			}			break;		    case 2:		    default:	/* to make sure we make some progress */			work->output[work->filled++] = 0xff &				dst_s_quick_random(bytes);			b = 1;			break;		}		if (b > 0) 			bytes += b;	}	return (work->filled);}/*  * dst_s_random() This function will return the requested number of bytes  * of randomness to the caller it will use the best available sources of  * randomness. * The current order is to use /dev/random, precalculated randomness, and  * finaly use some system calls and programs to generate semi random data that  * is then digested to generate randomness.  * This function is thread safe as each thread uses its own context, but * concurrent treads will affect each other as they update shared state  * information. * It is strongly recommended that this function be called requesting a size  * that is not a multiple of the output of the hash function used.  *  * If /dev/random is not available this function is not suitable to generate  * large ammounts of data, rather it is suitable to seed a pseudo-random  * generator  * Returns the number of bytes put in the output buffer  */intdst_s_random(u_char *output, unsigned size){	int n = 0, i;	unsigned s;	static u_char old_unused[DST_HASH_SIZE * DST_NUM_HASHES];	static unsigned unused = 0;	if (size <= 0 || output == NULL)		return (0);	if (size >= 2048)		return (-1);	/* 	 * Read from /dev/random 	 */	n = get_dev_random(output, size);	/* 	 *  If old data is available and needed use it 	 */	if (n < size && unused > 0) {		unsigned need = size - n;		if (unused <= need) {			memcpy(output, old_unused, unused);			n += unused;			unused = 0;		} else {			memcpy(output, old_unused, need);			n += need;			unused -= need;			memcpy(old_unused, &old_unused[need], unused);		}	}	/*	 * If we need more use the simulated randomness here.	 */	if (n < size) {		dst_work *my_work = (dst_work *) malloc(sizeof(dst_work));		if (my_work == NULL)			return (n);		my_work->needed = size - n;		my_work->filled = 0;		my_work->output = (u_char *) malloc(my_work->needed +						    DST_HASH_SIZE *						    DST_NUM_HASHES);		my_work->file_digest = NULL;		if (my_work->output == NULL)			return (n);		memset(my_work->output, 0x0, my_work->needed);/* allocate upto 4 different HMAC hash functions out of order */#if DST_NUM_HASHES >= 3		my_work->hash[2] = get_hmac_key(3, DST_RANDOM_BLOCK_SIZE / 2);#endif#if DST_NUM_HASHES >= 2		my_work->hash[1] = get_hmac_key(7, DST_RANDOM_BLOCK_SIZE / 6);#endif#if DST_NUM_HASHES >= 4		my_work->hash[3] = get_hmac_key(5, DST_RANDOM_BLOCK_SIZE / 4);#endif		my_work->hash[0] = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE);		if (my_work->hash[0] == NULL)	/* if failure bail out */			return (n);		s = own_random(my_work);/* if more generated than needed store it for future use */		if (s >= my_work->needed) {			EREPORT(("dst_s_random(): More than needed %d >= %d\n",				 s, my_work->needed));			memcpy(&output[n], my_work->output, my_work->needed);			n += my_work->needed;			/* saving unused data for next time */			unused = s - my_work->needed;			memcpy(old_unused, &my_work->output[my_work->needed],			       unused);		} else {			/* XXXX This should not happen */			EREPORT(("Not enough %d >= %d\n", s, my_work->needed));			memcpy(&output[n], my_work->output, s);			n += my_work->needed;		}/* delete the allocated work area */		for (i = 0; i < DST_NUM_HASHES; i++) {			dst_free_key(my_work->hash[i]->key);			SAFE_FREE(my_work->hash[i]);		}		SAFE_FREE(my_work->output);		SAFE_FREE(my_work);	}	return (n);}/* * A random number generator that is fast and strong  * this random number generator is based on HASHing data, * the input to the digest function is a collection of <NUMBER_OF_COUNTERS> * counters that is incremented between digest operations * each increment operation amortizes to 2 bits changed in that value * for 5 counters thus the input will amortize to have 10 bits changed  * The counters are initaly set using the strong random function above * the HMAC key is selected by the same methold as the HMAC keys for the  * strong random function.  * Each set of counters is used for 2^25 operations  *  * returns the number of bytes written to the output buffer  * or       negative number in case of error  */intdst_s_semi_random(u_char *output, unsigned size){	static u_int32_t counter[DST_NUMBER_OF_COUNTERS];	static u_char semi_old[DST_HASH_SIZE];	static int semi_loc = 0, cnt = 0;	static unsigned hb_size = 0;	static DST_KEY *my_key = NULL;	prand_hash *hash;	unsigned out = 0;	unsigned i;	int n;	if (output == NULL || size <= 0)		return (-2);/* check if we need a new key */	if (my_key == NULL || cnt > (1 << 25)) {	/* get HMAC KEY */		if (my_key)			my_key->dk_func->destroy(my_key);		if ((hash = get_hmac_key(1, DST_RANDOM_BLOCK_SIZE)) == NULL)			return (0);		my_key = hash->key;/* check if the key works stir the new key using some old random data */		hb_size = dst_sign_data(SIG_MODE_ALL, my_key, NULL, 				        (u_char *) counter, sizeof(counter),					semi_old, sizeof(semi_old));		if (hb_size <= 0) {			EREPORT(("dst_s_semi_random() Sign of alg %d failed %d\n",				 my_key->dk_alg, hb_size));			return (-1);		}/* new set the counters to random values */		dst_s_random((u_char *) counter, sizeof(counter));		cnt = 0;	}/* if old data around use it first */	if (semi_loc < hb_size) {		if (size <= hb_size - semi_loc) {	/* need less */			memcpy(output, &semi_old[semi_loc], size);			semi_loc += size;			return (size);	/* DONE */		} else {			out = hb_size - semi_loc;			memcpy(output, &semi_old[semi_loc], out);			semi_loc += out;		}	}/* generate more randome stuff */	while (out < size) {		/* 		 * modify at least one bit by incrementing at least one counter		 * based on the last bit of the last counter updated update		 * the next one.		 * minimaly this  operation will modify at least 1 bit, 		 * amortized 2 bits		 */		for (n = 0; n < DST_NUMBER_OF_COUNTERS; n++)			i = (int) counter[n]++;		i = dst_sign_data(SIG_MODE_ALL, my_key, NULL, 				  (u_char *) counter, hb_size,				  semi_old, sizeof(semi_old));		if (i != hb_size)			EREPORT(("HMAC SIGNATURE FAILURE %d\n", i));		cnt++;		if (size - out < i)	/* Not all data is needed */			semi_loc = i = size - out;		memcpy(&output[out], semi_old, i);		out += i;	}	return (out);}

⌨️ 快捷键说明

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