Esempio n. 1
0
/*
 * X.509 cert verification callback
 *
 * XXX This is a stub to get you started, just printing some information.
 */
static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags )
{
    char buf[1024];
    struct vrfy_state *state = (struct vrfy_state *) data;

    mbedtls_printf( "\nVerify requested for (Depth %d):\n", depth );
    mbedtls_x509_crt_info( buf, sizeof( buf ), "    ", crt );
    mbedtls_printf( "%s", buf );

    x509_crt_pkhash( crt, buf, sizeof( buf ) );
    mbedtls_printf( "  Certificate public key hash: %s\n", buf );

    // TODO: check certificate against pins
    (void) state;

    if ( ( *flags ) == 0 )
        mbedtls_printf( "  This certificate has no issues\n" );
    else
    {
        mbedtls_x509_crt_verify_info( buf, sizeof( buf ), "  ! ", *flags );
        mbedtls_printf( "%s\n", buf );
    }

    return( 0 );
}
Esempio n. 2
0
static bool mbedtls_handshake_result(const pmbedtls_msg Threadmsg)
{
	if (Threadmsg == NULL)
		return false;

	if (Threadmsg->ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) {
		int ret = 0;
		if (Threadmsg->listen_fd.fd == -1)
			ret = ssl_option.client.cert_ca_sector.flag;
		else
			ret = ssl_option.server.cert_ca_sector.flag;

		if (ret == 1){
			ret = mbedtls_ssl_get_verify_result(&Threadmsg->ssl);
			if (ret != 0) {
				char vrfy_buf[512];
				os_memset(vrfy_buf, 0, sizeof(vrfy_buf)-1);
				mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "!", ret);
				os_printf("%s\n", vrfy_buf);
				Threadmsg->verify_result = ret;
				return false;
			} else
				return true;
		} else
			return true;
	}else
		return false;
}
Esempio n. 3
0
static int do_handshake( mbedtls_ssl_context *ssl )
{
    int ret;
    uint32_t flags;
    unsigned char buf[1024];
    memset(buf, 0, 1024);

    /*
     * 4. Handshake
     */
    mbedtls_printf( "  . Performing the SSL/TLS handshake..." );
    fflush( stdout );

    while( ( ret = mbedtls_ssl_handshake( ssl ) ) != 0 )
    {
        if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
        {
#if defined(MBEDTLS_ERROR_C)
            mbedtls_strerror( ret, (char *) buf, 1024 );
#endif
            mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned %d: %s\n\n", ret, buf );
            return( -1 );
        }
    }

    mbedtls_printf( " ok\n    [ Ciphersuite is %s ]\n",
            mbedtls_ssl_get_ciphersuite( ssl ) );

    /*
     * 5. Verify the server certificate
     */
    mbedtls_printf( "  . Verifying peer X.509 certificate..." );

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

        mbedtls_printf( " failed\n" );

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

        mbedtls_printf( "%s\n", vrfy_buf );
    }
    else
        mbedtls_printf( " ok\n" );

    mbedtls_printf( "  . Peer certificate information    ...\n" );
    mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
                   mbedtls_ssl_get_peer_cert( ssl ) );
    mbedtls_printf( "%s\n", buf );

    return( 0 );
}
Esempio n. 4
0
static void verify_certificate(esp_tls_t *tls)
{
    int flags;
    char buf[100];
    if ((flags = mbedtls_ssl_get_verify_result(&tls->ssl)) != 0) {
        ESP_LOGI(TAG, "Failed to verify peer certificate!");
        bzero(buf, sizeof(buf));
        mbedtls_x509_crt_verify_info(buf, sizeof(buf), "  ! ", flags);
        ESP_LOGI(TAG, "verification info: %s", buf);
    } else {
        ESP_LOGI(TAG, "Certificate verified.");
    }
}
Esempio n. 5
0
  static int my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags )
  {
    char buf[1024];
    ((void) data);  // some hokey way to say "UNUSED"???

    printf( "\nVerify requested for (Depth %d):\n", depth );
    mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt );
    printf( "%s", buf );

    if ( ( *flags ) == 0 )
      printf( "  This certificate has no flags\n" );
    else
      {
        mbedtls_x509_crt_verify_info( buf, sizeof( buf ), "  ! ", *flags );
        printf( "%s\n", buf );
      }

    return( 0 );
  }
Esempio n. 6
0
int ssl_socket_connect(void *state_data, void *data, bool timeout_enable, bool nonblock)
{
   struct ssl_state *state = (struct ssl_state*)state_data;
   int ret, flags;

   if (socket_connect(state->net_ctx.fd, data, timeout_enable))
      return -1;

   if (mbedtls_ssl_config_defaults(&state->conf,
               MBEDTLS_SSL_IS_CLIENT,
               MBEDTLS_SSL_TRANSPORT_STREAM,
               MBEDTLS_SSL_PRESET_DEFAULT) != 0)
      return -1;

   mbedtls_ssl_conf_authmode(&state->conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
   mbedtls_ssl_conf_ca_chain(&state->conf, &state->ca, NULL);
   mbedtls_ssl_conf_rng(&state->conf, mbedtls_ctr_drbg_random, &state->ctr_drbg);
   mbedtls_ssl_conf_dbg(&state->conf, ssl_debug, stderr);

   if (mbedtls_ssl_setup(&state->ctx, &state->conf) != 0)
      return -1;

#if defined(MBEDTLS_X509_CRT_PARSE_C)
   if (mbedtls_ssl_set_hostname(&state->ctx, state->domain) != 0)
      return -1;
#endif

   mbedtls_ssl_set_bio(&state->ctx, &state->net_ctx, mbedtls_net_send, mbedtls_net_recv, NULL);

   while ((ret = mbedtls_ssl_handshake(&state->ctx)) != 0)
   {
      if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
         return -1;
   }

   if ((flags = mbedtls_ssl_get_verify_result(&state->ctx)) != 0)
   {
      char vrfy_buf[512];
      mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);
   }

   return state->net_ctx.fd;
}
Esempio n. 7
0
int main( void )
{
    int ret, i;
    mbedtls_x509_crt cacert;
    mbedtls_x509_crl crl;
    char buf[10240];

    mbedtls_x509_crt_init( &cacert );
    mbedtls_x509_crl_init( &crl );

    /*
     * 1.1. Load the trusted CA
     */
    mbedtls_printf( "\n  . Loading the CA root certificate ..." );
    fflush( stdout );

    /*
     * Alternatively, you may load the CA certificates from a .pem or
     * .crt file by calling mbedtls_x509_crt_parse_file( &cacert, "myca.crt" ).
     */
    ret = mbedtls_x509_crt_parse_file( &cacert, "ssl/test-ca/test-ca.crt" );
    if( ret != 0 )
    {
        mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file returned %d\n\n", ret );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    mbedtls_x509_crt_info( buf, 1024, "CRT: ", &cacert );
    mbedtls_printf("%s\n", buf );

    /*
     * 1.2. Load the CRL
     */
    mbedtls_printf( "  . Loading the CRL ..." );
    fflush( stdout );

    ret = mbedtls_x509_crl_parse_file( &crl, "ssl/test-ca/crl.pem" );
    if( ret != 0 )
    {
        mbedtls_printf( " failed\n  !  mbedtls_x509_crl_parse_file returned %d\n\n", ret );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    mbedtls_x509_crl_info( buf, 1024, "CRL: ", &crl );
    mbedtls_printf("%s\n", buf );

    for( i = 0; i < MAX_CLIENT_CERTS; i++ )
    {
        /*
         * 1.3. Load own certificate
         */
        char    name[512];
        uint32_t flags;
        mbedtls_x509_crt clicert;
        mbedtls_pk_context pk;

        mbedtls_x509_crt_init( &clicert );
        mbedtls_pk_init( &pk );

        mbedtls_snprintf(name, 512, "ssl/test-ca/%s", client_certificates[i]);

        mbedtls_printf( "  . Loading the client certificate %s...", name );
        fflush( stdout );

        ret = mbedtls_x509_crt_parse_file( &clicert, name );
        if( ret != 0 )
        {
            mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse_file returned %d\n\n", ret );
            goto exit;
        }

        mbedtls_printf( " ok\n" );

        /*
         * 1.4. Verify certificate validity with CA certificate
         */
        mbedtls_printf( "  . Verify the client certificate with CA certificate..." );
        fflush( stdout );

        ret = mbedtls_x509_crt_verify( &clicert, &cacert, &crl, NULL, &flags, NULL,
                               NULL );
        if( ret != 0 )
        {
            if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED )
            {
                 char vrfy_buf[512];

                 mbedtls_printf( " failed\n" );
                 mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), "  ! ", flags );
                 mbedtls_printf( "%s\n", vrfy_buf );
             }
             else
             {
                mbedtls_printf( " failed\n  !  mbedtls_x509_crt_verify returned %d\n\n", ret );
                goto exit;
            }
        }

        mbedtls_printf( " ok\n" );

        /*
         * 1.5. Load own private key
         */
        mbedtls_snprintf(name, 512, "ssl/test-ca/%s", client_private_keys[i]);

        mbedtls_printf( "  . Loading the client private key %s...", name );
        fflush( stdout );

        ret = mbedtls_pk_parse_keyfile( &pk, name, NULL );
        if( ret != 0 )
        {
            mbedtls_printf( " failed\n  !  mbedtls_pk_parse_keyfile returned %d\n\n", ret );
            goto exit;
        }

        mbedtls_printf( " ok\n" );

        /*
         * 1.6. Verify certificate validity with private key
         */
        mbedtls_printf( "  . Verify the client certificate with private key..." );
        fflush( stdout );


        /* EC NOT IMPLEMENTED YET */
        if( ! mbedtls_pk_can_do( &clicert.pk, MBEDTLS_PK_RSA ) )
        {
            mbedtls_printf( " failed\n  !  certificate's key is not RSA\n\n" );
            ret = MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE;
            goto exit;
        }

        ret = mbedtls_mpi_cmp_mpi(&mbedtls_pk_rsa( pk )->N, &mbedtls_pk_rsa( clicert.pk )->N);
        if( ret != 0 )
        {
            mbedtls_printf( " failed\n  !  mbedtls_mpi_cmp_mpi for N returned %d\n\n", ret );
            goto exit;
        }

        ret = mbedtls_mpi_cmp_mpi(&mbedtls_pk_rsa( pk )->E, &mbedtls_pk_rsa( clicert.pk )->E);
        if( ret != 0 )
        {
            mbedtls_printf( " failed\n  !  mbedtls_mpi_cmp_mpi for E returned %d\n\n", ret );
            goto exit;
        }

        ret = mbedtls_rsa_check_privkey( mbedtls_pk_rsa( pk ) );
        if( ret != 0 )
        {
            mbedtls_printf( " failed\n  !  mbedtls_rsa_check_privkey returned %d\n\n", ret );
            goto exit;
        }

        mbedtls_printf( " ok\n" );

        mbedtls_x509_crt_free( &clicert );
        mbedtls_pk_free( &pk );
    }

