Skip to content

Commit d252f96

Browse files
committed
merge of github #2123 with minor corrections
1 parent 1a47dd0 commit d252f96

24 files changed

+420
-121
lines changed

pg/src/main/java/org/bouncycastle/bcpg/AEADEncDataPacket.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,22 @@ public AEADEncDataPacket(BCPGInputStream in,
4040
version = (byte)in.read();
4141
if (version != VERSION_1)
4242
{
43-
throw new UnsupportedPacketVersionException("wrong AEAD packet version: " + version);
43+
throw new UnsupportedPacketVersionException("Unknown AEAD packet version: " + version);
4444
}
4545

4646
algorithm = (byte)in.read();
4747
aeadAlgorithm = (byte)in.read();
4848
chunkSize = (byte)in.read();
4949

50-
iv = new byte[AEADUtils.getIVLength(aeadAlgorithm)];
50+
try
51+
{
52+
int ivLen = AEADUtils.getIVLength(aeadAlgorithm);
53+
iv = new byte[ivLen];
54+
}
55+
catch (IllegalArgumentException e)
56+
{
57+
throw new MalformedPacketException("Unknown AEAD algorithm ID: " + aeadAlgorithm, e);
58+
}
5159
in.readFully(iv);
5260
}
5361

pg/src/main/java/org/bouncycastle/bcpg/ECDHPublicBCPGKey.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,12 @@ public ECDHPublicBCPGKey(
3636
super(in);
3737

3838
int length = in.read();
39-
byte[] kdfParameters = new byte[length];
40-
if (kdfParameters.length != 3)
39+
if (length != 3)
4140
{
42-
throw new IllegalStateException("kdf parameters size of 3 expected.");
41+
throw new MalformedPacketException("KDF parameters size of 3 expected.");
4342
}
4443

44+
byte[] kdfParameters = new byte[length];
4545
in.readFully(kdfParameters);
4646

4747
reserved = kdfParameters[0];

pg/src/main/java/org/bouncycastle/bcpg/LiteralDataPacket.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ public class LiteralDataPacket
3131

3232
format = in.read();
3333
int l = in.read();
34+
if (l < 0)
35+
{
36+
throw new MalformedPacketException("File name size cannot be negative.");
37+
}
3438

3539
fileName = new byte[l];
3640
for (int i = 0; i != fileName.length; i++)
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.bouncycastle.bcpg;
2+
3+
import java.io.IOException;
4+
5+
public class MalformedPacketException
6+
extends IOException
7+
{
8+
9+
public MalformedPacketException(String message)
10+
{
11+
super(message);
12+
}
13+
14+
public MalformedPacketException(Throwable cause)
15+
{
16+
super(cause);
17+
}
18+
19+
public MalformedPacketException(String message, Throwable cause)
20+
{
21+
super(message, cause);
22+
}
23+
}

pg/src/main/java/org/bouncycastle/bcpg/OctetArrayBCPGKey.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@ public abstract class OctetArrayBCPGKey
1515
OctetArrayBCPGKey(int length, BCPGInputStream in)
1616
throws IOException
1717
{
18+
if (length > PublicKeyPacket.MAX_LEN)
19+
{
20+
throw new IOException("Max key length (" + PublicKeyPacket.MAX_LEN + ") exceeded (" + length + ")");
21+
}
1822
key = new byte[length];
1923
in.readFully(key);
2024
}

pg/src/main/java/org/bouncycastle/bcpg/Packet.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,4 +60,18 @@ public boolean isCritical()
6060
{
6161
return getPacketTag() <= 39;
6262
}
63+
64+
static int sanitizeLength(int len, int max, String variableName)
65+
throws MalformedPacketException
66+
{
67+
if (len < 0)
68+
{
69+
throw new MalformedPacketException(variableName + " cannot be negative.");
70+
}
71+
if (len > max)
72+
{
73+
throw new MalformedPacketException(variableName + " (" + len + ") exceeds limit (" + max + ").");
74+
}
75+
return len;
76+
}
6377
}

