diff -r 000000000000 -r 33413c0669b9 vpnengine/dmadpki/src/dmadstorecert.cpp --- /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 + +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(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& aLuidList) + { + TRACE("CDmAdCert::ListL"); + for (TInt i=0; iCount(); ++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 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& 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; iCount(); ++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; iCount(); ++i) + { + CDmAdCertLuidMappingElem* certLuidMappingElem = iCertLuidMapping->At(i); + if (certLuidMappingElem->Luid().Compare(aLuid) == 0) + { + return certLuidMappingElem; + } + } + return NULL; + } + +void CDmAdCert::BuildCertLuidMappingTableL() + { + TRACE("CDmAdCert::BuildCertLuidMappingTableL"); + CArrayFix* certList; + iPkiServiceApi->ListCertificatesL(certList); + CleanupStack::PushL(certList); + + for (TInt i=0; iCount(); ++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; + }