Commit 761772d7 authored by Bodo Möller's avatar Bodo Möller
Browse files

Implement the Opaque PRF Input TLS extension

(draft-rescorla-tls-opaque-prf-input-00.txt), and do some cleanups and
bugfixes on the way.  In particular, this fixes the buffer bounds
checks in ssl_add_clienthello_tlsext() and in ssl_add_serverhello_tlsext().

Note that the opaque PRF Input TLS extension is not compiled by default;
see CHANGES.
parent 54ef01b5
Loading
Loading
Loading
Loading
+58 −0
Original line number Original line Diff line number Diff line
@@ -4,6 +4,64 @@


 Changes between 0.9.8f and 0.9.9  [xx XXX xxxx]
 Changes between 0.9.8f and 0.9.9  [xx XXX xxxx]


  *) Implement Opaque PRF Input TLS extension as specified in
     draft-rescorla-tls-opaque-prf-input-00.txt.  Since this is not an
     official specification yet and no extension type assignment by
     IANA exists, this extension (for now) will have to be explicitly
     enabled when building OpenSSL by providing the extension number
     to use.  For example, specify an option

         -DTLSEXT_TYPE_opaque_prf_input=0x9527

     to the "config" or "Configure" script to enable the extension,
     assuming extension number 0x9527 (which is a completely arbitrary
     and unofficial assignment based on the MD5 hash of the Internet
     Draft).  Note that by doing so, you potentially lose
     interoperability with other TLS implementations since these might
     be using the same extension number for other purposes.

     SSL_set_tlsext_opaque_prf_input(ssl, src, len) is used to set the
     opaque PRF input value to use in the handshake.  This will create
     an interal copy of the length-'len' string at 'src', and will
     return non-zero for success.

     To get more control and flexibility, provide a callback function
     by using

          SSL_CTX_set_tlsext_opaque_prf_input_callback(ctx, cb)
          SSL_CTX_set_tlsext_opaque_prf_input_callback_arg(ctx, arg)

     where

          int (*cb)(SSL *, void *peerinput, size_t len, void *arg);
          void *arg;

     Callback function 'cb' will be called in handshakes, and is
     expected to use SSL_set_tlsext_opaque_prf_input() as appropriate.
     Argument 'arg' is for application purposes (the value as given to
     SSL_CTX_set_tlsext_opaque_prf_input_callback_arg() will directly
     be provided to the callback function).  The callback function
     has to return non-zero to report success: usually 1 to use opaque
     PRF input just if possible, or 2 to enforce use of the opaque PRF
     input.  In the latter case, the library will abort the handshake
     if opaque PRF input is not successfully negotiated.

     Arguments 'peerinput' and 'len' given to the callback function
     will always be NULL and 0 in the case of a client.  A server will
     see the client's opaque PRF input through these variables if
     available (NULL and 0 otherwise).  Note that if the server
     provides an opaque PRF input, the length must be the same as the
     length of the client's opaque PRF input.

     Note that the callback function will only be called when creating
     a new session (session resumption can resume whatever was
     previously negotiated), and will not be called in SSL 2.0
     handshakes; thus, SSL_CTX_set_options(ctx, SSL_OP_NO_SSLv2) or
     SSL_set_options(ssl, SSL_OP_NO_SSLv2) is especially recommended
     for applications that need to enforce opaque PRF input.

     [Bodo Moeller]

  *) Update ssl code to support digests other than SHA1+MD5 for handshake
  *) Update ssl code to support digests other than SHA1+MD5 for handshake
     MAC. 
     MAC. 


+5 −0
Original line number Original line Diff line number Diff line
@@ -638,6 +638,11 @@ void MS_CALLBACK tlsext_cb(SSL *s, int client_server, int type,
		extname = "server ticket";
		extname = "server ticket";
		break;
		break;


#ifdef TLSEXT_TYPE_opaque_prf_input
		case TLSEXT_TYPE_opaque_prf_input:
		extname = "opaque PRF input";
		break;
#endif


		default:
		default:
		extname = "unknown";
		extname = "unknown";
+7 −0
Original line number Original line Diff line number Diff line
@@ -859,6 +859,11 @@ bad:
		}
		}
