libmongocrypt-helper 1.7.4.0.1001 → 1.8.0.0.1001

Sign up to get free protection for your applications and to get access to all the features.
Files changed (398) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/ext/libmongocrypt/extconf.rb +2 -2
  4. data/ext/libmongocrypt/libmongocrypt/CHANGELOG.md +9 -7
  5. data/ext/libmongocrypt/libmongocrypt/CMakeLists.txt +17 -23
  6. data/ext/libmongocrypt/libmongocrypt/Earthfile +374 -0
  7. data/ext/libmongocrypt/libmongocrypt/README.md +7 -7
  8. data/ext/libmongocrypt/libmongocrypt/VERSION_CURRENT +1 -1
  9. data/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/CryptClient.cs +25 -6
  10. data/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt/Library.cs +25 -3
  11. data/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Example/MongoDB.Libmongocrypt.Example.csproj +1 -1
  12. data/ext/libmongocrypt/libmongocrypt/bindings/cs/MongoDB.Libmongocrypt.Test/BasicTests.cs +1 -1
  13. data/ext/libmongocrypt/libmongocrypt/bindings/cs/Scripts/build.cake +3 -2
  14. data/ext/libmongocrypt/libmongocrypt/bindings/cs/cs.sln +79 -0
  15. data/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/build.gradle.kts +2 -2
  16. data/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/java/com/mongodb/crypt/capi/MongoCryptTest.java +6 -4
  17. data/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit-v2/int32/encrypted-payload.json +26 -0
  18. data/ext/libmongocrypt/libmongocrypt/bindings/node/CHANGELOG.md +24 -0
  19. data/ext/libmongocrypt/libmongocrypt/bindings/node/README.md +134 -5
  20. data/ext/libmongocrypt/libmongocrypt/bindings/node/etc/build-static.sh +3 -6
  21. data/ext/libmongocrypt/libmongocrypt/bindings/node/index.d.ts +203 -77
  22. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/autoEncrypter.js +1 -1
  23. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/clientEncryption.js +165 -43
  24. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/common.js +12 -14
  25. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/errors.js +75 -0
  26. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/index.js +34 -3
  27. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/aws.js +26 -0
  28. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/azure.js +178 -0
  29. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/gcp.js +24 -0
  30. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/index.js +54 -0
  31. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/providers/utils.js +39 -0
  32. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/stateMachine.js +9 -4
  33. data/ext/libmongocrypt/libmongocrypt/bindings/node/package-lock.json +4440 -5189
  34. data/ext/libmongocrypt/libmongocrypt/bindings/node/package.json +27 -8
  35. data/ext/libmongocrypt/libmongocrypt/bindings/node/src/mongocrypt.cc +65 -38
  36. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/autoEncrypter.test.js +4 -7
  37. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/clientEncryption.test.js +434 -42
  38. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/common.test.js +94 -0
  39. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/cryptoCallbacks.test.js +1 -45
  40. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/index.test.js +45 -0
  41. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/mongocryptdManager.test.js +1 -1
  42. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/providers/credentialsProvider.test.js +551 -0
  43. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/release.test.js +10 -3
  44. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/requirements.helper.js +23 -1
  45. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/stateMachine.test.js +1 -1
  46. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/tools/chai-addons.js +8 -0
  47. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/types/index.test-d.ts +63 -0
  48. data/ext/libmongocrypt/libmongocrypt/bindings/python/CHANGELOG.rst +26 -0
  49. data/ext/libmongocrypt/libmongocrypt/bindings/python/README.rst +2 -2
  50. data/ext/libmongocrypt/libmongocrypt/bindings/python/build-manylinux-wheel.sh +1 -1
  51. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/binding.py +128 -238
  52. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/compat.py +0 -27
  53. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/explicit_encrypter.py +1 -1
  54. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/mongocrypt.py +5 -21
  55. data/ext/libmongocrypt/libmongocrypt/bindings/python/pymongocrypt/version.py +2 -2
  56. data/ext/libmongocrypt/libmongocrypt/bindings/python/release.sh +5 -5
  57. data/ext/libmongocrypt/libmongocrypt/bindings/python/setup.py +14 -9
  58. data/ext/libmongocrypt/libmongocrypt/bindings/python/test/__init__.py +1 -10
  59. data/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit-v2/int32/encrypted-payload.json +26 -0
  60. data/ext/libmongocrypt/libmongocrypt/bindings/python/test/test_mongocrypt.py +5 -5
  61. data/ext/libmongocrypt/libmongocrypt/bindings/python/test-requirements.txt +4 -12
  62. data/ext/libmongocrypt/libmongocrypt/cmake/ImportBSON.cmake +8 -6
  63. data/ext/libmongocrypt/libmongocrypt/cmake/IntelDFP.cmake +2 -1
  64. data/ext/libmongocrypt/libmongocrypt/cmake/Platform.cmake +50 -0
  65. data/ext/libmongocrypt/libmongocrypt/cmake/mongocrypt-config.cmake +21 -0
  66. data/ext/libmongocrypt/libmongocrypt/debian/gbp.conf +2 -2
  67. data/ext/libmongocrypt/libmongocrypt/etc/c6-vault.repo +39 -0
  68. data/ext/libmongocrypt/libmongocrypt/etc/fle2_aead_generate_tests.py +15 -24
  69. data/ext/libmongocrypt/libmongocrypt/etc/fle2_crypto.py +66 -54
  70. data/ext/libmongocrypt/libmongocrypt/etc/fle2_generate_tests.py +14 -23
  71. data/ext/libmongocrypt/libmongocrypt/etc/fle2v2_aead_generate_tests.py +32 -0
  72. data/ext/libmongocrypt/libmongocrypt/etc/format-all.sh +12 -0
  73. data/ext/libmongocrypt/libmongocrypt/etc/format.sh +16 -0
  74. data/ext/libmongocrypt/libmongocrypt/etc/install-package.sh +48 -0
  75. data/ext/libmongocrypt/libmongocrypt/etc/mongo-inteldfp-libmongocrypt-pr-625.patch +13 -0
  76. data/ext/libmongocrypt/libmongocrypt/src/crypto/cng.c +381 -436
  77. data/ext/libmongocrypt/libmongocrypt/src/crypto/commoncrypto.c +162 -227
  78. data/ext/libmongocrypt/libmongocrypt/src/crypto/libcrypto.c +180 -248
  79. data/ext/libmongocrypt/libmongocrypt/src/crypto/none.c +33 -55
  80. data/ext/libmongocrypt/libmongocrypt/src/csfle-markup.cpp +175 -205
  81. data/ext/libmongocrypt/libmongocrypt/src/mc-array-private.h +10 -21
  82. data/ext/libmongocrypt/libmongocrypt/src/mc-array.c +44 -56
  83. data/ext/libmongocrypt/libmongocrypt/src/mc-check-conversions-private.h +4 -8
  84. data/ext/libmongocrypt/libmongocrypt/src/mc-dec128.h +351 -463
  85. data/ext/libmongocrypt/libmongocrypt/src/mc-dec128.test.cpp +59 -66
  86. data/ext/libmongocrypt/libmongocrypt/src/mc-efc-private.h +7 -11
  87. data/ext/libmongocrypt/libmongocrypt/src/mc-efc.c +80 -92
  88. data/ext/libmongocrypt/libmongocrypt/src/mc-fle-blob-subtype-private.h +18 -10
  89. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder-private.h +59 -70
  90. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-encryption-placeholder.c +384 -439
  91. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private-v2.h +41 -0
  92. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-private.h +11 -18
  93. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload-v2.c +135 -0
  94. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-equality-payload.c +109 -126
  95. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private-v2.h +88 -0
  96. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-private.h +24 -27
  97. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload-v2.c +137 -0
  98. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-find-range-payload.c +106 -125
  99. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private-v2.h +117 -0
  100. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-private.h +28 -36
  101. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload-v2.c +294 -0
  102. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-insert-update-payload.c +237 -278
  103. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-private-v2.h +133 -0
  104. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-private.h +67 -56
  105. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev-v2.c +437 -0
  106. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-iev.c +476 -325
  107. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-uev-common-private.h +69 -0
  108. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-uev-common.c +182 -0
  109. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-uev-private.h +23 -31
  110. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-uev-v2-private.h +85 -0
  111. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-uev-v2.c +142 -0
  112. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-payload-uev.c +104 -231
  113. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-range-operator-private.h +8 -7
  114. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds-private.h +55 -56
  115. data/ext/libmongocrypt/libmongocrypt/src/mc-fle2-rfds.c +517 -580
  116. data/ext/libmongocrypt/libmongocrypt/src/mc-optional-private.h +36 -66
  117. data/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation-private.h +57 -76
  118. data/ext/libmongocrypt/libmongocrypt/src/mc-range-edge-generation.c +158 -189
  119. data/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding-private.h +36 -42
  120. data/ext/libmongocrypt/libmongocrypt/src/mc-range-encoding.c +515 -558
  121. data/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-generator.template.h +155 -191
  122. data/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover-private.h +43 -53
  123. data/ext/libmongocrypt/libmongocrypt/src/mc-range-mincover.c +170 -240
  124. data/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts-private.h +29 -34
  125. data/ext/libmongocrypt/libmongocrypt/src/mc-rangeopts.c +289 -338
  126. data/ext/libmongocrypt/libmongocrypt/src/mc-reader-private.h +36 -71
  127. data/ext/libmongocrypt/libmongocrypt/src/mc-reader.c +111 -164
  128. data/ext/libmongocrypt/libmongocrypt/src/mc-tokens-private.h +55 -49
  129. data/ext/libmongocrypt/libmongocrypt/src/mc-tokens.c +109 -125
  130. data/ext/libmongocrypt/libmongocrypt/src/mc-writer-private.h +66 -0
  131. data/ext/libmongocrypt/libmongocrypt/src/mc-writer.c +141 -0
  132. data/ext/libmongocrypt/libmongocrypt/src/mlib/check.hpp +37 -55
  133. data/ext/libmongocrypt/libmongocrypt/src/mlib/endian.h +11 -11
  134. data/ext/libmongocrypt/libmongocrypt/src/mlib/error.h +27 -32
  135. data/ext/libmongocrypt/libmongocrypt/src/mlib/int128.h +444 -499
  136. data/ext/libmongocrypt/libmongocrypt/src/mlib/int128.test.cpp +251 -334
  137. data/ext/libmongocrypt/libmongocrypt/src/mlib/macros.h +4 -5
  138. data/ext/libmongocrypt/libmongocrypt/src/mlib/path.h +196 -231
  139. data/ext/libmongocrypt/libmongocrypt/src/mlib/path.test.c +56 -79
  140. data/ext/libmongocrypt/libmongocrypt/src/mlib/str.h +411 -530
  141. data/ext/libmongocrypt/libmongocrypt/src/mlib/str.test.c +116 -131
  142. data/ext/libmongocrypt/libmongocrypt/src/mlib/thread.h +17 -26
  143. data/ext/libmongocrypt/libmongocrypt/src/mlib/user-check.h +2 -2
  144. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-binary-private.h +3 -6
  145. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-binary.c +31 -48
  146. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-buffer-private.h +55 -131
  147. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-buffer.c +444 -565
  148. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-collinfo-private.h +1 -2
  149. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-collinfo.c +28 -45
  150. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key-private.h +11 -17
  151. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-key.c +103 -132
  152. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth-private.h +8 -14
  153. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-oauth.c +78 -90
  154. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache-private.h +26 -45
  155. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-cache.c +220 -273
  156. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ciphertext-private.h +13 -25
  157. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ciphertext.c +147 -166
  158. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-compat.h +2 -2
  159. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-crypto-private.h +110 -204
  160. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-crypto.c +1137 -1565
  161. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-datakey.c +425 -472
  162. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-decrypt.c +817 -694
  163. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-encrypt.c +2394 -2697
  164. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-private.h +166 -186
  165. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx-rewrap-many-datakey.c +308 -351
  166. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-ctx.c +921 -1138
  167. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-dll-private.h +16 -24
  168. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-endian-private.h +44 -58
  169. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-endpoint-private.h +21 -25
  170. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-endpoint.c +167 -181
  171. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek-private.h +37 -43
  172. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kek.c +215 -253
  173. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker-private.h +73 -108
  174. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-broker.c +889 -1034
  175. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key-private.h +27 -44
  176. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-key.c +349 -402
  177. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx-private.h +92 -120
  178. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-kms-ctx.c +1397 -1612
  179. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-log-private.h +35 -67
  180. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-log.c +49 -83
  181. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking-private.h +30 -36
  182. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-marking.c +1821 -1470
  183. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-mutex-private.h +7 -12
  184. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts-private.h +80 -108
  185. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-opts.c +354 -424
  186. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-private.h +101 -117
  187. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-status-private.h +3 -8
  188. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-status.c +92 -119
  189. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-traverse-util-private.h +19 -29
  190. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-traverse-util.c +136 -176
  191. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-util-private.h +11 -21
  192. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt-util.c +96 -135
  193. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt.c +1092 -1320
  194. data/ext/libmongocrypt/libmongocrypt/src/mongocrypt.h +130 -295
  195. data/ext/libmongocrypt/libmongocrypt/src/os_posix/os_dll.c +66 -78
  196. data/ext/libmongocrypt/libmongocrypt/src/os_posix/os_mutex.c +20 -28
  197. data/ext/libmongocrypt/libmongocrypt/src/os_win/os_dll.c +60 -73
  198. data/ext/libmongocrypt/libmongocrypt/src/os_win/os_mutex.c +8 -16
  199. data/ext/libmongocrypt/libmongocrypt/test/crypt_shared-stub.cpp +57 -87
  200. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-delete/empty/encrypted-payload-v2.json +60 -0
  201. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-delete/success/encrypted-payload-v2.json +67 -0
  202. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-explain/with-csfle/encrypted-payload.json +2 -2
  203. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-explicit/find-indexed-contentionFactor1-v2.json +8 -0
  204. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-explicit/find-indexed-v2.json +8 -0
  205. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-explicit/insert-indexed-contentionFactor1-v2.json +8 -0
  206. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-explicit/insert-indexed-same-user-and-index-key-v2.json +8 -0
  207. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-explicit/insert-indexed-v2.json +8 -0
  208. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-equality-v2/cmd.json +6 -0
  209. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-equality-v2/encrypted-field-map.json +22 -0
  210. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-equality-v2/encrypted-payload.json +40 -0
  211. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-equality-v2/mongocryptd-reply.json +19 -0
  212. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/date-v2/cmd.json +10 -0
  213. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/date-v2/encrypted-field-map.json +27 -0
  214. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/date-v2/encrypted-payload.json +41 -0
  215. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/date-v2/mongocryptd-reply.json +49 -0
  216. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-precision-v2/cmd.json +6 -0
  217. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-precision-v2/encrypted-field-map.json +30 -0
  218. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-precision-v2/encrypted-payload.json +50 -0
  219. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-precision-v2/mongocryptd-reply.json +58 -0
  220. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-v2/cmd.json +6 -0
  221. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-v2/encrypted-field-map.json +27 -0
  222. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-v2/encrypted-payload.json +41 -0
  223. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/decimal128-v2/mongocryptd-reply.json +49 -0
  224. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-precision-v2/cmd.json +8 -0
  225. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-precision-v2/encrypted-field-map.json +30 -0
  226. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-precision-v2/encrypted-payload.json +44 -0
  227. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-precision-v2/mongocryptd-reply.json +52 -0
  228. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-v2/cmd.json +8 -0
  229. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-v2/encrypted-field-map.json +27 -0
  230. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-v2/encrypted-payload.json +41 -0
  231. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/double-v2/mongocryptd-reply.json +49 -0
  232. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int32-v2/cmd.json +8 -0
  233. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int32-v2/encrypted-field-map.json +27 -0
  234. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int32-v2/encrypted-payload.json +41 -0
  235. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int32-v2/mongocryptd-reply.json +49 -0
  236. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int64-v2/cmd.json +8 -0
  237. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int64-v2/encrypted-field-map.json +27 -0
  238. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int64-v2/encrypted-payload.json +41 -0
  239. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range/int64-v2/mongocryptd-reply.json +49 -0
  240. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/double/encrypted-payload-v2.json +26 -0
  241. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/double-precision/encrypted-payload-v2.json +26 -0
  242. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/int32/encrypted-payload-v2.json +26 -0
  243. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/int32-nominmax/encrypted-payload-v2.json +26 -0
  244. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/int32-openinterval/encrypted-payload-v2.json +16 -0
  245. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert/cmd.json +1 -1
  246. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/date/RNG_DATA.h +65 -65
  247. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/date-v2/cmd.json +13 -0
  248. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/date-v2/encrypted-field-map.json +27 -0
  249. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/date-v2/encrypted-payload.json +44 -0
  250. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/date-v2/mongocryptd-reply.json +52 -0
  251. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128/RNG_DATA.h +132 -132
  252. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-precision/RNG_DATA.h +71 -71
  253. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-precision-v2/cmd.json +9 -0
  254. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-precision-v2/encrypted-field-map.json +30 -0
  255. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-precision-v2/encrypted-payload.json +53 -0
  256. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-precision-v2/mongocryptd-reply.json +61 -0
  257. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-v2/cmd.json +9 -0
  258. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-v2/encrypted-field-map.json +27 -0
  259. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-v2/encrypted-payload.json +44 -0
  260. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/decimal128-v2/mongocryptd-reply.json +52 -0
  261. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double/RNG_DATA.h +68 -68
  262. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-precision/RNG_DATA.h +19 -19
  263. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-precision-v2/cmd.json +11 -0
  264. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-precision-v2/encrypted-field-map.json +30 -0
  265. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-precision-v2/encrypted-payload.json +47 -0
  266. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-precision-v2/mongocryptd-reply.json +55 -0
  267. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-v2/cmd.json +11 -0
  268. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-v2/encrypted-field-map.json +27 -0
  269. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-v2/encrypted-payload.json +44 -0
  270. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/double-v2/mongocryptd-reply.json +52 -0
  271. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int32/RNG_DATA.h +25 -25
  272. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int32-v2/cmd.json +11 -0
  273. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int32-v2/encrypted-field-map.json +27 -0
  274. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int32-v2/encrypted-payload.json +44 -0
  275. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int32-v2/mongocryptd-reply.json +52 -0
  276. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int64/RNG_DATA.h +65 -65
  277. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int64-v2/cmd.json +11 -0
  278. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int64-v2/encrypted-field-map.json +27 -0
  279. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int64-v2/encrypted-payload.json +44 -0
  280. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range/int64-v2/mongocryptd-reply.json +52 -0
  281. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/double/RNG_DATA.h +68 -68
  282. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/double/encrypted-payload-v2.json +8 -0
  283. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/double-precision/RNG_DATA.h +19 -19
  284. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/double-precision/encrypted-payload-v2.json +8 -0
  285. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/int32/RNG_DATA.h +25 -25
  286. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/int32/encrypted-payload-v2.json +8 -0
  287. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/int32-nominmax/encrypted-payload-v2.json +8 -0
  288. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/sparsity-2/RNG_DATA.h +15 -15
  289. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/sparsity-2/encrypted-payload-v2.json +8 -0
  290. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-unindexed-v2/cmd.json +9 -0
  291. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-unindexed-v2/encrypted-field-map.json +18 -0
  292. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-unindexed-v2/encrypted-payload.json +14 -0
  293. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-unindexed-v2/mongocryptd-reply.json +41 -0
  294. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-v2/cmd.json +9 -0
  295. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-v2/encrypted-field-map.json +22 -0
  296. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-v2/encrypted-payload.json +39 -0
  297. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-v2/mongocryptd-reply.json +49 -0
  298. data/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneRangeV2.json +10 -0
  299. data/ext/libmongocrypt/libmongocrypt/test/data/iev-v2/FLECrudTest-insertOneV2.json +10 -0
  300. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/README.md +17 -0
  301. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/aes-ctr.json +29 -0
  302. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/fle2-fixed.json +10 -0
  303. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/fle2-generated.json +38 -0
  304. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/fle2aead-decrypt.json +35 -0
  305. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/fle2aead-fixed.json +29 -0
  306. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/fle2aead-generated.json +122 -0
  307. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/fle2v2-aead-fixed.json +29 -0
  308. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/fle2v2-aead-generated.json +122 -0
  309. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/mcgrew.json +12 -0
  310. data/ext/libmongocrypt/libmongocrypt/test/data/roundtrip/nist.json +20 -0
  311. data/ext/libmongocrypt/libmongocrypt/test/data/tokens/README.md +27 -0
  312. data/ext/libmongocrypt/libmongocrypt/test/data/tokens/mc.json +21 -0
  313. data/ext/libmongocrypt/libmongocrypt/test/data/tokens/server.json +21 -0
  314. data/ext/libmongocrypt/libmongocrypt/test/example-no-bson.c +4 -4
  315. data/ext/libmongocrypt/libmongocrypt/test/example-state-machine.c +278 -323
  316. data/ext/libmongocrypt/libmongocrypt/test/fuzz_kms.c +8 -7
  317. data/ext/libmongocrypt/libmongocrypt/test/test-dll.cpp +6 -7
  318. data/ext/libmongocrypt/libmongocrypt/test/test-gcp-auth.c +221 -283
  319. data/ext/libmongocrypt/libmongocrypt/test/test-mc-efc.c +58 -73
  320. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-equality-payload-v2.c +78 -0
  321. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-find-range-payload-v2.c +89 -0
  322. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iev-v2.c +248 -0
  323. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iev.c +467 -414
  324. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup-v2.c +172 -0
  325. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-iup.c +141 -159
  326. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-uev-v2.c +338 -0
  327. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-payload-uev.c +238 -176
  328. data/ext/libmongocrypt/libmongocrypt/test/test-mc-fle2-rfds.c +373 -474
  329. data/ext/libmongocrypt/libmongocrypt/test/test-mc-range-edge-generation.c +346 -388
  330. data/ext/libmongocrypt/libmongocrypt/test/test-mc-range-encoding.c +708 -825
  331. data/ext/libmongocrypt/libmongocrypt/test/test-mc-range-mincover.c +417 -481
  332. data/ext/libmongocrypt/libmongocrypt/test/test-mc-rangeopts.c +110 -144
  333. data/ext/libmongocrypt/libmongocrypt/test/test-mc-reader.c +124 -207
  334. data/ext/libmongocrypt/libmongocrypt/test/test-mc-tokens.c +223 -213
  335. data/ext/libmongocrypt/libmongocrypt/test/test-mc-writer.c +176 -0
  336. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.c +634 -807
  337. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert-match-bson.h +1 -2
  338. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-assert.h +168 -189
  339. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-buffer.c +187 -211
  340. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache-oauth.c +34 -36
  341. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-cache.c +210 -233
  342. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ciphertext.c +185 -220
  343. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-compact.c +331 -445
  344. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-hooks.c +670 -814
  345. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.c +102 -135
  346. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto-std-hooks.h +54 -71
  347. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-crypto.c +394 -846
  348. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-csfle-lib.c +159 -183
  349. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-decrypt.c +867 -1045
  350. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-encrypt.c +4349 -4713
  351. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-rewrap-many-datakey.c +750 -964
  352. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-ctx-setopt.c +991 -1178
  353. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-datakey.c +342 -419
  354. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-dll.c +23 -30
  355. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-endpoint.c +98 -111
  356. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kek.c +49 -52
  357. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-key-broker.c +770 -920
  358. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-key-cache.c +354 -407
  359. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-key.c +197 -245
  360. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-ctx.c +286 -370
  361. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-kms-responses.c +147 -166
  362. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-local-kms.c +50 -61
  363. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-log.c +85 -100
  364. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-marking.c +656 -692
  365. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-status.c +46 -58
  366. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-traverse-util.c +377 -451
  367. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.c +48 -67
  368. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt-util.h +4 -10
  369. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.c +827 -918
  370. data/ext/libmongocrypt/libmongocrypt/test/test-mongocrypt.h +111 -172
  371. data/ext/libmongocrypt/libmongocrypt/test/util/csfle.c +508 -559
  372. data/ext/libmongocrypt/libmongocrypt/test/util/util.c +735 -881
  373. data/ext/libmongocrypt/libmongocrypt/test/util/util.h +33 -55
  374. data/lib/libmongocrypt_helper/version.rb +2 -2
  375. data/lib/libmongocrypt_helper.rb +2 -2
  376. data.tar.gz.sig +0 -0
  377. metadata +154 -26
  378. metadata.gz.sig +0 -0
  379. data/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit/int32/encrypted-payload.json +0 -26
  380. data/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/fle2-find-range-explicit/int32/key-document.json +0 -0
  381. data/ext/libmongocrypt/libmongocrypt/bindings/node/lib/credentialsProvider.js +0 -33
  382. data/ext/libmongocrypt/libmongocrypt/bindings/node/test/credentialsProvider.test.js +0 -163
  383. data/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/fle2-find-range-explicit/int32/encrypted-payload.json +0 -26
  384. data/ext/libmongocrypt/libmongocrypt/test/data/aes-ctr.cstructs +0 -359
  385. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-aead.cstructs +0 -109
  386. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/int32-nominmax/encrypted-payload.json +0 -26
  387. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/int32-nominmax/rangeopts.json +0 -5
  388. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-find-range-explicit/int32-nominmax/value-to-encrypt.json +0 -20
  389. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/int32-nominmax/RNG_DATA.h +0 -70
  390. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/int32-nominmax/encrypted-payload.json +0 -8
  391. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/int32-nominmax/rangeopts.json +0 -5
  392. data/ext/libmongocrypt/libmongocrypt/test/data/fle2-insert-range-explicit/int32-nominmax/value-to-encrypt.json +0 -5
  393. data/ext/libmongocrypt/libmongocrypt/test/data/fle2.cstructs +0 -33
  394. /data/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/{fle2-find-range-explicit → fle2-find-range-explicit-v2}/int32/key-filter.json +0 -0
  395. /data/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/{fle2-find-range-explicit → fle2-find-range-explicit-v2}/int32/rangeopts.json +0 -0
  396. /data/ext/libmongocrypt/libmongocrypt/bindings/java/mongocrypt/src/test/resources/{fle2-find-range-explicit → fle2-find-range-explicit-v2}/int32/value-to-encrypt.json +0 -0
  397. /data/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/{fle2-find-range-explicit → fle2-find-range-explicit-v2}/int32/rangeopts.json +0 -0
  398. /data/ext/libmongocrypt/libmongocrypt/bindings/python/test/data/{fle2-find-range-explicit → fle2-find-range-explicit-v2}/int32/value-to-encrypt.json +0 -0