exit:
    mbedtls_x509_crt_free( &cacert );
    mbedtls_x509_crl_free( &crl );

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

    return( ret );
}
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
	if(NULL == pNetwork) {
		return NULL_VALUE_ERROR;
	}

	if(NULL != params) {
		_iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation,
									params->pDevicePrivateKeyLocation, params->pDestinationURL,
									params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag);
	}

	int ret = 0;
	const char *pers = "aws_iot_tls_wrapper";
#ifdef IOT_DEBUG
	unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1];
#endif
	TLSDataParams *tlsDataParams = &(pNetwork->tlsDataParams);

	mbedtls_net_init(&(tlsDataParams->server_fd));
	mbedtls_ssl_init(&(tlsDataParams->ssl));
	mbedtls_ssl_config_init(&(tlsDataParams->conf));
	mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg));
	mbedtls_x509_crt_init(&(tlsDataParams->cacert));
	mbedtls_x509_crt_init(&(tlsDataParams->clicert));
	mbedtls_pk_init(&(tlsDataParams->pkey));

	DEBUG("\n  . Seeding the random number generator...");
	mbedtls_entropy_init(&(tlsDataParams->entropy));
	if ((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy),
										(const unsigned char *) pers, strlen(pers))) != 0) {
		ERROR(" failed\n  ! mbedtls_ctr_drbg_seed returned -0x%x\n", -ret);
		return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
	}

	DEBUG("  . Loading the CA root certificate ...");
	ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation);
	if (ret < 0) {
		ERROR(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x while parsing root cert\n\n", -ret);
		return NETWORK_X509_ROOT_CRT_PARSE_ERROR;
	} DEBUG(" ok (%d skipped)\n", ret);

	DEBUG("  . Loading the client cert. and key...");
	ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert), pNetwork->tlsConnectParams.pDeviceCertLocation);
	if (ret != 0) {
		ERROR(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x while parsing device cert\n\n", -ret);
		return NETWORK_X509_DEVICE_CRT_PARSE_ERROR;
	}

	ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey), pNetwork->tlsConnectParams.pDevicePrivateKeyLocation, "");
	if (ret != 0) {
		ERROR(" failed\n  !  mbedtls_pk_parse_key returned -0x%x while parsing private key\n\n", -ret);
		DEBUG(" path : %s ", pNetwork->tlsConnectParams.pDevicePrivateKeyLocation);
		return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR;
	} DEBUG(" ok\n");
	char portBuffer[6];
	snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort);
	DEBUG("  . Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer);
	if ((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL,
								   portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) {
		ERROR(" failed\n  ! mbedtls_net_connect returned -0x%x\n\n", -ret);
		switch(ret) {
			case MBEDTLS_ERR_NET_SOCKET_FAILED:
				return NETWORK_ERR_NET_SOCKET_FAILED;
			case MBEDTLS_ERR_NET_UNKNOWN_HOST:
				return NETWORK_ERR_NET_UNKNOWN_HOST;
			case MBEDTLS_ERR_NET_CONNECT_FAILED:
			default:
				return NETWORK_ERR_NET_CONNECT_FAILED;
		};
	}

	ret = mbedtls_net_set_block(&(tlsDataParams->server_fd));
	if (ret != 0) {
		ERROR(" failed\n  ! net_set_(non)block() returned -0x%x\n\n", -ret);
		return SSL_CONNECTION_ERROR;
	} DEBUG(" ok\n");

	DEBUG("  . Setting up the SSL/TLS structure...");
	if ((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
			MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret);
		return SSL_CONNECTION_ERROR;
	}

	mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL);
	if (pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
		mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
	} else {
		mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL);
	}
	mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg));

	mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL);
	if ((ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey))) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
		return SSL_CONNECTION_ERROR;
	}

	mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms);

	if ((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_setup returned -0x%x\n\n", -ret);
		return SSL_CONNECTION_ERROR;
	}
	if ((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
		return SSL_CONNECTION_ERROR;
	}
	DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state);
	mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL, mbedtls_net_recv_timeout);
	DEBUG(" ok\n");

	DEBUG("\n\nSSL state connect : %d ", tlsDataParams->ssl.state);
	DEBUG("  . Performing the SSL/TLS handshake...");
	while ((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) {
		if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
			ERROR(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n", -ret);
			if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
				ERROR("    Unable to verify the server's certificate. "
						"Either it is invalid,\n"
						"    or you didn't set ca_file or ca_path "
						"to an appropriate value.\n"
						"    Alternatively, you may want to use "
						"auth_mode=optional for testing purposes.\n");
			}
			return SSL_CONNECTION_ERROR;
		}
	}

	DEBUG(" ok\n    [ Protocol is %s ]\n    [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&(tlsDataParams->ssl)), mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl)));
	if ((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) {
		DEBUG("    [ Record expansion is %d ]\n", ret);
	} else {
		DEBUG("    [ Record expansion is unknown (compression) ]\n");
	}

	DEBUG("  . Verifying peer X.509 certificate...");

	if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
		if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) {
			char vrfy_buf[512];
			ERROR(" failed\n");
			mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", tlsDataParams->flags);
			ERROR("%s\n", vrfy_buf);
			ret = SSL_CONNECTION_ERROR;
		} else {
			DEBUG(" ok\n");
			ret = SUCCESS;
		}
	} else {
		DEBUG(" Server Verification skipped\n");
		ret = SUCCESS;
	}

#ifdef IOT_DEBUG
	if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) {
		DEBUG("  . Peer certificate information    ...\n");
		mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, "      ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)));
		DEBUG("%s\n", buf);
	}
#endif

	mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), IOT_SSL_READ_TIMEOUT);

	return ret;
}
Esempio n. 9
0
int dtlsclient_main( int argc, char *argv[] )
{
    int ret, len;
    mbedtls_net_context server_fd;
    uint32_t flags;
    unsigned char buf[1024];
    const char *pers = "dtls_client";
    int retry_left = MAX_RETRY;

    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    mbedtls_x509_crt cacert;
    mbedtls_timing_delay_context timer;

    ((void) argc);
    ((void) argv);

#if defined(MBEDTLS_DEBUG_C)
    mbedtls_debug_set_threshold( DEBUG_LEVEL );
#endif

    /*
     * 0. Initialize the RNG and the session data
     */
    mbedtls_net_init( &server_fd );
    mbedtls_ssl_init( &ssl );
    mbedtls_ssl_config_init( &conf );
    mbedtls_x509_crt_init( &cacert );
    mbedtls_ctr_drbg_init( &ctr_drbg );

    mbedtls_printf( "\n  . Seeding the random number generator..." );
    fflush( stdout );

    mbedtls_entropy_init( &entropy );
    if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
                               (const unsigned char *) pers,
                               strlen( pers ) ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    /*
     * 0. Load certificates
     */
    mbedtls_printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

    ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
                          mbedtls_test_cas_pem_len );
    if( ret < 0 )
    {
        mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
        goto exit;
    }

    mbedtls_printf( " ok (%d skipped)\n", ret );

    /*
     * 1. Start the connection
     */
    mbedtls_printf( "  . Connecting to udp/%s/%s...", SERVER_NAME, SERVER_PORT );
    fflush( stdout );

    if( ( ret = mbedtls_net_connect( &server_fd, SERVER_ADDR,
                                         SERVER_PORT, MBEDTLS_NET_PROTO_UDP ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_net_connect returned %d\n\n", ret );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    /*
     * 2. Setup stuff
     */
    mbedtls_printf( "  . Setting up the DTLS structure..." );
    fflush( stdout );

    if( ( ret = mbedtls_ssl_config_defaults( &conf,
                   MBEDTLS_SSL_IS_CLIENT,
                   MBEDTLS_SSL_TRANSPORT_DATAGRAM,
                   MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
        goto exit;
    }

    /* OPTIONAL is usually a bad choice for security, but makes interop easier
     * in this simplified example, in which the ca chain is hardcoded.
     * Production code should set a proper ca chain and use REQUIRED. */
    mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
    mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
    mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
    mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );

    if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret );
        goto exit;
    }

    if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret );
        goto exit;
    }

    mbedtls_ssl_set_bio( &ssl, &server_fd,
                         mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout );

    mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
                                            mbedtls_timing_get_delay );

    mbedtls_printf( " ok\n" );

    /*
     * 4. Handshake
     */
    mbedtls_printf( "  . Performing the SSL/TLS handshake..." );
    fflush( stdout );

    do ret = mbedtls_ssl_handshake( &ssl );
    while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
           ret == MBEDTLS_ERR_SSL_WANT_WRITE );

    if( ret != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
        goto exit;
    }

    mbedtls_printf( " ok\n" );

    /*
     * 5. Verify the server certificate
     */
    mbedtls_printf( "  . Verifying peer X.509 certificate..." );

    /* In real life, we would have used MBEDTLS_SSL_VERIFY_REQUIRED so that the
     * handshake would not succeed if the peer's cert is bad.  Even if we used
     * MBEDTLS_SSL_VERIFY_OPTIONAL, we would bail out here if ret != 0 */
    if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 )
    {
        char vrfy_buf[512];

        mbedtls_printf( " failed\n" );

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

        mbedtls_printf( "%s\n", vrfy_buf );
    }
    else
        mbedtls_printf( " ok\n" );

    /*
     * 6. Write the echo request
     */
