int32_t bctbx_ssl_handshake(bctbx_ssl_context_t *ssl_ctx) {

	int ret = 0;
	while( ssl_ctx->ssl_ctx.state != SSL_HANDSHAKE_OVER )
	{
		ret = ssl_handshake_step(&(ssl_ctx->ssl_ctx));
		if( ret != 0 ) {
			break;
		}

		/* insert the callback function for client certificate request */
		if (ssl_ctx->callback_cli_cert_function != NULL) { /* check we have a callback function */
			/* when in state SSL_CLIENT_CERTIFICATE - which means, next call to ssl_handshake_step will send the client certificate to server -
			 * and the client_auth flag is set - which means the server requested a client certificate - */
			if (ssl_ctx->ssl_ctx.state == SSL_CLIENT_CERTIFICATE && ssl_ctx->ssl_ctx.client_auth > 0) {
				/* note: polarssl 1.3 is unable to retrieve certificate dn during handshake from server certificate request
				 * so the dn params in the callback are set to NULL and 0(dn string length) */
				if (ssl_ctx->callback_cli_cert_function(ssl_ctx->callback_cli_cert_data, ssl_ctx, NULL, 0)!=0) {
					if((ret=ssl_send_fatal_handshake_failure(&(ssl_ctx->ssl_ctx))) != 0 )
						return( ret );
				}
			}
		}

	}

	/* remap some output codes */
	if (ret == POLARSSL_ERR_NET_WANT_READ) {
		ret = BCTBX_ERROR_NET_WANT_READ;
	} else if (ret == POLARSSL_ERR_NET_WANT_WRITE) {
		ret = BCTBX_ERROR_NET_WANT_WRITE;
	}

	return(ret);
}
Esempio n. 2
0
static int ssl_do_handshake_part(ssl_context *ssl)
{
  int ret = 0;

  /* Only do steps till ServerHello is received */
  while (ssl->state != SSL_SERVER_HELLO)
  {
    ret = ssl_handshake_step (ssl);
    if (0 != ret)
    {
      die("SSL handshake failed");
    }
  }
  /* Do ServerHello so we can skim the timestamp */
  ret = ssl_handshake_step (ssl);
  if (0 != ret)
  {
    die("SSL handshake failed");
  }

  return 0;
}
Esempio n. 3
0
BELLE_SIP_INSTANCIATE_CUSTOM_VPTR_END

