From bba445103f8e1e2ebfb11e252e1a77c4b887e809 Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Mon, 23 May 2022 17:13:36 +0200 Subject: [PATCH] Throw UnsupportedError on unknown algorithm in keys and signatures --- src/crypto/crypto.js | 5 +++-- src/crypto/signature.js | 3 ++- src/packet/public_key.js | 1 + src/packet/secret_key.js | 3 +++ test/general/packet.js | 26 ++++++++++++++++++++++++++ 5 files changed, 35 insertions(+), 3 deletions(-) diff --git a/src/crypto/crypto.js b/src/crypto/crypto.js index 4980473375..06790dd583 100644 --- a/src/crypto/crypto.js +++ b/src/crypto/crypto.js @@ -34,6 +34,7 @@ import enums from '../enums'; import util from '../util'; import OID from '../type/oid'; import { Curve } from './public_key/elliptic/curves'; +import { UnsupportedError } from '../packet/packet'; /** * Encrypts data using specified algorithm and public key parameters. @@ -156,7 +157,7 @@ export function parsePublicKeyParams(algo, bytes) { return { read: read, publicParams: { oid, Q, kdfParams } }; } default: - throw new Error('Invalid public key encryption algorithm.'); + throw new UnsupportedError('Invalid public key encryption algorithm.'); } } @@ -197,7 +198,7 @@ export function parsePrivateKeyParams(algo, bytes, publicParams) { return { read, privateParams: { seed } }; } default: - throw new Error('Invalid public key encryption algorithm.'); + throw new UnsupportedError('Invalid public key encryption algorithm.'); } } diff --git a/src/crypto/signature.js b/src/crypto/signature.js index 012db2035d..f1c69b7011 100644 --- a/src/crypto/signature.js +++ b/src/crypto/signature.js @@ -7,6 +7,7 @@ import publicKey from './public_key'; import enums from '../enums'; import util from '../util'; +import { UnsupportedError } from '../packet/packet'; /** * Parse signature in binary form to get the parameters. @@ -55,7 +56,7 @@ export function parseSignatureParams(algo, signature) { return { r, s }; } default: - throw new Error('Invalid signature algorithm.'); + throw new UnsupportedError('Invalid signature algorithm.'); } } diff --git a/src/packet/public_key.js b/src/packet/public_key.js index 4a1ef78880..40fa0bd2a4 100644 --- a/src/packet/public_key.js +++ b/src/packet/public_key.js @@ -128,6 +128,7 @@ class PublicKeyPacket { this.publicParams = publicParams; pos += read; } catch (err) { + if (err instanceof UnsupportedError) throw err; throw new Error('Error reading MPIs'); } diff --git a/src/packet/secret_key.js b/src/packet/secret_key.js index 016fbd4f42..02b5631f8a 100644 --- a/src/packet/secret_key.js +++ b/src/packet/secret_key.js @@ -21,6 +21,7 @@ import crypto from '../crypto'; import enums from '../enums'; import util from '../util'; import defaultConfig from '../config'; +import { UnsupportedError } from './packet'; /** * A Secret-Key packet contains all the information that is found in a @@ -155,6 +156,8 @@ class SecretKeyPacket extends PublicKeyPacket { const { privateParams } = crypto.parsePrivateKeyParams(this.algorithm, cleartext, this.publicParams); this.privateParams = privateParams; } catch (err) { + if (err instanceof UnsupportedError) throw err; + // avoid throwing potentially sensitive errors throw new Error('Error reading MPIs'); } } diff --git a/test/general/packet.js b/test/general/packet.js index a99fe86b9d..abb7883c01 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -996,6 +996,32 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu ).to.be.rejectedWith(/Version 1 of the signature packet is unsupported/); }); + it('Ignores unknown signature algorithm only with `config.ignoreUnsupportedPackets` enabled', async function() { + const binarySignature = util.hexToUint8Array('c2750401630a00060502628b8e2200210910f30ddfc2310b3560162104b9b0045c1930f842cb245566f30ddfc2310b35602ded0100bd69fe6a9f52499cd8b2fd2493dae91c997979890df4467cf31b197901590ff10100ead4c671487535b718a8428c8e6099e3873a41610aad9fcdaa06f6df5f404002'); + + const parsed = await openpgp.PacketList.fromBinary(binarySignature, allAllowedPackets, { ...openpgp.config, ignoreUnsupportedPackets: true }); + expect(parsed.length).to.equal(1); + expect(parsed[0]).instanceOf(openpgp.UnparsablePacket); + expect(parsed[0].tag).to.equal(openpgp.enums.packet.signature); + + await expect( + openpgp.PacketList.fromBinary(binarySignature, allAllowedPackets, { ...openpgp.config, ignoreUnsupportedPackets: false }) + ).to.be.rejectedWith(/Invalid signature algorithm/); + }); + + it('Ignores unknown key algorithm only with `config.ignoreUnsupportedPackets` enabled', async function() { + const binaryKey = util.hexToUint8Array('c55804628b944e63092b06010401da470f01010740d01ab8619b6dc6a36da5bff62ff416a974900f5a8c74d1bd1760d717d0aad8d50000ff516f8e3190aa5b394597655d7c32e16392e638da0e2a869fb7b1f429d9de263d1062cd0f3c7465737440746573742e636f6d3ec28c0410160a001d0502628b944e040b0907080315080a0416000201021901021b03021e01002109104803e40df201fa5b16210496dc42e91cc585e2f5e331644803e40df201fa5b340b0100812c47b60fa509e12e329fc37cc9c437cc6a6500915caa03ad8703db849846f900ff571b9a0d9e1dcc087d9fae04ec2906e60ef40ca02a387eb07ce1c37bedeecd0a'); + + const parsed = await openpgp.PacketList.fromBinary(binaryKey, allAllowedPackets, { ...openpgp.config, ignoreUnsupportedPackets: true }); + expect(parsed.length).to.equal(3); + expect(parsed[0]).instanceOf(openpgp.UnparsablePacket); + expect(parsed[0].tag).to.equal(openpgp.enums.packet.secretKey); + + await expect( + openpgp.PacketList.fromBinary(binaryKey, allAllowedPackets, { ...openpgp.config, ignoreUnsupportedPackets: false }) + ).to.be.rejectedWith(/Invalid public key encryption algorithm/); + }); + it('Throws on disallowed packet even with tolerant mode enabled', async function() { const packets = new openpgp.PacketList(); packets.push(new openpgp.LiteralDataPacket());