--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/pkiutilities/DeviceToken/Src/KeyStore/Server/DevCertKeyDataManager.cpp Tue Jan 26 15:20:08 2010 +0200
@@ -0,0 +1,693 @@
+/*
+* Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "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: Implementation of DevCertKeyDataManager
+*
+*/
+
+
+
+#include "DevCertKeyDataManager.h"
+#include "DevTokenDataTypes.h"
+#include "DevTokenCliServ.h"
+#include "DevTokenUtil.h"
+
+_LIT(KDevCertKeyStoreFilename,"DevCertKeys.dat");
+
+
+// ======== MEMBER FUNCTIONS ========
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::NewL()
+// Key store data manager - maintains array of objects representing keys
+// ---------------------------------------------------------------------------
+//
+CDevCertKeyDataManager* CDevCertKeyDataManager::NewL()
+ {
+ CDevCertKeyDataManager* self = new (ELeave) CDevCertKeyDataManager();
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::~CDevCertKeyDataManager()
+// ---------------------------------------------------------------------------
+//
+CDevCertKeyDataManager::~CDevCertKeyDataManager()
+ {
+ if (iFileStore)
+ {
+ CompactStore();
+ delete iFileStore;
+ }
+
+ iFile.Close(); // May already have been closed by store
+ iFs.Close();
+
+ iKeys.ResetAndDestroy();
+ iKeys.Close();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::CDevCertKeyDataManager()
+// ---------------------------------------------------------------------------
+//
+CDevCertKeyDataManager::CDevCertKeyDataManager() :
+ iRootStreamId(KNullStreamId),
+ iInfoStreamId(KNullStreamId)
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::ConstructL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::ConstructL()
+ {
+ User::LeaveIfError(iFs.Connect());
+ OpenStoreL();
+
+ RStoreReadStream lookupStream;
+ lookupStream.OpenLC(*iFileStore, iInfoStreamId);
+
+ TInt count = lookupStream.ReadInt32L();
+ for (TInt index = 0; index < count; index++)
+ {
+ const CDevCertKeyData* keyData = CDevCertKeyData::NewL(lookupStream);
+
+ if (keyData->Handle() > iKeyIdentifier)
+ iKeyIdentifier = keyData->Handle();
+
+ iKeys.Append(keyData);
+ }
+
+ CleanupStack::PopAndDestroy(&lookupStream);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::OpenStoreL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::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, KDevCertKeyStoreFilename, 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, KDevCertKeyStoreFilename, 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));
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::CreateStoreInFileL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::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 info stream - Currently no passphrase created, and no keys
+ RStoreWriteStream managerStream;
+ iInfoStreamId = managerStream.CreateLC(*iFileStore);
+ 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
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::OpenStoreInFileL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::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
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::RevertStore()
+// This is a cleanup item that reverts the store
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::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.
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::RevertStore()
+// Rewrites the info stream (ie the array of key data info) to the store
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::WriteKeysToStoreL()
+ {
+ RStoreWriteStream lookupStream;
+ lookupStream.ReplaceLC(*iFileStore, iInfoStreamId);
+
+ TInt keyCount = iKeys.Count();
+ lookupStream.WriteInt32L(keyCount);
+
+ for (TInt index = 0; index < keyCount; index++)
+ {
+ const CDevCertKeyData* key = iKeys[index];
+ key->ExternalizeL(lookupStream);
+ }
+
+ lookupStream.CommitL();
+ CleanupStack::PopAndDestroy(&lookupStream);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::AddL()
+// Add a key to the store. Assumes that the key data streams (info, public key
+// and private key) have already been written.
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::AddL(const CDevCertKeyData* aKeyData)
+ {
+ ASSERT(aKeyData);
+
+ // Add the key to to the array, rewrite the infostream and
+ // ONLY THEN commit the store
+ User::LeaveIfError(iKeys.Append(aKeyData));
+
+ 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);
+ User::Leave(err);
+ }
+
+ iFileStore->CommitL();
+
+ CleanupStack::Pop(); // cleanupStore
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::RemoveL()
+// "Transaction safe" key removal - only removes the key in memory and file if
+// all operations are successful.
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::RemoveL(TInt aObjectId)
+ {
+ TInt index;
+ const CDevCertKeyData* 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 key
+ iKeys.Remove(index);
+
+ TRAPD(res, WriteKeysToStoreL());
+ if (res != KErrNone)
+ {
+ 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();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::IsKeyAlreadyInStore().
+// ---------------------------------------------------------------------------
+//
+TBool CDevCertKeyDataManager::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);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager::Count().
+// ---------------------------------------------------------------------------
+//
+TInt CDevCertKeyDataManager::Count() const
+ {
+ return iKeys.Count();
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::operator[](TInt aIndex) const
+// ---------------------------------------------------------------------------
+//
+const CDevCertKeyData* CDevCertKeyDataManager::operator[](TInt aIndex) const
+ {
+ return iKeys[aIndex];
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::Lookup()
+// ---------------------------------------------------------------------------
+//
+const CDevCertKeyData* CDevCertKeyDataManager::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
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::CreateKeyDataLC()
+// ---------------------------------------------------------------------------
+//
+const CDevCertKeyData* CDevCertKeyDataManager::CreateKeyDataLC( const TDesC& aLabel )
+ {
+ TInt objectId = ++iKeyIdentifier;
+ TStreamId infoData = CreateWriteStreamL();
+ TStreamId publicKeyData = CreateWriteStreamL();
+ TStreamId privateKeyData = CreateWriteStreamL();
+ return CDevCertKeyData::NewLC(objectId, aLabel, infoData, publicKeyData, privateKeyData);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::CreateWriteStreamL()
+// Creates a new write stream in the store (which it then closes)
+// Returns the TStreamId associated with it
+// ---------------------------------------------------------------------------
+//
+TStreamId CDevCertKeyDataManager::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;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::ReadKeyInfoLC()
+// ---------------------------------------------------------------------------
+//
+CDevTokenKeyInfo* CDevCertKeyDataManager::ReadKeyInfoLC(const CDevCertKeyData& aKeyData) const
+ {
+ __ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
+ RStoreReadStream stream;
+ stream.OpenLC(*iFileStore, aKeyData.InfoDataStreamId());
+ CDevTokenKeyInfo* info = CDevTokenKeyInfo::NewL(stream);
+ CleanupStack::PopAndDestroy(&stream);
+ info->CleanupPushL();
+ if (info->Handle() != aKeyData.Handle())
+ {
+ User::Leave(KErrCorrupt); // is this appropriate?
+ }
+ return info;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::WriteKeyInfoL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::WriteKeyInfoL(const CDevCertKeyData& aKeyData, const CDevTokenKeyInfo& aKeyInfo)
+ {
+ RStoreWriteStream infoStream;
+ OpenInfoDataStreamLC(aKeyData, infoStream);
+ infoStream << aKeyInfo;
+ infoStream.CommitL();
+ CleanupStack::PopAndDestroy(&infoStream);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::SafeWriteKeyInfoL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::SafeWriteKeyInfoL(const CDevCertKeyData& aKeyData, const CDevTokenKeyInfo& aKeyInfo)
+ {
+ TCleanupItem cleanupStore(RevertStore, iFileStore);
+ CleanupStack::PushL(cleanupStore);
+
+ WriteKeyInfoL(aKeyData, aKeyInfo);
+ iFileStore->CommitL();
+
+ CleanupStack::Pop(); // cleanupStore
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::OpenInfoDataStreamLC()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::OpenInfoDataStreamLC(const CDevCertKeyData& aKeyData, RStoreWriteStream& aStream)
+ {
+ __ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
+ aStream.ReplaceLC(*iFileStore, aKeyData.InfoDataStreamId());
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::OpenPublicDataStreamLC()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::OpenPublicDataStreamLC(const CDevCertKeyData& aKeyData, RStoreWriteStream& aStream)
+ {
+ __ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
+ aStream.ReplaceLC(*iFileStore, aKeyData.PublicDataStreamId());
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::OpenPublicDataStreamLC()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::OpenPublicDataStreamLC(const CDevCertKeyData& aKeyData, RStoreReadStream& aStream) const
+ {
+ __ASSERT_ALWAYS(iFileStore, PanicServer(EPanicStoreInitialised));
+ aStream.OpenLC(*iFileStore, aKeyData.PublicDataStreamId());
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::OpenPrivateDataStreamLC()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::OpenPrivateDataStreamLC(const CDevCertKeyData& aKeyData,
+ RStoreWriteStream& aStream)
+ {
+ __ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
+ aStream.ReplaceLC(*iFileStore, aKeyData.PrivateDataStreamId());
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::OpenPrivateDataStreamLC()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyDataManager::OpenPrivateDataStreamLC(const CDevCertKeyData& aKeyData,
+ RStoreReadStream& aStream)
+ {
+ __ASSERT_DEBUG(iFileStore, PanicServer(EPanicStoreInitialised));
+ aStream.OpenLC(*iFileStore, aKeyData.PrivateDataStreamId());
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyDataManager:::CompactStore()
+// 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 CDevCertKeyDataManager::CompactStore()
+ {
+ ASSERT(iFileStore);
+ TRAP_IGNORE(iFileStore->ReclaimL(); iFileStore->CompactL());
+ }
+
+
+// CDevCertKeyData
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyData::NewLC()
+// ---------------------------------------------------------------------------
+//
+CDevCertKeyData* CDevCertKeyData::NewLC(TInt aObjectId, const TDesC& aLabel, TStreamId aInfoData,
+ TStreamId aPublicData, TStreamId aPrivateData)
+ {
+ CDevCertKeyData* self = new (ELeave) CDevCertKeyData(aObjectId, aInfoData, aPublicData, aPrivateData);
+ CleanupStack::PushL(self);
+ self->ConstructL(aLabel);
+ return self;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyData::NewL()
+// ---------------------------------------------------------------------------
+//
+CDevCertKeyData* CDevCertKeyData::NewL(RStoreReadStream& aReadStream)
+ {
+ CDevCertKeyData* self = new (ELeave) CDevCertKeyData();
+ CleanupStack::PushL(self);
+ self->InternalizeL(aReadStream);
+ CleanupStack::Pop(self);
+ return (self);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyData::~CDevCertKeyData()
+// ---------------------------------------------------------------------------
+//
+CDevCertKeyData::~CDevCertKeyData()
+ {
+ delete iLabel;
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyData::CDevCertKeyData()
+// ---------------------------------------------------------------------------
+//
+CDevCertKeyData::CDevCertKeyData(TInt aObjectId, TStreamId aInfoData,
+ TStreamId aPublicData, TStreamId aPrivateData) :
+ iObjectId(aObjectId), iInfoData(aInfoData),
+ iPublicKeyData(aPublicData), iPrivateKeyData(aPrivateData)
+ {
+ ASSERT(iObjectId);
+ ASSERT(iInfoData != KNullStreamId);
+ ASSERT(iPublicKeyData != KNullStreamId);
+ ASSERT(iPrivateKeyData != KNullStreamId);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyData::CDevCertKeyData()
+// ---------------------------------------------------------------------------
+//
+CDevCertKeyData::CDevCertKeyData()
+ {
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyData::ConstructL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyData::ConstructL(const TDesC& aLabel)
+ {
+ TInt labelLen = aLabel.Length();
+ iLabel = HBufC::NewMaxL(labelLen);
+ TPtr theLabel(iLabel->Des());
+ theLabel.FillZ();
+ theLabel.Copy(aLabel);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyData::InternalizeL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyData::InternalizeL(RReadStream& aReadStream)
+ {
+ iObjectId = aReadStream.ReadInt32L();
+ iInfoData.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);
+ }
+
+
+// ---------------------------------------------------------------------------
+// CDevCertKeyData::ExternalizeL()
+// ---------------------------------------------------------------------------
+//
+void CDevCertKeyData::ExternalizeL(RWriteStream& aWriteStream) const
+ {
+ 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);
+ }
+
+//EOF
+