os/security/crypto/weakcryptospi/test/tpbe/texternpbeparams.cpp
changeset 0 bde4ae8d615e
     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 + */