blob: 2b5f0fb73003e90774e0e6853517b524a194491f [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 * @exception SecurityException if this constructor fails to verify
65 * its own integrity
66 */
67 public BlowfishCipher() {
68 SunJCE.ensureIntegrity(getClass());
69 core = new CipherCore(new BlowfishCrypt(),
70 BlowfishConstants.BLOWFISH_BLOCK_SIZE);
71 }
72
73 /**
74 * Sets the mode of this cipher.
75 *
76 * @param mode the cipher mode
77 *
78 * @exception NoSuchAlgorithmException if the requested cipher mode does
79 * not exist
80 */
81 protected void engineSetMode(String mode)
82 throws NoSuchAlgorithmException {
83 core.setMode(mode);
84 }
85
86 /**
87 * Sets the padding mechanism of this cipher.
88 *
89 * @param padding the padding mechanism
90 *
91 * @exception NoSuchPaddingException if the requested padding mechanism
92 * does not exist
93 */
94 protected void engineSetPadding(String paddingScheme)
95 throws NoSuchPaddingException {
96 core.setPadding(paddingScheme);
97 }
98
99 /**
100 * Returns the block size (in bytes).
101 *
102 * @return the block size (in bytes), or 0 if the underlying algorithm is
103 * not a block cipher
104 */
105 protected int engineGetBlockSize() {
106 return BlowfishConstants.BLOWFISH_BLOCK_SIZE;
107 }
108
109 /**
110 * Returns the length in bytes that an output buffer would need to be in
111 * order to hold the result of the next <code>update</code> or
112 * <code>doFinal</code> operation, given the input length
113 * <code>inputLen</code> (in bytes).
114 *
115 * <p>This call takes into account any unprocessed (buffered) data from a
116 * previous <code>update</code> call, and padding.
117 *
118 * <p>The actual output length of the next <code>update</code> or
119 * <code>doFinal</code> call may be smaller than the length returned by
120 * this method.
121 *
122 * @param inputLen the input length (in bytes)
123 *
124 * @return the required output buffer size (in bytes)
125 */
126 protected int engineGetOutputSize(int inputLen) {
127 return core.getOutputSize(inputLen);
128 }
129
130 /**
131 * Returns the initialization vector (IV) in a new buffer.
132 *
133 * <p>This is useful in the case where a random IV has been created
134 * (see <a href = "#init">init</a>),
135 * or in the context of password-based encryption or
136 * decryption, where the IV is derived from a user-supplied password.
137 *
138 * @return the initialization vector in a new buffer, or null if the
139 * underlying algorithm does not use an IV, or if the IV has not yet
140 * been set.
141 */
142 protected byte[] engineGetIV() {
143 return core.getIV();
144 }
145
146 /**
147 * Returns the parameters used with this cipher.
148 *
149 * <p>The returned parameters may be the same that were used to initialize
150 * this cipher, or may contain the default set of parameters or a set of
151 * randomly generated parameters used by the underlying cipher
152 * implementation (provided that the underlying cipher implementation
153 * uses a default set of parameters or creates new parameters if it needs
154 * parameters but was not initialized with any).
155 *
156 * @return the parameters used with this cipher, or null if this cipher
157 * does not use any parameters.
158 */
159 protected AlgorithmParameters engineGetParameters() {
160 return core.getParameters("Blowfish");
161 }
162
163 /**
164 * Initializes this cipher with a key and a source of randomness.
165 *
166 * <p>The cipher is initialized for one of the following four operations:
167 * encryption, decryption, key wrapping or key unwrapping, depending on
168 * the value of <code>opmode</code>.
169 *
170 * <p>If this cipher requires an initialization vector (IV), it will get
171 * it from <code>random</code>.
172 * This behaviour should only be used in encryption or key wrapping
173 * mode, however.
174 * When initializing a cipher that requires an IV for decryption or
175 * key unwrapping, the IV
176 * (same IV that was used for encryption or key wrapping) must be provided
177 * explicitly as a
178 * parameter, in order to get the correct result.
179 *
180 * <p>This method also cleans existing buffer and other related state
181 * information.
182 *
183 * @param opmode the operation mode of this cipher (this is one of
184 * the following:
185 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
186 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
187 * @param key the secret key
188 * @param random the source of randomness
189 *
190 * @exception InvalidKeyException if the given key is inappropriate for
191 * initializing this cipher
192 */
193 protected void engineInit(int opmode, Key key, SecureRandom random)
194 throws InvalidKeyException {
195 core.init(opmode, key, random);
196 }
197
198 /**
199 * Initializes this cipher with a key, a set of
200 * algorithm parameters, and a source of randomness.
201 *
202 * <p>The cipher is initialized for one of the following four operations:
203 * encryption, decryption, key wrapping or key unwrapping, depending on
204 * the value of <code>opmode</code>.
205 *
206 * <p>If this cipher (including its underlying feedback or padding scheme)
207 * requires any random bytes, it will get them from <code>random</code>.
208 *
209 * @param opmode the operation mode of this cipher (this is one of
210 * the following:
211 * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
212 * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
213 * @param key the encryption key
214 * @param params the algorithm parameters
215 * @param random the source of randomness
216 *
217 * @exception InvalidKeyException if the given key is inappropriate for
218 * initializing this cipher
219 * @exception InvalidAlgorithmParameterException if the given algorithm
220 * parameters are inappropriate for this cipher
221 */
222 protected void engineInit(int opmode, Key key,
223 AlgorithmParameterSpec params,
224 SecureRandom random)
225 throws InvalidKeyException, InvalidAlgorithmParameterException {
226 core.init(opmode, key, params, random);
227 }
228
229 protected void engineInit(int opmode, Key key,
230 AlgorithmParameters params,
231 SecureRandom random)
232 throws InvalidKeyException, InvalidAlgorithmParameterException {
233 core.init(opmode, key, params, random);
234 }
235
236 /**
237 * Continues a multiple-part encryption or decryption operation
238 * (depending on how this cipher was initialized), processing another data
239 * part.
240 *
241 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
242 * buffer, starting at <code>inputOffset</code>, are processed, and the
243 * result is stored in a new buffer.
244 *
245 * @param input the input buffer
246 * @param inputOffset the offset in <code>input</code> where the input
247 * starts
248 * @param inputLen the input length
249 *
250 * @return the new buffer with the result
251 *
252 * @exception IllegalStateException if this cipher is in a wrong state
253 * (e.g., has not been initialized)
254 */
255 protected byte[] engineUpdate(byte[] input, int inputOffset,
256 int inputLen) {
257 return core.update(input, inputOffset, inputLen);
258 }
259
260 /**
261 * Continues a multiple-part encryption or decryption operation
262 * (depending on how this cipher was initialized), processing another data
263 * part.
264 *
265 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
266 * buffer, starting at <code>inputOffset</code>, are processed, and the
267 * result is stored in the <code>output</code> buffer, starting at
268 * <code>outputOffset</code>.
269 *
270 * @param input the input buffer
271 * @param inputOffset the offset in <code>input</code> where the input
272 * starts
273 * @param inputLen the input length
274 * @param output the buffer for the result
275 * @param outputOffset the offset in <code>output</code> where the result
276 * is stored
277 *
278 * @return the number of bytes stored in <code>output</code>
279 *
280 * @exception ShortBufferException if the given output buffer is too small
281 * to hold the result
282 */
283 protected int engineUpdate(byte[] input, int inputOffset, int inputLen,
284 byte[] output, int outputOffset)
285 throws ShortBufferException {
286 return core.update(input, inputOffset, inputLen, output,
287 outputOffset);
288 }
289
290 /**
291 * Encrypts or decrypts data in a single-part operation,
292 * or finishes a multiple-part operation.
293 * The data is encrypted or decrypted, depending on how this cipher was
294 * initialized.
295 *
296 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
297 * buffer, starting at <code>inputOffset</code>, and any input bytes that
298 * may have been buffered during a previous <code>update</code> operation,
299 * are processed, with padding (if requested) being applied.
300 * The result is stored in a new buffer.
301 *
302 * <p>The cipher is reset to its initial state (uninitialized) after this
303 * call.
304 *
305 * @param input the input buffer
306 * @param inputOffset the offset in <code>input</code> where the input
307 * starts
308 * @param inputLen the input length
309 *
310 * @return the new buffer with the result
311 *
312 * @exception IllegalBlockSizeException if this cipher is a block cipher,
313 * no padding has been requested (only in encryption mode), and the total
314 * input length of the data processed by this cipher is not a multiple of
315 * block size
316 * @exception BadPaddingException if this cipher is in decryption mode,
317 * and (un)padding has been requested, but the decrypted data is not
318 * bounded by the appropriate padding bytes
319 */
320 protected byte[] engineDoFinal(byte[] input, int inputOffset,
321 int inputLen)
322 throws IllegalBlockSizeException, BadPaddingException {
323 return core.doFinal(input, inputOffset, inputLen);
324 }
325
326 /**
327 * Encrypts or decrypts data in a single-part operation,
328 * or finishes a multiple-part operation.
329 * The data is encrypted or decrypted, depending on how this cipher was
330 * initialized.
331 *
332 * <p>The first <code>inputLen</code> bytes in the <code>input</code>
333 * buffer, starting at <code>inputOffset</code>, and any input bytes that
334 * may have been buffered during a previous <code>update</code> operation,
335 * are processed, with padding (if requested) being applied.
336 * The result is stored in the <code>output</code> buffer, starting at
337 * <code>outputOffset</code>.
338 *
339 * <p>The cipher is reset to its initial state (uninitialized) after this
340 * call.
341 *
342 * @param input the input buffer
343 * @param inputOffset the offset in <code>input</code> where the input
344 * starts
345 * @param inputLen the input length
346 * @param output the buffer for the result
347 * @param outputOffset the offset in <code>output</code> where the result
348 * is stored
349 *
350 * @return the number of bytes stored in <code>output</code>
351 *
352 * @exception IllegalBlockSizeException if this cipher is a block cipher,
353 * no padding has been requested (only in encryption mode), and the total
354 * input length of the data processed by this cipher is not a multiple of
355 * block size
356 * @exception ShortBufferException if the given output buffer is too small
357 * to hold the result
358 * @exception BadPaddingException if this cipher is in decryption mode,
359 * and (un)padding has been requested, but the decrypted data is not
360 * bounded by the appropriate padding bytes
361 */
362 protected int engineDoFinal(byte[] input, int inputOffset, int inputLen,
363 byte[] output, int outputOffset)
364 throws IllegalBlockSizeException, ShortBufferException,
365 BadPaddingException {
366 return core.doFinal(input, inputOffset, inputLen, output,
367 outputOffset);
368 }
369
370 /**
371 * Returns the key size of the given key object.
372 *
373 * @param key the key object.
374 *
375 * @return the key size of the given key object.
376 *
377 * @exception InvalidKeyException if <code>key</code> is invalid.
378 */
379 protected int engineGetKeySize(Key key) throws InvalidKeyException {
380 return (key.getEncoded().length * 8);
381 }
382
383 /**
384 * Wrap a key.
385 *
386 * @param key the key to be wrapped.
387 *
388 * @return the wrapped key.
389 *
390 * @exception IllegalBlockSizeException if this cipher is a block
391 * cipher, no padding has been requested, and the length of the
392 * encoding of the key to be wrapped is not a
393 * multiple of the block size.
394 *
395 * @exception InvalidKeyException if it is impossible or unsafe to
396 * wrap the key with this cipher (e.g., a hardware protected key is
397 * being passed to a software only cipher).
398 */
399 protected byte[] engineWrap(Key key)
400 throws IllegalBlockSizeException, InvalidKeyException {
401 return core.wrap(key);
402 }
403
404 /**
405 * Unwrap a previously wrapped key.
406 *
407 * @param wrappedKey the key to be unwrapped.
408 *
409 * @param wrappedKeyAlgorithm the algorithm the wrapped key is for.
410 *
411 * @param wrappedKeyType the type of the wrapped key.
412 * This is one of <code>Cipher.SECRET_KEY</code>,
413 * <code>Cipher.PRIVATE_KEY</code>, or <code>Cipher.PUBLIC_KEY</code>.
414 *
415 * @return the unwrapped key.
416 *
417 * @exception NoSuchAlgorithmException if no installed providers
418 * can create keys of type <code>wrappedKeyType</code> for the
419 * <code>wrappedKeyAlgorithm</code>.
420 *
421 * @exception InvalidKeyException if <code>wrappedKey</code> does not
422 * represent a wrapped key of type <code>wrappedKeyType</code> for
423 * the <code>wrappedKeyAlgorithm</code>.
424 */
425 protected Key engineUnwrap(byte[] wrappedKey,
426 String wrappedKeyAlgorithm,
427 int wrappedKeyType)
428 throws InvalidKeyException, NoSuchAlgorithmException {
429 return core.unwrap(wrappedKey, wrappedKeyAlgorithm,
430 wrappedKeyType);
431 }
432}