mirror of
https://github.com/openpgpjs/openpgpjs.git
synced 2025-11-24 14:35:51 +00:00
Delay all errors in not-yet authenticated streams in packet parser
This commit is contained in:
parent
dcf456049e
commit
c60d8c9d91
@ -1,4 +1,4 @@
|
|||||||
import { transformPair as streamTransformPair, transform as streamTransform, getWriter as streamGetWriter, getReader as streamGetReader, clone as streamClone } from '@openpgp/web-stream-tools';
|
import { transformPair as streamTransformPair, transform as streamTransform, getWriter as streamGetWriter, getReader as streamGetReader, clone as streamClone, readToEnd as streamReadToEnd } from '@openpgp/web-stream-tools';
|
||||||
import {
|
import {
|
||||||
readPackets, supportsStreaming,
|
readPackets, supportsStreaming,
|
||||||
writeTag, writeHeader,
|
writeTag, writeHeader,
|
||||||
@ -75,6 +75,7 @@ class PacketList extends Array {
|
|||||||
try {
|
try {
|
||||||
while (true) {
|
while (true) {
|
||||||
await writer.ready;
|
await writer.ready;
|
||||||
|
let error;
|
||||||
const done = await readPackets(readable, async parsed => {
|
const done = await readPackets(readable, async parsed => {
|
||||||
try {
|
try {
|
||||||
if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust || parsed.tag === enums.packet.padding) {
|
if (parsed.tag === enums.packet.marker || parsed.tag === enums.packet.trust || parsed.tag === enums.packet.padding) {
|
||||||
@ -134,7 +135,11 @@ class PacketList extends Array {
|
|||||||
throwDataPacketError ||
|
throwDataPacketError ||
|
||||||
throwOtherError
|
throwOtherError
|
||||||
) {
|
) {
|
||||||
await writer.abort(e);
|
if (bytes.unauthenticated) {
|
||||||
|
error = e;
|
||||||
|
} else {
|
||||||
|
await writer.abort(e);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
const unparsedPacket = new UnparseablePacket(parsed.tag, parsed.packet);
|
const unparsedPacket = new UnparseablePacket(parsed.tag, parsed.packet);
|
||||||
await writer.write(unparsedPacket);
|
await writer.write(unparsedPacket);
|
||||||
@ -142,6 +147,14 @@ class PacketList extends Array {
|
|||||||
util.printDebugError(e);
|
util.printDebugError(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// If there was a parse error, read the entire input first
|
||||||
|
// in case there's an MDC error, which should take precedence.
|
||||||
|
if (error) {
|
||||||
|
await streamReadToEnd(readable);
|
||||||
|
// eslint-disable-next-line @typescript-eslint/no-throw-literal
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
if (done) {
|
if (done) {
|
||||||
// Here we are past the MDC check for SEIPDv1 data, hence
|
// Here we are past the MDC check for SEIPDv1 data, hence
|
||||||
// the data is always authenticated at this point.
|
// the data is always authenticated at this point.
|
||||||
|
|||||||
@ -1382,6 +1382,146 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu
|
|||||||
await expect(openpgp.PacketList.fromBinary(packets.write(), allAllowedPackets, openpgp.config, getMessageGrammarValidator())).to.be.rejectedWith(/Data does not respect OpenPGP grammar/);
|
await expect(openpgp.PacketList.fromBinary(packets.write(), allAllowedPackets, openpgp.config, getMessageGrammarValidator())).to.be.rejectedWith(/Data does not respect OpenPGP grammar/);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('reject duplicate literal packet inside encrypted data', async () => {
|
||||||
|
const literalPackets = new openpgp.PacketList();
|
||||||
|
literalPackets.push(new openpgp.LiteralDataPacket());
|
||||||
|
literalPackets.push(new openpgp.LiteralDataPacket());
|
||||||
|
const encrypted = new openpgp.SymEncryptedIntegrityProtectedDataPacket();
|
||||||
|
encrypted.version = 1;
|
||||||
|
encrypted.packets = literalPackets;
|
||||||
|
const packets = new openpgp.PacketList();
|
||||||
|
packets.push(encrypted);
|
||||||
|
await encrypted.encrypt(openpgp.enums.symmetric.aes128, new Uint8Array(16));
|
||||||
|
await expect(openpgp.decrypt({
|
||||||
|
message: await openpgp.readMessage({
|
||||||
|
binaryMessage: packets.write()
|
||||||
|
}),
|
||||||
|
sessionKeys: [{ algorithm: 'aes128', data: new Uint8Array(16) }]
|
||||||
|
})).to.be.rejectedWith(/Data does not respect OpenPGP grammar/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reject duplicate literal packet inside encrypted data (streaming)', async () => {
|
||||||
|
const literalPackets = new openpgp.PacketList();
|
||||||
|
literalPackets.push(new openpgp.LiteralDataPacket());
|
||||||
|
literalPackets.push(new openpgp.LiteralDataPacket());
|
||||||
|
const encrypted = new openpgp.SymEncryptedIntegrityProtectedDataPacket();
|
||||||
|
encrypted.version = 1;
|
||||||
|
encrypted.packets = literalPackets;
|
||||||
|
const packets = new openpgp.PacketList();
|
||||||
|
packets.push(encrypted);
|
||||||
|
await encrypted.encrypt(openpgp.enums.symmetric.aes128, new Uint8Array(16));
|
||||||
|
const decrypted = await openpgp.decrypt({
|
||||||
|
message: await openpgp.readMessage({
|
||||||
|
binaryMessage: new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue(packets.write());
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
sessionKeys: [{ algorithm: 'aes128', data: new Uint8Array(16) }],
|
||||||
|
config: {
|
||||||
|
allowUnauthenticatedStream: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await expect(stream.readToEnd(decrypted.data)).to.be.rejectedWith(/Data does not respect OpenPGP grammar/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reject duplicate literal packet inside encrypted data (MDC error gets precedence)', async () => {
|
||||||
|
const literalPackets = new openpgp.PacketList();
|
||||||
|
literalPackets.push(new openpgp.LiteralDataPacket());
|
||||||
|
const literal = new openpgp.LiteralDataPacket();
|
||||||
|
literal.data = new Uint8Array(1000);
|
||||||
|
literalPackets.push(literal);
|
||||||
|
const encrypted = new openpgp.SymEncryptedIntegrityProtectedDataPacket();
|
||||||
|
encrypted.version = 1;
|
||||||
|
encrypted.packets = literalPackets;
|
||||||
|
const packets = new openpgp.PacketList();
|
||||||
|
packets.push(encrypted);
|
||||||
|
await encrypted.encrypt(openpgp.enums.symmetric.aes128, new Uint8Array(16));
|
||||||
|
const encryptedData = packets.write();
|
||||||
|
encryptedData[encryptedData.length - 5] ^= 1;
|
||||||
|
const decrypted = await openpgp.decrypt({
|
||||||
|
message: await openpgp.readMessage({
|
||||||
|
binaryMessage: new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue(encryptedData.subarray(0, 500));
|
||||||
|
controller.enqueue(encryptedData.subarray(500));
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
sessionKeys: [{ algorithm: 'aes128', data: new Uint8Array(16) }],
|
||||||
|
config: {
|
||||||
|
allowUnauthenticatedStream: true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
await expect(stream.readToEnd(decrypted.data)).to.be.rejectedWith(/Modification detected/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reject malformed packet inside encrypted data', async () => {
|
||||||
|
const literalPackets = new openpgp.PacketList();
|
||||||
|
const signature = new openpgp.SignaturePacket();
|
||||||
|
signature.signatureData = signature.signedHashValue = new Uint8Array([4, 4]);
|
||||||
|
signature.params = {};
|
||||||
|
literalPackets.push(signature);
|
||||||
|
literalPackets.push(new openpgp.LiteralDataPacket());
|
||||||
|
const encrypted = new openpgp.SymEncryptedIntegrityProtectedDataPacket();
|
||||||
|
encrypted.version = 1;
|
||||||
|
encrypted.packets = literalPackets;
|
||||||
|
const packets = new openpgp.PacketList();
|
||||||
|
packets.push(encrypted);
|
||||||
|
await encrypted.encrypt(openpgp.enums.symmetric.aes128, new Uint8Array(16));
|
||||||
|
const encryptedData = packets.write();
|
||||||
|
await expect(openpgp.decrypt({
|
||||||
|
message: await openpgp.readMessage({
|
||||||
|
binaryMessage: new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue(encryptedData.subarray(0, 500));
|
||||||
|
controller.enqueue(encryptedData.subarray(500));
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
sessionKeys: [{ algorithm: 'aes128', data: new Uint8Array(16) }],
|
||||||
|
config: {
|
||||||
|
allowUnauthenticatedStream: true
|
||||||
|
}
|
||||||
|
})).to.be.rejectedWith(/Missing signature creation time subpacket/);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('reject malformed packet inside encrypted data (MDC error gets precedence)', async () => {
|
||||||
|
const literalPackets = new openpgp.PacketList();
|
||||||
|
const signature = new openpgp.SignaturePacket();
|
||||||
|
signature.signatureData = signature.signedHashValue = new Uint8Array([4, 4]);
|
||||||
|
signature.params = {};
|
||||||
|
literalPackets.push(signature);
|
||||||
|
literalPackets.push(new openpgp.LiteralDataPacket());
|
||||||
|
const encrypted = new openpgp.SymEncryptedIntegrityProtectedDataPacket();
|
||||||
|
encrypted.version = 1;
|
||||||
|
encrypted.packets = literalPackets;
|
||||||
|
const packets = new openpgp.PacketList();
|
||||||
|
packets.push(encrypted);
|
||||||
|
await encrypted.encrypt(openpgp.enums.symmetric.aes128, new Uint8Array(16));
|
||||||
|
const encryptedData = packets.write();
|
||||||
|
encryptedData[encryptedData.length - 5] ^= 1;
|
||||||
|
await expect(openpgp.decrypt({
|
||||||
|
message: await openpgp.readMessage({
|
||||||
|
binaryMessage: new ReadableStream({
|
||||||
|
start(controller) {
|
||||||
|
controller.enqueue(encryptedData.subarray(0, 500));
|
||||||
|
controller.enqueue(encryptedData.subarray(500));
|
||||||
|
controller.close();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
sessionKeys: [{ algorithm: 'aes128', data: new Uint8Array(16) }],
|
||||||
|
config: {
|
||||||
|
allowUnauthenticatedStream: true
|
||||||
|
}
|
||||||
|
})).to.be.rejectedWith(/Modification detected/);
|
||||||
|
});
|
||||||
|
|
||||||
it('accepts padding and marker packets', async () => {
|
it('accepts padding and marker packets', async () => {
|
||||||
const packets = new openpgp.PacketList();
|
const packets = new openpgp.PacketList();
|
||||||
const padding = new openpgp.PaddingPacket();
|
const padding = new openpgp.PaddingPacket();
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user