Thanks for reply matt.Yeah your correct I want implement completely from
starch as my agenda is to have complete manged code in my server app and i
did't find any manged manged crypto library with will is compatable with
Open SSL Client. Client will still remain using with Open SSL libraries
.There will not be any changes in client appWhen can i find the complete low
level details including the raw byte structure  of initial handshake between
the client and server and the internal logic used for encryption and
decryption.I am understood of how Diffie Hellman works but i need to know
how Open SSL client excepts initial handshake for exchange of DH public
parameters.Here is my current server code which uses Open SSL . I want to
rewrite this part with my own implementation in c# with out using Open SSL
Libraries.#include "StdAfx.h"#include "sslserver.h"namespace OSSL{      
namespace
Server  {          // Global declarations          int listenSd;                
///             /// SSLServer
Initialises SSL context and load Diffie HielMann parameters             ///     
SSLServer::SSLServer(String* DHFilePath)                {                       
try                     {                               m_pIDClientsList =
new CLIENTS_LIST();                             m_pcsClients  = new 
CRITICAL_SECTION();                 
m_pcsAcceptThreadLoop = new CRITICAL_SECTION();                                 
                // Initialise of SSL                    
Init();                                                 // 
win32_locking_callback                       
InitializeCriticalSection(m_pcsClients);                        
InitializeCriticalSection(m_pcsAcceptThreadLoop);                               
// Set the Diffe
HielMann parameters                             
LoadDHParams(m_pSSLCtx,DHFilePath);                             // Keep the
acceptor socket running until stopped from BNG                          
m_shouldStopAcceptThread =
false;                  }                       catch(Exception* ex)            
        {                               // Event entry                  
LogManager::Instance->WriteEntry("SSLServer:",ex);                      }       
        }               ///             ///
Initialise SSL context          ///             SSL_CTX * SSLServer::Init()     
        {                       // Create a
new SSL_CTX object                      m_pSSLCtx = 
SSL_CTX_new(SSLv23_server_method());                        //
SSL_CTX couldnt be created                      if(m_pSSLCtx == NULL)           
        {                       
LogManager::Instance->WriteEntry("SSLServer:Init:SSL_CTX could not be
created");                      }                       
SSL_CTX_set_verify(m_pSSLCtx,SSL_VERIFY_NONE,NULL);             
SSL_CTX_set_options(m_pSSLCtx, SSL_OP_ALL |
SSL_OP_NO_SSLv2|SSL_OP_SINGLE_DH_USE);                                          
// Set cipher list
"ADH:@STRENGTH"                 if(1 != SSL_CTX_set_cipher_list(m_pSSLCtx,
"ADH:@STRENGTH"))                       {                       
LogManager::Instance->WriteEntry("SSLServer:Init:Error in ADH:Strength");       
        
}                       return m_pSSLCtx;               }               ///     
        /// Accept TCP/IP Connections from the
clients                         ///             /// Returns false if the accept 
socket could not be bound.      
bool SSLServer::AcceptConnections()             {                       int 
fileDescriptor;                     struct
sockaddr_in socketServer;                       struct sockaddr_in 
socketClient;                        size_t
clientLength;                   // Create a socket and bind                 
listenSd =
socket(AF_INET, SOCK_STREAM, 0);                        memset (&socketServer, 
'\0',
sizeof(socketServer));                  socketServer.sin_family      = AF_INET; 
        
socketServer.sin_addr.s_addr = INADDR_ANY;                      
socketServer.sin_port        =
htons(ConfigManager::GetConfigAsInt(Constants::TcpPortNumber));                 
                        int
bindRes = bind(listenSd, (struct sockaddr*) &socketServer,
sizeof(socketServer));                  // If the listener socket could not be 
bound, throw
an exception and return immediately                     if (bindRes < 0)        
                {                               Exception*
bindEx = new Exception("Could not bind TCP port. Service will shutdown.");      
                
LogManager::Instance->WriteEntry("SSLServer::AcceptConnecetions", bindEx);      
                
return false;                   }                       while(1)                
        {                               // See if the thread has been requested
to stop by BNG                          if (GetShouldStopAcceptThread())        
                        {                                       break;          
                }                        
try                       {                               // Listen for 
incoming connections                              listen (listenSd,
99);                              clientLength = sizeof(socketClient);          
                  // Accept the
connection                                fileDescriptor = accept(listenSd, 
(struct sockaddr*)
&socketClient, (int*) &clientLength);                                           
                  // Get client ipaddress                                
String* ipAddress = socketClient.sin_addr.S_un.S_un_b.s_b1.ToString();          
                 
ipAddress =
ipAddress->Concat(ipAddress,".",socketClient.sin_addr.S_un.S_un_b.s_b2.ToString());
                              
ipAddress =
ipAddress->Concat(ipAddress,".",socketClient.sin_addr.S_un.S_un_b.s_b3.ToString());
                              
ipAddress =
ipAddress->Concat(ipAddress,".",socketClient.sin_addr.S_un.S_un_b.s_b4.ToString());
                              
// Store the new client information                               pClientData = 
new
CLIENTDATA(m_pSSLCtx);                            pClientData->IpAddress =
DotNetStringToCppString(ipAddress);                               // Check if 
initialization for new
client failed                             if(pClientData->m_FailedInit)         
                  {                                       // Event entry        
                                 
Exception* ex = new Exception("pClientData->m_FailedInit failed");              
                         
LogManager::Instance->WriteEntry("SSLServer:AcceptConnections",ex);             
                  }                              
// Set the socket file descriptor                                 
SSL_set_fd(pClientData->m_pSSL,
fileDescriptor);                                                                
  // Perform SSL Handshake                               
if(SSL_accept(pClientData->m_pSSL) <=0)                           {             
                           // Event entry                                       
 
String *errorLog;                                         
errorLog->Concat("Error in SSL handshake on accept
from ", ipAddress);                                       Exception* ex = new 
Exception(errorLog);                                       
LogManager::Instance->WriteEntry("SSLServer:AcceptConnections",ex);             
                  }                              
else                              {                                     try     
                                {                                               
// Store the Client information by mapping to
its File descriptor value                                               
EnterCriticalSection(m_pcsClients);                                     
(*m_pIDClientsList)[fileDescriptor] = pClientData;                              
        
LeaveCriticalSection(m_pcsClients);                                     }       
                                catch(Exception* ex)                            
        {                                       
LeaveCriticalSection(m_pcsClients);                                     
LogManager::Instance->WriteEntry("SSLServer:AcceptConnections:Error in
adding client information",ex);                                 }               
                  }                       }                     
catch(std::exception&
e)                      {                                 
closesocket(listenSd);                                          Exception* ex = 
new
Exception("std::exception& e");                          
LogManager::Instance->WriteEntry("Connection lost.
SSLServer:AcceptConnections.", ex);                     }                       
  catch (...)                     {                              
closesocket(listenSd);                            
LogManager::Instance->WriteEntry("Connection
lost. SSLServer:AcceptConnections.");                     }                     
}                       closesocket(listenSd);          
return true;            }               ///             /// Get the incoming 
messages from clients via
SSL_read                ///             void SSLServer::ReadData()              
{                       int nRead = 0;                  int Error =
0;                      int rc = 0;                     int max_sd = 0;         
        char buf[10000];                        fd_set selectFD;                
timeval timeout;                        // clear all File descriptors from 
Select list before
calling Select() API                    FD_ZERO(&selectFD);                     
// Iterate through the client
information                     std::map<int, CLIENTDATA __nogc*>::iterator i =
m_pIDClientsList->begin();                      for(;i != 
m_pIDClientsList->end();++i)                  {                       
// Get the Max value of the File descriptor                             max_sd =
max(i->first,max_sd);                           FD_SET(i->first,&selectFD);     
                }                       // If the max
value of File Descriptor is zero, then do nothing                       
if(max_sd == 0)                 {                       
return;                 }                       // Set the timeout interval for 
Select                  timeout.tv_sec = 0;             
timeout.tv_usec = 10*10;                        rc = select(max_sd
+1,&selectFD,NULL,NULL,&timeout);                       // If Select operation 
failed on the
available File descriptors                      if(rc<0)                        
{                               // Event entry                          
Exception* ex
= new Exception("Select() failed");                     
LogManager::Instance->WriteEntry("SSLServer:ReadData",ex);                      
        return;                 }               
// If none of the clients are currently communicating, then                     
// Just look
up for incoming data a little while later                       if(rc==0)       
                {                               return;                 }       
                                
// Loop for all the clients                     for(i= 
m_pIDClientsList->begin(); i !=
m_pIDClientsList->end();)                       {                               
// Get the File Descriptor of the client                        
int sock = i->first;                            // Check if this client if 
currently sending data                       
if(FD_ISSET(sock,&selectFD))                            {                       
                try                                     {                       
                
EnterCriticalSection(m_pcsClients);                                             
// Get the incoming data from the
client                                          nRead = 
SSL_read(i->second->m_pSSL, buf, 10000);                                        
        Error =
SSL_get_error(i->second->m_pSSL, nRead);                                        
LeaveCriticalSection(m_pcsClients);                                     }       
                                catch (...)                                     
{                                       
LogManager::Instance->WriteEntry("Stopped. SSLServer:ReadData:Error in
SSL_read");                                             
LeaveCriticalSection(m_pcsClients);                                             
return;                                 }                               
// Check if the data is obtained successfully                                   
if(nRead > 0)                                   {                               
        
Byte data[] = new Byte[nRead];                                          
Marshal::Copy(IntPtr(buf), data, 0,
nRead);                                         
//LogManager::Instance->WriteEntry(String::Format("SSL {0}
bytes read", Convert::ToString(nRead)));                                        
        // Send data to BNG
Application                                             
PassDataToBNG(data,i->second->IpAddress.c_str() ,
nRead,sock);                                                                    
                        // Delete the allocated memory                          
                delete [] data;                                 
data = NULL;                                    }                               
        else                                    {                               
                // If there was any error in getting
client's data                                           /*if(Error == 
SSL_ERROR_ZERO_RETURN)                                            {             
                                          
Exception* ex = new Exception("SSL READ FAILED");                               
                
LogManager::Instance->WriteEntry("SSLServer:ReadData:
SSL_ERROR_ZERO_RETURN",ex);                                             }       
                                        else*/ if(Error == SSL_ERROR_SSL)       
                                
{                                                       Exception* ex = new 
Exception("SSL READ FAILED");                                               
LogManager::Instance->WriteEntry("SSLServer:ReadData: SSL_ERROR_SSL",ex);       
                                
}                                               else if(Error == 
SSL_ERROR_WANT_READ)                                           {                
                                       Exception* ex =
new Exception("SSL READ FAILED");                                               
LogManager::Instance->WriteEntry("SSLServer:ReadData:
SSL_ERROR_WANT_READ",ex);                                               }       
                                        else if(Error == SSL_ERROR_WANT_WRITE)  
                                
{                                                       Exception* ex = new 
Exception("SSL READ FAILED");                                               
LogManager::Instance->WriteEntry("SSLServer:ReadData:
SSL_ERROR_WANT_WRITE",ex);                                              }       
                                        else                                    
        {                                                       Exception* ex = 
new
Exception("SSL READ FAILED");                                                   
LogManager::Instance->WriteEntry("Client
connection lost. SSLServer:ReadData. SSL READ FAILED");                         
                }                                               // Raise
the Disconnect event, as the client has disconnected                            
        
SendDisconnectEvent(i->second->IpAddress.c_str(),sock);                         
                // Close the
socket and remove the client's information, as we dont need it                  
                
closesocket(sock);                                              
DisconnectFromClient(i->first);                                         
FD_CLR(sock,
&selectFD);                                             // Iterate through the 
loop from the beginning                                          i=
m_pIDClientsList->begin();                                              
continue;                                       }                               
                                                 // Clear off the
File descriptor value from SelectFD list                                        
 FD_CLR(sock, &selectFD);                                }                      
        
// Process for the next client                          ++i;                    
 }              }               ///             /// Send the outgoing
client messages vie SSL_Write           ///             void 
SSLServer::SendData(int
fileDescriptor, Byte data[], int length)                {               
EnterCriticalSection(m_pcsClients);                     int nBytesWritten= 0;   
                int Error = 0;          
int max_sd = 0;                 timeval timeout;                        int rc 
= 0;                     fd_set selectFD;                                       
         //
clear all File descriptors from Select list before calling Select() API         
FD_ZERO(&selectFD);                     const unsigned char __pin* pBuf = 
&data[0];             
CLIENTDATA* pClientData;                        try                     {       
                        // Check and get the Client info based
on the File descriptor value                    
if(GetClientInfo(fileDescriptor,pClientData))                           {       
                                try                                     {       
                                        max_sd
= fileDescriptor;                                               
FD_SET(fileDescriptor,&selectFD);                                               
// Set the
timeout interval for Select                                             
timeout.tv_sec = 60;                                            timeout.tv_usec 
=
0;                                              rc = select(max_sd 
+1,NULL,&selectFD,NULL,&timeout);                                            
if(rc >0)                                       
{                                                       
if(FD_ISSET(fileDescriptor,&selectFD))                                          
        {                                                       
//LogManager::Instance->WriteEntry(String::Format("Writing {0} bytes",
Convert::ToString(length)));                                                    
        // Send the data to the client                                          
        
nBytesWritten = SSL_write(pClientData->m_pSSL,pBuf,length);                     
                                        Error =
SSL_get_error(pClientData->m_pSSL,nBytesWritten);                               
                        }                                               }       
                                        else                                    
{                                                       char error_buf[100];    
                                                if(rc == -1)                    
                                        rc =
WSAGetLastError();                                                      
sprintf_s(error_buf, "SSL WRITE FAILED: ErrorCode:
%d", rc);                                                       Exception* ex = 
new Exception(error_buf);                                               
LogManager::Instance->WriteEntry("SSLServer:SendData : Select() call failed
on write",ex);                                          }                       
                }                                       catch (...)             
                        {                                               // 
"Error" is logged
below                                   }                                       
// Check if there was any error in SSL write                                    
if(Error !=
SSL_ERROR_NONE)                                 {                               
                if(Error == SSL_ERROR_ZERO_RETURN)                              
                {                                                       
Exception* ex = new Exception("SSL WRITE FAILED");                              
                
LogManager::Instance->WriteEntry("SSLServer:SendData:
SSL_ERROR_ZERO_RETURN",ex);                                             }       
                                        else if(Error == SSL_ERROR_SSL)         
                        
{                                                       Exception* ex = new 
Exception("SSL WRITE FAILED");                                              
LogManager::Instance->WriteEntry("SSLServer:SendData: SSL_ERROR_SSL",ex);       
                                
}                                               else if(Error == 
SSL_ERROR_WANT_READ)                                           {                
                                       Exception* ex =
new Exception("SSL WRITE FAILED");                                              
LogManager::Instance->WriteEntry("SSLServer:SendData:
SSL_ERROR_WANT_READ",ex);                                               }       
                                        else if(Error == SSL_ERROR_WANT_WRITE)  
                                
{                                                       Exception* ex = new 
Exception("SSL WRITE FAILED");                                              
LogManager::Instance->WriteEntry("SSLServer:SendData:
SSL_ERROR_WANT_WRITE",ex);                                              }       
                                        else                                    
        {                                                       Exception* ex = 
new
Exception("SSL WRITE FAILED");                                          
LogManager::Instance->WriteEntry("SSLServer:SendData",ex);                      
                        }                                       }               
                
ERR_remove_state(0);                            }                       }       
                catch(Exception* ex)                    {                       
LogManager::Instance->WriteEntry("SSLServer:SendData:Exception in sending
data",ex);                      }                       
LeaveCriticalSection(m_pcsClients);             }               ///             
/// Load the
Diffe HellMann parameters from the file         ///                     DH*
SSLServer::LoadDHParams(SSL_CTX * m_pSSLCtx,String* DHFilePath)         {       
                // Get
the filepath from App.config file                       char* DHFile =
(char*)(void*)Marshal::StringToHGlobalAnsi(DHFilePath);                         
                // Load the BIO
with the DH parameters                  BIO *bio(BIO_new_file(DHFile,"r"));     
                if(! bio)                       {                       
// Event entry                          Exception* ex = new Exception("Error in 
loading the DH
file");                         
LogManager::Instance->WriteEntry("SSLServer:LoadDHParams",ex);          
}                       dh1024=PEM_read_bio_DHparams(bio,NULL,NULL,NULL);       
                // Set the DH
paramters to the SSL Context                    
if(SSL_CTX_set_tmp_dh(m_pSSLCtx,dh1024)<0)              
{                               // Event entry                          
Exception* ex = new Exception("Error in setting DH
parameters for SSL_CTX_set_tmp_dh");                    
LogManager::Instance->WriteEntry("SSLServer:LoadDHParams",ex);                  
}               
BIO_free(bio);                  Marshal::FreeHGlobal(DHFile);                   
return dh1024;          }               ///     
/// Convert System::String* to std::string              ///                     
std::string
SSLServer::DotNetStringToCppString(System::String* dotNetString)                
{                       char*
str = (char*)(void*)Marshal::StringToHGlobalAnsi(dotNetString);         
std::string ret(str);                   Marshal::FreeHGlobal(str);              
        return ret;             }               ///     
/// Disconnect the client and remove client's information               ///     
                void 
SSLServer::DisconnectFromClient(int fileDescriptor)             {               
        try                     {                       
CLIENTDATA* pClientData;                                pClientData =
(*m_pIDClientsList)[fileDescriptor];                            
SSL_shutdown(pClientData->m_pSSL);                      
RemoveClient(fileDescriptor);                   }                       
catch(Exception* ex)                    {                       
LogManager::Instance->WriteEntry("SSLServer:DisconnectFromClient",ex);          
        }       
}                       ///             /// Gets the clientInfo based on the 
file descriptor            ///             
bool SSLServer::GetClientInfo(int fileDescriptor, CLIENTDATA __nogc*&
pClientData)            {                       bool returnValue = false;       
        
EnterCriticalSection(m_pcsClients);                     if(m_pIDClientsList == 
NULL)                    {                       
LeaveCriticalSection(m_pcsClients);                             return 
returnValue;                     }                       // Look for
the client based on the File descriptor                 CLIENTS_LIST::iterator 
iter =
m_pIDClientsList->find(fileDescriptor);                 if(iter !=
m_pIDClientsList->end())                        {                               
pClientData = iter->second;                             returnValue =
true;                   }                       else                    {       
                        returnValue = false;                            }       
        
LeaveCriticalSection(m_pcsClients);                     return returnValue;     
        }               ///             ///
Remove the client's information         ///                     void 
SSLServer::RemoveClient(int
fileDescriptor)         {                       
EnterCriticalSection(m_pcsClients);                             
if(m_pIDClientsList != NULL)                    {                               
CLIENTS_LIST::iterator iter =
m_pIDClientsList->find(fileDescriptor);                         if(iter !=
m_pIDClientsList->end())                                {                       
                delete iter->second;                                    
iter->second =
NULL;                                   
m_pIDClientsList->erase(fileDescriptor);                                }       
                }               
LeaveCriticalSection(m_pcsClients);             }               ///             
/// Free all used memory                ///             
void SSLServer::Dispose(bool disposing)         {                       
ERR_remove_state(0);            
if(m_pIDClientsList != NULL)                    {                               
EnterCriticalSection(m_pcsClients);                     
CLIENTS_LIST::iterator iter = m_pIDClientsList->begin();                        
        for(; iter !=
m_pIDClientsList->end(); iter++)                                {               
                        delete iter->second;                            
iter->second = NULL;                            }                       
m_pIDClientsList->erase(m_pIDClientsList->begin(), m_pIDClientsList->end());    
                
delete m_pIDClientsList;                                m_pIDClientsList = 
NULL;                        
LeaveCriticalSection(m_pcsClients);                     }                       
if(!disposing)                  {                       
DeleteCriticalSection(m_pcsClients);                            delete 
m_pcsClients;                            m_pcsClients
= NULL;                         DeleteCriticalSection(m_pcsAcceptThreadLoop);   
                        delete
m_pcsAcceptThreadLoop;                          m_pcsAcceptThreadLoop = NULL;   
                        m_pSSLMethod =
NULL;                           if(m_pSSLCtx != NULL)                           
{                                       // Free allocated SSL_CTX object        
                        
SSL_CTX_free(m_pSSLCtx);                                        m_pSSLCtx = 
NULL;                               }                       }                }  
            ///             ///
Closes the listener socket              ///                     void 
SSLServer::CloseSockets()          {               
closesocket(listenSd);          }               ///             /// Returns the 
flag which tells SSLServer
whether or not to exit the socket accept thread         ///             bool
SSLServer::GetShouldStopAcceptThread()          {                       bool 
result;            
EnterCriticalSection(m_pcsAcceptThreadLoop);                    result =
m_shouldStopAcceptThread;                       
LeaveCriticalSection(m_pcsAcceptThreadLoop);            
return result;          }               ///             /// Sets the flag which 
tells SSLServer whether or
not to exit the socket accept thread            ///             void
SSLServer::SetShouldStopAcceptThread(bool shouldStop)           {               
EnterCriticalSection(m_pcsAcceptThreadLoop);                    
m_shouldStopAcceptThread =
shouldStop;                     LeaveCriticalSection(m_pcsAcceptThreadLoop);    
        }       }}



--
View this message in context: 
http://openssl.6102.n7.nabble.com/Diffie-hellman-Open-SSL-Client-and-C-Server-tp47524p47527.html
Sent from the OpenSSL - User mailing list archive at Nabble.com.

Reply via email to