Skip to content

Commit 07bb6a3

Browse files
author
gefeili
committed
Fix NISTCTSBlockCipher and OldCTSBlockCipher
1 parent 4a369f0 commit 07bb6a3

File tree

4 files changed

+131
-35
lines changed

4 files changed

+131
-35
lines changed

core/src/main/java/org/bouncycastle/crypto/modes/NISTCTSBlockCipher.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -155,15 +155,19 @@ public int processBytes(
155155
if (len > gapLen)
156156
{
157157
System.arraycopy(in, inOff, buf, bufOff, gapLen);
158-
158+
inOff += gapLen;
159+
len -= gapLen;
160+
if (in == out && segmentsOverlap(inOff, len, outOff, length))
161+
{
162+
in = new byte[len];
163+
System.arraycopy(out, inOff, in, 0, len);
164+
inOff = 0;
165+
}
159166
resultLen += cipher.processBlock(buf, 0, out, outOff);
160167
System.arraycopy(buf, blockSize, buf, 0, blockSize);
161168

162169
bufOff = blockSize;
163170

164-
len -= gapLen;
165-
inOff += gapLen;
166-
167171
while (len > blockSize)
168172
{
169173
System.arraycopy(in, inOff, buf, bufOff, blockSize);

core/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,15 +149,19 @@ public int processBytes(
149149
if (len > gapLen)
150150
{
151151
System.arraycopy(in, inOff, buf, bufOff, gapLen);
152-
152+
inOff += gapLen;
153+
len -= gapLen;
154+
if (in == out && segmentsOverlap(inOff, len, outOff, length))
155+
{
156+
in = new byte[len];
157+
System.arraycopy(out, inOff, in, 0, len);
158+
inOff = 0;
159+
}
153160
resultLen += cipher.processBlock(buf, 0, out, outOff);
154161
System.arraycopy(buf, blockSize, buf, 0, blockSize);
155162

156163
bufOff = blockSize;
157164

158-
len -= gapLen;
159-
inOff += gapLen;
160-
161165
while (len > blockSize)
162166
{
163167
System.arraycopy(in, inOff, buf, bufOff, blockSize);

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

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -204,6 +204,44 @@ private void testOverlapping()
204204
}
205205
}
206206

207+
private void testOverlapping2()
208+
throws Exception
209+
{
210+
//Skip the dofinal of the test
211+
OldCTSBlockCipher bc = new OldCTSBlockCipher(AESEngine.newInstance());
212+
SecureRandom random = new SecureRandom();
213+
byte[] keyBytes = new byte[16];
214+
random.nextBytes(keyBytes);
215+
KeyParameter key = new KeyParameter(keyBytes);
216+
217+
int offset = 1 + random.nextInt(bc.getBlockSize() - 1) + bc.getBlockSize();
218+
byte[] data = new byte[bc.getBlockSize() * 4 + offset];
219+
byte[] expected = new byte[bc.getOutputSize(bc.getBlockSize() * 3)];
220+
random.nextBytes(data);
221+
222+
bc.init(true, key);
223+
int len = bc.processBytes(data, 0, expected.length, expected, 0);
224+
bc.doFinal(expected, len);
225+
bc.init(true, key);
226+
len = bc.processBytes(data, 0, expected.length, data, offset);
227+
bc.doFinal(data, offset + len);
228+
229+
if (!areEqual(expected, Arrays.copyOfRange(data, offset, offset + expected.length)))
230+
{
231+
fail("failed to overlapping of encryption");
232+
}
233+
234+
bc.init(false, key);
235+
bc.processBytes(data, 0, expected.length, expected, 0);
236+
bc.init(false, key);
237+
bc.processBytes(data, 0, expected.length, data, offset);
238+
239+
if (!areEqual(expected, Arrays.copyOfRange(data, offset, offset + expected.length)))
240+
{
241+
fail("failed to overlapping of encryption");
242+
}
243+
}
244+
207245
public String getName()
208246
{
209247
return "CTS";
@@ -256,6 +294,7 @@ public void performTest()
256294

257295
testExceptions();
258296
testOverlapping();
297+
testOverlapping2();
259298
}
260299

261300
public static void main(

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

Lines changed: 76 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,19 @@
11
package org.bouncycastle.crypto.test;
22

3+
import java.security.SecureRandom;
4+
35
import org.bouncycastle.crypto.BlockCipher;
46
import org.bouncycastle.crypto.BufferedBlockCipher;
57
import org.bouncycastle.crypto.CipherParameters;
68
import org.bouncycastle.crypto.DataLengthException;
79
import org.bouncycastle.crypto.InvalidCipherTextException;
810
import org.bouncycastle.crypto.engines.AESEngine;
11+
import org.bouncycastle.crypto.engines.DSTU7624Engine;
12+
import org.bouncycastle.crypto.modes.KXTSBlockCipher;
913
import org.bouncycastle.crypto.modes.NISTCTSBlockCipher;
1014
import org.bouncycastle.crypto.params.KeyParameter;
1115
import org.bouncycastle.crypto.params.ParametersWithIV;
16+
import org.bouncycastle.util.Arrays;
1217
import org.bouncycastle.util.encoders.Hex;
1318
import org.bouncycastle.util.test.SimpleTest;
1419

@@ -36,23 +41,23 @@ public class NISTCTSTest
3641
private static byte[] cs2NotQuiteTwoBlockOut = Hex.decode("f098097ca69b72e3a46e9ca21bb5ebbc22ecf2ac77");
3742
private static byte[] cs3NotQuiteTwoBlockOut = Hex.decode("f098097ca69b72e3a46e9ca21bb5ebbc22ecf2ac77");
3843

39-
static byte[] in1 = Hex.decode("4e6f7720697320746865207420");
40-
static byte[] in2 = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f0aaa");
41-
static byte[] out1 = Hex.decode("9952f131588465033fa40e8a98");
42-
static byte[] out2 = Hex.decode("358f84d01eb42988dc34efb994");
43-
static byte[] out3 = Hex.decode("170171cfad3f04530c509b0c1f0be0aefbd45a8e3755a873bff5ea198504b71683c6");
44-
44+
static byte[] in1 = Hex.decode("4e6f7720697320746865207420");
45+
static byte[] in2 = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f0aaa");
46+
static byte[] out1 = Hex.decode("9952f131588465033fa40e8a98");
47+
static byte[] out2 = Hex.decode("358f84d01eb42988dc34efb994");
48+
static byte[] out3 = Hex.decode("170171cfad3f04530c509b0c1f0be0aefbd45a8e3755a873bff5ea198504b71683c6");
49+
4550
private void testCTS(
46-
int id,
47-
int type,
48-
BlockCipher cipher,
49-
CipherParameters params,
50-
byte[] input,
51-
byte[] output)
51+
int id,
52+
int type,
53+
BlockCipher cipher,
54+
CipherParameters params,
55+
byte[] input,
56+
byte[] output)
5257
throws Exception
5358
{
54-
byte[] out = new byte[input.length];
55-
BufferedBlockCipher engine = new NISTCTSBlockCipher(type, cipher);
59+
byte[] out = new byte[input.length];
60+
BufferedBlockCipher engine = new NISTCTSBlockCipher(type, cipher);
5661

5762
engine.init(true, params);
5863

@@ -77,63 +82,106 @@ private void testCTS(
7782
}
7883
}
7984

80-
private void testExceptions() throws InvalidCipherTextException
85+
private void testExceptions()
86+
throws InvalidCipherTextException
8187
{
8288
BufferedBlockCipher engine = new NISTCTSBlockCipher(NISTCTSBlockCipher.CS1, AESEngine.newInstance());
8389
CipherParameters params = new KeyParameter(new byte[engine.getBlockSize()]);
8490
engine.init(true, params);
8591

8692
byte[] out = new byte[engine.getOutputSize(engine.getBlockSize())];
87-
93+
8894
engine.processBytes(new byte[engine.getBlockSize() - 1], 0, engine.getBlockSize() - 1, out, 0);
89-
try
95+
try
9096
{
9197
engine.doFinal(out, 0);
9298
fail("Expected CTS encrypt error on < 1 block input");
93-
} catch(DataLengthException e)
99+
}
100+
catch (DataLengthException e)
94101
{
95102
// Expected
96103
}
97104

98105
engine.init(true, params);
99106
engine.processBytes(new byte[engine.getBlockSize()], 0, engine.getBlockSize(), out, 0);
100-
try
107+
try
101108
{
102109
engine.doFinal(out, 0);
103-
} catch(DataLengthException e)
110+
}
111+
catch (DataLengthException e)
104112
{
105113
fail("Unexpected CTS encrypt error on == 1 block input");
106114
}
107115

108116
engine.init(false, params);
109117
engine.processBytes(new byte[engine.getBlockSize() - 1], 0, engine.getBlockSize() - 1, out, 0);
110-
try
118+
try
111119
{
112120
engine.doFinal(out, 0);
113121
fail("Expected CTS decrypt error on < 1 block input");
114-
} catch(DataLengthException e)
122+
}
123+
catch (DataLengthException e)
115124
{
116125
// Expected
117126
}
118127

119128
engine.init(false, params);
120129
engine.processBytes(new byte[engine.getBlockSize()], 0, engine.getBlockSize(), out, 0);
121-
try
130+
try
122131
{
123132
engine.doFinal(out, 0);
124-
} catch(DataLengthException e)
133+
}
134+
catch (DataLengthException e)
125135
{
126136
fail("Unexpected CTS decrypt error on == 1 block input");
127137
}
128138

129139
}
130140

