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 import java.security.ProviderException; 30 31 32 /** 33 * This class represents ciphers in cipher block chaining (CBC) mode. 34 * 35 * <p>This mode is implemented independently of a particular cipher. 36 * Ciphers to which this mode should apply (e.g., DES) must be 37 * <i>plugged-in</i> using the constructor. 38 * 39 * <p>NOTE: This class does not deal with buffering or padding. 40 * 41 * @author Gigi Ankeny 42 */ 43 44 class CipherBlockChaining extends FeedbackCipher { 45 46 /* 47 * random bytes that are initialized with iv 48 */ 49 protected byte[] r; 121 122 /** 123 * Performs encryption operation. 124 * 125 * <p>The input plain text <code>plain</code>, starting at 126 * <code>plainOffset</code> and ending at 127 * <code>(plainOffset + plainLen - 1)</code>, is encrypted. 128 * The result is stored in <code>cipher</code>, starting at 129 * <code>cipherOffset</code>. 130 * 131 * @param plain the buffer with the input data to be encrypted 132 * @param plainOffset the offset in <code>plain</code> 133 * @param plainLen the length of the input data 134 * @param cipher the buffer for the result 135 * @param cipherOffset the offset in <code>cipher</code> 136 * @exception ProviderException if <code>len</code> is not 137 * a multiple of the block size 138 * @return the length of the encrypted data 139 */ 140 int encrypt(byte[] plain, int plainOffset, int plainLen, 141 byte[] cipher, int cipherOffset) 142 { 143 if ((plainLen % blockSize) != 0) { 144 throw new ProviderException("Internal error in input buffering"); 145 } 146 int endIndex = plainOffset + plainLen; 147 148 for (; plainOffset < endIndex; 149 plainOffset+=blockSize, cipherOffset += blockSize) { 150 for (int i = 0; i < blockSize; i++) { 151 k[i] = (byte)(plain[i + plainOffset] ^ r[i]); 152 } 153 embeddedCipher.encryptBlock(k, 0, cipher, cipherOffset); 154 System.arraycopy(cipher, cipherOffset, r, 0, blockSize); 155 } 156 return plainLen; 157 } 158 159 /** 160 * Performs decryption operation. 161 * 162 * <p>The input cipher text <code>cipher</code>, starting at 163 * <code>cipherOffset</code> and ending at 164 * <code>(cipherOffset + cipherLen - 1)</code>, is decrypted. 165 * The result is stored in <code>plain</code>, starting at 166 * <code>plainOffset</code>. 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 * @exception ProviderException if <code>len</code> is not 178 * a multiple of the block size 179 * @return the length of the decrypted data 180 */ 181 int decrypt(byte[] cipher, int cipherOffset, int cipherLen, 182 byte[] plain, int plainOffset) 183 { 184 if ((cipherLen % blockSize) != 0) { 185 throw new ProviderException("Internal error in input buffering"); 186 } 187 int endIndex = cipherOffset + cipherLen; 188 189 for (; cipherOffset < endIndex; 190 cipherOffset += blockSize, plainOffset += blockSize) { 191 embeddedCipher.decryptBlock(cipher, cipherOffset, k, 0); 192 for (int i = 0; i < blockSize; i++) { 193 plain[i + plainOffset] = (byte)(k[i] ^ r[i]); 194 } 195 System.arraycopy(cipher, cipherOffset, r, 0, blockSize); 196 } 197 return cipherLen; 198 } 199 } | 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 import java.security.ProviderException; 30 import java.util.Objects; 31 32 import jdk.internal.HotSpotIntrinsicCandidate; 33 34 35 /** 36 * This class represents ciphers in cipher block chaining (CBC) mode. 37 * 38 * <p>This mode is implemented independently of a particular cipher. 39 * Ciphers to which this mode should apply (e.g., DES) must be 40 * <i>plugged-in</i> using the constructor. 41 * 42 * <p>NOTE: This class does not deal with buffering or padding. 43 * 44 * @author Gigi Ankeny 45 */ 46 47 class CipherBlockChaining extends FeedbackCipher { 48 49 /* 50 * random bytes that are initialized with iv 51 */ 52 protected byte[] r; 124 125 /** 126 * Performs encryption operation. 127 * 128 * <p>The input plain text <code>plain</code>, starting at 129 * <code>plainOffset</code> and ending at 130 * <code>(plainOffset + plainLen - 1)</code>, is encrypted. 131 * The result is stored in <code>cipher</code>, starting at 132 * <code>cipherOffset</code>. 133 * 134 * @param plain the buffer with the input data to be encrypted 135 * @param plainOffset the offset in <code>plain</code> 136 * @param plainLen the length of the input data 137 * @param cipher the buffer for the result 138 * @param cipherOffset the offset in <code>cipher</code> 139 * @exception ProviderException if <code>len</code> is not 140 * a multiple of the block size 141 * @return the length of the encrypted data 142 */ 143 int encrypt(byte[] plain, int plainOffset, int plainLen, 144 byte[] cipher, int cipherOffset) { 145 cryptBlockSizeCheck(plainLen); 146 cryptNullAndBoundsCheck(plain, plainOffset, plainLen); 147 cryptNullAndBoundsCheck(cipher, cipherOffset, plainLen); 148 return implEncrypt(plain, plainOffset, plainLen, 149 cipher, cipherOffset); 150 } 151 152 @HotSpotIntrinsicCandidate 153 private int implEncrypt(byte[] plain, int plainOffset, int plainLen, 154 byte[] cipher, int cipherOffset) 155 { 156 int endIndex = plainOffset + plainLen; 157 158 for (; plainOffset < endIndex; 159 plainOffset += blockSize, cipherOffset += blockSize) { 160 for (int i = 0; i < blockSize; i++) { 161 k[i] = (byte)(plain[i + plainOffset] ^ r[i]); 162 } 163 embeddedCipher.encryptBlock(k, 0, cipher, cipherOffset); 164 System.arraycopy(cipher, cipherOffset, r, 0, blockSize); 165 } 166 return plainLen; 167 } 168 169 /** 170 * Performs decryption operation. 171 * 172 * <p>The input cipher text <code>cipher</code>, starting at 173 * <code>cipherOffset</code> and ending at 174 * <code>(cipherOffset + cipherLen - 1)</code>, is decrypted. 175 * The result is stored in <code>plain</code>, starting at 176 * <code>plainOffset</code>. 177 * 178 * <p>It is also the application's responsibility to make sure that 179 * <code>init</code> has been called before this method is called. 180 * (This check is omitted here, to avoid double checking.) 181 * 182 * @param cipher the buffer with the input data to be decrypted 183 * @param cipherOffset the offset in <code>cipherOffset</code> 184 * @param cipherLen the length of the input data 185 * @param plain the buffer for the result 186 * @param plainOffset the offset in <code>plain</code> 187 * @exception ProviderException if <code>len</code> is not 188 * a multiple of the block size 189 * @return the length of the decrypted data 190 */ 191 int decrypt(byte[] cipher, int cipherOffset, int cipherLen, 192 byte[] plain, int plainOffset) { 193 cryptBlockSizeCheck(cipherLen); 194 cryptNullAndBoundsCheck(cipher, cipherOffset, cipherLen); 195 cryptNullAndBoundsCheck(plain, plainOffset, cipherLen); 196 return implDecrypt(cipher, cipherOffset, cipherLen, plain, plainOffset); 197 } 198 199 @HotSpotIntrinsicCandidate 200 private int implDecrypt(byte[] cipher, int cipherOffset, int cipherLen, 201 byte[] plain, int plainOffset) 202 { 203 int endIndex = cipherOffset + cipherLen; 204 205 for (; cipherOffset < endIndex; 206 cipherOffset += blockSize, plainOffset += blockSize) { 207 embeddedCipher.decryptBlock(cipher, cipherOffset, k, 0); 208 for (int i = 0; i < blockSize; i++) { 209 plain[i + plainOffset] = (byte)(k[i] ^ r[i]); 210 } 211 System.arraycopy(cipher, cipherOffset, r, 0, blockSize); 212 } 213 return cipherLen; 214 } 215 216 private void cryptBlockSizeCheck(int len) { 217 if ((len % blockSize) != 0) { 218 throw new ProviderException("Internal error in input buffering"); 219 } 220 } 221 222 private static void cryptNullAndBoundsCheck(byte[] array, int offset, int len) { 223 if (len <= 0) { 224 return; // not an error because cryptImpl/decryptImpl won't execute if len <= 0 225 } 226 227 Objects.requireNonNull(array); 228 229 if (offset < 0 || offset >= array.length) { 230 throw new ArrayIndexOutOfBoundsException(offset); 231 } 232 233 int endIndex = offset + len - 1; 234 if (endIndex < 0 || endIndex >= array.length) { 235 throw new ArrayIndexOutOfBoundsException(endIndex); 236 } 237 } 238 } |