static int tls_channel_handshake(belle_sip_tls_channel_t *channel) {
	int ret;
	while( channel->sslctx.state != SSL_HANDSHAKE_OVER ) {
		if ((ret = ssl_handshake_step( &channel->sslctx ))) {
			break;
		}
		if (channel->sslctx.state == SSL_CLIENT_CERTIFICATE && channel->sslctx.client_auth >0) {
			BELLE_SIP_INVOKE_LISTENERS_ARG1_ARG2(	channel->base.base.listeners
					,belle_sip_channel_listener_t
					,on_auth_requested
					,&channel->base.base
					,NULL/*not set yet*/);

			if (channel->client_cert_chain && channel->client_cert_key) {
#if POLARSSL_VERSION_NUMBER >= 0x01030000
				int err;
#endif
				char tmp[512]={0};
#if POLARSSL_VERSION_NUMBER < 0x01030000
				x509parse_cert_info(tmp,sizeof(tmp)-1,"",&channel->client_cert_chain->cert);
#else
				x509_crt_info(tmp,sizeof(tmp)-1,"",&channel->client_cert_chain->cert);
#endif
				belle_sip_message("Channel [%p]  found client  certificate:\n%s",channel,tmp);
#if POLARSSL_VERSION_NUMBER < 0x01030000
				ssl_set_own_cert(&channel->sslctx,&channel->client_cert_chain->cert,&channel->client_cert_key->key);
#else
                                /* allows public keys other than RSA */
				if ((err=ssl_set_own_cert(&channel->sslctx,&channel->client_cert_chain->cert,&channel->client_cert_key->key))) {
					error_strerror(err,tmp,sizeof(tmp)-1);
					belle_sip_error("Channel [%p] cannot ssl_set_own_cert [%s]",channel,tmp);
				}

				/*update own cert see ssl_handshake frompolarssl*/
				channel->sslctx.handshake->key_cert = channel->sslctx.key_cert;
#endif
			}
		}

	}
	return ret;
}
Esempio n. 4
0
int main( int argc, const char *argv[] )
{
    /* Client and server declarations. */
    int ret;
    int len;
#if SOCKET_COMMUNICATION
    int listen_fd = -1;
    int client_fd = -1;
    int server_fd = -1;
#endif
    unsigned char buf[1024];
    /* Handshake step counter */
    size_t step = 1;
    int flags;

    ssl_context s_ssl, c_ssl;
    x509_crt srvcert;
    pk_context pkey;
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_context cache;
#endif

    if( argc == 3)
    {
        packet_in_num = atoi(argv[1]);
        packet_in_file = argv[2];
    }
    else if( argc != 1)
    {
        usage(argv[0]);
        exit(1);
    }

    /* Server init */
    memset( &s_ssl, 0, sizeof( ssl_context ) );
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_init( &cache );
#endif
    x509_crt_init( &srvcert );
    pk_init( &pkey );

    /* Client init */
    memset( &c_ssl, 0, sizeof( ssl_context ) );
    /*x509_crt_init( &cacert );*/

#if defined(POLARSSL_DEBUG_C)
    debug_set_threshold( DEBUG_LEVEL );
#endif

    /*
     * Server:
     * Load the certificates and private RSA key
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Loading the server cert. and key..." );
        fflush( stdout );
    }

    /*
     * This demonstration program uses embedded test certificates.
     * Instead, you may want to use x509_crt_parse_file() to read the
     * server and CA certificates, as well as pk_parse_keyfile().
     */
    ret = x509_crt_parse( &srvcert, (const unsigned char *) test_srv_crt,
                          strlen( test_srv_crt ) );
    if( ret != 0 )
    {
        printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
        goto exit;
    }

    ret = x509_crt_parse( &srvcert, (const unsigned char *) test_ca_list,
                          strlen( test_ca_list ) );
    if( ret != 0 )
    {
        polarssl_printf( " failed\n  !  x509_crt_parse returned %d\n\n", ret );
        goto exit;
    }

    ret =  pk_parse_key( &pkey, (const unsigned char *) test_srv_key,
                         strlen( test_srv_key ), NULL, 0 );
    if( ret != 0 )
    {
        printf( " failed\n  !  pk_parse_key returned %d\n\n", ret );
        goto exit;
    }

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Server:
     * Setup stuff
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Server: Setting up the SSL data...." );
        fflush( stdout );
    }

    if( ( ret = ssl_init( &s_ssl ) ) != 0 )
    {
        polarssl_printf( " failed\n  ! ssl_init returned %d\n\n", ret );
        goto exit;
    }

    ssl_set_endpoint( &s_ssl, SSL_IS_SERVER );
    ssl_set_authmode( &s_ssl, SSL_VERIFY_NONE );

    /* SSLv3 is deprecated, set minimum to TLS 1.0 */
    ssl_set_min_version( &s_ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1 );
    /* RC4 is deprecated, disable it */
    ssl_set_arc4_support( &s_ssl, SSL_ARC4_DISABLED );

    ssl_set_rng( &s_ssl, ctr_drbg_deterministic, NULL );
    ssl_set_dbg( &s_ssl, my_debug, stdout );

#if defined(POLARSSL_SSL_CACHE_C)
    ssl_set_session_cache( &s_ssl, ssl_cache_get, &cache,
                           ssl_cache_set, &cache );
#endif

    ssl_set_ca_chain( &s_ssl, srvcert.next, NULL, NULL );
    if( ( ret = ssl_set_own_cert( &s_ssl, &srvcert, &pkey ) ) != 0 )
    {
        printf( " failed\n  ! ssl_set_own_cert returned %d\n\n", ret );
        goto exit;
    }

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    ssl_session_reset( &s_ssl );

