os/security/cryptoservices/certificateandkeymgmt/pkixcertbase/pkixcerts.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.
sl@0
     1
/*
sl@0
     2
* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0
     3
* All rights reserved.
sl@0
     4
* This component and the accompanying materials are made available
sl@0
     5
* under the terms of the License "Eclipse Public License v1.0"
sl@0
     6
* which accompanies this distribution, and is available
sl@0
     7
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0
     8
*
sl@0
     9
* Initial Contributors:
sl@0
    10
* Nokia Corporation - initial contribution.
sl@0
    11
*
sl@0
    12
* Contributors:
sl@0
    13
*
sl@0
    14
* Description: 
sl@0
    15
*
sl@0
    16
*/
sl@0
    17
sl@0
    18
sl@0
    19
#include "pkixcerts.h"
sl@0
    20
#include <ccertattributefilter.h>
sl@0
    21
#include <cctcertinfo.h>
sl@0
    22
sl@0
    23
// CPKIXCertSource
sl@0
    24
////////////////////
sl@0
    25
sl@0
    26
MPKIXCertSource::~MPKIXCertSource()
sl@0
    27
	{
sl@0
    28
	}
sl@0
    29
sl@0
    30
// This function returns ETrue iff the issuer altname in aSubjectCert matches the
sl@0
    31
// subject altname in aIssuerCert
sl@0
    32
TBool MPKIXCertSource::AltNameMatchL(const CX509Certificate& aSubjectCert, 
sl@0
    33
									 const CX509Certificate& aIssuerCert) const 
sl@0
    34
	{
sl@0
    35
	TBool res = EFalse;
sl@0
    36
	const CX509CertExtension* subjectExt = aSubjectCert.Extension(KIssuerAltName);
sl@0
    37
	const CX509CertExtension* issuerExt = aIssuerCert.Extension(KSubjectAltName);
sl@0
    38
	if ((subjectExt) && (issuerExt))
sl@0
    39
		{
sl@0
    40
		const CX509AltNameExt* issuerAltName = CX509AltNameExt::NewLC(subjectExt->Data());
sl@0
    41
		const CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(issuerExt->Data());
sl@0
    42
		if (subjectAltName->Match(*issuerAltName))
sl@0
    43
			{
sl@0
    44
			res = ETrue;
sl@0
    45
			}
sl@0
    46
		CleanupStack::PopAndDestroy(2);//subjectAltName, issuerAltName
sl@0
    47
		}
sl@0
    48
	return res;
sl@0
    49
	}
sl@0
    50
sl@0
    51
// CPKIXCertsFromStore
sl@0
    52
////////////////////////
sl@0
    53
sl@0
    54
CPKIXCertsFromStore* CPKIXCertsFromStore::NewL(MCertStore& aCertStore)
sl@0
    55
	{
sl@0
    56
	CPKIXCertsFromStore* self = CPKIXCertsFromStore::NewLC(aCertStore);
sl@0
    57
	CleanupStack::Pop(self);
sl@0
    58
	return self;
sl@0
    59
	}
sl@0
    60
sl@0
    61
CPKIXCertsFromStore* CPKIXCertsFromStore::NewLC(MCertStore& aCertStore)
sl@0
    62
	{
sl@0
    63
	CPKIXCertsFromStore* self = new(ELeave) CPKIXCertsFromStore(aCertStore);
sl@0
    64
	CleanupStack::PushL(self);
sl@0
    65
	self->ConstructL();
sl@0
    66
	return self;
sl@0
    67
	}
sl@0
    68
sl@0
    69
CPKIXCertsFromStore* CPKIXCertsFromStore::NewL(MCertStore& aCertStore, TUid aClient)
sl@0
    70
	{
sl@0
    71
	CPKIXCertsFromStore* self = CPKIXCertsFromStore::NewLC(aCertStore, aClient);
sl@0
    72
	CleanupStack::Pop(self);
sl@0
    73
	return self;
sl@0
    74
	}
sl@0
    75
sl@0
    76
