Skip to content
GitLab
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Menu
Open sidebar
matrix-org
Olm
Commits
c0585541
Commit
c0585541
authored
May 17, 2016
by
Richard van der Hoff
Browse files
Implement pickling/unpickling for outbound group sessions
parent
caaed796
Changes
5
Hide whitespace changes
Inline
Side-by-side
include/olm/megolm.h
View file @
c0585541
...
...
@@ -61,6 +61,21 @@ const struct _olm_cipher *megolm_cipher();
*/
void
megolm_init
(
Megolm
*
megolm
,
uint8_t
const
*
random_data
,
uint32_t
counter
);
/** Returns the number of bytes needed to store a megolm */
size_t
megolm_pickle_length
(
const
Megolm
*
megolm
);
/**
* Pickle the megolm. Returns a pointer to the next free space in the buffer.
*/
uint8_t
*
megolm_pickle
(
const
Megolm
*
megolm
,
uint8_t
*
pos
);
/**
* Unpickle the megolm. Returns a pointer to the next item in the buffer.
*/
const
uint8_t
*
megolm_unpickle
(
Megolm
*
megolm
,
const
uint8_t
*
pos
,
const
uint8_t
*
end
);
/** advance the ratchet by one step */
void
megolm_advance
(
Megolm
*
megolm
);
...
...
include/olm/outbound_group_session.h
View file @
c0585541
...
...
@@ -48,6 +48,42 @@ size_t olm_clear_outbound_group_session(
OlmOutboundGroupSession
*
session
);
/** Returns the number of bytes needed to store an outbound group session */
size_t
olm_pickle_outbound_group_session_length
(
const
OlmOutboundGroupSession
*
session
);
/**
* Stores a group session as a base64 string. Encrypts the session using the
* supplied key. Returns the length of the session on success.
*
* Returns olm_error() on failure. If the pickle output buffer
* is smaller than olm_pickle_outbound_group_session_length() then
* olm_outbound_group_session_last_error() will be "OUTPUT_BUFFER_TOO_SMALL"
*/
size_t
olm_pickle_outbound_group_session
(
OlmOutboundGroupSession
*
session
,
void
const
*
key
,
size_t
key_length
,
void
*
pickled
,
size_t
pickled_length
);
/**
* Loads a group session from a pickled base64 string. Decrypts the session
* using the supplied key.
*
* Returns olm_error() on failure. If the key doesn't match the one used to
* encrypt the account then olm_outbound_group_session_last_error() will be
* "BAD_ACCOUNT_KEY". If the base64 couldn't be decoded then
* olm_outbound_group_session_last_error() will be "INVALID_BASE64". The input
* pickled buffer is destroyed
*/
size_t
olm_unpickle_outbound_group_session
(
OlmOutboundGroupSession
*
session
,
void
const
*
key
,
size_t
key_length
,
void
*
pickled
,
size_t
pickled_length
);
/** The number of random bytes needed to create an outbound group session */
size_t
olm_init_outbound_group_session_random_length
(
const
OlmOutboundGroupSession
*
session
...
...
src/megolm.c
View file @
c0585541
...
...
@@ -20,6 +20,7 @@
#include
"olm/cipher.h"
#include
"olm/crypto.h"
#include
"olm/pickle.h"
const
struct
_olm_cipher
*
megolm_cipher
()
{
static
const
uint8_t
CIPHER_KDF_INFO
[]
=
"MEGOLM_KEYS"
;
...
...
@@ -59,12 +60,32 @@ static void rehash_part(
void
megolm_init
(
Megolm
*
megolm
,
uint8_t
const
*
random_data
,
uint32_t
counter
)
{
void
megolm_init
(
Megolm
*
megolm
,
uint8_t
const
*
random_data
,
uint32_t
counter
)
{
megolm
->
counter
=
counter
;
memcpy
(
megolm
->
data
,
random_data
,
MEGOLM_RATCHET_LENGTH
);
}
size_t
megolm_pickle_length
(
const
Megolm
*
megolm
)
{
size_t
length
=
0
;
length
+=
_olm_pickle_bytes_length
(
megolm_get_data
(
megolm
),
MEGOLM_RATCHET_LENGTH
);
length
+=
_olm_pickle_uint32_length
(
megolm
->
counter
);
return
length
;
}
uint8_t
*
megolm_pickle
(
const
Megolm
*
megolm
,
uint8_t
*
pos
)
{
pos
=
_olm_pickle_bytes
(
pos
,
megolm_get_data
(
megolm
),
MEGOLM_RATCHET_LENGTH
);
pos
=
_olm_pickle_uint32
(
pos
,
megolm
->
counter
);
return
pos
;
}
const
uint8_t
*
megolm_unpickle
(
Megolm
*
megolm
,
const
uint8_t
*
pos
,
const
uint8_t
*
end
)
{
pos
=
_olm_unpickle_bytes
(
pos
,
end
,
(
uint8_t
*
)(
megolm
->
data
),
MEGOLM_RATCHET_LENGTH
);
pos
=
_olm_unpickle_uint32
(
pos
,
end
,
&
megolm
->
counter
);
return
pos
;
}
/* simplistic implementation for a single step */
void
megolm_advance
(
Megolm
*
megolm
)
{
...
...
src/outbound_group_session.c
View file @
c0585541
...
...
@@ -23,10 +23,13 @@
#include
"olm/error.h"
#include
"olm/megolm.h"
#include
"olm/message.h"
#include
"olm/pickle.h"
#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 PICKLE_VERSION 1
struct
OlmOutboundGroupSession
{
/** the Megolm ratchet providing the encryption keys */
...
...
@@ -64,6 +67,80 @@ size_t olm_clear_outbound_group_session(
return
sizeof
(
OlmOutboundGroupSession
);
}
static
size_t
raw_pickle_length
(
const
OlmOutboundGroupSession
*
session
)
{
size_t
length
=
0
;
length
+=
_olm_pickle_uint32_length
(
PICKLE_VERSION
);
length
+=
megolm_pickle_length
(
&
(
session
->
ratchet
));
length
+=
_olm_pickle_bytes_length
(
session
->
session_id
,
GROUP_SESSION_ID_LENGTH
);
return
length
;
}
size_t
olm_pickle_outbound_group_session_length
(
const
OlmOutboundGroupSession
*
session
)
{
return
_olm_enc_output_length
(
raw_pickle_length
(
session
));
}
size_t
olm_pickle_outbound_group_session
(
OlmOutboundGroupSession
*
session
,
void
const
*
key
,
size_t
key_length
,
void
*
pickled
,
size_t
pickled_length
)
{
size_t
raw_length
=
raw_pickle_length
(
session
);
uint8_t
*
pos
;
if
(
pickled_length
<
_olm_enc_output_length
(
raw_length
))
{
session
->
last_error
=
OLM_OUTPUT_BUFFER_TOO_SMALL
;
return
(
size_t
)
-
1
;
}
pos
=
_olm_enc_output_pos
(
pickled
,
raw_length
);
pos
=
_olm_pickle_uint32
(
pos
,
PICKLE_VERSION
);
pos
=
megolm_pickle
(
&
(
session
->
ratchet
),
pos
);
pos
=
_olm_pickle_bytes
(
pos
,
session
->
session_id
,
GROUP_SESSION_ID_LENGTH
);
return
_olm_enc_output
(
key
,
key_length
,
pickled
,
raw_length
);
}
size_t
olm_unpickle_outbound_group_session
(
OlmOutboundGroupSession
*
session
,
void
const
*
key
,
size_t
key_length
,
void
*
pickled
,
size_t
pickled_length
)
{
const
uint8_t
*
pos
;
const
uint8_t
*
end
;
uint32_t
pickle_version
;
size_t
raw_length
=
_olm_enc_input
(
key
,
key_length
,
pickled
,
pickled_length
,
&
(
session
->
last_error
)
);
if
(
raw_length
==
(
size_t
)
-
1
)
{
return
raw_length
;
}
pos
=
pickled
;
end
=
pos
+
raw_length
;
pos
=
_olm_unpickle_uint32
(
pos
,
end
,
&
pickle_version
);
if
(
pickle_version
!=
PICKLE_VERSION
)
{
session
->
last_error
=
OLM_UNKNOWN_PICKLE_VERSION
;
return
(
size_t
)
-
1
;
}
pos
=
megolm_unpickle
(
&
(
session
->
ratchet
),
pos
,
end
);
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. */
session
->
last_error
=
OLM_CORRUPTED_PICKLE
;
return
(
size_t
)
-
1
;
}
return
pickled_length
;
}
size_t
olm_init_outbound_group_session_random_length
(
const
OlmOutboundGroupSession
*
session
)
{
...
...
tests/test_group_session.cpp
View file @
c0585541
...
...
@@ -18,16 +18,50 @@
int
main
()
{
uint8_t
random_bytes
[]
=
"0123456789ABDEF0123456789ABCDEF"
"0123456789ABDEF0123456789ABCDEF"
"0123456789ABDEF0123456789ABCDEF"
"0123456789ABDEF0123456789ABCDEF"
"0123456789ABDEF0123456789ABCDEF"
;
{
TestCase
test_case
(
"Pickle outbound group"
);
size_t
size
=
olm_outbound_group_session_size
();
void
*
memory
=
alloca
(
size
);
OlmOutboundGroupSession
*
session
=
olm_outbound_group_session
(
memory
);
size_t
pickle_length
=
olm_pickle_outbound_group_session_length
(
session
);
uint8_t
pickle1
[
pickle_length
];
olm_pickle_outbound_group_session
(
session
,
"secret_key"
,
10
,
pickle1
,
pickle_length
);
uint8_t
pickle2
[
pickle_length
];
memcpy
(
pickle2
,
pickle1
,
pickle_length
);
uint8_t
buffer2
[
size
];
OlmOutboundGroupSession
*
session2
=
olm_outbound_group_session
(
buffer2
);
size_t
res
=
olm_unpickle_outbound_group_session
(
session2
,
"secret_key"
,
10
,
pickle2
,
pickle_length
);
assert_not_equals
((
size_t
)
-
1
,
res
);
assert_equals
(
pickle_length
,
olm_pickle_outbound_group_session_length
(
session2
));
olm_pickle_outbound_group_session
(
session2
,
"secret_key"
,
10
,
pickle2
,
pickle_length
);
assert_equals
(
pickle1
,
pickle2
,
pickle_length
);
}
{
TestCase
test_case
(
"Group message send/receive"
);
uint8_t
random_bytes
[]
=
"0123456789ABDEF0123456789ABCDEF"
"0123456789ABDEF0123456789ABCDEF"
"0123456789ABDEF0123456789ABCDEF"
"0123456789ABDEF0123456789ABCDEF"
"0123456789ABDEF0123456789ABCDEF"
;
size_t
size
=
olm_outbound_group_session_size
();
void
*
memory
=
alloca
(
size
);
OlmOutboundGroupSession
*
session
=
olm_outbound_group_session
(
memory
);
...
...
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment