Skip to content

Commit c4208f7

Browse files
authored
Merge pull request #734 from tls-attacker/issue720
2 parents 8808951 + e8b242a commit c4208f7

File tree

14 files changed

+459
-0
lines changed

14 files changed

+459
-0
lines changed

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/constants/HandshakeByteLength.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,11 @@ public class HandshakeByteLength {
254254
*/
255255
public static final int CERTIFICATE_STATUS_RESPONSE_LENGTH = 3;
256256

257+
/**
258+
* KeyUpdate Message Length
259+
*/
260+
public static final int KEY_UPDATE_LENGTH = 1;
261+
257262
private HandshakeByteLength() {
258263
}
259264
}

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/constants/HandshakeMessageType.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public enum HandshakeMessageType {
3737
CERTIFICATE_VERIFY((byte) 15),
3838
CLIENT_KEY_EXCHANGE((byte) 16),
3939
FINISHED((byte) 20),
40+
KEY_UPDATE((byte) 24),
4041
CERTIFICATE_STATUS((byte) 22),
4142
SUPPLEMENTAL_DATA((byte) 23),
4243
MESSAGE_HASH((byte) 254);
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
3+
*
4+
* Copyright 2014-2020 Ruhr University Bochum, Paderborn University,
5+
* and Hackmanit GmbH
6+
*
7+
* Licensed under Apache License 2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*/
10+
11+
package de.rub.nds.tlsattacker.core.constants;
12+
13+
import de.rub.nds.modifiablevariable.ModifiableVariableFactory;
14+
import de.rub.nds.modifiablevariable.singlebyte.ModifiableByte;
15+
16+
public enum KeyUpdateRequest {
17+
18+
UPDATE_NOT_REQUESTED((byte) 0),
19+
UPDATE_REQUESTED((byte) 1);
20+
21+
private ModifiableByte requestUpdate;
22+
23+
private KeyUpdateRequest(byte requestUpdate) {
24+
this.requestUpdate = ModifiableVariableFactory.safelySetValue(this.requestUpdate, requestUpdate);
25+
}
26+
27+
public byte getValue() {
28+
return requestUpdate.getValue();
29+
}
30+
31+
}

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/crypto/HKDFunction.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ public class HKDFunction {
6060

6161
public static final String RESUMPTION = "resumption";
6262

63+
public static final String TRAFFICUPD = "traffic upd";
64+
6365
private HKDFunction() {
6466
}
6567

Lines changed: 209 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,209 @@
1+
/**
2+
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
3+
*
4+
* Copyright 2014-2020 Ruhr University Bochum, Paderborn University,
5+
* and Hackmanit GmbH
6+
*
7+
* Licensed under Apache License 2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*/
10+
11+
package de.rub.nds.tlsattacker.core.protocol.handler;
12+
13+
import de.rub.nds.modifiablevariable.util.ArrayConverter;
14+
import de.rub.nds.tlsattacker.core.constants.AlgorithmResolver;
15+
import de.rub.nds.tlsattacker.core.constants.HKDFAlgorithm;
16+
import de.rub.nds.tlsattacker.core.constants.Tls13KeySetType;
17+
import de.rub.nds.tlsattacker.core.crypto.HKDFunction;
18+
import de.rub.nds.tlsattacker.core.exceptions.AdjustmentException;
19+
import de.rub.nds.tlsattacker.core.exceptions.CryptoException;
20+
import de.rub.nds.tlsattacker.core.protocol.message.KeyUpdateMessage;
21+
import de.rub.nds.tlsattacker.core.protocol.parser.KeyUpdateParser;
22+
import de.rub.nds.tlsattacker.core.protocol.parser.ProtocolMessageParser;
23+
import de.rub.nds.tlsattacker.core.protocol.preparator.KeyUpdatePreparator;
24+
import de.rub.nds.tlsattacker.core.protocol.preparator.ProtocolMessagePreparator;
25+
import de.rub.nds.tlsattacker.core.protocol.serializer.KeyUpdateSerializer;
26+
import de.rub.nds.tlsattacker.core.protocol.serializer.ProtocolMessageSerializer;
27+
import de.rub.nds.tlsattacker.core.record.cipher.RecordCipher;
28+
import de.rub.nds.tlsattacker.core.record.cipher.RecordCipherFactory;
29+
import de.rub.nds.tlsattacker.core.record.cipher.cryptohelper.KeySet;
30+
import de.rub.nds.tlsattacker.core.record.cipher.cryptohelper.KeySetGenerator;
31+
import de.rub.nds.tlsattacker.core.state.TlsContext;
32+
import de.rub.nds.tlsattacker.transport.ConnectionEndType;
33+
34+
import java.security.NoSuchAlgorithmException;
35+
36+
import javax.crypto.Mac;
37+
import org.apache.logging.log4j.LogManager;
38+
import org.apache.logging.log4j.Logger;
39+
40+
public class KeyUpdateHandler extends HandshakeMessageHandler<KeyUpdateMessage> {
41+
42+
private static final Logger LOGGER = LogManager.getLogger();
43+
44+
public KeyUpdateHandler(TlsContext tlsContext) {
45+
super(tlsContext);
46+
}
47+
48+
@Override
49+
public void adjustTLSContext(KeyUpdateMessage message) {
50+
if (tlsContext.getChooser().getTalkingConnectionEnd() != tlsContext.getChooser().getConnectionEndType()) {
51+
adjustApplicationTrafficSecrets();
52+
setRecordCipher(Tls13KeySetType.APPLICATION_TRAFFIC_SECRETS);
53+
}
54+
}
55+
56+
@Override
57+
public void adjustTlsContextAfterSerialize(KeyUpdateMessage message) {
58+
adjustApplicationTrafficSecrets();
59+
setRecordCipher(Tls13KeySetType.APPLICATION_TRAFFIC_SECRETS);
60+
}
61+
62+
@Override
63+
public ProtocolMessageParser getParser(byte[] message, int pointer) {
64+
return new KeyUpdateParser(pointer, message, tlsContext.getChooser().getSelectedProtocolVersion(),
65+
tlsContext.getConfig());
66+
67+
}
68+
69+
@Override
70+
public ProtocolMessagePreparator getPreparator(KeyUpdateMessage message) {
71+
return new KeyUpdatePreparator(tlsContext.getChooser(), message);
72+
}
73+
74+
@Override
75+
public ProtocolMessageSerializer getSerializer(KeyUpdateMessage message) {
76+
return new KeyUpdateSerializer(message, tlsContext.getChooser().getSelectedProtocolVersion());
77+
}
78+
79+
private void adjustApplicationTrafficSecrets() {
80+
HKDFAlgorithm hkdfAlgortihm =
81+
AlgorithmResolver.getHKDFAlgorithm(tlsContext.getChooser().getSelectedCipherSuite());
82+
83+
try {
84+
Mac mac = Mac.getInstance(hkdfAlgortihm.getMacAlgorithm().getJavaName());
85+
86+
if (tlsContext.getChooser().getTalkingConnectionEnd() == ConnectionEndType.CLIENT) {
87+
88+
byte[] clientApplicationTrafficSecret =
89+
HKDFunction.expandLabel(hkdfAlgortihm, tlsContext.getClientApplicationTrafficSecret(),
90+
HKDFunction.TRAFFICUPD, new byte[0], mac.getMacLength());
91+
92+
tlsContext.setClientApplicationTrafficSecret(clientApplicationTrafficSecret);
93+
LOGGER.debug("Set clientApplicationTrafficSecret in Context to "
94+
+ ArrayConverter.bytesToHexString(clientApplicationTrafficSecret));
95+
96+
} else {
97+
98+
byte[] serverApplicationTrafficSecret =
99+
HKDFunction.expandLabel(hkdfAlgortihm, tlsContext.getServerApplicationTrafficSecret(),
100+
HKDFunction.TRAFFICUPD, new byte[0], mac.getMacLength());
101+
102+
tlsContext.setServerApplicationTrafficSecret(serverApplicationTrafficSecret);
103+
LOGGER.debug("Set serverApplicationTrafficSecret in Context to "
104+
+ ArrayConverter.bytesToHexString(serverApplicationTrafficSecret));
105+
106+
}
107+
108+
} catch (NoSuchAlgorithmException | CryptoException ex) {
109+
throw new AdjustmentException(ex);
110+
}
111+
}
112+
113+
private KeySet getKeySet(TlsContext context, Tls13KeySetType keySetType) {
114+
try {
115+
LOGGER.debug("Generating new KeySet");
116+
KeySet keySet =
117+
KeySetGenerator.generateKeySet(context, context.getChooser().getSelectedProtocolVersion(), keySetType);
118+
119+
return keySet;
120+
} catch (NoSuchAlgorithmException | CryptoException ex) {
121+
throw new UnsupportedOperationException("The specified Algorithm is not supported", ex);
122+
}
123+
}
124+
125+
private void setRecordCipher(Tls13KeySetType keySetType) {
126+
try {
127+
int AEAD_IV_LENGTH = 12;
128+
KeySet keySet;
129+
HKDFAlgorithm hkdfAlgortihm =
130+
AlgorithmResolver.getHKDFAlgorithm(tlsContext.getChooser().getSelectedCipherSuite());
131+
132+
if (tlsContext.getChooser().getTalkingConnectionEnd() == ConnectionEndType.CLIENT) {
133+
134+
tlsContext.setActiveClientKeySetType(keySetType);
135+
LOGGER.debug("Setting cipher for client to use " + keySetType);
136+
keySet = getKeySet(tlsContext, tlsContext.getActiveClientKeySetType());
137+
138+
} else {
139+
tlsContext.setActiveServerKeySetType(keySetType);
140+
LOGGER.debug("Setting cipher for server to use " + keySetType);
141+
keySet = getKeySet(tlsContext, tlsContext.getActiveServerKeySetType());
142+
}
143+
144+
if (tlsContext.getChooser().getTalkingConnectionEnd() == tlsContext.getChooser().getConnectionEndType()) {
145+
146+
if (tlsContext.getChooser().getConnectionEndType() == ConnectionEndType.CLIENT) {
147+
148+
keySet.setClientWriteIv(HKDFunction.expandLabel(hkdfAlgortihm,
149+
tlsContext.getClientApplicationTrafficSecret(), HKDFunction.IV, new byte[0], AEAD_IV_LENGTH));
150+
151+
keySet.setClientWriteKey(HKDFunction.expandLabel(hkdfAlgortihm, tlsContext
152+
.getClientApplicationTrafficSecret(), HKDFunction.KEY, new byte[0], AlgorithmResolver
153+
.getCipher(tlsContext.getChooser().getSelectedCipherSuite()).getKeySize()));
154+
} else {
155+
156+
keySet.setServerWriteIv(HKDFunction.expandLabel(hkdfAlgortihm,
157+
tlsContext.getServerApplicationTrafficSecret(), HKDFunction.IV, new byte[0], AEAD_IV_LENGTH));
158+
159+
keySet.setServerWriteKey(HKDFunction.expandLabel(hkdfAlgortihm, tlsContext
160+
.getServerApplicationTrafficSecret(), HKDFunction.KEY, new byte[0], AlgorithmResolver
161+
.getCipher(tlsContext.getChooser().getSelectedCipherSuite()).getKeySize()));
162+
}
163+
164+
RecordCipher recordCipherClient =
165+
RecordCipherFactory.getRecordCipher(tlsContext, keySet, tlsContext.getChooser()
166+
.getSelectedCipherSuite());
167+
tlsContext.getRecordLayer().setRecordCipher(recordCipherClient);
168+
169+
tlsContext.setWriteSequenceNumber(0);
170+
tlsContext.getRecordLayer().updateEncryptionCipher();
171+
172+
} else if (tlsContext.getChooser().getTalkingConnectionEnd() != tlsContext.getChooser()
173+
.getConnectionEndType()) {
174+
175+
if (tlsContext.getChooser().getTalkingConnectionEnd() == ConnectionEndType.SERVER) {
176+
177+
keySet.setServerWriteIv(HKDFunction.expandLabel(hkdfAlgortihm,
178+
tlsContext.getServerApplicationTrafficSecret(), HKDFunction.IV, new byte[0], AEAD_IV_LENGTH));
179+
180+
keySet.setServerWriteKey(HKDFunction.expandLabel(hkdfAlgortihm, tlsContext
181+
.getServerApplicationTrafficSecret(), HKDFunction.KEY, new byte[0], AlgorithmResolver
182+
.getCipher(tlsContext.getChooser().getSelectedCipherSuite()).getKeySize()));
183+
184+
} else {
185+
186+
keySet.setClientWriteIv(HKDFunction.expandLabel(hkdfAlgortihm,
187+
tlsContext.getClientApplicationTrafficSecret(), HKDFunction.IV, new byte[0], AEAD_IV_LENGTH));
188+
189+
keySet.setClientWriteKey(HKDFunction.expandLabel(hkdfAlgortihm, tlsContext
190+
.getClientApplicationTrafficSecret(), HKDFunction.KEY, new byte[0], AlgorithmResolver
191+
.getCipher(tlsContext.getChooser().getSelectedCipherSuite()).getKeySize()));
192+
}
193+
194+
RecordCipher recordCipherClient =
195+
RecordCipherFactory.getRecordCipher(tlsContext, keySet, tlsContext.getChooser()
196+
.getSelectedCipherSuite());
197+
tlsContext.getRecordLayer().setRecordCipher(recordCipherClient);
198+
199+
tlsContext.setReadSequenceNumber(0);
200+
tlsContext.getRecordLayer().updateDecryptionCipher();
201+
202+
}
203+
204+
} catch (CryptoException ex) {
205+
throw new AdjustmentException(ex);
206+
}
207+
208+
}
209+
}

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/handler/factory/HandlerFactory.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import de.rub.nds.tlsattacker.core.protocol.handler.HelloRequestHandler;
3838
import de.rub.nds.tlsattacker.core.protocol.handler.HelloRetryRequestHandler;
3939
import de.rub.nds.tlsattacker.core.protocol.handler.HelloVerifyRequestHandler;
40+
import de.rub.nds.tlsattacker.core.protocol.handler.KeyUpdateHandler;
4041
import de.rub.nds.tlsattacker.core.protocol.handler.NewSessionTicketHandler;
4142
import de.rub.nds.tlsattacker.core.protocol.handler.PWDClientKeyExchangeHandler;
4243
import de.rub.nds.tlsattacker.core.protocol.handler.PWDServerKeyExchangeHandler;
@@ -163,6 +164,8 @@ public static HandshakeMessageHandler getHandshakeHandler(TlsContext context, Ha
163164
return new HelloVerifyRequestHandler(context);
164165
case NEW_SESSION_TICKET:
165166
return new NewSessionTicketHandler(context);
167+
case KEY_UPDATE:
168+
return new KeyUpdateHandler(context);
166169
case SERVER_HELLO:
167170
return new ServerHelloHandler(context);
168171
case SERVER_HELLO_DONE:
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
/**
2+
* TLS-Attacker - A Modular Penetration Testing Framework for TLS
3+
*
4+
* Copyright 2014-2020 Ruhr University Bochum, Paderborn University,
5+
* and Hackmanit GmbH
6+
*
7+
* Licensed under Apache License 2.0
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*/
10+
11+
package de.rub.nds.tlsattacker.core.protocol.message;
12+
13+
import de.rub.nds.tlsattacker.core.config.Config;
14+
import de.rub.nds.tlsattacker.core.constants.HandshakeMessageType;
15+
import de.rub.nds.tlsattacker.core.constants.KeyUpdateRequest;
16+
import de.rub.nds.tlsattacker.core.protocol.handler.ProtocolMessageHandler;
17+
import de.rub.nds.tlsattacker.core.state.TlsContext;
18+
import de.rub.nds.tlsattacker.core.protocol.handler.KeyUpdateHandler;
19+
20+
import org.apache.logging.log4j.LogManager;
21+
import org.apache.logging.log4j.Logger;
22+
23+
public class KeyUpdateMessage extends HandshakeMessage {
24+
25+
private static final Logger LOGGER = LogManager.getLogger();
26+
27+
private KeyUpdateRequest requestUpdate;
28+
29+
@Override
30+
public ProtocolMessageHandler getHandler(TlsContext context) {
31+
return new KeyUpdateHandler(context);
32+
}
33+
34+
public KeyUpdateMessage() {
35+
super(HandshakeMessageType.KEY_UPDATE);
36+
this.setIncludeInDigest(false);
37+
this.requestUpdate = KeyUpdateRequest.UPDATE_NOT_REQUESTED;
38+
}
39+
40+
public KeyUpdateMessage(Config tlsConfig) {
41+
super(tlsConfig, HandshakeMessageType.KEY_UPDATE);
42+
this.requestUpdate = KeyUpdateRequest.UPDATE_NOT_REQUESTED;
43+
this.setIncludeInDigest(false);
44+
}
45+
46+
public KeyUpdateMessage(HandshakeMessageType handshakeMessageType, KeyUpdateRequest requestUpdate) {
47+
super(handshakeMessageType);
48+
this.requestUpdate = requestUpdate;
49+
this.setIncludeInDigest(false);
50+
}
51+
52+
public void setRequestUpdate(KeyUpdateRequest keyupdaterequest) {
53+
requestUpdate = keyupdaterequest;
54+
}
55+
56+
public KeyUpdateRequest getRequestUpdate() {
57+
return this.requestUpdate;
58+
}
59+
60+
}

0 commit comments

Comments
 (0)