Skip to content

Commit 4e80c99

Browse files
author
gefeili
committed
Fix input/output overlapping in PaddedBufferedBlockCipher
1 parent 64026c2 commit 4e80c99

File tree

2 files changed

+102
-53
lines changed

2 files changed

+102
-53
lines changed

core/src/main/java/org/bouncycastle/crypto/paddings/PaddedBufferedBlockCipher.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -202,12 +202,24 @@ public int processBytes(
202202
if (len > gapLen)
203203
{
204204
System.arraycopy(in, inOff, buf, bufOff, gapLen);
205+
inOff += gapLen;
206+
len -= gapLen;
207+
if (in == out)
208+
{
209+
int inEnd = inOff + len;
210+
int outEnd = outOff + length;
211+
if ((inOff <= outOff && outOff <= inEnd) ||
212+
(outOff <= inOff && inOff <= outEnd))
213+
{
214+
in = new byte[len];
215+
System.arraycopy(out, inOff, in, 0, len);
216+
inOff = 0;
217+
}
218+
}
205219

206220
resultLen += cipher.processBlock(buf, 0, out, outOff);
207221

208222
bufOff = 0;
209-
len -= gapLen;
210-
inOff += gapLen;
211223

212224
while (len > buf.length)
213225
{

core/src/test/java/org/bouncycastle/crypto/test/PaddingTest.java

Lines changed: 88 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.bouncycastle.crypto.paddings.ZeroBytePadding;
1414
import org.bouncycastle.crypto.params.KeyParameter;
1515
import org.bouncycastle.crypto.InvalidCipherTextException;
16+
import org.bouncycastle.util.Arrays;
1617
import org.bouncycastle.util.encoders.Hex;
1718
import org.bouncycastle.util.test.SimpleTest;
1819

@@ -27,28 +28,28 @@ public PaddingTest()
2728
}
2829

2930
private void blockCheck(
30-
PaddedBufferedBlockCipher cipher,
31-
BlockCipherPadding padding,
32-
KeyParameter key,
33-
byte[] data)
31+
PaddedBufferedBlockCipher cipher,
32+
BlockCipherPadding padding,
33+
KeyParameter key,
34+
byte[] data)
3435
{
35-
byte[] out = new byte[data.length + 8];
36-
byte[] dec = new byte[data.length];
37-
36+
byte[] out = new byte[data.length + 8];
37+
byte[] dec = new byte[data.length];
38+
3839
try
39-
{
40+
{
4041
cipher.init(true, key);
41-
42-
int len = cipher.processBytes(data, 0, data.length, out, 0);
43-
42+
43+
int len = cipher.processBytes(data, 0, data.length, out, 0);
44+
4445
len += cipher.doFinal(out, len);
45-
46+
4647
cipher.init(false, key);
47-
48-
int decLen = cipher.processBytes(out, 0, len, dec, 0);
49-
48+
49+
int decLen = cipher.processBytes(out, 0, len, dec, 0);
50+
5051
decLen += cipher.doFinal(dec, decLen);
51-
52+
5253
if (!areEqual(data, dec))
5354
{
5455
fail("failed to decrypt - i = " + data.length + ", padding = " + padding.getPaddingName());
@@ -59,55 +60,55 @@ private void blockCheck(
5960
fail("Exception - " + e.toString(), e);
6061
}
6162
}
62-
63+
6364
public void testPadding(
64-
BlockCipherPadding padding,
65-
SecureRandom rand,
66-
byte[] ffVector,
67-
byte[] ZeroVector)
65+
BlockCipherPadding padding,
66+
SecureRandom rand,
67+
byte[] ffVector,
68+
byte[] ZeroVector)
6869
{
69-
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new DESEngine(), padding);
70-
KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
71-
70+
PaddedBufferedBlockCipher cipher = new PaddedBufferedBlockCipher(new DESEngine(), padding);
71+
KeyParameter key = new KeyParameter(Hex.decode("0011223344556677"));
72+
7273
//
7374
// ff test
7475
//
75-
byte[] data = { (byte)0xff, (byte)0xff, (byte)0xff, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0 };
76-
76+
byte[] data = {(byte)0xff, (byte)0xff, (byte)0xff, (byte)0, (byte)0, (byte)0, (byte)0, (byte)0};
77+
7778
if (ffVector != null)
7879
{
7980
padding.addPadding(data, 3);
80-
81+
8182
if (!areEqual(data, ffVector))
8283
{
8384
fail("failed ff test for " + padding.getPaddingName());
8485
}
8586
}
86-
87+
8788
//
8889
// zero test
8990
//
9091
if (ZeroVector != null)
9192
{
9293
data = new byte[8];
9394
padding.addPadding(data, 4);
94-
95+
9596
if (!areEqual(data, ZeroVector))
9697
{
9798
fail("failed zero test for " + padding.getPaddingName());
9899
}
99100
}
100-
101+
101102
for (int i = 1; i != 200; i++)
102103
{
103104
data = new byte[i];
104-
105+
105106
rand.nextBytes(data);
106107

107108
blockCheck(cipher, padding, key, data);
108109
}
109110
}
110-
111+
111112
private void testOutputSizes()
112113
{
113114
PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(new DESEngine(), new PKCS7Padding());
@@ -138,15 +139,51 @@ private void testOutputSizes()
138139
}
139140
}
140141

142+
private void testOverlapping()
143+
{
144+
//Skip the dofinal of the test
145+
PaddedBufferedBlockCipher bc = new PaddedBufferedBlockCipher(new DESEngine(), new PKCS7Padding());
146+
SecureRandom random = new SecureRandom();
147+
byte[] keyBytes = new byte[8];
148+
random.nextBytes(keyBytes);
149+
KeyParameter key = new KeyParameter(keyBytes);
150+
151+
int offset = 2 + random.nextInt(bc.getBlockSize() - 1);
152+
byte[] data = new byte[bc.getBlockSize() * 2 + offset];
153+
byte[] expected = new byte[bc.getOutputSize(bc.getBlockSize() * 2)];
154+
random.nextBytes(data);
155+
156+
bc.init(true, key);
157+
bc.processBytes(data, 0, bc.getBlockSize() * 2 + 1, expected, 0);
158+
bc.init(true, key);
159+
bc.processBytes(data, 0, bc.getBlockSize() * 2 + 1, data, offset);
160+
161+
if (!areEqual(expected, Arrays.copyOfRange(data, offset, offset + bc.getBlockSize() * 2)))
162+
{
163+
fail("failed to overlapping of encryption");
164+
}
165+
166+
bc.init(false, key);
167+
bc.processBytes(data, 0, bc.getBlockSize() * 2 + 1, expected, 0);
168+
bc.init(false, key);
169+
bc.processBytes(data, 0, bc.getBlockSize() * 2 + 1, data, offset);
170+
171+
if (!areEqual(expected, Arrays.copyOfRange(data, offset, offset + bc.getBlockSize() * 2)))
172+
{
173+
fail("failed to overlapping of encryption");
174+
}
175+
}
176+
141177
public void performTest()
142178
{
143-
SecureRandom rand = new SecureRandom(new byte[20]);
144-
179+
testOverlapping();
180+
SecureRandom rand = new SecureRandom(new byte[20]);
181+
145182
rand.setSeed(System.currentTimeMillis());
146-
183+
147184
testPadding(new PKCS7Padding(), rand,
148-
Hex.decode("ffffff0505050505"),
149-
Hex.decode("0000000004040404"));
185+
Hex.decode("ffffff0505050505"),
186+
Hex.decode("0000000004040404"));
150187

151188
PKCS7Padding padder = new PKCS7Padding();
152189
try
@@ -161,27 +198,27 @@ public void performTest()
161198
{
162199
fail("wrong exception for corrupt padding: " + e);
163200
}
164-
}
201+
}
165202

