Skip to content

Commit 95f2532

Browse files
authored
Merge pull request #397 from RUB-NDS/0rttPskOnly
Derivation of Handshake Secret for 0-RTT PSK-only
2 parents 185abd4 + c78b661 commit 95f2532

File tree

8 files changed

+121
-91
lines changed

8 files changed

+121
-91
lines changed

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,8 @@ public static List<CipherSuite> getImplemented() {
676676
list.add(TLS_DHE_RSA_WITH_AES_256_CCM);
677677
list.add(TLS_ECDHE_ECDSA_WITH_AES_128_CCM);
678678
list.add(TLS_ECDHE_ECDSA_WITH_AES_256_CCM);
679+
list.add(TLS_AES_128_GCM_SHA256);
680+
list.add(TLS_AES_256_GCM_SHA384);
679681

680682
return list;
681683
}

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

Lines changed: 1 addition & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -30,21 +30,10 @@ public HandshakeMessageHandler(TlsContext tlsContext) {
3030

3131
protected void adjustExtensions(ProtocolMessage message, HandshakeMessageType handshakeMessageType) {
3232
if (message.getExtensions() != null) {
33-
KeyShareExtensionHandler keyShareHandler = null;
34-
KeyShareExtensionMessage keyShareExtension = null;
3533
for (ExtensionMessage extension : message.getExtensions()) {
3634
ExtensionHandler handler = HandlerFactory.getExtensionHandler(tlsContext,
3735
extension.getExtensionTypeConstant(), handshakeMessageType);
38-
if (handler instanceof KeyShareExtensionHandler) {
39-
keyShareHandler = (KeyShareExtensionHandler) handler;
40-
keyShareExtension = (KeyShareExtensionMessage) extension;
41-
} else {
42-
handler.adjustTLSContext(extension);
43-
}
44-
}
45-
if (keyShareHandler != null) // delay KeyShare to process PSK first
46-
{
47-
keyShareHandler.adjustTLSContext(keyShareExtension);
36+
handler.adjustTLSContext(extension);
4837
}
4938
}
5039
}

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

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,20 @@
1212
import de.rub.nds.tlsattacker.core.constants.AlgorithmResolver;
1313
import de.rub.nds.tlsattacker.core.constants.CipherSuite;
1414
import de.rub.nds.tlsattacker.core.constants.CompressionMethod;
15+
import de.rub.nds.tlsattacker.core.constants.DigestAlgorithm;
16+
import de.rub.nds.tlsattacker.core.constants.ExtensionType;
17+
import de.rub.nds.tlsattacker.core.constants.HKDFAlgorithm;
1518
import de.rub.nds.tlsattacker.core.constants.HandshakeMessageType;
19+
import de.rub.nds.tlsattacker.core.constants.NamedCurve;
1620
import de.rub.nds.tlsattacker.core.constants.ProtocolVersion;
1721
import de.rub.nds.tlsattacker.core.constants.Tls13KeySetType;
22+
import de.rub.nds.tlsattacker.core.crypto.HKDFunction;
23+
import de.rub.nds.tlsattacker.core.crypto.ec.Curve25519;
24+
import de.rub.nds.tlsattacker.core.exceptions.CryptoException;
25+
import de.rub.nds.tlsattacker.core.exceptions.PreparationException;
1826
import static de.rub.nds.tlsattacker.core.protocol.handler.ProtocolMessageHandler.LOGGER;
1927
import de.rub.nds.tlsattacker.core.protocol.message.ServerHelloMessage;
28+
import de.rub.nds.tlsattacker.core.protocol.message.extension.KS.KSEntry;
2029
import de.rub.nds.tlsattacker.core.protocol.parser.ServerHelloParser;
2130
import de.rub.nds.tlsattacker.core.protocol.preparator.ServerHelloMessagePreparator;
2231
import de.rub.nds.tlsattacker.core.protocol.serializer.ServerHelloMessageSerializer;
@@ -29,6 +38,7 @@
2938
import de.rub.nds.tlsattacker.core.workflow.chooser.Chooser;
3039
import de.rub.nds.tlsattacker.transport.ConnectionEndType;
3140
import java.security.NoSuchAlgorithmException;
41+
import javax.crypto.Mac;
3242

3343
public class ServerHelloHandler extends HandshakeMessageHandler<ServerHelloMessage> {
3444

@@ -62,6 +72,7 @@ public void adjustTLSContext(ServerHelloMessage message) {
6272
adjustServerRandom(message);
6373
adjustExtensions(message, HandshakeMessageType.SERVER_HELLO);
6474
if (tlsContext.getChooser().getSelectedProtocolVersion().isTLS13()) {
75+
adjustHandshakeTrafficSecrets();
6576
if (tlsContext.getTalkingConnectionEndType() != tlsContext.getChooser().getConnectionEndType()) {
6677
setServerRecordCipher();
6778
}
@@ -168,4 +179,71 @@ public void adjustTlsContextAfterSerialize(ServerHelloMessage message) {
168179
setServerRecordCipher();
169180
}
170181
}
182+
183+
private void adjustHandshakeTrafficSecrets() {
184+
HKDFAlgorithm hkdfAlgortihm = AlgorithmResolver.getHKDFAlgorithm(tlsContext.getChooser()
185+
.getSelectedCipherSuite());
186+
DigestAlgorithm digestAlgo = AlgorithmResolver.getDigestAlgorithm(tlsContext.getChooser()
187+
.getSelectedProtocolVersion(), tlsContext.getChooser().getSelectedCipherSuite());
188+
189+
try {
190+
int macLength = Mac.getInstance(hkdfAlgortihm.getMacAlgorithm().getJavaName()).getMacLength();
191+
byte[] psk = (tlsContext.getConfig().isUsePsk() || tlsContext.getPsk() != null) ? tlsContext.getChooser()
192+
.getPsk() : new byte[macLength]; // use PSK if available
193+
byte[] earlySecret = HKDFunction.extract(hkdfAlgortihm, new byte[0], psk);
194+
byte[] saltHandshakeSecret = HKDFunction.deriveSecret(hkdfAlgortihm, digestAlgo.getJavaName(), earlySecret,
195+
HKDFunction.DERIVED, ArrayConverter.hexStringToByteArray(""));
196+
byte[] sharedSecret = new byte[macLength];
197+
if (tlsContext.getChooser().getConnectionEndType() == ConnectionEndType.CLIENT
198+
&& tlsContext.isExtensionNegotiated(ExtensionType.KEY_SHARE)) {
199+
if (tlsContext.getChooser().getServerKSEntry().getGroup() == NamedCurve.ECDH_X25519) {
200+
sharedSecret = computeSharedSecretECDH(tlsContext.getChooser().getServerKSEntry());
201+
} else {
202+
throw new PreparationException("Currently only the key exchange group ECDH_X25519 is supported");
203+
}
204+
} else if (tlsContext.isExtensionNegotiated(ExtensionType.KEY_SHARE)) {
205+
int pos = 0;
206+
for (KSEntry entry : tlsContext.getChooser().getClientKeyShareEntryList()) {
207+
if (entry.getGroup() == NamedCurve.ECDH_X25519) {
208+
pos = tlsContext.getChooser().getClientKeyShareEntryList().indexOf(entry);
209+
}
210+
}
211+
if (tlsContext.getChooser().getClientKeyShareEntryList().get(pos).getGroup() == NamedCurve.ECDH_X25519) {
212+
sharedSecret = computeSharedSecretECDH(tlsContext.getChooser().getClientKeyShareEntryList()
213+
.get(pos));
214+
} else {
215+
throw new PreparationException("Currently only the key exchange group ECDH_X25519 is supported");
216+
}
217+
}
218+
byte[] handshakeSecret = HKDFunction.extract(hkdfAlgortihm, saltHandshakeSecret, sharedSecret);
219+
tlsContext.setHandshakeSecret(handshakeSecret);
220+
LOGGER.debug("Set handshakeSecret in Context to " + ArrayConverter.bytesToHexString(handshakeSecret));
221+
byte[] clientHandshakeTrafficSecret = HKDFunction.deriveSecret(hkdfAlgortihm, digestAlgo.getJavaName(),
222+
handshakeSecret, HKDFunction.CLIENT_HANDSHAKE_TRAFFIC_SECRET, tlsContext.getDigest().getRawBytes());
223+
tlsContext.setClientHandshakeTrafficSecret(clientHandshakeTrafficSecret);
224+
LOGGER.debug("Set clientHandshakeTrafficSecret in Context to "
225+
+ ArrayConverter.bytesToHexString(clientHandshakeTrafficSecret));
226+
byte[] serverHandshakeTrafficSecret = HKDFunction.deriveSecret(hkdfAlgortihm, digestAlgo.getJavaName(),
227+
handshakeSecret, HKDFunction.SERVER_HANDSHAKE_TRAFFIC_SECRET, tlsContext.getDigest().getRawBytes());
228+
tlsContext.setServerHandshakeTrafficSecret(serverHandshakeTrafficSecret);
229+
LOGGER.debug("Set serverHandshakeTrafficSecret in Context to "
230+
+ ArrayConverter.bytesToHexString(serverHandshakeTrafficSecret));
231+
} catch (NoSuchAlgorithmException ex) {
232+
throw new CryptoException(ex);
233+
}
234+
}
235+
236+
/**
237+
* Computes the shared secret for ECDH_X25519
238+
*
239+
* @return
240+
*/
241+
private byte[] computeSharedSecretECDH(KSEntry keyShare) {
242+
byte[] privateKey = tlsContext.getConfig().getKeySharePrivate();
243+
byte[] publicKey = keyShare.getSerializedPublicKey();
244+
Curve25519.clamp(privateKey);
245+
byte[] sharedSecret = new byte[32];
246+
Curve25519.curve(sharedSecret, privateKey, publicKey);
247+
return sharedSecret;
248+
}
171249
}

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/protocol/handler/extension/KeyShareExtensionHandler.java

Lines changed: 0 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -73,74 +73,8 @@ public void adjustTLSExtensionContext(KeyShareExtensionMessage message) {
7373
if (ksEntryList.size() > 0) {
7474
context.setServerKSEntry(ksEntryList.get(0));
7575
}
76-
adjustHandshakeTrafficSecrets();
7776
} else {
7877
context.setClientKeyShareEntryList(ksEntryList);
7978
}
8079
}
81-
82-
private void adjustHandshakeTrafficSecrets() {
83-
HKDFAlgorithm hkdfAlgortihm = AlgorithmResolver.getHKDFAlgorithm(context.getChooser().getSelectedCipherSuite());
84-
DigestAlgorithm digestAlgo = AlgorithmResolver.getDigestAlgorithm(context.getChooser()
85-
.getSelectedProtocolVersion(), context.getChooser().getSelectedCipherSuite());
86-
87-
try {
88-
int macLength = Mac.getInstance(hkdfAlgortihm.getMacAlgorithm().getJavaName()).getMacLength();
89-
byte[] psk = (context.getConfig().isUsePsk() || context.getPsk() != null) ? context.getChooser().getPsk()
90-
: new byte[macLength]; // use PSK if available
91-
byte[] earlySecret = HKDFunction.extract(hkdfAlgortihm, new byte[0], psk);
92-
byte[] saltHandshakeSecret = HKDFunction.deriveSecret(hkdfAlgortihm, digestAlgo.getJavaName(), earlySecret,
93-
HKDFunction.DERIVED, ArrayConverter.hexStringToByteArray(""));
94-
byte[] sharedSecret;
95-
if (context.getChooser().getConnectionEndType() == ConnectionEndType.CLIENT) {
96-
if (context.getChooser().getServerKSEntry().getGroup() == NamedCurve.ECDH_X25519) {
97-
sharedSecret = computeSharedSecretECDH(context.getChooser().getServerKSEntry());
98-
} else {
99-
throw new PreparationException("Currently only the key exchange group ECDH_X25519 is supported");
100-
}
101-
} else {
102-
int pos = 0;
103-
for (KSEntry entry : context.getChooser().getClientKeyShareEntryList()) {
104-
if (entry.getGroup() == NamedCurve.ECDH_X25519) {
105-
pos = context.getChooser().getClientKeyShareEntryList().indexOf(entry);
106-
}
107-
}
108-
if (context.getChooser().getClientKeyShareEntryList().get(pos).getGroup() == NamedCurve.ECDH_X25519) {
109-
sharedSecret = computeSharedSecretECDH(context.getChooser().getClientKeyShareEntryList().get(pos));
110-
} else {
111-
throw new PreparationException("Currently only the key exchange group ECDH_X25519 is supported");
112-
}
113-
}
114-
byte[] handshakeSecret = HKDFunction.extract(hkdfAlgortihm, saltHandshakeSecret, sharedSecret);
115-
context.setHandshakeSecret(handshakeSecret);
116-
LOGGER.debug("Set handshakeSecret in Context to " + ArrayConverter.bytesToHexString(handshakeSecret));
117-
byte[] clientHandshakeTrafficSecret = HKDFunction.deriveSecret(hkdfAlgortihm, digestAlgo.getJavaName(),
118-
handshakeSecret, HKDFunction.CLIENT_HANDSHAKE_TRAFFIC_SECRET, context.getDigest().getRawBytes());
119-
context.setClientHandshakeTrafficSecret(clientHandshakeTrafficSecret);
120-
LOGGER.debug("Set clientHandshakeTrafficSecret in Context to "
121-
+ ArrayConverter.bytesToHexString(clientHandshakeTrafficSecret));
122-
byte[] serverHandshakeTrafficSecret = HKDFunction.deriveSecret(hkdfAlgortihm, digestAlgo.getJavaName(),
123-
handshakeSecret, HKDFunction.SERVER_HANDSHAKE_TRAFFIC_SECRET, context.getDigest().getRawBytes());
124-
context.setServerHandshakeTrafficSecret(serverHandshakeTrafficSecret);
125-
LOGGER.debug("Set serverHandshakeTrafficSecret in Context to "
126-
+ ArrayConverter.bytesToHexString(serverHandshakeTrafficSecret));
127-
} catch (NoSuchAlgorithmException ex) {
128-
throw new CryptoException(ex);
129-
}
130-
}
131-
132-
/**
133-
* Computes the shared secret for ECDH_X25519
134-
*
135-
* @return
136-
*/
137-
private byte[] computeSharedSecretECDH(KSEntry keyShare) {
138-
byte[] privateKey = context.getConfig().getKeySharePrivate();
139-
byte[] publicKey = keyShare.getSerializedPublicKey();
140-
Curve25519.clamp(privateKey);
141-
byte[] sharedSecret = new byte[32];
142-
Curve25519.curve(sharedSecret, privateKey, publicKey);
143-
return sharedSecret;
144-
}
145-
14680
}

