aboutsummaryrefslogtreecommitdiff
path: root/javascript/axolotl_post.js
diff options
context:
space:
mode:
authorMark Haines <mark.haines@matrix.org>2015-06-23 17:50:30 +0100
committerMark Haines <mark.haines@matrix.org>2015-06-23 17:50:30 +0100
commit07072912cdf680766d8c36f6333b77f9aa4f027c (patch)
treed809adaa9555ed3bb280013a3ce0d93e4d5bda13 /javascript/axolotl_post.js
parentf10c04d62d15cc42af4683c2020cf5dffe895bd2 (diff)
Add javascript bindings using emscripten
Diffstat (limited to 'javascript/axolotl_post.js')
-rw-r--r--javascript/axolotl_post.js247
1 files changed, 247 insertions, 0 deletions
diff --git a/javascript/axolotl_post.js b/javascript/axolotl_post.js
new file mode 100644
index 0000000..7902725
--- /dev/null
+++ b/javascript/axolotl_post.js
@@ -0,0 +1,247 @@
+var runtime = Module['Runtime'];
+var malloc = Module['_malloc'];
+var free = Module['_free'];
+var Pointer_stringify = Module['Pointer_stringify'];
+var AXOLOTL_ERROR = Module['_axolotl_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);
+}
+
+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['_axolotl_account_size']();
+ this.buf = malloc(size);
+ this.ptr = Module['_axolotl_account'](this.buf);
+}
+
+function account_method(wrapped) {
+ return function() {
+ var result = wrapped.apply(this, arguments);
+ if (result === AXOLOTL_ERROR) {
+ var message = Pointer_stringify(
+ Module['_axolotl_account_last_error'](arguments[0])
+ );
+ throw "AXOLOTL." + message;
+ }
+ return result;
+ }
+}
+
+Account.prototype['free'] = function() {
+ free(this.ptr);
+}
+
+Account.prototype['create'] = restore_stack(function() {
+ var random_length = account_method(
+ Module['_axolotl_create_account_random_length']
+ )(this.ptr);
+ var random = random_stack(random_length);
+ account_method(Module['_axolotl_create_account'])(
+ this.ptr, random, random_length
+ );
+});
+
+Account.prototype['identity_keys'] = restore_stack(function() {
+ var keys_length = account_method(
+ Module['_axolotl_account_identity_keys_length']
+ )(this.ptr);
+ var keys = stack(keys_length);
+ account_method(Module['_axolotl_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['_axolotl_account_one_time_keys_length']
+ )(this.ptr);
+ var keys = stack(keys_length);
+ account_method(Module['_axolotl_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['_axolotl_pickle_account_length']
+ )(this.ptr);
+ var key_buffer = stack(key_array);
+ var pickle_buffer = stack(pickle_length);
+ account_method(Module['_axolotl_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['_axolotl_unpickle_account'])(
+ this.ptr, key_buffer, key_array.length, pickle_buffer,
+ pickle_array.length
+ );
+});
+
+function Session() {
+ var size = Module['_axolotl_session_size']();
+ this.buf = malloc(size);
+ this.ptr = Module['_axolotl_session'](this.buf);
+}
+
+function session_method(wrapped) {
+ return function() {
+ var result = wrapped.apply(this, arguments);
+ if (result === AXOLOTL_ERROR) {
+ var message = Pointer_stringify(
+ Module['_axolotl_session_last_error'](arguments[0])
+ );
+ throw "AXOLOTL." + 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['_axolotl_pickle_session_length']
+ )(this.ptr);
+ var key_buffer = stack(key_array);
+ var pickle_buffer = stack(pickle_length);
+ session_method(Module['_axolotl_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['_axolotl_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['_axolotl_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['_axolotl_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['_axolotl_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['_axolotl_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['_axolotl_encrypt_random_length']
+ )(this.ptr);
+ var message_type = session_method(
+ Module['_axolotl_encrypt_message_type']
+ )(this.ptr);
+ var plaintext_array = array_from_string(plaintext);
+ var message_length = session_method(
+ Module['_axolotl_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['_axolotl_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['_axolotl_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["_axolotl_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};
+}();