在OpenSSL中使用内存BIO时,如何找到输入BIO的“所需大小”?

时间:2016-01-19 19:51:52

标签: c++ openssl

以下是一些示例代码,展示了我如何使用OpenSSL:

BIO *CreateMemoryBIO() {
    if (BIO *bio = BIO_new(BIO_s_mem())) {
        BIO_set_mem_eof_return(bio, -1);    
        return bio;
    }
    throw std::runtime_error("Could not create memory BIO");
}

m_readBIO = CreateMemoryBIO();
m_writeBIO = CreateMemoryBIO();
SSL_set_bio(m_ssl, m_readBIO, m_writeBIO);

现在,如果我执行了SSL_Read,我得到了SSL_ERROR_WANT_READ,有什么方法可以让我知道它在内部尝试了多少(换句话说,我有多少在满足BIO_write之前需要使用m_readBIO写入SSL_Read吗?)

一个好的下限也适用于我,我的问题是我需要报告要读取多少数据到我上面的层,并且它不会将控制权返回给我,直到它读取了那么多数据(和我不想退化为1字节读取。)

我知道SSL_ReadSSL_Write可以交替阅读&由于握手等而写,但我对内部正在进行的“当前”读取感兴趣。

如果无法使用标准BIO_s_mem,我认为如果我编写了自己的BIO,并且记得上次读取请求失败的大小,那么就可以完成。所以任何指向文档的指针都可以编写自定义BIO(据我所知,OpenSSL支持)也将受到赞赏。

1 个答案:

答案 0 :(得分:0)

感谢CristiFati建议的BIO_set_callback,它似乎有效。如果你想对答案做出评论,我会接受,但我想把这些细节放在后面。

在我的'SSLSocket'课程中:

in the constructor:
BIO_set_callback(m_readBIO, &BIOCallback);
BIO_set_callback_arg(m_readBIO, reinterpret_cast<char*>(this));

long SSLSocket::BIOCallback(
    BIO *in_bio,
    int in_operation,
    const char* in_arg1,
    int in_arg2,
    long in_arg3,
    long in_returnValue)
{
    // in_bio isn't provided for BIO_CB_FREE.
    if (BIO_CB_FREE == in_operation)
    {
        return in_returnValue;
    }

    assert(in_arg1);

    return reinterpret_cast<SSLSocket*>(BIO_get_callback_arg(in_bio))->DoBIOCallback(
        in_bio,
        in_operation,
        in_arg1,
        in_arg2,
        in_arg3,
        in_returnValue);

long SSLSocket::DoBIOCallback(
    BIO *in_bio,
    int in_operation,
    const char* in_arg1,
    int in_arg2,
    long in_arg3,
    long in_returnValue)
{
    UNUSED(in_arg3);

    // We only care about the return callback for BIO_read()
    if ((BIO_CB_READ | BIO_CB_RETURN) == in_operation)
    {
        const int shouldRetry = BIO_should_retry(in_bio);
        const int bytesRequested = in_arg2;
        assert(bytesRequested > 0);

        if ((in_returnValue <= 0) && shouldRetry)
        {
            m_needBytes = bytesRequested;
        }
        else if ((in_returnValue > 0) && (in_returnValue < bytesRequested) && shouldRetry)
        {
            m_needBytes = bytesRequested - in_returnValue;
        }
        else
        {
            m_needBytes = 0;
        }
    }

    return in_returnValue;
}

然后我使用m_needBytes来决定在BIO_write()中写入多少。