141+
private void testOverlapping()
142+
throws Exception
143+
{
144+
SecureRandom random = new SecureRandom();
145+
byte[] keyBytes = new byte[16];
146+
byte[] iv = new byte[16];
147+
random.nextBytes(keyBytes);
148+
BufferedBlockCipher bc = new NISTCTSBlockCipher(NISTCTSBlockCipher.CS1, AESEngine.newInstance());
149+
ParametersWithIV param = new ParametersWithIV(new KeyParameter(keyBytes), iv);
150+
151+
int offset = 1 + random.nextInt(bc.getBlockSize() - 1) + bc.getBlockSize();
152+
byte[] data = new byte[bc.getBlockSize() * 4 + offset];
153+
byte[] expected = new byte[bc.getOutputSize(bc.getBlockSize() * 3)];
154+
random.nextBytes(data);
155+
156+
bc.init(true, param);
157+
int len = bc.processBytes(data, 0, expected.length, expected, 0);
158+
bc.doFinal(expected, len);
159+
bc.init(true, param);
160+
len = bc.processBytes(data, 0, expected.length, data, offset);
161+
bc.doFinal(data, offset + len);
162+
163+
if (!areEqual(expected, Arrays.copyOfRange(data, offset, offset + expected.length)))
164+
{
165+
fail("failed to overlapping of encryption");
166+
}
167+
168+
bc.init(false, param);
169+
bc.processBytes(data, 0, expected.length, expected, 0);
170+
bc.init(false, param);
171+
bc.processBytes(data, 0, expected.length, data, offset);
172+
173+
if (!areEqual(expected, Arrays.copyOfRange(data, offset, offset + expected.length)))
174+
{
175+
fail("failed to overlapping of encryption");
176+
}
177+
}
178+
131179
public String getName()
132180
{
133181
return "NISTCTS";
134182
}
135183

