Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } int canuse = tr.supportsModePadding(s); if (canuse == S_NO) { // does not support mode or padding we need, ignore continue; } if (canuse == S_YES) { return new Cipher(null, s, t, transformation, transforms); } else { // S_MAYBE, try out if it works try { CipherSpi spi = (CipherSpi)s.newInstance(null); tr.setModePadding(spi); return new Cipher(spi, s, t, transformation, transforms); } catch (Exception e) { failure = e; } } } throw new NoSuchAlgorithmException ("Cannot find any provider supporting " + transformation, failure); } /** * Returns a <code>Cipher</code> object that implements the specified * transformation. * * <p> A new Cipher object encapsulating the * CipherSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * * <p> Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param transformation the name of the transformation, * e.g., <i>DES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard transformation names. * * @param provider the name of the provider. * * @return a cipher that implements the requested transformation. * * @exception NoSuchAlgorithmException if <code>transformation</code> * is null, empty, in an invalid format, * or if a CipherSpi implementation for the specified algorithm * is not available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception NoSuchPaddingException if <code>transformation</code> * contains a padding scheme that is not available. * * @exception IllegalArgumentException if the <code>provider</code> * is null or empty. * * @see java.security.Provider */ public static final Cipher getInstance(String transformation, String provider) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { if ((provider == null) || (provider.length() == 0)) { throw new IllegalArgumentException("Missing provider"); } Provider p = Security.getProvider(provider); if (p == null) { throw new NoSuchProviderException("No such provider: " + provider); } return getInstance(transformation, p); } /** * Returns a <code>Cipher</code> object that implements the specified * transformation. * * <p> A new Cipher object encapsulating the * CipherSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param transformation the name of the transformation, * e.g., <i>DES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard transformation names. * * @param provider the provider. * * @return a cipher that implements the requested transformation. * * @exception NoSuchAlgorithmException if <code>transformation</code> * is null, empty, in an invalid format, * or if a CipherSpi implementation for the specified algorithm * is not available from the specified Provider object. * * @exception NoSuchPaddingException if <code>transformation</code> * contains a padding scheme that is not available. * * @exception IllegalArgumentException if the <code>provider</code> * is null. * * @see java.security.Provider */ public static final Cipher getInstance(String transformation, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException { if (provider == null) { throw new IllegalArgumentException("Missing provider"); } Exception failure = null; List transforms = getTransforms(transformation); boolean providerChecked = false; String paddingError = null; for (Iterator t = transforms.iterator(); t.hasNext();) { Transform tr = (Transform)t.next(); Service s = provider.getService("Cipher", tr.transform); if (s == null) { continue; } if (providerChecked == false) { // for compatibility, first do the lookup and then verify // the provider. this makes the difference between a NSAE // and a SecurityException if the // provider does not support the algorithm. Exception ve = JceSecurity.getVerificationResult(provider); if (ve != null) { String msg = "JCE cannot authenticate the provider " + provider.getName(); throw new SecurityException(msg, ve); } providerChecked = true; } if (tr.supportsMode(s) == S_NO) { continue; } if (tr.supportsPadding(s) == S_NO) { paddingError = tr.pad; continue; } try { CipherSpi spi = (CipherSpi)s.newInstance(null); tr.setModePadding(spi); Cipher cipher = new Cipher(spi, transformation); cipher.provider = s.getProvider(); cipher.initCryptoPermission(); return cipher; } catch (Exception e) { failure = e; } } // throw NoSuchPaddingException if the problem is with padding if (failure instanceof NoSuchPaddingException) { throw (NoSuchPaddingException)failure; } if (paddingError != null) { throw new NoSuchPaddingException ("Padding not supported: " + paddingError); } throw new NoSuchAlgorithmException ("No such algorithm: " + transformation, failure); } // If the requested crypto service is export-controlled, // determine the maximum allowable keysize. private void initCryptoPermission() throws NoSuchAlgorithmException { if (JceSecurity.isRestricted() == false) { cryptoPerm = CryptoAllPermission.INSTANCE; exmech = null; return; } cryptoPerm = getConfiguredPermission(transformation); // Instantiate the exemption mechanism (if required) String exmechName = cryptoPerm.getExemptionMechanism(); if (exmechName != null) { exmech = ExemptionMechanism.getInstance(exmechName); } } // max number of debug warnings to print from chooseFirstProvider() private static int warnCount = 10; /** * Choose the Spi from the first provider available. Used if * delayed provider selection is not possible because init() * is not the first method called. */ void chooseFirstProvider() { if (spi != null) { return; } synchronized (lock) { if (spi != null) { return; } if (debug != null) { int w = --warnCount; if (w >= 0) { debug.println("Cipher.init() not first method " + "called, disabling delayed provider selection"); if (w == 0) { debug.println("Further warnings of this type will " + "be suppressed"); } new Exception("Call trace").printStackTrace(); } } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; CipherSpi thisSpi; if (firstService != null) { s = firstService; thisSpi = firstSpi; firstService = null; firstSpi = null; } else { s = (Service)serviceIterator.next(); thisSpi = null; } if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } if (tr.supportsModePadding(s) == S_NO) { continue; } try { if (thisSpi == null) { Object obj = s.newInstance(null); if (obj instanceof CipherSpi == false) { continue; } thisSpi = (CipherSpi)obj; } tr.setModePadding(thisSpi); initCryptoPermission(); spi = thisSpi; provider = s.getProvider(); // not needed any more firstService = null; serviceIterator = null; transforms = null; return; } catch (Exception e) { lastException = e; } } ProviderException e = new ProviderException ("Could not construct CipherSpi instance"); if (lastException != null) { e.initCause(lastException); } throw e; } } private final static int I_KEY = 1; private final static int I_PARAMSPEC = 2; private final static int I_PARAMS = 3; private final static int I_CERT = 4; private void implInit(CipherSpi thisSpi, int type, int opmode, Key key, AlgorithmParameterSpec paramSpec, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { switch (type) { case I_KEY: checkCryptoPerm(thisSpi, key); thisSpi.engineInit(opmode, key, random); break; case I_PARAMSPEC: checkCryptoPerm(thisSpi, key, paramSpec); thisSpi.engineInit(opmode, key, paramSpec, random); break; case I_PARAMS: checkCryptoPerm(thisSpi, key, params); thisSpi.engineInit(opmode, key, params, random); break; case I_CERT: checkCryptoPerm(thisSpi, key); thisSpi.engineInit(opmode, key, random); break; default: throw new AssertionError("Internal Cipher error: " + type); } } private void chooseProvider(int initType, int opmode, Key key, AlgorithmParameterSpec paramSpec, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { synchronized (lock) { if (spi != null) { implInit(spi, initType, opmode, key, paramSpec, params, random); return; } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; CipherSpi thisSpi; if (firstService != null) { s = firstService; thisSpi = firstSpi; firstService = null; firstSpi = null; } else { s = (Service)serviceIterator.next(); thisSpi = null; } // if provider says it does not support this key, ignore it if (s.supportsParameter(key) == false) { continue; } if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } if (tr.supportsModePadding(s) == S_NO) { continue; } try { if (thisSpi == null) { thisSpi = (CipherSpi)s.newInstance(null); } tr.setModePadding(thisSpi); initCryptoPermission(); implInit(thisSpi, initType, opmode, key, paramSpec, params, random); provider = s.getProvider(); this.spi = thisSpi; firstService = null; serviceIterator = null; transforms = null; return; } catch (Exception e) { // NoSuchAlgorithmException from newInstance() // InvalidKeyException from init() // RuntimeException (ProviderException) from init() // SecurityException from crypto permission check if (lastException == null) { lastException = e; } } } // no working provider found, fail if (lastException instanceof InvalidKeyException) { throw (InvalidKeyException)lastException; } if (lastException instanceof InvalidAlgorithmParameterException) { throw (InvalidAlgorithmParameterException)lastException; } if (lastException instanceof RuntimeException) { throw (RuntimeException)lastException; } String kName = (key != null) ? key.getClass().getName() : "(null)"; throw new InvalidKeyException ("No installed provider supports this key: " + kName, lastException); } } /** * Returns the provider of this <code>Cipher</code> object. * * @return the provider of this <code>Cipher</code> object */ public final Provider getProvider() { chooseFirstProvider(); return this.provider; } /** * Returns the algorithm name of this <code>Cipher</code> object. * * <p>This is the same name that was specified in one of the * <code>getInstance</code> calls that created this <code>Cipher</code> * object.. * * @return the algorithm name of this <code>Cipher</code> object. */ public final String getAlgorithm() { return this.transformation; } /** * Returns the block size (in bytes). * * @return the block size (in bytes), or 0 if the underlying algorithm is * not a block cipher */ public final int getBlockSize() { chooseFirstProvider(); return spi.engineGetBlockSize(); } /** * Returns the length in bytes that an output buffer would need to be in * order to hold the result of the next <code>update</code> or * <code>doFinal</code> operation, given the input length * <code>inputLen</code> (in bytes). * * <p>This call takes into account any unprocessed (buffered) data from a * previous <code>update</code> call, padding, and AEAD tagging. * * <p>The actual output length of the next <code>update</code> or * <code>doFinal</code> call may be smaller than the length returned by * this method. * * @param inputLen the input length (in bytes) * * @return the required output buffer size (in bytes) * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not yet been initialized) */ public final int getOutputSize(int inputLen) { if (!initialized && !(this instanceof NullCipher)) { throw new IllegalStateException("Cipher not initialized"); } if (inputLen < 0) { throw new IllegalArgumentException("Input size must be equal " + "to or greater than zero"); } chooseFirstProvider(); return spi.engineGetOutputSize(inputLen); } /** * Returns the initialization vector (IV) in a new buffer. * * <p>This is useful in the case where a random IV was created, * or in the context of password-based encryption or * decryption, where the IV is derived from a user-supplied password. * * @return the initialization vector in a new buffer, or null if the * underlying algorithm does not use an IV, or if the IV has not yet * been set. */ public final byte[] getIV() { chooseFirstProvider(); return spi.engineGetIV(); } /** * Returns the parameters used with this cipher. * * <p>The returned parameters may be the same that were used to initialize * this cipher, or may contain a combination of default and random * parameter values used by the underlying cipher implementation if this * cipher requires algorithm parameters but was not initialized with any. * * @return the parameters used with this cipher, or null if this cipher * does not use any parameters. */ public final AlgorithmParameters getParameters() { chooseFirstProvider(); return spi.engineGetParameters(); } /** * Returns the exemption mechanism object used with this cipher. * * @return the exemption mechanism object used with this cipher, or * null if this cipher does not use any exemption mechanism. */ public final ExemptionMechanism getExemptionMechanism() { chooseFirstProvider(); return exmech; } // // Crypto permission check code below // private void checkCryptoPerm(CipherSpi checkSpi, Key key) throws InvalidKeyException { if (cryptoPerm == CryptoAllPermission.INSTANCE) { return; }Lines 501–1000 of 2677. Previous lines Load more
Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } int canuse = tr.supportsModePadding(s); if (canuse == S_NO) { // does not support mode or padding we need, ignore continue; } if (canuse == S_YES) { return new Cipher(null, s, t, transformation, transforms); } else { // S_MAYBE, try out if it works try { CipherSpi spi = (CipherSpi)s.newInstance(null); tr.setModePadding(spi); return new Cipher(spi, s, t, transformation, transforms); } catch (Exception e) { failure = e; } } } throw new NoSuchAlgorithmException ("Cannot find any provider supporting " + transformation, failure); } /** * Returns a <code>Cipher</code> object that implements the specified * transformation. * * <p> A new Cipher object encapsulating the * CipherSpi implementation from the specified provider * is returned. The specified provider must be registered * in the security provider list. * * <p> Note that the list of registered providers may be retrieved via * the {@link Security#getProviders() Security.getProviders()} method. * * @param transformation the name of the transformation, * e.g., <i>DES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard transformation names. * * @param provider the name of the provider. * * @return a cipher that implements the requested transformation. * * @exception NoSuchAlgorithmException if <code>transformation</code> * is null, empty, in an invalid format, * or if a CipherSpi implementation for the specified algorithm * is not available from the specified provider. * * @exception NoSuchProviderException if the specified provider is not * registered in the security provider list. * * @exception NoSuchPaddingException if <code>transformation</code> * contains a padding scheme that is not available. * * @exception IllegalArgumentException if the <code>provider</code> * is null or empty. * * @see java.security.Provider */ public static final Cipher getInstance(String transformation, String provider) throws NoSuchAlgorithmException, NoSuchProviderException, NoSuchPaddingException { if ((provider == null) || (provider.length() == 0)) { throw new IllegalArgumentException("Missing provider"); } Provider p = Security.getProvider(provider); if (p == null) { throw new NoSuchProviderException("No such provider: " + provider); } return getInstance(transformation, p); } /** * Returns a <code>Cipher</code> object that implements the specified * transformation. * * <p> A new Cipher object encapsulating the * CipherSpi implementation from the specified Provider * object is returned. Note that the specified Provider object * does not have to be registered in the provider list. * * @param transformation the name of the transformation, * e.g., <i>DES/CBC/PKCS5Padding</i>. * See the Cipher section in the <a href= * "{@docRoot}/../technotes/guides/security/StandardNames.html#Cipher"> * Java Cryptography Architecture Standard Algorithm Name Documentation</a> * for information about standard transformation names. * * @param provider the provider. * * @return a cipher that implements the requested transformation. * * @exception NoSuchAlgorithmException if <code>transformation</code> * is null, empty, in an invalid format, * or if a CipherSpi implementation for the specified algorithm * is not available from the specified Provider object. * * @exception NoSuchPaddingException if <code>transformation</code> * contains a padding scheme that is not available. * * @exception IllegalArgumentException if the <code>provider</code> * is null. * * @see java.security.Provider */ public static final Cipher getInstance(String transformation, Provider provider) throws NoSuchAlgorithmException, NoSuchPaddingException { if (provider == null) { throw new IllegalArgumentException("Missing provider"); } Exception failure = null; List transforms = getTransforms(transformation); boolean providerChecked = false; String paddingError = null; for (Iterator t = transforms.iterator(); t.hasNext();) { Transform tr = (Transform)t.next(); Service s = provider.getService("Cipher", tr.transform); if (s == null) { continue; } if (providerChecked == false) { // for compatibility, first do the lookup and then verify // the provider. this makes the difference between a NSAE // and a SecurityException if the // provider does not support the algorithm. Exception ve = JceSecurity.getVerificationResult(provider); if (ve != null) { String msg = "JCE cannot authenticate the provider " + provider.getName(); throw new SecurityException(msg, ve); } providerChecked = true; } if (tr.supportsMode(s) == S_NO) { continue; } if (tr.supportsPadding(s) == S_NO) { paddingError = tr.pad; continue; } try { CipherSpi spi = (CipherSpi)s.newInstance(null); tr.setModePadding(spi); Cipher cipher = new Cipher(spi, transformation); cipher.provider = s.getProvider(); cipher.initCryptoPermission(); return cipher; } catch (Exception e) { failure = e; } } // throw NoSuchPaddingException if the problem is with padding if (failure instanceof NoSuchPaddingException) { throw (NoSuchPaddingException)failure; } if (paddingError != null) { throw new NoSuchPaddingException ("Padding not supported: " + paddingError); } throw new NoSuchAlgorithmException ("No such algorithm: " + transformation, failure); } // If the requested crypto service is export-controlled, // determine the maximum allowable keysize. private void initCryptoPermission() throws NoSuchAlgorithmException { if (JceSecurity.isRestricted() == false) { cryptoPerm = CryptoAllPermission.INSTANCE; exmech = null; return; } cryptoPerm = getConfiguredPermission(transformation); // Instantiate the exemption mechanism (if required) String exmechName = cryptoPerm.getExemptionMechanism(); if (exmechName != null) { exmech = ExemptionMechanism.getInstance(exmechName); } } // max number of debug warnings to print from chooseFirstProvider() private static int warnCount = 10; /** * Choose the Spi from the first provider available. Used if * delayed provider selection is not possible because init() * is not the first method called. */ void chooseFirstProvider() { if (spi != null) { return; } synchronized (lock) { if (spi != null) { return; } if (debug != null) { int w = --warnCount; if (w >= 0) { debug.println("Cipher.init() not first method " + "called, disabling delayed provider selection"); if (w == 0) { debug.println("Further warnings of this type will " + "be suppressed"); } new Exception("Call trace").printStackTrace(); } } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; CipherSpi thisSpi; if (firstService != null) { s = firstService; thisSpi = firstSpi; firstService = null; firstSpi = null; } else { s = (Service)serviceIterator.next(); thisSpi = null; } if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } if (tr.supportsModePadding(s) == S_NO) { continue; } try { if (thisSpi == null) { Object obj = s.newInstance(null); if (obj instanceof CipherSpi == false) { continue; } thisSpi = (CipherSpi)obj; } tr.setModePadding(thisSpi); initCryptoPermission(); spi = thisSpi; provider = s.getProvider(); // not needed any more firstService = null; serviceIterator = null; transforms = null; return; } catch (Exception e) { lastException = e; } } ProviderException e = new ProviderException ("Could not construct CipherSpi instance"); if (lastException != null) { e.initCause(lastException); } throw e; } } private final static int I_KEY = 1; private final static int I_PARAMSPEC = 2; private final static int I_PARAMS = 3; private final static int I_CERT = 4; private void implInit(CipherSpi thisSpi, int type, int opmode, Key key, AlgorithmParameterSpec paramSpec, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { switch (type) { case I_KEY: checkCryptoPerm(thisSpi, key); thisSpi.engineInit(opmode, key, random); break; case I_PARAMSPEC: checkCryptoPerm(thisSpi, key, paramSpec); thisSpi.engineInit(opmode, key, paramSpec, random); break; case I_PARAMS: checkCryptoPerm(thisSpi, key, params); thisSpi.engineInit(opmode, key, params, random); break; case I_CERT: checkCryptoPerm(thisSpi, key); thisSpi.engineInit(opmode, key, random); break; default: throw new AssertionError("Internal Cipher error: " + type); } } private void chooseProvider(int initType, int opmode, Key key, AlgorithmParameterSpec paramSpec, AlgorithmParameters params, SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { synchronized (lock) { if (spi != null) { implInit(spi, initType, opmode, key, paramSpec, params, random); return; } Exception lastException = null; while ((firstService != null) || serviceIterator.hasNext()) { Service s; CipherSpi thisSpi; if (firstService != null) { s = firstService; thisSpi = firstSpi; firstService = null; firstSpi = null; } else { s = (Service)serviceIterator.next(); thisSpi = null; } // if provider says it does not support this key, ignore it if (s.supportsParameter(key) == false) { continue; } if (JceSecurity.canUseProvider(s.getProvider()) == false) { continue; } Transform tr = getTransform(s, transforms); if (tr == null) { // should never happen continue; } if (tr.supportsModePadding(s) == S_NO) { continue; } try { if (thisSpi == null) { thisSpi = (CipherSpi)s.newInstance(null); } tr.setModePadding(thisSpi); initCryptoPermission(); implInit(thisSpi, initType, opmode, key, paramSpec, params, random); provider = s.getProvider(); this.spi = thisSpi; firstService = null; serviceIterator = null; transforms = null; return; } catch (Exception e) { // NoSuchAlgorithmException from newInstance() // InvalidKeyException from init() // RuntimeException (ProviderException) from init() // SecurityException from crypto permission check if (lastException == null) { lastException = e; } } } // no working provider found, fail if (lastException instanceof InvalidKeyException) { throw (InvalidKeyException)lastException; } if (lastException instanceof InvalidAlgorithmParameterException) { throw (InvalidAlgorithmParameterException)lastException; } if (lastException instanceof RuntimeException) { throw (RuntimeException)lastException; } String kName = (key != null) ? key.getClass().getName() : "(null)"; throw new InvalidKeyException ("No installed provider supports this key: " + kName, lastException); } } /** * Returns the provider of this <code>Cipher</code> object. * * @return the provider of this <code>Cipher</code> object */ public final Provider getProvider() { chooseFirstProvider(); return this.provider; } /** * Returns the algorithm name of this <code>Cipher</code> object. * * <p>This is the same name that was specified in one of the * <code>getInstance</code> calls that created this <code>Cipher</code> * object.. * * @return the algorithm name of this <code>Cipher</code> object. */ public final String getAlgorithm() { return this.transformation; } /** * Returns the block size (in bytes). * * @return the block size (in bytes), or 0 if the underlying algorithm is * not a block cipher */ public final int getBlockSize() { chooseFirstProvider(); return spi.engineGetBlockSize(); } /** * Returns the length in bytes that an output buffer would need to be in * order to hold the result of the next <code>update</code> or * <code>doFinal</code> operation, given the input length * <code>inputLen</code> (in bytes). * * <p>This call takes into account any unprocessed (buffered) data from a * previous <code>update</code> call, padding, and AEAD tagging. * * <p>The actual output length of the next <code>update</code> or * <code>doFinal</code> call may be smaller than the length returned by * this method. * * @param inputLen the input length (in bytes) * * @return the required output buffer size (in bytes) * * @exception IllegalStateException if this cipher is in a wrong state * (e.g., has not yet been initialized) */ public final int getOutputSize(int inputLen) { if (!initialized && !(this instanceof NullCipher)) { throw new IllegalStateException("Cipher not initialized"); } if (inputLen < 0) { throw new IllegalArgumentException("Input size must be equal " + "to or greater than zero"); } chooseFirstProvider(); return spi.engineGetOutputSize(inputLen); } /** * Returns the initialization vector (IV) in a new buffer. * * <p>This is useful in the case where a random IV was created, * or in the context of password-based encryption or * decryption, where the IV is derived from a user-supplied password. * * @return the initialization vector in a new buffer, or null if the * underlying algorithm does not use an IV, or if the IV has not yet * been set. */ public final byte[] getIV() { chooseFirstProvider(); return spi.engineGetIV(); } /** * Returns the parameters used with this cipher. * * <p>The returned parameters may be the same that were used to initialize * this cipher, or may contain a combination of default and random * parameter values used by the underlying cipher implementation if this * cipher requires algorithm parameters but was not initialized with any. * * @return the parameters used with this cipher, or null if this cipher * does not use any parameters. */ public final AlgorithmParameters getParameters() { chooseFirstProvider(); return spi.engineGetParameters(); } /** * Returns the exemption mechanism object used with this cipher. * * @return the exemption mechanism object used with this cipher, or * null if this cipher does not use any exemption mechanism. */ public final ExemptionMechanism getExemptionMechanism() { chooseFirstProvider(); return exmech; } // // Crypto permission check code below // private void checkCryptoPerm(CipherSpi checkSpi, Key key) throws InvalidKeyException { if (cryptoPerm == CryptoAllPermission.INSTANCE) { return; }