diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 19:33:14 +0000 |
commit | 36d22d82aa202bb199967e9512281e9a53db42c9 (patch) | |
tree | 105e8c98ddea1c1e4784a60a5a6410fa416be2de /third_party/js/PKI.js/src/SignerInfo.ts | |
parent | Initial commit. (diff) | |
download | firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.tar.xz firefox-esr-36d22d82aa202bb199967e9512281e9a53db42c9.zip |
Adding upstream version 115.7.0esr.upstream/115.7.0esr
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/js/PKI.js/src/SignerInfo.ts')
-rw-r--r-- | third_party/js/PKI.js/src/SignerInfo.ts | 352 |
1 files changed, 352 insertions, 0 deletions
diff --git a/third_party/js/PKI.js/src/SignerInfo.ts b/third_party/js/PKI.js/src/SignerInfo.ts new file mode 100644 index 0000000000..a6f59805dd --- /dev/null +++ b/third_party/js/PKI.js/src/SignerInfo.ts @@ -0,0 +1,352 @@ +import * as asn1js from "asn1js"; +import * as pvutils from "pvutils"; +import { AlgorithmIdentifier, AlgorithmIdentifierJson, AlgorithmIdentifierSchema } from "./AlgorithmIdentifier"; +import { SignedAndUnsignedAttributes, SignedAndUnsignedAttributesJson, SignedAndUnsignedAttributesSchema } from "./SignedAndUnsignedAttributes"; +import { IssuerAndSerialNumber, IssuerAndSerialNumberSchema } from "./IssuerAndSerialNumber"; +import * as Schema from "./Schema"; +import { PkiObject, PkiObjectParameters } from "./PkiObject"; +import { AsnError } from "./errors"; + +const VERSION = "version"; +const SID = "sid"; +const DIGEST_ALGORITHM = "digestAlgorithm"; +const SIGNED_ATTRS = "signedAttrs"; +const SIGNATURE_ALGORITHM = "signatureAlgorithm"; +const SIGNATURE = "signature"; +const UNSIGNED_ATTRS = "unsignedAttrs"; +const SIGNER_INFO = "SignerInfo"; +const SIGNER_INFO_VERSION = `${SIGNER_INFO}.${VERSION}`; +const SIGNER_INFO_SID = `${SIGNER_INFO}.${SID}`; +const SIGNER_INFO_DIGEST_ALGORITHM = `${SIGNER_INFO}.${DIGEST_ALGORITHM}`; +const SIGNER_INFO_SIGNED_ATTRS = `${SIGNER_INFO}.${SIGNED_ATTRS}`; +const SIGNER_INFO_SIGNATURE_ALGORITHM = `${SIGNER_INFO}.${SIGNATURE_ALGORITHM}`; +const SIGNER_INFO_SIGNATURE = `${SIGNER_INFO}.${SIGNATURE}`; +const SIGNER_INFO_UNSIGNED_ATTRS = `${SIGNER_INFO}.${UNSIGNED_ATTRS}`; +const CLEAR_PROPS = [ + SIGNER_INFO_VERSION, + SIGNER_INFO_SID, + SIGNER_INFO_DIGEST_ALGORITHM, + SIGNER_INFO_SIGNED_ATTRS, + SIGNER_INFO_SIGNATURE_ALGORITHM, + SIGNER_INFO_SIGNATURE, + SIGNER_INFO_UNSIGNED_ATTRS +]; + +export interface ISignerInfo { + version: number; + sid: Schema.SchemaType; + digestAlgorithm: AlgorithmIdentifier; + signedAttrs?: SignedAndUnsignedAttributes; + signatureAlgorithm: AlgorithmIdentifier; + signature: asn1js.OctetString; + unsignedAttrs?: SignedAndUnsignedAttributes; +} + +export interface SignerInfoJson { + version: number; + sid?: Schema.SchemaType; + digestAlgorithm: AlgorithmIdentifierJson; + signedAttrs?: SignedAndUnsignedAttributesJson; + signatureAlgorithm: AlgorithmIdentifierJson; + signature: asn1js.OctetStringJson; + unsignedAttrs?: SignedAndUnsignedAttributesJson; +} + +export type SignerInfoParameters = PkiObjectParameters & Partial<ISignerInfo>; + +/** + * Represents the SignerInfo structure described in [RFC5652](https://datatracker.ietf.org/doc/html/rfc5652) + */ +export class SignerInfo extends PkiObject implements ISignerInfo { + + public static override CLASS_NAME = "SignerInfo"; + + public version!: number; + public sid: Schema.SchemaType; + public digestAlgorithm!: AlgorithmIdentifier; + public signedAttrs?: SignedAndUnsignedAttributes; + public signatureAlgorithm!: AlgorithmIdentifier; + public signature!: asn1js.OctetString; + public unsignedAttrs?: SignedAndUnsignedAttributes; + + /** + * Initializes a new instance of the {@link SignerInfo} class + * @param parameters Initialization parameters + */ + constructor(parameters: SignerInfoParameters = {}) { + super(); + + this.version = pvutils.getParametersValue(parameters, VERSION, SignerInfo.defaultValues(VERSION)); + this.sid = pvutils.getParametersValue(parameters, SID, SignerInfo.defaultValues(SID)); + this.digestAlgorithm = pvutils.getParametersValue(parameters, DIGEST_ALGORITHM, SignerInfo.defaultValues(DIGEST_ALGORITHM)); + if (SIGNED_ATTRS in parameters) { + this.signedAttrs = pvutils.getParametersValue(parameters, SIGNED_ATTRS, SignerInfo.defaultValues(SIGNED_ATTRS)); + } + this.signatureAlgorithm = pvutils.getParametersValue(parameters, SIGNATURE_ALGORITHM, SignerInfo.defaultValues(SIGNATURE_ALGORITHM)); + this.signature = pvutils.getParametersValue(parameters, SIGNATURE, SignerInfo.defaultValues(SIGNATURE)); + if (UNSIGNED_ATTRS in parameters) { + this.unsignedAttrs = pvutils.getParametersValue(parameters, UNSIGNED_ATTRS, SignerInfo.defaultValues(UNSIGNED_ATTRS)); + } + + if (parameters.schema) { + this.fromSchema(parameters.schema); + } + } + + /** + * Returns default values for all class members + * @param memberName String name for a class member + * @returns Default value + */ + public static override defaultValues(memberName: typeof VERSION): number; + public static override defaultValues(memberName: typeof SID): Schema.SchemaType; + public static override defaultValues(memberName: typeof DIGEST_ALGORITHM): AlgorithmIdentifier; + public static override defaultValues(memberName: typeof SIGNED_ATTRS): SignedAndUnsignedAttributes; + public static override defaultValues(memberName: typeof SIGNATURE_ALGORITHM): AlgorithmIdentifier; + public static override defaultValues(memberName: typeof SIGNATURE): asn1js.OctetString; + public static override defaultValues(memberName: typeof UNSIGNED_ATTRS): SignedAndUnsignedAttributes; + public static override defaultValues(memberName: string): any { + switch (memberName) { + case VERSION: + return 0; + case SID: + return new asn1js.Any(); + case DIGEST_ALGORITHM: + return new AlgorithmIdentifier(); + case SIGNED_ATTRS: + return new SignedAndUnsignedAttributes({ type: 0 }); + case SIGNATURE_ALGORITHM: + return new AlgorithmIdentifier(); + case SIGNATURE: + return new asn1js.OctetString(); + case UNSIGNED_ATTRS: + return new SignedAndUnsignedAttributes({ type: 1 }); + default: + return super.defaultValues(memberName); + } + } + + /** + * Compare values with default values for all class members + * @param memberName String name for a class member + * @param memberValue Value to compare with default value + */ + public static compareWithDefault(memberName: string, memberValue: any): boolean { + switch (memberName) { + case VERSION: + return (SignerInfo.defaultValues(VERSION) === memberValue); + case SID: + return (memberValue instanceof asn1js.Any); + case DIGEST_ALGORITHM: + if ((memberValue instanceof AlgorithmIdentifier) === false) + return false; + + return memberValue.isEqual(SignerInfo.defaultValues(DIGEST_ALGORITHM)); + case SIGNED_ATTRS: + return ((SignedAndUnsignedAttributes.compareWithDefault("type", memberValue.type)) + && (SignedAndUnsignedAttributes.compareWithDefault("attributes", memberValue.attributes)) + && (SignedAndUnsignedAttributes.compareWithDefault("encodedValue", memberValue.encodedValue))); + case SIGNATURE_ALGORITHM: + if ((memberValue instanceof AlgorithmIdentifier) === false) + return false; + + return memberValue.isEqual(SignerInfo.defaultValues(SIGNATURE_ALGORITHM)); + case SIGNATURE: + case UNSIGNED_ATTRS: + return ((SignedAndUnsignedAttributes.compareWithDefault("type", memberValue.type)) + && (SignedAndUnsignedAttributes.compareWithDefault("attributes", memberValue.attributes)) + && (SignedAndUnsignedAttributes.compareWithDefault("encodedValue", memberValue.encodedValue))); + default: + return super.defaultValues(memberName); + } + } + + /** + * @inheritdoc + * @asn ASN.1 schema + * ```asn + * SignerInfo ::= SEQUENCE { + * version CMSVersion, + * sid SignerIdentifier, + * digestAlgorithm DigestAlgorithmIdentifier, + * signedAttrs [0] IMPLICIT SignedAttributes OPTIONAL, + * signatureAlgorithm SignatureAlgorithmIdentifier, + * signature SignatureValue, + * unsignedAttrs [1] IMPLICIT UnsignedAttributes OPTIONAL } + * + * SignerIdentifier ::= CHOICE { + * issuerAndSerialNumber IssuerAndSerialNumber, + * subjectKeyIdentifier [0] SubjectKeyIdentifier } + * + * SubjectKeyIdentifier ::= OCTET STRING + *``` + */ + public static override schema(parameters: Schema.SchemaParameters<{ + version?: string; + sidSchema?: IssuerAndSerialNumberSchema; + sid?: string; + digestAlgorithm?: AlgorithmIdentifierSchema; + signedAttrs?: SignedAndUnsignedAttributesSchema; + signatureAlgorithm?: AlgorithmIdentifierSchema; + signature?: string; + unsignedAttrs?: SignedAndUnsignedAttributesSchema; + }> = {}): Schema.SchemaType { + const names = pvutils.getParametersValue<NonNullable<typeof parameters.names>>(parameters, "names", {}); + + return ( + new asn1js.Sequence({ + name: SIGNER_INFO, + value: [ + new asn1js.Integer({ name: (names.version || SIGNER_INFO_VERSION) }), + new asn1js.Choice({ + value: [ + IssuerAndSerialNumber.schema(names.sidSchema || { + names: { + blockName: SIGNER_INFO_SID + } + }), + new asn1js.Choice({ + value: [ + new asn1js.Constructed({ + optional: true, + name: (names.sid || SIGNER_INFO_SID), + idBlock: { + tagClass: 3, // CONTEXT-SPECIFIC + tagNumber: 0 // [0] + }, + value: [new asn1js.OctetString()] + }), + new asn1js.Primitive({ + optional: true, + name: (names.sid || SIGNER_INFO_SID), + idBlock: { + tagClass: 3, // CONTEXT-SPECIFIC + tagNumber: 0 // [0] + } + }), + ] + }), + ] + }), + AlgorithmIdentifier.schema(names.digestAlgorithm || { + names: { + blockName: SIGNER_INFO_DIGEST_ALGORITHM + } + }), + SignedAndUnsignedAttributes.schema(names.signedAttrs || { + names: { + blockName: SIGNER_INFO_SIGNED_ATTRS, + tagNumber: 0 + } + }), + AlgorithmIdentifier.schema(names.signatureAlgorithm || { + names: { + blockName: SIGNER_INFO_SIGNATURE_ALGORITHM + } + }), + new asn1js.OctetString({ name: (names.signature || SIGNER_INFO_SIGNATURE) }), + SignedAndUnsignedAttributes.schema(names.unsignedAttrs || { + names: { + blockName: SIGNER_INFO_UNSIGNED_ATTRS, + tagNumber: 1 + } + }) + ] + }) + ); + } + + public fromSchema(schema: Schema.SchemaType): void { + // Clear input data first + pvutils.clearProps(schema, CLEAR_PROPS); + + // Check the schema is valid + const asn1 = asn1js.compareSchema(schema, + schema, + SignerInfo.schema() + ); + AsnError.assertSchema(asn1, this.className); + + // Get internal properties from parsed schema + this.version = asn1.result[SIGNER_INFO_VERSION].valueBlock.valueDec; + + const currentSid = asn1.result[SIGNER_INFO_SID]; + if (currentSid.idBlock.tagClass === 1) + this.sid = new IssuerAndSerialNumber({ schema: currentSid }); + else + this.sid = currentSid; + + this.digestAlgorithm = new AlgorithmIdentifier({ schema: asn1.result[SIGNER_INFO_DIGEST_ALGORITHM] }); + if (SIGNER_INFO_SIGNED_ATTRS in asn1.result) + this.signedAttrs = new SignedAndUnsignedAttributes({ type: 0, schema: asn1.result[SIGNER_INFO_SIGNED_ATTRS] }); + + this.signatureAlgorithm = new AlgorithmIdentifier({ schema: asn1.result[SIGNER_INFO_SIGNATURE_ALGORITHM] }); + this.signature = asn1.result[SIGNER_INFO_SIGNATURE]; + if (SIGNER_INFO_UNSIGNED_ATTRS in asn1.result) + this.unsignedAttrs = new SignedAndUnsignedAttributes({ type: 1, schema: asn1.result[SIGNER_INFO_UNSIGNED_ATTRS] }); + } + + public toSchema(): asn1js.Sequence { + if (SignerInfo.compareWithDefault(SID, this.sid)) + throw new Error("Incorrectly initialized \"SignerInfo\" class"); + + //#region Create array for output sequence + const outputArray = []; + + outputArray.push(new asn1js.Integer({ value: this.version })); + + if (this.sid instanceof IssuerAndSerialNumber) + outputArray.push(this.sid.toSchema()); + else + outputArray.push(this.sid); + + outputArray.push(this.digestAlgorithm.toSchema()); + + if (this.signedAttrs) { + if (SignerInfo.compareWithDefault(SIGNED_ATTRS, this.signedAttrs) === false) + outputArray.push(this.signedAttrs.toSchema()); + } + + outputArray.push(this.signatureAlgorithm.toSchema()); + outputArray.push(this.signature); + + if (this.unsignedAttrs) { + if (SignerInfo.compareWithDefault(UNSIGNED_ATTRS, this.unsignedAttrs) === false) + outputArray.push(this.unsignedAttrs.toSchema()); + } + //#endregion + + //#region Construct and return new ASN.1 schema for this object + return (new asn1js.Sequence({ + value: outputArray + })); + //#endregion + } + + public toJSON(): SignerInfoJson { + if (SignerInfo.compareWithDefault(SID, this.sid)) { + throw new Error("Incorrectly initialized \"SignerInfo\" class"); + } + + const res: SignerInfoJson = { + version: this.version, + digestAlgorithm: this.digestAlgorithm.toJSON(), + signatureAlgorithm: this.signatureAlgorithm.toJSON(), + signature: this.signature.toJSON(), + }; + + if (!(this.sid instanceof asn1js.Any)) + res.sid = this.sid.toJSON(); + + if (this.signedAttrs && SignerInfo.compareWithDefault(SIGNED_ATTRS, this.signedAttrs) === false) { + res.signedAttrs = this.signedAttrs.toJSON(); + } + + if (this.unsignedAttrs && SignerInfo.compareWithDefault(UNSIGNED_ATTRS, this.unsignedAttrs) === false) { + res.unsignedAttrs = this.unsignedAttrs.toJSON(); + } + + return res; + } + +} |