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

📄 pgprandompool.c

📁 PGP8.0源码 请认真阅读您的文件包然后写出其具体功能
💻 C
📖 第 1 页 / 共 3 页
字号:
	while (h--) {
		t = history[h];			/* Last delta */
		t = (x > t) ? x - t : t - x;	/* |x - history[h]| */
		history[h] = x;
		x = t;
		if (min > x)
			min = x;
	}
	return min;
}


	static PGPUInt32
sCollectEntropy()
{
	PGPUInt32			delta;
	PGPRandomContext	rc;
	
	/* call machine specific routine to get some entropy */
	pgpInitGlobalRandomPoolContext( &rc );
	delta	= pgpRandomCollectEntropy( &rc );
	
	return( delta );
}


/*
 * Gather and estimate entropy from keyboard timings.  Double letters
 * are allowed, but triples and more are considered suspiscious and
 * entropy is not counted.  (The actual criterion is that the current
 * letter has appeared more than once in the previous four letters,
 * which rejects aaaa... and ababa...)
 *
 * The "letter" can be generalized to mouse-clicks, button-pushes, menu
 * selections, or anything else that can be categorized into a finite
 * number of events.
 *
 * Question: is there a way to achieve this effect without remembering
 * the recent keystrokes so explicitly?  It seems like a possible
 * security hole.
 *
 * We incorporate entropy from the first 3 samples, but don't count them
 * since only after that many do we get reliable per-sample entropy estimates.
 * (This is time for the two entries in teh hist array to get initialized,
 * plus the one level of delta history implicitly included in the
 * ranGetEntropy timing.  It has to be there unless we want to export
 * knowledge about the modulus at which the timer it uses wraps.)
 */
#if ! PGPSDK_DRIVER
	static PGPUInt32
pgpGlobalRandomPoolAddKeystroke_internal( PGPInt32 event)
#else /* PGPSDK_DRIVER */
	PGPUInt32
PGPGlobalRandomPoolAddKeystroke( PGPInt32 event)
#endif /* PGPSDK_DRIVER */
{
	static PGPInt32		pastevent[4];	/* Last 4 events */
	static PGPUInt32	hist[2];
	static unsigned		histcount=elemsof(hist)+1;
						/* # invalid entries in hist array */
	PGPUInt32			delta;
	unsigned			n = 0;
	int					i;
	RandomPool			*pool = GetPool();
	PGPUInt32			result;
	
	pgpEnterZeroFunction();

#if (PGP_WIN32 || PGP_MACINTOSH) && ! PGPSDK_DRIVER
	/*
	** If the SDK driver is installed, do not count keystrokes added by
	** SDK clients because the keystroke has already been accounted
	** for in the driver.
	*/
	
	if( pgpSDKKeyboardEntropyDriverIsWorking() )
		return 0;
#endif

	delta = sCollectEntropy();
	delta = randEstimate(delta, hist, elemsof(hist));
    
	PGPRMWOLockStartWriting( &pool->criticalLock );

	sRandPoolAddBytes(NULL, (PGPByte *)&event, sizeof(event));

	/* Check for repetitive keystroke patterns */
	i = elemsof(pastevent) - 1;
	n = (event == pastevent[i]);
	do {
		n += (event == (pastevent[i] = pastevent[i-1]));
	} while (--i);
	pastevent[0] = event;

	if (histcount > 0) {
		/* Not yet filled hist array */
		--histcount;
		result = 0;
	}
	else if( n > 1 )
	{
		result = 0;
	}
	else
	{
		result = pgpGlobalRandomPoolEntropyWasAdded(delta);
	}
	
	PGPRMWOLockStopWriting( &pool->criticalLock );

	return( result );
}

#if ! PGPSDK_DRIVER
	PGPUInt32
PGPGlobalRandomPoolAddKeystroke( PGPInt32 event)
{
	pgpEnterZeroFunction();

#if (PGP_WIN32 || PGP_MACINTOSH) && ! PGPSDK_DRIVER
	/*
	** If the SDK driver is installed, do not count keystrokes added by
	** SDK clients because the keystroke has already been accounted
	** for in the driver.
	*/
	
	if( pgpSDKKeyboardEntropyDriverIsWorking() )
		return 0;
#endif

	return pgpGlobalRandomPoolAddState_back( TRUE, event, FALSE, FALSE );
}
#endif /* not PGPSDK_DRIVER */



