mirror of
https://github.com/morluto/rea.git
synced 2026-10-26 17:35:11 +00:00
fix(asn1): decode four-byte BER lengths unsigned
Accumulate length octets arithmetically so a four-octet length with bit 31 set remains a positive unsigned value and is rejected by the containing-range check rather than becoming a negative length.
This commit is contained in:
1 parent
ef05713d86
commit
3a2074b633
4 files changed
+42
-2
No files matched your search
@@ -244,3 +244,24 @@ it("rejects non-OCTET children inside a constructed signature", () => {
|
||||
).kind,
|
||||
).toBe("malformed-pkcs7");
|
||||
});
|
||||
|
||||
it.each([
|
||||
["primitive", 0x04],
|
||||
["constructed", 0x24],
|
||||
] as const)(
|
||||
"rejects a high-bit four-octet BER length on a %s signature field",
|
||||
(_kind, tag) => {
|
||||
const signature = Uint8Array.of(tag, 0x84, 0x80, 0, 0, 0);
|
||||
expect(
|
||||
errorOf(
|
||||
signedDataBlock({
|
||||
certificates: [LEAF_CERTIFICATE],
|
||||
signerInfos: [signerInfo({ names: LEAF_CERTIFICATE, signature })],
|
||||
}),
|
||||
),
|
||||
).toEqual({
|
||||
kind: "malformed-pkcs7",
|
||||
detail: "ASN.1 value exceeds its parent.",
|
||||
});
|
||||
},
|
||||
);
|
||||
@@ -90,7 +90,8 @@ export class Asn1BerReader {
|
||||
for (let index = 0; index < width; index += 1) {
|
||||
const byte = this.bytes[cursor];
|
||||
if (byte === undefined) return fail("Truncated ASN.1 length.");
|
||||
length = (length << 8) | byte;
|
||||
// Bitwise shifts sign-extend a four-octet length with bit 31 set.
|
||||
length = length * 256 + byte;
|
||||
cursor += 1;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,6 +94,23 @@ it("reads BER indefinite constructed ContentInfo and preserves certificate bytes
|
||||
);
|
||||
});
|
||||
|
||||
it.each([
|
||||
["primitive", 0x04],
|
||||
["constructed", 0x24],
|
||||
] as const)(
|
||||
"rejects a high-bit four-octet BER length on a %s SignerInfo signature",
|
||||
(_kind, tag) => {
|
||||
const payload = pkcs7SignedDataFixture(
|
||||
"REA Fixture",
|
||||
"REA Tests",
|
||||
Buffer.from([tag, 0x84, 0x80, 0, 0, 0]),
|
||||
);
|
||||
expect(() => parse(peCertificateFixture(false, payload))).toThrow(
|
||||
/PKCS#7 signedData is malformed: ASN\.1 value exceeds its parent\./u,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it("matches nested indefinite constructed values and rejects invalid EOC forms", () => {
|
||||
const nested = readAsn1(
|
||||
Buffer.from([0x30, 0x80, 0x30, 0x80, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00]),
|
||||
|
||||
@@ -66,6 +66,7 @@ const algorithm = (identifier: Buffer): Buffer => seq(identifier, nul());
|
||||
export const pkcs7SignedDataFixture = (
|
||||
commonName = "REA Fixture",
|
||||
organization = "REA Tests",
|
||||
signature = octet(Buffer.from("sig")),
|
||||
): Buffer => {
|
||||
const serial = Buffer.from([0x11, 0x22, 0x33, 0x44]);
|
||||
const subject = name(commonName, organization);
|
||||
@@ -92,7 +93,7 @@ export const pkcs7SignedDataFixture = (
|
||||
seq(subject, integer(serial)),
|
||||
algorithm(SHA256),
|
||||
algorithm(SHA256_RSA),
|
||||
octet(Buffer.from("sig")),
|
||||
signature,
|
||||
);
|
||||
const signedData = seq(
|
||||
integer(1),
|
||||
|
||||
Reference in new issue
Block a user