[TLS] bytes(TLS_Ext_CSR) gives wrong result when TLS_Ext_CSR.len=0
Brief description
bytes(TLS_Ext_CSR) returns one additional byte when with TLS_Ext_CSR.len=0
The reason should be that:
- raw_packet_cache is not considered in
_GenericTLSSessionInheritance.__bytes__() -
<Field (TLS_Ext_CSR).stype>.i2m()method returns 0 even if val is None.
Environment
- Scapy version: 2.4.0.dev601
- Python: 3.6.5
- Operating System: Ubuntu
How to reproduce
ext_csr = TLS_Ext_CSR(b'\x00\x05\x00\x00')
>>> ext_csr.show()
###[ TLS Extension - Certificate Status Request ]###
type = status_request
len = 0
stype = None
\req \
Actual result
>>> bytes(ext_csr)
b'\x00\x05\x00\x00\x00'
Expected result
>>> ext_csr.raw_packet_cache
b'\x00\x05\x00\x00'
As a consequence, the length (and bytes) of the TCP payload is also wrong, e.g. in the example in the picture, instead of length=1360:
>>> len(pkt[TCP].payload)
1361

Related resources
traces / sample pcaps (stripped to the relevant frames), related standards, RFCs or other resources
I have been reading the RFC4366 and I think that current Scapy behavior is correct. I believe that the best solution is to use TLS_Ext_Unknown(type=5, len=0) to generate such extension.
Is is something that you are trying to inject, of sniff from the network? Could you share some packets? I did not manage to capture similar ones.
Sorry, I cannot retrieve the packet. I was sniffing from the network, the picture is a real case.
If I understand correctly, you sniffed the Server Hello message, dissected it with Scapy, then tried to build it again?
The real extension was 4 bytes, but Scapy returned 5. Am I correct?
I sniffed Server Hello.
len(bytes(pkt[TCP])) gives 1380, which is correct.
len(bytes(pkt[TCP].payload)) gives 1361 bytes instead of 1360, as in picture.
bytes(pkt[TCP][TLS_Ext_CSR]) gives b'\x00\x05\x00\x00\x00'.
bytes(pkt[TCP][TLS_Ext_CSR].raw_packet_cache) gives b'\x00\x05\x00\x00', as it should be per picture. From here the extra byte in overall length 1361 vs. 1360.
The example above is reconstructing just the TLS Ext for sake of easy reproduction, the results is the same.
Thanks for the report.
I will try to find a correct fix. As of today, Scapy encodes the Certificate Status Request on 5 bytes. It still did not find an explanation in RFCs but other implementations seem to consider that empty extensions exist and are encoder on 4 bytes.
Scapy encodes on 5 bytes due to:
- raw_packet_cache is not considered in _GenericTLSSessionInheritance.bytes()
- <Field (TLS_Ext_CSR).stype>.i2m() method returns 0 even if val is None.
I do not know if this is wanted due to an RFC or not.
Fixed (indirectly) by #4012.