summaryrefslogtreecommitdiffstats
path: root/comm/third_party/asn1js/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 17:32:43 +0000
commit6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch)
treea68f146d7fa01f0134297619fbe7e33db084e0aa /comm/third_party/asn1js/src
parentInitial commit. (diff)
downloadthunderbird-upstream.tar.xz
thunderbird-upstream.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')
-rw-r--r--comm/third_party/asn1js/src/Any.ts22
-rw-r--r--comm/third_party/asn1js/src/BaseBlock.ts186
-rw-r--r--comm/third_party/asn1js/src/BaseStringBlock.ts74
-rw-r--r--comm/third_party/asn1js/src/BitString.ts64
-rw-r--r--comm/third_party/asn1js/src/BmpString.ts23
-rw-r--r--comm/third_party/asn1js/src/Boolean.ts43
-rw-r--r--comm/third_party/asn1js/src/CharacterString.ts22
-rw-r--r--comm/third_party/asn1js/src/Choice.ts22
-rw-r--r--comm/third_party/asn1js/src/Constructed.ts61
-rw-r--r--comm/third_party/asn1js/src/DATE.ts22
-rw-r--r--comm/third_party/asn1js/src/DateTime.ts22
-rw-r--r--comm/third_party/asn1js/src/Duration.ts21
-rw-r--r--comm/third_party/asn1js/src/EndOfContent.ts23
-rw-r--r--comm/third_party/asn1js/src/Enumerated.ts22
-rw-r--r--comm/third_party/asn1js/src/GeneralString.ts22
-rw-r--r--comm/third_party/asn1js/src/GeneralizedTime.ts262
-rw-r--r--comm/third_party/asn1js/src/GraphicString.ts22
-rw-r--r--comm/third_party/asn1js/src/HexBlock.ts110
-rw-r--r--comm/third_party/asn1js/src/IA5String.ts22
-rw-r--r--comm/third_party/asn1js/src/Integer.ts103
-rw-r--r--comm/third_party/asn1js/src/Null.ts65
-rw-r--r--comm/third_party/asn1js/src/NumericString.ts22
-rw-r--r--comm/third_party/asn1js/src/ObjectIdentifier.ts53
-rw-r--r--comm/third_party/asn1js/src/OctetString.ts103
-rw-r--r--comm/third_party/asn1js/src/Primitive.ts22
-rw-r--r--comm/third_party/asn1js/src/PrintableString.ts22
-rw-r--r--comm/third_party/asn1js/src/RawData.ts51
-rw-r--r--comm/third_party/asn1js/src/RelativeObjectIdentifier.ts54
-rw-r--r--comm/third_party/asn1js/src/Repeated.ts26
-rw-r--r--comm/third_party/asn1js/src/Sequence.ts22
-rw-r--r--comm/third_party/asn1js/src/Set.ts22
-rw-r--r--comm/third_party/asn1js/src/TIME.ts22
-rw-r--r--comm/third_party/asn1js/src/TeletexString.ts22
-rw-r--r--comm/third_party/asn1js/src/TimeOfDay.ts22
-rw-r--r--comm/third_party/asn1js/src/TypeStore.ts71
-rw-r--r--comm/third_party/asn1js/src/UTCTime.ts172
-rw-r--r--comm/third_party/asn1js/src/UniversalString.ts24
-rw-r--r--comm/third_party/asn1js/src/Utf8String.ts24
-rw-r--r--comm/third_party/asn1js/src/ValueBlock.ts21
-rw-r--r--comm/third_party/asn1js/src/VideotexString.ts22
-rw-r--r--comm/third_party/asn1js/src/ViewWriter.ts22
-rw-r--r--comm/third_party/asn1js/src/VisibleString.ts22
-rw-r--r--comm/third_party/asn1js/src/index.ts59
-rw-r--r--comm/third_party/asn1js/src/internals/LocalBaseBlock.ts93
-rw-r--r--comm/third_party/asn1js/src/internals/LocalBitStringValueBlock.ts168
-rw-r--r--comm/third_party/asn1js/src/internals/LocalBmpStringValueBlock.ts21
-rw-r--r--comm/third_party/asn1js/src/internals/LocalBooleanValueBlock.ts96
-rw-r--r--comm/third_party/asn1js/src/internals/LocalConstructedValueBlock.ts128
-rw-r--r--comm/third_party/asn1js/src/internals/LocalEndOfContentValueBlock.ts16
-rw-r--r--comm/third_party/asn1js/src/internals/LocalIdentificationBlock.ts280
-rw-r--r--comm/third_party/asn1js/src/internals/LocalIntegerValueBlock.ts330
-rw-r--r--comm/third_party/asn1js/src/internals/LocalLengthBlock.ts182
-rw-r--r--comm/third_party/asn1js/src/internals/LocalObjectIdentifierValueBlock.ts192
-rw-r--r--comm/third_party/asn1js/src/internals/LocalOctetStringValueBlock.ts103
-rw-r--r--comm/third_party/asn1js/src/internals/LocalPrimitiveValueBlock.ts36
-rw-r--r--comm/third_party/asn1js/src/internals/LocalRelativeObjectIdentifierValueBlock.ts140
-rw-r--r--comm/third_party/asn1js/src/internals/LocalRelativeSidValueBlock.ts140
-rw-r--r--comm/third_party/asn1js/src/internals/LocalSidValueBlock.ts197
-rw-r--r--comm/third_party/asn1js/src/internals/LocalSimpleStringBlock.ts34
-rw-r--r--comm/third_party/asn1js/src/internals/LocalSimpleStringValueBlock.ts11
-rw-r--r--comm/third_party/asn1js/src/internals/LocalStringValueBlock.ts52
-rw-r--r--comm/third_party/asn1js/src/internals/LocalUniversalStringValueBlockParams.ts45
-rw-r--r--comm/third_party/asn1js/src/internals/LocalUtf8StringValueBlock.ts27
-rw-r--r--comm/third_party/asn1js/src/internals/constants.ts20
-rw-r--r--comm/third_party/asn1js/src/internals/utils.ts81
-rw-r--r--comm/third_party/asn1js/src/parser.ts301
-rw-r--r--comm/third_party/asn1js/src/schema.ts475
-rw-r--r--comm/third_party/asn1js/src/types.ts62
68 files changed, 5363 insertions, 0 deletions
diff --git a/comm/third_party/asn1js/src/Any.ts b/comm/third_party/asn1js/src/Any.ts
new file mode 100644
index 0000000000..36db46cc2e
--- /dev/null
+++ b/comm/third_party/asn1js/src/Any.ts
@@ -0,0 +1,22 @@
+import { EMPTY_STRING } from "./internals/constants";
+
+export interface IAny {
+ name: string;
+ optional: boolean;
+}
+
+export type AnyParams = Partial<IAny>;
+
+export class Any implements IAny {
+
+ public name: string;
+ public optional: boolean;
+
+ constructor({
+ name = EMPTY_STRING, optional = false,
+ }: AnyParams = {}) {
+ this.name = name;
+ this.optional = optional;
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/BaseBlock.ts b/comm/third_party/asn1js/src/BaseBlock.ts
new file mode 100644
index 0000000000..8a4c58528c
--- /dev/null
+++ b/comm/third_party/asn1js/src/BaseBlock.ts
@@ -0,0 +1,186 @@
+import * as pvtsutils from "pvtsutils";
+import * as pvutils from "pvutils";
+import { IBerConvertible } from "./types";
+import { LocalBaseBlockJson, LocalBaseBlockParams, LocalBaseBlock } from "./internals/LocalBaseBlock";
+import { LocalIdentificationBlock, LocalIdentificationBlockJson, LocalIdentificationBlockParams } from "./internals/LocalIdentificationBlock";
+import { LocalLengthBlock, LocalLengthBlockJson, LocalLengthBlockParams } from "./internals/LocalLengthBlock";
+import { ViewWriter } from "./ViewWriter";
+import { ValueBlock, ValueBlockJson } from "./ValueBlock";
+import { EMPTY_BUFFER, EMPTY_STRING } from "./internals/constants";
+import { typeStore } from "./TypeStore";
+
+export interface IBaseBlock {
+ name: string;
+ optional: boolean;
+ primitiveSchema?: BaseBlock;
+}
+
+export interface BaseBlockParams extends LocalBaseBlockParams, LocalIdentificationBlockParams, LocalLengthBlockParams, Partial<IBaseBlock> { }
+
+export interface ValueBlockConstructor<T extends ValueBlock = ValueBlock> {
+ new(...args: any[]): T;
+}
+
+export interface BaseBlockJson<T extends LocalBaseBlockJson = LocalBaseBlockJson> extends LocalBaseBlockJson, Omit<IBaseBlock, "primitiveSchema"> {
+ idBlock: LocalIdentificationBlockJson;
+ lenBlock: LocalLengthBlockJson;
+ valueBlock: T;
+ primitiveSchema?: BaseBlockJson;
+}
+
+export type StringEncoding = "ascii" | "hex";
+
+export class BaseBlock<T extends ValueBlock = ValueBlock, J extends ValueBlockJson = ValueBlockJson> extends LocalBaseBlock implements IBaseBlock, IBerConvertible {
+
+ static {
+
+ }
+
+ public static override NAME = "BaseBlock";
+
+ public idBlock: LocalIdentificationBlock;
+ public lenBlock: LocalLengthBlock;
+ public valueBlock: T;
+ public name: string;
+ public optional: boolean;
+ public primitiveSchema?: BaseBlock;
+
+ constructor({
+ name = EMPTY_STRING,
+ optional = false,
+ primitiveSchema,
+ ...parameters
+ }: BaseBlockParams = {}, valueBlockType?: ValueBlockConstructor<T>) {
+ super(parameters);
+
+ this.name = name;
+ this.optional = optional;
+ if (primitiveSchema) {
+ this.primitiveSchema = primitiveSchema;
+ }
+
+ this.idBlock = new LocalIdentificationBlock(parameters);
+ this.lenBlock = new LocalLengthBlock(parameters);
+ this.valueBlock = valueBlockType ? new valueBlockType(parameters) : new ValueBlock(parameters) as unknown as T;
+ }
+
+ public fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, (this.lenBlock.isIndefiniteForm) ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+
+ return resultOffset;
+ }
+
+ if (!this.idBlock.error.length)
+ this.blockLength += this.idBlock.blockLength;
+
+ if (!this.lenBlock.error.length)
+ this.blockLength += this.lenBlock.blockLength;
+
+ if (!this.valueBlock.error.length)
+ this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+
+ public toBER(sizeOnly?: boolean, writer?: ViewWriter): ArrayBuffer {
+ const _writer = writer || new ViewWriter();
+
+ if (!writer) {
+ prepareIndefiniteForm(this);
+ }
+
+ const idBlockBuf = this.idBlock.toBER(sizeOnly);
+
+ _writer.write(idBlockBuf);
+
+ if (this.lenBlock.isIndefiniteForm) {
+ _writer.write(new Uint8Array([0x80]).buffer);
+
+ this.valueBlock.toBER(sizeOnly, _writer);
+
+ _writer.write(new ArrayBuffer(2));
+ }
+ else {
+ const valueBlockBuf = this.valueBlock.toBER(sizeOnly);
+ this.lenBlock.length = valueBlockBuf.byteLength;
+ const lenBlockBuf = this.lenBlock.toBER(sizeOnly);
+
+ _writer.write(lenBlockBuf);
+ _writer.write(valueBlockBuf);
+ }
+
+ if (!writer) {
+ return _writer.final();
+ }
+
+ return EMPTY_BUFFER;
+ }
+
+ public override toJSON(): BaseBlockJson<J> {
+ const object: BaseBlockJson = {
+ ...super.toJSON(),
+ idBlock: this.idBlock.toJSON(),
+ lenBlock: this.lenBlock.toJSON(),
+ valueBlock: this.valueBlock.toJSON(),
+ name: this.name,
+ optional: this.optional,
+ };
+
+
+ if (this.primitiveSchema)
+ object.primitiveSchema = this.primitiveSchema.toJSON();
+
+ return object as BaseBlockJson<J>;
+ }
+ public override toString(encoding: StringEncoding = "ascii"): string {
+ if (encoding === "ascii") {
+ return this.onAsciiEncoding();
+ }
+
+ return pvtsutils.Convert.ToHex(this.toBER());
+ }
+
+ protected onAsciiEncoding(): string {
+ return `${(this.constructor as typeof BaseBlock).NAME} : ${pvtsutils.Convert.ToHex(this.valueBlock.valueBeforeDecodeView)}`;
+ }
+
+ /**
+ * Determines whether two object instances are equal
+ * @param other Object to compare with the current object
+ */
+ public isEqual(other: unknown): other is this {
+ if (this === other) {
+ return true;
+ }
+
+ // Check input type
+ if (!(other instanceof this.constructor)) {
+ return false;
+ }
+
+ const thisRaw = this.toBER();
+ const otherRaw = (other as BaseBlock).toBER();
+
+ return pvutils.isEqualBuffer(thisRaw, otherRaw);
+ }
+
+}
+
+/**
+ * Recursive function which checks and enables isIndefiniteForm flag for constructed blocks if any child has that flag enabled
+ * @param baseBlock Base ASN.1 block
+ * @returns Returns `true` if incoming block is `indefinite form`
+ */
+function prepareIndefiniteForm(baseBlock: BaseBlock): boolean {
+ if (baseBlock instanceof typeStore.Constructed) {
+ for (const value of baseBlock.valueBlock.value) {
+ if (prepareIndefiniteForm(value)) {
+ baseBlock.lenBlock.isIndefiniteForm = true;
+ }
+ }
+ }
+
+ return !!baseBlock.lenBlock.isIndefiniteForm;
+}
diff --git a/comm/third_party/asn1js/src/BaseStringBlock.ts b/comm/third_party/asn1js/src/BaseStringBlock.ts
new file mode 100644
index 0000000000..606b330e0c
--- /dev/null
+++ b/comm/third_party/asn1js/src/BaseStringBlock.ts
@@ -0,0 +1,74 @@
+import { BaseBlock, BaseBlockParams } from "./BaseBlock";
+import { IStringConvertible } from "./types";
+import { EMPTY_STRING } from "./internals/constants";
+import { LocalStringValueBlock, LocalStringValueBlockJson, LocalStringValueBlockParams } from "./internals/LocalStringValueBlock";
+
+export interface BaseStringBlockParams extends BaseBlockParams, LocalStringValueBlockParams { }
+export type BaseStringBlockJson = LocalStringValueBlockJson;
+
+export abstract class BaseStringBlock<T extends LocalStringValueBlock = LocalStringValueBlock, J extends BaseStringBlockJson = BaseStringBlockJson> extends BaseBlock<T, J> implements IStringConvertible {
+
+ public static override NAME = "BaseStringBlock";
+
+ /**
+ * String value
+ * @since 3.0.0
+ */
+ public getValue(): string {
+ return this.valueBlock.value;
+ }
+ /**
+ * String value
+ * @param value String value
+ * @since 3.0.0
+ */
+ public setValue(value: string): void {
+ this.valueBlock.value = value;
+ }
+
+ constructor({
+ value = EMPTY_STRING,
+ ...parameters
+ }: BaseStringBlockParams = {}, stringValueBlockType: new () => T) {
+ super(parameters, stringValueBlockType);
+
+ if (value) {
+ this.fromString(value);
+ }
+ }
+
+ public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, (this.lenBlock.isIndefiniteForm) ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+
+ return resultOffset;
+ }
+
+ this.fromBuffer(this.valueBlock.valueHexView);
+
+ if (!this.idBlock.error.length)
+ this.blockLength += this.idBlock.blockLength;
+
+ if (!this.lenBlock.error.length)
+ this.blockLength += this.lenBlock.blockLength;
+
+ if (!this.valueBlock.error.length)
+ this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+
+ /**
+ * Function converting ArrayBuffer into ASN.1 internal string
+ * @param inputBuffer ASN.1 BER encoded array
+ */
+ public abstract fromBuffer(inputBuffer: ArrayBuffer | Uint8Array): void;
+
+ public abstract fromString(inputString: string): void;
+
+ protected override onAsciiEncoding(): string {
+ return `${(this.constructor as typeof BaseStringBlock).NAME} : '${this.valueBlock.value}'`;
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/BitString.ts b/comm/third_party/asn1js/src/BitString.ts
new file mode 100644
index 0000000000..2c8ada83cc
--- /dev/null
+++ b/comm/third_party/asn1js/src/BitString.ts
@@ -0,0 +1,64 @@
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { Constructed } from "./Constructed";
+import { BIT_STRING_NAME } from "./internals/constants";
+import { LocalBitStringValueBlockParams, LocalBitStringValueBlock, LocalBitStringValueBlockJson } from "./internals/LocalBitStringValueBlock";
+import { typeStore } from "./TypeStore";
+
+export interface BitStringParams extends BaseBlockParams, LocalBitStringValueBlockParams { }
+export type BitStringJson = BaseBlockJson<LocalBitStringValueBlockJson>;
+
+export class BitString extends BaseBlock<LocalBitStringValueBlock, LocalBitStringValueBlockJson> {
+
+ static {
+ typeStore.BitString = this;
+ }
+
+ public static override NAME = BIT_STRING_NAME;
+
+ constructor({
+ idBlock = {},
+ lenBlock = {},
+ ...parameters
+ }: BitStringParams = {}) {
+ parameters.isConstructed ??= !!parameters.value?.length;
+ super({
+ idBlock: {
+ isConstructed: parameters.isConstructed,
+ ...idBlock,
+ },
+ lenBlock: {
+ ...lenBlock,
+ isIndefiniteForm: !!parameters.isIndefiniteForm,
+ },
+ ...parameters,
+ }, LocalBitStringValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 3; // BitString
+ }
+
+ public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ this.valueBlock.isConstructed = this.idBlock.isConstructed;
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
+
+ return super.fromBER(inputBuffer, inputOffset, inputLength);
+ }
+
+ protected override onAsciiEncoding(): string {
+ if (this.valueBlock.isConstructed || (this.valueBlock.value && this.valueBlock.value.length)) {
+ return Constructed.prototype.onAsciiEncoding.call(this);
+ } else {
+ // convert bytes to bits
+ const bits = [];
+ const valueHex = this.valueBlock.valueHexView;
+ for (const byte of valueHex) {
+ bits.push(byte.toString(2).padStart(8, "0"));
+ }
+
+ const bitsStr = bits.join("");
+
+ return `${(this.constructor as typeof BitString).NAME} : ${bitsStr.substring(0, bitsStr.length - this.valueBlock.unusedBits)}`;
+ }
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/BmpString.ts b/comm/third_party/asn1js/src/BmpString.ts
new file mode 100644
index 0000000000..42f23ea773
--- /dev/null
+++ b/comm/third_party/asn1js/src/BmpString.ts
@@ -0,0 +1,23 @@
+import { LocalBmpStringValueBlockParams, LocalBmpStringValueBlock, LocalBmpStringValueBlockJson } from "./internals/LocalBmpStringValueBlock";
+import { typeStore } from "./TypeStore";
+
+export type BmpStringParams = LocalBmpStringValueBlockParams;
+export type BmpStringJson = LocalBmpStringValueBlockJson;
+
+export class BmpString extends LocalBmpStringValueBlock {
+
+ static {
+ typeStore.BmpString = this;
+ }
+ public static override NAME = "BMPString";
+
+ constructor({
+ ...parameters
+ }: BmpStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 30; // BmpString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Boolean.ts b/comm/third_party/asn1js/src/Boolean.ts
new file mode 100644
index 0000000000..3bcdb05ae2
--- /dev/null
+++ b/comm/third_party/asn1js/src/Boolean.ts
@@ -0,0 +1,43 @@
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { LocalBooleanValueBlockParams, LocalBooleanValueBlock, LocalBooleanValueBlockJson } from "./internals/LocalBooleanValueBlock";
+import { typeStore } from "./TypeStore";
+
+export interface BooleanParams extends BaseBlockParams, LocalBooleanValueBlockParams { }
+export type BooleanJson = BaseBlockJson<LocalBooleanValueBlockJson>;
+
+export class Boolean extends BaseBlock<LocalBooleanValueBlock, LocalBooleanValueBlockJson> {
+
+ static {
+ typeStore.Boolean = this;
+ }
+
+ /**
+ * Gets value
+ * @since 3.0.0
+ */
+ public getValue(): boolean {
+ return this.valueBlock.value;
+ }
+ /**
+ * Sets value
+ * @param value Boolean value
+ * @since 3.0.0
+ */
+ public setValue(value: boolean): void {
+ this.valueBlock.value = value;
+ }
+
+ public static override NAME = "BOOLEAN";
+
+ constructor(parameters: BooleanParams = {}) {
+ super(parameters, LocalBooleanValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 1; // Boolean
+ }
+
+ protected override onAsciiEncoding(): string {
+ return `${(this.constructor as typeof Boolean).NAME} : ${this.getValue}`;
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/CharacterString.ts b/comm/third_party/asn1js/src/CharacterString.ts
new file mode 100644
index 0000000000..a15798cced
--- /dev/null
+++ b/comm/third_party/asn1js/src/CharacterString.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type CharacterStringParams = LocalSimpleStringBlockParams;
+export type CharacterStringJson = LocalSimpleStringBlockJson;
+
+export class CharacterString extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.CharacterString = this;
+ }
+
+ public static override NAME = "CharacterString";
+
+ constructor(parameters: CharacterStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 29; // CharacterString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Choice.ts b/comm/third_party/asn1js/src/Choice.ts
new file mode 100644
index 0000000000..3246bfa3c3
--- /dev/null
+++ b/comm/third_party/asn1js/src/Choice.ts
@@ -0,0 +1,22 @@
+import { BaseBlock } from "./BaseBlock";
+import { IAny, Any } from "./Any";
+
+export interface IChoice extends IAny {
+ value: BaseBlock[];
+}
+
+export type ChoiceParams = Partial<IChoice>;
+
+export class Choice extends Any implements IChoice {
+ public value: BaseBlock[];
+
+ constructor({
+ value = [],
+ ...parameters
+ }: ChoiceParams = {}) {
+ super(parameters);
+
+ this.value = value;
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Constructed.ts b/comm/third_party/asn1js/src/Constructed.ts
new file mode 100644
index 0000000000..8fe3bc502f
--- /dev/null
+++ b/comm/third_party/asn1js/src/Constructed.ts
@@ -0,0 +1,61 @@
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { LocalConstructedValueBlock, LocalConstructedValueBlockJson, LocalConstructedValueBlockParams } from "./internals/LocalConstructedValueBlock";
+import { typeStore } from "./TypeStore";
+
+export interface ConstructedParams extends BaseBlockParams, LocalConstructedValueBlockParams { }
+export type ConstructedJson = BaseBlockJson<LocalConstructedValueBlockJson>;
+
+export class Constructed extends BaseBlock<LocalConstructedValueBlock, LocalConstructedValueBlockJson> {
+
+ static {
+ typeStore.Constructed = this;
+ }
+
+ public static override NAME = "CONSTRUCTED";
+
+ constructor(parameters: ConstructedParams = {}) {
+ super(parameters, LocalConstructedValueBlock);
+
+ this.idBlock.isConstructed = true;
+ }
+
+ public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
+
+ const resultOffset = this.valueBlock.fromBER(inputBuffer, inputOffset, (this.lenBlock.isIndefiniteForm) ? inputLength : this.lenBlock.length);
+ if (resultOffset === -1) {
+ this.error = this.valueBlock.error;
+
+ return resultOffset;
+ }
+
+ if (!this.idBlock.error.length)
+ this.blockLength += this.idBlock.blockLength;
+
+ if (!this.lenBlock.error.length)
+ this.blockLength += this.lenBlock.blockLength;
+
+ if (!this.valueBlock.error.length)
+ this.blockLength += this.valueBlock.blockLength;
+
+ return resultOffset;
+ }
+
+ /**
+ * @internal
+ */
+ public override onAsciiEncoding(): string {
+ const values = [];
+ for (const value of this.valueBlock.value) {
+ values.push(value.toString("ascii").split("\n").map(o => ` ${o}`).join("\n"));
+ }
+ const blockName = this.idBlock.tagClass === 3
+ ? `[${this.idBlock.tagNumber}]`
+ : (this.constructor as typeof Constructed).NAME;
+
+ return values.length
+ ? `${blockName} :\n${values.join("\n")}` // items
+ : `${blockName} :`; // empty
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/DATE.ts b/comm/third_party/asn1js/src/DATE.ts
new file mode 100644
index 0000000000..3a6f73d144
--- /dev/null
+++ b/comm/third_party/asn1js/src/DATE.ts
@@ -0,0 +1,22 @@
+import { typeStore } from "./TypeStore";
+import { Utf8StringParams, Utf8String, Utf8StringJson } from "./Utf8String";
+
+export type DATEParams = Utf8StringParams;
+export type DATEJson = Utf8StringJson;
+
+export class DATE extends Utf8String {
+
+ static {
+ typeStore.DATE = this;
+ }
+
+ public static override NAME = "DATE";
+
+ constructor(parameters: DATEParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 31; // DATE
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/DateTime.ts b/comm/third_party/asn1js/src/DateTime.ts
new file mode 100644
index 0000000000..a30f47dbe4
--- /dev/null
+++ b/comm/third_party/asn1js/src/DateTime.ts
@@ -0,0 +1,22 @@
+import { typeStore } from "./TypeStore";
+import { Utf8StringParams, Utf8String, Utf8StringJson } from "./Utf8String";
+
+export type DateTimeParams = Utf8StringParams;
+export type DateTimeJson = Utf8StringJson;
+
+export class DateTime extends Utf8String {
+
+ static {
+ typeStore.DateTime = this;
+ }
+
+ public static override NAME = "DateTime";
+
+ constructor(parameters: DateTimeParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 33; // DateTime
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Duration.ts b/comm/third_party/asn1js/src/Duration.ts
new file mode 100644
index 0000000000..618894e158
--- /dev/null
+++ b/comm/third_party/asn1js/src/Duration.ts
@@ -0,0 +1,21 @@
+import { typeStore } from "./TypeStore";
+import { Utf8StringParams, Utf8String, Utf8StringJson } from "./Utf8String";
+
+export type DurationParams = Utf8StringParams;
+export type DurationJson = Utf8StringJson;
+
+export class Duration extends Utf8String {
+
+ static {
+ typeStore.Duration = this;
+ }
+ public static override NAME = "Duration";
+
+ constructor(parameters: DurationParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 34; // Duration
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/EndOfContent.ts b/comm/third_party/asn1js/src/EndOfContent.ts
new file mode 100644
index 0000000000..b0e8ccf6c9
--- /dev/null
+++ b/comm/third_party/asn1js/src/EndOfContent.ts
@@ -0,0 +1,23 @@
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { END_OF_CONTENT_NAME } from "./internals/constants";
+import { LocalEndOfContentValueBlock } from "./internals/LocalEndOfContentValueBlock";
+import { typeStore } from "./TypeStore";
+
+export type EndOfContentParams = BaseBlockParams;
+export type EndOfContentJson = BaseBlockJson;
+
+export class EndOfContent extends BaseBlock<LocalEndOfContentValueBlock> {
+
+ static {
+ typeStore.EndOfContent = this;
+ }
+ public static override NAME = END_OF_CONTENT_NAME;
+
+ constructor(parameters: EndOfContentParams = {}) {
+ super(parameters, LocalEndOfContentValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 0; // EndOfContent
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Enumerated.ts b/comm/third_party/asn1js/src/Enumerated.ts
new file mode 100644
index 0000000000..53249a3cf9
--- /dev/null
+++ b/comm/third_party/asn1js/src/Enumerated.ts
@@ -0,0 +1,22 @@
+import { IntegerParams, Integer, IntegerJson } from "./Integer";
+import { typeStore } from "./TypeStore";
+
+export type EnumeratedParams = IntegerParams;
+export type EnumeratedJson = IntegerJson;
+
+export class Enumerated extends Integer {
+
+ static {
+ typeStore.Enumerated = this;
+ }
+
+ public static override NAME = "ENUMERATED";
+
+ constructor(parameters: EnumeratedParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 10; // Enumerated
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/GeneralString.ts b/comm/third_party/asn1js/src/GeneralString.ts
new file mode 100644
index 0000000000..f0ce52a607
--- /dev/null
+++ b/comm/third_party/asn1js/src/GeneralString.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type GeneralStringParams = LocalSimpleStringBlockParams;
+export type GeneralStringJson = LocalSimpleStringBlockJson;
+
+export class GeneralString extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.GeneralString = this;
+ }
+
+ public static override NAME = "GeneralString";
+
+ constructor(parameters: GeneralStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 27; // GeneralString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/GeneralizedTime.ts b/comm/third_party/asn1js/src/GeneralizedTime.ts
new file mode 100644
index 0000000000..7743ae1436
--- /dev/null
+++ b/comm/third_party/asn1js/src/GeneralizedTime.ts
@@ -0,0 +1,262 @@
+import * as pvutils from "pvutils";
+import { typeStore } from "./TypeStore";
+import { IUTCTime, UTCTimeParams, UTCTimeJson, UTCTime, DateStringEncoding } from "./UTCTime";
+
+export interface IGeneralizedTime extends IUTCTime {
+ millisecond: number;
+}
+
+export type GeneralizedTimeParams = UTCTimeParams;
+
+export interface GeneralizedTimeJson extends UTCTimeJson {
+ millisecond: number;
+}
+
+export class GeneralizedTime extends UTCTime {
+
+ static {
+ typeStore.GeneralizedTime = this;
+ }
+
+ public static override NAME = "GeneralizedTime";
+
+ public millisecond: number;
+
+ constructor(parameters: GeneralizedTimeParams = {}) {
+ super(parameters);
+
+ this.millisecond ??= 0;
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 24; // GeneralizedTime
+ }
+
+ public override fromDate(inputDate: Date): void {
+ super.fromDate(inputDate);
+ this.millisecond = inputDate.getUTCMilliseconds();
+ }
+
+ public override toDate(): Date {
+ return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second, this.millisecond)));
+ }
+
+ public override fromString(inputString: string): void {
+ //#region Initial variables
+ let isUTC = false;
+
+ let timeString = "";
+ let dateTimeString = "";
+ let fractionPart = 0;
+
+ let parser;
+
+ let hourDifference = 0;
+ let minuteDifference = 0;
+ //#endregion
+
+ //#region Convert as UTC time
+ if (inputString[inputString.length - 1] === "Z") {
+ timeString = inputString.substring(0, inputString.length - 1);
+
+ isUTC = true;
+ }
+ //#endregion
+ //#region Convert as local time
+ else {
+ const number = new Number(inputString[inputString.length - 1]);
+
+ if (isNaN(number.valueOf()))
+ throw new Error("Wrong input string for conversion");
+
+ timeString = inputString;
+ }
+ //#endregion
+
+ //#region Check that we do not have a "+" and "-" symbols inside UTC time
+ if (isUTC) {
+ if (timeString.indexOf("+") !== -1)
+ throw new Error("Wrong input string for conversion");
+
+ if (timeString.indexOf("-") !== -1)
+ throw new Error("Wrong input string for conversion");
+ }
+ //#endregion
+ //#region Get "UTC time difference" in case of local time
+ else {
+ let multiplier = 1;
+ let differencePosition = timeString.indexOf("+");
+ let differenceString = "";
+
+ if (differencePosition === -1) {
+ differencePosition = timeString.indexOf("-");
+ multiplier = -1;
+ }
+
+ if (differencePosition !== -1) {
+ differenceString = timeString.substring(differencePosition + 1);
+ timeString = timeString.substring(0, differencePosition);
+
+ if ((differenceString.length !== 2) && (differenceString.length !== 4))
+ throw new Error("Wrong input string for conversion");
+
+ let number = parseInt(differenceString.substring(0, 2), 10);
+
+ if (isNaN(number.valueOf()))
+ throw new Error("Wrong input string for conversion");
+
+ hourDifference = multiplier * number;
+
+ if (differenceString.length === 4) {
+ number = parseInt(differenceString.substring(2, 4), 10);
+
+ if (isNaN(number.valueOf()))
+ throw new Error("Wrong input string for conversion");
+
+ minuteDifference = multiplier * number;
+ }
+ }
+ }
+ //#endregion
+
+ //#region Get position of fraction point
+ let fractionPointPosition = timeString.indexOf("."); // Check for "full stop" symbol
+ if (fractionPointPosition === -1)
+ fractionPointPosition = timeString.indexOf(","); // Check for "comma" symbol
+ //#endregion
+
+ //#region Get fraction part
+ if (fractionPointPosition !== -1) {
+ const fractionPartCheck = new Number(`0${timeString.substring(fractionPointPosition)}`);
+
+ if (isNaN(fractionPartCheck.valueOf()))
+ throw new Error("Wrong input string for conversion");
+
+ fractionPart = fractionPartCheck.valueOf();
+
+ dateTimeString = timeString.substring(0, fractionPointPosition);
+ }
+ else
+ dateTimeString = timeString;
+ //#endregion
+
+ //#region Parse internal date
+ switch (true) {
+ case (dateTimeString.length === 8): // "YYYYMMDD"
+ parser = /(\d{4})(\d{2})(\d{2})/ig;
+ if (fractionPointPosition !== -1)
+ throw new Error("Wrong input string for conversion"); // Here we should not have a "fraction point"
+ break;
+ case (dateTimeString.length === 10): // "YYYYMMDDHH"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ let fractionResult = 60 * fractionPart;
+ this.minute = Math.floor(fractionResult);
+
+ fractionResult = 60 * (fractionResult - this.minute);
+ this.second = Math.floor(fractionResult);
+
+ fractionResult = 1000 * (fractionResult - this.second);
+ this.millisecond = Math.floor(fractionResult);
+ }
+ break;
+ case (dateTimeString.length === 12): // "YYYYMMDDHHMM"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ let fractionResult = 60 * fractionPart;
+ this.second = Math.floor(fractionResult);
+
+ fractionResult = 1000 * (fractionResult - this.second);
+ this.millisecond = Math.floor(fractionResult);
+ }
+ break;
+ case (dateTimeString.length === 14): // "YYYYMMDDHHMMSS"
+ parser = /(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})/ig;
+
+ if (fractionPointPosition !== -1) {
+ const fractionResult = 1000 * fractionPart;
+ this.millisecond = Math.floor(fractionResult);
+ }
+ break;
+ default:
+ throw new Error("Wrong input string for conversion");
+ }
+ //#endregion
+
+ //#region Put parsed values at right places
+ const parserArray = parser.exec(dateTimeString);
+ if (parserArray === null)
+ throw new Error("Wrong input string for conversion");
+
+ for (let j = 1; j < parserArray.length; j++) {
+ switch (j) {
+ case 1:
+ this.year = parseInt(parserArray[j], 10);
+ break;
+ case 2:
+ this.month = parseInt(parserArray[j], 10);
+ break;
+ case 3:
+ this.day = parseInt(parserArray[j], 10);
+ break;
+ case 4:
+ this.hour = parseInt(parserArray[j], 10) + hourDifference;
+ break;
+ case 5:
+ this.minute = parseInt(parserArray[j], 10) + minuteDifference;
+ break;
+ case 6:
+ this.second = parseInt(parserArray[j], 10);
+ break;
+ default:
+ throw new Error("Wrong input string for conversion");
+ }
+ }
+ //#endregion
+
+ //#region Get final date
+ if (isUTC === false) {
+ const tempDate = new Date(this.year, this.month, this.day, this.hour, this.minute, this.second, this.millisecond);
+
+ this.year = tempDate.getUTCFullYear();
+ this.month = tempDate.getUTCMonth();
+ this.day = tempDate.getUTCDay();
+ this.hour = tempDate.getUTCHours();
+ this.minute = tempDate.getUTCMinutes();
+ this.second = tempDate.getUTCSeconds();
+ this.millisecond = tempDate.getUTCMilliseconds();
+ }
+ //#endregion
+ }
+
+ public override toString(encoding: DateStringEncoding = "iso"): string {
+ if (encoding === "iso") {
+ const outputArray = [];
+
+ outputArray.push(pvutils.padNumber(this.year, 4));
+ outputArray.push(pvutils.padNumber(this.month, 2));
+ outputArray.push(pvutils.padNumber(this.day, 2));
+ outputArray.push(pvutils.padNumber(this.hour, 2));
+ outputArray.push(pvutils.padNumber(this.minute, 2));
+ outputArray.push(pvutils.padNumber(this.second, 2));
+ if (this.millisecond !== 0) {
+ outputArray.push(".");
+ outputArray.push(pvutils.padNumber(this.millisecond, 3));
+ }
+ outputArray.push("Z");
+
+ return outputArray.join("");
+ }
+
+ return super.toString(encoding);
+ }
+
+ public override toJSON(): GeneralizedTimeJson {
+ return {
+ ...super.toJSON(),
+ millisecond: this.millisecond,
+ };
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/GraphicString.ts b/comm/third_party/asn1js/src/GraphicString.ts
new file mode 100644
index 0000000000..3d2ab07577
--- /dev/null
+++ b/comm/third_party/asn1js/src/GraphicString.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type GraphicStringParams = LocalSimpleStringBlockParams;
+export type GraphicStringJson = LocalSimpleStringBlockJson;
+
+export class GraphicString extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.GraphicString = this;
+ }
+
+ public static override NAME = "GraphicString";
+
+ constructor(parameters: GraphicStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 25; // GraphicString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/HexBlock.ts b/comm/third_party/asn1js/src/HexBlock.ts
new file mode 100644
index 0000000000..cca34da5de
--- /dev/null
+++ b/comm/third_party/asn1js/src/HexBlock.ts
@@ -0,0 +1,110 @@
+/* eslint-disable @typescript-eslint/explicit-function-return-type */
+import * as pvtsutils from "pvtsutils";
+import { IBerConvertible } from "./types";
+import { EMPTY_BUFFER, EMPTY_VIEW } from "./internals/constants";
+import { LocalBaseBlockConstructor } from "./internals/LocalBaseBlock";
+import { checkBufferParams } from "./internals/utils";
+
+export interface IHexBlock {
+ isHexOnly: boolean;
+ valueHex: pvtsutils.BufferSource;
+}
+
+export interface HexBlockJson extends Omit<IHexBlock, "valueHex"> {
+ valueHex: string;
+}
+
+export type HexBlockParams = Partial<IHexBlock>;
+/**
+ * Class used as a base block for all remaining ASN.1 classes
+ */
+export function HexBlock<T extends LocalBaseBlockConstructor>(BaseClass: T) {
+ return class Some extends BaseClass implements IHexBlock, IBerConvertible {
+
+ public static override NAME = "hexBlock";
+
+ public isHexOnly: boolean;
+ /**
+ * Binary data in ArrayBuffer representation
+ *
+ * @deprecated since version 3.0.0
+ */
+ public get valueHex(): ArrayBuffer {
+ return this.valueHexView.slice().buffer;
+ }
+ /**
+ * Binary data in ArrayBuffer representation
+ *
+ * @deprecated since version 3.0.0
+ */
+ public set valueHex(value: ArrayBuffer) {
+ this.valueHexView = new Uint8Array(value);
+ }
+ /**
+ * Binary data in Uint8Array representation
+ *
+ * @since 3.0.0
+ */
+ public valueHexView: Uint8Array;
+
+ constructor(...args: any[]) {
+ super(...args);
+
+ const params: HexBlockParams = args[0] || {};
+ this.isHexOnly = params.isHexOnly ?? false;
+ this.valueHexView = params.valueHex ? pvtsutils.BufferSourceConverter.toUint8Array(params.valueHex) : EMPTY_VIEW;
+ }
+
+ public fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ // Basic check for parameters
+ const view = inputBuffer instanceof ArrayBuffer ? new Uint8Array(inputBuffer) : inputBuffer;
+ if (!checkBufferParams(this, view, inputOffset, inputLength)) {
+ return -1;
+ }
+
+ const endLength = inputOffset + inputLength;
+
+ // Initial checks
+ this.valueHexView = view.subarray(inputOffset, endLength);
+ if (!this.valueHexView.length) {
+ this.warnings.push("Zero buffer length");
+
+ return inputOffset;
+ }
+
+ this.blockLength = inputLength;
+
+ return endLength;
+ }
+
+ public toBER(sizeOnly = false): ArrayBuffer {
+ if (!this.isHexOnly) {
+ this.error = "Flag 'isHexOnly' is not set, abort";
+
+ return EMPTY_BUFFER;
+ }
+
+ if (sizeOnly) {
+ return new ArrayBuffer(this.valueHexView.byteLength);
+ }
+
+ // Don't copy data if View is not offset
+ return (this.valueHexView.byteLength === this.valueHexView.buffer.byteLength)
+ ? this.valueHexView.buffer
+ : this.valueHexView.slice().buffer;
+ }
+
+ /**
+ * Returns a JSON representation of an object
+ * @returns JSON object
+ */
+ public override toJSON() {
+ return {
+ ...super.toJSON(),
+ isHexOnly: this.isHexOnly,
+ valueHex: pvtsutils.Convert.ToHex(this.valueHexView),
+ };
+ }
+
+ };
+}
diff --git a/comm/third_party/asn1js/src/IA5String.ts b/comm/third_party/asn1js/src/IA5String.ts
new file mode 100644
index 0000000000..f0021cec51
--- /dev/null
+++ b/comm/third_party/asn1js/src/IA5String.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type IA5StringParams = LocalSimpleStringBlockParams;
+export type IA5StringJson = LocalSimpleStringBlockJson;
+
+export class IA5String extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.IA5String = this;
+ }
+
+ public static override NAME = "IA5String";
+
+ constructor(parameters: IA5StringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 22; // IA5String
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Integer.ts b/comm/third_party/asn1js/src/Integer.ts
new file mode 100644
index 0000000000..fd3d1d9e70
--- /dev/null
+++ b/comm/third_party/asn1js/src/Integer.ts
@@ -0,0 +1,103 @@
+import * as pvtsutils from "pvtsutils";
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { LocalIntegerValueBlockParams, LocalIntegerValueBlock, LocalIntegerValueBlockJson } from "./internals/LocalIntegerValueBlock";
+import { assertBigInt } from "./internals/utils";
+import { typeStore } from "./TypeStore";
+import { ViewWriter } from "./ViewWriter";
+
+export interface IntegerParams extends BaseBlockParams, LocalIntegerValueBlockParams { }
+export type IntegerJson = BaseBlockJson<LocalIntegerValueBlockJson>;
+
+export class Integer extends BaseBlock<LocalIntegerValueBlock, LocalIntegerValueBlockJson> {
+
+ static {
+ typeStore.Integer = this;
+ }
+
+ public static override NAME = "INTEGER";
+
+ constructor(parameters: IntegerParams = {}) {
+ super(parameters, LocalIntegerValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 2; // Integer
+ }
+
+ /**
+ * Converts Integer into BigInt
+ * @throws Throws Error if BigInt is not supported
+ * @since 3.0.0
+ */
+ public toBigInt(): bigint {
+ assertBigInt();
+
+ return BigInt(this.valueBlock.toString());
+ }
+
+ /**
+ * Creates Integer from BigInt value
+ * @param value BigInt value
+ * @returns ASN.1 Integer
+ * @throws Throws Error if BigInt is not supported
+ * @since 3.0.0
+ */
+ public static fromBigInt(value: number | string | bigint | boolean): Integer {
+ assertBigInt();
+
+ const bigIntValue = BigInt(value);
+ const writer = new ViewWriter();
+
+ const hex = bigIntValue.toString(16).replace(/^-/, "");
+ const view = new Uint8Array(pvtsutils.Convert.FromHex(hex));
+
+ if (bigIntValue < 0) {
+ // a negative number
+ const first = new Uint8Array(view.length + (view[0] & 0x80 ? 1 : 0));
+ first[0] |= 0x80;
+
+ const firstInt = BigInt(`0x${pvtsutils.Convert.ToHex(first)}`);
+ const secondInt = firstInt + bigIntValue;
+ const second = pvtsutils.BufferSourceConverter.toUint8Array(pvtsutils.Convert.FromHex(secondInt.toString(16)));
+ second[0] |= 0x80;
+
+ writer.write(second);
+ } else {
+ // a positive number
+ if (view[0] & 0x80) {
+ writer.write(new Uint8Array([0]));
+ }
+ writer.write(view);
+ }
+
+ const res = new Integer({
+ valueHex: writer.final(),
+ });
+
+ return res;
+ }
+
+ public convertToDER(): Integer {
+ const integer = new Integer({ valueHex: this.valueBlock.valueHexView });
+
+ integer.valueBlock.toDER();
+
+ return integer;
+ }
+
+ /**
+ * Convert current Integer value from DER to BER format
+ * @returns
+ */
+ public convertFromDER(): Integer {
+ return new Integer({
+ valueHex: this.valueBlock.valueHexView[0] === 0
+ ? this.valueBlock.valueHexView.subarray(1)
+ : this.valueBlock.valueHexView,
+ });
+ }
+
+ protected override onAsciiEncoding(): string {
+ return `${(this.constructor as typeof Integer).NAME} : ${this.valueBlock.toString()}`;
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Null.ts b/comm/third_party/asn1js/src/Null.ts
new file mode 100644
index 0000000000..8c4c4c580d
--- /dev/null
+++ b/comm/third_party/asn1js/src/Null.ts
@@ -0,0 +1,65 @@
+import { ViewWriter } from "./ViewWriter";
+import { ValueBlock, ValueBlockJson } from "./ValueBlock";
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { typeStore } from "./TypeStore";
+
+export type NullParams = BaseBlockParams;
+export type NullJson = BaseBlockJson<ValueBlockJson>;
+
+export class Null extends BaseBlock<ValueBlock, ValueBlockJson> {
+
+ static {
+ typeStore.Null = this;
+ }
+
+ public static override NAME = "NULL";
+
+ constructor(parameters: NullParams = {}) {
+ super(parameters, ValueBlock); // We will not have a call to "Null value block" because of specified FROM_BER and TO_BER functions
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 5; // Null
+ }
+
+ public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ if (this.lenBlock.length > 0)
+ this.warnings.push("Non-zero length of value block for Null type");
+
+ if (!this.idBlock.error.length)
+ this.blockLength += this.idBlock.blockLength;
+
+ if (!this.lenBlock.error.length)
+ this.blockLength += this.lenBlock.blockLength;
+
+ this.blockLength += inputLength;
+
+ if ((inputOffset + inputLength) > inputBuffer.byteLength) {
+ this.error = "End of input reached before message was fully decoded (inconsistent offset and length values)";
+
+ return -1;
+ }
+
+ return (inputOffset + inputLength);
+ }
+
+ public override toBER(sizeOnly?: boolean, writer?: ViewWriter): ArrayBuffer {
+ const retBuf = new ArrayBuffer(2);
+
+ if (!sizeOnly) {
+ const retView = new Uint8Array(retBuf);
+ retView[0] = 0x05;
+ retView[1] = 0x00;
+ }
+
+ if (writer) {
+ writer.write(retBuf);
+ }
+
+ return retBuf;
+ }
+
+ protected override onAsciiEncoding(): string {
+ return `${(this.constructor as typeof Null).NAME}`;
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/NumericString.ts b/comm/third_party/asn1js/src/NumericString.ts
new file mode 100644
index 0000000000..a917fd1dc2
--- /dev/null
+++ b/comm/third_party/asn1js/src/NumericString.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type NumericStringParams = LocalSimpleStringBlockParams;
+export type NumericStringJson = LocalSimpleStringBlockJson;
+
+export class NumericString extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.NumericString = this;
+ }
+
+ public static override NAME = "NumericString";
+
+ constructor(parameters: NumericStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 18; // NumericString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/ObjectIdentifier.ts b/comm/third_party/asn1js/src/ObjectIdentifier.ts
new file mode 100644
index 0000000000..7608a3cf7d
--- /dev/null
+++ b/comm/third_party/asn1js/src/ObjectIdentifier.ts
@@ -0,0 +1,53 @@
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { LocalObjectIdentifierValueBlockParams, LocalObjectIdentifierValueBlock, LocalObjectIdentifierValueBlockJson } from "./internals/LocalObjectIdentifierValueBlock";
+import { typeStore } from "./TypeStore";
+
+export interface ObjectIdentifierParams extends BaseBlockParams, LocalObjectIdentifierValueBlockParams { }
+export interface ObjectIdentifierJson extends BaseBlockJson<LocalObjectIdentifierValueBlockJson> {
+ value: string;
+}
+
+export class ObjectIdentifier extends BaseBlock<LocalObjectIdentifierValueBlock, LocalObjectIdentifierValueBlockJson> {
+
+ static {
+ typeStore.ObjectIdentifier = this;
+ }
+
+ public static override NAME = "OBJECT IDENTIFIER";
+
+ /**
+ * Gets string representation of Object Identifier
+ * @since 3.0.0
+ */
+ public getValue(): string {
+ return this.valueBlock.toString();
+ }
+
+ /**
+ * Sets Object Identifier value from string
+ * @param value String value
+ * @since 3.0.0
+ */
+ public setValue(value: string): void {
+ this.valueBlock.fromString(value);
+ }
+
+ constructor(parameters: ObjectIdentifierParams = {}) {
+ super(parameters, LocalObjectIdentifierValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 6; // OBJECT IDENTIFIER
+ }
+
+ protected override onAsciiEncoding(): string {
+ return `${(this.constructor as typeof ObjectIdentifier).NAME} : ${this.valueBlock.toString() || "empty"}`;
+ }
+
+ public override toJSON(): ObjectIdentifierJson {
+ return {
+ ...super.toJSON(),
+ value: this.getValue(),
+ };
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/OctetString.ts b/comm/third_party/asn1js/src/OctetString.ts
new file mode 100644
index 0000000000..df57e9bc6e
--- /dev/null
+++ b/comm/third_party/asn1js/src/OctetString.ts
@@ -0,0 +1,103 @@
+import * as pvtsutils from "pvtsutils";
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { Constructed } from "./Constructed";
+import { LocalOctetStringValueBlockParams, LocalOctetStringValueBlock, LocalOctetStringValueBlockJson } from "./internals/LocalOctetStringValueBlock";
+import { OCTET_STRING_NAME } from "./internals/constants";
+import { localFromBER } from "./parser";
+import { typeStore } from "./TypeStore";
+
+export interface OctetStringParams extends BaseBlockParams, LocalOctetStringValueBlockParams { }
+export type OctetStringJson = BaseBlockJson<LocalOctetStringValueBlockJson>;
+
+export class OctetString extends BaseBlock<LocalOctetStringValueBlock, LocalOctetStringValueBlockJson> {
+
+ static {
+ typeStore.OctetString = this;
+ }
+
+ public static override NAME = OCTET_STRING_NAME;
+
+ constructor({
+ idBlock = {},
+ lenBlock = {},
+ ...parameters
+ }: OctetStringParams = {}) {
+ parameters.isConstructed ??= !!parameters.value?.length;
+ super({
+ idBlock: {
+ isConstructed: parameters.isConstructed,
+ ...idBlock,
+ },
+ lenBlock: {
+ ...lenBlock,
+ isIndefiniteForm: !!parameters.isIndefiniteForm,
+ },
+ ...parameters,
+ }, LocalOctetStringValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 4; // OctetString
+ }
+
+ public override fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ this.valueBlock.isConstructed = this.idBlock.isConstructed;
+ this.valueBlock.isIndefiniteForm = this.lenBlock.isIndefiniteForm;
+
+ // Ability to encode empty OCTET STRING
+ if (inputLength === 0) {
+ if (this.idBlock.error.length === 0)
+ this.blockLength += this.idBlock.blockLength;
+
+ if (this.lenBlock.error.length === 0)
+ this.blockLength += this.lenBlock.blockLength;
+
+ return inputOffset;
+ }
+
+ if (!this.valueBlock.isConstructed) {
+ const view = inputBuffer instanceof ArrayBuffer ? new Uint8Array(inputBuffer) : inputBuffer;
+ const buf = view.subarray(inputOffset, inputOffset + inputLength);
+ try {
+ if (buf.byteLength) {
+ const asn = localFromBER(buf, 0, buf.byteLength);
+ if (asn.offset !== -1 && asn.offset === inputLength) {
+ this.valueBlock.value = [asn.result as OctetString];
+ }
+ }
+ } catch (e) {
+ // nothing
+ }
+ }
+
+ return super.fromBER(inputBuffer, inputOffset, inputLength);
+ }
+
+ protected override onAsciiEncoding(): string {
+ if (this.valueBlock.isConstructed || (this.valueBlock.value && this.valueBlock.value.length)) {
+ return Constructed.prototype.onAsciiEncoding.call(this);
+ }
+
+ return `${(this.constructor as typeof OctetString).NAME} : ${pvtsutils.Convert.ToHex(this.valueBlock.valueHexView)}`;
+ }
+
+ /**
+ * Returns OctetString value. If OctetString is constructed, returns concatenated internal OctetString values
+ * @returns Array buffer
+ * @since 3.0.0
+ */
+ public getValue(): ArrayBuffer {
+ if (!this.idBlock.isConstructed) {
+ return this.valueBlock.valueHexView.slice().buffer;
+ }
+
+ const array: ArrayBuffer[] = [];
+ for (const content of this.valueBlock.value) {
+ if (content instanceof OctetString) {
+ array.push(content.valueBlock.valueHexView);
+ }
+ }
+
+ return pvtsutils.BufferSourceConverter.concat(array);
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Primitive.ts b/comm/third_party/asn1js/src/Primitive.ts
new file mode 100644
index 0000000000..49b25c343b
--- /dev/null
+++ b/comm/third_party/asn1js/src/Primitive.ts
@@ -0,0 +1,22 @@
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { LocalPrimitiveValueBlock, LocalPrimitiveValueBlockJson, LocalPrimitiveValueBlockParams } from "./internals/LocalPrimitiveValueBlock";
+import { typeStore } from "./TypeStore";
+
+export interface PrimitiveParams extends BaseBlockParams, LocalPrimitiveValueBlockParams { }
+export type PrimitiveJson = BaseBlockJson<LocalPrimitiveValueBlockJson>;
+
+export class Primitive extends BaseBlock<LocalPrimitiveValueBlock, LocalPrimitiveValueBlockJson> {
+
+ static {
+ typeStore.Primitive = this;
+ }
+
+ public static override NAME = "PRIMITIVE";
+
+ constructor(parameters: PrimitiveParams = {}) {
+ super(parameters, LocalPrimitiveValueBlock);
+
+ this.idBlock.isConstructed = false;
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/PrintableString.ts b/comm/third_party/asn1js/src/PrintableString.ts
new file mode 100644
index 0000000000..3eca544079
--- /dev/null
+++ b/comm/third_party/asn1js/src/PrintableString.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type PrintableStringParams = LocalSimpleStringBlockParams;
+export type PrintableStringJson = LocalSimpleStringBlockJson;
+
+export class PrintableString extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.PrintableString = this;
+ }
+
+ public static override NAME = "PrintableString";
+
+ constructor(parameters: PrintableStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 19; // PrintableString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/RawData.ts b/comm/third_party/asn1js/src/RawData.ts
new file mode 100644
index 0000000000..86228739fc
--- /dev/null
+++ b/comm/third_party/asn1js/src/RawData.ts
@@ -0,0 +1,51 @@
+import * as pvtsutils from "pvtsutils";
+import { IBerConvertible } from "./types";
+import { EMPTY_VIEW } from "./internals/constants";
+
+export interface IRawData {
+ data: ArrayBuffer;
+}
+
+export type RawDataParams = Partial<IRawData>;
+
+/**
+ * Special class providing ability to have "toBER/fromBER" for raw ArrayBuffer
+ */
+export class RawData implements IBerConvertible {
+
+
+ /**
+ * @deprecated Since v3.0.0
+ */
+ public get data(): ArrayBuffer {
+ return this.dataView.slice().buffer;
+ }
+
+ /**
+ * @deprecated Since v3.0.0
+ */
+ public set data(value: ArrayBuffer) {
+ this.dataView = pvtsutils.BufferSourceConverter.toUint8Array(value);
+ }
+
+ /**
+ * @since 3.0.0
+ */
+ public dataView: Uint8Array;
+
+ constructor({ data = EMPTY_VIEW }: RawDataParams = {}) {
+ this.dataView = pvtsutils.BufferSourceConverter.toUint8Array(data);
+ }
+
+ public fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ const endLength = inputOffset + inputLength;
+ this.dataView = pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer).subarray(inputOffset, endLength);
+
+ return endLength;
+ }
+
+ public toBER(sizeOnly?: boolean): ArrayBuffer {
+ return this.dataView.slice().buffer;
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/RelativeObjectIdentifier.ts b/comm/third_party/asn1js/src/RelativeObjectIdentifier.ts
new file mode 100644
index 0000000000..997220eae4
--- /dev/null
+++ b/comm/third_party/asn1js/src/RelativeObjectIdentifier.ts
@@ -0,0 +1,54 @@
+import { BaseBlock, BaseBlockJson, BaseBlockParams } from "./BaseBlock";
+import { LocalRelativeObjectIdentifierValueBlockParams, LocalRelativeObjectIdentifierValueBlock, LocalRelativeObjectIdentifierValueBlockJson } from "./internals/LocalRelativeObjectIdentifierValueBlock";
+import { typeStore } from "./TypeStore";
+
+
+export interface RelativeObjectIdentifierParams extends BaseBlockParams, LocalRelativeObjectIdentifierValueBlockParams { }
+export interface RelativeObjectIdentifierJson extends BaseBlockJson<LocalRelativeObjectIdentifierValueBlockJson> {
+ value: string;
+}
+
+export class RelativeObjectIdentifier extends BaseBlock<LocalRelativeObjectIdentifierValueBlock, LocalRelativeObjectIdentifierValueBlockJson> {
+
+ static {
+ typeStore.RelativeObjectIdentifier = this;
+ }
+
+ /**
+ * Gets string representation of Relative Object Identifier
+ * @since 3.0.0
+ */
+ public getValue(): string {
+ return this.valueBlock.toString();
+ }
+
+ /**
+ * Sets Relative Object Identifier value from string
+ * @param value String value
+ * @since 3.0.0
+ */
+ public setValue(value: string): void {
+ this.valueBlock.fromString(value);
+ }
+
+ public static override NAME = "RelativeObjectIdentifier";
+
+ constructor(parameters: RelativeObjectIdentifierParams = {}) {
+ super(parameters, LocalRelativeObjectIdentifierValueBlock);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 13; // RELATIVE OBJECT IDENTIFIER
+ }
+
+ protected override onAsciiEncoding(): string {
+ return `${(this.constructor as typeof RelativeObjectIdentifier).NAME} : ${this.valueBlock.toString() || "empty"}`;
+ }
+
+ public override toJSON(): RelativeObjectIdentifierJson {
+ return {
+ ...super.toJSON(),
+ value: this.getValue(),
+ };
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Repeated.ts b/comm/third_party/asn1js/src/Repeated.ts
new file mode 100644
index 0000000000..38142fa533
--- /dev/null
+++ b/comm/third_party/asn1js/src/Repeated.ts
@@ -0,0 +1,26 @@
+import { IAny, Any } from "./Any";
+
+export interface IRepeated extends IAny {
+ value: Any;
+ local: boolean;
+}
+
+export type RepeatedParams = Partial<IRepeated>;
+
+export class Repeated extends Any {
+
+ public value: Any;
+ public local: boolean;
+
+ constructor({
+ value = new Any(),
+ local = false,
+ ...parameters
+ }: RepeatedParams = {}) {
+ super(parameters);
+
+ this.value = value;
+ this.local = local; // Could local or global array to store elements
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Sequence.ts b/comm/third_party/asn1js/src/Sequence.ts
new file mode 100644
index 0000000000..3303283bb2
--- /dev/null
+++ b/comm/third_party/asn1js/src/Sequence.ts
@@ -0,0 +1,22 @@
+import { ConstructedParams, Constructed, ConstructedJson } from "./Constructed";
+import { typeStore } from "./TypeStore";
+
+export type SequenceParams = ConstructedParams;
+export type SequenceJson = ConstructedJson;
+
+export class Sequence extends Constructed {
+
+ static {
+ typeStore.Sequence = this;
+ }
+
+ public static override NAME = "SEQUENCE";
+
+ constructor(parameters: SequenceParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 16; // Sequence
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Set.ts b/comm/third_party/asn1js/src/Set.ts
new file mode 100644
index 0000000000..1bbdec447c
--- /dev/null
+++ b/comm/third_party/asn1js/src/Set.ts
@@ -0,0 +1,22 @@
+import { ConstructedParams, Constructed, ConstructedJson } from "./Constructed";
+import { typeStore } from "./TypeStore";
+
+export type SetParams = ConstructedParams;
+export type SetJson = ConstructedJson;
+
+export class Set extends Constructed {
+
+ static {
+ typeStore.Set = this;
+ }
+
+ public static override NAME = "SET";
+
+ constructor(parameters: SetParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 17; // Set
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/TIME.ts b/comm/third_party/asn1js/src/TIME.ts
new file mode 100644
index 0000000000..97fee031b0
--- /dev/null
+++ b/comm/third_party/asn1js/src/TIME.ts
@@ -0,0 +1,22 @@
+import { typeStore } from "./TypeStore";
+import { Utf8StringParams, Utf8String, Utf8StringJson } from "./Utf8String";
+
+export type TIMEParams = Utf8StringParams;
+export type TIMEJson = Utf8StringJson;
+
+export class TIME extends Utf8String {
+
+ static {
+ typeStore.TIME = this;
+ }
+
+ public static override NAME = "TIME";
+
+ constructor(parameters: TIMEParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 14; // Time
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/TeletexString.ts b/comm/third_party/asn1js/src/TeletexString.ts
new file mode 100644
index 0000000000..0f7e38d36c
--- /dev/null
+++ b/comm/third_party/asn1js/src/TeletexString.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type TeletexStringParams = LocalSimpleStringBlockParams;
+export type TeletexStringJson = LocalSimpleStringBlockJson;
+
+export class TeletexString extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.TeletexString = this;
+ }
+
+ public static override NAME = "TeletexString";
+
+ constructor(parameters: TeletexStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 20; // TeletexString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/TimeOfDay.ts b/comm/third_party/asn1js/src/TimeOfDay.ts
new file mode 100644
index 0000000000..78c8fac4ec
--- /dev/null
+++ b/comm/third_party/asn1js/src/TimeOfDay.ts
@@ -0,0 +1,22 @@
+import { typeStore } from "./TypeStore";
+import { Utf8StringParams, Utf8String, Utf8StringJson } from "./Utf8String";
+
+export type TimeOfDayParams = Utf8StringParams;
+export type TimeOfDayJson = Utf8StringJson;
+
+export class TimeOfDay extends Utf8String {
+
+ static {
+ typeStore.TimeOfDay = this;
+ }
+
+ public static override NAME = "TimeOfDay";
+
+ constructor(parameters: TimeOfDayParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 32; // TimeOfDay
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/TypeStore.ts b/comm/third_party/asn1js/src/TypeStore.ts
new file mode 100644
index 0000000000..17b86ae97d
--- /dev/null
+++ b/comm/third_party/asn1js/src/TypeStore.ts
@@ -0,0 +1,71 @@
+import type { BaseBlock } from "./BaseBlock";
+import type { BitString } from "./BitString";
+import type { BmpString } from "./BmpString";
+import type { Boolean as AsnBoolean } from "./Boolean";
+import type { CharacterString } from "./CharacterString";
+import type { Constructed } from "./Constructed";
+import type { DATE } from "./DATE";
+import type { DateTime } from "./DateTime";
+import type { Duration } from "./Duration";
+import type { EndOfContent } from "./EndOfContent";
+import type { Enumerated } from "./Enumerated";
+import type { GeneralizedTime } from "./GeneralizedTime";
+import type { GeneralString } from "./GeneralString";
+import type { GraphicString } from "./GraphicString";
+import type { IA5String } from "./IA5String";
+import type { Integer } from "./Integer";
+import type { Null } from "./Null";
+import type { NumericString } from "./NumericString";
+import type { ObjectIdentifier } from "./ObjectIdentifier";
+import type { OctetString } from "./OctetString";
+import type { Primitive } from "./Primitive";
+import type { PrintableString } from "./PrintableString";
+import type { RelativeObjectIdentifier } from "./RelativeObjectIdentifier";
+import type { Sequence } from "./Sequence";
+import type { Set } from "./Set";
+import type { TeletexString } from "./TeletexString";
+import type { TIME } from "./TIME";
+import type { TimeOfDay } from "./TimeOfDay";
+import type { UniversalString } from "./UniversalString";
+import type { UTCTime } from "./UTCTime";
+import type { Utf8String } from "./Utf8String";
+import type { VideotexString } from "./VideotexString";
+import type { VisibleString } from "./VisibleString";
+
+export type AsnType = BaseBlock | EndOfContent | AsnBoolean | Integer | BitString | OctetString | Null | ObjectIdentifier | Enumerated | Utf8String | RelativeObjectIdentifier | TIME | Sequence | Set | NumericString | PrintableString | TeletexString | VideotexString | IA5String | UTCTime | GeneralizedTime | GraphicString | VisibleString | GeneralString | UniversalString | CharacterString | BmpString | DATE | TimeOfDay | DateTime | Duration | Constructed | Primitive;
+
+export interface TypeStore {
+ BitString: typeof BitString;
+ BmpString: typeof BmpString;
+ Boolean: typeof AsnBoolean;
+ CharacterString: typeof CharacterString;
+ Constructed: typeof Constructed;
+ DATE: typeof DATE;
+ DateTime: typeof DateTime;
+ Duration: typeof Duration;
+ EndOfContent: typeof EndOfContent;
+ Enumerated: typeof Enumerated;
+ GeneralizedTime: typeof GeneralizedTime;
+ GeneralString: typeof GeneralString;
+ GraphicString: typeof GraphicString;
+ IA5String: typeof IA5String;
+ Integer: typeof Integer;
+ Null: typeof Null;
+ NumericString: typeof NumericString;
+ ObjectIdentifier: typeof ObjectIdentifier;
+ OctetString: typeof OctetString;
+ Primitive: typeof Primitive;
+ PrintableString: typeof PrintableString;
+ RelativeObjectIdentifier: typeof RelativeObjectIdentifier;
+ Sequence: typeof Sequence;
+ Set: typeof Set;
+ TeletexString: typeof TeletexString;
+ TIME: typeof TIME;
+ TimeOfDay: typeof TimeOfDay;
+ UniversalString: typeof UniversalString;
+ UTCTime: typeof UTCTime;
+ Utf8String: typeof Utf8String;
+ VideotexString: typeof VideotexString;
+ VisibleString: typeof VisibleString;
+}
+export const typeStore = {} as TypeStore;
diff --git a/comm/third_party/asn1js/src/UTCTime.ts b/comm/third_party/asn1js/src/UTCTime.ts
new file mode 100644
index 0000000000..a387556051
--- /dev/null
+++ b/comm/third_party/asn1js/src/UTCTime.ts
@@ -0,0 +1,172 @@
+import * as pvtsutils from "pvtsutils";
+import * as pvutils from "pvutils";
+import { BaseBlockJson, StringEncoding } from "./BaseBlock";
+import { LocalSimpleStringValueBlockJson } from "./internals/LocalSimpleStringValueBlock";
+import { IDateConvertible } from "./types";
+import { typeStore } from "./TypeStore";
+import { VisibleStringParams, VisibleString } from "./VisibleString";
+
+export interface IUTCTime {
+ year: number;
+ month: number;
+ day: number;
+ hour: number;
+ minute: number;
+ second: number;
+}
+
+export interface UTCTimeParams extends VisibleStringParams {
+ value?: string;
+ valueDate?: Date;
+}
+export interface UTCTimeJson extends BaseBlockJson<LocalSimpleStringValueBlockJson>, IUTCTime { }
+
+export type DateStringEncoding = StringEncoding | "iso";
+
+export class UTCTime extends VisibleString implements IUTCTime, IDateConvertible {
+
+ static {
+ typeStore.UTCTime = this;
+ }
+
+ public static override NAME = "UTCTime";
+
+ public year: number;
+ public month: number;
+ public day: number;
+ public hour: number;
+ public minute: number;
+ public second: number;
+
+ constructor({
+ value,
+ valueDate,
+ ...parameters
+ }: UTCTimeParams = {}) {
+ super(parameters);
+
+ this.year = 0;
+ this.month = 0;
+ this.day = 0;
+ this.hour = 0;
+ this.minute = 0;
+ this.second = 0;
+
+ //#region Create UTCTime from ASN.1 UTC string value
+ if (value) {
+ this.fromString(value);
+
+ this.valueBlock.valueHexView = new Uint8Array(value.length);
+
+ for (let i = 0; i < value.length; i++)
+ this.valueBlock.valueHexView[i] = value.charCodeAt(i);
+ }
+ //#endregion
+ //#region Create GeneralizedTime from JavaScript Date type
+ if (valueDate) {
+ this.fromDate(valueDate);
+ this.valueBlock.valueHexView = new Uint8Array(this.toBuffer());
+ }
+ //#endregion
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 23; // UTCTime
+ }
+
+ public override fromBuffer(inputBuffer: ArrayBuffer | Uint8Array): void {
+ this.fromString(String.fromCharCode.apply(null, pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer) as unknown as number[]));
+ }
+
+ /**
+ * Function converting ASN.1 internal string into ArrayBuffer
+ * @returns
+ */
+ public toBuffer(): ArrayBuffer {
+ const str = this.toString(); // TODO use this.valueBlock.value and update toString
+
+ const buffer = new ArrayBuffer(str.length);
+ const view = new Uint8Array(buffer);
+
+ for (let i = 0; i < str.length; i++)
+ view[i] = str.charCodeAt(i);
+
+ return buffer;
+ }
+
+ /**
+ * Function converting "Date" object into ASN.1 internal string
+ * @param {!Date} inputDate JavaScript "Date" object
+ */
+ public fromDate(inputDate: Date): void {
+ this.year = inputDate.getUTCFullYear();
+ this.month = inputDate.getUTCMonth() + 1;
+ this.day = inputDate.getUTCDate();
+ this.hour = inputDate.getUTCHours();
+ this.minute = inputDate.getUTCMinutes();
+ this.second = inputDate.getUTCSeconds();
+ }
+
+ public toDate(): Date {
+ return (new Date(Date.UTC(this.year, this.month - 1, this.day, this.hour, this.minute, this.second)));
+ }
+
+ public override fromString(inputString: string): void {
+ //#region Parse input string
+ const parser = /(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})Z/ig;
+ const parserArray = parser.exec(inputString);
+ if (parserArray === null) {
+ this.error = "Wrong input string for conversion";
+
+ return;
+ }
+ //#endregion
+ //#region Store parsed values
+ const year = parseInt(parserArray[1], 10);
+ if (year >= 50)
+ this.year = 1900 + year;
+
+ else
+ this.year = 2000 + year;
+
+ this.month = parseInt(parserArray[2], 10);
+ this.day = parseInt(parserArray[3], 10);
+ this.hour = parseInt(parserArray[4], 10);
+ this.minute = parseInt(parserArray[5], 10);
+ this.second = parseInt(parserArray[6], 10);
+ //#endregion
+ }
+
+ public override toString(encoding: DateStringEncoding = "iso"): string {
+ if (encoding === "iso") {
+ const outputArray = new Array(7);
+
+ outputArray[0] = pvutils.padNumber(((this.year < 2000) ? (this.year - 1900) : (this.year - 2000)), 2);
+ outputArray[1] = pvutils.padNumber(this.month, 2);
+ outputArray[2] = pvutils.padNumber(this.day, 2);
+ outputArray[3] = pvutils.padNumber(this.hour, 2);
+ outputArray[4] = pvutils.padNumber(this.minute, 2);
+ outputArray[5] = pvutils.padNumber(this.second, 2);
+ outputArray[6] = "Z";
+
+ return outputArray.join("");
+ }
+
+ return super.toString(encoding);
+ }
+
+ protected override onAsciiEncoding(): string {
+ return `${(this.constructor as typeof UTCTime).NAME} : ${this.toDate().toISOString()}`;
+ }
+
+ public override toJSON(): UTCTimeJson {
+ return {
+ ...super.toJSON(),
+ year: this.year,
+ month: this.month,
+ day: this.day,
+ hour: this.hour,
+ minute: this.minute,
+ second: this.second,
+ };
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/UniversalString.ts b/comm/third_party/asn1js/src/UniversalString.ts
new file mode 100644
index 0000000000..fce5b1d0ac
--- /dev/null
+++ b/comm/third_party/asn1js/src/UniversalString.ts
@@ -0,0 +1,24 @@
+import { LocalUniversalStringValueBlockParams, LocalUniversalStringValueBlock, LocalUniversalStringValueBlockJson } from "./internals/LocalUniversalStringValueBlockParams";
+import { typeStore } from "./TypeStore";
+
+export type UniversalStringParams = LocalUniversalStringValueBlockParams;
+export type UniversalStringJson = LocalUniversalStringValueBlockJson;
+
+export class UniversalString extends LocalUniversalStringValueBlock {
+
+ static {
+ typeStore.UniversalString = this;
+ }
+
+ public static override NAME = "UniversalString";
+
+ constructor({
+ ...parameters
+ }: UniversalStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 28; // UniversalString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/Utf8String.ts b/comm/third_party/asn1js/src/Utf8String.ts
new file mode 100644
index 0000000000..2713cd1b95
--- /dev/null
+++ b/comm/third_party/asn1js/src/Utf8String.ts
@@ -0,0 +1,24 @@
+import { BaseBlockJson } from "./BaseBlock";
+import { BaseStringBlockParams } from "./BaseStringBlock";
+import { LocalUtf8StringValueBlockParams, LocalUtf8StringValueBlock, LocalUtf8StringValueBlockJson } from "./internals/LocalUtf8StringValueBlock";
+import { typeStore } from "./TypeStore";
+
+export interface Utf8StringParams extends BaseStringBlockParams, LocalUtf8StringValueBlockParams { }
+export type Utf8StringJson = BaseBlockJson<LocalUtf8StringValueBlockJson>;
+
+export class Utf8String extends LocalUtf8StringValueBlock {
+
+ static {
+ typeStore.Utf8String = this;
+ }
+
+ public static override NAME = "UTF8String";
+
+ constructor(parameters: Utf8StringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 12; // Utf8String
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/ValueBlock.ts b/comm/third_party/asn1js/src/ValueBlock.ts
new file mode 100644
index 0000000000..9463214aef
--- /dev/null
+++ b/comm/third_party/asn1js/src/ValueBlock.ts
@@ -0,0 +1,21 @@
+import { IBerConvertible } from "./types";
+import * as internals from "./internals/LocalBaseBlock";
+import { ViewWriter } from "./ViewWriter";
+
+export type IValueBlock = internals.ILocalBaseBlock;
+export type ValueBlockParams = internals.LocalBaseBlockParams;
+export type ValueBlockJson = internals.LocalBaseBlockJson;
+
+export class ValueBlock extends internals.LocalBaseBlock implements IValueBlock, IBerConvertible {
+
+ public static override NAME = "valueBlock";
+
+ public fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number {
+ throw TypeError("User need to make a specific function in a class which extends 'ValueBlock'");
+ }
+
+ public toBER(sizeOnly?: boolean, writer?: ViewWriter): ArrayBuffer {
+ throw TypeError("User need to make a specific function in a class which extends 'ValueBlock'");
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/VideotexString.ts b/comm/third_party/asn1js/src/VideotexString.ts
new file mode 100644
index 0000000000..d1867b602e
--- /dev/null
+++ b/comm/third_party/asn1js/src/VideotexString.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type VideotexStringParams = LocalSimpleStringBlockParams;
+export type VideotexStringJson = LocalSimpleStringBlockJson;
+
+export class VideotexString extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.VideotexString = this;
+ }
+
+ public static override NAME = "VideotexString";
+
+ constructor(parameters: VideotexStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 21; // VideotexString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/ViewWriter.ts b/comm/third_party/asn1js/src/ViewWriter.ts
new file mode 100644
index 0000000000..1df3a1170c
--- /dev/null
+++ b/comm/third_party/asn1js/src/ViewWriter.ts
@@ -0,0 +1,22 @@
+import * as utils from "./internals/utils";
+
+export class ViewWriter {
+
+ public items: ArrayBuffer[] = [];
+
+ /**
+ * Writes buffer
+ * @param buf
+ */
+ public write(buf: ArrayBuffer): void {
+ this.items.push(buf);
+ }
+
+ /**
+ * Concatenates all buffers
+ * @returns Concatenated buffer
+ */
+ public final(): ArrayBuffer {
+ return utils.concat(this.items);
+ }
+}
diff --git a/comm/third_party/asn1js/src/VisibleString.ts b/comm/third_party/asn1js/src/VisibleString.ts
new file mode 100644
index 0000000000..aead80a4cc
--- /dev/null
+++ b/comm/third_party/asn1js/src/VisibleString.ts
@@ -0,0 +1,22 @@
+import { LocalSimpleStringBlockParams, LocalSimpleStringBlock, LocalSimpleStringBlockJson } from "./internals/LocalSimpleStringBlock";
+import { typeStore } from "./TypeStore";
+
+export type VisibleStringParams = LocalSimpleStringBlockParams;
+export type VisibleStringJson = LocalSimpleStringBlockJson;
+
+export class VisibleString extends LocalSimpleStringBlock {
+
+ static {
+ typeStore.VisibleString = this;
+ }
+
+ public static override NAME = "VisibleString";
+
+ constructor(parameters: VisibleStringParams = {}) {
+ super(parameters);
+
+ this.idBlock.tagClass = 1; // UNIVERSAL
+ this.idBlock.tagNumber = 26; // VisibleString
+ }
+
+}
diff --git a/comm/third_party/asn1js/src/index.ts b/comm/third_party/asn1js/src/index.ts
new file mode 100644
index 0000000000..a4b15b34af
--- /dev/null
+++ b/comm/third_party/asn1js/src/index.ts
@@ -0,0 +1,59 @@
+export * from "./types";
+
+// basic
+export * from "./ViewWriter";
+export * from "./HexBlock";
+export * from "./ValueBlock";
+export * from "./BaseBlock";
+export * from "./BaseStringBlock";
+
+export * from "./Primitive";
+export * from "./Constructed";
+export * from "./EndOfContent";
+
+// common
+export * from "./Null";
+export * from "./Boolean";
+export * from "./OctetString";
+export * from "./BitString";
+export * from "./Integer";
+export * from "./Enumerated";
+export * from "./ObjectIdentifier";
+export * from "./RelativeObjectIdentifier";
+export * from "./Sequence";
+export * from "./Set";
+
+// strings
+export * from "./Utf8String";
+export * from "./BmpString";
+export * from "./UniversalString";
+export * from "./NumericString";
+export * from "./PrintableString";
+export * from "./TeletexString";
+export * from "./VideotexString";
+export * from "./IA5String";
+export * from "./GraphicString";
+export * from "./VisibleString";
+export * from "./GeneralString";
+export * from "./CharacterString";
+
+// date and time
+export * from "./UTCTime";
+export * from "./GeneralizedTime";
+export * from "./DATE";
+export * from "./TimeOfDay";
+export * from "./DateTime";
+export * from "./Duration";
+export * from "./TIME";
+
+// schema types
+export * from "./Any";
+export * from "./Choice";
+export * from "./Repeated";
+
+// special
+export * from "./RawData";
+
+export { FromBerResult, fromBER } from "./parser";
+export * from "./schema";
+export { AsnType } from "./TypeStore"; \ No newline at end of file
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
diff --git a/comm/third_party/asn1js/src/parser.ts b/comm/third_party/asn1js/src/parser.ts
new file mode 100644
index 0000000000..51ab7dfcd8
--- /dev/null
+++ b/comm/third_party/asn1js/src/parser.ts
@@ -0,0 +1,301 @@
+import * as pvtsutils from "pvtsutils";
+import { ValueBlock } from "./ValueBlock";
+import { BaseBlock } from "./BaseBlock";
+import { LocalBaseBlock } from "./internals/LocalBaseBlock";
+import { AsnType, typeStore } from "./TypeStore";
+import { checkBufferParams } from "./internals/utils";
+
+export interface FromBerResult {
+ offset: number;
+ result: AsnType;
+}
+
+/**
+ * Local function changing a type for ASN.1 classes
+ * @param inputObject Incoming object
+ * @param newType Target type to convert
+ * @returns Converted object
+ */
+function localChangeType<T extends BaseBlock>(inputObject: BaseBlock, newType: new () => T): T {
+ if (inputObject instanceof newType) {
+ return inputObject;
+ }
+
+ const newObject = new newType();
+ newObject.idBlock = inputObject.idBlock;
+ newObject.lenBlock = inputObject.lenBlock;
+ newObject.warnings = inputObject.warnings;
+ newObject.valueBeforeDecodeView = inputObject.valueBeforeDecodeView;
+
+ return newObject;
+}
+
+/**
+ * Internal library function for decoding ASN.1 BER
+ * @param inputBuffer ASN.1 BER encoded array
+ * @param inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param inputLength Maximum length of array of bytes which can be using in this function
+ * @returns
+ */
+export function localFromBER(inputBuffer: Uint8Array, inputOffset = 0, inputLength = inputBuffer.length): FromBerResult {
+ const incomingOffset = inputOffset; // Need to store initial offset since "inputOffset" is changing in the function
+
+ // Create a basic ASN.1 type since we need to return errors and warnings from the function
+ let returnObject = new BaseBlock({}, ValueBlock);
+
+ // Basic check for parameters
+ const baseBlock = new LocalBaseBlock();
+ if (!checkBufferParams(baseBlock, inputBuffer, inputOffset, inputLength)) {
+ returnObject.error = baseBlock.error;
+
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+
+ // Getting Uint8Array subarray
+ const intBuffer = inputBuffer.subarray(inputOffset, inputOffset + inputLength);
+
+ // Initial checks
+ if (!intBuffer.length) {
+ returnObject.error = "Zero buffer length";
+
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+
+ // Decode identification block of ASN.1 BER structure
+ // console.time("idBlock");
+ let resultOffset = returnObject.idBlock.fromBER(inputBuffer, inputOffset, inputLength);
+ if (returnObject.idBlock.warnings.length) {
+ returnObject.warnings.concat(returnObject.idBlock.warnings);
+ }
+ if (resultOffset === -1) {
+ returnObject.error = returnObject.idBlock.error;
+
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+ // console.timeEnd("idBlock");
+
+ inputOffset = resultOffset;
+ inputLength -= returnObject.idBlock.blockLength;
+
+ // Decode length block of ASN.1 BER structure
+ // console.time("lengthBlock");
+ resultOffset = returnObject.lenBlock.fromBER(inputBuffer, inputOffset, inputLength);
+ if (returnObject.lenBlock.warnings.length) {
+ returnObject.warnings.concat(returnObject.lenBlock.warnings);
+ }
+ if (resultOffset === -1) {
+ returnObject.error = returnObject.lenBlock.error;
+
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+ // console.timeEnd("lengthBlock");
+
+ inputOffset = resultOffset;
+ inputLength -= returnObject.lenBlock.blockLength;
+
+ // Check for using indefinite length form in encoding for primitive types
+ if (!returnObject.idBlock.isConstructed &&
+ returnObject.lenBlock.isIndefiniteForm) {
+ returnObject.error = "Indefinite length form used for primitive encoding form";
+
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+
+ // Switch ASN.1 block type
+ let newASN1Type: new () => AsnType = BaseBlock as any;
+
+ switch (returnObject.idBlock.tagClass) {
+ // UNIVERSAL
+ case 1:
+ // Check for reserved tag numbers
+ if ((returnObject.idBlock.tagNumber >= 37) &&
+ (returnObject.idBlock.isHexOnly === false)) {
+ returnObject.error = "UNIVERSAL 37 and upper tags are reserved by ASN.1 standard";
+
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+ switch (returnObject.idBlock.tagNumber) {
+ case 0: // EndOfContent
+ // Check for EndOfContent type
+ if ((returnObject.idBlock.isConstructed) &&
+ (returnObject.lenBlock.length > 0)) {
+ returnObject.error = "Type [UNIVERSAL 0] is reserved";
+
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ }
+
+ newASN1Type = typeStore.EndOfContent;
+
+ break;
+ case 1: // Boolean
+ newASN1Type = typeStore.Boolean;
+ break;
+ case 2: // Integer
+ newASN1Type = typeStore.Integer;
+ break;
+ case 3: // BitString
+ newASN1Type = typeStore.BitString;
+ break;
+ case 4: // OctetString
+ newASN1Type = typeStore.OctetString;
+ break;
+ case 5: // Null
+ newASN1Type = typeStore.Null;
+ break;
+ case 6: // ObjectIdentifier
+ newASN1Type = typeStore.ObjectIdentifier;
+ break;
+ case 10: // Enumerated
+ newASN1Type = typeStore.Enumerated;
+ break;
+ case 12: // Utf8String
+ newASN1Type = typeStore.Utf8String;
+ break;
+ case 13: // RelativeObjectIdentifier
+ newASN1Type = typeStore.RelativeObjectIdentifier;
+ break;
+ case 14: // TIME
+ newASN1Type = typeStore.TIME;
+ break;
+ case 15:
+ returnObject.error = "[UNIVERSAL 15] is reserved by ASN.1 standard";
+
+ return {
+ offset: -1,
+ result: returnObject
+ };
+ case 16: // Sequence
+ newASN1Type = typeStore.Sequence;
+ break;
+ case 17: // Set
+ newASN1Type = typeStore.Set;
+ break;
+ case 18: // NumericString
+ newASN1Type = typeStore.NumericString;
+ break;
+ case 19: // PrintableString
+ newASN1Type = typeStore.PrintableString;
+ break;
+ case 20: // TeletexString
+ newASN1Type = typeStore.TeletexString;
+ break;
+ case 21: // VideotexString
+ newASN1Type = typeStore.VideotexString;
+ break;
+ case 22: // IA5String
+ newASN1Type = typeStore.IA5String;
+ break;
+ case 23: // UTCTime
+ newASN1Type = typeStore.UTCTime;
+ break;
+ case 24: // GeneralizedTime
+ newASN1Type = typeStore.GeneralizedTime;
+ break;
+ case 25: // GraphicString
+ newASN1Type = typeStore.GraphicString;
+ break;
+ case 26: // VisibleString
+ newASN1Type = typeStore.VisibleString;
+ break;
+ case 27: // GeneralString
+ newASN1Type = typeStore.GeneralString;
+ break;
+ case 28: // UniversalString
+ newASN1Type = typeStore.UniversalString;
+ break;
+ case 29: // CharacterString
+ newASN1Type = typeStore.CharacterString;
+ break;
+ case 30: // BmpString
+ newASN1Type = typeStore.BmpString;
+ break;
+ case 31: // DATE
+ newASN1Type = typeStore.DATE;
+ break;
+ case 32: // TimeOfDay
+ newASN1Type = typeStore.TimeOfDay;
+ break;
+ case 33: // DateTime
+ newASN1Type = typeStore.DateTime;
+ break;
+ case 34: // Duration
+ newASN1Type = typeStore.Duration;
+ break;
+ default: {
+ const newObject = returnObject.idBlock.isConstructed
+ ? new typeStore.Constructed()
+ : new typeStore.Primitive();
+
+ newObject.idBlock = returnObject.idBlock;
+ newObject.lenBlock = returnObject.lenBlock;
+ newObject.warnings = returnObject.warnings;
+
+ returnObject = newObject;
+ }
+ }
+ break;
+ // All other tag classes
+ case 2: // APPLICATION
+ case 3: // CONTEXT-SPECIFIC
+ case 4: // PRIVATE
+ default: {
+ newASN1Type = returnObject.idBlock.isConstructed
+ ? typeStore.Constructed
+ : typeStore.Primitive;
+ }
+ }
+
+
+ // Change type and perform BER decoding
+ returnObject = localChangeType(returnObject, newASN1Type);
+ // console.time("valueBlock");
+ resultOffset = returnObject.fromBER(inputBuffer, inputOffset, returnObject.lenBlock.isIndefiniteForm ? inputLength : returnObject.lenBlock.length);
+
+ // Coping incoming buffer for entire ASN.1 block
+ returnObject.valueBeforeDecodeView = inputBuffer.subarray(incomingOffset, incomingOffset + returnObject.blockLength);
+ // console.timeEnd("valueBlock");
+
+ return {
+ offset: resultOffset,
+ result: returnObject
+ };
+}
+
+/**
+ * Major function for decoding ASN.1 BER array into internal library structures
+ * @param inputBuffer ASN.1 BER encoded array of bytes
+ */
+export function fromBER(inputBuffer: pvtsutils.BufferSource): FromBerResult {
+ if (!inputBuffer.byteLength) {
+ const result = new BaseBlock({}, ValueBlock);
+ result.error = "Input buffer has zero length";
+
+ return {
+ offset: -1,
+ result
+ };
+ }
+
+ return localFromBER(pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer).slice(), 0, inputBuffer.byteLength);
+}
diff --git a/comm/third_party/asn1js/src/schema.ts b/comm/third_party/asn1js/src/schema.ts
new file mode 100644
index 0000000000..4f07e92a13
--- /dev/null
+++ b/comm/third_party/asn1js/src/schema.ts
@@ -0,0 +1,475 @@
+/* eslint-disable @typescript-eslint/ban-ts-comment */
+import * as pvtsutils from "pvtsutils";
+import { IS_CONSTRUCTED, EMPTY_STRING, NAME, ID_BLOCK, FROM_BER, TO_BER, TAG_CLASS, TAG_NUMBER, IS_HEX_ONLY, LOCAL, VALUE_HEX_VIEW } from "./internals/constants";
+import { Any } from "./Any";
+import { Choice } from "./Choice";
+import { Repeated } from "./Repeated";
+import { localFromBER } from "./parser";
+import { AsnType, typeStore } from "./TypeStore";
+
+export type AsnSchemaType = AsnType | Any | Choice | Repeated;
+
+export interface CompareSchemaSuccess {
+ verified: true;
+ result: AsnType & { [key: string]: any; };
+}
+
+export interface CompareSchemaFail {
+ verified: false;
+ name?: string;
+ result: AsnType | { error: string; };
+}
+
+export type CompareSchemaResult = CompareSchemaSuccess | CompareSchemaFail;
+
+/**
+ * Compare of two ASN.1 object trees
+ * @param root Root of input ASN.1 object tree
+ * @param inputData Input ASN.1 object tree
+ * @param inputSchema Input ASN.1 schema to compare with
+ * @return Returns result of comparison
+ */
+export function compareSchema(root: AsnType, inputData: AsnType, inputSchema: AsnSchemaType): CompareSchemaResult {
+ //#region Special case for Choice schema element type
+ if (inputSchema instanceof Choice) {
+ const choiceResult = false;
+
+ for (let j = 0; j < inputSchema.value.length; j++) {
+ const result = compareSchema(root, inputData, inputSchema.value[j]);
+ if (result.verified) {
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ }
+
+ if (choiceResult === false) {
+ const _result: CompareSchemaResult = {
+ verified: false,
+ result: {
+ error: "Wrong values for Choice type"
+ },
+ };
+
+ if (inputSchema.hasOwnProperty(NAME))
+ _result.name = inputSchema.name;
+
+ return _result;
+ }
+ }
+ //#endregion
+ //#region Special case for Any schema element type
+ if (inputSchema instanceof Any) {
+ //#region Add named component of ASN.1 schema
+ if (inputSchema.hasOwnProperty(NAME))
+ (root as any)[inputSchema.name] = inputData; // TODO Such call may replace original field of the object (eg idBlock)
+
+
+ //#endregion
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ //#endregion
+ //#region Initial check
+ if ((root instanceof Object) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong root object" }
+ };
+ }
+
+ if ((inputData instanceof Object) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 data" }
+ };
+ }
+
+ if ((inputSchema instanceof Object) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if ((ID_BLOCK in inputSchema) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+ //#endregion
+ //#region Comparing idBlock properties in ASN.1 data and ASN.1 schema
+ //#region Encode and decode ASN.1 schema idBlock
+ /// <remarks>This encoding/decoding is necessary because could be an errors in schema definition</remarks>
+ if ((FROM_BER in inputSchema.idBlock) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if ((TO_BER in inputSchema.idBlock) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ const encodedId = inputSchema.idBlock.toBER(false);
+ if (encodedId.byteLength === 0) {
+ return {
+ verified: false,
+ result: { error: "Error encoding idBlock for ASN.1 schema" }
+ };
+ }
+
+ const decodedOffset = inputSchema.idBlock.fromBER(encodedId, 0, encodedId.byteLength);
+ if (decodedOffset === -1) {
+ return {
+ verified: false,
+ result: { error: "Error decoding idBlock for ASN.1 schema" }
+ };
+ }
+ //#endregion
+ //#region tagClass
+ if (inputSchema.idBlock.hasOwnProperty(TAG_CLASS) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if (inputSchema.idBlock.tagClass !== inputData.idBlock.tagClass) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //#endregion
+ //#region tagNumber
+ if (inputSchema.idBlock.hasOwnProperty(TAG_NUMBER) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if (inputSchema.idBlock.tagNumber !== inputData.idBlock.tagNumber) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //#endregion
+ //#region isConstructed
+ if (inputSchema.idBlock.hasOwnProperty(IS_CONSTRUCTED) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if (inputSchema.idBlock.isConstructed !== inputData.idBlock.isConstructed) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //#endregion
+ //#region isHexOnly
+ if (!(IS_HEX_ONLY in inputSchema.idBlock)) // Since 'isHexOnly' is an inherited property
+ {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ if (inputSchema.idBlock.isHexOnly !== inputData.idBlock.isHexOnly) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //#endregion
+ //#region valueHex
+ if (inputSchema.idBlock.isHexOnly) {
+ if ((VALUE_HEX_VIEW in inputSchema.idBlock) === false) // Since 'valueHex' is an inherited property
+ {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema" }
+ };
+ }
+
+ const schemaView = inputSchema.idBlock.valueHexView;
+ const asn1View = inputData.idBlock.valueHexView;
+
+ if (schemaView.length !== asn1View.length) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+
+ for (let i = 0; i < schemaView.length; i++) {
+ if (schemaView[i] !== asn1View[1]) {
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ }
+ }
+ //#endregion
+ //#endregion
+ //#region Add named component of ASN.1 schema
+ if (inputSchema.name) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, EMPTY_STRING);
+ if (inputSchema.name)
+ (root as any)[inputSchema.name] = inputData; // TODO check field existence. If exists throw an error
+ }
+ //#endregion
+ //#region Getting next ASN.1 block for comparison
+ if (inputSchema instanceof typeStore.Constructed) {
+ // TODO not clear how it works for OctetString and BitString
+ //* if (inputSchema.idBlock.isConstructed) {
+ let admission = 0;
+ let result: CompareSchemaResult = {
+ verified: false,
+ result: {
+ error: "Unknown error",
+ }
+ };
+
+ let maxLength = inputSchema.valueBlock.value.length;
+
+ if (maxLength > 0) {
+ if (inputSchema.valueBlock.value[0] instanceof Repeated) {
+ // @ts-ignore
+ maxLength = inputData.valueBlock.value.length; // TODO debug it
+ }
+ }
+
+ //#region Special case when constructive value has no elements
+ if (maxLength === 0) {
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ //#endregion
+ //#region Special case when "inputData" has no values and "inputSchema" has all optional values
+ // @ts-ignore
+ // TODO debug it
+ if ((inputData.valueBlock.value.length === 0) &&
+ (inputSchema.valueBlock.value.length !== 0)) {
+ let _optional = true;
+
+ for (let i = 0; i < inputSchema.valueBlock.value.length; i++)
+ _optional = _optional && (inputSchema.valueBlock.value[i].optional || false);
+
+ if (_optional) {
+ return {
+ verified: true,
+ result: root
+ };
+ }
+
+ //#region Delete early added name of block
+ if (inputSchema.name) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, EMPTY_STRING);
+ if (inputSchema.name)
+ delete (root as any)[inputSchema.name];
+ }
+ //#endregion
+ root.error = "Inconsistent object length";
+
+ return {
+ verified: false,
+ result: root
+ };
+ }
+ //#endregion
+ for (let i = 0; i < maxLength; i++) {
+ //#region Special case when there is an OPTIONAL element of ASN.1 schema at the end
+ // @ts-ignore
+ if ((i - admission) >= inputData.valueBlock.value.length) {
+ if (inputSchema.valueBlock.value[i].optional === false) {
+ const _result: CompareSchemaResult = {
+ verified: false,
+ result: root
+ };
+
+ root.error = "Inconsistent length between ASN.1 data and schema";
+
+ //#region Delete early added name of block
+ if (inputSchema.name) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, EMPTY_STRING);
+ if (inputSchema.name) {
+ delete (root as any)[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ }
+ //#endregion
+
+ return _result;
+ }
+ }
+
+ //#endregion
+ else {
+ //#region Special case for Repeated type of ASN.1 schema element
+ if (inputSchema.valueBlock.value[0] instanceof Repeated) {
+ // @ts-ignore
+ result = compareSchema(root, inputData.valueBlock.value[i], inputSchema.valueBlock.value[0].value);
+ if (result.verified === false) {
+ if (inputSchema.valueBlock.value[0].optional)
+ admission++;
+ else {
+ //#region Delete early added name of block
+ if (inputSchema.name) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, EMPTY_STRING);
+ if (inputSchema.name)
+ delete (root as any)[inputSchema.name];
+ }
+ //#endregion
+
+ return result;
+ }
+ }
+
+ if ((NAME in inputSchema.valueBlock.value[0]) && (inputSchema.valueBlock.value[0].name.length > 0)) {
+ let arrayRoot: Record<string, any> = {};
+
+ if ((LOCAL in inputSchema.valueBlock.value[0]) && (inputSchema.valueBlock.value[0].local))
+ arrayRoot = inputData;
+
+ else
+ arrayRoot = root;
+
+ if (typeof arrayRoot[inputSchema.valueBlock.value[0].name] === "undefined")
+ arrayRoot[inputSchema.valueBlock.value[0].name] = [];
+
+ // @ts-ignore
+ arrayRoot[inputSchema.valueBlock.value[0].name].push(inputData.valueBlock.value[i]);
+ }
+ }
+
+ //#endregion
+ else {
+ // @ts-ignore
+ result = compareSchema(root, inputData.valueBlock.value[i - admission], inputSchema.valueBlock.value[i]);
+ if (result.verified === false) {
+ if (inputSchema.valueBlock.value[i].optional)
+ admission++;
+ else {
+ //#region Delete early added name of block
+ if (inputSchema.name) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, EMPTY_STRING);
+ if (inputSchema.name)
+ delete (root as any)[inputSchema.name];
+ }
+ //#endregion
+
+ return result;
+ }
+ }
+ }
+ }
+ }
+
+ if (result.verified === false) // The situation may take place if last element is OPTIONAL and verification failed
+ {
+ const _result: CompareSchemaResult = {
+ verified: false,
+ result: root
+ };
+
+ //#region Delete early added name of block
+ if (inputSchema.name) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, EMPTY_STRING);
+ if (inputSchema.name) {
+ delete (root as any)[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ }
+ //#endregion
+
+ return _result;
+ }
+
+ return {
+ verified: true,
+ result: root
+ };
+ }
+ //#endregion
+ //#region Ability to parse internal value for primitive-encoded value (value of OctetString, for example)
+ if (inputSchema.primitiveSchema &&
+ (VALUE_HEX_VIEW in inputData.valueBlock)) {
+ //#region Decoding of raw ASN.1 data
+ const asn1 = localFromBER(inputData.valueBlock.valueHexView);
+ if (asn1.offset === -1) {
+ const _result: CompareSchemaResult = {
+ verified: false,
+ result: asn1.result
+ };
+
+ //#region Delete early added name of block
+ if (inputSchema.name) {
+ inputSchema.name = inputSchema.name.replace(/^\s+|\s+$/g, EMPTY_STRING);
+ if (inputSchema.name) {
+ delete (root as any)[inputSchema.name];
+ _result.name = inputSchema.name;
+ }
+ }
+ //#endregion
+
+ return _result;
+ }
+ //#endregion
+
+ return compareSchema(root, asn1.result, inputSchema.primitiveSchema);
+ }
+
+ return {
+ verified: true,
+ result: root
+ };
+ //#endregion
+}
+/**
+ * ASN.1 schema verification for ArrayBuffer data
+ * @param inputBuffer Input BER-encoded ASN.1 data
+ * @param inputSchema Input ASN.1 schema to verify against to
+ * @return
+ */
+
+export function verifySchema(inputBuffer: pvtsutils.BufferSource, inputSchema: AsnSchemaType): CompareSchemaResult {
+ //#region Initial check
+ if ((inputSchema instanceof Object) === false) {
+ return {
+ verified: false,
+ result: { error: "Wrong ASN.1 schema type" }
+ };
+ }
+ //#endregion
+ //#region Decoding of raw ASN.1 data
+ const asn1 = localFromBER(pvtsutils.BufferSourceConverter.toUint8Array(inputBuffer));
+ if (asn1.offset === -1) {
+ return {
+ verified: false,
+ result: asn1.result
+ };
+ }
+ //#endregion
+ //#region Compare ASN.1 struct with input schema
+
+ return compareSchema(asn1.result, asn1.result, inputSchema);
+ //#endregion
+}
diff --git a/comm/third_party/asn1js/src/types.ts b/comm/third_party/asn1js/src/types.ts
new file mode 100644
index 0000000000..60b5ee414a
--- /dev/null
+++ b/comm/third_party/asn1js/src/types.ts
@@ -0,0 +1,62 @@
+
+export interface IBerConvertible {
+
+ /**
+ * Base function for converting block from BER encoded array of bytes
+ * @param inputBuffer ASN.1 BER encoded array
+ * @param inputOffset Offset in ASN.1 BER encoded array where decoding should be started
+ * @param inputLength Maximum length of array of bytes which can be using in this function
+ * @returns Offset after least decoded byte
+ */
+ fromBER(inputBuffer: ArrayBuffer | Uint8Array, inputOffset: number, inputLength: number): number;
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (BER rules)
+ * @param sizeOnly Flag that we need only a size of encoding, not a real array of bytes
+ * @returns ASN.1 BER encoded array
+ */
+ toBER(sizeOnly?: boolean): ArrayBuffer;
+}
+
+export interface IDerConvertible {
+ /**
+ * Base function for converting block from DER encoded array of bytes
+ * @param inputBuffer ASN.1 DER encoded array
+ * @param inputOffset Offset in ASN.1 DER encoded array where decoding should be started
+ * @param inputLength Maximum length of array of bytes which can be using in this function
+ * @param expectedLength Expected length of converted VALUE_HEX buffer
+ * @returns Offset after least decoded byte
+ */
+ fromDER(inputBuffer: ArrayBuffer, inputOffset: number, inputLength: number, expectedLength?: number): number;
+ /**
+ * Encoding of current ASN.1 block into ASN.1 encoded array (DER rules)
+ * @param sizeOnly Flag that we need only a size of encoding, not a real array of bytes
+ * @returns ASN.1 DER encoded array
+ */
+ toDER(sizeOnly?: boolean): ArrayBuffer;
+}
+
+export interface IStringConvertible {
+ /**
+ * Returns a string representation of an object
+ * @returns String representation of the class object
+ */
+ toString(): string;
+ /**
+ * Creates a class object from the string
+ * @param data Input string to convert from
+ */
+ fromString(data: string): void;
+}
+
+export interface IDateConvertible {
+ /**
+ * Converts a class object into the JavaScrip Date Object
+ * @returns Date object
+ */
+ toDate(): Date;
+ /**
+ * Creates a class object from the JavaScript Date object
+ * @param date Date object
+ */
+ fromDate(date: Date): void;
+} \ No newline at end of file