doc: improve documentation of EVP in-place encryption
authorMatthias St. Pierre <matthias.st.pierre@ncp-e.com>
Wed, 29 Nov 2023 21:12:45 +0000 (22:12 +0100)
committerMatthias St. Pierre <matthias.st.pierre@ncp-e.com>
Tue, 12 Dec 2023 09:43:44 +0000 (10:43 +0100)
The EVP interface explicitly allows in-place encryption/decryption,
but this fact is just 'partially' documented in `EVP_EncryptUpdate(3)`
(pun intended): the manual page mentions only operation failure in
case of 'partial' overlaps. This is not even correct, because
the check for partially overlapping buffers is only implemented
in legacy code paths.

Currently, in-place encryption/decryption is only documented for
RSA (`RSA_public_encrypt(3)`) and DES (`DES_ecb_encrypt(3)`), as
well as in the provider interface (`provider-cipher(7)`).

This commit amends `EVP_EncryptUpdate(3)` and `provider-cipher(7)`
to make the front-end and back-end documentation consistent.

Reviewed-by: Tomas Mraz <tomas@openssl.org>
Reviewed-by: Tom Cosgrove <tom.cosgrove@arm.com>
(Merged from https://github.com/openssl/openssl/pull/22875)

(cherry picked from commit 6ebdbba76a45294e22006ede1442847cdee24f03)

doc/man3/EVP_EncryptInit.pod
doc/man7/provider-cipher.pod

index 56b29b52e1185597d75f4fa695c6df21668600c8..a2004e37d70be1d89170fdcaaf80578f7093bbee 100644 (file)
@@ -373,7 +373,12 @@ exists.
 =item EVP_EncryptUpdate()
 
 Encrypts I<inl> bytes from the buffer I<in> and writes the encrypted version to
-I<out>. This function can be called multiple times to encrypt successive blocks
+I<out>. The pointers I<out> and I<in> may point to the same location, in which
+case the encryption will be done in-place. If I<out> and I<in> point to different
+locations, the two buffers must be disjoint, otherwise the operation might fail
+or the outcome might be undefined.
+
+This function can be called multiple times to encrypt successive blocks
 of data. The amount of data written depends on the block alignment of the
 encrypted data.
 For most ciphers and modes, the amount of data written can be anything
@@ -382,10 +387,9 @@ 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.
-Thus, I<out> should contain sufficient room for the operation being performed.
-The actual number of bytes written is placed in I<outl>. It also
-checks if I<in> and I<out> are partially overlapping, and if they are
-0 is returned to indicate failure.
+Thus, the buffer pointed to by I<out> must contain sufficient room for the
+operation being performed.
+The actual number of bytes written is placed in I<outl>.
 
 If padding is enabled (the default) then EVP_EncryptFinal_ex() encrypts
 the "final" data, that is any data that remains in a partial block.
index 14ff581c72c492f47f3a49fca951eb6b34cd5379..eaad3cf2ff021abeee1c7f44e7e0ec760d59e206 100644 (file)
@@ -148,9 +148,13 @@ It is the responsibility of the cipher implementation to handle input lengths
 that are not multiples of the block length.
 In such cases a cipher implementation will typically cache partial blocks of
 input data until a complete block is obtained.
-I<out> may be the same location as I<in> but it should not partially overlap.
-The same expectations apply to I<outsize> as documented for
-L<EVP_EncryptUpdate(3)> and L<EVP_DecryptUpdate(3)>.
+The pointers I<out> and I<in> may point to the same location, in which
+case the encryption must be done in-place. If I<out> and I<in> point to different
+locations, the requirements of L<EVP_EncryptUpdate(3)> and L<EVP_DecryptUpdate(3)>
+guarantee that the two buffers are disjoint.
+Similarly, the requirements of L<EVP_EncryptUpdate(3)> and L<EVP_DecryptUpdate(3)>
+ensure that the buffer pointed to by I<out> contains sufficient room for the
+operation being performed.
 
 OSSL_FUNC_cipher_final() completes an encryption or decryption started through previous
 OSSL_FUNC_cipher_encrypt_init() or OSSL_FUNC_cipher_decrypt_init(), and OSSL_FUNC_cipher_update()