diff options
author | Tim Whittington <bc@whittington.net.nz> | 2014-03-06 00:04:26 +0400 |
---|---|---|
committer | Tim Whittington <bc@whittington.net.nz> | 2014-03-10 12:27:39 +0400 |
commit | 8eca220a9b2c68938b19ee6b88e0534d0a07c618 (patch) | |
tree | c86fc67b63b1e86101997475ef0f949d3d0890b1 /core/src/main/java/org/bouncycastle | |
parent | 089aec1b5ddcbd904ac057652c43c6f5b89d952d (diff) |
Implement and test consistent use of DataLengthException and OutputLengthException in AEAD ciphers.
Diffstat (limited to 'core/src/main/java/org/bouncycastle')
4 files changed, 76 insertions, 22 deletions
diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java index fef51fdb..7f870ca2 100644 --- a/core/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java +++ b/core/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java @@ -7,6 +7,7 @@ import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.Mac; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.macs.CBCBlockCipherMac; import org.bouncycastle.crypto.params.AEADParameters; import org.bouncycastle.crypto.params.ParametersWithIV; @@ -42,7 +43,7 @@ public class CCMBlockCipher this.cipher = c; this.blockSize = c.getBlockSize(); this.macBlock = new byte[blockSize]; - + if (blockSize != 16) { throw new IllegalArgumentException("cipher required with a block size of 16."); @@ -99,7 +100,7 @@ public class CCMBlockCipher { throw new IllegalArgumentException("nonce must have length from 7 to 13 octets"); } - + reset(); } @@ -130,6 +131,10 @@ public class CCMBlockCipher public int processBytes(byte[] in, int inOff, int inLen, byte[] out, int outOff) throws DataLengthException, IllegalStateException { + if (in.length < (inOff + inLen)) + { + throw new DataLengthException("Input buffer too short"); + } data.write(in, inOff, inLen); return 0; @@ -155,15 +160,15 @@ public class CCMBlockCipher /** * Returns a byte array containing the mac calculated as part of the * last encrypt or decrypt operation. - * + * * @return the last mac calculated. */ public byte[] getMac() { byte[] mac = new byte[macSize]; - + System.arraycopy(macBlock, 0, mac, 0, mac.length); - + return mac; } @@ -267,7 +272,7 @@ public class CCMBlockCipher outputLen = inLen + macSize; if (output.length < (outputLen + outOff)) { - throw new DataLengthException("Output buffer too short."); + throw new OutputLengthException("Output buffer too short."); } calculateMac(in, inOff, inLen, macBlock); @@ -300,7 +305,7 @@ public class CCMBlockCipher outputLen = inLen - macSize; if (output.length < (outputLen + outOff)) { - throw new DataLengthException("Output buffer too short."); + throw new OutputLengthException("Output buffer too short."); } System.arraycopy(in, inOff + outputLen, macBlock, 0, macSize); @@ -350,18 +355,18 @@ public class CCMBlockCipher // build b0 // byte[] b0 = new byte[16]; - + if (hasAssociatedText()) { b0[0] |= 0x40; } - + b0[0] |= (((cMac.getMacSize() - 2) / 2) & 0x7) << 3; b0[0] |= ((15 - nonce.length) - 1) & 0x7; - + System.arraycopy(nonce, 0, b0, 1, nonce.length); - + int q = dataLen; int count = 1; while (q > 0) @@ -370,22 +375,22 @@ public class CCMBlockCipher q >>>= 8; count++; } - + cMac.update(b0, 0, b0.length); - + // // process associated text // if (hasAssociatedText()) { int extra; - + int textLength = getAssociatedTextLength(); if (textLength < ((1 << 16) - (1 << 8))) { cMac.update((byte)(textLength >> 8)); cMac.update((byte)textLength); - + extra = 2; } else // can't go any higher than 2^32 @@ -396,7 +401,7 @@ public class CCMBlockCipher cMac.update((byte)(textLength >> 16)); cMac.update((byte)(textLength >> 8)); cMac.update((byte)textLength); - + extra = 6; } @@ -418,7 +423,7 @@ public class CCMBlockCipher } } } - + // // add the text // diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java index fbfe3727..209d5cdb 100644 --- a/core/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java +++ b/core/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java @@ -5,6 +5,7 @@ import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.InvalidCipherTextException; import org.bouncycastle.crypto.Mac; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.macs.CMac; import org.bouncycastle.crypto.params.AEADParameters; import org.bouncycastle.crypto.params.ParametersWithIV; @@ -219,6 +220,11 @@ public class EAXBlockCipher { initCipher(); + if (in.length < (inOff + len)) + { + throw new DataLengthException("Input buffer too short"); + } + int resultLen = 0; for (int i = 0; i != len; i++) @@ -241,9 +247,9 @@ public class EAXBlockCipher if (forEncryption) { - if (out.length < (outOff + extra)) + if (out.length < (outOff + extra + macSize)) { - throw new DataLengthException("Output buffer too short"); + throw new OutputLengthException("Output buffer too short"); } cipher.processBlock(bufBlock, 0, tmp, 0); @@ -261,6 +267,10 @@ public class EAXBlockCipher } else { + if (out.length < (outOff + extra - macSize)) + { + throw new OutputLengthException("Output buffer too short"); + } if (extra < macSize) { throw new InvalidCipherTextException("data too short"); @@ -328,6 +338,10 @@ public class EAXBlockCipher if (bufOff == bufBlock.length) { + if (out.length < (outOff + blockSize)) + { + throw new OutputLengthException("Output buffer is too short"); + } // TODO Could move the processByte(s) calls to here // initCipher(); diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java index 9e617ec9..59c2eb36 100644 --- a/core/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java +++ b/core/src/main/java/org/bouncycastle/crypto/modes/GCMBlockCipher.java @@ -4,6 +4,7 @@ import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.modes.gcm.GCMExponentiator; import org.bouncycastle.crypto.modes.gcm.GCMMultiplier; import org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator; @@ -23,7 +24,7 @@ public class GCMBlockCipher { private static final int BLOCK_SIZE = 16; - // not final due to a compiler bug + // not final due to a compiler bug private BlockCipher cipher; private GCMMultiplier multiplier; private GCMExponentiator exp; @@ -102,7 +103,7 @@ public class GCMBlockCipher throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits); } - macSize = macSizeBits / 8; + macSize = macSizeBits / 8; keyParam = param.getKey(); } else if (params instanceof ParametersWithIV) @@ -119,7 +120,7 @@ public class GCMBlockCipher throw new IllegalArgumentException("invalid parameters passed to GCM"); } - int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize); + int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize); this.bufBlock = new byte[bufLength]; if (nonce == null || nonce.length < 1) @@ -271,6 +272,10 @@ public class GCMBlockCipher public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) throws DataLengthException { + if (in.length < (inOff + len)) + { + throw new DataLengthException("Input buffer too short"); + } int resultLen = 0; for (int i = 0; i < len; ++i) @@ -288,6 +293,10 @@ public class GCMBlockCipher private void outputBlock(byte[] output, int offset) { + if (output.length < (offset + BLOCK_SIZE)) + { + throw new OutputLengthException("Output buffer too short"); + } if (totalLength == 0) { initCipher(); @@ -324,6 +333,10 @@ public class GCMBlockCipher if (extra > 0) { + if (out.length < (outOff + extra)) + { + throw new OutputLengthException("Output buffer too short"); + } gCTRPartial(bufBlock, 0, extra, out, outOff); } @@ -390,6 +403,10 @@ public class GCMBlockCipher if (forEncryption) { + if (out.length < (outOff + extra + macSize)) + { + throw new OutputLengthException("Output buffer too short"); + } // Append T to the message System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize); resultLen += macSize; diff --git a/core/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java b/core/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java index d0345c4b..66db8beb 100644 --- a/core/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java +++ b/core/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java @@ -6,6 +6,7 @@ import org.bouncycastle.crypto.BlockCipher; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.crypto.DataLengthException; import org.bouncycastle.crypto.InvalidCipherTextException; +import org.bouncycastle.crypto.OutputLengthException; import org.bouncycastle.crypto.params.AEADParameters; import org.bouncycastle.crypto.params.KeyParameter; import org.bouncycastle.crypto.params.ParametersWithIV; @@ -317,6 +318,10 @@ public class OCBBlockCipher public int processBytes(byte[] input, int inOff, int len, byte[] output, int outOff) throws DataLengthException { + if (input.length < (inOff + len)) + { + throw new DataLengthException("Input buffer too short"); + } int resultLen = 0; for (int i = 0; i < len; ++i) @@ -378,6 +383,10 @@ public class OCBBlockCipher xor(mainBlock, Pad); + if (output.length < (outOff + mainBlockPos)) + { + throw new OutputLengthException("Output buffer too short"); + } System.arraycopy(mainBlock, 0, output, outOff, mainBlockPos); if (!forEncryption) @@ -405,6 +414,10 @@ public class OCBBlockCipher if (forEncryption) { + if (output.length < (outOff + resultLen + macSize)) + { + throw new OutputLengthException("Output buffer too short"); + } // Append tag to the message System.arraycopy(macBlock, 0, output, outOff + resultLen, macSize); resultLen += macSize; @@ -456,6 +469,11 @@ public class OCBBlockCipher protected void processMainBlock(byte[] output, int outOff) { + if (output.length < (outOff + BLOCK_SIZE)) + { + throw new OutputLengthException("Output buffer too short"); + } + /* * OCB-ENCRYPT/OCB-DECRYPT: Process any whole blocks */ |