/**
* 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.constants.AlgorithmResolver;
import de.rub.nds.tlsattacker.tls.constants.ConnectionEnd;
import de.rub.nds.tlsattacker.tls.crypto.PseudoRandomFunction;
import de.rub.nds.tlsattacker.tls.exceptions.InvalidMessageTypeException;
import de.rub.nds.tlsattacker.tls.constants.HandshakeByteLength;
import de.rub.nds.tlsattacker.tls.constants.HandshakeMessageType;
import de.rub.nds.tlsattacker.tls.constants.PRFAlgorithm;
import de.rub.nds.tlsattacker.tls.workflow.TlsContext;
import de.rub.nds.tlsattacker.util.ArrayConverter;
import java.util.Arrays;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/**
* @author Juraj Somorovsky <juraj.somorovsky@rub.de>
* @author Philip Riese <philip.riese@rub.de>
*/
public class FinishedHandler extends HandshakeMessageHandler<FinishedMessage> {
private static final Logger LOGGER = LogManager.getLogger(FinishedHandler.class);
public FinishedHandler(TlsContext tlsContext) {
super(tlsContext);
this.correctProtocolMessageClass = FinishedMessage.class;
}
@Override
public byte[] prepareMessageAction() {
// protocolMessage.setType(HandshakeMessageType.FINISHED.getValue());
byte[] masterSecret = tlsContext.getMasterSecret();
byte[] handshakeMessagesHash = tlsContext.getDigest().digest();
PRFAlgorithm prfAlgorithm = AlgorithmResolver.getPRFAlgorithm(tlsContext.getProtocolVersion(),
tlsContext.getSelectedCipherSuite());
byte[] verifyData;
if (tlsContext.getMyConnectionEnd() == ConnectionEnd.SERVER) {
verifyData = PseudoRandomFunction.compute(prfAlgorithm, masterSecret,
PseudoRandomFunction.SERVER_FINISHED_LABEL, handshakeMessagesHash, HandshakeByteLength.VERIFY_DATA);
} else {
verifyData = PseudoRandomFunction.compute(prfAlgorithm, masterSecret,
PseudoRandomFunction.CLIENT_FINISHED_LABEL, handshakeMessagesHash, HandshakeByteLength.VERIFY_DATA);
}
protocolMessage.setVerifyData(verifyData);
LOGGER.debug("Computed verify data: {}", ArrayConverter.bytesToHexString(verifyData));
byte[] result = protocolMessage.getVerifyData().getValue();
protocolMessage.setLength(result.length);
long header = (protocolMessage.getHandshakeMessageType().getValue() << 24)
+ protocolMessage.getLength().getValue();
protocolMessage.setCompleteResultingMessage(ArrayConverter.concatenate(
ArrayConverter.longToUint32Bytes(header), result));
return protocolMessage.getCompleteResultingMessage().getValue();
}
@Override
public int parseMessageAction(byte[] message, int pointer) {
FinishedMessage finishedMessage = (FinishedMessage) protocolMessage;
if (message[pointer] != HandshakeMessageType.FINISHED.getValue()) {
throw new InvalidMessageTypeException("This is not a server finished message");
}
finishedMessage.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));
finishedMessage.setLength(length);
currentPointer = nextPointer;
nextPointer = currentPointer + length;
byte[] verifyData = Arrays.copyOfRange(message, currentPointer, nextPointer);
finishedMessage.setVerifyData(verifyData);
protocolMessage.setCompleteResultingMessage(Arrays.copyOfRange(message, pointer, nextPointer));
return nextPointer;
}
}