kerneltest/e32utils/nistsecurerng/src/assess.cpp
changeset 152 657f875b013e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32utils/nistsecurerng/src/assess.cpp	Fri Jun 11 15:02:23 2010 +0300
@@ -0,0 +1,419 @@
+/*
+* Portions Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+*/
+
+
+/* --------------------------------------------------------------------------
+   Title       :  The NIST Statistical Test Suite
+
+   Date        :  December 1999
+
+   Programmer  :  Juan Soto
+
+   Summary     :  For use in the evaluation of the randomness of bitstreams
+                  produced by cryptographic random number generators.
+
+   Package     :  Version 1.0
+
+   Copyright   :  (c) 1999 by the National Institute Of Standards & Technology
+
+   History     :  Version 1.0 by J. Soto, October 1999
+                  Revised by J. Soto, November 1999
+                  Revised by Larry Bassham, March 2008
+
+   Keywords    :  Pseudorandom Number Generator (PRNG), Randomness, Statistical 
+                  Tests, Complementary Error functions, Incomplete Gamma 
+                  Function, Random Walks, Rank, Fast Fourier Transform, 
+                  Template, Cryptographically Secure PRNG (CSPRNG),
+                  Approximate Entropy (ApEn), Secure Hash Algorithm (SHA-1), 
+                  Blum-Blum-Shub (BBS) CSPRNG, Micali-Schnorr (MS) CSPRNG, 
+
+   Source      :  David Banks, Elaine Barker, James Dray, Allen Heckert, 
+                  Stefan Leigh, Mark Levenson, James Nechvatal, Andrew Rukhin, 
+                  Miles Smid, Juan Soto, Mark Vangel, and San Vo.
+
+   Technical
+   Assistance  :  Larry Bassham, Ron Boisvert, James Filliben, Daniel Lozier,
+                  and Bert Rust.
+
+   Warning     :  Portability Issues.
+
+   Limitation  :  Amount of memory allocated for workspace.
+
+   Restrictions:  Permission to use, copy, and modify this software without 
+                  fee is hereby granted, provided that this entire notice is 
+                  included in all copies of any software which is or includes
+                  a copy or modification of this software and in all copies 
+                  of the supporting documentation for such software.
+   -------------------------------------------------------------------------- */
+//system include
+#include <e32base.h>
+#include <e32std.h>
+#include <e32cons.h>
+
+// user include
+#include "openc.h"
+#include "../include/decls.h"
+#include "../include/cephes.h"  
+#include "../include/utilities.h"
+#include "../include/generators.h"
+
+typedef int (*CompareFnType)(const void*, const void*);
+
+void	partitionResultFile(int numOfFiles, int numOfSequences, int option, int testNameID);
+void	postProcessResults(int option);
+int		cmp(const double *a, const double *b);
+int		computeMetrics(char *s, int test);
+
+int
+StartNISTTest()
+{
+	int		i;
+	int		option = 10;			/* TEMPLATE LENGTH/STREAM LENGTH/GENERATOR*/
+	char	*streamFile = NULL;	/* STREAM FILENAME     */
+	
+
+	tp.n = 1000000; // length of the individual bit stream(s) to be processed
+	tp.blockFrequencyBlockLength = 128;
+	tp.nonOverlappingTemplateBlockLength = 9;
+	tp.overlappingTemplateBlockLength = 9;
+	tp.approximateEntropyBlockLength = 10;
+	tp.serialBlockLength = 16;
+	tp.linearComplexitySequenceLength = 500;
+	tp.numOfBitStreams = 100;
+	chooseTests();
+	fixParameters();
+	openOutputStreams(option);
+	invokeTestSuite(option, streamFile);
+	fclose(freqfp);
+	for( i=1; i<=NUMOFTESTS; i++ ) {
+		if ( stats[i] != NULL )
+			fclose(stats[i]);
+		if ( results[i] != NULL )
+			fclose(results[i]);
+	}
+	if ( (testVector[0] == 1) || (testVector[TEST_CUSUM] == 1) ) 
+		partitionResultFile(2, tp.numOfBitStreams, option, TEST_CUSUM);
+	if ( (testVector[0] == 1) || (testVector[TEST_NONPERIODIC] == 1) ) 
+		partitionResultFile(MAXNUMOFTEMPLATES, tp.numOfBitStreams, option, TEST_NONPERIODIC);
+	if ( (testVector[0] == 1) || (testVector[TEST_RND_EXCURSION] == 1) )
+		partitionResultFile(8, tp.numOfBitStreams, option, TEST_RND_EXCURSION);
+	if ( (testVector[0] == 1) || (testVector[TEST_RND_EXCURSION_VAR] == 1) )
+		partitionResultFile(18, tp.numOfBitStreams, option, TEST_RND_EXCURSION_VAR);
+	if ( (testVector[0] == 1) || (testVector[TEST_SERIAL] == 1) )
+		partitionResultFile(2, tp.numOfBitStreams, option, TEST_SERIAL);
+	fprintf(summary, "------------------------------------------------------------------------------\n");
+	fprintf(summary, "RESULTS FOR THE UNIFORMITY OF P-VALUES AND THE PROPORTION OF PASSING SEQUENCES\n");
+	fprintf(summary, "------------------------------------------------------------------------------\n");
+	fprintf(summary, " C1  C2  C3  C4  C5  C6  C7  C8  C9 C10  P-VALUE  PROPORTION  STATISTICAL TEST\n");
+	fprintf(summary, "------------------------------------------------------------------------------\n");
+	postProcessResults(option);
+	fclose(summary);
+
+	return 1;
+    }
+
+void
+partitionResultFile(int numOfFiles, int numOfSequences, int option, int testNameID)
+{ 
+	int		i, k, m, j, start, end, num, numread;
+	float	c;
+	FILE	**fp = (FILE **)calloc(numOfFiles+1, sizeof(FILE *));
+	int		*results = (int *)calloc(numOfFiles, sizeof(int *));
+	char	*s[MAXFILESPERMITTEDFORPARTITION];
+	char	resultsDir[200];
+	
+	for ( i=0; i<MAXFILESPERMITTEDFORPARTITION; i++ )
+		s[i] = (char*)calloc(200, sizeof(char));
+	
+	sprintf(resultsDir, "%s\\experiments\\%s\\%s\\results", gLogFilePath.PtrZ(), generatorDir[option], testNames[testNameID]);
+	
+	if ( (fp[numOfFiles] = fopen(resultsDir, "r")) == NULL ) {
+		printf("%s", resultsDir);
+		printf(" -- file not found. Exiting program.\n");
+		exit(-1);
+	}
+	
+	for ( i=0; i<numOfFiles; i++ ) 
+	    {
+		sprintf(s[i], "%s\\experiments\\%s\\%s\\data%d", gLogFilePath.PtrZ(), generatorDir[option], testNames[testNameID], i+1);
+        }
+	numread = 0;
+	m = numOfFiles/20;
+	if ( (numOfFiles%20) != 0 )
+		m++;
+	for ( i=0; i<numOfFiles; i++ ) {
+		if ( (fp[i] = fopen(s[i], "w")) == NULL ) {
+			printf("%s", s[i]);
+			printf(" -- file not found. Exiting program.\n");
+			exit(-1);
+		}
+		fclose(fp[i]);
+	}
+	for ( num=0; num<numOfSequences; num++ ) {
+		for ( k=0; k<m; k++ ) { 			/* FOR EACH BATCH */
+			
+			start = k*20;		/* BOUNDARY SEGMENTS */
+			end   = k*20+19;
+			if ( k == (m-1) )
+				end = numOfFiles-1;
+			
+			for ( i=start; i<=end; i++ ) {		/* OPEN FILE */
+				if ( (fp[i] = fopen(s[i], "a")) == NULL ) {
+					printf("%s", s[i]);
+					printf(" -- file not found. Exiting program.\n");
+					exit(-1);
+				}
+			}
+			
+			for ( j=start; j<=end; j++ ) {		/* POPULATE FILE */
+				fscanf(fp[numOfFiles], "%f", &c);
+				fprintf(fp[j], "%f\n", c);
+				numread++;
+			}
+
+			for ( i=start; i<=end; i++ )		/* CLOSE FILE */
+				fclose(fp[i]);
+		}
+	}
+	fclose(fp[numOfFiles]);
+	for ( i=0; i<MAXFILESPERMITTEDFORPARTITION; i++ )
+		free(s[i]);
+	
+	free(fp);
+	free(results);
+	return;
+}
+
+int
+cmp(const double *a, const double *b)
+{
+	if ( *a < *b )
+		return -1;
+	if ( *a == *b )
+		return 0;
+	return 1;
+}
+
+void
+postProcessResults(int option)
+{
+	int    i, k;
+	int    randomExcursionSampleSize = 0;
+	int    generalSampleSize = 0;
+	int		case1, case2, numOfFiles = 2;
+	double	passRate;
+	char	s[200];
+	
+	for ( i=1; i<=NUMOFTESTS; i++ ) {		// FOR EACH TEST
+		if ( testVector[i] ) {
+			// SPECIAL CASES -- HANDLING MULTIPLE FILES FOR A SINGLE TEST
+			if ( ((i == TEST_CUSUM) && testVector[TEST_CUSUM] ) ||
+				 ((i == TEST_NONPERIODIC) && testVector[TEST_NONPERIODIC] ) ||
+				 ((i == TEST_RND_EXCURSION) && testVector[TEST_RND_EXCURSION]) ||
+				 ((i == TEST_RND_EXCURSION_VAR) && testVector[TEST_RND_EXCURSION_VAR]) || 
+				 ((i == TEST_SERIAL) && testVector[TEST_SERIAL]) ) {
+				
+				if ( (i == TEST_NONPERIODIC) && testVector[TEST_NONPERIODIC] )  
+					numOfFiles = MAXNUMOFTEMPLATES;
+				else if ( (i == TEST_RND_EXCURSION) && testVector[TEST_RND_EXCURSION] ) 
+					numOfFiles = 8;
+				else if ( (i == TEST_RND_EXCURSION_VAR) && testVector[TEST_RND_EXCURSION_VAR] ) 
+					numOfFiles = 18;
+				else
+					numOfFiles = 2;
+				for ( k=0; k<numOfFiles; k++ ) {
+					if ( k < 10 )
+						sprintf(s, "%s\\experiments\\%s\\%s\\data%1d", gLogFilePath.PtrZ(), generatorDir[option], testNames[i], k+1);
+					else if ( k < 100 )
+						sprintf(s, "%s\\experiments\\%s\\%s\\data%2d", gLogFilePath.PtrZ(), generatorDir[option], testNames[i], k+1);
+					else
+						sprintf(s, "%s\\experiments\\%s\\%s\\data%3d", gLogFilePath.PtrZ(), generatorDir[option], testNames[i], k+1);
+					if ( (i == TEST_RND_EXCURSION) || (i == TEST_RND_EXCURSION_VAR) ) 
+						randomExcursionSampleSize = computeMetrics(s,i);
+					else
+						generalSampleSize = computeMetrics(s,i);
+				}
+			}
+			else {
+				sprintf(s, "%s\\experiments\\%s\\%s\\results", gLogFilePath.PtrZ(), generatorDir[option], testNames[i]);
+				generalSampleSize = computeMetrics(s,i);
+			}
+		}
+	}
+
+	fprintf(summary, "\n\n- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
+	case1 = 0;
+	case2 = 0;
+	if ( testVector[TEST_RND_EXCURSION] || testVector[TEST_RND_EXCURSION_VAR] ) 
+		case2 = 1;
+	for ( i=1; i<=NUMOFTESTS; i++ ) {
+		if ( testVector[i] && (i != TEST_RND_EXCURSION) && (i != TEST_RND_EXCURSION_VAR) ) {
+			case1 = 1;
+			break;
+		}
+	}
+	if ( case1 ) {
+		if ( generalSampleSize == 0 ) {
+			fprintf(summary, "The minimum pass rate for each statistical test with the exception of the\n");
+			fprintf(summary, "random excursion (variant) test is undefined.\n\n");
+		}
+		else {
+			passRate = 0.99-3.0*sqrt(0.01*(1.0-ALPHA)/(double)generalSampleSize);
+			fprintf(summary, "The minimum pass rate for each statistical test with the exception of the\n");
+			fprintf(summary, "random excursion (variant) test is approximately = %f for a\n", generalSampleSize ? passRate : 0.0);
+			fprintf(summary, "sample size = %d binary sequences.\n\n", generalSampleSize);
+		}
+	}
+	if ( case2 ) {
+		if ( randomExcursionSampleSize == 0 )
+			fprintf(summary, "The minimum pass rate for the random excursion (variant) test is undefined.\n\n");
+		else {
+			passRate = 0.99-3.0*sqrt(0.01*(1.0-ALPHA)/(double)randomExcursionSampleSize);
+			fprintf(summary, "The minimum pass rate for the random excursion (variant) test\n");
+			fprintf(summary, "is approximately %f for a sample size = %d binary sequences.\n\n", passRate, randomExcursionSampleSize);
+		}
+	}
+	fprintf(summary, "For further guidelines construct a probability table using the MAPLE program\n");
+	fprintf(summary, "provided in the addendum section of the documentation.\n");
+	fprintf(summary, "- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -\n");
+}
+
+int
+computeMetrics(char *s, int test)
+{
+	int		j, pos, count, sampleSize, expCount;
+	int		freqPerBin[10] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+	double	*A = NULL;
+	double  *T = NULL;
+	double  chi2, proportion, uniformity;
+	float	c;
+	FILE	*fp = NULL;
+
+	if ( (fp = fopen(s, "r")) == NULL ) {
+		printf("%s",s);
+		printf(" -- file not found. Exiting program.\n");
+		exit(-1);
+	}
+	
+	/* Compute Metric 1: Proportion of Passing Sequences */
+	
+	count = 0; 		
+	sampleSize = tp.numOfBitStreams;
+	
+	if ( (test == TEST_RND_EXCURSION) || (test == TEST_RND_EXCURSION_VAR) ) { /* Special Case: Random Excursion Tests */
+		if ( (T = (double *)calloc(tp.numOfBitStreams, sizeof(double))) == NULL ) {
+			printf("Final Analysis Report aborted due to insufficient workspace\n");
+			// Perform cleanup before returning
+			fclose(fp);
+			return 0;
+		}
+		for ( j=0; j<sampleSize; j++ ) {
+			fscanf(fp, "%f", &c);
+			if ( c > 0.000000 )
+				T[count++] = c;
+		}
+
+		if ( (A = (double *)calloc(count, sizeof(double))) == NULL ) {
+			printf("Final Analysis Report aborted due to insufficient workspace\n");
+            // Perform cleanup before returning
+            fclose(fp);
+            free(T);
+			return 0;
+		}
+
+		for ( j=0; j<count; j++ )
+			A[j] = T[j];
+		
+		sampleSize = count;
+		count = 0;
+		for ( j=0; j<sampleSize; j++ )
+			if ( A[j] < ALPHA )
+				count++;
+		free(T);
+		T = NULL;
+	}
+	else {
+		if ( (A = (double *)calloc(sampleSize, sizeof(double))) == NULL ) {
+			printf("Final Analysis Report aborted due to insufficient workspace\n");
+            // Perform cleanup before returning
+            fclose(fp);
+			return 0;
+		}
+		for ( j=0; j<sampleSize; j++ ) {
+			fscanf(fp, "%f", &c);
+			if ( c < ALPHA )
+				count++;
+			A[j] = c;
+		}
+	}
+	if ( sampleSize == 0 )
+		proportion = 0.0;
+	else
+		proportion = 1.0-(double)count/sampleSize;
+
+	/* Compute Metric 2: Histogram */
+
+	qsort((void *)A, sampleSize, sizeof(double), (CompareFnType)cmp);
+	
+	for ( j=0; j<sampleSize; j++ ) {
+		pos = (int)floor(A[j]*10);
+		if ( pos == 10 )
+			pos--;
+		freqPerBin[pos]++;
+	}
+	chi2 = 0.0;
+	expCount = sampleSize/10;
+	for ( j=0; j<10; j++ )
+		chi2 += pow(freqPerBin[j]-expCount, 2)/expCount;
+	uniformity = cephes_igamc(9.0/2.0, chi2/2.0);
+
+	for ( j=0; j<10; j++ )			/* DISPLAY RESULTS */
+		fprintf(summary, "%3d ", freqPerBin[j]);
+
+	if ( expCount == 0 )
+		fprintf(summary, "    ----    ");
+	else if ( uniformity < 0.0001 )
+		fprintf(summary, " %8.6f * ", uniformity);
+	else
+		fprintf(summary, " %8.6f   ", uniformity);
+
+	if ( sampleSize == 0 )
+		fprintf(summary, " ----     %s\n", testNames[test]);
+	else if ( proportion < 0.96 )
+		fprintf(summary, "%6.4f *  %s\n", proportion, testNames[test]);
+	else
+		fprintf(summary, "%6.4f    %s\n", proportion, testNames[test]);
+
+	fclose(fp);
+	free(A);
+	
+	return sampleSize;
+}
+
+/*
+Gobal Entry Function
+*/
+GLDEF_C TInt E32Main()
+    {
+    __UHEAP_MARK;
+    TInt ret = StartNISTTest();
+    __UHEAP_MARKEND;
+    
+    return ret;
+    }
+
+
+