Revert "drsuapi_dissect_element_DsGetNCChangesCtr6TS_ctr6 dissect_krb5_PAC_NDRHEADERBLOB"
[wireshark-sm.git] / test / suite_decryption.py
blob3b337baf126733fd858e10cbf5e547e8bbccc951
2 # Wireshark tests
3 # By Gerald Combs <gerald@wireshark.org>
5 # Ported from a set of Bash scripts which were copyright 2005 Ulf Lamping
7 # SPDX-License-Identifier: GPL-2.0-or-later
9 '''Decryption tests'''
11 import os.path
12 import shutil
13 import subprocess
14 from subprocesstest import grep_output, count_output
15 import sys
16 import sysconfig
17 import types
18 import pytest
19 import binascii
21 class TestDecrypt80211:
22 def test_80211_wep(self, cmd_tshark, capture_file, test_env):
23 '''IEEE 802.11 WEP'''
24 # Included in git sources test/captures/wep.pcapng.gz
25 stdout = subprocess.check_output((cmd_tshark,
26 '-o', 'wlan.enable_decryption: TRUE',
27 '-r', capture_file('wep.pcapng.gz'),
28 ), encoding='utf-8', env=test_env)
29 assert grep_output(stdout, 'Who has 192.168.5.1')
30 assert grep_output(stdout, r'Echo \(ping\) request')
32 def test_80211_wpa_psk(self, cmd_tshark, capture_file, test_env):
33 '''IEEE 802.11 WPA PSK'''
34 # https://gitlab.com/wireshark/wireshark/-/wikis/uploads/__moin_import__/attachments/SampleCaptures/wpa-Induction.pcap
35 stdout = subprocess.check_output((cmd_tshark,
36 '-o', 'wlan.enable_decryption: TRUE',
37 '-Tfields',
38 '-e', 'http.request.uri',
39 '-r', capture_file('wpa-Induction.pcap.gz'),
40 '-Y', 'http',
41 ), encoding='utf-8', env=test_env)
42 assert grep_output(stdout, 'favicon.ico')
44 def test_80211_wpa_eap(self, cmd_tshark, capture_file, test_env):
45 '''IEEE 802.11 WPA EAP (EAPOL Rekey)'''
46 # Included in git sources test/captures/wpa-eap-tls.pcap.gz
47 stdout = subprocess.check_output((cmd_tshark,
48 '-o', 'wlan.enable_decryption: TRUE',
49 '-r', capture_file('wpa-eap-tls.pcap.gz'),
50 '-Y', 'wlan.analysis.tk==7d9987daf5876249b6c773bf454a0da7',
51 ), encoding='utf-8', env=test_env)
52 assert grep_output(stdout, 'Group Message')
54 def test_80211_wpa_eapol_incomplete_rekeys(self, cmd_tshark, capture_file, test_env):
55 '''WPA decode with message1+2 only and secure bit set on message 2'''
56 # Included in git sources test/captures/wpa-test-decode.pcap.gz
57 stdout = subprocess.check_output((cmd_tshark,
58 '-o', 'wlan.enable_decryption: TRUE',
59 '-r', capture_file('wpa-test-decode.pcap.gz'),
60 '-Y', 'icmp.resp_to == 4263',
61 ), encoding='utf-8', env=test_env)
62 assert grep_output(stdout, 'Echo')
64 def test_80211_wpa_psk_mfp(self, cmd_tshark, capture_file, test_env):
65 '''WPA decode management frames with MFP enabled (802.11w)'''
66 # Included in git sources test/captures/wpa-test-decode-mgmt.pcap.gz
67 stdout = subprocess.check_output((cmd_tshark,
68 '-o', 'wlan.enable_decryption: TRUE',
69 '-r', capture_file('wpa-test-decode-mgmt.pcap.gz'),
70 '-Y', 'wlan.fixed.reason_code == 2 || wlan.fixed.category_code == 3',
71 ), encoding='utf-8', env=test_env)
72 assert count_output(stdout, '802.11.*SN=.*FN=.*Flags=') == 3
74 def test_80211_wpa2_psk_mfp(self, cmd_tshark, capture_file, features, test_env):
75 '''IEEE 802.11 decode WPA2 PSK with MFP enabled (802.11w)'''
76 # Included in git sources test/captures/wpa2-psk-mfp.pcapng.gz
77 stdout = subprocess.check_output((cmd_tshark,
78 '-o', 'wlan.enable_decryption: TRUE',
79 '-r', capture_file('wpa2-psk-mfp.pcapng.gz'),
80 '-Y', 'wlan.analysis.tk == 4e30e8c019bea43ea5262b10853b818d || wlan.analysis.gtk == 70cdbf2e5bc0ca22e53930818a5d80e4',
81 ), encoding='utf-8', env=test_env)
82 assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK is correct
83 assert grep_output(stdout, 'DHCP Request') # Verifies TK is correct
84 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK is correct
86 def test_80211_wpa2_psk_ccmp_tkip(self, cmd_tshark, capture_file, features, test_env):
87 '''IEEE 802.11 decode WPA2 PSK CCMP/TKIP'''
88 # Included in git sources test/captures/wpa2-psk-ccmp-tkip.pcapng.gz
89 stdout = subprocess.check_output((cmd_tshark,
90 '-o', 'wlan.enable_decryption: TRUE',
91 '-r', capture_file('wpa2-psk-ccmp-tkip.pcapng.gz'),
92 '-Y', 'wlan.analysis.tk == 79712dd69a793c86a04b51e6aab91690 || wlan.analysis.gtk == c72aa2501e3be7d774badbd3b6c2bbe9',
93 ), encoding='utf-8', env=test_env)
94 assert count_output(stdout, r'ICMP.*Echo \(ping\)') == 5 # Verify unicast and broadcast frame decryption
96 def test_80211_wpa_tdls(self, cmd_tshark, capture_file, features, test_env):
97 '''WPA decode traffic in a TDLS (Tunneled Direct-Link Setup) session (802.11z)'''
98 # Included in git sources test/captures/wpa-test-decode-tdls.pcap.gz
99 stdout = subprocess.check_output((cmd_tshark,
100 #'-ouat:80211_keys:"wpa-pwd","12345678"',
101 '-o', 'wlan.enable_decryption: TRUE',
102 '-r', capture_file('wpa-test-decode-tdls.pcap.gz'),
103 '-Y', 'icmp',
104 ), encoding='utf-8', env=test_env)
105 assert count_output(stdout, 'ICMP.*Echo .ping') == 2
107 def test_80211_wpa3_personal(self, cmd_tshark, capture_file, test_env):
108 '''IEEE 802.11 decode WPA3 personal / SAE'''
109 # Included in git sources test/captures/wpa3-sae.pcapng.gz
110 stdout = subprocess.check_output((cmd_tshark,
111 '-o', 'wlan.enable_decryption: TRUE',
112 '-r', capture_file('wpa3-sae.pcapng.gz'),
113 '-Y', 'wlan.analysis.tk == 20a2e28f4329208044f4d7edca9e20a6 || wlan.analysis.gtk == 1fc82f8813160031d6bf87bca22b6354',
114 ), encoding='utf-8', env=test_env)
115 assert grep_output(stdout, 'Who has 192.168.5.18')
116 assert grep_output(stdout, 'DHCP ACK')
118 def test_80211_owe(self, cmd_tshark, capture_file, test_env):
119 '''IEEE 802.11 decode OWE'''
120 # Included in git sources test/captures/owe.pcapng.gz
121 stdout = subprocess.check_output((cmd_tshark,
122 '-o', 'wlan.enable_decryption: TRUE',
123 '-r', capture_file('owe.pcapng.gz'),
124 '-Y', 'wlan.analysis.tk == 10f3deccc00d5c8f629fba7a0fff34aa || wlan.analysis.gtk == 016b04ae9e6050bcc1f940dda9ffff2b',
125 ), encoding='utf-8', env=test_env)
126 assert grep_output(stdout, 'Who has 192.168.5.2')
127 assert grep_output(stdout, 'DHCP ACK')
129 def test_80211_wpa3_suite_b_192(self, cmd_tshark, capture_file, test_env):
130 '''IEEE 802.11 decode WPA3 Suite B 192-bit'''
131 # Included in git sources test/captures/wpa3-suiteb-192.pcapng.gz
132 stdout = subprocess.check_output((cmd_tshark,
133 '-o', 'wlan.enable_decryption: TRUE',
134 '-r', capture_file('wpa3-suiteb-192.pcapng.gz'),
135 '-Tfields',
136 '-e' 'wlan.rsn.ie.gtk_kde.gtk',
137 '-e' 'wlan.analysis.kck',
138 '-e' 'wlan.analysis.kek',
139 ), encoding='utf-8', env=test_env)
140 # Verify that correct PTKs (KCK, KEK) are derived and GTK correctly dissected
141 assert count_output(stdout, '^29f92526ccda5a5dfa0ffa44c26f576ee2d45bae7c5f63369103b1edcab206ea\t' \
142 'f49ac1a15121f1a597a60a469870450a588ef1f73a1017b1\t' \
143 '0289b022b4f54262048d3493834ae591e811870c4520ee1395dd215a6092fbfb$') == 1
144 assert count_output(stdout, '^29f92526ccda5a5dfa0ffa44c26f576ee2d45bae7c5f63369103b1edcab206ea\t' \
145 '1027c8d5b155ff574158bc50083e28f02e9636a2ac694901\t' \
146 'd4814a364419fa881a8593083f51497fe9e30556a91cc5d0b11cd2b3226038e1$') == 1
147 assert count_output(stdout, '^29f92526ccda5a5dfa0ffa44c26f576ee2d45bae7c5f63369103b1edcab206ea\t' \
148 '35db5e208c9caff2a4e00a54c5346085abaa6f422ef6df81\t' \
149 'a14d0d683c01bc631bf142e82dc4995d87364eeacfab75d74cf470683bd10c51$') == 1
151 def test_80211_wpa1_gtk_rekey(self, cmd_tshark, capture_file, test_env):
152 '''Decode WPA1 with multiple GTK rekeys'''
153 # Included in git sources test/captures/wpa1-gtk-rekey.pcapng.gz
154 stdout = subprocess.check_output((cmd_tshark,
155 '-o', 'wlan.enable_decryption: TRUE',
156 '-r', capture_file('wpa1-gtk-rekey.pcapng.gz'),
157 '-Y', 'wlan.analysis.tk == "d0e57d224c1bb8806089d8c23154074c" || wlan.analysis.gtk == "6eaf63f4ad7997ced353723de3029f4d" || wlan.analysis.gtk == "fb42811bcb59b7845376246454fbdab7"',
158 ), encoding='utf-8', env=test_env)
159 assert grep_output(stdout, 'DHCP Discover')
160 assert count_output(stdout, 'ICMP.*Echo .ping') == 8
162 def test_80211_wpa_extended_key_id_rekey(self, cmd_tshark, capture_file, test_env):
163 '''WPA decode for Extended Key ID'''
164 # Included in git sources test/captures/wpa_ptk_extended_key_id.pcap.gz
165 stdout = subprocess.check_output((cmd_tshark,
166 '-o', 'wlan.enable_decryption: TRUE',
167 '-r', capture_file('wpa_ptk_extended_key_id.pcap.gz'),
168 '-Tfields',
169 '-e' 'wlan.fc.type_subtype',
170 '-e' 'wlan.ra',
171 '-e' 'wlan.analysis.tk',
172 '-e' 'wlan.analysis.gtk',
173 '-e' 'wlan.rsn.ie.ptk.keyid',
174 ), encoding='utf-8', env=test_env)
175 # Verify frames are decoded with the correct key
176 assert count_output(stdout, '^0x0020\t33:33:00:00:00:16\t\t234a9a6ddcca3cb728751cea49d01bb0\t$') == 5
177 assert count_output(stdout, '^0x0020\t33:33:ff:00:00:00\t\t234a9a6ddcca3cb728751cea49d01bb0\t$') == 1
178 assert count_output(stdout, '^0x0020\t33:33:ff:00:03:00\t\t234a9a6ddcca3cb728751cea49d01bb0\t$') == 1
179 assert count_output(stdout, '^0x0020\tff:ff:ff:ff:ff:ff\t\t234a9a6ddcca3cb728751cea49d01bb0\t$') == 4
180 assert count_output(stdout, '^0x0028\t02:00:00:00:03:00\t618b4d1829e2a496d7fd8c034a6d024d\t\t$') == 2
181 assert count_output(stdout, '^0x0028\t02:00:00:00:00:00\t618b4d1829e2a496d7fd8c034a6d024d\t\t$') == 1
182 # Verify RSN PTK KeyID parsing
183 assert count_output(stdout, '^0x0028\t02:00:00:00:00:00\t\t\t1$') == 1
184 assert count_output(stdout, '^0x0028\t02:00:00:00:00:00\tf31ecff5452f4c286cf66ef50d10dabe\t\t0$') == 1
185 assert count_output(stdout, '^0x0028\t02:00:00:00:00:00\t28dd851decf3f1c2a35df8bcc22fa1d2\t\t1$') == 1
187 def test_80211_wpa_ccmp_256(self, cmd_tshark, capture_file, features, test_env):
188 '''IEEE 802.11 decode CCMP-256'''
189 # Included in git sources test/captures/wpa-ccmp-256.pcapng.gz
190 stdout = subprocess.check_output((cmd_tshark,
191 '-o', 'wlan.enable_decryption: TRUE',
192 '-r', capture_file('wpa-ccmp-256.pcapng.gz'),
193 '-Y', 'wlan.analysis.tk == 4e6abbcf9dc0943936700b6825952218f58a47dfdf51dbb8ce9b02fd7d2d9e40 || wlan.analysis.gtk == 502085ca205e668f7e7c61cdf4f731336bb31e4f5b28ec91860174192e9b2190',
194 ), encoding='utf-8', env=test_env)
195 assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK is correct
196 assert grep_output(stdout, 'DHCP Request') # Verifies TK is correct
197 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK is correct
199 def test_80211_wpa_gcmp(self, cmd_tshark, capture_file, features, test_env):
200 '''IEEE 802.11 decode GCMP'''
201 # Included in git sources test/captures/wpa-gcmp.pcapng.gz
202 stdout = subprocess.check_output((cmd_tshark,
203 '-o', 'wlan.enable_decryption: TRUE',
204 '-r', capture_file('wpa-gcmp.pcapng.gz'),
205 '-Y', 'wlan.analysis.tk == 755a9c1c9e605d5ff62849e4a17a935c || wlan.analysis.gtk == 7ff30f7a8dd67950eaaf2f20a869a62d',
206 ), encoding='utf-8', env=test_env)
207 assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK is correct
208 assert grep_output(stdout, 'DHCP Request') # Verifies TK is correct
209 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK is correct
211 def test_80211_wpa_gcmp_256(self, cmd_tshark, capture_file, features, test_env):
212 '''IEEE 802.11 decode GCMP-256'''
213 # Included in git sources test/captures/wpa-gcmp-256.pcapng.gz
214 stdout = subprocess.check_output((cmd_tshark,
215 '-o', 'wlan.enable_decryption: TRUE',
216 '-r', capture_file('wpa-gcmp-256.pcapng.gz'),
217 '-Y', 'wlan.analysis.tk == b3dc2ff2d88d0d34c1ddc421cea17f304af3c46acbbe7b6d808b6ebf1b98ec38 || wlan.analysis.gtk == a745ee2313f86515a155c4cb044bc148ae234b9c72707f772b69c2fede3e4016',
218 ), encoding='utf-8', env=test_env)
219 assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK is correct
220 assert grep_output(stdout, 'DHCP Request') # Verifies TK is correct
221 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK is correct
223 def test_80211_wpa2_ft_psk_no_roam(self, cmd_tshark, capture_file, test_env):
224 '''IEEE 802.11 decode WPA2 FT PSK (without roam verification)'''
225 # Included in git sources test/captures/wpa2-ft-psk.pcapng.gz
226 stdout = subprocess.check_output((cmd_tshark,
227 '-o', 'wlan.enable_decryption: TRUE',
228 '-r', capture_file('wpa2-ft-psk.pcapng.gz'),
229 '-Y', 'wlan.analysis.tk == ba60c7be2944e18f31949508a53ee9d6 || wlan.analysis.gtk == 6eab6a5f8d880f81104ed65ab0c74449',
230 ), encoding='utf-8', env=test_env)
231 # Verifies that traffic from initial authentication can be decrypted (both TK and GTK)
232 assert count_output(stdout, 'DHCP Discover') == 2
233 assert count_output(stdout, 'DHCP Offer') == 1
234 assert count_output(stdout, 'DHCP Request') == 2
235 assert count_output(stdout, 'DHCP ACK') == 1
236 assert count_output(stdout, 'ARP.*Who has') == 3
237 assert count_output(stdout, 'ARP.*is at') == 1
238 assert count_output(stdout, r'ICMP.*Echo \(ping\)') == 2
240 def test_80211_wpa2_ft_psk_roam(self, cmd_tshark, capture_file, features, test_env):
241 '''IEEE 802.11 decode WPA2 FT PSK'''
242 # Included in git sources test/captures/wpa2-ft-psk.pcapng.gz
244 # Verify TK and GTK for both initial authentication (AP1) and roam(AP2).
245 stdout = subprocess.check_output((cmd_tshark,
246 '-o', 'wlan.enable_decryption: TRUE',
247 '-r', capture_file('wpa2-ft-psk.pcapng.gz'),
248 '-Y', 'wlan.analysis.tk == ba60c7be2944e18f31949508a53ee9d6 || wlan.analysis.gtk == 6eab6a5f8d880f81104ed65ab0c74449 || wlan.analysis.tk == a6a3304e5a8fabe0dc427cc41a707858 || wlan.analysis.gtk == a6cc605e10878f86b20a266c9b58d230',
249 ), encoding='utf-8', env=test_env)
250 assert count_output(stdout, 'DHCP Discover') == 2
251 assert count_output(stdout, 'DHCP Offer') == 1
252 assert count_output(stdout, 'DHCP Request') == 2
253 assert count_output(stdout, 'DHCP ACK') == 1
254 assert count_output(stdout, 'ARP.*Who has') == 5
255 assert count_output(stdout, 'ARP.*is at') == 2
256 assert count_output(stdout, r'ICMP.*Echo \(ping\)') == 4
258 def test_80211_wpa2_ft_eap(self, cmd_tshark, capture_file, test_env):
259 '''IEEE 802.11 decode WPA2 FT EAP'''
260 # Included in git sources test/captures/wpa2-ft-eap.pcapng.gz
261 stdout = subprocess.check_output((cmd_tshark,
262 '-o', 'wlan.enable_decryption: TRUE',
263 '-r', capture_file('wpa2-ft-eap.pcapng.gz'),
264 '-Y', 'wlan.analysis.tk == 65471b64605bf2a04af296284cb4ae2a || wlan.analysis.gtk == 1783a5c28e046df6fb58cf4406c4b22c',
265 ), encoding='utf-8', env=test_env)
266 assert grep_output(stdout, 'Who has 192.168.1.1') # Verifies GTK decryption
267 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
269 class TestDecrypt80211UserTk:
270 def test_80211_user_tk_tkip(self, cmd_tshark, capture_file, test_env):
271 '''IEEE 802.11 decode TKIP using user TK'''
272 # Included in git sources test/captures/wpa1-gtk-rekey.pcapng.gz
273 stdout = subprocess.check_output((cmd_tshark,
274 '-o', 'wlan.enable_decryption: TRUE',
275 '-r', capture_file('wpa1-gtk-rekey.pcapng.gz'),
276 '-Y', 'wlan.analysis.tk == "d0e57d224c1bb8806089d8c23154074c" || wlan.analysis.gtk == "6eaf63f4ad7997ced353723de3029f4d" || wlan.analysis.gtk == "fb42811bcb59b7845376246454fbdab7"',
277 ), encoding='utf-8', env=test_env)
278 assert grep_output(stdout, 'DHCP Discover')
279 assert count_output(stdout, 'ICMP.*Echo .ping') == 8
281 def test_80211_user_tk_ccmp(self, cmd_tshark, capture_file, features, test_env):
282 '''IEEE 802.11 decode CCMP-128 using user TK'''
283 # Included in git sources test/captures/wpa2-psk-mfp.pcapng.gz
284 stdout = subprocess.check_output((cmd_tshark,
285 '-o', 'wlan.enable_decryption: TRUE',
286 '-r', capture_file('wpa2-psk-mfp.pcapng.gz'),
287 '-Y', 'wlan.analysis.tk == 4e30e8c019bea43ea5262b10853b818d || wlan.analysis.gtk == 70cdbf2e5bc0ca22e53930818a5d80e4',
288 ), encoding='utf-8', env=test_env)
289 assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK decryption
290 assert grep_output(stdout, 'DHCP Request') # Verifies TK decryption
291 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
293 def test_80211_user_tk_ccmp_256(self, cmd_tshark, capture_file, features, test_env):
294 '''IEEE 802.11 decode CCMP-256 using user TK'''
295 # Included in git sources test/captures/wpa-ccmp-256.pcapng.gz
296 stdout = subprocess.check_output((cmd_tshark,
297 '-o', 'wlan.enable_decryption: TRUE',
298 '-r', capture_file('wpa-ccmp-256.pcapng.gz'),
299 '-Y', 'wlan.analysis.tk == 4e6abbcf9dc0943936700b6825952218f58a47dfdf51dbb8ce9b02fd7d2d9e40 || wlan.analysis.gtk == 502085ca205e668f7e7c61cdf4f731336bb31e4f5b28ec91860174192e9b2190',
300 ), encoding='utf-8', env=test_env)
301 assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK decryption
302 assert grep_output(stdout, 'DHCP Request') # Verifies TK decryption
303 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
305 def test_80211_user_tk_gcmp(self, cmd_tshark, capture_file, features, test_env):
306 '''IEEE 802.11 decode GCMP using user TK'''
307 # Included in git sources test/captures/wpa-gcmp.pcapng.gz
308 stdout = subprocess.check_output((cmd_tshark,
309 '-o', 'wlan.enable_decryption: TRUE',
310 '-r', capture_file('wpa-gcmp.pcapng.gz'),
311 '-Y', 'wlan.analysis.tk == 755a9c1c9e605d5ff62849e4a17a935c || wlan.analysis.gtk == 7ff30f7a8dd67950eaaf2f20a869a62d',
312 ), encoding='utf-8', env=test_env)
313 assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK decryption
314 assert grep_output(stdout, 'DHCP Request') # Verifies TK decryption
315 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
317 def test_80211_wpa_gcmp_256(self, cmd_tshark, capture_file, features, test_env):
318 '''IEEE 802.11 decode GCMP-256 using user TK'''
319 # Included in git sources test/captures/wpa-gcmp-256.pcapng.gz
320 stdout = subprocess.check_output((cmd_tshark,
321 '-o', 'wlan.enable_decryption: TRUE',
322 '-r', capture_file('wpa-gcmp-256.pcapng.gz'),
323 '-Y', 'wlan.analysis.tk == b3dc2ff2d88d0d34c1ddc421cea17f304af3c46acbbe7b6d808b6ebf1b98ec38 || wlan.analysis.gtk == a745ee2313f86515a155c4cb044bc148ae234b9c72707f772b69c2fede3e4016',
324 ), encoding='utf-8', env=test_env)
325 assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK decryption
326 assert grep_output(stdout, 'DHCP Request') # Verifies TK decryption
327 assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
330 class TestDecryptDTLS:
331 def test_dtls_rsa(self, cmd_tshark, capture_file, features, test_env):
332 '''DTLS'''
333 if not features.have_gnutls:
334 pytest.skip('Requires GnuTLS.')
335 # https://gitlab.com/wireshark/wireshark/-/wikis/uploads/__moin_import__/attachments/SampleCaptures/snakeoil.tgz
336 stdout = subprocess.check_output((cmd_tshark,
337 '-r', capture_file('snakeoil-dtls.pcap'),
338 '-Tfields',
339 '-e', 'data.data',
340 '-Y', 'data',
341 ), encoding='utf-8', env=test_env)
342 assert grep_output(stdout, '697420776f726b20210a')
344 def test_dtls_psk_aes128ccm8(self, cmd_tshark, capture_file, test_env):
345 '''DTLS 1.2 with PSK, AES-128-CCM-8'''
346 stdout = subprocess.check_output((cmd_tshark,
347 '-r', capture_file('dtls12-aes128ccm8.pcap'),
348 '-o', 'dtls.psk:ca19e028a8a372ad2d325f950fcaceed',
349 '-x'
350 ), encoding='utf-8', env=test_env)
351 dt_count = count_output(stdout, 'Decrypted DTLS')
352 wfm_count = count_output(stdout, 'Works for me!.')
353 assert dt_count == 7 and wfm_count == 2
355 def test_dtls_dsb_aes128ccm8(self, cmd_tshark, capture_file, test_env):
356 '''DTLS 1.2 with master secrets in a pcapng Decryption Secrets Block.'''
357 stdout = subprocess.check_output((cmd_tshark,
358 '-r', capture_file('dtls12-aes128ccm8-dsb.pcapng'),
359 '-x'
360 ), encoding='utf-8', env=test_env)
361 dt_count = count_output(stdout, 'Decrypted DTLS')
362 wfm_count = count_output(stdout, 'Works for me!.')
363 assert dt_count == 7 and wfm_count == 2
365 def test_dtls_udt(self, cmd_tshark, dirs, capture_file, features, test_env):
366 '''UDT over DTLS 1.2 with RSA key'''
367 if not features.have_gnutls:
368 pytest.skip('Requires GnuTLS.')
369 key_file = os.path.join(dirs.key_dir, 'udt-dtls.key')
370 stdout = subprocess.check_output((cmd_tshark,
371 '-r', capture_file('udt-dtls.pcapng.gz'),
372 '-o', 'dtls.keys_list:0.0.0.0,0,data,{}'.format(key_file),
373 '-Y', 'dtls && udt.type==ack',
374 ), encoding='utf-8', env=test_env)
375 assert grep_output(stdout, 'UDT')
378 class TestDecryptTLS:
379 def test_tls_rsa(self, cmd_tshark, capture_file, features, test_env):
380 '''TLS using the server's private RSA key.'''
381 if not features.have_gnutls:
382 pytest.skip('Requires GnuTLS.')
383 # https://gitlab.com/wireshark/wireshark/-/wikis/uploads/__moin_import__/attachments/SampleCaptures/snakeoil2_070531.tgz
384 stdout = subprocess.check_output((cmd_tshark,
385 '-r', capture_file('rsasnakeoil2.pcap'),
386 '-Tfields',
387 '-e', 'http.request.uri',
388 '-Y', 'http',
389 ), encoding='utf-8', env=test_env)
390 assert grep_output(stdout, 'favicon.ico')
392 def test_tls_rsa_pq(self, cmd_tshark, dirs, capture_file, features, test_env):
393 '''TLS using the server's private key with p < q
394 (test whether libgcrypt is correctly called)'''
395 if not features.have_gnutls:
396 pytest.skip('Requires GnuTLS.')
397 key_file = os.path.join(dirs.key_dir, 'rsa-p-lt-q.key')
398 stdout = subprocess.check_output((cmd_tshark,
399 '-r', capture_file('rsa-p-lt-q.pcap'),
400 '-o', 'tls.keys_list:0.0.0.0,443,http,{}'.format(key_file),
401 '-Tfields',
402 '-e', 'http.request.uri',
403 '-Y', 'http',
404 ), encoding='utf-8', env=test_env)
405 assert grep_output(stdout, '/')
407 def test_tls_rsa_privkeys_uat(self, cmd_tshark, dirs, capture_file, features, test_env):
408 '''Check TLS decryption works using the rsa_keys UAT.'''
409 if not features.have_gnutls:
410 pytest.skip('Requires GnuTLS.')
411 key_file = os.path.join(dirs.key_dir, 'rsa-p-lt-q.key')
412 stdout = subprocess.check_output((cmd_tshark,
413 '-r', capture_file('rsa-p-lt-q.pcap'),
414 '-o', 'uat:rsa_keys:"{}",""'.format(key_file.replace('\\', '\\x5c')),
415 '-Tfields',
416 '-e', 'http.request.uri',
417 '-Y', 'http',
418 ), encoding='utf-8', env=test_env)
419 assert '/' in stdout
421 def test_tls_rsa_with_password(self, cmd_tshark, capture_file, features, test_env):
422 '''TLS using the server's private key with password'''
423 if not features.have_gnutls:
424 pytest.skip('Requires GnuTLS.')
425 stdout = subprocess.check_output((cmd_tshark,
426 '-r', capture_file('dmgr.pcapng'),
427 '-Tfields',
428 '-e', 'http.request.uri',
429 '-Y', 'http',
430 ), encoding='utf-8', env=test_env)
431 assert grep_output(stdout, 'unsecureLogon.jsp')
433 def test_tls_master_secret(self, cmd_tshark, dirs, capture_file, test_env):
434 '''TLS using the master secret and ssl.keylog_file preference aliasing'''
435 key_file = os.path.join(dirs.key_dir, 'dhe1_keylog.dat')
436 stdout = subprocess.check_output((cmd_tshark,
437 '-r', capture_file('dhe1.pcapng.gz'),
438 '-o', 'ssl.keylog_file: {}'.format(key_file),
439 '-o', 'tls.desegment_ssl_application_data: FALSE',
440 '-o', 'http.tls.port: 443',
441 '-Tfields',
442 '-e', 'http.request.method',
443 '-e', 'http.request.uri',
444 '-e', 'http.request.version',
445 '-Y', 'http',
446 ), encoding='utf-8', env=test_env)
447 assert grep_output(stdout, r'GET\s+/test\s+HTTP/1.0')
449 def test_tls12_renegotiation(self, cmd_tshark, dirs, capture_file, features, test_env):
450 '''TLS 1.2 with renegotiation'''
451 if not features.have_gnutls:
452 pytest.skip('Requires GnuTLS.')
453 key_file = os.path.join(dirs.key_dir, 'rsasnakeoil2.key')
454 # Test protocol alias while at it (ssl -> tls)
455 stdout = subprocess.check_output((cmd_tshark,
456 '-r', capture_file('tls-renegotiation.pcap'),
457 '-o', 'tls.keys_list:0.0.0.0,4433,http,{}'.format(key_file),
458 '-d', 'tcp.port==4433,ssl',
459 '-Tfields',
460 '-e', 'http.content_length',
461 '-Y', 'http',
462 ), encoding='utf-8', env=test_env)
463 count_0 = count_output(stdout, '^0$')
464 count_2151 = count_output(stdout, '^2151$')
465 assert count_0 == 1 and count_2151 == 1
467 def test_tls12_psk_aes128ccm(self, cmd_tshark, capture_file, test_env):
468 '''TLS 1.2 with PSK, AES-128-CCM'''
469 stdout = subprocess.check_output((cmd_tshark,
470 '-r', capture_file('tls12-aes128ccm.pcap'),
471 '-o', 'tls.psk:ca19e028a8a372ad2d325f950fcaceed',
472 '-q',
473 '-z', 'follow,tls,ascii,0',
474 ), encoding='utf-8', env=test_env)
475 assert grep_output(stdout, 'http://www.gnu.org/software/gnutls')
477 def test_tls12_psk_aes256gcm(self, cmd_tshark, capture_file, test_env):
478 '''TLS 1.2 with PSK, AES-256-GCM'''
479 stdout = subprocess.check_output((cmd_tshark,
480 '-r', capture_file('tls12-aes256gcm.pcap'),
481 '-o', 'tls.psk:ca19e028a8a372ad2d325f950fcaceed',
482 '-q',
483 '-z', 'follow,tls,ascii,0',
484 ), encoding='utf-8', env=test_env)
485 assert grep_output(stdout, 'http://www.gnu.org/software/gnutls')
487 def test_tls12_chacha20poly1305(self, cmd_tshark, dirs, features, capture_file, test_env):
488 '''TLS 1.2 with ChaCha20-Poly1305'''
489 key_file = os.path.join(dirs.key_dir, 'tls12-chacha20poly1305.keys')
490 ciphers=[
491 'ECDHE-ECDSA-CHACHA20-POLY1305',
492 'ECDHE-RSA-CHACHA20-POLY1305',
493 'DHE-RSA-CHACHA20-POLY1305',
494 'RSA-PSK-CHACHA20-POLY1305',
495 'DHE-PSK-CHACHA20-POLY1305',
496 'ECDHE-PSK-CHACHA20-POLY1305',
497 'PSK-CHACHA20-POLY1305',
499 stream = 0
500 for cipher in ciphers:
501 stdout = subprocess.check_output((cmd_tshark,
502 '-r', capture_file('tls12-chacha20poly1305.pcap'),
503 '-o', 'tls.keylog_file: {}'.format(key_file),
504 '-q',
505 '-z', 'follow,tls,ascii,{}'.format(stream),
506 ), encoding='utf-8', env=test_env)
507 stream += 1
508 assert grep_output(stdout, 'Cipher is {}'.format(cipher))
510 def test_tls13_chacha20poly1305(self, cmd_tshark, dirs, features, capture_file, test_env):
511 '''TLS 1.3 with ChaCha20-Poly1305'''
512 key_file = os.path.join(dirs.key_dir, 'tls13-20-chacha20poly1305.keys')
513 stdout = subprocess.check_output((cmd_tshark,
514 '-r', capture_file('tls13-20-chacha20poly1305.pcap'),
515 '-o', 'tls.keylog_file: {}'.format(key_file),
516 '-q',
517 '-z', 'follow,tls,ascii,0',
518 ), encoding='utf-8', env=test_env)
519 assert grep_output(stdout, 'TLS13-CHACHA20-POLY1305-SHA256')
521 def test_tls13_rfc8446(self, cmd_tshark, dirs, features, capture_file, test_env):
522 '''TLS 1.3 (normal session, then early data followed by normal data).'''
523 key_file = os.path.join(dirs.key_dir, 'tls13-rfc8446.keys')
524 stdout = subprocess.check_output((cmd_tshark,
525 '-r', capture_file('tls13-rfc8446.pcap'),
526 '-otls.keylog_file:{}'.format(key_file),
527 '-Y', 'http',
528 '-Tfields',
529 '-e', 'frame.number',
530 '-e', 'http.request.uri',
531 '-e', 'http.file_data',
532 '-E', 'separator=|',
533 ), encoding='utf-8', env=test_env)
534 first_response = binascii.hexlify(b'Request for /first, version TLSv1.3, Early data: no\n').decode("ascii")
535 early_response = binascii.hexlify(b'Request for /early, version TLSv1.3, Early data: yes\n').decode("ascii")
536 second_response = binascii.hexlify(b'Request for /second, version TLSv1.3, Early data: yes\n').decode("ascii")
537 # assert [
538 # r'5|/first|',
539 # fr'6||{first_response}',
540 # r'8|/early|',
541 # fr'10||{early_response}',
542 # r'12|/second|',
543 # fr'13||{second_response}',
544 # ] == stdout.splitlines()
546 assert [
547 r'5|/first|',
548 fr'6|/first|{first_response}',
549 r'8|/early|',
550 fr'10|/early|{early_response}',
551 r'12|/second|',
552 fr'13|/second|{second_response}',
553 ] == stdout.splitlines()
555 def test_tls13_rfc8446_noearly(self, cmd_tshark, dirs, features, capture_file, test_env):
556 '''TLS 1.3 (with undecryptable early data).'''
557 key_file = os.path.join(dirs.key_dir, 'tls13-rfc8446-noearly.keys')
558 stdout = subprocess.check_output((cmd_tshark,
559 '-r', capture_file('tls13-rfc8446.pcap'),
560 '-otls.keylog_file:{}'.format(key_file),
561 '-Y', 'http',
562 '-Tfields',
563 '-e', 'frame.number',
564 '-e', 'http.request.uri',
565 '-e', 'http.file_data',
566 '-E', 'separator=|',
567 ), encoding='utf-8', env=test_env)
568 first_response = binascii.hexlify(b'Request for /first, version TLSv1.3, Early data: no\n').decode("ascii")
569 early_response = binascii.hexlify(b'Request for /early, version TLSv1.3, Early data: yes\n').decode("ascii")
570 second_response = binascii.hexlify(b'Request for /second, version TLSv1.3, Early data: yes\n').decode("ascii")
571 # assert [
572 # r'5|/first|',
573 # fr'6||{first_response}',
574 # fr'10||{early_response}',
575 # r'12|/second|',
576 # fr'13||{second_response}',
577 # ] == stdout.splitlines()
579 assert [
580 r'5|/first|',
581 fr'6|/first|{first_response}',
582 fr'10||{early_response}',
583 r'12|/second|',
584 fr'13|/second|{second_response}',
585 ] == stdout.splitlines()
587 def test_tls12_dsb(self, cmd_tshark, capture_file, test_env):
588 '''TLS 1.2 with master secrets in pcapng Decryption Secrets Blocks.'''
589 output = subprocess.check_output((cmd_tshark,
590 '-r', capture_file('tls12-dsb.pcapng'),
591 '-Tfields',
592 '-e', 'http.host',
593 '-e', 'http.response.code',
594 '-Y', 'http',
595 ), encoding='utf-8', env=test_env)
596 assert 'example.com\t\n\t200\nexample.net\t\n\t200\n' == output
598 def test_tls_over_tls(self, cmd_tshark, dirs, capture_file, features, test_env):
599 '''TLS using the server's private key with p < q
600 (test whether libgcrypt is correctly called)'''
601 if not features.have_gnutls:
602 pytest.skip('Requires GnuTLS.')
603 key_file = os.path.join(dirs.key_dir, 'tls-over-tls.key')
604 output = subprocess.check_output((cmd_tshark,
605 '-r', capture_file('tls-over-tls.pcapng.gz'),
606 '-o', 'tls.keys_list:0.0.0.0,443,http,{}'.format(key_file),
607 '-z', 'expert,tls.handshake.certificates',
608 '-Tfields',
609 '-e', 'tls.handshake.certificate_length',
610 '-Y', 'tls.handshake.certificates',
611 ), encoding='utf-8', env=test_env)
612 assert '1152,1115,1352\n1152\n1412,1434,1382\n' == output
615 class TestDecryptZigbee:
616 def test_zigbee(self, cmd_tshark, capture_file, test_env):
617 '''ZigBee'''
618 # https://gitlab.com/wireshark/wireshark/-/issues/7022
619 stdout = subprocess.check_output((cmd_tshark,
620 '-r', capture_file('sample_control4_2012-03-24.pcap'),
621 '-Tfields',
622 '-e', 'data.data',
623 '-Y', 'zbee_aps',
624 ), encoding='utf-8', env=test_env)
625 assert grep_output(stdout, '3067636338652063342e646d2e747620')
628 class TestDecryptANSIC122:
629 def test_ansi_c1222(self, cmd_tshark, capture_file, test_env):
630 '''ANSI C12.22'''
631 # https://gitlab.com/wireshark/wireshark/-/issues/9196
632 stdout = subprocess.check_output((cmd_tshark,
633 '-r', capture_file('c1222_std_example8.pcap'),
634 '-o', 'c1222.decrypt: TRUE',
635 '-o', 'c1222.baseoid: 2.16.124.113620.1.22.0',
636 '-Tfields',
637 '-e', 'c1222.data',
638 ), encoding='utf-8', env=test_env)
639 assert grep_output(stdout, '00104d414e55464143545552455220534e2092')
642 class TestDecryptDVBCI:
643 def test_dvb_ci(self, cmd_tshark, capture_file, test_env):
644 '''DVB-CI'''
645 # simplified version of the sample capture in
646 # https://gitlab.com/wireshark/wireshark/-/issues/6700
647 stdout = subprocess.check_output((cmd_tshark,
648 '-r', capture_file('dvb-ci_UV1_0000.pcap'),
649 '-o', 'dvb-ci.sek: 00000000000000000000000000000000',
650 '-o', 'dvb-ci.siv: 00000000000000000000000000000000',
651 '-Tfields',
652 '-e', 'dvb-ci.cc.sac.padding',
653 ), encoding='utf-8', env=test_env)
654 assert grep_output(stdout, '800000000000000000000000')
657 class TestDecryptIPsec:
658 def test_ipsec_esp(self, cmd_tshark, capture_file, test_env):
659 '''IPsec ESP'''
660 # https://gitlab.com/wireshark/wireshark/-/issues/12671
661 stdout = subprocess.check_output((cmd_tshark,
662 '-r', capture_file('esp-bug-12671.pcapng.gz'),
663 '-o', 'esp.enable_encryption_decode: TRUE',
664 '-Tfields',
665 '-e', 'data.data',
666 ), encoding='utf-8', env=test_env)
667 assert grep_output(stdout, '08090a0b0c0d0e0f1011121314151617')
670 class TestDecryptIkeIsakmp:
671 def test_ikev1_certs(self, cmd_tshark, capture_file, test_env):
672 '''IKEv1 (ISAKMP) with certificates'''
673 # https://gitlab.com/wireshark/wireshark/-/issues/7951
674 stdout = subprocess.check_output((cmd_tshark,
675 '-r', capture_file('ikev1-certs.pcap'),
676 '-Tfields',
677 '-e', 'x509sat.printableString',
678 ), encoding='utf-8', env=test_env)
679 assert grep_output(stdout, 'OpenSwan')
681 def test_ikev1_simultaneous(self, cmd_tshark, capture_file, test_env):
682 '''IKEv1 (ISAKMP) simultaneous exchanges'''
683 # https://gitlab.com/wireshark/wireshark/-/issues/12610
684 stdout = subprocess.check_output((cmd_tshark,
685 '-r', capture_file('ikev1-bug-12610.pcapng.gz'),
686 '-Tfields',
687 '-e', 'isakmp.hash',
688 ), encoding='utf-8', env=test_env)
689 assert grep_output(stdout, 'b52521f774967402c9f6cee95fd17e5b')
691 def test_ikev1_unencrypted(self, cmd_tshark, capture_file, test_env):
692 '''IKEv1 (ISAKMP) unencrypted phase 1'''
693 # https://gitlab.com/wireshark/wireshark/-/issues/12620
694 stdout = subprocess.check_output((cmd_tshark,
695 '-r', capture_file('ikev1-bug-12620.pcapng.gz'),
696 '-Tfields',
697 '-e', 'isakmp.hash',
698 ), encoding='utf-8', env=test_env)
699 assert grep_output(stdout, '40043b640f4373250d5ac3a1fb63153c')
701 def test_ikev2_3des_sha160(self, cmd_tshark, capture_file, test_env):
702 '''IKEv2 decryption test (3DES-CBC/SHA1_160)'''
703 stdout = subprocess.check_output((cmd_tshark,
704 '-r', capture_file('ikev2-decrypt-3des-sha1_160.pcap'),
705 '-Tfields',
706 '-e', 'isakmp.auth.data',
707 ), encoding='utf-8', env=test_env)
708 assert grep_output(stdout, '02f7a0d5f1fdc8ea81039818c65bb9bd09af9b8917319b887ff9ba3046c344c7')
710 def test_ikev2_aes128_ccm12(self, cmd_tshark, capture_file, test_env):
711 '''IKEv2 decryption test (AES-128-CCM-12) - with CBC-MAC verification'''
712 stdout = subprocess.check_output((cmd_tshark,
713 '-r', capture_file('ikev2-decrypt-aes128ccm12.pcap'),
714 '-Tfields',
715 '-e', 'isakmp.auth.data',
716 ), encoding='utf-8', env=test_env)
717 assert grep_output(stdout, 'c2104394299e1ffe7908ea720ad5d13717a0d454e4fa0a2128ea689411f479c4')
719 def test_ikev2_aes128_ccm12_2(self, cmd_tshark, capture_file, test_env):
720 '''IKEv2 decryption test (AES-128-CCM-12 using CTR mode, without checksum)'''
721 stdout = subprocess.check_output((cmd_tshark,
722 '-r', capture_file('ikev2-decrypt-aes128ccm12-2.pcap'),
723 '-Tfields',
724 '-e', 'isakmp.auth.data',
725 ), encoding='utf-8', env=test_env)
726 assert grep_output(stdout, 'aaa281c87b4a19046c57271d557488ca413b57228cb951f5fa9640992a0285b9')
728 def test_ikev2_aes192ctr_sha512(self, cmd_tshark, capture_file, test_env):
729 '''IKEv2 decryption test (AES-192-CTR/SHA2-512)'''
730 stdout = subprocess.check_output((cmd_tshark,
731 '-r', capture_file('ikev2-decrypt-aes192ctr.pcap'),
732 '-Tfields',
733 '-e', 'isakmp.auth.data',
734 ), encoding='utf-8', env=test_env)
735 assert grep_output(stdout, '3ec23dcf9348485638407c754547aeb3085290082c49f583fdbae59263a20b4a')
737 def test_ikev2_aes256cbc_sha256(self, cmd_tshark, capture_file, test_env):
738 '''IKEv2 decryption test (AES-256-CBC/SHA2-256)'''
739 stdout = subprocess.check_output((cmd_tshark,
740 '-r', capture_file('ikev2-decrypt-aes256cbc.pcapng'),
741 '-Tfields',
742 '-e', 'isakmp.auth.data',
743 ), encoding='utf-8', env=test_env)
744 assert grep_output(stdout, 'e1a8d550064201a7ec024a85758d0673c61c5c510ac13bcd225d6327f50da3d3')
746 def test_ikev2_aes256ccm16(self, cmd_tshark, capture_file, test_env):
747 '''IKEv2 decryption test (AES-256-CCM-16)'''
748 stdout = subprocess.check_output((cmd_tshark,
749 '-r', capture_file('ikev2-decrypt-aes256ccm16.pcapng'),
750 '-Tfields',
751 '-e', 'isakmp.auth.data',
752 ), encoding='utf-8', env=test_env)
753 assert grep_output(stdout, 'fa2e74bdc01e30fb0b3ddc9723c9449095969da51f69e560209d2c2b7940210a')
755 def test_ikev2_aes256gcm16(self, cmd_tshark, capture_file, test_env):
756 '''IKEv2 decryption test (AES-256-GCM-16)'''
757 stdout = subprocess.check_output((cmd_tshark,
758 '-r', capture_file('ikev2-decrypt-aes256gcm16.pcap'),
759 '-Tfields',
760 '-e', 'isakmp.auth.data',
761 ), encoding='utf-8', env=test_env)
762 assert grep_output(stdout, '9ab71f14ab553cad873a1aa70b99df155dee77cdcf3694b3b7527acbb9712ded')
764 def test_ikev2_aes256gcm8(self, cmd_tshark, capture_file, test_env):
765 '''IKEv2 decryption test (AES-256-GCM-8)'''
766 stdout = subprocess.check_output((cmd_tshark,
767 '-r', capture_file('ikev2-decrypt-aes256gcm8.pcap'),
768 '-Tfields',
769 '-e', 'isakmp.auth.data',
770 ), encoding='utf-8', env=test_env)
771 assert grep_output(stdout, '4a66d822d0afbc22ad9a92a2cf4287c920ad8ac3b069a4a7e75fe0a5d499f914')
774 class TestDecryptHttp2:
775 def test_http2(self, cmd_tshark, capture_file, features, test_env):
776 '''HTTP2 (HPACK)'''
777 if not features.have_nghttp2:
778 pytest.skip('Requires nghttp2.')
779 stdout = subprocess.check_output((cmd_tshark,
780 '-r', capture_file('packet-h2-14_headers.pcapng'),
781 '-Tfields',
782 '-e', 'http2.header.value',
783 '-d', 'tcp.port==3000,http2',
784 ), encoding='utf-8', env=test_env)
785 assert grep_output(stdout, 'nghttp2')
788 class TestDecryptKerberos:
789 def test_kerberos(self, cmd_tshark, dirs, features, capture_file, test_env):
790 '''Kerberos'''
791 # Files are from krb-816.zip on the SampleCaptures page.
792 if not features.have_kerberos:
793 pytest.skip('Requires kerberos.')
794 keytab_file = os.path.join(dirs.key_dir, 'krb-816.keytab')
795 stdout = subprocess.check_output((cmd_tshark,
796 '-r', capture_file('krb-816.pcap.gz'),
797 '-o', 'kerberos.decrypt: TRUE',
798 '-o', 'kerberos.file: {}'.format(keytab_file),
799 '-Tfields',
800 '-e', 'kerberos.keyvalue',
801 ), encoding='utf-8', env=test_env)
802 # keyvalue: ccda7d48219f73c3b28311c4ba7242b3
803 assert grep_output(stdout, 'ccda7d48219f73c3b28311c4ba7242b3')
806 @pytest.fixture
807 def run_wireguard_test(cmd_tshark, capture_file, result_file, features, test_env):
808 def runOne(self, args, keylog=None, pcap_file='wireguard-ping-tcp.pcap'):
809 if keylog:
810 keylog_file = result_file('wireguard.keys')
811 args += ['-owg.keylog_file:%s' % keylog_file]
812 with open(keylog_file, 'w') as f:
813 f.write("\n".join(keylog))
814 stdout = subprocess.check_output([cmd_tshark, '-r', capture_file(pcap_file)] + args, encoding='utf-8', env=test_env)
815 return stdout.splitlines()
816 return runOne
819 class TestDecryptWireguard:
820 # The "foo_alt" keys are similar as "foo" except that some bits are changed.
821 # The crypto library should be able to handle this and internally the
822 # dissector uses MSB to recognize whether a private key is set.
823 key_Spriv_i = 'AKeZaHwBxjiKLFnkY2unvEdOTtg4AL+M9dQXfopFVFk='
824 key_Spriv_i_alt = 'B6eZaHwBxjiKLFnkY2unvEdOTtg4AL+M9dQXfopFVJk='
825 key_Spub_i = 'Igge9KzRytKNwrgkzDE/8hrLu6Ly0OqVdvOPWhA5KR4='
826 key_Spriv_r = 'cFIxTUyBs1Qil414hBwEgvasEax8CKJ5IS5ZougplWs='
827 key_Spub_r = 'YDCttCs9e1J52/g9vEnwJJa+2x6RqaayAYMpSVQfGEY='
828 key_Epriv_i0 = 'sLGLJSOQfyz7JNJ5ZDzFf3Uz1rkiCMMjbWerNYcPFFU='
829 key_Epriv_i0_alt = 't7GLJSOQfyz7JNJ5ZDzFf3Uz1rkiCMMjbWerNYcPFJU='
830 key_Epriv_r0 = 'QC4/FZKhFf0b/eXEcCecmZNt6V6PXmRa4EWG1PIYTU4='
831 key_Epriv_i1 = 'ULv83D+y3vA0t2mgmTmWz++lpVsrP7i4wNaUEK2oX0E='
832 key_Epriv_r1 = 'sBv1dhsm63cbvWMv/XML+bvynBp9PTdY9Vvptu3HQlg='
833 # Ephemeral keys and PSK for wireguard-psk.pcap
834 key_Epriv_i2 = 'iCv2VTi/BC/q0egU931KXrrQ4TSwXaezMgrhh7uCbXs='
835 key_Epriv_r2 = '8G1N3LnEqYC7+NW/b6mqceVUIGBMAZSm+IpwG1U0j0w='
836 key_psk2 = '//////////////////////////////////////////8='
837 key_Epriv_i3 = '+MHo9sfkjPsjCx7lbVhRLDvMxYvTirOQFDSdzAW6kUQ='
838 key_Epriv_r3 = '0G6t5j1B/We65MXVEBIGuRGYadwB2ITdvJovtAuATmc='
839 key_psk3 = 'iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIg='
840 # dummy key that should not work with anything.
841 key_dummy = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx='
843 def test_mac1_public(self, run_wireguard_test):
844 """Check that MAC1 identification using public keys work."""
845 lines = run_wireguard_test(self, [
846 '-ouat:wg_keys:"Public","%s"' % self.key_Spub_i,
847 '-ouat:wg_keys:"Public","%s"' % self.key_Spub_r,
848 '-Y', 'wg.receiver_pubkey',
849 '-Tfields',
850 '-e', 'frame.number',
851 '-e', 'wg.receiver_pubkey',
852 '-e', 'wg.receiver_pubkey.known_privkey',
854 assert len(lines) == 4
855 assert '1\t%s\tFalse' % self.key_Spub_r in lines
856 assert '2\t%s\tFalse' % self.key_Spub_i in lines
857 assert '13\t%s\tFalse' % self.key_Spub_r in lines
858 assert '14\t%s\tFalse' % self.key_Spub_i in lines
860 def test_mac1_private(self, run_wireguard_test):
861 """Check that MAC1 identification using private keys work."""
862 lines = run_wireguard_test(self, [
863 '-ouat:wg_keys:"Private","%s"' % self.key_Spriv_i,
864 '-ouat:wg_keys:"Private","%s"' % self.key_Spriv_r,
865 '-Y', 'wg.receiver_pubkey',
866 '-Tfields',
867 '-e', 'frame.number',
868 '-e', 'wg.receiver_pubkey',
869 '-e', 'wg.receiver_pubkey.known_privkey',
871 assert len(lines) == 4
872 assert '1\t%s\tTrue' % self.key_Spub_r in lines
873 assert '2\t%s\tTrue' % self.key_Spub_i in lines
874 assert '13\t%s\tTrue' % self.key_Spub_r in lines
875 assert '14\t%s\tTrue' % self.key_Spub_i in lines
877 def test_decrypt_initiation_sprivr(self, run_wireguard_test):
878 """Check for partial decryption using Spriv_r."""
879 lines = run_wireguard_test(self, [
880 '-ouat:wg_keys:"Private","%s"' % self.key_Spriv_r,
881 '-Y', 'wg.type==1',
882 '-Tfields',
883 '-e', 'frame.number',
884 '-e', 'wg.static',
885 '-e', 'wg.static.known_pubkey',
886 '-e', 'wg.static.known_privkey',
887 '-e', 'wg.timestamp.nanoseconds',
889 # static pubkey is unknown because Spub_i is not added to wg_keys.
890 assert '1\t%s\tFalse\tFalse\t%s' % (self.key_Spub_i, '356537872') in lines
891 assert '13\t%s\tFalse\tFalse\t%s' % (self.key_Spub_i, '490514356') in lines
893 def test_decrypt_initiation_ephemeral_only(self, run_wireguard_test):
894 """Check for partial decryption using Epriv_i."""
895 lines = run_wireguard_test(self, [
896 '-ouat:wg_keys:"Public","%s"' % self.key_Spub_r,
897 '-Y', 'wg.type==1',
898 '-Tfields',
899 '-e', 'frame.number',
900 '-e', 'wg.ephemeral.known_privkey',
901 '-e', 'wg.static',
902 '-e', 'wg.timestamp.nanoseconds',
903 ], keylog=[
904 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i0,
905 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i1,
907 # The current implementation tries to write as much decrypted data as
908 # possible, even if the full handshake cannot be derived.
909 assert '1\tTrue\t%s\t%s' % (self.key_Spub_i, '') in lines
910 assert '13\tTrue\t%s\t%s' % (self.key_Spub_i, '') in lines
912 def test_decrypt_full_initiator(self, run_wireguard_test):
914 Check for full handshake decryption using Spriv_r + Epriv_i.
915 The public key Spub_r is provided via the key log as well.
917 lines = run_wireguard_test(self, [
918 '-Tfields',
919 '-e', 'frame.number',
920 '-e', 'wg.ephemeral.known_privkey',
921 '-e', 'wg.static',
922 '-e', 'wg.timestamp.nanoseconds',
923 '-e', 'wg.handshake_ok',
924 '-e', 'icmp.type',
925 '-e', 'tcp.dstport',
926 ], keylog=[
927 ' REMOTE_STATIC_PUBLIC_KEY = %s' % self.key_Spub_r,
928 ' LOCAL_STATIC_PRIVATE_KEY = %s' % self.key_Spriv_i_alt,
929 ' LOCAL_EPHEMERAL_PRIVATE_KEY = %s' % self.key_Epriv_i0_alt,
930 ' LOCAL_EPHEMERAL_PRIVATE_KEY = %s' % self.key_Epriv_i1,
932 assert '1\tTrue\t%s\t%s\t\t\t' % (self.key_Spub_i, '356537872') in lines
933 assert '2\tFalse\t\t\tTrue\t\t' in lines
934 assert '3\t\t\t\t\t8\t' in lines
935 assert '4\t\t\t\t\t0\t' in lines
936 assert '13\tTrue\t%s\t%s\t\t\t' % (self.key_Spub_i, '490514356') in lines
937 assert '14\tFalse\t\t\tTrue\t\t' in lines
938 assert '17\t\t\t\t\t\t443' in lines
939 assert '18\t\t\t\t\t\t49472' in lines
941 def test_decrypt_wg_full_initiator_dsb(self, run_wireguard_test):
943 Similar to test_decrypt_full_initiator, but using decryption keys
944 embedded in the pcapng file. The embedded secrets do not contain leading
945 spaces nor spaces around the '=' character.
947 lines = run_wireguard_test(self, [
948 '-Tfields',
949 '-e', 'frame.number',
950 '-e', 'wg.ephemeral.known_privkey',
951 '-e', 'wg.static',
952 '-e', 'wg.timestamp.nanoseconds',
953 '-e', 'wg.handshake_ok',
954 '-e', 'icmp.type',
955 '-e', 'tcp.dstport',
956 ], pcap_file='wireguard-ping-tcp-dsb.pcapng')
957 assert '1\tTrue\t%s\t%s\t\t\t' % (self.key_Spub_i, '356537872') in lines
958 assert '2\tFalse\t\t\tTrue\t\t' in lines
959 assert '3\t\t\t\t\t8\t' in lines
960 assert '4\t\t\t\t\t0\t' in lines
961 assert '13\tTrue\t%s\t%s\t\t\t' % (self.key_Spub_i, '490514356') in lines
962 assert '14\tFalse\t\t\tTrue\t\t' in lines
963 assert '17\t\t\t\t\t\t443' in lines
964 assert '18\t\t\t\t\t\t49472' in lines
966 def test_decrypt_full_responder(self, run_wireguard_test):
967 """Check for full handshake decryption using responder secrets."""
968 lines = run_wireguard_test(self, [
969 '-Tfields',
970 '-e', 'frame.number',
971 '-e', 'wg.ephemeral.known_privkey',
972 '-e', 'wg.static',
973 '-e', 'wg.timestamp.nanoseconds',
974 '-e', 'wg.handshake_ok',
975 '-e', 'icmp.type',
976 '-e', 'tcp.dstport',
977 ], keylog=[
978 'REMOTE_STATIC_PUBLIC_KEY=%s' % self.key_Spub_i,
979 'LOCAL_STATIC_PRIVATE_KEY=%s' % self.key_Spriv_r,
980 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r0,
981 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r1,
983 assert '1\tFalse\t%s\t%s\t\t\t' % (self.key_Spub_i, '356537872') in lines
984 assert '2\tTrue\t\t\tTrue\t\t' in lines
985 assert '3\t\t\t\t\t8\t' in lines
986 assert '4\t\t\t\t\t0\t' in lines
987 assert '13\tFalse\t%s\t%s\t\t\t' % (self.key_Spub_i, '490514356') in lines
988 assert '14\tTrue\t\t\tTrue\t\t' in lines
989 assert '17\t\t\t\t\t\t443' in lines
990 assert '18\t\t\t\t\t\t49472' in lines
992 def test_decrypt_psk_initiator(self, run_wireguard_test):
993 """Check whether PSKs enable decryption for initiation keys."""
994 lines = run_wireguard_test(self, [
995 '-Tfields',
996 '-e', 'frame.number',
997 '-e', 'wg.handshake_ok',
998 ], keylog=[
999 'REMOTE_STATIC_PUBLIC_KEY = %s' % self.key_Spub_r,
1000 'LOCAL_STATIC_PRIVATE_KEY = %s' % self.key_Spriv_i,
1001 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i2,
1002 'PRESHARED_KEY=%s' % self.key_psk2,
1003 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r3,
1004 'PRESHARED_KEY=%s' % self.key_psk3,
1005 ], pcap_file='wireguard-psk.pcap')
1006 assert '2\tTrue' in lines
1007 assert '4\tTrue' in lines
1009 def test_decrypt_psk_responder(self, run_wireguard_test):
1010 """Check whether PSKs enable decryption for responder keys."""
1011 lines = run_wireguard_test(self, [
1012 '-Tfields',
1013 '-e', 'frame.number',
1014 '-e', 'wg.handshake_ok',
1015 ], keylog=[
1016 'REMOTE_STATIC_PUBLIC_KEY=%s' % self.key_Spub_i,
1017 'LOCAL_STATIC_PRIVATE_KEY=%s' % self.key_Spriv_r,
1018 # Epriv_r2 needs psk2. This tests handling of duplicate ephemeral
1019 # keys with multiple PSKs. It should not have adverse effects.
1020 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r2,
1021 'PRESHARED_KEY=%s' % self.key_dummy,
1022 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r2,
1023 'PRESHARED_KEY=%s' % self.key_psk2,
1024 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i3,
1025 'PRESHARED_KEY=%s' % self.key_psk3,
1026 # Epriv_i3 needs psk3, this tests that additional keys again have no
1027 # bad side-effects.
1028 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i3,
1029 'PRESHARED_KEY=%s' % self.key_dummy,
1030 ], pcap_file='wireguard-psk.pcap')
1031 assert '2\tTrue' in lines
1032 assert '4\tTrue' in lines
1034 def test_decrypt_psk_wrong_orderl(self, run_wireguard_test):
1035 """Check that the wrong order of lines indeed fail decryption."""
1036 lines = run_wireguard_test(self, [
1037 '-Tfields',
1038 '-e', 'frame.number',
1039 '-e', 'wg.handshake_ok',
1040 ], keylog=[
1041 'REMOTE_STATIC_PUBLIC_KEY=%s' % self.key_Spub_i,
1042 'LOCAL_STATIC_PRIVATE_KEY=%s' % self.key_Spriv_r,
1043 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r2,
1044 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i3,
1045 'PRESHARED_KEY=%s' % self.key_psk2, # note: swapped with previous line
1046 'PRESHARED_KEY=%s' % self.key_psk3,
1047 ], pcap_file='wireguard-psk.pcap')
1048 assert '2\tFalse' in lines
1049 assert '4\tFalse' in lines
1052 class TestDecryptKnxip:
1053 # Capture files for these tests contain single telegrams.
1054 # For realistic (live captured) KNX/IP telegram sequences, see:
1055 # https://gitlab.com/wireshark/wireshark/-/issues/14825
1057 def test_knxip_data_security_decryption_ok(self, cmd_tshark, capture_file, test_env):
1058 '''KNX/IP: Data Security decryption OK'''
1059 # capture_file('knxip_DataSec.pcap') contains KNX/IP ConfigReq DataSec PropExtValueWriteCon telegram
1060 stdout = subprocess.check_output((cmd_tshark,
1061 '-r', capture_file('knxip_DataSec.pcap'),
1062 '-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
1063 ), encoding='utf-8', env=test_env)
1064 assert grep_output(stdout, ' DataSec ')
1065 assert grep_output(stdout, ' PropExtValueWriteCon ')
1067 def test_knxip_data_security_decryption_fails(self, cmd_tshark, capture_file, test_env):
1068 '''KNX/IP: Data Security decryption fails'''
1069 # capture_file('knxip_DataSec.pcap') contains KNX/IP ConfigReq DataSec PropExtValueWriteCon telegram
1070 stdout = subprocess.check_output((cmd_tshark,
1071 '-r', capture_file('knxip_DataSec.pcap'),
1072 '-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
1073 ), encoding='utf-8', env=test_env)
1074 assert grep_output(stdout, ' DataSec ')
1075 assert not grep_output(stdout, ' PropExtValueWriteCon ')
1077 def test_knxip_secure_wrapper_decryption_ok(self, cmd_tshark, capture_file, test_env):
1078 '''KNX/IP: SecureWrapper decryption OK'''
1079 # capture_file('knxip_SecureWrapper.pcap') contains KNX/IP SecureWrapper RoutingInd telegram
1080 stdout = subprocess.check_output((cmd_tshark,
1081 '-r', capture_file('knxip_SecureWrapper.pcap'),
1082 '-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
1083 ), encoding='utf-8', env=test_env)
1084 assert grep_output(stdout, ' SecureWrapper ')
1085 assert grep_output(stdout, ' RoutingInd ')
1087 def test_knxip_secure_wrapper_decryption_fails(self, cmd_tshark, capture_file, test_env):
1088 '''KNX/IP: SecureWrapper decryption fails'''
1089 # capture_file('knxip_SecureWrapper.pcap') contains KNX/IP SecureWrapper RoutingInd telegram
1090 stdout = subprocess.check_output((cmd_tshark,
1091 '-r', capture_file('knxip_SecureWrapper.pcap'),
1092 '-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
1093 ), encoding='utf-8', env=test_env)
1094 assert grep_output(stdout, ' SecureWrapper ')
1095 assert not grep_output(stdout, ' RoutingInd ')
1097 def test_knxip_timer_notify_authentication_ok(self, cmd_tshark, capture_file, test_env):
1098 '''KNX/IP: TimerNotify authentication OK'''
1099 # capture_file('knxip_TimerNotify.pcap') contains KNX/IP TimerNotify telegram
1100 stdout = subprocess.check_output((cmd_tshark,
1101 '-r', capture_file('knxip_TimerNotify.pcap'),
1102 '-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
1103 ), encoding='utf-8', env=test_env)
1104 assert grep_output(stdout, ' TimerNotify ')
1105 assert grep_output(stdout, ' OK$')
1107 def test_knxip_timer_notify_authentication_fails(self, cmd_tshark, capture_file, test_env):
1108 '''KNX/IP: TimerNotify authentication fails'''
1109 # capture_file('knxip_TimerNotify.pcap') contains KNX/IP TimerNotify telegram
1110 stdout = subprocess.check_output((cmd_tshark,
1111 '-r', capture_file('knxip_TimerNotify.pcap'),
1112 '-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
1113 ), encoding='utf-8', env=test_env)
1114 assert grep_output(stdout, ' TimerNotify ')
1115 assert not grep_output(stdout, ' OK$')
1117 def test_knxip_keyring_xml_import(self, cmd_tshark, dirs, capture_file, test_env):
1118 '''KNX/IP: keyring.xml import'''
1119 # key_file "keyring.xml" contains KNX decryption keys
1120 key_file = os.path.join(dirs.key_dir, 'knx_keyring.xml')
1121 # capture_file('empty.pcap') is empty
1122 # Write extracted key info to stdout
1123 stdout = subprocess.check_output((cmd_tshark,
1124 '-o', 'kip.key_file:' + key_file,
1125 '-o', 'kip.key_info_file:-',
1126 '-r', capture_file('empty.pcap'),
1127 ), encoding='utf-8', env=test_env)
1128 assert grep_output(stdout, '^MCA 224[.]0[.]23[.]12 key A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF$')
1129 assert grep_output(stdout, '^GA 1/7/131 sender 1[.]1[.]1$')
1130 assert grep_output(stdout, '^GA 1/7/131 sender 1[.]1[.]3$')
1131 assert grep_output(stdout, '^GA 1/7/131 sender 1[.]1[.]4$')
1132 assert grep_output(stdout, '^GA 1/7/132 sender 1[.]1[.]2$')
1133 assert grep_output(stdout, '^GA 1/7/132 sender 1[.]1[.]4$')
1134 assert grep_output(stdout, '^GA 6/7/191 sender 1[.]1[.]1$')
1135 assert grep_output(stdout, '^GA 0/1/0 sender 1[.]1[.]1$')
1136 assert grep_output(stdout, '^GA 0/1/0 sender 1[.]1[.]3$')
1137 assert grep_output(stdout, '^GA 0/1/0 sender 1[.]1[.]4$')
1138 assert grep_output(stdout, '^GA 0/1/0 key A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF$')
1139 assert grep_output(stdout, '^GA 1/7/131 key A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF$')
1140 assert grep_output(stdout, '^GA 1/7/132 key A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF$')
1141 assert grep_output(stdout, '^GA 6/7/191 key A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 AA AB AC AD AE AF$')
1142 assert grep_output(stdout, '^IA 1[.]1[.]1 key B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF$')
1143 assert grep_output(stdout, '^IA 1[.]1[.]1 SeqNr 45678$')
1144 assert grep_output(stdout, '^IA 1[.]1[.]2 key B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF$')
1145 assert grep_output(stdout, '^IA 1[.]1[.]2 SeqNr 34567$')
1146 assert grep_output(stdout, '^IA 1[.]1[.]3 key B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF$')
1147 assert grep_output(stdout, '^IA 1[.]1[.]3 SeqNr 23456$')
1148 assert grep_output(stdout, '^IA 1[.]1[.]4 key B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF$')
1149 assert grep_output(stdout, '^IA 1[.]1[.]4 SeqNr 12345$')
1150 assert grep_output(stdout, '^IA 2[.]1[.]0 key B0 B1 B2 B3 B4 B5 B6 B7 B8 B9 BA BB BC BD BE BF$')
1151 assert grep_output(stdout, '^IA 2[.]1[.]0 SeqNr 1234$')
1154 @pytest.fixture(scope='session')
1155 def softhsm_paths(features):
1156 if sys.platform == 'win32':
1157 search_path = os.getenv('PATH') + r';C:\SoftHSM2\bin'
1158 else:
1159 search_path = None
1160 softhsm_tool = shutil.which('softhsm2-util', path=search_path)
1161 if not softhsm_tool:
1162 # Note: do not fallback to SoftHSMv1. While available on Ubuntu 14.04
1163 # (and 16.04), it is built with botan < 1.11.10 which causes a crash due
1164 # to a conflict with the GMP library that is also used by GnuTLS/nettle.
1165 # See https://github.com/randombit/botan/issues/1090
1166 pytest.skip('SoftHSM is not found')
1167 # Find provider library path.
1168 bindir = os.path.dirname(softhsm_tool)
1169 libdir = os.path.join(os.path.dirname(bindir), 'lib')
1170 if sys.platform == 'win32':
1171 libdirs = [libdir, bindir]
1172 if features.have_x64:
1173 name = 'softhsm2-x64.dll'
1174 else:
1175 name = 'softhsm2.dll'
1176 else:
1177 # Look in a variety of paths, Debian/Ubuntu, Fedora, RHEL/CentOS
1178 madir = sysconfig.get_config_var('multiarchsubdir')
1179 libdir_archs = (libdir, libdir + '64')
1180 libdir_subs = ('softhsm', 'pkcs11', '')
1181 libdirs = [os.path.join(libdir + madir, 'softhsm')] if madir else []
1182 libdirs += [os.path.join(arch, sub) for sub in libdir_subs for arch in libdir_archs]
1183 name = 'libsofthsm2.so'
1184 for libdir in libdirs:
1185 provider = os.path.join(libdir, name)
1186 if os.path.exists(provider):
1187 break
1188 else:
1189 # Even if p11-kit can automatically locate it, do not rely on it.
1190 pytest.skip('SoftHSM provider library not detected')
1191 # Now check whether the import tool is usable. SoftHSM < 2.3.0 did not
1192 # set CKA_DECRYPT when using softhsm2-tool --import and therefore cannot be
1193 # used to import keys for decryption. Use GnuTLS p11tool as workaround.
1194 softhsm_version = subprocess.check_output([softhsm_tool, '--version'],
1195 universal_newlines=True).strip()
1196 use_p11tool = softhsm_version in ('2.0.0', '2.1.0', '2.2.0')
1197 if use_p11tool and not shutil.which('p11tool'):
1198 pytest.skip('SoftHSM available, but GnuTLS p11tool is unavailable')
1199 return use_p11tool, softhsm_tool, provider
1202 @pytest.fixture
1203 def softhsm(softhsm_paths, home_path, base_env):
1204 '''Creates a temporary SoftHSM token store (and set it in the environment),
1205 returns a function to populate that token store and the path to the PKCS #11
1206 provider library.'''
1207 use_p11tool, softhsm_tool, provider = softhsm_paths
1208 conf_path = os.path.join(home_path, 'softhsm-test.conf')
1209 db_path = os.path.join(home_path, 'softhsm-test-tokens')
1210 os.makedirs(db_path)
1211 with open(conf_path, 'w') as f:
1212 f.write('directories.tokendir = %s\n' % db_path)
1213 f.write('objectstore.backend = file\n')
1214 # Avoid syslog spam
1215 f.write('log.level = ERROR\n')
1216 base_env['SOFTHSM2_CONF'] = conf_path
1218 tool_env = base_env.copy()
1219 if sys.platform == 'win32':
1220 # Ensure that softhsm2-util can find the library.
1221 tool_env['PATH'] += ';%s' % os.path.dirname(provider)
1223 # Initialize tokens store.
1224 token_name = 'Wireshark-Test-Tokens'
1225 pin = 'Secret'
1226 subprocess.check_call([softhsm_tool, '--init-token', '--slot', '0',
1227 '--label', token_name, '--so-pin', 'Supersecret', '--pin', pin],
1228 env=tool_env)
1229 if use_p11tool:
1230 tool_env['GNUTLS_PIN'] = pin
1232 # Arbitrary IDs and labels.
1233 ids = iter(range(0xab12, 0xffff))
1234 def import_key(keyfile):
1235 '''Returns a PKCS #11 URI to identify the imported key.'''
1236 label = os.path.basename(keyfile)
1237 obj_id = '%x' % next(ids)
1238 if not use_p11tool:
1239 tool_args = [softhsm_tool, '--import', keyfile, '--label', label,
1240 '--id', obj_id, '--pin', pin, '--token', token_name]
1241 else:
1242 # Fallback for SoftHSM < 2.3.0
1243 tool_args = ['p11tool', '--provider', provider, '--batch',
1244 '--login', '--write', 'pkcs11:token=%s' % token_name,
1245 '--load-privkey', keyfile, '--label', label, '--id', obj_id]
1246 subprocess.check_call(tool_args, env=tool_env)
1247 id_str = '%{}{}%{}{}'.format(*obj_id)
1248 return 'pkcs11:token=%s;id=%s;type=private' % (token_name, id_str)
1250 return types.SimpleNamespace(import_key=import_key, provider=provider, pin=pin)
1253 class TestDecryptPkcs11:
1254 def test_tls_pkcs11(self, cmd_tshark, dirs, capture_file, features, softhsm, test_env):
1255 '''Check that a RSA key in a PKCS #11 token enables decryption.'''
1256 if not features.have_pkcs11:
1257 pytest.skip('Requires GnuTLS with PKCS #11 support.')
1258 key_file = os.path.join(dirs.key_dir, 'rsa-p-lt-q.p8')
1259 key_uri = softhsm.import_key(key_file)
1260 stdout = subprocess.check_output((cmd_tshark,
1261 '-r', capture_file('rsa-p-lt-q.pcap'),
1262 '-o', 'uat:pkcs11_libs:"{}"'.format(softhsm.provider.replace('\\', '\\x5c')),
1263 '-o', 'uat:rsa_keys:"{}","{}"'.format(key_uri, softhsm.pin),
1264 '-Tfields',
1265 '-e', 'http.request.uri',
1266 '-Y', 'http',
1267 ), encoding='utf-8', env=test_env)
1268 assert '/' in stdout
1270 class TestDecryptSmb2:
1271 BAD_KEY = 'ffffffffffffffffffffffffffffffff'
1273 @staticmethod
1274 def check_bad_key(cmd_tshark, cap, disp_filter, sesid, seskey, s2ckey, c2skey, env=None):
1275 stdout = subprocess.check_output((cmd_tshark,
1276 '-r', cap,
1277 '-o', 'uat:smb2_seskey_list:{},{},{},{}'.format(sesid, seskey, s2ckey, c2skey),
1278 '-Y', disp_filter,
1279 ), encoding='utf-8', env=env)
1280 assert 'Encrypted SMB' in stdout
1283 # SMB3.0 CCM bad keys tests
1285 def test_smb300_bad_seskey(self, features, cmd_tshark, capture_file, test_env):
1286 '''Check that a bad session key doesn't crash'''
1287 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
1288 'frame.number == 7', '1900009c003c0000', self.BAD_KEY, '""', '""', env=test_env)
1290 def test_smb300_bad_s2ckey(self, features, cmd_tshark, capture_file, test_env):
1291 '''Check that a bad s2c key doesn't crash'''
1292 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
1293 'frame.number == 7', '1900009c003c0000', '""', self.BAD_KEY, '""', env=test_env)
1295 def test_smb300_bad_c2skey(self, features, cmd_tshark, capture_file, test_env):
1296 '''Check that a bad c2s key doesn't crash'''
1297 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
1298 'frame.number == 7', '1900009c003c0000', '""', '""', self.BAD_KEY, env=test_env)
1300 def test_smb300_bad_deckey(self, features, cmd_tshark, capture_file, test_env):
1301 '''Check that bad decryption keys doesn't crash'''
1302 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
1303 'frame.number == 7', '1900009c003c0000', '""', self.BAD_KEY, self.BAD_KEY, env=test_env)
1305 def test_smb300_bad_allkey(self, features, cmd_tshark, capture_file, test_env):
1306 '''Check that all bad keys doesn't crash'''
1307 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
1308 'frame.number == 7', '1900009c003c0000', self.BAD_KEY, self.BAD_KEY, self.BAD_KEY, env=test_env)
1311 # SMB3.1.1 CCM bad key tests
1313 def test_smb311_bad_seskey(self, features, cmd_tshark, capture_file, test_env):
1314 '''Check that a bad session key doesn't crash'''
1315 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
1316 'frame.number == 7', '2900009c003c0000', self.BAD_KEY, '""', '""', env=test_env)
1318 def test_smb311_bad_s2ckey(self, features, cmd_tshark, capture_file, test_env):
1319 '''Check that a bad s2c key doesn't crash'''
1320 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
1321 'frame.number == 7', '2900009c003c0000', '""', self.BAD_KEY, '""', env=test_env)
1323 def test_smb311_bad_c2skey(self, features, cmd_tshark, capture_file, test_env):
1324 '''Check that a bad c2s key doesn't crash'''
1325 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
1326 'frame.number == 7', '2900009c003c0000', '""', '""', self.BAD_KEY, env=test_env)
1328 def test_smb311_bad_deckey(self, features, cmd_tshark, capture_file, test_env):
1329 '''Check that bad decryption keys doesn't crash'''
1330 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
1331 'frame.number == 7', '2900009c003c0000', '""', self.BAD_KEY, self.BAD_KEY, env=test_env)
1333 def test_smb311_bad_allkey(self, features, cmd_tshark, capture_file, test_env):
1334 '''Check that all bad keys doesn't crash'''
1335 TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
1336 'frame.number == 7', '2900009c003c0000', self.BAD_KEY, self.BAD_KEY, self.BAD_KEY, env=test_env)
1339 # Decryption tests
1342 def check_tree(cmd_tshark, cap, tree, sesid, seskey, s2ckey, c2skey, env=None):
1343 stdout = subprocess.check_output((cmd_tshark,
1344 '-r', cap,
1345 '-o', 'uat:smb2_seskey_list:{},{},{},{}'.format(sesid, seskey, s2ckey, c2skey),
1346 '-Tfields',
1347 '-e', 'smb2.tree',
1348 '-Y', 'smb2.tree == "{}"'.format(tree.replace('\\', '\\\\')),
1349 ), encoding='unicode_escape', env=env)
1350 # Remove the escapes (we only have one field so this causes no issue)
1351 assert tree == stdout.strip()
1353 # SMB3.0 CCM
1354 def test_smb300_aes128ccm_seskey(self, features, cmd_tshark, capture_file, test_env):
1355 '''Check SMB 3.0 AES128CCM decryption with session key.'''
1356 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
1357 r'\\dfsroot1.foo.test\IPC$', '1900009c003c0000',
1358 '9a9ea16a0cdbeb6064772318073f172f', '""', '""', env=test_env)
1360 def test_smb300_aes128ccm_deckey(self, features, cmd_tshark, capture_file, test_env):
1361 '''Check SMB 3.0 AES128CCM decryption with decryption keys.'''
1362 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
1363 r'\\dfsroot1.foo.test\IPC$', '1900009c003c0000',
1364 '""', '8be6cc53d4beba29387e69aef035d497','bff985870e81784d533fdc09497b8eab', env=test_env)
1367 # SMB3.1.1 AES-CCM-128
1368 def test_smb311_aes128ccm_seskey(self, features, cmd_tshark, capture_file, test_env):
1369 '''Check SMB 3.1.1 AES128CCM decryption with session key.'''
1370 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
1371 r'\\dfsroot1.foo.test\IPC$', '2900009c003c0000',
1372 'f1fa528d3cd182cca67bd4596dabd885', '""', '""', env=test_env)
1374 def test_smb311_aes128ccm_deckey(self, features, cmd_tshark, capture_file, test_env):
1375 '''Check SMB 3.1.1 AES128CCM decryption with decryption keys.'''
1376 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
1377 r'\\dfsroot1.foo.test\IPC$', '2900009c003c0000',
1378 '""', '763d5552dbc9650b700869467a5857e4', '35e69833c6578e438c8701cb40bf483e', env=test_env)
1380 # SMB3.1.1 AES-GCM-128
1381 def test_smb311_aes128gcm_seskey(self, features, cmd_tshark, capture_file, test_env):
1382 '''Check SMB 3.1.1 AES128GCM decryption with session key.'''
1383 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-128-gcm.pcap.gz'),
1384 r'\\dfsroot1.foo.test\IPC$', '3900000000400000',
1385 'e79161ded03bda1449b2c8e58f753953', '""', '""', env=test_env)
1387 def test_smb311_aes128gcm_deckey(self, features, cmd_tshark, capture_file, test_env):
1388 '''Check SMB 3.1.1 AES128GCM decryption with decryption keys.'''
1389 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-128-gcm.pcap.gz'),
1390 r'\\dfsroot1.foo.test\IPC$', '3900000000400000',
1391 '""', 'b02f5de25e0562075c3dc329fa2aa396', '7201623a31754e6581864581209dd3d2', env=test_env)
1393 # SMB3.1.1 AES-CCM-256
1394 def test_smb311_aes256ccm_seskey(self, features, cmd_tshark, capture_file, test_env):
1395 '''Check SMB 3.1.1 AES256CCM decryption with session key.'''
1396 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-256-ccm.pcap.gz'),
1397 r'\\172.31.9.163\IPC$', 'd6fdb96d00000000',
1398 '6b559c2e60519e344581d086a6d3d050',
1399 '""',
1400 '""', env=test_env)
1402 def test_smb311_aes256ccm_deckey(self, features, cmd_tshark, capture_file, test_env):
1403 '''Check SMB 3.1.1 AES256CCM decryption with decryption keys.'''
1404 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-256-ccm.pcap.gz'),
1405 r'\\172.31.9.163\IPC$', 'd6fdb96d00000000',
1406 '""',
1407 '014fccd4a53554bf5b54b27a32512b35fca262b90e088a5efa7d6c952418578b',
1408 '1d34170138a77dac4abbe0149253c8b977a71f399081cda6cbaf62359670c1c5', env=test_env)
1410 # SMB3.1.1 AES-GCM-256
1411 def test_smb311_aes256gcm_seskey(self, features, cmd_tshark, capture_file, test_env):
1412 '''Check SMB 3.1.1 AES256GCM decryption with session key.'''
1413 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-256-gcm.pcap.gz'),
1414 r'\\172.31.9.163\IPC$', '56dc03ab00000000',
1415 '6a5004adfbdef1abd5879800675324e5',
1416 '""',
1417 '""', env=test_env)
1419 def test_smb311_aes256gcm_deckey(self, features, cmd_tshark, capture_file, test_env):
1420 '''Check SMB 3.1.1 AES256GCM decryption with decryption keys.'''
1421 TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-256-gcm.pcap.gz'),
1422 r'\\172.31.9.163\IPC$', '56dc03ab00000000',
1423 '""',
1424 '46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f',
1425 '484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4', env=test_env)
1427 def check_partial(home_path, cmd_tshark, full_cap, pkt_skip, tree, sesid, s2ckey, c2skey, env=None):
1428 # generate a trace without NegProt and SessionSetup
1429 partial_cap = os.path.join(home_path, 'short.pcap')
1430 stdout = subprocess.check_output((cmd_tshark,
1431 '-r', full_cap,
1432 '-Y', 'frame.number >= %d'%pkt_skip,
1433 '-w', partial_cap,
1434 ), encoding='utf-8', env=env)
1435 TestDecryptSmb2.check_tree(cmd_tshark, partial_cap, tree, sesid, '""', s2ckey, c2skey)
1437 def test_smb311_aes128gcm_partial(self, features, home_path, cmd_tshark, capture_file, test_env):
1438 '''Check SMB 3.1.1 AES128GCM decryption in capture missing session setup'''
1439 TestDecryptSmb2.check_partial(home_path, cmd_tshark,
1440 capture_file('smb311-aes-128-gcm.pcap.gz'), 7,
1441 r'\\dfsroot1.foo.test\IPC$', '3900000000400000',
1442 'b02f5de25e0562075c3dc329fa2aa396', '7201623a31754e6581864581209dd3d2', env=test_env)
1444 def test_smb311_aes128gcm_partial_keyswap(self, features, home_path, cmd_tshark, capture_file, test_env):
1445 '''Check SMB 3.1.1 AES128GCM decryption in capture missing session setup with keys in wrong order'''
1446 TestDecryptSmb2.check_partial(home_path, cmd_tshark,
1447 capture_file('smb311-aes-128-gcm.pcap.gz'), 7,
1448 r'\\dfsroot1.foo.test\IPC$', '3900000000400000',
1449 '7201623a31754e6581864581209dd3d2', 'b02f5de25e0562075c3dc329fa2aa396', env=test_env)
1451 def test_smb311_aes256gcm_partial(self, features, home_path, cmd_tshark, capture_file, test_env):
1452 '''Check SMB 3.1.1 AES128GCM decryption in capture missing session setup'''
1453 TestDecryptSmb2.check_partial(home_path, cmd_tshark,
1454 capture_file('smb311-aes-256-gcm.pcap.gz'), 7,
1455 r'\\172.31.9.163\IPC$', '56dc03ab00000000',
1456 '46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f',
1457 '484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4', env=test_env)
1459 def test_smb311_aes256gcm_partial_keyswap(self, features, home_path, cmd_tshark, capture_file, test_env):
1460 '''Check SMB 3.1.1 AES256GCM decryption in capture missing session setup with keys in wrong order'''
1461 TestDecryptSmb2.check_partial(home_path, cmd_tshark,
1462 capture_file('smb311-aes-256-gcm.pcap.gz'), 7,
1463 r'\\172.31.9.163\IPC$', '56dc03ab00000000',
1464 '484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4',
1465 '46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f', env=test_env)