send_request:
    mbedtls_printf( "  > Write to server:" );
    fflush( stdout );

    len = sizeof( MESSAGE ) - 1;

    do ret = mbedtls_ssl_write( &ssl, (unsigned char *) MESSAGE, len );
    while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
           ret == MBEDTLS_ERR_SSL_WANT_WRITE );

    if( ret < 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_write returned %d\n\n", ret );
        goto exit;
    }

    len = ret;
    mbedtls_printf( " %d bytes written\n\n%s\n\n", len, MESSAGE );

    /*
     * 7. Read the echo response
     */
    mbedtls_printf( "  < Read from server:" );
    fflush( stdout );

    len = sizeof( buf ) - 1;
    memset( buf, 0, sizeof( buf ) );

    do ret = mbedtls_ssl_read( &ssl, buf, len );
    while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
           ret == MBEDTLS_ERR_SSL_WANT_WRITE );

    if( ret <= 0 )
    {
        switch( ret )
        {
            case MBEDTLS_ERR_SSL_TIMEOUT:
                mbedtls_printf( " timeout\n\n" );
                if( retry_left-- > 0 )
                    goto send_request;
                goto exit;

            case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
                mbedtls_printf( " connection was closed gracefully\n" );
                ret = 0;
                goto close_notify;

            default:
                mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n\n", -ret );
                goto exit;
        }
    }

    len = ret;
    mbedtls_printf( " %d bytes read\n\n%s\n\n", len, buf );

    /*
     * 8. Done, cleanly close the connection
     */
close_notify:
    mbedtls_printf( "  . Closing the connection..." );

    /* No error checking, the connection might be closed already */
    do ret = mbedtls_ssl_close_notify( &ssl );
    while( ret == MBEDTLS_ERR_SSL_WANT_WRITE );
    ret = 0;

    mbedtls_printf( " done\n" );

    /*
     * 9. Final clean-ups and exit
     */
exit:

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

    mbedtls_net_free( &server_fd );

    mbedtls_x509_crt_free( &cacert );
    mbedtls_ssl_free( &ssl );
    mbedtls_ssl_config_free( &conf );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );

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

    /* Shell can not handle large exit numbers -> 1 for errors */
    if( ret < 0 )
        ret = 1;

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

    mbedtls_ssl_context s_ssl, c_ssl;
    mbedtls_ssl_config s_conf, c_conf;
    mbedtls_x509_crt srvcert;
    mbedtls_pk_context pkey;
#if defined(MBEDTLS_SSL_CACHE_C)
    mbedtls_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 */
#if SOCKET_COMMUNICATION
    mbedtls_net_init( &listen_fd );
    mbedtls_net_init( &client_fd );
#endif
    mbedtls_ssl_init( &s_ssl );
    mbedtls_ssl_config_init( &s_conf );
#if defined(MBEDTLS_SSL_CACHE_C)
    mbedtls_ssl_cache_init( &cache );
#endif
    mbedtls_x509_crt_init( &srvcert );
    mbedtls_pk_init( &pkey );

    /* Client init */
#if SOCKET_COMMUNICATION
    mbedtls_net_init( &server_fd );
#endif
    mbedtls_ssl_init( &c_ssl );
    mbedtls_ssl_config_init( &c_conf );
    /*mbedtls_x509_crt_init( &cacert );*/

#if defined(MBEDTLS_DEBUG_C)
    mbedtls_debug_set_threshold( DEBUG_LEVEL );
