aboutsummaryrefslogtreecommitdiffstats
path: root/src/vppinfra/qsort.c
AgeCommit message (Expand)AuthorFilesLines
2018-09-27Trivial: Cleanup some typos.Paul Vinciguerra1-1/+1
2016-12-28Reorganize source tree to use single autotools instanceDamjan Marion1-0/+269
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
diff --git a/scapy/layers/ipsec.py b/scapy/layers/ipsec.py
index 69e7ae3b..3a1724b2 100644
--- a/scapy/layers/ipsec.py
+++ b/scapy/layers/ipsec.py
@@ -344,8 +344,7 @@ class CryptAlgo(object):
             encryptor = cipher.encryptor()
 
             if self.is_aead:
-                aad = struct.pack('!LL', esp.spi, esp.seq)
-                encryptor.authenticate_additional_data(aad)
+                encryptor.authenticate_additional_data(sa.build_aead(esp))
                 data = encryptor.update(data) + encryptor.finalize()
                 data += encryptor.tag[:self.icv_size]
             else:
@@ -380,10 +379,7 @@ class CryptAlgo(object):
 
             if self.is_aead:
                 # Tag value check is done during the finalize method
-                decryptor.authenticate_additional_data(
-                    struct.pack('!LL', esp.spi, esp.seq)
-                )
-
+                decryptor.authenticate_additional_data(sa.build_aead(esp))
             try:
                 data = decryptor.update(data) + decryptor.finalize()
             except InvalidTag as err:
@@ -518,12 +514,16 @@ class AuthAlgo(object):
         else:
             return self.mac(key, self.digestmod(), default_backend())
 
-    def sign(self, pkt, key):
+    def sign(self, pkt, key, trailer=None):
         """
         Sign an IPsec (ESP or AH) packet with this algo.
 
         @param pkt:    a packet that contains a valid encrypted ESP or AH layer
         @param key:    the authentication key, a byte string
+        @param trailer: additional data appended to the packet for ICV
+                        calculation, but not trnasmitted with the packet.
+                        For example, the high order bits of the exteneded
+                        sequence number.
 
         @return: the signed packet
         """
@@ -534,16 +534,20 @@ class AuthAlgo(object):
 
         if pkt.haslayer(ESP):
             mac.update(raw(pkt[ESP]))
+            if trailer:
+                mac.update(trailer)
             pkt[ESP].data += mac.finalize()[:self.icv_size]
 
         elif pkt.haslayer(AH):
             clone = zero_mutable_fields(pkt.copy(), sending=True)
             mac.update(raw(clone))
+            if trailer:
+                mac.update(trailer)
             pkt[AH].icv = mac.finalize()[:self.icv_size]
 
         return pkt
 
-    def verify(self, pkt, key):
+    def verify(self, pkt, key, trailer):
         """
         Check that the integrity check value (icv) of a packet is valid.
 
@@ -574,6 +578,8 @@ class AuthAlgo(object):
             clone = zero_mutable_fields(pkt.copy(), sending=False)
 
         mac.update(raw(clone))
+        if trailer:
+            mac.update(trailer) # bytearray(4)) #raw(trailer))
         computed_icv = mac.finalize()[:self.icv_size]
 
         # XXX: Cannot use mac.verify because the ICV can be truncated
@@ -757,7 +763,8 @@ class SecurityAssociation(object):
     SUPPORTED_PROTOS = (IP, IPv6)
 
     def __init__(self, proto, spi, seq_num=1, crypt_algo=None, crypt_key=None,
-                 auth_algo=None, auth_key=None, tunnel_header=None, nat_t_header=None):
+                 auth_algo=None, auth_key=None, tunnel_header=None, nat_t_header=None,
+                 use_esn=False):
         """
         @param proto: the IPsec proto to use (ESP or AH)
         @param spi: the Security Parameters Index of this SA
@@ -771,6 +778,7 @@ class SecurityAssociation(object):
                               to encapsulate the encrypted packets.
         @param nat_t_header: an instance of a UDP header that will be used
                              for NAT-Traversal.