TLS-Core/src/main/java/de/rub/nds/tlsattacker/core/record/cipher/cryptohelper/KeySetGenerator.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,12 @@ private static KeySet getTls13KeySet(TlsContext context, Tls13KeySetType keySetT
6262
} else if (keySetType == Tls13KeySetType.EARLY_TRAFFIC_SECRETS) {
6363
cipherSuite = context.getChooser().getEarlyDataCipherSuite();
6464
clientSecret = context.getChooser().getClientEarlyTrafficSecret();
65-
serverSecret = context.getChooser().getClientEarlyTrafficSecret(); // won't
66-
// be
67-
// used
65+
serverSecret = context.getChooser().getClientEarlyTrafficSecret();
66+
} else if (keySetType == Tls13KeySetType.NONE) {
67+
LOGGER.warn("KeySet is NONE! , returning empty KeySet");
68+
return new KeySet(keySetType);
69+
} else {
70+
throw new CryptoException("Unknown KeySetType:" + keySetType.name());
6871
}
6972
LOGGER.debug("ActiveKeySetType is " + keySetType);
7073
CipherAlgorithm cipherAlg = AlgorithmResolver.getCipher(cipherSuite);

TLS-Core/src/test/java/de/rub/nds/tlsattacker/core/protocol/handler/ServerHelloHandlerTest.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,21 @@
88
*/
99
package de.rub.nds.tlsattacker.core.protocol.handler;
1010

