[修改] 增加freeRTOS

1. 版本FreeRTOSv202212.01,命名为kernel;
This commit is contained in:
2023-05-06 16:43:01 +00:00
commit a345df017b
20944 changed files with 11094377 additions and 0 deletions

View File

@ -0,0 +1,62 @@
set(THREADS_USE_PTHREADS_WIN32 true)
find_package(Threads)
set(libs
${mbedtls_target}
)
set(executables
dtls_client
dtls_server
mini_client
ssl_client1
ssl_client2
ssl_context_info
ssl_fork_server
ssl_mail_client
ssl_server
ssl_server2
)
if(GEN_FILES)
# Inform CMake that the following file will be generated as part of the build
# process, so it doesn't complain that it doesn't exist yet. Starting from
# CMake 3.20, this will no longer be necessary as CMake will automatically
# propagate this information across the tree, for now it's only visible
# inside the same directory, so we need to propagate manually.
set_source_files_properties(
${CMAKE_CURRENT_BINARY_DIR}/../test/query_config.c
PROPERTIES GENERATED TRUE)
endif()
foreach(exe IN LISTS executables)
set(extra_sources "")
if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
list(APPEND extra_sources
ssl_test_lib.c
${CMAKE_CURRENT_SOURCE_DIR}/../test/query_config.h
${CMAKE_CURRENT_BINARY_DIR}/../test/query_config.c)
endif()
add_executable(${exe} ${exe}.c $<TARGET_OBJECTS:mbedtls_test>
${extra_sources})
target_link_libraries(${exe} ${libs})
target_include_directories(${exe} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
if(exe STREQUAL "ssl_client2" OR exe STREQUAL "ssl_server2")
if(GEN_FILES)
add_dependencies(${exe} generate_query_config_c)
endif()
target_include_directories(${exe}
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../test)
endif()
endforeach()
if(THREADS_FOUND)
add_executable(ssl_pthread_server ssl_pthread_server.c $<TARGET_OBJECTS:mbedtls_test>)
target_include_directories(ssl_pthread_server PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/../../tests/include)
target_link_libraries(ssl_pthread_server ${libs} ${CMAKE_THREAD_LIBS_INIT})
list(APPEND executables ssl_pthread_server)
endif(THREADS_FOUND)
install(TARGETS ${executables}
DESTINATION "bin"
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE)

View File

@ -0,0 +1,357 @@
/*
* Simple DTLS client demonstration program
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_fprintf fprintf
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
#if !defined(MBEDTLS_SSL_CLI_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) || \
!defined(MBEDTLS_NET_C) || !defined(MBEDTLS_TIMING_C) || \
!defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_PEM_PARSE_C)
int main( void )
{
mbedtls_printf( "MBEDTLS_SSL_CLI_C and/or MBEDTLS_SSL_PROTO_DTLS and/or "
"MBEDTLS_NET_C and/or MBEDTLS_TIMING_C and/or "
"MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
"MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_RSA_C and/or "
"MBEDTLS_PEM_PARSE_C not defined.\n" );
mbedtls_exit( 0 );
}
#else
#include <string.h>
#include "mbedtls/net_sockets.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "mbedtls/timing.h"
#include "test/certs.h"
/* Uncomment out the following line to default to IPv4 and disable IPv6 */
//#define FORCE_IPV4
#define SERVER_PORT "4433"
#define SERVER_NAME "localhost"
#ifdef FORCE_IPV4
#define SERVER_ADDR "127.0.0.1" /* Forces IPv4 */
#else
#define SERVER_ADDR "::1"
#endif
#define MESSAGE "Echo this"
#define READ_TIMEOUT_MS 1000
#define MAX_RETRY 5
#define DEBUG_LEVEL 0
static void my_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
((void) level);
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
fflush( (FILE *) ctx );
}
int 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", (unsigned int) -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 );
mbedtls_ssl_conf_read_timeout( &conf, READ_TIMEOUT_MS );
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 DTLS 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", (unsigned int) -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 )
{
#if !defined(MBEDTLS_X509_REMOVE_INFO)
char vrfy_buf[512];
#endif
mbedtls_printf( " failed\n" );
#if !defined(MBEDTLS_X509_REMOVE_INFO)
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
mbedtls_printf( "%s\n", vrfy_buf );
#endif
}
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", (unsigned int) -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 );
/* Shell can not handle large exit numbers -> 1 for errors */
if( ret < 0 )
ret = 1;
mbedtls_exit( ret );
}
#endif /* MBEDTLS_SSL_CLI_C && MBEDTLS_SSL_PROTO_DTLS && MBEDTLS_NET_C &&
MBEDTLD_TIMING_C && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C &&
MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_RSA_C && MBEDTLS_PEM_PARSE_C */

View File

@ -0,0 +1,428 @@
/*
* Simple DTLS server demonstration program
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_fprintf fprintf
#define mbedtls_time_t time_t
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
/* Uncomment out the following line to default to IPv4 and disable IPv6 */
//#define FORCE_IPV4
#ifdef FORCE_IPV4
#define BIND_IP "0.0.0.0" /* Forces IPv4 */
#else
#define BIND_IP "::"
#endif
#if !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) || \
!defined(MBEDTLS_SSL_COOKIE_C) || !defined(MBEDTLS_NET_C) || \
!defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_PEM_PARSE_C) || !defined(MBEDTLS_TIMING_C)
int main( void )
{
printf( "MBEDTLS_SSL_SRV_C and/or MBEDTLS_SSL_PROTO_DTLS and/or "
"MBEDTLS_SSL_COOKIE_C and/or MBEDTLS_NET_C and/or "
"MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
"MBEDTLS_X509_CRT_PARSE_C and/or MBEDTLS_RSA_C and/or "
"MBEDTLS_PEM_PARSE_C and/or MBEDTLS_TIMING_C not defined.\n" );
mbedtls_exit( 0 );
}
#else
#if defined(_WIN32)
#include <windows.h>
#endif
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_cookie.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "mbedtls/timing.h"
#include "test/certs.h"
#if defined(MBEDTLS_SSL_CACHE_C)
#include "mbedtls/ssl_cache.h"
#endif
#define READ_TIMEOUT_MS 10000 /* 10 seconds */
#define DEBUG_LEVEL 0
static void my_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
((void) level);
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
fflush( (FILE *) ctx );
}
int main( void )
{
int ret, len;
mbedtls_net_context listen_fd, client_fd;
unsigned char buf[1024];
const char *pers = "dtls_server";
unsigned char client_ip[16] = { 0 };
size_t cliip_len;
mbedtls_ssl_cookie_ctx cookie_ctx;
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt srvcert;
mbedtls_pk_context pkey;
mbedtls_timing_delay_context timer;
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_context cache;
#endif
mbedtls_net_init( &listen_fd );
mbedtls_net_init( &client_fd );
mbedtls_ssl_init( &ssl );
mbedtls_ssl_config_init( &conf );
mbedtls_ssl_cookie_init( &cookie_ctx );
#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. Seed the RNG
*/
printf( " . Seeding the random number generator..." );
fflush( stdout );
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 );
goto exit;
}
printf( " ok\n" );
/*
* 2. Load the certificates and private RSA key
*/
printf( "\n . 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 )
{
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 )
{
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, mbedtls_ctr_drbg_random, &ctr_drbg );
if( ret != 0 )
{
printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret );
goto exit;
}
printf( " ok\n" );
/*
* 3. Setup the "listening" UDP socket
*/
printf( " . Bind on udp/*/4433 ..." );
fflush( stdout );
if( ( ret = mbedtls_net_bind( &listen_fd, BIND_IP, "4433", MBEDTLS_NET_PROTO_UDP ) ) != 0 )
{
printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret );
goto exit;
}
printf( " ok\n" );
/*
* 4. Setup stuff
*/
printf( " . Setting up the DTLS data..." );
fflush( stdout );
if( ( ret = mbedtls_ssl_config_defaults( &conf,
MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_DATAGRAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret );
goto exit;
}
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
mbedtls_ssl_conf_read_timeout( &conf, READ_TIMEOUT_MS );
#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 )
{
printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
goto exit;
}
if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx,
mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 )
{
printf( " failed\n ! mbedtls_ssl_cookie_setup returned %d\n\n", ret );
goto exit;
}
mbedtls_ssl_conf_dtls_cookies( &conf, mbedtls_ssl_cookie_write, mbedtls_ssl_cookie_check,
&cookie_ctx );
if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
{
printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
goto exit;
}
mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay,
mbedtls_timing_get_delay );
printf( " ok\n" );
reset:
#ifdef MBEDTLS_ERROR_C
if( ret != 0 )
{
char error_buf[100];
mbedtls_strerror( ret, error_buf, 100 );
printf("Last error was: %d - %s\n\n", ret, error_buf );
}
#endif
mbedtls_net_free( &client_fd );
mbedtls_ssl_session_reset( &ssl );
/*
* 3. Wait until a client connects
*/
printf( " . Waiting for a remote connection ..." );
fflush( stdout );
if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
client_ip, sizeof( client_ip ), &cliip_len ) ) != 0 )
{
printf( " failed\n ! mbedtls_net_accept returned %d\n\n", ret );
goto exit;
}
/* For HelloVerifyRequest cookies */
if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl,
client_ip, cliip_len ) ) != 0 )
{
printf( " failed\n ! "
"mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", (unsigned int) -ret );
goto exit;
}
mbedtls_ssl_set_bio( &ssl, &client_fd,
mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout );
printf( " ok\n" );
/*
* 5. Handshake
*/
printf( " . Performing the DTLS handshake..." );
fflush( stdout );
do ret = mbedtls_ssl_handshake( &ssl );
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED )
{
printf( " hello verification requested\n" );
ret = 0;
goto reset;
}
else if( ret != 0 )
{
printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", (unsigned int) -ret );
goto reset;
}
printf( " ok\n" );
/*
* 6. Read the echo Request
*/
printf( " < Read from client:" );
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:
printf( " timeout\n\n" );
goto reset;
case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
printf( " connection was closed gracefully\n" );
ret = 0;
goto close_notify;
default:
printf( " mbedtls_ssl_read returned -0x%x\n\n", (unsigned int) -ret );
goto reset;
}
}
len = ret;
printf( " %d bytes read\n\n%s\n\n", len, buf );
/*
* 7. Write the 200 Response
*/
printf( " > Write to client:" );
fflush( stdout );
do ret = mbedtls_ssl_write( &ssl, buf, len );
while( ret == MBEDTLS_ERR_SSL_WANT_READ ||
ret == MBEDTLS_ERR_SSL_WANT_WRITE );
if( ret < 0 )
{
printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
goto exit;
}
len = ret;
printf( " %d bytes written\n\n%s\n\n", len, buf );
/*
* 8. Done, cleanly close the connection
*/
close_notify:
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;
printf( " done\n" );
goto reset;
/*
* Final clean-ups and exit
*/
exit:
#ifdef MBEDTLS_ERROR_C
if( ret != 0 )
{
char error_buf[100];
mbedtls_strerror( ret, error_buf, 100 );
printf( "Last error was: %d - %s\n\n", ret, error_buf );
}
#endif
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 );
mbedtls_ssl_cookie_free( &cookie_ctx );
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_free( &cache );
#endif
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
/* Shell can not handle large exit numbers -> 1 for errors */
if( ret < 0 )
ret = 1;
mbedtls_exit( ret );
}
#endif /* MBEDTLS_SSL_SRV_C && MBEDTLS_SSL_PROTO_DTLS &&
MBEDTLS_SSL_COOKIE_C && MBEDTLS_NET_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_RSA_C
&& MBEDTLS_PEM_PARSE_C && MBEDTLS_TIMING_C */

View File

