PageRenderTime 45ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/test/patches/scapy-2.4/ipsec.patch

https://gitlab.com/x1046882802/flexiroutervpp
Patch | 215 lines | 181 code | 34 blank | 0 comment | 0 complexity | 3cdb8739c192dbca1b2a5988c84efd0f MD5 | raw file
  1. diff --git a/scapy/layers/ipsec.py b/scapy/layers/ipsec.py
  2. index 69e7ae3b..d9c1705b 100644
  3. --- a/scapy/layers/ipsec.py
  4. +++ b/scapy/layers/ipsec.py
  5. @@ -344,8 +344,7 @@ class CryptAlgo(object):
  6. encryptor = cipher.encryptor()
  7. if self.is_aead:
  8. - aad = struct.pack('!LL', esp.spi, esp.seq)
  9. - encryptor.authenticate_additional_data(aad)
  10. + encryptor.authenticate_additional_data(sa.build_aead(esp))
  11. data = encryptor.update(data) + encryptor.finalize()
  12. data += encryptor.tag[:self.icv_size]
  13. else:
  14. @@ -380,10 +379,7 @@ class CryptAlgo(object):
  15. if self.is_aead:
  16. # Tag value check is done during the finalize method
  17. - decryptor.authenticate_additional_data(
  18. - struct.pack('!LL', esp.spi, esp.seq)
  19. - )
  20. -
  21. + decryptor.authenticate_additional_data(sa.build_aead(esp))
  22. try:
  23. data = decryptor.update(data) + decryptor.finalize()
  24. except InvalidTag as err:
  25. @@ -422,6 +418,7 @@ if algorithms:
  26. CRYPT_ALGOS['AES-CTR'] = CryptAlgo('AES-CTR',
  27. cipher=algorithms.AES,
  28. mode=modes.CTR,
  29. + block_size=1,
  30. iv_size=8,
  31. salt_size=4,
  32. format_mode_iv=_aes_ctr_format_mode_iv)
  33. @@ -429,6 +426,7 @@ if algorithms:
  34. CRYPT_ALGOS['AES-GCM'] = CryptAlgo('AES-GCM',
  35. cipher=algorithms.AES,
  36. mode=modes.GCM,
  37. + block_size=1,
  38. salt_size=4,
  39. iv_size=8,
  40. icv_size=16,
  41. @@ -437,6 +435,7 @@ if algorithms:
  42. CRYPT_ALGOS['AES-CCM'] = CryptAlgo('AES-CCM',
  43. cipher=algorithms.AES,
  44. mode=modes.CCM,
  45. + block_size=1,
  46. iv_size=8,
  47. salt_size=3,
  48. icv_size=16,
  49. @@ -518,12 +517,16 @@ class AuthAlgo(object):
  50. else:
  51. return self.mac(key, self.digestmod(), default_backend())
  52. - def sign(self, pkt, key):
  53. + def sign(self, pkt, key, trailer=None):
  54. """
  55. Sign an IPsec (ESP or AH) packet with this algo.
  56. @param pkt: a packet that contains a valid encrypted ESP or AH layer
  57. @param key: the authentication key, a byte string
  58. + @param trailer: additional data appended to the packet for ICV
  59. + calculation, but not trnasmitted with the packet.
  60. + For example, the high order bits of the exteneded
  61. + sequence number.
  62. @return: the signed packet
  63. """
  64. @@ -534,16 +537,20 @@ class AuthAlgo(object):
  65. if pkt.haslayer(ESP):
  66. mac.update(raw(pkt[ESP]))
  67. + if trailer:
  68. + mac.update(trailer)
  69. pkt[ESP].data += mac.finalize()[:self.icv_size]
  70. elif pkt.haslayer(AH):
  71. clone = zero_mutable_fields(pkt.copy(), sending=True)
  72. mac.update(raw(clone))
  73. + if trailer:
  74. + mac.update(trailer)
  75. pkt[AH].icv = mac.finalize()[:self.icv_size]
  76. return pkt
  77. - def verify(self, pkt, key):
  78. + def verify(self, pkt, key, trailer):
  79. """
  80. Check that the integrity check value (icv) of a packet is valid.
  81. @@ -574,6 +581,8 @@ class AuthAlgo(object):
  82. clone = zero_mutable_fields(pkt.copy(), sending=False)
  83. mac.update(raw(clone))
  84. + if trailer:
  85. + mac.update(trailer) # bytearray(4)) #raw(trailer))
  86. computed_icv = mac.finalize()[:self.icv_size]
  87. # XXX: Cannot use mac.verify because the ICV can be truncated
  88. @@ -757,7 +766,8 @@ class SecurityAssociation(object):
  89. SUPPORTED_PROTOS = (IP, IPv6)
  90. def __init__(self, proto, spi, seq_num=1, crypt_algo=None, crypt_key=None,
  91. - auth_algo=None, auth_key=None, tunnel_header=None, nat_t_header=None):
  92. + auth_algo=None, auth_key=None, tunnel_header=None, nat_t_header=None,
  93. + use_esn=False):
  94. """
  95. @param proto: the IPsec proto to use (ESP or AH)
  96. @param spi: the Security Parameters Index of this SA
  97. @@ -771,6 +781,7 @@ class SecurityAssociation(object):
  98. to encapsulate the encrypted packets.
  99. @param nat_t_header: an instance of a UDP header that will be used
  100. for NAT-Traversal.
  101. + @param use_esn: Use Extended Sequence Numbers
  102. """
  103. if proto not in (ESP, AH, ESP.name, AH.name):
  104. @@ -782,6 +793,7 @@ class SecurityAssociation(object):
  105. self.spi = spi
  106. self.seq_num = seq_num
  107. + self.use_esn = use_esn
  108. if crypt_algo:
  109. if crypt_algo not in CRYPT_ALGOS:
  110. @@ -827,6 +839,23 @@ class SecurityAssociation(object):
  111. raise TypeError('packet spi=0x%x does not match the SA spi=0x%x' %
  112. (pkt.spi, self.spi))
  113. + def build_aead(self, esp):
  114. + if self.use_esn:
  115. + return (struct.pack('!LLL', esp.spi, self.seq_num >> 32, esp.seq))
  116. + else:
  117. + return (struct.pack('!LL', esp.spi, esp.seq))
  118. +
  119. + def build_seq_num(self, num):
  120. + # only lower order bits are transmitted
  121. + # higher order bits are used in the ICV
  122. + lower = num & 0xffffffff
  123. + upper = num >> 32
  124. +
  125. + if self.use_esn:
  126. + return lower, struct.pack("!I", upper)
  127. + else:
  128. + return lower, None
  129. +
  130. def _encrypt_esp(self, pkt, seq_num=None, iv=None):
  131. if iv is None:
  132. @@ -835,7 +864,8 @@ class SecurityAssociation(object):
  133. if len(iv) != self.crypt_algo.iv_size:
  134. raise TypeError('iv length must be %s' % self.crypt_algo.iv_size)
  135. - esp = _ESPPlain(spi=self.spi, seq=seq_num or self.seq_num, iv=iv)
  136. + low_seq_num, high_seq_num = self.build_seq_num(seq_num or self.seq_num)
  137. + esp = _ESPPlain(spi=self.spi, seq=low_seq_num, iv=iv)
  138. if self.tunnel_header:
  139. tunnel = self.tunnel_header.copy()
  140. @@ -857,7 +887,7 @@ class SecurityAssociation(object):
  141. esp = self.crypt_algo.pad(esp)
  142. esp = self.crypt_algo.encrypt(self, esp, self.crypt_key)
  143. - self.auth_algo.sign(esp, self.auth_key)
  144. + self.auth_algo.sign(esp, self.auth_key, high_seq_num)
  145. if self.nat_t_header:
  146. nat_t_header = self.nat_t_header.copy()
  147. @@ -884,7 +914,8 @@ class SecurityAssociation(object):
  148. def _encrypt_ah(self, pkt, seq_num=None):
  149. - ah = AH(spi=self.spi, seq=seq_num or self.seq_num,
  150. + low_seq_num, high_seq_num = self.build_seq_num(seq_num or self.seq_num)
  151. + ah = AH(spi=self.spi, seq=low_seq_num,
  152. icv = b"\x00" * self.auth_algo.icv_size)
  153. if self.tunnel_header:
  154. @@ -924,7 +955,8 @@ class SecurityAssociation(object):
  155. else:
  156. ip_header.plen = len(ip_header.payload) + len(ah) + len(payload)
  157. - signed_pkt = self.auth_algo.sign(ip_header / ah / payload, self.auth_key)
  158. + signed_pkt = self.auth_algo.sign(ip_header / ah / payload,
  159. + self.auth_key, high_seq_num)
  160. # sequence number must always change, unless specified by the user
  161. if seq_num is None:
  162. @@ -955,11 +987,12 @@ class SecurityAssociation(object):
  163. def _decrypt_esp(self, pkt, verify=True):
  164. + low_seq_num, high_seq_num = self.build_seq_num(self.seq_num)
  165. encrypted = pkt[ESP]
  166. if verify:
  167. self.check_spi(pkt)
  168. - self.auth_algo.verify(encrypted, self.auth_key)
  169. + self.auth_algo.verify(encrypted, self.auth_key, high_seq_num)
  170. esp = self.crypt_algo.decrypt(self, encrypted, self.crypt_key,
  171. self.crypt_algo.icv_size or
  172. @@ -998,9 +1031,11 @@ class SecurityAssociation(object):
  173. def _decrypt_ah(self, pkt, verify=True):
  174. + low_seq_num, high_seq_num = self.build_seq_num(self.seq_num)
  175. +
  176. if verify:
  177. self.check_spi(pkt)
  178. - self.auth_algo.verify(pkt, self.auth_key)
  179. + self.auth_algo.verify(pkt, self.auth_key, high_seq_num)
  180. ah = pkt[AH]
  181. payload = ah.payload