encryptor.cc 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210
  1. // Copyright (c) 2012 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/encryptor.h"
  5. #include <stddef.h>
  6. #include <stdint.h>
  7. #include "base/logging.h"
  8. #include "base/strings/string_util.h"
  9. #include "base/sys_byteorder.h"
  10. #include "crypto/openssl_util.h"
  11. #include "crypto/symmetric_key.h"
  12. #include "third_party/boringssl/src/include/openssl/aes.h"
  13. #include "third_party/boringssl/src/include/openssl/evp.h"
  14. namespace crypto {
  15. namespace {
  16. const EVP_CIPHER* GetCipherForKey(const SymmetricKey* key) {
  17. switch (key->key().length()) {
  18. case 16: return EVP_aes_128_cbc();
  19. case 32: return EVP_aes_256_cbc();
  20. default:
  21. return nullptr;
  22. }
  23. }
  24. } // namespace
  25. /////////////////////////////////////////////////////////////////////////////
  26. // Encryptor Implementation.
  27. Encryptor::Encryptor() : key_(nullptr), mode_(CBC) {}
  28. Encryptor::~Encryptor() = default;
  29. bool Encryptor::Init(const SymmetricKey* key, Mode mode, base::StringPiece iv) {
  30. return Init(key, mode, base::as_bytes(base::make_span(iv)));
  31. }
  32. bool Encryptor::Init(const SymmetricKey* key,
  33. Mode mode,
  34. base::span<const uint8_t> iv) {
  35. DCHECK(key);
  36. DCHECK(mode == CBC || mode == CTR);
  37. EnsureOpenSSLInit();
  38. if (mode == CBC && iv.size() != AES_BLOCK_SIZE)
  39. return false;
  40. // CTR mode passes the starting counter separately, via SetCounter().
  41. if (mode == CTR && !iv.empty())
  42. return false;
  43. if (GetCipherForKey(key) == nullptr)
  44. return false;
  45. key_ = key;
  46. mode_ = mode;
  47. iv_.assign(iv.begin(), iv.end());
  48. return true;
  49. }
  50. bool Encryptor::Encrypt(base::StringPiece plaintext, std::string* ciphertext) {
  51. CHECK(!plaintext.empty() || mode_ == CBC);
  52. return CryptString(/*do_encrypt=*/true, plaintext, ciphertext);
  53. }
  54. bool Encryptor::Encrypt(base::span<const uint8_t> plaintext,
  55. std::vector<uint8_t>* ciphertext) {
  56. CHECK(!plaintext.empty() || mode_ == CBC);
  57. return CryptBytes(/*do_encrypt=*/true, plaintext, ciphertext);
  58. }
  59. bool Encryptor::Decrypt(base::StringPiece ciphertext, std::string* plaintext) {
  60. CHECK(!ciphertext.empty());
  61. return CryptString(/*do_encrypt=*/false, ciphertext, plaintext);
  62. }
  63. bool Encryptor::Decrypt(base::span<const uint8_t> ciphertext,
  64. std::vector<uint8_t>* plaintext) {
  65. CHECK(!ciphertext.empty());
  66. return CryptBytes(/*do_encrypt=*/false, ciphertext, plaintext);
  67. }
  68. bool Encryptor::SetCounter(base::StringPiece counter) {
  69. return SetCounter(base::as_bytes(base::make_span(counter)));
  70. }
  71. bool Encryptor::SetCounter(base::span<const uint8_t> counter) {
  72. if (mode_ != CTR)
  73. return false;
  74. if (counter.size() != 16u)
  75. return false;
  76. iv_.assign(counter.begin(), counter.end());
  77. return true;
  78. }
  79. bool Encryptor::CryptString(bool do_encrypt,
  80. base::StringPiece input,
  81. std::string* output) {
  82. size_t out_size = MaxOutput(do_encrypt, input.size());
  83. CHECK_GT(out_size + 1, out_size); // Overflow
  84. std::string result;
  85. uint8_t* out_ptr =
  86. reinterpret_cast<uint8_t*>(base::WriteInto(&result, out_size + 1));
  87. absl::optional<size_t> len =
  88. (mode_ == CTR)
  89. ? CryptCTR(do_encrypt, base::as_bytes(base::make_span(input)),
  90. base::make_span(out_ptr, out_size))
  91. : Crypt(do_encrypt, base::as_bytes(base::make_span(input)),
  92. base::make_span(out_ptr, out_size));
  93. if (!len)
  94. return false;
  95. result.resize(*len);
  96. *output = std::move(result);
  97. return true;
  98. }
  99. bool Encryptor::CryptBytes(bool do_encrypt,
  100. base::span<const uint8_t> input,
  101. std::vector<uint8_t>* output) {
  102. std::vector<uint8_t> result(MaxOutput(do_encrypt, input.size()));
  103. absl::optional<size_t> len = (mode_ == CTR)
  104. ? CryptCTR(do_encrypt, input, result)
  105. : Crypt(do_encrypt, input, result);
  106. if (!len)
  107. return false;
  108. result.resize(*len);
  109. *output = std::move(result);
  110. return true;
  111. }
  112. size_t Encryptor::MaxOutput(bool do_encrypt, size_t length) {
  113. size_t result = length + ((do_encrypt && mode_ == CBC) ? 16 : 0);
  114. CHECK_GE(result, length); // Overflow
  115. return result;
  116. }
  117. absl::optional<size_t> Encryptor::Crypt(bool do_encrypt,
  118. base::span<const uint8_t> input,
  119. base::span<uint8_t> output) {
  120. DCHECK(key_); // Must call Init() before En/De-crypt.
  121. const EVP_CIPHER* cipher = GetCipherForKey(key_);
  122. DCHECK(cipher); // Already handled in Init();
  123. const std::string& key = key_->key();
  124. DCHECK_EQ(EVP_CIPHER_iv_length(cipher), iv_.size());
  125. DCHECK_EQ(EVP_CIPHER_key_length(cipher), key.size());
  126. OpenSSLErrStackTracer err_tracer(FROM_HERE);
  127. bssl::ScopedEVP_CIPHER_CTX ctx;
  128. if (!EVP_CipherInit_ex(ctx.get(), cipher, nullptr,
  129. reinterpret_cast<const uint8_t*>(key.data()),
  130. iv_.data(), do_encrypt)) {
  131. return absl::nullopt;
  132. }
  133. // Encrypting needs a block size of space to allow for any padding.
  134. CHECK_GE(output.size(), input.size() + (do_encrypt ? iv_.size() : 0));
  135. int out_len;
  136. if (!EVP_CipherUpdate(ctx.get(), output.data(), &out_len, input.data(),
  137. input.size()))
  138. return absl::nullopt;
  139. // Write out the final block plus padding (if any) to the end of the data
  140. // just written.
  141. int tail_len;
  142. if (!EVP_CipherFinal_ex(ctx.get(), output.data() + out_len, &tail_len))
  143. return absl::nullopt;
  144. out_len += tail_len;
  145. DCHECK_LE(out_len, static_cast<int>(output.size()));
  146. return out_len;
  147. }
  148. absl::optional<size_t> Encryptor::CryptCTR(bool do_encrypt,
  149. base::span<const uint8_t> input,
  150. base::span<uint8_t> output) {
  151. if (iv_.size() != AES_BLOCK_SIZE) {
  152. LOG(ERROR) << "Counter value not set in CTR mode.";
  153. return absl::nullopt;
  154. }
  155. AES_KEY aes_key;
  156. if (AES_set_encrypt_key(reinterpret_cast<const uint8_t*>(key_->key().data()),
  157. key_->key().size() * 8, &aes_key) != 0) {
  158. return absl::nullopt;
  159. }
  160. uint8_t ecount_buf[AES_BLOCK_SIZE] = { 0 };
  161. unsigned int block_offset = 0;
  162. // |output| must have room for |input|.
  163. CHECK_GE(output.size(), input.size());
  164. // Note AES_ctr128_encrypt() will update |iv_|. However, this method discards
  165. // |ecount_buf| and |block_offset|, so this is not quite a streaming API.
  166. AES_ctr128_encrypt(input.data(), output.data(), input.size(), &aes_key,
  167. iv_.data(), ecount_buf, &block_offset);
  168. return input.size();
  169. }
  170. } // namespace crypto