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
26package com.sun.crypto.provider;
27
28import java.security.InvalidKeyException;
29import 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 */
43abstract 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}
244