/*
 * Generate entropy from mouse motion.  This simply measures entropy
 * of timing, although that may be pretty low due to OS synchrony.
 *
 * We incorporate entropy from the first 2 samples, but don't count them
 * since only after that many do the predictors start working.
 */
 
#if ! PGPSDK_DRIVER
	static PGPUInt32
pgpGlobalRandomPoolMouseMoved_internal(void)
#else /* PGPSDK_DRIVER */
	PGPUInt32
PGPGlobalRandomPoolMouseMoved(void)
#endif /* PGPSDK_DRIVER */
{
	static PGPUInt32	hist[2];			/* Timing history */
	static unsigned		histcount=elemsof(hist);
						/* # invalid entries in histx array */
	PGPUInt32			delta;				/* Timing delta */
	RandomPool			*pool = GetPool();
	PGPUInt32			result;
	
	pgpEnterZeroFunction();

#if PGP_WIN32 && ! PGPSDK_DRIVER
	/*
	** If the SDK driver is installed, do not count keystrokes added by
	** SDK clients because the keystroke has already been accounted
	** for in the driver.  We don't cancel this out for the Mac because
	** our Mac driver's granularity only measures the mouse once a second
	** which can be too little when collecting random data.
	*/
	
	if( pgpSDKMouseEntropyDriverIsWorking() )
		return 0;
#endif

	delta = sCollectEntropy();
	delta = randEstimate(delta, hist, elemsof(hist));

	PGPRMWOLockStartWriting( &pool->criticalLock );

	/* Wait until we have filled our arrays to start counting entropy */
	if (histcount > 0)
	{
		--histcount;
		result = 0;
	}
	else
	{
		result = pgpGlobalRandomPoolEntropyWasAdded(delta);
	}
	
	PGPRMWOLockStopWriting( &pool->criticalLock );
	
	return( result );
}

#if ! PGPSDK_DRIVER
	PGPUInt32
PGPGlobalRandomPoolMouseMoved(void)
{
	pgpEnterZeroFunction();

#if PGP_WIN32 && ! PGPSDK_DRIVER
	/*
	** If the SDK driver is installed, do not count keystrokes added by
	** SDK clients because the keystroke has already been accounted
	** for in the driver.  We don't cancel this out for the Mac because
	** our Mac driver's granularity only measures the mouse once a second
	** which can be too little when collecting random data.
	*/
	
	if( pgpSDKMouseEntropyDriverIsWorking() )
		return 0;
#endif

	return pgpGlobalRandomPoolAddState_back( FALSE, 0, TRUE, FALSE );
}
#endif /* not PGPSDK_DRIVER */


/*
 * Generate entropy from mouse motion. This all is provided for backwards
 * compatability. Mouse coordinates are no longer used.
 */
 
	PGPUInt32
PGPGlobalRandomPoolAddMouse(
	PGPUInt32		x,
	PGPUInt32		y)
{
	(void) x;
	(void) y;
	
	pgpEnterZeroFunction();

	return( PGPGlobalRandomPoolMouseMoved() );
}


/*
 *	DUMMY POOL
 *
 *	The dummy pool is a pluggable replacement for the RandPool to be used
 *	for generating values which we want to be unique but don't have to be
 *	cryptographically strong: such as the p and q values used in discrete
 *	log keys.  We prefer not to use the regular RandPool for such values
 *	so that we don't leak information about the secret values which are
 *	calculated in close proximity.
 *
 *	The dummy pool should be used as the "base" paramater for
 *	pgpRandomCreateX9_17.  It always returns 0 values, and the X9.17 RNG
 *	will then produce non-cryptographically-strong pseudo-random numbers.
 *
 *	Use pgpRandomAddBytes on the X9.17 RandomContext to seed it.
 */

/* Dummy pool always returns zeros */
	static void
sDummyPoolGetBytesEntropy(
	void *			priv,
	PGPByte *		buf,
	unsigned		len,
	unsigned		bits)
{
	(void)priv;
	(void)bits;
	
	pgpClearMemory( buf, len );
}

	static void
sDummyPoolAddBytes(
	void *			priv,
	PGPByte const *	p,
	unsigned		len)
{
	(void)priv;
	(void)p;
	(void)len;
}
	static void
