使用Memory BIO直接读/写握手数据

我需要创建一个OpenSSL连接,我可以直接读/写握手数据。 原因是握手数据将以UDP连接方式传输(DTLS不是一个选项,因为数据不是直接在数据报中,而是在另一个协议包内,如果你好奇则是EAP )。 到目前为止,我已经创建了一个OpenSSL连接,但我甚至无法读取客户端的握手以发送到服务器。

在我的研究中,我发现我需要一个Memory BIO来读取/写入连接,但无法弄清楚如何提取握手数据。 以下是我初始化客户端连接的方法:

SSL_library_init(); SSL_load_error_strings(); OpenSSL_add_all_algorithms(); ctx = SSL_CTX_new(SSLv3_client_method()); SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); ssl = SSL_new(ctx); rbio = BIO_new(BIO_s_mem()); wbio = BIO_new(BIO_s_mem()); SSL_set_bio(ssl, rbio, wbio); SSL_set_connect_state(ssl); 

我尝试过doint SSL_connect来启动握手:

 int ret = SSL_connect(ssl); 

但返回-1 ,并执行SSL_get_error(ssl, res)我得到一个错误代码2 ,然后我用该代码执行ERR_error_string并得到:

 error:00000002:lib(0):func(0):system lib 

此外,如果我使用SSL_do_handshake而不是SSL_connect我会得到完全相同的错误。

我已经能够通过TCP设置OpenSSL连接,但从未使用Memory BIO进行此操作,因此对此的任何帮助都将非常感激。 谢谢!

最后,我得到它的工作,我是以正确的方式:

需要函数SSL_set_connect_state(ssl)来告知连接为握手初始化做好准备。 然后,我们调用SSL_do_handshake(ssl)来启动握手。 此函数将返回-1因为握手未完成,但我们实际上可以从客户端ssl连接BIO编写器读取并使用我们想要的协议(在我的情况下,通过UDP的EAP RADIUS数据包)发送数据。

客户

 ctx = SSL_CTX_new(SSLv3_client_method()); SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); ssl = SSL_new(ctx); rbio = BIO_new(BIO_s_mem()); wbio = BIO_new(BIO_s_mem()); SSL_set_bio(ssl, rbio, wbio); SSL_set_connect_state(ssl); SSL_do_handshake(ssl); // This will return -1 (error) as the handshake is not finished, we can ignore it. char buf[4096]; BIO_read(wbio, buf, 4096); // Read from BIO, put data in buffer // Then use data in buffer to send to the server 

另一方面,应使用凭证和私钥配置服务器。 此外,我们应该使用SSL_set_accept_state()代替SSL_set_accept_state()因为服务器将等待客户端的握手问候。 然后,我们简单地将客户端握手hello数据写入服务器BIO读取器:

服务器

 ctx = SSL_CTX_new(SSLv3_server_method()); // This is the server! SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); ssl = SSL_new(ctx); rbio = BIO_new(BIO_s_mem()); wbio = BIO_new(BIO_s_mem()); SSL_set_bio(ssl, rbio, wbio); SSL_set_accept_state(ssl); // The server uses SSL_set_accept_state // Here we get the data from the client suppose it's in the variable buf // and write it to the connection reader BIO. BIO_write(rbio, buf, strlen(buf)); if (!SSL_is_init_finished(ssl)) { SSL_do_handshake(ssl); } 

我们可以使用SSL_is_init_finished(ssl)函数来检查握手是否已完成,并且在未完成时我们调用SSL_do_handshake(ssl) ,然后再次从BIO_writer读取数据以将数据发送到客户端。

客户端和服务器之间的此过程应该完成,直到连接完成(即SSL_is_init_finished(ssl)返回true )。

然后,在握手完成后,您可以使用SSL_readSSL_write函数在客户端/服务器之间发送安全数据。 希望这个简短的解释对某人有用!

试试这个

 // Connect the TCP socket (this is client side) int sock = tcp_connect(host, port); // Create BIO around the connected TCP socket BIO *sbio = BIO_new_socket(sock, BIO_NOCLOSE); SSL_set_bio(ssl,sbio,sbio); int ret = SSL_connect(ssl); 

把BIO想象成套接字。 对于客户端,您必须使用connect(…)调用为其提供一个连接到所需主机和端口的套接字。 对于服务器端,只需使用从accept(…)调用返回的套接字。