os/security/crypto/weakcrypto/test/trandom/t_random.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
* (c) 1999 Symbian Ltd
sl@0
    16
*
sl@0
    17
*/
sl@0
    18
sl@0
    19
sl@0
    20
/**
sl@0
    21
 @file
sl@0
    22
*/
sl@0
    23
sl@0
    24
#include <e32base.h>
sl@0
    25
#include <e32std.h>
sl@0
    26
#include <e32test.h>
sl@0
    27
#include <random.h>
sl@0
    28
#include <f32file.h>
sl@0
    29
sl@0
    30
#include <randsvr.h>
sl@0
    31
sl@0
    32
RTest test(_L("Random Number Generator Tests"));
sl@0
    33
sl@0
    34
TInt gNumberOfRandomNumbers=10000;
sl@0
    35
sl@0
    36
/** Wraps a console and logs output to a file. */
sl@0
    37
class CTestConsole:public CConsoleBase
sl@0
    38
	{
sl@0
    39
	public:
sl@0
    40
		static CTestConsole* NewL(CConsoleBase* aCon, const TDesC& aFilename);
sl@0
    41
		TInt Create(const TDesC16& aTitle,TSize aSize) {return iCon->Create(aTitle,aSize);};
sl@0
    42
		void Read(TRequestStatus& aStatus) {iCon->Read(aStatus);};
sl@0
    43
		void ReadCancel(void) {iCon->ReadCancel();};
sl@0
    44
		void Write(const TDesC16& aString);
sl@0
    45
		TPoint CursorPos(void) const {return iCon->CursorPos();};
sl@0
    46
		void SetCursorPosAbs(const TPoint& aPos) {iCon->SetCursorPosAbs(aPos);};
sl@0
    47
		void SetCursorPosRel(const TPoint& aPos) {iCon->SetCursorPosRel(aPos);};
sl@0
    48
		void SetCursorHeight(TInt aHeight) {iCon->SetCursorHeight(aHeight);};
sl@0
    49
		void SetTitle(const TDesC16& aTitle) {iCon->SetTitle(aTitle);};
sl@0
    50
		void ClearScreen(void) {iCon->ClearScreen();};
sl@0
    51
		void ClearToEndOfLine(void) {iCon->ClearToEndOfLine();};
sl@0
    52
		TSize ScreenSize(void) const {return iCon->ScreenSize();};
sl@0
    53
		TKeyCode KeyCode(void) const {return iCon->KeyCode();};
sl@0
    54
		TUint KeyModifiers(void) const {return iCon->KeyModifiers();};
sl@0
    55
		~CTestConsole(void);
sl@0
    56
	private:
sl@0
    57
		CTestConsole(CConsoleBase* aCon);
sl@0
    58
	    void ConstructL(const TDesC& aFilename);
sl@0
    59
	    CConsoleBase* iCon;  ///< Pointer to wrapped console, we don't own this
sl@0
    60
	    RFs iFs;
sl@0
    61
	    RFile iFile;		 ///< Log file
sl@0
    62
	};
sl@0
    63
sl@0
    64
CTestConsole* CTestConsole::NewL(CConsoleBase* aCon, const TDesC& aFilename)
sl@0
    65
sl@0
    66
	{
sl@0
    67
	CTestConsole* self;
sl@0
    68
	self=new (ELeave) CTestConsole(aCon);
sl@0
    69
	CleanupStack::PushL(self);
sl@0
    70
	self->ConstructL(aFilename);
sl@0
    71
	CleanupStack::Pop(self);
sl@0
    72
	return self;
sl@0
    73
	}
sl@0
    74
sl@0
    75
CTestConsole::CTestConsole(CConsoleBase* aCon) :
sl@0
    76
	CConsoleBase(), iCon(aCon)
sl@0
    77
sl@0
    78
	{
sl@0
    79
	}
sl@0
    80
sl@0
    81
void CTestConsole::ConstructL(const TDesC& aFilename)
sl@0
    82
	
sl@0
    83
	{
sl@0
    84
	User::LeaveIfError(iFs.Connect());
sl@0
    85
	User::LeaveIfError(iFile.Replace(iFs,aFilename,EFileShareAny|EFileWrite));
sl@0
    86
	}
