Add SSL_AEAD_CTX_seal_scatter.
This plumbs EVP_AEAD_CTX_seal_scatter all the way through to
tls_record.c, so we can add a new zero-copy record sealing method on top
of the existing code.
Change-Id: I01fdd88abef5442dc16605ea31b29b4b1231c073
Reviewed-on: https://boringssl-review.googlesource.com/17684
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/ssl/ssl_aead_ctx.cc b/ssl/ssl_aead_ctx.cc
index 0cdf717..b78b06b 100644
--- a/ssl/ssl_aead_ctx.cc
+++ b/ssl/ssl_aead_ctx.cc
@@ -140,16 +140,19 @@
return 0;
}
-size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *aead) {
+size_t SSL_AEAD_CTX_max_suffix_len(const SSL_AEAD_CTX *aead,
+ size_t extra_in_len) {
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
aead = NULL;
#endif
- if (aead == NULL) {
- return 0;
- }
- return EVP_AEAD_max_overhead(aead->ctx.aead) +
- SSL_AEAD_CTX_explicit_nonce_len(aead);
+ return extra_in_len +
+ (aead == NULL ? 0 : EVP_AEAD_max_overhead(aead->ctx.aead));
+}
+
+size_t SSL_AEAD_CTX_max_overhead(const SSL_AEAD_CTX *aead) {
+ return SSL_AEAD_CTX_explicit_nonce_len(aead) +
+ SSL_AEAD_CTX_max_suffix_len(aead, 0);
}
/* ssl_aead_ctx_get_ad writes the additional data for |aead| into |out| and
@@ -252,22 +255,32 @@
return 1;
}
-int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
- size_t max_out, uint8_t type, uint16_t wire_version,
- const uint8_t seqnum[8], const uint8_t *in,
- size_t in_len) {
+int SSL_AEAD_CTX_seal_scatter(SSL_AEAD_CTX *aead, uint8_t *out_prefix,
+ uint8_t *out, uint8_t *out_suffix,
+ size_t *out_suffix_len, size_t max_out_suffix_len,
+ uint8_t type, uint16_t wire_version,
+ const uint8_t seqnum[8], const uint8_t *in,
+ size_t in_len, const uint8_t *extra_in,
+ size_t extra_in_len) {
#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
aead = NULL;
#endif
+ if ((in != out && buffers_alias(in, in_len, out, in_len)) ||
+ buffers_alias(in, in_len, out_suffix, max_out_suffix_len)) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
+ return 0;
+ }
+ if (extra_in_len > max_out_suffix_len) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
if (aead == NULL) {
/* Handle the initial NULL cipher. */
- if (in_len > max_out) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
- return 0;
- }
OPENSSL_memmove(out, in, in_len);
- *out_len = in_len;
+ OPENSSL_memmove(out_suffix, extra_in, extra_in_len);
+ *out_suffix_len = extra_in_len;
return 1;
}
@@ -303,22 +316,14 @@
nonce_len += aead->variable_nonce_len;
/* Emit the variable nonce if included in the record. */
- size_t extra_len = 0;
if (aead->variable_nonce_included_in_record) {
assert(!aead->xor_fixed_nonce);
- if (max_out < aead->variable_nonce_len) {
- OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
- return 0;
- }
- if (out < in + in_len && in < out + aead->variable_nonce_len) {
+ if (buffers_alias(in, in_len, out_prefix, aead->variable_nonce_len)) {
OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
return 0;
}
- OPENSSL_memcpy(out, nonce + aead->fixed_nonce_len,
+ OPENSSL_memcpy(out_prefix, nonce + aead->fixed_nonce_len,
aead->variable_nonce_len);
- extra_len = aead->variable_nonce_len;
- out += aead->variable_nonce_len;
- max_out -= aead->variable_nonce_len;
}
/* XOR the fixed nonce, if necessary. */
@@ -329,10 +334,33 @@
}
}
- if (!EVP_AEAD_CTX_seal(&aead->ctx, out, out_len, max_out, nonce, nonce_len,
- in, in_len, ad, ad_len)) {
+ return EVP_AEAD_CTX_seal_scatter(&aead->ctx, out, out_suffix, out_suffix_len,
+ max_out_suffix_len, nonce, nonce_len, in,
+ in_len, extra_in, extra_in_len, ad, ad_len);
+}
+
+int SSL_AEAD_CTX_seal(SSL_AEAD_CTX *aead, uint8_t *out, size_t *out_len,
+ size_t max_out_len, uint8_t type, uint16_t wire_version,
+ const uint8_t seqnum[8], const uint8_t *in,
+ size_t in_len) {
+ size_t prefix_len = SSL_AEAD_CTX_explicit_nonce_len(aead);
+ if (in_len + prefix_len < in_len) {
+ OPENSSL_PUT_ERROR(CIPHER, SSL_R_RECORD_TOO_LARGE);
return 0;
}
- *out_len += extra_len;
+ if (in_len + prefix_len > max_out_len) {
+ OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
+ return 0;
+ }
+
+ size_t suffix_len;
+ if (!SSL_AEAD_CTX_seal_scatter(aead, out, out + prefix_len,
+ out + prefix_len + in_len, &suffix_len,
+ max_out_len - prefix_len - in_len, type,
+ wire_version, seqnum, in, in_len, 0, 0)) {
+ return 0;
+ }
+ assert(suffix_len <= SSL_AEAD_CTX_max_suffix_len(aead, 0));
+ *out_len = prefix_len + in_len + suffix_len;
return 1;
}