void ssl_server(void const *argument)
{
int ret, len;
#ifdef MBEDTLS_MEMORY_BUFFER_ALLOC_C
mbedtls_memory_buffer_alloc_init(memory_buf, sizeof(memory_buf));
#endif
//mbedtls_net_init( &listen_fd );
listen_fd.fd = -1;
//mbedtls_net_init( &client_fd );
client_fd.fd = -1;
mbedtls_ssl_init( &ssl );
mbedtls_ssl_config_init( &conf );
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_init( &cache );
#endif
mbedtls_x509_crt_init( &srvcert );
mbedtls_pk_init( &pkey );
mbedtls_entropy_init( &entropy );
mbedtls_ctr_drbg_init( &ctr_drbg );
#if defined(MBEDTLS_DEBUG_C)
mbedtls_debug_set_threshold( DEBUG_LEVEL );
#endif
/*
* 1. Load the certificates and private RSA key
*/
mbedtls_printf( "\r\n . Loading the server cert. and key..." );
/*
* This demonstration program uses embedded test certificates.
* Using mbedtls_x509_crt_parse_file() to read the server and CA certificates
* resuires the implmentation of the File I/O API using the FatFs, that is
* not implemented yet.
*/
ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt, mbedtls_test_srv_crt_len );
if(ret != 0)
{
mbedtls_printf( " failed\r\n ! mbedtls_x509_crt_parse returned %d\r\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\r\n ! mbedtls_pk_parse_key returned %d\r\n", ret);
goto exit;
}
mbedtls_printf( " ok\r\n" );
/*
* 2. Setup the listening TCP socket
*/
mbedtls_printf( " . Bind on https://localhost:443/ ..." );
if((ret = mbedtls_net_bind(&listen_fd, NULL, "443", MBEDTLS_NET_PROTO_TCP )) != 0)
{
mbedtls_printf( " failed\r\n ! mbedtls_net_bind returned -0x%x\r\n", -ret );
goto exit;
}
mbedtls_printf( " ok\r\n" );
/*
* 3. Seed the RNG
*/
mbedtls_printf( " . Seeding the random number generator..." );
if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, ALTCP_MBEDTLS_RNG_FN, &entropy, (const unsigned char *) pers, strlen( (char *)pers))) != 0)
{
mbedtls_printf( " failed\r\n ! mbedtls_ctr_drbg_seed returned -0x%x\r\n", -ret );
goto exit;
}
mbedtls_printf( " ok\r\n" );
/*
* 4. Setup stuff
*/
mbedtls_printf( " . Setting up the SSL data...." );
if((ret = mbedtls_ssl_config_defaults(&conf, MBEDTLS_SSL_IS_SERVER, MBEDTLS_SSL_TRANSPORT_STREAM, MBEDTLS_SSL_PRESET_DEFAULT)) != 0)
{
mbedtls_printf( " failed\r\n ! mbedtls_ssl_config_defaults returned -0x%x\r\n", -ret );
goto exit;
}
mbedtls_ssl_conf_rng(&conf, mbedtls_ctr_drbg_random, &ctr_drbg);
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_conf_session_cache(&conf, &cache, mbedtls_ssl_cache_get, mbedtls_ssl_cache_set);
#endif
mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL);
if((ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey)) != 0)
{
mbedtls_printf( " failed\r\n ! mbedtls_ssl_conf_own_cert returned -0x%x\r\n", -ret );
goto exit;
}
if((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0)
{
mbedtls_printf( " failed\r\n ! mbedtls_ssl_setup returned -0x%x\r\n", -ret );
goto exit;
}
mbedtls_printf( " ok\r\n" );
reset:
#ifdef MBEDTLS_ERROR_C
if(ret != 0)
{
uint8_t error_buf[100];
mbedtls_strerror( ret, (char *)error_buf, 100 );
mbedtls_printf("Last error was: -0x%x - %s\r\n", -ret, error_buf );
}
#endif
mbedtls_net_free(&client_fd);
mbedtls_ssl_session_reset(&ssl);
/*
* 5. Wait until a client connects
*/
mbedtls_printf( " . Waiting for a remote connection ...\r\n" );
if((ret = mbedtls_net_accept(&listen_fd, &client_fd, NULL, 0, NULL)) != 0)
{
mbedtls_printf(" => connection failed\r\n ! mbedtls_net_accept returned -0x%x\r\n", -ret);
goto exit;
}
mbedtls_ssl_set_bio(&ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
mbedtls_printf(" => connection ok\r\n");
/*
* 6. Handshake
*/
mbedtls_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)
{
mbedtls_printf(" failed\r\n ! mbedtls_ssl_handshake returned -0x%x\r\n", -ret);
goto reset;
}
}
mbedtls_printf(" ok\r\n");
/*
* 7. Read the HTTP Request
*/
mbedtls_printf(" < Read from client:");
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 <= 0)
{
switch(ret)
{
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
mbedtls_printf(" connection was closed gracefully\r\n");
break;
case MBEDTLS_ERR_NET_CONN_RESET:
mbedtls_printf(" connection was reset by peer\r\n");
break;
default:
mbedtls_printf(" mbedtls_ssl_read returned -0x%x\r\n", -ret);
break;
}
break;
}
len = ret;
mbedtls_printf(" %d bytes read\r\n%s", len, (char *) buf);
if(ret > 0)
{
break;
}
} while(1);
/*
* 8. Write the 200 Response
*/
mbedtls_printf( " > Write to client:" );
len = sprintf((char *) buf, HTTP_RESPONSE, mbedtls_ssl_get_ciphersuite(&ssl));
while((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0)
{
if(ret == MBEDTLS_ERR_NET_CONN_RESET)
{
mbedtls_printf(" failed\r\n ! peer closed the connection\r\n");
goto reset;
}
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
{
mbedtls_printf( " failed\r\n ! mbedtls_ssl_write returned -0x%x\r\n", -ret );
goto exit;
}
}
len = ret;
mbedtls_printf(" %d bytes written\r\n%s", len, (char *) buf);
mbedtls_printf(" . Closing the connection...");
while((ret = mbedtls_ssl_close_notify(&ssl)) < 0)
{
if(ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE)
{
mbedtls_printf( " failed\r\n ! mbedtls_ssl_close_notify returned -0x%x\r\n", -ret );
goto reset;
}
}
mbedtls_printf( " ok\r\n" );
ret = 0;
goto reset;
exit:
mbedtls_net_free( &client_fd );
mbedtls_net_free( &listen_fd );
mbedtls_x509_crt_free( &srvcert );
mbedtls_pk_free( &pkey );
mbedtls_ssl_free( &ssl );
mbedtls_ssl_config_free( &conf );
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_free( &cache );
#endif
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
while(1);
}