no bug - Bumping Firefox l10n changesets r=release a=l10n-bump DONTBUILD CLOSED TREE
[gecko.git] / services / fxaccounts / FxAccountsPairingChannel.sys.mjs
blobcb6d3fdb91a4d5eb64d22095ef127f34bbbff49f
1 /*!
2  * 
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
6  * 
7  * The following bundle is from an external repository at github.com/mozilla/fxa-pairing-channel,
8  * it implements a shared library for two javascript environments to create an encrypted and authenticated
9  * communication channel by sharing a secret key and by relaying messages through a websocket server.
10  * 
11  * It is used by the Firefox Accounts pairing flow, with one side of the channel being web
12  * content from https://accounts.firefox.com and the other side of the channel being chrome native code.
13  * 
14  * This uses the event-target-shim node library published under the MIT license:
15  * https://github.com/mysticatea/event-target-shim/blob/master/LICENSE
16  * 
17  * Bundle generated from https://github.com/mozilla/fxa-pairing-channel.git. Hash:c8ec3119920b4ffa833b, Chunkhash:378a5f51445e7aa7630e.
18  * 
19  */
21 // This header provides a little bit of plumbing to use `FxAccountsPairingChannel`
22 // from Firefox browser code, hence the presence of these privileged browser APIs.
23 // If you're trying to use this from ordinary web content you're in for a bad time.
25 import { setTimeout } from "resource://gre/modules/Timer.sys.mjs";
27 // We cannot use WebSocket from chrome code without a window,
28 // see https://bugzilla.mozilla.org/show_bug.cgi?id=784686
29 const browser = Services.appShell.createWindowlessBrowser(true);
30 const {WebSocket} = browser.document.ownerGlobal;
32 export var FxAccountsPairingChannel =
33 /******/ (function(modules) { // webpackBootstrap
34 /******/        // The module cache
35 /******/        var installedModules = {};
36 /******/
37 /******/        // The require function
38 /******/        function __webpack_require__(moduleId) {
39 /******/
40 /******/                // Check if module is in cache
41 /******/                if(installedModules[moduleId]) {
42 /******/                        return installedModules[moduleId].exports;
43 /******/                }
44 /******/                // Create a new module (and put it into the cache)
45 /******/                var module = installedModules[moduleId] = {
46 /******/                        i: moduleId,
47 /******/                        l: false,
48 /******/                        exports: {}
49 /******/                };
50 /******/
51 /******/                // Execute the module function
52 /******/                modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
53 /******/
54 /******/                // Flag the module as loaded
55 /******/                module.l = true;
56 /******/
57 /******/                // Return the exports of the module
58 /******/                return module.exports;
59 /******/        }
60 /******/
61 /******/
62 /******/        // expose the modules object (__webpack_modules__)
63 /******/        __webpack_require__.m = modules;
64 /******/
65 /******/        // expose the module cache
66 /******/        __webpack_require__.c = installedModules;
67 /******/
68 /******/        // define getter function for harmony exports
69 /******/        __webpack_require__.d = function(exports, name, getter) {
70 /******/                if(!__webpack_require__.o(exports, name)) {
71 /******/                        Object.defineProperty(exports, name, { enumerable: true, get: getter });
72 /******/                }
73 /******/        };
74 /******/
75 /******/        // define __esModule on exports
76 /******/        __webpack_require__.r = function(exports) {
77 /******/                if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
78 /******/                        Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
79 /******/                }
80 /******/                Object.defineProperty(exports, '__esModule', { value: true });
81 /******/        };
82 /******/
83 /******/        // create a fake namespace object
84 /******/        // mode & 1: value is a module id, require it
85 /******/        // mode & 2: merge all properties of value into the ns
86 /******/        // mode & 4: return value when already ns object
87 /******/        // mode & 8|1: behave like require
88 /******/        __webpack_require__.t = function(value, mode) {
89 /******/                if(mode & 1) value = __webpack_require__(value);
90 /******/                if(mode & 8) return value;
91 /******/                if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
92 /******/                var ns = Object.create(null);
93 /******/                __webpack_require__.r(ns);
94 /******/                Object.defineProperty(ns, 'default', { enumerable: true, value: value });
95 /******/                if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
96 /******/                return ns;
97 /******/        };
98 /******/
99 /******/        // getDefaultExport function for compatibility with non-harmony modules
100 /******/        __webpack_require__.n = function(module) {
101 /******/                var getter = module && module.__esModule ?
102 /******/                        function getDefault() { return module['default']; } :
103 /******/                        function getModuleExports() { return module; };
104 /******/                __webpack_require__.d(getter, 'a', getter);
105 /******/                return getter;
106 /******/        };
107 /******/
108 /******/        // Object.prototype.hasOwnProperty.call
109 /******/        __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
110 /******/
111 /******/        // __webpack_public_path__
112 /******/        __webpack_require__.p = "";
113 /******/
114 /******/
115 /******/        // Load entry module and return exports
116 /******/        return __webpack_require__(__webpack_require__.s = 0);
117 /******/ })
118 /************************************************************************/
119 /******/ ([
120 /* 0 */
121 /***/ (function(module, __webpack_exports__, __webpack_require__) {
123 "use strict";
124 // ESM COMPAT FLAG
125 __webpack_require__.r(__webpack_exports__);
127 // EXPORTS
128 __webpack_require__.d(__webpack_exports__, "PairingChannel", function() { return /* binding */ src_PairingChannel; });
129 __webpack_require__.d(__webpack_exports__, "base64urlToBytes", function() { return /* reexport */ base64urlToBytes; });
130 __webpack_require__.d(__webpack_exports__, "bytesToBase64url", function() { return /* reexport */ bytesToBase64url; });
131 __webpack_require__.d(__webpack_exports__, "bytesToHex", function() { return /* reexport */ bytesToHex; });
132 __webpack_require__.d(__webpack_exports__, "bytesToUtf8", function() { return /* reexport */ bytesToUtf8; });
133 __webpack_require__.d(__webpack_exports__, "hexToBytes", function() { return /* reexport */ hexToBytes; });
134 __webpack_require__.d(__webpack_exports__, "TLSCloseNotify", function() { return /* reexport */ TLSCloseNotify; });
135 __webpack_require__.d(__webpack_exports__, "TLSError", function() { return /* reexport */ TLSError; });
136 __webpack_require__.d(__webpack_exports__, "utf8ToBytes", function() { return /* reexport */ utf8ToBytes; });
137 __webpack_require__.d(__webpack_exports__, "_internals", function() { return /* binding */ _internals; });
139 // CONCATENATED MODULE: ./src/alerts.js
140 /* This Source Code Form is subject to the terms of the Mozilla Public
141  * License, v. 2.0. If a copy of the MPL was not distributed with this
142  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
144 /* eslint-disable sorting/sort-object-props */
145 const ALERT_LEVEL = {
146   WARNING: 1,
147   FATAL: 2
150 const ALERT_DESCRIPTION = {
151   CLOSE_NOTIFY: 0,
152   UNEXPECTED_MESSAGE: 10,
153   BAD_RECORD_MAC: 20,
154   RECORD_OVERFLOW: 22,
155   HANDSHAKE_FAILURE: 40,
156   ILLEGAL_PARAMETER: 47,
157   DECODE_ERROR: 50,
158   DECRYPT_ERROR: 51,
159   PROTOCOL_VERSION: 70,
160   INTERNAL_ERROR: 80,
161   MISSING_EXTENSION: 109,
162   UNSUPPORTED_EXTENSION: 110,
163   UNKNOWN_PSK_IDENTITY: 115,
164   NO_APPLICATION_PROTOCOL: 120,
166 /* eslint-enable sorting/sort-object-props */
168 function alertTypeToName(type) {
169   for (const name in ALERT_DESCRIPTION) {
170     if (ALERT_DESCRIPTION[name] === type) {
171       return `${name} (${type})`;
172     }
173   }
174   return `UNKNOWN (${type})`;
177 class TLSAlert extends Error {
178   constructor(description, level) {
179     super(`TLS Alert: ${alertTypeToName(description)}`);
180     this.description = description;
181     this.level = level;
182   }
184   static fromBytes(bytes) {
185     if (bytes.byteLength !== 2) {
186       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
187     }
188     switch (bytes[1]) {
189       case ALERT_DESCRIPTION.CLOSE_NOTIFY:
190         if (bytes[0] !== ALERT_LEVEL.WARNING) {
191           // Close notifications should be fatal.
192           throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
193         }
194         return new TLSCloseNotify();
195       default:
196         return new TLSError(bytes[1]);
197     }
198   }
200   toBytes() {
201     return new Uint8Array([this.level, this.description]);
202   }
205 class TLSCloseNotify extends TLSAlert {
206   constructor() {
207     super(ALERT_DESCRIPTION.CLOSE_NOTIFY, ALERT_LEVEL.WARNING);
208   }
211 class TLSError extends TLSAlert {
212   constructor(description = ALERT_DESCRIPTION.INTERNAL_ERROR) {
213     super(description, ALERT_LEVEL.FATAL);
214   }
217 // CONCATENATED MODULE: ./src/utils.js
218 /* This Source Code Form is subject to the terms of the Mozilla Public
219  * License, v. 2.0. If a copy of the MPL was not distributed with this
220  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
225 // Various low-level utility functions.
227 // These are mostly conveniences for working with Uint8Arrays as
228 // the primitive "bytes" type.
231 const UTF8_ENCODER = new TextEncoder();
232 const UTF8_DECODER = new TextDecoder();
234 function noop() {}
236 function assert(cond, msg) {
237   if (! cond) {
238     throw new Error('assert failed: ' + msg);
239   }
242 function assertIsBytes(value, msg = 'value must be a Uint8Array') {
243   // Using `value instanceof Uint8Array` seems to fail in Firefox chrome code
244   // for inscrutable reasons, so we do a less direct check.
245   assert(ArrayBuffer.isView(value), msg);
246   assert(value.BYTES_PER_ELEMENT === 1, msg);
247   return value;
250 const EMPTY = new Uint8Array(0);
252 function zeros(n) {
253   return new Uint8Array(n);
256 function arrayToBytes(value) {
257   return new Uint8Array(value);
260 function bytesToHex(bytes) {
261   return Array.prototype.map.call(bytes, byte => {
262     let s = byte.toString(16);
263     if (s.length === 1) {
264       s = '0' + s;
265     }
266     return s;
267   }).join('');
270 function hexToBytes(hexstr) {
271   assert(hexstr.length % 2 === 0, 'hexstr.length must be even');
272   return new Uint8Array(Array.prototype.map.call(hexstr, (c, n) => {
273     if (n % 2 === 1) {
274       return hexstr[n - 1] + c;
275     } else {
276       return '';
277     }
278   }).filter(s => {
279     return !! s;
280   }).map(s => {
281     return parseInt(s, 16);
282   }));
285 function bytesToUtf8(bytes) {
286   return UTF8_DECODER.decode(bytes);
289 function utf8ToBytes(str) {
290   return UTF8_ENCODER.encode(str);
293 function bytesToBase64url(bytes) {
294   // XXX TODO: try to use something constant-time, in case calling code
295   // uses it to encode secrets?
296   const charCodes = String.fromCharCode.apply(String, bytes);
297   return btoa(charCodes).replace(/\+/g, '-').replace(/\//g, '_');
300 function base64urlToBytes(str) {
301   // XXX TODO: try to use something constant-time, in case calling code
302   // uses it to decode secrets?
303   str = atob(str.replace(/-/g, '+').replace(/_/g, '/'));
304   const bytes = new Uint8Array(str.length);
305   for (let i = 0; i < str.length; i++) {
306     bytes[i] = str.charCodeAt(i);
307   }
308   return bytes;
311 function bytesAreEqual(v1, v2) {
312   assertIsBytes(v1);
313   assertIsBytes(v2);
314   if (v1.length !== v2.length) {
315     return false;
316   }
317   for (let i = 0; i < v1.length; i++) {
318     if (v1[i] !== v2[i]) {
319       return false;
320     }
321   }
322   return true;
325 // The `BufferReader` and `BufferWriter` classes are helpers for dealing with the
326 // binary struct format that's used for various TLS message.  Think of them as a
327 // buffer with a pointer to the "current position" and a bunch of helper methods
328 // to read/write structured data and advance said pointer.
330 class utils_BufferWithPointer {
331   constructor(buf) {
332     this._buffer = buf;
333     this._dataview = new DataView(buf.buffer, buf.byteOffset, buf.byteLength);
334     this._pos = 0;
335   }
337   length() {
338     return this._buffer.byteLength;
339   }
341   tell() {
342     return this._pos;
343   }
345   seek(pos) {
346     if (pos < 0) {
347       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
348     }
349     if (pos > this.length()) {
350       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
351     }
352     this._pos = pos;
353   }
355   incr(offset) {
356     this.seek(this._pos + offset);
357   }
360 // The `BufferReader` class helps you read structured data from a byte array.
361 // It offers methods for reading both primitive values, and the variable-length
362 // vector structures defined in https://tools.ietf.org/html/rfc8446#section-3.4.
364 // Such vectors are represented as a length followed by the concatenated
365 // bytes of each item, and the size of the length field is determined by
366 // the maximum allowed number of bytes in the vector.  For example
367 // to read a vector that may contain up to 65535 bytes, use `readVector16`.
369 // To read a variable-length vector of between 1 and 100 uint16 values,
370 // defined in the RFC like this:
372 //    uint16 items<2..200>;
374 // You would do something like this:
376 //    const items = []
377 //    buf.readVector8(buf => {
378 //      items.push(buf.readUint16())
379 //    })
381 // The various `read` will throw `DECODE_ERROR` if you attempt to read path
382 // the end of the buffer, or past the end of a variable-length list.
384 class utils_BufferReader extends utils_BufferWithPointer {
386   hasMoreBytes() {
387     return this.tell() < this.length();
388   }
390   readBytes(length) {
391     // This avoids copies by returning a view onto the existing buffer.
392     const start = this._buffer.byteOffset + this.tell();
393     this.incr(length);
394     return new Uint8Array(this._buffer.buffer, start, length);
395   }
397   _rangeErrorToAlert(cb) {
398     try {
399       return cb(this);
400     } catch (err) {
401       if (err instanceof RangeError) {
402         throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
403       }
404       throw err;
405     }
406   }
408   readUint8() {
409     return this._rangeErrorToAlert(() => {
410       const n = this._dataview.getUint8(this._pos);
411       this.incr(1);
412       return n;
413     });
414   }
416   readUint16() {
417     return this._rangeErrorToAlert(() => {
418       const n = this._dataview.getUint16(this._pos);
419       this.incr(2);
420       return n;
421     });
422   }
424   readUint24() {
425     return this._rangeErrorToAlert(() => {
426       let n = this._dataview.getUint16(this._pos);
427       n = (n << 8) | this._dataview.getUint8(this._pos + 2);
428       this.incr(3);
429       return n;
430     });
431   }
433   readUint32() {
434     return this._rangeErrorToAlert(() => {
435       const n = this._dataview.getUint32(this._pos);
436       this.incr(4);
437       return n;
438     });
439   }
441   _readVector(length, cb) {
442     const contentsBuf = new utils_BufferReader(this.readBytes(length));
443     const expectedEnd = this.tell();
444     // Keep calling the callback until we've consumed the expected number of bytes.
445     let n = 0;
446     while (contentsBuf.hasMoreBytes()) {
447       const prevPos = contentsBuf.tell();
448       cb(contentsBuf, n);
449       // Check that the callback made forward progress, otherwise we'll infinite loop.
450       if (contentsBuf.tell() <= prevPos) {
451         throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
452       }
453       n += 1;
454     }
455     // Check that the callback correctly consumed the vector's entire contents.
456     if (this.tell() !== expectedEnd) {
457       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
458     }
459   }
461   readVector8(cb) {
462     const length = this.readUint8();
463     return this._readVector(length, cb);
464   }
466   readVector16(cb) {
467     const length = this.readUint16();
468     return this._readVector(length, cb);
469   }
471   readVector24(cb) {
472     const length = this.readUint24();
473     return this._readVector(length, cb);
474   }
476   readVectorBytes8() {
477     return this.readBytes(this.readUint8());
478   }
480   readVectorBytes16() {
481     return this.readBytes(this.readUint16());
482   }
484   readVectorBytes24() {
485     return this.readBytes(this.readUint24());
486   }
490 class utils_BufferWriter extends utils_BufferWithPointer {
491   constructor(size = 1024) {
492     super(new Uint8Array(size));
493   }
495   _maybeGrow(n) {
496     const curSize = this._buffer.byteLength;
497     const newPos = this._pos + n;
498     const shortfall = newPos - curSize;
499     if (shortfall > 0) {
500       // Classic grow-by-doubling, up to 4kB max increment.
501       // This formula was not arrived at by any particular science.
502       const incr = Math.min(curSize, 4 * 1024);
503       const newbuf = new Uint8Array(curSize + Math.ceil(shortfall / incr) * incr);
504       newbuf.set(this._buffer, 0);
505       this._buffer = newbuf;
506       this._dataview = new DataView(newbuf.buffer, newbuf.byteOffset, newbuf.byteLength);
507     }
508   }
510   slice(start = 0, end = this.tell()) {
511     if (end < 0) {
512       end = this.tell() + end;
513     }
514     if (start < 0) {
515       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
516     }
517     if (end < 0) {
518       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
519     }
520     if (end > this.length()) {
521       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
522     }
523     return this._buffer.slice(start, end);
524   }
526   flush() {
527     const slice = this.slice();
528     this.seek(0);
529     return slice;
530   }
532   writeBytes(data) {
533     this._maybeGrow(data.byteLength);
534     this._buffer.set(data, this.tell());
535     this.incr(data.byteLength);
536   }
538   writeUint8(n) {
539     this._maybeGrow(1);
540     this._dataview.setUint8(this._pos, n);
541     this.incr(1);
542   }
544   writeUint16(n) {
545     this._maybeGrow(2);
546     this._dataview.setUint16(this._pos, n);
547     this.incr(2);
548   }
550   writeUint24(n) {
551     this._maybeGrow(3);
552     this._dataview.setUint16(this._pos, n >> 8);
553     this._dataview.setUint8(this._pos + 2, n & 0xFF);
554     this.incr(3);
555   }
557   writeUint32(n) {
558     this._maybeGrow(4);
559     this._dataview.setUint32(this._pos, n);
560     this.incr(4);
561   }
563   // These are helpers for writing the variable-length vector structure
564   // defined in https://tools.ietf.org/html/rfc8446#section-3.4.
565   //
566   // Such vectors are represented as a length followed by the concatenated
567   // bytes of each item, and the size of the length field is determined by
568   // the maximum allowed size of the vector.  For example to write a vector
569   // that may contain up to 65535 bytes, use `writeVector16`.
570   //
571   // To write a variable-length vector of between 1 and 100 uint16 values,
572   // defined in the RFC like this:
573   //
574   //    uint16 items<2..200>;
575   //
576   // You would do something like this:
577   //
578   //    buf.writeVector8(buf => {
579   //      for (let item of items) {
580   //          buf.writeUint16(item)
581   //      }
582   //    })
583   //
584   // The helper will automatically take care of writing the appropriate
585   // length field once the callback completes.
587   _writeVector(maxLength, writeLength, cb) {
588     // Initially, write the length field as zero.
589     const lengthPos = this.tell();
590     writeLength(0);
591     // Call the callback to write the vector items.
592     const bodyPos = this.tell();
593     cb(this);
594     const length = this.tell() - bodyPos;
595     if (length >= maxLength) {
596       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
597     }
598     // Backfill the actual length field.
599     this.seek(lengthPos);
600     writeLength(length);
601     this.incr(length);
602     return length;
603   }
605   writeVector8(cb) {
606     return this._writeVector(Math.pow(2, 8), len => this.writeUint8(len), cb);
607   }
609   writeVector16(cb) {
610     return this._writeVector(Math.pow(2, 16), len => this.writeUint16(len), cb);
611   }
613   writeVector24(cb) {
614     return this._writeVector(Math.pow(2, 24), len => this.writeUint24(len), cb);
615   }
617   writeVectorBytes8(bytes) {
618     return this.writeVector8(buf => {
619       buf.writeBytes(bytes);
620     });
621   }
623   writeVectorBytes16(bytes) {
624     return this.writeVector16(buf => {
625       buf.writeBytes(bytes);
626     });
627   }
629   writeVectorBytes24(bytes) {
630     return this.writeVector24(buf => {
631       buf.writeBytes(bytes);
632     });
633   }
636 // CONCATENATED MODULE: ./src/crypto.js
637 /* This Source Code Form is subject to the terms of the Mozilla Public
638  * License, v. 2.0. If a copy of the MPL was not distributed with this
639  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
642 // Low-level crypto primitives.
644 // This file implements the AEAD encrypt/decrypt and hashing routines
645 // for the TLS_AES_128_GCM_SHA256 ciphersuite. They are (thankfully)
646 // fairly light-weight wrappers around what's available via the WebCrypto
647 // API.
653 const AEAD_SIZE_INFLATION = 16;
654 const KEY_LENGTH = 16;
655 const IV_LENGTH = 12;
656 const HASH_LENGTH = 32;
658 async function prepareKey(key, mode) {
659   return crypto.subtle.importKey('raw', key, { name: 'AES-GCM' }, false, [mode]);
662 async function encrypt(key, iv, plaintext, additionalData) {
663   const ciphertext = await crypto.subtle.encrypt({
664     additionalData,
665     iv,
666     name: 'AES-GCM',
667     tagLength: AEAD_SIZE_INFLATION * 8
668   }, key, plaintext);
669   return new Uint8Array(ciphertext);
672 async function decrypt(key, iv, ciphertext, additionalData) {
673   try {
674     const plaintext = await crypto.subtle.decrypt({
675       additionalData,
676       iv,
677       name: 'AES-GCM',
678       tagLength: AEAD_SIZE_INFLATION * 8
679     }, key, ciphertext);
680     return new Uint8Array(plaintext);
681   } catch (err) {
682     // Yes, we really do throw 'decrypt_error' when failing to verify a HMAC,
683     // and a 'bad_record_mac' error when failing to decrypt.
684     throw new TLSError(ALERT_DESCRIPTION.BAD_RECORD_MAC);
685   }
688 async function hash(message) {
689   return new Uint8Array(await crypto.subtle.digest({ name: 'SHA-256' }, message));
692 async function hmac(keyBytes, message) {
693   const key = await crypto.subtle.importKey('raw', keyBytes, {
694     hash: { name: 'SHA-256' },
695     name: 'HMAC',
696   }, false, ['sign']);
697   const sig = await crypto.subtle.sign({ name: 'HMAC' }, key, message);
698   return new Uint8Array(sig);
701 async function verifyHmac(keyBytes, signature, message) {
702   const key = await crypto.subtle.importKey('raw', keyBytes, {
703     hash: { name: 'SHA-256' },
704     name: 'HMAC',
705   }, false, ['verify']);
706   if (! (await crypto.subtle.verify({ name: 'HMAC' }, key, signature, message))) {
707     // Yes, we really do throw 'decrypt_error' when failing to verify a HMAC,
708     // and a 'bad_record_mac' error when failing to decrypt.
709     throw new TLSError(ALERT_DESCRIPTION.DECRYPT_ERROR);
710   }
713 async function hkdfExtract(salt, ikm) {
714   // Ref https://tools.ietf.org/html/rfc5869#section-2.2
715   return await hmac(salt, ikm);
718 async function hkdfExpand(prk, info, length) {
719   // Ref https://tools.ietf.org/html/rfc5869#section-2.3
720   const N = Math.ceil(length / HASH_LENGTH);
721   if (N <= 0) {
722     throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
723   }
724   if (N >= 255) {
725     throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
726   }
727   const input = new utils_BufferWriter();
728   const output = new utils_BufferWriter();
729   let T = new Uint8Array(0);
730   for (let i = 1; i <= N; i++) {
731     input.writeBytes(T);
732     input.writeBytes(info);
733     input.writeUint8(i);
734     T = await hmac(prk, input.flush());
735     output.writeBytes(T);
736   }
737   return output.slice(0, length);
740 async function hkdfExpandLabel(secret, label, context, length) {
741   //  struct {
742   //    uint16 length = Length;
743   //    opaque label < 7..255 > = "tls13 " + Label;
744   //    opaque context < 0..255 > = Context;
745   //  } HkdfLabel;
746   const hkdfLabel = new utils_BufferWriter();
747   hkdfLabel.writeUint16(length);
748   hkdfLabel.writeVectorBytes8(utf8ToBytes('tls13 ' + label));
749   hkdfLabel.writeVectorBytes8(context);
750   return hkdfExpand(secret, hkdfLabel.flush(), length);
753 async function getRandomBytes(size) {
754   const bytes = new Uint8Array(size);
755   crypto.getRandomValues(bytes);
756   return bytes;
759 // CONCATENATED MODULE: ./src/extensions.js
760 /* This Source Code Form is subject to the terms of the Mozilla Public
761  * License, v. 2.0. If a copy of the MPL was not distributed with this
762  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
765 // Extension parsing.
767 // This file contains some helpers for reading/writing the various kinds
768 // of Extension that might appear in a HandshakeMessage.
770 // "Extensions" are how TLS signals the presence of particular bits of optional
771 // functionality in the protocol. Lots of parts of TLS1.3 that don't seem like
772 // they're optional are implemented in terms of an extension, IIUC because that's
773 // what was needed for a clean deployment in amongst earlier versions of the protocol.
780 /* eslint-disable sorting/sort-object-props */
781 const EXTENSION_TYPE = {
782   PRE_SHARED_KEY: 41,
783   SUPPORTED_VERSIONS: 43,
784   PSK_KEY_EXCHANGE_MODES: 45,
786 /* eslint-enable sorting/sort-object-props */
788 // Base class for generic reading/writing of extensions,
789 // which are all uniformly formatted as:
791 //   struct {
792 //     ExtensionType extension_type;
793 //     opaque extension_data<0..2^16-1>;
794 //   } Extension;
796 // Extensions always appear inside of a handshake message,
797 // and their internal structure may differ based on the
798 // type of that message.
800 class extensions_Extension {
802   get TYPE_TAG() {
803     throw new Error('not implemented');
804   }
806   static read(messageType, buf) {
807     const type = buf.readUint16();
808     let ext = {
809       TYPE_TAG: type,
810     };
811     buf.readVector16(buf => {
812       switch (type) {
813         case EXTENSION_TYPE.PRE_SHARED_KEY:
814           ext = extensions_PreSharedKeyExtension._read(messageType, buf);
815           break;
816         case EXTENSION_TYPE.SUPPORTED_VERSIONS:
817           ext = extensions_SupportedVersionsExtension._read(messageType, buf);
818           break;
819         case EXTENSION_TYPE.PSK_KEY_EXCHANGE_MODES:
820           ext = extensions_PskKeyExchangeModesExtension._read(messageType, buf);
821           break;
822         default:
823           // Skip over unrecognised extensions.
824           buf.incr(buf.length());
825       }
826       if (buf.hasMoreBytes()) {
827         throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
828       }
829     });
830     return ext;
831   }
833   write(messageType, buf) {
834     buf.writeUint16(this.TYPE_TAG);
835     buf.writeVector16(buf => {
836       this._write(messageType, buf);
837     });
838   }
840   static _read(messageType, buf) {
841     throw new Error('not implemented');
842   }
844   static _write(messageType, buf) {
845     throw new Error('not implemented');
846   }
849 // The PreSharedKey extension:
851 //  struct {
852 //    opaque identity<1..2^16-1>;
853 //    uint32 obfuscated_ticket_age;
854 //  } PskIdentity;
855 //  opaque PskBinderEntry<32..255>;
856 //  struct {
857 //    PskIdentity identities<7..2^16-1>;
858 //    PskBinderEntry binders<33..2^16-1>;
859 //  } OfferedPsks;
860 //  struct {
861 //    select(Handshake.msg_type) {
862 //      case client_hello: OfferedPsks;
863 //      case server_hello: uint16 selected_identity;
864 //    };
865 //  } PreSharedKeyExtension;
867 class extensions_PreSharedKeyExtension extends extensions_Extension {
868   constructor(identities, binders, selectedIdentity) {
869     super();
870     this.identities = identities;
871     this.binders = binders;
872     this.selectedIdentity = selectedIdentity;
873   }
875   get TYPE_TAG() {
876     return EXTENSION_TYPE.PRE_SHARED_KEY;
877   }
879   static _read(messageType, buf) {
880     let identities = null, binders = null, selectedIdentity = null;
881     switch (messageType) {
882       case HANDSHAKE_TYPE.CLIENT_HELLO:
883         identities = []; binders = [];
884         buf.readVector16(buf => {
885           const identity = buf.readVectorBytes16();
886           buf.readBytes(4); // Skip over the ticket age.
887           identities.push(identity);
888         });
889         buf.readVector16(buf => {
890           const binder = buf.readVectorBytes8();
891           if (binder.byteLength < HASH_LENGTH) {
892             throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
893           }
894           binders.push(binder);
895         });
896         if (identities.length !== binders.length) {
897           throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
898         }
899         break;
900       case HANDSHAKE_TYPE.SERVER_HELLO:
901         selectedIdentity = buf.readUint16();
902         break;
903       default:
904         throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
905     }
906     return new this(identities, binders, selectedIdentity);
907   }
909   _write(messageType, buf) {
910     switch (messageType) {
911       case HANDSHAKE_TYPE.CLIENT_HELLO:
912         buf.writeVector16(buf => {
913           this.identities.forEach(pskId => {
914             buf.writeVectorBytes16(pskId);
915             buf.writeUint32(0); // Zero for "tag age" field.
916           });
917         });
918         buf.writeVector16(buf => {
919           this.binders.forEach(pskBinder => {
920             buf.writeVectorBytes8(pskBinder);
921           });
922         });
923         break;
924       case HANDSHAKE_TYPE.SERVER_HELLO:
925         buf.writeUint16(this.selectedIdentity);
926         break;
927       default:
928         throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
929     }
930   }
934 // The SupportedVersions extension:
936 //  struct {
937 //    select(Handshake.msg_type) {
938 //      case client_hello:
939 //        ProtocolVersion versions < 2..254 >;
940 //      case server_hello:
941 //        ProtocolVersion selected_version;
942 //    };
943 //  } SupportedVersions;
945 class extensions_SupportedVersionsExtension extends extensions_Extension {
946   constructor(versions, selectedVersion) {
947     super();
948     this.versions = versions;
949     this.selectedVersion = selectedVersion;
950   }
952   get TYPE_TAG() {
953     return EXTENSION_TYPE.SUPPORTED_VERSIONS;
954   }
956   static _read(messageType, buf) {
957     let versions = null, selectedVersion = null;
958     switch (messageType) {
959       case HANDSHAKE_TYPE.CLIENT_HELLO:
960         versions = [];
961         buf.readVector8(buf => {
962           versions.push(buf.readUint16());
963         });
964         break;
965       case HANDSHAKE_TYPE.SERVER_HELLO:
966         selectedVersion = buf.readUint16();
967         break;
968       default:
969         throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
970     }
971     return new this(versions, selectedVersion);
972   }
974   _write(messageType, buf) {
975     switch (messageType) {
976       case HANDSHAKE_TYPE.CLIENT_HELLO:
977         buf.writeVector8(buf => {
978           this.versions.forEach(version => {
979             buf.writeUint16(version);
980           });
981         });
982         break;
983       case HANDSHAKE_TYPE.SERVER_HELLO:
984         buf.writeUint16(this.selectedVersion);
985         break;
986       default:
987         throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
988     }
989   }
993 class extensions_PskKeyExchangeModesExtension extends extensions_Extension {
994   constructor(modes) {
995     super();
996     this.modes = modes;
997   }
999   get TYPE_TAG() {
1000     return EXTENSION_TYPE.PSK_KEY_EXCHANGE_MODES;
1001   }
1003   static _read(messageType, buf) {
1004     const modes = [];
1005     switch (messageType) {
1006       case HANDSHAKE_TYPE.CLIENT_HELLO:
1007         buf.readVector8(buf => {
1008           modes.push(buf.readUint8());
1009         });
1010         break;
1011       default:
1012         throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1013     }
1014     return new this(modes);
1015   }
1017   _write(messageType, buf) {
1018     switch (messageType) {
1019       case HANDSHAKE_TYPE.CLIENT_HELLO:
1020         buf.writeVector8(buf => {
1021           this.modes.forEach(mode => {
1022             buf.writeUint8(mode);
1023           });
1024         });
1025         break;
1026       default:
1027         throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
1028     }
1029   }
1032 // CONCATENATED MODULE: ./src/constants.js
1033 /* This Source Code Form is subject to the terms of the Mozilla Public
1034  * License, v. 2.0. If a copy of the MPL was not distributed with this
1035  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
1037 const VERSION_TLS_1_0 = 0x0301;
1038 const VERSION_TLS_1_2 = 0x0303;
1039 const VERSION_TLS_1_3 = 0x0304;
1040 const TLS_AES_128_GCM_SHA256 = 0x1301;
1041 const PSK_MODE_KE = 0;
1043 // CONCATENATED MODULE: ./src/messages.js
1044 /* This Source Code Form is subject to the terms of the Mozilla Public
1045  * License, v. 2.0. If a copy of the MPL was not distributed with this
1046  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
1049 // Message parsing.
1051 // Herein we have code for reading and writing the various Handshake
1052 // messages involved in the TLS protocol.
1061 /* eslint-disable sorting/sort-object-props */
1062 const HANDSHAKE_TYPE = {
1063   CLIENT_HELLO: 1,
1064   SERVER_HELLO: 2,
1065   NEW_SESSION_TICKET: 4,
1066   ENCRYPTED_EXTENSIONS: 8,
1067   FINISHED: 20,
1069 /* eslint-enable sorting/sort-object-props */
1071 // Base class for generic reading/writing of handshake messages,
1072 // which are all uniformly formatted as:
1074 //  struct {
1075 //    HandshakeType msg_type;    /* handshake type */
1076 //    uint24 length;             /* bytes in message */
1077 //    select(Handshake.msg_type) {
1078 //        ... type specific cases here ...
1079 //    };
1080 //  } Handshake;
1082 class messages_HandshakeMessage {
1084   get TYPE_TAG() {
1085     throw new Error('not implemented');
1086   }
1088   static fromBytes(bytes) {
1089     // Each handshake message has a type and length prefix, per
1090     // https://tools.ietf.org/html/rfc8446#appendix-B.3
1091     const buf = new utils_BufferReader(bytes);
1092     const msg = this.read(buf);
1093     if (buf.hasMoreBytes()) {
1094       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
1095     }
1096     return msg;
1097   }
1099   toBytes() {
1100     const buf = new utils_BufferWriter();
1101     this.write(buf);
1102     return buf.flush();
1103   }
1105   static read(buf) {
1106     const type = buf.readUint8();
1107     let msg = null;
1108     buf.readVector24(buf => {
1109       switch (type) {
1110         case HANDSHAKE_TYPE.CLIENT_HELLO:
1111           msg = messages_ClientHello._read(buf);
1112           break;
1113         case HANDSHAKE_TYPE.SERVER_HELLO:
1114           msg = messages_ServerHello._read(buf);
1115           break;
1116         case HANDSHAKE_TYPE.NEW_SESSION_TICKET:
1117           msg = messages_NewSessionTicket._read(buf);
1118           break;
1119         case HANDSHAKE_TYPE.ENCRYPTED_EXTENSIONS:
1120           msg = EncryptedExtensions._read(buf);
1121           break;
1122         case HANDSHAKE_TYPE.FINISHED:
1123           msg = messages_Finished._read(buf);
1124           break;
1125       }
1126       if (buf.hasMoreBytes()) {
1127         throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
1128       }
1129     });
1130     if (msg === null) {
1131       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1132     }
1133     return msg;
1134   }
1136   write(buf) {
1137     buf.writeUint8(this.TYPE_TAG);
1138     buf.writeVector24(buf => {
1139       this._write(buf);
1140     });
1141   }
1143   static _read(buf) {
1144     throw new Error('not implemented');
1145   }
1147   _write(buf) {
1148     throw new Error('not implemented');
1149   }
1151   // Some little helpers for reading a list of extensions,
1152   // which is uniformly represented as:
1153   //
1154   //   Extension extensions<8..2^16-1>;
1155   //
1156   // Recognized extensions are returned as a Map from extension type
1157   // to extension data object, with a special `lastSeenExtension`
1158   // property to make it easy to check which one came last.
1160   static _readExtensions(messageType, buf) {
1161     const extensions = new Map();
1162     buf.readVector16(buf => {
1163       const ext = extensions_Extension.read(messageType, buf);
1164       if (extensions.has(ext.TYPE_TAG)) {
1165         throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
1166       }
1167       extensions.set(ext.TYPE_TAG, ext);
1168       extensions.lastSeenExtension = ext.TYPE_TAG;
1169     });
1170     return extensions;
1171   }
1173   _writeExtensions(buf, extensions) {
1174     buf.writeVector16(buf => {
1175       extensions.forEach(ext => {
1176         ext.write(this.TYPE_TAG, buf);
1177       });
1178     });
1179   }
1183 // The ClientHello message:
1185 // struct {
1186 //   ProtocolVersion legacy_version = 0x0303;
1187 //   Random random;
1188 //   opaque legacy_session_id<0..32>;
1189 //   CipherSuite cipher_suites<2..2^16-2>;
1190 //   opaque legacy_compression_methods<1..2^8-1>;
1191 //   Extension extensions<8..2^16-1>;
1192 // } ClientHello;
1194 class messages_ClientHello extends messages_HandshakeMessage {
1196   constructor(random, sessionId, extensions) {
1197     super();
1198     this.random = random;
1199     this.sessionId = sessionId;
1200     this.extensions = extensions;
1201   }
1203   get TYPE_TAG() {
1204     return HANDSHAKE_TYPE.CLIENT_HELLO;
1205   }
1207   static _read(buf) {
1208     // The legacy_version field may indicate an earlier version of TLS
1209     // for backwards compatibility, but must not predate TLS 1.0!
1210     if (buf.readUint16() < VERSION_TLS_1_0) {
1211       throw new TLSError(ALERT_DESCRIPTION.PROTOCOL_VERSION);
1212     }
1213     // The random bytes provided by the peer.
1214     const random = buf.readBytes(32);
1215     // Read legacy_session_id, so the server can echo it.
1216     const sessionId = buf.readVectorBytes8();
1217     // We only support a single ciphersuite, but the peer may offer several.
1218     // Scan the list to confirm that the one we want is present.
1219     let found = false;
1220     buf.readVector16(buf => {
1221       const cipherSuite = buf.readUint16();
1222       if (cipherSuite === TLS_AES_128_GCM_SHA256) {
1223         found = true;
1224       }
1225     });
1226     if (! found) {
1227       throw new TLSError(ALERT_DESCRIPTION.HANDSHAKE_FAILURE);
1228     }
1229     // legacy_compression_methods must be a single zero byte for TLS1.3 ClientHellos.
1230     // It can be non-zero in previous versions of TLS, but we're not going to
1231     // make a successful handshake with such versions, so better to just bail out now.
1232     const legacyCompressionMethods = buf.readVectorBytes8();
1233     if (legacyCompressionMethods.byteLength !== 1) {
1234       throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1235     }
1236     if (legacyCompressionMethods[0] !== 0x00) {
1237       throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1238     }
1239     // Read and check the extensions.
1240     const extensions = this._readExtensions(HANDSHAKE_TYPE.CLIENT_HELLO, buf);
1241     if (! extensions.has(EXTENSION_TYPE.SUPPORTED_VERSIONS)) {
1242       throw new TLSError(ALERT_DESCRIPTION.MISSING_EXTENSION);
1243     }
1244     if (extensions.get(EXTENSION_TYPE.SUPPORTED_VERSIONS).versions.indexOf(VERSION_TLS_1_3) === -1) {
1245       throw new TLSError(ALERT_DESCRIPTION.PROTOCOL_VERSION);
1246     }
1247     // Was the PreSharedKey extension the last one?
1248     if (extensions.has(EXTENSION_TYPE.PRE_SHARED_KEY)) {
1249       if (extensions.lastSeenExtension !== EXTENSION_TYPE.PRE_SHARED_KEY) {
1250         throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1251       }
1252     }
1253     return new this(random, sessionId, extensions);
1254   }
1256   _write(buf) {
1257     buf.writeUint16(VERSION_TLS_1_2);
1258     buf.writeBytes(this.random);
1259     buf.writeVectorBytes8(this.sessionId);
1260     // Our single supported ciphersuite
1261     buf.writeVector16(buf => {
1262       buf.writeUint16(TLS_AES_128_GCM_SHA256);
1263     });
1264     // A single zero byte for legacy_compression_methods
1265     buf.writeVectorBytes8(new Uint8Array(1));
1266     this._writeExtensions(buf, this.extensions);
1267   }
1271 // The ServerHello message:
1273 //  struct {
1274 //      ProtocolVersion legacy_version = 0x0303;    /* TLS v1.2 */
1275 //      Random random;
1276 //      opaque legacy_session_id_echo<0..32>;
1277 //      CipherSuite cipher_suite;
1278 //      uint8 legacy_compression_method = 0;
1279 //      Extension extensions < 6..2 ^ 16 - 1 >;
1280 //  } ServerHello;
1282 class messages_ServerHello extends messages_HandshakeMessage {
1284   constructor(random, sessionId, extensions) {
1285     super();
1286     this.random = random;
1287     this.sessionId = sessionId;
1288     this.extensions = extensions;
1289   }
1291   get TYPE_TAG() {
1292     return HANDSHAKE_TYPE.SERVER_HELLO;
1293   }
1295   static _read(buf) {
1296     // Fixed value for legacy_version.
1297     if (buf.readUint16() !== VERSION_TLS_1_2) {
1298       throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1299     }
1300     // Random bytes from the server.
1301     const random = buf.readBytes(32);
1302     // It should have echoed our vector for legacy_session_id.
1303     const sessionId = buf.readVectorBytes8();
1304     // It should have selected our single offered ciphersuite.
1305     if (buf.readUint16() !== TLS_AES_128_GCM_SHA256) {
1306       throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1307     }
1308     // legacy_compression_method must be zero.
1309     if (buf.readUint8() !== 0) {
1310       throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1311     }
1312     const extensions = this._readExtensions(HANDSHAKE_TYPE.SERVER_HELLO, buf);
1313     if (! extensions.has(EXTENSION_TYPE.SUPPORTED_VERSIONS)) {
1314       throw new TLSError(ALERT_DESCRIPTION.MISSING_EXTENSION);
1315     }
1316     if (extensions.get(EXTENSION_TYPE.SUPPORTED_VERSIONS).selectedVersion !== VERSION_TLS_1_3) {
1317       throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1318     }
1319     return new this(random, sessionId, extensions);
1320   }
1322   _write(buf) {
1323     buf.writeUint16(VERSION_TLS_1_2);
1324     buf.writeBytes(this.random);
1325     buf.writeVectorBytes8(this.sessionId);
1326     // Our single supported ciphersuite
1327     buf.writeUint16(TLS_AES_128_GCM_SHA256);
1328     // A single zero byte for legacy_compression_method
1329     buf.writeUint8(0);
1330     this._writeExtensions(buf, this.extensions);
1331   }
1335 // The EncryptedExtensions message:
1337 //  struct {
1338 //    Extension extensions < 0..2 ^ 16 - 1 >;
1339 //  } EncryptedExtensions;
1341 // We don't actually send any EncryptedExtensions,
1342 // but still have to send an empty message.
1344 class EncryptedExtensions extends messages_HandshakeMessage {
1345   constructor(extensions) {
1346     super();
1347     this.extensions = extensions;
1348   }
1350   get TYPE_TAG() {
1351     return HANDSHAKE_TYPE.ENCRYPTED_EXTENSIONS;
1352   }
1354   static _read(buf) {
1355     const extensions = this._readExtensions(HANDSHAKE_TYPE.ENCRYPTED_EXTENSIONS, buf);
1356     return new this(extensions);
1357   }
1359   _write(buf) {
1360     this._writeExtensions(buf, this.extensions);
1361   }
1365 // The Finished message:
1367 // struct {
1368 //   opaque verify_data[Hash.length];
1369 // } Finished;
1371 class messages_Finished extends messages_HandshakeMessage {
1373   constructor(verifyData) {
1374     super();
1375     this.verifyData = verifyData;
1376   }
1378   get TYPE_TAG() {
1379     return HANDSHAKE_TYPE.FINISHED;
1380   }
1382   static _read(buf) {
1383     const verifyData = buf.readBytes(HASH_LENGTH);
1384     return new this(verifyData);
1385   }
1387   _write(buf) {
1388     buf.writeBytes(this.verifyData);
1389   }
1393 // The NewSessionTicket message:
1395 //   struct {
1396 //    uint32 ticket_lifetime;
1397 //    uint32 ticket_age_add;
1398 //    opaque ticket_nonce < 0..255 >;
1399 //    opaque ticket < 1..2 ^ 16 - 1 >;
1400 //    Extension extensions < 0..2 ^ 16 - 2 >;
1401 //  } NewSessionTicket;
1403 // We don't actually make use of these, but we need to be able
1404 // to accept them and do basic validation.
1406 class messages_NewSessionTicket extends messages_HandshakeMessage {
1407   constructor(ticketLifetime, ticketAgeAdd, ticketNonce, ticket, extensions) {
1408     super();
1409     this.ticketLifetime = ticketLifetime;
1410     this.ticketAgeAdd = ticketAgeAdd;
1411     this.ticketNonce = ticketNonce;
1412     this.ticket = ticket;
1413     this.extensions = extensions;
1414   }
1416   get TYPE_TAG() {
1417     return HANDSHAKE_TYPE.NEW_SESSION_TICKET;
1418   }
1420   static _read(buf) {
1421     const ticketLifetime = buf.readUint32();
1422     const ticketAgeAdd = buf.readUint32();
1423     const ticketNonce = buf.readVectorBytes8();
1424     const ticket = buf.readVectorBytes16();
1425     if (ticket.byteLength < 1) {
1426       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
1427     }
1428     const extensions = this._readExtensions(HANDSHAKE_TYPE.NEW_SESSION_TICKET, buf);
1429     return new this(ticketLifetime, ticketAgeAdd, ticketNonce, ticket, extensions);
1430   }
1432   _write(buf) {
1433     buf.writeUint32(this.ticketLifetime);
1434     buf.writeUint32(this.ticketAgeAdd);
1435     buf.writeVectorBytes8(this.ticketNonce);
1436     buf.writeVectorBytes16(this.ticket);
1437     this._writeExtensions(buf, this.extensions);
1438   }
1441 // CONCATENATED MODULE: ./src/states.js
1442 /* This Source Code Form is subject to the terms of the Mozilla Public
1443  * License, v. 2.0. If a copy of the MPL was not distributed with this
1444  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
1454 // State-machine for TLS Handshake Management.
1456 // Internally, we manage the TLS connection by explicitly modelling the
1457 // client and server state-machines from RFC8446.  You can think of
1458 // these `State` objects as little plugins for the `Connection` class
1459 // that provide different behaviours of `send` and `receive` depending
1460 // on the state of the connection.
1463 class states_State {
1465   constructor(conn) {
1466     this.conn = conn;
1467   }
1469   async initialize() {
1470     // By default, nothing to do when entering the state.
1471   }
1473   async sendApplicationData(bytes) {
1474     // By default, assume we're not ready to send yet and the caller
1475     // should be blocking on the connection promise before reaching here.
1476     throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
1477   }
1479   async recvApplicationData(bytes) {
1480     throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1481   }
1483   async recvHandshakeMessage(msg) {
1484     throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1485   }
1487   async recvAlertMessage(alert) {
1488     switch (alert.description) {
1489       case ALERT_DESCRIPTION.CLOSE_NOTIFY:
1490         this.conn._closeForRecv(alert);
1491         throw alert;
1492       default:
1493         return await this.handleErrorAndRethrow(alert);
1494     }
1495   }
1497   async recvChangeCipherSpec(bytes) {
1498     throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1499   }
1501   async handleErrorAndRethrow(err) {
1502     let alert = err;
1503     if (! (alert instanceof TLSAlert)) {
1504       alert = new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
1505     }
1506     // Try to send error alert to the peer, but we may not
1507     // be able to if the outgoing connection was already closed.
1508     try {
1509       await this.conn._sendAlertMessage(alert);
1510     } catch (_) { }
1511     await this.conn._transition(ERROR, err);
1512     throw err;
1513   }
1515   async close() {
1516     const alert = new TLSCloseNotify();
1517     await this.conn._sendAlertMessage(alert);
1518     this.conn._closeForSend(alert);
1519   }
1523 // A special "guard" state to prevent us from using
1524 // an improperly-initialized Connection.
1526 class UNINITIALIZED extends states_State {
1527   async initialize() {
1528     throw new Error('uninitialized state');
1529   }
1530   async sendApplicationData(bytes) {
1531     throw new Error('uninitialized state');
1532   }
1533   async recvApplicationData(bytes) {
1534     throw new Error('uninitialized state');
1535   }
1536   async recvHandshakeMessage(msg) {
1537     throw new Error('uninitialized state');
1538   }
1539   async recvChangeCipherSpec(bytes) {
1540     throw new Error('uninitialized state');
1541   }
1542   async handleErrorAndRethrow(err) {
1543     throw err;
1544   }
1545   async close() {
1546     throw new Error('uninitialized state');
1547   }
1550 // A special "error" state for when something goes wrong.
1551 // This state never transitions to another state, effectively
1552 // terminating the connection.
1554 class ERROR extends states_State {
1555   async initialize(err) {
1556     this.error = err;
1557     this.conn._setConnectionFailure(err);
1558     // Unceremoniously shut down the record layer on error.
1559     this.conn._recordlayer.setSendError(err);
1560     this.conn._recordlayer.setRecvError(err);
1561   }
1562   async sendApplicationData(bytes) {
1563     throw this.error;
1564   }
1565   async recvApplicationData(bytes) {
1566     throw this.error;
1567   }
1568   async recvHandshakeMessage(msg) {
1569     throw this.error;
1570   }
1571   async recvAlertMessage(err) {
1572     throw this.error;
1573   }
1574   async recvChangeCipherSpec(bytes) {
1575     throw this.error;
1576   }
1577   async handleErrorAndRethrow(err) {
1578     throw err;
1579   }
1580   async close() {
1581     throw this.error;
1582   }
1585 // The "connected" state, for when the handshake is complete
1586 // and we're ready to send application-level data.
1587 // The logic for this is largely symmetric between client and server.
1589 class states_CONNECTED extends states_State {
1590   async initialize() {
1591     this.conn._setConnectionSuccess();
1592   }
1593   async sendApplicationData(bytes) {
1594     await this.conn._sendApplicationData(bytes);
1595   }
1596   async recvApplicationData(bytes) {
1597     return bytes;
1598   }
1599   async recvChangeCipherSpec(bytes) {
1600     throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1601   }
1604 // A base class for states that occur in the middle of the handshake
1605 // (that is, between ClientHello and Finished).  These states may receive
1606 // CHANGE_CIPHER_SPEC records for b/w compat reasons, which must contain
1607 // exactly a single 0x01 byte and must otherwise be ignored.
1609 class states_MidHandshakeState extends states_State {
1610   async recvChangeCipherSpec(bytes) {
1611     if (this.conn._hasSeenChangeCipherSpec) {
1612       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1613     }
1614     if (bytes.byteLength !== 1 || bytes[0] !== 1) {
1615       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1616     }
1617     this.conn._hasSeenChangeCipherSpec = true;
1618   }
1621 // These states implement (part of) the client state-machine from
1622 // https://tools.ietf.org/html/rfc8446#appendix-A.1
1624 // Since we're only implementing a small subset of TLS1.3,
1625 // we only need a small subset of the handshake.  It basically goes:
1627 //   * send ClientHello
1628 //   * receive ServerHello
1629 //   * receive EncryptedExtensions
1630 //   * receive server Finished
1631 //   * send client Finished
1633 // We include some unused states for completeness, so that it's easier
1634 // to check the implementation against the diagrams in the RFC.
1636 class states_CLIENT_START extends states_State {
1637   async initialize() {
1638     const keyschedule = this.conn._keyschedule;
1639     await keyschedule.addPSK(this.conn.psk);
1640     // Construct a ClientHello message with our single PSK.
1641     // We can't know the PSK binder value yet, so we initially write zeros.
1642     const clientHello = new messages_ClientHello(
1643       // Client random salt.
1644       await getRandomBytes(32),
1645       // Random legacy_session_id; we *could* send an empty string here,
1646       // but sending a random one makes it easier to be compatible with
1647       // the data emitted by tlslite-ng for test-case generation.
1648       await getRandomBytes(32),
1649       [
1650         new extensions_SupportedVersionsExtension([VERSION_TLS_1_3]),
1651         new extensions_PskKeyExchangeModesExtension([PSK_MODE_KE]),
1652         new extensions_PreSharedKeyExtension([this.conn.pskId], [zeros(HASH_LENGTH)]),
1653       ],
1654     );
1655     const buf = new utils_BufferWriter();
1656     clientHello.write(buf);
1657     // Now that we know what the ClientHello looks like,
1658     // go back and calculate the appropriate PSK binder value.
1659     // We only support a single PSK, so the length of the binders field is the
1660     // length of the hash plus one for rendering it as a variable-length byte array,
1661     // plus two for rendering the variable-length list of PSK binders.
1662     const PSK_BINDERS_SIZE = HASH_LENGTH + 1 + 2;
1663     const truncatedTranscript = buf.slice(0, buf.tell() - PSK_BINDERS_SIZE);
1664     const pskBinder = await keyschedule.calculateFinishedMAC(keyschedule.extBinderKey, truncatedTranscript);
1665     buf.incr(-HASH_LENGTH);
1666     buf.writeBytes(pskBinder);
1667     await this.conn._sendHandshakeMessageBytes(buf.flush());
1668     await this.conn._transition(states_CLIENT_WAIT_SH, clientHello.sessionId);
1669   }
1672 class states_CLIENT_WAIT_SH extends states_State {
1673   async initialize(sessionId) {
1674     this._sessionId = sessionId;
1675   }
1676   async recvHandshakeMessage(msg) {
1677     if (! (msg instanceof messages_ServerHello)) {
1678       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1679     }
1680     if (! bytesAreEqual(msg.sessionId, this._sessionId)) {
1681       throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1682     }
1683     const pskExt = msg.extensions.get(EXTENSION_TYPE.PRE_SHARED_KEY);
1684     if (! pskExt) {
1685       throw new TLSError(ALERT_DESCRIPTION.MISSING_EXTENSION);
1686     }
1687     // We expect only the SUPPORTED_VERSIONS and PRE_SHARED_KEY extensions.
1688     if (msg.extensions.size !== 2) {
1689       throw new TLSError(ALERT_DESCRIPTION.UNSUPPORTED_EXTENSION);
1690     }
1691     if (pskExt.selectedIdentity !== 0) {
1692       throw new TLSError(ALERT_DESCRIPTION.ILLEGAL_PARAMETER);
1693     }
1694     await this.conn._keyschedule.addECDHE(null);
1695     await this.conn._setSendKey(this.conn._keyschedule.clientHandshakeTrafficSecret);
1696     await this.conn._setRecvKey(this.conn._keyschedule.serverHandshakeTrafficSecret);
1697     await this.conn._transition(states_CLIENT_WAIT_EE);
1698   }
1701 class states_CLIENT_WAIT_EE extends states_MidHandshakeState {
1702   async recvHandshakeMessage(msg) {
1703     // We don't make use of any encrypted extensions, but we still
1704     // have to wait for the server to send the (empty) list of them.
1705     if (! (msg instanceof EncryptedExtensions)) {
1706       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1707     }
1708     // We do not support any EncryptedExtensions.
1709     if (msg.extensions.size !== 0) {
1710       throw new TLSError(ALERT_DESCRIPTION.UNSUPPORTED_EXTENSION);
1711     }
1712     const keyschedule = this.conn._keyschedule;
1713     const serverFinishedTranscript = keyschedule.getTranscript();
1714     await this.conn._transition(states_CLIENT_WAIT_FINISHED, serverFinishedTranscript);
1715   }
1718 class states_CLIENT_WAIT_FINISHED extends states_State {
1719   async initialize(serverFinishedTranscript) {
1720     this._serverFinishedTranscript = serverFinishedTranscript;
1721   }
1722   async recvHandshakeMessage(msg) {
1723     if (! (msg instanceof messages_Finished)) {
1724       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1725     }
1726     // Verify server Finished MAC.
1727     const keyschedule = this.conn._keyschedule;
1728     await keyschedule.verifyFinishedMAC(keyschedule.serverHandshakeTrafficSecret, msg.verifyData, this._serverFinishedTranscript);
1729     // Send our own Finished message in return.
1730     // This must be encrypted with the handshake traffic key,
1731     // but must not appear in the transcript used to calculate the application keys.
1732     const clientFinishedMAC = await keyschedule.calculateFinishedMAC(keyschedule.clientHandshakeTrafficSecret);
1733     await keyschedule.finalize();
1734     await this.conn._sendHandshakeMessage(new messages_Finished(clientFinishedMAC));
1735     await this.conn._setSendKey(keyschedule.clientApplicationTrafficSecret);
1736     await this.conn._setRecvKey(keyschedule.serverApplicationTrafficSecret);
1737     await this.conn._transition(states_CLIENT_CONNECTED);
1738   }
1741 class states_CLIENT_CONNECTED extends states_CONNECTED {
1742   async recvHandshakeMessage(msg) {
1743     // A connected client must be prepared to accept NewSessionTicket
1744     // messages.  We never use them, but other server implementations
1745     // might send them.
1746     if (! (msg instanceof messages_NewSessionTicket)) {
1747       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1748     }
1749   }
1752 // These states implement (part of) the server state-machine from
1753 // https://tools.ietf.org/html/rfc8446#appendix-A.2
1755 // Since we're only implementing a small subset of TLS1.3,
1756 // we only need a small subset of the handshake.  It basically goes:
1758 //   * receive ClientHello
1759 //   * send ServerHello
1760 //   * send empty EncryptedExtensions
1761 //   * send server Finished
1762 //   * receive client Finished
1764 // We include some unused states for completeness, so that it's easier
1765 // to check the implementation against the diagrams in the RFC.
1767 class states_SERVER_START extends states_State {
1768   async recvHandshakeMessage(msg) {
1769     if (! (msg instanceof messages_ClientHello)) {
1770       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1771     }
1772     // In the spec, this is where we select connection parameters, and maybe
1773     // tell the client to try again if we can't find a compatible set.
1774     // Since we only support a fixed cipherset, the only thing to "negotiate"
1775     // is whether they provided an acceptable PSK.
1776     const pskExt = msg.extensions.get(EXTENSION_TYPE.PRE_SHARED_KEY);
1777     const pskModesExt = msg.extensions.get(EXTENSION_TYPE.PSK_KEY_EXCHANGE_MODES);
1778     if (! pskExt || ! pskModesExt) {
1779       throw new TLSError(ALERT_DESCRIPTION.MISSING_EXTENSION);
1780     }
1781     if (pskModesExt.modes.indexOf(PSK_MODE_KE) === -1) {
1782       throw new TLSError(ALERT_DESCRIPTION.HANDSHAKE_FAILURE);
1783     }
1784     const pskIndex = pskExt.identities.findIndex(pskId => bytesAreEqual(pskId, this.conn.pskId));
1785     if (pskIndex === -1) {
1786       throw new TLSError(ALERT_DESCRIPTION.UNKNOWN_PSK_IDENTITY);
1787     }
1788     await this.conn._keyschedule.addPSK(this.conn.psk);
1789     // Validate the PSK binder.
1790     const keyschedule = this.conn._keyschedule;
1791     const transcript = keyschedule.getTranscript();
1792     // Calculate size occupied by the PSK binders.
1793     let pskBindersSize = 2; // Vector16 representation overhead.
1794     for (const binder of pskExt.binders) {
1795       pskBindersSize += binder.byteLength + 1; // Vector8 representation overhead.
1796     }
1797     await keyschedule.verifyFinishedMAC(keyschedule.extBinderKey, pskExt.binders[pskIndex], transcript.slice(0, -pskBindersSize));
1798     await this.conn._transition(states_SERVER_NEGOTIATED, msg.sessionId, pskIndex);
1799   }
1802 class states_SERVER_NEGOTIATED extends states_MidHandshakeState {
1803   async initialize(sessionId, pskIndex) {
1804     await this.conn._sendHandshakeMessage(new messages_ServerHello(
1805       // Server random
1806       await getRandomBytes(32),
1807       sessionId,
1808       [
1809         new extensions_SupportedVersionsExtension(null, VERSION_TLS_1_3),
1810         new extensions_PreSharedKeyExtension(null, null, pskIndex),
1811       ]
1812     ));
1813     // If the client sent a non-empty sessionId, the server *must* send a change-cipher-spec for b/w compat.
1814     if (sessionId.byteLength > 0) {
1815       await this.conn._sendChangeCipherSpec();
1816     }
1817     // We can now transition to the encrypted part of the handshake.
1818     const keyschedule = this.conn._keyschedule;
1819     await keyschedule.addECDHE(null);
1820     await this.conn._setSendKey(keyschedule.serverHandshakeTrafficSecret);
1821     await this.conn._setRecvKey(keyschedule.clientHandshakeTrafficSecret);
1822     // Send an empty EncryptedExtensions message.
1823     await this.conn._sendHandshakeMessage(new EncryptedExtensions([]));
1824     // Send the Finished message.
1825     const serverFinishedMAC = await keyschedule.calculateFinishedMAC(keyschedule.serverHandshakeTrafficSecret);
1826     await this.conn._sendHandshakeMessage(new messages_Finished(serverFinishedMAC));
1827     // We can now *send* using the application traffic key,
1828     // but have to wait to receive the client Finished before receiving under that key.
1829     // We need to remember the handshake state from before the client Finished
1830     // in order to successfully verify the client Finished.
1831     const clientFinishedTranscript = await keyschedule.getTranscript();
1832     const clientHandshakeTrafficSecret = keyschedule.clientHandshakeTrafficSecret;
1833     await keyschedule.finalize();
1834     await this.conn._setSendKey(keyschedule.serverApplicationTrafficSecret);
1835     await this.conn._transition(states_SERVER_WAIT_FINISHED, clientHandshakeTrafficSecret, clientFinishedTranscript);
1836   }
1839 class states_SERVER_WAIT_FINISHED extends states_MidHandshakeState {
1840   async initialize(clientHandshakeTrafficSecret, clientFinishedTranscript) {
1841     this._clientHandshakeTrafficSecret = clientHandshakeTrafficSecret;
1842     this._clientFinishedTranscript = clientFinishedTranscript;
1843   }
1844   async recvHandshakeMessage(msg) {
1845     if (! (msg instanceof messages_Finished)) {
1846       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
1847     }
1848     const keyschedule = this.conn._keyschedule;
1849     await keyschedule.verifyFinishedMAC(this._clientHandshakeTrafficSecret, msg.verifyData, this._clientFinishedTranscript);
1850     this._clientHandshakeTrafficSecret = this._clientFinishedTranscript = null;
1851     await this.conn._setRecvKey(keyschedule.clientApplicationTrafficSecret);
1852     await this.conn._transition(states_CONNECTED);
1853   }
1856 // CONCATENATED MODULE: ./src/keyschedule.js
1857 /* This Source Code Form is subject to the terms of the Mozilla Public
1858  * License, v. 2.0. If a copy of the MPL was not distributed with this
1859  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
1861 // TLS1.3 Key Schedule.
1863 // In this file we implement the "key schedule" from
1864 // https://tools.ietf.org/html/rfc8446#section-7.1, which
1865 // defines how to calculate various keys as the handshake
1866 // state progresses.
1874 // The `KeySchedule` class progresses through three stages corresponding
1875 // to the three phases of the TLS1.3 key schedule:
1877 //   UNINITIALIZED
1878 //       |
1879 //       | addPSK()
1880 //       v
1881 //   EARLY_SECRET
1882 //       |
1883 //       | addECDHE()
1884 //       v
1885 //   HANDSHAKE_SECRET
1886 //       |
1887 //       | finalize()
1888 //       v
1889 //   MASTER_SECRET
1891 // It will error out if the calling code attempts to add key material
1892 // in the wrong order.
1894 const STAGE_UNINITIALIZED = 0;
1895 const STAGE_EARLY_SECRET = 1;
1896 const STAGE_HANDSHAKE_SECRET = 2;
1897 const STAGE_MASTER_SECRET = 3;
1899 class keyschedule_KeySchedule {
1900   constructor() {
1901     this.stage = STAGE_UNINITIALIZED;
1902     // WebCrypto doesn't support a rolling hash construct, so we have to
1903     // keep the entire message transcript in memory.
1904     this.transcript = new utils_BufferWriter();
1905     // This tracks the main secret from with other keys are derived at each stage.
1906     this.secret = null;
1907     // And these are all the various keys we'll derive as the handshake progresses.
1908     this.extBinderKey = null;
1909     this.clientHandshakeTrafficSecret = null;
1910     this.serverHandshakeTrafficSecret = null;
1911     this.clientApplicationTrafficSecret = null;
1912     this.serverApplicationTrafficSecret = null;
1913   }
1915   async addPSK(psk) {
1916     // Use the selected PSK (if any) to calculate the "early secret".
1917     if (psk === null) {
1918       psk = zeros(HASH_LENGTH);
1919     }
1920     if (this.stage !== STAGE_UNINITIALIZED) {
1921       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
1922     }
1923     this.stage = STAGE_EARLY_SECRET;
1924     this.secret = await hkdfExtract(zeros(HASH_LENGTH), psk);
1925     this.extBinderKey = await this.deriveSecret('ext binder', EMPTY);
1926     this.secret = await this.deriveSecret('derived', EMPTY);
1927   }
1929   async addECDHE(ecdhe) {
1930     // Mix in the ECDHE output (if any) to calculate the "handshake secret".
1931     if (ecdhe === null) {
1932       ecdhe = zeros(HASH_LENGTH);
1933     }
1934     if (this.stage !== STAGE_EARLY_SECRET) {
1935       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
1936     }
1937     this.stage = STAGE_HANDSHAKE_SECRET;
1938     this.extBinderKey = null;
1939     this.secret = await hkdfExtract(this.secret, ecdhe);
1940     this.clientHandshakeTrafficSecret = await this.deriveSecret('c hs traffic');
1941     this.serverHandshakeTrafficSecret = await this.deriveSecret('s hs traffic');
1942     this.secret = await this.deriveSecret('derived', EMPTY);
1943   }
1945   async finalize() {
1946     if (this.stage !== STAGE_HANDSHAKE_SECRET) {
1947       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
1948     }
1949     this.stage = STAGE_MASTER_SECRET;
1950     this.clientHandshakeTrafficSecret = null;
1951     this.serverHandshakeTrafficSecret = null;
1952     this.secret = await hkdfExtract(this.secret, zeros(HASH_LENGTH));
1953     this.clientApplicationTrafficSecret = await this.deriveSecret('c ap traffic');
1954     this.serverApplicationTrafficSecret = await this.deriveSecret('s ap traffic');
1955     this.secret = null;
1956   }
1958   addToTranscript(bytes) {
1959     this.transcript.writeBytes(bytes);
1960   }
1962   getTranscript() {
1963     return this.transcript.slice();
1964   }
1966   async deriveSecret(label, transcript = undefined) {
1967     transcript = transcript || this.getTranscript();
1968     return await hkdfExpandLabel(this.secret, label, await hash(transcript), HASH_LENGTH);
1969   }
1971   async calculateFinishedMAC(baseKey, transcript = undefined) {
1972     transcript = transcript || this.getTranscript();
1973     const finishedKey = await hkdfExpandLabel(baseKey, 'finished', EMPTY, HASH_LENGTH);
1974     return await hmac(finishedKey, await hash(transcript));
1975   }
1977   async verifyFinishedMAC(baseKey, mac, transcript = undefined) {
1978     transcript = transcript || this.getTranscript();
1979     const finishedKey = await hkdfExpandLabel(baseKey, 'finished', EMPTY, HASH_LENGTH);
1980     await verifyHmac(finishedKey, mac, await hash(transcript));
1981   }
1984 // CONCATENATED MODULE: ./src/recordlayer.js
1985 /* This Source Code Form is subject to the terms of the Mozilla Public
1986  * License, v. 2.0. If a copy of the MPL was not distributed with this
1987  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
1990 // This file implements the "record layer" for TLS1.3, as defined in
1991 // https://tools.ietf.org/html/rfc8446#section-5.
1993 // The record layer is responsible for encrypting/decrypting bytes to be
1994 // sent over the wire, including stateful management of sequence numbers
1995 // for the incoming and outgoing stream.
1997 // The main interface is the RecordLayer class, which takes a callback function
1998 // sending data and can be used like so:
2000 //    rl = new RecordLayer(async function send_encrypted_data(data) {
2001 //      // application-specific sending logic here.
2002 //    });
2004 //    // Records are sent and received in plaintext by default,
2005 //    // until you specify the key to use.
2006 //    await rl.setSendKey(key)
2008 //    // Send some data by specifying the record type and the bytes.
2009 //    // Where allowed by the record type, it will be buffered until
2010 //    // explicitly flushed, and then sent by calling the callback.
2011 //    await rl.send(RECORD_TYPE.HANDSHAKE, <bytes for a handshake message>)
2012 //    await rl.send(RECORD_TYPE.HANDSHAKE, <bytes for another handshake message>)
2013 //    await rl.flush()
2015 //    // Separate keys are used for sending and receiving.
2016 //    rl.setRecvKey(key);
2018 //    // When data is received, push it into the RecordLayer
2019 //    // and pass a callback that will be called with a [type, bytes]
2020 //    // pair for each message parsed from the data.
2021 //    rl.recv(dataReceivedFromPeer, async (type, bytes) => {
2022 //      switch (type) {
2023 //        case RECORD_TYPE.APPLICATION_DATA:
2024 //          // do something with application data
2025 //        case RECORD_TYPE.HANDSHAKE:
2026 //          // do something with a handshake message
2027 //        default:
2028 //          // etc...
2029 //      }
2030 //    });
2039 /* eslint-disable sorting/sort-object-props */
2040 const RECORD_TYPE = {
2041   CHANGE_CIPHER_SPEC: 20,
2042   ALERT: 21,
2043   HANDSHAKE: 22,
2044   APPLICATION_DATA: 23,
2046 /* eslint-enable sorting/sort-object-props */
2048 // Encrypting at most 2^24 records will force us to stay
2049 // below data limits on AES-GCM encryption key use, and also
2050 // means we can accurately represent the sequence number as
2051 // a javascript double.
2052 const MAX_SEQUENCE_NUMBER = Math.pow(2, 24);
2053 const MAX_RECORD_SIZE = Math.pow(2, 14);
2054 const MAX_ENCRYPTED_RECORD_SIZE = MAX_RECORD_SIZE + 256;
2055 const RECORD_HEADER_SIZE = 5;
2057 // These are some helper classes to manage the encryption/decryption state
2058 // for a particular key.
2060 class recordlayer_CipherState {
2061   constructor(key, iv) {
2062     this.key = key;
2063     this.iv = iv;
2064     this.seqnum = 0;
2065   }
2067   static async create(baseKey, mode) {
2068     // Derive key and iv per https://tools.ietf.org/html/rfc8446#section-7.3
2069     const key = await prepareKey(await hkdfExpandLabel(baseKey, 'key', EMPTY, KEY_LENGTH), mode);
2070     const iv = await hkdfExpandLabel(baseKey, 'iv', EMPTY, IV_LENGTH);
2071     return new this(key, iv);
2072   }
2074   nonce() {
2075     // Ref https://tools.ietf.org/html/rfc8446#section-5.3:
2076     // * left-pad the sequence number with zeros to IV_LENGTH
2077     // * xor with the provided iv
2078     // Our sequence numbers are always less than 2^24, so fit in a Uint32
2079     // in the last 4 bytes of the nonce.
2080     const nonce = this.iv.slice();
2081     const dv = new DataView(nonce.buffer, nonce.byteLength - 4, 4);
2082     dv.setUint32(0, dv.getUint32(0) ^ this.seqnum);
2083     this.seqnum += 1;
2084     if (this.seqnum > MAX_SEQUENCE_NUMBER) {
2085       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
2086     }
2087     return nonce;
2088   }
2091 class recordlayer_EncryptionState extends recordlayer_CipherState {
2092   static async create(key) {
2093     return super.create(key, 'encrypt');
2094   }
2096   async encrypt(plaintext, additionalData) {
2097     return await encrypt(this.key, this.nonce(), plaintext, additionalData);
2098   }
2101 class recordlayer_DecryptionState extends recordlayer_CipherState {
2102   static async create(key) {
2103     return super.create(key, 'decrypt');
2104   }
2106   async decrypt(ciphertext, additionalData) {
2107     return await decrypt(this.key, this.nonce(), ciphertext, additionalData);
2108   }
2111 // The main RecordLayer class.
2113 class recordlayer_RecordLayer {
2114   constructor(sendCallback) {
2115     this.sendCallback = sendCallback;
2116     this._sendEncryptState = null;
2117     this._sendError = null;
2118     this._recvDecryptState = null;
2119     this._recvError = null;
2120     this._pendingRecordType = 0;
2121     this._pendingRecordBuf = null;
2122   }
2124   async setSendKey(key) {
2125     await this.flush();
2126     this._sendEncryptState = await recordlayer_EncryptionState.create(key);
2127   }
2129   async setRecvKey(key) {
2130     this._recvDecryptState = await recordlayer_DecryptionState.create(key);
2131   }
2133   async setSendError(err) {
2134     this._sendError = err;
2135   }
2137   async setRecvError(err) {
2138     this._recvError = err;
2139   }
2141   async send(type, data) {
2142     if (this._sendError !== null) {
2143       throw this._sendError;
2144     }
2145     // Forbid sending data that doesn't fit into a single record.
2146     // We do not support fragmentation over multiple records.
2147     if (data.byteLength > MAX_RECORD_SIZE) {
2148       throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
2149     }
2150     // Flush if we're switching to a different record type.
2151     if (this._pendingRecordType && this._pendingRecordType !== type) {
2152       await this.flush();
2153     }
2154     // Flush if we would overflow the max size of a record.
2155     if (this._pendingRecordBuf !== null) {
2156       if (this._pendingRecordBuf.tell() + data.byteLength > MAX_RECORD_SIZE) {
2157         await this.flush();
2158       }
2159     }
2160     // Start a new pending record if necessary.
2161     // We reserve space at the start of the buffer for the record header,
2162     // which is conveniently always a fixed size.
2163     if (this._pendingRecordBuf === null) {
2164       this._pendingRecordType = type;
2165       this._pendingRecordBuf = new utils_BufferWriter();
2166       this._pendingRecordBuf.incr(RECORD_HEADER_SIZE);
2167     }
2168     this._pendingRecordBuf.writeBytes(data);
2169   }
2171   async flush() {
2172     // If there's nothing to flush, bail out early.
2173     // Don't throw `_sendError` if we're not sending anything, because `flush()`
2174     // can be called when we're trying to transition into an error state.
2175     const buf = this._pendingRecordBuf;
2176     let type = this._pendingRecordType;
2177     if (! type) {
2178       if (buf !== null) {
2179         throw new TLSError(ALERT_DESCRIPTION.INTERNAL_ERROR);
2180       }
2181       return;
2182     }
2183     if (this._sendError !== null) {
2184       throw this._sendError;
2185     }
2186     // If we're encrypting, turn the existing buffer contents into a `TLSInnerPlaintext` by
2187     // appending the type. We don't do any zero-padding, although the spec allows it.
2188     let inflation = 0, innerPlaintext = null;
2189     if (this._sendEncryptState !== null) {
2190       buf.writeUint8(type);
2191       innerPlaintext = buf.slice(RECORD_HEADER_SIZE);
2192       inflation = AEAD_SIZE_INFLATION;
2193       type = RECORD_TYPE.APPLICATION_DATA;
2194     }
2195     // Write the common header for either `TLSPlaintext` or `TLSCiphertext` record.
2196     const length = buf.tell() - RECORD_HEADER_SIZE + inflation;
2197     buf.seek(0);
2198     buf.writeUint8(type);
2199     buf.writeUint16(VERSION_TLS_1_2);
2200     buf.writeUint16(length);
2201     // Followed by different payload depending on encryption status.
2202     if (this._sendEncryptState !== null) {
2203       const additionalData = buf.slice(0, RECORD_HEADER_SIZE);
2204       const ciphertext = await this._sendEncryptState.encrypt(innerPlaintext, additionalData);
2205       buf.writeBytes(ciphertext);
2206     } else {
2207       buf.incr(length);
2208     }
2209     this._pendingRecordBuf = null;
2210     this._pendingRecordType = 0;
2211     await this.sendCallback(buf.flush());
2212   }
2214   async recv(data) {
2215     if (this._recvError !== null) {
2216       throw this._recvError;
2217     }
2218     // For simplicity, we assume that the given data contains exactly one record.
2219     // Peers using this library will send one record at a time over the websocket
2220     // connection, and we can assume that the server-side websocket bridge will split
2221     // up any traffic into individual records if we ever start interoperating with
2222     // peers using a different TLS implementation.
2223     // Similarly, we assume that handshake messages will not be fragmented across
2224     // multiple records. This should be trivially true for the PSK-only mode used
2225     // by this library, but we may want to relax it in future for interoperability
2226     // with e.g. large ClientHello messages that contain lots of different options.
2227     const buf = new utils_BufferReader(data);
2228     // The data to read is either a TLSPlaintext or TLSCiphertext struct,
2229     // depending on whether record protection has been enabled yet:
2230     //
2231     //    struct {
2232     //        ContentType type;
2233     //        ProtocolVersion legacy_record_version;
2234     //        uint16 length;
2235     //        opaque fragment[TLSPlaintext.length];
2236     //    } TLSPlaintext;
2237     //
2238     //    struct {
2239     //        ContentType opaque_type = application_data; /* 23 */
2240     //        ProtocolVersion legacy_record_version = 0x0303; /* TLS v1.2 */
2241     //        uint16 length;
2242     //        opaque encrypted_record[TLSCiphertext.length];
2243     //    } TLSCiphertext;
2244     //
2245     let type = buf.readUint8();
2246     // The spec says legacy_record_version "MUST be ignored for all purposes",
2247     // but we know TLS1.3 implementations will only ever emit two possible values,
2248     // so it seems useful to bail out early if we receive anything else.
2249     const version = buf.readUint16();
2250     if (version !== VERSION_TLS_1_2) {
2251       // TLS1.0 is only acceptable on initial plaintext records.
2252       if (this._recvDecryptState !== null || version !== VERSION_TLS_1_0) {
2253         throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
2254       }
2255     }
2256     const length = buf.readUint16();
2257     let plaintext;
2258     if (this._recvDecryptState === null || type === RECORD_TYPE.CHANGE_CIPHER_SPEC) {
2259       [type, plaintext] = await this._readPlaintextRecord(type, length, buf);
2260     } else {
2261       [type, plaintext] = await this._readEncryptedRecord(type, length, buf);
2262     }
2263     // Sanity-check that we received exactly one record.
2264     if (buf.hasMoreBytes()) {
2265       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
2266     }
2267     return [type, plaintext];
2268   }
2270   // Helper to read an unencrypted `TLSPlaintext` struct
2272   async _readPlaintextRecord(type, length, buf) {
2273     if (length > MAX_RECORD_SIZE) {
2274       throw new TLSError(ALERT_DESCRIPTION.RECORD_OVERFLOW);
2275     }
2276     return [type, buf.readBytes(length)];
2277   }
2279   // Helper to read an encrypted `TLSCiphertext` struct,
2280   // decrypting it into plaintext.
2282   async _readEncryptedRecord(type, length, buf) {
2283     if (length > MAX_ENCRYPTED_RECORD_SIZE) {
2284       throw new TLSError(ALERT_DESCRIPTION.RECORD_OVERFLOW);
2285     }
2286     // The outer type for encrypted records is always APPLICATION_DATA.
2287     if (type !== RECORD_TYPE.APPLICATION_DATA) {
2288       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
2289     }
2290     // Decrypt and decode the contained `TLSInnerPlaintext` struct:
2291     //
2292     //    struct {
2293     //        opaque content[TLSPlaintext.length];
2294     //        ContentType type;
2295     //        uint8 zeros[length_of_padding];
2296     //    } TLSInnerPlaintext;
2297     //
2298     // The additional data for the decryption is the `TLSCiphertext` record
2299     // header, which is a fixed size and immediately prior to current buffer position.
2300     buf.incr(-RECORD_HEADER_SIZE);
2301     const additionalData = buf.readBytes(RECORD_HEADER_SIZE);
2302     const ciphertext = buf.readBytes(length);
2303     const paddedPlaintext = await this._recvDecryptState.decrypt(ciphertext, additionalData);
2304     // We have to scan backwards over the zero padding at the end of the struct
2305     // in order to find the non-zero `type` byte.
2306     let i;
2307     for (i = paddedPlaintext.byteLength - 1; i >= 0; i--) {
2308       if (paddedPlaintext[i] !== 0) {
2309         break;
2310       }
2311     }
2312     if (i < 0) {
2313       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
2314     }
2315     type = paddedPlaintext[i];
2316     // `change_cipher_spec` records must always be plaintext.
2317     if (type === RECORD_TYPE.CHANGE_CIPHER_SPEC) {
2318       throw new TLSError(ALERT_DESCRIPTION.DECODE_ERROR);
2319     }
2320     return [type, paddedPlaintext.slice(0, i)];
2321   }
2324 // CONCATENATED MODULE: ./src/tlsconnection.js
2325 /* This Source Code Form is subject to the terms of the Mozilla Public
2326  * License, v. 2.0. If a copy of the MPL was not distributed with this
2327  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
2329 // The top-level APIs offered by this module are `ClientConnection` and
2330 // `ServerConnection` classes, which provide authenticated and encrypted
2331 // communication via the "externally-provisioned PSK" mode of TLS1.3.
2332 // They each take a callback to be used for sending data to the remote peer,
2333 // and operate like this:
2335 //    conn = await ClientConnection.create(psk, pskId, async function send_data_to_server(data) {
2336 //      // application-specific sending logic here.
2337 //    })
2339 //    // Send data to the server by calling `send`,
2340 //    // which will use the callback provided in the constructor.
2341 //    // A single `send()` by the application may result in multiple
2342 //    // invokations of the callback.
2344 //    await conn.send('application-level data')
2346 //    // When data is received from the server, push it into
2347 //    // the connection and let it return any decrypted app-level data.
2348 //    // There might not be any app-level data if it was a protocol control
2349 //    //  message, and the receipt of the data might trigger additional calls
2350 //    // to the send callback for protocol control purposes.
2352 //    serverSocket.on('data', async encrypted_data => {
2353 //      const plaintext = await conn.recv(data)
2354 //      if (plaintext !== null) {
2355 //        do_something_with_app_level_data(plaintext)
2356 //      }
2357 //    })
2359 //    // It's good practice to explicitly close the connection
2360 //    // when finished.  This will send a "closed" notification
2361 //    // to the server.
2363 //    await conn.close()
2365 //    // When the peer sends a "closed" notification it will show up
2366 //    // as a `TLSCloseNotify` exception from recv:
2368 //    try {
2369 //      data = await conn.recv(data);
2370 //    } catch (err) {
2371 //      if (! (err instanceof TLSCloseNotify) { throw err }
2372 //      do_something_to_cleanly_close_data_connection();
2373 //    }
2375 // The `ServerConnection` API operates similarly; the distinction is mainly
2376 // in which side is expected to send vs receieve during the protocol handshake.
2387 class tlsconnection_Connection {
2388   constructor(psk, pskId, sendCallback) {
2389     this.psk = assertIsBytes(psk);
2390     this.pskId = assertIsBytes(pskId);
2391     this.connected = new Promise((resolve, reject) => {
2392       this._onConnectionSuccess = resolve;
2393       this._onConnectionFailure = reject;
2394     });
2395     this._state = new UNINITIALIZED(this);
2396     this._handshakeRecvBuffer = null;
2397     this._hasSeenChangeCipherSpec = false;
2398     this._recordlayer = new recordlayer_RecordLayer(sendCallback);
2399     this._keyschedule = new keyschedule_KeySchedule();
2400     this._lastPromise = Promise.resolve();
2401   }
2403   // Subclasses will override this with some async initialization logic.
2404   static async create(psk, pskId, sendCallback) {
2405     return new this(psk, pskId, sendCallback);
2406   }
2408   // These are the three public API methods that consumers can use
2409   // to send and receive data encrypted with TLS1.3.
2411   async send(data) {
2412     assertIsBytes(data);
2413     await this.connected;
2414     await this._synchronized(async () => {
2415       await this._state.sendApplicationData(data);
2416     });
2417   }
2419   async recv(data) {
2420     assertIsBytes(data);
2421     return await this._synchronized(async () => {
2422       // Decrypt the data using the record layer.
2423       // We expect to receive precisely one record at a time.
2424       const [type, bytes] = await this._recordlayer.recv(data);
2425       // Dispatch based on the type of the record.
2426       switch (type) {
2427         case RECORD_TYPE.CHANGE_CIPHER_SPEC:
2428           await this._state.recvChangeCipherSpec(bytes);
2429           return null;
2430         case RECORD_TYPE.ALERT:
2431           await this._state.recvAlertMessage(TLSAlert.fromBytes(bytes));
2432           return null;
2433         case RECORD_TYPE.APPLICATION_DATA:
2434           return await this._state.recvApplicationData(bytes);
2435         case RECORD_TYPE.HANDSHAKE:
2436           // Multiple handshake messages may be coalesced into a single record.
2437           // Store the in-progress record buffer on `this` so that we can guard
2438           // against handshake messages that span a change in keys.
2439           this._handshakeRecvBuffer = new utils_BufferReader(bytes);
2440           if (! this._handshakeRecvBuffer.hasMoreBytes()) {
2441             throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
2442           }
2443           do {
2444             // Each handshake messages has a type and length prefix, per
2445             // https://tools.ietf.org/html/rfc8446#appendix-B.3
2446             this._handshakeRecvBuffer.incr(1);
2447             const mlength = this._handshakeRecvBuffer.readUint24();
2448             this._handshakeRecvBuffer.incr(-4);
2449             const messageBytes = this._handshakeRecvBuffer.readBytes(mlength + 4);
2450             this._keyschedule.addToTranscript(messageBytes);
2451             await this._state.recvHandshakeMessage(messages_HandshakeMessage.fromBytes(messageBytes));
2452           } while (this._handshakeRecvBuffer.hasMoreBytes());
2453           this._handshakeRecvBuffer = null;
2454           return null;
2455         default:
2456           throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
2457       }
2458     });
2459   }
2461   async close() {
2462     await this._synchronized(async () => {
2463       await this._state.close();
2464     });
2465   }
2467   // Ensure that async functions execute one at a time,
2468   // by waiting for the previous call to `_synchronized()` to complete
2469   // before starting a new one.  This helps ensure that we complete
2470   // one state-machine transition before starting to do the next.
2471   // It's also a convenient place to catch and alert on errors.
2473   _synchronized(cb) {
2474     const nextPromise = this._lastPromise.then(() => {
2475       return cb();
2476     }).catch(async err => {
2477       if (err instanceof TLSCloseNotify) {
2478         throw err;
2479       }
2480       await this._state.handleErrorAndRethrow(err);
2481     });
2482     // We don't want to hold on to the return value or error,
2483     // just synchronize on the fact that it completed.
2484     this._lastPromise = nextPromise.then(noop, noop);
2485     return nextPromise;
2486   }
2488   // This drives internal transition of the state-machine,
2489   // ensuring that the new state is properly initialized.
2491   async _transition(State, ...args) {
2492     this._state = new State(this);
2493     await this._state.initialize(...args);
2494     await this._recordlayer.flush();
2495   }
2497   // These are helpers to allow the State to manipulate the recordlayer
2498   // and send out various types of data.
2500   async _sendApplicationData(bytes) {
2501     await this._recordlayer.send(RECORD_TYPE.APPLICATION_DATA, bytes);
2502     await this._recordlayer.flush();
2503   }
2505   async _sendHandshakeMessage(msg) {
2506     await this._sendHandshakeMessageBytes(msg.toBytes());
2507   }
2509   async _sendHandshakeMessageBytes(bytes) {
2510     this._keyschedule.addToTranscript(bytes);
2511     await this._recordlayer.send(RECORD_TYPE.HANDSHAKE, bytes);
2512     // Don't flush after each handshake message, since we can probably
2513     // coalesce multiple messages into a single record.
2514   }
2516   async _sendAlertMessage(err) {
2517     await this._recordlayer.send(RECORD_TYPE.ALERT, err.toBytes());
2518     await this._recordlayer.flush();
2519   }
2521   async _sendChangeCipherSpec() {
2522     await this._recordlayer.send(RECORD_TYPE.CHANGE_CIPHER_SPEC, new Uint8Array([0x01]));
2523     await this._recordlayer.flush();
2524   }
2526   async _setSendKey(key) {
2527     return await this._recordlayer.setSendKey(key);
2528   }
2530   async _setRecvKey(key) {
2531     // Handshake messages that change keys must be on a record boundary.
2532     if (this._handshakeRecvBuffer && this._handshakeRecvBuffer.hasMoreBytes()) {
2533       throw new TLSError(ALERT_DESCRIPTION.UNEXPECTED_MESSAGE);
2534     }
2535     return await this._recordlayer.setRecvKey(key);
2536   }
2538   _setConnectionSuccess() {
2539     if (this._onConnectionSuccess !== null) {
2540       this._onConnectionSuccess();
2541       this._onConnectionSuccess = null;
2542       this._onConnectionFailure = null;
2543     }
2544   }
2546   _setConnectionFailure(err) {
2547     if (this._onConnectionFailure !== null) {
2548       this._onConnectionFailure(err);
2549       this._onConnectionSuccess = null;
2550       this._onConnectionFailure = null;
2551     }
2552   }
2554   _closeForSend(alert) {
2555     this._recordlayer.setSendError(alert);
2556   }
2558   _closeForRecv(alert) {
2559     this._recordlayer.setRecvError(alert);
2560   }
2563 class tlsconnection_ClientConnection extends tlsconnection_Connection {
2564   static async create(psk, pskId, sendCallback) {
2565     const instance = await super.create(psk, pskId, sendCallback);
2566     await instance._transition(states_CLIENT_START);
2567     return instance;
2568   }
2571 class tlsconnection_ServerConnection extends tlsconnection_Connection {
2572   static async create(psk, pskId, sendCallback) {
2573     const instance = await super.create(psk, pskId, sendCallback);
2574     await instance._transition(states_SERVER_START);
2575     return instance;
2576   }
2579 // CONCATENATED MODULE: ./node_modules/event-target-shim/dist/event-target-shim.mjs
2581  * @author Toru Nagashima <https://github.com/mysticatea>
2582  * @copyright 2015 Toru Nagashima. All rights reserved.
2583  * See LICENSE file in root directory for full license.
2584  */
2586  * @typedef {object} PrivateData
2587  * @property {EventTarget} eventTarget The event target.
2588  * @property {{type:string}} event The original event object.
2589  * @property {number} eventPhase The current event phase.
2590  * @property {EventTarget|null} currentTarget The current event target.
2591  * @property {boolean} canceled The flag to prevent default.
2592  * @property {boolean} stopped The flag to stop propagation.
2593  * @property {boolean} immediateStopped The flag to stop propagation immediately.
2594  * @property {Function|null} passiveListener The listener if the current listener is passive. Otherwise this is null.
2595  * @property {number} timeStamp The unix time.
2596  * @private
2597  */
2600  * Private data for event wrappers.
2601  * @type {WeakMap<Event, PrivateData>}
2602  * @private
2603  */
2604 const privateData = new WeakMap();
2607  * Cache for wrapper classes.
2608  * @type {WeakMap<Object, Function>}
2609  * @private
2610  */
2611 const wrappers = new WeakMap();
2614  * Get private data.
2615  * @param {Event} event The event object to get private data.
2616  * @returns {PrivateData} The private data of the event.
2617  * @private
2618  */
2619 function pd(event) {
2620     const retv = privateData.get(event);
2621     console.assert(
2622         retv != null,
2623         "'this' is expected an Event object, but got",
2624         event
2625     );
2626     return retv
2630  * https://dom.spec.whatwg.org/#set-the-canceled-flag
2631  * @param data {PrivateData} private data.
2632  */
2633 function setCancelFlag(data) {
2634     if (data.passiveListener != null) {
2635         if (
2636             typeof console !== "undefined" &&
2637             typeof console.error === "function"
2638         ) {
2639             console.error(
2640                 "Unable to preventDefault inside passive event listener invocation.",
2641                 data.passiveListener
2642             );
2643         }
2644         return
2645     }
2646     if (!data.event.cancelable) {
2647         return
2648     }
2650     data.canceled = true;
2651     if (typeof data.event.preventDefault === "function") {
2652         data.event.preventDefault();
2653     }
2657  * @see https://dom.spec.whatwg.org/#interface-event
2658  * @private
2659  */
2661  * The event wrapper.
2662  * @constructor
2663  * @param {EventTarget} eventTarget The event target of this dispatching.
2664  * @param {Event|{type:string}} event The original event to wrap.
2665  */
2666 function Event(eventTarget, event) {
2667     privateData.set(this, {
2668         eventTarget,
2669         event,
2670         eventPhase: 2,
2671         currentTarget: eventTarget,
2672         canceled: false,
2673         stopped: false,
2674         immediateStopped: false,
2675         passiveListener: null,
2676         timeStamp: event.timeStamp || Date.now(),
2677     });
2679     // https://heycam.github.io/webidl/#Unforgeable
2680     Object.defineProperty(this, "isTrusted", { value: false, enumerable: true });
2682     // Define accessors
2683     const keys = Object.keys(event);
2684     for (let i = 0; i < keys.length; ++i) {
2685         const key = keys[i];
2686         if (!(key in this)) {
2687             Object.defineProperty(this, key, defineRedirectDescriptor(key));
2688         }
2689     }
2692 // Should be enumerable, but class methods are not enumerable.
2693 Event.prototype = {
2694     /**
2695      * The type of this event.
2696      * @type {string}
2697      */
2698     get type() {
2699         return pd(this).event.type
2700     },
2702     /**
2703      * The target of this event.
2704      * @type {EventTarget}
2705      */
2706     get target() {
2707         return pd(this).eventTarget
2708     },
2710     /**
2711      * The target of this event.
2712      * @type {EventTarget}
2713      */
2714     get currentTarget() {
2715         return pd(this).currentTarget
2716     },
2718     /**
2719      * @returns {EventTarget[]} The composed path of this event.
2720      */
2721     composedPath() {
2722         const currentTarget = pd(this).currentTarget;
2723         if (currentTarget == null) {
2724             return []
2725         }
2726         return [currentTarget]
2727     },
2729     /**
2730      * Constant of NONE.
2731      * @type {number}
2732      */
2733     get NONE() {
2734         return 0
2735     },
2737     /**
2738      * Constant of CAPTURING_PHASE.
2739      * @type {number}
2740      */
2741     get CAPTURING_PHASE() {
2742         return 1
2743     },
2745     /**
2746      * Constant of AT_TARGET.
2747      * @type {number}
2748      */
2749     get AT_TARGET() {
2750         return 2
2751     },
2753     /**
2754      * Constant of BUBBLING_PHASE.
2755      * @type {number}
2756      */
2757     get BUBBLING_PHASE() {
2758         return 3
2759     },
2761     /**
2762      * The target of this event.
2763      * @type {number}
2764      */
2765     get eventPhase() {
2766         return pd(this).eventPhase
2767     },
2769     /**
2770      * Stop event bubbling.
2771      * @returns {void}
2772      */
2773     stopPropagation() {
2774         const data = pd(this);
2776         data.stopped = true;
2777         if (typeof data.event.stopPropagation === "function") {
2778             data.event.stopPropagation();
2779         }
2780     },
2782     /**
2783      * Stop event bubbling.
2784      * @returns {void}
2785      */
2786     stopImmediatePropagation() {
2787         const data = pd(this);
2789         data.stopped = true;
2790         data.immediateStopped = true;
2791         if (typeof data.event.stopImmediatePropagation === "function") {
2792             data.event.stopImmediatePropagation();
2793         }
2794     },
2796     /**
2797      * The flag to be bubbling.
2798      * @type {boolean}
2799      */
2800     get bubbles() {
2801         return Boolean(pd(this).event.bubbles)
2802     },
2804     /**
2805      * The flag to be cancelable.
2806      * @type {boolean}
2807      */
2808     get cancelable() {
2809         return Boolean(pd(this).event.cancelable)
2810     },
2812     /**
2813      * Cancel this event.
2814      * @returns {void}
2815      */
2816     preventDefault() {
2817         setCancelFlag(pd(this));
2818     },
2820     /**
2821      * The flag to indicate cancellation state.
2822      * @type {boolean}
2823      */
2824     get defaultPrevented() {
2825         return pd(this).canceled
2826     },
2828     /**
2829      * The flag to be composed.
2830      * @type {boolean}
2831      */
2832     get composed() {
2833         return Boolean(pd(this).event.composed)
2834     },
2836     /**
2837      * The unix time of this event.
2838      * @type {number}
2839      */
2840     get timeStamp() {
2841         return pd(this).timeStamp
2842     },
2844     /**
2845      * The target of this event.
2846      * @type {EventTarget}
2847      * @deprecated
2848      */
2849     get srcElement() {
2850         return pd(this).eventTarget
2851     },
2853     /**
2854      * The flag to stop event bubbling.
2855      * @type {boolean}
2856      * @deprecated
2857      */
2858     get cancelBubble() {
2859         return pd(this).stopped
2860     },
2861     set cancelBubble(value) {
2862         if (!value) {
2863             return
2864         }
2865         const data = pd(this);
2867         data.stopped = true;
2868         if (typeof data.event.cancelBubble === "boolean") {
2869             data.event.cancelBubble = true;
2870         }
2871     },
2873     /**
2874      * The flag to indicate cancellation state.
2875      * @type {boolean}
2876      * @deprecated
2877      */
2878     get returnValue() {
2879         return !pd(this).canceled
2880     },
2881     set returnValue(value) {
2882         if (!value) {
2883             setCancelFlag(pd(this));
2884         }
2885     },
2887     /**
2888      * Initialize this event object. But do nothing under event dispatching.
2889      * @param {string} type The event type.
2890      * @param {boolean} [bubbles=false] The flag to be possible to bubble up.
2891      * @param {boolean} [cancelable=false] The flag to be possible to cancel.
2892      * @deprecated
2893      */
2894     initEvent() {
2895         // Do nothing.
2896     },
2899 // `constructor` is not enumerable.
2900 Object.defineProperty(Event.prototype, "constructor", {
2901     value: Event,
2902     configurable: true,
2903     writable: true,
2906 // Ensure `event instanceof window.Event` is `true`.
2907 if (typeof window !== "undefined" && typeof window.Event !== "undefined") {
2908     Object.setPrototypeOf(Event.prototype, window.Event.prototype);
2910     // Make association for wrappers.
2911     wrappers.set(window.Event.prototype, Event);
2915  * Get the property descriptor to redirect a given property.
2916  * @param {string} key Property name to define property descriptor.
2917  * @returns {PropertyDescriptor} The property descriptor to redirect the property.
2918  * @private
2919  */
2920 function defineRedirectDescriptor(key) {
2921     return {
2922         get() {
2923             return pd(this).event[key]
2924         },
2925         set(value) {
2926             pd(this).event[key] = value;
2927         },
2928         configurable: true,
2929         enumerable: true,
2930     }
2934  * Get the property descriptor to call a given method property.
2935  * @param {string} key Property name to define property descriptor.
2936  * @returns {PropertyDescriptor} The property descriptor to call the method property.
2937  * @private
2938  */
2939 function defineCallDescriptor(key) {
2940     return {
2941         value() {
2942             const event = pd(this).event;
2943             return event[key].apply(event, arguments)
2944         },
2945         configurable: true,
2946         enumerable: true,
2947     }
2951  * Define new wrapper class.
2952  * @param {Function} BaseEvent The base wrapper class.
2953  * @param {Object} proto The prototype of the original event.
2954  * @returns {Function} The defined wrapper class.
2955  * @private
2956  */
2957 function defineWrapper(BaseEvent, proto) {
2958     const keys = Object.keys(proto);
2959     if (keys.length === 0) {
2960         return BaseEvent
2961     }
2963     /** CustomEvent */
2964     function CustomEvent(eventTarget, event) {
2965         BaseEvent.call(this, eventTarget, event);
2966     }
2968     CustomEvent.prototype = Object.create(BaseEvent.prototype, {
2969         constructor: { value: CustomEvent, configurable: true, writable: true },
2970     });
2972     // Define accessors.
2973     for (let i = 0; i < keys.length; ++i) {
2974         const key = keys[i];
2975         if (!(key in BaseEvent.prototype)) {
2976             const descriptor = Object.getOwnPropertyDescriptor(proto, key);
2977             const isFunc = typeof descriptor.value === "function";
2978             Object.defineProperty(
2979                 CustomEvent.prototype,
2980                 key,
2981                 isFunc
2982                     ? defineCallDescriptor(key)
2983                     : defineRedirectDescriptor(key)
2984             );
2985         }
2986     }
2988     return CustomEvent
2992  * Get the wrapper class of a given prototype.
2993  * @param {Object} proto The prototype of the original event to get its wrapper.
2994  * @returns {Function} The wrapper class.
2995  * @private
2996  */
2997 function getWrapper(proto) {
2998     if (proto == null || proto === Object.prototype) {
2999         return Event
3000     }
3002     let wrapper = wrappers.get(proto);
3003     if (wrapper == null) {
3004         wrapper = defineWrapper(getWrapper(Object.getPrototypeOf(proto)), proto);
3005         wrappers.set(proto, wrapper);
3006     }
3007     return wrapper
3011  * Wrap a given event to management a dispatching.
3012  * @param {EventTarget} eventTarget The event target of this dispatching.
3013  * @param {Object} event The event to wrap.
3014  * @returns {Event} The wrapper instance.
3015  * @private
3016  */
3017 function wrapEvent(eventTarget, event) {
3018     const Wrapper = getWrapper(Object.getPrototypeOf(event));
3019     return new Wrapper(eventTarget, event)
3023  * Get the immediateStopped flag of a given event.
3024  * @param {Event} event The event to get.
3025  * @returns {boolean} The flag to stop propagation immediately.
3026  * @private
3027  */
3028 function isStopped(event) {
3029     return pd(event).immediateStopped
3033  * Set the current event phase of a given event.
3034  * @param {Event} event The event to set current target.
3035  * @param {number} eventPhase New event phase.
3036  * @returns {void}
3037  * @private
3038  */
3039 function setEventPhase(event, eventPhase) {
3040     pd(event).eventPhase = eventPhase;
3044  * Set the current target of a given event.
3045  * @param {Event} event The event to set current target.
3046  * @param {EventTarget|null} currentTarget New current target.
3047  * @returns {void}
3048  * @private
3049  */
3050 function setCurrentTarget(event, currentTarget) {
3051     pd(event).currentTarget = currentTarget;
3055  * Set a passive listener of a given event.
3056  * @param {Event} event The event to set current target.
3057  * @param {Function|null} passiveListener New passive listener.
3058  * @returns {void}
3059  * @private
3060  */
3061 function setPassiveListener(event, passiveListener) {
3062     pd(event).passiveListener = passiveListener;
3066  * @typedef {object} ListenerNode
3067  * @property {Function} listener
3068  * @property {1|2|3} listenerType
3069  * @property {boolean} passive
3070  * @property {boolean} once
3071  * @property {ListenerNode|null} next
3072  * @private
3073  */
3076  * @type {WeakMap<object, Map<string, ListenerNode>>}
3077  * @private
3078  */
3079 const listenersMap = new WeakMap();
3081 // Listener types
3082 const CAPTURE = 1;
3083 const BUBBLE = 2;
3084 const ATTRIBUTE = 3;
3087  * Check whether a given value is an object or not.
3088  * @param {any} x The value to check.
3089  * @returns {boolean} `true` if the value is an object.
3090  */
3091 function isObject(x) {
3092     return x !== null && typeof x === "object" //eslint-disable-line no-restricted-syntax
3096  * Get listeners.
3097  * @param {EventTarget} eventTarget The event target to get.
3098  * @returns {Map<string, ListenerNode>} The listeners.
3099  * @private
3100  */
3101 function getListeners(eventTarget) {
3102     const listeners = listenersMap.get(eventTarget);
3103     if (listeners == null) {
3104         throw new TypeError(
3105             "'this' is expected an EventTarget object, but got another value."
3106         )
3107     }
3108     return listeners
3112  * Get the property descriptor for the event attribute of a given event.
3113  * @param {string} eventName The event name to get property descriptor.
3114  * @returns {PropertyDescriptor} The property descriptor.
3115  * @private
3116  */
3117 function defineEventAttributeDescriptor(eventName) {
3118     return {
3119         get() {
3120             const listeners = getListeners(this);
3121             let node = listeners.get(eventName);
3122             while (node != null) {
3123                 if (node.listenerType === ATTRIBUTE) {
3124                     return node.listener
3125                 }
3126                 node = node.next;
3127             }
3128             return null
3129         },
3131         set(listener) {
3132             if (typeof listener !== "function" && !isObject(listener)) {
3133                 listener = null; // eslint-disable-line no-param-reassign
3134             }
3135             const listeners = getListeners(this);
3137             // Traverse to the tail while removing old value.
3138             let prev = null;
3139             let node = listeners.get(eventName);
3140             while (node != null) {
3141                 if (node.listenerType === ATTRIBUTE) {
3142                     // Remove old value.
3143                     if (prev !== null) {
3144                         prev.next = node.next;
3145                     } else if (node.next !== null) {
3146                         listeners.set(eventName, node.next);
3147                     } else {
3148                         listeners.delete(eventName);
3149                     }
3150                 } else {
3151                     prev = node;
3152                 }
3154                 node = node.next;
3155             }
3157             // Add new value.
3158             if (listener !== null) {
3159                 const newNode = {
3160                     listener,
3161                     listenerType: ATTRIBUTE,
3162                     passive: false,
3163                     once: false,
3164                     next: null,
3165                 };
3166                 if (prev === null) {
3167                     listeners.set(eventName, newNode);
3168                 } else {
3169                     prev.next = newNode;
3170                 }
3171             }
3172         },
3173         configurable: true,
3174         enumerable: true,
3175     }
3179  * Define an event attribute (e.g. `eventTarget.onclick`).
3180  * @param {Object} eventTargetPrototype The event target prototype to define an event attrbite.
3181  * @param {string} eventName The event name to define.
3182  * @returns {void}
3183  */
3184 function defineEventAttribute(eventTargetPrototype, eventName) {
3185     Object.defineProperty(
3186         eventTargetPrototype,
3187         `on${eventName}`,
3188         defineEventAttributeDescriptor(eventName)
3189     );
3193  * Define a custom EventTarget with event attributes.
3194  * @param {string[]} eventNames Event names for event attributes.
3195  * @returns {EventTarget} The custom EventTarget.
3196  * @private
3197  */
3198 function defineCustomEventTarget(eventNames) {
3199     /** CustomEventTarget */
3200     function CustomEventTarget() {
3201         EventTarget.call(this);
3202     }
3204     CustomEventTarget.prototype = Object.create(EventTarget.prototype, {
3205         constructor: {
3206             value: CustomEventTarget,
3207             configurable: true,
3208             writable: true,
3209         },
3210     });
3212     for (let i = 0; i < eventNames.length; ++i) {
3213         defineEventAttribute(CustomEventTarget.prototype, eventNames[i]);
3214     }
3216     return CustomEventTarget
3220  * EventTarget.
3222  * - This is constructor if no arguments.
3223  * - This is a function which returns a CustomEventTarget constructor if there are arguments.
3225  * For example:
3227  *     class A extends EventTarget {}
3228  *     class B extends EventTarget("message") {}
3229  *     class C extends EventTarget("message", "error") {}
3230  *     class D extends EventTarget(["message", "error"]) {}
3231  */
3232 function EventTarget() {
3233     /*eslint-disable consistent-return */
3234     if (this instanceof EventTarget) {
3235         listenersMap.set(this, new Map());
3236         return
3237     }
3238     if (arguments.length === 1 && Array.isArray(arguments[0])) {
3239         return defineCustomEventTarget(arguments[0])
3240     }
3241     if (arguments.length > 0) {
3242         const types = new Array(arguments.length);
3243         for (let i = 0; i < arguments.length; ++i) {
3244             types[i] = arguments[i];
3245         }
3246         return defineCustomEventTarget(types)
3247     }
3248     throw new TypeError("Cannot call a class as a function")
3249     /*eslint-enable consistent-return */
3252 // Should be enumerable, but class methods are not enumerable.
3253 EventTarget.prototype = {
3254     /**
3255      * Add a given listener to this event target.
3256      * @param {string} eventName The event name to add.
3257      * @param {Function} listener The listener to add.
3258      * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.
3259      * @returns {void}
3260      */
3261     addEventListener(eventName, listener, options) {
3262         if (listener == null) {
3263             return
3264         }
3265         if (typeof listener !== "function" && !isObject(listener)) {
3266             throw new TypeError("'listener' should be a function or an object.")
3267         }
3269         const listeners = getListeners(this);
3270         const optionsIsObj = isObject(options);
3271         const capture = optionsIsObj
3272             ? Boolean(options.capture)
3273             : Boolean(options);
3274         const listenerType = capture ? CAPTURE : BUBBLE;
3275         const newNode = {
3276             listener,
3277             listenerType,
3278             passive: optionsIsObj && Boolean(options.passive),
3279             once: optionsIsObj && Boolean(options.once),
3280             next: null,
3281         };
3283         // Set it as the first node if the first node is null.
3284         let node = listeners.get(eventName);
3285         if (node === undefined) {
3286             listeners.set(eventName, newNode);
3287             return
3288         }
3290         // Traverse to the tail while checking duplication..
3291         let prev = null;
3292         while (node != null) {
3293             if (
3294                 node.listener === listener &&
3295                 node.listenerType === listenerType
3296             ) {
3297                 // Should ignore duplication.
3298                 return
3299             }
3300             prev = node;
3301             node = node.next;
3302         }
3304         // Add it.
3305         prev.next = newNode;
3306     },
3308     /**
3309      * Remove a given listener from this event target.
3310      * @param {string} eventName The event name to remove.
3311      * @param {Function} listener The listener to remove.
3312      * @param {boolean|{capture?:boolean,passive?:boolean,once?:boolean}} [options] The options for this listener.
3313      * @returns {void}
3314      */
3315     removeEventListener(eventName, listener, options) {
3316         if (listener == null) {
3317             return
3318         }
3320         const listeners = getListeners(this);
3321         const capture = isObject(options)
3322             ? Boolean(options.capture)
3323             : Boolean(options);
3324         const listenerType = capture ? CAPTURE : BUBBLE;
3326         let prev = null;
3327         let node = listeners.get(eventName);
3328         while (node != null) {
3329             if (
3330                 node.listener === listener &&
3331                 node.listenerType === listenerType
3332             ) {
3333                 if (prev !== null) {
3334                     prev.next = node.next;
3335                 } else if (node.next !== null) {
3336                     listeners.set(eventName, node.next);
3337                 } else {
3338                     listeners.delete(eventName);
3339                 }
3340                 return
3341             }
3343             prev = node;
3344             node = node.next;
3345         }
3346     },
3348     /**
3349      * Dispatch a given event.
3350      * @param {Event|{type:string}} event The event to dispatch.
3351      * @returns {boolean} `false` if canceled.
3352      */
3353     dispatchEvent(event) {
3354         if (event == null || typeof event.type !== "string") {
3355             throw new TypeError('"event.type" should be a string.')
3356         }
3358         // If listeners aren't registered, terminate.
3359         const listeners = getListeners(this);
3360         const eventName = event.type;
3361         let node = listeners.get(eventName);
3362         if (node == null) {
3363             return true
3364         }
3366         // Since we cannot rewrite several properties, so wrap object.
3367         const wrappedEvent = wrapEvent(this, event);
3369         // This doesn't process capturing phase and bubbling phase.
3370         // This isn't participating in a tree.
3371         let prev = null;
3372         while (node != null) {
3373             // Remove this listener if it's once
3374             if (node.once) {
3375                 if (prev !== null) {
3376                     prev.next = node.next;
3377                 } else if (node.next !== null) {
3378                     listeners.set(eventName, node.next);
3379                 } else {
3380                     listeners.delete(eventName);
3381                 }
3382             } else {
3383                 prev = node;
3384             }
3386             // Call this listener
3387             setPassiveListener(
3388                 wrappedEvent,
3389                 node.passive ? node.listener : null
3390             );
3391             if (typeof node.listener === "function") {
3392                 try {
3393                     node.listener.call(this, wrappedEvent);
3394                 } catch (err) {
3395                     if (
3396                         typeof console !== "undefined" &&
3397                         typeof console.error === "function"
3398                     ) {
3399                         console.error(err);
3400                     }
3401                 }
3402             } else if (
3403                 node.listenerType !== ATTRIBUTE &&
3404                 typeof node.listener.handleEvent === "function"
3405             ) {
3406                 node.listener.handleEvent(wrappedEvent);
3407             }
3409             // Break if `event.stopImmediatePropagation` was called.
3410             if (isStopped(wrappedEvent)) {
3411                 break
3412             }
3414             node = node.next;
3415         }
3416         setPassiveListener(wrappedEvent, null);
3417         setEventPhase(wrappedEvent, 0);
3418         setCurrentTarget(wrappedEvent, null);
3420         return !wrappedEvent.defaultPrevented
3421     },
3424 // `constructor` is not enumerable.
3425 Object.defineProperty(EventTarget.prototype, "constructor", {
3426     value: EventTarget,
3427     configurable: true,
3428     writable: true,
3431 // Ensure `eventTarget instanceof window.EventTarget` is `true`.
3432 if (
3433     typeof window !== "undefined" &&
3434     typeof window.EventTarget !== "undefined"
3435 ) {
3436     Object.setPrototypeOf(EventTarget.prototype, window.EventTarget.prototype);
3439 /* harmony default export */ var event_target_shim = (EventTarget);
3442 // CONCATENATED MODULE: ./src/index.js
3443 /* This Source Code Form is subject to the terms of the Mozilla Public
3444  * License, v. 2.0. If a copy of the MPL was not distributed with this
3445  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
3447 // A wrapper that combines a WebSocket to the channelserver
3448 // with some client-side encryption for securing the channel.
3450 // This code is responsible for the event handling and the consumer API.
3451 // All the details of encrypting the messages are delegated to`./tlsconnection.js`.
3459 const CLOSE_FLUSH_BUFFER_INTERVAL_MS = 200;
3460 const CLOSE_FLUSH_BUFFER_MAX_TRIES = 5;
3462 class src_PairingChannel extends EventTarget {
3463   constructor(channelId, channelKey, socket, connection) {
3464     super();
3465     this._channelId = channelId;
3466     this._channelKey = channelKey;
3467     this._socket = socket;
3468     this._connection = connection;
3469     this._selfClosed = false;
3470     this._peerClosed = false;
3471     this._setupListeners();
3472   }
3474   /**
3475    * Create a new pairing channel.
3476    *
3477    * This will open a channel on the channelserver, and generate a random client-side
3478    * encryption key. When the promise resolves, `this.channelId` and `this.channelKey`
3479    * can be transferred to another client to allow it to securely connect to the channel.
3480    *
3481    * @returns Promise<PairingChannel>
3482    */
3483   static create(channelServerURI) {
3484     const wsURI = new URL('/v1/ws/', channelServerURI).href;
3485     const channelKey = crypto.getRandomValues(new Uint8Array(32));
3486     // The one who creates the channel plays the role of 'server' in the underlying TLS exchange.
3487     return this._makePairingChannel(wsURI, tlsconnection_ServerConnection, channelKey);
3488   }
3490   /**
3491    * Connect to an existing pairing channel.
3492    *
3493    * This will connect to a channel on the channelserver previously established by
3494    * another client calling `create`. The `channelId` and `channelKey` must have been
3495    * obtained via some out-of-band mechanism (such as by scanning from a QR code).
3496    *
3497    * @returns Promise<PairingChannel>
3498    */
3499   static connect(channelServerURI, channelId, channelKey) {
3500     const wsURI = new URL(`/v1/ws/${channelId}`, channelServerURI).href;
3501     // The one who connects to an existing channel plays the role of 'client'
3502     // in the underlying TLS exchange.
3503     return this._makePairingChannel(wsURI, tlsconnection_ClientConnection, channelKey);
3504   }
3506   static _makePairingChannel(wsUri, ConnectionClass, psk) {
3507     const socket = new WebSocket(wsUri);
3508     return new Promise((resolve, reject) => {
3509       // eslint-disable-next-line prefer-const
3510       let stopListening;
3511       const onConnectionError = async () => {
3512         stopListening();
3513         reject(new Error('Error while creating the pairing channel'));
3514       };
3515       const onFirstMessage = async event => {
3516         stopListening();
3517         try {
3518           // The channelserver echos back the channel id, and we use it as an
3519           // additional input to the TLS handshake via the "psk id" field.
3520           const {channelid: channelId} = JSON.parse(event.data);
3521           const pskId = utf8ToBytes(channelId);
3522           const connection = await ConnectionClass.create(psk, pskId, data => {
3523             // Send data by forwarding it via the channelserver websocket.
3524             // The TLS connection gives us `data` as raw bytes, but channelserver
3525             // expects b64urlsafe strings, because it wraps them in a JSON object envelope.
3526             socket.send(bytesToBase64url(data));
3527           });
3528           const instance = new this(channelId, psk, socket, connection);
3529           resolve(instance);
3530         } catch (err) {
3531           reject(err);
3532         }
3533       };
3534       stopListening = () => {
3535         socket.removeEventListener('close', onConnectionError);
3536         socket.removeEventListener('error', onConnectionError);
3537         socket.removeEventListener('message', onFirstMessage);
3538       };
3539       socket.addEventListener('close', onConnectionError);
3540       socket.addEventListener('error', onConnectionError);
3541       socket.addEventListener('message', onFirstMessage);
3542     });
3543   }
3545   _setupListeners() {
3546     this._socket.addEventListener('message', async event => {
3547       try {
3548         // When we receive data from the channelserver, pump it through the TLS connection
3549         // to decrypt it, then echo it back out to consumers as an event.
3550         const channelServerEnvelope = JSON.parse(event.data);
3551         const payload = await this._connection.recv(base64urlToBytes(channelServerEnvelope.message));
3552         if (payload !== null) {
3553           const data = JSON.parse(bytesToUtf8(payload));
3554           this.dispatchEvent(new CustomEvent('message', {
3555             detail: {
3556               data,
3557               sender: channelServerEnvelope.sender,
3558             },
3559           }));
3560         }
3561       } catch (error) {
3562         let event;
3563         // The underlying TLS connection will signal a clean shutdown of the channel
3564         // by throwing a special error, because it doesn't really have a better
3565         // signally mechanism available.
3566         if (error instanceof TLSCloseNotify) {
3567           this._peerClosed = true;
3568           if (this._selfClosed) {
3569             this._shutdown();
3570           }
3571           event = new CustomEvent('close');
3572         } else {
3573           event = new CustomEvent('error', {
3574             detail: {
3575               error,
3576             }
3577           });
3578         }
3579         this.dispatchEvent(event);
3580       }
3581     });
3582     // Relay the WebSocket events.
3583     this._socket.addEventListener('error', () => {
3584       this._shutdown();
3585       // The dispatched event that we receive has no useful information.
3586       this.dispatchEvent(new CustomEvent('error', {
3587         detail: {
3588           error: new Error('WebSocket error.'),
3589         },
3590       }));
3591     });
3592     // In TLS, the peer has to explicitly send a close notification,
3593     // which we dispatch above.  Unexpected socket close is an error.
3594     this._socket.addEventListener('close', () => {
3595       this._shutdown();
3596       if (! this._peerClosed) {
3597         this.dispatchEvent(new CustomEvent('error', {
3598           detail: {
3599             error: new Error('WebSocket unexpectedly closed'),
3600           }
3601         }));
3602       }
3603     });
3604   }
3606   /**
3607    * @param {Object} data
3608    */
3609   async send(data) {
3610     const payload = utf8ToBytes(JSON.stringify(data));
3611     await this._connection.send(payload);
3612   }
3614   async close() {
3615     this._selfClosed = true;
3616     await this._connection.close();
3617     try {
3618       // Ensure all queued bytes have been sent before closing the connection.
3619       let tries = 0;
3620       while (this._socket.bufferedAmount > 0) {
3621         if (++tries > CLOSE_FLUSH_BUFFER_MAX_TRIES) {
3622           throw new Error('Could not flush the outgoing buffer in time.');
3623         }
3624         await new Promise(res => setTimeout(res, CLOSE_FLUSH_BUFFER_INTERVAL_MS));
3625       }
3626     } finally {
3627       // If the peer hasn't closed, we might still receive some data.
3628       if (this._peerClosed) {
3629         this._shutdown();
3630       }
3631     }
3632   }
3634   _shutdown() {
3635     if (this._socket) {
3636       this._socket.close();
3637       this._socket = null;
3638       this._connection = null;
3639     }
3640   }
3642   get closed() {
3643     return (! this._socket) || (this._socket.readyState === 3);
3644   }
3646   get channelId() {
3647     return this._channelId;
3648   }
3650   get channelKey() {
3651     return this._channelKey;
3652   }
3655 // Re-export helpful utilities for calling code to use.
3658 // For running tests using the built bundle,
3659 // expose a bunch of implementation details.
3667 const _internals = {
3668   arrayToBytes: arrayToBytes,
3669   BufferReader: utils_BufferReader,
3670   BufferWriter: utils_BufferWriter,
3671   bytesAreEqual: bytesAreEqual,
3672   bytesToHex: bytesToHex,
3673   bytesToUtf8: bytesToUtf8,
3674   ClientConnection: tlsconnection_ClientConnection,
3675   Connection: tlsconnection_Connection,
3676   DecryptionState: recordlayer_DecryptionState,
3677   EncryptedExtensions: EncryptedExtensions,
3678   EncryptionState: recordlayer_EncryptionState,
3679   Finished: messages_Finished,
3680   HASH_LENGTH: HASH_LENGTH,
3681   hexToBytes: hexToBytes,
3682   hkdfExpand: hkdfExpand,
3683   KeySchedule: keyschedule_KeySchedule,
3684   NewSessionTicket: messages_NewSessionTicket,
3685   RecordLayer: recordlayer_RecordLayer,
3686   ServerConnection: tlsconnection_ServerConnection,
3687   utf8ToBytes: utf8ToBytes,
3688   zeros: zeros,
3692 /***/ })
3693 /******/ ])["PairingChannel"];