From: Simon Josefsson Date: Fri, 15 Oct 2010 12:37:36 +0000 (+0200) Subject: Implement RFC 5929 tls-unique channel binding. X-Git-Tag: gnutls_2_11_4~5 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=3f86e31a554d02a2d92b5423942915554af7fc59;p=thirdparty%2Fgnutls.git Implement RFC 5929 tls-unique channel binding. --- diff --git a/lib/gnutls_handshake.c b/lib/gnutls_handshake.c index 20b06c4c30..e88b876f9d 100644 --- a/lib/gnutls_handshake.c +++ b/lib/gnutls_handshake.c @@ -710,6 +710,18 @@ _gnutls_send_finished (gnutls_session_t session, int again) return ret; } + if ((session->internals.resumed == RESUME_FALSE + && session->security_parameters.entity == GNUTLS_CLIENT) + || (session->internals.resumed == RESUME_TRUE + && session->security_parameters.entity == GNUTLS_SERVER)) + { + /* if we are a client not resuming - or we are a server resuming */ + _gnutls_handshake_log ("HSK[%p]: recording tls-unique CB (send)\n", + session); + memcpy (session->internals.cb_tls_unique, data, vdata_size); + session->internals.cb_tls_unique_len = vdata_size; + } + ret = _gnutls_send_handshake (session, bufel, GNUTLS_HANDSHAKE_FINISHED); } @@ -795,6 +807,18 @@ _gnutls_recv_finished (gnutls_session_t session) return ret; } + if ((session->internals.resumed == RESUME_TRUE + && session->security_parameters.entity == GNUTLS_CLIENT) + || (session->internals.resumed == RESUME_FALSE + && session->security_parameters.entity == GNUTLS_SERVER)) + { + /* if we are a client resuming - or we are a server not resuming */ + _gnutls_handshake_log ("HSK[%p]: recording tls-unique CB (recv)\n", + session); + memcpy (session->internals.cb_tls_unique, data, data_size); + session->internals.cb_tls_unique_len = data_size; + } + session->internals.initial_negotiation_completed = 1; return ret; diff --git a/lib/gnutls_int.h b/lib/gnutls_int.h index 87d8f5ca11..b97830e729 100644 --- a/lib/gnutls_int.h +++ b/lib/gnutls_int.h @@ -727,6 +727,9 @@ typedef struct int set:1; } resumed_extension_int_data[MAX_EXT_TYPES]; + unsigned int cb_tls_unique_len; + unsigned char cb_tls_unique[MAX_VERIFY_DATA_SIZE]; + /* If you add anything here, check _gnutls_handshake_internal_state_clear(). */ } internals_st; diff --git a/lib/gnutls_state.c b/lib/gnutls_state.c index 86e3c00ff4..310e143216 100644 --- a/lib/gnutls_state.c +++ b/lib/gnutls_state.c @@ -1354,7 +1354,8 @@ gnutls_session_enable_compatibility_mode (gnutls_session_t session) * @cbtype: an #gnutls_channel_binding_t enumeration type * @cb: output buffer array with data * - * Extract given channel binding data of the @cbtype type. + * Extract given channel binding data of the @cbtype (e.g., + * %GNUTLS_CB_TLS_UNIQUE) type. * * Returns: %GNUTLS_E_SUCCESS on success, * %GNUTLS_E_UNIMPLEMENTED_FEATURE if the @cbtype is unsupported, @@ -1368,5 +1369,18 @@ gnutls_session_channel_binding (gnutls_session_t session, gnutls_channel_binding_t cbtype, gnutls_datum_t *cb) { - return GNUTLS_E_UNIMPLEMENTED_FEATURE; + if (cbtype != GNUTLS_CB_TLS_UNIQUE) + return GNUTLS_E_UNIMPLEMENTED_FEATURE; + + if (!session->internals.initial_negotiation_completed) + return GNUTLS_E_CHANNEL_BINDING_NOT_AVAILABLE; + + cb->size = session->internals.cb_tls_unique_len; + cb->data = gnutls_malloc (cb->size); + if (cb->data == NULL) + return GNUTLS_E_MEMORY_ERROR; + + memcpy (cb->data, session->internals.cb_tls_unique, cb->size); + + return 0; } diff --git a/src/common.c b/src/common.c index 51ba9465a6..b270cd5f1f 100644 --- a/src/common.c +++ b/src/common.c @@ -488,6 +488,23 @@ print_info (gnutls_session_t session, const char *hostname, int insecure) printf ("- Session ID: %s\n", raw_to_string (id, id_size)); } + { + gnutls_datum cb; + int rc; + + rc = gnutls_session_channel_binding (session, GNUTLS_CB_TLS_UNIQUE, &cb); + if (rc) + fprintf (stderr, "Channel binding error: %s\n", gnutls_strerror (rc)); + else + { + size_t i; + + printf ("- Channel binding 'tls-unique': "); + for (i = 0; i < cb.size; i++) + printf ("%02x", cb.data[i]); + printf ("\n"); + } + } fflush (stdout);