1 /*
2  *  Licensed to the Apache Software Foundation (ASF) under one or more
3  *  contributor license agreements.  See the NOTICE file distributed with
4  *  this work for additional information regarding copyright ownership.
5  *  The ASF licenses this file to You under the Apache License, Version 2.0
6  *  (the "License"); you may not use this file except in compliance with
7  *  the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  *  Unless required by applicable law or agreed to in writing, software
12  *  distributed under the License is distributed on an "AS IS" BASIS,
13  *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  *  See the License for the specific language governing permissions and
15  *  limitations under the License.
16  */
17 
18 package javax.crypto;
19 
20 import java.nio.ByteBuffer;
21 import java.security.AlgorithmParameters;
22 import java.security.InvalidAlgorithmParameterException;
23 import java.security.InvalidKeyException;
24 import java.security.InvalidParameterException;
25 import java.security.Key;
26 import java.security.NoSuchAlgorithmException;
27 import java.security.NoSuchProviderException;
28 import java.security.Provider;
29 import java.security.Provider.Service;
30 import java.security.ProviderException;
31 import java.security.SecureRandom;
32 import java.security.Security;
33 import java.security.cert.Certificate;
34 import java.security.cert.X509Certificate;
35 import java.security.spec.AlgorithmParameterSpec;
36 import java.util.ArrayList;
37 import java.util.Locale;
38 import java.util.Set;
39 import org.apache.harmony.crypto.internal.NullCipherSpi;
40 import org.apache.harmony.security.fortress.Engine;
41 
42 /**
43  * This class provides access to implementations of cryptographic ciphers for
44  * encryption and decryption. Cipher classes can not be instantiated directly,
45  * one has to call the Cipher's {@code getInstance} method with the name of a
46  * requested transformation, optionally with a provider. A transformation
47  * specifies an operation (or a set of operations) as a string in the form:
48  * <ul>
49  * <li><i>"algorithm/mode/padding"</i></li> or
50  * <li><i>"algorithm"</i></li>
51  * </ul>
52  * <i>algorithm</i> is the name of a cryptographic algorithm, <i>mode</i> is the
53  * name of a feedback mode and <i>padding</i> is the name of a padding scheme.
54  * If <i>mode</i> and/or <i>padding</i> values are omitted, provider specific
55  * default values will be used.
56  * <p>
57  * A valid transformation would be:
58  * <ul>
59  * {@code Cipher c = Cipher.getInstance("AES/CBC/PKCS5Padding");}
60  * </ul>
61  * When a block cipher is requested in stream cipher mode, the number of bits
62  * to be processed at a time can be optionally specified by appending it to the
63  * mode name. e.g. <i>"AES/CFB8/NoPadding"</i>. If no number is specified, a
64  * provider specific default value is used.
65  */
66 public class Cipher {
67 
68     /**
69      * Constant for decryption operation mode.
70      */
71     public static final int DECRYPT_MODE = 2;
72 
73     /**
74      * Constant for encryption operation mode.
75      */
76     public static final int ENCRYPT_MODE = 1;
77 
78     /**
79      * Constant indicating that the key to be unwrapped is a private key.
80      */
81     public static final int PRIVATE_KEY = 2;
82 
83     /**
84      * Constant indicating that the key to be unwrapped is a public key.
85      */
86     public static final int PUBLIC_KEY = 1;
87 
88     /**
89      * Constant indicating that the key to be unwrapped is a secret key.
90      */
91     public static final int SECRET_KEY = 3;
92 
93     /**
94      * Constant for key unwrapping operation mode.
95      */
96     public static final int UNWRAP_MODE = 4;
97 
98     /**
99      * Constant for key wrapping operation mode.
100      */
101     public static final int WRAP_MODE = 3;
102 
103     private int mode;
104 
105     /** Items that need to be set on the Cipher instance. */
106     private enum NeedToSet {
107         NONE, MODE, PADDING, BOTH,
108     };
109 
110     /**
111      * The service name.
112      */
113     private static final String SERVICE = "Cipher";
114 
115     /**
116      * Used to access common engine functionality.
117      */
118     private static final Engine ENGINE = new Engine(SERVICE);
119 
120     /** The attribute used for supported paddings. */
121     private static final String ATTRIBUTE_PADDINGS = "SupportedPaddings";
122 
123     /** The attribute used for supported modes. */
124     private static final String ATTRIBUTE_MODES = "SupportedModes";
125 
126     /**
127      * The provider.
128      */
129     private Provider provider;
130 
131     /**
132      * The provider specified when instance created.
133      */
134     private final Provider specifiedProvider;
135 
136     /**
137      * The SPI implementation.
138      */
139     private CipherSpi spiImpl;
140 
141     /**
142      * The SPI implementation.
143      */
144     private final CipherSpi specifiedSpi;
145 
146     /**
147      * The transformation.
148      */
149     private final String transformation;
150 
151     /**
152      * The transformation split into parts.
153      */
154     private final String[] transformParts;
155 
156     /**
157      * Lock held while the SPI is initializing.
158      */
159     private final Object initLock = new Object();
160 
161     private static SecureRandom secureRandom;
162 
163     /**
164      * Creates a new Cipher instance.
165      *
166      * @param cipherSpi
167      *            the implementation delegate of the cipher.
168      * @param provider
169      *            the provider of the implementation of this cipher.
170      * @param transformation
171      *            the name of the transformation that this cipher performs.
172      * @throws NullPointerException
173      *             if either cipherSpi is {@code null} or provider is {@code
174      *             null} and {@code cipherSpi} is a {@code NullCipherSpi}.
175      */
Cipher(CipherSpi cipherSpi, Provider provider, String transformation)176     protected Cipher(CipherSpi cipherSpi, Provider provider, String transformation) {
177         if (cipherSpi == null) {
178             throw new NullPointerException("cipherSpi == null");
179         }
180         if (!(cipherSpi instanceof NullCipherSpi) && provider == null) {
181             throw new NullPointerException("provider == null");
182         }
183         this.specifiedProvider = provider;
184         this.specifiedSpi = cipherSpi;
185         this.transformation = transformation;
186         this.transformParts = null;
187     }
188 
Cipher(String transformation, String[] transformParts, Provider provider)189     private Cipher(String transformation, String[] transformParts, Provider provider) {
190         this.transformation = transformation;
191         this.transformParts = transformParts;
192         this.specifiedProvider = provider;
193         this.specifiedSpi = null;
194     }
195 
196 
197     /**
198      * Creates a new Cipher for the specified transformation. The installed
199      * providers are searched in order for an implementation of the specified
200      * transformation. The first found provider providing the transformation is
201      * used to create the cipher. If no provider is found an exception is
202      * thrown.
203      *
204      * @param transformation
205      *            the name of the transformation to create a cipher for.
206      * @return a cipher for the requested transformation.
207      * @throws NoSuchAlgorithmException
208      *             if no installed provider can provide the
209      *             <i>transformation</i>, or it is {@code null}, empty or in an
210      *             invalid format.
211      * @throws NoSuchPaddingException
212      *             if no installed provider can provide the padding scheme in
213      *             the <i>transformation</i>.
214      */
getInstance(String transformation)215     public static final Cipher getInstance(String transformation)
216             throws NoSuchAlgorithmException, NoSuchPaddingException {
217         return getCipher(transformation, null);
218     }
219 
220     /**
221      * Creates a new cipher for the specified transformation provided by the
222      * specified provider.
223      *
224      * @param transformation
225      *            the name of the transformation to create a cipher for.
226      * @param provider
227      *            the name of the provider to ask for the transformation.
228      * @return a cipher for the requested transformation.
229      * @throws NoSuchAlgorithmException
230      *             if the specified provider can not provide the
231      *             <i>transformation</i>, or it is {@code null}, empty or in an
232      *             invalid format.
233      * @throws NoSuchProviderException
234      *             if no provider with the specified name can be found.
235      * @throws NoSuchPaddingException
236      *             if the requested padding scheme in the <i>transformation</i>
237      *             is not available.
238      * @throws IllegalArgumentException
239      *             if the specified provider is {@code null}.
240      */
getInstance(String transformation, String provider)241     public static final Cipher getInstance(String transformation,
242             String provider) throws NoSuchAlgorithmException,
243             NoSuchProviderException, NoSuchPaddingException {
244 
245         if (provider == null) {
246             throw new IllegalArgumentException("provider == null");
247         }
248 
249         Provider p = Security.getProvider(provider);
250         if (p == null) {
251             throw new NoSuchProviderException("Provider not available: " + provider);
252         }
253         return getInstance(transformation, p);
254     }
255 
256     /**
257      * Creates a new cipher for the specified transformation. The
258      * {@code provider} supplied does not have to be registered.
259      *
260      * @param transformation
261      *            the name of the transformation to create a cipher for.
262      * @param provider
263      *            the provider to ask for the transformation.
264      * @return a cipher for the requested transformation.
265      * @throws NoSuchAlgorithmException
266      *             if the specified provider can not provide the
267      *             <i>transformation</i>, or it is {@code null}, empty or in an
268      *             invalid format.
269      * @throws NoSuchPaddingException
270      *             if the requested padding scheme in the <i>transformation</i>
271      *             is not available.
272      * @throws IllegalArgumentException
273      *             if the provider is {@code null}.
274      */
getInstance(String transformation, Provider provider)275     public static final Cipher getInstance(String transformation,
276             Provider provider) throws NoSuchAlgorithmException,
277             NoSuchPaddingException {
278         if (provider == null) {
279             throw new IllegalArgumentException("provider == null");
280         }
281         return getCipher(transformation, provider);
282     }
283 
invalidTransformation(String transformation)284     private static NoSuchAlgorithmException invalidTransformation(String transformation)
285             throws NoSuchAlgorithmException {
286         throw new NoSuchAlgorithmException("Invalid transformation: " + transformation);
287     }
288 
289     /**
290      * Create a Cipher instance but don't choose a CipherSpi until we have more
291      * information.
292      */
getCipher(String transformation, Provider provider)293     private static Cipher getCipher(String transformation, Provider provider)
294             throws NoSuchAlgorithmException, NoSuchPaddingException {
295         if (transformation == null || transformation.isEmpty()) {
296             throw invalidTransformation(transformation);
297         }
298 
299         String[] transformParts = checkTransformation(transformation);
300         if (tryCombinations(null, provider, transformParts) == null) {
301             if (provider == null) {
302                 throw new NoSuchAlgorithmException("No provider found for " + transformation);
303             } else {
304                 throw new NoSuchAlgorithmException("Provider " + provider.getName()
305                         + " does not provide " + transformation);
306             }
307         }
308         return new Cipher(transformation, transformParts, provider);
309     }
310 
checkTransformation(String transformation)311     private static String[] checkTransformation(String transformation)
312             throws NoSuchAlgorithmException {
313         // ignore an extra prefix / characters such as in
314         // "/DES/CBC/PKCS5Padding" http://b/3387688
315         if (transformation.startsWith("/")) {
316             transformation = transformation.substring(1);
317         }
318         // 'transformation' should be of the form "algorithm/mode/padding".
319         String[] pieces = transformation.split("/");
320         if (pieces.length > 3) {
321             throw invalidTransformation(transformation);
322         }
323         // Empty or missing pieces are represented by null.
324         String[] result = new String[3];
325         for (int i = 0; i < pieces.length; ++i) {
326             String piece = pieces[i].trim();
327             if (!piece.isEmpty()) {
328                 result[i] = piece;
329             }
330         }
331         // You MUST specify an algorithm.
332         if (result[0] == null) {
333             throw invalidTransformation(transformation);
334         }
335         if (!(result[1] == null && result[2] == null) && (result[1] == null || result[2] == null)) {
336             throw invalidTransformation(transformation);
337         }
338         return result;
339     }
340 
341     /**
342      * Makes sure a CipherSpi that matches this type is selected.
343      */
getSpi(Key key)344     private CipherSpi getSpi(Key key) {
345         if (specifiedSpi != null) {
346             return specifiedSpi;
347         }
348 
349         synchronized (initLock) {
350             if (spiImpl != null && key == null) {
351                 return spiImpl;
352             }
353 
354             final Engine.SpiAndProvider sap = tryCombinations(key, specifiedProvider,
355                     transformParts);
356             if (sap == null) {
357                 throw new ProviderException("No provider for " + transformation);
358             }
359 
360             spiImpl = (CipherSpi) sap.spi;
361             provider = sap.provider;
362 
363             return spiImpl;
364         }
365     }
366 
367     /**
368      * Convenience call when the Key is not available.
369      */
getSpi()370     private CipherSpi getSpi() {
371         return getSpi(null);
372     }
373 
374     /**
375      * Try all combinations of mode strings:
376      *
377      * <pre>
378      *   [cipher]/[mode]/[padding]
379      *   [cipher]/[mode]
380      *   [cipher]//[padding]
381      *   [cipher]
382      * </pre>
383      */
tryCombinations(Key key, Provider provider, String[] transformParts)384     private static Engine.SpiAndProvider tryCombinations(Key key, Provider provider,
385             String[] transformParts) {
386         Engine.SpiAndProvider sap = null;
387 
388         if (transformParts[1] != null && transformParts[2] != null) {
389             sap = tryTransform(key, provider, transformParts[0] + "/" + transformParts[1] + "/"
390                     + transformParts[2], transformParts, NeedToSet.NONE);
391             if (sap != null) {
392                 return sap;
393             }
394         }
395 
396         if (transformParts[1] != null) {
397             sap = tryTransform(key, provider, transformParts[0] + "/" + transformParts[1],
398                     transformParts, NeedToSet.PADDING);
399             if (sap != null) {
400                 return sap;
401             }
402         }
403 
404         if (transformParts[2] != null) {
405             sap = tryTransform(key, provider, transformParts[0] + "//" + transformParts[2],
406                     transformParts, NeedToSet.MODE);
407             if (sap != null) {
408                 return sap;
409             }
410         }
411 
412         return tryTransform(key, provider, transformParts[0], transformParts, NeedToSet.BOTH);
413     }
414 
tryTransform(Key key, Provider provider, String transform, String[] transformParts, NeedToSet type)415     private static Engine.SpiAndProvider tryTransform(Key key, Provider provider, String transform,
416             String[] transformParts, NeedToSet type) {
417         if (provider != null) {
418             Provider.Service service = provider.getService(SERVICE, transform);
419             if (service == null) {
420                 return null;
421             }
422             return tryTransformWithProvider(key, transformParts, type, service);
423         }
424         ArrayList<Provider.Service> services = ENGINE.getServices(transform);
425         if (services == null) {
426             return null;
427         }
428         for (Provider.Service service : services) {
429             Engine.SpiAndProvider sap = tryTransformWithProvider(key, transformParts, type, service);
430             if (sap != null) {
431                 return sap;
432             }
433         }
434         return null;
435     }
436 
tryTransformWithProvider(Key key, String[] transformParts, NeedToSet type, Provider.Service service)437     private static Engine.SpiAndProvider tryTransformWithProvider(Key key, String[] transformParts,
438             NeedToSet type, Provider.Service service) {
439         try {
440             if (key != null && !service.supportsParameter(key)) {
441                 return null;
442             }
443 
444             /*
445              * Check to see if the Cipher even supports the attributes before
446              * trying to instantiate it.
447              */
448             if (!matchAttribute(service, ATTRIBUTE_MODES, transformParts[1])
449                     || !matchAttribute(service, ATTRIBUTE_PADDINGS, transformParts[2])) {
450                 return null;
451             }
452 
453             Engine.SpiAndProvider sap = ENGINE.getInstance(service, null);
454             if (sap.spi == null || sap.provider == null) {
455                 return null;
456             }
457             if (!(sap.spi instanceof CipherSpi)) {
458                 return null;
459             }
460             CipherSpi spi = (CipherSpi) sap.spi;
461             if (((type == NeedToSet.MODE) || (type == NeedToSet.BOTH))
462                     && (transformParts[1] != null)) {
463                 spi.engineSetMode(transformParts[1]);
464             }
465             if (((type == NeedToSet.PADDING) || (type == NeedToSet.BOTH))
466                     && (transformParts[2] != null)) {
467                 spi.engineSetPadding(transformParts[2]);
468             }
469             return sap;
470         } catch (NoSuchAlgorithmException ignored) {
471         } catch (NoSuchPaddingException ignored) {
472         }
473         return null;
474     }
475 
476     /**
477      * If the attribute listed exists, check that it matches the regular
478      * expression.
479      */
matchAttribute(Service service, String attr, String value)480     private static boolean matchAttribute(Service service, String attr, String value) {
481         if (value == null) {
482             return true;
483         }
484         final String pattern = service.getAttribute(attr);
485         if (pattern == null) {
486             return true;
487         }
488         final String valueUc = value.toUpperCase(Locale.US);
489         return valueUc.matches(pattern.toUpperCase(Locale.US));
490     }
491 
492     /**
493      * Returns the provider of this cipher instance.
494      *
495      * @return the provider of this cipher instance.
496      */
getProvider()497     public final Provider getProvider() {
498         getSpi();
499         return provider;
500     }
501 
502     /**
503      * Returns the name of the algorithm of this cipher instance.
504      * <p>
505      * This is the name of the <i>transformation</i> argument used in the
506      * {@code getInstance} call creating this object.
507      *
508      * @return the name of the algorithm of this cipher instance.
509      */
getAlgorithm()510     public final String getAlgorithm() {
511         return transformation;
512     }
513 
514     /**
515      * Returns this ciphers block size (in bytes).
516      *
517      * @return this ciphers block size.
518      */
getBlockSize()519     public final int getBlockSize() {
520         return getSpi().engineGetBlockSize();
521     }
522 
523     /**
524      * Returns the length in bytes an output buffer needs to be when this cipher
525      * is updated with {@code inputLen} bytes.
526      *
527      * @param inputLen
528      *            the number of bytes of the input.
529      * @return the output buffer length for the input length.
530      * @throws IllegalStateException
531      *             if this cipher instance is in an invalid state.
532      */
getOutputSize(int inputLen)533     public final int getOutputSize(int inputLen) {
534         if (mode == 0) {
535             throw new IllegalStateException("Cipher has not yet been initialized");
536         }
537         return getSpi().engineGetOutputSize(inputLen);
538     }
539 
540     /**
541      * Returns the <i>initialization vector</i> for this cipher instance.
542      *
543      * @return the <i>initialization vector</i> for this cipher instance.
544      */
getIV()545     public final byte[] getIV() {
546         return getSpi().engineGetIV();
547     }
548 
549     /**
550      * Returns the parameters that where used to create this cipher instance.
551      * <p>
552      * These may be a the same parameters that were used to create this cipher
553      * instance, or may be a combination of default and random parameters,
554      * depending on the underlying cipher implementation.
555      *
556      * @return the parameters that where used to create this cipher instance, or
557      *         {@code null} if this cipher instance does not have any
558      *         parameters.
559      */
getParameters()560     public final AlgorithmParameters getParameters() {
561         return getSpi().engineGetParameters();
562     }
563 
564     /**
565      * Returns the exemption mechanism associated with this cipher.
566      *
567      * @return currently {@code null}
568      */
getExemptionMechanism()569     public final ExemptionMechanism getExemptionMechanism() {
570         //FIXME implement getExemptionMechanism
571 
572         //        try {
573         //            return ExemptionMechanism.getInstance(transformation, provider);
574         //        } catch (NoSuchAlgorithmException e) {
575         return null;
576         //        }
577 
578     }
579 
checkMode(int mode)580     private void checkMode(int mode) {
581         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE && mode != UNWRAP_MODE
582                 && mode != WRAP_MODE) {
583             throw new InvalidParameterException("Invalid mode: " + mode);
584         }
585     }
586 
587     /**
588      * Initializes this cipher instance with the specified key.
589      * <p>
590      * The cipher is initialized for the specified operational mode (one of:
591      * encryption, decryption, key wrapping or key unwrapping) depending on
592      * {@code opmode}.
593      * <p>
594      * If this cipher instance needs any algorithm parameters or random values
595      * that the specified key can not provide, the underlying implementation of
596      * this cipher is supposed to generate the required parameters (using its
597      * provider or random values).
598      * <p>
599      * When a cipher instance is initialized by a call to any of the {@code
600      * init} methods, the state of the instance is overridden, meaning that it
601      * is equivalent to creating a new instance and calling its {@code init}
602      * method.
603      *
604      * @param opmode
605      *            the operation this cipher instance should be initialized for
606      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
607      *            WRAP_MODE} or {@code UNWRAP_MODE}).
608      * @param key
609      *            the input key for the operation.
610      * @throws InvalidKeyException
611      *             if the specified key can not be used to initialize this
612      *             cipher instance.
613      */
init(int opmode, Key key)614     public final void init(int opmode, Key key) throws InvalidKeyException {
615         if (secureRandom == null) {
616             // In theory it might be thread-unsafe but in the given case it's OK
617             // since it does not matter which SecureRandom instance is passed
618             // to the init()
619             secureRandom = new SecureRandom();
620         }
621         init(opmode, key, secureRandom);
622     }
623 
624     /**
625      * Initializes this cipher instance with the specified key and a source of
626      * randomness.
627      * <p>
628      * The cipher is initialized for the specified operational mode (one of:
629      * encryption, decryption, key wrapping or key unwrapping) depending on
630      * {@code opmode}.
631      * <p>
632      * If this cipher instance needs any algorithm parameters or random values
633      * that the specified key can not provide, the underlying implementation of
634      * this cipher is supposed to generate the required parameters (using its
635      * provider or random values). Random values are generated using {@code
636      * random};
637      * <p>
638      * When a cipher instance is initialized by a call to any of the {@code
639      * init} methods, the state of the instance is overridden, means it is
640      * equivalent to creating a new instance and calling it {@code init} method.
641      *
642      * @param opmode
643      *            the operation this cipher instance should be initialized for
644      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
645      *            WRAP_MODE} or {@code UNWRAP_MODE}).
646      * @param key
647      *            the input key for the operation.
648      * @param random
649      *            the source of randomness to use.
650      * @throws InvalidKeyException
651      *             if the specified key can not be used to initialize this
652      *             cipher instance.
653      * @throws InvalidParameterException
654      *             if the specified opmode is invalid.
655      */
init(int opmode, Key key, SecureRandom random)656     public final void init(int opmode, Key key, SecureRandom random) throws InvalidKeyException {
657         checkMode(opmode);
658         //        FIXME InvalidKeyException
659         //        if keysize exceeds the maximum allowable keysize
660         //        (jurisdiction policy files)
661         getSpi(key).engineInit(opmode, key, random);
662         mode = opmode;
663     }
664 
665     /**
666      * Initializes this cipher instance with the specified key and algorithm
667      * parameters.
668      * <p>
669      * The cipher is initialized for the specified operational mode (one of:
670      * encryption, decryption, key wrapping or key unwrapping).
671      * <p>
672      * If this cipher instance needs any algorithm parameters and {@code params}
673      * is {@code null}, the underlying implementation of this cipher is supposed
674      * to generate the required parameters (using its provider or random
675      * values).
676      * <p>
677      * When a cipher instance is initialized by a call to any of the {@code
678      * init} methods, the state of the instance is overridden, means it is
679      * equivalent to creating a new instance and calling it {@code init} method.
680      *
681      * @param opmode
682      *            the operation this cipher instance should be initialized for
683      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
684      *            WRAP_MODE} or {@code UNWRAP_MODE}).
685      * @param key
686      *            the input key for the operation.
687      * @param params
688      *            the algorithm parameters.
689      * @throws InvalidKeyException
690      *             if the specified key can not be used to initialize this
691      *             cipher instance.
692      * @throws InvalidAlgorithmParameterException
693      *             it the specified parameters are inappropriate for this
694      *             cipher.
695      */
init(int opmode, Key key, AlgorithmParameterSpec params)696     public final void init(int opmode, Key key, AlgorithmParameterSpec params)
697             throws InvalidKeyException, InvalidAlgorithmParameterException {
698         if (secureRandom == null) {
699             secureRandom = new SecureRandom();
700         }
701         init(opmode, key, params, secureRandom);
702     }
703 
704     /**
705      * Initializes this cipher instance with the specified key, algorithm
706      * parameters and a source of randomness.
707      * <p>
708      * The cipher is initialized for the specified operational mode (one of:
709      * encryption, decryption, key wrapping or key unwrapping) depending on
710      * {@code opmode}.
711      * <p>
712      * If this cipher instance needs any algorithm parameters and {@code params}
713      * is {@code null}, the underlying implementation of this cipher is supposed
714      * to generate the required parameters (using its provider or random
715      * values). Random values are generated using {@code random};
716      * <p>
717      * When a cipher instance is initialized by a call to any of the {@code
718      * init} methods, the state of the instance is overridden, meaning that it
719      * is equivalent to creating a new instance and calling it {@code init}
720      * method.
721      *
722      * @param opmode
723      *            the operation this cipher instance should be initialized for
724      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
725      *            WRAP_MODE} or {@code UNWRAP_MODE}).
726      * @param key
727      *            the input key for the operation.
728      * @param params
729      *            the algorithm parameters.
730      * @param random
731      *            the source of randomness to use.
732      * @throws InvalidKeyException
733      *             if the specified key can not be used to initialize this
734      *             cipher instance.
735      * @throws InvalidAlgorithmParameterException
736      *             it the specified parameters are inappropriate for this
737      *             cipher.
738      * @throws InvalidParameterException
739      *             if the specified {@code opmode} is invalid.
740      */
init(int opmode, Key key, AlgorithmParameterSpec params, SecureRandom random)741     public final void init(int opmode, Key key, AlgorithmParameterSpec params,
742             SecureRandom random) throws InvalidKeyException,
743             InvalidAlgorithmParameterException {
744         checkMode(opmode);
745         //        FIXME InvalidKeyException
746         //        if keysize exceeds the maximum allowable keysize
747         //        (jurisdiction policy files)
748         //        FIXME InvalidAlgorithmParameterException
749         //        cryptographic strength exceed the legal limits
750         //        (jurisdiction policy files)
751         getSpi(key).engineInit(opmode, key, params, random);
752         mode = opmode;
753     }
754 
755     /**
756      * Initializes this cipher instance with the specified key and algorithm
757      * parameters.
758      * <p>
759      * The cipher is initialized for the specified operation (one of:
760      * encryption, decryption, key wrapping or key unwrapping) depending on
761      * {@code opmode}.
762      * <p>
763      * If this cipher instance needs any algorithm parameters and {@code params}
764      * is {@code null}, the underlying implementation of this cipher is supposed
765      * to generate the required parameters (using its provider or random
766      * values).
767      * <p>
768      * When a cipher instance is initialized by a call to any of the {@code
769      * init} methods, the state of the instance is overridden, meaning that it
770      * is equivalent to creating a new instance and calling it {@code init}
771      * method.
772      *
773      * @param opmode
774      *            the operation this cipher instance should be initialized for
775      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
776      *            WRAP_MODE} or {@code UNWRAP_MODE}).
777      * @param key
778      *            the input key for the operation.
779      * @param params
780      *            the algorithm parameters.
781      * @throws InvalidKeyException
782      *             if the specified key can not be used to initialize this
783      *             cipher instance.
784      * @throws InvalidAlgorithmParameterException
785      *             it the specified parameters are inappropriate for this
786      *             cipher.
787      */
init(int opmode, Key key, AlgorithmParameters params)788     public final void init(int opmode, Key key, AlgorithmParameters params)
789             throws InvalidKeyException, InvalidAlgorithmParameterException {
790         if (secureRandom == null) {
791             secureRandom = new SecureRandom();
792         }
793         init(opmode, key, params, secureRandom);
794     }
795 
796     /**
797      * Initializes this cipher instance with the specified key, algorithm
798      * parameters and a source of randomness.
799      * <p>
800      * The cipher will be initialized for the specified operation (one of:
801      * encryption, decryption, key wrapping or key unwrapping) depending on
802      * {@code opmode}.
803      * <p>
804      * If this cipher instance needs any algorithm parameters and {@code params}
805      * is {@code null}, the underlying implementation of this cipher is supposed
806      * to generate the required parameters (using its provider or random
807      * values). Random values are generated using {@code random}.
808      * <p>
809      * When a cipher instance is initialized by a call to any of the {@code
810      * init} methods, the state of the instance is overridden, means it is
811      * equivalent to creating a new instance and calling it {@code init} method.
812      *
813      * @param opmode
814      *            the operation this cipher instance should be initialized for
815      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
816      *            WRAP_MODE} or {@code UNWRAP_MODE}).
817      * @param key
818      *            the input key for the operation.
819      * @param params
820      *            the algorithm parameters.
821      * @param random
822      *            the source of randomness to use.
823      * @throws InvalidKeyException
824      *             if the specified key can not be used to initialize this
825      *             cipher instance.
826      * @throws InvalidAlgorithmParameterException
827      *             if the specified parameters are inappropriate for this
828      *             cipher.
829      * @throws InvalidParameterException
830      *             if the specified {@code opmode} is invalid.
831      */
init(int opmode, Key key, AlgorithmParameters params, SecureRandom random)832     public final void init(int opmode, Key key, AlgorithmParameters params,
833             SecureRandom random) throws InvalidKeyException,
834             InvalidAlgorithmParameterException {
835         checkMode(opmode);
836         //        FIXME InvalidKeyException
837         //        if keysize exceeds the maximum allowable keysize
838         //        (jurisdiction policy files)
839         //        FIXME InvalidAlgorithmParameterException
840         //        cryptographic strength exceed the legal limits
841         //        (jurisdiction policy files)
842         getSpi(key).engineInit(opmode, key, params, random);
843         mode = opmode;
844     }
845 
846     /**
847      * Initializes this cipher instance with the public key from the specified
848      * certificate.
849      * <p>
850      * The cipher will be initialized for the specified operation (one of:
851      * encryption, decryption, key wrapping or key unwrapping) depending on
852      * {@code opmode}.
853      * <p>
854      * It the type of the certificate is X.509 and the certificate has a <i>key
855      * usage</i> extension field marked as critical, the specified {@code
856      * opmode} has the be enabled for this key, otherwise an {@code
857      * InvalidKeyException} is thrown.
858      * <p>
859      * If this cipher instance needs any algorithm parameters that the key in
860      * the certificate can not provide, the underlying implementation of this
861      * cipher is supposed to generate the required parameters (using its
862      * provider or random values).
863      * <p>
864      * When a cipher instance is initialized by a call to any of the {@code
865      * init} methods, the state of the instance is overridden, means it is
866      * equivalent to creating a new instance and calling it {@code init} method.
867      *
868      * @param opmode
869      *            the operation this cipher instance should be initialized for
870      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
871      *            WRAP_MODE} or {@code UNWRAP_MODE}).
872      * @param certificate
873      *            the certificate.
874      * @throws InvalidKeyException
875      *             if the public key in the certificate can not be used to
876      *             initialize this cipher instance.
877      */
init(int opmode, Certificate certificate)878     public final void init(int opmode, Certificate certificate)
879             throws InvalidKeyException {
880         if (secureRandom == null) {
881             secureRandom = new SecureRandom();
882         }
883         init(opmode, certificate, secureRandom);
884     }
885 
886     /**
887      * Initializes this cipher instance with the public key from the specified
888      * certificate and a source of randomness.
889      * <p>
890      * The cipher will be initialized for the specified operation (one of:
891      * encryption, decryption, key wrapping or key unwrapping) depending on
892      * {@code opmode}.
893      * <p>
894      * It the type of the certificate is X.509 and the certificate has a <i>key
895      * usage</i> extension field marked as critical, the specified {@code
896      * opmode} has the be enabled for this key, otherwise an {@code
897      * InvalidKeyException} is thrown.
898      * <p>
899      * If this cipher instance needs any algorithm parameters that the key in
900      * the certificate can not provide, the underlying implementation of this
901      * cipher is supposed to generate the required parameters (using its
902      * provider or random values). Random values are generated using {@code
903      * random}.
904      * <p>
905      * When a cipher instance is initialized by a call to any of the {@code
906      * init} methods, the state of the instance is overridden, means it is
907      * equivalent to creating a new instance and calling it {@code init} method.
908      *
909      * @param opmode
910      *            the operation this cipher instance should be initialized for
911      *            (one of: {@code ENCRYPT_MODE}, {@code DECRYPT_MODE}, {@code
912      *            WRAP_MODE} or {@code UNWRAP_MODE}).
913      * @param certificate
914      *            the certificate.
915      * @param random
916      *            the source of randomness to be used.
917      * @throws InvalidKeyException
918      *             if the public key in the certificate can not be used to
919      *             initialize this cipher instance.
920      */
init(int opmode, Certificate certificate, SecureRandom random)921     public final void init(int opmode, Certificate certificate,
922             SecureRandom random) throws InvalidKeyException {
923         checkMode(opmode);
924         if (certificate instanceof X509Certificate) {
925             Set<String> ce = ((X509Certificate) certificate).getCriticalExtensionOIDs();
926             boolean critical = false;
927             if (ce != null && !ce.isEmpty()) {
928                 for (String oid : ce) {
929                     if (oid.equals("2.5.29.15")) { // KeyUsage OID = 2.5.29.15
930                         critical = true;
931                         break;
932                     }
933                 }
934                 if (critical) {
935                     boolean[] keyUsage = ((X509Certificate) certificate).getKeyUsage();
936                     // As specified in RFC 3280:
937                     //   Internet X.509 Public Key Infrastructure
938                     //   Certificate and Certificate Revocation List (CRL) Profile.
939                     // Section 4.2.1.3  Key Usage
940                     // http://www.ietf.org/rfc/rfc3280.txt
941                     //
942                     // KeyUsage ::= BIT STRING {digitalSignature (0),
943                     //                          nonRepudiation   (1),
944                     //                          keyEncipherment  (2),
945                     //                          dataEncipherment (3),
946                     //                          keyAgreement     (4),
947                     //                          keyCertSign      (5),
948                     //                          cRLSign          (6),
949                     //                          encipherOnly     (7),
950                     //                          decipherOnly     (8) }
951                     if (keyUsage != null) {
952                         if (opmode == ENCRYPT_MODE && !keyUsage[3]) {
953                             throw new InvalidKeyException("The public key in the certificate "
954                                                           + "cannot be used for ENCRYPT_MODE");
955                         } else if (opmode == WRAP_MODE && !keyUsage[2]) {
956                             throw new InvalidKeyException("The public key in the certificate "
957                                                           + "cannot be used for WRAP_MODE");
958                         }
959                     }
960                 }
961             }
962         }
963         //        FIXME InvalidKeyException
964         //        if keysize exceeds the maximum allowable keysize
965         //        (jurisdiction policy files)
966         final Key key = certificate.getPublicKey();
967         getSpi(key).engineInit(opmode, key, random);
968         mode = opmode;
969     }
970 
971     /**
972      * Continues a multi-part transformation (encryption or decryption). The
973      * transformed bytes are returned.
974      *
975      * @param input
976      *            the input bytes to transform.
977      * @return the transformed bytes in a new buffer, or {@code null} if the
978      *         input has zero length.
979      * @throws IllegalStateException
980      *             if this cipher instance is not initialized for encryption or
981      *             decryption.
982      * @throws IllegalArgumentException
983      *             if the input is {@code null}.
984      */
update(byte[] input)985     public final byte[] update(byte[] input) {
986         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
987             throw new IllegalStateException();
988         }
989         if (input == null) {
990             throw new IllegalArgumentException("input == null");
991         }
992         if (input.length == 0) {
993             return null;
994         }
995         return getSpi().engineUpdate(input, 0, input.length);
996     }
997 
998     /**
999      * Continues a multi-part transformation (encryption or decryption). The
1000      * transformed bytes are returned.
1001      *
1002      * @param input
1003      *            the input bytes to transform.
1004      * @param inputOffset
1005      *            the offset in the input to start.
1006      * @param inputLen
1007      *            the length of the input to transform.
1008      * @return the transformed bytes in a new buffer, or {@code null} if the
1009      *         input has zero length.
1010      * @throws IllegalStateException
1011      *             if this cipher instance is not initialized for encryption or
1012      *             decryption.
1013      * @throws IllegalArgumentException
1014      *             if {@code input} is {@code null}, or if {@code inputOffset} and
1015      *             {@code inputLen} do not specify a valid chunk in the input
1016      *             buffer.
1017      */
update(byte[] input, int inputOffset, int inputLen)1018     public final byte[] update(byte[] input, int inputOffset, int inputLen) {
1019         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1020             throw new IllegalStateException();
1021         }
1022         if (input == null) {
1023             throw new IllegalArgumentException("input == null");
1024         }
1025         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1026         if (input.length == 0) {
1027             return null;
1028         }
1029         return getSpi().engineUpdate(input, inputOffset, inputLen);
1030     }
1031 
checkInputOffsetAndCount(int inputArrayLength, int inputOffset, int inputLen)1032     private static void checkInputOffsetAndCount(int inputArrayLength,
1033                                                  int inputOffset,
1034                                                  int inputLen) {
1035         if ((inputOffset | inputLen) < 0
1036                 || inputOffset > inputArrayLength
1037                 || inputArrayLength - inputOffset < inputLen) {
1038             throw new IllegalArgumentException("input.length=" + inputArrayLength
1039                                                + "; inputOffset=" + inputOffset
1040                                                + "; inputLen=" + inputLen);
1041         }
1042     }
1043 
1044     /**
1045      * Continues a multi-part transformation (encryption or decryption). The
1046      * transformed bytes are stored in the {@code output} buffer.
1047      * <p>
1048      * If the size of the {@code output} buffer is too small to hold the result,
1049      * a {@code ShortBufferException} is thrown. Use
1050      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1051      * output buffer.
1052      *
1053      * @param input
1054      *            the input bytes to transform.
1055      * @param inputOffset
1056      *            the offset in the input to start.
1057      * @param inputLen
1058      *            the length of the input to transform.
1059      * @param output
1060      *            the output buffer.
1061      * @return the number of bytes placed in output.
1062      * @throws ShortBufferException
1063      *             if the size of the {@code output} buffer is too small.
1064      * @throws IllegalStateException
1065      *             if this cipher instance is not initialized for encryption or
1066      *             decryption.
1067      * @throws IllegalArgumentException
1068      *             if the input is {@code null}, the output is {@code null}, or
1069      *             if {@code inputOffset} and {@code inputLen} do not specify a
1070      *             valid chunk in the input buffer.
1071      */
update(byte[] input, int inputOffset, int inputLen, byte[] output)1072     public final int update(byte[] input, int inputOffset, int inputLen,
1073             byte[] output) throws ShortBufferException {
1074         return update(input, inputOffset, inputLen, output, 0);
1075     }
1076 
1077     /**
1078      * Continues a multi-part transformation (encryption or decryption). The
1079      * transformed bytes are stored in the {@code output} buffer.
1080      * <p>
1081      * If the size of the {@code output} buffer is too small to hold the result,
1082      * a {@code ShortBufferException} is thrown. Use
1083      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1084      * output buffer.
1085      *
1086      * @param input
1087      *            the input bytes to transform.
1088      * @param inputOffset
1089      *            the offset in the input to start.
1090      * @param inputLen
1091      *            the length of the input to transform.
1092      * @param output
1093      *            the output buffer.
1094      * @param outputOffset
1095      *            the offset in the output buffer.
1096      * @return the number of bytes placed in output.
1097      * @throws ShortBufferException
1098      *             if the size of the {@code output} buffer is too small.
1099      * @throws IllegalStateException
1100      *             if this cipher instance is not initialized for encryption or
1101      *             decryption.
1102      * @throws IllegalArgumentException
1103      *             if the input is {@code null}, the output is {@code null}, or
1104      *             if {@code inputOffset} and {@code inputLen} do not specify a
1105      *             valid chunk in the input buffer.
1106      */
update(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)1107     public final int update(byte[] input, int inputOffset, int inputLen,
1108             byte[] output, int outputOffset) throws ShortBufferException {
1109         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1110             throw new IllegalStateException();
1111         }
1112         if (input == null) {
1113             throw new IllegalArgumentException("input == null");
1114         }
1115         if (output == null) {
1116             throw new IllegalArgumentException("output == null");
1117         }
1118         if (outputOffset < 0) {
1119             throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset);
1120         }
1121         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1122         if (input.length == 0) {
1123             return 0;
1124         }
1125         return getSpi().engineUpdate(input, inputOffset, inputLen, output,
1126                 outputOffset);
1127     }
1128 
1129     /**
1130      * Continues a multi-part transformation (encryption or decryption). The
1131      * {@code input.remaining()} bytes starting at {@code input.position()} are
1132      * transformed and stored in the {@code output} buffer.
1133      * <p>
1134      * If the {@code output.remaining()} is too small to hold the transformed
1135      * bytes a {@code ShortBufferException} is thrown. Use
1136      * {@link Cipher#getOutputSize getOutputSize} to check for the size of the
1137      * output buffer.
1138      *
1139      * @param input
1140      *            the input buffer to transform.
1141      * @param output
1142      *            the output buffer to store the result within.
1143      * @return the number of bytes stored in the output buffer.
1144      * @throws ShortBufferException
1145      *             if the size of the {@code output} buffer is too small.
1146      * @throws IllegalStateException
1147      *             if this cipher instance is not initialized for encryption or
1148      *             decryption.
1149      * @throws IllegalArgumentException
1150      *             if the input buffer and the output buffer are the identical
1151      *             object.
1152      */
update(ByteBuffer input, ByteBuffer output)1153     public final int update(ByteBuffer input, ByteBuffer output)
1154             throws ShortBufferException {
1155         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1156             throw new IllegalStateException();
1157         }
1158         if (input == output) {
1159             throw new IllegalArgumentException("input == output");
1160         }
1161         return getSpi().engineUpdate(input, output);
1162     }
1163 
1164     /**
1165      * Continues a multi-part transformation (encryption or decryption) with
1166      * Authenticated Additional Data (AAD). AAD may only be added after the
1167      * {@code Cipher} is initialized and before any data is passed to the
1168      * instance.
1169      * <p>
1170      * This is only usable with cipher modes that support Authenticated
1171      * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1172      *
1173      * @param input bytes of AAD to use with the cipher
1174      * @throws IllegalStateException
1175      *             if this cipher instance is not initialized for encryption or
1176      *             decryption.
1177      * @throws IllegalArgumentException
1178      *             if {@code input} is {@code null}
1179      * @throws UnsupportedOperationException if the cipher does not support AEAD
1180      * @since 1.7
1181      */
updateAAD(byte[] input)1182     public final void updateAAD(byte[] input) {
1183         if (input == null) {
1184             throw new IllegalArgumentException("input == null");
1185         }
1186         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1187             throw new IllegalStateException();
1188         }
1189         if (input.length == 0) {
1190             return;
1191         }
1192         getSpi().engineUpdateAAD(input, 0, input.length);
1193     }
1194 
1195     /**
1196      * Continues a multi-part transformation (encryption or decryption) with
1197      * Authenticated Additional Data (AAD). AAD may only be added after the
1198      * {@code Cipher} is initialized and before any data is passed to the
1199      * instance.
1200      * <p>
1201      * This is only usable with cipher modes that support Authenticated
1202      * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1203      *
1204      * @param input bytes of AAD to use with the cipher
1205      * @param inputOffset offset within bytes of additional data to add to cipher
1206      * @param inputLen length of bytes of additional data to add to cipher
1207      * @throws IllegalStateException
1208      *             if this cipher instance is not initialized for encryption or
1209      *             decryption.
1210      * @throws IllegalArgumentException
1211      *             if {@code input} is {@code null}, or if {@code inputOffset} and
1212      *             {@code inputLen} do not specify a valid chunk in the input
1213      *             buffer.
1214      * @throws UnsupportedOperationException if the cipher does not support AEAD
1215      * @since 1.7
1216      */
updateAAD(byte[] input, int inputOffset, int inputLen)1217     public final void updateAAD(byte[] input, int inputOffset, int inputLen) {
1218         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1219             throw new IllegalStateException();
1220         }
1221         if (input == null) {
1222             throw new IllegalArgumentException("input == null");
1223         }
1224         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1225         if (input.length == 0) {
1226             return;
1227         }
1228         getSpi().engineUpdateAAD(input, inputOffset, inputLen);
1229     }
1230 
1231     /**
1232      * Continues a multi-part transformation (encryption or decryption) with
1233      * Authenticated Additional Data (AAD). AAD may only be added after the
1234      * {@code Cipher} is initialized and before any data is passed to the
1235      * instance.
1236      * <p>
1237      * This is only usable with cipher modes that support Authenticated
1238      * Encryption with Additional Data (AEAD) such as Galois/Counter Mode (GCM).
1239      *
1240      * @param input buffer of AAD to be used
1241      * @throws IllegalStateException
1242      *             if this cipher instance is not initialized for encryption or
1243      *             decryption.
1244      * @throws UnsupportedOperationException if the cipher does not support AEAD
1245      * @since 1.7
1246      */
updateAAD(ByteBuffer input)1247     public final void updateAAD(ByteBuffer input) {
1248         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1249             throw new IllegalStateException("Cipher is not initialized");
1250         }
1251         if (input == null) {
1252             throw new IllegalArgumentException("input == null");
1253         }
1254         getSpi().engineUpdateAAD(input);
1255     }
1256 
1257     /**
1258      * Finishes a multi-part transformation (encryption or decryption).
1259      * <p>
1260      * Processes any bytes that may have been buffered in previous {@code
1261      * update} calls.
1262      *
1263      * @return the final bytes from the transformation.
1264      * @throws IllegalBlockSizeException
1265      *             if the size of the resulting bytes is not a multiple of the
1266      *             cipher block size.
1267      * @throws BadPaddingException
1268      *             if the padding of the data does not match the padding scheme.
1269      * @throws IllegalStateException
1270      *             if this cipher instance is not initialized for encryption or
1271      *             decryption.
1272      */
doFinal()1273     public final byte[] doFinal() throws IllegalBlockSizeException,
1274             BadPaddingException {
1275         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1276             throw new IllegalStateException();
1277         }
1278         return getSpi().engineDoFinal(null, 0, 0);
1279     }
1280 
1281     /**
1282      * Finishes a multi-part transformation (encryption or decryption).
1283      * <p>
1284      * Processes any bytes that may have been buffered in previous {@code
1285      * update} calls.
1286      * <p>
1287      * The final transformed bytes are stored in the {@code output} buffer.
1288      *
1289      * @param output
1290      *            the output buffer.
1291      * @param outputOffset
1292      *            the offset in the output buffer.
1293      * @return the number of bytes placed in the output buffer.
1294      * @throws IllegalBlockSizeException
1295      *             if the size of the resulting bytes is not a multiple of the
1296      *             cipher block size.
1297      * @throws ShortBufferException
1298      *             if the size of the {@code output} buffer is too small.
1299      * @throws BadPaddingException
1300      *             if the padding of the data does not match the padding scheme.
1301      * @throws IllegalStateException
1302      *             if this cipher instance is not initialized for encryption or
1303      *             decryption.
1304      */
doFinal(byte[] output, int outputOffset)1305     public final int doFinal(byte[] output, int outputOffset)
1306             throws IllegalBlockSizeException, ShortBufferException,
1307             BadPaddingException {
1308         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1309             throw new IllegalStateException();
1310         }
1311         if (outputOffset < 0) {
1312             throw new IllegalArgumentException("outputOffset < 0. outputOffset=" + outputOffset);
1313         }
1314         return getSpi().engineDoFinal(null, 0, 0, output, outputOffset);
1315     }
1316 
1317     /**
1318      * Finishes a multi-part transformation (encryption or decryption).
1319      * <p>
1320      * Processes the bytes in {@code input} buffer, and any bytes that have been
1321      * buffered in previous {@code update} calls.
1322      *
1323      * @param input
1324      *            the input buffer.
1325      * @return the final bytes from the transformation.
1326      * @throws IllegalBlockSizeException
1327      *             if the size of the resulting bytes is not a multiple of the
1328      *             cipher block size.
1329      * @throws BadPaddingException
1330      *             if the padding of the data does not match the padding scheme.
1331      * @throws IllegalStateException
1332      *             if this cipher instance is not initialized for encryption or
1333      *             decryption.
1334      */
doFinal(byte[] input)1335     public final byte[] doFinal(byte[] input) throws IllegalBlockSizeException,
1336             BadPaddingException {
1337         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1338             throw new IllegalStateException();
1339         }
1340         return getSpi().engineDoFinal(input, 0, input.length);
1341     }
1342 
1343     /**
1344      * Finishes a multi-part transformation (encryption or decryption).
1345      * <p>
1346      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1347      * inputOffset}, and any bytes that have been buffered in previous {@code
1348      * update} calls.
1349      *
1350      * @param input
1351      *            the input buffer.
1352      * @param inputOffset
1353      *            the offset in the input buffer.
1354      * @param inputLen
1355      *            the length of the input
1356      * @return the final bytes from the transformation.
1357      * @throws IllegalBlockSizeException
1358      *             if the size of the resulting bytes is not a multiple of the
1359      *             cipher block size.
1360      * @throws BadPaddingException
1361      *             if the padding of the data does not match the padding scheme.
1362      * @throws IllegalStateException
1363      *             if this cipher instance is not initialized for encryption or
1364      *             decryption.
1365      * @throws IllegalArgumentException
1366      *             if {@code inputOffset} and {@code inputLen} do not specify an
1367      *             valid chunk in the input buffer.
1368      */
doFinal(byte[] input, int inputOffset, int inputLen)1369     public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
1370             throws IllegalBlockSizeException, BadPaddingException {
1371         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1372             throw new IllegalStateException();
1373         }
1374         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1375         return getSpi().engineDoFinal(input, inputOffset, inputLen);
1376     }
1377 
1378     /**
1379      * Finishes a multi-part transformation (encryption or decryption).
1380      * <p>
1381      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1382      * inputOffset}, and any bytes that have been buffered in previous {@code
1383      * update} calls.
1384      *
1385      * @param input
1386      *            the input buffer.
1387      * @param inputOffset
1388      *            the offset in the input buffer.
1389      * @param inputLen
1390      *            the length of the input.
1391      * @param output
1392      *            the output buffer for the transformed bytes.
1393      * @return the number of bytes placed in the output buffer.
1394      * @throws ShortBufferException
1395      *             if the size of the {@code output} buffer is too small.
1396      * @throws IllegalBlockSizeException
1397      *             if the size of the resulting bytes is not a multiple of the
1398      *             cipher block size.
1399      * @throws BadPaddingException
1400      *             if the padding of the data does not match the padding scheme.
1401      * @throws IllegalStateException
1402      *             if this cipher instance is not initialized for encryption or
1403      *             decryption.
1404      * @throws IllegalArgumentException
1405      *             if {@code inputOffset} and {@code inputLen} do not specify an
1406      *             valid chunk in the input buffer.
1407      */
doFinal(byte[] input, int inputOffset, int inputLen, byte[] output)1408     public final int doFinal(byte[] input, int inputOffset, int inputLen,
1409             byte[] output) throws ShortBufferException,
1410             IllegalBlockSizeException, BadPaddingException {
1411         return doFinal(input, inputOffset, inputLen, output, 0);
1412     }
1413 
1414     /**
1415      * Finishes a multi-part transformation (encryption or decryption).
1416      * <p>
1417      * Processes the {@code inputLen} bytes in {@code input} buffer at {@code
1418      * inputOffset}, and any bytes that have been buffered in previous {@code
1419      * update} calls.
1420      *
1421      * @param input
1422      *            the input buffer.
1423      * @param inputOffset
1424      *            the offset in the input buffer.
1425      * @param inputLen
1426      *            the length of the input.
1427      * @param output
1428      *            the output buffer for the transformed bytes.
1429      * @param outputOffset
1430      *            the offset in the output buffer.
1431      * @return the number of bytes placed in the output buffer.
1432      * @throws ShortBufferException
1433      *             if the size of the {@code output} buffer is too small.
1434      * @throws IllegalBlockSizeException
1435      *             if the size of the resulting bytes is not a multiple of the
1436      *             cipher block size.
1437      * @throws BadPaddingException
1438      *             if the padding of the data does not match the padding scheme.
1439      * @throws IllegalStateException
1440      *             if this cipher instance is not initialized for encryption or
1441      *             decryption.
1442      * @throws IllegalArgumentException
1443      *             if {@code inputOffset} and {@code inputLen} do not specify an
1444      *             valid chunk in the input buffer.
1445      */
doFinal(byte[] input, int inputOffset, int inputLen, byte[] output, int outputOffset)1446     public final int doFinal(byte[] input, int inputOffset, int inputLen,
1447             byte[] output, int outputOffset) throws ShortBufferException,
1448             IllegalBlockSizeException, BadPaddingException {
1449         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1450             throw new IllegalStateException();
1451         }
1452         checkInputOffsetAndCount(input.length, inputOffset, inputLen);
1453         return getSpi().engineDoFinal(input, inputOffset, inputLen, output,
1454                 outputOffset);
1455     }
1456 
1457     /**
1458      * Finishes a multi-part transformation (encryption or decryption).
1459      * <p>
1460      * Processes the {@code input.remaining()} bytes in {@code input} buffer at
1461      * {@code input.position()}, and any bytes that have been buffered in
1462      * previous {@code update} calls. The transformed bytes are placed into
1463      * {@code output} buffer.
1464      *
1465      * @param input
1466      *            the input buffer.
1467      * @param output
1468      *            the output buffer.
1469      * @return the number of bytes placed into the output buffer.
1470      * @throws ShortBufferException
1471      *             if the size of the {@code output} buffer is too small.
1472      * @throws IllegalBlockSizeException
1473      *             if the size of the resulting bytes is not a multiple of the
1474      *             cipher block size.
1475      * @throws BadPaddingException
1476      *             if the padding of the data does not match the padding scheme.
1477      * @throws IllegalArgumentException
1478      *             if the input buffer and the output buffer are the same
1479      *             object.
1480      * @throws IllegalStateException
1481      *             if this cipher instance is not initialized for encryption or
1482      *             decryption.
1483      */
doFinal(ByteBuffer input, ByteBuffer output)1484     public final int doFinal(ByteBuffer input, ByteBuffer output)
1485             throws ShortBufferException, IllegalBlockSizeException,
1486             BadPaddingException {
1487         if (mode != ENCRYPT_MODE && mode != DECRYPT_MODE) {
1488             throw new IllegalStateException();
1489         }
1490         if (input == output) {
1491             throw new IllegalArgumentException("input == output");
1492         }
1493         return getSpi().engineDoFinal(input, output);
1494     }
1495 
1496     /**
1497      * Wraps a key using this cipher instance.
1498      *
1499      * @param key
1500      *            the key to wrap.
1501      * @return the wrapped key.
1502      * @throws IllegalBlockSizeException
1503      *             if the size of the resulting bytes is not a multiple of the
1504      *             cipher block size.
1505      * @throws InvalidKeyException
1506      *             if this cipher instance can not wrap this key.
1507      * @throws IllegalStateException
1508      *             if this cipher instance is not initialized for wrapping.
1509      */
wrap(Key key)1510     public final byte[] wrap(Key key) throws IllegalBlockSizeException,
1511             InvalidKeyException {
1512         if (mode != WRAP_MODE) {
1513             throw new IllegalStateException();
1514         }
1515         return getSpi().engineWrap(key);
1516     }
1517 
1518     /**
1519      * Unwraps a key using this cipher instance.
1520      *
1521      * @param wrappedKey
1522      *            the wrapped key to unwrap.
1523      * @param wrappedKeyAlgorithm
1524      *            the algorithm for the wrapped key.
1525      * @param wrappedKeyType
1526      *            the type of the wrapped key (one of: {@code SECRET_KEY
1527      *            <code>, <code>PRIVATE_KEY} or {@code PUBLIC_KEY})
1528      * @return the unwrapped key
1529      * @throws InvalidKeyException
1530      *             if the {@code wrappedKey} can not be unwrapped to a key of
1531      *             type {@code wrappedKeyType} for the {@code
1532      *             wrappedKeyAlgorithm}.
1533      * @throws NoSuchAlgorithmException
1534      *             if no provider can be found that can create a key of type
1535      *             {@code wrappedKeyType} for the {@code wrappedKeyAlgorithm}.
1536      * @throws IllegalStateException
1537      *             if this cipher instance is not initialized for unwrapping.
1538      */
unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, int wrappedKeyType)1539     public final Key unwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
1540             int wrappedKeyType) throws InvalidKeyException,
1541             NoSuchAlgorithmException {
1542         if (mode != UNWRAP_MODE) {
1543             throw new IllegalStateException();
1544         }
1545         return getSpi().engineUnwrap(wrappedKey, wrappedKeyAlgorithm,
1546                 wrappedKeyType);
1547     }
1548 
1549     /**
1550      * Returns the maximum key length for the specified transformation.
1551      *
1552      * @param transformation
1553      *            the transformation name.
1554      * @return the maximum key length, currently {@code Integer.MAX_VALUE}.
1555      * @throws NoSuchAlgorithmException
1556      *             if no provider for the specified {@code transformation} can
1557      *             be found.
1558      * @throws NullPointerException
1559      *             if {@code transformation} is {@code null}.
1560      */
getMaxAllowedKeyLength(String transformation)1561     public static final int getMaxAllowedKeyLength(String transformation)
1562             throws NoSuchAlgorithmException {
1563         if (transformation == null) {
1564             throw new NullPointerException("transformation == null");
1565         }
1566         checkTransformation(transformation);
1567         //FIXME jurisdiction policy files
1568         return Integer.MAX_VALUE;
1569     }
1570 
1571     /**
1572      * Returns the maximum cipher parameter value for the specified
1573      * transformation. If there is no maximum limit, {@code null} is returned.
1574      *
1575      * @param transformation
1576      *            the transformation name.
1577      * @return a parameter spec holding the maximum value or {@code null}.
1578      *         Currently {@code null}.
1579      * @throws NoSuchAlgorithmException
1580      *             if no provider for the specified {@code transformation} can
1581      *             be found.
1582      * @throws NullPointerException
1583      *             if {@code transformation} is {@code null}.
1584      */
getMaxAllowedParameterSpec( String transformation)1585     public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
1586             String transformation) throws NoSuchAlgorithmException {
1587         if (transformation == null) {
1588             throw new NullPointerException("transformation == null");
1589         }
1590         checkTransformation(transformation);
1591         //FIXME jurisdiction policy files
1592         return null;
1593     }
1594 }
1595