#endif	/* OPENSSL_NO_KRB5  */
#endif	/* OPENSSL_NO_KRB5  */
/*	SSL_set_cipher_list(con,"RC4-MD5"); */
/*	SSL_set_cipher_list(con,"RC4-MD5"); */
#if 0
#ifdef TLSEXT_TYPE_opaque_prf_input
	SSL_set_tlsext_opaque_prf_input(con, "Test client", 1);
#endif
#endif


re_start:
re_start:


@@ -1073,11 +1078,13 @@ re_start:
			if (in_init)
			if (in_init)
				{
				{
				in_init=0;
				in_init=0;
#if 0 /* This test doesn't really work as intended (needs to be fixed) */
#ifndef OPENSSL_NO_TLSEXT
#ifndef OPENSSL_NO_TLSEXT
				if (servername != NULL && !SSL_session_reused(con))
				if (servername != NULL && !SSL_session_reused(con))
					{
					{
					BIO_printf(bio_c_out,"Server did %sacknowledge servername extension.\n",tlsextcbp.ack?"":"not ");
					BIO_printf(bio_c_out,"Server did %sacknowledge servername extension.\n",tlsextcbp.ack?"":"not ");
					}
					}
#endif
#endif
#endif
				if (sess_out)
				if (sess_out)
					{
					{
+5 −0
Original line number Original line Diff line number Diff line
@@ -1575,6 +1575,11 @@ static int sv_body(char *hostname, int s, unsigned char *context)
						 strlen((char *)context));
						 strlen((char *)context));
	}
	}
	SSL_clear(con);
	SSL_clear(con);
#if 0
#ifdef TLSEXT_TYPE_opaque_prf_input
	SSL_set_tlsext_opaque_prf_input(con, "Test server", 1);
#endif
#endif


	if (SSL_version(con) == DTLS1_VERSION)
	if (SSL_version(con) == DTLS1_VERSION)
		{
		{
+19 −0
Original line number Original line Diff line number Diff line
@@ -277,6 +277,19 @@ static int ssl23_client_hello(SSL *s)
		version = SSL2_VERSION;
		version = SSL2_VERSION;
		}
		}


	if (version != SSL2_VERSION)
		{
		/* have to disable SSL 2.0 compatibility if we need TLS extensions */

		if (s->tlsext_hostname != NULL)
			ssl2_compat = 0;
		
#ifdef TLSEXT_TYPE_opaque_prf_input
		if (s->ctx->tlsext_opaque_prf_input_callback != 0 || s->tlsext_opaque_prf_input != NULL)
			ssl2_compat = 0;
#endif
		}

	buf=(unsigned char *)s->init_buf->data;
	buf=(unsigned char *)s->init_buf->data;
	if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
	if (s->state == SSL23_ST_CW_CLNT_HELLO_A)
		{
		{
@@ -420,6 +433,12 @@ static int ssl23_client_hello(SSL *s)
			*(p++)=0; /* Add the NULL method */
			*(p++)=0; /* Add the NULL method */


#ifndef OPENSSL_NO_TLSEXT
#ifndef OPENSSL_NO_TLSEXT
			/* TLS extensions*/
			if (ssl_prepare_clienthello_tlsext(s) <= 0)
				{
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,SSL_R_CLIENTHELLO_TLSEXT);
				return -1;
				}
			if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
			if ((p = ssl_add_clienthello_tlsext(s, p, buf+SSL3_RT_MAX_PLAIN_LENGTH)) == NULL)
				{
				{
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
				SSLerr(SSL_F_SSL23_CLIENT_HELLO,ERR_R_INTERNAL_ERROR);
Loading