
org.bouncycastle.jsse.provider.ContextData Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of bctls-fips Show documentation
Show all versions of bctls-fips Show documentation
The Bouncy Castle Java APIs for the TLS, including a JSSE provider. The APIs are designed primarily to be used in conjunction with the BC FIPS provider. The APIs may also be used with other providers although if being used in a FIPS context it is the responsibility of the user to ensure that any other providers used are FIPS certified and used appropriately.
The newest version!
package org.bouncycastle.jsse.provider;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;
import java.util.Vector;
import org.bouncycastle.jsse.BCX509ExtendedKeyManager;
import org.bouncycastle.jsse.BCX509ExtendedTrustManager;
import org.bouncycastle.jsse.java.security.BCAlgorithmConstraints;
import org.bouncycastle.jsse.java.security.BCCryptoPrimitive;
import org.bouncycastle.tls.ProtocolVersion;
import org.bouncycastle.tls.SignatureAndHashAlgorithm;
import org.bouncycastle.tls.TlsUtils;
import org.bouncycastle.tls.crypto.impl.jcajce.JcaTlsCrypto;
final class ContextData
{
private static final Set TLS_CRYPTO_PRIMITIVES_BC = JsseUtils.KEY_AGREEMENT_CRYPTO_PRIMITIVES_BC;
private final boolean fipsMode;
private final JcaTlsCrypto crypto;
private final BCX509ExtendedKeyManager x509KeyManager;
private final BCX509ExtendedTrustManager x509TrustManager;
private final Map supportedCipherSuites;
private final Map supportedProtocols;
private final String[] defaultCipherSuitesClient;
private final String[] defaultCipherSuitesServer;
private final String[] defaultProtocolsClient;
private final String[] defaultProtocolsServer;
private final ProvSSLSessionContext clientSessionContext;
private final ProvSSLSessionContext serverSessionContext;
private final NamedGroupInfo.PerContext namedGroups;
private final SignatureSchemeInfo.PerContext signatureSchemes;
ContextData(boolean fipsMode, JcaTlsCrypto crypto, BCX509ExtendedKeyManager x509KeyManager,
BCX509ExtendedTrustManager x509TrustManager, Map supportedCipherSuites,
Map supportedProtocols, String[] defaultCipherSuitesClient,
String[] defaultCipherSuitesServer, String[] defaultProtocolsClient, String[] defaultProtocolsServer)
{
this.fipsMode = fipsMode;
this.crypto = crypto;
this.x509KeyManager = x509KeyManager;
this.x509TrustManager = x509TrustManager;
this.supportedCipherSuites = supportedCipherSuites;
this.supportedProtocols = supportedProtocols;
this.defaultCipherSuitesClient = defaultCipherSuitesClient;
this.defaultCipherSuitesServer = defaultCipherSuitesServer;
this.defaultProtocolsClient = defaultProtocolsClient;
this.defaultProtocolsServer = defaultProtocolsServer;
this.clientSessionContext = new ProvSSLSessionContext(this);
this.serverSessionContext = new ProvSSLSessionContext(this);
this.namedGroups = NamedGroupInfo.createPerContext(fipsMode, crypto);
this.signatureSchemes = SignatureSchemeInfo.createPerContext(fipsMode, crypto, namedGroups);
}
int[] getActiveCipherSuites(JcaTlsCrypto crypto, ProvSSLParameters sslParameters,
ProtocolVersion[] activeProtocolVersions)
{
String[] enabledCipherSuites = sslParameters.getCipherSuitesArray();
BCAlgorithmConstraints algorithmConstraints = sslParameters.getAlgorithmConstraints();
ProtocolVersion latest = ProtocolVersion.getLatestTLS(activeProtocolVersions);
ProtocolVersion earliest = ProtocolVersion.getEarliestTLS(activeProtocolVersions);
boolean post13Active = TlsUtils.isTLSv13(latest);
boolean pre13Active = !TlsUtils.isTLSv13(earliest);
int[] candidates = new int[enabledCipherSuites.length];
int count = 0;
for (String enabledCipherSuite : enabledCipherSuites)
{
CipherSuiteInfo candidate = supportedCipherSuites.get(enabledCipherSuite);
if (null == candidate)
{
continue;
}
if (candidate.isTLSv13())
{
if (!post13Active)
{
continue;
}
}
else
{
if (!pre13Active)
{
continue;
}
}
if (!algorithmConstraints.permits(TLS_CRYPTO_PRIMITIVES_BC, enabledCipherSuite, null))
{
continue;
}
/*
* TODO[jsse] SunJSSE also checks that the cipher suite is usable for at least one of
* the active protocol versions. Also, if the cipher suite involves a key exchange,
* there must be at least one suitable NamedGroup available.
*/
candidates[count++] = candidate.getCipherSuite();
}
/*
* TODO Move cipher suite management into CipherSuiteInfo (PerConnection/PerContext pattern
* like NamedGroupInfo) to avoid unnecessary repetition of these sorts of checks.
*/
int[] result = TlsUtils.getSupportedCipherSuites(crypto, candidates, 0, count);
if (result.length < 1)
{
// TODO[jsse] Refactor so that this can be an SSLHandshakeException?
throw new IllegalStateException("No usable cipher suites enabled");
}
return result;
}
ProtocolVersion[] getActiveProtocolVersions(ProvSSLParameters sslParameters)
{
// String[] enabledCipherSuites = sslParameters.getCipherSuitesArray();
String[] enabledProtocols = sslParameters.getProtocolsArray();
BCAlgorithmConstraints algorithmConstraints = sslParameters.getAlgorithmConstraints();
SortedSet result = new TreeSet(new Comparator()
{
public int compare(ProtocolVersion o1, ProtocolVersion o2)
{
return o1.isLaterVersionOf(o2) ? -1 : o2.isLaterVersionOf(o1) ? 1 : 0;
}
});
for (String enabledProtocol : enabledProtocols)
{
ProtocolVersion candidate = supportedProtocols.get(enabledProtocol);
if (null == candidate)
{
continue;
}
if (!algorithmConstraints.permits(TLS_CRYPTO_PRIMITIVES_BC, enabledProtocol, null))
{
continue;
}
/*
* TODO[jsse] SunJSSE also checks that there is at least one "activatable" cipher suite
* that could be used for this protocol version.
*/
result.add(candidate);
}
if (result.isEmpty())
{
// TODO[jsse] Refactor so that this can be an SSLHandshakeException?
throw new IllegalStateException("No usable protocols enabled");
}
return result.toArray(new ProtocolVersion[result.size()]);
}
ProvSSLSessionContext getClientSessionContext()
{
return clientSessionContext;
}
JcaTlsCrypto getCrypto()
{
return crypto;
}
String[] getDefaultCipherSuites(boolean isClient)
{
return implGetDefaultCipherSuites(isClient).clone();
}
String[] getDefaultProtocols(boolean isClient)
{
return implGetDefaultProtocols(isClient).clone();
}
ProvSSLParameters getDefaultSSLParameters(boolean isClient)
{
return new ProvSSLParameters(this, implGetDefaultCipherSuites(isClient), implGetDefaultProtocols(isClient));
}
ProvSSLParameters getSupportedSSLParameters(boolean isClient)
{
return new ProvSSLParameters(this, getSupportedCipherSuites(), getSupportedProtocols());
}
NamedGroupInfo.PerConnection getNamedGroupsClient(ProvSSLParameters sslParameters,
ProtocolVersion[] activeProtocolVersions)
{
return NamedGroupInfo.createPerConnectionClient(namedGroups, sslParameters, activeProtocolVersions);
}
NamedGroupInfo.PerConnection getNamedGroupsServer(ProvSSLParameters sslParameters,
ProtocolVersion negotiatedVersion)
{
return NamedGroupInfo.createPerConnectionServer(namedGroups, sslParameters, negotiatedVersion);
}
ProvSSLSessionContext getServerSessionContext()
{
return serverSessionContext;
}
SignatureSchemeInfo.PerConnection getSignatureSchemesClient(ProvSSLParameters sslParameters,
ProtocolVersion[] activeProtocolVersions, NamedGroupInfo.PerConnection namedGroups)
{
return SignatureSchemeInfo.createPerConnectionClient(signatureSchemes, sslParameters, activeProtocolVersions,
namedGroups);
}
SignatureSchemeInfo.PerConnection getSignatureSchemesServer(ProvSSLParameters sslParameters,
ProtocolVersion negotiatedVersion, NamedGroupInfo.PerConnection namedGroups)
{
return SignatureSchemeInfo.createPerConnectionServer(signatureSchemes, sslParameters, negotiatedVersion,
namedGroups);
}
List getSignatureSchemes(Vector sigAndHashAlgs)
{
return SignatureSchemeInfo.getSignatureSchemes(signatureSchemes, sigAndHashAlgs);
}
String[] getSupportedCipherSuites()
{
return JsseUtils.getKeysArray(supportedCipherSuites);
}
String[] getSupportedCipherSuites(String[] cipherSuites)
{
if (null == cipherSuites)
{
throw new NullPointerException("'cipherSuites' cannot be null");
}
ArrayList result = new ArrayList(cipherSuites.length);
for (String cipherSuite : cipherSuites)
{
if (TlsUtils.isNullOrEmpty(cipherSuite))
{
throw new IllegalArgumentException("'cipherSuites' cannot contain null or empty string elements");
}
if (supportedCipherSuites.containsKey(cipherSuite))
{
result.add(cipherSuite);
}
}
// NOTE: This method must always return a copy, so no fast path when all supported
return JsseUtils.getArray(result);
}
String[] getSupportedProtocols()
{
return JsseUtils.getKeysArray(supportedProtocols);
}
BCX509ExtendedKeyManager getX509KeyManager()
{
return x509KeyManager;
}
BCX509ExtendedTrustManager getX509TrustManager()
{
return x509TrustManager;
}
boolean isFipsMode()
{
return fipsMode;
}
boolean isSupportedProtocols(String[] protocols)
{
if (protocols == null)
{
return false;
}
for (String protocol : protocols)
{
if (protocol == null || !supportedProtocols.containsKey(protocol))
{
return false;
}
}
return true;
}
void updateDefaultSSLParameters(ProvSSLParameters sslParameters, boolean isClient)
{
if (sslParameters.getCipherSuitesArray() == implGetDefaultCipherSuites(!isClient))
{
sslParameters.setCipherSuitesArray(implGetDefaultCipherSuites(isClient));
}
if (sslParameters.getProtocolsArray() == implGetDefaultProtocols(!isClient))
{
sslParameters.setProtocolsArray(implGetDefaultProtocols(isClient));
}
}
String validateNegotiatedCipherSuite(ProvSSLParameters sslParameters, int cipherSuite)
{
// NOTE: The redundancy among these various checks is intentional
String name = ProvSSLContextSpi.getCipherSuiteName(cipherSuite);
if (null == name
|| !JsseUtils.contains(sslParameters.getCipherSuitesArray(), name)
|| !sslParameters.getAlgorithmConstraints().permits(TLS_CRYPTO_PRIMITIVES_BC, name, null)
|| !supportedCipherSuites.containsKey(name))
{
throw new IllegalStateException("SSL connection negotiated unsupported ciphersuite: " + cipherSuite);
}
return name;
}
String validateNegotiatedProtocol(ProvSSLParameters sslParameters, ProtocolVersion protocol)
{
// NOTE: The redundancy among these various checks is intentional
String name = ProvSSLContextSpi.getProtocolVersionName(protocol);
if (null == name
|| !JsseUtils.contains(sslParameters.getProtocolsArray(), name)
|| !sslParameters.getAlgorithmConstraints().permits(TLS_CRYPTO_PRIMITIVES_BC, name, null)
|| !supportedProtocols.containsKey(name))
{
throw new IllegalStateException("SSL connection negotiated unsupported protocol: " + protocol);
}
return name;
}
private String[] implGetDefaultCipherSuites(boolean isClient)
{
return isClient ? defaultCipherSuitesClient : defaultCipherSuitesServer;
}
private String[] implGetDefaultProtocols(boolean isClient)
{
return isClient ? defaultProtocolsClient : defaultProtocolsServer;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy