我正在使用一个传输库,该库可以模拟Berkeley套接字API来使用它(具有阻塞和非阻塞模式)。需要向我发送的数据添加TLS加密,并且可以想到两种方式:
自定义BIO:找到了Socket BIO的代码,因此考虑对其进行复制并将所有berkeley套接字调用替换为该库的函数。但是,我在网上找不到有关自定义BIO的太多信息,因此请谨慎对待我在没有太多帮助的情况下遇到的陷阱。
Memory BIO:这种方法有更多的关注者,也有很多示例。尽管,大多数人警告说,具有非阻塞套接字的Memory BIO比阻塞路由要复杂一个数量级。
关于内存BIO方法,我看到的源代码对我来说很有意义,但这只是一个简单的回显客户端/服务器。让我感到困惑的是,当SSL_Read / SSL_Write返回SSL_WANT_READ或SSL_WANT_WRITE时该怎么办。我的理解是,在使用Blocking Socket BIO的情况下,您只需稍后重试该调用,因为底层代码将处理所有事情。
如果是Memory BIO +无阻塞插槽,例如如果SSL_Read返回SSL_WANT_WRITE,这是否意味着我的代码应随后从输出BIO(BIO_read)读取并将其发送到套接字,并且在原始SSL_Read调用成功之前也不允许任何SSL_Read / SSL_Write?在这段时间内允许SSL_Write可以吗?
编辑:我将仅使用TLS 1.3,只是发现它不支持重新协商。这是否意味着一旦建立连接,我完全不必担心SSL_Read上的WANT_WRITE和SSL_Write上的WANT_READ?
答案 0 :(得分:1)
“如果使用内存BIO +非阻塞套接字,例如SSL_Read返回SSL_WANT_WRITE,那是否意味着我的代码应随后从输出BIO(BIO_read)中读取并将其发送到套接字” - -是的取出输出BIO中的所有字节并将其写入套接字。
here解释了为什么会发生这种情况:
任何TLS / SSL I / O功能都可以导致SSL_ERROR_WANT_READ和 SSL_ERROR_WANT_WRITE。特别是SSL_read_ex(),SSL_read(), SSL_peek_ex()或SSL_peek()可能要写入数据,而SSL_write()或 SSL_write_ex()可能要读取数据。这主要是因为TLS / SSL 协议期间的任何时候都可能发生握手(由 客户端还是服务器); SSL_read_ex(),SSL_read(), SSL_peek_ex(),SSL_peek(),SSL_write_ex()和SSL_write()将处理 任何未完成的握手。
一旦SSL_read以这种方式失败,我认为对SSL_read的进一步尝试不会成功,除非您将更多字节写入到输入bio中。
与此同时,您可以尝试进一步进行SSL_write;只需检查返回码和SSL状态,以检查数据是否被部分完全转移。
我在github
上写了一些示例代码