|
1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of the License "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // |
|
12 // Description: |
|
13 // e32test\random\t_securerng.cpp |
|
14 // |
|
15 // |
|
16 |
|
17 //system include |
|
18 #include <e32test.h> |
|
19 #include <e32math.h> |
|
20 #include <e32cmn.h> |
|
21 #include "../mmu/mmudetect.h" |
|
22 |
|
23 //--------------------------------------------------------------------------------------------------------------------- |
|
24 //! @SYMTestCaseID KBASE-securerng-2702 |
|
25 //! @SYMTestType UT |
|
26 //! @SYMTestCaseDesc Verifies correct operation of the Secure RNG |
|
27 //! @SYMPREQ PREQ211 |
|
28 //! @SYMTestPriority High |
|
29 //! @SYMTestActions |
|
30 //! 1. TestRandomNumberGeneration: tests that random data is generated correctly. |
|
31 //! |
|
32 //! 2. SecureRNGTestWithMultiThread: tests that random data can be provided to multiple threads simultaneously |
|
33 //! |
|
34 //! 3. TestSecureRNGForPanicScenarios: tests that the correct panics are issued for common error conditions |
|
35 //! |
|
36 //! |
|
37 //! @SYMTestExpectedResults |
|
38 //! 1. Properties checked: |
|
39 //! 1) checks that requests for random data with a buffer length of zero do not cause an error. |
|
40 //! 2) checks that requests for a large amount of random data do not cause an error. |
|
41 //! 3) checks that some random data has been returned (comparison to zero filled buffer). |
|
42 //! 4) checks that the new Math::RandomL() API either returns some random data or correctly indicates the RNG |
|
43 //! as not secure (KErrNotReady). |
|
44 //! |
|
45 //! 2. Properties checked: |
|
46 //! 5) checks that making requests for random data from multiple threads simultaneously does not cause an error. |
|
47 //! |
|
48 //! 3. Properties checked: |
|
49 //! 6) checks passing a user non-writable memory address to the random function through a valid pointer results |
|
50 //! results in the correct panic. |
|
51 //! 7) checks passing a null pointer to the random function results in the correct panic. |
|
52 //! 8) checks passing a non-modifiable descriptor to the random function results in the correct panic. |
|
53 //--------------------------------------------------------------------------------------------------------------------- |
|
54 |
|
55 |
|
56 // RTest for testing Secure RNG unit |
|
57 RTest test(_L("Secure RNG Unit Test")); |
|
58 |
|
59 // Threads required for multi thread testing |
|
60 RThread SecureRNGTestThread1; |
|
61 RThread SecureRNGTestThread2; |
|
62 RThread SecureRNGTestThread3; |
|
63 |
|
64 // Threads name to identify |
|
65 _LIT(KSecureRNGTestThread1, "SecureRNGTestThread1"); |
|
66 _LIT(KSecureRNGTestThread2, "SecureRNGTestThread2"); |
|
67 _LIT(KSecureRNGTestThread3, "SecureRNGTestThread3"); |
|
68 |
|
69 //length of the buffer data |
|
70 const TInt KDataLength = 10; |
|
71 |
|
72 /* |
|
73 *Test Secure RNG with invalid and non-writable and non modifiable descriptor type |
|
74 */ |
|
75 TInt PanicFuncForBadDesc(TAny* aDes) |
|
76 { |
|
77 Math::Random(*(TDes8*)aDes); |
|
78 return KErrNone; |
|
79 } |
|
80 |
|
81 void CreatePanicThreads(TAny* aThreadData, TInt aExpectedStatusOfThread) |
|
82 { |
|
83 RThread panicThread; |
|
84 _LIT(KPanicThreadName, "SecureRNGTestPanicThread"); |
|
85 |
|
86 test(panicThread.Create(KPanicThreadName(),PanicFuncForBadDesc,KDefaultStackSize,0x200,0x900,aThreadData) == KErrNone); |
|
87 TRequestStatus status; |
|
88 panicThread.Logon(status); |
|
89 panicThread.Resume(); |
|
90 User::WaitForRequest(status); |
|
91 test.Printf(_L("Exit Reason %d\r\n"), status.Int()); |
|
92 test.Printf(_L("Exit Type %d\r\n"),(TInt)panicThread.ExitType()); |
|
93 //Test for expected result from thread |
|
94 test(status.Int()== aExpectedStatusOfThread); //(status of thread = thread Exit Reason) |
|
95 test(panicThread.ExitCategory() == _L("KERN-EXEC")); |
|
96 test(panicThread.ExitType()==EExitPanic); |
|
97 |
|
98 CLOSE_AND_WAIT(panicThread); |
|
99 } |
|
100 |
|
101 /* |
|
102 * Panic test cases for testing Secure RNG |
|
103 */ |
|
104 void TestSecureRNGForPanicScenarios() |
|
105 { |
|
106 test.Printf(_L("Passing user non-writable memory address to the random function through a valid pointer \n")); |
|
107 TPtr8 tptr(KernData(), KDataLength, KDataLength); |
|
108 CreatePanicThreads(&tptr, 3); |
|
109 |
|
110 test.Printf(_L("Passing null pointer to random function \n")); |
|
111 tptr.Set(NULL, KDataLength, KDataLength); |
|
112 CreatePanicThreads(&tptr, 3); |
|
113 |
|
114 test.Printf(_L("Passing non-modifiable descriptor to the random function \n")); |
|
115 HBufC8* randbuf =HBufC8::New(25); |
|
116 TPtr8 ptr = randbuf->Des(); |
|
117 ptr.SetMax(); |
|
118 CreatePanicThreads(randbuf, 34); |
|
119 delete randbuf; |
|
120 } |
|
121 |
|
122 TInt GenerateRandomNumber(TAny*) |
|
123 { |
|
124 HBufC8* randbuf = HBufC8::New(3000); |
|
125 TPtr8 ptr = randbuf->Des(); |
|
126 ptr.SetMax(); |
|
127 for(;;) |
|
128 { |
|
129 Math::Random(ptr); |
|
130 } |
|
131 } |
|
132 |
|
133 /* |
|
134 * Test Secure RNG with multi threads requesting for random numbers |
|
135 */ |
|
136 void SecureRNGTestWithMultiThread() |
|
137 { |
|
138 test(SecureRNGTestThread1.Create(KSecureRNGTestThread1(),GenerateRandomNumber,KDefaultStackSize,0x200,0x900,NULL)== KErrNone); |
|
139 SecureRNGTestThread1.SetPriority(EPriorityLess); |
|
140 test(SecureRNGTestThread2.Create(KSecureRNGTestThread2(),GenerateRandomNumber,KDefaultStackSize,0x200,0x900,NULL)== KErrNone); |
|
141 SecureRNGTestThread2.SetPriority(EPriorityLess); |
|
142 test(SecureRNGTestThread3.Create(KSecureRNGTestThread3(),GenerateRandomNumber,KDefaultStackSize,0x200,0x900,NULL)== KErrNone); |
|
143 SecureRNGTestThread3.SetPriority(EPriorityLess); |
|
144 |
|
145 SecureRNGTestThread1.Resume(); |
|
146 SecureRNGTestThread2.Resume(); |
|
147 SecureRNGTestThread3.Resume(); |
|
148 |
|
149 User::After(30 * 1000 * 1000); //30 seconds |
|
150 // After waiting for few seconds, kill the threads now. |
|
151 SecureRNGTestThread1.Kill(KErrNone); |
|
152 test(SecureRNGTestThread1.ExitType()==EExitKill); |
|
153 SecureRNGTestThread2.Kill(KErrNone); |
|
154 test(SecureRNGTestThread2.ExitType()==EExitKill); |
|
155 SecureRNGTestThread3.Kill(KErrNone); |
|
156 test(SecureRNGTestThread3.ExitType()==EExitKill); |
|
157 |
|
158 CLOSE_AND_WAIT(SecureRNGTestThread1); |
|
159 CLOSE_AND_WAIT(SecureRNGTestThread2); |
|
160 CLOSE_AND_WAIT(SecureRNGTestThread3); |
|
161 } |
|
162 |
|
163 const TInt KChunkLength = 2048; |
|
164 void CheckForRandomNumbers(const TUint8* aRandomNumbers, TInt aLength) |
|
165 { |
|
166 TBuf8<KChunkLength> buf; |
|
167 buf.FillZ(); |
|
168 TInt bytesToCompare = aLength; |
|
169 TInt index = 0; |
|
170 while(bytesToCompare > 0) |
|
171 { |
|
172 // check there is at least some random numbers in every chunk |
|
173 TInt newLength = bytesToCompare > KChunkLength ? KChunkLength : bytesToCompare; |
|
174 test(memcompare(aRandomNumbers+ (index* KChunkLength), newLength, buf.Ptr(), newLength) != 0); |
|
175 index++; |
|
176 bytesToCompare = bytesToCompare - KChunkLength; |
|
177 } |
|
178 } |
|
179 /* |
|
180 * Functionality test for the Random APIs |
|
181 */ |
|
182 //required for testing for large number of random numbers request |
|
183 const TInt KRandomNumsRequired = 70000; |
|
184 void TestRandomNumberGeneration() |
|
185 { |
|
186 test.Printf(_L(" Request for zero random numbers \n")); |
|
187 TBuf8<KDataLength> randomBuffer; |
|
188 randomBuffer.SetLength(0); |
|
189 TRAPD(error, Math::RandomL(randomBuffer)); |
|
190 test(error == KErrNone); |
|
191 |
|
192 test.Printf(_L(" Request for huge random numbers of 70000 bytes in length \n")); |
|
193 HBufC8* randbuf =HBufC8::New(KRandomNumsRequired); |
|
194 TPtr8 ptr = randbuf->Des(); |
|
195 ptr.SetMax(); |
|
196 TRAP(error, Math::RandomL(ptr)); |
|
197 test(error == KErrNotReady || error == KErrNone); |
|
198 //check we have some random numbers atleast in every chunk of large randomnumbers received |
|
199 CheckForRandomNumbers(ptr.Ptr(), KRandomNumsRequired); |
|
200 delete randbuf; |
|
201 |
|
202 test.Printf(_L(" Request for 32 bit random number using the new leaving function: Math::RandomL() api \n")); |
|
203 for (TInt i=0; i<50; ++i) |
|
204 { |
|
205 // Try to prove it's working by looking for a nonzero value - 50 32-bit zero values |
|
206 // in a row from a random source is extremely unlikely. However, if it's not ready |
|
207 // we will get 0 every time as the return value is not set when it leaves, so we |
|
208 // give up. |
|
209 TUint32 randomNumber = 0; |
|
210 TRAP(error ,randomNumber = Math::RandomL()); |
|
211 test.Printf(_L("The generated four byte random number is %d \n" ), randomNumber); |
|
212 test(error == KErrNotReady || error == KErrNone); |
|
213 if (error == KErrNotReady || randomNumber != 0) |
|
214 break; |
|
215 } |
|
216 } |
|
217 |
|
218 /* |
|
219 * Test Secure RNG for functionality test, multi-thread tests and panic test cases |
|
220 */ |
|
221 void SecureRNGTest() |
|
222 { |
|
223 test.Printf(_L("\n Functionality test for RNG \n")); |
|
224 TestRandomNumberGeneration(); |
|
225 |
|
226 // Test Secure RNG with multi threads |
|
227 test.Printf(_L("Testing Secure RNG with Multithreads requesting for random numbers \n")); |
|
228 SecureRNGTestWithMultiThread(); |
|
229 |
|
230 //Panic test cases - check with non-writable descriptor type and null pointer |
|
231 test.Printf(_L("\n Panic test cases for Secure RNG \n")); |
|
232 TestSecureRNGForPanicScenarios(); |
|
233 } |
|
234 |
|
235 /* |
|
236 Gobal Entry Function |
|
237 */ |
|
238 GLDEF_C TInt E32Main() |
|
239 { |
|
240 test.Title(); |
|
241 test.Start(_L("\n Starting Secure RNG Unit tests \n")); |
|
242 |
|
243 CTrapCleanup* cleanup=CTrapCleanup::New(); |
|
244 test(cleanup != NULL); |
|
245 |
|
246 __KHEAP_MARK; |
|
247 __UHEAP_MARK; |
|
248 SecureRNGTest(); |
|
249 __UHEAP_MARKEND; |
|
250 __KHEAP_MARKEND; |
|
251 |
|
252 test.End(); |
|
253 delete cleanup; |
|
254 return KErrNone; |
|
255 } |