First public contribution.
2 * Copyright (c) 2005-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
20 #include "tcertutils.h"
22 #include <certificateapps.h>
24 #include <ccertattributefilter.h>
25 #include <cctcertinfo.h>
26 #include <mctwritablecertstore.h>
29 EXPORT_C CCertUtils* CCertUtils::NewL(RFs& aFs)
31 CCertUtils* self = CCertUtils::NewLC(aFs);
32 CleanupStack::Pop(self);
36 EXPORT_C CCertUtils* CCertUtils::NewLC(RFs& aFs)
38 CCertUtils* self = new(ELeave) CCertUtils(aFs);
39 CleanupStack::PushL(self);
44 CCertUtils::CCertUtils(RFs& aFs)
45 : CActive(EPriorityNormal), iFs(aFs)
47 CActiveScheduler::Add(this);
50 EXPORT_C CCertUtils::~CCertUtils()
55 delete iCreatedUnifiedCertStore;
59 delete iSecondCertUtils;
64 iCACertStoreEntries.Close(); // The entries are owned by us
65 iUserCertStoreEntries.Close(); // The entries are owned by us
70 This function handles all the asynchronous calls. There is at least
71 one state for each of the functions of CCertUtils that requires
74 void CCertUtils::RunL()
76 if (iStatus != KErrNone)
78 User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
84 // Used for AddCACerts
91 TRAPD(err, HandleEAddCACertL());
94 iDiagnosticState = EAddCert;
95 User::RequestComplete(iOriginalRequestStatus, err);
98 case EAddCACertGetCAEntry:
99 HandleEAddCACertGetCAEntry();
101 case EAddCACertSetApplications:
102 HandleEAddCACertSetApplicationsL();
104 case EAddCACertSetTrust:
105 HandleEAddCACertSetTrust();
107 case EAddCACertFinished:
108 HandleEAddCACertFinishedL();
109 delete iCreatedUnifiedCertStore;
110 iCreatedUnifiedCertStore = 0;
113 // Used for RemoveCerts
114 case ERemoveCertsGetCACerts:
115 HandleERemoveCertsGetCACerts();
117 case ERemoveCertsCACertsRetrieved:
118 HandleERemoveCertsCACertsRetrieved();
120 case ERemoveCertsRemoveCACerts:
121 HandleERemoveCertsRemoveCACerts();
123 case ERemoveCertsGetUserCerts:
124 HandleERemoveCertsGetUserCerts();
126 case ERemoveCertsUserCertsRetrieved:
127 HandleERemoveCertsUserCertsRetrieved();
129 case ERemoveCertsRemoveUserCerts:
130 HandleERemoveCertsRemoveUserCerts();
132 case ERemoveCertsFinished:
133 HandleERemoveCertsFinished();
134 delete iCreatedUnifiedCertStore;
135 iCreatedUnifiedCertStore = 0;
143 TInt CCertUtils::RunError(TInt aError)
145 User::RequestComplete(iOriginalRequestStatus, aError);
149 void CCertUtils::DoCancel()
151 if (iSecondCertUtils)
152 iSecondCertUtils->Cancel();
154 if (iUnifiedCertStore)
156 iUnifiedCertStore->Cancel();
157 if (iUnifiedCertStore->WritableCertStoreCount() != 0)
159 MCTWritableCertStore *store;
160 store = &iUnifiedCertStore->WritableCertStore(0);
161 store->CancelRemove();
162 store->CancelSetApplicability();
170 EXPORT_C CCertificate* CCertUtils::CertFromFileLC(const TDesC& aFilename,
171 const TDesC& aPathname,
173 TCertificateFormat aFormat)
176 fullname.Append(aPathname);
177 fullname.Append(aFilename);
178 HBufC8* certBuf = Input::ReadFileLC(fullname, aFs);
179 CCertificate* cert = 0;
180 if (aFormat == EX509Certificate)
182 cert = CX509Certificate::NewLC(*certBuf);
184 else if (aFormat == EWTLSCertificate)
186 cert = CWTLSCertificate::NewLC(*certBuf);
188 CleanupStack::Pop();//cert
189 CleanupStack::PopAndDestroy();//buf
190 CleanupStack::PushL(cert);
194 EXPORT_C CCertificate* CCertUtils::CertFromFileL(const TDesC& aFilename,
195 const TDesC& aPathname,
197 TCertificateFormat aFormat)
199 CCertificate* cert = CertFromFileLC(aFilename, aPathname, aFs, aFormat);
204 EXPORT_C void CCertUtils::AddCertL(const TDesC& aLabel,
205 TCertificateFormat aFormat,
206 TCertificateOwnerType aCertificateOwnerType,
208 const TDesC& aCertificatePath,
209 const TDesC& aCertificateFileName,
210 TRequestStatus& aStatus)
212 iOriginalRequestStatus = &aStatus;
213 aStatus = KRequestPending;
215 // We set up the member variable as required for this function
216 iCertificateFileName = &aCertificateFileName;
219 iTrustedUsage = aTrustedUsage;
220 iPath = &aCertificatePath;
221 iCertificateOwnerType = aCertificateOwnerType;
223 if (iCreatedUnifiedCertStore)
225 delete iCreatedUnifiedCertStore;
228 iCreatedUnifiedCertStore = CUnifiedCertStore::NewL(iFs, ETrue); // We want to open it for
230 iUnifiedCertStore = iCreatedUnifiedCertStore;
231 iCreatedUnifiedCertStore->Initialize(iStatus);
236 EXPORT_C void CCertUtils::AddCert(const TDesC& aLabel,
237 TCertificateFormat aFormat,
238 TCertificateOwnerType aCertificateOwnerType,
240 const TDesC& aCertificatePath,
241 const TDesC& aCertificateFileName,
242 CUnifiedCertStore& aUnifiedCertStore,
243 TRequestStatus& aStatus)
245 iOriginalRequestStatus = &aStatus;
246 aStatus = KRequestPending;
248 // We set up the member variable as required for this function
249 iCertificateFileName = &aCertificateFileName;
252 iTrustedUsage = aTrustedUsage;
253 iPath = &aCertificatePath;
254 iCertificateOwnerType = aCertificateOwnerType;
255 iUnifiedCertStore = &aUnifiedCertStore;
259 TRequestStatus* status = &iStatus;
260 User::RequestComplete(status, KErrNone);
263 EXPORT_C void CCertUtils::AddCACertsL(const CDesCArray& aRoots,
264 const CDesCArray& aLabels,
265 TCertificateFormat aFormat,
268 TRequestStatus& aStatus)
270 iOriginalRequestStatus = &aStatus;
271 aStatus = KRequestPending;
273 // We set up the member variable as required for this function
277 iTrustedUsage = aTrustedUsage;
280 iIndex = -1; // -1 because it will be incremented before its first use
281 if (!iSecondCertUtils)
283 iSecondCertUtils = CCertUtils::NewL(iFs);
286 if (iCreatedUnifiedCertStore)
288 delete iCreatedUnifiedCertStore;
291 iCreatedUnifiedCertStore = CUnifiedCertStore::NewL(iFs, ETrue); // We want to open it for
293 iUnifiedCertStore = iCreatedUnifiedCertStore;
294 iCreatedUnifiedCertStore->Initialize(iStatus);
296 iState = EAddCACerts;
300 EXPORT_C void CCertUtils::AddCACertsL(const CDesCArray& aRoots,
301 const CDesCArray& aLabels,
302 TCertificateFormat aFormat,
305 CUnifiedCertStore& aUnifiedCertStore,
306 TRequestStatus& aStatus)
308 iOriginalRequestStatus = &aStatus;
309 aStatus = KRequestPending;
311 // We set up the member variable as required for this function
315 iTrustedUsage = aTrustedUsage;
317 iUnifiedCertStore = &aUnifiedCertStore;
319 iIndex = -1; // -1 because it will be incremented before its first use
320 if (!iSecondCertUtils)
322 iSecondCertUtils = CCertUtils::NewL(iFs);
325 iState = EAddCACerts;
327 TRequestStatus* status = &iStatus;
328 User::RequestComplete(status, KErrNone);
331 EXPORT_C void CCertUtils::RemoveCertsL(CUnifiedCertStore& aUnifiedCertStore,
332 TRequestStatus& aStatus)
334 iOriginalRequestStatus = &aStatus;
335 aStatus = KRequestPending;
336 iUnifiedCertStore = &aUnifiedCertStore;
338 iState = ERemoveCertsGetCACerts;
339 TRequestStatus* status = &iStatus;
340 User::RequestComplete(status, KErrNone);
344 EXPORT_C void CCertUtils::RemoveCertsL(TRequestStatus& aStatus)
346 iOriginalRequestStatus = &aStatus;
347 aStatus = KRequestPending;
348 iState = ERemoveCertsGetCACerts;
350 if (iCreatedUnifiedCertStore)
352 delete iCreatedUnifiedCertStore;
355 iCreatedUnifiedCertStore = CUnifiedCertStore::NewL(iFs, ETrue); // We want to open it for
357 iUnifiedCertStore = iCreatedUnifiedCertStore;
358 iCreatedUnifiedCertStore->Initialize(iStatus);
362 EXPORT_C void CCertUtils::WriteError(TValidationError aError, Output& aOut)
364 aOut.writeString(CCertUtils::MapError(aError));
367 EXPORT_C TPtrC CCertUtils::MapError(TValidationError aError)
375 return (_L("Validated OK"));
377 case EChainHasNoRoot:
379 return(_L("Chain has no root"));
381 case ESignatureInvalid:
383 return(_L("Signature invalid"));
385 case EDateOutOfRange:
387 return(_L("Date out of range"));
389 case ENameIsExcluded:
391 return(_L("Name is excluded"));
393 case ENameNotPermitted:
395 return(_L("Name is not permitted"));
397 case ECertificateRevoked:
399 return(_L("Certificate revoked"));
401 case EUnrecognizedCriticalExtension:
403 return(_L("Unrecognized Critical Extension"));
405 case ENoBasicConstraintInCACert:
407 return(_L("CA cert with no Basic Constraint"));
409 case ENoAcceptablePolicy:
411 return(_L("No acceptable policy"));
415 return(_L("Path too long"));
417 case ENegativePathLengthSpecified:
419 return(_L("Negative path length specified"));
421 case ENamesDontChain:
423 return(_L("Names don't chain"));
425 case ERequiredPolicyNotFound:
427 return(_L("Required policy not found"));
431 return(_L("Bad key usage"));
435 return(_L("Non-CA cert used as CA cert"));
438 case ERootCertNotSelfSigned:
440 return(_L("Root cert not self-signed"));
442 case ECriticalExtendedKeyUsage:
444 return(_L("Critical extended key usage"));
446 case ECriticalCertPoliciesWithQualifiers:
448 return(_L("Critical cert policies with qualifiers"));
450 case ECriticalPolicyMapping:
452 return(_L("Critical policy mapping"));
454 case ECriticalDeviceId:
456 return(_L("Critical Device Id"));
460 return(_L("Critical Sid"));
464 return(_L("Critical Vid"));
466 case ECriticalCapabilities:
468 return(_L("Critical Capabilities"));
471 return (_L("Unknown Error"));
475 EXPORT_C HBufC* CCertUtils::DiagnosticLC() const
477 HBufC* result = HBufC::NewLC(600);
478 switch (iDiagnosticState)
481 result->Des().Append(_L("EAddCACert"));
482 result->Des().Append(_L(" : "));
483 result->Des().Append(iDiagnosticMessage);
493 EXPORT_C void CCertUtils::AddApplicationL(const TDesC& aName, TUid aUid) const
495 CCertificateAppInfoManager* appManager = CCertificateAppInfoManager::NewL(iFs, ETrue);
496 CleanupStack::PushL(appManager);
498 // Only add the application if it doesn't exist already
499 const RArray<TCertificateAppInfo>& apps = appManager->Applications();
501 for (i = 0 ; i < apps.Count() ; ++i)
503 if (apps[i].Id() == aUid && apps[i].Name() == aName)
507 if (i == apps.Count())
509 appManager->AddL(TCertificateAppInfo(aUid, aName));
512 CleanupStack::PopAndDestroy(appManager);
515 EXPORT_C void CCertUtils::RemoveApplicationL(TUid aUid) const
517 CCertificateAppInfoManager* appManager = CCertificateAppInfoManager::NewL(iFs, ETrue);
518 CleanupStack::PushL(appManager);
519 appManager->RemoveL(aUid);
520 CleanupStack::PopAndDestroy(appManager);
524 void CCertUtils::ConstructL()
526 iCAFilter = CCertAttributeFilter::NewL();
527 iCAFilter->SetOwnerType(ECACertificate);
528 iUserFilter = CCertAttributeFilter::NewL();
529 iUserFilter->SetOwnerType(EUserCertificate);
532 void CCertUtils::HandleEAddCACertsL()
535 if (iIndex < iRoots->Count())
537 // We still have some certificates to add
543 iCertData = iRoots->MdcaPoint(iIndex).AllocL();
549 iLabelData = iLabels->MdcaPoint(iIndex).AllocL();
550 iSecondCertUtils->AddCert(*iLabelData, iFormat, ECACertificate,
551 iTrustedUsage, *iPath, *iCertData, *iUnifiedCertStore, iStatus);
556 // We have finished adding all the certificates
557 delete iSecondCertUtils;
558 iSecondCertUtils = 0;
559 delete iCreatedUnifiedCertStore;
560 iCreatedUnifiedCertStore = 0;
561 User::RequestComplete(iOriginalRequestStatus, KErrNone);
565 void CCertUtils::HandleEAddCACertL()
567 // At this stage we should always have an initialized iStoreManager
568 __ASSERT_DEBUG(iUnifiedCertStore, User::Panic(_L("TCertUtils"), 1));
570 // We use the first writable certstore
571 iStore = &iUnifiedCertStore->WritableCertStore(0);
573 __ASSERT_DEBUG(!iCertificate, User::Panic(_L("TCertUtils"), 1));
575 TRAPD(err, iCertificate =
576 CCertUtils::CertFromFileL(*iCertificateFileName, *iPath, iFs, iFormat));
579 if (err != KErrNoMemory)
581 iDiagnosticMessage.Zero();
582 iDiagnosticMessage.Append(_L("CertFromFileL failed ("));
583 iDiagnosticMessage.Append(*iCertificateFileName);
584 iDiagnosticMessage.Append(_L(")"));
588 iEncoding.Set(iCertificate->Encoding());
589 iStore->Add(*iLabel, iFormat, iCertificateOwnerType, 0, 0, iEncoding, iStatus);
590 iState = EAddCACertGetCAEntry;
594 void CCertUtils::HandleEAddCACertGetCAEntry()
598 iCACertStoreEntries.Close();
599 iUnifiedCertStore->List(iCACertStoreEntries, *iCAFilter, iStatus);
600 iState = EAddCACertSetApplications;
604 void CCertUtils::HandleEAddCACertSetApplicationsL()
606 CCTCertInfo* entry = 0;
607 TInt iEnd = iCACertStoreEntries.Count();
608 for (TInt i = 0; i < iEnd; i++)
610 if (iCACertStoreEntries[i]->Label() == *iLabel)
612 entry = iCACertStoreEntries[i];
616 __ASSERT_ALWAYS(entry, User::Panic(_L("TCertUtils"), 1));
619 TUid truster = { iTrustedUsage };
620 User::LeaveIfError(iTrusters.Append(truster));
622 iUnifiedCertStore->SetApplicability(*entry, iTrusters, iStatus);
623 iState = EAddCACertSetTrust;
627 void CCertUtils::HandleEAddCACertSetTrust()
629 CCTCertInfo* entry = 0;
630 TInt iEnd = iCACertStoreEntries.Count();
631 for (TInt i = 0; i < iEnd; i++)
633 if (iCACertStoreEntries[i]->Label() == *iLabel)
635 entry = iCACertStoreEntries[i];
639 __ASSERT_ALWAYS(entry, User::Panic(_L("TCertUtils"), 1));
641 iUnifiedCertStore->SetTrust(*entry, ETrue, iStatus);
642 iState = EAddCACertFinished;
646 void CCertUtils::HandleEAddCACertFinishedL()
648 User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
651 void CCertUtils::HandleERemoveCertsGetCACerts()
653 // At this stage we should always have an initialized iStoreManager
654 __ASSERT_DEBUG(iUnifiedCertStore, User::Panic(_L("TCertUtils"), 1));
656 iCACertStoreEntries.Close();
657 iUnifiedCertStore->List(iCACertStoreEntries, *iCAFilter, iStatus);
659 iState = ERemoveCertsCACertsRetrieved;
663 void CCertUtils::HandleERemoveCertsCACertsRetrieved()
665 // This index will be used to keep track of the current entry
668 iState = ERemoveCertsRemoveCACerts;
669 TRequestStatus* status = &iStatus;
671 User::RequestComplete(status, KErrNone);
674 void CCertUtils::HandleERemoveCertsRemoveCACerts()
677 if (iIndex < iCACertStoreEntries.Count())
679 // Remove this certificate if it can be deleted.
681 CCTCertInfo& cert = *iCACertStoreEntries[iIndex];
683 // Unfortunately, certs in non-writable stores can still be
684 // marked as deletable, so need to check if cert is also in a
687 TBool isDeletable = cert.IsDeletable();
689 TBool inWritableStore = EFalse;
691 TCTTokenObjectHandle certHandle(cert.Handle());
692 TInt writeStoreCount = iUnifiedCertStore->WritableCertStoreCount();
693 for (TInt i = 0; i < writeStoreCount; ++i)
695 MCTWritableCertStore& wcs = iUnifiedCertStore->WritableCertStore(i);
696 if (wcs.Token().Handle() == certHandle.iTokenHandle)
698 inWritableStore = ETrue;
703 if (isDeletable && inWritableStore)
705 iUnifiedCertStore->Remove(cert, iStatus);
710 TRequestStatus* status = &iStatus;
712 User::RequestComplete(status, KErrNone);
717 iState = ERemoveCertsGetUserCerts;
718 TRequestStatus* status = &iStatus;
720 User::RequestComplete(status, KErrNone);
724 void CCertUtils::HandleERemoveCertsGetUserCerts()
726 // At this stage we should always have an initialized iStoreManager
727 __ASSERT_DEBUG(iUnifiedCertStore, User::Panic(_L("TCertUtils"), 1));
729 iUserCertStoreEntries.Close();
730 iUnifiedCertStore->List(iUserCertStoreEntries, *iUserFilter, iStatus);
732 iState = ERemoveCertsUserCertsRetrieved;
736 void CCertUtils::HandleERemoveCertsUserCertsRetrieved()
740 iState = ERemoveCertsRemoveUserCerts;
741 TRequestStatus* status = &iStatus;
743 User::RequestComplete(status, KErrNone);
746 void CCertUtils::HandleERemoveCertsRemoveUserCerts()
748 // At this stage we should always have an initialized iStoreManager
749 __ASSERT_DEBUG(iUnifiedCertStore, User::Panic(_L("TCertUtils"), 1));
752 if (iIndex < iUserCertStoreEntries.Count())
754 iUnifiedCertStore->Remove(*iUserCertStoreEntries[iIndex], iStatus);
759 iState = ERemoveCertsFinished;
760 TRequestStatus* status = &iStatus;
762 User::RequestComplete(status, KErrNone);
766 void CCertUtils::HandleERemoveCertsFinished()
768 User::RequestComplete(iOriginalRequestStatus, KErrNone);