blob: 933d94b302ba3a853b0db08542a1c42badadc37a [file] [log] [blame]
Avi Drissman201a9a832022-09-13 19:39:251// Copyright 2015 The Chromium Authors
estark03206a12015-04-25 04:52:252// 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
David Benjamin78bbd022024-02-09 01:02:4911#include "base/containers/span.h"
12#include "base/numerics/checked_math.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 switch (algorithm) {
20 case AES_128_CTR_HMAC_SHA256:
21 aead_ = EVP_aead_aes_128_ctr_hmac_sha256();
22 break;
Kim Paulhamus98e3cb92c2018-05-01 16:49:4223 case AES_256_GCM:
24 aead_ = EVP_aead_aes_256_gcm();
25 break;
Martin Kreichgaueraa06bffa2018-06-29 07:54:1026 case AES_256_GCM_SIV:
27 aead_ = EVP_aead_aes_256_gcm_siv();
28 break;
Leonid Baraz07c05772020-08-18 19:55:0929 case CHACHA20_POLY1305:
30 aead_ = EVP_aead_chacha20_poly1305();
31 break;
estark03206a12015-04-25 04:52:2532 }
33}
34
Chris Watkinsa850a302017-11-30 03:53:4935Aead::~Aead() = default;
estark03206a12015-04-25 04:52:2536
Adam Langleyf21497312019-08-09 22:23:3337void Aead::Init(base::span<const uint8_t> key) {
estark03206a12015-04-25 04:52:2538 DCHECK(!key_);
Adam Langleyf21497312019-08-09 22:23:3339 DCHECK_EQ(KeyLength(), key.size());
estark03206a12015-04-25 04:52:2540 key_ = key;
41}
42
Adam Langleyf21497312019-08-09 22:23:3343void Aead::Init(const std::string* key) {
David Benjamin78bbd022024-02-09 01:02:4944 Init(base::as_byte_span(*key));
Adam Langleyf21497312019-08-09 22:23:3345}
46
47std::vector<uint8_t> Aead::Seal(
48 base::span<const uint8_t> plaintext,
49 base::span<const uint8_t> nonce,
50 base::span<const uint8_t> additional_data) const {
David Benjamin78bbd022024-02-09 01:02:4951 size_t max_output_length =
52 base::CheckAdd(plaintext.size(), EVP_AEAD_max_overhead(aead_))
53 .ValueOrDie();
54 std::vector<uint8_t> ret(max_output_length);
Adam Langleyf21497312019-08-09 22:23:3355
David Benjamin78bbd022024-02-09 01:02:4956 std::optional<size_t> output_length =
57 Seal(plaintext, nonce, additional_data, ret);
58 CHECK(output_length);
59 ret.resize(*output_length);
Adam Langleyf21497312019-08-09 22:23:3360 return ret;
61}
62
David Benjamin3bfdc522023-09-01 21:13:4563bool Aead::Seal(std::string_view plaintext,
64 std::string_view nonce,
65 std::string_view additional_data,
estark03206a12015-04-25 04:52:2566 std::string* ciphertext) const {
David Benjamin78bbd022024-02-09 01:02:4967 size_t max_output_length =
68 base::CheckAdd(plaintext.size(), EVP_AEAD_max_overhead(aead_))
69 .ValueOrDie();
70 ciphertext->resize(max_output_length);
estark03206a12015-04-25 04:52:2571
David Benjamin78bbd022024-02-09 01:02:4972 std::optional<size_t> output_length =
73 Seal(base::as_byte_span(plaintext), base::as_byte_span(nonce),
74 base::as_byte_span(additional_data),
75 base::as_writable_byte_span(*ciphertext));
76 if (!output_length) {
Adam Langleyf21497312019-08-09 22:23:3377 ciphertext->clear();
estark03206a12015-04-25 04:52:2578 return false;
79 }
80
David Benjamin78bbd022024-02-09 01:02:4981 ciphertext->resize(*output_length);
estark03206a12015-04-25 04:52:2582 return true;
83}
84
Arthur Sonzogni59ac8222023-11-10 09:46:5485std::optional<std::vector<uint8_t>> Aead::Open(
Adam Langleyf21497312019-08-09 22:23:3386 base::span<const uint8_t> ciphertext,
87 base::span<const uint8_t> nonce,
88 base::span<const uint8_t> additional_data) const {
89 const size_t max_output_length = ciphertext.size();
David Benjamin78bbd022024-02-09 01:02:4990 std::vector<uint8_t> ret(max_output_length);
Adam Langleyf21497312019-08-09 22:23:3391
David Benjamin78bbd022024-02-09 01:02:4992 std::optional<size_t> output_length =
93 Open(ciphertext, nonce, additional_data, ret);
94 if (!output_length) {
Arthur Sonzogni59ac8222023-11-10 09:46:5495 return std::nullopt;
Adam Langleyf21497312019-08-09 22:23:3396 }
97
David Benjamin78bbd022024-02-09 01:02:4998 ret.resize(*output_length);
Adam Langleyf21497312019-08-09 22:23:3399 return ret;
100}
101
David Benjamin3bfdc522023-09-01 21:13:45102bool Aead::Open(std::string_view ciphertext,
103 std::string_view nonce,
104 std::string_view additional_data,
estark03206a12015-04-25 04:52:25105 std::string* plaintext) const {
estark03206a12015-04-25 04:52:25106 const size_t max_output_length = ciphertext.size();
David Benjamin78bbd022024-02-09 01:02:49107 plaintext->resize(max_output_length);
estark03206a12015-04-25 04:52:25108
David Benjamin78bbd022024-02-09 01:02:49109 std::optional<size_t> output_length =
110 Open(base::as_byte_span(ciphertext), base::as_byte_span(nonce),
111 base::as_byte_span(additional_data),
112 base::as_writable_byte_span(*plaintext));
113 if (!output_length) {
Adam Langleyf21497312019-08-09 22:23:33114 plaintext->clear();
estark03206a12015-04-25 04:52:25115 return false;
116 }
117
David Benjamin78bbd022024-02-09 01:02:49118 plaintext->resize(*output_length);
estark03206a12015-04-25 04:52:25119 return true;
120}
121
122size_t Aead::KeyLength() const {
123 return EVP_AEAD_key_length(aead_);
124}
125
126size_t Aead::NonceLength() const {
127 return EVP_AEAD_nonce_length(aead_);
128}
129
David Benjamin78bbd022024-02-09 01:02:49130std::optional<size_t> Aead::Seal(base::span<const uint8_t> plaintext,
131 base::span<const uint8_t> nonce,
132 base::span<const uint8_t> additional_data,
133 base::span<uint8_t> out) const {
Adam Langleyf21497312019-08-09 22:23:33134 DCHECK(key_);
135 DCHECK_EQ(NonceLength(), nonce.size());
136 bssl::ScopedEVP_AEAD_CTX ctx;
137
David Benjamin78bbd022024-02-09 01:02:49138 size_t out_len;
Adam Langleyf21497312019-08-09 22:23:33139 if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
140 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
David Benjamin78bbd022024-02-09 01:02:49141 !EVP_AEAD_CTX_seal(ctx.get(), out.data(), &out_len, out.size(),
Adam Langleyf21497312019-08-09 22:23:33142 nonce.data(), nonce.size(), plaintext.data(),
143 plaintext.size(), additional_data.data(),
144 additional_data.size())) {
David Benjamin78bbd022024-02-09 01:02:49145 return std::nullopt;
Adam Langleyf21497312019-08-09 22:23:33146 }
147
David Benjamin78bbd022024-02-09 01:02:49148 DCHECK_LE(out_len, out.size());
149 return out_len;
Adam Langleyf21497312019-08-09 22:23:33150}
151
David Benjamin78bbd022024-02-09 01:02:49152std::optional<size_t> Aead::Open(base::span<const uint8_t> plaintext,
153 base::span<const uint8_t> nonce,
154 base::span<const uint8_t> additional_data,
155 base::span<uint8_t> out) const {
Adam Langleyf21497312019-08-09 22:23:33156 DCHECK(key_);
157 DCHECK_EQ(NonceLength(), nonce.size());
158 bssl::ScopedEVP_AEAD_CTX ctx;
159
David Benjamin78bbd022024-02-09 01:02:49160 size_t out_len;
Adam Langleyf21497312019-08-09 22:23:33161 if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
162 EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
David Benjamin78bbd022024-02-09 01:02:49163 !EVP_AEAD_CTX_open(ctx.get(), out.data(), &out_len, out.size(),
Adam Langleyf21497312019-08-09 22:23:33164 nonce.data(), nonce.size(), plaintext.data(),
165 plaintext.size(), additional_data.data(),
166 additional_data.size())) {
David Benjamin78bbd022024-02-09 01:02:49167 return std::nullopt;
Adam Langleyf21497312019-08-09 22:23:33168 }
169
David Benjamin78bbd022024-02-09 01:02:49170 DCHECK_LE(out_len, out.size());
171 return out_len;
Adam Langleyf21497312019-08-09 22:23:33172}
173
davidben6004dc52017-02-03 04:15:29174} // namespace crypto