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 
  26 package com.sun.crypto.provider;
  27 
  28 import java.security.*;
  29 import java.security.spec.*;
  30 import sun.security.util.*;
  31 import javax.crypto.*;
  32 import javax.crypto.spec.*;
  33 import 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 
  53 public 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 padding 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 }