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