Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/javax/crypto/Cipher.java
38829 views
/*1* Copyright (c) 1997, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package javax.crypto;2627import java.util.*;28import java.util.concurrent.ConcurrentHashMap;29import java.util.concurrent.ConcurrentMap;30import java.util.regex.*;313233import java.security.*;34import java.security.Provider.Service;35import java.security.spec.AlgorithmParameterSpec;36import java.security.spec.InvalidParameterSpecException;37import java.security.cert.Certificate;38import java.security.cert.X509Certificate;3940import javax.crypto.spec.*;4142import java.nio.ByteBuffer;43import java.nio.ReadOnlyBufferException;4445import sun.security.util.Debug;46import sun.security.jca.*;4748/**49* This class provides the functionality of a cryptographic cipher for50* encryption and decryption. It forms the core of the Java Cryptographic51* Extension (JCE) framework.52*53* <p>In order to create a Cipher object, the application calls the54* Cipher's {@code getInstance} method, and passes the name of the55* requested <i>transformation</i> to it. Optionally, the name of a provider56* may be specified.57*58* <p>A <i>transformation</i> is a string that describes the operation (or59* set of operations) to be performed on the given input, to produce some60* output. A transformation always includes the name of a cryptographic61* algorithm (e.g., <i>AES</i>), and may be followed by a feedback mode and62* padding scheme.63*64* <p> A transformation is of the form:65*66* <ul>67* <li>"<i>algorithm/mode/padding</i>" or68*69* <li>"<i>algorithm</i>"70* </ul>71*72* <P> (in the latter case,73* provider-specific default values for the mode and padding scheme are used).74* For example, the following is a valid transformation:75*76* <pre>77* Cipher c = Cipher.getInstance("<i>AES/CBC/PKCS5Padding</i>");78* </pre>79*80* Using modes such as {@code CFB} and {@code OFB}, block81* ciphers can encrypt data in units smaller than the cipher's actual82* block size. When requesting such a mode, you may optionally specify83* the number of bits to be processed at a time by appending this number84* to the mode name as shown in the "{@code AES/CFB8/NoPadding}" and85* "{@code AES/OFB32/PKCS5Padding}" transformations. If no such86* number is specified, a provider-specific default is used.87* Thus, block ciphers can be turned into byte-oriented stream ciphers by88* using an 8 bit mode such as CFB8 or OFB8.89* <p>90* Modes such as Authenticated Encryption with Associated Data (AEAD)91* provide authenticity assurances for both confidential data and92* Additional Associated Data (AAD) that is not encrypted. (Please see93* <a href="http://www.ietf.org/rfc/rfc5116.txt"> RFC 5116 </a> for more94* information on AEAD and AEAD algorithms such as GCM/CCM.) Both95* confidential and AAD data can be used when calculating the96* authentication tag (similar to a {@link Mac}). This tag is appended97* to the ciphertext during encryption, and is verified on decryption.98* <p>99* AEAD modes such as GCM/CCM perform all AAD authenticity calculations100* before starting the ciphertext authenticity calculations. To avoid101* implementations having to internally buffer ciphertext, all AAD data102* must be supplied to GCM/CCM implementations (via the {@code103* updateAAD} methods) <b>before</b> the ciphertext is processed (via104* the {@code update} and {@code doFinal} methods).105* <p>106* Note that GCM mode has a uniqueness requirement on IVs used in107* encryption with a given key. When IVs are repeated for GCM108* encryption, such usages are subject to forgery attacks. Thus, after109* each encryption operation using GCM mode, callers should re-initialize110* the cipher objects with GCM parameters which has a different IV value.111* <pre>112* GCMParameterSpec s = ...;113* cipher.init(..., s);114*115* // If the GCM parameters were generated by the provider, it can116* // be retrieved by:117* // cipher.getParameters().getParameterSpec(GCMParameterSpec.class);118*119* cipher.updateAAD(...); // AAD120* cipher.update(...); // Multi-part update121* cipher.doFinal(...); // conclusion of operation122*123* // Use a different IV value for every encryption124* byte[] newIv = ...;125* s = new GCMParameterSpec(s.getTLen(), newIv);126* cipher.init(..., s);127* ...128*129* </pre>130* Every implementation of the Java platform is required to support131* the following standard {@code Cipher} transformations with the keysizes132* in parentheses:133* <ul>134* <li>{@code AES/CBC/NoPadding} (128)</li>135* <li>{@code AES/CBC/PKCS5Padding} (128)</li>136* <li>{@code AES/ECB/NoPadding} (128)</li>137* <li>{@code AES/ECB/PKCS5Padding} (128)</li>138* <li>{@code DES/CBC/NoPadding} (56)</li>139* <li>{@code DES/CBC/PKCS5Padding} (56)</li>140* <li>{@code DES/ECB/NoPadding} (56)</li>141* <li>{@code DES/ECB/PKCS5Padding} (56)</li>142* <li>{@code DESede/CBC/NoPadding} (168)</li>143* <li>{@code DESede/CBC/PKCS5Padding} (168)</li>144* <li>{@code DESede/ECB/NoPadding} (168)</li>145* <li>{@code DESede/ECB/PKCS5Padding} (168)</li>146* <li>{@code RSA/ECB/PKCS1Padding} (1024, 2048)</li>147* <li>{@code RSA/ECB/OAEPWithSHA-1AndMGF1Padding} (1024, 2048)</li>148* <li>{@code RSA/ECB/OAEPWithSHA-256AndMGF1Padding} (1024, 2048)</li>149* </ul>150* These transformations are described in the151* <a href="{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">152* Cipher section</a> of the153* Java Cryptography Architecture Standard Algorithm Name Documentation.154* Consult the release documentation for your implementation to see if any155* other transformations are supported.156*157* @author Jan Luehe158* @see KeyGenerator159* @see SecretKey160* @since 1.4161*/162163public class Cipher {164165private static final Debug debug =166Debug.getInstance("jca", "Cipher");167168private static final Debug pdebug =169Debug.getInstance("provider", "Provider");170private static final boolean skipDebug =171Debug.isOn("engine=") && !Debug.isOn("cipher");172173/**174* Constant used to initialize cipher to encryption mode.175*/176public static final int ENCRYPT_MODE = 1;177178/**179* Constant used to initialize cipher to decryption mode.180*/181public static final int DECRYPT_MODE = 2;182183/**184* Constant used to initialize cipher to key-wrapping mode.185*/186public static final int WRAP_MODE = 3;187188/**189* Constant used to initialize cipher to key-unwrapping mode.190*/191public static final int UNWRAP_MODE = 4;192193/**194* Constant used to indicate the to-be-unwrapped key is a "public key".195*/196public static final int PUBLIC_KEY = 1;197198/**199* Constant used to indicate the to-be-unwrapped key is a "private key".200*/201public static final int PRIVATE_KEY = 2;202203/**204* Constant used to indicate the to-be-unwrapped key is a "secret key".205*/206public static final int SECRET_KEY = 3;207208// The provider209private Provider provider;210211// The provider implementation (delegate)212private CipherSpi spi;213214// The transformation215private String transformation;216217// Crypto permission representing the maximum allowable cryptographic218// strength that this Cipher object can be used for. (The cryptographic219// strength is a function of the keysize and algorithm parameters encoded220// in the crypto permission.)221private CryptoPermission cryptoPerm;222223// The exemption mechanism that needs to be enforced224private ExemptionMechanism exmech;225226// Flag which indicates whether or not this cipher has been initialized227private boolean initialized = false;228229// The operation mode - store the operation mode after the230// cipher has been initialized.231private int opmode = 0;232233// The OID for the KeyUsage extension in an X.509 v3 certificate234private static final String KEY_USAGE_EXTENSION_OID = "2.5.29.15";235236// next SPI to try in provider selection237// null once provider is selected238private CipherSpi firstSpi;239240// next service to try in provider selection241// null once provider is selected242private Service firstService;243244// remaining services to try in provider selection245// null once provider is selected246private Iterator<Service> serviceIterator;247248// list of transform Strings to lookup in the provider249private List<Transform> transforms;250251private final Object lock;252253/**254* Creates a Cipher object.255*256* @param cipherSpi the delegate257* @param provider the provider258* @param transformation the transformation259*/260protected Cipher(CipherSpi cipherSpi,261Provider provider,262String transformation) {263// See bug 4341369 & 4334690 for more info.264// If the caller is trusted, then okey.265// Otherwise throw a NullPointerException.266if (!JceSecurityManager.INSTANCE.isCallerTrusted()) {267throw new NullPointerException();268}269this.spi = cipherSpi;270this.provider = provider;271this.transformation = transformation;272this.cryptoPerm = CryptoAllPermission.INSTANCE;273this.lock = null;274}275276/**277* Creates a Cipher object. Called internally and by NullCipher.278*279* @param cipherSpi the delegate280* @param transformation the transformation281*/282Cipher(CipherSpi cipherSpi, String transformation) {283this.spi = cipherSpi;284this.transformation = transformation;285this.cryptoPerm = CryptoAllPermission.INSTANCE;286this.lock = null;287}288289private Cipher(CipherSpi firstSpi, Service firstService,290Iterator<Service> serviceIterator, String transformation,291List<Transform> transforms) {292this.firstSpi = firstSpi;293this.firstService = firstService;294this.serviceIterator = serviceIterator;295this.transforms = transforms;296this.transformation = transformation;297this.lock = new Object();298}299300private static String[] tokenizeTransformation(String transformation)301throws NoSuchAlgorithmException {302if (transformation == null) {303throw new NoSuchAlgorithmException("No transformation given");304}305/*306* array containing the components of a Cipher transformation:307*308* index 0: algorithm component (e.g., AES)309* index 1: feedback component (e.g., CFB)310* index 2: padding component (e.g., PKCS5Padding)311*/312String[] parts = new String[3];313int count = 0;314StringTokenizer parser = new StringTokenizer(transformation, "/");315try {316while (parser.hasMoreTokens() && count < 3) {317parts[count++] = parser.nextToken().trim();318}319if (count == 0 || count == 2) {320throw new NoSuchAlgorithmException("Invalid transformation"321+ " format:" +322transformation);323}324// treats all subsequent tokens as part of padding325if (count == 3 && parser.hasMoreTokens()) {326parts[2] = parts[2] + parser.nextToken("\r\n");327}328} catch (NoSuchElementException e) {329throw new NoSuchAlgorithmException("Invalid transformation " +330"format:" + transformation);331}332if ((parts[0] == null) || (parts[0].length() == 0)) {333throw new NoSuchAlgorithmException("Invalid transformation:" +334"algorithm not specified-"335+ transformation);336}337return parts;338}339340// Provider attribute name for supported chaining mode341private final static String ATTR_MODE = "SupportedModes";342// Provider attribute name for supported padding names343private final static String ATTR_PAD = "SupportedPaddings";344345// constants indicating whether the provider supports346// a given mode or padding347private final static int S_NO = 0; // does not support348private final static int S_MAYBE = 1; // unable to determine349private final static int S_YES = 2; // does support350351/**352* Nested class to deal with modes and paddings.353*/354private static class Transform {355// transform string to lookup in the provider356final String transform;357// the mode/padding suffix in upper case. for example, if the algorithm358// to lookup is "AES/CBC/PKCS5Padding" suffix is "/CBC/PKCS5PADDING"359// if lookup is "AES", suffix is the empty string360// needed because aliases prevent straight transform.equals()361final String suffix;362// value to pass to setMode() or null if no such call required363final String mode;364// value to pass to setPadding() or null if no such call required365final String pad;366Transform(String alg, String suffix, String mode, String pad) {367this.transform = alg + suffix;368this.suffix = suffix.toUpperCase(Locale.ENGLISH);369this.mode = mode;370this.pad = pad;371}372// set mode and padding for the given SPI373void setModePadding(CipherSpi spi) throws NoSuchAlgorithmException,374NoSuchPaddingException {375if (mode != null) {376spi.engineSetMode(mode);377}378if (pad != null) {379spi.engineSetPadding(pad);380}381}382// check whether the given services supports the mode and383// padding described by this Transform384int supportsModePadding(Service s) {385int smode = supportsMode(s);386if (smode == S_NO) {387return smode;388}389int spad = supportsPadding(s);390// our constants are defined so that Math.min() is a tri-valued AND391return Math.min(smode, spad);392}393394// separate methods for mode and padding395// called directly by Cipher only to throw the correct exception396int supportsMode(Service s) {397return supports(s, ATTR_MODE, mode);398}399int supportsPadding(Service s) {400return supports(s, ATTR_PAD, pad);401}402403private static int supports(Service s, String attrName, String value) {404if (value == null) {405return S_YES;406}407String regexp = s.getAttribute(attrName);408if (regexp == null) {409return S_MAYBE;410}411return matches(regexp, value) ? S_YES : S_NO;412}413414// ConcurrentMap<String,Pattern> for previously compiled patterns415private final static ConcurrentMap<String, Pattern> patternCache =416new ConcurrentHashMap<String, Pattern>();417418private static boolean matches(String regexp, String str) {419Pattern pattern = patternCache.get(regexp);420if (pattern == null) {421pattern = Pattern.compile(regexp);422patternCache.putIfAbsent(regexp, pattern);423}424return pattern.matcher(str.toUpperCase(Locale.ENGLISH)).matches();425}426427}428429private static List<Transform> getTransforms(String transformation)430throws NoSuchAlgorithmException {431String[] parts = tokenizeTransformation(transformation);432433String alg = parts[0];434String mode = parts[1];435String pad = parts[2];436if ((mode != null) && (mode.length() == 0)) {437mode = null;438}439if ((pad != null) && (pad.length() == 0)) {440pad = null;441}442443if ((mode == null) && (pad == null)) {444// AES445Transform tr = new Transform(alg, "", null, null);446return Collections.singletonList(tr);447} else { // if ((mode != null) && (pad != null)) {448// AES/CBC/PKCS5Padding449List<Transform> list = new ArrayList<>(4);450list.add(new Transform(alg, "/" + mode + "/" + pad, null, null));451list.add(new Transform(alg, "/" + mode, null, pad));452list.add(new Transform(alg, "//" + pad, mode, null));453list.add(new Transform(alg, "", mode, pad));454return list;455}456}457458// get the transform matching the specified service459private static Transform getTransform(Service s,460List<Transform> transforms) {461String alg = s.getAlgorithm().toUpperCase(Locale.ENGLISH);462for (Transform tr : transforms) {463if (alg.endsWith(tr.suffix)) {464return tr;465}466}467return null;468}469470/**471* Returns a {@code Cipher} object that implements the specified472* transformation.473*474* <p> This method traverses the list of registered security Providers,475* starting with the most preferred Provider.476* A new Cipher object encapsulating the477* CipherSpi implementation from the first478* Provider that supports the specified algorithm is returned.479*480* <p> Note that the list of registered providers may be retrieved via481* the {@link Security#getProviders() Security.getProviders()} method.482*483* @param transformation the name of the transformation, e.g.,484* <i>AES/CBC/PKCS5Padding</i>.485* See the Cipher section in the <a href=486* "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">487* Java Cryptography Architecture Standard Algorithm Name Documentation</a>488* for information about standard transformation names.489*490* @return a cipher that implements the requested transformation.491*492* @exception NoSuchAlgorithmException if {@code transformation}493* is null, empty, in an invalid format,494* or if no Provider supports a CipherSpi implementation for the495* specified algorithm.496*497* @exception NoSuchPaddingException if {@code transformation}498* contains a padding scheme that is not available.499*500* @see java.security.Provider501*/502public static final Cipher getInstance(String transformation)503throws NoSuchAlgorithmException, NoSuchPaddingException504{505List<Transform> transforms = getTransforms(transformation);506List<ServiceId> cipherServices = new ArrayList<>(transforms.size());507for (Transform transform : transforms) {508cipherServices.add(new ServiceId("Cipher", transform.transform));509}510List<Service> services = GetInstance.getServices(cipherServices);511// make sure there is at least one service from a signed provider512// and that it can use the specified mode and padding513Iterator<Service> t = services.iterator();514Exception failure = null;515while (t.hasNext()) {516Service s = t.next();517if (JceSecurity.canUseProvider(s.getProvider()) == false) {518continue;519}520Transform tr = getTransform(s, transforms);521if (tr == null) {522// should never happen523continue;524}525int canuse = tr.supportsModePadding(s);526if (canuse == S_NO) {527// does not support mode or padding we need, ignore528continue;529}530if (canuse == S_YES) {531return new Cipher(null, s, t, transformation, transforms);532} else { // S_MAYBE, try out if it works533try {534CipherSpi spi = (CipherSpi)s.newInstance(null);535tr.setModePadding(spi);536return new Cipher(spi, s, t, transformation, transforms);537} catch (Exception e) {538failure = e;539}540}541}542throw new NoSuchAlgorithmException543("Cannot find any provider supporting " + transformation, failure);544}545546/**547* Returns a {@code Cipher} object that implements the specified548* transformation.549*550* <p> A new Cipher object encapsulating the551* CipherSpi implementation from the specified provider552* is returned. The specified provider must be registered553* in the security provider list.554*555* <p> Note that the list of registered providers may be retrieved via556* the {@link Security#getProviders() Security.getProviders()} method.557*558* @param transformation the name of the transformation,559* e.g., <i>AES/CBC/PKCS5Padding</i>.560* See the Cipher section in the <a href=561* "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">562* Java Cryptography Architecture Standard Algorithm Name Documentation</a>563* for information about standard transformation names.564*565* @param provider the name of the provider.566*567* @return a cipher that implements the requested transformation.568*569* @exception NoSuchAlgorithmException if {@code transformation}570* is null, empty, in an invalid format,571* or if a CipherSpi implementation for the specified algorithm572* is not available from the specified provider.573*574* @exception NoSuchProviderException if the specified provider is not575* registered in the security provider list.576*577* @exception NoSuchPaddingException if {@code transformation}578* contains a padding scheme that is not available.579*580* @exception IllegalArgumentException if the {@code provider}581* is null or empty.582*583* @see java.security.Provider584*/585public static final Cipher getInstance(String transformation,586String provider)587throws NoSuchAlgorithmException, NoSuchProviderException,588NoSuchPaddingException589{590if ((provider == null) || (provider.length() == 0)) {591throw new IllegalArgumentException("Missing provider");592}593Provider p = Security.getProvider(provider);594if (p == null) {595throw new NoSuchProviderException("No such provider: " +596provider);597}598return getInstance(transformation, p);599}600601/**602* Returns a {@code Cipher} object that implements the specified603* transformation.604*605* <p> A new Cipher object encapsulating the606* CipherSpi implementation from the specified Provider607* object is returned. Note that the specified Provider object608* does not have to be registered in the provider list.609*610* @param transformation the name of the transformation,611* e.g., <i>AES/CBC/PKCS5Padding</i>.612* See the Cipher section in the <a href=613* "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher">614* Java Cryptography Architecture Standard Algorithm Name Documentation</a>615* for information about standard transformation names.616*617* @param provider the provider.618*619* @return a cipher that implements the requested transformation.620*621* @exception NoSuchAlgorithmException if {@code transformation}622* is null, empty, in an invalid format,623* or if a CipherSpi implementation for the specified algorithm624* is not available from the specified Provider object.625*626* @exception NoSuchPaddingException if {@code transformation}627* contains a padding scheme that is not available.628*629* @exception IllegalArgumentException if the {@code provider}630* is null.631*632* @see java.security.Provider633*/634public static final Cipher getInstance(String transformation,635Provider provider)636throws NoSuchAlgorithmException, NoSuchPaddingException637{638if (provider == null) {639throw new IllegalArgumentException("Missing provider");640}641Exception failure = null;642List<Transform> transforms = getTransforms(transformation);643boolean providerChecked = false;644String paddingError = null;645for (Transform tr : transforms) {646Service s = provider.getService("Cipher", tr.transform);647if (s == null) {648continue;649}650if (providerChecked == false) {651// for compatibility, first do the lookup and then verify652// the provider. this makes the difference between a NSAE653// and a SecurityException if the654// provider does not support the algorithm.655Exception ve = JceSecurity.getVerificationResult(provider);656if (ve != null) {657String msg = "JCE cannot authenticate the provider "658+ provider.getName();659throw new SecurityException(msg, ve);660}661providerChecked = true;662}663if (tr.supportsMode(s) == S_NO) {664continue;665}666if (tr.supportsPadding(s) == S_NO) {667paddingError = tr.pad;668continue;669}670try {671CipherSpi spi = (CipherSpi)s.newInstance(null);672tr.setModePadding(spi);673Cipher cipher = new Cipher(spi, transformation);674cipher.provider = s.getProvider();675cipher.initCryptoPermission();676return cipher;677} catch (Exception e) {678failure = e;679}680}681682// throw NoSuchPaddingException if the problem is with padding683if (failure instanceof NoSuchPaddingException) {684throw (NoSuchPaddingException)failure;685}686if (paddingError != null) {687throw new NoSuchPaddingException688("Padding not supported: " + paddingError);689}690throw new NoSuchAlgorithmException691("No such algorithm: " + transformation, failure);692}693694// If the requested crypto service is export-controlled,695// determine the maximum allowable keysize.696private void initCryptoPermission() throws NoSuchAlgorithmException {697if (JceSecurity.isRestricted() == false) {698cryptoPerm = CryptoAllPermission.INSTANCE;699exmech = null;700return;701}702cryptoPerm = getConfiguredPermission(transformation);703// Instantiate the exemption mechanism (if required)704String exmechName = cryptoPerm.getExemptionMechanism();705if (exmechName != null) {706exmech = ExemptionMechanism.getInstance(exmechName);707}708}709710// max number of debug warnings to print from chooseFirstProvider()711private static int warnCount = 10;712713/**714* Choose the Spi from the first provider available. Used if715* delayed provider selection is not possible because init()716* is not the first method called.717*/718void chooseFirstProvider() {719if (spi != null) {720return;721}722synchronized (lock) {723if (spi != null) {724return;725}726if (debug != null) {727int w = --warnCount;728if (w >= 0) {729debug.println("Cipher.init() not first method "730+ "called, disabling delayed provider selection");731if (w == 0) {732debug.println("Further warnings of this type will "733+ "be suppressed");734}735new Exception("Call trace").printStackTrace();736}737}738Exception lastException = null;739while ((firstService != null) || serviceIterator.hasNext()) {740Service s;741CipherSpi thisSpi;742if (firstService != null) {743s = firstService;744thisSpi = firstSpi;745firstService = null;746firstSpi = null;747} else {748s = serviceIterator.next();749thisSpi = null;750}751if (JceSecurity.canUseProvider(s.getProvider()) == false) {752continue;753}754Transform tr = getTransform(s, transforms);755if (tr == null) {756// should never happen757continue;758}759if (tr.supportsModePadding(s) == S_NO) {760continue;761}762try {763if (thisSpi == null) {764Object obj = s.newInstance(null);765if (obj instanceof CipherSpi == false) {766continue;767}768thisSpi = (CipherSpi)obj;769}770tr.setModePadding(thisSpi);771initCryptoPermission();772spi = thisSpi;773provider = s.getProvider();774// not needed any more775firstService = null;776serviceIterator = null;777transforms = null;778return;779} catch (Exception e) {780lastException = e;781}782}783ProviderException e = new ProviderException784("Could not construct CipherSpi instance");785if (lastException != null) {786e.initCause(lastException);787}788throw e;789}790}791792private final static int I_KEY = 1;793private final static int I_PARAMSPEC = 2;794private final static int I_PARAMS = 3;795private final static int I_CERT = 4;796797private void implInit(CipherSpi thisSpi, int type, int opmode, Key key,798AlgorithmParameterSpec paramSpec, AlgorithmParameters params,799SecureRandom random) throws InvalidKeyException,800InvalidAlgorithmParameterException {801switch (type) {802case I_KEY:803checkCryptoPerm(thisSpi, key);804thisSpi.engineInit(opmode, key, random);805break;806case I_PARAMSPEC:807checkCryptoPerm(thisSpi, key, paramSpec);808thisSpi.engineInit(opmode, key, paramSpec, random);809break;810case I_PARAMS:811checkCryptoPerm(thisSpi, key, params);812thisSpi.engineInit(opmode, key, params, random);813break;814case I_CERT:815checkCryptoPerm(thisSpi, key);816thisSpi.engineInit(opmode, key, random);817break;818default:819throw new AssertionError("Internal Cipher error: " + type);820}821}822823private void chooseProvider(int initType, int opmode, Key key,824AlgorithmParameterSpec paramSpec,825AlgorithmParameters params, SecureRandom random)826throws InvalidKeyException, InvalidAlgorithmParameterException {827synchronized (lock) {828if (spi != null) {829implInit(spi, initType, opmode, key, paramSpec, params, random);830return;831}832Exception lastException = null;833while ((firstService != null) || serviceIterator.hasNext()) {834Service s;835CipherSpi thisSpi;836if (firstService != null) {837s = firstService;838thisSpi = firstSpi;839firstService = null;840firstSpi = null;841} else {842s = serviceIterator.next();843thisSpi = null;844}845// if provider says it does not support this key, ignore it846if (s.supportsParameter(key) == false) {847continue;848}849if (JceSecurity.canUseProvider(s.getProvider()) == false) {850continue;851}852Transform tr = getTransform(s, transforms);853if (tr == null) {854// should never happen855continue;856}857if (tr.supportsModePadding(s) == S_NO) {858continue;859}860try {861if (thisSpi == null) {862thisSpi = (CipherSpi)s.newInstance(null);863}864tr.setModePadding(thisSpi);865initCryptoPermission();866implInit(thisSpi, initType, opmode, key, paramSpec,867params, random);868provider = s.getProvider();869this.spi = thisSpi;870firstService = null;871serviceIterator = null;872transforms = null;873return;874} catch (Exception e) {875// NoSuchAlgorithmException from newInstance()876// InvalidKeyException from init()877// RuntimeException (ProviderException) from init()878// SecurityException from crypto permission check879if (lastException == null) {880lastException = e;881}882}883}884// no working provider found, fail885if (lastException instanceof InvalidKeyException) {886throw (InvalidKeyException)lastException;887}888if (lastException instanceof InvalidAlgorithmParameterException) {889throw (InvalidAlgorithmParameterException)lastException;890}891if (lastException instanceof RuntimeException) {892throw (RuntimeException)lastException;893}894String kName = (key != null) ? key.getClass().getName() : "(null)";895throw new InvalidKeyException896("No installed provider supports this key: "897+ kName, lastException);898}899}900901/**902* Returns the provider of this {@code Cipher} object.903*904* @return the provider of this {@code Cipher} object905*/906public final Provider getProvider() {907chooseFirstProvider();908return this.provider;909}910911/**912* Returns the algorithm name of this {@code Cipher} object.913*914* <p>This is the same name that was specified in one of the915* {@code getInstance} calls that created this {@code Cipher}916* object..917*918* @return the algorithm name of this {@code Cipher} object.919*/920public final String getAlgorithm() {921return this.transformation;922}923924/**925* Returns the block size (in bytes).926*927* @return the block size (in bytes), or 0 if the underlying algorithm is928* not a block cipher929*/930public final int getBlockSize() {931chooseFirstProvider();932return spi.engineGetBlockSize();933}934935/**936* Returns the length in bytes that an output buffer would need to be in937* order to hold the result of the next {@code update} or938* {@code doFinal} operation, given the input length939* {@code inputLen} (in bytes).940*941* <p>This call takes into account any unprocessed (buffered) data from a942* previous {@code update} call, padding, and AEAD tagging.943*944* <p>The actual output length of the next {@code update} or945* {@code doFinal} call may be smaller than the length returned by946* this method.947*948* @param inputLen the input length (in bytes)949*950* @return the required output buffer size (in bytes)951*952* @exception IllegalStateException if this cipher is in a wrong state953* (e.g., has not yet been initialized)954*/955public final int getOutputSize(int inputLen) {956957if (!initialized && !(this instanceof NullCipher)) {958throw new IllegalStateException("Cipher not initialized");959}960if (inputLen < 0) {961throw new IllegalArgumentException("Input size must be equal " +962"to or greater than zero");963}964chooseFirstProvider();965return spi.engineGetOutputSize(inputLen);966}967968/**969* Returns the initialization vector (IV) in a new buffer.970*971* <p>This is useful in the case where a random IV was created,972* or in the context of password-based encryption or973* decryption, where the IV is derived from a user-supplied password.974*975* @return the initialization vector in a new buffer, or null if the976* underlying algorithm does not use an IV, or if the IV has not yet977* been set.978*/979public final byte[] getIV() {980chooseFirstProvider();981return spi.engineGetIV();982}983984/**985* Returns the parameters used with this cipher.986*987* <p>The returned parameters may be the same that were used to initialize988* this cipher, or may contain a combination of default and random989* parameter values used by the underlying cipher implementation if this990* cipher requires algorithm parameters but was not initialized with any.991*992* @return the parameters used with this cipher, or null if this cipher993* does not use any parameters.994*/995public final AlgorithmParameters getParameters() {996chooseFirstProvider();997return spi.engineGetParameters();998}9991000/**1001* Returns the exemption mechanism object used with this cipher.1002*1003* @return the exemption mechanism object used with this cipher, or1004* null if this cipher does not use any exemption mechanism.1005*/1006public final ExemptionMechanism getExemptionMechanism() {1007chooseFirstProvider();1008return exmech;1009}10101011//1012// Crypto permission check code below1013//1014private void checkCryptoPerm(CipherSpi checkSpi, Key key)1015throws InvalidKeyException {1016if (cryptoPerm == CryptoAllPermission.INSTANCE) {1017return;1018}1019// Check if key size and default parameters are within legal limits1020AlgorithmParameterSpec params;1021try {1022params = getAlgorithmParameterSpec(checkSpi.engineGetParameters());1023} catch (InvalidParameterSpecException ipse) {1024throw new InvalidKeyException1025("Unsupported default algorithm parameters");1026}1027if (!passCryptoPermCheck(checkSpi, key, params)) {1028throw new InvalidKeyException(1029"Illegal key size or default parameters");1030}1031}10321033private void checkCryptoPerm(CipherSpi checkSpi, Key key,1034AlgorithmParameterSpec params) throws InvalidKeyException,1035InvalidAlgorithmParameterException {1036if (cryptoPerm == CryptoAllPermission.INSTANCE) {1037return;1038}1039// Determine keysize and check if it is within legal limits1040if (!passCryptoPermCheck(checkSpi, key, null)) {1041throw new InvalidKeyException("Illegal key size");1042}1043if ((params != null) && (!passCryptoPermCheck(checkSpi, key, params))) {1044throw new InvalidAlgorithmParameterException("Illegal parameters");1045}1046}10471048private void checkCryptoPerm(CipherSpi checkSpi, Key key,1049AlgorithmParameters params)1050throws InvalidKeyException, InvalidAlgorithmParameterException {1051if (cryptoPerm == CryptoAllPermission.INSTANCE) {1052return;1053}1054// Convert the specified parameters into specs and then delegate.1055AlgorithmParameterSpec pSpec;1056try {1057pSpec = getAlgorithmParameterSpec(params);1058} catch (InvalidParameterSpecException ipse) {1059throw new InvalidAlgorithmParameterException1060("Failed to retrieve algorithm parameter specification");1061}1062checkCryptoPerm(checkSpi, key, pSpec);1063}10641065private boolean passCryptoPermCheck(CipherSpi checkSpi, Key key,1066AlgorithmParameterSpec params)1067throws InvalidKeyException {1068String em = cryptoPerm.getExemptionMechanism();1069int keySize = checkSpi.engineGetKeySize(key);1070// Use the "algorithm" component of the cipher1071// transformation so that the perm check would1072// work when the key has the "aliased" algo.1073String algComponent;1074int index = transformation.indexOf('/');1075if (index != -1) {1076algComponent = transformation.substring(0, index);1077} else {1078algComponent = transformation;1079}1080CryptoPermission checkPerm =1081new CryptoPermission(algComponent, keySize, params, em);10821083if (!cryptoPerm.implies(checkPerm)) {1084if (debug != null) {1085debug.println("Crypto Permission check failed");1086debug.println("granted: " + cryptoPerm);1087debug.println("requesting: " + checkPerm);1088}1089return false;1090}1091if (exmech == null) {1092return true;1093}1094try {1095if (!exmech.isCryptoAllowed(key)) {1096if (debug != null) {1097debug.println(exmech.getName() + " isn't enforced");1098}1099return false;1100}1101} catch (ExemptionMechanismException eme) {1102if (debug != null) {1103debug.println("Cannot determine whether "+1104exmech.getName() + " has been enforced");1105eme.printStackTrace();1106}1107return false;1108}1109return true;1110}11111112// check if opmode is one of the defined constants1113// throw InvalidParameterExeption if not1114private static void checkOpmode(int opmode) {1115if ((opmode < ENCRYPT_MODE) || (opmode > UNWRAP_MODE)) {1116throw new InvalidParameterException("Invalid operation mode");1117}1118}11191120private static String getOpmodeString(int opmode) {1121switch (opmode) {1122case ENCRYPT_MODE:1123return "encryption";1124case DECRYPT_MODE:1125return "decryption";1126case WRAP_MODE:1127return "key wrapping";1128case UNWRAP_MODE:1129return "key unwrapping";1130default:1131return "";1132}1133}11341135/**1136* Initializes this cipher with a key.1137*1138* <p>The cipher is initialized for one of the following four operations:1139* encryption, decryption, key wrapping or key unwrapping, depending1140* on the value of {@code opmode}.1141*1142* <p>If this cipher requires any algorithm parameters that cannot be1143* derived from the given {@code key}, the underlying cipher1144* implementation is supposed to generate the required parameters itself1145* (using provider-specific default or random values) if it is being1146* initialized for encryption or key wrapping, and raise an1147* {@code InvalidKeyException} if it is being1148* initialized for decryption or key unwrapping.1149* The generated parameters can be retrieved using1150* {@link #getParameters() getParameters} or1151* {@link #getIV() getIV} (if the parameter is an IV).1152*1153* <p>If this cipher requires algorithm parameters that cannot be1154* derived from the input parameters, and there are no reasonable1155* provider-specific default values, initialization will1156* necessarily fail.1157*1158* <p>If this cipher (including its underlying feedback or padding scheme)1159* requires any random bytes (e.g., for parameter generation), it will get1160* them using the {@link java.security.SecureRandom}1161* implementation of the highest-priority1162* installed provider as the source of randomness.1163* (If none of the installed providers supply an implementation of1164* SecureRandom, a system-provided source of randomness will be used.)1165*1166* <p>Note that when a Cipher object is initialized, it loses all1167* previously-acquired state. In other words, initializing a Cipher is1168* equivalent to creating a new instance of that Cipher and initializing1169* it.1170*1171* @param opmode the operation mode of this cipher (this is one of1172* the following:1173* {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},1174* {@code WRAP_MODE} or {@code UNWRAP_MODE})1175* @param key the key1176*1177* @exception InvalidKeyException if the given key is inappropriate for1178* initializing this cipher, or requires1179* algorithm parameters that cannot be1180* determined from the given key, or if the given key has a keysize that1181* exceeds the maximum allowable keysize (as determined from the1182* configured jurisdiction policy files).1183* @throws UnsupportedOperationException if (@code opmode} is1184* {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented1185* by the underlying {@code CipherSpi}.1186*/1187public final void init(int opmode, Key key) throws InvalidKeyException {1188init(opmode, key, JceSecurity.RANDOM);1189}11901191/**1192* Initializes this cipher with a key and a source of randomness.1193*1194* <p>The cipher is initialized for one of the following four operations:1195* encryption, decryption, key wrapping or key unwrapping, depending1196* on the value of {@code opmode}.1197*1198* <p>If this cipher requires any algorithm parameters that cannot be1199* derived from the given {@code key}, the underlying cipher1200* implementation is supposed to generate the required parameters itself1201* (using provider-specific default or random values) if it is being1202* initialized for encryption or key wrapping, and raise an1203* {@code InvalidKeyException} if it is being1204* initialized for decryption or key unwrapping.1205* The generated parameters can be retrieved using1206* {@link #getParameters() getParameters} or1207* {@link #getIV() getIV} (if the parameter is an IV).1208*1209* <p>If this cipher requires algorithm parameters that cannot be1210* derived from the input parameters, and there are no reasonable1211* provider-specific default values, initialization will1212* necessarily fail.1213*1214* <p>If this cipher (including its underlying feedback or padding scheme)1215* requires any random bytes (e.g., for parameter generation), it will get1216* them from {@code random}.1217*1218* <p>Note that when a Cipher object is initialized, it loses all1219* previously-acquired state. In other words, initializing a Cipher is1220* equivalent to creating a new instance of that Cipher and initializing1221* it.1222*1223* @param opmode the operation mode of this cipher (this is one of the1224* following:1225* {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},1226* {@code WRAP_MODE} or {@code UNWRAP_MODE})1227* @param key the encryption key1228* @param random the source of randomness1229*1230* @exception InvalidKeyException if the given key is inappropriate for1231* initializing this cipher, or requires1232* algorithm parameters that cannot be1233* determined from the given key, or if the given key has a keysize that1234* exceeds the maximum allowable keysize (as determined from the1235* configured jurisdiction policy files).1236* @throws UnsupportedOperationException if (@code opmode} is1237* {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented1238* by the underlying {@code CipherSpi}.1239*/1240public final void init(int opmode, Key key, SecureRandom random)1241throws InvalidKeyException1242{1243initialized = false;1244checkOpmode(opmode);12451246if (spi != null) {1247checkCryptoPerm(spi, key);1248spi.engineInit(opmode, key, random);1249} else {1250try {1251chooseProvider(I_KEY, opmode, key, null, null, random);1252} catch (InvalidAlgorithmParameterException e) {1253// should never occur1254throw new InvalidKeyException(e);1255}1256}12571258initialized = true;1259this.opmode = opmode;12601261if (!skipDebug && pdebug != null) {1262pdebug.println("Cipher." + transformation + " " +1263getOpmodeString(opmode) + " algorithm from: " +1264this.provider.getName());1265}1266}12671268/**1269* Initializes this cipher with a key and a set of algorithm1270* parameters.1271*1272* <p>The cipher is initialized for one of the following four operations:1273* encryption, decryption, key wrapping or key unwrapping, depending1274* on the value of {@code opmode}.1275*1276* <p>If this cipher requires any algorithm parameters and1277* {@code params} is null, the underlying cipher implementation is1278* supposed to generate the required parameters itself (using1279* provider-specific default or random values) if it is being1280* initialized for encryption or key wrapping, and raise an1281* {@code InvalidAlgorithmParameterException} if it is being1282* initialized for decryption or key unwrapping.1283* The generated parameters can be retrieved using1284* {@link #getParameters() getParameters} or1285* {@link #getIV() getIV} (if the parameter is an IV).1286*1287* <p>If this cipher requires algorithm parameters that cannot be1288* derived from the input parameters, and there are no reasonable1289* provider-specific default values, initialization will1290* necessarily fail.1291*1292* <p>If this cipher (including its underlying feedback or padding scheme)1293* requires any random bytes (e.g., for parameter generation), it will get1294* them using the {@link java.security.SecureRandom}1295* implementation of the highest-priority1296* installed provider as the source of randomness.1297* (If none of the installed providers supply an implementation of1298* SecureRandom, a system-provided source of randomness will be used.)1299*1300* <p>Note that when a Cipher object is initialized, it loses all1301* previously-acquired state. In other words, initializing a Cipher is1302* equivalent to creating a new instance of that Cipher and initializing1303* it.1304*1305* @param opmode the operation mode of this cipher (this is one of the1306* following:1307* {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},1308* {@code WRAP_MODE} or {@code UNWRAP_MODE})1309* @param key the encryption key1310* @param params the algorithm parameters1311*1312* @exception InvalidKeyException if the given key is inappropriate for1313* initializing this cipher, or its keysize exceeds the maximum allowable1314* keysize (as determined from the configured jurisdiction policy files).1315* @exception InvalidAlgorithmParameterException if the given algorithm1316* parameters are inappropriate for this cipher,1317* or this cipher requires1318* algorithm parameters and {@code params} is null, or the given1319* algorithm parameters imply a cryptographic strength that would exceed1320* the legal limits (as determined from the configured jurisdiction1321* policy files).1322* @throws UnsupportedOperationException if (@code opmode} is1323* {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented1324* by the underlying {@code CipherSpi}.1325*/1326public final void init(int opmode, Key key, AlgorithmParameterSpec params)1327throws InvalidKeyException, InvalidAlgorithmParameterException1328{1329init(opmode, key, params, JceSecurity.RANDOM);1330}13311332/**1333* Initializes this cipher with a key, a set of algorithm1334* parameters, and a source of randomness.1335*1336* <p>The cipher is initialized for one of the following four operations:1337* encryption, decryption, key wrapping or key unwrapping, depending1338* on the value of {@code opmode}.1339*1340* <p>If this cipher requires any algorithm parameters and1341* {@code params} is null, the underlying cipher implementation is1342* supposed to generate the required parameters itself (using1343* provider-specific default or random values) if it is being1344* initialized for encryption or key wrapping, and raise an1345* {@code InvalidAlgorithmParameterException} if it is being1346* initialized for decryption or key unwrapping.1347* The generated parameters can be retrieved using1348* {@link #getParameters() getParameters} or1349* {@link #getIV() getIV} (if the parameter is an IV).1350*1351* <p>If this cipher requires algorithm parameters that cannot be1352* derived from the input parameters, and there are no reasonable1353* provider-specific default values, initialization will1354* necessarily fail.1355*1356* <p>If this cipher (including its underlying feedback or padding scheme)1357* requires any random bytes (e.g., for parameter generation), it will get1358* them from {@code random}.1359*1360* <p>Note that when a Cipher object is initialized, it loses all1361* previously-acquired state. In other words, initializing a Cipher is1362* equivalent to creating a new instance of that Cipher and initializing1363* it.1364*1365* @param opmode the operation mode of this cipher (this is one of the1366* following:1367* {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},1368* {@code WRAP_MODE} or {@code UNWRAP_MODE})1369* @param key the encryption key1370* @param params the algorithm parameters1371* @param random the source of randomness1372*1373* @exception InvalidKeyException if the given key is inappropriate for1374* initializing this cipher, or its keysize exceeds the maximum allowable1375* keysize (as determined from the configured jurisdiction policy files).1376* @exception InvalidAlgorithmParameterException if the given algorithm1377* parameters are inappropriate for this cipher,1378* or this cipher requires1379* algorithm parameters and {@code params} is null, or the given1380* algorithm parameters imply a cryptographic strength that would exceed1381* the legal limits (as determined from the configured jurisdiction1382* policy files).1383* @throws UnsupportedOperationException if (@code opmode} is1384* {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented1385* by the underlying {@code CipherSpi}.1386*/1387public final void init(int opmode, Key key, AlgorithmParameterSpec params,1388SecureRandom random)1389throws InvalidKeyException, InvalidAlgorithmParameterException1390{1391initialized = false;1392checkOpmode(opmode);13931394if (spi != null) {1395checkCryptoPerm(spi, key, params);1396spi.engineInit(opmode, key, params, random);1397} else {1398chooseProvider(I_PARAMSPEC, opmode, key, params, null, random);1399}14001401initialized = true;1402this.opmode = opmode;14031404if (!skipDebug && pdebug != null) {1405pdebug.println("Cipher." + transformation + " " +1406getOpmodeString(opmode) + " algorithm from: " +1407this.provider.getName());1408}1409}14101411/**1412* Initializes this cipher with a key and a set of algorithm1413* parameters.1414*1415* <p>The cipher is initialized for one of the following four operations:1416* encryption, decryption, key wrapping or key unwrapping, depending1417* on the value of {@code opmode}.1418*1419* <p>If this cipher requires any algorithm parameters and1420* {@code params} is null, the underlying cipher implementation is1421* supposed to generate the required parameters itself (using1422* provider-specific default or random values) if it is being1423* initialized for encryption or key wrapping, and raise an1424* {@code InvalidAlgorithmParameterException} if it is being1425* initialized for decryption or key unwrapping.1426* The generated parameters can be retrieved using1427* {@link #getParameters() getParameters} or1428* {@link #getIV() getIV} (if the parameter is an IV).1429*1430* <p>If this cipher requires algorithm parameters that cannot be1431* derived from the input parameters, and there are no reasonable1432* provider-specific default values, initialization will1433* necessarily fail.1434*1435* <p>If this cipher (including its underlying feedback or padding scheme)1436* requires any random bytes (e.g., for parameter generation), it will get1437* them using the {@link java.security.SecureRandom}1438* implementation of the highest-priority1439* installed provider as the source of randomness.1440* (If none of the installed providers supply an implementation of1441* SecureRandom, a system-provided source of randomness will be used.)1442*1443* <p>Note that when a Cipher object is initialized, it loses all1444* previously-acquired state. In other words, initializing a Cipher is1445* equivalent to creating a new instance of that Cipher and initializing1446* it.1447*1448* @param opmode the operation mode of this cipher (this is one of the1449* following: {@code ENCRYPT_MODE},1450* {@code DECRYPT_MODE}, {@code WRAP_MODE}1451* or {@code UNWRAP_MODE})1452* @param key the encryption key1453* @param params the algorithm parameters1454*1455* @exception InvalidKeyException if the given key is inappropriate for1456* initializing this cipher, or its keysize exceeds the maximum allowable1457* keysize (as determined from the configured jurisdiction policy files).1458* @exception InvalidAlgorithmParameterException if the given algorithm1459* parameters are inappropriate for this cipher,1460* or this cipher requires1461* algorithm parameters and {@code params} is null, or the given1462* algorithm parameters imply a cryptographic strength that would exceed1463* the legal limits (as determined from the configured jurisdiction1464* policy files).1465* @throws UnsupportedOperationException if (@code opmode} is1466* {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented1467* by the underlying {@code CipherSpi}.1468*/1469public final void init(int opmode, Key key, AlgorithmParameters params)1470throws InvalidKeyException, InvalidAlgorithmParameterException1471{1472init(opmode, key, params, JceSecurity.RANDOM);1473}14741475/**1476* Initializes this cipher with a key, a set of algorithm1477* parameters, and a source of randomness.1478*1479* <p>The cipher is initialized for one of the following four operations:1480* encryption, decryption, key wrapping or key unwrapping, depending1481* on the value of {@code opmode}.1482*1483* <p>If this cipher requires any algorithm parameters and1484* {@code params} is null, the underlying cipher implementation is1485* supposed to generate the required parameters itself (using1486* provider-specific default or random values) if it is being1487* initialized for encryption or key wrapping, and raise an1488* {@code InvalidAlgorithmParameterException} if it is being1489* initialized for decryption or key unwrapping.1490* The generated parameters can be retrieved using1491* {@link #getParameters() getParameters} or1492* {@link #getIV() getIV} (if the parameter is an IV).1493*1494* <p>If this cipher requires algorithm parameters that cannot be1495* derived from the input parameters, and there are no reasonable1496* provider-specific default values, initialization will1497* necessarily fail.1498*1499* <p>If this cipher (including its underlying feedback or padding scheme)1500* requires any random bytes (e.g., for parameter generation), it will get1501* them from {@code random}.1502*1503* <p>Note that when a Cipher object is initialized, it loses all1504* previously-acquired state. In other words, initializing a Cipher is1505* equivalent to creating a new instance of that Cipher and initializing1506* it.1507*1508* @param opmode the operation mode of this cipher (this is one of the1509* following: {@code ENCRYPT_MODE},1510* {@code DECRYPT_MODE}, {@code WRAP_MODE}1511* or {@code UNWRAP_MODE})1512* @param key the encryption key1513* @param params the algorithm parameters1514* @param random the source of randomness1515*1516* @exception InvalidKeyException if the given key is inappropriate for1517* initializing this cipher, or its keysize exceeds the maximum allowable1518* keysize (as determined from the configured jurisdiction policy files).1519* @exception InvalidAlgorithmParameterException if the given algorithm1520* parameters are inappropriate for this cipher,1521* or this cipher requires1522* algorithm parameters and {@code params} is null, or the given1523* algorithm parameters imply a cryptographic strength that would exceed1524* the legal limits (as determined from the configured jurisdiction1525* policy files).1526* @throws UnsupportedOperationException if (@code opmode} is1527* {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented1528* by the underlying {@code CipherSpi}.1529*/1530public final void init(int opmode, Key key, AlgorithmParameters params,1531SecureRandom random)1532throws InvalidKeyException, InvalidAlgorithmParameterException1533{1534initialized = false;1535checkOpmode(opmode);15361537if (spi != null) {1538checkCryptoPerm(spi, key, params);1539spi.engineInit(opmode, key, params, random);1540} else {1541chooseProvider(I_PARAMS, opmode, key, null, params, random);1542}15431544initialized = true;1545this.opmode = opmode;15461547if (!skipDebug && pdebug != null) {1548pdebug.println("Cipher." + transformation + " " +1549getOpmodeString(opmode) + " algorithm from: " +1550this.provider.getName());1551}1552}15531554/**1555* Initializes this cipher with the public key from the given certificate.1556* <p> The cipher is initialized for one of the following four operations:1557* encryption, decryption, key wrapping or key unwrapping, depending1558* on the value of {@code opmode}.1559*1560* <p>If the certificate is of type X.509 and has a <i>key usage</i>1561* extension field marked as critical, and the value of the <i>key usage</i>1562* extension field implies that the public key in1563* the certificate and its corresponding private key are not1564* supposed to be used for the operation represented by the value1565* of {@code opmode},1566* an {@code InvalidKeyException}1567* is thrown.1568*1569* <p> If this cipher requires any algorithm parameters that cannot be1570* derived from the public key in the given certificate, the underlying1571* cipher1572* implementation is supposed to generate the required parameters itself1573* (using provider-specific default or random values) if it is being1574* initialized for encryption or key wrapping, and raise an {@code1575* InvalidKeyException} if it is being initialized for decryption or1576* key unwrapping.1577* The generated parameters can be retrieved using1578* {@link #getParameters() getParameters} or1579* {@link #getIV() getIV} (if the parameter is an IV).1580*1581* <p>If this cipher requires algorithm parameters that cannot be1582* derived from the input parameters, and there are no reasonable1583* provider-specific default values, initialization will1584* necessarily fail.1585*1586* <p>If this cipher (including its underlying feedback or padding scheme)1587* requires any random bytes (e.g., for parameter generation), it will get1588* them using the1589* {@code SecureRandom}1590* implementation of the highest-priority1591* installed provider as the source of randomness.1592* (If none of the installed providers supply an implementation of1593* SecureRandom, a system-provided source of randomness will be used.)1594*1595* <p>Note that when a Cipher object is initialized, it loses all1596* previously-acquired state. In other words, initializing a Cipher is1597* equivalent to creating a new instance of that Cipher and initializing1598* it.1599*1600* @param opmode the operation mode of this cipher (this is one of the1601* following:1602* {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},1603* {@code WRAP_MODE} or {@code UNWRAP_MODE})1604* @param certificate the certificate1605*1606* @exception InvalidKeyException if the public key in the given1607* certificate is inappropriate for initializing this cipher, or this1608* cipher requires algorithm parameters that cannot be determined from the1609* public key in the given certificate, or the keysize of the public key1610* in the given certificate has a keysize that exceeds the maximum1611* allowable keysize (as determined by the configured jurisdiction policy1612* files).1613* @throws UnsupportedOperationException if (@code opmode} is1614* {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented1615* by the underlying {@code CipherSpi}.1616*/1617public final void init(int opmode, Certificate certificate)1618throws InvalidKeyException1619{1620init(opmode, certificate, JceSecurity.RANDOM);1621}16221623/**1624* Initializes this cipher with the public key from the given certificate1625* and1626* a source of randomness.1627*1628* <p>The cipher is initialized for one of the following four operations:1629* encryption, decryption, key wrapping1630* or key unwrapping, depending on1631* the value of {@code opmode}.1632*1633* <p>If the certificate is of type X.509 and has a <i>key usage</i>1634* extension field marked as critical, and the value of the <i>key usage</i>1635* extension field implies that the public key in1636* the certificate and its corresponding private key are not1637* supposed to be used for the operation represented by the value of1638* {@code opmode},1639* an {@code InvalidKeyException}1640* is thrown.1641*1642* <p>If this cipher requires any algorithm parameters that cannot be1643* derived from the public key in the given {@code certificate},1644* the underlying cipher1645* implementation is supposed to generate the required parameters itself1646* (using provider-specific default or random values) if it is being1647* initialized for encryption or key wrapping, and raise an1648* {@code InvalidKeyException} if it is being1649* initialized for decryption or key unwrapping.1650* The generated parameters can be retrieved using1651* {@link #getParameters() getParameters} or1652* {@link #getIV() getIV} (if the parameter is an IV).1653*1654* <p>If this cipher requires algorithm parameters that cannot be1655* derived from the input parameters, and there are no reasonable1656* provider-specific default values, initialization will1657* necessarily fail.1658*1659* <p>If this cipher (including its underlying feedback or padding scheme)1660* requires any random bytes (e.g., for parameter generation), it will get1661* them from {@code random}.1662*1663* <p>Note that when a Cipher object is initialized, it loses all1664* previously-acquired state. In other words, initializing a Cipher is1665* equivalent to creating a new instance of that Cipher and initializing1666* it.1667*1668* @param opmode the operation mode of this cipher (this is one of the1669* following:1670* {@code ENCRYPT_MODE}, {@code DECRYPT_MODE},1671* {@code WRAP_MODE} or {@code UNWRAP_MODE})1672* @param certificate the certificate1673* @param random the source of randomness1674*1675* @exception InvalidKeyException if the public key in the given1676* certificate is inappropriate for initializing this cipher, or this1677* cipher1678* requires algorithm parameters that cannot be determined from the1679* public key in the given certificate, or the keysize of the public key1680* in the given certificate has a keysize that exceeds the maximum1681* allowable keysize (as determined by the configured jurisdiction policy1682* files).1683* @throws UnsupportedOperationException if (@code opmode} is1684* {@code WRAP_MODE} or {@code UNWRAP_MODE} but the mode is not implemented1685* by the underlying {@code CipherSpi}.1686*/1687public final void init(int opmode, Certificate certificate,1688SecureRandom random)1689throws InvalidKeyException1690{1691initialized = false;1692checkOpmode(opmode);16931694// Check key usage if the certificate is of1695// type X.509.1696if (certificate instanceof java.security.cert.X509Certificate) {1697// Check whether the cert has a key usage extension1698// marked as a critical extension.1699X509Certificate cert = (X509Certificate)certificate;1700Set<String> critSet = cert.getCriticalExtensionOIDs();17011702if (critSet != null && !critSet.isEmpty()1703&& critSet.contains(KEY_USAGE_EXTENSION_OID)) {1704boolean[] keyUsageInfo = cert.getKeyUsage();1705// keyUsageInfo[2] is for keyEncipherment;1706// keyUsageInfo[3] is for dataEncipherment.1707if ((keyUsageInfo != null) &&1708(((opmode == Cipher.ENCRYPT_MODE) &&1709(keyUsageInfo.length > 3) &&1710(keyUsageInfo[3] == false)) ||1711((opmode == Cipher.WRAP_MODE) &&1712(keyUsageInfo.length > 2) &&1713(keyUsageInfo[2] == false)))) {1714throw new InvalidKeyException("Wrong key usage");1715}1716}1717}17181719PublicKey publicKey =1720(certificate==null? null:certificate.getPublicKey());17211722if (spi != null) {1723checkCryptoPerm(spi, publicKey);1724spi.engineInit(opmode, publicKey, random);1725} else {1726try {1727chooseProvider(I_CERT, opmode, publicKey, null, null, random);1728} catch (InvalidAlgorithmParameterException e) {1729// should never occur1730throw new InvalidKeyException(e);1731}1732}17331734initialized = true;1735this.opmode = opmode;17361737if (!skipDebug && pdebug != null) {1738pdebug.println("Cipher." + transformation + " " +1739getOpmodeString(opmode) + " algorithm from: " +1740this.provider.getName());1741}1742}17431744/**1745* Ensures that Cipher is in a valid state for update() and doFinal()1746* calls - should be initialized and in ENCRYPT_MODE or DECRYPT_MODE.1747* @throws IllegalStateException if Cipher object is not in valid state.1748*/1749private void checkCipherState() {1750if (!(this instanceof NullCipher)) {1751if (!initialized) {1752throw new IllegalStateException("Cipher not initialized");1753}1754if ((opmode != Cipher.ENCRYPT_MODE) &&1755(opmode != Cipher.DECRYPT_MODE)) {1756throw new IllegalStateException("Cipher not initialized " +1757"for encryption/decryption");1758}1759}1760}17611762/**1763* Continues a multiple-part encryption or decryption operation1764* (depending on how this cipher was initialized), processing another data1765* part.1766*1767* <p>The bytes in the {@code input} buffer are processed, and the1768* result is stored in a new buffer.1769*1770* <p>If {@code input} has a length of zero, this method returns1771* {@code null}.1772*1773* @param input the input buffer1774*1775* @return the new buffer with the result, or null if the underlying1776* cipher is a block cipher and the input data is too short to result in a1777* new block.1778*1779* @exception IllegalStateException if this cipher is in a wrong state1780* (e.g., has not been initialized)1781*/1782public final byte[] update(byte[] input) {1783checkCipherState();17841785// Input sanity check1786if (input == null) {1787throw new IllegalArgumentException("Null input buffer");1788}17891790chooseFirstProvider();1791if (input.length == 0) {1792return null;1793}1794return spi.engineUpdate(input, 0, input.length);1795}17961797/**1798* Continues a multiple-part encryption or decryption operation1799* (depending on how this cipher was initialized), processing another data1800* part.1801*1802* <p>The first {@code inputLen} bytes in the {@code input}1803* buffer, starting at {@code inputOffset} inclusive, are processed,1804* and the result is stored in a new buffer.1805*1806* <p>If {@code inputLen} is zero, this method returns1807* {@code null}.1808*1809* @param input the input buffer1810* @param inputOffset the offset in {@code input} where the input1811* starts1812* @param inputLen the input length1813*1814* @return the new buffer with the result, or null if the underlying1815* cipher is a block cipher and the input data is too short to result in a1816* new block.1817*1818* @exception IllegalStateException if this cipher is in a wrong state1819* (e.g., has not been initialized)1820*/1821public final byte[] update(byte[] input, int inputOffset, int inputLen) {1822checkCipherState();18231824// Input sanity check1825if (input == null || inputOffset < 01826|| inputLen > (input.length - inputOffset) || inputLen < 0) {1827throw new IllegalArgumentException("Bad arguments");1828}18291830chooseFirstProvider();1831if (inputLen == 0) {1832return null;1833}1834return spi.engineUpdate(input, inputOffset, inputLen);1835}18361837/**1838* Continues a multiple-part encryption or decryption operation1839* (depending on how this cipher was initialized), processing another data1840* part.1841*1842* <p>The first {@code inputLen} bytes in the {@code input}1843* buffer, starting at {@code inputOffset} inclusive, are processed,1844* and the result is stored in the {@code output} buffer.1845*1846* <p>If the {@code output} buffer is too small to hold the result,1847* a {@code ShortBufferException} is thrown. In this case, repeat this1848* call with a larger output buffer. Use1849* {@link #getOutputSize(int) getOutputSize} to determine how big1850* the output buffer should be.1851*1852* <p>If {@code inputLen} is zero, this method returns1853* a length of zero.1854*1855* <p>Note: this method should be copy-safe, which means the1856* {@code input} and {@code output} buffers can reference1857* the same byte array and no unprocessed input data is overwritten1858* when the result is copied into the output buffer.1859*1860* @param input the input buffer1861* @param inputOffset the offset in {@code input} where the input1862* starts1863* @param inputLen the input length1864* @param output the buffer for the result1865*1866* @return the number of bytes stored in {@code output}1867*1868* @exception IllegalStateException if this cipher is in a wrong state1869* (e.g., has not been initialized)1870* @exception ShortBufferException if the given output buffer is too small1871* to hold the result1872*/1873public final int update(byte[] input, int inputOffset, int inputLen,1874byte[] output)1875throws ShortBufferException {1876checkCipherState();18771878// Input sanity check1879if (input == null || inputOffset < 01880|| inputLen > (input.length - inputOffset) || inputLen < 0) {1881throw new IllegalArgumentException("Bad arguments");1882}18831884chooseFirstProvider();1885if (inputLen == 0) {1886return 0;1887}1888return spi.engineUpdate(input, inputOffset, inputLen,1889output, 0);1890}18911892/**1893* Continues a multiple-part encryption or decryption operation1894* (depending on how this cipher was initialized), processing another data1895* part.1896*1897* <p>The first {@code inputLen} bytes in the {@code input}1898* buffer, starting at {@code inputOffset} inclusive, are processed,1899* and the result is stored in the {@code output} buffer, starting at1900* {@code outputOffset} inclusive.1901*1902* <p>If the {@code output} buffer is too small to hold the result,1903* a {@code ShortBufferException} is thrown. In this case, repeat this1904* call with a larger output buffer. Use1905* {@link #getOutputSize(int) getOutputSize} to determine how big1906* the output buffer should be.1907*1908* <p>If {@code inputLen} is zero, this method returns1909* a length of zero.1910*1911* <p>Note: this method should be copy-safe, which means the1912* {@code input} and {@code output} buffers can reference1913* the same byte array and no unprocessed input data is overwritten1914* when the result is copied into the output buffer.1915*1916* @param input the input buffer1917* @param inputOffset the offset in {@code input} where the input1918* starts1919* @param inputLen the input length1920* @param output the buffer for the result1921* @param outputOffset the offset in {@code output} where the result1922* is stored1923*1924* @return the number of bytes stored in {@code output}1925*1926* @exception IllegalStateException if this cipher is in a wrong state1927* (e.g., has not been initialized)1928* @exception ShortBufferException if the given output buffer is too small1929* to hold the result1930*/1931public final int update(byte[] input, int inputOffset, int inputLen,1932byte[] output, int outputOffset)1933throws ShortBufferException {1934checkCipherState();19351936// Input sanity check1937if (input == null || inputOffset < 01938|| inputLen > (input.length - inputOffset) || inputLen < 01939|| outputOffset < 0) {1940throw new IllegalArgumentException("Bad arguments");1941}19421943chooseFirstProvider();1944if (inputLen == 0) {1945return 0;1946}1947return spi.engineUpdate(input, inputOffset, inputLen,1948output, outputOffset);1949}19501951/**1952* Continues a multiple-part encryption or decryption operation1953* (depending on how this cipher was initialized), processing another data1954* part.1955*1956* <p>All {@code input.remaining()} bytes starting at1957* {@code input.position()} are processed. The result is stored1958* in the output buffer.1959* Upon return, the input buffer's position will be equal1960* to its limit; its limit will not have changed. The output buffer's1961* position will have advanced by n, where n is the value returned1962* by this method; the output buffer's limit will not have changed.1963*1964* <p>If {@code output.remaining()} bytes are insufficient to1965* hold the result, a {@code ShortBufferException} is thrown.1966* In this case, repeat this call with a larger output buffer. Use1967* {@link #getOutputSize(int) getOutputSize} to determine how big1968* the output buffer should be.1969*1970* <p>Note: this method should be copy-safe, which means the1971* {@code input} and {@code output} buffers can reference1972* the same block of memory and no unprocessed input data is overwritten1973* when the result is copied into the output buffer.1974*1975* @param input the input ByteBuffer1976* @param output the output ByteByffer1977*1978* @return the number of bytes stored in {@code output}1979*1980* @exception IllegalStateException if this cipher is in a wrong state1981* (e.g., has not been initialized)1982* @exception IllegalArgumentException if input and output are the1983* same object1984* @exception ReadOnlyBufferException if the output buffer is read-only1985* @exception ShortBufferException if there is insufficient space in the1986* output buffer1987* @since 1.51988*/1989public final int update(ByteBuffer input, ByteBuffer output)1990throws ShortBufferException {1991checkCipherState();19921993if ((input == null) || (output == null)) {1994throw new IllegalArgumentException("Buffers must not be null");1995}1996if (input == output) {1997throw new IllegalArgumentException("Input and output buffers must "1998+ "not be the same object, consider using buffer.duplicate()");1999}2000if (output.isReadOnly()) {2001throw new ReadOnlyBufferException();2002}20032004chooseFirstProvider();2005return spi.engineUpdate(input, output);2006}20072008/**2009* Finishes a multiple-part encryption or decryption operation, depending2010* on how this cipher was initialized.2011*2012* <p>Input data that may have been buffered during a previous2013* {@code update} operation is processed, with padding (if requested)2014* being applied.2015* If an AEAD mode such as GCM/CCM is being used, the authentication2016* tag is appended in the case of encryption, or verified in the2017* case of decryption.2018* The result is stored in a new buffer.2019*2020* <p>Upon finishing, this method resets this cipher object to the state2021* it was in when previously initialized via a call to {@code init}.2022* That is, the object is reset and available to encrypt or decrypt2023* (depending on the operation mode that was specified in the call to2024* {@code init}) more data.2025*2026* <p>Note: if any exception is thrown, this cipher object may need to2027* be reset before it can be used again.2028*2029* @return the new buffer with the result2030*2031* @exception IllegalStateException if this cipher is in a wrong state2032* (e.g., has not been initialized)2033* @exception IllegalBlockSizeException if this cipher is a block cipher,2034* no padding has been requested (only in encryption mode), and the total2035* input length of the data processed by this cipher is not a multiple of2036* block size; or if this encryption algorithm is unable to2037* process the input data provided.2038* @exception BadPaddingException if this cipher is in decryption mode,2039* and (un)padding has been requested, but the decrypted data is not2040* bounded by the appropriate padding bytes2041* @exception AEADBadTagException if this cipher is decrypting in an2042* AEAD mode (such as GCM/CCM), and the received authentication tag2043* does not match the calculated value2044*/2045public final byte[] doFinal()2046throws IllegalBlockSizeException, BadPaddingException {2047checkCipherState();20482049chooseFirstProvider();2050return spi.engineDoFinal(null, 0, 0);2051}20522053/**2054* Finishes a multiple-part encryption or decryption operation, depending2055* on how this cipher was initialized.2056*2057* <p>Input data that may have been buffered during a previous2058* {@code update} operation is processed, with padding (if requested)2059* being applied.2060* If an AEAD mode such as GCM/CCM is being used, the authentication2061* tag is appended in the case of encryption, or verified in the2062* case of decryption.2063* The result is stored in the {@code output} buffer, starting at2064* {@code outputOffset} inclusive.2065*2066* <p>If the {@code output} buffer is too small to hold the result,2067* a {@code ShortBufferException} is thrown. In this case, repeat this2068* call with a larger output buffer. Use2069* {@link #getOutputSize(int) getOutputSize} to determine how big2070* the output buffer should be.2071*2072* <p>Upon finishing, this method resets this cipher object to the state2073* it was in when previously initialized via a call to {@code init}.2074* That is, the object is reset and available to encrypt or decrypt2075* (depending on the operation mode that was specified in the call to2076* {@code init}) more data.2077*2078* <p>Note: if any exception is thrown, this cipher object may need to2079* be reset before it can be used again.2080*2081* @param output the buffer for the result2082* @param outputOffset the offset in {@code output} where the result2083* is stored2084*2085* @return the number of bytes stored in {@code output}2086*2087* @exception IllegalStateException if this cipher is in a wrong state2088* (e.g., has not been initialized)2089* @exception IllegalBlockSizeException if this cipher is a block cipher,2090* no padding has been requested (only in encryption mode), and the total2091* input length of the data processed by this cipher is not a multiple of2092* block size; or if this encryption algorithm is unable to2093* process the input data provided.2094* @exception ShortBufferException if the given output buffer is too small2095* to hold the result2096* @exception BadPaddingException if this cipher is in decryption mode,2097* and (un)padding has been requested, but the decrypted data is not2098* bounded by the appropriate padding bytes2099* @exception AEADBadTagException if this cipher is decrypting in an2100* AEAD mode (such as GCM/CCM), and the received authentication tag2101* does not match the calculated value2102*/2103public final int doFinal(byte[] output, int outputOffset)2104throws IllegalBlockSizeException, ShortBufferException,2105BadPaddingException {2106checkCipherState();21072108// Input sanity check2109if ((output == null) || (outputOffset < 0)) {2110throw new IllegalArgumentException("Bad arguments");2111}21122113chooseFirstProvider();2114return spi.engineDoFinal(null, 0, 0, output, outputOffset);2115}21162117/**2118* Encrypts or decrypts data in a single-part operation, or finishes a2119* multiple-part operation. The data is encrypted or decrypted,2120* depending on how this cipher was initialized.2121*2122* <p>The bytes in the {@code input} buffer, and any input bytes that2123* may have been buffered during a previous {@code update} operation,2124* are processed, with padding (if requested) being applied.2125* If an AEAD mode such as GCM/CCM is being used, the authentication2126* tag is appended in the case of encryption, or verified in the2127* case of decryption.2128* The result is stored in a new buffer.2129*2130* <p>Upon finishing, this method resets this cipher object to the state2131* it was in when previously initialized via a call to {@code init}.2132* That is, the object is reset and available to encrypt or decrypt2133* (depending on the operation mode that was specified in the call to2134* {@code init}) more data.2135*2136* <p>Note: if any exception is thrown, this cipher object may need to2137* be reset before it can be used again.2138*2139* @param input the input buffer2140*2141* @return the new buffer with the result2142*2143* @exception IllegalStateException if this cipher is in a wrong state2144* (e.g., has not been initialized)2145* @exception IllegalBlockSizeException if this cipher is a block cipher,2146* no padding has been requested (only in encryption mode), and the total2147* input length of the data processed by this cipher is not a multiple of2148* block size; or if this encryption algorithm is unable to2149* process the input data provided.2150* @exception BadPaddingException if this cipher is in decryption mode,2151* and (un)padding has been requested, but the decrypted data is not2152* bounded by the appropriate padding bytes2153* @exception AEADBadTagException if this cipher is decrypting in an2154* AEAD mode (such as GCM/CCM), and the received authentication tag2155* does not match the calculated value2156*/2157public final byte[] doFinal(byte[] input)2158throws IllegalBlockSizeException, BadPaddingException {2159checkCipherState();21602161// Input sanity check2162if (input == null) {2163throw new IllegalArgumentException("Null input buffer");2164}21652166chooseFirstProvider();2167return spi.engineDoFinal(input, 0, input.length);2168}21692170/**2171* Encrypts or decrypts data in a single-part operation, or finishes a2172* multiple-part operation. The data is encrypted or decrypted,2173* depending on how this cipher was initialized.2174*2175* <p>The first {@code inputLen} bytes in the {@code input}2176* buffer, starting at {@code inputOffset} inclusive, and any input2177* bytes that may have been buffered during a previous {@code update}2178* operation, are processed, with padding (if requested) being applied.2179* If an AEAD mode such as GCM/CCM is being used, the authentication2180* tag is appended in the case of encryption, or verified in the2181* case of decryption.2182* The result is stored in a new buffer.2183*2184* <p>Upon finishing, this method resets this cipher object to the state2185* it was in when previously initialized via a call to {@code init}.2186* That is, the object is reset and available to encrypt or decrypt2187* (depending on the operation mode that was specified in the call to2188* {@code init}) more data.2189*2190* <p>Note: if any exception is thrown, this cipher object may need to2191* be reset before it can be used again.2192*2193* @param input the input buffer2194* @param inputOffset the offset in {@code input} where the input2195* starts2196* @param inputLen the input length2197*2198* @return the new buffer with the result2199*2200* @exception IllegalStateException if this cipher is in a wrong state2201* (e.g., has not been initialized)2202* @exception IllegalBlockSizeException if this cipher is a block cipher,2203* no padding has been requested (only in encryption mode), and the total2204* input length of the data processed by this cipher is not a multiple of2205* block size; or if this encryption algorithm is unable to2206* process the input data provided.2207* @exception BadPaddingException if this cipher is in decryption mode,2208* and (un)padding has been requested, but the decrypted data is not2209* bounded by the appropriate padding bytes2210* @exception AEADBadTagException if this cipher is decrypting in an2211* AEAD mode (such as GCM/CCM), and the received authentication tag2212* does not match the calculated value2213*/2214public final byte[] doFinal(byte[] input, int inputOffset, int inputLen)2215throws IllegalBlockSizeException, BadPaddingException {2216checkCipherState();22172218// Input sanity check2219if (input == null || inputOffset < 02220|| inputLen > (input.length - inputOffset) || inputLen < 0) {2221throw new IllegalArgumentException("Bad arguments");2222}22232224chooseFirstProvider();2225return spi.engineDoFinal(input, inputOffset, inputLen);2226}22272228/**2229* Encrypts or decrypts data in a single-part operation, or finishes a2230* multiple-part operation. The data is encrypted or decrypted,2231* depending on how this cipher was initialized.2232*2233* <p>The first {@code inputLen} bytes in the {@code input}2234* buffer, starting at {@code inputOffset} inclusive, and any input2235* bytes that may have been buffered during a previous {@code update}2236* operation, are processed, with padding (if requested) being applied.2237* If an AEAD mode such as GCM/CCM is being used, the authentication2238* tag is appended in the case of encryption, or verified in the2239* case of decryption.2240* The result is stored in the {@code output} buffer.2241*2242* <p>If the {@code output} buffer is too small to hold the result,2243* a {@code ShortBufferException} is thrown. In this case, repeat this2244* call with a larger output buffer. Use2245* {@link #getOutputSize(int) getOutputSize} to determine how big2246* the output buffer should be.2247*2248* <p>Upon finishing, this method resets this cipher object to the state2249* it was in when previously initialized via a call to {@code init}.2250* That is, the object is reset and available to encrypt or decrypt2251* (depending on the operation mode that was specified in the call to2252* {@code init}) more data.2253*2254* <p>Note: if any exception is thrown, this cipher object may need to2255* be reset before it can be used again.2256*2257* <p>Note: this method should be copy-safe, which means the2258* {@code input} and {@code output} buffers can reference2259* the same byte array and no unprocessed input data is overwritten2260* when the result is copied into the output buffer.2261*2262* @param input the input buffer2263* @param inputOffset the offset in {@code input} where the input2264* starts2265* @param inputLen the input length2266* @param output the buffer for the result2267*2268* @return the number of bytes stored in {@code output}2269*2270* @exception IllegalStateException if this cipher is in a wrong state2271* (e.g., has not been initialized)2272* @exception IllegalBlockSizeException if this cipher is a block cipher,2273* no padding has been requested (only in encryption mode), and the total2274* input length of the data processed by this cipher is not a multiple of2275* block size; or if this encryption algorithm is unable to2276* process the input data provided.2277* @exception ShortBufferException if the given output buffer is too small2278* to hold the result2279* @exception BadPaddingException if this cipher is in decryption mode,2280* and (un)padding has been requested, but the decrypted data is not2281* bounded by the appropriate padding bytes2282* @exception AEADBadTagException if this cipher is decrypting in an2283* AEAD mode (such as GCM/CCM), and the received authentication tag2284* does not match the calculated value2285*/2286public final int doFinal(byte[] input, int inputOffset, int inputLen,2287byte[] output)2288throws ShortBufferException, IllegalBlockSizeException,2289BadPaddingException {2290checkCipherState();22912292// Input sanity check2293if (input == null || inputOffset < 02294|| inputLen > (input.length - inputOffset) || inputLen < 0) {2295throw new IllegalArgumentException("Bad arguments");2296}22972298chooseFirstProvider();2299return spi.engineDoFinal(input, inputOffset, inputLen,2300output, 0);2301}23022303/**2304* Encrypts or decrypts data in a single-part operation, or finishes a2305* multiple-part operation. The data is encrypted or decrypted,2306* depending on how this cipher was initialized.2307*2308* <p>The first {@code inputLen} bytes in the {@code input}2309* buffer, starting at {@code inputOffset} inclusive, and any input2310* bytes that may have been buffered during a previous2311* {@code update} operation, are processed, with padding2312* (if requested) being applied.2313* If an AEAD mode such as GCM/CCM is being used, the authentication2314* tag is appended in the case of encryption, or verified in the2315* case of decryption.2316* The result is stored in the {@code output} buffer, starting at2317* {@code outputOffset} inclusive.2318*2319* <p>If the {@code output} buffer is too small to hold the result,2320* a {@code ShortBufferException} is thrown. In this case, repeat this2321* call with a larger output buffer. Use2322* {@link #getOutputSize(int) getOutputSize} to determine how big2323* the output buffer should be.2324*2325* <p>Upon finishing, this method resets this cipher object to the state2326* it was in when previously initialized via a call to {@code init}.2327* That is, the object is reset and available to encrypt or decrypt2328* (depending on the operation mode that was specified in the call to2329* {@code init}) more data.2330*2331* <p>Note: if any exception is thrown, this cipher object may need to2332* be reset before it can be used again.2333*2334* <p>Note: this method should be copy-safe, which means the2335* {@code input} and {@code output} buffers can reference2336* the same byte array and no unprocessed input data is overwritten2337* when the result is copied into the output buffer.2338*2339* @param input the input buffer2340* @param inputOffset the offset in {@code input} where the input2341* starts2342* @param inputLen the input length2343* @param output the buffer for the result2344* @param outputOffset the offset in {@code output} where the result2345* is stored2346*2347* @return the number of bytes stored in {@code output}2348*2349* @exception IllegalStateException if this cipher is in a wrong state2350* (e.g., has not been initialized)2351* @exception IllegalBlockSizeException if this cipher is a block cipher,2352* no padding has been requested (only in encryption mode), and the total2353* input length of the data processed by this cipher is not a multiple of2354* block size; or if this encryption algorithm is unable to2355* process the input data provided.2356* @exception ShortBufferException if the given output buffer is too small2357* to hold the result2358* @exception BadPaddingException if this cipher is in decryption mode,2359* and (un)padding has been requested, but the decrypted data is not2360* bounded by the appropriate padding bytes2361* @exception AEADBadTagException if this cipher is decrypting in an2362* AEAD mode (such as GCM/CCM), and the received authentication tag2363* does not match the calculated value2364*/2365public final int doFinal(byte[] input, int inputOffset, int inputLen,2366byte[] output, int outputOffset)2367throws ShortBufferException, IllegalBlockSizeException,2368BadPaddingException {2369checkCipherState();23702371// Input sanity check2372if (input == null || inputOffset < 02373|| inputLen > (input.length - inputOffset) || inputLen < 02374|| outputOffset < 0) {2375throw new IllegalArgumentException("Bad arguments");2376}23772378chooseFirstProvider();2379return spi.engineDoFinal(input, inputOffset, inputLen,2380output, outputOffset);2381}23822383/**2384* Encrypts or decrypts data in a single-part operation, or finishes a2385* multiple-part operation. The data is encrypted or decrypted,2386* depending on how this cipher was initialized.2387*2388* <p>All {@code input.remaining()} bytes starting at2389* {@code input.position()} are processed.2390* If an AEAD mode such as GCM/CCM is being used, the authentication2391* tag is appended in the case of encryption, or verified in the2392* case of decryption.2393* The result is stored in the output buffer.2394* Upon return, the input buffer's position will be equal2395* to its limit; its limit will not have changed. The output buffer's2396* position will have advanced by n, where n is the value returned2397* by this method; the output buffer's limit will not have changed.2398*2399* <p>If {@code output.remaining()} bytes are insufficient to2400* hold the result, a {@code ShortBufferException} is thrown.2401* In this case, repeat this call with a larger output buffer. Use2402* {@link #getOutputSize(int) getOutputSize} to determine how big2403* the output buffer should be.2404*2405* <p>Upon finishing, this method resets this cipher object to the state2406* it was in when previously initialized via a call to {@code init}.2407* That is, the object is reset and available to encrypt or decrypt2408* (depending on the operation mode that was specified in the call to2409* {@code init}) more data.2410*2411* <p>Note: if any exception is thrown, this cipher object may need to2412* be reset before it can be used again.2413*2414* <p>Note: this method should be copy-safe, which means the2415* {@code input} and {@code output} buffers can reference2416* the same byte array and no unprocessed input data is overwritten2417* when the result is copied into the output buffer.2418*2419* @param input the input ByteBuffer2420* @param output the output ByteBuffer2421*2422* @return the number of bytes stored in {@code output}2423*2424* @exception IllegalStateException if this cipher is in a wrong state2425* (e.g., has not been initialized)2426* @exception IllegalArgumentException if input and output are the2427* same object2428* @exception ReadOnlyBufferException if the output buffer is read-only2429* @exception IllegalBlockSizeException if this cipher is a block cipher,2430* no padding has been requested (only in encryption mode), and the total2431* input length of the data processed by this cipher is not a multiple of2432* block size; or if this encryption algorithm is unable to2433* process the input data provided.2434* @exception ShortBufferException if there is insufficient space in the2435* output buffer2436* @exception BadPaddingException if this cipher is in decryption mode,2437* and (un)padding has been requested, but the decrypted data is not2438* bounded by the appropriate padding bytes2439* @exception AEADBadTagException if this cipher is decrypting in an2440* AEAD mode (such as GCM/CCM), and the received authentication tag2441* does not match the calculated value2442*2443* @since 1.52444*/2445public final int doFinal(ByteBuffer input, ByteBuffer output)2446throws ShortBufferException, IllegalBlockSizeException,2447BadPaddingException {2448checkCipherState();24492450if ((input == null) || (output == null)) {2451throw new IllegalArgumentException("Buffers must not be null");2452}2453if (input == output) {2454throw new IllegalArgumentException("Input and output buffers must "2455+ "not be the same object, consider using buffer.duplicate()");2456}2457if (output.isReadOnly()) {2458throw new ReadOnlyBufferException();2459}24602461chooseFirstProvider();2462return spi.engineDoFinal(input, output);2463}24642465/**2466* Wrap a key.2467*2468* @param key the key to be wrapped.2469*2470* @return the wrapped key.2471*2472* @exception IllegalStateException if this cipher is in a wrong2473* state (e.g., has not been initialized).2474*2475* @exception IllegalBlockSizeException if this cipher is a block2476* cipher, no padding has been requested, and the length of the2477* encoding of the key to be wrapped is not a2478* multiple of the block size.2479*2480* @exception InvalidKeyException if it is impossible or unsafe to2481* wrap the key with this cipher (e.g., a hardware protected key is2482* being passed to a software-only cipher).2483*2484* @throws UnsupportedOperationException if the corresponding method in the2485* {@code CipherSpi} is not supported.2486*/2487public final byte[] wrap(Key key)2488throws IllegalBlockSizeException, InvalidKeyException {2489if (!(this instanceof NullCipher)) {2490if (!initialized) {2491throw new IllegalStateException("Cipher not initialized");2492}2493if (opmode != Cipher.WRAP_MODE) {2494throw new IllegalStateException("Cipher not initialized " +2495"for wrapping keys");2496}2497}24982499chooseFirstProvider();2500return spi.engineWrap(key);2501}25022503/**2504* Unwrap a previously wrapped key.2505*2506* @param wrappedKey the key to be unwrapped.2507*2508* @param wrappedKeyAlgorithm the algorithm associated with the wrapped2509* key.2510*2511* @param wrappedKeyType the type of the wrapped key. This must be one of2512* {@code SECRET_KEY}, {@code PRIVATE_KEY}, or2513* {@code PUBLIC_KEY}.2514*2515* @return the unwrapped key.2516*2517* @exception IllegalStateException if this cipher is in a wrong state2518* (e.g., has not been initialized).2519*2520* @exception NoSuchAlgorithmException if no installed providers2521* can create keys of type {@code wrappedKeyType} for the2522* {@code wrappedKeyAlgorithm}.2523*2524* @exception InvalidKeyException if {@code wrappedKey} does not2525* represent a wrapped key of type {@code wrappedKeyType} for2526* the {@code wrappedKeyAlgorithm}.2527*2528* @throws UnsupportedOperationException if the corresponding method in the2529* {@code CipherSpi} is not supported.2530*/2531public final Key unwrap(byte[] wrappedKey,2532String wrappedKeyAlgorithm,2533int wrappedKeyType)2534throws InvalidKeyException, NoSuchAlgorithmException {25352536if (!(this instanceof NullCipher)) {2537if (!initialized) {2538throw new IllegalStateException("Cipher not initialized");2539}2540if (opmode != Cipher.UNWRAP_MODE) {2541throw new IllegalStateException("Cipher not initialized " +2542"for unwrapping keys");2543}2544}2545if ((wrappedKeyType != SECRET_KEY) &&2546(wrappedKeyType != PRIVATE_KEY) &&2547(wrappedKeyType != PUBLIC_KEY)) {2548throw new InvalidParameterException("Invalid key type");2549}25502551chooseFirstProvider();2552return spi.engineUnwrap(wrappedKey,2553wrappedKeyAlgorithm,2554wrappedKeyType);2555}25562557private AlgorithmParameterSpec getAlgorithmParameterSpec(2558AlgorithmParameters params)2559throws InvalidParameterSpecException {2560if (params == null) {2561return null;2562}25632564String alg = params.getAlgorithm().toUpperCase(Locale.ENGLISH);25652566if (alg.equalsIgnoreCase("RC2")) {2567return params.getParameterSpec(RC2ParameterSpec.class);2568}25692570if (alg.equalsIgnoreCase("RC5")) {2571return params.getParameterSpec(RC5ParameterSpec.class);2572}25732574if (alg.startsWith("PBE")) {2575return params.getParameterSpec(PBEParameterSpec.class);2576}25772578if (alg.startsWith("DES")) {2579return params.getParameterSpec(IvParameterSpec.class);2580}2581return null;2582}25832584private static CryptoPermission getConfiguredPermission(2585String transformation) throws NullPointerException,2586NoSuchAlgorithmException {2587if (transformation == null) throw new NullPointerException();2588String[] parts = tokenizeTransformation(transformation);2589return JceSecurityManager.INSTANCE.getCryptoPermission(parts[0]);2590}25912592/**2593* Returns the maximum key length for the specified transformation2594* according to the installed JCE jurisdiction policy files. If2595* JCE unlimited strength jurisdiction policy files are installed,2596* Integer.MAX_VALUE will be returned.2597* For more information on default key size in JCE jurisdiction2598* policy files, please see Appendix E in the2599* <a href=2600* "{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html#AppC">2601* Java Cryptography Architecture Reference Guide</a>.2602*2603* @param transformation the cipher transformation.2604* @return the maximum key length in bits or Integer.MAX_VALUE.2605* @exception NullPointerException if {@code transformation} is null.2606* @exception NoSuchAlgorithmException if {@code transformation}2607* is not a valid transformation, i.e. in the form of "algorithm" or2608* "algorithm/mode/padding".2609* @since 1.52610*/2611public static final int getMaxAllowedKeyLength(String transformation)2612throws NoSuchAlgorithmException {2613CryptoPermission cp = getConfiguredPermission(transformation);2614return cp.getMaxKeySize();2615}26162617/**2618* Returns an AlgorithmParameterSpec object which contains2619* the maximum cipher parameter value according to the2620* jurisdiction policy file. If JCE unlimited strength jurisdiction2621* policy files are installed or there is no maximum limit on the2622* parameters for the specified transformation in the policy file,2623* null will be returned.2624*2625* @param transformation the cipher transformation.2626* @return an AlgorithmParameterSpec which holds the maximum2627* value or null.2628* @exception NullPointerException if {@code transformation}2629* is null.2630* @exception NoSuchAlgorithmException if {@code transformation}2631* is not a valid transformation, i.e. in the form of "algorithm" or2632* "algorithm/mode/padding".2633* @since 1.52634*/2635public static final AlgorithmParameterSpec getMaxAllowedParameterSpec(2636String transformation) throws NoSuchAlgorithmException {2637CryptoPermission cp = getConfiguredPermission(transformation);2638return cp.getAlgorithmParameterSpec();2639}26402641/**2642* Continues a multi-part update of the Additional Authentication2643* Data (AAD).2644* <p>2645* Calls to this method provide AAD to the cipher when operating in2646* modes such as AEAD (GCM/CCM). If this cipher is operating in2647* either GCM or CCM mode, all AAD must be supplied before beginning2648* operations on the ciphertext (via the {@code update} and {@code2649* doFinal} methods).2650*2651* @param src the buffer containing the Additional Authentication Data2652*2653* @throws IllegalArgumentException if the {@code src}2654* byte array is null2655* @throws IllegalStateException if this cipher is in a wrong state2656* (e.g., has not been initialized), does not accept AAD, or if2657* operating in either GCM or CCM mode and one of the {@code update}2658* methods has already been called for the active2659* encryption/decryption operation2660* @throws UnsupportedOperationException if the corresponding method2661* in the {@code CipherSpi} has not been overridden by an2662* implementation2663*2664* @since 1.72665*/2666public final void updateAAD(byte[] src) {2667if (src == null) {2668throw new IllegalArgumentException("src buffer is null");2669}26702671updateAAD(src, 0, src.length);2672}26732674/**2675* Continues a multi-part update of the Additional Authentication2676* Data (AAD), using a subset of the provided buffer.2677* <p>2678* Calls to this method provide AAD to the cipher when operating in2679* modes such as AEAD (GCM/CCM). If this cipher is operating in2680* either GCM or CCM mode, all AAD must be supplied before beginning2681* operations on the ciphertext (via the {@code update} and {@code2682* doFinal} methods).2683*2684* @param src the buffer containing the AAD2685* @param offset the offset in {@code src} where the AAD input starts2686* @param len the number of AAD bytes2687*2688* @throws IllegalArgumentException if the {@code src}2689* byte array is null, or the {@code offset} or {@code length}2690* is less than 0, or the sum of the {@code offset} and2691* {@code len} is greater than the length of the2692* {@code src} byte array2693* @throws IllegalStateException if this cipher is in a wrong state2694* (e.g., has not been initialized), does not accept AAD, or if2695* operating in either GCM or CCM mode and one of the {@code update}2696* methods has already been called for the active2697* encryption/decryption operation2698* @throws UnsupportedOperationException if the corresponding method2699* in the {@code CipherSpi} has not been overridden by an2700* implementation2701*2702* @since 1.72703*/2704public final void updateAAD(byte[] src, int offset, int len) {2705checkCipherState();27062707// Input sanity check2708if ((src == null) || (offset < 0) || (len < 0)2709|| (len > (src.length - offset))) {2710throw new IllegalArgumentException("Bad arguments");2711}27122713chooseFirstProvider();2714if (len == 0) {2715return;2716}2717spi.engineUpdateAAD(src, offset, len);2718}27192720/**2721* Continues a multi-part update of the Additional Authentication2722* Data (AAD).2723* <p>2724* Calls to this method provide AAD to the cipher when operating in2725* modes such as AEAD (GCM/CCM). If this cipher is operating in2726* either GCM or CCM mode, all AAD must be supplied before beginning2727* operations on the ciphertext (via the {@code update} and {@code2728* doFinal} methods).2729* <p>2730* All {@code src.remaining()} bytes starting at2731* {@code src.position()} are processed.2732* Upon return, the input buffer's position will be equal2733* to its limit; its limit will not have changed.2734*2735* @param src the buffer containing the AAD2736*2737* @throws IllegalArgumentException if the {@code src ByteBuffer}2738* is null2739* @throws IllegalStateException if this cipher is in a wrong state2740* (e.g., has not been initialized), does not accept AAD, or if2741* operating in either GCM or CCM mode and one of the {@code update}2742* methods has already been called for the active2743* encryption/decryption operation2744* @throws UnsupportedOperationException if the corresponding method2745* in the {@code CipherSpi} has not been overridden by an2746* implementation2747*2748* @since 1.72749*/2750public final void updateAAD(ByteBuffer src) {2751checkCipherState();27522753// Input sanity check2754if (src == null) {2755throw new IllegalArgumentException("src ByteBuffer is null");2756}27572758chooseFirstProvider();2759if (src.remaining() == 0) {2760return;2761}2762spi.engineUpdateAAD(src);2763}2764}276527662767