/** * 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.tls.protocol.handshake; import de.rub.nds.tlsattacker.tls.crypto.ECCUtilsBCWrapper; import de.rub.nds.tlsattacker.tls.constants.HandshakeByteLength; import de.rub.nds.tlsattacker.tls.constants.HandshakeMessageType; import de.rub.nds.tlsattacker.tls.exceptions.InvalidMessageTypeException; import de.rub.nds.tlsattacker.tls.exceptions.WorkflowExecutionException; import de.rub.nds.tlsattacker.tls.constants.EllipticCurveType; import de.rub.nds.tlsattacker.tls.constants.HashAlgorithm; import de.rub.nds.tlsattacker.tls.constants.NamedCurve; import de.rub.nds.tlsattacker.tls.constants.ProtocolVersion; import de.rub.nds.tlsattacker.tls.constants.SignatureAlgorithm; import de.rub.nds.tlsattacker.tls.workflow.TlsContext; import de.rub.nds.tlsattacker.util.ArrayConverter; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.bouncycastle.crypto.params.ECPublicKeyParameters; /** * @author Juraj Somorovsky <juraj.somorovsky@rub.de> */ public class ECDHEServerKeyExchangeHandler extends HandshakeMessageHandler<ECDHEServerKeyExchangeMessage> { private static final Logger LOGGER = LogManager.getLogger(ECDHEServerKeyExchangeHandler.class); public ECDHEServerKeyExchangeHandler(TlsContext tlsContext) { super(tlsContext); this.correctProtocolMessageClass = ECDHEServerKeyExchangeMessage.class; } /** * @param message * @param pointer * @return */ @Override public int parseMessageAction(byte[] message, int pointer) { if (message[pointer] != HandshakeMessageType.SERVER_KEY_EXCHANGE.getValue()) { throw new InvalidMessageTypeException(HandshakeMessageType.SERVER_KEY_EXCHANGE); } protocolMessage.setType(message[pointer]); int currentPointer = pointer + HandshakeByteLength.MESSAGE_TYPE; int nextPointer = currentPointer + HandshakeByteLength.MESSAGE_TYPE_LENGTH; int length = ArrayConverter.bytesToInt(Arrays.copyOfRange(message, currentPointer, nextPointer)); protocolMessage.setLength(length); currentPointer = nextPointer; nextPointer++; EllipticCurveType ct = EllipticCurveType.getCurveType(message[currentPointer]); if (ct != EllipticCurveType.NAMED_CURVE) { throw new UnsupportedOperationException("Currently only named curves are supported"); } protocolMessage.setCurveType(ct.getValue()); currentPointer = nextPointer; nextPointer = currentPointer + NamedCurve.LENGTH; NamedCurve nc = NamedCurve.getNamedCurve(Arrays.copyOfRange(message, currentPointer, nextPointer)); protocolMessage.setNamedCurve(nc.getValue()); currentPointer = nextPointer; nextPointer++; int publicKeyLength = message[currentPointer] & 0xFF; protocolMessage.setPublicKeyLength(publicKeyLength); currentPointer = nextPointer; nextPointer = currentPointer + publicKeyLength; protocolMessage.setPublicKey(Arrays.copyOfRange(message, currentPointer, nextPointer)); byte[] ecParams = ArrayConverter.concatenate(new byte[]{protocolMessage.getCurveType().getValue()}, protocolMessage.getNamedCurve().getValue(), ArrayConverter.intToBytes(protocolMessage .getPublicKeyLength().getValue(), 1), protocolMessage.getPublicKey().getValue()); InputStream is = new ByteArrayInputStream(ecParams); try { ECPublicKeyParameters publicKeyParameters = ECCUtilsBCWrapper.readECParametersWithPublicKey(is); LOGGER.debug("Parsed the following EC domain parameters: "); LOGGER.debug(" Curve order: {}", publicKeyParameters.getParameters().getCurve().getOrder()); LOGGER.debug(" Parameter A: {}", publicKeyParameters.getParameters().getCurve().getA()); LOGGER.debug(" Parameter B: {}", publicKeyParameters.getParameters().getCurve().getB()); LOGGER.debug(" Base point: {} ", publicKeyParameters.getParameters().getG()); LOGGER.debug(" Public key point Q: {} ", publicKeyParameters.getQ()); tlsContext.getEcContext().setServerPublicKeyParameters(publicKeyParameters); if (tlsContext.getProtocolVersion() == ProtocolVersion.DTLS12 || tlsContext.getProtocolVersion() == ProtocolVersion.TLS12) { currentPointer = nextPointer; nextPointer++; HashAlgorithm ha = HashAlgorithm.getHashAlgorithm(message[currentPointer]); protocolMessage.setHashAlgorithm(ha.getValue()); currentPointer = nextPointer; nextPointer++; SignatureAlgorithm sa = SignatureAlgorithm.getSignatureAlgorithm(message[currentPointer]); protocolMessage.setSignatureAlgorithm(sa.getValue()); } currentPointer = nextPointer; nextPointer = currentPointer + HandshakeByteLength.SIGNATURE_LENGTH; int signatureLength = ArrayConverter.bytesToInt(Arrays.copyOfRange(message, currentPointer, nextPointer)); protocolMessage.setSignatureLength(signatureLength); currentPointer = nextPointer; nextPointer = currentPointer + signatureLength; protocolMessage.setSignature(Arrays.copyOfRange(message, currentPointer, nextPointer)); protocolMessage.setCompleteResultingMessage(Arrays.copyOfRange(message, pointer, nextPointer)); return nextPointer; } catch (IOException ex) { // ex.printStackTrace(); throw new WorkflowExecutionException("EC public key parsing failed", ex); } } @Override public byte[] prepareMessageAction() { throw new UnsupportedOperationException("ECDHE message preparation not supported yet."); } }