crypto/weakcryptospi/source/hash/hashshim.cpp
changeset 19 cd501b96611d
child 43 2f10d260163b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypto/weakcryptospi/source/hash/hashshim.cpp	Fri Nov 06 13:21:00 2009 +0200
@@ -0,0 +1,856 @@
+/*
+* Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+* hash shim implementation
+* hash shim implementation
+*
+*/
+
+
+/**
+ @file
+*/
+
+#include "hashshim.h"
+#include <cryptospi/cryptospidef.h>
+#include <cryptospi/plugincharacteristics.h>
+#include "keys.h"
+
+
+using namespace CryptoSpi;
+
+//
+// MD2 shim implementation
+//
+CMD2Shim* CMD2Shim::NewL()
+	{
+	CMD2Shim* self=CMD2Shim::NewLC();
+	CleanupStack::Pop();
+	return self;	
+	}
+
+CMD2Shim* CMD2Shim::NewLC()
+	{
+	CMD2Shim* self=new(ELeave) CMD2Shim();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;	
+	}
+
+TInt CMD2Shim::Extension_(TUint aExtensionId, TAny*& a0, TAny* /*a1*/)
+	{
+	TInt ret(KErrNotSupported);
+	
+	if (KHashInterfaceUid.iUid==aExtensionId && iHashImpl)
+		{
+		a0=iHashImpl;
+		ret=KErrNone;	
+		}
+		
+	return ret;
+	}
+
+CMD2Shim::CMD2Shim()
+	{		
+	}
+
+CMD2Shim::~CMD2Shim()
+	{
+	delete iHashImpl;				
+	}
+
+
+void CMD2Shim::ConstructL()
+	{	
+	CHashFactory::CreateHashL(iHashImpl,
+							KMd2Uid,
+							KHashModeUid,
+							NULL, NULL);
+	}
+
+CMessageDigest* CMD2Shim::CopyL()
+	{
+	CMD2Shim* copy=new(ELeave) CMD2Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->CopyL();
+	CleanupStack::Pop();
+	return copy;
+	}
+	
+CMessageDigest* CMD2Shim::ReplicateL()
+	{
+	CMD2Shim* copy=new(ELeave) CMD2Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->ReplicateL();
+	CleanupStack::Pop();
+	return copy;
+	}
+
+
+TInt CMD2Shim::BlockSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iBlockSize/8;
+	}
+
+TInt CMD2Shim::HashSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}	
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iOutputSize/8;
+	}
+
+void CMD2Shim::Update(const TDesC8& aMessage)
+	{
+	iHashImpl->Update(aMessage);	
+	}
+	
+	
+TPtrC8 CMD2Shim::Final(const TDesC8& aMessage)
+	{
+	return iHashImpl->Final(aMessage);
+	}
+
+TPtrC8 CMD2Shim::Final()
+	{
+	TPtrC8 ptr(KNullDesC8());
+	return iHashImpl->Final(ptr);
+	}
+		
+void CMD2Shim::Reset()
+	{
+	iHashImpl->Reset();
+	}
+	
+
+TPtrC8 CMD2Shim::Hash(const TDesC8& aMessage)
+	{
+	return iHashImpl->Hash(aMessage);
+	}
+
+//
+// Implementation of MD5 shim
+//
+CMD5Shim* CMD5Shim::NewL()
+	{
+	CMD5Shim* self=CMD5Shim::NewLC();
+	CleanupStack::Pop();
+	return self;	
+	}
+
+CMD5Shim* CMD5Shim::NewLC()
+	{
+	
+	CMD5Shim* self=new(ELeave) CMD5Shim();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;	
+	
+	}
+
+CMD5Shim::CMD5Shim()
+	{		
+	}
+	
+TInt CMD5Shim::Extension_(TUint aExtensionId, TAny*& a0, TAny* /*a1*/)
+	{
+	TInt ret(KErrNotSupported);
+	
+	if (KHashInterfaceUid.iUid==aExtensionId && iHashImpl)
+		{
+		a0=iHashImpl;
+		ret=KErrNone;	
+		}
+		
+	return ret;
+	}
+
+CMD5Shim::~CMD5Shim()
+	{
+	delete iHashImpl;				
+	}
+
+
+void CMD5Shim::ConstructL()
+	{	
+	CHashFactory::CreateHashL(iHashImpl,
+							KMd5Uid,
+							KHashModeUid,
+							NULL,
+							NULL);
+	}
+
+CMessageDigest* CMD5Shim::CopyL()
+	{
+	CMD5Shim* copy=new(ELeave) CMD5Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->CopyL();
+	CleanupStack::Pop();
+	return copy;
+	}
+
+CMessageDigest* CMD5Shim::ReplicateL()
+	{
+	CMD5Shim* copy=new(ELeave) CMD5Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->ReplicateL();
+	CleanupStack::Pop();
+	return copy;
+	}
+
+TInt CMD5Shim::BlockSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}		
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iBlockSize/8;
+	}
+
+TInt CMD5Shim::HashSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}		
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iOutputSize/8;
+	}
+
+void CMD5Shim::Update(const TDesC8& aMessage)
+	{
+	iHashImpl->Update(aMessage);	
+	}
+	
+TPtrC8 CMD5Shim::Final(const TDesC8& aMessage)
+	{
+	return iHashImpl->Final(aMessage);
+	}
+
+TPtrC8 CMD5Shim::Final()
+	{
+	TPtrC8 ptr(KNullDesC8());
+	return iHashImpl->Final(ptr);
+	}
+		
+void CMD5Shim::Reset()
+	{
+	iHashImpl->Reset();
+	}
+	
+
+TPtrC8 CMD5Shim::Hash(const TDesC8& aMessage)
+	{
+	return iHashImpl->Hash(aMessage);
+	}
+	
+//
+// Implementation of SHA1 shim
+//	
+	
+CSHA1Shim* CSHA1Shim::NewL()
+	{
+	CSHA1Shim* self=CSHA1Shim::NewLC();
+	CleanupStack::Pop();
+	return self;	
+	}
+
+CSHA1Shim* CSHA1Shim::NewLC()
+	{
+	
+	CSHA1Shim* self=new(ELeave) CSHA1Shim();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;	
+	
+	}
+
+CSHA1Shim::CSHA1Shim()
+	{		
+	}
+	
+	
+TInt CSHA1Shim::Extension_(TUint aExtensionId, TAny*& a0, TAny* /*a1*/)
+	{
+	TInt ret(KErrNotSupported);
+	
+	if (KHashInterfaceUid.iUid==aExtensionId && iHashImpl)
+		{
+		a0=iHashImpl;
+		ret=KErrNone;	
+		}
+		
+	return ret;
+	}
+
+CSHA1Shim::~CSHA1Shim()
+	{
+	delete iHashImpl;			
+	}
+
+
+void CSHA1Shim::ConstructL()
+	{
+	CHashFactory::CreateHashL(iHashImpl,
+							KSha1Uid,
+							KHashModeUid,
+							NULL,
+							NULL);
+	}
+
+CMessageDigest* CSHA1Shim::CopyL()
+	{
+	CSHA1Shim* copy=new(ELeave) CSHA1Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->CopyL();
+	CleanupStack::Pop();
+	return copy;
+	}
+	
+CMessageDigest* CSHA1Shim::ReplicateL()
+	{
+	CSHA1Shim* copy=new(ELeave) CSHA1Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->ReplicateL();
+	CleanupStack::Pop();
+	return copy;
+	}
+
+TInt CSHA1Shim::BlockSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}	
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iBlockSize/8;
+	}
+
+TInt CSHA1Shim::HashSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iOutputSize/8;
+	}
+
+void CSHA1Shim::Update(const TDesC8& aMessage)
+	{
+	iHashImpl->Update(aMessage);	
+	}
+	
+TPtrC8 CSHA1Shim::Final(const TDesC8& aMessage)
+	{
+	return iHashImpl->Final(aMessage);
+	}
+
+TPtrC8 CSHA1Shim::Final()
+	{
+	TPtrC8 ptr(KNullDesC8());
+	return iHashImpl->Final(ptr);
+	}
+		
+void CSHA1Shim::Reset()
+	{
+	iHashImpl->Reset();
+	}
+
+TPtrC8 CSHA1Shim::Hash(const TDesC8& aMessage)
+	{
+	return iHashImpl->Hash(aMessage);
+	}
+	
+
+//
+// Implementation of SHA2 shim
+//	
+	
+CSHA2Shim* CSHA2Shim::NewL(TSH2Algo aAlgorithmId)
+	{
+	CSHA2Shim* self=CSHA2Shim::NewLC(aAlgorithmId);
+	CleanupStack::Pop();
+	return self;	
+	}
+
+CSHA2Shim* CSHA2Shim::NewLC(TSH2Algo aAlgorithmId)
+	{
+	
+	CSHA2Shim* self=new(ELeave) CSHA2Shim();
+	CleanupStack::PushL(self);
+	self->ConstructL(aAlgorithmId);
+	return self;
+	}
+
+CSHA2Shim::CSHA2Shim()
+	{		
+	}
+	
+TInt CSHA2Shim::Extension_(TUint aExtensionId, TAny*& a0, TAny* /*a1*/)
+	{
+	TInt ret(KErrNotSupported);
+	
+	if (KHashInterfaceUid.iUid==aExtensionId && iHashImpl)
+		{
+		a0=iHashImpl;
+		ret=KErrNone;	
+		}
+	return ret;
+	}
+
+CSHA2Shim::~CSHA2Shim()
+	{
+	delete iHashImpl;			
+	}
+
+void CSHA2Shim::ConstructL(TSH2Algo aAlgorithmId)
+	{
+	TUid algoId = {0};
+	switch(aAlgorithmId)
+		{
+		case E224Bit:
+			{
+			algoId = KSha224Uid;
+			break;
+			}
+		case E256Bit:
+			{
+			algoId = KSha256Uid;
+			break;
+			}
+		case E384Bit:
+			{
+			algoId = KSha384Uid;
+			break;
+			}
+		case E512Bit:
+			{
+			algoId = KSha512Uid;
+			break;
+			}
+		default:
+			User::Leave(KErrNotSupported);
+		}
+	
+	CHashFactory::CreateHashL(iHashImpl,
+							  algoId,
+							  KHashModeUid,
+							  NULL,
+							  NULL);				
+	}
+
+CMessageDigest* CSHA2Shim::CopyL()
+	{
+	CSHA2Shim* copy=new(ELeave) CSHA2Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->CopyL();
+	CleanupStack::Pop();
+	return copy;
+	}
+	
+CMessageDigest* CSHA2Shim::ReplicateL()
+	{
+	CSHA2Shim* copy=new(ELeave) CSHA2Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->ReplicateL();
+	CleanupStack::Pop();
+	return copy;
+	}
+
+TInt CSHA2Shim::BlockSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}	
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iBlockSize/8;
+	}
+
+TInt CSHA2Shim::HashSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iOutputSize/8;
+	}
+
+void CSHA2Shim::Update(const TDesC8& aMessage)
+	{
+	iHashImpl->Update(aMessage);	
+	}
+	
+TPtrC8 CSHA2Shim::Final(const TDesC8& aMessage)
+	{
+	return iHashImpl->Final(aMessage);
+	}
+
+TPtrC8 CSHA2Shim::Final()
+	{
+	TPtrC8 ptr(KNullDesC8());
+	return iHashImpl->Final(ptr);
+	}
+		
+void CSHA2Shim::Reset()
+	{
+	iHashImpl->Reset();
+	}
+
+TPtrC8 CSHA2Shim::Hash(const TDesC8& aMessage)
+	{
+	return iHashImpl->Hash(aMessage);
+	}
+
+//
+// Implementation of HMAC shim
+//	
+
+CHMACShim* CHMACShim::NewL(const TDesC8& aKey, CMessageDigest* aDigest)
+	{
+	CHMACShim* self(0);
+	
+	// Check whether the hash contains an SPI plug-in
+	TAny* implPtr(0);
+	TInt err = aDigest->GetExtension(CryptoSpi::KHashInterface, implPtr, NULL);	
+	if (err == KErrNone && implPtr)
+		{
+		CryptoSpi::CHash* impl(static_cast<CryptoSpi::CHash*>(implPtr));
+		const CryptoSpi::TCharacteristics* c(0);
+		impl->GetCharacteristicsL(c);
+		const CryptoSpi::THashCharacteristics* hashCharacteristics(static_cast<const CryptoSpi::THashCharacteristics*>(c));
+			
+		
+		// Verify that the plug-in supports Hmac mode
+		if (hashCharacteristics->IsOperationModeSupported(CryptoSpi::KHmacModeUid))
+			{
+			
+	#ifndef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT				
+			// Make an own copy
+			CHash* myHash=impl->ReplicateL();
+			CleanupStack::PushL(myHash);	
+	#endif	
+			// Set the key
+			TKeyProperty keyProperty = {KHmacModeUid, KNullUid, KSymmetricKey, KNonEmbeddedKeyUid};
+		 	CCryptoParams* keyParam =CCryptoParams::NewLC();
+		 	keyParam->AddL(aKey, KHmacKeyParameterUid);
+		 	CKey* uniKey= CKey::NewLC(keyProperty, *keyParam);
+	#ifndef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT		
+		 	myHash->SetKeyL(*uniKey);		 			 	
+		 	CleanupStack::PopAndDestroy(2, keyParam);
+			// Set hash to Hmac mode			
+			myHash->SetOperationModeL(CryptoSpi::KHmacModeUid);
+			self = new(ELeave) CHMACShim(myHash, aDigest);
+			CleanupStack::Pop(myHash);
+	#else 	
+		 	TUid algorithmUID = algorithmUID.Uid(hashCharacteristics->cmn.iAlgorithmUID);
+			//Create a pointer for the Mac Implementation Object
+			CMac* macImpl = NULL;
+			CMacFactory::CreateMacL(macImpl,algorithmUID,*uniKey, NULL);
+			CleanupStack::PushL(macImpl);
+		 	self = new(ELeave) CHMACShim(macImpl, aDigest,uniKey, algorithmUID);
+		 	CleanupStack::Pop(macImpl);
+		 	CleanupStack::Pop(uniKey);			
+		 	CleanupStack::PopAndDestroy(keyParam);
+	#endif		 	
+			}
+		}				
+	return self;
+	}
+	
+#ifdef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT	
+
+CHMACShim::CHMACShim(CryptoSpi::CMac* aImpl, CMessageDigest* aDigest, CryptoSpi::CKey* aKey, TUid aAlgorithmUid)
+	: CHMAC(aDigest), iMacImpl(aImpl), iKey(aKey), iAlgorithmUid(aAlgorithmUid)
+	{		
+	}
+
+#else
+
+CHMACShim::CHMACShim(CryptoSpi::CHash* aImpl, CMessageDigest* aDigest)
+	: CHMAC(aDigest), iMacImpl(aImpl)
+	{		
+	}
+
+#endif
+
+CHMACShim::CHMACShim()
+	{		
+	}
+
+CHMACShim::~CHMACShim()
+	{
+	delete iMacImpl;
+#ifdef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT		
+	delete iKey;
+#endif
+	}
+
+TInt CHMACShim::BlockSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iMacImpl->GetCharacteristicsL(ptr));
+
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}
+
+#ifndef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT			
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iBlockSize/8;
+#else		
+	const TMacCharacteristics* macPtr=static_cast<const TMacCharacteristics*>(ptr);
+	return macPtr->iHashAlgorithmChar->iBlockSize/8;
+#endif	
+	}
+
+TInt CHMACShim::HashSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iMacImpl->GetCharacteristicsL(ptr));
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}
+
+#ifndef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT			
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iOutputSize/8;
+#else			
+	const TMacCharacteristics* macPtr=static_cast<const TMacCharacteristics*>(ptr);
+	return macPtr->iHashAlgorithmChar->iOutputSize/8;
+#endif	
+	}
+
+void CHMACShim::Update(const TDesC8& aMessage)
+	{
+#ifdef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT
+	// The error is ignored as the legacy code methods are non-leaving and they call 
+	// the new MAC interfaces which uses leaving methods for processing MAC value. 	
+	// This call always call the non-leaving legacy method.	
+	TRAP_IGNORE(iMacImpl->UpdateL(aMessage));
+#else
+	iMacImpl->Update(aMessage);
+#endif	
+	}
+	
+TPtrC8 CHMACShim::Final(const TDesC8& aMessage)
+	{
+#ifdef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT
+	TPtrC8 macPtr(KNullDesC8());
+	// The error is ignored as the legacy code methods are non-leaving and they call 
+	// the new MAC interfaces which uses leaving methods for processing MAC value. 	
+	// This call always call the non-leaving legacy method.	
+	TRAP_IGNORE(macPtr.Set(iMacImpl->FinalL(aMessage)));	
+	return macPtr;
+#else
+	return iMacImpl->Final(aMessage);
+#endif	
+	}
+
+TPtrC8 CHMACShim::Final()
+	{
+	TPtrC8 ptr(KNullDesC8());
+#ifdef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT
+	TPtrC8 macPtr(KNullDesC8());
+	// The error is ignored as the legacy code methods are non-leaving and they call 
+	// the new MAC interfaces which uses leaving methods for processing MAC value. 	
+	// This call always call the non-leaving legacy method.	
+	TRAP_IGNORE(macPtr.Set(iMacImpl->FinalL(ptr)));	
+	return macPtr;
+#else
+	return iMacImpl->Final(ptr);
+#endif	
+	}
+		
+void CHMACShim::Reset()
+	{
+	iMacImpl->Reset();
+	}
+	
+TPtrC8 CHMACShim::Hash(const TDesC8& aMessage)
+	{
+#ifdef SYMBIAN_SDP_IPSEC_VOIP_SUPPORT	
+	TPtrC8 macPtr(KNullDesC8());
+	// The error is ignored as the legacy code methods are non-leaving and they call 
+	// the new MAC interfaces which uses leaving methods for processing MAC value. 	
+	// This call always call the non-leaving legacy method.	
+	TRAP_IGNORE(macPtr.Set(iMacImpl->MacL(aMessage)));	
+	return macPtr;
+#else
+	return iMacImpl->Hash(aMessage);
+#endif	
+	}
+	
+CMessageDigest* CHMACShim::ReplicateL()
+	{
+	CHMACShim* copy=new(ELeave) CHMACShim();
+	CleanupStack::PushL(copy);
+	copy->iMacImpl=iMacImpl->ReplicateL();
+	CleanupStack::Pop(copy);
+	return copy;	
+	}
+	
+CMessageDigest* CHMACShim::CopyL()
+	{
+	CHMACShim* copy=new(ELeave) CHMACShim();
+	CleanupStack::PushL(copy);
+	copy->iMacImpl=iMacImpl->CopyL();
+	CleanupStack::Pop(copy);
+	return copy;	
+	}
+
+//
+// Implemetation of MD4 shim
+//
+CMD4Shim* CMD4Shim::NewL()
+	{
+	CMD4Shim* self=CMD4Shim::NewLC();
+	CleanupStack::Pop();
+	return self;	
+	}
+
+CMD4Shim* CMD4Shim::NewLC()
+	{
+	CMD4Shim* self=new(ELeave) CMD4Shim();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;	
+	}
+
+CMD4Shim::CMD4Shim()
+	{		
+	}
+	
+TInt CMD4Shim::Extension_(TUint aExtensionId, TAny*& a0, TAny* /*a1*/)
+	{
+	TInt ret(KErrNotSupported);
+	
+	if (KHashInterfaceUid.iUid==aExtensionId && iHashImpl)
+		{
+		a0=iHashImpl;
+		ret=KErrNone;	
+		}
+		
+	return ret;
+	}
+
+CMD4Shim::~CMD4Shim()
+	{
+	delete iHashImpl;				
+	}
+
+
+void CMD4Shim::ConstructL()
+	{	
+	CHashFactory::CreateHashL(iHashImpl,KMd4Uid,KHashModeUid,NULL,NULL);
+	}
+
+CMessageDigest* CMD4Shim::CopyL()
+	{
+	CMD4Shim* copy=new(ELeave) CMD4Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->CopyL();
+	CleanupStack::Pop();
+	return copy;
+	}
+
+CMessageDigest* CMD4Shim::ReplicateL()
+	{
+	CMD4Shim* copy=new(ELeave) CMD4Shim();
+	CleanupStack::PushL(copy);
+	copy->iHashImpl=iHashImpl->ReplicateL();
+	CleanupStack::Pop();
+	return copy;
+	}
+
+TInt CMD4Shim::BlockSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}		
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iBlockSize/8;
+	}
+
+TInt CMD4Shim::HashSize()
+	{
+	const TCharacteristics* ptr(NULL);
+	TRAPD(err, iHashImpl->GetCharacteristicsL(ptr);)
+	if (err)
+		{
+		return ((err>0)? KErrGeneral : err);
+		}		
+	const THashCharacteristics* hashPtr=static_cast<const THashCharacteristics*>(ptr);
+	return hashPtr->iOutputSize/8;
+	}
+
+void CMD4Shim::Update(const TDesC8& aMessage)
+	{
+	iHashImpl->Update(aMessage);	
+	}
+	
+TPtrC8 CMD4Shim::Final(const TDesC8& aMessage)
+	{
+	return iHashImpl->Final(aMessage);
+	}
+
+TPtrC8 CMD4Shim::Final()
+	{
+	TPtrC8 ptr(KNullDesC8());
+	return iHashImpl->Final(ptr);
+	}
+		
+void CMD4Shim::Reset()
+	{
+	iHashImpl->Reset();
+	}
+	
+
+TPtrC8 CMD4Shim::Hash(const TDesC8& aMessage)
+	{
+	return iHashImpl->Hash(aMessage);
+	}
+