@@ -36,430 +36,418 @@
36
36
  * encryption function
37
37
  */
38
38
 
39
- static bool
40
- _crypto_aes_256_ctr_encrypt_decrypt_via_ecb (
41
- void *ctx,
42
- mongocrypt_crypto_fn aes_256_ecb_encrypt,
43
- aes_256_args_t args,
44
- mongocrypt_status_t *status)
45
- {
46
- BSON_ASSERT (args.iv && args.iv->len);
47
- BSON_ASSERT (args.in);
48
- BSON_ASSERT (args.out);
49
-
50
- if (args.out->len < args.in->len) {
51
- CLIENT_ERR ("output buffer too small");
52
- return false;
53
- }
54
-
55
- _mongocrypt_buffer_t ctr, tmp;
56
- mongocrypt_binary_t key_bin, out_bin, in_bin, ctr_bin, tmp_bin;
57
- bool ret;
58
-
59
- _mongocrypt_buffer_to_binary (args.key, &key_bin);
60
- _mongocrypt_buffer_init (&ctr);
61
- _mongocrypt_buffer_copy_to (args.iv, &ctr);
62
- _mongocrypt_buffer_to_binary (&ctr, &ctr_bin);
63
- _mongocrypt_buffer_to_binary (args.out, &out_bin);
64
- _mongocrypt_buffer_to_binary (args.in, &in_bin);
65
- _mongocrypt_buffer_init_size (&tmp, args.iv->len);
66
- _mongocrypt_buffer_to_binary (&tmp, &tmp_bin);
67
-
68
- for (uint32_t ptr = 0; ptr < args.in->len;) {
69
- /* Encrypt value in CTR buffer */
70
- uint32_t bytes_written = 0;
71
- if (!aes_256_ecb_encrypt (
72
- ctx, &key_bin, NULL, &ctr_bin, &tmp_bin, &bytes_written, status)) {
73
- ret = false;
74
- goto cleanup;
75
- }
76
-
77
- if (bytes_written != tmp_bin.len) {
78
- CLIENT_ERR ("encryption hook returned unexpected length");
79
- ret = false;
80
- goto cleanup;
81
- }
82
-
83
- /* XOR resulting stream with original data */
84
- for (uint32_t i = 0; i < bytes_written && ptr < args.in->len;
85
- i++, ptr++) {
86
- out_bin.data[ptr] = in_bin.data[ptr] ^ tmp_bin.data[i];
87
- }
88
-
89
- /* Increment value in CTR buffer */
90
- uint32_t carry = 1;
91
- /* assert rather than return since this should never happen */
92
- BSON_ASSERT (ctr_bin.len == 0u || ctr_bin.len - 1u <= INT_MAX);
93
- for (int i = (int) ctr_bin.len - 1; i >= 0 && carry != 0; --i) {
94
- uint32_t bpp = carry + ctr_bin.data[i];
95
- carry = bpp >> 8;
96
- ctr_bin.data[i] = bpp & 0xFF;
97
- }
98
- }
99
-
100
- if (args.bytes_written) {
101
- *args.bytes_written = args.in->len;
102
- }
103
-
104
- ret = true;
39
+ static bool _crypto_aes_256_ctr_encrypt_decrypt_via_ecb(void *ctx,
40
+ mongocrypt_crypto_fn aes_256_ecb_encrypt,
41
+ aes_256_args_t args,
42
+ mongocrypt_status_t *status) {
43
+ BSON_ASSERT(args.iv && args.iv->len);
44
+ BSON_ASSERT(args.in);
45
+ BSON_ASSERT(args.out);
46
+
47
+ if (args.out->len < args.in->len) {
48
+ CLIENT_ERR("output buffer too small");
49
+ return false;
50
+ }
51
+
52
+ _mongocrypt_buffer_t ctr, tmp;
53
+ mongocrypt_binary_t key_bin, out_bin, in_bin, ctr_bin, tmp_bin;
54
+ bool ret;
55
+
56
+ _mongocrypt_buffer_to_binary(args.key, &key_bin);
57
+ _mongocrypt_buffer_init(&ctr);
58
+ _mongocrypt_buffer_copy_to(args.iv, &ctr);
59
+ _mongocrypt_buffer_to_binary(&ctr, &ctr_bin);
60
+ _mongocrypt_buffer_to_binary(args.out, &out_bin);
61
+ _mongocrypt_buffer_to_binary(args.in, &in_bin);
62
+ _mongocrypt_buffer_init_size(&tmp, args.iv->len);
63
+ _mongocrypt_buffer_to_binary(&tmp, &tmp_bin);
64
+
65
+ for (uint32_t ptr = 0; ptr < args.in->len;) {
66
+ /* Encrypt value in CTR buffer */
67
+ uint32_t bytes_written = 0;
68
+ if (!aes_256_ecb_encrypt(ctx, &key_bin, NULL, &ctr_bin, &tmp_bin, &bytes_written, status)) {
69
+ ret = false;
70
+ goto cleanup;
71
+ }
72
+
73
+ if (bytes_written != tmp_bin.len) {
74
+ CLIENT_ERR("encryption hook returned unexpected length");
75
+ ret = false;
76
+ goto cleanup;
77
+ }
78
+
79
+ /* XOR resulting stream with original data */
80
+ for (uint32_t i = 0; i < bytes_written && ptr < args.in->len; i++, ptr++) {
81
+ out_bin.data[ptr] = in_bin.data[ptr] ^ tmp_bin.data[i];
82
+ }
83
+
84
+ /* Increment value in CTR buffer */
85
+ uint32_t carry = 1;
86
+ /* assert rather than return since this should never happen */
87
+ BSON_ASSERT(ctr_bin.len == 0u || ctr_bin.len - 1u <= INT_MAX);
88
+ for (int i = (int)ctr_bin.len - 1; i >= 0 && carry != 0; --i) {
89
+ uint32_t bpp = carry + ctr_bin.data[i];
90
+ carry = bpp >> 8;
91
+ ctr_bin.data[i] = bpp & 0xFF;
92
+ }
93
+ }
94
+
95
+ if (args.bytes_written) {
96
+ *args.bytes_written = args.in->len;
97
+ }
98
+
99
+ ret = true;
105
100
 
106
101
  cleanup:
107
- _mongocrypt_buffer_cleanup (&ctr);
108
- _mongocrypt_buffer_cleanup (&tmp);
109
- return ret;
102
+ _mongocrypt_buffer_cleanup(&ctr);
103
+ _mongocrypt_buffer_cleanup(&tmp);
104
+ return ret;
110
105
  }
111
106
 
112
107
  /* Crypto primitives. These either call the native built in crypto primitives or
113
108
  * user supplied hooks. */
114
- static bool
115
- _crypto_aes_256_cbc_encrypt (_mongocrypt_crypto_t *crypto, aes_256_args_t args)
116
- {
117
- mongocrypt_status_t *status = args.status;
118
-
119
- BSON_ASSERT_PARAM (crypto);
120
-
121
- BSON_ASSERT (args.key);
122
- if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
123
- CLIENT_ERR ("invalid encryption key length");
124
- return false;
125
- }
126
-
127
- BSON_ASSERT (args.iv);
128
- if (args.iv->len != MONGOCRYPT_IV_LEN) {
129
- CLIENT_ERR ("invalid iv length");
130
- return false;
131
- }
132
-
133
- if (crypto->hooks_enabled) {
134
- mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
135
- bool ret;
136
-
137
- _mongocrypt_buffer_to_binary (args.key, &enc_key_bin);
138
- _mongocrypt_buffer_to_binary (args.iv, &iv_bin);
139
- _mongocrypt_buffer_to_binary (args.out, &out_bin);
140
- _mongocrypt_buffer_to_binary (args.in, &in_bin);
141
-
142
- ret = crypto->aes_256_cbc_encrypt (crypto->ctx,
143
- &enc_key_bin,
144
- &iv_bin,
145
- &in_bin,
146
- &out_bin,
147
- args.bytes_written,
148
- status);
149
- return ret;
150
- }
151
- return _native_crypto_aes_256_cbc_encrypt (args);
109
+ static bool _crypto_aes_256_cbc_encrypt(_mongocrypt_crypto_t *crypto, aes_256_args_t args) {
110
+ mongocrypt_status_t *status = args.status;
111
+
112
+ BSON_ASSERT_PARAM(crypto);
113
+
114
+ BSON_ASSERT(args.key);
115
+ if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
116
+ CLIENT_ERR("invalid encryption key length");
117
+ return false;
118
+ }
119
+
120
+ BSON_ASSERT(args.iv);
121
+ if (args.iv->len != MONGOCRYPT_IV_LEN) {
122
+ CLIENT_ERR("invalid iv length");
123
+ return false;
124
+ }
125
+
126
+ if (crypto->hooks_enabled) {
127
+ mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
128
+ bool ret;
129
+
130
+ _mongocrypt_buffer_to_binary(args.key, &enc_key_bin);
131
+ _mongocrypt_buffer_to_binary(args.iv, &iv_bin);
132
+ _mongocrypt_buffer_to_binary(args.out, &out_bin);
133
+ _mongocrypt_buffer_to_binary(args.in, &in_bin);
134
+
135
+ ret = crypto->aes_256_cbc_encrypt(crypto->ctx,
136
+ &enc_key_bin,
137
+ &iv_bin,
138
+ &in_bin,
139
+ &out_bin,
140
+ args.bytes_written,
141
+ status);
142
+ return ret;
143
+ }
144
+ return _native_crypto_aes_256_cbc_encrypt(args);
152
145
  }
153
146
 
154
- static bool
155
- _crypto_aes_256_ctr_encrypt (_mongocrypt_crypto_t *crypto, aes_256_args_t args)
156
- {
157
- mongocrypt_status_t *status = args.status;
158
-
159
- BSON_ASSERT_PARAM (crypto);
160
-
161
- BSON_ASSERT (args.key);
162
- if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
163
- CLIENT_ERR ("invalid encryption key length");
164
- return false;
165
- }
166
-
167
- BSON_ASSERT (args.iv);
168
- if (args.iv->len != MONGOCRYPT_IV_LEN) {
169
- CLIENT_ERR ("invalid iv length");
170
- return false;
171
- }
172
-
173
- if (crypto->aes_256_ctr_encrypt) {
174
- mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
175
- bool ret;
176
-
177
- _mongocrypt_buffer_to_binary (args.key, &enc_key_bin);
178
- _mongocrypt_buffer_to_binary (args.iv, &iv_bin);
179
- _mongocrypt_buffer_to_binary (args.out, &out_bin);
180
- _mongocrypt_buffer_to_binary (args.in, &in_bin);
181
-
182
- ret = crypto->aes_256_ctr_encrypt (crypto->ctx,
183
- &enc_key_bin,
184
- &iv_bin,
185
- &in_bin,
186
- &out_bin,
187
- args.bytes_written,
188
- status);
189
- return ret;
190
- }
191
-
192
- if (crypto->aes_256_ecb_encrypt) {
193
- return _crypto_aes_256_ctr_encrypt_decrypt_via_ecb (
194
- crypto->ctx, crypto->aes_256_ecb_encrypt, args, status);
195
- }
196
-
197
- return _native_crypto_aes_256_ctr_encrypt (args);
147
+ static bool _crypto_aes_256_ctr_encrypt(_mongocrypt_crypto_t *crypto, aes_256_args_t args) {
148
+ mongocrypt_status_t *status = args.status;
149
+
150
+ BSON_ASSERT_PARAM(crypto);
151
+
152
+ BSON_ASSERT(args.key);
153
+ if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
154
+ CLIENT_ERR("invalid encryption key length");
155
+ return false;
156
+ }
157
+
158
+ BSON_ASSERT(args.iv);
159
+ if (args.iv->len != MONGOCRYPT_IV_LEN) {
160
+ CLIENT_ERR("invalid iv length");
161
+ return false;
162
+ }
163
+
164
+ if (crypto->aes_256_ctr_encrypt) {
165
+ mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
166
+ bool ret;
167
+
168
+ _mongocrypt_buffer_to_binary(args.key, &enc_key_bin);
169
+ _mongocrypt_buffer_to_binary(args.iv, &iv_bin);
170
+ _mongocrypt_buffer_to_binary(args.out, &out_bin);
171
+ _mongocrypt_buffer_to_binary(args.in, &in_bin);
172
+
173
+ ret = crypto->aes_256_ctr_encrypt(crypto->ctx,
174
+ &enc_key_bin,
175
+ &iv_bin,
176
+ &in_bin,
177
+ &out_bin,
178
+ args.bytes_written,
179
+ status);
180
+ return ret;
181
+ }
182
+
183
+ if (crypto->aes_256_ecb_encrypt) {
184
+ return _crypto_aes_256_ctr_encrypt_decrypt_via_ecb(crypto->ctx, crypto->aes_256_ecb_encrypt, args, status);
185
+ }
186
+
187
+ return _native_crypto_aes_256_ctr_encrypt(args);
198
188
  }
199
189
 
