@@ -387,11 +387,23 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
387387 if ((in_len = RSTRING_LEN (data )) == 0 )
388388 ossl_raise (rb_eArgError , "data must not be empty" );
389389 GetCipher (self , ctx );
390- out_len = in_len + EVP_CIPHER_CTX_block_size (ctx );
391- if (out_len <= 0 ) {
390+
391+ /*
392+ * As of OpenSSL 3.2, there is no reliable way to determine the required
393+ * output buffer size for arbitrary cipher modes.
394+ * https://github.com/openssl/openssl/issues/22628
395+ *
396+ * in_len+block_size is usually sufficient, but AES key wrap with padding
397+ * ciphers require in_len+15 even though they have a block size of 8 bytes.
398+ *
399+ * Using EVP_MAX_BLOCK_LENGTH (32) as a safe upper bound for ciphers
400+ * currently implemented in OpenSSL, but this can change in the future.
401+ */
402+ if (in_len > LONG_MAX - EVP_MAX_BLOCK_LENGTH ) {
392403 ossl_raise (rb_eRangeError ,
393404 "data too big to make output buffer: %ld bytes" , in_len );
394405 }
406+ out_len = in_len + EVP_MAX_BLOCK_LENGTH ;
395407
396408 if (NIL_P (str )) {
397409 str = rb_str_new (0 , out_len );
@@ -402,7 +414,7 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self)
402414
403415 if (!ossl_cipher_update_long (ctx , (unsigned char * )RSTRING_PTR (str ), & out_len , in , in_len ))
404416 ossl_raise (eCipherError , NULL );
405- assert (out_len < RSTRING_LEN (str ));
417+ assert (out_len <= RSTRING_LEN (str ));
406418 rb_str_set_len (str , out_len );
407419
408420 return str ;
0 commit comments