tor-browser

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

GeneralSubtree.ts (6659B)


      1 import * as asn1js from "asn1js";
      2 import * as pvutils from "pvutils";
      3 import { EMPTY_STRING } from "./constants";
      4 import { AsnError } from "./errors";
      5 import { GeneralName, GeneralNameJson, GeneralNameSchema } from "./GeneralName";
      6 import { PkiObject, PkiObjectParameters } from "./PkiObject";
      7 import * as Schema from "./Schema";
      8 
      9 const BASE = "base";
     10 const MINIMUM = "minimum";
     11 const MAXIMUM = "maximum";
     12 const CLEAR_PROPS = [
     13  BASE,
     14  MINIMUM,
     15  MAXIMUM
     16 ];
     17 
     18 export interface IGeneralSubtree {
     19  base: GeneralName;
     20  minimum: number | asn1js.Integer;
     21  maximum?: number | asn1js.Integer;
     22 }
     23 
     24 export interface GeneralSubtreeJson {
     25  base: GeneralNameJson;
     26  minimum?: number | asn1js.IntegerJson;
     27  maximum?: number | asn1js.IntegerJson;
     28 }
     29 
     30 export type GeneralSubtreeParameters = PkiObjectParameters & Partial<IGeneralSubtree>;
     31 
     32 /**
     33 * Represents the GeneralSubtree structure described in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)
     34 */
     35 export class GeneralSubtree extends PkiObject implements IGeneralSubtree {
     36 
     37  public static override CLASS_NAME = "GeneralSubtree";
     38 
     39  public base!: GeneralName;
     40  public minimum!: number | asn1js.Integer;
     41  public maximum?: number | asn1js.Integer;
     42 
     43  /**
     44   * Initializes a new instance of the {@link GeneralSubtree} class
     45   * @param parameters Initialization parameters
     46   */
     47  constructor(parameters: GeneralSubtreeParameters = {}) {
     48    super();
     49 
     50    this.base = pvutils.getParametersValue(parameters, BASE, GeneralSubtree.defaultValues(BASE));
     51    this.minimum = pvutils.getParametersValue(parameters, MINIMUM, GeneralSubtree.defaultValues(MINIMUM));
     52    if (MAXIMUM in parameters) {
     53      this.maximum = pvutils.getParametersValue(parameters, MAXIMUM, GeneralSubtree.defaultValues(MAXIMUM));
     54    }
     55 
     56    if (parameters.schema) {
     57      this.fromSchema(parameters.schema);
     58    }
     59  }
     60 
     61  /**
     62   * Returns default values for all class members
     63   * @param memberName String name for a class member
     64   * @returns Default value
     65   */
     66  public static override defaultValues(memberName: typeof BASE): GeneralName;
     67  public static override defaultValues(memberName: typeof MINIMUM): number;
     68  public static override defaultValues(memberName: typeof MAXIMUM): number;
     69  public static override defaultValues(memberName: string): any {
     70    switch (memberName) {
     71      case BASE:
     72        return new GeneralName();
     73      case MINIMUM:
     74        return 0;
     75      case MAXIMUM:
     76        return 0;
     77      default:
     78        return super.defaultValues(memberName);
     79    }
     80  }
     81 
     82  /**
     83   * @inheritdoc
     84   * @asn ASN.1 schema
     85   * ```asn
     86   * GeneralSubtree ::= SEQUENCE {
     87   *    base                    GeneralName,
     88   *    minimum         [0]     BaseDistance DEFAULT 0,
     89   *    maximum         [1]     BaseDistance OPTIONAL }
     90   *
     91   * BaseDistance ::= INTEGER (0..MAX)
     92   *```
     93   */
     94  public static override schema(parameters: Schema.SchemaParameters<{
     95    base?: GeneralNameSchema;
     96    minimum?: string;
     97    maximum?: string;
     98  }> = {}): Schema.SchemaType {
     99    const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
    100 
    101    return (new asn1js.Sequence({
    102      name: (names.blockName || EMPTY_STRING),
    103      value: [
    104        GeneralName.schema(names.base || {}),
    105        new asn1js.Constructed({
    106          optional: true,
    107          idBlock: {
    108            tagClass: 3, // CONTEXT-SPECIFIC
    109            tagNumber: 0 // [0]
    110          },
    111          value: [new asn1js.Integer({ name: (names.minimum || EMPTY_STRING) })]
    112        }),
    113        new asn1js.Constructed({
    114          optional: true,
    115          idBlock: {
    116            tagClass: 3, // CONTEXT-SPECIFIC
    117            tagNumber: 1 // [1]
    118          },
    119          value: [new asn1js.Integer({ name: (names.maximum || EMPTY_STRING) })]
    120        })
    121      ]
    122    }));
    123  }
    124 
    125  public fromSchema(schema: Schema.SchemaType): void {
    126    // Clear input data first
    127    pvutils.clearProps(schema, CLEAR_PROPS);
    128 
    129    // Check the schema is valid
    130    const asn1 = asn1js.compareSchema(schema,
    131      schema,
    132      GeneralSubtree.schema({
    133        names: {
    134          base: {
    135            names: {
    136              blockName: BASE
    137            }
    138          },
    139          minimum: MINIMUM,
    140          maximum: MAXIMUM
    141        }
    142      })
    143    );
    144    AsnError.assertSchema(asn1, this.className);
    145 
    146    // Get internal properties from parsed schema
    147    this.base = new GeneralName({ schema: asn1.result.base });
    148 
    149    if (MINIMUM in asn1.result) {
    150      if (asn1.result.minimum.valueBlock.isHexOnly)
    151        this.minimum = asn1.result.minimum;
    152      else
    153        this.minimum = asn1.result.minimum.valueBlock.valueDec;
    154    }
    155 
    156    if (MAXIMUM in asn1.result) {
    157      if (asn1.result.maximum.valueBlock.isHexOnly)
    158        this.maximum = asn1.result.maximum;
    159      else
    160        this.maximum = asn1.result.maximum.valueBlock.valueDec;
    161    }
    162  }
    163 
    164  public toSchema(): asn1js.Sequence {
    165    //#region Create array for output sequence
    166    const outputArray = [];
    167 
    168    outputArray.push(this.base.toSchema());
    169 
    170    if (this.minimum !== 0) {
    171      let valueMinimum: number | asn1js.Integer = 0;
    172 
    173      if (this.minimum instanceof asn1js.Integer) {
    174        valueMinimum = this.minimum;
    175      } else {
    176        valueMinimum = new asn1js.Integer({ value: this.minimum });
    177      }
    178 
    179      outputArray.push(new asn1js.Constructed({
    180        optional: true,
    181        idBlock: {
    182          tagClass: 3, // CONTEXT-SPECIFIC
    183          tagNumber: 0 // [0]
    184        },
    185        value: [valueMinimum]
    186      }));
    187    }
    188 
    189    if (MAXIMUM in this) {
    190      let valueMaximum: number | asn1js.Integer = 0;
    191 
    192      if (this.maximum instanceof asn1js.Integer) {
    193        valueMaximum = this.maximum;
    194      } else {
    195        valueMaximum = new asn1js.Integer({ value: this.maximum });
    196      }
    197 
    198      outputArray.push(new asn1js.Constructed({
    199        optional: true,
    200        idBlock: {
    201          tagClass: 3, // CONTEXT-SPECIFIC
    202          tagNumber: 1 // [1]
    203        },
    204        value: [valueMaximum]
    205      }));
    206    }
    207    //#endregion
    208 
    209    //#region Construct and return new ASN.1 schema for this object
    210    return (new asn1js.Sequence({
    211      value: outputArray
    212    }));
    213    //#endregion
    214  }
    215 
    216  public toJSON(): GeneralSubtreeJson {
    217    const res: GeneralSubtreeJson = {
    218      base: this.base.toJSON()
    219    };
    220 
    221    if (this.minimum !== 0) {
    222      if (typeof this.minimum === "number") {
    223        res.minimum = this.minimum;
    224      } else {
    225        res.minimum = this.minimum.toJSON();
    226      }
    227    }
    228 
    229    if (this.maximum !== undefined) {
    230      if (typeof this.maximum === "number") {
    231        res.maximum = this.maximum;
    232      } else {
    233        res.maximum = this.maximum.toJSON();
    234      }
    235    }
    236 
    237    return res;
    238  }
    239 
    240 }