/* * Copyright (C) 2000-2012 Free Software Foundation, Inc. * * This file is part of GnuTLS. * * GnuTLS is free software: you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * GnuTLS is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see * . */ #include #include #include #ifndef _WIN32 #include #include #else #include #endif #include #include #include #include #include extern gnutls_srp_client_credentials_t srp_cred; extern gnutls_anon_client_credentials_t anon_cred; extern gnutls_certificate_credentials_t xcred; extern int verbose; int tls1_ok = 0; int ssl3_ok = 0; int tls1_1_ok = 0; int tls1_2_ok = 0; /* keep session info */ static char *session_data = NULL; static char session_id[32]; static size_t session_data_size = 0, session_id_size = 0; static int sfree = 0; static int handshake_output = 0; static int do_handshake (gnutls_session_t session) { int ret, alert; do { ret = gnutls_handshake (session); } while (ret == GNUTLS_E_INTERRUPTED || ret == GNUTLS_E_AGAIN); handshake_output = ret; if (ret < 0 && verbose > 1) { if (ret == GNUTLS_E_WARNING_ALERT_RECEIVED || ret == GNUTLS_E_FATAL_ALERT_RECEIVED) { alert = gnutls_alert_get (session); printf ("\n"); printf ("*** Received alert [%d]: %s\n", alert, gnutls_alert_get_name (alert)); } } if (ret < 0) return TEST_FAILED; gnutls_session_get_data (session, NULL, &session_data_size); if (sfree != 0) { free (session_data); sfree = 0; } session_data = malloc (session_data_size); sfree = 1; if (session_data == NULL) { fprintf (stderr, "Memory error\n"); exit (1); } gnutls_session_get_data (session, session_data, &session_data_size); session_id_size = sizeof (session_id); gnutls_session_get_id (session, session_id, &session_id_size); return TEST_SUCCEED; } char protocol_str[] = "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0"; char protocol_all_str[] = "+VERS-TLS1.2:+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0"; char prio_str[512] = ""; #define ALL_CIPHERS "+3DES-CBC:+ARCFOUR-128:+ARCFOUR-40" #define BLOCK_CIPHERS "+3DES-CBC:+AES-128-CBC" #define ALL_COMP "+COMP-NULL" #define ALL_MACS "+SHA1:+MD5" #define ALL_CERTTYPES "+CTYPE-X509" #define ALL_KX "+RSA:+DHE-RSA:+DHE-DSS:+ANON-DH:+RSA-EXPORT:+ECDHE-RSA:+ECDHE-ECDSA:+ANON-ECDH" #define INIT_STR "NONE:" char rest[128] = "%UNSAFE_RENEGOTIATION:+SIGN-ALL:+CURVE-ALL"; static inline void _gnutls_priority_set_direct (gnutls_session_t session, const char *str) { const char *err; int ret = gnutls_priority_set_direct (session, str, &err); if (ret < 0) { fprintf (stderr, "Error with string %s\n", str); fprintf (stderr, "Error at %s: %s\n", err, gnutls_strerror (ret)); exit (1); } } test_code_t test_server (gnutls_session_t session) { int ret, i = 0; char buf[5 * 1024]; char *p; const char snd_buf[] = "GET / HTTP/1.0\n\n"; if (verbose == 0) return TEST_UNSURE; buf[sizeof (buf) - 1] = 0; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":" "%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret != TEST_SUCCEED) return TEST_FAILED; gnutls_record_send (session, snd_buf, sizeof (snd_buf) - 1); ret = gnutls_record_recv (session, buf, sizeof (buf) - 1); if (ret < 0) return TEST_FAILED; p = strstr (buf, "Server:"); if (p != NULL) p = strchr (p, ':'); if (p != NULL) { p++; while (*p != 0 && *p != '\r' && *p != '\n') { putc (*p, stdout); p++; i++; if (i > 128) break; } } return TEST_SUCCEED; } static int export_true = 0; static gnutls_datum_t exp = { NULL, 0 }, mod = { NULL, 0}; #ifdef ENABLE_RSA_EXPORT test_code_t test_export (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+ARCFOUR-40:+RSA-EXPORT:" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_SUCCEED) { export_true = 1; gnutls_rsa_export_get_pubkey (session, &exp, &mod); } return ret; } test_code_t test_export_info (gnutls_session_t session) { int ret2, ret; gnutls_datum_t exp2, mod2; const char *print; if (verbose == 0 || export_true == 0) return TEST_IGNORE; sprintf (prio_str, INIT_STR "+ARCFOUR-40:+RSA-EXPORT:" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_SUCCEED) { ret2 = gnutls_rsa_export_get_pubkey (session, &exp2, &mod2); if (ret2 >= 0) { printf ("\n"); print = raw_to_string (exp2.data, exp2.size); if (print) printf (" Exponent [%d bits]: %s\n", exp2.size * 8, print); print = raw_to_string (mod2.data, mod2.size); if (print) printf (" Modulus [%d bits]: %s\n", mod2.size * 8, print); if (mod2.size != mod.size || exp2.size != exp.size || memcmp (mod2.data, mod.data, mod.size) != 0 || memcmp (exp2.data, exp.data, exp.size) != 0) { printf (" (server uses different public keys per connection)\n"); } } } return ret; } #endif static gnutls_datum_t pubkey = { NULL, 0 }; static gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID; test_code_t test_dhe (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":+DHE-RSA:+DHE-DSS:%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); gnutls_dh_get_pubkey (session, &pubkey); return ret; } test_code_t test_ecdhe (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":+ECDHE-RSA:+ECDHE-ECDSA:+CURVE-ALL:%s", protocol_all_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); curve = gnutls_ecc_curve_get(session); return ret; } test_code_t test_safe_renegotiation (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%%SAFE_RENEGOTIATION", protocol_str); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_safe_renegotiation_scsv (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":+VERS-SSL3.0:" ALL_MACS ":" ALL_KX ":%%SAFE_RENEGOTIATION"); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_dhe_group (gnutls_session_t session) { int ret, ret2; gnutls_datum_t gen, prime, pubkey2; const char *print; if (verbose == 0 || pubkey.data == NULL) return TEST_IGNORE; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":+DHE-RSA:+DHE-DSS:%s", protocol_str, rest); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); ret2 = gnutls_dh_get_group (session, &gen, &prime); if (ret2 >= 0) { printf ("\n"); print = raw_to_string (gen.data, gen.size); if (print) printf (" Generator [%d bits]: %s\n", gen.size * 8, print); print = raw_to_string (prime.data, prime.size); if (print) printf (" Prime [%d bits]: %s\n", prime.size * 8, print); gnutls_dh_get_pubkey (session, &pubkey2); print = raw_to_string (pubkey2.data, pubkey2.size); if (print) printf (" Pubkey [%d bits]: %s\n", pubkey2.size * 8, print); if (pubkey2.data && pubkey2.size == pubkey.size && memcmp (pubkey.data, pubkey2.data, pubkey.size) == 0) { printf (" (public key seems to be static among sessions)\n"); } } return ret; } test_code_t test_ecdhe_curve (gnutls_session_t session) { if (curve == GNUTLS_ECC_CURVE_INVALID) return TEST_IGNORE; printf ("\n Curve %s", gnutls_ecc_curve_get_name(curve)); return TEST_SUCCEED; } test_code_t test_ssl3 (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":+VERS-SSL3.0:" ALL_MACS ":" ALL_KX ":%s", rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_SUCCEED) ssl3_ok = 1; return ret; } static int alrm = 0; static void got_alarm (int k) { alrm = 1; } test_code_t test_bye (gnutls_session_t session) { int ret; char data[20]; int secs = 6; #ifndef _WIN32 int old; signal (SIGALRM, got_alarm); #endif sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) return ret; ret = gnutls_bye (session, GNUTLS_SHUT_WR); if (ret < 0) return TEST_FAILED; #ifndef _WIN32 old = siginterrupt (SIGALRM, 1); alarm (secs); #else setsockopt ((int) gnutls_transport_get_ptr (session), SOL_SOCKET, SO_RCVTIMEO, (char *) &secs, sizeof (int)); #endif do { ret = gnutls_record_recv (session, data, sizeof (data)); } while (ret > 0); #ifndef _WIN32 siginterrupt (SIGALRM, old); #else if (WSAGetLastError () == WSAETIMEDOUT || WSAGetLastError () == WSAECONNABORTED) alrm = 1; #endif if (ret == 0) return TEST_SUCCEED; if (alrm == 0) return TEST_UNSURE; return TEST_FAILED; } test_code_t test_aes (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+AES-128-CBC:" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_aes_gcm (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+AES-128-GCM:+AES-256-GCM:+AEAD:" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_all_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_camellia (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+CAMELLIA-128-CBC:" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_openpgp1 (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":+CTYPE-OPENPGP:%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) return ret; if (gnutls_certificate_type_get (session) == GNUTLS_CRT_OPENPGP) return TEST_SUCCEED; return TEST_FAILED; } test_code_t test_unknown_ciphersuites (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+AES-128-CBC:" ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_md5 (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+AES-128-CBC:" ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:+MD5:" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } #ifdef HAVE_LIBZ test_code_t test_zlib (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":+COMP-DEFLATE:" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } #endif test_code_t test_sha (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+AES-128-CBC:" ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:+SHA1:" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_sha256 (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+AES-128-CBC:" ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:+SHA256:" ALL_KX ":%s", protocol_all_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_3des (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+3DES-CBC:" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_arcfour (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+ARCFOUR-128:" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_arcfour_40 (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR "+ARCFOUR-40:" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" "+RSA-EXPORT" ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); return ret; } test_code_t test_tls1 (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":+VERS-TLS1.0:" ALL_MACS ":" ALL_KX ":%s", rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_SUCCEED) tls1_ok = 1; return ret; } test_code_t test_record_padding (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR BLOCK_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":+VERS-TLS1.0:" ALL_MACS ":" ALL_KX ":%s", rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_SUCCEED) { tls1_ok = 1; } else { strcat (rest, ":%COMPAT"); } return ret; } test_code_t test_tls1_2 (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":+VERS-TLS1.2:" ALL_MACS ":" ALL_KX ":%s", rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_SUCCEED) tls1_2_ok = 1; return ret; } test_code_t test_tls1_1 (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":+VERS-TLS1.1:" ALL_MACS ":" ALL_KX ":%s", rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_SUCCEED) tls1_1_ok = 1; return ret; } test_code_t test_tls1_1_fallback (gnutls_session_t session) { int ret; if (tls1_1_ok) return TEST_IGNORE; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":+VERS-TLS1.1:+VERS-TLS1.0:+VERS-SSL3.0:" ALL_MACS ":" ALL_KX ":%s", rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret != TEST_SUCCEED) return TEST_FAILED; if (gnutls_protocol_get_version (session) == GNUTLS_TLS1) return TEST_SUCCEED; else if (gnutls_protocol_get_version (session) == GNUTLS_SSL3) return TEST_UNSURE; return TEST_FAILED; } /* Advertize both TLS 1.0 and SSL 3.0. If the connection fails, * but the previous SSL 3.0 test succeeded then disable TLS 1.0. */ test_code_t test_tls_disable0 (gnutls_session_t session) { int ret; if (tls1_ok != 0) return TEST_IGNORE; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) { /* disable TLS 1.0 */ if (ssl3_ok != 0) { strcpy (protocol_str, "+VERS-SSL3.0"); } } return ret; } test_code_t test_tls_disable1 (gnutls_session_t session) { int ret; if (tls1_1_ok != 0) return TEST_IGNORE; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) { protocol_str[0] = 0; /* disable TLS 1.1 */ if (tls1_ok != 0) { strcat (protocol_str, "+VERS-TLS1.0"); } if (ssl3_ok != 0) { if (protocol_str[0] != 0) strcat (protocol_str, ":+VERS-SSL3.0"); else strcat (protocol_str, "+VERS-SSL3.0"); } } return ret; } test_code_t test_tls_disable2 (gnutls_session_t session) { int ret; if (tls1_2_ok != 0) return TEST_IGNORE; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) { /* disable TLS 1.2 */ protocol_str[0] = 0; if (tls1_1_ok != 0) { strcat (protocol_str, "+VERS-TLS1.1"); } if (tls1_ok != 0) { if (protocol_str[0] != 0) strcat (protocol_str, ":+VERS-TLS1.0"); else strcat (protocol_str, "+VERS-TLS1.0"); } if (ssl3_ok != 0) { if (protocol_str[0] != 0) strcat (protocol_str, ":+VERS-SSL3.0"); else strcat (protocol_str, "+VERS-SSL3.0"); } } return ret; } test_code_t test_rsa_pms (gnutls_session_t session) { int ret; /* here we enable both SSL 3.0 and TLS 1.0 * and try to connect and use rsa authentication. * If the server is old, buggy and only supports * SSL 3.0 then the handshake will fail. */ sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":+RSA:%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) return TEST_FAILED; if (gnutls_protocol_get_version (session) == GNUTLS_TLS1) return TEST_SUCCEED; return TEST_UNSURE; } test_code_t test_max_record_size (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_record_set_max_size (session, 512); ret = do_handshake (session); if (ret == TEST_FAILED) return ret; ret = gnutls_record_get_max_size (session); if (ret == 512) return TEST_SUCCEED; return TEST_FAILED; } test_code_t test_hello_extension (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_record_set_max_size (session, 4096); ret = do_handshake (session); return ret; } test_code_t test_heartbeat_extension (gnutls_session_t session) { sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_record_set_max_size (session, 4096); gnutls_heartbeat_enable (session, GNUTLS_HB_PEER_ALLOWED_TO_SEND); do_handshake (session); switch (gnutls_heartbeat_allowed (session, 1)) { case 1: return TEST_SUCCEED; case 0: return TEST_FAILED; default: return TEST_UNSURE; } } test_code_t test_small_records (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_record_set_max_size (session, 512); ret = do_handshake (session); return ret; } void _gnutls_record_set_default_version (gnutls_session_t session, unsigned char major, unsigned char minor); test_code_t test_version_rollback (gnutls_session_t session) { int ret; if (tls1_ok == 0) return TEST_IGNORE; /* here we enable both SSL 3.0 and TLS 1.0 * and we connect using a 3.1 client hello version, * and a 3.0 record version. Some implementations * are buggy (and vulnerable to man in the middle * attacks which allow a version downgrade) and this * connection will fail. */ sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); _gnutls_record_set_default_version (session, 3, 0); ret = do_handshake (session); if (ret != TEST_SUCCEED) return ret; if (tls1_ok != 0 && gnutls_protocol_get_version (session) == GNUTLS_SSL3) return TEST_FAILED; return TEST_SUCCEED; } /* See if the server tolerates out of bounds * record layer versions in the first client hello * message. */ test_code_t test_version_oob (gnutls_session_t session) { int ret; /* here we enable both SSL 3.0 and TLS 1.0 * and we connect using a 5.5 record version. */ sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); _gnutls_record_set_default_version (session, 5, 5); ret = do_handshake (session); return ret; } void _gnutls_rsa_pms_set_version (gnutls_session_t session, unsigned char major, unsigned char minor); test_code_t test_rsa_pms_version_check (gnutls_session_t session) { int ret; /* here we use an arbitary version in the RSA PMS * to see whether to server will check this version. * * A normal server would abort this handshake. */ sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); _gnutls_rsa_pms_set_version (session, 5, 5); /* use SSL 5.5 version */ ret = do_handshake (session); return ret; } #ifdef ENABLE_ANON test_code_t test_anonymous (gnutls_session_t session) { int ret; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":+ANON-DH:+ANON-ECDH:+CURVE-ALL:%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_ANON, anon_cred); ret = do_handshake (session); if (ret == TEST_SUCCEED) gnutls_dh_get_pubkey (session, &pubkey); return ret; } #endif test_code_t test_session_resume2 (gnutls_session_t session) { int ret; char tmp_session_id[32]; size_t tmp_session_id_size; if (session == NULL) return TEST_IGNORE; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_credentials_set (session, GNUTLS_CRD_ANON, anon_cred); gnutls_session_set_data (session, session_data, session_data_size); memcpy (tmp_session_id, session_id, session_id_size); tmp_session_id_size = session_id_size; ret = do_handshake (session); if (ret == TEST_FAILED) return ret; /* check if we actually resumed the previous session */ session_id_size = sizeof (session_id); gnutls_session_get_id (session, session_id, &session_id_size); if (session_id_size == 0) return TEST_FAILED; if (gnutls_session_is_resumed (session)) return TEST_SUCCEED; if (tmp_session_id_size == session_id_size && memcmp (tmp_session_id, session_id, tmp_session_id_size) == 0) return TEST_SUCCEED; else return TEST_FAILED; } extern char *hostname; test_code_t test_certificate (gnutls_session_t session) { int ret; if (verbose == 0) return TEST_IGNORE; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); ret = do_handshake (session); if (ret == TEST_FAILED) return ret; printf ("\n"); print_cert_info (session, GNUTLS_CRT_PRINT_FULL, verbose); return TEST_SUCCEED; } /* A callback function to be used at the certificate selection time. */ static int cert_callback (gnutls_session_t session, const gnutls_datum_t * req_ca_rdn, int nreqs, const gnutls_pk_algorithm_t * sign_algos, int sign_algos_length, gnutls_retr2_st * st) { char issuer_dn[256]; int i, ret; size_t len; if (verbose == 0) return -1; /* Print the server's trusted CAs */ printf ("\n"); if (nreqs > 0) printf ("- Server's trusted authorities:\n"); else printf ("- Server did not send us any trusted authorities names.\n"); /* print the names (if any) */ for (i = 0; i < nreqs; i++) { len = sizeof (issuer_dn); ret = gnutls_x509_rdn_get (&req_ca_rdn[i], issuer_dn, &len); if (ret >= 0) { printf (" [%d]: ", i); printf ("%s\n", issuer_dn); } } return -1; } /* Prints the trusted server's CAs. This is only * if the server sends a certificate request packet. */ test_code_t test_server_cas (gnutls_session_t session) { int ret; if (verbose == 0) return TEST_IGNORE; sprintf (prio_str, INIT_STR ALL_CIPHERS ":" ALL_COMP ":" ALL_CERTTYPES ":%s:" ALL_MACS ":" ALL_KX ":%s", protocol_str, rest); _gnutls_priority_set_direct (session, prio_str); gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, xcred); gnutls_certificate_set_retrieve_function (xcred, cert_callback); ret = do_handshake (session); gnutls_certificate_set_retrieve_function (xcred, NULL); if (ret == TEST_FAILED) return ret; return TEST_SUCCEED; }