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