Fix output bounds checking in EVP_AEAD_CTX_seal_scatter This broke with the CRYPTO_IOVEC change and, in calls with extra_in, we didn't actually notice if the output buffer wasn't sized correctly. Bug: 383343306 Change-Id: I719f427cf53359c2d77829e2732d8a9d119a4d67 Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/93547 Auto-Submit: David Benjamin <davidben@google.com> Presubmit-BoringSSL-Verified: boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com <boringssl-scoped@luci-project-accounts.iam.gserviceaccount.com> Commit-Queue: Rudolf Polzer <rpolzer@google.com> Reviewed-by: Rudolf Polzer <rpolzer@google.com>
diff --git a/crypto/cipher/aead_test.cc b/crypto/cipher/aead_test.cc index 1131263..12a35c6 100644 --- a/crypto/cipher/aead_test.cc +++ b/crypto/cipher/aead_test.cc
@@ -332,6 +332,25 @@ EXPECT_EQ(Bytes(ct), Bytes(out.data(), in.size())); EXPECT_EQ(Bytes(tag), Bytes(out_tag.data() + extra_in_size, tag_bytes_written - extra_in_size)); + + // Bounds on the tag output should be checked. + { + std::vector<uint8_t> tag_buf(extra_in_size == 0 ? 0 + : extra_in_size - 1); + EXPECT_FALSE(EVP_AEAD_CTX_seal_scatter( + ctx.get(), out.data(), tag_buf.data(), &tag_bytes_written, + tag_buf.size(), nonce.data(), nonce.size(), in.data(), + in.size() - extra_in_size, in.data() + in.size() - extra_in_size, + extra_in_size, ad.data(), ad.size())); + } + { + std::vector<uint8_t> tag_buf(extra_in_size + tag.size() - 1); + EXPECT_FALSE(EVP_AEAD_CTX_seal_scatter( + ctx.get(), out.data(), tag_buf.data(), &tag_bytes_written, + tag_buf.size(), nonce.data(), nonce.size(), in.data(), + in.size() - extra_in_size, in.data() + in.size() - extra_in_size, + extra_in_size, ad.data(), ad.size())); + } } }); }
diff --git a/crypto/fipsmodule/cipher/aead.cc.inc b/crypto/fipsmodule/cipher/aead.cc.inc index caee3ed..0e721ac 100644 --- a/crypto/fipsmodule/cipher/aead.cc.inc +++ b/crypto/fipsmodule/cipher/aead.cc.inc
@@ -178,19 +178,28 @@ } }); + // |out_tag| contains both the encryption of |extra_in| and the tag. + Span<uint8_t> out_tag_span(out_tag, max_out_tag_len); + if (out_tag_span.size() < extra_in_len) { + OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_BUFFER_TOO_SMALL); + return 0; + } + Span<uint8_t> extra_out = out_tag_span.first(extra_in_len); + Span<uint8_t> tag_only_out = out_tag_span.subspan(extra_in_len); + CRYPTO_IOVEC iovec[2]; iovec[0].in = in; iovec[0].out = out; iovec[0].len = in_len; iovec[1].in = extra_in; - iovec[1].out = out_tag; + iovec[1].out = extra_out.data(); iovec[1].len = extra_in_len; CRYPTO_IVEC aadvec[1]; aadvec[0].in = ad; aadvec[0].len = ad_len; - if (!EVP_AEAD_CTX_sealv( - ctx, iovec, extra_in_len ? 2 : 1, out_tag + extra_in_len, out_tag_len, - max_out_tag_len - extra_in_len, nonce, nonce_len, aadvec, 1)) { + if (!EVP_AEAD_CTX_sealv(ctx, iovec, extra_in_len ? 2 : 1, tag_only_out.data(), + out_tag_len, tag_only_out.size(), nonce, nonce_len, + aadvec, 1)) { *out_tag_len = 0; return 0; }