blob: 03bf0a912ae7b14bae1371d299b3e402f1ffe80a [file] [log] [blame]
David Benjamin31a07792015-03-03 14:20:26 -05001/* Copyright (c) 2015, Google Inc.
2 *
3 * Permission to use, copy, modify, and/or distribute this software for any
4 * purpose with or without fee is hereby granted, provided that the above
5 * copyright notice and this permission notice appear in all copies.
6 *
7 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
8 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
10 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
12 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
13 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
14
David Benjamin86e95b82017-07-18 16:34:25 -040015#define BORINGSSL_INTERNAL_CXX_TYPES
16
David Benjamin9e4e01e2015-09-15 01:48:04 -040017#include <openssl/ssl.h>
18
David Benjamin31a07792015-03-03 14:20:26 -050019#include <assert.h>
20#include <string.h>
21
22#include <openssl/aead.h>
23#include <openssl/err.h>
24#include <openssl/rand.h>
David Benjamin31a07792015-03-03 14:20:26 -050025
David Benjamin17cf2cb2016-12-13 01:07:13 -050026#include "../crypto/internal.h"
David Benjamin31a07792015-03-03 14:20:26 -050027#include "internal.h"
28
29
David Benjamincfc11c22017-07-18 22:45:18 -040030#if defined(BORINGSSL_UNSAFE_FUZZER_MODE)
31#define FUZZER_MODE true
32#else
33#define FUZZER_MODE false
34#endif
35
David Benjamin86e95b82017-07-18 16:34:25 -040036namespace bssl {
37
David Benjamincfc11c22017-07-18 22:45:18 -040038SSLAEADContext::SSLAEADContext(uint16_t version_arg,
39 const SSL_CIPHER *cipher_arg)
40 : cipher_(cipher_arg),
41 version_(version_arg),
42 variable_nonce_included_in_record_(false),
43 random_variable_nonce_(false),
44 omit_length_in_ad_(false),
45 omit_version_in_ad_(false),
46 omit_ad_(false),
47 xor_fixed_nonce_(false) {
48 OPENSSL_memset(fixed_nonce_, 0, sizeof(fixed_nonce_));
49}
50
51SSLAEADContext::~SSLAEADContext() {}
52
53UniquePtr<SSLAEADContext> SSLAEADContext::CreateNullCipher() {
54 return MakeUnique<SSLAEADContext>(0 /* version */, nullptr /* cipher */);
55}
56
57UniquePtr<SSLAEADContext> SSLAEADContext::Create(
58 enum evp_aead_direction_t direction, uint16_t version, int is_dtls,
59 const SSL_CIPHER *cipher, const uint8_t *enc_key, size_t enc_key_len,
60 const uint8_t *mac_key, size_t mac_key_len, const uint8_t *fixed_iv,
61 size_t fixed_iv_len) {
David Benjamin31a07792015-03-03 14:20:26 -050062 const EVP_AEAD *aead;
David Benjamin4b0d0e42016-10-28 17:17:14 -040063 size_t expected_mac_key_len, expected_fixed_iv_len;
64 if (!ssl_cipher_get_evp_aead(&aead, &expected_mac_key_len,
Steven Valdez2f3404b2017-05-24 16:54:35 -040065 &expected_fixed_iv_len, cipher, version,
66 is_dtls) ||
David Benjamin4b0d0e42016-10-28 17:17:14 -040067 /* Ensure the caller returned correct key sizes. */
68 expected_fixed_iv_len != fixed_iv_len ||
69 expected_mac_key_len != mac_key_len) {
David Benjamin3570d732015-06-29 00:28:17 -040070 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamincfc11c22017-07-18 22:45:18 -040071 return nullptr;
David Benjamin31a07792015-03-03 14:20:26 -050072 }
73
74 uint8_t merged_key[EVP_AEAD_MAX_KEY_LENGTH];
75 if (mac_key_len > 0) {
76 /* This is a "stateful" AEAD (for compatibility with pre-AEAD cipher
77 * suites). */
78 if (mac_key_len + enc_key_len + fixed_iv_len > sizeof(merged_key)) {
David Benjamin3570d732015-06-29 00:28:17 -040079 OPENSSL_PUT_ERROR(SSL, ERR_R_INTERNAL_ERROR);
David Benjamincfc11c22017-07-18 22:45:18 -040080 return nullptr;
David Benjamin31a07792015-03-03 14:20:26 -050081 }
David Benjamin17cf2cb2016-12-13 01:07:13 -050082 OPENSSL_memcpy(merged_key, mac_key, mac_key_len);
83 OPENSSL_memcpy(merged_key + mac_key_len, enc_key, enc_key_len);
84 OPENSSL_memcpy(merged_key + mac_key_len + enc_key_len, fixed_iv,
85 fixed_iv_len);
David Benjamin31a07792015-03-03 14:20:26 -050086 enc_key = merged_key;
87 enc_key_len += mac_key_len;
88 enc_key_len += fixed_iv_len;
89 }
90
David Benjamincfc11c22017-07-18 22:45:18 -040091 UniquePtr<SSLAEADContext> aead_ctx =
92 MakeUnique<SSLAEADContext>(version, cipher);
93 if (!aead_ctx) {
David Benjamin3570d732015-06-29 00:28:17 -040094 OPENSSL_PUT_ERROR(SSL, ERR_R_MALLOC_FAILURE);
David Benjamincfc11c22017-07-18 22:45:18 -040095 return nullptr;
David Benjamin31a07792015-03-03 14:20:26 -050096 }
David Benjamin31a07792015-03-03 14:20:26 -050097
98 if (!EVP_AEAD_CTX_init_with_direction(
David Benjamincfc11c22017-07-18 22:45:18 -040099 aead_ctx->ctx_.get(), aead, enc_key, enc_key_len,
David Benjamin31a07792015-03-03 14:20:26 -0500100 EVP_AEAD_DEFAULT_TAG_LENGTH, direction)) {
David Benjamincfc11c22017-07-18 22:45:18 -0400101 return nullptr;
David Benjamin31a07792015-03-03 14:20:26 -0500102 }
103
104 assert(EVP_AEAD_nonce_length(aead) <= EVP_AEAD_MAX_NONCE_LENGTH);
David Benjamina3d76d02017-07-14 19:36:07 -0400105 static_assert(EVP_AEAD_MAX_NONCE_LENGTH < 256,
106 "variable_nonce_len doesn't fit in uint8_t");
David Benjamincfc11c22017-07-18 22:45:18 -0400107 aead_ctx->variable_nonce_len_ = (uint8_t)EVP_AEAD_nonce_length(aead);
David Benjamin51a01a52015-10-29 13:19:56 -0400108 if (mac_key_len == 0) {
David Benjamincfc11c22017-07-18 22:45:18 -0400109 assert(fixed_iv_len <= sizeof(aead_ctx->fixed_nonce_));
110 OPENSSL_memcpy(aead_ctx->fixed_nonce_, fixed_iv, fixed_iv_len);
111 aead_ctx->fixed_nonce_len_ = fixed_iv_len;
David Benjamin13414b32015-12-09 23:02:39 -0500112
113 if (cipher->algorithm_enc & SSL_CHACHA20POLY1305) {
114 /* The fixed nonce into the actual nonce (the sequence number). */
David Benjamincfc11c22017-07-18 22:45:18 -0400115 aead_ctx->xor_fixed_nonce_ = true;
116 aead_ctx->variable_nonce_len_ = 8;
David Benjamin13414b32015-12-09 23:02:39 -0500117 } else {
118 /* The fixed IV is prepended to the nonce. */
David Benjamincfc11c22017-07-18 22:45:18 -0400119 assert(fixed_iv_len <= aead_ctx->variable_nonce_len_);
120 aead_ctx->variable_nonce_len_ -= fixed_iv_len;
David Benjamin13414b32015-12-09 23:02:39 -0500121 }
122
David Benjaminb2a985b2015-06-21 15:13:57 -0400123 /* AES-GCM uses an explicit nonce. */
124 if (cipher->algorithm_enc & (SSL_AES128GCM | SSL_AES256GCM)) {
David Benjamincfc11c22017-07-18 22:45:18 -0400125 aead_ctx->variable_nonce_included_in_record_ = true;
David Benjaminb2a985b2015-06-21 15:13:57 -0400126 }
Steven Valdez494650c2016-05-24 12:43:04 -0400127
128 /* The TLS 1.3 construction XORs the fixed nonce into the sequence number
129 * and omits the additional data. */
130 if (version >= TLS1_3_VERSION) {
David Benjamincfc11c22017-07-18 22:45:18 -0400131 aead_ctx->xor_fixed_nonce_ = true;
132 aead_ctx->variable_nonce_len_ = 8;
133 aead_ctx->variable_nonce_included_in_record_ = false;
134 aead_ctx->omit_ad_ = true;
135 assert(fixed_iv_len >= aead_ctx->variable_nonce_len_);
Steven Valdez494650c2016-05-24 12:43:04 -0400136 }
David Benjamin31a07792015-03-03 14:20:26 -0500137 } else {
Steven Valdez79750562016-06-16 06:38:04 -0400138 assert(version < TLS1_3_VERSION);
David Benjamincfc11c22017-07-18 22:45:18 -0400139 aead_ctx->variable_nonce_included_in_record_ = true;
140 aead_ctx->random_variable_nonce_ = true;
141 aead_ctx->omit_length_in_ad_ = true;
142 aead_ctx->omit_version_in_ad_ = (version == SSL3_VERSION);
David Benjamin31a07792015-03-03 14:20:26 -0500143 }
144
145 return aead_ctx;
146}
147
David Benjamincfc11c22017-07-18 22:45:18 -0400148size_t SSLAEADContext::ExplicitNonceLen() const {
149 if (!FUZZER_MODE && variable_nonce_included_in_record_) {
150 return variable_nonce_len_;
David Benjamin31a07792015-03-03 14:20:26 -0500151 }
152 return 0;
153}
154
David Benjamincfc11c22017-07-18 22:45:18 -0400155size_t SSLAEADContext::MaxSuffixLen(size_t extra_in_len) const {
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700156 return extra_in_len +
David Benjamincfc11c22017-07-18 22:45:18 -0400157 (is_null_cipher() || FUZZER_MODE
158 ? 0
159 : EVP_AEAD_max_overhead(EVP_AEAD_CTX_aead(ctx_.get())));
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700160}
161
David Benjamincfc11c22017-07-18 22:45:18 -0400162size_t SSLAEADContext::MaxOverhead() const {
163 return ExplicitNonceLen() + MaxSuffixLen(0);
David Benjamin31a07792015-03-03 14:20:26 -0500164}
165
David Benjamincfc11c22017-07-18 22:45:18 -0400166size_t SSLAEADContext::GetAdditionalData(uint8_t out[13], uint8_t type,
167 uint16_t wire_version,
168 const uint8_t seqnum[8],
169 size_t plaintext_len) {
170 if (omit_ad_) {
Steven Valdez494650c2016-05-24 12:43:04 -0400171 return 0;
172 }
173
David Benjamin17cf2cb2016-12-13 01:07:13 -0500174 OPENSSL_memcpy(out, seqnum, 8);
David Benjamin31a07792015-03-03 14:20:26 -0500175 size_t len = 8;
176 out[len++] = type;
David Benjamincfc11c22017-07-18 22:45:18 -0400177 if (!omit_version_in_ad_) {
178 out[len++] = static_cast<uint8_t>((wire_version >> 8));
179 out[len++] = static_cast<uint8_t>(wire_version);
David Benjamin31a07792015-03-03 14:20:26 -0500180 }
David Benjamincfc11c22017-07-18 22:45:18 -0400181 if (!omit_length_in_ad_) {
182 out[len++] = static_cast<uint8_t>((plaintext_len >> 8));
183 out[len++] = static_cast<uint8_t>(plaintext_len);
David Benjamin31a07792015-03-03 14:20:26 -0500184 }
185 return len;
186}
187
David Benjamincfc11c22017-07-18 22:45:18 -0400188bool SSLAEADContext::Open(CBS *out, uint8_t type, uint16_t wire_version,
189 const uint8_t seqnum[8], uint8_t *in, size_t in_len) {
190 if (is_null_cipher() || FUZZER_MODE) {
David Benjamin31a07792015-03-03 14:20:26 -0500191 /* Handle the initial NULL cipher. */
David Benjamina7810c12016-06-06 18:54:51 -0400192 CBS_init(out, in, in_len);
David Benjamincfc11c22017-07-18 22:45:18 -0400193 return true;
David Benjamin31a07792015-03-03 14:20:26 -0500194 }
195
196 /* TLS 1.2 AEADs include the length in the AD and are assumed to have fixed
197 * overhead. Otherwise the parameter is unused. */
198 size_t plaintext_len = 0;
David Benjamincfc11c22017-07-18 22:45:18 -0400199 if (!omit_length_in_ad_) {
200 size_t overhead = MaxOverhead();
David Benjamin31a07792015-03-03 14:20:26 -0500201 if (in_len < overhead) {
202 /* Publicly invalid. */
David Benjamin3570d732015-06-29 00:28:17 -0400203 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
David Benjamincfc11c22017-07-18 22:45:18 -0400204 return false;
David Benjamin31a07792015-03-03 14:20:26 -0500205 }
206 plaintext_len = in_len - overhead;
207 }
208 uint8_t ad[13];
David Benjamincfc11c22017-07-18 22:45:18 -0400209 size_t ad_len =
210 GetAdditionalData(ad, type, wire_version, seqnum, plaintext_len);
David Benjamin31a07792015-03-03 14:20:26 -0500211
212 /* Assemble the nonce. */
213 uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
214 size_t nonce_len = 0;
David Benjamin13414b32015-12-09 23:02:39 -0500215
216 /* Prepend the fixed nonce, or left-pad with zeros if XORing. */
David Benjamincfc11c22017-07-18 22:45:18 -0400217 if (xor_fixed_nonce_) {
218 nonce_len = fixed_nonce_len_ - variable_nonce_len_;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500219 OPENSSL_memset(nonce, 0, nonce_len);
David Benjamin13414b32015-12-09 23:02:39 -0500220 } else {
David Benjamincfc11c22017-07-18 22:45:18 -0400221 OPENSSL_memcpy(nonce, fixed_nonce_, fixed_nonce_len_);
222 nonce_len += fixed_nonce_len_;
David Benjamin13414b32015-12-09 23:02:39 -0500223 }
224
225 /* Add the variable nonce. */
David Benjamincfc11c22017-07-18 22:45:18 -0400226 if (variable_nonce_included_in_record_) {
227 if (in_len < variable_nonce_len_) {
David Benjamin31a07792015-03-03 14:20:26 -0500228 /* Publicly invalid. */
David Benjamin3570d732015-06-29 00:28:17 -0400229 OPENSSL_PUT_ERROR(SSL, SSL_R_BAD_PACKET_LENGTH);
David Benjamincfc11c22017-07-18 22:45:18 -0400230 return false;
David Benjamin31a07792015-03-03 14:20:26 -0500231 }
David Benjamincfc11c22017-07-18 22:45:18 -0400232 OPENSSL_memcpy(nonce + nonce_len, in, variable_nonce_len_);
233 in += variable_nonce_len_;
234 in_len -= variable_nonce_len_;
David Benjamin31a07792015-03-03 14:20:26 -0500235 } else {
David Benjamincfc11c22017-07-18 22:45:18 -0400236 assert(variable_nonce_len_ == 8);
237 OPENSSL_memcpy(nonce + nonce_len, seqnum, variable_nonce_len_);
David Benjamin31a07792015-03-03 14:20:26 -0500238 }
David Benjamincfc11c22017-07-18 22:45:18 -0400239 nonce_len += variable_nonce_len_;
David Benjamin31a07792015-03-03 14:20:26 -0500240
David Benjamin13414b32015-12-09 23:02:39 -0500241 /* XOR the fixed nonce, if necessary. */
David Benjamincfc11c22017-07-18 22:45:18 -0400242 if (xor_fixed_nonce_) {
243 assert(nonce_len == fixed_nonce_len_);
244 for (size_t i = 0; i < fixed_nonce_len_; i++) {
245 nonce[i] ^= fixed_nonce_[i];
David Benjamin13414b32015-12-09 23:02:39 -0500246 }
247 }
248
David Benjamina7810c12016-06-06 18:54:51 -0400249 /* Decrypt in-place. */
250 size_t len;
David Benjamincfc11c22017-07-18 22:45:18 -0400251 if (!EVP_AEAD_CTX_open(ctx_.get(), in, &len, in_len, nonce, nonce_len, in,
252 in_len, ad, ad_len)) {
253 return false;
David Benjamina7810c12016-06-06 18:54:51 -0400254 }
255 CBS_init(out, in, len);
David Benjamincfc11c22017-07-18 22:45:18 -0400256 return true;
David Benjamin31a07792015-03-03 14:20:26 -0500257}
258
David Benjamincfc11c22017-07-18 22:45:18 -0400259bool SSLAEADContext::SealScatter(uint8_t *out_prefix, uint8_t *out,
260 uint8_t *out_suffix, size_t *out_suffix_len,
261 size_t max_out_suffix_len, uint8_t type,
262 uint16_t wire_version, const uint8_t seqnum[8],
263 const uint8_t *in, size_t in_len,
264 const uint8_t *extra_in, size_t extra_in_len) {
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700265 if ((in != out && buffers_alias(in, in_len, out, in_len)) ||
266 buffers_alias(in, in_len, out_suffix, max_out_suffix_len)) {
267 OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
David Benjamincfc11c22017-07-18 22:45:18 -0400268 return false;
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700269 }
270 if (extra_in_len > max_out_suffix_len) {
271 OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
David Benjamincfc11c22017-07-18 22:45:18 -0400272 return false;
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700273 }
274
David Benjamincfc11c22017-07-18 22:45:18 -0400275 if (is_null_cipher() || FUZZER_MODE) {
David Benjamin31a07792015-03-03 14:20:26 -0500276 /* Handle the initial NULL cipher. */
David Benjamin17cf2cb2016-12-13 01:07:13 -0500277 OPENSSL_memmove(out, in, in_len);
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700278 OPENSSL_memmove(out_suffix, extra_in, extra_in_len);
279 *out_suffix_len = extra_in_len;
David Benjamincfc11c22017-07-18 22:45:18 -0400280 return true;
David Benjamin31a07792015-03-03 14:20:26 -0500281 }
282
283 uint8_t ad[13];
David Benjamincfc11c22017-07-18 22:45:18 -0400284 size_t ad_len = GetAdditionalData(ad, type, wire_version, seqnum, in_len);
David Benjamin31a07792015-03-03 14:20:26 -0500285
286 /* Assemble the nonce. */
287 uint8_t nonce[EVP_AEAD_MAX_NONCE_LENGTH];
288 size_t nonce_len = 0;
David Benjamin13414b32015-12-09 23:02:39 -0500289
290 /* Prepend the fixed nonce, or left-pad with zeros if XORing. */
David Benjamincfc11c22017-07-18 22:45:18 -0400291 if (xor_fixed_nonce_) {
292 nonce_len = fixed_nonce_len_ - variable_nonce_len_;
David Benjamin17cf2cb2016-12-13 01:07:13 -0500293 OPENSSL_memset(nonce, 0, nonce_len);
David Benjamin13414b32015-12-09 23:02:39 -0500294 } else {
David Benjamincfc11c22017-07-18 22:45:18 -0400295 OPENSSL_memcpy(nonce, fixed_nonce_, fixed_nonce_len_);
296 nonce_len += fixed_nonce_len_;
David Benjamin13414b32015-12-09 23:02:39 -0500297 }
298
299 /* Select the variable nonce. */
David Benjamincfc11c22017-07-18 22:45:18 -0400300 if (random_variable_nonce_) {
301 assert(variable_nonce_included_in_record_);
302 if (!RAND_bytes(nonce + nonce_len, variable_nonce_len_)) {
303 return false;
David Benjamin31a07792015-03-03 14:20:26 -0500304 }
305 } else {
306 /* When sending we use the sequence number as the variable part of the
307 * nonce. */
David Benjamincfc11c22017-07-18 22:45:18 -0400308 assert(variable_nonce_len_ == 8);
309 OPENSSL_memcpy(nonce + nonce_len, seqnum, variable_nonce_len_);
David Benjamin31a07792015-03-03 14:20:26 -0500310 }
David Benjamincfc11c22017-07-18 22:45:18 -0400311 nonce_len += variable_nonce_len_;
David Benjamin31a07792015-03-03 14:20:26 -0500312
313 /* Emit the variable nonce if included in the record. */
David Benjamincfc11c22017-07-18 22:45:18 -0400314 if (variable_nonce_included_in_record_) {
315 assert(!xor_fixed_nonce_);
316 if (buffers_alias(in, in_len, out_prefix, variable_nonce_len_)) {
David Benjamin3570d732015-06-29 00:28:17 -0400317 OPENSSL_PUT_ERROR(SSL, SSL_R_OUTPUT_ALIASES_INPUT);
David Benjamincfc11c22017-07-18 22:45:18 -0400318 return false;
David Benjamin31a07792015-03-03 14:20:26 -0500319 }
David Benjamincfc11c22017-07-18 22:45:18 -0400320 OPENSSL_memcpy(out_prefix, nonce + fixed_nonce_len_,
321 variable_nonce_len_);
David Benjamin31a07792015-03-03 14:20:26 -0500322 }
323
David Benjamin13414b32015-12-09 23:02:39 -0500324 /* XOR the fixed nonce, if necessary. */
David Benjamincfc11c22017-07-18 22:45:18 -0400325 if (xor_fixed_nonce_) {
326 assert(nonce_len == fixed_nonce_len_);
327 for (size_t i = 0; i < fixed_nonce_len_; i++) {
328 nonce[i] ^= fixed_nonce_[i];
David Benjamin13414b32015-12-09 23:02:39 -0500329 }
330 }
331
David Benjamincfc11c22017-07-18 22:45:18 -0400332 return !!EVP_AEAD_CTX_seal_scatter(
333 ctx_.get(), out, out_suffix, out_suffix_len, max_out_suffix_len, nonce,
334 nonce_len, in, in_len, extra_in, extra_in_len, ad, ad_len);
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700335}
336
David Benjamincfc11c22017-07-18 22:45:18 -0400337bool SSLAEADContext::Seal(uint8_t *out, size_t *out_len, size_t max_out_len,
338 uint8_t type, uint16_t wire_version,
339 const uint8_t seqnum[8], const uint8_t *in,
340 size_t in_len) {
341 size_t prefix_len = ExplicitNonceLen();
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700342 if (in_len + prefix_len < in_len) {
343 OPENSSL_PUT_ERROR(CIPHER, SSL_R_RECORD_TOO_LARGE);
David Benjamincfc11c22017-07-18 22:45:18 -0400344 return false;
David Benjamin31a07792015-03-03 14:20:26 -0500345 }
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700346 if (in_len + prefix_len > max_out_len) {
347 OPENSSL_PUT_ERROR(SSL, SSL_R_BUFFER_TOO_SMALL);
David Benjamincfc11c22017-07-18 22:45:18 -0400348 return false;
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700349 }
350
351 size_t suffix_len;
David Benjamincfc11c22017-07-18 22:45:18 -0400352 if (!SealScatter(out, out + prefix_len, out + prefix_len + in_len,
353 &suffix_len, max_out_len - prefix_len - in_len, type,
354 wire_version, seqnum, in, in_len, 0, 0)) {
355 return false;
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700356 }
David Benjamincfc11c22017-07-18 22:45:18 -0400357 assert(suffix_len <= MaxSuffixLen(0));
Martin Kreichgauer9f2bffb2017-06-30 05:29:50 -0700358 *out_len = prefix_len + in_len + suffix_len;
David Benjamincfc11c22017-07-18 22:45:18 -0400359 return true;
360}
361
362bool SSLAEADContext::GetIV(const uint8_t **out_iv, size_t *out_iv_len) const {
363 return !is_null_cipher() &&
364 EVP_AEAD_CTX_get_iv(ctx_.get(), out_iv, out_iv_len);
David Benjamin31a07792015-03-03 14:20:26 -0500365}
David Benjamin86e95b82017-07-18 16:34:25 -0400366
367} // namespace bssl