KeyValueHolder.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Tencent is pleased to support the open source community by making
  3. * MMKV available.
  4. *
  5. * Copyright (C) 2020 THL A29 Limited, a Tencent company.
  6. * All rights reserved.
  7. *
  8. * Licensed under the BSD 3-Clause License (the "License"); you may not use
  9. * this file except in compliance with the License. You may obtain a copy of
  10. * the License at
  11. *
  12. * https://opensource.org/licenses/BSD-3-Clause
  13. *
  14. * Unless required by applicable law or agreed to in writing, software
  15. * distributed under the License is distributed on an "AS IS" BASIS,
  16. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17. * See the License for the specific language governing permissions and
  18. * limitations under the License.
  19. */
  20. #include "KeyValueHolder.h"
  21. #include "PBUtility.h"
  22. #include "aes/AESCrypt.h"
  23. #include <cerrno>
  24. #include <cstring>
  25. #include <stdexcept>
  26. namespace mmkv {
  27. KeyValueHolder::KeyValueHolder(uint32_t keyLength, uint32_t valueLength, uint32_t off)
  28. : keySize(static_cast<uint16_t>(keyLength)), valueSize(valueLength), offset(off) {
  29. computedKVSize = keySize + static_cast<uint16_t>(pbRawVarint32Size(keySize));
  30. computedKVSize += static_cast<uint16_t>(pbRawVarint32Size(valueSize));
  31. }
  32. MMBuffer KeyValueHolder::toMMBuffer(const void *basePtr) const {
  33. auto realPtr = (uint8_t *) basePtr + offset;
  34. realPtr += computedKVSize;
  35. return MMBuffer(realPtr, valueSize, MMBufferNoCopy);
  36. }
  37. #ifndef MMKV_DISABLE_CRYPT
  38. KeyValueHolderCrypt::KeyValueHolderCrypt(const void *src, size_t length) {
  39. if (length <= SmallBufferSize()) {
  40. type = KeyValueHolderType_Direct;
  41. paddedSize = static_cast<uint8_t>(length);
  42. memcpy(paddedValue, src, length);
  43. } else {
  44. type = KeyValueHolderType_Memory;
  45. memSize = static_cast<uint32_t>(length);
  46. memPtr = malloc(length);
  47. if (!memPtr) {
  48. throw std::runtime_error(strerror(errno));
  49. }
  50. memcpy(memPtr, src, memSize);
  51. }
  52. }
  53. KeyValueHolderCrypt::KeyValueHolderCrypt(MMBuffer &&data) {
  54. if (data.type == MMBuffer::MMBufferType_Small) {
  55. static_assert(SmallBufferSize() >= MMBuffer::SmallBufferSize(), "KeyValueHolderCrypt can't hold MMBuffer");
  56. type = KeyValueHolderType_Direct;
  57. paddedSize = static_cast<uint8_t>(data.length());
  58. memcpy(paddedValue, data.getPtr(), data.length());
  59. } else {
  60. type = KeyValueHolderType_Memory;
  61. memSize = static_cast<uint32_t>(data.length());
  62. # ifdef MMKV_APPLE
  63. if (data.m_data != nil) {
  64. memPtr = malloc(memSize);
  65. if (!memPtr) {
  66. throw std::runtime_error(strerror(errno));
  67. }
  68. memcpy(memPtr, data.getPtr(), memSize);
  69. return;
  70. }
  71. # endif
  72. memPtr = data.getPtr();
  73. data.detach();
  74. }
  75. }
  76. KeyValueHolderCrypt::KeyValueHolderCrypt(uint32_t keyLength, uint32_t valueLength, uint32_t off)
  77. : type(KeyValueHolderType_Offset), keySize(static_cast<uint16_t>(keyLength)), valueSize(valueLength), offset(off) {
  78. pbKeyValueSize = static_cast<uint8_t>(pbRawVarint32Size(keySize) + pbRawVarint32Size(valueSize));
  79. }
  80. KeyValueHolderCrypt::KeyValueHolderCrypt(KeyValueHolderCrypt &&other) noexcept {
  81. this->move(std::move(other));
  82. }
  83. KeyValueHolderCrypt &KeyValueHolderCrypt::operator=(KeyValueHolderCrypt &&other) noexcept {
  84. if (type == KeyValueHolderType_Memory && memPtr) {
  85. free(memPtr);
  86. }
  87. this->move(std::move(other));
  88. return *this;
  89. }
  90. void KeyValueHolderCrypt::move(KeyValueHolderCrypt &&other) noexcept {
  91. if (other.type == KeyValueHolderType_Direct || other.type == KeyValueHolderType_Offset) {
  92. memcpy(this, &other, sizeof(other));
  93. } else if (other.type == KeyValueHolderType_Memory) {
  94. type = KeyValueHolderType_Memory;
  95. memSize = other.memSize;
  96. memPtr = other.memPtr;
  97. other.memPtr = nullptr;
  98. }
  99. }
  100. KeyValueHolderCrypt::~KeyValueHolderCrypt() {
  101. if (type == KeyValueHolderType_Memory && memPtr) {
  102. free(memPtr);
  103. }
  104. }
  105. uint32_t KeyValueHolderCrypt::realValueSize() const {
  106. switch (type) {
  107. case KeyValueHolderType_Direct:
  108. return paddedSize;
  109. case KeyValueHolderType_Offset:
  110. return valueSize;
  111. case KeyValueHolderType_Memory:
  112. return memSize;
  113. }
  114. return 0;
  115. }
  116. // get decrypt data with [position, -1)
  117. static MMBuffer decryptBuffer(AESCrypt &crypter, const MMBuffer &inputBuffer, size_t position) {
  118. static size_t smallBuffer[16 / sizeof(size_t)];
  119. auto basePtr = (uint8_t *) inputBuffer.getPtr();
  120. auto ptr = basePtr;
  121. for (size_t index = sizeof(smallBuffer); index < position; index += sizeof(smallBuffer)) {
  122. crypter.decrypt(ptr, smallBuffer, sizeof(smallBuffer));
  123. ptr += sizeof(smallBuffer);
  124. }
  125. if (ptr < basePtr + position) {
  126. crypter.decrypt(ptr, smallBuffer, static_cast<size_t>(basePtr + position - ptr));
  127. ptr = basePtr + position;
  128. }
  129. size_t length = inputBuffer.length() - position;
  130. MMBuffer tmp(length);
  131. auto input = ptr;
  132. auto output = tmp.getPtr();
  133. crypter.decrypt(input, output, length);
  134. return tmp;
  135. }
  136. MMBuffer KeyValueHolderCrypt::toMMBuffer(const void *basePtr, const AESCrypt *crypter) const {
  137. if (type == KeyValueHolderType_Direct) {
  138. return MMBuffer((void *) paddedValue, paddedSize, MMBufferNoCopy);
  139. } else if (type == KeyValueHolderType_Memory) {
  140. return MMBuffer(memPtr, memSize, MMBufferNoCopy);
  141. } else {
  142. auto realPtr = (uint8_t *) basePtr + offset;
  143. auto position = static_cast<uint32_t>(pbKeyValueSize + keySize);
  144. auto realSize = position + valueSize;
  145. auto kvBuffer = MMBuffer(realPtr, realSize, MMBufferNoCopy);
  146. auto decrypter = crypter->cloneWithStatus(cryptStatus);
  147. return decryptBuffer(decrypter, kvBuffer, position);
  148. }
  149. }
  150. #endif // MMKV_DISABLE_CRYPT
  151. } // namespace mmkv
  152. #if !defined(MMKV_DISABLE_CRYPT) && defined(MMKV_DEBUG)
  153. # include "CodedInputData.h"
  154. # include "CodedOutputData.h"
  155. # include "MMKVLog.h"
  156. # include <ctime>
  157. using namespace std;
  158. namespace mmkv {
  159. void KeyValueHolderCrypt::testAESToMMBuffer() {
  160. const uint8_t plainText[] = "Hello, OpenSSL-mmkv::KeyValueHolderCrypt::testAESToMMBuffer() with AES CFB 128.";
  161. constexpr size_t textLength = sizeof(plainText) - 1;
  162. const uint8_t key[] = "TheAESKey";
  163. constexpr size_t keyLength = sizeof(key) - 1;
  164. uint8_t iv[AES_KEY_LEN];
  165. srand((unsigned) time(nullptr));
  166. for (uint32_t i = 0; i < AES_KEY_LEN; i++) {
  167. iv[i] = (uint8_t) rand();
  168. }
  169. AESCrypt crypt1(key, keyLength, iv, sizeof(iv));
  170. auto encryptText = new uint8_t[DEFAULT_MMAP_SIZE];
  171. memset(encryptText, 0, DEFAULT_MMAP_SIZE);
  172. CodedOutputData output(encryptText, DEFAULT_MMAP_SIZE);
  173. output.writeData(MMBuffer((void *) key, keyLength, MMBufferNoCopy));
  174. auto lengthOfValue = textLength + pbRawVarint32Size((uint32_t) textLength);
  175. output.writeRawVarint32((int32_t) lengthOfValue);
  176. output.writeData(MMBuffer((void *) plainText, textLength, MMBufferNoCopy));
  177. crypt1.encrypt(encryptText, encryptText, (size_t)(output.curWritePointer() - encryptText));
  178. AESCrypt decrypt(key, keyLength, iv, sizeof(iv));
  179. uint8_t smallBuffer[32];
  180. decrypt.decrypt(encryptText, smallBuffer, 5);
  181. auto keySize = CodedInputData(smallBuffer, 5).readUInt32();
  182. auto sizeOfKeySize = pbRawVarint32Size(keySize);
  183. auto position = sizeOfKeySize;
  184. decrypt.decrypt(encryptText + 5, smallBuffer + 5, static_cast<size_t>(sizeOfKeySize + keySize - 5));
  185. position += keySize;
  186. decrypt.decrypt(encryptText + position, smallBuffer + position, 5);
  187. auto valueSize = CodedInputData(smallBuffer + position, 5).readUInt32();
  188. // auto sizeOfValueSize = pbRawVarint32Size(valueSize);
  189. KeyValueHolderCrypt kvHolder(keySize, valueSize, 0);
  190. auto rollbackSize = position + 5;
  191. decrypt.statusBeforeDecrypt(encryptText + rollbackSize, smallBuffer + rollbackSize, rollbackSize,
  192. kvHolder.cryptStatus);
  193. auto value = kvHolder.toMMBuffer(encryptText, &decrypt);
  194. # ifdef MMKV_APPLE
  195. MMKVInfo("testAESToMMBuffer: %@", CodedInputData((char *) value.getPtr(), value.length()).readString());
  196. # else
  197. MMKVInfo("testAESToMMBuffer: %s", CodedInputData((char *) value.getPtr(), value.length()).readString().c_str());
  198. # endif
  199. MMKVInfo("MMBuffer::SmallBufferSize() = %u, KeyValueHolderCrypt::SmallBufferSize() = %u",
  200. MMBuffer::SmallBufferSize(), KeyValueHolderCrypt::SmallBufferSize());
  201. delete[] encryptText;
  202. }
  203. } // namespace mmkv
  204. #endif