/**
* Copyright 2003-2016 SSHTOOLS Limited. All Rights Reserved.
*
* For product documentation visit https://www.sshtools.com/
*
* This file is part of J2SSH Maverick.
*
* J2SSH Maverick is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* J2SSH Maverick is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with J2SSH Maverick. If not, see <http://www.gnu.org/licenses/>.
*/
package com.sshtools.ssh.components.jce;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.interfaces.DSAPrivateKey;
import java.security.interfaces.DSAPublicKey;
import java.security.interfaces.RSAPrivateCrtKey;
import java.security.interfaces.RSAPublicKey;
import com.sshtools.logging.Log;
import com.sshtools.ssh.SshException;
import com.sshtools.ssh.components.ComponentFactory;
import com.sshtools.ssh.components.ComponentManager;
import com.sshtools.ssh.components.Digest;
import com.sshtools.ssh.components.SshCipher;
import com.sshtools.ssh.components.SshDsaPrivateKey;
import com.sshtools.ssh.components.SshDsaPublicKey;
import com.sshtools.ssh.components.SshHmac;
import com.sshtools.ssh.components.SshKeyPair;
import com.sshtools.ssh.components.SshRsaPrivateCrtKey;
import com.sshtools.ssh.components.SshRsaPrivateKey;
import com.sshtools.ssh.components.SshRsaPublicKey;
import com.sshtools.ssh.components.SshSecureRandomGenerator;
/**
* A component manager for the Java runtime JCE provider. By default all
* algorithms will be selected from the default provider i.e no provider is
* specified in calls to JCE methods to create components. You can initialize a
* default provider to be used on all calls with the following code:
*
* <blockquote>
*
* <pre>
* JCEComponentManager.initializeDefaultProvider(new BouncyCastleProvider());
* </pre>
*
* </blockquote>
*
* Alternatively you can also assign a specific provider for an individual
* algorithm, all algorithms used by the API are included as static constants in
* this class.
*
* <blockquote>
*
* <pre>
* JCEComponentManager.initializeProviderForAlgorithm(JCEComponentManager.JCE_DSA,
* new BouncyCastleProvider());
* </pre>
*
* </blockquote>
*
* @author Lee David Painter
*/
public class JCEComponentManager extends ComponentManager implements
JCEAlgorithms {
SecureRND rnd;
public JCEComponentManager() {
try {
@SuppressWarnings("unchecked")
Class<Provider> cls = (Class<Provider>) Class
.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
Provider bc = (Provider) cls.newInstance();
java.security.Security.addProvider(bc);
JCEComponentManager.initializeProviderForAlgorithm(
JCEAlgorithms.JCE_DH, bc);
} catch (Throwable t) {
Log.error(
this,
"Could not find BouncyCastle provider diffie-hellman-group14-sha1 may not be available");
}
}
/**
* Initialize the default JCE provider used by the API.
*
* @param provider
*/
public static void initializeDefaultProvider(Provider provider) {
JCEProvider.initializeDefaultProvider(provider);
}
/**
* Initialize a provider for a specific algorithm.
*
* @param jceAlgorithm
* @param provider
*/
public static void initializeProviderForAlgorithm(String jceAlgorithm,
Provider provider) {
JCEProvider.initializeProviderForAlgorithm(jceAlgorithm, provider);
}
/**
* Get the algorithm used for secure random number generation.
*
* @return String
*/
public static String getSecureRandomAlgorithm() {
return JCEProvider.getSecureRandomAlgorithm();
}
/**
* Set the algorithm used for secure random number generation.
*
* @param secureRandomAlgorithm
*/
public static void setSecureRandomAlgorithm(String secureRandomAlgorithm) {
JCEProvider.setSecureRandomAlgorithm(secureRandomAlgorithm);
}
/**
* Get the provider for a specific algorithm.
*
* @param jceAlgorithm
* @return Provider
*/
public static Provider getProviderForAlgorithm(String jceAlgorithm) {
return JCEProvider.getProviderForAlgorithm(jceAlgorithm);
}
/**
* Get the secure random implementation for the API.
*
* @return SecureRandom
* @throws NoSuchAlgorithmException
*/
public static SecureRandom getSecureRandom()
throws NoSuchAlgorithmException {
return JCEProvider.getSecureRandom();
}
public SshDsaPrivateKey createDsaPrivateKey(BigInteger p, BigInteger q,
BigInteger g, BigInteger x, BigInteger y) throws SshException {
return new Ssh2DsaPrivateKey(p, q, g, x, y);
}
public SshDsaPublicKey createDsaPublicKey(BigInteger p, BigInteger q,
BigInteger g, BigInteger y) throws SshException {
try {
return new Ssh2DsaPublicKey(p, q, g, y);
} catch (Throwable e) {
throw new SshException(e);
}
}
public SshDsaPublicKey createDsaPublicKey() {
return new Ssh2DsaPublicKey();
}
public SshRsaPrivateCrtKey createRsaPrivateCrtKey(BigInteger modulus,
BigInteger publicExponent, BigInteger privateExponent,
BigInteger primeP, BigInteger primeQ, BigInteger crtCoefficient)
throws SshException {
try {
BigInteger primeExponentP = primeP.subtract(BigInteger.ONE);
primeExponentP = privateExponent.mod(primeExponentP);
BigInteger primeExponentQ = primeQ.subtract(BigInteger.ONE);
primeExponentQ = privateExponent.mod(primeExponentQ);
return new Ssh2RsaPrivateCrtKey(modulus, publicExponent,
privateExponent, primeP, primeQ, primeExponentP,
primeExponentQ, crtCoefficient);
} catch (Throwable e) {
throw new SshException(e);
}
}
public SshRsaPrivateCrtKey createRsaPrivateCrtKey(BigInteger modulus,
BigInteger publicExponent, BigInteger privateExponent,
BigInteger primeP, BigInteger primeQ, BigInteger primeExponentP,
BigInteger primeExponentQ, BigInteger crtCoefficient)
throws SshException {
try {
return new Ssh2RsaPrivateCrtKey(modulus, publicExponent,
privateExponent, primeP, primeQ, primeExponentP,
primeExponentQ, crtCoefficient);
} catch (Throwable e) {
throw new SshException(e);
}
}
public SshRsaPrivateKey createRsaPrivateKey(BigInteger modulus,
BigInteger privateExponent) throws SshException {
try {
return new Ssh2RsaPrivateKey(modulus, privateExponent);
} catch (Throwable t) {
throw new SshException(t);
}
}
public SshRsaPublicKey createRsaPublicKey(BigInteger modulus,
BigInteger publicExponent) throws SshException {
try {
return new Ssh2RsaPublicKey(modulus, publicExponent);
} catch (Throwable e) {
throw new SshException(e);
}
}
public SshRsaPublicKey createSsh2RsaPublicKey() throws SshException {
return new Ssh2RsaPublicKey();
}
public SshKeyPair generateDsaKeyPair(int bits) throws SshException {
try {
KeyPairGenerator keyGen = JCEProvider
.getProviderForAlgorithm(JCE_DSA) == null ? KeyPairGenerator
.getInstance(JCE_DSA) : KeyPairGenerator.getInstance(
JCE_DSA, JCEProvider.getProviderForAlgorithm(JCE_DSA));
keyGen.initialize(bits);
KeyPair keypair = keyGen.genKeyPair();
PrivateKey privateKey = keypair.getPrivate();
PublicKey publicKey = keypair.getPublic();
SshKeyPair pair = new SshKeyPair();
pair.setPrivateKey(new Ssh2DsaPrivateKey(
(DSAPrivateKey) privateKey, (DSAPublicKey) publicKey));
pair.setPublicKey(new Ssh2DsaPublicKey((DSAPublicKey) publicKey));
return pair;
} catch (java.security.NoSuchAlgorithmException e) {
throw new SshException(e);
}
}
public SshKeyPair generateRsaKeyPair(int bits) throws SshException {
try {
KeyPairGenerator keyGen = JCEProvider
.getProviderForAlgorithm(JCE_RSA) == null ? KeyPairGenerator
.getInstance(JCE_RSA) : KeyPairGenerator.getInstance(
JCE_RSA, JCEProvider.getProviderForAlgorithm(JCE_RSA));
keyGen.initialize(bits);
KeyPair keypair = keyGen.genKeyPair();
PrivateKey privateKey = keypair.getPrivate();
PublicKey publicKey = keypair.getPublic();
SshKeyPair pair = new SshKeyPair();
if (!(privateKey instanceof RSAPrivateCrtKey)) {
throw new SshException(
"RSA key generation requires RSAPrivateCrtKey as private key type.",
SshException.JCE_ERROR);
}
pair.setPrivateKey(new Ssh2RsaPrivateCrtKey(
(RSAPrivateCrtKey) privateKey));
pair.setPublicKey(new Ssh2RsaPublicKey((RSAPublicKey) publicKey));
return pair;
} catch (java.security.NoSuchAlgorithmException e) {
throw new SshException(e);
}
}
public SshSecureRandomGenerator getRND() throws SshException {
try {
return rnd == null ? new SecureRND() : rnd;
} catch (NoSuchAlgorithmException e) {
throw new SshException(e);
}
}
protected void initializeDigestFactory(ComponentFactory digests) {
if (testDigest(JCEAlgorithms.JCE_MD5, MD5Digest.class))
digests.add(JCEAlgorithms.JCE_MD5, MD5Digest.class);
if (testDigest(JCEAlgorithms.JCE_SHA1, SHA1Digest.class))
digests.add(JCEAlgorithms.JCE_SHA1, SHA1Digest.class);
if (testDigest("SHA1", SHA1Digest.class))
digests.add("SHA1", SHA1Digest.class);
if (testDigest("SHA-256", SHA256Digest.class))
digests.add("SHA-256", SHA256Digest.class);
if (testDigest("SHA-384", SHA384Digest.class))
digests.add("SHA-384", SHA384Digest.class);
if (testDigest("SHA-512", SHA512Digest.class))
digests.add("SHA-512", SHA512Digest.class);
}
protected void initializeHmacFactory(ComponentFactory hmacs) {
if (testHMac("hmac-md5", HmacMD5.class))
hmacs.add("hmac-md5", HmacMD5.class);
if (testHMac("hmac-sha1", HmacSha1.class))
hmacs.add("hmac-sha1", HmacSha1.class);
if (testHMac("hmac-md5-96", HmacMD596.class))
hmacs.add("hmac-md5-96", HmacMD596.class);
if (testHMac("hmac-sha1-96", HmacSha196.class))
hmacs.add("hmac-sha1-96", HmacSha196.class);
if (testHMac("hmac-sha256", HmacSha256.class)) {
hmacs.add("hmac-sha256", HmacSha256.class);
hmacs.add("hmac-sha2-256", HmacSha256.class);
hmacs.add("hmac-sha256@ssh.com", HmacSha256.class);
}
if(testHMac("hmac-sha512", HmacSha512.class)) {
hmacs.add("hmac-sha512", HmacSha512.class);
hmacs.add("hmac-sha512@ssh.com", HmacSha512.class);
}
}
protected void initializeKeyExchangeFactory(ComponentFactory keyexchange) {
// sshd has its own version of these classes so they will not be on its
// classpath, this is why we use class.forname
try {
Class<?> DiffieHellmanGroup14Sha1 = Class
.forName("com.sshtools.ssh.components.jce.DiffieHellmanGroup14Sha1");
Class<?> DiffieHellmanGroup1Sha1 = Class
.forName("com.sshtools.ssh.components.jce.DiffieHellmanGroup1Sha1");
Class<?> DiffieHellmanGroupExchangeSha1 = Class
.forName("com.sshtools.ssh.components.jce.DiffieHellmanGroupExchangeSha1");
Class<?> DiffieHellmanGroupExchangeSha256 = Class
.forName("com.sshtools.ssh.components.jce.DiffieHellmanGroupExchangeSha256");
if (testKeyExchangeAlgorithm("diffie-hellman-group14-sha1",
DiffieHellmanGroup14Sha1)) {
keyexchange.add("diffie-hellman-group14-sha1",
DiffieHellmanGroup14Sha1);
}
if (testKeyExchangeAlgorithm("diffie-hellman-group1-sha1",
DiffieHellmanGroup1Sha1)) {
keyexchange.add("diffie-hellman-group1-sha1",
DiffieHellmanGroup1Sha1);
}
if (testKeyExchangeAlgorithm("diffie-hellman-group-exchange-sha1",
DiffieHellmanGroupExchangeSha1)) {
keyexchange.add("diffie-hellman-group-exchange-sha1",
DiffieHellmanGroupExchangeSha1);
}
if (testKeyExchangeAlgorithm(
"diffie-hellman-group-exchange-sha256",
DiffieHellmanGroupExchangeSha256)) {
keyexchange.add("diffie-hellman-group-exchange-sha256",
DiffieHellmanGroupExchangeSha256);
}
keyexchange.add("ecdh-sha2-nistp256", DiffieHellmanEcdhNistp256.class);
keyexchange.add("ecdh-sha2-nistp384", DiffieHellmanEcdhNistp384.class);
// keyexchange.add("ecdh-sha2-nistp521", DiffieHellmanEcdhNistp521.class);
} catch (ClassNotFoundException e) {
// This is expected for SSHD
}
}
protected void initializePublicKeyFactory(ComponentFactory publickeys) {
publickeys.add("ssh-dss", Ssh2DsaPublicKey.class);
publickeys.add("ssh-rsa", Ssh2RsaPublicKey.class);
publickeys.add(SshX509RsaPublicKey.X509V3_SIGN_RSA,
SshX509RsaPublicKey.class);
publickeys.add(SshX509DsaPublicKey.X509V3_SIGN_DSA,
SshX509DsaPublicKey.class);
publickeys.add(SshX509RsaSha1PublicKey.X509V3_SIGN_RSA_SHA1,
SshX509RsaSha1PublicKey.class);
publickeys.add("ecdsa-sha2-nistp256",
Ssh2EcdsaSha2Nist256PublicKey.class);
publickeys.add("ecdsa-sha2-nistp384",
Ssh2EcdsaSha2Nist384PublicKey.class);
publickeys.add("ecdsa-sha2-nistp521",
Ssh2EcdsaSha2Nist521PublicKey.class);
}
protected void initializeSsh2CipherFactory(ComponentFactory ciphers) {
if (testJCECipher("3des-ctr", TripleDesCtr.class)) {
ciphers.add("3des-ctr", TripleDesCtr.class);
}
if (testJCECipher("aes128-ctr", AES128Ctr.class)) {
ciphers.add("aes128-ctr", AES128Ctr.class);
}
if (testJCECipher("aes192-ctr", AES192Ctr.class)) {
ciphers.add("aes192-ctr", AES192Ctr.class);
}
if (testJCECipher("aes256-ctr", AES256Ctr.class)) {
ciphers.add("aes256-ctr", AES256Ctr.class);
}
}
/**
* Install deprecated Counter-Block-Mode ciphers.
* @param ciphers
*/
public void installCBCCiphers(ComponentFactory ciphers) {
if (testJCECipher("3des-cbc", TripleDesCbc.class)) {
ciphers.add("3des-cbc", TripleDesCbc.class);
}
if (testJCECipher("blowfish-cbc", BlowfishCbc.class)) {
ciphers.add("blowfish-cbc", BlowfishCbc.class);
}
if (testJCECipher("aes128-cbc", AES128Cbc.class)) {
ciphers.add("aes128-cbc", AES128Cbc.class);
}
if (testJCECipher("aes192-cbc", AES192Cbc.class)) {
ciphers.add("aes192-cbc", AES192Cbc.class);
}
if (testJCECipher("aes256-cbc", AES256Cbc.class)) {
ciphers.add("aes256-cbc", AES256Cbc.class);
}
}
/**
* Install deprecated ArcFour ciphers
* @param ciphers
*/
public void installArcFourCiphers(ComponentFactory ciphers) {
if (testJCECipher("arcfour", ArcFour.class)) {
ciphers.add("arcfour", ArcFour.class);
}
if (testJCECipher("arcfour128", ArcFour128.class)) {
ciphers.add("arcfour128", ArcFour128.class);
}
if (testJCECipher("arcfour256", ArcFour256.class)) {
ciphers.add("arcfour256", ArcFour256.class);
}
}
private boolean testKeyExchangeAlgorithm(String name,
Class<?> keyExchangeAlgorithmClass) {
String provider = "[unknown]";
Object SshKeyExchangeClient_Instance = null;
try {
String clientId = "SSH-2.0-SOFTWARE_VERSION_COMMENTS";
String serverId = "SSH-2.0-ExampleSSHD_1.2.3_Comments";
byte[] clientKexInit = { 20, 9, 23, -34, -78, 80, 43, 43, -33, -62,
73, 10, 4, 125, -72, -88, -20, 0, 0, 0, 27, 100, 105, 102,
102, 105, 101, 45, 104, 101, 108, 108, 109, 97, 110, 45,
103, 114, 111, 117, 112, 49, 52, 45, 115, 104, 97, 49, 0,
0, 0, 15, 115, 115, 104, 45, 100, 115, 115, 44, 115, 115,
104, 45, 114, 115, 97, 0, 0, 0, 32, 97, 101, 115, 49, 50,
56, 45, 99, 98, 99, 44, 51, 100, 101, 115, 45, 99, 98, 99,
44, 98, 108, 111, 119, 102, 105, 115, 104, 45, 99, 98, 99,
0, 0, 0, 32, 97, 101, 115, 49, 50, 56, 45, 99, 98, 99, 44,
51, 100, 101, 115, 45, 99, 98, 99, 44, 98, 108, 111, 119,
102, 105, 115, 104, 45, 99, 98, 99, 0, 0, 0, 18, 104, 109,
97, 99, 45, 115, 104, 97, 49, 44, 104, 109, 97, 99, 45,
109, 100, 53, 0, 0, 0, 18, 104, 109, 97, 99, 45, 115, 104,
97, 49, 44, 104, 109, 97, 99, 45, 109, 100, 53, 0, 0, 0, 9,
110, 111, 110, 101, 44, 122, 108, 105, 98, 0, 0, 0, 9, 110,
111, 110, 101, 44, 122, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0 };
byte[] serverKexInit = { 20, 23, 119, -40, -10, 11, -1, -102, 84,
-3, 119, 47, -92, 81, 17, -51, -53, 0, 0, 0, 54, 100, 105,
102, 102, 105, 101, 45, 104, 101, 108, 108, 109, 97, 110,
45, 103, 114, 111, 117, 112, 49, 45, 115, 104, 97, 49, 44,
100, 105, 102, 102, 105, 101, 45, 104, 101, 108, 108, 109,
97, 110, 45, 103, 114, 111, 117, 112, 49, 52, 45, 115, 104,
97, 49, 0, 0, 0, 15, 115, 115, 104, 45, 100, 115, 115, 44,
115, 115, 104, 45, 114, 115, 97, 0, 0, 0, 111, 97, 101,
115, 49, 50, 56, 45, 99, 98, 99, 44, 51, 100, 101, 115, 45,
99, 98, 99, 44, 98, 108, 111, 119, 102, 105, 115, 104, 45,
99, 98, 99, 44, 97, 101, 115, 49, 57, 50, 45, 99, 98, 99,
44, 97, 101, 115, 50, 53, 54, 45, 99, 98, 99, 44, 116, 119,
111, 102, 105, 115, 104, 49, 50, 56, 45, 99, 98, 99, 44,
116, 119, 111, 102, 105, 115, 104, 49, 57, 50, 45, 99, 98,
99, 44, 116, 119, 111, 102, 105, 115, 104, 50, 53, 54, 45,
99, 98, 99, 44, 99, 97, 115, 116, 49, 50, 56, 45, 99, 98,
99, 0, 0, 0, 111, 97, 101, 115, 49, 50, 56, 45, 99, 98, 99,
44, 51, 100, 101, 115, 45, 99, 98, 99, 44, 98, 108, 111,
119, 102, 105, 115, 104, 45, 99, 98, 99, 44, 97, 101, 115,
49, 57, 50, 45, 99, 98, 99, 44, 97, 101, 115, 50, 53, 54,
45, 99, 98, 99, 44, 116, 119, 111, 102, 105, 115, 104, 49,
50, 56, 45, 99, 98, 99, 44, 116, 119, 111, 102, 105, 115,
104, 49, 57, 50, 45, 99, 98, 99, 44, 116, 119, 111, 102,
105, 115, 104, 50, 53, 54, 45, 99, 98, 99, 44, 99, 97, 115,
116, 49, 50, 56, 45, 99, 98, 99, 0, 0, 0, 43, 104, 109, 97,
99, 45, 115, 104, 97, 49, 44, 104, 109, 97, 99, 45, 109,
100, 53, 44, 104, 109, 97, 99, 45, 109, 100, 53, 45, 57,
54, 44, 104, 109, 97, 99, 45, 115, 104, 97, 49, 45, 57, 54,
0, 0, 0, 43, 104, 109, 97, 99, 45, 115, 104, 97, 49, 44,
104, 109, 97, 99, 45, 109, 100, 53, 44, 104, 109, 97, 99,
45, 109, 100, 53, 45, 57, 54, 44, 104, 109, 97, 99, 45,
115, 104, 97, 49, 45, 57, 54, 0, 0, 0, 9, 110, 111, 110,
101, 44, 122, 108, 105, 98, 0, 0, 0, 9, 110, 111, 110, 101,
44, 122, 108, 105, 98, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0 };
SshKeyExchangeClient_Instance = keyExchangeAlgorithmClass
.newInstance();
Method test = keyExchangeAlgorithmClass.getMethod(
"performClientExchange", new Class[] { String.class,
String.class, byte[].class, byte[].class });
test.invoke(SshKeyExchangeClient_Instance, new Object[] { clientId,
serverId, clientKexInit, serverKexInit });
} catch (InvocationTargetException e) {
if (e.getCause() instanceof SshException) {
if (e.getCause().getCause() instanceof NoSuchAlgorithmException) {
Log.info(this, " " + name
+ " will not be supported: "
+ e.getCause().getCause().getMessage());
return false;
} else if (e.getCause().getCause() instanceof InvalidAlgorithmParameterException) {
Log.info(this, " " + name
+ " will not be supported: "
+ e.getCause().getCause().getMessage());
return false;
}
}
} catch (Throwable e) {
// a null pointer exception will be caught at the end of the keyex
// call when transport.sendmessage is called, at this point the
// algorithm has not thrown an exception so we ignore this excpected
// exception.
}
try {
Method test = keyExchangeAlgorithmClass.getMethod("getProvider",
new Class[] {});
provider = (String) test.invoke(SshKeyExchangeClient_Instance,
new Object[] {});
} catch (Throwable t) {
}
Log.info(this, " " + name
+ " will be supported using JCEProvider " + provider);
return true;
}
private boolean testJCECipher(String name, Class<?> cls) {
try {
SshCipher c = (SshCipher) cls.newInstance();
byte[] tmp = new byte[1024];
c.init(SshCipher.ENCRYPT_MODE, tmp, tmp);
if (c instanceof AbstractJCECipher)
Log.info(this, " " + name
+ " will be supported using JCE Provider "
+ ((AbstractJCECipher) c).getProvider());
return true;
} catch (Throwable e) {
Log.info(this, " " + name + " will not be supported: "
+ e.getMessage());
return false;
}
}
private boolean testDigest(String name, Class<?> cls) {
try {
Digest c = (Digest) cls.newInstance();
if (c instanceof AbstractDigest)
Log.info(this, " " + name
+ " will be supported using JCE Provider "
+ ((AbstractDigest) c).getProvider());
return true;
} catch (Throwable e) {
Log.info(this, " " + name + " will not be supported: "
+ e.getMessage());
return false;
}
}
private boolean testHMac(String name, Class<?> cls) {
try {
SshHmac c = (SshHmac) cls.newInstance();
byte[] tmp = new byte[1024];
c.init(tmp);
if (c instanceof AbstractHmac)
Log.info(this, " " + name
+ " will be supported using JCE Provider "
+ ((AbstractHmac) c).getProvider());
return true;
} catch (Throwable e) {
Log.info(this, " " + name + " will not be supported: "
+ e.getMessage());
return false;
}
}
}