1/*
2 * Copyright (c) 1998, 2009, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26package com.sun.crypto.provider;
27
28import java.security.*;
29import java.security.spec.*;
30import sun.security.util.*;
31import javax.crypto.*;
32import javax.crypto.spec.*;
33import javax.crypto.BadPaddingException;
34
35/**
36 * This class implements the Blowfish algorithm in its various modes
37 * (<code>ECB</code>, <code>CFB</code>, <code>OFB</code>, <code>CBC</code>,
38 * <code>PCBC</code>) and padding schemes (<code>PKCS5Padding</code>,
39 * <code>NoPadding</code>, <code>ISO10126Padding</code>).
40 *
41 * <p> Blowfish is a 64-bit block cipher with a variable-length key.
42 *
43 * @author Jan Luehe
44 *
45 *
46 * @see BlowfishCrypt
47 * @see CipherBlockChaining
48 * @see ElectronicCodeBook
49 * @see CipherFeedback
50 * @see OutputFeedback
51 */
52
53public final class BlowfishCipher extends CipherSpi {
54
55    /*
56     * internal CipherCore object which does the real work.
57     */
58    private CipherCore core = null;
59
60    /**
61     * Creates an instance of Blowfish cipher with default ECB mode and
62     * PKCS5Padding.
63     */
64    public BlowfishCipher() {
65        core = new CipherCore(new BlowfishCrypt(),
66                              BlowfishConstants.BLOWFISH_BLOCK_SIZE);
67    }
68
69    /**
70     * Sets the mode of this cipher.
71     *
72     * @param mode the cipher mode
73     *
74     * @exception NoSuchAlgorithmException if the requested cipher mode does
75     * not exist
76     */
77    protected void engineSetMode(String mode)
78        throws NoSuchAlgorithmException {
79        core.setMode(mode);
80    }
81
82    /**
83     * Sets the padding mechanism of this cipher.
84     *
85     * @param paddingScheme the padding mechanism
86     *
87     * @exception NoSuchPaddingException if the requested padding mechanism
88     * does not exist
89     */
90    protected void engineSetPadding(String paddingScheme)
91        throws NoSuchPaddingException {
92        core.setPadding(paddingScheme);
93    }
94
95    /**
96     * Returns the block size (in bytes).
97     *
98     * @return the block size (in bytes), or 0 if the underlying algorithm is
99     * not a block cipher
100     */
101    protected int engineGetBlockSize() {
102        return BlowfishConstants.BLOWFISH_BLOCK_SIZE;
103    }
104
105    /**
106     * Returns the length in bytes that an output buffer would need to be in
107     * order to hold the result of the next <code>update</code> or
108     * <code>doFinal</code> operation, given the input length
109     * <code>inputLen</code> (in bytes).
110     *
111     * <p>This call takes into account any unprocessed (buffered) data from a
112     * previous <code>update</code> call, and padding.
113     *
114     * <p>The actual output length of the next <code>update</code> or
115     * <code>doFinal</code> call may be smaller than the length returned by
116     * this method.
117     *
118     * @param inputLen the input length (in bytes)
119     *
120     * @return the required output buffer size (in bytes)
121     */
122    protected int engineGetOutputSize(int inputLen) {
123        return core.getOutputSize(inputLen);
124    }
125
126    /**
127     * Returns the initialization vector (IV) in a new buffer.
128     *
129     * <p>This is useful in the case where a random IV has been created
130     * (see <a href = "#init">init</a>),
131     * or in the context of password-based encryption or
132     * decryption, where the IV is derived from a user-supplied password.
133     *
134     * @return the initialization vector in a new buffer, or null if the
135     * underlying algorithm does not use an IV, or if the IV has not yet
136     * been set.
137     */
138    protected byte[] engineGetIV() {
139        return core.getIV();
140    }
141
142    /**
143     * Returns the parameters used with this cipher.
144     *
145     * <p>The returned parameters may be the same that were used to initialize
146     * this cipher, or may contain the default set of parameters or a set of
147     * randomly generated parameters used by the underlying cipher
148     * implementation (provided that the underlying cipher implementation
149     * uses a default set of parameters or creates new parameters if it needs
150     * parameters but was not initialized with any).
151     *
152     * @return the parameters used with this cipher, or null if this cipher
153     * does not use any parameters.
154     */
155    protected AlgorithmParameters engineGetParameters() {
156        return core.getParameters("Blowfish");
157    }
158
159    /**
160     * Initializes this cipher with a key and a source of randomness.
161     *
162     * <p>The cipher is initialized for one of the following four operations:
163     * encryption, decryption, key wrapping or key unwrapping, depending on
164     * the value of <code>opmode</code>.
165     *
166     * <p>If this cipher requires an initialization vector (IV), it will get
167     * it from <code>random</code>.
168     * This behaviour should only be used in encryption or key wrapping
169     * mode, however.
170     * When initializing a cipher that requires an IV for decryption or
171     * key unwrapping, the IV
172     * (same IV that was used for encryption or key wrapping) must be provided
173     * explicitly as a
174     * parameter, in order to get the correct result.
175     *
176     * <p>This method also cleans existing buffer and other related state
177     * information.
178     *
179     * @param opmode the operation mode of this cipher (this is one of
180     * the following:
181     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
182     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
183     * @param key the secret key
184     * @param random the source of randomness
185     *
186     * @exception InvalidKeyException if the given key is inappropriate for
187     * initializing this cipher
188     */
189    protected void engineInit(int opmode, Key key, SecureRandom random)
190        throws InvalidKeyException {
191        core.init(opmode, key, random);
192    }
193
194    /**
195     * Initializes this cipher with a key, a set of
196     * algorithm parameters, and a source of randomness.
197     *
198     * <p>The cipher is initialized for one of the following four operations:
199     * encryption, decryption, key wrapping or key unwrapping, depending on
200     * the value of <code>opmode</code>.
201     *
202     * <p>If this cipher (including its underlying feedback or padding scheme)
203     * requires any random bytes, it will get them from <code>random</code>.
204     *
205     * @param opmode the operation mode of this cipher (this is one of
206     * the following:
207     * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
208     * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
209     * @param key the encryption key
210     * @param params the algorithm parameters
211     * @param random the source of randomness
212     *
213     * @exception InvalidKeyException if the given key is inappropriate for
214     * initializing this cipher
215     * @exception InvalidAlgorithmParameterException if the given algorithm
216     * parameters are inappropriate for this cipher
217     */
218    protected void engineInit(int opmode, Key key,
219                              AlgorithmParameterSpec params,
220                              SecureRandom random)
221        throws InvalidKeyException, InvalidAlgorithmParameterException {
222        core.init(opmode, key, params, random);
223    }
224
225    protected void engineInit(int opmode, Key key,
226                              AlgorithmParameters params,
227                              SecureRandom random)
228        throws InvalidKeyException, InvalidAlgorithmParameterException {
229        core.init(opmode, key, params, random);
230    }
231
232    /**
233     * Continues a multiple-part encryption or decryption operation
234     * (depending on how this cipher was initialized), processing another data
235     * part.
236     *
237     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
238     * buffer, starting at <code>inputOffset</code>, are processed, and the
239     * result is stored in a new buffer.
240     *
241     * @param input the input buffer
242     * @param inputOffset the offset in <code>input</code> where the input
243     * starts
244     * @param inputLen the input length
245     *
246     * @return the new buffer with the result
247     *
248     * @exception IllegalStateException if this cipher is in a wrong state
249     * (e.g., has not been initialized)
250     */
251    protected byte[] engineUpdate(byte[] input, int inputOffset,
252                                  int inputLen) {
253        return core.update(input, inputOffset, inputLen);
254    }
255
256    /**
257     * Continues a multiple-part encryption or decryption operation
258     * (depending on how this cipher was initialized), processing another data
259     * part.
260     *
261     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
262     * buffer, starting at <code>inputOffset</code>, are processed, and the
263     * result is stored in the <code>output</code> buffer, starting at
264     * <code>outputOffset</code>.
265     *
266     * @param input the input buffer
267     * @param inputOffset the offset in <code>input</code> where the input
268     * starts
269     * @param inputLen the input length
270     * @param output the buffer for the result
271     * @param outputOffset the offset in <code>output</code> where the result
272     * is stored
273     *
274     * @return the number of bytes stored in <code>output</code>
275     *
276     * @exception ShortBufferException if the given output buffer is too small
277     * to hold the result
278     */
279    protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
280                               byte[] output, int outputOffset)
281        throws ShortBufferException {
282        return core.update(input, inputOffset, inputLen, output,
283                           outputOffset);
284    }
285
286    /**
287     * Encrypts or decrypts data in a single-part operation,
288     * or finishes a multiple-part operation.
289     * The data is encrypted or decrypted, depending on how this cipher was
290     * initialized.
291     *
292     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
293     * buffer, starting at <code>inputOffset</code>, and any input bytes that
294     * may have been buffered during a previous <code>update</code> operation,
295     * are processed, with padding (if requested) being applied.
296     * The result is stored in a new buffer.
297     *
298     * <p>The cipher is reset to its initial state (uninitialized) after this
299     * call.
300     *
301     * @param input the input buffer
302     * @param inputOffset the offset in <code>input</code> where the input
303     * starts
304     * @param inputLen the input length
305     *
306     * @return the new buffer with the result
307     *
308     * @exception IllegalBlockSizeException if this cipher is a block cipher,
309     * no padding has been requested (only in encryption mode), and the total
310     * input length of the data processed by this cipher is not a multiple of
311     * block size
312     * @exception BadPaddingException if this cipher is in decryption mode,
313     * and (un)padding has been requested, but the decrypted data is not
314     * bounded by the appropriate padding bytes
315     */
316    protected byte[] engineDoFinal(byte[] input, int inputOffset,
317                                   int inputLen)
318        throws IllegalBlockSizeException, BadPaddingException {
319        return core.doFinal(input, inputOffset, inputLen);
320    }
321
322    /**
323     * Encrypts or decrypts data in a single-part operation,
324     * or finishes a multiple-part operation.
325     * The data is encrypted or decrypted, depending on how this cipher was
326     * initialized.
327     *
328     * <p>The first <code>inputLen</code> bytes in the <code>input</code>
329     * buffer, starting at <code>inputOffset</code>, and any input bytes that
330     * may have been buffered during a previous <code>update</code> operation,
331     * are processed, with padding (if requested) being applied.
332     * The result is stored in the <code>output</code> buffer, starting at
333     * <code>outputOffset</code>.
334     *
335     * <p>The cipher is reset to its initial state (uninitialized) after this
336     * call.
337     *
338     * @param input the input buffer
339     * @param inputOffset the offset in <code>input</code> where the input
340     * starts
341     * @param inputLen the input length
342     * @param output the buffer for the result
343     * @param outputOffset the offset in <code>output</code> where the result
344     * is stored
345     *
346     * @return the number of bytes stored in <code>output</code>
347     *
348     * @exception IllegalBlockSizeException if this cipher is a block cipher,
349     * no padding has been requested (only in encryption mode), and the total
350     * input length of the data processed by this cipher is not a multiple of
351     * block size
352     * @exception ShortBufferException if the given output buffer is too small
353     * to hold the result
354     * @exception BadPaddingException if this cipher is in decryption mode,
355     * and (un)padding has been requested, but the decrypted data is not
356     * bounded by the appropriate padding bytes
357     */
358    protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
359                                byte[] output, int outputOffset)
360        throws IllegalBlockSizeException, ShortBufferException,
361               BadPaddingException {
362        return core.doFinal(input, inputOffset, inputLen, output,
363                            outputOffset);
364    }
365
366    /**
367     *  Returns the key size of the given key object.
368     *
369     * @param key the key object.
370     *
371     * @return the key size of the given key object.
372     *
373     * @exception InvalidKeyException if <code>key</code> is invalid.
374     */
375    protected int engineGetKeySize(Key key) throws InvalidKeyException {
376        return (key.getEncoded().length * 8);
377    }
378
379    /**
380     * Wrap a key.
381     *
382     * @param key the key to be wrapped.
383     *
384     * @return the wrapped key.
385     *
386     * @exception IllegalBlockSizeException if this cipher is a block
387     * cipher, no padding has been requested, and the length of the
388     * encoding of the key to be wrapped is not a
389     * multiple of the block size.
390     *
391     * @exception InvalidKeyException if it is impossible or unsafe to
392     * wrap the key with this cipher (e.g., a hardware protected key is
393     * being passed to a software only cipher).
394     */
395    protected byte[] engineWrap(Key key)
396        throws IllegalBlockSizeException, InvalidKeyException {
397        return core.wrap(key);
398    }
399
400    /**
401     * Unwrap a previously wrapped key.
402     *
403     * @param wrappedKey the key to be unwrapped.
404     *
405     * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
406     *
407     * @param wrappedKeyType the type of the wrapped key.
408     * This is one of <code>Cipher.SECRET_KEY</code>,
409     * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
410     *
411     * @return the unwrapped key.
412     *
413     * @exception NoSuchAlgorithmException if no installed providers
414     * can create keys of type <code>wrappedKeyType</code> for the
415     * <code>wrappedKeyAlgorithm</code>.
416     *
417     * @exception InvalidKeyException if <code>wrappedKey</code> does not
418     * represent a wrapped key of type <code>wrappedKeyType</code> for
419     * the <code>wrappedKeyAlgorithm</code>.
420     */
421    protected Key engineUnwrap(byte[] wrappedKey,
422                                     String wrappedKeyAlgorithm,
423                                     int wrappedKeyType)
424        throws InvalidKeyException, NoSuchAlgorithmException {
425        return core.unwrap(wrappedKey, wrappedKeyAlgorithm,
426                           wrappedKeyType);
427    }
428}
429