2018-04-03 00:12:23 +00:00
|
|
|
#
|
|
|
|
# Wireshark tests
|
|
|
|
# By Gerald Combs <gerald@wireshark.org>
|
|
|
|
#
|
|
|
|
# Ported from a set of Bash scripts which were copyright 2005 Ulf Lamping
|
|
|
|
#
|
|
|
|
# SPDX-License-Identifier: GPL-2.0-or-later
|
|
|
|
#
|
|
|
|
'''Decryption tests'''
|
|
|
|
|
|
|
|
import os.path
|
2018-12-12 13:34:00 +00:00
|
|
|
import shutil
|
|
|
|
import subprocess
|
2023-06-04 22:17:07 +00:00
|
|
|
from subprocesstest import grep_output, count_output
|
2018-12-12 13:34:00 +00:00
|
|
|
import sys
|
|
|
|
import sysconfig
|
|
|
|
import types
|
2023-06-04 22:17:07 +00:00
|
|
|
import pytest
|
2023-09-19 17:52:21 +00:00
|
|
|
import binascii
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecrypt80211:
|
|
|
|
def test_80211_wep(self, cmd_tshark, capture_file, test_env):
|
2020-10-20 19:34:22 +00:00
|
|
|
'''IEEE 802.11 WEP'''
|
|
|
|
# Included in git sources test/captures/wep.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-10-20 19:34:22 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wep.pcapng.gz'),
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.1')
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request')
|
2020-10-20 19:34:22 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_psk(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IEEE 802.11 WPA PSK'''
|
2021-12-21 01:49:34 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/wikis/uploads/__moin_import__/attachments/SampleCaptures/wpa-Induction.pcap
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http.request.uri',
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('wpa-Induction.pcap.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'favicon.ico')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_eap(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IEEE 802.11 WPA EAP (EAPOL Rekey)'''
|
|
|
|
# Included in git sources test/captures/wpa-eap-tls.pcap.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('wpa-eap-tls.pcap.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Y', 'wlan.analysis.tk==7d9987daf5876249b6c773bf454a0da7',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Group Message')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_eapol_incomplete_rekeys(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''WPA decode with message1+2 only and secure bit set on message 2'''
|
|
|
|
# Included in git sources test/captures/wpa-test-decode.pcap.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('wpa-test-decode.pcap.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Y', 'icmp.resp_to == 4263',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Echo')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_psk_mfp(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''WPA decode management frames with MFP enabled (802.11w)'''
|
|
|
|
# Included in git sources test/captures/wpa-test-decode-mgmt.pcap.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('wpa-test-decode-mgmt.pcap.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Y', 'wlan.fixed.reason_code == 2 || wlan.fixed.category_code == 3',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert count_output(stdout, '802.11.*SN=.*FN=.*Flags=') == 3
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa2_psk_mfp(self, cmd_tshark, capture_file, features, test_env):
|
2020-03-22 09:06:56 +00:00
|
|
|
'''IEEE 802.11 decode WPA2 PSK with MFP enabled (802.11w)'''
|
|
|
|
# Included in git sources test/captures/wpa2-psk-mfp.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-03-22 09:06:56 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa2-psk-mfp.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 4e30e8c019bea43ea5262b10853b818d || wlan.analysis.gtk == 70cdbf2e5bc0ca22e53930818a5d80e4',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK is correct
|
|
|
|
assert grep_output(stdout, 'DHCP Request') # Verifies TK is correct
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK is correct
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_tdls(self, cmd_tshark, capture_file, features, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''WPA decode traffic in a TDLS (Tunneled Direct-Link Setup) session (802.11z)'''
|
|
|
|
# Included in git sources test/captures/wpa-test-decode-tdls.pcap.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-05-17 14:27:59 +00:00
|
|
|
#'-ouat:80211_keys:"wpa-pwd","12345678"',
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('wpa-test-decode-tdls.pcap.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Y', 'icmp',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert count_output(stdout, 'ICMP.*Echo .ping') == 2
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa3_personal(self, cmd_tshark, capture_file, test_env):
|
2019-03-18 13:56:39 +00:00
|
|
|
'''IEEE 802.11 decode WPA3 personal / SAE'''
|
|
|
|
# Included in git sources test/captures/wpa3-sae.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2019-03-18 13:56:39 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa3-sae.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 20a2e28f4329208044f4d7edca9e20a6 || wlan.analysis.gtk == 1fc82f8813160031d6bf87bca22b6354',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.18')
|
|
|
|
assert grep_output(stdout, 'DHCP ACK')
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_owe(self, cmd_tshark, capture_file, test_env):
|
2019-03-22 16:10:35 +00:00
|
|
|
'''IEEE 802.11 decode OWE'''
|
|
|
|
# Included in git sources test/captures/owe.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2019-03-22 16:10:35 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('owe.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 10f3deccc00d5c8f629fba7a0fff34aa || wlan.analysis.gtk == 016b04ae9e6050bcc1f940dda9ffff2b',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.2')
|
|
|
|
assert grep_output(stdout, 'DHCP ACK')
|
2019-03-22 16:10:35 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa3_suite_b_192(self, cmd_tshark, capture_file, test_env):
|
2019-11-12 12:13:21 +00:00
|
|
|
'''IEEE 802.11 decode WPA3 Suite B 192-bit'''
|
|
|
|
# Included in git sources test/captures/wpa3-suiteb-192.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2019-11-12 12:13:21 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa3-suiteb-192.pcapng.gz'),
|
|
|
|
'-Tfields',
|
2022-04-16 05:50:57 +00:00
|
|
|
'-e' 'wlan.rsn.ie.gtk_kde.gtk',
|
2019-11-12 12:13:21 +00:00
|
|
|
'-e' 'wlan.analysis.kck',
|
|
|
|
'-e' 'wlan.analysis.kek',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
2019-11-12 12:13:21 +00:00
|
|
|
# Verify that correct PTKs (KCK, KEK) are derived and GTK correctly dissected
|
2023-06-04 22:17:07 +00:00
|
|
|
assert count_output(stdout, '^29f92526ccda5a5dfa0ffa44c26f576ee2d45bae7c5f63369103b1edcab206ea\t' \
|
2019-11-12 12:13:21 +00:00
|
|
|
'f49ac1a15121f1a597a60a469870450a588ef1f73a1017b1\t' \
|
2023-06-04 22:17:07 +00:00
|
|
|
'0289b022b4f54262048d3493834ae591e811870c4520ee1395dd215a6092fbfb$') == 1
|
|
|
|
assert count_output(stdout, '^29f92526ccda5a5dfa0ffa44c26f576ee2d45bae7c5f63369103b1edcab206ea\t' \
|
2019-11-12 12:13:21 +00:00
|
|
|
'1027c8d5b155ff574158bc50083e28f02e9636a2ac694901\t' \
|
2023-06-04 22:17:07 +00:00
|
|
|
'd4814a364419fa881a8593083f51497fe9e30556a91cc5d0b11cd2b3226038e1$') == 1
|
|
|
|
assert count_output(stdout, '^29f92526ccda5a5dfa0ffa44c26f576ee2d45bae7c5f63369103b1edcab206ea\t' \
|
2019-11-12 12:13:21 +00:00
|
|
|
'35db5e208c9caff2a4e00a54c5346085abaa6f422ef6df81\t' \
|
2023-06-04 22:17:07 +00:00
|
|
|
'a14d0d683c01bc631bf142e82dc4995d87364eeacfab75d74cf470683bd10c51$') == 1
|
2019-11-12 12:13:21 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa1_gtk_rekey(self, cmd_tshark, capture_file, test_env):
|
2019-04-02 13:50:08 +00:00
|
|
|
'''Decode WPA1 with multiple GTK rekeys'''
|
|
|
|
# Included in git sources test/captures/wpa1-gtk-rekey.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2019-04-02 13:50:08 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa1-gtk-rekey.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == "d0e57d224c1bb8806089d8c23154074c" || wlan.analysis.gtk == "6eaf63f4ad7997ced353723de3029f4d" || wlan.analysis.gtk == "fb42811bcb59b7845376246454fbdab7"',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'DHCP Discover')
|
|
|
|
assert count_output(stdout, 'ICMP.*Echo .ping') == 8
|
2019-04-02 13:50:08 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_extended_key_id_rekey(self, cmd_tshark, capture_file, test_env):
|
2019-10-28 17:19:00 +00:00
|
|
|
'''WPA decode for Extended Key ID'''
|
|
|
|
# Included in git sources test/captures/wpa_ptk_extended_key_id.pcap.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2019-10-28 17:19:00 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa_ptk_extended_key_id.pcap.gz'),
|
|
|
|
'-Tfields',
|
|
|
|
'-e' 'wlan.fc.type_subtype',
|
|
|
|
'-e' 'wlan.ra',
|
|
|
|
'-e' 'wlan.analysis.tk',
|
|
|
|
'-e' 'wlan.analysis.gtk',
|
|
|
|
'-e' 'wlan.rsn.ie.ptk.keyid',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
2019-10-28 17:19:00 +00:00
|
|
|
# Verify frames are decoded with the correct key
|
2023-06-04 22:17:07 +00:00
|
|
|
assert count_output(stdout, '^0x0020\t33:33:00:00:00:16\t\t234a9a6ddcca3cb728751cea49d01bb0\t$') == 5
|
|
|
|
assert count_output(stdout, '^0x0020\t33:33:ff:00:00:00\t\t234a9a6ddcca3cb728751cea49d01bb0\t$') == 1
|
|
|
|
assert count_output(stdout, '^0x0020\t33:33:ff:00:03:00\t\t234a9a6ddcca3cb728751cea49d01bb0\t$') == 1
|
|
|
|
assert count_output(stdout, '^0x0020\tff:ff:ff:ff:ff:ff\t\t234a9a6ddcca3cb728751cea49d01bb0\t$') == 4
|
|
|
|
assert count_output(stdout, '^0x0028\t02:00:00:00:03:00\t618b4d1829e2a496d7fd8c034a6d024d\t\t$') == 2
|
|
|
|
assert count_output(stdout, '^0x0028\t02:00:00:00:00:00\t618b4d1829e2a496d7fd8c034a6d024d\t\t$') == 1
|
2019-10-28 17:19:00 +00:00
|
|
|
# Verify RSN PTK KeyID parsing
|
2023-06-04 22:17:07 +00:00
|
|
|
assert count_output(stdout, '^0x0028\t02:00:00:00:00:00\t\t\t1$') == 1
|
|
|
|
assert count_output(stdout, '^0x0028\t02:00:00:00:00:00\tf31ecff5452f4c286cf66ef50d10dabe\t\t0$') == 1
|
|
|
|
assert count_output(stdout, '^0x0028\t02:00:00:00:00:00\t28dd851decf3f1c2a35df8bcc22fa1d2\t\t1$') == 1
|
2019-10-28 17:19:00 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_ccmp_256(self, cmd_tshark, capture_file, features, test_env):
|
2020-01-12 22:28:37 +00:00
|
|
|
'''IEEE 802.11 decode CCMP-256'''
|
|
|
|
# Included in git sources test/captures/wpa-ccmp-256.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-01-12 22:28:37 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa-ccmp-256.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 4e6abbcf9dc0943936700b6825952218f58a47dfdf51dbb8ce9b02fd7d2d9e40 || wlan.analysis.gtk == 502085ca205e668f7e7c61cdf4f731336bb31e4f5b28ec91860174192e9b2190',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK is correct
|
|
|
|
assert grep_output(stdout, 'DHCP Request') # Verifies TK is correct
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK is correct
|
2020-01-12 22:28:37 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_gcmp(self, cmd_tshark, capture_file, features, test_env):
|
2020-03-08 11:40:20 +00:00
|
|
|
'''IEEE 802.11 decode GCMP'''
|
|
|
|
# Included in git sources test/captures/wpa-gcmp.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-03-08 11:40:20 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa-gcmp.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 755a9c1c9e605d5ff62849e4a17a935c || wlan.analysis.gtk == 7ff30f7a8dd67950eaaf2f20a869a62d',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK is correct
|
|
|
|
assert grep_output(stdout, 'DHCP Request') # Verifies TK is correct
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK is correct
|
2020-03-08 11:40:20 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_gcmp_256(self, cmd_tshark, capture_file, features, test_env):
|
2020-03-08 11:40:20 +00:00
|
|
|
'''IEEE 802.11 decode GCMP-256'''
|
|
|
|
# Included in git sources test/captures/wpa-gcmp-256.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-03-08 11:40:20 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa-gcmp-256.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == b3dc2ff2d88d0d34c1ddc421cea17f304af3c46acbbe7b6d808b6ebf1b98ec38 || wlan.analysis.gtk == a745ee2313f86515a155c4cb044bc148ae234b9c72707f772b69c2fede3e4016',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK is correct
|
|
|
|
assert grep_output(stdout, 'DHCP Request') # Verifies TK is correct
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK is correct
|
2020-03-08 11:40:20 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa2_ft_psk_no_roam(self, cmd_tshark, capture_file, test_env):
|
2021-01-22 09:57:05 +00:00
|
|
|
'''IEEE 802.11 decode WPA2 FT PSK (without roam verification)'''
|
|
|
|
# Included in git sources test/captures/wpa2-ft-psk.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2021-01-22 09:57:05 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa2-ft-psk.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == ba60c7be2944e18f31949508a53ee9d6 || wlan.analysis.gtk == 6eab6a5f8d880f81104ed65ab0c74449',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
2021-01-22 09:57:05 +00:00
|
|
|
# Verifies that traffic from initial authentication can be decrypted (both TK and GTK)
|
2023-06-04 22:17:07 +00:00
|
|
|
assert count_output(stdout, 'DHCP Discover') == 2
|
|
|
|
assert count_output(stdout, 'DHCP Offer') == 1
|
|
|
|
assert count_output(stdout, 'DHCP Request') == 2
|
|
|
|
assert count_output(stdout, 'DHCP ACK') == 1
|
|
|
|
assert count_output(stdout, 'ARP.*Who has') == 3
|
|
|
|
assert count_output(stdout, 'ARP.*is at') == 1
|
|
|
|
assert count_output(stdout, r'ICMP.*Echo \(ping\)') == 2
|
|
|
|
|
|
|
|
def test_80211_wpa2_ft_psk_roam(self, cmd_tshark, capture_file, features, test_env):
|
2021-01-06 06:49:59 +00:00
|
|
|
'''IEEE 802.11 decode WPA2 FT PSK'''
|
|
|
|
# Included in git sources test/captures/wpa2-ft-psk.pcapng.gz
|
2021-01-22 09:57:05 +00:00
|
|
|
|
|
|
|
# Verify TK and GTK for both initial authentication (AP1) and roam(AP2).
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2021-01-06 06:49:59 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa2-ft-psk.pcapng.gz'),
|
2021-01-22 09:57:05 +00:00
|
|
|
'-Y', 'wlan.analysis.tk == ba60c7be2944e18f31949508a53ee9d6 || wlan.analysis.gtk == 6eab6a5f8d880f81104ed65ab0c74449 || wlan.analysis.tk == a6a3304e5a8fabe0dc427cc41a707858 || wlan.analysis.gtk == a6cc605e10878f86b20a266c9b58d230',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert count_output(stdout, 'DHCP Discover') == 2
|
|
|
|
assert count_output(stdout, 'DHCP Offer') == 1
|
|
|
|
assert count_output(stdout, 'DHCP Request') == 2
|
|
|
|
assert count_output(stdout, 'DHCP ACK') == 1
|
|
|
|
assert count_output(stdout, 'ARP.*Who has') == 5
|
|
|
|
assert count_output(stdout, 'ARP.*is at') == 2
|
|
|
|
assert count_output(stdout, r'ICMP.*Echo \(ping\)') == 4
|
|
|
|
|
|
|
|
def test_80211_wpa2_ft_eap(self, cmd_tshark, capture_file, test_env):
|
2021-01-11 22:47:22 +00:00
|
|
|
'''IEEE 802.11 decode WPA2 FT EAP'''
|
|
|
|
# Included in git sources test/captures/wpa2-ft-eap.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2021-01-11 22:47:22 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa2-ft-eap.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 65471b64605bf2a04af296284cb4ae2a || wlan.analysis.gtk == 1783a5c28e046df6fb58cf4406c4b22c',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.1.1') # Verifies GTK decryption
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
|
|
|
|
|
|
|
|
class TestDecrypt80211UserTk:
|
|
|
|
def test_80211_user_tk_tkip(self, cmd_tshark, capture_file, test_env):
|
2020-05-22 19:32:38 +00:00
|
|
|
'''IEEE 802.11 decode TKIP using user TK'''
|
|
|
|
# Included in git sources test/captures/wpa1-gtk-rekey.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-05-22 19:32:38 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa1-gtk-rekey.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == "d0e57d224c1bb8806089d8c23154074c" || wlan.analysis.gtk == "6eaf63f4ad7997ced353723de3029f4d" || wlan.analysis.gtk == "fb42811bcb59b7845376246454fbdab7"',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'DHCP Discover')
|
|
|
|
assert count_output(stdout, 'ICMP.*Echo .ping') == 8
|
2020-05-22 19:32:38 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_user_tk_ccmp(self, cmd_tshark, capture_file, features, test_env):
|
2020-05-22 19:32:38 +00:00
|
|
|
'''IEEE 802.11 decode CCMP-128 using user TK'''
|
|
|
|
# Included in git sources test/captures/wpa2-psk-mfp.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-05-22 19:32:38 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa2-psk-mfp.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 4e30e8c019bea43ea5262b10853b818d || wlan.analysis.gtk == 70cdbf2e5bc0ca22e53930818a5d80e4',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK decryption
|
|
|
|
assert grep_output(stdout, 'DHCP Request') # Verifies TK decryption
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
|
2020-05-22 19:32:38 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_user_tk_ccmp_256(self, cmd_tshark, capture_file, features, test_env):
|
2020-05-22 19:32:38 +00:00
|
|
|
'''IEEE 802.11 decode CCMP-256 using user TK'''
|
|
|
|
# Included in git sources test/captures/wpa-ccmp-256.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-05-22 19:32:38 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa-ccmp-256.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 4e6abbcf9dc0943936700b6825952218f58a47dfdf51dbb8ce9b02fd7d2d9e40 || wlan.analysis.gtk == 502085ca205e668f7e7c61cdf4f731336bb31e4f5b28ec91860174192e9b2190',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK decryption
|
|
|
|
assert grep_output(stdout, 'DHCP Request') # Verifies TK decryption
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
|
2020-05-22 19:32:38 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_user_tk_gcmp(self, cmd_tshark, capture_file, features, test_env):
|
2020-05-22 19:32:38 +00:00
|
|
|
'''IEEE 802.11 decode GCMP using user TK'''
|
|
|
|
# Included in git sources test/captures/wpa-gcmp.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-05-22 19:32:38 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa-gcmp.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == 755a9c1c9e605d5ff62849e4a17a935c || wlan.analysis.gtk == 7ff30f7a8dd67950eaaf2f20a869a62d',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK decryption
|
|
|
|
assert grep_output(stdout, 'DHCP Request') # Verifies TK decryption
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
|
2020-05-22 19:32:38 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_80211_wpa_gcmp_256(self, cmd_tshark, capture_file, features, test_env):
|
2020-05-22 19:32:38 +00:00
|
|
|
'''IEEE 802.11 decode GCMP-256 using user TK'''
|
|
|
|
# Included in git sources test/captures/wpa-gcmp-256.pcapng.gz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-05-22 19:32:38 +00:00
|
|
|
'-o', 'wlan.enable_decryption: TRUE',
|
|
|
|
'-r', capture_file('wpa-gcmp-256.pcapng.gz'),
|
|
|
|
'-Y', 'wlan.analysis.tk == b3dc2ff2d88d0d34c1ddc421cea17f304af3c46acbbe7b6d808b6ebf1b98ec38 || wlan.analysis.gtk == a745ee2313f86515a155c4cb044bc148ae234b9c72707f772b69c2fede3e4016',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'Who has 192.168.5.5') # Verifies GTK decryption
|
|
|
|
assert grep_output(stdout, 'DHCP Request') # Verifies TK decryption
|
|
|
|
assert grep_output(stdout, r'Echo \(ping\) request') # Verifies TK decryption
|
|
|
|
|
|
|
|
|
|
|
|
class TestDecryptDTLS:
|
|
|
|
def test_dtls_rsa(self, cmd_tshark, capture_file, features, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''DTLS'''
|
2018-11-30 00:41:21 +00:00
|
|
|
if not features.have_gnutls:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires GnuTLS.')
|
2021-12-21 01:49:34 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/wikis/uploads/__moin_import__/attachments/SampleCaptures/snakeoil.tgz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('snakeoil-dtls.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'data.data',
|
|
|
|
'-Y', 'data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '697420776f726b20210a')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_dtls_psk_aes128ccm8(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''DTLS 1.2 with PSK, AES-128-CCM-8'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('dtls12-aes128ccm8.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'dtls.psk:ca19e028a8a372ad2d325f950fcaceed',
|
|
|
|
'-x'
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
dt_count = count_output(stdout, 'Decrypted DTLS')
|
|
|
|
wfm_count = count_output(stdout, 'Works for me!.')
|
|
|
|
assert dt_count == 7 and wfm_count == 2
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_dtls_dsb_aes128ccm8(self, cmd_tshark, capture_file, test_env):
|
2019-01-17 16:52:52 +00:00
|
|
|
'''DTLS 1.2 with master secrets in a pcapng Decryption Secrets Block.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2019-01-17 16:52:52 +00:00
|
|
|
'-r', capture_file('dtls12-aes128ccm8-dsb.pcapng'),
|
|
|
|
'-x'
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
dt_count = count_output(stdout, 'Decrypted DTLS')
|
|
|
|
wfm_count = count_output(stdout, 'Works for me!.')
|
|
|
|
assert dt_count == 7 and wfm_count == 2
|
2019-01-17 16:52:52 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_dtls_udt(self, cmd_tshark, dirs, capture_file, features, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''UDT over DTLS 1.2 with RSA key'''
|
2018-11-30 00:41:21 +00:00
|
|
|
if not features.have_gnutls:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires GnuTLS.')
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'udt-dtls.key')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('udt-dtls.pcapng.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'dtls.keys_list:0.0.0.0,0,data,{}'.format(key_file),
|
|
|
|
'-Y', 'dtls && udt.type==ack',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'UDT')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptTLS:
|
|
|
|
def test_tls_rsa(self, cmd_tshark, capture_file, features, test_env):
|
2018-11-30 00:41:21 +00:00
|
|
|
'''TLS using the server's private RSA key.'''
|
|
|
|
if not features.have_gnutls:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires GnuTLS.')
|
2021-12-21 01:49:34 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/wikis/uploads/__moin_import__/attachments/SampleCaptures/snakeoil2_070531.tgz
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('rsasnakeoil2.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http.request.uri',
|
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'favicon.ico')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls_rsa_pq(self, cmd_tshark, dirs, capture_file, features, test_env):
|
2018-09-13 15:40:27 +00:00
|
|
|
'''TLS using the server's private key with p < q
|
2018-04-03 00:12:23 +00:00
|
|
|
(test whether libgcrypt is correctly called)'''
|
2018-11-30 00:41:21 +00:00
|
|
|
if not features.have_gnutls:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires GnuTLS.')
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'rsa-p-lt-q.key')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('rsa-p-lt-q.pcap'),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-o', 'tls.keys_list:0.0.0.0,443,http,{}'.format(key_file),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http.request.uri',
|
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '/')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls_rsa_privkeys_uat(self, cmd_tshark, dirs, capture_file, features, test_env):
|
2018-12-09 16:28:48 +00:00
|
|
|
'''Check TLS decryption works using the rsa_keys UAT.'''
|
|
|
|
if not features.have_gnutls:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires GnuTLS.')
|
2018-12-09 16:28:48 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'rsa-p-lt-q.key')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-12-09 16:28:48 +00:00
|
|
|
'-r', capture_file('rsa-p-lt-q.pcap'),
|
|
|
|
'-o', 'uat:rsa_keys:"{}",""'.format(key_file.replace('\\', '\\x5c')),
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http.request.uri',
|
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert '/' in stdout
|
2018-12-09 16:28:48 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls_rsa_with_password(self, cmd_tshark, capture_file, features, test_env):
|
2018-09-13 15:40:27 +00:00
|
|
|
'''TLS using the server's private key with password'''
|
2018-11-30 00:41:21 +00:00
|
|
|
if not features.have_gnutls:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires GnuTLS.')
|
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('dmgr.pcapng'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http.request.uri',
|
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'unsecureLogon.jsp')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls_master_secret(self, cmd_tshark, dirs, capture_file, test_env):
|
2018-09-13 15:40:27 +00:00
|
|
|
'''TLS using the master secret and ssl.keylog_file preference aliasing'''
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'dhe1_keylog.dat')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('dhe1.pcapng.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'ssl.keylog_file: {}'.format(key_file),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-o', 'tls.desegment_ssl_application_data: FALSE',
|
|
|
|
'-o', 'http.tls.port: 443',
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
2018-09-13 15:40:27 +00:00
|
|
|
'-e', 'http.request.method',
|
2018-04-03 00:12:23 +00:00
|
|
|
'-e', 'http.request.uri',
|
2018-09-13 15:40:27 +00:00
|
|
|
'-e', 'http.request.version',
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, r'GET\s+/test\s+HTTP/1.0')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls12_renegotiation(self, cmd_tshark, dirs, capture_file, features, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''TLS 1.2 with renegotiation'''
|
2018-11-30 00:41:21 +00:00
|
|
|
if not features.have_gnutls:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires GnuTLS.')
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'rsasnakeoil2.key')
|
2019-02-05 13:13:29 +00:00
|
|
|
# Test protocol alias while at it (ssl -> tls)
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('tls-renegotiation.pcap'),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-o', 'tls.keys_list:0.0.0.0,4433,http,{}'.format(key_file),
|
2019-02-05 13:13:29 +00:00
|
|
|
'-d', 'tcp.port==4433,ssl',
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http.content_length',
|
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
count_0 = count_output(stdout, '^0$')
|
|
|
|
count_2151 = count_output(stdout, '^2151$')
|
|
|
|
assert count_0 == 1 and count_2151 == 1
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls12_psk_aes128ccm(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''TLS 1.2 with PSK, AES-128-CCM'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('tls12-aes128ccm.pcap'),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-o', 'tls.psk:ca19e028a8a372ad2d325f950fcaceed',
|
2018-04-03 00:12:23 +00:00
|
|
|
'-q',
|
2018-09-13 15:40:27 +00:00
|
|
|
'-z', 'follow,tls,ascii,0',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'http://www.gnu.org/software/gnutls')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls12_psk_aes256gcm(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''TLS 1.2 with PSK, AES-256-GCM'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('tls12-aes256gcm.pcap'),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-o', 'tls.psk:ca19e028a8a372ad2d325f950fcaceed',
|
2018-04-03 00:12:23 +00:00
|
|
|
'-q',
|
2018-09-13 15:40:27 +00:00
|
|
|
'-z', 'follow,tls,ascii,0',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'http://www.gnu.org/software/gnutls')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls12_chacha20poly1305(self, cmd_tshark, dirs, features, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''TLS 1.2 with ChaCha20-Poly1305'''
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'tls12-chacha20poly1305.keys')
|
2018-04-03 00:12:23 +00:00
|
|
|
ciphers=[
|
|
|
|
'ECDHE-ECDSA-CHACHA20-POLY1305',
|
|
|
|
'ECDHE-RSA-CHACHA20-POLY1305',
|
|
|
|
'DHE-RSA-CHACHA20-POLY1305',
|
|
|
|
'RSA-PSK-CHACHA20-POLY1305',
|
|
|
|
'DHE-PSK-CHACHA20-POLY1305',
|
|
|
|
'ECDHE-PSK-CHACHA20-POLY1305',
|
|
|
|
'PSK-CHACHA20-POLY1305',
|
|
|
|
]
|
|
|
|
stream = 0
|
|
|
|
for cipher in ciphers:
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('tls12-chacha20poly1305.pcap'),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-o', 'tls.keylog_file: {}'.format(key_file),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-q',
|
2018-09-13 15:40:27 +00:00
|
|
|
'-z', 'follow,tls,ascii,{}'.format(stream),
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
2018-04-03 00:12:23 +00:00
|
|
|
stream += 1
|
2023-06-04 22:17:07 +00:00
|
|
|
assert grep_output(stdout, 'Cipher is {}'.format(cipher))
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls13_chacha20poly1305(self, cmd_tshark, dirs, features, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''TLS 1.3 with ChaCha20-Poly1305'''
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'tls13-20-chacha20poly1305.keys')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('tls13-20-chacha20poly1305.pcap'),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-o', 'tls.keylog_file: {}'.format(key_file),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-q',
|
2018-09-13 15:40:27 +00:00
|
|
|
'-z', 'follow,tls,ascii,0',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'TLS13-CHACHA20-POLY1305-SHA256')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls13_rfc8446(self, cmd_tshark, dirs, features, capture_file, test_env):
|
2018-08-16 22:36:55 +00:00
|
|
|
'''TLS 1.3 (normal session, then early data followed by normal data).'''
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'tls13-rfc8446.keys')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('tls13-rfc8446.pcap'),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-otls.keylog_file:{}'.format(key_file),
|
2018-08-16 22:36:55 +00:00
|
|
|
'-Y', 'http',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'http.request.uri',
|
|
|
|
'-e', 'http.file_data',
|
|
|
|
'-E', 'separator=|',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
2023-09-19 17:52:21 +00:00
|
|
|
first_response = binascii.hexlify(b'Request for /first, version TLSv1.3, Early data: no\n').decode("ascii")
|
|
|
|
early_response = binascii.hexlify(b'Request for /early, version TLSv1.3, Early data: yes\n').decode("ascii")
|
|
|
|
second_response = binascii.hexlify(b'Request for /second, version TLSv1.3, Early data: yes\n').decode("ascii")
|
2024-03-22 22:02:08 +00:00
|
|
|
# assert [
|
|
|
|
# r'5|/first|',
|
|
|
|
# fr'6||{first_response}',
|
|
|
|
# r'8|/early|',
|
|
|
|
# fr'10||{early_response}',
|
|
|
|
# r'12|/second|',
|
|
|
|
# fr'13||{second_response}',
|
|
|
|
# ] == stdout.splitlines()
|
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
assert [
|
2018-08-16 22:36:55 +00:00
|
|
|
r'5|/first|',
|
2024-03-22 22:02:08 +00:00
|
|
|
fr'6|/first|{first_response}',
|
2018-08-16 22:36:55 +00:00
|
|
|
r'8|/early|',
|
2024-03-23 01:30:02 +00:00
|
|
|
fr'10|/early|{early_response}',
|
2018-08-16 22:36:55 +00:00
|
|
|
r'12|/second|',
|
2024-03-22 22:02:08 +00:00
|
|
|
fr'13|/second|{second_response}',
|
2023-06-04 22:17:07 +00:00
|
|
|
] == stdout.splitlines()
|
2018-08-16 22:36:55 +00:00
|
|
|
|
2024-03-22 23:23:18 +00:00
|
|
|
def test_tls13_rfc8446_noearly(self, cmd_tshark, dirs, features, capture_file, test_env):
|
2018-08-16 22:36:55 +00:00
|
|
|
'''TLS 1.3 (with undecryptable early data).'''
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'tls13-rfc8446-noearly.keys')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('tls13-rfc8446.pcap'),
|
2018-09-13 15:40:27 +00:00
|
|
|
'-otls.keylog_file:{}'.format(key_file),
|
2018-08-16 22:36:55 +00:00
|
|
|
'-Y', 'http',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'http.request.uri',
|
|
|
|
'-e', 'http.file_data',
|
|
|
|
'-E', 'separator=|',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
2023-09-19 17:52:21 +00:00
|
|
|
first_response = binascii.hexlify(b'Request for /first, version TLSv1.3, Early data: no\n').decode("ascii")
|
|
|
|
early_response = binascii.hexlify(b'Request for /early, version TLSv1.3, Early data: yes\n').decode("ascii")
|
|
|
|
second_response = binascii.hexlify(b'Request for /second, version TLSv1.3, Early data: yes\n').decode("ascii")
|
2024-03-22 22:02:08 +00:00
|
|
|
# assert [
|
|
|
|
# r'5|/first|',
|
|
|
|
# fr'6||{first_response}',
|
|
|
|
# fr'10||{early_response}',
|
|
|
|
# r'12|/second|',
|
|
|
|
# fr'13||{second_response}',
|
|
|
|
# ] == stdout.splitlines()
|
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
assert [
|
2018-08-16 22:36:55 +00:00
|
|
|
r'5|/first|',
|
2024-03-22 22:02:08 +00:00
|
|
|
fr'6|/first|{first_response}',
|
2023-09-19 17:52:21 +00:00
|
|
|
fr'10||{early_response}',
|
2018-08-16 22:36:55 +00:00
|
|
|
r'12|/second|',
|
2024-03-22 22:02:08 +00:00
|
|
|
fr'13|/second|{second_response}',
|
2023-06-04 22:17:07 +00:00
|
|
|
] == stdout.splitlines()
|
2018-08-16 22:36:55 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_tls12_dsb(self, cmd_tshark, capture_file, test_env):
|
2018-11-18 17:11:42 +00:00
|
|
|
'''TLS 1.2 with master secrets in pcapng Decryption Secrets Blocks.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
output = subprocess.check_output((cmd_tshark,
|
2018-11-18 17:11:42 +00:00
|
|
|
'-r', capture_file('tls12-dsb.pcapng'),
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http.host',
|
|
|
|
'-e', 'http.response.code',
|
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert 'example.com\t\n\t200\nexample.net\t\n\t200\n' == output
|
2018-08-16 22:36:55 +00:00
|
|
|
|
TLS: Fix TLS tunneled within TLS
In order to retrieve the correct set of TLS information, previously
pinfo->curr_layer_num was used. However, this is not a stable
identifier between the first and later passes, as subdissectors that
couldn't dissect data due to fragmentation on the first pass aren't
called on later passes.
To fix issue #16109, the layer number wasn't used at all, which did
break TLS over TLS.
We now have pinfo->curr_proto_layer_num which specifically counts
the number of layers of the current protocol instead of the total
number of layers; using that instead fixes TLS within TLS (in most
situations; some very rare cases, e.g. DVB baseband frames with
multiple TCP PDUs, which might be from the same or from different
TCP connections, might not work, but those don't work currently either)
while not reopening #16109.
Add tests for both cases, the one fixed by the other workaround and
for TLS over TLS.
As noted in the comments to #16109, there are other dissectors that
use curr_layer_num that might break in some cases because it's not stable.
Fix #17977.
2023-05-06 10:53:40 +00:00
|
|
|
def test_tls_over_tls(self, cmd_tshark, dirs, capture_file, features, test_env):
|
|
|
|
'''TLS using the server's private key with p < q
|
|
|
|
(test whether libgcrypt is correctly called)'''
|
|
|
|
if not features.have_gnutls:
|
|
|
|
pytest.skip('Requires GnuTLS.')
|
|
|
|
key_file = os.path.join(dirs.key_dir, 'tls-over-tls.key')
|
|
|
|
output = subprocess.check_output((cmd_tshark,
|
|
|
|
'-r', capture_file('tls-over-tls.pcapng.gz'),
|
|
|
|
'-o', 'tls.keys_list:0.0.0.0,443,http,{}'.format(key_file),
|
|
|
|
'-z', 'expert,tls.handshake.certificates',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'tls.handshake.certificate_length',
|
|
|
|
'-Y', 'tls.handshake.certificates',
|
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert '1152,1115,1352\n1152\n1412,1434,1382\n' == output
|
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptZigbee:
|
|
|
|
def test_zigbee(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''ZigBee'''
|
2020-09-15 21:42:19 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/issues/7022
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('sample_control4_2012-03-24.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'data.data',
|
|
|
|
'-Y', 'zbee_aps',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '3067636338652063342e646d2e747620')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptANSIC122:
|
|
|
|
def test_ansi_c1222(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''ANSI C12.22'''
|
2020-09-15 21:42:19 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/issues/9196
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('c1222_std_example8.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'c1222.decrypt: TRUE',
|
|
|
|
'-o', 'c1222.baseoid: 2.16.124.113620.1.22.0',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'c1222.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '00104d414e55464143545552455220534e2092')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptDVBCI:
|
|
|
|
def test_dvb_ci(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''DVB-CI'''
|
|
|
|
# simplified version of the sample capture in
|
2020-09-15 21:42:19 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/issues/6700
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('dvb-ci_UV1_0000.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'dvb-ci.sek: 00000000000000000000000000000000',
|
|
|
|
'-o', 'dvb-ci.siv: 00000000000000000000000000000000',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'dvb-ci.cc.sac.padding',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '800000000000000000000000')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptIPsec:
|
|
|
|
def test_ipsec_esp(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IPsec ESP'''
|
2020-09-15 21:42:19 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/issues/12671
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('esp-bug-12671.pcapng.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'esp.enable_encryption_decode: TRUE',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'data.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '08090a0b0c0d0e0f1011121314151617')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptIkeIsakmp:
|
|
|
|
def test_ikev1_certs(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv1 (ISAKMP) with certificates'''
|
2020-09-15 21:42:19 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/issues/7951
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev1-certs.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'x509sat.printableString',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'OpenSwan')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev1_simultaneous(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv1 (ISAKMP) simultaneous exchanges'''
|
2020-09-15 21:42:19 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/issues/12610
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev1-bug-12610.pcapng.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.hash',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'b52521f774967402c9f6cee95fd17e5b')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev1_unencrypted(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv1 (ISAKMP) unencrypted phase 1'''
|
2020-09-15 21:42:19 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/issues/12620
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev1-bug-12620.pcapng.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.hash',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '40043b640f4373250d5ac3a1fb63153c')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev2_3des_sha160(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv2 decryption test (3DES-CBC/SHA1_160)'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev2-decrypt-3des-sha1_160.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.auth.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '02f7a0d5f1fdc8ea81039818c65bb9bd09af9b8917319b887ff9ba3046c344c7')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev2_aes128_ccm12(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv2 decryption test (AES-128-CCM-12) - with CBC-MAC verification'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev2-decrypt-aes128ccm12.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.auth.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'c2104394299e1ffe7908ea720ad5d13717a0d454e4fa0a2128ea689411f479c4')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev2_aes128_ccm12_2(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv2 decryption test (AES-128-CCM-12 using CTR mode, without checksum)'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev2-decrypt-aes128ccm12-2.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.auth.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'aaa281c87b4a19046c57271d557488ca413b57228cb951f5fa9640992a0285b9')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev2_aes192ctr_sha512(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv2 decryption test (AES-192-CTR/SHA2-512)'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev2-decrypt-aes192ctr.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.auth.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '3ec23dcf9348485638407c754547aeb3085290082c49f583fdbae59263a20b4a')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev2_aes256cbc_sha256(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv2 decryption test (AES-256-CBC/SHA2-256)'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev2-decrypt-aes256cbc.pcapng'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.auth.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'e1a8d550064201a7ec024a85758d0673c61c5c510ac13bcd225d6327f50da3d3')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev2_aes256ccm16(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv2 decryption test (AES-256-CCM-16)'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev2-decrypt-aes256ccm16.pcapng'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.auth.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'fa2e74bdc01e30fb0b3ddc9723c9449095969da51f69e560209d2c2b7940210a')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev2_aes256gcm16(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv2 decryption test (AES-256-GCM-16)'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev2-decrypt-aes256gcm16.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.auth.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '9ab71f14ab553cad873a1aa70b99df155dee77cdcf3694b3b7527acbb9712ded')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_ikev2_aes256gcm8(self, cmd_tshark, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''IKEv2 decryption test (AES-256-GCM-8)'''
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('ikev2-decrypt-aes256gcm8.pcap'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'isakmp.auth.data',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, '4a66d822d0afbc22ad9a92a2cf4287c920ad8ac3b069a4a7e75fe0a5d499f914')
|
2018-04-03 00:12:23 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptHttp2:
|
|
|
|
def test_http2(self, cmd_tshark, capture_file, features, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''HTTP2 (HPACK)'''
|
2018-11-13 01:17:33 +00:00
|
|
|
if not features.have_nghttp2:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires nghttp2.')
|
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('packet-h2-14_headers.pcapng'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http2.header.value',
|
|
|
|
'-d', 'tcp.port==3000,http2',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, 'nghttp2')
|
|
|
|
|
|
|
|
|
|
|
|
class TestDecryptKerberos:
|
|
|
|
def test_kerberos(self, cmd_tshark, dirs, features, capture_file, test_env):
|
2018-04-03 00:12:23 +00:00
|
|
|
'''Kerberos'''
|
|
|
|
# Files are from krb-816.zip on the SampleCaptures page.
|
2018-11-13 01:17:33 +00:00
|
|
|
if not features.have_kerberos:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires kerberos.')
|
2018-11-13 01:17:33 +00:00
|
|
|
keytab_file = os.path.join(dirs.key_dir, 'krb-816.keytab')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('krb-816.pcap.gz'),
|
2018-04-03 00:12:23 +00:00
|
|
|
'-o', 'kerberos.decrypt: TRUE',
|
|
|
|
'-o', 'kerberos.file: {}'.format(keytab_file),
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'kerberos.keyvalue',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
2018-04-03 00:12:23 +00:00
|
|
|
# keyvalue: ccda7d48219f73c3b28311c4ba7242b3
|
2023-06-04 22:17:07 +00:00
|
|
|
assert grep_output(stdout, 'ccda7d48219f73c3b28311c4ba7242b3')
|
2018-06-22 17:36:11 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
@pytest.fixture
|
|
|
|
def run_wireguard_test(cmd_tshark, capture_file, result_file, features, test_env):
|
2018-11-13 01:17:33 +00:00
|
|
|
def runOne(self, args, keylog=None, pcap_file='wireguard-ping-tcp.pcap'):
|
|
|
|
if keylog:
|
2023-05-08 06:32:58 +00:00
|
|
|
keylog_file = result_file('wireguard.keys')
|
2018-11-13 01:17:33 +00:00
|
|
|
args += ['-owg.keylog_file:%s' % keylog_file]
|
|
|
|
with open(keylog_file, 'w') as f:
|
|
|
|
f.write("\n".join(keylog))
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output([cmd_tshark, '-r', capture_file(pcap_file)] + args, encoding='utf-8', env=test_env)
|
|
|
|
return stdout.splitlines()
|
2018-11-13 01:17:33 +00:00
|
|
|
return runOne
|
|
|
|
|
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptWireguard:
|
2018-07-26 11:54:43 +00:00
|
|
|
# The "foo_alt" keys are similar as "foo" except that some bits are changed.
|
|
|
|
# The crypto library should be able to handle this and internally the
|
|
|
|
# dissector uses MSB to recognize whether a private key is set.
|
2018-06-22 17:36:11 +00:00
|
|
|
key_Spriv_i = 'AKeZaHwBxjiKLFnkY2unvEdOTtg4AL+M9dQXfopFVFk='
|
2018-07-26 11:54:43 +00:00
|
|
|
key_Spriv_i_alt = 'B6eZaHwBxjiKLFnkY2unvEdOTtg4AL+M9dQXfopFVJk='
|
2018-06-22 17:36:11 +00:00
|
|
|
key_Spub_i = 'Igge9KzRytKNwrgkzDE/8hrLu6Ly0OqVdvOPWhA5KR4='
|
|
|
|
key_Spriv_r = 'cFIxTUyBs1Qil414hBwEgvasEax8CKJ5IS5ZougplWs='
|
|
|
|
key_Spub_r = 'YDCttCs9e1J52/g9vEnwJJa+2x6RqaayAYMpSVQfGEY='
|
|
|
|
key_Epriv_i0 = 'sLGLJSOQfyz7JNJ5ZDzFf3Uz1rkiCMMjbWerNYcPFFU='
|
2018-07-26 11:54:43 +00:00
|
|
|
key_Epriv_i0_alt = 't7GLJSOQfyz7JNJ5ZDzFf3Uz1rkiCMMjbWerNYcPFJU='
|
2018-06-22 17:36:11 +00:00
|
|
|
key_Epriv_r0 = 'QC4/FZKhFf0b/eXEcCecmZNt6V6PXmRa4EWG1PIYTU4='
|
|
|
|
key_Epriv_i1 = 'ULv83D+y3vA0t2mgmTmWz++lpVsrP7i4wNaUEK2oX0E='
|
|
|
|
key_Epriv_r1 = 'sBv1dhsm63cbvWMv/XML+bvynBp9PTdY9Vvptu3HQlg='
|
2018-08-01 00:10:40 +00:00
|
|
|
# Ephemeral keys and PSK for wireguard-psk.pcap
|
|
|
|
key_Epriv_i2 = 'iCv2VTi/BC/q0egU931KXrrQ4TSwXaezMgrhh7uCbXs='
|
|
|
|
key_Epriv_r2 = '8G1N3LnEqYC7+NW/b6mqceVUIGBMAZSm+IpwG1U0j0w='
|
|
|
|
key_psk2 = '//////////////////////////////////////////8='
|
|
|
|
key_Epriv_i3 = '+MHo9sfkjPsjCx7lbVhRLDvMxYvTirOQFDSdzAW6kUQ='
|
|
|
|
key_Epriv_r3 = '0G6t5j1B/We65MXVEBIGuRGYadwB2ITdvJovtAuATmc='
|
|
|
|
key_psk3 = 'iIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIiIg='
|
|
|
|
# dummy key that should not work with anything.
|
|
|
|
key_dummy = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx='
|
2018-06-22 17:36:11 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_mac1_public(self, run_wireguard_test):
|
2018-06-22 17:36:11 +00:00
|
|
|
"""Check that MAC1 identification using public keys work."""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-06-22 17:36:11 +00:00
|
|
|
'-ouat:wg_keys:"Public","%s"' % self.key_Spub_i,
|
|
|
|
'-ouat:wg_keys:"Public","%s"' % self.key_Spub_r,
|
|
|
|
'-Y', 'wg.receiver_pubkey',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.receiver_pubkey',
|
|
|
|
'-e', 'wg.receiver_pubkey.known_privkey',
|
|
|
|
])
|
2023-06-04 22:17:07 +00:00
|
|
|
assert len(lines) == 4
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '1\t%s\tFalse' % self.key_Spub_r in lines
|
|
|
|
assert '2\t%s\tFalse' % self.key_Spub_i in lines
|
|
|
|
assert '13\t%s\tFalse' % self.key_Spub_r in lines
|
|
|
|
assert '14\t%s\tFalse' % self.key_Spub_i in lines
|
2018-06-22 17:36:11 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_mac1_private(self, run_wireguard_test):
|
2018-06-22 17:36:11 +00:00
|
|
|
"""Check that MAC1 identification using private keys work."""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-06-22 17:36:11 +00:00
|
|
|
'-ouat:wg_keys:"Private","%s"' % self.key_Spriv_i,
|
|
|
|
'-ouat:wg_keys:"Private","%s"' % self.key_Spriv_r,
|
|
|
|
'-Y', 'wg.receiver_pubkey',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.receiver_pubkey',
|
|
|
|
'-e', 'wg.receiver_pubkey.known_privkey',
|
|
|
|
])
|
2023-06-04 22:17:07 +00:00
|
|
|
assert len(lines) == 4
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '1\t%s\tTrue' % self.key_Spub_r in lines
|
|
|
|
assert '2\t%s\tTrue' % self.key_Spub_i in lines
|
|
|
|
assert '13\t%s\tTrue' % self.key_Spub_r in lines
|
|
|
|
assert '14\t%s\tTrue' % self.key_Spub_i in lines
|
2018-07-24 21:50:51 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_decrypt_initiation_sprivr(self, run_wireguard_test):
|
2018-07-24 21:50:51 +00:00
|
|
|
"""Check for partial decryption using Spriv_r."""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-07-24 21:50:51 +00:00
|
|
|
'-ouat:wg_keys:"Private","%s"' % self.key_Spriv_r,
|
|
|
|
'-Y', 'wg.type==1',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.static',
|
|
|
|
'-e', 'wg.static.known_pubkey',
|
|
|
|
'-e', 'wg.static.known_privkey',
|
|
|
|
'-e', 'wg.timestamp.nanoseconds',
|
|
|
|
])
|
|
|
|
# static pubkey is unknown because Spub_i is not added to wg_keys.
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '1\t%s\tFalse\tFalse\t%s' % (self.key_Spub_i, '356537872') in lines
|
|
|
|
assert '13\t%s\tFalse\tFalse\t%s' % (self.key_Spub_i, '490514356') in lines
|
2018-07-26 11:54:43 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_decrypt_initiation_ephemeral_only(self, run_wireguard_test):
|
2018-07-26 11:54:43 +00:00
|
|
|
"""Check for partial decryption using Epriv_i."""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-07-26 11:54:43 +00:00
|
|
|
'-ouat:wg_keys:"Public","%s"' % self.key_Spub_r,
|
|
|
|
'-Y', 'wg.type==1',
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.ephemeral.known_privkey',
|
|
|
|
'-e', 'wg.static',
|
|
|
|
'-e', 'wg.timestamp.nanoseconds',
|
|
|
|
], keylog=[
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i0,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i1,
|
|
|
|
])
|
|
|
|
# The current implementation tries to write as much decrypted data as
|
|
|
|
# possible, even if the full handshake cannot be derived.
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '1\tTrue\t%s\t%s' % (self.key_Spub_i, '') in lines
|
|
|
|
assert '13\tTrue\t%s\t%s' % (self.key_Spub_i, '') in lines
|
2018-07-26 11:54:43 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_decrypt_full_initiator(self, run_wireguard_test):
|
2018-07-26 11:54:43 +00:00
|
|
|
"""
|
2018-07-26 17:10:31 +00:00
|
|
|
Check for full handshake decryption using Spriv_r + Epriv_i.
|
2018-07-26 11:54:43 +00:00
|
|
|
The public key Spub_r is provided via the key log as well.
|
|
|
|
"""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-07-26 11:54:43 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.ephemeral.known_privkey',
|
|
|
|
'-e', 'wg.static',
|
|
|
|
'-e', 'wg.timestamp.nanoseconds',
|
2018-07-26 17:10:31 +00:00
|
|
|
'-e', 'wg.handshake_ok',
|
2018-07-26 18:10:52 +00:00
|
|
|
'-e', 'icmp.type',
|
|
|
|
'-e', 'tcp.dstport',
|
2018-07-26 11:54:43 +00:00
|
|
|
], keylog=[
|
|
|
|
' REMOTE_STATIC_PUBLIC_KEY = %s' % self.key_Spub_r,
|
|
|
|
' LOCAL_STATIC_PRIVATE_KEY = %s' % self.key_Spriv_i_alt,
|
|
|
|
' LOCAL_EPHEMERAL_PRIVATE_KEY = %s' % self.key_Epriv_i0_alt,
|
|
|
|
' LOCAL_EPHEMERAL_PRIVATE_KEY = %s' % self.key_Epriv_i1,
|
|
|
|
])
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '1\tTrue\t%s\t%s\t\t\t' % (self.key_Spub_i, '356537872') in lines
|
|
|
|
assert '2\tFalse\t\t\tTrue\t\t' in lines
|
2023-06-04 22:17:07 +00:00
|
|
|
assert '3\t\t\t\t\t8\t' in lines
|
|
|
|
assert '4\t\t\t\t\t0\t' in lines
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '13\tTrue\t%s\t%s\t\t\t' % (self.key_Spub_i, '490514356') in lines
|
|
|
|
assert '14\tFalse\t\t\tTrue\t\t' in lines
|
2023-06-04 22:17:07 +00:00
|
|
|
assert '17\t\t\t\t\t\t443' in lines
|
|
|
|
assert '18\t\t\t\t\t\t49472' in lines
|
2018-07-26 17:10:31 +00:00
|
|
|
|
2019-05-21 17:06:49 +00:00
|
|
|
def test_decrypt_wg_full_initiator_dsb(self, run_wireguard_test):
|
|
|
|
"""
|
|
|
|
Similar to test_decrypt_full_initiator, but using decryption keys
|
|
|
|
embedded in the pcapng file. The embedded secrets do not contain leading
|
|
|
|
spaces nor spaces around the '=' character.
|
|
|
|
"""
|
|
|
|
lines = run_wireguard_test(self, [
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.ephemeral.known_privkey',
|
|
|
|
'-e', 'wg.static',
|
|
|
|
'-e', 'wg.timestamp.nanoseconds',
|
|
|
|
'-e', 'wg.handshake_ok',
|
|
|
|
'-e', 'icmp.type',
|
|
|
|
'-e', 'tcp.dstport',
|
|
|
|
], pcap_file='wireguard-ping-tcp-dsb.pcapng')
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '1\tTrue\t%s\t%s\t\t\t' % (self.key_Spub_i, '356537872') in lines
|
|
|
|
assert '2\tFalse\t\t\tTrue\t\t' in lines
|
2023-06-04 22:17:07 +00:00
|
|
|
assert '3\t\t\t\t\t8\t' in lines
|
|
|
|
assert '4\t\t\t\t\t0\t' in lines
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '13\tTrue\t%s\t%s\t\t\t' % (self.key_Spub_i, '490514356') in lines
|
|
|
|
assert '14\tFalse\t\t\tTrue\t\t' in lines
|
2023-06-04 22:17:07 +00:00
|
|
|
assert '17\t\t\t\t\t\t443' in lines
|
|
|
|
assert '18\t\t\t\t\t\t49472' in lines
|
2019-05-21 17:06:49 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_decrypt_full_responder(self, run_wireguard_test):
|
2018-07-26 17:10:31 +00:00
|
|
|
"""Check for full handshake decryption using responder secrets."""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-07-26 17:10:31 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.ephemeral.known_privkey',
|
|
|
|
'-e', 'wg.static',
|
|
|
|
'-e', 'wg.timestamp.nanoseconds',
|
|
|
|
'-e', 'wg.handshake_ok',
|
2018-07-26 18:10:52 +00:00
|
|
|
'-e', 'icmp.type',
|
|
|
|
'-e', 'tcp.dstport',
|
2018-07-26 17:10:31 +00:00
|
|
|
], keylog=[
|
|
|
|
'REMOTE_STATIC_PUBLIC_KEY=%s' % self.key_Spub_i,
|
|
|
|
'LOCAL_STATIC_PRIVATE_KEY=%s' % self.key_Spriv_r,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r0,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r1,
|
|
|
|
])
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '1\tFalse\t%s\t%s\t\t\t' % (self.key_Spub_i, '356537872') in lines
|
|
|
|
assert '2\tTrue\t\t\tTrue\t\t' in lines
|
2023-06-04 22:17:07 +00:00
|
|
|
assert '3\t\t\t\t\t8\t' in lines
|
|
|
|
assert '4\t\t\t\t\t0\t' in lines
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '13\tFalse\t%s\t%s\t\t\t' % (self.key_Spub_i, '490514356') in lines
|
|
|
|
assert '14\tTrue\t\t\tTrue\t\t' in lines
|
2023-06-04 22:17:07 +00:00
|
|
|
assert '17\t\t\t\t\t\t443' in lines
|
|
|
|
assert '18\t\t\t\t\t\t49472' in lines
|
2018-08-01 00:10:40 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_decrypt_psk_initiator(self, run_wireguard_test):
|
2018-08-01 00:10:40 +00:00
|
|
|
"""Check whether PSKs enable decryption for initiation keys."""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-08-01 00:10:40 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.handshake_ok',
|
|
|
|
], keylog=[
|
|
|
|
'REMOTE_STATIC_PUBLIC_KEY = %s' % self.key_Spub_r,
|
|
|
|
'LOCAL_STATIC_PRIVATE_KEY = %s' % self.key_Spriv_i,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i2,
|
|
|
|
'PRESHARED_KEY=%s' % self.key_psk2,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r3,
|
|
|
|
'PRESHARED_KEY=%s' % self.key_psk3,
|
|
|
|
], pcap_file='wireguard-psk.pcap')
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '2\tTrue' in lines
|
|
|
|
assert '4\tTrue' in lines
|
2018-08-01 00:10:40 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_decrypt_psk_responder(self, run_wireguard_test):
|
2018-08-01 00:10:40 +00:00
|
|
|
"""Check whether PSKs enable decryption for responder keys."""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-08-01 00:10:40 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.handshake_ok',
|
|
|
|
], keylog=[
|
|
|
|
'REMOTE_STATIC_PUBLIC_KEY=%s' % self.key_Spub_i,
|
|
|
|
'LOCAL_STATIC_PRIVATE_KEY=%s' % self.key_Spriv_r,
|
|
|
|
# Epriv_r2 needs psk2. This tests handling of duplicate ephemeral
|
|
|
|
# keys with multiple PSKs. It should not have adverse effects.
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r2,
|
|
|
|
'PRESHARED_KEY=%s' % self.key_dummy,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r2,
|
|
|
|
'PRESHARED_KEY=%s' % self.key_psk2,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i3,
|
|
|
|
'PRESHARED_KEY=%s' % self.key_psk3,
|
|
|
|
# Epriv_i3 needs psk3, this tests that additional keys again have no
|
|
|
|
# bad side-effects.
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i3,
|
|
|
|
'PRESHARED_KEY=%s' % self.key_dummy,
|
|
|
|
], pcap_file='wireguard-psk.pcap')
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '2\tTrue' in lines
|
|
|
|
assert '4\tTrue' in lines
|
2018-08-01 00:10:40 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
def test_decrypt_psk_wrong_orderl(self, run_wireguard_test):
|
2018-08-01 00:10:40 +00:00
|
|
|
"""Check that the wrong order of lines indeed fail decryption."""
|
2018-11-13 01:17:33 +00:00
|
|
|
lines = run_wireguard_test(self, [
|
2018-08-01 00:10:40 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'frame.number',
|
|
|
|
'-e', 'wg.handshake_ok',
|
|
|
|
], keylog=[
|
|
|
|
'REMOTE_STATIC_PUBLIC_KEY=%s' % self.key_Spub_i,
|
|
|
|
'LOCAL_STATIC_PRIVATE_KEY=%s' % self.key_Spriv_r,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_r2,
|
|
|
|
'LOCAL_EPHEMERAL_PRIVATE_KEY=%s' % self.key_Epriv_i3,
|
|
|
|
'PRESHARED_KEY=%s' % self.key_psk2, # note: swapped with previous line
|
|
|
|
'PRESHARED_KEY=%s' % self.key_psk3,
|
|
|
|
], pcap_file='wireguard-psk.pcap')
|
2023-09-21 23:41:32 +00:00
|
|
|
assert '2\tFalse' in lines
|
|
|
|
assert '4\tFalse' in lines
|
2018-08-16 08:49:31 +00:00
|
|
|
|
2018-11-13 01:17:33 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptKnxip:
|
2018-08-16 08:49:31 +00:00
|
|
|
# Capture files for these tests contain single telegrams.
|
|
|
|
# For realistic (live captured) KNX/IP telegram sequences, see:
|
2020-09-15 21:42:19 +00:00
|
|
|
# https://gitlab.com/wireshark/wireshark/-/issues/14825
|
2018-08-16 08:49:31 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_knxip_data_security_decryption_ok(self, cmd_tshark, capture_file, test_env):
|
2018-08-16 08:49:31 +00:00
|
|
|
'''KNX/IP: Data Security decryption OK'''
|
2018-11-13 01:17:33 +00:00
|
|
|
# capture_file('knxip_DataSec.pcap') contains KNX/IP ConfigReq DataSec PropExtValueWriteCon telegram
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('knxip_DataSec.pcap'),
|
2018-08-16 08:49:31 +00:00
|
|
|
'-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, ' DataSec ')
|
|
|
|
assert grep_output(stdout, ' PropExtValueWriteCon ')
|
2018-08-16 08:49:31 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_knxip_data_security_decryption_fails(self, cmd_tshark, capture_file, test_env):
|
2018-08-16 08:49:31 +00:00
|
|
|
'''KNX/IP: Data Security decryption fails'''
|
2018-11-13 01:17:33 +00:00
|
|
|
# capture_file('knxip_DataSec.pcap') contains KNX/IP ConfigReq DataSec PropExtValueWriteCon telegram
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('knxip_DataSec.pcap'),
|
2018-08-16 08:49:31 +00:00
|
|
|
'-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, ' DataSec ')
|
|
|
|
assert not grep_output(stdout, ' PropExtValueWriteCon ')
|
2018-08-16 08:49:31 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_knxip_secure_wrapper_decryption_ok(self, cmd_tshark, capture_file, test_env):
|
2018-08-16 08:49:31 +00:00
|
|
|
'''KNX/IP: SecureWrapper decryption OK'''
|
2018-11-13 01:17:33 +00:00
|
|
|
# capture_file('knxip_SecureWrapper.pcap') contains KNX/IP SecureWrapper RoutingInd telegram
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('knxip_SecureWrapper.pcap'),
|
2018-08-16 08:49:31 +00:00
|
|
|
'-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, ' SecureWrapper ')
|
|
|
|
assert grep_output(stdout, ' RoutingInd ')
|
2018-08-16 08:49:31 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_knxip_secure_wrapper_decryption_fails(self, cmd_tshark, capture_file, test_env):
|
2018-08-16 08:49:31 +00:00
|
|
|
'''KNX/IP: SecureWrapper decryption fails'''
|
2018-11-13 01:17:33 +00:00
|
|
|
# capture_file('knxip_SecureWrapper.pcap') contains KNX/IP SecureWrapper RoutingInd telegram
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('knxip_SecureWrapper.pcap'),
|
2018-08-16 08:49:31 +00:00
|
|
|
'-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, ' SecureWrapper ')
|
|
|
|
assert not grep_output(stdout, ' RoutingInd ')
|
2018-08-16 08:49:31 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_knxip_timer_notify_authentication_ok(self, cmd_tshark, capture_file, test_env):
|
2018-08-16 08:49:31 +00:00
|
|
|
'''KNX/IP: TimerNotify authentication OK'''
|
2018-11-13 01:17:33 +00:00
|
|
|
# capture_file('knxip_TimerNotify.pcap') contains KNX/IP TimerNotify telegram
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('knxip_TimerNotify.pcap'),
|
2018-08-16 08:49:31 +00:00
|
|
|
'-o', 'kip.key_1:00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, ' TimerNotify ')
|
|
|
|
assert grep_output(stdout, ' OK$')
|
2018-08-16 08:49:31 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_knxip_timer_notify_authentication_fails(self, cmd_tshark, capture_file, test_env):
|
2018-08-16 08:49:31 +00:00
|
|
|
'''KNX/IP: TimerNotify authentication fails'''
|
2018-11-13 01:17:33 +00:00
|
|
|
# capture_file('knxip_TimerNotify.pcap') contains KNX/IP TimerNotify telegram
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('knxip_TimerNotify.pcap'),
|
2018-08-16 08:49:31 +00:00
|
|
|
'-o', 'kip.key_1:""', # "" is really necessary, otherwise test fails
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert grep_output(stdout, ' TimerNotify ')
|
|
|
|
assert not grep_output(stdout, ' OK$')
|
2018-08-16 08:49:31 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_knxip_keyring_xml_import(self, cmd_tshark, dirs, capture_file, test_env):
|
2018-08-16 08:49:31 +00:00
|
|
|
'''KNX/IP: keyring.xml import'''
|
|
|
|
# key_file "keyring.xml" contains KNX decryption keys
|
2018-11-13 01:17:33 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'knx_keyring.xml')
|
|
|
|
# capture_file('empty.pcap') is empty
|
2018-08-16 08:49:31 +00:00
|
|
|
# Write extracted key info to stdout
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-08-16 08:49:31 +00:00
|
|
|
'-o', 'kip.key_file:' + key_file,
|
|
|
|
'-o', 'kip.key_info_file:-',
|
2018-11-13 01:17:33 +00:00
|
|
|
'-r', capture_file('empty.pcap'),
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
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$')
|
|
|
|
assert grep_output(stdout, '^GA 1/7/131 sender 1[.]1[.]1$')
|
|
|
|
assert grep_output(stdout, '^GA 1/7/131 sender 1[.]1[.]3$')
|
|
|
|
assert grep_output(stdout, '^GA 1/7/131 sender 1[.]1[.]4$')
|
|
|
|
assert grep_output(stdout, '^GA 1/7/132 sender 1[.]1[.]2$')
|
|
|
|
assert grep_output(stdout, '^GA 1/7/132 sender 1[.]1[.]4$')
|
|
|
|
assert grep_output(stdout, '^GA 6/7/191 sender 1[.]1[.]1$')
|
|
|
|
assert grep_output(stdout, '^GA 0/1/0 sender 1[.]1[.]1$')
|
|
|
|
assert grep_output(stdout, '^GA 0/1/0 sender 1[.]1[.]3$')
|
|
|
|
assert grep_output(stdout, '^GA 0/1/0 sender 1[.]1[.]4$')
|
|
|
|
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$')
|
|
|
|
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$')
|
|
|
|
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$')
|
|
|
|
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$')
|
|
|
|
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$')
|
|
|
|
assert grep_output(stdout, '^IA 1[.]1[.]1 SeqNr 45678$')
|
|
|
|
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$')
|
|
|
|
assert grep_output(stdout, '^IA 1[.]1[.]2 SeqNr 34567$')
|
|
|
|
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$')
|
|
|
|
assert grep_output(stdout, '^IA 1[.]1[.]3 SeqNr 23456$')
|
|
|
|
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$')
|
|
|
|
assert grep_output(stdout, '^IA 1[.]1[.]4 SeqNr 12345$')
|
|
|
|
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$')
|
|
|
|
assert grep_output(stdout, '^IA 2[.]1[.]0 SeqNr 1234$')
|
|
|
|
|
|
|
|
|
|
|
|
@pytest.fixture(scope='session')
|
2018-12-12 13:34:00 +00:00
|
|
|
def softhsm_paths(features):
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
search_path = os.getenv('PATH') + r';C:\SoftHSM2\bin'
|
|
|
|
else:
|
|
|
|
search_path = None
|
|
|
|
softhsm_tool = shutil.which('softhsm2-util', path=search_path)
|
|
|
|
if not softhsm_tool:
|
|
|
|
# Note: do not fallback to SoftHSMv1. While available on Ubuntu 14.04
|
|
|
|
# (and 16.04), it is built with botan < 1.11.10 which causes a crash due
|
|
|
|
# to a conflict with the GMP library that is also used by GnuTLS/nettle.
|
|
|
|
# See https://github.com/randombit/botan/issues/1090
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('SoftHSM is not found')
|
2018-12-12 13:34:00 +00:00
|
|
|
# Find provider library path.
|
|
|
|
bindir = os.path.dirname(softhsm_tool)
|
|
|
|
libdir = os.path.join(os.path.dirname(bindir), 'lib')
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
libdirs = [libdir, bindir]
|
|
|
|
if features.have_x64:
|
|
|
|
name = 'softhsm2-x64.dll'
|
|
|
|
else:
|
|
|
|
name = 'softhsm2.dll'
|
|
|
|
else:
|
2021-02-18 17:53:12 +00:00
|
|
|
# Look in a variety of paths, Debian/Ubuntu, Fedora, RHEL/CentOS
|
2018-12-12 13:34:00 +00:00
|
|
|
madir = sysconfig.get_config_var('multiarchsubdir')
|
2021-02-18 17:53:12 +00:00
|
|
|
libdir_archs = (libdir, libdir + '64')
|
|
|
|
libdir_subs = ('softhsm', 'pkcs11', '')
|
2018-12-12 13:34:00 +00:00
|
|
|
libdirs = [os.path.join(libdir + madir, 'softhsm')] if madir else []
|
2021-02-18 17:53:12 +00:00
|
|
|
libdirs += [os.path.join(arch, sub) for sub in libdir_subs for arch in libdir_archs]
|
2018-12-12 13:34:00 +00:00
|
|
|
name = 'libsofthsm2.so'
|
|
|
|
for libdir in libdirs:
|
|
|
|
provider = os.path.join(libdir, name)
|
|
|
|
if os.path.exists(provider):
|
|
|
|
break
|
|
|
|
else:
|
|
|
|
# Even if p11-kit can automatically locate it, do not rely on it.
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('SoftHSM provider library not detected')
|
2018-12-12 13:34:00 +00:00
|
|
|
# Now check whether the import tool is usable. SoftHSM < 2.3.0 did not
|
|
|
|
# set CKA_DECRYPT when using softhsm2-tool --import and therefore cannot be
|
|
|
|
# used to import keys for decryption. Use GnuTLS p11tool as workaround.
|
|
|
|
softhsm_version = subprocess.check_output([softhsm_tool, '--version'],
|
|
|
|
universal_newlines=True).strip()
|
|
|
|
use_p11tool = softhsm_version in ('2.0.0', '2.1.0', '2.2.0')
|
|
|
|
if use_p11tool and not shutil.which('p11tool'):
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('SoftHSM available, but GnuTLS p11tool is unavailable')
|
2018-12-12 13:34:00 +00:00
|
|
|
return use_p11tool, softhsm_tool, provider
|
|
|
|
|
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
@pytest.fixture
|
2018-12-12 13:34:00 +00:00
|
|
|
def softhsm(softhsm_paths, home_path, base_env):
|
|
|
|
'''Creates a temporary SoftHSM token store (and set it in the environment),
|
|
|
|
returns a function to populate that token store and the path to the PKCS #11
|
|
|
|
provider library.'''
|
|
|
|
use_p11tool, softhsm_tool, provider = softhsm_paths
|
|
|
|
conf_path = os.path.join(home_path, 'softhsm-test.conf')
|
|
|
|
db_path = os.path.join(home_path, 'softhsm-test-tokens')
|
|
|
|
os.makedirs(db_path)
|
|
|
|
with open(conf_path, 'w') as f:
|
|
|
|
f.write('directories.tokendir = %s\n' % db_path)
|
|
|
|
f.write('objectstore.backend = file\n')
|
|
|
|
# Avoid syslog spam
|
|
|
|
f.write('log.level = ERROR\n')
|
|
|
|
base_env['SOFTHSM2_CONF'] = conf_path
|
|
|
|
|
|
|
|
tool_env = base_env.copy()
|
|
|
|
if sys.platform == 'win32':
|
|
|
|
# Ensure that softhsm2-util can find the library.
|
|
|
|
tool_env['PATH'] += ';%s' % os.path.dirname(provider)
|
|
|
|
|
|
|
|
# Initialize tokens store.
|
|
|
|
token_name = 'Wireshark-Test-Tokens'
|
|
|
|
pin = 'Secret'
|
|
|
|
subprocess.check_call([softhsm_tool, '--init-token', '--slot', '0',
|
|
|
|
'--label', token_name, '--so-pin', 'Supersecret', '--pin', pin],
|
|
|
|
env=tool_env)
|
|
|
|
if use_p11tool:
|
|
|
|
tool_env['GNUTLS_PIN'] = pin
|
|
|
|
|
|
|
|
# Arbitrary IDs and labels.
|
|
|
|
ids = iter(range(0xab12, 0xffff))
|
|
|
|
def import_key(keyfile):
|
|
|
|
'''Returns a PKCS #11 URI to identify the imported key.'''
|
|
|
|
label = os.path.basename(keyfile)
|
|
|
|
obj_id = '%x' % next(ids)
|
|
|
|
if not use_p11tool:
|
|
|
|
tool_args = [softhsm_tool, '--import', keyfile, '--label', label,
|
|
|
|
'--id', obj_id, '--pin', pin, '--token', token_name]
|
|
|
|
else:
|
|
|
|
# Fallback for SoftHSM < 2.3.0
|
|
|
|
tool_args = ['p11tool', '--provider', provider, '--batch',
|
|
|
|
'--login', '--write', 'pkcs11:token=%s' % token_name,
|
|
|
|
'--load-privkey', keyfile, '--label', label, '--id', obj_id]
|
|
|
|
subprocess.check_call(tool_args, env=tool_env)
|
|
|
|
id_str = '%{}{}%{}{}'.format(*obj_id)
|
|
|
|
return 'pkcs11:token=%s;id=%s;type=private' % (token_name, id_str)
|
|
|
|
|
|
|
|
return types.SimpleNamespace(import_key=import_key, provider=provider, pin=pin)
|
|
|
|
|
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptPkcs11:
|
|
|
|
def test_tls_pkcs11(self, cmd_tshark, dirs, capture_file, features, softhsm, test_env):
|
2018-12-12 13:34:00 +00:00
|
|
|
'''Check that a RSA key in a PKCS #11 token enables decryption.'''
|
|
|
|
if not features.have_pkcs11:
|
2023-06-04 22:17:07 +00:00
|
|
|
pytest.skip('Requires GnuTLS with PKCS #11 support.')
|
2018-12-12 13:34:00 +00:00
|
|
|
key_file = os.path.join(dirs.key_dir, 'rsa-p-lt-q.p8')
|
|
|
|
key_uri = softhsm.import_key(key_file)
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2018-12-12 13:34:00 +00:00
|
|
|
'-r', capture_file('rsa-p-lt-q.pcap'),
|
|
|
|
'-o', 'uat:pkcs11_libs:"{}"'.format(softhsm.provider.replace('\\', '\\x5c')),
|
|
|
|
'-o', 'uat:rsa_keys:"{}","{}"'.format(key_uri, softhsm.pin),
|
|
|
|
'-Tfields',
|
|
|
|
'-e', 'http.request.uri',
|
|
|
|
'-Y', 'http',
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=test_env)
|
|
|
|
assert '/' in stdout
|
2019-01-24 20:30:02 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
class TestDecryptSmb2:
|
2020-02-19 21:35:50 +00:00
|
|
|
BAD_KEY = 'ffffffffffffffffffffffffffffffff'
|
2019-01-24 20:30:02 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
@staticmethod
|
|
|
|
def check_bad_key(cmd_tshark, cap, disp_filter, sesid, seskey, s2ckey, c2skey, env=None):
|
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-02-19 21:35:50 +00:00
|
|
|
'-r', cap,
|
|
|
|
'-o', 'uat:smb2_seskey_list:{},{},{},{}'.format(sesid, seskey, s2ckey, c2skey),
|
|
|
|
'-Y', disp_filter,
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=env)
|
|
|
|
assert 'Encrypted SMB' in stdout
|
2019-01-24 20:30:02 +00:00
|
|
|
|
2020-02-19 21:35:50 +00:00
|
|
|
#
|
|
|
|
# SMB3.0 CCM bad keys tests
|
|
|
|
#
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb300_bad_seskey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that a bad session key doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '1900009c003c0000', self.BAD_KEY, '""', '""', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb300_bad_s2ckey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that a bad s2c key doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '1900009c003c0000', '""', self.BAD_KEY, '""', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb300_bad_c2skey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that a bad c2s key doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '1900009c003c0000', '""', '""', self.BAD_KEY, env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb300_bad_deckey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that bad decryption keys doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '1900009c003c0000', '""', self.BAD_KEY, self.BAD_KEY, env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb300_bad_allkey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that all bad keys doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '1900009c003c0000', self.BAD_KEY, self.BAD_KEY, self.BAD_KEY, env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# SMB3.1.1 CCM bad key tests
|
|
|
|
#
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_bad_seskey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that a bad session key doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '2900009c003c0000', self.BAD_KEY, '""', '""', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_bad_s2ckey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that a bad s2c key doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '2900009c003c0000', '""', self.BAD_KEY, '""', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_bad_c2skey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that a bad c2s key doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '2900009c003c0000', '""', '""', self.BAD_KEY, env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_bad_deckey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that bad decryption keys doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '2900009c003c0000', '""', self.BAD_KEY, self.BAD_KEY, env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_bad_allkey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check that all bad keys doesn't crash'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_bad_key(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
|
|
|
|
'frame.number == 7', '2900009c003c0000', self.BAD_KEY, self.BAD_KEY, self.BAD_KEY, env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
|
|
|
#
|
|
|
|
# Decryption tests
|
|
|
|
#
|
2019-01-24 20:30:02 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def check_tree(cmd_tshark, cap, tree, sesid, seskey, s2ckey, c2skey, env=None):
|
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-02-19 21:35:50 +00:00
|
|
|
'-r', cap,
|
|
|
|
'-o', 'uat:smb2_seskey_list:{},{},{},{}'.format(sesid, seskey, s2ckey, c2skey),
|
2019-01-24 20:30:02 +00:00
|
|
|
'-Tfields',
|
|
|
|
'-e', 'smb2.tree',
|
|
|
|
'-Y', 'smb2.tree == "{}"'.format(tree.replace('\\', '\\\\')),
|
2023-11-07 12:09:34 +00:00
|
|
|
), encoding='unicode_escape', env=env)
|
|
|
|
# Remove the escapes (we only have one field so this causes no issue)
|
2023-06-04 22:17:07 +00:00
|
|
|
assert tree == stdout.strip()
|
2019-06-14 19:35:48 +00:00
|
|
|
|
2020-02-19 21:35:50 +00:00
|
|
|
# SMB3.0 CCM
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb300_aes128ccm_seskey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check SMB 3.0 AES128CCM decryption with session key.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
|
2020-02-19 21:35:50 +00:00
|
|
|
r'\\dfsroot1.foo.test\IPC$', '1900009c003c0000',
|
2023-06-04 22:17:07 +00:00
|
|
|
'9a9ea16a0cdbeb6064772318073f172f', '""', '""', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb300_aes128ccm_deckey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check SMB 3.0 AES128CCM decryption with decryption keys.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb300-aes-128-ccm.pcap.gz'),
|
2020-02-19 21:35:50 +00:00
|
|
|
r'\\dfsroot1.foo.test\IPC$', '1900009c003c0000',
|
2023-06-04 22:17:07 +00:00
|
|
|
'""', '8be6cc53d4beba29387e69aef035d497','bff985870e81784d533fdc09497b8eab', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
|
|
|
|
2021-07-14 22:16:03 +00:00
|
|
|
# SMB3.1.1 AES-CCM-128
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes128ccm_seskey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check SMB 3.1.1 AES128CCM decryption with session key.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
|
2020-02-19 21:35:50 +00:00
|
|
|
r'\\dfsroot1.foo.test\IPC$', '2900009c003c0000',
|
2023-06-04 22:17:07 +00:00
|
|
|
'f1fa528d3cd182cca67bd4596dabd885', '""', '""', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes128ccm_deckey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check SMB 3.1.1 AES128CCM decryption with decryption keys.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-128-ccm.pcap.gz'),
|
2020-02-19 21:35:50 +00:00
|
|
|
r'\\dfsroot1.foo.test\IPC$', '2900009c003c0000',
|
2023-06-04 22:17:07 +00:00
|
|
|
'""', '763d5552dbc9650b700869467a5857e4', '35e69833c6578e438c8701cb40bf483e', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2021-07-14 22:16:03 +00:00
|
|
|
# SMB3.1.1 AES-GCM-128
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes128gcm_seskey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check SMB 3.1.1 AES128GCM decryption with session key.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-128-gcm.pcap.gz'),
|
2020-02-19 21:35:50 +00:00
|
|
|
r'\\dfsroot1.foo.test\IPC$', '3900000000400000',
|
2023-06-04 22:17:07 +00:00
|
|
|
'e79161ded03bda1449b2c8e58f753953', '""', '""', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes128gcm_deckey(self, features, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check SMB 3.1.1 AES128GCM decryption with decryption keys.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-128-gcm.pcap.gz'),
|
2020-02-19 21:35:50 +00:00
|
|
|
r'\\dfsroot1.foo.test\IPC$', '3900000000400000',
|
2023-06-04 22:17:07 +00:00
|
|
|
'""', 'b02f5de25e0562075c3dc329fa2aa396', '7201623a31754e6581864581209dd3d2', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2021-07-14 22:16:03 +00:00
|
|
|
# SMB3.1.1 AES-CCM-256
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes256ccm_seskey(self, features, cmd_tshark, capture_file, test_env):
|
2021-07-14 22:16:03 +00:00
|
|
|
'''Check SMB 3.1.1 AES256CCM decryption with session key.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-256-ccm.pcap.gz'),
|
2021-07-14 22:16:03 +00:00
|
|
|
r'\\172.31.9.163\IPC$', 'd6fdb96d00000000',
|
|
|
|
'6b559c2e60519e344581d086a6d3d050',
|
|
|
|
'""',
|
2023-06-04 22:17:07 +00:00
|
|
|
'""', env=test_env)
|
2021-07-14 22:16:03 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes256ccm_deckey(self, features, cmd_tshark, capture_file, test_env):
|
2021-07-14 22:16:03 +00:00
|
|
|
'''Check SMB 3.1.1 AES256CCM decryption with decryption keys.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-256-ccm.pcap.gz'),
|
2021-07-14 22:16:03 +00:00
|
|
|
r'\\172.31.9.163\IPC$', 'd6fdb96d00000000',
|
|
|
|
'""',
|
|
|
|
'014fccd4a53554bf5b54b27a32512b35fca262b90e088a5efa7d6c952418578b',
|
2023-06-04 22:17:07 +00:00
|
|
|
'1d34170138a77dac4abbe0149253c8b977a71f399081cda6cbaf62359670c1c5', env=test_env)
|
2021-07-14 22:16:03 +00:00
|
|
|
|
|
|
|
# SMB3.1.1 AES-GCM-256
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes256gcm_seskey(self, features, cmd_tshark, capture_file, test_env):
|
2021-07-14 22:16:03 +00:00
|
|
|
'''Check SMB 3.1.1 AES256GCM decryption with session key.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-256-gcm.pcap.gz'),
|
2021-07-14 22:16:03 +00:00
|
|
|
r'\\172.31.9.163\IPC$', '56dc03ab00000000',
|
|
|
|
'6a5004adfbdef1abd5879800675324e5',
|
|
|
|
'""',
|
2023-06-04 22:17:07 +00:00
|
|
|
'""', env=test_env)
|
2021-07-14 22:16:03 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes256gcm_deckey(self, features, cmd_tshark, capture_file, test_env):
|
2021-07-14 22:16:03 +00:00
|
|
|
'''Check SMB 3.1.1 AES256GCM decryption with decryption keys.'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, capture_file('smb311-aes-256-gcm.pcap.gz'),
|
2021-07-14 22:16:03 +00:00
|
|
|
r'\\172.31.9.163\IPC$', '56dc03ab00000000',
|
|
|
|
'""',
|
|
|
|
'46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f',
|
2023-06-04 22:17:07 +00:00
|
|
|
'484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4', env=test_env)
|
2021-07-14 22:16:03 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def check_partial(home_path, cmd_tshark, full_cap, pkt_skip, tree, sesid, s2ckey, c2skey, env=None):
|
2020-02-19 21:35:50 +00:00
|
|
|
# generate a trace without NegProt and SessionSetup
|
|
|
|
partial_cap = os.path.join(home_path, 'short.pcap')
|
2023-06-04 22:17:07 +00:00
|
|
|
stdout = subprocess.check_output((cmd_tshark,
|
2020-02-19 21:35:50 +00:00
|
|
|
'-r', full_cap,
|
|
|
|
'-Y', 'frame.number >= %d'%pkt_skip,
|
|
|
|
'-w', partial_cap,
|
2023-06-04 22:17:07 +00:00
|
|
|
), encoding='utf-8', env=env)
|
|
|
|
TestDecryptSmb2.check_tree(cmd_tshark, partial_cap, tree, sesid, '""', s2ckey, c2skey)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes128gcm_partial(self, features, home_path, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check SMB 3.1.1 AES128GCM decryption in capture missing session setup'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_partial(home_path, cmd_tshark,
|
2020-02-19 21:35:50 +00:00
|
|
|
capture_file('smb311-aes-128-gcm.pcap.gz'), 7,
|
|
|
|
r'\\dfsroot1.foo.test\IPC$', '3900000000400000',
|
2023-06-04 22:17:07 +00:00
|
|
|
'b02f5de25e0562075c3dc329fa2aa396', '7201623a31754e6581864581209dd3d2', env=test_env)
|
2020-02-19 21:35:50 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes128gcm_partial_keyswap(self, features, home_path, cmd_tshark, capture_file, test_env):
|
2020-02-19 21:35:50 +00:00
|
|
|
'''Check SMB 3.1.1 AES128GCM decryption in capture missing session setup with keys in wrong order'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_partial(home_path, cmd_tshark,
|
2020-02-19 21:35:50 +00:00
|
|
|
capture_file('smb311-aes-128-gcm.pcap.gz'), 7,
|
|
|
|
r'\\dfsroot1.foo.test\IPC$', '3900000000400000',
|
2023-06-04 22:17:07 +00:00
|
|
|
'7201623a31754e6581864581209dd3d2', 'b02f5de25e0562075c3dc329fa2aa396', env=test_env)
|
2021-07-14 22:16:03 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes256gcm_partial(self, features, home_path, cmd_tshark, capture_file, test_env):
|
2021-07-14 22:16:03 +00:00
|
|
|
'''Check SMB 3.1.1 AES128GCM decryption in capture missing session setup'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_partial(home_path, cmd_tshark,
|
2021-07-14 22:16:03 +00:00
|
|
|
capture_file('smb311-aes-256-gcm.pcap.gz'), 7,
|
|
|
|
r'\\172.31.9.163\IPC$', '56dc03ab00000000',
|
|
|
|
'46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f',
|
2023-06-04 22:17:07 +00:00
|
|
|
'484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4', env=test_env)
|
2021-07-14 22:16:03 +00:00
|
|
|
|
2023-06-04 22:17:07 +00:00
|
|
|
def test_smb311_aes256gcm_partial_keyswap(self, features, home_path, cmd_tshark, capture_file, test_env):
|
2021-07-14 22:16:03 +00:00
|
|
|
'''Check SMB 3.1.1 AES256GCM decryption in capture missing session setup with keys in wrong order'''
|
2023-06-04 22:17:07 +00:00
|
|
|
TestDecryptSmb2.check_partial(home_path, cmd_tshark,
|
2021-07-14 22:16:03 +00:00
|
|
|
capture_file('smb311-aes-256-gcm.pcap.gz'), 7,
|
|
|
|
r'\\172.31.9.163\IPC$', '56dc03ab00000000',
|
|
|
|
'484c30bf3e17e322e0d217764d4584a325ec0495519c3f1547e0f996ab76c4c4',
|
2023-06-04 22:17:07 +00:00
|
|
|
'46b64f320a0f856b63b3a0dc2c058a67267830a8cbdd44a088fbf1d0308a981f', env=test_env)
|