Skip to content

Commit 7bb88a6

Browse files
author
gefeili
committed
Update AEAD modes
1 parent 8e1bb62 commit 7bb88a6

File tree

4 files changed

+92
-2
lines changed

4 files changed

+92
-2
lines changed

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

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,12 @@ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
224224
{
225225
throw new DataLengthException("Input buffer too short");
226226
}
227+
if (in == out && segmentsOverlap(inOff, len, outOff, getUpdateOutputSize(len)))
228+
{
229+
in = new byte[len];
230+
System.arraycopy(out, inOff, in, 0, len);
231+
inOff = 0;
232+
}
227233

228234
int resultLen = 0;
229235

@@ -384,4 +390,10 @@ private boolean verifyMac(byte[] mac, int off)
384390

385391
return nonEqual == 0;
386392
}
393+
394+
protected boolean segmentsOverlap(int inOff, int inLen, int outOff, int outLen)
395+
{
396+
// please ensure a valid check for inLen > 0 and outLen > 0 outside this function
397+
return inOff <= outOff + outLen && outOff <= inOff + inLen;
398+
}
387399
}

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -383,7 +383,12 @@ public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
383383
{
384384
throw new DataLengthException("Input buffer too short");
385385
}
386-
386+
if (in == out && segmentsOverlap(inOff, len, outOff, getUpdateOutputSize(len)))
387+
{
388+
in = new byte[len];
389+
System.arraycopy(out, inOff, in, 0, len);
390+
inOff = 0;
391+
}
387392
int resultLen = 0;
388393

389394
if (forEncryption)
@@ -749,4 +754,10 @@ private void checkStatus()
749754
throw new IllegalStateException("GCM cipher needs to be initialised");
750755
}
751756
}
757+
758+
protected boolean segmentsOverlap(int inOff, int inLen, int outOff, int outLen)
759+
{
760+
// please ensure a valid check for inLen > 0 and outLen > 0 outside this function
761+
return inOff <= outOff + outLen && outOff <= inOff + inLen;
762+
}
752763
}

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

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -333,7 +333,12 @@ public int processBytes(byte[] input, int inOff, int len, byte[] output, int out
333333
throw new DataLengthException("Input buffer too short");
334334
}
335335
int resultLen = 0;
336-
336+
if (input == output && segmentsOverlap(inOff, len, outOff, getUpdateOutputSize(len)))
337+
{
338+
input = new byte[len];
339+
System.arraycopy(output, inOff, input, 0, len);
340+
inOff = 0;
341+
}
337342
for (int i = 0; i < len; ++i)
338343
{
339344
mainBlock[mainBlockPos] = input[inOff + i];
@@ -592,4 +597,10 @@ protected static void xor(byte[] block, byte[] val)
592597
{
593598
Bytes.xorTo(16, val, block);
594599
}
600+
601+
protected boolean segmentsOverlap(int inOff, int inLen, int outOff, int outLen)
602+
{
603+
// please ensure a valid check for inLen > 0 and outLen > 0 outside this function
604+
return inOff <= outOff + outLen && outOff <= inOff + inLen;
605+
}
595606
}

prov/src/test/java/org/bouncycastle/jce/provider/test/BlockCipherTest.java

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import org.bouncycastle.util.encoders.Hex;
5151
import org.bouncycastle.util.test.SimpleTest;
5252
import org.bouncycastle.util.test.TestFailedException;
53+
import org.junit.Assert;
5354

5455
/**
5556
* basic test class for a block cipher, basically this just exercises the provider, and makes sure we
@@ -850,6 +851,61 @@ else if (algorithm.startsWith("RC5"))
850851
fail("" + algorithm + " failed encryption - expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(bytes)));
851852
}
852853

854+
//
855+
// Try the doFinal - same input/output same index, index
856+
//
857+
byte[] data = Arrays.concatenate(input, new byte[2 * in.getBlockSize()]);
858+
int len = 0;
859+
try
860+
{
861+
if (algorithm.indexOf("GCM") > 0)
862+
{
863+
out = Cipher.getInstance(algorithm, "BC");
864+
out.init(Cipher.ENCRYPT_MODE, key, rand);
865+
}
866+
867+
len = out.doFinal(data, 0, input.length, data, 0);
868+
}
869+
catch (Exception e)
870+
{
871+
Assert.fail(e.toString());
872+
}
873+
874+
if (!Arrays.areEqual(data, 0, len, output, 0, output.length))
875+
{
876+
Assert.fail("" + algorithm + " failed doFinal - expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(data)));
877+
}
878+
879+
//
880+
// Try the doFinal - same input/output shifted offset
881+
//
882+
data = Arrays.concatenate(input, new byte[2 * in.getBlockSize()]);
883+
len = 0;
884+
try
885+
{
886+
887+
if (algorithm.indexOf("GCM") > 0)
888+
{
889+
out = Cipher.getInstance(algorithm, "BC");
890+
out.init(Cipher.ENCRYPT_MODE, key, rand);
891+
}
892+
893+
len = out.doFinal(data, 0, input.length, data, 1);
894+
895+
// System.out.println(Hex.toHexString(output));
896+
// System.out.println(Hex.toHexString(Arrays.copyOfRange(data, 1, 1 + len)));
897+
// System.out.println(len + " " + output.length);
898+
}
899+
catch (Exception e)
900+
{
901+
Assert.fail(e.toString());
902+
}
903+
904+
if (!Arrays.areEqual(data, 1, 1 + len, output, 0, output.length))
905+
{
906+
Assert.fail("" + algorithm + " failed doFinal - expected " + new String(Hex.encode(output)) + " got " + new String(Hex.encode(data)));
907+
}
908+
853909
//
854910
// decryption pass
855911
//

0 commit comments

Comments
 (0)