#endif

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

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

    ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_cas_pem,
            mbedtls_test_cas_pem_len );
    if( ret != 0 )
    {
        mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret );
        goto exit;
    }

    ret =  mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key,
            mbedtls_test_srv_key_len, NULL, 0 );
    if( ret != 0 )
    {
        mbedtls_printf( " failed\n  !  mbedtls_pk_parse_key returned %d\n\n", ret );
        goto exit;
    }

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

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

    if( ( ret = mbedtls_ssl_config_defaults( &s_conf,
                    MBEDTLS_SSL_IS_SERVER,
                    MBEDTLS_SSL_TRANSPORT_STREAM,
                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
        goto exit;
    }

    mbedtls_ssl_conf_rng( &s_conf, mbedtls_ctr_drbg_deterministic, NULL );
    mbedtls_ssl_conf_dbg( &s_conf, my_debug, stdout );

#if defined(MBEDTLS_SSL_CACHE_C)
    mbedtls_ssl_conf_session_cache( &s_conf, &cache,
            mbedtls_ssl_cache_get,
            mbedtls_ssl_cache_set );
#endif

    mbedtls_ssl_conf_ca_chain( &s_conf, srvcert.next, NULL );
    if( ( ret = mbedtls_ssl_conf_own_cert( &s_conf, &srvcert, &pkey ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
        goto exit;
    }

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

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

    mbedtls_ssl_session_reset( &s_ssl );

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

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

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

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

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

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

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

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

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

    mbedtls_ssl_set_bio( &s_ssl, &client_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL );
#else
    mbedtls_ssl_set_bio( &s_ssl, NULL, mbedtls_server_send_buf, mbedtls_server_recv_buf, NULL );
#endif

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

    if( ( ret = mbedtls_ssl_config_defaults( &c_conf,
                    MBEDTLS_SSL_IS_CLIENT,
                    MBEDTLS_SSL_TRANSPORT_STREAM,
                    MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
    {
        mbedtls_printf( " failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
        goto exit;
    }

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

    /* OPTIONAL is not optimal for security,
     * but makes interop easier in this simplified example */
    mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
    /* NONE permits man-in-the-middle attacks. */
    /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_NONE );*/
    /*mbedtls_ssl_conf_authmode( &c_conf, MBEDTLS_SSL_VERIFY_REQUIRED );*/
    mbedtls_ssl_conf_ca_chain( &c_conf, &srvcert, NULL );
    mbedtls_ssl_conf_rng( &c_conf, mbedtls_ctr_drbg_deterministic, NULL );
    mbedtls_ssl_conf_dbg( &c_conf, my_debug, stdout );

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

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

#if SOCKET_COMMUNICATION
    mbedtls_ssl_set_bio( &c_ssl, &server_fd, mbedtls_send_custom, mbedtls_recv_custom, NULL );
#else
    mbedtls_ssl_set_bio( &c_ssl, NULL, mbedtls_client_send_buf, mbedtls_client_recv_buf, NULL );
#endif

    if( packet_in_num == 0 )
    {
        mbedtls_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  10
     */
    int client_steps[] = { 2, 1, 1, 1, 4, 2, 1, 1, 2, 1 };
    int server_steps[] = { 3, 1, 1, 2, 3, 1, 2, 1, 1, 1 };

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

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

        for (i = 0; i < no_steps; i++) {
            if(  ( ret = mbedtls_ssl_handshake_step( &c_ssl ) ) != 0 )
            {
                if(  ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
                {
                    mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret );
                    goto exit;
                }
            }
        }

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

        /*
         * Server:
         * Handshake step
         */
        if( s_ssl.state == MBEDTLS_SSL_HANDSHAKE_OVER) {
            no_steps = 0;
        } else {
            no_steps = server_steps[step - 1];
        }

        for (i = 0; i < no_steps; i++) {
            if(  ( ret = mbedtls_ssl_handshake_step( &s_ssl ) ) != 0 )
            {
                if(  ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
                {
                    mbedtls_printf( " failed\n  ! mbedtls_ssl_handshake returned %d\n\n", ret );
                    goto exit;
                }
            }
        }

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

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

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

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

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

        mbedtls_printf( " failed\n" );

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

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

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

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

    while( ( ret = mbedtls_ssl_write( &c_ssl, buf, len ) ) <= 0 )
    {
        if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
        {
            mbedtls_printf( " failed\n  ! mbedtls_ssl_write returned %d\n\n", ret );
            goto exit;
        }
    }

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

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

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

        if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
            continue;

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

                case MBEDTLS_ERR_NET_CONN_RESET:
                    mbedtls_printf( " connection was reset by peer\n" );
                    break;

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

            break;
        }

        len = ret;
        if( packet_in_num == 0 )
        {
            mbedtls_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 )
    {
        mbedtls_printf( "  > Write to client:" );
        fflush( stdout );
    }

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

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

        if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
        {
            mbedtls_printf( " failed\n  ! mbedtls_ssl_write returned %d\n\n", ret );
            goto exit;
        }
    }

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

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

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

        if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
            continue;

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

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

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

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

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

        while( ( ret = mbedtls_ssl_close_notify( &s_ssl ) ) < 0 )
        {
            if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
                    ret != MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                mbedtls_printf( " failed\n  ! mbedtls_ssl_close_notify returned %d\n\n", ret );
                goto exit;
            }
        }

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

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

    mbedtls_ssl_close_notify( &c_ssl );

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

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

exit:

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

#if SOCKET_COMMUNICATION
    mbedtls_net_free( &client_fd );
    mbedtls_net_free( &listen_fd );
    mbedtls_net_free( &server_fd );
#endif

    mbedtls_x509_crt_free( &srvcert );
    mbedtls_pk_free( &pkey );
    mbedtls_ssl_free( &s_ssl );
    mbedtls_ssl_free( &c_ssl );
    mbedtls_ssl_config_free( &s_conf );
    mbedtls_ssl_config_free( &c_conf );
#if defined(MBEDTLS_SSL_CACHE_C)
    mbedtls_ssl_cache_free( &cache );
#endif

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

    return( ret );
}
static void https_get_task(void *pvParameters)
{
    char buf[512];
    int ret, flags, len;

    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
    mbedtls_x509_crt cacert;
    mbedtls_ssl_config conf;
    mbedtls_net_context server_fd;

    mbedtls_ssl_init(&ssl);
    mbedtls_x509_crt_init(&cacert);
    mbedtls_ctr_drbg_init(&ctr_drbg);
    ESP_LOGI(TAG, "Seeding the random number generator");

    mbedtls_ssl_config_init(&conf);

    mbedtls_entropy_init(&entropy);
    if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                                    NULL, 0)) != 0)
    {
        ESP_LOGE(TAG, "mbedtls_ctr_drbg_seed returned %d", ret);
        abort();
    }

    ESP_LOGI(TAG, "Loading the CA root certificate...");

    ret = mbedtls_x509_crt_parse(&cacert, server_root_cert_pem_start,
                                 server_root_cert_pem_end-server_root_cert_pem_start);

    if(ret < 0)
    {
        ESP_LOGE(TAG, "mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
        abort();
    }

    ESP_LOGI(TAG, "Setting hostname for TLS session...");

     /* Hostname set here should match CN in server certificate */
    if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0)
    {
        ESP_LOGE(TAG, "mbedtls_ssl_set_hostname returned -0x%x", -ret);
        abort();
    }

    ESP_LOGI(TAG, "Setting up the SSL/TLS structure...");

    if((ret = mbedtls_ssl_config_defaults(&conf,
                                          MBEDTLS_SSL_IS_CLIENT,
                                          MBEDTLS_SSL_TRANSPORT_STREAM,
                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
    {
        ESP_LOGE(TAG, "mbedtls_ssl_config_defaults returned %d", ret);
        goto exit;
    }

    /* MBEDTLS_SSL_VERIFY_OPTIONAL is bad for security, in this example it will print
       a warning if CA verification fails but it will continue to connect.

       You should consider using MBEDTLS_SSL_VERIFY_REQUIRED in your own code.
    */
    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
    mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
    mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
#ifdef CONFIG_MBEDTLS_DEBUG
    mbedtls_esp_enable_debug_log(&conf, 4);
#endif

    if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
    {
        ESP_LOGE(TAG, "mbedtls_ssl_setup returned -0x%x\n\n", -ret);
        goto exit;
    }

    while(1) {
        /* Wait for the callback to set the CONNECTED_BIT in the
           event group.
        */
        xEventGroupWaitBits(wifi_event_group, CONNECTED_BIT,
                            false, true, portMAX_DELAY);
        ESP_LOGI(TAG, "Connected to AP");

        mbedtls_net_init(&server_fd);

        ESP_LOGI(TAG, "Connecting to %s:%s...", WEB_SERVER, WEB_PORT);

        if ((ret = mbedtls_net_connect(&server_fd, WEB_SERVER,
                                      WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0)
        {
            ESP_LOGE(TAG, "mbedtls_net_connect returned -%x", -ret);
            goto exit;
        }

        ESP_LOGI(TAG, "Connected.");

        mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

        ESP_LOGI(TAG, "Performing the SSL/TLS handshake...");

        while ((ret = mbedtls_ssl_handshake(&ssl)) != 0)
        {
            if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
            {
                ESP_LOGE(TAG, "mbedtls_ssl_handshake returned -0x%x", -ret);
                goto exit;
            }
        }

        ESP_LOGI(TAG, "Verifying peer X.509 certificate...");

        if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0)
        {
            /* In real life, we probably want to close connection if ret != 0 */
            ESP_LOGW(TAG, "Failed to verify peer certificate!");
            bzero(buf, sizeof(buf));
            mbedtls_x509_crt_verify_info(buf, sizeof(buf), "  ! ", flags);
            ESP_LOGW(TAG, "verification info: %s", buf);
        }
        else {
            ESP_LOGI(TAG, "Certificate verified.");
        }

        ESP_LOGI(TAG, "Cipher suite is %s", mbedtls_ssl_get_ciphersuite(&ssl));

        ESP_LOGI(TAG, "Writing HTTP request...");

        size_t written_bytes = 0;
        do {
            ret = mbedtls_ssl_write(&ssl,
                                    (const unsigned char *)REQUEST + written_bytes,
                                    strlen(REQUEST) - written_bytes);
            if (ret >= 0) {
                ESP_LOGI(TAG, "%d bytes written", ret);
                written_bytes += ret;
            } else if (ret != MBEDTLS_ERR_SSL_WANT_WRITE && ret != MBEDTLS_ERR_SSL_WANT_READ) {
                ESP_LOGE(TAG, "mbedtls_ssl_write returned -0x%x", -ret);
                goto exit;
            }
        } while(written_bytes < strlen(REQUEST));

        ESP_LOGI(TAG, "Reading HTTP response...");

        do
        {
            len = sizeof(buf) - 1;
            bzero(buf, sizeof(buf));
            ret = mbedtls_ssl_read(&ssl, (unsigned char *)buf, len);

            if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
                continue;

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

            if(ret < 0)
            {
                ESP_LOGE(TAG, "mbedtls_ssl_read returned -0x%x", -ret);
                break;
            }

            if(ret == 0)
            {
                ESP_LOGI(TAG, "connection closed");
                break;
            }

            len = ret;
            ESP_LOGD(TAG, "%d bytes read", len);
            /* Print response directly to stdout as it is read */
            for(int i = 0; i < len; i++) {
                putchar(buf[i]);
            }
        } while(1);

        mbedtls_ssl_close_notify(&ssl);

    exit:
        mbedtls_ssl_session_reset(&ssl);
        mbedtls_net_free(&server_fd);

        if(ret != 0)
        {
            mbedtls_strerror(ret, buf, 100);
            ESP_LOGE(TAG, "Last error was: -0x%x - %s", -ret, buf);
        }

        putchar('\n'); // JSON output doesn't have a newline at end

        static int request_count;
        ESP_LOGI(TAG, "Completed %d requests", ++request_count);

        for(int countdown = 10; countdown >= 0; countdown--) {
            ESP_LOGI(TAG, "%d...", countdown);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
        ESP_LOGI(TAG, "Starting again!");
    }
}
Esempio n. 12
0
mbedtls_x509_crt *load_cert_file( const char *ca_file, const char *certfile )
{
    int ret = 0;
    unsigned char buf[1024];
    mbedtls_net_context server_fd;
    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
    mbedtls_ssl_config conf;
    mbedtls_x509_crt cacert;
    mbedtls_x509_crt *cur;
    mbedtls_x509_crt *cert;
    mbedtls_pk_context pkey;
    int i;
    uint32_t flags;
    int verify = 0;
    char *p, *q;

    /*
     * Set to sane values
     */
    cert = (mbedtls_x509_crt *)mbedtls_calloc(1, sizeof(*cert));
    cur  = cert;
    mbedtls_x509_crt_init( cert );
    mbedtls_ctr_drbg_init( &ctr_drbg );
    mbedtls_x509_crt_init( &cacert );

    /* Zeroize structure as CRL parsing is not supported and we have to pass
       it to the verify function */
    mbedtls_pk_init( &pkey );

    /*
     * 1.1. Load the trusted CA
     */
    mbedtls_printf( "  . Loading the CA root certificate ..." );
    fflush( stdout );

    ret = mbedtls_x509_crt_parse_file( &cacert, ca_file );

    if( ret < 0 )
    {
      fprintf(stderr, " failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret );
      return NULL;
    }

    mbedtls_printf( " ok (%d skipped)\n", ret );

    /*
     * 1.1. Load the certificate(s)
     */
    printf( "\n  . Loading the certificate at: %s ...", certfile);

    ret = mbedtls_x509_crt_parse_file( cert, certfile );

    if( ret < 0 )
      {
        char errorbuf[256];
        mbedtls_strerror( ret, errorbuf, sizeof(errorbuf));
        printf( " failed\n  !  mbedtls_x509_crt_parse_file returned %d: %s\n\n", ret, errorbuf );

        mbedtls_x509_crt_free( cert );
        goto exit;
      }

    printf( " ok\n" );

    /*
     * 1.2 Print the certificate(s)
     */
    while( cur != NULL )
      {
        printf( "  . Peer certificate information    ...\n" );
        ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, "      ",
                                     cur );
        if( ret == -1 )
          {
            printf( " failed\n  !  mbedtls_x509_crt_info returned %d\n\n", ret );
            goto exit;
          }

        printf( "%s\n", buf );

        cur = cur->next;
      }

    ret = 0;

    /*
     * 1.3 Verify the certificate
     */
    printf( "  . Verifying X.509 certificate..." );

    if( ( ret = mbedtls_x509_crt_verify( cert, &cacert, NULL, NULL, &flags,
                                         my_verify, NULL ) ) != 0 )
      {
        char vrfy_buf[512];

        printf( " failed\n" );

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

        printf( "%s\n", vrfy_buf );
        goto exit;
      }
    else
      printf( " ok\n" );


exit:
    //mbedtls_net_free( &server_fd );
    mbedtls_x509_crt_free( &cacert );
    mbedtls_pk_free( &pkey );
    mbedtls_ctr_drbg_free( &ctr_drbg );
    mbedtls_entropy_free( &entropy );

    if( ret < 0 ) {
      mbedtls_x509_crt_free( cert );
      mbedtls_free(cert);
      return NULL;
    }

    return cert;
}
Esempio n. 13
0
void WiiSocket::Update(bool read, bool write, bool except)
{
  auto it = pending_sockops.begin();
  while (it != pending_sockops.end())
  {
    s32 ReturnValue = 0;
    bool forceNonBlock = false;
    IPCCommandType ct = static_cast<IPCCommandType>(Memory::Read_U32(it->_CommandAddress));
    if (!it->is_ssl && ct == IPC_CMD_IOCTL)
    {
      u32 BufferIn = Memory::Read_U32(it->_CommandAddress + 0x10);
      u32 BufferInSize = Memory::Read_U32(it->_CommandAddress + 0x14);
      u32 BufferOut = Memory::Read_U32(it->_CommandAddress + 0x18);
      u32 BufferOutSize = Memory::Read_U32(it->_CommandAddress + 0x1C);

      switch (it->net_type)
      {
      case IOCTL_SO_FCNTL:
      {
        u32 cmd = Memory::Read_U32(BufferIn + 4);
        u32 arg = Memory::Read_U32(BufferIn + 8);
        ReturnValue = FCntl(cmd, arg);
        break;
      }
      case IOCTL_SO_BIND:
      {
        // u32 has_addr = Memory::Read_U32(BufferIn + 0x04);
        sockaddr_in local_name;
        WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn + 0x08);
        WiiSockMan::Convert(*wii_name, local_name);

        int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name));
        ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_BIND", false);

        INFO_LOG(WII_IPC_NET, "IOCTL_SO_BIND (%08X %s:%d) = %d ", fd,
                 inet_ntoa(local_name.sin_addr), Common::swap16(local_name.sin_port), ret);
        break;
      }
      case IOCTL_SO_CONNECT:
      {
        // u32 has_addr = Memory::Read_U32(BufferIn + 0x04);
        sockaddr_in local_name;
        WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn + 0x08);
        WiiSockMan::Convert(*wii_name, local_name);

        int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name));
        ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_CONNECT", false);

        INFO_LOG(WII_IPC_NET, "IOCTL_SO_CONNECT (%08x, %s:%d)", fd, inet_ntoa(local_name.sin_addr),
                 Common::swap16(local_name.sin_port));
        break;
      }
      case IOCTL_SO_ACCEPT:
      {
        if (BufferOutSize > 0)
        {
          sockaddr_in local_name;
          WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut);
          WiiSockMan::Convert(*wii_name, local_name);

          socklen_t addrlen = sizeof(sockaddr_in);
          int ret = (s32)accept(fd, (sockaddr*)&local_name, &addrlen);
          ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_ACCEPT", true);

          WiiSockMan::Convert(local_name, *wii_name, addrlen);
        }
        else
        {
          int ret = (s32)accept(fd, nullptr, nullptr);
          ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_ACCEPT", true);
        }

        WiiSockMan::GetInstance().AddSocket(ReturnValue);

        INFO_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT "
                              "BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
                 BufferIn, BufferInSize, BufferOut, BufferOutSize);

        break;
      }
      default:
        break;
      }

      // Fix blocking error codes
      if (!nonBlock)
      {
        if (it->net_type == IOCTL_SO_CONNECT && ReturnValue == -SO_EISCONN)
        {
          ReturnValue = SO_SUCCESS;
        }
      }
    }
    else if (ct == IPC_CMD_IOCTLV)
    {
      SIOCtlVBuffer CommandBuffer(it->_CommandAddress);
      u32 BufferIn = 0, BufferIn2 = 0;
      u32 BufferInSize = 0, BufferInSize2 = 0;
      u32 BufferOut = 0, BufferOut2 = 0;
      u32 BufferOutSize = 0, BufferOutSize2 = 0;

      if (CommandBuffer.InBuffer.size() > 0)
      {
        BufferIn = CommandBuffer.InBuffer.at(0).m_Address;
        BufferInSize = CommandBuffer.InBuffer.at(0).m_Size;
      }

      if (CommandBuffer.PayloadBuffer.size() > 0)
      {
        BufferOut = CommandBuffer.PayloadBuffer.at(0).m_Address;
        BufferOutSize = CommandBuffer.PayloadBuffer.at(0).m_Size;
      }

      if (CommandBuffer.PayloadBuffer.size() > 1)
      {
        BufferOut2 = CommandBuffer.PayloadBuffer.at(1).m_Address;
        BufferOutSize2 = CommandBuffer.PayloadBuffer.at(1).m_Size;
      }

      if (CommandBuffer.InBuffer.size() > 1)
      {
        BufferIn2 = CommandBuffer.InBuffer.at(1).m_Address;
        BufferInSize2 = CommandBuffer.InBuffer.at(1).m_Size;
      }

      if (it->is_ssl)
      {
        int sslID = Memory::Read_U32(BufferOut) - 1;
        if (SSLID_VALID(sslID))
        {
          switch (it->ssl_type)
          {
          case IOCTLV_NET_SSL_DOHANDSHAKE:
          {
            mbedtls_ssl_context* ctx = &CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx;
            int ret = mbedtls_ssl_handshake(ctx);
            if (ret)
            {
              char error_buffer[256] = "";
              mbedtls_strerror(ret, error_buffer, sizeof(error_buffer));
              ERROR_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE: %s", error_buffer);
            }
            switch (ret)
            {
            case 0:
              Memory::Write_U32(SSL_OK, BufferIn);
              break;
            case MBEDTLS_ERR_SSL_WANT_READ:
              Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn);
              if (!nonBlock)
                ReturnValue = SSL_ERR_RAGAIN;
              break;
            case MBEDTLS_ERR_SSL_WANT_WRITE:
              Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn);
              if (!nonBlock)
                ReturnValue = SSL_ERR_WAGAIN;
              break;
            case MBEDTLS_ERR_X509_CERT_VERIFY_FAILED:
            {
              char error_buffer[256] = "";
              int res = mbedtls_ssl_get_verify_result(ctx);
              mbedtls_x509_crt_verify_info(error_buffer, sizeof(error_buffer), "", res);
              ERROR_LOG(WII_IPC_SSL, "MBEDTLS_ERR_X509_CERT_VERIFY_FAILED (verify_result = %d): %s",
                        res, error_buffer);

              if (res & MBEDTLS_X509_BADCERT_CN_MISMATCH)
                res = SSL_ERR_VCOMMONNAME;
              else if (res & MBEDTLS_X509_BADCERT_NOT_TRUSTED)
                res = SSL_ERR_VROOTCA;
              else if (res & MBEDTLS_X509_BADCERT_REVOKED)
                res = SSL_ERR_VCHAIN;
              else if (res & MBEDTLS_X509_BADCERT_EXPIRED || res & MBEDTLS_X509_BADCERT_FUTURE)
                res = SSL_ERR_VDATE;
              else
                res = SSL_ERR_FAILED;

              Memory::Write_U32(res, BufferIn);
              if (!nonBlock)
                ReturnValue = res;
              break;
            }
            default:
              Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
              break;
            }

            // mbedtls_ssl_get_peer_cert(ctx) seems not to work if handshake failed
            // Below is an alternative to dump the peer certificate
            if (SConfig::GetInstance().m_SSLDumpPeerCert && ctx->session_negotiate != nullptr)
            {
              const mbedtls_x509_crt* cert = ctx->session_negotiate->peer_cert;
              if (cert != nullptr)
              {
                std::string filename = File::GetUserPath(D_DUMPSSL_IDX) +
                                       ((ctx->hostname != nullptr) ? ctx->hostname : "") +
                                       "_peercert.der";
                File::IOFile(filename, "wb").WriteBytes(cert->raw.p, cert->raw.len);
              }
            }

            INFO_LOG(WII_IPC_SSL, "IOCTLV_NET_SSL_DOHANDSHAKE = (%d) "
                                  "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
                                  "BufferOut: (%08x, %i), BufferOut2: (%08x, %i)",
                     ret, BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferOut,
                     BufferOutSize, BufferOut2, BufferOutSize2);
            break;
          }
          case IOCTLV_NET_SSL_WRITE:
          {
            int ret = mbedtls_ssl_write(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx,
                                        Memory::GetPointer(BufferOut2), BufferOutSize2);

            if (SConfig::GetInstance().m_SSLDumpWrite && ret > 0)
            {
              std::string filename = File::GetUserPath(D_DUMPSSL_IDX) +
                                     SConfig::GetInstance().GetGameID() + "_write.bin";
              File::IOFile(filename, "ab").WriteBytes(Memory::GetPointer(BufferOut2), ret);
            }

            if (ret >= 0)
            {
              // Return bytes written or SSL_ERR_ZERO if none
              Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
            }
            else
            {
              switch (ret)
              {
              case MBEDTLS_ERR_SSL_WANT_READ:
                Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn);
                if (!nonBlock)
                  ReturnValue = SSL_ERR_RAGAIN;
                break;
              case MBEDTLS_ERR_SSL_WANT_WRITE:
                Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn);
                if (!nonBlock)
                  ReturnValue = SSL_ERR_WAGAIN;
                break;
              default:
                Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
                break;
              }
            }
            break;
          }
          case IOCTLV_NET_SSL_READ:
          {
            int ret = mbedtls_ssl_read(&CWII_IPC_HLE_Device_net_ssl::_SSL[sslID].ctx,
                                       Memory::GetPointer(BufferIn2), BufferInSize2);

            if (SConfig::GetInstance().m_SSLDumpRead && ret > 0)
            {
              std::string filename = File::GetUserPath(D_DUMPSSL_IDX) +
                                     SConfig::GetInstance().GetGameID() + "_read.bin";
              File::IOFile(filename, "ab").WriteBytes(Memory::GetPointer(BufferIn2), ret);
            }

            if (ret >= 0)
            {
              // Return bytes read or SSL_ERR_ZERO if none
              Memory::Write_U32((ret == 0) ? SSL_ERR_ZERO : ret, BufferIn);
            }
            else
            {
              switch (ret)
              {
              case MBEDTLS_ERR_SSL_WANT_READ:
                Memory::Write_U32(SSL_ERR_RAGAIN, BufferIn);
                if (!nonBlock)
                  ReturnValue = SSL_ERR_RAGAIN;
                break;
              case MBEDTLS_ERR_SSL_WANT_WRITE:
                Memory::Write_U32(SSL_ERR_WAGAIN, BufferIn);
                if (!nonBlock)
                  ReturnValue = SSL_ERR_WAGAIN;
                break;
              default:
                Memory::Write_U32(SSL_ERR_FAILED, BufferIn);
                break;
              }
            }
            break;
          }
          default:
            break;
          }
        }
        else
        {
          Memory::Write_U32(SSL_ERR_ID, BufferIn);
        }
      }
      else
      {
        switch (it->net_type)
        {
        case IOCTLV_SO_SENDTO:
        {
          u32 flags = Memory::Read_U32(BufferIn2 + 0x04);
          u32 has_destaddr = Memory::Read_U32(BufferIn2 + 0x08);

          // Not a string, Windows requires a const char* for sendto
          const char* data = (const char*)Memory::GetPointer(BufferIn);

          // Act as non blocking when SO_MSG_NONBLOCK is specified
          forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);
          // send/sendto only handles MSG_OOB
          flags &= SO_MSG_OOB;

          sockaddr_in local_name = {0};
          if (has_destaddr)
          {
            WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn2 + 0x0C);
            WiiSockMan::Convert(*wii_name, local_name);
          }

          int ret = sendto(fd, data, BufferInSize, flags,
                           has_destaddr ? (struct sockaddr*)&local_name : nullptr,
                           has_destaddr ? sizeof(sockaddr) : 0);
          ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_SENDTO", true);

          DEBUG_LOG(
              WII_IPC_NET,
              "%s = %d Socket: %08x, BufferIn: (%08x, %i), BufferIn2: (%08x, %i), %u.%u.%u.%u",
              has_destaddr ? "IOCTLV_SO_SENDTO " : "IOCTLV_SO_SEND ", ReturnValue, fd, BufferIn,
              BufferInSize, BufferIn2, BufferInSize2, local_name.sin_addr.s_addr & 0xFF,
              (local_name.sin_addr.s_addr >> 8) & 0xFF, (local_name.sin_addr.s_addr >> 16) & 0xFF,
              (local_name.sin_addr.s_addr >> 24) & 0xFF);
          break;
        }
        case IOCTLV_SO_RECVFROM:
        {
          u32 flags = Memory::Read_U32(BufferIn + 0x04);
          // Not a string, Windows requires a char* for recvfrom
          char* data = (char*)Memory::GetPointer(BufferOut);
          int data_len = BufferOutSize;

          sockaddr_in local_name;
          memset(&local_name, 0, sizeof(sockaddr_in));

          if (BufferOutSize2 != 0)
          {
            WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut2);
            WiiSockMan::Convert(*wii_name, local_name);
          }

          // Act as non blocking when SO_MSG_NONBLOCK is specified
          forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);

          // recv/recvfrom only handles PEEK/OOB
          flags &= SO_MSG_PEEK | SO_MSG_OOB;
