// 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:
//
#include "T_TLS_test.h"
#include <e32svr.h>
#include <ssl.h>
#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
#include <ssl_internal.h>
#endif
const TInt KHexDumpWidth = 16;
const TInt KEAPKeyLength = 128+64;
TInt CTLSTest::RunError( TInt aError )
{
iTestStep->Log( _L("RunL err %d"), aError );
if ( iTlsSocket )
{
iTlsSocket->Close();
delete iTlsSocket;
iTlsSocket = 0;
}
iInUse = EFalse;
return KErrNone;
}
CTLSTest* CTLSTest::NewL()
{
CTLSTest* self = new(ELeave) CTLSTest;
CleanupStack::PushL( self );
self->ConstructL();
CleanupStack::Pop();
return self;
}
// Constructor should also call the parent constructor to set the priority
// of the active object.
CTLSTest::CTLSTest() : CActive(0)
{
}
CTLSTest::~CTLSTest()
{
// Cancel any outstanding request
Cancel();
delete iTlsSocket;
delete iTlsSocket2;
delete iGenericSocket;
iTimer.Close();
// Close the resources in the reverse order
iHostResolver.Close();
iSocket.Close();
iSocketServ.Close();
// __UHEAP_MARK;
// __UHEAP_MARKEND;
}
void CTLSTest::ConstructL()
{
// Connect the socket server
User::LeaveIfError( iSocketServ.Connect() );
// Create a local timer
User::LeaveIfError( iTimer.CreateLocal() );
// Connect to a host resolver
User::LeaveIfError( iHostResolver.Open( iSocketServ, KAfInet, KProtocolInetTcp ) );
iRunState = ESocketConnected;
iInUse = EFalse;
CActiveScheduler::Add( this );
}
void CTLSTest::RunL()
{
THTTPMessage *iMyHTTP;
TInt err = KErrNone;
#ifdef __WINS__
TText margin = 0;
TText header = 0;
TSockXfrLength aLen;
#endif
switch ( iRunState )
{
case ESocketConnected:
{
iTestStep->Log( _L("STATE: ENotSecureConnected Status: %d"), iStatus.Int() );
// As the receive buffer is static, set it's length to 0 here,
// so if there is an error somewhere, the previous buffer's contents
// wont be dumped to the log file again.
iRcvBuffer.SetLength( 0 );
iBytesRead = 0;
iTotalBytesRead = 0;
iFirstRunFlag = ETrue;
if ( iStatus != KErrNone )
{
iTestStep->Log( KStateErrConnected, iStatus.Int() );
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
//=========================================================
// Construct the Tls socket
if ( !iTlsSocket )
{
TInt lcode = KErrNone;
if(iUseGenericSocket)
{
iTestStep->Log( _L("Creating SecureSocket using Generic Socket") );
TRAP(lcode, iTlsSocket = CSecureSocket::NewL( *iGenericSocket, iProtocol ) );
}
else
{
iTestStep->Log( _L("Creating SecureSocket using RSocket") );
TRAP(lcode, iTlsSocket = CSecureSocket::NewL( iSocket, iProtocol ) );
}
if ( lcode )
{
iTestStep->Log( _L("Error creating secure socket: %d"), lcode );
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
}
//=========================================================
if( iEAPKeyDerivation )
{
if(KeyDerivationTests(EFalse) != KErrNone)
{
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
}
//======================================================================================
// Set any options before the handshake starts
if ( !iTlsSocket2 )
{
iTestStep->Log( _L("Flush session cache") );
iTlsSocket->FlushSessionCache();
}
//=========================================================
// Set the cipher suite list
if ( iCipherSuites.Length() > 1 )
{
// Create the buffer with the cipher suites
TBuf8<KCipherBufSize> cipherBuf;
// TBuf8<KCipherBufSize> iCipherSuites;
TBuf8<3> tempBuf;
TInt i;
TInt value;
TInt ret = KErrNone;
TInt cCount = 0; // used as an array index into the cipherBuf descriptor
TLex8 myLex;
// The cipher buffer will actually be the same length as the aCipherSuite passed in
// because it's in binary format with leading 0's.
cipherBuf.SetLength( iCipherSuites.Length() );
iTestStep->Log( _L("Cipher suites") );
for ( i=0; i<iCipherSuites.Length(); i+=2 )
{
// iCipherSuites contains a list of decimal values for each cipher suite that
// the client should offer to use. They are in a string format, so each decimal
// value takes 2 bytes.
//
// Copy the 2 bytes of one value into a buffer so that it can be converted into
// a real decimal value;
tempBuf.SetLength( 2 );
tempBuf[0] = iCipherSuites[i];
tempBuf[1] = iCipherSuites[i+1];
myLex.Assign( tempBuf );
ret = myLex.Val( value );
if ( ret!=KErrNone )
{
break; // from for loop
}
iTestStep->Log( _L(":%X"), value );
if ( value == 99 )
{
cipherBuf[ cCount++ ] = 0xFF;
cipherBuf[ cCount++ ] = 0xFF;
}
else
{
// The actual cipher suite list that must be passed in the socket options
// is in a binary format of 0x0,0xCipherValue,0x0,CipherValue etc
cipherBuf[ cCount++ ] = 0;
cipherBuf[ cCount++ ] = (unsigned char)value;
}
} // end of for loop
if ( cipherBuf.Length() )
{
#ifdef __WINS__
iTestStep->Log( _L("Setting avilable cipher suites") );
HexDump( &header, &margin, &cipherBuf[0], cipherBuf.Length() );
#endif
ret = iTlsSocket->SetOpt(KSoEnableNullCiphers, KSolInetSSL, ETrue);
if ( ret != KErrNone )
{
TPtrC errorText = iTestStep->EpocErrorToText(ret);
iTestStep->Log( _L("Couldnt set NULL cipher suite option :%S (%d)"),&errorText, ret );
iTestPassed = EFalse;
}
ret = iTlsSocket->SetAvailableCipherSuites( cipherBuf );
if ( ret != KErrNone )
{
TPtrC errorText = iTestStep->EpocErrorToText(ret);
iTestStep->Log( _L("Couldnt set available cipher suites error:%S (%d)"),&errorText, ret );
iTestPassed = EFalse;
}
}
iTestStep->Log( _L("") );
} // end of if iciphersuites .length
// end of setting the cipher suite list
//=========================================================
TBuf<8> prot;
err = iTlsSocket->Protocol( prot );
//*****************************************************
if ( !err )
{
iTestStep->Log( _L("Protocol set for use:") );
iTestStep->Log( prot );
}
err = iTlsSocket->SetProtocol( prot );
if ( err )
{
iTestStep->Log( _L("Failed to set Protocol for use: (%d)"),err );
}
// Set the domain name we're connecting to...
iStatus = iTlsSocket->SetOpt(KSoSSLDomainName,KSolInetSSL, iDNSName);
if ( iStatus != KErrNone )
{
iTestStep->Log( KStateErrReceivePage, iStatus.Int() );
iTestStep->Log( KStateErrReceivePage, iStatus.Int() );
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTlsSocket->Close();
iTimer.After( iStatus, 1000000 );
}
// end of setting options
//======================================================================================
else
{
//=========================================================
// start the handshake
iTlsSocket->StartClientHandshake( iStatus );
//=========================================================
iRunState = ESecureConnected;
}
SetActive();
break;
}
case ESecureConnected:
case ESecureRenegotiated:
{
iTestStep->Log( _L("STATE: ESecureConnected/ESecureRenegotiated Status: %d"), iStatus.Int() );
// The secure connection has now been made.
// Send a get request for the page.
// Send the get request
if ( iStatus != KErrNone )
{
TPtrC errorText = iTestStep->EpocErrorToText(iStatus.Int());
iTestStep->Log( _L("ESecureConnected:%S %d"),&errorText, iStatus.Int() );
iTestStep->Log( KStateErrReceivePage, iStatus.Int() );
iTestStep->Log( KStateErrReceivePage, iStatus.Int() );
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTlsSocket->Close();
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
else
{
iTestStep->Log( _L("ESecureConnected:KErrNone %d"),iStatus.Int() );
}
TDes8* pSendDes;
if ( !iTlsSocket2 )
{
pSendDes = &iRcvBuffer;
iRcvBuffer.SetLength( iRcvBuffer.MaxLength() );
iTestStep->Log( _L("Sending %d bytes"), iRcvBuffer.Length() );
}
else
{
pSendDes = &iSndBuffer;
// Can a simple "GET /page.htm" request be used?
if ( iSimpleGet )
{
iSndBuffer.Copy( _L("GET ") );
iSndBuffer.Append( iPage );
iSndBuffer.Append( _L("") );
iTestStep->Log( _L("Using simple get") );
}
else
{
// build and send a HTTP GET request to retrieve a page
iMyHTTP = new THTTPMessage;
iMyHTTP->Method(_L8("GET"));
iMyHTTP->URI( iPage );
iMyHTTP->AddHeaderField(_L8("Connection"),_L8("close"));
iMyHTTP->AddHeaderField(_L8("User-Agent"),_L8("SSL_TEST"));
iMyHTTP->AddHeaderField(_L8("Accept-Encoding"));
iMyHTTP->AddHeaderField(_L8("Accept"),_L8("*/*"));
iMyHTTP->GetHeader(iSndBuffer);
delete iMyHTTP;
}
iTestStep->Log( KLogSendingRequest );
#ifdef __WINS__
HexDump( &header, &margin, &iSndBuffer[0], iSndBuffer.Length() );
#endif
}
iRunState = iRunState == ESecureRenegotiated ? EGetRequestSentReneg : EGetRequestSent;
//=========================================================
// send the request
iTlsSocket->Send( *pSendDes, iStatus, iBytesSent );
//=========================================================
if( iEAPKeyDerivation )
{
if(KeyDerivationTests(ETrue) != KErrNone)
{
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
}
SetActive();
break;
}
case EGetRequestSent:
case EGetRequestSentReneg:
{
// The get request has been sent, can now try and receive the data
iTestStep->Log( _L("STATE: EGetRequestSent/EGetRequestSentReneg Status: %d"), iStatus.Int() );
if ( iStatus != KErrNone )
{
iTestStep->Log( _L("EGetRequestSent: %d"), iStatus.Int() );
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTlsSocket->Close();
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
// Before that, check which cipher suite has been negotiated.
TBuf8<4> buf;
// no need to set descriptor length as in case with the old getopt,
// CurrentCipherSuite will do that
err = iTlsSocket->CurrentCipherSuite( buf );
if ( err )
{
iTestStep->Log( _L("CurrentCipherSuite: %d"), err );
}
else
{
#ifdef __WINS__
iTestStep->Log( _L("Cipher suite in use:") );
HexDump( &header, &margin, &buf[0], buf.Length() );
#endif
}
// Get the servers certificate
const CX509Certificate *servCert = iTlsSocket->ServerCert();
if ( servCert )
{
GetCertInfo( *servCert );
}
else
{
iTestStep->Log( _L("No server certificate is available") );
}
// Get the protocol version string
TBuf<32> protocol;
err = iTlsSocket->Protocol( protocol );
if ( !err )
{
iTestStep->Log( _L("Protocol used in connection:") );
iTestStep->Log( protocol );
}
// New tests added as part of GT167 Zephyr.
// These tests are not meant to be in a logical order. They simply exercise the
// Secure socket API. Logical ordering of the tests should happen in further
// development of the TLS test code and all supported APIS should be called/tested.
// Get the Client certificate
const CX509Certificate *clientCert = iTlsSocket->ClientCert();
if ( clientCert )
{
GetCertInfo( *clientCert );
}
else
{
iTestStep->Log( _L("No client certificate is available") );
}
// Get the Client cert mode. This API is NOT supported in client mode.
TClientCertMode certMode = iTlsSocket->ClientCertMode();
if ( certMode )
{
iTestStep->Log( _L("ClientCertMode() is not supported, Default value is: %d"), EClientCertModeIgnore );
iTestStep->Log( _L("Current mode setting is: %d"), certMode );
}
iTestStep->Log( _L("Set Client Cert mode to: %d"), EClientCertModeOptional );
err = iTlsSocket->SetClientCertMode(EClientCertModeOptional);
if (err != KErrNotSupported)
{
iTestStep->Log( _L("SetClientCertMode Failed: %d"), err );
}
// Get the Dialog mode.
TDialogMode dialogMode = iTlsSocket->DialogMode();
iTestStep->Log( _L("Dialog mode setting is: %d"), dialogMode );
// GetOpt() API: Current cipher suite option
TUint optionName = KSoCurrentCipherSuite;
TUint optionLevel = KSolInetSSL;
TBuf8<30> option; // Note that the size of 30 is arbitrary.
TInt retValue = iTlsSocket->GetOpt(optionName, optionLevel, option);
// GetOpt() API: Available cipher cipher suites option
option.FillZ(); // reset the descriptor before reuse
option.Zero();
optionName = KSoAvailableCipherSuites;
retValue = iTlsSocket->GetOpt(optionName, optionLevel, option);
// GetOpt() API: Dialog mode option
option.FillZ(); // reset the descriptor before reuse
option.Zero();
optionName = KSoDialogMode;
retValue = iTlsSocket->GetOpt(optionName, optionLevel, option);
// GetOpt() API: Server certificate option
option.FillZ(); // reset the descriptor before reuse
option.Zero();
optionName = KSoSSLServerCert;
// retValue = iTlsSocket->GetOpt(optionName, optionLevel, option);
// SetOpt() API: Dialog mode option
option.FillZ(); // reset the descriptor before reuse
option.Zero();
optionName = KSoDialogMode;
// retValue = iTlsSocket->SetOpt(optionName, optionLevel, option);
// End of the addition of new tests for GT167 Zephyr
iRunState = iRunState == EGetRequestSent ? EDataReceived : EDataReceivedReneg;
if ( iTlsSocket2 )
{
iRcvBuffer.Zero();
iTlsSocket->Recv( iRcvBuffer, iStatus );
SetActive();
break;
}
iRcvBuffer.Zero();
if( iEAPKeyDerivation )
{
if(KeyDerivationTests(ETrue) != KErrNone)
{
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTlsSocket->Close();
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
}
// Fall through
}
case EDataReceived:
case EDataReceivedReneg:
{
iTestStep->Log( _L("STATE: EDataReceived/EDataReceivedReneg Status: %d"), iStatus.Int() );
iTestStep->Log( _L("EDataReceived length:%d"), iRcvBuffer.Length() );
// Any error other than KErrEof means the test is a failure
if ( iStatus!=KErrNone && iStatus!=KErrEof)
{
// Close the socket neatly
iRunState = EConnectionClosed;
iTlsSocket->Close();
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
// Log the received buffer
if ( iRcvBuffer.Length() )
{
iTestStep->Log( KLogBytesRead, iRcvBuffer.Length() );
#ifdef __WINS__
HexDump( &header, &margin, &iRcvBuffer[0], iRcvBuffer.Length() );
#endif
iTotalBytesRead += iRcvBuffer.Length();
if ( iStatus==KErrEof )
{
iRunState = EConnectionClosed;
iTlsSocket->Close();
iTimer.After( iStatus, 1000000 );
if( iEAPKeyDerivation )
{
if(KeyDerivationTests(EFalse) != KErrNone)
{
iTestPassed = EFalse;
}
}
}
else
{
//read again
iRcvBuffer.SetLength( 0 );
iTlsSocket->Recv( iRcvBuffer, iStatus );
}
SetActive();
break;
}
else
{
if ( iRunState == EDataReceived )
{
iRunState = ESecureRenegotiated;
iTestStep->Log( _L("******* Trying renegotiate *******") );
iTlsSocket->FlushSessionCache();
iTlsSocket->RenegotiateHandshake( iStatus );
if( iEAPKeyDerivation )
{
if(KeyDerivationTests(ETrue) != KErrNone)
{
iRunState = EConnectionClosed;
iTestPassed = EFalse;
iTlsSocket->Close();
iTimer.After( iStatus, 1000000 );
SetActive();
break;
}
}
SetActive();
break;
}
else
{
iRunState = EConnectionClosed;
}
}
// Fall through
}
case EConnectionClosed:
{
iTestStep->Log( _L("STATE: EConnectionClose Status: %d"), iStatus.Int() );
if ( iStatus != KErrNone )
{
iTestStep->Log( KStateErrFinished, iStatus.Int() );
iTestStep->Log( KStateErrFinished, iStatus.Int() );
iTestPassed = EFalse;
}
if ( iTotalBytesRead )
{
iTestStep->Log( KLogBytesRead, iTotalBytesRead );
}
if ( iTestPassed )
{
iTestStep->iTestStepResult = EPass;
iTestStep->Log( KLogTestPassed );
}
else
{
iTestStep->iTestStepResult = EFail;
iTestStep->Log( KLogTestFailed );
}
if ( iTlsSocket2 ) //to test abreviatted handshake
{
iInUse = EFalse;
iTlsSocket->Close();
delete iTlsSocket;
iTlsSocket =0;
delete iTlsSocket2;
iTlsSocket2 =0;
}
else if ( iTlsSocket )
{//keep the first instance live not to destroy the session cache
iTlsSocket2 = iTlsSocket;
iTlsSocket = NULL;
iTestStep->Log(_L("Connecting to %s:%d"), iAddress.PtrZ(), iPortNum );
iTlsSocket2->Close();
User::LeaveIfError( iSocket.Open( iSocketServ, KAfInet, KSockStream, KProtocolInetTcp ) );
iSocket.Connect( iInetAddr, iStatus );
SetActive();
iRunState = ESocketConnected;
}
else
{
iInUse = EFalse;
}
// can wait here for an unload of the ssl.dll to make sure that a session is not
// reconnected next time. The option to set the unload timeout via a SetOpt
// may not currently work, so this is a sure way to stop a reconnection.
if ( iTestEndDelay )
{
iTestStep->Log( _L("Waiting for %d seconds"), iTestEndDelay );
User::After( 1000000 * iTestEndDelay );
}
break;
}
case EDummyConnection:
iTestStep->Log( _L("STATE: EDummyConnection Status: %d"), iStatus.Int() );
iInUse = EFalse;
break;
// end switch
}
}
void CTLSTest::DoCancel()
{
// Cancel the connect
iSocket.CancelConnect();
}
void CTLSTest::ConnectL( const TDesC &aAddress,
const TInt aPortNum,
const TDesC &aPage,
const TDesC8 &aCipherSuite,
const TInt aCipher,
const TInt aSimpleGet,
const TInt aTestEndDelay,
const TDesC8& aDNSName ,
const TDesC& aProtocol,
TBool aUseGenericSocket,
TBool aEAPKeyDerivation )
{
#if 0
iRunState = EDummyConnection;
TRequestStatus* p=&iStatus;
User::RequestComplete( p, KErrNone );
SetActive();
return;
#endif
TInt err;
TNameEntry nameEntry;
TNameRecord nameRecord;
TSockAddr sockAddr;
iInUse = ETrue;
err = iInetAddr.Input( aAddress );
if ( err != KErrNone )
{
err = iHostResolver.GetByName( aAddress, nameEntry );
if ( err == KErrNone )
{
nameRecord = nameEntry();
sockAddr = nameRecord.iAddr;
iInetAddr = iInetAddr.Cast( sockAddr );
}
}
iInetAddr.SetPort( aPortNum );
iAddress = aAddress;
iDNSName = aDNSName;
iPortNum = aPortNum;
iCipherSuites.Copy( aCipherSuite );
iProtocol.Copy( aProtocol );
iCipher = aCipher;
iPage.Copy( aPage );
iSimpleGet = aSimpleGet;
iTestEndDelay = aTestEndDelay;
iUseGenericSocket = aUseGenericSocket;
iEAPKeyDerivation = aEAPKeyDerivation;
// Print info to the log
iTestStep->Log( _L("*****Connecting to*****") );
iTestStep->Log( _L("%s:%d "), iAddress.PtrZ(), iPortNum );
// Open the socket
User::LeaveIfError( iSocket.Open( iSocketServ, KAfInet, KSockStream, KProtocolInetTcp ) );
if(iUseGenericSocket)
{
iGenericSocket = new(ELeave)CGenericSecureSocket<RSocket>(iSocket);
}
iTestPassed = ETrue;
iCiphersMatch = EFalse;
iRunState = ESocketConnected;
// Open the socket
User::LeaveIfError( iInetAddr.Input( iAddress ));
iInetAddr.SetPort( iPortNum );
iTestStep->Log(_L("Connecting to %s:%d"), iAddress.PtrZ(), iPortNum );
iSocket.Connect( iInetAddr, iStatus );
SetActive();
}
void CTLSTest::SetConsole( CTestStepTls * aTestStep )
{
iTestStep = aTestStep;
}
TBool CTLSTest::InUse()
{
return iInUse;
}
TBool CTLSTest::TestingSite( const TDesC &aAddress, const TInt aPortNum )
{
TInt match = iAddress.Compare( aAddress );
if ( ( aPortNum == iPortNum ) && ( match == 0 ) && ( iInUse ) )
return ETrue ;
else
return EFalse;
}
void CTLSTest::HexDump(const TText* aHeader, const TText* aMargin, const TUint8* aPtr, TInt aLen)
{
TBuf<0x100> buf;
buf.SetLength(0);
TInt i = 0;
const TText* p = aHeader;
while (aLen>0)
{
TInt n = aLen>KHexDumpWidth ? KHexDumpWidth : aLen;
buf.AppendFormat(_L("%s%04x : "), p, i);
TInt j;
for (j=0; j<n; j++)
buf.AppendFormat(_L("%02x "), aPtr[i+j]);
while (j++<KHexDumpWidth)
buf.AppendFormat(_L(" "));
buf.AppendFormat(_L(" "));
for (j=0; j<n; j++)
{
TUint8 byteAsChar;
byteAsChar = aPtr[i+j]<32 || aPtr[i+j]>126 ? '.' : aPtr[i+j];
if ((byteAsChar == '%') || (byteAsChar == '<'))
byteAsChar = '.';
buf.AppendFormat(_L("%c"), byteAsChar );
}
iTestStep->Log(buf);
buf.SetLength(0);
aLen -= n;
i += n;
p = aMargin;
}
}
TInt CTLSTest::GetCertInfo(const CX509Certificate& aSource)
{
TText margin = 0;
TText header = 0;
iTestStep->Log( _L("------Certificate Info------") );
iTestStep->Log( _L("FingerPrint") );
HexDump( &header, &margin, aSource.Fingerprint().Ptr(), aSource.Fingerprint().Length() );
iTestStep->Log( _L("SerialNumber") );
HexDump( &header, &margin, aSource.SerialNumber().Ptr(), aSource.SerialNumber().Length() );
const CSubjectPublicKeyInfo& publicKeyInfo = aSource.PublicKey();
iTestStep->Log( _L("PublicKeyInfo") );
HexDump( &header, &margin, publicKeyInfo.KeyData().Ptr(), publicKeyInfo.KeyData().Length() );
iTestStep->Log( _L("----------------------------") );
return KErrNone;
}
TInt CTLSTest::KeyDerivationTests(TBool aSocketOpen)
{
if( aSocketOpen )
{
// Input should be no longer than 100 bytes
iTestStep->Log( _L("Attempt to get EAP Keys with too large an input descriptor") );
TBuf8<KEAPKeyLength> tooBig;
tooBig.Fill('X',101);
TInt err = iTlsSocket->GetOpt(KSoKeyingMaterial, KSolInetSSL, tooBig);
if(err != KErrArgument)
{
iTestStep->Log( _L("FAILED: Did not return KErrArgument. Error: %d"), err );
if(err == KErrNone)
{
err = KErrGeneral;
}
return err;
}
iTestStep->Log( _L("Passed") );
// Descriptor should be of size to fit 128+64 bytes
iTestStep->Log( _L("Attempt to get EAP Keys with too small an input descriptor") );
TBuf8<KEAPKeyLength-5> tooSmall;
err = iTlsSocket->GetOpt(KSoKeyingMaterial, KSolInetSSL, tooSmall);
if(err != KErrArgument)
{
iTestStep->Log( _L("FAILED: Did not return KErrArgument. Error: %d"), err );
if(err == KErrNone)
{
err = KErrGeneral;
}
return err;
}
iTestStep->Log( _L("Passed") );
// Should be able to generate key
iTestStep->Log( _L("Attempt to get EAP Keys with a valid input descriptor") );
TBuf8<KEAPKeyLength+5> retVal;
err = iTlsSocket->GetOpt(KSoKeyingMaterial, KSolInetSSL, retVal);
if(err != KErrNone)
{
iTestStep->Log( _L("FAILED: Call failed with error: %d"), err );
if(err == KErrNone)
{
err = KErrGeneral;
}
return err;
}
if(retVal.Length() != KEAPKeyLength)
{
iTestStep->Log( _L("FAILED: Call OK but Key returned is the wrong size. Expected=%d Actual=%d"), 128+64, retVal.Length() );
err = KErrGeneral;
return err;
}
iTestStep->Log( _L("Passed") );
}
else
{
// Can only generate keys whilst have an open socket that has completed the SSL handshake
iTestStep->Log( _L("Attempt to get EAP Keys before handshake/after socket closed") );
TBuf8<KEAPKeyLength> retVal;
TInt err = iTlsSocket->GetOpt(KSoKeyingMaterial, KSolInetSSL, retVal);
if(err != KErrNotReady)
{
iTestStep->Log( _L("FAILED: Did not return KErrNotReady. Error: %d"), err );
if(err == KErrNone) err = KErrGeneral;
return err;
}
iTestStep->Log( _L("Passed") );
}
return KErrNone;
}