aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/olm/inbound_group_session.h23
-rw-r--r--javascript/olm_inbound_group_session.js15
-rw-r--r--python/olm/inbound_group_session.py15
-rw-r--r--src/inbound_group_session.c49
-rw-r--r--src/outbound_group_session.c41
-rw-r--r--tests/test_group_session.cpp39
6 files changed, 137 insertions, 45 deletions
diff --git a/include/olm/inbound_group_session.h b/include/olm/inbound_group_session.h
index 49992b2..59146c2 100644
--- a/include/olm/inbound_group_session.h
+++ b/include/olm/inbound_group_session.h
@@ -95,8 +95,6 @@ size_t olm_unpickle_inbound_group_session(
*/
size_t olm_init_inbound_group_session(
OlmInboundGroupSession *session,
- uint32_t message_index,
-
/* base64-encoded keys */
uint8_t const * session_key, size_t session_key_length
);
@@ -146,6 +144,27 @@ size_t olm_group_decrypt(
);
+/**
+ * Get the number of bytes returned by olm_inbound_group_session_id()
+ */
+size_t olm_inbound_group_session_id_length(
+ const OlmInboundGroupSession *session
+);
+
+/**
+ * Get a base64-encoded identifier for this session.
+ *
+ * Returns the length of the session id on success or olm_error() on
+ * failure. On failure last_error will be set with an error code. The
+ * last_error will be OUTPUT_BUFFER_TOO_SMALL if the id buffer was too
+ * small.
+ */
+size_t olm_inbound_group_session_id(
+ OlmInboundGroupSession *session,
+ uint8_t * id, size_t id_length
+);
+
+
#ifdef __cplusplus
} // extern "C"
#endif
diff --git a/javascript/olm_inbound_group_session.js b/javascript/olm_inbound_group_session.js
index 9722c31..6058233 100644
--- a/javascript/olm_inbound_group_session.js
+++ b/javascript/olm_inbound_group_session.js
@@ -52,12 +52,12 @@ InboundGroupSession.prototype['unpickle'] = restore_stack(function(key, pickle)
);
});
-InboundGroupSession.prototype['create'] = restore_stack(function(message_index, session_key) {
+InboundGroupSession.prototype['create'] = restore_stack(function(session_key) {
var key_array = array_from_string(session_key);
var key_buffer = stack(key_array);
inbound_group_session_method(Module['_olm_init_inbound_group_session'])(
- this.ptr, message_index, key_buffer, key_array.length
+ this.ptr, key_buffer, key_array.length
);
});
@@ -89,4 +89,15 @@ InboundGroupSession.prototype['decrypt'] = restore_stack(function(
return Pointer_stringify(plaintext_buffer);
});
+InboundGroupSession.prototype['session_id'] = restore_stack(function() {
+ var length = inbound_group_session_method(
+ Module['_olm_inbound_group_session_id_length']
+ )(this.ptr);
+ var session_id = stack(length + NULL_BYTE_PADDING_LENGTH);
+ inbound_group_session_method(Module['_olm_inbound_group_session_id'])(
+ this.ptr, session_id, length
+ );
+ return Pointer_stringify(session_id);
+});
+
olm_exports['InboundGroupSession'] = InboundGroupSession;
diff --git a/python/olm/inbound_group_session.py b/python/olm/inbound_group_session.py
index 6c01095..d5547fd 100644
--- a/python/olm/inbound_group_session.py
+++ b/python/olm/inbound_group_session.py
@@ -33,7 +33,7 @@ inbound_group_session_function(
)
inbound_group_session_function(
- lib.olm_init_inbound_group_session, c_uint32, c_void_p, c_size_t
+ lib.olm_init_inbound_group_session, c_void_p, c_size_t
)
inbound_group_session_function(
@@ -45,6 +45,9 @@ inbound_group_session_function(
c_void_p, c_size_t, # plaintext
)
+inbound_group_session_function(lib.olm_inbound_group_session_id_length)
+inbound_group_session_function(lib.olm_inbound_group_session_id, c_void_p, c_size_t)
+
class InboundGroupSession(object):
def __init__(self):
self.buf = create_string_buffer(lib.olm_inbound_group_session_size())
@@ -66,10 +69,10 @@ class InboundGroupSession(object):
self.ptr, key_buffer, len(key), pickle_buffer, len(pickle)
)
- def init(self, message_index, session_key):
+ def init(self, session_key):
key_buffer = create_string_buffer(session_key)
lib.olm_init_inbound_group_session(
- self.ptr, message_index, key_buffer, len(session_key)
+ self.ptr, key_buffer, len(session_key)
)
def decrypt(self, message):
@@ -84,3 +87,9 @@ class InboundGroupSession(object):
plaintext_buffer, max_plaintext_length
)
return plaintext_buffer.raw[:plaintext_length]
+
+ def session_id(self):
+ id_length = lib.olm_inbound_group_session_id_length(self.ptr)
+ id_buffer = create_string_buffer(id_length)
+ lib.olm_inbound_group_session_id(self.ptr, id_buffer, id_length);
+ return id_buffer.raw
diff --git a/src/inbound_group_session.c b/src/inbound_group_session.c
index 11e3dbe..bf00008 100644
--- a/src/inbound_group_session.c
+++ b/src/inbound_group_session.c
@@ -29,8 +29,9 @@
#define OLM_PROTOCOL_VERSION 3
+#define GROUP_SESSION_ID_LENGTH ED25519_PUBLIC_KEY_LENGTH
#define PICKLE_VERSION 1
-#define SESSION_KEY_VERSION 1
+#define SESSION_KEY_VERSION 2
struct OlmInboundGroupSession {
/** our earliest known ratchet value */
@@ -71,12 +72,12 @@ size_t olm_clear_inbound_group_session(
}
#define SESSION_KEY_RAW_LENGTH \
- (1 + MEGOLM_RATCHET_LENGTH + ED25519_PUBLIC_KEY_LENGTH)
+ (1 + 4 + MEGOLM_RATCHET_LENGTH + ED25519_PUBLIC_KEY_LENGTH\
+ + ED25519_SIGNATURE_LENGTH)
/** init the session keys from the un-base64-ed session keys */
static size_t _init_group_session_keys(
OlmInboundGroupSession *session,
- uint32_t message_index,
const uint8_t *key_buf
) {
const uint8_t *ptr = key_buf;
@@ -87,19 +88,32 @@ static size_t _init_group_session_keys(
return (size_t)-1;
}
- megolm_init(&session->initial_ratchet, ptr, message_index);
- megolm_init(&session->latest_ratchet, ptr, message_index);
+ uint32_t counter = 0;
+ // Decode counter as a big endian 32-bit number.
+ for (unsigned i = 0; i < 4; i++) {
+ counter <<= 8; counter |= *ptr++;
+ }
+
+ megolm_init(&session->initial_ratchet, ptr, counter);
+ megolm_init(&session->latest_ratchet, ptr, counter);
+
ptr += MEGOLM_RATCHET_LENGTH;
memcpy(
session->signing_key.public_key, ptr, ED25519_PUBLIC_KEY_LENGTH
);
ptr += ED25519_PUBLIC_KEY_LENGTH;
+
+ if (!_olm_crypto_ed25519_verify(
+ &session->signing_key, key_buf, ptr - key_buf, ptr
+ )) {
+ session->last_error = OLM_BAD_SIGNATURE;
+ return (size_t)-1;
+ }
return 0;
}
size_t olm_init_inbound_group_session(
OlmInboundGroupSession *session,
- uint32_t message_index,
const uint8_t * session_key, size_t session_key_length
) {
uint8_t key_buf[SESSION_KEY_RAW_LENGTH];
@@ -117,7 +131,7 @@ size_t olm_init_inbound_group_session(
}
_olm_decode_base64(session_key, session_key_length, key_buf);
- result = _init_group_session_keys(session, message_index, key_buf);
+ result = _init_group_session_keys(session, key_buf);
_olm_unset(key_buf, SESSION_KEY_RAW_LENGTH);
return result;
}
@@ -288,7 +302,6 @@ static size_t _decrypt(
return (size_t)-1;
}
-
max_length = megolm_cipher->ops->decrypt_max_plaintext_length(
megolm_cipher,
decoded_results.ciphertext_length
@@ -351,3 +364,23 @@ size_t olm_group_decrypt(
plaintext, max_plaintext_length
);
}
+
+size_t olm_inbound_group_session_id_length(
+ const OlmInboundGroupSession *session
+) {
+ return _olm_encode_base64_length(GROUP_SESSION_ID_LENGTH);
+}
+
+size_t olm_inbound_group_session_id(
+ OlmInboundGroupSession *session,
+ uint8_t * id, size_t id_length
+) {
+ if (id_length < olm_inbound_group_session_id_length(session)) {
+ session->last_error = OLM_OUTPUT_BUFFER_TOO_SMALL;
+ return (size_t)-1;
+ }
+
+ return _olm_encode_base64(
+ session->signing_key.public_key, GROUP_SESSION_ID_LENGTH, id
+ );
+}
diff --git a/src/outbound_group_session.c b/src/outbound_group_session.c
index a605fa6..4e4561a 100644
--- a/src/outbound_group_session.c
+++ b/src/outbound_group_session.c
@@ -29,10 +29,9 @@
#include "olm/pickle_encoding.h"
#define OLM_PROTOCOL_VERSION 3
-#define SESSION_ID_RANDOM_BYTES 4
-#define GROUP_SESSION_ID_LENGTH (sizeof(struct timeval) + SESSION_ID_RANDOM_BYTES)
+#define GROUP_SESSION_ID_LENGTH ED25519_PUBLIC_KEY_LENGTH
#define PICKLE_VERSION 1
-#define SESSION_KEY_VERSION 1
+#define SESSION_KEY_VERSION 2
struct OlmOutboundGroupSession {
/** the Megolm ratchet providing the encryption keys */
@@ -41,9 +40,6 @@ struct OlmOutboundGroupSession {
/** The ed25519 keypair used for signing the messages */
struct _olm_ed25519_key_pair signing_key;
- /** unique identifier for this session */
- uint8_t session_id[GROUP_SESSION_ID_LENGTH];
-
enum OlmErrorCode last_error;
};
@@ -80,8 +76,6 @@ static size_t raw_pickle_length(
length += _olm_pickle_uint32_length(PICKLE_VERSION);
length += megolm_pickle_length(&(session->ratchet));
length += _olm_pickle_ed25519_key_pair_length(&(session->signing_key));
- length += _olm_pickle_bytes_length(session->session_id,
- GROUP_SESSION_ID_LENGTH);
return length;
}
@@ -108,7 +102,6 @@ size_t olm_pickle_outbound_group_session(
pos = _olm_pickle_uint32(pos, PICKLE_VERSION);
pos = megolm_pickle(&(session->ratchet), pos);
pos = _olm_pickle_ed25519_key_pair(pos, &(session->signing_key));
- pos = _olm_pickle_bytes(pos, session->session_id, GROUP_SESSION_ID_LENGTH);
return _olm_enc_output(key, key_length, pickled, raw_length);
}
@@ -138,7 +131,6 @@ size_t olm_unpickle_outbound_group_session(
}
pos = megolm_unpickle(&(session->ratchet), pos, end);
pos = _olm_unpickle_ed25519_key_pair(pos, end, &(session->signing_key));
- pos = _olm_unpickle_bytes(pos, end, session->session_id, GROUP_SESSION_ID_LENGTH);
if (end != pos) {
/* We had the wrong number of bytes in the input. */
@@ -157,8 +149,7 @@ size_t olm_init_outbound_group_session_random_length(
* session id.
*/
return MEGOLM_RATCHET_LENGTH +
- ED25519_RANDOM_LENGTH +
- SESSION_ID_RANDOM_BYTES;
+ ED25519_RANDOM_LENGTH;
}
size_t olm_init_outbound_group_session(
@@ -177,13 +168,6 @@ size_t olm_init_outbound_group_session(
_olm_crypto_ed25519_generate_key(random, &(session->signing_key));
random += ED25519_RANDOM_LENGTH;
- /* initialise the session id. This just has to be unique. We use the
- * current time plus some random data.
- */
- gettimeofday((struct timeval *)(session->session_id), NULL);
- memcpy((session->session_id) + sizeof(struct timeval),
- random, SESSION_ID_RANDOM_BYTES);
-
return 0;
}
@@ -314,7 +298,9 @@ size_t olm_outbound_group_session_id(
return (size_t)-1;
}
- return _olm_encode_base64(session->session_id, GROUP_SESSION_ID_LENGTH, id);
+ return _olm_encode_base64(
+ session->signing_key.public_key.public_key, GROUP_SESSION_ID_LENGTH, id
+ );
}
uint32_t olm_outbound_group_session_message_index(
@@ -324,7 +310,8 @@ uint32_t olm_outbound_group_session_message_index(
}
#define SESSION_KEY_RAW_LENGTH \
- (1 + MEGOLM_RATCHET_LENGTH + ED25519_PUBLIC_KEY_LENGTH)
+ (1 + 4 + MEGOLM_RATCHET_LENGTH + ED25519_PUBLIC_KEY_LENGTH\
+ + ED25519_SIGNATURE_LENGTH)
size_t olm_outbound_group_session_key_length(
const OlmOutboundGroupSession *session
@@ -349,6 +336,12 @@ size_t olm_outbound_group_session_key(
raw = ptr = key + encoded_length - SESSION_KEY_RAW_LENGTH;
*ptr++ = SESSION_KEY_VERSION;
+ uint32_t counter = session->ratchet.counter;
+ // Encode counter as a big endian 32-bit number.
+ for (unsigned i = 0; i < 4; i++) {
+ *ptr++ = 0xFF & (counter >> 24); counter <<= 8;
+ }
+
memcpy(ptr, megolm_get_data(&session->ratchet), MEGOLM_RATCHET_LENGTH);
ptr += MEGOLM_RATCHET_LENGTH;
@@ -358,5 +351,11 @@ size_t olm_outbound_group_session_key(
);
ptr += ED25519_PUBLIC_KEY_LENGTH;
+ /* sign the whole thing with the ed25519 key. */
+ _olm_crypto_ed25519_sign(
+ &(session->signing_key),
+ raw, ptr - raw, ptr
+ );
+
return _olm_encode_base64(raw, SESSION_KEY_RAW_LENGTH, key);
}
diff --git a/tests/test_group_session.cpp b/tests/test_group_session.cpp
index 7ac91c3..9930927 100644
--- a/tests/test_group_session.cpp
+++ b/tests/test_group_session.cpp
@@ -97,7 +97,7 @@ int main() {
uint8_t memory[size];
OlmOutboundGroupSession *session = olm_outbound_group_session(memory);
- assert_equals((size_t)164,
+ assert_equals((size_t)160,
olm_init_outbound_group_session_random_length(session));
size_t res = olm_init_outbound_group_session(
@@ -130,9 +130,29 @@ int main() {
olm_inbound_group_session(inbound_session_memory);
res = olm_init_inbound_group_session(
- inbound_session, 0U, session_key, session_key_len);
+ inbound_session, session_key, session_key_len);
assert_equals((size_t)0, res);
+
+ /* Check the session ids */
+
+ size_t out_session_id_len = olm_outbound_group_session_id_length(session);
+ uint8_t out_session_id[out_session_id_len];
+ assert_equals(out_session_id_len, olm_outbound_group_session_id(
+ session, out_session_id, out_session_id_len
+ ));
+
+ size_t in_session_id_len = olm_inbound_group_session_id_length(
+ inbound_session
+ );
+ uint8_t in_session_id[in_session_id_len];
+ assert_equals(in_session_id_len, olm_inbound_group_session_id(
+ inbound_session, in_session_id, in_session_id_len
+ ));
+
+ assert_equals(in_session_id_len, out_session_id_len);
+ assert_equals(out_session_id, in_session_id, in_session_id_len);
+
/* decode the message */
/* olm_group_decrypt_max_plaintext_length destroys the input so we have to
@@ -154,14 +174,15 @@ int main() {
size_t plaintext_length = sizeof(plaintext) - 1;
uint8_t session_key[] =
- "ATAxMjM0NTY3ODlBQkRFRjAxMjM0NTY3ODlBQkNERUYwMTIzNDU2Nzg5QUJERUYw"
- "MTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4OUFCREVGMDEyMzQ1Njc4OUFCQ0RFRjAx"
- "MjM0NTY3ODlBQkRFRjAxMjM0NTY3ODlBQkNERUYwMTIzDRt2DUEOrg/H+yUGjDTq"
- "ryf8H1YF/BZjI04HwOVSZcY";
+ "AgAAAAAwMTIzNDU2Nzg5QUJERUYwMTIzNDU2Nzg5QUJDREVGMDEyMzQ1Njc4OUFCREVGM"
+ "DEyMzQ1Njc4OUFCQ0RFRjAxMjM0NTY3ODlBQkRFRjAxMjM0NTY3ODlBQkNERUYwMTIzND"
+ "U2Nzg5QUJERUYwMTIzNDU2Nzg5QUJDREVGMDEyMztqJ7zOtqQtYqOo0CpvDXNlMhV3HeJ"
+ "DpjrASKGLWdop4lx1cSN3Xv1TgfLPW8rhGiW+hHiMxd36nRuxscNv9k4oJA/KP+o0mi1w"
+ "v44StrEJ1wwx9WZHBUIWkQbaBSuBDw";
uint8_t message[] =
- "AwgAEhAcbh6UpbByoyZxufQ+h2B+8XHMjhR69G8F4+qjMaFlnIXusJZX3r8LnROR"
- "G9T3DXFdbVuvIWrLyRfm4i8QRbe8VPwGRFG57B1CtmxanuP8bHtnnYqlwPsD";
+ "AwgAEhAcbh6UpbByoyZxufQ+h2B+8XHMjhR69G8nP4pNZGl/3QMgrzCZPmP+F2aPLyKPz"
+ "xRPBMUkeXRJ6Iqm5NeOdx2eERgTW7P20CM+lL3Xpk+ZUOOPvsSQNaAL";
size_t msglen = sizeof(message)-1;
/* build the inbound session */
@@ -171,7 +192,7 @@ int main() {
olm_inbound_group_session(inbound_session_memory);
size_t res = olm_init_inbound_group_session(
- inbound_session, 0U, session_key, sizeof(session_key)-1
+ inbound_session, session_key, sizeof(session_key)-1
);
assert_equals((size_t)0, res);