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