tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HPKEConfigManager.sys.mjs (2333B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
      3 * You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 let knownConfigs = new Map();
      6 
      7 export class HPKEConfigManager {
      8  /**
      9   * Decodes a base64url-encoded key string.
     10   *
     11   * @param {string} aBase64Key
     12   * @returns {Uint8Array}
     13   */
     14  static decodeKey(aBase64Key) {
     15    return new Uint8Array(
     16      ChromeUtils.base64URLDecode(aBase64Key, { padding: "ignore" })
     17    );
     18  }
     19 
     20  static async get(aURL, aOptions = {}) {
     21    // If we're in a child, forward to the parent.
     22    let { remoteType } = Services.appinfo;
     23    if (remoteType) {
     24      if (remoteType != "privilegedabout") {
     25        // The remoteTypes definition in the actor definition will enforce
     26        // that calling getActor fails, this is a more readable error:
     27        throw new Error(
     28          "HPKEConfigManager cannot be used outside of the privilegedabout process."
     29        );
     30      }
     31      let actor = ChromeUtils.domProcessChild.getActor("HPKEConfigManager");
     32      return actor.sendQuery("getconfig", { url: aURL, options: aOptions });
     33    }
     34    try {
     35      let config = await this.#getInternal(aURL, aOptions);
     36      return new Uint8Array(config);
     37    } catch (ex) {
     38      console.error(ex);
     39      return null;
     40    }
     41  }
     42 
     43  static async #getInternal(aURL, aOptions = {}) {
     44    let { maxAge = -1 } = aOptions;
     45    let knownConfig = knownConfigs.get(aURL);
     46    if (
     47      knownConfig &&
     48      (maxAge < 0 || Date.now() - knownConfig.fetchDate < maxAge)
     49    ) {
     50      return knownConfig.config;
     51    }
     52    return this.#fetchAndStore(aURL, aOptions);
     53  }
     54 
     55  static async #fetchAndStore(aURL, aOptions = {}) {
     56    let fetchDate = Date.now();
     57    let resp = await fetch(aURL, { signal: aOptions.abortSignal });
     58    if (!resp?.ok) {
     59      throw new Error(
     60        `Fetching HPKE config from ${aURL} failed with error ${resp.status}`
     61      );
     62    }
     63    let config = await resp.blob().then(b => b.arrayBuffer());
     64    knownConfigs.set(aURL, { config, fetchDate });
     65    return config;
     66  }
     67 }
     68 
     69 export class HPKEConfigManagerParent extends JSProcessActorParent {
     70  receiveMessage(msg) {
     71    if (msg.name == "getconfig") {
     72      return HPKEConfigManager.get(msg.data.url, msg.data.options);
     73    }
     74    return null;
     75  }
     76 }