#if SOCKET_COMMUNICATION
    /*
     * Server:
     * Setup the listening TCP socket
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Bind on https://localhost:%d/ ...", SERVER_PORT );
        fflush( stdout );
    }

    if( ( ret = net_bind( &listen_fd, NULL, SERVER_PORT ) ) != 0 )
    {
        printf( " failed\n  ! net_bind returned %d\n\n", ret );
        goto exit;
    }

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Client:
     * Start the connection
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Connecting to tcp/%s/%d...", SERVER_NAME, SERVER_PORT );
        fflush( stdout );
    }

    if( ( ret = net_connect( &server_fd, SERVER_NAME,
                             SERVER_PORT ) ) != 0 )
    {
        printf( " failed\n  ! net_connect returned %d\n\n", ret );
        goto exit;
    }

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Server:
     * Start listening for client connections
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Waiting for a remote connection ..." );
        fflush( stdout );
    }

    /*
     * Server:
     * Accept client connection (socket is set non-blocking in
     * library/net.c)
     */
    if( ( ret = net_accept( listen_fd, &client_fd,
                            NULL ) ) != 0 )
    {
        printf( " failed\n  ! net_accept returned %d\n\n", ret );
        goto exit;
    }

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    ssl_set_bio( &s_ssl, recv_custom, &client_fd, send_custom, &client_fd );
#else
    ssl_set_bio( &s_ssl, func_server_recv_buf, NULL, func_server_send_buf, NULL );
#endif

    /*
     * Client:
     * Setup stuff
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Client: Setting up the SSL/TLS structure..." );
        fflush( stdout );
    }

    if( ( ret = ssl_init( &c_ssl ) ) != 0 )
    {
        polarssl_printf( " failed\n  ! ssl_init returned %d\n\n", ret );
        goto exit;
    }

    if( packet_in_num == 0 )
    {
        polarssl_printf( " ok\n" );
    }

    ssl_set_endpoint( &c_ssl, SSL_IS_CLIENT );
    /* OPTIONAL is not optimal for security,
     * but makes interop easier in this simplified example */
    ssl_set_authmode( &c_ssl, SSL_VERIFY_OPTIONAL );
    /* NONE permits man-in-the-middle attacks. */
    /*ssl_set_authmode( &c_ssl, VERIFY_NONE );*/
    /*ssl_set_authmode( &c_ssl, SSL_VERIFY_REQUIRED );*/
    ssl_set_ca_chain( &c_ssl, &srvcert, NULL, "PolarSSL Server 1" );

    /* SSLv3 is deprecated, set minimum to TLS 1.0 */
    ssl_set_min_version( &c_ssl, SSL_MAJOR_VERSION_3, SSL_MINOR_VERSION_1 );
    /* RC4 is deprecated, disable it */
    ssl_set_arc4_support( &c_ssl, SSL_ARC4_DISABLED );

    ssl_set_rng( &c_ssl, ctr_drbg_deterministic, NULL );
    ssl_set_dbg( &c_ssl, my_debug, stdout );

    if( ( ret = ssl_set_hostname( &c_ssl, "mbed TLS Server 1" ) ) != 0 )
    {
        printf( " failed\n  ! ssl_set_hostname returned %d\n\n", ret );
        goto exit;
    }

#if SOCKET_COMMUNICATION
    ssl_set_bio( &c_ssl, recv_custom, &server_fd, send_custom, &server_fd );
#else
    ssl_set_bio( &c_ssl, func_client_recv_buf, NULL, func_client_send_buf,  NULL );
