GordianSosemanukEngine.java
/*
* GordianKnot: Security Suite
* Copyright 2012-2026. Tony Washer
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.github.tonywasher.joceanus.gordianknot.impl.ext.engines;
import org.bouncycastle.crypto.CipherParameters;
import org.bouncycastle.crypto.DataLengthException;
import org.bouncycastle.crypto.OutputLengthException;
import org.bouncycastle.crypto.StreamCipher;
import org.bouncycastle.crypto.params.KeyParameter;
import org.bouncycastle.crypto.params.ParametersWithIV;
import org.bouncycastle.util.Memoable;
/**
* StreamCipher implementation based on the SosemanukFast java implementation.
* <p>
* Copied from http://www.ecrypt.eu.org/stream/e2-sosemanuk.html.
*/
@SuppressWarnings("checkstyle:MagicNumber")
public class GordianSosemanukEngine
implements StreamCipher, Memoable {
/**
* Advanced stream length.
*/
private static final int STREAM_LEN = 80;
/**
* index of next byte in keyStream.
*/
private int theIndex;
/**
* Advanced stream.
*/
private final byte[] keyStream = new byte[STREAM_LEN];
/**
* Reset state.
*/
private GordianSosemanukEngine theResetState;
/**
* Constructor.
*/
public GordianSosemanukEngine() {
}
/**
* Constructor.
*
* @param pSource the source engine
*/
private GordianSosemanukEngine(final GordianSosemanukEngine pSource) {
reset(pSource);
}
/**
* initialise a Susemanuk cipher.
*
* @param forEncryption whether or not we are for encryption.
* @param params the parameters required to set up the cipher.
* @throws IllegalArgumentException if the params argument is inappropriate.
*/
public void init(final boolean forEncryption,
final CipherParameters params) {
/*
* Sosemanuk encryption and decryption is completely symmetrical, so the 'forEncryption' is
* irrelevant. (Like 90% of stream ciphers)
*/
/* Determine parameters */
CipherParameters myParams = params;
byte[] newKey = null;
byte[] newIV = null;
if ((myParams instanceof ParametersWithIV)) {
final ParametersWithIV ivParams = (ParametersWithIV) myParams;
newIV = ivParams.getIV();
myParams = ivParams.getParameters();
}
if (myParams instanceof KeyParameter) {
final KeyParameter keyParam = (KeyParameter) myParams;
newKey = keyParam.getKey();
}
/* Initialise engine and mark as initialised */
theIndex = 0;
setKey(newKey);
setIV(newIV);
makeStreamBlock(keyStream, 0);
/* Save reset state */
theResetState = copy();
}
@Override
public String getAlgorithmName() {
return "Sosemanuk";
}
@Override
public int processBytes(final byte[] in,
final int inOff,
final int len,
final byte[] out,
final int outOff) {
/* Check for errors */
if (theResetState == null) {
throw new IllegalStateException(getAlgorithmName() + " not initialised");
}
if ((inOff + len) > in.length) {
throw new DataLengthException("input buffer too short");
}
if ((outOff + len) > out.length) {
throw new OutputLengthException("output buffer too short");
}
/* Loop through the input bytes */
for (int i = 0; i < len; i++) {
out[i + outOff] = returnByte(in[i + inOff]);
}
return len;
}
@Override
public void reset() {
if (theResetState != null) {
reset(theResetState);
}
}
@Override
public byte returnByte(final byte in) {
final byte out = (byte) (keyStream[theIndex] ^ in);
theIndex = (theIndex + 1) % STREAM_LEN;
if (theIndex == 0) {
makeStreamBlock(keyStream, 0);
}
return out;
}
@Override
public GordianSosemanukEngine copy() {
return new GordianSosemanukEngine(this);
}
@Override
public void reset(final Memoable pState) {
final GordianSosemanukEngine e = (GordianSosemanukEngine) pState;
lfsr0 = e.lfsr0;
lfsr1 = e.lfsr1;
lfsr2 = e.lfsr2;
lfsr3 = e.lfsr3;
lfsr4 = e.lfsr4;
lfsr5 = e.lfsr5;
lfsr6 = e.lfsr6;
lfsr7 = e.lfsr7;
lfsr8 = e.lfsr8;
lfsr9 = e.lfsr9;
fsmR1 = e.fsmR1;
fsmR2 = e.fsmR2;
System.arraycopy(e.keyStream, 0, keyStream, 0, STREAM_LEN);
theIndex = e.theIndex;
}
/**
* LFSR0 State.
*/
private int lfsr0;
/**
* LFSR1 State.
*/
private int lfsr1;
/**
* LFSR2 State.
*/
private int lfsr2;
/**
* LFSR3 State.
*/
private int lfsr3;
/**
* LFSR4 State.
*/
private int lfsr4;
/**
* LFSR5 State.
*/
private int lfsr5;
/**
* LFSR6 State.
*/
private int lfsr6;
/**
* LFSR7 State.
*/
private int lfsr7;
/**
* LFSR8 State.
*/
private int lfsr8;
/**
* LFSR9 State.
*/
private int lfsr9;
/**
* FSMR1 State.
*/
private int fsmR1;
/**
* FSMR2 State.
*/
private int fsmR2;
/*
* The code internals for the SERPENT-derived functions have been
* semi-automatically generated, using a mixture of C, C
* preprocessor, vi macros and Forth. The base circuits for
* the SERPENT S-boxes have been published by Dag Arne Osvik
* ("Speeding up Serpent", at the 3rd AES Candidate Conference).
*/
/**
* Decode a 32-bit value from a buffer (little-endian).
*
* @param buf the input buffer
* @param off the input offset
* @return the decoded value
*/
private static int decode32le(final byte[] buf, final int off) {
return (buf[off] & 0xFF)
| ((buf[off + 1] & 0xFF) << 8)
| ((buf[off + 2] & 0xFF) << 16)
| ((buf[off + 3] & 0xFF) << 24);
}
/**
* Encode a 32-bit value into a buffer (little-endian).
*
* @param val the value to encode
* @param buf the output buffer
* @param off the output offset
*/
private static void encode32le(final int val, final byte[] buf, final int off) {
buf[off] = (byte) val;
buf[off + 1] = (byte) (val >> 8);
buf[off + 2] = (byte) (val >> 16);
buf[off + 3] = (byte) (val >> 24);
}
/**
* Left-rotate a 32-bit value by some bit.
*
* @param val the value to rotate
* @param n the rotation count (between 1 and 31)
* @return rotated value
*/
private static int rotateLeft(final int val, final int n) {
return (val << n) | (val >>> (32 - n));
}
/**
* Subkeys for Serpent24: 100 32-bit words.
*/
private final int[] serpent24SubKeys = new int[100];
/**
* Set the private key. The key length must be between 1
* and 32 bytes.
*
* @param key the private key
*/
@SuppressWarnings("checkstyle:MethodLength")
public void setKey(final byte[] key) {
if (key.length < 1 || key.length > 32) {
throw new IllegalArgumentException("bad key length: " + key.length);
}
final byte[] lkey;
if (key.length == 32) {
lkey = key;
} else {
lkey = new byte[32];
System.arraycopy(key, 0, lkey, 0, key.length);
lkey[key.length] = 0x01;
for (int i = key.length + 1; i < lkey.length; i++) {
lkey[i] = 0x00;
}
}
int i = 0;
int w0 = decode32le(lkey, 0);
int w1 = decode32le(lkey, 4);
int w2 = decode32le(lkey, 8);
int w3 = decode32le(lkey, 12);
int w4 = decode32le(lkey, 16);
int w5 = decode32le(lkey, 20);
int w6 = decode32le(lkey, 24);
int w7 = decode32le(lkey, 28);
int tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (0));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (0 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (0 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (0 + 3));
w3 = rotateLeft(tt, 11);
int r0 = w0;
int r1 = w1;
int r2 = w2;
int r3 = w3;
int r4 = r0;
r0 |= r3;
r3 ^= r1;
r1 &= r4;
r4 ^= r2;
r2 ^= r3;
r3 &= r0;
r4 |= r1;
r3 ^= r4;
r0 ^= r1;
r4 &= r0;
r1 ^= r3;
r4 ^= r2;
r1 |= r0;
r1 ^= r2;
r0 ^= r3;
r2 = r1;
r1 |= r3;
r1 ^= r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r4;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (4));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (4 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (4 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (4 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r4 = r0;
r0 &= r2;
r0 ^= r3;
r2 ^= r1;
r2 ^= r0;
r3 |= r4;
r3 ^= r1;
r4 ^= r2;
r1 = r3;
r3 |= r4;
r3 ^= r0;
r0 &= r1;
r4 ^= r0;
r1 ^= r3;
r1 ^= r4;
r4 = ~r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (8));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (8 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (8 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (8 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 = ~r0;
r2 = ~r2;
r4 = r0;
r0 &= r1;
r2 ^= r0;
r0 |= r3;
r3 ^= r2;
r1 ^= r0;
r0 ^= r4;
r4 |= r1;
r1 ^= r3;
r2 |= r0;
r2 &= r4;
r0 ^= r1;
r1 &= r2;
r1 ^= r0;
r0 &= r2;
r0 ^= r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (12));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (12 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (12 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (12 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r4 ^= r2;
r1 ^= r0;
r0 |= r3;
r0 ^= r4;
r4 ^= r3;
r3 ^= r2;
r2 |= r1;
r2 ^= r4;
r4 = ~r4;
r4 |= r1;
r1 ^= r3;
r1 ^= r4;
r3 |= r0;
r1 ^= r3;
r4 ^= r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (16));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (16 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (16 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (16 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r1;
r1 |= r2;
r1 ^= r3;
r4 ^= r2;
r2 ^= r1;
r3 |= r4;
r3 &= r0;
r4 ^= r2;
r3 ^= r1;
r1 |= r4;
r1 ^= r0;
r0 |= r4;
r0 ^= r2;
r1 ^= r4;
r2 ^= r1;
r1 &= r0;
r1 ^= r4;
r2 = ~r2;
r2 |= r0;
r4 ^= r2;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r0;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (20));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (20 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (20 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (20 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r2 = ~r2;
r4 = r3;
r3 &= r0;
r0 ^= r4;
r3 ^= r2;
r2 |= r4;
r1 ^= r3;
r2 ^= r0;
r0 |= r1;
r2 ^= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r4 ^= r3;
r4 ^= r0;
r3 = ~r3;
r2 &= r4;
r2 ^= r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (24));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (24 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (24 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (24 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 ^= r1;
r1 ^= r3;
r3 = ~r3;
r4 = r1;
r1 &= r0;
r2 ^= r3;
r1 ^= r2;
r2 |= r4;
r4 ^= r3;
r3 &= r1;
r3 ^= r0;
r4 ^= r1;
r4 ^= r2;
r2 ^= r0;
r0 &= r3;
r2 = ~r2;
r0 ^= r4;
r4 |= r3;
r2 ^= r4;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r2;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (28));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (28 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (28 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (28 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r1 ^= r3;
r3 = ~r3;
r2 ^= r3;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r1 ^= r2;
r4 ^= r3;
r0 ^= r4;
r2 &= r4;
r2 ^= r0;
r0 &= r1;
r3 ^= r0;
r4 |= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r2 &= r3;
r0 = ~r0;
r4 ^= r2;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (32));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (32 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (32 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (32 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r0;
r0 |= r3;
r3 ^= r1;
r1 &= r4;
r4 ^= r2;
r2 ^= r3;
r3 &= r0;
r4 |= r1;
r3 ^= r4;
r0 ^= r1;
r4 &= r0;
r1 ^= r3;
r4 ^= r2;
r1 |= r0;
r1 ^= r2;
r0 ^= r3;
r2 = r1;
r1 |= r3;
r1 ^= r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r4;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (36));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (36 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (36 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (36 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r4 = r0;
r0 &= r2;
r0 ^= r3;
r2 ^= r1;
r2 ^= r0;
r3 |= r4;
r3 ^= r1;
r4 ^= r2;
r1 = r3;
r3 |= r4;
r3 ^= r0;
r0 &= r1;
r4 ^= r0;
r1 ^= r3;
r1 ^= r4;
r4 = ~r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (40));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (40 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (40 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (40 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 = ~r0;
r2 = ~r2;
r4 = r0;
r0 &= r1;
r2 ^= r0;
r0 |= r3;
r3 ^= r2;
r1 ^= r0;
r0 ^= r4;
r4 |= r1;
r1 ^= r3;
r2 |= r0;
r2 &= r4;
r0 ^= r1;
r1 &= r2;
r1 ^= r0;
r0 &= r2;
r0 ^= r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (44));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (44 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (44 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (44 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r4 ^= r2;
r1 ^= r0;
r0 |= r3;
r0 ^= r4;
r4 ^= r3;
r3 ^= r2;
r2 |= r1;
r2 ^= r4;
r4 = ~r4;
r4 |= r1;
r1 ^= r3;
r1 ^= r4;
r3 |= r0;
r1 ^= r3;
r4 ^= r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (48));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (48 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (48 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (48 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r1;
r1 |= r2;
r1 ^= r3;
r4 ^= r2;
r2 ^= r1;
r3 |= r4;
r3 &= r0;
r4 ^= r2;
r3 ^= r1;
r1 |= r4;
r1 ^= r0;
r0 |= r4;
r0 ^= r2;
r1 ^= r4;
r2 ^= r1;
r1 &= r0;
r1 ^= r4;
r2 = ~r2;
r2 |= r0;
r4 ^= r2;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r0;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (52));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (52 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (52 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (52 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r2 = ~r2;
r4 = r3;
r3 &= r0;
r0 ^= r4;
r3 ^= r2;
r2 |= r4;
r1 ^= r3;
r2 ^= r0;
r0 |= r1;
r2 ^= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r4 ^= r3;
r4 ^= r0;
r3 = ~r3;
r2 &= r4;
r2 ^= r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (56));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (56 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (56 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (56 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 ^= r1;
r1 ^= r3;
r3 = ~r3;
r4 = r1;
r1 &= r0;
r2 ^= r3;
r1 ^= r2;
r2 |= r4;
r4 ^= r3;
r3 &= r1;
r3 ^= r0;
r4 ^= r1;
r4 ^= r2;
r2 ^= r0;
r0 &= r3;
r2 = ~r2;
r0 ^= r4;
r4 |= r3;
r2 ^= r4;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r2;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (60));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (60 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (60 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (60 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r1 ^= r3;
r3 = ~r3;
r2 ^= r3;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r1 ^= r2;
r4 ^= r3;
r0 ^= r4;
r2 &= r4;
r2 ^= r0;
r0 &= r1;
r3 ^= r0;
r4 |= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r2 &= r3;
r0 = ~r0;
r4 ^= r2;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (64));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (64 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (64 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (64 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r0;
r0 |= r3;
r3 ^= r1;
r1 &= r4;
r4 ^= r2;
r2 ^= r3;
r3 &= r0;
r4 |= r1;
r3 ^= r4;
r0 ^= r1;
r4 &= r0;
r1 ^= r3;
r4 ^= r2;
r1 |= r0;
r1 ^= r2;
r0 ^= r3;
r2 = r1;
r1 |= r3;
r1 ^= r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r4;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (68));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (68 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (68 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (68 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r4 = r0;
r0 &= r2;
r0 ^= r3;
r2 ^= r1;
r2 ^= r0;
r3 |= r4;
r3 ^= r1;
r4 ^= r2;
r1 = r3;
r3 |= r4;
r3 ^= r0;
r0 &= r1;
r4 ^= r0;
r1 ^= r3;
r1 ^= r4;
r4 = ~r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (72));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (72 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (72 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (72 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 = ~r0;
r2 = ~r2;
r4 = r0;
r0 &= r1;
r2 ^= r0;
r0 |= r3;
r3 ^= r2;
r1 ^= r0;
r0 ^= r4;
r4 |= r1;
r1 ^= r3;
r2 |= r0;
r2 &= r4;
r0 ^= r1;
r1 &= r2;
r1 ^= r0;
r0 &= r2;
r0 ^= r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (76));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (76 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (76 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (76 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r4 ^= r2;
r1 ^= r0;
r0 |= r3;
r0 ^= r4;
r4 ^= r3;
r3 ^= r2;
r2 |= r1;
r2 ^= r4;
r4 = ~r4;
r4 |= r1;
r1 ^= r3;
r1 ^= r4;
r3 |= r0;
r1 ^= r3;
r4 ^= r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r0;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (80));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (80 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (80 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (80 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r1;
r1 |= r2;
r1 ^= r3;
r4 ^= r2;
r2 ^= r1;
r3 |= r4;
r3 &= r0;
r4 ^= r2;
r3 ^= r1;
r1 |= r4;
r1 ^= r0;
r0 |= r4;
r0 ^= r2;
r1 ^= r4;
r2 ^= r1;
r1 &= r0;
r1 ^= r4;
r2 = ~r2;
r2 |= r0;
r4 ^= r2;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r0;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (84));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (84 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (84 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (84 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r2 = ~r2;
r4 = r3;
r3 &= r0;
r0 ^= r4;
r3 ^= r2;
r2 |= r4;
r1 ^= r3;
r2 ^= r0;
r0 |= r1;
r2 ^= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r4 ^= r3;
r4 ^= r0;
r3 = ~r3;
r2 &= r4;
r2 ^= r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r2;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (88));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (88 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (88 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (88 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r0 ^= r1;
r1 ^= r3;
r3 = ~r3;
r4 = r1;
r1 &= r0;
r2 ^= r3;
r1 ^= r2;
r2 |= r4;
r4 ^= r3;
r3 &= r1;
r3 ^= r0;
r4 ^= r1;
r4 ^= r2;
r2 ^= r0;
r0 &= r3;
r2 = ~r2;
r0 ^= r4;
r4 |= r3;
r2 ^= r4;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r2;
tt = w4 ^ w7 ^ w1 ^ w3 ^ (0x9E3779B9 ^ (92));
w4 = rotateLeft(tt, 11);
tt = w5 ^ w0 ^ w2 ^ w4 ^ (0x9E3779B9 ^ (92 + 1));
w5 = rotateLeft(tt, 11);
tt = w6 ^ w1 ^ w3 ^ w5 ^ (0x9E3779B9 ^ (92 + 2));
w6 = rotateLeft(tt, 11);
tt = w7 ^ w2 ^ w4 ^ w6 ^ (0x9E3779B9 ^ (92 + 3));
w7 = rotateLeft(tt, 11);
r0 = w4;
r1 = w5;
r2 = w6;
r3 = w7;
r1 ^= r3;
r3 = ~r3;
r2 ^= r3;
r3 ^= r0;
r4 = r1;
r1 &= r3;
r1 ^= r2;
r4 ^= r3;
r0 ^= r4;
r2 &= r4;
r2 ^= r0;
r0 &= r1;
r3 ^= r0;
r4 |= r1;
r4 ^= r0;
r0 |= r3;
r0 ^= r2;
r2 &= r3;
r0 = ~r0;
r4 ^= r2;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r4;
serpent24SubKeys[i++] = r0;
serpent24SubKeys[i++] = r3;
tt = w0 ^ w3 ^ w5 ^ w7 ^ (0x9E3779B9 ^ (96));
w0 = rotateLeft(tt, 11);
tt = w1 ^ w4 ^ w6 ^ w0 ^ (0x9E3779B9 ^ (96 + 1));
w1 = rotateLeft(tt, 11);
tt = w2 ^ w5 ^ w7 ^ w1 ^ (0x9E3779B9 ^ (96 + 2));
w2 = rotateLeft(tt, 11);
tt = w3 ^ w6 ^ w0 ^ w2 ^ (0x9E3779B9 ^ (96 + 3));
w3 = rotateLeft(tt, 11);
r0 = w0;
r1 = w1;
r2 = w2;
r3 = w3;
r4 = r0;
r0 |= r3;
r3 ^= r1;
r1 &= r4;
r4 ^= r2;
r2 ^= r3;
r3 &= r0;
r4 |= r1;
r3 ^= r4;
r0 ^= r1;
r4 &= r0;
r1 ^= r3;
r4 ^= r2;
r1 |= r0;
r1 ^= r2;
r0 ^= r3;
r2 = r1;
r1 |= r3;
r1 ^= r0;
serpent24SubKeys[i++] = r1;
serpent24SubKeys[i++] = r2;
serpent24SubKeys[i++] = r3;
serpent24SubKeys[i++] = r4;
}
/**
* Set the IV. The IV length must lie between 0 and 16 (inclusive).
* <code>null</code> is accepted, and yields the same result
* than an IV of length 0.
*
* @param iv the IV (or <code>null</code>)
*/
@SuppressWarnings("checkstyle:MethodLength")
public void setIV(final byte[] iv) {
byte[] myIV = iv;
if (myIV == null) {
myIV = new byte[0];
}
if (myIV.length > 16) {
throw new IllegalArgumentException("bad IV length: " + myIV.length);
}
final byte[] piv;
if (myIV.length == 16) {
piv = myIV;
} else {
piv = new byte[16];
System.arraycopy(myIV, 0, piv, 0, myIV.length);
for (int i = myIV.length; i < piv.length; i++) {
piv[i] = 0x00;
}
}
int r0 = decode32le(piv, 0);
int r1 = decode32le(piv, 4);
int r2 = decode32le(piv, 8);
int r3 = decode32le(piv, 12);
int r4;
r0 ^= serpent24SubKeys[0];
r1 ^= serpent24SubKeys[0 + 1];
r2 ^= serpent24SubKeys[0 + 2];
r3 ^= serpent24SubKeys[0 + 3];
r3 ^= r0;
r4 = r1;
r1 &= r3;
r4 ^= r2;
r1 ^= r0;
r0 |= r3;
r0 ^= r4;
r4 ^= r3;
r3 ^= r2;
r2 |= r1;
r2 ^= r4;
r4 = ~r4;
r4 |= r1;
r1 ^= r3;
r1 ^= r4;
r3 |= r0;
r1 ^= r3;
r4 ^= r3;
r1 = rotateLeft(r1, 13);
r2 = rotateLeft(r2, 3);
r4 = r4 ^ r1 ^ r2;
r0 = r0 ^ r2 ^ (r1 << 3);
r4 = rotateLeft(r4, 1);
r0 = rotateLeft(r0, 7);
r1 = r1 ^ r4 ^ r0;
r2 = r2 ^ r0 ^ (r4 << 7);
r1 = rotateLeft(r1, 5);
r2 = rotateLeft(r2, 22);
r1 ^= serpent24SubKeys[4];
r4 ^= serpent24SubKeys[4 + 1];
r2 ^= serpent24SubKeys[4 + 2];
r0 ^= serpent24SubKeys[4 + 3];
r1 = ~r1;
r2 = ~r2;
r3 = r1;
r1 &= r4;
r2 ^= r1;
r1 |= r0;
r0 ^= r2;
r4 ^= r1;
r1 ^= r3;
r3 |= r4;
r4 ^= r0;
r2 |= r1;
r2 &= r3;
r1 ^= r4;
r4 &= r2;
r4 ^= r1;
r1 &= r2;
r1 ^= r3;
r2 = rotateLeft(r2, 13);
r0 = rotateLeft(r0, 3);
r1 = r1 ^ r2 ^ r0;
r4 = r4 ^ r0 ^ (r2 << 3);
r1 = rotateLeft(r1, 1);
r4 = rotateLeft(r4, 7);
r2 = r2 ^ r1 ^ r4;
r0 = r0 ^ r4 ^ (r1 << 7);
r2 = rotateLeft(r2, 5);
r0 = rotateLeft(r0, 22);
r2 ^= serpent24SubKeys[8];
r1 ^= serpent24SubKeys[8 + 1];
r0 ^= serpent24SubKeys[8 + 2];
r4 ^= serpent24SubKeys[8 + 3];
r3 = r2;
r2 &= r0;
r2 ^= r4;
r0 ^= r1;
r0 ^= r2;
r4 |= r3;
r4 ^= r1;
r3 ^= r0;
r1 = r4;
r4 |= r3;
r4 ^= r2;
r2 &= r1;
r3 ^= r2;
r1 ^= r4;
r1 ^= r3;
r3 = ~r3;
r0 = rotateLeft(r0, 13);
r1 = rotateLeft(r1, 3);
r4 = r4 ^ r0 ^ r1;
r3 = r3 ^ r1 ^ (r0 << 3);
r4 = rotateLeft(r4, 1);
r3 = rotateLeft(r3, 7);
r0 = r0 ^ r4 ^ r3;
r1 = r1 ^ r3 ^ (r4 << 7);
r0 = rotateLeft(r0, 5);
r1 = rotateLeft(r1, 22);
r0 ^= serpent24SubKeys[12];
r4 ^= serpent24SubKeys[12 + 1];
r1 ^= serpent24SubKeys[12 + 2];
r3 ^= serpent24SubKeys[12 + 3];
r2 = r0;
r0 |= r3;
r3 ^= r4;
r4 &= r2;
r2 ^= r1;
r1 ^= r3;
r3 &= r0;
r2 |= r4;
r3 ^= r2;
r0 ^= r4;
r2 &= r0;
r4 ^= r3;
r2 ^= r1;
r4 |= r0;
r4 ^= r1;
r0 ^= r3;
r1 = r4;
r4 |= r3;
r4 ^= r0;
r4 = rotateLeft(r4, 13);
r3 = rotateLeft(r3, 3);
r1 = r1 ^ r4 ^ r3;
r2 = r2 ^ r3 ^ (r4 << 3);
r1 = rotateLeft(r1, 1);
r2 = rotateLeft(r2, 7);
r4 = r4 ^ r1 ^ r2;
r3 = r3 ^ r2 ^ (r1 << 7);
r4 = rotateLeft(r4, 5);
r3 = rotateLeft(r3, 22);
r4 ^= serpent24SubKeys[16];
r1 ^= serpent24SubKeys[16 + 1];
r3 ^= serpent24SubKeys[16 + 2];
r2 ^= serpent24SubKeys[16 + 3];
r1 ^= r2;
r2 = ~r2;
r3 ^= r2;
r2 ^= r4;
r0 = r1;
r1 &= r2;
r1 ^= r3;
r0 ^= r2;
r4 ^= r0;
r3 &= r0;
r3 ^= r4;
r4 &= r1;
r2 ^= r4;
r0 |= r1;
r0 ^= r4;
r4 |= r2;
r4 ^= r3;
r3 &= r2;
r4 = ~r4;
r0 ^= r3;
r1 = rotateLeft(r1, 13);
r4 = rotateLeft(r4, 3);
r0 = r0 ^ r1 ^ r4;
r2 = r2 ^ r4 ^ (r1 << 3);
r0 = rotateLeft(r0, 1);
r2 = rotateLeft(r2, 7);
r1 = r1 ^ r0 ^ r2;
r4 = r4 ^ r2 ^ (r0 << 7);
r1 = rotateLeft(r1, 5);
r4 = rotateLeft(r4, 22);
r1 ^= serpent24SubKeys[20];
r0 ^= serpent24SubKeys[20 + 1];
r4 ^= serpent24SubKeys[20 + 2];
r2 ^= serpent24SubKeys[20 + 3];
r1 ^= r0;
r0 ^= r2;
r2 = ~r2;
r3 = r0;
r0 &= r1;
r4 ^= r2;
r0 ^= r4;
r4 |= r3;
r3 ^= r2;
r2 &= r0;
r2 ^= r1;
r3 ^= r0;
r3 ^= r4;
r4 ^= r1;
r1 &= r2;
r4 = ~r4;
r1 ^= r3;
r3 |= r2;
r4 ^= r3;
r0 = rotateLeft(r0, 13);
r1 = rotateLeft(r1, 3);
r2 = r2 ^ r0 ^ r1;
r4 = r4 ^ r1 ^ (r0 << 3);
r2 = rotateLeft(r2, 1);
r4 = rotateLeft(r4, 7);
r0 = r0 ^ r2 ^ r4;
r1 = r1 ^ r4 ^ (r2 << 7);
r0 = rotateLeft(r0, 5);
r1 = rotateLeft(r1, 22);
r0 ^= serpent24SubKeys[24];
r2 ^= serpent24SubKeys[24 + 1];
r1 ^= serpent24SubKeys[24 + 2];
r4 ^= serpent24SubKeys[24 + 3];
r1 = ~r1;
r3 = r4;
r4 &= r0;
r0 ^= r3;
r4 ^= r1;
r1 |= r3;
r2 ^= r4;
r1 ^= r0;
r0 |= r2;
r1 ^= r2;
r3 ^= r0;
r0 |= r4;
r0 ^= r1;
r3 ^= r4;
r3 ^= r0;
r4 = ~r4;
r1 &= r3;
r1 ^= r4;
r0 = rotateLeft(r0, 13);
r3 = rotateLeft(r3, 3);
r2 = r2 ^ r0 ^ r3;
r1 = r1 ^ r3 ^ (r0 << 3);
r2 = rotateLeft(r2, 1);
r1 = rotateLeft(r1, 7);
r0 = r0 ^ r2 ^ r1;
r3 = r3 ^ r1 ^ (r2 << 7);
r0 = rotateLeft(r0, 5);
r3 = rotateLeft(r3, 22);
r0 ^= serpent24SubKeys[28];
r2 ^= serpent24SubKeys[28 + 1];
r3 ^= serpent24SubKeys[28 + 2];
r1 ^= serpent24SubKeys[28 + 3];
r4 = r2;
r2 |= r3;
r2 ^= r1;
r4 ^= r3;
r3 ^= r2;
r1 |= r4;
r1 &= r0;
r4 ^= r3;
r1 ^= r2;
r2 |= r4;
r2 ^= r0;
r0 |= r4;
r0 ^= r3;
r2 ^= r4;
r3 ^= r2;
r2 &= r0;
r2 ^= r4;
r3 = ~r3;
r3 |= r0;
r4 ^= r3;
r4 = rotateLeft(r4, 13);
r2 = rotateLeft(r2, 3);
r1 = r1 ^ r4 ^ r2;
r0 = r0 ^ r2 ^ (r4 << 3);
r1 = rotateLeft(r1, 1);
r0 = rotateLeft(r0, 7);
r4 = r4 ^ r1 ^ r0;
r2 = r2 ^ r0 ^ (r1 << 7);
r4 = rotateLeft(r4, 5);
r2 = rotateLeft(r2, 22);
r4 ^= serpent24SubKeys[32];
r1 ^= serpent24SubKeys[32 + 1];
r2 ^= serpent24SubKeys[32 + 2];
r0 ^= serpent24SubKeys[32 + 3];
r0 ^= r4;
r3 = r1;
r1 &= r0;
r3 ^= r2;
r1 ^= r4;
r4 |= r0;
r4 ^= r3;
r3 ^= r0;
r0 ^= r2;
r2 |= r1;
r2 ^= r3;
r3 = ~r3;
r3 |= r1;
r1 ^= r0;
r1 ^= r3;
r0 |= r4;
r1 ^= r0;
r3 ^= r0;
r1 = rotateLeft(r1, 13);
r2 = rotateLeft(r2, 3);
r3 = r3 ^ r1 ^ r2;
r4 = r4 ^ r2 ^ (r1 << 3);
r3 = rotateLeft(r3, 1);
r4 = rotateLeft(r4, 7);
r1 = r1 ^ r3 ^ r4;
r2 = r2 ^ r4 ^ (r3 << 7);
r1 = rotateLeft(r1, 5);
r2 = rotateLeft(r2, 22);
r1 ^= serpent24SubKeys[36];
r3 ^= serpent24SubKeys[36 + 1];
r2 ^= serpent24SubKeys[36 + 2];
r4 ^= serpent24SubKeys[36 + 3];
r1 = ~r1;
r2 = ~r2;
r0 = r1;
r1 &= r3;
r2 ^= r1;
r1 |= r4;
r4 ^= r2;
r3 ^= r1;
r1 ^= r0;
r0 |= r3;
r3 ^= r4;
r2 |= r1;
r2 &= r0;
r1 ^= r3;
r3 &= r2;
r3 ^= r1;
r1 &= r2;
r1 ^= r0;
r2 = rotateLeft(r2, 13);
r4 = rotateLeft(r4, 3);
r1 = r1 ^ r2 ^ r4;
r3 = r3 ^ r4 ^ (r2 << 3);
r1 = rotateLeft(r1, 1);
r3 = rotateLeft(r3, 7);
r2 = r2 ^ r1 ^ r3;
r4 = r4 ^ r3 ^ (r1 << 7);
r2 = rotateLeft(r2, 5);
r4 = rotateLeft(r4, 22);
r2 ^= serpent24SubKeys[40];
r1 ^= serpent24SubKeys[40 + 1];
r4 ^= serpent24SubKeys[40 + 2];
r3 ^= serpent24SubKeys[40 + 3];
r0 = r2;
r2 &= r4;
r2 ^= r3;
r4 ^= r1;
r4 ^= r2;
r3 |= r0;
r3 ^= r1;
r0 ^= r4;
r1 = r3;
r3 |= r0;
r3 ^= r2;
r2 &= r1;
r0 ^= r2;
r1 ^= r3;
r1 ^= r0;
r0 = ~r0;
r4 = rotateLeft(r4, 13);
r1 = rotateLeft(r1, 3);
r3 = r3 ^ r4 ^ r1;
r0 = r0 ^ r1 ^ (r4 << 3);
r3 = rotateLeft(r3, 1);
r0 = rotateLeft(r0, 7);
r4 = r4 ^ r3 ^ r0;
r1 = r1 ^ r0 ^ (r3 << 7);
r4 = rotateLeft(r4, 5);
r1 = rotateLeft(r1, 22);
r4 ^= serpent24SubKeys[44];
r3 ^= serpent24SubKeys[44 + 1];
r1 ^= serpent24SubKeys[44 + 2];
r0 ^= serpent24SubKeys[44 + 3];
r2 = r4;
r4 |= r0;
r0 ^= r3;
r3 &= r2;
r2 ^= r1;
r1 ^= r0;
r0 &= r4;
r2 |= r3;
r0 ^= r2;
r4 ^= r3;
r2 &= r4;
r3 ^= r0;
r2 ^= r1;
r3 |= r4;
r3 ^= r1;
r4 ^= r0;
r1 = r3;
r3 |= r0;
r3 ^= r4;
r3 = rotateLeft(r3, 13);
r0 = rotateLeft(r0, 3);
r1 = r1 ^ r3 ^ r0;
r2 = r2 ^ r0 ^ (r3 << 3);
r1 = rotateLeft(r1, 1);
r2 = rotateLeft(r2, 7);
r3 = r3 ^ r1 ^ r2;
r0 = r0 ^ r2 ^ (r1 << 7);
r3 = rotateLeft(r3, 5);
r0 = rotateLeft(r0, 22);
lfsr9 = r3;
lfsr8 = r1;
lfsr7 = r0;
lfsr6 = r2;
r3 ^= serpent24SubKeys[48];
r1 ^= serpent24SubKeys[48 + 1];
r0 ^= serpent24SubKeys[48 + 2];
r2 ^= serpent24SubKeys[48 + 3];
r1 ^= r2;
r2 = ~r2;
r0 ^= r2;
r2 ^= r3;
r4 = r1;
r1 &= r2;
r1 ^= r0;
r4 ^= r2;
r3 ^= r4;
r0 &= r4;
r0 ^= r3;
r3 &= r1;
r2 ^= r3;
r4 |= r1;
r4 ^= r3;
r3 |= r2;
r3 ^= r0;
r0 &= r2;
r3 = ~r3;
r4 ^= r0;
r1 = rotateLeft(r1, 13);
r3 = rotateLeft(r3, 3);
r4 = r4 ^ r1 ^ r3;
r2 = r2 ^ r3 ^ (r1 << 3);
r4 = rotateLeft(r4, 1);
r2 = rotateLeft(r2, 7);
r1 = r1 ^ r4 ^ r2;
r3 = r3 ^ r2 ^ (r4 << 7);
r1 = rotateLeft(r1, 5);
r3 = rotateLeft(r3, 22);
r1 ^= serpent24SubKeys[52];
r4 ^= serpent24SubKeys[52 + 1];
r3 ^= serpent24SubKeys[52 + 2];
r2 ^= serpent24SubKeys[52 + 3];
r1 ^= r4;
r4 ^= r2;
r2 = ~r2;
r0 = r4;
r4 &= r1;
r3 ^= r2;
r4 ^= r3;
r3 |= r0;
r0 ^= r2;
r2 &= r4;
r2 ^= r1;
r0 ^= r4;
r0 ^= r3;
r3 ^= r1;
r1 &= r2;
r3 = ~r3;
r1 ^= r0;
r0 |= r2;
r3 ^= r0;
r4 = rotateLeft(r4, 13);
r1 = rotateLeft(r1, 3);
r2 = r2 ^ r4 ^ r1;
r3 = r3 ^ r1 ^ (r4 << 3);
r2 = rotateLeft(r2, 1);
r3 = rotateLeft(r3, 7);
r4 = r4 ^ r2 ^ r3;
r1 = r1 ^ r3 ^ (r2 << 7);
r4 = rotateLeft(r4, 5);
r1 = rotateLeft(r1, 22);
r4 ^= serpent24SubKeys[56];
r2 ^= serpent24SubKeys[56 + 1];
r1 ^= serpent24SubKeys[56 + 2];
r3 ^= serpent24SubKeys[56 + 3];
r1 = ~r1;
r0 = r3;
r3 &= r4;
r4 ^= r0;
r3 ^= r1;
r1 |= r0;
r2 ^= r3;
r1 ^= r4;
r4 |= r2;
r1 ^= r2;
r0 ^= r4;
r4 |= r3;
r4 ^= r1;
r0 ^= r3;
r0 ^= r4;
r3 = ~r3;
r1 &= r0;
r1 ^= r3;
r4 = rotateLeft(r4, 13);
r0 = rotateLeft(r0, 3);
r2 = r2 ^ r4 ^ r0;
r1 = r1 ^ r0 ^ (r4 << 3);
r2 = rotateLeft(r2, 1);
r1 = rotateLeft(r1, 7);
r4 = r4 ^ r2 ^ r1;
r0 = r0 ^ r1 ^ (r2 << 7);
r4 = rotateLeft(r4, 5);
r0 = rotateLeft(r0, 22);
r4 ^= serpent24SubKeys[60];
r2 ^= serpent24SubKeys[60 + 1];
r0 ^= serpent24SubKeys[60 + 2];
r1 ^= serpent24SubKeys[60 + 3];
r3 = r2;
r2 |= r0;
r2 ^= r1;
r3 ^= r0;
r0 ^= r2;
r1 |= r3;
r1 &= r4;
r3 ^= r0;
r1 ^= r2;
r2 |= r3;
r2 ^= r4;
r4 |= r3;
r4 ^= r0;
r2 ^= r3;
r0 ^= r2;
r2 &= r4;
r2 ^= r3;
r0 = ~r0;
r0 |= r4;
r3 ^= r0;
r3 = rotateLeft(r3, 13);
r2 = rotateLeft(r2, 3);
r1 = r1 ^ r3 ^ r2;
r4 = r4 ^ r2 ^ (r3 << 3);
r1 = rotateLeft(r1, 1);
r4 = rotateLeft(r4, 7);
r3 = r3 ^ r1 ^ r4;
r2 = r2 ^ r4 ^ (r1 << 7);
r3 = rotateLeft(r3, 5);
r2 = rotateLeft(r2, 22);
r3 ^= serpent24SubKeys[64];
r1 ^= serpent24SubKeys[64 + 1];
r2 ^= serpent24SubKeys[64 + 2];
r4 ^= serpent24SubKeys[64 + 3];
r4 ^= r3;
r0 = r1;
r1 &= r4;
r0 ^= r2;
r1 ^= r3;
r3 |= r4;
r3 ^= r0;
r0 ^= r4;
r4 ^= r2;
r2 |= r1;
r2 ^= r0;
r0 = ~r0;
r0 |= r1;
r1 ^= r4;
r1 ^= r0;
r4 |= r3;
r1 ^= r4;
r0 ^= r4;
r1 = rotateLeft(r1, 13);
r2 = rotateLeft(r2, 3);
r0 = r0 ^ r1 ^ r2;
r3 = r3 ^ r2 ^ (r1 << 3);
r0 = rotateLeft(r0, 1);
r3 = rotateLeft(r3, 7);
r1 = r1 ^ r0 ^ r3;
r2 = r2 ^ r3 ^ (r0 << 7);
r1 = rotateLeft(r1, 5);
r2 = rotateLeft(r2, 22);
r1 ^= serpent24SubKeys[68];
r0 ^= serpent24SubKeys[68 + 1];
r2 ^= serpent24SubKeys[68 + 2];
r3 ^= serpent24SubKeys[68 + 3];
r1 = ~r1;
r2 = ~r2;
r4 = r1;
r1 &= r0;
r2 ^= r1;
r1 |= r3;
r3 ^= r2;
r0 ^= r1;
r1 ^= r4;
r4 |= r0;
r0 ^= r3;
r2 |= r1;
r2 &= r4;
r1 ^= r0;
r0 &= r2;
r0 ^= r1;
r1 &= r2;
r1 ^= r4;
r2 = rotateLeft(r2, 13);
r3 = rotateLeft(r3, 3);
r1 = r1 ^ r2 ^ r3;
r0 = r0 ^ r3 ^ (r2 << 3);
r1 = rotateLeft(r1, 1);
r0 = rotateLeft(r0, 7);
r2 = r2 ^ r1 ^ r0;
r3 = r3 ^ r0 ^ (r1 << 7);
r2 = rotateLeft(r2, 5);
r3 = rotateLeft(r3, 22);
fsmR1 = r2;
lfsr4 = r1;
fsmR2 = r3;
lfsr5 = r0;
r2 ^= serpent24SubKeys[72];
r1 ^= serpent24SubKeys[72 + 1];
r3 ^= serpent24SubKeys[72 + 2];
r0 ^= serpent24SubKeys[72 + 3];
r4 = r2;
r2 &= r3;
r2 ^= r0;
r3 ^= r1;
r3 ^= r2;
r0 |= r4;
r0 ^= r1;
r4 ^= r3;
r1 = r0;
r0 |= r4;
r0 ^= r2;
r2 &= r1;
r4 ^= r2;
r1 ^= r0;
r1 ^= r4;
r4 = ~r4;
r3 = rotateLeft(r3, 13);
r1 = rotateLeft(r1, 3);
r0 = r0 ^ r3 ^ r1;
r4 = r4 ^ r1 ^ (r3 << 3);
r0 = rotateLeft(r0, 1);
r4 = rotateLeft(r4, 7);
r3 = r3 ^ r0 ^ r4;
r1 = r1 ^ r4 ^ (r0 << 7);
r3 = rotateLeft(r3, 5);
r1 = rotateLeft(r1, 22);
r3 ^= serpent24SubKeys[76];
r0 ^= serpent24SubKeys[76 + 1];
r1 ^= serpent24SubKeys[76 + 2];
r4 ^= serpent24SubKeys[76 + 3];
r2 = r3;
r3 |= r4;
r4 ^= r0;
r0 &= r2;
r2 ^= r1;
r1 ^= r4;
r4 &= r3;
r2 |= r0;
r4 ^= r2;
r3 ^= r0;
r2 &= r3;
r0 ^= r4;
r2 ^= r1;
r0 |= r3;
r0 ^= r1;
r3 ^= r4;
r1 = r0;
r0 |= r4;
r0 ^= r3;
r0 = rotateLeft(r0, 13);
r4 = rotateLeft(r4, 3);
r1 = r1 ^ r0 ^ r4;
r2 = r2 ^ r4 ^ (r0 << 3);
r1 = rotateLeft(r1, 1);
r2 = rotateLeft(r2, 7);
r0 = r0 ^ r1 ^ r2;
r4 = r4 ^ r2 ^ (r1 << 7);
r0 = rotateLeft(r0, 5);
r4 = rotateLeft(r4, 22);
r0 ^= serpent24SubKeys[80];
r1 ^= serpent24SubKeys[80 + 1];
r4 ^= serpent24SubKeys[80 + 2];
r2 ^= serpent24SubKeys[80 + 3];
r1 ^= r2;
r2 = ~r2;
r4 ^= r2;
r2 ^= r0;
r3 = r1;
r1 &= r2;
r1 ^= r4;
r3 ^= r2;
r0 ^= r3;
r4 &= r3;
r4 ^= r0;
r0 &= r1;
r2 ^= r0;
r3 |= r1;
r3 ^= r0;
r0 |= r2;
r0 ^= r4;
r4 &= r2;
r0 = ~r0;
r3 ^= r4;
r1 = rotateLeft(r1, 13);
r0 = rotateLeft(r0, 3);
r3 = r3 ^ r1 ^ r0;
r2 = r2 ^ r0 ^ (r1 << 3);
r3 = rotateLeft(r3, 1);
r2 = rotateLeft(r2, 7);
r1 = r1 ^ r3 ^ r2;
r0 = r0 ^ r2 ^ (r3 << 7);
r1 = rotateLeft(r1, 5);
r0 = rotateLeft(r0, 22);
r1 ^= serpent24SubKeys[84];
r3 ^= serpent24SubKeys[84 + 1];
r0 ^= serpent24SubKeys[84 + 2];
r2 ^= serpent24SubKeys[84 + 3];
r1 ^= r3;
r3 ^= r2;
r2 = ~r2;
r4 = r3;
r3 &= r1;
r0 ^= r2;
r3 ^= r0;
r0 |= r4;
r4 ^= r2;
r2 &= r3;
r2 ^= r1;
r4 ^= r3;
r4 ^= r0;
r0 ^= r1;
r1 &= r2;
r0 = ~r0;
r1 ^= r4;
r4 |= r2;
r0 ^= r4;
r3 = rotateLeft(r3, 13);
r1 = rotateLeft(r1, 3);
r2 = r2 ^ r3 ^ r1;
r0 = r0 ^ r1 ^ (r3 << 3);
r2 = rotateLeft(r2, 1);
r0 = rotateLeft(r0, 7);
r3 = r3 ^ r2 ^ r0;
r1 = r1 ^ r0 ^ (r2 << 7);
r3 = rotateLeft(r3, 5);
r1 = rotateLeft(r1, 22);
r3 ^= serpent24SubKeys[88];
r2 ^= serpent24SubKeys[88 + 1];
r1 ^= serpent24SubKeys[88 + 2];
r0 ^= serpent24SubKeys[88 + 3];
r1 = ~r1;
r4 = r0;
r0 &= r3;
r3 ^= r4;
r0 ^= r1;
r1 |= r4;
r2 ^= r0;
r1 ^= r3;
r3 |= r2;
r1 ^= r2;
r4 ^= r3;
r3 |= r0;
r3 ^= r1;
r4 ^= r0;
r4 ^= r3;
r0 = ~r0;
r1 &= r4;
r1 ^= r0;
r3 = rotateLeft(r3, 13);
r4 = rotateLeft(r4, 3);
r2 = r2 ^ r3 ^ r4;
r1 = r1 ^ r4 ^ (r3 << 3);
r2 = rotateLeft(r2, 1);
r1 = rotateLeft(r1, 7);
r3 = r3 ^ r2 ^ r1;
r4 = r4 ^ r1 ^ (r2 << 7);
r3 = rotateLeft(r3, 5);
r4 = rotateLeft(r4, 22);
r3 ^= serpent24SubKeys[92];
r2 ^= serpent24SubKeys[92 + 1];
r4 ^= serpent24SubKeys[92 + 2];
r1 ^= serpent24SubKeys[92 + 3];
r0 = r2;
r2 |= r4;
r2 ^= r1;
r0 ^= r4;
r4 ^= r2;
r1 |= r0;
r1 &= r3;
r0 ^= r4;
r1 ^= r2;
r2 |= r0;
r2 ^= r3;
r3 |= r0;
r3 ^= r4;
r2 ^= r0;
r4 ^= r2;
r2 &= r3;
r2 ^= r0;
r4 = ~r4;
r4 |= r3;
r0 ^= r4;
r0 = rotateLeft(r0, 13);
r2 = rotateLeft(r2, 3);
r1 = r1 ^ r0 ^ r2;
r3 = r3 ^ r2 ^ (r0 << 3);
r1 = rotateLeft(r1, 1);
r3 = rotateLeft(r3, 7);
r0 = r0 ^ r1 ^ r3;
r2 = r2 ^ r3 ^ (r1 << 7);
r0 = rotateLeft(r0, 5);
r2 = rotateLeft(r2, 22);
r0 ^= serpent24SubKeys[96];
r1 ^= serpent24SubKeys[96 + 1];
r2 ^= serpent24SubKeys[96 + 2];
r3 ^= serpent24SubKeys[96 + 3];
lfsr3 = r0;
lfsr2 = r1;
lfsr1 = r2;
lfsr0 = r3;
}
/**
* mulAlpha[] is used to multiply a word by alpha; mulAlpha[x]
* is equal to x * alpha^4.
*/
private static final int[] MUL_ALPHA = new int[256];
/**
* divAlpha[] is used to divide a word by alpha; divAlpha[x]
* is equal to x / alpha.
*/
private static final int[] DIV_ALPHA = new int[256];
static {
/*
* We first build exponential and logarithm tables
* relatively to beta in F_{2^8}. We set log(0x00) = 0xFF
* conventionaly, but this is actually not used in our
* computations.
*/
final int[] expb = new int[256];
for (int i = 0, x = 0x01; i < 0xFF; i++) {
expb[i] = x;
x <<= 1;
if (x > 0xFF) {
x ^= 0x1A9;
}
}
expb[0xFF] = 0x00;
final int[] logb = new int[256];
for (int i = 0; i < 0x100; i++) {
logb[expb[i]] = i;
}
/*
* We now compute mulAlpha[] and divAlpha[]. For all
* x != 0, we work with invertible numbers, which are
* as such powers of beta. Multiplication (in F_{2^8})
* is then implemented as integer addition modulo 255,
* over the exponents computed by the logb[] table.
*
* We have the following equations:
* alpha^4 = beta^23 * alpha^3 + beta^245 * alpha^2
* + beta^48 * alpha + beta^239
* 1/alpha = beta^16 * alpha^3 + beta^39 * alpha^2
* + beta^6 * alpha + beta^64
*/
MUL_ALPHA[0x00] = 0x00000000;
DIV_ALPHA[0x00] = 0x00000000;
for (int x = 1; x < 0x100; x++) {
final int ex = logb[x];
MUL_ALPHA[x] = (expb[(ex + 23) % 255] << 24)
| (expb[(ex + 245) % 255] << 16)
| (expb[(ex + 48) % 255] << 8)
| expb[(ex + 239) % 255];
DIV_ALPHA[x] = (expb[(ex + 16) % 255] << 24)
| (expb[(ex + 39) % 255] << 16)
| (expb[(ex + 6) % 255] << 8)
| expb[(ex + 64) % 255];
}
}
/**
* Produce 80 bytes of output stream into the provided buffer.
*
* @param buf the output buffer
* @param off the output offset
*/
@SuppressWarnings("checkstyle:MethodLength")
private void makeStreamBlock(final byte[] buf, final int off) {
int s0 = lfsr0;
int s1 = lfsr1;
int s2 = lfsr2;
int s3 = lfsr3;
int s4 = lfsr4;
int s5 = lfsr5;
int s6 = lfsr6;
int s7 = lfsr7;
int s8 = lfsr8;
int s9 = lfsr9;
int r1 = fsmR1;
int r2 = fsmR2;
int tt = r1;
r1 = r2 + (s1 ^ ((r1 & 0x01) != 0 ? s8 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
int v0 = s0;
s0 = ((s0 << 8) ^ MUL_ALPHA[s0 >>> 24])
^ ((s3 >>> 8) ^ DIV_ALPHA[s3 & 0xFF]) ^ s9;
int f0 = (s9 + r1) ^ r2;
tt = r1;
r1 = r2 + (s2 ^ ((r1 & 0x01) != 0 ? s9 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
int v1 = s1;
s1 = ((s1 << 8) ^ MUL_ALPHA[s1 >>> 24])
^ ((s4 >>> 8) ^ DIV_ALPHA[s4 & 0xFF]) ^ s0;
int f1 = (s0 + r1) ^ r2;
tt = r1;
r1 = r2 + (s3 ^ ((r1 & 0x01) != 0 ? s0 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
int v2 = s2;
s2 = ((s2 << 8) ^ MUL_ALPHA[s2 >>> 24])
^ ((s5 >>> 8) ^ DIV_ALPHA[s5 & 0xFF]) ^ s1;
int f2 = (s1 + r1) ^ r2;
tt = r1;
r1 = r2 + (s4 ^ ((r1 & 0x01) != 0 ? s1 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
int v3 = s3;
s3 = ((s3 << 8) ^ MUL_ALPHA[s3 >>> 24])
^ ((s6 >>> 8) ^ DIV_ALPHA[s6 & 0xFF]) ^ s2;
int f3 = (s2 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
int f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
encode32le(f2 ^ v0, buf, off);
encode32le(f3 ^ v1, buf, off + 4);
encode32le(f1 ^ v2, buf, off + 8);
encode32le(f4 ^ v3, buf, off + 12);
tt = r1;
r1 = r2 + (s5 ^ ((r1 & 0x01) != 0 ? s2 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v0 = s4;
s4 = ((s4 << 8) ^ MUL_ALPHA[s4 >>> 24])
^ ((s7 >>> 8) ^ DIV_ALPHA[s7 & 0xFF]) ^ s3;
f0 = (s3 + r1) ^ r2;
tt = r1;
r1 = r2 + (s6 ^ ((r1 & 0x01) != 0 ? s3 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v1 = s5;
s5 = ((s5 << 8) ^ MUL_ALPHA[s5 >>> 24])
^ ((s8 >>> 8) ^ DIV_ALPHA[s8 & 0xFF]) ^ s4;
f1 = (s4 + r1) ^ r2;
tt = r1;
r1 = r2 + (s7 ^ ((r1 & 0x01) != 0 ? s4 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v2 = s6;
s6 = ((s6 << 8) ^ MUL_ALPHA[s6 >>> 24])
^ ((s9 >>> 8) ^ DIV_ALPHA[s9 & 0xFF]) ^ s5;
f2 = (s5 + r1) ^ r2;
tt = r1;
r1 = r2 + (s8 ^ ((r1 & 0x01) != 0 ? s5 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v3 = s7;
s7 = ((s7 << 8) ^ MUL_ALPHA[s7 >>> 24])
^ ((s0 >>> 8) ^ DIV_ALPHA[s0 & 0xFF]) ^ s6;
f3 = (s6 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
encode32le(f2 ^ v0, buf, off + 16);
encode32le(f3 ^ v1, buf, off + 20);
encode32le(f1 ^ v2, buf, off + 24);
encode32le(f4 ^ v3, buf, off + 28);
tt = r1;
r1 = r2 + (s9 ^ ((r1 & 0x01) != 0 ? s6 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v0 = s8;
s8 = ((s8 << 8) ^ MUL_ALPHA[s8 >>> 24])
^ ((s1 >>> 8) ^ DIV_ALPHA[s1 & 0xFF]) ^ s7;
f0 = (s7 + r1) ^ r2;
tt = r1;
r1 = r2 + (s0 ^ ((r1 & 0x01) != 0 ? s7 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v1 = s9;
s9 = ((s9 << 8) ^ MUL_ALPHA[s9 >>> 24])
^ ((s2 >>> 8) ^ DIV_ALPHA[s2 & 0xFF]) ^ s8;
f1 = (s8 + r1) ^ r2;
tt = r1;
r1 = r2 + (s1 ^ ((r1 & 0x01) != 0 ? s8 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v2 = s0;
s0 = ((s0 << 8) ^ MUL_ALPHA[s0 >>> 24])
^ ((s3 >>> 8) ^ DIV_ALPHA[s3 & 0xFF]) ^ s9;
f2 = (s9 + r1) ^ r2;
tt = r1;
r1 = r2 + (s2 ^ ((r1 & 0x01) != 0 ? s9 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v3 = s1;
s1 = ((s1 << 8) ^ MUL_ALPHA[s1 >>> 24])
^ ((s4 >>> 8) ^ DIV_ALPHA[s4 & 0xFF]) ^ s0;
f3 = (s0 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
encode32le(f2 ^ v0, buf, off + 32);
encode32le(f3 ^ v1, buf, off + 36);
encode32le(f1 ^ v2, buf, off + 40);
encode32le(f4 ^ v3, buf, off + 44);
tt = r1;
r1 = r2 + (s3 ^ ((r1 & 0x01) != 0 ? s0 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v0 = s2;
s2 = ((s2 << 8) ^ MUL_ALPHA[s2 >>> 24])
^ ((s5 >>> 8) ^ DIV_ALPHA[s5 & 0xFF]) ^ s1;
f0 = (s1 + r1) ^ r2;
tt = r1;
r1 = r2 + (s4 ^ ((r1 & 0x01) != 0 ? s1 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v1 = s3;
s3 = ((s3 << 8) ^ MUL_ALPHA[s3 >>> 24])
^ ((s6 >>> 8) ^ DIV_ALPHA[s6 & 0xFF]) ^ s2;
f1 = (s2 + r1) ^ r2;
tt = r1;
r1 = r2 + (s5 ^ ((r1 & 0x01) != 0 ? s2 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v2 = s4;
s4 = ((s4 << 8) ^ MUL_ALPHA[s4 >>> 24])
^ ((s7 >>> 8) ^ DIV_ALPHA[s7 & 0xFF]) ^ s3;
f2 = (s3 + r1) ^ r2;
tt = r1;
r1 = r2 + (s6 ^ ((r1 & 0x01) != 0 ? s3 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v3 = s5;
s5 = ((s5 << 8) ^ MUL_ALPHA[s5 >>> 24])
^ ((s8 >>> 8) ^ DIV_ALPHA[s8 & 0xFF]) ^ s4;
f3 = (s4 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
encode32le(f2 ^ v0, buf, off + 48);
encode32le(f3 ^ v1, buf, off + 52);
encode32le(f1 ^ v2, buf, off + 56);
encode32le(f4 ^ v3, buf, off + 60);
tt = r1;
r1 = r2 + (s7 ^ ((r1 & 0x01) != 0 ? s4 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v0 = s6;
s6 = ((s6 << 8) ^ MUL_ALPHA[s6 >>> 24])
^ ((s9 >>> 8) ^ DIV_ALPHA[s9 & 0xFF]) ^ s5;
f0 = (s5 + r1) ^ r2;
tt = r1;
r1 = r2 + (s8 ^ ((r1 & 0x01) != 0 ? s5 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v1 = s7;
s7 = ((s7 << 8) ^ MUL_ALPHA[s7 >>> 24])
^ ((s0 >>> 8) ^ DIV_ALPHA[s0 & 0xFF]) ^ s6;
f1 = (s6 + r1) ^ r2;
tt = r1;
r1 = r2 + (s9 ^ ((r1 & 0x01) != 0 ? s6 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v2 = s8;
s8 = ((s8 << 8) ^ MUL_ALPHA[s8 >>> 24])
^ ((s1 >>> 8) ^ DIV_ALPHA[s1 & 0xFF]) ^ s7;
f2 = (s7 + r1) ^ r2;
tt = r1;
r1 = r2 + (s0 ^ ((r1 & 0x01) != 0 ? s7 : 0));
r2 = rotateLeft(tt * 0x54655307, 7);
v3 = s9;
s9 = ((s9 << 8) ^ MUL_ALPHA[s9 >>> 24])
^ ((s2 >>> 8) ^ DIV_ALPHA[s2 & 0xFF]) ^ s8;
f3 = (s8 + r1) ^ r2;
/*
* Apply the third S-box (number 2) on (f3, f2, f1, f0).
*/
f4 = f0;
f0 &= f2;
f0 ^= f3;
f2 ^= f1;
f2 ^= f0;
f3 |= f4;
f3 ^= f1;
f4 ^= f2;
f1 = f3;
f3 |= f4;
f3 ^= f0;
f0 &= f1;
f4 ^= f0;
f1 ^= f3;
f1 ^= f4;
f4 = ~f4;
/*
* S-box result is in (f2, f3, f1, f4).
*/
encode32le(f2 ^ v0, buf, off + 64);
encode32le(f3 ^ v1, buf, off + 68);
encode32le(f1 ^ v2, buf, off + 72);
encode32le(f4 ^ v3, buf, off + 76);
lfsr0 = s0;
lfsr1 = s1;
lfsr2 = s2;
lfsr3 = s3;
lfsr4 = s4;
lfsr5 = s5;
lfsr6 = s6;
lfsr7 = s7;
lfsr8 = s8;
lfsr9 = s9;
fsmR1 = r1;
fsmR2 = r2;
}
}