CPKIXCertsFromStore* CPKIXCertsFromStore::NewLC(MCertStore& aCertStore, TUid aClient)
sl@0
    77
	{
sl@0
    78
	CPKIXCertsFromStore* self = new(ELeave) CPKIXCertsFromStore(aCertStore, aClient);
sl@0
    79
	CleanupStack::PushL(self);
sl@0
    80
	self->ConstructL(aClient);
sl@0
    81
	return self;
sl@0
    82
	}
sl@0
    83
sl@0
    84
void CPKIXCertsFromStore::Initialize(TRequestStatus& aStatus)
sl@0
    85
	{
sl@0
    86
	// In the case of a WIM, we don't have trust settings,
sl@0
    87
	// the WIM store will ignore the filter and return all certificates
sl@0
    88
	aStatus = KRequestPending;
sl@0
    89
	iOriginalRequestStatus = &aStatus;
sl@0
    90
	iState = EInitialize;
sl@0
    91
	iCertStore.List(iCertInfos, *iFilter, iStatus);
sl@0
    92
	SetActive();
sl@0
    93
	}
sl@0
    94
sl@0
    95
void CPKIXCertsFromStore::CandidatesL(const CX509Certificate& aSubject,
sl@0
    96
									 RPointerArray<CX509Certificate>& aCandidates, 
sl@0
    97
									 TRequestStatus& aStatus)
sl@0
    98
	{
sl@0
    99
	aStatus = KRequestPending;
sl@0
   100
	iOriginalRequestStatus = &aStatus;
sl@0
   101
sl@0
   102
	iRootName = &aSubject.IssuerName();
sl@0
   103
	iSubject = &aSubject;
sl@0
   104
	iCandidates = &aCandidates;
sl@0
   105
	iEntriesIndex = -1;
sl@0
   106
	
sl@0
   107
	iState = ECheckTrusted;
sl@0
   108
	TRequestStatus* status = &iStatus;
sl@0
   109
	User::RequestComplete(status, KErrNone);
sl@0
   110
	SetActive();
sl@0
   111
	}
sl@0
   112
sl@0
   113
void CPKIXCertsFromStore::CancelCandidates()
sl@0
   114
	{
sl@0
   115
	Cancel();
sl@0
   116
	}
sl@0
   117
sl@0
   118
void CPKIXCertsFromStore::Release()
sl@0
   119
	{
sl@0
   120
	delete this;
sl@0
   121
	}
sl@0
   122
sl@0
   123
CPKIXCertsFromStore::~CPKIXCertsFromStore()
sl@0
   124
	{
sl@0
   125
	Cancel();
sl@0
   126
sl@0
   127
	iCertInfos.Close();
sl@0
   128
sl@0
   129
	delete iFilter;
sl@0
   130
	
sl@0
   131
	delete iCertData;
sl@0
   132
	delete iCertPtr;
sl@0
   133
	}
sl@0
   134
sl@0
   135
//private functions
sl@0
   136
CPKIXCertsFromStore::CPKIXCertsFromStore(MCertStore& aCertStore)
sl@0
   137
	: CActive(EPriorityNormal), iCertStore(aCertStore)
sl@0
   138
	{
sl@0
   139
	CActiveScheduler::Add(this);
sl@0
   140
	}
sl@0
   141
sl@0
   142
CPKIXCertsFromStore::CPKIXCertsFromStore(MCertStore& aCertStore, TUid aClient)
sl@0
   143
: CActive(EPriorityNormal), iClient(aClient), iCertStore(aCertStore)
sl@0
   144
	{
sl@0
   145
	CActiveScheduler::Add(this);
sl@0
   146
	}
sl@0
   147
sl@0
   148
void CPKIXCertsFromStore::ConstructL()
sl@0
   149
	{
sl@0
   150
	iFilter = CCertAttributeFilter::NewL();
sl@0
   151
	iFilter->SetFormat(EX509Certificate);
sl@0
   152
	iFilter->SetOwnerType(ECACertificate);
sl@0
   153
	}
sl@0
   154
sl@0
   155
void CPKIXCertsFromStore::ConstructL(TUid aClient)
sl@0
   156
	{
sl@0
   157
	iFilter = CCertAttributeFilter::NewL();
sl@0
   158
	iFilter->SetUid(aClient);
sl@0
   159
	iFilter->SetFormat(EX509Certificate);
sl@0
   160
	iFilter->SetOwnerType(ECACertificate);
sl@0
   161
	}
