authenticationservices/authenticationserver/test/reftestplugin/pinplugin/pinpluginao.cpp
changeset 29 ece3df019add
equal deleted inserted replaced
19:cd501b96611d 29:ece3df019add
       
     1 /*
       
     2 * Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * CPinPluginAO implementation
       
    16 *
       
    17 */
       
    18 
       
    19 
       
    20 /**
       
    21  @file 
       
    22 */
       
    23 
       
    24 #include "pinpluginao.h"
       
    25 #include <hash.h>
       
    26 #include <authserver/auth_srv_errs.h>
       
    27 #include <authserver/authtypes.h>
       
    28 #include <e32math.h>
       
    29 
       
    30 using namespace AuthServer;
       
    31 
       
    32 /** 
       
    33  KDefaultPinDigit is used to generate the default pinvalue for the DefaultData().
       
    34  The default pinvalue is generated by appending KDefaultPinDigit for iPinSize times.
       
    35  */
       
    36 const TUint KDefaultPinDigit = 1;
       
    37 
       
    38 /** 
       
    39  The selected pin index for the Train/Retrain operation, returned by
       
    40  Dialog Notifier should be in the range KIndexLow and KIndexHigh. This should
       
    41  be validated in the Dialog implementation. If Pinplugin receives any other
       
    42  values, then pinplugin will panic.
       
    43  */
       
    44 const TInt KIndexLow = 0;
       
    45 const TInt KIndexHigh = 3;
       
    46 
       
    47 CPinPluginAO* CPinPluginAO::NewL(TInt aPinSize, TInt aPinMinSize, TInt aPinMaxSize, TInt aRetryCount)
       
    48 	{
       
    49 	CPinPluginAO* self = CPinPluginAO::NewLC(aPinSize, aPinMinSize, aPinMaxSize, aRetryCount);
       
    50 	CleanupStack::Pop(self);
       
    51 	return self;
       
    52 	}
       
    53 
       
    54 CPinPluginAO* CPinPluginAO::NewLC(TInt aPinSize, TInt aPinMinSize, TInt aPinMaxSize, TInt aRetryCount)
       
    55 	{
       
    56 	CPinPluginAO* self = new(ELeave) CPinPluginAO(aPinSize, aPinMinSize, aPinMaxSize, aRetryCount);
       
    57 	CleanupStack::PushL(self);
       
    58 	self->ConstructL();
       
    59 	return self;
       
    60 	}
       
    61 	
       
    62 CPinPluginAO::CPinPluginAO(TInt aPinSize, TInt aPinMinSize, TInt aPinMaxSize, TInt aRetryCount)
       
    63 	:CActive(EPriorityStandard), iRetryCount(aRetryCount), iPinSize(aPinSize), iPinMinSize(aPinMinSize),
       
    64 	iPinMaxSize(aPinMaxSize)
       
    65 	{
       
    66 	CActiveScheduler::Add(this);
       
    67 	}
       
    68 	
       
    69 void CPinPluginAO::ConstructL()
       
    70 	{
       
    71 	iNewPinSize = iPinSize;
       
    72 	
       
    73 	// construct PinpluginDialog
       
    74 	iPinPluginDialog = CPinPluginDialog::NewL();
       
    75 	// construct the DB
       
    76 	iPinPluginDb = CPinPluginDB::NewL();
       
    77 	iDialogResult = new (ELeave) TPinPluginDialogResult;
       
    78 	iRetryRefCount = iRetryCount;
       
    79 	}
       
    80 
       
    81 CPinPluginAO::~CPinPluginAO()
       
    82 	{
       
    83 	Deque();
       
    84 	delete iDialogResult;
       
    85 	delete iPinPluginDialog;
       
    86 	delete iPinPluginDb;
       
    87 	iPinList.ResetAndDestroy();
       
    88 	iIdKeyList.ResetAndDestroy();
       
    89 	iIdKeyHashList.ResetAndDestroy();
       
    90 	}
       
    91 	
       
    92 void CPinPluginAO::Identify(TIdentityId& aId, const TDesC& aClientMessage,
       
    93 							HBufC8*& aResult, TRequestStatus& aRequest)
       
    94 	{
       
    95 	iState = EIdentify;
       
    96 	iIdentityId = aId;
       
    97 	iIdentityIdPtr = &aId;
       
    98 	
       
    99 	aRequest = KRequestPending;
       
   100 	iRequestStatus = &aRequest;
       
   101 
       
   102 	iClientMessage = static_cast<const HBufC*>(&aClientMessage);
       
   103 	iResult = &aResult;
       
   104 	aResult = NULL;	
       
   105  
       
   106 	SetActive();
       
   107 	TRequestStatus* stat = &iStatus;
       
   108 	User::RequestComplete(stat, KErrNone);
       
   109 	}
       
   110 
       
   111 void CPinPluginAO::Train(TIdentityId aId, HBufC8*& aResult, TRequestStatus& aRequest)
       
   112 	{
       
   113 	iState = ETrain;
       
   114 	iIdentityId = aId;
       
   115 
       
   116 	aRequest = KRequestPending;
       
   117 	iRequestStatus = &aRequest;
       
   118 
       
   119 	iResult = &aResult;
       
   120 	aResult = NULL;	
       
   121 
       
   122 	SetActive();
       
   123 	TRequestStatus* stat = &iStatus;
       
   124 	User::RequestComplete(stat, KErrNone);
       
   125     }
       
   126 	
       
   127 TInt CPinPluginAO::DefaultData(TIdentityId aId, HBufC8*& aOutputBuf)
       
   128 	{
       
   129 	aOutputBuf = NULL;
       
   130 	TPinValue defaultPin;
       
   131 	for (TInt i = 0; i < iPinSize; i++)
       
   132 		{
       
   133 		defaultPin.AppendNum(KDefaultPinDigit);	
       
   134 		}
       
   135 		
       
   136 	HBufC8* identityKey = NULL;
       
   137 	HBufC8* identityKeyHash = NULL;
       
   138 	TRAPD(err, 
       
   139 		identityKeyHash = GenerateKeyHashL(defaultPin, identityKey);
       
   140 		CleanupStack::PushL(identityKeyHash);
       
   141 		CleanupStack::PushL(identityKey);
       
   142 		aOutputBuf = (*identityKey).AllocL();
       
   143 		iPinPluginDb->AddPinL(aId, *identityKeyHash);
       
   144 		CleanupStack::PopAndDestroy(2, identityKeyHash));
       
   145 		
       
   146 	return err;
       
   147 	}
       
   148 
       
   149 TInt CPinPluginAO::Forget(TIdentityId aId)
       
   150 	{
       
   151 	TInt err = KErrNone;
       
   152 	TRAP(err, iPinPluginDb->RemovePinL(aId));
       
   153 	if (err == KErrNotFound)
       
   154 		{
       
   155 		err = KErrAuthServNoSuchIdentity;
       
   156 		}
       
   157 	return err;
       
   158 	}
       
   159 
       
   160 void CPinPluginAO::ResetL(TIdentityId aIdentityId, const TDesC& aRegistrationData, HBufC8*& aResult)
       
   161 	{
       
   162 	// Remove the current trained information and register using the newly supplied registration
       
   163 	// data (Since pin plugin is a knowledge based plugin, the registration data supplied is assumed to be the pin)
       
   164 	// For other plugin types this information is ignored and the identity is simply set as untrained
       
   165 
       
   166 	// If no registration data is supplied then just perform a forget
       
   167 	if (aRegistrationData == KNullDesC)
       
   168 		{
       
   169 		aResult = NULL;
       
   170 		TInt err = Forget(aIdentityId);
       
   171 		User::LeaveIfError(err);
       
   172 		return;
       
   173 		}
       
   174 
       
   175 	// Ensure registration data length is less than or equal to max allowed pin length
       
   176 	TInt pinLen = aRegistrationData.Length();
       
   177 	if (pinLen > KMaxPinLength)
       
   178 		{
       
   179 		User::Leave(KErrArgument);
       
   180 		}
       
   181 
       
   182 	// Convert registration data to 8 bit 
       
   183 	// Note that no unicode conversion is being done here since a pin cannot be in unicode
       
   184 	RBuf8 pinBuf;
       
   185 	pinBuf.CreateL(pinLen);
       
   186 	CleanupClosePushL(pinBuf);
       
   187 	pinBuf.Copy(aRegistrationData.Left(pinLen));
       
   188 	TPinValue pin(pinBuf);
       
   189 	CleanupStack::PopAndDestroy(&pinBuf);
       
   190 
       
   191 	// Generate the identity key and identity key hash
       
   192 	HBufC8* identityKey = NULL;
       
   193 	HBufC8* identityKeyHash = GenerateKeyHashL(pin, identityKey);
       
   194 	CleanupStack::PushL(identityKeyHash);
       
   195 	CleanupStack::PushL(identityKey);
       
   196 
       
   197 	// Ensure another identity doesn't have the same pin
       
   198 	TIdentityId tempId = iPinPluginDb->IdFromPin(*identityKeyHash);
       
   199 	if ((tempId != aIdentityId) && (tempId != KUnknownIdentity))
       
   200 		{
       
   201 		CleanupStack::PopAndDestroy(2, identityKeyHash);
       
   202 		// This appears to be the most appropriate error code - The important point is to convery Reset has failed.
       
   203 		User::Leave(KErrInUse);
       
   204 		}
       
   205 	else if (tempId == aIdentityId)
       
   206 		{
       
   207 		// Nothing to do
       
   208 		aResult = identityKey;		// Ownership transferred to caller
       
   209 		CleanupStack::Pop(identityKey);
       
   210 		CleanupStack::PopAndDestroy(identityKeyHash);
       
   211 		return;
       
   212 		}
       
   213 
       
   214 	// Replace the training data
       
   215 	iPinPluginDb->UpdatePinL(aIdentityId, *identityKeyHash);
       
   216 	aResult = identityKey;		// Ownership transferred to caller
       
   217 	CleanupStack::Pop(identityKey);
       
   218 	CleanupStack::PopAndDestroy(identityKeyHash);
       
   219 	}
       
   220 
       
   221 void CPinPluginAO::DoCancel()
       
   222 	{
       
   223 	iPinPluginDialog->Cancel();
       
   224 	if(iRequestStatus)
       
   225 		{
       
   226 		User::RequestComplete(iRequestStatus, KErrCancel);
       
   227 		}
       
   228 	}
       
   229 	
       
   230 void CPinPluginAO::RunL()
       
   231 	{
       
   232 	// Leave if there has been an error
       
   233 	User::LeaveIfError(iStatus.Int());
       
   234 	
       
   235 	switch(iState)
       
   236 		{
       
   237 		case EIdentify:
       
   238 			{
       
   239 			IdentifyId();	
       
   240 			}
       
   241 			break;
       
   242 		case EIdentifyResult:
       
   243 			{
       
   244 			if (*iDialogResult == EOk)
       
   245 				{
       
   246 				IdentifyResultL();
       
   247 				}
       
   248 			else if (*iDialogResult == ECancel)
       
   249 				{
       
   250 				User::RequestComplete(iRequestStatus, KErrAuthServPluginCancelled);
       
   251 				}
       
   252 			else if (*iDialogResult == EQuit)
       
   253 				{
       
   254 				User::RequestComplete(iRequestStatus, KErrAuthServPluginQuit);
       
   255 				}
       
   256 			*iDialogResult = static_cast<TPinPluginDialogResult>(0);
       
   257 			}
       
   258 			break;
       
   259 		case ETrain:
       
   260 			{
       
   261 			TrainIdL();	
       
   262 			}
       
   263 			break;
       
   264 		case ETrainResult:
       
   265 			{
       
   266 			if (*iDialogResult == EOk)
       
   267 				{
       
   268 				AddTrainResultToDBL();
       
   269 				}
       
   270 			else if (*iDialogResult == ECancel)
       
   271 				{
       
   272 				User::RequestComplete(iRequestStatus, KErrAuthServPluginCancelled);
       
   273 				}
       
   274 			else if (*iDialogResult == EQuit)
       
   275 				{
       
   276 				User::RequestComplete(iRequestStatus, KErrAuthServPluginQuit);
       
   277 				}
       
   278 			else if (*iDialogResult == ENext)
       
   279 				{
       
   280 				iState = ETrain;
       
   281 				TRequestStatus* status = &iStatus;
       
   282 				User::RequestComplete(status, KErrNone);
       
   283 				SetActive();
       
   284 				}
       
   285 			*iDialogResult = static_cast<TPinPluginDialogResult>(0);
       
   286 			}
       
   287 			break;
       
   288 		case EInfo:
       
   289 			{
       
   290 			iPinPluginDialog->PinInfo(iMessage, iStatus);
       
   291 			iState = EFinished;
       
   292 			SetActive();
       
   293 			}
       
   294 			break;
       
   295 		case EFinished:
       
   296 			{
       
   297 			User::RequestComplete(iRequestStatus, iStatus.Int());
       
   298 			}
       
   299 			break;
       
   300 		default:
       
   301 			{
       
   302 			User::Leave(KErrNotSupported);
       
   303 			}
       
   304 			break;
       
   305 		}
       
   306 	}
       
   307 	
       
   308 TInt CPinPluginAO::RunError(TInt aError)
       
   309 	{
       
   310 	if(iRequestStatus)
       
   311 		{
       
   312 		User::RequestComplete(iRequestStatus, aError);
       
   313 		}
       
   314 	return KErrNone;
       
   315 	}
       
   316 
       
   317 void CPinPluginAO::IdentifyId()
       
   318 	{
       
   319 	if (iRetryRefCount--)
       
   320 		{
       
   321 		iPinPluginDialog->PinIdentify(iPinMinSize, iPinMaxSize, ETrue, iPinValue, *iDialogResult, iStatus);
       
   322 		iState = EIdentifyResult;
       
   323 		}
       
   324 	else
       
   325 		{
       
   326 		iRetryRefCount = iRetryCount;
       
   327 		*iIdentityIdPtr = KUnknownIdentity;
       
   328 		iMessage = EPinPluginIdentificationFailure;
       
   329 		TRequestStatus* status = &iStatus;
       
   330 		User::RequestComplete(status, KErrNone);
       
   331 		iState = EInfo;
       
   332 		}
       
   333 	SetActive();
       
   334 	}
       
   335 
       
   336 void CPinPluginAO::IdentifyResultL()
       
   337 	{
       
   338 	TIdentityId identityId;
       
   339 	HBufC8* identityKey = NULL;
       
   340 	HBufC8* identityKeyHash = GenerateKeyHashL(iPinValue, identityKey);
       
   341 	CleanupStack::PushL(identityKeyHash);
       
   342 	CleanupStack::PushL(identityKey);	
       
   343 	identityId = iPinPluginDb->IdFromPin(*identityKeyHash);
       
   344 	if (identityId != KUnknownIdentity)
       
   345 		{
       
   346 		*iIdentityIdPtr = identityId;
       
   347 		iRetryRefCount = iRetryCount;
       
   348 		*iResult = identityKey;
       
   349 		iMessage = EPinPluginIdentificationSuccess;
       
   350 		iState = EInfo;
       
   351 		CleanupStack::Pop(identityKey);
       
   352 		}
       
   353 	else
       
   354 		{	
       
   355 		CleanupStack::PopAndDestroy(identityKey);
       
   356 		iState = EIdentify;
       
   357 		}
       
   358 	CleanupStack::PopAndDestroy(identityKeyHash);
       
   359 	TRequestStatus* status = &iStatus;
       
   360 	User::RequestComplete(status, KErrNone);
       
   361 	SetActive();
       
   362 	}
       
   363 		
       
   364 void CPinPluginAO::TrainIdL()
       
   365 	{
       
   366         // Check for invalid pinsize.
       
   367 	if( !(iNewPinSize >= iPinMinSize && iNewPinSize <= iPinMaxSize)  )
       
   368                 {
       
   369                 User::Leave(KErrAuthServRegistrationFailed);
       
   370                 }
       
   371 
       
   372 
       
   373 	iPinList.ResetAndDestroy();
       
   374 	iIdKeyList.ResetAndDestroy();
       
   375 	iIdKeyHashList.ResetAndDestroy();
       
   376 	GenerateUniquePinsL(iPinList, iIdKeyList, iIdKeyHashList);
       
   377 	TInt indexValue = iPinPluginDb->IdIndex(iIdentityId);
       
   378 	TPinPluginTrainingMessage trainMessage;
       
   379 	if (indexValue >= 0)
       
   380 		{
       
   381 		trainMessage = EReTraining;
       
   382 		}
       
   383 	else
       
   384 		{
       
   385 		trainMessage = ETraining;
       
   386 		}
       
   387 	iPinPluginDialog->PinTraining(trainMessage, iPinList, iPinMinSize, iPinMaxSize, iIndex, iNewPinSize, *iDialogResult, iStatus);
       
   388 	iState = ETrainResult;
       
   389 	SetActive();	
       
   390 	}
       
   391 
       
   392 void CPinPluginAO::AddTrainResultToDBL()
       
   393 	{
       
   394 	__ASSERT_ALWAYS(iIndex >= KIndexLow && iIndex <= KIndexHigh,
       
   395 		User::Panic(KPinPluginPanicString(), EPinPanicIncorrectIndex));
       
   396 
       
   397 	TInt indexValue = iPinPluginDb->IdIndex(iIdentityId);
       
   398 	if (indexValue >= 0)
       
   399 		{
       
   400 		iPinPluginDb->UpdatePinL(iIdentityId, *iIdKeyHashList[iIndex]);
       
   401 		iMessage = EPinPluginReTrainingSuccess;
       
   402 		}
       
   403 	else
       
   404 		{
       
   405 		iPinPluginDb->AddPinL(iIdentityId, *iIdKeyHashList[iIndex]);
       
   406 		iMessage = EPinPluginTrainingSuccess;
       
   407 		}
       
   408 	TPtrC8 idKeyPtr = *iIdKeyList[iIndex];
       
   409 	HBufC8* identityKey = idKeyPtr.AllocL();
       
   410 	*iResult = identityKey;
       
   411 	iNewPinSize = iPinSize;
       
   412 	iState = EInfo;
       
   413 	TRequestStatus* status = &iStatus;
       
   414 	User::RequestComplete(status, KErrNone);
       
   415 	SetActive();
       
   416 	}
       
   417 
       
   418 HBufC8* CPinPluginAO::GenerateKeyHashL(TPinValue& aPinValue, HBufC8*& aIdentityKey)
       
   419 	{
       
   420 	CSHA1* sha1 = CSHA1::NewL();
       
   421 	CleanupStack::PushL(sha1);
       
   422 	HBufC8* pinValue = aPinValue.AllocLC();
       
   423 	TPtrC8 hash = sha1->Hash(*pinValue);
       
   424 	CleanupStack::PopAndDestroy(pinValue);
       
   425 	aIdentityKey = hash.AllocLC();
       
   426 	TPtrC8 hash1 = sha1->Hash(hash);
       
   427 	HBufC8* idkeyHash = hash1.AllocL();
       
   428 	CleanupStack::Pop(aIdentityKey);
       
   429 	CleanupStack::PopAndDestroy(sha1);
       
   430 	return idkeyHash;
       
   431 	}
       
   432 	
       
   433 	
       
   434 void CPinPluginAO::GenerateUniquePinsL(RPointerArray<TPinValue>& aPinList,
       
   435 		RPointerArray<HBufC8>& aIdKeyList, RPointerArray<HBufC8>& aIdKeyHashList)
       
   436 	{
       
   437 	TInt count = 4; 
       
   438 	while (count)
       
   439 		{
       
   440 		TPinValue* randomPin = new (ELeave) TPinValue;
       
   441 		CleanupStack::PushL(randomPin);
       
   442 		for (TInt k = 0; k < iNewPinSize ; k++)
       
   443 			{
       
   444 			TUint8 num = Math::Random();
       
   445 			num = num % 10;
       
   446 			randomPin->AppendNum(num);
       
   447 			}
       
   448 		HBufC8* identityKey = NULL;
       
   449 		HBufC8* identityKeyHash = GenerateKeyHashL(*randomPin, identityKey);
       
   450 		CleanupStack::PushL(identityKeyHash);
       
   451 		CleanupStack::PushL(identityKey);
       
   452 		if (iPinPluginDb->IsUniquePin(*identityKeyHash))
       
   453 			{
       
   454 			aIdKeyList.AppendL(identityKey);
       
   455 			CleanupStack::Pop(identityKey);
       
   456 			aIdKeyHashList.AppendL(identityKeyHash);
       
   457 			CleanupStack::Pop(identityKeyHash);
       
   458 			aPinList.AppendL(randomPin);
       
   459 			CleanupStack::Pop(randomPin);
       
   460 			count--;
       
   461 			}
       
   462 		}
       
   463 	}
       
   464 
       
   465 
       
   466 
       
   467 
       
   468 
       
   469 
       
   470 
       
   471 
       
   472 
       
   473 
       
   474 	
       
   475 	
       
   476 	
       
   477