sl@0
    87
sl@0
    88
CTestConsole::~CTestConsole(void)
sl@0
    89
sl@0
    90
	{
sl@0
    91
	iFile.Close();
sl@0
    92
	iFs.Close();
sl@0
    93
	}
sl@0
    94
sl@0
    95
void CTestConsole::Write(const TDesC16& aString)
sl@0
    96
sl@0
    97
	{
sl@0
    98
	iCon->Write(aString);
sl@0
    99
	TUint8 space[200];
sl@0
   100
	TPtr8 ptr(space,200);
sl@0
   101
	ptr.Copy(aString);
sl@0
   102
	iFile.Write(ptr);
sl@0
   103
	}
sl@0
   104
sl@0
   105
void Monobit(const TUint8* aData)
sl@0
   106
sl@0
   107
	{
sl@0
   108
	const TInt bitcount[256]=
sl@0
   109
		{ 0,1,1,2,1,2,2,3,		// 00-07
sl@0
   110
		  1,2,2,3,2,3,3,4,		// 08-0f
sl@0
   111
		  1,2,2,3,2,3,3,4,		// 10-17
sl@0
   112
		  2,3,3,4,3,4,4,5,		// 18-1f
sl@0
   113
		  1,2,2,3,2,3,3,4,		// 20-27
sl@0
   114
		  2,3,3,4,3,4,4,5,		// 28-2f
sl@0
   115
		  2,3,3,4,3,4,4,5,		// 30-37
sl@0
   116
		  3,4,4,5,4,5,5,6,		// 38-3f
sl@0
   117
sl@0
   118
		  1,2,2,3,2,3,3,4,		// 40-47
sl@0
   119
		  2,3,3,4,3,4,4,5,		// 48-4f
sl@0
   120
		  2,3,3,4,3,4,4,5,		// 50-57
sl@0
   121
		  3,4,4,5,4,5,5,6,		// 58-5f
sl@0
   122
		  2,3,3,4,3,4,4,5,		// 60-67
sl@0
   123
		  3,4,4,5,4,5,5,6,		// 68-6f
sl@0
   124
		  3,4,4,5,4,5,5,6,		// 70-77
sl@0
   125
		  4,5,5,6,5,6,6,7,		// 78-7f
sl@0
   126
sl@0
   127
		  1,2,2,3,2,3,3,4,		// 80-87
sl@0
   128
		  2,3,3,4,3,4,4,5,		// 88-8f
sl@0
   129
		  2,3,3,4,3,4,4,5,		// 90-97
sl@0
   130
		  3,4,4,5,4,5,5,6,		// 98-9f
sl@0
   131
		  2,3,3,4,3,4,4,5,		// a0-a7
sl@0
   132
		  3,4,4,5,4,5,5,6,		// a8-af
sl@0
   133
		  3,4,4,5,4,5,5,6,		// b0-b7
sl@0
   134
		  4,5,5,6,5,6,6,7,		// b8-bf
sl@0
   135
sl@0
   136
		  2,3,3,4,3,4,4,5,		// c0-c7
sl@0
   137
		  3,4,4,5,4,5,5,6,		// c8-cf
sl@0
   138
		  3,4,4,5,4,5,5,6,		// d0-d7
sl@0
   139
		  4,5,5,6,5,6,6,7,		// d8-df
sl@0
   140
		  3,4,4,5,4,5,5,6,		// e0-e7
sl@0
   141
		  4,5,5,6,5,6,6,7,		// e8-ef
sl@0
   142
		  4,5,5,6,5,6,6,7,		// f0-f7
sl@0
   143
		  5,6,6,7,6,7,7,8		// f8-ff
sl@0
   144
		};
sl@0
   145
	TInt total=0;
sl@0
   146
	TInt i;
sl@0
   147
	for (i=0;i<2500;i++)
sl@0
   148
		{
sl@0
   149
		total+=bitcount[aData[i]];
sl@0
   150
		}
sl@0
   151
	test.Printf(_L("    Total bitcount %d\r\n"),total);
sl@0
   152
	if ((total>9654)&&(total<10346))
sl@0
   153
		{
sl@0
   154
		test.Printf(_L("    Passed Monobit\r\n"));
sl@0
   155
		}
sl@0
   156
	else
sl@0
   157
		{
sl@0
   158
		test.Printf(_L("    ***FAILED!\r\n"));
sl@0
   159
		User::Panic(_L("t_random.exe"), KErrGeneral);
sl@0
   160
		}
sl@0
   161
	}