sl@0
   162
sl@0
   163
void CPKIXCertsFromStore::RunL()
sl@0
   164
	{
sl@0
   165
	User::LeaveIfError(iStatus.Int());
sl@0
   166
sl@0
   167
	switch (iState)
sl@0
   168
		{
sl@0
   169
		case EInitialize:
sl@0
   170
			iState = EIdle;
sl@0
   171
			User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
sl@0
   172
			break;
sl@0
   173
sl@0
   174
		case ECheckTrusted:
sl@0
   175
			HandleECheckTrusted();
sl@0
   176
			break;
sl@0
   177
sl@0
   178
		case EGetCertificate:
sl@0
   179
			HandleEGetCertificateL();
sl@0
   180
			break;
sl@0
   181
sl@0
   182
		case EAddCandidate:
sl@0
   183
			HandleEAddCandidateL();
sl@0
   184
			break;
sl@0
   185
sl@0
   186
		case EEnd:
sl@0
   187
			iState = EIdle;
sl@0
   188
			User::RequestComplete(iOriginalRequestStatus, KErrNone);
sl@0
   189
			break;
sl@0
   190
sl@0
   191
		default:
sl@0
   192
			__ASSERT_ALWAYS(0, User::Panic(_L("CPKIXCertsFromStore"), 1));
sl@0
   193
			break;
sl@0
   194
			}
sl@0
   195
	}
sl@0
   196
sl@0
   197
TInt CPKIXCertsFromStore::RunError(TInt aError)
sl@0
   198
	{
sl@0
   199
	User::RequestComplete(iOriginalRequestStatus, aError);
sl@0
   200
	return KErrNone;
sl@0
   201
	}
sl@0
   202
sl@0
   203
void CPKIXCertsFromStore::DoCancel()
sl@0
   204
	{
sl@0
   205
	switch(iState)
sl@0
   206
		{
sl@0
   207
		case EInitialize:
sl@0
   208
			iCertStore.CancelList();
sl@0
   209
			break;
sl@0
   210
sl@0
   211
		case EGetCertificate:
sl@0
   212
			iCertStore.CancelTrusted();
sl@0
   213
			break;
sl@0
   214
sl@0
   215
		case EAddCandidate:
sl@0
   216
			iCertStore.CancelRetrieve();
sl@0
   217
			break;
sl@0
   218
sl@0
   219
		case ECheckTrusted:
sl@0
   220
		case EEnd:
sl@0
   221
			// nothing to do
sl@0
   222
			break;
sl@0
   223
sl@0
   224
		default:
sl@0
   225
			__ASSERT_ALWAYS(0, User::Panic(_L("CPKIXCertsFromStore"), 1));
sl@0
   226
			break;
sl@0
   227
		}
sl@0
   228
	
sl@0
   229
	User::RequestComplete(iOriginalRequestStatus, KErrCancel);
sl@0
   230
	iState = EIdle;
sl@0
   231
	}
sl@0
   232
sl@0
   233
void CPKIXCertsFromStore::HandleECheckTrusted()
sl@0
   234
	{// iEntriesIndex has been initialized to -1 by Candidates
sl@0
   235
	iEntriesIndex++;
sl@0
   236
	if (iEntriesIndex < iCertInfos.Count())
sl@0
   237
		{
sl@0
   238
		const CCTCertInfo* entry = iCertInfos[iEntriesIndex];
sl@0
   239
sl@0
   240
	//	Fix for DEF017139  "PKIXCert ignores trust"
sl@0
   241
	//	Check the certificate is trusted and discard it if not
sl@0
   242
		iCertStore.Trusted(*entry, iIsTrusted, iStatus);
sl@0
   243
		iState = EGetCertificate;
sl@0
   244
		}
sl@0
   245
	else
sl@0
   246
		{
sl@0
   247
		iState = EEnd;
sl@0
   248
		TRequestStatus* status = &iStatus;
sl@0
   249
		User::RequestComplete(status, KErrNone);
sl@0
   250
		}
sl@0
   251
	SetActive();
sl@0
   252
	}
sl@0
   253
sl@0
   254
