/**
* 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 java.util.Arrays;
import java.util.LinkedList;
import de.rub.nds.tlsattacker.tls.constants.ClientCertificateType;
import de.rub.nds.tlsattacker.tls.constants.HandshakeByteLength;
import de.rub.nds.tlsattacker.tls.constants.HandshakeMessageType;
import de.rub.nds.tlsattacker.tls.constants.HashAlgorithm;
import de.rub.nds.tlsattacker.tls.constants.SignatureAlgorithm;
import de.rub.nds.tlsattacker.tls.constants.SignatureAndHashAlgorithm;
import de.rub.nds.tlsattacker.tls.exceptions.InvalidMessageTypeException;
import de.rub.nds.tlsattacker.tls.workflow.TlsContext;
import de.rub.nds.tlsattacker.util.ArrayConverter;
/**
* @author Juraj Somorovsky <juraj.somorovsky@rub.de>
* @author Philip Riese <philip.riese@rub.de>
*/
/**
* @param <HandshakeMessage>
*/
public class CertificateRequestHandler<Message extends CertificateRequestMessage> extends
HandshakeMessageHandler<Message> {
@SuppressWarnings("unchecked")
public CertificateRequestHandler(TlsContext tlsContext) {
super(tlsContext);
this.correctProtocolMessageClass = (Class<? extends Message>) CertificateRequestMessage.class;
}
@Override
public byte[] prepareMessageAction() {
// TODO parse Arguments from Console and set properties with
// Confighandler to support more Certificate types
byte[] clientCertificateTypes = { ClientCertificateType.RSA_SIGN.getValue() };
protocolMessage.setClientCertificateTypes(clientCertificateTypes);
int clientCertificateTypesCount = protocolMessage.getClientCertificateTypes().getValue().length;
protocolMessage.setClientCertificateTypesCount(clientCertificateTypesCount);
byte[] signatureAndHashAlgorithms = new SignatureAndHashAlgorithm(SignatureAlgorithm.RSA, HashAlgorithm.SHA512)
.getByteValue();
signatureAndHashAlgorithms = ArrayConverter.concatenate(signatureAndHashAlgorithms,
new SignatureAndHashAlgorithm(SignatureAlgorithm.RSA, HashAlgorithm.SHA384).getByteValue(),
new SignatureAndHashAlgorithm(SignatureAlgorithm.RSA, HashAlgorithm.SHA256).getByteValue(),
new SignatureAndHashAlgorithm(SignatureAlgorithm.RSA, HashAlgorithm.SHA224).getByteValue(),
new SignatureAndHashAlgorithm(SignatureAlgorithm.RSA, HashAlgorithm.SHA1).getByteValue(),
new SignatureAndHashAlgorithm(SignatureAlgorithm.RSA, HashAlgorithm.MD5).getByteValue());
protocolMessage.setSignatureHashAlgorithms(signatureAndHashAlgorithms);
int signatureAndHashAlgorithmsCount = protocolMessage.getSignatureHashAlgorithms().getValue().length;
protocolMessage.setSignatureHashAlgorithmsLength(signatureAndHashAlgorithmsCount);
int distinguishedNamesLength = 0;
protocolMessage.setDistinguishedNamesLength(distinguishedNamesLength);
byte[] result = ArrayConverter.concatenate(ArrayConverter.intToBytes(protocolMessage
.getClientCertificateTypesCount().getValue(), 1), protocolMessage.getClientCertificateTypes()
.getValue(), ArrayConverter.intToBytes(protocolMessage.getSignatureHashAlgorithmsLength().getValue(),
HandshakeByteLength.SIGNATURE_HASH_ALGORITHMS_LENGTH), protocolMessage.getSignatureHashAlgorithms()
.getValue(), ArrayConverter.intToBytes(protocolMessage.getDistinguishedNamesLength().getValue(),
HandshakeByteLength.DISTINGUISHED_NAMES_LENGTH));
protocolMessage.setLength(result.length);
long header = (HandshakeMessageType.CERTIFICATE_REQUEST.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) {
if (message[pointer] != HandshakeMessageType.CERTIFICATE_REQUEST.getValue()) {
throw new InvalidMessageTypeException("This is not a Certificate Request message");
}
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 = currentPointer + 1;
int certificateTypesCount = ArrayConverter.bytesToInt(Arrays.copyOfRange(message, currentPointer, nextPointer));
protocolMessage.setClientCertificateTypesCount(certificateTypesCount);
currentPointer = nextPointer;
nextPointer = currentPointer + certificateTypesCount;
protocolMessage.setClientCertificateTypes(Arrays.copyOfRange(message, currentPointer, nextPointer));
currentPointer = nextPointer;
nextPointer = currentPointer + HandshakeByteLength.SIGNATURE_HASH_ALGORITHMS_LENGTH;
int signatureHashAlgorithmsLength = ArrayConverter.bytesToInt(Arrays.copyOfRange(message, currentPointer,
nextPointer));
protocolMessage.setSignatureHashAlgorithmsLength(signatureHashAlgorithmsLength);
currentPointer = nextPointer;
nextPointer = currentPointer + signatureHashAlgorithmsLength;
protocolMessage.setSignatureHashAlgorithms(Arrays.copyOfRange(message, currentPointer, nextPointer));
currentPointer = nextPointer;
LinkedList<SignatureAndHashAlgorithm> signatureAndHashAlgorithms = new LinkedList<>();
for (int i = 0; i < protocolMessage.getSignatureHashAlgorithmsLength().getValue() / 2; i++) {
SignatureAndHashAlgorithm sha = SignatureAndHashAlgorithm.getSignatureAndHashAlgorithm(Arrays.copyOfRange(
protocolMessage.getSignatureHashAlgorithms().getValue(), i * 2, i * 2 + 2));
signatureAndHashAlgorithms.add(sha);
}
tlsContext.setSupportedSignatureAndHashAlgorithms(signatureAndHashAlgorithms);
nextPointer = currentPointer + HandshakeByteLength.DISTINGUISHED_NAMES_LENGTH;
int distinguishedNamesLength = ArrayConverter.bytesToInt(Arrays.copyOfRange(message, currentPointer,
nextPointer));
protocolMessage.setDistinguishedNamesLength(distinguishedNamesLength);
currentPointer = nextPointer;
nextPointer = currentPointer + distinguishedNamesLength;
protocolMessage.setDistinguishedNames(Arrays.copyOfRange(message, currentPointer, nextPointer));
currentPointer = nextPointer;
protocolMessage.setCompleteResultingMessage(Arrays.copyOfRange(message, pointer, nextPointer));
return currentPointer;
}
}