os/security/cryptoservices/filebasedcertificateandkeystores/test/keytool/keytool_migratestore.cpp
First public contribution.
2 * Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies).
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".
9 * Initial Contributors:
10 * Nokia Corporation - initial contribution.
19 #include <mctkeystore.h>
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>
31 #include <mctkeystore.h>
32 #include <keystore_errs.h>
33 #include <securityerr.h>
34 #include <keytool.rsg>
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"
44 #include "keytool_utils.h"
45 #include "keytool_commands.h"
46 #include "keytool_controller.h"
49 /*static*/ CKeytoolMigrateStore* CKeytoolMigrateStore::NewLC(CKeyToolParameters* aParams)
51 CKeytoolMigrateStore* self = new (ELeave) CKeytoolMigrateStore();
52 CleanupStack::PushL(self);
53 self->ConstructL(aParams);
57 /*static*/ CKeytoolMigrateStore* CKeytoolMigrateStore::NewL(CKeyToolParameters* aParams)
59 CKeytoolMigrateStore* self = CKeytoolMigrateStore::NewLC(aParams);
60 CleanupStack::Pop(self);
64 CKeytoolMigrateStore::CKeytoolMigrateStore()
65 :CActive(EPriorityNormal)
67 CActiveScheduler::Add(this);
70 CKeytoolMigrateStore::~CKeytoolMigrateStore()
72 delete iWriteFileStore;
73 delete iReadFileStore;
74 delete iKeyStoreCenrep;
77 iKeyList.ResetAndDestroy();
82 void CKeytoolMigrateStore::ConstructL(CKeyToolParameters* aParams)
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)
91 iParams->iAuthExpression = HBufC::NewL(1024);
92 TPtr exprPtr = iParams->iAuthExpression->Des();
93 iKeyStoreCenrep->AuthExpressionL( exprPtr );
95 if(iParams->iFreshness == -1)
97 iParams->iFreshness = iKeyStoreCenrep->FreshnessL();
100 User::LeaveIfError(iFs.Connect());
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);
106 RStoreWriteStream writeLookupStream;
107 iWriteLookupStreamId = writeLookupStream.CreateLC(*iWriteFileStore);
108 writeLookupStream.WriteUint32L(0); // Write key count of zero
109 writeLookupStream.CommitL();
110 CleanupStack::PopAndDestroy(&writeLookupStream);
112 // Create root stream - just contains id of info stream
113 RStoreWriteStream writeRootStream;
114 TStreamId writeRootStreamId = writeRootStream.CreateLC(*iWriteFileStore);
115 iWriteFileStore->SetRootL(writeRootStreamId);
117 writeRootStream.WriteUint32L(iWriteLookupStreamId.Value());
118 writeRootStream.CommitL();
119 CleanupStack::PopAndDestroy(&writeRootStream);
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));
126 CleanupClosePushL(readFile);
127 User::LeaveIfError(readFile.Open(iFs, *iParams->iOldKeyFile, EFileRead | EFileWrite | EFileShareExclusive));
128 iReadFileStore = CPermanentFileStore::FromL(readFile);
129 CleanupStack::PopAndDestroy(&readFile);
131 TStreamId readRootStreamId = iReadFileStore->Root();
132 if (readRootStreamId == KNullStreamId)
134 User::Leave(KErrCorrupt);
137 RStoreReadStream readRootStream;
138 readRootStream.OpenLC(*iReadFileStore, readRootStreamId);
139 TStreamId readLookupStreamId = (TStreamId)(readRootStream.ReadUint32L());
140 CleanupStack::PopAndDestroy(&readRootStream);
142 RStoreReadStream readLookupStream;
143 readLookupStream.OpenLC(*iReadFileStore, readLookupStreamId);
145 // ignore passStreamId and timeoutStreamId for migration
146 TStreamId passStreamId = readLookupStream.ReadUint32L();
147 TStreamId timeoutStreamId = readLookupStream.ReadUint32L();
149 TInt keyCount = readLookupStream.ReadInt32L();
151 // read the keys that are stored in this store
152 for (TInt index = 0; index < keyCount; index++)
154 const CFileKeyData* keyData = CFileKeyData::CreateOldKeyL(readLookupStream);
155 iKeyList.Append(keyData);
158 CleanupStack::PopAndDestroy(&readLookupStream);
160 RStoreReadStream timeoutStream;
161 timeoutStream.OpenLC(*iReadFileStore, timeoutStreamId);
162 TInt timeout = timeoutStream.ReadInt32L();
163 CleanupStack::PopAndDestroy(&timeoutStream);
165 iPassphrase = CPassphrase::NewL( timeout, *iReadFileStore,
166 passStreamId, *iParams->iPassphrase);
168 User::LeaveIfError(iAuthClient.Connect());
172 void CKeytoolMigrateStore::DoCommandL()
174 if(iParams->iOldKeyFile == NULL ||
175 iParams->iPassphrase == NULL )
177 User::Leave(CKeyToolParameters::EMandatoryArgumentMissing);
180 TUid uid = TUid::Uid(0);
181 AuthServer::CAuthExpression* expression = iAuthClient.CreateAuthExpressionL(*(iParams->iAuthExpression));
182 CleanupStack::PushL(expression);
183 iState = EAfterAuthentication;
185 iAuthClient.AuthenticateL(*expression,iParams->iFreshness, EFalse, uid, EFalse, KNullDesC, iUserIdentity, iStatus);
187 CleanupStack::PopAndDestroy(expression);
191 void CKeytoolMigrateStore::CleanKeyInfo(TAny* aKeyInfo)
193 delete reinterpret_cast<CKeyInfo*>(aKeyInfo);
196 void CKeytoolMigrateStore::WriteKeyInformationL()
199 TInt keysCount = iKeyList.Count();
201 for (TInt index = 0; index < keysCount; index++)
203 CFileKeyData* keyData = iKeyList[index];
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);
216 case (CKeyInfo::ERSA):
218 // retrieve the public key and write it in the new stream
219 CRSAPublicKey* publicKey = NULL;
220 RetrieveAndStorePublicKeyL(keyData, publicKey);
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);
228 case (CKeyInfo::EDSA):
230 // retrieve the public key and write it in the new stream
231 CDSAPublicKey* publicKey = NULL;
232 RetrieveAndStorePublicKeyL(keyData, publicKey);
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);
240 case (CKeyInfo::EDH):
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());
253 CreateLC(privateStream, dhKey);
254 RStoreWriteStream writePvtStr;
255 TStreamId pvtStrId = writePvtStr.CreateLC(*iWriteFileStore);
256 keyData->SetPrivateDataStreamId(pvtStrId);
258 if (KNullStreamId == pvtStrId)
260 User::Leave(KErrBadHandle);
262 EncryptAndStoreL(dhKey, writePvtStr );
263 writePvtStr.CommitL();
264 CleanupStack::PopAndDestroy(3, &privateStream); // dhKey, writePvtStr
270 User::Leave(KErrKeyAlgorithm);
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
283 RStoreWriteStream writeLookupStream;
284 writeLookupStream.ReplaceLC(*iWriteFileStore, iWriteLookupStreamId );
286 // write the count of keys
287 writeLookupStream.WriteInt32L(keysCount);
289 for(TInt index=0;index<keysCount;++index)
291 CFileKeyData* keyData = iKeyList[index];
292 // write the key using the lookupstream
293 keyData->ExternalizeWithAuthL(writeLookupStream);
296 writeLookupStream.CommitL();
297 CleanupStack::PopAndDestroy(&writeLookupStream);
299 iWriteFileStore->CommitL();
300 iReadFileStore->CommitL();
304 void CKeytoolMigrateStore::WriteKeyL( const CKeyInfo& aKeyInfo,
305 RStoreWriteStream& aWriteInfoStream )
307 aWriteInfoStream << aKeyInfo;
308 WriteAuthDetailsL(aWriteInfoStream);
309 aWriteInfoStream.CommitL();
312 void CKeytoolMigrateStore::WriteAuthDetailsL( RStoreWriteStream& aWriteInfoStream )
314 aWriteInfoStream.WriteInt32L(iUserIdentity->Id());
315 aWriteInfoStream << *(iParams->iAuthExpression);
316 aWriteInfoStream.WriteInt32L(iParams->iFreshness);
319 // This is a cleanup item that reverts the store
320 void CKeytoolMigrateStore::RevertStore(TAny* aStore)
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.
330 void CKeytoolMigrateStore::RunL()
332 User::LeaveIfError(iStatus.Int());
336 case EAfterAuthentication:
338 if(iUserIdentity == AuthServer::KUnknownIdentity)
340 User::Leave(KErrAuthenticationFailure);
342 WriteKeyInformationL();
343 // once keyinformation has been written
344 // delete the user identity
345 delete iUserIdentity;
346 iUserIdentity = NULL;
348 CActiveScheduler::Stop();
352 User::Leave(KErrNotSupported);
356 void CKeytoolMigrateStore::DoCancel()
361 TInt CKeytoolMigrateStore::RunError(TInt aError)
363 if(aError != KErrNone)
367 CActiveScheduler::Stop();
371 void CKeytoolMigrateStore::StoreKeyL(const TDesC8& aKeyData, RStoreWriteStream& aStream)
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);
395 CleanupStack::PopAndDestroy(3, pbeEncrypt); // ciphertext,encryptor