diff -r 000000000000 -r 2c201484c85f crypto/weakcrypto/test/tpbe/texternpbeparams.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/crypto/weakcrypto/test/tpbe/texternpbeparams.cpp Wed Jul 08 11:25:26 2009 +0100 @@ -0,0 +1,464 @@ +/* +* Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + +#include +#include +#include "texternpbeparams.h" + + +CTestAction* CExternPbeParams::NewL( + RFs& aFs, CConsoleBase& aConsole, + Output& aOut, const TTestActionSpec& aTestActionSpec) +/** + Factory function allocates new instance of CExternPbeParams and extracts + the element body from the supplied test action spec. + + @param aFs Used to parse XML script file. + @param aConsole Required by CTestAction. + @param aOut Required by CTestAction. + @param aTestActionSpec Action specification contains type, name, and + XML contents. + @return New instance of CExternPbeParams, which is owned + by the caller. + */ + { + CExternPbeParams* self = new(ELeave) CExternPbeParams(aConsole, aOut, aFs); + CleanupStack::PushL(self); + self->ConstructL(aTestActionSpec); + CleanupStack::Pop(self); + return self; + } + +CExternPbeParams::CExternPbeParams(CConsoleBase& aConsole, Output& aOut, RFs& aFs) +/** + This constructor exists to record the file server session and to initialize + the CTestAction superclass. + + @param aConsole Required by CTestAction. + @param aOut Required by CTestAction. + @param aFs Used to read from and write to files in PerformAction, + which stores and restores the externalized params. + */ +: CTestAction(aConsole, aOut), + iFs(aFs) + { + // empty. + } + +void CExternPbeParams::ConstructL(const TTestActionSpec& aTestActionSpec) +/** + Second phase initialization initializes the superclass and + makes a copy of the test element. + + @param aTestActionSpec Action specification contains type, name, and + XML contents. + */ + { + CTestAction::ConstructL(aTestActionSpec); + iBody = aTestActionSpec.iActionBody.AllocL(); + + // iBody is deconstructed in DoPerformPrerequisite + } + +CExternPbeParams::~CExternPbeParams() +/** + Free resources allocated in ConstructL. Specifically, + deletes the copy of the element body text. + */ + { + delete iBody; + } + +// -------- implement CTestAction -------- + +void CExternPbeParams::DoPerformPrerequisite(TRequestStatus& aStatus) +/** + Override CTestAction by deconstructing element body allocated + in ConstructL. + + If this function fails then DoPerformPostrequisite must still + be called. + + @param aStatus This status is completed when the prerequisite + has finished. (This implementation is actually + synchronous so the request will already be completed + when it returns.) + */ + { + TRAPD(r, DoPerformPrerequisiteL()); + + iActionState = CTestAction::EAction; + TRequestStatus* ps = &aStatus; + User::RequestComplete(ps, r); + } + +void CExternPbeParams::DoPerformPrerequisiteL() +/** + Helper function for DoPerformPrerequisite contains resource allocation + functions which can leave. + + Extracts cipher, salt, iv, iter count, and kdf values. + */ + { + _LIT8(KOrigFileName, "orig-filename"); + iOrigFileName = ReadStringLC(*iBody, KOrigFileName); + CleanupStack::Pop(iOrigFileName); + + _LIT8(KExpCipherElemName, "expected-cipher"); + iExpCipher = ReadDecStringL(*iBody, KExpCipherElemName); + _LIT8(KExpSaltElemName, "expected-salt"); + iExpSalt = ReadHexStringL(*iBody, KExpSaltElemName); + _LIT8(KExpIvElemName, "expected-iv"); + iExpIv = ReadHexStringL(*iBody, KExpIvElemName); + _LIT8(KExpIterCountElemName, "expected-iter-count"); + iExpIterCount = ReadDecStringL(*iBody, KExpIterCountElemName); + _LIT8(KExpKdfElemName, "expected-kdf"); + iExpKdf = ReadDecStringL(*iBody, KExpKdfElemName); + } + +void CExternPbeParams::DoPerformPostrequisite(TRequestStatus& aStatus) +/** + Implements CTestAction by cleaning up data allocated in DoPerformPrerequisiteL. + + @param aStatus This status is completed to indicate the + postrequisite has finished. (This function + is synchronous so the status is completed before + this function returns.) + */ + { + delete iExpIv; + iExpIv = 0; + delete iExpSalt; + iExpSalt = 0; + delete iOrigFileName; + iOrigFileName = NULL; + + iFinished = ETrue; + TRequestStatus* ps = &aStatus; + User::RequestComplete(ps, KErrNone); + } + +void CExternPbeParams::PerformAction(TRequestStatus& aStatus) +/** + Implements CTestAction by running the actual tests. This + consists of: + + Reading an externalized CPBEncryptParms object and testing the + cipher, salt, iv, iteration count, and KDF are as expected. + + Externalizing the object to memory. + + Testing the two externalizations are binary identical. + + Creating an equivalent object from scratch and externalizing it. + + Testing the externalizations are binary identical. + + As well as testing the objects can be stored reliably, this + test also ensures that old (pre-PKCS#12) files can still be + read and, and that objects are stored in the old format if they + do not use any PKCS#12-specific features. (I.e., they use the + default PKCS#5 KDF.) + + @param aStatus This request status is completed when + the action has finished, successfully + or otherwise. This implementation is + synchronous, and so the status is actually + completed before this function returns. + */ + { + TFileName fn; + fn.Copy(*iOrigFileName); // convert from narrow + + // ensure reference file matches re-externalized form + + TRAPD(r, + TestDecodeMatchesScriptL(fn); + TestReExternMatchesL(fn); + TestScratchExternL(fn) ); + + iResult = (r == KErrNone); + iActionState = CTestAction::EPostrequisite; + TRequestStatus* status = &aStatus; + User::RequestComplete(status, KErrNone); + } + +CPBEncryptParms* CExternPbeParams::InternalizeEncryptionParamsLC(const TDesC& aFileName) +/** + Construct a CPBEncryptParms object from the externalized + form in the named file. + + @param aFileName File which contains externalized form. + @return Internalized encryption parameters object + which is placed on the cleanup stack. + */ + { + RFileReadStream frs; + TInt r = frs.Open(iFs, aFileName, EFileStream | EFileRead); + User::LeaveIfError(r); + CleanupClosePushL(frs); + CPBEncryptParms* pbep = CPBEncryptParms::NewL(frs); + CleanupStack::PopAndDestroy(&frs); + CleanupStack::PushL(pbep); + return pbep; + } + +void CExternPbeParams::TestDecodeMatchesScriptL(const TDesC& aFileName) +/** + Test whether the encryption parameters which were externalized + to the supplied file match those specified in the script file. + + @param aFileName Name of file which contains externalized form. + @leave KErrGeneral The internalized form doesn't match the parameters + in the script. + */ + { + CPBEncryptParms* pbep = InternalizeEncryptionParamsLC(aFileName); + + TBool match = + pbep->Cipher() == iExpCipher + && pbep->Salt() == *iExpSalt + && pbep->Iterations() == iExpIterCount; + + match = match && pbep->Kdf() == iExpKdf; + + if (! match) + User::Leave(KErrGeneral); + + CleanupStack::PopAndDestroy(pbep); + } + +void CExternPbeParams::CompareAgainstTestFileL( + const TDesC& aFileName, const CPBEncryptParms& aParams) +/** + Externalize the supplied parameters object and ensure it matches the + test file. + + @param aFileName File which contains externalized parameters. + @param aParams Test object to externalize. + @leave KErrGeneral The externalized forms do not match. + */ + { + // open a file stream on the externalized form + RFileReadStream frs; + TInt r = frs.Open(iFs, aFileName, EFileStream | EFileRead); + User::LeaveIfError(r); + CleanupClosePushL(frs); + + // externalize the object to memory + const TInt KMaxBufferLen = 128; + HBufC8* reExtBuf = HBufC8::NewLC(KMaxBufferLen); + TPtr8 reDes = reExtBuf->Des(); + RDesWriteStream dws(reDes); + CleanupClosePushL(dws); + aParams.ExternalizeL(dws); + dws.CommitL(); + + // ensure the externalized forms are equal + RDesReadStream drs(reDes); + TInt fLen = frs.Source()->SizeL(); + TInt mLen = drs.Source()->SizeL(); + if (fLen != mLen) + User::Leave(KErrGeneral); + + TBuf8<1> fByte; + TBuf8<1> mByte; + for (TInt i = 0; i < fLen; ++i) + { + frs.ReadL(fByte, 1); + drs.ReadL(mByte, 1); + if (fByte != mByte) + User::Leave(KErrGeneral); + } + + CleanupStack::PopAndDestroy(3, &frs); // frs, reExtBuf, dws + } + +void CExternPbeParams::TestReExternMatchesL(const TDesC& aFileName) +/** + Read the CPBEncryptParms object which is externalized in + the named file, re-externalize it, and check the two + representations are binary equivalent. + + @param aFileName Name of file which contains externalized form. + @leave KErrGeneral The externalized forms are different. + */ + { + CPBEncryptParms* pbep = InternalizeEncryptionParamsLC(aFileName); + + CompareAgainstTestFileL(aFileName, *pbep); + + CleanupStack::PopAndDestroy(pbep); + } + +void CExternPbeParams::TestScratchExternL(const TDesC& aFileName) +/** + Construct a CPBEncryptParams object from the parameter values + in the script file. Test it matches the test file. + + @param aFileName Test file which contains externalized parameters. + */ + { + CPBEncryptParms* pbep = CPBEncryptParms::NewLC( + static_cast(iExpCipher), + *iExpSalt, + *iExpIv, + iExpIterCount); + + pbep->SetKdf(static_cast(iExpKdf)); + + CompareAgainstTestFileL(aFileName, *pbep); + + CleanupStack::PopAndDestroy(pbep); + } + +void CExternPbeParams::DoReportAction(void) +/** + Implements CTestAction but is empty. + */ + { + // empty. + } + +void CExternPbeParams::DoCheckResult(TInt /*aError*/) +/** + Implements CTestAction but is empty. + */ + { + // empty. + } + + +// -------- support functions -------- + + +HBufC8* CExternPbeParams::ReadHexStringL(const TDesC8& aBody, const TDesC8& aTag) +/** + Convert a string in the test script to an 8-bit buffer. The string + is a sequence of hex digits, e.g. "abcdef01", which is converted to a + descriptor containing the matching bytes {0xab, 0xcd, 0xef, 0x01}. + + @param aBody Body of parent element. + @param aTag Bare tag name. This function extracts the text + between "" and "". + @return Newly-allocated buffer containing matching bytes. + This is owned by the caller. + */ + { + HBufC8* scriptString = ReadStringLC(aBody, aTag); + + TInt textLen = scriptString->Length(); + if ((textLen % 2) != 0) + User::Leave(KErrCorrupt); + TInt byteCount = textLen / 2; + HBufC8* procString = HBufC8::NewMaxLC(byteCount); + TPtr8 procDes = procString->Des(); + for (TInt i = 0; i < byteCount; ++i) + { + TUint8 byteVal; + TInt r = TLex8(scriptString->Mid(i * 2, 2)).Val(byteVal, EHex); + User::LeaveIfError(r); + procDes[i] = byteVal; + } + + CleanupStack::Pop(procString); + CleanupStack::PopAndDestroy(scriptString); + return procString; + } + +TInt CExternPbeParams::ReadDecStringL(const TDesC8& aBody, const TDesC8& aTag) +/** + Finds a decimal text string in the script and returns the + integer value which it represents. + + @param aBody Body of parent element. + @param aTag Bare tag name. This function extracts the text + between "" and "". + @return Integer value encoded in the script file. + */ + { + HBufC8* scriptString = ReadStringLC(aBody, aTag); + + TInt value; + User::LeaveIfError(TLex8(*scriptString).Val(value)); + CleanupStack::PopAndDestroy(scriptString); + return value; + } + +HBufC8* CExternPbeParams::ReadStringLC(const TDesC8& aBody, const TDesC8& aTag) +/** + Extracts a string from the supplied script file. + + @param aBody Body of parent element. + @param aTag Bare tag name. This function extracts the text + between "" and "". + @return A copy of the string allocated on the heap. The + string is placed on the cleanup stack. + */ + { + TBuf8<32> startTag; + startTag.Format(_L8("<%S>"), &aTag); + TBuf8<32> endTag; + endTag.Format(_L8(""), &aTag); + + TInt pos = 0; + TInt r; + const TPtrC8 contents = Input::ParseElement( + aBody, startTag, endTag, pos, r); + User::LeaveIfError(r); + + return contents.AllocLC(); + } + +/** + This code was originally in PerformAction to create the initial + data files. + + // GENERATE PKCS5 TEST PARAMS FILE + RFileWriteStream fws; + r = fws.Replace(iFs, _L("c:\\tpbe\\pkcs5-orig.dat"), EFileStream | EFileWrite); + User::LeaveIfError(r); + CleanupClosePushL(fws); + + _LIT8(KSalt, "SALT4567"); + _LIT8(KIv, "IV23456789abcdef"); + const TInt KIterCount = 1234; + CPBEncryptParms* pbep = CPBEncryptParms::NewLC( + ECipherAES_CBC_256, KSalt, KIv, KIterCount); + pbep->ExternalizeL(fws); + fws.CommitL(); + CleanupStack::PopAndDestroy(2, &fws); + +#ifdef SYMBIAN_PKCS12 + // GENERATE PKCS12 TEST PARAMS FILE + RFileWriteStream fws; + r = fws.Replace(iFs, _L("c:\\tpbe\\pkcs12-first.dat"), EFileStream | EFileWrite); + User::LeaveIfError(r); + CleanupClosePushL(fws); + + _LIT8(KSalt, "SALT4567"); + _LIT8(KIv, "IV23456789abcdef"); + const TInt KIterCount = 1234; + CPBEncryptParms* pbep = CPBEncryptParms::NewLC( + ECipherAES_CBC_256, KSalt, KIv, KIterCount); + pbep->SetKdf(CPBEncryptParms::EKdfPkcs12); + pbep->ExternalizeL(fws); + fws.CommitL(); + CleanupStack::PopAndDestroy(2, &fws); +#endif // #ifdef SYMBIAN_PKCS12 + + */