user864940
user864940

Reputation: 99

OpenSSL memory BIO and partial cipher blocks

I'm using OpenSSL in an architecture which requires me to perform encryption and decryption locally.

The decryption function gets a buffer which was encrypted on the other side of the connection. The encryption/decryption process usually works fine, but for the case where the buffer contains a partial cipher block.

I guess my issue boils down to this: Let s be an SSL object and buf be a memory buffer or encrypted data. What I do in order to decrypt it (minus error handling, thread safety, memory safety, etc.) is along the lines of

int decDataBufSize = 1000000; //approximation of length of decrypted data
int8_t* decData = (int8_t*)malloc(decDataBufSize*sizeof(int8_t)); //room for the decrypted data to be written into
BIO* bio = BIO_new_mem_buf(encData, decDataBufSize); //set up BIO pointing to the encrypted data
int decDataLength;
BIO_set_close(bio, BIO_NOCLOSE); //This means OpenSSL doesn't try to free the encrypted data buffer
int totalDecData = 0;
for(int remaining_length = buffie->getBuffer()->limit() ; remaining_length > 0 ; )
{
    SSL_set_bio(ssl, bio, bio);
    remaining_length -= BIO_pending(bio);
    int decDataLength = SSL_read(ssl, decData + totalDecData, decDataBufSize - totalDecData);
    totalDecData += decDataLength;
    remaining_length += BIO_pending(bio);
}
return decData;

This seems to be working fine but for the case where I have a part of a block in the buffer. I know that, had I worked with a socket instead of a memory BIO, I'd get an SSL_ERROR_WANT_READ, but in my case I get a most laconic SSL_ERROR_SSL (decryption failed or bad record mac).

Is there any way I could verify in advance that I have a full block?

Thanks in advance

Upvotes: 0

Views: 1729

Answers (1)

user864940
user864940

Reputation: 99

Apparently the solution lies in BIO_get_mem_data.

Something along the lines of: #define DEC_BUF_SIZE 1000000 static int buffer_length; static int8_t* partial_block;

int8_t* decrypt(int8_t* ecnData) { 
    int decDataBufSize = 1000000; //approximation of length of decrypted data
    int8_t* decData = (int8_t*)malloc(decDataBufSize*sizeof(int8_t)); //room for the decrypted data to be written into
    if (buffer_length == 0) /*prepend the contents of partial_block to encData somehow*/;
    BIO* bio = BIO_new_mem_buf(encData, decDataBufSize); //set up BIO pointing to the encrypted data
    int decDataLength;
    BIO_set_close(bio, BIO_NOCLOSE); //This means OpenSSL doesn't try to free the encrypted data buffer
    int totalDecData = 0;
    for(int remaining_length = buffie->getBuffer()->limit() ; remaining_length > 0 ; ) {
        buffer_length = BIO_get_mem_data(bio,&partial_block);
        SSL_set_bio(ssl, bio, bio);
        remaining_length -= BIO_pending(bio);
        int decDataLength = SSL_read(ssl, decData + totalDecData, decDataBufSize - totalDecData);
        totalDecData += decDataLength;
        remaining_length += BIO_pending(bio);
    }
return decData;
}

Upvotes: 1

Related Questions