@ -0,0 +1,295 @@
/*
* Minimal SSL client, used for memory measurements.
* (meant to be used with config-suite-b.h or config-ccm-psk-tls1_2.h)
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_printf printf
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
/*
* We're creating and connecting the socket "manually" rather than using the
* NET module, in order to avoid the overhead of getaddrinfo() which tends to
* dominate memory usage in small configurations. For the sake of simplicity,
* only a Unix version is implemented.
*
* Warning: we are breaking some of the abstractions from the NET layer here.
* This is not a good example for general use. This programs has the specific
* goal of minimizing use of the libc functions on full-blown OSes.
*/
#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__)
#define UNIX
#endif
#if !defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_NET_C) || !defined(MBEDTLS_SSL_CLI_C) || \
!defined(UNIX)
int main( void )
{
mbedtls_printf( "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_ENTROPY_C and/or "
"MBEDTLS_NET_C and/or MBEDTLS_SSL_CLI_C and/or UNIX "
"not defined.\n");
mbedtls_exit( 0 );
}
#else
#include <string.h>
#include "mbedtls/net_sockets.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
/*
* Hardcoded values for server host and port
*/
#define PORT_BE 0x1151 /* 4433 */
#define PORT_LE 0x5111
#define ADDR_BE 0x7f000001 /* 127.0.0.1 */
#define ADDR_LE 0x0100007f
#define HOSTNAME "localhost" /* for cert verification if enabled */
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
const char *pers = "mini_client";
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
const unsigned char psk[] = {
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f
};
const char psk_id[] = "Client_identity";
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/* This is tests/data_files/test-ca2.crt, a CA using EC secp384r1 */
const unsigned char ca_cert[] = {
0x30, 0x82, 0x02, 0x52, 0x30, 0x82, 0x01, 0xd7, 0xa0, 0x03, 0x02, 0x01,
0x02, 0x02, 0x09, 0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8,
0x30, 0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02,
0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a,
0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c,
0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c,
0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45,
0x43, 0x20, 0x43, 0x41, 0x30, 0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x39,
0x32, 0x34, 0x31, 0x35, 0x34, 0x39, 0x34, 0x38, 0x5a, 0x17, 0x0d, 0x32,
0x33, 0x30, 0x39, 0x32, 0x32, 0x31, 0x35, 0x34, 0x39, 0x34, 0x38, 0x5a,
0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09, 0x06, 0x03, 0x55, 0x04, 0x06, 0x13,
0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30, 0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a,
0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c,
0x30, 0x1a, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c,
0x61, 0x72, 0x73, 0x73, 0x6c, 0x20, 0x54, 0x65, 0x73, 0x74, 0x20, 0x45,
0x43, 0x20, 0x43, 0x41, 0x30, 0x76, 0x30, 0x10, 0x06, 0x07, 0x2a, 0x86,
0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x05, 0x2b, 0x81, 0x04, 0x00, 0x22,
0x03, 0x62, 0x00, 0x04, 0xc3, 0xda, 0x2b, 0x34, 0x41, 0x37, 0x58, 0x2f,
0x87, 0x56, 0xfe, 0xfc, 0x89, 0xba, 0x29, 0x43, 0x4b, 0x4e, 0xe0, 0x6e,
0xc3, 0x0e, 0x57, 0x53, 0x33, 0x39, 0x58, 0xd4, 0x52, 0xb4, 0x91, 0x95,
0x39, 0x0b, 0x23, 0xdf, 0x5f, 0x17, 0x24, 0x62, 0x48, 0xfc, 0x1a, 0x95,
0x29, 0xce, 0x2c, 0x2d, 0x87, 0xc2, 0x88, 0x52, 0x80, 0xaf, 0xd6, 0x6a,
0xab, 0x21, 0xdd, 0xb8, 0xd3, 0x1c, 0x6e, 0x58, 0xb8, 0xca, 0xe8, 0xb2,
0x69, 0x8e, 0xf3, 0x41, 0xad, 0x29, 0xc3, 0xb4, 0x5f, 0x75, 0xa7, 0x47,
0x6f, 0xd5, 0x19, 0x29, 0x55, 0x69, 0x9a, 0x53, 0x3b, 0x20, 0xb4, 0x66,
0x16, 0x60, 0x33, 0x1e, 0xa3, 0x81, 0xa0, 0x30, 0x81, 0x9d, 0x30, 0x1d,
0x06, 0x03, 0x55, 0x1d, 0x0e, 0x04, 0x16, 0x04, 0x14, 0x9d, 0x6d, 0x20,
0x24, 0x49, 0x01, 0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24,
0xc9, 0xdb, 0xfb, 0x36, 0x7c, 0x30, 0x6e, 0x06, 0x03, 0x55, 0x1d, 0x23,
0x04, 0x67, 0x30, 0x65, 0x80, 0x14, 0x9d, 0x6d, 0x20, 0x24, 0x49, 0x01,
0x3f, 0x2b, 0xcb, 0x78, 0xb5, 0x19, 0xbc, 0x7e, 0x24, 0xc9, 0xdb, 0xfb,
0x36, 0x7c, 0xa1, 0x42, 0xa4, 0x40, 0x30, 0x3e, 0x31, 0x0b, 0x30, 0x09,
0x06, 0x03, 0x55, 0x04, 0x06, 0x13, 0x02, 0x4e, 0x4c, 0x31, 0x11, 0x30,
0x0f, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x08, 0x50, 0x6f, 0x6c, 0x61,
0x72, 0x53, 0x53, 0x4c, 0x31, 0x1c, 0x30, 0x1a, 0x06, 0x03, 0x55, 0x04,
0x03, 0x13, 0x13, 0x50, 0x6f, 0x6c, 0x61, 0x72, 0x73, 0x73, 0x6c, 0x20,
0x54, 0x65, 0x73, 0x74, 0x20, 0x45, 0x43, 0x20, 0x43, 0x41, 0x82, 0x09,
0x00, 0xc1, 0x43, 0xe2, 0x7e, 0x62, 0x43, 0xcc, 0xe8, 0x30, 0x0c, 0x06,
0x03, 0x55, 0x1d, 0x13, 0x04, 0x05, 0x30, 0x03, 0x01, 0x01, 0xff, 0x30,
0x0a, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x03,
0x69, 0x00, 0x30, 0x66, 0x02, 0x31, 0x00, 0xc3, 0xb4, 0x62, 0x73, 0x56,
0x28, 0x95, 0x00, 0x7d, 0x78, 0x12, 0x26, 0xd2, 0x71, 0x7b, 0x19, 0xf8,
0x8a, 0x98, 0x3e, 0x92, 0xfe, 0x33, 0x9e, 0xe4, 0x79, 0xd2, 0xfe, 0x7a,
0xb7, 0x87, 0x74, 0x3c, 0x2b, 0xb8, 0xd7, 0x69, 0x94, 0x0b, 0xa3, 0x67,
0x77, 0xb8, 0xb3, 0xbe, 0xd1, 0x36, 0x32, 0x02, 0x31, 0x00, 0xfd, 0x67,
0x9c, 0x94, 0x23, 0x67, 0xc0, 0x56, 0xba, 0x4b, 0x33, 0x15, 0x00, 0xc6,
0xe3, 0xcc, 0x31, 0x08, 0x2c, 0x9c, 0x8b, 0xda, 0xa9, 0x75, 0x23, 0x2f,
0xb8, 0x28, 0xe7, 0xf2, 0x9c, 0x14, 0x3a, 0x40, 0x01, 0x5c, 0xaf, 0x0c,
0xb2, 0xcf, 0x74, 0x7f, 0x30, 0x9f, 0x08, 0x43, 0xad, 0x20,
};
#endif /* MBEDTLS_X509_CRT_PARSE_C */
enum exit_codes
{
exit_ok = 0,
ctr_drbg_seed_failed,
ssl_config_defaults_failed,
ssl_setup_failed,
hostname_failed,
socket_failed,
connect_failed,
x509_crt_parse_failed,
ssl_handshake_failed,
ssl_write_failed,
};
int main( void )
{
int ret = exit_ok;
mbedtls_net_context server_fd;
struct sockaddr_in addr;
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt ca;
#endif
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_ctr_drbg_init( &ctr_drbg );
/*
* 0. Initialize and setup stuff
*/
mbedtls_net_init( &server_fd );
mbedtls_ssl_init( &ssl );
mbedtls_ssl_config_init( &conf );
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt_init( &ca );
#endif
mbedtls_entropy_init( &entropy );
if( mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers, strlen( pers ) ) != 0 )
{
ret = ctr_drbg_seed_failed;
goto exit;
}
if( mbedtls_ssl_config_defaults( &conf,
MBEDTLS_SSL_IS_CLIENT,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) != 0 )
{
ret = ssl_config_defaults_failed;
goto exit;
}
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
#if defined(MBEDTLS_KEY_EXCHANGE_SOME_PSK_ENABLED)
mbedtls_ssl_conf_psk( &conf, psk, sizeof( psk ),
(const unsigned char *) psk_id, sizeof( psk_id ) - 1 );
#endif
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if( mbedtls_x509_crt_parse_der( &ca, ca_cert, sizeof( ca_cert ) ) != 0 )
{
ret = x509_crt_parse_failed;
goto exit;
}
mbedtls_ssl_conf_ca_chain( &conf, &ca, NULL );
mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED );
#endif
if( mbedtls_ssl_setup( &ssl, &conf ) != 0 )
{
ret = ssl_setup_failed;
goto exit;
}
#if defined(MBEDTLS_X509_CRT_PARSE_C)
if( mbedtls_ssl_set_hostname( &ssl, HOSTNAME ) != 0 )
{
ret = hostname_failed;
goto exit;
}
#endif
/*
* 1. Start the connection
*/
memset( &addr, 0, sizeof( addr ) );
addr.sin_family = AF_INET;
ret = 1; /* for endianness detection */
addr.sin_port = *((char *) &ret) == ret ? PORT_LE : PORT_BE;
addr.sin_addr.s_addr = *((char *) &ret) == ret ? ADDR_LE : ADDR_BE;
ret = 0;
if( ( server_fd.fd = socket( AF_INET, SOCK_STREAM, 0 ) ) < 0 )
{
ret = socket_failed;
goto exit;
}
if( connect( server_fd.fd,
(const struct sockaddr *) &addr, sizeof( addr ) ) < 0 )
{
ret = connect_failed;
goto exit;
}
mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
if( mbedtls_ssl_handshake( &ssl ) != 0 )
{
ret = ssl_handshake_failed;
goto exit;
}
/*
* 2. Write the GET request and close the connection
*/
if( mbedtls_ssl_write( &ssl, (const unsigned char *) GET_REQUEST,
sizeof( GET_REQUEST ) - 1 ) <= 0 )
{
ret = ssl_write_failed;
goto exit;
}
mbedtls_ssl_close_notify( &ssl );
exit:
mbedtls_net_free( &server_fd );
mbedtls_ssl_free( &ssl );
mbedtls_ssl_config_free( &conf );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
#if defined(MBEDTLS_X509_CRT_PARSE_C)
mbedtls_x509_crt_free( &ca );
#endif
mbedtls_exit( ret );
}
#endif

View File

