[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: kernel/1671: Not enough random bytes available (GnuPG & OBSD2.8)



The following reply was made to PR kernel/1671; it has been noted by GNATS.

From: Brad Allen <Ulmo_(_at_)_Q_(_dot_)_Net>
To: deraadt_(_at_)_cvs_(_dot_)_openbsd_(_dot_)_org
Cc: ulmo_(_at_)_BayView_(_dot_)_COM, gnats_(_at_)_openbsd_(_dot_)_org
Subject: Re: kernel/1671: Not enough random bytes available (GnuPG &
 OBSD2.8) 
Date: Sat, 10 Feb 2001 20:45:35 -0400 (AST)

 From: Theo de Raadt <deraadt_(_at_)_cvs_(_dot_)_openbsd_(_dot_)_org>
 Subject: Re: kernel/1671: Not enough random bytes available (GnuPG & OBSD2.8) 
 Date: Tue, 06 Feb 2001 02:51:05 -0700
 Message-ID: <200102060951_(_dot_)_f169p5b29957_(_at_)_cvs_(_dot_)_openbsd_(_dot_)_org>
 
 deraadt> I bet that gpg is one of those completely retarded programs
 deraadt> that opens /dev/srandom using stdio.  Which then tries to go
 deraadt> and read 8K which it will never use.
 
 Relevent lines from gnupg-1.0.4.tar.gz: cipher/rndlinux.c: [used for OpenBSD]
 81:    fd = open( name, O_RDONLY );
 106:    byte buffer[768];
 126:    while( length ) {
 143:"Not enough random bytes available.  Please do some other work to give\n"
     "the OS a chance to collect more entropy! (Need %d more bytes)\n"), length );
 159:	    int nbytes = length < sizeof(buffer)? length : sizeof(buffer);
 160:	    n = read(fd, buffer, nbytes );
 170:        length -= n;
 
 Apparently, you are mistaken: GnuPG in this incarnation knows
 precisely how many octets it needs, and then goes after them one by
 one.  Sticking a debugging line in there to reveal how many octets
 it's reading, I find in just one run each (I didn't search very deeply
 to see if this changes under conditions):
 
 signing:           0x10 octets
 encrypt:           0x10 octets
 sign and encrypt:  0x10 octets.
 
 BTW, the problem and fix *might* be related to the RTC (Real Time
 Clock).  I am preparing a large bug report, and want more time to
 polish it off.  Just in case it gets lost in time, I will give you
 this patch as a clue as to what I think is a clue, and tell you I
 haven't had this problem *yet*, but the last time I had it it was
 after a few weeks of uptime and I still don't know what the trigger
 is:
 
 Index: clock.c
 ===================================================================
 RCS file: /cvs/src/sys/arch/i386/isa/clock.c,v
 retrieving revision 1.21
 diff -u -r1.21 clock.c
 --- clock.c	2000/01/29 04:27:48	1.21
 +++ clock.c	2001/02/11 00:35:11
 @@ -207,7 +207,62 @@
  	hardclock(frame);
  	return 1;
  }
 +#if 0
  
 +This is what was in FreeBSD:
 +
 +? log
 +? clock.c.annotate
 +? clock.c.diff
 +Index: clock.c
 +===================================================================
 +RCS file: /home/ncvs/src/sys/i386/isa/clock.c,v
 +retrieving revision 1.79
 +retrieving revision 1.80
 +diff -u -r1.79 -r1.80
 +--- clock.c	1997/03/05 08:08:48	1.79
 ++++ clock.c	1997/04/06 13:25:48	1.80
 +@@ -34,7 +34,7 @@
 +  * SUCH DAMAGE.
 +  *
 +  *	from: @(#)clock.c	7.2 (Berkeley) 5/12/91
 +- *	$Id: clock.c,v 1.78 1997/03/05 00:54:00 gpalmer Exp $
 ++ *	$Id: clock.c,v 1.79 1997/03/05 08:08:48 bde Exp $
 +  */
 + 
 + /*
 +@@ -311,15 +311,20 @@
 +  *
 +  * The RTC chip requires that we read status register C (RTC_INTR)
 +  * to acknowledge an interrupt, before it will generate the next one.
 ++ * Under high interrupt load, rtcintr() can be indefinitely delayed and
 ++ * the clock can tick immediately after the read from RTC_INTR.  In this
 ++ * case, the mc146818A interrupt signal will not drop for long enough
 ++ * to register with the 8259 PIC.  If an interrupt is missed, the stat
 ++ * clock will halt, considerably degrading system performance.  This is
 ++ * why we use 'while' rather than a more straightforward 'if' below.
 ++ * Stat clock ticks can still be lost, causing minor loss of accuracy
 ++ * in the statistics, but the stat clock will no longer stop.
 +  */
 + static void
 + rtcintr(struct clockframe frame)
 + {
 +-	u_char stat;
 +-	stat = rtcin(RTC_INTR);
 +-	if(stat & RTCIR_PERIOD) {
 ++	while (rtcin(RTC_INTR) & RTCIR_PERIOD)
 + 		statclock(&frame);
 +-	}
 + }
 + 
 + #include "opt_ddb.h"
 +
 +
 +So, my interpretation (and therefore interpolation) will follow.
 +
 +#endif /* 0 */
 +
 +
  int
  rtcintr(arg)
  	void *arg;
 @@ -215,12 +270,38 @@
  	struct clockframe *frame = arg;		/* not strictly neccecary */
  	u_int stat;
  
 +#if 0
  	stat = mc146818_read(NULL, MC_REGC);
  	if (stat & MC_REGC_PF) {
  		statclock(frame);
  		return 1;
  	}
 +
 +	return 0;
 +#elif 0
 +	if (!((mc146818_read(NULL, MC_REGC) & MC_REGC_PF))) return 0;
 +	do statclock(frame);
 +	while (mc146818_read(NULL, MC_REGC) & MC_REGC_PF);
 +	return 1;
 +#else /* 0 */
 +	stat = mc146818_read(NULL, MC_REGC);
 +	if (stat & MC_REGC_PF) {
 +	repeat:
 +		statclock(frame);
 +		return 1;
 +	}
 +	stat = mc146818_read(NULL, MC_REGC);
 +	if (stat & MC_REGC_PF) {
 +		static u_char gave_mc146818_repeating_message=0;
 +		if(!gave_mc146818_repeating_message) {
 +		  gave_mc146818_repeating_message=1;
 +		  printf("stat clock repeat"); /* how do I err msg? */
 +		}
 +		goto repeat;
 +	}
 +
  	return 0;
 +#endif /* 0 */
  }
  
  int
 



Visit your host, monkey.org