cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/CCreateKey.cpp
changeset 0 2c201484c85f
child 8 35751d3474b7
equal deleted inserted replaced
-1:000000000000 0:2c201484c85f
       
     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 "CCreateKey.h"
       
    20 #include "tokenserverdebug.h"
       
    21 #include <bigint.h>
       
    22 
       
    23 //	Wrapper class because we differ from crypto on what a DH key is
       
    24 class CSimpleDHKey : public CBase
       
    25 {
       
    26 public:
       
    27 	static CSimpleDHKey* NewL(TInt aSize);
       
    28 	~CSimpleDHKey();
       
    29 public:
       
    30 	inline RInteger& DHKey() {return (iKey);};
       
    31 private:
       
    32 	CSimpleDHKey() {};
       
    33 	void ConstructL(TInt aSize);
       
    34 private:
       
    35 	RInteger iKey;
       
    36 };
       
    37 
       
    38 CSimpleDHKey* CSimpleDHKey::NewL(TInt aSize)
       
    39 {
       
    40 	CSimpleDHKey* me = new (ELeave) CSimpleDHKey();
       
    41 	CleanupStack::PushL(me);
       
    42 	me->ConstructL(aSize);
       
    43 	CleanupStack::Pop(me);
       
    44 	return (me);
       
    45 }
       
    46 
       
    47 void CSimpleDHKey::ConstructL(TInt aSize)
       
    48 {
       
    49 	iKey = RInteger::NewRandomL(aSize - 1);							
       
    50 }
       
    51 
       
    52 CSimpleDHKey::~CSimpleDHKey()
       
    53 {
       
    54 	iKey.Close();
       
    55 }
       
    56 
       
    57 CKeyCreator::CKeyCreator()
       
    58 : CActive(EPriorityStandard), iAction(EIdle)
       
    59 {
       
    60 	CActiveScheduler::Add(this);
       
    61 }
       
    62 
       
    63 
       
    64 CKeyCreator::~CKeyCreator()
       
    65 {
       
    66 	Cancel(); 
       
    67 
       
    68 	iCreatorThread.LogonCancel(iStatus);
       
    69 	iCreatorThread.Close();
       
    70 
       
    71 	delete iCreateData;
       
    72 }
       
    73 
       
    74 //	Spin a thread to create an appropriate key, if successful, left on CleanupStack
       
    75 void CKeyCreator::DoCreateKeyAsyncL(CKeyInfo::EKeyAlgorithm aAlgorithm, TInt aSize, TRequestStatus& aStatus)
       
    76 {
       
    77 	if ( (aSize <= 0) ||
       
    78 		 (aAlgorithm==CKeyInfo::EInvalidAlgorithm) || 
       
    79 		 ((aAlgorithm!=CKeyInfo::ERSA) && (aAlgorithm!=CKeyInfo::EDSA) && (aAlgorithm!=CKeyInfo::EDH)) )
       
    80 		 User::Leave(KErrArgument);
       
    81 
       
    82 	iClientStatus = &aStatus;
       
    83 	*iClientStatus = KRequestPending;
       
    84 	
       
    85 	iCreateData = new (ELeave) CKeyCreatorData(aAlgorithm, aSize);
       
    86 	
       
    87 //	OK, ready to start the async operation...do it in RunL
       
    88 	iAction = EReadyToCreateKey;
       
    89 	iStatus = KRequestPending;
       
    90 	SetActive();
       
    91 	TRequestStatus* stat = &iStatus;
       
    92 	User::RequestComplete(stat, KErrNone);
       
    93 }
       
    94 
       
    95 //	HERE'S THE THREAD TO CREATE THE KEY
       
    96 //	Code cannot leave in here, but not as many traps as it looks
       
    97 /*static*/ TInt CKeyCreator::CreatorThreadEntryPoint(TAny* aParameters)
       
    98 {
       
    99 	CTrapCleanup* cleanup = CTrapCleanup::New();
       
   100 	if (!cleanup)
       
   101 		User::Exit(KErrNoMemory);
       
   102 
       
   103 #ifdef _DEBUG
       
   104 	TokenServerDebug::PauseOOMTest();
       
   105 #endif
       
   106 	
       
   107 	ASSERT(aParameters);
       
   108 	TInt result = KErrNone;
       
   109 	CKeyCreatorData* createData = static_cast<CKeyCreatorData*>(aParameters);
       
   110 	switch (createData->iKeyAlgorithm)
       
   111 	{
       
   112 		case(CKeyInfo::ERSA):
       
   113 			{//	Currently, CRT signing is not supported, in case the key is to be used
       
   114 			//	for such, create a standard (private) key as part of the pair
       
   115 				TRAP(result, createData->iKey.iRSAKey = CRSAKeyPair::NewL(createData->iSize));
       
   116 			}
       
   117 			break;
       
   118 		case (CKeyInfo::EDSA):
       
   119 			{
       
   120 				TRAP(result, createData->iKey.iDSAKey = CDSAKeyPair::NewL(createData->iSize));
       
   121 			}
       
   122 			break;
       
   123 		case (CKeyInfo::EDH):
       
   124 			{//	Generate a number that's less than N. The snag is that
       
   125 			//	we don't know what N is. We do know that it'll be of a
       
   126 			//	particular size, so we can safely generate any number
       
   127 			//	with less than iSize digits
       
   128 				TRAP(result, createData->iKey.iDHKey = CSimpleDHKey::NewL(createData->iSize));				
       
   129 			}
       
   130 			break;
       
   131 		default:
       
   132 			ASSERT(EFalse);
       
   133 			result = KErrArgument;
       
   134 	}
       
   135 
       
   136 #ifdef _DEBUG
       
   137 	TokenServerDebug::ResumeOOMTest();
       
   138 #endif
       
   139 	delete cleanup;
       
   140 	User::Exit(result);
       
   141 	return (KErrNone);
       
   142 }
       
   143 
       
   144 CRSAKeyPair* CKeyCreator::GetCreatedRSAKey()
       
   145 {//	Check algorithm is as expected, return NULL if no key or wrong type
       
   146 	if ( (!iCreateData) || (CKeyInfo::ERSA!=iCreateData->iKeyAlgorithm) )
       
   147 		return (NULL);
       
   148 	else
       
   149 		return (iCreateData->iKey.iRSAKey);
       
   150 }
       
   151 
       
   152 CDSAKeyPair* CKeyCreator::GetCreatedDSAKey()
       
   153 {//	Check algorithm is as expected, return NULL if no key or wrong type
       
   154 	if ( (!iCreateData) || (CKeyInfo::EDSA!=iCreateData->iKeyAlgorithm) )
       
   155 		return (NULL);
       
   156 	else
       
   157 		return (iCreateData->iKey.iDSAKey);
       
   158 }
       
   159 
       
   160 void CKeyCreator::GetCreatedDHKey(RInteger& aDHKey)
       
   161 {
       
   162 	ASSERT(iCreateData);
       
   163 	ASSERT(CKeyInfo::EDH==iCreateData->iKeyAlgorithm);		
       
   164 	aDHKey = iCreateData->iKey.iDHKey->DHKey();
       
   165 }
       
   166 
       
   167 void CKeyCreator::DoCancel()
       
   168 {//	Only do the cancel if in the middle of creating a key.  Kill the thread.
       
   169 	if (iAction!=EIdle)
       
   170 	{
       
   171 		TExitType exitType = iCreatorThread.ExitType();
       
   172 		if (EExitPending==exitType)	//	Still alive, so kill it
       
   173 			iCreatorThread.Kill(KErrCancel);
       
   174 
       
   175 		iAction = EIdle;
       
   176 	}
       
   177 
       
   178 	ASSERT(iClientStatus);
       
   179 	User::RequestComplete(iClientStatus, KErrCancel);
       
   180 }
       
   181 
       
   182 void CKeyCreator::RunL()
       
   183 {
       
   184 	ASSERT(iClientStatus);
       
   185 	
       
   186 	switch (iAction)
       
   187 	{
       
   188 		case (EReadyToCreateKey):
       
   189 		{	// Spin off the thread and pass it the parameter data, then stand by
       
   190 			// INC118634
       
   191 			// To be safe, we should use anonymous threads because naming a thread means anybody could have opened a handle on the thread,
       
   192 			// most likely system applications which want to know about panicing threads. So next thread creation will fail with KErrAlreadyExist(-11).
       
   193 			User::LeaveIfError(iCreatorThread.Create(KNullDesC, CreatorThreadEntryPoint, KDefaultStackSize, NULL, (TAny*)iCreateData));
       
   194 			iStatus = KRequestPending;
       
   195 			iCreatorThread.Logon(iStatus);
       
   196 			iAction = ECreatedKey;
       
   197 			SetActive();
       
   198 			iCreatorThread.Resume();
       
   199 		}
       
   200 		break;
       
   201 		case (ECreatedKey):
       
   202 		{//	Notify the caller
       
   203 			ASSERT(iClientStatus);
       
   204 			// May be OOM creating logon, in which case we should kill thread
       
   205 			if (iStatus.Int() == KErrNoMemory)
       
   206 				{
       
   207 				TExitType exitType = iCreatorThread.ExitType();
       
   208 				if (EExitPending==exitType)	//	Still alive, so kill it
       
   209 					iCreatorThread.Kill(KErrNone);
       
   210 				}
       
   211 			
       
   212 			User::RequestComplete(iClientStatus, iStatus.Int());
       
   213 			iAction = EIdle;
       
   214 		}
       
   215 		break;
       
   216 		default:
       
   217 			ASSERT(EFalse);
       
   218 	}
       
   219 }
       
   220 
       
   221 TInt CKeyCreator::RunError(TInt anError)
       
   222 {
       
   223 	if (iClientStatus)
       
   224 		User::RequestComplete(iClientStatus, anError);
       
   225 
       
   226 	return (KErrNone);
       
   227 }
       
   228 
       
   229 
       
   230 
       
   231 CKeyCreator::CKeyCreatorData::CKeyCreatorData(CKeyInfo::EKeyAlgorithm aAlgorithm, TInt aSize)
       
   232 :	iSize(aSize), iKeyAlgorithm(aAlgorithm)
       
   233 {}
       
   234 
       
   235 CKeyCreator::CKeyCreatorData::~CKeyCreatorData()
       
   236 {
       
   237 	if (iKeyAlgorithm==CKeyInfo::ERSA)
       
   238 		delete iKey.iRSAKey;
       
   239 	else if (iKeyAlgorithm==CKeyInfo::EDSA)
       
   240 		delete iKey.iDSAKey;
       
   241 	else if (iKeyAlgorithm==CKeyInfo::EDH)
       
   242 		delete iKey.iDHKey;
       
   243 }