2015-06-23 18:50:30 +02:00
|
|
|
var runtime = Module['Runtime'];
|
|
|
|
var malloc = Module['_malloc'];
|
|
|
|
var free = Module['_free'];
|
|
|
|
var Pointer_stringify = Module['Pointer_stringify'];
|
2015-06-27 01:15:23 +02:00
|
|
|
var OLM_ERROR = Module['_olm_error']();
|
2015-06-23 18:50:30 +02:00
|
|
|
|
|
|
|
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);
|
2015-06-26 17:16:34 +02:00
|
|
|
return ptr;
|
2015-06-23 18:50:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function restore_stack(wrapped) {
|
|
|
|
return function() {
|
|
|
|
var sp = runtime.stackSave();
|
|
|
|
try {
|
|
|
|
return wrapped.apply(this, arguments);
|
|
|
|
} finally {
|
|
|
|
runtime.stackRestore(sp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
function Account() {
|
2015-06-27 01:15:23 +02:00
|
|
|
var size = Module['_olm_account_size']();
|
2015-06-23 18:50:30 +02:00
|
|
|
this.buf = malloc(size);
|
2015-06-27 01:15:23 +02:00
|
|
|
this.ptr = Module['_olm_account'](this.buf);
|
2015-06-23 18:50:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function account_method(wrapped) {
|
|
|
|
return function() {
|
|
|
|
var result = wrapped.apply(this, arguments);
|
2015-06-27 01:15:23 +02:00
|
|
|
if (result === OLM_ERROR) {
|
2015-06-23 18:50:30 +02:00
|
|
|
var message = Pointer_stringify(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_account_last_error'](arguments[0])
|
2015-06-23 18:50:30 +02:00
|
|
|
);
|
2015-06-27 01:15:23 +02:00
|
|
|
throw new Error("OLM." + message);
|
2015-06-23 18:50:30 +02:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Account.prototype['free'] = function() {
|
|
|
|
free(this.ptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
Account.prototype['create'] = restore_stack(function() {
|
|
|
|
var random_length = account_method(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_create_account_random_length']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(this.ptr);
|
|
|
|
var random = random_stack(random_length);
|
2015-06-27 01:15:23 +02:00
|
|
|
account_method(Module['_olm_create_account'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
this.ptr, random, random_length
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
2015-07-08 12:16:00 +02:00
|
|
|
Account.prototype['identity_keys'] = restore_stack(function(
|
|
|
|
user_id, device_id, valid_after, valid_until
|
|
|
|
) {
|
|
|
|
var user_id_array = array_from_string(user_id);
|
|
|
|
var device_id_array = array_from_string(device_id);
|
2015-06-23 18:50:30 +02:00
|
|
|
var keys_length = account_method(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_account_identity_keys_length']
|
2015-07-08 12:16:00 +02:00
|
|
|
)(
|
|
|
|
this.ptr, user_id_array.length, device_id_array.length,
|
|
|
|
valid_after, valid_after / Math.pow(2, 32),
|
|
|
|
valid_until, valid_until / Math.pow(2, 32)
|
|
|
|
);
|
|
|
|
var user_id_buffer = stack(user_id_array);
|
|
|
|
var device_id_buffer = stack(device_id_array);
|
2015-06-23 18:50:30 +02:00
|
|
|
var keys = stack(keys_length);
|
2015-06-27 01:15:23 +02:00
|
|
|
account_method(Module['_olm_account_identity_keys'])(
|
2015-07-08 12:16:00 +02:00
|
|
|
this.ptr,
|
|
|
|
user_id_buffer, user_id_array.length,
|
|
|
|
device_id_buffer, device_id_array.length,
|
|
|
|
valid_after, valid_after / Math.pow(2, 32),
|
|
|
|
valid_until, valid_until / Math.pow(2, 32),
|
|
|
|
keys, keys_length
|
2015-06-23 18:50:30 +02:00
|
|
|
);
|
|
|
|
return Pointer_stringify(keys, keys_length);
|
|
|
|
});
|
|
|
|
|
|
|
|
Account.prototype['one_time_keys'] = restore_stack(function() {
|
|
|
|
var keys_length = account_method(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_account_one_time_keys_length']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(this.ptr);
|
|
|
|
var keys = stack(keys_length);
|
2015-06-27 01:15:23 +02:00
|
|
|
account_method(Module['_olm_account_one_time_keys'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
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(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_pickle_account_length']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(this.ptr);
|
|
|
|
var key_buffer = stack(key_array);
|
|
|
|
var pickle_buffer = stack(pickle_length);
|
2015-06-27 01:15:23 +02:00
|
|
|
account_method(Module['_olm_pickle_account'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
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);
|
2015-06-27 01:15:23 +02:00
|
|
|
account_method(Module['_olm_unpickle_account'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
this.ptr, key_buffer, key_array.length, pickle_buffer,
|
|
|
|
pickle_array.length
|
|
|
|
);
|
|
|
|
});
|
|
|
|
|
|
|
|
function Session() {
|
2015-06-27 01:15:23 +02:00
|
|
|
var size = Module['_olm_session_size']();
|
2015-06-23 18:50:30 +02:00
|
|
|
this.buf = malloc(size);
|
2015-06-27 01:15:23 +02:00
|
|
|
this.ptr = Module['_olm_session'](this.buf);
|
2015-06-23 18:50:30 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
function session_method(wrapped) {
|
|
|
|
return function() {
|
|
|
|
var result = wrapped.apply(this, arguments);
|
2015-06-27 01:15:23 +02:00
|
|
|
if (result === OLM_ERROR) {
|
2015-06-23 18:50:30 +02:00
|
|
|
var message = Pointer_stringify(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_session_last_error'](arguments[0])
|
2015-06-23 18:50:30 +02:00
|
|
|
);
|
2015-06-27 01:15:23 +02:00
|
|
|
throw new Error("OLM." + message);
|
2015-06-23 18:50:30 +02:00
|
|
|
}
|
|
|
|
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(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_pickle_session_length']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(this.ptr);
|
|
|
|
var key_buffer = stack(key_array);
|
|
|
|
var pickle_buffer = stack(pickle_length);
|
2015-06-27 01:15:23 +02:00
|
|
|
session_method(Module['_olm_pickle_session'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
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);
|
2015-06-27 01:15:23 +02:00
|
|
|
session_method(Module['_olm_unpickle_session'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
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(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_create_outbound_session_random_length']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(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);
|
2015-06-27 01:15:23 +02:00
|
|
|
session_method(Module['_olm_create_outbound_session'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
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);
|
2015-06-27 01:15:23 +02:00
|
|
|
session_method(Module['_olm_create_inbound_session'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
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);
|
2015-06-27 01:15:23 +02:00
|
|
|
return session_method(Module['_olm_matches_inbound_session'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
this.ptr, account.ptr, message_buffer, message_array.length
|
|
|
|
) ? true : false;
|
|
|
|
});
|
|
|
|
|
|
|
|
Session.prototype['encrypt'] = restore_stack(function(
|
|
|
|
plaintext
|
|
|
|
) {
|
|
|
|
var random_length = session_method(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_encrypt_random_length']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(this.ptr);
|
|
|
|
var message_type = session_method(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_encrypt_message_type']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(this.ptr);
|
|
|
|
var plaintext_array = array_from_string(plaintext);
|
|
|
|
var message_length = session_method(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_encrypt_message_length']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(this.ptr, plaintext_array.length);
|
|
|
|
var random = random_stack(random_length);
|
|
|
|
var plaintext_buffer = stack(plaintext_array);
|
|
|
|
var message_buffer = stack(message_length);
|
2015-06-27 01:15:23 +02:00
|
|
|
session_method(Module['_olm_encrypt'])(
|
2015-06-23 18:50:30 +02:00
|
|
|
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(
|
2015-06-27 01:15:23 +02:00
|
|
|
Module['_olm_decrypt_max_plaintext_length']
|
2015-06-23 18:50:30 +02:00
|
|
|
)(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);
|
2015-06-27 01:15:23 +02:00
|
|
|
var plaintext_length = session_method(Module["_olm_decrypt"])(
|
2015-06-23 18:50:30 +02:00
|
|
|
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};
|
|
|
|
}();
|