11+
import de.rub.nds.modifiablevariable.util.ArrayConverter;
1112
import de.rub.nds.tlsattacker.core.constants.CipherSuite;
1213
import de.rub.nds.tlsattacker.core.constants.CompressionMethod;
14+
import de.rub.nds.tlsattacker.core.constants.ExtensionType;
15+
import de.rub.nds.tlsattacker.core.constants.NamedCurve;
1316
import de.rub.nds.tlsattacker.core.constants.ProtocolVersion;
1417
import de.rub.nds.tlsattacker.core.protocol.message.ServerHelloMessage;
18+
import de.rub.nds.tlsattacker.core.protocol.message.extension.KS.KSEntry;
1519
import de.rub.nds.tlsattacker.core.protocol.parser.ServerHelloParser;
1620
import de.rub.nds.tlsattacker.core.protocol.preparator.ServerHelloMessagePreparator;
1721
import de.rub.nds.tlsattacker.core.protocol.serializer.ServerHelloMessageSerializer;
22+
import de.rub.nds.tlsattacker.core.record.layer.RecordLayerFactory;
23+
import de.rub.nds.tlsattacker.core.record.layer.RecordLayerType;
1824
import de.rub.nds.tlsattacker.core.state.TlsContext;
25+
import de.rub.nds.tlsattacker.transport.ConnectionEndType;
1926
import org.junit.After;
2027
import static org.junit.Assert.*;
2128
import org.junit.Before;
@@ -82,4 +89,29 @@ public void testAdjustTLSContext() {
8289
assertArrayEquals(context.getSelectedProtocolVersion().getValue(), ProtocolVersion.TLS12.getValue());
8390
}
8491

