diff options
author | Sergio Giro <sgiro@google.com> | 2016-02-01 18:52:42 +0000 |
---|---|---|
committer | Gerrit Code Review <noreply-gerritcodereview@google.com> | 2016-02-01 18:52:42 +0000 |
commit | 9218edabd1ef9852bc2f13115dcadc81b442dd6c (patch) | |
tree | 8229ff72c8cbb06f49dce3a8382930919fa6fc2b /bcprov/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java | |
parent | 9b30eb05e5be69d51881a0d1b31e503e97acd784 (diff) | |
parent | 397d32894b89b506dc318e0f83446187c9b76ebe (diff) | |
download | android_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.tar.gz android_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.tar.bz2 android_external_bouncycastle-9218edabd1ef9852bc2f13115dcadc81b442dd6c.zip |
Merge "Merge remote-tracking branch 'aosp/upstream-master' into merge-152-from-upstream"
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java | 263 |
1 files changed, 263 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java b/bcprov/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java new file mode 100644 index 0000000..c4494c4 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/crypto/engines/NoekeonEngine.java @@ -0,0 +1,263 @@ +package org.bouncycastle.crypto.engines; + +import org.bouncycastle.crypto.BlockCipher; +import org.bouncycastle.crypto.CipherParameters; +import org.bouncycastle.crypto.DataLengthException; +import org.bouncycastle.crypto.OutputLengthException; +import org.bouncycastle.crypto.params.KeyParameter; + +/** + * A Noekeon engine, using direct-key mode. + */ + +public class NoekeonEngine + implements BlockCipher +{ + private static final int genericSize = 16; // Block and key size, as well as the amount of rounds. + + private static final int[] nullVector = + { + 0x00, 0x00, 0x00, 0x00 // Used in decryption + }, + + roundConstants = + { + 0x80, 0x1b, 0x36, 0x6c, + 0xd8, 0xab, 0x4d, 0x9a, + 0x2f, 0x5e, 0xbc, 0x63, + 0xc6, 0x97, 0x35, 0x6a, + 0xd4 + }; + + private int[] state = new int[4], // a + subKeys = new int[4], // k + decryptKeys = new int[4]; + + private boolean _initialised, + _forEncryption; + + /** + * Create an instance of the Noekeon encryption algorithm + * and set some defaults + */ + public NoekeonEngine() + { + _initialised = false; + } + + public String getAlgorithmName() + { + return "Noekeon"; + } + + public int getBlockSize() + { + return genericSize; + } + + /** + * initialise + * + * @param forEncryption whether or not we are for encryption. + * @param params the parameters required to set up the cipher. + * @exception IllegalArgumentException if the params argument is + * inappropriate. + */ + public void init( + boolean forEncryption, + CipherParameters params) + { + if (!(params instanceof KeyParameter)) + { + throw new IllegalArgumentException("invalid parameter passed to Noekeon init - " + params.getClass().getName()); + } + + _forEncryption = forEncryption; + _initialised = true; + + KeyParameter p = (KeyParameter)params; + + setKey(p.getKey()); + } + + public int processBlock( + byte[] in, + int inOff, + byte[] out, + int outOff) + { + if (!_initialised) + { + throw new IllegalStateException(getAlgorithmName()+" not initialised"); + } + + if ((inOff + genericSize) > in.length) + { + throw new DataLengthException("input buffer too short"); + } + + if ((outOff + genericSize) > out.length) + { + throw new OutputLengthException("output buffer too short"); + } + + return (_forEncryption) ? encryptBlock(in, inOff, out, outOff) + : decryptBlock(in, inOff, out, outOff); + } + + public void reset() + { + } + + /** + * Re-key the cipher. + * <p> + * @param key the key to be used + */ + private void setKey( + byte[] key) + { + subKeys[0] = bytesToIntBig(key, 0); + subKeys[1] = bytesToIntBig(key, 4); + subKeys[2] = bytesToIntBig(key, 8); + subKeys[3] = bytesToIntBig(key, 12); + } + + private int encryptBlock( + byte[] in, + int inOff, + byte[] out, + int outOff) + { + state[0] = bytesToIntBig(in, inOff); + state[1] = bytesToIntBig(in, inOff+4); + state[2] = bytesToIntBig(in, inOff+8); + state[3] = bytesToIntBig(in, inOff+12); + + int i; + for (i = 0; i < genericSize; i++) + { + state[0] ^= roundConstants[i]; + theta(state, subKeys); + pi1(state); + gamma(state); + pi2(state); + } + + state[0] ^= roundConstants[i]; + theta(state, subKeys); + + intToBytesBig(state[0], out, outOff); + intToBytesBig(state[1], out, outOff+4); + intToBytesBig(state[2], out, outOff+8); + intToBytesBig(state[3], out, outOff+12); + + return genericSize; + } + + private int decryptBlock( + byte[] in, + int inOff, + byte[] out, + int outOff) + { + state[0] = bytesToIntBig(in, inOff); + state[1] = bytesToIntBig(in, inOff+4); + state[2] = bytesToIntBig(in, inOff+8); + state[3] = bytesToIntBig(in, inOff+12); + + System.arraycopy(subKeys, 0, decryptKeys, 0, subKeys.length); + theta(decryptKeys, nullVector); + + int i; + for (i = genericSize; i > 0; i--) + { + theta(state, decryptKeys); + state[0] ^= roundConstants[i]; + pi1(state); + gamma(state); + pi2(state); + } + + theta(state, decryptKeys); + state[0] ^= roundConstants[i]; + + intToBytesBig(state[0], out, outOff); + intToBytesBig(state[1], out, outOff+4); + intToBytesBig(state[2], out, outOff+8); + intToBytesBig(state[3], out, outOff+12); + + return genericSize; + } + + private void gamma(int[] a) + { + a[1] ^= ~a[3] & ~a[2]; + a[0] ^= a[2] & a[1]; + + int tmp = a[3]; + a[3] = a[0]; + a[0] = tmp; + a[2] ^= a[0]^a[1]^a[3]; + + a[1] ^= ~a[3] & ~a[2]; + a[0] ^= a[2] & a[1]; + } + + private void theta(int[] a, int[] k) + { + int tmp; + + tmp = a[0]^a[2]; + tmp ^= rotl(tmp,8)^rotl(tmp,24); + a[1] ^= tmp; + a[3] ^= tmp; + + for (int i = 0; i < 4; i++) + { + a[i] ^= k[i]; + } + + tmp = a[1]^a[3]; + tmp ^= rotl(tmp,8)^rotl(tmp,24); + a[0] ^= tmp; + a[2] ^= tmp; + } + + private void pi1(int[] a) + { + a[1] = rotl(a[1], 1); + a[2] = rotl(a[2], 5); + a[3] = rotl(a[3], 2); + } + + private void pi2(int[] a) + { + a[1] = rotl(a[1], 31); + a[2] = rotl(a[2], 27); + a[3] = rotl(a[3], 30); + } + + // Helpers + + private int bytesToIntBig(byte[] in, int off) + { + return ((in[off++]) << 24) | + ((in[off++] & 0xff) << 16) | + ((in[off++] & 0xff) << 8) | + (in[off ] & 0xff); + } + + private void intToBytesBig(int x, byte[] out, int off) + { + out[off++] = (byte)(x >>> 24); + out[off++] = (byte)(x >>> 16); + out[off++] = (byte)(x >>> 8); + out[off ] = (byte)x; + } + + private int rotl(int x, int y) + { + return (x << y) | (x >>> (32-y)); + } +} |