diff options
Diffstat (limited to 'third_party/js/PKI.js/src/TBSRequest.ts')
-rw-r--r-- | third_party/js/PKI.js/src/TBSRequest.ts | 337 |
1 files changed, 337 insertions, 0 deletions
diff --git a/third_party/js/PKI.js/src/TBSRequest.ts b/third_party/js/PKI.js/src/TBSRequest.ts new file mode 100644 index 0000000000..cca0b47150 --- /dev/null +++ b/third_party/js/PKI.js/src/TBSRequest.ts @@ -0,0 +1,337 @@ +import * as asn1js from "asn1js"; +import * as pvtsutils from "pvtsutils"; +import * as pvutils from "pvutils"; +import { GeneralName, GeneralNameJson, GeneralNameSchema } from "./GeneralName"; +import { Request, RequestJson, RequestSchema } from "./Request"; +import { Extension, ExtensionJson } from "./Extension"; +import { Extensions, ExtensionsSchema } from "./Extensions"; +import * as Schema from "./Schema"; +import { AsnError } from "./errors"; +import { PkiObject, PkiObjectParameters } from "./PkiObject"; +import { EMPTY_BUFFER } from "./constants"; + +const TBS = "tbs"; +const VERSION = "version"; +const REQUESTOR_NAME = "requestorName"; +const REQUEST_LIST = "requestList"; +const REQUEST_EXTENSIONS = "requestExtensions"; +const TBS_REQUEST = "TBSRequest"; +const TBS_REQUEST_VERSION = `${TBS_REQUEST}.${VERSION}`; +const TBS_REQUEST_REQUESTOR_NAME = `${TBS_REQUEST}.${REQUESTOR_NAME}`; +const TBS_REQUEST_REQUESTS = `${TBS_REQUEST}.requests`; +const TBS_REQUEST_REQUEST_EXTENSIONS = `${TBS_REQUEST}.${REQUEST_EXTENSIONS}`; +const CLEAR_PROPS = [ + TBS_REQUEST, + TBS_REQUEST_VERSION, + TBS_REQUEST_REQUESTOR_NAME, + TBS_REQUEST_REQUESTS, + TBS_REQUEST_REQUEST_EXTENSIONS +]; + +export interface ITBSRequest { + tbs: ArrayBuffer; + version?: number; + requestorName?: GeneralName; + requestList: Request[]; + requestExtensions?: Extension[]; +} + +export interface TBSRequestJson { + tbs: string; + version?: number; + requestorName?: GeneralNameJson; + requestList: RequestJson[]; + requestExtensions?: ExtensionJson[]; +} + +export type TBSRequestParameters = PkiObjectParameters & Partial<ITBSRequest>; + +export type TBSRequestSchema = Schema.SchemaParameters<{ + TBSRequestVersion?: string; + requestorName?: GeneralNameSchema; + requestList?: string; + requests?: string; + requestNames?: RequestSchema; + extensions?: ExtensionsSchema; + requestExtensions?: string; +}>; + +/** + * Represents the TBSRequest structure described in [RFC6960](https://datatracker.ietf.org/doc/html/rfc6960) + */ +export class TBSRequest extends PkiObject implements ITBSRequest { + + public static override CLASS_NAME = "TBSRequest"; + + public tbsView!: Uint8Array; + /** + * @deprecated Since version 3.0.0 + */ + public get tbs(): ArrayBuffer { + return pvtsutils.BufferSourceConverter.toArrayBuffer(this.tbsView); + } + + /** + * @deprecated Since version 3.0.0 + */ + public set tbs(value: ArrayBuffer) { + this.tbsView = new Uint8Array(value); + } + public version?: number; + public requestorName?: GeneralName; + public requestList!: Request[]; + public requestExtensions?: Extension[]; + + /** + * Initializes a new instance of the {@link TBSRequest} class + * @param parameters Initialization parameters + */ + constructor(parameters: TBSRequestParameters = {}) { + super(); + + this.tbsView = new Uint8Array(pvutils.getParametersValue(parameters, TBS, TBSRequest.defaultValues(TBS))); + if (VERSION in parameters) { + this.version = pvutils.getParametersValue(parameters, VERSION, TBSRequest.defaultValues(VERSION)); + } + if (REQUESTOR_NAME in parameters) { + this.requestorName = pvutils.getParametersValue(parameters, REQUESTOR_NAME, TBSRequest.defaultValues(REQUESTOR_NAME)); + } + this.requestList = pvutils.getParametersValue(parameters, REQUEST_LIST, TBSRequest.defaultValues(REQUEST_LIST)); + if (REQUEST_EXTENSIONS in parameters) { + this.requestExtensions = pvutils.getParametersValue(parameters, REQUEST_EXTENSIONS, TBSRequest.defaultValues(REQUEST_EXTENSIONS)); + } + + if (parameters.schema) { + this.fromSchema(parameters.schema); + } + } + + /** + * Returns default values for all class members + * @param memberName String name for a class member + * @returns Default value + */ + public static override defaultValues(memberName: typeof TBS): ArrayBuffer; + public static override defaultValues(memberName: typeof VERSION): number; + public static override defaultValues(memberName: typeof REQUESTOR_NAME): GeneralName; + public static override defaultValues(memberName: typeof REQUEST_LIST): Request[]; + public static override defaultValues(memberName: typeof REQUEST_EXTENSIONS): Extension[]; + public static override defaultValues(memberName: string): any { + switch (memberName) { + case TBS: + return EMPTY_BUFFER; + case VERSION: + return 0; + case REQUESTOR_NAME: + return new GeneralName(); + case REQUEST_LIST: + case REQUEST_EXTENSIONS: + return []; + default: + return super.defaultValues(memberName); + } + } + + /** + * Compare values with default values for all class members + * @param memberName String name for a class member + * @param memberValue Value to compare with default value + */ + public static compareWithDefault(memberName: string, memberValue: any): boolean { + switch (memberName) { + case TBS: + return (memberValue.byteLength === 0); + case VERSION: + return (memberValue === TBSRequest.defaultValues(memberName)); + case REQUESTOR_NAME: + return ((memberValue.type === GeneralName.defaultValues("type")) && (Object.keys(memberValue.value).length === 0)); + case REQUEST_LIST: + case REQUEST_EXTENSIONS: + return (memberValue.length === 0); + default: + return super.defaultValues(memberName); + } + } + + /** + * @inheritdoc + * @asn ASN.1 schema + * ```asn + * TBSRequest ::= SEQUENCE { + * version [0] EXPLICIT Version DEFAULT v1, + * requestorName [1] EXPLICIT GeneralName OPTIONAL, + * requestList SEQUENCE OF Request, + * requestExtensions [2] EXPLICIT Extensions OPTIONAL } + *``` + */ + public static override schema(parameters: TBSRequestSchema = {}): Schema.SchemaType { + const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); + + return (new asn1js.Sequence({ + name: (names.blockName || TBS_REQUEST), + value: [ + new asn1js.Constructed({ + optional: true, + idBlock: { + tagClass: 3, // CONTEXT-SPECIFIC + tagNumber: 0 // [0] + }, + value: [new asn1js.Integer({ name: (names.TBSRequestVersion || TBS_REQUEST_VERSION) })] + }), + new asn1js.Constructed({ + optional: true, + idBlock: { + tagClass: 3, // CONTEXT-SPECIFIC + tagNumber: 1 // [1] + }, + value: [GeneralName.schema(names.requestorName || { + names: { + blockName: TBS_REQUEST_REQUESTOR_NAME + } + })] + }), + new asn1js.Sequence({ + name: (names.requestList || "TBSRequest.requestList"), + value: [ + new asn1js.Repeated({ + name: (names.requests || TBS_REQUEST_REQUESTS), + value: Request.schema(names.requestNames || {}) + }) + ] + }), + new asn1js.Constructed({ + optional: true, + idBlock: { + tagClass: 3, // CONTEXT-SPECIFIC + tagNumber: 2 // [2] + }, + value: [Extensions.schema(names.extensions || { + names: { + blockName: (names.requestExtensions || TBS_REQUEST_REQUEST_EXTENSIONS) + } + })] + }) + ] + })); + } + + public fromSchema(schema: Schema.SchemaType): void { + // Clear input data first + pvutils.clearProps(schema, CLEAR_PROPS); + + // Check the schema is valid + const asn1 = asn1js.compareSchema(schema, + schema, + TBSRequest.schema() + ); + AsnError.assertSchema(asn1, this.className); + + // Get internal properties from parsed schema + this.tbsView = asn1.result.TBSRequest.valueBeforeDecodeView; + + if (TBS_REQUEST_VERSION in asn1.result) + this.version = asn1.result[TBS_REQUEST_VERSION].valueBlock.valueDec; + if (TBS_REQUEST_REQUESTOR_NAME in asn1.result) + this.requestorName = new GeneralName({ schema: asn1.result[TBS_REQUEST_REQUESTOR_NAME] }); + + this.requestList = Array.from(asn1.result[TBS_REQUEST_REQUESTS], element => new Request({ schema: element })); + + if (TBS_REQUEST_REQUEST_EXTENSIONS in asn1.result) + this.requestExtensions = Array.from(asn1.result[TBS_REQUEST_REQUEST_EXTENSIONS].valueBlock.value, element => new Extension({ schema: element })); + } + + /** + * Convert current object to asn1js object and set correct values + * @param encodeFlag If param equal to false then create TBS schema via decoding stored value. In othe case create TBS schema via assembling from TBS parts. + * @returns asn1js object + */ + public toSchema(encodeFlag = false): asn1js.Sequence { + //#region Decode stored TBS value + let tbsSchema; + + if (encodeFlag === false) { + if (this.tbsView.byteLength === 0) // No stored TBS part + return TBSRequest.schema(); + + const asn1 = asn1js.fromBER(this.tbsView); + AsnError.assert(asn1, "TBS Request"); + if (!(asn1.result instanceof asn1js.Sequence)) { + throw new Error("ASN.1 result should be SEQUENCE"); + } + + tbsSchema = asn1.result; + } + //#endregion + //#region Create TBS schema via assembling from TBS parts + else { + const outputArray = []; + + if (this.version !== undefined) { + outputArray.push(new asn1js.Constructed({ + idBlock: { + tagClass: 3, // CONTEXT-SPECIFIC + tagNumber: 0 // [0] + }, + value: [new asn1js.Integer({ value: this.version })] + })); + } + + if (this.requestorName) { + outputArray.push(new asn1js.Constructed({ + idBlock: { + tagClass: 3, // CONTEXT-SPECIFIC + tagNumber: 1 // [1] + }, + value: [this.requestorName.toSchema()] + })); + } + + outputArray.push(new asn1js.Sequence({ + value: Array.from(this.requestList, o => o.toSchema()) + })); + + if (this.requestExtensions) { + outputArray.push(new asn1js.Constructed({ + idBlock: { + tagClass: 3, // CONTEXT-SPECIFIC + tagNumber: 2 // [2] + }, + value: [ + new asn1js.Sequence({ + value: Array.from(this.requestExtensions, o => o.toSchema()) + }) + ] + })); + } + + tbsSchema = new asn1js.Sequence({ + value: outputArray + }); + } + //#endregion + + //#region Construct and return new ASN.1 schema for this object + return tbsSchema; + //#endregion + } + + public toJSON(): TBSRequestJson { + const res: any = {}; + + if (this.version != undefined) + res.version = this.version; + + if (this.requestorName) { + res.requestorName = this.requestorName.toJSON(); + } + + res.requestList = Array.from(this.requestList, o => o.toJSON()); + + if (this.requestExtensions) { + res.requestExtensions = Array.from(this.requestExtensions, o => o.toJSON()); + } + + return res; + } + +} |