]> git.ipfire.org Git - thirdparty/gnutls.git/commitdiff
handshake: fix timing of sending early data
authorDaiki Ueno <ueno@gnu.org>
Fri, 23 Apr 2021 13:36:37 +0000 (15:36 +0200)
committerDaiki Ueno <ueno@gnu.org>
Sun, 25 Apr 2021 06:42:47 +0000 (08:42 +0200)
Previously, the client was sending early data after receiving a Server
Hello message, which not only negates the benefit of 0-RTT, but also
was a logic error as it can only be decrypted by the server when the
initial handshake and the resuming handshake agree on the same
ciphersuites.  This fixes that behavior in the following ways:

- extend the session data format to include the selected ciphersuites,
  even in TLS 1.3
- setup the epoch for early data, right before the client sending
  early data (also right after the server deciding to accept early
  data).
- extend the test case to use different ciphersuites in the initial
  and resuming handshakes

Signed-off-by: Daiki Ueno <ueno@gnu.org>
NEWS
lib/cipher.c
lib/constate.c
lib/handshake-tls13.c
lib/handshake.c
lib/record.c
lib/session_pack.c
tests/tls13-early-data.c
tests/tls13/prf-early.c

diff --git a/NEWS b/NEWS
index 8b3538d05d086067480ce4260ffab509f6337b97..f4ebe43ffb7fac47d1aa59dadff57989c69898bd 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,11 @@ See the end for copying conditions.
    This can be enabled with --enable-afalg configure option, when libkcapi
    package is installed (#308).
 
+** libgnutls: Fixed timing of early data exchange. Previously, the client was
+   sending early data after receiving Server Hello, which not only negates the
+   benefit of 0-RTT, but also works under certain assumptions hold (e.g., the
+   same ciphersuite is selected in initial and resumption handshake) (#1146).
+
 * Version 3.7.1 (released 2021-03-10)
 
 ** libgnutls: Fixed potential use-after-free in sending "key_share"
index 90ab1d3a9b2105ee39b9f9387f4f68f8c4e2c5f8..28eafbe1883cb91d7b052bbff277bfcbd543b96b 100644 (file)
@@ -85,7 +85,11 @@ _gnutls_encrypt(gnutls_session_t session,
                content_type_t type, record_parameters_st *params)
 {
        gnutls_datum_t plaintext;
-       const version_entry_st *vers = get_version(session);
+       const version_entry_st *vers =
+               (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) &&
+               !IS_SERVER(session) ?
+               session->internals.resumed_security_parameters.pversion :
+               get_version(session);
        int ret;
 
        plaintext.data = (uint8_t *) data;
index fc56a7569aac11e63ff805898f2b784d66e4eda2..ffa343000eedae1bd5d32ea4c2d9902c87bed17e 100644 (file)
@@ -336,11 +336,19 @@ _tls13_set_early_keys(gnutls_session_t session,
                return GNUTLS_E_INVALID_REQUEST;
        }
 
-       ret = _tls13_expand_secret(session, "key", 3, NULL, 0, session->key.proto.tls13.e_ckey, key_size, key_block);
+       ret = _tls13_expand_secret2(session->internals.
+                                   resumed_security_parameters.prf,
+                                   "key", 3, NULL, 0,
+                                   session->key.proto.tls13.e_ckey,
+                                   key_size, key_block);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
-       ret = _tls13_expand_secret(session, "iv", 2, NULL, 0, session->key.proto.tls13.e_ckey, iv_size, iv_block);
+       ret = _tls13_expand_secret2(session->internals.
+                                   resumed_security_parameters.prf,
+                                   "iv", 2, NULL, 0,
+                                   session->key.proto.tls13.e_ckey,
+                                   iv_size, iv_block);
        if (ret < 0)
                return gnutls_assert_val(ret);
 
@@ -592,10 +600,19 @@ _gnutls_set_cipher_suite2(gnutls_session_t session,
                        return gnutls_assert_val(GNUTLS_E_RECEIVED_ILLEGAL_PARAMETER);
 
                return 0;
-       } else {
-               if (params->initialized
-                   || params->cipher != NULL || params->mac != NULL)
-                       return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+       }
+
+       /* The params shouldn't have been initialized at this point, unless we
+        * are doing trial encryption/decryption of early data.
+        */
+       if (unlikely
+           (!((session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT &&
+               !IS_SERVER(session)) ||
+              (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED &&
+               IS_SERVER(session))) &&
+            (params->initialized
+             || params->cipher != NULL || params->mac != NULL))) {
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
        }
 
        if (_gnutls_cipher_is_ok(cipher_algo) == 0
@@ -655,7 +672,10 @@ int _gnutls_epoch_set_keys(gnutls_session_t session, uint16_t epoch, hs_stage_t
        int key_size;
        record_parameters_st *params;
        int ret;
-       const version_entry_st *ver = get_version(session);
+       const version_entry_st *ver =
+               stage == STAGE_EARLY && !IS_SERVER(session) ?
+               session->internals.resumed_security_parameters.pversion :
+               get_version(session);
 
        if (unlikely(ver == NULL))
                return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
@@ -1200,12 +1220,18 @@ int _tls13_read_connection_state_init(gnutls_session_t session, hs_stage_t stage
            session->security_parameters.epoch_next;
        int ret;
 
+       if (unlikely(stage == STAGE_EARLY && !IS_SERVER(session))) {
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+       }
+
        ret = _gnutls_epoch_set_keys(session, epoch_next, stage);
        if (ret < 0)
                return ret;
 
        _gnutls_handshake_log("HSK[%p]: TLS 1.3 set read key with cipher suite: %s\n",
                              session,
+                             stage == STAGE_EARLY ?
+                             session->internals.resumed_security_parameters.cs->name :
                              session->security_parameters.cs->name);
 
        session->security_parameters.epoch_read = epoch_next;
@@ -1223,12 +1249,18 @@ int _tls13_write_connection_state_init(gnutls_session_t session, hs_stage_t stag
            session->security_parameters.epoch_next;
        int ret;
 
+       if (unlikely(stage == STAGE_EARLY && IS_SERVER(session))) {
+               return gnutls_assert_val(GNUTLS_E_INTERNAL_ERROR);
+       }
+
        ret = _gnutls_epoch_set_keys(session, epoch_next, stage);
        if (ret < 0)
                return ret;
 
        _gnutls_handshake_log("HSK[%p]: TLS 1.3 set write key with cipher suite: %s\n",
                              session,
+                             stage == STAGE_EARLY ?
+                             session->internals.resumed_security_parameters.cs->name :
                              session->security_parameters.cs->name);
 
        session->security_parameters.epoch_write = epoch_next;
index 9687707a32912fb55d9e776d556f8fa9e186a897..d9071e2b312049d7f126573190b63c9486f225e9 100644 (file)
@@ -84,7 +84,9 @@ int _gnutls13_handshake_client(gnutls_session_t session)
        case STATE99:
        case STATE100:
 #ifdef TLS13_APPENDIX_D4
-               if (session->internals.priorities->tls13_compat_mode) {
+               if (session->internals.priorities->tls13_compat_mode &&
+                   /* Key change is indicated by sending an EndOfEarlyData below */
+                   !(session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT)) {
                        /* We send it before keys are generated. That works because CCS
                         * is always being cached and queued and not being sent directly */
                        ret = _gnutls_send_change_cipher_spec(session, AGAIN(STATE100));
@@ -94,26 +96,7 @@ int _gnutls13_handshake_client(gnutls_session_t session)
 #endif
                FALLTHROUGH;
        case STATE101:
-               /* Note that we check IN_FLIGHT, not ACCEPTED
-                * here. This is because the client sends early data
-                * speculatively. */
-               if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) {
-                       ret = _tls13_write_connection_state_init(session, STAGE_EARLY);
-                       if (ret == 0) {
-                               _gnutls_epoch_bump(session);
-                               ret = _gnutls_epoch_dup(session, EPOCH_WRITE_CURRENT);
-                       }
-                       STATE = STATE101;
-                       IMED_RET_FATAL("set early traffic keys", ret, 0);
-               }
-               FALLTHROUGH;
-       case STATE102:
-               ret = _gnutls13_send_early_data(session);
-               STATE = STATE102;
-               IMED_RET("send early data", ret, 0);
-               FALLTHROUGH;
-       case STATE103:
-               STATE = STATE103;
+               STATE = STATE101;
                ret = generate_hs_traffic_keys(session);
                /* Note that we check IN_FLIGHT, not ACCEPTED
                 * here. This is because the client sends early data
@@ -125,40 +108,40 @@ int _gnutls13_handshake_client(gnutls_session_t session)
                        ret = _tls13_connection_state_init(session, STAGE_HS);
                IMED_RET_FATAL("set hs traffic keys", ret, 0);
                FALLTHROUGH;
-       case STATE104:
+       case STATE102:
                ret = _gnutls13_recv_encrypted_extensions(session);
-               STATE = STATE104;
+               STATE = STATE102;
                IMED_RET("recv encrypted extensions", ret, 0);
                FALLTHROUGH;
-       case STATE105:
+       case STATE103:
                ret = _gnutls13_recv_certificate_request(session);
-               STATE = STATE105;
+               STATE = STATE103;
                IMED_RET("recv certificate request", ret, 0);
                FALLTHROUGH;
-       case STATE106:
+       case STATE104:
                ret = _gnutls13_recv_certificate(session);
-               STATE = STATE106;
+               STATE = STATE104;
                IMED_RET("recv certificate", ret, 0);
                FALLTHROUGH;
-       case STATE107:
+       case STATE105:
                ret = _gnutls13_recv_certificate_verify(session);
-               STATE = STATE107;
+               STATE = STATE105;
                IMED_RET("recv server certificate verify", ret, 0);
                FALLTHROUGH;
-       case STATE108:
+       case STATE106:
                ret = _gnutls_run_verify_callback(session, GNUTLS_CLIENT);
-               STATE = STATE108;
+               STATE = STATE106;
                if (ret < 0)
                        return gnutls_assert_val(ret);
                FALLTHROUGH;
-       case STATE109:
+       case STATE107:
                ret = _gnutls13_recv_finished(session);
-               STATE = STATE109;
+               STATE = STATE107;
                IMED_RET("recv finished", ret, 0);
                FALLTHROUGH;
-       case STATE110:
-               ret = _gnutls13_send_end_of_early_data(session, AGAIN(STATE110));
-               STATE = STATE110;
+       case STATE108:
+               ret = _gnutls13_send_end_of_early_data(session, AGAIN(STATE108));
+               STATE = STATE108;
                IMED_RET("send end of early data", ret, 0);
 
                /* Note that we check IN_FLIGHT, not ACCEPTED
@@ -170,23 +153,23 @@ int _gnutls13_handshake_client(gnutls_session_t session)
                        IMED_RET_FATAL("set hs traffic key after sending early data", ret, 0);
                }
                FALLTHROUGH;
-       case STATE111:
-               ret = _gnutls13_send_certificate(session, AGAIN(STATE111));
-               STATE = STATE111;
+       case STATE109:
+               ret = _gnutls13_send_certificate(session, AGAIN(STATE109));
+               STATE = STATE109;
                IMED_RET("send certificate", ret, 0);
                FALLTHROUGH;
-       case STATE112:
-               ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE112));
-               STATE = STATE112;
+       case STATE110:
+               ret = _gnutls13_send_certificate_verify(session, AGAIN(STATE110));
+               STATE = STATE110;
                IMED_RET("send certificate verify", ret, 0);
                FALLTHROUGH;
-       case STATE113:
-               ret = _gnutls13_send_finished(session, AGAIN(STATE113));
-               STATE = STATE113;
+       case STATE111:
+               ret = _gnutls13_send_finished(session, AGAIN(STATE111));
+               STATE = STATE111;
                IMED_RET("send finished", ret, 0);
                FALLTHROUGH;
-       case STATE114:
-               STATE = STATE114;
+       case STATE112:
+               STATE = STATE112;
 
                ret =
                    generate_ap_traffic_keys(session);
@@ -430,22 +413,13 @@ int _gnutls13_handshake_server(gnutls_session_t session)
                FALLTHROUGH;
        case STATE101:
                STATE = STATE101;
-               if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
-                       ret = _tls13_read_connection_state_init(session, STAGE_EARLY);
-                       if (ret == 0) {
-                               _gnutls_epoch_bump(session);
-                               ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);
-                       }
-                       IMED_RET_FATAL("set early traffic keys", ret, 0);
 
-                       ret = generate_hs_traffic_keys(session);
-                       IMED_RET_FATAL("generate hs traffic keys", ret, 0);
+               ret = generate_hs_traffic_keys(session);
+               IMED_RET_FATAL("generate hs traffic keys", ret, 0);
 
+               if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
                        ret = _tls13_write_connection_state_init(session, STAGE_HS);
                } else {
-                       ret = generate_hs_traffic_keys(session);
-                       IMED_RET_FATAL("generate hs traffic keys", ret, 0);
-
                        ret = _tls13_connection_state_init(session, STAGE_HS);
                }
                IMED_RET_FATAL("set hs traffic keys", ret, 0);
index c30703ccbd4740176f429a135d2f81a9ad5ac71f..1153eac85dc47509f04962f4a0468d33e023d959 100644 (file)
@@ -55,6 +55,7 @@
 #include <random.h>
 #include <dtls.h>
 #include "secrets.h"
+#include "tls13/early_data.h"
 #include "tls13/session_ticket.h"
 #include "locks.h"
 #ifdef HAVE_VALGRIND_MEMCHECK_H
@@ -788,6 +789,38 @@ read_client_hello(gnutls_session_t session, uint8_t * data,
                return ret;
        }
 
+       if (session->internals.hsk_flags & HSK_EARLY_DATA_ACCEPTED) {
+               const cipher_entry_st *ce;
+               const mac_entry_st *me;
+               record_parameters_st *params;
+
+               ce = cipher_to_entry(session->internals.
+                                    resumed_security_parameters.
+                                    cs->block_algorithm);
+               me = mac_to_entry(session->internals.
+                                 resumed_security_parameters.
+                                 cs->mac_algorithm);
+
+               ret = _gnutls_epoch_get(session, EPOCH_NEXT, &params);
+               if (ret < 0) {
+                       return gnutls_assert_val(ret);
+               }
+
+               params->cipher = ce;
+               params->mac = me;
+
+               ret = _tls13_read_connection_state_init(session, STAGE_EARLY);
+               if (ret < 0) {
+                       return gnutls_assert_val(ret);
+               }
+
+               _gnutls_epoch_bump(session);
+               ret = _gnutls_epoch_dup(session, EPOCH_READ_CURRENT);
+               if (ret < 0) {
+                       return gnutls_assert_val(ret);
+               }
+       }
+
        /* resumed by session_ticket extension */
        if (!vers->tls13_sem && session->internals.resumed) {
                session->internals.resumed_security_parameters.
@@ -2309,6 +2342,43 @@ static int send_client_hello(gnutls_session_t session, int again)
        ret = _gnutls_send_handshake(session, bufel,
                                     GNUTLS_HANDSHAKE_CLIENT_HELLO);
 
+       if (session->internals.hsk_flags & HSK_EARLY_DATA_IN_FLIGHT) {
+               const cipher_entry_st *ce;
+               const mac_entry_st *me;
+               record_parameters_st *params;
+
+               ce = cipher_to_entry(session->internals.
+                                    resumed_security_parameters.
+                                    cs->block_algorithm);
+               me = mac_to_entry(session->internals.
+                                 resumed_security_parameters.
+                                 cs->mac_algorithm);
+
+               ret = _gnutls_epoch_get(session, EPOCH_NEXT, &params);
+               if (ret < 0) {
+                       return gnutls_assert_val(ret);
+               }
+
+               params->cipher = ce;
+               params->mac = me;
+
+               ret = _tls13_write_connection_state_init(session, STAGE_EARLY);
+               if (ret < 0) {
+                       return gnutls_assert_val(ret);
+               }
+
+               _gnutls_epoch_bump(session);
+               ret = _gnutls_epoch_dup(session, EPOCH_WRITE_CURRENT);
+               if (ret < 0) {
+                       return gnutls_assert_val(ret);
+               }
+
+               ret = _gnutls13_send_early_data(session);
+               if (ret < 0) {
+                       return gnutls_assert_val(ret);
+               }
+       }
+
        return ret;
 
  cleanup:
index cd9df80520febab64e25af3700360e2018e732e7..860b9897d6ce42dd26633197d52712441dc33ff6 100644 (file)
@@ -2120,7 +2120,7 @@ ssize_t gnutls_record_send_early_data(gnutls_session_t session,
  * @data: the buffer that the data will be read into
  * @data_size: the number of requested bytes
  *
- * This function can be used by a searver to retrieve data sent early
+ * This function can be used by a server to retrieve data sent early
  * in the handshake processes when resuming a session.  This is used
  * to implement a zero-roundtrip (0-RTT) mode.  It has the same
  * semantics as gnutls_record_recv().
index a6d11c4cfc26e50155a87623073a4406061fb958..1f3bc4740c57cbea657a406530cea207aeab8879 100644 (file)
@@ -911,11 +911,11 @@ pack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
        BUFFER_APPEND_NUM(ps, session->security_parameters.client_ctype);
        BUFFER_APPEND_NUM(ps, session->security_parameters.server_ctype);
 
+       BUFFER_APPEND(ps, session->security_parameters.cs->id, 2);
+
        /* if we are under TLS 1.3 do not pack keys or params negotiated using an extension
         * they are not necessary */
        if (!session->security_parameters.pversion->tls13_sem) {
-               BUFFER_APPEND(ps, session->security_parameters.cs->id, 2);
-
                BUFFER_APPEND_PFX1(ps, session->security_parameters.master_secret,
                              GNUTLS_MASTER_SIZE);
                BUFFER_APPEND_PFX1(ps, session->security_parameters.client_random,
@@ -1026,12 +1026,12 @@ unpack_security_parameters(gnutls_session_t session, gnutls_buffer_st * ps)
                       session->internals.resumed_security_parameters.
                       server_ctype);
 
-       if (!session->internals.resumed_security_parameters.pversion->tls13_sem) {
-               BUFFER_POP(ps, cs, 2);
-               session->internals.resumed_security_parameters.cs = ciphersuite_to_entry(cs);
-               if (session->internals.resumed_security_parameters.cs == NULL)
-                       return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
+       BUFFER_POP(ps, cs, 2);
+       session->internals.resumed_security_parameters.cs = ciphersuite_to_entry(cs);
+       if (session->internals.resumed_security_parameters.cs == NULL)
+               return gnutls_assert_val(GNUTLS_E_INVALID_REQUEST);
 
+       if (!session->internals.resumed_security_parameters.pversion->tls13_sem) {
                /* master secret */
                ret = _gnutls_buffer_pop_datum_prefix8(ps, &t);
                if (ret < 0) {
index 4235e12e2a3e75ceba2922be20562639d699a383..8091572dfa3efe6f3ce79e1ebe789cc1ea7af53c 100644 (file)
@@ -70,11 +70,19 @@ static void client_log_func(int level, const char *str)
 /* A very basic TLS client.
  */
 
-#define SESSIONS 3
 #define MAX_BUF 1024
 #define MSG "Hello TLS"
 #define EARLY_MSG "Hello TLS, it's early"
-#define PRIORITY "NORMAL:-VERS-ALL:+VERS-TLS1.3"
+
+/* This test makes connection 3 times with different ciphersuites: first with
+ * TLS_AES_128_GCM_SHA256, then TLS_AES_256_GCM_SHA384 two times.  The reason
+ * for doing this is to check that the early data is encrypted with the
+ * ciphersuite selected during the initial handshake, not the resuming
+ * handshakes.
+ */
+#define SESSIONS 3
+#define TLS13_AES_128_GCM "NORMAL:-VERS-ALL:+VERS-TLS1.3:+AES-128-GCM"
+#define TLS13_AES_256_GCM "NORMAL:-VERS-ALL:+VERS-TLS1.3:+AES-256-GCM"
 
 static const
 gnutls_datum_t hrnd = {(void*)"\x00\x02\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32};
@@ -120,7 +128,7 @@ static void client(int sds[], const char *data, size_t size, size_t maxsize)
                int sd = sds[t];
 
                assert(gnutls_init(&session, GNUTLS_CLIENT)>=0);
-               assert(gnutls_priority_set_direct(session, PRIORITY, NULL)>=0);
+               assert(gnutls_priority_set_direct(session, t == 0 ? TLS13_AES_128_GCM : TLS13_AES_256_GCM, NULL)>=0);
 
                gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
 
@@ -289,7 +297,7 @@ static void server(int sds[], const char *data, size_t size, size_t maxsize)
 
                assert(gnutls_init(&session, GNUTLS_SERVER|GNUTLS_ENABLE_EARLY_DATA)>=0);
 
-               assert(gnutls_priority_set_direct(session, PRIORITY, NULL)>=0);
+               assert(gnutls_priority_set_direct(session, t == 0 ? TLS13_AES_128_GCM : TLS13_AES_256_GCM, NULL)>=0);
 
                gnutls_credentials_set(session, GNUTLS_CRD_CERTIFICATE, x509_cred);
 
index 51dd7a3f76cba92adee8209bd5d8b9b4382ccda0..3d9462848a608f392c2123ae5a7cf98f394d46ed 100644 (file)
@@ -123,10 +123,10 @@ static void dump(const char *name, const uint8_t *data, unsigned data_size)
        } \
        }
 
-#define KEY_EXP_VALUE "\x7f\x9a\x62\x64\x5e\x90\xa4\x19\x6f\xbf\x7b\x4e\x98\x63\x29\xb0\x46\xa2\x2a\x47\x94\x6a\x78\xdc\x6e\xea\x90\x13\x9d\xd4\xd1\x20\x02\x04"
-#define HELLO_VALUE "\x38\x40\x8c\x0d\x53\xe5\xd2\xe8\x66\xb4\x46\xce\x32\x85\xd5\x02\x3a\x4f\x81\x3c\x9e\x1b\x4a\x53\x73\x22\xad\xf2\x11\xc6\x45"
-#define CONTEXT_VALUE "\xf6\x95\x60\x0d\x51\x9e\x1a\x40\xb2\x9e\xb0\x48\x55\xfe\x64\xf8\xa0\x26\x31\xd8\xb1\x66\xf3\x10\x62\x32\x26\x52\x9e\x63\x49"
-#define NULL_CONTEXT_VALUE "\xb1\x80\x8c\xb3\xc2\xa9\x06\x88\xb7\xc2\xed\xd4\x5f\x1c\xad\x0b\xb2\x1f\xa9\xe2\xc6\x37\xd3\x52\x73\x1b\xf5\x3b\x92\x61\x08"
+#define KEY_EXP_VALUE "\xec\xc2\x4a\x6b\x07\x89\xd9\x19\xd9\x73\x6d\xd0\x00\x73\xc9\x7a\xd7\x92\xef\x56\x91\x61\xb4\xff\x5f\xef\x81\xc1\x98\x68\x4e\xdf\xd7\x7e"
+#define HELLO_VALUE "\x4f\x85\x33\x64\x48\xff\x0d\x8b\xd5\x50\x0f\x97\x91\x5b\x7d\x8d\xc9\x05\x91\x45\x4f\xb9\x4b\x4b\xbc\xbf\x58\x84\x1a\x46\xe3"
+#define CONTEXT_VALUE "\x11\x8d\x85\xa8\x91\xe5\x50\x75\x44\x88\x69\xaf\x95\x9a\xb0\x29\xd4\xae\xcd\x11\xcb\x1d\x29\x7c\xe6\x24\xd4\x7c\x95\xdb\x5c"
+#define NULL_CONTEXT_VALUE "\x56\x99\x41\x73\x5e\x73\x34\x7f\x3d\x69\x9f\xc0\x3b\x8b\x86\x33\xc6\xc3\x97\x46\x61\x62\x3f\x55\xab\x39\x60\xa5\xeb\xfe\x37"
 
 static int handshake_callback_called;