123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182 |
- // Copyright 2015 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "crypto/aead.h"
- #include <stddef.h>
- #include <stdint.h>
- #include <string>
- #include "base/strings/string_util.h"
- #include "crypto/openssl_util.h"
- #include "third_party/boringssl/src/include/openssl/aes.h"
- #include "third_party/boringssl/src/include/openssl/evp.h"
- namespace crypto {
- Aead::Aead(AeadAlgorithm algorithm) {
- EnsureOpenSSLInit();
- switch (algorithm) {
- case AES_128_CTR_HMAC_SHA256:
- aead_ = EVP_aead_aes_128_ctr_hmac_sha256();
- break;
- case AES_256_GCM:
- aead_ = EVP_aead_aes_256_gcm();
- break;
- case AES_256_GCM_SIV:
- aead_ = EVP_aead_aes_256_gcm_siv();
- break;
- case CHACHA20_POLY1305:
- aead_ = EVP_aead_chacha20_poly1305();
- break;
- }
- }
- Aead::~Aead() = default;
- void Aead::Init(base::span<const uint8_t> key) {
- DCHECK(!key_);
- DCHECK_EQ(KeyLength(), key.size());
- key_ = key;
- }
- static base::span<const uint8_t> ToSpan(base::StringPiece sp) {
- return base::as_bytes(base::make_span(sp));
- }
- void Aead::Init(const std::string* key) {
- Init(ToSpan(*key));
- }
- std::vector<uint8_t> Aead::Seal(
- base::span<const uint8_t> plaintext,
- base::span<const uint8_t> nonce,
- base::span<const uint8_t> additional_data) const {
- const size_t max_output_length =
- EVP_AEAD_max_overhead(aead_) + plaintext.size();
- CHECK(max_output_length >= plaintext.size());
- std::vector<uint8_t> ret;
- ret.resize(max_output_length);
- size_t output_length;
- CHECK(Seal(plaintext, nonce, additional_data, ret.data(), &output_length,
- max_output_length));
- ret.resize(output_length);
- return ret;
- }
- bool Aead::Seal(base::StringPiece plaintext,
- base::StringPiece nonce,
- base::StringPiece additional_data,
- std::string* ciphertext) const {
- const size_t max_output_length =
- EVP_AEAD_max_overhead(aead_) + plaintext.size();
- CHECK(max_output_length + 1 >= plaintext.size());
- uint8_t* out_ptr = reinterpret_cast<uint8_t*>(
- base::WriteInto(ciphertext, max_output_length + 1));
- size_t output_length;
- if (!Seal(ToSpan(plaintext), ToSpan(nonce), ToSpan(additional_data), out_ptr,
- &output_length, max_output_length)) {
- ciphertext->clear();
- return false;
- }
- ciphertext->resize(output_length);
- return true;
- }
- absl::optional<std::vector<uint8_t>> Aead::Open(
- base::span<const uint8_t> ciphertext,
- base::span<const uint8_t> nonce,
- base::span<const uint8_t> additional_data) const {
- const size_t max_output_length = ciphertext.size();
- std::vector<uint8_t> ret;
- ret.resize(max_output_length);
- size_t output_length;
- if (!Open(ciphertext, nonce, additional_data, ret.data(), &output_length,
- max_output_length)) {
- return absl::nullopt;
- }
- ret.resize(output_length);
- return ret;
- }
- bool Aead::Open(base::StringPiece ciphertext,
- base::StringPiece nonce,
- base::StringPiece additional_data,
- std::string* plaintext) const {
- const size_t max_output_length = ciphertext.size();
- CHECK(max_output_length + 1 > max_output_length);
- uint8_t* out_ptr = reinterpret_cast<uint8_t*>(
- base::WriteInto(plaintext, max_output_length + 1));
- size_t output_length;
- if (!Open(ToSpan(ciphertext), ToSpan(nonce), ToSpan(additional_data), out_ptr,
- &output_length, max_output_length)) {
- plaintext->clear();
- return false;
- }
- plaintext->resize(output_length);
- return true;
- }
- size_t Aead::KeyLength() const {
- return EVP_AEAD_key_length(aead_);
- }
- size_t Aead::NonceLength() const {
- return EVP_AEAD_nonce_length(aead_);
- }
- bool Aead::Seal(base::span<const uint8_t> plaintext,
- base::span<const uint8_t> nonce,
- base::span<const uint8_t> additional_data,
- uint8_t* out,
- size_t* output_length,
- size_t max_output_length) const {
- DCHECK(key_);
- DCHECK_EQ(NonceLength(), nonce.size());
- bssl::ScopedEVP_AEAD_CTX ctx;
- if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
- EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
- !EVP_AEAD_CTX_seal(ctx.get(), out, output_length, max_output_length,
- nonce.data(), nonce.size(), plaintext.data(),
- plaintext.size(), additional_data.data(),
- additional_data.size())) {
- return false;
- }
- DCHECK_LE(*output_length, max_output_length);
- return true;
- }
- bool Aead::Open(base::span<const uint8_t> plaintext,
- base::span<const uint8_t> nonce,
- base::span<const uint8_t> additional_data,
- uint8_t* out,
- size_t* output_length,
- size_t max_output_length) const {
- DCHECK(key_);
- DCHECK_EQ(NonceLength(), nonce.size());
- bssl::ScopedEVP_AEAD_CTX ctx;
- if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
- EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
- !EVP_AEAD_CTX_open(ctx.get(), out, output_length, max_output_length,
- nonce.data(), nonce.size(), plaintext.data(),
- plaintext.size(), additional_data.data(),
- additional_data.size())) {
- return false;
- }
- DCHECK_LE(*output_length, max_output_length);
- return true;
- }
- } // namespace crypto
|