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