=head1 NOTES
-The AES-SIV and AES-WRAP mode implementations do not support streaming. That
-means to obtain correct results there can be only one L<EVP_EncryptUpdate(3)>
-or L<EVP_DecryptUpdate(3)> call after the initialization of the context.
+The AES-SIV, AES-WRAP, and GCM-SIV mode implementations do not support
+streaming. That means to obtain correct results there can be only one
+L<EVP_EncryptUpdate(3)> or L<EVP_DecryptUpdate(3)> call on the payload after
+the initialization of the context.
When wrapping with AES-WRAP-PAD ciphers, the output buffer must be at least
I<inl> rounded up to the cipher block size (8 bytes) plus the block size.
#include "internal/deprecated.h"
#include <openssl/evp.h>
+#include <openssl/proverr.h>
#include <internal/endian.h>
#include <prov/implementations.h>
#include "cipher_aes_gcm_siv.h"
DECLARE_IS_ENDIAN;
ctx->generated_tag = 0;
- if (!ctx->speed && ctx->used_enc)
- return 0;
/* need to check the size of the input! */
if (len64 > ((int64_t)1 << 36))
return 0;
DECLARE_IS_ENDIAN;
ctx->generated_tag = 0;
- if (!ctx->speed && ctx->used_dec)
- return 0;
/* need to check the size of the input! */
if (len64 > ((int64_t)1 << 36))
return 0;
if (in == NULL)
return aes_gcm_siv_finish(ctx);
+ /*
+ * SIV derives the CTR IV from the tag, which depends on the whole plaintext,
+ * so the payload cannot be streamed.
+ * Payload must arrive in a single update, after which the tag is fixed.
+ * Any later AAD or payload update is therefore out of order and errors out.
+ * The speed benchmark test is exempt.
+ */
+ if (!ctx->speed && (ctx->used_enc || ctx->used_dec)) {
+ ERR_raise(ERR_LIB_PROV, PROV_R_UPDATE_CALL_OUT_OF_ORDER);
+ return 0;
+ }
+
/* Deal with associated data */
if (out == NULL)
return aes_gcm_siv_aad(ctx, in, len);
|| info->mode == EVP_CIPH_GCM_MODE /* rejects, raises 102 PROV_R_CIPHER_OPERATION_FAILED */
|| info->mode == EVP_CIPH_CCM_MODE /* fails at first AAD */
|| info->mode == EVP_CIPH_OCB_MODE /* accepts late AAD */
- || info->mode == EVP_CIPH_GCM_SIV_MODE /* accepts late AAD */
/* skip TLS stitched MTE cipher */
|| EVP_CIPHER_is_a(info->ciph, "AES-128-CBC-HMAC-SHA1")
/* skip TLS stitched MTE cipher */