Skip to content

Commit eefaaea

Browse files
committed
Initial work in RSA-PKCS check
1 parent 84616db commit eefaaea

File tree

4 files changed

+72
-28
lines changed

4 files changed

+72
-28
lines changed

checks/models.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,12 @@ class ZeroRttStatus(Enum):
9595
na = 2
9696

9797

98+
class KexRSAPKCSStatus(Enum):
99+
bad = 0
100+
good = 1
101+
unknown = 2
102+
103+
98104
class KexHashFuncStatus(Enum):
99105
bad = 0
100106
good = 1

checks/scoring.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,11 @@
190190
WEB_TLS_OCSP_STAPLING_BAD = NO_POINTS
191191
WEB_TLS_OCSP_STAPLING_WORST_STATUS = STATUS_NOTICE
192192

193+
WEB_TLS_KEX_RSA_PKCS_GOOD = FULL_WEIGHT_POINTS
194+
WEB_TLS_KEX_RSA_PKCS_OK = FULL_WEIGHT_POINTS
195+
WEB_TLS_KEX_RSA_PKCS_BAD = NO_POINTS
196+
WEB_TLS_KEX_RSA_PKCS_WORST_STATUS = STATUS_NOTICE
197+
193198
WEB_TLS_KEX_HASH_FUNC_GOOD = FULL_WEIGHT_POINTS
194199
WEB_TLS_KEX_HASH_FUNC_OK = FULL_WEIGHT_POINTS
195200
WEB_TLS_KEX_HASH_FUNC_BAD = NO_POINTS

checks/tasks/tls/evaluation.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from sslyze.plugins.openssl_cipher_suites.cipher_suites import _TLS_1_3_CIPHER_SUITES
99

1010
from checks import scoring
11-
from checks.models import KexHashFuncStatus, CipherOrderStatus, OcspStatus
11+
from checks.models import KexHashFuncStatus, CipherOrderStatus, OcspStatus, KexRSAPKCSStatus
1212
from checks.tasks.tls.tls_constants import (
1313
PROTOCOLS_GOOD,
1414
PROTOCOLS_SUFFICIENT,
@@ -244,11 +244,22 @@ def score(self) -> scoring.Score:
244244
)
245245

246246

247+
@dataclass(frozen=True)
248+
class KeyExchangeRSAPKCSFunctionEvaluation:
249+
"""
250+
Results of support for PKCS padding for RSA per NCSC 3.3.2.1.
251+
NCSC table 5
252+
"""
253+
254+
status: KexRSAPKCSStatus
255+
score: scoring.Score
256+
257+
247258
@dataclass(frozen=True)
248259
class KeyExchangeHashFunctionEvaluation:
249260
"""
250261
Results of "hash functions for key exchange" evaluation.
251-
NCSC table 5
262+
NCSC 3.3.5
252263
"""
253264

254265
status: KexHashFuncStatus

checks/tasks/tls/scans.py

Lines changed: 48 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@
6161
ZeroRttStatus,
6262
KexHashFuncStatus,
6363
CipherOrderStatus,
64+
KexRSAPKCSStatus,
6465
)
6566
from checks.resolver import dns_resolve_tlsa, DNSSECStatus, dns_resolve_a
6667
from checks.tasks.tls import TLSException
@@ -71,6 +72,7 @@
7172
KeyExchangeHashFunctionEvaluation,
7273
TLSCipherOrderEvaluation,
7374
TLSOCSPEvaluation,
75+
KeyExchangeRSAPKCSFunctionEvaluation,
7476
)
7577
from checks.tasks.tls.tls_constants import (
7678
CERT_SIGALG_GOOD,
@@ -82,6 +84,7 @@
8284
CERT_RSA_MIN_PHASE_OUT_KEY_SIZE,
8385
SIGNATURE_ALGORITHMS_BAD_HASH,
8486
SIGNATURE_ALGORITHMS_PHASE_OUT_HASH,
87+
SIGNATURE_ALGORITHMS_RSA_PKCS,
8588
)
8689
from internetnl import log
8790