pg/src/main/java/org/bouncycastle/bcpg/PublicKeyEncSessionPacket.java

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ public class PublicKeyEncSessionPacket
5555
else if (version == VERSION_6)
5656
{
5757
int keyInfoLen = in.read();
58+
if (keyInfoLen < 0)
59+
{
60+
throw new MalformedPacketException("Key Info Length cannot be negative: " + keyInfoLen);
61+
}
5862
if (keyInfoLen == 0)
5963
{
6064
// anon recipient
@@ -69,13 +73,20 @@ else if (version == VERSION_6)
6973
in.readFully(keyFingerprint);
7074
// Derived key-ID from fingerprint
7175
// TODO: Replace with getKeyIdentifier
72-
if (keyVersion == PublicKeyPacket.VERSION_4)
76+
try
7377
{
74-
keyID = FingerprintUtil.keyIdFromV4Fingerprint(keyFingerprint);
78+
if (keyVersion == PublicKeyPacket.VERSION_4)
79+
{
80+
keyID = FingerprintUtil.keyIdFromV4Fingerprint(keyFingerprint);
81+
}
82+
else
83+
{
84+
keyID = FingerprintUtil.keyIdFromV6Fingerprint(keyFingerprint);
85+
}
7586
}
76-
else
87+
catch (IllegalArgumentException e)
7788
{
78-
keyID = FingerprintUtil.keyIdFromV6Fingerprint(keyFingerprint);
89+
throw new MalformedPacketException("Malformed fingerprint encoding.", e);
7990
}
8091
}
8192
}

