ruby_olm 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (194) hide show
  1. checksums.yaml +7 -0
  2. data/ext/ruby_olm/ext_lib_olm/ext_account.c +274 -0
  3. data/ext/ruby_olm/ext_lib_olm/ext_lib_olm.c +51 -0
  4. data/ext/ruby_olm/ext_lib_olm/ext_lib_olm.h +13 -0
  5. data/ext/ruby_olm/ext_lib_olm/ext_session.c +363 -0
  6. data/ext/ruby_olm/ext_lib_olm/ext_utility.c +69 -0
  7. data/ext/ruby_olm/ext_lib_olm/extconf.rb +69 -0
  8. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_account.cpp +695 -0
  9. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_account.h +56 -0
  10. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +654 -0
  11. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_inbound_group_session.h +51 -0
  12. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_jni.h +81 -0
  13. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_jni_helper.cpp +224 -0
  14. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_jni_helper.h +30 -0
  15. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_manager.cpp +35 -0
  16. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_manager.h +36 -0
  17. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +563 -0
  18. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_outbound_group_session.h +49 -0
  19. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_pk.cpp +716 -0
  20. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_pk.h +48 -0
  21. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_session.cpp +977 -0
  22. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_session.h +59 -0
  23. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_utility.cpp +236 -0
  24. data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_utility.h +40 -0
  25. data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_decode_message.cpp +14 -0
  26. data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_decrypt.cpp +65 -0
  27. data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_group_decrypt.cpp +73 -0
  28. data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_unpickle_account.cpp +14 -0
  29. data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_unpickle_session.cpp +14 -0
  30. data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/include/fuzzing.hh +82 -0
  31. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/account.hh +160 -0
  32. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/base64.h +77 -0
  33. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/base64.hh +63 -0
  34. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/cipher.h +138 -0
  35. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/crypto.h +202 -0
  36. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/error.h +72 -0
  37. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/inbound_group_session.h +235 -0
  38. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/list.hh +119 -0
  39. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/megolm.h +95 -0
  40. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/memory.h +41 -0
  41. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/memory.hh +90 -0
  42. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/message.h +93 -0
  43. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/message.hh +138 -0
  44. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/olm.h +451 -0
  45. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/olm.hh +4 -0
  46. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/outbound_group_session.h +181 -0
  47. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/pickle.h +90 -0
  48. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/pickle.hh +149 -0
  49. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/pickle_encoding.h +76 -0
  50. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/pk.h +214 -0
  51. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/ratchet.hh +184 -0
  52. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/session.hh +156 -0
  53. data/ext/ruby_olm/ext_lib_olm/olm/include/olm/utility.hh +61 -0
  54. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/aes.c +1073 -0
  55. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/aes.h +123 -0
  56. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/aes_test.c +276 -0
  57. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/arcfour.c +45 -0
  58. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/arcfour.h +30 -0
  59. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/arcfour_test.c +47 -0
  60. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/base64.c +135 -0
  61. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/base64.h +27 -0
  62. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/base64_test.c +54 -0
  63. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/blowfish.c +269 -0
  64. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/blowfish.h +32 -0
  65. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/blowfish_test.c +68 -0
  66. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/des.c +269 -0
  67. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/des.h +37 -0
  68. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/des_test.c +83 -0
  69. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md2.c +104 -0
  70. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md2.h +33 -0
  71. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md2_test.c +58 -0
  72. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md5.c +189 -0
  73. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md5.h +34 -0
  74. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md5_test.c +60 -0
  75. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/rot-13.c +35 -0
  76. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/rot-13.h +20 -0
  77. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/rot-13_test.c +44 -0
  78. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha1.c +149 -0
  79. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha1.h +35 -0
  80. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha1_test.c +58 -0
  81. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha256.c +159 -0
  82. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha256.h +34 -0
  83. data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha256_test.c +61 -0
  84. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/contrib/Curve25519Donna.c +118 -0
  85. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/contrib/Curve25519Donna.h +53 -0
  86. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/curve25519-donna-c64.c +449 -0
  87. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/curve25519-donna.c +860 -0
  88. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/python-src/curve25519/curve25519module.c +105 -0
  89. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/speed-curve25519.c +50 -0
  90. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/test-curve25519.c +54 -0
  91. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/test-noncanon.c +39 -0
  92. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/test-sc-curve25519.c +72 -0
  93. data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna.h +18 -0
  94. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/add_scalar.c +56 -0
  95. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/ed25519.h +38 -0
  96. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/fe.c +1493 -0
  97. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/fe.h +41 -0
  98. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/fixedint.h +72 -0
  99. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/ge.c +467 -0
  100. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/ge.h +74 -0
  101. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/key_exchange.c +79 -0
  102. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/keypair.c +16 -0
  103. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/precomp_data.h +1391 -0
  104. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sc.c +814 -0
  105. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sc.h +12 -0
  106. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/seed.c +40 -0
  107. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sha512.c +275 -0
  108. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sha512.h +21 -0
  109. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sign.c +31 -0
  110. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/verify.c +77 -0
  111. data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/test.c +150 -0
  112. data/ext/ruby_olm/ext_lib_olm/olm/python/dummy/stddef.h +0 -0
  113. data/ext/ruby_olm/ext_lib_olm/olm/python/dummy/stdint.h +0 -0
  114. data/ext/ruby_olm/ext_lib_olm/olm/src/account.cpp +380 -0
  115. data/ext/ruby_olm/ext_lib_olm/olm/src/base64.cpp +167 -0
  116. data/ext/ruby_olm/ext_lib_olm/olm/src/cipher.cpp +152 -0
  117. data/ext/ruby_olm/ext_lib_olm/olm/src/crypto.cpp +299 -0
  118. data/ext/ruby_olm/ext_lib_olm/olm/src/ed25519.c +22 -0
  119. data/ext/ruby_olm/ext_lib_olm/olm/src/error.c +44 -0
  120. data/ext/ruby_olm/ext_lib_olm/olm/src/inbound_group_session.c +524 -0
  121. data/ext/ruby_olm/ext_lib_olm/olm/src/megolm.c +150 -0
  122. data/ext/ruby_olm/ext_lib_olm/olm/src/memory.cpp +45 -0
  123. data/ext/ruby_olm/ext_lib_olm/olm/src/message.cpp +401 -0
  124. data/ext/ruby_olm/ext_lib_olm/olm/src/olm.cpp +738 -0
  125. data/ext/ruby_olm/ext_lib_olm/olm/src/outbound_group_session.c +363 -0
  126. data/ext/ruby_olm/ext_lib_olm/olm/src/pickle.cpp +242 -0
  127. data/ext/ruby_olm/ext_lib_olm/olm/src/pickle_encoding.c +92 -0
  128. data/ext/ruby_olm/ext_lib_olm/olm/src/pk.cpp +412 -0
  129. data/ext/ruby_olm/ext_lib_olm/olm/src/ratchet.cpp +625 -0
  130. data/ext/ruby_olm/ext_lib_olm/olm/src/session.cpp +462 -0
  131. data/ext/ruby_olm/ext_lib_olm/olm/src/utility.cpp +57 -0
  132. data/ext/ruby_olm/ext_lib_olm/olm/tests/include/unittest.hh +107 -0
  133. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_base64.cpp +70 -0
  134. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_crypto.cpp +246 -0
  135. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_group_session.cpp +329 -0
  136. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_list.cpp +92 -0
  137. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_megolm.cpp +134 -0
  138. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_message.cpp +112 -0
  139. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm.cpp +405 -0
  140. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm_decrypt.cpp +90 -0
  141. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm_sha256.cpp +20 -0
  142. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm_signature.cpp +81 -0
  143. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm_using_malloc.cpp +210 -0
  144. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_pk.cpp +166 -0
  145. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_ratchet.cpp +221 -0
  146. data/ext/ruby_olm/ext_lib_olm/olm/tests/test_session.cpp +144 -0
  147. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMAccount.h +51 -0
  148. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMAccount_Private.h +25 -0
  149. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMInboundGroupSession.h +38 -0
  150. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMKit.h +37 -0
  151. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMMessage.h +38 -0
  152. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMOutboundGroupSession.h +32 -0
  153. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMPkDecryption.h +71 -0
  154. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMPkEncryption.h +42 -0
  155. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMPkMessage.h +31 -0
  156. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMSerializable.h +29 -0
  157. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMSession.h +44 -0
  158. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMSession_Private.h +26 -0
  159. data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMUtility.h +49 -0
  160. data/ext/ruby_olm/ext_lib_olm/staging/account.cpp +380 -0
  161. data/ext/ruby_olm/ext_lib_olm/staging/aes.c +1073 -0
  162. data/ext/ruby_olm/ext_lib_olm/staging/base64.cpp +167 -0
  163. data/ext/ruby_olm/ext_lib_olm/staging/cipher.cpp +152 -0
  164. data/ext/ruby_olm/ext_lib_olm/staging/crypto.cpp +299 -0
  165. data/ext/ruby_olm/ext_lib_olm/staging/curve25519-donna.c +860 -0
  166. data/ext/ruby_olm/ext_lib_olm/staging/ed25519.c +22 -0
  167. data/ext/ruby_olm/ext_lib_olm/staging/error.c +44 -0
  168. data/ext/ruby_olm/ext_lib_olm/staging/inbound_group_session.c +524 -0
  169. data/ext/ruby_olm/ext_lib_olm/staging/megolm.c +150 -0
  170. data/ext/ruby_olm/ext_lib_olm/staging/memory.cpp +45 -0
  171. data/ext/ruby_olm/ext_lib_olm/staging/message.cpp +401 -0
  172. data/ext/ruby_olm/ext_lib_olm/staging/olm.cpp +738 -0
  173. data/ext/ruby_olm/ext_lib_olm/staging/outbound_group_session.c +363 -0
  174. data/ext/ruby_olm/ext_lib_olm/staging/pickle.cpp +242 -0
  175. data/ext/ruby_olm/ext_lib_olm/staging/pickle_encoding.c +92 -0
  176. data/ext/ruby_olm/ext_lib_olm/staging/pk.cpp +412 -0
  177. data/ext/ruby_olm/ext_lib_olm/staging/ratchet.cpp +625 -0
  178. data/ext/ruby_olm/ext_lib_olm/staging/session.cpp +461 -0
  179. data/ext/ruby_olm/ext_lib_olm/staging/sha256.c +159 -0
  180. data/ext/ruby_olm/ext_lib_olm/staging/utility.cpp +57 -0
  181. data/lib/ruby_olm/account.rb +42 -0
  182. data/lib/ruby_olm/message.rb +6 -0
  183. data/lib/ruby_olm/olm_error.rb +70 -0
  184. data/lib/ruby_olm/olm_message.rb +25 -0
  185. data/lib/ruby_olm/pre_key_message.rb +6 -0
  186. data/lib/ruby_olm/session.rb +16 -0
  187. data/lib/ruby_olm/version.rb +5 -0
  188. data/lib/ruby_olm.rb +10 -0
  189. data/rakefile +18 -0
  190. data/test/examples/test_bob_no_answer.rb +62 -0
  191. data/test/examples/test_exchange.rb +60 -0
  192. data/test/spec/test_account.rb +152 -0
  193. data/test/unit/test_account_methods.rb +85 -0
  194. metadata +282 -0
