ABI-test each AEAD.
This keeps coverage for some assembly once we stop ABI testing by
default.
Change-Id: I2937a2961c19de560cb63e180646eb0e7d59d4ec
Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/40424
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
diff --git a/crypto/cipher_extra/aead_test.cc b/crypto/cipher_extra/aead_test.cc
index 9a4ef4f..fdf71b0 100644
--- a/crypto/cipher_extra/aead_test.cc
+++ b/crypto/cipher_extra/aead_test.cc
@@ -25,6 +25,7 @@
#include "../fipsmodule/cipher/internal.h"
#include "../internal.h"
+#include "../test/abi_test.h"
#include "../test/file_test.h"
#include "../test/test_util.h"
#include "../test/wycheproof_util.h"
@@ -664,6 +665,91 @@
}
}
+#if defined(SUPPORTS_ABI_TEST)
+// CHECK_ABI can't pass enums, i.e. |evp_aead_seal| and |evp_aead_open|. Thus
+// these two wrappers.
+static int aead_ctx_init_for_seal(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
+ const uint8_t *key, size_t key_len) {
+ return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, 0,
+ evp_aead_seal);
+}
+
+static int aead_ctx_init_for_open(EVP_AEAD_CTX *ctx, const EVP_AEAD *aead,
+ const uint8_t *key, size_t key_len) {
+ return EVP_AEAD_CTX_init_with_direction(ctx, aead, key, key_len, 0,
+ evp_aead_open);
+}
+
+// CHECK_ABI can pass, at most, eight arguments. Thus these wrappers that
+// figure out the output length from the input length, and take the nonce length
+// from the configuration of the AEAD.
+static int aead_ctx_seal(EVP_AEAD_CTX *ctx, uint8_t *out_ciphertext,
+ size_t *out_ciphertext_len, const uint8_t *nonce,
+ const uint8_t *plaintext, size_t plaintext_len,
+ const uint8_t *ad, size_t ad_len) {
+ const size_t nonce_len = EVP_AEAD_nonce_length(EVP_AEAD_CTX_aead(ctx));
+ return EVP_AEAD_CTX_seal(ctx, out_ciphertext, out_ciphertext_len,
+ plaintext_len + EVP_AEAD_MAX_OVERHEAD, nonce,
+ nonce_len, plaintext, plaintext_len, ad, ad_len);
+}
+
+static int aead_ctx_open(EVP_AEAD_CTX *ctx, uint8_t *out_plaintext,
+ size_t *out_plaintext_len, const uint8_t *nonce,
+ const uint8_t *ciphertext, size_t ciphertext_len,
+ const uint8_t *ad, size_t ad_len) {
+ const size_t nonce_len = EVP_AEAD_nonce_length(EVP_AEAD_CTX_aead(ctx));
+ return EVP_AEAD_CTX_open(ctx, out_plaintext, out_plaintext_len,
+ ciphertext_len, nonce, nonce_len, ciphertext,
+ ciphertext_len, ad, ad_len);
+}
+
+TEST_P(PerAEADTest, ABI) {
+ uint8_t key[EVP_AEAD_MAX_KEY_LENGTH];
+ OPENSSL_memset(key, 'K', sizeof(key));
+ const size_t key_len = EVP_AEAD_key_length(aead());
+ ASSERT_LE(key_len, sizeof(key));
+
+ bssl::ScopedEVP_AEAD_CTX ctx_seal;
+ ASSERT_TRUE(
+ CHECK_ABI(aead_ctx_init_for_seal, ctx_seal.get(), aead(), key, key_len));
+
+ bssl::ScopedEVP_AEAD_CTX ctx_open;
+ ASSERT_TRUE(
+ CHECK_ABI(aead_ctx_init_for_open, ctx_open.get(), aead(), key, key_len));
+
+ alignas(2) uint8_t plaintext[512];
+ OPENSSL_memset(plaintext, 'P', sizeof(plaintext));
+
+ alignas(2) uint8_t ad_buf[512];
+ OPENSSL_memset(ad_buf, 'A', sizeof(ad_buf));
+ const uint8_t *const ad = ad_buf + 1;
+ ASSERT_LE(GetParam().ad_len, sizeof(ad_buf) - 1);
+ const size_t ad_len =
+ GetParam().ad_len != 0 ? GetParam().ad_len : sizeof(ad_buf) - 1;
+
+ uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
+ const size_t nonce_len = EVP_AEAD_nonce_length(aead());
+ ASSERT_LE(nonce_len, sizeof(nonce));
+
+ alignas(2) uint8_t ciphertext[sizeof(plaintext) + EVP_AEAD_MAX_OVERHEAD + 1];
+ size_t ciphertext_len;
+ // Knock plaintext, ciphertext, and AD off alignment and give odd lengths for
+ // plaintext and AD. This hopefully triggers any edge-cases in the assembly.
+ ASSERT_TRUE(CHECK_ABI(aead_ctx_seal, ctx_seal.get(), ciphertext + 1,
+ &ciphertext_len, nonce, plaintext + 1,
+ sizeof(plaintext) - 1, ad, ad_len));
+
+ alignas(2) uint8_t plaintext2[sizeof(ciphertext) + 1];
+ size_t plaintext2_len;
+ ASSERT_TRUE(CHECK_ABI(aead_ctx_open, ctx_open.get(), plaintext2 + 1,
+ &plaintext2_len, nonce, ciphertext + 1, ciphertext_len,
+ ad, ad_len));
+
+ EXPECT_EQ(Bytes(plaintext + 1, sizeof(plaintext) - 1),
+ Bytes(plaintext2 + 1, plaintext2_len));
+}
+#endif // SUPPORTS_ABI_TEST
+
TEST(AEADTest, AESCCMLargeAD) {
static const std::vector<uint8_t> kKey(16, 'A');
static const std::vector<uint8_t> kNonce(13, 'N');