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-feedback (CFB) 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   final class CipherFeedback extends FeedbackCipher {
   43   
   44       /*
   45        * encrypt/decrypt output buffer
   46        */
   47       private final byte[] k;
   48   
   49       /*
   50        * register value, initialized with iv
   51        */
   52       private final byte[] register;
   53   
   54       /*
   55        * number of bytes for each stream unit, defaults to the blocksize
   56        * of the embedded cipher
   57        */
   58       private int numBytes;
   59   
   60       // variables for save/restore calls
   61       private byte[] registerSave = null;
   62   
   63       CipherFeedback(SymmetricCipher embeddedCipher, int numBytes) {
   64           super(embeddedCipher);
   65           if (numBytes > blockSize) {
   66               numBytes = blockSize;
   67           }
   68           this.numBytes = numBytes;
   69           k = new byte[blockSize];
   70           register = new byte[blockSize];
   71       }
   72   
   73       /**
   74        * Gets the name of this feedback mode.
   75        *
   76        * @return the string <code>CFB</code>
   77        */
   78       String getFeedback() {
   79           return "CFB";
   80       }
   81   
   82       /**
   83        * Initializes the cipher in the specified mode with the given key
   84        * and iv.
   85        *
   86        * @param decrypting flag indicating encryption or decryption
   87        * @param algorithm the algorithm name
   88        * @param key the key
   89        * @param iv the iv
   90        *
   91        * @exception InvalidKeyException if the given key is inappropriate for
   92        * initializing this cipher
   93        */
   94       void init(boolean decrypting, String algorithm, byte[] key, byte[] iv)
   95               throws InvalidKeyException {
   96           if ((key == null) || (iv == null) || (iv.length != blockSize)) {
   97               throw new InvalidKeyException("Internal error");
   98           }
   99           this.iv = iv;
  100           reset();
  101           // always encrypt mode for embedded cipher
  102           embeddedCipher.init(false, algorithm, key);
  103       }
  104   
  105       /**
  106        * Resets the iv to its original value.
  107        * This is used when doFinal is called in the Cipher class, so that the
  108        * cipher can be reused (with its original iv).
  109        */
  110       void reset() {
  111           System.arraycopy(iv, 0, register, 0, blockSize);
  112       }
  113   
  114       /**
  115        * Save the current content of this cipher.
  116        */
  117       void save() {
  118           if (registerSave == null) {
  119               registerSave = new byte[blockSize];
  120           }
  121           System.arraycopy(register, 0, registerSave, 0, blockSize);
  122       }
  123   
  124       /**
  125        * Restores the content of this cipher to the previous saved one.
  126        */
  127       void restore() {
  128           System.arraycopy(registerSave, 0, register, 0, blockSize);
  129       }
  130   
  131       /**
  132        * Performs encryption operation.
  133        *
  134        * <p>The input plain text <code>plain</code>, starting at
  135        * <code>plainOffset</code> and ending at
  136        * <code>(plainOffset + len - 1)</code>, is encrypted.
  137        * The result is stored in <code>cipher</code>, starting at
  138        * <code>cipherOffset</code>.
  139        *
  140        * <p>It is the application's responsibility to make sure that
  141        * <code>plainLen</code> is a multiple of the stream unit size
  142        * <code>numBytes</code>, as any excess bytes are ignored.
  143        *
  144        * <p>It is also the application's responsibility to make sure that
  145        * <code>init</code> has been called before this method is called.
  146        * (This check is omitted here, to avoid double checking.)
  147        *
  148        * @param plain the buffer with the input data to be encrypted
  149        * @param plainOffset the offset in <code>plain</code>
  150        * @param plainLen the length of the input data
  151        * @param cipher the buffer for the result
  152        * @param cipherOffset the offset in <code>cipher</code>
  153        */
  154       void encrypt(byte[] plain, int plainOffset, int plainLen,
  155                           byte[] cipher, int cipherOffset)
  156       {
  157           int i, len;
  158           len = blockSize - numBytes;
  159           int loopCount = plainLen / numBytes;
  160           int oddBytes = plainLen % numBytes;
  161   
  162           if (len == 0) {
  163               for (; loopCount > 0 ;
  164                    plainOffset += numBytes, cipherOffset += numBytes,
  165                    loopCount--) {
  166                   embeddedCipher.encryptBlock(register, 0, k, 0);
  167                   for (i = 0; i < blockSize; i++)
  168                       register[i] = cipher[i+cipherOffset] =
  169                           (byte)(k[i] ^ plain[i+plainOffset]);
  170               }
  171               if (oddBytes > 0) {
  172                   embeddedCipher.encryptBlock(register, 0, k, 0);
  173                   for (i=0; i<oddBytes; i++)
  174                       register[i] = cipher[i+cipherOffset] =
  175                           (byte)(k[i] ^ plain[i+plainOffset]);
  176               }
  177           } else {
  178               for (; loopCount > 0 ;
  179                    plainOffset += numBytes, cipherOffset += numBytes,
  180                    loopCount--) {
  181                   embeddedCipher.encryptBlock(register, 0, k, 0);
  182                   System.arraycopy(register, numBytes, register, 0, len);
  183                   for (i=0; i<numBytes; i++)
  184                       register[i+len] = cipher[i+cipherOffset] =
  185                           (byte)(k[i] ^ plain[i+plainOffset]);
  186   
  187               }
  188               if (oddBytes != 0) {
  189                   embeddedCipher.encryptBlock(register, 0, k, 0);
  190                   System.arraycopy(register, numBytes, register, 0, len);
  191                   for (i=0; i<oddBytes; i++) {
  192                       register[i+len] = cipher[i+cipherOffset] =
  193                           (byte)(k[i] ^ plain[i+plainOffset]);
  194                   }
  195               }
  196           }
  197       }
  198   
  199       /**
  200        * Performs decryption operation.
  201        *
  202        * <p>The input cipher text <code>cipher</code>, starting at
  203        * <code>cipherOffset</code> and ending at
  204        * <code>(cipherOffset + len - 1)</code>, is decrypted.
  205        * The result is stored in <code>plain</code>, starting at
  206        * <code>plainOffset</code>.
  207        *
  208        * <p>It is the application's responsibility to make sure that
  209        * <code>cipherLen</code> is a multiple of the stream unit size
  210        * <code>numBytes</code>, as any excess bytes are ignored.
  211        *
  212        * <p>It is also the application's responsibility to make sure that
  213        * <code>init</code> has been called before this method is called.
  214        * (This check is omitted here, to avoid double checking.)
  215        *
  216        * @param cipher the buffer with the input data to be decrypted
  217        * @param cipherOffset the offset in <code>cipherOffset</code>
  218        * @param cipherLen the length of the input data
  219        * @param plain the buffer for the result
  220        * @param plainOffset the offset in <code>plain</code>
  221        */
  222       void decrypt(byte[] cipher, int cipherOffset, int cipherLen,
  223                           byte[] plain, int plainOffset)
  224       {
  225           int i, len;
  226           len = blockSize - numBytes;
  227           int loopCount = cipherLen / numBytes;
  228           int oddBytes = cipherLen % numBytes;
  229   
  230           if (len == 0) {
  231               for (; loopCount > 0;
  232                    plainOffset += numBytes, cipherOffset += numBytes,
  233                    loopCount--) {
  234                   embeddedCipher.encryptBlock(register, 0, k, 0);
  235                   for (i = 0; i < blockSize; i++) {
  236                       register[i] = cipher[i+cipherOffset];
  237                       plain[i+plainOffset]
  238                           = (byte)(cipher[i+cipherOffset] ^ k[i]);
  239                   }
  240               }
  241               if (oddBytes > 0) {
  242                   embeddedCipher.encryptBlock(register, 0, k, 0);
  243                   for (i=0; i<oddBytes; i++) {
  244                       register[i] = cipher[i+cipherOffset];
  245                       plain[i+plainOffset]
  246                           = (byte)(cipher[i+cipherOffset] ^ k[i]);
  247                   }
  248               }
  249           } else {
  250               for (; loopCount > 0;
  251                    plainOffset += numBytes, cipherOffset += numBytes,
  252                    loopCount--) {
  253                   embeddedCipher.encryptBlock(register, 0, k, 0);
  254                   System.arraycopy(register, numBytes, register, 0, len);
  255                   for (i=0; i<numBytes; i++) {
  256                       register[i+len] = cipher[i+cipherOffset];
  257                       plain[i+plainOffset]
  258                           = (byte)(cipher[i+cipherOffset] ^ k[i]);
  259                   }
  260               }
  261               if (oddBytes != 0) {
  262                   embeddedCipher.encryptBlock(register, 0, k, 0);
  263                   System.arraycopy(register, numBytes, register, 0, len);
  264                   for (i=0; i<oddBytes; i++) {
  265                       register[i+len] = cipher[i+cipherOffset];
  266                       plain[i+plainOffset]
  267                           = (byte)(cipher[i+cipherOffset] ^ k[i]);
  268                   }
  269               }
  270           }
  271       }
  272   }

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