--- a/cryptoservices/filebasedcertificateandkeystores/test/tcryptotokenhai/tcryptotokenhai.cpp Thu Apr 01 00:24:41 2010 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,619 +0,0 @@
-/*
-* 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 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:
-* This class implements the reference Crypto Token Hardware Abstraction
-* Interface (HAI). It is just intended to show how operations using
-* device keys can be performed using crypto token framework. In the
-* real world scenario, this HAI should be replaced by device drivers
-* by the licensees. In such a case, all the operations performed by
-* the replacing class would be performed in Kernel Space.
-*
-*/
-
-
-#include "tcryptotokenhai.h"
-#include "tkeydetails.h"
-#include "cryptosignatureapi.h"
-#include "keys.h"
-
-#include <cryptospi/cryptoparams.h>
-#include <cryptospi/cryptospidef.h>
-
-EXPORT_C CCryptoTokenHai* CCryptoTokenHai::NewLC(MCTToken* aToken)
- {
- CCryptoTokenHai* instance = new(ELeave) CCryptoTokenHai(*aToken);
- CleanupStack::PushL(instance);
- instance->ConstructL();
- return instance;
- }
-
-EXPORT_C CCryptoTokenHai* CCryptoTokenHai::NewL(MCTToken* aToken)
- {
- CCryptoTokenHai* instance = CCryptoTokenHai::NewLC(aToken);
- CleanupStack::Pop(instance);
- return instance;
- }
-
-void CCryptoTokenHai::ConstructL()
- {
- User::LeaveIfError(iFs.Connect());
- OpenStoreL();
- }
-
-CCryptoTokenHai::CCryptoTokenHai(MCTToken& aToken)
- :iToken(aToken)
- {}
-
-EXPORT_C CCryptoTokenHai::~CCryptoTokenHai()
- {
- if(iFileStore)
- {
- CompactStore();
- delete iFileStore;
- }
-
- iFs.Close();
- iKeys.ResetAndDestroy();
- iKeys.Close();
- }
-
-/**
- * Performs the decryption operation.
- *
- * This API gets called when the decryption is supposed to be done in
- * the hardware.
- *
- * @param aHandle The key handle
- * @param aCiphertext The cipher text. This is not being used presently
- * due to decryption logic used in this function.
- * @param aPlainText Output param. The decrypted plain text. Ownership
- * of the pointer lies with the caller.
- *
- * @leave This function can leave with following error codes:-
- * - KErrNotFound - If the key corresponding to given handle is not
- * found.
- * - Any other error code returned by AllocL().
- *
- * @note This function does not actually implement ECC decryption. It
- * just intends to show that the key is with this class and it can
- * do actual ECC decryption here. This function just returns the
- * private key as decrypted text. The caller can verify the decryption
- * by ensuring that test case has same public and private keys and then
- * comparing the decrypted text with public key.
- */
-EXPORT_C void CCryptoTokenHai::DecryptL( TInt aHandle,
- const TDesC8& /* aCiphertext */,
- HBufC8*& aPlainText )
- {
- TInt keyIndex = KeyPresent(aHandle);
- if(keyIndex == KErrNotFound)
- {
- User::Leave(KErrNotFound);
- }
-
- ExportPrivateKeyL(aHandle, aPlainText);
- }
-
-/**
- * Performs the signing operation.
- *
- * This API gets called when the signing is supposed to be done inside
- * the hardware.
- *
- * @param aHandle The key handle
- * @param aPlaintext The text which has to be signed. This is not being
- * used due to signing logic used in this function.
- * @param aSignature Output param. The signature in HBufC8 format.
- * Ownership of the pointer lies with the caller. This should be
- * converted to CCryptoParams by the crypto token reference plugin.
- *
- * @leave This function can leave with following error codes:-
- * - KErrNotFound - If the key corresponding to given handle is not
- * found.
- * - Any other error code returned by AllocL().
- *
- * @note This function does not actually implement ECC signing. It
- * just intends to show that the key is with this class and it can
- * do actual ECC signing here. Currently this function just returns
- * the private key as output signature. The caller can verify the
- * signature by ensuring that test case has same public and private
- * keys and then comparing the signature with public key.
- */
-EXPORT_C void CCryptoTokenHai::SignL( TInt aHandle,
- const TDesC8& /* aPlaintext */,
- HBufC8*& aSignature )
- {
- TInt keyIndex = KeyPresent(aHandle);
- if(keyIndex == KErrNotFound)
- {
- User::Leave(KErrNotFound);
- }
-
- ExportPrivateKeyL(aHandle, aSignature);
- }
-
-/**
- * Returns the index of the key whose handle is given.
- *
- * @param aHandle Handle of the key. This is used to search the key.
- *
- * @return index of the key if search is successful, KErrNotFound
- * otherwise.
- */
-EXPORT_C TInt CCryptoTokenHai::KeyPresent( TInt aHandle )
- {
- int keysCount = iKeys.Count();
- for(TInt i=0; i < keysCount; ++i)
- {
- if(iKeys[i]->Handle() == aHandle)
- {
- return i;
- }
- }
- return KErrNotFound;
- }
-
-/**
- * Extracts the private key.
- *
- * @param aHandle Handle of the private key to be extracted.
- * @param aKey Output Parameter. Stores the private key on success.
- * Ownership of pointer is with the caller.
- *
- * @leave Following leave codes possible:-
- * - Any leave code returned by AllocL().
- * - KErrNotFound - If key corresponding to the given handle is not
- * found.
- *
- * @note In the actual implementation, licensees should ensure that
- * this function can be called only in Kernel space. In the reference
- * implementation, this function gets called only by CCryptoSpiHai,
- * which is assumed to operate in kernel space. This would ensure that
- * the private key always stays inside the hardware.
- */
-EXPORT_C void CCryptoTokenHai::ExportPrivateKeyL( TInt aHandle, HBufC8*& aKey )
- {
- int keysCount = iKeys.Count();
- for(int i = 0; i < keysCount; ++i)
- {
- if(iKeys[i]->Handle() == aHandle)
- {
- aKey = iKeys[i]->PrivateKey()->AllocL();
- return;
- }
- }
- User::Leave(KErrNotFound);
- }
-
-/**
- * Extracts the public key.
- *
- * @param aHandle Handle of the public key to be extracted.
- * @param aKey Output Parameter. Stores the public key on success.
- * Ownership of pointer is with the caller.
- *
- * @leave Following leave codes possible:-
- * - Any leave code returned by AllocL().
- * - KErrNotFound - If key corresponding to the given handle is not
- * found.
- */
-EXPORT_C void CCryptoTokenHai::ExportPublicKeyL( TInt aHandle, HBufC8*& aKey )
- {
- int keysCount = iKeys.Count();
- for(int i = 0; i < keysCount; ++i)
- {
- if(iKeys[i]->Handle() == aHandle)
- {
- aKey = iKeys[i]->PublicKey()->AllocL();
- return;
- }
- }
- User::Leave(KErrNotFound);
- }
-
-/**
- * Stores the key with given details.
- *
- * @param aLabel Label of the key.
- * @param aPrivateKey Private component of the key.
- * @param aPublicKey Public component of the key.
- *
- * @leave Following leave codes possible:-
- * - KErrAlreadyExists If there is already a key with the inputted
- * label.
- * - Any other leave code returned by NewL() or AppendL().
- *
- * @note In the present reference implementation this function is not
- * being used, since device keys are pre-provisioned by the licensees.
- * Hence licensees may decide not to implement this function in their
- * real implementation.
- */
-EXPORT_C void CCryptoTokenHai::ImportKeyL(const TDesC& aLabel,
- const TDesC8& aPrivateKey, const TDesC8& aPublicKey)
- {
- int keysCount = iKeys.Count();
- for(int i = 0; i < keysCount; ++i)
- {
- if(iKeys[i]->Label() == aLabel)
- {
- User::Leave(KErrAlreadyExists);
- }
- }
- CKeyDetails* keyDetails = CKeyDetails::NewL(keysCount+1,aLabel,aPrivateKey,aPublicKey);
- iKeys.AppendL(keyDetails);
- }
-
-/**
- * Populates the string containing full RAM path of file containing
- * keys.
- */
-void CCryptoTokenHai::MakePrivateFilenameL(RFs& aFs, const TDesC& aLeafName, TDes& aNameOut)
- {
- aNameOut.SetLength(0);
- aNameOut.Append(RFs::GetSystemDriveChar());
-
- aNameOut.Append(':');
-
- // Get private path
- TBuf<20> privatePath;
- User::LeaveIfError(aFs.PrivatePath(privatePath));
- aNameOut.Append(privatePath);
-
- aNameOut.Append(aLeafName);
- }
-
-/**
- * Creates the corresponding directory, if it does not exist.
- */
-void CCryptoTokenHai::EnsurePathL(RFs& aFs, const TDesC& aFile)
- {
- TInt err = aFs.MkDirAll(aFile);
- if (err != KErrNone && err != KErrAlreadyExists)
- {
- User::Leave(err);
- }
- }
-
-/**
- * Populates the string containing full ROM path of the keys file.
- */
-void CCryptoTokenHai::MakePrivateROMFilenameL(RFs& aFs, const TDesC& aLeafName, TDes& aNameOut)
- {
- _LIT(KFileStoreROMDrive, "Z:");
-
- aNameOut.Copy(KFileStoreROMDrive);
-
- // Get private path
- TBuf<20> privatePath;
- User::LeaveIfError(aFs.PrivatePath(privatePath));
- aNameOut.Append(privatePath);
- aNameOut.Append(aLeafName);
- }
-
-/**
- * Copies the contents of source file to destination file.
- *
- * This is typically used to copy the keys file from ROM to RAM.
- */
-void CCryptoTokenHai::CopyL(RFs& aFs, const TDesC& aSouce, const TDesC& aDest)
- {
- RFileReadStream in;
- User::LeaveIfError(in.Open(aFs, aSouce, EFileRead | EFileShareReadersOnly));
- CleanupClosePushL(in);
-
- RFileWriteStream out;
- User::LeaveIfError(out.Replace(aFs, aDest, EFileWrite | EFileShareExclusive));
- CleanupClosePushL(out);
-
- in.ReadL(out);
- CleanupStack::PopAndDestroy(2, &in);
- }
-
-/**
- * Keys corresponding to this store are present in hwkeys.dat.
- * In the production code written by licensees, this would be the path
- * where device keys are stored.
- */
-_LIT(KKeyStoreFilename,"hwkeys.dat");
-
-/**
- * Opens a store containing hardware keys.
- *
- * This function uses the following logic to open the store:-
- * -# Try to open the store from the private directory.
- * -# If this fails copy the file from ROM to RAM.
- * -# If both fail, create your own keys store from scratch.
- */
-void CCryptoTokenHai::OpenStoreL()
- {
- TFileName fullPath;
- MakePrivateFilenameL(iFs, KKeyStoreFilename, fullPath);
-
- EnsurePathL(iFs, fullPath);
- TRAPD(result, OpenStoreInFileL(fullPath));
-
- if (result == KErrInUse )
- {
- // Cannot access the file now. Abort 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.
- */
- TRAPD(result2, CopyStoreFromROML(fullPath, result));
-
- if (KErrNone != result2)
- {
- /*
- * 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);
- }
- }
-
- }
-
-/**
- * Copies the key store file from ROM to RAM.
- */
-void CCryptoTokenHai::CopyStoreFromROML(const TDesC& fullPath, TInt result)
- {
- if (result != KErrNotFound)
- {
- // Wipe the keystore if we can't open it (it's corrupt anyway)
- User::LeaveIfError(iFs.Delete(fullPath));
- }
-
- TFileName romPath;
- MakePrivateROMFilenameL(iFs, KKeyStoreFilename, romPath);
-
- // Copy data from rom and open it
- CopyL(iFs, romPath, fullPath);
- OpenStoreInFileL(fullPath);
- }
-
-/**
- * Opens a store from the given file.
- */
-void CCryptoTokenHai::OpenStoreInFileL(const TDesC& aFile)
- {
- RFile file;
- User::LeaveIfError(file.Open(iFs, aFile, EFileRead | EFileWrite | EFileShareAny));
- CleanupClosePushL(file);
- delete iFileStore;
- iFileStore = NULL;
-
- iFileStore = CPermanentFileStore::FromL(file);
- // iFileStore takes ownership of file now
- CleanupStack::Pop(&file);
-
- // Get the salt, root and manager TStreamIds
- iRootStreamId = iFileStore->Root();
- if (iRootStreamId == KNullStreamId)
- {
- User::Leave(KErrCorrupt);
- }
- RStoreReadStream rootStream;
- rootStream.OpenLC(*iFileStore, iRootStreamId);
- ReadKeysFromStoreL();
- CleanupStack::PopAndDestroy(&rootStream);
- }
-
-/**
- * Creates a keys store in RAM from scratch.
- *
- * @note This function should never get called as hwkeys.dat should be
- * always present in ROM. If this function somehow gets called, it
- * will create a hwkeys.dat file from scratch. However, this file would
- * not contain any keys and tests would not pass.
- */
-void CCryptoTokenHai::CreateStoreInFileL(const TDesC& aFile)
- {
- TInt r = iFs.MkDirAll(aFile);
- if ( (r!=KErrNone) && (r!=KErrAlreadyExists) )
- User::Leave(r);
-
- delete iFileStore;
- iFileStore = NULL;
- iFileStore = CPermanentFileStore::ReplaceL(iFs, aFile, EFileRead | EFileWrite | EFileShareExclusive);
- iFileStore->SetTypeL(KPermanentFileStoreLayoutUid);
-
- TCleanupItem cleanupStore(RevertStore, iFileStore);
- CleanupStack::PushL(cleanupStore);
-
- // Create root stream - just contains id of info stream
- RStoreWriteStream rootStream;
- iRootStreamId = rootStream.CreateLC(*iFileStore);
- iFileStore->SetRootL(iRootStreamId);
- WriteKeysToStoreL(rootStream);
- iFileStore->CommitL();
- CleanupStack::PopAndDestroy(&rootStream);
- CleanupStack::Pop(); // cleanupStore
- }
-
-/**
- * Copies the keys stored in the instance to inputted write stream.
- *
- * This invokes the CKeyDetails::ExternalizeL() function.
- */
-void CCryptoTokenHai::WriteKeysToStoreL(RStoreWriteStream& aRootStream)
- {
- TInt keyCount = iKeys.Count();
- aRootStream.WriteInt32L(keyCount);
-
- for (TInt index = 0; index < keyCount; index++)
- {
- aRootStream << *iKeys[index];
- }
- aRootStream.CommitL();
- }
-
-/**
- * Copies the keys present in the read store to instance of class.
- *
- * This eventually invokes the CKeyDetails::InternalizeL() function.
- */
-void CCryptoTokenHai::ReadKeysFromStoreL()
- {
- RStoreReadStream rootStream;
-
- rootStream.OpenLC(*iFileStore, iRootStreamId);
- TInt keyCount = rootStream.ReadInt32L();
-
- for (TInt index = 0; index < keyCount; index++)
- {
- CKeyDetails* keyDetails = CKeyDetails::NewL(rootStream);
- iKeys.Append(keyDetails);
- }
- CleanupStack::PopAndDestroy(&rootStream);
- }
-
-/**
- * This is a cleanup item that reverts the store.
- */
-void CCryptoTokenHai::RevertStore(TAny* aStore)
- {
- CPermanentFileStore* store = reinterpret_cast<CPermanentFileStore*>(aStore);
- TRAP_IGNORE(store->RevertL());
- }
-
-/**
- * Compacts the store.
- */
-void CCryptoTokenHai::CompactStore()
- {
- ASSERT(iFileStore);
- TRAP_IGNORE(iFileStore->ReclaimL(); iFileStore->CompactL());
- }
-
-/**
- * Populates the list of keys based on the input filter.
- *
- * @param aFilter Set of conditions to be used to decide which keys
- * should be listed
- * @param aKeys Output param. Contains the array of keys which fulfil
- * criteria mentioned in filter. Caller should take responsibility of
- * this array.
- *
- * @leave Any of the system wide error codes.
- *
- * @note Though Crypto Token HAI internally operates in CKeyDetails,
- * this function returns CCTKeyInfo array.
- */
-EXPORT_C void CCryptoTokenHai::ListL(const TCTKeyAttributeFilter& aFilter ,
- RPointerArray<CCTKeyInfo>& aKeys) const
- {
- TInt count = iKeys.Count();
- for(TInt index = 0 ;index < count; ++ index)
- {
- const CKeyDetails* keyDetails = iKeys[index];
-
- if(KeyMatchesFilterL(*keyDetails,aFilter))
- {
- MCTAuthenticationObject* authObject = NULL;
- HBufC8* attribute = keyDetails->PKCS8AttributeSet().AllocLC();
- HBufC* label = keyDetails->Label().AllocLC();
-
- CCTKeyInfo* keyInfo = CCTKeyInfo::NewL(
- keyDetails->ID(),keyDetails->Usage(),keyDetails->Size(),
- authObject,label,iToken,keyDetails->Handle(),keyDetails->UsePolicy(),
- keyDetails->ManagementPolicy(),keyDetails->Algorithm(),keyDetails->AccessType(),
- keyDetails->Native(),keyDetails->StartDate(),keyDetails->EndDate(),attribute);
-
- CleanupStack::Pop(2, attribute); // label
- CleanupReleasePushL(*keyInfo);
-
- User::LeaveIfError(aKeys.Append(keyInfo));
- CleanupStack::Pop(keyInfo);
-
- }
- }
-
- }
-
-/**
- * Takes in a filter and key details and decides if key fulfils the
- * filter criteria.
- *
- * @param aInfo The Key Details
- * @param aFilter Filter specifying the conditions to be satisfied for
- * listing the keys.
- *
- * @retval ETrue if key satisfies the conditions specified in filter
- * @retval EFalse otherwise.
- *
- * @leave KErrArgument If there is an issue in policy filter.
- */
-TBool CCryptoTokenHai::KeyMatchesFilterL(const CKeyDetails& aInfo,
- const TCTKeyAttributeFilter& aFilter) const
- {
-
- if (aFilter.iKeyId.Length() && aFilter.iKeyId != aInfo.ID())
- {
- return EFalse;
- }
-
- if (aFilter.iUsage != EPKCS15UsageAll)
- {
- if ((aInfo.Usage() & aFilter.iUsage) == 0)
- return EFalse;
- }
-
- if (aFilter.iKeyAlgorithm != CCTKeyInfo::EInvalidAlgorithm &&
- aFilter.iKeyAlgorithm != aInfo.Algorithm())
- {
- return EFalse;
- }
-
- switch (aFilter.iPolicyFilter)
- {
- case TCTKeyAttributeFilter::EAllKeys:
- // All keys pass
- break;
-
- case TCTKeyAttributeFilter::EUsableKeys:
- if (!aInfo.UsePolicy().CheckPolicy(RThread()))
- {
- return EFalse;
- }
- break;
- case TCTKeyAttributeFilter::EManageableKeys:
- // As this key store implementation is a hardware simulation,
- // the support for managing through software interface has been diabled.
- return EFalse;
-
- case TCTKeyAttributeFilter::EUsableOrManageableKeys:
- if (!aInfo.UsePolicy().CheckPolicy(RThread()) &&
- !aInfo.ManagementPolicy().CheckPolicy(RThread()))
- {
- return EFalse;
- }
- break;
-
- default:
- User::Leave(KErrArgument);
- }
-
- return ETrue;
- }
-
-
-