ipsec: User can choose the UDP source port
[vpp.git] / test / patches / scapy-2.4.3 / ipsec.patch
1 diff --git a/scapy/layers/ipsec.py b/scapy/layers/ipsec.py
2 index f8c601fa..f566d288 100644
3 --- a/scapy/layers/ipsec.py
4 +++ b/scapy/layers/ipsec.py
5 @@ -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
13 @@ -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
158 @@ -1050,11 +1069,12 @@ class SecurityAssociation(object):
159  
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
171