sl@0
   162
sl@0
   163
void Poker(const TUint8* aData)
sl@0
   164
	
sl@0
   165
	{
sl@0
   166
	TInt f[16]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
sl@0
   167
	TInt i;
sl@0
   168
	for (i=0;i<2500;i++)
sl@0
   169
		{
sl@0
   170
		f[(aData[i]&0x0f)]++;
sl@0
   171
		f[((aData[i]&0xf0)>>4)]++;
sl@0
   172
		}
sl@0
   173
	TReal x=0;
sl@0
   174
	for (i=0;i<16;i++)
sl@0
   175
		{
sl@0
   176
		x+=f[i]*f[i];
sl@0
   177
		}
sl@0
   178
	x*=16;
sl@0
   179
	x/=5000;
sl@0
   180
	x-=5000;
sl@0
   181
	if ((x>1.03)&&(x<57.4))
sl@0
   182
		{
sl@0
   183
		test.Printf(_L("    Passed poker test\r\n"));
sl@0
   184
		}
sl@0
   185
	else
sl@0
   186
		{
sl@0
   187
		test.Printf(_L("    ***FAILED poker test\r\n"));
sl@0
   188
		User::Panic(_L("t_random.exe"), KErrGeneral);
sl@0
   189
		}
sl@0
   190
	}
sl@0
   191
sl@0
   192
void Runs(const TUint8* aData)
sl@0
   193
sl@0
   194
	{
sl@0
   195
	TInt i;
sl@0
   196
	TInt lastbit=0;
sl@0
   197
	TInt count[7][2]={
sl@0
   198
		{ 0,0 },
sl@0
   199
		{ 0,0 },
sl@0
   200
		{ 0,0 },
sl@0
   201
		{ 0,0 },
sl@0
   202
		{ 0,0 },
sl@0
   203
		{ 0,0 },
sl@0
   204
		{ 0,0 }
sl@0
   205
		};
sl@0
   206
	TInt thisrun=0;
sl@0
   207
	TInt longrun=0;
sl@0
   208
	for (i=0;i<2500;i++)
sl@0
   209
		{
sl@0
   210
		TInt bit;
sl@0
   211
		for (bit=0;bit<8;bit++)
sl@0
   212
			{
sl@0
   213
			if (((aData[i]>>bit)&1)==lastbit)
sl@0
   214
				{
sl@0
   215
				thisrun++;
sl@0
   216
				}
sl@0
   217
			else
sl@0
   218
				{
sl@0
   219
				if (thisrun<5)
sl@0
   220
					{
sl@0
   221
					count[thisrun][lastbit]++;
sl@0
   222
					}
sl@0
   223
				else
sl@0
   224
					{
sl@0
   225
					count[5][lastbit]++;
sl@0
   226
					}
sl@0
   227
				lastbit^=1;
sl@0
   228
				if (thisrun>longrun)
sl@0
   229
					{
sl@0
   230
					longrun=thisrun;
sl@0
   231
					}
sl@0
   232
				thisrun=0;
sl@0
   233
				}
sl@0
   234
			}
sl@0
   235
		}
sl@0
   236
	TInt bound[6][2]=
sl@0
   237
		{
sl@0
   238
			{2267,2733},
sl@0
   239
			{1079,1421},
sl@0
   240
			{ 502, 748},
sl@0
   241
			{ 223, 402},
sl@0
   242
			{  90, 223},
sl@0
   243
			{  90, 223}
sl@0
   244
		};
sl@0
   245
	TBool failed=EFalse;
sl@0
   246
	for (i=0;i<6;i++)
sl@0
   247
		{
sl@0
   248
		if (!((count[i][0]>bound[i][0])&&(count[i][0]<bound[i][1])))
sl@0
   249
			{
sl@0
   250
			test.Printf(_L("    ***FAILED runs test\r\n"));
sl@0
   251
			failed=ETrue;
sl@0
   252
			}
sl@0
   253
		if (!((count[i][1]>bound[i][0])&&(count[i][1]<bound[i][1])))
sl@0
   254
			{
sl@0
   255
			test.Printf(_L("    ***FAILED runs test\r\n"));
sl@0
   256
			failed=ETrue;
sl@0
   257
			}
sl@0
   258
		}
sl@0
   259
	if (!failed)
sl@0
   260
		{
sl@0
   261
		test.Printf(_L("    Passed runs test\r\n"));
sl@0
   262
		}
sl@0
   263
	if ( (longrun>34) || (failed) )
sl@0
   264
		{
sl@0
   265
		test.Printf(_L("    ***FAILED longrun test\r\n"));
sl@0
   266
		User::Panic(_L("t_random.exe"), KErrGeneral);
sl@0
   267
		}
sl@0
   268
	}
