History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/crypto/Cipher.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/crypto/Cipher.java+2677−0
@@ -0,0 +1,2677 @@
1+/*
2+ * Copyright (c) 1997, 2011, 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 javax.crypto;
27+
28+import java.util.*;
29+import java.util.regex.*;
30+
31+import static java.util.Locale.ENGLISH;
32+
33+import java.security.*;
34+import java.security.Provider.Service;
35+import java.security.spec.AlgorithmParameterSpec;
36+import java.security.spec.InvalidParameterSpecException;
37+import java.security.cert.Certificate;
38+import java.security.cert.X509Certificate;
39+
40+import javax.crypto.spec.*;
41+
42+import java.nio.ByteBuffer;
43+import java.nio.ReadOnlyBufferException;
44+
45+import sun.security.util.Debug;
46+import sun.security.jca.*;
47+import sun.security.jca.GetInstance.Instance;
48+
49+/**
50+ * This class provides the functionality of a cryptographic cipher for
51+ * encryption and decryption. It forms the core of the Java Cryptographic
52+ * Extension (JCE) framework.
53+ *
54+ * <p>In order to create a Cipher object, the application calls the
55+ * Cipher's <code>getInstance</code> method, and passes the name of the
56+ * requested <i>transformation</i> to it. Optionally, the name of a provider
57+ * may be specified.
58+ *
59+ * <p>A <i>transformation</i> is a string that describes the operation (or
60+ * set of operations) to be performed on the given input, to produce some
61+ * output. A transformation always includes the name of a cryptographic
62+ * algorithm (e.g., <i>DES</i>), and may be followed by a feedback mode and
63+ * padding scheme.
64+ *
65+ * <p> A transformation is of the form:<p>
66+ *
67+ * <ul>
68+ * <li>"<i>algorithm/mode/padding</i>" or
69+ * <p>
70+ * <li>"<i>algorithm</i>"
71+ * </ul>
72+ *
73+ * <P> (in the latter case,
74+ * provider-specific default values for the mode and padding scheme are used).
75+ * For example, the following is a valid transformation:<p>
76+ *
77+ * <pre>
78+ * Cipher c = Cipher.getInstance("<i>DES/CBC/PKCS5Padding</i>");
79+ * </pre>
80+ *
81+ * Using modes such as <code>CFB</code> and <code>OFB</code>, block
82+ * ciphers can encrypt data in units smaller than the cipher's actual
83+ * block size. When requesting such a mode, you may optionally specify
84+ * the number of bits to be processed at a time by appending this number
85+ * to the mode name as shown in the "<code>DES/CFB8/NoPadding</code>" and
86+ * "<code>DES/OFB32/PKCS5Padding</code>" transformations. If no such
87+ * number is specified, a provider-specific default is used. (For
88+ * example, the SunJCE provider uses a default of 64 bits for DES.)
89+ * Thus, block ciphers can be turned into byte-oriented stream ciphers by
90+ * using an 8 bit mode such as CFB8 or OFB8.
91+ * <p>
92+ * Modes such as Authenticated Encryption with Associated Data (AEAD)
93+ * provide authenticity assurances for both confidential data and
94+ * Additional Associated Data (AAD) that is not encrypted. (Please see
95+ * <a href="http://www.ietf.org/rfc/rfc5116.txt"> RFC 5116 </a> for more
96+ * information on AEAD and AEAD algorithms such as GCM/CCM.) Both
97+ * confidential and AAD data can be used when calculating the
98+ * authentication tag (similar to a {@link Mac}). This tag is appended
99+ * to the ciphertext during encryption, and is verified on decryption.
100+ * <p>
101+ * AEAD modes such as GCM/CCM perform all AAD authenticity calculations
102+ * before starting the ciphertext authenticity calculations. To avoid
103+ * implementations having to internally buffer ciphertext, all AAD data
104+ * must be supplied to GCM/CCM implementations (via the {@code
105+ * updateAAD} methods) <b>before</b> the ciphertext is processed (via
106+ * the {@code update} and {@code doFinal} methods).
107+ *
108+ * <pre>
109+ * GCMParameterSpec s = new GCMParameterSpec(...);
110+ * cipher.init(..., s);
111+ *
112+ * // If the GCMParameterSpec is needed again
113+ * cipher.getParameters().getParameterSpec(GCMParameterSpec.class));
114+ *
115+ * cipher.updateAAD(...); // AAD
116+ * cipher.update(...); // Multi-part update
117+ * cipher.doFinal(...); // conclusion of operation
118+ * </pre>
119+ * Every implementation of the Java platform is required to support
120+ * the following standard <code>Cipher</code> transformations with the keysizes
121+ * in parentheses:
122+ * <ul>
123+ * <li><tt>AES/CBC/NoPadding</tt> (128)</li>
124+ * <li><tt>AES/CBC/PKCS5Padding</tt> (128)</li>
125+ * <li><tt>AES/ECB/NoPadding</tt> (128)</li>
126+ * <li><tt>AES/ECB/PKCS5Padding</tt> (128)</li>
127+ * <li><tt>DES/CBC/NoPadding</tt> (56)</li>
128+ * <li><tt>DES/CBC/PKCS5Padding</tt> (56)</li>
129+ * <li><tt>DES/ECB/NoPadding</tt> (56)</li>
130+ * <li><tt>DES/ECB/PKCS5Padding</tt> (56)</li>
131+ * <li><tt>DESede/CBC/NoPadding</tt> (168)</li>
132+ * <li><tt>DESede/CBC/PKCS5Padding</tt> (168)</li>
133+ * <li><tt>DESede/ECB/NoPadding</tt> (168)</li>
134+ * <li><tt>DESede/ECB/PKCS5Padding</tt> (168)</li>
135+ * <li><tt>RSA/ECB/PKCS1Padding</tt> (1024, 2048)</li>
136+ * <li><tt>RSA/ECB/OAEPWithSHA-1AndMGF1Padding</tt> (1024, 2048)</li>
137+ * <li><tt>RSA/ECB/OAEPWithSHA-256AndMGF1Padding</tt> (1024, 2048)</li>
138+ * </ul>
139+ * These transformations are described in the
140+ * <a href="{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
141+ * Cipher section</a> of the
142+ * Java Cryptography Architecture Standard Algorithm Name Documentation.
143+ * Consult the release documentation for your implementation to see if any
144+ * other transformations are supported.
145+ *
146+ * @author Jan Luehe
147+ * @see KeyGenerator
148+ * @see SecretKey
149+ * @since 1.4
150+ */
151+
152+public class Cipher {
153+
154+ private static final Debug debug =
155+ Debug.getInstance("jca", "Cipher");
156+
157+ /**
158+ * Constant used to initialize cipher to encryption mode.
159+ */
160+ public static final int ENCRYPT_MODE = 1;
161+
162+ /**
163+ * Constant used to initialize cipher to decryption mode.
164+ */
165+ public static final int DECRYPT_MODE = 2;
166+
167+ /**
168+ * Constant used to initialize cipher to key-wrapping mode.
169+ */
170+ public static final int WRAP_MODE = 3;
171+
172+ /**
173+ * Constant used to initialize cipher to key-unwrapping mode.
174+ */
175+ public static final int UNWRAP_MODE = 4;
176+
177+ /**
178+ * Constant used to indicate the to-be-unwrapped key is a "public key".
179+ */
180+ public static final int PUBLIC_KEY = 1;
181+
182+ /**
183+ * Constant used to indicate the to-be-unwrapped key is a "private key".
184+ */
185+ public static final int PRIVATE_KEY = 2;
186+
187+ /**
188+ * Constant used to indicate the to-be-unwrapped key is a "secret key".
189+ */
190+ public static final int SECRET_KEY = 3;
191+
192+ // The provider
193+ private Provider provider;
194+
195+ // The provider implementation (delegate)
196+ private CipherSpi spi;
197+
198+ // The transformation
199+ private String transformation;
200+
201+ // Crypto permission representing the maximum allowable cryptographic
202+ // strength that this Cipher object can be used for. (The cryptographic
203+ // strength is a function of the keysize and algorithm parameters encoded
204+ // in the crypto permission.)
205+ private CryptoPermission cryptoPerm;
206+
207+ // The exemption mechanism that needs to be enforced
208+ private ExemptionMechanism exmech;
209+
210+ // Flag which indicates whether or not this cipher has been initialized
211+ private boolean initialized = false;
212+
213+ // The operation mode - store the operation mode after the
214+ // cipher has been initialized.
215+ private int opmode = 0;
216+
217+ // The OID for the KeyUsage extension in an X.509 v3 certificate
218+ private static final String KEY_USAGE_EXTENSION_OID = "2.5.29.15";
219+
220+ // next SPI to try in provider selection
221+ // null once provider is selected
222+ private CipherSpi firstSpi;
223+
224+ // next service to try in provider selection
225+ // null once provider is selected
226+ private Service firstService;
227+
228+ // remaining services to try in provider selection
229+ // null once provider is selected
230+ private Iterator serviceIterator;
231+
232+ // list of transform Strings to lookup in the provider
233+ private List transforms;
234+
235+ private final Object lock;
236+
237+ /**
238+ * Creates a Cipher object.
239+ *
240+ * @param cipherSpi the delegate
241+ * @param provider the provider
242+ * @param transformation the transformation
243+ */
244+ protected Cipher(CipherSpi cipherSpi,
245+ Provider provider,
246+ String transformation) {
247+ // See bug 4341369 & 4334690 for more info.
248+ // If the caller is trusted, then okey.
249+ // Otherwise throw a NullPointerException.
250+ if (!JceSecurityManager.INSTANCE.isCallerTrusted()) {
251+ throw new NullPointerException();
252+ }
253+ this.spi = cipherSpi;
254+ this.provider = provider;
255+ this.transformation = transformation;
256+ this.cryptoPerm = CryptoAllPermission.INSTANCE;
257+ this.lock = null;
258+ }
259+
260+ /**
261+ * Creates a Cipher object. Called internally and by NullCipher.
262+ *
263+ * @param cipherSpi the delegate
264+ * @param transformation the transformation
265+ */
266+ Cipher(CipherSpi cipherSpi, String transformation) {
267+ this.spi = cipherSpi;
268+ this.transformation = transformation;
269+ this.cryptoPerm = CryptoAllPermission.INSTANCE;
270+ this.lock = null;
271+ }
272+
273+ private Cipher(CipherSpi firstSpi, Service firstService,
274+ Iterator serviceIterator, String transformation, List transforms) {
275+ this.firstSpi = firstSpi;
276+ this.firstService = firstService;
277+ this.serviceIterator = serviceIterator;
278+ this.transforms = transforms;
279+ this.transformation = transformation;
280+ this.lock = new Object();
281+ }
282+
283+ private static String[] tokenizeTransformation(String transformation)
284+ throws NoSuchAlgorithmException {
285+ if (transformation == null) {
286+ throw new NoSuchAlgorithmException("No transformation given");
287+ }
288+ /*
289+ * array containing the components of a Cipher transformation:
290+ *
291+ * index 0: algorithm component (e.g., DES)
292+ * index 1: feedback component (e.g., CFB)
293+ * index 2: padding component (e.g., PKCS5Padding)
294+ */
295+ String[] parts = new String[3];
296+ int count = 0;
297+ StringTokenizer parser = new StringTokenizer(transformation, "/");
298+ try {
299+ while (parser.hasMoreTokens() && count < 3) {
300+ parts[count++] = parser.nextToken().trim();
301+ }
302+ if (count == 0 || count == 2 || parser.hasMoreTokens()) {
303+ throw new NoSuchAlgorithmException("Invalid transformation"
304+ + " format:" +
305+ transformation);
306+ }
307+ } catch (NoSuchElementException e) {
308+ throw new NoSuchAlgorithmException("Invalid transformation " +
309+ "format:" + transformation);
310+ }
311+ if ((parts[0] == null) || (parts[0].length() == 0)) {
312+ throw new NoSuchAlgorithmException("Invalid transformation:" +
313+ "algorithm not specified-"
314+ + transformation);
315+ }
316+ return parts;
317+ }
318+
319+ // Provider attribute name for supported chaining mode
320+ private final static String ATTR_MODE = "SupportedModes";
321+ // Provider attribute name for supported padding names
322+ private final static String ATTR_PAD = "SupportedPaddings";
323+
324+ // constants indicating whether the provider supports
325+ // a given mode or padding
326+ private final static int S_NO = 0; // does not support
327+ private final static int S_MAYBE = 1; // unable to determine
328+ private final static int S_YES = 2; // does support
329+
330+ /**
331+ * Nested class to deal with modes and paddings.
332+ */
333+ private static class Transform {
334+ // transform string to lookup in the provider
335+ final String transform;
336+ // the mode/padding suffix in upper case. for example, if the algorithm
337+ // to lookup is "DES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING"
338+ // if loopup is "DES", suffix is the empty string
339+ // needed because aliases prevent straight transform.equals()
340+ final String suffix;
341+ // value to pass to setMode() or null if no such call required
342+ final String mode;
343+ // value to pass to setPadding() or null if no such call required
344+ final String pad;
345+ Transform(String alg, String suffix, String mode, String pad) {
346+ this.transform = alg + suffix;
347+ this.suffix = suffix.toUpperCase(Locale.ENGLISH);
348+ this.mode = mode;
349+ this.pad = pad;
350+ }
351+ // set mode and padding for the given SPI
352+ void setModePadding(CipherSpi spi) throws NoSuchAlgorithmException,
353+ NoSuchPaddingException {
354+ if (mode != null) {
355+ spi.engineSetMode(mode);
356+ }
357+ if (pad != null) {
358+ spi.engineSetPadding(pad);
359+ }
360+ }
361+ // check whether the given services supports the mode and
362+ // padding described by this Transform
363+ int supportsModePadding(Service s) {
364+ int smode = supportsMode(s);
365+ if (smode == S_NO) {
366+ return smode;
367+ }
368+ int spad = supportsPadding(s);
369+ // our constants are defined so that Math.min() is a tri-valued AND
370+ return Math.min(smode, spad);
371+ }
372+
373+ // separate methods for mode and padding
374+ // called directly by Cipher only to throw the correct exception
375+ int supportsMode(Service s) {
376+ return supports(s, ATTR_MODE, mode);
377+ }
378+ int supportsPadding(Service s) {
379+ return supports(s, ATTR_PAD, pad);
380+ }
381+
382+ private static int supports(Service s, String attrName, String value) {
383+ if (value == null) {
384+ return S_YES;
385+ }
386+ String regexp = s.getAttribute(attrName);
387+ if (regexp == null) {
388+ return S_MAYBE;
389+ }
390+ return matches(regexp, value) ? S_YES : S_NO;
391+ }
392+
393+ // Map<String,Pattern> for previously compiled patterns
394+ // XXX use ConcurrentHashMap once available
395+ private final static Map patternCache =
396+ Collections.synchronizedMap(new HashMap());
397+
398+ private static boolean matches(String regexp, String str) {
399+ Pattern pattern = (Pattern)patternCache.get(regexp);
400+ if (pattern == null) {
401+ pattern = Pattern.compile(regexp);
402+ patternCache.put(regexp, pattern);
403+ }
404+ return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches();
405+ }
406+
407+ }
408+
409+ private static List getTransforms(String transformation)
410+ throws NoSuchAlgorithmException {
411+ String[] parts = tokenizeTransformation(transformation);
412+
413+ String alg = parts[0];
414+ String mode = parts[1];
415+ String pad = parts[2];
416+ if ((mode != null) && (mode.length() == 0)) {
417+ mode = null;
418+ }
419+ if ((pad != null) && (pad.length() == 0)) {
420+ pad = null;
421+ }
422+
423+ if ((mode == null) && (pad == null)) {
424+ // DES
425+ Transform tr = new Transform(alg, "", null, null);
426+ return Collections.singletonList(tr);
427+ } else { // if ((mode != null) && (pad != null)) {
428+ // DES/CBC/PKCS5Padding
429+ List list = new ArrayList(4);
430+ list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));
431+ list.add(new Transform(alg, "/" + mode, null, pad));
432+ list.add(new Transform(alg, "//" + pad, mode, null));
433+ list.add(new Transform(alg, "", mode, pad));
434+ return list;
435+ }
436+ }
437+
438+ // get the transform matching the specified service
439+ private static Transform getTransform(Service s, List transforms) {
440+ String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH);
441+ for (Iterator t = transforms.iterator(); t.hasNext(); ) {
442+ Transform tr = (Transform)t.next();
443+ if (alg.endsWith(tr.suffix)) {
444+ return tr;
445+ }
446+ }
447+ return null;
448+ }
449+
450+ /**
451+ * Returns a <code>Cipher</code> object that implements the specified
452+ * transformation.
453+ *
454+ * <p> This method traverses the list of registered security Providers,
455+ * starting with the most preferred Provider.
456+ * A new Cipher object encapsulating the
457+ * CipherSpi implementation from the first
458+ * Provider that supports the specified algorithm is returned.
459+ *
460+ * <p> Note that the list of registered providers may be retrieved via
461+ * the {@link Security#getProviders() Security.getProviders()} method.
462+ *
463+ * @param transformation the name of the transformation, e.g.,
464+ * <i>DES/CBC/PKCS5Padding</i>.
465+ * See the Cipher section in the <a href=
466+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
467+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
468+ * for information about standard transformation names.
469+ *
470+ * @return a cipher that implements the requested transformation.
471+ *
472+ * @exception NoSuchAlgorithmException if <code>transformation</code>
473+ * is null, empty, in an invalid format,
474+ * or if no Provider supports a CipherSpi implementation for the
475+ * specified algorithm.
476+ *
477+ * @exception NoSuchPaddingException if <code>transformation</code>
478+ * contains a padding scheme that is not available.
479+ *
480+ * @see java.security.Provider
481+ */
482+ public static final Cipher getInstance(String transformation)
483+ throws NoSuchAlgorithmException, NoSuchPaddingException
484+ {
485+ List transforms = getTransforms(transformation);
486+ List cipherServices = new ArrayList(transforms.size());
487+ for (Iterator t = transforms.iterator(); t.hasNext(); ) {
488+ Transform transform = (Transform)t.next();
489+ cipherServices.add(new ServiceId("Cipher", transform.transform));
490+ }
491+ List services = GetInstance.getServices(cipherServices);
492+ // make sure there is at least one service from a signed provider
493+ // and that it can use the specified mode and padding
494+ Iterator t = services.iterator();
495+ Exception failure = null;
496+ while (t.hasNext()) {
497+ Service s = (Service)t.next();
498+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
499+ continue;
500+ }
501+ Transform tr = getTransform(s, transforms);
502+ if (tr == null) {
503+ // should never happen
504+ continue;
505+ }
506+ int canuse = tr.supportsModePadding(s);
507+ if (canuse == S_NO) {
508+ // does not support mode or padding we need, ignore
509+ continue;
510+ }
511+ if (canuse == S_YES) {
512+ return new Cipher(null, s, t, transformation, transforms);
513+ } else { // S_MAYBE, try out if it works
514+ try {
515+ CipherSpi spi = (CipherSpi)s.newInstance(null);
516+ tr.setModePadding(spi);
517+ return new Cipher(spi, s, t, transformation, transforms);
518+ } catch (Exception e) {
519+ failure = e;
520+ }
521+ }
522+ }
523+ throw new NoSuchAlgorithmException
524+ ("Cannot find any provider supporting " + transformation, failure);
525+ }
526+
527+ /**
528+ * Returns a <code>Cipher</code> object that implements the specified
529+ * transformation.
530+ *
531+ * <p> A new Cipher object encapsulating the
532+ * CipherSpi implementation from the specified provider
533+ * is returned. The specified provider must be registered
534+ * in the security provider list.
535+ *
536+ * <p> Note that the list of registered providers may be retrieved via
537+ * the {@link Security#getProviders() Security.getProviders()} method.
538+ *
539+ * @param transformation the name of the transformation,
540+ * e.g., <i>DES/CBC/PKCS5Padding</i>.
541+ * See the Cipher section in the <a href=
542+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
543+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
544+ * for information about standard transformation names.
545+ *
546+ * @param provider the name of the provider.
547+ *
548+ * @return a cipher that implements the requested transformation.
549+ *
550+ * @exception NoSuchAlgorithmException if <code>transformation</code>
551+ * is null, empty, in an invalid format,
552+ * or if a CipherSpi implementation for the specified algorithm
553+ * is not available from the specified provider.
554+ *
555+ * @exception NoSuchProviderException if the specified provider is not
556+ * registered in the security provider list.
557+ *
558+ * @exception NoSuchPaddingException if <code>transformation</code>
559+ * contains a padding scheme that is not available.
560+ *
561+ * @exception IllegalArgumentException if the <code>provider</code>
562+ * is null or empty.
563+ *
564+ * @see java.security.Provider
565+ */
566+ public static final Cipher getInstance(String transformation,
567+ String provider)
568+ throws NoSuchAlgorithmException, NoSuchProviderException,
569+ NoSuchPaddingException
570+ {
571+ if ((provider == null) || (provider.length() == 0)) {
572+ throw new IllegalArgumentException("Missing provider");
573+ }
574+ Provider p = Security.getProvider(provider);
575+ if (p == null) {
576+ throw new NoSuchProviderException("No such provider: " +
577+ provider);
578+ }
579+ return getInstance(transformation, p);
580+ }
581+
582+ /**
583+ * Returns a <code>Cipher</code> object that implements the specified
584+ * transformation.
585+ *
586+ * <p> A new Cipher object encapsulating the
587+ * CipherSpi implementation from the specified Provider
588+ * object is returned. Note that the specified Provider object
589+ * does not have to be registered in the provider list.
590+ *
591+ * @param transformation the name of the transformation,
592+ * e.g., <i>DES/CBC/PKCS5Padding</i>.
593+ * See the Cipher section in the <a href=
594+ * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">
595+ * Java Cryptography Architecture Standard Algorithm Name Documentation</a>
596+ * for information about standard transformation names.
597+ *
598+ * @param provider the provider.
599+ *
600+ * @return a cipher that implements the requested transformation.
601+ *
602+ * @exception NoSuchAlgorithmException if <code>transformation</code>
603+ * is null, empty, in an invalid format,
604+ * or if a CipherSpi implementation for the specified algorithm
605+ * is not available from the specified Provider object.
606+ *
607+ * @exception NoSuchPaddingException if <code>transformation</code>
608+ * contains a padding scheme that is not available.
609+ *
610+ * @exception IllegalArgumentException if the <code>provider</code>
611+ * is null.
612+ *
613+ * @see java.security.Provider
614+ */
615+ public static final Cipher getInstance(String transformation,
616+ Provider provider)
617+ throws NoSuchAlgorithmException, NoSuchPaddingException
618+ {
619+ if (provider == null) {
620+ throw new IllegalArgumentException("Missing provider");
621+ }
622+ Exception failure = null;
623+ List transforms = getTransforms(transformation);
624+ boolean providerChecked = false;
625+ String paddingError = null;
626+ for (Iterator t = transforms.iterator(); t.hasNext();) {
627+ Transform tr = (Transform)t.next();
628+ Service s = provider.getService("Cipher", tr.transform);
629+ if (s == null) {
630+ continue;
631+ }
632+ if (providerChecked == false) {
633+ // for compatibility, first do the lookup and then verify
634+ // the provider. this makes the difference between a NSAE
635+ // and a SecurityException if the
636+ // provider does not support the algorithm.
637+ Exception ve = JceSecurity.getVerificationResult(provider);
638+ if (ve != null) {
639+ String msg = "JCE cannot authenticate the provider "
640+ + provider.getName();
641+ throw new SecurityException(msg, ve);
642+ }
643+ providerChecked = true;
644+ }
645+ if (tr.supportsMode(s) == S_NO) {
646+ continue;
647+ }
648+ if (tr.supportsPadding(s) == S_NO) {
649+ paddingError = tr.pad;
650+ continue;
651+ }
652+ try {
653+ CipherSpi spi = (CipherSpi)s.newInstance(null);
654+ tr.setModePadding(spi);
655+ Cipher cipher = new Cipher(spi, transformation);
656+ cipher.provider = s.getProvider();
657+ cipher.initCryptoPermission();
658+ return cipher;
659+ } catch (Exception e) {
660+ failure = e;
661+ }
662+ }
663+
664+ // throw NoSuchPaddingException if the problem is with padding
665+ if (failure instanceof NoSuchPaddingException) {
666+ throw (NoSuchPaddingException)failure;
667+ }
668+ if (paddingError != null) {
669+ throw new NoSuchPaddingException
670+ ("Padding not supported: " + paddingError);
671+ }
672+ throw new NoSuchAlgorithmException
673+ ("No such algorithm: " + transformation, failure);
674+ }
675+
676+ // If the requested crypto service is export-controlled,
677+ // determine the maximum allowable keysize.
678+ private void initCryptoPermission() throws NoSuchAlgorithmException {
679+ if (JceSecurity.isRestricted() == false) {
680+ cryptoPerm = CryptoAllPermission.INSTANCE;
681+ exmech = null;
682+ return;
683+ }
684+ cryptoPerm = getConfiguredPermission(transformation);
685+ // Instantiate the exemption mechanism (if required)
686+ String exmechName = cryptoPerm.getExemptionMechanism();
687+ if (exmechName != null) {
688+ exmech = ExemptionMechanism.getInstance(exmechName);
689+ }
690+ }
691+
692+ // max number of debug warnings to print from chooseFirstProvider()
693+ private static int warnCount = 10;
694+
695+ /**
696+ * Choose the Spi from the first provider available. Used if
697+ * delayed provider selection is not possible because init()
698+ * is not the first method called.
699+ */
700+ void chooseFirstProvider() {
701+ if (spi != null) {
702+ return;
703+ }
704+ synchronized (lock) {
705+ if (spi != null) {
706+ return;
707+ }
708+ if (debug != null) {
709+ int w = --warnCount;
710+ if (w >= 0) {
711+ debug.println("Cipher.init() not first method "
712+ + "called, disabling delayed provider selection");
713+ if (w == 0) {
714+ debug.println("Further warnings of this type will "
715+ + "be suppressed");
716+ }
717+ new Exception("Call trace").printStackTrace();
718+ }
719+ }
720+ Exception lastException = null;
721+ while ((firstService != null) || serviceIterator.hasNext()) {
722+ Service s;
723+ CipherSpi thisSpi;
724+ if (firstService != null) {
725+ s = firstService;
726+ thisSpi = firstSpi;
727+ firstService = null;
728+ firstSpi = null;
729+ } else {
730+ s = (Service)serviceIterator.next();
731+ thisSpi = null;
732+ }
733+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
734+ continue;
735+ }
736+ Transform tr = getTransform(s, transforms);
737+ if (tr == null) {
738+ // should never happen
739+ continue;
740+ }
741+ if (tr.supportsModePadding(s) == S_NO) {
742+ continue;
743+ }
744+ try {
745+ if (thisSpi == null) {
746+ Object obj = s.newInstance(null);
747+ if (obj instanceof CipherSpi == false) {
748+ continue;
749+ }
750+ thisSpi = (CipherSpi)obj;
751+ }
752+ tr.setModePadding(thisSpi);
753+ initCryptoPermission();
754+ spi = thisSpi;
755+ provider = s.getProvider();
756+ // not needed any more
757+ firstService = null;
758+ serviceIterator = null;
759+ transforms = null;
760+ return;
761+ } catch (Exception e) {
762+ lastException = e;
763+ }
764+ }
765+ ProviderException e = new ProviderException
766+ ("Could not construct CipherSpi instance");
767+ if (lastException != null) {
768+ e.initCause(lastException);
769+ }
770+ throw e;
771+ }
772+ }
773+
774+ private final static int I_KEY = 1;
775+ private final static int I_PARAMSPEC = 2;
776+ private final static int I_PARAMS = 3;
777+ private final static int I_CERT = 4;
778+
779+ private void implInit(CipherSpi thisSpi, int type, int opmode, Key key,
780+ AlgorithmParameterSpec paramSpec, AlgorithmParameters params,
781+ SecureRandom random) throws InvalidKeyException,
782+ InvalidAlgorithmParameterException {
783+ switch (type) {
784+ case I_KEY:
785+ checkCryptoPerm(thisSpi, key);
786+ thisSpi.engineInit(opmode, key, random);
787+ break;
788+ case I_PARAMSPEC:
789+ checkCryptoPerm(thisSpi, key, paramSpec);
790+ thisSpi.engineInit(opmode, key, paramSpec, random);
791+ break;
792+ case I_PARAMS:
793+ checkCryptoPerm(thisSpi, key, params);
794+ thisSpi.engineInit(opmode, key, params, random);
795+ break;
796+ case I_CERT:
797+ checkCryptoPerm(thisSpi, key);
798+ thisSpi.engineInit(opmode, key, random);
799+ break;
800+ default:
801+ throw new AssertionError("Internal Cipher error: " + type);
802+ }
803+ }
804+
805+ private void chooseProvider(int initType, int opmode, Key key,
806+ AlgorithmParameterSpec paramSpec,
807+ AlgorithmParameters params, SecureRandom random)
808+ throws InvalidKeyException, InvalidAlgorithmParameterException {
809+ synchronized (lock) {
810+ if (spi != null) {
811+ implInit(spi, initType, opmode, key, paramSpec, params, random);
812+ return;
813+ }
814+ Exception lastException = null;
815+ while ((firstService != null) || serviceIterator.hasNext()) {
816+ Service s;
817+ CipherSpi thisSpi;
818+ if (firstService != null) {
819+ s = firstService;
820+ thisSpi = firstSpi;
821+ firstService = null;
822+ firstSpi = null;
823+ } else {
824+ s = (Service)serviceIterator.next();
825+ thisSpi = null;
826+ }
827+ // if provider says it does not support this key, ignore it
828+ if (s.supportsParameter(key) == false) {
829+ continue;
830+ }
831+ if (JceSecurity.canUseProvider(s.getProvider()) == false) {
832+ continue;
833+ }
834+ Transform tr = getTransform(s, transforms);
835+ if (tr == null) {
836+ // should never happen
837+ continue;
838+ }
839+ if (tr.supportsModePadding(s) == S_NO) {
840+ continue;
841+ }
842+ try {
843+ if (thisSpi == null) {
844+ thisSpi = (CipherSpi)s.newInstance(null);
845+ }
846+ tr.setModePadding(thisSpi);
847+ initCryptoPermission();
848+ implInit(thisSpi, initType, opmode, key, paramSpec,
849+ params, random);
850+ provider = s.getProvider();
851+ this.spi = thisSpi;
852+ firstService = null;
853+ serviceIterator = null;
854+ transforms = null;
855+ return;
856+ } catch (Exception e) {
857+ // NoSuchAlgorithmException from newInstance()
858+ // InvalidKeyException from init()
859+ // RuntimeException (ProviderException) from init()
860+ // SecurityException from crypto permission check
861+ if (lastException == null) {
862+ lastException = e;
863+ }
864+ }
865+ }
866+ // no working provider found, fail
867+ if (lastException instanceof InvalidKeyException) {
868+ throw (InvalidKeyException)lastException;
869+ }
870+ if (lastException instanceof InvalidAlgorithmParameterException) {
871+ throw (InvalidAlgorithmParameterException)lastException;
872+ }
873+ if (lastException instanceof RuntimeException) {
874+ throw (RuntimeException)lastException;
875+ }
876+ String kName = (key != null) ? key.getClass().getName() : "(null)";
877+ throw new InvalidKeyException
878+ ("No installed provider supports this key: "
879+ + kName, lastException);
880+ }
881+ }
882+
883+ /**
884+ * Returns the provider of this <code>Cipher</code> object.
885+ *
886+ * @return the provider of this <code>Cipher</code> object
887+ */
888+ public final Provider getProvider() {
889+ chooseFirstProvider();
890+ return this.provider;
891+ }
892+
893+ /**
894+ * Returns the algorithm name of this <code>Cipher</code> object.
895+ *
896+ * <p>This is the same name that was specified in one of the
897+ * <code>getInstance</code> calls that created this <code>Cipher</code>
898+ * object..
899+ *
900+ * @return the algorithm name of this <code>Cipher</code> object.
901+ */
902+ public final String getAlgorithm() {
903+ return this.transformation;
904+ }
905+
906+ /**
907+ * Returns the block size (in bytes).
908+ *
909+ * @return the block size (in bytes), or 0 if the underlying algorithm is
910+ * not a block cipher
911+ */
912+ public final int getBlockSize() {
913+ chooseFirstProvider();
914+ return spi.engineGetBlockSize();
915+ }
916+
917+ /**
918+ * Returns the length in bytes that an output buffer would need to be in
919+ * order to hold the result of the next <code>update</code> or
920+ * <code>doFinal</code> operation, given the input length
921+ * <code>inputLen</code> (in bytes).
922+ *
923+ * <p>This call takes into account any unprocessed (buffered) data from a
924+ * previous <code>update</code> call, padding, and AEAD tagging.
925+ *
926+ * <p>The actual output length of the next <code>update</code> or
927+ * <code>doFinal</code> call may be smaller than the length returned by
928+ * this method.
929+ *
930+ * @param inputLen the input length (in bytes)
931+ *
932+ * @return the required output buffer size (in bytes)
933+ *
934+ * @exception IllegalStateException if this cipher is in a wrong state
935+ * (e.g., has not yet been initialized)
936+ */
937+ public final int getOutputSize(int inputLen) {
938+
939+ if (!initialized && !(this instanceof NullCipher)) {
940+ throw new IllegalStateException("Cipher not initialized");
941+ }
942+ if (inputLen < 0) {
943+ throw new IllegalArgumentException("Input size must be equal " +
944+ "to or greater than zero");
945+ }
946+ chooseFirstProvider();
947+ return spi.engineGetOutputSize(inputLen);
948+ }
949+
950+ /**
951+ * Returns the initialization vector (IV) in a new buffer.
952+ *
953+ * <p>This is useful in the case where a random IV was created,
954+ * or in the context of password-based encryption or
955+ * decryption, where the IV is derived from a user-supplied password.
956+ *
957+ * @return the initialization vector in a new buffer, or null if the
958+ * underlying algorithm does not use an IV, or if the IV has not yet
959+ * been set.
960+ */
961+ public final byte[] getIV() {
962+ chooseFirstProvider();
963+ return spi.engineGetIV();
964+ }
965+
966+ /**
967+ * Returns the parameters used with this cipher.
968+ *
969+ * <p>The returned parameters may be the same that were used to initialize
970+ * this cipher, or may contain a combination of default and random
971+ * parameter values used by the underlying cipher implementation if this
972+ * cipher requires algorithm parameters but was not initialized with any.
973+ *
974+ * @return the parameters used with this cipher, or null if this cipher
975+ * does not use any parameters.
976+ */
977+ public final AlgorithmParameters getParameters() {
978+ chooseFirstProvider();
979+ return spi.engineGetParameters();
980+ }
981+
982+ /**
983+ * Returns the exemption mechanism object used with this cipher.
984+ *
985+ * @return the exemption mechanism object used with this cipher, or
986+ * null if this cipher does not use any exemption mechanism.
987+ */
988+ public final ExemptionMechanism getExemptionMechanism() {
989+ chooseFirstProvider();
990+ return exmech;
991+ }
992+
993+ //
994+ // Crypto permission check code below
995+ //
996+ private void checkCryptoPerm(CipherSpi checkSpi, Key key)
997+ throws InvalidKeyException {
998+ if (cryptoPerm == CryptoAllPermission.INSTANCE) {
999+ return;
1000+ }
1001+ // Check if key size and default parameters are within legal limits
1002+ AlgorithmParameterSpec params;
1003+ try {
1004+ params = getAlgorithmParameterSpec(checkSpi.engineGetParameters());
1005+ } catch (InvalidParameterSpecException ipse) {
1006+ throw new InvalidKeyException
1007+ ("Unsupported default algorithm parameters");
1008+ }
1009+ if (!passCryptoPermCheck(checkSpi, key, params)) {
1010+ throw new InvalidKeyException(
1011+ "Illegal key size or default parameters");
1012+ }
1013+ }
1014+
1015+ private void checkCryptoPerm(CipherSpi checkSpi, Key key,
1016+ AlgorithmParameterSpec params) throws InvalidKeyException,
1017+ InvalidAlgorithmParameterException {
1018+ if (cryptoPerm == CryptoAllPermission.INSTANCE) {
1019+ return;
1020+ }
1021+ // Determine keysize and check if it is within legal limits
1022+ if (!passCryptoPermCheck(checkSpi, key, null)) {
1023+ throw new InvalidKeyException("Illegal key size");
1024+ }
1025+ if ((params != null) && (!passCryptoPermCheck(checkSpi, key, params))) {
1026+ throw new InvalidAlgorithmParameterException("Illegal parameters");
1027+ }
1028+ }
1029+
1030+ private void checkCryptoPerm(CipherSpi checkSpi, Key key,
1031+ AlgorithmParameters params)
1032+ throws InvalidKeyException, InvalidAlgorithmParameterException {
1033+ if (cryptoPerm == CryptoAllPermission.INSTANCE) {
1034+ return;
1035+ }
1036+ // Convert the specified parameters into specs and then delegate.
1037+ AlgorithmParameterSpec pSpec;
1038+ try {
1039+ pSpec = getAlgorithmParameterSpec(params);
1040+ } catch (InvalidParameterSpecException ipse) {
1041+ throw new InvalidAlgorithmParameterException
1042+ ("Failed to retrieve algorithm parameter specification");
1043+ }
1044+ checkCryptoPerm(checkSpi, key, pSpec);
1045+ }
1046+
1047+ private boolean passCryptoPermCheck(CipherSpi checkSpi, Key key,
1048+ AlgorithmParameterSpec params)
1049+ throws InvalidKeyException {
1050+ String em = cryptoPerm.getExemptionMechanism();
1051+ int keySize = checkSpi.engineGetKeySize(key);
1052+ // Use the "algorithm" component of the cipher
1053+ // transformation so that the perm check would
1054+ // work when the key has the "aliased" algo.
1055+ String algComponent;
1056+ int index = transformation.indexOf('/');
1057+ if (index != -1) {
1058+ algComponent = transformation.substring(0, index);
1059+ } else {
1060+ algComponent = transformation;
1061+ }
1062+ CryptoPermission checkPerm =
1063+ new CryptoPermission(algComponent, keySize, params, em);
1064+
1065+ if (!cryptoPerm.implies(checkPerm)) {
1066+ if (debug != null) {
1067+ debug.println("Crypto Permission check failed");
1068+ debug.println("granted: " + cryptoPerm);
1069+ debug.println("requesting: " + checkPerm);
1070+ }
1071+ return false;
1072+ }
1073+ if (exmech == null) {
1074+ return true;
1075+ }
1076+ try {
1077+ if (!exmech.isCryptoAllowed(key)) {
1078+ if (debug != null) {
1079+ debug.println(exmech.getName() + " isn't enforced");
1080+ }
1081+ return false;
1082+ }
1083+ } catch (ExemptionMechanismException eme) {
1084+ if (debug != null) {
1085+ debug.println("Cannot determine whether "+
1086+ exmech.getName() + " has been enforced");
1087+ eme.printStackTrace();
1088+ }
1089+ return false;
1090+ }
1091+ return true;
1092+ }
1093+
1094+ // check if opmode is one of the defined constants
1095+ // throw InvalidParameterExeption if not
1096+ private static void checkOpmode(int opmode) {
1097+ if ((opmode < ENCRYPT_MODE) || (opmode > UNWRAP_MODE)) {
1098+ throw new InvalidParameterException("Invalid operation mode");
1099+ }
1100+ }
1101+
1102+ /**
1103+ * Initializes this cipher with a key.
1104+ *
1105+ * <p>The cipher is initialized for one of the following four operations:
1106+ * encryption, decryption, key wrapping or key unwrapping, depending
1107+ * on the value of <code>opmode</code>.
1108+ *
1109+ * <p>If this cipher requires any algorithm parameters that cannot be
1110+ * derived from the given <code>key</code>, the underlying cipher
1111+ * implementation is supposed to generate the required parameters itself
1112+ * (using provider-specific default or random values) if it is being
1113+ * initialized for encryption or key wrapping, and raise an
1114+ * <code>InvalidKeyException</code> if it is being
1115+ * initialized for decryption or key unwrapping.
1116+ * The generated parameters can be retrieved using
1117+ * {@link #getParameters() getParameters} or
1118+ * {@link #getIV() getIV} (if the parameter is an IV).
1119+ *
1120+ * <p>If this cipher requires algorithm parameters that cannot be
1121+ * derived from the input parameters, and there are no reasonable
1122+ * provider-specific default values, initialization will
1123+ * necessarily fail.
1124+ *
1125+ * <p>If this cipher (including its underlying feedback or padding scheme)
1126+ * requires any random bytes (e.g., for parameter generation), it will get
1127+ * them using the {@link SecureRandom <code>SecureRandom</code>}
1128+ * implementation of the highest-priority
1129+ * installed provider as the source of randomness.
1130+ * (If none of the installed providers supply an implementation of
1131+ * SecureRandom, a system-provided source of randomness will be used.)
1132+ *
1133+ * <p>Note that when a Cipher object is initialized, it loses all
1134+ * previously-acquired state. In other words, initializing a Cipher is
1135+ * equivalent to creating a new instance of that Cipher and initializing
1136+ * it.
1137+ *
1138+ * @param opmode the operation mode of this cipher (this is one of
1139+ * the following:
1140+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
1141+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
1142+ * @param key the key
1143+ *
1144+ * @exception InvalidKeyException if the given key is inappropriate for
1145+ * initializing this cipher, or requires
1146+ * algorithm parameters that cannot be
1147+ * determined from the given key, or if the given key has a keysize that
1148+ * exceeds the maximum allowable keysize (as determined from the
1149+ * configured jurisdiction policy files).
1150+ */
1151+ public final void init(int opmode, Key key) throws InvalidKeyException {
1152+ init(opmode, key, JceSecurity.RANDOM);
1153+ }
1154+
1155+ /**
1156+ * Initializes this cipher with a key and a source of randomness.
1157+ *
1158+ * <p>The cipher is initialized for one of the following four operations:
1159+ * encryption, decryption, key wrapping or key unwrapping, depending
1160+ * on the value of <code>opmode</code>.
1161+ *
1162+ * <p>If this cipher requires any algorithm parameters that cannot be
1163+ * derived from the given <code>key</code>, the underlying cipher
1164+ * implementation is supposed to generate the required parameters itself
1165+ * (using provider-specific default or random values) if it is being
1166+ * initialized for encryption or key wrapping, and raise an
1167+ * <code>InvalidKeyException</code> if it is being
1168+ * initialized for decryption or key unwrapping.
1169+ * The generated parameters can be retrieved using
1170+ * {@link #getParameters() getParameters} or
1171+ * {@link #getIV() getIV} (if the parameter is an IV).
1172+ *
1173+ * <p>If this cipher requires algorithm parameters that cannot be
1174+ * derived from the input parameters, and there are no reasonable
1175+ * provider-specific default values, initialization will
1176+ * necessarily fail.
1177+ *
1178+ * <p>If this cipher (including its underlying feedback or padding scheme)
1179+ * requires any random bytes (e.g., for parameter generation), it will get
1180+ * them from <code>random</code>.
1181+ *
1182+ * <p>Note that when a Cipher object is initialized, it loses all
1183+ * previously-acquired state. In other words, initializing a Cipher is
1184+ * equivalent to creating a new instance of that Cipher and initializing
1185+ * it.
1186+ *
1187+ * @param opmode the operation mode of this cipher (this is one of the
1188+ * following:
1189+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
1190+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
1191+ * @param key the encryption key
1192+ * @param random the source of randomness
1193+ *
1194+ * @exception InvalidKeyException if the given key is inappropriate for
1195+ * initializing this cipher, or requires
1196+ * algorithm parameters that cannot be
1197+ * determined from the given key, or if the given key has a keysize that
1198+ * exceeds the maximum allowable keysize (as determined from the
1199+ * configured jurisdiction policy files).
1200+ */
1201+ public final void init(int opmode, Key key, SecureRandom random)
1202+ throws InvalidKeyException
1203+ {
1204+ initialized = false;
1205+ checkOpmode(opmode);
1206+
1207+ if (spi != null) {
1208+ checkCryptoPerm(spi, key);
1209+ spi.engineInit(opmode, key, random);
1210+ } else {
1211+ try {
1212+ chooseProvider(I_KEY, opmode, key, null, null, random);
1213+ } catch (InvalidAlgorithmParameterException e) {
1214+ // should never occur
1215+ throw new InvalidKeyException(e);
1216+ }
1217+ }
1218+
1219+ initialized = true;
1220+ this.opmode = opmode;
1221+ }
1222+
1223+ /**
1224+ * Initializes this cipher with a key and a set of algorithm
1225+ * parameters.
1226+ *
1227+ * <p>The cipher is initialized for one of the following four operations:
1228+ * encryption, decryption, key wrapping or key unwrapping, depending
1229+ * on the value of <code>opmode</code>.
1230+ *
1231+ * <p>If this cipher requires any algorithm parameters and
1232+ * <code>params</code> is null, the underlying cipher implementation is
1233+ * supposed to generate the required parameters itself (using
1234+ * provider-specific default or random values) if it is being
1235+ * initialized for encryption or key wrapping, and raise an
1236+ * <code>InvalidAlgorithmParameterException</code> if it is being
1237+ * initialized for decryption or key unwrapping.
1238+ * The generated parameters can be retrieved using
1239+ * {@link #getParameters() getParameters} or
1240+ * {@link #getIV() getIV} (if the parameter is an IV).
1241+ *
1242+ * <p>If this cipher requires algorithm parameters that cannot be
1243+ * derived from the input parameters, and there are no reasonable
1244+ * provider-specific default values, initialization will
1245+ * necessarily fail.
1246+ *
1247+ * <p>If this cipher (including its underlying feedback or padding scheme)
1248+ * requires any random bytes (e.g., for parameter generation), it will get
1249+ * them using the {@link SecureRandom <code>SecureRandom</code>}
1250+ * implementation of the highest-priority
1251+ * installed provider as the source of randomness.
1252+ * (If none of the installed providers supply an implementation of
1253+ * SecureRandom, a system-provided source of randomness will be used.)
1254+ *
1255+ * <p>Note that when a Cipher object is initialized, it loses all
1256+ * previously-acquired state. In other words, initializing a Cipher is
1257+ * equivalent to creating a new instance of that Cipher and initializing
1258+ * it.
1259+ *
1260+ * @param opmode the operation mode of this cipher (this is one of the
1261+ * following:
1262+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
1263+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
1264+ * @param key the encryption key
1265+ * @param params the algorithm parameters
1266+ *
1267+ * @exception InvalidKeyException if the given key is inappropriate for
1268+ * initializing this cipher, or its keysize exceeds the maximum allowable
1269+ * keysize (as determined from the configured jurisdiction policy files).
1270+ * @exception InvalidAlgorithmParameterException if the given algorithm
1271+ * parameters are inappropriate for this cipher,
1272+ * or this cipher requires
1273+ * algorithm parameters and <code>params</code> is null, or the given
1274+ * algorithm parameters imply a cryptographic strength that would exceed
1275+ * the legal limits (as determined from the configured jurisdiction
1276+ * policy files).
1277+ */
1278+ public final void init(int opmode, Key key, AlgorithmParameterSpec params)
1279+ throws InvalidKeyException, InvalidAlgorithmParameterException
1280+ {
1281+ init(opmode, key, params, JceSecurity.RANDOM);
1282+ }
1283+
1284+ /**
1285+ * Initializes this cipher with a key, a set of algorithm
1286+ * parameters, and a source of randomness.
1287+ *
1288+ * <p>The cipher is initialized for one of the following four operations:
1289+ * encryption, decryption, key wrapping or key unwrapping, depending
1290+ * on the value of <code>opmode</code>.
1291+ *
1292+ * <p>If this cipher requires any algorithm parameters and
1293+ * <code>params</code> is null, the underlying cipher implementation is
1294+ * supposed to generate the required parameters itself (using
1295+ * provider-specific default or random values) if it is being
1296+ * initialized for encryption or key wrapping, and raise an
1297+ * <code>InvalidAlgorithmParameterException</code> if it is being
1298+ * initialized for decryption or key unwrapping.
1299+ * The generated parameters can be retrieved using
1300+ * {@link #getParameters() getParameters} or
1301+ * {@link #getIV() getIV} (if the parameter is an IV).
1302+ *
1303+ * <p>If this cipher requires algorithm parameters that cannot be
1304+ * derived from the input parameters, and there are no reasonable
1305+ * provider-specific default values, initialization will
1306+ * necessarily fail.
1307+ *
1308+ * <p>If this cipher (including its underlying feedback or padding scheme)
1309+ * requires any random bytes (e.g., for parameter generation), it will get
1310+ * them from <code>random</code>.
1311+ *
1312+ * <p>Note that when a Cipher object is initialized, it loses all
1313+ * previously-acquired state. In other words, initializing a Cipher is
1314+ * equivalent to creating a new instance of that Cipher and initializing
1315+ * it.
1316+ *
1317+ * @param opmode the operation mode of this cipher (this is one of the
1318+ * following:
1319+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
1320+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
1321+ * @param key the encryption key
1322+ * @param params the algorithm parameters
1323+ * @param random the source of randomness
1324+ *
1325+ * @exception InvalidKeyException if the given key is inappropriate for
1326+ * initializing this cipher, or its keysize exceeds the maximum allowable
1327+ * keysize (as determined from the configured jurisdiction policy files).
1328+ * @exception InvalidAlgorithmParameterException if the given algorithm
1329+ * parameters are inappropriate for this cipher,
1330+ * or this cipher requires
1331+ * algorithm parameters and <code>params</code> is null, or the given
1332+ * algorithm parameters imply a cryptographic strength that would exceed
1333+ * the legal limits (as determined from the configured jurisdiction
1334+ * policy files).
1335+ */
1336+ public final void init(int opmode, Key key, AlgorithmParameterSpec params,
1337+ SecureRandom random)
1338+ throws InvalidKeyException, InvalidAlgorithmParameterException
1339+ {
1340+ initialized = false;
1341+ checkOpmode(opmode);
1342+
1343+ if (spi != null) {
1344+ checkCryptoPerm(spi, key, params);
1345+ spi.engineInit(opmode, key, params, random);
1346+ } else {
1347+ chooseProvider(I_PARAMSPEC, opmode, key, params, null, random);
1348+ }
1349+
1350+ initialized = true;
1351+ this.opmode = opmode;
1352+ }
1353+
1354+ /**
1355+ * Initializes this cipher with a key and a set of algorithm
1356+ * parameters.
1357+ *
1358+ * <p>The cipher is initialized for one of the following four operations:
1359+ * encryption, decryption, key wrapping or key unwrapping, depending
1360+ * on the value of <code>opmode</code>.
1361+ *
1362+ * <p>If this cipher requires any algorithm parameters and
1363+ * <code>params</code> is null, the underlying cipher implementation is
1364+ * supposed to generate the required parameters itself (using
1365+ * provider-specific default or random values) if it is being
1366+ * initialized for encryption or key wrapping, and raise an
1367+ * <code>InvalidAlgorithmParameterException</code> if it is being
1368+ * initialized for decryption or key unwrapping.
1369+ * The generated parameters can be retrieved using
1370+ * {@link #getParameters() getParameters} or
1371+ * {@link #getIV() getIV} (if the parameter is an IV).
1372+ *
1373+ * <p>If this cipher requires algorithm parameters that cannot be
1374+ * derived from the input parameters, and there are no reasonable
1375+ * provider-specific default values, initialization will
1376+ * necessarily fail.
1377+ *
1378+ * <p>If this cipher (including its underlying feedback or padding scheme)
1379+ * requires any random bytes (e.g., for parameter generation), it will get
1380+ * them using the {@link SecureRandom <code>SecureRandom</code>}
1381+ * implementation of the highest-priority
1382+ * installed provider as the source of randomness.
1383+ * (If none of the installed providers supply an implementation of
1384+ * SecureRandom, a system-provided source of randomness will be used.)
1385+ *
1386+ * <p>Note that when a Cipher object is initialized, it loses all
1387+ * previously-acquired state. In other words, initializing a Cipher is
1388+ * equivalent to creating a new instance of that Cipher and initializing
1389+ * it.
1390+ *
1391+ * @param opmode the operation mode of this cipher (this is one of the
1392+ * following: <code>ENCRYPT_MODE</code>,
1393+ * <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code>
1394+ * or <code>UNWRAP_MODE</code>)
1395+ * @param key the encryption key
1396+ * @param params the algorithm parameters
1397+ *
1398+ * @exception InvalidKeyException if the given key is inappropriate for
1399+ * initializing this cipher, or its keysize exceeds the maximum allowable
1400+ * keysize (as determined from the configured jurisdiction policy files).
1401+ * @exception InvalidAlgorithmParameterException if the given algorithm
1402+ * parameters are inappropriate for this cipher,
1403+ * or this cipher requires
1404+ * algorithm parameters and <code>params</code> is null, or the given
1405+ * algorithm parameters imply a cryptographic strength that would exceed
1406+ * the legal limits (as determined from the configured jurisdiction
1407+ * policy files).
1408+ */
1409+ public final void init(int opmode, Key key, AlgorithmParameters params)
1410+ throws InvalidKeyException, InvalidAlgorithmParameterException
1411+ {
1412+ init(opmode, key, params, JceSecurity.RANDOM);
1413+ }
1414+
1415+ /**
1416+ * Initializes this cipher with a key, a set of algorithm
1417+ * parameters, and a source of randomness.
1418+ *
1419+ * <p>The cipher is initialized for one of the following four operations:
1420+ * encryption, decryption, key wrapping or key unwrapping, depending
1421+ * on the value of <code>opmode</code>.
1422+ *
1423+ * <p>If this cipher requires any algorithm parameters and
1424+ * <code>params</code> is null, the underlying cipher implementation is
1425+ * supposed to generate the required parameters itself (using
1426+ * provider-specific default or random values) if it is being
1427+ * initialized for encryption or key wrapping, and raise an
1428+ * <code>InvalidAlgorithmParameterException</code> if it is being
1429+ * initialized for decryption or key unwrapping.
1430+ * The generated parameters can be retrieved using
1431+ * {@link #getParameters() getParameters} or
1432+ * {@link #getIV() getIV} (if the parameter is an IV).
1433+ *
1434+ * <p>If this cipher requires algorithm parameters that cannot be
1435+ * derived from the input parameters, and there are no reasonable
1436+ * provider-specific default values, initialization will
1437+ * necessarily fail.
1438+ *
1439+ * <p>If this cipher (including its underlying feedback or padding scheme)
1440+ * requires any random bytes (e.g., for parameter generation), it will get
1441+ * them from <code>random</code>.
1442+ *
1443+ * <p>Note that when a Cipher object is initialized, it loses all
1444+ * previously-acquired state. In other words, initializing a Cipher is
1445+ * equivalent to creating a new instance of that Cipher and initializing
1446+ * it.
1447+ *
1448+ * @param opmode the operation mode of this cipher (this is one of the
1449+ * following: <code>ENCRYPT_MODE</code>,
1450+ * <code>DECRYPT_MODE</code>, <code>WRAP_MODE</code>
1451+ * or <code>UNWRAP_MODE</code>)
1452+ * @param key the encryption key
1453+ * @param params the algorithm parameters
1454+ * @param random the source of randomness
1455+ *
1456+ * @exception InvalidKeyException if the given key is inappropriate for
1457+ * initializing this cipher, or its keysize exceeds the maximum allowable
1458+ * keysize (as determined from the configured jurisdiction policy files).
1459+ * @exception InvalidAlgorithmParameterException if the given algorithm
1460+ * parameters are inappropriate for this cipher,
1461+ * or this cipher requires
1462+ * algorithm parameters and <code>params</code> is null, or the given
1463+ * algorithm parameters imply a cryptographic strength that would exceed
1464+ * the legal limits (as determined from the configured jurisdiction
1465+ * policy files).
1466+ */
1467+ public final void init(int opmode, Key key, AlgorithmParameters params,
1468+ SecureRandom random)
1469+ throws InvalidKeyException, InvalidAlgorithmParameterException
1470+ {
1471+ initialized = false;
1472+ checkOpmode(opmode);
1473+
1474+ if (spi != null) {
1475+ checkCryptoPerm(spi, key, params);
1476+ spi.engineInit(opmode, key, params, random);
1477+ } else {
1478+ chooseProvider(I_PARAMS, opmode, key, null, params, random);
1479+ }
1480+
1481+ initialized = true;
1482+ this.opmode = opmode;
1483+ }
1484+
1485+ /**
1486+ * Initializes this cipher with the public key from the given certificate.
1487+ * <p> The cipher is initialized for one of the following four operations:
1488+ * encryption, decryption, key wrapping or key unwrapping, depending
1489+ * on the value of <code>opmode</code>.
1490+ *
1491+ * <p>If the certificate is of type X.509 and has a <i>key usage</i>
1492+ * extension field marked as critical, and the value of the <i>key usage</i>
1493+ * extension field implies that the public key in
1494+ * the certificate and its corresponding private key are not
1495+ * supposed to be used for the operation represented by the value
1496+ * of <code>opmode</code>,
1497+ * an <code>InvalidKeyException</code>
1498+ * is thrown.
1499+ *
1500+ * <p> If this cipher requires any algorithm parameters that cannot be
1501+ * derived from the public key in the given certificate, the underlying
1502+ * cipher
1503+ * implementation is supposed to generate the required parameters itself
1504+ * (using provider-specific default or random values) if it is being
1505+ * initialized for encryption or key wrapping, and raise an <code>
1506+ * InvalidKeyException</code> if it is being initialized for decryption or
1507+ * key unwrapping.
1508+ * The generated parameters can be retrieved using
1509+ * {@link #getParameters() getParameters} or
1510+ * {@link #getIV() getIV} (if the parameter is an IV).
1511+ *
1512+ * <p>If this cipher requires algorithm parameters that cannot be
1513+ * derived from the input parameters, and there are no reasonable
1514+ * provider-specific default values, initialization will
1515+ * necessarily fail.
1516+ *
1517+ * <p>If this cipher (including its underlying feedback or padding scheme)
1518+ * requires any random bytes (e.g., for parameter generation), it will get
1519+ * them using the
1520+ * <code>SecureRandom</code>
1521+ * implementation of the highest-priority
1522+ * installed provider as the source of randomness.
1523+ * (If none of the installed providers supply an implementation of
1524+ * SecureRandom, a system-provided source of randomness will be used.)
1525+ *
1526+ * <p>Note that when a Cipher object is initialized, it loses all
1527+ * previously-acquired state. In other words, initializing a Cipher is
1528+ * equivalent to creating a new instance of that Cipher and initializing
1529+ * it.
1530+ *
1531+ * @param opmode the operation mode of this cipher (this is one of the
1532+ * following:
1533+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
1534+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
1535+ * @param certificate the certificate
1536+ *
1537+ * @exception InvalidKeyException if the public key in the given
1538+ * certificate is inappropriate for initializing this cipher, or this
1539+ * cipher requires algorithm parameters that cannot be determined from the
1540+ * public key in the given certificate, or the keysize of the public key
1541+ * in the given certificate has a keysize that exceeds the maximum
1542+ * allowable keysize (as determined by the configured jurisdiction policy
1543+ * files).
1544+ */
1545+ public final void init(int opmode, Certificate certificate)
1546+ throws InvalidKeyException
1547+ {
1548+ init(opmode, certificate, JceSecurity.RANDOM);
1549+ }
1550+
1551+ /**
1552+ * Initializes this cipher with the public key from the given certificate
1553+ * and
1554+ * a source of randomness.
1555+ *
1556+ * <p>The cipher is initialized for one of the following four operations:
1557+ * encryption, decryption, key wrapping
1558+ * or key unwrapping, depending on
1559+ * the value of <code>opmode</code>.
1560+ *
1561+ * <p>If the certificate is of type X.509 and has a <i>key usage</i>
1562+ * extension field marked as critical, and the value of the <i>key usage</i>
1563+ * extension field implies that the public key in
1564+ * the certificate and its corresponding private key are not
1565+ * supposed to be used for the operation represented by the value of
1566+ * <code>opmode</code>,
1567+ * an <code>InvalidKeyException</code>
1568+ * is thrown.
1569+ *
1570+ * <p>If this cipher requires any algorithm parameters that cannot be
1571+ * derived from the public key in the given <code>certificate</code>,
1572+ * the underlying cipher
1573+ * implementation is supposed to generate the required parameters itself
1574+ * (using provider-specific default or random values) if it is being
1575+ * initialized for encryption or key wrapping, and raise an
1576+ * <code>InvalidKeyException</code> if it is being
1577+ * initialized for decryption or key unwrapping.
1578+ * The generated parameters can be retrieved using
1579+ * {@link #getParameters() getParameters} or
1580+ * {@link #getIV() getIV} (if the parameter is an IV).
1581+ *
1582+ * <p>If this cipher requires algorithm parameters that cannot be
1583+ * derived from the input parameters, and there are no reasonable
1584+ * provider-specific default values, initialization will
1585+ * necessarily fail.
1586+ *
1587+ * <p>If this cipher (including its underlying feedback or padding scheme)
1588+ * requires any random bytes (e.g., for parameter generation), it will get
1589+ * them from <code>random</code>.
1590+ *
1591+ * <p>Note that when a Cipher object is initialized, it loses all
1592+ * previously-acquired state. In other words, initializing a Cipher is
1593+ * equivalent to creating a new instance of that Cipher and initializing
1594+ * it.
1595+ *
1596+ * @param opmode the operation mode of this cipher (this is one of the
1597+ * following:
1598+ * <code>ENCRYPT_MODE</code>, <code>DECRYPT_MODE</code>,
1599+ * <code>WRAP_MODE</code> or <code>UNWRAP_MODE</code>)
1600+ * @param certificate the certificate
1601+ * @param random the source of randomness
1602+ *
1603+ * @exception InvalidKeyException if the public key in the given
1604+ * certificate is inappropriate for initializing this cipher, or this
1605+ * cipher
1606+ * requires algorithm parameters that cannot be determined from the
1607+ * public key in the given certificate, or the keysize of the public key
1608+ * in the given certificate has a keysize that exceeds the maximum
1609+ * allowable keysize (as determined by the configured jurisdiction policy
1610+ * files).
1611+ */
1612+ public final void init(int opmode, Certificate certificate,
1613+ SecureRandom random)
1614+ throws InvalidKeyException
1615+ {
1616+ initialized = false;
1617+ checkOpmode(opmode);
1618+
1619+ // Check key usage if the certificate is of
1620+ // type X.509.
1621+ if (certificate instanceof java.security.cert.X509Certificate) {
1622+ // Check whether the cert has a key usage extension
1623+ // marked as a critical extension.
1624+ X509Certificate cert = (X509Certificate)certificate;
1625+ Set critSet = cert.getCriticalExtensionOIDs();
1626+
1627+ if (critSet != null && !critSet.isEmpty()
1628+ && critSet.contains(KEY_USAGE_EXTENSION_OID)) {
1629+ boolean[] keyUsageInfo = cert.getKeyUsage();
1630+ // keyUsageInfo[2] is for keyEncipherment;
1631+ // keyUsageInfo[3] is for dataEncipherment.
1632+ if ((keyUsageInfo != null) &&
1633+ (((opmode == Cipher.ENCRYPT_MODE) &&
1634+ (keyUsageInfo.length > 3) &&
1635+ (keyUsageInfo[3] == false)) ||
1636+ ((opmode == Cipher.WRAP_MODE) &&
1637+ (keyUsageInfo.length > 2) &&
1638+ (keyUsageInfo[2] == false)))) {
1639+ throw new InvalidKeyException("Wrong key usage");
1640+ }
1641+ }
1642+ }
1643+
1644+ PublicKey publicKey =
1645+ (certificate==null? null:certificate.getPublicKey());
1646+
1647+ if (spi != null) {
1648+ checkCryptoPerm(spi, publicKey);
1649+ spi.engineInit(opmode, publicKey, random);
1650+ } else {
1651+ try {
1652+ chooseProvider(I_CERT, opmode, publicKey, null, null, random);
1653+ } catch (InvalidAlgorithmParameterException e) {
1654+ // should never occur
1655+ throw new InvalidKeyException(e);
1656+ }
1657+ }
1658+
1659+ initialized = true;
1660+ this.opmode = opmode;
1661+ }
1662+
1663+ /**
1664+ * Ensures that Cipher is in a valid state for update() and doFinal()
1665+ * calls - should be initialized and in ENCRYPT_MODE or DECRYPT_MODE.
1666+ * @throws IllegalStateException if Cipher object is not in valid state.
1667+ */
1668+ private void checkCipherState() {
1669+ if (!(this instanceof NullCipher)) {
1670+ if (!initialized) {
1671+ throw new IllegalStateException("Cipher not initialized");
1672+ }
1673+ if ((opmode != Cipher.ENCRYPT_MODE) &&
1674+ (opmode != Cipher.DECRYPT_MODE)) {
1675+ throw new IllegalStateException("Cipher not initialized " +
1676+ "for encryption/decryption");
1677+ }
1678+ }
1679+ }
1680+
1681+ /**
1682+ * Continues a multiple-part encryption or decryption operation
1683+ * (depending on how this cipher was initialized), processing another data
1684+ * part.
1685+ *
1686+ * <p>The bytes in the <code>input</code> buffer are processed, and the
1687+ * result is stored in a new buffer.
1688+ *
1689+ * <p>If <code>input</code> has a length of zero, this method returns
1690+ * <code>null</code>.
1691+ *
1692+ * @param input the input buffer
1693+ *
1694+ * @return the new buffer with the result, or null if the underlying
1695+ * cipher is a block cipher and the input data is too short to result in a
1696+ * new block.
1697+ *
1698+ * @exception IllegalStateException if this cipher is in a wrong state
1699+ * (e.g., has not been initialized)
1700+ */
1701+ public final byte[] update(byte[] input) {
1702+ checkCipherState();
1703+
1704+ // Input sanity check
1705+ if (input == null) {
1706+ throw new IllegalArgumentException("Null input buffer");
1707+ }
1708+
1709+ chooseFirstProvider();
1710+ if (input.length == 0) {
1711+ return null;
1712+ }
1713+ return spi.engineUpdate(input, 0, input.length);
1714+ }
1715+
1716+ /**
1717+ * Continues a multiple-part encryption or decryption operation
1718+ * (depending on how this cipher was initialized), processing another data
1719+ * part.
1720+ *
1721+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
1722+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
1723+ * and the result is stored in a new buffer.
1724+ *
1725+ * <p>If <code>inputLen</code> is zero, this method returns
1726+ * <code>null</code>.
1727+ *
1728+ * @param input the input buffer
1729+ * @param inputOffset the offset in <code>input</code> where the input
1730+ * starts
1731+ * @param inputLen the input length
1732+ *
1733+ * @return the new buffer with the result, or null if the underlying
1734+ * cipher is a block cipher and the input data is too short to result in a
1735+ * new block.
1736+ *
1737+ * @exception IllegalStateException if this cipher is in a wrong state
1738+ * (e.g., has not been initialized)
1739+ */
1740+ public final byte[] update(byte[] input, int inputOffset, int inputLen) {
1741+ checkCipherState();
1742+
1743+ // Input sanity check
1744+ if (input == null || inputOffset < 0
1745+ || inputLen > (input.length - inputOffset) || inputLen < 0) {
1746+ throw new IllegalArgumentException("Bad arguments");
1747+ }
1748+
1749+ chooseFirstProvider();
1750+ if (inputLen == 0) {
1751+ return null;
1752+ }
1753+ return spi.engineUpdate(input, inputOffset, inputLen);
1754+ }
1755+
1756+ /**
1757+ * Continues a multiple-part encryption or decryption operation
1758+ * (depending on how this cipher was initialized), processing another data
1759+ * part.
1760+ *
1761+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
1762+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
1763+ * and the result is stored in the <code>output</code> buffer.
1764+ *
1765+ * <p>If the <code>output</code> buffer is too small to hold the result,
1766+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
1767+ * call with a larger output buffer. Use
1768+ * {@link #getOutputSize(int) getOutputSize} to determine how big
1769+ * the output buffer should be.
1770+ *
1771+ * <p>If <code>inputLen</code> is zero, this method returns
1772+ * a length of zero.
1773+ *
1774+ * <p>Note: this method should be copy-safe, which means the
1775+ * <code>input</code> and <code>output</code> buffers can reference
1776+ * the same byte array and no unprocessed input data is overwritten
1777+ * when the result is copied into the output buffer.
1778+ *
1779+ * @param input the input buffer
1780+ * @param inputOffset the offset in <code>input</code> where the input
1781+ * starts
1782+ * @param inputLen the input length
1783+ * @param output the buffer for the result
1784+ *
1785+ * @return the number of bytes stored in <code>output</code>
1786+ *
1787+ * @exception IllegalStateException if this cipher is in a wrong state
1788+ * (e.g., has not been initialized)
1789+ * @exception ShortBufferException if the given output buffer is too small
1790+ * to hold the result
1791+ */
1792+ public final int update(byte[] input, int inputOffset, int inputLen,
1793+ byte[] output)
1794+ throws ShortBufferException {
1795+ checkCipherState();
1796+
1797+ // Input sanity check
1798+ if (input == null || inputOffset < 0
1799+ || inputLen > (input.length - inputOffset) || inputLen < 0) {
1800+ throw new IllegalArgumentException("Bad arguments");
1801+ }
1802+
1803+ chooseFirstProvider();
1804+ if (inputLen == 0) {
1805+ return 0;
1806+ }
1807+ return spi.engineUpdate(input, inputOffset, inputLen,
1808+ output, 0);
1809+ }
1810+
1811+ /**
1812+ * Continues a multiple-part encryption or decryption operation
1813+ * (depending on how this cipher was initialized), processing another data
1814+ * part.
1815+ *
1816+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
1817+ * buffer, starting at <code>inputOffset</code> inclusive, are processed,
1818+ * and the result is stored in the <code>output</code> buffer, starting at
1819+ * <code>outputOffset</code> inclusive.
1820+ *
1821+ * <p>If the <code>output</code> buffer is too small to hold the result,
1822+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
1823+ * call with a larger output buffer. Use
1824+ * {@link #getOutputSize(int) getOutputSize} to determine how big
1825+ * the output buffer should be.
1826+ *
1827+ * <p>If <code>inputLen</code> is zero, this method returns
1828+ * a length of zero.
1829+ *
1830+ * <p>Note: this method should be copy-safe, which means the
1831+ * <code>input</code> and <code>output</code> buffers can reference
1832+ * the same byte array and no unprocessed input data is overwritten
1833+ * when the result is copied into the output buffer.
1834+ *
1835+ * @param input the input buffer
1836+ * @param inputOffset the offset in <code>input</code> where the input
1837+ * starts
1838+ * @param inputLen the input length
1839+ * @param output the buffer for the result
1840+ * @param outputOffset the offset in <code>output</code> where the result
1841+ * is stored
1842+ *
1843+ * @return the number of bytes stored in <code>output</code>
1844+ *
1845+ * @exception IllegalStateException if this cipher is in a wrong state
1846+ * (e.g., has not been initialized)
1847+ * @exception ShortBufferException if the given output buffer is too small
1848+ * to hold the result
1849+ */
1850+ public final int update(byte[] input, int inputOffset, int inputLen,
1851+ byte[] output, int outputOffset)
1852+ throws ShortBufferException {
1853+ checkCipherState();
1854+
1855+ // Input sanity check
1856+ if (input == null || inputOffset < 0
1857+ || inputLen > (input.length - inputOffset) || inputLen < 0
1858+ || outputOffset < 0) {
1859+ throw new IllegalArgumentException("Bad arguments");
1860+ }
1861+
1862+ chooseFirstProvider();
1863+ if (inputLen == 0) {
1864+ return 0;
1865+ }
1866+ return spi.engineUpdate(input, inputOffset, inputLen,
1867+ output, outputOffset);
1868+ }
1869+
1870+ /**
1871+ * Continues a multiple-part encryption or decryption operation
1872+ * (depending on how this cipher was initialized), processing another data
1873+ * part.
1874+ *
1875+ * <p>All <code>input.remaining()</code> bytes starting at
1876+ * <code>input.position()</code> are processed. The result is stored
1877+ * in the output buffer.
1878+ * Upon return, the input buffer's position will be equal
1879+ * to its limit; its limit will not have changed. The output buffer's
1880+ * position will have advanced by n, where n is the value returned
1881+ * by this method; the output buffer's limit will not have changed.
1882+ *
1883+ * <p>If <code>output.remaining()</code> bytes are insufficient to
1884+ * hold the result, a <code>ShortBufferException</code> is thrown.
1885+ * In this case, repeat this call with a larger output buffer. Use
1886+ * {@link #getOutputSize(int) getOutputSize} to determine how big
1887+ * the output buffer should be.
1888+ *
1889+ * <p>Note: this method should be copy-safe, which means the
1890+ * <code>input</code> and <code>output</code> buffers can reference
1891+ * the same block of memory and no unprocessed input data is overwritten
1892+ * when the result is copied into the output buffer.
1893+ *
1894+ * @param input the input ByteBuffer
1895+ * @param output the output ByteByffer
1896+ *
1897+ * @return the number of bytes stored in <code>output</code>
1898+ *
1899+ * @exception IllegalStateException if this cipher is in a wrong state
1900+ * (e.g., has not been initialized)
1901+ * @exception IllegalArgumentException if input and output are the
1902+ * same object
1903+ * @exception ReadOnlyBufferException if the output buffer is read-only
1904+ * @exception ShortBufferException if there is insufficient space in the
1905+ * output buffer
1906+ * @since 1.5
1907+ */
1908+ public final int update(ByteBuffer input, ByteBuffer output)
1909+ throws ShortBufferException {
1910+ checkCipherState();
1911+
1912+ if ((input == null) || (output == null)) {
1913+ throw new IllegalArgumentException("Buffers must not be null");
1914+ }
1915+ if (input == output) {
1916+ throw new IllegalArgumentException("Input and output buffers must "
1917+ + "not be the same object, consider using buffer.duplicate()");
1918+ }
1919+ if (output.isReadOnly()) {
1920+ throw new ReadOnlyBufferException();
1921+ }
1922+
1923+ chooseFirstProvider();
1924+ return spi.engineUpdate(input, output);
1925+ }
1926+
1927+ /**
1928+ * Finishes a multiple-part encryption or decryption operation, depending
1929+ * on how this cipher was initialized.
1930+ *
1931+ * <p>Input data that may have been buffered during a previous
1932+ * <code>update</code> operation is processed, with padding (if requested)
1933+ * being applied.
1934+ * If an AEAD mode such as GCM/CCM is being used, the authentication
1935+ * tag is appended in the case of encryption, or verified in the
1936+ * case of decryption.
1937+ * The result is stored in a new buffer.
1938+ *
1939+ * <p>Upon finishing, this method resets this cipher object to the state
1940+ * it was in when previously initialized via a call to <code>init</code>.
1941+ * That is, the object is reset and available to encrypt or decrypt
1942+ * (depending on the operation mode that was specified in the call to
1943+ * <code>init</code>) more data.
1944+ *
1945+ * <p>Note: if any exception is thrown, this cipher object may need to
1946+ * be reset before it can be used again.
1947+ *
1948+ * @return the new buffer with the result
1949+ *
1950+ * @exception IllegalStateException if this cipher is in a wrong state
1951+ * (e.g., has not been initialized)
1952+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
1953+ * no padding has been requested (only in encryption mode), and the total
1954+ * input length of the data processed by this cipher is not a multiple of
1955+ * block size; or if this encryption algorithm is unable to
1956+ * process the input data provided.
1957+ * @exception BadPaddingException if this cipher is in decryption mode,
1958+ * and (un)padding has been requested, but the decrypted data is not
1959+ * bounded by the appropriate padding bytes
1960+ * @exception AEADBadTagException if this cipher is decrypting in an
1961+ * AEAD mode (such as GCM/CCM), and the received authentication tag
1962+ * does not match the calculated value
1963+ */
1964+ public final byte[] doFinal()
1965+ throws IllegalBlockSizeException, BadPaddingException {
1966+ checkCipherState();
1967+
1968+ chooseFirstProvider();
1969+ return spi.engineDoFinal(null, 0, 0);
1970+ }
1971+
1972+ /**
1973+ * Finishes a multiple-part encryption or decryption operation, depending
1974+ * on how this cipher was initialized.
1975+ *
1976+ * <p>Input data that may have been buffered during a previous
1977+ * <code>update</code> operation is processed, with padding (if requested)
1978+ * being applied.
1979+ * If an AEAD mode such as GCM/CCM is being used, the authentication
1980+ * tag is appended in the case of encryption, or verified in the
1981+ * case of decryption.
1982+ * The result is stored in the <code>output</code> buffer, starting at
1983+ * <code>outputOffset</code> inclusive.
1984+ *
1985+ * <p>If the <code>output</code> buffer is too small to hold the result,
1986+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
1987+ * call with a larger output buffer. Use
1988+ * {@link #getOutputSize(int) getOutputSize} to determine how big
1989+ * the output buffer should be.
1990+ *
1991+ * <p>Upon finishing, this method resets this cipher object to the state
1992+ * it was in when previously initialized via a call to <code>init</code>.
1993+ * That is, the object is reset and available to encrypt or decrypt
1994+ * (depending on the operation mode that was specified in the call to
1995+ * <code>init</code>) more data.
1996+ *
1997+ * <p>Note: if any exception is thrown, this cipher object may need to
1998+ * be reset before it can be used again.
1999+ *
2000+ * @param output the buffer for the result
2001+ * @param outputOffset the offset in <code>output</code> where the result
2002+ * is stored
2003+ *
2004+ * @return the number of bytes stored in <code>output</code>
2005+ *
2006+ * @exception IllegalStateException if this cipher is in a wrong state
2007+ * (e.g., has not been initialized)
2008+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
2009+ * no padding has been requested (only in encryption mode), and the total
2010+ * input length of the data processed by this cipher is not a multiple of
2011+ * block size; or if this encryption algorithm is unable to
2012+ * process the input data provided.
2013+ * @exception ShortBufferException if the given output buffer is too small
2014+ * to hold the result
2015+ * @exception BadPaddingException if this cipher is in decryption mode,
2016+ * and (un)padding has been requested, but the decrypted data is not
2017+ * bounded by the appropriate padding bytes
2018+ * @exception AEADBadTagException if this cipher is decrypting in an
2019+ * AEAD mode (such as GCM/CCM), and the received authentication tag
2020+ * does not match the calculated value
2021+ */
2022+ public final int doFinal(byte[] output, int outputOffset)
2023+ throws IllegalBlockSizeException, ShortBufferException,
2024+ BadPaddingException {
2025+ checkCipherState();
2026+
2027+ // Input sanity check
2028+ if ((output == null) || (outputOffset < 0)) {
2029+ throw new IllegalArgumentException("Bad arguments");
2030+ }
2031+
2032+ chooseFirstProvider();
2033+ return spi.engineDoFinal(null, 0, 0, output, outputOffset);
2034+ }
2035+
2036+ /**
2037+ * Encrypts or decrypts data in a single-part operation, or finishes a
2038+ * multiple-part operation. The data is encrypted or decrypted,
2039+ * depending on how this cipher was initialized.
2040+ *
2041+ * <p>The bytes in the <code>input</code> buffer, and any input bytes that
2042+ * may have been buffered during a previous <code>update</code> operation,
2043+ * are processed, with padding (if requested) being applied.
2044+ * If an AEAD mode such as GCM/CCM is being used, the authentication
2045+ * tag is appended in the case of encryption, or verified in the
2046+ * case of decryption.
2047+ * The result is stored in a new buffer.
2048+ *
2049+ * <p>Upon finishing, this method resets this cipher object to the state
2050+ * it was in when previously initialized via a call to <code>init</code>.
2051+ * That is, the object is reset and available to encrypt or decrypt
2052+ * (depending on the operation mode that was specified in the call to
2053+ * <code>init</code>) more data.
2054+ *
2055+ * <p>Note: if any exception is thrown, this cipher object may need to
2056+ * be reset before it can be used again.
2057+ *
2058+ * @param input the input buffer
2059+ *
2060+ * @return the new buffer with the result
2061+ *
2062+ * @exception IllegalStateException if this cipher is in a wrong state
2063+ * (e.g., has not been initialized)
2064+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
2065+ * no padding has been requested (only in encryption mode), and the total
2066+ * input length of the data processed by this cipher is not a multiple of
2067+ * block size; or if this encryption algorithm is unable to
2068+ * process the input data provided.
2069+ * @exception BadPaddingException if this cipher is in decryption mode,
2070+ * and (un)padding has been requested, but the decrypted data is not
2071+ * bounded by the appropriate padding bytes
2072+ * @exception AEADBadTagException if this cipher is decrypting in an
2073+ * AEAD mode (such as GCM/CCM), and the received authentication tag
2074+ * does not match the calculated value
2075+ */
2076+ public final byte[] doFinal(byte[] input)
2077+ throws IllegalBlockSizeException, BadPaddingException {
2078+ checkCipherState();
2079+
2080+ // Input sanity check
2081+ if (input == null) {
2082+ throw new IllegalArgumentException("Null input buffer");
2083+ }
2084+
2085+ chooseFirstProvider();
2086+ return spi.engineDoFinal(input, 0, input.length);
2087+ }
2088+
2089+ /**
2090+ * Encrypts or decrypts data in a single-part operation, or finishes a
2091+ * multiple-part operation. The data is encrypted or decrypted,
2092+ * depending on how this cipher was initialized.
2093+ *
2094+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
2095+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
2096+ * bytes that may have been buffered during a previous <code>update</code>
2097+ * operation, are processed, with padding (if requested) being applied.
2098+ * If an AEAD mode such as GCM/CCM is being used, the authentication
2099+ * tag is appended in the case of encryption, or verified in the
2100+ * case of decryption.
2101+ * The result is stored in a new buffer.
2102+ *
2103+ * <p>Upon finishing, this method resets this cipher object to the state
2104+ * it was in when previously initialized via a call to <code>init</code>.
2105+ * That is, the object is reset and available to encrypt or decrypt
2106+ * (depending on the operation mode that was specified in the call to
2107+ * <code>init</code>) more data.
2108+ *
2109+ * <p>Note: if any exception is thrown, this cipher object may need to
2110+ * be reset before it can be used again.
2111+ *
2112+ * @param input the input buffer
2113+ * @param inputOffset the offset in <code>input</code> where the input
2114+ * starts
2115+ * @param inputLen the input length
2116+ *
2117+ * @return the new buffer with the result
2118+ *
2119+ * @exception IllegalStateException if this cipher is in a wrong state
2120+ * (e.g., has not been initialized)
2121+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
2122+ * no padding has been requested (only in encryption mode), and the total
2123+ * input length of the data processed by this cipher is not a multiple of
2124+ * block size; or if this encryption algorithm is unable to
2125+ * process the input data provided.
2126+ * @exception BadPaddingException if this cipher is in decryption mode,
2127+ * and (un)padding has been requested, but the decrypted data is not
2128+ * bounded by the appropriate padding bytes
2129+ * @exception AEADBadTagException if this cipher is decrypting in an
2130+ * AEAD mode (such as GCM/CCM), and the received authentication tag
2131+ * does not match the calculated value
2132+ */
2133+ public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)
2134+ throws IllegalBlockSizeException, BadPaddingException {
2135+ checkCipherState();
2136+
2137+ // Input sanity check
2138+ if (input == null || inputOffset < 0
2139+ || inputLen > (input.length - inputOffset) || inputLen < 0) {
2140+ throw new IllegalArgumentException("Bad arguments");
2141+ }
2142+
2143+ chooseFirstProvider();
2144+ return spi.engineDoFinal(input, inputOffset, inputLen);
2145+ }
2146+
2147+ /**
2148+ * Encrypts or decrypts data in a single-part operation, or finishes a
2149+ * multiple-part operation. The data is encrypted or decrypted,
2150+ * depending on how this cipher was initialized.
2151+ *
2152+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
2153+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
2154+ * bytes that may have been buffered during a previous <code>update</code>
2155+ * operation, are processed, with padding (if requested) being applied.
2156+ * If an AEAD mode such as GCM/CCM is being used, the authentication
2157+ * tag is appended in the case of encryption, or verified in the
2158+ * case of decryption.
2159+ * The result is stored in the <code>output</code> buffer.
2160+ *
2161+ * <p>If the <code>output</code> buffer is too small to hold the result,
2162+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
2163+ * call with a larger output buffer. Use
2164+ * {@link #getOutputSize(int) getOutputSize} to determine how big
2165+ * the output buffer should be.
2166+ *
2167+ * <p>Upon finishing, this method resets this cipher object to the state
2168+ * it was in when previously initialized via a call to <code>init</code>.
2169+ * That is, the object is reset and available to encrypt or decrypt
2170+ * (depending on the operation mode that was specified in the call to
2171+ * <code>init</code>) more data.
2172+ *
2173+ * <p>Note: if any exception is thrown, this cipher object may need to
2174+ * be reset before it can be used again.
2175+ *
2176+ * <p>Note: this method should be copy-safe, which means the
2177+ * <code>input</code> and <code>output</code> buffers can reference
2178+ * the same byte array and no unprocessed input data is overwritten
2179+ * when the result is copied into the output buffer.
2180+ *
2181+ * @param input the input buffer
2182+ * @param inputOffset the offset in <code>input</code> where the input
2183+ * starts
2184+ * @param inputLen the input length
2185+ * @param output the buffer for the result
2186+ *
2187+ * @return the number of bytes stored in <code>output</code>
2188+ *
2189+ * @exception IllegalStateException if this cipher is in a wrong state
2190+ * (e.g., has not been initialized)
2191+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
2192+ * no padding has been requested (only in encryption mode), and the total
2193+ * input length of the data processed by this cipher is not a multiple of
2194+ * block size; or if this encryption algorithm is unable to
2195+ * process the input data provided.
2196+ * @exception ShortBufferException if the given output buffer is too small
2197+ * to hold the result
2198+ * @exception BadPaddingException if this cipher is in decryption mode,
2199+ * and (un)padding has been requested, but the decrypted data is not
2200+ * bounded by the appropriate padding bytes
2201+ * @exception AEADBadTagException if this cipher is decrypting in an
2202+ * AEAD mode (such as GCM/CCM), and the received authentication tag
2203+ * does not match the calculated value
2204+ */
2205+ public final int doFinal(byte[] input, int inputOffset, int inputLen,
2206+ byte[] output)
2207+ throws ShortBufferException, IllegalBlockSizeException,
2208+ BadPaddingException {
2209+ checkCipherState();
2210+
2211+ // Input sanity check
2212+ if (input == null || inputOffset < 0
2213+ || inputLen > (input.length - inputOffset) || inputLen < 0) {
2214+ throw new IllegalArgumentException("Bad arguments");
2215+ }
2216+
2217+ chooseFirstProvider();
2218+ return spi.engineDoFinal(input, inputOffset, inputLen,
2219+ output, 0);
2220+ }
2221+
2222+ /**
2223+ * Encrypts or decrypts data in a single-part operation, or finishes a
2224+ * multiple-part operation. The data is encrypted or decrypted,
2225+ * depending on how this cipher was initialized.
2226+ *
2227+ * <p>The first <code>inputLen</code> bytes in the <code>input</code>
2228+ * buffer, starting at <code>inputOffset</code> inclusive, and any input
2229+ * bytes that may have been buffered during a previous
2230+ * <code>update</code> operation, are processed, with padding
2231+ * (if requested) being applied.
2232+ * If an AEAD mode such as GCM/CCM is being used, the authentication
2233+ * tag is appended in the case of encryption, or verified in the
2234+ * case of decryption.
2235+ * The result is stored in the <code>output</code> buffer, starting at
2236+ * <code>outputOffset</code> inclusive.
2237+ *
2238+ * <p>If the <code>output</code> buffer is too small to hold the result,
2239+ * a <code>ShortBufferException</code> is thrown. In this case, repeat this
2240+ * call with a larger output buffer. Use
2241+ * {@link #getOutputSize(int) getOutputSize} to determine how big
2242+ * the output buffer should be.
2243+ *
2244+ * <p>Upon finishing, this method resets this cipher object to the state
2245+ * it was in when previously initialized via a call to <code>init</code>.
2246+ * That is, the object is reset and available to encrypt or decrypt
2247+ * (depending on the operation mode that was specified in the call to
2248+ * <code>init</code>) more data.
2249+ *
2250+ * <p>Note: if any exception is thrown, this cipher object may need to
2251+ * be reset before it can be used again.
2252+ *
2253+ * <p>Note: this method should be copy-safe, which means the
2254+ * <code>input</code> and <code>output</code> buffers can reference
2255+ * the same byte array and no unprocessed input data is overwritten
2256+ * when the result is copied into the output buffer.
2257+ *
2258+ * @param input the input buffer
2259+ * @param inputOffset the offset in <code>input</code> where the input
2260+ * starts
2261+ * @param inputLen the input length
2262+ * @param output the buffer for the result
2263+ * @param outputOffset the offset in <code>output</code> where the result
2264+ * is stored
2265+ *
2266+ * @return the number of bytes stored in <code>output</code>
2267+ *
2268+ * @exception IllegalStateException if this cipher is in a wrong state
2269+ * (e.g., has not been initialized)
2270+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
2271+ * no padding has been requested (only in encryption mode), and the total
2272+ * input length of the data processed by this cipher is not a multiple of
2273+ * block size; or if this encryption algorithm is unable to
2274+ * process the input data provided.
2275+ * @exception ShortBufferException if the given output buffer is too small
2276+ * to hold the result
2277+ * @exception BadPaddingException if this cipher is in decryption mode,
2278+ * and (un)padding has been requested, but the decrypted data is not
2279+ * bounded by the appropriate padding bytes
2280+ * @exception AEADBadTagException if this cipher is decrypting in an
2281+ * AEAD mode (such as GCM/CCM), and the received authentication tag
2282+ * does not match the calculated value
2283+ */
2284+ public final int doFinal(byte[] input, int inputOffset, int inputLen,
2285+ byte[] output, int outputOffset)
2286+ throws ShortBufferException, IllegalBlockSizeException,
2287+ BadPaddingException {
2288+ checkCipherState();
2289+
2290+ // Input sanity check
2291+ if (input == null || inputOffset < 0
2292+ || inputLen > (input.length - inputOffset) || inputLen < 0
2293+ || outputOffset < 0) {
2294+ throw new IllegalArgumentException("Bad arguments");
2295+ }
2296+
2297+ chooseFirstProvider();
2298+ return spi.engineDoFinal(input, inputOffset, inputLen,
2299+ output, outputOffset);
2300+ }
2301+
2302+ /**
2303+ * Encrypts or decrypts data in a single-part operation, or finishes a
2304+ * multiple-part operation. The data is encrypted or decrypted,
2305+ * depending on how this cipher was initialized.
2306+ *
2307+ * <p>All <code>input.remaining()</code> bytes starting at
2308+ * <code>input.position()</code> are processed.
2309+ * If an AEAD mode such as GCM/CCM is being used, the authentication
2310+ * tag is appended in the case of encryption, or verified in the
2311+ * case of decryption.
2312+ * The result is stored in the output buffer.
2313+ * Upon return, the input buffer's position will be equal
2314+ * to its limit; its limit will not have changed. The output buffer's
2315+ * position will have advanced by n, where n is the value returned
2316+ * by this method; the output buffer's limit will not have changed.
2317+ *
2318+ * <p>If <code>output.remaining()</code> bytes are insufficient to
2319+ * hold the result, a <code>ShortBufferException</code> is thrown.
2320+ * In this case, repeat this call with a larger output buffer. Use
2321+ * {@link #getOutputSize(int) getOutputSize} to determine how big
2322+ * the output buffer should be.
2323+ *
2324+ * <p>Upon finishing, this method resets this cipher object to the state
2325+ * it was in when previously initialized via a call to <code>init</code>.
2326+ * That is, the object is reset and available to encrypt or decrypt
2327+ * (depending on the operation mode that was specified in the call to
2328+ * <code>init</code>) more data.
2329+ *
2330+ * <p>Note: if any exception is thrown, this cipher object may need to
2331+ * be reset before it can be used again.
2332+ *
2333+ * <p>Note: this method should be copy-safe, which means the
2334+ * <code>input</code> and <code>output</code> buffers can reference
2335+ * the same byte array and no unprocessed input data is overwritten
2336+ * when the result is copied into the output buffer.
2337+ *
2338+ * @param input the input ByteBuffer
2339+ * @param output the output ByteBuffer
2340+ *
2341+ * @return the number of bytes stored in <code>output</code>
2342+ *
2343+ * @exception IllegalStateException if this cipher is in a wrong state
2344+ * (e.g., has not been initialized)
2345+ * @exception IllegalArgumentException if input and output are the
2346+ * same object
2347+ * @exception ReadOnlyBufferException if the output buffer is read-only
2348+ * @exception IllegalBlockSizeException if this cipher is a block cipher,
2349+ * no padding has been requested (only in encryption mode), and the total
2350+ * input length of the data processed by this cipher is not a multiple of
2351+ * block size; or if this encryption algorithm is unable to
2352+ * process the input data provided.
2353+ * @exception ShortBufferException if there is insufficient space in the
2354+ * output buffer
2355+ * @exception BadPaddingException if this cipher is in decryption mode,
2356+ * and (un)padding has been requested, but the decrypted data is not
2357+ * bounded by the appropriate padding bytes
2358+ * @exception AEADBadTagException if this cipher is decrypting in an
2359+ * AEAD mode (such as GCM/CCM), and the received authentication tag
2360+ * does not match the calculated value
2361+ *
2362+ * @since 1.5
2363+ */
2364+ public final int doFinal(ByteBuffer input, ByteBuffer output)
2365+ throws ShortBufferException, IllegalBlockSizeException,
2366+ BadPaddingException {
2367+ checkCipherState();
2368+
2369+ if ((input == null) || (output == null)) {
2370+ throw new IllegalArgumentException("Buffers must not be null");
2371+ }
2372+ if (input == output) {
2373+ throw new IllegalArgumentException("Input and output buffers must "
2374+ + "not be the same object, consider using buffer.duplicate()");
2375+ }
2376+ if (output.isReadOnly()) {
2377+ throw new ReadOnlyBufferException();
2378+ }
2379+
2380+ chooseFirstProvider();
2381+ return spi.engineDoFinal(input, output);
2382+ }
2383+
2384+ /**
2385+ * Wrap a key.
2386+ *
2387+ * @param key the key to be wrapped.
2388+ *
2389+ * @return the wrapped key.
2390+ *
2391+ * @exception IllegalStateException if this cipher is in a wrong
2392+ * state (e.g., has not been initialized).
2393+ *
2394+ * @exception IllegalBlockSizeException if this cipher is a block
2395+ * cipher, no padding has been requested, and the length of the
2396+ * encoding of the key to be wrapped is not a
2397+ * multiple of the block size.
2398+ *
2399+ * @exception InvalidKeyException if it is impossible or unsafe to
2400+ * wrap the key with this cipher (e.g., a hardware protected key is
2401+ * being passed to a software-only cipher).
2402+ */
2403+ public final byte[] wrap(Key key)
2404+ throws IllegalBlockSizeException, InvalidKeyException {
2405+ if (!(this instanceof NullCipher)) {
2406+ if (!initialized) {
2407+ throw new IllegalStateException("Cipher not initialized");
2408+ }
2409+ if (opmode != Cipher.WRAP_MODE) {
2410+ throw new IllegalStateException("Cipher not initialized " +
2411+ "for wrapping keys");
2412+ }
2413+ }
2414+
2415+ chooseFirstProvider();
2416+ return spi.engineWrap(key);
2417+ }
2418+
2419+ /**
2420+ * Unwrap a previously wrapped key.
2421+ *
2422+ * @param wrappedKey the key to be unwrapped.
2423+ *
2424+ * @param wrappedKeyAlgorithm the algorithm associated with the wrapped
2425+ * key.
2426+ *
2427+ * @param wrappedKeyType the type of the wrapped key. This must be one of
2428+ * <code>SECRET_KEY</code>, <code>PRIVATE_KEY</code>, or
2429+ * <code>PUBLIC_KEY</code>.
2430+ *
2431+ * @return the unwrapped key.
2432+ *
2433+ * @exception IllegalStateException if this cipher is in a wrong state
2434+ * (e.g., has not been initialized).
2435+ *
2436+ * @exception NoSuchAlgorithmException if no installed providers
2437+ * can create keys of type <code>wrappedKeyType</code> for the
2438+ * <code>wrappedKeyAlgorithm</code>.
2439+ *
2440+ * @exception InvalidKeyException if <code>wrappedKey</code> does not
2441+ * represent a wrapped key of type <code>wrappedKeyType</code> for
2442+ * the <code>wrappedKeyAlgorithm</code>.
2443+ */
2444+ public final Key unwrap(byte[] wrappedKey,
2445+ String wrappedKeyAlgorithm,
2446+ int wrappedKeyType)
2447+ throws InvalidKeyException, NoSuchAlgorithmException {
2448+
2449+ if (!(this instanceof NullCipher)) {
2450+ if (!initialized) {
2451+ throw new IllegalStateException("Cipher not initialized");
2452+ }
2453+ if (opmode != Cipher.UNWRAP_MODE) {
2454+ throw new IllegalStateException("Cipher not initialized " +
2455+ "for unwrapping keys");
2456+ }
2457+ }
2458+ if ((wrappedKeyType != SECRET_KEY) &&
2459+ (wrappedKeyType != PRIVATE_KEY) &&
2460+ (wrappedKeyType != PUBLIC_KEY)) {
2461+ throw new InvalidParameterException("Invalid key type");
2462+ }
2463+
2464+ chooseFirstProvider();
2465+ return spi.engineUnwrap(wrappedKey,
2466+ wrappedKeyAlgorithm,
2467+ wrappedKeyType);
2468+ }
2469+
2470+ private AlgorithmParameterSpec getAlgorithmParameterSpec(
2471+ AlgorithmParameters params)
2472+ throws InvalidParameterSpecException {
2473+ if (params == null) {
2474+ return null;
2475+ }
2476+
2477+ String alg = params.getAlgorithm().toUpperCase(Locale.ENGLISH);
2478+
2479+ if (alg.equalsIgnoreCase("RC2")) {
2480+ return params.getParameterSpec(RC2ParameterSpec.class);
2481+ }
2482+
2483+ if (alg.equalsIgnoreCase("RC5")) {
2484+ return params.getParameterSpec(RC5ParameterSpec.class);
2485+ }
2486+
2487+ if (alg.startsWith("PBE")) {
2488+ return params.getParameterSpec(PBEParameterSpec.class);
2489+ }
2490+
2491+ if (alg.startsWith("DES")) {
2492+ return params.getParameterSpec(IvParameterSpec.class);
2493+ }
2494+ return null;
2495+ }
2496+
2497+ private static CryptoPermission getConfiguredPermission(
2498+ String transformation) throws NullPointerException,
2499+ NoSuchAlgorithmException {
2500+ if (transformation == null) throw new NullPointerException();
2501+ String[] parts = tokenizeTransformation(transformation);
2502+ return JceSecurityManager.INSTANCE.getCryptoPermission(parts[0]);
2503+ }
2504+
2505+ /**
2506+ * Returns the maximum key length for the specified transformation
2507+ * according to the installed JCE jurisdiction policy files. If
2508+ * JCE unlimited strength jurisdiction policy files are installed,
2509+ * Integer.MAX_VALUE will be returned.
2510+ * For more information on default key size in JCE jurisdiction
2511+ * policy files, please see Appendix E in the
2512+ * <a href=
2513+ * "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppC">
2514+ * Java Cryptography Architecture Reference Guide</a>.
2515+ *
2516+ * @param transformation the cipher transformation.
2517+ * @return the maximum key length in bits or Integer.MAX_VALUE.
2518+ * @exception NullPointerException if <code>transformation</code> is null.
2519+ * @exception NoSuchAlgorithmException if <code>transformation</code>
2520+ * is not a valid transformation, i.e. in the form of "algorithm" or
2521+ * "algorithm/mode/padding".
2522+ * @since 1.5
2523+ */
2524+ public static final int getMaxAllowedKeyLength(String transformation)
2525+ throws NoSuchAlgorithmException {
2526+ CryptoPermission cp = getConfiguredPermission(transformation);
2527+ return cp.getMaxKeySize();
2528+ }
2529+
2530+ /**
2531+ * Returns an AlgorithmParameterSpec object which contains
2532+ * the maximum cipher parameter value according to the
2533+ * jurisdiction policy file. If JCE unlimited strength jurisdiction
2534+ * policy files are installed or there is no maximum limit on the
2535+ * parameters for the specified transformation in the policy file,
2536+ * null will be returned.
2537+ *
2538+ * @param transformation the cipher transformation.
2539+ * @return an AlgorithmParameterSpec which holds the maximum
2540+ * value or null.
2541+ * @exception NullPointerException if <code>transformation</code>
2542+ * is null.
2543+ * @exception NoSuchAlgorithmException if <code>transformation</code>
2544+ * is not a valid transformation, i.e. in the form of "algorithm" or
2545+ * "algorithm/mode/padding".
2546+ * @since 1.5
2547+ */
2548+ public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(
2549+ String transformation) throws NoSuchAlgorithmException {
2550+ CryptoPermission cp = getConfiguredPermission(transformation);
2551+ return cp.getAlgorithmParameterSpec();
2552+ }
2553+
2554+ /**
2555+ * Continues a multi-part update of the Additional Authentication
2556+ * Data (AAD).
2557+ * <p>
2558+ * Calls to this method provide AAD to the cipher when operating in
2559+ * modes such as AEAD (GCM/CCM). If this cipher is operating in
2560+ * either GCM or CCM mode, all AAD must be supplied before beginning
2561+ * operations on the ciphertext (via the {@code update} and {@code
2562+ * doFinal} methods).
2563+ *
2564+ * @param src the buffer containing the Additional Authentication Data
2565+ *
2566+ * @throws IllegalArgumentException if the {@code src}
2567+ * byte array is null
2568+ * @throws IllegalStateException if this cipher is in a wrong state
2569+ * (e.g., has not been initialized), does not accept AAD, or if
2570+ * operating in either GCM or CCM mode and one of the {@code update}
2571+ * methods has already been called for the active
2572+ * encryption/decryption operation
2573+ * @throws UnsupportedOperationException if the corresponding method
2574+ * in the {@code CipherSpi} has not been overridden by an
2575+ * implementation
2576+ *
2577+ * @since 1.7
2578+ */
2579+ public final void updateAAD(byte[] src) {
2580+ if (src == null) {
2581+ throw new IllegalArgumentException("src buffer is null");
2582+ }
2583+
2584+ updateAAD(src, 0, src.length);
2585+ }
2586+
2587+ /**
2588+ * Continues a multi-part update of the Additional Authentication
2589+ * Data (AAD), using a subset of the provided buffer.
2590+ * <p>
2591+ * Calls to this method provide AAD to the cipher when operating in
2592+ * modes such as AEAD (GCM/CCM). If this cipher is operating in
2593+ * either GCM or CCM mode, all AAD must be supplied before beginning
2594+ * operations on the ciphertext (via the {@code update} and {@code
2595+ * doFinal} methods).
2596+ *
2597+ * @param src the buffer containing the AAD
2598+ * @param offset the offset in {@code src} where the AAD input starts
2599+ * @param len the number of AAD bytes
2600+ *
2601+ * @throws IllegalArgumentException if the {@code src}
2602+ * byte array is null, or the {@code offset} or {@code length}
2603+ * is less than 0, or the sum of the {@code offset} and
2604+ * {@code len} is greater than the length of the
2605+ * {@code src} byte array
2606+ * @throws IllegalStateException if this cipher is in a wrong state
2607+ * (e.g., has not been initialized), does not accept AAD, or if
2608+ * operating in either GCM or CCM mode and one of the {@code update}
2609+ * methods has already been called for the active
2610+ * encryption/decryption operation
2611+ * @throws UnsupportedOperationException if the corresponding method
2612+ * in the {@code CipherSpi} has not been overridden by an
2613+ * implementation
2614+ *
2615+ * @since 1.7
2616+ */
2617+ public final void updateAAD(byte[] src, int offset, int len) {
2618+ checkCipherState();
2619+
2620+ // Input sanity check
2621+ if ((src == null) || (offset < 0) || (len < 0)
2622+ || ((len + offset) > src.length)) {
2623+ throw new IllegalArgumentException("Bad arguments");
2624+ }
2625+
2626+ chooseFirstProvider();
2627+ if (len == 0) {
2628+ return;
2629+ }
2630+ spi.engineUpdateAAD(src, offset, len);
2631+ }
2632+
2633+ /**
2634+ * Continues a multi-part update of the Additional Authentication
2635+ * Data (AAD).
2636+ * <p>
2637+ * Calls to this method provide AAD to the cipher when operating in
2638+ * modes such as AEAD (GCM/CCM). If this cipher is operating in
2639+ * either GCM or CCM mode, all AAD must be supplied before beginning
2640+ * operations on the ciphertext (via the {@code update} and {@code
2641+ * doFinal} methods).
2642+ * <p>
2643+ * All {@code src.remaining()} bytes starting at
2644+ * {@code src.position()} are processed.
2645+ * Upon return, the input buffer's position will be equal
2646+ * to its limit; its limit will not have changed.
2647+ *
2648+ * @param src the buffer containing the AAD
2649+ *
2650+ * @throws IllegalArgumentException if the {@code src ByteBuffer}
2651+ * is null
2652+ * @throws IllegalStateException if this cipher is in a wrong state
2653+ * (e.g., has not been initialized), does not accept AAD, or if
2654+ * operating in either GCM or CCM mode and one of the {@code update}
2655+ * methods has already been called for the active
2656+ * encryption/decryption operation
2657+ * @throws UnsupportedOperationException if the corresponding method
2658+ * in the {@code CipherSpi} has not been overridden by an
2659+ * implementation
2660+ *
2661+ * @since 1.7
2662+ */
2663+ public final void updateAAD(ByteBuffer src) {
2664+ checkCipherState();
2665+
2666+ // Input sanity check
2667+ if (src == null) {
2668+ throw new IllegalArgumentException("src ByteBuffer is null");
2669+ }
2670+
2671+ chooseFirstProvider();
2672+ if (src.remaining() == 0) {
2673+ return;
2674+ }
2675+ spi.engineUpdateAAD(src);
2676+ }
2677+}