Re: Output buffer length in EVP_EncryptUpdate for ECB mode

2022-11-04 Thread Wiktor Kwapisiewicz via openssl-users

Matt,

EVP_EncryptUpdate() can be called repeatedly, incrementally feeding in 
the data to be encrypted. The ECB mode (when used with AES-128) will 
encrypt input data 16 bytes at a time, and the output size will also be 
16 bytes per input block. If the data that you feed in to 
EVP_EncryptUpdate() is not a multiple of 16 bytes then the amount of 
data that is over a multiple of 16 bytes will be cached until a 
subsequent call where it does have 16 bytes.


Let's say you call EVP_EncryptUpdate() with 15 bytes of data. In that 
case all 15 bytes will be cached and 0 bytes will be output.


If you then call it again with 17 bytes of data, then added to the 15 
bytes already cached we have a total of 32 bytes. This is a multiple of 
16, so 2 blocks (32 bytes) will be output, so:


(inl + cipher_block_size - 1) = (17 + 16 - 1) = 32


This explanation makes perfect sense. Thank you!

The context I asked is that the rust-openssl wrapper always requires the 
output buffer to be at least as big as the input buffer + the cipher's 
block size [0] (assuming pessimistic case). That is even if I always 
feed the EVP_EncryptUpdate with blocks exactly 16 bytes long the wrapper 
requires 32 byte output buffers, while, based on your description 16 
byte output buffers should be sufficient.


Thank you for your time!

Kind regards,
Wiktor

[0]: https://docs.rs/openssl/latest/src/openssl/cipher_ctx.rs.html#504


Re: Output buffer length in EVP_EncryptUpdate for ECB mode

2022-11-03 Thread Matt Caswell




On 03/11/2022 14:21, Wiktor Kwapisiewicz via openssl-users wrote:

Hello,

I'd like to clarify one aspect of the API regarding EVP_EncryptUpdate
[0] that is the length of the output buffer that should be passed to
that function ("out" parameter). (Actually I'm using EVP_CipherUpdate 
but the docs are more comprehensive for EVP_EncryptUpdate).


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

For the record I'm using AES-128 cipher in ECB mode and the docs say:


For most ciphers and modes, the amount of data written can be
anything from zero bytes to (inl + cipher_block_size - 1) bytes. For
wrap cipher modes, the amount of data written can be anything from
zero bytes to (inl + cipher_block_size) bytes. For stream ciphers,
the amount of data written can be anything from zero bytes to inl
bytes.


AES-128-ECB doesn't appear to be a stream cipher (since the "block size" 
returns 16 not the magical value of 1) and I'm unable to find any 
mentions of "wrap cipher modes" in search engines. Apparently ECB is a 
block cipher mode.


Does that mean that "wrap cipher modes" == "block cipher modes"?


No.

The term "block cipher" is a feature of the underlying primitive - so 
AES-128 is a block cipher. It encrypts in blocks of 16 bytes. ECB is a 
particular mode for using a block cipher. "Wrap" modes are specialist 
modes used for encrypting key material.




Is there any documentation I could read on the reasoning of why a space 
for additional block is needed in this case ("(inl + cipher_block_size) 
bytes")? I'm trying to understand the differences between OpenSSL and 
other cryptographic backends in an OpenPGP library [1].



EVP_EncryptUpdate() can be called repeatedly, incrementally feeding in 
the data to be encrypted. The ECB mode (when used with AES-128) will 
encrypt input data 16 bytes at a time, and the output size will also be 
16 bytes per input block. If the data that you feed in to 
EVP_EncryptUpdate() is not a multiple of 16 bytes then the amount of 
data that is over a multiple of 16 bytes will be cached until a 
subsequent call where it does have 16 bytes.


Let's say you call EVP_EncryptUpdate() with 15 bytes of data. In that 
case all 15 bytes will be cached and 0 bytes will be output.


If you then call it again with 17 bytes of data, then added to the 15 
bytes already cached we have a total of 32 bytes. This is a multiple of 
16, so 2 blocks (32 bytes) will be output, so:


(inl + cipher_block_size - 1) = (17 + 16 - 1) = 32


Matt




Thank you for your time and help!

Kind regards,
Wiktor

[1]: 
https://gitlab.com/sequoia-pgp/sequoia/-/merge_requests/1361#note_1150958453