os/security/cryptoservices/filebasedcertificateandkeystores/test/keytool/keytool_migratestore.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/security/cryptoservices/filebasedcertificateandkeystores/test/keytool/keytool_migratestore.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,397 @@
1.4 +/*
1.5 +* Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
1.6 +* All rights reserved.
1.7 +* This component and the accompanying materials are made available
1.8 +* under the terms of the License "Eclipse Public License v1.0"
1.9 +* which accompanies this distribution, and is available
1.10 +* at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.11 +*
1.12 +* Initial Contributors:
1.13 +* Nokia Corporation - initial contribution.
1.14 +*
1.15 +* Contributors:
1.16 +*
1.17 +* Description:
1.18 +*
1.19 +*/
1.20 +
1.21 +
1.22 +#include <mctkeystore.h>
1.23 +#include <f32file.h>
1.24 +#include <s32mem.h>
1.25 +
1.26 +#include <authserver/authtypes.h>
1.27 +#include <centralrepository.h>
1.28 +#include <authserver/authclient.h>
1.29 +#include <authserver/authexpression.h>
1.30 +#include <authserver/auth_srv_errs.h>
1.31 +#include <authserver/aspubsubdefs.h>
1.32 +#include <authserver/authtypes.h>
1.33 +#include <pbedata.h>
1.34 +#include <mctkeystore.h>
1.35 +#include <keystore_errs.h>
1.36 +#include <securityerr.h>
1.37 +#include <keytool.rsg>
1.38 +
1.39 +#include "keystorecenrepconfig.h"
1.40 +#include "fsdatatypes.h"
1.41 +#include "ckeydatamanager.h"
1.42 +#include "keystorepassphrase.h"
1.43 +#include "keystreamutils.h"
1.44 +#include "asymmetrickeys.h"
1.45 +#include "keytool_migratestore.inl"
1.46 +
1.47 +#include "keytool_utils.h"
1.48 +#include "keytool_commands.h"
1.49 +#include "keytool_controller.h"
1.50 +
1.51 +
1.52 +/*static*/ CKeytoolMigrateStore* CKeytoolMigrateStore::NewLC(CKeyToolParameters* aParams)
1.53 + {
1.54 + CKeytoolMigrateStore* self = new (ELeave) CKeytoolMigrateStore();
1.55 + CleanupStack::PushL(self);
1.56 + self->ConstructL(aParams);
1.57 + return self;
1.58 + }
1.59 +
1.60 +/*static*/ CKeytoolMigrateStore* CKeytoolMigrateStore::NewL(CKeyToolParameters* aParams)
1.61 + {
1.62 + CKeytoolMigrateStore* self = CKeytoolMigrateStore::NewLC(aParams);
1.63 + CleanupStack::Pop(self);
1.64 + return self;
1.65 + }
1.66 +
1.67 +CKeytoolMigrateStore::CKeytoolMigrateStore()
1.68 +:CActive(EPriorityNormal)
1.69 + {
1.70 + CActiveScheduler::Add(this);
1.71 + }
1.72 +
1.73 +CKeytoolMigrateStore::~CKeytoolMigrateStore()
1.74 + {
1.75 + delete iWriteFileStore;
1.76 + delete iReadFileStore;
1.77 + delete iKeyStoreCenrep;
1.78 + delete iPassphrase;
1.79 + delete iUserIdentity;
1.80 + iKeyList.ResetAndDestroy();
1.81 + iFs.Close();
1.82 + iAuthClient.Close();
1.83 + }
1.84 +
1.85 +void CKeytoolMigrateStore::ConstructL(CKeyToolParameters* aParams)
1.86 + {
1.87 + iParams = aParams;
1.88 +
1.89 + // retrieve the value of authexpression and freshness from the cenrep
1.90 + // file if not supplied in the command line.
1.91 + iKeyStoreCenrep = CKeyStoreCenrep::NewL();
1.92 + if(iParams->iAuthExpression == NULL)
1.93 + {
1.94 + iParams->iAuthExpression = HBufC::NewL(1024);
1.95 + TPtr exprPtr = iParams->iAuthExpression->Des();
1.96 + iKeyStoreCenrep->AuthExpressionL( exprPtr );
1.97 + }
1.98 + if(iParams->iFreshness == -1)
1.99 + {
1.100 + iParams->iFreshness = iKeyStoreCenrep->FreshnessL();
1.101 + }
1.102 +
1.103 + User::LeaveIfError(iFs.Connect());
1.104 +
1.105 + // open the file store to be created with the latest details.
1.106 + iWriteFileStore = CPermanentFileStore::ReplaceL(iFs, *iParams->iNewKeyFile, EFileRead | EFileWrite | EFileShareExclusive);
1.107 + iWriteFileStore->SetTypeL(KPermanentFileStoreLayoutUid);
1.108 +
1.109 + RStoreWriteStream writeLookupStream;
1.110 + iWriteLookupStreamId = writeLookupStream.CreateLC(*iWriteFileStore);
1.111 + writeLookupStream.WriteUint32L(0); // Write key count of zero
1.112 + writeLookupStream.CommitL();
1.113 + CleanupStack::PopAndDestroy(&writeLookupStream);
1.114 +
1.115 + // Create root stream - just contains id of info stream
1.116 + RStoreWriteStream writeRootStream;
1.117 + TStreamId writeRootStreamId = writeRootStream.CreateLC(*iWriteFileStore);
1.118 + iWriteFileStore->SetRootL(writeRootStreamId);
1.119 +
1.120 + writeRootStream.WriteUint32L(iWriteLookupStreamId.Value());
1.121 + writeRootStream.CommitL();
1.122 + CleanupStack::PopAndDestroy(&writeRootStream);
1.123 +
1.124 + // open the already existing key file.
1.125 + // Make sure the file isn't write protected
1.126 + User::LeaveIfError(iFs.SetAtt(*iParams->iOldKeyFile, 0, KEntryAttReadOnly));
1.127 +
1.128 + RFile readFile;
1.129 + CleanupClosePushL(readFile);
1.130 + User::LeaveIfError(readFile.Open(iFs, *iParams->iOldKeyFile, EFileRead | EFileWrite | EFileShareExclusive));
1.131 + iReadFileStore = CPermanentFileStore::FromL(readFile);
1.132 + CleanupStack::PopAndDestroy(&readFile);
1.133 +
1.134 + TStreamId readRootStreamId = iReadFileStore->Root();
1.135 + if (readRootStreamId == KNullStreamId)
1.136 + {
1.137 + User::Leave(KErrCorrupt);
1.138 + }
1.139 +
1.140 + RStoreReadStream readRootStream;
1.141 + readRootStream.OpenLC(*iReadFileStore, readRootStreamId);
1.142 + TStreamId readLookupStreamId = (TStreamId)(readRootStream.ReadUint32L());
1.143 + CleanupStack::PopAndDestroy(&readRootStream);
1.144 +
1.145 + RStoreReadStream readLookupStream;
1.146 + readLookupStream.OpenLC(*iReadFileStore, readLookupStreamId);
1.147 +
1.148 + // ignore passStreamId and timeoutStreamId for migration
1.149 + TStreamId passStreamId = readLookupStream.ReadUint32L();
1.150 + TStreamId timeoutStreamId = readLookupStream.ReadUint32L();
1.151 +
1.152 + TInt keyCount = readLookupStream.ReadInt32L();
1.153 +
1.154 + // read the keys that are stored in this store
1.155 + for (TInt index = 0; index < keyCount; index++)
1.156 + {
1.157 + const CFileKeyData* keyData = CFileKeyData::CreateOldKeyL(readLookupStream);
1.158 + iKeyList.Append(keyData);
1.159 + }
1.160 +
1.161 + CleanupStack::PopAndDestroy(&readLookupStream);
1.162 +
1.163 + RStoreReadStream timeoutStream;
1.164 + timeoutStream.OpenLC(*iReadFileStore, timeoutStreamId);
1.165 + TInt timeout = timeoutStream.ReadInt32L();
1.166 + CleanupStack::PopAndDestroy(&timeoutStream);
1.167 +
1.168 + iPassphrase = CPassphrase::NewL( timeout, *iReadFileStore,
1.169 + passStreamId, *iParams->iPassphrase);
1.170 +
1.171 + User::LeaveIfError(iAuthClient.Connect());
1.172 +
1.173 + }
1.174 +
1.175 +void CKeytoolMigrateStore::DoCommandL()
1.176 + {
1.177 + if(iParams->iOldKeyFile == NULL ||
1.178 + iParams->iPassphrase == NULL )
1.179 + {
1.180 + User::Leave(CKeyToolParameters::EMandatoryArgumentMissing);
1.181 + }
1.182 +
1.183 + TUid uid = TUid::Uid(0);
1.184 + AuthServer::CAuthExpression* expression = iAuthClient.CreateAuthExpressionL(*(iParams->iAuthExpression));
1.185 + CleanupStack::PushL(expression);
1.186 + iState = EAfterAuthentication;
1.187 + SetActive();
1.188 + iAuthClient.AuthenticateL(*expression,iParams->iFreshness, EFalse, uid, EFalse, KNullDesC, iUserIdentity, iStatus);
1.189 +
1.190 + CleanupStack::PopAndDestroy(expression);
1.191 +
1.192 + }
1.193 +
1.194 +void CKeytoolMigrateStore::CleanKeyInfo(TAny* aKeyInfo)
1.195 + {
1.196 + delete reinterpret_cast<CKeyInfo*>(aKeyInfo);
1.197 + }
1.198 +
1.199 +void CKeytoolMigrateStore::WriteKeyInformationL()
1.200 + {
1.201 +
1.202 + TInt keysCount = iKeyList.Count();
1.203 +
1.204 + for (TInt index = 0; index < keysCount; index++)
1.205 + {
1.206 + CFileKeyData* keyData = iKeyList[index];
1.207 +
1.208 + // Write the key information
1.209 + RStoreReadStream keyInfoStream;
1.210 + keyInfoStream.OpenLC(*iReadFileStore, keyData->InfoDataStreamId());
1.211 + CKeyInfo* keyInfo = CKeyInfo::NewL(keyInfoStream);
1.212 + TCleanupItem cleanupKeyInfo(CleanKeyInfo, keyInfo);
1.213 + CKeyInfoBase::EKeyAlgorithm algo = keyInfo->Algorithm();
1.214 + CleanupStack::PopAndDestroy(&keyInfoStream);
1.215 + CleanupStack::PushL(cleanupKeyInfo);
1.216 +
1.217 + switch(algo)
1.218 + {
1.219 + case (CKeyInfo::ERSA):
1.220 + {
1.221 + // retrieve the public key and write it in the new stream
1.222 + CRSAPublicKey* publicKey = NULL;
1.223 + RetrieveAndStorePublicKeyL(keyData, publicKey);
1.224 +
1.225 + // retrieve the private key, encrypt it with the protection key and store
1.226 + // it in the new key stream.
1.227 + CRSAPrivateKey* privateKey = NULL;
1.228 + RetrieveAndStorePrivateKeyL(keyData, privateKey);
1.229 + break;
1.230 + }
1.231 + case (CKeyInfo::EDSA):
1.232 + {
1.233 + // retrieve the public key and write it in the new stream
1.234 + CDSAPublicKey* publicKey = NULL;
1.235 + RetrieveAndStorePublicKeyL(keyData, publicKey);
1.236 +
1.237 + // retrieve the private key, encrypt it with the protection key and store
1.238 + // it in the new key stream.
1.239 + CDSAPrivateKey* privateKey = NULL;
1.240 + RetrieveAndStorePrivateKeyL(keyData, privateKey);
1.241 + break;
1.242 + }
1.243 + case (CKeyInfo::EDH):
1.244 + {
1.245 + // write the public stream id
1.246 + RStoreWriteStream writePublicStream;
1.247 + TStreamId publicStrId = writePublicStream.CreateLC(*iWriteFileStore);
1.248 + keyData->SetPublicDataStreamId(publicStrId);
1.249 + writePublicStream.CommitL();
1.250 + CleanupStack::PopAndDestroy(&writePublicStream);
1.251 + // open the privatekeystream based on the supplied passphrase
1.252 + RStoreReadStream privateStream;
1.253 + privateStream.OpenLC(iPassphrase->Store(), keyData->PrivateDataStreamId());
1.254 +
1.255 + RInteger dhKey;
1.256 + CreateLC(privateStream, dhKey);
1.257 + RStoreWriteStream writePvtStr;
1.258 + TStreamId pvtStrId = writePvtStr.CreateLC(*iWriteFileStore);
1.259 + keyData->SetPrivateDataStreamId(pvtStrId);
1.260 +
1.261 + if (KNullStreamId == pvtStrId)
1.262 + {
1.263 + User::Leave(KErrBadHandle);
1.264 + }
1.265 + EncryptAndStoreL(dhKey, writePvtStr );
1.266 + writePvtStr.CommitL();
1.267 + CleanupStack::PopAndDestroy(3, &privateStream); // dhKey, writePvtStr
1.268 +
1.269 + break;
1.270 +
1.271 + }
1.272 + default:
1.273 + User::Leave(KErrKeyAlgorithm);
1.274 + }
1.275 +
1.276 + // write the info stream for the key
1.277 + RStoreWriteStream writeInfoStream;
1.278 + TStreamId infoStrId = writeInfoStream.CreateLC(*iWriteFileStore);
1.279 + keyData->SetInfoDataStreamId(infoStrId);
1.280 + WriteKeyL(*keyInfo, writeInfoStream );
1.281 + CleanupStack::PopAndDestroy( &writeInfoStream);
1.282 + CleanupStack::PopAndDestroy(); // cleanupKeyInfo
1.283 +
1.284 + }
1.285 +
1.286 + RStoreWriteStream writeLookupStream;
1.287 + writeLookupStream.ReplaceLC(*iWriteFileStore, iWriteLookupStreamId );
1.288 +
1.289 + // write the count of keys
1.290 + writeLookupStream.WriteInt32L(keysCount);
1.291 +
1.292 + for(TInt index=0;index<keysCount;++index)
1.293 + {
1.294 + CFileKeyData* keyData = iKeyList[index];
1.295 + // write the key using the lookupstream
1.296 + keyData->ExternalizeWithAuthL(writeLookupStream);
1.297 + }
1.298 +
1.299 + writeLookupStream.CommitL();
1.300 + CleanupStack::PopAndDestroy(&writeLookupStream);
1.301 +
1.302 + iWriteFileStore->CommitL();
1.303 + iReadFileStore->CommitL();
1.304 +
1.305 + }
1.306 +
1.307 +void CKeytoolMigrateStore::WriteKeyL( const CKeyInfo& aKeyInfo,
1.308 + RStoreWriteStream& aWriteInfoStream )
1.309 + {
1.310 + aWriteInfoStream << aKeyInfo;
1.311 + WriteAuthDetailsL(aWriteInfoStream);
1.312 + aWriteInfoStream.CommitL();
1.313 + }
1.314 +
1.315 +void CKeytoolMigrateStore::WriteAuthDetailsL( RStoreWriteStream& aWriteInfoStream )
1.316 + {
1.317 + aWriteInfoStream.WriteInt32L(iUserIdentity->Id());
1.318 + aWriteInfoStream << *(iParams->iAuthExpression);
1.319 + aWriteInfoStream.WriteInt32L(iParams->iFreshness);
1.320 + }
1.321 +
1.322 +// This is a cleanup item that reverts the store
1.323 +void CKeytoolMigrateStore::RevertStore(TAny* aStore)
1.324 + {
1.325 + CPermanentFileStore* store = reinterpret_cast<CPermanentFileStore*>(aStore);
1.326 + TRAP_IGNORE(store->RevertL());
1.327 + // We're ignoring the leave code from this because there's no way we can
1.328 + // handle this sensibly. This shouldn't be a problem in practice - this
1.329 + // will leave if for example the file store is on removable which is
1.330 + // unexpectedly remove, and this is never the case for us.
1.331 + }
1.332 +
1.333 +void CKeytoolMigrateStore::RunL()
1.334 + {
1.335 + User::LeaveIfError(iStatus.Int());
1.336 +
1.337 + switch(iState)
1.338 + {
1.339 + case EAfterAuthentication:
1.340 + {
1.341 + if(iUserIdentity == AuthServer::KUnknownIdentity)
1.342 + {
1.343 + User::Leave(KErrAuthenticationFailure);
1.344 + }
1.345 + WriteKeyInformationL();
1.346 + // once keyinformation has been written
1.347 + // delete the user identity
1.348 + delete iUserIdentity;
1.349 + iUserIdentity = NULL;
1.350 +
1.351 + CActiveScheduler::Stop();
1.352 + break;
1.353 + }
1.354 + default:
1.355 + User::Leave(KErrNotSupported);
1.356 + }
1.357 + }
1.358 +
1.359 +void CKeytoolMigrateStore::DoCancel()
1.360 + {
1.361 +
1.362 + }
1.363 +
1.364 +TInt CKeytoolMigrateStore::RunError(TInt aError)
1.365 + {
1.366 + if(aError != KErrNone)
1.367 + {
1.368 + aError = KErrNone;
1.369 + }
1.370 + CActiveScheduler::Stop();
1.371 + return KErrNone;
1.372 + }
1.373 +
1.374 +void CKeytoolMigrateStore::StoreKeyL(const TDesC8& aKeyData, RStoreWriteStream& aStream)
1.375 + {
1.376 + // retrieve the protection key of the current authenticated user for encrypting the
1.377 + // user's private key.
1.378 + TPtrC8 key = iUserIdentity->Key().KeyData();
1.379 + // used for pbe, the class can be used for encryption/decryption based on the
1.380 + // password supplied.
1.381 + CPBEncryptElement* pbeEncrypt = CPBEncryptElement::NewL(key);
1.382 + CleanupStack::PushL(pbeEncrypt);
1.383 + // create an object for ecryption
1.384 + CPBEncryptor* encryptor = pbeEncrypt->NewEncryptLC();
1.385 + // cerate the buffer size required for storing the encrypted data.
1.386 + HBufC8* ciphertext = HBufC8::NewLC(encryptor->MaxFinalOutputLength(aKeyData.Length()));
1.387 + TPtr8 ciphertextTemp = ciphertext->Des();
1.388 + // data gets encrypted and stored in the buffer
1.389 + encryptor->ProcessFinalL(aKeyData, ciphertextTemp);
1.390 + // externalixe the encryption parameters, this information is required later
1.391 + // for decrypting the text later.
1.392 + pbeEncrypt->EncryptionData().ExternalizeL(aStream);
1.393 + // write out the cipher data length
1.394 + aStream.WriteInt32L(ciphertext->Length());
1.395 + // write the cipher data to the stream.
1.396 + aStream.WriteL(*ciphertext);
1.397 +
1.398 + CleanupStack::PopAndDestroy(3, pbeEncrypt); // ciphertext,encryptor
1.399 + }
1.400 +