ruby_olm 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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
+ }