1 // Copyright 2015 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "crypto/aead.h"
11 #include "base/strings/string_util.h"
12 #include "crypto/openssl_util.h"
13 #include "third_party/boringssl/src/include/openssl/aes.h"
14 #include "third_party/boringssl/src/include/openssl/evp.h"
18 Aead::Aead(AeadAlgorithm algorithm) {
21 case AES_128_CTR_HMAC_SHA256:
22 aead_ = EVP_aead_aes_128_ctr_hmac_sha256();
25 aead_ = EVP_aead_aes_256_gcm();
28 aead_ = EVP_aead_aes_256_gcm_siv();
30 case CHACHA20_POLY1305:
31 aead_ = EVP_aead_chacha20_poly1305();
36 Aead::~Aead() = default;
38 void Aead::Init(base::span<const uint8_t> key) {
40 DCHECK_EQ(KeyLength(), key.size());
44 static base::span<const uint8_t> ToSpan(std::string_view sp) {
45 return base::as_bytes(base::make_span(sp));
48 void Aead::Init(const std::string* key) {
52 std::vector<uint8_t> Aead::Seal(
53 base::span<const uint8_t> plaintext,
54 base::span<const uint8_t> nonce,
55 base::span<const uint8_t> additional_data) const {
56 const size_t max_output_length =
57 EVP_AEAD_max_overhead(aead_) + plaintext.size();
58 CHECK(max_output_length >= plaintext.size());
59 std::vector<uint8_t> ret;
60 ret.resize(max_output_length);
63 CHECK(Seal(plaintext, nonce, additional_data, ret.data(), &output_length,
65 ret.resize(output_length);
69 bool Aead::Seal(std::string_view plaintext,
70 std::string_view nonce,
71 std::string_view additional_data,
72 std::string* ciphertext) const {
73 const size_t max_output_length =
74 EVP_AEAD_max_overhead(aead_) + plaintext.size();
75 CHECK(max_output_length + 1 >= plaintext.size());
76 uint8_t* out_ptr = reinterpret_cast<uint8_t*>(
77 base::WriteInto(ciphertext, max_output_length + 1));
80 if (!Seal(ToSpan(plaintext), ToSpan(nonce), ToSpan(additional_data), out_ptr,
81 &output_length, max_output_length)) {
86 ciphertext->resize(output_length);
90 absl::optional<std::vector<uint8_t>> Aead::Open(
91 base::span<const uint8_t> ciphertext,
92 base::span<const uint8_t> nonce,
93 base::span<const uint8_t> additional_data) const {
94 const size_t max_output_length = ciphertext.size();
95 std::vector<uint8_t> ret;
96 ret.resize(max_output_length);
99 if (!Open(ciphertext, nonce, additional_data, ret.data(), &output_length,
100 max_output_length)) {
101 return absl::nullopt;
104 ret.resize(output_length);
108 bool Aead::Open(std::string_view ciphertext,
109 std::string_view nonce,
110 std::string_view additional_data,
111 std::string* plaintext) const {
112 const size_t max_output_length = ciphertext.size();
113 CHECK(max_output_length + 1 > max_output_length);
114 uint8_t* out_ptr = reinterpret_cast<uint8_t*>(
115 base::WriteInto(plaintext, max_output_length + 1));
117 size_t output_length;
118 if (!Open(ToSpan(ciphertext), ToSpan(nonce), ToSpan(additional_data), out_ptr,
119 &output_length, max_output_length)) {
124 plaintext->resize(output_length);
128 size_t Aead::KeyLength() const {
129 return EVP_AEAD_key_length(aead_);
132 size_t Aead::NonceLength() const {
133 return EVP_AEAD_nonce_length(aead_);
136 bool Aead::Seal(base::span<const uint8_t> plaintext,
137 base::span<const uint8_t> nonce,
138 base::span<const uint8_t> additional_data,
140 size_t* output_length,
141 size_t max_output_length) const {
143 DCHECK_EQ(NonceLength(), nonce.size());
144 bssl::ScopedEVP_AEAD_CTX ctx;
146 if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
147 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
148 !EVP_AEAD_CTX_seal(ctx.get(), out, output_length, max_output_length,
149 nonce.data(), nonce.size(), plaintext.data(),
150 plaintext.size(), additional_data.data(),
151 additional_data.size())) {
155 DCHECK_LE(*output_length, max_output_length);
159 bool Aead::Open(base::span<const uint8_t> plaintext,
160 base::span<const uint8_t> nonce,
161 base::span<const uint8_t> additional_data,
163 size_t* output_length,
164 size_t max_output_length) const {
166 DCHECK_EQ(NonceLength(), nonce.size());
167 bssl::ScopedEVP_AEAD_CTX ctx;
169 if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
170 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
171 !EVP_AEAD_CTX_open(ctx.get(), out, output_length, max_output_length,
172 nonce.data(), nonce.size(), plaintext.data(),
173 plaintext.size(), additional_data.data(),
174 additional_data.size())) {
178 DCHECK_LE(*output_length, max_output_length);
182 } // namespace crypto