sl@0
   269
sl@0
   270
void FIPSTest(const TUint8* aData)
sl@0
   271
//	Run some basic tests to check it's returned some numbers
sl@0
   272
//	These will panic if a failure is detected
sl@0
   273
	{
sl@0
   274
	Monobit(aData);
sl@0
   275
	Poker(aData);
sl@0
   276
	Runs(aData);
sl@0
   277
	}
sl@0
   278
sl@0
   279
void WriteFile(const TUint8* aData,const TDesC& aFileName)
sl@0
   280
sl@0
   281
	{
sl@0
   282
	RFs fs;
sl@0
   283
	fs.Connect();
sl@0
   284
	RFile file;
sl@0
   285
	TInt err;
sl@0
   286
	err=file.Open(fs,aFileName,EFileShareAny|EFileWrite);
sl@0
   287
	if (err)
sl@0
   288
		{
sl@0
   289
		if (file.Create(fs,aFileName,EFileShareAny|EFileWrite))
sl@0
   290
			{
sl@0
   291
			return;
sl@0
   292
			}
sl@0
   293
		}
sl@0
   294
	TPtrC8 ptr(aData,gNumberOfRandomNumbers);
sl@0
   295
	TInt size;
sl@0
   296
	file.Size(size);
sl@0
   297
	file.Write(size,ptr);
sl@0
   298
	file.Close();
sl@0
   299
	fs.Close();
sl@0
   300
	FIPSTest(aData);
sl@0
   301
	}
sl@0
   302
sl@0
   303
class RTestRandomSession : public RRandomSession
sl@0
   304
	{
sl@0
   305
	public:
sl@0
   306
	void SendMalformedInputL()
sl@0
   307
		{		
sl@0
   308
		test.Printf(_L("Test malformed input with negative buffer size\r\n"));		
sl@0
   309
		TBuf8<1024> buffer;
sl@0
   310
		TInt err = SendReceive(CRandomSession::KRandomRequest, TIpcArgs(&buffer, -1));
sl@0
   311
		if (err != KErrArgument)
sl@0
   312
			{
sl@0
   313
			test.Printf(_L("%d should have been returned on negative buffer size test, but %d was returned!\r\n"), KErrArgument, err);
sl@0
   314
			User::Leave(KErrGeneral);
sl@0
   315
			}
sl@0
   316
		}
sl@0
   317
	};
sl@0
   318
sl@0
   319
// Checks that RandomServer handles malformed length correctly - see INC113902
sl@0
   320
void TestMalformedInputL()
sl@0
   321
	{
sl@0
   322
	RTestRandomSession rs;
sl@0
   323
	TRAPD(err, rs.ConnectL());
sl@0
   324
	User::LeaveIfError(err); // The connect method leaves with zero even if it succeeds, so we have to trap the error
sl@0
   325
	CleanupClosePushL(rs);		
sl@0
   326
	rs.SendMalformedInputL();
sl@0
   327
	CleanupStack::PopAndDestroy(&rs);
sl@0
   328
	}
