wim/WimServer/src/WimCertHandler.cpp
changeset 0 164170e6151a
child 5 3b17fc5c9564
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/wim/WimServer/src/WimCertHandler.cpp	Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,1232 @@
+/*
+* 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:  Certificate management methods
+*
+*/
+
+
+
+// INCLUDE FILES
+#include    "Wimi.h"            // wimi definitions
+#include    "WimCertHandler.h"
+#include    "WimMemMgmt.h"
+#include    "WimSession.h"
+#include    "WimResponse.h"
+#include    "WimUtilityFuncs.h"
+#include    <asn1enc.h>         // asn.1 encoding
+#include    <asn1dec.h>         // asn.1 decoding
+#include    <x509cert.h>        // cx509certificate
+#ifndef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include    <x509keys.h>        // cx509rsapublickey
+#else
+#include    <x509keys.h>        // cx509rsapublickey
+#include    <x509keyencoder.h>        // cx509rsapublickey
+#endif
+#include    <wtlscert.h>        // cwtlscertificate
+#include    <wtlskeys.h>        // cwtlsrsapublickey
+#include    "WimTrace.h"
+#include    "WimCallbackImpl.h"
+#include    "WimCleanup.h"
+
+// ============================ MEMBER FUNCTIONS ===============================
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::CWimCertHandler
+// C++ default constructor can NOT contain any code, that
+// might leave.
+// -----------------------------------------------------------------------------
+//
+CWimCertHandler::CWimCertHandler()
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::CWimCertHandler | Begin"));
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::ConstructL()
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::ConstructL | Begin"));
+    iWimUtilFuncs = CWimUtilityFuncs::NewL();
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::NewL
+// Two-phased constructor.
+// -----------------------------------------------------------------------------
+//
+CWimCertHandler* CWimCertHandler::NewL() 
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::NewL | Begin"));
+    CWimCertHandler* self = new( ELeave ) CWimCertHandler;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop( self );
+    return self;
+    }
+
+    
+// Destructor
+CWimCertHandler::~CWimCertHandler()
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::~CWimCertHandler | Begin"));
+    delete iWimUtilFuncs;
+
+    for( TInt index = 0; index < iCertRefLst.Count(); ++index )
+        {
+        WIMI_Ref_t* ref = reinterpret_cast< WIMI_Ref_t* >( iCertRefLst[ index ] );
+        _WIMTRACE2(_L("WIM | WIMServer | CWimCertHandler::~CWimCertHandler, -ref 0x%08x"), ref);
+        free_WIMI_Ref_t( ref );
+        iCertRefLst[ index ] = 0;
+        }
+    iCertRefLst.Reset();
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetCertificatesFromWimL
+// Fetches certificates from WIM card.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::GetCertificatesFromWimL(
+    const RMessage2& aMessage, 
+    CWimMemMgmt* aWimMgmt )
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::GetCertificatesFromWimL | Begin"));
+    WIMI_STAT callStatus = WIMI_Ok;
+    TUint8 certNum = 0;
+    WIMI_Ref_t* temp = NULL;
+
+    HBufC8* certRefLst = iWimUtilFuncs->DesLC( 0, aMessage );
+    HBufC8* certInfoLst = iWimUtilFuncs->DesLC( 1, aMessage );
+
+    TWimEntryType certEntryType = ( TWimEntryType ) aMessage.Int2();
+
+    TUint32* pCertRefLst = ( TUint32* )( certRefLst->Des().Ptr() );
+    TWimCertInfo* pCertInfoLst = ( TWimCertInfo* )( certInfoLst->Des().Ptr() );
+
+    temp = aWimMgmt->WimRef();
+    if ( !temp )
+        { 
+        temp = WIMI_GetWIMRef( 0 );
+        aWimMgmt->SetWIMRef( temp );    // takes ownership
+        }
+
+    if ( temp )
+        {
+        if ( EWimEntryTypeAll == certEntryType || 
+             EWimEntryTypeCA == certEntryType )
+            {
+            callStatus = GetCertificateFromWimRefL( temp, WIMI_CU_CA,
+                                                    certNum, pCertRefLst,
+                                                    pCertInfoLst, aMessage );
+
+            }
+        if ( callStatus == WIMI_Ok && ( EWimEntryTypeAll == certEntryType || 
+                                   EWimEntryTypePersonal == certEntryType ) )
+            {
+            callStatus = GetCertificateFromWimRefL( temp, WIMI_CU_Client,
+                                                    certNum, pCertRefLst,
+                                                    pCertInfoLst, aMessage );
+
+            }
+        
+        //record the ref for sanity checking, deallocate old refs first
+        for( TInt index = 0; index < iCertRefLst.Count(); ++index )
+            {
+            WIMI_Ref_t* ref = reinterpret_cast< WIMI_Ref_t* >( iCertRefLst[ index ] );
+            _WIMTRACE2(_L("WIM | WIMServer | CWimCertHandler::GetCertificatesFromWimL, -ref 0x%08x"), ref);
+            free_WIMI_Ref_t( ref );
+            iCertRefLst[ index ] = 0;
+            }
+        iCertRefLst.Reset();
+        for( TInt index = 0; index < certNum; ++index )
+            {
+            _WIMTRACE2(_L("WIM | WIMServer | CWimCertHandler::GetCertificatesFromWimL, +ref 0x%08x"), pCertRefLst[ index ]);
+            iCertRefLst.AppendL( pCertRefLst[ index ] );
+            }
+        
+        aMessage.WriteL( 0, certRefLst->Des() );
+        aMessage.WriteL( 1, certInfoLst->Des() );
+        }
+    else
+        {
+        callStatus = WIMI_ERR_OutOfMemory;
+        }
+    CleanupStack::PopAndDestroy( 2, certRefLst );   // certInfoLst, certRefLst
+    aMessage.Complete( CWimUtilityFuncs::MapWIMError( callStatus ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetCertificateFromWimRefL
+// Fetches certificate from the WIM card.
+// -----------------------------------------------------------------------------
+//
+WIMI_STAT CWimCertHandler::GetCertificateFromWimRefL(
+    WIMI_Ref_t* aTmpWimRef,
+    TInt8 aUsage,
+    TUint8& aCertNum,
+    TUint32* aCertRefLst,
+    TWimCertInfo* aCertInfoLst,
+    const RMessage2& aMessage )
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::GetCertificateFromWimRefL | Begin"));
+    TUint8 tempCrtCount;
+    WIMI_RefList_t refList = NULL;
+    WIMI_STAT callStatus = WIMI_Ok;
+
+    if ( aTmpWimRef )
+        {
+        callStatus = WIMI_GetCertificateListByWIM( aTmpWimRef, 
+                                                   aUsage, 
+                                                   &tempCrtCount, 
+                                                   &refList );
+
+        if ( callStatus == WIMI_Ok )
+            {
+            // If the certifcate length is 0,
+            // the step increases by 1.
+            TInt step = 0;
+            TInt err = KErrNone;
+            for ( TUint8 certIndex = 0; certIndex < tempCrtCount; certIndex++ )
+                {
+                TInt current = aCertNum + certIndex - step;
+                err = CopyCertificateInfo( aCertInfoLst[current], refList[certIndex], aMessage );
+
+                if ( err == KErrNone )
+                    {
+                    // transfers ownership of refList item to aCertRefLst
+                    aCertRefLst[current] = reinterpret_cast< TUint32 >( refList[certIndex] );
+                    refList[certIndex] = NULL;
+                    }
+                else // KErrArgument
+                    {
+                    // ingore certificate info and continue with the next
+                	step++;
+                    free_WIMI_Ref_t( refList[certIndex] );
+                    }
+                }
+            //variable step is equal to the number of certificate in CDF whose 
+            //length is set as 0.     
+            aCertNum = static_cast< TUint8 >( aCertNum + tempCrtCount - step );
+
+            // 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.
+// This function MAY NOT leave.
+// -----------------------------------------------------------------------------
+//
+TInt CWimCertHandler::CopyCertificateInfo(
+    TWimCertInfo& aCertInfo,
+    WIMI_Ref_t* aCert,
+    const RMessage2& /*aMessage*/ )
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::CopyCertificateInfo | 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, /* Key Id (hash)*/
+                                &ptCAID,
+                                &ptIssuerHash,
+                                &ptTrustedUsage,
+                                &uiCDFRefs,
+                                &usage,  /* 0 = client, 1 = CA */
+                                &type,   /* WTLSCert(1), 
+                                            X509Cert(2), 
+                                            X968Cert(3), 
+                                            CertURL(4) */ 
+                                &certLen,   /* cert. content or URL length */
+                                &modifiable );
+
+    if ( callStatus == WIMI_Ok )
+        {
+        free_WIMI_Ref_t( tempRef );
+
+        // To make sure the length of the certificate is not zero
+        _WIMTRACE2(_L("WIM | WIMServer | CWimCertHandler::CopyCertificateInfoL | certLen %d"), certLen);
+        if ( certLen == 0 )
+            {
+            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 );
+        	return KErrArgument;
+            }
+
+        // it is x509cert
+        if ( type == 2 && certLen != 0 )
+            {
+            //use this rough sanity checking for temp
+            if ( certLen < 10 )
+                {
+                _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::CopyCertificateInfoL | cert is malformated, return KErrArgument"));
+                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 );
+                return KErrArgument;
+                }
+            }
+        _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::CopyCertificateInfoL | X509 check ok"));
+
+        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 * 16;
+
+        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 );
+        }
+
+    return KErrNone;
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetExtrasFromWimL
+// Fetches certificate's extra info from WIM card. In this case it is
+// trusted usage info.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::GetExtrasFromWimL(
+    const RMessage2& aMessage, 
+    CWimMemMgmt* aWimMgmt )
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::GetExtrasFromWimL | Begin"));
+
+    WIMI_STAT callStatus = WIMI_Ok;
+    TInt8 certUsage = 0;
+    
+    HBufC8* keyIdBuf = iWimUtilFuncs->DesLC( 0, aMessage );
+    TPtrC8 keyIdHash = keyIdBuf->Des();
+
+    WIMI_Ref_t* wimTempRef = aWimMgmt->WimRef();
+    if ( !wimTempRef )
+        { 
+        wimTempRef = WIMI_GetWIMRef( 0 );
+        aWimMgmt->SetWIMRef( wimTempRef );  // takes ownership
+        }
+
+    if ( wimTempRef )
+        {
+        TWimEntryType certEntryType = static_cast< TWimEntryType >( aMessage.Int2() );
+        switch ( certEntryType )
+            {
+            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,
+                                               keyIdHash,
+                                               aMessage );
+            }
+        }
+    else
+        {
+        callStatus = WIMI_ERR_BadReference;
+        }
+
+    CleanupStack::PopAndDestroy( keyIdBuf );
+    aMessage.Complete( CWimUtilityFuncs::MapWIMError( callStatus ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetExtrasFromWimRefL
+// Fetches extra information (e.g. certs trusted usage) from the WIM card.
+// -----------------------------------------------------------------------------
+//
+WIMI_STAT CWimCertHandler::GetExtrasFromWimRefL(
+    WIMI_Ref_t* aTmpWimRef,
+    TInt8 aUsage,
+    TDesC8& aKeyHash,
+    const RMessage2& aMessage )
+    {
+    _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;
+        }
+    CleanupPushWimRefListL( certRefList );
+    
+    if ( callStatus == WIMI_Ok )
+        {
+        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 )
+                {
+                free_WIMI_Ref_t( tempRef );
+
+                // Code MAY NOT leave before ptLabel.pb_buf, ptKeyID.pb_buf,
+                // ptCAID.pb_buf, ptIssuerHash.pt_buf, and ptTrustedUsage.pb_buf
+                // are deallocated.
+
+                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( 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 );
+                // Code can leave after this point.
+                }
+            }
+
+        if ( callStatus == WIMI_Ok )
+            {
+            CopyCertExtrasInfoL( certRefList[certIndex], aMessage );
+            }
+
+        CleanupStack::PopAndDestroy( certRefList );
+        }
+
+    return callStatus;
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::CopyCertExtrasInfoL
+// Copies certs extra information to client's allocated memory area.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::CopyCertExtrasInfoL(
+    WIMI_Ref_t* aCert,
+    const RMessage2& aMessage )
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::CopyCertExtrasInfoL | Begin"));
+    TUint8 pushedItemCount = 0;
+    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;
+
+    TCertExtrasInfo certExtraInfo;
+    certExtraInfo.iCDFRefs = 0;
+    certExtraInfo.iTrustedUsage = NULL;
+
+    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 );
+        pushedItemCount++;
+
+        TPtrC8 undecodedUsage;
+        undecodedUsage.Set( ptTrustedUsage.pb_buf ); 
+
+        if ( ptTrustedUsage.ui_buf_length == 0 ) // No OIDs
+            {
+            found = EFalse;
+            }
+
+        // DECODE OIDs
+        TASN1DecObjectIdentifier decoder;
+        RPointerArray<HBufC> decodedOIDArray;
+        CleanupResetAndDestroyPushL( decodedOIDArray );
+        pushedItemCount++;
+        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
+        TInt trustedUsagesBufMaxLength = oidsLength + decodedOIDArray.Count();
+        TPtr trustedUsage( NULL, 0, trustedUsagesBufMaxLength );
+
+        if ( oidsLength > 0 ) // OID's found
+            {
+            // Alloc new buffer for all OID's
+            HBufC* trustedUsagesBuf = HBufC::NewLC( trustedUsagesBufMaxLength );
+            pushedItemCount++;
+
+            trustedUsage.Set( trustedUsagesBuf->Des() );
+       
+            // Add OID's to one buffer from separate buffers
+            for ( TInt i = 0; i < decodedOIDArray.Count(); i++ )
+                {
+                if ( i == 0 ) //First one
+                    {
+                    trustedUsage.Copy( decodedOIDArray[i]->Des() );
+                    }
+                else // Append other OIDs, with delimeter
+                    {
+                    trustedUsage.Append( KDelimeter16 );
+                    trustedUsage.Append( decodedOIDArray[i]->Des() );
+                    }
+                }
+            }
+
+        TPckgBuf<TCertExtrasInfo> wimCertExtraPckg( certExtraInfo );
+        aMessage.ReadL( 1, wimCertExtraPckg );
+        
+        wimCertExtraPckg().iCDFRefs = iWimUtilFuncs->MapCertLocation( uiCDFRefs );
+        
+        if ( oidsLength > 0 ) // OID's found, write buffer to client
+            {
+            aMessage.WriteL( 3, trustedUsage );
+            }
+        aMessage.WriteL( 1, wimCertExtraPckg );
+
+        CleanupStack::PopAndDestroy( pushedItemCount, ptTrustedUsage.pb_buf );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetCerticateCountL
+// Fetches count of certicates in certain WIM card.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::GetCerticateCountL(
+    const RMessage2& aMessage, 
+    CWimMemMgmt* aWimMgmt ) const
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::GetCerticateCountL | Begin"));
+    WIMI_STAT callStatus = WIMI_Ok;
+    TWimEntryType certEntryType = ( TWimEntryType )aMessage.Int1();
+    
+    __ASSERT_ALWAYS( certEntryType != EWimEntryTypeAll ||
+        certEntryType != EWimEntryTypeCA ||
+        certEntryType != EWimEntryTypePersonal, User::Leave( KErrArgument ) );
+
+    WIMI_Ref_t* wimRef = NULL;
+    TUint8 certCount = 0;
+
+    wimRef = aWimMgmt->WimRef();
+    if ( !wimRef )
+        {
+        wimRef = WIMI_GetWIMRef( 0 );
+        aWimMgmt->SetWIMRef( wimRef );  // takes ownership
+        }
+
+    if ( wimRef )
+        {
+        if ( EWimEntryTypeAll == certEntryType || 
+            EWimEntryTypeCA == certEntryType )
+            {
+            callStatus = GetCertificateCountByWIM( wimRef, 
+                                                   certCount, 
+                                                   WIMI_CU_CA );            
+            }
+
+        if ( callStatus == WIMI_Ok && ( EWimEntryTypeAll == certEntryType || 
+                                     EWimEntryTypePersonal == certEntryType ) )
+            {
+            callStatus = GetCertificateCountByWIM( wimRef, 
+                                                   certCount, 
+                                                   WIMI_CU_Client );
+            }
+        }
+    else
+        {
+        callStatus = WIMI_ERR_OutOfMemory;
+        }
+
+    if ( callStatus == WIMI_Ok )
+        {
+        _WIMTRACE2(_L("WIM | WIMServer | CWimCertHandler::GetCerticateCountL | count=%d"), certCount);
+        TPckgBuf<TUint8> pckg( certCount );
+        aMessage.WriteL( 0, pckg );
+        }
+    aMessage.Complete( CWimUtilityFuncs::MapWIMError( callStatus ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetCertificateCountByWIM
+// Fetches count of certicates in certain WIM card.
+// This function MAY NOT leave.
+// -----------------------------------------------------------------------------
+//
+WIMI_STAT CWimCertHandler::GetCertificateCountByWIM(
+    WIMI_Ref_t* aRef, 
+    TUint8& aCertCount, 
+    TUint8 aUsage ) const
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::GetCertificateCountByWIM | Begin"));
+    
+    // Get the number of certificates from smart card.
+    TUint8 certNum = 0;
+    WIMI_RefList_t refList ;
+    WIMI_STAT callStatus = WIMI_GetCertificateListByWIM( aRef, 
+                                                         aUsage,
+                                                         &certNum, 
+                                                         &refList );
+
+    if ( callStatus != WIMI_Ok )   
+        {
+    	return callStatus;
+        }
+    
+    // Find out how many certificate has zero length
+    TInt certLenZero = 0;
+    TInt certMalformat = 0;
+    for ( TInt i = 0; i < certNum ; i++ )
+	    {
+	    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;
+	    callStatus = WIMI_GetCertificateInfo( 
+	                                refList[i],
+	                                &tempRef,
+	                                &ptLabel,
+	                                &ptKeyID, /* Key Id (hash)*/
+	                                &ptCAID,
+	                                &ptIssuerHash,
+	                                &ptTrustedUsage,
+	                                &uiCDFRefs,
+	                                &usage,  /* 0 = client, 1 = CA */
+	                                &type,   /* WTLSCert(1), 
+	                                            X509Cert(2), 
+	                                            X968Cert(3), 
+	                                            CertURL(4) */ 
+	                                &certLen,   /* cert. content or URL length */
+	                                &modifiable );
+
+	    if ( callStatus == WIMI_Ok )
+	        {
+	        free_WIMI_Ref_t( tempRef );
+	        
+	        if ( certLen == 0 )
+	            {
+	            certLenZero++;
+	            }
+
+            // it is x509cert
+            if ( type == 2 && certLen != 0 )
+                {
+
+                //use this rough sanity checking
+                if ( certLen < 10 )
+                    {
+                    certMalformat++;
+                    }
+                }
+
+            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 );
+	        }
+	    }
+
+    // only return the number of ceritifcates that have non-zero length
+    if ( callStatus == WIMI_Ok )
+        {
+        aCertCount = static_cast< TUint8 >( aCertCount + certNum - certLenZero - certMalformat );
+        }
+
+    free_WIMI_RefList_t( refList );
+
+    return callStatus;
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::StoreCertificateL
+// Stores certificate to the WIM card.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::StoreCertificateL( 
+    TWimServRqst /*aOpcode*/,
+    const RMessage2& aMessage ) const
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::StoreCertificateL | Begin"));
+    aMessage.Complete( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::RemoveCertificateL
+// Removes certificate from a WIM card.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::RemoveCertificateL( 
+    const RMessage2& aMessage,
+    CWimMemMgmt* /*aWimMgmt*/ ) const
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::RemoveCertificateL | Begin"));
+    aMessage.Complete( KErrNotSupported );
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::SanityCheck
+// -----------------------------------------------------------------------------
+//
+TBool CWimCertHandler::SanityCheck( TUint32 aCertRef )
+    {
+    TInt certNum = iCertRefLst.Count();
+    if ( certNum == 0 )
+        {
+        return EFalse;
+        }
+    
+    for ( TInt index = 0; index < certNum; ++index )
+        {
+        if( aCertRef == iCertRefLst[ index ] )
+            {
+            return ETrue;
+            }
+        }
+    return EFalse;
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetCertificateDetailsL
+// Fetches certificate details.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::GetCertificateDetailsL(
+    TWimServRqst aOpCode, 
+    const RMessage2& aMessage ) 
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimCertHandler::GetCertificateDetailsL | Begin"));
+    TBool IsOk = SanityCheck( (TUint32)aMessage.Ptr0() );
+    if ( ! IsOk  )
+        {
+        aMessage.Panic(_L("WIM"), KErrBadHandle );
+        return;
+        }
+    
+    //capability checking
+    TUint8 usage = 255;
+    WIMI_STAT callStatus = ResolveCertUsage( aMessage, usage );
+    if ( WIMI_Ok == callStatus )
+        {
+        if( !CheckReadCapsForUsage( aMessage, usage  ) )
+              {
+              aMessage.Complete(KErrPermissionDenied);  
+              return;
+              }
+        }
+
+    //capabilty ok, go to fetch the details of the certificate.
+    WIMI_Ref_pt pCertRef = const_cast<WIMI_Ref_pt>( aMessage.Ptr0() );
+    CWimResponse* responseID = new( ELeave ) CWimResponse( aMessage );
+    CleanupStack::PushL( responseID );
+    TWimReqTrId* trId = iWimUtilFuncs->TrIdLC( responseID, EWimMgmtReq );
+    responseID->iOpcode = aOpCode;
+    CleanupStack::Pop( 2, responseID ); // trId, responseID
+
+    WIMI_STAT certReqStatus = WIMI_CertificateReq( trId, pCertRef );
+    if ( certReqStatus != WIMI_Ok )
+        {
+        responseID->iStatus = certReqStatus;
+        responseID->CompleteMsgAndDelete();
+        delete trId;
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::ResolveCertUsage
+// Resolves usage (CA/User) for a certificate.
+// -----------------------------------------------------------------------------
+//
+WIMI_STAT CWimCertHandler::ResolveCertUsage( const RMessage2& aMsg,
+                                        TUint8& aUsage )
+    {
+    _WIMTRACE(_L("CWimServer::ResolveCertUsage | Begin"));
+
+    // aMsg.Ptr0 contains reference to certificate
+    
+    WIMI_Ref_pt pCertRef = const_cast< WIMI_Ref_pt >( aMsg.Ptr0() );
+    _WIMTRACE2(_L("CWimServer::ResolveCertUsage | Begin aMsg.Ptr0() = %d"), aMsg.Ptr0());
+
+    WIMI_STAT callStatus = GetCertificateInfo( pCertRef, aUsage );
+
+    _WIMTRACE(_L("CWimServer::ResolveCertUsage | End"));
+    return callStatus;
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetCertificateInfo
+// Fetches certificate info. Wrapper for WIMI call.
+// -----------------------------------------------------------------------------
+//
+WIMI_STAT CWimCertHandler::GetCertificateInfo( WIMI_Ref_pt aCertRef,
+                                          TUint8& aUsage )
+    {
+    _WIMTRACE(_L("CWimServer::GetCertificateInfo | Begin"));
+
+    WIMI_Ref_pt     pWimRef = NULL;
+    WIMI_BinData_t  ptLabel;
+    WIMI_BinData_t  ptKeyID;
+    WIMI_BinData_t  ptCAID;
+    WIMI_BinData_t  ptIssuerHash;
+    WIMI_BinData_t  ptTrustedUsage;
+    TUint8          uiCDFRefs;
+    TUint8          type;
+    TUint16         certLen;
+    TUint8          modifiable = 0;
+    _WIMTRACE(_L("CWimServer::GetCertificateInfo | Begin 1"));
+    WIMI_STAT callStatus = WIMI_GetCertificateInfo(
+                                aCertRef,
+                                &pWimRef,
+                                &ptLabel,
+                                &ptKeyID, // Key Id (hash)
+                                &ptCAID,
+                                &ptIssuerHash,
+                                &ptTrustedUsage,
+                                &uiCDFRefs,
+                                &aUsage,  // 0 = client, 1 = CA
+                                &type,    // WTLSCert(1),
+                                          // X509Cert(2),
+                                          // X968Cert(3),
+                                          // CertURL(4)
+                                &certLen, // cert. content or URL length
+                                &modifiable );
+    _WIMTRACE(_L("CWimServer::GetCertificateInfo | Begin 2"));
+    // Don't need references anymore
+    if ( callStatus == WIMI_Ok )
+        {
+        free_WIMI_Ref_t( pWimRef );
+        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 );
+        }
+
+    _WIMTRACE(_L("CWimServer::GetCertificateInfo | End"));
+    return callStatus;
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::GetCertificateInfo
+// Fetches certificate info. Wrapper for WIMI call.
+// -----------------------------------------------------------------------------
+//
+TBool CWimCertHandler::CheckReadCapsForUsage( const RMessage2& aMsg,
+                               TUint8 aUsage )
+    {
+    TBool result = EFalse;
+    
+    switch ( aUsage )
+        {
+        case WIMI_CU_CA:
+            {
+            // CA certificate reading doesn't require any capability.
+            _WIMTRACE(_L("CWimCertHandler::CheckReadCapsForUsage: CA cert read req, OK."));
+            result = ETrue;
+            break;
+            }
+        case WIMI_CU_Client:
+            {
+            // User certificate reading requires ReadUserData capability.
+            if ( aMsg.HasCapability( ECapabilityReadUserData ))
+                {
+                result = ETrue;
+                _WIMTRACE(_L("CWimCertHandler::CheckReadCapsForUsage: User cert read capa PASS"));
+                }
+            else
+                {
+                result = EFalse;
+                _WIMTRACE(_L("CWimCertHandler::CheckReadCapsForUsage: User cert read capa FAIL"));
+                }
+            break;
+            }
+        default:
+            {
+            _WIMTRACE(_L("CWimCertHandler::CheckReadCapsAccordingToUsage: FAIL:Unknown usage."));
+            result = EFalse;
+            break;
+            }
+        }
+    _WIMTRACE(_L("CWimCertHandler::CheckReadCapsForUsage | End"));
+    return result;
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::ExportPublicKeyL
+// Export public key from certificate.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::ExportPublicKeyL( const RMessage2& aMessage ) const
+    {
+    _WIMTRACE(_L("WIM | WIMServer | CWimPublicKeyHandler::ExportPublicKeyParamsL | Begin"));
+
+    TUint8 certType = 0;
+
+    TPckgBuf<TExportPublicKey> keyExportPckg;
+    aMessage.ReadL( 0, keyExportPckg );
+    
+    HBufC8* publicKeyBuf = HBufC8::NewLC( KPublicKeyLength );
+
+    TBuf8<KKeyIdLen> keyIdBuf = keyExportPckg().iKeyId;
+
+    WIMI_STAT callStatus = WIMI_Ok;
+    WIMI_BinData_t ptCertData;
+    ptCertData.pb_buf = NULL;
+    ptCertData.ui_buf_length = 0;
+    WIMI_Ref_t* pCert = NULL;
+    WIMI_TransactId_t trId = ( void* )EInitializationCertListHashing;
+    TUint8 certCount = 0;
+    WIMI_RefList_t certRefList = NULL;
+
+    // Check firs the Client certs
+    callStatus = WIMI_GetCertificateListByKeyHash( ( TUint8* )keyIdBuf.Ptr(),
+                                                   WIMI_CU_Client,
+                                                   &certCount,
+                                                   &certRefList );
+    if ( callStatus == WIMI_Ok )
+        {
+        if ( certCount == 0 ) // Not found client certs
+            {
+            free_WIMI_RefList_t( certRefList );
+            certRefList = NULL;
+
+            // Check CA certs
+            callStatus = WIMI_GetCertificateListByKeyHash(
+                                                    ( TUint8* )keyIdBuf.Ptr(),
+                                                    WIMI_CU_CA,
+                                                    &certCount,
+                                                    &certRefList );
+            }
+        }
+
+    if ( callStatus == WIMI_Ok )
+        {
+        CleanupPushWimRefListL( certRefList );
+        if ( certCount == 0 ) // No certificates found for key
+            {
+            CleanupStack::PopAndDestroy( certRefList );
+            callStatus = WIMI_ERR_CertNotFound;
+            }
+        }
+
+    if ( callStatus == WIMI_Ok )
+        {
+        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;
+
+        TUint16 certLen;
+        TUint8 modifiable = 0;
+
+        for ( TInt i = 0; i < certCount; 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( ptKeyID.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 );
+
+                // Certificate has to be WTLS or X509, not URL
+                if ( certType == WIMI_CT_X509 || certType == WIMI_CT_WTLS )
+                    {
+                    pCert = certRefList[i]; // Found one
+                    i = certCount; // Stop looping
+                    }
+                else // Cert not supported
+                    {
+                    callStatus = WIMI_ERR_UnsupportedCertificate;
+                    }
+                }
+            }
+    
+        // Retrieve certificate data from WIM
+        if ( callStatus == WIMI_Ok )
+            {
+            callStatus = WIMI_CertificateReqT( trId, pCert, &ptCertData );
+            if ( callStatus == WIMI_Ok )
+                {
+                CleanupPushWimBufL( ptCertData );
+
+                TPtrC8 certPtr( ptCertData.pb_buf, ptCertData.ui_buf_length );
+                TPtr8 publicKeyPtr = publicKeyBuf->Des();
+
+                TRAPD( parseOk, ParseCertPublicKeyL( certPtr, publicKeyPtr, certType ) );
+                if ( parseOk )
+                    {
+                    aMessage.WriteL( 1, publicKeyPtr );
+                    }
+                else
+                    {
+                    callStatus = WIMI_ERR_CertParseError;
+                    }
+
+                CleanupStack::PopAndDestroy( ptCertData.pb_buf );
+                }
+            }
+        
+        CleanupStack::PopAndDestroy( certRefList );
+        }
+
+    CleanupStack::PopAndDestroy( publicKeyBuf );
+
+    aMessage.Complete( CWimUtilityFuncs::MapWIMError( callStatus ) );
+    }
+
+// -----------------------------------------------------------------------------
+// CWimCertHandler::ParseCertPublicKeyL
+// Parse public key from certificate.
+// -----------------------------------------------------------------------------
+//
+void CWimCertHandler::ParseCertPublicKeyL(
+    const TDesC8& aCertData,
+    TDes8& aPublicKey,
+    const TUint8 aCertType ) const
+    {
+    CCertificate* certificate = NULL;
+    CRSAPublicKey* publicKey = NULL;
+
+    switch ( aCertType )
+        {
+        case WIMI_CT_WTLS:
+            {
+            certificate = CWTLSCertificate::NewLC( aCertData );
+            publicKey = CWTLSRSAPublicKey::NewLC( certificate->PublicKey().KeyData() );
+            break;
+            }
+    
+        case WIMI_CT_X509:
+            {
+            certificate = CX509Certificate::NewLC( aCertData );
+            publicKey = CX509RSAPublicKey::NewLC( certificate->PublicKey().KeyData() );
+            break;
+            }
+        default:
+            {
+            _WIMTRACE2(_L("WIM|WIMServer|CWimCertHandler::ParseCertPublicKeyL, type %d not supported"), aCertType);
+            User::Leave( KErrNotSupported );
+            break;
+            }
+        }
+
+    TX509RSAKeyEncoder encoder( *publicKey, ESHA1 );
+    CASN1EncBase* encoded = encoder.EncodeKeyLC();
+
+    TUint pos = 0;
+    aPublicKey.SetLength( KPublicKeyLength );
+    // Check that Max. length is not exceeded
+    if ( encoded->LengthDER() > static_cast< TUint >( KPublicKeyLength ) )
+        {
+        _WIMTRACE(_L("WIM|WIMServer|CWimCertHandler::ParseCertPublicKeyL, too long public key"));
+        User::Leave( KErrBadDescriptor );
+        }
+    // Write encoded key to prealloced buffer
+    encoded->WriteDERL( aPublicKey, pos );
+
+    CleanupStack::PopAndDestroy( 3, certificate );  // encoded, publicKey, certificate
+    }
+
+//  End of File