crypto/weakcryptospi/source/random/randsvr.cpp
changeset 19 cd501b96611d
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/crypto/weakcryptospi/source/random/randsvr.cpp	Fri Nov 06 13:21:00 2009 +0200
@@ -0,0 +1,255 @@
+/*
+* Copyright (c) 2005-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: 
+*
+*/
+
+
+/**
+ @file
+*/
+
+#include "randsvr.h"
+#include "randcliserv.h"
+#include "sha1shim.h"
+#include <e32math.h>
+#include "randsvrimpl.h"
+
+//const TInt KFastTickTimer=1000000;			// These are testing numbers!
+//const TInt KSlowTickTimer=30000000;
+const TInt KThreshold=1024;
+
+const TInt KFastTickTimer=30000000;			// These are the real numbers!
+const TInt KSlowTickTimer=0x7fffffff;
+
+using namespace CryptoSpi;
+
+void SignalClient()
+//
+// Signal the owning thread that the server has started successfully
+// This may itself fail
+//
+	{
+	RProcess::Rendezvous(KErrNone);
+	}
+
+
+TInt RunRandomServer(TAny* /*aUnused*/)
+	{
+
+	__UHEAP_MARK;
+
+	CTrapCleanup* cleanup=CTrapCleanup::New();
+	if (!cleanup)
+		{
+		return KErrNoMemory;
+		}
+
+	TInt ret = User::RenameThread(KRandomServerName);
+
+	__ASSERT_ALWAYS(ret==KErrNone,User::Panic(KRandomServerName,KErrServerTerminated));
+
+	if (CRandomScheduler::New())
+		return KErrNoMemory;
+	CRandomServer* random(0);
+	TRAP(ret, random = CRandomServer::NewL());
+	if (ret != KErrNone)
+		return ret;
+	random->Start(KRandomServerName);
+	// Initialisation complete, now signal the client
+	SignalClient();
+	
+	CRandomScheduler::Start();
+	delete random;
+	delete cleanup;
+
+	__UHEAP_MARKEND;
+	return KErrNone;
+	}
+
+TBool CRandomScheduler::New(void)
+	{
+	CRandomScheduler* rs;
+	rs=new CRandomScheduler;
+	CRandomScheduler::Install(rs);
+	return (rs == NULL);
+	}
+
+void CRandomScheduler::Error(TInt /*aError*/) const 
+	{
+	User::Panic(KRandomServerName, 3);
+	}
+
+CRandomServer::CRandomServer(void) : CServer2(EPriorityLow)
+	{
+	}
+
+CRandomServer::~CRandomServer(void)
+	{
+	// This should never happen....but in case it does:
+	delete iHash;
+	delete iTicker;
+	delete iPool;
+	}
+
+CRandomServer* CRandomServer::NewL(void)
+	{
+	CRandomServer* self = new (ELeave) CRandomServer;
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+void CRandomServer::ConstructL(void)
+	{
+	iPool=new (ELeave) TUint8[KRandomPoolSize];
+	iHash=CSHA1Shim::NewL();
+	iPoolIn=0;
+	iPoolOut=0;
+	iTicker=CPeriodic::NewL(EPriorityLow);
+	TCallBack callback(Tick,this);
+	iTicker->Start(KFastTickTimer,KFastTickTimer,callback);		// **** these figures might need tweaking!
+	iQuality=0;
+	iFast=ETrue;
+	}
+
+TInt CRandomServer::Tick(TAny* aServer)
+	{
+	CRandomServer* svr=(CRandomServer*)aServer;
+	svr->Stir();
+	svr->iQuality+=30;
+	if (svr->iFast)
+		{
+		if (svr->iQuality>KThreshold)
+			{
+			TCallBack callback(Tick,svr);
+			svr->iTicker->Cancel();
+			svr->iTicker->Start(KSlowTickTimer,KSlowTickTimer,callback);		// **** these figures might need tweaking!
+			svr->iFast=EFalse;
+			}
+		}
+	if (svr->iQuality>(KRandomPoolSize<<3))
+		{
+		svr->iQuality=(KRandomPoolSize<<3);
+		}
+	return ETrue;
+	}
+
+CSession2* CRandomServer::NewSessionL(const TVersion& /*aVersion*/, const RMessage2& /*aMessage*/) const
+	{
+	return CRandomSession::NewL(const_cast<CRandomServer*>(this));
+	//CRandomSession::NewL(CONST_CAST(CRandomServer*,this),Message().Client());
+	}
+
+TPtrC8 CRandomServer::GetRandom(void)
+	{
+	TPtr8 res(&iPool[iPoolOut],iHash->HashSize(),iHash->HashSize());
+	iPoolOut+=iHash->HashSize();
+	if ((iPoolOut+iHash->HashSize())>KRandomPoolSize)
+		{
+		iPoolOut=0;
+		}
+	return iHash->Hash(res);
+	}
+
+CMessageDigest* CRandomServer::Hash(void) const
+	{
+	return iHash;
+	}
+
+void CRandomServer::Stir(void) 
+	{
+	TInt rnd;
+	rnd=Math::Random();
+	TPtrC8 r((TUint8*)&rnd,sizeof(TInt));
+	iHash->Hash(r);
+	TPtr8 dest(&iPool[iPoolIn],iHash->HashSize());
+	dest.Copy(iHash->Hash(dest));
+	iPoolIn+=iHash->HashSize();
+	if ((iPoolIn+iHash->HashSize())>KRandomPoolSize)
+		{
+		iPoolIn=0;
+		}
+	}
+
+CRandomSession* CRandomSession::NewL(CRandomServer* aServer)
+	{
+	CRandomSession* self;
+	self=new (ELeave) CRandomSession(aServer);
+	return self;
+	}
+
+CRandomSession::CRandomSession(CRandomServer* aServer) : CSession2(), iServer(aServer)
+	{
+	}
+
+CRandomSession::~CRandomSession(void)
+	{
+	}
+
+void CRandomSession::ServiceL(const RMessage2& aMessage)
+	{
+	switch (aMessage.Function())
+		{
+	case KRandomRequest:
+		{
+		TInt ret = FillBuffer(aMessage);
+		aMessage.Complete(ret);
+		break;
+		}
+	default:
+		aMessage.Complete(KErrNotSupported);
+		break;
+		};
+	}
+
+TInt CRandomSession::FillBuffer(const RMessage2& aMessage)
+	{
+	TInt length = aMessage.Int1();
+	iServer->iQuality -= length;
+	if (iServer->iQuality<0)
+		{
+		iServer->iQuality=0;
+		}
+	if (!iServer->iFast)
+		{
+		if (iServer->iQuality<KThreshold)
+			{
+			TCallBack callback(CRandomServer::Tick,iServer);
+			iServer->iTicker->Cancel();
+			iServer->iTicker->Start(KFastTickTimer,KFastTickTimer,callback);		// **** these figures might need tweaking!
+			iServer->iFast=ETrue;
+			}
+		}
+	TBuf8<KRandomBlockSize> buf(0);
+	iServer->Stir();
+	TInt i;
+	TInt hashsize=iServer->Hash()->HashSize();
+	for (i=0; i+hashsize < length; i+=hashsize)
+		{
+		buf.Append(iServer->GetRandom());
+		iServer->Stir();
+		}
+	TPtrC8 ptr(iServer->GetRandom().Ptr(), length-i);
+	buf.Append(ptr);
+	
+	TRAPD(ret, aMessage.WriteL(0, buf));
+	return ret;
+	}
+
+GLDEF_C TInt E32Main(void)
+	{
+	return RunRandomServer(NULL);
+	}