|
12 | 12 | import de.rub.nds.tlsattacker.core.constants.AlgorithmResolver; |
13 | 13 | import de.rub.nds.tlsattacker.core.constants.CipherSuite; |
14 | 14 | 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; |
15 | 18 | import de.rub.nds.tlsattacker.core.constants.HandshakeMessageType; |
| 19 | +import de.rub.nds.tlsattacker.core.constants.NamedCurve; |
16 | 20 | import de.rub.nds.tlsattacker.core.constants.ProtocolVersion; |
17 | 21 | 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; |
18 | 26 | import static de.rub.nds.tlsattacker.core.protocol.handler.ProtocolMessageHandler.LOGGER; |
19 | 27 | import de.rub.nds.tlsattacker.core.protocol.message.ServerHelloMessage; |
| 28 | +import de.rub.nds.tlsattacker.core.protocol.message.extension.KS.KSEntry; |
20 | 29 | import de.rub.nds.tlsattacker.core.protocol.parser.ServerHelloParser; |
21 | 30 | import de.rub.nds.tlsattacker.core.protocol.preparator.ServerHelloMessagePreparator; |
22 | 31 | import de.rub.nds.tlsattacker.core.protocol.serializer.ServerHelloMessageSerializer; |
|
29 | 38 | import de.rub.nds.tlsattacker.core.workflow.chooser.Chooser; |
30 | 39 | import de.rub.nds.tlsattacker.transport.ConnectionEndType; |
31 | 40 | import java.security.NoSuchAlgorithmException; |
| 41 | +import javax.crypto.Mac; |
32 | 42 |
|
33 | 43 | public class ServerHelloHandler extends HandshakeMessageHandler<ServerHelloMessage> { |
34 | 44 |
|
@@ -62,6 +72,7 @@ public void adjustTLSContext(ServerHelloMessage message) { |
62 | 72 | adjustServerRandom(message); |
63 | 73 | adjustExtensions(message, HandshakeMessageType.SERVER_HELLO); |
64 | 74 | if (tlsContext.getChooser().getSelectedProtocolVersion().isTLS13()) { |
| 75 | + adjustHandshakeTrafficSecrets(); |
65 | 76 | if (tlsContext.getTalkingConnectionEndType() != tlsContext.getChooser().getConnectionEndType()) { |
66 | 77 | setServerRecordCipher(); |
67 | 78 | } |
@@ -168,4 +179,71 @@ public void adjustTlsContextAfterSerialize(ServerHelloMessage message) { |
168 | 179 | setServerRecordCipher(); |
169 | 180 | } |
170 | 181 | } |
| 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 | + } |
171 | 249 | } |
0 commit comments