summaryrefslogtreecommitdiffstats
path: root/comm/third_party/asn1js/src/internals/LocalIdentificationBlock.ts
diff options
context:
space:
mode:
Diffstat (limited to 'comm/third_party/asn1js/src/internals/LocalIdentificationBlock.ts')
-rw-r--r--comm/third_party/asn1js/src/internals/LocalIdentificationBlock.ts280
1 files changed, 280 insertions, 0 deletions
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