92+
@Test
93+
public void testAdjustTLSContextTls13() {
94+
ServerHelloMessage message = new ServerHelloMessage();
95+
context.setTalkingConnectionEndType(ConnectionEndType.SERVER);
96+
message.setUnixTime(new byte[] { 0, 1, 2 });
97+
message.setRandom(new byte[] { 0, 1, 2, 3, 4, 5 });
98+
message.setSelectedCompressionMethod(CompressionMethod.DEFLATE.getValue());
99+
message.setSelectedCipherSuite(CipherSuite.TLS_AES_128_GCM_SHA256.getByteValue());
100+
message.setSessionId(new byte[] { 6, 6, 6 });
101+
message.setProtocolVersion(ProtocolVersion.TLS13.getValue());
102+
context.setServerKSEntry(new KSEntry(NamedCurve.ECDH_X25519, ArrayConverter
103+
.hexStringToByteArray("9c1b0a7421919a73cb57b3a0ad9d6805861a9c47e11df8639d25323b79ce201c")));
104+
context.addNegotiatedExtension(ExtensionType.KEY_SHARE);
105+
context.setRecordLayer(RecordLayerFactory.getRecordLayer(RecordLayerType.RECORD, context));
106+
handler.adjustTLSContext(message);
107+
assertArrayEquals(
108+
ArrayConverter.hexStringToByteArray("EA2F968FD0A381E4B041E6D8DDBF6DA93DE4CEAC862693D3026323E780DB9FC3"),
109+
context.getHandshakeSecret());
110+
assertArrayEquals(
111+
ArrayConverter.hexStringToByteArray("C56CAE0B1A64467A0E3A3337F8636965787C9A741B0DAB63E503076051BCA15C"),
112+
context.getClientHandshakeTrafficSecret());
113+
assertArrayEquals(
114+
ArrayConverter.hexStringToByteArray("DBF731F5EE037C4494F24701FF074AD4048451C0E2803BC686AF1F2D18E861F5"),
115+
context.getServerHandshakeTrafficSecret());
116+
}
85117
}

