Save This Page
Home » openjdk-7 » com.sun.crypto » provider » [javadoc | source]
    1   /*
    2    * Copyright (c) 2004, 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 javax.crypto.IllegalBlockSizeException;
   29   import javax.crypto.ShortBufferException;
   30   
   31   /**
   32    * This class represents ciphers in cipher text stealing (CTS) mode.
   33    * <br>CTS provides a way to allow block ciphers to operate on partial
   34    * blocks without padding, and all bits of the message go through
   35    * the encryption algorithm, rather than simply being XOR'd.
   36    * <br>More details can be found in RFC 2040 section 8 "Description
   37    * of RC5-CTS".
   38    *
   39    * <p>This mode is implemented independently of a particular cipher.
   40    * Ciphers to which this mode should apply (e.g., DES) must be
   41    * <i>plugged-in</i> using the constructor.
   42    *
   43    * <p>NOTE#1: CTS requires the input data to be at least one block
   44    * long. Thus, callers of this class has to buffer the input data
   45    * to make sure the input data passed to encryptFinal()/decryptFinal()
   46    * is not shorter than a block.
   47    * <p>NOTE#2: This class does not deal with buffering or padding
   48    * just like all other cipher mode implementations.
   49    *
   50    * @author Valerie Peng
   51    */
   52   
   53   final class CipherTextStealing extends CipherBlockChaining {
   54   
   55       CipherTextStealing(SymmetricCipher embeddedCipher) {
   56           super(embeddedCipher);
   57       }
   58   
   59       /**
   60        * Gets the name of this feedback mode.
   61        *
   62        * @return the string <code>CBC</code>
   63        */
   64       String getFeedback() {
   65           return "CTS";
   66       }
   67   
   68       /**
   69        * Performs the last encryption operation.
   70        *
   71        * <p>The input plain text <code>plain</code>, starting at
   72        * <code>plainOffset</code> and ending at
   73        * <code>(plainOffset + len - 1)</code>, is encrypted.
   74        * The result is stored in <code>cipher</code>, starting at
   75        * <code>cipherOffset</code>.
   76        *
   77        * <p>It is the application's responsibility to make sure that
   78        * <code>plainLen</code> is a multiple of the embedded cipher's block size,
   79        * as any excess bytes are ignored.
   80        *
   81        * @param plain the buffer with the input data to be encrypted
   82        * @param plainOffset the offset in <code>plain</code>
   83        * @param plainLen the length of the input data
   84        * @param cipher the buffer for the result
   85        * @param cipherOffset the offset in <code>cipher</code>
   86        */
   87       void encryptFinal(byte[] plain, int plainOffset, int plainLen,
   88                         byte[] cipher, int cipherOffset)
   89           throws IllegalBlockSizeException {
   90   
   91           if (plainLen < blockSize) {
   92               throw new IllegalBlockSizeException("input is too short!");
   93           } else if (plainLen == blockSize) {
   94               encrypt(plain, plainOffset, plainLen, cipher, cipherOffset);
   95           } else {
   96               // number of bytes in the last block
   97               int nLeft = plainLen % blockSize;
   98               if (nLeft == 0) {
   99                   encrypt(plain, plainOffset, plainLen, cipher, cipherOffset);
  100                   // swap the last two blocks after encryption
  101                   int lastBlkIndex = cipherOffset + plainLen - blockSize;
  102                   int nextToLastBlkIndex = lastBlkIndex - blockSize;
  103                   byte[] tmp = new byte[blockSize];
  104                   System.arraycopy(cipher, lastBlkIndex, tmp, 0, blockSize);
  105                   System.arraycopy(cipher, nextToLastBlkIndex,
  106                                    cipher, lastBlkIndex, blockSize);
  107                   System.arraycopy(tmp, 0, cipher, nextToLastBlkIndex,
  108                                    blockSize);
  109               } else {
  110                   int newPlainLen = plainLen - (blockSize + nLeft);
  111                   if (newPlainLen > 0) {
  112                       encrypt(plain, plainOffset, newPlainLen, cipher,
  113                               cipherOffset);
  114                       plainOffset += newPlainLen;
  115                       cipherOffset += newPlainLen;
  116                   }
  117   
  118                   // Do final CTS step for last two blocks (the second of which
  119                   // may or may not be incomplete).
  120                   byte[] tmp = new byte[blockSize];
  121                   // now encrypt the next-to-last block
  122                   for (int i = 0; i < blockSize; i++) {
  123                       tmp[i] = (byte) (plain[plainOffset+i] ^ r[i]);
  124                   }
  125                   byte[] tmp2 = new byte[blockSize];
  126                   embeddedCipher.encryptBlock(tmp, 0, tmp2, 0);
  127                   System.arraycopy(tmp2, 0, cipher,
  128                                    cipherOffset+blockSize, nLeft);
  129                   // encrypt the last block
  130                   for (int i=0; i<nLeft; i++) {
  131                       tmp2[i] = (byte)
  132                           (plain[plainOffset+blockSize+i] ^ tmp2[i]);
  133                   }
  134                   embeddedCipher.encryptBlock(tmp2, 0, cipher, cipherOffset);
  135               }
  136           }
  137       }
  138   
  139       /**
  140        * Performs decryption operation.
  141        *
  142        * <p>The input cipher text <code>cipher</code>, starting at
  143        * <code>cipherOffset</code> and ending at
  144        * <code>(cipherOffset + len - 1)</code>, is decrypted.
  145        * The result is stored in <code>plain</code>, starting at
  146        * <code>plainOffset</code>.
  147        *
  148        * <p>It is the application's responsibility to make sure that
  149        * <code>cipherLen</code> is a multiple of the embedded cipher's block
  150        * size, as any excess bytes are ignored.
  151        *
  152        * <p>It is also the application's responsibility to make sure that
  153        * <code>init</code> has been called before this method is called.
  154        * (This check is omitted here, to avoid double checking.)
  155        *
  156        * @param cipher the buffer with the input data to be decrypted
  157        * @param cipherOffset the offset in <code>cipherOffset</code>
  158        * @param cipherLen the length of the input data
  159        * @param plain the buffer for the result
  160        * @param plainOffset the offset in <code>plain</code>
  161        */
  162       void decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
  163                         byte[] plain, int plainOffset)
  164           throws IllegalBlockSizeException {
  165           if (cipherLen < blockSize) {
  166               throw new IllegalBlockSizeException("input is too short!");
  167           } else if (cipherLen == blockSize) {
  168               decrypt(cipher, cipherOffset, cipherLen, plain, plainOffset);
  169           } else {
  170               // number of bytes in the last block
  171               int nLeft = cipherLen % blockSize;
  172               if (nLeft == 0) {
  173                   // swap the last two blocks before decryption
  174                   int lastBlkIndex = cipherOffset + cipherLen - blockSize;
  175                   int nextToLastBlkIndex =
  176                       cipherOffset + cipherLen - 2*blockSize;
  177                   byte[] tmp = new byte[2*blockSize];
  178                   System.arraycopy(cipher, lastBlkIndex, tmp, 0, blockSize);
  179                   System.arraycopy(cipher, nextToLastBlkIndex,
  180                                    tmp, blockSize, blockSize);
  181                   int cipherLen2 = cipherLen-2*blockSize;
  182                   decrypt(cipher, cipherOffset, cipherLen2, plain, plainOffset);
  183                   decrypt(tmp, 0, 2*blockSize, plain, plainOffset+cipherLen2);
  184               } else {
  185                   int newCipherLen = cipherLen-(blockSize+nLeft);
  186                   if (newCipherLen > 0) {
  187                       decrypt(cipher, cipherOffset, newCipherLen, plain,
  188                               plainOffset);
  189                       cipherOffset += newCipherLen;
  190                       plainOffset += newCipherLen;
  191                   }
  192                   // Do final CTS step for last two blocks (the second of which
  193                   // may or may not be incomplete).
  194   
  195                   // now decrypt the next-to-last block
  196                   byte[] tmp = new byte[blockSize];
  197                   embeddedCipher.decryptBlock(cipher, cipherOffset, tmp, 0);
  198                   for (int i = 0; i < nLeft; i++) {
  199                       plain[plainOffset+blockSize+i] =
  200                           (byte) (cipher[cipherOffset+blockSize+i] ^ tmp[i]);
  201                   }
  202   
  203                   // decrypt the last block
  204                   System.arraycopy(cipher, cipherOffset+blockSize, tmp, 0,
  205                                    nLeft);
  206                   embeddedCipher.decryptBlock(tmp, 0, plain, plainOffset);
  207                   //System.arraycopy(r, 0, tmp, 0, r.length);
  208                   for (int i=0; i<blockSize; i++) {
  209                       plain[plainOffset+i] = (byte)
  210                           (plain[plainOffset+i]^r[i]);
  211                   }
  212               }
  213           }
  214       }
  215   }

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