blob: ea425e2e489aa193c4ee25ababd72437e7c62582 [file] [log] [blame]
Filip Tehlar12b517b2020-04-26 18:05:05 +00001import os
Tom Jones800386a2024-02-07 13:26:41 +00002import socket
Filip Tehlar2008e312020-11-09 13:23:24 +00003import time
Filip Tehlarec112e52020-10-07 23:52:37 +00004from socket import inet_pton
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00005from cryptography import x509
Filip Tehlar12b517b2020-04-26 18:05:05 +00006from cryptography.hazmat.backends import default_backend
7from cryptography.hazmat.primitives import hashes, hmac
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00008from cryptography.hazmat.primitives.asymmetric import dh, padding
9from cryptography.hazmat.primitives.serialization import load_pem_private_key
Filip Tehlar12b517b2020-04-26 18:05:05 +000010from cryptography.hazmat.primitives.ciphers import (
11 Cipher,
12 algorithms,
13 modes,
14)
Filip Tehlar84962d12020-09-08 06:08:05 +000015from ipaddress import IPv4Address, IPv6Address, ip_address
Paul Vinciguerrae061dad2020-12-04 14:57:51 -050016import unittest
Klement Sekerab23ffd72021-05-31 16:08:53 +020017from config import config
Filip Tehlarbfeae8c2020-06-23 20:35:58 +000018from scapy.layers.ipsec import ESP
Filip Tehlar12b517b2020-04-26 18:05:05 +000019from scapy.layers.inet import IP, UDP, Ether
Filip Tehlar84962d12020-09-08 06:08:05 +000020from scapy.layers.inet6 import IPv6
Filip Tehlar12b517b2020-04-26 18:05:05 +000021from scapy.packet import raw, Raw
22from scapy.utils import long_converter
Dave Wallace8800f732023-08-31 00:47:44 -040023from framework import VppTestCase
24from asfframework import (
25 tag_fixme_vpp_workers,
26 tag_fixme_ubuntu2204,
27 tag_fixme_debian11,
28 is_distro_ubuntu2204,
29 is_distro_debian11,
30 VppTestRunner,
31)
Filip Tehlarbfeae8c2020-06-23 20:35:58 +000032from vpp_ikev2 import Profile, IDType, AuthMethod
Filip Tehlar4f42a712020-07-01 08:56:59 +000033from vpp_papi import VppEnum
Filip Tehlar12b517b2020-04-26 18:05:05 +000034
Filip Tehlar84962d12020-09-08 06:08:05 +000035try:
36 text_type = unicode
37except NameError:
38 text_type = str
Filip Tehlar12b517b2020-04-26 18:05:05 +000039
40KEY_PAD = b"Key Pad for IKEv2"
Filip Tehlara7b963d2020-07-08 13:25:34 +000041SALT_SIZE = 4
42GCM_ICV_SIZE = 16
43GCM_IV_SIZE = 8
Filip Tehlar12b517b2020-04-26 18:05:05 +000044
45
46# defined in rfc3526
47# tuple structure is (p, g, key_len)
48DH = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020049 "2048MODPgr": (
50 long_converter(
51 """
Filip Tehlar12b517b2020-04-26 18:05:05 +000052 FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
53 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
54 EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
55 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
56 EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
57 C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
58 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
59 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
60 E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
61 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020062 15728E5A 8AACAA68 FFFFFFFF FFFFFFFF"""
63 ),
64 2,
65 256,
66 ),
67 "3072MODPgr": (
68 long_converter(
69 """
Filip Tehlar4f42a712020-07-01 08:56:59 +000070 FFFFFFFF FFFFFFFF C90FDAA2 2168C234 C4C6628B 80DC1CD1
71 29024E08 8A67CC74 020BBEA6 3B139B22 514A0879 8E3404DD
72 EF9519B3 CD3A431B 302B0A6D F25F1437 4FE1356D 6D51C245
73 E485B576 625E7EC6 F44C42E9 A637ED6B 0BFF5CB6 F406B7ED
74 EE386BFB 5A899FA5 AE9F2411 7C4B1FE6 49286651 ECE45B3D
75 C2007CB8 A163BF05 98DA4836 1C55D39A 69163FA8 FD24CF5F
76 83655D23 DCA3AD96 1C62F356 208552BB 9ED52907 7096966D
77 670C354E 4ABC9804 F1746C08 CA18217C 32905E46 2E36CE3B
78 E39E772C 180E8603 9B2783A2 EC07A28F B5C55DF0 6F4C52C9
79 DE2BCBF6 95581718 3995497C EA956AE5 15D22618 98FA0510
80 15728E5A 8AAAC42D AD33170D 04507A33 A85521AB DF1CBA64
81 ECFB8504 58DBEF0A 8AEA7157 5D060C7D B3970F85 A6E1E4C7
82 ABF5AE8C DB0933D7 1E8C94E0 4A25619D CEE3D226 1AD2EE6B
83 F12FFA06 D98A0864 D8760273 3EC86A64 521F2B18 177B200C
84 BBE11757 7A615D6C 770988C0 BAD946E2 08E24FA0 74E5AB31
Klement Sekerad9b0c6f2022-04-26 19:02:15 +020085 43DB5BFC E0FD108E 4B82D120 A93AD2CA FFFFFFFF FFFFFFFF"""
86 ),
87 2,
88 384,
89 ),
Filip Tehlar12b517b2020-04-26 18:05:05 +000090}
91
92
93class CryptoAlgo(object):
94 def __init__(self, name, cipher, mode):
95 self.name = name
96 self.cipher = cipher
97 self.mode = mode
98 if self.cipher is not None:
99 self.bs = self.cipher.block_size // 8
100
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200101 if self.name == "AES-GCM-16ICV":
Filip Tehlara7b963d2020-07-08 13:25:34 +0000102 self.iv_len = GCM_IV_SIZE
103 else:
104 self.iv_len = self.bs
Filip Tehlar12b517b2020-04-26 18:05:05 +0000105
Filip Tehlara7b963d2020-07-08 13:25:34 +0000106 def encrypt(self, data, key, aad=None):
107 iv = os.urandom(self.iv_len)
108 if aad is None:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200109 encryptor = Cipher(
110 self.cipher(key), self.mode(iv), default_backend()
111 ).encryptor()
Filip Tehlara7b963d2020-07-08 13:25:34 +0000112 return iv + encryptor.update(data) + encryptor.finalize()
113 else:
114 salt = key[-SALT_SIZE:]
115 nonce = salt + iv
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200116 encryptor = Cipher(
117 self.cipher(key[:-SALT_SIZE]), self.mode(nonce), default_backend()
118 ).encryptor()
Filip Tehlara7b963d2020-07-08 13:25:34 +0000119 encryptor.authenticate_additional_data(aad)
120 data = encryptor.update(data) + encryptor.finalize()
121 data += encryptor.tag[:GCM_ICV_SIZE]
122 return iv + data
123
124 def decrypt(self, data, key, aad=None, icv=None):
125 if aad is None:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200126 iv = data[: self.iv_len]
127 ct = data[self.iv_len :]
128 decryptor = Cipher(
129 algorithms.AES(key), self.mode(iv), default_backend()
130 ).decryptor()
Filip Tehlara7b963d2020-07-08 13:25:34 +0000131 return decryptor.update(ct) + decryptor.finalize()
132 else:
133 salt = key[-SALT_SIZE:]
134 nonce = salt + data[:GCM_IV_SIZE]
135 ct = data[GCM_IV_SIZE:]
136 key = key[:-SALT_SIZE]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200137 decryptor = Cipher(
138 algorithms.AES(key), self.mode(nonce, icv, len(icv)), default_backend()
139 ).decryptor()
Filip Tehlara7b963d2020-07-08 13:25:34 +0000140 decryptor.authenticate_additional_data(aad)
Filip Tehlaredf29002020-10-10 04:39:11 +0000141 return decryptor.update(ct) + decryptor.finalize()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000142
143 def pad(self, data):
144 pad_len = (len(data) // self.bs + 1) * self.bs - len(data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200145 data = data + b"\x00" * (pad_len - 1)
Filip Tehlar558607d2020-07-16 07:25:56 +0000146 return data + bytes([pad_len - 1])
Filip Tehlar12b517b2020-04-26 18:05:05 +0000147
148
149class AuthAlgo(object):
150 def __init__(self, name, mac, mod, key_len, trunc_len=None):
151 self.name = name
152 self.mac = mac
153 self.mod = mod
154 self.key_len = key_len
155 self.trunc_len = trunc_len or key_len
156
157
158CRYPTO_ALGOS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200159 "NULL": CryptoAlgo("NULL", cipher=None, mode=None),
160 "AES-CBC": CryptoAlgo("AES-CBC", cipher=algorithms.AES, mode=modes.CBC),
161 "AES-GCM-16ICV": CryptoAlgo("AES-GCM-16ICV", cipher=algorithms.AES, mode=modes.GCM),
Filip Tehlar12b517b2020-04-26 18:05:05 +0000162}
163
164AUTH_ALGOS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200165 "NULL": AuthAlgo("NULL", mac=None, mod=None, key_len=0, trunc_len=0),
166 "HMAC-SHA1-96": AuthAlgo("HMAC-SHA1-96", hmac.HMAC, hashes.SHA1, 20, 12),
167 "SHA2-256-128": AuthAlgo("SHA2-256-128", hmac.HMAC, hashes.SHA256, 32, 16),
168 "SHA2-384-192": AuthAlgo("SHA2-384-192", hmac.HMAC, hashes.SHA256, 48, 24),
169 "SHA2-512-256": AuthAlgo("SHA2-512-256", hmac.HMAC, hashes.SHA256, 64, 32),
Filip Tehlar12b517b2020-04-26 18:05:05 +0000170}
171
172PRF_ALGOS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200173 "NULL": AuthAlgo("NULL", mac=None, mod=None, key_len=0, trunc_len=0),
174 "PRF_HMAC_SHA2_256": AuthAlgo("PRF_HMAC_SHA2_256", hmac.HMAC, hashes.SHA256, 32),
Filip Tehlar12b517b2020-04-26 18:05:05 +0000175}
176
Filip Tehlar68ad6252020-10-30 05:28:11 +0000177CRYPTO_IDS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200178 12: "AES-CBC",
179 20: "AES-GCM-16ICV",
Filip Tehlar68ad6252020-10-30 05:28:11 +0000180}
181
182INTEG_IDS = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200183 2: "HMAC-SHA1-96",
184 12: "SHA2-256-128",
185 13: "SHA2-384-192",
186 14: "SHA2-512-256",
Filip Tehlar68ad6252020-10-30 05:28:11 +0000187}
188
Filip Tehlar12b517b2020-04-26 18:05:05 +0000189
190class IKEv2ChildSA(object):
Filip Tehlar68ad6252020-10-30 05:28:11 +0000191 def __init__(self, local_ts, remote_ts, is_initiator):
192 spi = os.urandom(4)
193 if is_initiator:
194 self.ispi = spi
195 self.rspi = None
196 else:
197 self.rspi = spi
198 self.ispi = None
Filip Tehlar12b517b2020-04-26 18:05:05 +0000199 self.local_ts = local_ts
200 self.remote_ts = remote_ts
201
202
203class IKEv2SA(object):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200204 def __init__(
205 self,
206 test,
207 is_initiator=True,
208 i_id=None,
209 r_id=None,
210 spi=b"\x01\x02\x03\x04\x05\x06\x07\x08",
211 id_type="fqdn",
212 nonce=None,
213 auth_data=None,
214 local_ts=None,
215 remote_ts=None,
216 auth_method="shared-key",
217 priv_key=None,
218 i_natt=False,
219 r_natt=False,
220 udp_encap=False,
221 ):
Filip Tehlar67b8a7f2020-11-06 11:00:42 +0000222 self.udp_encap = udp_encap
Filip Tehlar027d8132020-12-04 17:38:11 +0000223 self.i_natt = i_natt
224 self.r_natt = r_natt
225 if i_natt or r_natt:
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000226 self.sport = 4500
227 self.dport = 4500
228 else:
229 self.sport = 500
230 self.dport = 500
Filip Tehlar558607d2020-07-16 07:25:56 +0000231 self.msg_id = 0
Filip Tehlar12b517b2020-04-26 18:05:05 +0000232 self.dh_params = None
233 self.test = test
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000234 self.priv_key = priv_key
Filip Tehlar12b517b2020-04-26 18:05:05 +0000235 self.is_initiator = is_initiator
236 nonce = nonce or os.urandom(32)
237 self.auth_data = auth_data
Filip Tehlar4128c7b2020-05-10 05:18:37 +0000238 self.i_id = i_id
239 self.r_id = r_id
Filip Tehlar12b517b2020-04-26 18:05:05 +0000240 if isinstance(id_type, str):
241 self.id_type = IDType.value(id_type)
242 else:
243 self.id_type = id_type
244 self.auth_method = auth_method
245 if self.is_initiator:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200246 self.rspi = 8 * b"\x00"
Filip Tehlar12b517b2020-04-26 18:05:05 +0000247 self.ispi = spi
Filip Tehlar12b517b2020-04-26 18:05:05 +0000248 self.i_nonce = nonce
249 else:
250 self.rspi = spi
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200251 self.ispi = 8 * b"\x00"
Filip Tehlare7c83962020-09-23 11:20:12 +0000252 self.r_nonce = nonce
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200253 self.child_sas = [IKEv2ChildSA(local_ts, remote_ts, self.is_initiator)]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000254
Filip Tehlar558607d2020-07-16 07:25:56 +0000255 def new_msg_id(self):
256 self.msg_id += 1
257 return self.msg_id
258
Filip Tehlare7c83962020-09-23 11:20:12 +0000259 @property
260 def my_dh_pub_key(self):
261 if self.is_initiator:
262 return self.i_dh_data
263 return self.r_dh_data
264
265 @property
266 def peer_dh_pub_key(self):
267 if self.is_initiator:
268 return self.r_dh_data
Filip Tehlar12b517b2020-04-26 18:05:05 +0000269 return self.i_dh_data
270
Filip Tehlar027d8132020-12-04 17:38:11 +0000271 @property
272 def natt(self):
273 return self.i_natt or self.r_natt
274
Filip Tehlar12b517b2020-04-26 18:05:05 +0000275 def compute_secret(self):
276 priv = self.dh_private_key
Filip Tehlare7c83962020-09-23 11:20:12 +0000277 peer = self.peer_dh_pub_key
Filip Tehlar12b517b2020-04-26 18:05:05 +0000278 p, g, l = self.ike_group
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200279 return pow(
280 int.from_bytes(peer, "big"), int.from_bytes(priv, "big"), p
281 ).to_bytes(l, "big")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000282
283 def generate_dh_data(self):
284 # generate DH keys
Filip Tehlare7c83962020-09-23 11:20:12 +0000285 if self.ike_dh not in DH:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200286 raise NotImplementedError("%s not in DH group" % self.ike_dh)
Filip Tehlare7c83962020-09-23 11:20:12 +0000287
288 if self.dh_params is None:
289 dhg = DH[self.ike_dh]
290 pn = dh.DHParameterNumbers(dhg[0], dhg[1])
291 self.dh_params = pn.parameters(default_backend())
292
293 priv = self.dh_params.generate_private_key()
294 pub = priv.public_key()
295 x = priv.private_numbers().x
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200296 self.dh_private_key = x.to_bytes(priv.key_size // 8, "big")
Filip Tehlare7c83962020-09-23 11:20:12 +0000297 y = pub.public_numbers().y
298
Filip Tehlar12b517b2020-04-26 18:05:05 +0000299 if self.is_initiator:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200300 self.i_dh_data = y.to_bytes(pub.key_size // 8, "big")
Filip Tehlare7c83962020-09-23 11:20:12 +0000301 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200302 self.r_dh_data = y.to_bytes(pub.key_size // 8, "big")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000303
304 def complete_dh_data(self):
305 self.dh_shared_secret = self.compute_secret()
306
Atzm Watanabec65921f2022-08-12 14:29:31 +0900307 def calc_child_keys(self, kex=False):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000308 prf = self.ike_prf_alg.mod()
309 s = self.i_nonce + self.r_nonce
Atzm Watanabec65921f2022-08-12 14:29:31 +0900310 if kex:
311 s = self.dh_shared_secret + s
Filip Tehlar12b517b2020-04-26 18:05:05 +0000312 c = self.child_sas[0]
313
314 encr_key_len = self.esp_crypto_key_len
Filip Tehlar4f42a712020-07-01 08:56:59 +0000315 integ_key_len = self.esp_integ_alg.key_len
316 salt_len = 0 if integ_key_len else 4
317
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200318 l = integ_key_len * 2 + encr_key_len * 2 + salt_len * 2
Filip Tehlar12b517b2020-04-26 18:05:05 +0000319 keymat = self.calc_prfplus(prf, self.sk_d, s, l)
320
321 pos = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200322 c.sk_ei = keymat[pos : pos + encr_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000323 pos += encr_key_len
324
Filip Tehlar4f42a712020-07-01 08:56:59 +0000325 if integ_key_len:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200326 c.sk_ai = keymat[pos : pos + integ_key_len]
Filip Tehlar4f42a712020-07-01 08:56:59 +0000327 pos += integ_key_len
328 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200329 c.salt_ei = keymat[pos : pos + salt_len]
Filip Tehlar4f42a712020-07-01 08:56:59 +0000330 pos += salt_len
Filip Tehlar12b517b2020-04-26 18:05:05 +0000331
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200332 c.sk_er = keymat[pos : pos + encr_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000333 pos += encr_key_len
334
Filip Tehlar4f42a712020-07-01 08:56:59 +0000335 if integ_key_len:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200336 c.sk_ar = keymat[pos : pos + integ_key_len]
Filip Tehlar4f42a712020-07-01 08:56:59 +0000337 pos += integ_key_len
338 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200339 c.salt_er = keymat[pos : pos + salt_len]
Filip Tehlar4f42a712020-07-01 08:56:59 +0000340 pos += salt_len
Filip Tehlar12b517b2020-04-26 18:05:05 +0000341
342 def calc_prfplus(self, prf, key, seed, length):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200343 r = b""
Filip Tehlar12b517b2020-04-26 18:05:05 +0000344 t = None
345 x = 1
346 while len(r) < length and x < 255:
347 if t is not None:
348 s = t
349 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200350 s = b""
Filip Tehlar12b517b2020-04-26 18:05:05 +0000351 s = s + seed + bytes([x])
352 t = self.calc_prf(prf, key, s)
353 r = r + t
354 x = x + 1
355
356 if x == 255:
357 return None
358 return r
359
360 def calc_prf(self, prf, key, data):
Filip Tehlara7b963d2020-07-08 13:25:34 +0000361 h = self.ike_prf_alg.mac(key, prf, backend=default_backend())
Filip Tehlar12b517b2020-04-26 18:05:05 +0000362 h.update(data)
363 return h.finalize()
364
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900365 def calc_keys(self, sk_d=None):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000366 prf = self.ike_prf_alg.mod()
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900367 if sk_d is None:
368 # SKEYSEED = prf(Ni | Nr, g^ir)
369 self.skeyseed = self.calc_prf(
370 prf, self.i_nonce + self.r_nonce, self.dh_shared_secret
371 )
372 else:
373 # SKEYSEED = prf(SK_d (old), g^ir (new) | Ni | Nr)
374 self.skeyseed = self.calc_prf(
375 prf, sk_d, self.dh_shared_secret + self.i_nonce + self.r_nonce
376 )
Filip Tehlar12b517b2020-04-26 18:05:05 +0000377
378 # calculate S = Ni | Nr | SPIi SPIr
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900379 s = self.i_nonce + self.r_nonce + self.ispi + self.rspi
Filip Tehlar12b517b2020-04-26 18:05:05 +0000380
381 prf_key_trunc = self.ike_prf_alg.trunc_len
382 encr_key_len = self.ike_crypto_key_len
383 tr_prf_key_len = self.ike_prf_alg.key_len
384 integ_key_len = self.ike_integ_alg.key_len
Filip Tehlara7b963d2020-07-08 13:25:34 +0000385 if integ_key_len == 0:
386 salt_size = 4
387 else:
388 salt_size = 0
389
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200390 l = (
391 prf_key_trunc
392 + integ_key_len * 2
393 + encr_key_len * 2
394 + tr_prf_key_len * 2
395 + salt_size * 2
396 )
Filip Tehlar12b517b2020-04-26 18:05:05 +0000397 keymat = self.calc_prfplus(prf, self.skeyseed, s, l)
398
399 pos = 0
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200400 self.sk_d = keymat[: pos + prf_key_trunc]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000401 pos += prf_key_trunc
402
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200403 self.sk_ai = keymat[pos : pos + integ_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000404 pos += integ_key_len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200405 self.sk_ar = keymat[pos : pos + integ_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000406 pos += integ_key_len
407
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200408 self.sk_ei = keymat[pos : pos + encr_key_len + salt_size]
Filip Tehlara7b963d2020-07-08 13:25:34 +0000409 pos += encr_key_len + salt_size
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200410 self.sk_er = keymat[pos : pos + encr_key_len + salt_size]
Filip Tehlara7b963d2020-07-08 13:25:34 +0000411 pos += encr_key_len + salt_size
Filip Tehlar12b517b2020-04-26 18:05:05 +0000412
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200413 self.sk_pi = keymat[pos : pos + tr_prf_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000414 pos += tr_prf_key_len
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200415 self.sk_pr = keymat[pos : pos + tr_prf_key_len]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000416
417 def generate_authmsg(self, prf, packet):
418 if self.is_initiator:
419 id = self.i_id
420 nonce = self.r_nonce
421 key = self.sk_pi
Filip Tehlare7c83962020-09-23 11:20:12 +0000422 else:
423 id = self.r_id
424 nonce = self.i_nonce
425 key = self.sk_pr
Filip Tehlar12b517b2020-04-26 18:05:05 +0000426 data = bytes([self.id_type, 0, 0, 0]) + id
427 id_hash = self.calc_prf(prf, key, data)
428 return packet + nonce + id_hash
429
430 def auth_init(self):
431 prf = self.ike_prf_alg.mod()
Filip Tehlare7c83962020-09-23 11:20:12 +0000432 if self.is_initiator:
433 packet = self.init_req_packet
434 else:
435 packet = self.init_resp_packet
436 authmsg = self.generate_authmsg(prf, raw(packet))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200437 if self.auth_method == "shared-key":
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000438 psk = self.calc_prf(prf, self.auth_data, KEY_PAD)
439 self.auth_data = self.calc_prf(prf, psk, authmsg)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200440 elif self.auth_method == "rsa-sig":
441 self.auth_data = self.priv_key.sign(
442 authmsg, padding.PKCS1v15(), hashes.SHA1()
443 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000444 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200445 raise TypeError("unknown auth method type!")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000446
Filip Tehlara7b963d2020-07-08 13:25:34 +0000447 def encrypt(self, data, aad=None):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000448 data = self.ike_crypto_alg.pad(data)
Filip Tehlara7b963d2020-07-08 13:25:34 +0000449 return self.ike_crypto_alg.encrypt(data, self.my_cryptokey, aad)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000450
451 @property
452 def peer_authkey(self):
453 if self.is_initiator:
454 return self.sk_ar
455 return self.sk_ai
456
457 @property
458 def my_authkey(self):
459 if self.is_initiator:
460 return self.sk_ai
461 return self.sk_ar
462
463 @property
464 def my_cryptokey(self):
465 if self.is_initiator:
466 return self.sk_ei
467 return self.sk_er
468
469 @property
470 def peer_cryptokey(self):
471 if self.is_initiator:
472 return self.sk_er
473 return self.sk_ei
474
Filip Tehlar4f42a712020-07-01 08:56:59 +0000475 def concat(self, alg, key_len):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200476 return alg + "-" + str(key_len * 8)
Filip Tehlar4f42a712020-07-01 08:56:59 +0000477
478 @property
479 def vpp_ike_cypto_alg(self):
480 return self.concat(self.ike_crypto, self.ike_crypto_key_len)
481
482 @property
483 def vpp_esp_cypto_alg(self):
484 return self.concat(self.esp_crypto, self.esp_crypto_key_len)
485
Filip Tehlar12b517b2020-04-26 18:05:05 +0000486 def verify_hmac(self, ikemsg):
487 integ_trunc = self.ike_integ_alg.trunc_len
488 exp_hmac = ikemsg[-integ_trunc:]
489 data = ikemsg[:-integ_trunc]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200490 computed_hmac = self.compute_hmac(
491 self.ike_integ_alg.mod(), self.peer_authkey, data
492 )
Filip Tehlar12b517b2020-04-26 18:05:05 +0000493 self.test.assertEqual(computed_hmac[:integ_trunc], exp_hmac)
494
495 def compute_hmac(self, integ, key, data):
496 h = self.ike_integ_alg.mac(key, integ, backend=default_backend())
497 h.update(data)
498 return h.finalize()
499
Filip Tehlara7b963d2020-07-08 13:25:34 +0000500 def decrypt(self, data, aad=None, icv=None):
501 return self.ike_crypto_alg.decrypt(data, self.peer_cryptokey, aad, icv)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000502
503 def hmac_and_decrypt(self, ike):
504 ep = ike[ikev2.IKEv2_payload_Encrypted]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200505 if self.ike_crypto == "AES-GCM-16ICV":
Filip Tehlara7b963d2020-07-08 13:25:34 +0000506 aad_len = len(ikev2.IKEv2_payload_Encrypted()) + len(ikev2.IKEv2())
507 ct = ep.load[:-GCM_ICV_SIZE]
508 tag = ep.load[-GCM_ICV_SIZE:]
Filip Tehlaredf29002020-10-10 04:39:11 +0000509 plain = self.decrypt(ct, raw(ike)[:aad_len], tag)
Filip Tehlara7b963d2020-07-08 13:25:34 +0000510 else:
511 self.verify_hmac(raw(ike))
512 integ_trunc = self.ike_integ_alg.trunc_len
Filip Tehlar12b517b2020-04-26 18:05:05 +0000513
Filip Tehlara7b963d2020-07-08 13:25:34 +0000514 # remove ICV and decrypt payload
515 ct = ep.load[:-integ_trunc]
Filip Tehlaredf29002020-10-10 04:39:11 +0000516 plain = self.decrypt(ct)
517 # remove padding
518 pad_len = plain[-1]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200519 return plain[: -pad_len - 1]
Filip Tehlar12b517b2020-04-26 18:05:05 +0000520
Filip Tehlar84962d12020-09-08 06:08:05 +0000521 def build_ts_addr(self, ts, version):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200522 return {
523 "starting_address_v" + version: ts["start_addr"],
524 "ending_address_v" + version: ts["end_addr"],
525 }
Filip Tehlar84962d12020-09-08 06:08:05 +0000526
527 def generate_ts(self, is_ip4):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000528 c = self.child_sas[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200529 ts_data = {"IP_protocol_ID": 0, "start_port": 0, "end_port": 0xFFFF}
Filip Tehlar84962d12020-09-08 06:08:05 +0000530 if is_ip4:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200531 ts_data.update(self.build_ts_addr(c.local_ts, "4"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000532 ts1 = ikev2.IPv4TrafficSelector(**ts_data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200533 ts_data.update(self.build_ts_addr(c.remote_ts, "4"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000534 ts2 = ikev2.IPv4TrafficSelector(**ts_data)
535 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200536 ts_data.update(self.build_ts_addr(c.local_ts, "6"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000537 ts1 = ikev2.IPv6TrafficSelector(**ts_data)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200538 ts_data.update(self.build_ts_addr(c.remote_ts, "6"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000539 ts2 = ikev2.IPv6TrafficSelector(**ts_data)
Filip Tehlare7c83962020-09-23 11:20:12 +0000540
541 if self.is_initiator:
542 return ([ts1], [ts2])
543 return ([ts2], [ts1])
Filip Tehlar12b517b2020-04-26 18:05:05 +0000544
545 def set_ike_props(self, crypto, crypto_key_len, integ, prf, dh):
546 if crypto not in CRYPTO_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200547 raise TypeError("unsupported encryption algo %r" % crypto)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000548 self.ike_crypto = crypto
549 self.ike_crypto_alg = CRYPTO_ALGOS[crypto]
550 self.ike_crypto_key_len = crypto_key_len
551
552 if integ not in AUTH_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200553 raise TypeError("unsupported auth algo %r" % integ)
554 self.ike_integ = None if integ == "NULL" else integ
Filip Tehlar12b517b2020-04-26 18:05:05 +0000555 self.ike_integ_alg = AUTH_ALGOS[integ]
556
557 if prf not in PRF_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200558 raise TypeError("unsupported prf algo %r" % prf)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000559 self.ike_prf = prf
560 self.ike_prf_alg = PRF_ALGOS[prf]
561 self.ike_dh = dh
562 self.ike_group = DH[self.ike_dh]
563
564 def set_esp_props(self, crypto, crypto_key_len, integ):
565 self.esp_crypto_key_len = crypto_key_len
566 if crypto not in CRYPTO_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200567 raise TypeError("unsupported encryption algo %r" % crypto)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000568 self.esp_crypto = crypto
569 self.esp_crypto_alg = CRYPTO_ALGOS[crypto]
570
571 if integ not in AUTH_ALGOS:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200572 raise TypeError("unsupported auth algo %r" % integ)
573 self.esp_integ = None if integ == "NULL" else integ
Filip Tehlar12b517b2020-04-26 18:05:05 +0000574 self.esp_integ_alg = AUTH_ALGOS[integ]
575
576 def crypto_attr(self, key_len):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200577 if self.ike_crypto in ["AES-CBC", "AES-GCM-16ICV"]:
578 return (0x800E << 16 | key_len << 3, 12)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000579 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200580 raise Exception("unsupported attribute type")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000581
582 def ike_crypto_attr(self):
583 return self.crypto_attr(self.ike_crypto_key_len)
584
585 def esp_crypto_attr(self):
586 return self.crypto_attr(self.esp_crypto_key_len)
587
Filip Tehlarec112e52020-10-07 23:52:37 +0000588 def compute_nat_sha1(self, ip, port, rspi=None):
589 if rspi is None:
590 rspi = self.rspi
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200591 data = self.ispi + rspi + ip + (port).to_bytes(2, "big")
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000592 digest = hashes.Hash(hashes.SHA1(), backend=default_backend())
593 digest.update(data)
594 return digest.finalize()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000595
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900596 def clone(self, test, **kwargs):
597 if "spi" not in kwargs:
598 kwargs["spi"] = self.ispi if self.is_initiator else self.rspi
599 if "nonce" not in kwargs:
600 kwargs["nonce"] = self.i_nonce if self.is_initiator else self.r_nonce
601 if self.child_sas:
602 if "local_ts" not in kwargs:
603 kwargs["local_ts"] = self.child_sas[0].local_ts
604 if "remote_ts" not in kwargs:
605 kwargs["remote_ts"] = self.child_sas[0].remote_ts
606 sa = type(self)(
607 test,
608 is_initiator=self.is_initiator,
609 i_id=self.i_id,
610 r_id=self.r_id,
611 id_type=self.id_type,
612 auth_data=self.auth_data,
613 auth_method=self.auth_method,
614 priv_key=self.priv_key,
615 i_natt=self.i_natt,
616 r_natt=self.r_natt,
617 udp_encap=self.udp_encap,
618 **kwargs,
619 )
620 if sa.is_initiator:
621 sa.set_ike_props(
622 crypto=self.ike_crypto,
623 crypto_key_len=self.ike_crypto_key_len,
624 integ=self.ike_integ,
625 prf=self.ike_prf,
626 dh=self.ike_dh,
627 )
628 sa.set_esp_props(
629 crypto=self.esp_crypto,
630 crypto_key_len=self.esp_crypto_key_len,
631 integ=self.esp_integ,
632 )
633 return sa
634
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000635
Andrew Yourtchenkobc378782023-09-26 16:01:21 +0200636@unittest.skipIf("ikev2" in config.excluded_plugins, "Exclude IKEv2 plugin tests")
Filip Tehlare7c83962020-09-23 11:20:12 +0000637class IkePeer(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200638 """common class for initiator and responder"""
Filip Tehlar12b517b2020-04-26 18:05:05 +0000639
640 @classmethod
641 def setUpClass(cls):
642 import scapy.contrib.ikev2 as _ikev2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200643
644 globals()["ikev2"] = _ikev2
Filip Tehlare7c83962020-09-23 11:20:12 +0000645 super(IkePeer, cls).setUpClass()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000646 cls.create_pg_interfaces(range(2))
647 for i in cls.pg_interfaces:
648 i.admin_up()
649 i.config_ip4()
650 i.resolve_arp()
Filip Tehlar84962d12020-09-08 06:08:05 +0000651 i.config_ip6()
652 i.resolve_ndp()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000653
654 @classmethod
655 def tearDownClass(cls):
Filip Tehlare7c83962020-09-23 11:20:12 +0000656 super(IkePeer, cls).tearDownClass()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000657
Filip Tehlaredf29002020-10-10 04:39:11 +0000658 def tearDown(self):
659 super(IkePeer, self).tearDown()
660 if self.del_sa_from_responder:
661 self.initiate_del_sa_from_responder()
662 else:
663 self.initiate_del_sa_from_initiator()
664 r = self.vapi.ikev2_sa_dump()
665 self.assertEqual(len(r), 0)
Denys Haryachyyf40a3542024-01-24 16:31:47 +0200666 r = self.vapi.ikev2_sa_v2_dump()
667 self.assertEqual(len(r), 0)
Filip Tehlaredf29002020-10-10 04:39:11 +0000668 sas = self.vapi.ipsec_sa_dump()
669 self.assertEqual(len(sas), 0)
670 self.p.remove_vpp_config()
671 self.assertIsNone(self.p.query_vpp_config())
672
Filip Tehlar12b517b2020-04-26 18:05:05 +0000673 def setUp(self):
Filip Tehlare7c83962020-09-23 11:20:12 +0000674 super(IkePeer, self).setUp()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000675 self.config_tc()
Filip Tehlar12b517b2020-04-26 18:05:05 +0000676 self.p.add_vpp_config()
Filip Tehlar459d17b2020-07-06 15:40:08 +0000677 self.assertIsNotNone(self.p.query_vpp_config())
Filip Tehlar68ad6252020-10-30 05:28:11 +0000678 if self.sa.is_initiator:
679 self.sa.generate_dh_data()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200680 self.vapi.cli("ikev2 set logging level 4")
681 self.vapi.cli("event-lo clear")
Filip Tehlar12b517b2020-04-26 18:05:05 +0000682
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200683 def assert_counter(self, count, name, version="ip4"):
684 node_name = "/err/ikev2-%s/" % version + name
Filip Tehlarfab5e7f2021-01-14 13:32:01 +0000685 self.assertEqual(count, self.statistics.get_err_counter(node_name))
686
Atzm Watanabec65921f2022-08-12 14:29:31 +0900687 def create_rekey_request(self, kex=False):
688 sa, first_payload = self.generate_auth_payload(is_rekey=True, kex=kex)
Filip Tehlar38340fa2020-11-19 21:34:48 +0000689 header = ikev2.IKEv2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200690 init_SPI=self.sa.ispi,
691 resp_SPI=self.sa.rspi,
692 id=self.sa.new_msg_id(),
693 flags="Initiator",
694 exch_type="CREATE_CHILD_SA",
695 )
Filip Tehlar38340fa2020-11-19 21:34:48 +0000696
697 ike_msg = self.encrypt_ike_msg(header, sa, first_payload)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200698 return self.create_packet(
699 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
700 )
Filip Tehlar38340fa2020-11-19 21:34:48 +0000701
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900702 def create_sa_rekey_request(self, **kwargs):
703 sa = self.generate_sa_init_payload(**kwargs)
704 header = ikev2.IKEv2(
705 init_SPI=self.sa.ispi,
706 resp_SPI=self.sa.rspi,
707 id=self.sa.new_msg_id(),
708 flags="Initiator",
709 exch_type="CREATE_CHILD_SA",
710 )
711 ike_msg = self.encrypt_ike_msg(header, sa, "SA")
712 return self.create_packet(
713 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
714 )
715
Filip Tehlar38340fa2020-11-19 21:34:48 +0000716 def create_empty_request(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200717 header = ikev2.IKEv2(
718 init_SPI=self.sa.ispi,
719 resp_SPI=self.sa.rspi,
720 id=self.sa.new_msg_id(),
721 flags="Initiator",
722 exch_type="INFORMATIONAL",
723 next_payload="Encrypted",
724 )
Filip Tehlar38340fa2020-11-19 21:34:48 +0000725
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200726 msg = self.encrypt_ike_msg(header, b"", None)
727 return self.create_packet(
728 self.pg0, msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
729 )
Filip Tehlar38340fa2020-11-19 21:34:48 +0000730
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200731 def create_packet(
732 self, src_if, msg, sport=500, dport=500, natt=False, use_ip6=False
733 ):
Filip Tehlar84962d12020-09-08 06:08:05 +0000734 if use_ip6:
735 src_ip = src_if.remote_ip6
736 dst_ip = src_if.local_ip6
737 ip_layer = IPv6
738 else:
739 src_ip = src_if.remote_ip4
740 dst_ip = src_if.local_ip4
741 ip_layer = IP
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200742 res = (
743 Ether(dst=src_if.local_mac, src=src_if.remote_mac)
744 / ip_layer(src=src_ip, dst=dst_ip)
745 / UDP(sport=sport, dport=dport)
746 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000747 if natt:
748 # insert non ESP marker
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200749 res = res / Raw(b"\x00" * 4)
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000750 return res / msg
Filip Tehlar12b517b2020-04-26 18:05:05 +0000751
Filip Tehlare7c83962020-09-23 11:20:12 +0000752 def verify_udp(self, udp):
753 self.assertEqual(udp.sport, self.sa.sport)
754 self.assertEqual(udp.dport, self.sa.dport)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000755
Filip Tehlare7c83962020-09-23 11:20:12 +0000756 def get_ike_header(self, packet):
757 try:
758 ih = packet[ikev2.IKEv2]
Filip Tehlar18107c92020-12-01 14:51:09 +0000759 ih = self.verify_and_remove_non_esp_marker(ih)
Filip Tehlare7c83962020-09-23 11:20:12 +0000760 except IndexError as e:
761 # this is a workaround for getting IKEv2 layer as both ikev2 and
762 # ipsec register for port 4500
763 esp = packet[ESP]
764 ih = self.verify_and_remove_non_esp_marker(esp)
765 self.assertEqual(ih.version, 0x20)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200766 self.assertNotIn("Version", ih.flags)
Filip Tehlare7c83962020-09-23 11:20:12 +0000767 return ih
Filip Tehlar12b517b2020-04-26 18:05:05 +0000768
Filip Tehlare7c83962020-09-23 11:20:12 +0000769 def verify_and_remove_non_esp_marker(self, packet):
770 if self.sa.natt:
771 # if we are in nat traversal mode check for non esp marker
772 # and remove it
773 data = raw(packet)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200774 self.assertEqual(data[:4], b"\x00" * 4)
Filip Tehlare7c83962020-09-23 11:20:12 +0000775 return ikev2.IKEv2(data[4:])
Filip Tehlarbfeae8c2020-06-23 20:35:58 +0000776 else:
Filip Tehlare7c83962020-09-23 11:20:12 +0000777 return packet
Filip Tehlar12b517b2020-04-26 18:05:05 +0000778
Filip Tehlar558607d2020-07-16 07:25:56 +0000779 def encrypt_ike_msg(self, header, plain, first_payload):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200780 if self.sa.ike_crypto == "AES-GCM-16ICV":
Filip Tehlar558607d2020-07-16 07:25:56 +0000781 data = self.sa.ike_crypto_alg.pad(raw(plain))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200782 plen = (
783 len(data)
784 + GCM_IV_SIZE
785 + GCM_ICV_SIZE
786 + len(ikev2.IKEv2_payload_Encrypted())
787 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000788 tlen = plen + len(ikev2.IKEv2())
789
790 # prepare aad data
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200791 sk_p = ikev2.IKEv2_payload_Encrypted(
792 next_payload=first_payload, length=plen
793 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000794 header.length = tlen
795 res = header / sk_p
796 encr = self.sa.encrypt(raw(plain), raw(res))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200797 sk_p = ikev2.IKEv2_payload_Encrypted(
798 next_payload=first_payload, length=plen, load=encr
799 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000800 res = header / sk_p
801 else:
802 encr = self.sa.encrypt(raw(plain))
803 trunc_len = self.sa.ike_integ_alg.trunc_len
804 plen = len(encr) + len(ikev2.IKEv2_payload_Encrypted()) + trunc_len
805 tlen = plen + len(ikev2.IKEv2())
806
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200807 sk_p = ikev2.IKEv2_payload_Encrypted(
808 next_payload=first_payload, length=plen, load=encr
809 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000810 header.length = tlen
811 res = header / sk_p
812
813 integ_data = raw(res)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200814 hmac_data = self.sa.compute_hmac(
815 self.sa.ike_integ_alg.mod(), self.sa.my_authkey, integ_data
816 )
Filip Tehlar558607d2020-07-16 07:25:56 +0000817 res = res / Raw(hmac_data[:trunc_len])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200818 assert len(res) == tlen
Filip Tehlar558607d2020-07-16 07:25:56 +0000819 return res
820
Filip Tehlar67b8a7f2020-11-06 11:00:42 +0000821 def verify_udp_encap(self, ipsec_sa):
822 e = VppEnum.vl_api_ipsec_sad_flags_t
823 if self.sa.udp_encap or self.sa.natt:
824 self.assertIn(e.IPSEC_API_SAD_FLAG_UDP_ENCAP, ipsec_sa.flags)
825 else:
826 self.assertNotIn(e.IPSEC_API_SAD_FLAG_UDP_ENCAP, ipsec_sa.flags)
827
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +0900828 def verify_ipsec_sas(self, is_rekey=False, sa_count=None):
Filip Tehlar12b517b2020-04-26 18:05:05 +0000829 sas = self.vapi.ipsec_sa_dump()
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +0900830 if sa_count is None:
831 if is_rekey:
832 # after rekey there is a short period of time in which old
833 # inbound SA is still present
834 sa_count = 3
835 else:
836 sa_count = 2
Filip Tehlar68ad6252020-10-30 05:28:11 +0000837 self.assertEqual(len(sas), sa_count)
Filip Tehlare7c83962020-09-23 11:20:12 +0000838 if self.sa.is_initiator:
Filip Tehlar68ad6252020-10-30 05:28:11 +0000839 if is_rekey:
840 sa0 = sas[0].entry
841 sa1 = sas[2].entry
842 else:
843 sa0 = sas[0].entry
844 sa1 = sas[1].entry
Filip Tehlare7c83962020-09-23 11:20:12 +0000845 else:
Filip Tehlar68ad6252020-10-30 05:28:11 +0000846 if is_rekey:
847 sa0 = sas[2].entry
848 sa1 = sas[0].entry
849 else:
850 sa1 = sas[0].entry
851 sa0 = sas[1].entry
Filip Tehlare7c83962020-09-23 11:20:12 +0000852
Filip Tehlar12b517b2020-04-26 18:05:05 +0000853 c = self.sa.child_sas[0]
854
Filip Tehlar67b8a7f2020-11-06 11:00:42 +0000855 self.verify_udp_encap(sa0)
856 self.verify_udp_encap(sa1)
Filip Tehlar4f42a712020-07-01 08:56:59 +0000857 vpp_crypto_alg = self.vpp_enums[self.sa.vpp_esp_cypto_alg]
858 self.assertEqual(sa0.crypto_algorithm, vpp_crypto_alg)
859 self.assertEqual(sa1.crypto_algorithm, vpp_crypto_alg)
860
861 if self.sa.esp_integ is None:
862 vpp_integ_alg = 0
863 else:
864 vpp_integ_alg = self.vpp_enums[self.sa.esp_integ]
865 self.assertEqual(sa0.integrity_algorithm, vpp_integ_alg)
866 self.assertEqual(sa1.integrity_algorithm, vpp_integ_alg)
867
Filip Tehlar12b517b2020-04-26 18:05:05 +0000868 # verify crypto keys
869 self.assertEqual(sa0.crypto_key.length, len(c.sk_er))
870 self.assertEqual(sa1.crypto_key.length, len(c.sk_ei))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200871 self.assertEqual(sa0.crypto_key.data[: len(c.sk_er)], c.sk_er)
872 self.assertEqual(sa1.crypto_key.data[: len(c.sk_ei)], c.sk_ei)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000873
874 # verify integ keys
Filip Tehlar4f42a712020-07-01 08:56:59 +0000875 if vpp_integ_alg:
876 self.assertEqual(sa0.integrity_key.length, len(c.sk_ar))
877 self.assertEqual(sa1.integrity_key.length, len(c.sk_ai))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200878 self.assertEqual(sa0.integrity_key.data[: len(c.sk_ar)], c.sk_ar)
879 self.assertEqual(sa1.integrity_key.data[: len(c.sk_ai)], c.sk_ai)
Filip Tehlar4f42a712020-07-01 08:56:59 +0000880 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200881 self.assertEqual(sa0.salt.to_bytes(4, "little"), c.salt_er)
882 self.assertEqual(sa1.salt.to_bytes(4, "little"), c.salt_ei)
Filip Tehlar12b517b2020-04-26 18:05:05 +0000883
jan_cavojskya340fe12020-07-08 09:24:12 +0200884 def verify_keymat(self, api_keys, keys, name):
885 km = getattr(keys, name)
886 api_km = getattr(api_keys, name)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200887 api_km_len = getattr(api_keys, name + "_len")
jan_cavojskya340fe12020-07-08 09:24:12 +0200888 self.assertEqual(len(km), api_km_len)
889 self.assertEqual(km, api_km[:api_km_len])
890
891 def verify_id(self, api_id, exp_id):
892 self.assertEqual(api_id.type, IDType.value(exp_id.type))
893 self.assertEqual(api_id.data_len, exp_id.data_len)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200894 self.assertEqual(bytes(api_id.data, "ascii"), exp_id.type)
jan_cavojskya340fe12020-07-08 09:24:12 +0200895
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900896 def verify_ike_sas(self, is_rekey=False):
jan_cavojskya340fe12020-07-08 09:24:12 +0200897 r = self.vapi.ikev2_sa_dump()
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900898 if is_rekey:
899 sa_count = 2
900 sa = r[1].sa
901 else:
902 sa_count = 1
903 sa = r[0].sa
904 self.assertEqual(len(r), sa_count)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200905 self.assertEqual(self.sa.ispi, (sa.ispi).to_bytes(8, "big"))
906 self.assertEqual(self.sa.rspi, (sa.rspi).to_bytes(8, "big"))
Filip Tehlar84962d12020-09-08 06:08:05 +0000907 if self.ip6:
Filip Tehlare7c83962020-09-23 11:20:12 +0000908 if self.sa.is_initiator:
909 self.assertEqual(sa.iaddr, IPv6Address(self.pg0.remote_ip6))
910 self.assertEqual(sa.raddr, IPv6Address(self.pg0.local_ip6))
911 else:
912 self.assertEqual(sa.iaddr, IPv6Address(self.pg0.local_ip6))
913 self.assertEqual(sa.raddr, IPv6Address(self.pg0.remote_ip6))
Filip Tehlar84962d12020-09-08 06:08:05 +0000914 else:
Filip Tehlare7c83962020-09-23 11:20:12 +0000915 if self.sa.is_initiator:
916 self.assertEqual(sa.iaddr, IPv4Address(self.pg0.remote_ip4))
917 self.assertEqual(sa.raddr, IPv4Address(self.pg0.local_ip4))
918 else:
919 self.assertEqual(sa.iaddr, IPv4Address(self.pg0.local_ip4))
920 self.assertEqual(sa.raddr, IPv4Address(self.pg0.remote_ip4))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200921 self.verify_keymat(sa.keys, self.sa, "sk_d")
922 self.verify_keymat(sa.keys, self.sa, "sk_ai")
923 self.verify_keymat(sa.keys, self.sa, "sk_ar")
924 self.verify_keymat(sa.keys, self.sa, "sk_ei")
925 self.verify_keymat(sa.keys, self.sa, "sk_er")
926 self.verify_keymat(sa.keys, self.sa, "sk_pi")
927 self.verify_keymat(sa.keys, self.sa, "sk_pr")
jan_cavojskya340fe12020-07-08 09:24:12 +0200928
929 self.assertEqual(sa.i_id.type, self.sa.id_type)
930 self.assertEqual(sa.r_id.type, self.sa.id_type)
931 self.assertEqual(sa.i_id.data_len, len(self.sa.i_id))
Benoît Gannec7cceee2021-09-28 11:19:37 +0200932 self.assertEqual(sa.r_id.data_len, len(self.idr))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200933 self.assertEqual(bytes(sa.i_id.data, "ascii"), self.sa.i_id)
934 self.assertEqual(bytes(sa.r_id.data, "ascii"), self.idr)
jan_cavojskya340fe12020-07-08 09:24:12 +0200935
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900936 n = self.vapi.ikev2_nonce_get(is_initiator=True, sa_index=sa.sa_index)
937 self.verify_nonce(n, self.sa.i_nonce)
938 n = self.vapi.ikev2_nonce_get(is_initiator=False, sa_index=sa.sa_index)
939 self.verify_nonce(n, self.sa.r_nonce)
940
jan_cavojskya340fe12020-07-08 09:24:12 +0200941 r = self.vapi.ikev2_child_sa_dump(sa_index=sa.sa_index)
Atzm Watanabed4f405a2022-08-18 17:57:53 +0900942 if is_rekey:
943 self.assertEqual(len(r), 0)
944 return
945
jan_cavojskya340fe12020-07-08 09:24:12 +0200946 self.assertEqual(len(r), 1)
947 csa = r[0].child_sa
948 self.assertEqual(csa.sa_index, sa.sa_index)
949 c = self.sa.child_sas[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200950 if hasattr(c, "sk_ai"):
951 self.verify_keymat(csa.keys, c, "sk_ai")
952 self.verify_keymat(csa.keys, c, "sk_ar")
953 self.verify_keymat(csa.keys, c, "sk_ei")
954 self.verify_keymat(csa.keys, c, "sk_er")
955 self.assertEqual(csa.i_spi.to_bytes(4, "big"), c.ispi)
956 self.assertEqual(csa.r_spi.to_bytes(4, "big"), c.rspi)
jan_cavojskya340fe12020-07-08 09:24:12 +0200957
Filip Tehlar84962d12020-09-08 06:08:05 +0000958 tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4)
jan_cavojskya340fe12020-07-08 09:24:12 +0200959 tsi = tsi[0]
960 tsr = tsr[0]
961 r = self.vapi.ikev2_traffic_selector_dump(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200962 is_initiator=True, sa_index=sa.sa_index, child_sa_index=csa.child_sa_index
963 )
jan_cavojskya340fe12020-07-08 09:24:12 +0200964 self.assertEqual(len(r), 1)
965 ts = r[0].ts
966 self.verify_ts(r[0].ts, tsi[0], True)
967
968 r = self.vapi.ikev2_traffic_selector_dump(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +0200969 is_initiator=False, sa_index=sa.sa_index, child_sa_index=csa.child_sa_index
970 )
jan_cavojskya340fe12020-07-08 09:24:12 +0200971 self.assertEqual(len(r), 1)
972 self.verify_ts(r[0].ts, tsr[0], False)
973
Denys Haryachyyf40a3542024-01-24 16:31:47 +0200974 def verify_ike_sas_v2(self):
975 r = self.vapi.ikev2_sa_v2_dump()
976 self.assertEqual(len(r), 1)
977 sa = r[0].sa
978 self.assertEqual(self.p.profile_name, sa.profile_name)
979 self.assertEqual(self.sa.ispi, (sa.ispi).to_bytes(8, "big"))
980 self.assertEqual(self.sa.rspi, (sa.rspi).to_bytes(8, "big"))
981 if self.ip6:
982 if self.sa.is_initiator:
983 self.assertEqual(sa.iaddr, IPv6Address(self.pg0.remote_ip6))
984 self.assertEqual(sa.raddr, IPv6Address(self.pg0.local_ip6))
985 else:
986 self.assertEqual(sa.iaddr, IPv6Address(self.pg0.local_ip6))
987 self.assertEqual(sa.raddr, IPv6Address(self.pg0.remote_ip6))
988 else:
989 if self.sa.is_initiator:
990 self.assertEqual(sa.iaddr, IPv4Address(self.pg0.remote_ip4))
991 self.assertEqual(sa.raddr, IPv4Address(self.pg0.local_ip4))
992 else:
993 self.assertEqual(sa.iaddr, IPv4Address(self.pg0.local_ip4))
994 self.assertEqual(sa.raddr, IPv4Address(self.pg0.remote_ip4))
995 self.verify_keymat(sa.keys, self.sa, "sk_d")
996 self.verify_keymat(sa.keys, self.sa, "sk_ai")
997 self.verify_keymat(sa.keys, self.sa, "sk_ar")
998 self.verify_keymat(sa.keys, self.sa, "sk_ei")
999 self.verify_keymat(sa.keys, self.sa, "sk_er")
1000 self.verify_keymat(sa.keys, self.sa, "sk_pi")
1001 self.verify_keymat(sa.keys, self.sa, "sk_pr")
1002
1003 self.assertEqual(sa.i_id.type, self.sa.id_type)
1004 self.assertEqual(sa.r_id.type, self.sa.id_type)
1005 self.assertEqual(sa.i_id.data_len, len(self.sa.i_id))
1006 self.assertEqual(sa.r_id.data_len, len(self.idr))
1007 self.assertEqual(bytes(sa.i_id.data, "ascii"), self.sa.i_id)
1008 self.assertEqual(bytes(sa.r_id.data, "ascii"), self.idr)
1009
1010 r = self.vapi.ikev2_child_sa_dump(sa_index=sa.sa_index)
1011 self.assertEqual(len(r), 1)
1012 csa = r[0].child_sa
1013 self.assertEqual(csa.sa_index, sa.sa_index)
1014 c = self.sa.child_sas[0]
1015 if hasattr(c, "sk_ai"):
1016 self.verify_keymat(csa.keys, c, "sk_ai")
1017 self.verify_keymat(csa.keys, c, "sk_ar")
1018 self.verify_keymat(csa.keys, c, "sk_ei")
1019 self.verify_keymat(csa.keys, c, "sk_er")
1020 self.assertEqual(csa.i_spi.to_bytes(4, "big"), c.ispi)
1021 self.assertEqual(csa.r_spi.to_bytes(4, "big"), c.rspi)
1022
1023 tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4)
1024 tsi = tsi[0]
1025 tsr = tsr[0]
1026 r = self.vapi.ikev2_traffic_selector_dump(
1027 is_initiator=True, sa_index=sa.sa_index, child_sa_index=csa.child_sa_index
1028 )
1029 self.assertEqual(len(r), 1)
1030 ts = r[0].ts
1031 self.verify_ts(r[0].ts, tsi[0], True)
1032
1033 r = self.vapi.ikev2_traffic_selector_dump(
1034 is_initiator=False, sa_index=sa.sa_index, child_sa_index=csa.child_sa_index
1035 )
1036 self.assertEqual(len(r), 1)
1037 self.verify_ts(r[0].ts, tsr[0], False)
1038
1039 n = self.vapi.ikev2_nonce_get(is_initiator=True, sa_index=sa.sa_index)
1040 self.verify_nonce(n, self.sa.i_nonce)
1041 n = self.vapi.ikev2_nonce_get(is_initiator=False, sa_index=sa.sa_index)
1042 self.verify_nonce(n, self.sa.r_nonce)
1043
jan_cavojskya340fe12020-07-08 09:24:12 +02001044 def verify_nonce(self, api_nonce, nonce):
1045 self.assertEqual(api_nonce.data_len, len(nonce))
1046 self.assertEqual(api_nonce.nonce, nonce)
1047
1048 def verify_ts(self, api_ts, ts, is_initiator):
1049 if is_initiator:
1050 self.assertTrue(api_ts.is_local)
1051 else:
1052 self.assertFalse(api_ts.is_local)
Filip Tehlar84962d12020-09-08 06:08:05 +00001053
1054 if self.p.ts_is_ip4:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001055 self.assertEqual(api_ts.start_addr, IPv4Address(ts.starting_address_v4))
1056 self.assertEqual(api_ts.end_addr, IPv4Address(ts.ending_address_v4))
Filip Tehlar84962d12020-09-08 06:08:05 +00001057 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001058 self.assertEqual(api_ts.start_addr, IPv6Address(ts.starting_address_v6))
1059 self.assertEqual(api_ts.end_addr, IPv6Address(ts.ending_address_v6))
jan_cavojskya340fe12020-07-08 09:24:12 +02001060 self.assertEqual(api_ts.start_port, ts.start_port)
1061 self.assertEqual(api_ts.end_port, ts.end_port)
1062 self.assertEqual(api_ts.protocol_id, ts.IP_protocol_ID)
1063
Filip Tehlare7c83962020-09-23 11:20:12 +00001064
1065class TemplateInitiator(IkePeer):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001066 """initiator test template"""
Filip Tehlare7c83962020-09-23 11:20:12 +00001067
Filip Tehlaredf29002020-10-10 04:39:11 +00001068 def initiate_del_sa_from_initiator(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001069 ispi = int.from_bytes(self.sa.ispi, "little")
Filip Tehlaredf29002020-10-10 04:39:11 +00001070 self.pg0.enable_capture()
1071 self.pg_start()
1072 self.vapi.ikev2_initiate_del_ike_sa(ispi=ispi)
1073 capture = self.pg0.get_capture(1)
1074 ih = self.get_ike_header(capture[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001075 self.assertNotIn("Response", ih.flags)
1076 self.assertIn("Initiator", ih.flags)
Filip Tehlaredf29002020-10-10 04:39:11 +00001077 self.assertEqual(ih.init_SPI, self.sa.ispi)
1078 self.assertEqual(ih.resp_SPI, self.sa.rspi)
1079 plain = self.sa.hmac_and_decrypt(ih)
1080 d = ikev2.IKEv2_payload_Delete(plain)
1081 self.assertEqual(d.proto, 1) # proto=IKEv2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001082 header = ikev2.IKEv2(
1083 init_SPI=self.sa.ispi,
1084 resp_SPI=self.sa.rspi,
1085 flags="Response",
1086 exch_type="INFORMATIONAL",
1087 id=ih.id,
1088 next_payload="Encrypted",
1089 )
1090 resp = self.encrypt_ike_msg(header, b"", None)
Filip Tehlaredf29002020-10-10 04:39:11 +00001091 self.send_and_assert_no_replies(self.pg0, resp)
1092
1093 def verify_del_sa(self, packet):
1094 ih = self.get_ike_header(packet)
1095 self.assertEqual(ih.id, self.sa.msg_id)
1096 self.assertEqual(ih.exch_type, 37) # exchange informational
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001097 self.assertIn("Response", ih.flags)
1098 self.assertIn("Initiator", ih.flags)
Filip Tehlaredf29002020-10-10 04:39:11 +00001099 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001100 self.assertEqual(plain, b"")
Filip Tehlaredf29002020-10-10 04:39:11 +00001101
1102 def initiate_del_sa_from_responder(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001103 header = ikev2.IKEv2(
1104 init_SPI=self.sa.ispi,
1105 resp_SPI=self.sa.rspi,
1106 exch_type="INFORMATIONAL",
1107 id=self.sa.new_msg_id(),
1108 )
1109 del_sa = ikev2.IKEv2_payload_Delete(proto="IKEv2")
1110 ike_msg = self.encrypt_ike_msg(header, del_sa, "Delete")
1111 packet = self.create_packet(
1112 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
1113 )
Filip Tehlaredf29002020-10-10 04:39:11 +00001114 self.pg0.add_stream(packet)
1115 self.pg0.enable_capture()
1116 self.pg_start()
1117 capture = self.pg0.get_capture(1)
1118 self.verify_del_sa(capture[0])
Filip Tehlare7c83962020-09-23 11:20:12 +00001119
Filip Tehlarec112e52020-10-07 23:52:37 +00001120 @staticmethod
1121 def find_notify_payload(packet, notify_type):
1122 n = packet[ikev2.IKEv2_payload_Notify]
1123 while n is not None:
1124 if n.type == notify_type:
1125 return n
1126 n = n.payload
1127 return None
1128
1129 def verify_nat_detection(self, packet):
1130 if self.ip6:
1131 iph = packet[IPv6]
1132 else:
1133 iph = packet[IP]
1134 udp = packet[UDP]
1135
1136 # NAT_DETECTION_SOURCE_IP
1137 s = self.find_notify_payload(packet, 16388)
1138 self.assertIsNotNone(s)
1139 src_sha = self.sa.compute_nat_sha1(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001140 inet_pton(socket.AF_INET, iph.src), udp.sport, b"\x00" * 8
1141 )
Filip Tehlarec112e52020-10-07 23:52:37 +00001142 self.assertEqual(s.load, src_sha)
1143
1144 # NAT_DETECTION_DESTINATION_IP
1145 s = self.find_notify_payload(packet, 16389)
1146 self.assertIsNotNone(s)
1147 dst_sha = self.sa.compute_nat_sha1(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001148 inet_pton(socket.AF_INET, iph.dst), udp.dport, b"\x00" * 8
1149 )
Filip Tehlarec112e52020-10-07 23:52:37 +00001150 self.assertEqual(s.load, dst_sha)
1151
Filip Tehlare7c83962020-09-23 11:20:12 +00001152 def verify_sa_init_request(self, packet):
Filip Tehlar18107c92020-12-01 14:51:09 +00001153 udp = packet[UDP]
1154 self.sa.dport = udp.sport
Filip Tehlare7c83962020-09-23 11:20:12 +00001155 ih = packet[ikev2.IKEv2]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001156 self.assertNotEqual(ih.init_SPI, 8 * b"\x00")
Filip Tehlare7c83962020-09-23 11:20:12 +00001157 self.assertEqual(ih.exch_type, 34) # SA_INIT
1158 self.sa.ispi = ih.init_SPI
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001159 self.assertEqual(ih.resp_SPI, 8 * b"\x00")
1160 self.assertIn("Initiator", ih.flags)
1161 self.assertNotIn("Response", ih.flags)
Filip Tehlare7c83962020-09-23 11:20:12 +00001162 self.sa.i_nonce = ih[ikev2.IKEv2_payload_Nonce].load
1163 self.sa.i_dh_data = ih[ikev2.IKEv2_payload_KE].load
1164
1165 prop = packet[ikev2.IKEv2_payload_Proposal]
1166 self.assertEqual(prop.proto, 1) # proto = ikev2
1167 self.assertEqual(prop.proposal, 1)
1168 self.assertEqual(prop.trans[0].transform_type, 1) # encryption
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001169 self.assertEqual(
1170 prop.trans[0].transform_id, self.p.ike_transforms["crypto_alg"]
1171 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001172 self.assertEqual(prop.trans[1].transform_type, 2) # prf
1173 self.assertEqual(prop.trans[1].transform_id, 5) # "hmac-sha2-256"
1174 self.assertEqual(prop.trans[2].transform_type, 4) # dh
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001175 self.assertEqual(prop.trans[2].transform_id, self.p.ike_transforms["dh_group"])
Filip Tehlare7c83962020-09-23 11:20:12 +00001176
Filip Tehlarec112e52020-10-07 23:52:37 +00001177 self.verify_nat_detection(packet)
Filip Tehlar68ad6252020-10-30 05:28:11 +00001178 self.sa.set_ike_props(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001179 crypto="AES-GCM-16ICV",
1180 crypto_key_len=32,
1181 integ="NULL",
1182 prf="PRF_HMAC_SHA2_256",
1183 dh="3072MODPgr",
1184 )
1185 self.sa.set_esp_props(crypto="AES-CBC", crypto_key_len=32, integ="SHA2-256-128")
Filip Tehlar68ad6252020-10-30 05:28:11 +00001186 self.sa.generate_dh_data()
Filip Tehlare7c83962020-09-23 11:20:12 +00001187 self.sa.complete_dh_data()
1188 self.sa.calc_keys()
1189
Filip Tehlar68ad6252020-10-30 05:28:11 +00001190 def update_esp_transforms(self, trans, sa):
1191 while trans:
1192 if trans.transform_type == 1: # ecryption
1193 sa.esp_crypto = CRYPTO_IDS[trans.transform_id]
1194 elif trans.transform_type == 3: # integrity
1195 sa.esp_integ = INTEG_IDS[trans.transform_id]
1196 trans = trans.payload
1197
Filip Tehlare7c83962020-09-23 11:20:12 +00001198 def verify_sa_auth_req(self, packet):
Filip Tehlar18107c92020-12-01 14:51:09 +00001199 udp = packet[UDP]
1200 self.sa.dport = udp.sport
Filip Tehlare7c83962020-09-23 11:20:12 +00001201 ih = self.get_ike_header(packet)
1202 self.assertEqual(ih.resp_SPI, self.sa.rspi)
1203 self.assertEqual(ih.init_SPI, self.sa.ispi)
1204 self.assertEqual(ih.exch_type, 35) # IKE_AUTH
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001205 self.assertIn("Initiator", ih.flags)
1206 self.assertNotIn("Response", ih.flags)
Filip Tehlare7c83962020-09-23 11:20:12 +00001207
1208 udp = packet[UDP]
1209 self.verify_udp(udp)
1210 self.assertEqual(ih.id, self.sa.msg_id + 1)
1211 self.sa.msg_id += 1
1212 plain = self.sa.hmac_and_decrypt(ih)
1213 idi = ikev2.IKEv2_payload_IDi(plain)
Filip Tehlare7c83962020-09-23 11:20:12 +00001214 self.assertEqual(idi.load, self.sa.i_id)
Benoît Gannec7cceee2021-09-28 11:19:37 +02001215 if self.no_idr_auth:
1216 self.assertEqual(idi.next_payload, 39) # AUTH
1217 else:
1218 idr = ikev2.IKEv2_payload_IDr(idi.payload)
1219 self.assertEqual(idr.load, self.sa.r_id)
Filip Tehlar68ad6252020-10-30 05:28:11 +00001220 prop = idi[ikev2.IKEv2_payload_Proposal]
1221 c = self.sa.child_sas[0]
1222 c.ispi = prop.SPI
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001223 self.update_esp_transforms(prop[ikev2.IKEv2_payload_Transform], self.sa)
Filip Tehlare7c83962020-09-23 11:20:12 +00001224
1225 def send_init_response(self):
1226 tr_attr = self.sa.ike_crypto_attr()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001227 trans = (
1228 ikev2.IKEv2_payload_Transform(
1229 transform_type="Encryption",
1230 transform_id=self.sa.ike_crypto,
1231 length=tr_attr[1],
1232 key_length=tr_attr[0],
1233 )
1234 / ikev2.IKEv2_payload_Transform(
1235 transform_type="Integrity", transform_id=self.sa.ike_integ
1236 )
1237 / ikev2.IKEv2_payload_Transform(
1238 transform_type="PRF", transform_id=self.sa.ike_prf_alg.name
1239 )
1240 / ikev2.IKEv2_payload_Transform(
1241 transform_type="GroupDesc", transform_id=self.sa.ike_dh
1242 )
1243 )
1244 props = ikev2.IKEv2_payload_Proposal(
1245 proposal=1, proto="IKEv2", trans_nb=4, trans=trans
1246 )
Filip Tehlar18107c92020-12-01 14:51:09 +00001247
1248 src_address = inet_pton(socket.AF_INET, self.pg0.remote_ip4)
1249 if self.sa.natt:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001250 dst_address = b"\x0a\x0a\x0a\x0a"
Filip Tehlar18107c92020-12-01 14:51:09 +00001251 else:
1252 dst_address = inet_pton(socket.AF_INET, self.pg0.local_ip4)
1253 src_nat = self.sa.compute_nat_sha1(src_address, self.sa.sport)
1254 dst_nat = self.sa.compute_nat_sha1(dst_address, self.sa.dport)
1255
Filip Tehlare7c83962020-09-23 11:20:12 +00001256 self.sa.init_resp_packet = (
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001257 ikev2.IKEv2(
1258 init_SPI=self.sa.ispi,
1259 resp_SPI=self.sa.rspi,
1260 exch_type="IKE_SA_INIT",
1261 flags="Response",
1262 )
1263 / ikev2.IKEv2_payload_SA(next_payload="KE", prop=props)
1264 / ikev2.IKEv2_payload_KE(
1265 next_payload="Nonce", group=self.sa.ike_dh, load=self.sa.my_dh_pub_key
1266 )
1267 / ikev2.IKEv2_payload_Nonce(load=self.sa.r_nonce, next_payload="Notify")
1268 / ikev2.IKEv2_payload_Notify(
1269 type="NAT_DETECTION_SOURCE_IP", load=src_nat, next_payload="Notify"
1270 )
1271 / ikev2.IKEv2_payload_Notify(
1272 type="NAT_DETECTION_DESTINATION_IP", load=dst_nat
1273 )
1274 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001275
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001276 ike_msg = self.create_packet(
1277 self.pg0,
1278 self.sa.init_resp_packet,
1279 self.sa.sport,
1280 self.sa.dport,
1281 False,
1282 self.ip6,
1283 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001284 self.pg_send(self.pg0, ike_msg)
1285 capture = self.pg0.get_capture(1)
1286 self.verify_sa_auth_req(capture[0])
1287
1288 def initiate_sa_init(self):
1289 self.pg0.enable_capture()
1290 self.pg_start()
1291 self.vapi.ikev2_initiate_sa_init(name=self.p.profile_name)
1292
1293 capture = self.pg0.get_capture(1)
1294 self.verify_sa_init_request(capture[0])
1295 self.send_init_response()
1296
1297 def send_auth_response(self):
1298 tr_attr = self.sa.esp_crypto_attr()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001299 trans = (
1300 ikev2.IKEv2_payload_Transform(
1301 transform_type="Encryption",
1302 transform_id=self.sa.esp_crypto,
1303 length=tr_attr[1],
1304 key_length=tr_attr[0],
1305 )
1306 / ikev2.IKEv2_payload_Transform(
1307 transform_type="Integrity", transform_id=self.sa.esp_integ
1308 )
1309 / ikev2.IKEv2_payload_Transform(
1310 transform_type="Extended Sequence Number", transform_id="No ESN"
1311 )
1312 / ikev2.IKEv2_payload_Transform(
1313 transform_type="Extended Sequence Number", transform_id="ESN"
1314 )
1315 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001316
Filip Tehlar68ad6252020-10-30 05:28:11 +00001317 c = self.sa.child_sas[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001318 props = ikev2.IKEv2_payload_Proposal(
1319 proposal=1, proto="ESP", SPIsize=4, SPI=c.rspi, trans_nb=4, trans=trans
1320 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001321
1322 tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001323 plain = (
1324 ikev2.IKEv2_payload_IDi(
1325 next_payload="IDr", IDtype=self.sa.id_type, load=self.sa.i_id
1326 )
1327 / ikev2.IKEv2_payload_IDr(
1328 next_payload="AUTH", IDtype=self.sa.id_type, load=self.sa.r_id
1329 )
1330 / ikev2.IKEv2_payload_AUTH(
1331 next_payload="SA",
1332 auth_type=AuthMethod.value(self.sa.auth_method),
1333 load=self.sa.auth_data,
1334 )
1335 / ikev2.IKEv2_payload_SA(next_payload="TSi", prop=props)
1336 / ikev2.IKEv2_payload_TSi(
1337 next_payload="TSr", number_of_TSs=len(tsi), traffic_selector=tsi
1338 )
1339 / ikev2.IKEv2_payload_TSr(
1340 next_payload="Notify", number_of_TSs=len(tsr), traffic_selector=tsr
1341 )
1342 / ikev2.IKEv2_payload_Notify(type="INITIAL_CONTACT")
1343 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001344
1345 header = ikev2.IKEv2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001346 init_SPI=self.sa.ispi,
1347 resp_SPI=self.sa.rspi,
1348 id=self.sa.new_msg_id(),
1349 flags="Response",
1350 exch_type="IKE_AUTH",
1351 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001352
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001353 ike_msg = self.encrypt_ike_msg(header, plain, "IDi")
1354 packet = self.create_packet(
1355 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
1356 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001357 self.pg_send(self.pg0, packet)
1358
1359 def test_initiator(self):
1360 self.initiate_sa_init()
1361 self.sa.auth_init()
1362 self.sa.calc_child_keys()
1363 self.send_auth_response()
1364 self.verify_ike_sas()
Denys Haryachyyf40a3542024-01-24 16:31:47 +02001365 self.verify_ike_sas_v2()
Filip Tehlare7c83962020-09-23 11:20:12 +00001366
1367
1368class TemplateResponder(IkePeer):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001369 """responder test template"""
Filip Tehlare7c83962020-09-23 11:20:12 +00001370
Filip Tehlaredf29002020-10-10 04:39:11 +00001371 def initiate_del_sa_from_responder(self):
1372 self.pg0.enable_capture()
1373 self.pg_start()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001374 self.vapi.ikev2_initiate_del_ike_sa(ispi=int.from_bytes(self.sa.ispi, "little"))
Filip Tehlaredf29002020-10-10 04:39:11 +00001375 capture = self.pg0.get_capture(1)
1376 ih = self.get_ike_header(capture[0])
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001377 self.assertNotIn("Response", ih.flags)
1378 self.assertNotIn("Initiator", ih.flags)
Filip Tehlaredf29002020-10-10 04:39:11 +00001379 self.assertEqual(ih.exch_type, 37) # INFORMATIONAL
1380 plain = self.sa.hmac_and_decrypt(ih)
1381 d = ikev2.IKEv2_payload_Delete(plain)
1382 self.assertEqual(d.proto, 1) # proto=IKEv2
1383 self.assertEqual(ih.init_SPI, self.sa.ispi)
1384 self.assertEqual(ih.resp_SPI, self.sa.rspi)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001385 header = ikev2.IKEv2(
1386 init_SPI=self.sa.ispi,
1387 resp_SPI=self.sa.rspi,
1388 flags="Initiator+Response",
1389 exch_type="INFORMATIONAL",
1390 id=ih.id,
1391 next_payload="Encrypted",
1392 )
1393 resp = self.encrypt_ike_msg(header, b"", None)
Filip Tehlaredf29002020-10-10 04:39:11 +00001394 self.send_and_assert_no_replies(self.pg0, resp)
Filip Tehlare7c83962020-09-23 11:20:12 +00001395
1396 def verify_del_sa(self, packet):
1397 ih = self.get_ike_header(packet)
1398 self.assertEqual(ih.id, self.sa.msg_id)
1399 self.assertEqual(ih.exch_type, 37) # exchange informational
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001400 self.assertIn("Response", ih.flags)
1401 self.assertNotIn("Initiator", ih.flags)
Filip Tehlaredf29002020-10-10 04:39:11 +00001402 self.assertEqual(ih.next_payload, 46) # Encrypted
1403 self.assertEqual(ih.init_SPI, self.sa.ispi)
1404 self.assertEqual(ih.resp_SPI, self.sa.rspi)
1405 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001406 self.assertEqual(plain, b"")
Filip Tehlare7c83962020-09-23 11:20:12 +00001407
Filip Tehlaredf29002020-10-10 04:39:11 +00001408 def initiate_del_sa_from_initiator(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001409 header = ikev2.IKEv2(
1410 init_SPI=self.sa.ispi,
1411 resp_SPI=self.sa.rspi,
1412 flags="Initiator",
1413 exch_type="INFORMATIONAL",
1414 id=self.sa.new_msg_id(),
1415 )
1416 del_sa = ikev2.IKEv2_payload_Delete(proto="IKEv2")
1417 ike_msg = self.encrypt_ike_msg(header, del_sa, "Delete")
1418 packet = self.create_packet(
1419 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
1420 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001421 self.pg0.add_stream(packet)
1422 self.pg0.enable_capture()
1423 self.pg_start()
1424 capture = self.pg0.get_capture(1)
1425 self.verify_del_sa(capture[0])
1426
Atzm Watanabed4f405a2022-08-18 17:57:53 +09001427 def generate_sa_init_payload(
1428 self, spi=None, dh_pub_key=None, nonce=None, next_payload=None
1429 ):
Filip Tehlare7c83962020-09-23 11:20:12 +00001430 tr_attr = self.sa.ike_crypto_attr()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001431 trans = (
1432 ikev2.IKEv2_payload_Transform(
1433 transform_type="Encryption",
1434 transform_id=self.sa.ike_crypto,
1435 length=tr_attr[1],
1436 key_length=tr_attr[0],
1437 )
1438 / ikev2.IKEv2_payload_Transform(
1439 transform_type="Integrity", transform_id=self.sa.ike_integ
1440 )
1441 / ikev2.IKEv2_payload_Transform(
1442 transform_type="PRF", transform_id=self.sa.ike_prf_alg.name
1443 )
1444 / ikev2.IKEv2_payload_Transform(
1445 transform_type="GroupDesc", transform_id=self.sa.ike_dh
1446 )
1447 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001448
Atzm Watanabed4f405a2022-08-18 17:57:53 +09001449 if spi is None:
1450 pargs = {}
1451 else:
1452 pargs = {"SPI": spi, "SPIsize": len(spi)}
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001453 props = ikev2.IKEv2_payload_Proposal(
Atzm Watanabed4f405a2022-08-18 17:57:53 +09001454 proposal=1,
1455 proto="IKEv2",
1456 trans_nb=4,
1457 trans=trans,
1458 **pargs,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001459 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001460
Atzm Watanabed4f405a2022-08-18 17:57:53 +09001461 return (
1462 ikev2.IKEv2_payload_SA(next_payload="KE", prop=props)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001463 / ikev2.IKEv2_payload_KE(
Atzm Watanabed4f405a2022-08-18 17:57:53 +09001464 next_payload="Nonce",
1465 group=self.sa.ike_dh,
1466 load=self.sa.my_dh_pub_key if dh_pub_key is None else dh_pub_key,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001467 )
Atzm Watanabed4f405a2022-08-18 17:57:53 +09001468 / ikev2.IKEv2_payload_Nonce(
1469 next_payload=next_payload,
1470 load=self.sa.i_nonce if nonce is None else nonce,
1471 )
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001472 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001473
Atzm Watanabed4f405a2022-08-18 17:57:53 +09001474 def send_sa_init_req(self):
1475 self.sa.init_req_packet = ikev2.IKEv2(
1476 init_SPI=self.sa.ispi, flags="Initiator", exch_type="IKE_SA_INIT"
1477 ) / self.generate_sa_init_payload(next_payload=None if self.ip6 else "Notify")
1478
Filip Tehlar027d8132020-12-04 17:38:11 +00001479 if not self.ip6:
1480 if self.sa.i_natt:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001481 src_address = b"\x0a\x0a\x0a\x01"
Filip Tehlar027d8132020-12-04 17:38:11 +00001482 else:
1483 src_address = inet_pton(socket.AF_INET, self.pg0.remote_ip4)
Filip Tehlare7c83962020-09-23 11:20:12 +00001484
Filip Tehlar027d8132020-12-04 17:38:11 +00001485 if self.sa.r_natt:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001486 dst_address = b"\x0a\x0a\x0a\x0a"
Filip Tehlar027d8132020-12-04 17:38:11 +00001487 else:
1488 dst_address = inet_pton(socket.AF_INET, self.pg0.local_ip4)
1489
1490 src_nat = self.sa.compute_nat_sha1(src_address, self.sa.sport)
1491 dst_nat = self.sa.compute_nat_sha1(dst_address, self.sa.dport)
1492 nat_src_detection = ikev2.IKEv2_payload_Notify(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001493 type="NAT_DETECTION_SOURCE_IP", load=src_nat, next_payload="Notify"
1494 )
Filip Tehlar027d8132020-12-04 17:38:11 +00001495 nat_dst_detection = ikev2.IKEv2_payload_Notify(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001496 type="NAT_DETECTION_DESTINATION_IP", load=dst_nat
1497 )
1498 self.sa.init_req_packet = (
1499 self.sa.init_req_packet / nat_src_detection / nat_dst_detection
1500 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001501
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001502 ike_msg = self.create_packet(
1503 self.pg0,
1504 self.sa.init_req_packet,
1505 self.sa.sport,
1506 self.sa.dport,
1507 self.sa.natt,
1508 self.ip6,
1509 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001510 self.pg0.add_stream(ike_msg)
1511 self.pg0.enable_capture()
1512 self.pg_start()
1513 capture = self.pg0.get_capture(1)
1514 self.verify_sa_init(capture[0])
1515
Atzm Watanabec65921f2022-08-12 14:29:31 +09001516 def generate_auth_payload(self, last_payload=None, is_rekey=False, kex=False):
Filip Tehlare7c83962020-09-23 11:20:12 +00001517 tr_attr = self.sa.esp_crypto_attr()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001518 last_payload = last_payload or "Notify"
Atzm Watanabec65921f2022-08-12 14:29:31 +09001519 trans_nb = 4
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001520 trans = (
1521 ikev2.IKEv2_payload_Transform(
1522 transform_type="Encryption",
1523 transform_id=self.sa.esp_crypto,
1524 length=tr_attr[1],
1525 key_length=tr_attr[0],
1526 )
1527 / ikev2.IKEv2_payload_Transform(
1528 transform_type="Integrity", transform_id=self.sa.esp_integ
1529 )
1530 / ikev2.IKEv2_payload_Transform(
1531 transform_type="Extended Sequence Number", transform_id="No ESN"
1532 )
1533 / ikev2.IKEv2_payload_Transform(
1534 transform_type="Extended Sequence Number", transform_id="ESN"
1535 )
1536 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001537
Atzm Watanabec65921f2022-08-12 14:29:31 +09001538 if kex:
1539 trans_nb += 1
1540 trans /= ikev2.IKEv2_payload_Transform(
1541 transform_type="GroupDesc", transform_id=self.sa.ike_dh
1542 )
1543
Filip Tehlar68ad6252020-10-30 05:28:11 +00001544 c = self.sa.child_sas[0]
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001545 props = ikev2.IKEv2_payload_Proposal(
Atzm Watanabec65921f2022-08-12 14:29:31 +09001546 proposal=1,
1547 proto="ESP",
1548 SPIsize=4,
1549 SPI=c.ispi,
1550 trans_nb=trans_nb,
1551 trans=trans,
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001552 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001553
1554 tsi, tsr = self.sa.generate_ts(self.p.ts_is_ip4)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001555 plain = (
1556 ikev2.IKEv2_payload_AUTH(
1557 next_payload="SA",
1558 auth_type=AuthMethod.value(self.sa.auth_method),
1559 load=self.sa.auth_data,
1560 )
1561 / ikev2.IKEv2_payload_SA(next_payload="TSi", prop=props)
1562 / ikev2.IKEv2_payload_TSi(
1563 next_payload="TSr", number_of_TSs=len(tsi), traffic_selector=tsi
1564 )
1565 / ikev2.IKEv2_payload_TSr(
1566 next_payload=last_payload, number_of_TSs=len(tsr), traffic_selector=tsr
1567 )
1568 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001569
Filip Tehlar68ad6252020-10-30 05:28:11 +00001570 if is_rekey:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001571 first_payload = "Nonce"
Atzm Watanabec65921f2022-08-12 14:29:31 +09001572 if kex:
1573 head = ikev2.IKEv2_payload_Nonce(
1574 load=self.sa.i_nonce, next_payload="KE"
1575 ) / ikev2.IKEv2_payload_KE(
1576 group=self.sa.ike_dh, load=self.sa.my_dh_pub_key, next_payload="SA"
1577 )
1578 else:
1579 head = ikev2.IKEv2_payload_Nonce(
1580 load=self.sa.i_nonce, next_payload="SA"
1581 )
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001582 plain = (
Atzm Watanabec65921f2022-08-12 14:29:31 +09001583 head
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001584 / plain
Atzm Watanabe03aae962022-08-08 15:45:36 +09001585 / ikev2.IKEv2_payload_Notify(
1586 type="REKEY_SA",
1587 proto="ESP",
1588 SPI=c.ispi,
1589 length=8 + len(c.ispi),
1590 next_payload="Notify",
1591 )
1592 / ikev2.IKEv2_payload_Notify(type="ESP_TFC_PADDING_NOT_SUPPORTED")
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001593 )
Filip Tehlar68ad6252020-10-30 05:28:11 +00001594 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001595 first_payload = "IDi"
Benoît Gannec7cceee2021-09-28 11:19:37 +02001596 if self.no_idr_auth:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001597 ids = ikev2.IKEv2_payload_IDi(
1598 next_payload="AUTH", IDtype=self.sa.id_type, load=self.sa.i_id
1599 )
Benoît Gannec7cceee2021-09-28 11:19:37 +02001600 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001601 ids = ikev2.IKEv2_payload_IDi(
1602 next_payload="IDr", IDtype=self.sa.id_type, load=self.sa.i_id
1603 ) / ikev2.IKEv2_payload_IDr(
1604 next_payload="AUTH", IDtype=self.sa.id_type, load=self.sa.r_id
1605 )
Filip Tehlar68ad6252020-10-30 05:28:11 +00001606 plain = ids / plain
1607 return plain, first_payload
1608
1609 def send_sa_auth(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001610 plain, first_payload = self.generate_auth_payload(last_payload="Notify")
1611 plain = plain / ikev2.IKEv2_payload_Notify(type="INITIAL_CONTACT")
Filip Tehlare7c83962020-09-23 11:20:12 +00001612 header = ikev2.IKEv2(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001613 init_SPI=self.sa.ispi,
1614 resp_SPI=self.sa.rspi,
1615 id=self.sa.new_msg_id(),
1616 flags="Initiator",
1617 exch_type="IKE_AUTH",
1618 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001619
Filip Tehlar68ad6252020-10-30 05:28:11 +00001620 ike_msg = self.encrypt_ike_msg(header, plain, first_payload)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001621 packet = self.create_packet(
1622 self.pg0, ike_msg, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
1623 )
Filip Tehlare7c83962020-09-23 11:20:12 +00001624 self.pg0.add_stream(packet)
1625 self.pg0.enable_capture()
1626 self.pg_start()
1627 capture = self.pg0.get_capture(1)
1628 self.verify_sa_auth_resp(capture[0])
1629
1630 def verify_sa_init(self, packet):
1631 ih = self.get_ike_header(packet)
1632
1633 self.assertEqual(ih.id, self.sa.msg_id)
1634 self.assertEqual(ih.exch_type, 34)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001635 self.assertIn("Response", ih.flags)
Filip Tehlare7c83962020-09-23 11:20:12 +00001636 self.assertEqual(ih.init_SPI, self.sa.ispi)
1637 self.assertNotEqual(ih.resp_SPI, 0)
1638 self.sa.rspi = ih.resp_SPI
1639 try:
1640 sa = ih[ikev2.IKEv2_payload_SA]
1641 self.sa.r_nonce = ih[ikev2.IKEv2_payload_Nonce].load
1642 self.sa.r_dh_data = ih[ikev2.IKEv2_payload_KE].load
1643 except IndexError as e:
1644 self.logger.error("unexpected reply: SA/Nonce/KE payload found!")
1645 self.logger.error(ih.show())
1646 raise
1647 self.sa.complete_dh_data()
1648 self.sa.calc_keys()
1649 self.sa.auth_init()
1650
1651 def verify_sa_auth_resp(self, packet):
1652 ike = self.get_ike_header(packet)
1653 udp = packet[UDP]
1654 self.verify_udp(udp)
1655 self.assertEqual(ike.id, self.sa.msg_id)
1656 plain = self.sa.hmac_and_decrypt(ike)
Filip Tehlar68ad6252020-10-30 05:28:11 +00001657 idr = ikev2.IKEv2_payload_IDr(plain)
1658 prop = idr[ikev2.IKEv2_payload_Proposal]
1659 self.assertEqual(prop.SPIsize, 4)
1660 self.sa.child_sas[0].rspi = prop.SPI
Filip Tehlare7c83962020-09-23 11:20:12 +00001661 self.sa.calc_child_keys()
1662
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001663 IKE_NODE_SUFFIX = "ip4"
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00001664
1665 def verify_counters(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001666 self.assert_counter(2, "processed", self.IKE_NODE_SUFFIX)
1667 self.assert_counter(1, "init_sa_req", self.IKE_NODE_SUFFIX)
1668 self.assert_counter(1, "ike_auth_req", self.IKE_NODE_SUFFIX)
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00001669
Filip Tehlar68d27532021-01-25 10:09:27 +00001670 r = self.vapi.ikev2_sa_dump()
1671 s = r[0].sa.stats
1672 self.assertEqual(1, s.n_sa_auth_req)
1673 self.assertEqual(1, s.n_sa_init_req)
1674
Denys Haryachyyf40a3542024-01-24 16:31:47 +02001675 r = self.vapi.ikev2_sa_v2_dump()
1676 s = r[0].sa.stats
1677 self.assertEqual(1, s.n_sa_auth_req)
1678 self.assertEqual(1, s.n_sa_init_req)
1679
Filip Tehlar12b517b2020-04-26 18:05:05 +00001680 def test_responder(self):
Filip Tehlar027d8132020-12-04 17:38:11 +00001681 self.send_sa_init_req()
Filip Tehlar12b517b2020-04-26 18:05:05 +00001682 self.send_sa_auth()
jan_cavojskya340fe12020-07-08 09:24:12 +02001683 self.verify_ipsec_sas()
1684 self.verify_ike_sas()
Denys Haryachyyf40a3542024-01-24 16:31:47 +02001685 self.verify_ike_sas_v2()
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00001686 self.verify_counters()
Filip Tehlar12b517b2020-04-26 18:05:05 +00001687
1688
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001689class Ikev2Params(object):
1690 def config_params(self, params={}):
Filip Tehlar4f42a712020-07-01 08:56:59 +00001691 ec = VppEnum.vl_api_ipsec_crypto_alg_t
1692 ei = VppEnum.vl_api_ipsec_integ_alg_t
1693 self.vpp_enums = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001694 "AES-CBC-128": ec.IPSEC_API_CRYPTO_ALG_AES_CBC_128,
1695 "AES-CBC-192": ec.IPSEC_API_CRYPTO_ALG_AES_CBC_192,
1696 "AES-CBC-256": ec.IPSEC_API_CRYPTO_ALG_AES_CBC_256,
1697 "AES-GCM-16ICV-128": ec.IPSEC_API_CRYPTO_ALG_AES_GCM_128,
1698 "AES-GCM-16ICV-192": ec.IPSEC_API_CRYPTO_ALG_AES_GCM_192,
1699 "AES-GCM-16ICV-256": ec.IPSEC_API_CRYPTO_ALG_AES_GCM_256,
1700 "HMAC-SHA1-96": ei.IPSEC_API_INTEG_ALG_SHA1_96,
1701 "SHA2-256-128": ei.IPSEC_API_INTEG_ALG_SHA_256_128,
1702 "SHA2-384-192": ei.IPSEC_API_INTEG_ALG_SHA_384_192,
1703 "SHA2-512-256": ei.IPSEC_API_INTEG_ALG_SHA_512_256,
1704 }
Filip Tehlar4f42a712020-07-01 08:56:59 +00001705
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001706 dpd_disabled = True if "dpd_disabled" not in params else params["dpd_disabled"]
Filip Tehlar2008e312020-11-09 13:23:24 +00001707 if dpd_disabled:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001708 self.vapi.cli("ikev2 dpd disable")
1709 self.del_sa_from_responder = (
1710 False
1711 if "del_sa_from_responder" not in params
1712 else params["del_sa_from_responder"]
1713 )
1714 i_natt = False if "i_natt" not in params else params["i_natt"]
1715 r_natt = False if "r_natt" not in params else params["r_natt"]
1716 self.p = Profile(self, "pr1")
1717 self.ip6 = False if "ip6" not in params else params["ip6"]
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001718
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001719 if "auth" in params and params["auth"] == "rsa-sig":
1720 auth_method = "rsa-sig"
Klement Sekerab23ffd72021-05-31 16:08:53 +02001721 work_dir = f"{config.vpp_ws_dir}/src/plugins/ikev2/test/certs/"
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001722 self.vapi.ikev2_set_local_key(key_file=work_dir + params["server-key"])
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001723
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001724 client_file = work_dir + params["client-cert"]
1725 server_pem = open(work_dir + params["server-cert"]).read()
1726 client_priv = open(work_dir + params["client-key"]).read()
1727 client_priv = load_pem_private_key(
1728 str.encode(client_priv), None, default_backend()
1729 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001730 self.peer_cert = x509.load_pem_x509_certificate(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001731 str.encode(server_pem), default_backend()
1732 )
1733 self.p.add_auth(method="rsa-sig", data=str.encode(client_file))
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001734 auth_data = None
1735 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001736 auth_data = b"$3cr3tpa$$w0rd"
1737 self.p.add_auth(method="shared-key", data=auth_data)
1738 auth_method = "shared-key"
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001739 client_priv = None
1740
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001741 is_init = True if "is_initiator" not in params else params["is_initiator"]
1742 self.no_idr_auth = params.get("no_idr_in_auth", False)
Filip Tehlare7c83962020-09-23 11:20:12 +00001743
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001744 idr = {"id_type": "fqdn", "data": b"vpp.home"}
1745 idi = {"id_type": "fqdn", "data": b"roadwarrior.example.com"}
1746 r_id = self.idr = idr["data"]
1747 i_id = self.idi = idi["data"]
Filip Tehlare7c83962020-09-23 11:20:12 +00001748 if is_init:
Benoît Gannec7cceee2021-09-28 11:19:37 +02001749 # scapy is initiator, VPP is responder
Filip Tehlare7c83962020-09-23 11:20:12 +00001750 self.p.add_local_id(**idr)
1751 self.p.add_remote_id(**idi)
Benoît Gannec7cceee2021-09-28 11:19:37 +02001752 if self.no_idr_auth:
1753 r_id = None
Filip Tehlare7c83962020-09-23 11:20:12 +00001754 else:
Benoît Gannec7cceee2021-09-28 11:19:37 +02001755 # VPP is initiator, scapy is responder
Filip Tehlare7c83962020-09-23 11:20:12 +00001756 self.p.add_local_id(**idi)
Benoît Gannec7cceee2021-09-28 11:19:37 +02001757 if not self.no_idr_auth:
1758 self.p.add_remote_id(**idr)
Filip Tehlare7c83962020-09-23 11:20:12 +00001759
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001760 loc_ts = (
1761 {"start_addr": "10.10.10.0", "end_addr": "10.10.10.255"}
1762 if "loc_ts" not in params
1763 else params["loc_ts"]
1764 )
1765 rem_ts = (
1766 {"start_addr": "10.0.0.0", "end_addr": "10.0.0.255"}
1767 if "rem_ts" not in params
1768 else params["rem_ts"]
1769 )
Filip Tehlar84962d12020-09-08 06:08:05 +00001770 self.p.add_local_ts(**loc_ts)
1771 self.p.add_remote_ts(**rem_ts)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001772 if "responder" in params:
1773 self.p.add_responder(params["responder"])
1774 if "ike_transforms" in params:
1775 self.p.add_ike_transforms(params["ike_transforms"])
1776 if "esp_transforms" in params:
1777 self.p.add_esp_transforms(params["esp_transforms"])
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001778
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001779 udp_encap = False if "udp_encap" not in params else params["udp_encap"]
Filip Tehlar67b8a7f2020-11-06 11:00:42 +00001780 if udp_encap:
1781 self.p.set_udp_encap(True)
1782
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001783 if "responder_hostname" in params:
1784 hn = params["responder_hostname"]
Filip Tehlaraf2cc642021-02-22 16:15:51 +00001785 self.p.add_responder_hostname(hn)
1786
1787 # configure static dns record
1788 self.vapi.dns_name_server_add_del(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001789 is_ip6=0, is_add=1, server_address=IPv4Address("8.8.8.8").packed
1790 )
Filip Tehlaraf2cc642021-02-22 16:15:51 +00001791 self.vapi.dns_enable_disable(enable=1)
1792
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001793 cmd = "dns cache add {} {}".format(hn["hostname"], self.pg0.remote_ip4)
Filip Tehlaraf2cc642021-02-22 16:15:51 +00001794 self.vapi.cli(cmd)
1795
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001796 self.sa = IKEv2SA(
1797 self,
1798 i_id=i_id,
1799 r_id=r_id,
1800 is_initiator=is_init,
1801 id_type=self.p.local_id["id_type"],
1802 i_natt=i_natt,
1803 r_natt=r_natt,
1804 priv_key=client_priv,
1805 auth_method=auth_method,
1806 nonce=params.get("nonce"),
1807 auth_data=auth_data,
1808 udp_encap=udp_encap,
1809 local_ts=self.p.remote_ts,
1810 remote_ts=self.p.local_ts,
1811 )
Benoît Gannec7cceee2021-09-28 11:19:37 +02001812
Filip Tehlar68ad6252020-10-30 05:28:11 +00001813 if is_init:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001814 ike_crypto = (
1815 ("AES-CBC", 32) if "ike-crypto" not in params else params["ike-crypto"]
1816 )
1817 ike_integ = (
1818 "HMAC-SHA1-96" if "ike-integ" not in params else params["ike-integ"]
1819 )
1820 ike_dh = "2048MODPgr" if "ike-dh" not in params else params["ike-dh"]
Filip Tehlar4f42a712020-07-01 08:56:59 +00001821
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001822 esp_crypto = (
1823 ("AES-CBC", 32) if "esp-crypto" not in params else params["esp-crypto"]
1824 )
1825 esp_integ = (
1826 "HMAC-SHA1-96" if "esp-integ" not in params else params["esp-integ"]
1827 )
Filip Tehlar4f42a712020-07-01 08:56:59 +00001828
Filip Tehlar68ad6252020-10-30 05:28:11 +00001829 self.sa.set_ike_props(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001830 crypto=ike_crypto[0],
1831 crypto_key_len=ike_crypto[1],
1832 integ=ike_integ,
1833 prf="PRF_HMAC_SHA2_256",
1834 dh=ike_dh,
1835 )
Filip Tehlar68ad6252020-10-30 05:28:11 +00001836 self.sa.set_esp_props(
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001837 crypto=esp_crypto[0], crypto_key_len=esp_crypto[1], integ=esp_integ
1838 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00001839
1840
Andrew Yourtchenkobc378782023-09-26 16:01:21 +02001841@unittest.skipIf("ikev2" in config.excluded_plugins, "Exclude IKEv2 plugin tests")
Filip Tehlar459d17b2020-07-06 15:40:08 +00001842class TestApi(VppTestCase):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001843 """Test IKEV2 API"""
1844
Filip Tehlar459d17b2020-07-06 15:40:08 +00001845 @classmethod
1846 def setUpClass(cls):
1847 super(TestApi, cls).setUpClass()
1848
1849 @classmethod
1850 def tearDownClass(cls):
1851 super(TestApi, cls).tearDownClass()
1852
1853 def tearDown(self):
1854 super(TestApi, self).tearDown()
1855 self.p1.remove_vpp_config()
1856 self.p2.remove_vpp_config()
1857 r = self.vapi.ikev2_profile_dump()
1858 self.assertEqual(len(r), 0)
1859
1860 def configure_profile(self, cfg):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001861 p = Profile(self, cfg["name"])
1862 p.add_local_id(id_type=cfg["loc_id"][0], data=cfg["loc_id"][1])
1863 p.add_remote_id(id_type=cfg["rem_id"][0], data=cfg["rem_id"][1])
1864 p.add_local_ts(**cfg["loc_ts"])
1865 p.add_remote_ts(**cfg["rem_ts"])
1866 p.add_responder(cfg["responder"])
1867 p.add_ike_transforms(cfg["ike_ts"])
1868 p.add_esp_transforms(cfg["esp_ts"])
1869 p.add_auth(**cfg["auth"])
1870 p.set_udp_encap(cfg["udp_encap"])
1871 p.set_ipsec_over_udp_port(cfg["ipsec_over_udp_port"])
1872 if "lifetime_data" in cfg:
1873 p.set_lifetime_data(cfg["lifetime_data"])
1874 if "tun_itf" in cfg:
1875 p.set_tunnel_interface(cfg["tun_itf"])
1876 if "natt_disabled" in cfg and cfg["natt_disabled"]:
Filip Tehlard7fc12f2020-10-30 04:47:44 +00001877 p.disable_natt()
Filip Tehlar459d17b2020-07-06 15:40:08 +00001878 p.add_vpp_config()
1879 return p
1880
1881 def test_profile_api(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001882 """test profile dump API"""
Filip Tehlar84962d12020-09-08 06:08:05 +00001883 loc_ts4 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001884 "proto": 8,
1885 "start_port": 1,
1886 "end_port": 19,
1887 "start_addr": "3.3.3.2",
1888 "end_addr": "3.3.3.3",
1889 }
Filip Tehlar84962d12020-09-08 06:08:05 +00001890 rem_ts4 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001891 "proto": 9,
1892 "start_port": 10,
1893 "end_port": 119,
1894 "start_addr": "4.5.76.80",
1895 "end_addr": "2.3.4.6",
1896 }
Filip Tehlar459d17b2020-07-06 15:40:08 +00001897
Filip Tehlar84962d12020-09-08 06:08:05 +00001898 loc_ts6 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001899 "proto": 8,
1900 "start_port": 1,
1901 "end_port": 19,
1902 "start_addr": "ab::1",
1903 "end_addr": "ab::4",
1904 }
Filip Tehlar84962d12020-09-08 06:08:05 +00001905 rem_ts6 = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001906 "proto": 9,
1907 "start_port": 10,
1908 "end_port": 119,
1909 "start_addr": "cd::12",
1910 "end_addr": "cd::13",
1911 }
Filip Tehlar84962d12020-09-08 06:08:05 +00001912
Filip Tehlar459d17b2020-07-06 15:40:08 +00001913 conf = {
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001914 "p1": {
1915 "name": "p1",
1916 "natt_disabled": True,
1917 "loc_id": ("fqdn", b"vpp.home"),
1918 "rem_id": ("fqdn", b"roadwarrior.example.com"),
1919 "loc_ts": loc_ts4,
1920 "rem_ts": rem_ts4,
1921 "responder": {"sw_if_index": 0, "addr": "5.6.7.8"},
1922 "ike_ts": {
1923 "crypto_alg": 20,
1924 "crypto_key_size": 32,
1925 "integ_alg": 0,
1926 "dh_group": 1,
1927 },
1928 "esp_ts": {"crypto_alg": 13, "crypto_key_size": 24, "integ_alg": 2},
1929 "auth": {"method": "shared-key", "data": b"sharedkeydata"},
1930 "udp_encap": True,
1931 "ipsec_over_udp_port": 4501,
1932 "lifetime_data": {
1933 "lifetime": 123,
1934 "lifetime_maxdata": 20192,
1935 "lifetime_jitter": 9,
1936 "handover": 132,
1937 },
Filip Tehlar459d17b2020-07-06 15:40:08 +00001938 },
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001939 "p2": {
1940 "name": "p2",
1941 "loc_id": ("ip4-addr", b"192.168.2.1"),
1942 "rem_id": ("ip6-addr", b"abcd::1"),
1943 "loc_ts": loc_ts6,
1944 "rem_ts": rem_ts6,
1945 "responder": {"sw_if_index": 4, "addr": "def::10"},
1946 "ike_ts": {
1947 "crypto_alg": 12,
1948 "crypto_key_size": 16,
1949 "integ_alg": 3,
1950 "dh_group": 3,
1951 },
1952 "esp_ts": {"crypto_alg": 9, "crypto_key_size": 24, "integ_alg": 4},
1953 "auth": {"method": "shared-key", "data": b"sharedkeydata"},
1954 "udp_encap": False,
1955 "ipsec_over_udp_port": 4600,
1956 "tun_itf": 0,
1957 },
Filip Tehlar459d17b2020-07-06 15:40:08 +00001958 }
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001959 self.p1 = self.configure_profile(conf["p1"])
1960 self.p2 = self.configure_profile(conf["p2"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001961
1962 r = self.vapi.ikev2_profile_dump()
1963 self.assertEqual(len(r), 2)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001964 self.verify_profile(r[0].profile, conf["p1"])
1965 self.verify_profile(r[1].profile, conf["p2"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001966
1967 def verify_id(self, api_id, cfg_id):
1968 self.assertEqual(api_id.type, IDType.value(cfg_id[0]))
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001969 self.assertEqual(bytes(api_id.data, "ascii"), cfg_id[1])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001970
1971 def verify_ts(self, api_ts, cfg_ts):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001972 self.assertEqual(api_ts.protocol_id, cfg_ts["proto"])
1973 self.assertEqual(api_ts.start_port, cfg_ts["start_port"])
1974 self.assertEqual(api_ts.end_port, cfg_ts["end_port"])
1975 self.assertEqual(api_ts.start_addr, ip_address(text_type(cfg_ts["start_addr"])))
1976 self.assertEqual(api_ts.end_addr, ip_address(text_type(cfg_ts["end_addr"])))
Filip Tehlar459d17b2020-07-06 15:40:08 +00001977
1978 def verify_responder(self, api_r, cfg_r):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001979 self.assertEqual(api_r.sw_if_index, cfg_r["sw_if_index"])
1980 self.assertEqual(api_r.addr, ip_address(cfg_r["addr"]))
Filip Tehlar459d17b2020-07-06 15:40:08 +00001981
1982 def verify_transforms(self, api_ts, cfg_ts):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001983 self.assertEqual(api_ts.crypto_alg, cfg_ts["crypto_alg"])
1984 self.assertEqual(api_ts.crypto_key_size, cfg_ts["crypto_key_size"])
1985 self.assertEqual(api_ts.integ_alg, cfg_ts["integ_alg"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001986
1987 def verify_ike_transforms(self, api_ts, cfg_ts):
1988 self.verify_transforms(api_ts, cfg_ts)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001989 self.assertEqual(api_ts.dh_group, cfg_ts["dh_group"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00001990
1991 def verify_esp_transforms(self, api_ts, cfg_ts):
1992 self.verify_transforms(api_ts, cfg_ts)
1993
1994 def verify_auth(self, api_auth, cfg_auth):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02001995 self.assertEqual(api_auth.method, AuthMethod.value(cfg_auth["method"]))
1996 self.assertEqual(api_auth.data, cfg_auth["data"])
1997 self.assertEqual(api_auth.data_len, len(cfg_auth["data"]))
Filip Tehlar459d17b2020-07-06 15:40:08 +00001998
1999 def verify_lifetime_data(self, p, ld):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002000 self.assertEqual(p.lifetime, ld["lifetime"])
2001 self.assertEqual(p.lifetime_maxdata, ld["lifetime_maxdata"])
2002 self.assertEqual(p.lifetime_jitter, ld["lifetime_jitter"])
2003 self.assertEqual(p.handover, ld["handover"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00002004
2005 def verify_profile(self, ap, cp):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002006 self.assertEqual(ap.name, cp["name"])
2007 self.assertEqual(ap.udp_encap, cp["udp_encap"])
2008 self.verify_id(ap.loc_id, cp["loc_id"])
2009 self.verify_id(ap.rem_id, cp["rem_id"])
2010 self.verify_ts(ap.loc_ts, cp["loc_ts"])
2011 self.verify_ts(ap.rem_ts, cp["rem_ts"])
2012 self.verify_responder(ap.responder, cp["responder"])
2013 self.verify_ike_transforms(ap.ike_ts, cp["ike_ts"])
2014 self.verify_esp_transforms(ap.esp_ts, cp["esp_ts"])
2015 self.verify_auth(ap.auth, cp["auth"])
2016 natt_dis = False if "natt_disabled" not in cp else cp["natt_disabled"]
Filip Tehlard7fc12f2020-10-30 04:47:44 +00002017 self.assertTrue(natt_dis == ap.natt_disabled)
2018
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002019 if "lifetime_data" in cp:
2020 self.verify_lifetime_data(ap, cp["lifetime_data"])
2021 self.assertEqual(ap.ipsec_over_udp_port, cp["ipsec_over_udp_port"])
2022 if "tun_itf" in cp:
2023 self.assertEqual(ap.tun_itf, cp["tun_itf"])
Filip Tehlar459d17b2020-07-06 15:40:08 +00002024 else:
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002025 self.assertEqual(ap.tun_itf, 0xFFFFFFFF)
Filip Tehlar459d17b2020-07-06 15:40:08 +00002026
2027
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002028@tag_fixme_vpp_workers
Filip Tehlar027d8132020-12-04 17:38:11 +00002029class TestResponderBehindNAT(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002030 """test responder - responder behind NAT"""
Filip Tehlar027d8132020-12-04 17:38:11 +00002031
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002032 IKE_NODE_SUFFIX = "ip4-natt"
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002033
Filip Tehlar027d8132020-12-04 17:38:11 +00002034 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002035 self.config_params({"r_natt": True})
Filip Tehlar027d8132020-12-04 17:38:11 +00002036
2037
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002038@tag_fixme_vpp_workers
Andrew Yourtchenko9987d472024-07-02 18:02:09 +02002039@tag_fixme_ubuntu2204
Filip Tehlar18107c92020-12-01 14:51:09 +00002040class TestInitiatorNATT(TemplateInitiator, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002041 """test ikev2 initiator - NAT traversal (intitiator behind NAT)"""
Filip Tehlar18107c92020-12-01 14:51:09 +00002042
2043 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002044 self.config_params(
2045 {
2046 "i_natt": True,
2047 "is_initiator": False, # seen from test case perspective
2048 # thus vpp is initiator
2049 "responder": {
2050 "sw_if_index": self.pg0.sw_if_index,
2051 "addr": self.pg0.remote_ip4,
2052 },
2053 "ike-crypto": ("AES-GCM-16ICV", 32),
2054 "ike-integ": "NULL",
2055 "ike-dh": "3072MODPgr",
2056 "ike_transforms": {
2057 "crypto_alg": 20, # "aes-gcm-16"
2058 "crypto_key_size": 256,
2059 "dh_group": 15, # "modp-3072"
2060 },
2061 "esp_transforms": {
2062 "crypto_alg": 12, # "aes-cbc"
2063 "crypto_key_size": 256,
2064 # "hmac-sha2-256-128"
2065 "integ_alg": 12,
2066 },
2067 }
2068 )
Filip Tehlar18107c92020-12-01 14:51:09 +00002069
2070
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002071@tag_fixme_vpp_workers
Andrew Yourtchenko9987d472024-07-02 18:02:09 +02002072@tag_fixme_ubuntu2204
Filip Tehlare7c83962020-09-23 11:20:12 +00002073class TestInitiatorPsk(TemplateInitiator, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002074 """test ikev2 initiator - pre shared key auth"""
Filip Tehlaredf29002020-10-10 04:39:11 +00002075
Filip Tehlare7c83962020-09-23 11:20:12 +00002076 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002077 self.config_params(
2078 {
2079 "is_initiator": False, # seen from test case perspective
2080 # thus vpp is initiator
2081 "ike-crypto": ("AES-GCM-16ICV", 32),
2082 "ike-integ": "NULL",
2083 "ike-dh": "3072MODPgr",
2084 "ike_transforms": {
2085 "crypto_alg": 20, # "aes-gcm-16"
2086 "crypto_key_size": 256,
2087 "dh_group": 15, # "modp-3072"
2088 },
2089 "esp_transforms": {
2090 "crypto_alg": 12, # "aes-cbc"
2091 "crypto_key_size": 256,
2092 # "hmac-sha2-256-128"
2093 "integ_alg": 12,
2094 },
2095 "responder_hostname": {
2096 "hostname": "vpp.responder.org",
2097 "sw_if_index": self.pg0.sw_if_index,
2098 },
2099 }
2100 )
Filip Tehlare7c83962020-09-23 11:20:12 +00002101
2102
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002103@tag_fixme_vpp_workers
Andrew Yourtchenko9987d472024-07-02 18:02:09 +02002104@tag_fixme_ubuntu2204
Filip Tehlar38340fa2020-11-19 21:34:48 +00002105class TestInitiatorRequestWindowSize(TestInitiatorPsk):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002106 """test initiator - request window size (1)"""
Filip Tehlar38340fa2020-11-19 21:34:48 +00002107
2108 def rekey_respond(self, req, update_child_sa_data):
2109 ih = self.get_ike_header(req)
2110 plain = self.sa.hmac_and_decrypt(ih)
2111 sa = ikev2.IKEv2_payload_SA(plain)
2112 if update_child_sa_data:
2113 prop = sa[ikev2.IKEv2_payload_Proposal]
2114 self.sa.i_nonce = sa[ikev2.IKEv2_payload_Nonce].load
2115 self.sa.r_nonce = self.sa.i_nonce
2116 self.sa.child_sas[0].ispi = prop.SPI
2117 self.sa.child_sas[0].rspi = prop.SPI
2118 self.sa.calc_child_keys()
2119
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002120 header = ikev2.IKEv2(
2121 init_SPI=self.sa.ispi,
2122 resp_SPI=self.sa.rspi,
2123 flags="Response",
2124 exch_type=36,
2125 id=ih.id,
2126 next_payload="Encrypted",
2127 )
2128 resp = self.encrypt_ike_msg(header, sa, "SA")
2129 packet = self.create_packet(
2130 self.pg0, resp, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
2131 )
Filip Tehlar38340fa2020-11-19 21:34:48 +00002132 self.send_and_assert_no_replies(self.pg0, packet)
2133
2134 def test_initiator(self):
2135 super(TestInitiatorRequestWindowSize, self).test_initiator()
2136 self.pg0.enable_capture()
2137 self.pg_start()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002138 ispi = int.from_bytes(self.sa.child_sas[0].ispi, "little")
Filip Tehlar38340fa2020-11-19 21:34:48 +00002139 self.vapi.ikev2_initiate_rekey_child_sa(ispi=ispi)
2140 self.vapi.ikev2_initiate_rekey_child_sa(ispi=ispi)
2141 capture = self.pg0.get_capture(2)
2142
2143 # reply in reverse order
2144 self.rekey_respond(capture[1], True)
2145 self.rekey_respond(capture[0], False)
2146
2147 # verify that only the second request was accepted
2148 self.verify_ike_sas()
Denys Haryachyyf40a3542024-01-24 16:31:47 +02002149 self.verify_ike_sas_v2()
Filip Tehlar38340fa2020-11-19 21:34:48 +00002150 self.verify_ipsec_sas(is_rekey=True)
2151
2152
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002153@tag_fixme_vpp_workers
Andrew Yourtchenko9987d472024-07-02 18:02:09 +02002154@tag_fixme_ubuntu2204
Filip Tehlar68ad6252020-10-30 05:28:11 +00002155class TestInitiatorRekey(TestInitiatorPsk):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002156 """test ikev2 initiator - rekey"""
Filip Tehlar68ad6252020-10-30 05:28:11 +00002157
2158 def rekey_from_initiator(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002159 ispi = int.from_bytes(self.sa.child_sas[0].ispi, "little")
Filip Tehlar68ad6252020-10-30 05:28:11 +00002160 self.pg0.enable_capture()
2161 self.pg_start()
2162 self.vapi.ikev2_initiate_rekey_child_sa(ispi=ispi)
2163 capture = self.pg0.get_capture(1)
2164 ih = self.get_ike_header(capture[0])
2165 self.assertEqual(ih.exch_type, 36) # CHILD_SA
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002166 self.assertNotIn("Response", ih.flags)
2167 self.assertIn("Initiator", ih.flags)
Filip Tehlar68ad6252020-10-30 05:28:11 +00002168 plain = self.sa.hmac_and_decrypt(ih)
2169 sa = ikev2.IKEv2_payload_SA(plain)
2170 prop = sa[ikev2.IKEv2_payload_Proposal]
Filip Tehlar68ad6252020-10-30 05:28:11 +00002171 self.sa.i_nonce = sa[ikev2.IKEv2_payload_Nonce].load
2172 self.sa.r_nonce = self.sa.i_nonce
2173 # update new responder SPI
2174 self.sa.child_sas[0].ispi = prop.SPI
2175 self.sa.child_sas[0].rspi = prop.SPI
2176 self.sa.calc_child_keys()
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002177 header = ikev2.IKEv2(
2178 init_SPI=self.sa.ispi,
2179 resp_SPI=self.sa.rspi,
2180 flags="Response",
2181 exch_type=36,
2182 id=ih.id,
2183 next_payload="Encrypted",
2184 )
2185 resp = self.encrypt_ike_msg(header, sa, "SA")
2186 packet = self.create_packet(
2187 self.pg0, resp, self.sa.sport, self.sa.dport, self.sa.natt, self.ip6
2188 )
Filip Tehlar68ad6252020-10-30 05:28:11 +00002189 self.send_and_assert_no_replies(self.pg0, packet)
2190
2191 def test_initiator(self):
2192 super(TestInitiatorRekey, self).test_initiator()
2193 self.rekey_from_initiator()
2194 self.verify_ike_sas()
Denys Haryachyyf40a3542024-01-24 16:31:47 +02002195 self.verify_ike_sas_v2()
Filip Tehlar68ad6252020-10-30 05:28:11 +00002196 self.verify_ipsec_sas(is_rekey=True)
2197
2198
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002199@tag_fixme_vpp_workers
Andrew Yourtchenko9987d472024-07-02 18:02:09 +02002200@tag_fixme_ubuntu2204
Filip Tehlaredf29002020-10-10 04:39:11 +00002201class TestInitiatorDelSAFromResponder(TemplateInitiator, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002202 """test ikev2 initiator - delete IKE SA from responder"""
Filip Tehlaredf29002020-10-10 04:39:11 +00002203
2204 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002205 self.config_params(
2206 {
2207 "del_sa_from_responder": True,
2208 "is_initiator": False, # seen from test case perspective
2209 # thus vpp is initiator
2210 "responder": {
2211 "sw_if_index": self.pg0.sw_if_index,
2212 "addr": self.pg0.remote_ip4,
2213 },
2214 "ike-crypto": ("AES-GCM-16ICV", 32),
2215 "ike-integ": "NULL",
2216 "ike-dh": "3072MODPgr",
2217 "ike_transforms": {
2218 "crypto_alg": 20, # "aes-gcm-16"
2219 "crypto_key_size": 256,
2220 "dh_group": 15, # "modp-3072"
2221 },
2222 "esp_transforms": {
2223 "crypto_alg": 12, # "aes-cbc"
2224 "crypto_key_size": 256,
2225 # "hmac-sha2-256-128"
2226 "integ_alg": 12,
2227 },
2228 "no_idr_in_auth": True,
2229 }
2230 )
Filip Tehlaredf29002020-10-10 04:39:11 +00002231
2232
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002233@tag_fixme_vpp_workers
Filip Tehlar027d8132020-12-04 17:38:11 +00002234class TestResponderInitBehindNATT(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002235 """test ikev2 responder - initiator behind NAT"""
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002236
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002237 IKE_NODE_SUFFIX = "ip4-natt"
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002238
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002239 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002240 self.config_params({"i_natt": True})
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002241
2242
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002243@tag_fixme_vpp_workers
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002244class TestResponderPsk(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002245 """test ikev2 responder - pre shared key auth"""
2246
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002247 def config_tc(self):
2248 self.config_params()
2249
2250
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002251@tag_fixme_vpp_workers
Filip Tehlar2008e312020-11-09 13:23:24 +00002252class TestResponderDpd(TestResponderPsk):
2253 """
2254 Dead peer detection test
2255 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002256
Filip Tehlar2008e312020-11-09 13:23:24 +00002257 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002258 self.config_params({"dpd_disabled": False})
Filip Tehlar2008e312020-11-09 13:23:24 +00002259
2260 def tearDown(self):
2261 pass
2262
2263 def test_responder(self):
2264 self.vapi.ikev2_profile_set_liveness(period=2, max_retries=1)
2265 super(TestResponderDpd, self).test_responder()
2266 self.pg0.enable_capture()
2267 self.pg_start()
2268 # capture empty request but don't reply
2269 capture = self.pg0.get_capture(expected_count=1, timeout=5)
2270 ih = self.get_ike_header(capture[0])
2271 self.assertEqual(ih.exch_type, 37) # INFORMATIONAL
2272 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002273 self.assertEqual(plain, b"")
Filip Tehlar2008e312020-11-09 13:23:24 +00002274 # wait for SA expiration
2275 time.sleep(3)
2276 ike_sas = self.vapi.ikev2_sa_dump()
2277 self.assertEqual(len(ike_sas), 0)
Denys Haryachyyf40a3542024-01-24 16:31:47 +02002278 ike_sas = self.vapi.ikev2_sa_v2_dump()
2279 self.assertEqual(len(ike_sas), 0)
Filip Tehlar2008e312020-11-09 13:23:24 +00002280 ipsec_sas = self.vapi.ipsec_sa_dump()
2281 self.assertEqual(len(ipsec_sas), 0)
2282
2283
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002284@tag_fixme_vpp_workers
Filip Tehlar68ad6252020-10-30 05:28:11 +00002285class TestResponderRekey(TestResponderPsk):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002286 """test ikev2 responder - rekey"""
Filip Tehlar68ad6252020-10-30 05:28:11 +00002287
Atzm Watanabec65921f2022-08-12 14:29:31 +09002288 WITH_KEX = False
2289
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002290 def send_rekey_from_initiator(self):
Atzm Watanabec65921f2022-08-12 14:29:31 +09002291 if self.WITH_KEX:
2292 self.sa.generate_dh_data()
2293 packet = self.create_rekey_request(kex=self.WITH_KEX)
Filip Tehlar68ad6252020-10-30 05:28:11 +00002294 self.pg0.add_stream(packet)
2295 self.pg0.enable_capture()
2296 self.pg_start()
2297 capture = self.pg0.get_capture(1)
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002298 return capture
2299
2300 def process_rekey_response(self, capture):
Filip Tehlar68ad6252020-10-30 05:28:11 +00002301 ih = self.get_ike_header(capture[0])
2302 plain = self.sa.hmac_and_decrypt(ih)
2303 sa = ikev2.IKEv2_payload_SA(plain)
2304 prop = sa[ikev2.IKEv2_payload_Proposal]
Filip Tehlar68ad6252020-10-30 05:28:11 +00002305 self.sa.r_nonce = sa[ikev2.IKEv2_payload_Nonce].load
2306 # update new responder SPI
2307 self.sa.child_sas[0].rspi = prop.SPI
Atzm Watanabec65921f2022-08-12 14:29:31 +09002308 if self.WITH_KEX:
2309 self.sa.r_dh_data = sa[ikev2.IKEv2_payload_KE].load
2310 self.sa.complete_dh_data()
2311 self.sa.calc_child_keys(kex=self.WITH_KEX)
Filip Tehlar68ad6252020-10-30 05:28:11 +00002312
2313 def test_responder(self):
2314 super(TestResponderRekey, self).test_responder()
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002315 self.process_rekey_response(self.send_rekey_from_initiator())
Filip Tehlar68ad6252020-10-30 05:28:11 +00002316 self.verify_ike_sas()
Denys Haryachyyf40a3542024-01-24 16:31:47 +02002317 self.verify_ike_sas_v2()
Filip Tehlar68ad6252020-10-30 05:28:11 +00002318 self.verify_ipsec_sas(is_rekey=True)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002319 self.assert_counter(1, "rekey_req", "ip4")
Filip Tehlar68d27532021-01-25 10:09:27 +00002320 r = self.vapi.ikev2_sa_dump()
2321 self.assertEqual(r[0].sa.stats.n_rekey_req, 1)
Denys Haryachyyf40a3542024-01-24 16:31:47 +02002322 r = self.vapi.ikev2_sa_v2_dump()
2323 self.assertEqual(r[0].sa.stats.n_rekey_req, 1)
Filip Tehlar68ad6252020-10-30 05:28:11 +00002324
2325
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002326@tag_fixme_vpp_workers
2327class TestResponderRekeyRepeat(TestResponderRekey):
2328 """test ikev2 responder - rekey repeat"""
2329
2330 def test_responder(self):
2331 super(TestResponderRekeyRepeat, self).test_responder()
2332 # rekey request is not accepted until old IPsec SA is expired
2333 capture = self.send_rekey_from_initiator()
2334 ih = self.get_ike_header(capture[0])
2335 plain = self.sa.hmac_and_decrypt(ih)
2336 notify = ikev2.IKEv2_payload_Notify(plain)
2337 self.assertEqual(notify.type, 43)
2338 self.assertEqual(len(self.vapi.ipsec_sa_dump()), 3)
2339 # rekey request is accepted after old IPsec SA was expired
2340 for _ in range(50):
2341 if len(self.vapi.ipsec_sa_dump()) != 3:
2342 break
2343 time.sleep(0.2)
2344 else:
2345 self.fail("old IPsec SA not expired")
2346 self.process_rekey_response(self.send_rekey_from_initiator())
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002347 self.verify_ike_sas()
Denys Haryachyyf40a3542024-01-24 16:31:47 +02002348 self.verify_ike_sas_v2()
Atzm Watanabe7e6ffba2022-08-09 14:00:03 +09002349 self.verify_ipsec_sas(sa_count=3)
2350
2351
Atzm Watanabec65921f2022-08-12 14:29:31 +09002352@tag_fixme_vpp_workers
2353class TestResponderRekeyKEX(TestResponderRekey):
2354 """test ikev2 responder - rekey with key exchange"""
2355
2356 WITH_KEX = True
2357
2358
2359@tag_fixme_vpp_workers
2360class TestResponderRekeyRepeatKEX(TestResponderRekeyRepeat):
2361 """test ikev2 responder - rekey repeat with key exchange"""
2362
2363 WITH_KEX = True
2364
2365
Atzm Watanabed4f405a2022-08-18 17:57:53 +09002366@tag_fixme_vpp_workers
2367class TestResponderRekeySA(TestResponderPsk):
2368 """test ikev2 responder - rekey IKE SA"""
2369
2370 def send_rekey_from_initiator(self, newsa):
2371 packet = self.create_sa_rekey_request(
2372 spi=newsa.ispi,
2373 dh_pub_key=newsa.my_dh_pub_key,
2374 nonce=newsa.i_nonce,
2375 )
2376 self.pg0.add_stream(packet)
2377 self.pg0.enable_capture()
2378 self.pg_start()
2379 capture = self.pg0.get_capture(1)
2380 return capture
2381
2382 def process_rekey_response(self, newsa, capture):
2383 ih = self.get_ike_header(capture[0])
2384 plain = self.sa.hmac_and_decrypt(ih)
2385 sa = ikev2.IKEv2_payload_SA(plain)
2386 prop = sa[ikev2.IKEv2_payload_Proposal]
2387 newsa.rspi = prop.SPI
2388 newsa.r_nonce = sa[ikev2.IKEv2_payload_Nonce].load
2389 newsa.r_dh_data = sa[ikev2.IKEv2_payload_KE].load
2390 newsa.complete_dh_data()
2391 newsa.calc_keys(sk_d=self.sa.sk_d)
2392 newsa.child_sas = self.sa.child_sas
2393 self.sa.child_sas = []
2394
2395 def test_responder(self):
2396 super(TestResponderRekeySA, self).test_responder()
2397 newsa = self.sa.clone(self, spi=os.urandom(8))
2398 newsa.generate_dh_data()
2399 capture = self.send_rekey_from_initiator(newsa)
2400 self.process_rekey_response(newsa, capture)
2401 self.verify_ike_sas(is_rekey=True)
2402 self.assert_counter(1, "rekey_req", "ip4")
2403 r = self.vapi.ikev2_sa_dump()
2404 self.assertEqual(r[1].sa.stats.n_rekey_req, 1)
2405 self.initiate_del_sa_from_initiator()
2406 self.sa = newsa
2407 self.verify_ike_sas()
2408
2409
Dave Wallace670724c2022-09-20 21:52:18 -04002410@tag_fixme_ubuntu2204
2411@tag_fixme_debian11
Filip Tehlard28196f2021-01-27 18:08:21 +00002412class TestResponderVrf(TestResponderPsk, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002413 """test ikev2 responder - non-default table id"""
Filip Tehlard28196f2021-01-27 18:08:21 +00002414
2415 @classmethod
2416 def setUpClass(cls):
2417 import scapy.contrib.ikev2 as _ikev2
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002418
2419 globals()["ikev2"] = _ikev2
Filip Tehlard28196f2021-01-27 18:08:21 +00002420 super(IkePeer, cls).setUpClass()
Andrew Yourtchenko9987d472024-07-02 18:02:09 +02002421 if (is_distro_debian11 == True) and not hasattr(cls, "vpp"):
Dave Wallace670724c2022-09-20 21:52:18 -04002422 return
Filip Tehlard28196f2021-01-27 18:08:21 +00002423 cls.create_pg_interfaces(range(1))
2424 cls.vapi.cli("ip table add 1")
2425 cls.vapi.cli("set interface ip table pg0 1")
2426 for i in cls.pg_interfaces:
2427 i.admin_up()
2428 i.config_ip4()
2429 i.resolve_arp()
2430 i.config_ip6()
2431 i.resolve_ndp()
2432
2433 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002434 self.config_params({"dpd_disabled": False})
Filip Tehlard28196f2021-01-27 18:08:21 +00002435
2436 def test_responder(self):
2437 self.vapi.ikev2_profile_set_liveness(period=2, max_retries=1)
2438 super(TestResponderVrf, self).test_responder()
2439 self.pg0.enable_capture()
2440 self.pg_start()
2441 capture = self.pg0.get_capture(expected_count=1, timeout=5)
2442 ih = self.get_ike_header(capture[0])
2443 self.assertEqual(ih.exch_type, 37) # INFORMATIONAL
2444 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002445 self.assertEqual(plain, b"")
Filip Tehlard28196f2021-01-27 18:08:21 +00002446
2447
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002448@tag_fixme_vpp_workers
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002449class TestResponderRsaSign(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002450 """test ikev2 responder - cert based auth"""
2451
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002452 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002453 self.config_params(
2454 {
2455 "udp_encap": True,
2456 "auth": "rsa-sig",
2457 "server-key": "server-key.pem",
2458 "client-key": "client-key.pem",
2459 "client-cert": "client-cert.pem",
2460 "server-cert": "server-cert.pem",
2461 }
2462 )
Filip Tehlarbfeae8c2020-06-23 20:35:58 +00002463
Filip Tehlar4f42a712020-07-01 08:56:59 +00002464
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002465@tag_fixme_vpp_workers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002466class Test_IKE_AES_CBC_128_SHA256_128_MODP2048_ESP_AES_CBC_192_SHA_384_192(
2467 TemplateResponder, Ikev2Params
2468):
Filip Tehlar4f42a712020-07-01 08:56:59 +00002469 """
2470 IKE:AES_CBC_128_SHA256_128,DH=modp2048 ESP:AES_CBC_192_SHA_384_192
2471 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002472
Filip Tehlar4f42a712020-07-01 08:56:59 +00002473 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002474 self.config_params(
2475 {
2476 "ike-crypto": ("AES-CBC", 16),
2477 "ike-integ": "SHA2-256-128",
2478 "esp-crypto": ("AES-CBC", 24),
2479 "esp-integ": "SHA2-384-192",
2480 "ike-dh": "2048MODPgr",
2481 "nonce": os.urandom(256),
2482 "no_idr_in_auth": True,
2483 }
2484 )
Filip Tehlar4f42a712020-07-01 08:56:59 +00002485
2486
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002487@tag_fixme_vpp_workers
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002488class TestAES_CBC_128_SHA256_128_MODP3072_ESP_AES_GCM_16(
2489 TemplateResponder, Ikev2Params
2490):
Filip Tehlar4f42a712020-07-01 08:56:59 +00002491 """
2492 IKE:AES_CBC_128_SHA256_128,DH=modp3072 ESP:AES_GCM_16
2493 """
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002494
Filip Tehlar4f42a712020-07-01 08:56:59 +00002495 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002496 self.config_params(
2497 {
2498 "ike-crypto": ("AES-CBC", 32),
2499 "ike-integ": "SHA2-256-128",
2500 "esp-crypto": ("AES-GCM-16ICV", 32),
2501 "esp-integ": "NULL",
2502 "ike-dh": "3072MODPgr",
2503 }
2504 )
Filip Tehlar4f42a712020-07-01 08:56:59 +00002505
2506
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002507@tag_fixme_vpp_workers
Filip Tehlara7b963d2020-07-08 13:25:34 +00002508class Test_IKE_AES_GCM_16_256(TemplateResponder, Ikev2Params):
2509 """
2510 IKE:AES_GCM_16_256
2511 """
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002512
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002513 IKE_NODE_SUFFIX = "ip6"
Filip Tehlarfab5e7f2021-01-14 13:32:01 +00002514
Filip Tehlara7b963d2020-07-08 13:25:34 +00002515 def config_tc(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002516 self.config_params(
2517 {
2518 "del_sa_from_responder": True,
2519 "ip6": True,
2520 "natt": True,
2521 "ike-crypto": ("AES-GCM-16ICV", 32),
2522 "ike-integ": "NULL",
2523 "ike-dh": "2048MODPgr",
2524 "loc_ts": {"start_addr": "ab:cd::0", "end_addr": "ab:cd::10"},
2525 "rem_ts": {"start_addr": "11::0", "end_addr": "11::100"},
2526 }
2527 )
Filip Tehlara7b963d2020-07-08 13:25:34 +00002528
2529
Andrew Yourtchenko8dc0d482021-01-29 13:17:19 +00002530@tag_fixme_vpp_workers
Andrew Yourtchenko9987d472024-07-02 18:02:09 +02002531@tag_fixme_ubuntu2204
Filip Tehlar2008e312020-11-09 13:23:24 +00002532class TestInitiatorKeepaliveMsg(TestInitiatorPsk):
2533 """
2534 Test for keep alive messages
2535 """
2536
2537 def send_empty_req_from_responder(self):
Filip Tehlar38340fa2020-11-19 21:34:48 +00002538 packet = self.create_empty_request()
Filip Tehlar2008e312020-11-09 13:23:24 +00002539 self.pg0.add_stream(packet)
2540 self.pg0.enable_capture()
2541 self.pg_start()
2542 capture = self.pg0.get_capture(1)
2543 ih = self.get_ike_header(capture[0])
2544 self.assertEqual(ih.id, self.sa.msg_id)
2545 plain = self.sa.hmac_and_decrypt(ih)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002546 self.assertEqual(plain, b"")
2547 self.assert_counter(1, "keepalive", "ip4")
Filip Tehlar68d27532021-01-25 10:09:27 +00002548 r = self.vapi.ikev2_sa_dump()
2549 self.assertEqual(1, r[0].sa.stats.n_keepalives)
Denys Haryachyyf40a3542024-01-24 16:31:47 +02002550 r = self.vapi.ikev2_sa_v2_dump()
2551 self.assertEqual(1, r[0].sa.stats.n_keepalives)
Filip Tehlar2008e312020-11-09 13:23:24 +00002552
2553 def test_initiator(self):
2554 super(TestInitiatorKeepaliveMsg, self).test_initiator()
2555 self.send_empty_req_from_responder()
2556
2557
Filip Tehlar558607d2020-07-16 07:25:56 +00002558class TestMalformedMessages(TemplateResponder, Ikev2Params):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002559 """malformed packet test"""
Filip Tehlar558607d2020-07-16 07:25:56 +00002560
2561 def tearDown(self):
2562 pass
2563
2564 def config_tc(self):
2565 self.config_params()
2566
Filip Tehlar558607d2020-07-16 07:25:56 +00002567 def create_ike_init_msg(self, length=None, payload=None):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002568 msg = ikev2.IKEv2(
2569 length=length,
2570 init_SPI="\x11" * 8,
2571 flags="Initiator",
2572 exch_type="IKE_SA_INIT",
2573 )
Filip Tehlar558607d2020-07-16 07:25:56 +00002574 if payload is not None:
2575 msg /= payload
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002576 return self.create_packet(self.pg0, msg, self.sa.sport, self.sa.dport)
Filip Tehlar558607d2020-07-16 07:25:56 +00002577
2578 def verify_bad_packet_length(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002579 ike_msg = self.create_ike_init_msg(length=0xDEAD)
Filip Tehlar558607d2020-07-16 07:25:56 +00002580 self.send_and_assert_no_replies(self.pg0, ike_msg * self.pkt_count)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002581 self.assert_counter(self.pkt_count, "bad_length")
Filip Tehlar558607d2020-07-16 07:25:56 +00002582
2583 def verify_bad_sa_payload_length(self):
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002584 p = ikev2.IKEv2_payload_SA(length=0xDEAD)
Filip Tehlar558607d2020-07-16 07:25:56 +00002585 ike_msg = self.create_ike_init_msg(payload=p)
2586 self.send_and_assert_no_replies(self.pg0, ike_msg * self.pkt_count)
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002587 self.assert_counter(self.pkt_count, "malformed_packet")
Filip Tehlar558607d2020-07-16 07:25:56 +00002588
2589 def test_responder(self):
2590 self.pkt_count = 254
2591 self.verify_bad_packet_length()
2592 self.verify_bad_sa_payload_length()
2593
2594
Klement Sekerad9b0c6f2022-04-26 19:02:15 +02002595if __name__ == "__main__":
Filip Tehlar12b517b2020-04-26 18:05:05 +00002596 unittest.main(testRunner=VppTestRunner)