@ -0,0 +1,312 @@
/*
* SSL client demonstration program
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_time time
#define mbedtls_time_t time_t
#define mbedtls_fprintf fprintf
#define mbedtls_printf printf
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
!defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_PEM_PARSE_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C)
int main( void )
{
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
"MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
"MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
"MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
"not defined.\n");
mbedtls_exit( 0 );
}
#else
#include "mbedtls/net_sockets.h"
#include "mbedtls/debug.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/error.h"
#include "test/certs.h"
#include <string.h>
#define SERVER_PORT "4433"
#define SERVER_NAME "localhost"
#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n"
#define DEBUG_LEVEL 1
static void my_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
((void) level);
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
fflush( (FILE *) ctx );
}
int main( void )
{
int ret = 1, len;
int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_net_context server_fd;
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_ssl_config conf;
mbedtls_x509_crt cacert;
#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. Initialize 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", (unsigned int) -ret );
goto exit;
}
mbedtls_printf( " ok (%d skipped)\n", ret );
/*
* 1. Start the connection
*/
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;
}
mbedtls_printf( " ok\n" );
/*
* 2. Setup stuff
*/
mbedtls_printf( " . Setting up the SSL/TLS structure..." );
fflush( stdout );
if( ( ret = mbedtls_ssl_config_defaults( &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;
}
mbedtls_printf( " ok\n" );
/* OPTIONAL is not optimal for security,
* but makes interop easier in this simplified example */
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, NULL );
/*
* 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 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", (unsigned int) -ret );
goto exit;
}
}
mbedtls_printf( " ok\n" );
/*
* 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 )
{
#if !defined(MBEDTLS_X509_REMOVE_INFO)
char vrfy_buf[512];
#endif
mbedtls_printf( " failed\n" );
#if !defined(MBEDTLS_X509_REMOVE_INFO)
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
mbedtls_printf( "%s\n", vrfy_buf );
#endif
}
else
mbedtls_printf( " ok\n" );
/*
* 3. Write the GET request
*/
mbedtls_printf( " > Write to server:" );
fflush( stdout );
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 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret );
goto exit;
}
}
len = ret;
mbedtls_printf( " %d bytes written\n\n%s", len, (char *) buf );
/*
* 7. Read the HTTP response
*/
mbedtls_printf( " < Read from server:" );
fflush( stdout );
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 )
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;
mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf );
}
while( 1 );
mbedtls_ssl_close_notify( &ssl );
exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
#ifdef MBEDTLS_ERROR_C
if( exit_code != MBEDTLS_EXIT_SUCCESS )
{
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 );
mbedtls_exit( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C &&
MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,415 @@
/*
* SSL server demonstration program using fork() for handling multiple clients
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_fprintf fprintf
#define mbedtls_printf printf
#define mbedtls_time_t time_t
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_SRV_C) || \
!defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
!defined(MBEDTLS_TIMING_C) || !defined(MBEDTLS_FS_IO) || \
!defined(MBEDTLS_PEM_PARSE_C)
int main( int argc, char *argv[] )
{
((void) argc);
((void) argv);
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C "
"and/or MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or "
"MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
"MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
"MBEDTLS_TIMING_C and/or MBEDTLS_PEM_PARSE_C not defined.\n");
mbedtls_exit( 0 );
}
#elif defined(_WIN32)
int main( void )
{
mbedtls_printf("_WIN32 defined. This application requires fork() and signals "
"to work correctly.\n");
mbedtls_exit( 0 );
}
#else
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "test/certs.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/timing.h"
#include <string.h>
#include <signal.h>
#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32)
#include <unistd.h>
#endif
#define HTTP_RESPONSE \
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
"<h2>mbed TLS Test Server</h2>\r\n" \
"<p>Successful connection using: %s</p>\r\n"
#define DEBUG_LEVEL 0
static void my_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
((void) level);
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
fflush( (FILE *) ctx );
}
int main( void )
{
int ret = 1, len, cnt = 0, pid;
int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_net_context listen_fd, client_fd;
unsigned char buf[1024];
const char *pers = "ssl_fork_server";
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt srvcert;
mbedtls_pk_context pkey;
mbedtls_net_init( &listen_fd );
mbedtls_net_init( &client_fd );
mbedtls_ssl_init( &ssl );
mbedtls_ssl_config_init( &conf );
mbedtls_entropy_init( &entropy );
mbedtls_pk_init( &pkey );
mbedtls_x509_crt_init( &srvcert );
mbedtls_ctr_drbg_init( &ctr_drbg );
signal( SIGCHLD, SIG_IGN );
/*
* 0. Initial seeding of the RNG
*/
mbedtls_printf( "\n . Initial seeding of the random generator..." );
fflush( stdout );
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers,
strlen( pers ) ) ) != 0 )
{
mbedtls_printf( " failed! mbedtls_ctr_drbg_seed returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 1. Load the certificates and private RSA key
*/
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! 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! 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,
mbedtls_ctr_drbg_random, &ctr_drbg );
if( ret != 0 )
{
mbedtls_printf( " failed! mbedtls_pk_parse_key returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 1b. Prepare SSL configuration
*/
mbedtls_printf( " . Configuring SSL..." );
fflush( stdout );
if( ( ret = mbedtls_ssl_config_defaults( &conf,
MBEDTLS_SSL_IS_SERVER,
MBEDTLS_SSL_TRANSPORT_STREAM,
MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
{
mbedtls_printf( " failed! mbedtls_ssl_config_defaults returned %d\n\n", ret );
goto exit;
}
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
mbedtls_ssl_conf_ca_chain( &conf, srvcert.next, NULL );
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
{
mbedtls_printf( " failed! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 2. Setup the listening TCP socket
*/
mbedtls_printf( " . Bind on https://localhost:4433/ ..." );
fflush( stdout );
if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 )
{
mbedtls_printf( " failed! mbedtls_net_bind returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
while( 1 )
{
/*
* 3. Wait until a client connects
*/
mbedtls_net_init( &client_fd );
mbedtls_ssl_init( &ssl );
mbedtls_printf( " . Waiting for a remote connection ...\n" );
fflush( stdout );
if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
NULL, 0, NULL ) ) != 0 )
{
mbedtls_printf( " failed! mbedtls_net_accept returned %d\n\n", ret );
goto exit;
}
/*
* 3.5. Forking server thread
*/
mbedtls_printf( " . Forking to handle connection ..." );
fflush( stdout );
pid = fork();
if( pid < 0 )
{
mbedtls_printf(" failed! fork returned %d\n\n", pid );
goto exit;
}
if( pid != 0 )
{
mbedtls_printf( " ok\n" );
mbedtls_net_close( &client_fd );
if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg,
(const unsigned char *) "parent",
6 ) ) != 0 )
{
mbedtls_printf( " failed! mbedtls_ctr_drbg_reseed returned %d\n\n", ret );
goto exit;
}
continue;
}
mbedtls_net_close( &listen_fd );
pid = getpid();
/*
* 4. Setup stuff
*/
mbedtls_printf( "pid %d: Setting up the SSL data.\n", pid );
fflush( stdout );
if( ( ret = mbedtls_ctr_drbg_reseed( &ctr_drbg,
(const unsigned char *) "child",
5 ) ) != 0 )
{
mbedtls_printf(
"pid %d: SSL setup failed! mbedtls_ctr_drbg_reseed returned %d\n\n",
pid, ret );
goto exit;
}
if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
{
mbedtls_printf(
"pid %d: SSL setup failed! mbedtls_ssl_setup returned %d\n\n",
pid, ret );
goto exit;
}
mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
mbedtls_printf( "pid %d: SSL setup ok\n", pid );
/*
* 5. Handshake
*/
mbedtls_printf( "pid %d: Performing the SSL/TLS handshake.\n", pid );
fflush( stdout );
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
mbedtls_printf(
"pid %d: SSL handshake failed! mbedtls_ssl_handshake returned %d\n\n",
pid, ret );
goto exit;
}
}
mbedtls_printf( "pid %d: SSL handshake ok\n", pid );
/*
* 6. Read the HTTP Request
*/
mbedtls_printf( "pid %d: Start reading from client.\n", pid );
fflush( stdout );
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( "pid %d: connection was closed gracefully\n", pid );
break;
case MBEDTLS_ERR_NET_CONN_RESET:
mbedtls_printf( "pid %d: connection was reset by peer\n", pid );
break;
default:
mbedtls_printf( "pid %d: mbedtls_ssl_read returned %d\n", pid, ret );
break;
}
break;
}
len = ret;
mbedtls_printf( "pid %d: %d bytes read\n\n%s", pid, len, (char *) buf );
if( ret > 0 )
break;
}
while( 1 );
/*
* 7. Write the 200 Response
*/
mbedtls_printf( "pid %d: Start writing to client.\n", pid );
fflush( stdout );
len = sprintf( (char *) buf, HTTP_RESPONSE,
mbedtls_ssl_get_ciphersuite( &ssl ) );
while( cnt++ < 100 )
{
while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 )
{
if( ret == MBEDTLS_ERR_NET_CONN_RESET )
{
mbedtls_printf(
"pid %d: Write failed! peer closed the connection\n\n", pid );
goto exit;
}
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
mbedtls_printf(
"pid %d: Write failed! mbedtls_ssl_write returned %d\n\n",
pid, ret );
goto exit;
}
}
len = ret;
mbedtls_printf( "pid %d: %d bytes written\n\n%s\n", pid, len, (char *) buf );
mbedtls_net_usleep( 1000000 );
}
mbedtls_ssl_close_notify( &ssl );
goto exit;
}
exit_code = MBEDTLS_EXIT_SUCCESS;
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 );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
mbedtls_exit( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C &&
MBEDTLS_RSA_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_PARSE_C &&
! _WIN32 */

View File

@ -0,0 +1,855 @@
/*
* SSL client for SMTP servers
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Enable definition of gethostname() even when compiling with -std=c99. Must
* be set before mbedtls_config.h, which pulls in glibc's features.h indirectly.
* Harmless on other platforms. */
#define _POSIX_C_SOURCE 200112L
#define _XOPEN_SOURCE 600
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_time time
#define mbedtls_time_t time_t
#define mbedtls_fprintf fprintf
#define mbedtls_printf printf
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif /* MBEDTLS_PLATFORM_C */
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \
!defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
!defined(MBEDTLS_FS_IO)
int main( void )
{
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C and/or "
"MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or "
"MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
"MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
"not defined.\n");
mbedtls_exit( 0 );
}
#else
#include "mbedtls/base64.h"
#include "mbedtls/error.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/ssl.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "test/certs.h"
#include "mbedtls/x509.h"
#include <stdlib.h>
#include <string.h>
#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32)
#include <unistd.h>
#else
#include <io.h>
#endif
#if defined(_WIN32) || defined(_WIN32_WCE)
#include <winsock2.h>
#include <windows.h>
#if defined(_MSC_VER)
#if defined(_WIN32_WCE)
#pragma comment( lib, "ws2.lib" )
#else
#pragma comment( lib, "ws2_32.lib" )
#endif
#endif /* _MSC_VER */
#endif
#define DFL_SERVER_NAME "localhost"
#define DFL_SERVER_PORT "465"
#define DFL_USER_NAME "user"
#define DFL_USER_PWD "password"
#define DFL_MAIL_FROM ""
#define DFL_MAIL_TO ""
#define DFL_DEBUG_LEVEL 0
#define DFL_CA_FILE ""
#define DFL_CRT_FILE ""
#define DFL_KEY_FILE ""
#define DFL_FORCE_CIPHER 0
#define DFL_MODE 0
#define DFL_AUTHENTICATION 0
#define MODE_SSL_TLS 0
#define MODE_STARTTLS 0
#if defined(MBEDTLS_BASE64_C)
#define USAGE_AUTH \
" authentication=%%d default: 0 (disabled)\n" \
" user_name=%%s default: \"" DFL_USER_NAME "\"\n" \
" user_pwd=%%s default: \"" DFL_USER_PWD "\"\n"
#else
#define USAGE_AUTH \
" authentication options disabled. (Require MBEDTLS_BASE64_C)\n"
#endif /* MBEDTLS_BASE64_C */
#if defined(MBEDTLS_FS_IO)
#define USAGE_IO \
" ca_file=%%s default: \"\" (pre-loaded)\n" \
" crt_file=%%s default: \"\" (pre-loaded)\n" \
" key_file=%%s default: \"\" (pre-loaded)\n"
#else
#define USAGE_IO \
" No file operations available (MBEDTLS_FS_IO not defined)\n"
#endif /* MBEDTLS_FS_IO */
#define USAGE \
"\n usage: ssl_mail_client param=<>...\n" \
"\n acceptable parameters:\n" \
" server_name=%%s default: " DFL_SERVER_NAME "\n" \
" server_port=%%d default: " DFL_SERVER_PORT "\n" \
" debug_level=%%d default: 0 (disabled)\n" \
" mode=%%d default: 0 (SSL/TLS) (1 for STARTTLS)\n" \
USAGE_AUTH \
" mail_from=%%s default: \"\"\n" \
" mail_to=%%s default: \"\"\n" \
USAGE_IO \
" force_ciphersuite=<name> default: all enabled\n" \
" acceptable ciphersuite names:\n"
/*
* global options
*/
struct options
{
const char *server_name; /* hostname of the server (client only) */
const char *server_port; /* port on which the ssl service runs */
int debug_level; /* level of debugging */
int authentication; /* if authentication is required */
int mode; /* SSL/TLS (0) or STARTTLS (1) */
const char *user_name; /* username to use for authentication */
const char *user_pwd; /* password to use for authentication */
const char *mail_from; /* E-Mail address to use as sender */
const char *mail_to; /* E-Mail address to use as recipient */
const char *ca_file; /* the file with the CA certificate(s) */
const char *crt_file; /* the file with the client certificate */
const char *key_file; /* the file with the client key */
int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */
} opt;
static void my_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
((void) level);
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
fflush( (FILE *) ctx );
}
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 )
{
#if !defined(MBEDTLS_X509_REMOVE_INFO)
char vrfy_buf[512];
#endif
mbedtls_printf( " failed\n" );
#if !defined(MBEDTLS_X509_REMOVE_INFO)
mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags );
mbedtls_printf( "%s\n", vrfy_buf );
#endif
}
else
mbedtls_printf( " ok\n" );
#if !defined(MBEDTLS_X509_REMOVE_INFO)
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 );
#endif
return( 0 );
}
static int write_ssl_data( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
{
int ret;
mbedtls_printf("\n%s", buf);
while( len && ( ret = mbedtls_ssl_write( 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 );
return -1;
}
}
return( 0 );
}
static int write_ssl_and_get_response( mbedtls_ssl_context *ssl, unsigned char *buf, size_t len )
{
int ret;
unsigned char data[128];
char code[4];
size_t i, idx = 0;
mbedtls_printf("\n%s", buf);
while( len && ( ret = mbedtls_ssl_write( 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 );
return -1;
}
}
do
{
len = sizeof( data ) - 1;
memset( data, 0, sizeof( data ) );
ret = mbedtls_ssl_read( ssl, data, len );
if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
continue;
if( ret == MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY )
return -1;
if( ret <= 0 )
{
mbedtls_printf( "failed\n ! mbedtls_ssl_read returned %d\n\n", ret );
return -1;
}
mbedtls_printf("\n%s", data);
len = ret;
for( i = 0; i < len; i++ )
{
if( data[i] != '\n' )
{
if( idx < 4 )
code[ idx++ ] = data[i];
continue;
}
if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' )
{
code[3] = '\0';
return atoi( code );
}
idx = 0;
}
}
while( 1 );
}
static int write_and_get_response( mbedtls_net_context *sock_fd, unsigned char *buf, size_t len )
{
int ret;
unsigned char data[128];
char code[4];
size_t i, idx = 0;
mbedtls_printf("\n%s", buf);
if( len && ( ret = mbedtls_net_send( sock_fd, buf, len ) ) <= 0 )
{
mbedtls_printf( " failed\n ! mbedtls_net_send returned %d\n\n", ret );
return -1;
}
do
{
len = sizeof( data ) - 1;
memset( data, 0, sizeof( data ) );
ret = mbedtls_net_recv( sock_fd, data, len );
if( ret <= 0 )
{
mbedtls_printf( "failed\n ! mbedtls_net_recv returned %d\n\n", ret );
return -1;
}
data[len] = '\0';
mbedtls_printf("\n%s", data);
len = ret;
for( i = 0; i < len; i++ )
{
if( data[i] != '\n' )
{
if( idx < 4 )
code[ idx++ ] = data[i];
continue;
}
if( idx == 4 && code[0] >= '0' && code[0] <= '9' && code[3] == ' ' )
{
code[3] = '\0';
return atoi( code );
}
idx = 0;
}
}
while( 1 );
}
int main( int argc, char *argv[] )
{
int ret = 1, len;
int exit_code = MBEDTLS_EXIT_FAILURE;
mbedtls_net_context server_fd;
#if defined(MBEDTLS_BASE64_C)
unsigned char base[1024];
/* buf is used as the destination buffer for printing base with the format:
* "%s\r\n". Hence, the size of buf should be at least the size of base
* plus 2 bytes for the \r and \n characters.
*/
unsigned char buf[sizeof( base ) + 2];
#else
unsigned char buf[1024];
#endif
char hostname[32];
const char *pers = "ssl_mail_client";
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 clicert;
mbedtls_pk_context pkey;
int i;
size_t n;
char *p, *q;
const int *list;
/*
* Make sure memory references are valid in case we exit early.
*/
mbedtls_net_init( &server_fd );
mbedtls_ssl_init( &ssl );
mbedtls_ssl_config_init( &conf );
memset( &buf, 0, sizeof( buf ) );
mbedtls_x509_crt_init( &cacert );
mbedtls_x509_crt_init( &clicert );
mbedtls_pk_init( &pkey );
mbedtls_ctr_drbg_init( &ctr_drbg );
if( argc == 0 )
{
usage:
mbedtls_printf( USAGE );
list = mbedtls_ssl_list_ciphersuites();
while( *list )
{
mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) );
list++;
}
mbedtls_printf("\n");
goto exit;
}
opt.server_name = DFL_SERVER_NAME;
opt.server_port = DFL_SERVER_PORT;
opt.debug_level = DFL_DEBUG_LEVEL;
opt.authentication = DFL_AUTHENTICATION;
opt.mode = DFL_MODE;
opt.user_name = DFL_USER_NAME;
opt.user_pwd = DFL_USER_PWD;
opt.mail_from = DFL_MAIL_FROM;
opt.mail_to = DFL_MAIL_TO;
opt.ca_file = DFL_CA_FILE;
opt.crt_file = DFL_CRT_FILE;
opt.key_file = DFL_KEY_FILE;
opt.force_ciphersuite[0]= DFL_FORCE_CIPHER;
for( i = 1; i < argc; i++ )
{
p = argv[i];
if( ( q = strchr( p, '=' ) ) == NULL )
goto usage;
*q++ = '\0';
if( strcmp( p, "server_name" ) == 0 )
opt.server_name = q;
else if( strcmp( p, "server_port" ) == 0 )
opt.server_port = q;
else if( strcmp( p, "debug_level" ) == 0 )
{
opt.debug_level = atoi( q );
if( opt.debug_level < 0 || opt.debug_level > 65535 )
goto usage;
}
else if( strcmp( p, "authentication" ) == 0 )
{
opt.authentication = atoi( q );
if( opt.authentication < 0 || opt.authentication > 1 )
goto usage;
}
else if( strcmp( p, "mode" ) == 0 )
{
opt.mode = atoi( q );
if( opt.mode < 0 || opt.mode > 1 )
goto usage;
}
else if( strcmp( p, "user_name" ) == 0 )
opt.user_name = q;
else if( strcmp( p, "user_pwd" ) == 0 )
opt.user_pwd = q;
else if( strcmp( p, "mail_from" ) == 0 )
opt.mail_from = q;
else if( strcmp( p, "mail_to" ) == 0 )
opt.mail_to = q;
else if( strcmp( p, "ca_file" ) == 0 )
opt.ca_file = q;
else if( strcmp( p, "crt_file" ) == 0 )
opt.crt_file = q;
else if( strcmp( p, "key_file" ) == 0 )
opt.key_file = q;
else if( strcmp( p, "force_ciphersuite" ) == 0 )
{
opt.force_ciphersuite[0] = -1;
opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q );
if( opt.force_ciphersuite[0] <= 0 )
goto usage;
opt.force_ciphersuite[1] = 0;
}
else
goto usage;
}
/*
* 0. Initialize the RNG and the session data
*/
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" );
/*
* 1.1. Load the trusted CA
*/
mbedtls_printf( " . Loading the CA root certificate ..." );
fflush( stdout );
#if defined(MBEDTLS_FS_IO)
if( strlen( opt.ca_file ) )
ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file );
else
#endif
#if defined(MBEDTLS_PEM_PARSE_C)
ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_cas_pem,
mbedtls_test_cas_pem_len );
#else
{
mbedtls_printf("MBEDTLS_PEM_PARSE_C not defined.");
goto exit;
}
#endif
if( ret < 0 )
{
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok (%d skipped)\n", ret );
/*
* 1.2. Load own certificate and private key
*
* (can be skipped if client authentication is not required)
*/
mbedtls_printf( " . Loading the client cert. and key..." );
fflush( stdout );
#if defined(MBEDTLS_FS_IO)
if( strlen( opt.crt_file ) )
ret = mbedtls_x509_crt_parse_file( &clicert, opt.crt_file );
else
#endif
ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt,
mbedtls_test_cli_crt_len );
if( ret != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned %d\n\n", ret );
goto exit;
}
#if defined(MBEDTLS_FS_IO)
if( strlen( opt.key_file ) )
{
ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "",
mbedtls_ctr_drbg_random, &ctr_drbg );
}
else
#endif
#if defined(MBEDTLS_PEM_PARSE_C)
{
ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_cli_key,
mbedtls_test_cli_key_len, NULL, 0, mbedtls_ctr_drbg_random, &ctr_drbg );
}
#else
{
mbedtls_printf("MBEDTLS_PEM_PARSE_C not defined.");
goto exit;
}
#endif
if( ret != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 2. Start the connection
*/
mbedtls_printf( " . Connecting to tcp/%s/%s...", opt.server_name,
opt.server_port );
fflush( stdout );
if( ( ret = mbedtls_net_connect( &server_fd, opt.server_name,
opt.server_port, MBEDTLS_NET_PROTO_TCP ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 3. Setup stuff
*/
mbedtls_printf( " . Setting up the SSL/TLS structure..." );
fflush( stdout );
if( ( ret = mbedtls_ssl_config_defaults( &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;
}
/* OPTIONAL is not optimal for security,
* but makes interop easier in this simplified example */
mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL );
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER )
mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite );
mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL );
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &clicert, &pkey ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
goto exit;
}
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, opt.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, NULL );
mbedtls_printf( " ok\n" );
if( opt.mode == MODE_SSL_TLS )
{
if( do_handshake( &ssl ) != 0 )
goto exit;
mbedtls_printf( " > Get header from server:" );
fflush( stdout );
ret = write_ssl_and_get_response( &ssl, buf, 0 );
if( ret < 200 || ret > 299 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_printf( " > Write EHLO to server:" );
fflush( stdout );
gethostname( hostname, 32 );
len = sprintf( (char *) buf, "EHLO %s\r\n", hostname );
ret = write_ssl_and_get_response( &ssl, buf, len );
if( ret < 200 || ret > 299 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
}
else
{
mbedtls_printf( " > Get header from server:" );
fflush( stdout );
ret = write_and_get_response( &server_fd, buf, 0 );
if( ret < 200 || ret > 299 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_printf( " > Write EHLO to server:" );
fflush( stdout );
gethostname( hostname, 32 );
len = sprintf( (char *) buf, "EHLO %s\r\n", hostname );
ret = write_and_get_response( &server_fd, buf, len );
if( ret < 200 || ret > 299 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_printf( " > Write STARTTLS to server:" );
fflush( stdout );
gethostname( hostname, 32 );
len = sprintf( (char *) buf, "STARTTLS\r\n" );
ret = write_and_get_response( &server_fd, buf, len );
if( ret < 200 || ret > 299 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
if( do_handshake( &ssl ) != 0 )
goto exit;
}
#if defined(MBEDTLS_BASE64_C)
if( opt.authentication )
{
mbedtls_printf( " > Write AUTH LOGIN to server:" );
fflush( stdout );
len = sprintf( (char *) buf, "AUTH LOGIN\r\n" );
ret = write_ssl_and_get_response( &ssl, buf, len );
if( ret < 200 || ret > 399 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_printf( " > Write username to server: %s", opt.user_name );
fflush( stdout );
ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_name,
strlen( opt.user_name ) );
if( ret != 0 ) {
mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret );
goto exit;
}
len = sprintf( (char *) buf, "%s\r\n", base );
ret = write_ssl_and_get_response( &ssl, buf, len );
if( ret < 300 || ret > 399 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_printf( " > Write password to server: %s", opt.user_pwd );
fflush( stdout );
ret = mbedtls_base64_encode( base, sizeof( base ), &n, (const unsigned char *) opt.user_pwd,
strlen( opt.user_pwd ) );
if( ret != 0 ) {
mbedtls_printf( " failed\n ! mbedtls_base64_encode returned %d\n\n", ret );
goto exit;
}
len = sprintf( (char *) buf, "%s\r\n", base );
ret = write_ssl_and_get_response( &ssl, buf, len );
if( ret < 200 || ret > 399 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
}
#endif
mbedtls_printf( " > Write MAIL FROM to server:" );
fflush( stdout );
len = sprintf( (char *) buf, "MAIL FROM:<%s>\r\n", opt.mail_from );
ret = write_ssl_and_get_response( &ssl, buf, len );
if( ret < 200 || ret > 299 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_printf( " > Write RCPT TO to server:" );
fflush( stdout );
len = sprintf( (char *) buf, "RCPT TO:<%s>\r\n", opt.mail_to );
ret = write_ssl_and_get_response( &ssl, buf, len );
if( ret < 200 || ret > 299 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_printf( " > Write DATA to server:" );
fflush( stdout );
len = sprintf( (char *) buf, "DATA\r\n" );
ret = write_ssl_and_get_response( &ssl, buf, len );
if( ret < 300 || ret > 399 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_printf( " > Write content to server:" );
fflush( stdout );
len = sprintf( (char *) buf, "From: %s\r\nSubject: mbed TLS Test mail\r\n\r\n"
"This is a simple test mail from the "
"mbed TLS mail client example.\r\n"
"\r\n"
"Enjoy!", opt.mail_from );
ret = write_ssl_data( &ssl, buf, len );
len = sprintf( (char *) buf, "\r\n.\r\n");
ret = write_ssl_and_get_response( &ssl, buf, len );
if( ret < 200 || ret > 299 )
{
mbedtls_printf( " failed\n ! server responded with %d\n\n", ret );
goto exit;
}
mbedtls_printf(" ok\n" );
mbedtls_ssl_close_notify( &ssl );
exit_code = MBEDTLS_EXIT_SUCCESS;
exit:
mbedtls_net_free( &server_fd );
mbedtls_x509_crt_free( &clicert );
mbedtls_x509_crt_free( &cacert );
mbedtls_pk_free( &pkey );
mbedtls_ssl_free( &ssl );
mbedtls_ssl_config_free( &conf );
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
mbedtls_exit( exit_code );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C &&
MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C **
MBEDTLS_CTR_DRBG_C */

View File

@ -0,0 +1,524 @@
/*
* SSL server demonstration program using pthread for handling multiple
* clients.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_fprintf fprintf
#define mbedtls_printf printf
#define mbedtls_snprintf snprintf
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_ENTROPY_C) || \
!defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_SRV_C) || \
!defined(MBEDTLS_NET_C) || !defined(MBEDTLS_RSA_C) || \
!defined(MBEDTLS_CTR_DRBG_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \
!defined(MBEDTLS_FS_IO) || !defined(MBEDTLS_THREADING_C) || \
!defined(MBEDTLS_THREADING_PTHREAD) || !defined(MBEDTLS_PEM_PARSE_C)
int main( void )
{
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C "
"and/or MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or "
"MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
"MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
"MBEDTLS_THREADING_C and/or MBEDTLS_THREADING_PTHREAD "
"and/or MBEDTLS_PEM_PARSE_C not defined.\n");
mbedtls_exit( 0 );
}
#else
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#endif
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/error.h"
#include "test/certs.h"
#if defined(MBEDTLS_SSL_CACHE_C)
#include "mbedtls/ssl_cache.h"
#endif
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#include "mbedtls/memory_buffer_alloc.h"
#endif
#define HTTP_RESPONSE \
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
"<h2>mbed TLS Test Server</h2>\r\n" \
"<p>Successful connection using: %s</p>\r\n"
#define DEBUG_LEVEL 0
#define MAX_NUM_THREADS 5
mbedtls_threading_mutex_t debug_mutex;
static void my_mutexed_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
long int thread_id = (long int) pthread_self();
mbedtls_mutex_lock( &debug_mutex );
((void) level);
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: [ #%ld ] %s",
file, line, thread_id, str );
fflush( (FILE *) ctx );
mbedtls_mutex_unlock( &debug_mutex );
}
typedef struct {
mbedtls_net_context client_fd;
int thread_complete;
const mbedtls_ssl_config *config;
} thread_info_t;
typedef struct {
int active;
thread_info_t data;
pthread_t thread;
} pthread_info_t;
static thread_info_t base_info;
static pthread_info_t threads[MAX_NUM_THREADS];
static void *handle_ssl_connection( void *data )
{
int ret, len;
thread_info_t *thread_info = (thread_info_t *) data;
mbedtls_net_context *client_fd = &thread_info->client_fd;
long int thread_id = (long int) pthread_self();
unsigned char buf[1024];
mbedtls_ssl_context ssl;
/* Make sure memory references are valid */
mbedtls_ssl_init( &ssl );
mbedtls_printf( " [ #%ld ] Setting up SSL/TLS data\n", thread_id );
/*
* 4. Get the SSL context ready
*/
if( ( ret = mbedtls_ssl_setup( &ssl, thread_info->config ) ) != 0 )
{
mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_setup returned -0x%04x\n",
thread_id, ( unsigned int ) -ret );
goto thread_exit;
}
mbedtls_ssl_set_bio( &ssl, client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
/*
* 5. Handshake
*/
mbedtls_printf( " [ #%ld ] Performing the SSL/TLS handshake\n", thread_id );
while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_handshake returned -0x%04x\n",
thread_id, ( unsigned int ) -ret );
goto thread_exit;
}
}
mbedtls_printf( " [ #%ld ] ok\n", thread_id );
/*
* 6. Read the HTTP Request
*/
mbedtls_printf( " [ #%ld ] < Read from client\n", thread_id );
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( " [ #%ld ] connection was closed gracefully\n",
thread_id );
goto thread_exit;
case MBEDTLS_ERR_NET_CONN_RESET:
mbedtls_printf( " [ #%ld ] connection was reset by peer\n",
thread_id );
goto thread_exit;
default:
mbedtls_printf( " [ #%ld ] mbedtls_ssl_read returned -0x%04x\n",
thread_id, ( unsigned int ) -ret );
goto thread_exit;
}
}
len = ret;
mbedtls_printf( " [ #%ld ] %d bytes read\n=====\n%s\n=====\n",
thread_id, len, (char *) buf );
if( ret > 0 )
break;
}
while( 1 );
/*
* 7. Write the 200 Response
*/
mbedtls_printf( " [ #%ld ] > Write to client:\n", thread_id );
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( " [ #%ld ] failed: peer closed the connection\n",
thread_id );
goto thread_exit;
}
if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_write returned -0x%04x\n",
thread_id, ( unsigned int ) ret );
goto thread_exit;
}
}
len = ret;
mbedtls_printf( " [ #%ld ] %d bytes written\n=====\n%s\n=====\n",
thread_id, len, (char *) buf );
mbedtls_printf( " [ #%ld ] . Closing the connection...", thread_id );
while( ( ret = mbedtls_ssl_close_notify( &ssl ) ) < 0 )
{
if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
ret != MBEDTLS_ERR_SSL_WANT_WRITE )
{
mbedtls_printf( " [ #%ld ] failed: mbedtls_ssl_close_notify returned -0x%04x\n",
thread_id, ( unsigned int ) ret );
goto thread_exit;
}
}
mbedtls_printf( " ok\n" );
ret = 0;
thread_exit:
#ifdef MBEDTLS_ERROR_C
if( ret != 0 )
{
char error_buf[100];
mbedtls_strerror( ret, error_buf, 100 );
mbedtls_printf(" [ #%ld ] Last error was: -0x%04x - %s\n\n",
thread_id, ( unsigned int ) -ret, error_buf );
}
#endif
mbedtls_net_free( client_fd );
mbedtls_ssl_free( &ssl );
thread_info->thread_complete = 1;
return( NULL );
}
static int thread_create( mbedtls_net_context *client_fd )
{
int ret, i;
/*
* Find in-active or finished thread slot
*/
for( i = 0; i < MAX_NUM_THREADS; i++ )
{
if( threads[i].active == 0 )
break;
if( threads[i].data.thread_complete == 1 )
{
mbedtls_printf( " [ main ] Cleaning up thread %d\n", i );
pthread_join(threads[i].thread, NULL );
memset( &threads[i], 0, sizeof(pthread_info_t) );
break;
}
}
if( i == MAX_NUM_THREADS )
return( -1 );
/*
* Fill thread-info for thread
*/
memcpy( &threads[i].data, &base_info, sizeof(base_info) );
threads[i].active = 1;
memcpy( &threads[i].data.client_fd, client_fd, sizeof( mbedtls_net_context ) );
if( ( ret = pthread_create( &threads[i].thread, NULL, handle_ssl_connection,
&threads[i].data ) ) != 0 )
{
return( ret );
}
return( 0 );
}
int main( void )
{
int ret;
mbedtls_net_context listen_fd, client_fd;
const char pers[] = "ssl_pthread_server";
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_config conf;
mbedtls_x509_crt srvcert;
mbedtls_x509_crt cachain;
mbedtls_pk_context pkey;
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
unsigned char alloc_buf[100000];
#endif
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_context cache;
#endif
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
#endif
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_init( &cache );
#endif
mbedtls_x509_crt_init( &srvcert );
mbedtls_x509_crt_init( &cachain );
mbedtls_ssl_config_init( &conf );
mbedtls_ctr_drbg_init( &ctr_drbg );
memset( threads, 0, sizeof(threads) );
mbedtls_net_init( &listen_fd );
mbedtls_net_init( &client_fd );
mbedtls_mutex_init( &debug_mutex );
base_info.config = &conf;
/*
* We use only a single entropy source that is used in all the threads.
*/
mbedtls_entropy_init( &entropy );
/*
* 1a. Seed the random number generator
*/
mbedtls_printf( " . Seeding the random number generator..." );
if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
(const unsigned char *) pers,
strlen( pers ) ) ) != 0 )
{
mbedtls_printf( " failed: mbedtls_ctr_drbg_seed returned -0x%04x\n",
( unsigned int ) -ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 1b. Load the certificates and private RSA key
*/
mbedtls_printf( "\n . 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( &cachain, (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;
}
mbedtls_pk_init( &pkey );
ret = mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key,
mbedtls_test_srv_key_len, NULL, 0,
mbedtls_ctr_drbg_random, &ctr_drbg );
if( ret != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 1c. Prepare SSL configuration
*/
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: mbedtls_ssl_config_defaults returned -0x%04x\n",
( unsigned int ) -ret );
goto exit;
}
mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
mbedtls_ssl_conf_dbg( &conf, my_mutexed_debug, stdout );
/* mbedtls_ssl_cache_get() and mbedtls_ssl_cache_set() are thread-safe if
* MBEDTLS_THREADING_C is set.
*/
#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, &cachain, NULL );
if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 2. Setup the listening TCP socket
*/
mbedtls_printf( " . Bind on https://localhost:4433/ ..." );
fflush( stdout );
if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
reset:
#ifdef MBEDTLS_ERROR_C
if( ret != 0 )
{
char error_buf[100];
mbedtls_strerror( ret, error_buf, 100 );
mbedtls_printf( " [ main ] Last error was: -0x%04x - %s\n", ( unsigned int ) -ret,
error_buf );
}
#endif
/*
* 3. Wait until a client connects
*/
mbedtls_printf( " [ main ] Waiting for a remote connection\n" );
if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
NULL, 0, NULL ) ) != 0 )
{
mbedtls_printf( " [ main ] failed: mbedtls_net_accept returned -0x%04x\n",
( unsigned int ) ret );
goto exit;
}
mbedtls_printf( " [ main ] ok\n" );
mbedtls_printf( " [ main ] Creating a new thread\n" );
if( ( ret = thread_create( &client_fd ) ) != 0 )
{
mbedtls_printf( " [ main ] failed: thread_create returned %d\n", ret );
mbedtls_net_free( &client_fd );
goto reset;
}
ret = 0;
goto reset;
exit:
mbedtls_x509_crt_free( &srvcert );
mbedtls_pk_free( &pkey );
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_free( &cache );
#endif
mbedtls_ctr_drbg_free( &ctr_drbg );
mbedtls_entropy_free( &entropy );
mbedtls_ssl_config_free( &conf );
mbedtls_net_free( &listen_fd );
mbedtls_mutex_free( &debug_mutex );
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
mbedtls_memory_buffer_alloc_free();
#endif
mbedtls_exit( ret );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C &&
MBEDTLS_RSA_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_THREADING_C &&
MBEDTLS_THREADING_PTHREAD && MBEDTLS_PEM_PARSE_C */

