tls-attacker / TLS-Attacker

TLS-Attacker is a Java-based framework for analyzing TLS libraries. It can be used to manually test TLS clients and servers or as as a software library for more advanced tools.
Apache License 2.0
789 stars 136 forks source link

help for sending HelloRetryRequest #91

Closed ghost closed 3 years ago

ghost commented 3 years ago

Need example how to send HelloRetryRequest

mmaehren commented 3 years ago

Hi, the current public branch of TLS-Attacker only supports the HelloRetryRequest used in an older draft of TLS 1.3. You can construct your own HelloRetryRequest using a ServerHello and ModifiableVariables like this:

ServerHelloMessage serverHello = new ServerHelloMessage(tlsConfig);
serverHello.setRandom(Modifiable.explicit(new byte[] { (byte) 0xCF, (byte) 0x21, (byte) 0xAD,
            (byte) 0x74, (byte) 0xE5, (byte) 0x9A, (byte) 0x61, (byte) 0x11, (byte) 0xBE, (byte) 0x1D, (byte) 0x8C,
            (byte) 0x02, (byte) 0x1E, (byte) 0x65, (byte) 0xB8, (byte) 0x91, (byte) 0xC2, (byte) 0xA2, (byte) 0x11,
            (byte) 0x16, (byte) 0x7A, (byte) 0xBB, (byte) 0x8C, (byte) 0x5E, (byte) 0x07, (byte) 0x9E, (byte) 0x09,
            (byte) 0xE2, (byte) 0xC8, (byte) 0xA8, (byte) 0x33, (byte) 0x9C }));

To request a specific NamedGroup from the client you add a KeyShareExtension like this:

KeyShareExtensionMessage keyShareExtension = new KeyShareExtensionMessage();
keyShareExtension.setKeyShareListBytes(Modifiable.explicit(NamedGroup.ECDH_X25519.getValue()));
serverHello.addExtension(keyShareExtension);

You can then add this message to your WorkflowTrace. Please note that eventhough this results in a HelloRetryRequest, TLS-Attacker won't be able to complete a handshake with a new ClientHello sent in response by the client. This is due to how the initial ClientHello influences the message digest in the final version of the TLS 1.3 specification. Our development branch fully supports the new HelloRetryRequest mechanism, but it is still undergoing internal testing.

mmaehren commented 3 years ago

In case that you preffer to use XML, you can create a WorkflowTrace that waits for a ClientHello and sends a HelloRetryRequest like this:

<workflowTrace>
  <Receive>
    <expectedMessages>
     <ClientHello/>
    </expectedMessages>
  </Receive>
  <Send>
   <messages>
     <ServerHello>
       <extensions>
         <KeyShareExtension>
           <keyShareListBytes>
             <byteArrayExplicitValueModification>
               <explicitValue>0017</explicitValue>
             </byteArrayExplicitValueModification>
           </keyShareListBytes>
     </KeyShareExtension>
     <SupportedVersions/>
       </extensions>
       <random>
    <byteArrayExplicitValueModification>
      <explicitValue>CF21AD74E59A6111BE1D8C021E65B891C2A211167ABB8C5E079E09E2C8A8339C</explicitValue>
    </byteArrayExplicitValueModification>
       </random>
     </ServerHello>
   </messages>
  </Send>
</workflowTrace>

This also requires a config for TLS 1.3 like the example config under /resources/configs/

ghost commented 3 years ago

I need to send HelloRetryRequest From Client side

mmaehren commented 3 years ago

Since we include additional required lengthfields for extensions depending on if the client or server is sending it, you have to set all bytes for the KeyShare and SupportedVersionsExtension yourself:

<ServerHello>
  <extensions>
    <KeyShareExtension>
      <extensionBytes>
        <byteArrayExplicitValueModification>
           <explicitValue>003300020017</explicitValue>
         </byteArrayExplicitValueModification>
      </extensionBytes>
    </KeyShareExtension>
      <SupportedVersions>
       <extensionBytes>
          <byteArrayExplicitValueModification>
             <explicitValue>002b00020304</explicitValue>
           </byteArrayExplicitValueModification>
        </extensionBytes>
      </SupportedVersions>
  </extensions>
  <random>
      <byteArrayExplicitValueModification> 
        <explicitValue>CF21AD74E59A6111BE1D8C021E65B891C2A211167ABB8C5E079E09E2C8A8339C</explicitValue>
      </byteArrayExplicitValueModification>
  </random>
</ServerHello>

Or in code:

ServerHelloMessage serverHello = new ServerHelloMessage(tlsConfig);
serverHello.setRandom(Modifiable.explicit(new byte[] { (byte) 0xCF, (byte) 0x21, (byte) 0xAD,
            (byte) 0x74, (byte) 0xE5, (byte) 0x9A, (byte) 0x61, (byte) 0x11, (byte) 0xBE, (byte) 0x1D, (byte) 0x8C,
            (byte) 0x02, (byte) 0x1E, (byte) 0x65, (byte) 0xB8, (byte) 0x91, (byte) 0xC2, (byte) 0xA2, (byte) 0x11,
            (byte) 0x16, (byte) 0x7A, (byte) 0xBB, (byte) 0x8C, (byte) 0x5E, (byte) 0x07, (byte) 0x9E, (byte) 0x09,
            (byte) 0xE2, (byte) 0xC8, (byte) 0xA8, (byte) 0x33, (byte) 0x9C }));
byte[] keyShareExtension = ArrayConverter.hexStringToByteArray("003300020017");
byte[] supportedVersionsExtension = ArrayConverter.hexStringToByteArray("002b00020304"); 
serverHello.getExtension(KeyShareExtensionMessage.class).setExtensionBytes(Modifiable.explicit(keyShareExtension));
serverHello.getExtension(SupportedVersionsExtensionMessage.class).setExtensionBytes(Modifiable.explicit(supportedVersionsExtension));
ic0ns commented 3 years ago

HelloRetryRequests are now properly implemented and do not need this hack anymore