200
- static bool
201
- _crypto_aes_256_cbc_decrypt (_mongocrypt_crypto_t *crypto, aes_256_args_t args)
202
- {
203
- mongocrypt_status_t *status = args.status;
204
-
205
- BSON_ASSERT_PARAM (crypto);
206
-
207
- BSON_ASSERT (args.key);
208
- if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
209
- CLIENT_ERR ("invalid encryption key length");
210
- return false;
211
- }
212
-
213
- if (crypto->hooks_enabled) {
214
- mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
215
- bool ret;
216
-
217
- _mongocrypt_buffer_to_binary (args.key, &enc_key_bin);
218
- _mongocrypt_buffer_to_binary (args.iv, &iv_bin);
219
- _mongocrypt_buffer_to_binary (args.out, &out_bin);
220
- _mongocrypt_buffer_to_binary (args.in, &in_bin);
221
-
222
- ret = crypto->aes_256_cbc_decrypt (crypto->ctx,
223
- &enc_key_bin,
224
- &iv_bin,
225
- &in_bin,
226
- &out_bin,
227
- args.bytes_written,
228
- status);
229
- return ret;
230
- }
231
- return _native_crypto_aes_256_cbc_decrypt (args);
190
+ static bool _crypto_aes_256_cbc_decrypt(_mongocrypt_crypto_t *crypto, aes_256_args_t args) {
191
+ mongocrypt_status_t *status = args.status;
192
+
193
+ BSON_ASSERT_PARAM(crypto);
194
+
195
+ BSON_ASSERT(args.key);
196
+ if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
197
+ CLIENT_ERR("invalid encryption key length");
198
+ return false;
199
+ }
200
+
201
+ if (crypto->hooks_enabled) {
202
+ mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
203
+ bool ret;
204
+
205
+ _mongocrypt_buffer_to_binary(args.key, &enc_key_bin);
206
+ _mongocrypt_buffer_to_binary(args.iv, &iv_bin);
207
+ _mongocrypt_buffer_to_binary(args.out, &out_bin);
208
+ _mongocrypt_buffer_to_binary(args.in, &in_bin);
209
+
210
+ ret = crypto->aes_256_cbc_decrypt(crypto->ctx,
211
+ &enc_key_bin,
212
+ &iv_bin,
213
+ &in_bin,
214
+ &out_bin,
215
+ args.bytes_written,
216
+ status);
217
+ return ret;
218
+ }
219
+ return _native_crypto_aes_256_cbc_decrypt(args);
232
220
  }
233
221
 
234
- static bool
235
- _crypto_aes_256_ctr_decrypt (_mongocrypt_crypto_t *crypto, aes_256_args_t args)
236
- {
237
- mongocrypt_status_t *status = args.status;
238
-
239
- BSON_ASSERT_PARAM (crypto);
240
-
241
- BSON_ASSERT (args.key);
242
- if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
243
- CLIENT_ERR ("invalid encryption key length");
244
- return false;
245
- }
246
-
247
- if (crypto->aes_256_ctr_decrypt) {
248
- mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
249
- bool ret;
250
-
251
- _mongocrypt_buffer_to_binary (args.key, &enc_key_bin);
252
- _mongocrypt_buffer_to_binary (args.iv, &iv_bin);
253
- _mongocrypt_buffer_to_binary (args.out, &out_bin);
254
- _mongocrypt_buffer_to_binary (args.in, &in_bin);
255
-
256
- ret = crypto->aes_256_ctr_decrypt (crypto->ctx,
257
- &enc_key_bin,
258
- &iv_bin,
259
- &in_bin,
260
- &out_bin,
261
- args.bytes_written,
262
- status);
263
- return ret;
264
- }
265
-
266
- if (crypto->aes_256_ecb_encrypt) {
267
- return _crypto_aes_256_ctr_encrypt_decrypt_via_ecb (
268
- crypto->ctx, crypto->aes_256_ecb_encrypt, args, status);
269
- }
270
-
271
- return _native_crypto_aes_256_ctr_decrypt (args);
222
+ static bool _crypto_aes_256_ctr_decrypt(_mongocrypt_crypto_t *crypto, aes_256_args_t args) {
223
+ mongocrypt_status_t *status = args.status;
224
+
225
+ BSON_ASSERT_PARAM(crypto);
226
+
227
+ BSON_ASSERT(args.key);
228
+ if (args.key->len != MONGOCRYPT_ENC_KEY_LEN) {
229
+ CLIENT_ERR("invalid encryption key length");
230
+ return false;
231
+ }
232
+
233
+ if (crypto->aes_256_ctr_decrypt) {
234
+ mongocrypt_binary_t enc_key_bin, iv_bin, out_bin, in_bin;
235
+ bool ret;
236
+
237
+ _mongocrypt_buffer_to_binary(args.key, &enc_key_bin);
238
+ _mongocrypt_buffer_to_binary(args.iv, &iv_bin);
239
+ _mongocrypt_buffer_to_binary(args.out, &out_bin);
240
+ _mongocrypt_buffer_to_binary(args.in, &in_bin);
241
+
242
+ ret = crypto->aes_256_ctr_decrypt(crypto->ctx,
243
+ &enc_key_bin,
244
+ &iv_bin,
245
+ &in_bin,
246
+ &out_bin,
247
+ args.bytes_written,
248
+ status);
249
+ return ret;
250
+ }
251
+
252
+ if (crypto->aes_256_ecb_encrypt) {
253
+ return _crypto_aes_256_ctr_encrypt_decrypt_via_ecb(crypto->ctx, crypto->aes_256_ecb_encrypt, args, status);
254
+ }
255
+
256
+ return _native_crypto_aes_256_ctr_decrypt(args);
272
257
  }
273
258
 