#ifdef _WIN32
          if (flags & SO_MSG_PEEK)
          {
            unsigned long totallen = 0;
            ioctlsocket(fd, FIONREAD, &totallen);
            ReturnValue = totallen;
            break;
          }
#endif
          socklen_t addrlen = sizeof(sockaddr_in);
          int ret = recvfrom(fd, data, data_len, flags,
                             BufferOutSize2 ? (struct sockaddr*)&local_name : nullptr,
                             BufferOutSize2 ? &addrlen : nullptr);
          ReturnValue =
              WiiSockMan::GetNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true);

          INFO_LOG(WII_IPC_NET, "%s(%d, %p) Socket: %08X, Flags: %08X, "
                                "BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
                                "BufferOut: (%08x, %i), BufferOut2: (%08x, %i)",
                   BufferOutSize2 ? "IOCTLV_SO_RECVFROM " : "IOCTLV_SO_RECV ", ReturnValue, data,
                   fd, flags, BufferIn, BufferInSize, BufferIn2, BufferInSize2, BufferOut,
                   BufferOutSize, BufferOut2, BufferOutSize2);

          if (BufferOutSize2 != 0)
          {
            WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut2);
            WiiSockMan::Convert(local_name, *wii_name, addrlen);
          }
          break;
        }
        default:
          break;
        }
      }
    }

    if (nonBlock || forceNonBlock ||
        (!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS &&
         ReturnValue != -SO_EALREADY) ||
        (it->is_ssl && ReturnValue != SSL_ERR_WAGAIN && ReturnValue != SSL_ERR_RAGAIN))
    {
      DEBUG_LOG(WII_IPC_NET,
                "IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d", fd,
                it->is_ssl ? (int)it->ssl_type : (int)it->net_type, ReturnValue, nonBlock,
                forceNonBlock);
      Memory::Write_U32(ReturnValue, it->_CommandAddress + 4);
      WII_IPC_HLE_Interface::EnqueueReply(it->_CommandAddress);
      it = pending_sockops.erase(it);
    }
    else
    {
      ++it;
    }
  }
