diff options
-rw-r--r-- | lib/alert.c | 6 | ||||
-rw-r--r-- | lib/errors.c | 2 | ||||
-rw-r--r-- | lib/ext/key_share.c | 1 | ||||
-rw-r--r-- | lib/gnutls_int.h | 7 | ||||
-rw-r--r-- | lib/handshake.c | 29 | ||||
-rw-r--r-- | lib/includes/gnutls/gnutls.h.in | 9 | ||||
-rw-r--r-- | tests/suite/tls-fuzzer/gnutls-nocert-tls13.json | 31 | ||||
-rw-r--r-- | tests/suite/tls-fuzzer/gnutls-nocert.json | 43 | ||||
-rwxr-xr-x | tests/suite/tls-fuzzer/tls-fuzzer-nocert-tls13.sh | 2 | ||||
m--------- | tests/suite/tls-fuzzer/tlsfuzzer | 0 | ||||
m--------- | tests/suite/tls-fuzzer/tlslite-ng | 0 |
11 files changed, 115 insertions, 15 deletions
diff --git a/lib/alert.c b/lib/alert.c index 9b10123345..b9aa7bd9ba 100644 --- a/lib/alert.c +++ b/lib/alert.c @@ -79,6 +79,8 @@ static const gnutls_alert_entry sup_alerts[] = { N_("The server name sent was not recognized")), ALERT_ENTRY(GNUTLS_A_UNKNOWN_PSK_IDENTITY, N_("The SRP/PSK username is missing or not known")), + ALERT_ENTRY(GNUTLS_A_MISSING_EXTENSION, + N_("An extension was expected but was not seen")), ALERT_ENTRY(GNUTLS_A_NO_APPLICATION_PROTOCOL, N_ ("No supported application protocol could be negotiated")), @@ -262,6 +264,10 @@ int gnutls_error_to_alert(int err, int *level) ret = GNUTLS_A_UNSUPPORTED_EXTENSION; _level = GNUTLS_AL_FATAL; break; + case GNUTLS_E_MISSING_EXTENSION: + ret = GNUTLS_A_MISSING_EXTENSION; + _level = GNUTLS_AL_FATAL; + break; case GNUTLS_E_USER_ERROR: ret = GNUTLS_A_USER_CANCELED; _level = GNUTLS_AL_FATAL; diff --git a/lib/errors.c b/lib/errors.c index fb6b54b4b0..e579f46852 100644 --- a/lib/errors.c +++ b/lib/errors.c @@ -81,6 +81,8 @@ static const gnutls_error_entry error_entries[] = { GNUTLS_E_INAPPROPRIATE_FALLBACK), ERROR_ENTRY(N_("An illegal TLS extension was received."), GNUTLS_E_RECEIVED_ILLEGAL_EXTENSION), + ERROR_ENTRY(N_("An required TLS extension was received."), + GNUTLS_E_MISSING_EXTENSION), ERROR_ENTRY(N_("A TLS fatal alert has been received."), GNUTLS_E_FATAL_ALERT_RECEIVED), ERROR_ENTRY(N_("An unexpected TLS packet was received."), diff --git a/lib/ext/key_share.c b/lib/ext/key_share.c index c5b104f9ac..6a9e6513a9 100644 --- a/lib/ext/key_share.c +++ b/lib/ext/key_share.c @@ -575,6 +575,7 @@ key_share_recv_params(gnutls_session_t session, return gnutls_assert_val(GNUTLS_E_NO_COMMON_KEY_SHARE); } + session->internals.hsk_flags |= HSK_KEY_SHARE_RECEIVED; } else { /* Client */ ver = get_version(session); if (unlikely(ver == NULL || ver->key_shares == 0)) diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 3fb4ccb80b..f32eba181d 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -1332,9 +1332,12 @@ typedef struct { #define HSK_PSK_KE_MODE_DHE_PSK (1<<14) /* server: whether PSK with DH is selected * client: whether PSK with DH is allowed */ -#define HSK_PSK_SELECTED (1<<15) +#define HSK_PSK_SELECTED (1<<15) /* server: whether PSK was selected, either for resumption or not; + * on resumption session->internals.resumed will be set as well. + * client: the same */ #define HSK_KEY_SHARE_SENT (1<<16) /* server: key share was sent to client */ -#define HSK_KEY_SHARE_RECEIVED (1<<17) /* client: key share was received */ +#define HSK_KEY_SHARE_RECEIVED (1<<17) /* client: key share was received + * server: key share was received and accepted */ #define HSK_TLS13_TICKET_SENT (1<<18) /* client: sent a ticket under TLS1.3; * server: a ticket was sent to client. */ diff --git a/lib/handshake.c b/lib/handshake.c index 7db134a638..841c88385d 100644 --- a/lib/handshake.c +++ b/lib/handshake.c @@ -539,23 +539,40 @@ _gnutls_user_hello_func(gnutls_session_t session, return sret; } +/* Associates the right credential types for the session, and + * performs sanity checks. */ static int set_auth_types(gnutls_session_t session) { const version_entry_st *ver = get_version(session); gnutls_kx_algorithm_t kx; - kx = session->security_parameters.cs->kx_algorithm; - if (kx == 0 && ver->tls13_sem) { - /* if we are resuming then the KX seen doesn't match the original */ + /* sanity check: + * we see TLS1.3 negotiated but no key share was sent */ + if (ver->tls13_sem) { + if (unlikely(!(session->internals.hsk_flags & HSK_PSK_KE_MODE_PSK) && + !(session->internals.hsk_flags & HSK_KEY_SHARE_RECEIVED))) { + return gnutls_assert_val(GNUTLS_E_MISSING_EXTENSION); + } + + /* Under TLS1.3 this returns a KX which matches the negotiated + * groups from the key shares; if we are resuming then the KX seen + * here doesn't match the original session. */ if (session->internals.resumed == RESUME_FALSE) kx = gnutls_kx_get(session); + else + kx = GNUTLS_KX_UNKNOWN; + } else { + /* TLS1.2 or earlier, kx is associated with ciphersuite */ + kx = session->security_parameters.cs->kx_algorithm; } - if (kx) { + if (kx != GNUTLS_KX_UNKNOWN) { session->security_parameters.server_auth_type = _gnutls_map_kx_get_cred(kx, 1); session->security_parameters.client_auth_type = _gnutls_map_kx_get_cred(kx, 0); - } else if (session->internals.resumed == RESUME_FALSE) { - return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR); + } else if (unlikely(session->internals.resumed == RESUME_FALSE)) { + /* Here we can only arrive if something we received + * prevented the session from completing. */ + return gnutls_assert_val(GNUTLS_E_ILLEGAL_PARAMETER); } return 0; diff --git a/lib/includes/gnutls/gnutls.h.in b/lib/includes/gnutls/gnutls.h.in index 01cf9a880e..b4903bb97c 100644 --- a/lib/includes/gnutls/gnutls.h.in +++ b/lib/includes/gnutls/gnutls.h.in @@ -498,14 +498,15 @@ typedef enum { * @GNUTLS_A_EXPORT_RESTRICTION: Export restriction. * @GNUTLS_A_PROTOCOL_VERSION: Error in protocol version. * @GNUTLS_A_INSUFFICIENT_SECURITY: Insufficient security. - * @GNUTLS_A_USER_CANCELED: User canceled. * @GNUTLS_A_INTERNAL_ERROR: Internal error. * @GNUTLS_A_INAPPROPRIATE_FALLBACK: Inappropriate fallback, + * @GNUTLS_A_USER_CANCELED: User canceled. * @GNUTLS_A_NO_RENEGOTIATION: No renegotiation is allowed. - * @GNUTLS_A_CERTIFICATE_UNOBTAINABLE: Could not retrieve the - * specified certificate. + * @GNUTLS_A_MISSING_EXTENSION: An extension was expected but was not seen * @GNUTLS_A_UNSUPPORTED_EXTENSION: An unsupported extension was * sent. + * @GNUTLS_A_CERTIFICATE_UNOBTAINABLE: Could not retrieve the + * specified certificate. * @GNUTLS_A_UNRECOGNIZED_NAME: The server name sent was not * recognized. * @GNUTLS_A_UNKNOWN_PSK_IDENTITY: The SRP/PSK username is missing @@ -541,6 +542,7 @@ typedef enum { GNUTLS_A_INAPPROPRIATE_FALLBACK = 86, GNUTLS_A_USER_CANCELED = 90, GNUTLS_A_NO_RENEGOTIATION = 100, + GNUTLS_A_MISSING_EXTENSION = 109, GNUTLS_A_UNSUPPORTED_EXTENSION = 110, GNUTLS_A_CERTIFICATE_UNOBTAINABLE = 111, GNUTLS_A_UNRECOGNIZED_NAME = 112, @@ -3230,6 +3232,7 @@ void gnutls_fips140_set_mode(gnutls_fips_mode_t mode, unsigned flags); #define GNUTLS_E_REAUTH_REQUEST -424 #define GNUTLS_E_TOO_MANY_MATCHES -425 #define GNUTLS_E_CRL_VERIFICATION_ERROR -426 +#define GNUTLS_E_MISSING_EXTENSION -427 #define GNUTLS_E_UNIMPLEMENTED_FEATURE -1250 diff --git a/tests/suite/tls-fuzzer/gnutls-nocert-tls13.json b/tests/suite/tls-fuzzer/gnutls-nocert-tls13.json index 7b01c25ae8..d0d142e7a2 100644 --- a/tests/suite/tls-fuzzer/gnutls-nocert-tls13.json +++ b/tests/suite/tls-fuzzer/gnutls-nocert-tls13.json @@ -14,10 +14,26 @@ "tests" : [ {"name" : "test-tls13-0rtt-garbage.py", "arguments": ["-p", "@PORT@"]}, + {"name" : "test-tls13-crfg-curves.py", + "comment": "We do not support x448", + "arguments": ["-p", "@PORT@", + "-e", "empty x448 key share", + "-e", "sanity x448 with compression ansiX962_compressed_char2", + "-e", "sanity x448 with compression ansiX962_compressed_prime", + "-e", "sanity x448 with compression uncompressed", + "-e", "too big x448 key share", + "-e", "too small x448 key share", + "-e", "x448 key share of \"1\"", + "-e", "all zero x448 key share"]}, {"name" : "test-tls13-conversation.py", "arguments": ["-p", "@PORT@"]}, {"name" : "test-tls13-count-tickets.py", "arguments": ["-p", "@PORT@", "-t", "1"]}, + {"name" : "test-tls13-dhe-shared-secret-padding.py", + "comment": "We do not support x448", + "arguments": ["-p", "@PORT@", + "-e", "TLS 1.3 with x448", + "-n", "5"]}, {"name" : "test-tls13-empty-alert.py", "arguments": ["-p", "@PORT@"]}, {"name" : "test-tls13-ffdhe-sanity.py", @@ -29,6 +45,10 @@ "-e", "padding - cipher TLS_AES_256_GCM_SHA384, pad_byte 0, pad_left 0, pad_right 16777167"]}, {"name" : "test-tls13-hrr.py", "arguments": ["-p", "@PORT@"]}, + {"name" : "test-tls13-invalid-ciphers.py", + "arguments": ["-p", "@PORT@"]}, + {"name" : "test-tls13-keyshare-omitted.py", + "arguments": ["-p", "@PORT@"]}, {"name" : "test-tls13-legacy-version.py", "arguments": ["-p", "@PORT@"]}, {"name" : "test-tls13-nociphers.py", @@ -43,8 +63,17 @@ "arguments": ["-p", "@PORT@", "-b"]}, {"name" : "test-tls13-session-resumption.py", "arguments": ["-p", "@PORT@"]}, + {"name" : "test-tls13-serverhello-random.py", + "arguments": ["-p", "@PORT@", + "-e", "TLS 1.3 with x448"]}, {"name" : "test-tls13-signature-algorithms.py", - "arguments": ["-p", "@PORT@"]}, + "comment" : "gnutls doesn't handle well duplicated signature algorithms; this is not an issue in practice", + "arguments": ["-p", "@PORT@", + "-e", "213 invalid schemes", + "-e", "2353 invalid schemes", + "-e", "8130 invalid schemes", + "-e", "23752 invalid schemes", + "-e", "32715 invalid schemes"]}, {"name" : "test-tls13-unrecognised-groups.py", "arguments": ["-p", "@PORT@"]}, {"name" : "test-tls13-version-negotiation.py", diff --git a/tests/suite/tls-fuzzer/gnutls-nocert.json b/tests/suite/tls-fuzzer/gnutls-nocert.json index 6ddb6ebbe0..6e2a2ea47c 100644 --- a/tests/suite/tls-fuzzer/gnutls-nocert.json +++ b/tests/suite/tls-fuzzer/gnutls-nocert.json @@ -96,6 +96,21 @@ "-e", "Check if DHE preferred"]}, {"name" : "test-cve-2016-2107.py", "arguments" : ["-p", "@PORT@"] }, + {"name" : "test-dhe-key-share-random.py", + "comment": "This test assumes that record splitting is performed under SSLv3 and TLS1.0", + "arguments" : ["-p", "@PORT@", + "-e", "Protocol (3, 1)", + "-e", "Protocol (3, 1) in SSLv2 compatible ClientHello", + "-e", "Protocol (3, 0)", + "-e", "Protocol (3, 0) in SSLv2 compatible ClientHello"]}, + {"name" : "test-dhe-no-shared-secret-padding.py", + "comment": "This test assumes that record splitting is performed under SSLv3 and TLS1.0", + "arguments" : ["-p", "@PORT@", + "-e", "Protocol (3, 1)", + "-e", "Protocol (3, 1) in SSLv2 compatible ClientHello", + "-e", "Protocol (3, 0)", + "-e", "Protocol (3, 0) in SSLv2 compatible ClientHello", + "-n", "4"]}, {"name" : "test-dhe-rsa-key-exchange.py", "arguments" : ["-p", "@PORT@"] }, {"name" : "test-dhe-rsa-key-exchange-signatures.py", @@ -111,10 +126,24 @@ "arguments" : ["-p", "@PORT@"] }, {"name" : "test-early-application-data.py", "arguments" : ["-p", "@PORT@"] }, + {"name" : "test-ecdhe-padded-shared-secret.py", + "comment": "This test assumes that record splitting is performed under SSLv3 and TLS1.0; we don't support x448", + "arguments" : ["-p", "@PORT@", + "-e", "Protocol (3, 0) in SSLv2 compatible ClientHello", + "-e", "Protocol (3, 1) in SSLv2 compatible ClientHello", + "-e", "Protocol (3, 2) with x448 group", + "-n", "4"]}, {"name" : "test-ecdhe-rsa-key-exchange.py", "arguments" : ["-p", "@PORT@"] }, {"name" : "test-ecdhe-rsa-key-exchange-with-bad-messages.py", "arguments" : ["-p", "@PORT@"] }, + {"name" : "test-ecdhe-rsa-key-share-random.py", + "comment": "This test assumes that record splitting is performed under SSLv3 and TLS1.0; we don't support x448", + "arguments" : ["-p", "@PORT@", + "-e", "Protocol (3, 0) in SSLv2 compatible ClientHello", + "-e", "Protocol (3, 1) in SSLv2 compatible ClientHello", + "-e", "Protocol (3, 2) with x448 group", + "-n", "4"]}, {"name" : "test-empty-extensions.py", "arguments" : ["-p", "@PORT@"] }, {"name" : "test-export-ciphers-rejected.py", @@ -203,11 +232,23 @@ "-e", "medium, maximum fragmentation: 1 fragment - 1024B extension"]}, {"name" : "test-sessionID-resumption.py", "arguments" : ["-p", "@PORT@"] }, + {"name" : "test-serverhello-random.py", + "comment": "This test assumes that record splitting is performed under SSLv3 and TLS1.0; we don't support x448", + "arguments" : ["-p", "@PORT@", + "-e", "Protocol (3, 0) in SSLv2 compatible ClientHello", + "-e", "Protocol (3, 1) in SSLv2 compatible ClientHello", + "-e", "Protocol (3, 2) with x448 group", + "-n", "4"]}, {"name" : "test-sig-algs.py", "arguments" : ["-p", "@PORT@"] }, {"name" : "test-signature-algorithms.py", - "comment" : "gnutls doesn't tolerate that much", + "comment" : "gnutls doesn't handle well duplicated sign algorithms; this is not an issue in practice", "arguments" : ["-p", "@PORT@", + "-e", "duplicated 202 non-rsa schemes", + "-e", "duplicated 2342 non-rsa schemes", + "-e", "duplicated 8119 non-rsa schemes", + "-e", "duplicated 23741 non-rsa schemes", + "-e", "duplicated 32748 non-rsa schemes", "-e", "tolerance max (32764) number of methods"] }, {"name" : "test-sslv2-connection.py", diff --git a/tests/suite/tls-fuzzer/tls-fuzzer-nocert-tls13.sh b/tests/suite/tls-fuzzer/tls-fuzzer-nocert-tls13.sh index aab37db5e2..1b9b0f1765 100755 --- a/tests/suite/tls-fuzzer/tls-fuzzer-nocert-tls13.sh +++ b/tests/suite/tls-fuzzer/tls-fuzzer-nocert-tls13.sh @@ -24,8 +24,6 @@ tls_fuzzer_prepare() { PRIORITY="NORMAL:-VERS-ALL:+VERS-TLS1.3:+VERS-TLS1.2:+VERS-TLS1.1" sed -e "s|@SERVER@|$SERV|g" -e "s/@PORT@/$PORT/g" -e "s/@PRIORITY@/$PRIORITY/g" ../gnutls-nocert-tls13.json >${TMPFILE} - -sed -i 's/(127, 28)/(3, 4)/g' ./tlslite/constants.py } . "${srcdir}/tls-fuzzer/tls-fuzzer-common.sh" diff --git a/tests/suite/tls-fuzzer/tlsfuzzer b/tests/suite/tls-fuzzer/tlsfuzzer -Subproject 01f44ce66c54193176dac7c9e87afd248c58c08 +Subproject 64f4a6e94c6cc1357fdb9fb36b8467456509df6 diff --git a/tests/suite/tls-fuzzer/tlslite-ng b/tests/suite/tls-fuzzer/tlslite-ng -Subproject bad2b98b2c382674f71aff617a9274e2a095951 +Subproject af466651a7795ac5a6cf54932d496ca8e79b49b |