166203
testPadding(new ISO10126d2Padding(), rand,
167-
null,
168-
null);
169-
204+
null,
205+
null);
206+
170207
testPadding(new X923Padding(), rand,
171-
null,
172-
null);
208+
null,
209+
null);
173210

174211
testPadding(new TBCPadding(), rand,
175-
Hex.decode("ffffff0000000000"),
176-
Hex.decode("00000000ffffffff"));
212+
Hex.decode("ffffff0000000000"),
213+
Hex.decode("00000000ffffffff"));
177214

178215
testPadding(new ZeroBytePadding(), rand,
179-
Hex.decode("ffffff0000000000"),
180-
null);
181-
216+
Hex.decode("ffffff0000000000"),
217+
null);
218+
182219
testPadding(new ISO7816d4Padding(), rand,
183-
Hex.decode("ffffff8000000000"),
184-
Hex.decode("0000000080000000"));
220+
Hex.decode("ffffff8000000000"),
221+
Hex.decode("0000000080000000"));
185222

186223
testOutputSizes();
187224

@@ -193,7 +230,7 @@ public String getName()
193230
}
194231

195232
public static void main(
196-
String[] args)
233+
String[] args)
197234
{
198235
runTest(new PaddingTest());
199236
}

0 commit comments

Comments
 (0)