diff --git a/include/olm/account.hh b/include/olm/account.hh index f54758d..da3ca35 100644 --- a/include/olm/account.hh +++ b/include/olm/account.hh @@ -123,8 +123,8 @@ struct Account { /** The largest number of one time keys this account can store. */ std::size_t max_number_of_one_time_keys(); - /** Returns the number of random bytes needed to generate a given number - * of new one time keys. */ + /** The number of random bytes needed to generate a given number of new one + * time keys. */ std::size_t generate_one_time_keys_random_length( std::size_t number_of_keys ); diff --git a/include/olm/olm.hh b/include/olm/olm.hh index 891f953..46f7a68 100644 --- a/include/olm/olm.hh +++ b/include/olm/olm.hh @@ -157,12 +157,8 @@ size_t olm_account_one_time_keys_length( OlmAccount * account ); -/** Writes the public parts of the one time keys for the account into the - * one_time_keys output buffer. The first key will be formatted as though it was - * created with sprintf(output, "[[%10d,\"%43s\"]\n", key_id, key_base64). - * subsequent keys are formatted with ",[%10d,\"%43s\"]\n". The final byte of - * output will be "]". The output can either be parsed as fixed width using - * the above format or by a JSON parser. Returns olm_error() on failure. +/** Writes the public parts of the unpublished one time keys for the account + * into the one_time_keys output buffer. Returns olm_error() on failure. * If the one_time_keys buffer was too small then olm_account_last_error() * will be "OUTPUT_BUFFER_TOO_SMALL". */ size_t olm_account_one_time_keys( @@ -170,8 +166,32 @@ size_t olm_account_one_time_keys( void * one_time_keys, size_t one_time_keys_length ); -/* TODO: Add methods for marking keys as used, generating new keys, and - * tracking which keys have been uploaded to the central servers */ +/** Marks the current set of one time keys as being published. */ +size_t olm_account_mark_keys_as_published( + OlmAccount * account +); + +/** The largest number of one time keys this account can store. */ +size_t olm_account_max_number_of_one_time_keys( + OlmAccount * account +); + +/** The number of random bytes needed to generate a given number of new one + * time keys. */ +size_t olm_account_generate_one_time_keys_random_length( + OlmAccount * account, + size_t number_of_keys +); + +/** Generates a number of new one time keys. If the total number of keys stored + * by this account exceeds max_number_of_one_time_keys() then the old keys are + * discarded. 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_one_time_keys( + OlmAccount * account, + size_t number_of_keys, + void const * random, size_t random_length +); /** The number of random bytes needed to create an outbound session */ size_t olm_create_outbound_session_random_length( diff --git a/javascript/demo.html b/javascript/demo.html index c9cad8b..2120f95 100644 --- a/javascript/demo.html +++ b/javascript/demo.html @@ -28,6 +28,9 @@ document.addEventListener("DOMContentLoaded", function (event) { tasks.push(["alice", "Creating account", function() { alice.create() }]); tasks.push(["bob", "Creating account", function() { bob.create() }]); + tasks.push(["bob", "Generate one time keys", function() { + bob.generate_one_time_keys(1); + }]); tasks.push(["alice", "Create outbound session", function() { var bobs_id_keys = JSON.parse(bob.identity_keys("bob", "bob_device", 0, 0)); var bobs_id_key; diff --git a/javascript/olm_post.js b/javascript/olm_post.js index 7bcc580..aa28f86 100644 --- a/javascript/olm_post.js +++ b/javascript/olm_post.js @@ -100,6 +100,28 @@ Account.prototype['one_time_keys'] = restore_stack(function() { return Pointer_stringify(keys, keys_length); }); +Account.prototype['mark_keys_as_published'] = restore_stack(function() { + account_method(Module['_olm_account_mark_keys_as_published'])(this.ptr); +}); + +Account.prototype['max_number_of_one_time_keys'] = restore_stack(function() { + account_method(Module['_olm_account_max_number_of_one_time_keys'])( + this.ptr + ); +}); + +Account.prototype['generate_one_time_keys'] = restore_stack(function( + number_of_keys +) { + var random_length = account_method( + Module['_olm_account_generate_one_time_keys_random_length'] + )(this.ptr, number_of_keys); + var random = random_stack(random_length); + account_method(Module['_olm_account_generate_one_time_keys'])( + this.ptr, number_of_keys, random, random_length + ); +}); + Account.prototype['pickle'] = restore_stack(function(key) { var key_array = array_from_string(key); var pickle_length = account_method( diff --git a/olm.py b/olm.py index 81f9e25..eb36c5f 100755 --- a/olm.py +++ b/olm.py @@ -59,6 +59,18 @@ account_function( ) account_function(lib.olm_account_one_time_keys_length) account_function(lib.olm_account_one_time_keys, c_void_p, c_size_t) +account_function(lib.olm_account_mark_keys_as_published) +account_function(lib.olm_account_max_number_of_one_time_keys) +account_function( + lib.olm_account_generate_one_time_keys_random_length, + c_size_t +) +account_function( + lib.olm_account_generate_one_time_keys + c_size_t, + c_void_p, c_size_t +) + def read_random(n): with open("/dev/urandom", "rb") as f: @@ -113,6 +125,23 @@ class Account(object): lib.olm_account_one_time_keys(self.ptr, out_buffer, out_length) return json.loads(out_buffer.raw) + def mark_keys_as_published(self): + lib.olm_account_mark_keys_as_published(self.ptr) + + + def max_number_of_one_time_keys(self): + return lib.olm_account_max_number_of_one_time_keys(self.ptr) + + def generate_one_time_keys(self, count): + random_length = lib.olm_account_generate_one_time_keys_random_length( + self.ptr + ) + random = read_random(random_length) + random_buffer = create_string_buffer(random) + lib.olm_account_generate_one_time_keys( + self.ptr, random_buffer, random_length + ) + def clear(self): pass diff --git a/src/account.cpp b/src/account.cpp index ede327b..6a76583 100644 --- a/src/account.cpp +++ b/src/account.cpp @@ -48,7 +48,7 @@ std::size_t olm::Account::remove_key( } std::size_t olm::Account::new_account_random_length() { - return 12 * 32; + return 2 * 32; } std::size_t olm::Account::new_account( @@ -64,8 +64,6 @@ std::size_t olm::Account::new_account( olm::curve25519_generate_key(random, identity_keys.curve25519_key); random += 32; - generate_one_time_keys(10, random, random_length - 64); - return 0; } diff --git a/src/olm.cpp b/src/olm.cpp index 65d0648..6450999 100644 --- a/src/olm.cpp +++ b/src/olm.cpp @@ -370,12 +370,47 @@ size_t olm_account_one_time_keys( } +size_t olm_account_mark_keys_as_published( + OlmAccount * account +) { + return from_c(account)->mark_keys_as_published(); +} + + +size_t olm_account_max_number_of_one_time_keys( + OlmAccount * account +) { + return from_c(account)->max_number_of_one_time_keys(); +} + + +size_t olm_account_generate_one_time_keys_random_length( + OlmAccount * account, + size_t number_of_keys +) { + return from_c(account)->generate_one_time_keys_random_length(number_of_keys); +} + + +size_t olm_account_generate_one_time_keys( + OlmAccount * account, + size_t number_of_keys, + void const * random, size_t random_length +) { + return from_c(account)->generate_one_time_keys( + number_of_keys, + from_c(random), random_length + ); +} + + size_t olm_create_outbound_session_random_length( OlmSession * session ) { return from_c(session)->new_outbound_session_random_length(); } + size_t olm_create_outbound_session( OlmSession * session, OlmAccount * account, diff --git a/tests/test_olm.cpp b/tests/test_olm.cpp index bedabf3..8545e59 100644 --- a/tests/test_olm.cpp +++ b/tests/test_olm.cpp @@ -41,6 +41,12 @@ std::uint8_t account_buffer[::olm_account_size()]; std::uint8_t random[::olm_create_account_random_length(account)]; mock_random(random, sizeof(random)); ::olm_create_account(account, random, sizeof(random)); +std::uint8_t ot_random[::olm_account_generate_one_time_keys_random_length( + account, 42 +)]; +mock_random(ot_random, sizeof(ot_random)); +::olm_account_generate_one_time_keys(account, 42, ot_random, sizeof(ot_random)); + std::size_t pickle_length = ::olm_pickle_account_length(account); std::uint8_t pickle1[pickle_length]; ::olm_pickle_account(account, "secret_key", 10, pickle1, pickle_length); @@ -74,6 +80,11 @@ std::uint8_t b_account_buffer[::olm_account_size()]; std::uint8_t b_random[::olm_create_account_random_length(b_account)]; mock_random_b(b_random, sizeof(b_random)); ::olm_create_account(b_account, b_random, sizeof(b_random)); +std::uint8_t o_random[::olm_account_generate_one_time_keys_random_length( + b_account, 42 +)]; +mock_random_b(o_random, sizeof(o_random)); +::olm_account_generate_one_time_keys(b_account, 42, o_random, sizeof(o_random)); std::uint8_t b_id_keys[::olm_account_identity_keys_length(b_account, 0, 0, 0, 0)]; std::uint8_t b_ot_keys[::olm_account_one_time_keys_length(b_account)]; @@ -178,6 +189,11 @@ std::uint8_t b_account_buffer[::olm_account_size()]; std::uint8_t b_random[::olm_create_account_random_length(b_account)]; mock_random_b(b_random, sizeof(b_random)); ::olm_create_account(b_account, b_random, sizeof(b_random)); +std::uint8_t o_random[::olm_account_generate_one_time_keys_random_length( + b_account, 42 +)]; +mock_random_b(o_random, sizeof(o_random)); +::olm_account_generate_one_time_keys(b_account, 42, o_random, sizeof(o_random)); std::uint8_t b_id_keys[::olm_account_identity_keys_length(b_account, 0, 0, 0, 0)]; std::uint8_t b_ot_keys[::olm_account_one_time_keys_length(b_account)];