GNU Classpath (0.95) | |
Frames | No Frames |
1: /* CipherSpi.java -- The cipher service provider interface. 2: Copyright (C) 2004, 2006 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package javax.crypto; 40: 41: import java.nio.ByteBuffer; 42: 43: import java.security.AlgorithmParameters; 44: import java.security.InvalidAlgorithmParameterException; 45: import java.security.InvalidKeyException; 46: import java.security.Key; 47: import java.security.NoSuchAlgorithmException; 48: import java.security.SecureRandom; 49: import java.security.spec.AlgorithmParameterSpec; 50: 51: /** 52: * <p>This class represents the <i>Service Provider Interface</i> 53: * (<b>SPI</b>) for cryptographic ciphers.</p> 54: * 55: * <p>Providers of cryptographic ciphers must subclass this for every 56: * cipher they implement, implementing the abstract methods as 57: * appropriate, then provide an entry that points to the subclass in 58: * their implementation of {@link java.security.Provider}.</p> 59: * 60: * <p>CipherSpi objects are instantiated along with {@link Cipher}s when 61: * the {@link Cipher#getInstance(java.lang.String)} methods are invoked. 62: * Particular ciphers are referenced by a <i>transformation</i>, which 63: * is a String consisting of the cipher's name or the ciper's name 64: * followed by a mode and a padding. Transformations all follow the 65: * general form:</p> 66: * 67: * <ul> 68: * <li><i>algorithm</i>, or</li> 69: * <li><i>algorithm</i>/<i>mode</i>/<i>padding</i> 70: * </ul> 71: * 72: * <p>Cipher names in the master {@link java.security.Provider} class 73: * may be:</p> 74: * 75: * <ol> 76: * <li>The algorithm's name, which uses a pluggable mode and padding: 77: * <code>Cipher.<i>algorithm</i></code></li> 78: * <li>The algorithm's name and the mode, which uses pluggable padding: 79: * <code>Cipher.<i>algorithm</i>/<i>mode</i></code></li> 80: * <li>The algorithm's name and the padding, which uses a pluggable 81: * mode: <code>Cipher.<i>algorithm</i>//<i>padding</i></code></li> 82: * <li>The algorihtm's name, the mode, and the padding: 83: * <code>Cipher.<i>algorithm</i>/<i>mode</i>/<i>padding</i></code></li> 84: * </ol> 85: * 86: * <p>When any {@link Cipher#getInstance(java.lang.String)} method is 87: * invoked, the following happens if the transformation is simply 88: * <i>algorithm</i>:</p> 89: * 90: * <ol> 91: * <li>If the provider defines a <code>CipherSpi</code> implementation 92: * for "<i>algorithm</i>", return it. Otherwise throw a {@link 93: * java.security.NoSuchAlgorithmException}.</li> 94: * </ol> 95: * 96: * <p>If the transformation is of the form 97: * <i>algorithm</i>/<i>mode</i>/<i>padding</i>:</p> 98: * 99: * <ol> 100: * <li>If the provider defines a <code>CipherSpi</code> subclass for 101: * "<i>algorithm</i>/<i>mode</i>/<i>padding</i>", return it. Otherwise 102: * go to step 2.</li> 103: * 104: * <li>If the provider defines a <code>CipherSpi</code> subclass for 105: * "<i>algorithm</i>/<i>mode</i>", instatiate it, call {@link 106: * #engineSetPadding(java.lang.String)} for the padding name, and return 107: * it. Otherwise go to step 3.</li> 108: * 109: * <li>If the provider defines a <code>CipherSpi</code> subclass for 110: * "<i>algorithm</i>//<i>padding</i>", instatiate it, call {@link 111: * #engineSetMode(java.lang.String)} for the mode name, and return 112: * it. Otherwise go to step 4.</li> 113: * 114: * <li>If the provider defines a <code>CipherSpi</code> subclass for 115: * "<i>algorithm</i>", instatiate it, call {@link 116: * #engineSetMode(java.lang.String)} for the mode name, call {@link 117: * #engineSetPadding(java.lang.String)} for the padding name, and return 118: * it. Otherwise throw a {@link java.security.NoSuchAlgorithmException}.</li> 119: * </ol> 120: * 121: * @author Casey Marshall (csm@gnu.org) 122: * @since 1.4 123: */ 124: public abstract class CipherSpi 125: { 126: 127: // Constructors. 128: // ------------------------------------------------------------------------ 129: 130: /** 131: * Create a new CipherSpi. 132: */ 133: public CipherSpi() 134: { 135: } 136: 137: // Abstract methods to be implemented by providers. 138: // ------------------------------------------------------------------------ 139: 140: /** 141: * Finishes a multi-part transformation or transforms a portion of a 142: * byte array, and returns the transformed bytes. 143: * 144: * @param input The input bytes. 145: * @param inputOffset The index in the input at which to start. 146: * @param inputLength The number of bytes to transform. 147: * @return The transformed bytes in a new array. 148: * @throws javax.crypto.IllegalBlockSizeException If this instance has 149: * no padding and the input size is not a multiple of the 150: * block size. 151: * @throws javax.crypto.BadPaddingException If this instance is being 152: * used for decryption and the padding is not appropriate for 153: * this instance's padding scheme. 154: */ 155: protected abstract byte[] 156: engineDoFinal(byte[] input, int inputOffset, int inputLength) 157: throws IllegalBlockSizeException, BadPaddingException; 158: 159: /** 160: * Finishes a multi-part transformation or transforms a portion of a 161: * byte array, and stores the transformed bytes in the supplied array. 162: * 163: * @param input The input bytes. 164: * @param inputOffset The index in the input at which to start. 165: * @param inputLength The number of bytes to transform. 166: * @param output The output byte array. 167: * @param outputOffset The index in the output array at which to start. 168: * @return The number of transformed bytes stored in the output array. 169: * @throws javax.crypto.IllegalBlockSizeException If this instance has 170: * no padding and the input size is not a multiple of the 171: * block size. 172: * @throws javax.crypto.BadPaddingException If this instance is being 173: * used for decryption and the padding is not appropriate for 174: * this instance's padding scheme. 175: * @throws javax.crypto.ShortBufferException If there is not enough 176: * space in the output array for the transformed bytes. 177: */ 178: protected abstract int 179: engineDoFinal(byte[] input, int inputOffset, int inputLength, 180: byte[] output, int outputOffset) 181: throws IllegalBlockSizeException, BadPaddingException, ShortBufferException; 182: 183: /** 184: * @since 1.5 185: */ 186: protected int engineDoFinal (ByteBuffer input, ByteBuffer output) 187: throws BadPaddingException, IllegalBlockSizeException, 188: ShortBufferException 189: { 190: int total = 0; 191: byte[] inbuf = new byte[256]; 192: while (input.hasRemaining ()) 193: { 194: int in = Math.min (inbuf.length, input.remaining ()); 195: input.get (inbuf, 0, in); 196: byte[] outbuf = new byte[engineGetOutputSize (in)]; 197: int out = 0; 198: if (input.hasRemaining ()) // i.e., we have more 'update' calls 199: out = engineUpdate (inbuf, 0, in, outbuf, 0); 200: else 201: out = engineDoFinal (inbuf, 0, in, outbuf, 0); 202: output.put (outbuf, 0, out); 203: total += out; 204: } 205: return total; 206: } 207: 208: /** 209: * Returns the block size of the underlying cipher. 210: * 211: * @return The block size. 212: */ 213: protected abstract int engineGetBlockSize(); 214: 215: /** 216: * Returns the initializaiton vector this cipher was initialized with, 217: * if any. 218: * 219: * @return The IV, or null if this cipher uses no IV or if this 220: * instance has not been initialized yet. 221: */ 222: protected abstract byte[] engineGetIV(); 223: 224: /** 225: * <p>Return the length of the given key in bits.</p> 226: * 227: * <p>For compatibility this method is not declared 228: * <code>abstract</code>, and the default implementation will throw an 229: * {@link java.lang.UnsupportedOperationException}. Concrete 230: * subclasses should override this method to return the correct 231: * value.</p> 232: * 233: * @param key The key to get the size for. 234: * @return The size of the key, in bits. 235: * @throws java.security.InvalidKeyException If the key's length 236: * cannot be determined by this implementation. 237: */ 238: protected int engineGetKeySize(Key key) throws InvalidKeyException 239: { 240: throw new UnsupportedOperationException(); 241: } 242: 243: /** 244: * <p>Returns the size, in bytes, an output buffer must be for a call 245: * to {@link #engineUpdate(byte[],int,int,byte[],int)} or {@link 246: * #engineDoFinal(byte[],int,int,byte[],int)} to succeed.</p> 247: * 248: * <p>The actual output length may be smaller than the value returned 249: * by this method, as it considers the padding length as well. The 250: * length considered is the argument plus the length of any buffered, 251: * unprocessed bytes.</p> 252: * 253: * @param inputLength The input length, in bytes. 254: * @return The size an output buffer must be. 255: */ 256: protected abstract int engineGetOutputSize(int inputLength); 257: 258: /** 259: * Returns the parameters that this cipher is using. This may be the 260: * parameters used to initialize this cipher, or it may be parameters 261: * that have been initialized with random values. 262: * 263: * @return This cipher's parameters, or <code>null</code> if this 264: * cipher does not use parameters. 265: */ 266: protected abstract AlgorithmParameters engineGetParameters(); 267: 268: /** 269: * Initializes this cipher with an operation mode, key, and source of 270: * randomness. If this cipher requires any other initializing data, 271: * for example an initialization vector, then it should generate it 272: * from the provided source of randomness. 273: * 274: * @param opmode The operation mode, one of {@link 275: * Cipher#DECRYPT_MODE}, {@link Cipher#ENCRYPT_MODE}, {@link 276: * Cipher#UNWRAP_MODE}, or {@link Cipher#WRAP_MODE}. 277: * @param key The key to initialize this cipher with. 278: * @param random The source of random bytes to use. 279: * @throws java.security.InvalidKeyException If the given key is not 280: * acceptable for this implementation. 281: */ 282: protected abstract void engineInit(int opmode, Key key, SecureRandom random) 283: throws InvalidKeyException; 284: 285: /** 286: * Initializes this cipher with an operation mode, key, parameters, 287: * and source of randomness. If this cipher requires any other 288: * initializing data, for example an initialization vector, then it should 289: * generate it from the provided source of randomness. 290: * 291: * @param opmode The operation mode, one of {@link 292: * Cipher#DECRYPT_MODE}, {@link Cipher#ENCRYPT_MODE}, {@link 293: * Cipher#UNWRAP_MODE}, or {@link Cipher#WRAP_MODE}. 294: * @param key The key to initialize this cipher with. 295: * @param params The algorithm parameters to initialize with. 296: * @param random The source of random bytes to use. 297: * @throws java.security.InvalidAlgorithmParameterException If the 298: * given parameters are not appropriate for this 299: * implementation. 300: * @throws java.security.InvalidKeyException If the given key is not 301: * acceptable for this implementation. 302: */ 303: protected abstract void 304: engineInit(int opmode, Key key, AlgorithmParameters params, 305: SecureRandom random) 306: throws InvalidAlgorithmParameterException, InvalidKeyException; 307: 308: /** 309: * Initializes this cipher with an operation mode, key, parameters, 310: * and source of randomness. If this cipher requires any other 311: * initializing data, for example an initialization vector, then it should 312: * generate it from the provided source of randomness. 313: * 314: * @param opmode The operation mode, one of {@link 315: * Cipher#DECRYPT_MODE}, {@link Cipher#ENCRYPT_MODE}, {@link 316: * Cipher#UNWRAP_MODE}, or {@link Cipher#WRAP_MODE}. 317: * @param key The key to initialize this cipher with. 318: * @param params The algorithm parameters to initialize with. 319: * @param random The source of random bytes to use. 320: * @throws java.security.InvalidAlgorithmParameterException If the 321: * given parameters are not appropriate for this 322: * implementation. 323: * @throws java.security.InvalidKeyException If the given key is not 324: * acceptable for this implementation. 325: */ 326: protected abstract void 327: engineInit(int opmode, Key key, AlgorithmParameterSpec params, 328: SecureRandom random) 329: throws InvalidAlgorithmParameterException, InvalidKeyException; 330: 331: /** 332: * Set the mode in which this cipher is to run. 333: * 334: * @param mode The name of the mode to use. 335: * @throws java.security.NoSuchAlgorithmException If the mode is 336: * not supported by this cipher's provider. 337: */ 338: protected abstract void engineSetMode(String mode) 339: throws NoSuchAlgorithmException; 340: 341: /** 342: * Set the method with which the input is to be padded. 343: * 344: * @param padding The name of the padding to use. 345: * @throws javax.crypto.NoSuchPaddingException If the padding is not 346: * supported by this cipher's provider. 347: */ 348: protected abstract void engineSetPadding(String padding) 349: throws NoSuchPaddingException; 350: 351: /** 352: * <p>Unwraps a previously-wrapped key.</p> 353: * 354: * <p>For compatibility this method is not declared 355: * <code>abstract</code>, and the default implementation will throw an 356: * {@link java.lang.UnsupportedOperationException}.</p> 357: * 358: * @param wrappedKey The wrapped key. 359: * @param wrappedKeyAlgorithm The name of the algorithm used to wrap 360: * this key. 361: * @param wrappedKeyType The type of wrapped key; one of 362: * {@link Cipher#PRIVATE_KEY}, 363: * {@link Cipher#PUBLIC_KEY}, or 364: * {@link Cipher#SECRET_KEY}. 365: * @return The unwrapped key. 366: * @throws java.security.InvalidKeyException If the key cannot be 367: * unwrapped, or if <code>wrappedKeyType</code> is an 368: * inappropriate type for the unwrapped key. 369: * @throws java.security.NoSuchAlgorithmException If the 370: * <code>wrappedKeyAlgorithm</code> is unknown. 371: */ 372: protected Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, 373: int wrappedKeyType) 374: throws InvalidKeyException, NoSuchAlgorithmException 375: { 376: throw new UnsupportedOperationException(); 377: } 378: 379: /** 380: * Continue with a multi-part transformation, returning a new array of 381: * the transformed bytes. 382: * 383: * @param input The next input bytes. 384: * @param inputOffset The index in the input array from which to start. 385: * @param inputLength The number of bytes to input. 386: * @return The transformed bytes. 387: */ 388: protected abstract byte[] 389: engineUpdate(byte[] input, int inputOffset, int inputLength); 390: 391: /** 392: * Continue with a multi-part transformation, storing the transformed 393: * bytes into the specified array. 394: * 395: * @param input The next input bytes. 396: * @param inputOffset The index in the input from which to start. 397: * @param inputLength The number of bytes to input. 398: * @param output The output buffer. 399: * @param outputOffset The index in the output array from which to start. 400: * @return The transformed bytes. 401: * @throws javax.crypto.ShortBufferException If there is not enough 402: * space in the output array to store the transformed bytes. 403: */ 404: protected abstract int 405: engineUpdate(byte[] input, int inputOffset, int inputLength, 406: byte[] output, int outputOffset) 407: throws ShortBufferException; 408: 409: /** 410: * @since 1.5 411: */ 412: protected int engineUpdate (ByteBuffer input, ByteBuffer output) 413: throws ShortBufferException 414: { 415: int total = 0; 416: byte[] inbuf = new byte[256]; 417: while (input.hasRemaining ()) 418: { 419: int in = Math.min (inbuf.length, input.remaining ()); 420: input.get (inbuf, 0, in); 421: byte[] outbuf = new byte[engineGetOutputSize (in)]; 422: int out = engineUpdate (inbuf, 0, in, outbuf, 0); 423: output.put (outbuf, 0, out); 424: total += out; 425: } 426: return total; 427: } 428: 429: /** 430: * <p>Wrap a key.</p> 431: * 432: * <p>For compatibility this method is not declared 433: * <code>abstract</code>, and the default implementation will throw an 434: * {@link java.lang.UnsupportedOperationException}.</p> 435: * 436: * @param key The key to wrap. 437: * @return The wrapped key. 438: * @throws java.security.InvalidKeyException If the key cannot be 439: * wrapped. 440: */ 441: protected byte[] engineWrap(Key key) throws InvalidKeyException, IllegalBlockSizeException 442: { 443: throw new UnsupportedOperationException(); 444: } 445: }
GNU Classpath (0.95) |