diff options
Diffstat (limited to 'javascript/olm_post.js')
-rw-r--r-- | javascript/olm_post.js | 248 |
1 files changed, 248 insertions, 0 deletions
diff --git a/javascript/olm_post.js b/javascript/olm_post.js new file mode 100644 index 0000000..6ebd198 --- /dev/null +++ b/javascript/olm_post.js @@ -0,0 +1,248 @@ +var runtime = Module['Runtime']; +var malloc = Module['_malloc']; +var free = Module['_free']; +var Pointer_stringify = Module['Pointer_stringify']; +var OLM_ERROR = Module['_olm_error'](); + +function stack(size_or_array) { + return Module['allocate'](size_or_array, 'i8', Module['ALLOC_STACK']); +} + +function array_from_string(string) { + return Module['intArrayFromString'](string, true); +} + +function random_stack(size) { + var ptr = stack(size); + var array = new Uint8Array(Module['HEAPU8'].buffer, ptr, size); + window.crypto.getRandomValues(array); + return ptr; +} + +function restore_stack(wrapped) { + return function() { + var sp = runtime.stackSave(); + try { + return wrapped.apply(this, arguments); + } finally { + runtime.stackRestore(sp); + } + } +} + +function Account() { + var size = Module['_olm_account_size'](); + this.buf = malloc(size); + this.ptr = Module['_olm_account'](this.buf); +} + +function account_method(wrapped) { + return function() { + var result = wrapped.apply(this, arguments); + if (result === OLM_ERROR) { + var message = Pointer_stringify( + Module['_olm_account_last_error'](arguments[0]) + ); + throw new Error("OLM." + message); + } + return result; + } +} + +Account.prototype['free'] = function() { + free(this.ptr); +} + +Account.prototype['create'] = restore_stack(function() { + var random_length = account_method( + Module['_olm_create_account_random_length'] + )(this.ptr); + var random = random_stack(random_length); + account_method(Module['_olm_create_account'])( + this.ptr, random, random_length + ); +}); + +Account.prototype['identity_keys'] = restore_stack(function() { + var keys_length = account_method( + Module['_olm_account_identity_keys_length'] + )(this.ptr); + var keys = stack(keys_length); + account_method(Module['_olm_account_identity_keys'])( + this.ptr, keys, keys_length + ); + return Pointer_stringify(keys, keys_length); +}); + +Account.prototype['one_time_keys'] = restore_stack(function() { + var keys_length = account_method( + Module['_olm_account_one_time_keys_length'] + )(this.ptr); + var keys = stack(keys_length); + account_method(Module['_olm_account_one_time_keys'])( + this.ptr, keys, keys_length + ); + return Pointer_stringify(keys, keys_length); +}); + +Account.prototype['pickle'] = restore_stack(function(key) { + var key_array = array_from_string(key); + var pickle_length = account_method( + Module['_olm_pickle_account_length'] + )(this.ptr); + var key_buffer = stack(key_array); + var pickle_buffer = stack(pickle_length); + account_method(Module['_olm_pickle_account'])( + this.ptr, key_buffer, key_array.length, pickle_buffer, pickle_length + ); + return Pointer_stringify(pickle_buffer, pickle_length); +}); + +Account.prototype['unpickle'] = restore_stack(function(key, pickle) { + var key_array = array_from_string(key); + var key_buffer = stack(key_array); + var pickle_array = array_from_string(pickle); + var pickle_buffer = stack(pickle_length); + account_method(Module['_olm_unpickle_account'])( + this.ptr, key_buffer, key_array.length, pickle_buffer, + pickle_array.length + ); +}); + +function Session() { + var size = Module['_olm_session_size'](); + this.buf = malloc(size); + this.ptr = Module['_olm_session'](this.buf); +} + +function session_method(wrapped) { + return function() { + var result = wrapped.apply(this, arguments); + if (result === OLM_ERROR) { + var message = Pointer_stringify( + Module['_olm_session_last_error'](arguments[0]) + ); + throw new Error("OLM." + message); + } + return result; + } +} + +Session.prototype['free'] = function() { + free(this.ptr); +} + +Session.prototype['pickle'] = restore_stack(function(key) { + var key_array = array_from_string(key); + var pickle_length = session_method( + Module['_olm_pickle_session_length'] + )(this.ptr); + var key_buffer = stack(key_array); + var pickle_buffer = stack(pickle_length); + session_method(Module['_olm_pickle_session'])( + this.ptr, key_buffer, key_array.length, pickle_buffer, pickle_length + ); + return Pointer_stringify(pickle_buffer, pickle_length); +}); + +Session.prototype['unpickle'] = restore_stack(function(key, pickle) { + var key_array = array_from_string(key); + var key_buffer = stack(key_array); + var pickle_array = array_from_string(pickle); + var pickle_buffer = stack(pickle_array); + session_method(Module['_olm_unpickle_session'])( + this.ptr, key_buffer, key_array.length, pickle_buffer, + pickle_array.length + ); +}); + +Session.prototype['create_outbound'] = restore_stack(function( + account, their_identity_key, their_one_time_key_id, their_one_time_key +) { + var random_length = session_method( + Module['_olm_create_outbound_session_random_length'] + )(this.ptr); + var random = random_stack(random_length); + var identity_key_array = array_from_string(their_identity_key); + var one_time_key_array = array_from_string(their_one_time_key); + var identity_key_buffer = stack(identity_key_array); + var one_time_key_buffer = stack(one_time_key_array); + session_method(Module['_olm_create_outbound_session'])( + this.ptr, account.ptr, + identity_key_buffer, identity_key_array.length, + their_one_time_key_id, + one_time_key_buffer, one_time_key_array.length, + random, random_length + ); +}); + +Session.prototype['create_inbound'] = restore_stack(function( + account, one_time_key_message +) { + var message_array = array_from_string(one_time_key_message); + var message_buffer = stack(message_array); + session_method(Module['_olm_create_inbound_session'])( + this.ptr, account.ptr, message_buffer, message_array.length + ); +}); + +Session.prototype['matches_inbound'] = restore_stack(function( + account, one_time_key_message +) { + var message_array = array_from_string(one_time_key_message); + var message_buffer = stack(message_array); + return session_method(Module['_olm_matches_inbound_session'])( + this.ptr, account.ptr, message_buffer, message_array.length + ) ? true : false; +}); + +Session.prototype['encrypt'] = restore_stack(function( + plaintext +) { + var random_length = session_method( + Module['_olm_encrypt_random_length'] + )(this.ptr); + var message_type = session_method( + Module['_olm_encrypt_message_type'] + )(this.ptr); + var plaintext_array = array_from_string(plaintext); + var message_length = session_method( + Module['_olm_encrypt_message_length'] + )(this.ptr, plaintext_array.length); + var random = random_stack(random_length); + var plaintext_buffer = stack(plaintext_array); + var message_buffer = stack(message_length); + session_method(Module['_olm_encrypt'])( + this.ptr, + plaintext_buffer, plaintext_array.length, + random, random_length, + message_buffer, message_length + ); + return { + "type": message_type, + "body": Pointer_stringify(message_buffer, message_length) + }; +}); + +Session.prototype['decrypt'] = restore_stack(function( + message_type, message +) { + var message_array = array_from_string(message); + var message_buffer = stack(message_array); + var max_plaintext_length = session_method( + Module['_olm_decrypt_max_plaintext_length'] + )(this.ptr, message_type, message_buffer, message_array.length); + // caculating the length destroys the input buffer. + // So we copy the array to a new buffer + var message_buffer = stack(message_array); + var plaintext_buffer = stack(max_plaintext_length); + var plaintext_length = session_method(Module["_olm_decrypt"])( + this.ptr, message_type, + message_buffer, message.length, + plaintext_buffer, max_plaintext_length + ); + return Pointer_stringify(plaintext_buffer, plaintext_length); +}); + +return {"Account": Account, "Session": Session}; +}(); |