vpnengine/dmadpki/src/dmadstorecert.cpp
changeset 0 33413c0669b9
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vpnengine/dmadpki/src/dmadstorecert.cpp	Thu Dec 17 09:14:51 2009 +0200
@@ -0,0 +1,425 @@
+/*
+* Copyright (c) 2002 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: Implementation of CDmAdCert.
+*
+*/
+
+
+#include "dmadutil.h"
+#include "dmadstorecert.h"
+#include "vpnlogger.h"
+#include "dmadcertxmldefs.h"
+#include "XppImpl.h"
+#include "XwImpl.h"
+#include <vpnlogmessages.rsg>
+
+CDmAdCert* CDmAdCert::NewL(RPKIServiceAPI& aPkiServiceApi)
+    {
+    TRACE("CDmAdCert::NewL");
+    
+    CDmAdCert* self = NewLC(aPkiServiceApi);
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+CDmAdCert* CDmAdCert::NewLC(RPKIServiceAPI& aPkiServiceApi)
+    {
+    CDmAdCert* self = new (ELeave) CDmAdCert(aPkiServiceApi);
+    CleanupStack::PushL(self);
+    self->ConstructL();
+    return self;
+    }
+
+void CDmAdCert::ConstructL()
+    {
+    TRACE("CDmAdCert::ConstructL");
+    iCertLuidMapping = new (ELeave) CArrayPtrFlat<CDmAdCertLuidMappingElem>(4);
+    BuildCertLuidMappingTableL();
+    }
+    
+CDmAdCert::CDmAdCert(RPKIServiceAPI& aPkiServiceApi) : iPkiServiceApi(&aPkiServiceApi)
+    {
+    }
+    
+CDmAdCert::~CDmAdCert()
+    {
+    TRACE("CDmAdCert::~CDmAdCert");
+    CDmAdCertLuidMappingElem::CleanupOperationDeleteCArrayPtr(iCertLuidMapping);    
+    }
+    
+TBool CDmAdCert::FindL(const TDesC8& aLuid)
+    {
+    TRACE("CDmAdCert::FindL");
+    if (!FindCertLuidMappingElemL(aLuid))
+        {
+        return EFalse;
+        }
+    else
+        {
+        return ETrue;
+        }
+    }
+    
+HBufC8* CDmAdCert::AddL(const CDmAdCertParms& aParms)
+    {    
+    TRACE("CDmAdCert::AddL");
+    
+    TPKICertificateOwnerType ownerType = aParms.Type();
+
+    HBufC8* certRef = BuildCertRefL(aParms.Content(), EFalse);
+    CleanupStack::PushL(certRef);
+    CDmAdCertLuidMappingElem* certLuidMappingElem = FindCertLuidMappingElemL(*certRef);
+    if (certLuidMappingElem)
+        {
+        DEBUG_LOG(_L("Element already exists"));
+        User::Leave(KErrAlreadyExists);
+        }
+    CleanupStack::PopAndDestroy(certRef); 
+    
+
+    TInt status = KErrNone;
+    if (ownerType == EPKIUserCertificate)
+        {
+        DEBUG_LOG(_L("Attaching user certificate"));        
+        
+        TKeyListEntry* keyListEntry = new (ELeave) TKeyListEntry;
+        CleanupStack::PushL(keyListEntry);
+        
+        TPKIKeyIdentifier keyId = aParms.KeyId();
+        DEBUG_LOG(_L("Key id:"));
+        DEBUG_LOG_HEX(keyId);
+        
+        
+        User::LeaveIfError(iPkiServiceApi->KeyDetails(keyId,
+						   *keyListEntry));
+        
+        TInt keyLength = keyListEntry->iKeySize;
+        
+        DEBUG_LOG(_L("Key info:"));
+        DEBUG_LOG1(_L("Object name: %S"), &(keyListEntry->iObjectName));
+        DEBUG_LOG_HEX(keyListEntry->iSubjectKeyId);
+        DEBUG_LOG1(_L("Key size: %d"), keyListEntry->iKeySize);
+        DEBUG_LOG1(_L("Algorithm: %d"), keyListEntry->iKeyAlgorithm);
+
+        
+        
+        CleanupStack::PopAndDestroy(); //keyListEntry
+        
+        status = iPkiServiceApi->AttachCertificate(keyId,
+                                                   aParms.Deletable(),
+                                                   keyLength,
+                                                   EPKIRSA,
+                                                   aParms.Content());
+        }
+    else
+        {
+        status = iPkiServiceApi->StoreCertificate(ownerType,
+                                                  aParms.Deletable(),
+                                                  0, //Key length is undefined
+                                                  EPKIRSA,
+                                                  aParms.Content());            
+        }
+
+    if (status != KErrNone)
+        {
+        DEBUG_LOG1(_L("Operation failed with %d"), status);       
+        User::Leave(status);
+        }
+
+    certRef = BuildCertRefL(aParms.Content(), ETrue);
+    CleanupStack::PushL(certRef);
+    UpdateL(*certRef, aParms);
+    CleanupStack::Pop(certRef);
+    return certRef;
+    }
+
+void CDmAdCert::UpdateL(const TDesC8& aLuid, const CDmAdCertParms& aParms)
+    {
+    TRACE("CDmAdCert::UpdateL");
+    HBufC8* issuerName;
+    HBufC8* serialNumber;
+    GetIssuerAndSerialFromCertRefLC(aLuid, issuerName, serialNumber);
+
+    if (aParms.Type() == EPKICACertificate) // CA cert
+        {
+        UpdateTrustedL(*issuerName, *serialNumber, aParms);
+        UpdateApplicabilityL(*issuerName, *serialNumber, aParms);
+        }
+    
+    CleanupStack::PopAndDestroy(2); //serialNumber, issuerName
+    }
+    
+void CDmAdCert::FetchL(const TDesC8& aLuid, CDmAdCertParms& aParms)
+    {
+    TRACE("CDmAdCert::FetchL");
+    HBufC8* issuerName;
+    HBufC8* serialNumber;
+    GetIssuerAndSerialFromCertRefLC(aLuid, issuerName, serialNumber);
+    
+    //TInt certSize = 1024;
+    TInt certSize = 4096;
+    HBufC8* certBuf = NULL;
+    TPtr8 certBufDesc(NULL, 0);
+    TBool errBufferTooShortOccurred = EFalse;
+    for (;;)
+        {
+        if (certBuf)
+            {
+            CleanupStack::PopAndDestroy(certBuf);
+            }
+        certBuf = HBufC8::NewLC(certSize);
+        certBufDesc.Set(certBuf->Des());
+    
+        // Both user and device certificate stores needs to be used for
+        // certificate reading. Set certificate store type to STORETYPE_ANY.
+        TPkiServiceStoreType certStoreType(EPkiStoreTypeAny);
+        User::LeaveIfError(iPkiServiceApi->CertStoreType(certStoreType));
+        User::LeaveIfError(iPkiServiceApi->SetStoreType(STORE_CERTSTORE, EPkiStoreTypeAny));        
+        TInt err = iPkiServiceApi->ReadCertificate(*issuerName,
+                                                   *serialNumber,
+                                                   certBufDesc);
+                
+        // Set previous store type back
+        User::LeaveIfError(iPkiServiceApi->SetStoreType(STORE_CERTSTORE, certStoreType));                
+        
+        if (err == KErrNone)
+            {
+            break;
+            }
+        else if (err == KPKIErrBufferTooShort)
+            {
+            if (errBufferTooShortOccurred)
+                {
+                DEBUG_LOG(_L("Buffer too short"));                
+                User::Leave(KErrGeneral);
+                }
+            errBufferTooShortOccurred = ETrue;
+            User::LeaveIfError(iPkiServiceApi->GetRequiredBufferSize(certSize));
+            }
+        else
+            {
+            DEBUG_LOG1(_L("Fetch failed with %d"), err);            
+            User::Leave(err);
+            }
+        }
+
+    aParms.SetContentL(*certBuf);
+    ReadCertDetailsL(*issuerName, *serialNumber, aParms);
+
+    CleanupStack::PopAndDestroy(3); //certBuf, serialNumber, issuerName
+    }
+    
+void CDmAdCert::DeleteL(const TDesC8& aLuid)
+    {
+    TRACE("CDmAdCert::DeleteL");
+    HBufC8* issuerName;
+    HBufC8* serialNumber;
+    GetIssuerAndSerialFromCertRefLC(aLuid, issuerName, serialNumber);
+    while (FindCertLuidMappingElemL(aLuid))
+        {
+        User::LeaveIfError(iPkiServiceApi->RemoveCertificate(*issuerName,
+                                                             *serialNumber));
+        
+        RemoveCertLuidMappingElem(aLuid);
+        }
+    CleanupStack::PopAndDestroy(2); //serialNumber, issuerName
+    }
+
+void CDmAdCert::ListL(RPointerArray<HBufC8>& aLuidList)
+    {
+    TRACE("CDmAdCert::ListL");
+    for (TInt i=0; i<iCertLuidMapping->Count(); ++i)
+        {
+        CDmAdCertLuidMappingElem* certLuidMappingElem = iCertLuidMapping->At(i);
+                
+        HBufC8* luidElem = certLuidMappingElem->Luid().AllocLC();
+        aLuidList.AppendL(luidElem);
+        CleanupStack::Pop(luidElem);
+        }
+    }
+    
+//------------------------------------------------------------------------
+
+void CDmAdCert::ReadCertDetailsL(const TDesC8& aIssuerName, const TDesC8& aSerialNumber, CDmAdCertParms& aParms)
+    {
+    TRACE("CDmAdCert::ReadCertDetailsL");
+    TCertificateListEntry* entry = new (ELeave) TCertificateListEntry();
+    CleanupStack::PushL(entry);
+    
+    User::LeaveIfError(iPkiServiceApi->CertificateDetails(aIssuerName,
+                                                          aSerialNumber,
+                                                          *entry)); 
+    
+    aParms.SetType(entry->iOwnerType);    
+    aParms.SetDeletable(entry->iIsDeletable);
+       
+    TBool trusted = ETrue;
+    if (entry->iOwnerType == EPKICACertificate) // CA cert
+        {
+        User::LeaveIfError(iPkiServiceApi->Trusted(aIssuerName,
+                                                   aSerialNumber,
+                                                   trusted));        
+        }
+    aParms.SetTrusted(trusted);
+
+    if (entry->iOwnerType == EPKICACertificate) // CA cert
+        {
+        RArray<TUid> applications;
+        CleanupClosePushL(applications);
+        
+        iPkiServiceApi->ApplicationsL(aIssuerName,
+                                      aSerialNumber,
+                                      applications);
+        aParms.SetApplicabilityL(applications);                                      
+        CleanupStack::PopAndDestroy(); //applications
+        }    
+        
+    CleanupStack::PopAndDestroy(); // entry        
+    }
+    
+void CDmAdCert::UpdateTrustedL(const TDesC8& aIssuerName, const TDesC8& aSerialNumber, const CDmAdCertParms& aParms)
+    {
+    TRACE("CDmAdCert::UpdateTrustedL");
+    
+    User::LeaveIfError(iPkiServiceApi->SetTrust(aIssuerName,
+                                                aSerialNumber,
+                                                aParms.Trusted()));
+    }
+
+void CDmAdCert::UpdateApplicabilityL(const TDesC8& aIssuerName, const TDesC8& aSerialNumber, const CDmAdCertParms& aParms)
+    {
+    TRACE("CDmAdCert::UpdateApplicabilityL");
+    
+    const RArray<TUid>& applications = aParms.Applicability();   
+    if (applications.Count() > 0)
+        {
+        iPkiServiceApi->SetApplicabilityL(aIssuerName,
+                                          aSerialNumber,
+                                          applications);
+        }
+    }
+
+TPtrC8 CDmAdCert::AppendCertLuidMappingElemL(const TDesC8& aIssuerName, const TDesC8& aSerialNumber)
+    {
+    TRACE("CDmAdCert::AppendCertLuidMappingElemL");
+    TPtrC8 luid(KNullDesC8);
+    
+    CDmAdCertLuidMappingElem* certLuidMappingElem = CDmAdCertLuidMappingElem::NewLC(aIssuerName, aSerialNumber);
+    luid.Set(certLuidMappingElem->Luid());
+    
+    iCertLuidMapping->AppendL(certLuidMappingElem);
+    CleanupStack::Pop(certLuidMappingElem);
+    
+    return luid;
+    }
+
+void CDmAdCert::RemoveCertLuidMappingElem(const TDesC8& aLuid)
+    {
+    TRACE("CDmAdCert::RemoveCertLuidMappingElem");
+    for (TInt i=0; i<iCertLuidMapping->Count(); ++i)
+        {
+        CDmAdCertLuidMappingElem* certLuidMappingElem = iCertLuidMapping->At(i);
+        if (certLuidMappingElem->Luid().Compare(aLuid) == 0)
+            {
+            iCertLuidMapping->Delete(i);
+            i--;
+            delete certLuidMappingElem;
+            break;
+            }
+        }
+    }
+
+CDmAdCertLuidMappingElem* CDmAdCert::FindCertLuidMappingElemL(const TDesC8& aLuid)
+    {
+    TRACE("CDmAdCert::FindCertLuidMappingElemL");
+    for (TInt i=0; i<iCertLuidMapping->Count(); ++i)
+        {
+        CDmAdCertLuidMappingElem* certLuidMappingElem = iCertLuidMapping->At(i);
+        if (certLuidMappingElem->Luid().Compare(aLuid) == 0)
+            {
+            return certLuidMappingElem;
+            }
+        }
+    return NULL;
+    }
+
+void CDmAdCert::BuildCertLuidMappingTableL()
+    {
+    TRACE("CDmAdCert::BuildCertLuidMappingTableL");
+    CArrayFix<TCertificateListEntry>* certList;
+    iPkiServiceApi->ListCertificatesL(certList);
+    CleanupStack::PushL(certList);
+
+    for (TInt i=0; i<certList->Count(); ++i)
+        {
+        TCertificateListEntry& entry = certList->At(i);
+        AppendCertLuidMappingElemL(entry.iTrustedAuthority, entry.iSerialNumber);
+        }
+    
+    CleanupStack::PopAndDestroy(certList); 
+    }
+
+HBufC8* CDmAdCert::BuildCertRefL(const TDesC8& aCertificateDer, TBool aAppend)
+    {
+    TRACE("CDmAdCert::BuildCertRefL");
+    
+    CX509Certificate* certCx509 = CX509Certificate::NewL(aCertificateDer);
+    CleanupStack::PushL(certCx509);
+
+    const TPtrC8 issuerName(*(certCx509->DataElementEncoding(CX509Certificate::EIssuerName)));
+    const TPtrC8 serialNumber(*(certCx509->DataElementEncoding(CX509Certificate::ESerialNumber)));
+
+    HBufC8* certRef = 0;
+    if (aAppend)
+        {
+        TPtrC8 luid(AppendCertLuidMappingElemL(issuerName, serialNumber));
+        certRef = luid.AllocL();
+        }
+    else
+        {
+        certRef = CDmAdCertLuidMappingElem::BuildLuidL(issuerName, serialNumber);
+        }
+
+    CleanupStack::PopAndDestroy(certCx509);
+    return certRef;
+    }
+
+void CDmAdCert::GetIssuerAndSerialFromCertRefLC(const TDesC8&  aCertRef,
+                                                HBufC8*&       aIssuerName,
+                                                HBufC8*&       aSerialNumber)
+    {
+    CDmAdCertLuidMappingElem* certLuidMappingElem = FindCertLuidMappingElemL(aCertRef);
+    if (!certLuidMappingElem)
+        {
+        DEBUG_LOG(_L("Mapping not found"));        
+        User::Leave(KErrNotFound);
+        }
+
+    HBufC8* issuerNameHBuf = certLuidMappingElem->IssuerName().AllocLC();
+    HBufC8* serialNumberHBuf = certLuidMappingElem->SerialNumber().AllocLC();
+    
+    aIssuerName = issuerNameHBuf;
+    aSerialNumber = serialNumberHBuf;
+    }
+
+HBufC8* CDmAdCert::CertSubjectNameL(const TDesC8& aCertificateDer)
+    {
+    CX509Certificate* certCx509 = CX509Certificate::NewLC(aCertificateDer);
+    HBufC16* subjectName16 = certCx509->SubjectName().DisplayNameL();
+    CleanupStack::PushL(subjectName16);    
+    HBufC8* subjectName8 = HBufC8::NewL(subjectName16->Length());
+    subjectName8->Des().Copy(*subjectName16);
+    CleanupStack::PopAndDestroy(2, certCx509);
+    return subjectName8;
+    }