networksecurity/tls/protocol/tlsconnection.cpp
changeset 0 af10295192d8
child 6 c64cefac6e99
equal deleted inserted replaced
-1:000000000000 0:af10295192d8
       
     1 // Copyright (c) 2003-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // SSL3.0 and TLS1.0 Connection source file.
       
    15 // Describes the implementation of a secure (SSL/TLS) connection.
       
    16 // 
       
    17 //
       
    18 
       
    19 /**
       
    20  @file
       
    21 */
       
    22   
       
    23 #include "tlsconnection.h"
       
    24 #include "recordprotocolevents.h"
       
    25 #include "tlshandshake.h"
       
    26 #include "applicationdata.h"
       
    27 #include <es_sock.h>
       
    28 #include <in_sock.h>
       
    29 
       
    30 #ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
       
    31 #include <ssl_internal.h>
       
    32 #endif
       
    33 
       
    34 
       
    35 EXPORT_C MSecureSocket* CTlsConnection::NewL(RSocket& aSocket, const TDesC& aProtocol)
       
    36 /**
       
    37  * Creates and initialises a new CTlsConnection object.
       
    38  * 
       
    39  * @param aSocket is a reference to an already open and connected socket.
       
    40  * @param aProtocol is a descriptor containing the name of the protocol (SSL3.0 or 
       
    41  * TLS1.0) the application specified when the secure socket was created.
       
    42  * @return A pointer to a newly created Secure socket object.
       
    43  */
       
    44 {
       
    45 	LOG(Log::Printf(_L("CTlsConnection::NewL(RSocket,Protocol)"));)
       
    46 	CTlsConnection* self = new(ELeave) CTlsConnection();
       
    47   	LOG(Log::Printf(_L("self %x - %x"), self, (TUint)self + sizeof( CTlsConnection ));)
       
    48 
       
    49 #ifdef _DEBUG
       
    50    TInt nBlock;
       
    51   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
    52 #endif
       
    53 
       
    54 	CleanupStack::PushL(self);
       
    55 	self->ConstructL(aSocket, aProtocol);
       
    56 	CleanupStack::Pop();
       
    57 	return self;
       
    58 }
       
    59 
       
    60 EXPORT_C MSecureSocket* CTlsConnection::NewL(MGenericSecureSocket& aSocket, const TDesC& aProtocol)
       
    61 /**
       
    62  * Creates and initialises a new CTlsConnection object.
       
    63  * 
       
    64  * @param aSocket is a reference to socket like object derived from MGenericSecureSocket.
       
    65  * @param aProtocol is a descriptor containing the name of the protocol (SSL3.0 or 
       
    66  * TLS1.0) the application specified when the secure socket was created.
       
    67  * @return A pointer to a newly created Secure socket object.
       
    68  */
       
    69 {
       
    70 	LOG(Log::Printf(_L("CTlsConnection::NewL(GenericSocket,Protocol)"));)
       
    71 	CTlsConnection* self = new(ELeave) CTlsConnection();
       
    72   	LOG(Log::Printf(_L("self %x - %x"), self, (TUint)self + sizeof( CTlsConnection ));)
       
    73 
       
    74 #ifdef _DEBUG
       
    75    TInt nBlock;
       
    76   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
    77 #endif
       
    78 
       
    79 	CleanupStack::PushL(self);
       
    80 	self->ConstructL(aSocket, aProtocol);
       
    81 	CleanupStack::Pop();
       
    82 	return self;
       
    83 }
       
    84 
       
    85 EXPORT_C void CTlsConnection::UnloadDll(TAny* /*aPtr*/)
       
    86 /**
       
    87  Function called prior to unloading DLL.  
       
    88  Does nothing in this implementation but is needed to be exported.
       
    89  */
       
    90 {
       
    91 	LOG(Log::Printf(_L("CTlsConnection::UnloadDll()"));)
       
    92 }
       
    93 
       
    94 CTlsConnection::~CTlsConnection()
       
    95 /**
       
    96  * Destructor.
       
    97  * The user should ensure that the connection has been closed before destruction,
       
    98  * as there is no check for any pending asynch event here (apart from the panic 
       
    99  * in ~CActive).
       
   100  */
       
   101 {
       
   102 	LOG(Log::Printf(_L("CTlsConnection::~CTlsConnection()"));)
       
   103 
       
   104 #ifdef _DEBUG
       
   105    TInt nBlock;
       
   106   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
   107 #endif
       
   108 	DeleteStateMachines();
       
   109 
       
   110 	delete iRecordParser; //don't change the order of the deletion (see ~CRecordParser & CRecordParser:;Reset)
       
   111 	delete iRecordComposer;
       
   112 	delete iGenericSocket;
       
   113 	delete iClientCert;
       
   114 	delete iServerCert;
       
   115 #ifdef _DEBUG
       
   116   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
   117 #endif
       
   118 	delete iTlsProvider;
       
   119 	delete iTlsSession; 
       
   120 #ifdef _DEBUG
       
   121   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
   122 #endif
       
   123 }
       
   124 
       
   125 CTlsConnection::CTlsConnection() : CActive( EPriorityHigh )
       
   126 /**
       
   127  * Constructor .
       
   128  * Sets the Active object priority.
       
   129  */
       
   130 {
       
   131 }
       
   132 
       
   133 void CTlsConnection::ConstructL(RSocket& aSocket, const TDesC& aProtocol)
       
   134 /** 
       
   135  * Two-phase constructor.
       
   136  * Called by CTlsConnection::NewL() to initialise all the 
       
   137  * CTlsConnection objects (bar the State machines). It also sets the 
       
   138  * protocol for the connection. The Provider interface is created and the Session
       
   139  * interface pointer is set to NULL (as no session currently exists).
       
   140  * The dialog mode for the connection is set to Attended mode (default) and the current 
       
   141  * cipher suite is set to [0x00],[0x00].
       
   142  *
       
   143  * @param aSocket is a reference to an already open and connected socket.
       
   144  * @param aProtocol is a descriptor containing the name of the protocol (SSL3.0 or 
       
   145  * TLS1.0) the application specified when the secure socket was created.
       
   146  */
       
   147 {
       
   148 	LOG(Log::Printf(_L("CTlsConnection::ConstructL(RSocket,Protocol)"));)
       
   149 
       
   150 	CActiveScheduler::Add(this);		
       
   151 
       
   152 	iTlsProvider = CTLSProvider::ConnectL();		// Set up Security/crypto interfaces
       
   153 
       
   154 	User::LeaveIfError( SetProtocol(aProtocol) );
       
   155 	iTlsProvider->Attributes()->iCurrentCipherSuite.iLoByte = 0x00;
       
   156 	iTlsProvider->Attributes()->iCurrentCipherSuite.iHiByte = 0x00;
       
   157 	iTlsProvider->Attributes()->iDialogNonAttendedMode = EFalse;
       
   158 	iDialogMode = EDialogModeAttended;
       
   159 
       
   160 	iGenericSocket = new(ELeave)CGenericSecureSocket<RSocket>(aSocket);
       
   161 
       
   162 	iRecordParser = new(ELeave)CRecordParser( *iGenericSocket, *iTlsProvider );
       
   163   	LOG(Log::Printf(_L("iRecordParser %x - %x"), iRecordParser, (TUint)iRecordParser + sizeof( CRecordParser ));)
       
   164 	iRecordComposer = new(ELeave)CRecordComposer( *iGenericSocket, *iTlsProvider );
       
   165   	LOG(Log::Printf(_L("iRecordComposer %x - %x"), iRecordComposer, (TUint)iRecordComposer + sizeof( CRecordComposer ));)
       
   166 
       
   167 #ifdef _DEBUG
       
   168    TInt nBlock;
       
   169   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
   170 #endif
       
   171 }
       
   172 
       
   173 void CTlsConnection::ConstructL(MGenericSecureSocket& aSocket, const TDesC& aProtocol)
       
   174 /** 
       
   175  * Two-phase constructor.
       
   176  * Called by CTlsConnection::NewL() to initialise all the 
       
   177  * CTlsConnection objects (bar the State machines). It also sets the 
       
   178  * protocol for the connection. The Provider interface is created and the Session
       
   179  * interface pointer is set to NULL (as no session currently exists).
       
   180  * The dialog mode for the connection is set to Attended mode (default) and the current 
       
   181  * cipher suite is set to [0x00],[0x00].
       
   182  *
       
   183  * @param aSocket is a reference to socket like object derived from MGenericSecureSocket.
       
   184  * @param aProtocol is a descriptor containing the name of the protocol (SSL3.0 or 
       
   185  * TLS1.0) the application specified when the secure socket was created.
       
   186  */
       
   187 {
       
   188 	LOG(Log::Printf(_L("CTlsConnection::ConstructL(GenericSocket,Protocol)"));)
       
   189 
       
   190 	CActiveScheduler::Add(this);		
       
   191 
       
   192 	iTlsProvider = CTLSProvider::ConnectL();		// Set up Security/crypto interfaces
       
   193 
       
   194 	User::LeaveIfError( SetProtocol(aProtocol) );
       
   195 	iTlsProvider->Attributes()->iCurrentCipherSuite.iLoByte = 0x00;
       
   196 	iTlsProvider->Attributes()->iCurrentCipherSuite.iHiByte = 0x00;
       
   197 	iTlsProvider->Attributes()->iDialogNonAttendedMode = EFalse;
       
   198 	iDialogMode = EDialogModeAttended;
       
   199 
       
   200 	iRecordParser = new(ELeave)CRecordParser( aSocket, *iTlsProvider );
       
   201   	LOG(Log::Printf(_L("iRecordParser %x - %x"), iRecordParser, (TUint)iRecordParser + sizeof( CRecordParser ));)
       
   202 	iRecordComposer = new(ELeave)CRecordComposer( aSocket, *iTlsProvider );
       
   203   	LOG(Log::Printf(_L("iRecordComposer %x - %x"), iRecordComposer, (TUint)iRecordComposer + sizeof( CRecordComposer ));)
       
   204 #ifdef _DEBUG
       
   205    TInt nBlock;
       
   206   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
   207 #endif
       
   208 }
       
   209 
       
   210 void CTlsConnection::RunL()
       
   211 {
       
   212 	LOG(Log::Printf(_L("CTlsConnection::RunL()"));)
       
   213 #ifdef _DEBUG
       
   214    TInt nBlock;
       
   215   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
   216 #endif
       
   217 
       
   218 	CActiveScheduler::Stop();
       
   219 }
       
   220 
       
   221 void CTlsConnection::DoCancel()
       
   222 {
       
   223 }
       
   224 
       
   225 
       
   226 // MSecureSocket interface
       
   227 TInt CTlsConnection::AvailableCipherSuites( TDes8& aCiphers )
       
   228 /** 
       
   229  * Retrieves the list of cipher suites that are available to use
       
   230  * for handshake negotiation. 
       
   231  * Cipher suites are returned in two byte format as is specified in the SSL/TLS 
       
   232  * specifications, e.g. [0x00][0x03]. 
       
   233  *
       
   234  * @param aCiphers A reference to a descriptor which will contain a list of cipher suites. 
       
   235  * @return Any one of the system error codes, or KErrNone on success. 
       
   236  */
       
   237 {
       
   238 	LOG(Log::Printf(_L("CTlsConnection::AvailableCipherSuites()"));)
       
   239 
       
   240    if ( !iTlsProvider )
       
   241       {
       
   242       return KErrNotReady;
       
   243       }
       
   244 	RArray<TTLSCipherSuite> cipherList;
       
   245 	TRAPD(ret,iTlsProvider->CipherSuitesL(cipherList, iStatus));
       
   246 	if ( ret != KErrNone )
       
   247 		return ret;
       
   248 		
       
   249 	SetActive();
       
   250 	CActiveScheduler::Start();
       
   251 
       
   252 	if ( iStatus.Int() != KErrNone )
       
   253 	{
       
   254 		LOG(Log::Printf(_L("Error retrieving the available cipher suites %d"), iStatus.Int() );)
       
   255 		return iStatus.Int();
       
   256 	}
       
   257 	
       
   258 	// Each cipher suite contains 2 TUint8 elements. Check the length of the user's 
       
   259 	// descriptor, copy the available cipher suites into it and close the array.
       
   260 	if ( aCiphers.MaxLength() < (cipherList.Count() * 2) ) 
       
   261 		return KErrOverflow;
       
   262 
       
   263 	for (TInt loop = 0; loop < cipherList.Count(); ++loop)
       
   264 	{
       
   265 		aCiphers.Append( cipherList[loop].iHiByte );
       
   266 		aCiphers.Append( cipherList[loop].iLoByte );
       
   267 	}
       
   268 	
       
   269 	cipherList.Close();
       
   270 	return KErrNone;
       
   271 }
       
   272 
       
   273 void CTlsConnection::CancelAll()
       
   274 /**
       
   275  * Cancels all outstanding operations. 
       
   276  */
       
   277 {
       
   278 	LOG(Log::Printf(_L("CTlsConnection::CancelAll()"));)
       
   279 	CancelAll( KErrNone ); 
       
   280 }
       
   281 
       
   282 void CTlsConnection::CancelHandshake()
       
   283 /**
       
   284  * Cancels an outstanding handshake operation. It is equivalent to
       
   285  * a CancelAll() call.
       
   286  */
       
   287 {
       
   288 	LOG(Log::Printf(_L("CTlsConnection::CancelHandshake()"));)
       
   289 	CancelAll( KErrNone );
       
   290 }
       
   291 
       
   292 void CTlsConnection::CancelRecv()
       
   293 /** 
       
   294  * Cancels any outstanding read data operation.
       
   295  */
       
   296 {
       
   297 	LOG(Log::Printf(_L("CTlsConnection::CancelRecv()"));)
       
   298 	if ( iRecvAppData )
       
   299 		iRecvAppData->Cancel( KErrNone ); //no alert sent ? maybe we should send user abort
       
   300 		//but then it'll became be asynchronous fn	// @todo - Cancels have not been tested
       
   301 }
       
   302 
       
   303 void CTlsConnection::CancelSend()
       
   304 /** 
       
   305  * Cancels any outstanding send data operation.
       
   306  */
       
   307 {
       
   308 	LOG(Log::Printf(_L("CTlsConnection::CancelSend()"));)
       
   309 	if ( iSendAppData )
       
   310 		iSendAppData->Cancel( KErrNone );  //no alert sent ? maybe we should send user abort
       
   311 		//but then it'll became be asynchronous fn	// @todo
       
   312 }
       
   313 
       
   314 const CX509Certificate* CTlsConnection::ClientCert()
       
   315 /**
       
   316  * Returns a pointer to the current client certificate if a Server has
       
   317  * requested one. If there is no suitable client certificate available, a NULL pointer 
       
   318  * will be returned.
       
   319  * A client certificate (if available) can only be returned after the negotiation
       
   320  * is complete.
       
   321  *
       
   322  * @return A pointer to the client certificate, or NULL if none exists or is yet
       
   323  * available.
       
   324  */
       
   325 {
       
   326 	LOG(Log::Printf(_L("CTlsConnection::ClientCert()"));)
       
   327 
       
   328 	if (!iTlsProvider || !iTlsProvider->TlsSessionPtr())
       
   329 	{
       
   330 		LOG(Log::Printf(_L("The Client certificate is not yet available()"));)
       
   331 		return NULL;
       
   332 	}
       
   333 	else
       
   334 	{
       
   335       if ( !iClientCert )
       
   336          {
       
   337 		   iTlsProvider->TlsSessionPtr()->ClientCertificate(iClientCert, iStatus);
       
   338 	   
       
   339 		   SetActive();
       
   340    		CActiveScheduler::Start();		
       
   341          }
       
   342 		return iClientCert;
       
   343 	}
       
   344 }
       
   345 
       
   346 TClientCertMode CTlsConnection::ClientCertMode()
       
   347 /** 
       
   348  * Returns the current client certificate mode. This is used when the 
       
   349  * socket is acting as a server, and determines if a client certificate is requested.
       
   350  * This method is not supported as this implementation only acts in Client mode.
       
   351  *
       
   352  * The closest value that the TClientCertMode enumeration provides that supports this
       
   353  * is EClientCertModeIgnore.
       
   354  */
       
   355 {
       
   356 	LOG(Log::Printf(_L("CTlsConnection::ClientCertMode() - Not Supported"));)
       
   357 	return EClientCertModeIgnore;
       
   358 }
       
   359 
       
   360 void CTlsConnection::Close()
       
   361 /** 
       
   362  * Closes the secure connection.
       
   363  * All outstanding operations are cancelled, the internal state machines are deleted
       
   364  * and the socket is closed.
       
   365  */
       
   366 {
       
   367 	LOG(Log::Printf(_L("CTlsConnection::Close()"));)
       
   368 	//OK cancel with closure alert sent (=> asynch call) and delete the statemachines
       
   369 	CancelAll( KErrNone /*KErrSSLAlertCloseNotify*/ ); //it's possible to make it asynch
       
   370    //(send an alert) but....
       
   371    DeleteStateMachines();
       
   372    iRecordParser->Socket().Close();
       
   373    iRecordComposer->SetVersion( NULL );
       
   374 
       
   375    ResetCryptoAttributes();
       
   376 }
       
   377 
       
   378 TInt CTlsConnection::CurrentCipherSuite( TDes8& aCipherSuite )
       
   379 /**
       
   380  * Retrieves the current cipher suite in use. 
       
   381  * Cipher suites are returned in two byte format as is specified in the SSL/TLS 
       
   382  * specifications, i.e. [0x??][0x??]. 
       
   383  *
       
   384  * This method can only return the current cipher suite when the Server has proposed one
       
   385  * to use (i.e., anytime after the Server Hello has been received). Hence, it will only 
       
   386  * have a valid value after the Handshake negotiation has completed. If called before 
       
   387  * handshake negotiation, it will have the value of the NULL cipher, [0x00][0x00].
       
   388  *
       
   389  * @param aCipherSuite A reference to a descriptor at least 2 bytes long.
       
   390  * @return Any one of the system error codes, or KErrNone on success. 
       
   391  */
       
   392 {
       
   393 	LOG(Log::Printf(_L("CTlsConnection::CurrentCipherSuite()"));)
       
   394 	
       
   395    if ( !iTlsProvider )
       
   396       {
       
   397       return KErrNotReady;
       
   398       }
       
   399 	if ( aCipherSuite.MaxLength() < 2 )
       
   400 	{
       
   401 		LOG(Log::Printf(_L("CurrentCipherSuite() - Descriptor should be at least 2 bytes long"));)
       
   402 		return KErrOverflow;
       
   403 	}
       
   404 
       
   405 	aCipherSuite.SetLength(2);		// A cipher suite has a 2 byte length.
       
   406 	aCipherSuite[0] = iTlsProvider->Attributes()->iCurrentCipherSuite.iHiByte;
       
   407 	aCipherSuite[1] = iTlsProvider->Attributes()->iCurrentCipherSuite.iLoByte;
       
   408 
       
   409 	return KErrNone;
       
   410 }
       
   411 
       
   412 TDialogMode	CTlsConnection::DialogMode()
       
   413 /**
       
   414  * Returns the current dialog mode.
       
   415  *
       
   416  * @return The current dialog mode.
       
   417  */ 
       
   418 {
       
   419 	LOG(Log::Printf(_L("CTlsConnection::DialogMode()"));)
       
   420 	return iDialogMode;
       
   421 }
       
   422 
       
   423 void CTlsConnection::FlushSessionCache()
       
   424 /** 
       
   425  * This method does NOT flush the session cache (as this is device-wide). As such, its
       
   426  * interpretation has changed from the pre-Zephyr TLS implementation.
       
   427  *
       
   428  * It is now used as an indication that the client does not intend to reuse an existing
       
   429  * session. As such it sets a flag which is called during handshake negotiation which 
       
   430  * indicates whether a new session or existing session will be used.
       
   431  * The other choice for implementation of this method will be:
       
   432  * 1) Call TLS Provider's GetSession() API to retrieve the session information.
       
   433  * 2) Call TLS Provider's ClearSessionCache() API (with the retrieved session information) 
       
   434  * to remove the particular session from the session cache. Both these APIs are asynchronous.
       
   435  *
       
   436  * Note that there is no means of indicating the success or failure of this operation
       
   437  * to the client.
       
   438  */
       
   439 {
       
   440 	LOG(Log::Printf(_L("CTlsConnection::FlushSessionCache()"));)
       
   441    if ( iTlsProvider )
       
   442       {
       
   443       TTLSSessionNameAndID sessionNameAndID;
       
   444       GetServerAddrInfo( sessionNameAndID.iServerName );
       
   445       TRAPD(ret,iTlsProvider->ClearSessionCacheL( sessionNameAndID, iStatus ));
       
   446       if (KErrNone!=ret)
       
   447       	{
       
   448       	LOG(Log::Printf(_L("CTlsConnection: ClearSessionCacheL error: %d"),ret));
       
   449       	return;
       
   450       	}
       
   451 	  SetActive();
       
   452 	  CActiveScheduler::Start();
       
   453       }
       
   454 }
       
   455 
       
   456 TInt CTlsConnection::GetOpt(TUint aOptionName,TUint aOptionLevel,TDes8& aOption)
       
   457 /**
       
   458  * Gets a Socket option. 
       
   459  *
       
   460  * @param aOptionName An unsigned integer constant which identifies an option.
       
   461  * @param aOptionLevel An unsigned integer constant which identifies the level of an option.	 
       
   462  * @param aOption Option value packaged in a descriptor.
       
   463  * @return KErrNone if successful, otherwise another of the system-wide error codes.
       
   464  */
       
   465 {
       
   466 	LOG(Log::Printf(_L("CTlsConnection::GetOpt() method - descriptor Option"));)
       
   467 	if ( !iTlsProvider || !iTlsProvider->Attributes())
       
   468     	{
       
   469     	return KErrNotReady;
       
   470     	}
       
   471 
       
   472 	switch(aOptionLevel)
       
   473 	{
       
   474 	case KSolInetSSL:
       
   475 		{
       
   476 			switch (aOptionName)
       
   477 			{
       
   478 				case KSoCurrentCipherSuite:
       
   479 					{
       
   480 					// Call the API method that implements the functionality.
       
   481 					LOG(Log::Printf(_L("Option name: KSoCurrentCipherSuite")));
       
   482 					return CurrentCipherSuite(aOption);
       
   483 					}
       
   484 				case KSoAvailableCipherSuites:
       
   485 					{
       
   486 					// Call the API method that implements the functionality.
       
   487 					LOG(Log::Printf(_L("Option name: KSoAvailableCipherSuites")));
       
   488 					return AvailableCipherSuites(aOption);
       
   489 					}
       
   490 				case KSoDialogMode:
       
   491 					{
       
   492 					// Call the API method that implements the functionality.
       
   493 					LOG(Log::Printf(_L("Option name: KSoDialogMode")));
       
   494 					
       
   495 					TDialogMode mode = DialogMode();
       
   496 					TPckgBuf<TDialogMode> packedMode(mode); // Package the object into a descriptor
       
   497 					
       
   498 					if ( aOption.MaxLength() < packedMode.Length() )
       
   499 						return KErrOverflow;
       
   500 						
       
   501 					aOption.Copy(packedMode); 
       
   502 					return KErrNone;
       
   503 					}
       
   504 				case KSoSSLServerCert:
       
   505 					{
       
   506 						// Call the API method that implements the functionality.
       
   507 						LOG(Log::Printf(_L("Option name: KSoSSLServerCert")));
       
   508 						
       
   509 						const CX509Certificate* cert = ServerCert();			
       
   510 						TPckgBuf<const CX509Certificate*> packedCert(cert); // Package the pointer into a descriptor
       
   511 						
       
   512 						if ( aOption.MaxLength() < packedCert.Length() )
       
   513 							return KErrOverflow;
       
   514 						
       
   515 						aOption.Copy( packedCert );
       
   516 						return KErrNone;
       
   517 					}
       
   518 				case KSoUseSSLv2Handshake:
       
   519 					{
       
   520 					/*	
       
   521 					This option is no longer supported, but returning KErrNotSupported
       
   522 					or any other error code will result in a BC break. 
       
   523 					Hence we return KErrNone untill the break gets approved by SCB
       
   524 					*/
       
   525 					return KErrNone;
       
   526 					}
       
   527 				case KSoKeyingMaterial:
       
   528 					{
       
   529 					/*
       
   530 					Performs key generation as per RFC2716 
       
   531 					(PPP EAP TLS Authentication Protocol) section 3.5
       
   532 					*/
       
   533 					return GetKeyingMaterial(aOption);
       
   534 					}
       
   535 				case KSoEnableNullCiphers:
       
   536 					{
       
   537 					*((TInt *)aOption.Ptr()) = iTlsProvider->Attributes()->iAllowNullCipherSuites;
       
   538 					return KErrNone;
       
   539 					}				
       
   540 				
       
   541 				case KSoPskConfig:
       
   542 					{
       
   543 					CTlsCryptoAttributes *attrs = iTlsProvider->Attributes();
       
   544 					MSoPskKeyHandler *handler = NULL;
       
   545 					if(attrs->iPskConfigured)
       
   546 						{
       
   547 						handler = attrs->iPskKeyHandler;
       
   548 						}
       
   549 					if(aOption.Length() < sizeof(MSoPskKeyHandler *))
       
   550 						{
       
   551 						return KErrArgument;
       
   552 						}
       
   553 					// aOption must be a descriptor wrapped arround a MSoPskKeyHandler pointer
       
   554 					// For example TPckgBuf<MSoPskKeyHandler *> pskConfigPkg
       
   555 					*((MSoPskKeyHandler **)aOption.Ptr()) = handler;
       
   556 					return KErrNone;
       
   557 					}
       
   558 				default:
       
   559 					{
       
   560 						LOG(Log::Printf(_L("Unknown option name passed in.")));
       
   561 						return KErrNotSupported;
       
   562 					}
       
   563 			}	// switch (name)
       
   564 		}	// KSolInetSSL
       
   565 	default:
       
   566 		{
       
   567 			// Call the RSocket options directly
       
   568 			return iRecordComposer->Socket().GetOpt(aOptionName, aOptionLevel, aOption);
       
   569 		}
       
   570 	}	// switch (aOptionLevel)
       
   571 }
       
   572 
       
   573 TInt CTlsConnection::GetOpt(TUint aOptionName,TUint aOptionLevel,TInt& aOption)
       
   574 /**
       
   575  * Gets a Socket option. 
       
   576  *
       
   577  * @param aOptionName An integer constant which identifies an option.
       
   578  * @param aOptionLevel An integer constant which identifies the level of an option.	 
       
   579  * @param aOption Option value as an integer.
       
   580  * @return KErrNone if successful, otherwise another of the system-wide error codes.
       
   581  */
       
   582 { 
       
   583 	LOG(Log::Printf(_L("CTlsConnection::GetOpt() method - integer Option"));)
       
   584 
       
   585 	TPtr8 optionDes( (TUint8*)&aOption, sizeof(TInt), sizeof(TInt) );
       
   586 	return GetOpt(aOptionName, aOptionLevel, optionDes);
       
   587 }
       
   588 
       
   589 TInt CTlsConnection::Protocol(TDes& aProtocol)
       
   590 /**
       
   591  * Returns the Protocol version in use. A minimum descriptor size of 8 is
       
   592  * defined for the protocol name (a maximum of 32 is specified in the Secure Socket interface).
       
   593  *
       
   594  * This method can only return the agreed/negotiated Protocol anytime when the handshake 
       
   595  * negotiation has completed. If called before this, the value returned is the protocol
       
   596  * version proposed by the user.
       
   597  *
       
   598  * @param aProtocol A reference to a descriptor containing the protocol name in use.
       
   599  * @return An Integer value indicating the outcome of the function call.
       
   600  */
       
   601 {
       
   602 	LOG(Log::Printf(_L("CTlsConnection::Protocol()"));)
       
   603    if ( !iTlsProvider )
       
   604       {
       
   605       return KErrNotReady;
       
   606       }
       
   607 
       
   608 	// Ensure that the descriptor size passed in reaches our minimum requirement of KProtocolDescMinSize (i.e., 8)
       
   609 	if (aProtocol.MaxSize() < KProtocolDescMinSize) 
       
   610 		return KErrOverflow;
       
   611 
       
   612 	TInt ret = KErrNone;
       
   613 	
       
   614    CTlsCryptoAttributes& cryptoAttributes = *iTlsProvider->Attributes();
       
   615    //check whether any protocol's been negotiated yet. if no return the proposed protocol
       
   616    const TTLSProtocolVersion& tlsVersion = cryptoAttributes.iNegotiatedProtocol.iMajor ?
       
   617       cryptoAttributes.iNegotiatedProtocol : cryptoAttributes.iProposedProtocol;
       
   618 	if (tlsVersion == KSSL3_0)
       
   619 	{
       
   620 		aProtocol.Copy(KProtocolVerSSL30);	// SSL 3.0
       
   621 	}
       
   622 	else if (tlsVersion == KTLS1_0)
       
   623 	{
       
   624 		aProtocol.Copy(KProtocolVerTLS10);	// TLS 1.0
       
   625 	}
       
   626 	else
       
   627 	{
       
   628 		ret = KErrGeneral;					// Unknown protocol version
       
   629 		LOG(Log::Printf(_L("CTlsConnection::Protocol() Unknown protocol error %d"), ret );)
       
   630 	}
       
   631 
       
   632 	return ret;
       
   633 }
       
   634 
       
   635 void CTlsConnection::Recv(TDes8& aDesc, TRequestStatus & aStatus)
       
   636 /**
       
   637  * Receives data from the socket. 
       
   638  * It is an asynchronous method, and will complete when the descriptor has been filled. 
       
   639  * Only one Recv or RecvOneOrMore operation can be outstanding at any time. 
       
   640  * 
       
   641  * @param aDesc A descriptor where data read will be placed.
       
   642  * @param aStatus On completion, will contain an error code: see the system-wide error 
       
   643  * codes. Note that KErrEof indicates that a remote connection is closed, and that no 
       
   644  * more data is available for reading.
       
   645  */
       
   646 {
       
   647 	LOG(Log::Printf(_L("CTlsConnection::Recv()"));)
       
   648 
       
   649 	aDesc.Zero();
       
   650 	if ( RecvData( aDesc, aStatus ) )
       
   651 		iRecvAppData->SetSockXfrLength( NULL );
       
   652 }
       
   653 
       
   654 void CTlsConnection::RecvOneOrMore(TDes8& aDesc, TRequestStatus& aStatus, TSockXfrLength& aLen)
       
   655 /** 
       
   656  * Receives data from the socket. 
       
   657  * It is an asynchronous call, and will complete when at least one byte has been read.
       
   658  * Only one Recv or RecvOneOrMore operation can be outstanding at any time. 
       
   659  *
       
   660  * @param aDesc A descriptor where data read will be placed.
       
   661  * @param aStatus On completion, will contain an error code: see the system-wide error 
       
   662  * codes. Note that KErrEof indicates that a remote connection is closed, and that no 
       
   663  * more data is available for reading.
       
   664  * @param aLen On return, a length which indicates how much data was read. This is
       
   665  * the same as the length of the returned aDesc.
       
   666  */
       
   667 {
       
   668 	LOG(Log::Printf(_L("CTlsConnection::RecvOneOrMore()"));)
       
   669 
       
   670 	if ( RecvData( aDesc, aStatus ) )
       
   671 		iRecvAppData->SetSockXfrLength( &aLen() );
       
   672 }
       
   673 
       
   674 void CTlsConnection::RenegotiateHandshake(TRequestStatus& aStatus)
       
   675 /**
       
   676  * Initiates a renegotiation of the secure connection. 
       
   677  * It is an asynchronous method that completes when renegotiation is complete. 
       
   678  * The Client can initiate handshake renegotiation or it can receive a re-negotiation request 
       
   679  * from a remote server.
       
   680  * Note that the User should cancel any data transfer or wait for its completion before
       
   681  * attempting to re-negotiate.
       
   682  *
       
   683  * @param aStatus On completion, will contain an error code: see the system-wide error 
       
   684  * codes.
       
   685  */
       
   686 {
       
   687 	LOG(Log::Printf(_L("CTlsConnection::RenegotiateHandshake()"));)
       
   688    
       
   689 	TRequestStatus* pStatus = &aStatus;
       
   690 
       
   691 	// Renegotiation can only happen in data mode
       
   692 	if ( !IsInDataMode() )		
       
   693 	{
       
   694 		User::RequestComplete( pStatus, KErrNotReady );
       
   695 		return;
       
   696 	}
       
   697    
       
   698 	// Renegotiation is already taking place or client is tx-ing or rx-ing data
       
   699 	if ( IsReNegotiating() || iSendAppData->ClientStatus() || iRecvAppData->ClientStatus() )
       
   700 	{
       
   701 		User::RequestComplete( pStatus, KErrInUse );
       
   702 		return;
       
   703 	}
       
   704    
       
   705 	StartRenegotiation( pStatus );
       
   706 }
       
   707 
       
   708 void CTlsConnection::Send(const TDesC8& aDesc, TRequestStatus& aStatus)
       
   709 /** 
       
   710  * Sends data over the socket. 
       
   711  * Only one Send operation can be outstanding at any time.
       
   712  *
       
   713  * @param aDesc A constant descriptor containing the data to be sent.
       
   714  * @param aStatus On completion, will contain an error code: see the system-wide 
       
   715  * error codes. 
       
   716  */
       
   717 {
       
   718 	LOG(Log::Printf(_L("CTlsConnection::Send() - Descriptor only"));)
       
   719 
       
   720 	if ( SendData( aDesc, aStatus ) )
       
   721 		iSendAppData->SetSockXfrLength( NULL );
       
   722 }
       
   723 
       
   724 void CTlsConnection::Send(const TDesC8& aDesc, TRequestStatus& aStatus, TSockXfrLength& aLen)
       
   725 /** 
       
   726  * Sends data over the socket. 
       
   727  * Only one Send operation can be outstanding at any time. 
       
   728  *
       
   729  * @param aDesc A constant descriptor.
       
   730  * @param aStatus On completion, will contain an error code: see the system-wide 
       
   731  * error codes. 
       
   732  * @param aLen Filled in with amount of data sent before completion 
       
   733  */
       
   734 {
       
   735 	LOG(Log::Printf(_L("CTlsConnection::Send() - Descriptor and Length"));)
       
   736 
       
   737 	if ( SendData( aDesc, aStatus ) )
       
   738 		iSendAppData->SetSockXfrLength( &aLen() );
       
   739 }
       
   740 
       
   741 const CX509Certificate* CTlsConnection::ServerCert()
       
   742 /**
       
   743  * Returns a pointer to the current server certificate.
       
   744  * The returned certificate will be the certificate for the remote server. It is 
       
   745  * obtained via the TLS Provider API.
       
   746  *
       
   747  * A server certificate (if available) can only be returned only after the 
       
   748  * negotiation has reached a stage at which one has been received and verified.
       
   749  *
       
   750  * @return A pointer to the Server's certificate.
       
   751  */ 
       
   752 {
       
   753 	LOG(Log::Printf(_L("CTlsConnection::ServerCert()"));)
       
   754 
       
   755 	if ( !iTlsProvider || !iTlsProvider->TlsSessionPtr())
       
   756 	{
       
   757 		LOG(Log::Printf(_L("The Server certificate is not yet available()"));)
       
   758 		return NULL;
       
   759 	}
       
   760 	else
       
   761 	{
       
   762 		if ( !iServerCert )
       
   763          {
       
   764 		   iTlsProvider->TlsSessionPtr()->ServerCertificate(iServerCert, iStatus);  
       
   765 		   
       
   766 		   SetActive();
       
   767 		   CActiveScheduler::Start();
       
   768 
       
   769 		   if ( iStatus.Int() != KErrNone )
       
   770 		      {
       
   771 			   LOG(Log::Printf(_L("Error retrieving the Server certificate %d"), iStatus.Int() );)
       
   772 		      }
       
   773          }
       
   774 		return iServerCert;
       
   775 	}
       
   776 }
       
   777 
       
   778 TInt CTlsConnection::SetAvailableCipherSuites(const TDesC8& aCiphers)
       
   779 /** 
       
   780  * A client can be involved in the Handshake negotiation with the remote server by 
       
   781  * specifying which cipher suites it wants to use in the negotiation. 
       
   782  * The client should first call AvailableCipherSuites() to retrieve all the supported
       
   783  * cipher suites. This method can then be used to specify a subset which it wants to
       
   784  * use.
       
   785  * The list of cipher suites supplied in a descriptor to the protocol MUST be in two
       
   786  * byte format, i.e. [0x??][0x??]. The order of suites is important, and so they should 
       
   787  * be listed with the preferred suites first. 
       
   788  * A client does NOT have to call/use this method. In this instance, the preference
       
   789  * order of the cipher suites will be set by the TLS Provider.
       
   790  * 
       
   791  * @param aCiphers A descriptor containing the list of ciphers suites to use. 
       
   792  * @return Any one of the system error codes, or KErrNone on success. 
       
   793  */
       
   794 {
       
   795 	LOG(Log::Printf(_L("CTlsConnection::SetAvailableCipherSuites()"));)
       
   796 	if ( !iTlsProvider )
       
   797       {
       
   798       return KErrNotReady;
       
   799       }
       
   800 	// Get the available cipher suites from the Provider. 
       
   801 	RArray<TTLSCipherSuite> cipherList; 
       
   802 	TRAPD(ret,iTlsProvider->CipherSuitesL(cipherList, iStatus));
       
   803 	if ( ret != KErrNone )
       
   804 		return ret;
       
   805 		
       
   806 	SetActive();
       
   807 //   TRequestStatus* p=&iStatus;
       
   808 //   User::RequestComplete( p, KErrNone );
       
   809 	CActiveScheduler::Start();
       
   810 
       
   811 	// Cycle through the client's list of ciphers. 
       
   812 	// Ensure that values in the clients list are in the list of available ciphers.
       
   813 	TBool valueIsSet;		// Break out of the inner loop once the value is set.
       
   814    TInt returnValue = iStatus.Int();
       
   815    TDes8& proposedCiphers = iTlsProvider->Attributes()->iProposedCiphers;
       
   816    proposedCiphers.Zero();
       
   817 	for ( TInt outerLoop=0; outerLoop<aCiphers.Length(); outerLoop+=2 )					
       
   818 	{
       
   819 		valueIsSet = EFalse;
       
   820 
       
   821 		for (TInt innerLoop=0; innerLoop<cipherList.Count();++innerLoop)
       
   822 		{
       
   823 			if( aCiphers[outerLoop] == cipherList[innerLoop].iHiByte			
       
   824 			&& aCiphers[outerLoop+1] == cipherList[innerLoop].iLoByte )
       
   825 			{
       
   826 				// the suite is valid, so add it to the list of proposed ciphers
       
   827 				proposedCiphers.Append(aCiphers[outerLoop]);
       
   828 				proposedCiphers.Append(aCiphers[outerLoop+1]);
       
   829 				valueIsSet = 1;
       
   830 			}
       
   831 
       
   832 			if (valueIsSet)
       
   833 				break;
       
   834 		} // inner 'for' statement.
       
   835 	}	// outer 'for' statement.
       
   836 	
       
   837 	cipherList.Close();	// Close the array and free its memory.
       
   838 
       
   839 	// If no valid ciphers are received from the client, all available cipher suites
       
   840 	// returned by the protocol will be used
       
   841 	if ( proposedCiphers.Length() == 0 )
       
   842 	{
       
   843 		LOG(Log::Printf(_L("SetAvailableCipherSuites() - No valid ciphers received from client"));)
       
   844 		returnValue = KErrNotSupported;
       
   845 	}
       
   846 
       
   847 	return returnValue;
       
   848 }
       
   849 
       
   850 TInt CTlsConnection::SetClientCert(const CX509Certificate& /*aCert*/)
       
   851 /**
       
   852  * Sets the client certificate to use.
       
   853  * In client mode, this method will set the certificate that will be used if a 
       
   854  * server requests one.
       
   855  * Note that this method is NOT supported by the current implementation. Client 
       
   856  * Certificates are stored by the Security subsystem and it chooses the appropriate
       
   857  * Client certificate to use based on the Server's preference list.
       
   858  *
       
   859  * @param aCert A reference to the certificate to use.
       
   860  * @return Any one of the system error codes, or KErrNone on success. 
       
   861  */
       
   862 {
       
   863 	LOG(Log::Printf(_L("CTlsConnection::SetClientCert()"));)
       
   864 	return KErrNotSupported;
       
   865 }
       
   866 
       
   867 TInt CTlsConnection::SetClientCertMode(const TClientCertMode /*aClientCertMode*/)
       
   868 /** 
       
   869  * Sets the client certificate mode. 
       
   870  * This method only applies to Server mode operation (which is not supported by the 
       
   871  * current implementation). In client mode, no action will be performed and 
       
   872  * KErrNotSupported will be returned by the Protocol.
       
   873  *
       
   874  * @param aClientCertMode The client certificate mode to use.
       
   875  * @return Any one of the system error codes, or KErrNone on success. 
       
   876  */
       
   877 {
       
   878 	LOG(Log::Printf(_L("CTlsConnection::SetClientCertMode()"));)
       
   879 	return KErrNotSupported;
       
   880 }
       
   881 
       
   882 TInt CTlsConnection::SetDialogMode(const TDialogMode aDialogMode)
       
   883 /**
       
   884  * Sets the untrusted certificate dialog mode.
       
   885  * It determines if a dialog is displayed when an untrusted certificate is received.
       
   886  * The default behaviour is for the dialog to be set to EDialogModeAttended (this 
       
   887  * is set in the construction of a CTlsConnection object).
       
   888  * A client can either set the dialog mode directly by calling this method, or by
       
   889  * calling CTlsConnection::SetOpt() with an appropriate option value.
       
   890  *
       
   891  * @param aDialogMode The dialog mode to use.
       
   892  * @return Any one of the system error codes, or KErrNone on success. 
       
   893  */
       
   894 {
       
   895 	LOG(Log::Printf(_L("CTlsConnection::SetDialogMode()"));)
       
   896 	
       
   897 	// This method must ensure that the dialog mode passed in is part of the 
       
   898 	// TDialogMode enum or has the value EDialogModeUnattended/EDialogModeAttended. 
       
   899 	// Otherwise, it must return KErrArgument
       
   900 	TInt ret = KErrNone;
       
   901    
       
   902     switch(aDialogMode)
       
   903     {
       
   904         case EDialogModeUnattended:
       
   905         case EDialogModeAttended:
       
   906             iDialogMode = aDialogMode;
       
   907         break;
       
   908         
       
   909         default:  //-- wrong mode
       
   910             LOG(Log::Printf(_L("SetDialogMode() - Unknown dialog mode, default setting (Attended mode) being used"));)
       
   911         return KErrArgument;    
       
   912     };
       
   913 
       
   914     if ( iTlsProvider )
       
   915     {
       
   916    	    iTlsProvider->Attributes()->iDialogNonAttendedMode = (iDialogMode == EDialogModeUnattended);
       
   917     }	
       
   918 
       
   919     return ret;
       
   920 }
       
   921 
       
   922 TInt CTlsConnection::SetOpt(TUint aOptionName,TUint aOptionLevel, const TDesC8& aOption)
       
   923 /** 
       
   924  * Sets a Socket option. 
       
   925  *
       
   926  * @param aOption Option value packaged in a descriptor.
       
   927  * @param aOptionName An integer constant which identifies an option.
       
   928  * @param aOptionLevel An integer constant which identifies the level of an option 
       
   929  * (an option level groups related options together).
       
   930  * @return Any one of the system error codes, or KErrNone on success.
       
   931  */
       
   932 {
       
   933 	LOG(Log::Printf(_L("CTlsConnection::SetOpt() method - descriptor Option"));)
       
   934 	TInt ret=KErrNotSupported;
       
   935 
       
   936 	if ( !iTlsProvider || !iTlsProvider->Attributes())
       
   937     	{
       
   938     	return KErrNotReady;
       
   939     	}
       
   940 
       
   941 	switch(aOptionLevel)
       
   942 	{
       
   943 	case KSolInetSSL:		// This is the only supported option level in SSL/TLS
       
   944 		{
       
   945 			switch (aOptionName)
       
   946 			{
       
   947 			case KSoSSLDomainName:		
       
   948 				{
       
   949 				LOG(Log::Printf(_L("Option name: KSoSSLDomainName")));
       
   950 				iTlsProvider->Attributes()->idomainName.Copy(aOption);
       
   951 				// @todo Create a CX509Name object and set in the TTlsCryptoAttribs
       
   952 				// structure. Note that this structure has to updated to take a 
       
   953 				// CX509**** object. The iProposedCiphers buffer is still not correct.
       
   954 				// It must also have a iProposedProtocol and iNegotiatedProtocol.
       
   955 				ret = KErrNone;
       
   956 				break;
       
   957 				}
       
   958 			case KSoDialogMode:
       
   959 				{
       
   960 				// Call the API method that implements the functionality.
       
   961 				LOG(Log::Printf(_L("Option name: KSoDialogMode")));
       
   962 				
       
   963 				TDialogMode dialogMode = (TDialogMode) ( *(TUint*)aOption.Ptr() );
       
   964 				ret = SetDialogMode(dialogMode);
       
   965 				
       
   966 				break;
       
   967 				}
       
   968 			case KSoUseSSLv2Handshake:
       
   969 				{
       
   970 				/*	
       
   971 				This option is no longer supported, but returning KErrNotSupported
       
   972 				or any other error code will result in a BC break. 
       
   973 				Hence we return KErrNone untill the break gets approved by SCB
       
   974 				*/
       
   975 				ret = KErrNone;
       
   976 				break;
       
   977 				}
       
   978 			case KSoEnableNullCiphers:
       
   979 				{
       
   980 				TInt option = *reinterpret_cast<const TInt *>(aOption.Ptr());
       
   981 				iTlsProvider->Attributes()->iAllowNullCipherSuites = (option != 0);
       
   982 				ret = KErrNone;
       
   983 				break;
       
   984 				}
       
   985 			case KSoPskConfig:
       
   986 				{
       
   987 				/*
       
   988 					Set the PSK Key Exchange configuration.
       
   989 					aOption is a TDesC8 wrapper around a MSoPskKeyHandler pointer
       
   990 				*/
       
   991 				// aOption must be a descriptor wrapped arround a MSoPskKeyHandler pointer
       
   992 				// For example TPckgBuf<MSoPskKeyHandler *> pskConfigPkg
       
   993 				if(aOption.Length() < sizeof(MSoPskKeyHandler *))
       
   994 					{
       
   995 					return KErrArgument;
       
   996 					}
       
   997 				TPckgBuf<MSoPskKeyHandler *> pskConfigPkg;
       
   998 				MSoPskKeyHandler *handler = *reinterpret_cast<MSoPskKeyHandler * const *>(aOption.Ptr());
       
   999 
       
  1000 				CTlsCryptoAttributes *attrs = iTlsProvider->Attributes();
       
  1001 				attrs->iPskConfigured = (handler!=0);
       
  1002 				attrs->iPskKeyHandler = handler;
       
  1003 				ret = KErrNone;
       
  1004 				break;
       
  1005 				}
       
  1006 			case KSoServerNameIndication:
       
  1007 				{
       
  1008 				/*
       
  1009 				 * Set the list of server names to be passed to the server in the ClientHello as described in 
       
  1010 				 * RFC3546 "Server Name Indication".
       
  1011  				 * aOption is a TDesC8 wrapper around a CDesC8Array pointer.
       
  1012 				*/
       
  1013 				if(aOption.Length() < sizeof(CDesC8Array *))
       
  1014 					{
       
  1015 					return KErrArgument;
       
  1016 					}
       
  1017 				CDesC8Array *serverNames = *reinterpret_cast<CDesC8Array * const *>(aOption.Ptr());
       
  1018 
       
  1019 				CTlsCryptoAttributes *attrs = iTlsProvider->Attributes();
       
  1020 				delete attrs->iServerNames;
       
  1021 				attrs->iServerNames = serverNames;
       
  1022 
       
  1023 				ret = KErrNone;
       
  1024 				break;
       
  1025 				}
       
  1026 			default:
       
  1027 				break;
       
  1028 			}	// KSolInetSSL
       
  1029 
       
  1030 			break;
       
  1031 		}
       
  1032 	default:	// Not a supported SSL option, call RSocket::SetOpt directly
       
  1033 		{
       
  1034 			LOG(Log::Printf(_L("Default option level (not supported by protocol)")));
       
  1035 			ret = iRecordComposer->Socket().SetOpt(aOptionName, aOptionLevel, aOption);
       
  1036 
       
  1037 			break;
       
  1038 		}	// Default 'level' statement
       
  1039 	}	// switch statement
       
  1040 
       
  1041 	return ret;
       
  1042 }
       
  1043 
       
  1044 TInt CTlsConnection::SetOpt(TUint aOptionName,TUint aOptionLevel,TInt aOption)
       
  1045 /** 
       
  1046  * Sets a Socket option.  calls the SetOpt() method defined above.
       
  1047  *
       
  1048  * @param aOption Option value as an integer
       
  1049  * @param aOptionName An integer constant which identifies an option.
       
  1050  * @param aOptionLevel An integer constant which identifies level of an option (an
       
  1051  * option level groups related options together.
       
  1052  * @return Any one of the system error codes, or KErrNone on success.
       
  1053  */
       
  1054 {
       
  1055 	LOG(Log::Printf(_L("CTlsConnection::SetOpt() method - integer Option"));)
       
  1056 
       
  1057 	TPtr8 optionDes( (TUint8*)&aOption, sizeof(TInt), sizeof(TInt) );
       
  1058 	return SetOpt(aOptionName, aOptionLevel, optionDes);	
       
  1059 }
       
  1060 
       
  1061 TInt CTlsConnection::SetProtocol(const TDesC& aProtocol)
       
  1062 /**
       
  1063  * Sets the Secure socket protocol version (SSL v3.0 or TLS v1.0) to 
       
  1064  * use in the Handshake negotiation. It also initially sets the negotiated protocol 
       
  1065  * to the requested protocol. A maximum length of 32 is specified in the Secure Socket 
       
  1066  * interface for the protocol version.
       
  1067  *
       
  1068  * 
       
  1069  * @param aProtocol is a reference to a descriptor containing the protocol version to use.
       
  1070  * @return Any one of the system error codes, or KErrNone on success.
       
  1071  */
       
  1072 {
       
  1073 	LOG(Log::Printf(_L("CTlsConnection::SetProtocol()"));)
       
  1074 
       
  1075    if ( !iTlsProvider )
       
  1076       {
       
  1077       return KErrNotReady;
       
  1078       }
       
  1079 	// Convert the Protocol value to upper case before doing a comparison
       
  1080 	TBuf<32> tempBuf;
       
  1081 	tempBuf.Copy(aProtocol);
       
  1082 	tempBuf.UpperCase();
       
  1083 
       
  1084 	TInt ret = tempBuf.Compare(KProtocolVerSSL30);
       
  1085 	if ( ret == 0 )
       
  1086 	{
       
  1087 		iTlsProvider->Attributes()->iProposedProtocol = KSSL3_0;
       
  1088 	}
       
  1089 	else
       
  1090 	{
       
  1091 		ret = tempBuf.Compare(KProtocolVerTLS10);
       
  1092 		if ( ret == 0 )
       
  1093 		{
       
  1094 			iTlsProvider->Attributes()->iProposedProtocol = KTLS1_0;
       
  1095 		}
       
  1096 		else
       
  1097 			return KErrNotSupported;
       
  1098 	}
       
  1099 	return KErrNone;
       
  1100 }
       
  1101 
       
  1102 TInt CTlsConnection::SetServerCert(const CX509Certificate& /*aCert*/)
       
  1103 /**
       
  1104  * Reserved for future work, always returns KErrNotSupported. 
       
  1105  * 
       
  1106  * @param aCert The certificate to use.
       
  1107  * @return Any one of the system error codes, or KErrNone on success. 
       
  1108  */
       
  1109 {
       
  1110 	LOG(Log::Printf(_L("CTlsConnection::SetServerCert()"));)
       
  1111 	return KErrNotSupported;
       
  1112 }
       
  1113 
       
  1114 void CTlsConnection::StartClientHandshake(TRequestStatus& aStatus)
       
  1115 /**
       
  1116  * Starts a client request and initiates a handshake 
       
  1117  * with the remote server.
       
  1118  * Configuration retrieval happens during construction of the CTlsConnection object,
       
  1119  * which progresses the connection into the Idle state. 
       
  1120  *
       
  1121  * @param aStatus On completion, any one of the system error codes, or KErrNone 
       
  1122  * on success (handshake negotiation complete). 
       
  1123  */
       
  1124 {
       
  1125 	LOG(Log::Printf(_L("CTlsConnection::StartClientHandshake()"));)
       
  1126 	TRequestStatus* pStatus = &aStatus;
       
  1127 
       
  1128 	if ( !IsIdle() )	// The connection must be in the Idle state
       
  1129 	{
       
  1130 		User::RequestComplete( pStatus, KErrInUse );
       
  1131 		return;
       
  1132 	}
       
  1133 
       
  1134 	StartClientHandshakeStateMachine( pStatus );
       
  1135 }
       
  1136 
       
  1137 void CTlsConnection::StartServerHandshake(TRequestStatus& aStatus)
       
  1138 /**
       
  1139  * Start acting as a server and listen for a handshake from the remote client.
       
  1140  * This is an asynchronous call, and will only complete when a client completes the 
       
  1141  * handshake, or if it fails.
       
  1142  * Normally, the socket passed in will usually have been previously used in a call to 
       
  1143  * Accept() on a listening socket, but this is not required. 
       
  1144  * Note that this implementation does not support Server mode operation, so this method
       
  1145  * is NOT supported.
       
  1146  *
       
  1147  * @param aStatus On completion, any one of the system error codes, or KErrNone on success. 
       
  1148  */
       
  1149 {
       
  1150 	LOG(Log::Printf(_L("CTlsConnection::StartServerHandshake()"));)
       
  1151 	TRequestStatus* pStatus = &aStatus;
       
  1152 
       
  1153 	User::RequestComplete( pStatus, KErrNotSupported );
       
  1154 }
       
  1155 
       
  1156 
       
  1157 
       
  1158 //MStateMachineNotify interface
       
  1159 TBool CTlsConnection::OnCompletion( CStateMachine* aStateMachine )
       
  1160 /**
       
  1161  * Called only when negotiation or renegotiation has completed.
       
  1162  */
       
  1163 {
       
  1164 	LOG(Log::Printf(_L("CTlsConnection::OnCompletion()"));)
       
  1165 #ifdef _DEBUG
       
  1166    TInt nBlock;
       
  1167   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
  1168 #endif
       
  1169 
       
  1170    iRecordParser->IgnoreAppData( 0 );
       
  1171    __ASSERT_DEBUG( !aStateMachine->SuspendRequest(), TlsPanic(ETlsPanicStateMachineStopped) );
       
  1172    if ( aStateMachine->LastError() != KErrNone )
       
  1173    {//user will be notified after return from this fn
       
  1174 	   if ( iHandshake != aStateMachine )
       
  1175 	      {
       
  1176 		   return EFalse;
       
  1177 	      }
       
  1178       else
       
  1179          {//delete data path in case it's re-negotiation what's failed
       
  1180          delete iSendAppData;
       
  1181          iSendAppData = NULL;
       
  1182          delete iRecvAppData;
       
  1183          iRecvAppData = NULL;
       
  1184          ResetCryptoAttributes();
       
  1185          }
       
  1186    }
       
  1187    else
       
  1188    {//from now on we propose the alrady negotiated protocol untill the connection is closed
       
  1189       iTlsProvider->Attributes()->iProposedProtocol = iTlsProvider->Attributes()->iNegotiatedProtocol;
       
  1190       if ( IsReNegotiating() )
       
  1191       {
       
  1192          //resume the SM statuses
       
  1193          TRAPD(ret, iSendAppData->ResumeL();
       
  1194             iRecvAppData->ResumeL( *this ) );
       
  1195          if ( ret != KErrNone )
       
  1196          {//something went completely wrong
       
  1197           //set last error so that the user will be notified after return from this fn
       
  1198             aStateMachine->SetLastError( ret );
       
  1199             delete iSendAppData;
       
  1200             iSendAppData = NULL;
       
  1201             delete iRecvAppData;
       
  1202             iRecvAppData = NULL;
       
  1203          }
       
  1204          else
       
  1205          {
       
  1206             __ASSERT_DEBUG( !iSendAppData->IsActive(), TlsPanic(ETlsPanicAlreadyActive));
       
  1207             if ( iSendAppData->ClientStatus() ) //has the SM finished?
       
  1208             {//no => start it again to resume the task
       
  1209                iSendAppData->Start( iSendAppData->ClientStatus(), this );
       
  1210             }
       
  1211             //recv SM is active when re-negotiation started via HelloRequest
       
  1212             if ( !iRecvAppData->IsActive() && iRecvAppData->ClientStatus() ) 
       
  1213             {//not active and not finished => start it again to resume the the task
       
  1214                iRecvAppData->Start( iRecvAppData->ClientStatus(), this );
       
  1215             }
       
  1216          }
       
  1217       }
       
  1218       else if ( !IsInDataMode() )
       
  1219       {
       
  1220 	     // Create the Data state machines so that the user can send/receive data
       
  1221          __ASSERT_DEBUG( !iRecvAppData && !iSendAppData, TlsPanic(ETlsPanicStateMachineAlreadyExists));
       
  1222       
       
  1223 	     //don't change the order see CRecvAppData::ResumeL
       
  1224 	     TRAPD( ret, iSendAppData = CSendAppData::NewL( *iRecordComposer );
       
  1225 		     iRecvAppData = CRecvAppData::NewL( *this ) );
       
  1226          if ( ret != KErrNone )
       
  1227          {//something went completely wrong
       
  1228           //set last error so that the user will be notified after return from this fn
       
  1229             aStateMachine->SetLastError( ret );
       
  1230             //delete what may have been created
       
  1231             delete iRecvAppData;
       
  1232             iRecvAppData = 0;
       
  1233             delete iSendAppData;
       
  1234             iSendAppData = 0;
       
  1235          }
       
  1236       }
       
  1237       else
       
  1238       {
       
  1239 	      // Must be one of the Application data SM
       
  1240           __ASSERT_DEBUG( iRecvAppData == aStateMachine ||
       
  1241              iSendAppData == aStateMachine, TlsPanic(ETlsPanicInvalidStateMachine));
       
  1242           return EFalse; // Don't want to delete either of them.
       
  1243       }
       
  1244    }
       
  1245    __ASSERT_DEBUG( iHandshake == aStateMachine, TlsPanic(ETlsPanicInvalidStateMachine));
       
  1246    iHandshake = 0;
       
  1247    return ETrue; // Delete the Handshake state machine.
       
  1248 }
       
  1249 
       
  1250 
       
  1251 // Internal functions
       
  1252 
       
  1253 TBool CTlsConnection::IsIdle() const
       
  1254 /**
       
  1255  * Returns 'True' if a connection is idle.
       
  1256  */
       
  1257 {
       
  1258 	LOG(Log::Printf(_L("CTlsConnection::IsIdle()"));)
       
  1259 	return !iHandshake && !iSendAppData;
       
  1260 }
       
  1261 
       
  1262 
       
  1263 TBool CTlsConnection::SendData( const TDesC8& aDesc, TRequestStatus& aStatus )
       
  1264 /**
       
  1265  * Starts the Application data transmission state machine, 
       
  1266  * which sends data to a remote Server.
       
  1267  *
       
  1268  * @param aDesc Reference to the user's descriptor (data buffer)
       
  1269  * @param aClientStatus TRequestStatus object that completes when data transmission
       
  1270  * is finished.
       
  1271  */
       
  1272 {
       
  1273 	LOG(Log::Printf(_L("CTlsConnection::SendData()"));)
       
  1274 
       
  1275 	TRequestStatus* pStatus = &aStatus;
       
  1276 	if ( !iSendAppData )
       
  1277 	{
       
  1278 		User::RequestComplete( pStatus, KErrNotReady );
       
  1279 		return EFalse;
       
  1280 	}
       
  1281 	else if ( iSendAppData->ClientStatus() )
       
  1282 	{
       
  1283 		User::RequestComplete( pStatus, KErrInUse );
       
  1284 		return EFalse;
       
  1285 	}
       
  1286 	else if ( IsReNegotiating() )
       
  1287 	{
       
  1288 		iSendAppData->SetUserData( (TDesC8*)&aDesc );
       
  1289 		iSendAppData->SetClientStatus( &aStatus );
       
  1290 		//and wait for re-negotiation to finish (see CTlsConnection::OnCompletion)
       
  1291 	}
       
  1292 	else
       
  1293 	{	
       
  1294 		iRecordComposer->SetUserData( (TDesC8*)&aDesc );
       
  1295    	iRecordComposer->ResetCurrentPos();
       
  1296 		iSendAppData->Start( &aStatus, this );
       
  1297 	}
       
  1298 	
       
  1299 	return ETrue;
       
  1300 }
       
  1301 
       
  1302 TBool CTlsConnection::RecvData( TDes8& aDesc, TRequestStatus& aStatus )
       
  1303 /**
       
  1304  * Starts the Application data reception state machine, 
       
  1305  * which receives data from a remote Server.
       
  1306  *
       
  1307  * @param aDesc Reference to the user's descriptor (data buffer)
       
  1308  * @param aClientStatus TRequestStatus object that completes when data reception is 
       
  1309  * finished.
       
  1310  */
       
  1311 {
       
  1312 	LOG(Log::Printf(_L("CTlsConnection::RecvData()"));)
       
  1313 	TBool result = EFalse;
       
  1314 
       
  1315 	TRequestStatus* pStatus = &aStatus;
       
  1316 
       
  1317 	if ( !iRecvAppData )
       
  1318 		User::RequestComplete( pStatus, KErrNotReady );
       
  1319 	else if ( iRecvAppData->ClientStatus() || IsReNegotiating() )
       
  1320       User::RequestComplete( pStatus, KErrInUse );
       
  1321 	else
       
  1322 	{
       
  1323 		iRecordParser->SetUserData( &aDesc );
       
  1324 		iRecordParser->SetUserMaxLength( aDesc.MaxLength() );
       
  1325 		iRecvAppData->Start( &aStatus, this );
       
  1326 		result = ETrue;
       
  1327 	}
       
  1328    
       
  1329 	return result;
       
  1330 }
       
  1331 
       
  1332 void CTlsConnection::StartClientHandshakeStateMachine(TRequestStatus* aStatus)
       
  1333 /**
       
  1334  * Creates and starts the Handshake negotiation state machine, 
       
  1335  * which initiates negotiations with the remote Server.
       
  1336  */
       
  1337 {
       
  1338 	LOG(Log::Printf(_L("CTlsConnection::StartClientHandshakeStateMachine()"));)
       
  1339 	delete iClientCert;
       
  1340    iClientCert = NULL;
       
  1341 	delete iServerCert;
       
  1342    iServerCert = NULL;
       
  1343 
       
  1344 	// Assert that a Handshake negotiation object doesn't exist and that a request
       
  1345 	// status object is valid.
       
  1346 	__ASSERT_DEBUG( !iHandshake, TlsPanic(ETlsPanicStateMachineAlreadyExists) ); 
       
  1347 	__ASSERT_DEBUG( aStatus, TlsPanic(ETlsPanicInvalidStatus));
       
  1348 
       
  1349 	TRAPD( ret, iHandshake = CHandshake::NewL(*this) );
       
  1350 	if ( ret != KErrNone )
       
  1351 		User::RequestComplete(aStatus, ret);
       
  1352 	else
       
  1353   		{
       
  1354   		TRAP(ret, iHandshake->StartL(aStatus, this));
       
  1355   		if (ret!=KErrNone)
       
  1356   			{
       
  1357          delete iHandshake;
       
  1358          iHandshake = NULL;
       
  1359   			User::RequestComplete(aStatus, ret);
       
  1360   			}
       
  1361   		}
       
  1362 
       
  1363 
       
  1364 
       
  1365 #ifdef _DEBUG
       
  1366    TInt nBlock;
       
  1367   	LOG(Log::Printf(_L("RHeap::Size(), RHeap::Size() - RHeap::Available() %d, %d"), User::Heap().Size(), User::Heap().Size() - User::Heap().Available( nBlock ) );)
       
  1368 #endif
       
  1369 }
       
  1370 
       
  1371 void CTlsConnection::ResetCryptoAttributes()
       
  1372 {//don't change the order of the calls see (see ~CRecordParser & CRecordParser::Reset)
       
  1373 	LOG(Log::Printf(_L("CTlsConnection::ResetCryptoAttributes()"));)
       
  1374    iRecordComposer->Reset();
       
  1375    iRecordParser->Reset();
       
  1376 //   iRecordParser->SetTlsProvider( NULL );
       
  1377 //   iRecordComposer->SetTlsProvider( NULL );
       
  1378    if ( iTlsProvider )
       
  1379       {
       
  1380 	   TRAPD(ret, iTlsProvider->ReConnectL());		// Set up Security/crypto interfaces
       
  1381 	   delete iTlsSession; 
       
  1382       iTlsSession = NULL;
       
  1383       if ( ret )
       
  1384          {
       
  1385          delete iTlsProvider;
       
  1386          iTlsProvider = NULL;
       
  1387          iRecordParser->SetTlsProvider( iTlsProvider );
       
  1388          iRecordComposer->SetTlsProvider( iTlsProvider );
       
  1389          }
       
  1390       }
       
  1391 }
       
  1392 
       
  1393 void CTlsConnection::StartRenegotiation( TRequestStatus* aStatus )
       
  1394 /**
       
  1395  * Starts Handshake renegotiation. 
       
  1396  *
       
  1397  * It suspends the Application Data (transmission and reception) state machines
       
  1398  * and restarts the Handshake negotiation state m/c.
       
  1399  * It also creates a new TLS Provider object to access security services. This is 
       
  1400  * necessary as a new cryptographic token might be selected to create new key material.
       
  1401  * The session cache is flushed as session reuse should not take place (ensure that entirely
       
  1402  * new key material is generated).
       
  1403  */
       
  1404 {
       
  1405 	LOG(Log::Printf(_L("CTlsConnection::StartRenegotiation()"));)
       
  1406    //User::RequestComplete( aStatus, KErrNotSupported ); //not until we have CTlsProvider::Close()
       
  1407 
       
  1408 	iSendAppData->Suspend();
       
  1409 	iRecvAppData->Suspend();
       
  1410    iRecordParser->IgnoreAppData( 1 );
       
  1411 	StartClientHandshakeStateMachine( aStatus );
       
  1412 }
       
  1413 
       
  1414 void CTlsConnection::DeleteStateMachines()
       
  1415 /**
       
  1416  * Deletes the connections' state machines.
       
  1417  */
       
  1418 {
       
  1419 	LOG(Log::Printf(_L("CTlsConnection::DeleteStateMachines()"));)
       
  1420 
       
  1421 	delete iHandshake;
       
  1422 	iHandshake = NULL;
       
  1423    
       
  1424 	delete iRecvAppData;
       
  1425 	iRecvAppData = NULL;
       
  1426 	
       
  1427 	delete iSendAppData;
       
  1428 	iSendAppData = NULL;
       
  1429 }
       
  1430 
       
  1431 void CTlsConnection::CancelAll( TInt aError )
       
  1432 /**
       
  1433  * Cancels all outstanding operations. It is called by the Secure socket API, 
       
  1434  * CTlsConnection::CancelAll().
       
  1435  */
       
  1436 {
       
  1437 	LOG(Log::Printf(_L("CTlsConnection::CancelAll()"));)
       
  1438 
       
  1439 	if ( iRecvAppData )
       
  1440 	{
       
  1441 		iRecvAppData->Cancel( KErrNone );
       
  1442 	}
       
  1443 
       
  1444 	if ( iSendAppData )
       
  1445 	{
       
  1446 		// Send an alert if it is not going to be sent by iHandshake
       
  1447 		iSendAppData->Cancel( iHandshake ? KErrNone : aError );
       
  1448 	}
       
  1449 
       
  1450 	if ( iHandshake )
       
  1451 	{
       
  1452 		iHandshake->Cancel( aError );
       
  1453 		__ASSERT_DEBUG(!iHandshake, TlsPanic(ETlsPanicStateMachineAlreadyExists));
       
  1454 	}
       
  1455 }
       
  1456 
       
  1457 void CTlsConnection::GetServerAddrInfo( TTLSServerAddr& serverInfo )
       
  1458    {
       
  1459 	LOG(Log::Printf(_L("CTlsConnection::GetServerAddrInfo()"));)
       
  1460 	// Find out if there is an existing stored session for the RSocket object.
       
  1461 	TSockAddr sockAddr;		// Endpoint address for the socket object, TBuf<8>
       
  1462 	iRecordComposer->Socket().RemoteName( sockAddr );
       
  1463 	TInetAddr inetAddr( sockAddr );
       
  1464 	if ( sockAddr.Family() != KAfInet6 )
       
  1465 	   {
       
  1466 		inetAddr.ConvertToV4Mapped();
       
  1467 	   }
       
  1468 
       
  1469 	serverInfo.iAddress.Copy(TPtr8( (TUint8*)(&inetAddr.Ip6Address().u.iAddr8[0]), sizeof( TIp6Addr ), sizeof( TIp6Addr )));
       
  1470 	serverInfo.iPort = TUint16(sockAddr.Port()); //see TTLSServerAddr definition
       
  1471 	LOG(Log::Printf(_L("CTlsConnection::GetServerAddrInfo() port: %d"), serverInfo.iPort );)
       
  1472 	LOG(RFileLogger::HexDump(KSSLLogDir,KSSLLogFileName,EFileLoggingModeAppend, NULL, NULL, serverInfo.iAddress.Ptr(), serverInfo.iAddress.Length() ));
       
  1473    }
       
  1474 
       
  1475 TInt CTlsConnection::GetKeyingMaterial(TDes8& aKeyingMaterial)
       
  1476 /*
       
  1477 Performs key generation as per RFC2716 (PPP EAP TLS Authentication Protocol) section 3.5
       
  1478 */
       
  1479 	{
       
  1480 	if(iTlsSession == NULL)
       
  1481 		{
       
  1482 		LOG(Log::Printf(_L("iTlsSession needs to be created to call this function") );)
       
  1483 		return KErrNotReady;
       
  1484 		}
       
  1485 	
       
  1486 	if(aKeyingMaterial.Length()>KKeyingLabelMaxSize)
       
  1487 		{
       
  1488 		LOG(Log::Printf(_L("Supplied Descriptor is too large.  Size=%d Maximum=%d"), aKeyingMaterial.Length(), KKeyingLabelMaxSize);)
       
  1489 		return KErrArgument;
       
  1490 		}
       
  1491 	
       
  1492 	TBuf8<KKeyingLabelMaxSize> keyingLabel;
       
  1493 	keyingLabel.Copy(aKeyingMaterial);
       
  1494 	
       
  1495 	aKeyingMaterial.Zero();
       
  1496 	TInt err = iTlsSession->KeyDerivation(keyingLabel,iTlsSession->Attributes()->iMasterSecretInput, aKeyingMaterial);
       
  1497 	
       
  1498 	if(err == KErrNone && aKeyingMaterial.Length()<=0)
       
  1499 		{
       
  1500 		LOG(Log::Printf(_L("Failed to derive keys"));)
       
  1501 		err = KErrGeneral;
       
  1502 		}
       
  1503 
       
  1504 	return err;
       
  1505 	}