os/security/cryptoservices/filebasedcertificateandkeystores/test/keytool/keytool_migratestore.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 /*
     2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
     3 * All rights reserved.
     4 * This component and the accompanying materials are made available
     5 * under the terms of the License "Eclipse Public License v1.0"
     6 * which accompanies this distribution, and is available
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
     8 *
     9 * Initial Contributors:
    10 * Nokia Corporation - initial contribution.
    11 *
    12 * Contributors:
    13 *
    14 * Description: 
    15 *
    16 */
    17 
    18 
    19 #include <mctkeystore.h>
    20 #include <f32file.h>
    21 #include <s32mem.h>
    22 
    23 #include <authserver/authtypes.h>
    24 #include <centralrepository.h>
    25 #include <authserver/authclient.h>
    26 #include <authserver/authexpression.h>
    27 #include <authserver/auth_srv_errs.h>
    28 #include <authserver/aspubsubdefs.h>
    29 #include <authserver/authtypes.h>
    30 #include <pbedata.h>
    31 #include <mctkeystore.h>
    32 #include <keystore_errs.h>
    33 #include <securityerr.h>
    34 #include <keytool.rsg>
    35 
    36 #include "keystorecenrepconfig.h"
    37 #include "fsdatatypes.h"
    38 #include "ckeydatamanager.h"
    39 #include "keystorepassphrase.h"
    40 #include "keystreamutils.h"
    41 #include "asymmetrickeys.h"
    42 #include "keytool_migratestore.inl"
    43 
    44 #include "keytool_utils.h"
    45 #include "keytool_commands.h"
    46 #include "keytool_controller.h"
    47 
    48 
    49 /*static*/ CKeytoolMigrateStore* CKeytoolMigrateStore::NewLC(CKeyToolParameters* aParams)
    50 	{
    51 	CKeytoolMigrateStore* self = new (ELeave) CKeytoolMigrateStore();
    52 	CleanupStack::PushL(self);
    53 	self->ConstructL(aParams);
    54 	return self;
    55 	}
    56 	
    57 /*static*/ CKeytoolMigrateStore* CKeytoolMigrateStore::NewL(CKeyToolParameters* aParams)
    58 	{
    59 	CKeytoolMigrateStore* self = CKeytoolMigrateStore::NewLC(aParams);
    60 	CleanupStack::Pop(self);
    61 	return self;
    62 	}
    63 
    64 CKeytoolMigrateStore::CKeytoolMigrateStore()
    65 :CActive(EPriorityNormal)
    66 	{
    67 	CActiveScheduler::Add(this);
    68 	}
    69 	
    70 CKeytoolMigrateStore::~CKeytoolMigrateStore()
    71 	{	
    72 	delete iWriteFileStore;
    73 	delete iReadFileStore;
    74 	delete iKeyStoreCenrep;
    75 	delete iPassphrase;
    76 	delete iUserIdentity;
    77 	iKeyList.ResetAndDestroy();
    78 	iFs.Close();
    79 	iAuthClient.Close();
    80 	}
    81 
    82 void CKeytoolMigrateStore::ConstructL(CKeyToolParameters* aParams)
    83 	{
    84 	iParams = aParams;
    85 	
    86 	// retrieve the value of authexpression and freshness from the cenrep 
    87 	// file if not supplied in the command line.
    88 	iKeyStoreCenrep = CKeyStoreCenrep::NewL();
    89 	if(iParams->iAuthExpression == NULL)
    90 		{
    91 		iParams->iAuthExpression = HBufC::NewL(1024);
    92 		TPtr exprPtr = iParams->iAuthExpression->Des();
    93 		iKeyStoreCenrep->AuthExpressionL( exprPtr );
    94 		}
    95 	if(iParams->iFreshness == -1)
    96 		{
    97 		iParams->iFreshness = iKeyStoreCenrep->FreshnessL();
    98 		}
    99 	
   100 	User::LeaveIfError(iFs.Connect());
   101 	
   102 	// open the file store to be created with the latest details.
   103 	iWriteFileStore = CPermanentFileStore::ReplaceL(iFs, *iParams->iNewKeyFile, EFileRead | EFileWrite | EFileShareExclusive);
   104 	iWriteFileStore->SetTypeL(KPermanentFileStoreLayoutUid);
   105 
   106 	RStoreWriteStream writeLookupStream;
   107 	iWriteLookupStreamId = writeLookupStream.CreateLC(*iWriteFileStore);
   108 	writeLookupStream.WriteUint32L(0); // Write key count of zero
   109 	writeLookupStream.CommitL();
   110 	CleanupStack::PopAndDestroy(&writeLookupStream);
   111 	
   112 	// Create root stream - just contains id of info stream
   113 	RStoreWriteStream writeRootStream;
   114 	TStreamId writeRootStreamId = writeRootStream.CreateLC(*iWriteFileStore);
   115 	iWriteFileStore->SetRootL(writeRootStreamId);
   116 		
   117 	writeRootStream.WriteUint32L(iWriteLookupStreamId.Value());		
   118 	writeRootStream.CommitL();
   119 	CleanupStack::PopAndDestroy(&writeRootStream);
   120 	
   121 	// open the already existing key file.
   122 	// Make sure the file isn't write protected
   123 	User::LeaveIfError(iFs.SetAtt(*iParams->iOldKeyFile, 0, KEntryAttReadOnly));
   124 	
   125 	RFile readFile;
   126 	CleanupClosePushL(readFile);
   127 	User::LeaveIfError(readFile.Open(iFs, *iParams->iOldKeyFile, EFileRead | EFileWrite | EFileShareExclusive));
   128 	iReadFileStore = CPermanentFileStore::FromL(readFile);		
   129 	CleanupStack::PopAndDestroy(&readFile);
   130 	
   131 	TStreamId readRootStreamId = iReadFileStore->Root();
   132 	if (readRootStreamId == KNullStreamId)
   133 		{
   134 		User::Leave(KErrCorrupt);
   135 		}
   136 	
   137 	RStoreReadStream readRootStream;
   138 	readRootStream.OpenLC(*iReadFileStore, readRootStreamId);
   139 	TStreamId readLookupStreamId = (TStreamId)(readRootStream.ReadUint32L());
   140 	CleanupStack::PopAndDestroy(&readRootStream);
   141 	
   142 	RStoreReadStream readLookupStream;
   143 	readLookupStream.OpenLC(*iReadFileStore, readLookupStreamId);
   144 	
   145 	// ignore passStreamId and timeoutStreamId for migration
   146 	TStreamId passStreamId = readLookupStream.ReadUint32L();
   147 	TStreamId timeoutStreamId = readLookupStream.ReadUint32L();
   148 	
   149 	TInt keyCount = readLookupStream.ReadInt32L();
   150 	
   151 	// read the keys that are stored in this store
   152 	for (TInt index = 0; index < keyCount; index++)
   153 		{
   154 		const CFileKeyData* keyData = CFileKeyData::CreateOldKeyL(readLookupStream);
   155 		iKeyList.Append(keyData);
   156 		}
   157 		
   158 	CleanupStack::PopAndDestroy(&readLookupStream);
   159 	
   160 	RStoreReadStream timeoutStream;
   161 	timeoutStream.OpenLC(*iReadFileStore, timeoutStreamId);
   162 	TInt timeout = timeoutStream.ReadInt32L();
   163 	CleanupStack::PopAndDestroy(&timeoutStream);
   164 	
   165 	iPassphrase = CPassphrase::NewL( timeout, *iReadFileStore, 
   166 									  passStreamId, *iParams->iPassphrase);
   167 	
   168 	User::LeaveIfError(iAuthClient.Connect());
   169 	
   170 	}
   171 	
   172 void CKeytoolMigrateStore::DoCommandL()
   173 	{	
   174 	if(iParams->iOldKeyFile == NULL ||
   175 		iParams->iPassphrase == NULL )
   176 		{
   177 		User::Leave(CKeyToolParameters::EMandatoryArgumentMissing);
   178 		}
   179 			
   180 	TUid uid = TUid::Uid(0);
   181 	AuthServer::CAuthExpression* expression = iAuthClient.CreateAuthExpressionL(*(iParams->iAuthExpression));
   182 	CleanupStack::PushL(expression);
   183 	iState = EAfterAuthentication;
   184 	SetActive();
   185 	iAuthClient.AuthenticateL(*expression,iParams->iFreshness, EFalse, uid, EFalse, KNullDesC, iUserIdentity, iStatus);
   186 	
   187 	CleanupStack::PopAndDestroy(expression); 
   188 		
   189 	}
   190 
   191 void CKeytoolMigrateStore::CleanKeyInfo(TAny* aKeyInfo)
   192 	{
   193 	delete reinterpret_cast<CKeyInfo*>(aKeyInfo);
   194 	}
   195 
   196 void CKeytoolMigrateStore::WriteKeyInformationL()
   197 	{
   198 	
   199 	TInt keysCount = iKeyList.Count();
   200 	
   201 	for (TInt index = 0; index < keysCount; index++)
   202 		{
   203 		CFileKeyData* keyData = iKeyList[index];
   204 				
   205 		// Write the key information 
   206 		RStoreReadStream keyInfoStream;
   207 		keyInfoStream.OpenLC(*iReadFileStore, keyData->InfoDataStreamId());
   208 		CKeyInfo* keyInfo = CKeyInfo::NewL(keyInfoStream);
   209 		TCleanupItem cleanupKeyInfo(CleanKeyInfo, keyInfo);
   210 		CKeyInfoBase::EKeyAlgorithm algo = keyInfo->Algorithm();
   211 		CleanupStack::PopAndDestroy(&keyInfoStream);
   212 		CleanupStack::PushL(cleanupKeyInfo);
   213 		
   214 		switch(algo)
   215 			{
   216 			case (CKeyInfo::ERSA):
   217 				{
   218 				// retrieve the public key and write it in the new stream
   219 				CRSAPublicKey* publicKey = NULL;
   220 				RetrieveAndStorePublicKeyL(keyData, publicKey);
   221 				
   222 				// retrieve the private key, encrypt it with the protection key and store 
   223 				// it in the new key stream. 
   224 				CRSAPrivateKey* privateKey = NULL;
   225 				RetrieveAndStorePrivateKeyL(keyData, privateKey);
   226 				break;
   227 				}
   228 			case (CKeyInfo::EDSA):
   229 				{
   230 				// retrieve the public key and write it in the new stream
   231 				CDSAPublicKey* publicKey = NULL;
   232 				RetrieveAndStorePublicKeyL(keyData, publicKey);
   233 				
   234 				// retrieve the private key, encrypt it with the protection key and store 
   235 				// it in the new key stream. 
   236 				CDSAPrivateKey* privateKey = NULL;
   237 				RetrieveAndStorePrivateKeyL(keyData, privateKey);
   238 				break;
   239 				}
   240 			case (CKeyInfo::EDH):
   241 				{
   242 				// write the public stream id 
   243 				RStoreWriteStream writePublicStream;
   244 				TStreamId publicStrId = writePublicStream.CreateLC(*iWriteFileStore);
   245 				keyData->SetPublicDataStreamId(publicStrId);
   246 				writePublicStream.CommitL();
   247 				CleanupStack::PopAndDestroy(&writePublicStream);
   248 				// open the privatekeystream based on the supplied passphrase
   249 				RStoreReadStream privateStream;
   250 				privateStream.OpenLC(iPassphrase->Store(), keyData->PrivateDataStreamId());
   251 								
   252 				RInteger dhKey;
   253 				CreateLC(privateStream, dhKey);
   254 				RStoreWriteStream writePvtStr;
   255 				TStreamId pvtStrId = writePvtStr.CreateLC(*iWriteFileStore);
   256 				keyData->SetPrivateDataStreamId(pvtStrId);
   257 				
   258 				if (KNullStreamId == pvtStrId)
   259 					{
   260 					User::Leave(KErrBadHandle);
   261 					}
   262 				EncryptAndStoreL(dhKey, writePvtStr );
   263 				writePvtStr.CommitL();
   264 				CleanupStack::PopAndDestroy(3, &privateStream); // dhKey, writePvtStr
   265 				
   266 				break;
   267 				
   268 				}
   269 			default:
   270 				User::Leave(KErrKeyAlgorithm);
   271 			}
   272 		
   273 		// write the info stream for the key
   274 		RStoreWriteStream writeInfoStream;
   275 		TStreamId infoStrId = writeInfoStream.CreateLC(*iWriteFileStore);
   276 		keyData->SetInfoDataStreamId(infoStrId);
   277 		WriteKeyL(*keyInfo, writeInfoStream );
   278 		CleanupStack::PopAndDestroy( &writeInfoStream);
   279 		CleanupStack::PopAndDestroy(); // cleanupKeyInfo	
   280 		
   281 		}
   282 		
   283 	RStoreWriteStream writeLookupStream;
   284 	writeLookupStream.ReplaceLC(*iWriteFileStore, iWriteLookupStreamId );
   285 	
   286 	// write the count of keys 
   287 	writeLookupStream.WriteInt32L(keysCount);
   288 		
   289 	for(TInt index=0;index<keysCount;++index)
   290 		{
   291 		CFileKeyData* keyData = iKeyList[index];
   292 		// write the key using the lookupstream
   293 		keyData->ExternalizeWithAuthL(writeLookupStream);
   294 		}
   295 	
   296 	writeLookupStream.CommitL();
   297 	CleanupStack::PopAndDestroy(&writeLookupStream);
   298 	
   299 	iWriteFileStore->CommitL();
   300 	iReadFileStore->CommitL();
   301 	
   302 	}
   303 
   304 void CKeytoolMigrateStore::WriteKeyL(	const CKeyInfo& aKeyInfo, 
   305 										RStoreWriteStream& aWriteInfoStream )
   306 	{
   307 	aWriteInfoStream << aKeyInfo;
   308 	WriteAuthDetailsL(aWriteInfoStream);
   309 	aWriteInfoStream.CommitL();
   310 	}
   311 
   312 void CKeytoolMigrateStore::WriteAuthDetailsL( 	RStoreWriteStream& aWriteInfoStream	)
   313 	{
   314 	aWriteInfoStream.WriteInt32L(iUserIdentity->Id());
   315 	aWriteInfoStream << *(iParams->iAuthExpression);
   316 	aWriteInfoStream.WriteInt32L(iParams->iFreshness);
   317 	}
   318 
   319 // This is a cleanup item that reverts the store
   320 void CKeytoolMigrateStore::RevertStore(TAny* aStore)
   321 	{
   322 	CPermanentFileStore* store = reinterpret_cast<CPermanentFileStore*>(aStore);
   323 	TRAP_IGNORE(store->RevertL());
   324 	// We're ignoring the leave code from this because there's no way we can
   325 	// handle this sensibly.  This shouldn't be a problem in practice - this
   326 	// will leave if for example the file store is on removable which is
   327 	// unexpectedly remove, and this is never the case for us.
   328 	}
   329 
   330 void CKeytoolMigrateStore::RunL()
   331 	{
   332 	User::LeaveIfError(iStatus.Int());
   333 	
   334 	switch(iState)
   335 		{
   336 		case EAfterAuthentication:
   337 			{
   338 			if(iUserIdentity == AuthServer::KUnknownIdentity)
   339 				{
   340 				User::Leave(KErrAuthenticationFailure);
   341 				}
   342 			WriteKeyInformationL();
   343 			// once keyinformation has been written 
   344 			// delete the user identity
   345 			delete iUserIdentity;
   346 			iUserIdentity = NULL;
   347 			
   348 			CActiveScheduler::Stop();
   349 			break;
   350 			}
   351 		default:
   352 			User::Leave(KErrNotSupported);
   353 		}
   354 	}
   355 
   356 void CKeytoolMigrateStore::DoCancel()
   357 	{
   358 	
   359 	}
   360 
   361 TInt CKeytoolMigrateStore::RunError(TInt aError)
   362 	{
   363 	if(aError != KErrNone)
   364 		{
   365 		aError = KErrNone;
   366 		}
   367 	CActiveScheduler::Stop();
   368 	return KErrNone;
   369 	}
   370 
   371 void CKeytoolMigrateStore::StoreKeyL(const TDesC8& aKeyData, RStoreWriteStream& aStream)
   372 	{
   373 	// retrieve the protection key of the current authenticated user for encrypting the 
   374 	// user's private key.
   375 	TPtrC8 key = iUserIdentity->Key().KeyData();
   376 	// used for pbe, the class can be used for encryption/decryption based on the 
   377 	// password supplied.
   378 	CPBEncryptElement* pbeEncrypt = CPBEncryptElement::NewL(key);
   379 	CleanupStack::PushL(pbeEncrypt);
   380 	// create an object for ecryption
   381 	CPBEncryptor* encryptor = pbeEncrypt->NewEncryptLC();
   382 	// cerate the buffer size required for storing the encrypted data.
   383 	HBufC8* ciphertext = HBufC8::NewLC(encryptor->MaxFinalOutputLength(aKeyData.Length()));
   384 	TPtr8 ciphertextTemp = ciphertext->Des();
   385 	// data gets encrypted and stored in the buffer
   386 	encryptor->ProcessFinalL(aKeyData, ciphertextTemp);
   387 	// externalixe the encryption parameters, this information is required later
   388 	// for decrypting the text later.
   389 	pbeEncrypt->EncryptionData().ExternalizeL(aStream);
   390 	// write out the cipher data length
   391 	aStream.WriteInt32L(ciphertext->Length());
   392 	// write the cipher data to the stream.
   393 	aStream.WriteL(*ciphertext);
   394 		
   395 	CleanupStack::PopAndDestroy(3, pbeEncrypt); // ciphertext,encryptor
   396 	}
   397