1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/tx509/CorruptionTest.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,299 @@
1.4 +/*
1.5 +* Copyright (c) 1998-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 "CorruptionTest.h"
1.23 +#include "SyntaxTest.h"
1.24 +#include "wtlscert.h"
1.25 +#include "t_output.h"
1.26 +#include "t_input.h"
1.27 +#include <random.h>
1.28 +#include <asymmetric.h>
1.29 +#include <bigint.h>
1.30 +
1.31 +TInt CCorruptionTest::nInstances = 0;
1.32 +_LIT(KCorruptLogFile, "X509CorruptLog.txt");
1.33 +_LIT(KPathStart, "<path>");
1.34 +_LIT(KIterationsStart, "<iterations>");
1.35 +
1.36 +//////////////////////////////////////////////////////////////////////
1.37 +// Construction/Destruction
1.38 +//////////////////////////////////////////////////////////////////////
1.39 +
1.40 +CTestAction* CCorruptionTest::NewL(RFs& aFs, CConsoleBase& aConsole,
1.41 + Output& aOut, const TTestActionSpec& aTestActionSpec)
1.42 + {
1.43 + CTestAction* self = CCorruptionTest::NewLC(aFs, aConsole, aOut, aTestActionSpec);
1.44 + CleanupStack::Pop(self);
1.45 + return self;
1.46 + }
1.47 +
1.48 +CTestAction* CCorruptionTest::NewLC(RFs& aFs, CConsoleBase& aConsole,
1.49 + Output& aOut, const TTestActionSpec& aTestActionSpec)
1.50 + {
1.51 + CCorruptionTest* self = new(ELeave) CCorruptionTest(aFs, aConsole, aOut);
1.52 + CleanupStack::PushL(self);
1.53 + self->ConstructL(aTestActionSpec);
1.54 + return self;
1.55 + }
1.56 +
1.57 +CCorruptionTest::CCorruptionTest(RFs& aFs,
1.58 + CConsoleBase& aConsole,
1.59 + Output& aOut)
1.60 +: CTestAction(aConsole, aOut), iFs(aFs)
1.61 + {
1.62 + nFileNumber = 0;
1.63 + }
1.64 +
1.65 +CCorruptionTest::~CCorruptionTest(void)
1.66 + {
1.67 + delete iDirList;
1.68 + delete iWriter;
1.69 + iLogFile.Close();
1.70 + delete iNullOut;
1.71 + delete iCorruptOut;
1.72 + };
1.73 +
1.74 +void CCorruptionTest::ConstructL(const TTestActionSpec& aTestActionSpec)
1.75 + {
1.76 + CTestAction::ConstructL(aTestActionSpec);
1.77 +
1.78 + if(nInstances==0)
1.79 + {
1.80 + HBufC* body = HBufC::NewLC(aTestActionSpec.iActionBody.Length());
1.81 + TInt pos=0;
1.82 +
1.83 + nInstances++;
1.84 + iNullOut = new(ELeave) NullOutput;
1.85 + body->Des().Copy(aTestActionSpec.iActionBody);
1.86 + TPtrC chainBuf = Input::ParseElement(*body, KPathStart, pos);
1.87 + iPath.Copy(chainBuf);
1.88 + TPtrC itertaionBuf = Input::ParseElement(*body, KIterationsStart, pos);
1.89 + TLex itLex(itertaionBuf);
1.90 +
1.91 + itLex.Val(iIterations);
1.92 + CleanupStack::PopAndDestroy(); // body
1.93 + User::LeaveIfError(iLogFile.Replace(iFs,KCorruptLogFile,EFileWrite));
1.94 + iCorruptOut = new(ELeave) FileOutput(iLogFile);
1.95 + iWriter = new(ELeave) CertWriter(iCorruptOut);
1.96 + }
1.97 + else
1.98 + {
1.99 + SetScriptError(ESyntax, _L("Only one corruption test can be run in each script"));
1.100 + iFinished = ETrue;
1.101 + }
1.102 + }
1.103 +
1.104 +
1.105 +void CCorruptionTest::DoPerformPrerequisite(TRequestStatus& aStatus)
1.106 + {
1.107 + HBufC *searchPath = HBufC::NewLC(iPath.Size() + 1);
1.108 + TPtr searchPathPtr(searchPath->Des());
1.109 + searchPathPtr.Copy(iPath);
1.110 + searchPathPtr.Append(_L("*"));
1.111 + TInt err = iFs.GetDir(searchPathPtr, KEntryAttMaskSupported, ESortByName, iDirList);
1.112 + if (err != KErrNone)
1.113 + {
1.114 + iConsole.Printf(_L("Error getting directory "));
1.115 + iConsole.Printf(searchPathPtr);
1.116 + iConsole.Printf(_L("\n"));
1.117 + iOut.writeString(_L("Error getting directory "));
1.118 + iOut.writeString(searchPathPtr);
1.119 + iOut.writeNewLine();
1.120 + iFinished = ETrue;
1.121 + TRequestStatus* status = &aStatus;
1.122 + User::RequestComplete(status, KErrNone);
1.123 + SetScriptError(EFileNotFound, searchPathPtr);
1.124 + }
1.125 + else
1.126 + {
1.127 + iConsole.Printf(_L("Please view "));
1.128 + iConsole.Printf(KCorruptLogFile);
1.129 + iConsole.Printf(_L(" for results\n"));
1.130 + iOut.writeString(_L("Please view "));
1.131 + iOut.writeString(KCorruptLogFile);
1.132 + iOut.writeString(_L(" for results"));
1.133 + iOut.writeNewLine();
1.134 + iActionState = EAction;
1.135 + TRequestStatus* status = &aStatus;
1.136 + User::RequestComplete(status, KErrNone);
1.137 + iResult = ETrue;
1.138 + }
1.139 + CleanupStack::PopAndDestroy();
1.140 + }
1.141 +
1.142 +void CCorruptionTest::DoPerformPostrequisite(TRequestStatus& aStatus)
1.143 + {
1.144 + TRequestStatus* status = &aStatus;
1.145 + iFinished = ETrue;
1.146 + User::RequestComplete(status, KErrNone);
1.147 + }
1.148 +
1.149 +void CCorruptionTest::RunCorruptionTestL(const TDesC &aFilename)
1.150 + {
1.151 + __UHEAP_MARK;
1.152 + for (TInt i = 0; i < iIterations; i++)
1.153 + {
1.154 + HBufC8* buf = Input::ReadFileLC(aFilename, iPath, iFs);
1.155 + TPtr8 pBuf = buf->Des();
1.156 + TInt len = pBuf.Size();
1.157 + TInt pos = 0;
1.158 + //list of positions altered
1.159 + HBufC* posOctsBuf = HBufC::NewLC(70);
1.160 + TPtr pPosOctsBuf = posOctsBuf->Des();
1.161 + pPosOctsBuf.SetLength(0);
1.162 + pPosOctsBuf.Append(_L("p:"));
1.163 + //list of octets altered
1.164 + HBufC8* octsBuf = HBufC8::NewLC(40);
1.165 + TPtr8 pOctsBuf = octsBuf->Des();
1.166 + pOctsBuf.SetLength(0);
1.167 +
1.168 + for (TInt j = 0; j < 10; j++)
1.169 + {
1.170 + //randomness
1.171 + HBufC8* rand = HBufC8::NewLC(5);
1.172 + TPtr8 pRand = rand->Des();
1.173 + pRand.SetLength(5);
1.174 + TRandom::RandomL(pRand);
1.175 + TUint num = 0;
1.176 + for (TInt k = 0; k < 4 ; k++)
1.177 + {
1.178 + num<<=8;
1.179 + num+=pRand[k];
1.180 + }
1.181 + pos = num % len;
1.182 + TUint8 newOctet = pRand[4];
1.183 + //update output lines
1.184 + pPosOctsBuf.AppendNum(pos);
1.185 + pPosOctsBuf.Append(_L(" "));
1.186 + pOctsBuf.Append(pBuf.Mid(pos, 1));
1.187 + TPtrC8 pNewOct = pRand.Right(1);
1.188 + pOctsBuf.Append(pNewOct);
1.189 + //switch the selected octet
1.190 + pBuf[pos] = newOctet;
1.191 + //file out
1.192 + iCorruptOut->writeString(pPosOctsBuf);
1.193 + iCorruptOut->writeNewLine();
1.194 + iCorruptOut->writeString(_L("o:"));
1.195 + iCorruptOut->writeOctetString(pOctsBuf);
1.196 + iCorruptOut->writeNewLine();
1.197 + //try to make corrupt cert
1.198 + CX509Certificate* cert = NULL;
1.199 + TRAPD(err, cert = CX509Certificate::NewL(pBuf));
1.200 + CleanupStack::PushL(cert);
1.201 + if (err == KErrNone)
1.202 + {
1.203 + TBool res = EFalse;;
1.204 + // Don't bother attempting to verify if public key modulus is even
1.205 + // since CMontgomery methods will fail...
1.206 + TKeyFactory* theKeyFactory = new (ELeave) TX509KeyFactory();
1.207 + CleanupStack::PushL(theKeyFactory);
1.208 + CRSAPublicKey* key = theKeyFactory->RSAPublicKeyL(cert->PublicKey().KeyData());
1.209 + CleanupStack::Pop(theKeyFactory);
1.210 + delete theKeyFactory;
1.211 +
1.212 + const TInteger& theN = key->N();
1.213 + if (theN.IsOdd())
1.214 + {
1.215 + RInteger input = RInteger::NewL(cert->Signature());
1.216 + CleanupStack::PushL(input);
1.217 + // Check that the signature is not out of bounds for the key
1.218 + // Otherwise the crypto library will panic (descriptor out of bounds)
1.219 + if ( (input < theN) && (input > 0) )
1.220 + {
1.221 + TRAP_IGNORE(res = cert->VerifySignatureL(cert->PublicKey().KeyData()));
1.222 + if (res)
1.223 + {
1.224 + iCorruptOut->writeString(_L("!!!"));
1.225 + iCorruptOut->writeNewLine();
1.226 + }
1.227 + }
1.228 +
1.229 + CleanupStack::PopAndDestroy(&input);
1.230 + }
1.231 +
1.232 + delete key;
1.233 + }
1.234 + iCorruptOut->writeString(_L("r:"));
1.235 + iCorruptOut->writeNum(err);
1.236 + iCorruptOut->writeNewLine();
1.237 + CleanupStack::PopAndDestroy(2);// rand, cert
1.238 + }
1.239 + CleanupStack::PopAndDestroy(3);//
1.240 + }
1.241 + __UHEAP_MARKEND;
1.242 + }
1.243 +
1.244 +// These tests are very slow and do not need to be performed on every
1.245 +// certificate in the x509 test directory. Corrupt every 10th certificate.
1.246 +void CCorruptionTest::PerformAction(TRequestStatus& aStatus)
1.247 + {
1.248 + TBuf<256> filename = (*iDirList)[nFileNumber].iName;
1.249 + TInt error;
1.250 +
1.251 + if( (filename.CompareF(KResultsFile)!=0) && (nFileNumber%10==0) )
1.252 + {
1.253 + iCorruptOut->writeString(_L("file:"));
1.254 + iCorruptOut->writeString(filename);
1.255 + iCorruptOut->writeNewLine();
1.256 + iConsole.Printf(_L("file:%S\n"), &filename);
1.257 +
1.258 + TRAP(error, RunCorruptionTestL(filename));
1.259 + if(error == KErrNoMemory)
1.260 + User::Leave(error);
1.261 + };
1.262 +
1.263 +
1.264 + if(++nFileNumber == iDirList->Count())
1.265 + {
1.266 + iActionState = EPostrequisite;
1.267 + };
1.268 + TRequestStatus* status = &aStatus;
1.269 + User::RequestComplete(status, KErrNone);
1.270 + }
1.271 +
1.272 +void CCorruptionTest::DoReportAction()
1.273 + {
1.274 + }
1.275 +
1.276 +void CCorruptionTest::DoCheckResult(TInt /*aError*/)
1.277 + {
1.278 + }
1.279 +
1.280 +HBufC8* CCorruptionTest::readCertLC(const TDesC& aFilename)
1.281 + {
1.282 + TFileName fullname;
1.283 + fullname.Append(iPath);
1.284 + fullname.Append(aFilename);
1.285 +
1.286 + RFile file;
1.287 + User::LeaveIfError( file.Open(iFs, fullname, EFileRead) );
1.288 +
1.289 + TInt size;
1.290 + file.Size(size);
1.291 + file.Close();
1.292 +
1.293 + HBufC8* res = HBufC8::NewLC(size);
1.294 + TPtr8 p(res->Des());
1.295 + p.SetLength(size);
1.296 +
1.297 + RFileReadStream stream;
1.298 + User::LeaveIfError(stream.Open(iFs, fullname, EFileStream));
1.299 + stream.ReadL(p, size);
1.300 + stream.Close();
1.301 + return res;
1.302 + }