diff --git a/modules/test/tls/README.md b/modules/test/tls/README.md index c1f0c9072..cfca8100c 100644 --- a/modules/test/tls/README.md +++ b/modules/test/tls/README.md @@ -14,7 +14,7 @@ Within the ```python/src``` directory, the below tests are executed. | ID | Description | Expected behavior | Required result |---|---|---|---| -| security.tls.v1_0_client | Device uses TLS with connection to an external service on port 443 (or any other port which could be running the webserver-HTTPS) | The packet indicates a TLS connection with at least TLS 1.0 and support | Informational | +| security.tls.v1_0_client | Device uses TLS with connection to an external service on port 443 (or any other port which could be running the webserver-HTTPS) | The packet indicates a TLS connection with at least TLS 1.2 and support | Required if Applicable | | security.tls.v1_2_server | Check the device web server TLS 1.2 and the certificate is valid | TLS 1.2 certificate is issues to the web browser client when accessed | Required if Applicable | | security.tls.v1_2_client | Device uses TLS with connection to an external service on port 443 (or any other port which could be running the webserver-HTTPS) | The packet indicates a TLS connection with at least TLS v1.2 and support for ECDH and ECDSA ciphers | Required if Applicable | | security.tls.v1_3_server | Check the device web server TLS 1.3 and the certificate is valid | TLS 1.3 certificate is issued to the web browser client when accessed | Informational | diff --git a/modules/test/tls/bin/get_client_hello_packets.sh b/modules/test/tls/bin/get_client_hello_packets.sh index fd06a3d28..d6075d48f 100755 --- a/modules/test/tls/bin/get_client_hello_packets.sh +++ b/modules/test/tls/bin/get_client_hello_packets.sh @@ -26,7 +26,7 @@ if [[ $TLS_VERSION == '1.0' ]]; then elif [[ $TLS_VERSION == '1.1' ]]; then TSHARK_FILTER="$TSHARK_FILTER and ssl.handshake.version==0x0302" elif [[ $TLS_VERSION == '1.2' || -z $TLS_VERSION ]]; then - TSHARK_FILTER="$TSHARK_FILTER and ssl.handshake.version==0x0303" + TSHARK_FILTER="$TSHARK_FILTER and ssl.handshake.version==0x0303 and !tls.handshake.extensions.supported_version==0x0304" elif [[ $TLS_VERSION == '1.3' ]]; then TSHARK_FILTER="$TSHARK_FILTER and (ssl.handshake.version==0x0304 or tls.handshake.extensions.supported_version==0x0304)" else diff --git a/modules/test/tls/python/src/tls_module.py b/modules/test/tls/python/src/tls_module.py index bec708d3f..e0cf9f0d3 100644 --- a/modules/test/tls/python/src/tls_module.py +++ b/modules/test/tls/python/src/tls_module.py @@ -507,39 +507,38 @@ def _security_tls_v1_3_server(self): def _security_tls_v1_0_client(self): LOGGER.info('Running security.tls.v1_0_client') - tls_1_0_valid = self._validate_tls_client(self._device_mac, '1.0') - tls_1_1_valid = self._validate_tls_client(self._device_mac, '1.1') - tls_1_2_valid = self._validate_tls_client(self._device_mac, '1.2') - tls_1_3_valid = self._validate_tls_client(self._device_mac, '1.3') - states = [ - tls_1_0_valid[0], tls_1_1_valid[0], tls_1_2_valid[0], tls_1_3_valid[0] - ] - if any(state is True for state in states): - # If any state is True, return True - result_state = True - result_message = 'TLS 1.0 or higher detected' - elif all(state == 'Feature Not Detected' for state in states): - # If all states are "Feature not Detected" - result_state = 'Feature Not Detected' - result_message = tls_1_0_valid[1] - elif all(state == 'Error' for state in states): - # If all states are "Error" - result_state = 'Error' - result_message = '' - else: + try: + tls_versions = self._tls_util.detect_tls_client_versions( + client_mac=self._device_mac, + capture_files=[ + MONITOR_CAPTURE_FILE, STARTUP_CAPTURE_FILE, TLS_CAPTURE_FILE + ] + ) + LOGGER.info(f'TLS client version detection results: {tls_versions}') + except Exception as e: + LOGGER.error(f'Error detecting TLS client versions: {e}') + return 'Error', f'Error detecting TLS client versions: {e}', [] + result_state = 'Feature Not Detected' + result_message = 'No TLS client connections detected.' + result_details = [] + + if tls_versions['1.0']['present'] or tls_versions['1.1']['present']: result_state = False - result_message = 'TLS 1.0 or higher was not detected' - result_details = tuple({ - *tls_1_0_valid[2], - *tls_1_1_valid[2], - *tls_1_2_valid[2], - *tls_1_3_valid[2] - }) - LOGGER.info(f'TLS 1.0 Client Validation details: {result_details}') - result_tags = list( - set(tls_1_0_valid[3] + tls_1_1_valid[3] + tls_1_2_valid[3] + - tls_1_3_valid[3])) - return result_state, result_message, result_details, result_tags + result_message = 'TLS 1.0 or TLS 1.1 detected.' + LOGGER.info(result_message) + result_details.extend(tls_versions['1.0']['details']) + result_details.extend(tls_versions['1.1']['details']) + for detail in result_details: + LOGGER.info(detail) + elif tls_versions['1.2']['present'] or tls_versions['1.3']['present']: + result_state = True + result_message = 'TLS 1.2 or higher detected.' + LOGGER.info(result_message) + result_details.extend(tls_versions['1.2']['details']) + result_details.extend(tls_versions['1.3']['details']) + for detail in result_details: + LOGGER.info(detail) + return result_state, result_message, result_details def _security_tls_v1_2_client(self): LOGGER.info('Running security.tls.v1_2_client') diff --git a/test_vm/provision-compliant.yml b/test_vm/provision-compliant.yml index 0ebd59765..92c6b9a6c 100644 --- a/test_vm/provision-compliant.yml +++ b/test_vm/provision-compliant.yml @@ -270,13 +270,10 @@ fi sleep 1 done - # TLS 1.0 - openssl s_client -connect tls-v1-0.badssl.com:1010 -tls1 -bind "$IP" - # TLS 1.2 - openssl s_client -connect tls-v1-2.badssl.com:1012 -tls1_2 -bind "$IP" - # TLS 1.3 - openssl s_client -connect tls13.badssl.com:443 -tls1_3 -bind "$IP" - + # TLS 1.2 (using OpenSSL 3.1.4) + timeout 3 openssl s_client -connect tls-v1-2.badssl.com:1012 -tls1_2 -bind "$IP" -quiet /dev/null || true + # TLS 1.3 (using OpenSSL 3.1.4) + timeout 3 openssl s_client -connect google.com:443 -tls1_3 -bind "$IP" -quiet /dev/null || true - name: Create systemd service for TLS emulation ansible.builtin.copy: dest: /etc/systemd/system/tls-emulate.service diff --git a/test_vm/provision-non-compliant-tls.yml b/test_vm/provision-non-compliant-tls.yml index 2c6685925..4dc419c59 100644 --- a/test_vm/provision-non-compliant-tls.yml +++ b/test_vm/provision-non-compliant-tls.yml @@ -12,20 +12,73 @@ ssl_key: /etc/ssl/private/nginx-selfsigned.key tasks: - - name: Ensure openssl, dhclient, and nginx are installed + - name: Ensure openssl, dhclient, nginx and build dependencies are installed apt: name: - openssl - isc-dhcp-client - nginx + - perl + - pkg-config + - zlib1g-dev + - wget + - gcc + - make state: present update_cache: yes + - name: Download OpenSSL 1.1.1u source + get_url: + url: https://www.openssl.org/source/openssl-1.1.1u.tar.gz + dest: /tmp/openssl-1.1.1u.tar.gz + mode: '0644' + force: no + + - name: Extract OpenSSL 1.1.1u source + unarchive: + src: /tmp/openssl-1.1.1u.tar.gz + dest: /tmp + remote_src: yes + creates: /tmp/openssl-1.1.1u + + - name: Build and install OpenSSL 1.1.1 + shell: | + ./config --prefix=/opt/openssl-1.1.1 no-shared + make -j"$(nproc)" + make install_sw + args: + chdir: /tmp/openssl-1.1.1u + creates: /opt/openssl-1.1.1/bin/openssl + - name: Run dhclient on ens5 (in background) shell: nohup dhclient {{ iface }} & async: 0 poll: 0 + - name: Download OpenSSL 3.1.4 source + get_url: + url: https://www.openssl.org/source/openssl-3.1.4.tar.gz + dest: /tmp/openssl-3.1.4.tar.gz + mode: '0644' + force: no + + - name: Extract OpenSSL 3.1.4 source + unarchive: + src: /tmp/openssl-3.1.4.tar.gz + dest: /tmp + remote_src: yes + creates: /tmp/openssl-3.1.4 + + - name: Build and install OpenSSL 3.1.4 + shell: | + ./config --prefix=/opt/openssl-3.1.4 no-shared + make -j"$(nproc)" + make install_sw + args: + chdir: /tmp/openssl-3.1.4 + creates: /opt/openssl-3.1.4/bin/openssl + + # NGINX - name: Generate self-signed SSL certificate for nginx @@ -77,6 +130,14 @@ state: restarted enabled: yes + - name: Create custom OpenSSL config for legacy protocol support + copy: + dest: /etc/ssl/openssl-legacy.cnf + content: | + .include /etc/ssl/openssl.cnf + [system_default_sect] + MinProtocol = TLSv1.0 + MaxProtocol = TLSv1.3 - name: Copy fail_tls_handshake.sh script copy: @@ -105,11 +166,17 @@ echo "No IP $ip_addr on $iface" >> $LOG exit 1 fi - # TLS 1.2 + export OPENSSL_CONF=/etc/ssl/openssl-legacy.cnf + OLD_OPENSSL=/opt/openssl-1.1.1/bin/openssl + NEW_OPENSSL=/opt/openssl-3.1.4/bin/openssl + echo "Running TLS 1.0 handshake..." >> $LOG + timeout 3 "$OLD_OPENSSL" s_client -connect tls-v1-0.badssl.com:1010 -tls1 -bind $ip_addr -quiet < /dev/null >> $LOG 2>&1 || true + echo "Running TLS 1.1 handshake..." >> $LOG + timeout 3 "$OLD_OPENSSL" s_client -connect tls-v1-1.badssl.com:1011 -tls1_1 -bind $ip_addr -quiet < /dev/null >> $LOG 2>&1 || true echo "Running TLS 1.2 handshake..." >> $LOG - openssl s_client -connect $host:$port -tls1_2 -cipher "CAMELLIA256-SHA256" -bind $ip_addr -ign_eof < /dev/null >> $LOG 2>&1 + "$NEW_OPENSSL" s_client -connect $host:$port -tls1_2 -cipher "CAMELLIA256-SHA256" -bind $ip_addr -ign_eof < /dev/null >> $LOG 2>&1 echo "Running TLS 1.3 handshake..." >> $LOG - openssl s_client -connect tls-v1-2.badssl.com:1012 -tls1_3 + "$NEW_OPENSSL" s_client -connect tls-v1-2.badssl.com:1012 -tls1_3 - name: Create systemd service for failing TLS handshake diff --git a/testing/unit/tls/tls_module_test.py b/testing/unit/tls/tls_module_test.py index 26aa43d03..a0364b4ce 100644 --- a/testing/unit/tls/tls_module_test.py +++ b/testing/unit/tls/tls_module_test.py @@ -607,9 +607,9 @@ def security_tls_client_allowed_protocols_test(self): # Run the client test test_results = TLS_UTIL.validate_tls_client(client_mac='e4:5f:01:5f:92:9c', - tls_version='1.2', + tls_version='1.3', capture_files=[capture_file]) - print(str(test_results)) + print('results', str(test_results)) self.assertTrue(test_results[0]) def outbound_connections_test(self):