/**
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
*
* Copyright 2014-2016 Ruhr University Bochum / Hackmanit GmbH
*
* Licensed under Apache License 2.0
* http://www.apache.org/licenses/LICENSE-2.0
*/
package de.rub.nds.tlsattacker.testtls.impl;
import de.rub.nds.tlsattacker.testtls.config.TestServerConfig;
import de.rub.nds.tlsattacker.testtls.policy.TlsPeerProperties;
import de.rub.nds.tlsattacker.tls.config.ConfigHandler;
import de.rub.nds.tlsattacker.tls.constants.CipherSuite;
import de.rub.nds.tlsattacker.tls.constants.ConnectionEnd;
import de.rub.nds.tlsattacker.tls.constants.HandshakeMessageType;
import de.rub.nds.tlsattacker.tls.constants.ProtocolVersion;
import de.rub.nds.tlsattacker.tls.exceptions.ConfigurationException;
import de.rub.nds.tlsattacker.tls.protocol.ArbitraryMessage;
import de.rub.nds.tlsattacker.tls.protocol.handshake.ClientHelloMessage;
import de.rub.nds.tlsattacker.tls.protocol.handshake.ServerHelloMessage;
import de.rub.nds.tlsattacker.tls.workflow.TlsContext;
import de.rub.nds.tlsattacker.tls.workflow.WorkflowConfigurationFactory;
import de.rub.nds.tlsattacker.tls.workflow.WorkflowExecutor;
import de.rub.nds.tlsattacker.tls.workflow.WorkflowTrace;
import de.rub.nds.tlsattacker.transport.TransportHandler;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
*
* @author Juraj Somorovsky - juraj.somorovsky@rub.de
*/
public class CipherSuiteOrderTest extends HandshakeTest {
private boolean serverSupportsCipherSuitePreference;
private final Set<CipherSuite> supportedCipherSuites;
private ProtocolVersion currentProtocolVersion;
public CipherSuiteOrderTest(ConfigHandler configHandler, TestServerConfig serverConfig) {
super(configHandler, serverConfig);
supportedCipherSuites = new HashSet<>();
}
@Override
public void startTests() {
collectCipherSuites();
if (supportedCipherSuites.size() > 1) {
try {
List<CipherSuite> list = new ArrayList<>(supportedCipherSuites);
serverConfig.setCipherSuites(list);
serverConfig.setProtocolVersion(currentProtocolVersion);
CipherSuite cs1 = getSelectedCipherSuite();
Collections.reverse(list);
serverConfig.setCipherSuites(list);
CipherSuite cs2 = getSelectedCipherSuite();
if(cs2 == cs1) {
serverSupportsCipherSuitePreference = true;
}
} catch (Exception ex) {
LOGGER.info(ex.getLocalizedMessage());
LOGGER.debug(ex.getLocalizedMessage(), ex);
result = "\n Server cipher suite selection cannot be recognized";
}
result = "\n Server uses own cipher suite preferences: " + serverSupportsCipherSuitePreference;
} else {
result = "\n Server cipher suite selection cannot be recognized (lees than 2 cipher suites compatible)";
}
}
private void collectCipherSuites() {
for (ProtocolVersion pv : ProtocolVersion.values()) {
if (pv == ProtocolVersion.DTLS10 || pv == ProtocolVersion.DTLS12) {
continue;
}
currentProtocolVersion = pv;
for (CipherSuite cs : CipherSuite.values()) {
serverConfig.setProtocolVersion(pv);
serverConfig.setCipherSuites(Collections.singletonList(cs));
boolean success = false;
try {
success = executeHandshake();
} catch (Exception ex) {
LOGGER.info(ex.getLocalizedMessage());
LOGGER.debug(ex.getLocalizedMessage(), ex);
}
if (success) {
supportedCipherSuites.add(cs);
if (supportedCipherSuites.size() > 1) {
return;
}
}
}
}
}
CipherSuite getSelectedCipherSuite() {
TransportHandler transportHandler = configHandler.initializeTransportHandler(serverConfig);
TlsContext tlsContext = configHandler.initializeTlsContext(serverConfig);
tlsContext.setProtocolVersion(serverConfig.getProtocolVersion());
tlsContext.setSelectedCipherSuite(serverConfig.getCipherSuites().get(0));
WorkflowTrace workflowTrace = new WorkflowTrace();
ClientHelloMessage ch = new ClientHelloMessage(ConnectionEnd.CLIENT);
workflowTrace.add(ch);
workflowTrace.add(new ArbitraryMessage());
ch.setSupportedCipherSuites(serverConfig.getCipherSuites());
ch.setSupportedCompressionMethods(serverConfig.getCompressionMethods());
WorkflowConfigurationFactory.initializeClientHelloExtensions(serverConfig, ch);
tlsContext.setWorkflowTrace(workflowTrace);
WorkflowConfigurationFactory.initializeProtocolMessageOrder(tlsContext);
WorkflowExecutor workflowExecutor = configHandler.initializeWorkflowExecutor(transportHandler, tlsContext);
workflowExecutor.executeWorkflow();
transportHandler.closeConnection();
if(workflowTrace.containsHandshakeMessage(HandshakeMessageType.SERVER_HELLO)) {
ServerHelloMessage shm = (ServerHelloMessage) workflowTrace.getFirstHandshakeMessage(HandshakeMessageType.SERVER_HELLO);
return CipherSuite.getCipherSuite(shm.getSelectedCipherSuite().getValue());
}
throw new ConfigurationException("No ServerHello message found");
}
@Override
public void fillTlsPeerProperties(TlsPeerProperties properties) {
properties.setUsingCiphersuitePreferenes(serverSupportsCipherSuitePreference);
}
}