sDummyPoolStir(void *priv)
{
	(void)priv;
}

static const PGPRandomVTBL sDummyRandomPoolVTBL =
{
	"Dummy random-number pool",
	sDummyPoolAddBytes,
	sDummyPoolGetBytesEntropy,
	sDummyPoolStir
};


	PGPRandomVTBL const *
pgpGetGlobalDummyRandomPoolVTBL( void )
{
	return( &sDummyRandomPoolVTBL );
}

#if ! PGPSDK_DRIVER
	static PGPError
pgpGlobalRandomPoolAddSystemState_internal()
#else /* PGPSDK_DRIVER */
PGPError
PGPGlobalRandomPoolAddSystemState()
#endif /* PGPSDK_DRIVER */
{
	PGPRandomContext rc;
	
	pgpEnterPGPErrorFunction();

	pgpInitGlobalRandomPoolContext( &rc );
	if (pgpRandomCollectOsData( &rc, TRUE )) {
		pgpSetIsSeeded();
		return kPGPError_NoErr;
	}
	else {
		return kPGPError_UnknownError;
	}
}


#if ! PGPSDK_DRIVER
/* This is always called from the front end */
PGPError
PGPGlobalRandomPoolAddSystemState()
{
	pgpEnterPGPErrorFunction();

	return pgpGlobalRandomPoolAddState_back( FALSE, 0, FALSE, TRUE );
}


/* Entry point for back end (or if no back end is running */
	PGPError
pgpGlobalRandomPoolAddState_internal( PGPBoolean addKeyState,
	PGPInt32 keyEvent, PGPBoolean addMouseState, PGPBoolean addSystemState )
{
	if( addKeyState )
		(void) pgpGlobalRandomPoolAddKeystroke_internal( keyEvent );
	else if( addMouseState )
		(void) pgpGlobalRandomPoolMouseMoved_internal( );
	else if( addSystemState )
		return pgpGlobalRandomPoolAddSystemState_internal( );
	return kPGPError_NoErr;
}
#endif /* not PGPSDK_DRIVER */


#if ! PGPSDK_DRIVER
/* This is always called from the front end */
PGPBoolean
PGPGlobalRandomPoolHasIntelRNG( )
{
	PGPBoolean hasIntelRNG = FALSE;

	pgpEnterPGPErrorFunction();

	(void)pgpGlobalRandomPoolGetInfo_back( NULL, NULL, NULL, NULL,
										   &hasIntelRNG );
	return hasIntelRNG;
}
#endif /* not PGPSDK_DRIVER */


/*
 * Accumulate entropy from key into pool.
 * See comments with pgpGlobalRandomPoolEntropyWasAdded for how
 * the arithmetic works.
 */
static void
sRandAddKeyEntropy( RandomPool *pool )
{
	PGPUInt32		frac,		/* Fractional bits to add */
					keyfrac,
					t;
	PGPUInt32		n;			/* Number of whole bits to add */

	/* Add entropy from randKey into randPool */
	keyfrac = pool->randKeyFrac;
	frac = pool->randFrac;
	n = pool->randKeyBits;
	UMULH_32(t,keyfrac,frac);

	/* The comparison idiom used here detects overflow on addition */
	if ((frac += t) < t) {
		if ((frac += keyfrac) < keyfrac)
			frac = (frac >> 1) + 0x80000000ul;
		else
			frac >>= 1;
		n++;
	} else if ((frac += keyfrac) < keyfrac) {
		frac >>= 1;
		n++;
	}

	pool->randFrac = frac;
	if ((pool->randBits += n) >= RANDPOOLBITS) {
		/* Overflow - saturate at RANDPOOLBITS */
		pool->randBits = RANDPOOLBITS;
		pool->randFrac = 0;
	}
	/* Also count the inflow without regard to outflow */
	if ((pool->randInBits += n) >= RANDPOOLBITS) {
		pool->randInBits = RANDPOOLBITS;
	}
	pool->randKeyBits = pool->randKeyFrac = 0;
}


/*__Editor_settings____

	Local Variables:
	tab-width: 4
	End:
	vi: ts=4 sw=4
	vim: si
_____________________*/

⌨️ 快捷键说明

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