Skip to content

Instantly share code, notes, and snippets.

@apoleon
Created April 9, 2017 18:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save apoleon/f38f47fe05ee66efdfbd38ee60a57944 to your computer and use it in GitHub Desktop.
Save apoleon/f38f47fe05ee66efdfbd38ee60a57944 to your computer and use it in GitHub Desktop.
From: Markus Koschany <apo@debian.org>
Date: Sun, 9 Apr 2017 20:16:02 +0200
Subject: CVE-2015-6644
---
.../bouncycastle/crypto/modes/GCMBlockCipher.java | 38 ++++++++++++++--------
1 file changed, 24 insertions(+), 14 deletions(-)
diff --git a/src/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/src/org/bouncycastle/crypto/modes/GCMBlockCipher.java
index 8e7c315..73193bc 100644
--- a/src/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ b/src/org/bouncycastle/crypto/modes/GCMBlockCipher.java
@@ -41,6 +41,7 @@ public class GCMBlockCipher
private byte[] macBlock;
private byte[] S;
private byte[] counter;
+ private int blocksRemaining;
private int bufOff;
private long totalLength;
@@ -157,6 +158,7 @@ public class GCMBlockCipher
this.S = Arrays.clone(initS);
this.counter = Arrays.clone(J0);
+ this.blocksRemaining = -2;
this.bufOff = 0;
this.totalLength = 0;
}
@@ -307,6 +309,7 @@ public class GCMBlockCipher
{
S = Arrays.clone(initS);
counter = Arrays.clone(J0);
+ blocksRemaining = -2;
bufOff = 0;
totalLength = 0;
@@ -325,20 +328,7 @@ public class GCMBlockCipher
private void gCTRBlock(byte[] buf, int bufCount, byte[] out, int outOff)
{
-// inc(counter);
- for (int i = 15; i >= 12; --i)
- {
- byte b = (byte)((counter[i] + 1) & 0xff);
- counter[i] = b;
-
- if (b != 0)
- {
- break;
- }
- }
-
- byte[] tmp = new byte[BLOCK_SIZE];
- cipher.processBlock(counter, 0, tmp, 0);
+ byte[] tmp = getNextCounterBlock();
byte[] hashBytes;
if (forEncryption)
@@ -413,4 +403,24 @@ public class GCMBlockCipher
Pack.intToBigEndian((int)(count >>> 32), bs, off);
Pack.intToBigEndian((int)count, bs, off + 4);
}
+
+ private byte[] getNextCounterBlock()
+ {
+ if (blocksRemaining == 0)
+ {
+ throw new IllegalStateException("Attempt to process too many blocks");
+ }
+ blocksRemaining--;
+
+ int c = 1;
+ c += counter[15] & 0xFF; counter[15] = (byte)c; c >>>= 8;
+ c += counter[14] & 0xFF; counter[14] = (byte)c; c >>>= 8;
+ c += counter[13] & 0xFF; counter[13] = (byte)c; c >>>= 8;
+ c += counter[12] & 0xFF; counter[12] = (byte)c;
+
+ byte[] tmp = new byte[BLOCK_SIZE];
+ // TODO Sure would be nice if ciphers could operate on int[]
+ cipher.processBlock(counter, 0, tmp, 0);
+ return tmp;
+ }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment