cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/CKeyDataManager.cpp
changeset 8 35751d3474b7
parent 0 2c201484c85f
child 45 030c4fbc13d7
--- a/cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/CKeyDataManager.cpp	Tue Jul 21 01:04:32 2009 +0100
+++ b/cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/CKeyDataManager.cpp	Thu Sep 10 14:01:51 2009 +0300
@@ -1,642 +1,858 @@
-/*
-* Copyright (c) 2004-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: 
-*
-*/
-
-
-#include "CKeyDataManager.h"
-#include "fsdatatypes.h"
-#include <fstokencliserv.h>
-#include "fstokenutil.h"
-#include "keystorepassphrase.h"
-
-_LIT(KKeyStoreFilename,"keys.dat");
-
-const TInt KDefaultPassphraseTimeout = 30;
-
-//	*********************************************************************
-//	Key store data manager - maintains array of objects representing keys
-//	*********************************************************************
-
-/*static*/ CFileKeyDataManager* CFileKeyDataManager::NewL()
-	{
-	CFileKeyDataManager* self = new (ELeave) CFileKeyDataManager();
-	CleanupStack::PushL(self);
-	self->ConstructL();
-	CleanupStack::Pop(self);
-	return self;
-	}
-
-CFileKeyDataManager::~CFileKeyDataManager()
-	{
-	if (iFileStore)
-		{
-		CompactStore();
-		delete iFileStore;
-		}
-
-	iFile.Close(); // May already have been closed by store
-	iFs.Close();
-		
-	iKeys.ResetAndDestroy();
-	iKeys.Close();
-	}
-
-CFileKeyDataManager::CFileKeyDataManager() :
-	iRootStreamId(KNullStreamId),
-	iInfoStreamId(KNullStreamId),
-	iPassStreamId(KNullStreamId),
-	iTimeoutStreamId(KNullStreamId)
-	{
-	}
-
-void CFileKeyDataManager::ConstructL()
-	{
-	User::LeaveIfError(iFs.Connect());
-	OpenStoreL();
-
-	RStoreReadStream lookupStream;
-	lookupStream.OpenLC(*iFileStore, iInfoStreamId);
-
-	iPassStreamId = (TStreamId) lookupStream.ReadUint32L();
-	iTimeoutStreamId = (TStreamId) lookupStream.ReadUint32L();
-
-	TInt count = lookupStream.ReadInt32L();
-	for (TInt index = 0; index < count; index++)
-		{
-		const CFileKeyData* keyData = CFileKeyData::NewL(lookupStream);
-
-		if (keyData->Handle() > iKeyIdentifier)
-			iKeyIdentifier = keyData->Handle();
-
-		iKeys.Append(keyData);
-		}
-	
-	CleanupStack::PopAndDestroy(&lookupStream);
-
-	ReadPassphraseTimeoutL();
-	}
-
-CPassphraseManager* CFileKeyDataManager::CreatePassphraseManagerLC()
-	{
-	CPassphraseManager* result = CPassphraseManager::NewL(*iFileStore);
-	CleanupStack::PushL(result);
-	return result;
-	}
-
-void CFileKeyDataManager::OpenStoreL()
-	{
-	//	Tries to locate a key store file on the default drive and then from ROM
-	//	If it cannot find one, tries to create a file with permanent file store
-	//	inside it In all cases, should initialise iFileStore unless it cannot
-	//	create the file/store/streams
-	
-	__ASSERT_DEBUG(!iFileStore, PanicServer(EPanicStoreInitialised));
-
-	TFileName fullPath;
-	FileUtils::MakePrivateFilenameL(iFs, KKeyStoreFilename, fullPath);
-
-	FileUtils::EnsurePathL(iFs, fullPath);
-	TRAPD(result, OpenStoreInFileL(fullPath));
-
-	if (result == KErrInUse) 
-		{		
-		// Cannot access the file now. Abort server startup rather than wiping the keystore.
-		User::Leave(result); 
-		}
-
-	if (result != KErrNone)
-		{		
-		// Not yet opened a valid store, either no file to be found, or no valid
-		// store in it. Copy the original one stored in the ROM.
-		delete iFileStore;
-		iFileStore = NULL;
-		
-		TFileName romPath;
-		FileUtils::MakePrivateROMFilenameL(iFs, KKeyStoreFilename, romPath);
-
-		if (result != KErrNotFound)
-			{
-			// Wipe the keystore if we can't open it (it's corrupt anyway)
-			User::LeaveIfError(iFs.Delete(fullPath));
-			}
-
-		// Copy data from rom and open it	
-		TRAPD(err,
-			  FileUtils::CopyL(iFs, romPath, fullPath);
-			  OpenStoreInFileL(fullPath)
-			);
-		
-		if (KErrNone != err)
-			{
-			// We tried to copy the keystore from ROM. For some reason this
-			// failed and we still cannot open the file. Create a new one from
-			// scratch.
-			CreateStoreInFileL(fullPath);
-			}
-		}
-
-	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
-	__ASSERT_DEBUG((KNullStreamId!=iRootStreamId), PanicServer(EPanicRootStreamNotReady));
-	__ASSERT_DEBUG((KNullStreamId!=iInfoStreamId), PanicServer(EPanicManagerStreamNotReady));
-	}
-
-void CFileKeyDataManager::CreateStoreInFileL(const TDesC& aFile)
-	{
-	TInt r = iFs.MkDirAll(aFile);
-	if ( (r!=KErrNone) && (r!=KErrAlreadyExists) )
-		User::Leave(r);
-
-	iFileStore = CPermanentFileStore::ReplaceL(iFs, aFile, EFileRead | EFileWrite | EFileShareExclusive);
-	iFileStore->SetTypeL(KPermanentFileStoreLayoutUid);
-
-	TCleanupItem cleanupStore(RevertStore, iFileStore);
-	CleanupStack::PushL(cleanupStore);
-	
-	// Create timeout stream with default timeout
-	RStoreWriteStream timeoutStream;
-	iTimeoutStreamId = timeoutStream.CreateLC(*iFileStore);
-	timeoutStream.WriteUint32L(KDefaultPassphraseTimeout);
-	timeoutStream.CommitL();
-	CleanupStack::PopAndDestroy(&timeoutStream);
-
-	// Create info stream - Currently no passphrase created, and no keys
-	RStoreWriteStream managerStream;
-	iInfoStreamId = managerStream.CreateLC(*iFileStore);
-	managerStream.WriteUint32L(KNullStreamId.Value());
-	managerStream.WriteUint32L(iTimeoutStreamId.Value());
-	managerStream.WriteUint32L(0); // Write key count of zero
-	managerStream.CommitL();
-	CleanupStack::PopAndDestroy(&managerStream);
-
-	// Create root stream - just contains id of info stream
-	RStoreWriteStream rootStream;
-	iRootStreamId = rootStream.CreateLC(*iFileStore);
-	iFileStore->SetRootL(iRootStreamId);
-	rootStream.WriteUint32L(iInfoStreamId.Value());		
-	rootStream.CommitL();
-	CleanupStack::PopAndDestroy(&rootStream);
-
-	WriteKeysToStoreL();
-	
-	iFileStore->CommitL();
-	CleanupStack::Pop(); // cleanupStore
-	}
-
-void CFileKeyDataManager::OpenStoreInFileL(const TDesC& aFile)
-	{
-	// Make sure the file isn't write protected
-	User::LeaveIfError(iFs.SetAtt(aFile, 0, KEntryAttReadOnly));
-	
-	User::LeaveIfError(iFile.Open(iFs, aFile, EFileRead | EFileWrite | EFileShareExclusive));
-	
-	iFileStore = CPermanentFileStore::FromL(iFile);		
-
-	// Get the salt, root and manager TStreamIds
-	iRootStreamId = iFileStore->Root();
-	if (iRootStreamId == KNullStreamId)
-		{
-		User::Leave(KErrCorrupt);
-		}
-	
-	RStoreReadStream rootStream;
-	rootStream.OpenLC(*iFileStore, iRootStreamId);
-	iInfoStreamId = (TStreamId)(rootStream.ReadUint32L());
-	CleanupStack::PopAndDestroy(&rootStream);
-	}
-
-// Methods dealing with atomic updates to key data file ////////////////////////
-
-// This is a cleanup item that reverts the store
-void CFileKeyDataManager::RevertStore(TAny* aStore)
-{
-	CPermanentFileStore* store = reinterpret_cast<CPermanentFileStore*>(aStore);
-	TRAP_IGNORE(store->RevertL());
-	// We're ignoring the leave code from this becuase there's no way we can
-	// handle this sensibly.  This shouldn't be a problem in practice - this
-	// will leave if for example the file store is on removable which is
-	// unexpectedly remove, and this is never the case for us.
-}
-
-// Rewrites the info stream (ie the array of key data info) to the store
-void CFileKeyDataManager::WriteKeysToStoreL()
-{
-	RStoreWriteStream lookupStream;
-	lookupStream.ReplaceLC(*iFileStore, iInfoStreamId);
-
-	lookupStream.WriteUint32L(iPassStreamId.Value());
-	lookupStream.WriteUint32L(iTimeoutStreamId.Value());
-
-	TInt keyCount = iKeys.Count();
-	lookupStream.WriteInt32L(keyCount);
-
-	for (TInt index = 0; index < keyCount; index++)
-	{
-		const CFileKeyData* key = iKeys[index];
-		key->ExternalizeL(lookupStream);
-	}
-
-	lookupStream.CommitL();
-	CleanupStack::PopAndDestroy(&lookupStream);
-}
-
-/**
- * Add a key to the store.  Assumes that the key data streams (info, public key
- * and private key) have already been written.
- */
-void CFileKeyDataManager::AddL(const CFileKeyData* aKeyData)
-	{
-	ASSERT(aKeyData);
-	ASSERT(aKeyData->PassphraseStreamId() != KNullStreamId);
-
-	// Add the key to to the array, rewrite the infostream and 
-	// ONLY THEN commit the store
-	User::LeaveIfError(iKeys.Append(aKeyData));
-
-	// Set the default passphrase id if this is the first key
-	TStreamId oldDefaultPassphraseId = iPassStreamId;
-	if (iKeys.Count() == 1)
-		{
-		iPassStreamId = aKeyData->PassphraseStreamId();
-		}
-
-	TRAPD(err, WriteKeysToStoreL());
-
-	// Release ownership of key data and reset default passphrase id if store
-	// can't be written
-	TCleanupItem cleanupStore(RevertStore, iFileStore);
-	CleanupStack::PushL(cleanupStore);
-
-	if (err != KErrNone)
-		{
-		iKeys.Remove(iKeys.Count() - 1);
-		iPassStreamId = oldDefaultPassphraseId;
-		User::Leave(err);
-		}
-	iFileStore->CommitL();
-	
-	CleanupStack::Pop(); // cleanupStore
-	}
-
-/**
- * "Transaction safe" key removal - only removes the key in memory and file if
- * all operations are successful.
- */
-void CFileKeyDataManager::RemoveL(TInt aObjectId)
-	{
-	TInt index;
-	const CFileKeyData* key = NULL;
-	for (index = 0 ; index < iKeys.Count() ; ++index)
-		{
-		if (iKeys[index]->Handle() == aObjectId)
-			{
-			key = iKeys[index];
-			break;
-			}
-		}
-	
-	if (!key)
-		{
-		User::Leave(KErrNotFound);
-		}
-
-	TCleanupItem cleanupStore(RevertStore, iFileStore);
-	CleanupStack::PushL(cleanupStore);	
-
-	iFileStore->DeleteL(key->PrivateDataStreamId());
-	iFileStore->DeleteL(key->PublicDataStreamId());
-	iFileStore->DeleteL(key->InfoDataStreamId());
-
-	// Remove the passphrase if it's the last key
-	TStreamId oldPassphraseId = iPassStreamId;
-	if (Count() == 1)
-		{
-		iFileStore->DeleteL(iPassStreamId);
-		iPassStreamId = KNullStreamId;
-		}
-
-	// Remove the key
-	iKeys.Remove(index);
-	
-	TRAPD(res, WriteKeysToStoreL());
-	if (res != KErrNone)
-		{
-		iPassStreamId = oldPassphraseId;
-		User::LeaveIfError(iKeys.Append(key)); // Put it back, shouldn't leave
-		User::Leave(res);
-		}
-	else 
-		{
-		delete key;   // Cannot leave from the point it's removed to here, so no cleanup stack!
-		}		
-	iFileStore->CommitL();
-
-	CleanupStack::Pop(); // cleanupStore
-	CompactStore();
-}
-
-TBool CFileKeyDataManager::IsKeyAlreadyInStore(const TDesC& aKeyLabel) const
-{//	Check each key in the store to determine if aKeyLabel already exists
-	TInt keyCount = iKeys.Count();
-	TBool isInStore = EFalse;
-	for (TInt index = 0; index < keyCount; index++)
-	{
-		const TDesC& keyLabel = iKeys[index]->Label();
-		if (keyLabel.Compare(aKeyLabel)==0)
-		{
-			isInStore = ETrue;
-			break;
-		}
-	}
-
-	return (isInStore);
-}
-
-TInt CFileKeyDataManager::Count() const
-	{
-	return iKeys.Count();
-	}	
-
-const CFileKeyData* CFileKeyDataManager::operator[](TInt aIndex) const
-	{
-	return iKeys[aIndex];
-	}
-
-const CFileKeyData* CFileKeyDataManager::Lookup(TInt aObjectId) const
-	{
-	TInt count = Count();
-	for (TInt i = 0; i < count; ++i)
-		{
-		if ((*this)[i]->Handle() == aObjectId)
-			{
-			return (*this)[i];
-			}
-		}
-	return NULL;
-	}
-
-//	*********************************************************************
-//	Management of file and store therein
-//	*********************************************************************
-
-const CFileKeyData* CFileKeyDataManager::CreateKeyDataLC(const TDesC& aLabel, TStreamId aPassStreamId)
-	{
-	ASSERT(aPassStreamId != KNullStreamId);
-	TInt objectId = ++iKeyIdentifier;
-	TStreamId infoData = CreateWriteStreamL();
-	TStreamId publicKeyData = CreateWriteStreamL();
-	TStreamId privateKeyData = CreateWriteStreamL();
-	return CFileKeyData::NewLC(objectId, aLabel, infoData, aPassStreamId, publicKeyData, privateKeyData);
-	}
-
-//	Creates a new write stream in the store (which it then closes)
-//	Returns the TStreamId associated with it
-TStreamId CFileKeyDataManager::CreateWriteStreamL()
-	{
-	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
-	if (!iFileStore)
-		User::Leave(KErrNotReady);
-
-	RStoreWriteStream newStream;
-	TStreamId result = newStream.CreateLC(*iFileStore);
-	if (KNullStreamId == result)
-		User::Leave(KErrBadHandle);
-
-	newStream.CommitL();
-	CleanupStack::PopAndDestroy(&newStream);
-
-	return result;
-	}
-
-CKeyInfo* CFileKeyDataManager::ReadKeyInfoLC(const CFileKeyData& aKeyData) const
-	{
-	__ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
-	RStoreReadStream stream;
-	stream.OpenLC(*iFileStore, aKeyData.InfoDataStreamId());
-	CKeyInfo* info = CKeyInfo::NewL(stream);
-	CleanupStack::PopAndDestroy(&stream);
-	info->CleanupPushL();
-	if (info->Handle() != aKeyData.Handle())
-		{
-		User::Leave(KErrCorrupt); // is this appropriate?
-		}
-	return info;
-	}
-
-void CFileKeyDataManager::WriteKeyInfoL(const CFileKeyData& aKeyData, const CKeyInfo& aKeyInfo)
-	{
-	RStoreWriteStream infoStream;
-	OpenInfoDataStreamLC(aKeyData, infoStream);
-	infoStream << aKeyInfo;
-	infoStream.CommitL();
-	CleanupStack::PopAndDestroy(&infoStream);
-	}
-
-void CFileKeyDataManager::SafeWriteKeyInfoL(const CFileKeyData& aKeyData, const CKeyInfo& aKeyInfo)
-	{
-	TCleanupItem cleanupStore(RevertStore, iFileStore);
-	CleanupStack::PushL(cleanupStore);	
-
-	WriteKeyInfoL(aKeyData, aKeyInfo);
-	iFileStore->CommitL();
-	
-	CleanupStack::Pop(); // cleanupStore	
-	}
-
-void CFileKeyDataManager::OpenInfoDataStreamLC(const CFileKeyData& aKeyData, RStoreWriteStream& aStream)
-	{
-	__ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
-	aStream.ReplaceLC(*iFileStore, aKeyData.InfoDataStreamId());
-	}
-
-void CFileKeyDataManager::OpenPublicDataStreamLC(const CFileKeyData& aKeyData, RStoreWriteStream& aStream)
-	{
-	__ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
-	aStream.ReplaceLC(*iFileStore, aKeyData.PublicDataStreamId());
-	}
-
-void CFileKeyDataManager::OpenPublicDataStreamLC(const CFileKeyData& aKeyData, RStoreReadStream& aStream) const
-	{
-	__ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
-	aStream.OpenLC(*iFileStore, aKeyData.PublicDataStreamId());
-	}
-
-void CFileKeyDataManager::OpenPrivateDataStreamLC(const CFileKeyData& aKeyData, CPassphrase& aPassphrase,
-												  RStoreWriteStream& aStream)
-	{
-	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
-	aStream.ReplaceLC(aPassphrase.Store(), aKeyData.PrivateDataStreamId());
-	}
-
-void CFileKeyDataManager::OpenPrivateDataStreamLC(const CFileKeyData& aKeyData, CPassphrase& aPassphrase,
-												  RStoreReadStream& aStream) 
-	{
-	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
-	aStream.OpenLC(aPassphrase.Store(), aKeyData.PrivateDataStreamId());
-	}
-
-TInt CFileKeyDataManager::GetPassphraseTimeout() const
-	{
-	return iTimeout;
-	}
-
-void CFileKeyDataManager::SetPassphraseTimeoutL(TInt aTimeout)
-	{
-	TInt oldTimeout = iTimeout;
-
-	iTimeout = aTimeout;
-	TRAPD(err, WritePassphraseTimeoutL(); iFileStore->CommitL());
-
-	if (err != KErrNone)
-		{
-		iTimeout = oldTimeout;
-		iFileStore->RevertL(); // shouldn't leave
-		User::Leave(err);
-		}
-	}
-
-void CFileKeyDataManager::ReadPassphraseTimeoutL()
-	{
-	ASSERT(iTimeout == 0); // Only called from ConstructL()
-	
-	RStoreReadStream stream;
-	stream.OpenLC(*iFileStore, iTimeoutStreamId);
-	iTimeout = stream.ReadInt32L();
-	CleanupStack::PopAndDestroy(&stream);
-	}
-
-void CFileKeyDataManager::WritePassphraseTimeoutL()
-	{
-	RStoreWriteStream stream;
-	stream.ReplaceLC(*iFileStore, iTimeoutStreamId);
-	stream.WriteUint32L(iTimeout);	
-	stream.CommitL();
-	CleanupStack::PopAndDestroy(&stream);
-	}
-
-TStreamId CFileKeyDataManager::DefaultPassphraseId() const
-	{
-	ASSERT((iPassStreamId == KNullStreamId) == (Count() == 0));
-	return iPassStreamId;
-	}
-
-
-/**
- * Attempt to compact the store - it doesn't matter if these calls leave, it
- * will only mean that the store takes up more space than necessary.
- */
-void CFileKeyDataManager::CompactStore()
-	{
-	ASSERT(iFileStore);
-	TRAP_IGNORE(iFileStore->ReclaimL(); iFileStore->CompactL());
-	}
-
-/*
-  implement these, passphrase manager has pointer to key data manager,
-  passphrase doesn't have pointer to file store.
-  
-TStreamId CFileKeyDataManager::AddPassphraseDataL(const CPBEncryptSet& aEncryptSet)
-	{
-	}
-
-CPBEncryptSet* CFileKeyDataManager::GetPassphraseDataL(TStreamId aId)
-	{
-	return NULL;
-	}
-
-void CFileKeyDataManager::RemovePassphraseDataL(TStreamId aId)
-	{
-	}
-*/
-
-// CFileKeyData ////////////////////////////////////////////////////////////////
-
-CFileKeyData* CFileKeyData::NewLC(TInt aObjectId, const TDesC& aLabel, TStreamId aInfoData,
-								  TStreamId aPassphraseId, TStreamId aPublicData, TStreamId aPrivateData)
-	{
-	CFileKeyData* self = new (ELeave) CFileKeyData(aObjectId, aInfoData, aPassphraseId, aPublicData, aPrivateData);
-	CleanupStack::PushL(self);
-	self->ConstructL(aLabel);
-	return self;
-	}
-
-CFileKeyData* CFileKeyData::NewL(RStoreReadStream& aReadStream)
-	{
-	CFileKeyData* self = new (ELeave) CFileKeyData();
-	CleanupStack::PushL(self);
-	self->InternalizeL(aReadStream);
-	CleanupStack::Pop(self);
-	return (self);
-	}
-
-CFileKeyData::~CFileKeyData()
-	{
-	delete iLabel;
-	}
-
-CFileKeyData::CFileKeyData(TInt aObjectId, TStreamId aInfoData, TStreamId aPassphraseId, 
-						   TStreamId aPublicData, TStreamId aPrivateData) :
-	iObjectId(aObjectId), iInfoData(aInfoData), iPassphraseId(aPassphraseId),
-	iPublicKeyData(aPublicData), iPrivateKeyData(aPrivateData)
-	{
-	ASSERT(iObjectId);
-	ASSERT(iInfoData != KNullStreamId);
-	ASSERT(iPassphraseId != KNullStreamId);
-	ASSERT(iPublicKeyData != KNullStreamId);
-	ASSERT(iPrivateKeyData != KNullStreamId);
-	}
-
-CFileKeyData::CFileKeyData()
-	{
-	}
-
-void CFileKeyData::ConstructL(const TDesC& aLabel)
-	{
-	TInt labelLen = aLabel.Length();
-	iLabel = HBufC::NewMaxL(labelLen);
-	TPtr theLabel(iLabel->Des());
-	theLabel.FillZ();
-	theLabel.Copy(aLabel);
-	}
-
-void CFileKeyData::InternalizeL(RReadStream& aReadStream)
-{
-	iObjectId = aReadStream.ReadInt32L();
-	iInfoData.InternalizeL(aReadStream);
-	iPassphraseId.InternalizeL(aReadStream);
-	iPublicKeyData.InternalizeL(aReadStream);
-	iPrivateKeyData.InternalizeL(aReadStream);
-
-	TInt labelLen = aReadStream.ReadInt32L();
-	iLabel = HBufC::NewMaxL(labelLen);
-	TPtr theLabel((TUint16*)iLabel->Ptr(), labelLen, labelLen);
-	theLabel.FillZ(labelLen);
-	aReadStream.ReadL(theLabel);
-}
-
-void CFileKeyData::ExternalizeL(RWriteStream& aWriteStream) const
-{
-	aWriteStream.WriteInt32L(iObjectId);
-	iInfoData.ExternalizeL(aWriteStream);
-	iPassphraseId.ExternalizeL(aWriteStream);
-	iPublicKeyData.ExternalizeL(aWriteStream);
-	iPrivateKeyData.ExternalizeL(aWriteStream);
-
-	TInt labelLen = iLabel->Length();
-	aWriteStream.WriteInt32L(labelLen);
-	TPtr theLabel(iLabel->Des());
-	theLabel.SetLength(labelLen);
-	aWriteStream.WriteL(theLabel);
-}
+/*
+* Copyright (c) 2004-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: 
+*
+*/
+
+
+#include "CKeyDataManager.h"
+#include "fsdatatypes.h"
+#include "fstokencliserv.h"
+#include "fstokenutil.h"
+#include "keystorepassphrase.h"
+
+_LIT(KKeyStoreFilename,"keys.dat");
+
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+#include <e32property.h>
+#include <authserver/aspubsubdefs.h>
+#else
+const TInt KDefaultPassphraseTimeout = 30;
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+//	*********************************************************************
+//	Key store data manager - maintains array of objects representing keys
+//	*********************************************************************
+
+/*static*/ CFileKeyDataManager* CFileKeyDataManager::NewL()
+	{
+	CFileKeyDataManager* self = new (ELeave) CFileKeyDataManager();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CFileKeyDataManager::~CFileKeyDataManager()
+	{
+	if (iFileStore)
+		{
+		CompactStore();
+		delete iFileStore;
+		}
+
+	iFile.Close(); // May already have been closed by store
+	iFs.Close();
+		
+	iKeys.ResetAndDestroy();
+	iKeys.Close();
+	#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	iIdentityId.Close();
+	#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	}
+
+CFileKeyDataManager::CFileKeyDataManager() :
+	iRootStreamId(KNullStreamId),
+	iInfoStreamId(KNullStreamId)
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	,iPassStreamId(KNullStreamId),
+	iTimeoutStreamId(KNullStreamId)
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	{
+	}
+
+void CFileKeyDataManager::ConstructL()
+	{
+	
+	User::LeaveIfError(iFs.Connect());
+	OpenStoreL();
+
+	RStoreReadStream lookupStream;
+	lookupStream.OpenLC(*iFileStore, iInfoStreamId);
+
+	#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	User::LeaveIfError(iIdentityId.Attach(	AuthServer::KAuthServerSecureId,
+											AuthServer::KUidAuthServerAuthChangeEvent));
+	#else
+	iPassStreamId = (TStreamId) lookupStream.ReadUint32L();
+	iTimeoutStreamId = (TStreamId) lookupStream.ReadUint32L();
+	#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+	TInt count = lookupStream.ReadInt32L();
+	for (TInt index = 0; index < count; index++)
+		{
+		const CFileKeyData* keyData = CFileKeyData::NewL(lookupStream);
+
+		if (keyData->Handle() > iKeyIdentifier)
+			iKeyIdentifier = keyData->Handle();
+
+		iKeys.Append(keyData);
+		}
+	
+	CleanupStack::PopAndDestroy(&lookupStream);
+
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	ReadPassphraseTimeoutL();
+#endif //SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	
+	}
+
+CPassphraseManager* CFileKeyDataManager::CreatePassphraseManagerLC()
+	{
+	CPassphraseManager* result = CPassphraseManager::NewL(*iFileStore);
+	CleanupStack::PushL(result);
+	return result;
+	}
+
+void CFileKeyDataManager::OpenStoreL()
+	{
+	//	Tries to locate a key store file on the default drive and then from ROM
+	//	If it cannot find one, tries to create a file with permanent file store
+	//	inside it In all cases, should initialise iFileStore unless it cannot
+	//	create the file/store/streams
+	
+	__ASSERT_DEBUG(!iFileStore, PanicServer(EPanicStoreInitialised));
+
+	TFileName fullPath;
+	FileUtils::MakePrivateFilenameL(iFs, KKeyStoreFilename, fullPath);
+
+	FileUtils::EnsurePathL(iFs, fullPath);
+	TRAPD(result, OpenStoreInFileL(fullPath));
+
+	if (result == KErrInUse) 
+		{		
+		// Cannot access the file now. Abort server startup rather than wiping the keystore.
+		User::Leave(result); 
+		}
+
+	if (result != KErrNone)
+		{		
+		// Not yet opened a valid store, either no file to be found, or no valid
+		// store in it. Copy the original one stored in the ROM.
+		delete iFileStore;
+		iFileStore = NULL;
+		
+		TFileName romPath;
+		FileUtils::MakePrivateROMFilenameL(iFs, KKeyStoreFilename, romPath);
+
+		if (result != KErrNotFound)
+			{
+			// Wipe the keystore if we can't open it (it's corrupt anyway)
+			User::LeaveIfError(iFs.Delete(fullPath));
+			}
+
+		// Copy data from rom and open it	
+		TRAPD(err,
+			  FileUtils::CopyL(iFs, romPath, fullPath);
+			  OpenStoreInFileL(fullPath)
+			);
+		
+		if (KErrNone != err)
+			{
+			// We tried to copy the keystore from ROM. For some reason this
+			// failed and we still cannot open the file. Create a new one from
+			// scratch.
+			CreateStoreInFileL(fullPath);
+			}
+		}
+
+	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
+	__ASSERT_DEBUG((KNullStreamId!=iRootStreamId), PanicServer(EPanicRootStreamNotReady));
+	__ASSERT_DEBUG((KNullStreamId!=iInfoStreamId), PanicServer(EPanicManagerStreamNotReady));
+	}
+
+void CFileKeyDataManager::CreateStoreInFileL(const TDesC& aFile)
+	{
+	TInt r = iFs.MkDirAll(aFile);
+	if ( (r!=KErrNone) && (r!=KErrAlreadyExists) )
+		User::Leave(r);
+
+	iFileStore = CPermanentFileStore::ReplaceL(iFs, aFile, EFileRead | EFileWrite | EFileShareExclusive);
+	iFileStore->SetTypeL(KPermanentFileStoreLayoutUid);
+
+	TCleanupItem cleanupStore(RevertStore, iFileStore);
+	CleanupStack::PushL(cleanupStore);
+	
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	// Create timeout stream with default timeout
+	RStoreWriteStream timeoutStream;
+	iTimeoutStreamId = timeoutStream.CreateLC(*iFileStore);
+	timeoutStream.WriteUint32L(KDefaultPassphraseTimeout);
+	timeoutStream.CommitL();
+	CleanupStack::PopAndDestroy(&timeoutStream);
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	
+	// Create info stream - Currently no passphrase created, and no keys
+	RStoreWriteStream infoStream;
+	iInfoStreamId = infoStream.CreateLC(*iFileStore);
+	
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	infoStream.WriteUint32L(KNullStreamId.Value());
+	infoStream.WriteUint32L(iTimeoutStreamId.Value());
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	
+	infoStream.WriteUint32L(0); // Write key count of zero
+	infoStream.CommitL();
+	CleanupStack::PopAndDestroy(&infoStream);
+
+	// Create root stream - just contains id of info stream
+	RStoreWriteStream rootStream;
+	iRootStreamId = rootStream.CreateLC(*iFileStore);
+	iFileStore->SetRootL(iRootStreamId);
+
+	rootStream.WriteUint32L(iInfoStreamId.Value());		
+	rootStream.CommitL();
+	CleanupStack::PopAndDestroy(&rootStream);
+
+	WriteKeysToStoreL();
+	
+	iFileStore->CommitL();
+	CleanupStack::Pop(); // cleanupStore
+	}
+
+void CFileKeyDataManager::OpenStoreInFileL(const TDesC& aFile)
+	{
+	// Make sure the file isn't write protected
+	User::LeaveIfError(iFs.SetAtt(aFile, 0, KEntryAttReadOnly));
+	
+	User::LeaveIfError(iFile.Open(iFs, aFile, EFileRead | EFileWrite | EFileShareExclusive));
+	
+	iFileStore = CPermanentFileStore::FromL(iFile);		
+
+	// Get the salt, root and manager TStreamIds
+	iRootStreamId = iFileStore->Root();
+	if (iRootStreamId == KNullStreamId)
+		{
+		User::Leave(KErrCorrupt);
+		}
+	
+	RStoreReadStream rootStream;
+	rootStream.OpenLC(*iFileStore, iRootStreamId);
+	iInfoStreamId = (TStreamId)(rootStream.ReadUint32L());
+	CleanupStack::PopAndDestroy(&rootStream);
+	}
+
+// Methods dealing with atomic updates to key data file ////////////////////////
+
+// This is a cleanup item that reverts the store
+void CFileKeyDataManager::RevertStore(TAny* aStore)
+{
+	CPermanentFileStore* store = reinterpret_cast<CPermanentFileStore*>(aStore);
+	TRAP_IGNORE(store->RevertL());
+	// We're ignoring the leave code from this becuase there's no way we can
+	// handle this sensibly.  This shouldn't be a problem in practice - this
+	// will leave if for example the file store is on removable which is
+	// unexpectedly remove, and this is never the case for us.
+}
+
+// Rewrites the info stream (ie the array of key data info) to the store
+void CFileKeyDataManager::WriteKeysToStoreL()
+	{
+	RStoreWriteStream lookupStream;
+	lookupStream.ReplaceLC(*iFileStore, iInfoStreamId);
+
+	#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+		lookupStream.WriteUint32L(iPassStreamId.Value());
+		lookupStream.WriteUint32L(iTimeoutStreamId.Value());
+	#endif //SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	
+	TInt keyCount = iKeys.Count();
+	lookupStream.WriteInt32L(keyCount);
+
+	for (TInt index = 0; index < keyCount; index++)
+		{
+		const CFileKeyData* key = iKeys[index];
+		key->ExternalizeL(lookupStream);
+		}
+
+	lookupStream.CommitL();
+	CleanupStack::PopAndDestroy(&lookupStream);
+	}
+
+/**
+ * Add a key to the store.  Assumes that the key data streams (info, public key
+ * and private key) have already been written.
+ */
+void CFileKeyDataManager::AddL(const CFileKeyData* aKeyData)
+	{
+	ASSERT(aKeyData);
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+		ASSERT(aKeyData->PassphraseStreamId() != KNullStreamId);
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+	// Add the key to to the array, rewrite the infostream and 
+	// ONLY THEN commit the store
+	User::LeaveIfError(iKeys.Append(aKeyData));
+
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	TStreamId oldDefaultPassphraseId;
+
+	// Set the default passphrase id if this is the first key
+	oldDefaultPassphraseId = iPassStreamId;
+	if (iKeys.Count() == 1)
+		{
+		iPassStreamId = aKeyData->PassphraseStreamId();
+		}
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	
+	TRAPD(err,UpdateStoreL());
+	
+	if (err != KErrNone)
+		{
+		iKeys.Remove(iKeys.Count() - 1);
+		#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+			iPassStreamId = oldDefaultPassphraseId;
+		#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+		User::Leave(err);
+		}
+	}
+
+void CFileKeyDataManager::UpdateStoreL()
+	{
+	WriteKeysToStoreL();
+
+	// Release ownership of key data and reset default passphrase id if store
+	// can't be written
+	TCleanupItem cleanupStore(RevertStore, iFileStore);
+	CleanupStack::PushL(cleanupStore);
+
+	iFileStore->CommitL();
+	
+	CleanupStack::Pop(); // cleanupStore
+	}
+
+/**
+ * "Transaction safe" key removal - only removes the key in memory and file if
+ * all operations are successful.
+ */
+void CFileKeyDataManager::RemoveL(TInt aObjectId)
+	{
+	TInt index;
+	const CFileKeyData* key = NULL;
+	for (index = 0 ; index < iKeys.Count() ; ++index)
+		{
+		if (iKeys[index]->Handle() == aObjectId)
+			{
+			key = iKeys[index];
+			break;
+			}
+		}
+	
+	if (!key)
+		{
+		User::Leave(KErrNotFound);
+		}
+
+	TCleanupItem cleanupStore(RevertStore, iFileStore);
+	CleanupStack::PushL(cleanupStore);	
+
+	iFileStore->DeleteL(key->PrivateDataStreamId());
+	iFileStore->DeleteL(key->PublicDataStreamId());
+	iFileStore->DeleteL(key->InfoDataStreamId());
+
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	// Remove the passphrase if it's the last key
+	TStreamId oldPassphraseId = iPassStreamId;
+	if (Count() == 1)
+		{
+		iFileStore->DeleteL(iPassStreamId);
+		iPassStreamId = KNullStreamId;
+		}
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	
+	// Remove the key
+	iKeys.Remove(index);
+	
+	TRAPD(res, WriteKeysToStoreL());
+
+	if (res != KErrNone)
+		{
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER		
+		iPassStreamId = oldPassphraseId;
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+		User::LeaveIfError(iKeys.Append(key)); // Put it back, shouldn't leave
+		User::Leave(res);
+		}
+	else 
+		{
+		delete key;   // Cannot leave from the point it's removed to here, so no cleanup stack!
+		}		
+	iFileStore->CommitL();
+
+	CleanupStack::Pop(); // cleanupStore
+	CompactStore();
+}
+
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+TBool CFileKeyDataManager::IsKeyAlreadyInStore(const TDesC& aKeyLabel, AuthServer::TIdentityId aIdentity) const
+	{//	Check each key in the store to determine if aKeyLabel already exists
+	TInt keyCount = iKeys.Count();
+	TBool isInStore = EFalse;
+	for (TInt index = 0; index < keyCount; ++index)
+		{
+		const TDesC& keyLabel = iKeys[index]->Label();
+		if (keyLabel.Compare(aKeyLabel)==0 && (iKeys[index]->Identity() == aIdentity))
+			{
+			isInStore = ETrue;
+			break;
+			}
+		}
+	return (isInStore);
+	}
+
+#else
+TBool CFileKeyDataManager::IsKeyAlreadyInStore(const TDesC& aKeyLabel) const
+{//	Check each key in the store to determine if aKeyLabel already exists
+	TInt keyCount = iKeys.Count();
+	TBool isInStore = EFalse;
+	for (TInt index = 0; index < keyCount; index++)
+	{
+		const TDesC& keyLabel = iKeys[index]->Label();
+		if (keyLabel.Compare(aKeyLabel)==0)
+		{
+			isInStore = ETrue;
+			break;
+		}
+	}
+
+	return (isInStore);
+}
+
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+TInt CFileKeyDataManager::Count() const
+	{
+	return iKeys.Count();
+	}	
+
+const CFileKeyData* CFileKeyDataManager::operator[](TInt aIndex) const
+	{
+	return iKeys[aIndex];
+	}
+
+const CFileKeyData* CFileKeyDataManager::Lookup(TInt aObjectId) const
+	{
+	TInt count = Count();
+	for (TInt i = 0; i < count; ++i)
+		{
+		if ((*this)[i]->Handle() == aObjectId)
+			{
+			return (*this)[i];
+			}
+		}
+	return NULL;
+	}
+
+//	*********************************************************************
+//	Management of file and store therein
+//	*********************************************************************
+
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+const CFileKeyData* CFileKeyDataManager::CreateKeyDataLC(const TDesC& aLabel, AuthServer::TIdentityId aIdentityId)
+	{
+	TInt objectId = ++iKeyIdentifier;
+	TStreamId infoData = CreateWriteStreamL();
+	TStreamId publicKeyData = CreateWriteStreamL();
+	TStreamId privateKeyData = CreateWriteStreamL();
+	return CFileKeyData::NewLC(objectId, aLabel, infoData, publicKeyData, privateKeyData, aIdentityId);
+	}
+
+#else
+const CFileKeyData* CFileKeyDataManager::CreateKeyDataLC(const TDesC& aLabel, TStreamId aPassStreamId)
+	{
+	ASSERT(aPassStreamId != KNullStreamId);
+	TInt objectId = ++iKeyIdentifier;
+	TStreamId infoData = CreateWriteStreamL();
+	TStreamId publicKeyData = CreateWriteStreamL();
+	TStreamId privateKeyData = CreateWriteStreamL();
+	return CFileKeyData::NewLC(objectId, aLabel, infoData, aPassStreamId, publicKeyData, privateKeyData);
+	}
+
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+//	Creates a new write stream in the store (which it then closes)
+//	Returns the TStreamId associated with it
+TStreamId CFileKeyDataManager::CreateWriteStreamL()
+	{
+	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
+	if (!iFileStore)
+		User::Leave(KErrNotReady);
+
+	RStoreWriteStream newStream;
+	TStreamId result = newStream.CreateLC(*iFileStore);
+	if (KNullStreamId == result)
+		User::Leave(KErrBadHandle);
+
+	newStream.CommitL();
+	CleanupStack::PopAndDestroy(&newStream);
+
+	return result;
+	}
+
+CKeyInfo* CFileKeyDataManager::ReadKeyInfoLC(const CFileKeyData& aKeyData) const
+	{
+	__ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
+	RStoreReadStream stream;
+	stream.OpenLC(*iFileStore, aKeyData.InfoDataStreamId());
+	CKeyInfo* info = CKeyInfo::NewL(stream);
+	
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	ReadAuthDetailsL(stream, *info);
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	CleanupStack::PopAndDestroy(&stream);
+	info->CleanupPushL();
+	if (info->Handle() != aKeyData.Handle())
+		{
+		User::Leave(KErrCorrupt); // is this appropriate?
+		}
+	return info;
+	}
+
+void CFileKeyDataManager::WriteKeyInfoL(const CFileKeyData& aKeyData, const CKeyInfo& aKeyInfo)
+	{
+	RStoreWriteStream infoStream;
+	OpenInfoDataStreamLC(aKeyData, infoStream);
+	infoStream << aKeyInfo;
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	WriteAuthDetailsL(infoStream, aKeyInfo);
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	infoStream.CommitL();
+	CleanupStack::PopAndDestroy(&infoStream);
+	}
+
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+void CFileKeyDataManager::WriteAuthDetailsL( RStoreWriteStream& aInfoStream, const CKeyInfo& aKeyInfo )
+	{
+	aInfoStream.WriteInt32L(aKeyInfo.Identity());
+	aInfoStream << aKeyInfo.AuthExpression();
+  	aInfoStream.WriteInt32L(aKeyInfo.Freshness());
+	}
+
+void CFileKeyDataManager::ReadAuthDetailsL( RStoreReadStream& aInfoStream, CKeyInfo& aKeyInfo ) const
+	{
+	aKeyInfo.SetIdentity(aInfoStream.ReadInt32L());
+	HBufC* expression = HBufC::NewLC(aInfoStream, KMaxTInt);
+	aKeyInfo.SetAuthExpressionL(*expression);
+	aKeyInfo.SetFreshness(aInfoStream.ReadInt32L());
+	CleanupStack::PopAndDestroy(expression);
+	}
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+void CFileKeyDataManager::SafeWriteKeyInfoL(const CFileKeyData& aKeyData, const CKeyInfo& aKeyInfo)
+	{
+	TCleanupItem cleanupStore(RevertStore, iFileStore);
+	CleanupStack::PushL(cleanupStore);	
+
+	WriteKeyInfoL(aKeyData, aKeyInfo);
+	iFileStore->CommitL();
+	
+	CleanupStack::Pop(); // cleanupStore	
+	}
+
+void CFileKeyDataManager::OpenInfoDataStreamLC(const CFileKeyData& aKeyData, RStoreWriteStream& aStream)
+	{
+	__ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
+	aStream.ReplaceLC(*iFileStore, aKeyData.InfoDataStreamId());
+	}
+
+void CFileKeyDataManager::OpenPublicDataStreamLC(const CFileKeyData& aKeyData, RStoreWriteStream& aStream)
+	{
+	__ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
+	aStream.ReplaceLC(*iFileStore, aKeyData.PublicDataStreamId());
+	}
+
+void CFileKeyDataManager::OpenPublicDataStreamLC(const CFileKeyData& aKeyData, RStoreReadStream& aStream) const
+	{
+	__ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
+	aStream.OpenLC(*iFileStore, aKeyData.PublicDataStreamId());
+	}
+
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+void CFileKeyDataManager::OpenPrivateDataStreamLC(const CFileKeyData& aKeyData, RStoreWriteStream& aStream) 
+	{
+	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
+	aStream.ReplaceLC(*iFileStore, aKeyData.PrivateDataStreamId());
+	}
+
+void CFileKeyDataManager::OpenPrivateDataStreamLC(const CFileKeyData& aKeyData, RStoreReadStream& aStream) const
+	{
+	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
+	aStream.OpenLC(*iFileStore, aKeyData.PrivateDataStreamId());
+	}
+
+#else
+
+void CFileKeyDataManager::OpenPrivateDataStreamLC(const CFileKeyData& aKeyData, CPassphrase& aPassphrase,
+												  RStoreReadStream& aStream) 
+	{
+	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
+	aStream.OpenLC(aPassphrase.Store(), aKeyData.PrivateDataStreamId());
+	}
+
+void CFileKeyDataManager::OpenPrivateDataStreamLC(const CFileKeyData& aKeyData, CPassphrase& aPassphrase,
+												  RStoreWriteStream& aStream)
+	{
+	__ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
+	aStream.ReplaceLC(aPassphrase.Store(), aKeyData.PrivateDataStreamId());
+	}
+
+
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+TInt CFileKeyDataManager::GetPassphraseTimeout() const
+	{
+	return iTimeout;
+	}
+
+void CFileKeyDataManager::SetPassphraseTimeoutL(TInt aTimeout)
+	{
+	TInt oldTimeout = iTimeout;
+
+	iTimeout = aTimeout;
+	TRAPD(err, WritePassphraseTimeoutL(); iFileStore->CommitL());
+
+	if (err != KErrNone)
+		{
+		iTimeout = oldTimeout;
+		iFileStore->RevertL(); // shouldn't leave
+		User::Leave(err);
+		}
+	}
+
+void CFileKeyDataManager::ReadPassphraseTimeoutL()
+	{
+	ASSERT(iTimeout == 0); // Only called from ConstructL()
+	
+	RStoreReadStream stream;
+	stream.OpenLC(*iFileStore, iTimeoutStreamId);
+	iTimeout = stream.ReadInt32L();
+	CleanupStack::PopAndDestroy(&stream);
+	}
+
+void CFileKeyDataManager::WritePassphraseTimeoutL()
+	{
+	RStoreWriteStream stream;
+	stream.ReplaceLC(*iFileStore, iTimeoutStreamId);
+	stream.WriteUint32L(iTimeout);	
+	stream.CommitL();
+	CleanupStack::PopAndDestroy(&stream);
+	}
+
+TStreamId CFileKeyDataManager::DefaultPassphraseId() const
+	{
+	ASSERT((iPassStreamId == KNullStreamId) == (Count() == 0));
+	return iPassStreamId;
+	}
+
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+/**
+ * Attempt to compact the store - it doesn't matter if these calls leave, it
+ * will only mean that the store takes up more space than necessary.
+ */
+void CFileKeyDataManager::CompactStore()
+	{
+	ASSERT(iFileStore);
+	TRAP_IGNORE(iFileStore->ReclaimL(); iFileStore->CompactL());
+	}
+
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+TUint32 CFileKeyDataManager::CachedIdentity()
+	{
+	TInt value = 0;
+	iIdentityId.Get(value);
+	return value;
+	}
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+// CFileKeyData ////////////////////////////////////////////////////////////////
+
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+CFileKeyData* CFileKeyData::NewLC(	TInt aObjectId, const TDesC& aLabel, TStreamId aInfoData,
+								  TStreamId aPublicData, TStreamId aPrivateData,
+								  AuthServer::TIdentityId aIdentityId)
+	{
+	CFileKeyData* self = new (ELeave) CFileKeyData(aObjectId, aInfoData, aPublicData, aPrivateData, aIdentityId);
+	CleanupStack::PushL(self);
+	self->ConstructL(aLabel);
+	return self;
+	}
+#else
+CFileKeyData* CFileKeyData::NewLC(TInt aObjectId, const TDesC& aLabel, TStreamId aInfoData,
+								  TStreamId aPassphraseId, TStreamId aPublicData, TStreamId aPrivateData)
+	{
+	CFileKeyData* self = new (ELeave) CFileKeyData(aObjectId, aInfoData, aPassphraseId, aPublicData, aPrivateData);
+	CleanupStack::PushL(self);
+	self->ConstructL(aLabel);
+	return self;
+	}
+
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+CFileKeyData* CFileKeyData::NewL(RStoreReadStream& aReadStream)
+	{
+	CFileKeyData* self = new (ELeave) CFileKeyData();
+	CleanupStack::PushL(self);
+	self->InternalizeL(aReadStream);
+	CleanupStack::Pop(self);
+	return (self);
+	}
+
+CFileKeyData::~CFileKeyData()
+	{
+	delete iLabel;
+	}
+
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+CFileKeyData::CFileKeyData(TInt aObjectId, TStreamId aInfoData,  
+						   TStreamId aPublicData, TStreamId aPrivateData,
+						   AuthServer::TIdentityId aIdentityId) :
+	iObjectId(aObjectId), iInfoData(aInfoData), 
+	iPublicKeyData(aPublicData), iPrivateKeyData(aPrivateData),
+	iIdentityId(aIdentityId)
+	{
+	ASSERT(iObjectId);
+	ASSERT(iInfoData != KNullStreamId);
+	ASSERT(iPublicKeyData != KNullStreamId);
+	ASSERT(iPrivateKeyData != KNullStreamId);
+	ASSERT(iIdentityId);
+	}
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+#ifdef KEYTOOL
+CFileKeyData::CFileKeyData(TInt aObjectId, TStreamId aInfoData,  
+						   TStreamId aPublicData, TStreamId aPrivateData,
+						   AuthServer::TIdentityId aIdentityId) :
+	iObjectId(aObjectId), iInfoData(aInfoData), 
+	iPublicKeyData(aPublicData), iPrivateKeyData(aPrivateData),
+	iIdentityId(aIdentityId)
+	{
+	ASSERT(iObjectId);
+	ASSERT(iInfoData != KNullStreamId);
+	ASSERT(iPublicKeyData != KNullStreamId);
+	ASSERT(iPrivateKeyData != KNullStreamId);
+	ASSERT(iIdentityId);
+	}
+#endif // KEYTOOL
+
+CFileKeyData::CFileKeyData(TInt aObjectId, TStreamId aInfoData, TStreamId aPassphraseId, 
+						   TStreamId aPublicData, TStreamId aPrivateData) :
+	iObjectId(aObjectId), iInfoData(aInfoData), iPassphraseId(aPassphraseId),
+	iPublicKeyData(aPublicData), iPrivateKeyData(aPrivateData)
+	{
+	ASSERT(iObjectId);
+	ASSERT(iInfoData != KNullStreamId);
+	ASSERT(iPassphraseId != KNullStreamId);
+	ASSERT(iPublicKeyData != KNullStreamId);
+	ASSERT(iPrivateKeyData != KNullStreamId);
+	}
+
+CFileKeyData::CFileKeyData()
+	{
+	}
+
+void CFileKeyData::ConstructL(const TDesC& aLabel)
+	{
+	TInt labelLen = aLabel.Length();
+	iLabel = HBufC::NewMaxL(labelLen);
+	TPtr theLabel(iLabel->Des());
+	theLabel.FillZ();
+	theLabel.Copy(aLabel);
+	}
+
+void CFileKeyData::InternalizeL(RReadStream& aReadStream)
+{
+	iObjectId = aReadStream.ReadInt32L();
+	iInfoData.InternalizeL(aReadStream);
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	iPassphraseId.InternalizeL(aReadStream);
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	iPublicKeyData.InternalizeL(aReadStream);
+	iPrivateKeyData.InternalizeL(aReadStream);
+	
+	TInt labelLen = aReadStream.ReadInt32L();
+	iLabel = HBufC::NewMaxL(labelLen);
+	TPtr theLabel((TUint16*)iLabel->Ptr(), labelLen, labelLen);
+	theLabel.FillZ(labelLen);
+	aReadStream.ReadL(theLabel);
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	iIdentityId = aReadStream.ReadInt32L();
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+}
+
+void CFileKeyData::ExternalizeL(RWriteStream& aWriteStream) const
+{
+	aWriteStream.WriteInt32L(iObjectId);
+	iInfoData.ExternalizeL(aWriteStream);
+#ifndef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	iPassphraseId.ExternalizeL(aWriteStream);
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	iPublicKeyData.ExternalizeL(aWriteStream);
+	iPrivateKeyData.ExternalizeL(aWriteStream);
+
+	TInt labelLen = iLabel->Length();
+	aWriteStream.WriteInt32L(labelLen);
+	TPtr theLabel(iLabel->Des());
+	theLabel.SetLength(labelLen);
+	aWriteStream.WriteL(theLabel);
+#ifdef SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+	aWriteStream.WriteInt32L(iIdentityId);
+#endif // SYMBIAN_KEYSTORE_USE_AUTH_SERVER
+
+}
+
+#ifdef KEYTOOL
+
+CFileKeyData* CFileKeyData::CreateOldKeyL(RStoreReadStream& aReadStream)
+	{
+	CFileKeyData* self = new (ELeave) CFileKeyData();
+	CleanupStack::PushL(self);
+	self->InternalizeOldKeyL(aReadStream);
+	CleanupStack::Pop(self);
+	return (self);
+	}
+
+void CFileKeyData::InternalizeOldKeyL(RReadStream& aReadStream)
+	{
+	iObjectId = aReadStream.ReadInt32L();
+	iInfoData.InternalizeL(aReadStream);
+	iPassphraseId.InternalizeL(aReadStream);
+	iPublicKeyData.InternalizeL(aReadStream);
+	iPrivateKeyData.InternalizeL(aReadStream);
+	
+	TInt labelLen = aReadStream.ReadInt32L();
+	iLabel = HBufC::NewMaxL(labelLen);
+	TPtr theLabel((TUint16*)iLabel->Ptr(), labelLen, labelLen);
+	theLabel.FillZ(labelLen);
+	aReadStream.ReadL(theLabel);
+	}
+
+void CFileKeyData::ExternalizeWithAuthL(RWriteStream& aWriteStream) 
+{
+	aWriteStream.WriteInt32L(iObjectId);
+	iInfoData.ExternalizeL(aWriteStream);
+	iPublicKeyData.ExternalizeL(aWriteStream);
+	iPrivateKeyData.ExternalizeL(aWriteStream);
+
+	TInt labelLen = iLabel->Length();
+	aWriteStream.WriteInt32L(labelLen);
+	TPtr theLabel(iLabel->Des());
+	theLabel.SetLength(labelLen);
+	aWriteStream.WriteL(theLabel);
+	aWriteStream.WriteInt32L(iIdentityId);
+}
+
+#endif // KEYTOOL