vpnengine/pkiservice/src/pkimapper.cpp
changeset 0 33413c0669b9
child 1 c9c2ad51f972
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/pkiservice/src/pkimapper.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,984 @@
+/*
+* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: 
+* CPKIMapper class holds the information required to map API set to 
+* use the storage model which is not native for that API.
+*
+*/
+
+
+#include <x500dn.h>
+#include <x509cert.h>
+
+#include "PKIMapper.h"
+#include "pkcs10.h"
+#include "log_r6.h"
+#include "pkiserviceassert.h"
+
+
+CMapDescriptor::CMapDescriptor(TSecurityObjectDescriptor &aDesc)
+    {
+    this->iSubjectKeyId = aDesc.iSubjectKeyId;
+    this->iOwnerType = aDesc.iOwnerType;
+    this->iKeySize = aDesc.iKeySize;            
+    this->iKeyAlgorithm = aDesc.iKeyAlgorithm;      
+    this->iIsDeletable = aDesc.iIsDeletable;      
+    }
+
+CMapDescriptor& CMapDescriptor::operator=(CMapDescriptor& aMapDesc)
+{
+    delete this->iTrustedAuthority;
+    this->iTrustedAuthority = NULL;
+    if(aMapDesc.iTrustedAuthority != NULL)
+        {
+        this->iTrustedAuthority     = aMapDesc.iTrustedAuthority->Des().AllocL();           // Cert TrustedAuthority
+        }
+    delete this->iIdentitySubjectName;
+    this->iIdentitySubjectName = NULL;
+    if(aMapDesc.iIdentitySubjectName != NULL)
+        {
+        this->iIdentitySubjectName  = aMapDesc.iIdentitySubjectName->Des().AllocL();        // Identity subject name
+        }
+    delete this->iIdentityRfc822Name;
+    this->iIdentityRfc822Name = NULL;
+    if(aMapDesc.iIdentityRfc822Name != NULL)
+        {
+        this->iIdentityRfc822Name   = aMapDesc.iIdentityRfc822Name->Des().AllocL();         // Identity subjectAltName rfc822 name
+        }
+    delete this->iSerialNumber;
+    this->iSerialNumber = NULL;
+    if(aMapDesc.iSerialNumber != NULL)
+        {
+        this->iSerialNumber         = aMapDesc.iSerialNumber->Des().AllocL();               // Serialnumber
+        }
+        
+    this->iSubjectKeyId         = aMapDesc.iSubjectKeyId;                               // SHA1 hash of the corresponding private key
+    this->iOwnerType            = aMapDesc.iOwnerType;                                  // User, CA or peer. If user certificate, at least key usage must be set
+    this->iKeyUsageDer          = aMapDesc.iKeyUsageDer;                                // Der format flags
+    this->iObjectName           = aMapDesc.iObjectName;
+    this->iKeySize              = aMapDesc.iKeySize;                                    // Key size
+    this->iKeyAlgorithm         = aMapDesc.iKeyAlgorithm;                               // RSA, DSA
+    this->iStartTime            = aMapDesc.iStartTime;
+    this->iEndTime              = aMapDesc.iEndTime;
+    this->iIsDeletable          = aMapDesc.iIsDeletable;
+    TInt i;
+    for(i=0;i<aMapDesc.iApplUids.Count();i++)
+        {
+        this->iApplUids.Append(aMapDesc.iApplUids[i]);
+        }
+        
+    this->iCertStoreType        = aMapDesc.iCertStoreType;
+    return *this;
+}
+
+
+TBool CMapDescriptor::IsMatchingL(TSecurityObjectDescriptor &aDesc, 
+                                  const TBool aInfoOnly, 
+                                  TPkiServiceStoreType aCertStoreType) const
+    {
+    TBool match(EFalse);
+
+    LOG(Log::Printf(_L("Matching")));
+    LOG_1(" Pure informational: %d", aInfoOnly);
+
+    LOG(Log::Printf(_L("Matching: certificate %S"), &iObjectName));
+    for(;;)
+        {
+        if (aDesc.iOwnerType != EPKICACertificate &&
+            aCertStoreType != EPkiStoreTypeAny) 
+            {            
+            if (iCertStoreType != aCertStoreType)
+                {
+                LOG(Log::Printf(_L("    Store doesn't match, aborting")));
+                match = EFalse;
+                break;                
+                }
+            }
+        else 
+            {
+            LOG(Log::Printf(_L("Skipping store check, not relevant")));
+            }
+                    
+			
+        if (aDesc.iSubjectKeyIdUsed)
+            {            
+			if(iSubjectKeyId == aDesc.iSubjectKeyId)
+				{
+				match = ETrue;
+				}
+			else
+				{
+				match = EFalse;
+				break;
+				}
+			}
+			
+        if(aDesc.iTrustedAuthorityUsed)
+            {
+            if(iTrustedAuthority == NULL)
+                {
+                match = EFalse;
+                break;
+                }
+            else
+                {
+                CX500DistinguishedName* dnSuffix1 = CX500DistinguishedName::NewLC(*iTrustedAuthority);
+                CX500DistinguishedName* dnSuffix2;
+                TInt popCount = 3;
+
+                // ASN1 or plain text
+                if((aDesc.iTrustedAuthority[0] != 0x30)
+                   || ((aDesc.iTrustedAuthority[1] != 0x81)
+                   && (aDesc.iTrustedAuthority[1] != 0x82)
+                   && ((aDesc.iTrustedAuthority[1] + 2) != aDesc.iTrustedAuthority.Length())))
+                    {
+                    HBufC8* name2Der;
+                    CPkcs10Req::BuildDistinguishedNameDerFromTextL(name2Der,
+                                                                   aDesc.iTrustedAuthority,
+                                                                   EFalse, KNullDesC8);
+                    CleanupStack::PushL(name2Der);
+
+                    dnSuffix2 = CX500DistinguishedName::NewLC(*name2Der);
+                    }
+                else
+                    {
+                    dnSuffix2 = CX500DistinguishedName::NewLC(aDesc.iTrustedAuthority);
+                    popCount = 2;
+                    }
+
+
+                if(PkiUtil::MatchL(*dnSuffix1, *dnSuffix2))
+                    {
+                    match = ETrue;
+                    CleanupStack::PopAndDestroy(popCount);
+                    }
+                else
+                    {
+                    match = EFalse;
+                    CleanupStack::PopAndDestroy(popCount);
+                    break;
+                    }
+                }
+            }
+        if(aDesc.iOwnerTypeUsed)
+            {
+            if(iOwnerType == aDesc.iOwnerType)
+                {
+                match = ETrue;
+                }
+            else
+                {
+                match = EFalse;
+                break;
+                }
+            }
+        if(aDesc.iSerialNumberUsed)
+            {
+            if ((iSerialNumber != NULL) && ((*iSerialNumber).Compare(aDesc.iSerialNumber) == 0))
+                {
+                match = ETrue;
+                }
+            else
+                {
+                match = EFalse;
+                break;
+                }
+            }
+
+        if(aDesc.iIdentitySubjectNameUsed)
+            {
+            if(iIdentitySubjectName == NULL)
+                {
+                match = EFalse;
+                break;
+                }
+            else
+                {
+                CX500DistinguishedName* dnSuffix1 = CX500DistinguishedName::NewLC(*iIdentitySubjectName);
+                CX500DistinguishedName* dnSuffix2;
+                TInt popCount = 3;
+                // ASN1 or plain text
+                if((aDesc.iIdentitySubjectName[0] != 0x30)
+                   || ((aDesc.iIdentitySubjectName[1] != 0x81)
+                   && (aDesc.iIdentitySubjectName[1] != 0x82)
+                   && ((aDesc.iIdentitySubjectName[1] + 2) != aDesc.iIdentitySubjectName.Length())))
+                    {
+                    HBufC8* name2Der;
+                    CPkcs10Req::BuildDistinguishedNameDerFromTextL(name2Der,
+                                                                   aDesc.iIdentitySubjectName,
+                                                                   EFalse, KNullDesC8);
+                    CleanupStack::PushL(name2Der);
+
+                    dnSuffix2 = CX500DistinguishedName::NewLC(*name2Der);
+                    }
+                else
+                    {
+                    dnSuffix2 = CX500DistinguishedName::NewLC(aDesc.iIdentitySubjectName);
+                    popCount = 2;
+                    }
+
+                if(PkiUtil::MatchL(*dnSuffix1, *dnSuffix2))
+                    {
+                    CleanupStack::PopAndDestroy(popCount);
+                    match = ETrue;
+                    }
+                else
+                    {
+                    CleanupStack::PopAndDestroy(popCount);
+                    match = EFalse;
+                    break;
+                    }
+                }
+            }
+
+        if(aDesc.iIdentityRfc822NameUsed)
+            {
+            if(iIdentityRfc822Name == NULL)
+                {
+                match = EFalse;
+                break;
+                }
+            else
+                {
+                TInt bytes = aDesc.iIdentityRfc822Name.Length();
+                TPtrC8 tail = (*iIdentityRfc822Name).Right(bytes);
+                if (tail.CompareF(aDesc.iIdentityRfc822Name) == 0)
+                    {
+                    match = ETrue;
+                    }
+                else
+                    {
+                    match = EFalse;
+                    break;
+                    }
+                }
+            }
+
+        if(aDesc.iKeyUsageUsed)
+            {
+            CX509KeyUsageExt* tempUsage = NULL;
+            if(iKeyUsageDer.Length() != 0)
+                {
+                tempUsage = CX509KeyUsageExt::NewL(iKeyUsageDer);
+                }
+            if((tempUsage == NULL) || tempUsage->IsSet(aDesc.iKeyUsage))       
+                {
+                delete tempUsage;
+                match = ETrue;
+                }
+            else
+                {
+                delete tempUsage;
+                match = EFalse;
+                break;
+                }
+            }
+            
+        if(aDesc.iKeySizeUsed)
+            {
+            if(iKeySize == aDesc.iKeySize)
+                {
+                match = ETrue;
+                }
+            else
+                {
+                match = EFalse;
+                break;
+                }
+            }
+            
+        if (match && !aInfoOnly)
+            {            
+            TValidity  val = CPKIMapper::CertValidity(iStartTime, iEndTime);
+            // Treat future certificates as valid
+            if((val == EValid) || (val == ENotValidYet))
+                {
+                match = ETrue;
+                }
+            else
+                {
+                LOG_("Matching: Expired, and not an informational request");
+                match = EFalse;
+                break;
+                }
+            }
+            
+        break;
+        }
+		
+    return match;
+    }
+
+TBool CMapDescriptor::IsEqual(CMapDescriptor &aDesc)
+    {
+    TBool match = EFalse;
+
+    for(;;)
+        {
+        if((iTrustedAuthority != NULL) && (aDesc.iTrustedAuthority != NULL) && (iTrustedAuthority->Des().Compare(*aDesc.iTrustedAuthority) == 0))
+            {
+            match = ETrue;
+            }
+        else
+            {
+            match = EFalse;
+            break;
+            }
+        
+        if((iSerialNumber != NULL) && (aDesc.iSerialNumber != NULL) && (iSerialNumber->Des().Compare(*aDesc.iSerialNumber) == 0))
+            {
+                match = ETrue;
+                }
+            else
+                {
+                match = EFalse;
+                break;
+                }
+            
+        break;
+        }
+
+    return match;
+    }
+    
+    
+void CMapDescriptor::SetCertStoreType(TPkiServiceStoreType aCertStoreType)
+    {
+    iCertStoreType = aCertStoreType;
+    }
+
+CPKIMapper* CPKIMapper::NewL()
+    {
+    CPKIMapper* self = new (ELeave) CPKIMapper();
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CPKIMapper::~CPKIMapper()
+    {
+    if ( iMapping )
+        {
+        iMapping->ResetAndDestroy();
+        delete iMapping;
+        }
+    }
+
+
+CPKIMapper::CPKIMapper()
+    {
+    }
+
+void CPKIMapper::ConstructL()
+    {
+    LOG_("CPKIMapper::ConstructL");
+    // Allocate mapping vector. Approx granularity 20 
+    iMapping = new (ELeave) RPointerArray<CMapDescriptor>(20);
+    }
+
+void CPKIMapper::SetCacheCreated()
+    {
+    iCacheCreated = ETrue;
+    }
+TBool CPKIMapper::CacheCreated()
+    {
+    return iCacheCreated;
+    }
+    
+TInt CPKIMapper::AddMapping(CMapDescriptor& aMap)
+    {
+    // Insert as first element, so that newest object will be found first
+    return iMapping->Insert(&aMap, 0);
+    }
+
+void CPKIMapper::LogMap(CMapDescriptor &aDescriptor) const 
+    {
+    TInt len = aDescriptor.iSubjectKeyId.Length();
+    LOG(Log::Printf(_L("====CertificateObject====\n")));
+    LOG(Log::Printf(_L("ObjectName: %S\n"), &(aDescriptor.iObjectName)));
+    LOG(Log::Printf(_L("KeyId:")));
+    LOG(Log::HexDump(NULL, NULL, aDescriptor.iSubjectKeyId.Ptr(), len));
+    }
+
+    
+void CPKIMapper::DeleteMapping(TInt aIndex)
+    {
+    // Delete mapping at index
+    LOG(Log::Printf(_L("Delete mapping entry")));
+    LogMap(*(*iMapping)[aIndex]);
+    delete (*iMapping)[aIndex]; 
+    iMapping->Remove(aIndex);
+    iMapping->Compress();
+    }
+
+TInt CPKIMapper::DeleteMapping(CMapDescriptor &aDesc)
+    {
+    TInt status(KErrNotFound);
+    
+    for(TInt i(0); i < iMapping->Count(); i++)
+        {
+        if((*iMapping)[i]->IsEqual(aDesc))
+            {
+            DeleteMapping(i);
+            status = KErrNone;
+            break;
+            }
+        }
+    return status;
+    }
+
+TInt CPKIMapper::CertCount()
+    {
+    TInt count(0);    
+    
+    for(TInt i(0); i < iMapping->Count(); i++)
+        {
+        CMapDescriptor* mapping = (*iMapping)[i];
+        count++;
+        if (CertValidity(mapping->iStartTime, mapping->iEndTime) == EExpired)
+            {
+            // do not count expider certificates
+            count--;
+            }                
+        }
+    iCount = count;
+    return count;            
+    }
+
+TInt CPKIMapper::ApplicableCertCount(const RArray<TUid>& aUidArray)
+{
+    TInt count(0);
+    TBool uidMatch(EFalse);
+    
+    for(TInt i(0); i < iMapping->Count(); i++)
+        {
+        CMapDescriptor* mapping = (*iMapping)[i];
+        if(mapping->iOwnerType == EPKICACertificate)
+            {
+            if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired)
+                {
+                uidMatch = EFalse;
+                for(TInt j = 0; j < mapping->iApplUids.Count(); j++)
+                    {
+                    for(TInt k = 0; k < aUidArray.Count(); k++)
+                        {
+                        if(mapping->iApplUids[j].iUid == aUidArray[k].iUid)
+                            {
+                            uidMatch = ETrue;
+                            break;
+                            }
+                        }
+                    if(uidMatch)
+                        {
+                        count++;
+                        break;
+                        }
+                    }
+                }
+            }
+        }
+    iCount = count;
+    return count;
+}
+
+
+TInt CPKIMapper::GetCertListL(const RMessage2 &aMessage, TPkiServiceStoreType aStoreType, 
+                              TBool aDescUsed)
+{
+    TInt pos = 0;
+    TInt iLast = 0;
+    TInt iFirst = 0;
+
+    if(aDescUsed)
+        {
+        aMessage.ReadL(1, iCurrentDescriptor);
+        TSecurityObjectDescriptor& secDesc = iCurrentDescriptor();
+        TInt status = ResolveCertMappingL(
+            iCurrentDescriptor(), iObjectName, iFirst, EFalse, aStoreType);
+        if(status == KErrNone)
+            {
+            iCount = 1;
+            iLast = iFirst + 1;
+            }
+        }
+    else
+        {
+        iLast = iMapping->Count();
+        }
+    
+    CBufFlat* list = CBufFlat::NewL(sizeof(TCertificateListEntry));
+    CleanupStack::PushL(list);
+    list->ResizeL(iCount * sizeof(TCertificateListEntry));
+    TCertificateListEntry certInfo;
+    
+    for(TInt i = iFirst; i < iLast; i++)
+        {
+        CMapDescriptor* mapping = (*iMapping)[i];
+        if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired)
+            {
+            certInfo.iObjectName = mapping->iObjectName;
+            certInfo.iOwnerType = mapping->iOwnerType;
+            if(mapping->iTrustedAuthority != NULL)
+                {
+                certInfo.iTrustedAuthority = *(mapping->iTrustedAuthority);
+                }
+            if(mapping->iIdentitySubjectName != NULL)
+                {
+                certInfo.iIdentitySubjectName = *(mapping->iIdentitySubjectName);
+                }
+            if(mapping->iSerialNumber != NULL)
+                {
+                certInfo.iSerialNumber = *(mapping->iSerialNumber);
+                }
+            certInfo.iSubjectKeyId = mapping->iSubjectKeyId;
+            certInfo.iKeySize = mapping->iKeySize;                   // Key size
+            certInfo.iKeyAlgorithm = mapping->iKeyAlgorithm;         // RSA, DSA
+            certInfo.iIsDeletable = mapping->iIsDeletable;           // IsDeletable
+
+            list->Write(pos * sizeof(TCertificateListEntry),
+                        (TAny*)&certInfo,
+                        sizeof(TCertificateListEntry));
+            pos++;
+            if(pos >= iCount)
+                {
+                break;
+                }
+            }            
+        }
+    TPtr8 ptrList = list->Ptr(0);
+    aMessage.WriteL(0, ptrList);
+
+    CleanupStack::PopAndDestroy(1); // list
+    return KErrNone;
+}
+
+
+void CPKIMapper::GetApplicableCertListL(const RMessage2& aMessage, const RArray<TUid>& aUidArray)
+{
+    TBool uidMatch = EFalse;
+    TInt pos(0);
+    
+    CBufFlat* list = CBufFlat::NewL(sizeof(TCertificateListEntry));
+    CleanupStack::PushL(list);
+    list->ResizeL(iCount * sizeof(TCertificateListEntry));
+    TCertificateListEntry certInfo;
+
+    for(TInt i = 0; (i < iMapping->Count()) && (pos < iCount); i++)
+        {
+        CMapDescriptor* mapping = (*iMapping)[i];
+        if(mapping->iOwnerType == EPKICACertificate)
+            {
+            if(CertValidity(mapping->iStartTime, mapping->iEndTime) != EExpired)
+                {
+                uidMatch = EFalse;
+                for(TInt j = 0; j < mapping->iApplUids.Count(); j++)
+                    {
+                    for(TInt k = 0; k < aUidArray.Count(); k++)
+                        {
+                        if(mapping->iApplUids[j].iUid == aUidArray[k].iUid)
+                            {
+                            uidMatch = ETrue;
+                            break;
+                            }
+                        }
+                    if(uidMatch)
+                        {
+                        certInfo.iObjectName = mapping->iObjectName;
+                        certInfo.iOwnerType = mapping->iOwnerType;
+                        if(mapping->iTrustedAuthority != NULL)
+                            {
+                            certInfo.iTrustedAuthority = *(mapping->iTrustedAuthority);
+                            }
+                        if(mapping->iIdentitySubjectName != NULL)
+                            {
+                            certInfo.iIdentitySubjectName = *(mapping->iIdentitySubjectName);
+                            }
+                        if(mapping->iSerialNumber != NULL)
+                            {
+                            certInfo.iSerialNumber = *(mapping->iSerialNumber);
+                            }
+                        certInfo.iSubjectKeyId = mapping->iSubjectKeyId;
+                        certInfo.iKeySize = mapping->iKeySize;                   // Key size
+                        certInfo.iKeyAlgorithm = mapping->iKeyAlgorithm;         // RSA, DSA
+                        certInfo.iIsDeletable = mapping->iIsDeletable;           // IsDeletable
+
+                        list->Write(pos * sizeof(TCertificateListEntry),
+                                    (TAny*)&certInfo,
+                                    sizeof(TCertificateListEntry));
+                        pos++;
+                        break;
+                        }
+                    }
+                }
+            }
+        }
+    TPtr8 ptrList = list->Ptr(0);
+    aMessage.WriteL(0, ptrList);
+
+    CleanupStack::PopAndDestroy(1); // list
+}
+
+
+
+CMapDescriptor& CPKIMapper::GetMapDescriptorAtIndex(TInt aIndex)
+{
+    PKISERVICE_ASSERT(aIndex < iMapping->Count());
+    return *(*iMapping)[aIndex];
+}
+
+
+void CPKIMapper::GetCertificateKeyIdL(TSecurityObjectDescriptor &aDescriptor, TPKIKeyIdentifier &aKeyId,
+                                      TPkiServiceStoreType aStoreType) const
+    {
+    LOG(Log::Printf(_L("-> CPKIMapper::GetCertificateKeyIdL"), aStoreType));
+    aKeyId.Zero();
+    
+    TInt index;    
+    
+    TFileName* fileName = new (ELeave) TFileName;
+    CleanupDeletePushL(fileName);
+    fileName->Zero();
+    
+    TInt status = ResolveCertMappingL(aDescriptor, *fileName, index, EFalse, aStoreType);    
+
+    CleanupStack::PopAndDestroy(fileName);
+    
+    
+    if(status == KErrNone)
+        {
+        aKeyId.Copy((*iMapping)[index]->iSubjectKeyId);
+        }
+    else
+        {
+        LOG(Log::Printf(_L("ResolveKeyMapping: key NOT found\n")));
+        LogSearchArguments(aDescriptor);
+        }    
+    LOG(Log::Printf(_L("<- CPKIMapper::GetCertificateKeyIdL"), aStoreType));        
+    }
+
+/**
+    Check whether the given label is unique among all VPN certs.
+    @return True only if the given label doesn't exist
+*/
+TBool CPKIMapper::LabelIsUnique(const TDesC& aLabel) const
+    {
+    for (TInt i(0); i < iMapping->Count(); i++) 
+        {
+        if ((*iMapping)[i]->iObjectName.Compare(aLabel) == 0) 
+            {
+            return EFalse;
+            }
+        }
+    return ETrue;
+    }
+
+/**
+    Check whether the given certificate already exists among VPN certs.
+    @return True only if the given certificate does not exist in VPN's cert list.
+*/
+TBool CPKIMapper::CertificateIsUniqueL(const TDesC8& aCertData)
+    {
+    TBool ret(ETrue);
+    
+    LOG(Log::Printf(_L("Verifying the uniqueness of certificate:")));
+
+    CX509Certificate* certificate = CX509Certificate::NewLC(aCertData);
+    const TPtrC8* issuername = certificate->DataElementEncoding(CX509Certificate::EIssuerName);
+    const TPtrC8* subjectname = certificate->DataElementEncoding(CX509Certificate::ESubjectName);
+    
+    HBufC* issuerdispname = certificate->IssuerName().DisplayNameL();
+    CleanupStack::PushL(issuerdispname);
+    HBufC* subjectdispname = certificate->SubjectName().DisplayNameL();
+    CleanupStack::PushL(subjectdispname);
+    
+    TInt count(iMapping->Count());
+
+    for (TInt i(0); i < count; i++) 
+        {
+        CMapDescriptor* mapitem = (*iMapping)[i];
+
+        //  Use subject name for uniqueness criterion
+        if (mapitem->iIdentitySubjectName)
+            {
+            if (subjectname->Compare(*(mapitem->iIdentitySubjectName)) == 0) 
+                {
+                LOG(Log::Printf(_L("Found an existing cert that matches subject")));
+                if (issuername->Compare(*(mapitem->iTrustedAuthority)) == 0) 
+                    {
+                    ret = EFalse;
+                    break;
+                    }
+                }
+            }
+        else if (mapitem->iTrustedAuthority && (subjectname->Compare(*issuername) == 0))
+            {
+            if (subjectname->Compare(*(mapitem->iTrustedAuthority)) == 0) 
+                {
+                LOG(Log::Printf(_L("Found an existing cert that matches subject (CA)")));
+                ret = EFalse;
+                break;
+                }
+            }
+        }
+
+    CleanupStack::PopAndDestroy(3, certificate); // issuerdispname, subjectdispname
+
+    return ret;
+    }
+    
+/**
+    Generates an unique label name for a certificate, based on its subject name.
+    @param1 The binary data describing the certificate
+    @param2 Return value for the generated unique name
+    @param3 Certificate owner type -- currently not supported.
+    @return none
+*/
+void CPKIMapper::GenerateUniqueNameL(
+    const TDesC8 &aCertData, TDes& aName, 
+    TCertificateOwnerType /*aOwnerType*/ )
+    {
+    LOG(Log::Printf(_L("CPKIMapper::GenerateUniqueNameL() entry")));
+
+    CX509Certificate* certificate = CX509Certificate::NewLC(aCertData);
+
+    HBufC* baseline = certificate->SubjectName().DisplayNameL();
+    CleanupStack::PushL(baseline);
+    // +5 for (999) suffix
+    HBufC* variation = HBufC::NewLC(baseline->Length() + 5);
+    variation->Des().Append(*baseline);
+    
+    if (baseline->Length() == 0)
+        {
+        TPtr ptr = variation->Des();
+        ptr.Format(_L("(1)"));
+        }
+
+    // See whether the initial label is already unique    
+    TInt iter(2);
+    while (!LabelIsUnique(*variation)) 
+        {
+        // Iterate a new version of the label
+        if (iter > 999) 
+            {
+            // too long name, just go with the previous.
+            break;
+            }
+        TPtr ptr = variation->Des();
+        ptr.Format(_L("%S(%d)"), &(*baseline), iter);
+        iter++;
+        }
+
+    // Sanity check for string lengths
+    aName = variation->Left(MAX_FILENAME_LENGTH);
+
+    CleanupStack::PopAndDestroy(3); //variation, baseline, certificate
+
+    LOG(Log::Printf(_L("CPKIMapper::GenerateUniqueNameL() exit")));
+    }
+
+TInt CPKIMapper::ResolveCertMappingL(TSecurityObjectDescriptor &aDescriptor, TDes16 &aFilename, 
+                                     TInt &aIndex, const TBool aInfoOnly, 
+                                     TPkiServiceStoreType aStoreType) const   
+    {
+    TInt i;
+    TInt status = KErrNotFound;
+    TInt foundIndex = -1;
+    TTime furthestEndTime = TTime(0);
+
+    LOG(Log::Printf(_L("Resolving cert mapping, STORETYPE: %d\n"), aStoreType));
+
+    LOG(LogSearchArguments(aDescriptor));
+
+    // Scan available mappings
+    for(i = 0; i < iMapping->Count(); i++)
+        {
+        // Bypass entry in case that function leaves
+        // (issuer/subject name can be invalid)
+        CMapDescriptor* mapping = (*iMapping)[i];
+        if(mapping->IsMatchingL(aDescriptor, aInfoOnly, aStoreType))
+            {
+            // If we found a match, process it further
+            _LIT(KMidp2Label, "MIDP2");
+            TBuf<12> buf;
+            buf.Append(KMidp2Label);
+            // Discard all MIDP2 certificates to avoid label-mapping problem
+            if (buf.Compare(mapping->iObjectName) != 0)
+                {
+                if(mapping->iEndTime > furthestEndTime)
+                    {
+                    furthestEndTime = mapping->iEndTime;
+                    foundIndex = i;
+                    LOG(Log::Printf(_L("Resolve cert mapping: Tentatively found a suitable one")));
+                    // Continue to search the longest lasting certificate
+                    }
+                }
+            else 
+                {
+                LOG(Log::Printf(_L("Found a cert, but it was a MIDP2 one - continuing search")));
+                }
+            }
+        }
+    
+    if(foundIndex == -1)
+        {
+        LOG(Log::Printf(_L("Resolve cert mapping: No matching certificate found")));       
+        status = KErrNotFound;
+        }
+    else
+        {
+        aFilename.Zero();
+        status = KErrNone;
+        if(status == KErrNone)
+            {
+            aFilename.Append((*iMapping)[foundIndex]->iObjectName);
+            status = KErrNone;
+            aIndex = foundIndex;
+            }
+        LOG(Log::Printf(_L("ResolveCertMapping: certificate found\n")));
+        LogSearchArguments(aDescriptor);
+        LOG(Log::Printf(_L("ResolveCertMapping: Object info\n")));
+        LogMap(*(*iMapping)[aIndex]);
+        }
+    return status;
+    }    
+  
+
+TValidity CPKIMapper::CertValidity(const TTime &aStartTime,  const TTime &aEndTime) 
+    {
+    TTimeIntervalSeconds tolerance(120); 
+    TTime currentTime;
+    currentTime.UniversalTime();
+
+    if (aEndTime <= currentTime)
+        {
+        return EExpired;
+        }
+
+    if (aStartTime >= currentTime + tolerance)
+        {
+        return ENotValidYet;
+        }
+
+    return EValid;
+    }
+
+void CPKIMapper::LogSearchArguments(TSecurityObjectDescriptor &aDescriptor) const
+    {
+    TBuf<256> temp;
+    LOG(Log::Printf(_L("====Object Search arguments====\n")));
+    if(aDescriptor.iTrustedAuthorityUsed)
+        {
+        temp.Copy(aDescriptor.iTrustedAuthority);
+        if((aDescriptor.iTrustedAuthority[0] != 0x30)
+           || ((aDescriptor.iTrustedAuthority[1] != 0x81)
+               && (aDescriptor.iTrustedAuthority[1] != 0x82)
+               && ((aDescriptor.iTrustedAuthority[1] + 2) != aDescriptor.iTrustedAuthority.Length())))
+            {
+            LOG(Log::Printf(_L("Trusted authority: %S\n"), &temp));
+            }
+        else
+            {
+            LOG(Log::Printf(_L("Trusted authority:")));
+            LOG(Log::HexDump(NULL, NULL, aDescriptor.iTrustedAuthority.Ptr(), aDescriptor.iTrustedAuthority.Length()));
+            }
+        }
+    if(aDescriptor.iIdentitySubjectNameUsed)
+        {
+        temp.Copy(aDescriptor.iIdentitySubjectName);
+        if((aDescriptor.iIdentitySubjectName[0] != 0x30)
+           || ((aDescriptor.iIdentitySubjectName[1] != 0x81)
+               && (aDescriptor.iIdentitySubjectName[1] != 0x82)
+               && ((aDescriptor.iIdentitySubjectName[1] + 2) != aDescriptor.iIdentitySubjectName.Length())))
+            {
+            LOG(Log::Printf(_L("SubjectName: %S\n"), &temp));
+            }
+        else
+            {
+            LOG(Log::Printf(_L("SubjectName:")));
+            LOG(Log::HexDump(NULL, NULL, aDescriptor.iIdentitySubjectName.Ptr(), aDescriptor.iIdentitySubjectName.Length()));
+            }
+        }
+    if(aDescriptor.iIdentityRfc822NameUsed)
+        {
+        temp.Copy(aDescriptor.iIdentityRfc822Name);
+        LOG(Log::Printf(_L("Rfc822Name: %S\n"), &temp));
+        }
+    if(aDescriptor.iSerialNumberUsed)
+        {
+        LOG(Log::Printf(_L("SerialNumber:")));
+        LOG(Log::HexDump(NULL, NULL, aDescriptor.iSerialNumber.Ptr(), aDescriptor.iSerialNumber.Length()));
+        }
+    if(aDescriptor.iSubjectKeyIdUsed)
+        {
+        LOG(Log::Printf(_L("KeyId:")));
+        LOG(Log::HexDump(NULL, NULL, aDescriptor.iSubjectKeyId.Ptr(), aDescriptor.iSubjectKeyId.Length()));
+        }
+    if(aDescriptor.iOwnerTypeUsed)
+        {
+        LOG(Log::Printf(_L("OwnerType: %d\n"), aDescriptor.iOwnerType));
+        }
+    if(aDescriptor.iKeyUsageUsed)
+        {
+        LOG(Log::Printf(_L("KeyUsage:")));
+        LOG(Log::HexDump(NULL, NULL, aDescriptor.iKeyUsageDer.Ptr(), aDescriptor.iKeyUsageDer.Length()));
+        }
+    if(aDescriptor.iKeySizeUsed)
+        {
+        LOG(Log::Printf(_L("KeySize: %d\n"), aDescriptor.iKeySize));
+        }
+    if(aDescriptor.iKeyAlgorithmUsed)
+        {
+        LOG(Log::Printf(_L("KeyAlgorithm: %d\n"), aDescriptor.iKeyAlgorithm));
+        }
+    }   
+
+TBool PkiUtil::MatchL(const CX500DistinguishedName& aDn1, const CX500DistinguishedName& aDn2)
+{
+    if((aDn1.Count() == 0) || (aDn2.Count() == 0))
+        {
+        return EFalse;
+        }
+    
+    if (aDn1.Count() < aDn2.Count())
+        {
+        return EFalse;
+        }
+    else
+        {
+        // For each field in aDn2, aDn1 must contain a field with the same value
+        for (TInt i = 0; i < aDn2.Count(); i++)
+            {
+            if (!HasElementL(aDn1, aDn2.Element(i)))
+                {
+                return EFalse;
+                }
+            }
+        }
+
+    return ETrue;
+}
+
+TBool PkiUtil::HasElementL(const CX500DistinguishedName& aDn, const CX520AttributeTypeAndValue& aElement)
+{
+    for (TInt i = 0; i < aDn.Count(); i++)
+        {
+        if (aElement.ExactMatchL(aDn.Element(i)))
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+}
+