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.
- checksums.yaml +7 -0
- data/ext/ruby_olm/ext_lib_olm/ext_account.c +274 -0
- data/ext/ruby_olm/ext_lib_olm/ext_lib_olm.c +51 -0
- data/ext/ruby_olm/ext_lib_olm/ext_lib_olm.h +13 -0
- data/ext/ruby_olm/ext_lib_olm/ext_session.c +363 -0
- data/ext/ruby_olm/ext_lib_olm/ext_utility.c +69 -0
- data/ext/ruby_olm/ext_lib_olm/extconf.rb +69 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_account.cpp +695 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_account.h +56 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_inbound_group_session.cpp +654 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_inbound_group_session.h +51 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_jni.h +81 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_jni_helper.cpp +224 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_jni_helper.h +30 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_manager.cpp +35 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_manager.h +36 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_outbound_group_session.cpp +563 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_outbound_group_session.h +49 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_pk.cpp +716 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_pk.h +48 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_session.cpp +977 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_session.h +59 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_utility.cpp +236 -0
- data/ext/ruby_olm/ext_lib_olm/olm/android/olm-sdk/src/main/jni/olm_utility.h +40 -0
- data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_decode_message.cpp +14 -0
- data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_decrypt.cpp +65 -0
- data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_group_decrypt.cpp +73 -0
- data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_unpickle_account.cpp +14 -0
- data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/fuzz_unpickle_session.cpp +14 -0
- data/ext/ruby_olm/ext_lib_olm/olm/fuzzers/include/fuzzing.hh +82 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/account.hh +160 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/base64.h +77 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/base64.hh +63 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/cipher.h +138 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/crypto.h +202 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/error.h +72 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/inbound_group_session.h +235 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/list.hh +119 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/megolm.h +95 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/memory.h +41 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/memory.hh +90 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/message.h +93 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/message.hh +138 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/olm.h +451 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/olm.hh +4 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/outbound_group_session.h +181 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/pickle.h +90 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/pickle.hh +149 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/pickle_encoding.h +76 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/pk.h +214 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/ratchet.hh +184 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/session.hh +156 -0
- data/ext/ruby_olm/ext_lib_olm/olm/include/olm/utility.hh +61 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/aes.c +1073 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/aes.h +123 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/aes_test.c +276 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/arcfour.c +45 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/arcfour.h +30 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/arcfour_test.c +47 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/base64.c +135 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/base64.h +27 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/base64_test.c +54 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/blowfish.c +269 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/blowfish.h +32 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/blowfish_test.c +68 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/des.c +269 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/des.h +37 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/des_test.c +83 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md2.c +104 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md2.h +33 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md2_test.c +58 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md5.c +189 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md5.h +34 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/md5_test.c +60 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/rot-13.c +35 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/rot-13.h +20 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/rot-13_test.c +44 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha1.c +149 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha1.h +35 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha1_test.c +58 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha256.c +159 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha256.h +34 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/crypto-algorithms/sha256_test.c +61 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/contrib/Curve25519Donna.c +118 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/contrib/Curve25519Donna.h +53 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/curve25519-donna-c64.c +449 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/curve25519-donna.c +860 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/python-src/curve25519/curve25519module.c +105 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/speed-curve25519.c +50 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/test-curve25519.c +54 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/test-noncanon.c +39 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna/test-sc-curve25519.c +72 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/curve25519-donna.h +18 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/add_scalar.c +56 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/ed25519.h +38 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/fe.c +1493 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/fe.h +41 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/fixedint.h +72 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/ge.c +467 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/ge.h +74 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/key_exchange.c +79 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/keypair.c +16 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/precomp_data.h +1391 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sc.c +814 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sc.h +12 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/seed.c +40 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sha512.c +275 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sha512.h +21 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/sign.c +31 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/src/verify.c +77 -0
- data/ext/ruby_olm/ext_lib_olm/olm/lib/ed25519/test.c +150 -0
- data/ext/ruby_olm/ext_lib_olm/olm/python/dummy/stddef.h +0 -0
- data/ext/ruby_olm/ext_lib_olm/olm/python/dummy/stdint.h +0 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/account.cpp +380 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/base64.cpp +167 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/cipher.cpp +152 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/crypto.cpp +299 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/ed25519.c +22 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/error.c +44 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/inbound_group_session.c +524 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/megolm.c +150 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/memory.cpp +45 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/message.cpp +401 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/olm.cpp +738 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/outbound_group_session.c +363 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/pickle.cpp +242 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/pickle_encoding.c +92 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/pk.cpp +412 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/ratchet.cpp +625 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/session.cpp +462 -0
- data/ext/ruby_olm/ext_lib_olm/olm/src/utility.cpp +57 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/include/unittest.hh +107 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_base64.cpp +70 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_crypto.cpp +246 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_group_session.cpp +329 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_list.cpp +92 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_megolm.cpp +134 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_message.cpp +112 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm.cpp +405 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm_decrypt.cpp +90 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm_sha256.cpp +20 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm_signature.cpp +81 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_olm_using_malloc.cpp +210 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_pk.cpp +166 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_ratchet.cpp +221 -0
- data/ext/ruby_olm/ext_lib_olm/olm/tests/test_session.cpp +144 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMAccount.h +51 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMAccount_Private.h +25 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMInboundGroupSession.h +38 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMKit.h +37 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMMessage.h +38 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMOutboundGroupSession.h +32 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMPkDecryption.h +71 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMPkEncryption.h +42 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMPkMessage.h +31 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMSerializable.h +29 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMSession.h +44 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMSession_Private.h +26 -0
- data/ext/ruby_olm/ext_lib_olm/olm/xcode/OLMKit/OLMUtility.h +49 -0
- data/ext/ruby_olm/ext_lib_olm/staging/account.cpp +380 -0
- data/ext/ruby_olm/ext_lib_olm/staging/aes.c +1073 -0
- data/ext/ruby_olm/ext_lib_olm/staging/base64.cpp +167 -0
- data/ext/ruby_olm/ext_lib_olm/staging/cipher.cpp +152 -0
- data/ext/ruby_olm/ext_lib_olm/staging/crypto.cpp +299 -0
- data/ext/ruby_olm/ext_lib_olm/staging/curve25519-donna.c +860 -0
- data/ext/ruby_olm/ext_lib_olm/staging/ed25519.c +22 -0
- data/ext/ruby_olm/ext_lib_olm/staging/error.c +44 -0
- data/ext/ruby_olm/ext_lib_olm/staging/inbound_group_session.c +524 -0
- data/ext/ruby_olm/ext_lib_olm/staging/megolm.c +150 -0
- data/ext/ruby_olm/ext_lib_olm/staging/memory.cpp +45 -0
- data/ext/ruby_olm/ext_lib_olm/staging/message.cpp +401 -0
- data/ext/ruby_olm/ext_lib_olm/staging/olm.cpp +738 -0
- data/ext/ruby_olm/ext_lib_olm/staging/outbound_group_session.c +363 -0
- data/ext/ruby_olm/ext_lib_olm/staging/pickle.cpp +242 -0
- data/ext/ruby_olm/ext_lib_olm/staging/pickle_encoding.c +92 -0
- data/ext/ruby_olm/ext_lib_olm/staging/pk.cpp +412 -0
- data/ext/ruby_olm/ext_lib_olm/staging/ratchet.cpp +625 -0
- data/ext/ruby_olm/ext_lib_olm/staging/session.cpp +461 -0
- data/ext/ruby_olm/ext_lib_olm/staging/sha256.c +159 -0
- data/ext/ruby_olm/ext_lib_olm/staging/utility.cpp +57 -0
- data/lib/ruby_olm/account.rb +42 -0
- data/lib/ruby_olm/message.rb +6 -0
- data/lib/ruby_olm/olm_error.rb +70 -0
- data/lib/ruby_olm/olm_message.rb +25 -0
- data/lib/ruby_olm/pre_key_message.rb +6 -0
- data/lib/ruby_olm/session.rb +16 -0
- data/lib/ruby_olm/version.rb +5 -0
- data/lib/ruby_olm.rb +10 -0
- data/rakefile +18 -0
- data/test/examples/test_bob_no_answer.rb +62 -0
- data/test/examples/test_exchange.rb +60 -0
- data/test/spec/test_account.rb +152 -0
- data/test/unit/test_account_methods.rb +85 -0
- metadata +282 -0
|
@@ -0,0 +1,524 @@
|
|
|
1
|
+
/* Copyright 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
|
+
|
|
16
|
+
#include "olm/inbound_group_session.h"
|
|
17
|
+
|
|
18
|
+
#include <string.h>
|
|
19
|
+
|
|
20
|
+
#include "olm/base64.h"
|
|
21
|
+
#include "olm/cipher.h"
|
|
22
|
+
#include "olm/crypto.h"
|
|
23
|
+
#include "olm/error.h"
|
|
24
|
+
#include "olm/megolm.h"
|
|
25
|
+
#include "olm/memory.h"
|
|
26
|
+
#include "olm/message.h"
|
|
27
|
+
#include "olm/pickle.h"
|
|
28
|
+
#include "olm/pickle_encoding.h"
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
#define OLM_PROTOCOL_VERSION 3
|
|
32
|
+
#define GROUP_SESSION_ID_LENGTH ED25519_PUBLIC_KEY_LENGTH
|
|
33
|
+
#define PICKLE_VERSION 2
|
|
34
|
+
#define SESSION_KEY_VERSION 2
|
|
35
|
+
#define SESSION_EXPORT_VERSION 1
|
|
36
|
+
|
|
37
|
+
struct OlmInboundGroupSession {
|
|
38
|
+
/** our earliest known ratchet value */
|
|
39
|
+
Megolm initial_ratchet;
|
|
40
|
+
|
|
41
|
+
/** The most recent ratchet value */
|
|
42
|
+
Megolm latest_ratchet;
|
|
43
|
+
|
|
44
|
+
/** The ed25519 signing key */
|
|
45
|
+
struct _olm_ed25519_public_key signing_key;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Have we ever seen any evidence that this is a valid session?
|
|
49
|
+
* (either because the original session share was signed, or because we
|
|
50
|
+
* have subsequently successfully decrypted a message)
|
|
51
|
+
*
|
|
52
|
+
* (We don't do anything with this currently, but we may want to bear it in
|
|
53
|
+
* mind when we consider handling key-shares for sessions we already know
|
|
54
|
+
* about.)
|
|
55
|
+
*/
|
|
56
|
+
int signing_key_verified;
|
|
57
|
+
|
|
58
|
+
enum OlmErrorCode last_error;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
size_t olm_inbound_group_session_size(void) {
|
|
62
|
+
return sizeof(OlmInboundGroupSession);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
OlmInboundGroupSession * olm_inbound_group_session(
|
|
66
|
+
void *memory
|
|
67
|
+
) {
|
|
68
|
+
OlmInboundGroupSession *session = memory;
|
|
69
|
+
olm_clear_inbound_group_session(session);
|
|
70
|
+
return session;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const char *olm_inbound_group_session_last_error(
|
|
74
|
+
const OlmInboundGroupSession *session
|
|
75
|
+
) {
|
|
76
|
+
return _olm_error_to_string(session->last_error);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
size_t olm_clear_inbound_group_session(
|
|
80
|
+
OlmInboundGroupSession *session
|
|
81
|
+
) {
|
|
82
|
+
_olm_unset(session, sizeof(OlmInboundGroupSession));
|
|
83
|
+
return sizeof(OlmInboundGroupSession);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#define SESSION_EXPORT_RAW_LENGTH \
|
|
87
|
+
(1 + 4 + MEGOLM_RATCHET_LENGTH + ED25519_PUBLIC_KEY_LENGTH)
|
|
88
|
+
|
|
89
|
+
#define SESSION_KEY_RAW_LENGTH \
|
|
90
|
+
(1 + 4 + MEGOLM_RATCHET_LENGTH + ED25519_PUBLIC_KEY_LENGTH\
|
|
91
|
+
+ ED25519_SIGNATURE_LENGTH)
|
|
92
|
+
|
|
93
|
+
static size_t _init_group_session_keys(
|
|
94
|
+
OlmInboundGroupSession *session,
|
|
95
|
+
const uint8_t *key_buf,
|
|
96
|
+
int export_format
|
|
97
|
+
) {
|
|
98
|
+
const uint8_t expected_version =
|
|
99
|
+
(export_format ? SESSION_EXPORT_VERSION : SESSION_KEY_VERSION);
|
|
100
|
+
const uint8_t *ptr = key_buf;
|
|
101
|
+
size_t version = *ptr++;
|
|
102
|
+
|
|
103
|
+
if (version != expected_version) {
|
|
104
|
+
session->last_error = OLM_BAD_SESSION_KEY;
|
|
105
|
+
return (size_t)-1;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
uint32_t counter = 0;
|
|
109
|
+
// Decode counter as a big endian 32-bit number.
|
|
110
|
+
for (unsigned i = 0; i < 4; i++) {
|
|
111
|
+
counter <<= 8; counter |= *ptr++;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
megolm_init(&session->initial_ratchet, ptr, counter);
|
|
115
|
+
megolm_init(&session->latest_ratchet, ptr, counter);
|
|
116
|
+
|
|
117
|
+
ptr += MEGOLM_RATCHET_LENGTH;
|
|
118
|
+
memcpy(
|
|
119
|
+
session->signing_key.public_key, ptr, ED25519_PUBLIC_KEY_LENGTH
|
|
120
|
+
);
|
|
121
|
+
ptr += ED25519_PUBLIC_KEY_LENGTH;
|
|
122
|
+
|
|
123
|
+
if (!export_format) {
|
|
124
|
+
if (!_olm_crypto_ed25519_verify(&session->signing_key, key_buf,
|
|
125
|
+
ptr - key_buf, ptr)) {
|
|
126
|
+
session->last_error = OLM_BAD_SIGNATURE;
|
|
127
|
+
return (size_t)-1;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* signed keyshare */
|
|
131
|
+
session->signing_key_verified = 1;
|
|
132
|
+
}
|
|
133
|
+
return 0;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
size_t olm_init_inbound_group_session(
|
|
137
|
+
OlmInboundGroupSession *session,
|
|
138
|
+
const uint8_t * session_key, size_t session_key_length
|
|
139
|
+
) {
|
|
140
|
+
uint8_t key_buf[SESSION_KEY_RAW_LENGTH];
|
|
141
|
+
size_t raw_length = _olm_decode_base64_length(session_key_length);
|
|
142
|
+
size_t result;
|
|
143
|
+
|
|
144
|
+
if (raw_length == (size_t)-1) {
|
|
145
|
+
session->last_error = OLM_INVALID_BASE64;
|
|
146
|
+
return (size_t)-1;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
if (raw_length != SESSION_KEY_RAW_LENGTH) {
|
|
150
|
+
session->last_error = OLM_BAD_SESSION_KEY;
|
|
151
|
+
return (size_t)-1;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
_olm_decode_base64(session_key, session_key_length, key_buf);
|
|
155
|
+
result = _init_group_session_keys(session, key_buf, 0);
|
|
156
|
+
_olm_unset(key_buf, SESSION_KEY_RAW_LENGTH);
|
|
157
|
+
return result;
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
size_t olm_import_inbound_group_session(
|
|
161
|
+
OlmInboundGroupSession *session,
|
|
162
|
+
const uint8_t * session_key, size_t session_key_length
|
|
163
|
+
) {
|
|
164
|
+
uint8_t key_buf[SESSION_EXPORT_RAW_LENGTH];
|
|
165
|
+
size_t raw_length = _olm_decode_base64_length(session_key_length);
|
|
166
|
+
size_t result;
|
|
167
|
+
|
|
168
|
+
if (raw_length == (size_t)-1) {
|
|
169
|
+
session->last_error = OLM_INVALID_BASE64;
|
|
170
|
+
return (size_t)-1;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (raw_length != SESSION_EXPORT_RAW_LENGTH) {
|
|
174
|
+
session->last_error = OLM_BAD_SESSION_KEY;
|
|
175
|
+
return (size_t)-1;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
_olm_decode_base64(session_key, session_key_length, key_buf);
|
|
179
|
+
result = _init_group_session_keys(session, key_buf, 1);
|
|
180
|
+
_olm_unset(key_buf, SESSION_EXPORT_RAW_LENGTH);
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
static size_t raw_pickle_length(
|
|
185
|
+
const OlmInboundGroupSession *session
|
|
186
|
+
) {
|
|
187
|
+
size_t length = 0;
|
|
188
|
+
length += _olm_pickle_uint32_length(PICKLE_VERSION);
|
|
189
|
+
length += megolm_pickle_length(&session->initial_ratchet);
|
|
190
|
+
length += megolm_pickle_length(&session->latest_ratchet);
|
|
191
|
+
length += _olm_pickle_ed25519_public_key_length(&session->signing_key);
|
|
192
|
+
length += _olm_pickle_bool_length(session->signing_key_verified);
|
|
193
|
+
return length;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
size_t olm_pickle_inbound_group_session_length(
|
|
197
|
+
const OlmInboundGroupSession *session
|
|
198
|
+
) {
|
|
199
|
+
return _olm_enc_output_length(raw_pickle_length(session));
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
size_t olm_pickle_inbound_group_session(
|
|
203
|
+
OlmInboundGroupSession *session,
|
|
204
|
+
void const * key, size_t key_length,
|
|
205
|
+
void * pickled, size_t pickled_length
|
|
206
|
+
) {
|
|
207
|
+
size_t raw_length = raw_pickle_length(session);
|
|
208
|
+
uint8_t *pos;
|
|
209
|
+
|
|
210
|
+
if (pickled_length < _olm_enc_output_length(raw_length)) {
|
|
211
|
+
session->last_error = OLM_OUTPUT_BUFFER_TOO_SMALL;
|
|
212
|
+
return (size_t)-1;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
pos = _olm_enc_output_pos(pickled, raw_length);
|
|
216
|
+
pos = _olm_pickle_uint32(pos, PICKLE_VERSION);
|
|
217
|
+
pos = megolm_pickle(&session->initial_ratchet, pos);
|
|
218
|
+
pos = megolm_pickle(&session->latest_ratchet, pos);
|
|
219
|
+
pos = _olm_pickle_ed25519_public_key(pos, &session->signing_key);
|
|
220
|
+
pos = _olm_pickle_bool(pos, session->signing_key_verified);
|
|
221
|
+
|
|
222
|
+
return _olm_enc_output(key, key_length, pickled, raw_length);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
size_t olm_unpickle_inbound_group_session(
|
|
226
|
+
OlmInboundGroupSession *session,
|
|
227
|
+
void const * key, size_t key_length,
|
|
228
|
+
void * pickled, size_t pickled_length
|
|
229
|
+
) {
|
|
230
|
+
const uint8_t *pos;
|
|
231
|
+
const uint8_t *end;
|
|
232
|
+
uint32_t pickle_version;
|
|
233
|
+
|
|
234
|
+
size_t raw_length = _olm_enc_input(
|
|
235
|
+
key, key_length, pickled, pickled_length, &(session->last_error)
|
|
236
|
+
);
|
|
237
|
+
if (raw_length == (size_t)-1) {
|
|
238
|
+
return raw_length;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
pos = pickled;
|
|
242
|
+
end = pos + raw_length;
|
|
243
|
+
pos = _olm_unpickle_uint32(pos, end, &pickle_version);
|
|
244
|
+
if (pickle_version < 1 || pickle_version > PICKLE_VERSION) {
|
|
245
|
+
session->last_error = OLM_UNKNOWN_PICKLE_VERSION;
|
|
246
|
+
return (size_t)-1;
|
|
247
|
+
}
|
|
248
|
+
pos = megolm_unpickle(&session->initial_ratchet, pos, end);
|
|
249
|
+
pos = megolm_unpickle(&session->latest_ratchet, pos, end);
|
|
250
|
+
pos = _olm_unpickle_ed25519_public_key(pos, end, &session->signing_key);
|
|
251
|
+
|
|
252
|
+
if (pickle_version == 1) {
|
|
253
|
+
/* pickle v1 had no signing_key_verified field (all keyshares were
|
|
254
|
+
* verified at import time) */
|
|
255
|
+
session->signing_key_verified = 1;
|
|
256
|
+
} else {
|
|
257
|
+
pos = _olm_unpickle_bool(pos, end, &(session->signing_key_verified));
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
if (end != pos) {
|
|
261
|
+
/* We had the wrong number of bytes in the input. */
|
|
262
|
+
session->last_error = OLM_CORRUPTED_PICKLE;
|
|
263
|
+
return (size_t)-1;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
return pickled_length;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* get the max plaintext length in an un-base64-ed message
|
|
271
|
+
*/
|
|
272
|
+
static size_t _decrypt_max_plaintext_length(
|
|
273
|
+
OlmInboundGroupSession *session,
|
|
274
|
+
uint8_t * message, size_t message_length
|
|
275
|
+
) {
|
|
276
|
+
struct _OlmDecodeGroupMessageResults decoded_results;
|
|
277
|
+
|
|
278
|
+
_olm_decode_group_message(
|
|
279
|
+
message, message_length,
|
|
280
|
+
megolm_cipher->ops->mac_length(megolm_cipher),
|
|
281
|
+
ED25519_SIGNATURE_LENGTH,
|
|
282
|
+
&decoded_results);
|
|
283
|
+
|
|
284
|
+
if (decoded_results.version != OLM_PROTOCOL_VERSION) {
|
|
285
|
+
session->last_error = OLM_BAD_MESSAGE_VERSION;
|
|
286
|
+
return (size_t)-1;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (!decoded_results.ciphertext) {
|
|
290
|
+
session->last_error = OLM_BAD_MESSAGE_FORMAT;
|
|
291
|
+
return (size_t)-1;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
return megolm_cipher->ops->decrypt_max_plaintext_length(
|
|
295
|
+
megolm_cipher, decoded_results.ciphertext_length);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
size_t olm_group_decrypt_max_plaintext_length(
|
|
299
|
+
OlmInboundGroupSession *session,
|
|
300
|
+
uint8_t * message, size_t message_length
|
|
301
|
+
) {
|
|
302
|
+
size_t raw_length;
|
|
303
|
+
|
|
304
|
+
raw_length = _olm_decode_base64(message, message_length, message);
|
|
305
|
+
if (raw_length == (size_t)-1) {
|
|
306
|
+
session->last_error = OLM_INVALID_BASE64;
|
|
307
|
+
return (size_t)-1;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
return _decrypt_max_plaintext_length(
|
|
311
|
+
session, message, raw_length
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* get a copy of the megolm ratchet, advanced
|
|
317
|
+
* to the relevant index. Returns 0 on success, -1 on error
|
|
318
|
+
*/
|
|
319
|
+
static size_t _get_megolm(
|
|
320
|
+
OlmInboundGroupSession *session, uint32_t message_index, Megolm *result
|
|
321
|
+
) {
|
|
322
|
+
/* pick a megolm instance to use. If we're at or beyond the latest ratchet
|
|
323
|
+
* value, use that */
|
|
324
|
+
if ((message_index - session->latest_ratchet.counter) < (1U << 31)) {
|
|
325
|
+
megolm_advance_to(&session->latest_ratchet, message_index);
|
|
326
|
+
*result = session->latest_ratchet;
|
|
327
|
+
return 0;
|
|
328
|
+
} else if ((message_index - session->initial_ratchet.counter) >= (1U << 31)) {
|
|
329
|
+
/* the counter is before our intial ratchet - we can't decode this. */
|
|
330
|
+
session->last_error = OLM_UNKNOWN_MESSAGE_INDEX;
|
|
331
|
+
return (size_t)-1;
|
|
332
|
+
} else {
|
|
333
|
+
/* otherwise, start from the initial megolm. Take a copy so that we
|
|
334
|
+
* don't overwrite the initial megolm */
|
|
335
|
+
*result = session->initial_ratchet;
|
|
336
|
+
megolm_advance_to(result, message_index);
|
|
337
|
+
return 0;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
/**
|
|
342
|
+
* decrypt an un-base64-ed message
|
|
343
|
+
*/
|
|
344
|
+
static size_t _decrypt(
|
|
345
|
+
OlmInboundGroupSession *session,
|
|
346
|
+
uint8_t * message, size_t message_length,
|
|
347
|
+
uint8_t * plaintext, size_t max_plaintext_length,
|
|
348
|
+
uint32_t * message_index
|
|
349
|
+
) {
|
|
350
|
+
struct _OlmDecodeGroupMessageResults decoded_results;
|
|
351
|
+
size_t max_length, r;
|
|
352
|
+
Megolm megolm;
|
|
353
|
+
|
|
354
|
+
_olm_decode_group_message(
|
|
355
|
+
message, message_length,
|
|
356
|
+
megolm_cipher->ops->mac_length(megolm_cipher),
|
|
357
|
+
ED25519_SIGNATURE_LENGTH,
|
|
358
|
+
&decoded_results);
|
|
359
|
+
|
|
360
|
+
if (decoded_results.version != OLM_PROTOCOL_VERSION) {
|
|
361
|
+
session->last_error = OLM_BAD_MESSAGE_VERSION;
|
|
362
|
+
return (size_t)-1;
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
if (!decoded_results.has_message_index || !decoded_results.ciphertext) {
|
|
366
|
+
session->last_error = OLM_BAD_MESSAGE_FORMAT;
|
|
367
|
+
return (size_t)-1;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
if (message_index != NULL) {
|
|
371
|
+
*message_index = decoded_results.message_index;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
/* verify the signature. We could do this before decoding the message, but
|
|
375
|
+
* we allow for the possibility of future protocol versions which use a
|
|
376
|
+
* different signing mechanism; we would rather throw "BAD_MESSAGE_VERSION"
|
|
377
|
+
* than "BAD_SIGNATURE" in this case.
|
|
378
|
+
*/
|
|
379
|
+
message_length -= ED25519_SIGNATURE_LENGTH;
|
|
380
|
+
r = _olm_crypto_ed25519_verify(
|
|
381
|
+
&session->signing_key,
|
|
382
|
+
message, message_length,
|
|
383
|
+
message + message_length
|
|
384
|
+
);
|
|
385
|
+
if (!r) {
|
|
386
|
+
session->last_error = OLM_BAD_SIGNATURE;
|
|
387
|
+
return (size_t)-1;
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
max_length = megolm_cipher->ops->decrypt_max_plaintext_length(
|
|
391
|
+
megolm_cipher,
|
|
392
|
+
decoded_results.ciphertext_length
|
|
393
|
+
);
|
|
394
|
+
if (max_plaintext_length < max_length) {
|
|
395
|
+
session->last_error = OLM_OUTPUT_BUFFER_TOO_SMALL;
|
|
396
|
+
return (size_t)-1;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
r = _get_megolm(session, decoded_results.message_index, &megolm);
|
|
400
|
+
if (r == (size_t)-1) {
|
|
401
|
+
return r;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/* now try checking the mac, and decrypting */
|
|
405
|
+
r = megolm_cipher->ops->decrypt(
|
|
406
|
+
megolm_cipher,
|
|
407
|
+
megolm_get_data(&megolm), MEGOLM_RATCHET_LENGTH,
|
|
408
|
+
message, message_length,
|
|
409
|
+
decoded_results.ciphertext, decoded_results.ciphertext_length,
|
|
410
|
+
plaintext, max_plaintext_length
|
|
411
|
+
);
|
|
412
|
+
|
|
413
|
+
_olm_unset(&megolm, sizeof(megolm));
|
|
414
|
+
if (r == (size_t)-1) {
|
|
415
|
+
session->last_error = OLM_BAD_MESSAGE_MAC;
|
|
416
|
+
return r;
|
|
417
|
+
}
|
|
418
|
+
|
|
419
|
+
/* once we have successfully decrypted a message, set a flag to say the
|
|
420
|
+
* session appears valid. */
|
|
421
|
+
session->signing_key_verified = 1;
|
|
422
|
+
|
|
423
|
+
return r;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
size_t olm_group_decrypt(
|
|
427
|
+
OlmInboundGroupSession *session,
|
|
428
|
+
uint8_t * message, size_t message_length,
|
|
429
|
+
uint8_t * plaintext, size_t max_plaintext_length,
|
|
430
|
+
uint32_t * message_index
|
|
431
|
+
) {
|
|
432
|
+
size_t raw_message_length;
|
|
433
|
+
|
|
434
|
+
raw_message_length = _olm_decode_base64(message, message_length, message);
|
|
435
|
+
if (raw_message_length == (size_t)-1) {
|
|
436
|
+
session->last_error = OLM_INVALID_BASE64;
|
|
437
|
+
return (size_t)-1;
|
|
438
|
+
}
|
|
439
|
+
|
|
440
|
+
return _decrypt(
|
|
441
|
+
session, message, raw_message_length,
|
|
442
|
+
plaintext, max_plaintext_length,
|
|
443
|
+
message_index
|
|
444
|
+
);
|
|
445
|
+
}
|
|
446
|
+
|
|
447
|
+
size_t olm_inbound_group_session_id_length(
|
|
448
|
+
const OlmInboundGroupSession *session
|
|
449
|
+
) {
|
|
450
|
+
return _olm_encode_base64_length(GROUP_SESSION_ID_LENGTH);
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
size_t olm_inbound_group_session_id(
|
|
454
|
+
OlmInboundGroupSession *session,
|
|
455
|
+
uint8_t * id, size_t id_length
|
|
456
|
+
) {
|
|
457
|
+
if (id_length < olm_inbound_group_session_id_length(session)) {
|
|
458
|
+
session->last_error = OLM_OUTPUT_BUFFER_TOO_SMALL;
|
|
459
|
+
return (size_t)-1;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
return _olm_encode_base64(
|
|
463
|
+
session->signing_key.public_key, GROUP_SESSION_ID_LENGTH, id
|
|
464
|
+
);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
uint32_t olm_inbound_group_session_first_known_index(
|
|
468
|
+
const OlmInboundGroupSession *session
|
|
469
|
+
) {
|
|
470
|
+
return session->initial_ratchet.counter;
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
int olm_inbound_group_session_is_verified(
|
|
474
|
+
const OlmInboundGroupSession *session
|
|
475
|
+
) {
|
|
476
|
+
return session->signing_key_verified;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
size_t olm_export_inbound_group_session_length(
|
|
480
|
+
const OlmInboundGroupSession *session
|
|
481
|
+
) {
|
|
482
|
+
return _olm_encode_base64_length(SESSION_EXPORT_RAW_LENGTH);
|
|
483
|
+
}
|
|
484
|
+
|
|
485
|
+
size_t olm_export_inbound_group_session(
|
|
486
|
+
OlmInboundGroupSession *session,
|
|
487
|
+
uint8_t * key, size_t key_length, uint32_t message_index
|
|
488
|
+
) {
|
|
489
|
+
uint8_t *raw;
|
|
490
|
+
uint8_t *ptr;
|
|
491
|
+
Megolm megolm;
|
|
492
|
+
size_t r;
|
|
493
|
+
size_t encoded_length = olm_export_inbound_group_session_length(session);
|
|
494
|
+
|
|
495
|
+
if (key_length < encoded_length) {
|
|
496
|
+
session->last_error = OLM_OUTPUT_BUFFER_TOO_SMALL;
|
|
497
|
+
return (size_t)-1;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
r = _get_megolm(session, message_index, &megolm);
|
|
501
|
+
if (r == (size_t)-1) {
|
|
502
|
+
return r;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/* put the raw data at the end of the output buffer. */
|
|
506
|
+
raw = ptr = key + encoded_length - SESSION_EXPORT_RAW_LENGTH;
|
|
507
|
+
*ptr++ = SESSION_EXPORT_VERSION;
|
|
508
|
+
|
|
509
|
+
// Encode message index as a big endian 32-bit number.
|
|
510
|
+
for (unsigned i = 0; i < 4; i++) {
|
|
511
|
+
*ptr++ = 0xFF & (message_index >> 24); message_index <<= 8;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
memcpy(ptr, megolm_get_data(&megolm), MEGOLM_RATCHET_LENGTH);
|
|
515
|
+
ptr += MEGOLM_RATCHET_LENGTH;
|
|
516
|
+
|
|
517
|
+
memcpy(
|
|
518
|
+
ptr, session->signing_key.public_key,
|
|
519
|
+
ED25519_PUBLIC_KEY_LENGTH
|
|
520
|
+
);
|
|
521
|
+
ptr += ED25519_PUBLIC_KEY_LENGTH;
|
|
522
|
+
|
|
523
|
+
return _olm_encode_base64(raw, SESSION_EXPORT_RAW_LENGTH, key);
|
|
524
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/* Copyright 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
|
+
|
|
16
|
+
|
|
17
|
+
#include "olm/megolm.h"
|
|
18
|
+
|
|
19
|
+
#include <string.h>
|
|
20
|
+
|
|
21
|
+
#include "olm/cipher.h"
|
|
22
|
+
#include "olm/crypto.h"
|
|
23
|
+
#include "olm/pickle.h"
|
|
24
|
+
|
|
25
|
+
static const struct _olm_cipher_aes_sha_256 MEGOLM_CIPHER =
|
|
26
|
+
OLM_CIPHER_INIT_AES_SHA_256("MEGOLM_KEYS");
|
|
27
|
+
const struct _olm_cipher *megolm_cipher = OLM_CIPHER_BASE(&MEGOLM_CIPHER);
|
|
28
|
+
|
|
29
|
+
/* the seeds used in the HMAC-SHA-256 functions for each part of the ratchet.
|
|
30
|
+
*/
|
|
31
|
+
#define HASH_KEY_SEED_LENGTH 1
|
|
32
|
+
static uint8_t HASH_KEY_SEEDS[MEGOLM_RATCHET_PARTS][HASH_KEY_SEED_LENGTH] = {
|
|
33
|
+
{0x00},
|
|
34
|
+
{0x01},
|
|
35
|
+
{0x02},
|
|
36
|
+
{0x03}
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
static void rehash_part(
|
|
40
|
+
uint8_t data[MEGOLM_RATCHET_PARTS][MEGOLM_RATCHET_PART_LENGTH],
|
|
41
|
+
int rehash_from_part, int rehash_to_part
|
|
42
|
+
) {
|
|
43
|
+
_olm_crypto_hmac_sha256(
|
|
44
|
+
data[rehash_from_part],
|
|
45
|
+
MEGOLM_RATCHET_PART_LENGTH,
|
|
46
|
+
HASH_KEY_SEEDS[rehash_to_part], HASH_KEY_SEED_LENGTH,
|
|
47
|
+
data[rehash_to_part]
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
void megolm_init(Megolm *megolm, uint8_t const *random_data, uint32_t counter) {
|
|
54
|
+
megolm->counter = counter;
|
|
55
|
+
memcpy(megolm->data, random_data, MEGOLM_RATCHET_LENGTH);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
size_t megolm_pickle_length(const Megolm *megolm) {
|
|
59
|
+
size_t length = 0;
|
|
60
|
+
length += _olm_pickle_bytes_length(megolm_get_data(megolm), MEGOLM_RATCHET_LENGTH);
|
|
61
|
+
length += _olm_pickle_uint32_length(megolm->counter);
|
|
62
|
+
return length;
|
|
63
|
+
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
uint8_t * megolm_pickle(const Megolm *megolm, uint8_t *pos) {
|
|
67
|
+
pos = _olm_pickle_bytes(pos, megolm_get_data(megolm), MEGOLM_RATCHET_LENGTH);
|
|
68
|
+
pos = _olm_pickle_uint32(pos, megolm->counter);
|
|
69
|
+
return pos;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const uint8_t * megolm_unpickle(Megolm *megolm, const uint8_t *pos,
|
|
73
|
+
const uint8_t *end) {
|
|
74
|
+
pos = _olm_unpickle_bytes(pos, end, (uint8_t *)(megolm->data),
|
|
75
|
+
MEGOLM_RATCHET_LENGTH);
|
|
76
|
+
pos = _olm_unpickle_uint32(pos, end, &megolm->counter);
|
|
77
|
+
return pos;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* simplistic implementation for a single step */
|
|
81
|
+
void megolm_advance(Megolm *megolm) {
|
|
82
|
+
uint32_t mask = 0x00FFFFFF;
|
|
83
|
+
int h = 0;
|
|
84
|
+
int i;
|
|
85
|
+
|
|
86
|
+
megolm->counter++;
|
|
87
|
+
|
|
88
|
+
/* figure out how much we need to rekey */
|
|
89
|
+
while (h < (int)MEGOLM_RATCHET_PARTS) {
|
|
90
|
+
if (!(megolm->counter & mask))
|
|
91
|
+
break;
|
|
92
|
+
h++;
|
|
93
|
+
mask >>= 8;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/* now update R(h)...R(3) based on R(h) */
|
|
97
|
+
for (i = MEGOLM_RATCHET_PARTS-1; i >= h; i--) {
|
|
98
|
+
rehash_part(megolm->data, h, i);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
void megolm_advance_to(Megolm *megolm, uint32_t advance_to) {
|
|
103
|
+
int j;
|
|
104
|
+
|
|
105
|
+
/* starting with R0, see if we need to update each part of the hash */
|
|
106
|
+
for (j = 0; j < (int)MEGOLM_RATCHET_PARTS; j++) {
|
|
107
|
+
int shift = (MEGOLM_RATCHET_PARTS-j-1) * 8;
|
|
108
|
+
uint32_t mask = (~(uint32_t)0) << shift;
|
|
109
|
+
int k;
|
|
110
|
+
|
|
111
|
+
/* how many times do we need to rehash this part?
|
|
112
|
+
*
|
|
113
|
+
* '& 0xff' ensures we handle integer wraparound correctly
|
|
114
|
+
*/
|
|
115
|
+
unsigned int steps =
|
|
116
|
+
((advance_to >> shift) - (megolm->counter >> shift)) & 0xff;
|
|
117
|
+
|
|
118
|
+
if (steps == 0) {
|
|
119
|
+
/* deal with the edge case where megolm->counter is slightly larger
|
|
120
|
+
* than advance_to. This should only happen for R(0), and implies
|
|
121
|
+
* that advance_to has wrapped around and we need to advance R(0)
|
|
122
|
+
* 256 times.
|
|
123
|
+
*/
|
|
124
|
+
if (advance_to < megolm->counter) {
|
|
125
|
+
steps = 0x100;
|
|
126
|
+
} else {
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/* for all but the last step, we can just bump R(j) without regard
|
|
132
|
+
* to R(j+1)...R(3).
|
|
133
|
+
*/
|
|
134
|
+
while (steps > 1) {
|
|
135
|
+
rehash_part(megolm->data, j, j);
|
|
136
|
+
steps --;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* on the last step we also need to bump R(j+1)...R(3).
|
|
140
|
+
*
|
|
141
|
+
* (Theoretically, we could skip bumping R(j+2) if we're going to bump
|
|
142
|
+
* R(j+1) again, but the code to figure that out is a bit baroque and
|
|
143
|
+
* doesn't save us much).
|
|
144
|
+
*/
|
|
145
|
+
for (k = 3; k >= j; k--) {
|
|
146
|
+
rehash_part(megolm->data, j, k);
|
|
147
|
+
}
|
|
148
|
+
megolm->counter = advance_to & mask;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/* Copyright 2015 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/memory.hh"
|
|
16
|
+
#include "olm/memory.h"
|
|
17
|
+
|
|
18
|
+
void _olm_unset(
|
|
19
|
+
void volatile * buffer, size_t buffer_length
|
|
20
|
+
) {
|
|
21
|
+
olm::unset(buffer, buffer_length);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
void olm::unset(
|
|
25
|
+
void volatile * buffer, std::size_t buffer_length
|
|
26
|
+
) {
|
|
27
|
+
char volatile * pos = reinterpret_cast<char volatile *>(buffer);
|
|
28
|
+
char volatile * end = pos + buffer_length;
|
|
29
|
+
while (pos != end) {
|
|
30
|
+
*(pos++) = 0;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
bool olm::is_equal(
|
|
36
|
+
std::uint8_t const * buffer_a,
|
|
37
|
+
std::uint8_t const * buffer_b,
|
|
38
|
+
std::size_t length
|
|
39
|
+
) {
|
|
40
|
+
std::uint8_t volatile result = 0;
|
|
41
|
+
while (length--) {
|
|
42
|
+
result |= (*(buffer_a++)) ^ (*(buffer_b++));
|
|
43
|
+
}
|
|
44
|
+
return result == 0;
|
|
45
|
+
}
|