1 /*
2  * Copyright (c) 1997, 2017, 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 import java.security.InvalidAlgorithmParameterException;
30 import javax.crypto.*;
31 
32 /**
33  * This class represents a block cipher in one of its modes. It wraps
34  * a SymmetricCipher maintaining the mode state and providing
35  * the capability to encrypt amounts of data larger than a single block.
36  *
37  * @author Jan Luehe
38  * @see ElectronicCodeBook
39  * @see CipherBlockChaining
40  * @see CipherFeedback
41  * @see OutputFeedback
42  * @see PCBC
43  */
44 abstract class FeedbackCipher {
45 
46     // the embedded block cipher
47     final SymmetricCipher embeddedCipher;
48 
49     // the block size of the embedded block cipher
50     final int blockSize;
51 
52     // the initialization vector
53     byte[] iv;
54 
FeedbackCipher(SymmetricCipher embeddedCipher)55     FeedbackCipher(SymmetricCipher embeddedCipher) {
56         this.embeddedCipher = embeddedCipher;
57         blockSize = embeddedCipher.getBlockSize();
58     }
59 
getEmbeddedCipher()60     final SymmetricCipher getEmbeddedCipher() {
61         return embeddedCipher;
62     }
63 
64     /**
65      * Gets the block size of the embedded cipher.
66      *
67      * @return the block size of the embedded cipher
68      */
getBlockSize()69     final int getBlockSize() {
70         return blockSize;
71     }
72 
73     /**
74      * Gets the name of the feedback mechanism
75      *
76      * @return the name of the feedback mechanism
77      */
getFeedback()78     abstract String getFeedback();
79 
80     /**
81      * Save the current content of this cipher.
82      */
save()83     abstract void save();
84 
85     /**
86      * Restores the content of this cipher to the previous saved one.
87      */
restore()88     abstract void restore();
89 
90     /**
91      * Initializes the cipher in the specified mode with the given key
92      * and iv.
93      *
94      * @param decrypting flag indicating encryption or decryption mode
95      * @param algorithm the algorithm name (never null)
96      * @param key the key (never null)
97      * @param iv the iv (either null or blockSize bytes long)
98      *
99      * @exception InvalidKeyException if the given key is inappropriate for
100      * initializing this cipher
101      */
init(boolean decrypting, String algorithm, byte[] key, byte[] iv)102     abstract void init(boolean decrypting, String algorithm, byte[] key,
103                        byte[] iv) throws InvalidKeyException,
104                                          InvalidAlgorithmParameterException;
105 
106    /**
107      * Gets the initialization vector.
108      *
109      * @return the initialization vector
110      */
getIV()111     final byte[] getIV() {
112         return iv;
113     }
114 
115     /**
116      * Resets the iv to its original value.
117      * This is used when doFinal is called in the Cipher class, so that the
118      * cipher can be reused (with its original iv).
119      */
reset()120     abstract void reset();
121 
122     /**
123      * Performs encryption operation.
124      *
125      * <p>The input <code>plain</code>, starting at <code>plainOffset</code>
126      * and ending at <code>(plainOffset+plainLen-1)</code>, is encrypted.
127      * The result is stored in <code>cipher</code>, starting at
128      * <code>cipherOffset</code>.
129      *
130      * <p>The subclass that implements Cipher should ensure that
131      * <code>init</code> has been called before this method is called.
132      *
133      * @param plain the input buffer with the 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 encryption result
137      * @param cipherOffset the offset in <code>cipher</code>
138      * @return the number of bytes placed into <code>cipher</code>
139      */
encrypt(byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset)140     abstract int encrypt(byte[] plain, int plainOffset, int plainLen,
141                          byte[] cipher, int cipherOffset);
142     /**
143      * Performs encryption operation for the last time.
144      *
145      * <p>NOTE: For cipher feedback modes which does not perform
146      * special handling for the last few blocks, this is essentially
147      * the same as <code>encrypt(...)</code>. Given most modes do
148      * not do special handling, the default impl for this method is
149      * to simply call <code>encrypt(...)</code>.
150      *
151      * @param plain the input buffer with the data to be encrypted
152      * @param plainOffset the offset in <code>plain</code>
153      * @param plainLen the length of the input data
154      * @param cipher the buffer for the encryption result
155      * @param cipherOffset the offset in <code>cipher</code>
156      * @return the number of bytes placed into <code>cipher</code>
157      */
encryptFinal(byte[] plain, int plainOffset, int plainLen, byte[] cipher, int cipherOffset)158      int encryptFinal(byte[] plain, int plainOffset, int plainLen,
159                       byte[] cipher, int cipherOffset)
160          throws IllegalBlockSizeException, ShortBufferException {
161          return encrypt(plain, plainOffset, plainLen, cipher, cipherOffset);
162     }
163     /**
164      * Performs decryption operation.
165      *
166      * <p>The input <code>cipher</code>, starting at <code>cipherOffset</code>
167      * and ending at <code>(cipherOffset+cipherLen-1)</code>, is decrypted.
168      * The result is stored in <code>plain</code>, starting at
169      * <code>plainOffset</code>.
170      *
171      * <p>The subclass that implements Cipher should ensure that
172      * <code>init</code> has been called before this method is called.
173      *
174      * @param cipher the input buffer with the data to be decrypted
175      * @param cipherOffset the offset in <code>cipher</code>
176      * @param cipherLen the length of the input data
177      * @param plain the buffer for the decryption result
178      * @param plainOffset the offset in <code>plain</code>
179      * @return the number of bytes placed into <code>plain</code>
180      */
decrypt(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset)181     abstract int decrypt(byte[] cipher, int cipherOffset, int cipherLen,
182                          byte[] plain, int plainOffset);
183 
184     /**
185      * Performs decryption operation for the last time.
186      *
187      * <p>NOTE: For cipher feedback modes which does not perform
188      * special handling for the last few blocks, this is essentially
189      * the same as <code>encrypt(...)</code>. Given most modes do
190      * not do special handling, the default impl for this method is
191      * to simply call <code>decrypt(...)</code>.
192      *
193      * @param cipher the input buffer with the data to be decrypted
194      * @param cipherOffset the offset in <code>cipher</code>
195      * @param cipherLen the length of the input data
196      * @param plain the buffer for the decryption result
197      * @param plainOffset the offset in <code>plain</code>
198      * @return the number of bytes placed into <code>plain</code>
199      */
decryptFinal(byte[] cipher, int cipherOffset, int cipherLen, byte[] plain, int plainOffset)200      int decryptFinal(byte[] cipher, int cipherOffset, int cipherLen,
201                       byte[] plain, int plainOffset)
202          throws IllegalBlockSizeException, AEADBadTagException,
203          ShortBufferException {
204          return decrypt(cipher, cipherOffset, cipherLen, plain, plainOffset);
205      }
206 
207     /**
208      * Continues a multi-part update of the Additional Authentication
209      * Data (AAD), using a subset of the provided buffer. If this
210      * cipher is operating in either GCM or CCM mode, all AAD must be
211      * supplied before beginning operations on the ciphertext (via the
212      * {@code update} and {@code doFinal} methods).
213      * <p>
214      * NOTE: Given most modes do not accept AAD, default impl for this
215      * method throws IllegalStateException.
216      *
217      * @param src the buffer containing the AAD
218      * @param offset the offset in {@code src} where the AAD input starts
219      * @param len the number of AAD bytes
220      *
221      * @throws IllegalStateException if this cipher is in a wrong state
222      * (e.g., has not been initialized), does not accept AAD, or if
223      * operating in either GCM or CCM mode and one of the {@code update}
224      * methods has already been called for the active
225      * encryption/decryption operation
226      * @throws UnsupportedOperationException if this method
227      * has not been overridden by an implementation
228      *
229      * @since 1.8
230      */
updateAAD(byte[] src, int offset, int len)231     void updateAAD(byte[] src, int offset, int len) {
232         throw new IllegalStateException("No AAD accepted");
233     }
234 
235     /**
236      * @return the number of bytes that are buffered internally inside
237      * this FeedbackCipher instance.
238      * @since 1.8
239      */
getBufferedLength()240     int getBufferedLength() {
241         // Currently only AEAD cipher impl, e.g. GCM, buffers data
242         // internally during decryption mode
243         return 0;
244     }
245 }
246