/**
* 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 static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.ArrayList;
import java.util.List;
import org.junit.Test;
import de.rub.nds.tlsattacker.tls.constants.CipherSuite;
import de.rub.nds.tlsattacker.tls.constants.CompressionMethod;
import de.rub.nds.tlsattacker.tls.constants.ExtensionType;
import de.rub.nds.tlsattacker.tls.constants.HandshakeMessageType;
import de.rub.nds.tlsattacker.tls.constants.HeartbeatMode;
import de.rub.nds.tlsattacker.tls.constants.NamedCurve;
import de.rub.nds.tlsattacker.tls.constants.ProtocolVersion;
import de.rub.nds.tlsattacker.tls.protocol.extension.EllipticCurvesExtensionMessage;
import de.rub.nds.tlsattacker.tls.protocol.extension.ExtensionMessage;
import de.rub.nds.tlsattacker.tls.protocol.extension.HeartbeatExtensionMessage;
import de.rub.nds.tlsattacker.tls.workflow.TlsContext;
import de.rub.nds.tlsattacker.util.ArrayConverter;
import static org.junit.Assert.*;
/**
* @author Juraj Somorovsky <juraj.somorovsky@rub.de>
* @author Philip Riese <philip.riese@rub.de>
*/
public class ServerHelloHandlerTest {
static byte[] serverKeyExchangeWithoutExtensionBytes = ArrayConverter
.hexStringToByteArray("02000046030354cf6dcf922b63e8cb6af7527c6520f727d526b178ecf3218027ccf8bb125d5720682200"
+ "00ba8c0f774ba7de9f5cdbfdf364d81e28f6f68502cd596792769be4c0c01300");
static byte[] serverKeyExchangeWithHeartbeatBytes = ArrayConverter
.hexStringToByteArray("0200004D030354cf6dcf922b63e8cb6af7527c6520f727d526b178ecf3218027ccf8bb125d5720682200"
+ "00ba8c0f774ba7de9f5cdbfdf364d81e28f6f68502cd596792769be4c0c013000005000F000101");
ServerHelloHandler handler;
TlsContext tlsContext;
public ServerHelloHandlerTest() {
tlsContext = new TlsContext();
tlsContext.setProtocolVersion(ProtocolVersion.TLS12);
handler = new ServerHelloHandler(tlsContext);
}
/**
* Test of parseMessageAction method, of class ServerHelloHandler.
*/
@Test
public void testParseMessage() {
handler.initializeProtocolMessage();
int endPointer = handler.parseMessageAction(serverKeyExchangeWithoutExtensionBytes, 0);
ServerHelloMessage message = (ServerHelloMessage) handler.getProtocolMessage();
assertEquals("Message type must be ServerHello", HandshakeMessageType.SERVER_HELLO,
message.getHandshakeMessageType());
assertEquals("Message length must be 70", new Integer(70), message.getLength().getValue());
assertEquals("Protocol version must be TLS 1.2", ProtocolVersion.TLS12, tlsContext.getProtocolVersion());
assertArrayEquals(
"Server Session ID",
ArrayConverter.hexStringToByteArray("68220000ba8c0f774ba7de9f5cdbfdf364d81e28f6f68502cd596792769be4c0"),
message.getSessionId().getValue());
assertArrayEquals(
"Server Random",
ArrayConverter.hexStringToByteArray("54cf6dcf922b63e8cb6af7527c6520f727d526b178ecf3218027ccf8bb125d57"),
tlsContext.getServerRandom());
assertEquals("Ciphersuite must be TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tlsContext.getSelectedCipherSuite());
assertEquals("Compression must be null", CompressionMethod.NULL, tlsContext.getCompressionMethod());
assertEquals("The pointer has to return the length of this message + starting position",
serverKeyExchangeWithoutExtensionBytes.length, endPointer);
}
/**
* Test of parseMessageAction method, of class ServerHelloHandler.
*/
@Test
public void testParseMessageWithExtensions() {
handler.initializeProtocolMessage();
int endPointer = handler.parseMessageAction(serverKeyExchangeWithHeartbeatBytes, 0);
ServerHelloMessage message = (ServerHelloMessage) handler.getProtocolMessage();
assertEquals("Message type must be ServerHello", HandshakeMessageType.SERVER_HELLO,
message.getHandshakeMessageType());
assertEquals("Message length must be 77", new Integer(77), message.getLength().getValue());
assertEquals("Protocol version must be TLS 1.2", ProtocolVersion.TLS12, tlsContext.getProtocolVersion());
assertArrayEquals(
"Server Session ID",
ArrayConverter.hexStringToByteArray("68220000ba8c0f774ba7de9f5cdbfdf364d81e28f6f68502cd596792769be4c0"),
message.getSessionId().getValue());
assertArrayEquals(
"Server Random",
ArrayConverter.hexStringToByteArray("54cf6dcf922b63e8cb6af7527c6520f727d526b178ecf3218027ccf8bb125d57"),
tlsContext.getServerRandom());
assertEquals("Ciphersuite must be TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA, tlsContext.getSelectedCipherSuite());
assertEquals("Compression must be null", CompressionMethod.NULL, tlsContext.getCompressionMethod());
assertTrue("Extension must be Heartbeat", message.containsExtension(ExtensionType.HEARTBEAT));
assertEquals("The pointer has to return the length of this message + starting position",
serverKeyExchangeWithHeartbeatBytes.length, endPointer);
}
/**
* Test of prepareMessageAction method, of class ServerHelloHandler.
*/
@Test
public void testPrepareMessage() {
handler.setProtocolMessage(new ServerHelloMessage());
ServerHelloMessage message = (ServerHelloMessage) handler.getProtocolMessage();
tlsContext.setCompressionMethod(CompressionMethod.NULL);
tlsContext.setSelectedCipherSuite(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA);
byte[] returned = handler.prepareMessageAction();
byte[] expected = ArrayConverter.concatenate(new byte[] { HandshakeMessageType.SERVER_HELLO.getValue() },
new byte[] { 0x00, 0x00, 0x46 }, ProtocolVersion.TLS12.getValue(), message.getUnixTime().getValue(),
message.getRandom().getValue(), new byte[] { 0x20 }, message.getSessionId().getValue(),
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.getByteValue(),
new byte[] { CompressionMethod.NULL.getValue() });
assertNotNull("Confirm function didn't return 'NULL'", returned);
System.out.println(ArrayConverter.bytesToHexString(returned));
System.out.println(ArrayConverter.bytesToHexString(expected));
assertArrayEquals("Confirm returned message equals the expected message", expected, returned);
}
/**
* Test of prepareMessageAction method with Extensions, of class
* ServerHelloHandler.
*/
@Test
public void testPrepareMessageWithExtensions() {
handler.setProtocolMessage(new ServerHelloMessage());
ServerHelloMessage message = (ServerHelloMessage) handler.getProtocolMessage();
tlsContext.setCompressionMethod(CompressionMethod.NULL);
tlsContext.setSelectedCipherSuite(CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA);
HeartbeatExtensionMessage heart;
heart = new HeartbeatExtensionMessage();
heart.setHeartbeatModeConfig(HeartbeatMode.PEER_ALLOWED_TO_SEND);
EllipticCurvesExtensionMessage ecc;
ecc = new EllipticCurvesExtensionMessage();
List<NamedCurve> curve = new ArrayList<>();
curve.add(NamedCurve.SECP160K1);
curve.add(NamedCurve.SECT163K1);
ecc.setSupportedCurvesConfig(curve);
List<ExtensionMessage> extensions = new ArrayList<>();
extensions.add(heart);
extensions.add(ecc);
message.setExtensions(extensions);
byte[] returned = handler.prepareMessageAction();
byte[] expected = ArrayConverter.concatenate(new byte[] { HandshakeMessageType.SERVER_HELLO.getValue() },
new byte[] { 0x00, 0x00, 0x57 }, ProtocolVersion.TLS12.getValue(), message.getUnixTime().getValue(),
message.getRandom().getValue(), new byte[] { 0x20 }, message.getSessionId().getValue(),
CipherSuite.TLS_RSA_WITH_AES_128_CBC_SHA.getByteValue(),
new byte[] { CompressionMethod.NULL.getValue() }, new byte[] { 0x00, 0x0F },
ExtensionType.HEARTBEAT.getValue(),
new byte[] { 0x00, 0x01, HeartbeatMode.PEER_ALLOWED_TO_SEND.getValue() },
ExtensionType.ELLIPTIC_CURVES.getValue(), new byte[] { 0x00, 0x06 }, new byte[] { 0x00, 0x04 },
NamedCurve.SECP160K1.getValue(), NamedCurve.SECT163K1.getValue());
assertNotNull("Confirm function didn't return 'NULL'", returned);
assertArrayEquals("Confirm returned message equals the expected message", expected, returned);
}
}