1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoservices/certificateandkeymgmt/tx509/extensiontest.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,438 @@
1.4 +/*
1.5 +* Copyright (c) 2005-2010 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 "x509constraintext.h"
1.23 +#include "extensiontest.h"
1.24 +#include "t_input.h"
1.25 +
1.26 +_LIT(KFileNameStart, "<filename>");
1.27 +_LIT(KExpectedDeviceIdList, "<device_id_list>");
1.28 +_LIT(KExpectedDevice, "<device_id>");
1.29 +_LIT(KExpectedSidList, "<sid_list>");
1.30 +_LIT(KExpectedSid, "<sid>");
1.31 +_LIT(KExpectedVidList, "<vid_list>");
1.32 +_LIT(KExpectedVid, "<vid>");
1.33 +_LIT(KExpectedCapabilities, "<capabilities>");
1.34 +_LIT(KCorrupt, "<corrupt>");
1.35 +_LIT(KMatch, "<match>");
1.36 +
1.37 +CTestAction* CExtensionTest::NewL(RFs& aFs, CConsoleBase& aConsole,
1.38 + Output& aOut, const TTestActionSpec& aTestActionSpec)
1.39 + {
1.40 + CTestAction* self = CExtensionTest::NewLC(aFs, aConsole, aOut, aTestActionSpec);
1.41 + CleanupStack::Pop(self);
1.42 + return self;
1.43 + }
1.44 +
1.45 +CTestAction* CExtensionTest::NewLC(RFs& aFs, CConsoleBase& aConsole,
1.46 + Output& aOut, const TTestActionSpec& aTestActionSpec)
1.47 + {
1.48 + CExtensionTest* self = new(ELeave) CExtensionTest(aFs, aConsole, aOut);
1.49 + CleanupStack::PushL(self);
1.50 + self->ConstructL(aTestActionSpec);
1.51 + return self;
1.52 + }
1.53 +
1.54 +CExtensionTest::CExtensionTest(RFs& aFs, CConsoleBase& aConsole, Output& aOut)
1.55 + : CTestAction(aConsole, aOut),
1.56 + iFs(aFs)
1.57 + {
1.58 + }
1.59 +
1.60 +CExtensionTest::~CExtensionTest()
1.61 + {
1.62 + iExpectedDeviceIdList.ResetAndDestroy();
1.63 + iExpectedDeviceIdList.Close();
1.64 + iExpectedSidList.Close();
1.65 + iExpectedVidList.Close();
1.66 + }
1.67 +
1.68 +void CExtensionTest::ConstructL(const TTestActionSpec& aTestActionSpec)
1.69 + {
1.70 + CTestAction::ConstructL(aTestActionSpec);
1.71 + TInt startPos = 0;
1.72 + TInt err = 0;
1.73 +
1.74 + HBufC* aBody = HBufC::NewLC(aTestActionSpec.iActionBody.Length());
1.75 + aBody->Des().Copy(aTestActionSpec.iActionBody);
1.76 +
1.77 + // Filename of the certificate file
1.78 + TPtrC fileNameStart = Input::ParseElement(*aBody, KFileNameStart);
1.79 + iCertFileName.Copy(fileNameStart);
1.80 +
1.81 + // Whether we expect at least on of the extensions to be corrupt
1.82 + TPtrC corruptStart = Input::ParseElement(*aBody, KCorrupt);
1.83 + if (corruptStart.CompareF(_L("True")) == 0)
1.84 + {
1.85 + iExpectedCorrupt = ETrue;
1.86 + }
1.87 +
1.88 + // We expect the certificate to match the constraints
1.89 + TPtrC matchStart = Input::ParseElement(*aBody, KMatch);
1.90 + if (matchStart.CompareF(_L("True")) == 0)
1.91 + {
1.92 + iExpectedMatch = ETrue;
1.93 + }
1.94 +
1.95 + // Extract the lists of constraints that are expected to be present
1.96 + startPos = 0;
1.97 + TPtrC deviceListStart = Input::ParseElement(*aBody, KExpectedDeviceIdList, startPos, err);
1.98 + if (err >= 0)
1.99 + {
1.100 + BuildStringListL(iExpectedDeviceIdList, deviceListStart, KExpectedDevice);
1.101 + iDeviceIdsPresent = ETrue;
1.102 + }
1.103 +
1.104 + startPos = 0;
1.105 + TPtrC sidListStart = Input::ParseElement(*aBody, KExpectedSidList, startPos, err);
1.106 + if (err >= 0)
1.107 + {
1.108 + BuildIntList(iExpectedSidList, sidListStart, KExpectedSid);
1.109 + iSidsPresent = ETrue;
1.110 + }
1.111 +
1.112 + startPos = 0;
1.113 + TPtrC vidListStart = Input::ParseElement(*aBody, KExpectedVidList, startPos, err);
1.114 + if (err >= 0)
1.115 + {
1.116 + BuildIntList(iExpectedVidList, vidListStart, KExpectedVid);
1.117 + iVidsPresent = ETrue;
1.118 + }
1.119 +
1.120 + startPos = 0;
1.121 + TPtrC capabilities = Input::ParseElement(*aBody, KExpectedCapabilities, startPos, err);
1.122 + if (err >= 0)
1.123 + {
1.124 + BuildCapabilitySet(iExpectedCapabilities, capabilities);
1.125 + iCapabilitiesPresent = ETrue;
1.126 + }
1.127 +
1.128 + CleanupStack::PopAndDestroy(aBody);
1.129 + }
1.130 +
1.131 +void CExtensionTest::BuildStringListL(RPointerArray<HBufC>& aStrings, const TDesC& aBuf, const TDesC& aTag)
1.132 + {
1.133 + TInt pos = 0;
1.134 + TInt err = 0;
1.135 + do
1.136 + {
1.137 + // Find next value for the specified tag and add it to the string array
1.138 + // if it exists.
1.139 + TPtrC str = Input::ParseElement(aBuf, aTag, pos, err);
1.140 + if (err >= 0)
1.141 + {
1.142 + HBufC* string = str.AllocLC();
1.143 + aStrings.AppendL(string);
1.144 + CleanupStack::Pop(string);
1.145 + }
1.146 + }
1.147 + while (err >= 0);
1.148 + }
1.149 +
1.150 +void CExtensionTest::BuildIntList(RArray<TInt>& aInts, const TDesC& aBuf, const TDesC& aTag)
1.151 + {
1.152 + TInt pos = 0;
1.153 + TInt err = 0;
1.154 + do
1.155 + {
1.156 + // Attempt to convert the contents of val to an int and store in
1.157 + // the aInts array if it is a valid integer.
1.158 + TInt n = Input::ParseIntElement(aBuf, aTag, pos, err);
1.159 + if (err >= 0)
1.160 + {
1.161 + // This append should not fail as the parsing went fine.
1.162 + // So, ignoring the leave just to satisfy non leaving method convention.
1.163 + TRAP_IGNORE(aInts.AppendL(n));
1.164 + }
1.165 + }
1.166 + while (err >= 0);
1.167 + }
1.168 +
1.169 +void CExtensionTest::BuildCapabilitySet(TCapabilitySet& aCapabilitySet, const TDesC& aBuf)
1.170 + {
1.171 + aCapabilitySet.SetEmpty();
1.172 + TUint length = aBuf.Length();
1.173 + for (TUint i = 0; i < length && i < ECapability_Limit; i++)
1.174 + {
1.175 + if (aBuf[i] == '1')
1.176 + {
1.177 + aCapabilitySet.AddCapability(static_cast<TCapability>(i));
1.178 + }
1.179 + }
1.180 + }
1.181 +
1.182 +void CExtensionTest::PerformAction(TRequestStatus& aStatus)
1.183 + {
1.184 + HBufC8* buf = NULL;
1.185 + TInt err = KErrNone;
1.186 +
1.187 + TRAP(err, buf = Input::ReadFileL(iCertFileName, iFs));
1.188 + if (err == KErrNotFound)
1.189 + {
1.190 + iResult = EFalse;
1.191 + iFinished = ETrue;
1.192 + SetScriptError(EFileNotFound, iCertFileName);
1.193 + TRequestStatus* status = &aStatus;
1.194 + iActionState = EPostrequisite;
1.195 + User::RequestComplete(status, KErrNone);
1.196 + return;
1.197 + }
1.198 + else if (err != KErrNone)
1.199 + {
1.200 + User::Leave(err);
1.201 + }
1.202 +
1.203 + CleanupStack::PushL(buf);
1.204 + CX509Certificate* cert = CX509Certificate::NewLC(buf->Des());
1.205 +
1.206 + Print(_L("Checking certificate extensions in file "));
1.207 + PrintLine(iCertFileName);
1.208 +
1.209 + TBool match = EFalse;
1.210 + TBool corrupt = EFalse;
1.211 + CheckExtensionsL(*cert, match, corrupt);
1.212 + if (corrupt)
1.213 + {
1.214 + iResult = iExpectedCorrupt;
1.215 + if (!iResult)
1.216 + {
1.217 + Print(_L("Found unexpected corrupt extension."));
1.218 + }
1.219 + }
1.220 + else
1.221 + {
1.222 + // no error. test whether the certificate matched the
1.223 + // test script.
1.224 + iResult = (match == iExpectedMatch);
1.225 + }
1.226 + CleanupStack::PopAndDestroy(2, buf); // cert, buf
1.227 +
1.228 + TRequestStatus* status = &aStatus;
1.229 + iActionState = EPostrequisite;
1.230 + User::RequestComplete(status, KErrNone);
1.231 + }
1.232 +
1.233 +void CExtensionTest::CheckExtensionsL(const CX509Certificate& cert,
1.234 + TBool& match, TBool& corrupt)
1.235 + {
1.236 + TInt err = KErrNone;
1.237 +
1.238 + match = ETrue;
1.239 + corrupt = EFalse;
1.240 +
1.241 + TRAP(err, match &= CheckDeviceIdListL(cert));
1.242 + if (err == KErrArgument)
1.243 + {
1.244 + PrintLine(_L("The device id constraint is corrupt."));
1.245 + corrupt = ETrue;
1.246 + }
1.247 + else if (err != KErrNone)
1.248 + {
1.249 + User::Leave(err);
1.250 + }
1.251 +
1.252 + TRAP(err, match &= CheckSidListL(cert));
1.253 + if (err == KErrArgument)
1.254 + {
1.255 + PrintLine(_L("The secure id constraint is corrupt."));
1.256 + corrupt = ETrue;
1.257 + }
1.258 + else if (err != KErrNone)
1.259 + {
1.260 + User::Leave(err);
1.261 + }
1.262 +
1.263 + TRAP(err, match &= CheckVidListL(cert));
1.264 + if (err == KErrArgument)
1.265 + {
1.266 + PrintLine(_L("The vendor id constraint is corrupt."));
1.267 + corrupt = ETrue;
1.268 + }
1.269 + else if (err != KErrNone)
1.270 + {
1.271 + User::Leave(err);
1.272 + }
1.273 +
1.274 + TRAP(err, match &= CheckCapabilitiesL(cert));
1.275 + if (err == KErrArgument)
1.276 + {
1.277 + PrintLine(_L("The capabilities constraint is corrupt."));
1.278 + corrupt = ETrue;
1.279 + }
1.280 + else if (err != KErrNone)
1.281 + {
1.282 + User::Leave(err);
1.283 + }
1.284 + }
1.285 +
1.286 +TBool CExtensionTest::CheckDeviceIdListL(const CX509Certificate& cert)
1.287 + {
1.288 + TBool match = ETrue;
1.289 + const CX509CertExtension* ext = cert.Extension(KDeviceIdListConstraint);
1.290 + if (ext)
1.291 + {
1.292 + // use NewL because this covers NewLC as well
1.293 + CX509Utf8StringListExt* stringListExt = CX509Utf8StringListExt::NewL(ext->Data());
1.294 + CleanupStack::PushL(stringListExt);
1.295 + if (! IsEqual(stringListExt->StringArray(), iExpectedDeviceIdList))
1.296 + {
1.297 + PrintLine(_L("Device Id list is different."));
1.298 + match = EFalse;
1.299 + }
1.300 + CleanupStack::PopAndDestroy(stringListExt);
1.301 + }
1.302 + else if (iDeviceIdsPresent)
1.303 + {
1.304 + PrintLine(_L("Device Id constraint is missing."));
1.305 + match = EFalse;
1.306 + }
1.307 + return match;
1.308 + }
1.309 +
1.310 +TBool CExtensionTest::CheckSidListL(const CX509Certificate& cert)
1.311 + {
1.312 + const CX509CertExtension* ext = cert.Extension(KSidListConstraint);
1.313 + TBool match = ETrue;
1.314 + if (ext)
1.315 + {
1.316 + // use NewL because this covers NewLC as well
1.317 + CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data());
1.318 + CleanupStack::PushL(intListExt);
1.319 + if (! IsEqual(intListExt->IntArray(), iExpectedSidList))
1.320 + {
1.321 + PrintLine(_L("SID list is different"));
1.322 + match = EFalse;
1.323 + }
1.324 + CleanupStack::PopAndDestroy(intListExt);
1.325 + }
1.326 + else if (iSidsPresent)
1.327 + {
1.328 + PrintLine(_L("SID constraint is missing."));
1.329 + match = EFalse;
1.330 + }
1.331 + return match;
1.332 + }
1.333 +
1.334 +TBool CExtensionTest::CheckVidListL(const CX509Certificate& cert)
1.335 + {
1.336 + const CX509CertExtension* ext = cert.Extension(KVidListConstraint);
1.337 + TBool match = ETrue;
1.338 + if (ext)
1.339 + {
1.340 + // use NewL because this covers NewLC as well
1.341 + CX509IntListExt* intListExt = CX509IntListExt::NewL(ext->Data());
1.342 + CleanupStack::PushL(intListExt);
1.343 +
1.344 + if (! IsEqual(intListExt->IntArray(), iExpectedVidList))
1.345 + {
1.346 + PrintLine(_L("VID list is different"));
1.347 + match = EFalse;
1.348 + }
1.349 + CleanupStack::PopAndDestroy(intListExt);
1.350 + }
1.351 + else if (iVidsPresent)
1.352 + {
1.353 + PrintLine(_L("VID constraint is missing."));
1.354 + match = EFalse;
1.355 + }
1.356 + return match;
1.357 + }
1.358 +
1.359 +TBool CExtensionTest::CheckCapabilitiesL(const CX509Certificate& cert)
1.360 + {
1.361 + const CX509CertExtension* ext = cert.Extension(KCapabilitiesConstraint);
1.362 + TBool match = ETrue;
1.363 + if (ext)
1.364 + {
1.365 + // use NewL because this covers NewLC as well
1.366 + CX509CapabilitySetExt* capabilitySetExt = CX509CapabilitySetExt::NewL(ext->Data());
1.367 + CleanupStack::PushL(capabilitySetExt);
1.368 +
1.369 + const TCapabilitySet& capabilitySet = capabilitySetExt->CapabilitySet();
1.370 +
1.371 + if (! (capabilitySet.HasCapabilities(iExpectedCapabilities)
1.372 + && iExpectedCapabilities.HasCapabilities(capabilitySet)))
1.373 + {
1.374 + PrintLine(_L("Capability constraints are different."));
1.375 + match = EFalse;
1.376 + }
1.377 + CleanupStack::PopAndDestroy(capabilitySetExt);
1.378 + }
1.379 + else if (iCapabilitiesPresent)
1.380 + {
1.381 + PrintLine(_L("Capability constraint is missing."));
1.382 + match = EFalse;
1.383 + }
1.384 + return match;
1.385 + }
1.386 +
1.387 +TBool CExtensionTest::IsEqual(const RArray<TInt>& aArray1, const RArray<TInt>& aArray2)
1.388 + {
1.389 + if (aArray1.Count() == aArray2.Count())
1.390 + {
1.391 + TInt count = aArray1.Count();
1.392 + for (TInt i = 0; i < count; i++)
1.393 + {
1.394 + if (aArray1[i] != aArray2[i])
1.395 + {
1.396 + return EFalse;
1.397 + }
1.398 + }
1.399 + return ETrue;
1.400 + }
1.401 + return EFalse;
1.402 + }
1.403 +
1.404 +TBool CExtensionTest::IsEqual(const RPointerArray<HBufC>& aArray1, const RPointerArray<HBufC>& aArray2)
1.405 + {
1.406 + if (aArray1.Count() == aArray2.Count())
1.407 + {
1.408 + TInt count = aArray1.Count();
1.409 + for (TInt i = 0; i < count; i++)
1.410 + {
1.411 + if (aArray1[i]->Compare(*aArray2[i]) != 0)
1.412 + {
1.413 + return EFalse;
1.414 + }
1.415 + }
1.416 + return ETrue;
1.417 + }
1.418 + return EFalse;
1.419 + }
1.420 +
1.421 +void CExtensionTest::DoReportAction()
1.422 + {
1.423 + }
1.424 +
1.425 +void CExtensionTest::DoCheckResult(TInt /*aError*/)
1.426 + {
1.427 + }
1.428 +
1.429 +void CExtensionTest::Print(const TDesC& aText)
1.430 + {
1.431 + iConsole.Printf(aText);
1.432 + iOut.writeString(aText);
1.433 + }
1.434 +void CExtensionTest::PrintLine(const TDesC& aText)
1.435 + {
1.436 + iConsole.Printf(aText);
1.437 + iConsole.Printf(_L("\n"));
1.438 +
1.439 + iOut.writeString(aText);
1.440 + iOut.writeNewLine();
1.441 + }