void CPKIXCertsFromStore::HandleEGetCertificateL()
sl@0
   255
{
sl@0
   256
	if (iIsTrusted)
sl@0
   257
	{//	Fine to trust, go ahead
sl@0
   258
		const CCTCertInfo* entry = iCertInfos[iEntriesIndex];
sl@0
   259
		__ASSERT_DEBUG(!iCertData, User::Panic(_L("CPKIXCertsFromStore"), 1));
sl@0
   260
		iCertData = HBufC8::NewL(entry->Size());
sl@0
   261
		__ASSERT_DEBUG(!iCertPtr, User::Panic(_L("CPKIXCertsFromStore"), 1));
sl@0
   262
		iCertPtr = new(ELeave) TPtr8(iCertData->Des());
sl@0
   263
		iCertStore.Retrieve(*entry, *iCertPtr, iStatus);
sl@0
   264
		iState = EAddCandidate;
sl@0
   265
	}
sl@0
   266
	else
sl@0
   267
	{//	Not trusted, check next for trust
sl@0
   268
		iState = ECheckTrusted;
sl@0
   269
		TRequestStatus* status = &iStatus;
sl@0
   270
		User::RequestComplete(status, KErrNone);
sl@0
   271
	}
sl@0
   272
		
sl@0
   273
	SetActive();
sl@0
   274
}
sl@0
   275
sl@0
   276
sl@0
   277
TBool CPKIXCertsFromStore::IsDuplicateL(const CX509Certificate& aCandidate)
sl@0
   278
	{
sl@0
   279
	
sl@0
   280
	TInt candidatesCount = iCandidates->Count();
sl@0
   281
	for (TInt i = 0; i < candidatesCount; i++)
sl@0
   282
		{
sl@0
   283
		
sl@0
   284
		// Certificate is a duplicate iff
sl@0
   285
		// a) The public keys have the same hash, and
sl@0
   286
		// b) The serial numbers are identical
sl@0
   287
		
sl@0
   288
		CX509Certificate* cert = (*iCandidates)[i];
sl@0
   289
		if (cert->KeyIdentifierL() == aCandidate.KeyIdentifierL()
sl@0
   290
			&& cert->SerialNumber() == aCandidate.SerialNumber())
sl@0
   291
			{
sl@0
   292
			return ETrue;
sl@0
   293
			}
sl@0
   294
		
sl@0
   295
		}
sl@0
   296
	
sl@0
   297
	return EFalse;
sl@0
   298
	
sl@0
   299
	}
sl@0
   300
sl@0
   301
void CPKIXCertsFromStore::HandleEAddCandidateL()
sl@0
   302
	{
sl@0
   303
	CX509Certificate *candidate = CX509Certificate::NewLC(*iCertData);
sl@0
   304
	delete iCertData;
sl@0
   305
	iCertData = 0;
sl@0
   306
	delete iCertPtr;
sl@0
   307
	iCertPtr = 0;
sl@0
   308
sl@0
   309
	if (iRootName->Count() > 0)
sl@0
   310
		{
sl@0
   311
		if (candidate->SubjectName().ExactMatchL(*iRootName) && !IsDuplicateL(*candidate))
sl@0
   312
			{
sl@0
   313
			User::LeaveIfError(iCandidates->Append(candidate));
sl@0
   314
			CleanupStack::Pop();	// candidate
sl@0
   315
			}
sl@0
   316
		else
sl@0
   317
			{
sl@0
   318
			CleanupStack::PopAndDestroy();	// candidate
sl@0
   319
			}
sl@0
   320
		}
sl@0
   321
	else
sl@0
   322
		{
sl@0
   323
		const CX500DistinguishedName& candidateName = candidate->SubjectName();
sl@0
   324
		if ((candidateName.Count() == 0) && (AltNameMatchL(*iSubject, *candidate)))
sl@0
   325
			{
sl@0
   326
			User::LeaveIfError(iCandidates->Append(candidate));
sl@0
   327
			CleanupStack::Pop();	// candidate
sl@0
   328
			}
sl@0
   329
		else
sl@0
   330
			{
sl@0
   331
			CleanupStack::PopAndDestroy();	// candidate
sl@0
   332
			}
sl@0
   333
		}
sl@0
   334
sl@0
   335
	iState = ECheckTrusted;
sl@0
   336
	TRequestStatus* status = &iStatus;
sl@0
   337
	User::RequestComplete(status, KErrNone);
sl@0
   338
	SetActive();
sl@0
   339
	}