Esempio n. 14
0
IoT_Error_t iot_tls_connect(Network *pNetwork, TLSConnectParams *params) {
    int ret = SUCCESS;
    TLSDataParams *tlsDataParams = NULL;
    char portBuffer[6];
    char info_buf[256];

    if(NULL == pNetwork) {
        return NULL_VALUE_ERROR;
    }

    if(NULL != params) {
        _iot_tls_set_connect_params(pNetwork, params->pRootCALocation, params->pDeviceCertLocation,
                                    params->pDevicePrivateKeyLocation, params->pDestinationURL,
                                    params->DestinationPort, params->timeout_ms, params->ServerVerificationFlag);
    }

    tlsDataParams = &(pNetwork->tlsDataParams);

    mbedtls_net_init(&(tlsDataParams->server_fd));
    mbedtls_ssl_init(&(tlsDataParams->ssl));
    mbedtls_ssl_config_init(&(tlsDataParams->conf));

#ifdef CONFIG_MBEDTLS_DEBUG
    mbedtls_esp_enable_debug_log(&(tlsDataParams->conf), 4);
#endif

    mbedtls_ctr_drbg_init(&(tlsDataParams->ctr_drbg));
    mbedtls_x509_crt_init(&(tlsDataParams->cacert));
    mbedtls_x509_crt_init(&(tlsDataParams->clicert));
    mbedtls_pk_init(&(tlsDataParams->pkey));

    ESP_LOGD(TAG, "Seeding the random number generator...");
    mbedtls_entropy_init(&(tlsDataParams->entropy));
    if((ret = mbedtls_ctr_drbg_seed(&(tlsDataParams->ctr_drbg), mbedtls_entropy_func, &(tlsDataParams->entropy),
                                    (const unsigned char *) TAG, strlen(TAG))) != 0) {
        ESP_LOGE(TAG, "failed! mbedtls_ctr_drbg_seed returned -0x%x", -ret);
        return NETWORK_MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED;
    }

   /*  Load root CA...

       Certs/keys can be paths or they can be raw data. These use a
       very basic heuristic: if the cert starts with '/' then it's a
       path, if it's longer than this then it's raw cert data (PEM or DER,
       neither of which can start with a slash. */
    if (pNetwork->tlsConnectParams.pRootCALocation[0] == '/') {
        ESP_LOGD(TAG, "Loading CA root certificate from file ...");
        ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->cacert), pNetwork->tlsConnectParams.pRootCALocation);
    } else {
        ESP_LOGD(TAG, "Loading embedded CA root certificate ...");
        ret = mbedtls_x509_crt_parse(&(tlsDataParams->cacert), (const unsigned char *)pNetwork->tlsConnectParams.pRootCALocation,
                                 strlen(pNetwork->tlsConnectParams.pRootCALocation)+1);
    }

    if(ret < 0) {
        ESP_LOGE(TAG, "failed!  mbedtls_x509_crt_parse returned -0x%x while parsing root cert", -ret);
        return NETWORK_X509_ROOT_CRT_PARSE_ERROR;
    }
    ESP_LOGD(TAG, "ok (%d skipped)", ret);

    /* Load client certificate... */
    if (pNetwork->tlsConnectParams.pDeviceCertLocation[0] == '/') {
        ESP_LOGD(TAG, "Loading client cert from file...");
        ret = mbedtls_x509_crt_parse_file(&(tlsDataParams->clicert),
                                          pNetwork->tlsConnectParams.pDeviceCertLocation);
    } else {
        ESP_LOGD(TAG, "Loading embedded client certificate...");
        ret = mbedtls_x509_crt_parse(&(tlsDataParams->clicert),
                                     (const unsigned char *)pNetwork->tlsConnectParams.pDeviceCertLocation,
                                     strlen(pNetwork->tlsConnectParams.pDeviceCertLocation)+1);
    }
    if(ret != 0) {
        ESP_LOGE(TAG, "failed!  mbedtls_x509_crt_parse returned -0x%x while parsing device cert", -ret);
        return NETWORK_X509_DEVICE_CRT_PARSE_ERROR;
    }

    /* Parse client private key... */
    if (pNetwork->tlsConnectParams.pDevicePrivateKeyLocation[0] == '/') {
        ESP_LOGD(TAG, "Loading client private key from file...");
        ret = mbedtls_pk_parse_keyfile(&(tlsDataParams->pkey),
                                       pNetwork->tlsConnectParams.pDevicePrivateKeyLocation,
                                       "");
    } else {
        ESP_LOGD(TAG, "Loading embedded client private key...");
        ret = mbedtls_pk_parse_key(&(tlsDataParams->pkey),
                                   (const unsigned char *)pNetwork->tlsConnectParams.pDevicePrivateKeyLocation,
                                   strlen(pNetwork->tlsConnectParams.pDevicePrivateKeyLocation)+1,
                                   (const unsigned char *)"", 0);
    }
    if(ret != 0) {
        ESP_LOGE(TAG, "failed!  mbedtls_pk_parse_key returned -0x%x while parsing private key", -ret);
        return NETWORK_PK_PRIVATE_KEY_PARSE_ERROR;
    }

    /* Done parsing certs */
    ESP_LOGD(TAG, "ok");
    snprintf(portBuffer, 6, "%d", pNetwork->tlsConnectParams.DestinationPort);
    ESP_LOGD(TAG, "Connecting to %s/%s...", pNetwork->tlsConnectParams.pDestinationURL, portBuffer);
    if((ret = mbedtls_net_connect(&(tlsDataParams->server_fd), pNetwork->tlsConnectParams.pDestinationURL,
                                  portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) {
        ESP_LOGE(TAG, "failed! mbedtls_net_connect returned -0x%x", -ret);
        switch(ret) {
            case MBEDTLS_ERR_NET_SOCKET_FAILED:
                return NETWORK_ERR_NET_SOCKET_FAILED;
            case MBEDTLS_ERR_NET_UNKNOWN_HOST:
                return NETWORK_ERR_NET_UNKNOWN_HOST;
            case MBEDTLS_ERR_NET_CONNECT_FAILED:
            default:
                return NETWORK_ERR_NET_CONNECT_FAILED;
        };
    }

    ret = mbedtls_net_set_block(&(tlsDataParams->server_fd));
    if(ret != 0) {
        ESP_LOGE(TAG, "failed! net_set_(non)block() returned -0x%x", -ret);
        return SSL_CONNECTION_ERROR;
    } ESP_LOGD(TAG, "ok");

    ESP_LOGD(TAG, "Setting up the SSL/TLS structure...");
    if((ret = mbedtls_ssl_config_defaults(&(tlsDataParams->conf), MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
        ESP_LOGE(TAG, "failed! mbedtls_ssl_config_defaults returned -0x%x", -ret);
        return SSL_CONNECTION_ERROR;
    }

    mbedtls_ssl_conf_verify(&(tlsDataParams->conf), _iot_tls_verify_cert, NULL);

    if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
        mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_REQUIRED);
    } else {
        mbedtls_ssl_conf_authmode(&(tlsDataParams->conf), MBEDTLS_SSL_VERIFY_OPTIONAL);
    }
    mbedtls_ssl_conf_rng(&(tlsDataParams->conf), mbedtls_ctr_drbg_random, &(tlsDataParams->ctr_drbg));

    mbedtls_ssl_conf_ca_chain(&(tlsDataParams->conf), &(tlsDataParams->cacert), NULL);
    ret = mbedtls_ssl_conf_own_cert(&(tlsDataParams->conf), &(tlsDataParams->clicert), &(tlsDataParams->pkey));
    if(ret != 0) {
        ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_own_cert returned %d", ret);
        return SSL_CONNECTION_ERROR;
    }

    mbedtls_ssl_conf_read_timeout(&(tlsDataParams->conf), pNetwork->tlsConnectParams.timeout_ms);

#ifdef CONFIG_MBEDTLS_SSL_ALPN
    /* Use the AWS IoT ALPN extension for MQTT, if port 443 is requested */
    if (pNetwork->tlsConnectParams.DestinationPort == 443) {
        const char *alpnProtocols[] = { "x-amzn-mqtt-ca", NULL };
        if ((ret = mbedtls_ssl_conf_alpn_protocols(&(tlsDataParams->conf), alpnProtocols)) != 0) {
            ESP_LOGE(TAG, "failed! mbedtls_ssl_conf_alpn_protocols returned -0x%x", -ret);
            return SSL_CONNECTION_ERROR;
        }
    }
#endif

    if((ret = mbedtls_ssl_setup(&(tlsDataParams->ssl), &(tlsDataParams->conf))) != 0) {
        ESP_LOGE(TAG, "failed! mbedtls_ssl_setup returned -0x%x", -ret);
        return SSL_CONNECTION_ERROR;
    }
    if((ret = mbedtls_ssl_set_hostname(&(tlsDataParams->ssl), pNetwork->tlsConnectParams.pDestinationURL)) != 0) {
        ESP_LOGE(TAG, "failed! mbedtls_ssl_set_hostname returned %d", ret);
        return SSL_CONNECTION_ERROR;
    }
    ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state);
    mbedtls_ssl_set_bio(&(tlsDataParams->ssl), &(tlsDataParams->server_fd), mbedtls_net_send, NULL,
                        mbedtls_net_recv_timeout);
    ESP_LOGD(TAG, "ok");

    ESP_LOGD(TAG, "SSL state connect : %d ", tlsDataParams->ssl.state);
    ESP_LOGD(TAG, "Performing the SSL/TLS handshake...");
    while((ret = mbedtls_ssl_handshake(&(tlsDataParams->ssl))) != 0) {
        if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
            ESP_LOGE(TAG, "failed! mbedtls_ssl_handshake returned -0x%x", -ret);
            if(ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
                ESP_LOGE(TAG, "    Unable to verify the server's certificate. ");
            }
            return SSL_CONNECTION_ERROR;
        }
    }

    ESP_LOGD(TAG, "ok    [ Protocol is %s ]    [ Ciphersuite is %s ]", mbedtls_ssl_get_version(&(tlsDataParams->ssl)),
          mbedtls_ssl_get_ciphersuite(&(tlsDataParams->ssl)));
    if((ret = mbedtls_ssl_get_record_expansion(&(tlsDataParams->ssl))) >= 0) {
        ESP_LOGD(TAG, "    [ Record expansion is %d ]", ret);
    } else {
        ESP_LOGD(TAG, "    [ Record expansion is unknown (compression) ]");
    }

    ESP_LOGD(TAG, "Verifying peer X.509 certificate...");

    if(pNetwork->tlsConnectParams.ServerVerificationFlag == true) {
        if((tlsDataParams->flags = mbedtls_ssl_get_verify_result(&(tlsDataParams->ssl))) != 0) {
            ESP_LOGE(TAG, "failed");
            mbedtls_x509_crt_verify_info(info_buf, sizeof(info_buf), "  ! ", tlsDataParams->flags);
            ESP_LOGE(TAG, "%s", info_buf);
            ret = SSL_CONNECTION_ERROR;
        } else {
            ESP_LOGD(TAG, "ok");
            ret = SUCCESS;
        }
    } else {
        ESP_LOGW(TAG, " Server Verification skipped");
        ret = SUCCESS;
    }

    if(LOG_LOCAL_LEVEL >= ESP_LOG_DEBUG) {
        if (mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)) != NULL) {
            ESP_LOGD(TAG, "Peer certificate information:");
            mbedtls_x509_crt_info((char *) info_buf, sizeof(info_buf) - 1, "      ", mbedtls_ssl_get_peer_cert(&(tlsDataParams->ssl)));
            ESP_LOGD(TAG, "%s", info_buf);
        }
    }

    return (IoT_Error_t) ret;
}
Esempio n. 15
0
void http_get_task(void *pvParameters)
{
    int successes = 0, failures = 0, ret;
    printf("HTTP get task starting...\n");

    uint32_t flags;
    unsigned char buf[1024];
    const char *pers = "ssl_client1";

    mbedtls_entropy_context entropy;
    mbedtls_ctr_drbg_context ctr_drbg;
    mbedtls_ssl_context ssl;
    mbedtls_x509_crt cacert;
    mbedtls_ssl_config conf;
    mbedtls_net_context server_fd;

    /*
     * 0. Initialize the RNG and the session data
     */
    mbedtls_ssl_init(&ssl);
    mbedtls_x509_crt_init(&cacert);
    mbedtls_ctr_drbg_init(&ctr_drbg);
    printf("\n  . Seeding the random number generator...");

    mbedtls_ssl_config_init(&conf);

    mbedtls_entropy_init(&entropy);
    if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                                    (const unsigned char *) pers,
                                    strlen(pers))) != 0)
    {
        printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
        abort();
    }

    printf(" ok\n");

    /*
     * 0. Initialize certificates
     */
    printf("  . Loading the CA root certificate ...");

    ret = mbedtls_x509_crt_parse(&cacert, (uint8_t*)server_root_cert, strlen(server_root_cert)+1);
    if(ret < 0)
    {
        printf(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
        abort();
    }

    printf(" ok (%d skipped)\n", ret);

    /* Hostname set here should match CN in server certificate */
    if((ret = mbedtls_ssl_set_hostname(&ssl, WEB_SERVER)) != 0)
    {
        printf(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
        abort();
    }

    /*
     * 2. Setup stuff
     */
    printf("  . Setting up the SSL/TLS structure...");

    if((ret = mbedtls_ssl_config_defaults(&conf,
                                          MBEDTLS_SSL_IS_CLIENT,
                                          MBEDTLS_SSL_TRANSPORT_STREAM,
                                          MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
    {
        printf(" failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
        goto exit;
    }

    printf(" ok\n");

    /* OPTIONAL is not optimal for security, in this example it will print
       a warning if CA verification fails but it will continue to connect.
    */
    mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
    mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
    mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
#ifdef MBEDTLS_DEBUG_C
    mbedtls_debug_set_threshold(DEBUG_LEVEL);
    mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
#endif

    if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
    {
        printf(" failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret);
        goto exit;
    }

    /* Wait until we can resolve the DNS for the server, as an indication
       our network is probably working...
    */
    printf("Waiting for server DNS to resolve... ");
    err_t dns_err;
    ip_addr_t host_ip;
    do {
        vTaskDelay(500 / portTICK_PERIOD_MS);
        dns_err = netconn_gethostbyname(WEB_SERVER, &host_ip);
    } while(dns_err != ERR_OK);
    printf("done.\n");

    while(1) {
        mbedtls_net_init(&server_fd);
        printf("top of loop, free heap = %u\n", xPortGetFreeHeapSize());
        /*
         * 1. Start the connection
         */
        printf("  . Connecting to %s:%s...", WEB_SERVER, WEB_PORT);

        if((ret = mbedtls_net_connect(&server_fd, WEB_SERVER,
                                      WEB_PORT, MBEDTLS_NET_PROTO_TCP)) != 0)
        {
            printf(" failed\n  ! mbedtls_net_connect returned %d\n\n", ret);
            goto exit;
        }

        printf(" ok\n");

        mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL);

        /*
         * 4. Handshake
         */
        printf("  . Performing the SSL/TLS handshake...");

        while((ret = mbedtls_ssl_handshake(&ssl)) != 0)
        {
            if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
            {
                printf(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret);
                goto exit;
            }
        }

        printf(" ok\n");

        /*
         * 5. Verify the server certificate
         */
        printf("  . Verifying peer X.509 certificate...");

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

            printf(" failed\n");

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

            printf("%s\n", vrfy_buf);
        }
        else
            printf(" ok\n");

        /*
         * 3. Write the GET request
         */
        printf("  > Write to server:");

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

        while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
        {
            if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
            {
                printf(" failed\n  ! mbedtls_ssl_write returned %d\n\n", ret);
                goto exit;
            }
        }

        len = ret;
        printf(" %d bytes written\n\n%s", len, (char *) buf);

        /*
         * 7. Read the HTTP response
         */
        printf("  < Read from server:");

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

            if(ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE)
                continue;

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

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

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

            len = ret;
            printf(" %d bytes read\n\n%s", len, (char *) buf);
        } while(1);

        mbedtls_ssl_close_notify(&ssl);

    exit:
        mbedtls_ssl_session_reset(&ssl);
        mbedtls_net_free(&server_fd);

        if(ret != 0)
        {
            char error_buf[100];
            mbedtls_strerror(ret, error_buf, 100);
            printf("\n\nLast error was: %d - %s\n\n", ret, error_buf);
            failures++;
        } else {
            successes++;
        }

        printf("\n\nsuccesses = %d failures = %d\n", successes, failures);
        for(int countdown = successes ? 10 : 5; countdown >= 0; countdown--) {
            printf("%d... ", countdown);
            vTaskDelay(1000 / portTICK_PERIOD_MS);
        }
        printf("\nStarting again!\n");
    }
}
Esempio n. 16
0
int main(int argc, char *argv[]) {
  int ret, exitcode;
  mbedtls_net_context server_fd;
  uint32_t flags;
  char scenario[10000] = "";
  char server_host[100] = "";
  char server_port[6] = "";
  char server_ssl_hostname[100] = "";
  const char *pers = "dtls_client";
  int opt;
  struct timeval t0, t1;

  mbedtls_entropy_context entropy;
  mbedtls_ctr_drbg_context ctr_drbg;
  mbedtls_ssl_context ssl;
  mbedtls_ssl_config conf;
  mbedtls_x509_crt cacert;
  mbedtls_timing_delay_context timer;

  /* Parse command line */
  while ((opt = getopt(argc, argv, "h:n:p:s:")) != -1) {
    switch (opt) {
      case 'h':
        strncpy(server_host, optarg, sizeof(server_host));
        break;
      case 'n':
        strncpy(server_ssl_hostname, optarg, sizeof(server_ssl_hostname));
        break;
      case 'p':
        strncpy(server_port, optarg, sizeof(server_port));
        break;
      case 's':
        strncpy(scenario, optarg, sizeof(scenario));
        break;
      default:                 /* '?' */
        print_usage(argv[0]);
    }
  }

  if (!(scenario[0] && server_port[0] && server_host[0])) {
    print_usage(argv[0]);
  }

  if (!server_ssl_hostname[0]) {
    strncpy(server_ssl_hostname, server_host, sizeof(server_ssl_hostname));
  }
#if defined(MBEDTLS_DEBUG_C)
  mbedtls_debug_set_threshold(DEBUG_LEVEL);
#endif

  /*
   * 0. Initialize the RNG and the session data
   */
  mbedtls_net_init(&server_fd);
  mbedtls_ssl_init(&ssl);
  mbedtls_ssl_config_init(&conf);
  mbedtls_x509_crt_init(&cacert);
  mbedtls_ctr_drbg_init(&ctr_drbg);

  plog("Seeding the random number generator...");

  mbedtls_entropy_init(&entropy);
  if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
                                   (const unsigned char *)pers, strlen(pers))) != 0) {
    plog("ERROR: failed! mbedtls_ctr_drbg_seed returned %d", ret);
    goto exit;
  }

  /*
   * 0. Load certificates
   */
  plog("Loading the CA root certificate ...");

  ret = mbedtls_x509_crt_parse(&cacert, (const unsigned char *)mbedtls_test_cas_pem,
                               mbedtls_test_cas_pem_len);
  if (ret < 0) {
    plog("ERROR: failed! mbedtls_x509_crt_parse returned -0x%x", -ret);
    goto exit;
  }

  plog("Connecting to udp %s:%s (SSL hostname: %s)...",
       server_host, server_port, server_ssl_hostname);

  if ((ret = mbedtls_net_connect(&server_fd, server_host, server_port, MBEDTLS_NET_PROTO_UDP)) != 0) {
    plog("ERROR: failed! mbedtls_net_connect returned %d", ret);
    goto exit;
  }

  plog("The local client UDP source port is %d", get_source_port(server_fd.fd));

  plog("Setting up the DTLS structure...");

  if ((ret = mbedtls_ssl_config_defaults(&conf,
                                         MBEDTLS_SSL_IS_CLIENT,
                                         MBEDTLS_SSL_TRANSPORT_DATAGRAM,
                                         MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
    plog("ERROR: failed! mbedtls_ssl_config_defaults returned %d", ret);
    goto exit;
  }

  /* OPTIONAL is usually a bad choice for security, but makes interop easier
   * in this simplified example, in which the ca chain is hardcoded.
   * Production code should set a proper ca chain and use REQUIRED. */
  mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
  mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
  mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
  mbedtls_ssl_conf_dbg(&conf, log_mbedtls_debug_callback, NULL);
  /* TODO timeouts */

  if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
    plog("ERROR: failed! mbedtls_ssl_setup returned %d", ret);
    goto exit;
  }

  if ((ret = mbedtls_ssl_set_hostname(&ssl, server_ssl_hostname)) != 0) {
    plog("ERROR: failed! mbedtls_ssl_set_hostname returned %d", ret);
    goto exit;
  }

  mbedtls_ssl_set_bio(&ssl, &server_fd,
                      mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout);

  mbedtls_ssl_set_timer_cb(&ssl, &timer, mbedtls_timing_set_delay, mbedtls_timing_get_delay);

  plog("Performing the SSL/TLS handshake...");

  gettimeofday(&t0, NULL);
  do {
    ret = mbedtls_ssl_handshake(&ssl);
    plog(" ... during SSL handshake, ret=%d (WANT_READ=%d, WANT_WRITE=%d, RECV_FAILED=%d",
         ret, MBEDTLS_ERR_SSL_WANT_READ, MBEDTLS_ERR_SSL_WANT_WRITE, MBEDTLS_ERR_NET_RECV_FAILED);
    gettimeofday(&t1, NULL);
  } while ((duration_ms(&t1, &t0) <= SSL_HANDSHAKE_TIMEOUT_MILLISECS) &&
           (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE));

  plog("handshake duration: %d milliseconds", duration_ms(&t1, &t0));
  if (duration_ms(&t1, &t0) > SSL_HANDSHAKE_TIMEOUT_MILLISECS) {
    plog("ERROR: long time to perform handshake: %d milliseconds", duration_ms(&t1, &t0));
    ret = MBEDTLS_ERR_SSL_TIMEOUT;
    goto exit;
  }

  if (ret != 0) {
    plog("ERROR: failed! mbedtls_ssl_handshake returned -0x%x", -ret);
    goto exit;
  }

  plog("Verifying peer X.509 certificate...");

  /* In real life, we would have used MBEDTLS_SSL_VERIFY_REQUIRED so that the
   * handshake would not succeed if the peer's cert is bad.  Even if we used
   * MBEDTLS_SSL_VERIFY_OPTIONAL, we would bail out here if ret != 0 */
  if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) {
    char vrfy_buf[512];
    mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "! ", flags);
    plog("Verification failed: %s", vrfy_buf);
  } else {
    plog("Certificates ok");
  }

  ret = run_scenario(scenario, &ssl);
  if (ret != 0) {
    goto exit;
  }

  plog("Closing the connection...");

  /* No error checking, the connection might be closed already */
  do {
    ret = mbedtls_ssl_close_notify(&ssl);
  } while (ret == MBEDTLS_ERR_SSL_WANT_WRITE);
  ret = 0;

