Save This Page
Home » openjdk-7 » com.sun.crypto » provider » [javadoc | source]
    1   /*
    2    * Copyright (c) 1997, 2007, 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.InvalidKeyException;
   29   
   30   /**
   31    * This class represents ciphers in cipher block chaining (CBC) mode.
   32    *
   33    * <p>This mode is implemented independently of a particular cipher.
   34    * Ciphers to which this mode should apply (e.g., DES) must be
   35    * <i>plugged-in</i> using the constructor.
   36    *
   37    * <p>NOTE: This class does not deal with buffering or padding.
   38    *
   39    * @author Gigi Ankeny
   40    */
   41   
   42   class CipherBlockChaining extends FeedbackCipher  {
   43   
   44       /*
   45        * random bytes that are initialized with iv
   46        */
   47       protected byte[] r;
   48   
   49       /*
   50        * output buffer
   51        */
   52       private byte[] k;
   53   
   54       // variables for save/restore calls
   55       private byte[] rSave = null;
   56   
   57       CipherBlockChaining(SymmetricCipher embeddedCipher) {
   58           super(embeddedCipher);
   59           k = new byte[blockSize];
   60           r = new byte[blockSize];
   61       }
   62   
   63       /**
   64        * Gets the name of this feedback mode.
   65        *
   66        * @return the string <code>CBC</code>
   67        */
   68       String getFeedback() {
   69           return "CBC";
   70       }
   71   
   72       /**
   73        * Initializes the cipher in the specified mode with the given key
   74        * and iv.
   75        *
   76        * @param decrypting flag indicating encryption or decryption
   77        * @param algorithm the algorithm name
   78        * @param key the key
   79        * @param iv the iv
   80        *
   81        * @exception InvalidKeyException if the given key is inappropriate for
   82        * initializing this cipher
   83        */
   84       void init(boolean decrypting, String algorithm, byte[] key, byte[] iv)
   85               throws InvalidKeyException {
   86           if ((key == null) || (iv == null) || (iv.length != blockSize)) {
   87               throw new InvalidKeyException("Internal error");
   88           }
   89           this.iv = iv;
   90           reset();
   91           embeddedCipher.init(decrypting, algorithm, key);
   92       }
   93   
   94       /**
   95        * Resets the iv to its original value.
   96        * This is used when doFinal is called in the Cipher class, so that the
   97        * cipher can be reused (with its original iv).
   98        */
   99       void reset() {
  100           System.arraycopy(iv, 0, r, 0, blockSize);
  101       }
  102   
  103       /**
  104        * Save the current content of this cipher.
  105        */
  106       void save() {
  107           if (rSave == null) {
  108               rSave = new byte[blockSize];
  109           }
  110           System.arraycopy(r, 0, rSave, 0, blockSize);
  111       }
  112   
  113       /**
  114        * Restores the content of this cipher to the previous saved one.
  115        */
  116       void restore() {
  117           System.arraycopy(rSave, 0, r, 0, blockSize);
  118       }
  119   
  120       /**
  121        * Performs encryption operation.
  122        *
  123        * <p>The input plain text <code>plain</code>, starting at
  124        * <code>plainOffset</code> and ending at
  125        * <code>(plainOffset + len - 1)</code>, is encrypted.
  126        * The result is stored in <code>cipher</code>, starting at
  127        * <code>cipherOffset</code>.
  128        *
  129        * <p>It is the application's responsibility to make sure that
  130        * <code>plainLen</code> is a multiple of the embedded cipher's block size,
  131        * as any excess bytes are ignored.
  132        *
  133        * @param plain the buffer with the input data to be encrypted
  134        * @param plainOffset the offset in <code>plain</code>
  135        * @param plainLen the length of the input data
  136        * @param cipher the buffer for the result
  137        * @param cipherOffset the offset in <code>cipher</code>
  138        */
  139       void encrypt(byte[] plain, int plainOffset, int plainLen,
  140                    byte[] cipher, int cipherOffset)
  141       {
  142           int i;
  143           int endIndex = plainOffset + plainLen;
  144   
  145           for (; plainOffset < endIndex;
  146                plainOffset+=blockSize, cipherOffset += blockSize) {
  147               for (i=0; i<blockSize; i++) {
  148                   k[i] = (byte)(plain[i+plainOffset] ^ r[i]);
  149               }
  150               embeddedCipher.encryptBlock(k, 0, cipher, cipherOffset);
  151               System.arraycopy(cipher, cipherOffset, r, 0, blockSize);
  152           }
  153       }
  154   
  155       /**
  156        * Performs decryption operation.
  157        *
  158        * <p>The input cipher text <code>cipher</code>, starting at
  159        * <code>cipherOffset</code> and ending at
  160        * <code>(cipherOffset + len - 1)</code>, is decrypted.
  161        * The result is stored in <code>plain</code>, starting at
  162        * <code>plainOffset</code>.
  163        *
  164        * <p>It is the application's responsibility to make sure that
  165        * <code>cipherLen</code> is a multiple of the embedded cipher's block
  166        * size, as any excess bytes are ignored.
  167        *
  168        * <p>It is also the application's responsibility to make sure that
  169        * <code>init</code> has been called before this method is called.
  170        * (This check is omitted here, to avoid double checking.)
  171        *
  172        * @param cipher the buffer with the input data to be decrypted
  173        * @param cipherOffset the offset in <code>cipherOffset</code>
  174        * @param cipherLen the length of the input data
  175        * @param plain the buffer for the result
  176        * @param plainOffset the offset in <code>plain</code>
  177        *
  178        * @exception IllegalBlockSizeException if input data whose length does
  179        * not correspond to the embedded cipher's block size is passed to the
  180        * embedded cipher
  181        */
  182       void decrypt(byte[] cipher, int cipherOffset, int cipherLen,
  183                    byte[] plain, int plainOffset)
  184       {
  185           int i;
  186           byte[] cipherOrig=null;
  187           int endIndex = cipherOffset + cipherLen;
  188   
  189           if (cipher==plain && (cipherOffset >= plainOffset)
  190               && ((cipherOffset - plainOffset) < blockSize)) {
  191               // Save the original ciphertext blocks, so they can be
  192               // stored in the feedback register "r".
  193               // This is necessary because in this constellation, a
  194               // ciphertext block (or parts of it) will be overridden by
  195               // the plaintext result.
  196               cipherOrig = (byte[])cipher.clone();
  197           }
  198   
  199           for (; cipherOffset < endIndex;
  200                cipherOffset += blockSize, plainOffset += blockSize) {
  201               embeddedCipher.decryptBlock(cipher, cipherOffset, k, 0);
  202               for (i = 0; i < blockSize; i++) {
  203                   plain[i+plainOffset] = (byte)(k[i] ^ r[i]);
  204               }
  205               if (cipherOrig==null) {
  206                   System.arraycopy(cipher, cipherOffset, r, 0, blockSize);
  207               } else {
  208                   System.arraycopy(cipherOrig, cipherOffset, r, 0, blockSize);
  209               }
  210           }
  211       }
  212   }

Save This Page
Home » openjdk-7 » com.sun.crypto » provider » [javadoc | source]