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
14 from subprocesstest
import grep_output
, count_output
21 class TestDecrypt80211
:
22 def test_80211_wep(self
, cmd_tshark
, capture_file
, test_env
):
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',
38 '-e', 'http.request.uri',
39 '-r', capture_file('wpa-Induction.pcap.gz'),
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'),
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'),
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'),
169 '-e' 'wlan.fc.type_subtype',
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
):
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'),
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',
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'),
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'),
387 '-e', 'http.request.uri',
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
),
402 '-e', 'http.request.uri',
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')),
416 '-e', 'http.request.uri',
418 ), encoding
='utf-8', env
=test_env
)
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'),
428 '-e', 'http.request.uri',
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',
442 '-e', 'http.request.method',
443 '-e', 'http.request.uri',
444 '-e', 'http.request.version',
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',
460 '-e', 'http.content_length',
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',
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',
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')
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',
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
),
505 '-z', 'follow,tls,ascii,{}'.format(stream
),
506 ), encoding
='utf-8', env
=test_env
)
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
),
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
),
529 '-e', 'frame.number',
530 '-e', 'http.request.uri',
531 '-e', 'http.file_data',
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")
539 # fr'6||{first_response}',
541 # fr'10||{early_response}',
543 # fr'13||{second_response}',
544 # ] == stdout.splitlines()
548 fr
'6|/first|{first_response}',
550 fr
'10|/early|{early_response}',
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
),
563 '-e', 'frame.number',
564 '-e', 'http.request.uri',
565 '-e', 'http.file_data',
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")
573 # fr'6||{first_response}',
574 # fr'10||{early_response}',
576 # fr'13||{second_response}',
577 # ] == stdout.splitlines()
581 fr
'6|/first|{first_response}',
582 fr
'10||{early_response}',
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'),
593 '-e', 'http.response.code',
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',
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
):
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'),
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
):
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',
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
):
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',
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
):
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',
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'),
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'),
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'),
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'),
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'),
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'),
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'),
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'),
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'),
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'),
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'),
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
):
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'),
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
):
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
),
800 '-e', 'kerberos.keyvalue',
801 ), encoding
='utf-8', env
=test_env
)
802 # keyvalue: ccda7d48219f73c3b28311c4ba7242b3
803 assert grep_output(stdout
, 'ccda7d48219f73c3b28311c4ba7242b3')
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'):
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()
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',
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',
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
,
883 '-e', 'frame.number',
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
,
899 '-e', 'frame.number',
900 '-e', 'wg.ephemeral.known_privkey',
902 '-e', 'wg.timestamp.nanoseconds',
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
, [
919 '-e', 'frame.number',
920 '-e', 'wg.ephemeral.known_privkey',
922 '-e', 'wg.timestamp.nanoseconds',
923 '-e', 'wg.handshake_ok',
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
, [
949 '-e', 'frame.number',
950 '-e', 'wg.ephemeral.known_privkey',
952 '-e', 'wg.timestamp.nanoseconds',
953 '-e', 'wg.handshake_ok',
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
, [
970 '-e', 'frame.number',
971 '-e', 'wg.ephemeral.known_privkey',
973 '-e', 'wg.timestamp.nanoseconds',
974 '-e', 'wg.handshake_ok',
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
, [
996 '-e', 'frame.number',
997 '-e', 'wg.handshake_ok',
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
, [
1013 '-e', 'frame.number',
1014 '-e', 'wg.handshake_ok',
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
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
, [
1038 '-e', 'frame.number',
1039 '-e', 'wg.handshake_ok',
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'
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'
1175 name
= 'softhsm2.dll'
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
):
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
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')
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'
1226 subprocess
.check_call([softhsm_tool
, '--init-token', '--slot', '0',
1227 '--label', token_name
, '--so-pin', 'Supersecret', '--pin', pin
],
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
)
1239 tool_args
= [softhsm_tool
, '--import', keyfile
, '--label', label
,
1240 '--id', obj_id
, '--pin', pin
, '--token', token_name
]
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
),
1265 '-e', 'http.request.uri',
1267 ), encoding
='utf-8', env
=test_env
)
1268 assert '/' in stdout
1270 class TestDecryptSmb2
:
1271 BAD_KEY
= 'ffffffffffffffffffffffffffffffff'
1274 def check_bad_key(cmd_tshark
, cap
, disp_filter
, sesid
, seskey
, s2ckey
, c2skey
, env
=None):
1275 stdout
= subprocess
.check_output((cmd_tshark
,
1277 '-o', 'uat:smb2_seskey_list:{},{},{},{}'.format(sesid
, seskey
, s2ckey
, c2skey
),
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
)
1342 def check_tree(cmd_tshark
, cap
, tree
, sesid
, seskey
, s2ckey
, c2skey
, env
=None):
1343 stdout
= subprocess
.check_output((cmd_tshark
,
1345 '-o', 'uat:smb2_seskey_list:{},{},{},{}'.format(sesid
, seskey
, s2ckey
, c2skey
),
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()
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',
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',
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',
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',
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
,
1432 '-Y', 'frame.number >= %d'%pkt_skip
,
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
)