/** * 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.AlgorithmResolver; import de.rub.nds.tlsattacker.tls.constants.CipherAlgorithm; import de.rub.nds.tlsattacker.tls.constants.CipherSuite; import de.rub.nds.tlsattacker.tls.constants.KeyExchangeAlgorithm; import de.rub.nds.tlsattacker.tls.constants.MacAlgorithm; import de.rub.nds.tlsattacker.tls.constants.PRFAlgorithm; import de.rub.nds.tlsattacker.tls.constants.ProtocolVersion; import java.security.interfaces.DSAPublicKey; import java.security.interfaces.ECPublicKey; import java.security.interfaces.RSAPublicKey; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; /** * * @author Juraj Somorovsky - juraj.somorovsky@rub.de */ public class CryptoTest extends HandshakeTest { private final HashMap<ProtocolVersion, List<CipherSuite>> supportedCipherSuites; private final Set<CipherSuite> allSupportedCipherSuites; private final Set<KeyExchangeAlgorithm> supportedKeyExchangeAlgorithms; private final Set<PRFAlgorithm> supportedPRFAlgorithms; private final Set<CipherAlgorithm> supportedCipherAlgorithms; private final Set<MacAlgorithm> supportedMacAlgorithms; /** * Minimum size of the EC certificate provided by the server. ECDHE keys are * not considered here */ private int minimumECKeySize; private int minimumDHGroupSize; private int minimumRSAKeySize; public CryptoTest(ConfigHandler configHandler, TestServerConfig serverConfig) { super(configHandler, serverConfig); supportedCipherSuites = new HashMap<>(); allSupportedCipherSuites = new HashSet<>(); supportedKeyExchangeAlgorithms = new HashSet<>(); supportedPRFAlgorithms = new HashSet<>(); supportedCipherAlgorithms = new HashSet<>(); supportedMacAlgorithms = new HashSet<>(); } @Override public void startTests() { for (ProtocolVersion pv : ProtocolVersion.values()) { if (pv == ProtocolVersion.DTLS10 || pv == ProtocolVersion.DTLS12) { continue; } for (CipherSuite cs : CipherSuite.values()) { serverConfig.setProtocolVersion(pv); serverConfig.setCipherSuites(Collections.singletonList(cs)); boolean success = false; try { success = executeHandshake(); if (success) { analyzeHandshake(pv, cs); } } catch (Exception ex) { LOGGER.error(ex.getLocalizedMessage()); LOGGER.debug(ex.getLocalizedMessage(), ex); } } } buildResultString(); } private void analyzeHandshake(ProtocolVersion pv, CipherSuite cs) { if (!supportedCipherSuites.containsKey(pv)) { supportedCipherSuites.put(pv, new LinkedList<CipherSuite>()); } supportedCipherSuites.get(pv).add(cs); allSupportedCipherSuites.add(cs); supportedCipherAlgorithms.add(AlgorithmResolver.getCipher(cs)); supportedKeyExchangeAlgorithms.add(AlgorithmResolver.getKeyExchangeAlgorithm(cs)); supportedMacAlgorithms.add(AlgorithmResolver.getMacAlgorithm(cs)); supportedPRFAlgorithms.add(AlgorithmResolver.getPRFAlgorithm(pv, cs)); if (lastTlsContext.getServerDHParameters() != null) { LOGGER.info("DH parameter public key size: {}", lastTlsContext.getServerDHParameters().getPublicKey().getY().bitLength()); int groupSize = lastTlsContext.getServerDHParameters().getPublicKey().getParameters().getP().bitLength(); if (minimumDHGroupSize == 0 || groupSize < minimumDHGroupSize) { minimumDHGroupSize = groupSize; } } if (lastTlsContext.getX509ServerCertificateObject() != null) { String algorithm = lastTlsContext.getX509ServerCertificateObject().getPublicKey().getAlgorithm(); switch (algorithm) { case "RSA": RSAPublicKey rsaPK = (RSAPublicKey) lastTlsContext.getX509ServerCertificateObject().getPublicKey(); int rsaSize = rsaPK.getModulus().bitLength(); LOGGER.info("RSA certificate public key size: {}", rsaSize); if (minimumRSAKeySize == 0 || rsaSize < minimumRSAKeySize) { minimumRSAKeySize = rsaSize; } break; case "EC": ECPublicKey ecPK = (ECPublicKey) lastTlsContext.getX509ServerCertificateObject().getPublicKey(); int ecSize = ecPK.getParams().getCurve().getField().getFieldSize(); LOGGER.info("ECDSA certificate public key size: {}" + ecSize); if (minimumECKeySize == 0 || ecSize < minimumECKeySize) { minimumECKeySize = ecSize; } break; case "DSA": DSAPublicKey dhPK = (DSAPublicKey) lastTlsContext.getX509ServerCertificateObject().getPublicKey(); int dhSize = dhPK.getParams().getP().bitLength(); LOGGER.info("DSA certificate public key size: " + dhSize); if (minimumDHGroupSize == 0 || dhSize < minimumDHGroupSize) { minimumDHGroupSize = dhSize; } break; default: LOGGER.error("Unsupported key algorithm from in the certificate: {}", algorithm); } } } private void buildResultString() { StringBuilder sb = new StringBuilder("\n Supported cipher suites: "); for (ProtocolVersion pv : supportedCipherSuites.keySet()) { if (supportedCipherSuites.containsKey(pv)) { sb.append("\n ").append(pv.toString()).append(": ").append(ciphersToString(supportedCipherSuites.get(pv))); } } sb.append("\n Supported ciphers: "); for (CipherAlgorithm ca : supportedCipherAlgorithms) { sb.append(ca).append(", "); } sb.append("\n Supported key exchange algorithms: "); for (KeyExchangeAlgorithm ke : supportedKeyExchangeAlgorithms) { sb.append(ke).append(", "); } sb.append("\n Supported MAC algorithms: "); for (MacAlgorithm ma : supportedMacAlgorithms) { sb.append(ma).append(", "); } sb.append("\n Supported PRF algorithms: "); for (PRFAlgorithm prf : supportedPRFAlgorithms) { sb.append(prf).append(", "); } sb.append("\n Key sizes (0 if not provided):"); sb.append("\n Minimum RSA key size: ").append(minimumRSAKeySize); sb.append("\n Minimum EC key size: ").append(minimumECKeySize); sb.append("\n Minimum DH group size: ").append(minimumDHGroupSize); if (minimumDHGroupSize == 0) { if (supportedKeyExchangeAlgorithms.contains(KeyExchangeAlgorithm.DHE_RSA) || supportedKeyExchangeAlgorithms.contains(KeyExchangeAlgorithm.DHE_DSS) || supportedKeyExchangeAlgorithms.contains(KeyExchangeAlgorithm.DHE_PSK)) { sb.append(" (It is possible that the request timed out and the server was " + "not able to generate a new ephemeral DH key on time. Try to " + "increase the TLS timeout with the -tls_timeout parameter.)"); } } result = sb.toString(); } private String ciphersToString(List<CipherSuite> ciphers) { String output = ""; for (CipherSuite cs : ciphers) { output = output + cs.name() + " "; } return output; } public HashMap<ProtocolVersion, List<CipherSuite>> getSupportedCipherSuites() { return supportedCipherSuites; } public Set<CipherSuite> getAllSupportedCipherSuites() { return allSupportedCipherSuites; } public Set<KeyExchangeAlgorithm> getSupportedKeyExchangeAlgorithms() { return supportedKeyExchangeAlgorithms; } public Set<PRFAlgorithm> getSupportedPRFAlgorithms() { return supportedPRFAlgorithms; } public Set<CipherAlgorithm> getSupportedCipherAlgorithms() { return supportedCipherAlgorithms; } public Set<MacAlgorithm> getSupportedMacAlgorithms() { return supportedMacAlgorithms; } @Override public void fillTlsPeerProperties(TlsPeerProperties properties) { properties.setMacAlgorithms(supportedMacAlgorithms); properties.setCiphers(supportedCipherAlgorithms); properties.setMinimumDhGroupSize(minimumDHGroupSize); properties.setMinimumEcdhGroupSize(minimumECKeySize); properties.setMinimumRsaBits(minimumRSAKeySize); } }