This is on a WIN2000 server using VC++6.0. Eventually the server side will be multi-threaded, that's why the Mutex setup. Any help is appreciated. BTW - I'm also encountering Memory leaks so if anyone has any suggestions along those lines I could use them. Server side Error: 1832:error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number:.\ssl\s3_pkt.c:290: Server Side/Client Side Common class methods/functions (cMemoryBlob is a dynaiclly growing memory buffer): cSSL g_objSSL; bool cSSL::m_bLockCreated = false; HANDLE *cSSL::m_pMutex=NULL; int cSSL::m_iNumLocks=0; cSSL::cSSL() { if(!m_bLockCreated) { int iLoop; m_iNumLocks = CRYPTO_num_locks(); m_bLockCreated = true; m_pMutex = new HANDLE[m_iNumLocks]; for(iLoop=0; iLoop<m_iNumLocks; iLoop++) m_pMutex[iLoop] = CreateMutex(NULL, FALSE, NULL); } CRYPTO_set_locking_callback(&cSSL::ssl_lock); // CRYPTO_set_id_callback(); // Not needed for Windows or Linux m_bErrorStringsLoaded=true; SSL_load_error_strings(); m_pServerCTX=NULL; m_bServerCTXCreated=false; m_pClientCTX=NULL; m_bClientCTXCreated=false; rSeed(); OpenSSL_add_ssl_algorithms(); ssl_thread_start(); } cSSL::~cSSL() { ssl_thread_done(); if(m_bServerCTXCreated) SSL_CTX_free(m_pServerCTX); if(m_bClientCTXCreated) SSL_CTX_free(m_pClientCTX); if(m_bErrorStringsLoaded) ERR_free_strings(); RAND_cleanup(); // frees memory used by the PRNG OBJ_cleanup(); EVP_cleanup(); // for OpenSSL_add_all_algorithms() EVP_PBE_cleanup(); //ASN1_STRING_TABLE_cleanup(); BIO_sock_cleanup(); /*X509V3_EXT_cleanup(); X509_PURPOSE_cleanup(); X509_TRUST_cleanup(); */ //ERR_remove_state(0); OBJ_NAME_cleanup(-1); /* -1 for everything */ CRYPTO_set_locking_callback(NULL); if(m_bLockCreated) { int iLoop; m_bLockCreated = false; for(iLoop=0; iLoop<m_iNumLocks; iLoop++) CloseHandle(m_pMutex[iLoop]); delete[] m_pMutex; m_pMutex=NULL; m_iNumLocks=0; } } void cSSL::ssl_thread_start(void) { } void cSSL::ssl_thread_done(void) { ERR_remove_state(0); } SSL_CTX *cSSL::ClientCTX(void) { if(!m_bClientCTXCreated) { SSL_METHOD *meth = SSLv3_client_method(); m_pClientCTX = SSL_CTX_new(meth); SSL_CTX_set_options(m_pClientCTX, 0 /* ALL off*/); SSL_CTX_set_cipher_list(m_pClientCTX, "ADH-DES-CBC3-SHA"); //"EXP-ADH-DES-CBC-SHA"); m_bClientCTXCreated = true; } return m_pClientCTX; } SSL_CTX *cSSL::ServerCTX(void) { if(!m_bServerCTXCreated) { SSL_METHOD *meth = SSLv3_server_method(); m_pServerCTX = SSL_CTX_new(meth); SSL_CTX_set_quiet_shutdown(m_pServerCTX, 1 /* on */); SSL_CTX_set_options(m_pServerCTX, 0 /* ALL off*/); DH *dh = get_dh1024(); SSL_CTX_set_tmp_dh(m_pServerCTX, dh); DH_free(dh); SSL_CTX_set_cipher_list(m_pServerCTX, "ADH-DES-CBC3-SHA"); //"EXP-ADH-DES-CBC-SHA"); int sess_id_ctx=1; SSL_CTX_set_session_id_context(m_pServerCTX, (const unsigned char*)&sess_id_ctx, sizeof(sess_id_ctx)); m_bServerCTXCreated = true; } return m_pServerCTX; } void cSSL::rSeed(void) { RAND_screen(); ::rSeed(); } long cSSL::sendBIO(BIO *pBio, long lLength, BYTE *pData, long &lTimeOut) { long lOffset = 0; long lWritten = 0; while(lLength - lOffset> 0) { lWritten = BIO_write(pBio, &(pData[lOffset]), lLength - lOffset); if(lWritten <=0) { if(BIO_should_retry(pBio) && lTimeOut-- > 0) { if(!SwitchToThread()) Sleep(1); lWritten = 0; continue; } ERR_print_errors_fp(stderr); return -1; } lOffset += lWritten; } return lOffset; } long cSSL::sendBIOPrefixed(BIO *pBio, long lLength, BYTE *pData, long &lTimeOut) { long lWritten = 0; lWritten = sendBIO(pBio, sizeof(lLength), (BYTE *) &lLength, lTimeOut); if(lWritten == sizeof(lLength)) lWritten += sendBIO(pBio, lLength, pData, lTimeOut); return lWritten; } long cSSL::sendBIOSuffixed(BIO *pBio, long lLength, BYTE *pData, char cSuffix, long &lTimeOut) { long lWritten = 0; lWritten = sendBIO(pBio, lLength, pData, lTimeOut); if(lWritten == lLength) lWritten += sendBIO(pBio, sizeof(cSuffix), (BYTE *) &cSuffix, lTimeOut); return lWritten; } long cSSL::readBIO(BIO *pBio, long lLength, BYTE **ppData, long &lTimeOut) { BYTE buf[4096]; long lRead = 0; cMemoryBlob objMemBlob; *ppData = NULL; if(lLength <= 0 || lLength > 2000000000) lLength = 2000000000; do { lRead=BIO_read(pBio, buf, __min(sizeof(buf), lLength)); if(lRead == 0) break; if(lRead < 0) { if(BIO_should_retry(pBio) && lTimeOut-- > 0) { if(!SwitchToThread()) Sleep(1); lRead = 1; continue; } ERR_print_errors_fp(stderr); return -1; } objMemBlob.Append(lRead, buf); lLength -= lRead; } while(lRead && lLength); lRead = objMemBlob.GetBufSize(); if(lRead > 0) { objMemBlob.Reset(); *ppData = new BYTE[lRead]; objMemBlob.Read(lRead, *ppData); } return lRead; } long cSSL::readBIOPrefixed(BIO *pBio, BYTE **ppData, long &lTimeOut) { long *plLength = NULL; long lLength; long lOut; if((lOut = readBIO(pBio, sizeof(long), (BYTE **) &plLength, lTimeOut)) > 0) { lLength = *plLength; delete plLength; if(lLength > 0) if((lOut = readBIO(pBio, lLength, ppData, lTimeOut)) < 0) return lLength; } return lOut; } long cSSL::readBIOSuffixed(BIO *pBio, BYTE **ppData, char cSuffix, long &lTimeOut) { long lRead = 0; long lOut; BYTE *pData = NULL; cMemoryBlob objMemBlob; do { if(pData) delete pData; if((lOut = readBIO(pBio, sizeof(char), &pData, lTimeOut)) <= 0) return lOut; objMemBlob.Append(sizeof(char), pData); lRead++; } while(*pData != cSuffix && lRead < 2000000000); lRead = objMemBlob.GetBufSize() - 1; if(lRead > 0) { objMemBlob.Reset(); *ppData = new BYTE[lRead]; objMemBlob.Read(lRead, *ppData); } return lRead; } void cSSL::ssl_lock(int mode, int n, const char *file, int line) { if(mode & CRYPTO_LOCK) { WaitForSingleObject(m_pMutex[n-1], INFINITE); } else { ReleaseMutex(m_pMutex[n-1]); } } Simple Server program: int main(void) { BIO *pBio = BIO_new_accept("*:1111"); BIO_set_nbio(pBio, 1); BIO *pSSLBio = BIO_new_ssl(g_objSSL.ServerCTX(), 0); BIO_set_accept_bios(pBio, pSSLBio); { char cOutput[] = "I hear you."; int iLen = strlen(cOutput); char buf[4096]; int iRead=1; long lTimeOut = 1000000; char *pData=NULL; if((iRead = g_objSSL.readBIOPrefixed(pBio, (BYTE **) &pData, lTimeOut)) > 0) { strncpy(buf, pData, iRead); buf[iRead]=0; printf ("Got %d chars:'%s'\n", iRead, buf); delete pData; if(g_objSSL.sendBIOPrefixed(pBio, iLen, (BYTE *) cOutput, lTimeOut) <= 0) puts("Error in encrypted Write!"); } else puts("Error in encrypted Read!"); } BIO_ssl_shutdown(pBio); BIO_free_all(pBio); return 0; } Simple Client program: int main () { BIO *pBio = BIO_new_connect("localhost:1111"); BIO_set_nbio(pBio, 1); BIO *pSSLBio = BIO_new_ssl_connect(g_objSSL.ClientCTX()); BIO_push(pSSLBio, pBio); { char cOutput[] = "Hello World!"; int iLen = strlen(cOutput); char buf[4096]; int iRead=1; long lTimeOut = 10000; char *pData=NULL; if(g_objSSL.sendBIOPrefixed(pBio, iLen, (BYTE *) cOutput, lTimeOut) > 0) { if((iRead = g_objSSL.readBIOPrefixed(pBio, (BYTE **) &pData, lTimeOut)) > 0) { strncpy(buf, pData, iRead); buf[iRead]=0; printf ("Got %d chars:'%s'\n", iRead, buf); } else puts("Error in encrypted Read!"); delete pData; } else puts("Error in encrypted Write!"); } BIO_ssl_shutdown(pSSLBio); BIO_free_all(pSSLBio); return 0; } ______________________________________________________________________ OpenSSL Project http://www.openssl.org User Support Mailing List [EMAIL PROTECTED] Automated List Manager [EMAIL PROTECTED]