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