tor-browser

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

DistributionPoint.ts (10341B)


      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 } from "./GeneralName";
      6 import { DistributionPointName, DistributionPointNameJson } from "./IssuingDistributionPoint";
      7 import { PkiObject, PkiObjectParameters } from "./PkiObject";
      8 import { RelativeDistinguishedNames } from "./RelativeDistinguishedNames";
      9 import * as Schema from "./Schema";
     10 
     11 const DISTRIBUTION_POINT = "distributionPoint";
     12 const DISTRIBUTION_POINT_NAMES = "distributionPointNames";
     13 const REASONS = "reasons";
     14 const CRL_ISSUER = "cRLIssuer";
     15 const CRL_ISSUER_NAMES = "cRLIssuerNames";
     16 const CLEAR_PROPS = [
     17  DISTRIBUTION_POINT,
     18  DISTRIBUTION_POINT_NAMES,
     19  REASONS,
     20  CRL_ISSUER,
     21  CRL_ISSUER_NAMES,
     22 ];
     23 
     24 export interface IDistributionPoint {
     25  distributionPoint?: DistributionPointName;
     26  reasons?: asn1js.BitString;
     27  cRLIssuer?: GeneralName[];
     28 }
     29 
     30 export interface DistributionPointJson {
     31  distributionPoint?: DistributionPointNameJson;
     32  reasons?: asn1js.BitStringJson;
     33  cRLIssuer?: GeneralNameJson[];
     34 }
     35 
     36 export type DistributionPointParameters = PkiObjectParameters & Partial<IDistributionPoint>;
     37 
     38 /**
     39 * Represents the DistributionPoint structure described in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)
     40 */
     41 export class DistributionPoint extends PkiObject implements IDistributionPoint {
     42 
     43  public static override CLASS_NAME = "DistributionPoint";
     44 
     45  public distributionPoint?: DistributionPointName;
     46  public reasons?: asn1js.BitString;
     47  public cRLIssuer?: GeneralName[];
     48 
     49  /**
     50   * Initializes a new instance of the {@link DistributionPoint} class
     51   * @param parameters Initialization parameters
     52   */
     53  constructor(parameters: DistributionPointParameters = {}) {
     54    super();
     55 
     56    if (DISTRIBUTION_POINT in parameters) {
     57      this.distributionPoint = pvutils.getParametersValue(parameters, DISTRIBUTION_POINT, DistributionPoint.defaultValues(DISTRIBUTION_POINT));
     58    }
     59    if (REASONS in parameters) {
     60      this.reasons = pvutils.getParametersValue(parameters, REASONS, DistributionPoint.defaultValues(REASONS));
     61    }
     62    if (CRL_ISSUER in parameters) {
     63      this.cRLIssuer = pvutils.getParametersValue(parameters, CRL_ISSUER, DistributionPoint.defaultValues(CRL_ISSUER));
     64    }
     65 
     66    if (parameters.schema) {
     67      this.fromSchema(parameters.schema);
     68    }
     69  }
     70 
     71  /**
     72   * Returns default values for all class members
     73   * @param memberName String name for a class member
     74   * @returns Default value
     75   */
     76  public static override defaultValues(memberName: typeof DISTRIBUTION_POINT): DistributionPointName;
     77  public static override defaultValues(memberName: typeof REASONS): asn1js.BitString;
     78  public static override defaultValues(memberName: typeof CRL_ISSUER): GeneralName[];
     79  public static override defaultValues(memberName: string): any {
     80    switch (memberName) {
     81      case DISTRIBUTION_POINT:
     82        return [];
     83      case REASONS:
     84        return new asn1js.BitString();
     85      case CRL_ISSUER:
     86        return [];
     87      default:
     88        return super.defaultValues(memberName);
     89    }
     90  }
     91 
     92  /**
     93   * @inheritdoc
     94   * @asn ASN.1 schema
     95   * ```asn
     96   * DistributionPoint ::= SEQUENCE {
     97   *    distributionPoint       [0]     DistributionPointName OPTIONAL,
     98   *    reasons                 [1]     ReasonFlags OPTIONAL,
     99   *    cRLIssuer               [2]     GeneralNames OPTIONAL }
    100   *
    101   * DistributionPointName ::= CHOICE {
    102   *    fullName                [0]     GeneralNames,
    103   *    nameRelativeToCRLIssuer [1]     RelativeDistinguishedName }
    104   *
    105   * ReasonFlags ::= BIT STRING {
    106   *    unused                  (0),
    107   *    keyCompromise           (1),
    108   *    cACompromise            (2),
    109   *    affiliationChanged      (3),
    110   *    superseded              (4),
    111   *    cessationOfOperation    (5),
    112   *    certificateHold         (6),
    113   *    privilegeWithdrawn      (7),
    114   *    aACompromise            (8) }
    115   *```
    116   */
    117  public static override schema(parameters: Schema.SchemaParameters<{
    118    distributionPoint?: string;
    119    distributionPointNames?: string;
    120    reasons?: string;
    121    cRLIssuer?: string;
    122    cRLIssuerNames?: string;
    123  }> = {}): Schema.SchemaType {
    124    /**
    125     * @type {Object}
    126     * @property {string} [blockName]
    127     * @property {string} [distributionPoint]
    128     * @property {string} [distributionPointNames]
    129     * @property {string} [reasons]
    130     * @property {string} [cRLIssuer]
    131     * @property {string} [cRLIssuerNames]
    132     */
    133    const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
    134 
    135    return (new asn1js.Sequence({
    136      name: (names.blockName || EMPTY_STRING),
    137      value: [
    138        new asn1js.Constructed({
    139          optional: true,
    140          idBlock: {
    141            tagClass: 3, // CONTEXT-SPECIFIC
    142            tagNumber: 0 // [0]
    143          },
    144          value: [
    145            new asn1js.Choice({
    146              value: [
    147                new asn1js.Constructed({
    148                  name: (names.distributionPoint || EMPTY_STRING),
    149                  optional: true,
    150                  idBlock: {
    151                    tagClass: 3, // CONTEXT-SPECIFIC
    152                    tagNumber: 0 // [0]
    153                  },
    154                  value: [
    155                    new asn1js.Repeated({
    156                      name: (names.distributionPointNames || EMPTY_STRING),
    157                      value: GeneralName.schema()
    158                    })
    159                  ]
    160                }),
    161                new asn1js.Constructed({
    162                  name: (names.distributionPoint || EMPTY_STRING),
    163                  optional: true,
    164                  idBlock: {
    165                    tagClass: 3, // CONTEXT-SPECIFIC
    166                    tagNumber: 1 // [1]
    167                  },
    168                  value: RelativeDistinguishedNames.schema().valueBlock.value
    169                })
    170              ]
    171            })
    172          ]
    173        }),
    174        new asn1js.Primitive({
    175          name: (names.reasons || EMPTY_STRING),
    176          optional: true,
    177          idBlock: {
    178            tagClass: 3, // CONTEXT-SPECIFIC
    179            tagNumber: 1 // [1]
    180          }
    181        }), // IMPLICIT BitString value
    182        new asn1js.Constructed({
    183          name: (names.cRLIssuer || EMPTY_STRING),
    184          optional: true,
    185          idBlock: {
    186            tagClass: 3, // CONTEXT-SPECIFIC
    187            tagNumber: 2 // [2]
    188          },
    189          value: [
    190            new asn1js.Repeated({
    191              name: (names.cRLIssuerNames || EMPTY_STRING),
    192              value: GeneralName.schema()
    193            })
    194          ]
    195        }) // IMPLICIT BitString value
    196      ]
    197    }));
    198  }
    199 
    200  public fromSchema(schema: Schema.SchemaType): void {
    201    // Clear input data first
    202    pvutils.clearProps(schema, CLEAR_PROPS);
    203 
    204    // Check the schema is valid
    205    const asn1 = asn1js.compareSchema(schema,
    206      schema,
    207      DistributionPoint.schema({
    208        names: {
    209          distributionPoint: DISTRIBUTION_POINT,
    210          distributionPointNames: DISTRIBUTION_POINT_NAMES,
    211          reasons: REASONS,
    212          cRLIssuer: CRL_ISSUER,
    213          cRLIssuerNames: CRL_ISSUER_NAMES
    214        }
    215      })
    216    );
    217    AsnError.assertSchema(asn1, this.className);
    218 
    219    //#region Get internal properties from parsed schema
    220    if (DISTRIBUTION_POINT in asn1.result) {
    221      if (asn1.result.distributionPoint.idBlock.tagNumber === 0) { // GENERAL_NAMES variant
    222        this.distributionPoint = Array.from(asn1.result.distributionPointNames, element => new GeneralName({ schema: element }));
    223      }
    224 
    225      if (asn1.result.distributionPoint.idBlock.tagNumber === 1) {// RDN variant
    226        this.distributionPoint = new RelativeDistinguishedNames({
    227          schema: new asn1js.Sequence({
    228            value: asn1.result.distributionPoint.valueBlock.value
    229          })
    230        });
    231      }
    232    }
    233 
    234    if (REASONS in asn1.result) {
    235      this.reasons = new asn1js.BitString({ valueHex: asn1.result.reasons.valueBlock.valueHex });
    236    }
    237 
    238    if (CRL_ISSUER in asn1.result) {
    239      this.cRLIssuer = Array.from(asn1.result.cRLIssuerNames, element => new GeneralName({ schema: element }));
    240    }
    241    //#endregion
    242  }
    243 
    244  public toSchema(): asn1js.Sequence {
    245    //#region Create array for output sequence
    246    const outputArray = [];
    247 
    248    if (this.distributionPoint) {
    249      let internalValue;
    250 
    251      if (this.distributionPoint instanceof Array) {
    252        internalValue = new asn1js.Constructed({
    253          idBlock: {
    254            tagClass: 3, // CONTEXT-SPECIFIC
    255            tagNumber: 0 // [0]
    256          },
    257          value: Array.from(this.distributionPoint, o => o.toSchema())
    258        });
    259      } else {
    260        internalValue = new asn1js.Constructed({
    261          idBlock: {
    262            tagClass: 3, // CONTEXT-SPECIFIC
    263            tagNumber: 1 // [1]
    264          },
    265          value: [this.distributionPoint.toSchema()]
    266        });
    267      }
    268 
    269      outputArray.push(new asn1js.Constructed({
    270        idBlock: {
    271          tagClass: 3, // CONTEXT-SPECIFIC
    272          tagNumber: 0 // [0]
    273        },
    274        value: [internalValue]
    275      }));
    276    }
    277 
    278    if (this.reasons) {
    279      outputArray.push(new asn1js.Primitive({
    280        idBlock: {
    281          tagClass: 3, // CONTEXT-SPECIFIC
    282          tagNumber: 1 // [1]
    283        },
    284        valueHex: this.reasons.valueBlock.valueHexView
    285      }));
    286    }
    287 
    288    if (this.cRLIssuer) {
    289      outputArray.push(new asn1js.Constructed({
    290        idBlock: {
    291          tagClass: 3, // CONTEXT-SPECIFIC
    292          tagNumber: 2 // [2]
    293        },
    294        value: Array.from(this.cRLIssuer, o => o.toSchema())
    295      }));
    296    }
    297    //#endregion
    298 
    299    //#region Construct and return new ASN.1 schema for this object
    300    return (new asn1js.Sequence({
    301      value: outputArray
    302    }));
    303    //#endregion
    304  }
    305 
    306  public toJSON(): DistributionPointJson {
    307    const object: DistributionPointJson = {};
    308 
    309    if (this.distributionPoint) {
    310      if (this.distributionPoint instanceof Array) {
    311        object.distributionPoint = Array.from(this.distributionPoint, o => o.toJSON());
    312      } else {
    313        object.distributionPoint = this.distributionPoint.toJSON();
    314      }
    315    }
    316 
    317    if (this.reasons) {
    318      object.reasons = this.reasons.toJSON();
    319    }
    320 
    321    if (this.cRLIssuer) {
    322      object.cRLIssuer = Array.from(this.cRLIssuer, o => o.toJSON());
    323    }
    324 
    325    return object;
    326  }
    327 
    328 }