Change EVP_AEAD_CTX_seal_scatter to support an additional plaintext input.
Change-Id: I7e2fc8588d799d01d94cb5d94e49b53b367380ab
Reviewed-on: https://boringssl-review.googlesource.com/17344
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/cipher_extra/aead_test.cc b/crypto/cipher_extra/aead_test.cc
index e5e7761..6536e34 100644
--- a/crypto/cipher_extra/aead_test.cc
+++ b/crypto/cipher_extra/aead_test.cc
@@ -240,8 +240,8 @@
size_t out_tag_len;
ASSERT_TRUE(EVP_AEAD_CTX_seal_scatter(
ctx.get(), out.data(), out_tag.data(), &out_tag_len, out_tag.size(),
- nonce.data(), nonce.size(), in.data(), in.size(), ad.data(),
- ad.size()));
+ nonce.data(), nonce.size(), in.data(), in.size(), nullptr, 0,
+ ad.data(), ad.size()));
out_tag.resize(out_tag_len);
ASSERT_EQ(out.size(), ct.size());
diff --git a/crypto/cipher_extra/e_aesctrhmac.c b/crypto/cipher_extra/e_aesctrhmac.c
index dbe9f06..2982d0d 100644
--- a/crypto/cipher_extra/e_aesctrhmac.c
+++ b/crypto/cipher_extra/e_aesctrhmac.c
@@ -178,8 +178,8 @@
static int aead_aes_ctr_hmac_sha256_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
- size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad,
- size_t ad_len) {
+ size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_ctr_hmac_sha256_ctx *aes_ctx = ctx->aead_state;
const uint64_t in_len_64 = in_len;
@@ -242,9 +242,10 @@
static const EVP_AEAD aead_aes_128_ctr_hmac_sha256 = {
16 /* AES key */ + 32 /* HMAC key */,
- 12, /* nonce length */
- EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */
- EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */
+ 12, /* nonce length */
+ EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
aead_aes_ctr_hmac_sha256_init,
NULL /* init_with_direction */,
@@ -257,9 +258,10 @@
static const EVP_AEAD aead_aes_256_ctr_hmac_sha256 = {
32 /* AES key */ + 32 /* HMAC key */,
- 12, /* nonce length */
- EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */
- EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */
+ 12, /* nonce length */
+ EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* overhead */
+ EVP_AEAD_AES_CTR_HMAC_SHA256_TAG_LEN, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
aead_aes_ctr_hmac_sha256_init,
NULL /* init_with_direction */,
diff --git a/crypto/cipher_extra/e_aesgcmsiv.c b/crypto/cipher_extra/e_aesgcmsiv.c
index 3a1ec47..190a1b9 100644
--- a/crypto/cipher_extra/e_aesgcmsiv.c
+++ b/crypto/cipher_extra/e_aesgcmsiv.c
@@ -322,8 +322,8 @@
static int aead_aes_gcm_siv_asm_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
- size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad,
- size_t ad_len) {
+ size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_gcm_siv_asm_ctx *gcm_siv_ctx = ctx->aead_state;
const uint64_t in_len_64 = in_len;
const uint64_t ad_len_64 = ad_len;
@@ -505,6 +505,7 @@
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
aead_aes_gcm_siv_asm_init,
NULL /* init_with_direction */,
@@ -520,6 +521,7 @@
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
aead_aes_gcm_siv_asm_init,
NULL /* init_with_direction */,
@@ -698,12 +700,11 @@
key_material + 16, gcm_siv_ctx->is_256 ? 32 : 16);
}
-static int aead_aes_gcm_siv_seal_scatter(const EVP_AEAD_CTX *ctx, uint8_t *out,
- uint8_t *out_tag, size_t *out_tag_len,
- size_t max_out_tag_len,
- const uint8_t *nonce, size_t nonce_len,
- const uint8_t *in, size_t in_len,
- const uint8_t *ad, size_t ad_len) {
+static int aead_aes_gcm_siv_seal_scatter(
+ const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
+ size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
+ size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_aes_gcm_siv_ctx *gcm_siv_ctx = ctx->aead_state;
const uint64_t in_len_64 = in_len;
const uint64_t ad_len_64 = ad_len;
@@ -788,6 +789,7 @@
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
aead_aes_gcm_siv_init,
NULL /* init_with_direction */,
@@ -803,6 +805,7 @@
EVP_AEAD_AES_GCM_SIV_NONCE_LEN, /* nonce length */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* overhead */
EVP_AEAD_AES_GCM_SIV_TAG_LEN, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
aead_aes_gcm_siv_init,
NULL /* init_with_direction */,
diff --git a/crypto/cipher_extra/e_chacha20poly1305.c b/crypto/cipher_extra/e_chacha20poly1305.c
index c433053..6cfc856 100644
--- a/crypto/cipher_extra/e_chacha20poly1305.c
+++ b/crypto/cipher_extra/e_chacha20poly1305.c
@@ -157,8 +157,8 @@
static int aead_chacha20_poly1305_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
- size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad,
- size_t ad_len) {
+ size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
const struct aead_chacha20_poly1305_ctx *c20_ctx = ctx->aead_state;
if (nonce_len != 12) {
@@ -249,17 +249,19 @@
}
static const EVP_AEAD aead_chacha20_poly1305 = {
- 32, /* key len */
- 12, /* nonce len */
- POLY1305_TAG_LEN, /* overhead */
- POLY1305_TAG_LEN, /* max tag length */
+ 32, /* key len */
+ 12, /* nonce len */
+ POLY1305_TAG_LEN, /* overhead */
+ POLY1305_TAG_LEN, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
+
aead_chacha20_poly1305_init,
NULL, /* init_with_direction */
aead_chacha20_poly1305_cleanup,
NULL /* open */,
aead_chacha20_poly1305_seal_scatter,
aead_chacha20_poly1305_open_gather,
- NULL, /* get_iv */
+ NULL, /* get_iv */
};
const EVP_AEAD *EVP_aead_chacha20_poly1305(void) {
diff --git a/crypto/cipher_extra/e_ssl3.c b/crypto/cipher_extra/e_ssl3.c
index 7af9a58..f2eb357 100644
--- a/crypto/cipher_extra/e_ssl3.c
+++ b/crypto/cipher_extra/e_ssl3.c
@@ -127,7 +127,8 @@
uint8_t *out_tag, size_t *out_tag_len,
size_t max_out_tag_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in,
- size_t in_len, const uint8_t *ad,
+ size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad,
size_t ad_len) {
AEAD_SSL3_CTX *ssl3_ctx = (AEAD_SSL3_CTX *)ctx->aead_state;
@@ -362,6 +363,8 @@
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
+
NULL, /* init */
aead_aes_128_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
@@ -376,6 +379,8 @@
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
+
NULL, /* init */
aead_aes_256_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
@@ -390,6 +395,8 @@
0, /* nonce len */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
+
NULL, /* init */
aead_des_ede3_cbc_sha1_ssl3_init,
aead_ssl3_cleanup,
@@ -400,11 +407,13 @@
};
static const EVP_AEAD aead_null_sha1_ssl3 = {
- SHA_DIGEST_LENGTH, /* key len */
- 0, /* nonce len */
- SHA_DIGEST_LENGTH, /* overhead (SHA1) */
- SHA_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ SHA_DIGEST_LENGTH, /* key len */
+ 0, /* nonce len */
+ SHA_DIGEST_LENGTH, /* overhead (SHA1) */
+ SHA_DIGEST_LENGTH, /* max tag length */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_null_sha1_ssl3_init,
aead_ssl3_cleanup,
aead_ssl3_open,
diff --git a/crypto/cipher_extra/e_tls.c b/crypto/cipher_extra/e_tls.c
index bf4f2e4..14d5377 100644
--- a/crypto/cipher_extra/e_tls.c
+++ b/crypto/cipher_extra/e_tls.c
@@ -103,7 +103,8 @@
uint8_t *out_tag, size_t *out_tag_len,
size_t max_out_tag_len, const uint8_t *nonce,
size_t nonce_len, const uint8_t *in,
- size_t in_len, const uint8_t *ad,
+ size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad,
size_t ad_len) {
AEAD_TLS_CTX *tls_ctx = (AEAD_TLS_CTX *)ctx->aead_state;
@@ -457,7 +458,9 @@
16, /* nonce len (IV) */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_aes_128_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_open,
@@ -471,7 +474,9 @@
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_aes_128_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_open,
@@ -485,7 +490,9 @@
16, /* nonce len (IV) */
16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
SHA256_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_aes_128_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_open,
@@ -499,7 +506,9 @@
16, /* nonce len (IV) */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_aes_256_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_open,
@@ -513,7 +522,9 @@
0, /* nonce len */
16 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_aes_256_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_open,
@@ -527,7 +538,9 @@
16, /* nonce len (IV) */
16 + SHA256_DIGEST_LENGTH, /* overhead (padding + SHA256) */
SHA256_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_aes_256_cbc_sha256_tls_init,
aead_tls_cleanup,
aead_tls_open,
@@ -541,7 +554,9 @@
16, /* nonce len (IV) */
16 + SHA384_DIGEST_LENGTH, /* overhead (padding + SHA384) */
SHA384_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_aes_256_cbc_sha384_tls_init,
aead_tls_cleanup,
aead_tls_open,
@@ -555,7 +570,9 @@
8, /* nonce len (IV) */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_des_ede3_cbc_sha1_tls_init,
aead_tls_cleanup,
aead_tls_open,
@@ -569,7 +586,9 @@
0, /* nonce len */
8 + SHA_DIGEST_LENGTH, /* overhead (padding + SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_des_ede3_cbc_sha1_tls_implicit_iv_init,
aead_tls_cleanup,
aead_tls_open,
@@ -583,7 +602,9 @@
0, /* nonce len */
SHA_DIGEST_LENGTH, /* overhead (SHA1) */
SHA_DIGEST_LENGTH, /* max tag length */
- NULL, /* init */
+ 0, /* seal_scatter_supports_extra_in */
+
+ NULL, /* init */
aead_null_sha1_tls_init,
aead_tls_cleanup,
aead_tls_open,
diff --git a/crypto/fipsmodule/cipher/aead.c b/crypto/fipsmodule/cipher/aead.c
index a44889f..79139e6 100644
--- a/crypto/fipsmodule/cipher/aead.c
+++ b/crypto/fipsmodule/cipher/aead.c
@@ -134,7 +134,7 @@
size_t out_tag_len;
if (ctx->aead->seal_scatter(ctx, out, out + in_len, &out_tag_len,
max_out_len - in_len, nonce, nonce_len, in,
- in_len, ad, ad_len)) {
+ in_len, NULL, 0, ad, ad_len)) {
*out_len = in_len + out_tag_len;
return 1;
}
@@ -148,10 +148,10 @@
}
int EVP_AEAD_CTX_seal_scatter(
- const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
- size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
- size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad,
- size_t ad_len) {
+ const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag, size_t
+ *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce, size_t
+ nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
// |in| and |out| may alias exactly, |out_tag| may not alias.
if (!check_alias(in, in_len, out, in_len) ||
buffers_alias(out, in_len, out_tag, max_out_tag_len) ||
@@ -160,8 +160,14 @@
goto error;
}
+ if (!ctx->aead->seal_scatter_supports_extra_in && extra_in_len) {
+ OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_OPERATION);
+ goto error;
+ }
+
if (ctx->aead->seal_scatter(ctx, out, out_tag, out_tag_len, max_out_tag_len,
- nonce, nonce_len, in, in_len, ad, ad_len)) {
+ nonce, nonce_len, in, in_len, extra_in,
+ extra_in_len, ad, ad_len)) {
return 1;
}
diff --git a/crypto/fipsmodule/cipher/e_aes.c b/crypto/fipsmodule/cipher/e_aes.c
index 1505001..31d9877 100644
--- a/crypto/fipsmodule/cipher/e_aes.c
+++ b/crypto/fipsmodule/cipher/e_aes.c
@@ -1207,6 +1207,8 @@
size_t max_out_tag_len,
const uint8_t *nonce, size_t nonce_len,
const uint8_t *in, size_t in_len,
+ const uint8_t *extra_in,
+ size_t extra_in_len,
const uint8_t *ad, size_t ad_len) {
const struct aead_aes_gcm_ctx *gcm_ctx = ctx->aead_state;
GCM128_CONTEXT gcm;
@@ -1351,8 +1353,8 @@
static int aead_aes_gcm_tls12_seal_scatter(
const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
- size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad,
- size_t ad_len) {
+ size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad, size_t ad_len) {
struct aead_aes_gcm_tls12_ctx *gcm_ctx = ctx->aead_state;
if (gcm_ctx->counter == UINT64_MAX) {
OPENSSL_PUT_ERROR(CIPHER, CIPHER_R_INVALID_NONCE);
@@ -1374,7 +1376,7 @@
return aead_aes_gcm_seal_scatter(ctx, out, out_tag, out_tag_len,
max_out_tag_len, nonce, nonce_len, in,
- in_len, ad, ad_len);
+ in_len, extra_in, extra_in_len, ad, ad_len);
}
DEFINE_METHOD_FUNCTION(EVP_AEAD, EVP_aead_aes_128_gcm_tls12) {
diff --git a/crypto/fipsmodule/cipher/internal.h b/crypto/fipsmodule/cipher/internal.h
index c61bff7..ea59723 100644
--- a/crypto/fipsmodule/cipher/internal.h
+++ b/crypto/fipsmodule/cipher/internal.h
@@ -79,6 +79,7 @@
uint8_t nonce_len;
uint8_t overhead;
uint8_t max_tag_len;
+ int seal_scatter_supports_extra_in;
/* init initialises an |EVP_AEAD_CTX|. If this call returns zero then
* |cleanup| will not be called for that context. */
@@ -96,7 +97,8 @@
int (*seal_scatter)(const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
size_t *out_tag_len, size_t max_out_tag_len,
const uint8_t *nonce, size_t nonce_len, const uint8_t *in,
- size_t in_len, const uint8_t *ad, size_t ad_len);
+ size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len, const uint8_t *ad, size_t ad_len);
int (*open_gather)(const EVP_AEAD_CTX *ctx, uint8_t *out,
const uint8_t *nonce, size_t nonce_len, const uint8_t *in,
diff --git a/include/openssl/aead.h b/include/openssl/aead.h
index e0d6432..f0a67d8 100644
--- a/include/openssl/aead.h
+++ b/include/openssl/aead.h
@@ -267,8 +267,15 @@
* function on the same |EVP_AEAD_CTX|.
*
* Exactly |in_len| bytes are written to |out|, and up to
- * |EVP_AEAD_max_overhead| bytes to |out_tag|. On successful return,
- * |*out_tag_len| is set to the actual number of bytes written to |out_tag|.
+ * |EVP_AEAD_max_overhead+extra_in_len| bytes to |out_tag|. On successful
+ * return, |*out_tag_len| is set to the actual number of bytes written to
+ * |out_tag|.
+ *
+ * |extra_in| may point to an additional plaintext input buffer if the cipher
+ * supports it. If present, |extra_in_len| additional bytes of plaintext are
+ * encrypted and authenticated, and the ciphertext is written (before the tag)
+ * to |out_tag|. |max_out_tag_len| must be sized to allow for the additional
+ * |extra_in_len| bytes.
*
* The length of |nonce|, |nonce_len|, must be equal to the result of
* |EVP_AEAD_nonce_length| for this AEAD.
@@ -281,10 +288,12 @@
* If |in| and |out| alias then |out| must be == |in|. |out_tag| may not alias
* any other argument. */
OPENSSL_EXPORT int EVP_AEAD_CTX_seal_scatter(
- const EVP_AEAD_CTX *ctx, uint8_t *out, uint8_t *out_tag,
- size_t *out_tag_len, size_t max_out_tag_len, const uint8_t *nonce,
- size_t nonce_len, const uint8_t *in, size_t in_len, const uint8_t *ad,
- size_t ad_len);
+ const EVP_AEAD_CTX *ctx, uint8_t *out,
+ uint8_t *out_tag, size_t *out_tag_len, size_t max_out_tag_len,
+ const uint8_t *nonce, size_t nonce_len,
+ const uint8_t *in, size_t in_len,
+ const uint8_t *extra_in, size_t extra_in_len,
+ const uint8_t *ad, size_t ad_len);
/* EVP_AEAD_CTX_open_gather decrypts and authenticates |in_len| bytes from |in|
* and authenticates |ad_len| bytes from |ad| using |in_tag_len| bytes of