@@ -0,0 +1,625 @@
1
+ /* Copyright 2015, 2016 OpenMarket Ltd
2
+ *
3
+ * Licensed under the Apache License, Version 2.0 (the "License");
4
+ * you may not use this file except in compliance with the License.
5
+ * You may obtain a copy of the License at
6
+ *
7
+ * http://www.apache.org/licenses/LICENSE-2.0
8
+ *
9
+ * Unless required by applicable law or agreed to in writing, software
10
+ * distributed under the License is distributed on an "AS IS" BASIS,
11
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ * See the License for the specific language governing permissions and
13
+ * limitations under the License.
14
+ */
15
+ #include "olm/ratchet.hh"
16
+ #include "olm/message.hh"
17
+ #include "olm/memory.hh"
18
+ #include "olm/cipher.h"
19
+ #include "olm/pickle.hh"
20
+
21
+ #include <cstring>
22
+
23
+ namespace {
24
+
25
+ static const std::uint8_t PROTOCOL_VERSION = 3;
26
+ static const std::uint8_t MESSAGE_KEY_SEED[1] = {0x01};
27
+ static const std::uint8_t CHAIN_KEY_SEED[1] = {0x02};
28
+ static const std::size_t MAX_MESSAGE_GAP = 2000;
29
+
30
+
31
+ /**
32
+ * Advance the root key, creating a new message chain.
33
+ *
34
+ * @param root_key previous root key R(n-1)
35
+ * @param our_key our new ratchet key T(n)
36
+ * @param their_key their most recent ratchet key T(n-1)
37
+ * @param info table of constants for the ratchet function
38
+ * @param new_root_key[out] returns the new root key R(n)
39
+ * @param new_chain_key[out] returns the first chain key in the new chain
40
+ * C(n,0)
41
+ */
42
+ static void create_chain_key(
43
+ olm::SharedKey const & root_key,
44
+ _olm_curve25519_key_pair const & our_key,
45
+ _olm_curve25519_public_key const & their_key,
46
+ olm::KdfInfo const & info,
47
+ olm::SharedKey & new_root_key,
48
+ olm::ChainKey & new_chain_key
49
+ ) {
50
+ olm::SharedKey secret;
51
+ _olm_crypto_curve25519_shared_secret(&our_key, &their_key, secret);
52
+ std::uint8_t derived_secrets[2 * olm::OLM_SHARED_KEY_LENGTH];
53
+ _olm_crypto_hkdf_sha256(
54
+ secret, sizeof(secret),
55
+ root_key, sizeof(root_key),
56
+ info.ratchet_info, info.ratchet_info_length,
57
+ derived_secrets, sizeof(derived_secrets)
58
+ );
59
+ std::uint8_t const * pos = derived_secrets;
60
+ pos = olm::load_array(new_root_key, pos);
61
+ pos = olm::load_array(new_chain_key.key, pos);
62
+ new_chain_key.index = 0;
63
+ olm::unset(derived_secrets);
64
+ olm::unset(secret);
65
+ }
66
+
67
+
68
+ static void advance_chain_key(
69
+ olm::ChainKey const & chain_key,
70
+ olm::ChainKey & new_chain_key
71
+ ) {
72
+ _olm_crypto_hmac_sha256(
73
+ chain_key.key, sizeof(chain_key.key),
74
+ CHAIN_KEY_SEED, sizeof(CHAIN_KEY_SEED),
75
+ new_chain_key.key
76
+ );
77
+ new_chain_key.index = chain_key.index + 1;
78
+ }
79
+
80
+
81
+ static void create_message_keys(
82
+ olm::ChainKey const & chain_key,
83
+ olm::KdfInfo const & info,
84
+ olm::MessageKey & message_key) {
85
+ _olm_crypto_hmac_sha256(
86
+ chain_key.key, sizeof(chain_key.key),
87
+ MESSAGE_KEY_SEED, sizeof(MESSAGE_KEY_SEED),
88
+ message_key.key
89
+ );
90
+ message_key.index = chain_key.index;
91
+ }
92
+
93
+
94
+ static std::size_t verify_mac_and_decrypt(
95
+ _olm_cipher const *cipher,
96
+ olm::MessageKey const & message_key,
97
+ olm::MessageReader const & reader,
98
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
99
+ ) {
100
+ return cipher->ops->decrypt(
101
+ cipher,
102
+ message_key.key, sizeof(message_key.key),
103
+ reader.input, reader.input_length,
104
+ reader.ciphertext, reader.ciphertext_length,
105
+ plaintext, max_plaintext_length
106
+ );
107
+ }
108
+
109
+
110
+ static std::size_t verify_mac_and_decrypt_for_existing_chain(
111
+ olm::Ratchet const & session,
112
+ olm::ChainKey const & chain,
113
+ olm::MessageReader const & reader,
114
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
115
+ ) {
116
+ if (reader.counter < chain.index) {
117
+ return std::size_t(-1);
118
+ }
119
+
120
+ /* Limit the number of hashes we're prepared to compute */
121
+ if (reader.counter - chain.index > MAX_MESSAGE_GAP) {
122
+ return std::size_t(-1);
123
+ }
124
+
125
+ olm::ChainKey new_chain = chain;
126
+
127
+ while (new_chain.index < reader.counter) {
128
+ advance_chain_key(new_chain, new_chain);
129
+ }
130
+
131
+ olm::MessageKey message_key;
132
+ create_message_keys(new_chain, session.kdf_info, message_key);
133
+
134
+ std::size_t result = verify_mac_and_decrypt(
135
+ session.ratchet_cipher, message_key, reader,
136
+ plaintext, max_plaintext_length
137
+ );
138
+
139
+ olm::unset(new_chain);
140
+ return result;
141
+ }
142
+
143
+
144
+ static std::size_t verify_mac_and_decrypt_for_new_chain(
145
+ olm::Ratchet const & session,
146
+ olm::MessageReader const & reader,
147
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
148
+ ) {
149
+ olm::SharedKey new_root_key;
150
+ olm::ReceiverChain new_chain;
151
+
152
+ /* They shouldn't move to a new chain until we've sent them a message
153
+ * acknowledging the last one */
154
+ if (session.sender_chain.empty()) {
155
+ return std::size_t(-1);
156
+ }
157
+
158
+ /* Limit the number of hashes we're prepared to compute */
159
+ if (reader.counter > MAX_MESSAGE_GAP) {
160
+ return std::size_t(-1);
161
+ }
162
+ olm::load_array(new_chain.ratchet_key.public_key, reader.ratchet_key);
163
+
164
+ create_chain_key(
165
+ session.root_key, session.sender_chain[0].ratchet_key,
166
+ new_chain.ratchet_key, session.kdf_info,
167
+ new_root_key, new_chain.chain_key
168
+ );
169
+ std::size_t result = verify_mac_and_decrypt_for_existing_chain(
170
+ session, new_chain.chain_key, reader,
171
+ plaintext, max_plaintext_length
172
+ );
173
+ olm::unset(new_root_key);
174
+ olm::unset(new_chain);
175
+ return result;
176
+ }
177
+
178
+ } // namespace
179
+
180
+
181
+ olm::Ratchet::Ratchet(
182
+ olm::KdfInfo const & kdf_info,
183
+ _olm_cipher const * ratchet_cipher
184
+ ) : kdf_info(kdf_info),
185
+ ratchet_cipher(ratchet_cipher),
186
+ last_error(OlmErrorCode::OLM_SUCCESS) {
187
+ }
188
+
189
+
190
+ void olm::Ratchet::initialise_as_bob(
191
+ std::uint8_t const * shared_secret, std::size_t shared_secret_length,
192
+ _olm_curve25519_public_key const & their_ratchet_key
193
+ ) {
194
+ std::uint8_t derived_secrets[2 * olm::OLM_SHARED_KEY_LENGTH];
195
+ _olm_crypto_hkdf_sha256(
196
+ shared_secret, shared_secret_length,
197
+ nullptr, 0,
198
+ kdf_info.root_info, kdf_info.root_info_length,
199
+ derived_secrets, sizeof(derived_secrets)
200
+ );
201
+ receiver_chains.insert();
202
+ receiver_chains[0].chain_key.index = 0;
203
+ std::uint8_t const * pos = derived_secrets;
204
+ pos = olm::load_array(root_key, pos);
205
+ pos = olm::load_array(receiver_chains[0].chain_key.key, pos);
206
+ receiver_chains[0].ratchet_key = their_ratchet_key;
207
+ olm::unset(derived_secrets);
208
+ }
209
+
210
+
211
+ void olm::Ratchet::initialise_as_alice(
212
+ std::uint8_t const * shared_secret, std::size_t shared_secret_length,
213
+ _olm_curve25519_key_pair const & our_ratchet_key
214
+ ) {
215
+ std::uint8_t derived_secrets[2 * olm::OLM_SHARED_KEY_LENGTH];
216
+ _olm_crypto_hkdf_sha256(
217
+ shared_secret, shared_secret_length,
218
+ nullptr, 0,
219
+ kdf_info.root_info, kdf_info.root_info_length,
220
+ derived_secrets, sizeof(derived_secrets)
221
+ );
222
+ sender_chain.insert();
223
+ sender_chain[0].chain_key.index = 0;
224
+ std::uint8_t const * pos = derived_secrets;
225
+ pos = olm::load_array(root_key, pos);
226
+ pos = olm::load_array(sender_chain[0].chain_key.key, pos);
227
+ sender_chain[0].ratchet_key = our_ratchet_key;
228
+ olm::unset(derived_secrets);
229
+ }
230
+
231
+ namespace olm {
232
+
233
+
234
+ static std::size_t pickle_length(
235
+ const olm::SharedKey & value
236
+ ) {
237
+ return olm::OLM_SHARED_KEY_LENGTH;
238
+ }
239
+
240
+
241
+ static std::uint8_t * pickle(
242
+ std::uint8_t * pos,
243
+ const olm::SharedKey & value
244
+ ) {
245
+ return olm::pickle_bytes(pos, value, olm::OLM_SHARED_KEY_LENGTH);
246
+ }
247
+
248
+
249
+ static std::uint8_t const * unpickle(
250
+ std::uint8_t const * pos, std::uint8_t const * end,
251
+ olm::SharedKey & value
252
+ ) {
253
+ return olm::unpickle_bytes(pos, end, value, olm::OLM_SHARED_KEY_LENGTH);
254
+ }
255
+
256
+
257
+ static std::size_t pickle_length(
258
+ const olm::SenderChain & value
259
+ ) {
260
+ std::size_t length = 0;
261
+ length += olm::pickle_length(value.ratchet_key);
262
+ length += olm::pickle_length(value.chain_key.key);
263
+ length += olm::pickle_length(value.chain_key.index);
264
+ return length;
265
+ }
266
+
267
+
268
+ static std::uint8_t * pickle(
269
+ std::uint8_t * pos,
270
+ const olm::SenderChain & value
271
+ ) {
272
+ pos = olm::pickle(pos, value.ratchet_key);
273
+ pos = olm::pickle(pos, value.chain_key.key);
274
+ pos = olm::pickle(pos, value.chain_key.index);
275
+ return pos;
276
+ }
277
+
278
+
279
+ static std::uint8_t const * unpickle(
280
+ std::uint8_t const * pos, std::uint8_t const * end,
281
+ olm::SenderChain & value
282
+ ) {
283
+ pos = olm::unpickle(pos, end, value.ratchet_key);
284
+ pos = olm::unpickle(pos, end, value.chain_key.key);
285
+ pos = olm::unpickle(pos, end, value.chain_key.index);
286
+ return pos;
287
+ }
288
+
289
+ static std::size_t pickle_length(
290
+ const olm::ReceiverChain & value
291
+ ) {
292
+ std::size_t length = 0;
293
+ length += olm::pickle_length(value.ratchet_key);
294
+ length += olm::pickle_length(value.chain_key.key);
295
+ length += olm::pickle_length(value.chain_key.index);
296
+ return length;
297
+ }
298
+
299
+
300
+ static std::uint8_t * pickle(
301
+ std::uint8_t * pos,
302
+ const olm::ReceiverChain & value
303
+ ) {
304
+ pos = olm::pickle(pos, value.ratchet_key);
305
+ pos = olm::pickle(pos, value.chain_key.key);
306
+ pos = olm::pickle(pos, value.chain_key.index);
307
+ return pos;
308
+ }
309
+
310
+
311
+ static std::uint8_t const * unpickle(
312
+ std::uint8_t const * pos, std::uint8_t const * end,
313
+ olm::ReceiverChain & value
314
+ ) {
315
+ pos = olm::unpickle(pos, end, value.ratchet_key);
316
+ pos = olm::unpickle(pos, end, value.chain_key.key);
317
+ pos = olm::unpickle(pos, end, value.chain_key.index);
318
+ return pos;
319
+ }
320
+
321
+
322
+ static std::size_t pickle_length(
323
+ const olm::SkippedMessageKey & value
324
+ ) {
325
+ std::size_t length = 0;
326
+ length += olm::pickle_length(value.ratchet_key);
327
+ length += olm::pickle_length(value.message_key.key);
328
+ length += olm::pickle_length(value.message_key.index);
329
+ return length;
330
+ }
331
+
332
+
333
+ static std::uint8_t * pickle(
334
+ std::uint8_t * pos,
335
+ const olm::SkippedMessageKey & value
336
+ ) {
337
+ pos = olm::pickle(pos, value.ratchet_key);
338
+ pos = olm::pickle(pos, value.message_key.key);
339
+ pos = olm::pickle(pos, value.message_key.index);
340
+ return pos;
341
+ }
342
+
343
+
344
+ static std::uint8_t const * unpickle(
345
+ std::uint8_t const * pos, std::uint8_t const * end,
346
+ olm::SkippedMessageKey & value
347
+ ) {
348
+ pos = olm::unpickle(pos, end, value.ratchet_key);
349
+ pos = olm::unpickle(pos, end, value.message_key.key);
350
+ pos = olm::unpickle(pos, end, value.message_key.index);
351
+ return pos;
352
+ }
353
+
354
+
355
+ } // namespace olm
356
+
357
+
358
+ std::size_t olm::pickle_length(
359
+ olm::Ratchet const & value
360
+ ) {
361
+ std::size_t length = 0;
362
+ length += olm::OLM_SHARED_KEY_LENGTH;
363
+ length += olm::pickle_length(value.sender_chain);
364
+ length += olm::pickle_length(value.receiver_chains);
365
+ length += olm::pickle_length(value.skipped_message_keys);
366
+ return length;
367
+ }
368
+
369
+ std::uint8_t * olm::pickle(
370
+ std::uint8_t * pos,
371
+ olm::Ratchet const & value
372
+ ) {
373
+ pos = pickle(pos, value.root_key);
374
+ pos = pickle(pos, value.sender_chain);
375
+ pos = pickle(pos, value.receiver_chains);
376
+ pos = pickle(pos, value.skipped_message_keys);
377
+ return pos;
378
+ }
379
+
380
+
381
+ std::uint8_t const * olm::unpickle(
382
+ std::uint8_t const * pos, std::uint8_t const * end,
383
+ olm::Ratchet & value,
384
+ bool includes_chain_index
385
+ ) {
386
+ pos = unpickle(pos, end, value.root_key);
387
+ pos = unpickle(pos, end, value.sender_chain);
388
+ pos = unpickle(pos, end, value.receiver_chains);
389
+ pos = unpickle(pos, end, value.skipped_message_keys);
390
+
391
+ // pickle v 0x80000001 includes a chain index; pickle v1 does not.
392
+ if (includes_chain_index) {
393
+ std::uint32_t dummy;
394
+ pos = unpickle(pos, end, dummy);
395
+ }
396
+ return pos;
397
+ }
398
+
399
+
400
+ std::size_t olm::Ratchet::encrypt_output_length(
401
+ std::size_t plaintext_length
402
+ ) {
403
+ std::size_t counter = 0;
404
+ if (!sender_chain.empty()) {
405
+ counter = sender_chain[0].chain_key.index;
406
+ }
407
+ std::size_t padded = ratchet_cipher->ops->encrypt_ciphertext_length(
408
+ ratchet_cipher,
409
+ plaintext_length
410
+ );
411
+ return olm::encode_message_length(
412
+ counter, CURVE25519_KEY_LENGTH, padded, ratchet_cipher->ops->mac_length(ratchet_cipher)
413
+ );
414
+ }
415
+
416
+
417
+ std::size_t olm::Ratchet::encrypt_random_length() {
418
+ return sender_chain.empty() ? CURVE25519_RANDOM_LENGTH : 0;
419
+ }
420
+
421
+
422
+ std::size_t olm::Ratchet::encrypt(
423
+ std::uint8_t const * plaintext, std::size_t plaintext_length,
424
+ std::uint8_t const * random, std::size_t random_length,
425
+ std::uint8_t * output, std::size_t max_output_length
426
+ ) {
427
+ std::size_t output_length = encrypt_output_length(plaintext_length);
428
+
429
+ if (random_length < encrypt_random_length()) {
430
+ last_error = OlmErrorCode::OLM_NOT_ENOUGH_RANDOM;
431
+ return std::size_t(-1);
432
+ }
433
+ if (max_output_length < output_length) {
434
+ last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
435
+ return std::size_t(-1);
436
+ }
437
+
438
+ if (sender_chain.empty()) {
439
+ sender_chain.insert();
440
+ _olm_crypto_curve25519_generate_key(random, &sender_chain[0].ratchet_key);
441
+ create_chain_key(
442
+ root_key,
443
+ sender_chain[0].ratchet_key,
444
+ receiver_chains[0].ratchet_key,
445
+ kdf_info,
446
+ root_key, sender_chain[0].chain_key
447
+ );
448
+ }
449
+
450
+ MessageKey keys;
451
+ create_message_keys(sender_chain[0].chain_key, kdf_info, keys);
452
+ advance_chain_key(sender_chain[0].chain_key, sender_chain[0].chain_key);
453
+
454
+ std::size_t ciphertext_length = ratchet_cipher->ops->encrypt_ciphertext_length(
455
+ ratchet_cipher,
456
+ plaintext_length
457
+ );
458
+ std::uint32_t counter = keys.index;
459
+ _olm_curve25519_public_key const & ratchet_key =
460
+ sender_chain[0].ratchet_key.public_key;
461
+
462
+ olm::MessageWriter writer;
463
+
464
+ olm::encode_message(
465
+ writer, PROTOCOL_VERSION, counter, CURVE25519_KEY_LENGTH,
466
+ ciphertext_length,
467
+ output
468
+ );
469
+
470
+ olm::store_array(writer.ratchet_key, ratchet_key.public_key);
471
+
472
+ ratchet_cipher->ops->encrypt(
473
+ ratchet_cipher,
474
+ keys.key, sizeof(keys.key),
475
+ plaintext, plaintext_length,
476
+ writer.ciphertext, ciphertext_length,
477
+ output, output_length
478
+ );
479
+
480
+ olm::unset(keys);
481
+ return output_length;
482
+ }
483
+
484
+
485
+ std::size_t olm::Ratchet::decrypt_max_plaintext_length(
486
+ std::uint8_t const * input, std::size_t input_length
487
+ ) {
488
+ olm::MessageReader reader;
489
+ olm::decode_message(
490
+ reader, input, input_length,
491
+ ratchet_cipher->ops->mac_length(ratchet_cipher)
492
+ );
493
+
494
+ if (!reader.ciphertext) {
495
+ last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
496
+ return std::size_t(-1);
497
+ }
498
+
499
+ return ratchet_cipher->ops->decrypt_max_plaintext_length(
500
+ ratchet_cipher, reader.ciphertext_length);
501
+ }
502
+
503
+
504
+ std::size_t olm::Ratchet::decrypt(
505
+ std::uint8_t const * input, std::size_t input_length,
506
+ std::uint8_t * plaintext, std::size_t max_plaintext_length
507
+ ) {
508
+ olm::MessageReader reader;
509
+ olm::decode_message(
510
+ reader, input, input_length,
511
+ ratchet_cipher->ops->mac_length(ratchet_cipher)
512
+ );
513
+
514
+ if (reader.version != PROTOCOL_VERSION) {
515
+ last_error = OlmErrorCode::OLM_BAD_MESSAGE_VERSION;
516
+ return std::size_t(-1);
517
+ }
518
+
519
+ if (!reader.has_counter || !reader.ratchet_key || !reader.ciphertext) {
520
+ last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
521
+ return std::size_t(-1);
522
+ }
523
+
524
+ std::size_t max_length = ratchet_cipher->ops->decrypt_max_plaintext_length(
525
+ ratchet_cipher,
526
+ reader.ciphertext_length
527
+ );
528
+
529
+ if (max_plaintext_length < max_length) {
530
+ last_error = OlmErrorCode::OLM_OUTPUT_BUFFER_TOO_SMALL;
531
+ return std::size_t(-1);
532
+ }
533
+
534
+ if (reader.ratchet_key_length != CURVE25519_KEY_LENGTH) {
535
+ last_error = OlmErrorCode::OLM_BAD_MESSAGE_FORMAT;
536
+ return std::size_t(-1);
537
+ }
538
+
539
+ ReceiverChain * chain = nullptr;
540
+
541
+ for (olm::ReceiverChain & receiver_chain : receiver_chains) {
542
+ if (0 == std::memcmp(
543
+ receiver_chain.ratchet_key.public_key, reader.ratchet_key,
544
+ CURVE25519_KEY_LENGTH
545
+ )) {
546
+ chain = &receiver_chain;
547
+ break;
548
+ }
549
+ }
550
+
551
+ std::size_t result = std::size_t(-1);
552
+
553
+ if (!chain) {
554
+ result = verify_mac_and_decrypt_for_new_chain(
555
+ *this, reader, plaintext, max_plaintext_length
556
+ );
557
+ } else if (chain->chain_key.index > reader.counter) {
558
+ /* Chain already advanced beyond the key for this message
559
+ * Check if the message keys are in the skipped key list. */
560
+ for (olm::SkippedMessageKey & skipped : skipped_message_keys) {
561
+ if (reader.counter == skipped.message_key.index
562
+ && 0 == std::memcmp(
563
+ skipped.ratchet_key.public_key, reader.ratchet_key,
564
+ CURVE25519_KEY_LENGTH
565
+ )
566
+ ) {
567
+ /* Found the key for this message. Check the MAC. */
568
+
569
+ result = verify_mac_and_decrypt(
570
+ ratchet_cipher, skipped.message_key, reader,
571
+ plaintext, max_plaintext_length
572
+ );
573
+
574
+ if (result != std::size_t(-1)) {
575
+ /* Remove the key from the skipped keys now that we've
576
+ * decoded the message it corresponds to. */
577
+ olm::unset(skipped);
578
+ skipped_message_keys.erase(&skipped);
579
+ return result;
580
+ }
581
+ }
582
+ }
583
+ } else {
584
+ result = verify_mac_and_decrypt_for_existing_chain(
585
+ *this, chain->chain_key,
586
+ reader, plaintext, max_plaintext_length
587
+ );
588
+ }
589
+
590
+ if (result == std::size_t(-1)) {
591
+ last_error = OlmErrorCode::OLM_BAD_MESSAGE_MAC;
592
+ return std::size_t(-1);
593
+ }
594
+
595
+ if (!chain) {
596
+ /* They have started using a new ephemeral ratchet key.
597
+ * We need to derive a new set of chain keys.
598
+ * We can discard our previous empheral ratchet key.
599
+ * We will generate a new key when we send the next message. */
600
+
601
+ chain = receiver_chains.insert();
602
+ olm::load_array(chain->ratchet_key.public_key, reader.ratchet_key);
603
+
604
+ // TODO: we've already done this once, in
605
+ // verify_mac_and_decrypt_for_new_chain(). we could reuse the result.
606
+ create_chain_key(
607
+ root_key, sender_chain[0].ratchet_key, chain->ratchet_key,
608
+ kdf_info, root_key, chain->chain_key
609
+ );
610
+
611
+ olm::unset(sender_chain[0]);
612
+ sender_chain.erase(sender_chain.begin());
613
+ }
614
+
615
+ while (chain->chain_key.index < reader.counter) {
616
+ olm::SkippedMessageKey & key = *skipped_message_keys.insert();
617
+ create_message_keys(chain->chain_key, kdf_info, key.message_key);
618
+ key.ratchet_key = chain->ratchet_key;
619
+ advance_chain_key(chain->chain_key, chain->chain_key);
620
+ }
621
+
622
+ advance_chain_key(chain->chain_key, chain->chain_key);
623
+
624
+ return result;
625
+ }