pg/src/main/java/org/bouncycastle/bcpg/PublicKeyPacket.java

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public class PublicKeyPacket
2222
extends ContainedPacket
2323
implements PublicKeyAlgorithmTags
2424
{
25+
public final static int MAX_LEN = 2 * 1024 * 1024; // 2mb; McEliece keys can get ~1mb in size, so allow some margin
26+
2527
/**
2628
* OpenPGP v3 keys are deprecated.
2729
* They can only be used with RSA.
@@ -150,6 +152,10 @@ public class PublicKeyPacket
150152
{
151153
// TODO: Use keyOctets to be able to parse unknown keys
152154
keyOctets = StreamUtil.read4OctetLength(in);
155+
if (keyOctets < 0)
156+
{
157+
throw new MalformedPacketException("Octet length cannot be negative.");
158+
}
153159
}
154160

155161
parseKey(in, algorithm, keyOctets);
@@ -166,49 +172,56 @@ private void parseKey(BCPGInputStream in, int algorithmId, long optLen)
166172
throws IOException
167173
{
168174

169-
switch (algorithmId)
175+
try
170176
{
171-
case RSA_ENCRYPT:
172-
case RSA_GENERAL:
173-
case RSA_SIGN:
174-
key = new RSAPublicBCPGKey(in);
175-
break;
176-
case DSA:
177-
key = new DSAPublicBCPGKey(in);
178-
break;
179-
case ELGAMAL_ENCRYPT:
180-
case ELGAMAL_GENERAL:
181-
key = new ElGamalPublicBCPGKey(in);
182-
break;
183-
case ECDH:
184-
key = new ECDHPublicBCPGKey(in);
185-
break;
186-
case X25519:
187-
key = new X25519PublicBCPGKey(in);
188-
break;
189-
case X448:
190-
key = new X448PublicBCPGKey(in);
191-
break;
192-
case ECDSA:
193-
key = new ECDSAPublicBCPGKey(in);
194-
break;
195-
case EDDSA_LEGACY:
196-
key = new EdDSAPublicBCPGKey(in);
197-
break;
198-
case Ed25519:
199-
key = new Ed25519PublicBCPGKey(in);
200-
break;
201-
case Ed448:
202-
key = new Ed448PublicBCPGKey(in);
203-
break;
204-
default:
205-
if (version == VERSION_6 || version == LIBREPGP_5)
177+
switch (algorithmId)
206178
{
207-
// with version 5 & 6, we can gracefully handle unknown key types, as the length is known.
208-
key = new UnknownBCPGKey((int) optLen, in);
179+
case RSA_ENCRYPT:
180+
case RSA_GENERAL:
181+
case RSA_SIGN:
182+
key = new RSAPublicBCPGKey(in);
183+
break;
184+
case DSA:
185+
key = new DSAPublicBCPGKey(in);
186+
break;
187+
case ELGAMAL_ENCRYPT:
188+
case ELGAMAL_GENERAL:
189+
key = new ElGamalPublicBCPGKey(in);
190+
break;
191+
case ECDH:
192+
key = new ECDHPublicBCPGKey(in);
193+
break;
194+
case X25519:
195+
key = new X25519PublicBCPGKey(in);
196+
break;
197+
case X448:
198+
key = new X448PublicBCPGKey(in);
209199
break;
200+
case ECDSA:
201+
key = new ECDSAPublicBCPGKey(in);
202+
break;
203+
case EDDSA_LEGACY:
204+
key = new EdDSAPublicBCPGKey(in);
205+
break;
206+
case Ed25519:
207+
key = new Ed25519PublicBCPGKey(in);
208+
break;
209+
case Ed448:
210+
key = new Ed448PublicBCPGKey(in);
211+
break;
212+
default:
213+
if (version == VERSION_6 || version == LIBREPGP_5)
214+
{
215+
// with version 5 & 6, we can gracefully handle unknown key types, as the length is known.
216+
key = new UnknownBCPGKey((int)optLen, in);
217+
break;
218+
}
219+
throw new IOException("unknown PGP public key algorithm encountered: " + algorithm);
210220
}
211-
throw new IOException("unknown PGP public key algorithm encountered: " + algorithm);
221+
}
222+
catch (RuntimeException e)
223+
{
224+
throw new MalformedPacketException("Malformed PGP key.", e);
212225
}
213226
}
214227

pg/src/main/java/org/bouncycastle/bcpg/SecretKeyPacket.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ public class SecretKeyPacket
1414
extends ContainedPacket
1515
implements PublicKeyAlgorithmTags
1616
{
17+
public static final int MAX_S2K_ENCODING_LEN = 8192; // arbitrary
18+
1719
/**
1820
* S2K-usage octet indicating that the secret key material is unprotected.
1921
*/
@@ -178,7 +180,7 @@ public class SecretKeyPacket
178180
}
179181
if (version == PublicKeyPacket.VERSION_6 && (s2kUsage == USAGE_SHA1 || s2kUsage == USAGE_AEAD))
180182
{
181-
int s2KLen = in.read();
183+
int s2KLen = sanitizeLength(in.read(), MAX_S2K_ENCODING_LEN, "S2K length octet");
182184
byte[] s2kBytes = new byte[s2KLen];
183185
in.readFully(s2kBytes);
184186

@@ -194,7 +196,14 @@ public class SecretKeyPacket
194196
}
195197
if (s2kUsage == USAGE_AEAD)
196198
{
197-
iv = new byte[AEADUtils.getIVLength(aeadAlgorithm)];
199+
try
200+
{
201+
iv = new byte[AEADUtils.getIVLength(aeadAlgorithm)];
202+
}
203+
catch (IllegalArgumentException e)
204+
{
205+
throw new MalformedPacketException("Unknown AEAD algorithm", e);
206+
}
198207
in.readFully(iv);
199208
}
200209
else
@@ -227,7 +236,8 @@ public class SecretKeyPacket
227236
// encoded keyOctetCount does not contain checksum
228237
keyOctetCount += 2;
229238
}
230-
this.secKeyData = new byte[(int) keyOctetCount];
239+
int sanitizedOctetCount = sanitizeLength((int) keyOctetCount, PublicKeyPacket.MAX_LEN, "Key octet count");
240+
this.secKeyData = new byte[sanitizedOctetCount];
231241
in.readFully(secKeyData);
232242
}
233243
else

0 commit comments

Comments
 (0)