tor-browser

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

CertBag.ts (6561B)


      1 import * as asn1js from "asn1js";
      2 import * as pvutils from "pvutils";
      3 import { Certificate } from "./Certificate";
      4 import { AttributeCertificateV2 } from "./AttributeCertificateV2";
      5 import * as Schema from "./Schema";
      6 import { id_CertBag_AttributeCertificate, id_CertBag_SDSICertificate, id_CertBag_X509Certificate } from "./ObjectIdentifiers";
      7 import { AsnError } from "./errors";
      8 import { PkiObject, PkiObjectParameters } from "./PkiObject";
      9 import { EMPTY_STRING } from "./constants";
     10 
     11 const CERT_ID = "certId";
     12 const CERT_VALUE = "certValue";
     13 const PARSED_VALUE = "parsedValue";
     14 const CLEAR_PROPS = [
     15  CERT_ID,
     16  CERT_VALUE
     17 ];
     18 
     19 export interface ICertBag {
     20  certId: string;
     21  certValue: asn1js.OctetString | PkiObject;
     22  parsedValue: any;
     23 }
     24 
     25 export type CertBagParameters = PkiObjectParameters & Partial<ICertBag>;
     26 
     27 export interface CertBagJson {
     28  certId: string;
     29  certValue: any;
     30 }
     31 
     32 /**
     33 * Represents the CertBag structure described in [RFC7292](https://datatracker.ietf.org/doc/html/rfc7292)
     34 */
     35 export class CertBag extends PkiObject implements ICertBag {
     36 
     37  public static override CLASS_NAME = "CertBag";
     38 
     39  public certId!: string;
     40  public certValue: PkiObject | asn1js.OctetString;
     41  public parsedValue: any;
     42 
     43  /**
     44   * Initializes a new instance of the {@link CertBag} class
     45   * @param parameters Initialization parameters
     46   */
     47  constructor(parameters: CertBagParameters = {}) {
     48    super();
     49 
     50    this.certId = pvutils.getParametersValue(parameters, CERT_ID, CertBag.defaultValues(CERT_ID));
     51    this.certValue = pvutils.getParametersValue(parameters, CERT_VALUE, CertBag.defaultValues(CERT_VALUE));
     52    if (PARSED_VALUE in parameters) {
     53      this.parsedValue = pvutils.getParametersValue(parameters, PARSED_VALUE, CertBag.defaultValues(PARSED_VALUE));
     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 CERT_ID): string;
     67  public static override defaultValues(memberName: typeof CERT_VALUE): any;
     68  public static override defaultValues(memberName: typeof PARSED_VALUE): any;
     69  public static override defaultValues(memberName: string): any {
     70    switch (memberName) {
     71      case CERT_ID:
     72        return EMPTY_STRING;
     73      case CERT_VALUE:
     74        return (new asn1js.Any());
     75      case PARSED_VALUE:
     76        return {};
     77      default:
     78        return super.defaultValues(memberName);
     79    }
     80  }
     81 
     82  /**
     83   * Compare values with default values for all class members
     84   * @param memberName String name for a class member
     85   * @param memberValue Value to compare with default value
     86   */
     87  public static compareWithDefault(memberName: string, memberValue: any): boolean {
     88    switch (memberName) {
     89      case CERT_ID:
     90        return (memberValue === EMPTY_STRING);
     91      case CERT_VALUE:
     92        return (memberValue instanceof asn1js.Any);
     93      case PARSED_VALUE:
     94        return ((memberValue instanceof Object) && (Object.keys(memberValue).length === 0));
     95      default:
     96        return super.defaultValues(memberName);
     97    }
     98  }
     99 
    100  /**
    101   * @inheritdoc
    102   * @asn ASN.1 schema
    103   * ```asn
    104   * CertBag ::= SEQUENCE {
    105   *    certId    BAG-TYPE.&id   ({CertTypes}),
    106   *    certValue [0] EXPLICIT BAG-TYPE.&Type ({CertTypes}{@certId})
    107   * }
    108   *```
    109   */
    110  public static override schema(parameters: Schema.SchemaParameters<{
    111    id?: string;
    112    value?: string;
    113  }> = {}): Schema.SchemaType {
    114    const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {});
    115 
    116    return (new asn1js.Sequence({
    117      name: (names.blockName || EMPTY_STRING),
    118      value: [
    119        new asn1js.ObjectIdentifier({ name: (names.id || "id") }),
    120        new asn1js.Constructed({
    121          idBlock: {
    122            tagClass: 3, // CONTEXT-SPECIFIC
    123            tagNumber: 0 // [0]
    124          },
    125          value: [new asn1js.Any({ name: (names.value || "value") })] // EXPLICIT ANY value
    126        })
    127      ]
    128    }));
    129  }
    130 
    131  public fromSchema(schema: Schema.SchemaType): void {
    132    // Clear input data first
    133    pvutils.clearProps(schema, CLEAR_PROPS);
    134 
    135    // Check the schema is valid
    136    const asn1 = asn1js.compareSchema(schema,
    137      schema,
    138      CertBag.schema({
    139        names: {
    140          id: CERT_ID,
    141          value: CERT_VALUE
    142        }
    143      })
    144    );
    145    AsnError.assertSchema(asn1, this.className);
    146 
    147    //#region Get internal properties from parsed schema
    148    this.certId = asn1.result.certId.valueBlock.toString();
    149    this.certValue = asn1.result.certValue as asn1js.OctetString;
    150 
    151    const certValueHex = this.certValue.valueBlock.valueHexView;
    152    switch (this.certId) {
    153      case id_CertBag_X509Certificate: // x509Certificate
    154        {
    155          try {
    156            this.parsedValue = Certificate.fromBER(certValueHex as BufferSource);
    157          }
    158          catch // In some realizations the same OID used for attribute certificates
    159          {
    160            AttributeCertificateV2.fromBER(certValueHex as BufferSource);
    161          }
    162        }
    163        break;
    164      case id_CertBag_AttributeCertificate: // attributeCertificate - (!!!) THIS OID IS SUBJECT FOR CHANGE IN FUTURE (!!!)
    165        {
    166          this.parsedValue = AttributeCertificateV2.fromBER(certValueHex as BufferSource);
    167        }
    168        break;
    169      case id_CertBag_SDSICertificate: // sdsiCertificate
    170      default:
    171        throw new Error(`Incorrect CERT_ID value in CertBag: ${this.certId}`);
    172    }
    173    //#endregion
    174  }
    175 
    176  public toSchema(): asn1js.Sequence {
    177    //#region Construct and return new ASN.1 schema for this object
    178    if (PARSED_VALUE in this) {
    179      if ("acinfo" in this.parsedValue) {// attributeCertificate
    180        this.certId = id_CertBag_AttributeCertificate;
    181      } else {// x509Certificate
    182        this.certId = id_CertBag_X509Certificate;
    183      }
    184 
    185      this.certValue = new asn1js.OctetString({ valueHex: this.parsedValue.toSchema().toBER(false) });
    186    }
    187 
    188    return (new asn1js.Sequence({
    189      value: [
    190        new asn1js.ObjectIdentifier({ value: this.certId }),
    191        new asn1js.Constructed({
    192          idBlock: {
    193            tagClass: 3, // CONTEXT-SPECIFIC
    194            tagNumber: 0 // [0]
    195          },
    196          value: [(("toSchema" in this.certValue) ? this.certValue.toSchema() : this.certValue)]
    197        })
    198      ]
    199    }));
    200    //#endregion
    201  }
    202 
    203  public toJSON(): CertBagJson {
    204    return {
    205      certId: this.certId,
    206      certValue: this.certValue.toJSON()
    207    };
    208  }
    209 
    210 }