blob: 6ba5cec6b6a1095e045cf988e7faa5e506d7c832 [file] [log] [blame]
estark03206a12015-04-25 04:52:251// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
svaldez22de42fe2016-04-21 19:42:225#include "crypto/aead.h"
estark03206a12015-04-25 04:52:256
avidd373b8b2015-12-21 21:34:437#include <stddef.h>
8#include <stdint.h>
estark03206a12015-04-25 04:52:259#include <string>
10
estark03206a12015-04-25 04:52:2511#include "base/strings/string_util.h"
12#include "crypto/openssl_util.h"
tfarina29a3a1742016-10-28 18:47:3313#include "third_party/boringssl/src/include/openssl/aes.h"
14#include "third_party/boringssl/src/include/openssl/evp.h"
estark03206a12015-04-25 04:52:2515
16namespace crypto {
17
Adam Langleyf21497312019-08-09 22:23:3318Aead::Aead(AeadAlgorithm algorithm) {
estark03206a12015-04-25 04:52:2519 EnsureOpenSSLInit();
20 switch (algorithm) {
21 case AES_128_CTR_HMAC_SHA256:
22 aead_ = EVP_aead_aes_128_ctr_hmac_sha256();
23 break;
Kim Paulhamus98e3cb92c2018-05-01 16:49:4224 case AES_256_GCM:
25 aead_ = EVP_aead_aes_256_gcm();
26 break;
Martin Kreichgaueraa06bffa2018-06-29 07:54:1027 case AES_256_GCM_SIV:
28 aead_ = EVP_aead_aes_256_gcm_siv();
29 break;
Leonid Baraz07c05772020-08-18 19:55:0930 case CHACHA20_POLY1305:
31 aead_ = EVP_aead_chacha20_poly1305();
32 break;
estark03206a12015-04-25 04:52:2533 }
34}
35
Chris Watkinsa850a302017-11-30 03:53:4936Aead::~Aead() = default;
estark03206a12015-04-25 04:52:2537
Adam Langleyf21497312019-08-09 22:23:3338void Aead::Init(base::span<const uint8_t> key) {
estark03206a12015-04-25 04:52:2539 DCHECK(!key_);
Adam Langleyf21497312019-08-09 22:23:3340 DCHECK_EQ(KeyLength(), key.size());
estark03206a12015-04-25 04:52:2541 key_ = key;
42}
43
Adam Langleyf21497312019-08-09 22:23:3344static base::span<const uint8_t> ToSpan(base::StringPiece sp) {
45 return base::as_bytes(base::make_span(sp));
46}
47
48void Aead::Init(const std::string* key) {
49 Init(ToSpan(*key));
50}
51
52std::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);
61
62 size_t output_length;
63 CHECK(Seal(plaintext, nonce, additional_data, ret.data(), &output_length,
64 max_output_length));
65 ret.resize(output_length);
66 return ret;
67}
68
David Benjamincda45eb2017-11-06 18:16:5269bool Aead::Seal(base::StringPiece plaintext,
70 base::StringPiece nonce,
71 base::StringPiece additional_data,
estark03206a12015-04-25 04:52:2572 std::string* ciphertext) const {
estark03206a12015-04-25 04:52:2573 const size_t max_output_length =
74 EVP_AEAD_max_overhead(aead_) + plaintext.size();
Adam Langleyf21497312019-08-09 22:23:3375 CHECK(max_output_length + 1 >= plaintext.size());
avidd373b8b2015-12-21 21:34:4376 uint8_t* out_ptr = reinterpret_cast<uint8_t*>(
Adam Langleyf21497312019-08-09 22:23:3377 base::WriteInto(ciphertext, max_output_length + 1));
estark03206a12015-04-25 04:52:2578
Adam Langleyf21497312019-08-09 22:23:3379 size_t output_length;
80 if (!Seal(ToSpan(plaintext), ToSpan(nonce), ToSpan(additional_data), out_ptr,
81 &output_length, max_output_length)) {
82 ciphertext->clear();
estark03206a12015-04-25 04:52:2583 return false;
84 }
85
Adam Langleyf21497312019-08-09 22:23:3386 ciphertext->resize(output_length);
estark03206a12015-04-25 04:52:2587 return true;
88}
89
Adam Langleyf21497312019-08-09 22:23:3390base::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);
97
98 size_t output_length;
99 if (!Open(ciphertext, nonce, additional_data, ret.data(), &output_length,
100 max_output_length)) {
101 return base::nullopt;
102 }
103
104 ret.resize(output_length);
105 return ret;
106}
107
David Benjamincda45eb2017-11-06 18:16:52108bool Aead::Open(base::StringPiece ciphertext,
109 base::StringPiece nonce,
110 base::StringPiece additional_data,
estark03206a12015-04-25 04:52:25111 std::string* plaintext) const {
estark03206a12015-04-25 04:52:25112 const size_t max_output_length = ciphertext.size();
Adam Langleyf21497312019-08-09 22:23:33113 CHECK(max_output_length + 1 > max_output_length);
avidd373b8b2015-12-21 21:34:43114 uint8_t* out_ptr = reinterpret_cast<uint8_t*>(
Adam Langleyf21497312019-08-09 22:23:33115 base::WriteInto(plaintext, max_output_length + 1));
estark03206a12015-04-25 04:52:25116
Adam Langleyf21497312019-08-09 22:23:33117 size_t output_length;
118 if (!Open(ToSpan(ciphertext), ToSpan(nonce), ToSpan(additional_data), out_ptr,
119 &output_length, max_output_length)) {
120 plaintext->clear();
estark03206a12015-04-25 04:52:25121 return false;
122 }
123
Adam Langleyf21497312019-08-09 22:23:33124 plaintext->resize(output_length);
estark03206a12015-04-25 04:52:25125 return true;
126}
127
128size_t Aead::KeyLength() const {
129 return EVP_AEAD_key_length(aead_);
130}
131
132size_t Aead::NonceLength() const {
133 return EVP_AEAD_nonce_length(aead_);
134}
135
Adam Langleyf21497312019-08-09 22:23:33136bool Aead::Seal(base::span<const uint8_t> plaintext,
137 base::span<const uint8_t> nonce,
138 base::span<const uint8_t> additional_data,
139 uint8_t* out,
140 size_t* output_length,
141 size_t max_output_length) const {
142 DCHECK(key_);
143 DCHECK_EQ(NonceLength(), nonce.size());
144 bssl::ScopedEVP_AEAD_CTX ctx;
145
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())) {
152 return false;
153 }
154
155 DCHECK_LE(*output_length, max_output_length);
156 return true;
157}
158
159bool Aead::Open(base::span<const uint8_t> plaintext,
160 base::span<const uint8_t> nonce,
161 base::span<const uint8_t> additional_data,
162 uint8_t* out,
163 size_t* output_length,
164 size_t max_output_length) const {
165 DCHECK(key_);
166 DCHECK_EQ(NonceLength(), nonce.size());
167 bssl::ScopedEVP_AEAD_CTX ctx;
168
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())) {
175 return false;
176 }
177
178 DCHECK_LE(*output_length, max_output_length);
179 return true;
180}
181
davidben6004dc52017-02-03 04:15:29182} // namespace crypto