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 def test_80211_wpa3_ft_sae_h2e(self
, cmd_tshark
, capture_file
, test_env
):
270 '''IEEE 802.11 decode WPA3 FT SAE H2E'''
271 # Included in git sources test/captures/wpa3-ft-sae-h2e.pcapng.gz
272 stdout
= subprocess
.check_output((cmd_tshark
,
273 '-o', 'wlan.enable_decryption: TRUE',
274 '-r', capture_file('wpa3-ft-sae-h2e.pcapng.gz'),
275 '-Y', 'wlan.analysis.tk == 8c75edf396af8dea241eb72b2793489b || wlan.analysis.gtk == a31a5307ed7b250603cf1a33d1c1eee6 || wlan.analysis.tk == e80866b0ed3b534e1a924a1674e664ba',
276 ), encoding
='utf-8', env
=test_env
)
277 assert count_output(stdout
, 'DHCP Request') == 4
278 assert count_output(stdout
, 'DHCP ACK') == 2
279 assert count_output(stdout
, 'ARP.*Who has') == 4
280 assert count_output(stdout
, 'ARP.*is at') == 2
281 assert count_output(stdout
, r
'ICMP.*Echo \(ping\)') == 4
283 class TestDecrypt80211UserTk
:
284 def test_80211_user_tk_tkip(self
, cmd_tshark
, capture_file
, test_env
):
285 '''IEEE 802.11 decode TKIP using user TK'''
286 # Included in git sources test/captures/wpa1-gtk-rekey.pcapng.gz
287 stdout
= subprocess
.check_output((cmd_tshark
,
288 '-o', 'wlan.enable_decryption: TRUE',
289 '-r', capture_file('wpa1-gtk-rekey.pcapng.gz'),
290 '-Y', 'wlan.analysis.tk == "d0e57d224c1bb8806089d8c23154074c" || wlan.analysis.gtk == "6eaf63f4ad7997ced353723de3029f4d" || wlan.analysis.gtk == "fb42811bcb59b7845376246454fbdab7"',
291 ), encoding
='utf-8', env
=test_env
)
292 assert grep_output(stdout
, 'DHCP Discover')
293 assert count_output(stdout
, 'ICMP.*Echo .ping') == 8
295 def test_80211_user_tk_ccmp(self
, cmd_tshark
, capture_file
, features
, test_env
):
296 '''IEEE 802.11 decode CCMP-128 using user TK'''
297 # Included in git sources test/captures/wpa2-psk-mfp.pcapng.gz
298 stdout
= subprocess
.check_output((cmd_tshark
,
299 '-o', 'wlan.enable_decryption: TRUE',
300 '-r', capture_file('wpa2-psk-mfp.pcapng.gz'),
301 '-Y', 'wlan.analysis.tk == 4e30e8c019bea43ea5262b10853b818d || wlan.analysis.gtk == 70cdbf2e5bc0ca22e53930818a5d80e4',
302 ), encoding
='utf-8', env
=test_env
)
303 assert grep_output(stdout
, 'Who has 192.168.5.5') # Verifies GTK decryption
304 assert grep_output(stdout
, 'DHCP Request') # Verifies TK decryption
305 assert grep_output(stdout
, r
'Echo \(ping\) request') # Verifies TK decryption
307 def test_80211_user_tk_ccmp_256(self
, cmd_tshark
, capture_file
, features
, test_env
):
308 '''IEEE 802.11 decode CCMP-256 using user TK'''
309 # Included in git sources test/captures/wpa-ccmp-256.pcapng.gz
310 stdout
= subprocess
.check_output((cmd_tshark
,
311 '-o', 'wlan.enable_decryption: TRUE',
312 '-r', capture_file('wpa-ccmp-256.pcapng.gz'),
313 '-Y', 'wlan.analysis.tk == 4e6abbcf9dc0943936700b6825952218f58a47dfdf51dbb8ce9b02fd7d2d9e40 || wlan.analysis.gtk == 502085ca205e668f7e7c61cdf4f731336bb31e4f5b28ec91860174192e9b2190',
314 ), encoding
='utf-8', env
=test_env
)
315 assert grep_output(stdout
, 'Who has 192.168.5.5') # Verifies GTK decryption
316 assert grep_output(stdout
, 'DHCP Request') # Verifies TK decryption
317 assert grep_output(stdout
, r
'Echo \(ping\) request') # Verifies TK decryption
319 def test_80211_user_tk_gcmp(self
, cmd_tshark
, capture_file
, features
, test_env
):
320 '''IEEE 802.11 decode GCMP using user TK'''
321 # Included in git sources test/captures/wpa-gcmp.pcapng.gz
322 stdout
= subprocess
.check_output((cmd_tshark
,
323 '-o', 'wlan.enable_decryption: TRUE',
324 '-r', capture_file('wpa-gcmp.pcapng.gz'),
325 '-Y', 'wlan.analysis.tk == 755a9c1c9e605d5ff62849e4a17a935c || wlan.analysis.gtk == 7ff30f7a8dd67950eaaf2f20a869a62d',
326 ), encoding
='utf-8', env
=test_env
)
327 assert grep_output(stdout
, 'Who has 192.168.5.5') # Verifies GTK decryption
328 assert grep_output(stdout
, 'DHCP Request') # Verifies TK decryption
329 assert grep_output(stdout
, r
'Echo \(ping\) request') # Verifies TK decryption
331 def test_80211_wpa_gcmp_256(self
, cmd_tshark
, capture_file
, features
, test_env
):
332 '''IEEE 802.11 decode GCMP-256 using user TK'''
333 # Included in git sources test/captures/wpa-gcmp-256.pcapng.gz
334 stdout
= subprocess
.check_output((cmd_tshark
,
335 '-o', 'wlan.enable_decryption: TRUE',
336 '-r', capture_file('wpa-gcmp-256.pcapng.gz'),
337 '-Y', 'wlan.analysis.tk == b3dc2ff2d88d0d34c1ddc421cea17f304af3c46acbbe7b6d808b6ebf1b98ec38 || wlan.analysis.gtk == a745ee2313f86515a155c4cb044bc148ae234b9c72707f772b69c2fede3e4016',
338 ), encoding
='utf-8', env
=test_env
)
339 assert grep_output(stdout
, 'Who has 192.168.5.5') # Verifies GTK decryption
340 assert grep_output(stdout
, 'DHCP Request') # Verifies TK decryption
341 assert grep_output(stdout
, r
'Echo \(ping\) request') # Verifies TK decryption
344 class TestDecryptDTLS
:
345 def test_dtls_rsa(self
, cmd_tshark
, capture_file
, features
, test_env
):
347 if not features
.have_gnutls
:
348 pytest
.skip('Requires GnuTLS.')
349 # https://gitlab.com/wireshark/wireshark/-/wikis/uploads/__moin_import__/attachments/SampleCaptures/snakeoil.tgz
350 stdout
= subprocess
.check_output((cmd_tshark
,
351 '-r', capture_file('snakeoil-dtls.pcap'),
355 ), encoding
='utf-8', env
=test_env
)
356 assert grep_output(stdout
, '697420776f726b20210a')
358 def test_dtls_psk_aes128ccm8(self
, cmd_tshark
, capture_file
, test_env
):
359 '''DTLS 1.2 with PSK, AES-128-CCM-8'''
360 stdout
= subprocess
.check_output((cmd_tshark
,
361 '-r', capture_file('dtls12-aes128ccm8.pcap'),
362 '-o', 'dtls.psk:ca19e028a8a372ad2d325f950fcaceed',
364 ), encoding
='utf-8', env
=test_env
)
365 dt_count
= count_output(stdout
, 'Decrypted DTLS')
366 wfm_count
= count_output(stdout
, 'Works for me!.')
367 assert dt_count
== 7 and wfm_count
== 2
369 def test_dtls_dsb_aes128ccm8(self
, cmd_tshark
, capture_file
, test_env
):
370 '''DTLS 1.2 with master secrets in a pcapng Decryption Secrets Block.'''
371 stdout
= subprocess
.check_output((cmd_tshark
,
372 '-r', capture_file('dtls12-aes128ccm8-dsb.pcapng'),
374 ), encoding
='utf-8', env
=test_env
)
375 dt_count
= count_output(stdout
, 'Decrypted DTLS')
376 wfm_count
= count_output(stdout
, 'Works for me!.')
377 assert dt_count
== 7 and wfm_count
== 2
379 def test_dtls_udt(self
, cmd_tshark
, dirs
, capture_file
, features
, test_env
):
380 '''UDT over DTLS 1.2 with RSA key'''
381 if not features
.have_gnutls
:
382 pytest
.skip('Requires GnuTLS.')
383 key_file
= os
.path
.join(dirs
.key_dir
, 'udt-dtls.key')
384 stdout
= subprocess
.check_output((cmd_tshark
,
385 '-r', capture_file('udt-dtls.pcapng.gz'),
386 '-o', 'dtls.keys_list:0.0.0.0,0,data,{}'.format(key_file
),
387 '-Y', 'dtls && udt.type==ack',
388 ), encoding
='utf-8', env
=test_env
)
389 assert grep_output(stdout
, 'UDT')
392 class TestDecryptTLS
:
393 def test_tls_rsa(self
, cmd_tshark
, capture_file
, features
, test_env
):
394 '''TLS using the server's private RSA key.'''
395 if not features
.have_gnutls
:
396 pytest
.skip('Requires GnuTLS.')
397 # https://gitlab.com/wireshark/wireshark/-/wikis/uploads/__moin_import__/attachments/SampleCaptures/snakeoil2_070531.tgz
398 stdout
= subprocess
.check_output((cmd_tshark
,
399 '-r', capture_file('rsasnakeoil2.pcap'),
401 '-e', 'http.request.uri',
403 ), encoding
='utf-8', env
=test_env
)
404 assert grep_output(stdout
, 'favicon.ico')
406 def test_tls_rsa_pq(self
, cmd_tshark
, dirs
, capture_file
, features
, test_env
):
407 '''TLS using the server's private key with p < q
408 (test whether libgcrypt is correctly called)'''
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', 'tls.keys_list:0.0.0.0,443,http,{}'.format(key_file
),
416 '-e', 'http.request.uri',
418 ), encoding
='utf-8', env
=test_env
)
419 assert grep_output(stdout
, '/')
421 def test_tls_rsa_privkeys_uat(self
, cmd_tshark
, dirs
, capture_file
, features
, test_env
):
422 '''Check TLS decryption works using the rsa_keys UAT.'''
423 if not features
.have_gnutls
:
424 pytest
.skip('Requires GnuTLS.')
425 key_file
= os
.path
.join(dirs
.key_dir
, 'rsa-p-lt-q.key')
426 stdout
= subprocess
.check_output((cmd_tshark
,
427 '-r', capture_file('rsa-p-lt-q.pcap'),
428 '-o', 'uat:rsa_keys:"{}",""'.format(key_file
.replace('\\', '\\x5c')),
430 '-e', 'http.request.uri',
432 ), encoding
='utf-8', env
=test_env
)
435 def test_tls_rsa_with_password(self
, cmd_tshark
, capture_file
, features
, test_env
):
436 '''TLS using the server's private key with password'''
437 if not features
.have_gnutls
:
438 pytest
.skip('Requires GnuTLS.')
439 stdout
= subprocess
.check_output((cmd_tshark
,
440 '-r', capture_file('dmgr.pcapng'),
442 '-e', 'http.request.uri',
444 ), encoding
='utf-8', env
=test_env
)
445 assert grep_output(stdout
, 'unsecureLogon.jsp')
447 def test_tls_master_secret(self
, cmd_tshark
, dirs
, capture_file
, test_env
):
448 '''TLS using the master secret and ssl.keylog_file preference aliasing'''
449 key_file
= os
.path
.join(dirs
.key_dir
, 'dhe1_keylog.dat')
450 stdout
= subprocess
.check_output((cmd_tshark
,
451 '-r', capture_file('dhe1.pcapng.gz'),
452 '-o', 'ssl.keylog_file: {}'.format(key_file
),
453 '-o', 'tls.desegment_ssl_application_data: FALSE',
454 '-o', 'http.tls.port: 443',
456 '-e', 'http.request.method',
457 '-e', 'http.request.uri',
458 '-e', 'http.request.version',
460 ), encoding
='utf-8', env
=test_env
)
461 assert grep_output(stdout
, r
'GET\s+/test\s+HTTP/1.0')
463 def test_tls12_renegotiation(self
, cmd_tshark
, dirs
, capture_file
, features
, test_env
):
464 '''TLS 1.2 with renegotiation'''
465 if not features
.have_gnutls
:
466 pytest
.skip('Requires GnuTLS.')
467 key_file
= os
.path
.join(dirs
.key_dir
, 'rsasnakeoil2.key')
468 # Test protocol alias while at it (ssl -> tls)
469 stdout
= subprocess
.check_output((cmd_tshark
,
470 '-r', capture_file('tls-renegotiation.pcap'),
471 '-o', 'tls.keys_list:0.0.0.0,4433,http,{}'.format(key_file
),
472 '-d', 'tcp.port==4433,ssl',
474 '-e', 'http.content_length',
476 ), encoding
='utf-8', env
=test_env
)
477 count_0
= count_output(stdout
, '^0$')
478 count_2151
= count_output(stdout
, '^2151$')
479 assert count_0
== 1 and count_2151
== 1
481 def test_tls12_psk_aes128ccm(self
, cmd_tshark
, capture_file
, test_env
):
482 '''TLS 1.2 with PSK, AES-128-CCM'''
483 stdout
= subprocess
.check_output((cmd_tshark
,
484 '-r', capture_file('tls12-aes128ccm.pcap'),
485 '-o', 'tls.psk:ca19e028a8a372ad2d325f950fcaceed',
487 '-z', 'follow,tls,ascii,0',
488 ), encoding
='utf-8', env
=test_env
)
489 assert grep_output(stdout
, 'http://www.gnu.org/software/gnutls')
491 def test_tls12_psk_aes256gcm(self
, cmd_tshark
, capture_file
, test_env
):
492 '''TLS 1.2 with PSK, AES-256-GCM'''
493 stdout
= subprocess
.check_output((cmd_tshark
,
494 '-r', capture_file('tls12-aes256gcm.pcap'),
495 '-o', 'tls.psk:ca19e028a8a372ad2d325f950fcaceed',
497 '-z', 'follow,tls,ascii,0',
498 ), encoding
='utf-8', env
=test_env
)
499 assert grep_output(stdout
, 'http://www.gnu.org/software/gnutls')
501 def test_tls12_chacha20poly1305(self
, cmd_tshark
, dirs
, features
, capture_file
, test_env
):
502 '''TLS 1.2 with ChaCha20-Poly1305'''
503 key_file
= os
.path
.join(dirs
.key_dir
, 'tls12-chacha20poly1305.keys')
505 'ECDHE-ECDSA-CHACHA20-POLY1305',
506 'ECDHE-RSA-CHACHA20-POLY1305',
507 'DHE-RSA-CHACHA20-POLY1305',
508 'RSA-PSK-CHACHA20-POLY1305',
509 'DHE-PSK-CHACHA20-POLY1305',
510 'ECDHE-PSK-CHACHA20-POLY1305',
511 'PSK-CHACHA20-POLY1305',
514 for cipher
in ciphers
:
515 stdout
= subprocess
.check_output((cmd_tshark
,
516 '-r', capture_file('tls12-chacha20poly1305.pcap'),
517 '-o', 'tls.keylog_file: {}'.format(key_file
),
519 '-z', 'follow,tls,ascii,{}'.format(stream
),
520 ), encoding
='utf-8', env
=test_env
)
522 assert grep_output(stdout
, 'Cipher is {}'.format(cipher
))
524 def test_tls13_chacha20poly1305(self
, cmd_tshark
, dirs
, features
, capture_file
, test_env
):
525 '''TLS 1.3 with ChaCha20-Poly1305'''
526 key_file
= os
.path
.join(dirs
.key_dir
, 'tls13-20-chacha20poly1305.keys')
527 stdout
= subprocess
.check_output((cmd_tshark
,
528 '-r', capture_file('tls13-20-chacha20poly1305.pcap'),
529 '-o', 'tls.keylog_file: {}'.format(key_file
),
531 '-z', 'follow,tls,ascii,0',
532 ), encoding
='utf-8', env
=test_env
)
533 assert grep_output(stdout
, 'TLS13-CHACHA20-POLY1305-SHA256')
535 def test_tls13_rfc8446(self
, cmd_tshark
, dirs
, features
, capture_file
, test_env
):
536 '''TLS 1.3 (normal session, then early data followed by normal data).'''
537 key_file
= os
.path
.join(dirs
.key_dir
, 'tls13-rfc8446.keys')
538 stdout
= subprocess
.check_output((cmd_tshark
,
539 '-r', capture_file('tls13-rfc8446.pcap'),
540 '-otls.keylog_file:{}'.format(key_file
),
543 '-e', 'frame.number',
544 '-e', 'http.request.uri',
545 '-e', 'http.file_data',
547 ), encoding
='utf-8', env
=test_env
)
548 first_response
= binascii
.hexlify(b
'Request for /first, version TLSv1.3, Early data: no\n').decode("ascii")
549 early_response
= binascii
.hexlify(b
'Request for /early, version TLSv1.3, Early data: yes\n').decode("ascii")
550 second_response
= binascii
.hexlify(b
'Request for /second, version TLSv1.3, Early data: yes\n').decode("ascii")
553 # fr'6||{first_response}',
555 # fr'10||{early_response}',
557 # fr'13||{second_response}',
558 # ] == stdout.splitlines()
562 fr
'6|/first|{first_response}',
564 fr
'10|/early|{early_response}',
566 fr
'13|/second|{second_response}',
567 ] == stdout
.splitlines()
569 def test_tls13_rfc8446_noearly(self
, cmd_tshark
, dirs
, features
, capture_file
, test_env
):
570 '''TLS 1.3 (with undecryptable early data).'''
571 key_file
= os
.path
.join(dirs
.key_dir
, 'tls13-rfc8446-noearly.keys')
572 stdout
= subprocess
.check_output((cmd_tshark
,
573 '-r', capture_file('tls13-rfc8446.pcap'),
574 '-otls.keylog_file:{}'.format(key_file
),
577 '-e', 'frame.number',
578 '-e', 'http.request.uri',
579 '-e', 'http.file_data',
581 ), encoding
='utf-8', env
=test_env
)
582 first_response
= binascii
.hexlify(b
'Request for /first, version TLSv1.3, Early data: no\n').decode("ascii")
583 early_response
= binascii
.hexlify(b
'Request for /early, version TLSv1.3, Early data: yes\n').decode("ascii")
584 second_response
= binascii
.hexlify(b
'Request for /second, version TLSv1.3, Early data: yes\n').decode("ascii")
587 # fr'6||{first_response}',
588 # fr'10||{early_response}',
590 # fr'13||{second_response}',
591 # ] == stdout.splitlines()
595 fr
'6|/first|{first_response}',
596 fr
'10||{early_response}',
598 fr
'13|/second|{second_response}',
599 ] == stdout
.splitlines()
601 def test_tls12_dsb(self
, cmd_tshark
, capture_file
, test_env
):
602 '''TLS 1.2 with master secrets in pcapng Decryption Secrets Blocks.'''
603 output
= subprocess
.check_output((cmd_tshark
,
604 '-r', capture_file('tls12-dsb.pcapng'),
607 '-e', 'http.response.code',
609 ), encoding
='utf-8', env
=test_env
)
610 assert 'example.com\t\n\t200\nexample.net\t\n\t200\n' == output
612 def test_tls_over_tls(self
, cmd_tshark
, dirs
, capture_file
, features
, test_env
):
613 '''TLS using the server's private key with p < q
614 (test whether libgcrypt is correctly called)'''
615 if not features
.have_gnutls
:
616 pytest
.skip('Requires GnuTLS.')
617 key_file
= os
.path
.join(dirs
.key_dir
, 'tls-over-tls.key')
618 output
= subprocess
.check_output((cmd_tshark
,
619 '-r', capture_file('tls-over-tls.pcapng.gz'),
620 '-o', 'tls.keys_list:0.0.0.0,443,http,{}'.format(key_file
),
621 '-z', 'expert,tls.handshake.certificates',
623 '-e', 'tls.handshake.certificate_length',
624 '-Y', 'tls.handshake.certificates',
625 ), encoding
='utf-8', env
=test_env
)
626 assert '1152,1115,1352\n1152\n1412,1434,1382\n' == output
629 class TestDecryptZigbee
:
630 def test_zigbee(self
, cmd_tshark
, capture_file
, test_env
):
632 # https://gitlab.com/wireshark/wireshark/-/issues/7022
633 stdout
= subprocess
.check_output((cmd_tshark
,
634 '-r', capture_file('sample_control4_2012-03-24.pcap'),
638 ), encoding
='utf-8', env
=test_env
)
639 assert grep_output(stdout
, '3067636338652063342e646d2e747620')
642 class TestDecryptANSIC122
:
643 def test_ansi_c1222(self
, cmd_tshark
, capture_file
, test_env
):
645 # https://gitlab.com/wireshark/wireshark/-/issues/9196
646 stdout
= subprocess
.check_output((cmd_tshark
,
647 '-r', capture_file('c1222_std_example8.pcap'),
648 '-o', 'c1222.decrypt: TRUE',
649 '-o', 'c1222.baseoid: 2.16.124.113620.1.22.0',
652 ), encoding
='utf-8', env
=test_env
)
653 assert grep_output(stdout
, '00104d414e55464143545552455220534e2092')
656 class TestDecryptDVBCI
:
657 def test_dvb_ci(self
, cmd_tshark
, capture_file
, test_env
):
659 # simplified version of the sample capture in
660 # https://gitlab.com/wireshark/wireshark/-/issues/6700
661 stdout
= subprocess
.check_output((cmd_tshark
,
662 '-r', capture_file('dvb-ci_UV1_0000.pcap'),
663 '-o', 'dvb-ci.sek: 00000000000000000000000000000000',
664 '-o', 'dvb-ci.siv: 00000000000000000000000000000000',
666 '-e', 'dvb-ci.cc.sac.padding',
667 ), encoding
='utf-8', env
=test_env
)
668 assert grep_output(stdout
, '800000000000000000000000')
671 class TestDecryptIPsec
:
672 def test_ipsec_esp(self
, cmd_tshark
, capture_file
, test_env
):
674 # https://gitlab.com/wireshark/wireshark/-/issues/12671
675 stdout
= subprocess
.check_output((cmd_tshark
,
676 '-r', capture_file('esp-bug-12671.pcapng.gz'),
677 '-o', 'esp.enable_encryption_decode: TRUE',
680 ), encoding
='utf-8', env
=test_env
)
681 assert grep_output(stdout
, '08090a0b0c0d0e0f1011121314151617')
684 class TestDecryptIkeIsakmp
:
685 def test_ikev1_certs(self
, cmd_tshark
, capture_file
, test_env
):
686 '''IKEv1 (ISAKMP) with certificates'''
687 # https://gitlab.com/wireshark/wireshark/-/issues/7951
688 stdout
= subprocess
.check_output((cmd_tshark
,
689 '-r', capture_file('ikev1-certs.pcap'),
691 '-e', 'x509sat.printableString',
692 ), encoding
='utf-8', env
=test_env
)
693 assert grep_output(stdout
, 'OpenSwan')
695 def test_ikev1_simultaneous(self
, cmd_tshark
, capture_file
, test_env
):
696 '''IKEv1 (ISAKMP) simultaneous exchanges'''
697 # https://gitlab.com/wireshark/wireshark/-/issues/12610
698 stdout
= subprocess
.check_output((cmd_tshark
,
699 '-r', capture_file('ikev1-bug-12610.pcapng.gz'),
702 ), encoding
='utf-8', env
=test_env
)
703 assert grep_output(stdout
, 'b52521f774967402c9f6cee95fd17e5b')
705 def test_ikev1_unencrypted(self
, cmd_tshark
, capture_file
, test_env
):
706 '''IKEv1 (ISAKMP) unencrypted phase 1'''
707 # https://gitlab.com/wireshark/wireshark/-/issues/12620
708 stdout
= subprocess
.check_output((cmd_tshark
,
709 '-r', capture_file('ikev1-bug-12620.pcapng.gz'),
712 ), encoding
='utf-8', env
=test_env
)
713 assert grep_output(stdout
, '40043b640f4373250d5ac3a1fb63153c')
715 def test_ikev2_3des_sha160(self
, cmd_tshark
, capture_file
, test_env
):
716 '''IKEv2 decryption test (3DES-CBC/SHA1_160)'''
717 stdout
= subprocess
.check_output((cmd_tshark
,
718 '-r', capture_file('ikev2-decrypt-3des-sha1_160.pcap'),
720 '-e', 'isakmp.auth.data',
721 ), encoding
='utf-8', env
=test_env
)
722 assert grep_output(stdout
, '02f7a0d5f1fdc8ea81039818c65bb9bd09af9b8917319b887ff9ba3046c344c7')
724 def test_ikev2_aes128_ccm12(self
, cmd_tshark
, capture_file
, test_env
):
725 '''IKEv2 decryption test (AES-128-CCM-12) - with CBC-MAC verification'''
726 stdout
= subprocess
.check_output((cmd_tshark
,
727 '-r', capture_file('ikev2-decrypt-aes128ccm12.pcap'),
729 '-e', 'isakmp.auth.data',
730 ), encoding
='utf-8', env
=test_env
)
731 assert grep_output(stdout
, 'c2104394299e1ffe7908ea720ad5d13717a0d454e4fa0a2128ea689411f479c4')
733 def test_ikev2_aes128_ccm12_2(self
, cmd_tshark
, capture_file
, test_env
):
734 '''IKEv2 decryption test (AES-128-CCM-12 using CTR mode, without checksum)'''
735 stdout
= subprocess
.check_output((cmd_tshark
,
736 '-r', capture_file('ikev2-decrypt-aes128ccm12-2.pcap'),
738 '-e', 'isakmp.auth.data',
739 ), encoding
='utf-8', env
=test_env
)
740 assert grep_output(stdout
, 'aaa281c87b4a19046c57271d557488ca413b57228cb951f5fa9640992a0285b9')
742 def test_ikev2_aes192ctr_sha512(self
, cmd_tshark
, capture_file
, test_env
):
743 '''IKEv2 decryption test (AES-192-CTR/SHA2-512)'''
744 stdout
= subprocess
.check_output((cmd_tshark
,
745 '-r', capture_file('ikev2-decrypt-aes192ctr.pcap'),
747 '-e', 'isakmp.auth.data',
748 ), encoding
='utf-8', env
=test_env
)
749 assert grep_output(stdout
, '3ec23dcf9348485638407c754547aeb3085290082c49f583fdbae59263a20b4a')
751 def test_ikev2_aes256cbc_sha256(self
, cmd_tshark
, capture_file
, test_env
):
752 '''IKEv2 decryption test (AES-256-CBC/SHA2-256)'''
753 stdout
= subprocess
.check_output((cmd_tshark
,
754 '-r', capture_file('ikev2-decrypt-aes256cbc.pcapng'),
756 '-e', 'isakmp.auth.data',
757 ), encoding
='utf-8', env
=test_env
)
758 assert grep_output(stdout
, 'e1a8d550064201a7ec024a85758d0673c61c5c510ac13bcd225d6327f50da3d3')
760 def test_ikev2_aes256ccm16(self
, cmd_tshark
, capture_file
, test_env
):
761 '''IKEv2 decryption test (AES-256-CCM-16)'''
762 stdout
= subprocess
.check_output((cmd_tshark
,
763 '-r', capture_file('ikev2-decrypt-aes256ccm16.pcapng'),
765 '-e', 'isakmp.auth.data',
766 ), encoding
='utf-8', env
=test_env
)
767 assert grep_output(stdout
, 'fa2e74bdc01e30fb0b3ddc9723c9449095969da51f69e560209d2c2b7940210a')
769 def test_ikev2_aes256gcm16(self
, cmd_tshark
, capture_file
, test_env
):
770 '''IKEv2 decryption test (AES-256-GCM-16)'''
771 stdout
= subprocess
.check_output((cmd_tshark
,
772 '-r', capture_file('ikev2-decrypt-aes256gcm16.pcap'),
774 '-e', 'isakmp.auth.data',
775 ), encoding
='utf-8', env
=test_env
)
776 assert grep_output(stdout
, '9ab71f14ab553cad873a1aa70b99df155dee77cdcf3694b3b7527acbb9712ded')
778 def test_ikev2_aes256gcm8(self
, cmd_tshark
, capture_file
, test_env
):
779 '''IKEv2 decryption test (AES-256-GCM-8)'''
780 stdout
= subprocess
.check_output((cmd_tshark
,
781 '-r', capture_file('ikev2-decrypt-aes256gcm8.pcap'),
783 '-e', 'isakmp.auth.data',
784 ), encoding
='utf-8', env
=test_env
)
785 assert grep_output(stdout
, '4a66d822d0afbc22ad9a92a2cf4287c920ad8ac3b069a4a7e75fe0a5d499f914')
788 class TestDecryptHttp2
:
789 def test_http2(self
, cmd_tshark
, capture_file
, features
, test_env
):
791 if not features
.have_nghttp2
:
792 pytest
.skip('Requires nghttp2.')
793 stdout
= subprocess
.check_output((cmd_tshark
,
794 '-r', capture_file('packet-h2-14_headers.pcapng'),
796 '-e', 'http2.header.value',
797 '-d', 'tcp.port==3000,http2',
798 ), encoding
='utf-8', env
=test_env
)
799 assert grep_output(stdout
, 'nghttp2')
802 class TestDecryptKerberos
:
803 def test_kerberos(self
, cmd_tshark
, dirs
, features
, capture_file
, test_env
):
805 # Files are from krb-816.zip on the SampleCaptures page.
806 if not features
.have_kerberos
:
807 pytest
.skip('Requires kerberos.')
808 keytab_file
= os
.path
.join(dirs
.key_dir
, 'krb-816.keytab')
809 stdout
= subprocess
.check_output((cmd_tshark
,
810 '-r', capture_file('krb-816.pcap.gz'),
811 '-o', 'kerberos.decrypt: TRUE',
812 '-o', 'kerberos.file: {}'.format(keytab_file
),
814 '-e', 'kerberos.keyvalue',
815 ), encoding
='utf-8', env
=test_env
)
816 # keyvalue: ccda7d48219f73c3b28311c4ba7242b3
817 assert grep_output(stdout
, 'ccda7d48219f73c3b28311c4ba7242b3')
821 def run_wireguard_test(cmd_tshark
, capture_file
, result_file
, features
, test_env
):
822 def runOne(self
, args
, keylog
=None, pcap_file
='wireguard-ping-tcp.pcap'):
824 keylog_file
= result_file('wireguard.keys')
825 args
+= ['-owg.keylog_file:%s' % keylog_file
]
826 with
open(keylog_file
, 'w') as f
:
827 f
.write("\n".join(keylog
))
828 stdout
= subprocess
.check_output([cmd_tshark
, '-r', capture_file(pcap_file
)] + args
, encoding
='utf-8', env
=test_env
)
829 return stdout
.splitlines()
833 class TestDecryptWireguard
:
834 # The "foo_alt" keys are similar as "foo" except that some bits are changed.
835 # The crypto library should be able to handle this and internally the
836 # dissector uses MSB to recognize whether a private key is set.
837 key_Spriv_i
= 'AKeZaHwBxjiKLFnkY2unvEdOTtg4AL+M9dQXfopFVFk='
838 key_Spriv_i_alt
= 'B6eZaHwBxjiKLFnkY2unvEdOTtg4AL+M9dQXfopFVJk='
839 key_Spub_i
= 'Igge9KzRytKNwrgkzDE/8hrLu6Ly0OqVdvOPWhA5KR4='
840 key_Spriv_r
= 'cFIxTUyBs1Qil414hBwEgvasEax8CKJ5IS5ZougplWs='
841 key_Spub_r
= 'YDCttCs9e1J52/g9vEnwJJa+2x6RqaayAYMpSVQfGEY='
842 key_Epriv_i0
= 'sLGLJSOQfyz7JNJ5ZDzFf3Uz1rkiCMMjbWerNYcPFFU='
843 key_Epriv_i0_alt
= 't7GLJSOQfyz7JNJ5ZDzFf3Uz1rkiCMMjbWerNYcPFJU='
844 key_Epriv_r0
= 'QC4/FZKhFf0b/eXEcCecmZNt6V6PXmRa4EWG1PIYTU4='
845 key_Epriv_i1
= 'ULv83D+y3vA0t2mgmTmWz++lpVsrP7i4wNaUEK2oX0E='
846 key_Epriv_r1
= 'sBv1dhsm63cbvWMv/XML+bvynBp9PTdY9Vvptu3HQlg='
847 # Ephemeral keys and PSK for wireguard-psk.pcap
848 key_Epriv_i2
= 'iCv2VTi/BC/q0egU931KXrrQ4TSwXaezMgrhh7uCbXs='
849 key_Epriv_r2
= '8G1N3LnEqYC7+NW/b6mqceVUIGBMAZSm+IpwG1U0j0w='
850 key_psk2
= '//////////////////////////////////////////8='
851 key_Epriv_i3
= '+MHo9sfkjPsjCx7lbVhRLDvMxYvTirOQFDSdzAW6kUQ='
852 key_Epriv_r3
= '0G6t5j1B/We65MXVEBIGuRGYadwB2ITdvJovtAuATmc='
853 key_psk3
= 'iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIg='
854 # dummy key that should not work with anything.
855 key_dummy
= 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx='
857 def test_mac1_public(self
, run_wireguard_test
):
858 """Check that MAC1 identification using public keys work."""
859 lines
= run_wireguard_test(self
, [
860 '-ouat:wg_keys:"Public","%s"' % self
.key_Spub_i
,
861 '-ouat:wg_keys:"Public","%s"' % self
.key_Spub_r
,
862 '-Y', 'wg.receiver_pubkey',
864 '-e', 'frame.number',
865 '-e', 'wg.receiver_pubkey',
866 '-e', 'wg.receiver_pubkey.known_privkey',
868 assert len(lines
) == 4
869 assert '1\t%s\tFalse' % self
.key_Spub_r
in lines
870 assert '2\t%s\tFalse' % self
.key_Spub_i
in lines
871 assert '13\t%s\tFalse' % self
.key_Spub_r
in lines
872 assert '14\t%s\tFalse' % self
.key_Spub_i
in lines
874 def test_mac1_private(self
, run_wireguard_test
):
875 """Check that MAC1 identification using private keys work."""
876 lines
= run_wireguard_test(self
, [
877 '-ouat:wg_keys:"Private","%s"' % self
.key_Spriv_i
,
878 '-ouat:wg_keys:"Private","%s"' % self
.key_Spriv_r
,
879 '-Y', 'wg.receiver_pubkey',
881 '-e', 'frame.number',
882 '-e', 'wg.receiver_pubkey',
883 '-e', 'wg.receiver_pubkey.known_privkey',
885 assert len(lines
) == 4
886 assert '1\t%s\tTrue' % self
.key_Spub_r
in lines
887 assert '2\t%s\tTrue' % self
.key_Spub_i
in lines
888 assert '13\t%s\tTrue' % self
.key_Spub_r
in lines
889 assert '14\t%s\tTrue' % self
.key_Spub_i
in lines
891 def test_decrypt_initiation_sprivr(self
, run_wireguard_test
):
892 """Check for partial decryption using Spriv_r."""
893 lines
= run_wireguard_test(self
, [
894 '-ouat:wg_keys:"Private","%s"' % self
.key_Spriv_r
,
897 '-e', 'frame.number',
899 '-e', 'wg.static.known_pubkey',
900 '-e', 'wg.static.known_privkey',
901 '-e', 'wg.timestamp.nanoseconds',
903 # static pubkey is unknown because Spub_i is not added to wg_keys.
904 assert '1\t%s\tFalse\tFalse\t%s' % (self
.key_Spub_i
, '356537872') in lines
905 assert '13\t%s\tFalse\tFalse\t%s' % (self
.key_Spub_i
, '490514356') in lines
907 def test_decrypt_initiation_ephemeral_only(self
, run_wireguard_test
):
908 """Check for partial decryption using Epriv_i."""
909 lines
= run_wireguard_test(self
, [
910 '-ouat:wg_keys:"Public","%s"' % self
.key_Spub_r
,
913 '-e', 'frame.number',
914 '-e', 'wg.ephemeral.known_privkey',
916 '-e', 'wg.timestamp.nanoseconds',
918 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_i0
,
919 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_i1
,
921 # The current implementation tries to write as much decrypted data as
922 # possible, even if the full handshake cannot be derived.
923 assert '1\tTrue\t%s\t%s' % (self
.key_Spub_i
, '') in lines
924 assert '13\tTrue\t%s\t%s' % (self
.key_Spub_i
, '') in lines
926 def test_decrypt_full_initiator(self
, run_wireguard_test
):
928 Check for full handshake decryption using Spriv_r + Epriv_i.
929 The public key Spub_r is provided via the key log as well.
931 lines
= run_wireguard_test(self
, [
933 '-e', 'frame.number',
934 '-e', 'wg.ephemeral.known_privkey',
936 '-e', 'wg.timestamp.nanoseconds',
937 '-e', 'wg.handshake_ok',
941 ' REMOTE_STATIC_PUBLIC_KEY = %s' % self
.key_Spub_r
,
942 ' LOCAL_STATIC_PRIVATE_KEY = %s' % self
.key_Spriv_i_alt
,
943 ' LOCAL_EPHEMERAL_PRIVATE_KEY = %s' % self
.key_Epriv_i0_alt
,
944 ' LOCAL_EPHEMERAL_PRIVATE_KEY = %s' % self
.key_Epriv_i1
,
946 assert '1\tTrue\t%s\t%s\t\t\t' % (self
.key_Spub_i
, '356537872') in lines
947 assert '2\tFalse\t\t\tTrue\t\t' in lines
948 assert '3\t\t\t\t\t8\t' in lines
949 assert '4\t\t\t\t\t0\t' in lines
950 assert '13\tTrue\t%s\t%s\t\t\t' % (self
.key_Spub_i
, '490514356') in lines
951 assert '14\tFalse\t\t\tTrue\t\t' in lines
952 assert '17\t\t\t\t\t\t443' in lines
953 assert '18\t\t\t\t\t\t49472' in lines
955 def test_decrypt_wg_full_initiator_dsb(self
, run_wireguard_test
):
957 Similar to test_decrypt_full_initiator, but using decryption keys
958 embedded in the pcapng file. The embedded secrets do not contain leading
959 spaces nor spaces around the '=' character.
961 lines
= run_wireguard_test(self
, [
963 '-e', 'frame.number',
964 '-e', 'wg.ephemeral.known_privkey',
966 '-e', 'wg.timestamp.nanoseconds',
967 '-e', 'wg.handshake_ok',
970 ], pcap_file
='wireguard-ping-tcp-dsb.pcapng')
971 assert '1\tTrue\t%s\t%s\t\t\t' % (self
.key_Spub_i
, '356537872') in lines
972 assert '2\tFalse\t\t\tTrue\t\t' in lines
973 assert '3\t\t\t\t\t8\t' in lines
974 assert '4\t\t\t\t\t0\t' in lines
975 assert '13\tTrue\t%s\t%s\t\t\t' % (self
.key_Spub_i
, '490514356') in lines
976 assert '14\tFalse\t\t\tTrue\t\t' in lines
977 assert '17\t\t\t\t\t\t443' in lines
978 assert '18\t\t\t\t\t\t49472' in lines
980 def test_decrypt_full_responder(self
, run_wireguard_test
):
981 """Check for full handshake decryption using responder secrets."""
982 lines
= run_wireguard_test(self
, [
984 '-e', 'frame.number',
985 '-e', 'wg.ephemeral.known_privkey',
987 '-e', 'wg.timestamp.nanoseconds',
988 '-e', 'wg.handshake_ok',
992 'REMOTE_STATIC_PUBLIC_KEY=%s' % self
.key_Spub_i
,
993 'LOCAL_STATIC_PRIVATE_KEY=%s' % self
.key_Spriv_r
,
994 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_r0
,
995 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_r1
,
997 assert '1\tFalse\t%s\t%s\t\t\t' % (self
.key_Spub_i
, '356537872') in lines
998 assert '2\tTrue\t\t\tTrue\t\t' in lines
999 assert '3\t\t\t\t\t8\t' in lines
1000 assert '4\t\t\t\t\t0\t' in lines
1001 assert '13\tFalse\t%s\t%s\t\t\t' % (self
.key_Spub_i
, '490514356') in lines
1002 assert '14\tTrue\t\t\tTrue\t\t' in lines
1003 assert '17\t\t\t\t\t\t443' in lines
1004 assert '18\t\t\t\t\t\t49472' in lines
1006 def test_decrypt_psk_initiator(self
, run_wireguard_test
):
1007 """Check whether PSKs enable decryption for initiation keys."""
1008 lines
= run_wireguard_test(self
, [
1010 '-e', 'frame.number',
1011 '-e', 'wg.handshake_ok',
1013 'REMOTE_STATIC_PUBLIC_KEY = %s' % self
.key_Spub_r
,
1014 'LOCAL_STATIC_PRIVATE_KEY = %s' % self
.key_Spriv_i
,
1015 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_i2
,
1016 'PRESHARED_KEY=%s' % self
.key_psk2
,
1017 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_r3
,
1018 'PRESHARED_KEY=%s' % self
.key_psk3
,
1019 ], pcap_file
='wireguard-psk.pcap')
1020 assert '2\tTrue' in lines
1021 assert '4\tTrue' in lines
1023 def test_decrypt_psk_responder(self
, run_wireguard_test
):
1024 """Check whether PSKs enable decryption for responder keys."""
1025 lines
= run_wireguard_test(self
, [
1027 '-e', 'frame.number',
1028 '-e', 'wg.handshake_ok',
1030 'REMOTE_STATIC_PUBLIC_KEY=%s' % self
.key_Spub_i
,
1031 'LOCAL_STATIC_PRIVATE_KEY=%s' % self
.key_Spriv_r
,
1032 # Epriv_r2 needs psk2. This tests handling of duplicate ephemeral
1033 # keys with multiple PSKs. It should not have adverse effects.
1034 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_r2
,
1035 'PRESHARED_KEY=%s' % self
.key_dummy
,
1036 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_r2
,
1037 'PRESHARED_KEY=%s' % self
.key_psk2
,
1038 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_i3
,
1039 'PRESHARED_KEY=%s' % self
.key_psk3
,
1040 # Epriv_i3 needs psk3, this tests that additional keys again have no
1042 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_i3
,
1043 'PRESHARED_KEY=%s' % self
.key_dummy
,
1044 ], pcap_file
='wireguard-psk.pcap')
1045 assert '2\tTrue' in lines
1046 assert '4\tTrue' in lines
1048 def test_decrypt_psk_wrong_orderl(self
, run_wireguard_test
):
1049 """Check that the wrong order of lines indeed fail decryption."""
1050 lines
= run_wireguard_test(self
, [
1052 '-e', 'frame.number',
1053 '-e', 'wg.handshake_ok',
1055 'REMOTE_STATIC_PUBLIC_KEY=%s' % self
.key_Spub_i
,
1056 'LOCAL_STATIC_PRIVATE_KEY=%s' % self
.key_Spriv_r
,
1057 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_r2
,
1058 'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self
.key_Epriv_i3
,
1059 'PRESHARED_KEY=%s' % self
.key_psk2
, # note: swapped with previous line
1060 'PRESHARED_KEY=%s' % self
.key_psk3
,
1061 ], pcap_file
='wireguard-psk.pcap')
1062 assert '2\tFalse' in lines
1063 assert '4\tFalse' in lines
1066 class TestDecryptKnxip
:
1067 # Capture files for these tests contain single telegrams.
1068 # For realistic (live captured) KNX/IP telegram sequences, see:
1069 # https://gitlab.com/wireshark/wireshark/-/issues/14825
1071 def test_knxip_data_security_decryption_ok(self
, cmd_tshark
, capture_file
, test_env
):
1072 '''KNX/IP: Data Security decryption OK'''
1073 # capture_file('knxip_DataSec.pcap') contains KNX/IP ConfigReq DataSec PropExtValueWriteCon telegram
1074 stdout
= subprocess
.check_output((cmd_tshark
,
1075 '-r', capture_file('knxip_DataSec.pcap'),
1076 '-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
1077 ), encoding
='utf-8', env
=test_env
)
1078 assert grep_output(stdout
, ' DataSec ')
1079 assert grep_output(stdout
, ' PropExtValueWriteCon ')
1081 def test_knxip_data_security_decryption_fails(self
, cmd_tshark
, capture_file
, test_env
):
1082 '''KNX/IP: Data Security decryption fails'''
1083 # capture_file('knxip_DataSec.pcap') contains KNX/IP ConfigReq DataSec PropExtValueWriteCon telegram
1084 stdout
= subprocess
.check_output((cmd_tshark
,
1085 '-r', capture_file('knxip_DataSec.pcap'),
1086 '-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
1087 ), encoding
='utf-8', env
=test_env
)
1088 assert grep_output(stdout
, ' DataSec ')
1089 assert not grep_output(stdout
, ' PropExtValueWriteCon ')
1091 def test_knxip_secure_wrapper_decryption_ok(self
, cmd_tshark
, capture_file
, test_env
):
1092 '''KNX/IP: SecureWrapper decryption OK'''
1093 # capture_file('knxip_SecureWrapper.pcap') contains KNX/IP SecureWrapper RoutingInd telegram
1094 stdout
= subprocess
.check_output((cmd_tshark
,
1095 '-r', capture_file('knxip_SecureWrapper.pcap'),
1096 '-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
1097 ), encoding
='utf-8', env
=test_env
)
1098 assert grep_output(stdout
, ' SecureWrapper ')
1099 assert grep_output(stdout
, ' RoutingInd ')
1101 def test_knxip_secure_wrapper_decryption_fails(self
, cmd_tshark
, capture_file
, test_env
):
1102 '''KNX/IP: SecureWrapper decryption fails'''
1103 # capture_file('knxip_SecureWrapper.pcap') contains KNX/IP SecureWrapper RoutingInd telegram
1104 stdout
= subprocess
.check_output((cmd_tshark
,
1105 '-r', capture_file('knxip_SecureWrapper.pcap'),
1106 '-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
1107 ), encoding
='utf-8', env
=test_env
)
1108 assert grep_output(stdout
, ' SecureWrapper ')
1109 assert not grep_output(stdout
, ' RoutingInd ')
1111 def test_knxip_timer_notify_authentication_ok(self
, cmd_tshark
, capture_file
, test_env
):
1112 '''KNX/IP: TimerNotify authentication OK'''
1113 # capture_file('knxip_TimerNotify.pcap') contains KNX/IP TimerNotify telegram
1114 stdout
= subprocess
.check_output((cmd_tshark
,
1115 '-r', capture_file('knxip_TimerNotify.pcap'),
1116 '-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
1117 ), encoding
='utf-8', env
=test_env
)
1118 assert grep_output(stdout
, ' TimerNotify ')
1119 assert grep_output(stdout
, ' OK$')
1121 def test_knxip_timer_notify_authentication_fails(self
, cmd_tshark
, capture_file
, test_env
):
1122 '''KNX/IP: TimerNotify authentication fails'''
1123 # capture_file('knxip_TimerNotify.pcap') contains KNX/IP TimerNotify telegram
1124 stdout
= subprocess
.check_output((cmd_tshark
,
1125 '-r', capture_file('knxip_TimerNotify.pcap'),
1126 '-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
1127 ), encoding
='utf-8', env
=test_env
)
1128 assert grep_output(stdout
, ' TimerNotify ')
1129 assert not grep_output(stdout
, ' OK$')
1131 def test_knxip_keyring_xml_import(self
, cmd_tshark
, dirs
, capture_file
, test_env
):
1132 '''KNX/IP: keyring.xml import'''
1133 # key_file "keyring.xml" contains KNX decryption keys
1134 key_file
= os
.path
.join(dirs
.key_dir
, 'knx_keyring.xml')
1135 # capture_file('empty.pcap') is empty
1136 # Write extracted key info to stdout
1137 stdout
= subprocess
.check_output((cmd_tshark
,
1138 '-o', 'kip.key_file:' + key_file
,
1139 '-o', 'kip.key_info_file:-',
1140 '-r', capture_file('empty.pcap'),
1141 ), encoding
='utf-8', env
=test_env
)
1142 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$')
1143 assert grep_output(stdout
, '^GA 1/7/131 sender 1[.]1[.]1$')
1144 assert grep_output(stdout
, '^GA 1/7/131 sender 1[.]1[.]3$')
1145 assert grep_output(stdout
, '^GA 1/7/131 sender 1[.]1[.]4$')
1146 assert grep_output(stdout
, '^GA 1/7/132 sender 1[.]1[.]2$')
1147 assert grep_output(stdout
, '^GA 1/7/132 sender 1[.]1[.]4$')
1148 assert grep_output(stdout
, '^GA 6/7/191 sender 1[.]1[.]1$')
1149 assert grep_output(stdout
, '^GA 0/1/0 sender 1[.]1[.]1$')
1150 assert grep_output(stdout
, '^GA 0/1/0 sender 1[.]1[.]3$')
1151 assert grep_output(stdout
, '^GA 0/1/0 sender 1[.]1[.]4$')
1152 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$')
1153 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$')
1154 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$')
1155 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$')
1156 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$')
1157 assert grep_output(stdout
, '^IA 1[.]1[.]1 SeqNr 45678$')
1158 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$')
1159 assert grep_output(stdout
, '^IA 1[.]1[.]2 SeqNr 34567$')
1160 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$')
1161 assert grep_output(stdout
, '^IA 1[.]1[.]3 SeqNr 23456$')
1162 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$')
1163 assert grep_output(stdout
, '^IA 1[.]1[.]4 SeqNr 12345$')
1164 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$')
1165 assert grep_output(stdout
, '^IA 2[.]1[.]0 SeqNr 1234$')
1168 @pytest.fixture(scope
='session')
1169 def softhsm_paths(features
):
1170 if sys
.platform
== 'win32':
1171 search_path
= os
.getenv('PATH') + r
';C:\SoftHSM2\bin'
1174 softhsm_tool
= shutil
.which('softhsm2-util', path
=search_path
)
1175 if not softhsm_tool
:
1176 # Note: do not fallback to SoftHSMv1. While available on Ubuntu 14.04
1177 # (and 16.04), it is built with botan < 1.11.10 which causes a crash due
1178 # to a conflict with the GMP library that is also used by GnuTLS/nettle.
1179 # See https://github.com/randombit/botan/issues/1090
1180 pytest
.skip('SoftHSM is not found')
1181 # Find provider library path.
1182 bindir
= os
.path
.dirname(softhsm_tool
)
1183 libdir
= os
.path
.join(os
.path
.dirname(bindir
), 'lib')
1184 if sys
.platform
== 'win32':
1185 libdirs
= [libdir
, bindir
]
1186 if features
.have_x64
:
1187 name
= 'softhsm2-x64.dll'
1189 name
= 'softhsm2.dll'
1191 # Look in a variety of paths, Debian/Ubuntu, Fedora, RHEL/CentOS
1192 madir
= sysconfig
.get_config_var('multiarchsubdir')
1193 libdir_archs
= (libdir
, libdir
+ '64')
1194 libdir_subs
= ('softhsm', 'pkcs11', '')
1195 libdirs
= [os
.path
.join(libdir
+ madir
, 'softhsm')] if madir
else []
1196 libdirs
+= [os
.path
.join(arch
, sub
) for sub
in libdir_subs
for arch
in libdir_archs
]
1197 name
= 'libsofthsm2.so'
1198 for libdir
in libdirs
:
1199 provider
= os
.path
.join(libdir
, name
)
1200 if os
.path
.exists(provider
):
1203 # Even if p11-kit can automatically locate it, do not rely on it.
1204 pytest
.skip('SoftHSM provider library not detected')
1205 # Now check whether the import tool is usable. SoftHSM < 2.3.0 did not
1206 # set CKA_DECRYPT when using softhsm2-tool --import and therefore cannot be
1207 # used to import keys for decryption. Use GnuTLS p11tool as workaround.
1208 softhsm_version
= subprocess
.check_output([softhsm_tool
, '--version'],
1209 universal_newlines
=True).strip()
1210 use_p11tool
= softhsm_version
in ('2.0.0', '2.1.0', '2.2.0')
1211 if use_p11tool
and not shutil
.which('p11tool'):
1212 pytest
.skip('SoftHSM available, but GnuTLS p11tool is unavailable')
1213 return use_p11tool
, softhsm_tool
, provider
1217 def softhsm(softhsm_paths
, home_path
, base_env
):
1218 '''Creates a temporary SoftHSM token store (and set it in the environment),
1219 returns a function to populate that token store and the path to the PKCS #11
1220 provider library.'''
1221 use_p11tool
, softhsm_tool
, provider
= softhsm_paths
1222 conf_path
= os
.path
.join(home_path
, 'softhsm-test.conf')
1223 db_path
= os
.path
.join(home_path
, 'softhsm-test-tokens')
1224 os
.makedirs(db_path
)
1225 with
open(conf_path
, 'w') as f
:
1226 f
.write('directories.tokendir = %s\n' % db_path
)
1227 f
.write('objectstore.backend = file\n')
1229 f
.write('log.level = ERROR\n')
1230 base_env
['SOFTHSM2_CONF'] = conf_path
1232 tool_env
= base_env
.copy()
1233 if sys
.platform
== 'win32':
1234 # Ensure that softhsm2-util can find the library.
1235 tool_env
['PATH'] += ';%s' % os
.path
.dirname(provider
)
1237 # Initialize tokens store.
1238 token_name
= 'Wireshark-Test-Tokens'
1240 subprocess
.check_call([softhsm_tool
, '--init-token', '--slot', '0',
1241 '--label', token_name
, '--so-pin', 'Supersecret', '--pin', pin
],
1244 tool_env
['GNUTLS_PIN'] = pin
1246 # Arbitrary IDs and labels.
1247 ids
= iter(range(0xab12, 0xffff))
1248 def import_key(keyfile
):
1249 '''Returns a PKCS #11 URI to identify the imported key.'''
1250 label
= os
.path
.basename(keyfile
)
1251 obj_id
= '%x' % next(ids
)
1253 tool_args
= [softhsm_tool
, '--import', keyfile
, '--label', label
,
1254 '--id', obj_id
, '--pin', pin
, '--token', token_name
]
1256 # Fallback for SoftHSM < 2.3.0
1257 tool_args
= ['p11tool', '--provider', provider
, '--batch',
1258 '--login', '--write', 'pkcs11:token=%s' % token_name
,
1259 '--load-privkey', keyfile
, '--label', label
, '--id', obj_id
]
1260 subprocess
.check_call(tool_args
, env
=tool_env
)
1261 id_str
= '%{}{}%{}{}'.format(*obj_id
)
1262 return 'pkcs11:token=%s;id=%s;type=private' % (token_name
, id_str
)
1264 return types
.SimpleNamespace(import_key
=import_key
, provider
=provider
, pin
=pin
)
1267 class TestDecryptPkcs11
:
1268 def test_tls_pkcs11(self
, cmd_tshark
, dirs
, capture_file
, features
, softhsm
, test_env
):
1269 '''Check that a RSA key in a PKCS #11 token enables decryption.'''
1270 if not features
.have_pkcs11
:
1271 pytest
.skip('Requires GnuTLS with PKCS #11 support.')
1272 key_file
= os
.path
.join(dirs
.key_dir
, 'rsa-p-lt-q.p8')
1273 key_uri
= softhsm
.import_key(key_file
)
1274 stdout
= subprocess
.check_output((cmd_tshark
,
1275 '-r', capture_file('rsa-p-lt-q.pcap'),
1276 '-o', 'uat:pkcs11_libs:"{}"'.format(softhsm
.provider
.replace('\\', '\\x5c')),
1277 '-o', 'uat:rsa_keys:"{}","{}"'.format(key_uri
, softhsm
.pin
),
1279 '-e', 'http.request.uri',
1281 ), encoding
='utf-8', env
=test_env
)
1282 assert '/' in stdout
1284 class TestDecryptSmb2
:
1285 BAD_KEY
= 'ffffffffffffffffffffffffffffffff'
1288 def check_bad_key(cmd_tshark
, cap
, disp_filter
, sesid
, seskey
, s2ckey
, c2skey
, env
=None):
1289 stdout
= subprocess
.check_output((cmd_tshark
,
1291 '-o', 'uat:smb2_seskey_list:{},{},{},{}'.format(sesid
, seskey
, s2ckey
, c2skey
),
1293 ), encoding
='utf-8', env
=env
)
1294 assert 'Encrypted SMB' in stdout
1297 # SMB3.0 CCM bad keys tests
1299 def test_smb300_bad_seskey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1300 '''Check that a bad session key doesn't crash'''
1301 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb300-aes-128-ccm.pcap.gz'),
1302 'frame.number == 7', '1900009c003c0000', self
.BAD_KEY
, '""', '""', env
=test_env
)
1304 def test_smb300_bad_s2ckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1305 '''Check that a bad s2c key doesn't crash'''
1306 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb300-aes-128-ccm.pcap.gz'),
1307 'frame.number == 7', '1900009c003c0000', '""', self
.BAD_KEY
, '""', env
=test_env
)
1309 def test_smb300_bad_c2skey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1310 '''Check that a bad c2s key doesn't crash'''
1311 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb300-aes-128-ccm.pcap.gz'),
1312 'frame.number == 7', '1900009c003c0000', '""', '""', self
.BAD_KEY
, env
=test_env
)
1314 def test_smb300_bad_deckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1315 '''Check that bad decryption keys doesn't crash'''
1316 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb300-aes-128-ccm.pcap.gz'),
1317 'frame.number == 7', '1900009c003c0000', '""', self
.BAD_KEY
, self
.BAD_KEY
, env
=test_env
)
1319 def test_smb300_bad_allkey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1320 '''Check that all bad keys doesn't crash'''
1321 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb300-aes-128-ccm.pcap.gz'),
1322 'frame.number == 7', '1900009c003c0000', self
.BAD_KEY
, self
.BAD_KEY
, self
.BAD_KEY
, env
=test_env
)
1325 # SMB3.1.1 CCM bad key tests
1327 def test_smb311_bad_seskey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1328 '''Check that a bad session key doesn't crash'''
1329 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb311-aes-128-ccm.pcap.gz'),
1330 'frame.number == 7', '2900009c003c0000', self
.BAD_KEY
, '""', '""', env
=test_env
)
1332 def test_smb311_bad_s2ckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1333 '''Check that a bad s2c key doesn't crash'''
1334 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb311-aes-128-ccm.pcap.gz'),
1335 'frame.number == 7', '2900009c003c0000', '""', self
.BAD_KEY
, '""', env
=test_env
)
1337 def test_smb311_bad_c2skey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1338 '''Check that a bad c2s key doesn't crash'''
1339 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb311-aes-128-ccm.pcap.gz'),
1340 'frame.number == 7', '2900009c003c0000', '""', '""', self
.BAD_KEY
, env
=test_env
)
1342 def test_smb311_bad_deckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1343 '''Check that bad decryption keys doesn't crash'''
1344 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb311-aes-128-ccm.pcap.gz'),
1345 'frame.number == 7', '2900009c003c0000', '""', self
.BAD_KEY
, self
.BAD_KEY
, env
=test_env
)
1347 def test_smb311_bad_allkey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1348 '''Check that all bad keys doesn't crash'''
1349 TestDecryptSmb2
.check_bad_key(cmd_tshark
, capture_file('smb311-aes-128-ccm.pcap.gz'),
1350 'frame.number == 7', '2900009c003c0000', self
.BAD_KEY
, self
.BAD_KEY
, self
.BAD_KEY
, env
=test_env
)
1356 def check_tree(cmd_tshark
, cap
, tree
, sesid
, seskey
, s2ckey
, c2skey
, env
=None):
1357 stdout
= subprocess
.check_output((cmd_tshark
,
1359 '-o', 'uat:smb2_seskey_list:{},{},{},{}'.format(sesid
, seskey
, s2ckey
, c2skey
),
1362 '-Y', 'smb2.tree == "{}"'.format(tree
.replace('\\', '\\\\')),
1363 ), encoding
='unicode_escape', env
=env
)
1364 # Remove the escapes (we only have one field so this causes no issue)
1365 assert tree
== stdout
.strip()
1368 def test_smb300_aes128ccm_seskey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1369 '''Check SMB 3.0 AES128CCM decryption with session key.'''
1370 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb300-aes-128-ccm.pcap.gz'),
1371 r
'\\dfsroot1.foo.test\IPC$', '1900009c003c0000',
1372 '9a9ea16a0cdbeb6064772318073f172f', '""', '""', env
=test_env
)
1374 def test_smb300_aes128ccm_deckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1375 '''Check SMB 3.0 AES128CCM decryption with decryption keys.'''
1376 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb300-aes-128-ccm.pcap.gz'),
1377 r
'\\dfsroot1.foo.test\IPC$', '1900009c003c0000',
1378 '""', '8be6cc53d4beba29387e69aef035d497','bff985870e81784d533fdc09497b8eab', env
=test_env
)
1381 # SMB3.1.1 AES-CCM-128
1382 def test_smb311_aes128ccm_seskey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1383 '''Check SMB 3.1.1 AES128CCM decryption with session key.'''
1384 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb311-aes-128-ccm.pcap.gz'),
1385 r
'\\dfsroot1.foo.test\IPC$', '2900009c003c0000',
1386 'f1fa528d3cd182cca67bd4596dabd885', '""', '""', env
=test_env
)
1388 def test_smb311_aes128ccm_deckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1389 '''Check SMB 3.1.1 AES128CCM decryption with decryption keys.'''
1390 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb311-aes-128-ccm.pcap.gz'),
1391 r
'\\dfsroot1.foo.test\IPC$', '2900009c003c0000',
1392 '""', '763d5552dbc9650b700869467a5857e4', '35e69833c6578e438c8701cb40bf483e', env
=test_env
)
1394 # SMB3.1.1 AES-GCM-128
1395 def test_smb311_aes128gcm_seskey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1396 '''Check SMB 3.1.1 AES128GCM decryption with session key.'''
1397 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb311-aes-128-gcm.pcap.gz'),
1398 r
'\\dfsroot1.foo.test\IPC$', '3900000000400000',
1399 'e79161ded03bda1449b2c8e58f753953', '""', '""', env
=test_env
)
1401 def test_smb311_aes128gcm_deckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1402 '''Check SMB 3.1.1 AES128GCM decryption with decryption keys.'''
1403 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb311-aes-128-gcm.pcap.gz'),
1404 r
'\\dfsroot1.foo.test\IPC$', '3900000000400000',
1405 '""', 'b02f5de25e0562075c3dc329fa2aa396', '7201623a31754e6581864581209dd3d2', env
=test_env
)
1407 # SMB3.1.1 AES-CCM-256
1408 def test_smb311_aes256ccm_seskey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1409 '''Check SMB 3.1.1 AES256CCM decryption with session key.'''
1410 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb311-aes-256-ccm.pcap.gz'),
1411 r
'\\172.31.9.163\IPC$', 'd6fdb96d00000000',
1412 '6b559c2e60519e344581d086a6d3d050',
1416 def test_smb311_aes256ccm_deckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1417 '''Check SMB 3.1.1 AES256CCM decryption with decryption keys.'''
1418 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb311-aes-256-ccm.pcap.gz'),
1419 r
'\\172.31.9.163\IPC$', 'd6fdb96d00000000',
1421 '014fccd4a53554bf5b54b27a32512b35fca262b90e088a5efa7d6c952418578b',
1422 '1d34170138a77dac4abbe0149253c8b977a71f399081cda6cbaf62359670c1c5', env
=test_env
)
1424 # SMB3.1.1 AES-GCM-256
1425 def test_smb311_aes256gcm_seskey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1426 '''Check SMB 3.1.1 AES256GCM decryption with session key.'''
1427 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb311-aes-256-gcm.pcap.gz'),
1428 r
'\\172.31.9.163\IPC$', '56dc03ab00000000',
1429 '6a5004adfbdef1abd5879800675324e5',
1433 def test_smb311_aes256gcm_deckey(self
, features
, cmd_tshark
, capture_file
, test_env
):
1434 '''Check SMB 3.1.1 AES256GCM decryption with decryption keys.'''
1435 TestDecryptSmb2
.check_tree(cmd_tshark
, capture_file('smb311-aes-256-gcm.pcap.gz'),
1436 r
'\\172.31.9.163\IPC$', '56dc03ab00000000',
1438 '46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f',
1439 '484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4', env
=test_env
)
1441 def check_partial(home_path
, cmd_tshark
, full_cap
, pkt_skip
, tree
, sesid
, s2ckey
, c2skey
, env
=None):
1442 # generate a trace without NegProt and SessionSetup
1443 partial_cap
= os
.path
.join(home_path
, 'short.pcap')
1444 stdout
= subprocess
.check_output((cmd_tshark
,
1446 '-Y', 'frame.number >= %d'%pkt_skip
,
1448 ), encoding
='utf-8', env
=env
)
1449 TestDecryptSmb2
.check_tree(cmd_tshark
, partial_cap
, tree
, sesid
, '""', s2ckey
, c2skey
)
1451 def test_smb311_aes128gcm_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-128-gcm.pcap.gz'), 7,
1455 r
'\\dfsroot1.foo.test\IPC$', '3900000000400000',
1456 'b02f5de25e0562075c3dc329fa2aa396', '7201623a31754e6581864581209dd3d2', env
=test_env
)
1458 def test_smb311_aes128gcm_partial_keyswap(self
, features
, home_path
, cmd_tshark
, capture_file
, test_env
):
1459 '''Check SMB 3.1.1 AES128GCM decryption in capture missing session setup with keys in wrong order'''
1460 TestDecryptSmb2
.check_partial(home_path
, cmd_tshark
,
1461 capture_file('smb311-aes-128-gcm.pcap.gz'), 7,
1462 r
'\\dfsroot1.foo.test\IPC$', '3900000000400000',
1463 '7201623a31754e6581864581209dd3d2', 'b02f5de25e0562075c3dc329fa2aa396', env
=test_env
)
1465 def test_smb311_aes256gcm_partial(self
, features
, home_path
, cmd_tshark
, capture_file
, test_env
):
1466 '''Check SMB 3.1.1 AES128GCM decryption in capture missing session setup'''
1467 TestDecryptSmb2
.check_partial(home_path
, cmd_tshark
,
1468 capture_file('smb311-aes-256-gcm.pcap.gz'), 7,
1469 r
'\\172.31.9.163\IPC$', '56dc03ab00000000',
1470 '46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f',
1471 '484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4', env
=test_env
)
1473 def test_smb311_aes256gcm_partial_keyswap(self
, features
, home_path
, cmd_tshark
, capture_file
, test_env
):
1474 '''Check SMB 3.1.1 AES256GCM decryption in capture missing session setup with keys in wrong order'''
1475 TestDecryptSmb2
.check_partial(home_path
, cmd_tshark
,
1476 capture_file('smb311-aes-256-gcm.pcap.gz'), 7,
1477 r
'\\172.31.9.163\IPC$', '56dc03ab00000000',
1478 '484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4',
1479 '46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f', env
=test_env
)