aead.cc 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  1. // 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. #include "crypto/aead.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include <string>
  8. #include "base/strings/string_util.h"
  9. #include "crypto/openssl_util.h"
  10. #include "third_party/boringssl/src/include/openssl/aes.h"
  11. #include "third_party/boringssl/src/include/openssl/evp.h"
  12. namespace crypto {
  13. Aead::Aead(AeadAlgorithm algorithm) {
  14. EnsureOpenSSLInit();
  15. switch (algorithm) {
  16. case AES_128_CTR_HMAC_SHA256:
  17. aead_ = EVP_aead_aes_128_ctr_hmac_sha256();
  18. break;
  19. case AES_256_GCM:
  20. aead_ = EVP_aead_aes_256_gcm();
  21. break;
  22. case AES_256_GCM_SIV:
  23. aead_ = EVP_aead_aes_256_gcm_siv();
  24. break;
  25. case CHACHA20_POLY1305:
  26. aead_ = EVP_aead_chacha20_poly1305();
  27. break;
  28. }
  29. }
  30. Aead::~Aead() = default;
  31. void Aead::Init(base::span<const uint8_t> key) {
  32. DCHECK(!key_);
  33. DCHECK_EQ(KeyLength(), key.size());
  34. key_ = key;
  35. }
  36. static base::span<const uint8_t> ToSpan(base::StringPiece sp) {
  37. return base::as_bytes(base::make_span(sp));
  38. }
  39. void Aead::Init(const std::string* key) {
  40. Init(ToSpan(*key));
  41. }
  42. std::vector<uint8_t> Aead::Seal(
  43. base::span<const uint8_t> plaintext,
  44. base::span<const uint8_t> nonce,
  45. base::span<const uint8_t> additional_data) const {
  46. const size_t max_output_length =
  47. EVP_AEAD_max_overhead(aead_) + plaintext.size();
  48. CHECK(max_output_length >= plaintext.size());
  49. std::vector<uint8_t> ret;
  50. ret.resize(max_output_length);
  51. size_t output_length;
  52. CHECK(Seal(plaintext, nonce, additional_data, ret.data(), &output_length,
  53. max_output_length));
  54. ret.resize(output_length);
  55. return ret;
  56. }
  57. bool Aead::Seal(base::StringPiece plaintext,
  58. base::StringPiece nonce,
  59. base::StringPiece additional_data,
  60. std::string* ciphertext) const {
  61. const size_t max_output_length =
  62. EVP_AEAD_max_overhead(aead_) + plaintext.size();
  63. CHECK(max_output_length + 1 >= plaintext.size());
  64. uint8_t* out_ptr = reinterpret_cast<uint8_t*>(
  65. base::WriteInto(ciphertext, max_output_length + 1));
  66. size_t output_length;
  67. if (!Seal(ToSpan(plaintext), ToSpan(nonce), ToSpan(additional_data), out_ptr,
  68. &output_length, max_output_length)) {
  69. ciphertext->clear();
  70. return false;
  71. }
  72. ciphertext->resize(output_length);
  73. return true;
  74. }
  75. absl::optional<std::vector<uint8_t>> Aead::Open(
  76. base::span<const uint8_t> ciphertext,
  77. base::span<const uint8_t> nonce,
  78. base::span<const uint8_t> additional_data) const {
  79. const size_t max_output_length = ciphertext.size();
  80. std::vector<uint8_t> ret;
  81. ret.resize(max_output_length);
  82. size_t output_length;
  83. if (!Open(ciphertext, nonce, additional_data, ret.data(), &output_length,
  84. max_output_length)) {
  85. return absl::nullopt;
  86. }
  87. ret.resize(output_length);
  88. return ret;
  89. }
  90. bool Aead::Open(base::StringPiece ciphertext,
  91. base::StringPiece nonce,
  92. base::StringPiece additional_data,
  93. std::string* plaintext) const {
  94. const size_t max_output_length = ciphertext.size();
  95. CHECK(max_output_length + 1 > max_output_length);
  96. uint8_t* out_ptr = reinterpret_cast<uint8_t*>(
  97. base::WriteInto(plaintext, max_output_length + 1));
  98. size_t output_length;
  99. if (!Open(ToSpan(ciphertext), ToSpan(nonce), ToSpan(additional_data), out_ptr,
  100. &output_length, max_output_length)) {
  101. plaintext->clear();
  102. return false;
  103. }
  104. plaintext->resize(output_length);
  105. return true;
  106. }
  107. size_t Aead::KeyLength() const {
  108. return EVP_AEAD_key_length(aead_);
  109. }
  110. size_t Aead::NonceLength() const {
  111. return EVP_AEAD_nonce_length(aead_);
  112. }
  113. bool Aead::Seal(base::span<const uint8_t> plaintext,
  114. base::span<const uint8_t> nonce,
  115. base::span<const uint8_t> additional_data,
  116. uint8_t* out,
  117. size_t* output_length,
  118. size_t max_output_length) const {
  119. DCHECK(key_);
  120. DCHECK_EQ(NonceLength(), nonce.size());
  121. bssl::ScopedEVP_AEAD_CTX ctx;
  122. if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
  123. EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
  124. !EVP_AEAD_CTX_seal(ctx.get(), out, output_length, max_output_length,
  125. nonce.data(), nonce.size(), plaintext.data(),
  126. plaintext.size(), additional_data.data(),
  127. additional_data.size())) {
  128. return false;
  129. }
  130. DCHECK_LE(*output_length, max_output_length);
  131. return true;
  132. }
  133. bool Aead::Open(base::span<const uint8_t> plaintext,
  134. base::span<const uint8_t> nonce,
  135. base::span<const uint8_t> additional_data,
  136. uint8_t* out,
  137. size_t* output_length,
  138. size_t max_output_length) const {
  139. DCHECK(key_);
  140. DCHECK_EQ(NonceLength(), nonce.size());
  141. bssl::ScopedEVP_AEAD_CTX ctx;
  142. if (!EVP_AEAD_CTX_init(ctx.get(), aead_, key_->data(), key_->size(),
  143. EVP_AEAD_DEFAULT_TAG_LENGTH, nullptr) ||
  144. !EVP_AEAD_CTX_open(ctx.get(), out, output_length, max_output_length,
  145. nonce.data(), nonce.size(), plaintext.data(),
  146. plaintext.size(), additional_data.data(),
  147. additional_data.size())) {
  148. return false;
  149. }
  150. DCHECK_LE(*output_length, max_output_length);
  151. return true;
  152. }
  153. } // namespace crypto