136-
public void performTest()
184+
public void performTest()
137185
throws Exception
138186
{
139187
testCTS(1, NISTCTSBlockCipher.CS1, AESEngine.newInstance(), new ParametersWithIV(key, iv), singleBlock, singleOut);
@@ -149,7 +197,7 @@ public void performTest()
149197
testCTS(9, NISTCTSBlockCipher.CS3, AESEngine.newInstance(), new ParametersWithIV(key, iv), notQuiteTwo, cs3NotQuiteTwoBlockOut);
150198

151199
byte[] aes128b = Hex.decode("aafd12f659cae63489b479e5076ddec2f06cb58faafd12f6");
152-
byte[] aesIn1b = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
200+
byte[] aesIn1b = Hex.decode("000102030405060708090a0b0c0d0e0fff0102030405060708090a0b0c0d0e0f");
153201
byte[] aesOut1b = Hex.decode("6db2f802d99e1ef0a5940f306079e083cf87f4d8bb9d1abb36cdd9f44ead7d04");
154202

155203
testCTS(10, NISTCTSBlockCipher.CS3, AESEngine.newInstance(), new ParametersWithIV(new KeyParameter(aes128b), Hex.decode("aafd12f659cae63489b479e5076ddec2")), aesIn1b, aesOut1b);
@@ -160,10 +208,11 @@ public void performTest()
160208
testCTS(11, NISTCTSBlockCipher.CS3, AESEngine.newInstance(), new ParametersWithIV(new KeyParameter(aes128c), Hex.decode("aafd12f659cae63489b479e5076ddec2")), aesIn1b, aesOut1c);
161209

162210
testExceptions();
211+
testOverlapping();
163212
}
164213

165214
public static void main(
166-
String[] args)
215+
String[] args)
167216
{
168217
runTest(new NISTCTSTest());
169218
}

0 commit comments

Comments
 (0)