blob: 5e2625d021134360748168691a36bdaef5540fc7 [file] [log] [blame]
Filip Tehlar12b517b2020-04-26 18:05:05 +00001import os
Filip Tehlar2008e312020-11-09 13:23:24 +00002import time
Filip Tehlarec112e52020-10-07 23:52:37 +00003from socket import inet_pton
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00004from cryptography import x509
Filip Tehlar12b517b2020-04-26 18:05:05 +00005from cryptography.hazmat.backends import default_backend
6from cryptography.hazmat.primitives import hashes, hmac
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00007from cryptography.hazmat.primitives.asymmetric import dh, padding
8from cryptography.hazmat.primitives.serialization import load_pem_private_key
Filip Tehlar12b517b2020-04-26 18:05:05 +00009from cryptography.hazmat.primitives.ciphers import (
10 Cipher,
11 algorithms,
12 modes,
13)
Filip Tehlar84962d12020-09-08 06:08:05 +000014from ipaddress import IPv4Address, IPv6Address, ip_address
Paul Vinciguerrae061dad2020-12-04 14:57:51 -050015import unittest
Klement Sekerab23ffd72021-05-31 16:08:53 +020016from config import config
Filip Tehlarbfeae8c2020-06-23 20:35:58 +000017from scapy.layers.ipsec import ESP
Filip Tehlar12b517b2020-04-26 18:05:05 +000018from scapy.layers.inet import IP, UDP, Ether
Filip Tehlar84962d12020-09-08 06:08:05 +000019from scapy.layers.inet6 import IPv6
Filip Tehlar12b517b2020-04-26 18:05:05 +000020from scapy.packet import raw, Raw
21from scapy.utils import long_converter
Dave Wallace670724c2022-09-20 21:52:18 -040022from framework import tag_fixme_vpp_workers, tag_fixme_ubuntu2204, tag_fixme_debian11
23from framework import is_distro_ubuntu2204, is_distro_debian11
Filip Tehlar12b517b2020-04-26 18:05:05 +000024from framework import VppTestCase, VppTestRunner
Filip Tehlarbfeae8c2020-06-23 20:35:58 +000025from vpp_ikev2 import Profile, IDType, AuthMethod
Filip Tehlar4f42a712020-07-01 08:56:59 +000026from vpp_papi import VppEnum
Filip Tehlar12b517b2020-04-26 18:05:05 +000027
Filip Tehlar84962d12020-09-08 06:08:05 +000028try:
29 text_type = unicode
30except NameError:
31 text_type = str
Filip Tehlar12b517b2020-04-26 18:05:05 +000032
33KEY_PAD = b"Key Pad for IKEv2"
Filip Tehlara7b963d2020-07-08 13:25:34 +000034SALT_SIZE = 4
35GCM_ICV_SIZE = 16
36GCM_IV_SIZE = 8
Filip Tehlar12b517b2020-04-26 18:05:05 +000037
38
39# defined in rfc3526
40# tuple structure is (p, g, key_len)
41DH = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020042 "2048MODPgr": (
43 long_converter(
44 """
Filip Tehlar12b517b2020-04-26 18:05:05 +000045 FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
46 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
47 EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
48 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
49 EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
50 C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
51 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
52 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
53 E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
54 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020055 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF"""
56 ),
57 2,
58 256,
59 ),
60 "3072MODPgr": (
61 long_converter(
62 """
Filip Tehlar4f42a712020-07-01 08:56:59 +000063 FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
64 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
65 EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
66 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
67 EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
68 C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
69 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
70 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
71 E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
72 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
73 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64
74 ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7
75 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B
76 F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
77 BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020078 43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF"""
79 ),
80 2,
81 384,
82 ),
Filip Tehlar12b517b2020-04-26 18:05:05 +000083}
84
85
86class CryptoAlgo(object):
87 def __init__(self, name, cipher, mode):
88 self.name = name
89 self.cipher = cipher
90 self.mode = mode
91 if self.cipher is not None:
92 self.bs = self.cipher.block_size // 8
93
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020094 if self.name == "AES-GCM-16ICV":
Filip Tehlara7b963d2020-07-08 13:25:34 +000095 self.iv_len = GCM_IV_SIZE
96 else:
97 self.iv_len = self.bs
Filip Tehlar12b517b2020-04-26 18:05:05 +000098
Filip Tehlara7b963d2020-07-08 13:25:34 +000099 def encrypt(self, data, key, aad=None):
100 iv = os.urandom(self.iv_len)
101 if aad is None:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200102 encryptor = Cipher(
103 self.cipher(key), self.mode(iv), default_backend()
104 ).encryptor()
Filip Tehlara7b963d2020-07-08 13:25:34 +0000105 return iv + encryptor.update(data) + encryptor.finalize()
106 else:
107 salt = key[-SALT_SIZE:]
108 nonce = salt + iv
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200109 encryptor = Cipher(
110 self.cipher(key[:-SALT_SIZE]), self.mode(nonce), default_backend()
111 ).encryptor()
Filip Tehlara7b963d2020-07-08 13:25:34 +0000112 encryptor.authenticate_additional_data(aad)
113 data = encryptor.update(data) + encryptor.finalize()
114 data += encryptor.tag[:GCM_ICV_SIZE]
115 return iv + data
116
117 def decrypt(self, data, key, aad=None, icv=None):
118 if aad is None:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200119 iv = data[: self.iv_len]
120 ct = data[self.iv_len :]
121 decryptor = Cipher(
122 algorithms.AES(key), self.mode(iv), default_backend()
123 ).decryptor()
Filip Tehlara7b963d2020-07-08 13:25:34 +0000124 return decryptor.update(ct) + decryptor.finalize()
125 else:
126 salt = key[-SALT_SIZE:]
127 nonce = salt + data[:GCM_IV_SIZE]
128 ct = data[GCM_IV_SIZE:]
129 key = key[:-SALT_SIZE]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200130 decryptor = Cipher(
131 algorithms.AES(key), self.mode(nonce, icv, len(icv)), default_backend()
132 ).decryptor()
Filip Tehlara7b963d2020-07-08 13:25:34 +0000133 decryptor.authenticate_additional_data(aad)
Filip Tehlaredf29002020-10-10 04:39:11 +0000134 return decryptor.update(ct) + decryptor.finalize()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000135
136 def pad(self, data):
137 pad_len = (len(data) // self.bs + 1) * self.bs - len(data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200138 data = data + b"\x00" * (pad_len - 1)
Filip Tehlar558607d2020-07-16 07:25:56 +0000139 return data + bytes([pad_len - 1])
Filip Tehlar12b517b2020-04-26 18:05:05 +0000140
141
142class AuthAlgo(object):
143 def __init__(self, name, mac, mod, key_len, trunc_len=None):
144 self.name = name
145 self.mac = mac
146 self.mod = mod
147 self.key_len = key_len
148 self.trunc_len = trunc_len or key_len
149
150
151CRYPTO_ALGOS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200152 "NULL": CryptoAlgo("NULL", cipher=None, mode=None),
153 "AES-CBC": CryptoAlgo("AES-CBC", cipher=algorithms.AES, mode=modes.CBC),
154 "AES-GCM-16ICV": CryptoAlgo("AES-GCM-16ICV", cipher=algorithms.AES, mode=modes.GCM),
Filip Tehlar12b517b2020-04-26 18:05:05 +0000155}
156
157AUTH_ALGOS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200158 "NULL": AuthAlgo("NULL", mac=None, mod=None, key_len=0, trunc_len=0),
159 "HMAC-SHA1-96": AuthAlgo("HMAC-SHA1-96", hmac.HMAC, hashes.SHA1, 20, 12),
160 "SHA2-256-128": AuthAlgo("SHA2-256-128", hmac.HMAC, hashes.SHA256, 32, 16),
161 "SHA2-384-192": AuthAlgo("SHA2-384-192", hmac.HMAC, hashes.SHA256, 48, 24),
162 "SHA2-512-256": AuthAlgo("SHA2-512-256", hmac.HMAC, hashes.SHA256, 64, 32),
Filip Tehlar12b517b2020-04-26 18:05:05 +0000163}
164
165PRF_ALGOS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200166 "NULL": AuthAlgo("NULL", mac=None, mod=None, key_len=0, trunc_len=0),
167 "PRF_HMAC_SHA2_256": AuthAlgo("PRF_HMAC_SHA2_256", hmac.HMAC, hashes.SHA256, 32),
Filip Tehlar12b517b2020-04-26 18:05:05 +0000168}
169
Filip Tehlar68ad6252020-10-30 05:28:11 +0000170CRYPTO_IDS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200171 12: "AES-CBC",
172 20: "AES-GCM-16ICV",
Filip Tehlar68ad6252020-10-30 05:28:11 +0000173}
174
175INTEG_IDS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200176 2: "HMAC-SHA1-96",
177 12: "SHA2-256-128",
178 13: "SHA2-384-192",
179 14: "SHA2-512-256",
Filip Tehlar68ad6252020-10-30 05:28:11 +0000180}
181
Filip Tehlar12b517b2020-04-26 18:05:05 +0000182
183class IKEv2ChildSA(object):
Filip Tehlar68ad6252020-10-30 05:28:11 +0000184 def __init__(self, local_ts, remote_ts, is_initiator):
185 spi = os.urandom(4)
186 if is_initiator:
187 self.ispi = spi
188 self.rspi = None
189 else:
190 self.rspi = spi
191 self.ispi = None
Filip Tehlar12b517b2020-04-26 18:05:05 +0000192 self.local_ts = local_ts
193 self.remote_ts = remote_ts
194
195
196class IKEv2SA(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200197 def __init__(
198 self,
199 test,
200 is_initiator=True,
201 i_id=None,
202 r_id=None,
203 spi=b"\x01\x02\x03\x04\x05\x06\x07\x08",
204 id_type="fqdn",
205 nonce=None,
206 auth_data=None,
207 local_ts=None,
208 remote_ts=None,
209 auth_method="shared-key",
210 priv_key=None,
211 i_natt=False,
212 r_natt=False,
213 udp_encap=False,
214 ):
Filip Tehlar67b8a7f2020-11-06 11:00:42 +0000215 self.udp_encap = udp_encap
Filip Tehlar027d8132020-12-04 17:38:11 +0000216 self.i_natt = i_natt
217 self.r_natt = r_natt
218 if i_natt or r_natt:
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000219 self.sport = 4500
220 self.dport = 4500
221 else:
222 self.sport = 500
223 self.dport = 500
Filip Tehlar558607d2020-07-16 07:25:56 +0000224 self.msg_id = 0
Filip Tehlar12b517b2020-04-26 18:05:05 +0000225 self.dh_params = None
226 self.test = test
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000227 self.priv_key = priv_key
Filip Tehlar12b517b2020-04-26 18:05:05 +0000228 self.is_initiator = is_initiator
229 nonce = nonce or os.urandom(32)
230 self.auth_data = auth_data
Filip Tehlar4128c7b2020-05-10 05:18:37 +0000231 self.i_id = i_id
232 self.r_id = r_id
Filip Tehlar12b517b2020-04-26 18:05:05 +0000233 if isinstance(id_type, str):
234 self.id_type = IDType.value(id_type)
235 else:
236 self.id_type = id_type
237 self.auth_method = auth_method
238 if self.is_initiator:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200239 self.rspi = 8 * b"\x00"
Filip Tehlar12b517b2020-04-26 18:05:05 +0000240 self.ispi = spi
Filip Tehlar12b517b2020-04-26 18:05:05 +0000241 self.i_nonce = nonce
242 else:
243 self.rspi = spi
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200244 self.ispi = 8 * b"\x00"
Filip Tehlare7c83962020-09-23 11:20:12 +0000245 self.r_nonce = nonce
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200246 self.child_sas = [IKEv2ChildSA(local_ts, remote_ts, self.is_initiator)]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000247
Filip Tehlar558607d2020-07-16 07:25:56 +0000248 def new_msg_id(self):
249 self.msg_id += 1
250 return self.msg_id
251
Filip Tehlare7c83962020-09-23 11:20:12 +0000252 @property
253 def my_dh_pub_key(self):
254 if self.is_initiator:
255 return self.i_dh_data
256 return self.r_dh_data
257
258 @property
259 def peer_dh_pub_key(self):
260 if self.is_initiator:
261 return self.r_dh_data
Filip Tehlar12b517b2020-04-26 18:05:05 +0000262 return self.i_dh_data
263
Filip Tehlar027d8132020-12-04 17:38:11 +0000264 @property
265 def natt(self):
266 return self.i_natt or self.r_natt
267
Filip Tehlar12b517b2020-04-26 18:05:05 +0000268 def compute_secret(self):
269 priv = self.dh_private_key
Filip Tehlare7c83962020-09-23 11:20:12 +0000270 peer = self.peer_dh_pub_key
Filip Tehlar12b517b2020-04-26 18:05:05 +0000271 p, g, l = self.ike_group
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200272 return pow(
273 int.from_bytes(peer, "big"), int.from_bytes(priv, "big"), p
274 ).to_bytes(l, "big")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000275
276 def generate_dh_data(self):
277 # generate DH keys
Filip Tehlare7c83962020-09-23 11:20:12 +0000278 if self.ike_dh not in DH:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200279 raise NotImplementedError("%s not in DH group" % self.ike_dh)
Filip Tehlare7c83962020-09-23 11:20:12 +0000280
281 if self.dh_params is None:
282 dhg = DH[self.ike_dh]
283 pn = dh.DHParameterNumbers(dhg[0], dhg[1])
284 self.dh_params = pn.parameters(default_backend())
285
286 priv = self.dh_params.generate_private_key()
287 pub = priv.public_key()
288 x = priv.private_numbers().x
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200289 self.dh_private_key = x.to_bytes(priv.key_size // 8, "big")
Filip Tehlare7c83962020-09-23 11:20:12 +0000290 y = pub.public_numbers().y
291
Filip Tehlar12b517b2020-04-26 18:05:05 +0000292 if self.is_initiator:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200293 self.i_dh_data = y.to_bytes(pub.key_size // 8, "big")
Filip Tehlare7c83962020-09-23 11:20:12 +0000294 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200295 self.r_dh_data = y.to_bytes(pub.key_size // 8, "big")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000296
297 def complete_dh_data(self):
298 self.dh_shared_secret = self.compute_secret()
299
Atzm Watanabec65921f2022-08-12 14:29:31 +0900300 def calc_child_keys(self, kex=False):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000301 prf = self.ike_prf_alg.mod()
302 s = self.i_nonce + self.r_nonce
Atzm Watanabec65921f2022-08-12 14:29:31 +0900303 if kex:
304 s = self.dh_shared_secret + s
Filip Tehlar12b517b2020-04-26 18:05:05 +0000305 c = self.child_sas[0]
306
307 encr_key_len = self.esp_crypto_key_len
Filip Tehlar4f42a712020-07-01 08:56:59 +0000308 integ_key_len = self.esp_integ_alg.key_len
309 salt_len = 0 if integ_key_len else 4
310
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200311 l = integ_key_len * 2 + encr_key_len * 2 + salt_len * 2
Filip Tehlar12b517b2020-04-26 18:05:05 +0000312 keymat = self.calc_prfplus(prf, self.sk_d, s, l)
313
314 pos = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200315 c.sk_ei = keymat[pos : pos + encr_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000316 pos += encr_key_len
317
Filip Tehlar4f42a712020-07-01 08:56:59 +0000318 if integ_key_len:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200319 c.sk_ai = keymat[pos : pos + integ_key_len]
Filip Tehlar4f42a712020-07-01 08:56:59 +0000320 pos += integ_key_len
321 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200322 c.salt_ei = keymat[pos : pos + salt_len]
Filip Tehlar4f42a712020-07-01 08:56:59 +0000323 pos += salt_len
Filip Tehlar12b517b2020-04-26 18:05:05 +0000324
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200325 c.sk_er = keymat[pos : pos + encr_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000326 pos += encr_key_len
327
Filip Tehlar4f42a712020-07-01 08:56:59 +0000328 if integ_key_len:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200329 c.sk_ar = keymat[pos : pos + integ_key_len]
Filip Tehlar4f42a712020-07-01 08:56:59 +0000330 pos += integ_key_len
331 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200332 c.salt_er = keymat[pos : pos + salt_len]
Filip Tehlar4f42a712020-07-01 08:56:59 +0000333 pos += salt_len
Filip Tehlar12b517b2020-04-26 18:05:05 +0000334
335 def calc_prfplus(self, prf, key, seed, length):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200336 r = b""
Filip Tehlar12b517b2020-04-26 18:05:05 +0000337 t = None
338 x = 1
339 while len(r) < length and x < 255:
340 if t is not None:
341 s = t
342 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200343 s = b""
Filip Tehlar12b517b2020-04-26 18:05:05 +0000344 s = s + seed + bytes([x])
345 t = self.calc_prf(prf, key, s)
346 r = r + t
347 x = x + 1
348
349 if x == 255:
350 return None
351 return r
352
353 def calc_prf(self, prf, key, data):
Filip Tehlara7b963d2020-07-08 13:25:34 +0000354 h = self.ike_prf_alg.mac(key, prf, backend=default_backend())
Filip Tehlar12b517b2020-04-26 18:05:05 +0000355 h.update(data)
356 return h.finalize()
357
358 def calc_keys(self):
359 prf = self.ike_prf_alg.mod()
360 # SKEYSEED = prf(Ni | Nr, g^ir)
361 s = self.i_nonce + self.r_nonce
362 self.skeyseed = self.calc_prf(prf, s, self.dh_shared_secret)
363
364 # calculate S = Ni | Nr | SPIi SPIr
365 s = s + self.ispi + self.rspi
366
367 prf_key_trunc = self.ike_prf_alg.trunc_len
368 encr_key_len = self.ike_crypto_key_len
369 tr_prf_key_len = self.ike_prf_alg.key_len
370 integ_key_len = self.ike_integ_alg.key_len
Filip Tehlara7b963d2020-07-08 13:25:34 +0000371 if integ_key_len == 0:
372 salt_size = 4
373 else:
374 salt_size = 0
375
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200376 l = (
377 prf_key_trunc
378 + integ_key_len * 2
379 + encr_key_len * 2
380 + tr_prf_key_len * 2
381 + salt_size * 2
382 )
Filip Tehlar12b517b2020-04-26 18:05:05 +0000383 keymat = self.calc_prfplus(prf, self.skeyseed, s, l)
384
385 pos = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200386 self.sk_d = keymat[: pos + prf_key_trunc]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000387 pos += prf_key_trunc
388
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200389 self.sk_ai = keymat[pos : pos + integ_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000390 pos += integ_key_len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200391 self.sk_ar = keymat[pos : pos + integ_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000392 pos += integ_key_len
393
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200394 self.sk_ei = keymat[pos : pos + encr_key_len + salt_size]
Filip Tehlara7b963d2020-07-08 13:25:34 +0000395 pos += encr_key_len + salt_size
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200396 self.sk_er = keymat[pos : pos + encr_key_len + salt_size]
Filip Tehlara7b963d2020-07-08 13:25:34 +0000397 pos += encr_key_len + salt_size
Filip Tehlar12b517b2020-04-26 18:05:05 +0000398
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200399 self.sk_pi = keymat[pos : pos + tr_prf_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000400 pos += tr_prf_key_len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200401 self.sk_pr = keymat[pos : pos + tr_prf_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000402
403 def generate_authmsg(self, prf, packet):
404 if self.is_initiator:
405 id = self.i_id
406 nonce = self.r_nonce
407 key = self.sk_pi
Filip Tehlare7c83962020-09-23 11:20:12 +0000408 else:
409 id = self.r_id
410 nonce = self.i_nonce
411 key = self.sk_pr
Filip Tehlar12b517b2020-04-26 18:05:05 +0000412 data = bytes([self.id_type, 0, 0, 0]) + id
413 id_hash = self.calc_prf(prf, key, data)
414 return packet + nonce + id_hash
415
416 def auth_init(self):
417 prf = self.ike_prf_alg.mod()
Filip Tehlare7c83962020-09-23 11:20:12 +0000418 if self.is_initiator:
419 packet = self.init_req_packet
420 else:
421 packet = self.init_resp_packet
422 authmsg = self.generate_authmsg(prf, raw(packet))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200423 if self.auth_method == "shared-key":
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000424 psk = self.calc_prf(prf, self.auth_data, KEY_PAD)
425 self.auth_data = self.calc_prf(prf, psk, authmsg)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200426 elif self.auth_method == "rsa-sig":
427 self.auth_data = self.priv_key.sign(
428 authmsg, padding.PKCS1v15(), hashes.SHA1()
429 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000430 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200431 raise TypeError("unknown auth method type!")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000432
Filip Tehlara7b963d2020-07-08 13:25:34 +0000433 def encrypt(self, data, aad=None):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000434 data = self.ike_crypto_alg.pad(data)
Filip Tehlara7b963d2020-07-08 13:25:34 +0000435 return self.ike_crypto_alg.encrypt(data, self.my_cryptokey, aad)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000436
437 @property
438 def peer_authkey(self):
439 if self.is_initiator:
440 return self.sk_ar
441 return self.sk_ai
442
443 @property
444 def my_authkey(self):
445 if self.is_initiator:
446 return self.sk_ai
447 return self.sk_ar
448
449 @property
450 def my_cryptokey(self):
451 if self.is_initiator:
452 return self.sk_ei
453 return self.sk_er
454
455 @property
456 def peer_cryptokey(self):
457 if self.is_initiator:
458 return self.sk_er
459 return self.sk_ei
460
Filip Tehlar4f42a712020-07-01 08:56:59 +0000461 def concat(self, alg, key_len):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200462 return alg + "-" + str(key_len * 8)
Filip Tehlar4f42a712020-07-01 08:56:59 +0000463
464 @property
465 def vpp_ike_cypto_alg(self):
466 return self.concat(self.ike_crypto, self.ike_crypto_key_len)
467
468 @property
469 def vpp_esp_cypto_alg(self):
470 return self.concat(self.esp_crypto, self.esp_crypto_key_len)
471
Filip Tehlar12b517b2020-04-26 18:05:05 +0000472 def verify_hmac(self, ikemsg):
473 integ_trunc = self.ike_integ_alg.trunc_len
474 exp_hmac = ikemsg[-integ_trunc:]
475 data = ikemsg[:-integ_trunc]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200476 computed_hmac = self.compute_hmac(
477 self.ike_integ_alg.mod(), self.peer_authkey, data
478 )
Filip Tehlar12b517b2020-04-26 18:05:05 +0000479 self.test.assertEqual(computed_hmac[:integ_trunc], exp_hmac)
480
481 def compute_hmac(self, integ, key, data):
482 h = self.ike_integ_alg.mac(key, integ, backend=default_backend())
483 h.update(data)
484 return h.finalize()
485
Filip Tehlara7b963d2020-07-08 13:25:34 +0000486 def decrypt(self, data, aad=None, icv=None):
487 return self.ike_crypto_alg.decrypt(data, self.peer_cryptokey, aad, icv)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000488
489 def hmac_and_decrypt(self, ike):
490 ep = ike[ikev2.IKEv2_payload_Encrypted]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200491 if self.ike_crypto == "AES-GCM-16ICV":
Filip Tehlara7b963d2020-07-08 13:25:34 +0000492 aad_len = len(ikev2.IKEv2_payload_Encrypted()) + len(ikev2.IKEv2())
493 ct = ep.load[:-GCM_ICV_SIZE]
494 tag = ep.load[-GCM_ICV_SIZE:]
Filip Tehlaredf29002020-10-10 04:39:11 +0000495 plain = self.decrypt(ct, raw(ike)[:aad_len], tag)
Filip Tehlara7b963d2020-07-08 13:25:34 +0000496 else:
497 self.verify_hmac(raw(ike))
498 integ_trunc = self.ike_integ_alg.trunc_len
Filip Tehlar12b517b2020-04-26 18:05:05 +0000499
Filip Tehlara7b963d2020-07-08 13:25:34 +0000500 # remove ICV and decrypt payload
501 ct = ep.load[:-integ_trunc]
Filip Tehlaredf29002020-10-10 04:39:11 +0000502 plain = self.decrypt(ct)
503 # remove padding
504 pad_len = plain[-1]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200505 return plain[: -pad_len - 1]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000506
Filip Tehlar84962d12020-09-08 06:08:05 +0000507 def build_ts_addr(self, ts, version):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200508 return {
509 "starting_address_v" + version: ts["start_addr"],
510 "ending_address_v" + version: ts["end_addr"],
511 }
Filip Tehlar84962d12020-09-08 06:08:05 +0000512
513 def generate_ts(self, is_ip4):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000514 c = self.child_sas[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200515 ts_data = {"IP_protocol_ID": 0, "start_port": 0, "end_port": 0xFFFF}
Filip Tehlar84962d12020-09-08 06:08:05 +0000516 if is_ip4:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200517 ts_data.update(self.build_ts_addr(c.local_ts, "4"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000518 ts1 = ikev2.IPv4TrafficSelector(**ts_data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200519 ts_data.update(self.build_ts_addr(c.remote_ts, "4"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000520 ts2 = ikev2.IPv4TrafficSelector(**ts_data)
521 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 ts_data.update(self.build_ts_addr(c.local_ts, "6"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000523 ts1 = ikev2.IPv6TrafficSelector(**ts_data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200524 ts_data.update(self.build_ts_addr(c.remote_ts, "6"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000525 ts2 = ikev2.IPv6TrafficSelector(**ts_data)
Filip Tehlare7c83962020-09-23 11:20:12 +0000526
527 if self.is_initiator:
528 return ([ts1], [ts2])
529 return ([ts2], [ts1])
Filip Tehlar12b517b2020-04-26 18:05:05 +0000530
531 def set_ike_props(self, crypto, crypto_key_len, integ, prf, dh):
532 if crypto not in CRYPTO_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200533 raise TypeError("unsupported encryption algo %r" % crypto)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000534 self.ike_crypto = crypto
535 self.ike_crypto_alg = CRYPTO_ALGOS[crypto]
536 self.ike_crypto_key_len = crypto_key_len
537
538 if integ not in AUTH_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200539 raise TypeError("unsupported auth algo %r" % integ)
540 self.ike_integ = None if integ == "NULL" else integ
Filip Tehlar12b517b2020-04-26 18:05:05 +0000541 self.ike_integ_alg = AUTH_ALGOS[integ]
542
543 if prf not in PRF_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200544 raise TypeError("unsupported prf algo %r" % prf)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000545 self.ike_prf = prf
546 self.ike_prf_alg = PRF_ALGOS[prf]
547 self.ike_dh = dh
548 self.ike_group = DH[self.ike_dh]
549
550 def set_esp_props(self, crypto, crypto_key_len, integ):
551 self.esp_crypto_key_len = crypto_key_len
552 if crypto not in CRYPTO_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200553 raise TypeError("unsupported encryption algo %r" % crypto)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000554 self.esp_crypto = crypto
555 self.esp_crypto_alg = CRYPTO_ALGOS[crypto]
556
557 if integ not in AUTH_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200558 raise TypeError("unsupported auth algo %r" % integ)
559 self.esp_integ = None if integ == "NULL" else integ
Filip Tehlar12b517b2020-04-26 18:05:05 +0000560 self.esp_integ_alg = AUTH_ALGOS[integ]
561
562 def crypto_attr(self, key_len):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200563 if self.ike_crypto in ["AES-CBC", "AES-GCM-16ICV"]:
564 return (0x800E << 16 | key_len << 3, 12)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000565 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200566 raise Exception("unsupported attribute type")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000567
568 def ike_crypto_attr(self):
569 return self.crypto_attr(self.ike_crypto_key_len)
570
571 def esp_crypto_attr(self):
572 return self.crypto_attr(self.esp_crypto_key_len)
573
Filip Tehlarec112e52020-10-07 23:52:37 +0000574 def compute_nat_sha1(self, ip, port, rspi=None):
575 if rspi is None:
576 rspi = self.rspi
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200577 data = self.ispi + rspi + ip + (port).to_bytes(2, "big")
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000578 digest = hashes.Hash(hashes.SHA1(), backend=default_backend())
579 digest.update(data)
580 return digest.finalize()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000581
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000582
Andrew Yourtchenkobc378782023-09-26 16:01:21 +0200583@unittest.skipIf("ikev2" in config.excluded_plugins, "Exclude IKEv2 plugin tests")
Filip Tehlare7c83962020-09-23 11:20:12 +0000584class IkePeer(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200585 """common class for initiator and responder"""
Filip Tehlar12b517b2020-04-26 18:05:05 +0000586
587 @classmethod
588 def setUpClass(cls):
589 import scapy.contrib.ikev2 as _ikev2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200590
591 globals()["ikev2"] = _ikev2
Filip Tehlare7c83962020-09-23 11:20:12 +0000592 super(IkePeer, cls).setUpClass()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000593 cls.create_pg_interfaces(range(2))
594 for i in cls.pg_interfaces:
595 i.admin_up()
596 i.config_ip4()
597 i.resolve_arp()
Filip Tehlar84962d12020-09-08 06:08:05 +0000598 i.config_ip6()
599 i.resolve_ndp()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000600
601 @classmethod
602 def tearDownClass(cls):
Filip Tehlare7c83962020-09-23 11:20:12 +0000603 super(IkePeer, cls).tearDownClass()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000604
Filip Tehlaredf29002020-10-10 04:39:11 +0000605 def tearDown(self):
606 super(IkePeer, self).tearDown()
607 if self.del_sa_from_responder:
608 self.initiate_del_sa_from_responder()
609 else:
610 self.initiate_del_sa_from_initiator()
611 r = self.vapi.ikev2_sa_dump()
612 self.assertEqual(len(r), 0)
613 sas = self.vapi.ipsec_sa_dump()
614 self.assertEqual(len(sas), 0)
615 self.p.remove_vpp_config()
616 self.assertIsNone(self.p.query_vpp_config())
617
Filip Tehlar12b517b2020-04-26 18:05:05 +0000618 def setUp(self):
Filip Tehlare7c83962020-09-23 11:20:12 +0000619 super(IkePeer, self).setUp()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000620 self.config_tc()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000621 self.p.add_vpp_config()
Filip Tehlar459d17b2020-07-06 15:40:08 +0000622 self.assertIsNotNone(self.p.query_vpp_config())
Filip Tehlar68ad6252020-10-30 05:28:11 +0000623 if self.sa.is_initiator:
624 self.sa.generate_dh_data()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200625 self.vapi.cli("ikev2 set logging level 4")
626 self.vapi.cli("event-lo clear")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000627
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200628 def assert_counter(self, count, name, version="ip4"):
629 node_name = "/err/ikev2-%s/" % version + name
Filip Tehlarfab5e7f2021-01-14 13:32:01 +0000630 self.assertEqual(count, self.statistics.get_err_counter(node_name))
631
Atzm Watanabec65921f2022-08-12 14:29:31 +0900632 def create_rekey_request(self, kex=False):
633 sa, first_payload = self.generate_auth_payload(is_rekey=True, kex=kex)
Filip Tehlar38340fa2020-11-19 21:34:48 +0000634 header = ikev2.IKEv2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200635 init_SPI=self.sa.ispi,
636 resp_SPI=self.sa.rspi,
637 id=self.sa.new_msg_id(),
638 flags="Initiator",
639 exch_type="CREATE_CHILD_SA",
640 )
Filip Tehlar38340fa2020-11-19 21:34:48 +0000641
642 ike_msg = self.encrypt_ike_msg(header, sa, first_payload)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200643 return self.create_packet(
644 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
645 )
Filip Tehlar38340fa2020-11-19 21:34:48 +0000646
647 def create_empty_request(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200648 header = ikev2.IKEv2(
649 init_SPI=self.sa.ispi,
650 resp_SPI=self.sa.rspi,
651 id=self.sa.new_msg_id(),
652 flags="Initiator",
653 exch_type="INFORMATIONAL",
654 next_payload="Encrypted",
655 )
Filip Tehlar38340fa2020-11-19 21:34:48 +0000656
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200657 msg = self.encrypt_ike_msg(header, b"", None)
658 return self.create_packet(
659 self.pg0, msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
660 )
Filip Tehlar38340fa2020-11-19 21:34:48 +0000661
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200662 def create_packet(
663 self, src_if, msg, sport=500, dport=500, natt=False, use_ip6=False
664 ):
Filip Tehlar84962d12020-09-08 06:08:05 +0000665 if use_ip6:
666 src_ip = src_if.remote_ip6
667 dst_ip = src_if.local_ip6
668 ip_layer = IPv6
669 else:
670 src_ip = src_if.remote_ip4
671 dst_ip = src_if.local_ip4
672 ip_layer = IP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200673 res = (
674 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
675 / ip_layer(src=src_ip, dst=dst_ip)
676 / UDP(sport=sport, dport=dport)
677 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000678 if natt:
679 # insert non ESP marker
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200680 res = res / Raw(b"\x00" * 4)
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000681 return res / msg
Filip Tehlar12b517b2020-04-26 18:05:05 +0000682
Filip Tehlare7c83962020-09-23 11:20:12 +0000683 def verify_udp(self, udp):
684 self.assertEqual(udp.sport, self.sa.sport)
685 self.assertEqual(udp.dport, self.sa.dport)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000686
Filip Tehlare7c83962020-09-23 11:20:12 +0000687 def get_ike_header(self, packet):
688 try:
689 ih = packet[ikev2.IKEv2]
Filip Tehlar18107c92020-12-01 14:51:09 +0000690 ih = self.verify_and_remove_non_esp_marker(ih)
Filip Tehlare7c83962020-09-23 11:20:12 +0000691 except IndexError as e:
692 # this is a workaround for getting IKEv2 layer as both ikev2 and
693 # ipsec register for port 4500
694 esp = packet[ESP]
695 ih = self.verify_and_remove_non_esp_marker(esp)
696 self.assertEqual(ih.version, 0x20)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200697 self.assertNotIn("Version", ih.flags)
Filip Tehlare7c83962020-09-23 11:20:12 +0000698 return ih
Filip Tehlar12b517b2020-04-26 18:05:05 +0000699
Filip Tehlare7c83962020-09-23 11:20:12 +0000700 def verify_and_remove_non_esp_marker(self, packet):
701 if self.sa.natt:
702 # if we are in nat traversal mode check for non esp marker
703 # and remove it
704 data = raw(packet)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200705 self.assertEqual(data[:4], b"\x00" * 4)
Filip Tehlare7c83962020-09-23 11:20:12 +0000706 return ikev2.IKEv2(data[4:])
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000707 else:
Filip Tehlare7c83962020-09-23 11:20:12 +0000708 return packet
Filip Tehlar12b517b2020-04-26 18:05:05 +0000709
Filip Tehlar558607d2020-07-16 07:25:56 +0000710 def encrypt_ike_msg(self, header, plain, first_payload):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200711 if self.sa.ike_crypto == "AES-GCM-16ICV":
Filip Tehlar558607d2020-07-16 07:25:56 +0000712 data = self.sa.ike_crypto_alg.pad(raw(plain))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200713 plen = (
714 len(data)
715 + GCM_IV_SIZE
716 + GCM_ICV_SIZE
717 + len(ikev2.IKEv2_payload_Encrypted())
718 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000719 tlen = plen + len(ikev2.IKEv2())
720
721 # prepare aad data
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200722 sk_p = ikev2.IKEv2_payload_Encrypted(
723 next_payload=first_payload, length=plen
724 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000725 header.length = tlen
726 res = header / sk_p
727 encr = self.sa.encrypt(raw(plain), raw(res))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200728 sk_p = ikev2.IKEv2_payload_Encrypted(
729 next_payload=first_payload, length=plen, load=encr
730 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000731 res = header / sk_p
732 else:
733 encr = self.sa.encrypt(raw(plain))
734 trunc_len = self.sa.ike_integ_alg.trunc_len
735 plen = len(encr) + len(ikev2.IKEv2_payload_Encrypted()) + trunc_len
736 tlen = plen + len(ikev2.IKEv2())
737
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200738 sk_p = ikev2.IKEv2_payload_Encrypted(
739 next_payload=first_payload, length=plen, load=encr
740 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000741 header.length = tlen
742 res = header / sk_p
743
744 integ_data = raw(res)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200745 hmac_data = self.sa.compute_hmac(
746 self.sa.ike_integ_alg.mod(), self.sa.my_authkey, integ_data
747 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000748 res = res / Raw(hmac_data[:trunc_len])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200749 assert len(res) == tlen
Filip Tehlar558607d2020-07-16 07:25:56 +0000750 return res
751
Filip Tehlar67b8a7f2020-11-06 11:00:42 +0000752 def verify_udp_encap(self, ipsec_sa):
753 e = VppEnum.vl_api_ipsec_sad_flags_t
754 if self.sa.udp_encap or self.sa.natt:
755 self.assertIn(e.IPSEC_API_SAD_FLAG_UDP_ENCAP, ipsec_sa.flags)
756 else:
757 self.assertNotIn(e.IPSEC_API_SAD_FLAG_UDP_ENCAP, ipsec_sa.flags)
758
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +0900759 def verify_ipsec_sas(self, is_rekey=False, sa_count=None):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000760 sas = self.vapi.ipsec_sa_dump()
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +0900761 if sa_count is None:
762 if is_rekey:
763 # after rekey there is a short period of time in which old
764 # inbound SA is still present
765 sa_count = 3
766 else:
767 sa_count = 2
Filip Tehlar68ad6252020-10-30 05:28:11 +0000768 self.assertEqual(len(sas), sa_count)
Filip Tehlare7c83962020-09-23 11:20:12 +0000769 if self.sa.is_initiator:
Filip Tehlar68ad6252020-10-30 05:28:11 +0000770 if is_rekey:
771 sa0 = sas[0].entry
772 sa1 = sas[2].entry
773 else:
774 sa0 = sas[0].entry
775 sa1 = sas[1].entry
Filip Tehlare7c83962020-09-23 11:20:12 +0000776 else:
Filip Tehlar68ad6252020-10-30 05:28:11 +0000777 if is_rekey:
778 sa0 = sas[2].entry
779 sa1 = sas[0].entry
780 else:
781 sa1 = sas[0].entry
782 sa0 = sas[1].entry
Filip Tehlare7c83962020-09-23 11:20:12 +0000783
Filip Tehlar12b517b2020-04-26 18:05:05 +0000784 c = self.sa.child_sas[0]
785
Filip Tehlar67b8a7f2020-11-06 11:00:42 +0000786 self.verify_udp_encap(sa0)
787 self.verify_udp_encap(sa1)
Filip Tehlar4f42a712020-07-01 08:56:59 +0000788 vpp_crypto_alg = self.vpp_enums[self.sa.vpp_esp_cypto_alg]
789 self.assertEqual(sa0.crypto_algorithm, vpp_crypto_alg)
790 self.assertEqual(sa1.crypto_algorithm, vpp_crypto_alg)
791
792 if self.sa.esp_integ is None:
793 vpp_integ_alg = 0
794 else:
795 vpp_integ_alg = self.vpp_enums[self.sa.esp_integ]
796 self.assertEqual(sa0.integrity_algorithm, vpp_integ_alg)
797 self.assertEqual(sa1.integrity_algorithm, vpp_integ_alg)
798
Filip Tehlar12b517b2020-04-26 18:05:05 +0000799 # verify crypto keys
800 self.assertEqual(sa0.crypto_key.length, len(c.sk_er))
801 self.assertEqual(sa1.crypto_key.length, len(c.sk_ei))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200802 self.assertEqual(sa0.crypto_key.data[: len(c.sk_er)], c.sk_er)
803 self.assertEqual(sa1.crypto_key.data[: len(c.sk_ei)], c.sk_ei)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000804
805 # verify integ keys
Filip Tehlar4f42a712020-07-01 08:56:59 +0000806 if vpp_integ_alg:
807 self.assertEqual(sa0.integrity_key.length, len(c.sk_ar))
808 self.assertEqual(sa1.integrity_key.length, len(c.sk_ai))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200809 self.assertEqual(sa0.integrity_key.data[: len(c.sk_ar)], c.sk_ar)
810 self.assertEqual(sa1.integrity_key.data[: len(c.sk_ai)], c.sk_ai)
Filip Tehlar4f42a712020-07-01 08:56:59 +0000811 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200812 self.assertEqual(sa0.salt.to_bytes(4, "little"), c.salt_er)
813 self.assertEqual(sa1.salt.to_bytes(4, "little"), c.salt_ei)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000814
jan_cavojskya340fe12020-07-08 09:24:12 +0200815 def verify_keymat(self, api_keys, keys, name):
816 km = getattr(keys, name)
817 api_km = getattr(api_keys, name)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200818 api_km_len = getattr(api_keys, name + "_len")
jan_cavojskya340fe12020-07-08 09:24:12 +0200819 self.assertEqual(len(km), api_km_len)
820 self.assertEqual(km, api_km[:api_km_len])
821
822 def verify_id(self, api_id, exp_id):
823 self.assertEqual(api_id.type, IDType.value(exp_id.type))
824 self.assertEqual(api_id.data_len, exp_id.data_len)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200825 self.assertEqual(bytes(api_id.data, "ascii"), exp_id.type)
jan_cavojskya340fe12020-07-08 09:24:12 +0200826
827 def verify_ike_sas(self):
828 r = self.vapi.ikev2_sa_dump()
829 self.assertEqual(len(r), 1)
830 sa = r[0].sa
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200831 self.assertEqual(self.sa.ispi, (sa.ispi).to_bytes(8, "big"))
832 self.assertEqual(self.sa.rspi, (sa.rspi).to_bytes(8, "big"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000833 if self.ip6:
Filip Tehlare7c83962020-09-23 11:20:12 +0000834 if self.sa.is_initiator:
835 self.assertEqual(sa.iaddr, IPv6Address(self.pg0.remote_ip6))
836 self.assertEqual(sa.raddr, IPv6Address(self.pg0.local_ip6))
837 else:
838 self.assertEqual(sa.iaddr, IPv6Address(self.pg0.local_ip6))
839 self.assertEqual(sa.raddr, IPv6Address(self.pg0.remote_ip6))
Filip Tehlar84962d12020-09-08 06:08:05 +0000840 else:
Filip Tehlare7c83962020-09-23 11:20:12 +0000841 if self.sa.is_initiator:
842 self.assertEqual(sa.iaddr, IPv4Address(self.pg0.remote_ip4))
843 self.assertEqual(sa.raddr, IPv4Address(self.pg0.local_ip4))
844 else:
845 self.assertEqual(sa.iaddr, IPv4Address(self.pg0.local_ip4))
846 self.assertEqual(sa.raddr, IPv4Address(self.pg0.remote_ip4))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200847 self.verify_keymat(sa.keys, self.sa, "sk_d")
848 self.verify_keymat(sa.keys, self.sa, "sk_ai")
849 self.verify_keymat(sa.keys, self.sa, "sk_ar")
850 self.verify_keymat(sa.keys, self.sa, "sk_ei")
851 self.verify_keymat(sa.keys, self.sa, "sk_er")
852 self.verify_keymat(sa.keys, self.sa, "sk_pi")
853 self.verify_keymat(sa.keys, self.sa, "sk_pr")
jan_cavojskya340fe12020-07-08 09:24:12 +0200854
855 self.assertEqual(sa.i_id.type, self.sa.id_type)
856 self.assertEqual(sa.r_id.type, self.sa.id_type)
857 self.assertEqual(sa.i_id.data_len, len(self.sa.i_id))
Benoît Gannec7cceee2021-09-28 11:19:37 +0200858 self.assertEqual(sa.r_id.data_len, len(self.idr))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200859 self.assertEqual(bytes(sa.i_id.data, "ascii"), self.sa.i_id)
860 self.assertEqual(bytes(sa.r_id.data, "ascii"), self.idr)
jan_cavojskya340fe12020-07-08 09:24:12 +0200861
862 r = self.vapi.ikev2_child_sa_dump(sa_index=sa.sa_index)
863 self.assertEqual(len(r), 1)
864 csa = r[0].child_sa
865 self.assertEqual(csa.sa_index, sa.sa_index)
866 c = self.sa.child_sas[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200867 if hasattr(c, "sk_ai"):
868 self.verify_keymat(csa.keys, c, "sk_ai")
869 self.verify_keymat(csa.keys, c, "sk_ar")
870 self.verify_keymat(csa.keys, c, "sk_ei")
871 self.verify_keymat(csa.keys, c, "sk_er")
872 self.assertEqual(csa.i_spi.to_bytes(4, "big"), c.ispi)
873 self.assertEqual(csa.r_spi.to_bytes(4, "big"), c.rspi)
jan_cavojskya340fe12020-07-08 09:24:12 +0200874
Filip Tehlar84962d12020-09-08 06:08:05 +0000875 tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4)
jan_cavojskya340fe12020-07-08 09:24:12 +0200876 tsi = tsi[0]
877 tsr = tsr[0]
878 r = self.vapi.ikev2_traffic_selector_dump(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200879 is_initiator=True, sa_index=sa.sa_index, child_sa_index=csa.child_sa_index
880 )
jan_cavojskya340fe12020-07-08 09:24:12 +0200881 self.assertEqual(len(r), 1)
882 ts = r[0].ts
883 self.verify_ts(r[0].ts, tsi[0], True)
884
885 r = self.vapi.ikev2_traffic_selector_dump(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200886 is_initiator=False, sa_index=sa.sa_index, child_sa_index=csa.child_sa_index
887 )
jan_cavojskya340fe12020-07-08 09:24:12 +0200888 self.assertEqual(len(r), 1)
889 self.verify_ts(r[0].ts, tsr[0], False)
890
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200891 n = self.vapi.ikev2_nonce_get(is_initiator=True, sa_index=sa.sa_index)
jan_cavojskya340fe12020-07-08 09:24:12 +0200892 self.verify_nonce(n, self.sa.i_nonce)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200893 n = self.vapi.ikev2_nonce_get(is_initiator=False, sa_index=sa.sa_index)
jan_cavojskya340fe12020-07-08 09:24:12 +0200894 self.verify_nonce(n, self.sa.r_nonce)
895
896 def verify_nonce(self, api_nonce, nonce):
897 self.assertEqual(api_nonce.data_len, len(nonce))
898 self.assertEqual(api_nonce.nonce, nonce)
899
900 def verify_ts(self, api_ts, ts, is_initiator):
901 if is_initiator:
902 self.assertTrue(api_ts.is_local)
903 else:
904 self.assertFalse(api_ts.is_local)
Filip Tehlar84962d12020-09-08 06:08:05 +0000905
906 if self.p.ts_is_ip4:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200907 self.assertEqual(api_ts.start_addr, IPv4Address(ts.starting_address_v4))
908 self.assertEqual(api_ts.end_addr, IPv4Address(ts.ending_address_v4))
Filip Tehlar84962d12020-09-08 06:08:05 +0000909 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200910 self.assertEqual(api_ts.start_addr, IPv6Address(ts.starting_address_v6))
911 self.assertEqual(api_ts.end_addr, IPv6Address(ts.ending_address_v6))
jan_cavojskya340fe12020-07-08 09:24:12 +0200912 self.assertEqual(api_ts.start_port, ts.start_port)
913 self.assertEqual(api_ts.end_port, ts.end_port)
914 self.assertEqual(api_ts.protocol_id, ts.IP_protocol_ID)
915
Filip Tehlare7c83962020-09-23 11:20:12 +0000916
917class TemplateInitiator(IkePeer):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200918 """initiator test template"""
Filip Tehlare7c83962020-09-23 11:20:12 +0000919
Filip Tehlaredf29002020-10-10 04:39:11 +0000920 def initiate_del_sa_from_initiator(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200921 ispi = int.from_bytes(self.sa.ispi, "little")
Filip Tehlaredf29002020-10-10 04:39:11 +0000922 self.pg0.enable_capture()
923 self.pg_start()
924 self.vapi.ikev2_initiate_del_ike_sa(ispi=ispi)
925 capture = self.pg0.get_capture(1)
926 ih = self.get_ike_header(capture[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200927 self.assertNotIn("Response", ih.flags)
928 self.assertIn("Initiator", ih.flags)
Filip Tehlaredf29002020-10-10 04:39:11 +0000929 self.assertEqual(ih.init_SPI, self.sa.ispi)
930 self.assertEqual(ih.resp_SPI, self.sa.rspi)
931 plain = self.sa.hmac_and_decrypt(ih)
932 d = ikev2.IKEv2_payload_Delete(plain)
933 self.assertEqual(d.proto, 1) # proto=IKEv2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200934 header = ikev2.IKEv2(
935 init_SPI=self.sa.ispi,
936 resp_SPI=self.sa.rspi,
937 flags="Response",
938 exch_type="INFORMATIONAL",
939 id=ih.id,
940 next_payload="Encrypted",
941 )
942 resp = self.encrypt_ike_msg(header, b"", None)
Filip Tehlaredf29002020-10-10 04:39:11 +0000943 self.send_and_assert_no_replies(self.pg0, resp)
944
945 def verify_del_sa(self, packet):
946 ih = self.get_ike_header(packet)
947 self.assertEqual(ih.id, self.sa.msg_id)
948 self.assertEqual(ih.exch_type, 37) # exchange informational
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200949 self.assertIn("Response", ih.flags)
950 self.assertIn("Initiator", ih.flags)
Filip Tehlaredf29002020-10-10 04:39:11 +0000951 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200952 self.assertEqual(plain, b"")
Filip Tehlaredf29002020-10-10 04:39:11 +0000953
954 def initiate_del_sa_from_responder(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200955 header = ikev2.IKEv2(
956 init_SPI=self.sa.ispi,
957 resp_SPI=self.sa.rspi,
958 exch_type="INFORMATIONAL",
959 id=self.sa.new_msg_id(),
960 )
961 del_sa = ikev2.IKEv2_payload_Delete(proto="IKEv2")
962 ike_msg = self.encrypt_ike_msg(header, del_sa, "Delete")
963 packet = self.create_packet(
964 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
965 )
Filip Tehlaredf29002020-10-10 04:39:11 +0000966 self.pg0.add_stream(packet)
967 self.pg0.enable_capture()
968 self.pg_start()
969 capture = self.pg0.get_capture(1)
970 self.verify_del_sa(capture[0])
Filip Tehlare7c83962020-09-23 11:20:12 +0000971
Filip Tehlarec112e52020-10-07 23:52:37 +0000972 @staticmethod
973 def find_notify_payload(packet, notify_type):
974 n = packet[ikev2.IKEv2_payload_Notify]
975 while n is not None:
976 if n.type == notify_type:
977 return n
978 n = n.payload
979 return None
980
981 def verify_nat_detection(self, packet):
982 if self.ip6:
983 iph = packet[IPv6]
984 else:
985 iph = packet[IP]
986 udp = packet[UDP]
987
988 # NAT_DETECTION_SOURCE_IP
989 s = self.find_notify_payload(packet, 16388)
990 self.assertIsNotNone(s)
991 src_sha = self.sa.compute_nat_sha1(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200992 inet_pton(socket.AF_INET, iph.src), udp.sport, b"\x00" * 8
993 )
Filip Tehlarec112e52020-10-07 23:52:37 +0000994 self.assertEqual(s.load, src_sha)
995
996 # NAT_DETECTION_DESTINATION_IP
997 s = self.find_notify_payload(packet, 16389)
998 self.assertIsNotNone(s)
999 dst_sha = self.sa.compute_nat_sha1(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001000 inet_pton(socket.AF_INET, iph.dst), udp.dport, b"\x00" * 8
1001 )
Filip Tehlarec112e52020-10-07 23:52:37 +00001002 self.assertEqual(s.load, dst_sha)
1003
Filip Tehlare7c83962020-09-23 11:20:12 +00001004 def verify_sa_init_request(self, packet):
Filip Tehlar18107c92020-12-01 14:51:09 +00001005 udp = packet[UDP]
1006 self.sa.dport = udp.sport
Filip Tehlare7c83962020-09-23 11:20:12 +00001007 ih = packet[ikev2.IKEv2]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001008 self.assertNotEqual(ih.init_SPI, 8 * b"\x00")
Filip Tehlare7c83962020-09-23 11:20:12 +00001009 self.assertEqual(ih.exch_type, 34) # SA_INIT
1010 self.sa.ispi = ih.init_SPI
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001011 self.assertEqual(ih.resp_SPI, 8 * b"\x00")
1012 self.assertIn("Initiator", ih.flags)
1013 self.assertNotIn("Response", ih.flags)
Filip Tehlare7c83962020-09-23 11:20:12 +00001014 self.sa.i_nonce = ih[ikev2.IKEv2_payload_Nonce].load
1015 self.sa.i_dh_data = ih[ikev2.IKEv2_payload_KE].load
1016
1017 prop = packet[ikev2.IKEv2_payload_Proposal]
1018 self.assertEqual(prop.proto, 1) # proto = ikev2
1019 self.assertEqual(prop.proposal, 1)
1020 self.assertEqual(prop.trans[0].transform_type, 1) # encryption
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001021 self.assertEqual(
1022 prop.trans[0].transform_id, self.p.ike_transforms["crypto_alg"]
1023 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001024 self.assertEqual(prop.trans[1].transform_type, 2) # prf
1025 self.assertEqual(prop.trans[1].transform_id, 5) # "hmac-sha2-256"
1026 self.assertEqual(prop.trans[2].transform_type, 4) # dh
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001027 self.assertEqual(prop.trans[2].transform_id, self.p.ike_transforms["dh_group"])
Filip Tehlare7c83962020-09-23 11:20:12 +00001028
Filip Tehlarec112e52020-10-07 23:52:37 +00001029 self.verify_nat_detection(packet)
Filip Tehlar68ad6252020-10-30 05:28:11 +00001030 self.sa.set_ike_props(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001031 crypto="AES-GCM-16ICV",
1032 crypto_key_len=32,
1033 integ="NULL",
1034 prf="PRF_HMAC_SHA2_256",
1035 dh="3072MODPgr",
1036 )
1037 self.sa.set_esp_props(crypto="AES-CBC", crypto_key_len=32, integ="SHA2-256-128")
Filip Tehlar68ad6252020-10-30 05:28:11 +00001038 self.sa.generate_dh_data()
Filip Tehlare7c83962020-09-23 11:20:12 +00001039 self.sa.complete_dh_data()
1040 self.sa.calc_keys()
1041
Filip Tehlar68ad6252020-10-30 05:28:11 +00001042 def update_esp_transforms(self, trans, sa):
1043 while trans:
1044 if trans.transform_type == 1: # ecryption
1045 sa.esp_crypto = CRYPTO_IDS[trans.transform_id]
1046 elif trans.transform_type == 3: # integrity
1047 sa.esp_integ = INTEG_IDS[trans.transform_id]
1048 trans = trans.payload
1049
Filip Tehlare7c83962020-09-23 11:20:12 +00001050 def verify_sa_auth_req(self, packet):
Filip Tehlar18107c92020-12-01 14:51:09 +00001051 udp = packet[UDP]
1052 self.sa.dport = udp.sport
Filip Tehlare7c83962020-09-23 11:20:12 +00001053 ih = self.get_ike_header(packet)
1054 self.assertEqual(ih.resp_SPI, self.sa.rspi)
1055 self.assertEqual(ih.init_SPI, self.sa.ispi)
1056 self.assertEqual(ih.exch_type, 35) # IKE_AUTH
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001057 self.assertIn("Initiator", ih.flags)
1058 self.assertNotIn("Response", ih.flags)
Filip Tehlare7c83962020-09-23 11:20:12 +00001059
1060 udp = packet[UDP]
1061 self.verify_udp(udp)
1062 self.assertEqual(ih.id, self.sa.msg_id + 1)
1063 self.sa.msg_id += 1
1064 plain = self.sa.hmac_and_decrypt(ih)
1065 idi = ikev2.IKEv2_payload_IDi(plain)
Filip Tehlare7c83962020-09-23 11:20:12 +00001066 self.assertEqual(idi.load, self.sa.i_id)
Benoît Gannec7cceee2021-09-28 11:19:37 +02001067 if self.no_idr_auth:
1068 self.assertEqual(idi.next_payload, 39) # AUTH
1069 else:
1070 idr = ikev2.IKEv2_payload_IDr(idi.payload)
1071 self.assertEqual(idr.load, self.sa.r_id)
Filip Tehlar68ad6252020-10-30 05:28:11 +00001072 prop = idi[ikev2.IKEv2_payload_Proposal]
1073 c = self.sa.child_sas[0]
1074 c.ispi = prop.SPI
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001075 self.update_esp_transforms(prop[ikev2.IKEv2_payload_Transform], self.sa)
Filip Tehlare7c83962020-09-23 11:20:12 +00001076
1077 def send_init_response(self):
1078 tr_attr = self.sa.ike_crypto_attr()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001079 trans = (
1080 ikev2.IKEv2_payload_Transform(
1081 transform_type="Encryption",
1082 transform_id=self.sa.ike_crypto,
1083 length=tr_attr[1],
1084 key_length=tr_attr[0],
1085 )
1086 / ikev2.IKEv2_payload_Transform(
1087 transform_type="Integrity", transform_id=self.sa.ike_integ
1088 )
1089 / ikev2.IKEv2_payload_Transform(
1090 transform_type="PRF", transform_id=self.sa.ike_prf_alg.name
1091 )
1092 / ikev2.IKEv2_payload_Transform(
1093 transform_type="GroupDesc", transform_id=self.sa.ike_dh
1094 )
1095 )
1096 props = ikev2.IKEv2_payload_Proposal(
1097 proposal=1, proto="IKEv2", trans_nb=4, trans=trans
1098 )
Filip Tehlar18107c92020-12-01 14:51:09 +00001099
1100 src_address = inet_pton(socket.AF_INET, self.pg0.remote_ip4)
1101 if self.sa.natt:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001102 dst_address = b"\x0a\x0a\x0a\x0a"
Filip Tehlar18107c92020-12-01 14:51:09 +00001103 else:
1104 dst_address = inet_pton(socket.AF_INET, self.pg0.local_ip4)
1105 src_nat = self.sa.compute_nat_sha1(src_address, self.sa.sport)
1106 dst_nat = self.sa.compute_nat_sha1(dst_address, self.sa.dport)
1107
Filip Tehlare7c83962020-09-23 11:20:12 +00001108 self.sa.init_resp_packet = (
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001109 ikev2.IKEv2(
1110 init_SPI=self.sa.ispi,
1111 resp_SPI=self.sa.rspi,
1112 exch_type="IKE_SA_INIT",
1113 flags="Response",
1114 )
1115 / ikev2.IKEv2_payload_SA(next_payload="KE", prop=props)
1116 / ikev2.IKEv2_payload_KE(
1117 next_payload="Nonce", group=self.sa.ike_dh, load=self.sa.my_dh_pub_key
1118 )
1119 / ikev2.IKEv2_payload_Nonce(load=self.sa.r_nonce, next_payload="Notify")
1120 / ikev2.IKEv2_payload_Notify(
1121 type="NAT_DETECTION_SOURCE_IP", load=src_nat, next_payload="Notify"
1122 )
1123 / ikev2.IKEv2_payload_Notify(
1124 type="NAT_DETECTION_DESTINATION_IP", load=dst_nat
1125 )
1126 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001127
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001128 ike_msg = self.create_packet(
1129 self.pg0,
1130 self.sa.init_resp_packet,
1131 self.sa.sport,
1132 self.sa.dport,
1133 False,
1134 self.ip6,
1135 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001136 self.pg_send(self.pg0, ike_msg)
1137 capture = self.pg0.get_capture(1)
1138 self.verify_sa_auth_req(capture[0])
1139
1140 def initiate_sa_init(self):
1141 self.pg0.enable_capture()
1142 self.pg_start()
1143 self.vapi.ikev2_initiate_sa_init(name=self.p.profile_name)
1144
1145 capture = self.pg0.get_capture(1)
1146 self.verify_sa_init_request(capture[0])
1147 self.send_init_response()
1148
1149 def send_auth_response(self):
1150 tr_attr = self.sa.esp_crypto_attr()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001151 trans = (
1152 ikev2.IKEv2_payload_Transform(
1153 transform_type="Encryption",
1154 transform_id=self.sa.esp_crypto,
1155 length=tr_attr[1],
1156 key_length=tr_attr[0],
1157 )
1158 / ikev2.IKEv2_payload_Transform(
1159 transform_type="Integrity", transform_id=self.sa.esp_integ
1160 )
1161 / ikev2.IKEv2_payload_Transform(
1162 transform_type="Extended Sequence Number", transform_id="No ESN"
1163 )
1164 / ikev2.IKEv2_payload_Transform(
1165 transform_type="Extended Sequence Number", transform_id="ESN"
1166 )
1167 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001168
Filip Tehlar68ad6252020-10-30 05:28:11 +00001169 c = self.sa.child_sas[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001170 props = ikev2.IKEv2_payload_Proposal(
1171 proposal=1, proto="ESP", SPIsize=4, SPI=c.rspi, trans_nb=4, trans=trans
1172 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001173
1174 tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001175 plain = (
1176 ikev2.IKEv2_payload_IDi(
1177 next_payload="IDr", IDtype=self.sa.id_type, load=self.sa.i_id
1178 )
1179 / ikev2.IKEv2_payload_IDr(
1180 next_payload="AUTH", IDtype=self.sa.id_type, load=self.sa.r_id
1181 )
1182 / ikev2.IKEv2_payload_AUTH(
1183 next_payload="SA",
1184 auth_type=AuthMethod.value(self.sa.auth_method),
1185 load=self.sa.auth_data,
1186 )
1187 / ikev2.IKEv2_payload_SA(next_payload="TSi", prop=props)
1188 / ikev2.IKEv2_payload_TSi(
1189 next_payload="TSr", number_of_TSs=len(tsi), traffic_selector=tsi
1190 )
1191 / ikev2.IKEv2_payload_TSr(
1192 next_payload="Notify", number_of_TSs=len(tsr), traffic_selector=tsr
1193 )
1194 / ikev2.IKEv2_payload_Notify(type="INITIAL_CONTACT")
1195 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001196
1197 header = ikev2.IKEv2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001198 init_SPI=self.sa.ispi,
1199 resp_SPI=self.sa.rspi,
1200 id=self.sa.new_msg_id(),
1201 flags="Response",
1202 exch_type="IKE_AUTH",
1203 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001204
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001205 ike_msg = self.encrypt_ike_msg(header, plain, "IDi")
1206 packet = self.create_packet(
1207 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
1208 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001209 self.pg_send(self.pg0, packet)
1210
1211 def test_initiator(self):
1212 self.initiate_sa_init()
1213 self.sa.auth_init()
1214 self.sa.calc_child_keys()
1215 self.send_auth_response()
1216 self.verify_ike_sas()
1217
1218
1219class TemplateResponder(IkePeer):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001220 """responder test template"""
Filip Tehlare7c83962020-09-23 11:20:12 +00001221
Filip Tehlaredf29002020-10-10 04:39:11 +00001222 def initiate_del_sa_from_responder(self):
1223 self.pg0.enable_capture()
1224 self.pg_start()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001225 self.vapi.ikev2_initiate_del_ike_sa(ispi=int.from_bytes(self.sa.ispi, "little"))
Filip Tehlaredf29002020-10-10 04:39:11 +00001226 capture = self.pg0.get_capture(1)
1227 ih = self.get_ike_header(capture[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001228 self.assertNotIn("Response", ih.flags)
1229 self.assertNotIn("Initiator", ih.flags)
Filip Tehlaredf29002020-10-10 04:39:11 +00001230 self.assertEqual(ih.exch_type, 37) # INFORMATIONAL
1231 plain = self.sa.hmac_and_decrypt(ih)
1232 d = ikev2.IKEv2_payload_Delete(plain)
1233 self.assertEqual(d.proto, 1) # proto=IKEv2
1234 self.assertEqual(ih.init_SPI, self.sa.ispi)
1235 self.assertEqual(ih.resp_SPI, self.sa.rspi)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001236 header = ikev2.IKEv2(
1237 init_SPI=self.sa.ispi,
1238 resp_SPI=self.sa.rspi,
1239 flags="Initiator+Response",
1240 exch_type="INFORMATIONAL",
1241 id=ih.id,
1242 next_payload="Encrypted",
1243 )
1244 resp = self.encrypt_ike_msg(header, b"", None)
Filip Tehlaredf29002020-10-10 04:39:11 +00001245 self.send_and_assert_no_replies(self.pg0, resp)
Filip Tehlare7c83962020-09-23 11:20:12 +00001246
1247 def verify_del_sa(self, packet):
1248 ih = self.get_ike_header(packet)
1249 self.assertEqual(ih.id, self.sa.msg_id)
1250 self.assertEqual(ih.exch_type, 37) # exchange informational
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001251 self.assertIn("Response", ih.flags)
1252 self.assertNotIn("Initiator", ih.flags)
Filip Tehlaredf29002020-10-10 04:39:11 +00001253 self.assertEqual(ih.next_payload, 46) # Encrypted
1254 self.assertEqual(ih.init_SPI, self.sa.ispi)
1255 self.assertEqual(ih.resp_SPI, self.sa.rspi)
1256 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001257 self.assertEqual(plain, b"")
Filip Tehlare7c83962020-09-23 11:20:12 +00001258
Filip Tehlaredf29002020-10-10 04:39:11 +00001259 def initiate_del_sa_from_initiator(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001260 header = ikev2.IKEv2(
1261 init_SPI=self.sa.ispi,
1262 resp_SPI=self.sa.rspi,
1263 flags="Initiator",
1264 exch_type="INFORMATIONAL",
1265 id=self.sa.new_msg_id(),
1266 )
1267 del_sa = ikev2.IKEv2_payload_Delete(proto="IKEv2")
1268 ike_msg = self.encrypt_ike_msg(header, del_sa, "Delete")
1269 packet = self.create_packet(
1270 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
1271 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001272 self.pg0.add_stream(packet)
1273 self.pg0.enable_capture()
1274 self.pg_start()
1275 capture = self.pg0.get_capture(1)
1276 self.verify_del_sa(capture[0])
1277
Filip Tehlar027d8132020-12-04 17:38:11 +00001278 def send_sa_init_req(self):
Filip Tehlare7c83962020-09-23 11:20:12 +00001279 tr_attr = self.sa.ike_crypto_attr()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001280 trans = (
1281 ikev2.IKEv2_payload_Transform(
1282 transform_type="Encryption",
1283 transform_id=self.sa.ike_crypto,
1284 length=tr_attr[1],
1285 key_length=tr_attr[0],
1286 )
1287 / ikev2.IKEv2_payload_Transform(
1288 transform_type="Integrity", transform_id=self.sa.ike_integ
1289 )
1290 / ikev2.IKEv2_payload_Transform(
1291 transform_type="PRF", transform_id=self.sa.ike_prf_alg.name
1292 )
1293 / ikev2.IKEv2_payload_Transform(
1294 transform_type="GroupDesc", transform_id=self.sa.ike_dh
1295 )
1296 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001297
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001298 props = ikev2.IKEv2_payload_Proposal(
1299 proposal=1, proto="IKEv2", trans_nb=4, trans=trans
1300 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001301
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001302 next_payload = None if self.ip6 else "Notify"
Filip Tehlar027d8132020-12-04 17:38:11 +00001303
Filip Tehlare7c83962020-09-23 11:20:12 +00001304 self.sa.init_req_packet = (
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001305 ikev2.IKEv2(
1306 init_SPI=self.sa.ispi, flags="Initiator", exch_type="IKE_SA_INIT"
1307 )
1308 / ikev2.IKEv2_payload_SA(next_payload="KE", prop=props)
1309 / ikev2.IKEv2_payload_KE(
1310 next_payload="Nonce", group=self.sa.ike_dh, load=self.sa.my_dh_pub_key
1311 )
1312 / ikev2.IKEv2_payload_Nonce(next_payload=next_payload, load=self.sa.i_nonce)
1313 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001314
Filip Tehlar027d8132020-12-04 17:38:11 +00001315 if not self.ip6:
1316 if self.sa.i_natt:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001317 src_address = b"\x0a\x0a\x0a\x01"
Filip Tehlar027d8132020-12-04 17:38:11 +00001318 else:
1319 src_address = inet_pton(socket.AF_INET, self.pg0.remote_ip4)
Filip Tehlare7c83962020-09-23 11:20:12 +00001320
Filip Tehlar027d8132020-12-04 17:38:11 +00001321 if self.sa.r_natt:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001322 dst_address = b"\x0a\x0a\x0a\x0a"
Filip Tehlar027d8132020-12-04 17:38:11 +00001323 else:
1324 dst_address = inet_pton(socket.AF_INET, self.pg0.local_ip4)
1325
1326 src_nat = self.sa.compute_nat_sha1(src_address, self.sa.sport)
1327 dst_nat = self.sa.compute_nat_sha1(dst_address, self.sa.dport)
1328 nat_src_detection = ikev2.IKEv2_payload_Notify(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001329 type="NAT_DETECTION_SOURCE_IP", load=src_nat, next_payload="Notify"
1330 )
Filip Tehlar027d8132020-12-04 17:38:11 +00001331 nat_dst_detection = ikev2.IKEv2_payload_Notify(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001332 type="NAT_DETECTION_DESTINATION_IP", load=dst_nat
1333 )
1334 self.sa.init_req_packet = (
1335 self.sa.init_req_packet / nat_src_detection / nat_dst_detection
1336 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001337
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001338 ike_msg = self.create_packet(
1339 self.pg0,
1340 self.sa.init_req_packet,
1341 self.sa.sport,
1342 self.sa.dport,
1343 self.sa.natt,
1344 self.ip6,
1345 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001346 self.pg0.add_stream(ike_msg)
1347 self.pg0.enable_capture()
1348 self.pg_start()
1349 capture = self.pg0.get_capture(1)
1350 self.verify_sa_init(capture[0])
1351
Atzm Watanabec65921f2022-08-12 14:29:31 +09001352 def generate_auth_payload(self, last_payload=None, is_rekey=False, kex=False):
Filip Tehlare7c83962020-09-23 11:20:12 +00001353 tr_attr = self.sa.esp_crypto_attr()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001354 last_payload = last_payload or "Notify"
Atzm Watanabec65921f2022-08-12 14:29:31 +09001355 trans_nb = 4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001356 trans = (
1357 ikev2.IKEv2_payload_Transform(
1358 transform_type="Encryption",
1359 transform_id=self.sa.esp_crypto,
1360 length=tr_attr[1],
1361 key_length=tr_attr[0],
1362 )
1363 / ikev2.IKEv2_payload_Transform(
1364 transform_type="Integrity", transform_id=self.sa.esp_integ
1365 )
1366 / ikev2.IKEv2_payload_Transform(
1367 transform_type="Extended Sequence Number", transform_id="No ESN"
1368 )
1369 / ikev2.IKEv2_payload_Transform(
1370 transform_type="Extended Sequence Number", transform_id="ESN"
1371 )
1372 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001373
Atzm Watanabec65921f2022-08-12 14:29:31 +09001374 if kex:
1375 trans_nb += 1
1376 trans /= ikev2.IKEv2_payload_Transform(
1377 transform_type="GroupDesc", transform_id=self.sa.ike_dh
1378 )
1379
Filip Tehlar68ad6252020-10-30 05:28:11 +00001380 c = self.sa.child_sas[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001381 props = ikev2.IKEv2_payload_Proposal(
Atzm Watanabec65921f2022-08-12 14:29:31 +09001382 proposal=1,
1383 proto="ESP",
1384 SPIsize=4,
1385 SPI=c.ispi,
1386 trans_nb=trans_nb,
1387 trans=trans,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001388 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001389
1390 tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001391 plain = (
1392 ikev2.IKEv2_payload_AUTH(
1393 next_payload="SA",
1394 auth_type=AuthMethod.value(self.sa.auth_method),
1395 load=self.sa.auth_data,
1396 )
1397 / ikev2.IKEv2_payload_SA(next_payload="TSi", prop=props)
1398 / ikev2.IKEv2_payload_TSi(
1399 next_payload="TSr", number_of_TSs=len(tsi), traffic_selector=tsi
1400 )
1401 / ikev2.IKEv2_payload_TSr(
1402 next_payload=last_payload, number_of_TSs=len(tsr), traffic_selector=tsr
1403 )
1404 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001405
Filip Tehlar68ad6252020-10-30 05:28:11 +00001406 if is_rekey:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001407 first_payload = "Nonce"
Atzm Watanabec65921f2022-08-12 14:29:31 +09001408 if kex:
1409 head = ikev2.IKEv2_payload_Nonce(
1410 load=self.sa.i_nonce, next_payload="KE"
1411 ) / ikev2.IKEv2_payload_KE(
1412 group=self.sa.ike_dh, load=self.sa.my_dh_pub_key, next_payload="SA"
1413 )
1414 else:
1415 head = ikev2.IKEv2_payload_Nonce(
1416 load=self.sa.i_nonce, next_payload="SA"
1417 )
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001418 plain = (
Atzm Watanabec65921f2022-08-12 14:29:31 +09001419 head
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001420 / plain
Atzm Watanabe03aae962022-08-08 15:45:36 +09001421 / ikev2.IKEv2_payload_Notify(
1422 type="REKEY_SA",
1423 proto="ESP",
1424 SPI=c.ispi,
1425 length=8 + len(c.ispi),
1426 next_payload="Notify",
1427 )
1428 / ikev2.IKEv2_payload_Notify(type="ESP_TFC_PADDING_NOT_SUPPORTED")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001429 )
Filip Tehlar68ad6252020-10-30 05:28:11 +00001430 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001431 first_payload = "IDi"
Benoît Gannec7cceee2021-09-28 11:19:37 +02001432 if self.no_idr_auth:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001433 ids = ikev2.IKEv2_payload_IDi(
1434 next_payload="AUTH", IDtype=self.sa.id_type, load=self.sa.i_id
1435 )
Benoît Gannec7cceee2021-09-28 11:19:37 +02001436 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001437 ids = ikev2.IKEv2_payload_IDi(
1438 next_payload="IDr", IDtype=self.sa.id_type, load=self.sa.i_id
1439 ) / ikev2.IKEv2_payload_IDr(
1440 next_payload="AUTH", IDtype=self.sa.id_type, load=self.sa.r_id
1441 )
Filip Tehlar68ad6252020-10-30 05:28:11 +00001442 plain = ids / plain
1443 return plain, first_payload
1444
1445 def send_sa_auth(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001446 plain, first_payload = self.generate_auth_payload(last_payload="Notify")
1447 plain = plain / ikev2.IKEv2_payload_Notify(type="INITIAL_CONTACT")
Filip Tehlare7c83962020-09-23 11:20:12 +00001448 header = ikev2.IKEv2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001449 init_SPI=self.sa.ispi,
1450 resp_SPI=self.sa.rspi,
1451 id=self.sa.new_msg_id(),
1452 flags="Initiator",
1453 exch_type="IKE_AUTH",
1454 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001455
Filip Tehlar68ad6252020-10-30 05:28:11 +00001456 ike_msg = self.encrypt_ike_msg(header, plain, first_payload)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001457 packet = self.create_packet(
1458 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
1459 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001460 self.pg0.add_stream(packet)
1461 self.pg0.enable_capture()
1462 self.pg_start()
1463 capture = self.pg0.get_capture(1)
1464 self.verify_sa_auth_resp(capture[0])
1465
1466 def verify_sa_init(self, packet):
1467 ih = self.get_ike_header(packet)
1468
1469 self.assertEqual(ih.id, self.sa.msg_id)
1470 self.assertEqual(ih.exch_type, 34)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001471 self.assertIn("Response", ih.flags)
Filip Tehlare7c83962020-09-23 11:20:12 +00001472 self.assertEqual(ih.init_SPI, self.sa.ispi)
1473 self.assertNotEqual(ih.resp_SPI, 0)
1474 self.sa.rspi = ih.resp_SPI
1475 try:
1476 sa = ih[ikev2.IKEv2_payload_SA]
1477 self.sa.r_nonce = ih[ikev2.IKEv2_payload_Nonce].load
1478 self.sa.r_dh_data = ih[ikev2.IKEv2_payload_KE].load
1479 except IndexError as e:
1480 self.logger.error("unexpected reply: SA/Nonce/KE payload found!")
1481 self.logger.error(ih.show())
1482 raise
1483 self.sa.complete_dh_data()
1484 self.sa.calc_keys()
1485 self.sa.auth_init()
1486
1487 def verify_sa_auth_resp(self, packet):
1488 ike = self.get_ike_header(packet)
1489 udp = packet[UDP]
1490 self.verify_udp(udp)
1491 self.assertEqual(ike.id, self.sa.msg_id)
1492 plain = self.sa.hmac_and_decrypt(ike)
Filip Tehlar68ad6252020-10-30 05:28:11 +00001493 idr = ikev2.IKEv2_payload_IDr(plain)
1494 prop = idr[ikev2.IKEv2_payload_Proposal]
1495 self.assertEqual(prop.SPIsize, 4)
1496 self.sa.child_sas[0].rspi = prop.SPI
Filip Tehlare7c83962020-09-23 11:20:12 +00001497 self.sa.calc_child_keys()
1498
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001499 IKE_NODE_SUFFIX = "ip4"
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00001500
1501 def verify_counters(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001502 self.assert_counter(2, "processed", self.IKE_NODE_SUFFIX)
1503 self.assert_counter(1, "init_sa_req", self.IKE_NODE_SUFFIX)
1504 self.assert_counter(1, "ike_auth_req", self.IKE_NODE_SUFFIX)
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00001505
Filip Tehlar68d27532021-01-25 10:09:27 +00001506 r = self.vapi.ikev2_sa_dump()
1507 s = r[0].sa.stats
1508 self.assertEqual(1, s.n_sa_auth_req)
1509 self.assertEqual(1, s.n_sa_init_req)
1510
Filip Tehlar12b517b2020-04-26 18:05:05 +00001511 def test_responder(self):
Filip Tehlar027d8132020-12-04 17:38:11 +00001512 self.send_sa_init_req()
Filip Tehlar12b517b2020-04-26 18:05:05 +00001513 self.send_sa_auth()
jan_cavojskya340fe12020-07-08 09:24:12 +02001514 self.verify_ipsec_sas()
1515 self.verify_ike_sas()
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00001516 self.verify_counters()
Filip Tehlar12b517b2020-04-26 18:05:05 +00001517
1518
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001519class Ikev2Params(object):
1520 def config_params(self, params={}):
Filip Tehlar4f42a712020-07-01 08:56:59 +00001521 ec = VppEnum.vl_api_ipsec_crypto_alg_t
1522 ei = VppEnum.vl_api_ipsec_integ_alg_t
1523 self.vpp_enums = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001524 "AES-CBC-128": ec.IPSEC_API_CRYPTO_ALG_AES_CBC_128,
1525 "AES-CBC-192": ec.IPSEC_API_CRYPTO_ALG_AES_CBC_192,
1526 "AES-CBC-256": ec.IPSEC_API_CRYPTO_ALG_AES_CBC_256,
1527 "AES-GCM-16ICV-128": ec.IPSEC_API_CRYPTO_ALG_AES_GCM_128,
1528 "AES-GCM-16ICV-192": ec.IPSEC_API_CRYPTO_ALG_AES_GCM_192,
1529 "AES-GCM-16ICV-256": ec.IPSEC_API_CRYPTO_ALG_AES_GCM_256,
1530 "HMAC-SHA1-96": ei.IPSEC_API_INTEG_ALG_SHA1_96,
1531 "SHA2-256-128": ei.IPSEC_API_INTEG_ALG_SHA_256_128,
1532 "SHA2-384-192": ei.IPSEC_API_INTEG_ALG_SHA_384_192,
1533 "SHA2-512-256": ei.IPSEC_API_INTEG_ALG_SHA_512_256,
1534 }
Filip Tehlar4f42a712020-07-01 08:56:59 +00001535
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001536 dpd_disabled = True if "dpd_disabled" not in params else params["dpd_disabled"]
Filip Tehlar2008e312020-11-09 13:23:24 +00001537 if dpd_disabled:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001538 self.vapi.cli("ikev2 dpd disable")
1539 self.del_sa_from_responder = (
1540 False
1541 if "del_sa_from_responder" not in params
1542 else params["del_sa_from_responder"]
1543 )
1544 i_natt = False if "i_natt" not in params else params["i_natt"]
1545 r_natt = False if "r_natt" not in params else params["r_natt"]
1546 self.p = Profile(self, "pr1")
1547 self.ip6 = False if "ip6" not in params else params["ip6"]
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001548
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001549 if "auth" in params and params["auth"] == "rsa-sig":
1550 auth_method = "rsa-sig"
Klement Sekerab23ffd72021-05-31 16:08:53 +02001551 work_dir = f"{config.vpp_ws_dir}/src/plugins/ikev2/test/certs/"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001552 self.vapi.ikev2_set_local_key(key_file=work_dir + params["server-key"])
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001553
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001554 client_file = work_dir + params["client-cert"]
1555 server_pem = open(work_dir + params["server-cert"]).read()
1556 client_priv = open(work_dir + params["client-key"]).read()
1557 client_priv = load_pem_private_key(
1558 str.encode(client_priv), None, default_backend()
1559 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001560 self.peer_cert = x509.load_pem_x509_certificate(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001561 str.encode(server_pem), default_backend()
1562 )
1563 self.p.add_auth(method="rsa-sig", data=str.encode(client_file))
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001564 auth_data = None
1565 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001566 auth_data = b"$3cr3tpa$$w0rd"
1567 self.p.add_auth(method="shared-key", data=auth_data)
1568 auth_method = "shared-key"
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001569 client_priv = None
1570
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001571 is_init = True if "is_initiator" not in params else params["is_initiator"]
1572 self.no_idr_auth = params.get("no_idr_in_auth", False)
Filip Tehlare7c83962020-09-23 11:20:12 +00001573
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001574 idr = {"id_type": "fqdn", "data": b"vpp.home"}
1575 idi = {"id_type": "fqdn", "data": b"roadwarrior.example.com"}
1576 r_id = self.idr = idr["data"]
1577 i_id = self.idi = idi["data"]
Filip Tehlare7c83962020-09-23 11:20:12 +00001578 if is_init:
Benoît Gannec7cceee2021-09-28 11:19:37 +02001579 # scapy is initiator, VPP is responder
Filip Tehlare7c83962020-09-23 11:20:12 +00001580 self.p.add_local_id(**idr)
1581 self.p.add_remote_id(**idi)
Benoît Gannec7cceee2021-09-28 11:19:37 +02001582 if self.no_idr_auth:
1583 r_id = None
Filip Tehlare7c83962020-09-23 11:20:12 +00001584 else:
Benoît Gannec7cceee2021-09-28 11:19:37 +02001585 # VPP is initiator, scapy is responder
Filip Tehlare7c83962020-09-23 11:20:12 +00001586 self.p.add_local_id(**idi)
Benoît Gannec7cceee2021-09-28 11:19:37 +02001587 if not self.no_idr_auth:
1588 self.p.add_remote_id(**idr)
Filip Tehlare7c83962020-09-23 11:20:12 +00001589
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001590 loc_ts = (
1591 {"start_addr": "10.10.10.0", "end_addr": "10.10.10.255"}
1592 if "loc_ts" not in params
1593 else params["loc_ts"]
1594 )
1595 rem_ts = (
1596 {"start_addr": "10.0.0.0", "end_addr": "10.0.0.255"}
1597 if "rem_ts" not in params
1598 else params["rem_ts"]
1599 )
Filip Tehlar84962d12020-09-08 06:08:05 +00001600 self.p.add_local_ts(**loc_ts)
1601 self.p.add_remote_ts(**rem_ts)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001602 if "responder" in params:
1603 self.p.add_responder(params["responder"])
1604 if "ike_transforms" in params:
1605 self.p.add_ike_transforms(params["ike_transforms"])
1606 if "esp_transforms" in params:
1607 self.p.add_esp_transforms(params["esp_transforms"])
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001608
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001609 udp_encap = False if "udp_encap" not in params else params["udp_encap"]
Filip Tehlar67b8a7f2020-11-06 11:00:42 +00001610 if udp_encap:
1611 self.p.set_udp_encap(True)
1612
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001613 if "responder_hostname" in params:
1614 hn = params["responder_hostname"]
Filip Tehlaraf2cc642021-02-22 16:15:51 +00001615 self.p.add_responder_hostname(hn)
1616
1617 # configure static dns record
1618 self.vapi.dns_name_server_add_del(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001619 is_ip6=0, is_add=1, server_address=IPv4Address("8.8.8.8").packed
1620 )
Filip Tehlaraf2cc642021-02-22 16:15:51 +00001621 self.vapi.dns_enable_disable(enable=1)
1622
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001623 cmd = "dns cache add {} {}".format(hn["hostname"], self.pg0.remote_ip4)
Filip Tehlaraf2cc642021-02-22 16:15:51 +00001624 self.vapi.cli(cmd)
1625
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001626 self.sa = IKEv2SA(
1627 self,
1628 i_id=i_id,
1629 r_id=r_id,
1630 is_initiator=is_init,
1631 id_type=self.p.local_id["id_type"],
1632 i_natt=i_natt,
1633 r_natt=r_natt,
1634 priv_key=client_priv,
1635 auth_method=auth_method,
1636 nonce=params.get("nonce"),
1637 auth_data=auth_data,
1638 udp_encap=udp_encap,
1639 local_ts=self.p.remote_ts,
1640 remote_ts=self.p.local_ts,
1641 )
Benoît Gannec7cceee2021-09-28 11:19:37 +02001642
Filip Tehlar68ad6252020-10-30 05:28:11 +00001643 if is_init:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001644 ike_crypto = (
1645 ("AES-CBC", 32) if "ike-crypto" not in params else params["ike-crypto"]
1646 )
1647 ike_integ = (
1648 "HMAC-SHA1-96" if "ike-integ" not in params else params["ike-integ"]
1649 )
1650 ike_dh = "2048MODPgr" if "ike-dh" not in params else params["ike-dh"]
Filip Tehlar4f42a712020-07-01 08:56:59 +00001651
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001652 esp_crypto = (
1653 ("AES-CBC", 32) if "esp-crypto" not in params else params["esp-crypto"]
1654 )
1655 esp_integ = (
1656 "HMAC-SHA1-96" if "esp-integ" not in params else params["esp-integ"]
1657 )
Filip Tehlar4f42a712020-07-01 08:56:59 +00001658
Filip Tehlar68ad6252020-10-30 05:28:11 +00001659 self.sa.set_ike_props(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001660 crypto=ike_crypto[0],
1661 crypto_key_len=ike_crypto[1],
1662 integ=ike_integ,
1663 prf="PRF_HMAC_SHA2_256",
1664 dh=ike_dh,
1665 )
Filip Tehlar68ad6252020-10-30 05:28:11 +00001666 self.sa.set_esp_props(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001667 crypto=esp_crypto[0], crypto_key_len=esp_crypto[1], integ=esp_integ
1668 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001669
1670
Andrew Yourtchenkobc378782023-09-26 16:01:21 +02001671@unittest.skipIf("ikev2" in config.excluded_plugins, "Exclude IKEv2 plugin tests")
Filip Tehlar459d17b2020-07-06 15:40:08 +00001672class TestApi(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001673 """Test IKEV2 API"""
1674
Filip Tehlar459d17b2020-07-06 15:40:08 +00001675 @classmethod
1676 def setUpClass(cls):
1677 super(TestApi, cls).setUpClass()
1678
1679 @classmethod
1680 def tearDownClass(cls):
1681 super(TestApi, cls).tearDownClass()
1682
1683 def tearDown(self):
1684 super(TestApi, self).tearDown()
1685 self.p1.remove_vpp_config()
1686 self.p2.remove_vpp_config()
1687 r = self.vapi.ikev2_profile_dump()
1688 self.assertEqual(len(r), 0)
1689
1690 def configure_profile(self, cfg):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001691 p = Profile(self, cfg["name"])
1692 p.add_local_id(id_type=cfg["loc_id"][0], data=cfg["loc_id"][1])
1693 p.add_remote_id(id_type=cfg["rem_id"][0], data=cfg["rem_id"][1])
1694 p.add_local_ts(**cfg["loc_ts"])
1695 p.add_remote_ts(**cfg["rem_ts"])
1696 p.add_responder(cfg["responder"])
1697 p.add_ike_transforms(cfg["ike_ts"])
1698 p.add_esp_transforms(cfg["esp_ts"])
1699 p.add_auth(**cfg["auth"])
1700 p.set_udp_encap(cfg["udp_encap"])
1701 p.set_ipsec_over_udp_port(cfg["ipsec_over_udp_port"])
1702 if "lifetime_data" in cfg:
1703 p.set_lifetime_data(cfg["lifetime_data"])
1704 if "tun_itf" in cfg:
1705 p.set_tunnel_interface(cfg["tun_itf"])
1706 if "natt_disabled" in cfg and cfg["natt_disabled"]:
Filip Tehlard7fc12f2020-10-30 04:47:44 +00001707 p.disable_natt()
Filip Tehlar459d17b2020-07-06 15:40:08 +00001708 p.add_vpp_config()
1709 return p
1710
1711 def test_profile_api(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001712 """test profile dump API"""
Filip Tehlar84962d12020-09-08 06:08:05 +00001713 loc_ts4 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001714 "proto": 8,
1715 "start_port": 1,
1716 "end_port": 19,
1717 "start_addr": "3.3.3.2",
1718 "end_addr": "3.3.3.3",
1719 }
Filip Tehlar84962d12020-09-08 06:08:05 +00001720 rem_ts4 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001721 "proto": 9,
1722 "start_port": 10,
1723 "end_port": 119,
1724 "start_addr": "4.5.76.80",
1725 "end_addr": "2.3.4.6",
1726 }
Filip Tehlar459d17b2020-07-06 15:40:08 +00001727
Filip Tehlar84962d12020-09-08 06:08:05 +00001728 loc_ts6 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001729 "proto": 8,
1730 "start_port": 1,
1731 "end_port": 19,
1732 "start_addr": "ab::1",
1733 "end_addr": "ab::4",
1734 }
Filip Tehlar84962d12020-09-08 06:08:05 +00001735 rem_ts6 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001736 "proto": 9,
1737 "start_port": 10,
1738 "end_port": 119,
1739 "start_addr": "cd::12",
1740 "end_addr": "cd::13",
1741 }
Filip Tehlar84962d12020-09-08 06:08:05 +00001742
Filip Tehlar459d17b2020-07-06 15:40:08 +00001743 conf = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001744 "p1": {
1745 "name": "p1",
1746 "natt_disabled": True,
1747 "loc_id": ("fqdn", b"vpp.home"),
1748 "rem_id": ("fqdn", b"roadwarrior.example.com"),
1749 "loc_ts": loc_ts4,
1750 "rem_ts": rem_ts4,
1751 "responder": {"sw_if_index": 0, "addr": "5.6.7.8"},
1752 "ike_ts": {
1753 "crypto_alg": 20,
1754 "crypto_key_size": 32,
1755 "integ_alg": 0,
1756 "dh_group": 1,
1757 },
1758 "esp_ts": {"crypto_alg": 13, "crypto_key_size": 24, "integ_alg": 2},
1759 "auth": {"method": "shared-key", "data": b"sharedkeydata"},
1760 "udp_encap": True,
1761 "ipsec_over_udp_port": 4501,
1762 "lifetime_data": {
1763 "lifetime": 123,
1764 "lifetime_maxdata": 20192,
1765 "lifetime_jitter": 9,
1766 "handover": 132,
1767 },
Filip Tehlar459d17b2020-07-06 15:40:08 +00001768 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001769 "p2": {
1770 "name": "p2",
1771 "loc_id": ("ip4-addr", b"192.168.2.1"),
1772 "rem_id": ("ip6-addr", b"abcd::1"),
1773 "loc_ts": loc_ts6,
1774 "rem_ts": rem_ts6,
1775 "responder": {"sw_if_index": 4, "addr": "def::10"},
1776 "ike_ts": {
1777 "crypto_alg": 12,
1778 "crypto_key_size": 16,
1779 "integ_alg": 3,
1780 "dh_group": 3,
1781 },
1782 "esp_ts": {"crypto_alg": 9, "crypto_key_size": 24, "integ_alg": 4},
1783 "auth": {"method": "shared-key", "data": b"sharedkeydata"},
1784 "udp_encap": False,
1785 "ipsec_over_udp_port": 4600,
1786 "tun_itf": 0,
1787 },
Filip Tehlar459d17b2020-07-06 15:40:08 +00001788 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001789 self.p1 = self.configure_profile(conf["p1"])
1790 self.p2 = self.configure_profile(conf["p2"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001791
1792 r = self.vapi.ikev2_profile_dump()
1793 self.assertEqual(len(r), 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001794 self.verify_profile(r[0].profile, conf["p1"])
1795 self.verify_profile(r[1].profile, conf["p2"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001796
1797 def verify_id(self, api_id, cfg_id):
1798 self.assertEqual(api_id.type, IDType.value(cfg_id[0]))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001799 self.assertEqual(bytes(api_id.data, "ascii"), cfg_id[1])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001800
1801 def verify_ts(self, api_ts, cfg_ts):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001802 self.assertEqual(api_ts.protocol_id, cfg_ts["proto"])
1803 self.assertEqual(api_ts.start_port, cfg_ts["start_port"])
1804 self.assertEqual(api_ts.end_port, cfg_ts["end_port"])
1805 self.assertEqual(api_ts.start_addr, ip_address(text_type(cfg_ts["start_addr"])))
1806 self.assertEqual(api_ts.end_addr, ip_address(text_type(cfg_ts["end_addr"])))
Filip Tehlar459d17b2020-07-06 15:40:08 +00001807
1808 def verify_responder(self, api_r, cfg_r):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001809 self.assertEqual(api_r.sw_if_index, cfg_r["sw_if_index"])
1810 self.assertEqual(api_r.addr, ip_address(cfg_r["addr"]))
Filip Tehlar459d17b2020-07-06 15:40:08 +00001811
1812 def verify_transforms(self, api_ts, cfg_ts):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001813 self.assertEqual(api_ts.crypto_alg, cfg_ts["crypto_alg"])
1814 self.assertEqual(api_ts.crypto_key_size, cfg_ts["crypto_key_size"])
1815 self.assertEqual(api_ts.integ_alg, cfg_ts["integ_alg"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001816
1817 def verify_ike_transforms(self, api_ts, cfg_ts):
1818 self.verify_transforms(api_ts, cfg_ts)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001819 self.assertEqual(api_ts.dh_group, cfg_ts["dh_group"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001820
1821 def verify_esp_transforms(self, api_ts, cfg_ts):
1822 self.verify_transforms(api_ts, cfg_ts)
1823
1824 def verify_auth(self, api_auth, cfg_auth):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001825 self.assertEqual(api_auth.method, AuthMethod.value(cfg_auth["method"]))
1826 self.assertEqual(api_auth.data, cfg_auth["data"])
1827 self.assertEqual(api_auth.data_len, len(cfg_auth["data"]))
Filip Tehlar459d17b2020-07-06 15:40:08 +00001828
1829 def verify_lifetime_data(self, p, ld):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001830 self.assertEqual(p.lifetime, ld["lifetime"])
1831 self.assertEqual(p.lifetime_maxdata, ld["lifetime_maxdata"])
1832 self.assertEqual(p.lifetime_jitter, ld["lifetime_jitter"])
1833 self.assertEqual(p.handover, ld["handover"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001834
1835 def verify_profile(self, ap, cp):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001836 self.assertEqual(ap.name, cp["name"])
1837 self.assertEqual(ap.udp_encap, cp["udp_encap"])
1838 self.verify_id(ap.loc_id, cp["loc_id"])
1839 self.verify_id(ap.rem_id, cp["rem_id"])
1840 self.verify_ts(ap.loc_ts, cp["loc_ts"])
1841 self.verify_ts(ap.rem_ts, cp["rem_ts"])
1842 self.verify_responder(ap.responder, cp["responder"])
1843 self.verify_ike_transforms(ap.ike_ts, cp["ike_ts"])
1844 self.verify_esp_transforms(ap.esp_ts, cp["esp_ts"])
1845 self.verify_auth(ap.auth, cp["auth"])
1846 natt_dis = False if "natt_disabled" not in cp else cp["natt_disabled"]
Filip Tehlard7fc12f2020-10-30 04:47:44 +00001847 self.assertTrue(natt_dis == ap.natt_disabled)
1848
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001849 if "lifetime_data" in cp:
1850 self.verify_lifetime_data(ap, cp["lifetime_data"])
1851 self.assertEqual(ap.ipsec_over_udp_port, cp["ipsec_over_udp_port"])
1852 if "tun_itf" in cp:
1853 self.assertEqual(ap.tun_itf, cp["tun_itf"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001854 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001855 self.assertEqual(ap.tun_itf, 0xFFFFFFFF)
Filip Tehlar459d17b2020-07-06 15:40:08 +00001856
1857
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001858@tag_fixme_vpp_workers
Filip Tehlar027d8132020-12-04 17:38:11 +00001859class TestResponderBehindNAT(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001860 """test responder - responder behind NAT"""
Filip Tehlar027d8132020-12-04 17:38:11 +00001861
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001862 IKE_NODE_SUFFIX = "ip4-natt"
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00001863
Filip Tehlar027d8132020-12-04 17:38:11 +00001864 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001865 self.config_params({"r_natt": True})
Filip Tehlar027d8132020-12-04 17:38:11 +00001866
1867
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001868@tag_fixme_vpp_workers
Filip Tehlar18107c92020-12-01 14:51:09 +00001869class TestInitiatorNATT(TemplateInitiator, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001870 """test ikev2 initiator - NAT traversal (intitiator behind NAT)"""
Filip Tehlar18107c92020-12-01 14:51:09 +00001871
1872 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001873 self.config_params(
1874 {
1875 "i_natt": True,
1876 "is_initiator": False, # seen from test case perspective
1877 # thus vpp is initiator
1878 "responder": {
1879 "sw_if_index": self.pg0.sw_if_index,
1880 "addr": self.pg0.remote_ip4,
1881 },
1882 "ike-crypto": ("AES-GCM-16ICV", 32),
1883 "ike-integ": "NULL",
1884 "ike-dh": "3072MODPgr",
1885 "ike_transforms": {
1886 "crypto_alg": 20, # "aes-gcm-16"
1887 "crypto_key_size": 256,
1888 "dh_group": 15, # "modp-3072"
1889 },
1890 "esp_transforms": {
1891 "crypto_alg": 12, # "aes-cbc"
1892 "crypto_key_size": 256,
1893 # "hmac-sha2-256-128"
1894 "integ_alg": 12,
1895 },
1896 }
1897 )
Filip Tehlar18107c92020-12-01 14:51:09 +00001898
1899
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001900@tag_fixme_vpp_workers
Filip Tehlare7c83962020-09-23 11:20:12 +00001901class TestInitiatorPsk(TemplateInitiator, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001902 """test ikev2 initiator - pre shared key auth"""
Filip Tehlaredf29002020-10-10 04:39:11 +00001903
Filip Tehlare7c83962020-09-23 11:20:12 +00001904 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001905 self.config_params(
1906 {
1907 "is_initiator": False, # seen from test case perspective
1908 # thus vpp is initiator
1909 "ike-crypto": ("AES-GCM-16ICV", 32),
1910 "ike-integ": "NULL",
1911 "ike-dh": "3072MODPgr",
1912 "ike_transforms": {
1913 "crypto_alg": 20, # "aes-gcm-16"
1914 "crypto_key_size": 256,
1915 "dh_group": 15, # "modp-3072"
1916 },
1917 "esp_transforms": {
1918 "crypto_alg": 12, # "aes-cbc"
1919 "crypto_key_size": 256,
1920 # "hmac-sha2-256-128"
1921 "integ_alg": 12,
1922 },
1923 "responder_hostname": {
1924 "hostname": "vpp.responder.org",
1925 "sw_if_index": self.pg0.sw_if_index,
1926 },
1927 }
1928 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001929
1930
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001931@tag_fixme_vpp_workers
Filip Tehlar38340fa2020-11-19 21:34:48 +00001932class TestInitiatorRequestWindowSize(TestInitiatorPsk):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001933 """test initiator - request window size (1)"""
Filip Tehlar38340fa2020-11-19 21:34:48 +00001934
1935 def rekey_respond(self, req, update_child_sa_data):
1936 ih = self.get_ike_header(req)
1937 plain = self.sa.hmac_and_decrypt(ih)
1938 sa = ikev2.IKEv2_payload_SA(plain)
1939 if update_child_sa_data:
1940 prop = sa[ikev2.IKEv2_payload_Proposal]
1941 self.sa.i_nonce = sa[ikev2.IKEv2_payload_Nonce].load
1942 self.sa.r_nonce = self.sa.i_nonce
1943 self.sa.child_sas[0].ispi = prop.SPI
1944 self.sa.child_sas[0].rspi = prop.SPI
1945 self.sa.calc_child_keys()
1946
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001947 header = ikev2.IKEv2(
1948 init_SPI=self.sa.ispi,
1949 resp_SPI=self.sa.rspi,
1950 flags="Response",
1951 exch_type=36,
1952 id=ih.id,
1953 next_payload="Encrypted",
1954 )
1955 resp = self.encrypt_ike_msg(header, sa, "SA")
1956 packet = self.create_packet(
1957 self.pg0, resp, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
1958 )
Filip Tehlar38340fa2020-11-19 21:34:48 +00001959 self.send_and_assert_no_replies(self.pg0, packet)
1960
1961 def test_initiator(self):
1962 super(TestInitiatorRequestWindowSize, self).test_initiator()
1963 self.pg0.enable_capture()
1964 self.pg_start()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001965 ispi = int.from_bytes(self.sa.child_sas[0].ispi, "little")
Filip Tehlar38340fa2020-11-19 21:34:48 +00001966 self.vapi.ikev2_initiate_rekey_child_sa(ispi=ispi)
1967 self.vapi.ikev2_initiate_rekey_child_sa(ispi=ispi)
1968 capture = self.pg0.get_capture(2)
1969
1970 # reply in reverse order
1971 self.rekey_respond(capture[1], True)
1972 self.rekey_respond(capture[0], False)
1973
1974 # verify that only the second request was accepted
1975 self.verify_ike_sas()
1976 self.verify_ipsec_sas(is_rekey=True)
1977
1978
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00001979@tag_fixme_vpp_workers
Filip Tehlar68ad6252020-10-30 05:28:11 +00001980class TestInitiatorRekey(TestInitiatorPsk):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001981 """test ikev2 initiator - rekey"""
Filip Tehlar68ad6252020-10-30 05:28:11 +00001982
1983 def rekey_from_initiator(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001984 ispi = int.from_bytes(self.sa.child_sas[0].ispi, "little")
Filip Tehlar68ad6252020-10-30 05:28:11 +00001985 self.pg0.enable_capture()
1986 self.pg_start()
1987 self.vapi.ikev2_initiate_rekey_child_sa(ispi=ispi)
1988 capture = self.pg0.get_capture(1)
1989 ih = self.get_ike_header(capture[0])
1990 self.assertEqual(ih.exch_type, 36) # CHILD_SA
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001991 self.assertNotIn("Response", ih.flags)
1992 self.assertIn("Initiator", ih.flags)
Filip Tehlar68ad6252020-10-30 05:28:11 +00001993 plain = self.sa.hmac_and_decrypt(ih)
1994 sa = ikev2.IKEv2_payload_SA(plain)
1995 prop = sa[ikev2.IKEv2_payload_Proposal]
Filip Tehlar68ad6252020-10-30 05:28:11 +00001996 self.sa.i_nonce = sa[ikev2.IKEv2_payload_Nonce].load
1997 self.sa.r_nonce = self.sa.i_nonce
1998 # update new responder SPI
1999 self.sa.child_sas[0].ispi = prop.SPI
2000 self.sa.child_sas[0].rspi = prop.SPI
2001 self.sa.calc_child_keys()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002002 header = ikev2.IKEv2(
2003 init_SPI=self.sa.ispi,
2004 resp_SPI=self.sa.rspi,
2005 flags="Response",
2006 exch_type=36,
2007 id=ih.id,
2008 next_payload="Encrypted",
2009 )
2010 resp = self.encrypt_ike_msg(header, sa, "SA")
2011 packet = self.create_packet(
2012 self.pg0, resp, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
2013 )
Filip Tehlar68ad6252020-10-30 05:28:11 +00002014 self.send_and_assert_no_replies(self.pg0, packet)
2015
2016 def test_initiator(self):
2017 super(TestInitiatorRekey, self).test_initiator()
2018 self.rekey_from_initiator()
2019 self.verify_ike_sas()
2020 self.verify_ipsec_sas(is_rekey=True)
2021
2022
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002023@tag_fixme_vpp_workers
Filip Tehlaredf29002020-10-10 04:39:11 +00002024class TestInitiatorDelSAFromResponder(TemplateInitiator, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002025 """test ikev2 initiator - delete IKE SA from responder"""
Filip Tehlaredf29002020-10-10 04:39:11 +00002026
2027 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002028 self.config_params(
2029 {
2030 "del_sa_from_responder": True,
2031 "is_initiator": False, # seen from test case perspective
2032 # thus vpp is initiator
2033 "responder": {
2034 "sw_if_index": self.pg0.sw_if_index,
2035 "addr": self.pg0.remote_ip4,
2036 },
2037 "ike-crypto": ("AES-GCM-16ICV", 32),
2038 "ike-integ": "NULL",
2039 "ike-dh": "3072MODPgr",
2040 "ike_transforms": {
2041 "crypto_alg": 20, # "aes-gcm-16"
2042 "crypto_key_size": 256,
2043 "dh_group": 15, # "modp-3072"
2044 },
2045 "esp_transforms": {
2046 "crypto_alg": 12, # "aes-cbc"
2047 "crypto_key_size": 256,
2048 # "hmac-sha2-256-128"
2049 "integ_alg": 12,
2050 },
2051 "no_idr_in_auth": True,
2052 }
2053 )
Filip Tehlaredf29002020-10-10 04:39:11 +00002054
2055
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002056@tag_fixme_vpp_workers
Filip Tehlar027d8132020-12-04 17:38:11 +00002057class TestResponderInitBehindNATT(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002058 """test ikev2 responder - initiator behind NAT"""
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002059
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002060 IKE_NODE_SUFFIX = "ip4-natt"
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002061
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002062 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002063 self.config_params({"i_natt": True})
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002064
2065
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002066@tag_fixme_vpp_workers
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002067class TestResponderPsk(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002068 """test ikev2 responder - pre shared key auth"""
2069
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002070 def config_tc(self):
2071 self.config_params()
2072
2073
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002074@tag_fixme_vpp_workers
Filip Tehlar2008e312020-11-09 13:23:24 +00002075class TestResponderDpd(TestResponderPsk):
2076 """
2077 Dead peer detection test
2078 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002079
Filip Tehlar2008e312020-11-09 13:23:24 +00002080 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002081 self.config_params({"dpd_disabled": False})
Filip Tehlar2008e312020-11-09 13:23:24 +00002082
2083 def tearDown(self):
2084 pass
2085
2086 def test_responder(self):
2087 self.vapi.ikev2_profile_set_liveness(period=2, max_retries=1)
2088 super(TestResponderDpd, self).test_responder()
2089 self.pg0.enable_capture()
2090 self.pg_start()
2091 # capture empty request but don't reply
2092 capture = self.pg0.get_capture(expected_count=1, timeout=5)
2093 ih = self.get_ike_header(capture[0])
2094 self.assertEqual(ih.exch_type, 37) # INFORMATIONAL
2095 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002096 self.assertEqual(plain, b"")
Filip Tehlar2008e312020-11-09 13:23:24 +00002097 # wait for SA expiration
2098 time.sleep(3)
2099 ike_sas = self.vapi.ikev2_sa_dump()
2100 self.assertEqual(len(ike_sas), 0)
2101 ipsec_sas = self.vapi.ipsec_sa_dump()
2102 self.assertEqual(len(ipsec_sas), 0)
2103
2104
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002105@tag_fixme_vpp_workers
Filip Tehlar68ad6252020-10-30 05:28:11 +00002106class TestResponderRekey(TestResponderPsk):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002107 """test ikev2 responder - rekey"""
Filip Tehlar68ad6252020-10-30 05:28:11 +00002108
Atzm Watanabec65921f2022-08-12 14:29:31 +09002109 WITH_KEX = False
2110
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002111 def send_rekey_from_initiator(self):
Atzm Watanabec65921f2022-08-12 14:29:31 +09002112 if self.WITH_KEX:
2113 self.sa.generate_dh_data()
2114 packet = self.create_rekey_request(kex=self.WITH_KEX)
Filip Tehlar68ad6252020-10-30 05:28:11 +00002115 self.pg0.add_stream(packet)
2116 self.pg0.enable_capture()
2117 self.pg_start()
2118 capture = self.pg0.get_capture(1)
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002119 return capture
2120
2121 def process_rekey_response(self, capture):
Filip Tehlar68ad6252020-10-30 05:28:11 +00002122 ih = self.get_ike_header(capture[0])
2123 plain = self.sa.hmac_and_decrypt(ih)
2124 sa = ikev2.IKEv2_payload_SA(plain)
2125 prop = sa[ikev2.IKEv2_payload_Proposal]
Filip Tehlar68ad6252020-10-30 05:28:11 +00002126 self.sa.r_nonce = sa[ikev2.IKEv2_payload_Nonce].load
2127 # update new responder SPI
2128 self.sa.child_sas[0].rspi = prop.SPI
Atzm Watanabec65921f2022-08-12 14:29:31 +09002129 if self.WITH_KEX:
2130 self.sa.r_dh_data = sa[ikev2.IKEv2_payload_KE].load
2131 self.sa.complete_dh_data()
2132 self.sa.calc_child_keys(kex=self.WITH_KEX)
Filip Tehlar68ad6252020-10-30 05:28:11 +00002133
2134 def test_responder(self):
2135 super(TestResponderRekey, self).test_responder()
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002136 self.process_rekey_response(self.send_rekey_from_initiator())
Filip Tehlar68ad6252020-10-30 05:28:11 +00002137 self.verify_ike_sas()
2138 self.verify_ipsec_sas(is_rekey=True)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002139 self.assert_counter(1, "rekey_req", "ip4")
Filip Tehlar68d27532021-01-25 10:09:27 +00002140 r = self.vapi.ikev2_sa_dump()
2141 self.assertEqual(r[0].sa.stats.n_rekey_req, 1)
Filip Tehlar68ad6252020-10-30 05:28:11 +00002142
2143
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002144@tag_fixme_vpp_workers
2145class TestResponderRekeyRepeat(TestResponderRekey):
2146 """test ikev2 responder - rekey repeat"""
2147
2148 def test_responder(self):
2149 super(TestResponderRekeyRepeat, self).test_responder()
2150 # rekey request is not accepted until old IPsec SA is expired
2151 capture = self.send_rekey_from_initiator()
2152 ih = self.get_ike_header(capture[0])
2153 plain = self.sa.hmac_and_decrypt(ih)
2154 notify = ikev2.IKEv2_payload_Notify(plain)
2155 self.assertEqual(notify.type, 43)
2156 self.assertEqual(len(self.vapi.ipsec_sa_dump()), 3)
2157 # rekey request is accepted after old IPsec SA was expired
2158 for _ in range(50):
2159 if len(self.vapi.ipsec_sa_dump()) != 3:
2160 break
2161 time.sleep(0.2)
2162 else:
2163 self.fail("old IPsec SA not expired")
2164 self.process_rekey_response(self.send_rekey_from_initiator())
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002165 self.verify_ike_sas()
2166 self.verify_ipsec_sas(sa_count=3)
2167
2168
Atzm Watanabec65921f2022-08-12 14:29:31 +09002169@tag_fixme_vpp_workers
2170class TestResponderRekeyKEX(TestResponderRekey):
2171 """test ikev2 responder - rekey with key exchange"""
2172
2173 WITH_KEX = True
2174
2175
2176@tag_fixme_vpp_workers
2177class TestResponderRekeyRepeatKEX(TestResponderRekeyRepeat):
2178 """test ikev2 responder - rekey repeat with key exchange"""
2179
2180 WITH_KEX = True
2181
2182
Dave Wallace670724c2022-09-20 21:52:18 -04002183@tag_fixme_ubuntu2204
2184@tag_fixme_debian11
Filip Tehlard28196f2021-01-27 18:08:21 +00002185class TestResponderVrf(TestResponderPsk, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002186 """test ikev2 responder - non-default table id"""
Filip Tehlard28196f2021-01-27 18:08:21 +00002187
2188 @classmethod
2189 def setUpClass(cls):
2190 import scapy.contrib.ikev2 as _ikev2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002191
2192 globals()["ikev2"] = _ikev2
Filip Tehlard28196f2021-01-27 18:08:21 +00002193 super(IkePeer, cls).setUpClass()
Dave Wallace670724c2022-09-20 21:52:18 -04002194 if (is_distro_ubuntu2204 == True or is_distro_debian11 == True) and not hasattr(
2195 cls, "vpp"
2196 ):
2197 return
Filip Tehlard28196f2021-01-27 18:08:21 +00002198 cls.create_pg_interfaces(range(1))
2199 cls.vapi.cli("ip table add 1")
2200 cls.vapi.cli("set interface ip table pg0 1")
2201 for i in cls.pg_interfaces:
2202 i.admin_up()
2203 i.config_ip4()
2204 i.resolve_arp()
2205 i.config_ip6()
2206 i.resolve_ndp()
2207
2208 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002209 self.config_params({"dpd_disabled": False})
Filip Tehlard28196f2021-01-27 18:08:21 +00002210
2211 def test_responder(self):
2212 self.vapi.ikev2_profile_set_liveness(period=2, max_retries=1)
2213 super(TestResponderVrf, self).test_responder()
2214 self.pg0.enable_capture()
2215 self.pg_start()
2216 capture = self.pg0.get_capture(expected_count=1, timeout=5)
2217 ih = self.get_ike_header(capture[0])
2218 self.assertEqual(ih.exch_type, 37) # INFORMATIONAL
2219 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002220 self.assertEqual(plain, b"")
Filip Tehlard28196f2021-01-27 18:08:21 +00002221
2222
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002223@tag_fixme_vpp_workers
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002224class TestResponderRsaSign(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002225 """test ikev2 responder - cert based auth"""
2226
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002227 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002228 self.config_params(
2229 {
2230 "udp_encap": True,
2231 "auth": "rsa-sig",
2232 "server-key": "server-key.pem",
2233 "client-key": "client-key.pem",
2234 "client-cert": "client-cert.pem",
2235 "server-cert": "server-cert.pem",
2236 }
2237 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002238
Filip Tehlar4f42a712020-07-01 08:56:59 +00002239
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002240@tag_fixme_vpp_workers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002241class Test_IKE_AES_CBC_128_SHA256_128_MODP2048_ESP_AES_CBC_192_SHA_384_192(
2242 TemplateResponder, Ikev2Params
2243):
Filip Tehlar4f42a712020-07-01 08:56:59 +00002244 """
2245 IKE:AES_CBC_128_SHA256_128,DH=modp2048 ESP:AES_CBC_192_SHA_384_192
2246 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002247
Filip Tehlar4f42a712020-07-01 08:56:59 +00002248 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002249 self.config_params(
2250 {
2251 "ike-crypto": ("AES-CBC", 16),
2252 "ike-integ": "SHA2-256-128",
2253 "esp-crypto": ("AES-CBC", 24),
2254 "esp-integ": "SHA2-384-192",
2255 "ike-dh": "2048MODPgr",
2256 "nonce": os.urandom(256),
2257 "no_idr_in_auth": True,
2258 }
2259 )
Filip Tehlar4f42a712020-07-01 08:56:59 +00002260
2261
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002262@tag_fixme_vpp_workers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002263class TestAES_CBC_128_SHA256_128_MODP3072_ESP_AES_GCM_16(
2264 TemplateResponder, Ikev2Params
2265):
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002266
Filip Tehlar4f42a712020-07-01 08:56:59 +00002267 """
2268 IKE:AES_CBC_128_SHA256_128,DH=modp3072 ESP:AES_GCM_16
2269 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002270
Filip Tehlar4f42a712020-07-01 08:56:59 +00002271 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002272 self.config_params(
2273 {
2274 "ike-crypto": ("AES-CBC", 32),
2275 "ike-integ": "SHA2-256-128",
2276 "esp-crypto": ("AES-GCM-16ICV", 32),
2277 "esp-integ": "NULL",
2278 "ike-dh": "3072MODPgr",
2279 }
2280 )
Filip Tehlar4f42a712020-07-01 08:56:59 +00002281
2282
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002283@tag_fixme_vpp_workers
Filip Tehlara7b963d2020-07-08 13:25:34 +00002284class Test_IKE_AES_GCM_16_256(TemplateResponder, Ikev2Params):
2285 """
2286 IKE:AES_GCM_16_256
2287 """
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002288
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002289 IKE_NODE_SUFFIX = "ip6"
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002290
Filip Tehlara7b963d2020-07-08 13:25:34 +00002291 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002292 self.config_params(
2293 {
2294 "del_sa_from_responder": True,
2295 "ip6": True,
2296 "natt": True,
2297 "ike-crypto": ("AES-GCM-16ICV", 32),
2298 "ike-integ": "NULL",
2299 "ike-dh": "2048MODPgr",
2300 "loc_ts": {"start_addr": "ab:cd::0", "end_addr": "ab:cd::10"},
2301 "rem_ts": {"start_addr": "11::0", "end_addr": "11::100"},
2302 }
2303 )
Filip Tehlara7b963d2020-07-08 13:25:34 +00002304
2305
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002306@tag_fixme_vpp_workers
Filip Tehlar2008e312020-11-09 13:23:24 +00002307class TestInitiatorKeepaliveMsg(TestInitiatorPsk):
2308 """
2309 Test for keep alive messages
2310 """
2311
2312 def send_empty_req_from_responder(self):
Filip Tehlar38340fa2020-11-19 21:34:48 +00002313 packet = self.create_empty_request()
Filip Tehlar2008e312020-11-09 13:23:24 +00002314 self.pg0.add_stream(packet)
2315 self.pg0.enable_capture()
2316 self.pg_start()
2317 capture = self.pg0.get_capture(1)
2318 ih = self.get_ike_header(capture[0])
2319 self.assertEqual(ih.id, self.sa.msg_id)
2320 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002321 self.assertEqual(plain, b"")
2322 self.assert_counter(1, "keepalive", "ip4")
Filip Tehlar68d27532021-01-25 10:09:27 +00002323 r = self.vapi.ikev2_sa_dump()
2324 self.assertEqual(1, r[0].sa.stats.n_keepalives)
Filip Tehlar2008e312020-11-09 13:23:24 +00002325
2326 def test_initiator(self):
2327 super(TestInitiatorKeepaliveMsg, self).test_initiator()
2328 self.send_empty_req_from_responder()
2329
2330
Filip Tehlar558607d2020-07-16 07:25:56 +00002331class TestMalformedMessages(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002332 """malformed packet test"""
Filip Tehlar558607d2020-07-16 07:25:56 +00002333
2334 def tearDown(self):
2335 pass
2336
2337 def config_tc(self):
2338 self.config_params()
2339
Filip Tehlar558607d2020-07-16 07:25:56 +00002340 def create_ike_init_msg(self, length=None, payload=None):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002341 msg = ikev2.IKEv2(
2342 length=length,
2343 init_SPI="\x11" * 8,
2344 flags="Initiator",
2345 exch_type="IKE_SA_INIT",
2346 )
Filip Tehlar558607d2020-07-16 07:25:56 +00002347 if payload is not None:
2348 msg /= payload
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002349 return self.create_packet(self.pg0, msg, self.sa.sport, self.sa.dport)
Filip Tehlar558607d2020-07-16 07:25:56 +00002350
2351 def verify_bad_packet_length(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002352 ike_msg = self.create_ike_init_msg(length=0xDEAD)
Filip Tehlar558607d2020-07-16 07:25:56 +00002353 self.send_and_assert_no_replies(self.pg0, ike_msg * self.pkt_count)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002354 self.assert_counter(self.pkt_count, "bad_length")
Filip Tehlar558607d2020-07-16 07:25:56 +00002355
2356 def verify_bad_sa_payload_length(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002357 p = ikev2.IKEv2_payload_SA(length=0xDEAD)
Filip Tehlar558607d2020-07-16 07:25:56 +00002358 ike_msg = self.create_ike_init_msg(payload=p)
2359 self.send_and_assert_no_replies(self.pg0, ike_msg * self.pkt_count)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002360 self.assert_counter(self.pkt_count, "malformed_packet")
Filip Tehlar558607d2020-07-16 07:25:56 +00002361
2362 def test_responder(self):
2363 self.pkt_count = 254
2364 self.verify_bad_packet_length()
2365 self.verify_bad_sa_payload_length()
2366
2367
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002368if __name__ == "__main__":
Filip Tehlar12b517b2020-04-26 18:05:05 +00002369 unittest.main(testRunner=VppTestRunner)