--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/kerneltest/e32utils/nistsecurerng/src/assess.cpp Tue Aug 31 16:34:26 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;
+ }
+
+
+