In TLSClientKeyExchange elliptic curve exchange keys include the length byte
Brief description
When defining an TLSClientKeyExchange object in the exchangekeys field the length byte is included, although its named "exchkeys"
Scapy version
2.6.0rc1
Python version
3.10.12
Operating system
Ubuntu 22.04.2 LTS
Additional environment information
No response
How to reproduce
clientkeyexchange_bytes = bytes.fromhex(
"100000424104b7378d5a30c8e2e24e58b9b43fae9ec7eae275b04e4e98e6607d937870e375b56f4053e412f5f1d26e9a04c2ffe1821bfbf9ac0b590cc3a337238fb45bd53c0d"
)
tls_client_key_exchange = TLSClientKeyExchange(clientkeyexchange_bytes)
print(tls_client_key_exchange.exchkeys.load.hex())
Actual result
4104b7378d5a30c8e2e24e58b9b43fae9ec7eae275b04e4e98e6607d937870e375b56f4053e412f5f1d26e9a04c2ffe1821bfbf9ac0b590cc3a337238fb45bd53c0d
Expected result
04b7378d5a30c8e2e24e58b9b43fae9ec7eae275b04e4e98e6607d937870e375b56f4053e412f5f1d26e9a04c2ffe1821bfbf9ac0b590cc3a337238fb45bd53c0d
The first byte differs
Related resources
No response
I don't really see why you would be expecting this result. Can you share a pcap, wireshark result or something more explicit?
The first byte is just the length byte. If you for example try to derive the keys normally it shouldnt be in there. I mean normally as a developer you could just ignore the first length
byte so it isn't really unavoidable to fix this. So you'd need to do this:
EllipticCurvePublicKey.from_encoded_point(curve_func, client_key_exchange.exchkeys.load[1:])
I'll include the wireshark logs. This is the code for the keyexchange:
my_key_exchange = bytes.fromhex('10000042410477ad56d41fe2e9df347001f3e1f9299066b2c78770f5274a28654d1cf6f45e62a67872a37444e72362118332520c8d435cbf70fce701af100028856b9d72ea39')
tls_my_key_exchange = TLSClientKeyExchange(my_key_exchange)
print(tls_my_key_exchange.exchkeys.load.hex())
This would return
410477ad56d41fe2e9df347001f3e1f9299066b2c78770f5274a28654d1cf6f45e62a67872a37444e72362118332520c8d435cbf70fce701af100028856b9d72ea39
As you can see in the wireshark logs: In the client key exchange and EC Diffie-Hellman Client Params the pubkey is:
0477ad56d41fe2e9df347001f3e1f9299066b2c78770f5274a28654d1cf6f45e62a67872a37444e72362118332520c8d435cbf70fce701af100028856b9d72ea39
The first byte 41 is the length in hex (65 bytes length key). Theoretically you could include the length byte (maybe in a separate field?) Technically it is part in the client params (but not part of the publickey) so I'm not exactly sure if you'd consider this a bug.
Sorry for the late response and Regards test_exchange_keys.zip
That's expected, that's how our implementation sticks to the spec.
You'll notice there isn't a 'len' field in the spec: https://datatracker.ietf.org/doc/html/rfc5246#appendix-A.4.3
In your case, you'd parse it via:
clientkeyexchange_bytes = bytes.fromhex("100000424104b7378d5a30c8e2e24e58b9b43fae9ec7eae275b04e4e98e6607d937870e375b56f4053e412f5f1d26e9a04c2ffe1821bfbf9ac0b590cc3a337238fb45bd53c0d")
tls_client_key_exchange = TLSClientKeyExchange(clientkeyexchange_bytes)
ClientECDiffieHellmanPublic(tls_client_key_exchange.exchkeys.load)
I don't know how you're parsing those blobs, but remember that you can set conf.tls_session_enable = True to have Scapy properly remember how to parse those things.