CBCBlockCipher.java revision 4c111300c39cb2e27f07fc2ae3b00e23ed4443b2
1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.modes; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.BlockCipher; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.CipherParameters; 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.DataLengthException; 6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.ParametersWithIV; 7c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstromimport org.bouncycastle.util.Arrays; 8b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * implements Cipher-Block-Chaining (CBC) mode on top of a simple cipher. 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class CBCBlockCipher 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam implements BlockCipher 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private byte[] IV; 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private byte[] cbcV; 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private byte[] cbcNextV; 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private int blockSize; 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private BlockCipher cipher = null; 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private boolean encrypting; 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Basic constructor. 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param cipher the block cipher to be used as the basis of chaining. 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public CBCBlockCipher( 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam BlockCipher cipher) 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.cipher = cipher; 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.blockSize = cipher.getBlockSize(); 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.IV = new byte[blockSize]; 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.cbcV = new byte[blockSize]; 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.cbcNextV = new byte[blockSize]; 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return the underlying block cipher that we are wrapping. 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the underlying block cipher that we are wrapping. 43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public BlockCipher getUnderlyingCipher() 45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return cipher; 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Initialise the cipher and, possibly, the initialisation vector (IV). 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * If an IV isn't passed as part of the parameter, the IV will be all zeros. 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param encrypting if true the cipher is initialised for 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * encryption, if false for decryption. 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param params the key and other data required by the cipher. 56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalArgumentException if the params argument is 57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * inappropriate. 58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public void init( 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam boolean encrypting, 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam CipherParameters params) 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IllegalArgumentException 63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 644c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom boolean oldEncrypting = this.encrypting; 654c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.encrypting = encrypting; 674c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom 68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (params instanceof ParametersWithIV) 69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 704c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom ParametersWithIV ivParam = (ParametersWithIV)params; 714c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom byte[] iv = ivParam.getIV(); 72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 734c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (iv.length != blockSize) 744c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 754c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throw new IllegalArgumentException("initialisation vector must be the same length as block size"); 764c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 784c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom System.arraycopy(iv, 0, IV, 0, iv.length); 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 804c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom reset(); 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 824c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // if null it's an IV changed only. 834c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (ivParam.getParameters() != null) 844c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam cipher.init(encrypting, ivParam.getParameters()); 864c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 874c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom else if (oldEncrypting != encrypting) 884c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 894c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throw new IllegalArgumentException("cannot change encrypting state without providing key."); 904c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 944c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom reset(); 95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 964c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom // if it;s null key is to be reused. 974c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom if (params != null) 984c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam cipher.init(encrypting, params); 1004c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 1014c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom else if (oldEncrypting != encrypting) 1024c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom { 1034c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom throw new IllegalArgumentException("cannot change encrypting state without providing key."); 1044c111300c39cb2e27f07fc2ae3b00e23ed4443b2Brian Carlstrom } 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return the algorithm name and mode. 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the name of the underlying algorithm followed by "/CBC". 112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public String getAlgorithmName() 114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return cipher.getAlgorithmName() + "/CBC"; 116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return the block size of the underlying cipher. 120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the block size of the underlying cipher. 122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int getBlockSize() 124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return cipher.getBlockSize(); 126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Process one block of input from the array in and write it to 130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * the out array. 131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param in the array containing the input data. 133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param inOff offset into the in array the data starts at. 134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param out the array the output data will be copied into. 135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param outOff the offset into the out array the output will start at. 136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception DataLengthException if there isn't enough data in in, or 137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * space in out. 138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalStateException if the cipher isn't initialised. 139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of bytes processed and produced. 140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int processBlock( 142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] in, 143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inOff, 144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] out, 145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int outOff) 146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws DataLengthException, IllegalStateException 147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return (encrypting) ? encryptBlock(in, inOff, out, outOff) : decryptBlock(in, inOff, out, outOff); 149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * reset the chaining vector back to the IV and reset the underlying 153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * cipher. 154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public void reset() 156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(IV, 0, cbcV, 0, IV.length); 158c37f4a04ef89e73a39a59f3c5a179af8c8ab5974Brian Carlstrom Arrays.fill(cbcNextV, (byte)0); 159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam cipher.reset(); 161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Do the appropriate chaining step for CBC mode encryption. 165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param in the array containing the data to be encrypted. 167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param inOff offset into the in array the data starts at. 168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param out the array the encrypted data will be copied into. 169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param outOff the offset into the out array the output will start at. 170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception DataLengthException if there isn't enough data in in, or 171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * space in out. 172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalStateException if the cipher isn't initialised. 173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of bytes processed and produced. 174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private int encryptBlock( 176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] in, 177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inOff, 178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] out, 179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int outOff) 180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws DataLengthException, IllegalStateException 181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if ((inOff + blockSize) > in.length) 183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new DataLengthException("input buffer too short"); 185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /* 188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * XOR the cbcV and the input, 189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * then encrypt the cbcV 190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = 0; i < blockSize; i++) 192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam cbcV[i] ^= in[inOff + i]; 194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 195b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int length = cipher.processBlock(cbcV, 0, out, outOff); 197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /* 199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * copy ciphertext to cbcV 200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(out, outOff, cbcV, 0, cbcV.length); 202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return length; 204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Do the appropriate chaining step for CBC mode decryption. 208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param in the array containing the data to be decrypted. 210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param inOff offset into the in array the data starts at. 211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param out the array the decrypted data will be copied into. 212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param outOff the offset into the out array the output will start at. 213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception DataLengthException if there isn't enough data in in, or 214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * space in out. 215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalStateException if the cipher isn't initialised. 216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of bytes processed and produced. 217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam private int decryptBlock( 219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] in, 220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inOff, 221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] out, 222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int outOff) 223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws DataLengthException, IllegalStateException 224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if ((inOff + blockSize) > in.length) 226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new DataLengthException("input buffer too short"); 228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(in, inOff, cbcNextV, 0, blockSize); 231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int length = cipher.processBlock(in, inOff, out, outOff); 233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /* 235b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * XOR the cbcV and the output 236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam for (int i = 0; i < blockSize; i++) 238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam out[outOff + i] ^= cbcV[i]; 240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /* 243b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * swap the back up buffer into next position 244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] tmp; 246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 247b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam tmp = cbcV; 248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam cbcV = cbcNextV; 249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam cbcNextV = tmp; 250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return length; 252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 254