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 }
|