]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
mem: instrument with ASan memory poisoning as well as valgrind
authorDaiki Ueno <ueno@gnu.org>
Sat, 7 Aug 2021 07:16:50 +0000 (09:16 +0200)
committerDaiki Ueno <ueno@gnu.org>
Mon, 9 Aug 2021 11:20:07 +0000 (13:20 +0200)
This makes it possible to catch undefined memory access in the more
lightweight CI runs.

Signed-off-by: Daiki Ueno <ueno@gnu.org>
configure.ac
devel/cppcheck.suppressions
lib/constate.c
lib/handshake.c
lib/kx.c
lib/mem.h
lib/state.c
lib/stek.c
tests/session-export-funcs.c

index 11ea91c822de12d85b4a1cee98e9e048c016ebd5..10b25e216d0b1885d5789d7768fe196415dbce13 100644 (file)
@@ -250,6 +250,7 @@ AS_IF([test "$ac_cv_search___atomic_load_4" = "none required" || test "$ac_cv_se
 dnl We use its presence to detect C11 threads
 AC_CHECK_HEADERS([threads.h])
 
+AC_CHECK_HEADERS([sanitizer/asan_interface.h])
 AC_CHECK_HEADERS([valgrind/memcheck.h])
 
 AC_ARG_ENABLE(padlock,
index c572747c3022fbc26a3da1b2698551925072d5b5..34c4d6bab05b6616050bbb22c9c2ef81b34134f3 100644 (file)
@@ -14,6 +14,3 @@ invalidLifetime:lib/pkcs11_privkey.c:602
 invalidLifetime:lib/pkcs11_privkey.c:603
 invalidLifetime:lib/pkcs11_privkey.c:604
 invalidLifetime:lib/pkcs11_privkey.c:606
-autoVariables:lib/stek.c:302
-autoVariables:lib/stek.c:306
-autoVariables:lib/stek.c:310
index ca520480aeb3cfbad5b0b80905fea9d2c797144d..b8437c7a68e4fb75b65d37f5437bcc2af9e1e386 100644 (file)
@@ -83,6 +83,8 @@ _gnutls_set_keys(gnutls_session_t session, record_parameters_st * params,
               session->security_parameters.client_random,
               GNUTLS_RANDOM_SIZE);
 
+       _gnutls_memory_mark_defined(session->security_parameters.master_secret,
+                                   GNUTLS_MASTER_SIZE);
 #ifdef ENABLE_SSL3
        if (get_num_version(session) == GNUTLS_SSL3) {  /* SSL 3 */
                ret =
@@ -99,8 +101,11 @@ _gnutls_set_keys(gnutls_session_t session, record_parameters_st * params,
                                rnd, 2 * GNUTLS_RANDOM_SIZE, block_size,
                                key_block);
 
-       if (ret < 0)
+       if (ret < 0) {
+               _gnutls_memory_mark_undefined(session->security_parameters.master_secret,
+                                             GNUTLS_MASTER_SIZE);
                return gnutls_assert_val(ret);
+       }
 
        _gnutls_hard_log("INT: KEY BLOCK[%d]: %s\n", block_size,
                         _gnutls_bin2hex(key_block, block_size, buf,
@@ -765,29 +770,6 @@ int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch, hs_stage_t
        return 0;
 }
 
-/* This copies the session values which apply to subsequent/resumed
- * sessions. Under TLS 1.3, these values are items which are not
- * negotiated on the subsequent session. */
-#define CPY_COMMON(tls13_sem) \
-       if (!tls13_sem) { \
-               dst->cs = src->cs; \
-               memcpy(dst->master_secret, src->master_secret, GNUTLS_MASTER_SIZE); \
-               memcpy(dst->client_random, src->client_random, GNUTLS_RANDOM_SIZE); \
-               memcpy(dst->server_random, src->server_random, GNUTLS_RANDOM_SIZE); \
-               dst->ext_master_secret = src->ext_master_secret; \
-               dst->etm = src->etm; \
-               dst->prf = src->prf; \
-               dst->grp = src->grp; \
-               dst->pversion = src->pversion; \
-       } \
-       memcpy(dst->session_id, src->session_id, GNUTLS_MAX_SESSION_ID_SIZE); \
-       dst->session_id_size = src->session_id_size; \
-       dst->timestamp = src->timestamp; \
-       dst->client_ctype = src->client_ctype; \
-       dst->server_ctype = src->server_ctype; \
-       dst->client_auth_type = src->client_auth_type; \
-       dst->server_auth_type = src->server_auth_type
-
 void _gnutls_set_resumed_parameters(gnutls_session_t session)
 {
        security_parameters_st *src =
@@ -795,7 +777,29 @@ void _gnutls_set_resumed_parameters(gnutls_session_t session)
        security_parameters_st *dst = &session->security_parameters;
        const version_entry_st *ver = get_version(session);
 
-       CPY_COMMON(ver->tls13_sem);
+       /* Under TLS 1.3, these values are items which are not
+        * negotiated on the subsequent session. */
+       if (!ver->tls13_sem) {
+               dst->cs = src->cs;
+               _gnutls_memory_mark_defined(dst->master_secret, GNUTLS_MASTER_SIZE);
+               memcpy(dst->master_secret, src->master_secret, GNUTLS_MASTER_SIZE);
+               _gnutls_memory_mark_defined(dst->client_random, GNUTLS_RANDOM_SIZE);
+               memcpy(dst->client_random, src->client_random, GNUTLS_RANDOM_SIZE);
+               _gnutls_memory_mark_defined(dst->server_random, GNUTLS_RANDOM_SIZE);
+               memcpy(dst->server_random, src->server_random, GNUTLS_RANDOM_SIZE);
+               dst->ext_master_secret = src->ext_master_secret;
+               dst->etm = src->etm;
+               dst->prf = src->prf;
+               dst->grp = src->grp;
+               dst->pversion = src->pversion;
+       }
+       memcpy(dst->session_id, src->session_id, GNUTLS_MAX_SESSION_ID_SIZE);
+       dst->session_id_size = src->session_id_size;
+       dst->timestamp = src->timestamp;
+       dst->client_ctype = src->client_ctype;
+       dst->server_ctype = src->server_ctype;
+       dst->client_auth_type = src->client_auth_type;
+       dst->server_auth_type = src->server_auth_type;
 
        if (!ver->tls13_sem &&
            !(session->internals.hsk_flags & HSK_RECORD_SIZE_LIMIT_NEGOTIATED)) {
index 1153eac85dc47509f04962f4a0468d33e023d959..565012d499198f04d9fa336ad5746354da385c3e 100644 (file)
@@ -58,9 +58,6 @@
 #include "tls13/early_data.h"
 #include "tls13/session_ticket.h"
 #include "locks.h"
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-#include <valgrind/memcheck.h>
-#endif
 
 static int check_if_null_comp_present(gnutls_session_t session,
                                             uint8_t * data, int datalen);
@@ -220,6 +217,8 @@ static int tls12_resume_copy_required_vals(gnutls_session_t session, unsigned ti
 
 void _gnutls_set_client_random(gnutls_session_t session, uint8_t * rnd)
 {
+       _gnutls_memory_mark_defined(session->security_parameters.client_random,
+                                   GNUTLS_RANDOM_SIZE);
        memcpy(session->security_parameters.client_random, rnd,
               GNUTLS_RANDOM_SIZE);
 }
@@ -231,24 +230,25 @@ int _gnutls_gen_client_random(gnutls_session_t session)
 
        /* no random given, we generate. */
        if (session->internals.sc_random_set != 0) {
+               _gnutls_memory_mark_defined(session->security_parameters.client_random,
+                                           GNUTLS_RANDOM_SIZE);
                memcpy(session->security_parameters.client_random,
                       session->internals.
                       resumed_security_parameters.client_random,
                       GNUTLS_RANDOM_SIZE);
        } else {
+               _gnutls_memory_mark_defined(session->security_parameters.client_random,
+                                           GNUTLS_RANDOM_SIZE);
                ret = gnutls_rnd(GNUTLS_RND_NONCE,
                        session->security_parameters.client_random,
                        GNUTLS_RANDOM_SIZE);
-               if (ret < 0)
+               if (ret < 0) {
+                       _gnutls_memory_mark_undefined(session->security_parameters.client_random,
+                                                     GNUTLS_RANDOM_SIZE);
                        return gnutls_assert_val(ret);
+               }
        }
 
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-       if (RUNNING_ON_VALGRIND)
-               VALGRIND_MAKE_MEM_DEFINED(session->security_parameters.client_random,
-                                         GNUTLS_RANDOM_SIZE);
-#endif
-
        return 0;
 }
 
@@ -257,6 +257,8 @@ int _gnutls_set_server_random(gnutls_session_t session, const version_entry_st *
 {
        const version_entry_st *max;
 
+       _gnutls_memory_mark_defined(session->security_parameters.server_random,
+                                   GNUTLS_RANDOM_SIZE);
        memcpy(session->security_parameters.server_random, rnd,
               GNUTLS_RANDOM_SIZE);
 
@@ -294,6 +296,8 @@ int _gnutls_gen_server_random(gnutls_session_t session, int version)
        const version_entry_st *max;
 
        if (session->internals.sc_random_set != 0) {
+               _gnutls_memory_mark_defined(session->security_parameters.server_random,
+                                           GNUTLS_RANDOM_SIZE);
                memcpy(session->security_parameters.server_random,
                       session->internals.
                       resumed_security_parameters.server_random,
@@ -305,6 +309,9 @@ int _gnutls_gen_server_random(gnutls_session_t session, int version)
        if (max == NULL)
                return gnutls_assert_val(GNUTLS_E_NO_CIPHER_SUITES);
 
+       _gnutls_memory_mark_defined(session->security_parameters.server_random,
+                                   GNUTLS_RANDOM_SIZE);
+
        if (!IS_DTLS(session) && max->id >= GNUTLS_TLS1_3 &&
            version <= GNUTLS_TLS1_2) {
                if (version == GNUTLS_TLS1_2) {
@@ -324,15 +331,11 @@ int _gnutls_gen_server_random(gnutls_session_t session, int version)
 
        if (ret < 0) {
                gnutls_assert();
+               _gnutls_memory_mark_undefined(session->security_parameters.server_random,
+                                             GNUTLS_RANDOM_SIZE);
                return ret;
        }
 
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-       if (RUNNING_ON_VALGRIND)
-               VALGRIND_MAKE_MEM_DEFINED(session->security_parameters.server_random,
-                                         GNUTLS_RANDOM_SIZE);
-#endif
-
        return 0;
 }
 
@@ -438,10 +441,17 @@ _gnutls_finished(gnutls_session_t session, int type, void *ret,
                mesg = CLIENT_MSG;
        }
 
-       return _gnutls_PRF(session,
-                          session->security_parameters.master_secret,
-                          GNUTLS_MASTER_SIZE, mesg, siz, concat, hash_len,
-                          12, ret);
+       _gnutls_memory_mark_defined(session->security_parameters.master_secret,
+                                   GNUTLS_MASTER_SIZE);
+       rc = _gnutls_PRF(session,
+                        session->security_parameters.master_secret,
+                        GNUTLS_MASTER_SIZE, mesg, siz, concat, hash_len,
+                        12, ret);
+       if (rc < 0) {
+               _gnutls_memory_mark_undefined(session->security_parameters.master_secret,
+                                             GNUTLS_MASTER_SIZE);
+       }
+       return rc;
 }
 
 
index 5d6420fd4bab6d361ab449426a7cd7cb999175a4..43a7e295188acaf8808a6f86e7157fce166d8386 100644 (file)
--- a/lib/kx.c
+++ b/lib/kx.c
@@ -209,6 +209,8 @@ generate_normal_master(gnutls_session_t session,
                       session->security_parameters.server_random,
                       GNUTLS_RANDOM_SIZE);
 
+               _gnutls_memory_mark_defined(session->security_parameters.master_secret,
+                                           GNUTLS_MASTER_SIZE);
 #ifdef ENABLE_SSL3
                if (get_num_version(session) == GNUTLS_SSL3) {
                        ret =
@@ -227,6 +229,9 @@ generate_normal_master(gnutls_session_t session,
                                        GNUTLS_MASTER_SIZE,
                                        session->security_parameters.
                                        master_secret);
+               if (ret < 0)
+                       _gnutls_memory_mark_undefined(session->security_parameters.master_secret,
+                                                     GNUTLS_MASTER_SIZE);
        } else {
                gnutls_datum_t shash = {NULL, 0};
 
@@ -239,6 +244,8 @@ generate_normal_master(gnutls_session_t session,
                        return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
 #endif
 
+               _gnutls_memory_mark_defined(session->security_parameters.master_secret,
+                                           GNUTLS_MASTER_SIZE);
                ret =
                    _gnutls_PRF(session, premaster->data, premaster->size,
                                EXT_MASTER_SECRET, EXT_MASTER_SECRET_SIZE,
@@ -246,6 +253,9 @@ generate_normal_master(gnutls_session_t session,
                                GNUTLS_MASTER_SIZE,
                                session->security_parameters.
                                master_secret);
+               if (ret < 0)
+                       _gnutls_memory_mark_undefined(session->security_parameters.master_secret,
+                                                     GNUTLS_MASTER_SIZE);
 
                gnutls_free(shash.data);
        }
index 10a8db742d082818c7c171e6fce61e949381fefb..3082aa82bfadb8d8e2bfac4b66239788d4631db6 100644 (file)
--- a/lib/mem.h
+++ b/lib/mem.h
 #ifndef GNUTLS_LIB_MEM_H
 #define GNUTLS_LIB_MEM_H
 
-#include <config.h>
+#include "config.h"
+
+#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
+#include <sanitizer/asan_interface.h>
+#endif
+
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+#include <valgrind/memcheck.h>
+#endif
 
 /* These realloc functions will return ptr if size==0, and will free
  * the ptr if the new allocation failed.
@@ -47,4 +55,28 @@ unsigned _gnutls_mem_is_zero(const uint8_t *ptr, unsigned size);
 #define zeroize_temp_key zeroize_key
 #define zrelease_temp_mpi_key zrelease_mpi_key
 
+static inline void
+_gnutls_memory_mark_undefined(void *addr, size_t size)
+{
+#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
+       ASAN_POISON_MEMORY_REGION(addr, size);
+#endif
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+       if (RUNNING_ON_VALGRIND)
+               VALGRIND_MAKE_MEM_UNDEFINED(addr, size);
+#endif
+}
+
+static inline void
+_gnutls_memory_mark_defined(void *addr, size_t size)
+{
+#ifdef HAVE_SANITIZER_ASAN_INTERFACE_H
+       ASAN_UNPOISON_MEMORY_REGION(addr, size);
+#endif
+#ifdef HAVE_VALGRIND_MEMCHECK_H
+       if (RUNNING_ON_VALGRIND)
+               VALGRIND_MAKE_MEM_DEFINED(addr, size);
+#endif
+}
+
 #endif /* GNUTLS_LIB_MEM_H */
index bd55a4be57553abfdd1ccd6708cf1d5698905a78..94a15e2d4b7d25bb682fff5d13688cfe0185432b 100644 (file)
@@ -55,9 +55,6 @@
 #include "ext/cert_types.h"
 #include "locks.h"
 #include "kx.h"
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-#include <valgrind/memcheck.h>
-#endif
 
 /* to be used by supplemental data support to disable TLS1.3
  * when supplemental data have been globally registered */
@@ -640,19 +637,19 @@ int gnutls_init(gnutls_session_t * session, unsigned int flags)
         * runtime before being used. Mark such regions with a
         * valgrind client request as undefined.
         */
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-       if (RUNNING_ON_VALGRIND) {
-               if (flags & GNUTLS_CLIENT)
-                       VALGRIND_MAKE_MEM_UNDEFINED((*session)->security_parameters.client_random,
-                                                   GNUTLS_RANDOM_SIZE);
-               if (flags & GNUTLS_SERVER) {
-                       VALGRIND_MAKE_MEM_UNDEFINED((*session)->security_parameters.server_random,
-                                                   GNUTLS_RANDOM_SIZE);
-                       VALGRIND_MAKE_MEM_UNDEFINED((*session)->key.session_ticket_key,
-                                                   TICKET_MASTER_KEY_SIZE);
-               }
-       }
-#endif
+       _gnutls_memory_mark_undefined((*session)->security_parameters.master_secret,
+                                     GNUTLS_MASTER_SIZE);
+       _gnutls_memory_mark_undefined((*session)->security_parameters.client_random,
+                                     GNUTLS_RANDOM_SIZE);
+       _gnutls_memory_mark_undefined((*session)->security_parameters.server_random,
+                                     GNUTLS_RANDOM_SIZE);
+       _gnutls_memory_mark_undefined((*session)->key.session_ticket_key,
+                                     TICKET_MASTER_KEY_SIZE);
+       _gnutls_memory_mark_undefined((*session)->key.previous_ticket_key,
+                                     TICKET_MASTER_KEY_SIZE);
+       _gnutls_memory_mark_undefined((*session)->key.initial_stek,
+                                     TICKET_MASTER_KEY_SIZE);
+
        handshake_internal_state_clear1(*session);
 
 #ifdef MSG_NOSIGNAL
@@ -771,12 +768,26 @@ void gnutls_deinit(gnutls_session_t session)
        gnutls_memset(&session->key.proto, 0, sizeof(session->key.proto));
 
        /* clear session ticket keys */
+       _gnutls_memory_mark_defined(session->key.session_ticket_key,
+                                   TICKET_MASTER_KEY_SIZE);
        gnutls_memset(&session->key.session_ticket_key, 0,
                      TICKET_MASTER_KEY_SIZE);
+       _gnutls_memory_mark_undefined(session->key.session_ticket_key,
+                                     TICKET_MASTER_KEY_SIZE);
+
+       _gnutls_memory_mark_defined(session->key.previous_ticket_key,
+                                   TICKET_MASTER_KEY_SIZE);
        gnutls_memset(&session->key.previous_ticket_key, 0,
                      TICKET_MASTER_KEY_SIZE);
+       _gnutls_memory_mark_undefined(session->key.previous_ticket_key,
+                                     TICKET_MASTER_KEY_SIZE);
+
+       _gnutls_memory_mark_defined(session->key.initial_stek,
+                                   TICKET_MASTER_KEY_SIZE);
        gnutls_memset(&session->key.initial_stek, 0,
                      TICKET_MASTER_KEY_SIZE);
+       _gnutls_memory_mark_undefined(session->key.initial_stek,
+                                     TICKET_MASTER_KEY_SIZE);
 
        gnutls_mutex_deinit(&session->internals.post_negotiation_lock);
        gnutls_mutex_deinit(&session->internals.epoch_lock);
index 316555b49a8d996ecf8fd933b869ec1f7ea82d87..afcf3edf3750901252e6295138bfaa796301b840 100644 (file)
@@ -21,9 +21,6 @@
  */
 #include "gnutls_int.h"
 #include "stek.h"
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-#include <valgrind/memcheck.h>
-#endif
 
 #define NAME_POS (0)
 #define KEY_POS (TICKET_KEY_NAME_SIZE)
@@ -145,12 +142,9 @@ static int rotate(gnutls_session_t session)
                /* Replace old key with new one, and call callback if provided */
                call_rotation_callback(session, key, t);
                session->key.totp.last_result = t;
+               _gnutls_memory_mark_defined(session->key.session_ticket_key,
+                                           sizeof(key));
                memcpy(session->key.session_ticket_key, key, sizeof(key));
-#ifdef HAVE_VALGRIND_MEMCHECK_H
-               if (RUNNING_ON_VALGRIND)
-                       VALGRIND_MAKE_MEM_DEFINED(session->key.session_ticket_key,
-                                                 TICKET_MASTER_KEY_SIZE);
-#endif
 
                session->key.totp.was_rotated = 1;
        } else if (t < 0) {
@@ -257,10 +251,7 @@ int _gnutls_get_session_ticket_decryption_key(gnutls_session_t session,
                                              gnutls_datum_t *enc_key)
 {
        int retval;
-       gnutls_datum_t key = {
-               .data = session->key.session_ticket_key,
-               .size = TICKET_MASTER_KEY_SIZE
-       };
+       uint8_t *key_data;
 
        if (unlikely(session == NULL || ticket_data == NULL || ticket_data->data == NULL))
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
@@ -276,38 +267,42 @@ int _gnutls_get_session_ticket_decryption_key(gnutls_session_t session,
         * We compare the first 16 bytes --> The key_name field.
         */
        if (memcmp(ticket_data->data,
-                  &key.data[NAME_POS],
-                  TICKET_KEY_NAME_SIZE) == 0)
+                  &session->key.session_ticket_key[NAME_POS],
+                  TICKET_KEY_NAME_SIZE) == 0) {
+               key_data = session->key.session_ticket_key;
                goto key_found;
-
-       key.size = TICKET_MASTER_KEY_SIZE;
-       key.data = session->key.previous_ticket_key;
+       }
 
        /*
         * Current key is not valid.
         * Compute previous key and see if that matches.
         */
-       if ((retval = rotate_back_and_peek(session, key.data)) < 0)
+       _gnutls_memory_mark_defined(session->key.previous_ticket_key, TICKET_MASTER_KEY_SIZE);
+       if ((retval = rotate_back_and_peek(session, session->key.previous_ticket_key)) < 0) {
+               _gnutls_memory_mark_undefined(session->key.previous_ticket_key, TICKET_MASTER_KEY_SIZE);
                return gnutls_assert_val(retval);
+       }
 
        if (memcmp(ticket_data->data,
-                  &key.data[NAME_POS],
-                  TICKET_KEY_NAME_SIZE) == 0)
+                  &session->key.previous_ticket_key[NAME_POS],
+                  TICKET_KEY_NAME_SIZE) == 0) {
+               key_data = session->key.previous_ticket_key;
                goto key_found;
+       }
 
        return GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE;
 
 key_found:
        if (key_name) {
-               key_name->data = &key.data[NAME_POS];
+               key_name->data = &key_data[NAME_POS];
                key_name->size = TICKET_KEY_NAME_SIZE;
        }
        if (mac_key) {
-               mac_key->data = &key.data[MAC_SECRET_POS];
+               mac_key->data = &key_data[MAC_SECRET_POS];
                mac_key->size = TICKET_MAC_SECRET_SIZE;
        }
        if (enc_key) {
-               enc_key->data = &key.data[KEY_POS];
+               enc_key->data = &key_data[KEY_POS];
                enc_key->size = TICKET_CIPHER_KEY_SIZE;
        }
 
@@ -334,6 +329,8 @@ int _gnutls_initialize_session_ticket_key_rotation(gnutls_session_t session, con
        if (unlikely(session->key.totp.last_result != 0))
                return GNUTLS_E_INVALID_REQUEST;
 
+       _gnutls_memory_mark_defined(session->key.initial_stek,
+                                   TICKET_MASTER_KEY_SIZE);
        memcpy(session->key.initial_stek, key->data, key->size);
 
        session->key.totp.was_rotated = 0;
index 5bf82016112e77b2745b416395e3f0a0c122c585..579c9d60053463e67dfca70cf4d426059297e72e 100644 (file)
@@ -156,19 +156,21 @@ void start(const char *prio)
        memset(&v1, 0, sizeof(v1));
        memset(&v2, 0, sizeof(v2));
 
-       /* check master secret */
-       gnutls_session_get_master_secret(server, &v1);
-       if (v1.size <= 0) {
-               fail("error in server's master secret\n");
-       }
-
-       gnutls_session_get_master_secret(client, &v2);
-       if (v2.size <= 0) {
-               fail("error in client's master secret\n");
-       }
-
-       if (v1.size != v2.size || memcmp(v1.data, v2.data, v1.size) != 0) {
-               fail("master secret don't match!\n");
+       if (gnutls_protocol_get_version(client) != GNUTLS_TLS1_3) {
+               /* check master secret */
+               gnutls_session_get_master_secret(server, &v1);
+               if (v1.size <= 0) {
+                       fail("error in server's master secret\n");
+               }
+
+               gnutls_session_get_master_secret(client, &v2);
+               if (v2.size <= 0) {
+                       fail("error in client's master secret\n");
+               }
+
+               if (v1.size != v2.size || memcmp(v1.data, v2.data, v1.size) != 0) {
+                       fail("master secret don't match!\n");
+               }
        }
        
        gnutls_bye(client, GNUTLS_SHUT_RDWR);