summaryrefslogtreecommitdiffstats
path: root/pki/base/native-tools/src/tkstool/random.c
diff options
context:
space:
mode:
Diffstat (limited to 'pki/base/native-tools/src/tkstool/random.c')
-rw-r--r--pki/base/native-tools/src/tkstool/random.c173
1 files changed, 173 insertions, 0 deletions
diff --git a/pki/base/native-tools/src/tkstool/random.c b/pki/base/native-tools/src/tkstool/random.c
new file mode 100644
index 000000000..49dfb525e
--- /dev/null
+++ b/pki/base/native-tools/src/tkstool/random.c
@@ -0,0 +1,173 @@
+/* --- BEGIN COPYRIGHT BLOCK ---
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2007 Red Hat, Inc.
+ * All rights reserved.
+ * --- END COPYRIGHT BLOCK ---
+ */
+
+#include "tkstool.h"
+
+/* returns 0 for success, -1 for failure (EOF encountered) */
+static int
+UpdateRNG( void )
+{
+ char *randbuf;
+ int fd;
+ int i;
+ int count;
+ int c;
+ int rv = 0;
+#ifdef XP_UNIX
+ cc_t orig_cc_min;
+ cc_t orig_cc_time;
+ tcflag_t orig_lflag;
+ struct termios tio;
+#endif
+
+#define FPS PR_fprintf( PR_STDOUT,
+ FPS "\n");
+ FPS "A random seed must be generated that will be used in the\n");
+ FPS "creation of your key. One of the easiest ways to create a\n");
+ FPS "random seed is to use the timing of keystrokes on a keyboard.\n");
+ FPS "\n");
+ FPS "To begin, type keys on the keyboard until this progress meter\n");
+ FPS "is full. DO NOT USE THE AUTOREPEAT FUNCTION ON YOUR KEYBOARD!\n");
+ FPS "\n");
+ FPS "\n");
+ FPS "Continue typing until the progress meter is full:\n\n");
+ FPS "| |\r|");
+
+ /* turn off echo on stdin & return on 1 char instead of NL */
+ fd = fileno( stdin );
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ tcgetattr( fd, &tio );
+ orig_lflag = tio.c_lflag;
+ orig_cc_min = tio.c_cc[VMIN];
+ orig_cc_time = tio.c_cc[VTIME];
+ tio.c_lflag &= ~ECHO;
+ tio.c_lflag &= ~ICANON;
+ tio.c_cc[VMIN] = 1;
+ tio.c_cc[VTIME] = 0;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ /* Get random noise from keyboard strokes */
+ randbuf = ( char * ) PORT_Alloc( RAND_BUF_LENGTH );
+ count = 0;
+ while( randbuf != NULL && count < NUM_KEYSTROKES+1 ) {
+#ifdef VMS
+ c = GENERIC_GETCHAR_NOECHO();
+#elif XP_UNIX
+ c = getc( stdin );
+#else
+ c = getch();
+#endif
+ if( c == EOF ) {
+ rv = -1;
+ break;
+ }
+
+ PK11_RandomUpdate(
+ /* data */ randbuf,
+ /* length in bytes */ RAND_BUF_LENGTH );
+
+ if( c != randbuf[0] ) {
+ randbuf[0] = c;
+
+ FPS "\r|");
+
+ for( i = 0 ;
+ i < count / ( NUM_KEYSTROKES / RAND_BUF_LENGTH ) ;
+ i++ ) {
+ FPS "*");
+ }
+
+ if( count % ( NUM_KEYSTROKES / RAND_BUF_LENGTH ) == 1 ) {
+ FPS "/");
+ }
+
+ count++;
+ }
+ }
+
+ if (randbuf != NULL) free (randbuf);
+
+ FPS "\n\n");
+ FPS "Finished.\n");
+
+ TKS_TypeProceedToContinue();
+
+ FPS "\n");
+
+#undef FPS
+
+#if defined( XP_UNIX ) && !defined( VMS )
+ /* set back termio the way it was */
+ tio.c_lflag = orig_lflag;
+ tio.c_cc[VMIN] = orig_cc_min;
+ tio.c_cc[VTIME] = orig_cc_time;
+ tcsetattr( fd, TCSAFLUSH, &tio );
+#endif
+
+ return rv;
+}
+
+
+void
+TKS_FileForRNG( char *noise )
+{
+ char buf[2048];
+ PRFileDesc *fd;
+ PRInt32 count;
+
+ fd = PR_OpenFile( noise, PR_RDONLY, 0666 );
+ if( !fd ) {
+ return;
+ }
+
+ do {
+ count = PR_Read( fd, buf, sizeof( buf ) );
+ if (count > 0) {
+ PK11_RandomUpdate(
+ /* data */ buf,
+ /* length in bytes */ count );
+ }
+ } while( count > 0 );
+
+ PR_Close( fd );
+}
+
+
+SECStatus
+TKS_SeedRNG( char *noise )
+{
+ /* Clear the screen */
+ TKS_ClearScreen();
+
+ /* Seed the RNG */
+ if( noise ) {
+ TKS_FileForRNG( noise );
+ } else {
+ int rv = UpdateRNG();
+ if( rv ) {
+ PORT_SetError( PR_END_OF_FILE_ERROR );
+ return SECFailure;
+ }
+ }
+
+ return SECSuccess;
+}
+