--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networksecurity/tlsprovider/source/tlsprovider/CTlsProvider.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,1644 @@
+// Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// CTlsProviderImpl.CPP
+//
+//
+
+#include <ecom/ecom.h>
+#include <securitydefsconst.h>
+#include <x520ava.h>
+
+#include "tlsprovider.h"
+#include "cryptostrength.h"
+
+
+//
+// CTlsProviderImpl
+//
+
+/**
+This method creates a new CTlsProviderImpl object
+@return Pointer to a new CTlsProviderImpl object is returned
+
+*/
+CTlsProviderImpl* CTlsProviderImpl::ConnectL()
+ {
+
+ CTlsProviderImpl* tPtr = new (ELeave)CTlsProviderImpl;
+ CleanupStack::PushL(tPtr);
+ tPtr->ConstructL();
+ tPtr->iTlsCryptoAttributes = CTlsCryptoAttributes::NewL();
+ CleanupStack::Pop();
+ return tPtr;
+ }
+
+
+CTlsProviderImpl::CTlsProviderImpl()
+ :CActive(0), iValidationStatus(EValidatedOK, 0), iTlsProviderPolicy(NULL)
+ {
+ if(CActiveScheduler::Current()) //Allready installed?
+ {
+ CActiveScheduler::Add( this );
+ }
+ }
+
+TInt CipherSuiteOrder(
+ const TTLSCipherSuite& aLeft,
+ const TTLSCipherSuite& aRight)
+ {
+ if((aLeft.iHiByte == aRight.iHiByte) && (aLeft.iLoByte == aRight.iLoByte))
+ return 1;
+ else
+ return 0;
+ }
+
+static TInt CompareCipherIdentities(
+ const TTLSCipherSuite& aLeft, const TTLSCipherSuite& aRight)
+/**
+ This ordering relation is used by CTlsProviderImpl::ReturnCipherListL
+ to ensure that cipher appears in a list at most once. (It will
+ also order the ciphers by identity, but that is incidental.)
+
+ It is used with a TLinearOrder template and an RArray.
+ It orders the ciphers by identity, which means iHiByte is the most
+ significant byte, and iLoByte is the least significant byte.
+
+ @param aLeft Left cipher suite to compare.
+ @param aRight Right cipher suite to compare.
+ @return <0 if the left cipher's identity is less
+ than the right cipher's; 0 if they are
+ the same; >0 otherwise.
+ @see CTlsProviderImpl::ReturnCipherListL
+ */
+ {
+ TInt leftHi = aLeft.iHiByte;
+ TInt leftLo = aLeft.iLoByte;
+ TInt leftIdentity = (leftHi << 8) | leftLo;
+
+ TInt rightHi = aRight.iHiByte;
+ TInt rightLo = aRight.iLoByte;
+ TInt rightIdentity = (rightHi << 8) | rightLo;
+
+ return leftIdentity - rightIdentity;
+ }
+
+
+static TInt CompareCipherPriorities(
+ const TTLSCipherSuite& aLeft, const TTLSCipherSuite& aRight)
+/**
+ This ordering relation is used by CTlsProviderImpl::ReturnCipherListL
+ to put the ciphers in priority order, highest priority first.
+ A higher priority means the numerically lower value of iPriority.
+ E.g. priority 1 is before priority 2.
+
+ It is wrapped in a TLinearOrder object and used to sort an RArray.
+
+ @param aLeft Left cipher suite to compare.
+ @param aRight Right cipher suite to compare.
+ @return <0 if the left cipher's priority is gt
+ the right cipher; 0 if they are the same;
+ >0 otherwise.
+
+ @see CTlsProviderImpl::ReturnCipherListL
+ */
+ {
+ const TTLSCipherSuiteMapping* cipherDetail = aLeft.CipherDetails();
+ TInt leftPri = (cipherDetail == NULL)? pri_unsupp: cipherDetail->iPriority;
+ cipherDetail = aRight.CipherDetails();
+ TInt rightPri = (cipherDetail == NULL)? pri_unsupp: cipherDetail->iPriority;
+
+ return leftPri - rightPri;
+ }
+
+
+/**
+The first call to CTlsProviderImpl takes place before ClientHello is sent,then as the handshake progresses,
+the information relevant for Provider and token will be gradually filled in a structure. This
+structure CTlsCryptoAttributes will be returned in this API, If the structure already exists,
+then the pointer to the same structure is returned.
+@param None
+@return Pointer to a CTlsCryptoAttributes structure
+@see CTlsCryptoAttributes
+*/
+CTlsCryptoAttributes* CTlsCryptoAttributes::NewL()
+ {
+ CTlsCryptoAttributes* tPtr = new (ELeave)CTlsCryptoAttributes;
+ CleanupStack::PushL(tPtr);
+ tPtr->iPublicKeyParams = new (ELeave)CTLSPublicKeyParams;
+ CleanupStack::Pop();
+ return tPtr;
+ }
+
+CTlsCryptoAttributes::CTlsCryptoAttributes()
+ {
+ }
+
+CTlsCryptoAttributes::~CTlsCryptoAttributes()
+ {
+ delete iPskIdentityHint;
+ iReqCertTypes.Close();
+ if(iPublicKeyParams)
+ delete iPublicKeyParams;
+ for ( TInt n = 0; n < iDistinguishedCANames.Count(); n++ )
+ {
+ HBufC8* buf = (HBufC8*)(iDistinguishedCANames[n]);
+ delete buf;
+ }
+ iDistinguishedCANames.Close();
+
+ delete iServerNames;
+ if(iServerDNFromCertSubject)
+ delete iServerDNFromCertSubject;
+ if(iServerDNFromCertIssuer)
+ delete iServerDNFromCertIssuer;
+ }
+
+CTlsCryptoAttributes* CTlsProviderImpl::Attributes()
+ {
+ return iTlsCryptoAttributes;
+ }
+
+
+CTlsSessionImpl* CTlsProviderImpl::TlsSessionPtr()
+ {
+ return iTlsSessionImpl;
+ }
+
+
+void CTlsProviderImpl::CreateL(
+ CTLSSession*& aTlsSession,
+ TRequestStatus& aStatus)
+ {
+ TInt Err = 0;
+ aStatus = KRequestPending;
+ iOriginalRequestStatus = &aStatus;
+ aTlsSession = 0;
+ iTlsSessionHldr = 0;
+ if(IsActive())
+ {
+ Err = KErrInUse;
+ }
+
+
+ if(iTlsCryptoAttributes)
+ {
+ if((iTlsCryptoAttributes->iSessionNameAndID.iSessionId.Length()) &&
+ (iTlsCryptoAttributes->iSessionNameAndID.iSessionId == iSessionData.iSessionId)
+ )
+ {
+ iSelectedTypeIndex = 0;
+ iAbbreviatedHandshake = ETrue;
+ }
+ else
+ {
+ iAbbreviatedHandshake = EFalse;
+
+ TIdentityRelation<TTLSCipherSuite> CipherOrder(CipherSuiteOrder);
+ if((iTlsCryptoAttributes->iNegotiatedProtocol != KTLS1_0) || (iTlsCryptoAttributes->iNegotiatedProtocol != KSSL3_0) )
+ Err = KErrSSLAlertIllegalParameter;
+ if(iSupportedCipherSuiteList.Count() &&
+ (iSupportedCipherSuiteList.Find((iTlsCryptoAttributes->iCurrentCipherSuite),CipherOrder) ==KErrNotFound))
+ Err = KErrSSLAlertIllegalParameter;
+ if(iTlsCryptoAttributes->iMasterSecretInput.iServerRandom.Size() != 32)
+ Err = KErrSSLAlertIllegalParameter;
+ if(!(
+ (iTlsCryptoAttributes->iMasterSecretInput.iServerRandom).Compare(iTlsCryptoAttributes->iMasterSecretInput.iClientRandom)
+ )
+ )
+ Err = KErrSSLAlertIllegalParameter;
+ if(!iTotalTokenTypeCount)
+ Err = KErrSSLAlertIllegalParameter;
+ }
+
+ }
+
+ if(Err != KErrNone || !iTlsCryptoAttributes)
+ {
+ User::RequestComplete(iOriginalRequestStatus, Err);
+ return;
+ }
+
+ iOriginalState = ECreate;
+ iTlsSessionHldr = &aTlsSession;
+ iSelectedTypeIndex = -1;
+
+ TBool TokenFound = EFalse;
+ if(!iAbbreviatedHandshake) //Full handshake
+ {
+ TokenFound = SelectToken();
+
+ if(!TokenFound) //No tokens supporting the selected cipher
+ {
+ User::RequestComplete(iOriginalRequestStatus, KErrCipherNotSupported);
+ }
+ else
+ {
+ if(iTlsCryptoAttributes->iClientAuthenticate)
+ {
+ //Before we initilize client authenticate, let's check if server
+ //provides us it's DN name
+ if(!iTlsCryptoAttributes->iDistinguishedCANames.Count())
+ {
+ //seems we need to use the server DN obtained from server cert as a backup
+ iTlsCryptoAttributes->iDistinguishedCANames.AppendL(iTlsCryptoAttributes->iServerDNFromCertSubject);
+ iTlsCryptoAttributes->iDistinguishedCANames.AppendL(iTlsCryptoAttributes->iServerDNFromCertIssuer);
+ iTlsCryptoAttributes->iServerDNFromCertSubject = NULL; //ownership handover
+ iTlsCryptoAttributes->iServerDNFromCertIssuer = NULL; //ownership handover
+ }
+
+ iClntAuthenticate = CTlsClntAuthenticate::NewL(*iTlsCryptoAttributes,
+ iEncodedServerCerts);
+ iCurrentState = EClientAuthenticate;
+
+ iStoredIntermediatesCACertificates.Reset();
+ iClntAuthenticate->DoClientAuthenticate(iSelectedCertInfo,
+ iSelectedKeyInfo,
+ &iStoredIntermediatesCACertificates,
+ iStatus);
+ SetActive();
+ }
+ else
+ {
+ // Get the session interface and create CtlsSession object
+ TLSPROV_LOG2(_L("Using (newly selected) token %d's provider interface"), iSelectedTypeIndex)
+ iPtrTokenSearch->GetSessionInterface(iListAllTokensAndTypes[iSelectedTypeIndex].iProviderInterface,
+ iSessionInterface,iStatus);
+ iCurrentState = EGetSessionInterface;
+ iStatus = KRequestPending;
+ SetActive();
+ }
+ }
+ }
+ else //Abbrevated handshake
+ {
+ iCurrentState = EGetSessionInterface;
+ iNextState = EConstructResumed;
+ iStatus = KRequestPending;
+ iPtrTokenSearch->GetSessionInterface(iSessionData.iProviderInterface,
+ iSessionInterface,iStatus);
+ SetActive();
+ }
+ return;
+ }
+
+void CTlsProviderImpl::GetSessionL(
+ TTLSServerAddr& aServerName,
+ TTLSSessionId& aSessionId,
+ TRequestStatus& aStatus)
+ {
+ aStatus = KRequestPending;
+ iOriginalRequestStatus = &aStatus;
+ if(IsActive())
+ {
+ User::RequestComplete(iOriginalRequestStatus, KErrInUse);
+ return;
+ }
+
+ iPServerName = &aServerName;
+ iOutputSessionData.iSessionId.Zero();
+ iPSessionId= &aSessionId;
+
+ if(iPtrTokenSearch)
+ iTotalTokenTypeCount = iPtrTokenSearch->TotalTypeCount();
+
+ iCurrentTokentype = 0;
+ iCurrentToken = 0;
+ iOriginalState = EGetSession;
+
+
+ if(!iTotalTokenTypeCount)
+ {
+ iCurrentState = EBrowseTokens;
+ iPtrTokenSearch = CTlsBrowseToken::NewL();
+ iStatus = KRequestPending;
+ iPtrTokenSearch->StartBrowsingL(iListAllTokensAndTypes,iStatus);
+ SetActive();
+ return;
+ }
+ else
+ RetrieveSession();
+
+ return;
+ }
+
+void CTlsProviderImpl::RetrieveSession()
+ {
+
+ while((iCurrentTokentype + 1) <= iListAllTokensAndTypes.Count())
+ {
+ iCurrentState = EGetSession;
+ iReqProtList.Reset();
+ if(iTlsCryptoAttributes)
+ {
+ if((iTlsCryptoAttributes->iProposedProtocol.iMajor !=0)
+ && (iTlsCryptoAttributes->iProposedProtocol.iMajor != 0))
+ {
+ iReqProtList.Append(iTlsCryptoAttributes->iProposedProtocol);
+ }
+ }
+ iStatus = KRequestPending;
+ iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface->GetSession(
+ ( (iOriginalState != EClearSessionCache)?(*iPServerName):(iServerNameAndId.iServerName)),
+ iReqProtList,
+ iOutputSessionData,iStatus);
+ SetActive();
+ return;
+ }
+ ReturnResult();
+ }
+
+
+
+void CTlsProviderImpl::CipherSuitesL(RArray<TTLSCipherSuite>& aUserCipherSuiteList,TRequestStatus& aStatus)
+ {
+
+ aStatus = KRequestPending;
+ iOriginalState = EGetCiphers;
+ iOriginalRequestStatus = &aStatus;
+ if(IsActive())
+ {
+ User::RequestComplete(iOriginalRequestStatus, KErrInUse);
+ return;
+ }
+
+ TLSPROV_LOG2(_L("Obtaining the list of ciphersuites %d"), iTotalTokenTypeCount)
+
+ iUserCipherSuiteList = &aUserCipherSuiteList;
+ aUserCipherSuiteList.Reset();
+
+ if(iPtrTokenSearch)
+ iTotalTokenTypeCount = iListAllTokensAndTypes.Count();
+
+ if(!iTotalTokenTypeCount)
+ {
+
+ iCurrentState = EBrowseTokens;
+ iStatus = KRequestPending;
+ iPtrTokenSearch = CTlsBrowseToken::NewL();
+ iPtrTokenSearch->StartBrowsingL(iListAllTokensAndTypes,iStatus);
+ SetActive();
+ return;
+ }
+ else
+ {
+ //we have the Token details already...so lets return the cipher list
+ TRAPD(err,ReturnCipherListL());
+ User::RequestComplete(iOriginalRequestStatus, err);
+ }
+ return;
+ }
+
+void CTlsProviderImpl::OnEBrowseTokens()
+ {
+ if ( iStatus == KErrNone )
+ {
+ if(iPtrTokenSearch)
+ iTotalTokenTypeCount = iListAllTokensAndTypes.Count();
+
+ switch(iOriginalState)
+ {
+ case EGetCiphers:
+ ReturnResult();
+ break;
+ case EGetSession:
+ case EClearSessionCache:
+ {
+ RetrieveSession();
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ else
+ {
+ User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
+ }
+ return;
+ }
+
+void CTlsProviderImpl::VerifyServerCertificate(
+ const TDesC8& aEncodedServerCerts,
+ CX509Certificate*& aServerCert,
+ TRequestStatus& aStatus)
+ {
+ aStatus = KRequestPending;
+ iOriginalRequestStatus = &aStatus;
+ if(IsActive())
+ {
+ User::RequestComplete(iOriginalRequestStatus, KErrInUse);
+ return;
+ }
+
+ TTime ValidationTime;
+ ValidationTime.UniversalTime();
+ iStatus = KRequestPending;
+ iX509ServerCert= &aServerCert;
+
+ iOriginalState = EValidateCertificate;
+
+ TRAPD(leaveValue,
+ iEncodedServerCerts=aEncodedServerCerts.AllocL();
+ (iCertVerificationResult= CPKIXValidationResult::NewL());
+ iServerCertsChain = CPKIXCertChain::NewL(iFs, aEncodedServerCerts,
+ TUid::Uid(KUidUnicodeSSLProtocolModule));
+
+ if ( iTlsProviderPolicy->PKICriticalExtensions() != 0 )
+ {
+ TLSPROV_LOG2(_L("Adding %d additionally Supported Critical Extensions"), iTlsProviderPolicy->PKICriticalExtensions())
+ iServerCertsChain->AddSupportedCriticalExtensionsL(iTlsProviderPolicy->GetPKICriticalExtensions());
+ }
+
+ iServerCertsChain->ValidateL(*iCertVerificationResult,ValidationTime,iStatus) );
+
+ if (leaveValue!=KErrNone)
+ {
+ delete iServerCertsChain;
+ iServerCertsChain = 0;
+ delete iEncodedServerCerts;
+ iEncodedServerCerts = 0;
+ iStatus = KErrNone;
+ User::RequestComplete(iOriginalRequestStatus, leaveValue);
+ }
+ else
+ {
+ iCurrentState = EValidateCertificate;
+ SetActive();
+ }
+
+ return;
+ }
+
+
+
+TBool CTlsProviderImpl::VerifySignatureL(
+ const CSubjectPublicKeyInfo& aServerPublicKey,
+ const TDesC8& aDigest,const TDesC8& aSignature)
+ {
+ TBool tempResult;
+ tempResult = EFalse;
+ switch(iTlsCryptoAttributes->isignatureAlgorithm)
+ {
+ case ERsaSigAlg:
+ {
+
+ //create an RSA public key object from the server certificate
+ CRSAPublicKey* rsaPublicKey = CX509RSAPublicKey::NewLC(aServerPublicKey.KeyData());
+
+ //create an RSA signature object from the signature buffer
+ RInteger sigInt = RInteger::NewL(aSignature);
+ CleanupStack::PushL(sigInt);
+ CRSASignature* rsaSignature = CRSASignature::NewL(sigInt);
+ CleanupStack::Pop(&sigInt); // Owned by rsaSignature
+ CleanupStack::PushL(rsaSignature);
+
+ //create a verifier with the server public key
+ CRSAPKCS1v15Verifier* Verifier = CRSAPKCS1v15Verifier::NewLC(*rsaPublicKey);
+
+ //verify the signature
+ tempResult = Verifier->VerifyL(aDigest, *rsaSignature);
+ CleanupStack::PopAndDestroy(3, rsaPublicKey);
+ }
+ break;
+ case EDsa:
+ {
+ //digest and signature are 8-bit descriptors
+ //create a DSA public key object from the server certificate
+ CDSAPublicKey* dsaPublicKey = CX509DSAPublicKey::NewL(aServerPublicKey.EncodedParams(),
+ aServerPublicKey.KeyData());
+
+ CleanupStack::PushL(dsaPublicKey);
+
+ //create verifier, verify sig
+ CDSAVerifier* verifier = CDSAVerifier::NewL(*dsaPublicKey);
+ CleanupStack::PushL(verifier);
+
+ //create DSA signature object from signature buffer
+ CDSASignature* dsaSignature = CX509DSASignature::NewLC(aSignature);
+
+ tempResult = verifier->VerifyL(aDigest, *dsaSignature);
+ CleanupStack::PopAndDestroy(3, dsaPublicKey);
+ }
+ break;
+ default:
+ break;
+ }
+
+ return tempResult;
+ }
+
+
+
+void CTlsProviderImpl::GenerateRandom(TDes8& aBuffer)
+ {
+ // Fill the buffer with zero bytes
+ aBuffer.SetLength(KTLSServerClientRandomLen);
+ aBuffer.Fill(0);
+
+ // The last 28 bytes should be filled with random data
+ TPtr8 random = aBuffer.MidTPtr(4);
+ TRAPD(errRandom,TRandom::RandomL(random));
+ if (errRandom)
+ {
+ aBuffer.SetLength(0);
+ return;
+ }
+
+ // The first 4 bytes should a unix timestamp.
+ TTime now;
+ now.UniversalTime();
+
+ _LIT(KEpoch,"19700000:");
+ TTime epoch(KEpoch);
+
+ TTimeIntervalSeconds timestamp;
+ TInt err = now.SecondsFrom(epoch, timestamp);
+
+ if (err == KErrNone)
+ {
+ TInt timestampInt = timestamp.Int();
+ aBuffer[0] = timestampInt >> 24;
+ aBuffer[1] = timestampInt >> 16;
+ aBuffer[2] = timestampInt >> 8;
+ aBuffer[3] = timestampInt;
+ }
+
+ }
+
+
+void CTlsProviderImpl::ClearSessionCacheL(
+ TTLSSessionNameAndID& aServerNameAndId,
+ TRequestStatus& aStatus)
+{
+ aStatus = KRequestPending;
+ iOriginalRequestStatus = &aStatus;
+ if(IsActive())
+ {
+ User::RequestComplete(iOriginalRequestStatus, KErrInUse);
+ return;
+ }
+
+ iServerNameAndId = aServerNameAndId;
+ iOriginalState = EClearSessionCache;
+ iOutputSessionData.iSessionId.Zero();
+
+
+ if(iPtrTokenSearch)
+ iTotalTokenTypeCount = iPtrTokenSearch->TotalTypeCount();
+
+ if(!iTotalTokenTypeCount)
+ {
+ iPtrTokenSearch = CTlsBrowseToken::NewL();
+ iCurrentState = EBrowseTokens;
+ iStatus = KRequestPending;
+ iPtrTokenSearch->StartBrowsingL(iListAllTokensAndTypes,iStatus);
+ SetActive();
+ return;
+ }
+ else
+ RetrieveSession();
+
+ return;
+}
+
+#ifdef _DEBUG
+
+void CTlsProviderImpl::Panic(CTlsProviderImpl::TPanic aPanic)
+/**
+ Halt the current thread with the panic category "TlsProvImpl"
+ and the supplied panic reason.
+
+ @param aPanic Panic reason.
+ */
+ {
+ _LIT(KPanicCat, "TlsProvImpl");
+ User::Panic(KPanicCat, aPanic);
+ }
+
+static TBool AreSuitesInPriorityOrder(const RArray<TTLSCipherSuite>& aSuites)
+/**
+ Predicate function determines whether the supplied array contains
+ cipher suites in priority order, highest-priority first.
+ (Higher priority suites have numerically lower iPriority fields.)
+
+ @param aSuites Array of cipher suites.
+ @return ETrue if the suites are in priority
+ order, EFalse otherwise.
+ */
+ {
+ TInt curSuite = aSuites.Count();
+ if (curSuite == 0)
+ return ETrue;
+
+ const TTLSCipherSuiteMapping* cipherDetail = aSuites[--curSuite].CipherDetails();
+ TInt nextPri = (cipherDetail == NULL)? pri_unsupp: cipherDetail->iPriority;
+ while (--curSuite >= 0)
+ {
+ cipherDetail = aSuites[curSuite].CipherDetails();
+ TInt curPri = (cipherDetail == NULL)? pri_unsupp: cipherDetail->iPriority;
+ if (nextPri < curPri)
+ return EFalse;
+ nextPri = curPri;
+ }
+
+ return ETrue;
+ }
+
+#endif // #ifdef _DEBUG
+
+TBool CTlsProviderImpl::IsCipherAvailable( const TTLSCipherSuiteMapping& aCipherSuiteMapping ) const
+{
+//this is a simplification that is allowable as DES_CBS & 3DES_CBS cipher ignore one & three bytes
+//respectively from the key material so the key length is in fact shorter than the computed one
+//but this still allows us to distinguish between strong & weak cipher suites...
+ TInt nKeyBits = aCipherSuiteMapping.iKeyMaterial * 8;
+ return aCipherSuiteMapping.iSupported && (TCrypto::Strength() == TCrypto::EStrong || nKeyBits <= 64);
+}
+
+
+void CTlsProviderImpl::ReturnCipherListL()
+ {
+
+ TInt aTotalTokenTypes = iListAllTokensAndTypes.Count();
+
+ iUserCipherSuiteList->Reset();
+ TLinearOrder<TTLSCipherSuite> CipherOrder(CompareCipherIdentities);
+
+ TLSPROV_LOG2(_L("CTlsProviderImpl::ReturnCipherListL %d"), aTotalTokenTypes)
+ TBool thisCipherSupportedByAToken = EFalse;
+
+ for (TInt CipherIndex = 0; CipherIndex < TLS_CIPHER_SUITES_NUMBER; ++CipherIndex)
+ {
+ const TTLSCipherSuiteMapping& mapping = KSetOfTLSCipherSuites[CipherIndex];
+ thisCipherSupportedByAToken = EFalse; // reset
+
+ if(! IsCipherAvailable(mapping))
+ continue;
+
+ // NULL encryption based ciphersuites are disallowed unless explicitly enabled
+ if( (! iTlsCryptoAttributes->iAllowNullCipherSuites) && (mapping.iBulkCiphAlg == ENullSymCiph))
+ {
+ continue;
+ }
+
+ // PSK key exchange ciphersuites are not usable unless PSK has been configured.
+ if((! iTlsCryptoAttributes->iPskConfigured) &&
+ ((mapping.iKeyExAlg==EPsk) || (mapping.iKeyExAlg==EDhePsk) || (mapping.iKeyExAlg==ERsaPsk)))
+ {
+ continue;
+ }
+
+ TLSPROV_LOG3(_L("cipher 0x%02x.0x%02x available"), mapping.iCipherSuite.iHiByte, mapping.iCipherSuite.iLoByte)
+
+ //offer just these matching the current crypto strength.
+ for (TInt i = 0; i < aTotalTokenTypes; i++) //For every Token type
+ {
+ CTokenInfo* tokenInfo = iListAllTokensAndTypes[i].iTokenInfo;
+
+ // check if this token contains the required key exchange and
+ // signature algorithms
+
+ TBool reqAlgs =
+ tokenInfo->aKeyExchAlgs.Find(mapping.iKeyExAlg) != KErrNotFound
+ && tokenInfo->aSignatureExchAlgs.Find(mapping.iSigAlg) != KErrNotFound;
+
+ if (! reqAlgs)
+ continue;
+
+ TLSPROV_LOG2(_L("token %d supports this cipher"), i)
+ thisCipherSupportedByAToken = ETrue;
+
+ // Add this cipher to the token's list of suites supported
+ if(tokenInfo->iCipherSuitesSupported.InsertInOrder(mapping.iCipherSuite,CipherOrder) == KErrNoMemory)
+ User::Leave(KErrNoMemory);
+ }
+
+ if (thisCipherSupportedByAToken)
+ {
+ // don't need to order the ciphers as they are sorted below
+ TLSPROV_LOG(_L("adding this cipher to iUserCipherSuiteList"))
+ iUserCipherSuiteList->AppendL(mapping.iCipherSuite);
+ }
+ }
+
+ // order the cipher suites by priority, highest-priority first.
+ const TLinearOrder<TTLSCipherSuite> priOrder(CompareCipherPriorities);
+ iUserCipherSuiteList->Sort(priOrder);
+
+ // also order the cipher suites stored with each token type
+ for (TInt j = aTotalTokenTypes - 1; j >= 0 ; --j)
+ {
+ CTokenInfo* tokenInfo = iListAllTokensAndTypes[j].iTokenInfo;
+ tokenInfo->iCipherSuitesSupported.Sort(priOrder);
+ }
+
+#ifdef _DEBUG
+ // Ensure suites are in priority order, as required for
+ // DEF063433 - TLS is sending CipherSuites in the wrong order
+
+ if (! AreSuitesInPriorityOrder(*iUserCipherSuiteList))
+ Panic(ERCLBadUserOrder);
+
+ for (TInt k = aTotalTokenTypes - 1; k >= 0 ; --k)
+ {
+ const CTokenInfo* tokenInfo = iListAllTokensAndTypes[k].iTokenInfo;
+ const RArray<TTLSCipherSuite>& suites = tokenInfo->iCipherSuitesSupported;
+ if (! AreSuitesInPriorityOrder(suites))
+ Panic(ERCLBadTokenOrder);
+ }
+#endif
+
+ TLSPROV_LOG(_L("Returning the list of ciphersuites"))
+ }
+
+void CTlsProviderImpl::ReturnSession()
+ {
+ if((iOutputSessionData.iSessionId).Length())
+ {
+ *iPSessionId = iOutputSessionData.iSessionId;
+ iPSessionId = 0;
+ }
+ User::RequestComplete(iOriginalRequestStatus, KErrNone);
+ }
+
+void CTlsProviderImpl::OnEGetSessionInterfaceL()
+ {
+
+ if(!iStatus.Int()) //Successfull, Session interface obtained
+ {
+ TLSPROV_LOG(_L("Session interface from token obtained successfully"))
+
+ iCurrentState = EStartSession;
+
+ //we can delete the token search object here
+ if(iPtrTokenSearch)
+ {
+ delete iPtrTokenSearch;
+ iPtrTokenSearch = 0;
+ }
+
+ iTlsSessionImpl = 0;
+ CTlsSessionImpl *newImpl = 0;
+ TRAPD(Kerr, ( newImpl = CTlsSessionImpl::NewL(
+ iSessionInterface,
+ iSelectedCertInfo,
+ iSelectedKeyInfo,
+ &iStoredIntermediatesCACertificates)
+ ) );
+
+ if(Kerr != KErrNone)
+ {
+ User::RequestComplete(iOriginalRequestStatus,Kerr);
+ return;
+ }
+
+ CleanupStack::PushL(newImpl);
+
+ if(iNextState == EConstructResumed)
+ {
+ iStatus = KRequestPending;
+ iCurrentState = iNextState;
+ newImpl->ConstructResumedL(iTlsCryptoAttributes,iStatus);
+ SetActive();
+ CleanupStack::Pop(newImpl);
+ iTlsSessionImpl = newImpl;
+ return;
+
+ }
+ else
+ {
+ iCurrentState = EConstruct;
+ iStatus = KRequestPending;
+ newImpl->ConstructL(iTlsCryptoAttributes,iEncodedServerCerts,iStatus);
+ SetActive();
+ CleanupStack::Pop(newImpl);
+ iTlsSessionImpl = newImpl;
+ return;
+ }
+ }
+ else //session interface not obtained..Dodgy token..release it
+ {
+ User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
+ }
+ }
+
+
+void CTlsProviderImpl::OnEGetSession()
+ {
+ if( (!iStatus.Int()) &&
+ ( (iOutputSessionData.iSessionId).Size())
+ )
+ {
+
+ TLSPROV_LOG(_L(" GetSession obtained successfully"))
+
+ if(iOriginalState == EClearSessionCache)
+ {
+ TBool result;
+ iStatus = KRequestPending;
+ iCurrentState = EClearSessionCache;
+ iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface->ClearSessionCache(iServerNameAndId.iServerName,
+ iServerNameAndId.iSessionId,result,iStatus);
+ SetActive();
+ return;
+ }
+
+ iSessionData.iSessionId = iOutputSessionData.iSessionId;
+ iSessionData.iProviderInterface = iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface;
+
+ if(iOriginalState == EGetSession )
+ {
+ //return the result here
+ ReturnSession();
+ return;
+ }
+ }
+ iCurrentTokentype++;
+ RetrieveSession();
+ return;
+ }
+
+
+void CTlsProviderImpl::RunL()
+{
+
+ switch(iCurrentState)
+ {
+
+ //Obtain Session Interface
+ case EGetSessionInterface:
+ {
+ OnEGetSessionInterfaceL();
+ }
+ break;
+
+ //Retrieving and clearing of Sesion cache
+ case EGetSession:
+ {
+ OnEGetSession();
+ }
+ break;
+
+ case EClearSessionCache:
+ {
+ if(!iStatus.Int())
+ {
+ if((iSessionData.iSessionId).Compare(iOutputSessionData.iSessionId) ==0)
+ {
+ (iSessionData.iSessionId).Zero();
+ }
+ }
+ User::RequestComplete(iOriginalRequestStatus,iStatus.Int());
+ }
+ break;
+
+ //Abbreviated handshake
+ case EConstructResumed:
+ {
+ if(iStatus.Int() != KErrNone)
+ {
+ delete iTlsSessionImpl;
+ iTlsSessionImpl = NULL;
+ }
+ *iTlsSessionHldr = CTLSSession::NewL(iTlsSessionImpl);
+ iTlsSessionOwnershipPassedToCaller = ETrue;
+ User::RequestComplete(iOriginalRequestStatus,iStatus.Int());
+ return;
+ }
+
+ //Full handshake
+ case EConstruct:
+ {
+ iEncodedServerCerts = 0; //Owned by CTLSSession
+ if(iStatus.Int() != KErrNone)
+ {
+ delete iTlsSessionImpl;
+ iTlsSessionImpl = NULL;
+ }
+ *iTlsSessionHldr = CTLSSession::NewL(iTlsSessionImpl);
+ iTlsSessionOwnershipPassedToCaller = ETrue;
+ User::RequestComplete(iOriginalRequestStatus,iStatus.Int());
+ return;
+ }
+
+ //To obtain client certificate
+ case EClientAuthenticate:
+ {
+ delete iClntAuthenticate;
+ iClntAuthenticate = 0;
+
+ iCurrentState = EGetSessionInterface;
+ iNextState = EStartSession;
+ iStatus = KRequestPending;
+
+ // Iterate through tokens, GetSessionInterface() for this token if pointers match
+ for(TInt i=0; i< iListAllTokensAndTypes.Count(); i++)
+ {
+ MCTToken* tempPtr = &(iListAllTokensAndTypes[i].iProviderInterface->Token());
+ if(iSelectedKeyInfo && (tempPtr == &(iSelectedKeyInfo->Token())))
+ {
+ TLSPROV_LOG(_L("EClientAuthenticate: iSelectedKeyInfo->Token() valid; reusing this token interface"))
+ // Keep existing selected token
+ iPtrTokenSearch->GetSessionInterface(iListAllTokensAndTypes[i].iProviderInterface, iSessionInterface,iStatus);
+ SetActive();
+ return;
+ }
+ }
+
+ // Otherwise, have already selected (potentially new) token in call to SelectToken()
+ // in previous state. Use iSelectedTypeIndex in call to GetSessionInterface()
+ TLSPROV_LOG2(_L("EClientAuthenticate: Using (newly selected) token %d's provider interface"), iSelectedTypeIndex)
+ iPtrTokenSearch->GetSessionInterface(iListAllTokensAndTypes[iSelectedTypeIndex].iProviderInterface,
+ iSessionInterface,iStatus);
+ SetActive();
+ }
+ break;
+
+ case EQueryCache:
+ {
+ OnQueryCacheL();
+ }
+ break;
+
+ case EUserDialog:
+ {
+ OnEUserDialogL();
+ }
+ break;
+
+ case EValidateCertificate:
+ {
+ User::LeaveIfError(iStatus.Int());
+
+ //We set iServerDNFromCert in case server doesn't
+ //give us DistingshedName in CertificateRequest Message.
+ if(iValidationStatus.iReason == EValidatedOK)
+ {
+ TInt serverCertChainLength = iServerCertsChain->Count();
+ TLSPROV_LOG2(_L("EValidateCertificate iServerCertsChain length = %d"), serverCertChainLength);
+ CX509Certificate* cert = CX509Certificate::NewL(iServerCertsChain->Cert(serverCertChainLength-1));
+ CleanupStack::PushL(cert);
+ iTlsCryptoAttributes->iServerDNFromCertIssuer = cert->DataElementEncoding(CX509Certificate::EIssuerName)->AllocL();
+ iTlsCryptoAttributes->iServerDNFromCertSubject = cert->DataElementEncoding(CX509Certificate::ESubjectName)->AllocL();
+ CleanupStack::PopAndDestroy(cert);
+
+ }
+ delete iServerCertsChain;
+ iServerCertsChain = 0;
+ iValidationStatus = iCertVerificationResult->Error();
+ delete iCertVerificationResult;
+ iCertVerificationResult = 0;
+ TBool acceptCert = EFalse;
+ GetX509CertL(iEncodedServerCerts,*iX509ServerCert);
+
+ if (iValidationStatus.iReason == EValidatedOK)
+ {
+
+ // If the certificate is fine, check whether the server name matches
+ // the site the certificate was issued to.
+
+ if (iTlsCryptoAttributes->idomainName.Length() != 0) // skip the check if domain name is unset.
+ {
+ acceptCert = ValidateDNSNameL(**iX509ServerCert);
+ }
+ else
+ {
+ acceptCert = ETrue;
+ }
+
+ if(acceptCert)
+ {
+ acceptCert = CheckExtendedKeyUsageL(**iX509ServerCert);
+ if(!acceptCert)
+ {
+ iValidationStatus.iReason = ECriticalExtendedKeyUsage;
+ }
+ }
+ }
+
+ if(acceptCert)
+ {
+ TLSPROV_LOG(_L("Server Certificate verified successfully"))
+ iCurrentState = iOriginalState = ENullState;
+ User::RequestComplete(iOriginalRequestStatus,KErrNone);
+ }
+ else
+ {
+ if(iTlsCryptoAttributes && iTlsCryptoAttributes->iDialogNonAttendedMode)
+ {
+ TLSPROV_LOG(_L("Server Certificate validation failed but in DialogNonAttended mode"))
+ TInt err(0);
+
+ switch(iValidationStatus.iReason)
+ {
+ case EChainHasNoRoot:
+ err = KErrSSLAlertUnknownCA;
+ break;
+ case EDateOutOfRange:
+ err = KErrSSLAlertCertificateExpired;
+ break;
+ case ECertificateRevoked:
+ err = KErrSSLAlertCertificateRevoked;
+ break;
+ case ECriticalExtendedKeyUsage:
+ err = KErrSSLAlertUnsupportedCertificate;
+ break;
+ default:
+ err = KErrSSLAlertIllegalParameter;
+ break;
+ }
+
+ iCurrentState = iOriginalState = ENullState;
+ User::RequestComplete(iOriginalRequestStatus,err);
+ }
+ else
+ {
+
+ User::LeaveIfError(iCacheClient.Open(**iX509ServerCert));
+ HandleBadCertificateL(iValidationStatus);
+
+ }
+ }
+
+ }
+ break;
+ //Obtain interface form all tokens supproted
+ case EBrowseTokens:
+ OnEBrowseTokens();
+ break;
+ BULLSEYE_OFF
+ default:
+ {
+ TLSPROV_LOG(_L("PANIC: in Default state of the state machine..cant happen"))
+ }
+ break;
+ BULLSEYE_RESTORE
+ }
+
+}
+
+TBool CTlsProviderImpl::CheckExtendedKeyUsageL(const CX509Certificate& aCert)
+ {
+ TBool result(ETrue);
+
+ const CX509CertExtension* ext = aCert.Extension(KExtendedKeyUsage);
+ if (ext)
+ {
+ result = EFalse;
+ CX509ExtendedKeyUsageExt* extendedKeyUsage = CX509ExtendedKeyUsageExt::NewLC(ext->Data());
+ const CArrayPtrFlat<HBufC>& usages = extendedKeyUsage->KeyUsages();
+
+ for (TInt k = 0; k < usages.Count(); k++)
+ {
+ if (usages[k]->Compare(KServerAuthOID) == 0)
+ {
+ result = ETrue;
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy(); // Cannot leave before we get here
+ }
+
+ return result;
+ }
+
+void CTlsProviderImpl::HandleBadCertificateL(const TValidationStatus aResult)
+ {
+ TCacheEntryState entryState = iCacheClient.GetStateL();
+
+ switch (entryState)
+ {
+ case ENewEntry:
+ // Show dialog
+ ShowUntrustedDialogL(aResult);
+ break;
+
+ case EEntryAwaitingApproval:
+ // Request notification on status change
+ iCurrentState = EQueryCache;
+ iCacheClient.RequestNotify(iStatus);
+ SetActive();
+ break;
+
+ case EEntryDenied:
+ iCurrentState = iOriginalState = ENullState;
+ User::RequestComplete(iOriginalRequestStatus,KErrAbort);
+ break;
+
+ case EEntryApproved:
+ iCurrentState = iOriginalState = ENullState;
+ User::RequestComplete(iOriginalRequestStatus,KErrNone);
+ break;
+
+ }
+ }
+
+void CTlsProviderImpl::ShowUntrustedDialogL(const TValidationStatus aResult)
+ {
+ iCurrentState = EUserDialog;
+#ifdef _USESECDLGSV_
+ TLSPROV_LOG(_L("Server Certificate validation failed old dialog"))
+ User::LeaveIfError( iDialogServ.Connect() );
+ iDialogServ.DisplayCertNotTrustedDlg(iProceed, **iX509ServerCert, iStatus);
+#else
+ TLSPROV_LOG(_L("Server Authentication Failure New dialog"))
+ iSecurityDialog = SecurityDialogFactory::CreateL();
+ iStatus = KRequestPending;
+ TPtrC8 encodedCert(iEncodedServerCerts->Des());
+ // Calls Server authentication failure dialog box
+ iSecurityDialog->ServerAuthenticationFailure(iTlsCryptoAttributes->idomainName,aResult.iReason,encodedCert,iStatus );
+#endif
+ SetActive();
+ }
+
+CTlsProviderImpl::~CTlsProviderImpl()
+ {
+ Cancel();
+
+ if ( iTlsProviderPolicy )
+ {
+ delete iTlsProviderPolicy;
+ iTlsProviderPolicy = NULL;
+ }
+
+#if !defined(_USESECDLGSV_)
+ if(iSecurityDialog)
+ {
+ iSecurityDialog->Release();
+ }
+#endif
+ iReqProtList.Close();
+
+ if((!iTlsSessionOwnershipPassedToCaller) && (iTlsSessionImpl))
+ {
+ // We have created a CTlsSessionImpl (which now owns iSelectedCertInfo etc)
+ // BUT the CTLSSession create failed so we still own the CTlsSessionImpl and
+ // are still responsible for deleting it.
+ delete iTlsSessionImpl;
+ iTlsSessionImpl = 0;
+ }
+ else
+ {
+ if(iTlsSessionImpl == NULL) //Session object not created
+ {
+ if(iSelectedCertInfo)
+ iSelectedCertInfo->Release();
+
+ if(iSelectedKeyInfo)
+ iSelectedKeyInfo->Release();
+
+ if(iSessionInterface)
+ iSessionInterface->Release();
+
+ if(iTlsCryptoAttributes)
+ delete iTlsCryptoAttributes;
+
+ if(iEncodedServerCerts)
+ delete iEncodedServerCerts;
+ }
+ }
+
+ if(iServerCertsChain)
+ {
+ delete iServerCertsChain;
+ iServerCertsChain = NULL;
+ }
+
+ delete iCertVerificationResult;
+ iCertVerificationResult = NULL;
+
+ if(iPtrTokenSearch)
+ {
+ delete iPtrTokenSearch;
+ iPtrTokenSearch = NULL;
+ }
+
+ TInt count = iListAllTokensAndTypes.Count();
+ TInt i(0);
+
+ while(i<count)
+ {
+ iListAllTokensAndTypes[i].Release();
+ i++;
+ }
+
+ // clear the intermediate certificates
+ TInt certCount = iStoredIntermediatesCACertificates.Count();
+ for (TInt i = 0; i < certCount; i++)
+ {
+ CX509Certificate *x509Cert = (CX509Certificate*)(iStoredIntermediatesCACertificates[i]);
+ delete x509Cert;
+ }
+ iStoredIntermediatesCACertificates.Reset();
+
+ iListAllTokensAndTypes.Close();
+ if(iClntAuthenticate)
+ delete iClntAuthenticate;
+
+ iCacheClient.Close();
+
+ iFs.Close();
+ REComSession::FinalClose();
+ }
+
+
+
+void CTlsProviderImpl::CancelRequest()
+ {
+ if(IsActive())
+ Cancel();
+ }
+
+void CTlsProviderImpl::DoCancel()
+ {
+ switch(iCurrentState)
+ {
+
+ case EGetSessionInterface:
+ {
+ iPtrTokenSearch->CancelRequest();
+ break;
+ }
+ case EGetCiphers:
+ {
+ if(iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface)
+ iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface->CancelCryptoCapabilities();
+ }
+ break;
+ case EGetSession:
+ {
+ if(iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface)
+ iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface->CancelGetSession();
+ }
+ break;
+ case EClearSessionCache:
+ {
+ if(iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface)
+ iListAllTokensAndTypes[iCurrentTokentype].iProviderInterface->CancelClearSessionCache();
+ }
+ break;
+ case EConstruct:
+ case EConstructResumed:
+ {
+ if(iTlsSessionImpl)
+ iTlsSessionImpl->CancelRequest();
+ }
+ break;
+
+ case EValidateCertificate:
+ {
+ if(iServerCertsChain)
+ iServerCertsChain->CancelValidate();
+
+ }
+ break;
+ case EBrowseTokens:
+ {
+ if(iPtrTokenSearch)
+ iPtrTokenSearch->CancelRequest();
+ }
+ break;
+
+ case EQueryCache:
+ {
+ iCacheClient.Cancel();
+ }
+ break;
+
+ case EUserDialog:
+ {
+#ifdef _USESECDLGSV_
+ iDialogServ.Cancel();
+#else
+ iSecurityDialog->Cancel();
+#endif
+ }
+ break;
+
+ default:
+ break;
+ }
+ iCurrentState = ENullState;
+
+ User::RequestComplete(iOriginalRequestStatus, KErrCancel);
+
+ return;
+ }
+
+
+void CTlsProviderImpl::ReturnResult()
+ {
+ switch(iOriginalState)
+ {
+ case EGetCiphers:
+ {
+ iCurrentTokentype= 0;
+ TRAPD(err,ReturnCipherListL());
+ if(err != KErrNone)
+ {
+ iUserCipherSuiteList->Reset();
+ }
+ User::RequestComplete(iOriginalRequestStatus, err);
+ }
+ break;
+ case EGetSession:
+ {
+ iCurrentTokentype= 0;
+ ReturnSession();
+ }
+ break;
+ case EClearSessionCache:
+ {
+ User::RequestComplete(iOriginalRequestStatus, iStatus.Int());
+ }
+ break;
+ BULLSEYE_OFF
+ default:
+ {
+ //Not possible......Log him anyway
+ }
+ break;
+ BULLSEYE_RESTORE
+ }
+ iCurrentState = ENullState;
+ }
+
+
+void CTlsProviderImpl::OnQueryCacheL()
+ {
+ HandleBadCertificateL(iValidationStatus);
+ }
+
+void CTlsProviderImpl::OnEUserDialogL()
+ {
+ TCacheEntryState entryStatus;
+#ifdef _USESECDLGSV_
+ entryStatus = iProceed ? EEntryApproved : EEntryDenied;
+#else
+ entryStatus = iStatus.Int() == KErrNone ? EEntryApproved : EEntryDenied;
+#endif
+
+ iCacheClient.SetStateL(entryStatus);
+ User::RequestComplete(iOriginalRequestStatus, entryStatus == EEntryApproved ? KErrNone : KErrAbort);
+ iCurrentState = iOriginalState = ENullState;
+ }
+
+TBool CTlsProviderImpl::SelectToken()
+ {
+ TLSPROV_LOG(_L("In CTlsProviderImpl::SelectToken()"))
+ if(iSelectedTypeIndex == -1)
+ {
+ TIdentityRelation<TTLSCipherSuite> CipherOrder(CipherSuiteOrder);
+ TInt selectedSoftwareToken = -1;
+ TInt selectedHardwareToken = -1;
+ TBool foundToken = EFalse;
+
+ // Iterate through all tokens; pick a supported token
+ TInt total = iListAllTokensAndTypes.Count();
+ for(TInt i = 0; i < total; i++)
+ {
+ TLSPROV_LOG3(_L("token %d supports %d total ciphers"),
+ i, iListAllTokensAndTypes[i].iTokenInfo->iCipherSuitesSupported.Count())
+ if ((iListAllTokensAndTypes[i].iTokenInfo)->iCipherSuitesSupported.Find(
+ iTlsCryptoAttributes->iCurrentCipherSuite, CipherOrder) != KErrNotFound)
+ {
+ // Select the first valid token found (from zero upwards)
+ foundToken = ETrue;
+ if (iListAllTokensAndTypes[i].iSoftwareToken && selectedSoftwareToken == -1)
+ selectedSoftwareToken = i;
+
+ if (! iListAllTokensAndTypes[i].iSoftwareToken && selectedHardwareToken == -1)
+ selectedHardwareToken = i;
+ }
+
+ // No need to continue if we've found a hardware token, otherwise keep
+ // searching, since there might be a hardware token later in the search
+ // and this should always be used in preference to a software token
+ if (selectedHardwareToken != -1)
+ break;
+ }
+
+ if (foundToken == EFalse)
+ {
+ TLSPROV_LOG(_L("Didn't find a suitable token for this cipher"))
+ return EFalse;
+ }
+
+ // Prefer a hardware token
+ if (selectedHardwareToken != -1)
+ {
+ iSelectedTypeIndex = selectedHardwareToken;
+ TLSPROV_LOG2(_L("Hardware Token %d selected"), iSelectedTypeIndex)
+ }
+ else
+ {
+ iSelectedTypeIndex = selectedSoftwareToken;
+ TLSPROV_LOG2(_L("Software Token %d selected"), iSelectedTypeIndex)
+ }
+ }
+
+ return ETrue;
+ }
+
+
+/*The following function gets the encoded certificate and converts it into
+an x509 object..Only called from a direct secure socket API call
+*/
+void CTlsProviderImpl::GetX509CertL(HBufC8*& aEncodedCert,CX509Certificate*& aOutputX509)
+ {
+ if(aEncodedCert)
+ {
+ TLSPROV_LOG(_L("CTlsProviderImpl::GetX509CertL"))
+ CPKIXCertChain* CertsChain = CPKIXCertChain::NewLC(iFs,aEncodedCert->Des(),
+ TUid::Uid(KUidUnicodeSSLProtocolModule));
+ if(CertsChain->Count())
+ {
+ TLSPROV_LOG(_L("CX509Certificate::NewL"))
+ aOutputX509 = CX509Certificate::NewL(CertsChain->Cert(0));
+ }
+ CleanupStack::PopAndDestroy(CertsChain);
+ }
+ }
+
+TBool CTlsProviderImpl::ValidateDNSNameL(const CX509Certificate& aSource)
+ {
+ TBool ret = EFalse;
+ TBool hasAltNameExt = EFalse;
+
+ // Get a unicode descriptor with the server DNS name
+ HBufC* server = HBufC::NewLC(iTlsCryptoAttributes->idomainName.Length());
+ TPtr des = server->Des();
+ des.Copy(iTlsCryptoAttributes->idomainName);
+
+ // and contruct a domain name from it
+ CX509DNSName* serverDns = CX509DNSName::NewLC(*server);
+ CX509DNSName* dNS = NULL;
+
+ // try fetch Alt Name first (see RFC 2595)
+ const CX509CertExtension* ext = aSource.Extension(KSubjectAltName);
+ if (ext)
+ {
+ CX509AltNameExt* subjectAltName = CX509AltNameExt::NewLC(ext->Data());
+ const CArrayPtrFlat<CX509GeneralName>& gNs = subjectAltName->AltName();
+ TInt count = gNs.Count();
+
+ for (TInt i = 0; i < count; i++)
+ {
+ const CX509GeneralName* gN = gNs.At(i);
+ if (gN->Tag() == EX509DNSName)
+ {
+ hasAltNameExt = ETrue;
+
+ // wildcards are allowed at every part of DNS name
+ // e.g. "foo.example.com" would be validated
+ // against cert "foo.*.com", even though RFC 2595 states:
+ // "A '*' wildcard character MAY be used as the left-most name
+ // component in the certificate"
+ TBool wildcard = (gN->Data().Locate('*') > KErrNotFound);
+ dNS = CX509DNSName::NewL(gN->Data());
+
+ // Check if the server matches this cert name
+ if (NameIsInSubtree(*serverDns, *dNS, wildcard))
+ {
+ ret = ETrue;
+ }
+
+ delete dNS;
+ if ( ret )
+ break;
+ }
+ }
+ CleanupStack::PopAndDestroy(subjectAltName);
+ }
+
+ // if the certificate has an alternative name extension, with DNS entries, ignore the common name
+ if(!hasAltNameExt)
+ {
+ // no name yet lets try common name from Subject
+ HBufC* commonName = aSource.SubjectName().ExtractFieldL(KX520CommonName);
+ if(commonName)
+ {
+ CleanupStack::PushL(commonName);
+ TPtr name = commonName->Des();
+ // check for wildcard, we consider it only if left-most name component (see RFC 2595)
+ TBool wildcard = EFalse;
+ if(0 == name.Locate('*'))
+ {
+ // wildcard as the left-most part,
+ // lets return the name without it...
+ // Do NOT remove the '.' otherwise DNS name "example.com" would validate
+ // against cert "*.example.com" and that's not correct
+ name = name.Mid(1);
+ wildcard = ETrue;
+ }
+ dNS = CX509DNSName::NewL(name);
+ ret = NameIsInSubtree(*serverDns, *dNS, wildcard);
+ delete dNS;
+ CleanupStack::PopAndDestroy(commonName);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(2, server);
+ return ret;
+ }
+
+TBool CTlsProviderImpl::NameIsInSubtree(CX509DNSName& aServerName, CX509DNSName& aCertName, TBool aIsWildcard)
+ {
+ return (aServerName.IsWithinSubtree(aCertName) &&
+ (aIsWildcard || (aCertName.Name().Length() == aServerName.Name().Length())));
+ }
+
+TInt CTlsProviderImpl::RunError(TInt aError)
+ {
+
+ if (iCurrentState == EUserDialog)
+ {
+ // Treat this as denied
+ // ignore any problems writing this entry to disk
+ TRAP_IGNORE(iCacheClient.SetStateL(EEntryDenied));
+ }
+
+ User::RequestComplete(iOriginalRequestStatus, aError);
+ return KErrNone;
+ }
+
+
+MCTToken* CTlsProviderImpl::GetTokenHandle()
+ {
+
+ if(iListAllTokensAndTypes.Count() > iSelectedTypeIndex && iSelectedTypeIndex >=0 )
+ {
+ CTokenTypesAndTokens& Tokens = iListAllTokensAndTypes[iSelectedTypeIndex];
+ if ( Tokens.iProviderInterface )
+ {
+ MCTToken& tempPtr = Tokens.iProviderInterface->Token();
+ iListAllTokensAndTypes[iSelectedTypeIndex].iProviderInterface->Release();
+ iListAllTokensAndTypes[iSelectedTypeIndex].iProviderInterface = 0;
+ return &tempPtr;
+ }
+ }
+ return NULL;
+ }
+
+void CTokenTypesAndTokens::Release()
+ {
+ if(iProviderInterface)
+ {
+ MCTToken& tempPtr = iProviderInterface->Token();
+ iProviderInterface->Release(); //Release provider interface
+ tempPtr.Release(); //Release token
+ iProviderInterface = 0;
+ }
+ if(iTokenInfo)
+ {
+ iTokenInfo->Close();
+ delete iTokenInfo;
+ }
+
+ }
+
+CTokenTypesAndTokens::~CTokenTypesAndTokens()
+ {
+ Release();
+ }
+
+void CTokenInfo::Close()
+ {
+ aKeyExchAlgs.Close();
+ aSignatureExchAlgs.Close();
+ iCipherSuitesSupported.Close();
+ iSupportedProtocols.Close();
+ }
+
+CTokenInfo::~CTokenInfo()
+ {
+ Close();
+ }
+
+void CTlsProviderImpl::ConstructL()
+ {
+ User::LeaveIfError(iFs.Connect());
+
+ TLSPROV_LOG(_L("Creating a newer instance of TlsProviderPolicy"))
+ iTlsProviderPolicy = CTlsProviderPolicy::NewL();
+ }
+
+CTLSPublicKeyParams::~CTLSPublicKeyParams()
+ {
+ delete iValue1;
+ delete iValue2;
+ delete iValue3;
+ delete iValue4;
+ delete iValue5;
+ }