diff -r 000000000000 -r 164170e6151a wim/WimServer/src/WimCertUtil.cpp --- /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 +#include // 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& 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(); + //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 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