1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/crypto/weakcryptospi/test/tpbe/texternpbeparams.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,465 @@
1.4 +/*
1.5 +* Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include <s32mem.h>
1.23 +#include <s32file.h>
1.24 +#include "texternpbeparams.h"
1.25 +
1.26 +
1.27 +CTestAction* CExternPbeParams::NewL(
1.28 + RFs& aFs, CConsoleBase& aConsole,
1.29 + Output& aOut, const TTestActionSpec& aTestActionSpec)
1.30 +/**
1.31 + Factory function allocates new instance of CExternPbeParams and extracts
1.32 + the element body from the supplied test action spec.
1.33 +
1.34 + @param aFs Used to parse XML script file.
1.35 + @param aConsole Required by CTestAction.
1.36 + @param aOut Required by CTestAction.
1.37 + @param aTestActionSpec Action specification contains type, name, and
1.38 + XML contents.
1.39 + @return New instance of CExternPbeParams, which is owned
1.40 + by the caller.
1.41 + */
1.42 + {
1.43 + CExternPbeParams* self = new(ELeave) CExternPbeParams(aConsole, aOut, aFs);
1.44 + CleanupStack::PushL(self);
1.45 + self->ConstructL(aTestActionSpec);
1.46 + CleanupStack::Pop(self);
1.47 + return self;
1.48 + }
1.49 +
1.50 +CExternPbeParams::CExternPbeParams(CConsoleBase& aConsole, Output& aOut, RFs& aFs)
1.51 +/**
1.52 + This constructor exists to record the file server session and to initialize
1.53 + the CTestAction superclass.
1.54 +
1.55 + @param aConsole Required by CTestAction.
1.56 + @param aOut Required by CTestAction.
1.57 + @param aFs Used to read from and write to files in PerformAction,
1.58 + which stores and restores the externalized params.
1.59 + */
1.60 +: CTestAction(aConsole, aOut),
1.61 + iFs(aFs)
1.62 + {
1.63 + // empty.
1.64 + }
1.65 +
1.66 +void CExternPbeParams::ConstructL(const TTestActionSpec& aTestActionSpec)
1.67 +/**
1.68 + Second phase initialization initializes the superclass and
1.69 + makes a copy of the test element.
1.70 +
1.71 + @param aTestActionSpec Action specification contains type, name, and
1.72 + XML contents.
1.73 + */
1.74 + {
1.75 + CTestAction::ConstructL(aTestActionSpec);
1.76 + iBody = aTestActionSpec.iActionBody.AllocL();
1.77 +
1.78 + // iBody is deconstructed in DoPerformPrerequisite
1.79 + }
1.80 +
1.81 +CExternPbeParams::~CExternPbeParams()
1.82 +/**
1.83 + Free resources allocated in ConstructL. Specifically,
1.84 + deletes the copy of the element body text.
1.85 + */
1.86 + {
1.87 + delete iBody;
1.88 + }
1.89 +
1.90 +// -------- implement CTestAction --------
1.91 +
1.92 +void CExternPbeParams::DoPerformPrerequisite(TRequestStatus& aStatus)
1.93 +/**
1.94 + Override CTestAction by deconstructing element body allocated
1.95 + in ConstructL.
1.96 +
1.97 + If this function fails then DoPerformPostrequisite must still
1.98 + be called.
1.99 +
1.100 + @param aStatus This status is completed when the prerequisite
1.101 + has finished. (This implementation is actually
1.102 + synchronous so the request will already be completed
1.103 + when it returns.)
1.104 + */
1.105 + {
1.106 + TRAPD(r, DoPerformPrerequisiteL());
1.107 +
1.108 + iActionState = CTestAction::EAction;
1.109 + TRequestStatus* ps = &aStatus;
1.110 + User::RequestComplete(ps, r);
1.111 + }
1.112 +
1.113 +void CExternPbeParams::DoPerformPrerequisiteL()
1.114 +/**
1.115 + Helper function for DoPerformPrerequisite contains resource allocation
1.116 + functions which can leave.
1.117 +
1.118 + Extracts cipher, salt, iv, iter count, and kdf values.
1.119 + */
1.120 + {
1.121 + _LIT8(KOrigFileName, "orig-filename");
1.122 + iOrigFileName = ReadStringLC(*iBody, KOrigFileName);
1.123 + CleanupStack::Pop(iOrigFileName);
1.124 +
1.125 + _LIT8(KExpCipherElemName, "expected-cipher");
1.126 + iExpCipher = ReadDecStringL(*iBody, KExpCipherElemName);
1.127 + _LIT8(KExpSaltElemName, "expected-salt");
1.128 + iExpSalt = ReadHexStringL(*iBody, KExpSaltElemName);
1.129 + _LIT8(KExpIvElemName, "expected-iv");
1.130 + iExpIv = ReadHexStringL(*iBody, KExpIvElemName);
1.131 + _LIT8(KExpIterCountElemName, "expected-iter-count");
1.132 + iExpIterCount = ReadDecStringL(*iBody, KExpIterCountElemName);
1.133 + _LIT8(KExpKdfElemName, "expected-kdf");
1.134 + iExpKdf = ReadDecStringL(*iBody, KExpKdfElemName);
1.135 + }
1.136 +
1.137 +void CExternPbeParams::DoPerformPostrequisite(TRequestStatus& aStatus)
1.138 +/**
1.139 + Implements CTestAction by cleaning up data allocated in DoPerformPrerequisiteL.
1.140 +
1.141 + @param aStatus This status is completed to indicate the
1.142 + postrequisite has finished. (This function
1.143 + is synchronous so the status is completed before
1.144 + this function returns.)
1.145 + */
1.146 + {
1.147 + delete iExpIv;
1.148 + iExpIv = 0;
1.149 + delete iExpSalt;
1.150 + iExpSalt = 0;
1.151 + delete iOrigFileName;
1.152 + iOrigFileName = NULL;
1.153 +
1.154 + iFinished = ETrue;
1.155 + TRequestStatus* ps = &aStatus;
1.156 + User::RequestComplete(ps, KErrNone);
1.157 + }
1.158 +
1.159 +void CExternPbeParams::PerformAction(TRequestStatus& aStatus)
1.160 +/**
1.161 + Implements CTestAction by running the actual tests. This
1.162 + consists of:
1.163 +
1.164 + Reading an externalized CPBEncryptParms object and testing the
1.165 + cipher, salt, iv, iteration count, and KDF are as expected.
1.166 +
1.167 + Externalizing the object to memory.
1.168 +
1.169 + Testing the two externalizations are binary identical.
1.170 +
1.171 + Creating an equivalent object from scratch and externalizing it.
1.172 +
1.173 + Testing the externalizations are binary identical.
1.174 +
1.175 + As well as testing the objects can be stored reliably, this
1.176 + test also ensures that old (pre-PKCS#12) files can still be
1.177 + read and, and that objects are stored in the old format if they
1.178 + do not use any PKCS#12-specific features. (I.e., they use the
1.179 + default PKCS#5 KDF.)
1.180 +
1.181 + @param aStatus This request status is completed when
1.182 + the action has finished, successfully
1.183 + or otherwise. This implementation is
1.184 + synchronous, and so the status is actually
1.185 + completed before this function returns.
1.186 + */
1.187 + {
1.188 + TFileName fn;
1.189 + fn.Copy(*iOrigFileName); // convert from narrow
1.190 +
1.191 + // ensure reference file matches re-externalized form
1.192 +
1.193 + TRAPD(r,
1.194 + TestDecodeMatchesScriptL(fn);
1.195 + TestReExternMatchesL(fn);
1.196 + TestScratchExternL(fn) );
1.197 +
1.198 + iResult = (r == KErrNone);
1.199 + iActionState = CTestAction::EPostrequisite;
1.200 + TRequestStatus* status = &aStatus;
1.201 + User::RequestComplete(status, KErrNone);
1.202 + }
1.203 +
1.204 +CPBEncryptParms* CExternPbeParams::InternalizeEncryptionParamsLC(const TDesC& aFileName)
1.205 +/**
1.206 + Construct a CPBEncryptParms object from the externalized
1.207 + form in the named file.
1.208 +
1.209 + @param aFileName File which contains externalized form.
1.210 + @return Internalized encryption parameters object
1.211 + which is placed on the cleanup stack.
1.212 + */
1.213 + {
1.214 + RFileReadStream frs;
1.215 + TInt r = frs.Open(iFs, aFileName, EFileStream | EFileRead);
1.216 + User::LeaveIfError(r);
1.217 + CleanupClosePushL(frs);
1.218 + CPBEncryptParms* pbep = CPBEncryptParms::NewL(frs);
1.219 + CleanupStack::PopAndDestroy(&frs);
1.220 + CleanupStack::PushL(pbep);
1.221 + return pbep;
1.222 + }
1.223 +
1.224 +void CExternPbeParams::TestDecodeMatchesScriptL(const TDesC& aFileName)
1.225 +/**
1.226 + Test whether the encryption parameters which were externalized
1.227 + to the supplied file match those specified in the script file.
1.228 +
1.229 + @param aFileName Name of file which contains externalized form.
1.230 + @leave KErrGeneral The internalized form doesn't match the parameters
1.231 + in the script.
1.232 + */
1.233 + {
1.234 + CPBEncryptParms* pbep = InternalizeEncryptionParamsLC(aFileName);
1.235 +
1.236 + TBool match =
1.237 + pbep->Cipher() == iExpCipher
1.238 + && pbep->Salt() == *iExpSalt
1.239 + && pbep->Iterations() == iExpIterCount;
1.240 +
1.241 + match = match && pbep->Kdf() == iExpKdf;
1.242 +
1.243 + if (! match)
1.244 + User::Leave(KErrGeneral);
1.245 +
1.246 + CleanupStack::PopAndDestroy(pbep);
1.247 + }
1.248 +
1.249 +void CExternPbeParams::CompareAgainstTestFileL(
1.250 + const TDesC& aFileName, const CPBEncryptParms& aParams)
1.251 +/**
1.252 + Externalize the supplied parameters object and ensure it matches the
1.253 + test file.
1.254 +
1.255 + @param aFileName File which contains externalized parameters.
1.256 + @param aParams Test object to externalize.
1.257 + @leave KErrGeneral The externalized forms do not match.
1.258 + */
1.259 + {
1.260 + // open a file stream on the externalized form
1.261 + RFileReadStream frs;
1.262 + TInt r = frs.Open(iFs, aFileName, EFileStream | EFileRead);
1.263 + User::LeaveIfError(r);
1.264 + CleanupClosePushL(frs);
1.265 +
1.266 + // externalize the object to memory
1.267 + const TInt KMaxBufferLen = 128;
1.268 + HBufC8* reExtBuf = HBufC8::NewLC(KMaxBufferLen);
1.269 + TPtr8 reDes = reExtBuf->Des();
1.270 + RDesWriteStream dws(reDes);
1.271 + CleanupClosePushL(dws);
1.272 + aParams.ExternalizeL(dws);
1.273 + dws.CommitL();
1.274 +
1.275 + // ensure the externalized forms are equal
1.276 + RDesReadStream drs(reDes);
1.277 + TInt fLen = frs.Source()->SizeL();
1.278 + TInt mLen = drs.Source()->SizeL();
1.279 + if (fLen != mLen)
1.280 + User::Leave(KErrGeneral);
1.281 +
1.282 + TBuf8<1> fByte;
1.283 + TBuf8<1> mByte;
1.284 + for (TInt i = 0; i < fLen; ++i)
1.285 + {
1.286 + frs.ReadL(fByte, 1);
1.287 + drs.ReadL(mByte, 1);
1.288 + if (fByte != mByte)
1.289 + User::Leave(KErrGeneral);
1.290 + }
1.291 +
1.292 + CleanupStack::PopAndDestroy(3, &frs); // frs, reExtBuf, dws
1.293 + }
1.294 +
1.295 +void CExternPbeParams::TestReExternMatchesL(const TDesC& aFileName)
1.296 +/**
1.297 + Read the CPBEncryptParms object which is externalized in
1.298 + the named file, re-externalize it, and check the two
1.299 + representations are binary equivalent.
1.300 +
1.301 + @param aFileName Name of file which contains externalized form.
1.302 + @leave KErrGeneral The externalized forms are different.
1.303 + */
1.304 + {
1.305 + CPBEncryptParms* pbep = InternalizeEncryptionParamsLC(aFileName);
1.306 +
1.307 + CompareAgainstTestFileL(aFileName, *pbep);
1.308 +
1.309 + CleanupStack::PopAndDestroy(pbep);
1.310 + }
1.311 +
1.312 +void CExternPbeParams::TestScratchExternL(const TDesC& aFileName)
1.313 +/**
1.314 + Construct a CPBEncryptParams object from the parameter values
1.315 + in the script file. Test it matches the test file.
1.316 +
1.317 + @param aFileName Test file which contains externalized parameters.
1.318 + */
1.319 + {
1.320 + CPBEncryptParms* pbep = CPBEncryptParms::NewLC(
1.321 + static_cast<TPBECipher>(iExpCipher),
1.322 + *iExpSalt,
1.323 + *iExpIv,
1.324 + iExpIterCount);
1.325 +
1.326 + pbep->SetKdf(static_cast<CPBEncryptParms::TKdf>(iExpKdf));
1.327 +
1.328 + CompareAgainstTestFileL(aFileName, *pbep);
1.329 +
1.330 + CleanupStack::PopAndDestroy(pbep);
1.331 + }
1.332 +
1.333 +void CExternPbeParams::DoReportAction(void)
1.334 +/**
1.335 + Implements CTestAction but is empty.
1.336 + */
1.337 + {
1.338 + // empty.
1.339 + }
1.340 +
1.341 +void CExternPbeParams::DoCheckResult(TInt /*aError*/)
1.342 +/**
1.343 + Implements CTestAction but is empty.
1.344 + */
1.345 + {
1.346 + // empty.
1.347 + }
1.348 +
1.349 +
1.350 +// -------- support functions --------
1.351 +
1.352 +
1.353 +HBufC8* CExternPbeParams::ReadHexStringL(const TDesC8& aBody, const TDesC8& aTag)
1.354 +/**
1.355 + Convert a string in the test script to an 8-bit buffer. The string
1.356 + is a sequence of hex digits, e.g. "abcdef01", which is converted to a
1.357 + descriptor containing the matching bytes {0xab, 0xcd, 0xef, 0x01}.
1.358 +
1.359 + @param aBody Body of parent element.
1.360 + @param aTag Bare tag name. This function extracts the text
1.361 + between "<aTag>" and "</aTag>".
1.362 + @return Newly-allocated buffer containing matching bytes.
1.363 + This is owned by the caller.
1.364 + */
1.365 + {
1.366 + HBufC8* scriptString = ReadStringLC(aBody, aTag);
1.367 +
1.368 + TInt textLen = scriptString->Length();
1.369 + if ((textLen % 2) != 0)
1.370 + User::Leave(KErrCorrupt);
1.371 + TInt byteCount = textLen / 2;
1.372 + HBufC8* procString = HBufC8::NewMaxLC(byteCount);
1.373 + TPtr8 procDes = procString->Des();
1.374 + for (TInt i = 0; i < byteCount; ++i)
1.375 + {
1.376 + TUint8 byteVal;
1.377 + TInt r = TLex8(scriptString->Mid(i * 2, 2)).Val(byteVal, EHex);
1.378 + User::LeaveIfError(r);
1.379 + procDes[i] = byteVal;
1.380 + }
1.381 +
1.382 + CleanupStack::Pop(procString);
1.383 + CleanupStack::PopAndDestroy(scriptString);
1.384 + return procString;
1.385 + }
1.386 +
1.387 +TInt CExternPbeParams::ReadDecStringL(const TDesC8& aBody, const TDesC8& aTag)
1.388 +/**
1.389 + Finds a decimal text string in the script and returns the
1.390 + integer value which it represents.
1.391 +
1.392 + @param aBody Body of parent element.
1.393 + @param aTag Bare tag name. This function extracts the text
1.394 + between "<aTag>" and "</aTag>".
1.395 + @return Integer value encoded in the script file.
1.396 + */
1.397 + {
1.398 + HBufC8* scriptString = ReadStringLC(aBody, aTag);
1.399 +
1.400 + TInt value;
1.401 + User::LeaveIfError(TLex8(*scriptString).Val(value));
1.402 + CleanupStack::PopAndDestroy(scriptString);
1.403 + return value;
1.404 + }
1.405 +
1.406 +HBufC8* CExternPbeParams::ReadStringLC(const TDesC8& aBody, const TDesC8& aTag)
1.407 +/**
1.408 + Extracts a string from the supplied script file.
1.409 +
1.410 + @param aBody Body of parent element.
1.411 + @param aTag Bare tag name. This function extracts the text
1.412 + between "<aTag>" and "</aTag>".
1.413 + @return A copy of the string allocated on the heap. The
1.414 + string is placed on the cleanup stack.
1.415 + */
1.416 + {
1.417 + TBuf8<32> startTag;
1.418 + startTag.Format(_L8("<%S>"), &aTag);
1.419 + TBuf8<32> endTag;
1.420 + endTag.Format(_L8("</%S>"), &aTag);
1.421 +
1.422 + TInt pos = 0;
1.423 + TInt r;
1.424 + const TPtrC8 contents = Input::ParseElement(
1.425 + aBody, startTag, endTag, pos, r);
1.426 + User::LeaveIfError(r);
1.427 +
1.428 + return contents.AllocLC();
1.429 + }
1.430 +
1.431 +/**
1.432 + This code was originally in PerformAction to create the initial
1.433 + data files.
1.434 +
1.435 + // GENERATE PKCS5 TEST PARAMS FILE
1.436 + RFileWriteStream fws;
1.437 + r = fws.Replace(iFs, _L("c:\\tpbe\\pkcs5-orig.dat"), EFileStream | EFileWrite);
1.438 + User::LeaveIfError(r);
1.439 + CleanupClosePushL(fws);
1.440 +
1.441 + _LIT8(KSalt, "SALT4567");
1.442 + _LIT8(KIv, "IV23456789abcdef");
1.443 + const TInt KIterCount = 1234;
1.444 + CPBEncryptParms* pbep = CPBEncryptParms::NewLC(
1.445 + ECipherAES_CBC_256, KSalt, KIv, KIterCount);
1.446 + pbep->ExternalizeL(fws);
1.447 + fws.CommitL();
1.448 + CleanupStack::PopAndDestroy(2, &fws);
1.449 +
1.450 +#ifdef SYMBIAN_PKCS12
1.451 + // GENERATE PKCS12 TEST PARAMS FILE
1.452 + RFileWriteStream fws;
1.453 + r = fws.Replace(iFs, _L("c:\\tpbe\\pkcs12-first.dat"), EFileStream | EFileWrite);
1.454 + User::LeaveIfError(r);
1.455 + CleanupClosePushL(fws);
1.456 +
1.457 + _LIT8(KSalt, "SALT4567");
1.458 + _LIT8(KIv, "IV23456789abcdef");
1.459 + const TInt KIterCount = 1234;
1.460 + CPBEncryptParms* pbep = CPBEncryptParms::NewLC(
1.461 + ECipherAES_CBC_256, KSalt, KIv, KIterCount);
1.462 + pbep->SetKdf(CPBEncryptParms::EKdfPkcs12);
1.463 + pbep->ExternalizeL(fws);
1.464 + fws.CommitL();
1.465 + CleanupStack::PopAndDestroy(2, &fws);
1.466 +#endif // #ifdef SYMBIAN_PKCS12
1.467 +
1.468 + */