sl@0
   340
sl@0
   341
//CPKIXCertsFromClient
sl@0
   342
//public functions
sl@0
   343
CPKIXCertsFromClient* CPKIXCertsFromClient::NewL(const RPointerArray<CX509Certificate>& aCerts)
sl@0
   344
	{
sl@0
   345
	CPKIXCertsFromClient* self = new(ELeave) CPKIXCertsFromClient(aCerts);
sl@0
   346
	return self;
sl@0
   347
	}
sl@0
   348
sl@0
   349
CPKIXCertsFromClient* CPKIXCertsFromClient::NewLC(const RPointerArray<CX509Certificate>& aCerts)
sl@0
   350
	{
sl@0
   351
	CPKIXCertsFromClient* self = new(ELeave) CPKIXCertsFromClient(aCerts);
sl@0
   352
	CleanupStack::PushL(self);
sl@0
   353
	return self;
sl@0
   354
	}
sl@0
   355
sl@0
   356
void CPKIXCertsFromClient::Release()
sl@0
   357
	{
sl@0
   358
	delete this;
sl@0
   359
	}
sl@0
   360
sl@0
   361
CPKIXCertsFromClient::~CPKIXCertsFromClient()
sl@0
   362
	{
sl@0
   363
	}
sl@0
   364
sl@0
   365
void CPKIXCertsFromClient::CandidatesL(const CX509Certificate& aSubject,
sl@0
   366
									   RPointerArray<CX509Certificate>& aCandidates, 
sl@0
   367
									   TRequestStatus& aStatus)
sl@0
   368
	{
sl@0
   369
	// There is no need for this to be asynchronous but it is because the base class
sl@0
   370
	// wants this to be
sl@0
   371
sl@0
   372
	const CX500DistinguishedName& rootName = aSubject.IssuerName();
sl@0
   373
	TInt count = iCerts.Count();
sl@0
   374
	const CX509Certificate* candidate = NULL;
sl@0
   375
	if (rootName.Count() > 0)
sl@0
   376
		{
sl@0
   377
		for (TInt i = 0; i < count; i++)
sl@0
   378
			{
sl@0
   379
			candidate = iCerts[i];
sl@0
   380
			if (candidate->SubjectName().ExactMatchL(rootName))
sl@0
   381
				{
sl@0
   382
				CX509Certificate* cert = CX509Certificate::NewLC(*candidate);
sl@0
   383
				User::LeaveIfError(aCandidates.Append(cert));
sl@0
   384
				CleanupStack::Pop();
sl@0
   385
				}
sl@0
   386
			}
sl@0
   387
		}
sl@0
   388
	else
sl@0
   389
		{
sl@0
   390
		for (TInt i = 0; i < count; i++)
sl@0
   391
			{
sl@0
   392
			candidate = iCerts[i];
sl@0
   393
			const CX500DistinguishedName& candidateName = candidate->SubjectName();
sl@0
   394
			if ((candidateName.Count() ==0) && (AltNameMatchL(aSubject, *candidate)))
sl@0
   395
				{
sl@0
   396
				CX509Certificate* cert = CX509Certificate::NewLC(*candidate);
sl@0
   397
				User::LeaveIfError(aCandidates.Append(cert));
sl@0
   398
				CleanupStack::Pop();
sl@0
   399
				}
sl@0
   400
			}
sl@0
   401
		}
sl@0
   402
sl@0
   403
	TRequestStatus* status = &aStatus;
sl@0
   404
	User::RequestComplete(status, KErrNone);
sl@0
   405
	}
sl@0
   406
sl@0
   407
void CPKIXCertsFromClient::CancelCandidates()
sl@0
   408
	{
sl@0
   409
	// Nothing to do because the function completes immediately
sl@0
   410
	}
sl@0
   411
sl@0
   412
//private functions
sl@0
   413
CPKIXCertsFromClient::CPKIXCertsFromClient(const RPointerArray<CX509Certificate>& aCerts)
sl@0
   414
	:iCerts(aCerts)
sl@0
   415
	{
sl@0
   416
	}