1*6777b538SAndroid Build Coastguard Worker // Copyright 2015 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "crypto/aead.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <stddef.h>
8*6777b538SAndroid Build Coastguard Worker #include <stdint.h>
9*6777b538SAndroid Build Coastguard Worker #include <string>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/containers/span.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/numerics/checked_math.h"
13*6777b538SAndroid Build Coastguard Worker #include "crypto/openssl_util.h"
14*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/aes.h"
15*6777b538SAndroid Build Coastguard Worker #include "third_party/boringssl/src/include/openssl/evp.h"
16*6777b538SAndroid Build Coastguard Worker
17*6777b538SAndroid Build Coastguard Worker namespace crypto {
18*6777b538SAndroid Build Coastguard Worker
Aead(AeadAlgorithm algorithm)19*6777b538SAndroid Build Coastguard Worker Aead::Aead(AeadAlgorithm algorithm) {
20*6777b538SAndroid Build Coastguard Worker EnsureOpenSSLInit();
21*6777b538SAndroid Build Coastguard Worker switch (algorithm) {
22*6777b538SAndroid Build Coastguard Worker case AES_128_CTR_HMAC_SHA256:
23*6777b538SAndroid Build Coastguard Worker aead_ = EVP_aead_aes_128_ctr_hmac_sha256();
24*6777b538SAndroid Build Coastguard Worker break;
25*6777b538SAndroid Build Coastguard Worker case AES_256_GCM:
26*6777b538SAndroid Build Coastguard Worker aead_ = EVP_aead_aes_256_gcm();
27*6777b538SAndroid Build Coastguard Worker break;
28*6777b538SAndroid Build Coastguard Worker case AES_256_GCM_SIV:
29*6777b538SAndroid Build Coastguard Worker aead_ = EVP_aead_aes_256_gcm_siv();
30*6777b538SAndroid Build Coastguard Worker break;
31*6777b538SAndroid Build Coastguard Worker case CHACHA20_POLY1305:
32*6777b538SAndroid Build Coastguard Worker aead_ = EVP_aead_chacha20_poly1305();
33*6777b538SAndroid Build Coastguard Worker break;
34*6777b538SAndroid Build Coastguard Worker }
35*6777b538SAndroid Build Coastguard Worker }
36*6777b538SAndroid Build Coastguard Worker
37*6777b538SAndroid Build Coastguard Worker Aead::~Aead() = default;
38*6777b538SAndroid Build Coastguard Worker
Init(base::span<const uint8_t> key)39*6777b538SAndroid Build Coastguard Worker void Aead::Init(base::span<const uint8_t> key) {
40*6777b538SAndroid Build Coastguard Worker DCHECK(!key_);
41*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(KeyLength(), key.size());
42*6777b538SAndroid Build Coastguard Worker key_ = key;
43*6777b538SAndroid Build Coastguard Worker }
44*6777b538SAndroid Build Coastguard Worker
Init(const std::string * key)45*6777b538SAndroid Build Coastguard Worker void Aead::Init(const std::string* key) {
46*6777b538SAndroid Build Coastguard Worker Init(base::as_byte_span(*key));
47*6777b538SAndroid Build Coastguard Worker }
48*6777b538SAndroid Build Coastguard Worker
Seal(base::span<const uint8_t> plaintext,base::span<const uint8_t> nonce,base::span<const uint8_t> additional_data) const49*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> Aead::Seal(
50*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> plaintext,
51*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> nonce,
52*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> additional_data) const {
53*6777b538SAndroid Build Coastguard Worker size_t max_output_length =
54*6777b538SAndroid Build Coastguard Worker base::CheckAdd(plaintext.size(), EVP_AEAD_max_overhead(aead_))
55*6777b538SAndroid Build Coastguard Worker .ValueOrDie();
56*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> ret(max_output_length);
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker std::optional<size_t> output_length =
59*6777b538SAndroid Build Coastguard Worker Seal(plaintext, nonce, additional_data, ret);
60*6777b538SAndroid Build Coastguard Worker CHECK(output_length);
61*6777b538SAndroid Build Coastguard Worker ret.resize(*output_length);
62*6777b538SAndroid Build Coastguard Worker return ret;
63*6777b538SAndroid Build Coastguard Worker }
64*6777b538SAndroid Build Coastguard Worker
Seal(std::string_view plaintext,std::string_view nonce,std::string_view additional_data,std::string * ciphertext) const65*6777b538SAndroid Build Coastguard Worker bool Aead::Seal(std::string_view plaintext,
66*6777b538SAndroid Build Coastguard Worker std::string_view nonce,
67*6777b538SAndroid Build Coastguard Worker std::string_view additional_data,
68*6777b538SAndroid Build Coastguard Worker std::string* ciphertext) const {
69*6777b538SAndroid Build Coastguard Worker size_t max_output_length =
70*6777b538SAndroid Build Coastguard Worker base::CheckAdd(plaintext.size(), EVP_AEAD_max_overhead(aead_))
71*6777b538SAndroid Build Coastguard Worker .ValueOrDie();
72*6777b538SAndroid Build Coastguard Worker ciphertext->resize(max_output_length);
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Worker std::optional<size_t> output_length =
75*6777b538SAndroid Build Coastguard Worker Seal(base::as_byte_span(plaintext), base::as_byte_span(nonce),
76*6777b538SAndroid Build Coastguard Worker base::as_byte_span(additional_data),
77*6777b538SAndroid Build Coastguard Worker base::as_writable_byte_span(*ciphertext));
78*6777b538SAndroid Build Coastguard Worker if (!output_length) {
79*6777b538SAndroid Build Coastguard Worker ciphertext->clear();
80*6777b538SAndroid Build Coastguard Worker return false;
81*6777b538SAndroid Build Coastguard Worker }
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Worker ciphertext->resize(*output_length);
84*6777b538SAndroid Build Coastguard Worker return true;
85*6777b538SAndroid Build Coastguard Worker }
86*6777b538SAndroid Build Coastguard Worker
Open(base::span<const uint8_t> ciphertext,base::span<const uint8_t> nonce,base::span<const uint8_t> additional_data) const87*6777b538SAndroid Build Coastguard Worker std::optional<std::vector<uint8_t>> Aead::Open(
88*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> ciphertext,
89*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> nonce,
90*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> additional_data) const {
91*6777b538SAndroid Build Coastguard Worker const size_t max_output_length = ciphertext.size();
92*6777b538SAndroid Build Coastguard Worker std::vector<uint8_t> ret(max_output_length);
93*6777b538SAndroid Build Coastguard Worker
94*6777b538SAndroid Build Coastguard Worker std::optional<size_t> output_length =
95*6777b538SAndroid Build Coastguard Worker Open(ciphertext, nonce, additional_data, ret);
96*6777b538SAndroid Build Coastguard Worker if (!output_length) {
97*6777b538SAndroid Build Coastguard Worker return std::nullopt;
98*6777b538SAndroid Build Coastguard Worker }
99*6777b538SAndroid Build Coastguard Worker
100*6777b538SAndroid Build Coastguard Worker ret.resize(*output_length);
101*6777b538SAndroid Build Coastguard Worker return ret;
102*6777b538SAndroid Build Coastguard Worker }
103*6777b538SAndroid Build Coastguard Worker
Open(std::string_view ciphertext,std::string_view nonce,std::string_view additional_data,std::string * plaintext) const104*6777b538SAndroid Build Coastguard Worker bool Aead::Open(std::string_view ciphertext,
105*6777b538SAndroid Build Coastguard Worker std::string_view nonce,
106*6777b538SAndroid Build Coastguard Worker std::string_view additional_data,
107*6777b538SAndroid Build Coastguard Worker std::string* plaintext) const {
108*6777b538SAndroid Build Coastguard Worker const size_t max_output_length = ciphertext.size();
109*6777b538SAndroid Build Coastguard Worker plaintext->resize(max_output_length);
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker std::optional<size_t> output_length =
112*6777b538SAndroid Build Coastguard Worker Open(base::as_byte_span(ciphertext), base::as_byte_span(nonce),
113*6777b538SAndroid Build Coastguard Worker base::as_byte_span(additional_data),
114*6777b538SAndroid Build Coastguard Worker base::as_writable_byte_span(*plaintext));
115*6777b538SAndroid Build Coastguard Worker if (!output_length) {
116*6777b538SAndroid Build Coastguard Worker plaintext->clear();
117*6777b538SAndroid Build Coastguard Worker return false;
118*6777b538SAndroid Build Coastguard Worker }
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker plaintext->resize(*output_length);
121*6777b538SAndroid Build Coastguard Worker return true;
122*6777b538SAndroid Build Coastguard Worker }
123*6777b538SAndroid Build Coastguard Worker
KeyLength() const124*6777b538SAndroid Build Coastguard Worker size_t Aead::KeyLength() const {
125*6777b538SAndroid Build Coastguard Worker return EVP_AEAD_key_length(aead_);
126*6777b538SAndroid Build Coastguard Worker }
127*6777b538SAndroid Build Coastguard Worker
NonceLength() const128*6777b538SAndroid Build Coastguard Worker size_t Aead::NonceLength() const {
129*6777b538SAndroid Build Coastguard Worker return EVP_AEAD_nonce_length(aead_);
130*6777b538SAndroid Build Coastguard Worker }
131*6777b538SAndroid Build Coastguard Worker
Seal(base::span<const uint8_t> plaintext,base::span<const uint8_t> nonce,base::span<const uint8_t> additional_data,base::span<uint8_t> out) const132*6777b538SAndroid Build Coastguard Worker std::optional<size_t> Aead::Seal(base::span<const uint8_t> plaintext,
133*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> nonce,
134*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> additional_data,
135*6777b538SAndroid Build Coastguard Worker base::span<uint8_t> out) const {
136*6777b538SAndroid Build Coastguard Worker DCHECK(key_);
137*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(NonceLength(), nonce.size());
138*6777b538SAndroid Build Coastguard Worker bssl::ScopedEVP_AEAD_CTX ctx;
139*6777b538SAndroid Build Coastguard Worker
140*6777b538SAndroid Build Coastguard Worker size_t out_len;
141*6777b538SAndroid Build Coastguard Worker if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
142*6777b538SAndroid Build Coastguard Worker EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
143*6777b538SAndroid Build Coastguard Worker !EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
144*6777b538SAndroid Build Coastguard Worker nonce.data(), nonce.size(), plaintext.data(),
145*6777b538SAndroid Build Coastguard Worker plaintext.size(), additional_data.data(),
146*6777b538SAndroid Build Coastguard Worker additional_data.size())) {
147*6777b538SAndroid Build Coastguard Worker return std::nullopt;
148*6777b538SAndroid Build Coastguard Worker }
149*6777b538SAndroid Build Coastguard Worker
150*6777b538SAndroid Build Coastguard Worker DCHECK_LE(out_len, out.size());
151*6777b538SAndroid Build Coastguard Worker return out_len;
152*6777b538SAndroid Build Coastguard Worker }
153*6777b538SAndroid Build Coastguard Worker
Open(base::span<const uint8_t> plaintext,base::span<const uint8_t> nonce,base::span<const uint8_t> additional_data,base::span<uint8_t> out) const154*6777b538SAndroid Build Coastguard Worker std::optional<size_t> Aead::Open(base::span<const uint8_t> plaintext,
155*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> nonce,
156*6777b538SAndroid Build Coastguard Worker base::span<const uint8_t> additional_data,
157*6777b538SAndroid Build Coastguard Worker base::span<uint8_t> out) const {
158*6777b538SAndroid Build Coastguard Worker DCHECK(key_);
159*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(NonceLength(), nonce.size());
160*6777b538SAndroid Build Coastguard Worker bssl::ScopedEVP_AEAD_CTX ctx;
161*6777b538SAndroid Build Coastguard Worker
162*6777b538SAndroid Build Coastguard Worker size_t out_len;
163*6777b538SAndroid Build Coastguard Worker if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
164*6777b538SAndroid Build Coastguard Worker EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
165*6777b538SAndroid Build Coastguard Worker !EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
166*6777b538SAndroid Build Coastguard Worker nonce.data(), nonce.size(), plaintext.data(),
167*6777b538SAndroid Build Coastguard Worker plaintext.size(), additional_data.data(),
168*6777b538SAndroid Build Coastguard Worker additional_data.size())) {
169*6777b538SAndroid Build Coastguard Worker return std::nullopt;
170*6777b538SAndroid Build Coastguard Worker }
171*6777b538SAndroid Build Coastguard Worker
172*6777b538SAndroid Build Coastguard Worker DCHECK_LE(out_len, out.size());
173*6777b538SAndroid Build Coastguard Worker return out_len;
174*6777b538SAndroid Build Coastguard Worker }
175*6777b538SAndroid Build Coastguard Worker
176*6777b538SAndroid Build Coastguard Worker } // namespace crypto
177