1   /* $RCSfile: RSACipherEngine.java,v $
2    * $Revision: 1.4 $
3    * $Date: 2003/10/04 19:18:38 $
4    * $Author: uwe_guenther $
5    * $State: Exp $
6    *
7    * Created on July 23, 2001 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.CipherSpi;
44  import javax.crypto.IllegalBlockSizeException;
45  import javax.crypto.NoSuchPaddingException;
46  import javax.crypto.ShortBufferException;
47  
48  /**
49   * RSACipherEngine Class.
50   *
51   * @author  <a href=mailto:uwe@cscc.de>Uwe G&uuml;nther</a>
52   * @version $Revision: 1.4 $
53   */
54  public final class RSACipherEngine extends CipherSpi {
55      
56      private RSACipherImpl cipher = new RSACipherImpl();
57  
58      public RSACipherEngine() {
59          if (JHBCI.selfIntegrityChecking() == false) {
60              throw new SecurityException("JHBCI-Provider is tampered.");
61          }    
62      }
63      
64      /**
65       * Returns a string representation of the object.
66       *
67       * @return  a string representation of the object.
68       */
69      public String toString() {
70          return this.cipher.toString();
71      }
72      
73      /**
74       * Sets the mode of this cipher.
75       * @param mode the cipher mode.
76       * @throws NoSuchAlgorithmException if the requested cipher mode does not exist.
77       */
78      protected void engineSetMode(String mode) throws NoSuchAlgorithmException {
79          this.cipher.setMode(mode);
80      }
81      
82      /**
83       * Sets the padding mechanism of this cipher.
84       *
85       * @param padding the padding mechanism.
86       * @throws NoSuchPaddingException if the requested padding mechanism does not exist.
87       */
88      protected void engineSetPadding(String padding)
89      throws NoSuchPaddingException {
90          this.cipher.setPadding(padding);
91      }
92      
93      /**
94       * Initializes this cipher with a key and a source of randomness.
95       *
96       * @param opmode the operation mode  of this cipher.
97       * This is one of the following:
98       * javax.crypto.Cipher.ENCRYPT_MODE
99       * javax.crypto.Cipher.DECRYPT_MODE
100      * javax.crypto.Cipher.WRAP_MODE
101      * javax.crypto.Cipher.UNWRAP_MODE
102      * @param key the key to encrypt or to decrypt.
103      * @param random the source of randomness.
104      * @throws InvalidKeyException if the given key is inappropriate for
105      * initializing this cipher, this means if the key does not match to
106      * the specific opmode.
107      * @throws NullPointerException if key is null.
108      */
109     protected void engineInit(int opmode, Key key, SecureRandom random)
110     throws InvalidKeyException {
111         this.cipher.init(opmode, key, random);
112     }
113     
114     /**
115      * Initializes this cipher with a key, a set of algorithm parameters,
116      * and a source of randomness.
117      *
118      * @param opmode the operation mode  of this cipher.
119      * This is one of the following:
120      * javax.crypto.Cipher.ENCRYPT_MODE
121      * javax.crypto.Cipher.DECRYPT_MODE
122      * javax.crypto.Cipher.WRAP_MODE
123      * javax.crypto.Cipher.UNWRAP_MODE
124      * @param key the key to encrypt or to decrypt.
125      * @param params the algorithm paramter.
126      * @param random the source of randomness.
127      * @throws InvalidKeyException if the given key is inappropriate for
128      * initializing this cipher.
129      * @throws InvalidAlgorithmParameterException if params isn't null, because
130      * we don't support AlgorithmParameters.
131      */
132     protected void engineInit(int opmode, Key key, AlgorithmParameters params,
133     SecureRandom random)
134     throws InvalidKeyException, InvalidAlgorithmParameterException {
135         this.cipher.init(opmode, key, params, random);
136     }
137     
138     /**
139      * Initializes this cipher with a key, a set of algorithm parameters,
140      * and a source of randomness.
141      *
142      * @param opmode the operation mode  of this cipher.
143      * This is one of the following:
144      * javax.crypto.Cipher.ENCRYPT_MODE
145      * javax.crypto.Cipher.DECRYPT_MODE
146      * javax.crypto.Cipher.WRAP_MODE
147      * javax.crypto.Cipher.UNWRAP_MODE
148      * @param key the key to encrypt or to decrypt.
149      * @param params the algorithm paramter.
150      * @param random the source of randomness.
151      * @throws InvalidKeyException if the given key is inappropriate for
152      * initializing this cipher.
153      * @throws InvalidAlgorithmParameterException if params isn't null, because
154      * we don't support AlgorithmParameterSpecs.
155      */
156     protected void engineInit(int opmode, Key key, AlgorithmParameterSpec params,
157     SecureRandom random)
158     throws InvalidKeyException, InvalidAlgorithmParameterException {
159         this.cipher.init(opmode, key, params, random);
160     }
161     
162     /**
163      * Continues a multiple-part encryption or decryption operation
164      * (depending on how this cipher was initialized), processing another data
165      * part.
166      *
167      * @param input the input buffer.
168      * @param inputOffset the offset in input where the input starts.
169      * @param inputLen the input length.
170      * @throws IllegalStateException if the Cipher was not initialized, or you
171      * invoke this method in WRAP_MODE or UNWRAP_MODE.
172      * @return the new buffer with the result, or null if the
173      * underlying cipher is a block cipher and the input
174      * data is too short to result in a new block.
175      */
176     protected byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
177         return this.cipher.update(input, inputOffset, inputLen);
178     }
179     
180     /**
181      * Continues a multiple-part encryption or decryption operation
182      * (depending on how this cipher was initialized), processing another data
183      * part.
184      *
185      * @param input the input buffer.
186      * @param inputOffset the offset in input where the input starts.
187      * @param inputLen the input length.
188      * @param output the buffer for the result.
189      * @param outputOffset the offset in output where the result is stored.
190      * @throws ShortBufferException if the given output buffer is too small to
191      * hold the result.
192      * @throws IllegalStateException if the Cipher was not initialized, or you
193      * invoke this method in WRAP_MODE or UNWRAP_MODE.
194      * @return the number of bytes stored in output
195      */
196     protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
197     byte[] output, int outputOffset)
198     throws ShortBufferException {
199         return this.cipher.update(input, inputOffset, inputLen, 
200         output, outputOffset);
201     }
202     
203     
204     /**
205      * Encrypts or decrypts data in a single-part operation, or finishes a
206      * multiple-part operation.
207      *
208      * @param input the input buffer.
209      * @param inputOffset the offset in input where the input starts.
210      * @param inputLen the input length.
211      * @throws IllegalBlockSizeException if this cipher is a block cipher, no padding
212      * has been requested (only in encryption mode),
213      * and the total input length of the data processed
214      * by this cipher is not a multiple of block size.
215      * @throws BadPaddingException if this cipher is in decryption mode,
216      * and (un)padding has been requested,
217      * but the decrypted data is not bounded
218      * by the appropriate padding bytes.
219      * @throws IllegalStateException if the Cipher was not initialized, or you
220      * invoke this method in WRAP_MODE or UNWRAP_MODE.
221      * @return the new buffer with the finally result.
222      */
223     protected byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
224     throws IllegalBlockSizeException, BadPaddingException {
225         return this.cipher.doFinal(input, inputOffset, inputLen);
226     }
227     
228     
229     /**
230      * Encrypts or decrypts data in a single-part operation, or finishes a
231      * multiple-part operation.
232      *
233      * @param input the input buffer.
234      * @param inputOffset the offset in input where the input starts.
235      * @param inputLen the input length.
236      * @param output the buffer for the finally result.
237      * @param outputOffset the offset in output where the result is stored.
238      * @throws ShortBufferException if the given output buffer is too small to
239      * hold the result.
240      * @throws IllegalBlockSizeException if this cipher is a block cipher, no padding
241      * has been requested (only in encryption mode),
242      * and the total input length of the data processed
243      * by this cipher is not a multiple of block size.
244      * @throws BadPaddingException if this cipher is in decryption mode,
245      * and (un)padding has been requested,
246      * but the decrypted data is not bounded
247      * by the appropriate padding bytes.
248      * @throws IllegalStateException if the Cipher was not initialized, or you
249      * invoke this method in WRAP_MODE or UNWRAP_MODE.
250      * @return the number of bytes stored in output.
251      */
252     protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
253     byte[] output, int outputOffset) throws ShortBufferException,
254     IllegalBlockSizeException, BadPaddingException {
255         return this.cipher.doFinal(input, inputOffset, inputLen, 
256         output, outputOffset);
257     }
258     
259     
260     /**
261      * Wrap a key.
262      *
263      * @param key the key to be wrapped.
264      * @throws NullpointerException if <code>key.getEncoded()</code> is null.
265      * This means the key does not support encoding.
266      * @throws IllegalBlockSizeException if the unsigned number representation
267      * of the encoded key is equal or greater than the modulus of the RSAKey.
268      * @throws InvalidKeyException if it is impossible or unsafe to wrap the
269      * key with this cipher (e.g., a hardware
270      * public key is being passed to a
271      * software-only cipher).
272      * @throws IllegalStateException if the Cipher was not initialized, or you
273      * invoke this method in ENCRYPT_MODE or DECRTYPT_MODE.
274      * @return the wrapped key.
275      */
276     protected byte[] engineWrap(Key key)
277     throws IllegalBlockSizeException, InvalidKeyException {
278         return this.cipher.wrap(key);
279     }
280 
281     /**
282      * Unwrap a previously wrapped key.
283      *
284      * @param wrappedKey the wrapped key to unwrap.
285      * @param wrappedKeyAlgorithm the algorithm associated with the key wrapped
286      * key.
287      * @param wrappedKeyType the type of the wrapped key. This is one of
288      * javax.crypto.Cipher.SECRET_KEY,
289      * javax.crypto.Cipher.PRIVATE_KEY,
290      * javax.crypto.Cipher.PUBLIC_KEY.
291      * @throws InvalidKeyException if wrappedKey does not represent a wrapped
292      * key, or if the algorithm associated with the wrapped key is different
293      * from wrappedKeyAlgorithm and/or its key type is different from
294      * wrappedKeyType.
295      * @throws NoSuchAlgorithmException if no installed providers can create
296      * keys for the wrappedKeyAlgorithm.
297      * @throws IllegalStateException if the Cipher was not initialized.
298      * @return the unwrapped key.
299      */
300     protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
301     int wrappedKeyType)
302     throws InvalidKeyException, NoSuchAlgorithmException {
303         return this.cipher.unwrap(wrappedKey, wrappedKeyAlgorithm, 
304         wrappedKeyType);
305     }
306 
307     /**
308      * Returns the block size (in bytes) that can be processed while a
309      * multipart cipher operation.
310      *
311      * @throws IllegalStateException if the Cipher was not initialized or a
312      * opmode does not match.
313      * @return the input block size (in bytes).
314      */
315     protected int engineGetBlockSize() {
316         return this.cipher.getBlockSize();
317     }
318 
319     /**
320      * Returns the length in bytes that an output buffer would need to be in
321      * order to hold the result of the next update or doFinal operation, given
322      * the input length inputLen (in bytes).
323      *
324      * @param inputLen the input length in bytes.
325      * @throws IllegalStateException if the Cipher was not initialized or a
326      * opmode does not match.
327      * @return the reqired output buffer size in bytes.
328      */
329     protected int engineGetOutputSize(int inputLen) {
330         return this.cipher.getOutputSize(inputLen);
331     }
332 
333     /**
334      * Returns the key size of the given key object in bit. This method will be
335      * invoked trough the JCE before engineInit is invoked.
336      *
337      * @param key the key object.
338      * @throws InvalidKeyException if key is invalid.
339      * @return the key size of the given key object.
340      */
341     protected int engineGetKeySize(Key key) throws InvalidKeyException {
342         return this.cipher.getKeySize(key);
343     }    
344     
345     /** 
346      * Returns the parameters used with this cipher.
347      *
348      * @throws IllegalStateException if the Cipher was not initialized.
349      * @return the parameters used with this cipher,
350      * or null if this cipher does not use
351      * any parameters.
352      */
353     protected AlgorithmParameters engineGetParameters() {
354         return this.cipher.getParameters();
355     }
356     
357     /**
358      * Returns the initialization vector (IV) in a new buffer.
359      *
360      * @throws IllegalStateException if the Cipher was not initialized.
361      * @return the initialization vector in a new buffer,
362      * or null if the underlying algorithm does not
363      * use an IV, or if the IV has not yet been set.
364      */
365     protected byte[] engineGetIV() {
366         return this.cipher.getIV();
367     }
368 
369 
370 }
371