Skip to content
GitLab
Menu
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
171044f3
Commit
171044f3
authored
Aug 14, 2020
by
Hubert Chathi
Browse files
add support for fallback keys
parent
a0284c2b
Changes
6
Hide whitespace changes
Inline
Side-by-side
include/olm/account.hh
View file @
171044f3
...
...
@@ -43,6 +43,8 @@ struct Account {
Account
();
IdentityKeys
identity_keys
;
List
<
OneTimeKey
,
MAX_ONE_TIME_KEYS
>
one_time_keys
;
OneTimeKey
current_fallback_key
;
OneTimeKey
prev_fallback_key
;
std
::
uint32_t
next_one_time_key_id
;
OlmErrorCode
last_error
;
...
...
@@ -126,6 +128,36 @@ struct Account {
std
::
uint8_t
const
*
random
,
std
::
size_t
random_length
);
/** The number of random bytes needed to generate a fallback key. */
std
::
size_t
generate_fallback_key_random_length
(
);
/** Generates a new fallback key. Returns std::size_t(-1) on error. If the
* number of random bytes is too small then last_error will be
* NOT_ENOUGH_RANDOM */
std
::
size_t
generate_fallback_key
(
std
::
uint8_t
const
*
random
,
std
::
size_t
random_length
);
/** Number of bytes needed to output the one time keys for this account */
std
::
size_t
get_fallback_key_json_length
();
/** Output the fallback key as JSON:
*
* {"curve25519":
* ["<6 byte key id>":"<43 base64 characters>"
* ,"<6 byte key id>":"<43 base64 characters>"
* ...
* ]
* }
*
* Returns the size of the JSON written or std::size_t(-1) on error.
* If the buffer is too small last_error will be OUTPUT_BUFFER_TOO_SMALL.
*/
std
::
size_t
get_fallback_key_json
(
std
::
uint8_t
*
fallback_json
,
std
::
size_t
fallback_json_length
);
/** Lookup a one time key with the given public key */
OneTimeKey
const
*
lookup_key
(
_olm_curve25519_public_key
const
&
public_key
...
...
include/olm/olm.h
View file @
171044f3
...
...
@@ -254,6 +254,31 @@ size_t olm_account_generate_one_time_keys(
void
*
random
,
size_t
random_length
);
/** The number of random bytes needed to generate a fallback key. */
size_t
olm_account_generate_fallback_key_random_length
(
OlmAccount
*
account
);
/** Generates a new fallback key. Only one previous fallback key is
* stored. Returns olm_error() on error. If the number of random bytes is too
* small then olm_account_last_error() will be "NOT_ENOUGH_RANDOM". */
size_t
olm_account_generate_fallback_key
(
OlmAccount
*
account
,
void
*
random
,
size_t
random_length
);
/** The number of bytes needed to hold the fallback key as returned by
* olm_account_fallback_key. */
size_t
olm_account_fallback_key_length
(
OlmAccount
*
account
);
size_t
olm_account_fallback_key
(
OlmAccount
*
account
,
void
*
fallback_key
,
size_t
fallback_key_size
);
/** The number of random bytes needed to create an outbound session */
size_t
olm_create_outbound_session_random_length
(
OlmSession
*
session
...
...
javascript/index.d.ts
View file @
171044f3
...
...
@@ -27,6 +27,8 @@ declare class Account {
max_number_of_one_time_keys
():
number
;
generate_one_time_keys
(
number_of_keys
:
number
);
remove_one_time_keys
(
session
:
Session
);
generate_fallback_key
();
fallback_key
():
string
;
pickle
(
key
:
string
):
string
;
unpickle
(
key
:
string
,
pickle
:
string
);
}
...
...
javascript/olm_post.js
View file @
171044f3
...
...
@@ -141,11 +141,32 @@ Account.prototype['generate_one_time_keys'] = restore_stack(function(
});
Account
.
prototype
[
'
remove_one_time_keys
'
]
=
restore_stack
(
function
(
session
)
{
account_method
(
Module
[
'
_olm_remove_one_time_keys
'
])(
account_method
(
Module
[
'
_olm_remove_one_time_keys
'
])(
this
.
ptr
,
session
.
ptr
);
});
Account
.
prototype
[
'
generate_fallback_key
'
]
=
restore_stack
(
function
()
{
var
random_length
=
account_method
(
Module
[
'
_olm_account_generate_fallback_key_random_length
'
]
)(
this
.
ptr
);
var
random
=
random_stack
(
random_length
);
account_method
(
Module
[
'
_olm_account_generate_fallback_key
'
])(
this
.
ptr
,
random
,
random_length
);
});
Account
.
prototype
[
'
fallback_key
'
]
=
restore_stack
(
function
()
{
var
keys_length
=
account_method
(
Module
[
'
_olm_account_fallback_key_length
'
]
)(
this
.
ptr
);
var
keys
=
stack
(
keys_length
+
NULL_BYTE_PADDING_LENGTH
);
account_method
(
Module
[
'
_olm_account_fallback_key
'
])(
this
.
ptr
,
keys
,
keys_length
);
return
UTF8ToString
(
keys
,
keys_length
);
});
Account
.
prototype
[
'
pickle
'
]
=
restore_stack
(
function
(
key
)
{
var
key_array
=
array_from_string
(
key
);
var
pickle_length
=
account_method
(
...
...
src/account.cpp
View file @
171044f3
...
...
@@ -21,6 +21,11 @@
olm
::
Account
::
Account
(
)
:
next_one_time_key_id
(
0
),
last_error
(
OlmErrorCode
::
OLM_SUCCESS
)
{
// since we don't need to keep track of whether the fallback keys are
// published, use the published flag as in indication for whether the keys
// were generated
current_fallback_key
.
published
=
false
;
prev_fallback_key
.
published
=
false
;
}
...
...
@@ -32,6 +37,14 @@ olm::OneTimeKey const * olm::Account::lookup_key(
return
&
key
;
}
}
if
(
current_fallback_key
.
published
&&
olm
::
array_equal
(
current_fallback_key
.
key
.
public_key
.
public_key
,
public_key
.
public_key
))
{
return
&
current_fallback_key
;
}
if
(
prev_fallback_key
.
published
&&
olm
::
array_equal
(
prev_fallback_key
.
key
.
public_key
.
public_key
,
public_key
.
public_key
))
{
return
&
prev_fallback_key
;
}
return
0
;
}
...
...
@@ -46,6 +59,16 @@ std::size_t olm::Account::remove_key(
return
id
;
}
}
// check if the key is a fallback key, to avoid returning an error, but
// don't actually remove it
if
(
current_fallback_key
.
published
&&
olm
::
array_equal
(
current_fallback_key
.
key
.
public_key
.
public_key
,
public_key
.
public_key
))
{
return
current_fallback_key
.
id
;
}
if
(
prev_fallback_key
.
published
&&
olm
::
array_equal
(
prev_fallback_key
.
key
.
public_key
.
public_key
,
public_key
.
public_key
))
{
return
prev_fallback_key
.
id
;
}
return
std
::
size_t
(
-
1
);
}
...
...
@@ -260,6 +283,67 @@ std::size_t olm::Account::generate_one_time_keys(
return
number_of_keys
;
}
std
::
size_t
olm
::
Account
::
generate_fallback_key_random_length
()
{
return
CURVE25519_RANDOM_LENGTH
;
}
std
::
size_t
olm
::
Account
::
generate_fallback_key
(
std
::
uint8_t
const
*
random
,
std
::
size_t
random_length
)
{
if
(
random_length
<
generate_fallback_key_random_length
())
{
last_error
=
OlmErrorCode
::
OLM_NOT_ENOUGH_RANDOM
;
return
std
::
size_t
(
-
1
);
}
prev_fallback_key
=
current_fallback_key
;
current_fallback_key
.
id
=
++
next_one_time_key_id
;
current_fallback_key
.
published
=
true
;
_olm_crypto_curve25519_generate_key
(
random
,
&
current_fallback_key
.
key
);
return
1
;
}
std
::
size_t
olm
::
Account
::
get_fallback_key_json_length
(
)
{
std
::
size_t
length
=
4
+
sizeof
(
KEY_JSON_CURVE25519
);
/* {"curve25519":{}} */
OneTimeKey
&
key
=
current_fallback_key
;
if
(
key
.
published
)
{
length
+=
1
;
/* " */
length
+=
olm
::
encode_base64_length
(
_olm_pickle_uint32_length
(
key
.
id
));
length
+=
3
;
/* ":" */
length
+=
olm
::
encode_base64_length
(
sizeof
(
key
.
key
.
public_key
));
length
+=
1
;
/* " */
}
return
length
;
}
std
::
size_t
olm
::
Account
::
get_fallback_key_json
(
std
::
uint8_t
*
fallback_json
,
std
::
size_t
fallback_json_length
)
{
std
::
uint8_t
*
pos
=
fallback_json
;
if
(
fallback_json_length
<
get_fallback_key_json_length
())
{
last_error
=
OlmErrorCode
::
OLM_OUTPUT_BUFFER_TOO_SMALL
;
return
std
::
size_t
(
-
1
);
}
*
(
pos
++
)
=
'{'
;
pos
=
write_string
(
pos
,
KEY_JSON_CURVE25519
);
*
(
pos
++
)
=
'{'
;
OneTimeKey
&
key
=
current_fallback_key
;
if
(
key
.
published
)
{
*
(
pos
++
)
=
'\"'
;
std
::
uint8_t
key_id
[
_olm_pickle_uint32_length
(
key
.
id
)];
_olm_pickle_uint32
(
key_id
,
key
.
id
);
pos
=
olm
::
encode_base64
(
key_id
,
sizeof
(
key_id
),
pos
);
*
(
pos
++
)
=
'\"'
;
*
(
pos
++
)
=
':'
;
*
(
pos
++
)
=
'\"'
;
pos
=
olm
::
encode_base64
(
key
.
key
.
public_key
.
public_key
,
sizeof
(
key
.
key
.
public_key
.
public_key
),
pos
);
*
(
pos
++
)
=
'\"'
;
}
*
(
pos
++
)
=
'}'
;
*
(
pos
++
)
=
'}'
;
return
pos
-
fallback_json
;
}
namespace
olm
{
static
std
::
size_t
pickle_length
(
...
...
@@ -329,7 +413,8 @@ static std::uint8_t const * unpickle(
namespace
{
// pickle version 1 used only 32 bytes for the ed25519 private key.
// Any keys thus used should be considered compromised.
static
const
std
::
uint32_t
ACCOUNT_PICKLE_VERSION
=
2
;
// pickle version 2 does not have fallback keys.
static
const
std
::
uint32_t
ACCOUNT_PICKLE_VERSION
=
3
;
}
...
...
@@ -340,6 +425,8 @@ std::size_t olm::pickle_length(
length
+=
olm
::
pickle_length
(
ACCOUNT_PICKLE_VERSION
);
length
+=
olm
::
pickle_length
(
value
.
identity_keys
);
length
+=
olm
::
pickle_length
(
value
.
one_time_keys
);
length
+=
olm
::
pickle_length
(
value
.
current_fallback_key
);
length
+=
olm
::
pickle_length
(
value
.
prev_fallback_key
);
length
+=
olm
::
pickle_length
(
value
.
next_one_time_key_id
);
return
length
;
}
...
...
@@ -352,6 +439,8 @@ std::uint8_t * olm::pickle(
pos
=
olm
::
pickle
(
pos
,
ACCOUNT_PICKLE_VERSION
);
pos
=
olm
::
pickle
(
pos
,
value
.
identity_keys
);
pos
=
olm
::
pickle
(
pos
,
value
.
one_time_keys
);
pos
=
olm
::
pickle
(
pos
,
value
.
current_fallback_key
);
pos
=
olm
::
pickle
(
pos
,
value
.
prev_fallback_key
);
pos
=
olm
::
pickle
(
pos
,
value
.
next_one_time_key_id
);
return
pos
;
}
...
...
@@ -365,6 +454,7 @@ std::uint8_t const * olm::unpickle(
pos
=
olm
::
unpickle
(
pos
,
end
,
pickle_version
);
switch
(
pickle_version
)
{
case
ACCOUNT_PICKLE_VERSION
:
case
2
:
break
;
case
1
:
value
.
last_error
=
OlmErrorCode
::
OLM_BAD_LEGACY_ACCOUNT_PICKLE
;
...
...
@@ -375,6 +465,14 @@ std::uint8_t const * olm::unpickle(
}
pos
=
olm
::
unpickle
(
pos
,
end
,
value
.
identity_keys
);
pos
=
olm
::
unpickle
(
pos
,
end
,
value
.
one_time_keys
);
if
(
pickle_version
==
2
)
{
// version 2 did not have fallback keys
value
.
current_fallback_key
.
published
=
false
;
value
.
prev_fallback_key
.
published
=
false
;
}
else
{
pos
=
olm
::
unpickle
(
pos
,
end
,
value
.
current_fallback_key
);
pos
=
olm
::
unpickle
(
pos
,
end
,
value
.
prev_fallback_key
);
}
pos
=
olm
::
unpickle
(
pos
,
end
,
value
.
next_one_time_key_id
);
return
pos
;
}
src/olm.cpp
View file @
171044f3
...
...
@@ -417,6 +417,42 @@ size_t olm_account_generate_one_time_keys(
}
size_t
olm_account_generate_fallback_key_random_length
(
OlmAccount
*
account
)
{
return
from_c
(
account
)
->
generate_fallback_key_random_length
();
}
size_t
olm_account_generate_fallback_key
(
OlmAccount
*
account
,
void
*
random
,
size_t
random_length
)
{
size_t
result
=
from_c
(
account
)
->
generate_fallback_key
(
from_c
(
random
),
random_length
);
olm
::
unset
(
random
,
random_length
);
return
result
;
}
size_t
olm_account_fallback_key_length
(
OlmAccount
*
account
)
{
return
from_c
(
account
)
->
get_fallback_key_json_length
();
}
size_t
olm_account_fallback_key
(
OlmAccount
*
account
,
void
*
fallback_key_json
,
size_t
fallback_key_json_length
)
{
return
from_c
(
account
)
->
get_fallback_key_json
(
from_c
(
fallback_key_json
),
fallback_key_json_length
);
}
size_t
olm_create_outbound_session_random_length
(
OlmSession
*
session
)
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a 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