View File

@ -0,0 +1,394 @@
/*
* SSL server demonstration program
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_time time
#define mbedtls_time_t time_t
#define mbedtls_fprintf fprintf
#define mbedtls_printf printf
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
#if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_PEM_PARSE_C) || \
!defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_SSL_TLS_C) || \
!defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_NET_C) || \
!defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_CTR_DRBG_C) || \
!defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO)
int main( void )
{
mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_ENTROPY_C "
"and/or MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or "
"MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
"MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C "
"and/or MBEDTLS_PEM_PARSE_C not defined.\n");
mbedtls_exit( 0 );
}
#else
#include <stdlib.h>
#include <string.h>
#if defined(_WIN32)
#include <windows.h>
#endif
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/x509.h"
#include "mbedtls/ssl.h"
#include "mbedtls/net_sockets.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "test/certs.h"
#if defined(MBEDTLS_SSL_CACHE_C)
#include "mbedtls/ssl_cache.h"
#endif
#define HTTP_RESPONSE \
"HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
"<h2>mbed TLS Test Server</h2>\r\n" \
"<p>Successful connection using: %s</p>\r\n"
#define DEBUG_LEVEL 0
static void my_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
((void) level);
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: %s", file, line, str );
fflush( (FILE *) ctx );
}
int main( void )
{
int ret, len;
mbedtls_net_context listen_fd, client_fd;
unsigned char buf[1024];
const char *pers = "ssl_server";
mbedtls_entropy_context entropy;
mbedtls_ctr_drbg_context ctr_drbg;
mbedtls_ssl_context ssl;
mbedtls_ssl_config conf;
mbedtls_x509_crt srvcert;
mbedtls_pk_context pkey;
#if defined(MBEDTLS_SSL_CACHE_C)
mbedtls_ssl_cache_context cache;
#endif
mbedtls_net_init( &listen_fd );
mbedtls_net_init( &client_fd );
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. Seed the RNG
*/
mbedtls_printf( " . Seeding the random number generator..." );
fflush( stdout );
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" );
/*
* 2. Load the certificates and private RSA key
*/
mbedtls_printf( "\n . 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,
mbedtls_ctr_drbg_random, &ctr_drbg );
if( ret != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 3. Setup the listening TCP socket
*/
mbedtls_printf( " . Bind on https://localhost:4433/ ..." );
fflush( stdout );
if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
/*
* 4. Setup stuff
*/
mbedtls_printf( " . Setting up the SSL data...." );
fflush( stdout );
if( ( ret = mbedtls_ssl_config_defaults( &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( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
mbedtls_ssl_conf_dbg( &conf, my_debug, stdout );
#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\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
goto exit;
}
if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret );
goto exit;
}
mbedtls_printf( " ok\n" );
reset:
#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( &client_fd );
mbedtls_ssl_session_reset( &ssl );
/*
* 3. Wait until a client connects
*/
mbedtls_printf( " . Waiting for a remote connection ..." );
fflush( stdout );
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;
}
mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
mbedtls_printf( " ok\n" );
/*
* 5. 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 )
{
mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned %d\n\n", ret );
goto reset;
}
}
mbedtls_printf( " ok\n" );
/*
* 6. Read the HTTP Request
*/
mbedtls_printf( " < Read from client:" );
fflush( stdout );
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\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", (unsigned int) -ret );
break;
}
break;
}
len = ret;
mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf );
if( ret > 0 )
break;
}
while( 1 );
/*
* 7. Write the 200 Response
*/
mbedtls_printf( " > Write to client:" );
fflush( stdout );
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\n ! peer closed the connection\n\n" );
goto reset;
}
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;
mbedtls_printf( " %d bytes written\n\n%s\n", 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\n ! mbedtls_ssl_close_notify returned %d\n\n", ret );
goto reset;
}
}
mbedtls_printf( " ok\n" );
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
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 );
mbedtls_exit( ret );
}
#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C &&
MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C &&
MBEDTLS_RSA_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_X509_CRT_PARSE_C
&& MBEDTLS_FS_IO && MBEDTLS_PEM_PARSE_C */

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,381 @@
/*
* Common source code for SSL test programs. This file is included by
* both ssl_client2.c and ssl_server2.c and is intended for source
* code that is textually identical in both programs, but that cannot be
* compiled separately because it refers to types or macros that are
* different in the two programs, or because it would have an incomplete
* type.
*
* This file is meant to be #include'd and cannot be compiled separately.
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
void eap_tls_key_derivation( void *p_expkey,
mbedtls_ssl_key_export_type secret_type,
const unsigned char *secret,
size_t secret_len,
const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type )
{
eap_tls_keys *keys = (eap_tls_keys *)p_expkey;
/* We're only interested in the TLS 1.2 master secret */
if( secret_type != MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET )
return;
if( secret_len != sizeof( keys->master_secret ) )
return;
memcpy( keys->master_secret, secret, sizeof( keys->master_secret ) );
memcpy( keys->randbytes, client_random, 32 );
memcpy( keys->randbytes + 32, server_random, 32 );
keys->tls_prf_type = tls_prf_type;
}
void nss_keylog_export( void *p_expkey,
mbedtls_ssl_key_export_type secret_type,
const unsigned char *secret,
size_t secret_len,
const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type )
{
char nss_keylog_line[ 200 ];
size_t const client_random_len = 32;
size_t len = 0;
size_t j;
/* We're only interested in the TLS 1.2 master secret */
if( secret_type != MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET )
return;
((void) p_expkey);
((void) server_random);
((void) tls_prf_type);
len += sprintf( nss_keylog_line + len,
"%s", "CLIENT_RANDOM " );
for( j = 0; j < client_random_len; j++ )
{
len += sprintf( nss_keylog_line + len,
"%02x", client_random[j] );
}
len += sprintf( nss_keylog_line + len, " " );
for( j = 0; j < secret_len; j++ )
{
len += sprintf( nss_keylog_line + len,
"%02x", secret[j] );
}
len += sprintf( nss_keylog_line + len, "\n" );
nss_keylog_line[ len ] = '\0';
mbedtls_printf( "\n" );
mbedtls_printf( "---------------- NSS KEYLOG -----------------\n" );
mbedtls_printf( "%s", nss_keylog_line );
mbedtls_printf( "---------------------------------------------\n" );
if( opt.nss_keylog_file != NULL )
{
FILE *f;
if( ( f = fopen( opt.nss_keylog_file, "a" ) ) == NULL )
{
goto exit;
}
/* Ensure no stdio buffering of secrets, as such buffers cannot be
* wiped. */
mbedtls_setbuf( f, NULL );
if( fwrite( nss_keylog_line, 1, len, f ) != len )
{
fclose( f );
goto exit;
}
fclose( f );
}
exit:
mbedtls_platform_zeroize( nss_keylog_line,
sizeof( nss_keylog_line ) );
}
#if defined( MBEDTLS_SSL_DTLS_SRTP )
void dtls_srtp_key_derivation( void *p_expkey,
mbedtls_ssl_key_export_type secret_type,
const unsigned char *secret,
size_t secret_len,
const unsigned char client_random[32],
const unsigned char server_random[32],
mbedtls_tls_prf_types tls_prf_type )
{
dtls_srtp_keys *keys = (dtls_srtp_keys *)p_expkey;
/* We're only interested in the TLS 1.2 master secret */
if( secret_type != MBEDTLS_SSL_KEY_EXPORT_TLS12_MASTER_SECRET )
return;
if( secret_len != sizeof( keys->master_secret ) )
return;
memcpy( keys->master_secret, secret, sizeof( keys->master_secret ) );
memcpy( keys->randbytes, client_random, 32 );
memcpy( keys->randbytes + 32, server_random, 32 );
keys->tls_prf_type = tls_prf_type;
}
#endif /* MBEDTLS_SSL_DTLS_SRTP */
int ssl_check_record( mbedtls_ssl_context const *ssl,
unsigned char const *buf, size_t len )
{
int my_ret = 0, ret_cr1, ret_cr2;
unsigned char *tmp_buf;
/* Record checking may modify the input buffer,
* so make a copy. */
tmp_buf = mbedtls_calloc( 1, len );
if( tmp_buf == NULL )
return( MBEDTLS_ERR_SSL_ALLOC_FAILED );
memcpy( tmp_buf, buf, len );
ret_cr1 = mbedtls_ssl_check_record( ssl, tmp_buf, len );
if( ret_cr1 != MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE )
{
/* Test-only: Make sure that mbedtls_ssl_check_record()
* doesn't alter state. */
memcpy( tmp_buf, buf, len ); /* Restore buffer */
ret_cr2 = mbedtls_ssl_check_record( ssl, tmp_buf, len );
if( ret_cr2 != ret_cr1 )
{
mbedtls_printf( "mbedtls_ssl_check_record() returned inconsistent results.\n" );
my_ret = -1;
goto cleanup;
}
switch( ret_cr1 )
{
case 0:
break;
case MBEDTLS_ERR_SSL_INVALID_RECORD:
if( opt.debug_level > 1 )
mbedtls_printf( "mbedtls_ssl_check_record() detected invalid record.\n" );
break;
case MBEDTLS_ERR_SSL_INVALID_MAC:
if( opt.debug_level > 1 )
mbedtls_printf( "mbedtls_ssl_check_record() detected unauthentic record.\n" );
break;
case MBEDTLS_ERR_SSL_UNEXPECTED_RECORD:
if( opt.debug_level > 1 )
mbedtls_printf( "mbedtls_ssl_check_record() detected unexpected record.\n" );
break;
default:
mbedtls_printf( "mbedtls_ssl_check_record() failed fatally with -%#04x.\n", (unsigned int) -ret_cr1 );
my_ret = -1;
goto cleanup;
}
/* Regardless of the outcome, forward the record to the stack. */
}
cleanup:
mbedtls_free( tmp_buf );
return( my_ret );
}
int recv_cb( void *ctx, unsigned char *buf, size_t len )
{
io_ctx_t *io_ctx = (io_ctx_t*) ctx;
size_t recv_len;
int ret;
if( opt.nbio == 2 )
ret = delayed_recv( io_ctx->net, buf, len );
else
ret = mbedtls_net_recv( io_ctx->net, buf, len );
if( ret < 0 )
return( ret );
recv_len = (size_t) ret;
if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
/* Here's the place to do any datagram/record checking
* in between receiving the packet from the underlying
* transport and passing it on to the TLS stack. */
if( ssl_check_record( io_ctx->ssl, buf, recv_len ) != 0 )
return( -1 );
}
return( (int) recv_len );
}
int recv_timeout_cb( void *ctx, unsigned char *buf, size_t len,
uint32_t timeout )
{
io_ctx_t *io_ctx = (io_ctx_t*) ctx;
int ret;
size_t recv_len;
ret = mbedtls_net_recv_timeout( io_ctx->net, buf, len, timeout );
if( ret < 0 )
return( ret );
recv_len = (size_t) ret;
if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM )
{
/* Here's the place to do any datagram/record checking
* in between receiving the packet from the underlying
* transport and passing it on to the TLS stack. */
if( ssl_check_record( io_ctx->ssl, buf, recv_len ) != 0 )
return( -1 );
}
return( (int) recv_len );
}
int send_cb( void *ctx, unsigned char const *buf, size_t len )
{
io_ctx_t *io_ctx = (io_ctx_t*) ctx;
if( opt.nbio == 2 )
return( delayed_send( io_ctx->net, buf, len ) );
return( mbedtls_net_send( io_ctx->net, buf, len ) );
}
#if defined(MBEDTLS_X509_CRT_PARSE_C)
#if defined(MBEDTLS_ECDSA_C) && defined(MBEDTLS_RSA_C)
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/*
* When GnuTLS/Openssl server is configured in TLS 1.2 mode with a certificate
* declaring an RSA public key and Mbed TLS is configured in hybrid mode, if
* `rsa_pss_rsae_*` algorithms are before `rsa_pkcs1_*` ones in this list then
* the GnuTLS/Openssl server chooses an `rsa_pss_rsae_*` signature algorithm
* for its signature in the key exchange message. As Mbed TLS 1.2 does not
* support them, the handshake fails.
*/
#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA), \
(( hash << 8 ) | MBEDTLS_SSL_SIG_RSA), \
( 0x800 | hash ),
#else
#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA), \
(( hash << 8 ) | MBEDTLS_SSL_SIG_RSA),
#endif
#elif defined(MBEDTLS_ECDSA_C)
#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_ECDSA),
#elif defined(MBEDTLS_RSA_C)
#if defined(MBEDTLS_SSL_PROTO_TLS1_3)
/* See above */
#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_RSA), \
( 0x800 | hash ),
#else
#define MBEDTLS_SSL_SIG_ALG( hash ) (( hash << 8 ) | MBEDTLS_SSL_SIG_RSA),
#endif
#else
#define MBEDTLS_SSL_SIG_ALG( hash )
#endif
uint16_t ssl_sig_algs_for_test[] = {
#if defined(MBEDTLS_SHA512_C)
MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA512 )
#endif
#if defined(MBEDTLS_SHA384_C)
MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA384 )
#endif
#if defined(MBEDTLS_SHA256_C)
MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA256 )
#endif
#if defined(MBEDTLS_SHA224_C)
MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA224 )
#endif
#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_SHA256_C)
MBEDTLS_TLS1_3_SIG_RSA_PSS_RSAE_SHA256,
#endif /* MBEDTLS_RSA_C && MBEDTLS_SHA256_C */
#if defined(MBEDTLS_SHA1_C)
/* Allow SHA-1 as we use it extensively in tests. */
MBEDTLS_SSL_SIG_ALG( MBEDTLS_SSL_HASH_SHA1 )
#endif
MBEDTLS_TLS1_3_SIG_NONE
};
#endif /* MBEDTLS_X509_CRT_PARSE_C */
#if defined(MBEDTLS_X509_CRT_PARSE_C)
/** Functionally equivalent to mbedtls_x509_crt_verify_info, see that function
* for more info.
*/
int x509_crt_verify_info( char *buf, size_t size, const char *prefix,
uint32_t flags )
{
#if !defined(MBEDTLS_X509_REMOVE_INFO)
return( mbedtls_x509_crt_verify_info( buf, size, prefix, flags ) );
#else /* !MBEDTLS_X509_REMOVE_INFO */
int ret;
char *p = buf;
size_t n = size;
#define X509_CRT_ERROR_INFO( err, err_str, info ) \
if( ( flags & err ) != 0 ) \
{ \
ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, info ); \
MBEDTLS_X509_SAFE_SNPRINTF; \
flags ^= err; \
}
MBEDTLS_X509_CRT_ERROR_INFO_LIST
#undef X509_CRT_ERROR_INFO
if( flags != 0 )
{
ret = mbedtls_snprintf( p, n, "%sUnknown reason "
"(this should not happen)\n", prefix );
MBEDTLS_X509_SAFE_SNPRINTF;
}
return( (int) ( size - n ) );
#endif /* MBEDTLS_X509_REMOVE_INFO */
}
#endif /* MBEDTLS_X509_CRT_PARSE_C */
void mbedtls_print_supported_sig_algs( void )
{
mbedtls_printf( "supported signature algorithms:\n" );
mbedtls_printf("\trsa_pkcs1_sha256 ");
mbedtls_printf("rsa_pkcs1_sha384 ");
mbedtls_printf("rsa_pkcs1_sha512\n");
mbedtls_printf("\tecdsa_secp256r1_sha256 ");
mbedtls_printf("ecdsa_secp384r1_sha384 ");
mbedtls_printf("ecdsa_secp521r1_sha512\n");
mbedtls_printf("\trsa_pss_rsae_sha256 ");
mbedtls_printf("rsa_pss_rsae_sha384 ");
mbedtls_printf("rsa_pss_rsae_sha512\n");
mbedtls_printf("\trsa_pss_pss_sha256 ");
mbedtls_printf("rsa_pss_pss_sha384 ");
mbedtls_printf("rsa_pss_pss_sha512\n");
mbedtls_printf("\ted25519 ");
mbedtls_printf("ed448 ");
mbedtls_printf("rsa_pkcs1_sha1 ");
mbedtls_printf("ecdsa_sha1\n");
mbedtls_printf( "\n" );
}

