diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/asn1js/src/internals | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'comm/third_party/asn1js/src/internals')
22 files changed, 2392 insertions, 0 deletions
diff --git a/comm/third_party/asn1js/src/internals/LocalBaseBlock.ts b/comm/third_party/asn1js/src/internals/LocalBaseBlock.ts new file mode 100644 index 0000000000..c144c49d10 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalBaseBlock.ts @@ -0,0 +1,93 @@ +import * as pvtsutils from "pvtsutils"; +import { EMPTY_STRING, EMPTY_VIEW } from "./constants"; + +export interface ILocalBaseBlock { + blockLength: number; + error: string; + warnings: string[]; +} + +export interface LocalBaseBlockJson extends ILocalBaseBlock { + blockName: string; + valueBeforeDecode: string; +} + +export interface LocalBaseBlockParams extends Partial<ILocalBaseBlock> { + valueBeforeDecode?: pvtsutils.BufferSource; +} + +export interface LocalBaseBlockConstructor<T extends LocalBaseBlock = LocalBaseBlock> { + new(...args: any[]): T; + prototype: T; + NAME: string; + blockName(): string; +} + +/** + * Class used as a base block for all remaining ASN.1 classes + */ +export class LocalBaseBlock implements ILocalBaseBlock { + + /** + * Name of the block + */ + public static NAME = "baseBlock"; + /** + * Aux function, need to get a block name. Need to have it here for inheritance + * @returns Returns name of the block + */ + public static blockName(): string { + return this.NAME; + } + + public blockLength: number; + public error: string; + public warnings: string[]; + /** + * @deprecated since version 3.0.0 + */ + public get valueBeforeDecode(): ArrayBuffer { + return this.valueBeforeDecodeView.slice().buffer; + } + /** + * @deprecated since version 3.0.0 + */ + public set valueBeforeDecode(value: ArrayBuffer) { + this.valueBeforeDecodeView = new Uint8Array(value); + } + /** + * @since 3.0.0 + */ + public valueBeforeDecodeView: Uint8Array; + + /** + * Creates and initializes an object instance of that class + * @param param0 Initialization parameters + */ + constructor({ + blockLength = 0, + error = EMPTY_STRING, + warnings = [], + valueBeforeDecode = EMPTY_VIEW, + }: LocalBaseBlockParams = {}) { + this.blockLength = blockLength; + this.error = error; + this.warnings = warnings; + this.valueBeforeDecodeView = pvtsutils.BufferSourceConverter.toUint8Array(valueBeforeDecode); + } + + /** + * Returns a JSON representation of an object + * @returns JSON object + */ + public toJSON(): LocalBaseBlockJson { + return { + blockName: (this.constructor as typeof LocalBaseBlock).NAME, + blockLength: this.blockLength, + error: this.error, + warnings: this.warnings, + valueBeforeDecode: pvtsutils.Convert.ToHex(this.valueBeforeDecodeView), + }; + } + +} diff --git a/comm/third_party/asn1js/src/internals/LocalBitStringValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalBitStringValueBlock.ts new file mode 100644 index 0000000000..1720b55d82 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalBitStringValueBlock.ts @@ -0,0 +1,168 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import * as pvtsutils from "pvtsutils"; +import { ViewWriter } from "../ViewWriter"; +import { HexBlockJson, HexBlockParams, HexBlock } from "../HexBlock"; +import { BIT_STRING_NAME, EMPTY_BUFFER, END_OF_CONTENT_NAME } from "./constants"; +import { LocalConstructedValueBlockParams, LocalConstructedValueBlockJson, LocalConstructedValueBlock } from "./LocalConstructedValueBlock"; +import { localFromBER } from "../parser"; +import { checkBufferParams } from "./utils"; +import type { BitString } from "../BitString"; + +export interface ILocalBitStringValueBlock { + unusedBits: number; + isConstructed: boolean; +} + +export interface LocalBitStringValueBlockParams extends HexBlockParams, LocalConstructedValueBlockParams, Partial<ILocalBitStringValueBlock> { + value?: BitString[]; +} + +export interface LocalBitStringValueBlockJson extends HexBlockJson, LocalConstructedValueBlockJson, ILocalBitStringValueBlock { } + +export class LocalBitStringValueBlock extends HexBlock(LocalConstructedValueBlock) implements ILocalBitStringValueBlock { + + public static override NAME = "BitStringValueBlock"; + + public unusedBits: number; + public isConstructed: boolean; + + constructor({ + unusedBits = 0, + isConstructed = false, + ...parameters + }: LocalBitStringValueBlockParams = {}) { + super(parameters); + + this.unusedBits = unusedBits; + this.isConstructed = isConstructed; + this.blockLength = this.valueHexView.byteLength; + } + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + // Ability to decode zero-length BitString value + if (!inputLength) { + return inputOffset; + } + + let resultOffset = -1; + + // If the BIT STRING supposed to be a constructed value + if (this.isConstructed) { + resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength); + if (resultOffset === -1) + return resultOffset; + + for (const value of this.value) { + const currentBlockName = (value.constructor as typeof LocalBitStringValueBlock).NAME; + + if (currentBlockName === END_OF_CONTENT_NAME) { + if (this.isIndefiniteForm) + break; + else { + this.error = "EndOfContent is unexpected, BIT STRING may consists of BIT STRINGs only"; + + return -1; + } + } + + if (currentBlockName !== BIT_STRING_NAME) { + this.error = "BIT STRING may consists of BIT STRINGs only"; + + return -1; + } + + const valueBlock = value.valueBlock as unknown as LocalBitStringValueBlock; + if ((this.unusedBits > 0) && (valueBlock.unusedBits > 0)) { + this.error = "Using of \"unused bits\" inside constructive BIT STRING allowed for least one only"; + + return -1; + } + + this.unusedBits = valueBlock.unusedBits; + } + + return resultOffset; + } + + const inputView = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + + //If the BitString supposed to be a primitive value + if (!checkBufferParams(this, inputView, inputOffset, inputLength)) { + return -1; + } + + const intBuffer = inputView.subarray(inputOffset, inputOffset + inputLength); + + this.unusedBits = intBuffer[0]; + + if (this.unusedBits > 7) { + this.error = "Unused bits for BitString must be in range 0-7"; + + return -1; + } + + if (!this.unusedBits) { + const buf = intBuffer.subarray(1); + try { + if (buf.byteLength) { + const asn = localFromBER(buf, 0, buf.byteLength); + if (asn.offset !== -1 && asn.offset === (inputLength - 1)) { + this.value = [asn.result as BitString]; + } + } + } catch (e) { + // nothing + } + } + + // Copy input buffer to internal buffer + this.valueHexView = intBuffer.subarray(1); + this.blockLength = intBuffer.length; + + return (inputOffset + inputLength); + } + + public override toBER(sizeOnly?: boolean, writer?: ViewWriter): ArrayBuffer { + if (this.isConstructed) { + return LocalConstructedValueBlock.prototype.toBER.call(this, sizeOnly, writer); + } + + if (sizeOnly) { + return new ArrayBuffer(this.valueHexView.byteLength + 1); + } + + if (!this.valueHexView.byteLength) { + return EMPTY_BUFFER; + } + + const retView = new Uint8Array(this.valueHexView.length + 1); + + retView[0] = this.unusedBits; + retView.set(this.valueHexView, 1); + + return retView.buffer; + } + + public override toJSON(): LocalBitStringValueBlockJson { + return { + ...super.toJSON(), + unusedBits: this.unusedBits, + isConstructed: this.isConstructed, + } as LocalBitStringValueBlockJson; + } +} + +export interface LocalBitStringValueBlock { + /** + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueBeforeDecode: ArrayBuffer; + /** + * Binary data in ArrayBuffer representation + * + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueHex: ArrayBuffer; +} diff --git a/comm/third_party/asn1js/src/internals/LocalBmpStringValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalBmpStringValueBlock.ts new file mode 100644 index 0000000000..6245512755 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalBmpStringValueBlock.ts @@ -0,0 +1,21 @@ +import * as pvtsutils from "pvtsutils"; +import { LocalSimpleStringBlock, LocalSimpleStringBlockJson, LocalSimpleStringBlockParams } from "./LocalSimpleStringBlock"; + +export type LocalBmpStringValueBlockParams = LocalSimpleStringBlockParams; +export type LocalBmpStringValueBlockJson = LocalSimpleStringBlockJson; + +export class LocalBmpStringValueBlock extends LocalSimpleStringBlock { + + public static override NAME = "BmpStringValueBlock"; + + public override fromBuffer(inputBuffer: ArrayBuffer | Uint8Array): void { + this.valueBlock.value = pvtsutils.Convert.ToUtf16String(inputBuffer); + this.valueBlock.valueHexView = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + } + + public override fromString(inputString: string): void { + this.valueBlock.value = inputString; + this.valueBlock.valueHexView = new Uint8Array(pvtsutils.Convert.FromUtf16String(inputString)); + } + +} diff --git a/comm/third_party/asn1js/src/internals/LocalBooleanValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalBooleanValueBlock.ts new file mode 100644 index 0000000000..a4cdb35dee --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalBooleanValueBlock.ts @@ -0,0 +1,96 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import * as pvtsutils from "pvtsutils"; +import * as pvutils from "pvutils"; +import { HexBlockJson, HexBlockParams, HexBlock } from "../HexBlock"; +import { ValueBlock, ValueBlockJson, ValueBlockParams } from "../ValueBlock"; +import { checkBufferParams } from "./utils"; + +export interface ILocalBooleanValueBlock { + value: boolean; +} + +export interface LocalBooleanValueBlockParams extends ValueBlockParams, HexBlockParams, Partial<ILocalBooleanValueBlock> { } + +export interface LocalBooleanValueBlockJson extends ValueBlockJson, HexBlockJson, ILocalBooleanValueBlock { } + +export class LocalBooleanValueBlock extends HexBlock(ValueBlock) implements ILocalBooleanValueBlock { + + public static override NAME = "BooleanValueBlock"; + + public get value(): boolean { + for (const octet of this.valueHexView) { + if (octet > 0) { + return true; + } + } + + return false; + } + + public set value(value: boolean) { + this.valueHexView[0] = value ? 0xFF : 0x00; + } + + constructor({ + value, + ...parameters + }: LocalBooleanValueBlockParams = {}) { + super(parameters); + + if (parameters.valueHex) { + this.valueHexView = pvtsutils.BufferSourceConverter.toUint8Array(parameters.valueHex); + } else { + this.valueHexView = new Uint8Array(1); + } + + if (value) { + this.value = value; + } + } + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + const inputView = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + // Basic check for parameters + if (!checkBufferParams(this, inputView, inputOffset, inputLength)) { + return -1; + } + + // Getting Uint8Array + this.valueHexView = inputView.subarray(inputOffset, inputOffset + inputLength); + + if (inputLength > 1) + this.warnings.push("Boolean value encoded in more then 1 octet"); + + this.isHexOnly = true; + pvutils.utilDecodeTC.call(this); + this.blockLength = inputLength; + + return (inputOffset + inputLength); + } + + public override toBER(): ArrayBuffer { + return this.valueHexView.slice(); + } + + public override toJSON(): LocalBooleanValueBlockJson { + return { + ...super.toJSON(), + value: this.value, + }; + } +} + +export interface LocalBooleanValueBlock { + /** + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueBeforeDecode: ArrayBuffer; + /** + * Binary data in ArrayBuffer representation + * + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueHex: ArrayBuffer; +} diff --git a/comm/third_party/asn1js/src/internals/LocalConstructedValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalConstructedValueBlock.ts new file mode 100644 index 0000000000..db3ba9f35e --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalConstructedValueBlock.ts @@ -0,0 +1,128 @@ +import * as pvtsutils from "pvtsutils"; +import { LocalBaseBlockJson } from "./LocalBaseBlock"; +import { EMPTY_BUFFER, END_OF_CONTENT_NAME } from "./constants"; +import type { BaseBlock } from "../BaseBlock"; +import { ValueBlock, ValueBlockParams } from "../ValueBlock"; +import { ViewWriter } from "../ViewWriter"; +import { localFromBER } from "../parser"; +import { checkBufferParams } from "./utils"; +import type { Any } from "../Any"; + +export type ConstructedItem = BaseBlock | Any; + +export interface ILocalConstructedValueBlock { + value: ConstructedItem[]; + isIndefiniteForm: boolean; +} + +export interface LocalConstructedValueBlockParams extends ValueBlockParams, Partial<ILocalConstructedValueBlock> { } + +export interface LocalConstructedValueBlockJson extends LocalBaseBlockJson, Omit<ILocalConstructedValueBlock, "value"> { + value: LocalBaseBlockJson[]; +} + +function checkLen(indefiniteLength: boolean, length: number): number { + if (indefiniteLength) { + return 1; + } + + return length; +} + +export class LocalConstructedValueBlock extends ValueBlock implements ILocalConstructedValueBlock { + + public static override NAME = "ConstructedValueBlock"; + + public value: BaseBlock[]; + public isIndefiniteForm: boolean; + + constructor({ + value = [], + isIndefiniteForm = false, + ...parameters + }: LocalConstructedValueBlockParams = {}) { + super(parameters); + + this.value = value as BaseBlock[]; // It's possible to set Any type for Schema declaration + this.isIndefiniteForm = isIndefiniteForm; + } + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + const view = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + + // Basic check for parameters + if (!checkBufferParams(this, view, inputOffset, inputLength)) { + return -1; + } + + this.valueBeforeDecodeView = view.subarray(inputOffset, inputOffset + inputLength); + + // Initial checks + if (this.valueBeforeDecodeView.length === 0) { + this.warnings.push("Zero buffer length"); + + return inputOffset; + } + + let currentOffset = inputOffset; + + while (checkLen(this.isIndefiniteForm, inputLength) > 0) { + const returnObject = localFromBER(view, currentOffset, inputLength); + if (returnObject.offset === -1) { + this.error = returnObject.result.error; + this.warnings.concat(returnObject.result.warnings); + + return -1; + } + + currentOffset = returnObject.offset; + + this.blockLength += returnObject.result.blockLength; + inputLength -= returnObject.result.blockLength; + + this.value.push(returnObject.result); + + if (this.isIndefiniteForm && (returnObject.result.constructor as typeof BaseBlock).NAME === END_OF_CONTENT_NAME) { + break; + } + } + + if (this.isIndefiniteForm) { + if ((this.value[this.value.length - 1].constructor as typeof BaseBlock).NAME === END_OF_CONTENT_NAME) { + this.value.pop(); + } else { + this.warnings.push("No EndOfContent block encoded"); + } + } + + return currentOffset; + } + + public override toBER(sizeOnly?: boolean, writer?: ViewWriter): ArrayBuffer { + const _writer = writer || new ViewWriter(); + + for (let i = 0; i < this.value.length; i++) { + this.value[i].toBER(sizeOnly, _writer); + } + + if (!writer) { + return _writer.final(); + } + + return EMPTY_BUFFER; + } + + public override toJSON(): LocalConstructedValueBlockJson { + const object: LocalConstructedValueBlockJson = { + ...super.toJSON(), + isIndefiniteForm: this.isIndefiniteForm, + value: [], + }; + + for (const value of this.value) { + object.value.push(value.toJSON()); + } + + return object; + } +} diff --git a/comm/third_party/asn1js/src/internals/LocalEndOfContentValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalEndOfContentValueBlock.ts new file mode 100644 index 0000000000..4a1db86681 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalEndOfContentValueBlock.ts @@ -0,0 +1,16 @@ +import { ValueBlock } from "../ValueBlock"; +import { EMPTY_BUFFER } from "./constants"; + +export class LocalEndOfContentValueBlock extends ValueBlock { + + public static override = "EndOfContentValueBlock"; + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + // There is no "value block" for EndOfContent type and we need to return the same offset + return inputOffset; + } + + public override toBER(sizeOnly?: boolean): ArrayBuffer { + return EMPTY_BUFFER; + } +} diff --git a/comm/third_party/asn1js/src/internals/LocalIdentificationBlock.ts b/comm/third_party/asn1js/src/internals/LocalIdentificationBlock.ts new file mode 100644 index 0000000000..d97c874b7a --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalIdentificationBlock.ts @@ -0,0 +1,280 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import * as pvtsutils from "pvtsutils"; +import * as pvutils from "pvutils"; +import { HexBlockJson, HexBlockParams, HexBlock } from "../HexBlock"; +import { EMPTY_BUFFER, EMPTY_VIEW } from "./constants"; +import { LocalBaseBlock, LocalBaseBlockJson } from "./LocalBaseBlock"; +import { checkBufferParams } from "./utils"; + + +export interface ILocalIdentificationBlock { + tagClass: number; + tagNumber: number; + isConstructed: boolean; +} + +export interface LocalIdentificationBlockParams { + idBlock?: Partial<ILocalIdentificationBlock> & HexBlockParams; +} + +export interface LocalIdentificationBlockJson extends HexBlockJson, LocalBaseBlockJson, ILocalIdentificationBlock { } + + +export class LocalIdentificationBlock extends HexBlock(LocalBaseBlock) implements ILocalIdentificationBlock { + + public static override NAME = "identificationBlock"; + + public tagClass: number; + public tagNumber: number; + public isConstructed: boolean; + + constructor({ + idBlock = {}, + }: LocalIdentificationBlockParams = {}) { + super(); + + if (idBlock) { + //#region Properties from hexBlock class + this.isHexOnly = idBlock.isHexOnly ?? false; + this.valueHexView = idBlock.valueHex ? pvtsutils.BufferSourceConverter.toUint8Array(idBlock.valueHex) : EMPTY_VIEW; + //#endregion + this.tagClass = idBlock.tagClass ?? -1; + this.tagNumber = idBlock.tagNumber ?? -1; + this.isConstructed = idBlock.isConstructed ?? false; + } else { + this.tagClass = -1; + this.tagNumber = -1; + this.isConstructed = false; + } + } + + public override toBER(sizeOnly = false): ArrayBuffer { + let firstOctet = 0; + + switch (this.tagClass) { + case 1: + firstOctet |= 0x00; // UNIVERSAL + break; + case 2: + firstOctet |= 0x40; // APPLICATION + break; + case 3: + firstOctet |= 0x80; // CONTEXT-SPECIFIC + break; + case 4: + firstOctet |= 0xC0; // PRIVATE + break; + default: + this.error = "Unknown tag class"; + + return EMPTY_BUFFER; + } + + if (this.isConstructed) + firstOctet |= 0x20; + + if (this.tagNumber < 31 && !this.isHexOnly) { + const retView = new Uint8Array(1); + + if (!sizeOnly) { + let number = this.tagNumber; + number &= 0x1F; + firstOctet |= number; + + retView[0] = firstOctet; + } + + return retView.buffer; + } + + if (!this.isHexOnly) { + const encodedBuf = pvutils.utilToBase(this.tagNumber, 7); + const encodedView = new Uint8Array(encodedBuf); + const size = encodedBuf.byteLength; + + const retView = new Uint8Array(size + 1); + retView[0] = (firstOctet | 0x1F); + + if (!sizeOnly) { + for (let i = 0; i < (size - 1); i++) + retView[i + 1] = encodedView[i] | 0x80; + + retView[size] = encodedView[size - 1]; + } + + return retView.buffer; + } + + const retView = new Uint8Array(this.valueHexView.byteLength + 1); + + retView[0] = (firstOctet | 0x1F); + + if (!sizeOnly) { + const curView = this.valueHexView; + + for (let i = 0; i < (curView.length - 1); i++) + retView[i + 1] = curView[i] | 0x80; + + retView[this.valueHexView.byteLength] = curView[curView.length - 1]; + } + + return retView.buffer; + } + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + const inputView = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + + // Basic check for parameters + if (!checkBufferParams(this, inputView, inputOffset, inputLength)) { + return -1; + } + + // Getting Uint8Array from ArrayBuffer + const intBuffer = inputView.subarray(inputOffset, inputOffset + inputLength); + + // Initial checks + if (intBuffer.length === 0) { + this.error = "Zero buffer length"; + + return -1; + } + + //#region Find tag class + const tagClassMask = intBuffer[0] & 0xC0; + + switch (tagClassMask) { + case 0x00: + this.tagClass = (1); // UNIVERSAL + break; + case 0x40: + this.tagClass = (2); // APPLICATION + break; + case 0x80: + this.tagClass = (3); // CONTEXT-SPECIFIC + break; + case 0xC0: + this.tagClass = (4); // PRIVATE + break; + default: + this.error = "Unknown tag class"; + + return -1; + } + //#endregion + // Find it's constructed or not + this.isConstructed = (intBuffer[0] & 0x20) === 0x20; + + // Find tag number + this.isHexOnly = false; + const tagNumberMask = intBuffer[0] & 0x1F; + + if (tagNumberMask !== 0x1F) { + // Simple case (tag number < 31) + this.tagNumber = (tagNumberMask); + this.blockLength = 1; + } else { + // Tag number bigger or equal to 31 + let count = 1; + + let intTagNumberBuffer = this.valueHexView = new Uint8Array(255); + let tagNumberBufferMaxLength = 255; + + while (intBuffer[count] & 0x80) { + intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F; + count++; + + if (count >= intBuffer.length) { + this.error = "End of input reached before message was fully decoded"; + + return -1; + } + + // In case if tag number length is greater than 255 bytes (rare but possible case) + if (count === tagNumberBufferMaxLength) { + tagNumberBufferMaxLength += 255; + + const tempBufferView = new Uint8Array(tagNumberBufferMaxLength); + + for (let i = 0; i < intTagNumberBuffer.length; i++) + tempBufferView[i] = intTagNumberBuffer[i]; + + intTagNumberBuffer = this.valueHexView = new Uint8Array(tagNumberBufferMaxLength); + } + } + + this.blockLength = (count + 1); + intTagNumberBuffer[count - 1] = intBuffer[count] & 0x7F; // Write last byte to buffer + + + //#region Cut buffer + const tempBufferView = new Uint8Array(count); + + for (let i = 0; i < count; i++) + tempBufferView[i] = intTagNumberBuffer[i]; + + intTagNumberBuffer = this.valueHexView = new Uint8Array(count); + intTagNumberBuffer.set(tempBufferView); + //#endregion + //#region Try to convert long tag number to short form + if (this.blockLength <= 9) + this.tagNumber = pvutils.utilFromBase(intTagNumberBuffer, 7); + else { + this.isHexOnly = true; + this.warnings.push("Tag too long, represented as hex-coded"); + } + //#endregion + } + //#endregion + //#endregion + //#region Check if constructed encoding was using for primitive type + if (((this.tagClass === 1)) && + (this.isConstructed)) { + switch (this.tagNumber) { + case 1: // Boolean + case 2: // REAL + case 5: // Null + case 6: // OBJECT IDENTIFIER + case 9: // REAL + case 13: // RELATIVE OBJECT IDENTIFIER + case 14: // Time + case 23: + case 24: + case 31: + case 32: + case 33: + case 34: + this.error = "Constructed encoding used for primitive type"; + + return -1; + default: + } + } + //#endregion + + return (inputOffset + this.blockLength); // Return current offset in input buffer + } + + public override toJSON(): LocalIdentificationBlockJson { + return { + ...super.toJSON(), + tagClass: this.tagClass, + tagNumber: this.tagNumber, + isConstructed: this.isConstructed, + }; + } +} + +export interface LocalIdentificationBlock { + /** + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueBeforeDecode: ArrayBuffer; + /** + * Binary data in ArrayBuffer representation + * + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueHex: ArrayBuffer; +}
\ No newline at end of file diff --git a/comm/third_party/asn1js/src/internals/LocalIntegerValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalIntegerValueBlock.ts new file mode 100644 index 0000000000..3a7b299caf --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalIntegerValueBlock.ts @@ -0,0 +1,330 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import * as pvutils from "pvutils"; +import { HexBlockJson, HexBlockParams, HexBlock } from "../HexBlock"; +import { IDerConvertible } from "../types"; +import { ValueBlock, ValueBlockJson, ValueBlockParams } from "../ValueBlock"; +import { powers2, digitsString } from "./constants"; + +function viewAdd(first: Uint8Array, second: Uint8Array): Uint8Array { + //#region Initial variables + const c = new Uint8Array([0]); + + const firstView = new Uint8Array(first); + const secondView = new Uint8Array(second); + + let firstViewCopy = firstView.slice(0); + const firstViewCopyLength = firstViewCopy.length - 1; + const secondViewCopy = secondView.slice(0); + const secondViewCopyLength = secondViewCopy.length - 1; + + let value = 0; + + const max = (secondViewCopyLength < firstViewCopyLength) ? firstViewCopyLength : secondViewCopyLength; + + let counter = 0; + //#endregion + for (let i = max; i >= 0; i--, counter++) { + switch (true) { + case (counter < secondViewCopy.length): + value = firstViewCopy[firstViewCopyLength - counter] + secondViewCopy[secondViewCopyLength - counter] + c[0]; + break; + default: + value = firstViewCopy[firstViewCopyLength - counter] + c[0]; + } + + c[0] = value / 10; + + switch (true) { + case (counter >= firstViewCopy.length): + firstViewCopy = pvutils.utilConcatView(new Uint8Array([value % 10]), firstViewCopy); + break; + default: + firstViewCopy[firstViewCopyLength - counter] = value % 10; + } + } + + if (c[0] > 0) + firstViewCopy = pvutils.utilConcatView(c, firstViewCopy); + + return firstViewCopy; +} + +function power2(n: number): Uint8Array { + if (n >= powers2.length) { + for (let p = powers2.length; p <= n; p++) { + const c = new Uint8Array([0]); + let digits = (powers2[p - 1]).slice(0); + + for (let i = (digits.length - 1); i >= 0; i--) { + const newValue = new Uint8Array([(digits[i] << 1) + c[0]]); + c[0] = newValue[0] / 10; + digits[i] = newValue[0] % 10; + } + + if (c[0] > 0) + digits = pvutils.utilConcatView(c, digits); + + powers2.push(digits); + } + } + + return powers2[n]; +} + +function viewSub(first: Uint8Array, second: Uint8Array): Uint8Array { + //#region Initial variables + let b = 0; + + const firstView = new Uint8Array(first); + const secondView = new Uint8Array(second); + + const firstViewCopy = firstView.slice(0); + const firstViewCopyLength = firstViewCopy.length - 1; + const secondViewCopy = secondView.slice(0); + const secondViewCopyLength = secondViewCopy.length - 1; + + let value; + + let counter = 0; + //#endregion + for (let i = secondViewCopyLength; i >= 0; i--, counter++) { + value = firstViewCopy[firstViewCopyLength - counter] - secondViewCopy[secondViewCopyLength - counter] - b; + + switch (true) { + case (value < 0): + b = 1; + firstViewCopy[firstViewCopyLength - counter] = value + 10; + break; + default: + b = 0; + firstViewCopy[firstViewCopyLength - counter] = value; + } + } + + if (b > 0) { + for (let i = (firstViewCopyLength - secondViewCopyLength + 1); i >= 0; i--, counter++) { + value = firstViewCopy[firstViewCopyLength - counter] - b; + + if (value < 0) { + b = 1; + firstViewCopy[firstViewCopyLength - counter] = value + 10; + } + else { + b = 0; + firstViewCopy[firstViewCopyLength - counter] = value; + break; + } + } + } + + return firstViewCopy.slice(); +} + +export interface ILocalIntegerValueBlock { + value: number; +} + +export interface LocalIntegerValueBlockParams extends HexBlockParams, ValueBlockParams, Partial<ILocalIntegerValueBlock> { } + +export interface LocalIntegerValueBlockJson extends HexBlockJson, ValueBlockJson { + valueDec: number; +} + +export class LocalIntegerValueBlock extends HexBlock(ValueBlock) implements IDerConvertible { + protected setValueHex(): void { + if (this.valueHexView.length >= 4) { + this.warnings.push("Too big Integer for decoding, hex only"); + this.isHexOnly = true; + this._valueDec = 0; + } else { + this.isHexOnly = false; + + if (this.valueHexView.length > 0) { + this._valueDec = pvutils.utilDecodeTC.call(this); + } + } + } + + public static override NAME = "IntegerValueBlock"; + + static { + Object.defineProperty(this.prototype, "valueHex", { + set: function (this: LocalIntegerValueBlock, v: ArrayBuffer) { + this.valueHexView = new Uint8Array(v); + + this.setValueHex(); + }, + get: function (this: LocalIntegerValueBlock) { + return this.valueHexView.slice().buffer; + }, + }); + } + + private _valueDec = 0; + + constructor({ + value, + ...parameters + }: LocalIntegerValueBlockParams = {}) { + super(parameters); + + if (parameters.valueHex) { + this.setValueHex(); + } + + if (value !== undefined) { + this.valueDec = value; + } + } + + public set valueDec(v: number) { + this._valueDec = v; + + this.isHexOnly = false; + this.valueHexView = new Uint8Array(pvutils.utilEncodeTC(v)); + } + + public get valueDec(): number { + return this._valueDec; + } + + public fromDER(inputBuffer: ArrayBuffer, inputOffset: number, inputLength: number, expectedLength = 0): number { + const offset = this.fromBER(inputBuffer, inputOffset, inputLength); + if (offset === -1) + return offset; + + const view = this.valueHexView; + + if ((view[0] === 0x00) && ((view[1] & 0x80) !== 0)) { + this.valueHexView = view.subarray(1); + } + else { + if (expectedLength !== 0) { + if (view.length < expectedLength) { + if ((expectedLength - view.length) > 1) + expectedLength = view.length + 1; + + this.valueHexView = view.subarray(expectedLength - view.length); + } + } + } + + return offset; + } + + public toDER(sizeOnly = false): ArrayBuffer { + const view = this.valueHexView; + + switch (true) { + case ((view[0] & 0x80) !== 0): + { + const updatedView = new Uint8Array(this.valueHexView.length + 1); + + updatedView[0] = 0x00; + updatedView.set(view, 1); + + this.valueHexView = updatedView; + } + break; + case ((view[0] === 0x00) && ((view[1] & 0x80) === 0)): + { + this.valueHexView = this.valueHexView.subarray(1); + } + break; + default: + } + + return this.toBER(sizeOnly); + } + + public override fromBER(inputBuffer: ArrayBuffer, inputOffset: number, inputLength: number): number { + const resultOffset = super.fromBER(inputBuffer, inputOffset, inputLength); + if (resultOffset === -1) { + return resultOffset; + } + + this.setValueHex(); + + return resultOffset; + } + + public override toBER(sizeOnly?: boolean): ArrayBuffer { + return sizeOnly + ? new ArrayBuffer(this.valueHexView.length) + : this.valueHexView.slice().buffer; + } + + public override toJSON(): LocalIntegerValueBlockJson { + return { + ...super.toJSON(), + valueDec: this.valueDec, + }; + } + + public override toString(): string { + //#region Initial variables + const firstBit = (this.valueHexView.length * 8) - 1; + + let digits = new Uint8Array((this.valueHexView.length * 8) / 3); + let bitNumber = 0; + let currentByte; + + const asn1View = this.valueHexView; + + let result = ""; + + let flag = false; + //#endregion + //#region Calculate number + for (let byteNumber = (asn1View.byteLength - 1); byteNumber >= 0; byteNumber--) { + currentByte = asn1View[byteNumber]; + + for (let i = 0; i < 8; i++) { + if ((currentByte & 1) === 1) { + switch (bitNumber) { + case firstBit: + digits = viewSub(power2(bitNumber), digits); + result = "-"; + break; + default: + digits = viewAdd(digits, power2(bitNumber)); + } + } + + bitNumber++; + currentByte >>= 1; + } + } + //#endregion + //#region Print number + for (let i = 0; i < digits.length; i++) { + if (digits[i]) + flag = true; + + if (flag) + result += digitsString.charAt(digits[i]); + } + + if (flag === false) + result += digitsString.charAt(0); + //#endregion + + return result; + } + +} + +export interface LocalIntegerValueBlock { + /** + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueBeforeDecode: ArrayBuffer; + /** + * Binary data in ArrayBuffer representation + * + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueHex: ArrayBuffer; +} diff --git a/comm/third_party/asn1js/src/internals/LocalLengthBlock.ts b/comm/third_party/asn1js/src/internals/LocalLengthBlock.ts new file mode 100644 index 0000000000..a4c7940b02 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalLengthBlock.ts @@ -0,0 +1,182 @@ +import * as pvtsutils from "pvtsutils"; +import * as pvutils from "pvutils"; +import { IBerConvertible } from "../types"; +import { EMPTY_BUFFER } from "./constants"; +import { LocalBaseBlock, LocalBaseBlockJson } from "./LocalBaseBlock"; +import { checkBufferParams } from "./utils"; + +export interface ILocalLengthBlock { + isIndefiniteForm: boolean; + longFormUsed: boolean; + length: number; +} + +export interface LocalLengthBlockParams { + lenBlock?: Partial<ILocalLengthBlock>; +} + +export interface LocalLengthBlockJson extends LocalBaseBlockJson, ILocalLengthBlock { + isIndefiniteForm: boolean; + longFormUsed: boolean; + length: number; +} + +export class LocalLengthBlock extends LocalBaseBlock implements ILocalLengthBlock, IBerConvertible { + + public static override NAME = "lengthBlock"; + + public isIndefiniteForm: boolean; + public longFormUsed: boolean; + public length: number; + + constructor({ + lenBlock = {}, + }: LocalLengthBlockParams = {}) { + super(); + + this.isIndefiniteForm = lenBlock.isIndefiniteForm ?? false; + this.longFormUsed = lenBlock.longFormUsed ?? false; + this.length = lenBlock.length ?? 0; + } + + + public fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + const view = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + // Basic check for parameters + if (!checkBufferParams(this, view, inputOffset, inputLength)) { + return -1; + } + //#region Getting Uint8Array from ArrayBuffer + const intBuffer = view.subarray(inputOffset, inputOffset + inputLength); + //#endregion + //#region Initial checks + if (intBuffer.length === 0) { + this.error = "Zero buffer length"; + + return -1; + } + + if (intBuffer[0] === 0xFF) { + this.error = "Length block 0xFF is reserved by standard"; + + return -1; + } + //#endregion + //#region Check for length form type + this.isIndefiniteForm = intBuffer[0] === 0x80; + //#endregion + //#region Stop working in case of indefinite length form + if (this.isIndefiniteForm) { + this.blockLength = 1; + + return (inputOffset + this.blockLength); + } + //#endregion + //#region Check is long form of length encoding using + this.longFormUsed = !!(intBuffer[0] & 0x80); + //#endregion + //#region Stop working in case of short form of length value + if (this.longFormUsed === false) { + this.length = (intBuffer[0]); + this.blockLength = 1; + + return (inputOffset + this.blockLength); + } + //#endregion + //#region Calculate length value in case of long form + const count = intBuffer[0] & 0x7F; + + if (count > 8) // Too big length value + { + this.error = "Too big integer"; + + return -1; + } + + if ((count + 1) > intBuffer.length) { + this.error = "End of input reached before message was fully decoded"; + + return -1; + } + + const lenOffset = inputOffset + 1; + const lengthBufferView = view.subarray(lenOffset, lenOffset + count); + + if (lengthBufferView[count - 1] === 0x00) + this.warnings.push("Needlessly long encoded length"); + + this.length = pvutils.utilFromBase(lengthBufferView, 8); + + if (this.longFormUsed && (this.length <= 127)) + this.warnings.push("Unnecessary usage of long length form"); + + this.blockLength = count + 1; + //#endregion + + return (inputOffset + this.blockLength); // Return current offset in input buffer + } + + public toBER(sizeOnly = false): ArrayBuffer { + //#region Initial variables + let retBuf: ArrayBuffer; + let retView: Uint8Array; + //#endregion + if (this.length > 127) + this.longFormUsed = true; + + if (this.isIndefiniteForm) { + retBuf = new ArrayBuffer(1); + + if (sizeOnly === false) { + retView = new Uint8Array(retBuf); + retView[0] = 0x80; + } + + return retBuf; + } + + if (this.longFormUsed) { + const encodedBuf = pvutils.utilToBase(this.length, 8); + + if (encodedBuf.byteLength > 127) { + this.error = "Too big length"; + + return (EMPTY_BUFFER); + } + + retBuf = new ArrayBuffer(encodedBuf.byteLength + 1); + + if (sizeOnly) + return retBuf; + + const encodedView = new Uint8Array(encodedBuf); + retView = new Uint8Array(retBuf); + + retView[0] = encodedBuf.byteLength | 0x80; + + for (let i = 0; i < encodedBuf.byteLength; i++) + retView[i + 1] = encodedView[i]; + + return retBuf; + } + + retBuf = new ArrayBuffer(1); + + if (sizeOnly === false) { + retView = new Uint8Array(retBuf); + + retView[0] = this.length; + } + + return retBuf; + } + + public override toJSON(): LocalLengthBlockJson { + return { + ...super.toJSON(), + isIndefiniteForm: this.isIndefiniteForm, + longFormUsed: this.longFormUsed, + length: this.length, + }; + } +} diff --git a/comm/third_party/asn1js/src/internals/LocalObjectIdentifierValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalObjectIdentifierValueBlock.ts new file mode 100644 index 0000000000..a24b9e947a --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalObjectIdentifierValueBlock.ts @@ -0,0 +1,192 @@ +import { ValueBlock, ValueBlockJson, ValueBlockParams } from "../ValueBlock"; +import { EMPTY_BUFFER, EMPTY_STRING } from "./constants"; +import * as utils from "./utils"; +import { LocalSidValueBlockJson, LocalSidValueBlock } from "./LocalSidValueBlock"; +import { IStringConvertible } from "../types"; + + +export interface ILocalObjectIdentifierValueBlock { + value: string; +} + +export interface LocalObjectIdentifierValueBlockParams extends ValueBlockParams, Partial<ILocalObjectIdentifierValueBlock> { } + +export interface LocalObjectIdentifierValueBlockJson extends ValueBlockJson, ILocalObjectIdentifierValueBlock { + sidArray: LocalSidValueBlockJson[]; +} + +export class LocalObjectIdentifierValueBlock extends ValueBlock implements IStringConvertible { + + public static override NAME = "ObjectIdentifierValueBlock"; + + public value: LocalSidValueBlock[] = []; + + constructor({ + value = EMPTY_STRING, + ...parameters + }: LocalObjectIdentifierValueBlockParams = {}) { + super(parameters); + + if (value) { + this.fromString(value); + } + } + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + let resultOffset = inputOffset; + + while (inputLength > 0) { + const sidBlock = new LocalSidValueBlock(); + resultOffset = sidBlock.fromBER(inputBuffer, resultOffset, inputLength); + if (resultOffset === -1) { + this.blockLength = 0; + this.error = sidBlock.error; + + return resultOffset; + } + + if (this.value.length === 0) + sidBlock.isFirstSid = true; + + this.blockLength += sidBlock.blockLength; + inputLength -= sidBlock.blockLength; + + this.value.push(sidBlock); + } + + return resultOffset; + } + public override toBER(sizeOnly?: boolean): ArrayBuffer { + const retBuffers: ArrayBuffer[] = []; + + for (let i = 0; i < this.value.length; i++) { + const valueBuf = this.value[i].toBER(sizeOnly); + if (valueBuf.byteLength === 0) { + this.error = this.value[i].error; + + return EMPTY_BUFFER; + } + + retBuffers.push(valueBuf); + } + + return utils.concat(retBuffers); + } + + public fromString(string: string): void { + this.value = []; // Clear existing SID values + + let pos1 = 0; + let pos2 = 0; + + let sid = ""; + + let flag = false; + + // const sids = string.split("."); + // for (const sid of sids) { + + // } + do { + pos2 = string.indexOf(".", pos1); + if (pos2 === -1) + sid = string.substring(pos1); + + else + sid = string.substring(pos1, pos2); + + pos1 = pos2 + 1; + + if (flag) { + const sidBlock = this.value[0]; + + let plus = 0; + + switch (sidBlock.valueDec) { + case 0: + break; + case 1: + plus = 40; + break; + case 2: + plus = 80; + break; + default: + this.value = []; // clear SID array + + return; + } + + const parsedSID = parseInt(sid, 10); + if (isNaN(parsedSID)) + return; + + sidBlock.valueDec = parsedSID + plus; + + flag = false; + } else { + const sidBlock = new LocalSidValueBlock(); + if ((sid as any) > Number.MAX_SAFE_INTEGER) { // TODO remove as any + utils.assertBigInt(); + const sidValue = BigInt(sid); + sidBlock.valueBigInt = sidValue; + } else { + sidBlock.valueDec = parseInt(sid, 10); + if (isNaN(sidBlock.valueDec)) + return; + } + + if (!this.value.length) { + sidBlock.isFirstSid = true; + flag = true; + } + + this.value.push(sidBlock); + } + } while (pos2 !== -1); + } + + public override toString(): string { + let result = ""; + let isHexOnly = false; + + for (let i = 0; i < this.value.length; i++) { + isHexOnly = this.value[i].isHexOnly; + + let sidStr = this.value[i].toString(); + + if (i !== 0) + result = `${result}.`; + + if (isHexOnly) { + sidStr = `{${sidStr}}`; + + if (this.value[i].isFirstSid) + result = `2.{${sidStr} - 80}`; + + else + result += sidStr; + } + + else + result += sidStr; + } + + return result; + } + + public override toJSON(): LocalObjectIdentifierValueBlockJson { + const object: LocalObjectIdentifierValueBlockJson = { + ...super.toJSON(), + value: this.toString(), + sidArray: [], + }; + + for (let i = 0; i < this.value.length; i++) { + object.sidArray.push(this.value[i].toJSON()); + } + + return object; + } + +} diff --git a/comm/third_party/asn1js/src/internals/LocalOctetStringValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalOctetStringValueBlock.ts new file mode 100644 index 0000000000..fb2dfd562b --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalOctetStringValueBlock.ts @@ -0,0 +1,103 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { ViewWriter } from "../ViewWriter"; +import { HexBlockJson, HexBlockParams, HexBlock } from "../HexBlock"; +import { END_OF_CONTENT_NAME, OCTET_STRING_NAME } from "./constants"; +import { LocalConstructedValueBlockParams, LocalConstructedValueBlockJson, LocalConstructedValueBlock } from "./LocalConstructedValueBlock"; +import type { OctetString } from "../OctetString"; + +export interface ILocalOctetStringValueBlock { + isConstructed: boolean; +} + +export interface LocalOctetStringValueBlockParams extends HexBlockParams, LocalConstructedValueBlockParams, Partial<ILocalOctetStringValueBlock> { + value?: OctetString[]; +} + +export interface LocalOctetStringValueBlockJson extends HexBlockJson, LocalConstructedValueBlockJson, ILocalOctetStringValueBlock { } + +export class LocalOctetStringValueBlock extends HexBlock(LocalConstructedValueBlock) { + + public static override NAME = "OctetStringValueBlock"; + + public isConstructed: boolean; + + constructor({ + isConstructed = false, + ...parameters + }: LocalOctetStringValueBlockParams = {}) { + super(parameters); + + this.isConstructed = isConstructed; + } + + public override fromBER(inputBuffer: ArrayBuffer, inputOffset: number, inputLength: number): number { + let resultOffset = 0; + + if (this.isConstructed) { + this.isHexOnly = false; + + resultOffset = LocalConstructedValueBlock.prototype.fromBER.call(this, inputBuffer, inputOffset, inputLength); + if (resultOffset === -1) + return resultOffset; + + for (let i = 0; i < this.value.length; i++) { + const currentBlockName = (this.value[i].constructor as typeof LocalOctetStringValueBlock).NAME; + + if (currentBlockName === END_OF_CONTENT_NAME) { + if (this.isIndefiniteForm) + break; + else { + this.error = "EndOfContent is unexpected, OCTET STRING may consists of OCTET STRINGs only"; + + return -1; + } + } + + if (currentBlockName !== OCTET_STRING_NAME) { + this.error = "OCTET STRING may consists of OCTET STRINGs only"; + + return -1; + } + } + } else { + this.isHexOnly = true; + + resultOffset = super.fromBER(inputBuffer, inputOffset, inputLength); + this.blockLength = inputLength; + } + + return resultOffset; + } + + public override toBER(sizeOnly?: boolean, writer?: ViewWriter): ArrayBuffer { + if (this.isConstructed) + return LocalConstructedValueBlock.prototype.toBER.call(this, sizeOnly, writer); + + return sizeOnly + ? new ArrayBuffer(this.valueHexView.byteLength) + : this.valueHexView.slice().buffer; + } + + public override toJSON(): LocalOctetStringValueBlockJson { + return { + ...super.toJSON(), + isConstructed: this.isConstructed, + } as LocalOctetStringValueBlockJson; + } + +} + +export interface LocalOctetStringValueBlock { + /** + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueBeforeDecode: ArrayBuffer; + /** + * Binary data in ArrayBuffer representation + * + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueHex: ArrayBuffer; +} diff --git a/comm/third_party/asn1js/src/internals/LocalPrimitiveValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalPrimitiveValueBlock.ts new file mode 100644 index 0000000000..7fe2408b96 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalPrimitiveValueBlock.ts @@ -0,0 +1,36 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { HexBlock, HexBlockJson, HexBlockParams } from "../HexBlock"; +import { ValueBlock, ValueBlockJson, ValueBlockParams } from "../ValueBlock"; + +export interface LocalPrimitiveValueBlockParams extends HexBlockParams, ValueBlockParams { } +export interface LocalPrimitiveValueBlockJson extends HexBlockJson, ValueBlockJson { } + +export class LocalPrimitiveValueBlock extends HexBlock(ValueBlock) { + + public static override NAME = "PrimitiveValueBlock"; + + constructor({ + isHexOnly = true, + ...parameters + }: LocalPrimitiveValueBlockParams = {}) { + super(parameters); + + this.isHexOnly = isHexOnly; + } + +} + +export interface LocalPrimitiveValueBlock { + /** + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueBeforeDecode: ArrayBuffer; + /** + * Binary data in ArrayBuffer representation + * + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueHex: ArrayBuffer; +} diff --git a/comm/third_party/asn1js/src/internals/LocalRelativeObjectIdentifierValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalRelativeObjectIdentifierValueBlock.ts new file mode 100644 index 0000000000..13237f50ec --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalRelativeObjectIdentifierValueBlock.ts @@ -0,0 +1,140 @@ +import { ViewWriter } from "../ViewWriter"; +import { ValueBlock, ValueBlockJson, ValueBlockParams } from "../ValueBlock"; +import { EMPTY_BUFFER, EMPTY_STRING } from "./constants"; +import * as utils from "./utils"; +import { LocalRelativeSidValueBlockJson, LocalRelativeSidValueBlock } from "./LocalRelativeSidValueBlock"; +import { IStringConvertible } from "../types"; + +export interface ILocalRelativeObjectIdentifierValueBlock { + value: string; +} + +export interface LocalRelativeObjectIdentifierValueBlockParams extends ValueBlockParams, Partial<ILocalRelativeObjectIdentifierValueBlock> { } + +export interface LocalRelativeObjectIdentifierValueBlockJson extends ValueBlockJson, ILocalRelativeObjectIdentifierValueBlock { + sidArray: LocalRelativeSidValueBlockJson[]; +} + +export class LocalRelativeObjectIdentifierValueBlock extends ValueBlock implements IStringConvertible { + + public static override NAME = "RelativeObjectIdentifierValueBlock"; + + public value: LocalRelativeSidValueBlock[] = []; + + constructor({ + value = EMPTY_STRING, + ...parameters + }: LocalRelativeObjectIdentifierValueBlockParams = {}) { + super(parameters); + + if (value) { + this.fromString(value); + } + } + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + let resultOffset = inputOffset; + + while (inputLength > 0) { + const sidBlock = new LocalRelativeSidValueBlock(); + resultOffset = sidBlock.fromBER(inputBuffer, resultOffset, inputLength); + if (resultOffset === -1) { + this.blockLength = 0; + this.error = sidBlock.error; + + return resultOffset; + } + + this.blockLength += sidBlock.blockLength; + inputLength -= sidBlock.blockLength; + + this.value.push(sidBlock); + } + + return resultOffset; + } + + public override toBER(sizeOnly?: boolean, writer?: ViewWriter): ArrayBuffer { + const retBuffers: ArrayBuffer[] = []; + + for (let i = 0; i < this.value.length; i++) { + const valueBuf = this.value[i].toBER(sizeOnly); + if (valueBuf.byteLength === 0) { + this.error = this.value[i].error; + + return EMPTY_BUFFER; + } + + retBuffers.push(valueBuf); + } + + return utils.concat(retBuffers); + } + + public fromString(string: string): boolean { + this.value = []; // Clear existing SID values + + let pos1 = 0; + let pos2 = 0; + + let sid = ""; + + do { + pos2 = string.indexOf(".", pos1); + if (pos2 === -1) + sid = string.substring(pos1); + + else + sid = string.substring(pos1, pos2); + + pos1 = pos2 + 1; + + const sidBlock = new LocalRelativeSidValueBlock(); + sidBlock.valueDec = parseInt(sid, 10); + if (isNaN(sidBlock.valueDec)) + return true; + + this.value.push(sidBlock); + + } while (pos2 !== -1); + + return true; + } + + public override toString(): string { + let result = ""; + let isHexOnly = false; + + for (let i = 0; i < this.value.length; i++) { + isHexOnly = this.value[i].isHexOnly; + + let sidStr = this.value[i].toString(); + + if (i !== 0) + result = `${result}.`; + + if (isHexOnly) { + sidStr = `{${sidStr}}`; + result += sidStr; + } + else + result += sidStr; + } + + return result; + } + + public override toJSON(): LocalRelativeObjectIdentifierValueBlockJson { + const object: LocalRelativeObjectIdentifierValueBlockJson = { + ...super.toJSON(), + value: this.toString(), + sidArray: [], + }; + + for (let i = 0; i < this.value.length; i++) + object.sidArray.push(this.value[i].toJSON()); + + return object; + } + +} diff --git a/comm/third_party/asn1js/src/internals/LocalRelativeSidValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalRelativeSidValueBlock.ts new file mode 100644 index 0000000000..3a10c617aa --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalRelativeSidValueBlock.ts @@ -0,0 +1,140 @@ +import * as pvtsutils from "pvtsutils"; +import * as pvutils from "pvutils"; +import { HexBlockJson, HexBlockParams, HexBlock } from "../HexBlock"; +import { ValueBlockJson, ValueBlockParams } from "../ValueBlock"; +import { LocalBaseBlock } from "./LocalBaseBlock"; +import { EMPTY_BUFFER } from "./constants"; +import { checkBufferParams } from "./utils"; + +export interface ILocalRelativeSidValueBlock { + valueDec: number; +} + +export interface LocalRelativeSidValueBlockParams extends HexBlockParams, ValueBlockParams, Partial<ILocalRelativeSidValueBlock> { } + +export interface LocalRelativeSidValueBlockJson extends HexBlockJson, ValueBlockJson, ILocalRelativeSidValueBlock { } + +export class LocalRelativeSidValueBlock extends HexBlock(LocalBaseBlock) implements ILocalRelativeSidValueBlock { + + public static override NAME = "relativeSidBlock"; + + public valueDec: number; + + constructor({ + valueDec = 0, + ...parameters + }: LocalRelativeSidValueBlockParams = {}) { + super(parameters); + + this.valueDec = valueDec; + } + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + if (inputLength === 0) + return inputOffset; + + const inputView = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + + // Basic check for parameters + if (!checkBufferParams(this, inputView, inputOffset, inputLength)) + return -1; + + const intBuffer = inputView.subarray(inputOffset, inputOffset + inputLength); + + this.valueHexView = new Uint8Array(inputLength); + + for (let i = 0; i < inputLength; i++) { + this.valueHexView[i] = intBuffer[i] & 0x7F; + + this.blockLength++; + + if ((intBuffer[i] & 0x80) === 0x00) + break; + } + + //#region Adjust size of valueHex buffer + const tempView = new Uint8Array(this.blockLength); + + for (let i = 0; i < this.blockLength; i++) + tempView[i] = this.valueHexView[i]; + + this.valueHexView = tempView; + //#endregion + if ((intBuffer[this.blockLength - 1] & 0x80) !== 0x00) { + this.error = "End of input reached before message was fully decoded"; + + return -1; + } + + if (this.valueHexView[0] === 0x00) + this.warnings.push("Needlessly long format of SID encoding"); + + if (this.blockLength <= 8) + this.valueDec = pvutils.utilFromBase(this.valueHexView, 7); + else { + this.isHexOnly = true; + this.warnings.push("Too big SID for decoding, hex only"); + } + + return (inputOffset + this.blockLength); + } + + public override toBER(sizeOnly?: boolean): ArrayBuffer { + if (this.isHexOnly) { + if (sizeOnly) + return (new ArrayBuffer(this.valueHexView.byteLength)); + + const curView = this.valueHexView; + + const retView = new Uint8Array(this.blockLength); + + for (let i = 0; i < (this.blockLength - 1); i++) + retView[i] = curView[i] | 0x80; + + retView[this.blockLength - 1] = curView[this.blockLength - 1]; + + return retView.buffer; + } + + const encodedBuf = pvutils.utilToBase(this.valueDec, 7); + if (encodedBuf.byteLength === 0) { + this.error = "Error during encoding SID value"; + + return EMPTY_BUFFER; + } + + const retView = new Uint8Array(encodedBuf.byteLength); + + if (!sizeOnly) { + const encodedView = new Uint8Array(encodedBuf); + const len = encodedBuf.byteLength - 1; + + for (let i = 0; i < len; i++) + retView[i] = encodedView[i] | 0x80; + + retView[len] = encodedView[len]; + } + + return retView.buffer; + } + + public override toString(): string { + let result = ""; + + if (this.isHexOnly) + result = pvtsutils.Convert.ToHex(this.valueHexView); + else { + result = this.valueDec.toString(); + } + + return result; + } + + public override toJSON(): LocalRelativeSidValueBlockJson { + return { + ...super.toJSON(), + valueDec: this.valueDec, + }; + } + +} diff --git a/comm/third_party/asn1js/src/internals/LocalSidValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalSidValueBlock.ts new file mode 100644 index 0000000000..a9a45ba359 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalSidValueBlock.ts @@ -0,0 +1,197 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import * as pvtsutils from "pvtsutils"; +import * as pvutils from "pvutils"; +import { HexBlockJson, HexBlockParams, HexBlock } from "../HexBlock"; +import { ValueBlock, ValueBlockJson, ValueBlockParams } from "../ValueBlock"; +import { EMPTY_BUFFER } from "./constants"; +import * as utils from "./utils"; + +export interface ILocalSidValueBlock { + valueDec: number; + isFirstSid: boolean; +} + +export interface LocalSidValueBlockParams extends HexBlockParams, ValueBlockParams, Partial<ILocalSidValueBlock> { } + +export interface LocalSidValueBlockJson extends HexBlockJson, ValueBlockJson, ILocalSidValueBlock { } + +export class LocalSidValueBlock extends HexBlock(ValueBlock) implements ILocalSidValueBlock { + + public static override NAME = "sidBlock"; + + public valueDec: number; + public isFirstSid: boolean; + + constructor({ + valueDec = -1, + isFirstSid = false, + ...parameters + }: LocalSidValueBlockParams = {}) { + super(parameters); + + this.valueDec = valueDec; + this.isFirstSid = isFirstSid; + } + + public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number { + if (!inputLength) { + return inputOffset; + } + const inputView = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + + // Basic check for parameters + if (!utils.checkBufferParams(this, inputView, inputOffset, inputLength)) { + return -1; + } + + const intBuffer = inputView.subarray(inputOffset, inputOffset + inputLength); + + this.valueHexView = new Uint8Array(inputLength); + + for (let i = 0; i < inputLength; i++) { + this.valueHexView[i] = intBuffer[i] & 0x7F; + + this.blockLength++; + + if ((intBuffer[i] & 0x80) === 0x00) + break; + } + + //#region Adjust size of valueHex buffer + const tempView = new Uint8Array(this.blockLength); + + for (let i = 0; i < this.blockLength; i++) { + tempView[i] = this.valueHexView[i]; + } + + this.valueHexView = tempView; + //#endregion + + if ((intBuffer[this.blockLength - 1] & 0x80) !== 0x00) { + this.error = "End of input reached before message was fully decoded"; + + return -1; + } + + if (this.valueHexView[0] === 0x00) + this.warnings.push("Needlessly long format of SID encoding"); + + if (this.blockLength <= 8) + this.valueDec = pvutils.utilFromBase(this.valueHexView, 7); + else { + this.isHexOnly = true; + this.warnings.push("Too big SID for decoding, hex only"); + } + + return (inputOffset + this.blockLength); + } + + public set valueBigInt(value: bigint) { + + utils.assertBigInt(); + + let bits = BigInt(value).toString(2); + while (bits.length % 7) { + bits = "0" + bits; + } + const bytes = new Uint8Array(bits.length / 7); + for (let i = 0; i < bytes.length; i++) { + bytes[i] = parseInt(bits.slice(i * 7, i * 7 + 7), 2) + (i + 1 < bytes.length ? 0x80 : 0); + } + this.fromBER(bytes.buffer, 0, bytes.length); + } + + public override toBER(sizeOnly?: boolean): ArrayBuffer { + if (this.isHexOnly) { + if (sizeOnly) + return (new ArrayBuffer(this.valueHexView.byteLength)); + + const curView = this.valueHexView; + const retView = new Uint8Array(this.blockLength); + + for (let i = 0; i < (this.blockLength - 1); i++) + retView[i] = curView[i] | 0x80; + + retView[this.blockLength - 1] = curView[this.blockLength - 1]; + + return retView.buffer; + } + + const encodedBuf = pvutils.utilToBase(this.valueDec, 7); + if (encodedBuf.byteLength === 0) { + this.error = "Error during encoding SID value"; + + return EMPTY_BUFFER; + } + + const retView = new Uint8Array(encodedBuf.byteLength); + + if (!sizeOnly) { + const encodedView = new Uint8Array(encodedBuf); + const len = encodedBuf.byteLength - 1; + + for (let i = 0; i < len; i++) + retView[i] = encodedView[i] | 0x80; + + retView[len] = encodedView[len]; + } + + return retView; + } + + public override toString(): string { + let result = ""; + + if (this.isHexOnly) + result = pvtsutils.Convert.ToHex(this.valueHexView); + else { + if (this.isFirstSid) { + let sidValue = this.valueDec; + + if (this.valueDec <= 39) + result = "0."; + else { + if (this.valueDec <= 79) { + result = "1."; + sidValue -= 40; + } + else { + result = "2."; + sidValue -= 80; + } + } + + result += sidValue.toString(); + } + + else + result = this.valueDec.toString(); + } + + return result; + } + + public override toJSON(): LocalSidValueBlockJson { + return { + ...super.toJSON(), + valueDec: this.valueDec, + isFirstSid: this.isFirstSid, + }; + } + +} + +export interface LocalSidValueBlock { + /** + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueBeforeDecode: ArrayBuffer; + /** + * Binary data in ArrayBuffer representation + * + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueHex: ArrayBuffer; +} diff --git a/comm/third_party/asn1js/src/internals/LocalSimpleStringBlock.ts b/comm/third_party/asn1js/src/internals/LocalSimpleStringBlock.ts new file mode 100644 index 0000000000..a52c9e2898 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalSimpleStringBlock.ts @@ -0,0 +1,34 @@ +import * as pvtsutils from "pvtsutils"; +import { BaseBlockParams } from "../BaseBlock"; +import { BaseStringBlock } from "../BaseStringBlock"; +import { LocalSimpleStringValueBlock, LocalSimpleStringValueBlockJson, LocalSimpleStringValueBlockParams } from "./LocalSimpleStringValueBlock"; + +export interface LocalSimpleStringBlockParams extends BaseBlockParams, LocalSimpleStringValueBlockParams { } +export type LocalSimpleStringBlockJson = LocalSimpleStringValueBlockJson; + +export class LocalSimpleStringBlock extends BaseStringBlock<LocalSimpleStringValueBlock, LocalSimpleStringValueBlockJson> { + + public static override NAME = "SIMPLE STRING"; + + constructor({ + ...parameters + }: LocalSimpleStringBlockParams = {}) { + super(parameters, LocalSimpleStringValueBlock); + } + + public override fromBuffer(inputBuffer: ArrayBuffer | Uint8Array): void { + this.valueBlock.value = String.fromCharCode.apply(null, pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer) as unknown as number[]); + } + + public fromString(inputString: string): void { + const strLen = inputString.length; + + const view = this.valueBlock.valueHexView = new Uint8Array(strLen); + + for (let i = 0; i < strLen; i++) + view[i] = inputString.charCodeAt(i); + + this.valueBlock.value = inputString; + } + +} diff --git a/comm/third_party/asn1js/src/internals/LocalSimpleStringValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalSimpleStringValueBlock.ts new file mode 100644 index 0000000000..f2ee09a8a3 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalSimpleStringValueBlock.ts @@ -0,0 +1,11 @@ +import { ILocalStringValueBlock, LocalStringValueBlockParams, LocalStringValueBlockJson, LocalStringValueBlock } from "./LocalStringValueBlock"; + +export type ILocalSimpleStringValueBlock = ILocalStringValueBlock; +export type LocalSimpleStringValueBlockParams = LocalStringValueBlockParams; +export type LocalSimpleStringValueBlockJson = LocalStringValueBlockJson; + +export class LocalSimpleStringValueBlock extends LocalStringValueBlock { + + public static override NAME = "SimpleStringValueBlock"; + +} diff --git a/comm/third_party/asn1js/src/internals/LocalStringValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalStringValueBlock.ts new file mode 100644 index 0000000000..dfd0ee19e3 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalStringValueBlock.ts @@ -0,0 +1,52 @@ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +import { HexBlockJson, HexBlockParams, HexBlock } from "../HexBlock"; +import { ValueBlock, ValueBlockJson, ValueBlockParams } from "../ValueBlock"; +import { EMPTY_STRING } from "./constants"; +import { LocalUtf8StringValueBlockParams, LocalUtf8StringValueBlockJson } from "./LocalUtf8StringValueBlock"; + +export interface ILocalStringValueBlock { + value: string; +} + +export interface LocalStringValueBlockParams extends Omit<HexBlockParams, "isHexOnly">, ValueBlockParams, Partial<ILocalStringValueBlock> { } + +export interface LocalStringValueBlockJson extends HexBlockJson, ValueBlockJson, ILocalStringValueBlock { } + +export abstract class LocalStringValueBlock extends HexBlock(ValueBlock) implements ILocalStringValueBlock { + + public static override NAME = "StringValueBlock"; + + public value: string; + + constructor({ + ...parameters + }: LocalUtf8StringValueBlockParams = {}) { + super(parameters); + + this.isHexOnly = true; + this.value = EMPTY_STRING; // String representation of decoded ArrayBuffer + } + + public override toJSON(): LocalUtf8StringValueBlockJson { + return { + ...super.toJSON(), + value: this.value, + }; + } + +} + +export interface LocalStringValueBlock { + /** + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueBeforeDecode: ArrayBuffer; + /** + * Binary data in ArrayBuffer representation + * + * @deprecated since version 3.0.0 + */ + // @ts-ignore + valueHex: ArrayBuffer; +} diff --git a/comm/third_party/asn1js/src/internals/LocalUniversalStringValueBlockParams.ts b/comm/third_party/asn1js/src/internals/LocalUniversalStringValueBlockParams.ts new file mode 100644 index 0000000000..6b3b09359a --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalUniversalStringValueBlockParams.ts @@ -0,0 +1,45 @@ +import * as pvutils from "pvutils"; +import { LocalSimpleStringBlock, LocalSimpleStringBlockJson, LocalSimpleStringBlockParams } from "./LocalSimpleStringBlock"; + +export type LocalUniversalStringValueBlockParams = LocalSimpleStringBlockParams; +export type LocalUniversalStringValueBlockJson = LocalSimpleStringBlockJson; + +export class LocalUniversalStringValueBlock extends LocalSimpleStringBlock { + + public static override NAME = "UniversalStringValueBlock"; + + public override fromBuffer(inputBuffer: ArrayBuffer | Uint8Array): void { + const copyBuffer = ArrayBuffer.isView(inputBuffer) ? inputBuffer.slice().buffer : inputBuffer.slice(0); + const valueView = new Uint8Array(copyBuffer); + + for (let i = 0; i < valueView.length; i += 4) { + valueView[i] = valueView[i + 3]; + valueView[i + 1] = valueView[i + 2]; + valueView[i + 2] = 0x00; + valueView[i + 3] = 0x00; + } + + this.valueBlock.value = String.fromCharCode.apply(null, new Uint32Array(copyBuffer) as unknown as number[]); + } + + public override fromString(inputString: string): void { + const strLength = inputString.length; + + const valueHexView = this.valueBlock.valueHexView = new Uint8Array(strLength * 4); + + for (let i = 0; i < strLength; i++) { + const codeBuf = pvutils.utilToBase(inputString.charCodeAt(i), 8); + const codeView = new Uint8Array(codeBuf); + if (codeView.length > 4) + continue; + + const dif = 4 - codeView.length; + + for (let j = (codeView.length - 1); j >= 0; j--) + valueHexView[i * 4 + j + dif] = codeView[j]; + } + + this.valueBlock.value = inputString; + } + +} diff --git a/comm/third_party/asn1js/src/internals/LocalUtf8StringValueBlock.ts b/comm/third_party/asn1js/src/internals/LocalUtf8StringValueBlock.ts new file mode 100644 index 0000000000..7d578d8950 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/LocalUtf8StringValueBlock.ts @@ -0,0 +1,27 @@ +import * as pvtsutils from "pvtsutils"; +import { LocalSimpleStringBlock, LocalSimpleStringBlockJson, LocalSimpleStringBlockParams } from "./LocalSimpleStringBlock"; + +export type LocalUtf8StringValueBlockParams = LocalSimpleStringBlockParams; +export type LocalUtf8StringValueBlockJson = LocalSimpleStringBlockJson; + +export class LocalUtf8StringValueBlock extends LocalSimpleStringBlock { + + public static override NAME = "Utf8StringValueBlock"; + + public override fromBuffer(inputBuffer: ArrayBuffer | Uint8Array): void { + this.valueBlock.valueHexView = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer); + try { + this.valueBlock.value = pvtsutils.Convert.ToUtf8String(inputBuffer); + } + catch (ex) { + this.warnings.push(`Error during "decodeURIComponent": ${ex}, using raw string`); + this.valueBlock.value = pvtsutils.Convert.ToBinary(inputBuffer); + } + } + + public override fromString(inputString: string): void { + this.valueBlock.valueHexView = new Uint8Array(pvtsutils.Convert.FromUtf8String(inputString)); + this.valueBlock.value = inputString; + } + +} diff --git a/comm/third_party/asn1js/src/internals/constants.ts b/comm/third_party/asn1js/src/internals/constants.ts new file mode 100644 index 0000000000..beb0bd9eb8 --- /dev/null +++ b/comm/third_party/asn1js/src/internals/constants.ts @@ -0,0 +1,20 @@ +// Declaration of global variables + +export const powers2 = [new Uint8Array([1])]; +export const digitsString = "0123456789"; +export const NAME = "name"; +export const VALUE_HEX_VIEW = "valueHexView"; +export const IS_HEX_ONLY = "isHexOnly"; +export const ID_BLOCK = "idBlock"; +export const TAG_CLASS = "tagClass"; +export const TAG_NUMBER = "tagNumber"; +export const IS_CONSTRUCTED = "isConstructed"; +export const FROM_BER = "fromBER"; +export const TO_BER = "toBER"; +export const LOCAL = "local"; +export const EMPTY_STRING = ""; +export const EMPTY_BUFFER = new ArrayBuffer(0); +export const EMPTY_VIEW = new Uint8Array(0); +export const END_OF_CONTENT_NAME = "EndOfContent"; +export const OCTET_STRING_NAME = "OCTET STRING"; +export const BIT_STRING_NAME = "BIT STRING"; diff --git a/comm/third_party/asn1js/src/internals/utils.ts b/comm/third_party/asn1js/src/internals/utils.ts new file mode 100644 index 0000000000..84d1f3164f --- /dev/null +++ b/comm/third_party/asn1js/src/internals/utils.ts @@ -0,0 +1,81 @@ +// Utility functions + +import type { LocalBaseBlock } from "./LocalBaseBlock"; + +/** + * Throws an exception if BigInt is not supported + * @throws Throws Error if BigInt is not supported + */ +export function assertBigInt(): void { + if (typeof BigInt === "undefined") { + throw new Error("BigInt is not defined. Your environment doesn't implement BigInt."); + } +} + +/** + * Concatenates buffers from the list + * @param buffers List of buffers + * @returns Concatenated buffer + */ +export function concat(buffers: ArrayBuffer[]): ArrayBuffer { + let outputLength = 0; + let prevLength = 0; + + // Calculate output length + for (let i = 0; i < buffers.length; i++) { + const buffer = buffers[i]; + outputLength += buffer.byteLength; + } + + const retView = new Uint8Array(outputLength); + + for (let i = 0; i < buffers.length; i++) { + const buffer = buffers[i]; + retView.set(new Uint8Array(buffer), prevLength); + prevLength += buffer.byteLength; + } + + return retView.buffer; +} + +/** + * Check input "Uint8Array" for common functions + * @param baseBlock + * @param inputBuffer + * @param inputOffset + * @param inputLength + * @returns + */ +export function checkBufferParams(baseBlock: LocalBaseBlock, inputBuffer: Uint8Array, inputOffset: number, inputLength: number): boolean { + if (!(inputBuffer instanceof Uint8Array)) { + baseBlock.error = "Wrong parameter: inputBuffer must be 'Uint8Array'"; + + return false; + } + + if (!inputBuffer.byteLength) { + baseBlock.error = "Wrong parameter: inputBuffer has zero length"; + + return false; + } + + if (inputOffset < 0) { + baseBlock.error = "Wrong parameter: inputOffset less than zero"; + + return false; + } + + if (inputLength < 0) { + baseBlock.error = "Wrong parameter: inputLength less than zero"; + + return false; + } + + if ((inputBuffer.byteLength - inputOffset - inputLength) < 0) { + baseBlock.error = "End of input reached before message was fully decoded (inconsistent offset and length values)"; + + return false; + } + + return true; +}
\ No newline at end of file |