stream_cipher.h 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
  2. This program is free software; you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License, version 2.0,
  4. as published by the Free Software Foundation.
  5. This program is also distributed with certain software (including
  6. but not limited to OpenSSL) that is licensed under separate terms,
  7. as designated in a particular file or component or in included license
  8. documentation. The authors of MySQL hereby grant you an additional
  9. permission to link the program and your derivative works with the
  10. separately licensed software that they have included with MySQL.
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. GNU General Public License, version 2.0, for more details.
  15. You should have received a copy of the GNU General Public License
  16. along with this program; if not, write to the Free Software
  17. Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
  18. #ifndef STREAM_CIPHER_INCLUDED
  19. #define STREAM_CIPHER_INCLUDED
  20. #include <openssl/evp.h>
  21. #include <memory>
  22. #include <string>
  23. /**
  24. @file stream_cipher.h
  25. @brief This file includes core components for encrypting/decrypting
  26. binary log files.
  27. */
  28. typedef std::basic_string<unsigned char> Key_string;
  29. /**
  30. @class Stream_cipher
  31. This abstract class represents the interface of a replication logs encryption
  32. cipher that can be used to encrypt/decrypt a given stream content in both
  33. sequential and random way.
  34. - Sequential means encrypting/decrypting a stream from the begin to end
  35. in order. For sequential encrypting/decrypting, you just need to call
  36. it like:
  37. open();
  38. encrypt();
  39. ...
  40. encrypt(); // call it again and again
  41. ...
  42. close();
  43. - Random means encrypting/decrypting a stream data without order. For
  44. example:
  45. - It first encrypts the data of a stream at the offset from 100 to 200.
  46. - And then encrypts the data of the stream at the offset from 0 to 99.
  47. For random encrypting/decrypting, you need to call set_stream_offset()
  48. before calling encrypt(). Example:
  49. open();
  50. set_stream_offset(100);
  51. encrypt(...);
  52. ...
  53. set_stream_offset(0);
  54. encrypt(...)
  55. close();
  56. */
  57. class Stream_cipher {
  58. public:
  59. virtual ~Stream_cipher() {}
  60. /**
  61. Open the cipher with given password.
  62. @param[in] password The password which is used to initialize the cipher.
  63. @param[in] header_size The encrypted stream offset wrt the down stream.
  64. @retval false Success.
  65. @retval true Error.
  66. */
  67. virtual bool open(const Key_string &password, int header_size) = 0;
  68. /** Close the cipher. */
  69. virtual void close() = 0;
  70. /**
  71. Encrypt data.
  72. @param[in] dest The buffer for storing encrypted data. It should be
  73. at least 'length' bytes.
  74. @param[in] src The data which will be encrypted.
  75. @param[in] length Length of the data.
  76. @retval false Success.
  77. @retval true Error.
  78. */
  79. virtual bool encrypt(unsigned char *dest, const unsigned char *src,
  80. int length) = 0;
  81. /**
  82. Decrypt data.
  83. @param[in] dest The buffer for storing decrypted data. It should be
  84. at least 'length' bytes.
  85. @param[in] src The data which will be decrypted.
  86. @param[in] length Length of the data.
  87. @retval false Success.
  88. @retval true Error.
  89. */
  90. virtual bool decrypt(unsigned char *dest, const unsigned char *src,
  91. int length) = 0;
  92. /**
  93. Support encrypting/decrypting data at random position of a stream.
  94. @param[in] offset The stream offset of the data which will be encrypted/
  95. decrypted in next encrypt()/decrypt() call.
  96. @retval false Success.
  97. @retval true Error.
  98. */
  99. virtual bool set_stream_offset(uint64_t offset) = 0;
  100. /**
  101. Returns the size of the header of the stream being encrypted/decrypted.
  102. @return the size of the header of the stream being encrypted/decrypted.
  103. */
  104. int get_header_size();
  105. protected:
  106. int m_header_size = 0;
  107. };
  108. /**
  109. @class Aes_ctr
  110. The class provides standards to be used by the Aes_ctr ciphers.
  111. */
  112. class Aes_ctr {
  113. public:
  114. static const int PASSWORD_LENGTH = 32;
  115. static const int AES_BLOCK_SIZE = 16;
  116. static const int FILE_KEY_LENGTH = 32;
  117. /**
  118. Returns the message digest function to be uses when opening the cipher.
  119. @return SHA-512 message digest.
  120. */
  121. static const EVP_MD *get_evp_md() { return EVP_sha512(); }
  122. /**
  123. Returns the cipher to be uses when using the cipher.
  124. @return AES-256-CTR.
  125. */
  126. static const EVP_CIPHER *get_evp_cipher() { return EVP_aes_256_ctr(); }
  127. /**
  128. Returns a new unique Stream_cipher encryptor.
  129. @return A new Stream_cipher encryptor.
  130. */
  131. static std::unique_ptr<Stream_cipher> get_encryptor();
  132. /**
  133. Returns a new unique Stream_cipher decryptor.
  134. @return A new Stream_cipher decryptor.
  135. */
  136. static std::unique_ptr<Stream_cipher> get_decryptor();
  137. };
  138. enum class Cipher_type : int { ENCRYPT = 0, DECRYPT = 1 };
  139. /**
  140. @class Aes_ctr_cipher
  141. The class implements AES-CTR encryption/decryption. It supports to
  142. encrypt/decrypt a stream in both sequential and random way.
  143. */
  144. template <Cipher_type TYPE>
  145. class Aes_ctr_cipher : public Stream_cipher {
  146. public:
  147. static const int PASSWORD_LENGTH = Aes_ctr::PASSWORD_LENGTH;
  148. static const int AES_BLOCK_SIZE = Aes_ctr::AES_BLOCK_SIZE;
  149. static const int FILE_KEY_LENGTH = Aes_ctr::FILE_KEY_LENGTH;
  150. virtual ~Aes_ctr_cipher() override;
  151. bool open(const Key_string &password, int header_size) override;
  152. void close() override;
  153. bool encrypt(unsigned char *dest, const unsigned char *src,
  154. int length) override;
  155. bool decrypt(unsigned char *dest, const unsigned char *src,
  156. int length) override;
  157. bool set_stream_offset(uint64_t offset) override;
  158. private:
  159. /* Cipher context */
  160. EVP_CIPHER_CTX *m_ctx = nullptr;
  161. /* The file key to encrypt/decrypt data. */
  162. unsigned char m_file_key[FILE_KEY_LENGTH];
  163. /* The initialization vector (IV) used to encrypt/decrypt data. */
  164. unsigned char m_iv[AES_BLOCK_SIZE];
  165. /**
  166. Initialize OpenSSL cipher related context and IV.
  167. @param[in] offset The stream offset to compute the AES-CTR counter which
  168. will be set into IV.
  169. @retval false Success.
  170. @retval true Error.
  171. */
  172. bool init_cipher(uint64_t offset);
  173. /** Destroy OpenSSL cipher related context. */
  174. void deinit_cipher();
  175. };
  176. typedef class Aes_ctr_cipher<Cipher_type::ENCRYPT> Aes_ctr_encryptor;
  177. typedef class Aes_ctr_cipher<Cipher_type::DECRYPT> Aes_ctr_decryptor;
  178. #endif // STREAM_CIPHER_INCLUDED