in platform/posix/transport/src/openssl_posix.c [582:709]
OpensslStatus_t Openssl_Connect( NetworkContext_t * pNetworkContext,
const ServerInfo_t * pServerInfo,
const OpensslCredentials_t * pOpensslCredentials,
uint32_t sendTimeoutMs,
uint32_t recvTimeoutMs )
{
OpensslParams_t * pOpensslParams = NULL;
SocketStatus_t socketStatus = SOCKETS_CONNECT_FAILURE;
OpensslStatus_t returnStatus = OPENSSL_SUCCESS;
int32_t sslStatus = 0;
uint8_t sslObjectCreated = 0;
SSL_CTX * pSslContext = NULL;
/* Validate parameters. */
if( ( pNetworkContext == NULL ) || ( pNetworkContext->pParams == NULL ) )
{
LogError( ( "Parameter check failed: pNetworkContext is NULL." ) );
returnStatus = OPENSSL_INVALID_PARAMETER;
}
else if( pOpensslCredentials == NULL )
{
LogError( ( "Parameter check failed: pOpensslCredentials is NULL." ) );
returnStatus = OPENSSL_INVALID_PARAMETER;
}
else
{
/* Empty else. */
}
/* Establish the TCP connection. */
if( returnStatus == OPENSSL_SUCCESS )
{
pOpensslParams = pNetworkContext->pParams;
socketStatus = Sockets_Connect( &pOpensslParams->socketDescriptor,
pServerInfo, sendTimeoutMs, recvTimeoutMs );
/* Convert socket wrapper status to openssl status. */
returnStatus = convertToOpensslStatus( socketStatus );
}
/* Create SSL context. */
if( returnStatus == OPENSSL_SUCCESS )
{
pSslContext = SSL_CTX_new( TLS_client_method() );
if( pSslContext == NULL )
{
LogError( ( "Creation of a new SSL_CTX object failed." ) );
returnStatus = OPENSSL_API_ERROR;
}
}
/* Setup credentials. */
if( returnStatus == OPENSSL_SUCCESS )
{
/* Enable partial writes for blocking calls to SSL_write to allow a
* payload larger than the maximum fragment length.
* The mask returned by SSL_CTX_set_mode does not need to be checked. */
/* MISRA Directive 4.6 flags the following line for using basic
* numerical type long. This directive is suppressed because openssl
* function #SSL_CTX_set_mode takes an argument of type long. */
/* coverity[misra_c_2012_directive_4_6_violation] */
( void ) SSL_CTX_set_mode( pSslContext, ( long ) SSL_MODE_ENABLE_PARTIAL_WRITE );
sslStatus = setCredentials( pSslContext, pOpensslCredentials );
if( sslStatus != 1 )
{
LogError( ( "Setting up credentials failed." ) );
returnStatus = OPENSSL_INVALID_CREDENTIALS;
}
}
/* Create a new SSL session. */
if( returnStatus == OPENSSL_SUCCESS )
{
pOpensslParams->pSsl = SSL_new( pSslContext );
if( pOpensslParams->pSsl == NULL )
{
LogError( ( "SSL_new failed to create a new SSL context." ) );
returnStatus = OPENSSL_API_ERROR;
}
else
{
sslObjectCreated = 1u;
}
}
/* Setup the socket to use for communication. */
if( returnStatus == OPENSSL_SUCCESS )
{
returnStatus =
tlsHandshake( pServerInfo, pOpensslParams, pOpensslCredentials );
}
/* Free the SSL context. */
if( pSslContext != NULL )
{
SSL_CTX_free( pSslContext );
pSslContext = NULL;
}
/* Clean up on error. */
if( ( returnStatus != OPENSSL_SUCCESS ) && ( sslObjectCreated == 1u ) )
{
SSL_free( pOpensslParams->pSsl );
pOpensslParams->pSsl = NULL;
}
/* Log failure or success depending on status. */
if( returnStatus != OPENSSL_SUCCESS )
{
LogError( ( "Failed to establish a TLS connection." ) );
if( socketStatus == SOCKETS_SUCCESS )
{
Sockets_Disconnect( pOpensslParams->socketDescriptor );
}
}
else
{
LogDebug( ( "Established a TLS connection." ) );
}
return returnStatus;
}