"num" parameter and expected output buffer size in EVP_CipherUpdate

Wiktor Kwapisiewicz wiktor at metacode.biz
Thu Dec 15 16:57:50 UTC 2022


Hello,

I've got a question about the "num" parameter of the cipher context 
(EVP_CIPHER_CTX_get_num [0]). The documentation states:

> Gets or sets the cipher specific "num" parameter for the associated ctx. Built-in ciphers typically use this to track how much of the current underlying block has been "used" already.

I'd like to use this parameter to check in advance how big should the 
output buffer passed to EVP_CipherUpdate be. My understanding of it was 
that "num" would be incremented if I feed partial block to 
EVP_CipherUpdate but I've failed to observe any other values of "num" 
than 0.

My two questions:

   - what is the "num" parameter used for? is it only for internal use?

and, more importantly,

   - given EVP_CIPHER_CTX object and the length of the input buffer, is 
it possible to calculate the needed output buffer size without 
explicitly keeping external state?

The manual algorithm on how it is handled has been excellently described 
by Matt here [1]. I'm wondering if it's possible to calculate that in 
code (from OpenSSL client's perspective).

Thank you in advance for your time!

Kind regards,
Wiktor

[0]: https://www.openssl.org/docs/man3.0/man3/EVP_CIPHER_CTX_get_num.html

[1]: 
https://mta.openssl.org/pipermail/openssl-users/2022-November/015623.html

Below you will find sample code that reproduces the behavior of "num" 
I've seen. (Please beware that C is not my native language :))

#include <string.h>
#include <openssl/evp.h>

int main()
{
     unsigned char outbuf[1024];
     int outlen, tmplen;
     unsigned char key[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
     unsigned char iv[] = {1,2,3,4,5,6,7,8};
     char intext[] = "1234567"; // half of block size
     EVP_CIPHER_CTX *ctx;
     FILE *out;
     int num;
     unsigned int block_size;

     ctx = EVP_CIPHER_CTX_new();
     EVP_EncryptInit_ex2(ctx, EVP_aes_128_cbc(), key, iv, NULL);

     block_size = EVP_CIPHER_CTX_block_size(ctx);
     printf("Block size: %d\n", block_size); // 16- block cipher

     num = EVP_CIPHER_CTX_num(ctx);
     printf("Num is: %d\n", num); // num is 0

     if (!EVP_CipherUpdate(ctx, outbuf, &outlen, intext, strlen(intext))) {
         EVP_CIPHER_CTX_free(ctx);
         return 1;
     }
     printf("Out len: %d\n", outlen); // 0 - no block produced, OK

     num = EVP_CIPHER_CTX_num(ctx);
     printf("Num is: %d\n", num); // num is still 0

     // I want to know the exact size of output buffer needed here
     if (!EVP_CipherFinal(ctx, outbuf + outlen, &tmplen)) {
         EVP_CIPHER_CTX_free(ctx);
         return 1;
     }
     outlen += tmplen;
     EVP_CIPHER_CTX_free(ctx);
     out = fopen("outfile", "wb");
     if (out == NULL) {
         return 1;
     }
     fwrite(outbuf, 1, outlen, out);
     fclose(out);
     return 0;
}


More information about the openssl-users mailing list