@@ -604,24 +607,21 @@ def check_mail_tls(result: ServerScanResult, all_suites: List[CipherSuitesScanAt
604607
protocol_evaluation = TLSProtocolEvaluation.from_protocols_accepted(prots_accepted)
605608
fs_evaluation = TLSForwardSecrecyParameterEvaluation.from_ciphers_accepted(ciphers_accepted)
606609
cipher_evaluation = TLSCipherEvaluation.from_ciphers_accepted(ciphers_accepted)
610+
611+
server_conn_info = ServerConnectivityInfo(
612+
server_location=result.server_location,
613+
network_configuration=result.network_configuration,
614+
tls_probing_result=result.connectivity_result,
615+
)
607616
cipher_order_evaluation = test_cipher_order(
608-
ServerConnectivityInfo(
609-
server_location=result.server_location,
610-
network_configuration=result.network_configuration,
611-
tls_probing_result=result.connectivity_result,
612-
),
617+
server_conn_info,
613618
prots_accepted,
614619
cipher_evaluation,
615620
)
616-
cert_results = cert_checks(result.server_location.hostname, ChecksMode.MAIL)
621+
key_exchange_rsa_pkcs_evaluation = test_key_exchange_rsa_pkcs(server_conn_info)
622+
key_exchange_hash_evaluation = test_key_exchange_hash(server_conn_info)
617623

618-
key_exchange_hash_evaluation = test_key_exchange_hash(
619-
ServerConnectivityInfo(
620-
server_location=result.server_location,
621-
network_configuration=result.network_configuration,
622-
tls_probing_result=result.connectivity_result,
623-
),
624-
)
624+
cert_results = cert_checks(result.server_location.hostname, ChecksMode.MAIL)
625625

626626
# HACK for DANE-TA(2) and hostname mismatch!
627627
# Give a good hosmatch score if DANE-TA *is not* present.
@@ -677,6 +677,8 @@ def check_mail_tls(result: ServerScanResult, all_suites: List[CipherSuitesScanAt
677677
if result.scan_result.tls_1_3_early_data.result.supports_early_data
678678
else scoring.WEB_TLS_ZERO_RTT_GOOD
679679
),
680+
key_exchange_rsa_pkcs=key_exchange_rsa_pkcs_evaluation.status,
681+
key_exchange_rsa_pkcs_score=key_exchange_rsa_pkcs_evaluation.score,
680682
kex_hash_func=key_exchange_hash_evaluation.status,
681683
kex_hash_func_score=key_exchange_hash_evaluation.score,
682684
)
@@ -735,22 +737,19 @@ def check_web_tls(url, af_ip_pair=None, *args, **kwargs):
735737
protocol_evaluation = TLSProtocolEvaluation.from_protocols_accepted(supported_tls_versions)
736738
fs_evaluation = TLSForwardSecrecyParameterEvaluation.from_ciphers_accepted(ciphers_accepted)
737739
cipher_evaluation = TLSCipherEvaluation.from_ciphers_accepted(ciphers_accepted)
740+
741+
server_conn_info = ServerConnectivityInfo(
742+
server_location=result.server_location,
743+
network_configuration=result.network_configuration,
744+
tls_probing_result=result.connectivity_result,
745+
)
738746
cipher_order_evaluation = test_cipher_order(
739-
ServerConnectivityInfo(
740-
server_location=result.server_location,
741-
network_configuration=result.network_configuration,
742-
tls_probing_result=result.connectivity_result,
743-
),
747+
server_conn_info,
744748
supported_tls_versions,
745749
cipher_evaluation,
746750
)
747-
key_exchange_hash_evaluation = test_key_exchange_hash(
748-
ServerConnectivityInfo(
749-
server_location=result.server_location,
750-
network_configuration=result.network_configuration,
751-
tls_probing_result=result.connectivity_result,
752-
),
753-
)
751+
key_exchange_rsa_pkcs_evaluation = test_key_exchange_rsa_pkcs(server_conn_info)
752+
key_exchange_hash_evaluation = test_key_exchange_hash(server_conn_info)
754753

755754
ocsp_evaluation = TLSOCSPEvaluation.from_certificate_deployments(
756755
result.scan_result.certificate_info.result.certificate_deployments[0]
@@ -804,6 +803,8 @@ def check_web_tls(url, af_ip_pair=None, *args, **kwargs):
804803
),
805804
ocsp_stapling=ocsp_evaluation.status,
806805
ocsp_stapling_score=ocsp_evaluation.score,
806+
key_exchange_rsa_pkcs=key_exchange_rsa_pkcs_evaluation.status,
807+
key_exchange_rsa_pkcs_score=key_exchange_rsa_pkcs_evaluation.score,
807808
kex_hash_func=key_exchange_hash_evaluation.status,
808809
kex_hash_func_score=key_exchange_hash_evaluation.score,
809810
)
@@ -863,6 +864,27 @@ def raise_sslyze_errors(result: ServerScanResult) -> None:
863864
raise TLSException(str(last_error_trace))
864865

865866

867+
def test_key_exchange_rsa_pkcs(
868+
server_connectivity_info: ServerConnectivityInfo,
869+
) -> KeyExchangeRSAPKCSFunctionEvaluation:
870+
"""
871+
Test key exchange for RSA PKCS support per NCSC 3.3.2.1.
872+
See also RFC8446 1.3 and 4.2.3, RFC 5246 7.4.1.4.1.
873+
"""
874+
rsa_pkcs_result = _test_connection_with_limited_sigalgs(server_connectivity_info, SIGNATURE_ALGORITHMS_RSA_PKCS)
875+
if rsa_pkcs_result:
876+
log.info(f"RSA-PKCS key exchange check: negotiated bad sigalg ({rsa_pkcs_result})")
877+
return KeyExchangeRSAPKCSFunctionEvaluation(
878+
status=KexRSAPKCSStatus.bad,
879+
score=scoring.WEB_TLS_KEX_RSA_PKCS_BAD,
880+
)
881+
882+
return KeyExchangeRSAPKCSFunctionEvaluation(
883+
status=KexRSAPKCSStatus.good,
884+
score=scoring.WEB_TLS_KEX_RSA_PKCS_GOOD,
885+
)
886+
887+
866888
def test_key_exchange_hash(
867889
server_connectivity_info: ServerConnectivityInfo,
868890
) -> KeyExchangeHashFunctionEvaluation:
@@ -873,7 +895,7 @@ def test_key_exchange_hash(
873895
"""
874896
bad_hash_result = _test_connection_with_limited_sigalgs(server_connectivity_info, SIGNATURE_ALGORITHMS_BAD_HASH)
875897
if bad_hash_result:
876-
log.info(f"SHA2 key exchange check: negotiated bad hash ({bad_hash_result})")
898+
log.info(f"SHA2 key exchange check: negotiated bad sigalg ({bad_hash_result})")
877899
return KeyExchangeHashFunctionEvaluation(
878900
status=KexHashFuncStatus.bad,
879901
score=scoring.WEB_TLS_KEX_HASH_FUNC_BAD,

0 commit comments

Comments
 (0)