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.