sl@0
   329
sl@0
   330
void DoTestsL()
sl@0
   331
sl@0
   332
	{
sl@0
   333
	TestMalformedInputL();
sl@0
   334
	
sl@0
   335
	test.Printf(_L("  Run random tests with normal salting\r\n"));
sl@0
   336
    
sl@0
   337
	TInt i;
sl@0
   338
	TBuf8<16> buf2;
sl@0
   339
	for (i=0;i<16;i++)
sl@0
   340
		{
sl@0
   341
		buf2.SetLength(i);
sl@0
   342
		TRandom::RandomL(buf2);
sl@0
   343
		}
sl@0
   344
	HBufC8* buf=HBufC8::NewMaxL(gNumberOfRandomNumbers);
sl@0
   345
	TPtr8 buffer=buf->Des();
sl@0
   346
	for (i=0;i<11;i++)
sl@0
   347
		{
sl@0
   348
		User::After(10000000);
sl@0
   349
		TPtr8 thePtr(buf->Des());
sl@0
   350
		thePtr.FillZ();
sl@0
   351
	//	Generate the random data	
sl@0
   352
		TRandom::RandomL(buffer);
sl@0
   353
		if (buf->Length()!=gNumberOfRandomNumbers)
sl@0
   354
			User::Leave(KErrGeneral);
sl@0
   355
sl@0
   356
sl@0
   357
		WriteFile(buffer.Ptr(),_L("User.rnd"));
sl@0
   358
		test.Printf(_L("."));
sl@0
   359
		}
sl@0
   360
	delete buf;
sl@0
   361
	}
sl@0
   362
sl@0
   363
void TestsL(void)
sl@0
   364
	{
sl@0
   365
	TDriveUnit sysDrive (RFs::GetSystemDrive());
sl@0
   366
	TDriveName driveName(sysDrive.Name());
sl@0
   367
	TBuf<64> logFile (driveName);
sl@0
   368
	logFile.Append(_L("\\t_random.log"));
sl@0
   369
	CTestConsole* con = CTestConsole::NewL(test.Console(), logFile);
sl@0
   370
	test.SetConsole(con);
sl@0
   371
	
sl@0
   372
	DoTestsL();
sl@0
   373
	
sl@0
   374
	//	If test reached here, no tests failed, otherwise it would have panicked
sl@0
   375
	//	and terminated prematurely. Print this out for tester's reference.	
sl@0
   376
	test.Printf(_L("\n0 tests failed out of 12\r\n"));
sl@0
   377
	}
sl@0
   378
sl@0
   379
GLDEF_C TInt E32Main(void)
sl@0
   380
sl@0
   381
	{
sl@0
   382
	CTrapCleanup* cleanup;
sl@0
   383
	cleanup=CTrapCleanup::New();
sl@0
   384
	
sl@0
   385
	__UHEAP_MARK;
sl@0
   386
	
sl@0
   387
	test.Start(_L(" SYMTestCaseID:SEC-CRYPTO-RANDOM-0001 Starting random number generator tests\r\n"));
sl@0
   388
	CConsoleBase* originalConsole = test.Console();
sl@0
   389
sl@0
   390
	TRAPD(ret,TestsL());
sl@0
   391
	if (ret)
sl@0
   392
		{
sl@0
   393
		test.Printf(_L("Unexpected leave\r\n"));
sl@0
   394
		// Print something to let the build system know we failed
sl@0
   395
		test.Printf(_L("\n1 tests failed out of 11\r\n"));
sl@0
   396
		}	
sl@0
   397
	test.End();
sl@0
   398
sl@0
   399
	if (test.Console() != originalConsole)
sl@0
   400
		{
sl@0
   401
		delete test.Console();
sl@0
   402
		test.SetConsole(originalConsole);
sl@0
   403
		}	
sl@0
   404
	test.Close();
sl@0
   405
	
sl@0
   406
	__UHEAP_MARKEND;
sl@0
   407
	
sl@0
   408
	delete cleanup;
sl@0
   409
	return(KErrNone);
sl@0
   410
	}