diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/crypto/agreement/ECDHBasicAgreement.java | 22 | ||||
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java | 33 |
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"); |