1   /* $RCSfile: DESBaseCipherEngine.java,v $
2    * $Revision: 1.5 $
3    * $Date: 2003/10/04 19:18:38 $
4    * $Author: uwe_guenther $
5    * $State: Exp $
6    *
7    * Created on January 2, 2002 1:36 PM
8    *
9    * Copyright (C) 2001 Uwe Guenther <uwe@cscc.de>
10   *
11   * This file is part of the jhbci JCE-ServiceProvider. The jhbci JCE-
12   * ServiceProvider is a library, written in JavaTM, that should be 
13   * used in HBCI banking applications (clients and may be servers),
14   * to do cryptographic operations.
15   *
16   * The jhbci library is free software; you can redistribute it and/or
17   * modify it under the terms of the GNU Lesser General Public
18   * License as published by the Free Software Foundation; either
19   * version 2.1 of the License, or (at your option) any later version.
20   *
21   * The jhbci library is distributed in the hope that it will be useful,
22   * but WITHOUT ANY WARRANTY; without even the implied warranty of
23   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
24   * Lesser General Public License for more details.
25   *
26   * You should have received a copy of the GNU Lesser General Public
27   * License along with this library; if not, write to the Free Software
28   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
29   *
30   */
31  
32  package de.cscc.crypto.provider;
33  
34  import java.security.AlgorithmParameters;
35  import java.security.InvalidAlgorithmParameterException;
36  import java.security.InvalidKeyException;
37  import java.security.Key;
38  import java.security.NoSuchAlgorithmException;
39  import java.security.SecureRandom;
40  import java.security.spec.AlgorithmParameterSpec;
41  
42  import javax.crypto.BadPaddingException;
43  import javax.crypto.IllegalBlockSizeException;
44  import javax.crypto.NoSuchPaddingException;
45  import javax.crypto.ShortBufferException;
46  
47  /** 
48   * DESBaseCipherEngine Class.
49   *
50   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
51   * @version $Revision: 1.5 $
52   */
53  class DESBaseCipherEngine extends javax.crypto.CipherSpi {
54  
55      /** 
56       * Holds an instance of a DESBaseCipherImpl subclass for a
57       * concret algorithm DES1Key, DESede2Key or DESede3Key.
58       */    
59      private DESBaseCipherImpl cipher;
60      
61      /** 
62       * Creates new DESBaseCipherEngine from a given DESBaseCipherImpl Instance.
63       * Usefull for super(cipher); calls in subclasses.
64       * @param cipher the cipher
65       */
66      DESBaseCipherEngine(DESBaseCipherImpl cipher) {
67          
68          if (JHBCI.selfIntegrityChecking() == false) {
69              throw new SecurityException("JHBCI-Provider is tampered.");
70          }        
71          
72          this.cipher = cipher;
73      }
74      
75      /** 
76       * Returns a string representation of the object. 
77       * @return  a string representation of the object.
78       */
79      public String toString() {
80          return this.cipher.toString();
81      }    
82      
83      /** 
84       * Sets the mode of this cipher.
85       * @param mode the cipher mode.
86       * @throws NoSuchAlgorithmException if the requested cipher mode does not exist.
87       */
88      protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
89          this.cipher.setMode(mode);
90      }
91      
92      /** 
93       * Sets the padding mechanism of this cipher.
94       * @param padding the padding mechanism.
95       * @throws NoSuchPaddingException if the requested padding mechanism does not exist.
96       */
97      protected void engineSetPadding(String padding) 
98              throws NoSuchPaddingException {
99                  
100         this.cipher.setPadding(padding);
101     }
102     
103     /** 
104      * Initializes this cipher with a key and a source of randomness.
105      * @param opmode the operation mode  of this cipher.
106      * This is one of the following:
107      * javax.crypto.Cipher.ENCRYPT_MODE
108      * javax.crypto.Cipher.DECRYPT_MODE
109      * javax.crypto.Cipher.WRAP_MODE
110      * javax.crypto.Cipher.UNWRAP_MODE
111      * @param key the key to encrypt or to decrypt.
112      * @param random the source of randomness.
113      * @throws InvalidKeyException if the given key is inappropriate for initializing
114      * this cipher, or if this cipher is being initialized
115      * for decryption and requires algorithm parameters
116      * that cannot be determinated from the given key.
117      */
118     protected void engineInit(int opmode, Key key, SecureRandom random) 
119             throws InvalidKeyException {
120                 
121         this.cipher.init(opmode, key, random);
122     }
123     
124     /** 
125      * Initializes this cipher with a key, a set of algorithm parameters,
126      * and a source of randomness.
127      * @param opmode the operation mode  of this cipher.
128      * This is one of the following:
129      * javax.crypto.Cipher.ENCRYPT_MODE
130      * javax.crypto.Cipher.DECRYPT_MODE
131      * javax.crypto.Cipher.WRAP_MODE
132      * javax.crypto.Cipher.UNWRAP_MODE
133      * @param key the key to encrypt or to decrypt.
134      * @param params the algorithm paramter.
135      * @param random the source of randomness.
136      * @throws InvalidKeyException if the given key is inappropriate for initializing
137      * this cipher.
138      * @throws InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate
139      * for this cipher, or if this cipher is being
140      * initialized for decryption and requires algorithm
141      * parameters and params is null.
142      */
143     protected void engineInit(int opmode, Key key, AlgorithmParameters params, 
144             SecureRandom random) 
145             throws InvalidKeyException, InvalidAlgorithmParameterException {
146                 
147         this.cipher.init(opmode, key, params, random);
148     }
149     
150     /** 
151      * Initializes this cipher with a key, a set of algorithm parameters,
152      * and a source of randomness.
153      * @param opmode the operation mode  of this cipher.
154      * This is one of the following:
155      * javax.crypto.Cipher.ENCRYPT_MODE
156      * javax.crypto.Cipher.DECRYPT_MODE
157      * javax.crypto.Cipher.WRAP_MODE
158      * javax.crypto.Cipher.UNWRAP_MODE
159      * @param key the key to encrypt or to decrypt.
160      * @param params the algorithm paramter.
161      * @param random the source of randomness.
162      * @throws InvalidKeyException if the given key is inappropriate for initializing
163      * this cipher.
164      * @throws InvalidAlgorithmParameterException if the given algorithm parameters are inappropriate
165      * for this cipher, or if this cipher is being
166      * initialized for decryption and requires algorithm
167      * parameters and params is null.
168      */     
169     protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params, 
170             SecureRandom random) 
171             throws InvalidKeyException, InvalidAlgorithmParameterException {
172                 
173         this.cipher.init(opmode, key, params, random);
174     }
175     
176     /** 
177      * Continues a multiple-part encryption or decryption operation
178      * (depending on how this cipher was initialized), processing another data
179      * part.
180      * @param input the input buffer.
181      * @param inputOffset the offset in input where the input starts.
182      * @param inputLen the input length.
183      * @return the new buffer with the result, or null if the
184      * underlying cipher is a block cipher and the input
185      * data is too short to result in a new block.
186      */
187     protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
188         
189         return this.cipher.update(input, inputOffset, inputLen);
190     }
191     
192     /** 
193      * Continues a multiple-part encryption or decryption operation
194      * (depending on how this cipher was initialized), processing another data
195      * part.
196      * @param input the input buffer.
197      * @param inputOffset the offset in input where the input starts.
198      * @param inputLen the input length.
199      * @param output the buffer for the result.
200      * @param outputOffset the offset in output where the result is stored.
201      * @throws ShortBufferException if the given output buffer is too small to
202      * hold the result.
203      * @return the number of bytes stored in output
204      */      
205     protected int engineUpdate(byte[] input, int inputOffset, int inputLen, 
206                                byte[] output, int outputOffset) 
207             throws ShortBufferException {
208                 
209         return this.cipher.update(input, inputOffset, inputLen, output, outputOffset);
210     }
211     
212     
213     /** 
214      * Encrypts or decrypts data in a single-part operation, or finishes a
215      * multiple-part operation.
216      * @param input the input buffer.
217      * @param inputOffset the offset in input where the input starts.
218      * @param inputLen the input length.
219      * @throws IllegalBlockSizeException if this cipher is a block cipher, no padding
220      * has been requested (only in encryption mode),
221      * and the total input length of the data processed
222      * by this cipher is not a multiple of block size.
223      * @throws BadPaddingException if this cipher is in decryption mode,
224      * and (un)padding has been requested,
225      * but the decrypted data is not bounded
226      * by the appropriate padding bytes.
227      * @return the new buffer with the finally result.
228      */
229     protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) 
230             throws IllegalBlockSizeException, BadPaddingException {
231         
232         return this.cipher.doFinal(input, inputOffset, inputLen);
233     }
234     
235     
236     /** 
237      * Encrypts or decrypts data in a single-part operation, or finishes a
238      * multiple-part operation.
239      * @param input the input buffer.
240      * @param inputOffset the offset in input where the input starts.
241      * @param inputLen the input length.
242      * @param output the buffer for the finally result.
243      * @param outputOffset the offset in output where the result is stored.
244      * @throws ShortBufferException if the given output buffer is too small to
245      * hold the result.
246      * @throws IllegalBlockSizeException if this cipher is a block cipher, no padding
247      * has been requested (only in encryption mode),
248      * and the total input length of the data processed
249      * by this cipher is not a multiple of block size.
250      * @throws BadPaddingException if this cipher is in decryption mode,
251      * and (un)padding has been requested,
252      * but the decrypted data is not bounded
253      * by the appropriate padding bytes.
254      * @return the number of bytes stored in output.
255      */       
256     protected int engineDoFinal(byte[] input, 
257                                 int inputOffset, 
258                                 int inputLen, 
259                                 byte[] output, 
260                                 int outputOffset) 
261     throws ShortBufferException, IllegalBlockSizeException, BadPaddingException 
262     {
263         return this.cipher.doFinal(input, inputOffset, inputLen, output, outputOffset);        
264     }
265     
266     /** Returns the length in bytes that an output buffer would need to be in
267      * order to hold the result of the next update or doFinal operation, given
268      * the input length inputLen (in bytes).
269      * @param inputLen the input length in bytes.
270      * @return the reqired output buffer size in bytes.
271      */
272     protected int engineGetOutputSize(int inputLen) 
273     {
274         return this.cipher.getOutputSize(inputLen);
275     }
276     
277     /** Returns the parameters used with this cipher.
278      * @return the parameters used with this cipher,
279      * or null if this cipher does not use
280      * any parameters.
281      */
282     protected AlgorithmParameters engineGetParameters() 
283     {
284         return this.cipher.getParameters();
285     }
286     
287     /** 
288      * Returns the initialization vector (IV) in a new buffer.
289      * @return the initialization vector in a new buffer,
290      * or null if the underlying algorithm does not
291      * use an IV, or if the IV has not yet been set.
292      */
293     protected byte[] engineGetIV() {
294         
295         return this.cipher.getIV();
296     }
297     
298     /**
299      * Returns the block size (in bytes).
300      * @return the block size (in bytes), or 0 if the
301      * underlying algorithm is not a block cipher
302      */
303     protected int engineGetBlockSize() {
304         
305         return this.cipher.getBlockSize();
306     }
307     
308     /** 
309      * Returns the key size of the given key object.
310      * @param key the key object.
311      * @throws InvalidKeyException if key is invalid.
312      * @return the key size of the given key object.
313      */
314     protected int engineGetKeySize(Key key) throws InvalidKeyException {
315         
316         return this.cipher.getKeySize(key);
317     }
318     
319     /** 
320      * Unwrap a previously wrapped key.
321      * @param wrappedKey the wrapped key to unwrap.
322      * @param wrappedKeyAlgorithm the algorithm associated with the key wrapped key.
323      * @param wrappedKeyType the type of the wrapped key. This is one of
324      * javax.crypto.Cipher.SECRET_KEY,
325      * javax.crypto.Cipher.PRIVATE_KEY,
326      * javax.crypto.Cipher.PUBLIC_KEY.
327      * @throws InvalidKeyException if wrappedKey does not represent a wrapped key,
328      * or if the algorithm associated with the wrapped
329      * key is different from wrappedKeyAlgorithm and/or
330      * its key type is different from wrappedKeyType.
331      * @throws NoSuchAlgorithmException if no installed providers can create
332      * keys for the wrappedKeyAlgorithm.
333      * @return the unwrapped key.
334      */
335     protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
336                                int wrappedKeyType) 
337             throws InvalidKeyException, NoSuchAlgorithmException {
338                 
339         return this.cipher.unwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType);
340     }
341     
342     /** 
343      * Wrap a key.
344      * @param key the key to be wrapped.
345      * @throws IllegalBlockSizeException if this cipher is a block cipher,
346      * no padding has been requested, and the
347      * length of the encoding of the key to be
348      * wrapped is not a multiple of the block size.
349      * @throws InvalidKeyException if it is impossible or unsafe to wrap the
350      * key with this cipher (e.g., a hardware
351      * public key is being passed to a
352      * software-only cipher).
353      * @return the wrapped key.
354      */
355     protected byte[] engineWrap(Key key) 
356             throws IllegalBlockSizeException, InvalidKeyException {
357                 
358         return this.cipher.wrap(key);
359     }
360 }
361