exit:

#ifdef MBEDTLS_ERROR_C
  if (ret != 0) {
    char error_buf[100];
    mbedtls_strerror(ret, error_buf, 100);
    plog("ERROR: Last error was: %d - %s", ret, error_buf);
  }
#endif

  mbedtls_net_free(&server_fd);

  mbedtls_x509_crt_free(&cacert);
  mbedtls_ssl_free(&ssl);
  mbedtls_ssl_config_free(&conf);
  mbedtls_ctr_drbg_free(&ctr_drbg);
  mbedtls_entropy_free(&entropy);

  exitcode = ret == 0 ? 0 : 1;
  plog("Done, exitcode=%d", exitcode);
  return exitcode;
}
int iot_tls_connect(Network *pNetwork, TLSConnectParams params) {
	const char *pers = "aws_iot_tls_wrapper";
	unsigned char buf[MBEDTLS_SSL_MAX_CONTENT_LEN + 1];

	DEBUG("  . Loading the CA root certificate ...");
	ret = mbedtls_x509_crt_parse_file(&cacert, params.pRootCALocation);
	if (ret < 0) {
		ERROR(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
		return ret;
	} DEBUG(" ok (%d skipped)\n", ret);

	DEBUG("  . Loading the client cert. and key...");
	ret = mbedtls_x509_crt_parse_file(&clicert, params.pDeviceCertLocation);
	if (ret != 0) {
		ERROR(" failed\n  !  mbedtls_x509_crt_parse returned -0x%x\n\n", -ret);
		return ret;
	}

	ret = mbedtls_pk_parse_keyfile(&pkey, params.pDevicePrivateKeyLocation, "");
	if (ret != 0) {
		ERROR(" failed\n  !  mbedtls_pk_parse_key returned -0x%x\n\n", -ret);
		return ret;
	} DEBUG(" ok\n");
	char portBuffer[6];
	sprintf(portBuffer, "%d", params.DestinationPort); DEBUG("  . Connecting to %s/%s...", params.pDestinationURL, portBuffer);
	if ((ret = mbedtls_net_connect(&server_fd, params.pDestinationURL, portBuffer, MBEDTLS_NET_PROTO_TCP)) != 0) {
		ERROR(" failed\n  ! mbedtls_net_connect returned -0x%x\n\n", -ret);
		return ret;
	}

	ret = mbedtls_net_set_block(&server_fd);
	if (ret != 0) {
		ERROR(" failed\n  ! net_set_(non)block() returned -0x%x\n\n", -ret);
		return ret;
	} DEBUG(" ok\n");

	DEBUG("  . Setting up the SSL/TLS structure...");
	if ((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_CLIENT, MBEDTLS_SSL_TRANSPORT_STREAM,
			MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret);
		return ret;
	}

	mbedtls_ssl_conf_verify(&conf, myCertVerify, NULL);
	if (params.ServerVerificationFlag == true) {
		mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_REQUIRED);
	} else {
		mbedtls_ssl_conf_authmode(&conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
	}
	mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);

	mbedtls_ssl_conf_ca_chain(&conf, &cacert, NULL);
	if ((ret = mbedtls_ssl_conf_own_cert(&conf, &clicert, &pkey)) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
		return ret;
	}

	mbedtls_ssl_conf_read_timeout(&conf, params.timeout_ms);

	if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_setup returned -0x%x\n\n", -ret);
		return ret;
	}
	if ((ret = mbedtls_ssl_set_hostname(&ssl, params.pDestinationURL)) != 0) {
		ERROR(" failed\n  ! mbedtls_ssl_set_hostname returned %d\n\n", ret);
		return ret;
	}
	mbedtls_ssl_set_bio(&ssl, &server_fd, mbedtls_net_send, NULL, mbedtls_net_recv_timeout);
	DEBUG(" ok\n");

	DEBUG("  . Performing the SSL/TLS handshake...");
	while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
		if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
			ERROR(" failed\n  ! mbedtls_ssl_handshake returned -0x%x\n", -ret);
			if (ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) {
				ERROR("    Unable to verify the server's certificate. "
						"Either it is invalid,\n"
						"    or you didn't set ca_file or ca_path "
						"to an appropriate value.\n"
						"    Alternatively, you may want to use "
						"auth_mode=optional for testing purposes.\n");
			}
			return ret;
		}
	}

	DEBUG(" ok\n    [ Protocol is %s ]\n    [ Ciphersuite is %s ]\n", mbedtls_ssl_get_version(&ssl), mbedtls_ssl_get_ciphersuite(&ssl));
	if ((ret = mbedtls_ssl_get_record_expansion(&ssl)) >= 0) {
		DEBUG("    [ Record expansion is %d ]\n", ret);
	} else {
		DEBUG("    [ Record expansion is unknown (compression) ]\n");
	}

	DEBUG("  . Verifying peer X.509 certificate...");

	if (params.ServerVerificationFlag == true) {
		if ((flags = mbedtls_ssl_get_verify_result(&ssl)) != 0) {
			char vrfy_buf[512];
			ERROR(" failed\n");
			mbedtls_x509_crt_verify_info(vrfy_buf, sizeof(vrfy_buf), "  ! ", flags);
			ERROR("%s\n", vrfy_buf);
		} else {
			DEBUG(" ok\n");
			ret = NONE_ERROR;
		}
	} else {
		DEBUG(" Server Verification skipped\n");
		ret = NONE_ERROR;
	}

	if (mbedtls_ssl_get_peer_cert(&ssl) != NULL) {
		DEBUG("  . Peer certificate information    ...\n");
		mbedtls_x509_crt_info((char *) buf, sizeof(buf) - 1, "      ", mbedtls_ssl_get_peer_cert(&ssl));
		DEBUG("%s\n", buf);
	}

	mbedtls_ssl_conf_read_timeout(&conf, 10);

	return ret;
}