sl@0: /* sl@0: * Copyright (c) 1998-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: * All rights reserved. sl@0: * This component and the accompanying materials are made available sl@0: * under the terms of the License "Eclipse Public License v1.0" sl@0: * which accompanies this distribution, and is available sl@0: * at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: * sl@0: * Initial Contributors: sl@0: * Nokia Corporation - initial contribution. sl@0: * sl@0: * Contributors: sl@0: * sl@0: * Description: sl@0: * sl@0: */ sl@0: sl@0: sl@0: #include "CorruptionTest.h" sl@0: #include "SyntaxTest.h" sl@0: #include "wtlscert.h" sl@0: #include "t_output.h" sl@0: #include "t_input.h" sl@0: #include sl@0: #include sl@0: #include sl@0: sl@0: TInt CCorruptionTest::nInstances = 0; sl@0: _LIT(KCorruptLogFile, "X509CorruptLog.txt"); sl@0: _LIT(KPathStart, ""); sl@0: _LIT(KIterationsStart, ""); sl@0: sl@0: ////////////////////////////////////////////////////////////////////// sl@0: // Construction/Destruction sl@0: ////////////////////////////////////////////////////////////////////// sl@0: sl@0: CTestAction* CCorruptionTest::NewL(RFs& aFs, CConsoleBase& aConsole, sl@0: Output& aOut, const TTestActionSpec& aTestActionSpec) sl@0: { sl@0: CTestAction* self = CCorruptionTest::NewLC(aFs, aConsole, aOut, aTestActionSpec); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CTestAction* CCorruptionTest::NewLC(RFs& aFs, CConsoleBase& aConsole, sl@0: Output& aOut, const TTestActionSpec& aTestActionSpec) sl@0: { sl@0: CCorruptionTest* self = new(ELeave) CCorruptionTest(aFs, aConsole, aOut); sl@0: CleanupStack::PushL(self); sl@0: self->ConstructL(aTestActionSpec); sl@0: return self; sl@0: } sl@0: sl@0: CCorruptionTest::CCorruptionTest(RFs& aFs, sl@0: CConsoleBase& aConsole, sl@0: Output& aOut) sl@0: : CTestAction(aConsole, aOut), iFs(aFs) sl@0: { sl@0: nFileNumber = 0; sl@0: } sl@0: sl@0: CCorruptionTest::~CCorruptionTest(void) sl@0: { sl@0: delete iDirList; sl@0: delete iWriter; sl@0: iLogFile.Close(); sl@0: delete iNullOut; sl@0: delete iCorruptOut; sl@0: }; sl@0: sl@0: void CCorruptionTest::ConstructL(const TTestActionSpec& aTestActionSpec) sl@0: { sl@0: CTestAction::ConstructL(aTestActionSpec); sl@0: sl@0: if(nInstances==0) sl@0: { sl@0: HBufC* body = HBufC::NewLC(aTestActionSpec.iActionBody.Length()); sl@0: TInt pos=0; sl@0: sl@0: nInstances++; sl@0: iNullOut = new(ELeave) NullOutput; sl@0: body->Des().Copy(aTestActionSpec.iActionBody); sl@0: TPtrC chainBuf = Input::ParseElement(*body, KPathStart, pos); sl@0: iPath.Copy(chainBuf); sl@0: TPtrC itertaionBuf = Input::ParseElement(*body, KIterationsStart, pos); sl@0: TLex itLex(itertaionBuf); sl@0: sl@0: itLex.Val(iIterations); sl@0: CleanupStack::PopAndDestroy(); // body sl@0: User::LeaveIfError(iLogFile.Replace(iFs,KCorruptLogFile,EFileWrite)); sl@0: iCorruptOut = new(ELeave) FileOutput(iLogFile); sl@0: iWriter = new(ELeave) CertWriter(iCorruptOut); sl@0: } sl@0: else sl@0: { sl@0: SetScriptError(ESyntax, _L("Only one corruption test can be run in each script")); sl@0: iFinished = ETrue; sl@0: } sl@0: } sl@0: sl@0: sl@0: void CCorruptionTest::DoPerformPrerequisite(TRequestStatus& aStatus) sl@0: { sl@0: HBufC *searchPath = HBufC::NewLC(iPath.Size() + 1); sl@0: TPtr searchPathPtr(searchPath->Des()); sl@0: searchPathPtr.Copy(iPath); sl@0: searchPathPtr.Append(_L("*")); sl@0: TInt err = iFs.GetDir(searchPathPtr, KEntryAttMaskSupported, ESortByName, iDirList); sl@0: if (err != KErrNone) sl@0: { sl@0: iConsole.Printf(_L("Error getting directory ")); sl@0: iConsole.Printf(searchPathPtr); sl@0: iConsole.Printf(_L("\n")); sl@0: iOut.writeString(_L("Error getting directory ")); sl@0: iOut.writeString(searchPathPtr); sl@0: iOut.writeNewLine(); sl@0: iFinished = ETrue; sl@0: TRequestStatus* status = &aStatus; sl@0: User::RequestComplete(status, KErrNone); sl@0: SetScriptError(EFileNotFound, searchPathPtr); sl@0: } sl@0: else sl@0: { sl@0: iConsole.Printf(_L("Please view ")); sl@0: iConsole.Printf(KCorruptLogFile); sl@0: iConsole.Printf(_L(" for results\n")); sl@0: iOut.writeString(_L("Please view ")); sl@0: iOut.writeString(KCorruptLogFile); sl@0: iOut.writeString(_L(" for results")); sl@0: iOut.writeNewLine(); sl@0: iActionState = EAction; sl@0: TRequestStatus* status = &aStatus; sl@0: User::RequestComplete(status, KErrNone); sl@0: iResult = ETrue; sl@0: } sl@0: CleanupStack::PopAndDestroy(); sl@0: } sl@0: sl@0: void CCorruptionTest::DoPerformPostrequisite(TRequestStatus& aStatus) sl@0: { sl@0: TRequestStatus* status = &aStatus; sl@0: iFinished = ETrue; sl@0: User::RequestComplete(status, KErrNone); sl@0: } sl@0: sl@0: void CCorruptionTest::RunCorruptionTestL(const TDesC &aFilename) sl@0: { sl@0: __UHEAP_MARK; sl@0: for (TInt i = 0; i < iIterations; i++) sl@0: { sl@0: HBufC8* buf = Input::ReadFileLC(aFilename, iPath, iFs); sl@0: TPtr8 pBuf = buf->Des(); sl@0: TInt len = pBuf.Size(); sl@0: TInt pos = 0; sl@0: //list of positions altered sl@0: HBufC* posOctsBuf = HBufC::NewLC(70); sl@0: TPtr pPosOctsBuf = posOctsBuf->Des(); sl@0: pPosOctsBuf.SetLength(0); sl@0: pPosOctsBuf.Append(_L("p:")); sl@0: //list of octets altered sl@0: HBufC8* octsBuf = HBufC8::NewLC(40); sl@0: TPtr8 pOctsBuf = octsBuf->Des(); sl@0: pOctsBuf.SetLength(0); sl@0: sl@0: for (TInt j = 0; j < 10; j++) sl@0: { sl@0: //randomness sl@0: HBufC8* rand = HBufC8::NewLC(5); sl@0: TPtr8 pRand = rand->Des(); sl@0: pRand.SetLength(5); sl@0: TRandom::RandomL(pRand); sl@0: TUint num = 0; sl@0: for (TInt k = 0; k < 4 ; k++) sl@0: { sl@0: num<<=8; sl@0: num+=pRand[k]; sl@0: } sl@0: pos = num % len; sl@0: TUint8 newOctet = pRand[4]; sl@0: //update output lines sl@0: pPosOctsBuf.AppendNum(pos); sl@0: pPosOctsBuf.Append(_L(" ")); sl@0: pOctsBuf.Append(pBuf.Mid(pos, 1)); sl@0: TPtrC8 pNewOct = pRand.Right(1); sl@0: pOctsBuf.Append(pNewOct); sl@0: //switch the selected octet sl@0: pBuf[pos] = newOctet; sl@0: //file out sl@0: iCorruptOut->writeString(pPosOctsBuf); sl@0: iCorruptOut->writeNewLine(); sl@0: iCorruptOut->writeString(_L("o:")); sl@0: iCorruptOut->writeOctetString(pOctsBuf); sl@0: iCorruptOut->writeNewLine(); sl@0: //try to make corrupt cert sl@0: CX509Certificate* cert = NULL; sl@0: TRAPD(err, cert = CX509Certificate::NewL(pBuf)); sl@0: CleanupStack::PushL(cert); sl@0: if (err == KErrNone) sl@0: { sl@0: TBool res = EFalse;; sl@0: // Don't bother attempting to verify if public key modulus is even sl@0: // since CMontgomery methods will fail... sl@0: TKeyFactory* theKeyFactory = new (ELeave) TX509KeyFactory(); sl@0: CleanupStack::PushL(theKeyFactory); sl@0: CRSAPublicKey* key = theKeyFactory->RSAPublicKeyL(cert->PublicKey().KeyData()); sl@0: CleanupStack::Pop(theKeyFactory); sl@0: delete theKeyFactory; sl@0: sl@0: const TInteger& theN = key->N(); sl@0: if (theN.IsOdd()) sl@0: { sl@0: RInteger input = RInteger::NewL(cert->Signature()); sl@0: CleanupStack::PushL(input); sl@0: // Check that the signature is not out of bounds for the key sl@0: // Otherwise the crypto library will panic (descriptor out of bounds) sl@0: if ( (input < theN) && (input > 0) ) sl@0: { sl@0: TRAP_IGNORE(res = cert->VerifySignatureL(cert->PublicKey().KeyData())); sl@0: if (res) sl@0: { sl@0: iCorruptOut->writeString(_L("!!!")); sl@0: iCorruptOut->writeNewLine(); sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(&input); sl@0: } sl@0: sl@0: delete key; sl@0: } sl@0: iCorruptOut->writeString(_L("r:")); sl@0: iCorruptOut->writeNum(err); sl@0: iCorruptOut->writeNewLine(); sl@0: CleanupStack::PopAndDestroy(2);// rand, cert sl@0: } sl@0: CleanupStack::PopAndDestroy(3);// sl@0: } sl@0: __UHEAP_MARKEND; sl@0: } sl@0: sl@0: // These tests are very slow and do not need to be performed on every sl@0: // certificate in the x509 test directory. Corrupt every 10th certificate. sl@0: void CCorruptionTest::PerformAction(TRequestStatus& aStatus) sl@0: { sl@0: TBuf<256> filename = (*iDirList)[nFileNumber].iName; sl@0: TInt error; sl@0: sl@0: if( (filename.CompareF(KResultsFile)!=0) && (nFileNumber%10==0) ) sl@0: { sl@0: iCorruptOut->writeString(_L("file:")); sl@0: iCorruptOut->writeString(filename); sl@0: iCorruptOut->writeNewLine(); sl@0: iConsole.Printf(_L("file:%S\n"), &filename); sl@0: sl@0: TRAP(error, RunCorruptionTestL(filename)); sl@0: if(error == KErrNoMemory) sl@0: User::Leave(error); sl@0: }; sl@0: sl@0: sl@0: if(++nFileNumber == iDirList->Count()) sl@0: { sl@0: iActionState = EPostrequisite; sl@0: }; sl@0: TRequestStatus* status = &aStatus; sl@0: User::RequestComplete(status, KErrNone); sl@0: } sl@0: sl@0: void CCorruptionTest::DoReportAction() sl@0: { sl@0: } sl@0: sl@0: void CCorruptionTest::DoCheckResult(TInt /*aError*/) sl@0: { sl@0: } sl@0: sl@0: HBufC8* CCorruptionTest::readCertLC(const TDesC& aFilename) sl@0: { sl@0: TFileName fullname; sl@0: fullname.Append(iPath); sl@0: fullname.Append(aFilename); sl@0: sl@0: RFile file; sl@0: User::LeaveIfError( file.Open(iFs, fullname, EFileRead) ); sl@0: sl@0: TInt size; sl@0: file.Size(size); sl@0: file.Close(); sl@0: sl@0: HBufC8* res = HBufC8::NewLC(size); sl@0: TPtr8 p(res->Des()); sl@0: p.SetLength(size); sl@0: sl@0: RFileReadStream stream; sl@0: User::LeaveIfError(stream.Open(iFs, fullname, EFileStream)); sl@0: stream.ReadL(p, size); sl@0: stream.Close(); sl@0: return res; sl@0: }