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