TLS-Core/src/test/java/de/rub/nds/tlsattacker/core/protocol/handler/extension/KeyShareExtensionHandlerTest.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -66,15 +66,6 @@ public void testAdjustTLSContext() {
6666
ArrayConverter.hexStringToByteArray("9c1b0a7421919a73cb57b3a0ad9d6805861a9c47e11df8639d25323b79ce201c"),
6767
entry.getSerializedPublicKey());
6868
assertTrue(entry.getGroup() == NamedCurve.ECDH_X25519);
69-
assertArrayEquals(
70-
ArrayConverter.hexStringToByteArray("EA2F968FD0A381E4B041E6D8DDBF6DA93DE4CEAC862693D3026323E780DB9FC3"),
71-
context.getHandshakeSecret());
72-
assertArrayEquals(
73-
ArrayConverter.hexStringToByteArray("C56CAE0B1A64467A0E3A3337F8636965787C9A741B0DAB63E503076051BCA15C"),
74-
context.getClientHandshakeTrafficSecret());
75-
assertArrayEquals(
76-
ArrayConverter.hexStringToByteArray("DBF731F5EE037C4494F24701FF074AD4048451C0E2803BC686AF1F2D18E861F5"),
77-
context.getServerHandshakeTrafficSecret());
7869
}
7970

8071
/**

TLS-Core/src/test/java/de/rub/nds/tlsattacker/core/record/cipher/KeySetGeneratorTest.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import de.rub.nds.tlsattacker.core.record.cipher.cryptohelper.KeySetGenerator;
1212
import de.rub.nds.tlsattacker.core.constants.CipherSuite;
1313
import de.rub.nds.tlsattacker.core.constants.ProtocolVersion;
14+
import de.rub.nds.tlsattacker.core.constants.Tls13KeySetType;
1415
import de.rub.nds.tlsattacker.core.state.TlsContext;
1516
import de.rub.nds.tlsattacker.util.tests.IntegrationTests;
1617
import java.security.NoSuchAlgorithmException;
@@ -38,7 +39,7 @@ public void setUp() {
3839
* be generated without throwing an exception
3940
*/
4041
@Test
41-
@Category(IntegrationTests.class)
42+
// @Category(IntegrationTests.class)
4243
public void testGenerateKeySet() {
4344
for (CipherSuite suite : CipherSuite.getImplemented()) {
4445
for (ProtocolVersion version : ProtocolVersion.values()) {

0 commit comments

Comments
 (0)