tor-browser

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

IssuingDistributionPoint.ts (15117B)


      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 { PkiObject, PkiObjectParameters } from "./PkiObject";
      7 import { RelativeDistinguishedNames, RelativeDistinguishedNamesJson } from "./RelativeDistinguishedNames";
      8 import * as Schema from "./Schema";
      9 
     10 const DISTRIBUTION_POINT = "distributionPoint";
     11 const DISTRIBUTION_POINT_NAMES = "distributionPointNames";
     12 const ONLY_CONTAINS_USER_CERTS = "onlyContainsUserCerts";
     13 const ONLY_CONTAINS_CA_CERTS = "onlyContainsCACerts";
     14 const ONLY_SOME_REASON = "onlySomeReasons";
     15 const INDIRECT_CRL = "indirectCRL";
     16 const ONLY_CONTAINS_ATTRIBUTE_CERTS = "onlyContainsAttributeCerts";
     17 const CLEAR_PROPS = [
     18  DISTRIBUTION_POINT,
     19  DISTRIBUTION_POINT_NAMES,
     20  ONLY_CONTAINS_USER_CERTS,
     21  ONLY_CONTAINS_CA_CERTS,
     22  ONLY_SOME_REASON,
     23  INDIRECT_CRL,
     24  ONLY_CONTAINS_ATTRIBUTE_CERTS,
     25 ];
     26 
     27 export interface IIssuingDistributionPoint {
     28  distributionPoint?: DistributionPointName;
     29  onlyContainsUserCerts: boolean;
     30  onlyContainsCACerts: boolean;
     31  onlySomeReasons?: number;
     32  indirectCRL: boolean;
     33  onlyContainsAttributeCerts: boolean;
     34 }
     35 
     36 export interface IssuingDistributionPointJson {
     37  distributionPoint?: DistributionPointNameJson;
     38  onlyContainsUserCerts?: boolean;
     39  onlyContainsCACerts?: boolean;
     40  onlySomeReasons?: number;
     41  indirectCRL?: boolean;
     42  onlyContainsAttributeCerts?: boolean;
     43 }
     44 
     45 export type DistributionPointName = GeneralName[] | RelativeDistinguishedNames;
     46 export type DistributionPointNameJson = GeneralNameJson[] | RelativeDistinguishedNamesJson;
     47 
     48 export type IssuingDistributionPointParameters = PkiObjectParameters & Partial<IIssuingDistributionPoint>;
     49 
     50 /**
     51 * Represents the IssuingDistributionPoint structure described in [RFC5280](https://datatracker.ietf.org/doc/html/rfc5280)
     52 */
     53 export class IssuingDistributionPoint extends PkiObject implements IIssuingDistributionPoint {
     54 
     55  public static override CLASS_NAME = "IssuingDistributionPoint";
     56 
     57  public distributionPoint?: DistributionPointName;
     58  public onlyContainsUserCerts!: boolean;
     59  public onlyContainsCACerts!: boolean;
     60  public onlySomeReasons?: number;
     61  public indirectCRL!: boolean;
     62  public onlyContainsAttributeCerts!: boolean;
     63 
     64  /**
     65   * Initializes a new instance of the {@link IssuingDistributionPoint} class
     66   * @param parameters Initialization parameters
     67   */
     68  constructor(parameters: IssuingDistributionPointParameters = {}) {
     69    super();
     70 
     71    if (DISTRIBUTION_POINT in parameters) {
     72      this.distributionPoint = pvutils.getParametersValue(parameters, DISTRIBUTION_POINT, IssuingDistributionPoint.defaultValues(DISTRIBUTION_POINT));
     73    }
     74 
     75    this.onlyContainsUserCerts = pvutils.getParametersValue(parameters, ONLY_CONTAINS_USER_CERTS, IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_USER_CERTS));
     76    this.onlyContainsCACerts = pvutils.getParametersValue(parameters, ONLY_CONTAINS_CA_CERTS, IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_CA_CERTS));
     77    if (ONLY_SOME_REASON in parameters) {
     78      this.onlySomeReasons = pvutils.getParametersValue(parameters, ONLY_SOME_REASON, IssuingDistributionPoint.defaultValues(ONLY_SOME_REASON));
     79    }
     80    this.indirectCRL = pvutils.getParametersValue(parameters, INDIRECT_CRL, IssuingDistributionPoint.defaultValues(INDIRECT_CRL));
     81    this.onlyContainsAttributeCerts = pvutils.getParametersValue(parameters, ONLY_CONTAINS_ATTRIBUTE_CERTS, IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_ATTRIBUTE_CERTS));
     82 
     83    if (parameters.schema) {
     84      this.fromSchema(parameters.schema);
     85    }
     86  }
     87 
     88  /**
     89   * Returns default values for all class members
     90   * @param memberName String name for a class member
     91   * @returns Default value
     92   */
     93  public static override defaultValues(memberName: typeof DISTRIBUTION_POINT): DistributionPointName;
     94  public static override defaultValues(memberName: typeof ONLY_CONTAINS_USER_CERTS): boolean;
     95  public static override defaultValues(memberName: typeof ONLY_CONTAINS_CA_CERTS): boolean;
     96  public static override defaultValues(memberName: typeof ONLY_SOME_REASON): number;
     97  public static override defaultValues(memberName: typeof INDIRECT_CRL): boolean;
     98  public static override defaultValues(memberName: typeof ONLY_CONTAINS_ATTRIBUTE_CERTS): boolean;
     99  public static override defaultValues(memberName: string): any {
    100    switch (memberName) {
    101      case DISTRIBUTION_POINT:
    102        return [];
    103      case ONLY_CONTAINS_USER_CERTS:
    104        return false;
    105      case ONLY_CONTAINS_CA_CERTS:
    106        return false;
    107      case ONLY_SOME_REASON:
    108        return 0;
    109      case INDIRECT_CRL:
    110        return false;
    111      case ONLY_CONTAINS_ATTRIBUTE_CERTS:
    112        return false;
    113      default:
    114        return super.defaultValues(memberName);
    115    }
    116  }
    117 
    118  /**
    119   * @inheritdoc
    120   * @asn ASN.1 schema
    121   * ```asn
    122   * IssuingDistributionPoint ::= SEQUENCE {
    123   *    distributionPoint          [0] DistributionPointName OPTIONAL,
    124   *    onlyContainsUserCerts      [1] BOOLEAN DEFAULT FALSE,
    125   *    onlyContainsCACerts        [2] BOOLEAN DEFAULT FALSE,
    126   *    onlySomeReasons            [3] ReasonFlags OPTIONAL,
    127   *    indirectCRL                [4] BOOLEAN DEFAULT FALSE,
    128   *    onlyContainsAttributeCerts [5] BOOLEAN DEFAULT FALSE }
    129   *
    130   * ReasonFlags ::= BIT STRING {
    131   *    unused                  (0),
    132   *    keyCompromise           (1),
    133   *    cACompromise            (2),
    134   *    affiliationChanged      (3),
    135   *    superseded              (4),
    136   *    cessationOfOperation    (5),
    137   *    certificateHold         (6),
    138   *    privilegeWithdrawn      (7),
    139   *    aACompromise            (8) }
    140   *```
    141   */
    142  public static override schema(parameters: Schema.SchemaParameters<{
    143    distributionPoint?: string;
    144    distributionPointNames?: string;
    145    onlyContainsUserCerts?: string;
    146    onlyContainsCACerts?: string;
    147    onlySomeReasons?: string;
    148    indirectCRL?: string;
    149    onlyContainsAttributeCerts?: string;
    150  }> = {}): Schema.SchemaType {
    151    const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
    152 
    153    return (new asn1js.Sequence({
    154      name: (names.blockName || EMPTY_STRING),
    155      value: [
    156        new asn1js.Constructed({
    157          optional: true,
    158          idBlock: {
    159            tagClass: 3, // CONTEXT-SPECIFIC
    160            tagNumber: 0 // [0]
    161          },
    162          value: [
    163            new asn1js.Choice({
    164              value: [
    165                new asn1js.Constructed({
    166                  name: (names.distributionPoint || EMPTY_STRING),
    167                  idBlock: {
    168                    tagClass: 3, // CONTEXT-SPECIFIC
    169                    tagNumber: 0 // [0]
    170                  },
    171                  value: [
    172                    new asn1js.Repeated({
    173                      name: (names.distributionPointNames || EMPTY_STRING),
    174                      value: GeneralName.schema()
    175                    })
    176                  ]
    177                }),
    178                new asn1js.Constructed({
    179                  name: (names.distributionPoint || EMPTY_STRING),
    180                  idBlock: {
    181                    tagClass: 3, // CONTEXT-SPECIFIC
    182                    tagNumber: 1 // [1]
    183                  },
    184                  value: RelativeDistinguishedNames.schema().valueBlock.value
    185                })
    186              ]
    187            })
    188          ]
    189        }),
    190        new asn1js.Primitive({
    191          name: (names.onlyContainsUserCerts || EMPTY_STRING),
    192          optional: true,
    193          idBlock: {
    194            tagClass: 3, // CONTEXT-SPECIFIC
    195            tagNumber: 1 // [1]
    196          }
    197        }), // IMPLICIT boolean value
    198        new asn1js.Primitive({
    199          name: (names.onlyContainsCACerts || EMPTY_STRING),
    200          optional: true,
    201          idBlock: {
    202            tagClass: 3, // CONTEXT-SPECIFIC
    203            tagNumber: 2 // [2]
    204          }
    205        }), // IMPLICIT boolean value
    206        new asn1js.Primitive({
    207          name: (names.onlySomeReasons || EMPTY_STRING),
    208          optional: true,
    209          idBlock: {
    210            tagClass: 3, // CONTEXT-SPECIFIC
    211            tagNumber: 3 // [3]
    212          }
    213        }), // IMPLICIT BitString value
    214        new asn1js.Primitive({
    215          name: (names.indirectCRL || EMPTY_STRING),
    216          optional: true,
    217          idBlock: {
    218            tagClass: 3, // CONTEXT-SPECIFIC
    219            tagNumber: 4 // [4]
    220          }
    221        }), // IMPLICIT boolean value
    222        new asn1js.Primitive({
    223          name: (names.onlyContainsAttributeCerts || EMPTY_STRING),
    224          optional: true,
    225          idBlock: {
    226            tagClass: 3, // CONTEXT-SPECIFIC
    227            tagNumber: 5 // [5]
    228          }
    229        }) // IMPLICIT boolean value
    230      ]
    231    }));
    232  }
    233 
    234  public fromSchema(schema: Schema.SchemaType): void {
    235    // Clear input data first
    236    pvutils.clearProps(schema, CLEAR_PROPS);
    237 
    238    // Check the schema is valid
    239    const asn1 = asn1js.compareSchema(schema,
    240      schema,
    241      IssuingDistributionPoint.schema({
    242        names: {
    243          distributionPoint: DISTRIBUTION_POINT,
    244          distributionPointNames: DISTRIBUTION_POINT_NAMES,
    245          onlyContainsUserCerts: ONLY_CONTAINS_USER_CERTS,
    246          onlyContainsCACerts: ONLY_CONTAINS_CA_CERTS,
    247          onlySomeReasons: ONLY_SOME_REASON,
    248          indirectCRL: INDIRECT_CRL,
    249          onlyContainsAttributeCerts: ONLY_CONTAINS_ATTRIBUTE_CERTS
    250        }
    251      })
    252    );
    253    AsnError.assertSchema(asn1, this.className);
    254 
    255    // Get internal properties from parsed schema
    256    if (DISTRIBUTION_POINT in asn1.result) {
    257      switch (true) {
    258        case (asn1.result.distributionPoint.idBlock.tagNumber === 0): // GENERAL_NAMES variant
    259          this.distributionPoint = Array.from(asn1.result.distributionPointNames, element => new GeneralName({ schema: element }));
    260          break;
    261        case (asn1.result.distributionPoint.idBlock.tagNumber === 1): // RDN variant
    262          {
    263            this.distributionPoint = new RelativeDistinguishedNames({
    264              schema: new asn1js.Sequence({
    265                value: asn1.result.distributionPoint.valueBlock.value
    266              })
    267            });
    268          }
    269          break;
    270        default:
    271          throw new Error("Unknown tagNumber for distributionPoint: {$asn1.result.distributionPoint.idBlock.tagNumber}");
    272      }
    273    }
    274 
    275    if (ONLY_CONTAINS_USER_CERTS in asn1.result) {
    276      const view = new Uint8Array(asn1.result.onlyContainsUserCerts.valueBlock.valueHex);
    277      this.onlyContainsUserCerts = (view[0] !== 0x00);
    278    }
    279 
    280    if (ONLY_CONTAINS_CA_CERTS in asn1.result) {
    281      const view = new Uint8Array(asn1.result.onlyContainsCACerts.valueBlock.valueHex);
    282      this.onlyContainsCACerts = (view[0] !== 0x00);
    283    }
    284 
    285    if (ONLY_SOME_REASON in asn1.result) {
    286      const view = new Uint8Array(asn1.result.onlySomeReasons.valueBlock.valueHex);
    287      this.onlySomeReasons = view[0];
    288    }
    289 
    290    if (INDIRECT_CRL in asn1.result) {
    291      const view = new Uint8Array(asn1.result.indirectCRL.valueBlock.valueHex);
    292      this.indirectCRL = (view[0] !== 0x00);
    293    }
    294 
    295    if (ONLY_CONTAINS_ATTRIBUTE_CERTS in asn1.result) {
    296      const view = new Uint8Array(asn1.result.onlyContainsAttributeCerts.valueBlock.valueHex);
    297      this.onlyContainsAttributeCerts = (view[0] !== 0x00);
    298    }
    299  }
    300 
    301  public toSchema(): asn1js.Sequence {
    302    //#region Create array for output sequence
    303    const outputArray = [];
    304 
    305    if (this.distributionPoint) {
    306      let value;
    307 
    308      if (this.distributionPoint instanceof Array) {
    309        value = new asn1js.Constructed({
    310          idBlock: {
    311            tagClass: 3, // CONTEXT-SPECIFIC
    312            tagNumber: 0 // [0]
    313          },
    314          value: Array.from(this.distributionPoint, o => o.toSchema())
    315        });
    316      } else {
    317        value = this.distributionPoint.toSchema();
    318 
    319        value.idBlock.tagClass = 3; // CONTEXT - SPECIFIC
    320        value.idBlock.tagNumber = 1; // [1]
    321      }
    322 
    323      outputArray.push(new asn1js.Constructed({
    324        idBlock: {
    325          tagClass: 3, // CONTEXT-SPECIFIC
    326          tagNumber: 0 // [0]
    327        },
    328        value: [value]
    329      }));
    330    }
    331 
    332    if (this.onlyContainsUserCerts !== IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_USER_CERTS)) {
    333      outputArray.push(new asn1js.Primitive({
    334        idBlock: {
    335          tagClass: 3, // CONTEXT-SPECIFIC
    336          tagNumber: 1 // [1]
    337        },
    338        valueHex: (new Uint8Array([0xFF])).buffer
    339      }));
    340    }
    341 
    342    if (this.onlyContainsCACerts !== IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_CA_CERTS)) {
    343      outputArray.push(new asn1js.Primitive({
    344        idBlock: {
    345          tagClass: 3, // CONTEXT-SPECIFIC
    346          tagNumber: 2 // [2]
    347        },
    348        valueHex: (new Uint8Array([0xFF])).buffer
    349      }));
    350    }
    351 
    352    if (this.onlySomeReasons !== undefined) {
    353      const buffer = new ArrayBuffer(1);
    354      const view = new Uint8Array(buffer);
    355 
    356      view[0] = this.onlySomeReasons;
    357 
    358      outputArray.push(new asn1js.Primitive({
    359        idBlock: {
    360          tagClass: 3, // CONTEXT-SPECIFIC
    361          tagNumber: 3 // [3]
    362        },
    363        valueHex: buffer
    364      }));
    365    }
    366 
    367    if (this.indirectCRL !== IssuingDistributionPoint.defaultValues(INDIRECT_CRL)) {
    368      outputArray.push(new asn1js.Primitive({
    369        idBlock: {
    370          tagClass: 3, // CONTEXT-SPECIFIC
    371          tagNumber: 4 // [4]
    372        },
    373        valueHex: (new Uint8Array([0xFF])).buffer
    374      }));
    375    }
    376 
    377    if (this.onlyContainsAttributeCerts !== IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_ATTRIBUTE_CERTS)) {
    378      outputArray.push(new asn1js.Primitive({
    379        idBlock: {
    380          tagClass: 3, // CONTEXT-SPECIFIC
    381          tagNumber: 5 // [5]
    382        },
    383        valueHex: (new Uint8Array([0xFF])).buffer
    384      }));
    385    }
    386    //#endregion
    387 
    388    //#region Construct and return new ASN.1 schema for this object
    389    return (new asn1js.Sequence({
    390      value: outputArray
    391    }));
    392    //#endregion
    393  }
    394 
    395  public toJSON(): IssuingDistributionPointJson {
    396    const obj: IssuingDistributionPointJson = {};
    397 
    398    if (this.distributionPoint) {
    399      if (this.distributionPoint instanceof Array) {
    400        obj.distributionPoint = Array.from(this.distributionPoint, o => o.toJSON());
    401      } else {
    402        obj.distributionPoint = this.distributionPoint.toJSON();
    403      }
    404    }
    405 
    406    if (this.onlyContainsUserCerts !== IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_USER_CERTS)) {
    407      obj.onlyContainsUserCerts = this.onlyContainsUserCerts;
    408    }
    409 
    410    if (this.onlyContainsCACerts !== IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_CA_CERTS)) {
    411      obj.onlyContainsCACerts = this.onlyContainsCACerts;
    412    }
    413 
    414    if (ONLY_SOME_REASON in this) {
    415      obj.onlySomeReasons = this.onlySomeReasons;
    416    }
    417 
    418    if (this.indirectCRL !== IssuingDistributionPoint.defaultValues(INDIRECT_CRL)) {
    419      obj.indirectCRL = this.indirectCRL;
    420    }
    421 
    422    if (this.onlyContainsAttributeCerts !== IssuingDistributionPoint.defaultValues(ONLY_CONTAINS_ATTRIBUTE_CERTS)) {
    423      obj.onlyContainsAttributeCerts = this.onlyContainsAttributeCerts;
    424    }
    425 
    426    return obj;
    427  }
    428 
    429 }