storage_encryption.cpp 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // This file is part of Desktop App Toolkit,
  2. // a set of libraries for developing nice desktop applications.
  3. //
  4. // For license and copyright information please follow this link:
  5. // https://github.com/desktop-app/legal/blob/master/LEGAL
  6. //
  7. #include "storage/storage_encryption.h"
  8. #include "base/openssl_help.h"
  9. namespace Storage {
  10. CtrState::CtrState(bytes::const_span key, bytes::const_span iv) {
  11. Expects(key.size() == _key.size());
  12. Expects(iv.size() == _iv.size());
  13. bytes::copy(_key, key);
  14. bytes::copy(_iv, iv);
  15. }
  16. template <typename Method>
  17. void CtrState::process(bytes::span data, int64 offset, Method method) {
  18. Expects((data.size() % kBlockSize) == 0);
  19. Expects((offset % kBlockSize) == 0);
  20. AES_KEY aes;
  21. AES_set_encrypt_key(
  22. reinterpret_cast<const uchar*>(_key.data()),
  23. _key.size() * CHAR_BIT,
  24. &aes);
  25. unsigned char ecountBuf[kBlockSize] = { 0 };
  26. unsigned int offsetInBlock = 0;
  27. const auto blockIndex = offset / kBlockSize;
  28. auto iv = incrementedIv(blockIndex);
  29. CRYPTO_ctr128_encrypt(
  30. reinterpret_cast<const uchar*>(data.data()),
  31. reinterpret_cast<uchar*>(data.data()),
  32. data.size(),
  33. &aes,
  34. reinterpret_cast<unsigned char*>(iv.data()),
  35. ecountBuf,
  36. &offsetInBlock,
  37. (block128_f)method);
  38. }
  39. auto CtrState::incrementedIv(int64 blockIndex)
  40. -> bytes::array<kIvSize> {
  41. Expects(blockIndex >= 0);
  42. if (!blockIndex) {
  43. return _iv;
  44. }
  45. auto result = _iv;
  46. auto digits = kIvSize;
  47. auto increment = uint64(blockIndex);
  48. do {
  49. --digits;
  50. increment += static_cast<uint64>(result[digits]);
  51. result[digits] = static_cast<bytes::type>(increment & 0xFFULL);
  52. increment >>= 8;
  53. } while (digits != 0 && increment != 0);
  54. return result;
  55. }
  56. void CtrState::encrypt(bytes::span data, int64 offset) {
  57. return process(data, offset, AES_encrypt);
  58. }
  59. void CtrState::decrypt(bytes::span data, int64 offset) {
  60. return process(data, offset, AES_encrypt);
  61. }
  62. EncryptionKey::EncryptionKey(bytes::vector &&data)
  63. : _data(std::move(data)) {
  64. Expects(_data.size() == kSize || _data.size() == kSize_v2);
  65. }
  66. bool EncryptionKey::empty() const {
  67. return _data.empty();
  68. }
  69. EncryptionKey::operator bool() const {
  70. return !empty();
  71. }
  72. const bytes::vector &EncryptionKey::data() const {
  73. return _data;
  74. }
  75. CtrState EncryptionKey::prepareCtrState(bytes::const_span salt) const {
  76. Expects(salt.size() == kSaltSize);
  77. Expects(!empty());
  78. const auto data = bytes::make_span(_data);
  79. const auto key = openssl::Sha256(
  80. data.subspan(0, data.size() / 2),
  81. salt.subspan(0, kSaltSize / 2));
  82. const auto iv = openssl::Sha256(
  83. data.subspan(data.size() / 2),
  84. salt.subspan(kSaltSize / 2));
  85. return CtrState(
  86. key,
  87. bytes::make_span(iv).subspan(0, CtrState::kIvSize));
  88. }
  89. } // namespace Storage