blob: 7ee8316bce36bd36364741db0eb708f82c013f42 [file] [log] [blame]
snaramre5d4b8912019-12-13 23:39:35 +00001diff --git a/scapy/layers/ipsec.py b/scapy/layers/ipsec.py
2index f8c601fa..f566d288 100644
3--- a/scapy/layers/ipsec.py
4+++ b/scapy/layers/ipsec.py
Neale Rannsabc56602020-04-01 09:45:23 +00005@@ -138,6 +138,7 @@ bind_layers(IP, ESP, proto=socket.IPPROTO_ESP)
6 bind_layers(IPv6, ESP, nh=socket.IPPROTO_ESP)
7 bind_layers(UDP, ESP, dport=4500) # NAT-Traversal encapsulation
8 bind_layers(UDP, ESP, sport=4500) # NAT-Traversal encapsulation
9+bind_layers(UDP, ESP, dport=4545) # NAT-Traversal encapsulation - random port
10
11 ###############################################################################
12
snaramre5d4b8912019-12-13 23:39:35 +000013@@ -359,11 +359,8 @@ class CryptAlgo(object):
14 encryptor = cipher.encryptor()
15
16 if self.is_aead:
17- if esn_en:
18- aad = struct.pack('!LLL', esp.spi, esn, esp.seq)
19- else:
20- aad = struct.pack('!LL', esp.spi, esp.seq)
21- encryptor.authenticate_additional_data(aad)
22+ encryptor.authenticate_additional_data(sa.build_aead(esp))
23+
24 data = encryptor.update(data) + encryptor.finalize()
25 data += encryptor.tag[:self.icv_size]
26 else:
27@@ -401,12 +398,7 @@ class CryptAlgo(object):
28
29 if self.is_aead:
30 # Tag value check is done during the finalize method
31- if esn_en:
32- decryptor.authenticate_additional_data(
33- struct.pack('!LLL', esp.spi, esn, esp.seq))
34- else:
35- decryptor.authenticate_additional_data(
36- struct.pack('!LL', esp.spi, esp.seq))
37+ decryptor.authenticate_additional_data(sa.build_aead(esp))
38 try:
39 data = decryptor.update(data) + decryptor.finalize()
40 except InvalidTag as err:
41@@ -545,7 +537,7 @@ class AuthAlgo(object):
42 else:
43 return self.mac(key, self.digestmod(), default_backend())
44
45- def sign(self, pkt, key):
46+ def sign(self, pkt, key, trailer=None):
47 """
48 Sign an IPsec (ESP or AH) packet with this algo.
49
50@@ -561,16 +553,20 @@ class AuthAlgo(object):
51
52 if pkt.haslayer(ESP):
53 mac.update(raw(pkt[ESP]))
54+ if trailer:
55+ mac.update(trailer)
56 pkt[ESP].data += mac.finalize()[:self.icv_size]
57
58 elif pkt.haslayer(AH):
59 clone = zero_mutable_fields(pkt.copy(), sending=True)
60 mac.update(raw(clone))
61+ if trailer:
62+ mac.update(trailer)
63 pkt[AH].icv = mac.finalize()[:self.icv_size]
64
65 return pkt
66
67- def verify(self, pkt, key):
68+ def verify(self, pkt, key, trailer):
69 """
70 Check that the integrity check value (icv) of a packet is valid.
71
72@@ -602,6 +598,8 @@ class AuthAlgo(object):
73 clone = zero_mutable_fields(pkt.copy(), sending=False)
74
75 mac.update(raw(clone))
76+ if trailer:
77+ mac.update(trailer) # bytearray(4)) #raw(trailer))
78 computed_icv = mac.finalize()[:self.icv_size]
79
80 # XXX: Cannot use mac.verify because the ICV can be truncated
81@@ -864,6 +862,23 @@ class SecurityAssociation(object):
82 raise TypeError('nat_t_header must be %s' % UDP.name)
83 self.nat_t_header = nat_t_header
84
85+ def build_aead(self, esp):
86+ if self.esn_en:
87+ return (struct.pack('!LLL', esp.spi, self.seq_num >> 32, esp.seq))
88+ else:
89+ return (struct.pack('!LL', esp.spi, esp.seq))
90+
91+ def build_seq_num(self, num):
92+ # only lower order bits are transmitted
93+ # higher order bits are used in the ICV
94+ lower = num & 0xffffffff
95+ upper = num >> 32
96+
97+ if self.esn_en:
98+ return lower, struct.pack("!I", upper)
99+ else:
100+ return lower, None
101+
102 def check_spi(self, pkt):
103 if pkt.spi != self.spi:
104 raise TypeError('packet spi=0x%x does not match the SA spi=0x%x' %
105@@ -877,7 +892,8 @@ class SecurityAssociation(object):
106 if len(iv) != self.crypt_algo.iv_size:
107 raise TypeError('iv length must be %s' % self.crypt_algo.iv_size) # noqa: E501
108
109- esp = _ESPPlain(spi=self.spi, seq=seq_num or self.seq_num, iv=iv)
110+ low_seq_num, high_seq_num = self.build_seq_num(seq_num or self.seq_num)
111+ esp = _ESPPlain(spi=self.spi, seq=low_seq_num, iv=iv)
112
113 if self.tunnel_header:
114 tunnel = self.tunnel_header.copy()
115@@ -901,7 +917,7 @@ class SecurityAssociation(object):
116 esn_en=esn_en or self.esn_en,
117 esn=esn or self.esn)
118
119- self.auth_algo.sign(esp, self.auth_key)
120+ self.auth_algo.sign(esp, self.auth_key, high_seq_num)
121
122 if self.nat_t_header:
123 nat_t_header = self.nat_t_header.copy()
124@@ -928,7 +944,8 @@ class SecurityAssociation(object):
125
126 def _encrypt_ah(self, pkt, seq_num=None):
127
128- ah = AH(spi=self.spi, seq=seq_num or self.seq_num,
129+ low_seq_num, high_seq_num = self.build_seq_num(seq_num or self.seq_num)
130+ ah = AH(spi=self.spi, seq=low_seq_num,
131 icv=b"\x00" * self.auth_algo.icv_size)
132
133 if self.tunnel_header:
134@@ -968,7 +985,8 @@ class SecurityAssociation(object):
135 else:
136 ip_header.plen = len(ip_header.payload) + len(ah) + len(payload)
137
138- signed_pkt = self.auth_algo.sign(ip_header / ah / payload, self.auth_key) # noqa: E501
139+ signed_pkt = self.auth_algo.sign(ip_header / ah / payload,
140+ self.auth_key, high_seq_num) # noqa: E501
141
142 # sequence number must always change, unless specified by the user
143 if seq_num is None:
144@@ -1005,11 +1023,12 @@ class SecurityAssociation(object):
145
146 def _decrypt_esp(self, pkt, verify=True, esn_en=None, esn=None):
147
148+ low_seq_num, high_seq_num = self.build_seq_num(self.seq_num)
149 encrypted = pkt[ESP]
150
151 if verify:
152 self.check_spi(pkt)
153- self.auth_algo.verify(encrypted, self.auth_key)
154+ self.auth_algo.verify(encrypted, self.auth_key, high_seq_num)
155
156 esp = self.crypt_algo.decrypt(self, encrypted, self.crypt_key,
157 self.crypt_algo.icv_size or
Neale Rannsabc56602020-04-01 09:45:23 +0000158@@ -1050,11 +1069,12 @@ class SecurityAssociation(object):
snaramre5d4b8912019-12-13 23:39:35 +0000159
160 def _decrypt_ah(self, pkt, verify=True):
161
162+ low_seq_num, high_seq_num = self.build_seq_num(self.seq_num)
163 if verify:
164 self.check_spi(pkt)
165- self.auth_algo.verify(pkt, self.auth_key)
166+ self.auth_algo.verify(pkt, self.auth_key, high_seq_num)
167
168 ah = pkt[AH]
169 payload = ah.payload
170
Neale Rannsabc56602020-04-01 09:45:23 +0000171