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