os/security/cryptoservices/filebasedcertificateandkeystores/source/keystore/Server/CCreateKey.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 #include <securityerr.h>
    23 
    24 //	Wrapper class because we differ from crypto on what a DH key is
    25 class CSimpleDHKey : public CBase
    26 	{
    27 	public:
    28 		static CSimpleDHKey* NewL(TInt aSize);
    29 		~CSimpleDHKey();
    30 	public:
    31 		inline RInteger& DHKey() {return (iKey);};
    32 	private:
    33 		CSimpleDHKey() {};
    34 		void ConstructL(TInt aSize);
    35 	private:
    36 		RInteger iKey;
    37 	};
    38 
    39 CSimpleDHKey* CSimpleDHKey::NewL(TInt aSize)
    40 	{
    41 	CSimpleDHKey* me = new (ELeave) CSimpleDHKey();
    42 	CleanupStack::PushL(me);
    43 	me->ConstructL(aSize);
    44 	CleanupStack::Pop(me);
    45 	return (me);
    46 	}
    47 
    48 void CSimpleDHKey::ConstructL(TInt aSize)
    49 	{
    50 	iKey = RInteger::NewRandomL(aSize - 1);							
    51 	}
    52 
    53 CSimpleDHKey::~CSimpleDHKey()
    54 	{
    55 	iKey.Close();
    56 	}
    57 
    58 CKeyCreator::CKeyCreator()
    59 	: CActive(EPriorityStandard), 
    60 	iAction(EIdle)
    61 	{
    62 	CActiveScheduler::Add(this);
    63 	}
    64 
    65 CKeyCreator::~CKeyCreator()
    66 	{
    67 	Cancel(); 
    68 
    69 	iCreatorThread.LogonCancel(iStatus);
    70 	iCreatorThread.Close();
    71 
    72 	delete iCreateData;
    73 	}
    74 
    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)
    77 	{
    78 	iClientStatus = &aStatus;
    79 	*iClientStatus = KRequestPending;
    80 	iStatus = KRequestPending;
    81 		
    82 	TInt err = KErrNone;
    83 	
    84 	if ( (aSize <= 0) ||
    85 		 (aAlgorithm==CKeyInfo::EInvalidAlgorithm) || 
    86 		 ((aAlgorithm!=CKeyInfo::ERSA) && (aAlgorithm!=CKeyInfo::EDSA) && (aAlgorithm!=CKeyInfo::EDH)) )
    87 		{
    88 		err = KErrKeyAlgorithm;
    89 		}
    90 	if(err == KErrNone)
    91 		{
    92 		iCreateData = new CKeyCreatorData(aAlgorithm, aSize);
    93 		if(iCreateData == NULL)
    94 			{
    95 			err = KErrNoMemory;
    96 			}
    97 		}
    98 	else
    99 		{
   100 		User::RequestComplete(iClientStatus, err);
   101 		return;
   102 		}
   103 	
   104 	//	OK, ready to start the async operation...do it in RunL
   105 	iAction = EReadyToCreateKey;
   106 	
   107 	SetActive();
   108 	TRequestStatus* stat = &iStatus;
   109 	User::RequestComplete(stat, err);
   110 	}	
   111 
   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)
   115 	{
   116 	CTrapCleanup* cleanup = CTrapCleanup::New();
   117 	if (!cleanup)
   118 		User::Exit(KErrNoMemory);
   119 
   120 #ifdef _DEBUG
   121 	TokenServerDebug::PauseOOMTest();
   122 #endif
   123 	
   124 	ASSERT(aParameters);
   125 	TInt result = KErrNone;
   126 	CKeyCreatorData* createData = static_cast<CKeyCreatorData*>(aParameters);
   127 	switch (createData->iKeyAlgorithm)
   128 		{
   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));
   133 			}
   134 			break;
   135 		case (CKeyInfo::EDSA):
   136 			{
   137 				TRAP(result, createData->iKey.iDSAKey = CDSAKeyPair::NewL(createData->iSize));
   138 			}
   139 			break;
   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));				
   146 			}
   147 			break;
   148 		default:
   149 			ASSERT(EFalse);
   150 			result = KErrArgument;
   151 		}
   152 
   153 	#ifdef _DEBUG
   154 		TokenServerDebug::ResumeOOMTest();
   155 	#endif
   156 	delete cleanup;
   157 	User::Exit(result);
   158 	return (KErrNone);
   159 	}
   160 
   161 CRSAKeyPair* CKeyCreator::GetCreatedRSAKey()
   162 	{
   163 	//	Check algorithm is as expected, return NULL if no key or wrong type
   164 	if ( (!iCreateData) || (CKeyInfo::ERSA!=iCreateData->iKeyAlgorithm) )
   165 		return (NULL);
   166 	else
   167 		return (iCreateData->iKey.iRSAKey);
   168 	}
   169 
   170 CDSAKeyPair* CKeyCreator::GetCreatedDSAKey()
   171 	{
   172 	//	Check algorithm is as expected, return NULL if no key or wrong type
   173 	if ( (!iCreateData) || (CKeyInfo::EDSA!=iCreateData->iKeyAlgorithm) )
   174 		return (NULL);
   175 	else
   176 		return (iCreateData->iKey.iDSAKey);
   177 	}
   178 
   179 void CKeyCreator::GetCreatedDHKey(RInteger& aDHKey)
   180 	{
   181 	ASSERT(iCreateData);
   182 	ASSERT(CKeyInfo::EDH==iCreateData->iKeyAlgorithm);		
   183 	aDHKey = iCreateData->iKey.iDHKey->DHKey();
   184 	}
   185 
   186 void CKeyCreator::DoCancel()
   187 	{
   188 	//	Only do the cancel if in the middle of creating a key.  Kill the thread.
   189 	if (iAction!=EIdle)
   190 		{
   191 		TExitType exitType = iCreatorThread.ExitType();
   192 		if (EExitPending==exitType)	//	Still alive, so kill it
   193 			{
   194 			iCreatorThread.Kill(KErrCancel);
   195 			}
   196 		iAction = EIdle;
   197 		}
   198 
   199 	ASSERT(iClientStatus);
   200 	User::RequestComplete(iClientStatus, KErrCancel);
   201 	}
   202 
   203 void CKeyCreator::RunL()
   204 	{
   205 	ASSERT(iClientStatus);
   206 	User::LeaveIfError(iStatus.Int());
   207 	
   208 	switch (iAction)
   209 		{
   210 		case (EReadyToCreateKey):
   211 			{	
   212 			// Spin off the thread and pass it the parameter data, then stand by
   213 			// INC118634
   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;
   220 			SetActive();
   221 			iCreatorThread.Resume();
   222 			}
   223 		break;
   224 		
   225 		case (ECreatedKey):
   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)
   230 				{
   231 				TExitType exitType = iCreatorThread.ExitType();
   232 				if (EExitPending==exitType)	//	Still alive, so kill it
   233 					iCreatorThread.Kill(KErrNone);
   234 				}
   235 			
   236 			User::RequestComplete(iClientStatus, iStatus.Int());
   237 			iAction = EIdle;
   238 			}
   239 		break;
   240 		default:
   241 			ASSERT(EFalse);
   242 		}
   243 	}
   244 
   245 TInt CKeyCreator::RunError(TInt anError)
   246 	{
   247 	if (iClientStatus)
   248 		User::RequestComplete(iClientStatus, anError);
   249 
   250 	return (KErrNone);
   251 	}
   252 
   253 
   254 
   255 CKeyCreator::CKeyCreatorData::CKeyCreatorData(CKeyInfo::EKeyAlgorithm aAlgorithm, TInt aSize)
   256 	:iSize(aSize), 
   257 	iKeyAlgorithm(aAlgorithm)
   258 	{}
   259 
   260 CKeyCreator::CKeyCreatorData::~CKeyCreatorData()
   261 	{
   262 	if (iKeyAlgorithm==CKeyInfo::ERSA)
   263 		delete iKey.iRSAKey;
   264 	else if (iKeyAlgorithm==CKeyInfo::EDSA)
   265 		delete iKey.iDSAKey;
   266 	else if (iKeyAlgorithm==CKeyInfo::EDH)
   267 		delete iKey.iDHKey;
   268 	}
   269