View File

@ -0,0 +1,458 @@
/*
* Common code library for SSL test programs.
*
* In addition to the functions in this file, there is shared source code
* that cannot be compiled separately in "ssl_test_common_source.c".
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define MBEDTLS_ALLOW_PRIVATE_ACCESS
#include "ssl_test_lib.h"
#if defined(MBEDTLS_TEST_HOOKS)
#include "test/helpers.h"
#endif
#if !defined(MBEDTLS_SSL_TEST_IMPOSSIBLE)
void my_debug( void *ctx, int level,
const char *file, int line,
const char *str )
{
const char *p, *basename;
/* Extract basename from file */
for( p = basename = file; *p != '\0'; p++ )
if( *p == '/' || *p == '\\' )
basename = p + 1;
mbedtls_fprintf( (FILE *) ctx, "%s:%04d: |%d| %s",
basename, line, level, str );
fflush( (FILE *) ctx );
}
#if defined(MBEDTLS_HAVE_TIME)
mbedtls_time_t dummy_constant_time( mbedtls_time_t* time )
{
(void) time;
return 0x5af2a056;
}
#endif
#if !defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
static int dummy_entropy( void *data, unsigned char *output, size_t len )
{
size_t i;
int ret;
(void) data;
ret = mbedtls_entropy_func( data, output, len );
for( i = 0; i < len; i++ )
{
//replace result with pseudo random
output[i] = (unsigned char) rand();
}
return( ret );
}
#endif
void rng_init( rng_context_t *rng )
{
#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
(void) rng;
psa_crypto_init( );
#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
#if defined(MBEDTLS_CTR_DRBG_C)
mbedtls_ctr_drbg_init( &rng->drbg );
#elif defined(MBEDTLS_HMAC_DRBG_C)
mbedtls_hmac_drbg_init( &rng->drbg );
#else
#error "No DRBG available"
#endif
mbedtls_entropy_init( &rng->entropy );
#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
}
int rng_seed( rng_context_t *rng, int reproducible, const char *pers )
{
#if defined(MBEDTLS_USE_PSA_CRYPTO)
if( reproducible )
{
mbedtls_fprintf( stderr,
"MBEDTLS_USE_PSA_CRYPTO does not support reproducible mode.\n" );
return( -1 );
}
#endif
#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
/* The PSA crypto RNG does its own seeding. */
(void) rng;
(void) pers;
if( reproducible )
{
mbedtls_fprintf( stderr,
"The PSA RNG does not support reproducible mode.\n" );
return( -1 );
}
return( 0 );
#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
int ( *f_entropy )( void *, unsigned char *, size_t ) =
( reproducible ? dummy_entropy : mbedtls_entropy_func );
if ( reproducible )
srand( 1 );
#if defined(MBEDTLS_CTR_DRBG_C)
int ret = mbedtls_ctr_drbg_seed( &rng->drbg,
f_entropy, &rng->entropy,
(const unsigned char *) pers,
strlen( pers ) );
#elif defined(MBEDTLS_HMAC_DRBG_C)
#if defined(MBEDTLS_SHA256_C)
const mbedtls_md_type_t md_type = MBEDTLS_MD_SHA256;
#elif defined(MBEDTLS_SHA512_C)
const mbedtls_md_type_t md_type = MBEDTLS_MD_SHA512;
#else
#error "No message digest available for HMAC_DRBG"
#endif
int ret = mbedtls_hmac_drbg_seed( &rng->drbg,
mbedtls_md_info_from_type( md_type ),
f_entropy, &rng->entropy,
(const unsigned char *) pers,
strlen( pers ) );
#else /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) */
#error "No DRBG available"
#endif /* !defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_HMAC_DRBG_C) */
if( ret != 0 )
{
mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned -0x%x\n",
(unsigned int) -ret );
return( ret );
}
#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
return( 0 );
}
void rng_free( rng_context_t *rng )
{
#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
(void) rng;
/* Deinitialize the PSA crypto subsystem. This deactivates all PSA APIs.
* This is ok because none of our applications try to do any crypto after
* deinitializing the RNG. */
mbedtls_psa_crypto_free( );
#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
#if defined(MBEDTLS_CTR_DRBG_C)
mbedtls_ctr_drbg_free( &rng->drbg );
#elif defined(MBEDTLS_HMAC_DRBG_C)
mbedtls_hmac_drbg_free( &rng->drbg );
#else
#error "No DRBG available"
#endif
mbedtls_entropy_free( &rng->entropy );
#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
}
int rng_get( void *p_rng, unsigned char *output, size_t output_len )
{
#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
(void) p_rng;
return( mbedtls_psa_get_random( MBEDTLS_PSA_RANDOM_STATE,
output, output_len ) );
#else /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
rng_context_t *rng = p_rng;
#if defined(MBEDTLS_CTR_DRBG_C)
return( mbedtls_ctr_drbg_random( &rng->drbg, output, output_len ) );
#elif defined(MBEDTLS_HMAC_DRBG_C)
return( mbedtls_hmac_drbg_random( &rng->drbg, output, output_len ) );
#else
#error "No DRBG available"
#endif
#endif /* !MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
}
int key_opaque_alg_parse( const char *arg, const char **alg1, const char **alg2 )
{
char* separator;
if( ( separator = strchr( arg, ',' ) ) == NULL )
return 1;
*separator = '\0';
*alg1 = arg;
*alg2 = separator + 1;
if( strcmp( *alg1, "rsa-sign-pkcs1" ) != 0 &&
strcmp( *alg1, "rsa-sign-pss" ) != 0 &&
strcmp( *alg1, "rsa-decrypt" ) != 0 &&
strcmp( *alg1, "ecdsa-sign" ) != 0 &&
strcmp( *alg1, "ecdh" ) != 0 )
return 1;
if( strcmp( *alg2, "rsa-sign-pkcs1" ) != 0 &&
strcmp( *alg2, "rsa-sign-pss" ) != 0 &&
strcmp( *alg2, "rsa-decrypt" ) != 0 &&
strcmp( *alg2, "ecdsa-sign" ) != 0 &&
strcmp( *alg2, "ecdh" ) != 0 &&
strcmp( *alg2, "none" ) != 0 )
return 1;
return 0;
}
#if defined(MBEDTLS_USE_PSA_CRYPTO)
int key_opaque_set_alg_usage( const char *alg1, const char *alg2,
psa_algorithm_t *psa_alg1,
psa_algorithm_t *psa_alg2,
psa_key_usage_t *usage,
mbedtls_pk_type_t key_type )
{
if( strcmp( alg1, "none" ) != 0 )
{
const char * algs[] = { alg1, alg2 };
psa_algorithm_t *psa_algs[] = { psa_alg1, psa_alg2 };
for ( int i = 0; i < 2; i++ )
{
if( strcmp( algs[i], "rsa-sign-pkcs1" ) == 0 )
{
*psa_algs[i] = PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_ANY_HASH );
*usage |= PSA_KEY_USAGE_SIGN_HASH;
}
else if( strcmp( algs[i], "rsa-sign-pss" ) == 0 )
{
*psa_algs[i] = PSA_ALG_RSA_PSS( PSA_ALG_ANY_HASH );
*usage |= PSA_KEY_USAGE_SIGN_HASH;
}
else if( strcmp( algs[i], "rsa-decrypt" ) == 0 )
{
*psa_algs[i] = PSA_ALG_RSA_PKCS1V15_CRYPT;
*usage |= PSA_KEY_USAGE_DECRYPT;
}
else if( strcmp( algs[i], "ecdsa-sign" ) == 0 )
{
*psa_algs[i] = PSA_ALG_ECDSA( PSA_ALG_ANY_HASH );
*usage |= PSA_KEY_USAGE_SIGN_HASH;
}
else if( strcmp( algs[i], "ecdh" ) == 0 )
{
*psa_algs[i] = PSA_ALG_ECDH;
*usage |= PSA_KEY_USAGE_DERIVE;
}
else if( strcmp( algs[i], "none" ) == 0 )
{
*psa_algs[i] = PSA_ALG_NONE;
}
}
}
else
{
if( key_type == MBEDTLS_PK_ECKEY )
{
*psa_alg1 = PSA_ALG_ECDSA( PSA_ALG_ANY_HASH );
*psa_alg2 = PSA_ALG_ECDH;
*usage = PSA_KEY_USAGE_SIGN_HASH | PSA_KEY_USAGE_DERIVE;
}
else if( key_type == MBEDTLS_PK_RSA )
{
*psa_alg1 = PSA_ALG_RSA_PKCS1V15_SIGN( PSA_ALG_ANY_HASH );
*psa_alg2 = PSA_ALG_RSA_PSS( PSA_ALG_ANY_HASH );
*usage = PSA_KEY_USAGE_SIGN_HASH;
}
else
{
return 1;
}
}
return 0;
}
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
int ca_callback( void *data, mbedtls_x509_crt const *child,
mbedtls_x509_crt **candidates )
{
int ret = 0;
mbedtls_x509_crt *ca = (mbedtls_x509_crt *) data;
mbedtls_x509_crt *first;
/* This is a test-only implementation of the CA callback
* which always returns the entire list of trusted certificates.
* Production implementations managing a large number of CAs
* should use an efficient presentation and lookup for the
* set of trusted certificates (such as a hashtable) and only
* return those trusted certificates which satisfy basic
* parental checks, such as the matching of child `Issuer`
* and parent `Subject` field or matching key identifiers. */
((void) child);
first = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) );
if( first == NULL )
{
ret = -1;
goto exit;
}
mbedtls_x509_crt_init( first );
if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 )
{
ret = -1;
goto exit;
}
while( ca->next != NULL )
{
ca = ca->next;
if( mbedtls_x509_crt_parse_der( first, ca->raw.p, ca->raw.len ) != 0 )
{
ret = -1;
goto exit;
}
}
exit:
if( ret != 0 )
{
mbedtls_x509_crt_free( first );
mbedtls_free( first );
first = NULL;
}
*candidates = first;
return( ret );
}
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
int delayed_recv( void *ctx, unsigned char *buf, size_t len )
{
static int first_try = 1;
int ret;
if( first_try )
{
first_try = 0;
return( MBEDTLS_ERR_SSL_WANT_READ );
}
ret = mbedtls_net_recv( ctx, buf, len );
if( ret != MBEDTLS_ERR_SSL_WANT_READ )
first_try = 1; /* Next call will be a new operation */
return( ret );
}
int delayed_send( void *ctx, const unsigned char *buf, size_t len )
{
static int first_try = 1;
int ret;
if( first_try )
{
first_try = 0;
return( MBEDTLS_ERR_SSL_WANT_WRITE );
}
ret = mbedtls_net_send( ctx, buf, len );
if( ret != MBEDTLS_ERR_SSL_WANT_WRITE )
first_try = 1; /* Next call will be a new operation */
return( ret );
}
#if !defined(MBEDTLS_TIMING_C)
int idle( mbedtls_net_context *fd,
int idle_reason )
#else
int idle( mbedtls_net_context *fd,
mbedtls_timing_delay_context *timer,
int idle_reason )
#endif
{
int ret;
int poll_type = 0;
if( idle_reason == MBEDTLS_ERR_SSL_WANT_WRITE )
poll_type = MBEDTLS_NET_POLL_WRITE;
else if( idle_reason == MBEDTLS_ERR_SSL_WANT_READ )
poll_type = MBEDTLS_NET_POLL_READ;
#if !defined(MBEDTLS_TIMING_C)
else
return( 0 );
#endif
while( 1 )
{
/* Check if timer has expired */
#if defined(MBEDTLS_TIMING_C)
if( timer != NULL &&
mbedtls_timing_get_delay( timer ) == 2 )
{
break;
}
#endif /* MBEDTLS_TIMING_C */
/* Check if underlying transport became available */
if( poll_type != 0 )
{
ret = mbedtls_net_poll( fd, poll_type, 0 );
if( ret < 0 )
return( ret );
if( ret == poll_type )
break;
}
}
return( 0 );
}
#if defined(MBEDTLS_TEST_HOOKS)
void test_hooks_init( void )
{
mbedtls_test_info_reset( );
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
mbedtls_test_mutex_usage_init( );
#endif
}
int test_hooks_failure_detected( void )
{
#if defined(MBEDTLS_TEST_MUTEX_USAGE)
/* Errors are reported via mbedtls_test_info. */
mbedtls_test_mutex_usage_check( );
#endif
if( mbedtls_test_info.result != MBEDTLS_TEST_RESULT_SUCCESS )
return( 1 );
return( 0 );
}
void test_hooks_free( void )
{
}
#endif /* MBEDTLS_TEST_HOOKS */
#endif /* !defined(MBEDTLS_SSL_TEST_IMPOSSIBLE) */

