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