@smartdcc/gbcs-parser
Version:
GBCS parser based on henrygiraldo.github.io
592 lines • 24.5 kB
JavaScript
;
/*
*
* Original copyright holders for the GBCS message parser tool:
*
* Copyright (c) 2019 Andre B. Oliveira
* 2019 Enrique Giraldo
* 2019 Cristóbal Borrero
*
* Copyright for subsequent changes, including porting to NodeJS,
* updating for TypeScript and refactor to support unit testing:
*
* Copyright (c) 2022 Smart DCC Limited
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseProvideSecurityCredentialDetailsCommand = parseProvideSecurityCredentialDetailsCommand;
exports.parseProvideSecurityCredentialDetailsResponse = parseProvideSecurityCredentialDetailsResponse;
exports.parseUpdateSecurityCredentialsCommand = parseUpdateSecurityCredentialsCommand;
exports.parseUpdateSecurityCredentialsResponse = parseUpdateSecurityCredentialsResponse;
exports.parseUpdateSecurityCredentialsAlert = parseUpdateSecurityCredentialsAlert;
exports.parseUpdateSecurityCredentialsExecutionOutcome = parseUpdateSecurityCredentialsExecutionOutcome;
exports.parseReplacementOutcome = parseReplacementOutcome;
exports.parseIssueSecurityCredentialsCommand = parseIssueSecurityCredentialsCommand;
exports.parseIssueSecurityCredentialsResponse = parseIssueSecurityCredentialsResponse;
exports.parseUpdateDeviceCertificateCommand = parseUpdateDeviceCertificateCommand;
exports.parseUpdateDeviceCertificateResponse = parseUpdateDeviceCertificateResponse;
exports.parseProvideDeviceCertificateCommand = parseProvideDeviceCertificateCommand;
exports.parseProvideDeviceCertificateResponse = parseProvideDeviceCertificateResponse;
exports.parseJoinDeviceCommand = parseJoinDeviceCommand;
exports.parseJoindDeviceResponse = parseJoindDeviceResponse;
exports.parseUnjoinDeviceCommand = parseUnjoinDeviceCommand;
exports.parseUnjoindDeviceResponse = parseUnjoindDeviceResponse;
exports.parseActivateFirmwareCommand = parseActivateFirmwareCommand;
exports.parseActivateFirmwareResponse = parseActivateFirmwareResponse;
exports.parseActivateFirmwareAlert = parseActivateFirmwareAlert;
exports.parseActivateFirmwareExecutionOutcome = parseActivateFirmwareExecutionOutcome;
exports.parseReadDeviceJoinDetailsCommand = parseReadDeviceJoinDetailsCommand;
exports.parseReadDeviceJoinDetailsResponse = parseReadDeviceJoinDetailsResponse;
exports.parseDeviceLogEntry = parseDeviceLogEntry;
exports.parseFirmwareTransferAlert = parseFirmwareTransferAlert;
exports.parseReadPPMIDHCALCSFirmwareVersionCommand = parseReadPPMIDHCALCSFirmwareVersionCommand;
exports.parseReadPPMIDHCALCSFirmwareVersionResponse = parseReadPPMIDHCALCSFirmwareVersionResponse;
exports.parseReadPPMIDHCALCSFirmwareVersionAlert = parseReadPPMIDHCALCSFirmwareVersionAlert;
exports.parseSetTimeCommand = parseSetTimeCommand;
exports.parseSetTimeResponse = parseSetTimeResponse;
exports.parseGpfDeviceLogRestoreCommand = parseGpfDeviceLogRestoreCommand;
exports.parseGpfDeviceLogRestoreResponse = parseGpfDeviceLogRestoreResponse;
exports.parseGpfDeviceLogBackupAlert = parseGpfDeviceLogBackupAlert;
exports.parseCertificate = parseCertificate;
exports.parseSequence = parseSequence;
// ASN.1 DER Payloads
const common_1 = require("./common");
const context_1 = require("./context");
const util_1 = require("./util");
// CS02a Provide Security Credentials
function parseProvideSecurityCredentialDetailsCommand(ctx, x) {
const s = parseSequence(ctx, x, 'Provide Security Credential Details Command');
const indent = ' ';
parseTrustAnchorCellIdentifier(ctx, s, `${indent}Authorising Remote Party TA Cell Identifier`);
parseSequenceOf(ctx, s, `${indent}Remote Party Roles Credentials Required`, parseRemotePartyRole);
}
function parseProvideSecurityCredentialDetailsResponse(ctx, x) {
parseSequenceOf(ctx, x, 'Provide Security Credential Details Response', (ctx, x, name) => {
parseSequenceOf(ctx, x, `${name}Remote Party Details`, (ctx, x, name) => {
const indent = name.match(/^ */)?.[0] ?? '';
parseRemotePartyRole(ctx, x, indent);
parseStatusCode(ctx, x, indent);
if (x.index < x.end) {
parseSeqNumber(ctx, x, `${indent}Current Seq Number`);
parseSequenceOf(ctx, x, `${indent}Trust Anchor Cell Details`, (ctx, x, name) => {
const indent = (name.match(/^ */)?.[0] ?? '') + ' ';
const s = parseSequence(ctx, x, `${name}Trust Anchor Cell Contents`);
parseKeyUsage(ctx, s, indent);
parseCellUsage(ctx, s, indent);
parseDerOctetString(ctx, s, `${indent}Subject Unique ID`);
parseDerOctetString(ctx, s, `${indent}Subject Key Identifier`);
});
}
});
});
}
// CS02b Update Security Credentials
function parseUpdateSecurityCredentialsCommand(ctx, x) {
const s = parseSequence(ctx, x, 'Update Security Credentials Command');
const indent = ' ';
parseAuthorisingRemotePartyControl(ctx, s, indent);
parseSequenceOf(ctx, s, `${indent}Replacements`, parseTrustAnchorReplacement);
parseSequenceOf(ctx, s, `${indent}Certification Path Certificates`, parseCertificate);
if (isPresent(s, 0x18))
parseGeneralizedTime(ctx, s, `${indent}Execution Date Time`);
}
function parseUpdateSecurityCredentialsResponse(ctx, x) {
const s = parseSequence(ctx, x, 'Update Security Credentials Response');
const indent = ' ';
parseNull(ctx, s, `${indent}Command Accepted`);
if (isPresent(s, 0x30))
parseUpdateSecurityCredentialsExecutionOutcome(ctx, s, indent);
}
function parseUpdateSecurityCredentialsAlert(ctx, x) {
const s = parseSequence(ctx, x, 'Update Security Credentials Alert');
const indent = ' ';
parseAsn1AlertCode(ctx, s, indent);
parseGeneralizedTime(ctx, s, `${indent}Execution Date Time`);
parseUpdateSecurityCredentialsExecutionOutcome(ctx, s, indent);
}
function parseUpdateSecurityCredentialsExecutionOutcome(ctx, x, indent) {
const s = parseSequence(ctx, x, `${indent}Execution Outcome`);
indent = indent + ' ';
parseSeqNumber(ctx, s, `${indent}Authorising Remote Party Seq Number`);
parseCredentialsReplacementMode(ctx, s, indent);
parseSequenceOf(ctx, s, `${indent}Remote Party Seq Number Changes`, parseRemotePartySeqNumberChange);
parseSequenceOf(ctx, s, `${indent}Replacement Outcomes`, parseReplacementOutcome);
}
function parseReplacementOutcome(ctx, x, name) {
const s = parseSequence(ctx, x, `${name}Replacement Outcome`);
const indent = (name.match(/^ */)?.[0] ?? '') + ' ';
parseTrustAnchorCellIdentifier(ctx, s, `${indent}Affected Trust Anchor Cell`);
parseStatusCode(ctx, s, indent);
parseDerOctetString(ctx, s, `${indent}Existing Subject Unique ID`);
parseDerOctetString(ctx, s, `${indent}Existing Subject Key ID`);
parseDerOctetString(ctx, s, `${indent}Replacing Subject Unique ID`);
parseDerOctetString(ctx, s, `${indent}Replacing Subject Key ID`);
}
// CS02c Issue Security Credentials
function parseIssueSecurityCredentialsCommand(ctx, x) {
const s = parseSequence(ctx, x, 'Issue Security Credentials Command');
parseKeyUsage(ctx, s, ' ');
}
function parseIssueSecurityCredentialsResponse(ctx, x) {
if (isPresent(x, 0x30)) {
(0, context_1.putBytes)(ctx, 'Certification Request', x);
}
else {
parseInteger(ctx, x, 'Response Code', {
1: 'Invalid Key Usage',
2: 'Key Pair Generation Failed',
3: 'CR Production Failed',
});
}
}
// CS02d Update Device Certificate on Device
function parseUpdateDeviceCertificateCommand(ctx, x) {
parseCertificate(ctx, x);
}
function parseUpdateDeviceCertificateResponse(ctx, x) {
const responseCodes = {
0: 'Success',
1: 'Invalid Certificate',
2: 'Wrong Device Identity',
3: 'Invalid Key Usage',
4: 'No Corresponding Key Pair Generated',
5: 'Wrong Public Key',
6: 'Certificate Storage Failed',
7: 'Private Key Change Failed',
};
parseInteger(ctx, x, 'Response Code', responseCodes);
}
// CS02e Provide Device Certificate from Device
function parseProvideDeviceCertificateCommand(ctx, x) {
const s = parseSequence(ctx, x, 'Provide Device Certificate Command');
parseKeyUsage(ctx, s, ' ');
}
function parseProvideDeviceCertificateResponse(ctx, x) {
if (isPresent(x, 0x30)) {
parseCertificate(ctx, x);
}
else {
parseInteger(ctx, x, 'Response Code', {
1: 'Invalid Key Usage',
2: 'No Certificate Held',
3: 'Certificate Retrieval Failure',
});
}
}
// CS03XY
function parseJoinDeviceCommand(ctx, x) {
const s = parseSequence(ctx, x, 'Join Device Command');
const indent = ' ';
parseInteger(ctx, s, `${indent}Join Method and Role`, {
0: 'Method A Initiator',
1: 'Method A Responder',
2: 'Method B',
3: 'Method C',
});
parseDerOctetString(ctx, s, `${indent}Entity Id`);
parseDeviceType(ctx, s, indent);
if (s.index < s.end) {
parseCertificate(ctx, s, indent);
}
}
function parseJoindDeviceResponse(ctx, x) {
const responseCodes = {
0: 'Success',
1: 'Invalid Message Code for Join Method and Role',
2: 'Invalid Join Method and Role',
3: 'Incompatible with Existing Entry',
4: 'Device Log Full',
5: 'Write Failure',
6: 'Key Agreement no Resources',
7: 'Key Agreement Unknown Issuer',
8: 'Key Agreement Unsupported Suite',
9: 'Key Agreement Bad Message',
10: 'Key Agreement Bad Key Confirm',
11: 'Invalid or Missing Certificate',
12: 'No Partner Link Key Received',
13: 'No CBKE Response',
};
parseInteger(ctx, x, 'Response Code', responseCodes);
}
// CS04XY
function parseUnjoinDeviceCommand(ctx, x) {
parseDerOctetString(ctx, x, 'Entity Id');
}
function parseUnjoindDeviceResponse(ctx, x) {
parseInteger(ctx, x, 'Response Code', {
0: 'Success',
1: 'Not in Device Log',
2: 'Other Failure',
});
}
// CS06
function parseActivateFirmwareCommand(ctx, x) {
const s = parseSequence(ctx, x, 'Activate Firmware Command');
const indent = ' ';
parseDerOctetString(ctx, s, `${indent}Manufacturer Image Hash`);
parseSeqNumber(ctx, s, `${indent}Originator Counter`);
if (s.index < s.end) {
parseGeneralizedTime(ctx, s, `${indent}Execution Date Time`);
}
}
function parseActivateFirmwareResponse(ctx, x) {
if (isPresent(x, 5)) {
parseNull(ctx, x, 'Command Accepted');
}
else {
parseActivateFirmwareExecutionOutcome(ctx, x, '');
}
}
function parseActivateFirmwareAlert(ctx, x) {
const s = parseSequence(ctx, x, 'Activate Firmware Alert');
const indent = ' ';
parseAsn1AlertCode(ctx, s, indent);
parseGeneralizedTime(ctx, s, `${indent}Execution Date Time`);
parseSeqNumber(ctx, s, `${indent}Originator Counter`);
parseActivateFirmwareExecutionOutcome(ctx, s, indent);
}
function parseActivateFirmwareExecutionOutcome(ctx, x, indent) {
const s = parseSequence(ctx, x, `${indent}Execution Outcome`);
indent = indent + ' ';
parseInteger(ctx, s, `${indent}Response Code`, {
0: 'Success',
1: 'No Image Held',
2: 'Hash Mismatch',
3: 'Activation Failure',
});
parseDerOctetString(ctx, s, `${indent}Firmware Version`);
}
// CS07
function parseReadDeviceJoinDetailsCommand(ctx, x) {
parseNull(ctx, x, 'Read Device Join Details Command');
}
function parseReadDeviceJoinDetailsResponse(ctx, x) {
const s = parseSequence(ctx, x, 'Read Device Join Details Response');
const indent = ' ';
parseInteger(ctx, s, `${indent}Response Code`, {
0: 'Success',
1: 'Read Failure',
});
if (s.index < s.end) {
parseSequenceOf(ctx, s, `${indent}Device Log Entries`, parseDeviceLogEntry);
}
}
function parseDeviceLogEntry(ctx, x, name) {
const s = parseSequence(ctx, x, `${name}Device Log Entry`);
const indent = (name.match(/^ */)?.[0] ?? '') + ' ';
parseDerOctetString(ctx, s, `${indent}Device Id`);
parseDeviceType(ctx, s, indent);
}
// CCS08
function parseFirmwareTransferAlert(ctx, x) {
const s = parseSequence(ctx, x, 'Firmware Transfer Alert');
const indent = ' ';
parseAsn1AlertCode(ctx, s, indent);
parseGeneralizedTime(ctx, s, `${indent}Execution Date Time`);
parseDerOctetString(ctx, s, `${indent}Entity Id`);
parseDerOctetString(ctx, s, `${indent}Firmware Version`);
parseInteger(ctx, s, `${indent}Response Code`, {
0: 'Success',
1: 'Image Discarded',
2: 'Hardware Version Mismatch',
3: 'File Transfer Failure',
});
}
// CS08
function parseReadPPMIDHCALCSFirmwareVersionCommand(ctx, x) {
parseNull(ctx, x, 'Read PPMID HCALCS Firmware version');
}
function parseReadPPMIDHCALCSFirmwareVersionResponse(ctx, x) {
const s = parseSequence(ctx, x, 'Read Device Join Details Response');
const indent = ' ';
parseDerOctetString(ctx, s, `${indent}Firmware Version`);
parseInteger(ctx, s, `${indent}Response Code`, {
0: 'Read Success',
1: 'Read Failure',
});
}
function parseReadPPMIDHCALCSFirmwareVersionAlert(ctx, x) {
const s = parseSequence(ctx, x, 'Read PPMID/HCALCS Firmware Version');
const indent = ' ';
parseAsn1AlertCode(ctx, s, indent);
parseGeneralizedTime(ctx, s, `${indent}Execution Date Time`);
parseDerOctetString(ctx, s, `${indent}Firmware Version`);
parseInteger(ctx, s, `${indent}Activate image`, {
0: 'Success',
1: 'Failure',
});
}
// GCS28
function parseSetTimeCommand(ctx, x) {
const s = parseSequence(ctx, x, 'Set Time Command');
const indent = ' ';
parseGeneralizedTime(ctx, s, `${indent}Validity Interval Start`);
parseGeneralizedTime(ctx, s, `${indent}Validity Interval End`);
}
function parseSetTimeResponse(ctx, x) {
const s = parseSequence(ctx, x, 'Set Time Response');
const indent = ' ';
parseGeneralizedTime(ctx, s, `${indent}Device Time`);
parseInteger(ctx, s, `${indent}Device Time Status`, {
0: 'Reliable',
1: 'Invalid',
2: 'Unreliable',
});
}
// GCS59
function parseGpfDeviceLogRestoreCommand(ctx, x) {
const s = parseSequence(ctx, x, 'GPF Device Log Restore Command');
const indent = ' ';
parseSequenceOf(ctx, s, `${indent}Device Log Entries`, parseDeviceLogEntry);
}
function parseGpfDeviceLogRestoreResponse(ctx, x) {
const s = parseSequence(ctx, x, 'GPF Device Log Restore Response');
const indent = ' ';
parseSequenceOf(ctx, s, `${indent}Restore Outcomes`, parseGpfDeviceLogRestoreOutcome);
}
function parseGpfDeviceLogRestoreOutcome(ctx, x, name) {
const s = parseSequence(ctx, x, `${name}Restore Outcome`);
const indent = (name.match(/^ */)?.[0] ?? '') + ' ';
parseDeviceLogEntry(ctx, s, indent);
const joinResponseCodes = {
0: 'Success',
1: 'Invalid Message Code for Join Method and Role',
2: 'Invalid Join Method and Role',
3: 'Incompatible with Existing Entry',
4: 'Device Log Full',
5: 'Write Failure',
6: 'Key Agreement No Resources',
7: 'Key Agreement Unknown Issuer',
8: 'Key Agreement Unsupported Suite',
9: 'Key Agreement Bad Message',
10: 'Key Agreement Bad Key Confirm',
11: 'Invalid or Missing Certificate',
};
parseInteger(ctx, s, `${indent}Join Response Code`, joinResponseCodes);
}
// GCS62
function parseGpfDeviceLogBackupAlert(ctx, x) {
const s = parseSequence(ctx, x, 'GPF Device Log Backup Alert');
const indent = ' ';
parseAsn1AlertCode(ctx, s, indent);
parseGeneralizedTime(ctx, s, `${indent}Backup Date Time`);
parseSequenceOf(ctx, s, `${indent}Device Log Entries`, parseDeviceLogEntry);
}
// GBCS ASN.1 definitions used by multiple use cases
function parseDeviceType(ctx, x, indent) {
parseInteger(ctx, x, `${indent}Device Type`, {
0: 'GSME',
1: 'ESME',
2: 'CHF',
3: 'GPF',
4: 'HCALCS',
5: 'PPMID',
6: 'Type 2',
});
}
function parseTrustAnchorCellIdentifier(ctx, x, name) {
const indent = (name.match(/^ */)?.[0] ?? '') + ' ';
const s = parseSequence(ctx, x, name);
parseRemotePartyRole(ctx, s, indent);
parseKeyUsage(ctx, s, indent);
parseCellUsage(ctx, s, indent);
}
function parseRemotePartyRole(ctx, x, name) {
const values = {
0: 'Root',
1: 'Recovery',
2: 'Supplier',
3: 'Network Operator',
4: 'Access Control Broker',
5: 'Transitional Change of Supplier',
6: 'WAN Provider',
7: 'Issuing Authority',
127: 'Other',
};
parseInteger(ctx, x, `${name}Remote Party Role`, values);
}
function parseKeyUsage(ctx, x, indent) {
const bits = {
0: 'Digital Signature',
4: 'Key Agreement',
5: 'Key Cert Sign',
6: 'CRL Sign',
};
const length = x.input.byte(x.index + 1);
const bitstring = x.input.byte(x.index + 3);
let notes = '';
for (let i = 0; i < 8; i++) {
if (bitstring & (0x80 >> i)) {
if (bits[i]) {
if (notes)
notes += ' ';
notes += bits[i];
}
}
}
(0, context_1.putBytes)(ctx, `${indent}Key Usage`, (0, util_1.getBytes)(x, 2 + length), notes);
}
// CellUsage ::= INTEGER { management (0), prePaymentTopUp (1) } DEFAULT management
function parseCellUsage(ctx, x, indent) {
if (x.index + 2 < x.end &&
x.input.byte(x.index) === 2 &&
x.input.byte(x.index + 1) === 1) {
if (x.input.byte(x.index + 2) === 1) {
(0, context_1.putBytes)(ctx, `${indent}Cell Usage`, (0, util_1.getBytes)(x, 3), 'Prepayment Top Up');
}
else {
// assume x.input.byte(x.index + 2) === 0
(0, context_1.putBytes)(ctx, `${indent}Cell Usage`, (0, util_1.getBytes)(x, 3), 'Management');
}
}
else {
(0, context_1.putBytes)(ctx, `${indent}Cell Usage`, (0, util_1.getBytes)(x, 0), 'Management (DEFAULT)');
}
}
function parseSeqNumber(ctx, x, name) {
const length = x.input.byte(x.index + 1);
const bytes = (0, util_1.getBytes)(x, 2 + length);
const value = { input: bytes.input, index: bytes.index + 2, end: bytes.end };
(0, context_1.putBytes)(ctx, name, bytes, (0, util_1.getDecimalString)(value));
}
function parseCredentialsReplacementMode(ctx, x, indent) {
const values = {
2: 'Supplier by Supplier',
3: 'Network Operator by Network Operator',
4: 'ACB by ACB',
5: 'WAN Provider by WAN Provider',
6: 'TransCoS by TransCoS',
7: 'Supplier by TransCoS',
8: 'Any Except Abnormal Root by Recovery',
9: 'Any by Contingency',
};
parseInteger(ctx, x, `${indent}Credentials Replacement Mode`, values);
}
function parseAuthorisingRemotePartyControl(ctx, x, indent) {
const s = parseSequence(ctx, x, `${indent}Authorising Remote Party Control`);
indent = indent + ' ';
parseCredentialsReplacementMode(ctx, s, indent);
if (isPresent(s, 0x80))
parseDerOctetString(ctx, s, `${indent}Plaintext Symmetric Key`);
if (isPresent(s, 0x81))
parseInteger(ctx, s, `${indent}Apply Time Based CPV Checks`, {
0: 'Apply',
1: 'Disapply',
});
if (isPresent(s, 0xa2))
parseTrustAnchorCellIdentifier(ctx, s, `${indent}Authorising Remote Party TA Cell Identifier`);
parseSeqNumber(ctx, s, `${indent}Authorising Remote Party Seq Number`);
if (isPresent(s, 0x84))
parseSeqNumber(ctx, s, `${indent}New Remote Party Floor Seq Number`);
if (isPresent(s, 0xa5))
parseSequenceOf(ctx, s, `${indent}New Remote Party Specialist Floor Seq Number`, parseSpecialistSeqNumber);
if (isPresent(s, 0xa6))
parseSequenceOf(ctx, s, `${indent}Other Remote Party Seq Number Changes`, parseRemotePartySeqNumberChange);
}
function parseSpecialistSeqNumber(ctx, x, name) {
const s = parseSequence(ctx, x, `${name}Specialist Seq Number`);
const indent = (name.match(/^ */)?.[0] ?? '') + ' ';
parseInteger(ctx, s, `${indent}Seq Number Usage`, { 0: 'Prepayment Top Up' });
parseSeqNumber(ctx, s, `${indent}Seq Number`);
}
function parseRemotePartySeqNumberChange(ctx, x, name) {
const s = parseSequence(ctx, x, `${name}Remote Party Seq Number Change`);
const indent = (name.match(/^ */)?.[0] ?? '') + ' ';
parseRemotePartyRole(ctx, s, indent);
parseSeqNumber(ctx, s, `${indent}Floor Seq Number`);
if (isPresent(s, 0x30))
parseSequenceOf(ctx, s, `${indent}Specialist Floor Seq Number`, parseSpecialistSeqNumber);
}
function parseTrustAnchorReplacement(ctx, x, name) {
const s = parseSequence(ctx, x, `${name}Trust Anchor Replacement`);
const indent = (name.match(/^ */)?.[0] ?? '') + ' ';
parseCertificate(ctx, s, indent);
parseTrustAnchorCellIdentifier(ctx, s, `${indent}Target Trust Anchor Cell`);
}
// StatusCode ::= ENUMERATED { success (0), ... }
// Used in the CS02a and CS02b responses
function parseStatusCode(ctx, x, indent) {
const values = {
0: 'Success',
5: 'Bad Certificate',
10: 'No Trust Anchor',
17: 'Insufficient Memory',
25: 'Trust Anchor Not Found',
30: 'Resources Busy',
127: 'Other',
};
parseEnumerated(ctx, x, `${indent}Status Code`, values);
}
function parseCertificate(ctx, x, name) {
const lenSz = (0, common_1.parseLength)(x, 1);
const size = 1 + lenSz.size + lenSz.length;
(0, context_1.putBytes)(ctx, name ?? 'Certificate', (0, util_1.getBytes)(x, size));
}
// ASN.1 Types
function parseSequence(ctx, x, name) {
const lenSz = (0, common_1.parseLength)(x, 1);
(0, context_1.putBytes)(ctx, name, (0, util_1.getBytes)(x, 1 + lenSz.size));
return (0, util_1.getBytes)(x, lenSz.length);
}
function parseSequenceOf(ctx, x, name, parse) {
const indent = name.match(/^ */)?.[0] ?? '';
const s = parseSequence(ctx, x, name);
let i = 0;
while (s.index < s.end) {
parse(ctx, s, `${indent} [${i}] `);
i++;
}
}
function parseInteger(ctx, x, name, values) {
let value = 0;
const length = x.input.byte(x.index + 1);
value = (0, common_1.parseNumber)(x, length, 2);
(0, context_1.putBytes)(ctx, name, (0, util_1.getBytes)(x, 2 + length), values?.[value] ?? String(value));
}
function parseAsn1AlertCode(ctx, x, indent) {
let alertCode = 0;
const length = x.input.byte(x.index + 1);
alertCode = (0, common_1.parseNumber)(x, length, 2);
(0, context_1.putBytes)(ctx, `${indent}Alert Code`, (0, util_1.getBytes)(x, 2 + length), (0, util_1.getAlertCodeName)(alertCode));
}
function parseEnumerated(ctx, x, name, values) {
parseInteger(ctx, x, name, values);
}
function parseDerOctetString(ctx, x, name) {
const lenSz = (0, common_1.parseLength)(x, 1);
(0, context_1.putBytes)(ctx, name, (0, util_1.getBytes)(x, 1 + lenSz.size + lenSz.length));
}
function parseGeneralizedTime(ctx, x, name) {
const length = x.input.byte(x.index + 1);
let time = '';
for (let i = 0; i < length; i++) {
const c = x.input.byte(x.index + 2 + i);
if (i === 4 || i === 6)
time += '-';
else if (i === 8 || i === 14)
time += ' ';
else if (i === 10 || i === 12)
time += ':';
time += String.fromCharCode(c);
}
(0, context_1.putBytes)(ctx, name, (0, util_1.getBytes)(x, 2 + length), time);
}
function parseNull(ctx, x, name) {
(0, context_1.putBytes)(ctx, name, (0, util_1.getBytes)(x, 2));
}
function isPresent(x, tag) {
return x.index < x.end && x.input.byte(x.index) === tag;
}
//# sourceMappingURL=asn1.js.map