authenticationservices/authenticationserver/test/reftestplugin/pinplugin/pinpluginao.cpp
changeset 19 ece3df019add
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/authenticationservices/authenticationserver/test/reftestplugin/pinplugin/pinpluginao.cpp	Tue Nov 24 09:06:03 2009 +0200
@@ -0,0 +1,477 @@
+/*
+* 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: 
+* CPinPluginAO implementation
+*
+*/
+
+
+/**
+ @file 
+*/
+
+#include "pinpluginao.h"
+#include <hash.h>
+#include <authserver/auth_srv_errs.h>
+#include <authserver/authtypes.h>
+#include <e32math.h>
+
+using namespace AuthServer;
+
+/** 
+ KDefaultPinDigit is used to generate the default pinvalue for the DefaultData().
+ The default pinvalue is generated by appending KDefaultPinDigit for iPinSize times.
+ */
+const TUint KDefaultPinDigit = 1;
+
+/** 
+ The selected pin index for the Train/Retrain operation, returned by
+ Dialog Notifier should be in the range KIndexLow and KIndexHigh. This should
+ be validated in the Dialog implementation. If Pinplugin receives any other
+ values, then pinplugin will panic.
+ */
+const TInt KIndexLow = 0;
+const TInt KIndexHigh = 3;
+
+CPinPluginAO* CPinPluginAO::NewL(TInt aPinSize, TInt aPinMinSize, TInt aPinMaxSize, TInt aRetryCount)
+	{
+	CPinPluginAO* self = CPinPluginAO::NewLC(aPinSize, aPinMinSize, aPinMaxSize, aRetryCount);
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CPinPluginAO* CPinPluginAO::NewLC(TInt aPinSize, TInt aPinMinSize, TInt aPinMaxSize, TInt aRetryCount)
+	{
+	CPinPluginAO* self = new(ELeave) CPinPluginAO(aPinSize, aPinMinSize, aPinMaxSize, aRetryCount);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+	
+CPinPluginAO::CPinPluginAO(TInt aPinSize, TInt aPinMinSize, TInt aPinMaxSize, TInt aRetryCount)
+	:CActive(EPriorityStandard), iRetryCount(aRetryCount), iPinSize(aPinSize), iPinMinSize(aPinMinSize),
+	iPinMaxSize(aPinMaxSize)
+	{
+	CActiveScheduler::Add(this);
+	}
+	
+void CPinPluginAO::ConstructL()
+	{
+	iNewPinSize = iPinSize;
+	
+	// construct PinpluginDialog
+	iPinPluginDialog = CPinPluginDialog::NewL();
+	// construct the DB
+	iPinPluginDb = CPinPluginDB::NewL();
+	iDialogResult = new (ELeave) TPinPluginDialogResult;
+	iRetryRefCount = iRetryCount;
+	}
+
+CPinPluginAO::~CPinPluginAO()
+	{
+	Deque();
+	delete iDialogResult;
+	delete iPinPluginDialog;
+	delete iPinPluginDb;
+	iPinList.ResetAndDestroy();
+	iIdKeyList.ResetAndDestroy();
+	iIdKeyHashList.ResetAndDestroy();
+	}
+	
+void CPinPluginAO::Identify(TIdentityId& aId, const TDesC& aClientMessage,
+							HBufC8*& aResult, TRequestStatus& aRequest)
+	{
+	iState = EIdentify;
+	iIdentityId = aId;
+	iIdentityIdPtr = &aId;
+	
+	aRequest = KRequestPending;
+	iRequestStatus = &aRequest;
+
+	iClientMessage = static_cast<const HBufC*>(&aClientMessage);
+	iResult = &aResult;
+	aResult = NULL;	
+ 
+	SetActive();
+	TRequestStatus* stat = &iStatus;
+	User::RequestComplete(stat, KErrNone);
+	}
+
+void CPinPluginAO::Train(TIdentityId aId, HBufC8*& aResult, TRequestStatus& aRequest)
+	{
+	iState = ETrain;
+	iIdentityId = aId;
+
+	aRequest = KRequestPending;
+	iRequestStatus = &aRequest;
+
+	iResult = &aResult;
+	aResult = NULL;	
+
+	SetActive();
+	TRequestStatus* stat = &iStatus;
+	User::RequestComplete(stat, KErrNone);
+    }
+	
+TInt CPinPluginAO::DefaultData(TIdentityId aId, HBufC8*& aOutputBuf)
+	{
+	aOutputBuf = NULL;
+	TPinValue defaultPin;
+	for (TInt i = 0; i < iPinSize; i++)
+		{
+		defaultPin.AppendNum(KDefaultPinDigit);	
+		}
+		
+	HBufC8* identityKey = NULL;
+	HBufC8* identityKeyHash = NULL;
+	TRAPD(err, 
+		identityKeyHash = GenerateKeyHashL(defaultPin, identityKey);
+		CleanupStack::PushL(identityKeyHash);
+		CleanupStack::PushL(identityKey);
+		aOutputBuf = (*identityKey).AllocL();
+		iPinPluginDb->AddPinL(aId, *identityKeyHash);
+		CleanupStack::PopAndDestroy(2, identityKeyHash));
+		
+	return err;
+	}
+
+TInt CPinPluginAO::Forget(TIdentityId aId)
+	{
+	TInt err = KErrNone;
+	TRAP(err, iPinPluginDb->RemovePinL(aId));
+	if (err == KErrNotFound)
+		{
+		err = KErrAuthServNoSuchIdentity;
+		}
+	return err;
+	}
+
+void CPinPluginAO::ResetL(TIdentityId aIdentityId, const TDesC& aRegistrationData, HBufC8*& aResult)
+	{
+	// Remove the current trained information and register using the newly supplied registration
+	// data (Since pin plugin is a knowledge based plugin, the registration data supplied is assumed to be the pin)
+	// For other plugin types this information is ignored and the identity is simply set as untrained
+
+	// If no registration data is supplied then just perform a forget
+	if (aRegistrationData == KNullDesC)
+		{
+		aResult = NULL;
+		TInt err = Forget(aIdentityId);
+		User::LeaveIfError(err);
+		return;
+		}
+
+	// Ensure registration data length is less than or equal to max allowed pin length
+	TInt pinLen = aRegistrationData.Length();
+	if (pinLen > KMaxPinLength)
+		{
+		User::Leave(KErrArgument);
+		}
+
+	// Convert registration data to 8 bit 
+	// Note that no unicode conversion is being done here since a pin cannot be in unicode
+	RBuf8 pinBuf;
+	pinBuf.CreateL(pinLen);
+	CleanupClosePushL(pinBuf);
+	pinBuf.Copy(aRegistrationData.Left(pinLen));
+	TPinValue pin(pinBuf);
+	CleanupStack::PopAndDestroy(&pinBuf);
+
+	// Generate the identity key and identity key hash
+	HBufC8* identityKey = NULL;
+	HBufC8* identityKeyHash = GenerateKeyHashL(pin, identityKey);
+	CleanupStack::PushL(identityKeyHash);
+	CleanupStack::PushL(identityKey);
+
+	// Ensure another identity doesn't have the same pin
+	TIdentityId tempId = iPinPluginDb->IdFromPin(*identityKeyHash);
+	if ((tempId != aIdentityId) && (tempId != KUnknownIdentity))
+		{
+		CleanupStack::PopAndDestroy(2, identityKeyHash);
+		// This appears to be the most appropriate error code - The important point is to convery Reset has failed.
+		User::Leave(KErrInUse);
+		}
+	else if (tempId == aIdentityId)
+		{
+		// Nothing to do
+		aResult = identityKey;		// Ownership transferred to caller
+		CleanupStack::Pop(identityKey);
+		CleanupStack::PopAndDestroy(identityKeyHash);
+		return;
+		}
+
+	// Replace the training data
+	iPinPluginDb->UpdatePinL(aIdentityId, *identityKeyHash);
+	aResult = identityKey;		// Ownership transferred to caller
+	CleanupStack::Pop(identityKey);
+	CleanupStack::PopAndDestroy(identityKeyHash);
+	}
+
+void CPinPluginAO::DoCancel()
+	{
+	iPinPluginDialog->Cancel();
+	if(iRequestStatus)
+		{
+		User::RequestComplete(iRequestStatus, KErrCancel);
+		}
+	}
+	
+void CPinPluginAO::RunL()
+	{
+	// Leave if there has been an error
+	User::LeaveIfError(iStatus.Int());
+	
+	switch(iState)
+		{
+		case EIdentify:
+			{
+			IdentifyId();	
+			}
+			break;
+		case EIdentifyResult:
+			{
+			if (*iDialogResult == EOk)
+				{
+				IdentifyResultL();
+				}
+			else if (*iDialogResult == ECancel)
+				{
+				User::RequestComplete(iRequestStatus, KErrAuthServPluginCancelled);
+				}
+			else if (*iDialogResult == EQuit)
+				{
+				User::RequestComplete(iRequestStatus, KErrAuthServPluginQuit);
+				}
+			*iDialogResult = static_cast<TPinPluginDialogResult>(0);
+			}
+			break;
+		case ETrain:
+			{
+			TrainIdL();	
+			}
+			break;
+		case ETrainResult:
+			{
+			if (*iDialogResult == EOk)
+				{
+				AddTrainResultToDBL();
+				}
+			else if (*iDialogResult == ECancel)
+				{
+				User::RequestComplete(iRequestStatus, KErrAuthServPluginCancelled);
+				}
+			else if (*iDialogResult == EQuit)
+				{
+				User::RequestComplete(iRequestStatus, KErrAuthServPluginQuit);
+				}
+			else if (*iDialogResult == ENext)
+				{
+				iState = ETrain;
+				TRequestStatus* status = &iStatus;
+				User::RequestComplete(status, KErrNone);
+				SetActive();
+				}
+			*iDialogResult = static_cast<TPinPluginDialogResult>(0);
+			}
+			break;
+		case EInfo:
+			{
+			iPinPluginDialog->PinInfo(iMessage, iStatus);
+			iState = EFinished;
+			SetActive();
+			}
+			break;
+		case EFinished:
+			{
+			User::RequestComplete(iRequestStatus, iStatus.Int());
+			}
+			break;
+		default:
+			{
+			User::Leave(KErrNotSupported);
+			}
+			break;
+		}
+	}
+	
+TInt CPinPluginAO::RunError(TInt aError)
+	{
+	if(iRequestStatus)
+		{
+		User::RequestComplete(iRequestStatus, aError);
+		}
+	return KErrNone;
+	}
+
+void CPinPluginAO::IdentifyId()
+	{
+	if (iRetryRefCount--)
+		{
+		iPinPluginDialog->PinIdentify(iPinMinSize, iPinMaxSize, ETrue, iPinValue, *iDialogResult, iStatus);
+		iState = EIdentifyResult;
+		}
+	else
+		{
+		iRetryRefCount = iRetryCount;
+		*iIdentityIdPtr = KUnknownIdentity;
+		iMessage = EPinPluginIdentificationFailure;
+		TRequestStatus* status = &iStatus;
+		User::RequestComplete(status, KErrNone);
+		iState = EInfo;
+		}
+	SetActive();
+	}
+
+void CPinPluginAO::IdentifyResultL()
+	{
+	TIdentityId identityId;
+	HBufC8* identityKey = NULL;
+	HBufC8* identityKeyHash = GenerateKeyHashL(iPinValue, identityKey);
+	CleanupStack::PushL(identityKeyHash);
+	CleanupStack::PushL(identityKey);	
+	identityId = iPinPluginDb->IdFromPin(*identityKeyHash);
+	if (identityId != KUnknownIdentity)
+		{
+		*iIdentityIdPtr = identityId;
+		iRetryRefCount = iRetryCount;
+		*iResult = identityKey;
+		iMessage = EPinPluginIdentificationSuccess;
+		iState = EInfo;
+		CleanupStack::Pop(identityKey);
+		}
+	else
+		{	
+		CleanupStack::PopAndDestroy(identityKey);
+		iState = EIdentify;
+		}
+	CleanupStack::PopAndDestroy(identityKeyHash);
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+		
+void CPinPluginAO::TrainIdL()
+	{
+        // Check for invalid pinsize.
+	if( !(iNewPinSize >= iPinMinSize && iNewPinSize <= iPinMaxSize)  )
+                {
+                User::Leave(KErrAuthServRegistrationFailed);
+                }
+
+
+	iPinList.ResetAndDestroy();
+	iIdKeyList.ResetAndDestroy();
+	iIdKeyHashList.ResetAndDestroy();
+	GenerateUniquePinsL(iPinList, iIdKeyList, iIdKeyHashList);
+	TInt indexValue = iPinPluginDb->IdIndex(iIdentityId);
+	TPinPluginTrainingMessage trainMessage;
+	if (indexValue >= 0)
+		{
+		trainMessage = EReTraining;
+		}
+	else
+		{
+		trainMessage = ETraining;
+		}
+	iPinPluginDialog->PinTraining(trainMessage, iPinList, iPinMinSize, iPinMaxSize, iIndex, iNewPinSize, *iDialogResult, iStatus);
+	iState = ETrainResult;
+	SetActive();	
+	}
+
+void CPinPluginAO::AddTrainResultToDBL()
+	{
+	__ASSERT_ALWAYS(iIndex >= KIndexLow && iIndex <= KIndexHigh,
+		User::Panic(KPinPluginPanicString(), EPinPanicIncorrectIndex));
+
+	TInt indexValue = iPinPluginDb->IdIndex(iIdentityId);
+	if (indexValue >= 0)
+		{
+		iPinPluginDb->UpdatePinL(iIdentityId, *iIdKeyHashList[iIndex]);
+		iMessage = EPinPluginReTrainingSuccess;
+		}
+	else
+		{
+		iPinPluginDb->AddPinL(iIdentityId, *iIdKeyHashList[iIndex]);
+		iMessage = EPinPluginTrainingSuccess;
+		}
+	TPtrC8 idKeyPtr = *iIdKeyList[iIndex];
+	HBufC8* identityKey = idKeyPtr.AllocL();
+	*iResult = identityKey;
+	iNewPinSize = iPinSize;
+	iState = EInfo;
+	TRequestStatus* status = &iStatus;
+	User::RequestComplete(status, KErrNone);
+	SetActive();
+	}
+
+HBufC8* CPinPluginAO::GenerateKeyHashL(TPinValue& aPinValue, HBufC8*& aIdentityKey)
+	{
+	CSHA1* sha1 = CSHA1::NewL();
+	CleanupStack::PushL(sha1);
+	HBufC8* pinValue = aPinValue.AllocLC();
+	TPtrC8 hash = sha1->Hash(*pinValue);
+	CleanupStack::PopAndDestroy(pinValue);
+	aIdentityKey = hash.AllocLC();
+	TPtrC8 hash1 = sha1->Hash(hash);
+	HBufC8* idkeyHash = hash1.AllocL();
+	CleanupStack::Pop(aIdentityKey);
+	CleanupStack::PopAndDestroy(sha1);
+	return idkeyHash;
+	}
+	
+	
+void CPinPluginAO::GenerateUniquePinsL(RPointerArray<TPinValue>& aPinList,
+		RPointerArray<HBufC8>& aIdKeyList, RPointerArray<HBufC8>& aIdKeyHashList)
+	{
+	TInt count = 4; 
+	while (count)
+		{
+		TPinValue* randomPin = new (ELeave) TPinValue;
+		CleanupStack::PushL(randomPin);
+		for (TInt k = 0; k < iNewPinSize ; k++)
+			{
+			TUint8 num = Math::Random();
+			num = num % 10;
+			randomPin->AppendNum(num);
+			}
+		HBufC8* identityKey = NULL;
+		HBufC8* identityKeyHash = GenerateKeyHashL(*randomPin, identityKey);
+		CleanupStack::PushL(identityKeyHash);
+		CleanupStack::PushL(identityKey);
+		if (iPinPluginDb->IsUniquePin(*identityKeyHash))
+			{
+			aIdKeyList.AppendL(identityKey);
+			CleanupStack::Pop(identityKey);
+			aIdKeyHashList.AppendL(identityKeyHash);
+			CleanupStack::Pop(identityKeyHash);
+			aPinList.AppendL(randomPin);
+			CleanupStack::Pop(randomPin);
+			count--;
+			}
+		}
+	}
+
+
+
+
+
+
+
+
+
+
+	
+	
+	
+