+        @param use_esn: Use Extended Sequence Numbers
         """
 
         if proto not in (ESP, AH, ESP.name, AH.name):
@@ -782,6 +790,7 @@ class SecurityAssociation(object):
 
         self.spi = spi
         self.seq_num = seq_num
+        self.use_esn = use_esn
 
         if crypt_algo:
             if crypt_algo not in CRYPT_ALGOS:
@@ -827,6 +836,23 @@ class SecurityAssociation(object):
             raise TypeError('packet spi=0x%x does not match the SA spi=0x%x' %
                             (pkt.spi, self.spi))
 
+    def build_aead(self, esp):
+        if self.use_esn:
+            return (struct.pack('!LLL', esp.spi, self.seq_num >> 32, esp.seq))
+        else:
+            return (struct.pack('!LL', esp.spi, esp.seq))
+
+    def build_seq_num(self, num):
+        # only lower order bits are  transmitted
+        # higher order bits are used in the ICV
+        lower = num & 0xffffffff
+        upper = num >> 32
+
+        if self.use_esn:
+            return lower, struct.pack("!I", upper)
+        else:
+            return lower, None
+
     def _encrypt_esp(self, pkt, seq_num=None, iv=None):
 
         if iv is None:
@@ -835,7 +861,8 @@ class SecurityAssociation(object):
             if len(iv) != self.crypt_algo.iv_size:
                 raise TypeError('iv length must be %s' % self.crypt_algo.iv_size)
 
-        esp = _ESPPlain(spi=self.spi, seq=seq_num or self.seq_num, iv=iv)
+        low_seq_num, high_seq_num = self.build_seq_num(seq_num or self.seq_num)
+        esp = _ESPPlain(spi=self.spi, seq=low_seq_num, iv=iv)
 
         if self.tunnel_header:
             tunnel = self.tunnel_header.copy()
@@ -857,7 +884,7 @@ class SecurityAssociation(object):
         esp = self.crypt_algo.pad(esp)
         esp = self.crypt_algo.encrypt(self, esp, self.crypt_key)
 
-        self.auth_algo.sign(esp, self.auth_key)
+        self.auth_algo.sign(esp, self.auth_key, high_seq_num)
 
         if self.nat_t_header:
             nat_t_header = self.nat_t_header.copy()
@@ -884,7 +911,8 @@ class SecurityAssociation(object):
 
     def _encrypt_ah(self, pkt, seq_num=None):
 
-        ah = AH(spi=self.spi, seq=seq_num or self.seq_num,
+        low_seq_num, high_seq_num = self.build_seq_num(seq_num or self.seq_num)
+        ah = AH(spi=self.spi, seq=low_seq_num,
                 icv = b"\x00" * self.auth_algo.icv_size)
 
         if self.tunnel_header:
@@ -924,7 +952,8 @@ class SecurityAssociation(object):
         else:
             ip_header.plen = len(ip_header.payload) + len(ah) + len(payload)
 
-        signed_pkt = self.auth_algo.sign(ip_header / ah / payload, self.auth_key)
+        signed_pkt = self.auth_algo.sign(ip_header / ah / payload,
+                                         self.auth_key, high_seq_num)
 
         # sequence number must always change, unless specified by the user
         if seq_num is None:
@@ -955,11 +984,12 @@ class SecurityAssociation(object):
 
     def _decrypt_esp(self, pkt, verify=True):
 
+        low_seq_num, high_seq_num = self.build_seq_num(self.seq_num)
         encrypted = pkt[ESP]
 
         if verify:
             self.check_spi(pkt)
-            self.auth_algo.verify(encrypted, self.auth_key)
+            self.auth_algo.verify(encrypted, self.auth_key, high_seq_num)
 
         esp = self.crypt_algo.decrypt(self, encrypted, self.crypt_key,
                                       self.crypt_algo.icv_size or
@@ -998,9 +1028,11 @@ class SecurityAssociation(object):
 
     def _decrypt_ah(self, pkt, verify=True):
 
+        low_seq_num, high_seq_num = self.build_seq_num(self.seq_num)
+
         if verify:
             self.check_spi(pkt)
-            self.auth_algo.verify(pkt, self.auth_key)
+            self.auth_algo.verify(pkt, self.auth_key, high_seq_num)
 
         ah = pkt[AH]
         payload = ah.payload