os/security/cryptoservices/certificateandkeymgmt/tx509/CorruptionTest.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 1998-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 "CorruptionTest.h"
    20 #include "SyntaxTest.h"
    21 #include "wtlscert.h"
    22 #include "t_output.h"
    23 #include "t_input.h"
    24 #include <random.h>
    25 #include <asymmetric.h>
    26 #include <bigint.h>
    27 
    28 TInt CCorruptionTest::nInstances = 0;
    29 _LIT(KCorruptLogFile, "X509CorruptLog.txt");
    30 _LIT(KPathStart, "<path>");
    31 _LIT(KIterationsStart, "<iterations>");
    32 
    33 //////////////////////////////////////////////////////////////////////
    34 // Construction/Destruction
    35 //////////////////////////////////////////////////////////////////////
    36 
    37 CTestAction* CCorruptionTest::NewL(RFs& aFs, CConsoleBase& aConsole, 
    38 		Output& aOut, const TTestActionSpec& aTestActionSpec)
    39 	{
    40 	CTestAction* self = CCorruptionTest::NewLC(aFs, aConsole, aOut, aTestActionSpec);
    41 	CleanupStack::Pop(self);
    42 	return self;
    43 	}
    44 
    45 CTestAction* CCorruptionTest::NewLC(RFs& aFs, CConsoleBase& aConsole, 
    46 		Output& aOut, const TTestActionSpec& aTestActionSpec)
    47 	{
    48 	CCorruptionTest* self = new(ELeave) CCorruptionTest(aFs, aConsole, aOut);
    49 	CleanupStack::PushL(self);
    50 	self->ConstructL(aTestActionSpec);
    51 	return self;
    52 	}
    53 
    54 CCorruptionTest::CCorruptionTest(RFs& aFs, 
    55 								 CConsoleBase& aConsole,
    56 								 Output& aOut)
    57 : CTestAction(aConsole, aOut), iFs(aFs)
    58 	{
    59 	nFileNumber = 0;
    60 	}
    61 
    62 CCorruptionTest::~CCorruptionTest(void)
    63 	{
    64 	delete iDirList;
    65 	delete iWriter;
    66 	iLogFile.Close();
    67 	delete iNullOut;
    68 	delete iCorruptOut;
    69 	};
    70 
    71 void CCorruptionTest::ConstructL(const TTestActionSpec& aTestActionSpec)
    72 	{
    73 	CTestAction::ConstructL(aTestActionSpec);
    74 
    75 	if(nInstances==0)
    76 		{
    77 		HBufC* body = HBufC::NewLC(aTestActionSpec.iActionBody.Length());
    78 		TInt pos=0;
    79 
    80 		nInstances++;
    81 		iNullOut = new(ELeave) NullOutput;
    82 		body->Des().Copy(aTestActionSpec.iActionBody);
    83 		TPtrC chainBuf = Input::ParseElement(*body, KPathStart, pos);
    84 		iPath.Copy(chainBuf);
    85 		TPtrC itertaionBuf = Input::ParseElement(*body, KIterationsStart, pos);
    86 		TLex itLex(itertaionBuf);
    87 
    88 		itLex.Val(iIterations);
    89 		CleanupStack::PopAndDestroy(); // body
    90 		User::LeaveIfError(iLogFile.Replace(iFs,KCorruptLogFile,EFileWrite));
    91 		iCorruptOut = new(ELeave) FileOutput(iLogFile);
    92 		iWriter = new(ELeave) CertWriter(iCorruptOut);
    93 		}
    94 	else
    95 		{
    96 		SetScriptError(ESyntax, _L("Only one corruption test can be run in each script"));
    97 		iFinished = ETrue;
    98 		}
    99 	}
   100 
   101 
   102 void CCorruptionTest::DoPerformPrerequisite(TRequestStatus& aStatus)
   103 	{
   104 	HBufC *searchPath = HBufC::NewLC(iPath.Size() + 1);
   105 	TPtr searchPathPtr(searchPath->Des());
   106 	searchPathPtr.Copy(iPath);
   107 	searchPathPtr.Append(_L("*"));
   108     TInt err = iFs.GetDir(searchPathPtr, KEntryAttMaskSupported, ESortByName, iDirList);
   109 	if (err != KErrNone)
   110 		{
   111 		iConsole.Printf(_L("Error getting directory "));
   112 		iConsole.Printf(searchPathPtr);
   113 		iConsole.Printf(_L("\n"));
   114 		iOut.writeString(_L("Error getting directory "));
   115 		iOut.writeString(searchPathPtr);
   116 		iOut.writeNewLine();
   117 		iFinished = ETrue;
   118 		TRequestStatus* status = &aStatus;
   119 		User::RequestComplete(status, KErrNone);
   120 		SetScriptError(EFileNotFound, searchPathPtr);
   121 		}
   122 	else
   123 		{
   124 		iConsole.Printf(_L("Please view "));
   125 		iConsole.Printf(KCorruptLogFile);
   126 		iConsole.Printf(_L(" for results\n"));
   127 		iOut.writeString(_L("Please view "));
   128 		iOut.writeString(KCorruptLogFile);
   129 		iOut.writeString(_L(" for results"));
   130 		iOut.writeNewLine();
   131 		iActionState = EAction;
   132 		TRequestStatus* status = &aStatus;
   133 		User::RequestComplete(status, KErrNone);
   134 		iResult = ETrue;
   135 		}
   136 	CleanupStack::PopAndDestroy();
   137 	}
   138 
   139 void CCorruptionTest::DoPerformPostrequisite(TRequestStatus& aStatus)
   140 	{
   141 	TRequestStatus* status = &aStatus;
   142 	iFinished = ETrue;
   143 	User::RequestComplete(status, KErrNone);
   144 	}
   145 
   146 void CCorruptionTest::RunCorruptionTestL(const TDesC &aFilename)
   147 	{
   148 	__UHEAP_MARK;
   149 	for (TInt i = 0; i < iIterations; i++)
   150 		{
   151 		HBufC8* buf = Input::ReadFileLC(aFilename, iPath, iFs);
   152 		TPtr8 pBuf = buf->Des();
   153 		TInt len = pBuf.Size();
   154 		TInt pos = 0;
   155 				//list of positions altered
   156 		HBufC* posOctsBuf = HBufC::NewLC(70);
   157 		TPtr pPosOctsBuf = posOctsBuf->Des();
   158 		pPosOctsBuf.SetLength(0);
   159 		pPosOctsBuf.Append(_L("p:"));
   160 				//list of octets altered
   161 		HBufC8* octsBuf = HBufC8::NewLC(40);
   162 		TPtr8 pOctsBuf = octsBuf->Des();
   163 		pOctsBuf.SetLength(0);
   164 
   165 		for (TInt j = 0; j < 10; j++)
   166 			{
   167 				//randomness
   168 			HBufC8* rand = HBufC8::NewLC(5);
   169 			TPtr8 pRand = rand->Des();
   170 			pRand.SetLength(5);
   171 			TRandom::RandomL(pRand);
   172 			TUint num = 0;
   173 			for (TInt k = 0; k < 4 ; k++)
   174 				{
   175 				num<<=8;
   176 				num+=pRand[k];
   177 				}
   178 			pos = num % len;
   179 			TUint8 newOctet = pRand[4];
   180 				//update output lines
   181 			pPosOctsBuf.AppendNum(pos);
   182 			pPosOctsBuf.Append(_L(" "));
   183 			pOctsBuf.Append(pBuf.Mid(pos, 1));
   184 			TPtrC8 pNewOct = pRand.Right(1);
   185 			pOctsBuf.Append(pNewOct);
   186 				//switch the selected octet
   187 			pBuf[pos] = newOctet;
   188 				//file out
   189 			iCorruptOut->writeString(pPosOctsBuf);
   190 			iCorruptOut->writeNewLine();
   191 			iCorruptOut->writeString(_L("o:"));
   192 			iCorruptOut->writeOctetString(pOctsBuf);
   193 			iCorruptOut->writeNewLine();
   194 				//try to make corrupt cert
   195 			CX509Certificate* cert = NULL;
   196 			TRAPD(err, cert = CX509Certificate::NewL(pBuf));
   197 			CleanupStack::PushL(cert);
   198 			if (err == KErrNone)
   199 				{
   200 				TBool res = EFalse;;
   201 			//	Don't bother attempting to verify if public key modulus is even
   202 			//	since CMontgomery methods will fail...	
   203 				TKeyFactory* theKeyFactory = new (ELeave) TX509KeyFactory();
   204 				CleanupStack::PushL(theKeyFactory);
   205 				CRSAPublicKey* key = theKeyFactory->RSAPublicKeyL(cert->PublicKey().KeyData());
   206 				CleanupStack::Pop(theKeyFactory);
   207 				delete theKeyFactory;
   208 				
   209 				const TInteger& theN = key->N();
   210 				if (theN.IsOdd())
   211 					{
   212 					RInteger input = RInteger::NewL(cert->Signature());
   213 					CleanupStack::PushL(input);
   214 				//	Check that the signature is not out of bounds for the key
   215 				//	Otherwise the crypto library will panic (descriptor out of bounds)
   216 					if ( (input < theN) && (input > 0) )
   217 						{
   218 						TRAP_IGNORE(res = cert->VerifySignatureL(cert->PublicKey().KeyData()));
   219 						if (res)
   220 							{
   221 							iCorruptOut->writeString(_L("!!!"));
   222 							iCorruptOut->writeNewLine();
   223 							}
   224 						}
   225 	
   226 						CleanupStack::PopAndDestroy(&input);
   227 					}
   228 
   229 					delete key;
   230 				}
   231 			iCorruptOut->writeString(_L("r:"));
   232 			iCorruptOut->writeNum(err);
   233 			iCorruptOut->writeNewLine();
   234 			CleanupStack::PopAndDestroy(2);// rand, cert
   235 			}
   236 		CleanupStack::PopAndDestroy(3);//
   237 		}
   238 	__UHEAP_MARKEND;
   239 	}
   240 
   241 //	These tests are very slow and do not need to be performed on every
   242 //	certificate in the x509 test directory.  Corrupt every 10th certificate.
   243 void CCorruptionTest::PerformAction(TRequestStatus& aStatus)
   244 	{
   245 	TBuf<256> filename = (*iDirList)[nFileNumber].iName;
   246 	TInt error;
   247 	
   248 	if( (filename.CompareF(KResultsFile)!=0) && (nFileNumber%10==0) )
   249 		{
   250 		iCorruptOut->writeString(_L("file:"));
   251 		iCorruptOut->writeString(filename);
   252 		iCorruptOut->writeNewLine();
   253 		iConsole.Printf(_L("file:%S\n"), &filename);
   254 		
   255 		TRAP(error, RunCorruptionTestL(filename));
   256 		if(error == KErrNoMemory)
   257 			User::Leave(error);
   258 		};
   259 
   260 	
   261 	if(++nFileNumber == iDirList->Count())
   262 		{
   263 		iActionState = EPostrequisite;
   264 		};
   265 	TRequestStatus* status = &aStatus;
   266 	User::RequestComplete(status, KErrNone);
   267 	}
   268 
   269 void CCorruptionTest::DoReportAction()
   270 	{
   271 	}
   272 
   273 void CCorruptionTest::DoCheckResult(TInt /*aError*/)
   274 	{
   275 	}
   276 
   277 HBufC8* CCorruptionTest::readCertLC(const TDesC& aFilename)
   278 	{
   279 	TFileName fullname;
   280 	fullname.Append(iPath);
   281 	fullname.Append(aFilename);
   282 
   283 	RFile file;
   284 	User::LeaveIfError( file.Open(iFs, fullname, EFileRead) );
   285 	
   286 	TInt size;
   287 	file.Size(size);
   288 	file.Close();
   289 
   290 	HBufC8* res = HBufC8::NewLC(size);
   291 	TPtr8 p(res->Des());
   292 	p.SetLength(size);
   293 
   294 	RFileReadStream stream;
   295 	User::LeaveIfError(stream.Open(iFs, fullname, EFileStream));
   296 	stream.ReadL(p, size);
   297 	stream.Close();
   298 	return res;
   299 	}