View File

@ -0,0 +1,330 @@
/*
* Common code for SSL test programs
*
* Copyright The Mbed TLS Contributors
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef MBEDTLS_PROGRAMS_SSL_SSL_TEST_LIB_H
#define MBEDTLS_PROGRAMS_SSL_SSL_TEST_LIB_H
#include "mbedtls/build_info.h"
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#include <stdlib.h>
#define mbedtls_calloc calloc
#define mbedtls_free free
#define mbedtls_time time
#define mbedtls_time_t time_t
#define mbedtls_printf printf
#define mbedtls_fprintf fprintf
#define mbedtls_snprintf snprintf
#define mbedtls_setbuf setbuf
#define mbedtls_exit exit
#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS
#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE
#endif
#undef HAVE_RNG
#if defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG) && \
( defined(MBEDTLS_USE_PSA_CRYPTO) || \
defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG) )
#define HAVE_RNG
#elif defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_CTR_DRBG_C)
#define HAVE_RNG
#elif defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_HMAC_DRBG_C) && \
( defined(MBEDTLS_SHA256_C) || defined(MBEDTLS_SHA512_C) )
#define HAVE_RNG
#endif
#if !defined(MBEDTLS_NET_C) || \
!defined(MBEDTLS_SSL_TLS_C)
#define MBEDTLS_SSL_TEST_IMPOSSIBLE \
"MBEDTLS_NET_C and/or " \
"MBEDTLS_SSL_TLS_C not defined."
#elif !defined(HAVE_RNG)
#define MBEDTLS_SSL_TEST_IMPOSSIBLE \
"No random generator is available.\n"
#else
#undef MBEDTLS_SSL_TEST_IMPOSSIBLE
#undef HAVE_RNG
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mbedtls/net_sockets.h"
#include "mbedtls/ssl.h"
#include "mbedtls/ssl_ciphersuites.h"
#include "mbedtls/entropy.h"
#include "mbedtls/ctr_drbg.h"
#include "mbedtls/hmac_drbg.h"
#include "mbedtls/x509.h"
#include "mbedtls/error.h"
#include "mbedtls/debug.h"
#include "mbedtls/timing.h"
#include "mbedtls/base64.h"
#include "test/certs.h"
#if defined(MBEDTLS_USE_PSA_CRYPTO) || defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
#include "psa/crypto.h"
#include "mbedtls/psa_util.h"
#endif
#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
#include "mbedtls/memory_buffer_alloc.h"
#endif
#include <test/helpers.h>
#include "../test/query_config.h"
typedef struct eap_tls_keys
{
unsigned char master_secret[48];
unsigned char randbytes[64];
mbedtls_tls_prf_types tls_prf_type;
} eap_tls_keys;
#if defined( MBEDTLS_SSL_DTLS_SRTP )
/* Supported SRTP mode needs a maximum of :
* - 16 bytes for key (AES-128)
* - 14 bytes SALT
* One for sender, one for receiver context
*/
#define MBEDTLS_TLS_SRTP_MAX_KEY_MATERIAL_LENGTH 60
typedef struct dtls_srtp_keys
{
unsigned char master_secret[48];
unsigned char randbytes[64];
mbedtls_tls_prf_types tls_prf_type;
} dtls_srtp_keys;
#endif /* MBEDTLS_SSL_DTLS_SRTP */
typedef struct
{
mbedtls_ssl_context *ssl;
mbedtls_net_context *net;
} io_ctx_t;
void my_debug( void *ctx, int level,
const char *file, int line,
const char *str );
#if defined(MBEDTLS_HAVE_TIME)
mbedtls_time_t dummy_constant_time( mbedtls_time_t* time );
#endif
#if defined(MBEDTLS_USE_PSA_CRYPTO) && !defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
/* If MBEDTLS_TEST_USE_PSA_CRYPTO_RNG is defined, the SSL test programs will use
* mbedtls_psa_get_random() rather than entropy+DRBG as a random generator.
*
* The constraints are:
* - Without the entropy module, the PSA RNG is the only option.
* - Without at least one of the DRBG modules, the PSA RNG is the only option.
* - The PSA RNG does not support explicit seeding, so it is incompatible with
* the reproducible mode used by test programs.
* - For good overall test coverage, there should be at least one configuration
* where the test programs use the PSA RNG while the PSA RNG is itself based
* on entropy+DRBG, and at least one configuration where the test programs
* do not use the PSA RNG even though it's there.
*
* A simple choice that meets the constraints is to use the PSA RNG whenever
* MBEDTLS_USE_PSA_CRYPTO is enabled. There's no real technical reason the
* choice to use the PSA RNG in the test programs and the choice to use
* PSA crypto when TLS code needs crypto have to be tied together, but it
* happens to be a good match. It's also a good match from an application
* perspective: either PSA is preferred for TLS (both for crypto and for
* random generation) or it isn't.
*/
#define MBEDTLS_TEST_USE_PSA_CRYPTO_RNG
#endif
/** A context for random number generation (RNG).
*/
typedef struct
{
#if defined(MBEDTLS_TEST_USE_PSA_CRYPTO_RNG)
unsigned char dummy;
#else /* MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
mbedtls_entropy_context entropy;
#if defined(MBEDTLS_CTR_DRBG_C)
mbedtls_ctr_drbg_context drbg;
#elif defined(MBEDTLS_HMAC_DRBG_C)
mbedtls_hmac_drbg_context drbg;
#else
#error "No DRBG available"
#endif
#endif /* MBEDTLS_TEST_USE_PSA_CRYPTO_RNG */
} rng_context_t;
/** Initialize the RNG.
*
* This function only initializes the memory used by the RNG context.
* Before using the RNG, it must be seeded with rng_seed().
*/
void rng_init( rng_context_t *rng );
/* Seed the random number generator.
*
* \param rng The RNG context to use. It must have been initialized
* with rng_init().
* \param reproducible If zero, seed the RNG from entropy.
* If nonzero, use a fixed seed, so that the program
* will produce the same sequence of random numbers
* each time it is invoked.
* \param pers A null-terminated string. Different values for this
* string cause the RNG to emit different output for
* the same seed.
*
* return 0 on success, a negative value on error.
*/
int rng_seed( rng_context_t *rng, int reproducible, const char *pers );
/** Deinitialize the RNG. Free any embedded resource.
*
* \param rng The RNG context to deinitialize. It must have been
* initialized with rng_init().
*/
void rng_free( rng_context_t *rng );
/** Generate random data.
*
* This function is suitable for use as the \c f_rng argument to Mbed TLS
* library functions.
*
* \param p_rng The random generator context. This must be a pointer to
* a #rng_context_t structure.
* \param output The buffer to fill.
* \param output_len The length of the buffer in bytes.
*
* \return \c 0 on success.
* \return An Mbed TLS error code on error.
*/
int rng_get( void *p_rng, unsigned char *output, size_t output_len );
/** Parse command-line option: key_opaque_algs
*
*
* \param arg String value of key_opaque_algs
* Coma-separated pair of values among the following:
* - "rsa-sign-pkcs1"
* - "rsa-sign-pss"
* - "rsa-decrypt"
* - "ecdsa-sign"
* - "ecdh"
* - "none" (only acceptable for the second value).
* \param alg1 Address of pointer to alg #1
* \param alg2 Address of pointer to alg #2
*
* \return \c 0 on success.
* \return \c 1 on parse failure.
*/
int key_opaque_alg_parse( const char *arg, const char **alg1, const char **alg2 );
#if defined(MBEDTLS_USE_PSA_CRYPTO)
/** Parse given opaque key algorithms to obtain psa algs and usage
* that will be passed to mbedtls_pk_wrap_as_opaque().
*
*
* \param alg1 input string opaque key algorithm #1
* \param alg2 input string opaque key algorithm #2
* \param psa_alg1 output PSA algorithm #1
* \param psa_alg2 output PSA algorithm #2
* \param usage output key usage
* \param key_type key type used to set default psa algorithm/usage
* when alg1 in "none"
*
* \return \c 0 on success.
* \return \c 1 on parse failure.
*/
int key_opaque_set_alg_usage( const char *alg1, const char *alg2,
psa_algorithm_t *psa_alg1,
psa_algorithm_t *psa_alg2,
psa_key_usage_t *usage,
mbedtls_pk_type_t key_type );
#endif /* MBEDTLS_USE_PSA_CRYPTO */
#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG)
/* The test implementation of the PSA external RNG is insecure. When
* MBEDTLS_PSA_CRYPTO_EXTERNAL_RNG is enabled, before using any PSA crypto
* function that makes use of an RNG, you must call
* mbedtls_test_enable_insecure_external_rng(). */
#include <test/fake_external_rng_for_test.h>
#endif
#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK)
int ca_callback( void *data, mbedtls_x509_crt const *child,
mbedtls_x509_crt **candidates );
#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */
/*
* Test recv/send functions that make sure each try returns
* WANT_READ/WANT_WRITE at least once before succeeding
*/
int delayed_recv( void *ctx, unsigned char *buf, size_t len );
int delayed_send( void *ctx, const unsigned char *buf, size_t len );
/*
* Wait for an event from the underlying transport or the timer
* (Used in event-driven IO mode).
*/
int idle( mbedtls_net_context *fd,
#if defined(MBEDTLS_TIMING_C)
mbedtls_timing_delay_context *timer,
#endif
int idle_reason );
#if defined(MBEDTLS_TEST_HOOKS)
/** Initialize whatever test hooks are enabled by the compile-time
* configuration and make sense for the TLS test programs. */
void test_hooks_init( void );
/** Check if any test hooks detected a problem.
*
* If a problem was detected, it's ok for the calling program to keep going,
* but it should ultimately exit with an error status.
*
* \note When implementing a test hook that detects errors on its own
* (as opposed to e.g. leaving the error for a memory sanitizer to
* report), make sure to print a message to standard error either at
* the time the problem is detected or during the execution of this
* function. This function does not indicate what problem was detected,
* so printing a message is the only way to provide feedback in the
* logs of the calling program.
*
* \return Nonzero if a problem was detected.
* \c 0 if no problem was detected.
*/
int test_hooks_failure_detected( void );
/** Free any resources allocated for the sake of test hooks.
*
* Call this at the end of the program so that resource leak analyzers
* don't complain.
*/
void test_hooks_free( void );
#endif /* !MBEDTLS_TEST_HOOKS */
#endif /* MBEDTLS_SSL_TEST_IMPOSSIBLE conditions: else */
#endif /* MBEDTLS_PROGRAMS_SSL_SSL_TEST_LIB_H */