UNPKG

@richardhopton/noise-c.wasm

Version:

rweather/noise-c compiled to WebAssembly using Emscripten and optimized for small size

672 lines (671 loc) 24.8 kB
// Generated by LiveScript 1.6.0 /** * @package noise-c.wasm * @author Nazar Mokrynskyi <nazar@mokrynskyi.com> * @license 0BSD */ (function(){ var random_bytes; if (typeof crypto !== 'undefined') { /** * @param {number} size * * @return {!Uint8Array} */ random_bytes = function(size){ var array; array = new Uint8Array(size); crypto.getRandomValues(array); return array; }; } else { /** * @param {string} size * * @return {!Uint8Array} */ random_bytes = require('crypto').randomBytes; } function CreateLib(lib, constants, arg1, arg2){ var options, callback, allocate, allocate_pointer; options = typeof arg1 === 'function' ? {} : arg1; callback = arg2 || arg1; if (typeof callback !== 'function') { throw new TypeError('noise-c.wasm: Callback is not a function'); } lib(options).then(lib => { lib['_random_bytes'] = random_bytes; allocate = lib['allocateBytes']; allocate_pointer = lib['allocatePointer']; function allocate_buffer(data, size){ var tmp, buffer; tmp = allocate_pointer(); lib._NoiseBuffer_create(tmp, data, size, data.length); buffer = tmp.dereference(); tmp.free(); return buffer; } function assert_no_error(error, object_to_free){ var key, ref$, code; if (error === constants.NOISE_ERROR_NONE) { return; } for (key in ref$ = constants) { code = ref$[key]; if (code === error) { if (object_to_free) { try { object_to_free.free(); } catch (e$) {} } throw new Error(key); } } } /** * Create a new X25519 or X448 keypair * * @param {number} curve_id constants.NOISE_DH_CURVE25519 or constants.NOISE_DH_CURVE448 * * @return {!Uint8Array[]} `[private_key, public_key]` * * @throws {TypeError} In case incorrect `curve_id` specified */ function CreateKeyPair(curve_id){ var tmp, error, dh, e, key_length, private_buffer, public_buffer, private_key, public_key; if (!(curve_id === constants.NOISE_DH_CURVE448 || curve_id === constants.NOISE_DH_CURVE25519)) { throw new TypeError('Invalid keypair type'); } tmp = allocate_pointer(); error = lib._noise_dhstate_new_by_id(tmp, curve_id); assert_no_error(error, tmp); dh = tmp.dereference(); tmp.free(); error = lib._noise_dhstate_generate_keypair(dh); try { assert_no_error(error); } catch (e$) { e = e$; lib._noise_dhstate_free(dh); throw e; } if (curve_id === constants.NOISE_DH_CURVE448) { key_length = 56; } else { key_length = 32; } private_buffer = allocate(key_length); public_buffer = allocate(key_length); error = lib._noise_dhstate_get_keypair(dh, private_buffer, private_buffer.length, public_buffer, public_buffer.length); lib._noise_dhstate_free(dh); try { assert_no_error(error); private_key = private_buffer.get(); private_buffer.free(); public_key = public_buffer.get(); public_buffer.free(); return [private_key, public_key]; } catch (e$) { e = e$; private_buffer.free(); public_buffer.free(); throw e; } } /** * The CipherState object, API is close to the spec: http://noiseprotocol.org/noise.html#the-cipherstate-object * * NOTE: If you ever get an exception with Error object, whose message is one of constants.NOISE_ERROR_* keys, object is no longer usable and there is no need * to call free() method, as it was called for you automatically already (except in EncryptWithAd and DecryptWithAd) * * @param {string} cipher constants.NOISE_CIPHER_CHACHAPOLY, constants.NOISE_CIPHER_AESGCM, etc. */ function CipherState(cipher){ var tmp, error; if (!(this instanceof CipherState)) { return new CipherState(cipher); } tmp = allocate_pointer(); error = lib._noise_cipherstate_new_by_id(tmp, cipher); assert_no_error(error, tmp); this._state = tmp.dereference(); this._mac_length = lib._noise_cipherstate_get_mac_length(this._state); tmp.free(); } CipherState.prototype = { /** * @param {Uint8Array} key */ InitializeKey: function(key){ var error; key = allocate(0, key); error = lib._noise_cipherstate_init_key(this._state, key, key.length); key.free(); assert_no_error(error, this); }, HasKey: function(){ return lib._noise_cipherstate_has_key(this._state) === 1; } /** * @param {number} nonce */, SetNonce: function(nonce){ var error; error = lib._noise_cipherstate_set_nonce(this._state, nonce); assert_no_error(error, this); } /** * @param {Uint8Array} ad * @param {Uint8Array} plaintext * * @return {Uint8Array} */, EncryptWithAd: function(ad, plaintext){ var buffer, error, ciphertext; ad = allocate(0, ad); plaintext = allocate(plaintext.length + this._mac_length, plaintext); buffer = allocate_buffer(plaintext, plaintext.length - this._mac_length); error = lib._noise_cipherstate_encrypt_with_ad(this._state, ad, ad.length, buffer); ciphertext = plaintext.get(); ad.free(); plaintext.free(); buffer.free(); assert_no_error(error); return ciphertext; } /** * @param {Uint8Array} ad * @param {Uint8Array} ciphertext * * @return {Uint8Array} */, DecryptWithAd: function(ad, ciphertext){ var buffer, error, plaintext; ad = allocate(0, ad); ciphertext = allocate(0, ciphertext); buffer = allocate_buffer(ciphertext, ciphertext.length); error = lib._noise_cipherstate_decrypt_with_ad(this._state, ad, ad.length, buffer); plaintext = ciphertext.get().slice(0, ciphertext.length - this._mac_length); ad.free(); ciphertext.free(); buffer.free(); assert_no_error(error); return plaintext; } /** * @return {boolean} */, Rekey: function(){ throw 'Not implemented'; } /** * Call this when object is not needed anymore to avoid memory leaks */, free: function(){ var error; error = lib._noise_cipherstate_free(this._state); delete this._state; delete this._mac_length; assert_no_error(error); } }; Object.defineProperty(CipherState.prototype, 'constructor', { enumerable: false, value: CipherState }); function CipherState_split(state){ this._state = state; this._mac_length = lib._noise_cipherstate_get_mac_length(this._state); } CipherState_split.prototype = Object.create(CipherState.prototype); Object.defineProperty(CipherState_split.prototype, 'constructor', { enumerable: false, value: CipherState_split }); /** * The SymmetricState object, API is close to the spec: http://noiseprotocol.org/noise.html#the-symmetricstate-object * * NOTE: If you ever get an exception with Error object, whose message is one of constants.NOISE_ERROR_* keys, object is no longer usable and there is no need * to call free() method, as it was called for you automatically already * * @param {string} protocol_name The name of the Noise protocol to use, for instance, Noise_N_25519_ChaChaPoly_BLAKE2b */ function SymmetricState(protocol_name){ var tmp, error, this$ = this; if (!(this instanceof SymmetricState)) { return new SymmetricState(protocol_name); } tmp = allocate_pointer(); protocol_name = allocate(0, protocol_name); error = lib._noise_symmetricstate_new_by_name(tmp, protocol_name); assert_no_error(error, tmp); this._state = tmp.dereference(); tmp.free(); protocol_name.free(); Object.defineProperty(this, '_mac_length', { configurable: true, get: function(){ var mac_length; mac_length = lib._noise_symmetricstate_get_mac_length(this$._state); if (mac_length > 0) { this$._mac_length = mac_length; } return mac_length; } }); } SymmetricState.prototype = { /** * @param {Uint8Array} input_key_material */ MixKey: function(input_key_material){ var error; input_key_material = allocate(0, input_key_material); error = lib._noise_symmetricstate_mix_key(this._state, input_key_material, input_key_material.length); input_key_material.free(); assert_no_error(error, this); } /** * @param {Uint8Array} data */, MixHash: function(data){ var error; data = allocate(0, data); error = lib._noise_symmetricstate_mix_hash(this._state, data, data.length); data.free(); assert_no_error(error, this); } /** * @param {Uint8Array} input_key_material */, MixKeyAndHash: function(input_key_material){ var tmp, length, ck, data; this.MixKey(input_key_material); tmp = allocate_pointer(); length = lib._SymmetricState_get_ck(this._state, tmp); ck = tmp.dereference(length); tmp.free(); data = ck.get(); ck.free(); this.MixHash(data); } /** * @param {Uint8Array} plaintext * * @return {Uint8Array} */, EncryptAndHash: function(plaintext){ var buffer, error, ciphertext; plaintext = allocate(plaintext.length + this._mac_length, plaintext); buffer = allocate_buffer(plaintext, plaintext.length - this._mac_length); error = lib._noise_symmetricstate_encrypt_and_hash(this._state, buffer); ciphertext = plaintext.get(); plaintext.free(); buffer.free(); assert_no_error(error, this); return ciphertext; } /** * @param {Uint8Array} ciphertext * * @return {Uint8Array} */, DecryptAndHash: function(ciphertext){ var buffer, error, plaintext; ciphertext = allocate(0, ciphertext); buffer = allocate_buffer(ciphertext, ciphertext.length); error = lib._noise_symmetricstate_decrypt_and_hash(this._state, buffer); plaintext = ciphertext.get().slice(0, ciphertext.length - this._mac_length); ciphertext.free(); buffer.free(); assert_no_error(error, this); return plaintext; } /** * @return {CipherState[]} */, Split: function(){ var tmp1, tmp2, error, e, cs1, cs2; tmp1 = allocate_pointer(); tmp2 = allocate_pointer(); error = lib._noise_symmetricstate_split(this._state, tmp1, tmp2); try { assert_no_error(error); } catch (e$) { e = e$; tmp1.free(); tmp2.free(); throw e; } cs1 = new CipherState_split(tmp1.dereference()); cs2 = new CipherState_split(tmp2.dereference()); tmp1.free(); tmp2.free(); try { this.free(); } catch (e$) { e = e$; try { cs1.free(); } catch (e$) {} try { cs2.free(); } catch (e$) {} throw e; } return [cs1, cs2]; } /** * Call this when object is not needed anymore to avoid memory leaks */, free: function(){ var error; error = lib._noise_symmetricstate_free(this._state); delete this._state; delete this._mac_length; assert_no_error(error); } }; Object.defineProperty(SymmetricState.prototype, 'constructor', { enumerable: false, value: SymmetricState }); /** * The HandshakeState object, API is close to the spec: http://noiseprotocol.org/noise.html#the-handshakestate-object * * NOTE: If you ever get an exception with Error object, whose message is one of constants.NOISE_ERROR_* keys, object is no longer usable and there is no need * to call free() method, as it was called for you automatically already (except in ReadMessage with fallback_supported == true) * * @param {string} protocol_name The name of the Noise protocol to use, for instance, Noise_N_25519_ChaChaPoly_BLAKE2b * @param {number} role The role for the new object, either constants.NOISE_ROLE_INITIATOR or constants.NOISE_ROLE_RESPONDER */ function HandshakeState(protocol_name, role){ var tmp, error; if (!(this instanceof HandshakeState)) { return new HandshakeState(protocol_name, role); } tmp = allocate_pointer(); protocol_name = allocate(0, protocol_name); error = lib._noise_handshakestate_new_by_name(tmp, protocol_name, role); protocol_name.free(); assert_no_error(error, tmp); this._state = tmp.dereference(); tmp.free(); } HandshakeState.prototype = { /** * Must be called after object creation and after switch to a fallback handshake. * * In case of fallback handshake it is not required to specify values that are the same as in previous Initialize() call, those will be used by default * * @param {null|Uint8Array} prologue Prologue value * @param {null|Uint8Array} s Local static private key * @param {null|Uint8Array} rs Remote static public key * @param {null|Uint8Array} psk Pre-shared symmetric key */ Initialize: function(prologue, s, rs, psk){ var error, dh; prologue == null && (prologue = null); s == null && (s = null); rs == null && (rs = null); psk == null && (psk = null); if (prologue) { prologue = allocate(0, prologue); error = lib._noise_handshakestate_set_prologue(this._state, prologue, prologue.length); prologue.free(); assert_no_error(error, this); } if (psk && lib._noise_handshakestate_needs_pre_shared_key(this._state) === 1) { psk = allocate(0, psk); error = lib._noise_handshakestate_set_pre_shared_key(this._state, psk, psk.length); psk.free(); assert_no_error(error, this); } if (lib._noise_handshakestate_needs_local_keypair(this._state) === 1) { if (!s) { throw new Error('Local static private key (s) required, but not provided'); } dh = lib._noise_handshakestate_get_local_keypair_dh(this._state); s = allocate(0, s); error = lib._noise_dhstate_set_keypair_private(dh, s, s.length); s.free(); assert_no_error(error, this); } if (lib._noise_handshakestate_needs_remote_public_key(this._state) === 1) { if (!rs) { throw new Error('Remote static public key (rs) required, but not provided'); } dh = lib._noise_handshakestate_get_remote_public_key_dh(this._state); rs = allocate(0, rs); error = lib._noise_dhstate_set_public_key(dh, rs, rs.length); rs.free(); assert_no_error(error, this); } error = lib._noise_handshakestate_start(this._state); assert_no_error(error, this); } /** * @return {number} One of constants.NOISE_ACTION_* */, GetAction: function(){ return lib._noise_handshakestate_get_action(this._state); } /** * Might be called when GetAction() returned constants.NOISE_ACTION_FAILED and switching to fallback protocol is desired, don't forget to call Initialize() * after FallbackTo() * * @param {number} pattern_id One of constants.NOISE_PATTERN_*_FALLBACK* */, FallbackTo: function(pattern_id){ var error; pattern_id == null && (pattern_id = constants.NOISE_PATTERN_XX_FALLBACK); error = lib._noise_handshakestate_fallback_to(this._state, pattern_id); assert_no_error(error, this); } /** * @param {null|Uint8Array} payload null if no payload is required * * @return {Uint8Array} Message that should be sent to the other side */, WriteMessage: function(payload){ var message, message_buffer, payload_buffer, error, e, message_length, real_message; payload == null && (payload = null); message = allocate(constants.NOISE_MAX_PAYLOAD_LEN); message_buffer = allocate_buffer(message, 0); payload_buffer = null; if (payload) { payload = allocate(0, payload); payload_buffer = allocate_buffer(payload, payload.length); } error = lib._noise_handshakestate_write_message(this._state, message_buffer, payload_buffer); if (payload) { payload.free(); payload_buffer.free(); } try { assert_no_error(error, this); } catch (e$) { e = e$; message.free(); message_buffer.free(); throw e; } message_length = lib._NoiseBuffer_get_size(message_buffer); real_message = message.get().slice(0, message_length); message.free(); message_buffer.free(); return real_message; } /** * @param {Uint8Array} message Message received from the other side * @param {boolean} payload_needed false if the application does not need the message payload * @param {boolean} fallback_supported true if application is ready to switch to fallback pattern (will throw, but without free() call on read failure) * * @return {null|Uint8Array} */, ReadMessage: function(message, payload_needed, fallback_supported){ var message_buffer, payload_buffer, payload, error, e, real_payload, payload_length; payload_needed == null && (payload_needed = false); fallback_supported == null && (fallback_supported = false); message = allocate(0, message); message_buffer = allocate_buffer(message, message.length); payload_buffer = null; if (payload_needed) { payload = allocate(constants.NOISE_MAX_PAYLOAD_LEN); payload_buffer = allocate_buffer(payload, payload.length); } error = lib._noise_handshakestate_read_message(this._state, message_buffer, payload_buffer); message.free(); message_buffer.free(); try { assert_no_error(error, fallback_supported ? undefined : this); } catch (e$) { e = e$; if (payload_needed) { payload.free(); payload_buffer.free(); } throw e; } real_payload = null; if (payload_needed) { payload_length = lib._NoiseBuffer_get_size(payload_buffer); real_payload = payload.get().slice(0, payload_length); payload.free(); payload_buffer.free(); } return real_payload; } /** * @return {CipherState[]} [send, receive] */, Split: function(){ var tmp1, tmp2, error, e, cs1, cs2; tmp1 = allocate_pointer(); tmp2 = allocate_pointer(); error = lib._noise_handshakestate_split(this._state, tmp1, tmp2); try { assert_no_error(error, this); } catch (e$) { e = e$; tmp1.free(); tmp2.free(); throw e; } cs1 = new CipherState_split(tmp1.dereference()); cs2 = new CipherState_split(tmp2.dereference()); tmp1.free(); tmp2.free(); try { this.free(); } catch (e$) { e = e$; try { cs1.free(); } catch (e$) {} try { cs2.free(); } catch (e$) {} throw e; } return [cs1, cs2]; } /** * Gets the channel binding has if the handshake is completed otherwise throws `Error` * * @return {Uint8Array} * * @throws {Error} */, GetHandshakeHash: function(){ var hash_buffer, error, hs_id, real_hash, e; hash_buffer = allocate(64); error = lib._noise_handshakestate_get_handshake_hash(this._state, hash_buffer, hash_buffer.length); try { assert_no_error(error); hs_id = lib._NoiseHandshakeState_get_hash_id(this._state); switch (hs_id) { case constants.NOISE_HASH_BLAKE2s: case constants.NOISE_HASH_SHA256: real_hash = hash_buffer.get().slice(0, 32); break; case constants.NOISE_HASH_BLAKE2b: case constants.NOISE_HASH_SHA512: real_hash = hash_buffer.get(); break; default: throw new Error("invalid hash id:" + hs_id); } hash_buffer.free(); hash_buffer = null; } catch (e$) { e = e$; hash_buffer.free(); hash_buffer = null; throw e; } return real_hash; } /** * Gets raw remote static public key if available * * @return {Uint8Array} `null` if not available */, GetRemotePublicKey: function(){ var dhs, key_length, key_buffer, error, real_key, e; if (lib._noise_handshakestate_has_remote_public_key(this._state)) { dhs = lib._noise_handshakestate_get_remote_public_key_dh(this._state); key_length = lib._noise_dhstate_get_public_key_length(dhs); if (key_length) { key_buffer = allocate(key_length); error = lib._noise_dhstate_get_public_key(dhs, key_buffer, key_length); dhs = null; try { assert_no_error(error); real_key = key_buffer.get(); key_buffer.free(); return real_key; } catch (e$) { e = e$; key_buffer.free(); throw e; } } } return null; } /** * Call this when object is not needed anymore to avoid memory leaks */, free: function(){ var error; error = lib._noise_handshakestate_free(this._state); delete this._state; assert_no_error(error); } }; Object.defineProperty(HandshakeState.prototype, 'constructor', { enumerable: false, value: HandshakeState }); callback({ 'constants': constants, 'CipherState': CipherState, 'SymmetricState': SymmetricState, 'HandshakeState': HandshakeState, 'CreateKeyPair': CreateKeyPair, '_lib_internal': lib }); }); } function Wrapper(lib, constants){ return CreateLib.bind(this, lib, constants); } if (typeof define === 'function' && define['amd']) { define(['./noise-c', './constants'], Wrapper); } else if (typeof exports === 'object') { module.exports = Wrapper(require('./noise-c'), require('./constants')); } else { this['noise_c_wasm'] = Wrapper(this['__noise_c_wasm'], this['__noise_c_wasm_constants']); } }).call(this);