1b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampackage org.bouncycastle.crypto.paddings; 2b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 3b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.BlockCipher; 4b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.BufferedBlockCipher; 5b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.CipherParameters; 6b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.DataLengthException; 7b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.InvalidCipherTextException; 870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstromimport org.bouncycastle.crypto.OutputLengthException; 9b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallamimport org.bouncycastle.crypto.params.ParametersWithRandom; 10b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 11b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam/** 12b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * A wrapper class that allows block ciphers to be used to process data in 13b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * a piecemeal fashion with padding. The PaddedBufferedBlockCipher 14b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * outputs a block only when the buffer is full and more data is being added, 15b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * or on a doFinal (unless the current block in the buffer is a pad block). 16b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * The default padding mechanism used is the one outlined in PKCS5/PKCS7. 17b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 18b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallampublic class PaddedBufferedBlockCipher 19b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam extends BufferedBlockCipher 20b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam{ 21b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam BlockCipherPadding padding; 22b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 23b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 24b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Create a buffered block cipher with the desired padding. 25b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 26b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param cipher the underlying block cipher this buffering object wraps. 27b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param padding the padding type. 28b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 29b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public PaddedBufferedBlockCipher( 30b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam BlockCipher cipher, 31b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam BlockCipherPadding padding) 32b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 33b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.cipher = cipher; 34b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.padding = padding; 35b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 36b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam buf = new byte[cipher.getBlockSize()]; 37b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam bufOff = 0; 38b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 39b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 40b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 41b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Create a buffered block cipher PKCS7 padding 42b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 43b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param cipher the underlying block cipher this buffering object wraps. 44b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 45b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public PaddedBufferedBlockCipher( 46b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam BlockCipher cipher) 47b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 48b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this(cipher, new PKCS7Padding()); 49b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 50b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 51b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 52b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * initialise the cipher. 53b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 54b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param forEncryption if true the cipher is initialised for 55b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * encryption, if false for decryption. 56b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param params the key and other data required by the cipher. 57b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalArgumentException if the params argument is 58b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * inappropriate. 59b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 60b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public void init( 61b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam boolean forEncryption, 62b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam CipherParameters params) 63b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws IllegalArgumentException 64b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 65b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam this.forEncryption = forEncryption; 66b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 67b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam reset(); 68b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 69b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (params instanceof ParametersWithRandom) 70b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 71b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam ParametersWithRandom p = (ParametersWithRandom)params; 72b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 73b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam padding.init(p.getRandom()); 74b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 75b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam cipher.init(forEncryption, p.getParameters()); 76b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 77b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 78b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 79b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam padding.init(null); 80b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 81b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam cipher.init(forEncryption, params); 82b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 83b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 84b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 85b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 86b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return the minimum size of the output buffer required for an update 87b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * plus a doFinal with an input of len bytes. 88b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 89b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param len the length of the input. 90b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the space required to accommodate a call to update and doFinal 91b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * with len bytes of input. 92b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 93b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int getOutputSize( 94b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int len) 95b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 96b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int total = len + bufOff; 97b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int leftOver = total % buf.length; 98b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 99b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (leftOver == 0) 100b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 101b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (forEncryption) 102b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 103b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return total + buf.length; 104b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 105b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 106b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return total; 107b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 108b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 109b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return total - leftOver + buf.length; 110b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 111b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 112b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 113b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * return the size of the output buffer required for an update 114b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * an input of len bytes. 115b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 116b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param len the length of the input. 117b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the space required to accommodate a call to update 118b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * with len bytes of input. 119b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 120b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int getUpdateOutputSize( 121b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int len) 122b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 123b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int total = len + bufOff; 124b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int leftOver = total % buf.length; 125b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 126b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (leftOver == 0) 127b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 128b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return total - buf.length; 129b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 130b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 131b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return total - leftOver; 132b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 133b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 134b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 135b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * process a single byte, producing an output block if neccessary. 136b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 137b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param in the input byte. 138b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param out the space for any output that might be produced. 139b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param outOff the offset from which the output will be copied. 140b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of output bytes copied to out. 141b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception DataLengthException if there isn't enough space in out. 142b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalStateException if the cipher isn't initialised. 143b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 144b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int processByte( 145b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte in, 146b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] out, 147b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int outOff) 148b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws DataLengthException, IllegalStateException 149b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 150b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int resultLen = 0; 151b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 152b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (bufOff == buf.length) 153b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 154b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam resultLen = cipher.processBlock(buf, 0, out, outOff); 155b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam bufOff = 0; 156b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 157b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 158b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam buf[bufOff++] = in; 159b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 160b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return resultLen; 161b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 162b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 163b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 164b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * process an array of bytes, producing output if necessary. 165b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 166b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param in the input byte array. 167b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param inOff the offset at which the input data starts. 168b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param len the number of bytes to be copied out of the input array. 169b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param out the space for any output that might be produced. 170b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param outOff the offset from which the output will be copied. 171b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of output bytes copied to out. 172b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception DataLengthException if there isn't enough space in out. 173b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalStateException if the cipher isn't initialised. 174b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 175b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int processBytes( 176b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] in, 177b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int inOff, 178b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int len, 179b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] out, 180b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int outOff) 181b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws DataLengthException, IllegalStateException 182b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 183b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (len < 0) 184b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 185b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new IllegalArgumentException("Can't have a negative input length!"); 186b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 187b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 188b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int blockSize = getBlockSize(); 189b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int length = getUpdateOutputSize(len); 190b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 191b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (length > 0) 192b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 193b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if ((outOff + length) > out.length) 194b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 19570c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom throw new OutputLengthException("output buffer too short"); 196b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 197b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 198b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 199b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int resultLen = 0; 200b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int gapLen = buf.length - bufOff; 201b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 202b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (len > gapLen) 203b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 204b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(in, inOff, buf, bufOff, gapLen); 205b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 206b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam resultLen += cipher.processBlock(buf, 0, out, outOff); 207b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 208b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam bufOff = 0; 209b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam len -= gapLen; 210b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam inOff += gapLen; 211b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 212b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam while (len > buf.length) 213b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 214b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam resultLen += cipher.processBlock(in, inOff, out, outOff + resultLen); 215b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 216b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam len -= blockSize; 217b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam inOff += blockSize; 218b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 219b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 220b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 221b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(in, inOff, buf, bufOff, len); 222b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 223b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam bufOff += len; 224b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 225b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return resultLen; 226b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 227b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 228b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam /** 229b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * Process the last block in the buffer. If the buffer is currently 230b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * full and padding needs to be added a call to doFinal will produce 231b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 2 * getBlockSize() bytes. 232b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * 233b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param out the array the block currently being held is copied into. 234b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @param outOff the offset at which the copying starts. 235b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @return the number of output bytes copied to out. 236b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception DataLengthException if there is insufficient space in out for 237b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * the output or we are decrypting and the input is not block size aligned. 238b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception IllegalStateException if the underlying cipher is not 239b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * initialised. 240b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam * @exception InvalidCipherTextException if padding is expected and not found. 241b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam */ 242b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam public int doFinal( 243b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam byte[] out, 244b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int outOff) 245b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throws DataLengthException, IllegalStateException, InvalidCipherTextException 246b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 247b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int blockSize = cipher.getBlockSize(); 248b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam int resultLen = 0; 249b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 250b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (forEncryption) 251b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 252b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (bufOff == blockSize) 253b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 254b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if ((outOff + 2 * blockSize) > out.length) 255b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 256b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam reset(); 257b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 25870c8287138e69a98c2f950036f9f703ee37228c8Brian Carlstrom throw new OutputLengthException("output buffer too short"); 259b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 260b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 261b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam resultLen = cipher.processBlock(buf, 0, out, outOff); 262b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam bufOff = 0; 263b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 264b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 265b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam padding.addPadding(buf, bufOff); 266b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 267b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam resultLen += cipher.processBlock(buf, 0, out, outOff + resultLen); 268b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 269b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam reset(); 270b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 271b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 272b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 273b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam if (bufOff == blockSize) 274b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 275b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam resultLen = cipher.processBlock(buf, 0, buf, 0); 276b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam bufOff = 0; 277b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 278b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam else 279b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 280b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam reset(); 281b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 282b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam throw new DataLengthException("last block incomplete in decryption"); 283b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 284b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 285b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam try 286b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 287b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam resultLen -= padding.padCount(buf); 288b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 289b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam System.arraycopy(buf, 0, out, outOff, resultLen); 290b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 291b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam finally 292b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam { 293b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam reset(); 294b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 295b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 296b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam 297b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam return resultLen; 298b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam } 299b61a96e7ef1a78acf013bbf08fe537e5b5f129caPeter Hallam} 300