vpnengine/pkiservice/src/keymanager.cpp
changeset 0 33413c0669b9
child 4 29b591713d44
equal deleted inserted replaced
-1:000000000000 0:33413c0669b9
       
     1 /*
       
     2 * Copyright (c) 2008 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 "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:   Class, which provides operation for deleting, saving and creating keypairs.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 #include <mctauthobject.h>
       
    21 
       
    22 #include "keymanager.h"
       
    23 #include "logonservices.h"
       
    24 #include "utlcrypto.h"
       
    25 #include "base64.h"
       
    26 #include "pkiserviceassert.h"
       
    27 #include "pkiserviceconstants.h"
       
    28 
       
    29 const TTimeIntervalYears KValidityPeriod(20);
       
    30 _LIT_SECURITY_POLICY_C1(KSymbianKeyStoreMgmtPolicy, ECapabilityWriteDeviceData);
       
    31 _LIT_SECURITY_POLICY_C1(KSymbianKeyStoreUsePolicy, ECapabilityReadDeviceData);
       
    32 
       
    33 CKeyManager* CKeyManager::NewL(CLogonServices& aLogonServices)
       
    34     {
       
    35     CKeyManager* self = new (ELeave) CKeyManager(aLogonServices);
       
    36     CleanupStack::PushL(self);
       
    37     self->ConstructL();
       
    38     CleanupStack::Pop(self);    
       
    39     return self;
       
    40     }
       
    41 
       
    42 
       
    43 CKeyManager::CKeyManager(CLogonServices& aLogonServices)
       
    44 :CActive(EPriorityNormal), iLogonServices(aLogonServices)
       
    45     {
       
    46     CActiveScheduler::Add(this);
       
    47     }
       
    48 
       
    49 
       
    50 void CKeyManager::ConstructL()
       
    51     {
       
    52     }
       
    53 
       
    54 
       
    55 CKeyManager::~CKeyManager()
       
    56     {
       
    57     Cleanup();
       
    58     }
       
    59 
       
    60 
       
    61 void CKeyManager::RemoveKeyPair(const TPKIKeyIdentifier& aKeyId, 
       
    62                                 CUnifiedKeyStore& aUnifiedKeyStore,
       
    63                                 TInt aUsedKeyStore,
       
    64                                 TRequestStatus& aClientStatus)
       
    65     {
       
    66     PKISERVICE_ASSERT(iState == EKeyManagerIdle);
       
    67     PKISERVICE_ASSERT(iClientStatus == NULL);
       
    68     PKISERVICE_ASSERT(aUsedKeyStore == STORETYPE_USER_KEY_ID ||
       
    69                    aUsedKeyStore == STORETYPE_DEVICE_KEY_ID ||
       
    70                    aUsedKeyStore == STORETYPE_ANY_KEY_ID);
       
    71     
       
    72     
       
    73     iState = ERetrievingKeyPairForRemove;
       
    74     
       
    75     iClientStatus = &aClientStatus;
       
    76     *iClientStatus = KRequestPending;
       
    77     
       
    78     iUsedKeyStore = aUsedKeyStore;
       
    79     iUnifiedKeyStore = &aUnifiedKeyStore;
       
    80     
       
    81     TCTKeyAttributeFilter filter;
       
    82     filter.iKeyId = aKeyId;
       
    83 
       
    84     iUnifiedKeyStore->List(iKeysList, filter, iStatus);
       
    85     SetActive();        
       
    86     }
       
    87 
       
    88 
       
    89 void CKeyManager::GenerateKeyPair(CUnifiedKeyStore& aUnifiedKeyStore,
       
    90                                   TInt aUsedKeyStore, 
       
    91                                   const TUint aKeySize, 
       
    92                                   TPKIKeyAlgorithm aKeyAlgorithm,
       
    93                                   TPKIKeyIdentifier& aKeyId,
       
    94                                   TRequestStatus& aClientStatus)                          
       
    95     {        
       
    96     PKISERVICE_ASSERT(iState == EKeyManagerIdle);
       
    97     PKISERVICE_ASSERT(iObjectName == NULL);    
       
    98     PKISERVICE_ASSERT(iClientStatus == NULL);    
       
    99     PKISERVICE_ASSERT(aUsedKeyStore == STORETYPE_USER_KEY_ID ||
       
   100                    aUsedKeyStore == STORETYPE_DEVICE_KEY_ID ||
       
   101                    aUsedKeyStore == STORETYPE_ANY_KEY_ID);
       
   102 
       
   103     iState = EGeneratingKeyPair;
       
   104 
       
   105     iKeyId = &aKeyId;
       
   106     iClientStatus = &aClientStatus;
       
   107     *iClientStatus = KRequestPending;
       
   108             
       
   109     iUnifiedKeyStore = &aUnifiedKeyStore;   
       
   110                  
       
   111     if (aUsedKeyStore == STORETYPE_ANY_KEY_ID)
       
   112         {
       
   113         //If any type is used the key is greated in 
       
   114         //user store.
       
   115         aUsedKeyStore = STORETYPE_USER_KEY_ID;
       
   116         }
       
   117             
       
   118     TRAPD(err, iObjectName = GetUniqueNameL());
       
   119     if (err == KErrNone)
       
   120         {                   
       
   121         TTime startDate;
       
   122         TTime endDate;
       
   123         startDate.UniversalTime();
       
   124         endDate.UniversalTime();
       
   125         endDate += KValidityPeriod;
       
   126                     
       
   127         TInt keyStoreCount = iUnifiedKeyStore->KeyStoreManagerCount(); 
       
   128         TInt i = 0;
       
   129         for (i = 0; i < keyStoreCount; ++i)
       
   130             {
       
   131             MCTKeyStoreManager& keyStore = iUnifiedKeyStore->KeyStoreManager(i);        
       
   132             if (keyStore.Token().TokenType().Type().iUid == aUsedKeyStore)            
       
   133                 {
       
   134                 break;
       
   135                 }
       
   136             }
       
   137         PKISERVICE_ASSERT(i < keyStoreCount);
       
   138         
       
   139          
       
   140         iUnifiedKeyStore->CreateKey(i, EPKCS15UsageSignDecrypt, 
       
   141                                     aKeySize,
       
   142                                     *iObjectName,
       
   143                                     ConvertPKIAlgorithm(aKeyAlgorithm),
       
   144                                     CKeyInfoBase::EExtractable,
       
   145                                     startDate,
       
   146                                     endDate,
       
   147                                     iKeyInfo,
       
   148                                     iStatus);        
       
   149         SetActive();
       
   150 
       
   151         }
       
   152     else    
       
   153         {
       
   154         TRequestStatus* ownStatus = &iStatus;
       
   155         *ownStatus = KRequestPending;
       
   156         SetActive();
       
   157         
       
   158         User::RequestComplete(ownStatus, err);
       
   159         }
       
   160     }
       
   161 
       
   162 
       
   163 void CKeyManager::ImportKeyPair(CUnifiedKeyStore& aUnifiedKeyStore,
       
   164                                 TInt aUsedKeyStore, 
       
   165                                 const TDesC8& aKeyData,
       
   166                                 TPKIKeyIdentifier& aKeyId,
       
   167                                 TRequestStatus& aClientStatus)
       
   168     {
       
   169     PKISERVICE_ASSERT(iState == EKeyManagerIdle);
       
   170     PKISERVICE_ASSERT(iObjectName == NULL);    
       
   171     PKISERVICE_ASSERT(iClientStatus == NULL);  
       
   172     PKISERVICE_ASSERT(aUsedKeyStore == STORETYPE_USER_KEY_ID ||
       
   173                    aUsedKeyStore == STORETYPE_DEVICE_KEY_ID ||
       
   174                    aUsedKeyStore == STORETYPE_ANY_KEY_ID);
       
   175       
       
   176 
       
   177     iState = EImportingKeyPair;
       
   178 
       
   179     iKeyId = &aKeyId;
       
   180     iClientStatus = &aClientStatus;
       
   181     *iClientStatus = KRequestPending;
       
   182             
       
   183     iUnifiedKeyStore = &aUnifiedKeyStore;            
       
   184           
       
   185     if (aUsedKeyStore == STORETYPE_ANY_KEY_ID)
       
   186         {
       
   187         //If any type is used the key is greated in 
       
   188         //user store.
       
   189         aUsedKeyStore = STORETYPE_USER_KEY_ID;
       
   190         }
       
   191           
       
   192             
       
   193     TRAPD(err, iObjectName = GetUniqueNameL());
       
   194     if (err == KErrNone)
       
   195         {                   
       
   196         TTime startDate;
       
   197         TTime endDate;
       
   198         startDate.UniversalTime();
       
   199         endDate.UniversalTime();
       
   200         endDate += KValidityPeriod;
       
   201         
       
   202         TInt keyStoreCount = iUnifiedKeyStore->KeyStoreManagerCount(); 
       
   203         TInt i = 0;
       
   204         for (i = 0; i < keyStoreCount; ++i)
       
   205             {
       
   206             MCTKeyStoreManager& keyStore = iUnifiedKeyStore->KeyStoreManager(i);        
       
   207             if (keyStore.Token().TokenType().Type().iUid == aUsedKeyStore)            
       
   208                 {
       
   209                 break;
       
   210                 }
       
   211             }
       
   212         PKISERVICE_ASSERT(i < keyStoreCount);
       
   213         
       
   214          
       
   215         iUnifiedKeyStore->ImportKey(i, aKeyData,
       
   216                                     EPKCS15UsageSignDecrypt, 
       
   217                                     *iObjectName,
       
   218                                     CKeyInfoBase::EExtractable,
       
   219                                     startDate,
       
   220                                     endDate,
       
   221                                     iKeyInfo,
       
   222                                     iStatus);        
       
   223         SetActive();
       
   224         }
       
   225     else    
       
   226         {
       
   227         TRequestStatus* ownStatus = &iStatus;
       
   228         *ownStatus = KRequestPending;
       
   229         SetActive();
       
   230         
       
   231         User::RequestComplete(ownStatus, err);
       
   232         }    
       
   233     }
       
   234 
       
   235 
       
   236 void CKeyManager::ExportPublicKey(CUnifiedKeyStore& aUnifiedKeyStore,
       
   237                                   TInt aUsedKeyStore,                          
       
   238                                   const TPKIKeyIdentifier& aKeyId,
       
   239                                   HBufC8*& aPublicKeyData,
       
   240                                   TRequestStatus& aClientStatus)
       
   241     {
       
   242     PKISERVICE_ASSERT(iState == EKeyManagerIdle);
       
   243     PKISERVICE_ASSERT(iPublicKeyData == NULL);    
       
   244     PKISERVICE_ASSERT(iClientStatus == NULL);  
       
   245     PKISERVICE_ASSERT(aUsedKeyStore == STORETYPE_USER_KEY_ID ||
       
   246                    aUsedKeyStore == STORETYPE_DEVICE_KEY_ID ||
       
   247                    aUsedKeyStore == STORETYPE_ANY_KEY_ID);
       
   248                    
       
   249     iState = ERetrievingKeyListForExport;                   
       
   250     iPublicKeyData = &aPublicKeyData;    
       
   251     iUsedKeyStore = aUsedKeyStore;
       
   252 
       
   253     iClientStatus = &aClientStatus;
       
   254     *iClientStatus = KRequestPending;
       
   255             
       
   256     iUnifiedKeyStore = &aUnifiedKeyStore;            
       
   257 
       
   258     
       
   259 	TCTKeyAttributeFilter filter;
       
   260     filter.iKeyId = aKeyId;
       
   261 
       
   262 	iUnifiedKeyStore->List(iKeysList, filter, iStatus);
       
   263 	SetActive();        
       
   264     }
       
   265 
       
   266 
       
   267 
       
   268 void CKeyManager::RunL()
       
   269     {
       
   270     if (iStatus.Int() == KErrNone)
       
   271         {        
       
   272         switch(iState)
       
   273             {
       
   274             case ERetrievingKeyPairForRemove:                
       
   275                 {                                        
       
   276                 TInt keyIndex = GetKeyIndex(iUsedKeyStore, iKeysList);
       
   277                 if ( keyIndex >= 0)
       
   278                     {                    
       
   279                     iState = ERemovingKeyPair;
       
   280                     iUnifiedKeyStore->DeleteKey(iKeysList[keyIndex]->Handle(), iStatus);
       
   281                     SetActive();
       
   282                     }
       
   283                 else
       
   284                     {
       
   285                     Cleanup();
       
   286                     User::RequestComplete(iClientStatus, KPKIErrNotFound);                    
       
   287                     }                
       
   288                 }
       
   289                 break;
       
   290             case ERemovingKeyPair:
       
   291                 Cleanup(); 
       
   292                 User::RequestComplete(iClientStatus, iStatus.Int());   
       
   293                 break;   
       
   294             case EImportingKeyPair: //falls through                
       
   295             case EGeneratingKeyPair:                  
       
   296                 {                                  
       
   297                 iState = ESettingManagementPolicy;   
       
   298                 
       
   299                 MCTAuthenticationObject* authObject = iKeyInfo->Protector();
       
   300                 if (authObject != NULL)
       
   301                     {
       
   302                     //authObject is NULL for device store
       
   303                     iLogonServices.SetAuthenticationObject(authObject);
       
   304                     }
       
   305                  
       
   306                 iUnifiedKeyStore->SetManagementPolicy(iKeyInfo->Handle(), 
       
   307                                                       KSymbianKeyStoreMgmtPolicy, 
       
   308                                                       iStatus);                    
       
   309                 SetActive();
       
   310                 }
       
   311                 break;
       
   312             case ESettingManagementPolicy:
       
   313                 iState = ESettingUsePolicy;
       
   314                 iUnifiedKeyStore->SetUsePolicy(iKeyInfo->Handle(), 
       
   315                                                KSymbianKeyStoreUsePolicy, 
       
   316                                                iStatus);
       
   317                 SetActive();                                               
       
   318                 break;
       
   319             case ESettingUsePolicy:
       
   320                 *iKeyId = iKeyInfo->ID();
       
   321                 Cleanup();
       
   322                 User::RequestComplete(iClientStatus, KErrNone);
       
   323                 break;
       
   324             case ERetrievingKeyListForExport:
       
   325                 {                    
       
   326                 TInt keyIndex = GetKeyIndex(iUsedKeyStore, iKeysList);
       
   327                 if ( keyIndex >= 0)
       
   328                     {                    
       
   329                     iState = EExportingPublicKey;                    
       
   330                     TCTTokenObjectHandle tokenHandle = iKeysList[keyIndex]->Handle();                    
       
   331                     iUnifiedKeyStore->ExportPublic(tokenHandle, *iPublicKeyData, iStatus);
       
   332                     SetActive();
       
   333                     
       
   334                     }
       
   335                 else
       
   336                     {
       
   337                     Cleanup();
       
   338                     User::RequestComplete(iClientStatus, KPKIErrNotFound);                    
       
   339                     }                            
       
   340                 }
       
   341                 break;
       
   342             case EExportingPublicKey:
       
   343                 {                    
       
   344                 iState = EKeyManagerIdle;     
       
   345                                            
       
   346                 if (iStatus.Int() == KErrNone)
       
   347                     {                                                
       
   348                     TPtr8 publicKeyPtr = (*iPublicKeyData)->Des();
       
   349 
       
   350                     // Fix length and strip header (not a
       
   351                     // perfect solution!), but certificate
       
   352                     // enrollment request wants to have
       
   353                     // only PKCS#1 key data.
       
   354                     TInt tempLength = 0;
       
   355                     TInt skip = 0;
       
   356                     if(publicKeyPtr[1] == 0x82)
       
   357                         {
       
   358                         tempLength = (publicKeyPtr[2] << 8) + publicKeyPtr[3] + 4 - 0x18;
       
   359                         skip = 0x18;
       
   360                         }
       
   361                     else
       
   362                         {
       
   363                         tempLength = publicKeyPtr[2] + 3 - 0x16;
       
   364                         skip = 0x16;
       
   365                         }
       
   366                         
       
   367                     PKISERVICE_ASSERT(tempLength <= publicKeyPtr.MaxLength());
       
   368                     publicKeyPtr.Copy(publicKeyPtr.Ptr() + skip, tempLength);                                
       
   369                     }
       
   370                 Cleanup();
       
   371                 User::RequestComplete(iClientStatus, iStatus.Int());                       
       
   372                 }
       
   373                 break;                
       
   374             default:
       
   375                 PKISERVICE_INVARIANT();            
       
   376             }    
       
   377         }
       
   378     else
       
   379         {
       
   380         Cleanup();
       
   381         User::RequestComplete(iClientStatus, iStatus.Int());
       
   382         }
       
   383     }
       
   384 
       
   385 
       
   386 void CKeyManager::DoCancel()
       
   387     {
       
   388     switch(iState)
       
   389         {
       
   390         case ERetrievingKeyListForExport: //falls through
       
   391         case ERetrievingKeyPairForRemove:
       
   392             iUnifiedKeyStore->CancelList();
       
   393             break;
       
   394         case ERemovingKeyPair:
       
   395             iUnifiedKeyStore->CancelDeleteKey();
       
   396             break;
       
   397         case EGeneratingKeyPair:
       
   398             iUnifiedKeyStore->CancelCreateKey();
       
   399             break;
       
   400         case EImportingKeyPair:
       
   401             iUnifiedKeyStore->CancelImportKey();
       
   402             break;
       
   403         case ESettingManagementPolicy:
       
   404             iUnifiedKeyStore->CancelSetManagementPolicy();
       
   405             break;
       
   406         case ESettingUsePolicy:
       
   407             iUnifiedKeyStore->CancelSetUsePolicy();
       
   408             break;
       
   409         case EExportingPublicKey:
       
   410             iUnifiedKeyStore->CancelExportPublic();
       
   411             delete *iPublicKeyData;
       
   412             *iPublicKeyData = NULL;
       
   413             break;
       
   414         default:
       
   415             PKISERVICE_INVARIANT();            
       
   416         }
       
   417     Cleanup();        
       
   418     User::RequestComplete(iClientStatus, KErrCancel);
       
   419     }
       
   420 
       
   421 
       
   422 void CKeyManager::RunError()
       
   423     {
       
   424     //RunL doesn't leave
       
   425     PKISERVICE_INVARIANT();
       
   426     }
       
   427 
       
   428 void CKeyManager::Cleanup()
       
   429     {
       
   430     iState = EKeyManagerIdle;   
       
   431     
       
   432     iPublicKeyData = NULL;
       
   433     
       
   434     if (iKeyInfo != NULL)
       
   435         {
       
   436         iKeyInfo->Release();
       
   437         iKeyInfo = NULL;
       
   438         }
       
   439     iKeysList.Close();
       
   440           
       
   441     delete iObjectName;
       
   442     iObjectName = NULL;          
       
   443           
       
   444     iUnifiedKeyStore = NULL;        
       
   445     
       
   446     iUsedKeyStore = 0;    
       
   447     }
       
   448 
       
   449 
       
   450 HBufC* CKeyManager::GetUniqueNameL() const
       
   451     {
       
   452     TBuf<MAX_FILENAME_LENGTH> date;
       
   453     TTime time;
       
   454     TDateTime dateTime;
       
   455 
       
   456     time.HomeTime();
       
   457     dateTime = time.DateTime();
       
   458 
       
   459     TBuf8<16> dateString;
       
   460 
       
   461     _LIT8(KFormatTxt,"%4d%02d%02d%02d%02d%02d%02d");
       
   462     dateString.Format(KFormatTxt,
       
   463                       dateTime.Year(),
       
   464                       dateTime.Month()+1, 
       
   465                       // Format the month as a TInt to preserve locale independence
       
   466                       dateTime.Day()+1, 
       
   467                       // Day and month ranges begin at zero (0-30 and 0-11), 
       
   468                       // so add one when formatting
       
   469                       dateTime.Hour(), dateTime.Minute(), dateTime.Second(), dateTime.MicroSecond()
       
   470                       );
       
   471 
       
   472     TPKISHA1Hash hash;
       
   473     CUtlMessageDigest* digester = TUtlCrypto::MakeMessageDigesterL(TUtlCrypto::EUtlMessageDigestSha1);   
       
   474     CleanupStack::PushL(digester);
       
   475     TPtrC8 hashValue = digester->Final(dateString);
       
   476     
       
   477     TBase64Codec base64Codec;    
       
   478     HBufC8* uniqueName8 = base64Codec.Base64EncodeLC(hashValue);
       
   479     TPtr8 uniqueName8Ptr = uniqueName8->Des();
       
   480 
       
   481     // Replace /
       
   482     for(TInt i = 0; i < uniqueName8->Length(); i++)
       
   483         {
       
   484         if(uniqueName8Ptr[i] == '/')
       
   485             {
       
   486             uniqueName8Ptr[i] = '_';
       
   487             }
       
   488         }
       
   489     
       
   490     HBufC* uniqueName = HBufC::NewL(uniqueName8->Length());
       
   491     uniqueName->Des().Copy(*uniqueName8);
       
   492     
       
   493     CleanupStack::PopAndDestroy(uniqueName8);  
       
   494     CleanupStack::PopAndDestroy(digester);  
       
   495             
       
   496     return uniqueName;
       
   497     }
       
   498 
       
   499 
       
   500 CCTKeyInfo::EKeyAlgorithm CKeyManager::ConvertPKIAlgorithm(TPKIKeyAlgorithm aAlg) const
       
   501     {
       
   502     CCTKeyInfo::EKeyAlgorithm algorithm = CCTKeyInfo::EInvalidAlgorithm;
       
   503 
       
   504     switch(aAlg)
       
   505         {
       
   506         case EPKIRSA:
       
   507             algorithm = CCTKeyInfo::ERSA;
       
   508             break;
       
   509         case EPKIDSA:
       
   510             algorithm = CCTKeyInfo::EDSA;
       
   511             break;
       
   512         case EPKIDH:
       
   513             algorithm = CCTKeyInfo::EDH;
       
   514             break;
       
   515         default:
       
   516             break;
       
   517         }
       
   518     return algorithm;
       
   519     }
       
   520 
       
   521 
       
   522 TInt CKeyManager::GetKeyIndex(TInt aUsedKeyStore, const RMPointerArray<CCTKeyInfo>& aKeysList) const
       
   523     {
       
   524     TInt i;
       
   525     for (i = 0; i < aKeysList.Count(); ++i)
       
   526         {
       
   527         if (aUsedKeyStore == STORETYPE_ANY_KEY_ID ||
       
   528             aUsedKeyStore == aKeysList[i]->Token().TokenType().Type().iUid)
       
   529             {
       
   530             break;
       
   531             }
       
   532         }
       
   533     if ( i >= aKeysList.Count())
       
   534         {                    
       
   535         i = KErrNotFound;
       
   536         }    
       
   537     
       
   538     return i;
       
   539     }