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