--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/wim/WimServer/src/WimCertUtil.cpp Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,1311 @@
+/*
+* Copyright (c) 2002-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: Utility functions for certificate related functionality
+*
+*/
+
+
+
+#include "WimCertUtil.h"
+#include "WimTrace.h"
+#include "WimCertInfo.h"
+#include "WimUtilityFuncs.h"
+#include "WimCleanup.h"
+#include <cctcertinfo.h>
+#include <asn1dec.h> // ASN.1 decoding
+
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::CWimCertUtil()
+// Default constructor
+// -----------------------------------------------------------------------------
+CWimCertUtil::CWimCertUtil( MCTToken& aToken )
+ : CActive( EPriorityStandard ),
+ iToken( aToken )
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::NewL()
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+CWimCertUtil* CWimCertUtil::NewL( MCTToken& aToken )
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::NewL" ) );
+ CWimCertUtil* self = new( ELeave ) CWimCertUtil( aToken );
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self ); //self
+ return self;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::ConstructL()
+// Second phase
+// -----------------------------------------------------------------------------
+void CWimCertUtil::ConstructL()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::ConstructL" ) );
+ CActiveScheduler::Add( this );
+ iWimUtilFuncs = CWimUtilityFuncs::NewL();
+ _WIMTRACE ( _L( "CWimCertUtil::ConstructL() completed" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::Restore()
+// Returns CCTCertInfo objects in array
+// -----------------------------------------------------------------------------
+void CWimCertUtil::Restore( RPointerArray<CWimCertInfo>& aArray,
+ TRequestStatus& aStatus )
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::Restore" ) );
+ iClientStatus = &aStatus;
+ aStatus = KRequestPending;
+ iArray = &aArray;
+ iPhase = EListCertsFromWim;
+ SignalOwnStatusAndComplete();
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::CancelRestore()
+// Cancels outgoing Restore operation. Sets an internal flag to true.
+// After necessary cleanup, caller is signalled with KErrCancel
+// -error code.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::CancelRestore()
+ {
+ _WIMTRACE ( _L( "CWimCertUtil::CancelRestore" ) );
+ Cancel();
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::RetrieveCertByIndexL()
+// Retrieves the actual certificate.
+// -----------------------------------------------------------------------------
+
+void CWimCertUtil::RetrieveCertByIndexL( const TInt aIndex,
+ TDes8& aEncodedCert,
+ TRequestStatus& aStatus )
+ {
+ _WIMTRACE ( _L( "WimServer|CWimCertUtil::RetrieveCertByIndexL" ) );
+ //Check that index is valid
+ __ASSERT_ALWAYS( aIndex <= iArraySize && iCertRefLst,
+ User::Leave( KErrArgument ) );
+ iClientStatus = &aStatus;
+ iCertRetrieveIndex = aIndex;
+ iEncodedCert = &aEncodedCert;
+ aStatus = KRequestPending;
+ iPhase = ERetrieveCertificate;
+ SignalOwnStatusAndComplete();
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::SignalOwnStatusAndComplete()
+// Sets own iStatus to KRequestPending, and signals it
+// with User::RequestComplete() -request. This gives chance
+// active scheduler to run other active objects. After a quick
+// visit in active scheduler, signal returns to RunL() and starts next
+// phase of operation.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::SignalOwnStatusAndComplete()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::SignalOwnStatusAndComplete()" ) );
+ iStatus = KRequestPending;
+ SetActive();
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::~CWimCertUtil()
+// Allocated memory is released.
+// -----------------------------------------------------------------------------
+CWimCertUtil::~CWimCertUtil()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::~CWimCertUtil()" ) );
+ Cancel();
+ DeallocWimCertInfo();
+ DeallocCertHBufs();
+ DeallocReferences();
+ delete iTrustedUsages;
+ delete iTrustedUsagesPtr;
+ delete iKeyIdBuf;
+ delete iKeyIdPointer;
+ delete iWimUtilFuncs;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::RunL()
+// This has eight different phases which are explained here:
+// 1. EListCertsFromWim:Allocate member variables for arrays usage.
+// Array is passed as an argument to server and it is filled with
+// certificate information found from WIM.
+// 2. ECreateNewCertObjects: New certificate objects are created based on
+// received information on step one. A little bit of conversion is
+// required. Objects are inserted to an array.
+// 3. ERetrieveCertificate:Allocate member variables for struct,
+// which is used to fetch certificate details
+// 4. ERetrievingCompleted: Check cancellation. If not cancelled,
+// copy information to caller's buffer.
+// 5. EAddCertificate: Adds certificate to WIM.
+// 6. EAddCertificateCompleted: Certificate is added successfully. Deallocate
+// variables and complete request.
+// 7. ERemove: Before removing, we will check for cancellation. After that
+// cancellation is too late.
+// 8. ERemoveCompleted: Removal operation completed ok. Deallocte variables and
+// complete request
+// 9. EGetCertExtras: Extra data is fetched and async. waiter needs to be
+// stopped
+// -----------------------------------------------------------------------------
+void CWimCertUtil::RunL()
+ {
+ _WIMTRACE3(_L("WimServer|CWimCertUtil::RunL(), iStatus=%d, iPhase=%d"), iStatus.Int(), iPhase);
+ //Check for error
+ if ( iStatus.Int() != KErrNone )
+ {
+ //failed to retrieve certificate
+ if ( iPhase == ERetrievingCompleted )
+ {
+ DeallocCertHBufs();
+ _WIMTRACE2 ( _L( "CWimCertUtil::RunL() failed to retrieve \
+ certificate, ERROR = %d" ),iStatus.Int() );
+ }
+
+ User::RequestComplete( iClientStatus, iStatus.Int() );
+ }
+ else
+ {
+ switch( iPhase )
+ {
+ case EListCertsFromWim: //get certificates from WIM.
+ {
+ if ( iArraySize ) //Delete previous preferences.
+ { //User might added or removed a certificate.
+ DeallocWimCertInfo();
+ DeallocReferences();
+ }
+
+ //Ok ready to begin. First get Cert count
+ iCertCount = CertCount( EWimEntryTypeAll );
+ _WIMTRACE2 ( _L( "CWimCertUtil::RunL() \
+ certCount =%d" ),iCertCount );
+ if ( !iCertCount )
+ {
+ User::RequestComplete( iClientStatus, KErrNotFound );
+ }
+ else
+ {
+ __ASSERT_DEBUG( iCertRefLst == NULL, User::Invariant() );
+ iCertRefLst = new( ELeave ) TCertificateAddress[iCertCount];
+
+ //Creates new array according to certificate count
+ __ASSERT_DEBUG( iCertInfoArr == NULL, User::Invariant() );
+ iCertInfoArr = new( ELeave ) TWimCertInfo[iCertCount];
+
+ AllocWimCertInfoL( iCertInfoArr, iCertCount );
+ iStatus = KRequestPending;
+
+ CertRefLstL( iCertRefLst,
+ iCertInfoArr,
+ EWimEntryTypeAll );
+
+ iPhase = ECreateNewCertObjects;
+ iIndex = 0;
+ SetActive();
+
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+
+ _WIMTRACE( _L( "CWimCertUtil::RunL() \
+ GetCertRefLst" ) );
+ }
+ break;
+ }
+ case ECreateNewCertObjects: //Certificates fetched,
+ {
+ CreateNewCertObjectsL();//create new cert-objects
+ break;
+ }
+ case EGetTrustedUsages:
+ {
+ GetTrustedUsagesL();
+ break;
+ }
+ case ETrustedUsagesDone:
+ {
+ TrustedUsagesDoneL();
+ break;
+ }
+ case ECertObjectsDone:
+ {
+ User::RequestComplete( iClientStatus, KErrNone );
+ _WIMTRACE ( _L( "CWimCertUtil::RunL() \
+ ECertObjectsDone" ) );
+ break;
+ }
+ case ERetrieveCertificate: //Get Cert details from WIM
+ {
+ AllocMemoryForCertDetailsL();
+ CertDetailsL( iCertRefLst[iCertRetrieveIndex],
+ iWimCertDetails );
+ iPhase = ERetrievingCompleted;
+ SetActive();
+
+ TRequestStatus* status = &iStatus;
+ User::RequestComplete( status, KErrNone );
+
+ _WIMTRACE ( _L( "CWimCertUtil::RunL() \
+ ERetrieveCertificate" ) );
+ break;
+ }
+ case ERetrievingCompleted: //Cert details fetched, check errors &
+ { //cancellations & complete request
+ //copy cert details to iEncodedCert -buffer,
+ //which points to received aEncoded -cert buffer.
+ CopyRetrievedCertData();
+ DeallocCertHBufs();
+ User::RequestComplete( iClientStatus, KErrNone );
+ _WIMTRACE ( _L( "CWimCertUtil::RunL() \
+ ERetrievingCompleted" ) );
+ break;
+ }
+
+ default:
+ {
+ User::RequestComplete( iClientStatus, KErrNotSupported );
+ break;
+ }
+ }
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::CreateNewCertObjectsL()
+// Creates new certificate objects which can be returned to the caller.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::CreateNewCertObjectsL()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::CreateNewCertObjectsL() | Begin" ) );
+
+ HBufC16* label16 = NULL;
+ HBufC8* hash8 = NULL;
+
+ if ( iIndex < iCertCount )
+ {
+ TCertificateOwnerType certificateType;
+ if ( iCertInfoArr[iIndex].iUsage == 0 )
+ {
+ certificateType = EUserCertificate; // 0 == User
+ }
+ else
+ {
+ certificateType = ECACertificate; // 1 == CA
+ }
+
+ label16 = HBufC16::NewLC( iCertInfoArr[iIndex].iLabel.Length() );
+ label16->Des().Copy( iCertInfoArr[iIndex].iLabel );
+
+ hash8 = HBufC8::NewLC( iCertInfoArr[iIndex].iIssuerHash.Length() );
+ hash8->Des().Copy( iCertInfoArr[iIndex].iIssuerHash );
+ // Convert type
+ TCertificateFormat format;
+ format = GetCertFormatByIndex( iIndex );
+ //Create key indentifiers
+ TKeyIdentifier subjectKeyId;
+ TKeyIdentifier issuerKeyId;
+ //needs these for CCTCertInfo object -creation
+ subjectKeyId = iCertInfoArr[iIndex].iKeyId;
+ issuerKeyId = iCertInfoArr[iIndex].iCAId;
+ //Create CCTCertInfo object.
+ if ( iCertInfoArr[iIndex].iIssuerHash.Length() > 0 )
+ {
+ iCert = CCTCertInfo::NewL( label16->Des(),
+ format,
+ certificateType,
+ iCertInfoArr[iIndex].iCertlen,
+ &subjectKeyId,
+ &issuerKeyId,
+ iToken,
+ iIndex,
+ iCertInfoArr[iIndex].iModifiable,
+ hash8 );
+ }
+ else
+ {
+ iCert = CCTCertInfo::NewL( label16->Des(),
+ format,
+ certificateType,
+ iCertInfoArr[iIndex].iCertlen,
+ &subjectKeyId,
+ &issuerKeyId,
+ iToken,
+ iIndex,
+ iCertInfoArr[iIndex].iModifiable );
+ }
+
+ CleanupStack::PopAndDestroy( hash8 );
+ CleanupStack::PopAndDestroy( label16 );
+
+ iOids = new( ELeave ) RArray<HBufC*>();
+ //Check whether certificate has extra data. Certificate type must be
+ // X509
+ if ( iCertInfoArr[iIndex].iCDFRefs &&
+ iCertInfoArr[iIndex].iType == WIMI_CT_X509 )
+ {
+ iPhase = EGetTrustedUsages;
+ }
+ else
+ {
+ CreateNewWimCertObjectL();
+ }
+ }
+ else
+ {
+ DeallocWimCertInfo();
+ iPhase = ECertObjectsDone;
+ }
+ SignalOwnStatusAndComplete();
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::CreateNewWimCertObjectL()
+//
+// -----------------------------------------------------------------------------
+void CWimCertUtil::CreateNewWimCertObjectL()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::CreateNewWimCertObjectL()" ) );
+
+ iCertInfo = CWimCertInfo::NewL( iCert, //CCTCertInfo object
+ iCert->SubjectKeyId(), //key hash
+ *iOids,
+ iCertInfoArr[iIndex].iCDFRefs );
+
+ delete iOids;
+ iOids = NULL;
+
+ //Append WimCertInfo -object to array. Ownership to iArray here.
+ User::LeaveIfError( iArray->Append( iCertInfo ) );
+
+ iPhase = ECreateNewCertObjects;
+ iIndex++;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::GetTrustedUsagesL
+// Get trusted usages (OIDs) of a current certificate, which is pointed out
+// by a index
+// -----------------------------------------------------------------------------
+void CWimCertUtil::GetTrustedUsagesL()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::GetTrustedUsagesL() | Begin" ) );
+
+ delete iTrustedUsages;
+ iTrustedUsages = NULL;
+ delete iTrustedUsagesPtr;
+ iTrustedUsagesPtr = NULL;
+ //Allocate variables for trusted usage fetching
+ iTrustedUsages = HBufC::NewL( iCertInfoArr[iIndex].iTrustedUsageLength );
+ iTrustedUsagesPtr = new( ELeave ) TPtr( iTrustedUsages->Des() );
+
+ iCertExtrasInfo.iTrustedUsage = iTrustedUsagesPtr;
+ iPhase = ETrustedUsagesDone;
+
+ delete iKeyIdBuf;
+ iKeyIdBuf = NULL;
+ delete iKeyIdPointer;
+ iKeyIdPointer = NULL;
+ // Take a copy of key identifier
+ iKeyIdBuf = iCertInfoArr[iIndex].iKeyId.AllocL();
+ iKeyIdPointer = new( ELeave ) TPtr8( iKeyIdBuf->Des() );
+
+ GetCertExtrasL( iKeyIdPointer,
+ iCertExtrasInfo,
+ iCertInfoArr[iIndex].iUsage,
+ iStatus );
+ SetActive();
+ _WIMTRACE ( _L( "CWimCertUtil::GetTrustedUsagesL() | End" ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::TrustedUsagesDoneL()
+// -----------------------------------------------------------------------------
+void CWimCertUtil::TrustedUsagesDoneL()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::TrustedUsagesDoneL()" ) );
+ if ( iStatus.Int() == KErrNone )
+ {
+ //Parse oids and put them to an array
+ TLex16 lex( *iTrustedUsages );
+ TPtrC16 lexToken;
+ for ( TBool extrasDone = EFalse; extrasDone == EFalse; )
+ {
+ lexToken.Set( lex.NextToken() );
+ if ( lexToken.Length() )
+ {
+ HBufC* oid = lexToken.AllocLC();
+ User::LeaveIfError( iOids->Append( oid ) );
+ CleanupStack::Pop( oid ); //oid
+ }
+ else
+ {
+ extrasDone = ETrue;
+ }
+ }
+ CreateNewWimCertObjectL();
+ SignalOwnStatusAndComplete();
+ }
+ else
+ {
+ User::RequestComplete( iClientStatus, iStatus.Int() );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::GetCertFormatByIndex()
+// Returns certificate format according to received index
+// -----------------------------------------------------------------------------
+TCertificateFormat CWimCertUtil::GetCertFormatByIndex( TInt aIndex )
+ {
+ _WIMTRACE ( _L( "WimServer|CWimCertUtil::GetCertFormatByIndex()" ) );
+
+ // Convert type
+ TCertificateFormat format;
+ switch ( iCertInfoArr[aIndex].iType )
+ {
+ case WIMI_CT_WTLS:
+ {
+ format = EWTLSCertificate;
+ break;
+ }
+ case WIMI_CT_X509:
+ {
+ format = EX509Certificate;
+ break;
+ }
+ case WIMI_CT_X968:
+ {
+ format = EX968Certificate;
+ break;
+ }
+ case WIMI_CT_URL:
+ {
+ format = EX509CertificateUrl;
+ break;
+ }
+ default:
+ {
+ format = EUnknownCertificate;
+ break;
+ }
+ }
+ return format;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::DoCancel()
+// Deallocates member variables and completes client status with
+// KErrCancel error code.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::DoCancel()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::DoCancel()" ) );
+
+ if ( iPhase == EGetTrustedUsages || iPhase == ETrustedUsagesDone )
+ {
+ iCert->Release();
+ }
+
+ DeallocWimCertInfo();
+ DeallocCertHBufs();
+ DeallocReferences();
+ User::RequestComplete( iClientStatus, KErrCancel );
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::RunError()
+//
+// The active scheduler calls this function if this active object's RunL()
+// function leaves. This gives this active object the opportunity to perform
+// any necessary cleanup.
+// After array's cleanup, complete request with received error code.
+// -----------------------------------------------------------------------------
+TInt CWimCertUtil::RunError( TInt aError )
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::RunError Error = %d" ) );
+ DeallocWimCertInfo();
+ DeallocCertHBufs();
+ delete iTrustedUsages;
+ iTrustedUsages = NULL;
+ delete iTrustedUsagesPtr;
+ iTrustedUsagesPtr = NULL;
+ delete iKeyIdBuf;
+ iKeyIdBuf = NULL;
+ delete iKeyIdPointer;
+ iKeyIdPointer = NULL;
+
+ User::RequestComplete( iClientStatus, aError );
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::AllocWimCertInfoL()
+// Allocates memory for the array which is filled by server.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::AllocWimCertInfoL(
+ TWimCertInfo* aWimCertInfoArr,
+ TInt aCount )
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::AllocWimCertInfoL()" ) );
+
+ TUint8 index;
+ //These are arrays
+ iLabel = new( ELeave ) PHBufC8[aCount];
+ iKeyId = new( ELeave ) PHBufC8[aCount];
+ iCAId = new( ELeave ) PHBufC8[aCount];
+ iIssuerHash = new( ELeave ) PHBufC8[aCount];
+
+ iLabelPtr = new( ELeave ) PTPtr8[aCount];
+ iKeyIdPtr = new( ELeave ) PTPtr8[aCount];
+ iCAIdPtr = new( ELeave ) PTPtr8[aCount];
+ iIssuerHashPtr = new( ELeave ) PTPtr8[aCount];
+
+ for ( index = 0; index < aCount ; index++ )
+ {
+ iLabel[index] = HBufC8::NewL( KLabelLen );
+ iKeyId[index] = HBufC8::NewL( KKeyIdLen );
+ iCAId[index] = HBufC8::NewL( KPkcs15IdLen );
+ iIssuerHash[index] = HBufC8::NewL( KIssuerHash );
+
+ iLabelPtr[index] = new( ELeave ) TPtr8( iLabel[index]->Des() );
+ iKeyIdPtr[index] = new( ELeave ) TPtr8( iKeyId[index]->Des() );
+ iCAIdPtr[index] = new( ELeave ) TPtr8( iCAId[index]->Des() );
+ iIssuerHashPtr[index] = new( ELeave )
+ TPtr8( iIssuerHash[index]->Des() );
+
+ aWimCertInfoArr[index].iLabel.Copy( iLabelPtr[index]->Ptr(),
+ iLabelPtr[index]->Length() );
+ aWimCertInfoArr[index].iKeyId.Copy( iKeyIdPtr[index]->Ptr(),
+ iKeyIdPtr[index]->Length() );
+ aWimCertInfoArr[index].iCAId.Copy( iCAIdPtr[index]->Ptr(),
+ iCAIdPtr[index]->Length() );
+ aWimCertInfoArr[index].iIssuerHash.Copy(
+ iIssuerHashPtr[index]->Ptr(), iIssuerHashPtr[index]->Length() );
+ }
+ iArraySize = aCount;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::AllocMemoryForCertDetailsL()
+// Allocates memory for a struct which is filled by server.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::AllocMemoryForCertDetailsL()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::AllocMemoryForCertDetailsL()" ) );
+ iCertHBufOne = HBufC8::NewL( iEncodedCert->MaxLength() ); //whole cert
+ iCertHBufOnePtr = new( ELeave ) TPtr8( iCertHBufOne->Des() );
+ iWimCertDetails.iCert = iCertHBufOnePtr;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::CopyRetrievedCertData()
+// Writes data to caller's buffer by using pointer.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::CopyRetrievedCertData()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::CopyRetrievedCertData()" ) );
+ TPtr8 ptr = iCertHBufOne->Des();
+ iEncodedCert->Copy( ptr );
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::DeallocCertHBufs()
+// DeAllocates memory from member variables, which are used
+// when communicating with WIM.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::DeallocCertHBufs()
+ {
+ _WIMTRACE ( _L( "WimServer|CWimCertUtil::DeallocCertHBufs()" ) );
+ if ( iCertHBufOne )
+ {
+ delete iCertHBufOne;
+ delete iCertHBufOnePtr;
+ iCertHBufOne = NULL;
+ iCertHBufOnePtr = NULL;
+ }
+ if ( iCertHBufTwo )
+ {
+ delete iCertHBufTwo;
+ delete iCertHBufTwoPtr;
+ iCertHBufTwo = NULL;
+ iCertHBufTwoPtr = NULL;
+ }
+ if ( iCertHBufThree )
+ {
+ delete iCertHBufThree;
+ delete iCertHBufThreePtr;
+ iCertHBufThree = NULL;
+ iCertHBufThreePtr = NULL;
+ }
+ if ( iCertHBufFour )
+ {
+ delete iCertHBufFour;
+ delete iCertHBufFourPtr;
+ iCertHBufFour = NULL;
+ iCertHBufFourPtr = NULL;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::DeallocReferences()
+// Deallocates memory. If user has cancelled initialization process, we need
+// to dealloc our references to loaded certs.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::DeallocReferences()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::DeallocReferences()" ) );
+ if ( iCertRefLst )
+ {
+ for( TInt index = 0; index < iCertCount; ++index )
+ {
+ WIMI_Ref_t* ref = reinterpret_cast< WIMI_Ref_t* >( iCertRefLst[ index ] );
+ _WIMTRACE2( _L( "WimServer|CWimCertUtil::DeallocReferences(), -ref 0x%08x" ), ref );
+ free_WIMI_Ref_t( ref );
+ iCertRefLst[ index ] = 0;
+ }
+ delete[] iCertRefLst;
+ iCertRefLst = NULL;
+ }
+ if ( iCertInfoArr )
+ {
+ delete iCertInfoArr;
+ iCertInfoArr = NULL;
+ }
+ iArraySize = 0;
+ iArray = NULL;
+ iCertCount = 0;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::DeallocWimCertInfo()
+// Deallocates memory. If something has leaved during asynchronous request, we
+// will deallocate all member data.
+// -----------------------------------------------------------------------------
+void CWimCertUtil::DeallocWimCertInfo()
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::DeallocWimCertInfo()" ) );
+ TUint8 index;
+ for ( index = 0; index < iArraySize; index ++ )
+ {
+ if ( iLabel )
+ {
+ delete iLabel[index];
+ }
+ if ( iKeyId )
+ {
+ delete iKeyId[index];
+ }
+ if ( iCAId )
+ {
+ delete iCAId[index];
+ }
+ if ( iIssuerHash )
+ {
+ delete iIssuerHash[index];
+ }
+ if ( iLabelPtr )
+ {
+ delete iLabelPtr[index];
+ }
+ if ( iKeyIdPtr )
+ {
+ delete iKeyIdPtr[index];
+ }
+ if ( iCAIdPtr )
+ {
+ delete iCAIdPtr[index];
+ }
+ if ( iIssuerHashPtr )
+ {
+ delete iIssuerHashPtr[index];
+ }
+ }
+
+ delete iLabel;
+ delete iKeyId;
+ delete iCAId;
+ delete iIssuerHash;
+ delete iLabelPtr;
+ delete iKeyIdPtr;
+ delete iCAIdPtr;
+ delete iIssuerHashPtr;
+ iLabel = NULL;
+ iKeyId = NULL;
+ iCAId = NULL;
+ iIssuerHash = NULL;
+ iLabelPtr = NULL;
+ iKeyIdPtr = NULL;
+ iCAIdPtr = NULL;
+ iIssuerHashPtr = NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::CertCount
+// Get count of certificate in WIM
+// -----------------------------------------------------------------------------
+//
+TUint8 CWimCertUtil::CertCount( TWimEntryType aType )
+ {
+ _WIMTRACE( _L( "WimServer|CWimCertUtil::DeallocWimCertInfo()" ) );
+ WIMI_STAT callStatus = WIMI_Ok;
+
+ WIMI_Ref_t* wimRef = NULL;
+ TUint8 certCount = 0;
+
+ wimRef = WIMI_GetWIMRef( 0 );
+
+ if ( wimRef )
+ {
+ if ( aType == EWimEntryTypeAll || aType == EWimEntryTypeCA )
+ {
+ callStatus = GetCertificateCountByWIM( wimRef,
+ certCount,
+ WIMI_CU_CA );
+ }
+
+ if ( callStatus == WIMI_Ok && ( aType == EWimEntryTypeAll ||
+ aType == EWimEntryTypePersonal ) )
+ {
+ callStatus = GetCertificateCountByWIM( wimRef,
+ certCount,
+ WIMI_CU_Client );
+ }
+
+ free_WIMI_Ref_t( wimRef );
+ }
+ else
+ {
+ certCount = 0;
+ }
+
+ return certCount;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::CertRefLstL
+//
+// -----------------------------------------------------------------------------
+//
+void CWimCertUtil::CertRefLstL(
+ TCertificateAddressList aCertAddrLst,
+ TWimCertInfo* aCertInfoArr,
+ TWimEntryType aCertEntryType )
+ {
+
+ WIMI_STAT callStatus = WIMI_Ok;
+ TUint8 certNum = 0;
+ WIMI_Ref_t* wimRef = NULL;
+
+ wimRef = WIMI_GetWIMRef( 0 );
+
+ if ( wimRef )
+ {
+ CleanupPushWimRefL( wimRef );
+
+ if ( aCertEntryType == EWimEntryTypeAll ||
+ aCertEntryType == EWimEntryTypeCA )
+ {
+ callStatus = GetCertificateFromWimRefL( wimRef,
+ WIMI_CU_CA,
+ certNum,
+ aCertAddrLst,
+ aCertInfoArr );
+ }
+ if ( callStatus == WIMI_Ok &&
+ ( aCertEntryType == EWimEntryTypeAll ||
+ aCertEntryType == EWimEntryTypePersonal ) )
+ {
+ callStatus = GetCertificateFromWimRefL( wimRef,
+ WIMI_CU_Client,
+ certNum,
+ aCertAddrLst,
+ aCertInfoArr );
+ }
+
+ CleanupStack::PopAndDestroy( wimRef );
+ }
+ else
+ {
+ callStatus = WIMI_ERR_OutOfMemory;
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::GetCertExtrasL
+//
+// -----------------------------------------------------------------------------
+//
+void CWimCertUtil::GetCertExtrasL(
+ const TPtr8* aKeyId,
+ TCertExtrasInfo& aCertExtrasInfo,
+ TUint aUsage,
+ TRequestStatus& aStatus )
+ {
+ WIMI_STAT callStatus = WIMI_Ok;
+ TInt8 certUsage = 0;
+
+ TPtrC8 keyID( aKeyId->Ptr(), aKeyId->Length() );
+
+ WIMI_Ref_t* wimTempRef = WIMI_GetWIMRef( 0 );
+
+ if ( wimTempRef )
+ {
+ CleanupPushWimRefL( wimTempRef );
+
+ switch ( aUsage )
+ {
+ case EWimEntryTypeCA:
+ {
+ certUsage = WIMI_CU_CA;
+ break;
+ }
+ case EWimEntryTypeAll: //Flow through
+ case EWimEntryTypePersonal:
+ {
+ certUsage = WIMI_CU_Client;
+ break;
+ }
+ default:
+ {
+ callStatus = WIMI_ERR_BadParameters;
+ break;
+ }
+ }
+
+ if ( callStatus == WIMI_Ok )
+ {
+ callStatus = GetExtrasFromWimRefL( wimTempRef,
+ certUsage,
+ keyID,
+ aCertExtrasInfo );
+ }
+
+ CleanupStack::PopAndDestroy( wimTempRef );
+ }
+ else
+ {
+ callStatus = WIMI_ERR_BadReference;
+ }
+
+ TRequestStatus* status = &aStatus;
+ User::RequestComplete( status, iWimUtilFuncs->MapWIMError( callStatus ) );
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::CertDetailsL
+//
+// -----------------------------------------------------------------------------
+//
+void CWimCertUtil::CertDetailsL(
+ const TCertificateAddress aCertAddr,
+ TWimCertDetails& aWimCertDetails )
+ {
+ WIMI_STAT callStatus = WIMI_Ok;
+ WIMI_TransactId_t trId = ( void* )EInitializationCertListHashing;
+
+ WIMI_BinData_t ptCertData;
+ ptCertData.pb_buf = NULL;
+ ptCertData.ui_buf_length = 0;
+
+ callStatus = WIMI_CertificateReqT( trId, ( void* )aCertAddr, &ptCertData );
+
+ if ( callStatus == WIMI_Ok )
+ {
+ // Now we have certificate data, copy it to allocated buffer
+ if( aWimCertDetails.iCert->MaxLength() < ptCertData.ui_buf_length )
+ {
+ WSL_OS_Free( ptCertData.pb_buf );
+ User::Leave( KErrOverflow );
+ }
+ aWimCertDetails.iCert->Copy( ptCertData.pb_buf,
+ ptCertData.ui_buf_length );
+ WSL_OS_Free( ptCertData.pb_buf );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertUtil::GetCertificateCountByWIM
+// Fetches count of certicates in certain WIM card.
+// -----------------------------------------------------------------------------
+//
+WIMI_STAT CWimCertUtil::GetCertificateCountByWIM(
+ WIMI_Ref_t* aRef,
+ TUint8& aCertCount,
+ TUint8 aUsage ) const
+ {
+ _WIMTRACE(_L("WIM | WIMServer | CWimCertUtil::GetCertificateCountByWIM | Begin"));
+ TUint8 certNum = 0;
+ WIMI_RefList_t refList ;
+ WIMI_STAT callStatus = WIMI_GetCertificateListByWIM( aRef,
+ aUsage,
+ &certNum,
+ &refList );
+ if ( callStatus == WIMI_Ok )
+ {
+ aCertCount = ( TUint8 )( aCertCount + certNum );
+ }
+ free_WIMI_RefList_t( refList );
+ return callStatus;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetExtrasFromWimRefL
+// Fetches extra information (e.g. certs trusted usage) from the WIM card.
+// -----------------------------------------------------------------------------
+//
+WIMI_STAT CWimCertUtil::GetExtrasFromWimRefL(
+ WIMI_Ref_t* aTmpWimRef,
+ TInt8 aUsage,
+ TDesC8& aKeyHash,
+ TCertExtrasInfo& aCertExtrasInfo ) const
+ {
+ _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::GetExtrasFromWimRefL | Begin"));
+
+ TUint8 tempCertCount = 0;
+ WIMI_RefList_t certRefList = NULL;
+ WIMI_STAT callStatus = WIMI_Ok;
+ TInt certIndex = 0;
+ TPtrC8 keyHash;
+
+ if ( aTmpWimRef )
+ {
+ // List all certificates (by WIM and usage)
+ callStatus = WIMI_GetCertificateListByWIM( aTmpWimRef,
+ aUsage,
+ &tempCertCount,
+ &certRefList );
+ }
+ else
+ {
+ callStatus = WIMI_ERR_BadReference;
+ }
+
+ if ( callStatus == WIMI_Ok )
+ {
+ CleanupPushWimRefListL( certRefList );
+
+ WIMI_Ref_t* tempRef = NULL;
+ WIMI_BinData_t ptLabel;
+ WIMI_BinData_t ptKeyID;
+ WIMI_BinData_t ptCAID;
+ WIMI_BinData_t ptIssuerHash;
+ WIMI_BinData_t ptTrustedUsage;
+ TUint8 uiCDFRefs;
+ TUint8 usage;
+ TUint8 certType;
+ TUint16 certLen;
+ TUint8 modifiable = 0;
+
+ for ( TInt i = 0; i < tempCertCount; i++ )
+ {
+ // Get info for each certificate until we find valid cert
+ callStatus = WIMI_GetCertificateInfo( certRefList[i],
+ &tempRef,
+ &ptLabel,
+ &ptKeyID,
+ &ptCAID,
+ &ptIssuerHash,
+ &ptTrustedUsage,
+ &uiCDFRefs,
+ &usage,
+ &certType,
+ &certLen,
+ &modifiable );
+ if ( callStatus == WIMI_Ok )
+ {
+ WSL_OS_Free( ptLabel.pb_buf );
+ WSL_OS_Free( ptCAID.pb_buf );
+ WSL_OS_Free( ptIssuerHash.pb_buf );
+ WSL_OS_Free( ptTrustedUsage.pb_buf );
+ free_WIMI_Ref_t( tempRef );
+
+ keyHash.Set( ptKeyID.pb_buf, ptKeyID.ui_buf_length );
+
+ // Compare given and fetched key hash
+ if ( keyHash.Compare( aKeyHash ) == 0 &&
+ certType == WIMI_CT_X509 ) //Match
+ {
+ certIndex = i; // Found one
+ i = tempCertCount; // Stop looping
+ callStatus = WIMI_Ok;
+ }
+ else // Cert not supported
+ {
+ callStatus = WIMI_ERR_UnsupportedCertificate;
+ }
+
+ WSL_OS_Free( ptKeyID.pb_buf );
+ }
+ }
+
+ if ( callStatus == WIMI_Ok )
+ {
+ CopyCertExtrasInfoL( certRefList[certIndex], aCertExtrasInfo );
+ }
+ CleanupStack::PopAndDestroy( certRefList );
+ }
+
+ return callStatus;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::CopyCertExtrasInfoL
+// Copies certs extra information to client's allocated structure.
+// -----------------------------------------------------------------------------
+//
+void CWimCertUtil::CopyCertExtrasInfoL(
+ WIMI_Ref_t* aCert,
+ TCertExtrasInfo& aCertExtrasInfo ) const
+ {
+ _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::CopyCertExtrasInfoL | Begin"));
+ WIMI_Ref_t* tempref = NULL;
+ WIMI_BinData_t ptLabel;
+ WIMI_BinData_t ptKeyID;
+ WIMI_BinData_t ptCAID;
+ WIMI_BinData_t ptIssuerHash;
+ WIMI_BinData_t ptTrustedUsage;
+ TUint8 uiCDFRefs;
+ TUint8 usage;
+ TUint8 type;
+ TUint16 certlen;
+ TUint8 modifiable = 0;
+ TBool found = ETrue;
+
+ WIMI_STAT callStatus = WIMI_GetCertificateInfo(
+ aCert,
+ &tempref,
+ &ptLabel,
+ &ptKeyID, /* Key Id (hash)*/
+ &ptCAID,
+ &ptIssuerHash,
+ &ptTrustedUsage,
+ &uiCDFRefs,
+ &usage, /* 0 = client, 1 = CA */
+ &type,
+ &certlen, /* cert. content or URL length */
+ &modifiable);
+ if ( callStatus == WIMI_Ok )
+ {
+ free_WIMI_Ref_t( tempref );
+ WSL_OS_Free( ptLabel.pb_buf );
+ WSL_OS_Free( ptKeyID.pb_buf );
+ WSL_OS_Free( ptCAID.pb_buf );
+ WSL_OS_Free( ptIssuerHash.pb_buf );
+
+ CleanupPushWimBufL( ptTrustedUsage );
+
+ TPtrC8 undecodedUsage;
+ undecodedUsage.Set( ptTrustedUsage.pb_buf );
+
+ if ( ptTrustedUsage.ui_buf_length == 0 ) // No OIDs
+ {
+ found = EFalse;
+ }
+
+ // DECODE OIDs
+ TASN1DecObjectIdentifier decoder;
+ RPointerArray<HBufC> decodedOIDArray;
+ HBufC* decodedOIDs = NULL;
+ TInt oidsLength = 0; // length of total OID buffer
+ TInt err;
+
+ for ( TInt position = 0; found; ) //Loop until no OIDs found anymore
+ {
+ if ( undecodedUsage.Length() > position ) //Don't go over buffer
+ {
+ TRAP( err, decodedOIDs = decoder.DecodeDERL( undecodedUsage, position ) );
+ if ( err == KErrNone ) //Found OID
+ {
+ CleanupStack::PushL( decodedOIDs );
+ if ( decodedOIDs->Length() )
+ {
+ found = ETrue;
+ decodedOIDArray.AppendL( decodedOIDs );
+ oidsLength += decodedOIDs->Length();
+ CleanupStack::Pop( decodedOIDs );
+ }
+ else // Not found OID from buffer
+ {
+ found = EFalse;
+ CleanupStack::PopAndDestroy( decodedOIDs );
+ }
+ decodedOIDs = NULL;
+ }
+ else // Error in OID parsing -> Not found OID
+ {
+ found = EFalse;
+ }
+ }
+ else // undecoded OID buffer seeked through
+ {
+ found = EFalse;
+ }
+ }
+
+ _LIT( KDelimeter16, " " ); //Delimeter between OIDs
+
+ if ( oidsLength > 0 ) // OID's found
+ {
+ // Add OID's to one buffer from separate buffers
+ for ( TInt i = 0; i < decodedOIDArray.Count(); i++ )
+ {
+ if ( i == 0 ) //First one
+ {
+ aCertExtrasInfo.iTrustedUsage->Copy( decodedOIDArray[i]->Des() );
+ }
+ else // Append other OIDs, with delimeter
+ {
+ aCertExtrasInfo.iTrustedUsage->Append( KDelimeter16 );
+ aCertExtrasInfo.iTrustedUsage->Append( decodedOIDArray[i]->Des() );
+ }
+ }
+ }
+
+ aCertExtrasInfo.iCDFRefs = iWimUtilFuncs->MapCertLocation( uiCDFRefs );
+
+ // Free the memory
+ decodedOIDArray.ResetAndDestroy();
+ CleanupStack::PopAndDestroy( ptTrustedUsage.pb_buf );
+ }
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetCertificateFromWimRefL
+// Fetches certificate from the WIM card.
+// -----------------------------------------------------------------------------
+//
+WIMI_STAT CWimCertUtil::GetCertificateFromWimRefL(
+ WIMI_Ref_t* aTmpWimRef,
+ TInt8 aUsage,
+ TUint8& aCertNum,
+ TUint32* aCertRefLst,
+ TWimCertInfo* aCertInfoLst )
+ {
+ _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::GetCertificateFromWimRefL | Begin"));
+ TUint8 tempCrtCount;
+ WIMI_RefList_t refList ;
+ WIMI_STAT callStatus = WIMI_Ok;
+
+ if ( aTmpWimRef )
+ {
+ callStatus = WIMI_GetCertificateListByWIM( aTmpWimRef,
+ aUsage,
+ &tempCrtCount,
+ &refList );
+ if ( callStatus == WIMI_Ok )
+ {
+ for ( TUint8 certIndex = 0; certIndex < tempCrtCount; certIndex++ )
+ {
+ TInt current = aCertNum + certIndex;
+ _WIMTRACE2( _L( "CWimCertHandler::GetCertificateFromWimRefL, +ref 0x%08x" ),
+ refList[certIndex] );
+ // transfers ownership of the refList item to aCertRefLst
+ aCertRefLst[current] = reinterpret_cast< TUint32 >( refList[certIndex] );
+ CopyCertificateInfo( aCertInfoLst[current], refList[certIndex] );
+ }
+ aCertNum = static_cast< TUint8 >( aCertNum + tempCrtCount );
+
+ // Because list items are moved to aCertRefLst, only refList array
+ // needs to be freed. Cannot use free_WIMI_RefList_t() as it would
+ // delete also items contained in refList.
+ WSL_OS_Free( refList );
+ }
+ }
+ return callStatus;
+ }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::CopyCertificateInfo
+// Copies certificate information to client's allocated memory area.
+// -----------------------------------------------------------------------------
+//
+void CWimCertUtil::CopyCertificateInfo(
+ TWimCertInfo& aCertInfo,
+ WIMI_Ref_t* aCert )
+ {
+ _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::CopyCertificateInfoL | Begin"));
+
+ WIMI_Ref_t* tempRef = NULL;
+ WIMI_BinData_t ptLabel;
+ WIMI_BinData_t ptKeyID;
+ WIMI_BinData_t ptCAID;
+ WIMI_BinData_t ptIssuerHash;
+ WIMI_BinData_t ptTrustedUsage;
+ TUint8 uiCDFRefs;
+ TUint8 usage;
+ TUint8 type;
+ TUint16 certLen;
+ TUint8 modifiable = 0;
+ WIMI_STAT callStatus = WIMI_GetCertificateInfo( aCert,
+ &tempRef,
+ &ptLabel,
+ &ptKeyID,
+ &ptCAID,
+ &ptIssuerHash,
+ &ptTrustedUsage,
+ &uiCDFRefs,
+ &usage,
+ &type,
+ &certLen,
+ &modifiable );
+
+ if ( callStatus == WIMI_Ok )
+ {
+ free_WIMI_Ref_t( tempRef );
+
+ aCertInfo.iLabel.Copy( TPtr8( ptLabel.pb_buf,
+ ptLabel.ui_buf_length,
+ ptLabel.ui_buf_length ) );
+
+ aCertInfo.iKeyId.Copy( TPtr8( ptKeyID.pb_buf,
+ ptKeyID.ui_buf_length,
+ ptKeyID.ui_buf_length ) );
+
+ aCertInfo.iCAId.Copy( TPtr8( ptCAID.pb_buf,
+ ptCAID.ui_buf_length,
+ ptCAID.ui_buf_length ) );
+
+ aCertInfo.iIssuerHash.Copy( TPtr8( ptIssuerHash.pb_buf,
+ ptIssuerHash.ui_buf_length,
+ ptIssuerHash.ui_buf_length ) );
+
+ aCertInfo.iUsage = usage;
+ aCertInfo.iType = type;
+ aCertInfo.iCertlen = certLen;
+ aCertInfo.iModifiable = modifiable;
+
+ // Certificate location
+ aCertInfo.iCDFRefs = iWimUtilFuncs->MapCertLocation( uiCDFRefs );
+
+ //Allocate enough memory for OID
+ aCertInfo.iTrustedUsageLength = ptTrustedUsage.ui_buf_length * 6;
+
+ WSL_OS_Free( ptLabel.pb_buf );
+ WSL_OS_Free( ptKeyID.pb_buf );
+ WSL_OS_Free( ptCAID.pb_buf );
+ WSL_OS_Free( ptIssuerHash.pb_buf );
+ WSL_OS_Free( ptTrustedUsage.pb_buf );
+ }
+ }
+
+// End of File