--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xmlsecurityengine/xmlseccertman/src/xmlsecmsymbiankeystore.cpp Thu Dec 17 09:29:21 2009 +0200
@@ -0,0 +1,788 @@
+/*
+* Copyright (c) 2009 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: An XmlSec interface to the Symbian Unified Key Store.
+*
+*/
+
+#include <mctkeystore.h>
+#include <asymmetric.h>
+#include <asn1dec.h>
+#include <asn1enc.h>
+#include <x509cert.h>
+#include <charconv.h>
+#include <utf.h>
+
+#include "xmlsecmsymbiankeystore.h"
+
+// -----------------------------------------------------------------------------
+// FindMatchedKey Find the key that matched iKeyLabelToFind from iKeys.
+// The key found will be stored in iKey
+// -----------------------------------------------------------------------------
+//
+void CSymbianKeyStore::FindMatchedKey()
+ {
+
+ TInt numKey = iKeys.Count();
+
+ // Reset iKey
+ if (iKey)
+ {
+ iKey->Release();
+ iKey = NULL;
+ }
+
+ // No label to be found
+ if (!iKeyLabelToFind)
+ return;
+
+ for (int i=0;i<numKey;i++)
+ {
+ CCTKeyInfo* key = (CCTKeyInfo *)iKeys[i];
+ if (iKeyLabelToFind->Compare(key->Label()) == 0)
+ {
+ iKey = key;
+ }
+ }
+
+ ResetAndDestroyKeysArray(); //iKeys
+ }
+
+// -----------------------------------------------------------------------------
+// GetRSASignatureL
+// Sets iSignature buffer
+// -----------------------------------------------------------------------------
+//
+void CSymbianKeyStore::GetRSASignatureL()
+ {
+ if (iSignature)
+ {
+ delete iSignature;
+ iSignature = NULL;
+ }
+ iSignature = iRSASignature->S().BufferLC();
+ CleanupStack::Pop(iSignature); // BufferLC
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CSymbianKeyStore::CSymbianKeyStore()
+: CActive( EPriorityStandard ),
+ iState( EUnitialized ),
+ iVerifyResult( EFalse )
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// Second phase constructor
+// ---------------------------------------------------------------------------
+//
+void CSymbianKeyStore::ConstructL()
+ {
+ User::LeaveIfError(iFs.Connect());
+ CActiveScheduler::Add(this);
+ }
+
+// ---------------------------------------------------------------------------
+// Two phase constructor
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CSymbianKeyStore* CSymbianKeyStore::NewL()
+ {
+ CSymbianKeyStore* self = NewLC();
+ CleanupStack::Pop(self);
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Two phase constructor
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CSymbianKeyStore* CSymbianKeyStore::NewLC()
+ {
+ CSymbianKeyStore* self = new( ELeave ) CSymbianKeyStore;
+
+ CleanupStack::PushL( self );
+ self->ConstructL();
+
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+CSymbianKeyStore::~CSymbianKeyStore()
+ {
+ Cancel();
+
+ ResetAndDestroyKeysArray(); //iKeys
+
+ // Free memory
+ delete iDataToSign;
+ delete iDataToVerify;
+ delete iSignature;
+ delete iPublicKeyData;
+ delete iKeyLabelToFind;
+ delete iRSASignature;
+ if (iKey)
+ {
+ iKey->Release();
+ }
+
+ if (iRSASigner)
+ {
+ iRSASigner->Release();
+ }
+
+ delete iKeyStore;
+
+ iFs.Close();
+ }
+
+// -----------------------------------------------------------------------------
+// Release all resources kept in iKeys array (exept for iKey which is released
+// separetly) and empty iKeys array
+// -----------------------------------------------------------------------------
+//
+void CSymbianKeyStore::ResetAndDestroyKeysArray()
+ {
+ TInt count = iKeys.Count();
+
+ for ( int i=0; i<count; ++i )
+ {
+ CCTKeyInfo* key = iKeys[i];
+ if ( key != iKey )
+ {
+ key->Release();
+ }
+ }
+ iKeys.Reset();
+ }
+
+// -----------------------------------------------------------------------------
+// PerformRSASignOperation
+// Sign data
+// -----------------------------------------------------------------------------
+//
+void CSymbianKeyStore::PerformRSASignOperation()
+{
+ if (!iKey || !iKeyStore)
+ {
+ return;
+ }
+
+ iRSASigner->Sign(*iDataToSign, iRSASignature, iStatus);
+ iState = EPerformRSASignOperation;
+ SetActive();
+
+ // RunL called again when this completes
+}
+
+// -----------------------------------------------------------------------------
+// ExportRSAPublicKeyL
+// Export public key if none present
+// -----------------------------------------------------------------------------
+//
+void CSymbianKeyStore::ExportRSAPublicKeyL()
+{
+ // iKey is a CCTKeyInfo*
+ // iPublicKeyData is an HBufC8*
+ __ASSERT_ALWAYS(iKey, User::Leave(KErrGeneral));
+
+ if (iPublicKeyData)
+ {
+ delete iPublicKeyData;
+ iPublicKeyData = NULL;
+ }
+
+ iKeyStore->ExportPublic(*iKey, iPublicKeyData, iStatus);
+ iState = EExportPublic;
+ SetActive();
+
+ }
+
+// -----------------------------------------------------------------------------
+// PerformRSAVerifyOperationL
+// Verify an RSA signed data
+// -----------------------------------------------------------------------------
+//
+void CSymbianKeyStore::PerformRSAVerifyOperationL()
+ {
+ // iRSAPublicKey is a CRSAPublicKey*
+ if (!iPublicKeyData)
+ {
+ return;
+ }
+
+ CX509SubjectPublicKeyInfo* ki =
+ CX509SubjectPublicKeyInfo::NewLC(*iPublicKeyData);
+
+ TAlgorithmId algorithmId = ESHA1;
+ CAlgorithmIdentifier* digestId=CAlgorithmIdentifier::NewLC(algorithmId,KNullDesC8());
+
+ TX509KeyFactory factory;
+ CRSAPublicKey *publicKey = factory.RSAPublicKeyL(ki->KeyData());
+ CleanupStack::PushL(publicKey);
+
+ CRSAPKCS1v15Verifier* verifier = CRSAPKCS1v15Verifier::NewLC(*publicKey);
+
+ HBufC8* publicDecryptOutput = verifier->InverseSignLC(*iRSASignature);
+ CRSASignatureResult* decoder = factory.RSASignatureResultL(*digestId, *iDataToVerify);
+ CleanupStack::PushL(decoder);
+
+ TPtr8 outputPtr(publicDecryptOutput->Des());
+ iVerifyResult = decoder->VerifyL(outputPtr);
+
+ CleanupStack::PopAndDestroy(decoder);
+ CleanupStack::PopAndDestroy(publicDecryptOutput);
+ CleanupStack::PopAndDestroy(verifier);
+ CleanupStack::PopAndDestroy(publicKey);
+ CleanupStack::PopAndDestroy(digestId);
+ CleanupStack::PopAndDestroy(ki);
+ }
+
+// -----------------------------------------------------------------------------
+// CSymbianKeyStore::RunL
+// Handles an active object's request completion event.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CSymbianKeyStore::RunL()
+ {
+ if (iStatus!=KErrNone)
+ {
+ User::Leave(iStatus.Int());
+ }
+
+ switch(iState)
+ {
+ case EInitializingKeystore:
+ CActiveScheduler::Stop();
+ break;
+ case EFindingKeys:
+ FindMatchedKey();
+ CActiveScheduler::Stop();
+ break;
+ case EImportKey:
+ case ECreateKey:
+ CActiveScheduler::Stop();
+ break;
+ case EOpenRSAKeyForSigning:
+ PerformRSASignOperation();
+ break;
+ case EPerformRSASignOperation:
+ CActiveScheduler::Stop();
+ break;
+ case EExportPublic:
+ PerformRSAVerifyOperationL();
+ CActiveScheduler::Stop();
+ break;
+
+ }
+
+ }
+
+// -----------------------------------------------------------------------------
+// CSymbianKeyStore::DoCancel
+// This function is called as part of the active object's Cancel().
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+void CSymbianKeyStore::DoCancel()
+ {
+ }
+
+// -----------------------------------------------------------------------------
+// CSymbianKeyStore::RunError
+// Handles Leaves from RunL function.
+// (other items were commented in a header).
+// -----------------------------------------------------------------------------
+//
+TInt CSymbianKeyStore::RunError(TInt aError)
+ {
+ iError=aError;
+ CActiveScheduler::Stop();
+ return KErrNone;
+ }
+
+// -----------------------------------------------------------------------------
+// CSymbianKeyStore::CreateUnifiedKeyStoreL
+// Create the Unified Key Store structure iKeyStore
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSymbianKeyStore::CreateUnifiedKeyStoreL()
+ {
+
+ if (iKeyStore)
+ {
+ delete iKeyStore;
+ iKeyStore = NULL;
+ }
+ iKeyStore = CUnifiedKeyStore::NewL(iFs);
+ iKeyStore->Initialize(iStatus);
+ iState = EInitializingKeystore;
+ SetActive();
+
+ // RunL() called when this completes
+
+ }
+
+// -----------------------------------------------------------------------------
+// FindKey
+// Lists keys from Unified Key Store
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSymbianKeyStore::FindKey(
+ const TDesC8 &aLabel, CKeyInfoBase::EKeyAlgorithm aAlgo)
+ {
+ // KApplicationUID is the UID of the key owner application
+ // iKeys is an RMPointerArray<CCTKeyInfo> that is filled with the keys found
+
+ TCTKeyAttributeFilter filter;
+ filter.iUsage = EPKCS15UsageSign;
+ if (aAlgo!=CCTKeyInfo::EInvalidAlgorithm)
+ filter.iKeyAlgorithm = aAlgo;
+
+ // Store aLabel
+ if (iKeyLabelToFind)
+ {
+ delete iKeyLabelToFind;
+ iKeyLabelToFind = NULL;
+ }
+ TRAPD(err,iKeyLabelToFind = CnvUtfConverter::ConvertToUnicodeFromUtf8L(aLabel));
+ if (err != KErrNone)
+ {
+ iError=err;
+ return;
+ }
+
+ iKeyStore->List(iKeys, filter, iStatus);
+ iState = EFindingKeys;
+ SetActive();
+ // RunL() called when this completes
+ }
+
+// -----------------------------------------------------------------------------
+// hasKey
+// Check if a key is found in the Unified Key Store
+// Returns: KErrNone if the key is found
+// KErrNotFound if the key is not found
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CSymbianKeyStore::hasKey()
+ {
+ if (iKey)
+ return KErrNone;
+ else
+ return KErrNotFound;
+ }
+
+// -----------------------------------------------------------------------------
+// GetKeySize
+// Get the size of the key stored
+// Returns: Size of the key
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TUint CSymbianKeyStore::GetKeySize()
+ {
+ // assert iKey
+ return iKey->Size();
+ }
+
+// -----------------------------------------------------------------------------
+// GetKeyAlgorithm
+// Get the algorithm of the key stored
+// Returns: CCTKeyInfo::EKeyAlgorithm
+// -----------------------------------------------------------------------------
+//
+EXPORT_C CCTKeyInfo::EKeyAlgorithm CSymbianKeyStore::GetKeyAlgorithm()
+ {
+ // assert iKey
+ return iKey->Algorithm();
+ }
+
+// -----------------------------------------------------------------------------
+// CreateRSAKey
+// Creates RSA key and adds it to Unified Key Store
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSymbianKeyStore::CreateRSAKey(
+ const TUint aSize, const TDesC8 &aKeyName)
+ {
+ HBufC16* unicodeKeyName=NULL;
+ // iKey is a CCTKeyInfo* that will be set if the function succeeds
+ if (iKey)
+ {
+ //delete iKey;
+ iKey->Release();
+ iKey = NULL;
+ }
+ // Convert key name from TDesC8 to TDesC16
+ TRAPD(err,unicodeKeyName=CnvUtfConverter::ConvertToUnicodeFromUtf8L(aKeyName));
+ if (err != KErrNone)
+ {
+ iError=err;
+ return;
+ }
+
+ // Find the number of file key stores present
+ TInt num = iKeyStore->KeyStoreManagerCount();
+ TBool found = EFalse;
+ TInt keyStoreIndex = 0;
+ TInt index;
+
+ // Find the Symbian file key store index
+ for (index = 0;index < num;index++)
+ {
+ MCTKeyStoreManager& manager = iKeyStore->KeyStoreManager(index);
+ MCTToken& token = manager.Token();
+ TUid tokenuid = token.Handle().iTokenTypeUid;
+
+ if ( tokenuid == TUid::Uid(KTokenTypeFileKeystore) ) // Symbian's file key store, defined in mctkeystore.h
+ {
+ found = ETrue;
+ break;
+ }
+ }
+
+ if ( found )
+ {
+ // If found, then store in the place pointed by the index else it shall take the first key store
+ keyStoreIndex = index;
+ }
+
+ TTime startDate, endDate;
+ startDate.UniversalTime();
+ endDate.UniversalTime();
+ endDate += TTimeIntervalYears(1); // key valid for a year
+
+ iKeyStore->CreateKey(
+ keyStoreIndex,
+ EPKCS15UsageSign,
+ aSize,
+ *unicodeKeyName,
+ CCTKeyInfo::ERSA,
+ CCTKeyInfo::EExtractable,
+ startDate,
+ endDate,
+ iKey,
+ iStatus);
+ delete unicodeKeyName;
+ iState = ECreateKey;
+ SetActive();
+
+ // RunL() called when this completes
+ }
+
+// -----------------------------------------------------------------------------
+// ImportKey
+// Import Key from Unified Key Store
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSymbianKeyStore::ImportKey(
+ const TDesC8 &aKeyData,
+ const TDesC8 &aKeyName)
+ {
+ HBufC16* unicodeKeyName=NULL;
+ // iKey is a CCTKeyInfo* that will be set if the function succeeds
+ if (iKey)
+ {
+ //delete iKey;
+ iKey->Release();
+ iKey = NULL;
+ }
+
+ // Convert key name from TDesC8 to TDesC16
+ TRAPD(err,unicodeKeyName=CnvUtfConverter::ConvertToUnicodeFromUtf8L(aKeyName));
+ if (err != KErrNone)
+ {
+ iError=err;
+ return;
+ }
+
+ // Find the number of file key stores present
+ TInt num = iKeyStore->KeyStoreManagerCount();
+ TBool found = EFalse;
+ TInt keyStoreIndex = 0;
+ TInt index;
+
+ // Find the Symbian file key store index
+ for (index = 0;index < num;index++)
+ {
+ MCTKeyStoreManager& manager = iKeyStore->KeyStoreManager(index);
+ MCTToken& token = manager.Token();
+ TUid tokenuid = token.Handle().iTokenTypeUid;
+
+ if ( tokenuid == TUid::Uid(KTokenTypeFileKeystore) ) // Symbian's file key store, defined in mctkeystore.h
+ {
+ found = ETrue;
+ break;
+ }
+ }
+
+ if ( found )
+ {
+ // If found, then store in the place pointed by the index else it shall take the first key store
+ keyStoreIndex = index;
+ }
+
+
+ TTime startDate, endDate;
+ startDate.UniversalTime();
+ endDate.UniversalTime();
+ endDate += TTimeIntervalYears(1); // key valid for a year
+
+ iKeyStore->ImportKey(
+ keyStoreIndex,
+ aKeyData,
+ EPKCS15UsageSign,
+ *unicodeKeyName,
+ CCTKeyInfo::EExtractable,
+ startDate,
+ endDate,
+ iKey,
+ iStatus);
+ iState = EImportKey;
+ delete unicodeKeyName;
+ SetActive();
+
+ // RunL() called when this completes
+ }
+
+// -----------------------------------------------------------------------------
+// RSASignL
+// Opens RSA key for signing the data
+// -----------------------------------------------------------------------------
+//
+EXPORT_C void CSymbianKeyStore::RSASignL(
+ const TUint8* aDataToSign, TUint aLen)
+ {
+ // iRSASigner is an MRSASigner* object returned from Open()
+ // iDataToSign is a HBufC8* containing data to be signed
+ // iRSASignature is a CRSASignature* which will contain the result
+ __ASSERT_ALWAYS(iKey, User::Leave(KErrGeneral));
+
+ if (iDataToSign)
+ {
+ delete iDataToSign;
+ iDataToSign = NULL;
+ }
+
+ if (iRSASigner)
+ {
+ iRSASigner->Release();
+ iRSASigner = NULL;
+ }
+
+ if (iRSASignature)
+ {
+ delete iRSASignature;
+ iRSASignature = NULL;
+ }
+
+ TPtrC8 dataPtr(aDataToSign, aLen);
+ // Build ASN1 encoding of digestAlgId and digest..
+ CASN1EncSequence* encAll = CASN1EncSequence::NewLC();
+
+ // Build AlgID encoder (for SHA1)
+ CASN1EncSequence* encAlgId = CASN1EncSequence::NewLC();
+
+ CASN1EncObjectIdentifier* encObjId = CASN1EncObjectIdentifier::NewLC(KSHA1);
+ encAlgId->AddChildL(encObjId);
+ CleanupStack::Pop(encObjId); // encObjId, now owned by endAlgId
+
+ CASN1EncNull* encNull = CASN1EncNull::NewLC();
+ encAlgId->AddChildL(encNull);
+ CleanupStack::Pop(encNull); // encNull, now owned by endAlgId
+
+ encAll->AddChildL(encAlgId);
+ CleanupStack::Pop(encAlgId); // encAlgId, now owned by encAll
+
+ CASN1EncOctetString* encDigest = CASN1EncOctetString::NewLC(dataPtr);
+ encAll->AddChildL(encDigest);
+ CleanupStack::Pop(encDigest); // encDigest, now owned by encAll
+
+ iDataToSign = HBufC8::NewMaxL(encAll->LengthDER());
+ TUint pos = 0;
+ TPtr8 digestInfoPtr = iDataToSign->Des();
+ encAll->WriteDERL(digestInfoPtr, pos);
+ CleanupStack::PopAndDestroy(encAll);
+
+ iKeyStore->Open(*iKey, iRSASigner, iStatus);
+ iState = EOpenRSAKeyForSigning;
+ SetActive();
+
+ }
+
+// -----------------------------------------------------------------------------
+// RSAVerifyL
+// Verify an RSA signature with a self-created private key in Unified Key Store
+// -----------------------------------------------------------------------------
+//
+
+EXPORT_C void CSymbianKeyStore::RSAVerifyL(
+ const TUint8* aDataToVerify, // Data to be verified with the signature
+ TUint aDataLen, // Length of the data to be verified
+ const TUint8* aSig, // A reference to the signature that signed the data
+ TUint aSigLen) // Length of the signature
+ {
+ iOutOfMemoryFlag = EFalse;
+ if (iDataToVerify)
+ {
+ delete iDataToVerify;
+ iDataToVerify = NULL;
+ }
+
+ // Store the data
+
+ TPtrC8 ptr(aDataToVerify, aDataLen);
+ iDataToVerify = ptr.AllocL();
+ // Store the signature
+ ptr.Set(aSig, aSigLen);
+ RInteger sigInt = RInteger::NewL(ptr);
+ CleanupClosePushL(sigInt);
+ if (iRSASignature)
+ {
+ delete iRSASignature;
+ iRSASignature = NULL;
+ }
+ iRSASignature = CRSASignature::NewL(sigInt);
+ CleanupStack::Pop(&sigInt);
+
+ // Export public key if none present
+ // iPublicKeyData is an HBufC8*
+ ExportRSAPublicKeyL();
+
+ }
+
+// -----------------------------------------------------------------------------
+// RSAVerifyWithPublicKeyL
+// Verify an RSA signed data with a public key passed from a certificate
+// Returns: ETrue The verification is succeeded
+// EFalse The verification is failed
+// -----------------------------------------------------------------------------
+//
+
+EXPORT_C TBool CSymbianKeyStore::RSAVerifyWithPublicKeyL(
+ const TUint8* aDataToVerify, // Signed data to be verified
+ TUint aDataLen, // Length of the signed data
+ const TUint8* aSig, // A reference to the signature that signed the data
+ TUint aSigLen, // Length of the signature
+ CSubjectPublicKeyInfo *aSubPubKeyInfo) // A handle to the public key passed from a certificate
+ {
+ iOutOfMemoryFlag = EFalse;
+ if (iDataToVerify)
+ {
+ delete iDataToVerify;
+ iDataToVerify = NULL;
+ }
+
+ // Store the data
+ TPtrC8 ptr(aDataToVerify, aDataLen);
+ iDataToVerify = ptr.AllocL();
+
+ // Store the signature
+ ptr.Set(aSig, aSigLen);
+ RInteger sigInt = RInteger::NewL(ptr);
+ CleanupClosePushL(sigInt);
+ if (iRSASignature)
+ {
+ delete iRSASignature;
+ iRSASignature = NULL;
+ }
+ iRSASignature = CRSASignature::NewL(sigInt);
+ CleanupStack::Pop(&sigInt);
+
+ TAlgorithmId algorithmId = ESHA1;
+ CAlgorithmIdentifier* digestId=CAlgorithmIdentifier::NewLC(algorithmId,KNullDesC8());
+ TX509KeyFactory factory;
+ CRSAPublicKey *publicKey = factory.RSAPublicKeyL(aSubPubKeyInfo->KeyData());
+ CleanupStack::PushL(publicKey);
+
+ CRSAPKCS1v15Verifier* verifier = CRSAPKCS1v15Verifier::NewLC(*publicKey);
+ HBufC8* publicDecryptOutput = verifier->InverseSignLC(*iRSASignature);
+ CRSASignatureResult* decoder = factory.RSASignatureResultL(*digestId, *iDataToVerify);
+ CleanupStack::PushL(decoder);
+ TPtr8 outputPtr(publicDecryptOutput->Des());
+ iVerifyResult = decoder->VerifyL(outputPtr);
+
+ CleanupStack::PopAndDestroy(decoder);
+ CleanupStack::PopAndDestroy(publicDecryptOutput);
+ CleanupStack::PopAndDestroy(verifier);
+ CleanupStack::PopAndDestroy(publicKey);
+ CleanupStack::PopAndDestroy(digestId);
+
+ return iVerifyResult;
+ }
+
+// -----------------------------------------------------------------------------
+// GetSignedData
+// Get signed data
+// Returns: length of signed data
+// -----------------------------------------------------------------------------
+//
+EXPORT_C const TUint8* CSymbianKeyStore::GetSignedData(TUint *aLen)
+ {
+ TInt leaveValue;
+
+ if (iRSASignature)
+ {
+ if (iSignature)
+ {
+ delete iSignature;
+ iSignature = NULL;
+ }
+
+ TRAP(leaveValue, GetRSASignatureL()) ;
+ if ( leaveValue != KErrNone )
+ {
+ iError = leaveValue;
+ }
+ if (iSignature)
+ {
+ *aLen = iSignature->Length();
+ return (iSignature->Ptr());
+ }
+ }
+
+ // in case of errors
+ *aLen = 0;
+ return NULL;
+ }
+
+// -----------------------------------------------------------------------------
+// GetVerifyResult
+// Returns verification result
+// Returns: ETrue The verification is succeeded
+// EFalse The verification is failed
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TBool CSymbianKeyStore::GetVerifyResult()
+ {
+ return iVerifyResult;
+ }
+
+// -----------------------------------------------------------------------------
+// GetError
+// Get the error flag
+// Returns: error code
+// -----------------------------------------------------------------------------
+//
+EXPORT_C TInt CSymbianKeyStore::GetError()
+ {
+ return iError;
+ }