#endif

    if( packet_in_num == 0 )
    {
        printf( "  . Performing the SSL/TLS handshake...\n" );
        fflush( stdout );
    }

    /*
     * The following number of steps are hardcoded to ensure
     * that the client and server complete the handshake without
     * waiting infinitely for the other side to send data.
     *
     *                     1  2  3  4  5  6  7  8  9
     */
    int client_steps[] = { 2, 1, 1, 1, 4, 2, 1, 1, 3 };
    int server_steps[] = { 3, 1, 1, 3, 2, 1, 2, 1, 2 };

    do {
        /*
         * Client:
         * Handshake step
         */
        int i;
        int no_steps;

        if( c_ssl.state == SSL_HANDSHAKE_OVER ) {
            no_steps = 0;
        } else {
            no_steps = client_steps[step - 1];
        }

        for (i = 0; i < no_steps; i++) {
            if(  ( ret = ssl_handshake_step( &c_ssl ) ) != 0 )
            {
                if(  ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
                {
                    printf( " failed\n  ! ssl_handshake returned -0x%x\n\n", -ret );
                    goto exit;
                }
            }
        }

        if( packet_in_num == 0 )
        {
            printf( "--- client handshake step %zd ok\n", step );
        }

        /*
         * Server:
         * Handshake step
         */
        if( s_ssl.state == SSL_HANDSHAKE_OVER ) {
            printf("over\n");
            no_steps = 0;
        } else {
            no_steps = server_steps[step - 1];
        }

        for (i = 0; i < no_steps; i++) {
            if(  ( ret = ssl_handshake_step( &s_ssl ) ) != 0 )
            {
                if(  ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
                {
                    printf( " failed\n  ! ssl_handshake returned %d\n\n", ret );
                    goto exit;
                }
            }
        }

        if( packet_in_num == 0 )
        {
            printf( "--- server handshake step %zd ok\n", step );
        }

        step++;
    } while( ((c_ssl.state != SSL_HANDSHAKE_OVER)
              || (s_ssl.state != SSL_HANDSHAKE_OVER))
             && (step <= MAX_HANDSHAKE_STEPS) );

    if( packet_in_num == 0 )
    {
        printf( "c_ssl.state: %d\n", c_ssl.state != SSL_HANDSHAKE_OVER );
        printf( "s_ssl.state: %d\n", s_ssl.state != SSL_HANDSHAKE_OVER );
    }

    /*
     * Client:
     * Verify the server certificate
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Verifying peer X.509 certificate..." );
    }

    /* In real life, we probably want to bail out when ret != 0 */
    if( ( flags = ssl_get_verify_result( &c_ssl ) ) != 0 )
    {
        char vrfy_buf[512];

        printf( " failed\n" );

        x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", flags );

        printf( "%s\n", vrfy_buf );
    }
    else if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Client:
     * Write the GET request
     */
    if( packet_in_num == 0 )
    {
        printf( "  > Write to server:" );
        fflush( stdout );
    }

    len = sprintf( (char *) buf, GET_REQUEST );

    while( ( ret = ssl_write( &c_ssl, buf, len ) ) <= 0 )
    {
        if( ret !=POLARSSL_ERR_NET_WANT_READ && ret !=POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_write returned %d\n\n", ret );
            goto exit;
        }
    }

    len = ret;
    if( packet_in_num == 0 )
    {
        printf( " %d bytes written\n\n%s", len, (char *) buf );
    }

    /*
     * Server:
     * Read the HTTP Request
     */
    if( packet_in_num == 0 )
    {
        printf( "  < Read from client:" );
        fflush( stdout );
    }

    do
    {
        len = sizeof( buf ) - 1;
        memset( buf, 0, sizeof( buf ) );
        ret = ssl_read( &s_ssl, buf, len );

        if( ret ==POLARSSL_ERR_NET_WANT_READ || ret ==POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret <= 0 )
        {
            switch( ret )
            {
            case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
                printf( " connection was closed gracefully\n" );
                break;

            case POLARSSL_ERR_NET_CONN_RESET:
                printf( " connection was reset by peer\n" );
                break;

            default:
                printf( " ssl_read returned -0x%x\n", -ret );
                break;
            }

            break;
        }

        len = ret;
        if( packet_in_num == 0 )
        {
            printf( " %d bytes read\n\n%s", len, (char *) buf );
        }

        if( ret > 0 )
            break;
    }
    while( 1 );

    /*
     * Server:
     * Write the 200 Response
     */
    if( packet_in_num == 0 )
    {
        printf( "  > Write to client:" );
        fflush( stdout );
    }

    len = sprintf( (char *) buf, HTTP_RESPONSE,
                   ssl_get_ciphersuite( &s_ssl ) );

    while( ( ret = ssl_write( &s_ssl, buf, len ) ) <= 0 )
    {
        if( ret == POLARSSL_ERR_NET_CONN_RESET )
        {
            printf( " failed\n  ! peer closed the connection\n\n" );
            goto exit;
        }

        if( ret != POLARSSL_ERR_NET_WANT_READ && ret != POLARSSL_ERR_NET_WANT_WRITE )
        {
            printf( " failed\n  ! ssl_write returned %d\n\n", ret );
            goto exit;
        }
    }

    len = ret;
    if( packet_in_num == 0 )
    {
        printf( " %d bytes written\n\n%s\n", len, (char *) buf );
    }

    /*
     * Client:
     * Read the HTTP response
     */
    if( packet_in_num == 0 )
    {
        printf( "  < Read from server:" );
        fflush( stdout );
    }

    do
    {
        len = sizeof( buf ) - 1;
        memset( buf, 0, sizeof( buf ) );
        ret = ssl_read( &c_ssl, buf, len );

        if( ret == POLARSSL_ERR_NET_WANT_READ || ret == POLARSSL_ERR_NET_WANT_WRITE )
            continue;

        if( ret == POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY )
        {
            ret = 0;
            break;
        }

        if( ret < 0 )
        {
            printf( "failed\n  ! ssl_read returned %d\n\n", ret );
            break;
        }

        if( ret == 0 )
        {
            printf( "\n\nEOF\n\n" );
            break;
        }

        len = ret;
        if( packet_in_num == 0 )
        {
            printf( " %d bytes read\n\n%s", len, (char *) buf );
        }

        /*
         * Server:
         * Client read response. Close connection.
         */
        if ( packet_in_num == 0 )
        {
            printf( "  . Closing the connection..." );
            fflush( stdout );
        }

        while( ( ret = ssl_close_notify( &s_ssl ) ) < 0 )
        {
            if( ret != POLARSSL_ERR_NET_WANT_READ &&
                    ret != POLARSSL_ERR_NET_WANT_WRITE )
            {
                printf( " failed\n  ! ssl_close_notify returned %d\n\n", ret );
                goto exit;
            }
        }

        if( packet_in_num == 0 )
        {
            printf( " ok\n" );
        }
    }
    while( 1 );

    /*
     * Client:
     * Close connection.
     */
    if( packet_in_num == 0 )
    {
        printf( "  . Closing the connection..." );
        fflush( stdout );
    }

    ssl_close_notify( &c_ssl );

    if( packet_in_num == 0 )
    {
        printf( " ok\n" );
    }

    /*
     * Server:
     * We do not have multiple clients and therefore do not goto reset.
     */
    /*ret = 0;*/
    /*goto reset;*/

exit:

#ifdef POLARSSL_ERROR_C
    if( ret != 0 )
    {
        char error_buf[100];
        polarssl_strerror( ret, error_buf, 100 );
        printf("Last error was: %d - %s\n\n", ret, error_buf );
    }
#endif

#if SOCKET_COMMUNICATION
    if ( client_fd != 1 )
        net_close( client_fd );
    if( server_fd != -1 )
        net_close( server_fd );
    if ( listen_fd != 1 )
        net_close( listen_fd );
#endif

    x509_crt_free( &srvcert );
    pk_free( &pkey );
    ssl_free( &s_ssl );
    ssl_free( &c_ssl );
#if defined(POLARSSL_SSL_CACHE_C)
    ssl_cache_free( &cache );
#endif

#if defined(_WIN32)
    printf( "  Press Enter to exit this program.\n" );
    fflush( stdout );
    getchar();
#endif

    return( ret );
}