--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/networksecurity/tls/protocol/recordprotocolevents.cpp Tue Jan 26 15:23:49 2010 +0200
@@ -0,0 +1,629 @@
+// 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:
+// Record protocol source file.
+// Describes the implementation of the Record protocol classes: Record parser
+// (CRecordParser) and the Record composer (CRecordComposer).
+//
+//
+
+/**
+ @file
+*/
+
+#include <es_sock.h>
+#include "recordprotocolevents.h"
+#include "AlertProtocolEvents.h"
+#include "handshakereceiveevents.h"
+#include "changecipherevents.h"
+#include "tlshandshake.h"
+
+void CRecordParser::ReConstructL( CStateMachine* aStateMachine, const TPtr8& /*aHeldData*/, CSendAlert& aSendAlert )
+/**
+ * This method sets the iStateMachine and iNext (CAsynchEvent*) data members
+ * inherited from the CAsynchEvent class, in addition to some of its own data members.
+ * It also creates a list of the expected Record protocol content types.
+ */
+ {
+ LOG(Log::Printf(_L("CRecordParser::ReConstructL(CStateMachine*, const TPtr8&, CSendAlert&)"));)
+
+ iStateMachine = aStateMachine;
+
+ if (!iDataIn)
+ {
+ iDataIn = HBufC8::NewL( KTlsRecordPrealocate );
+ }
+
+ ReConstructL();
+
+ CTlsEvent* alertItem = new(ELeave)CRecvAlert( *iStateMachine, *this, aSendAlert );
+ //coverity[leave_without_push]
+ LOG(Log::Printf(_L("CRecvAlert %x - %x"), alertItem, (TUint)alertItem + sizeof( CRecvAlert ));)
+ iExpRecordTypes.AddLast( *alertItem );
+
+ iHandshakeParser = new(ELeave)CHandshakeParser( *iStateMachine, *this);
+ LOG(Log::Printf(_L("CHandshakeParser %x - %x"), iHandshakeParser, (TUint)iHandshakeParser + sizeof( CHandshakeParser ));)
+ iExpRecordTypes.AddLast( *iHandshakeParser );
+ }
+
+
+void CRecordParser::ReConstructL()
+/**
+ * This method resets the state of the object as if it had just been created.
+ */
+ {
+ LOG(Log::Printf(_L("CRecordParser::ReConstructL()"));)
+
+ DestroyList();
+
+ iHeldData.Zero();
+
+ iReadState = iHeldData.Length() ? ETlsFragmentRecord : ETlsReceiveRecordHeader;
+
+ // Add TLS record protocol content types to the list of expected types
+ // It is important that the Handshake parser object is last in the list
+ if (iStateMachine->History() == ETlsHandshakeStart)
+ {
+ // Change Cipher Spec protocol applies only during handshake negotiation
+ __ASSERT_DEBUG( iTlsProvider, TlsPanic(ETlsPanicTlsProviderNotReady));
+ CTlsEvent* ccsItem = new(ELeave)CRecvChangeCipherSpec( *iStateMachine, *this );
+ //coverity[leave_without_push]
+ LOG(Log::Printf(_L("RecvChangeCipherSpec %x - %x"), ccsItem, (TUint)ccsItem + sizeof( CRecvChangeCipherSpec ));)
+ iExpRecordTypes.AddLast( *ccsItem );
+ }
+
+ iNext = NULL;
+ }
+
+
+CRecordParser::~CRecordParser()
+{
+ LOG(Log::Printf(_L("CRecordParser::~CRecordParser()"));)
+
+ DestroyList();
+ delete iDecryptedData;
+ delete iDataIn;
+ Reset();
+}
+
+void CRecordParser::DestroyList()
+{
+ LOG(Log::Printf(_L("CRecordParser::DestroyList() of expected record protocol Content types"));)
+
+ CTlsEvent* listItem;
+
+ TSglQueIter<CTlsEvent> expListIter( iExpRecordTypes );
+ expListIter.SetToFirst();
+ while ( (listItem = expListIter++) != NULL )
+ {
+ iExpRecordTypes.Remove(*listItem);
+ delete listItem;
+ };
+}
+
+void CRecordParser::ChangeCipher()
+{
+ if ( iStateMachine->History() & ETlsChangeCipherSent )
+ {
+ __ASSERT_DEBUG( iActiveTlsSession != iTlsProvider->TlsSessionPtr(), TlsPanic(ETlsPanicInvalidTlsSession));
+ delete iActiveTlsSession;
+ }
+ iActiveTlsSession = iTlsProvider->TlsSessionPtr();
+ iReadSequenceNum = 0;
+}
+
+void CRecordParser::Reset()
+{
+ iReadSequenceNum = 0; // reset the sequence number
+ if ( iTlsProvider && iTlsProvider->TlsSessionPtr() && iActiveTlsSession != iTlsProvider->TlsSessionPtr() )
+ {//this could happen just in case we re-negotiated unsuccessfully but passed CTlsProvider::Create()
+ delete iActiveTlsSession;
+ }
+ iActiveTlsSession = NULL;
+}
+
+CTlsEvent* CRecordParser::LookUpEventL( TInt aRecordType )
+/**
+ * This method is used to determine which record protocol content type (handshake,
+ * change cipher spec, alert, application data) will process a received message.
+ * It cycles through the list of expected record types to see which one would
+ * accept the received record.
+ *
+ * @param aRecordType An integer representing the content type.
+ * @return CTlsEvent* A pointer to the event that will process the received message.
+ */
+{
+ LOG(Log::Printf(_L("CRecordParser::LookUpEventL()"));)
+
+ TSglQueIter<CTlsEvent> expListIter( iExpRecordTypes );
+ expListIter.SetToFirst();
+ CTlsEvent* pEvent;
+
+ while ( ((pEvent = expListIter++) != 0) && !pEvent->AcceptRecord( aRecordType ) )
+ {
+ }
+
+ // When processing application data, NULL is returned as this is the only class processing it
+ if ( !pEvent )
+ {
+ if ( aRecordType != ETlsAppDataContentType )
+ {
+ User::Leave( KErrSSLAlertUnexpectedMessage );
+ }
+ else if ( iStateMachine->History() != KTlsApplicationData )
+ {//application adta received during handshaking
+ if ( iIgnoreRecordAllowed )
+ {//in case client's initiated re-negotiation while the server is still sending some app data
+ LOG(Log::Printf(_L("Application data received while re-negotiating => skip the record"));)
+ iIgnoreRecord = 1;
+ }
+ else
+ {
+ User::Leave( KErrSSLAlertUnexpectedMessage );
+ }
+ }
+ }
+ else
+ {//once i've received any record but application data one no record will be ignored
+ iIgnoreRecordAllowed = 0;
+ iIgnoreRecord = 0;
+ }
+ return pEvent;
+
+}
+
+TInt CRecordParser::ParseHeaderL()
+/**
+ * This method parses the record header to check that the Protocol version is as
+ * expected. It also retrieves and returns the length of the record fragment from
+ * the Record Protocol header.
+ */
+{
+ LOG(Log::Printf(_L("CRecordParser::ParseHeaderL()"));)
+
+ TUint8* dataPtr = (TUint8*) iDataIn->Des().Ptr();
+ iTlsRecordType = static_cast<ETlsRecordType>(dataPtr[KTlsRecordTypeOffset]);
+ iNext = LookUpEventL( iTlsRecordType );
+
+ const TTLSProtocolVersion& tlsVersion = iTlsProvider->Attributes()->iNegotiatedProtocol;
+ if ( tlsVersion.iMajor )
+ {
+ if ( dataPtr[KTlsRecordVersionOffset] != tlsVersion.iMajor ||
+ dataPtr[KTlsRecordVersionOffset + 1] != tlsVersion.iMinor )
+ {
+ User::Leave( KErrSSLAlertProtocolVersion );
+ }
+ }
+ //no protocol's been agreed yet => must be one of these
+ else if ( (dataPtr[KTlsRecordVersionOffset] != KSSL3_0.iMajor ||
+ dataPtr[KTlsRecordVersionOffset + 1] != KSSL3_0.iMinor) &&
+ (dataPtr[KTlsRecordVersionOffset] != KTLS1_0.iMajor ||
+ dataPtr[KTlsRecordVersionOffset + 1] != KTLS1_0.iMinor) )
+ {
+ User::Leave( KErrSSLAlertProtocolVersion );
+ }
+
+ //extract and return the fragment length from the header
+ TBigEndian value;
+ return value.GetValue( dataPtr + KTlsRecordLengthOffset, KTlsRecordBodyLength );
+}
+
+void CRecordParser::CancelAll()
+/**
+ * Cancel all read functionality.
+ * This method should also cancel decompression when it is supported.
+ */
+{
+ LOG(Log::Printf(_L("CRecordParser::CancelAll()"));)
+
+ iSocket.CancelRead();
+ // Cancel the asynchronous service request made.
+ iSocket.CancelRecv();
+ iTlsProvider->CancelRequest();
+ if ( iActiveTlsSession )
+ {
+ iActiveTlsSession->CancelRequest();
+ }
+ ReConstructL();
+}
+
+void CRecordParser::DispatchData()
+{
+ TInt nUserFree = iUserData ? iUserMaxLength - iUserData->Length() : 0;
+ LOG(Log::Printf(_L("CRecordParser::DispatchData() - %x, %d"), iUserData, nUserFree);)
+
+ if ( iHeldData.Length() )
+ {
+ LOG(Log::Printf(_L("iHeldData.Length(), %d"), iHeldData.Length());)
+ // Client has data left. Assert that its buffer exists.
+ __ASSERT_DEBUG( iUserData, TlsPanic(ETlsPanicNoUserData));
+
+ TInt nToCopy = Min( nUserFree, iHeldData.Length() ); // amount of data to copy
+ iUserData->Append( iHeldData.Ptr(), nToCopy );
+
+ TInt n = iHeldData.Length() - nToCopy; // Reset the held data ptr to what is left-over
+ iHeldData.Set( (TUint8*)iHeldData.Ptr() + nToCopy, n, n );
+
+ }
+ else
+ {
+ iHeldData.Set(iPtrHBuf);
+
+ LOG(Log::Printf(_L("iHeldData.Length() == 0 %d"), iHeldData.Length());)
+ if ( iUserData && nUserFree >= iHeldData.Length() )
+ { // User's data buffer is big enough, copy data directly into it.
+ iUserData->Append(iHeldData.Ptr(), iHeldData.Length());
+ iHeldData.Zero();
+ }
+ else if ( iUserData && nUserFree < iHeldData.Length() )
+ { // User's data buffer is not long enough. Copy nUserFree bytes and
+ // save the rest for later
+ iUserData->Append( iHeldData.Ptr(), nUserFree );
+ TInt n = iHeldData.Length() - nUserFree;
+ iHeldData.Set( (TUint8*)iHeldData.Ptr() + nUserFree, n, n ); // Left-over data is in iHeldData
+ }
+ }
+#ifdef _DEBUG
+ if ( iUserData )
+ {
+ LOG(Log::Printf(_L("CRecordParser::DispatchData() end iUserData->Length() = %d, %d"), iUserData->Length(), iHeldData.Length());)
+ }
+#endif
+}
+
+CAsynchEvent* CRecordParser::ProcessL( TRequestStatus& aStatus )
+/**
+ * This asynchronous method parses a received SSL/TLS record.
+ * The record protocol is responsible for decrypting, message authentication (verifying
+ * data), decompressing and reassembling data.
+ *
+ * Note that the record header is transmitted in the clear (i.e., it is not encrypted
+ * or MACed). As such, only the record body is passed through to Security for deciphering
+ * and validation. Also, only NULL compression is supported. MAC verification + Decryption
+ * only happen when security services are active.
+ *
+ * @param aStatus TRequestStatus object
+ * @return CAsynchEvent* A pointer to an asynchronous event (the next event to be processed).
+ */
+{
+
+ if ( iStateMachine->History() == KTlsApplicationData )
+ {
+ LOG(Log::Printf(_L("CRecordParser::ProcessL()"));)
+ }
+ switch ( iReadState )
+ {
+ case ETlsReceiveRecordHeader:
+ {
+ LOG(Log::Printf(_L("CRecordParser::ProcessL() - ETlsReceiveRecordHeader"));)
+
+ // Prepare to receive a new record fragment. Receive the header initially.
+ // Parse it and determine the fragment length. Check that the record
+ // fragment length does not exceed the allowed maximum for a SSL/TLS record
+ if ( iStateMachine->Fragment() ) // For App data rx, this pointer is NULL
+ {
+ iStateMachine->Fragment()->Des().Zero();
+ }
+ iPtrHBuf.Set( (TUint8*)iDataIn->Des().Ptr(), 0, KTlsRecordHeaderSize );
+
+ iSocket.Recv( iPtrHBuf, 0, aStatus );
+ iReadState = ETlsReceiveRecordBody;
+ break;
+ }
+ case ETlsReceiveRecordBody:
+ {
+ TInt fragLength = ParseHeaderL(); // Returns the length of the fragment
+ //parameters swap due to the defect
+ LOG(RFileLogger::HexDump(KSSLLogDir,KSSLLogFileName,EFileLoggingModeAppend, NULL, NULL, iPtrHBuf.Ptr(), iPtrHBuf.Length() ));
+ LOG(Log::Printf(_L("CRecordParser::ProcessL() - ETlsReceiveRecordBody of length %x"), fragLength);)
+
+ User::LeaveIfError( fragLength > KTlsRecordMaxBodySize || fragLength < 0 ? KErrSSLAlertRecordOverflow : KErrNone );
+ if ( fragLength > iDataIn->Des().MaxLength() )
+ {
+ delete iDataIn;
+ iDataIn = NULL;
+ iDataIn = HBufC8::NewL( fragLength );
+ }
+
+ // Read the record fragment and overwrite the header (already been evaluated)
+ iPtrHBuf.Set( (TUint8*)iDataIn->Des().Ptr(), 0, fragLength );
+ iSocket.Recv( iPtrHBuf, 0, aStatus );
+
+ iReadState = ETlsCipherRecord;
+ break;
+ }
+ case ETlsCipherRecord:
+ {
+ LOG(Log::Printf(_L("CRecordParser::ProcessL() - ETlsCipherRecord"));)
+
+ if ( iIgnoreRecord )
+ {//nothing to be done => skip it all
+ iReadState = ETlsReceiveRecordHeader;
+ }
+ else
+ {
+ // Decrypt and verify the MACed record fragment, if appropriate
+ // Initialise the buffer for the plain text data.
+ if (iActiveTlsSession) // Security is active
+ {
+ TRecordProtocol type = (TRecordProtocol) iTlsRecordType;
+ User::LeaveIfError( iActiveTlsSession->DecryptAndVerifyL(iPtrHBuf, iDecryptedData, iReadSequenceNum, type ) );
+ // If error is not zero, it should generate an alert.
+ iPtrHBuf.Set( iDecryptedData->Des() );
+ User::LeaveIfError( iPtrHBuf.Length() > KTlsRecordPlainText ? KErrSSLAlertRecordOverflow : KErrNone );
+ }
+
+ // Update the sequence number
+ iReadSequenceNum++; // Increment the sequence number
+
+ iReadState = ETlsCompressRecord;
+ }
+
+ TRequestStatus* p=&aStatus;
+ User::RequestComplete( p, KErrNone );
+
+ break;
+ }
+ case ETlsCompressRecord:
+ {
+ LOG(Log::Printf(_L("CRecordParser::ProcessL() - ETlsCompressRecord"));)
+
+ // De-compresses the SSL/TLS plain text data. Only NULL compression is
+ // currently supported (identity operation). Fall through to the next state.
+ iReadState = ETlsFragmentRecord;
+ }
+ case ETlsFragmentRecord:
+ {
+ LOG(Log::Printf(_L("CRecordParser::ProcessL() - ETlsFragmentRecord"));)
+
+ // In application data mode, if the Client's data buffer is big enough,
+ // then copy the verified data directly into it as an append. Otherwise,
+ // copy as much as is possible (dependent on the free space in the client's
+ // buffer.
+ // The 'if' statement below solves the case where, in Application data
+ // mode, the clients data buffer (iUserData) is not big enough to hold the
+ // received record fragment. nUserFree is the amount of free space in the
+ // User's data buffer. This is the amount of data that is appended to its
+ // buffer whilst the rest is held till the client frees up space.
+
+ if ( (iStateMachine->History() == KTlsApplicationData && iTlsRecordType == ETlsAppDataContentType) ||
+ (iStateMachine->History() != KTlsApplicationData && iTlsRecordType == ETlsHandshakeContentType))
+ {//don't put wrong data into the user buffer
+ DispatchData();
+ }
+ if ( iHeldData.Length() == 0 )
+ { //prepare to read new record and clear the statemachine buffer
+ iReadState = ETlsReceiveRecordHeader;
+ }
+
+ TRequestStatus* p=&aStatus;
+ User::RequestComplete( p, KErrNone );
+ LOG(Log::Printf(_L("CRecordParser::ProcessL() iNext == %x"), iNext);)
+ return iNext; // record body parser looked up in ParseHeaderL() function
+ // or NULL if in application data mode
+ } // case statement
+ default:
+ {
+ LOG(Log::Printf(_L("CRecordParser::ProcessL() - Default statement, unknown state"));)
+ __ASSERT_ALWAYS( EFalse, TlsPanic(ETlsPanicInvalidProcessState));
+ }
+ } // switch statement
+
+ return this;
+}
+
+//
+void CRecordComposer::ReConstructL( CStateMachine* aStateMachine, TInt aCurrentPos )
+/**
+ * This method sets the iStateMachine and iNext (CAsynchEvent*) data members
+ * inherited from the CAsynchEvent class, in addition to some of its own data members.
+ * It also sets the record's content type. Once set, this will remain, unless it's
+ * interrupted by an alert or handshake negotiation. In this instance, the
+ * ReConstructL() function will be called again.
+ */
+{
+ LOG(Log::Printf(_L("CRecordComposer::ReConstructL()"));)
+
+ iStateMachine = aStateMachine;
+ iWriteState = ETlsFragmentRecord;
+ iCurrentPos = aCurrentPos;
+
+ TUint8* dataPtr = (TUint8*) iDataOut.Ptr();
+ dataPtr[KTlsRecordTypeOffset] = ETlsAppDataContentType; // Default setting
+
+ iNext = 0;
+}
+
+void CRecordComposer::ChangeCipher()
+{
+ if ( iStateMachine->History() & ETlsChangeCipherRecv )
+ {
+ __ASSERT_DEBUG( iActiveTlsSession != iTlsProvider->TlsSessionPtr(), TlsPanic(ETlsPanicInvalidTlsSession));
+ delete iActiveTlsSession;
+ }
+ iActiveTlsSession = iTlsProvider->TlsSessionPtr();
+ iWriteSequenceNum = 0;
+}
+
+void CRecordComposer::ComposeHeader( TInt aLength )
+/**
+ * This method composes a Record protocol header. It sets the Protocol version,
+ * and the length of the Protocol message (the length is in big endian format).
+ *
+ * Note that the content type has previously been set by the message class which
+ * prepared the Record payload. For the first transmitted message (ClientHello),
+ * SSL v3.0 is used (to enable TLS to SSL fallback). The record composer's version
+ * object is then set to NULL.
+ * Subsequent transmitted messages then use the negotiated protocol version.
+ */
+{
+ LOG(Log::Printf(_L("CRecordComposer::ComposeHeader()"));)
+
+ TUint8* dataPtr = (TUint8*) iDataOut.Ptr();
+ if ( iTlsVersion )
+ {
+ dataPtr[KTlsRecordVersionOffset] = iTlsVersion->iMajor;
+ dataPtr[KTlsRecordVersionOffset + 1] = iTlsVersion->iMinor;
+ }
+ else
+ {
+ dataPtr[KTlsRecordVersionOffset] = KSSL3_0.iMajor;
+ dataPtr[KTlsRecordVersionOffset + 1] = KSSL3_0.iMinor;
+ }
+
+ TBigEndian value;
+ value.SetValue( (TUint8*)iDataOut.Ptr() + KTlsRecordLengthOffset, KTlsRecordBodyLength, aLength );
+}
+
+void CRecordComposer::CancelAll()
+/**
+ * Cancel all write functionality.
+ * This method should also cancel compression when it is supported.
+ */
+{
+ LOG(Log::Printf(_L("CRecordComposer::CancelAll()"));)
+
+ iSocket.CancelSend();
+ iTlsProvider->CancelRequest();
+
+ if (iActiveTlsSession)
+ iActiveTlsSession->CancelRequest();
+}
+
+CAsynchEvent* CRecordComposer::ProcessL( TRequestStatus& aStatus )
+/**
+ * This asynchronous method composes a SSL/TLS record.
+ * The record protocol is responsible for fragmenting, compressing, message
+ * authentication (adding a MAC) and encrypting data. It then transmits the result.
+ *
+ * Compression, MAC computation and Encryption only happen when security services are
+ * active. At present, only NULL compression is supported.
+ *
+ * @param aStatus TRequestStatus object
+ * @return CAsynchEvent* A pointer to an asynchronous event (the next event to be
+ * processed).
+ */
+{
+ LOG(Log::Printf(_L("CRecordComposer::ProcessL()"));)
+
+ // Get a pointer to the data to be transmitted via the Record layer.
+ TDesC8* pFragment = iUserData ? iUserData : iStateMachine->Fragment();
+
+ switch ( iWriteState )
+ {
+ case ETlsFragmentRecord:
+ {
+ LOG(Log::Printf(_L("CRecordComposer::ProcessL() - ETlsFragmentRecord"));)
+
+ // Fragments the SSL/TLS plain text data.
+ // The current position within the plain text buffer is initially set to
+ // zero by the state machine (when CRecordComposer::ReconstructL() is called).
+ // The maximum amount of plain text that can be sent is KTlsRecordPlainText
+ // and this data is stored in the iPtrHBuf descriptor.
+
+ iSentPlainTextLength = Min( pFragment->Length() - iCurrentPos, KTlsRecordPlainTextToSend );
+ iPtrHBuf.Set( (TUint8*)pFragment->Ptr() + iCurrentPos, SentPlainTextLength() );
+ iCurrentPos += iSentPlainTextLength; // keep track of fragmented plain text
+
+ iWriteState = ETlsCompressRecord;
+ // Fall through to the next case statement (no TRequestStatus to complete).
+ }
+ case ETlsCompressRecord:
+ {
+ LOG(Log::Printf(_L("CRecordComposer::ProcessL() - ETlsCompressRecord"));)
+
+ // Compresses the SSL/TLS plain text data.
+ // NULL compression only so fall through to the next state
+ iWriteState = ETlsCipherRecord;
+ }
+ case ETlsCipherRecord:
+ {
+ // Apply a MAC and encrypt the compressed SSL/TLS data.
+ // MAC and encryption uses the current SSL/TLS connection state and only
+ // happens when the keys have been created and activated. The connection
+ // state specifies the compression, encryption and MAC algorithms.
+ // Set iPtrEncryptTo to a maximum length of the correct size (plainText + cipherText length)
+ iPtrEncryptTo.Set( (TUint8*)iDataOut.Ptr() + KTlsRecordHeaderSize, 0, iPtrHBuf.Length() + KTlsRecordCipherText);
+
+ // Check that security is active
+ if (iActiveTlsSession)
+ {
+ LOG(Log::Printf(_L("CRecordComposer::ProcessL() - ETlsCipherRecord - Encrypt plain text"));)
+ TRecordProtocol type = (TRecordProtocol) iDataOut[KTlsRecordTypeOffset];
+ User::LeaveIfError( iActiveTlsSession->EncryptL(iPtrHBuf, iEncryptedData, iWriteSequenceNum, type) );
+ iPtrEncryptTo.Copy( iEncryptedData->Des() );
+ User::LeaveIfError( iPtrEncryptTo.Length() > iDataOut.MaxLength() ? KErrSSLAlertRecordOverflow : KErrNone );
+ }
+ else
+ { // No security is active. Copy the data into the iPtrEncryptTo buffer
+ LOG(Log::Printf(_L("CRecordComposer::ProcessL() - ETlsCipherRecord - No Encryption plain text"));)
+ iPtrEncryptTo.Copy(iPtrHBuf);
+ }
+
+ // Get the record length and compose the header. Prepend it to the record data
+ iDataOut.SetLength( iPtrEncryptTo.Length() + KTlsRecordHeaderSize );
+ ComposeHeader( iPtrEncryptTo.Length() );
+ iWriteState = ETlsTransmitRecord;
+ }
+ case ETlsTransmitRecord:
+ {
+ LOG(Log::Printf(_L("CRecordComposer::ProcessL() - ETlsTransmitRecord"));)
+ //parameters swap due to the defect
+ LOG(RFileLogger::HexDump(KSSLLogDir,KSSLLogFileName,EFileLoggingModeAppend, NULL, NULL, iDataOut.Ptr(), iDataOut.Length() ));
+
+ // Transmit the Record data (header + data), activate the Write state (if
+ // appropriate), increment or reset the Sequence number.
+ iSocket.Send( iDataOut, 0, aStatus );
+
+ iWriteSequenceNum++; // Increment the sequence number
+ if ( iDataOut[KTlsRecordTypeOffset] == ETlsChangeCipherContentType )
+ {
+ ChangeCipher();
+ }
+
+ iWriteState = ETlsFragmentRecord;
+
+ // Check to see if there is any more plain text data to secure and transmit.
+ // If yes, process this data. Otherwise, process the next asynchronous event.
+ // The content type is reset to Application data as a default
+
+ if ( iCurrentPos >= pFragment->Length() )
+ {
+ if ( !IsAppData() )
+ { // See CSendAppData::OnCompletion().
+ iCurrentPos = 0; // All the plain text has been secured and transmitted
+ }
+
+ return iNext;
+ }
+
+ break;
+ }
+ default:
+ {
+ LOG(Log::Printf(_L("CRecordComposer::ProcessL() - Default statement, unknown state"));)
+ break;
+ }
+ } // switch statement
+
+ return this;
+}
+
+CRecordComposer::~CRecordComposer()
+/**
+ * Standard Destructor.
+ */
+{
+ LOG(Log::Printf(_L("CRecordComposer::~CRecordComposer()"));)
+ delete iEncryptedData;
+}