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
Michael Telatynski
Olm
Commits
3cd6b158
Commit
3cd6b158
authored
Sep 17, 2020
by
Hubert Chathi
Browse files
Merge branch 'uhoreg/fallback' into 'master'
add support for fallback keys See merge request
!13
parents
89050dc0
c47c6ca3
Changes
6
Hide whitespace changes
Inline
Side-by-side
include/olm/account.hh
View file @
3cd6b158
...
...
@@ -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,35 @@ 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 @
3cd6b158
...
...
@@ -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 @
3cd6b158
...
...
@@ -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 @
3cd6b158
...
...
@@ -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 @
3cd6b158
...
...
@@ -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,20 @@ 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 +65,22 @@ 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 +295,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 +425,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 +437,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 +451,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 +466,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 +477,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 @
3cd6b158
...
...
@@ -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