1c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrompackage org.bouncycastle.crypto.modes; 2c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 3c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.BlockCipher; 4c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.CipherParameters; 5c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.DataLengthException; 6c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.InvalidCipherTextException; 770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.crypto.modes.gcm.GCMExponentiator; 8c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.modes.gcm.GCMMultiplier; 970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.crypto.modes.gcm.Tables1kGCMExponentiator; 10c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.modes.gcm.Tables8kGCMMultiplier; 11c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.params.AEADParameters; 12c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.params.KeyParameter; 13c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.params.ParametersWithIV; 14c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.crypto.util.Pack; 15c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.Arrays; 16c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 17c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom/** 18c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * Implements the Galois/Counter mode (GCM) detailed in 19c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom * NIST Special Publication 800-38D. 20c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom */ 21c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrompublic class GCMBlockCipher 22c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom implements AEADBlockCipher 23c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom{ 24c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private static final int BLOCK_SIZE = 16; 25c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 26c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // not final due to a compiler bug 27c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private BlockCipher cipher; 28c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private GCMMultiplier multiplier; 2970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private GCMExponentiator exp; 30c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 31c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // These fields are set by init and not modified by processing 32c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private boolean forEncryption; 33c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private int macSize; 34c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private byte[] nonce; 3570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private byte[] initialAssociatedText; 36c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private byte[] H; 37c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private byte[] J0; 38c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 39c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // These fields are modified during processing 40c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private byte[] bufBlock; 41c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private byte[] macBlock; 4270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private byte[] S, S_at, S_atPre; 43c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private byte[] counter; 44c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private int bufOff; 45c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private long totalLength; 4670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private byte[] atBlock; 4770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private int atBlockPos; 4870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private long atLength; 4970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private long atLengthPre; 50c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 51c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public GCMBlockCipher(BlockCipher c) 52c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 53c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this(c, null); 54c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 55c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 56c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public GCMBlockCipher(BlockCipher c, GCMMultiplier m) 57c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 58c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (c.getBlockSize() != BLOCK_SIZE) 59c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 60c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new IllegalArgumentException( 61c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom "cipher required with a block size of " + BLOCK_SIZE + "."); 62c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 63c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 64c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (m == null) 65c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 66c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // TODO Consider a static property specifying default multiplier 67c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom m = new Tables8kGCMMultiplier(); 68c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 69c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 70c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.cipher = c; 71c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.multiplier = m; 72c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 73c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 74c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public BlockCipher getUnderlyingCipher() 75c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 76c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return cipher; 77c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 78c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 79c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public String getAlgorithmName() 80c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 81c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return cipher.getAlgorithmName() + "/GCM"; 82c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 83c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 84c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public void init(boolean forEncryption, CipherParameters params) 85c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throws IllegalArgumentException 86c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 87c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.forEncryption = forEncryption; 88c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.macBlock = null; 89c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 9070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom KeyParameter keyParam; 914c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 92c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (params instanceof AEADParameters) 93c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 94c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom AEADParameters param = (AEADParameters)params; 95c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 96c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom nonce = param.getNonce(); 9770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom initialAssociatedText = param.getAssociatedText(); 98c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 99c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int macSizeBits = param.getMacSize(); 100c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (macSizeBits < 96 || macSizeBits > 128 || macSizeBits % 8 != 0) 101c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 102c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new IllegalArgumentException("Invalid value for MAC size: " + macSizeBits); 103c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 104c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 105c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom macSize = macSizeBits / 8; 106c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom keyParam = param.getKey(); 107c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 108c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom else if (params instanceof ParametersWithIV) 109c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 110c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom ParametersWithIV param = (ParametersWithIV)params; 111c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 112c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom nonce = param.getIV(); 11370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom initialAssociatedText = null; 114c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom macSize = 16; 115c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom keyParam = (KeyParameter)param.getParameters(); 116c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 117c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom else 118c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 119c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new IllegalArgumentException("invalid parameters passed to GCM"); 120c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 121c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 122c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int bufLength = forEncryption ? BLOCK_SIZE : (BLOCK_SIZE + macSize); 123c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.bufBlock = new byte[bufLength]; 124c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 125c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (nonce == null || nonce.length < 1) 126c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 127c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new IllegalArgumentException("IV must be at least 1 byte"); 128c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 129c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 13070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // TODO This should be configurable by init parameters 13170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // (but must be 16 if nonce length not 12) (BLOCK_SIZE?) 13270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom// this.tagLength = 16; 133c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 134c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // Cipher always used in forward mode 1354c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // if keyParam is null we're reusing the last key. 1364c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (keyParam != null) 1374c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1384c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom cipher.init(true, keyParam); 139c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 14070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.H = new byte[BLOCK_SIZE]; 14170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom cipher.processBlock(H, 0, H, 0); 142c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 14370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // GCMMultiplier tables don't change unless the key changes (and are expensive to init) 14470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom multiplier.init(H); 14570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom exp = null; 14670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 147c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 14870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.J0 = new byte[BLOCK_SIZE]; 149c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 150c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (nonce.length == 12) 151c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 152c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom System.arraycopy(nonce, 0, J0, 0, nonce.length); 15370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.J0[BLOCK_SIZE - 1] = 0x01; 154c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 155c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom else 156c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 15770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASH(J0, nonce, nonce.length); 15870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom byte[] X = new byte[BLOCK_SIZE]; 15970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom Pack.longToBigEndian((long)nonce.length * 8, X, 8); 16070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHBlock(J0, X); 161c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 162c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 16370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.S = new byte[BLOCK_SIZE]; 16470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.S_at = new byte[BLOCK_SIZE]; 16570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.S_atPre = new byte[BLOCK_SIZE]; 16670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.atBlock = new byte[BLOCK_SIZE]; 16770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.atBlockPos = 0; 16870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.atLength = 0; 16970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom this.atLengthPre = 0; 170c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.counter = Arrays.clone(J0); 171c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.bufOff = 0; 172c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.totalLength = 0; 17370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 17470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (initialAssociatedText != null) 17570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 17670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom processAADBytes(initialAssociatedText, 0, initialAssociatedText.length); 17770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 178c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 179c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 180c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public byte[] getMac() 181c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 182c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return Arrays.clone(macBlock); 183c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 184c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 185c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public int getOutputSize(int len) 186c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 18770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom int totalData = len + bufOff; 18870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 189c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (forEncryption) 190c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 19170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return totalData + macSize; 192c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 193c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 19470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return totalData < macSize ? 0 : totalData - macSize; 195c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 196c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 197c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public int getUpdateOutputSize(int len) 198c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 19970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom int totalData = len + bufOff; 20070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (!forEncryption) 20170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 20270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (totalData < macSize) 20370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 20470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return 0; 20570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 20670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom totalData -= macSize; 20770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 20870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return totalData - totalData % BLOCK_SIZE; 20970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 21070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 21170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom public void processAADByte(byte in) 21270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 21370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atBlock[atBlockPos] = in; 21470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (++atBlockPos == BLOCK_SIZE) 21570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 21670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Hash each block as it fills 21770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHBlock(S_at, atBlock); 21870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atBlockPos = 0; 21970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atLength += BLOCK_SIZE; 22070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 22170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 22270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 22370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom public void processAADBytes(byte[] in, int inOff, int len) 22470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 22570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom for (int i = 0; i < len; ++i) 22670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 22770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atBlock[atBlockPos] = in[inOff + i]; 22870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (++atBlockPos == BLOCK_SIZE) 22970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 23070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Hash each block as it fills 23170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHBlock(S_at, atBlock); 23270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atBlockPos = 0; 23370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atLength += BLOCK_SIZE; 23470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 23570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 23670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 23770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 23870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private void initCipher() 23970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 24070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (atLength > 0) 24170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 24270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom System.arraycopy(S_at, 0, S_atPre, 0, BLOCK_SIZE); 24370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atLengthPre = atLength; 24470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 24570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 24670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Finish hash for partial AAD block 24770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (atBlockPos > 0) 24870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 24970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHPartial(S_atPre, atBlock, 0, atBlockPos); 25070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atLengthPre += atBlockPos; 25170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 25270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 25370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (atLengthPre > 0) 25470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 25570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom System.arraycopy(S_atPre, 0, S, 0, BLOCK_SIZE); 25670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 257c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 258c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 259c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public int processByte(byte in, byte[] out, int outOff) 260c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throws DataLengthException 261c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 26270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom bufBlock[bufOff] = in; 26370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (++bufOff == bufBlock.length) 26470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 26570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom outputBlock(out, outOff); 26670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return BLOCK_SIZE; 26770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 26870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return 0; 269c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 270c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 271c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public int processBytes(byte[] in, int inOff, int len, byte[] out, int outOff) 272c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throws DataLengthException 273c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 274c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int resultLen = 0; 275c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 27670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom for (int i = 0; i < len; ++i) 277c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 27870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom bufBlock[bufOff] = in[inOff + i]; 27970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (++bufOff == bufBlock.length) 280c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 28170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom outputBlock(out, outOff + resultLen); 282c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom resultLen += BLOCK_SIZE; 283c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 284c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 285c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 286c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return resultLen; 287c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 288c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 28970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private void outputBlock(byte[] output, int offset) 290c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 29170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (totalLength == 0) 292c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 29370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom initCipher(); 29470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 29570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gCTRBlock(bufBlock, output, offset); 29670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (forEncryption) 29770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 29870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom bufOff = 0; 29970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 30070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom else 30170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 30270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom System.arraycopy(bufBlock, BLOCK_SIZE, bufBlock, 0, macSize); 30370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom bufOff = macSize; 304c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 305c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 306c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 307c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public int doFinal(byte[] out, int outOff) 308c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throws IllegalStateException, InvalidCipherTextException 309c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 31070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (totalLength == 0) 31170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 31270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom initCipher(); 31370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 31470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 315c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int extra = bufOff; 316c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (!forEncryption) 317c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 318c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (extra < macSize) 319c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 320c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new InvalidCipherTextException("data too short"); 321c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 322c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom extra -= macSize; 323c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 324c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 325c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (extra > 0) 326c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 32770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gCTRPartial(bufBlock, 0, extra, out, outOff); 32870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 32970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 33070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atLength += atBlockPos; 33170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 33270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (atLength > atLengthPre) 33370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 33470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom /* 33570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom * Some AAD was sent after the cipher started. We determine the difference b/w the hash value 33670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom * we actually used when the cipher started (S_atPre) and the final hash value calculated (S_at). 33770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom * Then we carry this difference forward by multiplying by H^c, where c is the number of (full or 33870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom * partial) cipher-text blocks produced, and adjust the current hash. 33970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom */ 34070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 34170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Finish hash for partial AAD block 34270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (atBlockPos > 0) 34370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 34470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHPartial(S_at, atBlock, 0, atBlockPos); 34570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 34670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 34770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Find the difference between the AAD hashes 34870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (atLengthPre > 0) 34970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 35070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom xor(S_at, S_atPre); 35170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 35270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 35370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Number of cipher-text blocks produced 35470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom long c = ((totalLength * 8) + 127) >>> 7; 35570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 35670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Calculate the adjustment factor 35770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom byte[] H_c = new byte[16]; 35870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (exp == null) 35970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 36070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom exp = new Tables1kGCMExponentiator(); 36170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom exp.init(H); 36270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 36370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom exp.exponentiateX(c, H_c); 36470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 36570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Carry the difference forward 36670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom multiply(S_at, H_c); 36770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 36870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // Adjust the current hash 36970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom xor(S, S_at); 370c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 371c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 372c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // Final gHASH 37370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom byte[] X = new byte[BLOCK_SIZE]; 37470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom Pack.longToBigEndian(atLength * 8, X, 0); 37570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom Pack.longToBigEndian(totalLength * 8, X, 8); 376c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 37770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHBlock(S, X); 378c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 379c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // TODO Fix this if tagLength becomes configurable 380c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // T = MSBt(GCTRk(J0,S)) 381c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] tag = new byte[BLOCK_SIZE]; 382c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom cipher.processBlock(J0, 0, tag, 0); 383c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom xor(tag, S); 384c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 385c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom int resultLen = extra; 386c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 387c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // We place into macBlock our calculated value for T 388c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom this.macBlock = new byte[macSize]; 389c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom System.arraycopy(tag, 0, macBlock, 0, macSize); 390c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 391c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (forEncryption) 392c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 393c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // Append T to the message 394c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom System.arraycopy(macBlock, 0, out, outOff + bufOff, macSize); 395c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom resultLen += macSize; 396c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 397c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom else 398c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 399c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom // Retrieve the T value from the message and compare to calculated one 400c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] msgMac = new byte[macSize]; 401c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom System.arraycopy(bufBlock, extra, msgMac, 0, macSize); 402c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (!Arrays.constantTimeAreEqual(this.macBlock, msgMac)) 403c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 404c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom throw new InvalidCipherTextException("mac check in GCM failed"); 405c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 406c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 407c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 408c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom reset(false); 409c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 410c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom return resultLen; 411c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 412c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 413c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom public void reset() 414c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 415c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom reset(true); 416c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 417c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 418c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private void reset( 419c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom boolean clearMac) 420c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 42170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom cipher.reset(); 42270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 42370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom S = new byte[BLOCK_SIZE]; 42470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom S_at = new byte[BLOCK_SIZE]; 42570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom S_atPre = new byte[BLOCK_SIZE]; 42670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atBlock = new byte[BLOCK_SIZE]; 42770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atBlockPos = 0; 42870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atLength = 0; 42970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom atLengthPre = 0; 430c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom counter = Arrays.clone(J0); 431c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom bufOff = 0; 432c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom totalLength = 0; 433c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 434c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (bufBlock != null) 435c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 436c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom Arrays.fill(bufBlock, (byte)0); 437c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 438c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 439c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (clearMac) 440c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 441c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom macBlock = null; 442c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 443c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 44470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (initialAssociatedText != null) 44570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 44670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom processAADBytes(initialAssociatedText, 0, initialAssociatedText.length); 44770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 44870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 44970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 45070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private void gCTRBlock(byte[] block, byte[] out, int outOff) 45170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 45270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom byte[] tmp = getNextCounterBlock(); 45370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 45470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom xor(tmp, block); 45570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom System.arraycopy(tmp, 0, out, outOff, BLOCK_SIZE); 45670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 45770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHBlock(S, forEncryption ? tmp : block); 45870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 45970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom totalLength += BLOCK_SIZE; 46070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 46170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 46270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private void gCTRPartial(byte[] buf, int off, int len, byte[] out, int outOff) 46370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 46470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom byte[] tmp = getNextCounterBlock(); 46570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 46670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom xor(tmp, buf, off, len); 46770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom System.arraycopy(tmp, 0, out, outOff, len); 46870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 46970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHPartial(S, forEncryption ? tmp : buf, 0, len); 47070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 47170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom totalLength += len; 47270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 47370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 47470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private void gHASH(byte[] Y, byte[] b, int len) 47570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 47670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom for (int pos = 0; pos < len; pos += BLOCK_SIZE) 47770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 47870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom int num = Math.min(len - pos, BLOCK_SIZE); 47970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom gHASHPartial(Y, b, pos, num); 48070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 48170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 48270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 48370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private void gHASHBlock(byte[] Y, byte[] b) 48470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 48570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom xor(Y, b); 48670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom multiplier.multiplyH(Y); 48770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 48870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom 48970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private void gHASHPartial(byte[] Y, byte[] b, int off, int len) 49070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 49170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom xor(Y, b, off, len); 49270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom multiplier.multiplyH(Y); 493c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 494c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 49570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private byte[] getNextCounterBlock() 496c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 497c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom for (int i = 15; i >= 12; --i) 498c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 499c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte b = (byte)((counter[i] + 1) & 0xff); 500c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom counter[i] = b; 501c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 502c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom if (b != 0) 503c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 504c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom break; 505c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 506c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 507c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 508c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom byte[] tmp = new byte[BLOCK_SIZE]; 50970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // TODO Sure would be nice if ciphers could operate on int[] 510c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom cipher.processBlock(counter, 0, tmp, 0); 51170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom return tmp; 51270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 513c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 51470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private static void multiply(byte[] block, byte[] val) 51570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 51670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom byte[] tmp = Arrays.clone(block); 51770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom byte[] c = new byte[16]; 518c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 51970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom for (int i = 0; i < 16; ++i) 520c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 52170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom byte bits = val[i]; 52270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom for (int j = 7; j >= 0; --j) 52370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 52470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if ((bits & (1 << j)) != 0) 52570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 52670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom xor(c, tmp); 52770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 528c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 52970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom boolean lsb = (tmp[15] & 1) != 0; 53070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom shiftRight(tmp); 53170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (lsb) 53270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 53370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom // R = new byte[]{ 0xe1, ... }; 53470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom// xor(v, R); 53570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom tmp[0] ^= (byte)0xe1; 53670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 53770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 53870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 539c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 54070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom System.arraycopy(c, 0, block, 0, 16); 541c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 542c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 54370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private static void shiftRight(byte[] block) 544c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 54570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom int i = 0; 54670c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom int bit = 0; 54770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom for (;;) 548c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 54970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom int b = block[i] & 0xff; 55070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom block[i] = (byte) ((b >>> 1) | bit); 55170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom if (++i == 16) 55270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 55370c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom break; 55470c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 55570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom bit = (b & 1) << 7; 556c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 557c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 558c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 559c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom private static void xor(byte[] block, byte[] val) 560c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 561c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom for (int i = 15; i >= 0; --i) 562c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 563c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom block[i] ^= val[i]; 564c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 565c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 566c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom 56770c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom private static void xor(byte[] block, byte[] val, int off, int len) 568c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom { 56970c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom while (len-- > 0) 57070c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom { 57170c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom block[len] ^= val[off + len]; 57270c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom } 573c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom } 574c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom} 575