summaryrefslogtreecommitdiffstats
path: root/bcprov/src/main/java/org/bouncycastle/crypto/modes
diff options
context:
space:
mode:
authorSergio Giro <sgiro@google.com>2016-01-27 20:40:41 +0000
committerSergio Giro <sgiro@google.com>2016-01-28 15:30:59 +0000
commit80261dd2d1824bb3862e90e77a5412d56ad88b1f (patch)
treed89e670054247d0a050ac1b0d9a7918cbe3498d6 /bcprov/src/main/java/org/bouncycastle/crypto/modes
parent9be78fe4c709f1e585b5ed7e99b21084045b7fba (diff)
downloadandroid_external_bouncycastle-80261dd2d1824bb3862e90e77a5412d56ad88b1f.tar.gz
android_external_bouncycastle-80261dd2d1824bb3862e90e77a5412d56ad88b1f.tar.bz2
android_external_bouncycastle-80261dd2d1824bb3862e90e77a5412d56ad88b1f.zip
bouncycastle: Android tree with upstream code for version 1.50
Android tree as of c0d8909a6c6a4ac075a9dee7ac1fe6baff34acc0 Change-Id: I8d381554d6edec32aae8ff5bab5d5314f0954440
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto/modes')
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java142
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java11
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java88
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java20
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java109
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java3
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java30
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java269
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java15
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java10
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java487
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java13
-rw-r--r--bcprov/src/main/java/org/bouncycastle/crypto/modes/package.html5
13 files changed, 937 insertions, 265 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
index 9a6e2e0..fef51fd 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CCMBlockCipher.java
@@ -29,8 +29,8 @@ public class CCMBlockCipher
private int macSize;
private CipherParameters keyParam;
private byte[] macBlock;
- private ByteArrayOutputStream associatedText = new ByteArrayOutputStream();
- private ByteArrayOutputStream data = new ByteArrayOutputStream();
+ private ExposedByteArrayOutputStream associatedText = new ExposedByteArrayOutputStream();
+ private ExposedByteArrayOutputStream data = new ExposedByteArrayOutputStream();
/**
* Basic constructor.
@@ -65,6 +65,7 @@ public class CCMBlockCipher
{
this.forEncryption = forEncryption;
+ CipherParameters cipherParameters;
if (params instanceof AEADParameters)
{
AEADParameters param = (AEADParameters)params;
@@ -72,7 +73,7 @@ public class CCMBlockCipher
nonce = param.getNonce();
initialAssociatedText = param.getAssociatedText();
macSize = param.getMacSize() / 8;
- keyParam = param.getKey();
+ cipherParameters = param.getKey();
}
else if (params instanceof ParametersWithIV)
{
@@ -81,17 +82,25 @@ public class CCMBlockCipher
nonce = param.getIV();
initialAssociatedText = null;
macSize = macBlock.length / 2;
- keyParam = param.getParameters();
+ cipherParameters = param.getParameters();
}
else
{
throw new IllegalArgumentException("invalid parameters passed to CCM");
}
+ // NOTE: Very basic support for key re-use, but no performance gain from it
+ if (cipherParameters != null)
+ {
+ keyParam = cipherParameters;
+ }
+
if (nonce == null || nonce.length < 7 || nonce.length > 13)
{
throw new IllegalArgumentException("nonce must have length from 7 to 13 octets");
}
+
+ reset();
}
public String getAlgorithmName()
@@ -129,14 +138,11 @@ public class CCMBlockCipher
public int doFinal(byte[] out, int outOff)
throws IllegalStateException, InvalidCipherTextException
{
- byte[] text = data.toByteArray();
- byte[] enc = processPacket(text, 0, text.length);
-
- System.arraycopy(enc, 0, out, outOff, enc.length);
+ int len = processPacket(data.getBuffer(), 0, data.size(), out, outOff);
reset();
- return enc.length;
+ return len;
}
public void reset()
@@ -178,9 +184,55 @@ public class CCMBlockCipher
return totalData < macSize ? 0 : totalData - macSize;
}
+ /**
+ * Process a packet of data for either CCM decryption or encryption.
+ *
+ * @param in data for processing.
+ * @param inOff offset at which data starts in the input array.
+ * @param inLen length of the data in the input array.
+ * @return a byte array containing the processed input..
+ * @throws IllegalStateException if the cipher is not appropriately set up.
+ * @throws InvalidCipherTextException if the input data is truncated or the mac check fails.
+ */
public byte[] processPacket(byte[] in, int inOff, int inLen)
throws IllegalStateException, InvalidCipherTextException
{
+ byte[] output;
+
+ if (forEncryption)
+ {
+ output = new byte[inLen + macSize];
+ }
+ else
+ {
+ if (inLen < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ output = new byte[inLen - macSize];
+ }
+
+ processPacket(in, inOff, inLen, output, 0);
+
+ return output;
+ }
+
+ /**
+ * Process a packet of data for either CCM decryption or encryption.
+ *
+ * @param in data for processing.
+ * @param inOff offset at which data starts in the input array.
+ * @param inLen length of the data in the input array.
+ * @param output output array.
+ * @param outOff offset into output array to start putting processed bytes.
+ * @return the number of bytes added to output.
+ * @throws IllegalStateException if the cipher is not appropriately set up.
+ * @throws InvalidCipherTextException if the input data is truncated or the mac check fails.
+ * @throws DataLengthException if output buffer too short.
+ */
+ public int processPacket(byte[] in, int inOff, int inLen, byte[] output, int outOff)
+ throws IllegalStateException, InvalidCipherTextException, DataLengthException
+ {
// TODO: handle null keyParam (e.g. via RepeatedKeySpec)
// Need to keep the CTR and CBC Mac parts around and reset
if (keyParam == null)
@@ -206,42 +258,52 @@ public class CCMBlockCipher
BlockCipher ctrCipher = new SICBlockCipher(cipher);
ctrCipher.init(forEncryption, new ParametersWithIV(keyParam, iv));
- int index = inOff;
- int outOff = 0;
- byte[] output;
+ int outputLen;
+ int inIndex = inOff;
+ int outIndex = outOff;
if (forEncryption)
{
- output = new byte[inLen + macSize];
+ outputLen = inLen + macSize;
+ if (output.length < (outputLen + outOff))
+ {
+ throw new DataLengthException("Output buffer too short.");
+ }
calculateMac(in, inOff, inLen, macBlock);
ctrCipher.processBlock(macBlock, 0, macBlock, 0); // S0
- while (index < inLen - blockSize) // S1...
+ while (inIndex < (inOff + inLen - blockSize)) // S1...
{
- ctrCipher.processBlock(in, index, output, outOff);
- outOff += blockSize;
- index += blockSize;
+ ctrCipher.processBlock(in, inIndex, output, outIndex);
+ outIndex += blockSize;
+ inIndex += blockSize;
}
byte[] block = new byte[blockSize];
- System.arraycopy(in, index, block, 0, inLen - index);
+ System.arraycopy(in, inIndex, block, 0, inLen + inOff - inIndex);
ctrCipher.processBlock(block, 0, block, 0);
- System.arraycopy(block, 0, output, outOff, inLen - index);
+ System.arraycopy(block, 0, output, outIndex, inLen + inOff - inIndex);
- outOff += inLen - index;
-
- System.arraycopy(macBlock, 0, output, outOff, output.length - outOff);
+ System.arraycopy(macBlock, 0, output, outOff + inLen, macSize);
}
else
{
- output = new byte[inLen - macSize];
+ if (inLen < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
+ outputLen = inLen - macSize;
+ if (output.length < (outputLen + outOff))
+ {
+ throw new DataLengthException("Output buffer too short.");
+ }
- System.arraycopy(in, inOff + inLen - macSize, macBlock, 0, macSize);
+ System.arraycopy(in, inOff + outputLen, macBlock, 0, macSize);
ctrCipher.processBlock(macBlock, 0, macBlock, 0);
@@ -250,24 +312,24 @@ public class CCMBlockCipher
macBlock[i] = 0;
}
- while (outOff < output.length - blockSize)
+ while (inIndex < (inOff + outputLen - blockSize))
{
- ctrCipher.processBlock(in, index, output, outOff);
- outOff += blockSize;
- index += blockSize;
+ ctrCipher.processBlock(in, inIndex, output, outIndex);
+ outIndex += blockSize;
+ inIndex += blockSize;
}
byte[] block = new byte[blockSize];
- System.arraycopy(in, index, block, 0, output.length - outOff);
+ System.arraycopy(in, inIndex, block, 0, outputLen - (inIndex - inOff));
ctrCipher.processBlock(block, 0, block, 0);
- System.arraycopy(block, 0, output, outOff, output.length - outOff);
+ System.arraycopy(block, 0, output, outIndex, outputLen - (inIndex - inOff));
byte[] calculatedMacBlock = new byte[blockSize];
- calculateMac(output, 0, output.length, calculatedMacBlock);
+ calculateMac(output, outOff, outputLen, calculatedMacBlock);
if (!Arrays.constantTimeAreEqual(macBlock, calculatedMacBlock))
{
@@ -275,7 +337,7 @@ public class CCMBlockCipher
}
}
- return output;
+ return outputLen;
}
private int calculateMac(byte[] data, int dataOff, int dataLen, byte[] macBlock)
@@ -344,8 +406,7 @@ public class CCMBlockCipher
}
if (associatedText.size() > 0)
{
- byte[] tmp = associatedText.toByteArray();
- cMac.update(tmp, 0, tmp.length);
+ cMac.update(associatedText.getBuffer(), 0, associatedText.size());
}
extra = (extra + textLength) % 16;
@@ -375,4 +436,17 @@ public class CCMBlockCipher
{
return getAssociatedTextLength() > 0;
}
+
+ private class ExposedByteArrayOutputStream
+ extends ByteArrayOutputStream
+ {
+ public ExposedByteArrayOutputStream()
+ {
+ }
+
+ public byte[] getBuffer()
+ {
+ return this.buf;
+ }
+ }
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
index d0fb9bb..a885169 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CFBBlockCipher.java
@@ -4,6 +4,7 @@ import org.bouncycastle.crypto.BlockCipher;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.util.Arrays;
/**
* implements a Cipher-FeedBack (CFB) mode on top of a simple cipher.
@@ -246,6 +247,16 @@ public class CFBBlockCipher
}
/**
+ * Return the current state of the initialisation vector.
+ *
+ * @return current IV
+ */
+ public byte[] getCurrentIV()
+ {
+ return Arrays.clone(cfbV);
+ }
+
+ /**
* reset the chaining vector back to the IV and reset the underlying
* cipher.
*/
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
index b8e5b61..5388b40 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/CTSBlockCipher.java
@@ -22,8 +22,9 @@ public class CTSBlockCipher
public CTSBlockCipher(
BlockCipher cipher)
{
- if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher))
+ if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher) || (cipher instanceof SICBlockCipher))
{
+ // TODO: This is broken - need to introduce marker interface to differentiate block cipher primitive from mode?
throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
}
@@ -72,7 +73,7 @@ public class CTSBlockCipher
}
/**
- * process a single byte, producing an output block if neccessary.
+ * process a single byte, producing an output block if necessary.
*
* @param in the input byte.
* @param out the space for any output that might be produced.
@@ -200,60 +201,81 @@ public class CTSBlockCipher
if (forEncryption)
{
- cipher.processBlock(buf, 0, block, 0);
-
if (bufOff < blockSize)
{
throw new DataLengthException("need at least one block of input for CTS");
}
- for (int i = bufOff; i != buf.length; i++)
- {
- buf[i] = block[i - blockSize];
- }
-
- for (int i = blockSize; i != bufOff; i++)
- {
- buf[i] ^= block[i - blockSize];
- }
+ cipher.processBlock(buf, 0, block, 0);
- if (cipher instanceof CBCBlockCipher)
+ if (bufOff > blockSize)
{
- BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
-
- c.processBlock(buf, blockSize, out, outOff);
+ for (int i = bufOff; i != buf.length; i++)
+ {
+ buf[i] = block[i - blockSize];
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ buf[i] ^= block[i - blockSize];
+ }
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, blockSize, out, outOff);
+ }
+ else
+ {
+ cipher.processBlock(buf, blockSize, out, outOff);
+ }
+
+ System.arraycopy(block, 0, out, outOff + blockSize, len);
}
else
{
- cipher.processBlock(buf, blockSize, out, outOff);
+ System.arraycopy(block, 0, out, outOff, blockSize);
}
-
- System.arraycopy(block, 0, out, outOff + blockSize, len);
}
else
{
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
byte[] lastBlock = new byte[blockSize];
- if (cipher instanceof CBCBlockCipher)
+ if (bufOff > blockSize)
{
- BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
-
- c.processBlock(buf, 0, block, 0);
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, 0, block, 0);
+ }
+ else
+ {
+ cipher.processBlock(buf, 0, block, 0);
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ }
+
+ System.arraycopy(buf, blockSize, block, 0, len);
+
+ cipher.processBlock(block, 0, out, outOff);
+ System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
}
else
{
cipher.processBlock(buf, 0, block, 0);
- }
- for (int i = blockSize; i != bufOff; i++)
- {
- lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ System.arraycopy(block, 0, out, outOff, blockSize);
}
-
- System.arraycopy(buf, blockSize, block, 0, len);
-
- cipher.processBlock(block, 0, out, outOff);
- System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
}
int offset = bufOff;
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java
index 4999caa..8f74000 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/EAXBlockCipher.java
@@ -123,16 +123,10 @@ public class EAXBlockCipher
mac.update(nonce, 0, nonce.length);
mac.doFinal(nonceMac, 0);
- tag[blockSize - 1] = hTAG;
- mac.update(tag, 0, blockSize);
-
- if (initialAssociatedText != null)
- {
- processAADBytes(initialAssociatedText, 0, initialAssociatedText.length);
- }
-
// Same BlockCipher underlies this and the mac, so reuse last key on cipher
cipher.init(true, new ParametersWithIV(null, nonceMac));
+
+ reset();
}
private void initCipher()
@@ -206,7 +200,7 @@ public class EAXBlockCipher
{
if (cipherInitialized)
{
- throw new IllegalStateException("AAD data cannot be added after encryption/decription processing has begun.");
+ throw new IllegalStateException("AAD data cannot be added after encryption/decryption processing has begun.");
}
mac.update(in, inOff, len);
}
@@ -246,6 +240,10 @@ public class EAXBlockCipher
if (forEncryption)
{
+ if (out.length < (outOff + extra))
+ {
+ throw new DataLengthException("Output buffer too short");
+ }
cipher.processBlock(bufBlock, 0, tmp, 0);
cipher.processBlock(bufBlock, blockSize, tmp, blockSize);
@@ -263,6 +261,10 @@ public class EAXBlockCipher
}
else
{
+ if (extra < macSize)
+ {
+ throw new InvalidCipherTextException("data too short");
+ }
if (extra > macSize)
{
mac.update(bufBlock, 0, extra - macSize);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
new file mode 100644
index 0000000..887c169
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GCFBBlockCipher.java
@@ -0,0 +1,109 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.CipherParameters;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.params.KeyParameter;
+import org.bouncycastle.crypto.params.ParametersWithIV;
+import org.bouncycastle.crypto.params.ParametersWithRandom;
+import org.bouncycastle.crypto.params.ParametersWithSBox;
+
+/**
+ * An implementation of the GOST CFB mode with CryptoPro key meshing as described in RFC 4357.
+ */
+public class GCFBBlockCipher
+ implements BlockCipher
+{
+ private static final byte[] C =
+ {
+ 0x69, 0x00, 0x72, 0x22, 0x64, (byte)0xC9, 0x04, 0x23,
+ (byte)0x8D, 0x3A, (byte)0xDB, (byte)0x96, 0x46, (byte)0xE9, 0x2A, (byte)0xC4,
+ 0x18, (byte)0xFE, (byte)0xAC, (byte)0x94, 0x00, (byte)0xED, 0x07, 0x12,
+ (byte)0xC0, (byte)0x86, (byte)0xDC, (byte)0xC2, (byte)0xEF, 0x4C, (byte)0xA9, 0x2B
+ };
+
+ private final CFBBlockCipher cfbEngine;
+
+ private KeyParameter key;
+ private long counter = 0;
+ private boolean forEncryption;
+
+ public GCFBBlockCipher(BlockCipher engine)
+ {
+ this.cfbEngine = new CFBBlockCipher(engine, engine.getBlockSize() * 8);
+ }
+
+ public void init(boolean forEncryption, CipherParameters params)
+ throws IllegalArgumentException
+ {
+ counter = 0;
+ cfbEngine.init(forEncryption, params);
+
+ this.forEncryption = forEncryption;
+
+ if (params instanceof ParametersWithIV)
+ {
+ params = ((ParametersWithIV)params).getParameters();
+ }
+
+ if (params instanceof ParametersWithRandom)
+ {
+ params = ((ParametersWithRandom)params).getParameters();
+ }
+
+ if (params instanceof ParametersWithSBox)
+ {
+ params = ((ParametersWithSBox)params).getParameters();
+ }
+
+ key = (KeyParameter)params;
+ }
+
+ public String getAlgorithmName()
+ {
+ return "G" + cfbEngine.getAlgorithmName();
+ }
+
+ public int getBlockSize()
+ {
+ return cfbEngine.getBlockSize();
+ }
+
+ public int processBlock(byte[] in, int inOff, byte[] out, int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (counter > 0 && counter % 1024 == 0)
+ {
+ BlockCipher base = cfbEngine.getUnderlyingCipher();
+
+ base.init(false, key);
+
+ byte[] nextKey = new byte[32];
+
+ base.processBlock(C, 0, nextKey, 0);
+ base.processBlock(C, 8, nextKey, 8);
+ base.processBlock(C, 16, nextKey, 16);
+ base.processBlock(C, 24, nextKey, 24);
+
+ key = new KeyParameter(nextKey);
+
+ byte[] iv = new byte[8];
+
+ base.init(true, key);
+
+ base.processBlock(cfbEngine.getCurrentIV(), 0, iv, 0);
+
+ cfbEngine.init(forEncryption, new ParametersWithIV(key, iv));
+ }
+
+ counter += cfbEngine.getBlockSize();
+
+ return cfbEngine.processBlock(in, inOff, out, outOff);
+ }
+
+ public void reset()
+ {
+ counter = 0;
+ cfbEngine.reset();
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
index 1178974..0e66cf3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/GOFBBlockCipher.java
@@ -206,6 +206,9 @@ public class GOFBBlockCipher
*/
public void reset()
{
+ firstStep = true;
+ N3 = 0;
+ N4 = 0;
System.arraycopy(IV, 0, ofbV, 0, IV.length);
cipher.reset();
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java
index d4d2910..6dc7148 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OCBBlockCipher.java
@@ -13,7 +13,7 @@ import org.bouncycastle.util.Arrays;
/**
* An implementation of the "work in progress" Internet-Draft <a
- * href="http://tools.ietf.org/html/draft-irtf-cfrg-ocb-00">The OCB Authenticated-Encryption
+ * href="http://tools.ietf.org/html/draft-irtf-cfrg-ocb-03">The OCB Authenticated-Encryption
* Algorithm</a>, licensed per:
* <p/>
* <blockquote> <a href="http://www.cs.ucdavis.edu/~rogaway/ocb/license1.pdf">License for
@@ -111,7 +111,6 @@ public class OCBBlockCipher
public void init(boolean forEncryption, CipherParameters parameters)
throws IllegalArgumentException
{
-
this.forEncryption = forEncryption;
this.macBlock = null;
@@ -156,23 +155,18 @@ public class OCBBlockCipher
N = new byte[0];
}
- if (N.length > 16 || (N.length == 16 && (N[0] & 0x80) != 0))
+ if (N.length > 15)
{
- /*
- * NOTE: We don't just ignore bit 128 because it would hide from the caller the fact
- * that two nonces differing only in bit 128 are not different.
- */
- throw new IllegalArgumentException("IV must be no more than 127 bits");
+ throw new IllegalArgumentException("IV must be no more than 15 bytes");
}
/*
* KEY-DEPENDENT INITIALISATION
*/
- // if keyParam is null we're reusing the last key.
- if (keyParameter != null)
+ if (keyParameter == null)
{
- // TODO
+ // TODO If 'keyParameter' is null we're re-using the last key.
}
// hashCipher always used in forward mode
@@ -193,17 +187,10 @@ public class OCBBlockCipher
byte[] nonce = new byte[16];
System.arraycopy(N, 0, nonce, nonce.length - N.length, N.length);
- if (N.length == 16)
- {
- nonce[0] &= 0x80;
- }
- else
- {
- nonce[15 - N.length] = 1;
- }
+ nonce[0] = (byte)(macSize << 4);
+ nonce[15 - N.length] |= 1;
int bottom = nonce[15] & 0x3F;
- // System.out.println("bottom: " + bottom);
byte[] Ktop = new byte[16];
nonce[15] &= 0xC0;
@@ -314,7 +301,6 @@ public class OCBBlockCipher
public int processBytes(byte[] input, int inOff, int len, byte[] output, int outOff)
throws DataLengthException
{
-
int resultLen = 0;
for (int i = 0; i < len; ++i)
@@ -334,7 +320,6 @@ public class OCBBlockCipher
throws IllegalStateException,
InvalidCipherTextException
{
-
/*
* For decryption, get the tag from the end of the message
*/
@@ -483,7 +468,6 @@ public class OCBBlockCipher
protected void reset(boolean clearMac)
{
-
hashCipher.reset();
mainCipher.reset();
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java
new file mode 100644
index 0000000..b34432a
--- /dev/null
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/OldCTSBlockCipher.java
@@ -0,0 +1,269 @@
+package org.bouncycastle.crypto.modes;
+
+import org.bouncycastle.crypto.BlockCipher;
+import org.bouncycastle.crypto.BufferedBlockCipher;
+import org.bouncycastle.crypto.DataLengthException;
+import org.bouncycastle.crypto.InvalidCipherTextException;
+
+/**
+ * A Cipher Text Stealing (CTS) mode cipher. CTS allows block ciphers to
+ * be used to produce cipher text which is the same length as the plain text.
+ * <p>
+ * This version applies the CTS algorithm from one block up, rather than following the errata update issued in 2004, where CTS mode is applied
+ * from greater than 1 block up and the first block is processed using CBC mode.
+ * </p>
+ */
+public class OldCTSBlockCipher
+ extends BufferedBlockCipher
+{
+ private int blockSize;
+
+ /**
+ * Create a buffered block cipher that uses Cipher Text Stealing
+ *
+ * @param cipher the underlying block cipher this buffering object wraps.
+ */
+ public OldCTSBlockCipher(
+ BlockCipher cipher)
+ {
+ if ((cipher instanceof OFBBlockCipher) || (cipher instanceof CFBBlockCipher))
+ {
+ throw new IllegalArgumentException("CTSBlockCipher can only accept ECB, or CBC ciphers");
+ }
+
+ this.cipher = cipher;
+
+ blockSize = cipher.getBlockSize();
+
+ buf = new byte[blockSize * 2];
+ bufOff = 0;
+ }
+
+ /**
+ * return the size of the output buffer required for an update
+ * an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update
+ * with len bytes of input.
+ */
+ public int getUpdateOutputSize(
+ int len)
+ {
+ int total = len + bufOff;
+ int leftOver = total % buf.length;
+
+ if (leftOver == 0)
+ {
+ return total - buf.length;
+ }
+
+ return total - leftOver;
+ }
+
+ /**
+ * return the size of the output buffer required for an update plus a
+ * doFinal with an input of len bytes.
+ *
+ * @param len the length of the input.
+ * @return the space required to accommodate a call to update and doFinal
+ * with len bytes of input.
+ */
+ public int getOutputSize(
+ int len)
+ {
+ return len + bufOff;
+ }
+
+ /**
+ * process a single byte, producing an output block if necessary.
+ *
+ * @param in the input byte.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception org.bouncycastle.crypto.DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processByte(
+ byte in,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ int resultLen = 0;
+
+ if (bufOff == buf.length)
+ {
+ resultLen = cipher.processBlock(buf, 0, out, outOff);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+ }
+
+ buf[bufOff++] = in;
+
+ return resultLen;
+ }
+
+ /**
+ * process an array of bytes, producing output if necessary.
+ *
+ * @param in the input byte array.
+ * @param inOff the offset at which the input data starts.
+ * @param len the number of bytes to be copied out of the input array.
+ * @param out the space for any output that might be produced.
+ * @param outOff the offset from which the output will be copied.
+ * @return the number of output bytes copied to out.
+ * @exception org.bouncycastle.crypto.DataLengthException if there isn't enough space in out.
+ * @exception IllegalStateException if the cipher isn't initialised.
+ */
+ public int processBytes(
+ byte[] in,
+ int inOff,
+ int len,
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException
+ {
+ if (len < 0)
+ {
+ throw new IllegalArgumentException("Can't have a negative input length!");
+ }
+
+ int blockSize = getBlockSize();
+ int length = getUpdateOutputSize(len);
+
+ if (length > 0)
+ {
+ if ((outOff + length) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+ }
+
+ int resultLen = 0;
+ int gapLen = buf.length - bufOff;
+
+ if (len > gapLen)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, gapLen);
+
+ resultLen += cipher.processBlock(buf, 0, out, outOff);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ bufOff = blockSize;
+
+ len -= gapLen;
+ inOff += gapLen;
+
+ while (len > blockSize)
+ {
+ System.arraycopy(in, inOff, buf, bufOff, blockSize);
+ resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen);
+ System.arraycopy(buf, blockSize, buf, 0, blockSize);
+
+ len -= blockSize;
+ inOff += blockSize;
+ }
+ }
+
+ System.arraycopy(in, inOff, buf, bufOff, len);
+
+ bufOff += len;
+
+ return resultLen;
+ }
+
+ /**
+ * Process the last block in the buffer.
+ *
+ * @param out the array the block currently being held is copied into.
+ * @param outOff the offset at which the copying starts.
+ * @return the number of output bytes copied to out.
+ * @exception org.bouncycastle.crypto.DataLengthException if there is insufficient space in out for
+ * the output.
+ * @exception IllegalStateException if the underlying cipher is not
+ * initialised.
+ * @exception org.bouncycastle.crypto.InvalidCipherTextException if cipher text decrypts wrongly (in
+ * case the exception will never get thrown).
+ */
+ public int doFinal(
+ byte[] out,
+ int outOff)
+ throws DataLengthException, IllegalStateException, InvalidCipherTextException
+ {
+ if (bufOff + outOff > out.length)
+ {
+ throw new DataLengthException("output buffer to small in doFinal");
+ }
+
+ int blockSize = cipher.getBlockSize();
+ int len = bufOff - blockSize;
+ byte[] block = new byte[blockSize];
+
+ if (forEncryption)
+ {
+ cipher.processBlock(buf, 0, block, 0);
+
+ if (bufOff < blockSize)
+ {
+ throw new DataLengthException("need at least one block of input for CTS");
+ }
+
+ for (int i = bufOff; i != buf.length; i++)
+ {
+ buf[i] = block[i - blockSize];
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ buf[i] ^= block[i - blockSize];
+ }
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, blockSize, out, outOff);
+ }
+ else
+ {
+ cipher.processBlock(buf, blockSize, out, outOff);
+ }
+
+ System.arraycopy(block, 0, out, outOff + blockSize, len);
+ }
+ else
+ {
+ byte[] lastBlock = new byte[blockSize];
+
+ if (cipher instanceof CBCBlockCipher)
+ {
+ BlockCipher c = ((CBCBlockCipher)cipher).getUnderlyingCipher();
+
+ c.processBlock(buf, 0, block, 0);
+ }
+ else
+ {
+ cipher.processBlock(buf, 0, block, 0);
+ }
+
+ for (int i = blockSize; i != bufOff; i++)
+ {
+ lastBlock[i - blockSize] = (byte)(block[i - blockSize] ^ buf[i]);
+ }
+
+ System.arraycopy(buf, blockSize, block, 0, len);
+
+ cipher.processBlock(block, 0, out, outOff);
+ System.arraycopy(lastBlock, 0, out, outOff + blockSize, len);
+ }
+
+ int offset = bufOff;
+
+ reset();
+
+ return offset;
+ }
+}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
index 18e612b..4dee63a 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/PGPCFBBlockCipher.java
@@ -220,13 +220,13 @@ public class PGPCFBBlockCipher
throw new DataLengthException("input buffer too short");
}
- if ((outOff + blockSize) > out.length)
- {
- throw new DataLengthException("output buffer too short");
- }
-
if (count == 0)
{
+ if ((outOff + 2 * blockSize + 2) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
@@ -258,6 +258,11 @@ public class PGPCFBBlockCipher
}
else if (count >= blockSize + 2)
{
+ if ((outOff + blockSize) > out.length)
+ {
+ throw new DataLengthException("output buffer too short");
+ }
+
cipher.processBlock(FR, 0, FRE, 0);
for (int n = 0; n < blockSize; n++)
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
index f2be2fc..fc25810 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/BasicGCMExponentiator.java
@@ -4,21 +4,21 @@ import org.bouncycastle.util.Arrays;
public class BasicGCMExponentiator implements GCMExponentiator
{
- private byte[] x;
+ private int[] x;
public void init(byte[] x)
{
- this.x = Arrays.clone(x);
+ this.x = GCMUtil.asInts(x);
}
public void exponentiateX(long pow, byte[] output)
{
// Initial value is little-endian 1
- byte[] y = GCMUtil.oneAsBytes();
+ int[] y = GCMUtil.oneAsInts();
if (pow > 0)
{
- byte[] powX = Arrays.clone(x);
+ int[] powX = Arrays.clone(x);
do
{
if ((pow & 1L) != 0)
@@ -31,6 +31,6 @@ public class BasicGCMExponentiator implements GCMExponentiator
while (pow > 0);
}
- System.arraycopy(y, 0, output, 0, 16);
+ GCMUtil.asBytes(y, output);
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
index 4875301..3031a44 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/GCMUtil.java
@@ -5,6 +5,32 @@ import org.bouncycastle.util.Arrays;
abstract class GCMUtil
{
+ private static final int E1 = 0xe1000000;
+ private static final byte E1B = (byte)0xe1;
+ private static final long E1L = (E1 & 0xFFFFFFFFL) << 24;
+
+ private static int[] generateLookup()
+ {
+ int[] lookup = new int[256];
+
+ for (int c = 0; c < 256; ++c)
+ {
+ int v = 0;
+ for (int i = 7; i >= 0; --i)
+ {
+ if ((c & (1 << i)) != 0)
+ {
+ v ^= (E1 >>> (7 - i));
+ }
+ }
+ lookup[c] = v;
+ }
+
+ return lookup;
+ }
+
+ private static final int[] LOOKUP = generateLookup();
+
static byte[] oneAsBytes()
{
byte[] tmp = new byte[16];
@@ -15,78 +41,155 @@ abstract class GCMUtil
static int[] oneAsInts()
{
int[] tmp = new int[4];
- tmp[0] = 0x80000000;
+ tmp[0] = 1 << 31;
+ return tmp;
+ }
+
+ static long[] oneAsLongs()
+ {
+ long[] tmp = new long[2];
+ tmp[0] = 1L << 63;
return tmp;
}
- static byte[] asBytes(int[] ns)
+ static byte[] asBytes(int[] x)
+ {
+ byte[] z = new byte[16];
+ Pack.intToBigEndian(x, z, 0);
+ return z;
+ }
+
+ static void asBytes(int[] x, byte[] z)
+ {
+ Pack.intToBigEndian(x, z, 0);
+ }
+
+ static byte[] asBytes(long[] x)
+ {
+ byte[] z = new byte[16];
+ Pack.longToBigEndian(x, z, 0);
+ return z;
+ }
+
+ static void asBytes(long[] x, byte[] z)
+ {
+ Pack.longToBigEndian(x, z, 0);
+ }
+
+ static int[] asInts(byte[] x)
+ {
+ int[] z = new int[4];
+ Pack.bigEndianToInt(x, 0, z);
+ return z;
+ }
+
+ static void asInts(byte[] x, int[] z)
{
- byte[] output = new byte[16];
- Pack.intToBigEndian(ns, output, 0);
- return output;
+ Pack.bigEndianToInt(x, 0, z);
}
- static int[] asInts(byte[] bs)
+ static long[] asLongs(byte[] x)
{
- int[] output = new int[4];
- Pack.bigEndianToInt(bs, 0, output);
- return output;
+ long[] z = new long[2];
+ Pack.bigEndianToLong(x, 0, z);
+ return z;
}
- static void asInts(byte[] bs, int[] output)
+ static void asLongs(byte[] x, long[] z)
{
- Pack.bigEndianToInt(bs, 0, output);
+ Pack.bigEndianToLong(x, 0, z);
}
- static void multiply(byte[] block, byte[] val)
+ static void multiply(byte[] x, byte[] y)
{
- byte[] tmp = Arrays.clone(block);
- byte[] c = new byte[16];
+ byte[] r0 = Arrays.clone(x);
+ byte[] r1 = new byte[16];
for (int i = 0; i < 16; ++i)
{
- byte bits = val[i];
+ byte bits = y[i];
for (int j = 7; j >= 0; --j)
{
if ((bits & (1 << j)) != 0)
{
- xor(c, tmp);
+ xor(r1, r0);
}
- boolean lsb = (tmp[15] & 1) != 0;
- shiftRight(tmp);
- if (lsb)
+ if (shiftRight(r0) != 0)
{
- // R = new byte[]{ 0xe1, ... };
-// GCMUtil.xor(v, R);
- tmp[0] ^= (byte)0xe1;
+ r0[0] ^= E1B;
}
}
}
- System.arraycopy(c, 0, block, 0, 16);
+ System.arraycopy(r1, 0, x, 0, 16);
+ }
+
+ static void multiply(int[] x, int[] y)
+ {
+ int[] r0 = Arrays.clone(x);
+ int[] r1 = new int[4];
+
+ for (int i = 0; i < 4; ++i)
+ {
+ int bits = y[i];
+ for (int j = 31; j >= 0; --j)
+ {
+ if ((bits & (1 << j)) != 0)
+ {
+ xor(r1, r0);
+ }
+
+ if (shiftRight(r0) != 0)
+ {
+ r0[0] ^= E1;
+ }
+ }
+ }
+
+ System.arraycopy(r1, 0, x, 0, 4);
+ }
+
+ static void multiply(long[] x, long[] y)
+ {
+ long[] r0 = new long[]{ x[0], x[1] };
+ long[] r1 = new long[2];
+
+ for (int i = 0; i < 2; ++i)
+ {
+ long bits = y[i];
+ for (int j = 63; j >= 0; --j)
+ {
+ if ((bits & (1L << j)) != 0)
+ {
+ xor(r1, r0);
+ }
+
+ if (shiftRight(r0) != 0)
+ {
+ r0[0] ^= E1L;
+ }
+ }
+ }
+
+ x[0] = r1[0];
+ x[1] = r1[1];
}
// P is the value with only bit i=1 set
static void multiplyP(int[] x)
{
- boolean lsb = (x[3] & 1) != 0;
- shiftRight(x);
- if (lsb)
+ if (shiftRight(x) != 0)
{
- // R = new int[]{ 0xe1000000, 0, 0, 0 };
-// xor(v, R);
- x[0] ^= 0xe1000000;
+ x[0] ^= E1;
}
}
- static void multiplyP(int[] x, int[] output)
+ static void multiplyP(int[] x, int[] y)
{
- boolean lsb = (x[3] & 1) != 0;
- shiftRight(x, output);
- if (lsb)
+ if (shiftRight(x, y) != 0)
{
- output[0] ^= 0xe1000000;
+ y[0] ^= E1;
}
}
@@ -98,163 +201,257 @@ abstract class GCMUtil
// multiplyP(x);
// }
- int lsw = x[3];
- shiftRightN(x, 8);
- for (int i = 7; i >= 0; --i)
- {
- if ((lsw & (1 << i)) != 0)
- {
- x[0] ^= (0xe1000000 >>> (7 - i));
- }
- }
+ int c = shiftRightN(x, 8);
+ x[0] ^= LOOKUP[c >>> 24];
}
- static void multiplyP8(int[] x, int[] output)
+ static void multiplyP8(int[] x, int[] y)
{
- int lsw = x[3];
- shiftRightN(x, 8, output);
- for (int i = 7; i >= 0; --i)
- {
- if ((lsw & (1 << i)) != 0)
- {
- output[0] ^= (0xe1000000 >>> (7 - i));
- }
- }
+ int c = shiftRightN(x, 8, y);
+ y[0] ^= LOOKUP[c >>> 24];
}
- static void shiftRight(byte[] block)
+ static byte shiftRight(byte[] x)
{
- int i = 0;
- int bit = 0;
- for (;;)
+// int c = 0;
+// for (int i = 0; i < 16; ++i)
+// {
+// int b = x[i] & 0xff;
+// x[i] = (byte)((b >>> 1) | c);
+// c = (b & 1) << 7;
+// }
+// return (byte)c;
+
+ int i = 0, c = 0;
+ do
{
- int b = block[i] & 0xff;
- block[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
+ int b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ x[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
}
+ while (i < 16);
+ return (byte)c;
}
- static void shiftRight(byte[] block, byte[] output)
+ static byte shiftRight(byte[] x, byte[] z)
{
- int i = 0;
- int bit = 0;
- for (;;)
+// int c = 0;
+// for (int i = 0; i < 16; ++i)
+// {
+// int b = x[i] & 0xff;
+// z[i] = (byte) ((b >>> 1) | c);
+// c = (b & 1) << 7;
+// }
+// return (byte) c;
+
+ int i = 0, c = 0;
+ do
{
- int b = block[i] & 0xff;
- output[i] = (byte) ((b >>> 1) | bit);
- if (++i == 16)
- {
- break;
- }
- bit = (b & 1) << 7;
+ int b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
+ b = x[i] & 0xff;
+ z[i++] = (byte)((b >>> 1) | c);
+ c = (b & 1) << 7;
}
+ while (i < 16);
+ return (byte)c;
}
- static void shiftRight(int[] block)
+ static int shiftRight(int[] x)
{
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i];
- block[i] = (b >>> 1) | bit;
- if (++i == 4)
- {
- break;
- }
- bit = b << 31;
- }
+// int c = 0;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// x[i] = (b >>> 1) | c;
+// c = b << 31;
+// }
+// return c;
+
+ int b = x[0];
+ x[0] = b >>> 1;
+ int c = b << 31;
+ b = x[1];
+ x[1] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[2];
+ x[2] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[3];
+ x[3] = (b >>> 1) | c;
+ return b << 31;
}
- static void shiftRight(int[] block, int[] output)
+ static int shiftRight(int[] x, int[] z)
{
- int i = 0;
- int bit = 0;
- for (;;)
- {
- int b = block[i];
- output[i] = (b >>> 1) | bit;
- if (++i == 4)
- {
- break;
- }
- bit = b << 31;
- }
+// int c = 0;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// z[i] = (b >>> 1) | c;
+// c = b << 31;
+// }
+// return c;
+
+ int b = x[0];
+ z[0] = b >>> 1;
+ int c = b << 31;
+ b = x[1];
+ z[1] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[2];
+ z[2] = (b >>> 1) | c;
+ c = b << 31;
+ b = x[3];
+ z[3] = (b >>> 1) | c;
+ return b << 31;
}
- static void shiftRightN(int[] block, int n)
+ static long shiftRight(long[] x)
{
- int i = 0;
- int bits = 0;
- for (;;)
- {
- int b = block[i];
- block[i] = (b >>> n) | bits;
- if (++i == 4)
- {
- break;
- }
- bits = b << (32 - n);
- }
+ long b = x[0];
+ x[0] = b >>> 1;
+ long c = b << 63;
+ b = x[1];
+ x[1] = (b >>> 1) | c;
+ return b << 63;
+ }
+
+ static long shiftRight(long[] x, long[] z)
+ {
+ long b = x[0];
+ z[0] = b >>> 1;
+ long c = b << 63;
+ b = x[1];
+ z[1] = (b >>> 1) | c;
+ return b << 63;
+ }
+
+ static int shiftRightN(int[] x, int n)
+ {
+// int c = 0, nInv = 32 - n;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// x[i] = (b >>> n) | c;
+// c = b << nInv;
+// }
+// return c;
+
+ int b = x[0], nInv = 32 - n;
+ x[0] = b >>> n;
+ int c = b << nInv;
+ b = x[1];
+ x[1] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[2];
+ x[2] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[3];
+ x[3] = (b >>> n) | c;
+ return b << nInv;
}
- static void shiftRightN(int[] block, int n, int[] output)
+ static int shiftRightN(int[] x, int n, int[] z)
+ {
+// int c = 0, nInv = 32 - n;
+// for (int i = 0; i < 4; ++i)
+// {
+// int b = x[i];
+// z[i] = (b >>> n) | c;
+// c = b << nInv;
+// }
+// return c;
+
+ int b = x[0], nInv = 32 - n;
+ z[0] = b >>> n;
+ int c = b << nInv;
+ b = x[1];
+ z[1] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[2];
+ z[2] = (b >>> n) | c;
+ c = b << nInv;
+ b = x[3];
+ z[3] = (b >>> n) | c;
+ return b << nInv;
+ }
+
+ static void xor(byte[] x, byte[] y)
{
int i = 0;
- int bits = 0;
- for (;;)
+ do
{
- int b = block[i];
- output[i] = (b >>> n) | bits;
- if (++i == 4)
- {
- break;
- }
- bits = b << (32 - n);
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
+ x[i] ^= y[i]; ++i;
}
+ while (i < 16);
}
- static void xor(byte[] block, byte[] val)
+ static void xor(byte[] x, byte[] y, int yOff, int yLen)
{
- for (int i = 15; i >= 0; --i)
+ while (yLen-- > 0)
{
- block[i] ^= val[i];
+ x[yLen] ^= y[yOff + yLen];
}
}
- static void xor(byte[] block, byte[] val, int off, int len)
+ static void xor(byte[] x, byte[] y, byte[] z)
{
- while (len-- > 0)
+ int i = 0;
+ do
{
- block[len] ^= val[off + len];
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
+ z[i] = (byte)(x[i] ^ y[i]); ++i;
}
+ while (i < 16);
}
- static void xor(byte[] block, byte[] val, byte[] output)
+ static void xor(int[] x, int[] y)
{
- for (int i = 15; i >= 0; --i)
- {
- output[i] = (byte)(block[i] ^ val[i]);
- }
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ x[2] ^= y[2];
+ x[3] ^= y[3];
}
- static void xor(int[] block, int[] val)
+ static void xor(int[] x, int[] y, int[] z)
{
- for (int i = 3; i >= 0; --i)
- {
- block[i] ^= val[i];
- }
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
+ z[2] = x[2] ^ y[2];
+ z[3] = x[3] ^ y[3];
}
- static void xor(int[] block, int[] val, int[] output)
+ static void xor(long[] x, long[] y)
{
- for (int i = 3; i >= 0; --i)
- {
- output[i] = block[i] ^ val[i];
- }
+ x[0] ^= y[0];
+ x[1] ^= y[1];
+ }
+
+ static void xor(long[] x, long[] y, long[] z)
+ {
+ z[0] = x[0] ^ y[0];
+ z[1] = x[1] ^ y[1];
}
}
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
index a051208..6eff4e3 100644
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
+++ b/bcprov/src/main/java/org/bouncycastle/crypto/modes/gcm/Tables1kGCMExponentiator.java
@@ -12,31 +12,32 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
public void init(byte[] x)
{
- if (lookupPowX2 != null && Arrays.areEqual(x, (byte[])lookupPowX2.elementAt(0)))
+ int[] y = GCMUtil.asInts(x);
+ if (lookupPowX2 != null && Arrays.areEqual(y, (int[])lookupPowX2.elementAt(0)))
{
return;
}
lookupPowX2 = new Vector(8);
- lookupPowX2.addElement(Arrays.clone(x));
+ lookupPowX2.addElement(y);
}
public void exponentiateX(long pow, byte[] output)
{
- byte[] y = GCMUtil.oneAsBytes();
+ int[] y = GCMUtil.oneAsInts();
int bit = 0;
while (pow > 0)
{
if ((pow & 1L) != 0)
{
ensureAvailable(bit);
- GCMUtil.multiply(y, (byte[])lookupPowX2.elementAt(bit));
+ GCMUtil.multiply(y, (int[])lookupPowX2.elementAt(bit));
}
++bit;
pow >>>= 1;
}
- System.arraycopy(y, 0, output, 0, 16);
+ GCMUtil.asBytes(y, output);
}
private void ensureAvailable(int bit)
@@ -44,7 +45,7 @@ public class Tables1kGCMExponentiator implements GCMExponentiator
int count = lookupPowX2.size();
if (count <= bit)
{
- byte[] tmp = (byte[])lookupPowX2.elementAt(count - 1);
+ int[] tmp = (int[])lookupPowX2.elementAt(count - 1);
do
{
tmp = Arrays.clone(tmp);
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/modes/package.html b/bcprov/src/main/java/org/bouncycastle/crypto/modes/package.html
deleted file mode 100644
index 5402df4..0000000
--- a/bcprov/src/main/java/org/bouncycastle/crypto/modes/package.html
+++ /dev/null
@@ -1,5 +0,0 @@
-<html>
-<body bgcolor="#ffffff">
-Modes for symmetric ciphers.
-</body>
-</html>