274
- static bool
275
- _crypto_hmac_sha_512 (_mongocrypt_crypto_t *crypto,
276
- const _mongocrypt_buffer_t *hmac_key,
277
- const _mongocrypt_buffer_t *in,
278
- _mongocrypt_buffer_t *out,
279
- mongocrypt_status_t *status)
280
- {
281
- BSON_ASSERT_PARAM (crypto);
282
- BSON_ASSERT_PARAM (hmac_key);
283
- BSON_ASSERT_PARAM (in);
284
- BSON_ASSERT_PARAM (out);
285
-
286
- if (hmac_key->len != MONGOCRYPT_MAC_KEY_LEN) {
287
- CLIENT_ERR ("invalid hmac key length");
288
- return false;
289
- }
290
-
291
- if (out->len != MONGOCRYPT_HMAC_SHA512_LEN) {
292
- CLIENT_ERR ("out does not contain %d bytes", MONGOCRYPT_HMAC_SHA512_LEN);
293
- return false;
294
- }
295
-
296
- if (crypto->hooks_enabled) {
297
- mongocrypt_binary_t hmac_key_bin, out_bin, in_bin;
298
- bool ret;
299
-
300
- _mongocrypt_buffer_to_binary (hmac_key, &hmac_key_bin);
301
- _mongocrypt_buffer_to_binary (out, &out_bin);
302
- _mongocrypt_buffer_to_binary (in, &in_bin);
303
-
304
- ret = crypto->hmac_sha_512 (
305
- crypto->ctx, &hmac_key_bin, &in_bin, &out_bin, status);
306
- return ret;
307
- }
308
- return _native_crypto_hmac_sha_512 (hmac_key, in, out, status);
259
+ static bool _crypto_hmac_sha_512(_mongocrypt_crypto_t *crypto,
260
+ const _mongocrypt_buffer_t *hmac_key,
261
+ const _mongocrypt_buffer_t *in,
262
+ _mongocrypt_buffer_t *out,
263
+ mongocrypt_status_t *status) {
264
+ BSON_ASSERT_PARAM(crypto);
265
+ BSON_ASSERT_PARAM(hmac_key);
266
+ BSON_ASSERT_PARAM(in);
267
+ BSON_ASSERT_PARAM(out);
268
+
269
+ if (hmac_key->len != MONGOCRYPT_MAC_KEY_LEN) {
270
+ CLIENT_ERR("invalid hmac key length");
271
+ return false;
272
+ }
273
+
274
+ if (out->len != MONGOCRYPT_HMAC_SHA512_LEN) {
275
+ CLIENT_ERR("out does not contain %d bytes", MONGOCRYPT_HMAC_SHA512_LEN);
276
+ return false;
277
+ }
278
+
279
+ if (crypto->hooks_enabled) {
280
+ mongocrypt_binary_t hmac_key_bin, out_bin, in_bin;
281
+ bool ret;
282
+
283
+ _mongocrypt_buffer_to_binary(hmac_key, &hmac_key_bin);
284
+ _mongocrypt_buffer_to_binary(out, &out_bin);
285
+ _mongocrypt_buffer_to_binary(in, &in_bin);
286
+
287
+ ret = crypto->hmac_sha_512(crypto->ctx, &hmac_key_bin, &in_bin, &out_bin, status);
288
+ return ret;
289
+ }
290
+ return _native_crypto_hmac_sha_512(hmac_key, in, out, status);
309
291
  }
310
292
 
293
+ bool _mongocrypt_hmac_sha_256(_mongocrypt_crypto_t *crypto,
294
+ const _mongocrypt_buffer_t *key,
295
+ const _mongocrypt_buffer_t *in,
296
+ _mongocrypt_buffer_t *out,
297
+ mongocrypt_status_t *status) {
298
+ BSON_ASSERT_PARAM(crypto);
299
+ BSON_ASSERT_PARAM(key);
300
+ BSON_ASSERT_PARAM(in);
301
+ BSON_ASSERT_PARAM(out);
302
+
303
+ if (key->len != MONGOCRYPT_MAC_KEY_LEN) {
304
+ CLIENT_ERR("invalid hmac_sha_256 key length. Got %" PRIu32 ", expected: %" PRIu32,
305
+ key->len,
306
+ MONGOCRYPT_MAC_KEY_LEN);
307
+ return false;
308
+ }
309
+
310
+ if (crypto->hooks_enabled) {
311
+ mongocrypt_binary_t key_bin, out_bin, in_bin;
312
+ _mongocrypt_buffer_to_binary(key, &key_bin);
313
+ _mongocrypt_buffer_to_binary(out, &out_bin);
314
+ _mongocrypt_buffer_to_binary(in, &in_bin);
315
+
316
+ return crypto->hmac_sha_256(crypto->ctx, &key_bin, &in_bin, &out_bin, status);
317
+ }
318
+ return _native_crypto_hmac_sha_256(key, in, out, status);
319
+ }
311
320
 
312
321
  static bool
313
- _crypto_random (_mongocrypt_crypto_t *crypto,
314
- _mongocrypt_buffer_t *out,
315
- uint32_t count,
316
- mongocrypt_status_t *status)
317
- {
318
- BSON_ASSERT_PARAM (crypto);
319
- BSON_ASSERT_PARAM (out);
320
-
321
- if (out->len != count) {
322
- CLIENT_ERR ("out does not contain %u bytes", count);
323
- return false;
324
- }
325
-
326
- if (crypto->hooks_enabled) {
327
- mongocrypt_binary_t out_bin;
328
-
329
- _mongocrypt_buffer_to_binary (out, &out_bin);
330
- return crypto->random (crypto->ctx, &out_bin, count, status);
331
- }
332
- return _native_crypto_random (out, count, status);
322
+ _crypto_random(_mongocrypt_crypto_t *crypto, _mongocrypt_buffer_t *out, uint32_t count, mongocrypt_status_t *status) {
323
+ BSON_ASSERT_PARAM(crypto);
324
+ BSON_ASSERT_PARAM(out);
325
+
326
+ if (out->len != count) {
327
+ CLIENT_ERR("out does not contain %u bytes", count);
328
+ return false;
329
+ }
330
+
331
+ if (crypto->hooks_enabled) {
332
+ mongocrypt_binary_t out_bin;
333
+
334
+ _mongocrypt_buffer_to_binary(out, &out_bin);
335
+ return crypto->random(crypto->ctx, &out_bin, count, status);
336
+ }
337
+ return _native_crypto_random(out, count, status);
333
338
  }
334
339
 
335
-
336
340
  /*
337
341
  * Secure memcmp copied from the C driver.
338
342
  */
339
- int
340
- _mongocrypt_memequal (const void *const b1, const void *const b2, size_t len)
341
- {
342
- const unsigned char *p1 = b1, *p2 = b2;
343
- int ret = 0;
343
+ int _mongocrypt_memequal(const void *const b1, const void *const b2, size_t len) {
344
+ const unsigned char *p1 = b1, *p2 = b2;
345
+ int ret = 0;
344
346
 
345
- BSON_ASSERT_PARAM (b1);
346
- BSON_ASSERT_PARAM (b2);
347
+ BSON_ASSERT_PARAM(b1);
348
+ BSON_ASSERT_PARAM(b2);
347
349
 
348
- for (; len > 0; len--) {
349
- ret |= *p1++ ^ *p2++;
350
- }
350
+ for (; len > 0; len--) {
351
+ ret |= *p1++ ^ *p2++;
352
+ }
351
353
 
352
- return ret;
354
+ return ret;
353
355
  }
354
356
 
357
+ typedef enum {
358
+ MODE_CBC,
359
+ MODE_CTR,
360
+ } _mongocrypt_encryption_mode_t;
361
+
362
+ typedef enum {
363
+ HMAC_NONE,
364
+ HMAC_SHA_512_256, // sha512 truncated to 256 bits
365
+ HMAC_SHA_256,
366
+ } _mongocrypt_hmac_type_t;
367
+
368
+ typedef enum {
369
+ KEY_FORMAT_FLE1, // 32 octets MAC key, 32 DATA key, 32 IV key (ignored)
370
+ KEY_FORMAT_FLE2, // 32 octets DATA key
371
+ KEY_FORMAT_FLE2AEAD, // 32 octets DATA key, 32 MAC key, 32 IV key (ignored)
372
+ KEY_FORMAT_FLE2v2AEAD, // 32 octets DATA key, 32 MAC key, 32 IV key (ignored)
373
+ } _mongocrypt_key_format_t;
374
+
375
+ typedef enum {
376
+ MAC_FORMAT_FLE1, // HMAC(AAD || IV || S || LEN(AAD) as uint64be)
377
+ MAC_FORMAT_FLE2, // NONE
378
+ MAC_FORMAT_FLE2AEAD, // HMAC(AAD || IV || S)
379
+ MAC_FORMAT_FLE2v2AEAD, // HMAC(AAD || IV || S)
380
+ } _mongocrypt_mac_format_t;
381
+
355
382
  /* ----------------------------------------------------------------------------
356
383
  *
357
- * _mongocrypt_calculate_ciphertext_len --
384
+ * _mongocrypt_calculate_ciphertext_len
358
385
  *
359
- * For a given plaintext length, return the length of the ciphertext.
360
- * This includes IV and HMAC.
386
+ * Calculate the space needed for a ciphertext payload of a given size
387
+ * and using fixed iv/hmac lengths.
361
388
  *
362
- * To compute that I'm following section 2.3 in [MCGREW]:
363
- * L = 16 * ( floor(M / 16) + 2)
364
- * This formula includes space for the IV, but not the sha512 HMAC.
365
- * Add 32 for the sha512 HMAC.
389
+ * MODE_CBC: Assumes the ciphertext will be padded according to PKCS#7
390
+ * which rounds up to the next block size, adding up to a complete block
391
+ * for block aligned input payloads.
366
392
  *
367
- * Parameters:
368
- * @plaintext_len then length of the plaintext.
369
- * @status set on error.
393
+ * MODE_CTR: Assumes no additional padding since CTR is a streaming cipher.
370
394
  *
371
- * Returns:
372
- * The calculated length of the ciphertext.
395
+ * Assumes all algorithms use identical IV length and blocksizes.
373
396
  *
374
397
  * ----------------------------------------------------------------------------
375
398
  */
376
- uint32_t
377
- _mongocrypt_calculate_ciphertext_len (uint32_t plaintext_len,
378
- mongocrypt_status_t *status)
379
- {
380
- if ((plaintext_len / 16u) >
381
- ((UINT32_MAX - (uint32_t) MONGOCRYPT_HMAC_LEN) / 16u) - 2u) {
382
- CLIENT_ERR ("plaintext too long");
383
- return 0;
384
- }
385
- return 16 * ((plaintext_len / 16) + 2) + MONGOCRYPT_HMAC_LEN;
386
- }
387
-
388
- uint32_t
389
- _mongocrypt_fle2aead_calculate_ciphertext_len (uint32_t plaintext_len,
390
- mongocrypt_status_t *status)
391
- {
392
- if (plaintext_len > UINT32_MAX - MONGOCRYPT_IV_LEN - MONGOCRYPT_HMAC_LEN) {
393
- CLIENT_ERR ("plaintext too long");
394
- return 0;
395
- }
396
- /* FLE2 AEAD uses CTR mode. CTR mode does not pad. */
397
- return MONGOCRYPT_IV_LEN + plaintext_len + MONGOCRYPT_HMAC_LEN;
399
+ static uint32_t _mongocrypt_calculate_ciphertext_len(uint32_t inlen,
400
+ _mongocrypt_encryption_mode_t mode,
401
+ _mongocrypt_hmac_type_t hmac,
402
+ mongocrypt_status_t *status) {
403
+ const uint32_t hmaclen = (hmac == HMAC_NONE) ? 0 : MONGOCRYPT_HMAC_LEN;
404
+ const uint32_t maxinlen = UINT32_MAX - (MONGOCRYPT_IV_LEN + MONGOCRYPT_BLOCK_SIZE + hmaclen);
405
+ uint32_t fill;
406
+ if (inlen > maxinlen) {
407
+ CLIENT_ERR("plaintext too long");
408
+ return 0;
409
+ }
410
+
411
+ if (mode == MODE_CBC) {
412
+ fill = MONGOCRYPT_BLOCK_SIZE - (inlen % MONGOCRYPT_BLOCK_SIZE);
413
+ } else {
414
+ BSON_ASSERT(mode == MODE_CTR);
415
+ fill = 0;
416
+ }
417
+
418
+ return MONGOCRYPT_IV_LEN + inlen + fill + hmaclen;
398
419
  }
399
420
 
400
- uint32_t
401
- _mongocrypt_fle2_calculate_ciphertext_len (uint32_t plaintext_len,
402
- mongocrypt_status_t *status)
403
- {
404
- if (plaintext_len > UINT32_MAX - MONGOCRYPT_IV_LEN) {
405
- CLIENT_ERR ("plaintext too long");
406
- return 0;
407
- }
408
- /* FLE2 AEAD uses CTR mode. CTR mode does not pad. */
409
- return MONGOCRYPT_IV_LEN + plaintext_len;
410
- }
411
-
412
-
413
421
  /* ----------------------------------------------------------------------------
414
422
  *
415
- * _mongocrypt_calculate_plaintext_len --
423
+ * _mongocrypt_calculate_plaintext_len
416
424
  *
417
- * For a given ciphertext length, return the length of the plaintext.
418
- * This excludes the IV and HMAC, but includes the padding.
425
+ * Calculate the space needed for a plaintext payload of a given size
426
+ * and using fixed iv/hmac lengths.
419
427
  *
420
- * Parameters:
421
- * @ciphertext_len then length of the ciphertext.
422
- * @status set on error.
428
+ * MODE_CBC: In practice, plaintext will be between 1 and {blocksize} bytes
429
+ * shorter
430
+ * than the input ciphertext, but it's easier and safer to assume the
431
+ * full ciphertext length and waste a few bytes.
423
432
  *
424
- * Returns:
425
- * The calculated length of the plaintext.
433
+ * MODE_CTR: Assumes no additional padding since CTR is a streaming cipher.
434
+ *
435
+ * Assumes all algorithms use identical IV length and blocksizes.
426
436
  *
427
437
  * ----------------------------------------------------------------------------
428
438
  */
429
- uint32_t
430
- _mongocrypt_calculate_plaintext_len (uint32_t ciphertext_len,
431
- mongocrypt_status_t *status)
432
- {
433
- if (ciphertext_len <
434
- MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN + MONGOCRYPT_BLOCK_SIZE) {
435
- CLIENT_ERR ("ciphertext too short");
436
- return 0;
437
- }
438
- return ciphertext_len - (MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN);
439
- }
440
-
441
- uint32_t
442
- _mongocrypt_fle2aead_calculate_plaintext_len (uint32_t ciphertext_len,
443
- mongocrypt_status_t *status)
444
- {
445
- /* FLE2 AEAD uses CTR mode. CTR mode does not pad. */
446
- if (ciphertext_len < MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN) {
447
- CLIENT_ERR ("ciphertext too short");
448
- return 0;
449
- }
450
- return ciphertext_len - MONGOCRYPT_IV_LEN - MONGOCRYPT_HMAC_LEN;
451
- }
452
-
453
- uint32_t
454
- _mongocrypt_fle2_calculate_plaintext_len (uint32_t ciphertext_len,
455
- mongocrypt_status_t *status)
456
- {
457
- /* FLE2 AEAD uses CTR mode. CTR mode does not pad. */
458
- if (ciphertext_len < MONGOCRYPT_IV_LEN) {
459
- CLIENT_ERR ("ciphertext too short");
460
- return 0;
461
- }
462
- return ciphertext_len - MONGOCRYPT_IV_LEN;
439
+ static uint32_t _mongocrypt_calculate_plaintext_len(uint32_t inlen,
440
+ _mongocrypt_encryption_mode_t mode,
441
+ _mongocrypt_hmac_type_t hmac,
442
+ mongocrypt_status_t *status) {
443
+ const uint32_t hmaclen = (hmac == HMAC_NONE) ? 0 : MONGOCRYPT_HMAC_LEN;
444
+ const uint32_t mincipher = (mode == MODE_CTR) ? 0 : MONGOCRYPT_BLOCK_SIZE;
445
+ if (inlen < (MONGOCRYPT_IV_LEN + mincipher + hmaclen)) {
446
+ CLIENT_ERR("input ciphertext too small. Must be at least %" PRIu32 " bytes",
447
+ MONGOCRYPT_IV_LEN + mincipher + hmaclen);
448
+ return 0;
449
+ }
450
+ return inlen - (MONGOCRYPT_IV_LEN + hmaclen);
463
451
  }
464
452
 
465
453
  /* ----------------------------------------------------------------------------
@@ -487,129 +475,120 @@ _mongocrypt_fle2_calculate_plaintext_len (uint32_t ciphertext_len,
487
475
  * Postconditions:
488
476
  * 1. bytes_written is set to the length of the written ciphertext. This
489
477
  * is the same as
490
- * _mongocrypt_calculate_ciphertext_len (plaintext->len, status).
478
+ * _mongocrypt_calculate_ciphertext_len (plaintext->len, mode, hmac, status).
491
479
  *
492
480
  * ----------------------------------------------------------------------------
493
481
  */
494
- static bool
495
- _encrypt_step (_mongocrypt_crypto_t *crypto,
496
- const _mongocrypt_buffer_t *iv,
497
- const _mongocrypt_buffer_t *enc_key,
498
- const _mongocrypt_buffer_t *plaintext,
499
- _mongocrypt_buffer_t *ciphertext,
500
- uint32_t *bytes_written,
501
- mongocrypt_status_t *status)
502
- {
503
- uint32_t unaligned;
504
- uint32_t padding_byte;
505
- _mongocrypt_buffer_t intermediates[2];
506
- _mongocrypt_buffer_t to_encrypt;
507
- uint8_t final_block_storage[MONGOCRYPT_BLOCK_SIZE];
508
- bool ret = false;
509
-
510
- BSON_ASSERT_PARAM (crypto);
511
- BSON_ASSERT_PARAM (iv);
512
- BSON_ASSERT_PARAM (enc_key);
513
- BSON_ASSERT_PARAM (plaintext);
514
- BSON_ASSERT_PARAM (ciphertext);
515
-
516
- _mongocrypt_buffer_init (&to_encrypt);
517
-
518
- BSON_ASSERT_PARAM (bytes_written);
519
- *bytes_written = 0;
520
-
521
- if (MONGOCRYPT_IV_LEN != iv->len) {
522
- CLIENT_ERR ("IV should have length %d, but has length %d",
523
- MONGOCRYPT_IV_LEN,
524
- iv->len);
525
- goto done;
526
- }
527
-
528
- if (MONGOCRYPT_ENC_KEY_LEN != enc_key->len) {
529
- CLIENT_ERR ("Encryption key should have length %d, but has length %d",
530
- MONGOCRYPT_ENC_KEY_LEN,
531
- enc_key->len);
532
- goto done;
533
- }
534
-
535
- /* calculate how many extra bytes there are after a block boundary */
536
- unaligned = plaintext->len % MONGOCRYPT_BLOCK_SIZE;
537
-
538
- /* Some crypto providers disallow variable length inputs, and require
539
- * the input to be a multiple of the block size. So add everything up
540
- * to but excluding the last block if not block aligned, then add
541
- * the last block with padding. */
542
- _mongocrypt_buffer_init (&intermediates[0]);
543
- _mongocrypt_buffer_init (&intermediates[1]);
544
- intermediates[0].data = (uint8_t *) plaintext->data;
545
- /* don't check plaintext->len, as the above modulo operation guarantees
546
- * that unaligned will be smaller */
547
- intermediates[0].len = plaintext->len - unaligned;
548
- intermediates[1].data = final_block_storage;
549
- intermediates[1].len = sizeof (final_block_storage);
550
-
551
- /* [MCGREW]: "Prior to CBC encryption, the plaintext P is padded by appending
552
- * a padding string PS to that data, to ensure that len(P || PS) is a
553
- * multiple of 128". This is also known as PKCS #7 padding. */
554
- if (unaligned) {
555
- /* Copy the unaligned bytes. */
556
- memcpy (intermediates[1].data,
557
- plaintext->data + (plaintext->len - unaligned),
558
- unaligned);
559
- /* Fill the rest with the padding byte. */
560
- BSON_ASSERT (MONGOCRYPT_BLOCK_SIZE >= unaligned);
561
- padding_byte = MONGOCRYPT_BLOCK_SIZE - unaligned;
562
- /* it is certain that padding_byte is in range for a cast to int */
563
- memset (
564
- intermediates[1].data + unaligned, (int) padding_byte, padding_byte);
565
- } else {
566
- /* Fill the rest with the padding byte. */
567
- padding_byte = MONGOCRYPT_BLOCK_SIZE;
568
- memset (intermediates[1].data, (int) padding_byte, padding_byte);
569
- }
570
-
571
- if (!_mongocrypt_buffer_concat (&to_encrypt, intermediates, 2)) {
572
- CLIENT_ERR ("failed to allocate buffer");
573
- goto done;
574
- }
575
-
576
- if (!_crypto_aes_256_cbc_encrypt (
577
- crypto,
578
- (aes_256_args_t){.key = enc_key,
579
- .iv = iv,
580
- .in = &to_encrypt,
581
- .out = ciphertext,
582
- .bytes_written = bytes_written,
583
- .status = status})) {
584
- goto done;
585
- }
586
-
587
-
588
- if (*bytes_written % MONGOCRYPT_BLOCK_SIZE != 0) {
589
- CLIENT_ERR ("encryption failure, wrote %d bytes, not a multiple of %d",
590
- *bytes_written,
591
- MONGOCRYPT_BLOCK_SIZE);
592
- goto done;
593
- }
594
-
595
- ret = true;
596
- done:
597
- _mongocrypt_buffer_cleanup (&to_encrypt);
598
- return ret;
482
+ static bool _encrypt_step(_mongocrypt_crypto_t *crypto,
483
+ _mongocrypt_encryption_mode_t mode,
484
+ const _mongocrypt_buffer_t *iv,
485
+ const _mongocrypt_buffer_t *enc_key,
486
+ const _mongocrypt_buffer_t *plaintext,
487
+ _mongocrypt_buffer_t *ciphertext,
488
+ uint32_t *bytes_written,
489
+ mongocrypt_status_t *status) {
490
+ BSON_ASSERT_PARAM(crypto);
491
+ BSON_ASSERT_PARAM(iv);
492
+ BSON_ASSERT_PARAM(enc_key);
493
+ BSON_ASSERT_PARAM(plaintext);
494
+ BSON_ASSERT_PARAM(ciphertext);
495
+
496
+ BSON_ASSERT_PARAM(bytes_written);
497
+ *bytes_written = 0;
498
+
499
+ if (MONGOCRYPT_IV_LEN != iv->len) {
500
+ CLIENT_ERR("IV should have length %d, but has length %d", MONGOCRYPT_IV_LEN, iv->len);
501
+ return false;
502
+ }
503
+
504
+ if (MONGOCRYPT_ENC_KEY_LEN != enc_key->len) {
505
+ CLIENT_ERR("Encryption key should have length %d, but has length %d", MONGOCRYPT_ENC_KEY_LEN, enc_key->len);
506
+ return false;
507
+ }
508
+
509
+ if (mode == MODE_CTR) {
510
+ // Streaming cipher, no padding required.
511
+ return _crypto_aes_256_ctr_encrypt(crypto,
512
+ (aes_256_args_t){.key = enc_key,
513
+ .iv = iv,
514
+ .in = plaintext,
515
+ .out = ciphertext,
516
+ .bytes_written = bytes_written,
517
+ .status = status});
518
+ }
519
+
520
+ BSON_ASSERT(mode == MODE_CBC);
521
+
522
+ /* calculate how many extra bytes there are after a block boundary */
523
+ const uint32_t unaligned = plaintext->len % MONGOCRYPT_BLOCK_SIZE;
524
+ uint32_t padding_byte = MONGOCRYPT_BLOCK_SIZE - unaligned;
525
+ _mongocrypt_buffer_t intermediates[2], to_encrypt;
526
+ uint8_t final_block_storage[MONGOCRYPT_BLOCK_SIZE];
527
+ bool ret;
528
+
529
+ BSON_ASSERT(MONGOCRYPT_BLOCK_SIZE >= unaligned);
530
+
531
+ /* Some crypto providers disallow variable length inputs, and require
532
+ * the input to be a multiple of the block size. So add everything up
533
+ * to but excluding the last block if not block aligned, then add
534
+ * the last block with padding. */
535
+ _mongocrypt_buffer_init(&intermediates[0]);
536
+ _mongocrypt_buffer_init(&intermediates[1]);
537
+ intermediates[0].data = (uint8_t *)plaintext->data;
538
+ /* don't check plaintext->len, as the above modulo operation guarantees
539
+ * that unaligned will be smaller */
540
+ intermediates[0].len = plaintext->len - unaligned;
541
+ intermediates[1].data = final_block_storage;
542
+ intermediates[1].len = sizeof(final_block_storage);
543
+
544
+ /* [MCGREW]: "Prior to CBC encryption, the plaintext P is padded by appending
545
+ * a padding string PS to that data, to ensure that len(P || PS) is a
546
+ * multiple of 128". This is also known as PKCS #7 padding. */
547
+ if (unaligned) {
548
+ /* Copy the unaligned bytes. */
549
+ memcpy(intermediates[1].data, plaintext->data + (plaintext->len - unaligned), unaligned);
550
+ }
551
+ /* Fill out block remained or whole block with padding_byte */
552
+ memset(intermediates[1].data + unaligned, (int)padding_byte, padding_byte);
553
+
554
+ _mongocrypt_buffer_init(&to_encrypt);
555
+ if (!_mongocrypt_buffer_concat(&to_encrypt, intermediates, 2)) {
556
+ CLIENT_ERR("failed to allocate buffer");
557
+ _mongocrypt_buffer_cleanup(&to_encrypt);
558
+ return false;
559
+ }
560
+
561
+ ret = _crypto_aes_256_cbc_encrypt(crypto,
562
+ (aes_256_args_t){.key = enc_key,
563
+ .iv = iv,
564
+ .in = &to_encrypt,
565
+ .out = ciphertext,
566
+ .bytes_written = bytes_written,
567
+ .status = status});
568
+ _mongocrypt_buffer_cleanup(&to_encrypt);
569
+ if (!ret) {
570
+ return false;
571
+ }
572
+
573
+ if (*bytes_written % MONGOCRYPT_BLOCK_SIZE != 0) {
574
+ CLIENT_ERR("encryption failure, wrote %d bytes, not a multiple of %d", *bytes_written, MONGOCRYPT_BLOCK_SIZE);
575
+ return false;
576
+ }
577
+
578
+ return true;
599
579
  }
600
580
 
601
-
602
581
  /* ----------------------------------------------------------------------------
603
582
  *
604
- * _hmac_sha512 --
583
+ * _hmac_step --
605
584
  *
606
- * Compute the SHA512 HMAC with a secret key.
585
+ * Compute the selected HMAC with a secret key.
607
586
  *
608
587
  * Parameters:
609
- * @mac_key a 32 byte key.
610
- * @associated_data associated data to add into the HMAC. This may be
588
+ * @Km a 32 byte key.
589
+ * @AAD associated data to add into the HMAC. This may be
611
590
  * an empty buffer.
612
- * @ciphertext the ciphertext to add into the HMAC.
591
+ * @iv_and_ciphertext the IV and S components to add into the HMAC.
613
592
  * @out a location for the resulting HMAC tag.
614
593
  * @status set on error.
615
594
  *
@@ -624,84 +603,99 @@ done:
624
603
  *
625
604
  * ----------------------------------------------------------------------------
626
605
  */
627
- static bool
628
- _hmac_step (_mongocrypt_crypto_t *crypto,
629
- const _mongocrypt_buffer_t *mac_key,
630
- const _mongocrypt_buffer_t *associated_data,
631
- const _mongocrypt_buffer_t *ciphertext,
632
- _mongocrypt_buffer_t *out,
633
- mongocrypt_status_t *status)
634
- {
635
- _mongocrypt_buffer_t intermediates[3];
636
- _mongocrypt_buffer_t to_hmac;
637
- uint64_t associated_data_len_be;
638
- uint8_t tag_storage[64];
639
- _mongocrypt_buffer_t tag;
640
- bool ret = false;
641
-
642
- BSON_ASSERT_PARAM (crypto);
643
- BSON_ASSERT_PARAM (mac_key);
644
- BSON_ASSERT_PARAM (associated_data);
645
- BSON_ASSERT_PARAM (ciphertext);
646
- BSON_ASSERT_PARAM (out);
647
-
648
- _mongocrypt_buffer_init (&to_hmac);
649
-
650
- if (MONGOCRYPT_MAC_KEY_LEN != mac_key->len) {
651
- CLIENT_ERR ("HMAC key wrong length: %d", mac_key->len);
652
- goto done;
653
- }
654
-
655
- if (out->len != MONGOCRYPT_HMAC_LEN) {
656
- CLIENT_ERR ("out wrong length: %d", out->len);
657
- goto done;
658
- }
659
-
660
- /* [MCGREW]:
661
- * """
662
- * 4. The octet string AL is equal to the number of bits in A expressed as a
663
- * 64-bit unsigned integer in network byte order.
664
- * 5. A message authentication tag T is computed by applying HMAC [RFC2104]
665
- * to the following data, in order:
666
- * the associated data A,
667
- * the ciphertext S computed in the previous step, and
668
- * the octet string AL defined above.
669
- * """
670
- */
671
-
672
- /* Add associated data. */
673
- _mongocrypt_buffer_init (&intermediates[0]);
674
- _mongocrypt_buffer_init (&intermediates[1]);
675
- _mongocrypt_buffer_init (&intermediates[2]);
676
- intermediates[0].data = associated_data->data;
677
- intermediates[0].len = associated_data->len;
678
- /* Add ciphertext. */
679
- intermediates[1].data = ciphertext->data;
680
- intermediates[1].len = ciphertext->len;
681
- /* Add associated data length in bits. */
682
- /* multiplying a uint32_t by 8 won't bring it anywhere close to UINT64_MAX */
683
- associated_data_len_be = 8 * (uint64_t) associated_data->len;
684
- associated_data_len_be = BSON_UINT64_TO_BE (associated_data_len_be);
685
- intermediates[2].data = (uint8_t *) &associated_data_len_be;
686
- intermediates[2].len = sizeof (uint64_t);
687
- tag.data = tag_storage;
688
- tag.len = sizeof (tag_storage);
689
-
690
-
691
- if (!_mongocrypt_buffer_concat (&to_hmac, intermediates, 3)) {
692
- CLIENT_ERR ("failed to allocate buffer");
693
- goto done;
694
- }
695
- if (!_crypto_hmac_sha_512 (crypto, mac_key, &to_hmac, &tag, status)) {
696
- goto done;
697
- }
698
-
699
- /* [MCGREW 2.7] "The HMAC-SHA-512 value is truncated to T_LEN=32 octets" */
700
- memcpy (out->data, tag.data, MONGOCRYPT_HMAC_LEN);
701
- ret = true;
606
+ static bool _hmac_step(_mongocrypt_crypto_t *crypto,
607
+ _mongocrypt_mac_format_t mac_format,
608
+ _mongocrypt_hmac_type_t hmac,
609
+ const _mongocrypt_buffer_t *Km,
610
+ const _mongocrypt_buffer_t *AAD,
611
+ const _mongocrypt_buffer_t *iv_and_ciphertext,
612
+ _mongocrypt_buffer_t *out,
613
+ mongocrypt_status_t *status) {
614
+ _mongocrypt_buffer_t to_hmac = {0};
615
+ bool ret = false;
616
+
617
+ BSON_ASSERT(hmac != HMAC_NONE);
618
+ BSON_ASSERT_PARAM(crypto);
619
+ BSON_ASSERT_PARAM(Km);
620
+ // AAD may be NULL
621
+ BSON_ASSERT_PARAM(iv_and_ciphertext);
622
+ BSON_ASSERT_PARAM(out);
623
+
624
+ _mongocrypt_buffer_init(&to_hmac);
625
+
626
+ if (MONGOCRYPT_MAC_KEY_LEN != Km->len) {
627
+ CLIENT_ERR("HMAC key wrong length: %d", Km->len);
628
+ goto done;
629
+ }
630
+
631
+ if (out->len != MONGOCRYPT_HMAC_LEN) {
632
+ CLIENT_ERR("out wrong length: %d", out->len);
633
+ goto done;
634
+ }
635
+
636
+ /* Construct the input to the HMAC */
637
+ uint32_t num_intermediates = 0;
638
+ _mongocrypt_buffer_t intermediates[3];
639
+ if (AAD && !_mongocrypt_buffer_from_subrange(&intermediates[num_intermediates++], AAD, 0, AAD->len)) {
640
+ CLIENT_ERR("Failed creating MAC subrange on AD");
641
+ goto done;
642
+ }
643
+ if (!_mongocrypt_buffer_from_subrange(&intermediates[num_intermediates++],
644
+ iv_and_ciphertext,
645
+ 0,
646
+ iv_and_ciphertext->len)) {
647
+ CLIENT_ERR("Failed creating MAC subrange on IV and S");
648
+ goto done;
649
+ }
650
+
651
+ // {AL} must be stored in the function's lexical scope so that
652
+ // {intermediates}'s reference to it survives until the
653
+ // _mongocrypt_buffer_concat operation later.
654
+ uint64_t AL;
655
+ if (mac_format == MAC_FORMAT_FLE1) {
656
+ /* T := HMAC(AAD || IV || S || AL)
657
+ * AL is equal to the number of bits in AAD expressed
658
+ * as a 64bit unsigned big-endian integer.
659
+ * Multiplying a uint32_t by 8 won't bring it anywhere close to
660
+ * UINT64_MAX.
661
+ */
662
+ AL = AAD ? BSON_UINT64_TO_BE(8 * (uint64_t)AAD->len) : 0;
663
+ _mongocrypt_buffer_init(&intermediates[num_intermediates]);
664
+ intermediates[num_intermediates].data = (uint8_t *)&AL;
665
+ intermediates[num_intermediates++].len = sizeof(uint64_t);
666
+
667
+ } else {
668
+ /* T := HMAC(AAD || IV || S) */
669
+ BSON_ASSERT((mac_format == MAC_FORMAT_FLE2AEAD) || (mac_format == MAC_FORMAT_FLE2v2AEAD));
670
+ }
671
+
672
+ if (!_mongocrypt_buffer_concat(&to_hmac, intermediates, num_intermediates)) {
673
+ CLIENT_ERR("failed to allocate buffer");
674
+ goto done;
675
+ }
676
+
677
+ if (hmac == HMAC_SHA_512_256) {
678
+ uint8_t storage[64];
679
+ _mongocrypt_buffer_t tag = {.data = storage, .len = sizeof(storage)};
680
+
681
+ if (!_crypto_hmac_sha_512(crypto, Km, &to_hmac, &tag, status)) {
682
+ goto done;
683
+ }
684
+
685
+ // Truncate sha512 to first 256 bits.
686
+ memcpy(out->data, tag.data, MONGOCRYPT_HMAC_LEN);
687
+
688
+ } else {
689
+ BSON_ASSERT(hmac == HMAC_SHA_256);
690
+ if (!_mongocrypt_hmac_sha_256(crypto, Km, &to_hmac, out, status)) {
691
+ goto done;
692
+ }
693
+ }
694
+
695
+ ret = true;
702
696
  done:
703
- _mongocrypt_buffer_cleanup (&to_hmac);
704
- return ret;
697
+ _mongocrypt_buffer_cleanup(&to_hmac);
698
+ return ret;
705
699
  }
706
700
 
707
701
  /* ----------------------------------------------------------------------------
@@ -713,7 +707,7 @@ done:
713
707
  * Parameters:
714
708
  * @iv a 16 byte IV.
715
709
  * @associated_data associated data for the HMAC. May be NULL.
716
- * @key a 96 byte key.
710
+ * @key is the encryption key. The size depends on @key_format.
717
711
  * @plaintext the plaintext to encrypt.
718
712
  * @ciphertext a location for the resulting ciphertext and HMAC tag.
719
713
  * @bytes_written a location for the resulting bytes written.
@@ -729,117 +723,124 @@ done:
729
723
  * Postconditions:
730
724
  * 1. bytes_written is set to the length of the written ciphertext. This
731
725
  * is the same as
732
- * _mongocrypt_calculate_ciphertext_len (plaintext->len, status).
726
+ * _mongocrypt_calculate_ciphertext_len (plaintext->len, mode, hmac, status).
733
727
  *
734
728
  * ----------------------------------------------------------------------------
735
729
  */
736
- bool
737
- _mongocrypt_do_encryption (_mongocrypt_crypto_t *crypto,
738
- const _mongocrypt_buffer_t *iv,
739
- const _mongocrypt_buffer_t *associated_data,
740
- const _mongocrypt_buffer_t *key,
741
- const _mongocrypt_buffer_t *plaintext,
742
- _mongocrypt_buffer_t *ciphertext,
743
- uint32_t *bytes_written,
744
- mongocrypt_status_t *status)
745
- {
746
- _mongocrypt_buffer_t mac_key = {0}, enc_key = {0}, intermediate = {0},
747
- intermediate_hmac = {0}, empty_buffer = {0};
748
- uint32_t intermediate_bytes_written = 0;
749
-
750
- BSON_ASSERT_PARAM (crypto);
751
- BSON_ASSERT_PARAM (iv);
752
- /* associated_data is checked at the point it is used, so it can be NULL */
753
- BSON_ASSERT_PARAM (key);
754
- BSON_ASSERT_PARAM (plaintext);
755
- BSON_ASSERT_PARAM (ciphertext);
756
-
757
- memset (ciphertext->data, 0, ciphertext->len);
758
-
759
- if (ciphertext->len !=
760
- _mongocrypt_calculate_ciphertext_len (plaintext->len, status)) {
761
- CLIENT_ERR (
762
- "output ciphertext should have been allocated with %d bytes",
763
- _mongocrypt_calculate_ciphertext_len (plaintext->len, status));
764
- return false;
765
- }
766
-
767
- BSON_ASSERT_PARAM (bytes_written);
768
- *bytes_written = 0;
769
-
770
- if (MONGOCRYPT_IV_LEN != iv->len) {
771
- CLIENT_ERR ("IV should have length %d, but has length %d",
772
- MONGOCRYPT_IV_LEN,
773
- iv->len);
774
- return false;
775
- }
776
- if (MONGOCRYPT_KEY_LEN != key->len) {
777
- CLIENT_ERR ("key should have length %d, but has length %d",
778
- MONGOCRYPT_KEY_LEN,
779
- key->len);
780
- return false;
781
- }
782
-
783
- intermediate.len = ciphertext->len;
784
- intermediate.data = ciphertext->data;
785
-
786
- /* [MCGREW]: Step 1. "MAC_KEY consists of the initial MAC_KEY_LEN octets of
787
- * K, in order. ENC_KEY consists of the final ENC_KEY_LEN octets of K, in
788
- * order." */
789
- mac_key.data = (uint8_t *) key->data;
790
- mac_key.len = MONGOCRYPT_MAC_KEY_LEN;
791
- enc_key.data = (uint8_t *) key->data + MONGOCRYPT_MAC_KEY_LEN;
792
- enc_key.len = MONGOCRYPT_ENC_KEY_LEN;
793
-
794
- /* Prepend the IV. */
795
- memcpy (intermediate.data, iv->data, iv->len);
796
- intermediate.data += iv->len;
797
- BSON_ASSERT (intermediate.len >= iv->len);
798
- intermediate.len -= iv->len;
799
- BSON_ASSERT (*bytes_written <= UINT32_MAX - iv->len);
800
- *bytes_written += iv->len;
801
-
802
- /* [MCGREW]: Steps 2 & 3. */
803
- if (!_encrypt_step (crypto,
804
- iv,
805
- &enc_key,
806
- plaintext,
807
- &intermediate,
808
- &intermediate_bytes_written,
809
- status)) {
810
- return false;
811
- }
812
-
813
- BSON_ASSERT (*bytes_written <= UINT32_MAX - intermediate_bytes_written);
814
- *bytes_written += intermediate_bytes_written;
815
-
816
- /* Append the HMAC tag. */
817
- intermediate_hmac.data = ciphertext->data + *bytes_written;
818
- intermediate_hmac.len = MONGOCRYPT_HMAC_LEN;
819
-
820
- intermediate.data = ciphertext->data;
821
- intermediate.len = *bytes_written;
822
-
823
- /* [MCGREW]: Steps 4 & 5, compute the HMAC. */
824
- if (!_hmac_step (crypto,
825
- &mac_key,
826
- associated_data ? associated_data : &empty_buffer,
827
- &intermediate,
828
- &intermediate_hmac,
829
- status)) {
830
- return false;
831
- }
832
-
833
- *bytes_written += MONGOCRYPT_HMAC_LEN;
834
- return true;
730
+ static bool _mongocrypt_do_encryption(_mongocrypt_crypto_t *crypto,
731
+ _mongocrypt_key_format_t key_format,
732
+ _mongocrypt_mac_format_t mac_format,
733
+ _mongocrypt_encryption_mode_t mode,
734
+ _mongocrypt_hmac_type_t hmac,
735
+ const _mongocrypt_buffer_t *iv,
736
+ const _mongocrypt_buffer_t *associated_data,
737
+ const _mongocrypt_buffer_t *key,
738
+ const _mongocrypt_buffer_t *plaintext,
739
+ _mongocrypt_buffer_t *ciphertext,
740
+ uint32_t *bytes_written,
741
+ mongocrypt_status_t *status) {
742
+ _mongocrypt_buffer_t Ke = {0}; // Ke == Key for Encryption
743
+ BSON_ASSERT_PARAM(crypto);
744
+ BSON_ASSERT_PARAM(iv);
745
+ /* associated_data is checked at the point it is used, so it can be NULL */
746
+ BSON_ASSERT_PARAM(key);
747
+ BSON_ASSERT_PARAM(plaintext);
748
+ BSON_ASSERT_PARAM(ciphertext);
749
+
750
+ if (plaintext->len <= 0) {
751
+ CLIENT_ERR("input plaintext too small. Must be more than zero bytes.");
752
+ return false;
753
+ }
754
+
755
+ const uint32_t expect_ciphertext_len = _mongocrypt_calculate_ciphertext_len(plaintext->len, mode, hmac, status);
756
+ if (mongocrypt_status_type(status) != MONGOCRYPT_STATUS_OK) {
757
+ return false;
758
+ }
759
+ if (expect_ciphertext_len != ciphertext->len) {
760
+ CLIENT_ERR("output ciphertext should have been allocated with %d bytes", expect_ciphertext_len);
761
+ return false;
762
+ }
763
+
764
+ if (MONGOCRYPT_IV_LEN != iv->len) {
765
+ CLIENT_ERR("IV should have length %d, but has length %d", MONGOCRYPT_IV_LEN, iv->len);
766
+ return false;
767
+ }
768
+
769
+ const uint32_t expected_key_len = (key_format == KEY_FORMAT_FLE2) ? MONGOCRYPT_ENC_KEY_LEN : MONGOCRYPT_KEY_LEN;
770
+ if (key->len != expected_key_len) {
771
+ CLIENT_ERR("key should have length %d, but has length %d", expected_key_len, key->len);
772
+ return false;
773
+ }
774
+
775
+ // Copy IV into the output, and clear remainder.
776
+ memmove(ciphertext->data, iv->data, MONGOCRYPT_IV_LEN);
777
+ memset(ciphertext->data + MONGOCRYPT_IV_LEN, 0, ciphertext->len - MONGOCRYPT_IV_LEN);
778
+
779
+ // S is the encryption payload without IV or HMAC
780
+ _mongocrypt_buffer_t S;
781
+ if (!_mongocrypt_buffer_from_subrange(&S, ciphertext, MONGOCRYPT_IV_LEN, ciphertext->len - MONGOCRYPT_IV_LEN)) {
782
+ CLIENT_ERR("unable to create S subrange from C");
783
+ return false;
784
+ }
785
+ if (hmac != HMAC_NONE) {
786
+ S.len -= MONGOCRYPT_HMAC_LEN;
787
+ }
788
+
789
+ // Ke is the key used for payload encryption
790
+ const uint32_t Ke_offset = (key_format == KEY_FORMAT_FLE1) ? MONGOCRYPT_MAC_KEY_LEN : 0;
791
+ if (!_mongocrypt_buffer_from_subrange(&Ke, key, Ke_offset, MONGOCRYPT_ENC_KEY_LEN)) {
792
+ CLIENT_ERR("unable to create Ke subrange from key");
793
+ return false;
794
+ }
795
+
796
+ uint32_t S_bytes_written = 0;
797
+ if (!_encrypt_step(crypto, mode, iv, &Ke, plaintext, &S, &S_bytes_written, status)) {
798
+ return false;
799
+ }
800
+ BSON_ASSERT_PARAM(bytes_written);
801
+ BSON_ASSERT((UINT32_MAX - S_bytes_written) > MONGOCRYPT_IV_LEN);
802
+ *bytes_written = MONGOCRYPT_IV_LEN + S_bytes_written;
803
+
804
+ if (hmac != HMAC_NONE) {
805
+ // Km == Key for MAC
806
+ const uint32_t Km_offset = (key_format == KEY_FORMAT_FLE1) ? 0 : MONGOCRYPT_ENC_KEY_LEN;
807
+
808
+ // Km is the HMAC Key.
809
+ _mongocrypt_buffer_t Km;
810
+ if (!_mongocrypt_buffer_from_subrange(&Km, key, Km_offset, MONGOCRYPT_MAC_KEY_LEN)) {
811
+ CLIENT_ERR("unable to create Km subrange from key");
812
+ return false;
813
+ }
814
+
815
+ /* Primary payload to MAC. */
816
+ _mongocrypt_buffer_t iv_and_ciphertext;
817
+ if (!_mongocrypt_buffer_from_subrange(&iv_and_ciphertext, ciphertext, 0, *bytes_written)) {
818
+ CLIENT_ERR("unable to create IV || S subrange from C");
819
+ return false;
820
+ }
821
+
822
+ // T == HMAC Tag
823
+ _mongocrypt_buffer_t T;
824
+ if (!_mongocrypt_buffer_from_subrange(&T, ciphertext, *bytes_written, MONGOCRYPT_HMAC_LEN)) {
825
+ CLIENT_ERR("unable to create T subrange from C");
826
+ return false;
827
+ }
828
+
829
+ if (!_hmac_step(crypto, mac_format, hmac, &Km, associated_data, &iv_and_ciphertext, &T, status)) {
830
+ return false;
831
+ }
832
+
833
+ *bytes_written += MONGOCRYPT_HMAC_LEN;
834
+ }
835
+
836
+ return true;
835
837
  }
836
838
 
837
-
838
839
  /* ----------------------------------------------------------------------------
839
840
  *
840
- * _aes256_cbc_decrypt --
841
+ * _decrypt_step --
841
842
  *
842
- * Decrypts using AES256 CBC using a secret key and a known IV.
843
+ * Decrypts using AES256 using a secret key and a known IV.
843
844
  *
844
845
  * Parameters:
845
846
  * @enc_key a 32 byte key.
@@ -859,71 +860,77 @@ _mongocrypt_do_encryption (_mongocrypt_crypto_t *crypto,
859
860
  * Postconditions:
860
861
  * 1. bytes_written is set to the length of the written plaintext, excluding
861
862
  * padding. This may be less than
862
- * _mongocrypt_calculate_plaintext_len (ciphertext->len, status).
863
+ * _mongocrypt_calculate_plaintext_len (ciphertext->len, home, hmac, status).
863
864
  *
864
865
  * ----------------------------------------------------------------------------
865
866
  */
866
- static bool
867
- _decrypt_step (_mongocrypt_crypto_t *crypto,
868
- const _mongocrypt_buffer_t *iv,
869
- const _mongocrypt_buffer_t *enc_key,
870
- const _mongocrypt_buffer_t *ciphertext,
871
- _mongocrypt_buffer_t *plaintext,
872
- uint32_t *bytes_written,
873
- mongocrypt_status_t *status)
874
- {
875
- uint8_t padding_byte;
876
-
877
- BSON_ASSERT_PARAM (crypto);
878
- BSON_ASSERT_PARAM (iv);
879
- BSON_ASSERT_PARAM (enc_key);
880
- BSON_ASSERT_PARAM (ciphertext);
881
- BSON_ASSERT_PARAM (plaintext);
882
-
883
- BSON_ASSERT_PARAM (bytes_written);
884
- *bytes_written = 0;
885
-
886
- if (MONGOCRYPT_IV_LEN != iv->len) {
887
- CLIENT_ERR ("IV should have length %d, but has length %d",
888
- MONGOCRYPT_IV_LEN,
889
- iv->len);
890
- return false;
891
- }
892
- if (MONGOCRYPT_ENC_KEY_LEN != enc_key->len) {
893
- CLIENT_ERR ("encryption key should have length %d, but has length %d",
894
- MONGOCRYPT_ENC_KEY_LEN,
895
- enc_key->len);
896
- return false;
897
- }
898
-
899
-
900
- if (ciphertext->len % MONGOCRYPT_BLOCK_SIZE > 0) {
901
- CLIENT_ERR ("error, ciphertext length is not a multiple of block size");
902
- return false;
903
- }
904
-
905
- if (!_crypto_aes_256_cbc_decrypt (
906
- crypto,
907
- (aes_256_args_t){.iv = iv,
908
- .key = enc_key,
909
- .in = ciphertext,
910
- .out = plaintext,
911
- .bytes_written = bytes_written,
912
- .status = status})) {
913
- return false;
914
- }
915
-
916
- BSON_ASSERT (*bytes_written > 0);
917
- padding_byte = plaintext->data[*bytes_written - 1];
918
- if (padding_byte > 16) {
919
- CLIENT_ERR ("error, ciphertext malformed padding");
920
- return false;
921
- }
922
- *bytes_written -= padding_byte;
923
- return true;
867
+ static bool _decrypt_step(_mongocrypt_crypto_t *crypto,
868
+ _mongocrypt_encryption_mode_t mode,
869
+ const _mongocrypt_buffer_t *iv,
870
+ const _mongocrypt_buffer_t *enc_key,
871
+ const _mongocrypt_buffer_t *ciphertext,
872
+ _mongocrypt_buffer_t *plaintext,
873
+ uint32_t *bytes_written,
874
+ mongocrypt_status_t *status) {
875
+ BSON_ASSERT_PARAM(crypto);
876
+ BSON_ASSERT_PARAM(iv);
877
+ BSON_ASSERT_PARAM(enc_key);
878
+ BSON_ASSERT_PARAM(ciphertext);
879
+ BSON_ASSERT_PARAM(plaintext);
880
+
881
+ BSON_ASSERT_PARAM(bytes_written);
882
+ *bytes_written = 0;
883
+
884
+ if (MONGOCRYPT_IV_LEN != iv->len) {
885
+ CLIENT_ERR("IV should have length %d, but has length %d", MONGOCRYPT_IV_LEN, iv->len);
886
+ return false;
887
+ }
888
+ if (MONGOCRYPT_ENC_KEY_LEN != enc_key->len) {
889
+ CLIENT_ERR("encryption key should have length %d, but has length %d", MONGOCRYPT_ENC_KEY_LEN, enc_key->len);
890
+ return false;
891
+ }
892
+
893
+ if (mode == MODE_CBC) {
894
+ if (ciphertext->len % MONGOCRYPT_BLOCK_SIZE > 0) {
895
+ CLIENT_ERR("error, ciphertext length is not a multiple of block size");
896
+ return false;
897
+ }
898
+
899
+ if (!_crypto_aes_256_cbc_decrypt(crypto,
900
+ (aes_256_args_t){.iv = iv,
901
+ .key = enc_key,
902
+ .in = ciphertext,
903
+ .out = plaintext,
904
+ .bytes_written = bytes_written,
905
+ .status = status})) {
906
+ return false;
907
+ }
908
+
909
+ BSON_ASSERT(*bytes_written > 0);
910
+ uint8_t padding_byte = plaintext->data[*bytes_written - 1];
911
+ if (padding_byte > 16) {
912
+ CLIENT_ERR("error, ciphertext malformed padding");
913
+ return false;
914
+ }
915
+ *bytes_written -= padding_byte;
916
+
917
+ } else {
918
+ BSON_ASSERT(mode == MODE_CTR);
919
+ if (!_crypto_aes_256_ctr_decrypt(crypto,
920
+ (aes_256_args_t){.iv = iv,
921
+ .key = enc_key,
922
+ .in = ciphertext,
923
+ .out = plaintext,
924
+ .bytes_written = bytes_written,
925
+ .status = status})) {
926
+ return false;
927
+ }
928
+ BSON_ASSERT(*bytes_written == plaintext->len);
929
+ }
930
+
931
+ return true;
924
932
  }
925
933
 
926
-
927
934
  /* ----------------------------------------------------------------------------
928
935
  *
929
936
  * _mongocrypt_do_decryption --
@@ -948,108 +955,200 @@ _decrypt_step (_mongocrypt_crypto_t *crypto,
948
955
  * Postconditions:
949
956
  * 1. bytes_written is set to the length of the written plaintext, excluding
950
957
  * padding. This may be less than
951
- * _mongocrypt_calculate_plaintext_len (ciphertext->len, status).
958
+ * _mongocrypt_calculate_plaintext_len (ciphertext->len, mode, hmac, status).
952
959
  *
953
960
  * ----------------------------------------------------------------------------
954
961
  */
955
- bool
956
- _mongocrypt_do_decryption (_mongocrypt_crypto_t *crypto,
957
- const _mongocrypt_buffer_t *associated_data,
958
- const _mongocrypt_buffer_t *key,
959
- const _mongocrypt_buffer_t *ciphertext,
960
- _mongocrypt_buffer_t *plaintext,
961
- uint32_t *bytes_written,
962
- mongocrypt_status_t *status)
963
- {
964
- bool ret = false;
965
- _mongocrypt_buffer_t mac_key = {0}, enc_key = {0}, intermediate = {0},
966
- hmac_tag = {0}, iv = {0}, empty_buffer = {0};
967
- uint8_t hmac_tag_storage[MONGOCRYPT_HMAC_LEN];
968
-
969
- BSON_ASSERT_PARAM (crypto);
970
- /* associated_data is checked at the point it is used, so it can be NULL */
971
- BSON_ASSERT_PARAM (key);
972
- BSON_ASSERT_PARAM (ciphertext);
973
- BSON_ASSERT_PARAM (plaintext);
974
- BSON_ASSERT_PARAM (bytes_written);
975
-
976
- if (plaintext->len !=
977
- _mongocrypt_calculate_plaintext_len (ciphertext->len, status)) {
978
- CLIENT_ERR ("output plaintext should have been allocated with %d bytes, "
979
- "but has: %d",
980
- _mongocrypt_calculate_plaintext_len (ciphertext->len, status),
981
- plaintext->len);
982
- return false;
983
- }
984
-
985
- if (MONGOCRYPT_KEY_LEN != key->len) {
986
- CLIENT_ERR ("key should have length %d, but has length %d",
987
- MONGOCRYPT_KEY_LEN,
988
- key->len);
989
- return false;
990
- }
991
-
992
- if (ciphertext->len <
993
- MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN + MONGOCRYPT_BLOCK_SIZE) {
994
- CLIENT_ERR ("corrupt ciphertext - must be > %d bytes",
995
- MONGOCRYPT_HMAC_LEN + MONGOCRYPT_IV_LEN +
996
- MONGOCRYPT_BLOCK_SIZE);
997
- goto done;
998
- }
999
-
1000
- mac_key.data = (uint8_t *) key->data;
1001
- mac_key.len = MONGOCRYPT_MAC_KEY_LEN;
1002
- enc_key.data = (uint8_t *) key->data + MONGOCRYPT_MAC_KEY_LEN;
1003
- enc_key.len = MONGOCRYPT_ENC_KEY_LEN;
1004
-
1005
- iv.data = ciphertext->data;
1006
- iv.len = MONGOCRYPT_IV_LEN;
1007
-
1008
- intermediate.data = (uint8_t *) ciphertext->data;
1009
- intermediate.len = ciphertext->len - MONGOCRYPT_HMAC_LEN;
1010
-
1011
- hmac_tag.data = hmac_tag_storage;
1012
- hmac_tag.len = MONGOCRYPT_HMAC_LEN;
1013
-
1014
- /* [MCGREW 2.2]: Step 3: HMAC check. */
1015
- if (!_hmac_step (crypto,
1016
- &mac_key,
1017
- associated_data ? associated_data : &empty_buffer,
1018
- &intermediate,
1019
- &hmac_tag,
1020
- status)) {
1021
- goto done;
1022
- }
1023
-
1024
- /* [MCGREW] "using a comparison routine that takes constant time". */
1025
- if (0 != _mongocrypt_memequal (hmac_tag.data,
1026
- ciphertext->data +
1027
- (ciphertext->len - MONGOCRYPT_HMAC_LEN),
1028
- MONGOCRYPT_HMAC_LEN)) {
1029
- CLIENT_ERR ("HMAC validation failure");
1030
- goto done;
1031
- }
1032
-
1033
- /* Decrypt data excluding IV + HMAC. */
1034
- intermediate.data = (uint8_t *) ciphertext->data + MONGOCRYPT_IV_LEN;
1035
- intermediate.len =
1036
- ciphertext->len - (MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN);
1037
-
1038
- if (!_decrypt_step (crypto,
1039
- &iv,
1040
- &enc_key,
1041
- &intermediate,
1042
- plaintext,
1043
- bytes_written,
1044
- status)) {
1045
- goto done;
1046
- }
1047
-
1048
- ret = true;
1049
- done:
1050
- return ret;
962
+ static bool _mongocrypt_do_decryption(_mongocrypt_crypto_t *crypto,
963
+ _mongocrypt_key_format_t key_format,
964
+ _mongocrypt_mac_format_t mac_format,
965
+ _mongocrypt_encryption_mode_t mode,
966
+ _mongocrypt_hmac_type_t hmac,
967
+ const _mongocrypt_buffer_t *associated_data,
968
+ const _mongocrypt_buffer_t *key,
969
+ const _mongocrypt_buffer_t *ciphertext,
970
+ _mongocrypt_buffer_t *plaintext,
971
+ uint32_t *bytes_written,
972
+ mongocrypt_status_t *status) {
973
+ BSON_ASSERT_PARAM(crypto);
974
+ /* associated_data is checked at the point it is used, so it can be NULL */
975
+ BSON_ASSERT_PARAM(key);
976
+ BSON_ASSERT_PARAM(ciphertext);
977
+ BSON_ASSERT_PARAM(plaintext);
978
+ BSON_ASSERT_PARAM(bytes_written);
979
+
980
+ const uint32_t expect_plaintext_len = _mongocrypt_calculate_plaintext_len(ciphertext->len, mode, hmac, status);
981
+ if (mongocrypt_status_type(status) != MONGOCRYPT_STATUS_OK) {
982
+ return false;
983
+ }
984
+ if (plaintext->len != expect_plaintext_len) {
985
+ CLIENT_ERR("output plaintext should have been allocated with %d bytes, "
986
+ "but has: %d",
987
+ expect_plaintext_len,
988
+ plaintext->len);
989
+ return false;
990
+ }
991
+ if (expect_plaintext_len == 0) {
992
+ // While a ciphertext string describing a zero length plaintext is
993
+ // technically valid,
994
+ // it's not actually particularly useful in the context of FLE where such
995
+ // values aren't encoded.
996
+ CLIENT_ERR("input ciphertext too small. Must be more than %" PRIu32 " bytes",
997
+ _mongocrypt_calculate_ciphertext_len(0, mode, hmac, NULL));
998
+ return false;
999
+ }
1000
+
1001
+ const uint32_t expected_key_len = (key_format == KEY_FORMAT_FLE2) ? MONGOCRYPT_ENC_KEY_LEN : MONGOCRYPT_KEY_LEN;
1002
+ if (expected_key_len != key->len) {
1003
+ CLIENT_ERR("key should have length %d, but has length %d", expected_key_len, key->len);
1004
+ return false;
1005
+ }
1006
+
1007
+ const uint32_t min_cipherlen = _mongocrypt_calculate_ciphertext_len(0, mode, hmac, NULL);
1008
+ if (ciphertext->len < min_cipherlen) {
1009
+ CLIENT_ERR("corrupt ciphertext - must be >= %d bytes", min_cipherlen);
1010
+ return false;
1011
+ }
1012
+
1013
+ _mongocrypt_buffer_t Ke;
1014
+ const uint32_t Ke_offset = (key_format == KEY_FORMAT_FLE1) ? MONGOCRYPT_MAC_KEY_LEN : 0;
1015
+ if (!_mongocrypt_buffer_from_subrange(&Ke, key, Ke_offset, MONGOCRYPT_ENC_KEY_LEN)) {
1016
+ CLIENT_ERR("unable to create Ke subrange from key");
1017
+ return false;
1018
+ }
1019
+
1020
+ _mongocrypt_buffer_t IV;
1021
+ if (!_mongocrypt_buffer_from_subrange(&IV, ciphertext, 0, MONGOCRYPT_IV_LEN)) {
1022
+ CLIENT_ERR("unable to create IV subrange from ciphertext");
1023
+ return false;
1024
+ }
1025
+
1026
+ if (hmac == HMAC_NONE) {
1027
+ BSON_ASSERT(key_format == KEY_FORMAT_FLE2);
1028
+
1029
+ } else {
1030
+ BSON_ASSERT(key_format != KEY_FORMAT_FLE2);
1031
+
1032
+ uint8_t hmac_tag_storage[MONGOCRYPT_HMAC_LEN];
1033
+ const uint32_t mac_key_offset = (key_format == KEY_FORMAT_FLE1) ? 0 : MONGOCRYPT_ENC_KEY_LEN;
1034
+ _mongocrypt_buffer_t Km;
1035
+ if (!_mongocrypt_buffer_from_subrange(&Km, key, mac_key_offset, MONGOCRYPT_MAC_KEY_LEN)) {
1036
+ CLIENT_ERR("unable to create Km subrange from key");
1037
+ return false;
1038
+ }
1039
+
1040
+ _mongocrypt_buffer_t iv_and_ciphertext;
1041
+ if (!_mongocrypt_buffer_from_subrange(&iv_and_ciphertext,
1042
+ ciphertext,
1043
+ 0,
1044
+ ciphertext->len - MONGOCRYPT_HMAC_LEN)) {
1045
+ CLIENT_ERR("unable to create IV || S subrange from C");
1046
+ return false;
1047
+ }
1048
+
1049
+ _mongocrypt_buffer_t hmac_tag = {.data = hmac_tag_storage, .len = MONGOCRYPT_HMAC_LEN};
1050
+
1051
+ if (!_hmac_step(crypto, mac_format, hmac, &Km, associated_data, &iv_and_ciphertext, &hmac_tag, status)) {
1052
+ return false;
1053
+ }
1054
+
1055
+ /* Constant time compare. */
1056
+ _mongocrypt_buffer_t T;
1057
+ if (!_mongocrypt_buffer_from_subrange(&T,
1058
+ ciphertext,
1059
+ ciphertext->len - MONGOCRYPT_HMAC_LEN,
1060
+ MONGOCRYPT_HMAC_LEN)) {
1061
+ CLIENT_ERR("unable to create T subrange from C");
1062
+ return false;
1063
+ }
1064
+ if (0 != _mongocrypt_memequal(hmac_tag.data, T.data, MONGOCRYPT_HMAC_LEN)) {
1065
+ CLIENT_ERR("HMAC validation failure");
1066
+ return false;
1067
+ }
1068
+ }
1069
+
1070
+ /* Decrypt data excluding IV + HMAC. */
1071
+ const uint32_t hmac_len = (hmac == HMAC_NONE) ? 0 : MONGOCRYPT_HMAC_LEN;
1072
+ _mongocrypt_buffer_t S;
1073
+ if (!_mongocrypt_buffer_from_subrange(&S,
1074
+ ciphertext,
1075
+ MONGOCRYPT_IV_LEN,
1076
+ ciphertext->len - MONGOCRYPT_IV_LEN - hmac_len)) {
1077
+ CLIENT_ERR("unable to create S subrange from C");
1078
+ return false;
1079
+ }
1080
+
1081
+ return _decrypt_step(crypto, mode, &IV, &Ke, &S, plaintext, bytes_written, status);
1051
1082
  }
1052
1083
 
1084
+ #define DECLARE_ALGORITHM(name, mode, hmac) \
1085
+ static uint32_t _mc_##name##_ciphertext_len(uint32_t plaintext_len, mongocrypt_status_t *status) { \
1086
+ return _mongocrypt_calculate_ciphertext_len(plaintext_len, MODE_##mode, HMAC_##hmac, status); \
1087
+ } \
1088
+ static uint32_t _mc_##name##_plaintext_len(uint32_t ciphertext_len, mongocrypt_status_t *status) { \
1089
+ return _mongocrypt_calculate_plaintext_len(ciphertext_len, MODE_##mode, HMAC_##hmac, status); \
1090
+ } \
1091
+ static bool _mc_##name##_do_encryption(_mongocrypt_crypto_t *crypto, \
1092
+ const _mongocrypt_buffer_t *iv, \
1093
+ const _mongocrypt_buffer_t *aad, \
1094
+ const _mongocrypt_buffer_t *key, \
1095
+ const _mongocrypt_buffer_t *plaintext, \
1096
+ _mongocrypt_buffer_t *ciphertext, \
1097
+ uint32_t *written, \
1098
+ mongocrypt_status_t *status) { \
1099
+ return _mongocrypt_do_encryption(crypto, \
1100
+ KEY_FORMAT_##name, \
1101
+ MAC_FORMAT_##name, \
1102
+ MODE_##mode, \
1103
+ HMAC_##hmac, \
1104
+ iv, \
1105
+ aad, \
1106
+ key, \
1107
+ plaintext, \
1108
+ ciphertext, \
1109
+ written, \
1110
+ status); \
1111
+ } \
1112
+ static bool _mc_##name##_do_decryption(_mongocrypt_crypto_t *crypto, \
1113
+ const _mongocrypt_buffer_t *aad, \
1114
+ const _mongocrypt_buffer_t *key, \
1115
+ const _mongocrypt_buffer_t *ciphertext, \
1116
+ _mongocrypt_buffer_t *plaintext, \
1117
+ uint32_t *written, \
1118
+ mongocrypt_status_t *status) { \
1119
+ return _mongocrypt_do_decryption(crypto, \
1120
+ KEY_FORMAT_##name, \
1121
+ MAC_FORMAT_##name, \
1122
+ MODE_##mode, \
1123
+ HMAC_##hmac, \
1124
+ aad, \
1125
+ key, \
1126
+ ciphertext, \
1127
+ plaintext, \
1128
+ written, \
1129
+ status); \
1130
+ } \
1131
+ static const _mongocrypt_value_encryption_algorithm_t _mc##name##Algorithm_definition = { \
1132
+ _mc_##name##_ciphertext_len, \
1133
+ _mc_##name##_plaintext_len, \
1134
+ _mc_##name##_do_encryption, \
1135
+ _mc_##name##_do_decryption, \
1136
+ }; \
1137
+ const _mongocrypt_value_encryption_algorithm_t *_mc##name##Algorithm() { return &_mc##name##Algorithm_definition; }
1138
+
1139
+ // FLE1 algorithm: AES-256-CBC HMAC/SHA-512-256 (SHA-512 truncated to 256 bits)
1140
+ DECLARE_ALGORITHM(FLE1, CBC, SHA_512_256)
1141
+
1142
+ // FLE2 AEAD used value algorithm: AES-256-CTR HMAC/SHA-256
1143
+ DECLARE_ALGORITHM(FLE2AEAD, CTR, SHA_256)
1144
+
1145
+ // FLE2 used with ESC/ECOC tokens: AES-256-CTR no HMAC
1146
+ DECLARE_ALGORITHM(FLE2, CTR, NONE)
1147
+
1148
+ // FLE2v2 AEAD general algorithm: AES-256-CBC HMAC/SHA-256
1149
+ DECLARE_ALGORITHM(FLE2v2AEAD, CBC, SHA_256)
1150
+
1151
+ #undef DECLARE_ALGORITHM
1053
1152
 
1054
1153
  /* ----------------------------------------------------------------------------
1055
1154
  *
@@ -1070,25 +1169,21 @@ done:
1070
1169
  *
1071
1170
  * ----------------------------------------------------------------------------
1072
1171
  */
1073
- bool
1074
- _mongocrypt_random (_mongocrypt_crypto_t *crypto,
1075
- _mongocrypt_buffer_t *out,
1076
- uint32_t count,
1077
- mongocrypt_status_t *status)
1078
- {
1079
- BSON_ASSERT_PARAM (crypto);
1080
- BSON_ASSERT_PARAM (out);
1081
-
1082
- if (count != out->len) {
1083
- CLIENT_ERR (
1084
- "out should have length %d, but has length %d", count, out->len);
1085
- return false;
1086
- }
1087
-
1088
- return _crypto_random (crypto, out, count, status);
1172
+ bool _mongocrypt_random(_mongocrypt_crypto_t *crypto,
1173
+ _mongocrypt_buffer_t *out,
1174
+ uint32_t count,
1175
+ mongocrypt_status_t *status) {
1176
+ BSON_ASSERT_PARAM(crypto);
1177
+ BSON_ASSERT_PARAM(out);
1178
+
1179
+ if (count != out->len) {
1180
+ CLIENT_ERR("out should have length %d, but has length %d", count, out->len);
1181
+ return false;
1182
+ }
1183
+
1184
+ return _crypto_random(crypto, out, count, status);
1089
1185
  }
1090
1186
 
1091
-
1092
1187
  /* ----------------------------------------------------------------------------
1093
1188
  *
1094
1189
  * _mongocrypt_calculate_deterministic_iv --
@@ -1111,740 +1206,217 @@ _mongocrypt_random (_mongocrypt_crypto_t *crypto,
1111
1206
  *
1112
1207
  * ----------------------------------------------------------------------------
1113
1208
  */
1114
- bool
1115
- _mongocrypt_calculate_deterministic_iv (
1116
- _mongocrypt_crypto_t *crypto,
1117
- const _mongocrypt_buffer_t *key,
1118
- const _mongocrypt_buffer_t *plaintext,
1119
- const _mongocrypt_buffer_t *associated_data,
1120
- _mongocrypt_buffer_t *out,
1121
- mongocrypt_status_t *status)
1122
- {
1123
- _mongocrypt_buffer_t intermediates[3];
1124
- _mongocrypt_buffer_t to_hmac;
1125
- _mongocrypt_buffer_t iv_key;
1126
- uint64_t associated_data_len_be;
1127
- uint8_t tag_storage[64];
1128
- _mongocrypt_buffer_t tag;
1129
- bool ret = false;
1130
-
1131
- _mongocrypt_buffer_init (&to_hmac);
1132
-
1133
- BSON_ASSERT_PARAM (crypto);
1134
- BSON_ASSERT_PARAM (key);
1135
- BSON_ASSERT_PARAM (plaintext);
1136
- BSON_ASSERT_PARAM (associated_data);
1137
- BSON_ASSERT_PARAM (out);
1138
-
1139
- if (MONGOCRYPT_KEY_LEN != key->len) {
1140
- CLIENT_ERR ("key should have length %d, but has length %d\n",
1141
- MONGOCRYPT_KEY_LEN,
1142
- key->len);
1143
- goto done;
1144
- }
1145
- if (MONGOCRYPT_IV_LEN != out->len) {
1146
- CLIENT_ERR ("out should have length %d, but has length %d\n",
1147
- MONGOCRYPT_IV_LEN,
1148
- out->len);
1149
- goto done;
1150
- }
1151
-
1152
- _mongocrypt_buffer_init (&iv_key);
1153
- iv_key.data = key->data + MONGOCRYPT_ENC_KEY_LEN + MONGOCRYPT_MAC_KEY_LEN;
1154
- iv_key.len = MONGOCRYPT_IV_KEY_LEN;
1155
-
1156
- _mongocrypt_buffer_init (&intermediates[0]);
1157
- _mongocrypt_buffer_init (&intermediates[1]);
1158
- _mongocrypt_buffer_init (&intermediates[2]);
1159
- /* Add associated data. */
1160
- intermediates[0].data = associated_data->data;
1161
- intermediates[0].len = associated_data->len;
1162
- /* Add associated data length in bits. */
1163
- /* multiplying a uint32_t by 8 won't bring it anywhere close to UINT64_MAX */
1164
- associated_data_len_be = 8 * (uint64_t) associated_data->len;
1165
- associated_data_len_be = BSON_UINT64_TO_BE (associated_data_len_be);
1166
- intermediates[1].data = (uint8_t *) &associated_data_len_be;
1167
- intermediates[1].len = sizeof (uint64_t);
1168
- /* Add plaintext. */
1169
- intermediates[2].data = (uint8_t *) plaintext->data;
1170
- intermediates[2].len = plaintext->len;
1171
-
1172
- tag.data = tag_storage;
1173
- tag.len = sizeof (tag_storage);
1174
-
1175
- if (!_mongocrypt_buffer_concat (&to_hmac, intermediates, 3)) {
1176
- CLIENT_ERR ("failed to allocate buffer");
1177
- goto done;
1178
- }
1179
-
1180
- if (!_crypto_hmac_sha_512 (crypto, &iv_key, &to_hmac, &tag, status)) {
1181
- goto done;
1182
- }
1183
-
1184
- /* Truncate to IV length */
1185
- memcpy (out->data, tag.data, MONGOCRYPT_IV_LEN);
1186
-
1187
- ret = true;
1209
+ bool _mongocrypt_calculate_deterministic_iv(_mongocrypt_crypto_t *crypto,
1210
+ const _mongocrypt_buffer_t *key,
1211
+ const _mongocrypt_buffer_t *plaintext,
1212
+ const _mongocrypt_buffer_t *associated_data,
1213
+ _mongocrypt_buffer_t *out,
1214
+ mongocrypt_status_t *status) {
1215
+ _mongocrypt_buffer_t intermediates[3];
1216
+ _mongocrypt_buffer_t to_hmac;
1217
+ _mongocrypt_buffer_t iv_key;
1218
+ uint64_t associated_data_len_be;
1219
+ uint8_t tag_storage[64];
1220
+ _mongocrypt_buffer_t tag;
1221
+ bool ret = false;
1222
+
1223
+ _mongocrypt_buffer_init(&to_hmac);
1224
+
1225
+ BSON_ASSERT_PARAM(crypto);
1226
+ BSON_ASSERT_PARAM(key);
1227
+ BSON_ASSERT_PARAM(plaintext);
1228
+ BSON_ASSERT_PARAM(associated_data);
1229
+ BSON_ASSERT_PARAM(out);
1230
+
1231
+ if (MONGOCRYPT_KEY_LEN != key->len) {
1232
+ CLIENT_ERR("key should have length %d, but has length %d\n", MONGOCRYPT_KEY_LEN, key->len);
1233
+ goto done;
1234
+ }
1235
+ if (MONGOCRYPT_IV_LEN != out->len) {
1236
+ CLIENT_ERR("out should have length %d, but has length %d\n", MONGOCRYPT_IV_LEN, out->len);
1237
+ goto done;
1238
+ }
1239
+
1240
+ _mongocrypt_buffer_init(&iv_key);
1241
+ iv_key.data = key->data + MONGOCRYPT_ENC_KEY_LEN + MONGOCRYPT_MAC_KEY_LEN;
1242
+ iv_key.len = MONGOCRYPT_IV_KEY_LEN;
1243
+
1244
+ _mongocrypt_buffer_init(&intermediates[0]);
1245
+ _mongocrypt_buffer_init(&intermediates[1]);
1246
+ _mongocrypt_buffer_init(&intermediates[2]);
1247
+ /* Add associated data. */
1248
+ intermediates[0].data = associated_data->data;
1249
+ intermediates[0].len = associated_data->len;
1250
+ /* Add associated data length in bits. */
1251
+ /* multiplying a uint32_t by 8 won't bring it anywhere close to UINT64_MAX */
1252
+ associated_data_len_be = 8 * (uint64_t)associated_data->len;
1253
+ associated_data_len_be = BSON_UINT64_TO_BE(associated_data_len_be);
1254
+ intermediates[1].data = (uint8_t *)&associated_data_len_be;
1255
+ intermediates[1].len = sizeof(uint64_t);
1256
+ /* Add plaintext. */
1257
+ intermediates[2].data = (uint8_t *)plaintext->data;
1258
+ intermediates[2].len = plaintext->len;
1259
+
1260
+ tag.data = tag_storage;
1261
+ tag.len = sizeof(tag_storage);
1262
+
1263
+ if (!_mongocrypt_buffer_concat(&to_hmac, intermediates, 3)) {
1264
+ CLIENT_ERR("failed to allocate buffer");
1265
+ goto done;
1266
+ }
1267
+
1268
+ if (!_crypto_hmac_sha_512(crypto, &iv_key, &to_hmac, &tag, status)) {
1269
+ goto done;
1270
+ }
1271
+
1272
+ /* Truncate to IV length */
1273
+ memcpy(out->data, tag.data, MONGOCRYPT_IV_LEN);
1274
+
1275
+ ret = true;
1188
1276
  done:
1189
- _mongocrypt_buffer_cleanup (&to_hmac);
1190
- return ret;
1277
+ _mongocrypt_buffer_cleanup(&to_hmac);
1278
+ return ret;
1191
1279
  }
1192
1280
 
1193
- bool
1194
- _mongocrypt_wrap_key (_mongocrypt_crypto_t *crypto,
1195
- _mongocrypt_buffer_t *kek,
1196
- _mongocrypt_buffer_t *dek,
1197
- _mongocrypt_buffer_t *encrypted_dek,
1198
- mongocrypt_status_t *status)
1199
- {
1200
- uint32_t bytes_written;
1201
- _mongocrypt_buffer_t iv = {0};
1202
- bool ret = false;
1203
-
1204
- BSON_ASSERT_PARAM (crypto);
1205
- BSON_ASSERT_PARAM (kek);
1206
- BSON_ASSERT_PARAM (dek);
1207
- BSON_ASSERT_PARAM (encrypted_dek);
1208
-
1209
- _mongocrypt_buffer_init (encrypted_dek);
1210
-
1211
- if (dek->len != MONGOCRYPT_KEY_LEN) {
1212
- CLIENT_ERR ("data encryption key is incorrect length, expected: %" PRIu32
1213
- ", got: %" PRIu32,
1214
- MONGOCRYPT_KEY_LEN,
1215
- dek->len);
1216
- goto done;
1217
- }
1218
-
1219
- _mongocrypt_buffer_resize (
1220
- encrypted_dek, _mongocrypt_calculate_ciphertext_len (dek->len, status));
1221
- _mongocrypt_buffer_resize (&iv, MONGOCRYPT_IV_LEN);
1222
-
1223
- if (!_mongocrypt_random (crypto, &iv, MONGOCRYPT_IV_LEN, status)) {
1224
- goto done;
1225
- }
1226
-
1227
- if (!_mongocrypt_do_encryption (crypto,
1228
- &iv,
1229
- NULL /* associated data. */,
1230
- kek,
1231
- dek,
1232
- encrypted_dek,
1233
- &bytes_written,
1234
- status)) {
1235
- goto done;
1236
- }
1237
-
1238
- ret = true;
1281
+ bool _mongocrypt_wrap_key(_mongocrypt_crypto_t *crypto,
1282
+ _mongocrypt_buffer_t *kek,
1283
+ _mongocrypt_buffer_t *dek,
1284
+ _mongocrypt_buffer_t *encrypted_dek,
1285
+ mongocrypt_status_t *status) {
1286
+ const _mongocrypt_value_encryption_algorithm_t *fle1alg = _mcFLE1Algorithm();
1287
+ uint32_t bytes_written;
1288
+ _mongocrypt_buffer_t iv = {0};
1289
+ bool ret = false;
1290
+
1291
+ BSON_ASSERT_PARAM(crypto);
1292
+ BSON_ASSERT_PARAM(kek);
1293
+ BSON_ASSERT_PARAM(dek);
1294
+ BSON_ASSERT_PARAM(encrypted_dek);
1295
+
1296
+ _mongocrypt_buffer_init(encrypted_dek);
1297
+
1298
+ if (dek->len != MONGOCRYPT_KEY_LEN) {
1299
+ CLIENT_ERR("data encryption key is incorrect length, expected: %" PRIu32 ", got: %" PRIu32,
1300
+ MONGOCRYPT_KEY_LEN,
1301
+ dek->len);
1302
+ goto done;
1303
+ }
1304
+
1305
+ // _mongocrypt_wrap_key() uses FLE1 algorithm parameters.
1306
+ _mongocrypt_buffer_resize(encrypted_dek, fle1alg->get_ciphertext_len(dek->len, status));
1307
+ _mongocrypt_buffer_resize(&iv, MONGOCRYPT_IV_LEN);
1308
+
1309
+ if (!_mongocrypt_random(crypto, &iv, MONGOCRYPT_IV_LEN, status)) {
1310
+ goto done;
1311
+ }
1312
+
1313
+ if (!fle1alg
1314
+ ->do_encrypt(crypto, &iv, NULL /* associated data. */, kek, dek, encrypted_dek, &bytes_written, status)) {
1315
+ goto done;
1316
+ }
1317
+
1318
+ ret = true;
1239
1319
  done:
1240
- _mongocrypt_buffer_cleanup (&iv);
1241
- return ret;
1320
+ _mongocrypt_buffer_cleanup(&iv);
1321
+ return ret;
1242
1322
  }
1243
1323
 
1244
- bool
1245
- _mongocrypt_unwrap_key (_mongocrypt_crypto_t *crypto,
1246
- _mongocrypt_buffer_t *kek,
1247
- _mongocrypt_buffer_t *encrypted_dek,
1248
- _mongocrypt_buffer_t *dek,
1249
- mongocrypt_status_t *status)
1250
- {
1251
- uint32_t bytes_written;
1252
-
1253
- BSON_ASSERT_PARAM (crypto);
1254
- BSON_ASSERT_PARAM (kek);
1255
- BSON_ASSERT_PARAM (dek);
1256
- BSON_ASSERT_PARAM (encrypted_dek);
1257
-
1258
- _mongocrypt_buffer_init (dek);
1259
- _mongocrypt_buffer_resize (
1260
- dek, _mongocrypt_calculate_plaintext_len (encrypted_dek->len, status));
1261
-
1262
- if (!_mongocrypt_do_decryption (crypto,
1263
- NULL /* associated data. */,
1264
- kek,
1265
- encrypted_dek,
1266
- dek,
1267
- &bytes_written,
1268
- status)) {
1269
- return false;
1270
- }
1271
- dek->len = bytes_written;
1272
-
1273
- if (dek->len != MONGOCRYPT_KEY_LEN) {
1274
- CLIENT_ERR ("decrypted key is incorrect length, expected: %" PRIu32
1275
- ", got: %" PRIu32,
1276
- MONGOCRYPT_KEY_LEN,
1277
- dek->len);
1278
- return false;
1279
- }
1280
- return true;
1324
+ bool _mongocrypt_unwrap_key(_mongocrypt_crypto_t *crypto,
1325
+ _mongocrypt_buffer_t *kek,
1326
+ _mongocrypt_buffer_t *encrypted_dek,
1327
+ _mongocrypt_buffer_t *dek,
1328
+ mongocrypt_status_t *status) {
1329
+ const _mongocrypt_value_encryption_algorithm_t *fle1alg = _mcFLE1Algorithm();
1330
+ uint32_t bytes_written;
1331
+
1332
+ BSON_ASSERT_PARAM(crypto);
1333
+ BSON_ASSERT_PARAM(kek);
1334
+ BSON_ASSERT_PARAM(dek);
1335
+ BSON_ASSERT_PARAM(encrypted_dek);
1336
+
1337
+ // _mongocrypt_wrap_key() uses FLE1 algorithm parameters.
1338
+ _mongocrypt_buffer_init(dek);
1339
+ _mongocrypt_buffer_resize(dek, fle1alg->get_plaintext_len(encrypted_dek->len, status));
1340
+
1341
+ if (!fle1alg->do_decrypt(crypto, NULL /* associated data. */, kek, encrypted_dek, dek, &bytes_written, status)) {
1342
+ return false;
1343
+ }
1344
+ dek->len = bytes_written;
1345
+
1346
+ if (dek->len != MONGOCRYPT_KEY_LEN) {
1347
+ CLIENT_ERR("decrypted key is incorrect length, expected: %" PRIu32 ", got: %" PRIu32,
1348
+ MONGOCRYPT_KEY_LEN,
1349
+ dek->len);
1350
+ return false;
1351
+ }
1352
+ return true;
1281
1353
  }
1282
1354
 
1283
- bool
1284
- _mongocrypt_hmac_sha_256 (_mongocrypt_crypto_t *crypto,
1285
- const _mongocrypt_buffer_t *key,
1286
- const _mongocrypt_buffer_t *in,
1287
- _mongocrypt_buffer_t *out,
1288
- mongocrypt_status_t *status)
1289
- {
1290
- BSON_ASSERT_PARAM (crypto);
1291
- BSON_ASSERT_PARAM (key);
1292
- BSON_ASSERT_PARAM (in);
1293
- BSON_ASSERT_PARAM (out);
1294
-
1295
- if (key->len != MONGOCRYPT_MAC_KEY_LEN) {
1296
- CLIENT_ERR ("invalid hmac_sha_256 key length. Got %" PRIu32
1297
- ", expected: %" PRIu32,
1298
- key->len,
1299
- MONGOCRYPT_MAC_KEY_LEN);
1300
- return false;
1301
- }
1302
-
1303
- if (crypto->hooks_enabled) {
1304
- mongocrypt_binary_t key_bin, out_bin, in_bin;
1305
- _mongocrypt_buffer_to_binary (key, &key_bin);
1306
- _mongocrypt_buffer_to_binary (out, &out_bin);
1307
- _mongocrypt_buffer_to_binary (in, &in_bin);
1308
-
1309
- return crypto->hmac_sha_256 (
1310
- crypto->ctx, &key_bin, &in_bin, &out_bin, status);
1311
- }
1312
- return _native_crypto_hmac_sha_256 (key, in, out, status);
1313
- }
1355
+ /* This implementation avoids modulo bias. It is based on arc4random_uniform:
1356
+ https://github.com/openbsd/src/blob/2207c4325726fdc5c4bcd0011af0fdf7d3dab137/lib/libc/crypt/arc4random_uniform.c#L33
1357
+ */
1358
+ bool _mongocrypt_random_uint64(_mongocrypt_crypto_t *crypto,
1359
+ uint64_t exclusive_upper_bound,
1360
+ uint64_t *out,
1361
+ mongocrypt_status_t *status) {
1362
+ BSON_ASSERT_PARAM(crypto);
1363
+ BSON_ASSERT_PARAM(out);
1314
1364
 
1315
- bool
1316
- _mongocrypt_fle2aead_do_encryption (_mongocrypt_crypto_t *crypto,
1317
- const _mongocrypt_buffer_t *iv,
1318
- const _mongocrypt_buffer_t *associated_data,
1319
- const _mongocrypt_buffer_t *key,
1320
- const _mongocrypt_buffer_t *plaintext,
1321
- _mongocrypt_buffer_t *ciphertext,
1322
- uint32_t *bytes_written,
1323
- mongocrypt_status_t *status)
1324
- {
1325
- BSON_ASSERT_PARAM (crypto);
1326
- BSON_ASSERT_PARAM (iv);
1327
- BSON_ASSERT_PARAM (associated_data);
1328
- BSON_ASSERT_PARAM (key);
1329
- BSON_ASSERT_PARAM (plaintext);
1330
- BSON_ASSERT_PARAM (ciphertext);
1331
- BSON_ASSERT_PARAM (bytes_written);
1332
-
1333
- if (ciphertext->len !=
1334
- _mongocrypt_fle2aead_calculate_ciphertext_len (plaintext->len, status)) {
1335
- CLIENT_ERR ("output ciphertext must be allocated with %" PRIu32 " bytes",
1336
- _mongocrypt_fle2aead_calculate_ciphertext_len (plaintext->len,
1337
- status));
1338
- return false;
1339
- }
1340
-
1341
- if (plaintext->len <= 0) {
1342
- CLIENT_ERR ("input plaintext too small. Must be more than zero bytes.");
1343
- return false;
1344
- }
1345
-
1346
- if (MONGOCRYPT_IV_LEN != iv->len) {
1347
- CLIENT_ERR ("IV must be length %d, but is length %" PRIu32,
1348
- MONGOCRYPT_IV_LEN,
1349
- iv->len);
1350
- return false;
1351
- }
1352
- if (MONGOCRYPT_KEY_LEN != key->len) {
1353
- CLIENT_ERR ("key must be length %d, but is length %" PRIu32,
1354
- MONGOCRYPT_KEY_LEN,
1355
- key->len);
1356
- return false;
1357
- }
1358
-
1359
- memset (ciphertext->data, 0, ciphertext->len);
1360
- *bytes_written = 0;
1361
-
1362
- /* Declare variable names matching [AEAD with
1363
- * CTR](https://docs.google.com/document/d/1eCU7R8Kjr-mdyz6eKvhNIDVmhyYQcAaLtTfHeK7a_vE/).
1364
- */
1365
- /* M is the input plaintext. */
1366
- _mongocrypt_buffer_t M;
1367
- if (!_mongocrypt_buffer_from_subrange (&M, plaintext, 0, plaintext->len)) {
1368
- CLIENT_ERR ("unable to create M view from plaintext");
1369
- return false;
1370
- }
1371
- /* Ke is 32 byte Key for encryption. */
1372
- _mongocrypt_buffer_t Ke;
1373
- if (!_mongocrypt_buffer_from_subrange (
1374
- &Ke, key, 0, MONGOCRYPT_ENC_KEY_LEN)) {
1375
- CLIENT_ERR ("unable to create Ke view from key");
1376
- return false;
1377
- }
1378
- /* IV is 16 byte IV. */
1379
- _mongocrypt_buffer_t IV;
1380
- if (!_mongocrypt_buffer_from_subrange (&IV, iv, 0, iv->len)) {
1381
- CLIENT_ERR ("unable to create IV view from iv");
1382
- return false;
1383
- }
1384
- /* Km is 32 byte Key for HMAC. */
1385
- _mongocrypt_buffer_t Km;
1386
- if (!_mongocrypt_buffer_from_subrange (
1387
- &Km, key, MONGOCRYPT_ENC_KEY_LEN, MONGOCRYPT_MAC_KEY_LEN)) {
1388
- CLIENT_ERR ("unable to create Km view from key");
1389
- return false;
1390
- }
1391
- /* AD is Associated Data. */
1392
- _mongocrypt_buffer_t AD;
1393
- if (!_mongocrypt_buffer_from_subrange (
1394
- &AD, associated_data, 0, associated_data->len)) {
1395
- CLIENT_ERR ("unable to create AD view from associated_data");
1396
- return false;
1397
- }
1398
- /* C is the output ciphertext. */
1399
- _mongocrypt_buffer_t C;
1400
- if (!_mongocrypt_buffer_from_subrange (&C, ciphertext, 0, ciphertext->len)) {
1401
- CLIENT_ERR ("unable to create C view from ciphertext");
1402
- return false;
1403
- }
1404
- /* S is the output of the symmetric cipher. It is appended after IV in C. */
1405
- _mongocrypt_buffer_t S;
1406
- BSON_ASSERT (C.len >= MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN);
1407
- if (!_mongocrypt_buffer_from_subrange (&S,
1408
- &C,
1409
- MONGOCRYPT_IV_LEN,
1410
- C.len - MONGOCRYPT_IV_LEN -
1411
- MONGOCRYPT_HMAC_LEN)) {
1412
- CLIENT_ERR ("unable to create S view from C");
1413
- return false;
1414
- }
1415
- uint32_t S_bytes_written = 0;
1416
- /* T is the output of the HMAC tag. It is appended after S in C. */
1417
- _mongocrypt_buffer_t T;
1418
- if (!_mongocrypt_buffer_from_subrange (
1419
- &T, &C, C.len - MONGOCRYPT_HMAC_LEN, MONGOCRYPT_HMAC_LEN)) {
1420
- CLIENT_ERR ("unable to create T view from C");
1421
- return false;
1422
- }
1423
-
1424
- /* Compute S = AES-CTR.Enc(Ke, IV, M). */
1425
- if (!_crypto_aes_256_ctr_encrypt (
1426
- crypto,
1427
- (aes_256_args_t){.key = &Ke,
1428
- .iv = &IV,
1429
- .in = &M,
1430
- .out = &S,
1431
- .bytes_written = &S_bytes_written,
1432
- .status = status})) {
1433
- return false;
1434
- }
1435
-
1436
- /* Compute T = HMAC-SHA256(Km, AD || IV || S). */
1437
- {
1438
- _mongocrypt_buffer_t hmac_inputs[] = {AD, IV, S};
1439
- _mongocrypt_buffer_t hmac_input = {0};
1440
- _mongocrypt_buffer_concat (&hmac_input, hmac_inputs, 3);
1441
- if (!_mongocrypt_hmac_sha_256 (crypto, &Km, &hmac_input, &T, status)) {
1442
- _mongocrypt_buffer_cleanup (&hmac_input);
1443
- return false;
1444
- }
1445
- _mongocrypt_buffer_cleanup (&hmac_input);
1446
- }
1447
-
1448
- /* Output C = IV || S || T. */
1449
- /* S and T are already in C. Prepend IV. */
1450
- memmove (C.data, IV.data, MONGOCRYPT_IV_LEN);
1451
-
1452
- *bytes_written = MONGOCRYPT_IV_LEN + S_bytes_written + MONGOCRYPT_HMAC_LEN;
1453
- return true;
1454
- }
1365
+ *out = 0;
1455
1366
 
1456
- bool
1457
- _mongocrypt_fle2aead_do_decryption (_mongocrypt_crypto_t *crypto,
1458
- const _mongocrypt_buffer_t *associated_data,
1459
- const _mongocrypt_buffer_t *key,
1460
- const _mongocrypt_buffer_t *ciphertext,
1461
- _mongocrypt_buffer_t *plaintext,
1462
- uint32_t *bytes_written,
1463
- mongocrypt_status_t *status)
1464
- {
1465
- BSON_ASSERT_PARAM (crypto);
1466
- BSON_ASSERT_PARAM (associated_data);
1467
- BSON_ASSERT_PARAM (key);
1468
- BSON_ASSERT_PARAM (ciphertext);
1469
- BSON_ASSERT_PARAM (plaintext);
1470
- BSON_ASSERT_PARAM (bytes_written);
1471
-
1472
- if (ciphertext->len <= MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN) {
1473
- CLIENT_ERR ("input ciphertext too small. Must be more than %" PRIu32
1474
- " bytes",
1475
- MONGOCRYPT_IV_LEN + MONGOCRYPT_HMAC_LEN);
1476
- return false;
1477
- }
1478
-
1479
- if (plaintext->len !=
1480
- _mongocrypt_fle2aead_calculate_plaintext_len (ciphertext->len, status)) {
1481
- CLIENT_ERR ("output plaintext must be allocated with %" PRIu32 " bytes",
1482
- _mongocrypt_fle2aead_calculate_plaintext_len (ciphertext->len,
1483
- status));
1484
- return false;
1485
- }
1486
-
1487
- if (MONGOCRYPT_KEY_LEN != key->len) {
1488
- CLIENT_ERR ("key must be length %d, but is length %" PRIu32,
1489
- MONGOCRYPT_KEY_LEN,
1490
- key->len);
1491
- return false;
1492
- }
1493
-
1494
- memset (plaintext->data, 0, plaintext->len);
1495
- *bytes_written = 0;
1496
-
1497
- /* Declare variable names matching [AEAD with
1498
- * CTR](https://docs.google.com/document/d/1eCU7R8Kjr-mdyz6eKvhNIDVmhyYQcAaLtTfHeK7a_vE/).
1499
- */
1500
- /* C is the input ciphertext. */
1501
- _mongocrypt_buffer_t C;
1502
- if (!_mongocrypt_buffer_from_subrange (&C, ciphertext, 0, ciphertext->len)) {
1503
- CLIENT_ERR ("unable to create C view from ciphertext");
1504
- return false;
1505
- }
1506
- /* IV is 16 byte IV. It is the first part of C. */
1507
- _mongocrypt_buffer_t IV;
1508
- if (!_mongocrypt_buffer_from_subrange (
1509
- &IV, ciphertext, 0, MONGOCRYPT_IV_LEN)) {
1510
- CLIENT_ERR ("unable to create IV view from ciphertext");
1511
- return false;
1512
- }
1513
- /* S is the symmetric cipher output from C. It is after the IV in C. */
1514
- _mongocrypt_buffer_t S;
1515
- if (!_mongocrypt_buffer_from_subrange (&S,
1516
- ciphertext,
1517
- MONGOCRYPT_IV_LEN,
1518
- C.len - MONGOCRYPT_IV_LEN -
1519
- MONGOCRYPT_HMAC_LEN)) {
1520
- CLIENT_ERR ("unable to create S view from C");
1521
- return false;
1522
- }
1523
- /* T is the HMAC tag from C. It is after S in C. */
1524
- _mongocrypt_buffer_t T;
1525
- if (!_mongocrypt_buffer_from_subrange (
1526
- &T, &C, C.len - MONGOCRYPT_HMAC_LEN, MONGOCRYPT_HMAC_LEN)) {
1527
- CLIENT_ERR ("unable to create T view from C");
1528
- return false;
1529
- }
1530
- /* Tp is the computed HMAC of the input. */
1531
- _mongocrypt_buffer_t Tp = {0};
1532
- /* M is the output plaintext. */
1533
- _mongocrypt_buffer_t M;
1534
- if (!_mongocrypt_buffer_from_subrange (&M, plaintext, 0, plaintext->len)) {
1535
- CLIENT_ERR ("unable to create M view from plaintext");
1536
- return false;
1537
- }
1538
- /* Ke is 32 byte Key for encryption. */
1539
- _mongocrypt_buffer_t Ke;
1540
- if (!_mongocrypt_buffer_from_subrange (
1541
- &Ke, key, 0, MONGOCRYPT_ENC_KEY_LEN)) {
1542
- CLIENT_ERR ("unable to create Ke view from key");
1543
- return false;
1544
- }
1545
- /* Km is 32 byte Key for HMAC. */
1546
- _mongocrypt_buffer_t Km;
1547
- if (!_mongocrypt_buffer_from_subrange (
1548
- &Km, key, MONGOCRYPT_ENC_KEY_LEN, MONGOCRYPT_MAC_KEY_LEN)) {
1549
- CLIENT_ERR ("unable to create Km view from key");
1550
- return false;
1551
- }
1552
- /* AD is Associated Data. */
1553
- _mongocrypt_buffer_t AD;
1554
- if (!_mongocrypt_buffer_from_subrange (
1555
- &AD, associated_data, 0, associated_data->len)) {
1556
- CLIENT_ERR ("unable to create AD view from associated_data");
1557
- return false;
1558
- }
1559
-
1560
- /* Compute Tp = HMAC-SHA256(Km, AD || IV || S). Check that it matches input
1561
- * ciphertext T. */
1562
- {
1563
- _mongocrypt_buffer_t hmac_inputs[] = {AD, IV, S};
1564
- _mongocrypt_buffer_t hmac_input = {0};
1565
- _mongocrypt_buffer_concat (&hmac_input, hmac_inputs, 3);
1566
- _mongocrypt_buffer_resize (&Tp, MONGOCRYPT_HMAC_LEN);
1567
- if (!_mongocrypt_hmac_sha_256 (crypto, &Km, &hmac_input, &Tp, status)) {
1568
- _mongocrypt_buffer_cleanup (&hmac_input);
1569
- _mongocrypt_buffer_cleanup (&Tp);
1570
- return false;
1571
- }
1572
- if (0 != _mongocrypt_buffer_cmp (&T, &Tp)) {
1573
- CLIENT_ERR ("decryption error");
1574
- _mongocrypt_buffer_cleanup (&hmac_input);
1575
- _mongocrypt_buffer_cleanup (&Tp);
1576
- return false;
1577
- }
1578
- _mongocrypt_buffer_cleanup (&hmac_input);
1579
- _mongocrypt_buffer_cleanup (&Tp);
1580
- }
1581
-
1582
- /* Compute and output M = AES-CTR.Dec(Ke, S) */
1583
- if (!_crypto_aes_256_ctr_decrypt (
1584
- crypto,
1585
- (aes_256_args_t){.key = &Ke,
1586
- .iv = &IV,
1587
- .in = &S,
1588
- .out = &M,
1589
- .bytes_written = bytes_written,
1590
- .status = status})) {
1591
- return false;
1592
- }
1593
-
1594
- return true;
1595
- }
1367
+ if (exclusive_upper_bound < 2) {
1368
+ *out = 0;
1369
+ return true;
1370
+ }
1596
1371
 
1597
- bool
1598
- _mongocrypt_fle2_do_encryption (_mongocrypt_crypto_t *crypto,
1599
- const _mongocrypt_buffer_t *iv,
1600
- const _mongocrypt_buffer_t *key,
1601
- const _mongocrypt_buffer_t *plaintext,
1602
- _mongocrypt_buffer_t *ciphertext,
1603
- uint32_t *bytes_written,
1604
- mongocrypt_status_t *status)
1605
- {
1606
- BSON_ASSERT_PARAM (crypto);
1607
- BSON_ASSERT_PARAM (iv);
1608
- BSON_ASSERT_PARAM (key);
1609
- BSON_ASSERT_PARAM (plaintext);
1610
- BSON_ASSERT_PARAM (ciphertext);
1611
- BSON_ASSERT_PARAM (bytes_written);
1612
-
1613
- if (ciphertext->len !=
1614
- _mongocrypt_fle2_calculate_ciphertext_len (plaintext->len, status)) {
1615
- CLIENT_ERR (
1616
- "output ciphertext must be allocated with %" PRIu32 " bytes",
1617
- _mongocrypt_fle2_calculate_ciphertext_len (plaintext->len, status));
1618
- return false;
1619
- }
1620
-
1621
- if (plaintext->len <= 0) {
1622
- CLIENT_ERR ("input plaintext too small. Must be more than zero bytes.");
1623
- return false;
1624
- }
1625
-
1626
- if (MONGOCRYPT_IV_LEN != iv->len) {
1627
- CLIENT_ERR ("IV must be length %d, but is length %" PRIu32,
1628
- MONGOCRYPT_IV_LEN,
1629
- iv->len);
1630
- return false;
1631
- }
1632
- if (MONGOCRYPT_ENC_KEY_LEN != key->len) {
1633
- CLIENT_ERR ("key must be length %d, but is length %" PRIu32,
1634
- MONGOCRYPT_ENC_KEY_LEN,
1635
- key->len);
1636
- return false;
1637
- }
1638
-
1639
- BSON_ASSERT (ciphertext->len >= MONGOCRYPT_IV_LEN);
1640
- memset (ciphertext->data + MONGOCRYPT_IV_LEN,
1641
- 0,
1642
- ciphertext->len - MONGOCRYPT_IV_LEN);
1643
- *bytes_written = 0;
1644
-
1645
- /* Declare variable names matching [AEAD with
1646
- * CTR](https://docs.google.com/document/d/1eCU7R8Kjr-mdyz6eKvhNIDVmhyYQcAaLtTfHeK7a_vE/).
1647
- */
1648
- /* M is the input plaintext. */
1649
- _mongocrypt_buffer_t M = *plaintext;
1650
- /* Ke is 32 byte Key for encryption. */
1651
- _mongocrypt_buffer_t Ke = *key;
1652
- /* IV is 16 byte IV. */
1653
- _mongocrypt_buffer_t IV = *iv;
1654
- /* C is the output ciphertext. */
1655
- _mongocrypt_buffer_t C = *ciphertext;
1656
- /* S is the output of the symmetric cipher. It is appended after IV in C. */
1657
- _mongocrypt_buffer_t S;
1658
- if (!_mongocrypt_buffer_from_subrange (
1659
- &S, &C, MONGOCRYPT_IV_LEN, C.len - MONGOCRYPT_IV_LEN)) {
1660
- CLIENT_ERR ("unable to create S view from C");
1661
- return false;
1662
- }
1663
- uint32_t S_bytes_written = 0;
1664
-
1665
- /* Compute S = AES-CTR.Enc(Ke, IV, M). */
1666
- if (!_crypto_aes_256_ctr_encrypt (
1667
- crypto,
1668
- (aes_256_args_t){.key = &Ke,
1669
- .iv = &IV,
1670
- .in = &M,
1671
- .out = &S,
1672
- .bytes_written = &S_bytes_written,
1673
- .status = status})) {
1674
- return false;
1675
- }
1676
-
1677
- if (S_bytes_written != M.len) {
1678
- CLIENT_ERR ("expected S_bytes_written=%" PRIu32 " got %" PRIu32,
1679
- M.len,
1680
- S_bytes_written);
1681
- return false;
1682
- }
1683
-
1684
- /* Output C = IV || S. */
1685
- /* S is already in C. Prepend IV. */
1686
- memmove (C.data, IV.data, MONGOCRYPT_IV_LEN);
1687
-
1688
- *bytes_written = MONGOCRYPT_IV_LEN + S_bytes_written;
1689
- return true;
1690
- }
1372
+ /* 2**64 % x == (2**64 - x) % x */
1373
+ uint64_t min = (0 - exclusive_upper_bound) % exclusive_upper_bound;
1691
1374
 
1692
- bool
1693
- _mongocrypt_fle2_do_decryption (_mongocrypt_crypto_t *crypto,
1694
- const _mongocrypt_buffer_t *key,
1695
- const _mongocrypt_buffer_t *ciphertext,
1696
- _mongocrypt_buffer_t *plaintext,
1697
- uint32_t *bytes_written,
1698
- mongocrypt_status_t *status)
1699
- {
1700
- BSON_ASSERT_PARAM (crypto);
1701
- BSON_ASSERT_PARAM (key);
1702
- BSON_ASSERT_PARAM (ciphertext);
1703
- BSON_ASSERT_PARAM (plaintext);
1704
- BSON_ASSERT_PARAM (bytes_written);
1705
-
1706
- if (ciphertext->len <= MONGOCRYPT_IV_LEN) {
1707
- CLIENT_ERR ("input ciphertext too small. Must be more than %" PRIu32
1708
- " bytes",
1709
- MONGOCRYPT_IV_LEN);
1710
- return false;
1711
- }
1712
-
1713
- if (plaintext->len !=
1714
- _mongocrypt_fle2_calculate_plaintext_len (ciphertext->len, status)) {
1715
- CLIENT_ERR (
1716
- "output plaintext must be allocated with %" PRIu32 " bytes",
1717
- _mongocrypt_fle2_calculate_plaintext_len (ciphertext->len, status));
1718
- return false;
1719
- }
1720
-
1721
- if (MONGOCRYPT_ENC_KEY_LEN != key->len) {
1722
- CLIENT_ERR ("key must be length %d, but is length %" PRIu32,
1723
- MONGOCRYPT_ENC_KEY_LEN,
1724
- key->len);
1725
- return false;
1726
- }
1727
-
1728
- memset (plaintext->data, 0, plaintext->len);
1729
- *bytes_written = 0;
1730
-
1731
- /* Declare variable names matching [AEAD with
1732
- * CTR](https://docs.google.com/document/d/1eCU7R8Kjr-mdyz6eKvhNIDVmhyYQcAaLtTfHeK7a_vE/).
1733
- */
1734
- /* C is the input ciphertext. */
1735
- _mongocrypt_buffer_t C = *ciphertext;
1736
- /* IV is 16 byte IV. It is the first part of C. */
1737
- _mongocrypt_buffer_t IV;
1738
- if (!_mongocrypt_buffer_from_subrange (
1739
- &IV, ciphertext, 0, MONGOCRYPT_IV_LEN)) {
1740
- CLIENT_ERR ("unable to create IV view from ciphertext");
1741
- return false;
1742
- }
1743
- /* S is the symmetric cipher output from C. It is after the IV in C. */
1744
- _mongocrypt_buffer_t S;
1745
- if (!_mongocrypt_buffer_from_subrange (
1746
- &S, ciphertext, MONGOCRYPT_IV_LEN, C.len - MONGOCRYPT_IV_LEN)) {
1747
- CLIENT_ERR ("unable to create S view from C");
1748
- return false;
1749
- }
1750
- /* M is the output plaintext. */
1751
- _mongocrypt_buffer_t M = *plaintext;
1752
- /* Ke is 32 byte Key for encryption. */
1753
- _mongocrypt_buffer_t Ke = *key;
1754
-
1755
- /* Compute and output M = AES-CTR.Dec(Ke, S) */
1756
- if (!_crypto_aes_256_ctr_decrypt (
1757
- crypto,
1758
- (aes_256_args_t){.key = &Ke,
1759
- .iv = &IV,
1760
- .in = &S,
1761
- .out = &M,
1762
- .bytes_written = bytes_written,
1763
- .status = status})) {
1764
- return false;
1765
- }
1766
-
1767
- if (*bytes_written != S.len) {
1768
- CLIENT_ERR ("expected bytes_written=%" PRIu32 " got %" PRIu32,
1769
- S.len,
1770
- *bytes_written);
1771
- return false;
1772
- }
1773
-
1774
- return true;
1775
- }
1375
+ _mongocrypt_buffer_t rand_u64_buf;
1376
+ _mongocrypt_buffer_init(&rand_u64_buf);
1377
+ _mongocrypt_buffer_resize(&rand_u64_buf, (uint32_t)sizeof(uint64_t));
1776
1378
 
1777
- /* This implementation avoids modulo bias. It is based on arc4random_uniform:
1778
- https://github.com/openbsd/src/blob/2207c4325726fdc5c4bcd0011af0fdf7d3dab137/lib/libc/crypt/arc4random_uniform.c#L33
1779
- */
1780
- bool
1781
- _mongocrypt_random_uint64 (_mongocrypt_crypto_t *crypto,
1782
- uint64_t exclusive_upper_bound,
1783
- uint64_t *out,
1784
- mongocrypt_status_t *status)
1785
- {
1786
- BSON_ASSERT_PARAM (crypto);
1787
- BSON_ASSERT_PARAM (out);
1788
-
1789
- *out = 0;
1790
-
1791
- if (exclusive_upper_bound < 2) {
1792
- *out = 0;
1793
- return true;
1794
- }
1795
-
1796
- /* 2**64 % x == (2**64 - x) % x */
1797
- uint64_t min = (0 - exclusive_upper_bound) % exclusive_upper_bound;
1798
-
1799
- _mongocrypt_buffer_t rand_u64_buf;
1800
- _mongocrypt_buffer_init (&rand_u64_buf);
1801
- _mongocrypt_buffer_resize (&rand_u64_buf, (uint32_t) sizeof (uint64_t));
1802
-
1803
- uint64_t rand_u64;
1804
- for (;;) {
1805
- if (!_mongocrypt_random (
1806
- crypto, &rand_u64_buf, rand_u64_buf.len, status)) {
1807
- _mongocrypt_buffer_cleanup (&rand_u64_buf);
1808
- return false;
1809
- }
1810
-
1811
- memcpy (&rand_u64, rand_u64_buf.data, rand_u64_buf.len);
1812
-
1813
- if (rand_u64 >= min) {
1814
- break;
1815
- }
1816
- }
1817
-
1818
- *out = rand_u64 % exclusive_upper_bound;
1819
-
1820
- _mongocrypt_buffer_cleanup (&rand_u64_buf);
1821
- return true;
1379
+ uint64_t rand_u64;
1380
+ for (;;) {
1381
+ if (!_mongocrypt_random(crypto, &rand_u64_buf, rand_u64_buf.len, status)) {
1382
+ _mongocrypt_buffer_cleanup(&rand_u64_buf);
1383
+ return false;
1384
+ }
1385
+
1386
+ memcpy(&rand_u64, rand_u64_buf.data, rand_u64_buf.len);
1387
+
1388
+ if (rand_u64 >= min) {
1389
+ break;
1390
+ }
1391
+ }
1392
+
1393
+ *out = rand_u64 % exclusive_upper_bound;
1394
+
1395
+ _mongocrypt_buffer_cleanup(&rand_u64_buf);
1396
+ return true;
1822
1397
  }
1823
1398
 
1824
- bool
1825
- _mongocrypt_random_int64 (_mongocrypt_crypto_t *crypto,
1826
- int64_t exclusive_upper_bound,
1827
- int64_t *out,
1828
- mongocrypt_status_t *status)
1829
- {
1830
- BSON_ASSERT_PARAM (crypto);
1831
- BSON_ASSERT_PARAM (out);
1832
-
1833
- if (exclusive_upper_bound <= 0) {
1834
- CLIENT_ERR ("Expected exclusive_upper_bound > 0");
1835
- return false;
1836
- }
1837
-
1838
- uint64_t u64_exclusive_upper_bound = (uint64_t) exclusive_upper_bound;
1839
- uint64_t u64_out;
1840
-
1841
- if (!_mongocrypt_random_uint64 (
1842
- crypto, u64_exclusive_upper_bound, &u64_out, status)) {
1843
- return false;
1844
- }
1845
-
1846
- /* Zero the leading bit to ensure rand_i64 is non-negative. */
1847
- u64_out &= (~(1ull << 63));
1848
- *out = (int64_t) u64_out;
1849
- return true;
1399
+ bool _mongocrypt_random_int64(_mongocrypt_crypto_t *crypto,
1400
+ int64_t exclusive_upper_bound,
1401
+ int64_t *out,
1402
+ mongocrypt_status_t *status) {
1403
+ BSON_ASSERT_PARAM(crypto);
1404
+ BSON_ASSERT_PARAM(out);
1405
+
1406
+ if (exclusive_upper_bound <= 0) {
1407
+ CLIENT_ERR("Expected exclusive_upper_bound > 0");
1408
+ return false;
1409
+ }
1410
+
1411
+ uint64_t u64_exclusive_upper_bound = (uint64_t)exclusive_upper_bound;
1412
+ uint64_t u64_out;
1413
+
1414
+ if (!_mongocrypt_random_uint64(crypto, u64_exclusive_upper_bound, &u64_out, status)) {
1415
+ return false;
1416
+ }
1417
+
1418
+ /* Zero the leading bit to ensure rand_i64 is non-negative. */
1419
+ u64_out &= (~(1ull << 63));
1420
+ *out = (int64_t)u64_out;
1421
+ return true;
1850
1422
  }