os/security/cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/CCreateKey.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 "CCreateKey.h"
20 #include "tokenserverdebug.h"
22 #include <securityerr.h>
24 // Wrapper class because we differ from crypto on what a DH key is
25 class CSimpleDHKey : public CBase
28 static CSimpleDHKey* NewL(TInt aSize);
31 inline RInteger& DHKey() {return (iKey);};
34 void ConstructL(TInt aSize);
39 CSimpleDHKey* CSimpleDHKey::NewL(TInt aSize)
41 CSimpleDHKey* me = new (ELeave) CSimpleDHKey();
42 CleanupStack::PushL(me);
43 me->ConstructL(aSize);
44 CleanupStack::Pop(me);
48 void CSimpleDHKey::ConstructL(TInt aSize)
50 iKey = RInteger::NewRandomL(aSize - 1);
53 CSimpleDHKey::~CSimpleDHKey()
58 CKeyCreator::CKeyCreator()
59 : CActive(EPriorityStandard),
62 CActiveScheduler::Add(this);
65 CKeyCreator::~CKeyCreator()
69 iCreatorThread.LogonCancel(iStatus);
70 iCreatorThread.Close();
75 // Spin a thread to create an appropriate key, if successful, left on CleanupStack
76 void CKeyCreator::DoCreateKeyAsync(CKeyInfo::EKeyAlgorithm aAlgorithm, TInt aSize, TRequestStatus& aStatus)
78 iClientStatus = &aStatus;
79 *iClientStatus = KRequestPending;
80 iStatus = KRequestPending;
85 (aAlgorithm==CKeyInfo::EInvalidAlgorithm) ||
86 ((aAlgorithm!=CKeyInfo::ERSA) && (aAlgorithm!=CKeyInfo::EDSA) && (aAlgorithm!=CKeyInfo::EDH)) )
88 err = KErrKeyAlgorithm;
92 iCreateData = new CKeyCreatorData(aAlgorithm, aSize);
93 if(iCreateData == NULL)
100 User::RequestComplete(iClientStatus, err);
104 // OK, ready to start the async operation...do it in RunL
105 iAction = EReadyToCreateKey;
108 TRequestStatus* stat = &iStatus;
109 User::RequestComplete(stat, err);
112 // HERE'S THE THREAD TO CREATE THE KEY
113 // Code cannot leave in here, but not as many traps as it looks
114 /*static*/ TInt CKeyCreator::CreatorThreadEntryPoint(TAny* aParameters)
116 CTrapCleanup* cleanup = CTrapCleanup::New();
118 User::Exit(KErrNoMemory);
121 TokenServerDebug::PauseOOMTest();
125 TInt result = KErrNone;
126 CKeyCreatorData* createData = static_cast<CKeyCreatorData*>(aParameters);
127 switch (createData->iKeyAlgorithm)
129 case(CKeyInfo::ERSA):
130 {// Currently, CRT signing is not supported, in case the key is to be used
131 // for such, create a standard (private) key as part of the pair
132 TRAP(result, createData->iKey.iRSAKey = CRSAKeyPair::NewL(createData->iSize));
135 case (CKeyInfo::EDSA):
137 TRAP(result, createData->iKey.iDSAKey = CDSAKeyPair::NewL(createData->iSize));
140 case (CKeyInfo::EDH):
141 {// Generate a number that's less than N. The snag is that
142 // we don't know what N is. We do know that it'll be of a
143 // particular size, so we can safely generate any number
144 // with less than iSize digits
145 TRAP(result, createData->iKey.iDHKey = CSimpleDHKey::NewL(createData->iSize));
150 result = KErrArgument;
154 TokenServerDebug::ResumeOOMTest();
161 CRSAKeyPair* CKeyCreator::GetCreatedRSAKey()
163 // Check algorithm is as expected, return NULL if no key or wrong type
164 if ( (!iCreateData) || (CKeyInfo::ERSA!=iCreateData->iKeyAlgorithm) )
167 return (iCreateData->iKey.iRSAKey);
170 CDSAKeyPair* CKeyCreator::GetCreatedDSAKey()
172 // Check algorithm is as expected, return NULL if no key or wrong type
173 if ( (!iCreateData) || (CKeyInfo::EDSA!=iCreateData->iKeyAlgorithm) )
176 return (iCreateData->iKey.iDSAKey);
179 void CKeyCreator::GetCreatedDHKey(RInteger& aDHKey)
182 ASSERT(CKeyInfo::EDH==iCreateData->iKeyAlgorithm);
183 aDHKey = iCreateData->iKey.iDHKey->DHKey();
186 void CKeyCreator::DoCancel()
188 // Only do the cancel if in the middle of creating a key. Kill the thread.
191 TExitType exitType = iCreatorThread.ExitType();
192 if (EExitPending==exitType) // Still alive, so kill it
194 iCreatorThread.Kill(KErrCancel);
199 ASSERT(iClientStatus);
200 User::RequestComplete(iClientStatus, KErrCancel);
203 void CKeyCreator::RunL()
205 ASSERT(iClientStatus);
206 User::LeaveIfError(iStatus.Int());
210 case (EReadyToCreateKey):
212 // Spin off the thread and pass it the parameter data, then stand by
214 // To be safe, we should use anonymous threads because naming a thread means anybody could have opened a handle on the thread,
215 // most likely system applications which want to know about panicing threads. So next thread creation will fail with KErrAlreadyExist(-11).
216 User::LeaveIfError(iCreatorThread.Create(KNullDesC, CreatorThreadEntryPoint, KDefaultStackSize, NULL, (TAny*)iCreateData));
217 iStatus = KRequestPending;
218 iCreatorThread.Logon(iStatus);
219 iAction = ECreatedKey;
221 iCreatorThread.Resume();
226 {// Notify the caller
227 ASSERT(iClientStatus);
228 // May be OOM creating logon, in which case we should kill thread
229 if (iStatus.Int() == KErrNoMemory)
231 TExitType exitType = iCreatorThread.ExitType();
232 if (EExitPending==exitType) // Still alive, so kill it
233 iCreatorThread.Kill(KErrNone);
236 User::RequestComplete(iClientStatus, iStatus.Int());
245 TInt CKeyCreator::RunError(TInt anError)
248 User::RequestComplete(iClientStatus, anError);
255 CKeyCreator::CKeyCreatorData::CKeyCreatorData(CKeyInfo::EKeyAlgorithm aAlgorithm, TInt aSize)
257 iKeyAlgorithm(aAlgorithm)
260 CKeyCreator::CKeyCreatorData::~CKeyCreatorData()
262 if (iKeyAlgorithm==CKeyInfo::ERSA)
264 else if (iKeyAlgorithm==CKeyInfo::EDSA)
266 else if (iKeyAlgorithm==CKeyInfo::EDH)