--- /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);
+ }