Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: cryptix/jce/provider/cipher/Padding.java


1   /* $Id: Padding.java,v 1.20 2005/03/28 15:44:53 woudt Exp $
2    *
3    * Copyright (C) 1995-2000 The Cryptix Foundation Limited.
4    * All rights reserved.
5    *
6    * Use, modification, copying and distribution of this software is subject
7    * the terms and conditions of the Cryptix General Licence. You should have
8    * received a copy of the Cryptix General Licence along with this library;
9    * if not, you can download a copy from http://www.cryptix.org/ .
10   */
11  package cryptix.jce.provider.cipher;
12  
13  
14  import java.security.InvalidAlgorithmParameterException;
15  import java.security.InvalidKeyException;
16  import java.security.Key;
17  import java.security.SecureRandom;
18  import java.security.spec.AlgorithmParameterSpec;
19  import javax.crypto.ShortBufferException;
20  import javax.crypto.IllegalBlockSizeException;
21  import javax.crypto.BadPaddingException;
22  import javax.crypto.NoSuchPaddingException;
23  
24  
25  /**
26   * <p>
27   * A fully constructed Cipher instance looks like this:
28   * <pre>
29   * +------------------------------------------+
30   * | CipherSpi (API methods)                  |
31   * |                                          |
32   * | +--------------------------------------+ |
33   * | | Padding                              | |
34   * | |                                      | |
35   * | | +----------------------------------+ | |
36   * | | | Mode                             | | |
37   * | | |                                  | | |
38   * | | | +------------------------------+ | | |
39   * | | | | CipherSpi                    | | | |
40   * | | | | (blockcipher implementation) | | | |
41   * | | | |                              | | | |
42   * | | | +------------------------------+ | | |
43   * | | |                                  | | |
44   * | | +----------------------------------+ | |
45   * | |                                      | |
46   * | +--------------------------------------+ |
47   * |                                          |
48   * +------------------------------------------+
49   * </pre>
50   *
51   * @author  Jeroen C. van Gelderen (gelderen@cryptix.org)
52   * @author  Paul Waserbrot (pw@cryptix.org)
53   * @version $Revision: 1.20 $
54   */
55  abstract class Padding
56  {
57      /** Cipher/Mode delegate */
58      private final Mode mode;
59  
60  
61      private byte[] scratchBuf;
62      private int blSize;
63      private boolean isBuffered;
64  
65  
66      protected boolean decrypt;
67  
68  
69      Padding(Mode mode) {
70          this.mode = mode;
71          blSize = this.getBlockSize();
72          scratchBuf = new byte[blSize];
73          isBuffered = false;
74      }
75  
76  
77      /**
78       * Factory method for obtaining different padding type objects.
79       *
80       * This method accept a padding name and a Mode instance and
81       * returns a Padding instance that wraps the given Mode instance.
82       * 
83       * This class is package protected therefore the various padding 
84       * types can be (and are) hardcoded here.
85       *
86       * @throws NoSuchPaddingException
87       *         When the requested padding type cannot be provided.
88       */
89      static Padding getInstance(String padding, Mode mode)
90      throws NoSuchPaddingException
91      {
92          // Debug.assert(padding!=null);
93          // Debug.assert(mode!=null);
94          
95          // None
96          if( padding.equalsIgnoreCase("None")
97           || padding.equalsIgnoreCase("NoPadding") )
98              return new PaddingNone(mode);
99          
100         // Generalized PKCS#5 (aka PKCS#7)
101         if( padding.equalsIgnoreCase("PKCS5") 
102          || padding.equalsIgnoreCase("PKCS#5")
103          || padding.equalsIgnoreCase("PKCS5Padding")
104          || padding.equalsIgnoreCase("PKCS7")
105          || padding.equalsIgnoreCase("PKCS#7") )
106             return new PaddingPKCS5(mode);
107         
108         // Oops, not supported
109         throw new NoSuchPaddingException(
110             "Padding not available [" + padding + "]");
111     }
112 
113 
114     /**
115      * This method delegates to the wrapped Mode instance.
116      */
117     final int getBlockSize() {
118         return mode.getBlockSize();
119     }
120 
121 
122     final int getOutputSize(int inputLen) {
123         if (isBuffered) 
124             return mode.getOutputSize(inputLen + this.getPadSize(inputLen))
125                    + blSize;
126         else
127             return mode.getOutputSize(inputLen + this.getPadSize(inputLen));
128     }
129 
130 
131     /**
132      * This method delegates to the wrapped Mode instance.
133      */
134     final AlgorithmParameterSpec getParamSpec() {
135         return mode.getParamSpec();
136     }
137 
138 
139     /**
140      * This method delegates to the wrapped Mode instance.
141      */
142     final byte[] getIV() {
143         return mode.getIV();
144     }
145 
146 
147     /**
148      * This method delegates to the wrapped Mode instance.
149      */
150     final void init(boolean decrypt, Key key, AlgorithmParameterSpec params,
151                     SecureRandom random)
152     throws InvalidKeyException, InvalidAlgorithmParameterException
153     {
154         mode.init(this.decrypt = decrypt, key, params, random);
155     }
156 
157 
158     /**
159      * This method delegates to the wrapped Mode instance.
160      *
161      * @throws ShortBufferException
162      *         If output is too short to hold the result.
163      */
164     final int update(byte[] input, int inputOffset, int inputLen,
165                      byte[] output, int outputOffset)
166     throws ShortBufferException
167     {
168         if (output.length < this.getOutputSize(inputLen))
169             throw new ShortBufferException("The output buffer is too short");
170         
171         if (decrypt) {
172             int i = 0;
173              if (!isBuffered) {
174                 i = mode.update(input, inputOffset, inputLen - blSize,
175                                  output, outputOffset);
176                 System.arraycopy(input, inputOffset + (inputLen - blSize),
177                                  scratchBuf, 0, blSize);
178                 isBuffered = true;
179             } else {
180                 i = mode.update(scratchBuf, 0, blSize, output, outputOffset);
181                 System.arraycopy(input, inputOffset + (inputLen - blSize),
182                                  scratchBuf, 0, blSize);
183                 i += mode.update(input, inputOffset, inputLen - blSize,
184                                  output, outputOffset + blSize);
185             }
186             return i;
187         } else
188             return mode.update(input, inputOffset, inputLen, 
189                                output, outputOffset);
190     }
191 
192     /**
193      * @throws BadPaddingException
194      *         If the padding data is corrupt or not found (decrypt only).
195      * @throws IllegalBlockSizeException
196      *         If no padding is specified *and* the input data was not a
197      *         multiple of the Cipher's blocksize.
198      * @throws ShortBufferException
199      *         If output is too short to hold the result.
200      */
201     final int doFinal(byte[] input, int inputOffset, int inputLen,
202                       byte[] output, int outputOffset)
203     throws ShortBufferException, IllegalBlockSizeException, BadPaddingException
204     {
205         if (output.length < this.getOutputSize(inputLen))
206             throw new ShortBufferException("The output buffer is too short");
207         byte [] t;
208         if (decrypt) {
209            if (input == null && !isBuffered) return 0;
210            if (input != null && inputLen < this.getPadSize(inputLen))
211               throw new BadPaddingException("Input data not bounded by the "+
212                                             "padding size");
213            int i = 0;
214            if (isBuffered) {
215                i = mode.update(scratchBuf, 0, blSize, 
216                                output, outputOffset);
217                if (input != null)
218                    i += mode.update(input, inputOffset, 
219                                     inputLen, output, outputOffset + blSize);
220            } else {
221                i = mode.update(input, inputOffset, inputLen, 
222                                output, outputOffset);
223            }
224            isBuffered = false;
225            return coreUnPad(output,i);
226         }
227         t = this.corePad(input, inputLen);
228         return mode.update(t, inputOffset, t.length, output, outputOffset);
229     }
230 
231 
232     protected int getBufSize() {
233         return mode.getBufSize();
234     }
235 
236     // Abstract methods which the Padding classes must implement
237     abstract byte [] corePad(byte [] input, int inputLen)
238         throws IllegalBlockSizeException;
239 
240     abstract int coreUnPad(byte [] input, int inputLen)
241         throws BadPaddingException;
242 
243     abstract int getPadSize(int inputLen); 
244 }