summaryrefslogtreecommitdiff
path: root/bcprov/src/main/java/org/bouncycastle/crypto
diff options
context:
space:
mode:
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java22
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java33
2 files changed, 53 insertions, 2 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
index a491b9df..5aa2f2bb 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java
@@ -6,6 +6,9 @@ import org.bouncycastle.crypto.BasicAgreement;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters;
+// BEGIN android-added
+import org.bouncycastle.math.ec.ECCurve;
+// END android-added
import org.bouncycastle.math.ec.ECPoint;
/**
@@ -41,8 +44,23 @@ public class ECDHBasicAgreement
public BigInteger calculateAgreement(
CipherParameters pubKey)
{
- ECPublicKeyParameters pub = (ECPublicKeyParameters)pubKey;
- ECPoint P = pub.getQ().multiply(key.getD()).normalize();
+ // BEGIN android-changed
+ ECPoint peerPoint = ((ECPublicKeyParameters) pubKey).getQ();
+ ECCurve myCurve = key.getParameters().getCurve();
+ if (peerPoint.isInfinity()) {
+ throw new IllegalStateException("Infinity is not a valid public key for ECDH");
+ }
+ try {
+ myCurve.validatePoint(peerPoint.getXCoord().toBigInteger(),
+ peerPoint.getYCoord().toBigInteger());
+ } catch (IllegalArgumentException ex) {
+ throw new IllegalStateException("The peer public key must be on the curve for ECDH");
+ }
+ // Explicitly construct a public key using the private key's curve.
+ ECPoint pubPoint = myCurve.createPoint(peerPoint.getXCoord().toBigInteger(),
+ peerPoint.getYCoord().toBigInteger());
+ ECPoint P = pubPoint.multiply(key.getD()).normalize();
+ // END android-changed
if (P.isInfinity())
{
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
index b30b4aac..ed89ef7d 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java
@@ -24,6 +24,11 @@ public class GCMBlockCipher
implements AEADBlockCipher
{
private static final int BLOCK_SIZE = 16;
+ // BEGIN android-added
+ // 2^36-32 : limitation imposed by NIST GCM as otherwise the counter is wrapped and it can leak
+ // plaintext and authentication key
+ private static final long MAX_INPUT_SIZE = 68719476704L;
+ // END android-added
// not final due to a compiler bug
private BlockCipher cipher;
@@ -202,6 +207,14 @@ public class GCMBlockCipher
return totalData < macSize ? 0 : totalData - macSize;
}
+ // BEGIN android-added
+ /** Helper used to ensure that {@link #MAX_INPUT_SIZE} is not exceeded. */
+ private long getTotalInputSizeAfterNewInput(int newInputLen)
+ {
+ return totalLength + newInputLen + bufOff;
+ }
+ // END android-added
+
public int getUpdateOutputSize(int len)
{
int totalData = len + bufOff;
@@ -218,6 +231,11 @@ public class GCMBlockCipher
public void processAADByte(byte in)
{
+ // BEGIN android-added
+ if (getTotalInputSizeAfterNewInput(1) > MAX_INPUT_SIZE) {
+ throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes");
+ }
+ // END android-added
atBlock[atBlockPos] = in;
if (++atBlockPos == BLOCK_SIZE)
{
@@ -230,6 +248,11 @@ public class GCMBlockCipher
public void processAADBytes(byte[] in, int inOff, int len)
{
+ // BEGIN android-added
+ if (getTotalInputSizeAfterNewInput(len) > MAX_INPUT_SIZE) {
+ throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes");
+ }
+ // END android-added
for (int i = 0; i < len; ++i)
{
atBlock[atBlockPos] = in[inOff + i];
@@ -267,6 +290,11 @@ public class GCMBlockCipher
public int processByte(byte in, byte[] out, int outOff)
throws DataLengthException
{
+ // BEGIN android-added
+ if (getTotalInputSizeAfterNewInput(1) > MAX_INPUT_SIZE) {
+ throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes");
+ }
+ // END android-added
bufBlock[bufOff] = in;
if (++bufOff == bufBlock.length)
{
@@ -279,6 +307,11 @@ public class GCMBlockCipher
public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff)
throws DataLengthException
{
+ // BEGIN android-added
+ if (getTotalInputSizeAfterNewInput(len) > MAX_INPUT_SIZE) {
+ throw new DataLengthException("Input exceeded " + MAX_INPUT_SIZE + " bytes");
+ }
+ // END android-added
if (in.length < (inOff + len))
{
throw new DataLengthException("Input buffer too short");