72
|
1 |
/*
|
|
2 |
* Copyright (c) 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 |
*
|
|
16 |
*/
|
|
17 |
|
|
18 |
|
|
19 |
#include <s32mem.h>
|
|
20 |
#include <s32file.h>
|
|
21 |
#include "texternpbeparams.h"
|
|
22 |
|
|
23 |
|
|
24 |
CTestAction* CExternPbeParams::NewL(
|
|
25 |
RFs& aFs, CConsoleBase& aConsole,
|
|
26 |
Output& aOut, const TTestActionSpec& aTestActionSpec)
|
|
27 |
/**
|
|
28 |
Factory function allocates new instance of CExternPbeParams and extracts
|
|
29 |
the element body from the supplied test action spec.
|
|
30 |
|
|
31 |
@param aFs Used to parse XML script file.
|
|
32 |
@param aConsole Required by CTestAction.
|
|
33 |
@param aOut Required by CTestAction.
|
|
34 |
@param aTestActionSpec Action specification contains type, name, and
|
|
35 |
XML contents.
|
|
36 |
@return New instance of CExternPbeParams, which is owned
|
|
37 |
by the caller.
|
|
38 |
*/
|
|
39 |
{
|
|
40 |
CExternPbeParams* self = new(ELeave) CExternPbeParams(aConsole, aOut, aFs);
|
|
41 |
CleanupStack::PushL(self);
|
|
42 |
self->ConstructL(aTestActionSpec);
|
|
43 |
CleanupStack::Pop(self);
|
|
44 |
return self;
|
|
45 |
}
|
|
46 |
|
|
47 |
CExternPbeParams::CExternPbeParams(CConsoleBase& aConsole, Output& aOut, RFs& aFs)
|
|
48 |
/**
|
|
49 |
This constructor exists to record the file server session and to initialize
|
|
50 |
the CTestAction superclass.
|
|
51 |
|
|
52 |
@param aConsole Required by CTestAction.
|
|
53 |
@param aOut Required by CTestAction.
|
|
54 |
@param aFs Used to read from and write to files in PerformAction,
|
|
55 |
which stores and restores the externalized params.
|
|
56 |
*/
|
|
57 |
: CTestAction(aConsole, aOut),
|
|
58 |
iFs(aFs)
|
|
59 |
{
|
|
60 |
// empty.
|
|
61 |
}
|
|
62 |
|
|
63 |
void CExternPbeParams::ConstructL(const TTestActionSpec& aTestActionSpec)
|
|
64 |
/**
|
|
65 |
Second phase initialization initializes the superclass and
|
|
66 |
makes a copy of the test element.
|
|
67 |
|
|
68 |
@param aTestActionSpec Action specification contains type, name, and
|
|
69 |
XML contents.
|
|
70 |
*/
|
|
71 |
{
|
|
72 |
CTestAction::ConstructL(aTestActionSpec);
|
|
73 |
iBody = aTestActionSpec.iActionBody.AllocL();
|
|
74 |
|
|
75 |
// iBody is deconstructed in DoPerformPrerequisite
|
|
76 |
}
|
|
77 |
|
|
78 |
CExternPbeParams::~CExternPbeParams()
|
|
79 |
/**
|
|
80 |
Free resources allocated in ConstructL. Specifically,
|
|
81 |
deletes the copy of the element body text.
|
|
82 |
*/
|
|
83 |
{
|
|
84 |
delete iBody;
|
|
85 |
}
|
|
86 |
|
|
87 |
// -------- implement CTestAction --------
|
|
88 |
|
|
89 |
void CExternPbeParams::DoPerformPrerequisite(TRequestStatus& aStatus)
|
|
90 |
/**
|
|
91 |
Override CTestAction by deconstructing element body allocated
|
|
92 |
in ConstructL.
|
|
93 |
|
|
94 |
If this function fails then DoPerformPostrequisite must still
|
|
95 |
be called.
|
|
96 |
|
|
97 |
@param aStatus This status is completed when the prerequisite
|
|
98 |
has finished. (This implementation is actually
|
|
99 |
synchronous so the request will already be completed
|
|
100 |
when it returns.)
|
|
101 |
*/
|
|
102 |
{
|
|
103 |
TRAPD(r, DoPerformPrerequisiteL());
|
|
104 |
|
|
105 |
iActionState = CTestAction::EAction;
|
|
106 |
TRequestStatus* ps = &aStatus;
|
|
107 |
User::RequestComplete(ps, r);
|
|
108 |
}
|
|
109 |
|
|
110 |
void CExternPbeParams::DoPerformPrerequisiteL()
|
|
111 |
/**
|
|
112 |
Helper function for DoPerformPrerequisite contains resource allocation
|
|
113 |
functions which can leave.
|
|
114 |
|
|
115 |
Extracts cipher, salt, iv, iter count, and kdf values.
|
|
116 |
*/
|
|
117 |
{
|
|
118 |
_LIT8(KOrigFileName, "orig-filename");
|
|
119 |
iOrigFileName = ReadStringLC(*iBody, KOrigFileName);
|
|
120 |
CleanupStack::Pop(iOrigFileName);
|
|
121 |
|
|
122 |
_LIT8(KExpCipherElemName, "expected-cipher");
|
|
123 |
iExpCipher = ReadDecStringL(*iBody, KExpCipherElemName);
|
|
124 |
_LIT8(KExpSaltElemName, "expected-salt");
|
|
125 |
iExpSalt = ReadHexStringL(*iBody, KExpSaltElemName);
|
|
126 |
_LIT8(KExpIvElemName, "expected-iv");
|
|
127 |
iExpIv = ReadHexStringL(*iBody, KExpIvElemName);
|
|
128 |
_LIT8(KExpIterCountElemName, "expected-iter-count");
|
|
129 |
iExpIterCount = ReadDecStringL(*iBody, KExpIterCountElemName);
|
|
130 |
_LIT8(KExpKdfElemName, "expected-kdf");
|
|
131 |
iExpKdf = ReadDecStringL(*iBody, KExpKdfElemName);
|
|
132 |
}
|
|
133 |
|
|
134 |
void CExternPbeParams::DoPerformPostrequisite(TRequestStatus& aStatus)
|
|
135 |
/**
|
|
136 |
Implements CTestAction by cleaning up data allocated in DoPerformPrerequisiteL.
|
|
137 |
|
|
138 |
@param aStatus This status is completed to indicate the
|
|
139 |
postrequisite has finished. (This function
|
|
140 |
is synchronous so the status is completed before
|
|
141 |
this function returns.)
|
|
142 |
*/
|
|
143 |
{
|
|
144 |
delete iExpIv;
|
|
145 |
iExpIv = 0;
|
|
146 |
delete iExpSalt;
|
|
147 |
iExpSalt = 0;
|
|
148 |
delete iOrigFileName;
|
|
149 |
iOrigFileName = NULL;
|
|
150 |
|
|
151 |
iFinished = ETrue;
|
|
152 |
TRequestStatus* ps = &aStatus;
|
|
153 |
User::RequestComplete(ps, KErrNone);
|
|
154 |
}
|
|
155 |
|
|
156 |
void CExternPbeParams::PerformAction(TRequestStatus& aStatus)
|
|
157 |
/**
|
|
158 |
Implements CTestAction by running the actual tests. This
|
|
159 |
consists of:
|
|
160 |
|
|
161 |
Reading an externalized CPBEncryptParms object and testing the
|
|
162 |
cipher, salt, iv, iteration count, and KDF are as expected.
|
|
163 |
|
|
164 |
Externalizing the object to memory.
|
|
165 |
|
|
166 |
Testing the two externalizations are binary identical.
|
|
167 |
|
|
168 |
Creating an equivalent object from scratch and externalizing it.
|
|
169 |
|
|
170 |
Testing the externalizations are binary identical.
|
|
171 |
|
|
172 |
As well as testing the objects can be stored reliably, this
|
|
173 |
test also ensures that old (pre-PKCS#12) files can still be
|
|
174 |
read and, and that objects are stored in the old format if they
|
|
175 |
do not use any PKCS#12-specific features. (I.e., they use the
|
|
176 |
default PKCS#5 KDF.)
|
|
177 |
|
|
178 |
@param aStatus This request status is completed when
|
|
179 |
the action has finished, successfully
|
|
180 |
or otherwise. This implementation is
|
|
181 |
synchronous, and so the status is actually
|
|
182 |
completed before this function returns.
|
|
183 |
*/
|
|
184 |
{
|
|
185 |
TFileName fn;
|
|
186 |
fn.Copy(*iOrigFileName); // convert from narrow
|
|
187 |
|
|
188 |
// ensure reference file matches re-externalized form
|
|
189 |
|
|
190 |
TRAPD(r,
|
|
191 |
TestDecodeMatchesScriptL(fn);
|
|
192 |
TestReExternMatchesL(fn);
|
|
193 |
TestScratchExternL(fn) );
|
|
194 |
|
|
195 |
iResult = (r == KErrNone);
|
|
196 |
iActionState = CTestAction::EPostrequisite;
|
|
197 |
TRequestStatus* status = &aStatus;
|
|
198 |
User::RequestComplete(status, KErrNone);
|
|
199 |
}
|
|
200 |
|
|
201 |
CPBEncryptParms* CExternPbeParams::InternalizeEncryptionParamsLC(const TDesC& aFileName)
|
|
202 |
/**
|
|
203 |
Construct a CPBEncryptParms object from the externalized
|
|
204 |
form in the named file.
|
|
205 |
|
|
206 |
@param aFileName File which contains externalized form.
|
|
207 |
@return Internalized encryption parameters object
|
|
208 |
which is placed on the cleanup stack.
|
|
209 |
*/
|
|
210 |
{
|
|
211 |
RFileReadStream frs;
|
|
212 |
TInt r = frs.Open(iFs, aFileName, EFileStream | EFileRead);
|
|
213 |
User::LeaveIfError(r);
|
|
214 |
CleanupClosePushL(frs);
|
|
215 |
CPBEncryptParms* pbep = CPBEncryptParms::NewL(frs);
|
|
216 |
CleanupStack::PopAndDestroy(&frs);
|
|
217 |
CleanupStack::PushL(pbep);
|
|
218 |
return pbep;
|
|
219 |
}
|
|
220 |
|
|
221 |
void CExternPbeParams::TestDecodeMatchesScriptL(const TDesC& aFileName)
|
|
222 |
/**
|
|
223 |
Test whether the encryption parameters which were externalized
|
|
224 |
to the supplied file match those specified in the script file.
|
|
225 |
|
|
226 |
@param aFileName Name of file which contains externalized form.
|
|
227 |
@leave KErrGeneral The internalized form doesn't match the parameters
|
|
228 |
in the script.
|
|
229 |
*/
|
|
230 |
{
|
|
231 |
CPBEncryptParms* pbep = InternalizeEncryptionParamsLC(aFileName);
|
|
232 |
|
|
233 |
TBool match =
|
|
234 |
pbep->Cipher() == iExpCipher
|
|
235 |
&& pbep->Salt() == *iExpSalt
|
|
236 |
&& pbep->Iterations() == iExpIterCount;
|
|
237 |
|
|
238 |
match = match && pbep->Kdf() == iExpKdf;
|
|
239 |
|
|
240 |
if (! match)
|
|
241 |
User::Leave(KErrGeneral);
|
|
242 |
|
|
243 |
CleanupStack::PopAndDestroy(pbep);
|
|
244 |
}
|
|
245 |
|
|
246 |
void CExternPbeParams::CompareAgainstTestFileL(
|
|
247 |
const TDesC& aFileName, const CPBEncryptParms& aParams)
|
|
248 |
/**
|
|
249 |
Externalize the supplied parameters object and ensure it matches the
|
|
250 |
test file.
|
|
251 |
|
|
252 |
@param aFileName File which contains externalized parameters.
|
|
253 |
@param aParams Test object to externalize.
|
|
254 |
@leave KErrGeneral The externalized forms do not match.
|
|
255 |
*/
|
|
256 |
{
|
|
257 |
// open a file stream on the externalized form
|
|
258 |
RFileReadStream frs;
|
|
259 |
TInt r = frs.Open(iFs, aFileName, EFileStream | EFileRead);
|
|
260 |
User::LeaveIfError(r);
|
|
261 |
CleanupClosePushL(frs);
|
|
262 |
|
|
263 |
// externalize the object to memory
|
|
264 |
const TInt KMaxBufferLen = 128;
|
|
265 |
HBufC8* reExtBuf = HBufC8::NewLC(KMaxBufferLen);
|
|
266 |
TPtr8 reDes = reExtBuf->Des();
|
|
267 |
RDesWriteStream dws(reDes);
|
|
268 |
CleanupClosePushL(dws);
|
|
269 |
aParams.ExternalizeL(dws);
|
|
270 |
dws.CommitL();
|
|
271 |
|
|
272 |
// ensure the externalized forms are equal
|
|
273 |
RDesReadStream drs(reDes);
|
|
274 |
TInt fLen = frs.Source()->SizeL();
|
|
275 |
TInt mLen = drs.Source()->SizeL();
|
|
276 |
if (fLen != mLen)
|
|
277 |
User::Leave(KErrGeneral);
|
|
278 |
|
|
279 |
TBuf8<1> fByte;
|
|
280 |
TBuf8<1> mByte;
|
|
281 |
for (TInt i = 0; i < fLen; ++i)
|
|
282 |
{
|
|
283 |
frs.ReadL(fByte, 1);
|
|
284 |
drs.ReadL(mByte, 1);
|
|
285 |
if (fByte != mByte)
|
|
286 |
User::Leave(KErrGeneral);
|
|
287 |
}
|
|
288 |
|
|
289 |
CleanupStack::PopAndDestroy(3, &frs); // frs, reExtBuf, dws
|
|
290 |
}
|
|
291 |
|
|
292 |
void CExternPbeParams::TestReExternMatchesL(const TDesC& aFileName)
|
|
293 |
/**
|
|
294 |
Read the CPBEncryptParms object which is externalized in
|
|
295 |
the named file, re-externalize it, and check the two
|
|
296 |
representations are binary equivalent.
|
|
297 |
|
|
298 |
@param aFileName Name of file which contains externalized form.
|
|
299 |
@leave KErrGeneral The externalized forms are different.
|
|
300 |
*/
|
|
301 |
{
|
|
302 |
CPBEncryptParms* pbep = InternalizeEncryptionParamsLC(aFileName);
|
|
303 |
|
|
304 |
CompareAgainstTestFileL(aFileName, *pbep);
|
|
305 |
|
|
306 |
CleanupStack::PopAndDestroy(pbep);
|
|
307 |
}
|
|
308 |
|
|
309 |
void CExternPbeParams::TestScratchExternL(const TDesC& aFileName)
|
|
310 |
/**
|
|
311 |
Construct a CPBEncryptParams object from the parameter values
|
|
312 |
in the script file. Test it matches the test file.
|
|
313 |
|
|
314 |
@param aFileName Test file which contains externalized parameters.
|
|
315 |
*/
|
|
316 |
{
|
|
317 |
CPBEncryptParms* pbep = CPBEncryptParms::NewLC(
|
|
318 |
static_cast<TPBECipher>(iExpCipher),
|
|
319 |
*iExpSalt,
|
|
320 |
*iExpIv,
|
|
321 |
iExpIterCount);
|
|
322 |
|
|
323 |
pbep->SetKdf(static_cast<CPBEncryptParms::TKdf>(iExpKdf));
|
|
324 |
|
|
325 |
CompareAgainstTestFileL(aFileName, *pbep);
|
|
326 |
|
|
327 |
CleanupStack::PopAndDestroy(pbep);
|
|
328 |
}
|
|
329 |
|
|
330 |
void CExternPbeParams::DoReportAction(void)
|
|
331 |
/**
|
|
332 |
Implements CTestAction but is empty.
|
|
333 |
*/
|
|
334 |
{
|
|
335 |
// empty.
|
|
336 |
}
|
|
337 |
|
|
338 |
void CExternPbeParams::DoCheckResult(TInt /*aError*/)
|
|
339 |
/**
|
|
340 |
Implements CTestAction but is empty.
|
|
341 |
*/
|
|
342 |
{
|
|
343 |
// empty.
|
|
344 |
}
|
|
345 |
|
|
346 |
|
|
347 |
// -------- support functions --------
|
|
348 |
|
|
349 |
|
|
350 |
HBufC8* CExternPbeParams::ReadHexStringL(const TDesC8& aBody, const TDesC8& aTag)
|
|
351 |
/**
|
|
352 |
Convert a string in the test script to an 8-bit buffer. The string
|
|
353 |
is a sequence of hex digits, e.g. "abcdef01", which is converted to a
|
|
354 |
descriptor containing the matching bytes {0xab, 0xcd, 0xef, 0x01}.
|
|
355 |
|
|
356 |
@param aBody Body of parent element.
|
|
357 |
@param aTag Bare tag name. This function extracts the text
|
|
358 |
between "<aTag>" and "</aTag>".
|
|
359 |
@return Newly-allocated buffer containing matching bytes.
|
|
360 |
This is owned by the caller.
|
|
361 |
*/
|
|
362 |
{
|
|
363 |
HBufC8* scriptString = ReadStringLC(aBody, aTag);
|
|
364 |
|
|
365 |
TInt textLen = scriptString->Length();
|
|
366 |
if ((textLen % 2) != 0)
|
|
367 |
User::Leave(KErrCorrupt);
|
|
368 |
TInt byteCount = textLen / 2;
|
|
369 |
HBufC8* procString = HBufC8::NewMaxLC(byteCount);
|
|
370 |
TPtr8 procDes = procString->Des();
|
|
371 |
for (TInt i = 0; i < byteCount; ++i)
|
|
372 |
{
|
|
373 |
TUint8 byteVal;
|
|
374 |
TInt r = TLex8(scriptString->Mid(i * 2, 2)).Val(byteVal, EHex);
|
|
375 |
User::LeaveIfError(r);
|
|
376 |
procDes[i] = byteVal;
|
|
377 |
}
|
|
378 |
|
|
379 |
CleanupStack::Pop(procString);
|
|
380 |
CleanupStack::PopAndDestroy(scriptString);
|
|
381 |
return procString;
|
|
382 |
}
|
|
383 |
|
|
384 |
TInt CExternPbeParams::ReadDecStringL(const TDesC8& aBody, const TDesC8& aTag)
|
|
385 |
/**
|
|
386 |
Finds a decimal text string in the script and returns the
|
|
387 |
integer value which it represents.
|
|
388 |
|
|
389 |
@param aBody Body of parent element.
|
|
390 |
@param aTag Bare tag name. This function extracts the text
|
|
391 |
between "<aTag>" and "</aTag>".
|
|
392 |
@return Integer value encoded in the script file.
|
|
393 |
*/
|
|
394 |
{
|
|
395 |
HBufC8* scriptString = ReadStringLC(aBody, aTag);
|
|
396 |
|
|
397 |
TInt value;
|
|
398 |
User::LeaveIfError(TLex8(*scriptString).Val(value));
|
|
399 |
CleanupStack::PopAndDestroy(scriptString);
|
|
400 |
return value;
|
|
401 |
}
|
|
402 |
|
|
403 |
HBufC8* CExternPbeParams::ReadStringLC(const TDesC8& aBody, const TDesC8& aTag)
|
|
404 |
/**
|
|
405 |
Extracts a string from the supplied script file.
|
|
406 |
|
|
407 |
@param aBody Body of parent element.
|
|
408 |
@param aTag Bare tag name. This function extracts the text
|
|
409 |
between "<aTag>" and "</aTag>".
|
|
410 |
@return A copy of the string allocated on the heap. The
|
|
411 |
string is placed on the cleanup stack.
|
|
412 |
*/
|
|
413 |
{
|
|
414 |
TBuf8<32> startTag;
|
|
415 |
startTag.Format(_L8("<%S>"), &aTag);
|
|
416 |
TBuf8<32> endTag;
|
|
417 |
endTag.Format(_L8("</%S>"), &aTag);
|
|
418 |
|
|
419 |
TInt pos = 0;
|
|
420 |
TInt r;
|
|
421 |
const TPtrC8 contents = Input::ParseElement(
|
|
422 |
aBody, startTag, endTag, pos, r);
|
|
423 |
User::LeaveIfError(r);
|
|
424 |
|
|
425 |
return contents.AllocLC();
|
|
426 |
}
|
|
427 |
|
|
428 |
/**
|
|
429 |
This code was originally in PerformAction to create the initial
|
|
430 |
data files.
|
|
431 |
|
|
432 |
// GENERATE PKCS5 TEST PARAMS FILE
|
|
433 |
RFileWriteStream fws;
|
|
434 |
r = fws.Replace(iFs, _L("c:\\tpbe\\pkcs5-orig.dat"), EFileStream | EFileWrite);
|
|
435 |
User::LeaveIfError(r);
|
|
436 |
CleanupClosePushL(fws);
|
|
437 |
|
|
438 |
_LIT8(KSalt, "SALT4567");
|
|
439 |
_LIT8(KIv, "IV23456789abcdef");
|
|
440 |
const TInt KIterCount = 1234;
|
|
441 |
CPBEncryptParms* pbep = CPBEncryptParms::NewLC(
|
|
442 |
ECipherAES_CBC_256, KSalt, KIv, KIterCount);
|
|
443 |
pbep->ExternalizeL(fws);
|
|
444 |
fws.CommitL();
|
|
445 |
CleanupStack::PopAndDestroy(2, &fws);
|
|
446 |
|
|
447 |
#ifdef SYMBIAN_PKCS12
|
|
448 |
// GENERATE PKCS12 TEST PARAMS FILE
|
|
449 |
RFileWriteStream fws;
|
|
450 |
r = fws.Replace(iFs, _L("c:\\tpbe\\pkcs12-first.dat"), EFileStream | EFileWrite);
|
|
451 |
User::LeaveIfError(r);
|
|
452 |
CleanupClosePushL(fws);
|
|
453 |
|
|
454 |
_LIT8(KSalt, "SALT4567");
|
|
455 |
_LIT8(KIv, "IV23456789abcdef");
|
|
456 |
const TInt KIterCount = 1234;
|
|
457 |
CPBEncryptParms* pbep = CPBEncryptParms::NewLC(
|
|
458 |
ECipherAES_CBC_256, KSalt, KIv, KIterCount);
|
|
459 |
pbep->SetKdf(CPBEncryptParms::EKdfPkcs12);
|
|
460 |
pbep->ExternalizeL(fws);
|
|
461 |
fws.CommitL();
|
|
462 |
CleanupStack::PopAndDestroy(2, &fws);
|
|
463 |
#endif // #ifdef SYMBIAN_PKCS12
|
|
464 |
|
|
465 |
*/
|