From 70824f2c9ea28a0c044f14d967ce21899f41441d Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 26 Feb 2020 19:05:33 +0100 Subject: [PATCH] Revert "Remove programs that depend on TLS or X.509" This reverts commit 0688e4f2668dab8ad95b734c23b35977134a6d21. Run scripts/generate_visualc_files.pl to account for the added programs. --- programs/.gitignore | 17 + programs/CMakeLists.txt | 2 + programs/Makefile | 83 + programs/README.md | 43 + programs/ssl/CMakeLists.txt | 64 + programs/ssl/dtls_client.c | 374 +++ programs/ssl/dtls_server.c | 449 +++ programs/ssl/mini_client.c | 312 +++ programs/ssl/ssl_client1.c | 331 +++ programs/ssl/ssl_client2.c | 2454 ++++++++++++++++ programs/ssl/ssl_fork_server.c | 435 +++ programs/ssl/ssl_mail_client.c | 871 ++++++ programs/ssl/ssl_pthread_server.c | 545 ++++ programs/ssl/ssl_server.c | 416 +++ programs/ssl/ssl_server2.c | 3533 ++++++++++++++++++++++++ programs/test/CMakeLists.txt | 5 +- programs/test/udp_proxy.c | 944 +++++++ programs/test/udp_proxy_wrapper.sh | 117 + programs/x509/CMakeLists.txt | 30 + programs/x509/cert_app.c | 515 ++++ programs/x509/cert_req.c | 453 +++ programs/x509/cert_write.c | 825 ++++++ programs/x509/crl_app.c | 164 ++ programs/x509/req_app.c | 164 ++ tests/data_files/Makefile | 2 + visualc/VS2010/cert_app.vcxproj | 177 ++ visualc/VS2010/cert_req.vcxproj | 177 ++ visualc/VS2010/cert_write.vcxproj | 177 ++ visualc/VS2010/crl_app.vcxproj | 177 ++ visualc/VS2010/dtls_client.vcxproj | 177 ++ visualc/VS2010/dtls_server.vcxproj | 177 ++ visualc/VS2010/mbedTLS.sln | 195 ++ visualc/VS2010/mini_client.vcxproj | 177 ++ visualc/VS2010/req_app.vcxproj | 177 ++ visualc/VS2010/ssl_client1.vcxproj | 177 ++ visualc/VS2010/ssl_client2.vcxproj | 178 ++ visualc/VS2010/ssl_fork_server.vcxproj | 177 ++ visualc/VS2010/ssl_mail_client.vcxproj | 177 ++ visualc/VS2010/ssl_server.vcxproj | 177 ++ visualc/VS2010/ssl_server2.vcxproj | 178 ++ visualc/VS2010/udp_proxy.vcxproj | 177 ++ 41 files changed, 15999 insertions(+), 1 deletion(-) create mode 100644 programs/ssl/CMakeLists.txt create mode 100644 programs/ssl/dtls_client.c create mode 100644 programs/ssl/dtls_server.c create mode 100644 programs/ssl/mini_client.c create mode 100644 programs/ssl/ssl_client1.c create mode 100644 programs/ssl/ssl_client2.c create mode 100644 programs/ssl/ssl_fork_server.c create mode 100644 programs/ssl/ssl_mail_client.c create mode 100644 programs/ssl/ssl_pthread_server.c create mode 100644 programs/ssl/ssl_server.c create mode 100644 programs/ssl/ssl_server2.c create mode 100644 programs/test/udp_proxy.c create mode 100755 programs/test/udp_proxy_wrapper.sh create mode 100644 programs/x509/CMakeLists.txt create mode 100644 programs/x509/cert_app.c create mode 100644 programs/x509/cert_req.c create mode 100644 programs/x509/cert_write.c create mode 100644 programs/x509/crl_app.c create mode 100644 programs/x509/req_app.c create mode 100644 visualc/VS2010/cert_app.vcxproj create mode 100644 visualc/VS2010/cert_req.vcxproj create mode 100644 visualc/VS2010/cert_write.vcxproj create mode 100644 visualc/VS2010/crl_app.vcxproj create mode 100644 visualc/VS2010/dtls_client.vcxproj create mode 100644 visualc/VS2010/dtls_server.vcxproj create mode 100644 visualc/VS2010/mini_client.vcxproj create mode 100644 visualc/VS2010/req_app.vcxproj create mode 100644 visualc/VS2010/ssl_client1.vcxproj create mode 100644 visualc/VS2010/ssl_client2.vcxproj create mode 100644 visualc/VS2010/ssl_fork_server.vcxproj create mode 100644 visualc/VS2010/ssl_mail_client.vcxproj create mode 100644 visualc/VS2010/ssl_server.vcxproj create mode 100644 visualc/VS2010/ssl_server2.vcxproj create mode 100644 visualc/VS2010/udp_proxy.vcxproj diff --git a/programs/.gitignore b/programs/.gitignore index a6df08f9e..30489bed0 100644 --- a/programs/.gitignore +++ b/programs/.gitignore @@ -34,14 +34,31 @@ psa/key_ladder_demo random/gen_entropy random/gen_random_ctr_drbg random/gen_random_havege +ssl/dtls_client +ssl/dtls_server +ssl/ssl_client1 +ssl/ssl_client2 +ssl/ssl_fork_server +ssl/ssl_mail_client +ssl/ssl_pthread_server +ssl/ssl_server +ssl/ssl_server2 +ssl/mini_client test/benchmark test/ecp-bench test/selftest test/cpp_dummy_build +test/ssl_cert_test +test/udp_proxy test/zeroize test/query_compile_time_config util/pem2der util/strerror +x509/cert_app +x509/cert_req +x509/crl_app +x509/cert_write +x509/req_app # generated files pkey/keyfile.key diff --git a/programs/CMakeLists.txt b/programs/CMakeLists.txt index b99b44e80..661b12071 100644 --- a/programs/CMakeLists.txt +++ b/programs/CMakeLists.txt @@ -3,5 +3,7 @@ add_subdirectory(hash) add_subdirectory(pkey) add_subdirectory(psa) add_subdirectory(random) +add_subdirectory(ssl) add_subdirectory(test) +add_subdirectory(x509) add_subdirectory(util) diff --git a/programs/Makefile b/programs/Makefile index 7074df70a..c5ac76749 100644 --- a/programs/Makefile +++ b/programs/Makefile @@ -70,17 +70,36 @@ APPS = \ psa/crypto_examples$(EXEXT) \ psa/key_ladder_demo$(EXEXT) \ psa/psa_constant_names$(EXEXT) \ + ssl/dtls_client$(EXEXT) \ + ssl/dtls_server$(EXEXT) \ + ssl/ssl_client1$(EXEXT) \ + ssl/ssl_client2$(EXEXT) \ + ssl/ssl_server$(EXEXT) \ + ssl/ssl_server2$(EXEXT) \ + ssl/ssl_fork_server$(EXEXT) \ + ssl/mini_client$(EXEXT) \ + ssl/ssl_mail_client$(EXEXT) \ random/gen_entropy$(EXEXT) \ random/gen_random_havege$(EXEXT) \ random/gen_random_ctr_drbg$(EXEXT) \ test/benchmark$(EXEXT) \ test/selftest$(EXEXT) \ + test/udp_proxy$(EXEXT) \ test/zeroize$(EXEXT) \ test/query_compile_time_config$(EXEXT) \ util/pem2der$(EXEXT) \ util/strerror$(EXEXT) \ + x509/cert_app$(EXEXT) \ + x509/crl_app$(EXEXT) \ + x509/cert_req$(EXEXT) \ + x509/cert_write$(EXEXT) \ + x509/req_app$(EXEXT) \ # End of APPS +ifdef PTHREAD +APPS += ssl/ssl_pthread_server$(EXEXT) +endif + ifdef TEST_CPP APPS += test/cpp_dummy_build$(EXEXT) endif @@ -214,6 +233,46 @@ random/gen_random_ctr_drbg$(EXEXT): random/gen_random_ctr_drbg.c $(DEP) echo " CC random/gen_random_ctr_drbg.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) random/gen_random_ctr_drbg.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ +ssl/dtls_client$(EXEXT): ssl/dtls_client.c $(DEP) + echo " CC ssl/dtls_client.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/dtls_client.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/dtls_server$(EXEXT): ssl/dtls_server.c $(DEP) + echo " CC ssl/dtls_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/dtls_server.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_client1$(EXEXT): ssl/ssl_client1.c $(DEP) + echo " CC ssl/ssl_client1.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_client1.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_client2$(EXEXT): ssl/ssl_client2.c test/query_config.c $(DEP) + echo " CC ssl/ssl_client2.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_client2.c test/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_server$(EXEXT): ssl/ssl_server.c $(DEP) + echo " CC ssl/ssl_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_server.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_server2$(EXEXT): ssl/ssl_server2.c test/query_config.c $(DEP) + echo " CC ssl/ssl_server2.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_server2.c test/query_config.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_fork_server$(EXEXT): ssl/ssl_fork_server.c $(DEP) + echo " CC ssl/ssl_fork_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_fork_server.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/ssl_pthread_server$(EXEXT): ssl/ssl_pthread_server.c $(DEP) + echo " CC ssl/ssl_pthread_server.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_pthread_server.c $(LOCAL_LDFLAGS) -lpthread $(LDFLAGS) -o $@ + +ssl/ssl_mail_client$(EXEXT): ssl/ssl_mail_client.c $(DEP) + echo " CC ssl/ssl_mail_client.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/ssl_mail_client.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +ssl/mini_client$(EXEXT): ssl/mini_client.c $(DEP) + echo " CC ssl/mini_client.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) ssl/mini_client.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + test/benchmark$(EXEXT): test/benchmark.c $(DEP) echo " CC test/benchmark.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/benchmark.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ @@ -226,6 +285,10 @@ test/selftest$(EXEXT): test/selftest.c $(DEP) echo " CC test/selftest.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/selftest.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ +test/udp_proxy$(EXEXT): test/udp_proxy.c $(DEP) + echo " CC test/udp_proxy.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/udp_proxy.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + test/zeroize$(EXEXT): test/zeroize.c $(DEP) echo " CC test/zeroize.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) test/zeroize.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ @@ -242,6 +305,26 @@ util/strerror$(EXEXT): util/strerror.c $(DEP) echo " CC util/strerror.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) util/strerror.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ +x509/cert_app$(EXEXT): x509/cert_app.c $(DEP) + echo " CC x509/cert_app.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_app.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/cert_write$(EXEXT): x509/cert_write.c $(DEP) + echo " CC x509/cert_write.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_write.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/crl_app$(EXEXT): x509/crl_app.c $(DEP) + echo " CC x509/crl_app.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/crl_app.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/cert_req$(EXEXT): x509/cert_req.c $(DEP) + echo " CC x509/cert_req.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/cert_req.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + +x509/req_app$(EXEXT): x509/req_app.c $(DEP) + echo " CC x509/req_app.c" + $(CC) $(LOCAL_CFLAGS) $(CFLAGS) x509/req_app.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ + psa/crypto_examples$(EXEXT): psa/crypto_examples.c $(DEP) echo " CC psa/crypto_examples.c" $(CC) $(LOCAL_CFLAGS) $(CFLAGS) psa/crypto_examples.c $(LOCAL_LDFLAGS) $(LDFLAGS) -o $@ diff --git a/programs/README.md b/programs/README.md index 977e26c41..44edd617a 100644 --- a/programs/README.md +++ b/programs/README.md @@ -61,6 +61,36 @@ This subdirectory mostly contains sample programs that illustrate specific featu * [`random/gen_random_havege.c`](random/gen_random_havege.c): demonstrates the HAVEGE entropy collector. +## SSL/TLS examples + +### SSL/TLS sample applications + +* [`ssl/dtls_client.c`](ssl/dtls_client.c): a simple DTLS client program, which sends one datagram to the server and reads one datagram in response. + +* [`ssl/dtls_server.c`](ssl/dtls_server.c): a simple DTLS server program, which expects one datagram from the client and writes one datagram in response. This program supports DTLS cookies for hello verification. + +* [`ssl/mini_client.c`](ssl/mini_client.c): a minimalistic SSL client, which sends a short string and disconnects. This is primarily intended as a benchmark; for a better example of a typical TLS client, see `ssl/ssl_client1.c`. + +* [`ssl/ssl_client1.c`](ssl/ssl_client1.c): a simple HTTPS client that sends a fixed request and displays the response. + +* [`ssl/ssl_fork_server.c`](ssl/ssl_fork_server.c): a simple HTTPS server using one process per client to send a fixed response. This program requires a Unix/POSIX environment implementing the `fork` system call. + +* [`ssl/ssl_mail_client.c`](ssl/ssl_mail_client.c): a simple SMTP-over-TLS or SMTP-STARTTLS client. This client sends an email with fixed content. + +* [`ssl/ssl_pthread_server.c`](ssl/ssl_pthread_server.c): a simple HTTPS server using one thread per client to send a fixed response. This program requires the pthread library. + +* [`ssl/ssl_server.c`](ssl/ssl_server.c): a simple HTTPS server that sends a fixed response. It serves a single client at a time. + +### SSL/TLS feature demonstrators + +Note: unlike most of the other programs under the `programs/` directory, these two programs are not intended as a basis for writing an application. They combine most of the features supported by the library, and most applications require only a few features. To write a new application, we recommended that you start with `ssl_client1.c` or `ssl_server.c`, and then look inside `ssl/ssl_client2.c` or `ssl/ssl_server2.c` to see how to use the specific features that your application needs. + +* [`ssl/ssl_client2.c`](ssl/ssl_client2.c): an HTTPS client that sends a fixed request and displays the response, with options to select TLS protocol features and Mbed TLS library features. + +* [`ssl/ssl_server2.c`](ssl/ssl_server2.c): an HTTPS server that sends a fixed response, with options to select TLS protocol features and Mbed TLS library features. + +In addition to providing options for testing client-side features, the `ssl_client2` program has options that allow you to trigger certain behaviors in the server. For example, there are options to select ciphersuites, or to force a renegotiation. These options are useful for testing the corresponding features in a TLS server. Likewise, `ssl_server2` has options to activate certain behaviors that are useful for testing a TLS client. + ## Test utilities * [`test/benchmark.c`](test/benchmark.c): benchmark for cryptographic algorithms. @@ -76,3 +106,16 @@ This subdirectory mostly contains sample programs that illustrate specific featu * [`util/pem2der.c`](util/pem2der.c): a PEM to DER converter. Mbed TLS can read PEM files directly, but this utility can be useful for interacting with other tools or with minimal Mbed TLS builds that lack PEM support. * [`util/strerror.c`](util/strerror.c): prints the error description corresponding to an integer status returned by an Mbed TLS function. + +## X.509 certificate examples + +* [`x509/cert_app.c`](x509/cert_app.c): connects to a TLS server and verifies its certificate chain. + +* [`x509/cert_req.c`](x509/cert_req.c): generates a certificate signing request (CSR) for a private key. + +* [`x509/cert_write.c`](x509/cert_write.c): signs a certificate signing request, or self-signs a certificate. + +* [`x509/crl_app.c`](x509/crl_app.c): loads and dumps a certificate revocation list (CRL). + +* [`x509/req_app.c`](x509/req_app.c): loads and dumps a certificate signing request (CSR). + diff --git a/programs/ssl/CMakeLists.txt b/programs/ssl/CMakeLists.txt new file mode 100644 index 000000000..f28a47d87 --- /dev/null +++ b/programs/ssl/CMakeLists.txt @@ -0,0 +1,64 @@ +set(THREADS_USE_PTHREADS_WIN32 true) +find_package(Threads) + +set(libs + mbedtls +) + +set(targets + dtls_client + dtls_server + ssl_client1 + ssl_client2 + ssl_server + ssl_fork_server + ssl_mail_client + mini_client +) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +add_executable(dtls_client dtls_client.c) +target_link_libraries(dtls_client ${libs}) + +add_executable(dtls_server dtls_server.c) +target_link_libraries(dtls_server ${libs}) + +add_executable(ssl_client1 ssl_client1.c) +target_link_libraries(ssl_client1 ${libs}) + +add_executable(ssl_client2 ssl_client2.c) +target_sources(ssl_client2 PUBLIC ../test/query_config.c) +target_link_libraries(ssl_client2 ${libs}) + +add_executable(ssl_server ssl_server.c) +target_link_libraries(ssl_server ${libs}) + +add_executable(ssl_server2 ssl_server2.c) +target_sources(ssl_server2 PUBLIC ../test/query_config.c) +target_link_libraries(ssl_server2 ${libs}) + +add_executable(ssl_fork_server ssl_fork_server.c) +target_link_libraries(ssl_fork_server ${libs}) + +add_executable(ssl_mail_client ssl_mail_client.c) +target_link_libraries(ssl_mail_client ${libs}) + +add_executable(mini_client mini_client.c) +target_link_libraries(mini_client ${libs}) + +if(THREADS_FOUND) + add_executable(ssl_pthread_server ssl_pthread_server.c) + target_link_libraries(ssl_pthread_server ${libs} ${CMAKE_THREAD_LIBS_INIT}) + set(targets ${targets} ssl_pthread_server) +endif(THREADS_FOUND) + +install(TARGETS ${targets} + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/programs/ssl/dtls_client.c b/programs/ssl/dtls_client.c new file mode 100644 index 000000000..90db06ca9 --- /dev/null +++ b/programs/ssl/dtls_client.c @@ -0,0 +1,374 @@ +/* + * Simple DTLS client demonstration program + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#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_CERTS_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_CERTS_C and/or MBEDTLS_PEM_PARSE_C not defined.\n" ); + return( 0 ); +} +#else + +#include + +#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/certs.h" +#include "mbedtls/timing.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 + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +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", -ret ); + goto exit; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + + /* + * 1. Start the connection + */ + mbedtls_printf( " . Connecting to udp/%s/%s...", SERVER_NAME, SERVER_PORT ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, SERVER_ADDR, + SERVER_PORT, MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 2. Setup stuff + */ + mbedtls_printf( " . Setting up the DTLS structure..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_config_defaults( &conf, + MBEDTLS_SSL_IS_CLIENT, + MBEDTLS_SSL_TRANSPORT_DATAGRAM, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned %d\n\n", ret ); + goto exit; + } + + /* OPTIONAL is usually a bad choice for security, but makes interop easier + * in this simplified example, in which the ca chain is hardcoded. + * Production code should set a proper ca chain and use REQUIRED. */ + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_OPTIONAL ); + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg ); + mbedtls_ssl_conf_dbg( &conf, my_debug, stdout ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned %d\n\n", ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_set_hostname( &ssl, SERVER_NAME ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hostname returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_set_bio( &ssl, &server_fd, + mbedtls_net_send, mbedtls_net_recv, mbedtls_net_recv_timeout ); + + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); + + mbedtls_printf( " ok\n" ); + + /* + * 4. Handshake + */ + mbedtls_printf( " . Performing the 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", -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 5. Verify the server certificate + */ + mbedtls_printf( " . Verifying peer X.509 certificate..." ); + + /* In real life, we would have used MBEDTLS_SSL_VERIFY_REQUIRED so that the + * handshake would not succeed if the peer's cert is bad. Even if we used + * MBEDTLS_SSL_VERIFY_OPTIONAL, we would bail out here if ret != 0 */ + if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + /* + * 6. Write the echo request + */ +send_request: + mbedtls_printf( " > Write to server:" ); + fflush( stdout ); + + len = sizeof( MESSAGE ) - 1; + + do ret = mbedtls_ssl_write( &ssl, (unsigned char *) MESSAGE, len ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto exit; + } + + len = ret; + mbedtls_printf( " %d bytes written\n\n%s\n\n", len, MESSAGE ); + + /* + * 7. Read the echo response + */ + mbedtls_printf( " < Read from server:" ); + fflush( stdout ); + + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + + do ret = mbedtls_ssl_read( &ssl, buf, len ); + while( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_TIMEOUT: + mbedtls_printf( " timeout\n\n" ); + if( retry_left-- > 0 ) + goto send_request; + goto exit; + + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + ret = 0; + goto close_notify; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n\n", -ret ); + goto exit; + } + } + + len = ret; + mbedtls_printf( " %d bytes read\n\n%s\n\n", len, buf ); + + /* + * 8. Done, cleanly close the connection + */ +close_notify: + mbedtls_printf( " . Closing the connection..." ); + + /* No error checking, the connection might be closed already */ + do ret = mbedtls_ssl_close_notify( &ssl ); + while( ret == MBEDTLS_ERR_SSL_WANT_WRITE ); + ret = 0; + + mbedtls_printf( " done\n" ); + + /* + * 9. Final clean-ups and exit + */ +exit: + +#ifdef MBEDTLS_ERROR_C + if( ret != 0 ) + { + char error_buf[100]; + mbedtls_strerror( ret, error_buf, 100 ); + mbedtls_printf( "Last error was: %d - %s\n\n", ret, error_buf ); + } +#endif + + mbedtls_net_free( &server_fd ); + + mbedtls_x509_crt_free( &cacert ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + /* Shell can not handle large exit numbers -> 1 for errors */ + if( ret < 0 ) + ret = 1; + + return( ret ); +} +#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_CERTS_C && + MBEDTLS_PEM_PARSE_C */ diff --git a/programs/ssl/dtls_server.c b/programs/ssl/dtls_server.c new file mode 100644 index 000000000..dd21fbf47 --- /dev/null +++ b/programs/ssl/dtls_server.c @@ -0,0 +1,449 @@ +/* + * Simple DTLS server demonstration program + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#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_CERTS_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_CERTS_C and/or MBEDTLS_PEM_PARSE_C and/or " + "MBEDTLS_TIMING_C not defined.\n" ); + return( 0 ); +} +#else + +#if defined(_WIN32) +#include +#endif + +#include +#include +#include + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.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" + +#if defined(MBEDTLS_SSL_CACHE_C) +#include "mbedtls/ssl_cache.h" +#endif + +#define READ_TIMEOUT_MS 10000 /* 5 seconds */ +#define DEBUG_LEVEL 0 + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +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. 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 ); + if( ret != 0 ) + { + printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); + goto exit; + } + + printf( " ok\n" ); + + /* + * 2. 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" ); + + /* + * 3. 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" ); + + /* + * 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 ); + +#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", -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", -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", -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 ); + +#if defined(_WIN32) + printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + /* Shell can not handle large exit numbers -> 1 for errors */ + if( ret < 0 ) + ret = 1; + + return( ret ); +} +#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_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_TIMING_C */ diff --git a/programs/ssl/mini_client.c b/programs/ssl/mini_client.c new file mode 100644 index 000000000..ff3612885 --- /dev/null +++ b/programs/ssl/mini_client.c @@ -0,0 +1,312 @@ +/* + * Minimal SSL client, used for memory measurements. + * (meant to be used with config-suite-b.h or config-ccm-psk-tls1_2.h) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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 abtractions 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"); + return( 0 ); +} +#else + +#include + +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" + +#include +#include +#include + +/* + * 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, +}; + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +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 + + return( ret ); +} +#endif diff --git a/programs/ssl/ssl_client1.c b/programs/ssl/ssl_client1.c new file mode 100644 index 000000000..646909f11 --- /dev/null +++ b/programs/ssl/ssl_client1.c @@ -0,0 +1,331 @@ +/* + * SSL client demonstration program + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_CERTS_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"); + return( 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 "mbedtls/certs.h" + +#include + +#define SERVER_PORT "4433" +#define SERVER_NAME "localhost" +#define GET_REQUEST "GET / HTTP/1.0\r\n\r\n" + +#define DEBUG_LEVEL 1 + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +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", -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", -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 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + /* + * 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 ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && + MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C && + MBEDTLS_CERTS_C && MBEDTLS_PEM_PARSE_C && MBEDTLS_CTR_DRBG_C && + MBEDTLS_X509_CRT_PARSE_C */ diff --git a/programs/ssl/ssl_client2.c b/programs/ssl/ssl_client2.c new file mode 100644 index 000000000..2cddfb42a --- /dev/null +++ b/programs/ssl/ssl_client2.c @@ -0,0 +1,2454 @@ +/* + * SSL client with certificate authentication + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_printf printf +#define mbedtls_fprintf fprintf +#define mbedtls_snprintf snprintf +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_exit exit +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif + +#if !defined(MBEDTLS_ENTROPY_C) || \ + !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_CLI_C) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_CLI_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined.\n"); + return( 0 ); +} +#else + +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/timing.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif + +#include +#include +#include + +#define MAX_REQUEST_SIZE 20000 +#define MAX_REQUEST_SIZE_STR "20000" + +#define DFL_SERVER_NAME "localhost" +#define DFL_SERVER_ADDR NULL +#define DFL_SERVER_PORT "4433" +#define DFL_REQUEST_PAGE "/" +#define DFL_REQUEST_SIZE -1 +#define DFL_DEBUG_LEVEL 0 +#define DFL_CONTEXT_CRT_CB 0 +#define DFL_NBIO 0 +#define DFL_EVENT 0 +#define DFL_READ_TIMEOUT 0 +#define DFL_MAX_RESEND 0 +#define DFL_CA_FILE "" +#define DFL_CA_PATH "" +#define DFL_CRT_FILE "" +#define DFL_KEY_FILE "" +#define DFL_KEY_OPAQUE 0 +#define DFL_PSK "" +#define DFL_PSK_OPAQUE 0 +#define DFL_PSK_IDENTITY "Client_identity" +#define DFL_ECJPAKE_PW NULL +#define DFL_EC_MAX_OPS -1 +#define DFL_FORCE_CIPHER 0 +#define DFL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define DFL_ALLOW_LEGACY -2 +#define DFL_RENEGOTIATE 0 +#define DFL_EXCHANGES 1 +#define DFL_MIN_VERSION -1 +#define DFL_MAX_VERSION -1 +#define DFL_ARC4 -1 +#define DFL_SHA1 -1 +#define DFL_AUTH_MODE -1 +#define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define DFL_TRUNC_HMAC -1 +#define DFL_RECSPLIT -1 +#define DFL_DHMLEN -1 +#define DFL_RECONNECT 0 +#define DFL_RECO_DELAY 0 +#define DFL_RECONNECT_HARD 0 +#define DFL_TICKETS MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define DFL_ALPN_STRING NULL +#define DFL_CURVES NULL +#define DFL_TRANSPORT MBEDTLS_SSL_TRANSPORT_STREAM +#define DFL_HS_TO_MIN 0 +#define DFL_HS_TO_MAX 0 +#define DFL_DTLS_MTU -1 +#define DFL_DGRAM_PACKING 1 +#define DFL_FALLBACK -1 +#define DFL_EXTENDED_MS -1 +#define DFL_ETM -1 +#define DFL_CA_CALLBACK 0 + + +#define GET_REQUEST "GET %s HTTP/1.0\r\nExtra-header: " +#define GET_REQUEST_END "\r\n\r\n" + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#define USAGE_CONTEXT_CRT_CB \ + " context_crt_cb=%%d This determines whether the CRT verification callback is bound\n" \ + " to the SSL configuration of the SSL context.\n" \ + " Possible values:\n"\ + " - 0 (default): Use CRT callback bound to configuration\n" \ + " - 1: Use CRT callback bound to SSL context\n" +#else +#define USAGE_CONTEXT_CRT_CB "" +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_FS_IO) +#define USAGE_IO \ + " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (pre-loaded)\n" \ + " ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (pre-loaded) (overrides ca_file)\n" \ + " crt_file=%%s Your own cert and chain (in bottom to top order, top may be omitted)\n" \ + " 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 */ +#else /* MBEDTLS_X509_CRT_PARSE_C */ +#define USAGE_IO "" +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_X509_CRT_PARSE_C) +#define USAGE_KEY_OPAQUE \ + " key_opaque=%%d Handle your private key as if it were opaque\n" \ + " default: 0 (disabled)\n" +#else +#define USAGE_KEY_OPAQUE "" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#define USAGE_PSK_RAW \ + " psk=%%s default: \"\" (in hex, without 0x)\n" \ + " psk_identity=%%s default: \"Client_identity\"\n" +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define USAGE_PSK_SLOT \ + " psk_opaque=%%d default: 0 (don't use opaque static PSK)\n" \ + " Enable this to store the PSK configured through command line\n" \ + " parameter `psk` in a PSA-based key slot.\n" \ + " Note: Currently only supported in conjunction with\n" \ + " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ + " to force a particular PSK-only ciphersuite.\n" \ + " Note: This is to test integration of PSA-based opaque PSKs with\n" \ + " Mbed TLS only. Production systems are likely to configure Mbed TLS\n" \ + " with prepopulated key slots instead of importing raw key material.\n" +#else +#define USAGE_PSK_SLOT "" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#define USAGE_PSK USAGE_PSK_RAW USAGE_PSK_SLOT +#else +#define USAGE_PSK "" +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +#define USAGE_CA_CALLBACK \ + " ca_callback=%%d default: 0 (disabled)\n" \ + " Enable this to use the trusted certificate callback function\n" +#else +#define USAGE_CA_CALLBACK "" +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define USAGE_TICKETS \ + " tickets=%%d default: 1 (enabled)\n" +#else +#define USAGE_TICKETS "" +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#define USAGE_TRUNC_HMAC \ + " trunc_hmac=%%d default: library default\n" +#else +#define USAGE_TRUNC_HMAC "" +#endif /* MBEDTLS_SSL_TRUNCATED_HMAC */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define USAGE_MAX_FRAG_LEN \ + " max_frag_len=%%d default: 16384 (tls default)\n" \ + " options: 512, 1024, 2048, 4096\n" +#else +#define USAGE_MAX_FRAG_LEN "" +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) +#define USAGE_RECSPLIT \ + " recsplit=0/1 default: (library default: on)\n" +#else +#define USAGE_RECSPLIT +#endif + +#if defined(MBEDTLS_DHM_C) +#define USAGE_DHMLEN \ + " dhmlen=%%d default: (library default: 1024 bits)\n" +#else +#define USAGE_DHMLEN +#endif + +#if defined(MBEDTLS_SSL_ALPN) +#define USAGE_ALPN \ + " alpn=%%s default: \"\" (disabled)\n" \ + " example: spdy/1,http/1.1\n" +#else +#define USAGE_ALPN "" +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_ECP_C) +#define USAGE_CURVES \ + " curves=a,b,c,d default: \"default\" (library default)\n" \ + " example: \"secp521r1,brainpoolP512r1\"\n" \ + " - use \"none\" for empty list\n" \ + " - see mbedtls_ecp_curve_list()\n" \ + " for acceptable curve names\n" +#else +#define USAGE_CURVES "" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#define USAGE_DTLS \ + " dtls=%%d default: 0 (TLS)\n" \ + " hs_timeout=%%d-%%d default: (library default: 1000-60000)\n" \ + " range of DTLS handshake timeouts in millisecs\n" \ + " mtu=%%d default: (library default: unlimited)\n" \ + " dgram_packing=%%d default: 1 (allowed)\n" \ + " allow or forbid packing of multiple\n" \ + " records within a single datgram.\n" +#else +#define USAGE_DTLS "" +#endif + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) +#define USAGE_FALLBACK \ + " fallback=0/1 default: (library default: off)\n" +#else +#define USAGE_FALLBACK "" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +#define USAGE_EMS \ + " extended_ms=0/1 default: (library default: on)\n" +#else +#define USAGE_EMS "" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define USAGE_ETM \ + " etm=0/1 default: (library default: on)\n" +#else +#define USAGE_ETM "" +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#define USAGE_RENEGO \ + " renegotiation=%%d default: 0 (disabled)\n" \ + " renegotiate=%%d default: 0 (disabled)\n" +#else +#define USAGE_RENEGO "" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define USAGE_ECJPAKE \ + " ecjpake_pw=%%s default: none (disabled)\n" +#else +#define USAGE_ECJPAKE "" +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) +#define USAGE_ECRESTART \ + " ec_max_ops=%%s default: library default (restart disabled)\n" +#else +#define USAGE_ECRESTART "" +#endif + +#define USAGE \ + "\n usage: ssl_client2 param=<>...\n" \ + "\n acceptable parameters:\n" \ + " server_name=%%s default: localhost\n" \ + " server_addr=%%s default: given by name\n" \ + " server_port=%%d default: 4433\n" \ + " request_page=%%s default: \".\"\n" \ + " request_size=%%d default: about 34 (basic request)\n" \ + " (minimum: 0, max: " MAX_REQUEST_SIZE_STR ")\n" \ + " If 0, in the first exchange only an empty\n" \ + " application data message is sent followed by\n" \ + " a second non-empty message before attempting\n" \ + " to read a response from the server\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " nbio=%%d default: 0 (blocking I/O)\n" \ + " options: 1 (non-blocking), 2 (added delays)\n" \ + " event=%%d default: 0 (loop)\n" \ + " options: 1 (level-triggered, implies nbio=1),\n" \ + " read_timeout=%%d default: 0 ms (no timeout)\n" \ + " max_resend=%%d default: 0 (no resend on timeout)\n" \ + "\n" \ + USAGE_DTLS \ + "\n" \ + " auth_mode=%%s default: (library default: none)\n" \ + " options: none, optional, required\n" \ + USAGE_IO \ + USAGE_KEY_OPAQUE \ + USAGE_CA_CALLBACK \ + "\n" \ + USAGE_PSK \ + USAGE_ECJPAKE \ + USAGE_ECRESTART \ + "\n" \ + " allow_legacy=%%d default: (library default: no)\n" \ + USAGE_RENEGO \ + " exchanges=%%d default: 1\n" \ + " reconnect=%%d default: 0 (disabled)\n" \ + " reco_delay=%%d default: 0 seconds\n" \ + " reconnect_hard=%%d default: 0 (disabled)\n" \ + USAGE_TICKETS \ + USAGE_MAX_FRAG_LEN \ + USAGE_TRUNC_HMAC \ + USAGE_CONTEXT_CRT_CB \ + USAGE_ALPN \ + USAGE_FALLBACK \ + USAGE_EMS \ + USAGE_ETM \ + USAGE_CURVES \ + USAGE_RECSPLIT \ + USAGE_DHMLEN \ + "\n" \ + " arc4=%%d default: (library default: 0)\n" \ + " allow_sha1=%%d default: 0\n" \ + " min_version=%%s default: (library default: tls1)\n" \ + " max_version=%%s default: (library default: tls1_2)\n" \ + " force_version=%%s default: \"\" (none)\n" \ + " options: ssl3, tls1, tls1_1, tls1_2, dtls1, dtls1_2\n" \ + "\n" \ + " force_ciphersuite= default: all enabled\n"\ + " query_config= return 0 if the specified\n" \ + " configuration macro is defined and 1\n" \ + " otherwise. The expansion of the macro\n" \ + " is printed if it is defined\n" \ + " acceptable ciphersuite names:\n" + +#define ALPN_LIST_SIZE 10 +#define CURVE_LIST_SIZE 20 + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +/* + * global options + */ +struct options +{ + const char *server_name; /* hostname of the server (client only) */ + const char *server_addr; /* address of the server (client only) */ + const char *server_port; /* port on which the ssl service runs */ + int debug_level; /* level of debugging */ + int nbio; /* should I/O be blocking? */ + int event; /* loop or event-driven IO? level or edge triggered? */ + uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */ + int max_resend; /* DTLS times to resend on read timeout */ + const char *request_page; /* page on server to request */ + int request_size; /* pad request with header to requested size */ + const char *ca_file; /* the file with the CA certificate(s) */ + const char *ca_path; /* the path with the CA certificate(s) reside */ + const char *crt_file; /* the file with the client certificate */ + const char *key_file; /* the file with the client key */ + int key_opaque; /* handle private key as if it were opaque */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int psk_opaque; +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + int ca_callback; /* Use callback for trusted certificate list */ +#endif + const char *psk; /* the pre-shared key */ + const char *psk_identity; /* the pre-shared key identity */ + const char *ecjpake_pw; /* the EC J-PAKE password */ + int ec_max_ops; /* EC consecutive operations limit */ + int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ + int renegotiation; /* enable / disable renegotiation */ + int allow_legacy; /* allow legacy renegotiation */ + int renegotiate; /* attempt renegotiation? */ + int renego_delay; /* delay before enforcing renegotiation */ + int exchanges; /* number of data exchanges */ + int min_version; /* minimum protocol version accepted */ + int max_version; /* maximum protocol version accepted */ + int arc4; /* flag for arc4 suites support */ + int allow_sha1; /* flag for SHA-1 support */ + int auth_mode; /* verify mode for connection */ + unsigned char mfl_code; /* code for maximum fragment length */ + int trunc_hmac; /* negotiate truncated hmac or not */ + int recsplit; /* enable record splitting? */ + int dhmlen; /* minimum DHM params len in bits */ + int reconnect; /* attempt to resume session */ + int reco_delay; /* delay in seconds before resuming session */ + int reconnect_hard; /* unexpectedly reconnect from the same port */ + int tickets; /* enable / disable session tickets */ + const char *curves; /* list of supported elliptic curves */ + const char *alpn_string; /* ALPN supported protocols */ + int transport; /* TLS or DTLS? */ + uint32_t hs_to_min; /* Initial value of DTLS handshake timer */ + uint32_t hs_to_max; /* Max value of DTLS handshake timer */ + int dtls_mtu; /* UDP Maximum tranport unit for DTLS */ + int fallback; /* is this a fallback connection? */ + int dgram_packing; /* allow/forbid datagram packing */ + int extended_ms; /* negotiate extended master secret? */ + int etm; /* negotiate encrypt then mac? */ + int context_crt_cb; /* use context-specific CRT verify callback */ +} opt; + +int query_config( const char *config ); + +static 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_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 */ + +/* + * Test recv/send functions that make sure each try returns + * WANT_READ/WANT_WRITE at least once before sucesseding + */ +static int my_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 ); +} + +static int my_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_X509_CRT_PARSE_C) +static unsigned char peer_crt_info[1024]; + +/* + * Enabled if debug_level > 1 in code below + */ +static int my_verify( void *data, mbedtls_x509_crt *crt, + int depth, uint32_t *flags ) +{ + char buf[1024]; + ((void) data); + + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + if( depth == 0 ) + memcpy( peer_crt_info, buf, sizeof( buf ) ); + + if( opt.debug_level == 0 ) + return( 0 ); + + mbedtls_printf( "\nVerify requested for (Depth %d):\n", depth ); + mbedtls_printf( "%s", buf ); + + if ( ( *flags ) == 0 ) + mbedtls_printf( " This certificate has no flags\n" ); + else + { + mbedtls_x509_crt_verify_info( buf, sizeof( buf ), " ! ", *flags ); + mbedtls_printf( "%s\n", buf ); + } + + return( 0 ); +} + +static int ssl_sig_hashes_for_test[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) + /* Allow SHA-1 as we use it extensively in tests. */ + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* + * Wait for an event from the underlying transport or the timer + * (Used in event-driven IO mode). + */ +#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 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 0, len, tail_len, i, written, frags, retry_left; + mbedtls_net_context server_fd; + + unsigned char buf[MAX_REQUEST_SIZE + 1]; + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + unsigned char psk[MBEDTLS_PSK_MAX_LEN]; + size_t psk_len = 0; +#endif +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_list[ALPN_LIST_SIZE]; +#endif +#if defined(MBEDTLS_ECP_C) + mbedtls_ecp_group_id curve_list[CURVE_LIST_SIZE]; + const mbedtls_ecp_curve_info *curve_cur; +#endif + + const char *pers = "ssl_client2"; + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_handle_t slot = 0; + psa_algorithm_t alg = 0; + psa_key_policy_t policy; + psa_status_t status; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_profile crt_profile_for_test = mbedtls_x509_crt_profile_default; +#endif + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_ssl_session saved_session; +#if defined(MBEDTLS_TIMING_C) + mbedtls_timing_delay_context timer; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + mbedtls_pk_context pkey; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_handle_t key_slot = 0; /* invalid key slot */ +#endif +#endif + char *p, *q; + const int *list; + + /* + * Make sure memory references are valid. + */ + mbedtls_net_init( &server_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + memset( &saved_session, 0, sizeof( mbedtls_ssl_session ) ); + mbedtls_ctr_drbg_init( &ctr_drbg ); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init( &cacert ); + mbedtls_x509_crt_init( &clicert ); + mbedtls_pk_init( &pkey ); +#endif +#if defined(MBEDTLS_SSL_ALPN) + memset( (void * ) alpn_list, 0, sizeof( alpn_list ) ); +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_crypto_init(); + if( status != PSA_SUCCESS ) + { + mbedtls_fprintf( stderr, "Failed to initialize PSA Crypto implementation: %d\n", + (int) status ); + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } +#endif + + if( argc == 0 ) + { + usage: + if( ret == 0 ) + ret = 1; + + mbedtls_printf( USAGE ); + + list = mbedtls_ssl_list_ciphersuites(); + while( *list ) + { + mbedtls_printf(" %-42s", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + if( !*list ) + break; + mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + } + mbedtls_printf("\n"); + goto exit; + } + + opt.server_name = DFL_SERVER_NAME; + opt.server_addr = DFL_SERVER_ADDR; + opt.server_port = DFL_SERVER_PORT; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.nbio = DFL_NBIO; + opt.event = DFL_EVENT; + opt.context_crt_cb = DFL_CONTEXT_CRT_CB; + opt.read_timeout = DFL_READ_TIMEOUT; + opt.max_resend = DFL_MAX_RESEND; + opt.request_page = DFL_REQUEST_PAGE; + opt.request_size = DFL_REQUEST_SIZE; + opt.ca_file = DFL_CA_FILE; + opt.ca_path = DFL_CA_PATH; + opt.crt_file = DFL_CRT_FILE; + opt.key_file = DFL_KEY_FILE; + opt.key_opaque = DFL_KEY_OPAQUE; + opt.psk = DFL_PSK; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + opt.psk_opaque = DFL_PSK_OPAQUE; +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + opt.ca_callback = DFL_CA_CALLBACK; +#endif + opt.psk_identity = DFL_PSK_IDENTITY; + opt.ecjpake_pw = DFL_ECJPAKE_PW; + opt.ec_max_ops = DFL_EC_MAX_OPS; + opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; + opt.renegotiation = DFL_RENEGOTIATION; + opt.allow_legacy = DFL_ALLOW_LEGACY; + opt.renegotiate = DFL_RENEGOTIATE; + opt.exchanges = DFL_EXCHANGES; + opt.min_version = DFL_MIN_VERSION; + opt.max_version = DFL_MAX_VERSION; + opt.arc4 = DFL_ARC4; + opt.allow_sha1 = DFL_SHA1; + opt.auth_mode = DFL_AUTH_MODE; + opt.mfl_code = DFL_MFL_CODE; + opt.trunc_hmac = DFL_TRUNC_HMAC; + opt.recsplit = DFL_RECSPLIT; + opt.dhmlen = DFL_DHMLEN; + opt.reconnect = DFL_RECONNECT; + opt.reco_delay = DFL_RECO_DELAY; + opt.reconnect_hard = DFL_RECONNECT_HARD; + opt.tickets = DFL_TICKETS; + opt.alpn_string = DFL_ALPN_STRING; + opt.curves = DFL_CURVES; + opt.transport = DFL_TRANSPORT; + opt.hs_to_min = DFL_HS_TO_MIN; + opt.hs_to_max = DFL_HS_TO_MAX; + opt.dtls_mtu = DFL_DTLS_MTU; + opt.fallback = DFL_FALLBACK; + opt.extended_ms = DFL_EXTENDED_MS; + opt.etm = DFL_ETM; + opt.dgram_packing = DFL_DGRAM_PACKING; + + 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_addr" ) == 0 ) + opt.server_addr = q; + else if( strcmp( p, "server_port" ) == 0 ) + opt.server_port = q; + else if( strcmp( p, "dtls" ) == 0 ) + { + int t = atoi( q ); + if( t == 0 ) + opt.transport = MBEDTLS_SSL_TRANSPORT_STREAM; + else if( t == 1 ) + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + else + goto usage; + } + 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, "context_crt_cb" ) == 0 ) + { + opt.context_crt_cb = atoi( q ); + if( opt.context_crt_cb != 0 && opt.context_crt_cb != 1 ) + goto usage; + } + else if( strcmp( p, "nbio" ) == 0 ) + { + opt.nbio = atoi( q ); + if( opt.nbio < 0 || opt.nbio > 2 ) + goto usage; + } + else if( strcmp( p, "event" ) == 0 ) + { + opt.event = atoi( q ); + if( opt.event < 0 || opt.event > 2 ) + goto usage; + } + else if( strcmp( p, "read_timeout" ) == 0 ) + opt.read_timeout = atoi( q ); + else if( strcmp( p, "max_resend" ) == 0 ) + { + opt.max_resend = atoi( q ); + if( opt.max_resend < 0 ) + goto usage; + } + else if( strcmp( p, "request_page" ) == 0 ) + opt.request_page = q; + else if( strcmp( p, "request_size" ) == 0 ) + { + opt.request_size = atoi( q ); + if( opt.request_size < 0 || + opt.request_size > MAX_REQUEST_SIZE ) + goto usage; + } + else if( strcmp( p, "ca_file" ) == 0 ) + opt.ca_file = q; + else if( strcmp( p, "ca_path" ) == 0 ) + opt.ca_path = q; + else if( strcmp( p, "crt_file" ) == 0 ) + opt.crt_file = q; + else if( strcmp( p, "key_file" ) == 0 ) + opt.key_file = q; +#if defined(MBEDTLS_USE_PSA_CRYPTO) && defined(MBEDTLS_X509_CRT_PARSE_C) + else if( strcmp( p, "key_opaque" ) == 0 ) + opt.key_opaque = atoi( q ); +#endif + else if( strcmp( p, "psk" ) == 0 ) + opt.psk = q; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + else if( strcmp( p, "psk_opaque" ) == 0 ) + opt.psk_opaque = atoi( q ); +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + else if( strcmp( p, "ca_callback" ) == 0) + opt.ca_callback = atoi( q ); +#endif + else if( strcmp( p, "psk_identity" ) == 0 ) + opt.psk_identity = q; + else if( strcmp( p, "ecjpake_pw" ) == 0 ) + opt.ecjpake_pw = q; + else if( strcmp( p, "ec_max_ops" ) == 0 ) + opt.ec_max_ops = atoi( q ); + else if( strcmp( p, "force_ciphersuite" ) == 0 ) + { + opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); + + if( opt.force_ciphersuite[0] == 0 ) + { + ret = 2; + goto usage; + } + opt.force_ciphersuite[1] = 0; + } + else if( strcmp( p, "renegotiation" ) == 0 ) + { + opt.renegotiation = (atoi( q )) ? + MBEDTLS_SSL_RENEGOTIATION_ENABLED : + MBEDTLS_SSL_RENEGOTIATION_DISABLED; + } + else if( strcmp( p, "allow_legacy" ) == 0 ) + { + switch( atoi( q ) ) + { + case -1: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; + break; + case 0: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; + break; + case 1: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; + break; + default: goto usage; + } + } + else if( strcmp( p, "renegotiate" ) == 0 ) + { + opt.renegotiate = atoi( q ); + if( opt.renegotiate < 0 || opt.renegotiate > 1 ) + goto usage; + } + else if( strcmp( p, "exchanges" ) == 0 ) + { + opt.exchanges = atoi( q ); + if( opt.exchanges < 1 ) + goto usage; + } + else if( strcmp( p, "reconnect" ) == 0 ) + { + opt.reconnect = atoi( q ); + if( opt.reconnect < 0 || opt.reconnect > 2 ) + goto usage; + } + else if( strcmp( p, "reco_delay" ) == 0 ) + { + opt.reco_delay = atoi( q ); + if( opt.reco_delay < 0 ) + goto usage; + } + else if( strcmp( p, "reconnect_hard" ) == 0 ) + { + opt.reconnect_hard = atoi( q ); + if( opt.reconnect_hard < 0 || opt.reconnect_hard > 1 ) + goto usage; + } + else if( strcmp( p, "tickets" ) == 0 ) + { + opt.tickets = atoi( q ); + if( opt.tickets < 0 || opt.tickets > 2 ) + goto usage; + } + else if( strcmp( p, "alpn" ) == 0 ) + { + opt.alpn_string = q; + } + else if( strcmp( p, "fallback" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.fallback = MBEDTLS_SSL_IS_NOT_FALLBACK; break; + case 1: opt.fallback = MBEDTLS_SSL_IS_FALLBACK; break; + default: goto usage; + } + } + else if( strcmp( p, "extended_ms" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: + opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; + break; + case 1: + opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + break; + default: goto usage; + } + } + else if( strcmp( p, "curves" ) == 0 ) + opt.curves = q; + else if( strcmp( p, "etm" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.etm = MBEDTLS_SSL_ETM_DISABLED; break; + case 1: opt.etm = MBEDTLS_SSL_ETM_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "min_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_0; + else if( strcmp( q, "tls1" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_1; + else if( strcmp( q, "tls1_1" ) == 0 || + strcmp( q, "dtls1" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + else if( strcmp( q, "tls1_2" ) == 0 || + strcmp( q, "dtls1_2" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + else + goto usage; + } + else if( strcmp( p, "max_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_0; + else if( strcmp( q, "tls1" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_1; + else if( strcmp( q, "tls1_1" ) == 0 || + strcmp( q, "dtls1" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + else if( strcmp( q, "tls1_2" ) == 0 || + strcmp( q, "dtls1_2" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + else + goto usage; + } + else if( strcmp( p, "arc4" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.arc4 = MBEDTLS_SSL_ARC4_DISABLED; break; + case 1: opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "allow_sha1" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.allow_sha1 = 0; break; + case 1: opt.allow_sha1 = 1; break; + default: goto usage; + } + } + else if( strcmp( p, "force_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_0; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_0; + } + else if( strcmp( q, "tls1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_1; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_1; + } + else if( strcmp( q, "tls1_1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + else if( strcmp( q, "tls1_2" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + } + else if( strcmp( q, "dtls1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + } + else if( strcmp( q, "dtls1_2" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + } + else + goto usage; + } + else if( strcmp( p, "auth_mode" ) == 0 ) + { + if( strcmp( q, "none" ) == 0 ) + opt.auth_mode = MBEDTLS_SSL_VERIFY_NONE; + else if( strcmp( q, "optional" ) == 0 ) + opt.auth_mode = MBEDTLS_SSL_VERIFY_OPTIONAL; + else if( strcmp( q, "required" ) == 0 ) + opt.auth_mode = MBEDTLS_SSL_VERIFY_REQUIRED; + else + goto usage; + } + else if( strcmp( p, "max_frag_len" ) == 0 ) + { + if( strcmp( q, "512" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_512; + else if( strcmp( q, "1024" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_1024; + else if( strcmp( q, "2048" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_2048; + else if( strcmp( q, "4096" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_4096; + else + goto usage; + } + else if( strcmp( p, "trunc_hmac" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_DISABLED; break; + case 1: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "hs_timeout" ) == 0 ) + { + if( ( p = strchr( q, '-' ) ) == NULL ) + goto usage; + *p++ = '\0'; + opt.hs_to_min = atoi( q ); + opt.hs_to_max = atoi( p ); + if( opt.hs_to_min == 0 || opt.hs_to_max < opt.hs_to_min ) + goto usage; + } + else if( strcmp( p, "mtu" ) == 0 ) + { + opt.dtls_mtu = atoi( q ); + if( opt.dtls_mtu < 0 ) + goto usage; + } + else if( strcmp( p, "dgram_packing" ) == 0 ) + { + opt.dgram_packing = atoi( q ); + if( opt.dgram_packing != 0 && + opt.dgram_packing != 1 ) + { + goto usage; + } + } + else if( strcmp( p, "recsplit" ) == 0 ) + { + opt.recsplit = atoi( q ); + if( opt.recsplit < 0 || opt.recsplit > 1 ) + goto usage; + } + else if( strcmp( p, "dhmlen" ) == 0 ) + { + opt.dhmlen = atoi( q ); + if( opt.dhmlen < 0 ) + goto usage; + } + else if( strcmp( p, "query_config" ) == 0 ) + { + return query_config( q ); + } + else + goto usage; + } + + /* Event-driven IO is incompatible with the above custom + * receive and send functions, as the polling builds on + * refers to the underlying net_context. */ + if( opt.event == 1 && opt.nbio != 1 ) + { + mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" ); + opt.nbio = 1; + } + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( opt.debug_level ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* + * Unhexify the pre-shared key if any is given + */ + if( strlen( opt.psk ) ) + { + unsigned char c; + size_t j; + + if( strlen( opt.psk ) % 2 != 0 ) + { + mbedtls_printf( "pre-shared key not valid hex\n" ); + goto exit; + } + + psk_len = strlen( opt.psk ) / 2; + + for( j = 0; j < strlen( opt.psk ); j += 2 ) + { + c = opt.psk[j]; + if( c >= '0' && c <= '9' ) + c -= '0'; + else if( c >= 'a' && c <= 'f' ) + c -= 'a' - 10; + else if( c >= 'A' && c <= 'F' ) + c -= 'A' - 10; + else + { + mbedtls_printf( "pre-shared key not valid hex\n" ); + goto exit; + } + psk[ j / 2 ] = c << 4; + + c = opt.psk[j + 1]; + if( c >= '0' && c <= '9' ) + c -= '0'; + else if( c >= 'a' && c <= 'f' ) + c -= 'a' - 10; + else if( c >= 'A' && c <= 'F' ) + c -= 'A' - 10; + else + { + mbedtls_printf( "pre-shared key not valid hex\n" ); + goto exit; + } + psk[ j / 2 ] |= c; + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_opaque != 0 ) + { + if( opt.psk == NULL ) + { + mbedtls_printf( "psk_opaque set but no psk to be imported specified.\n" ); + ret = 2; + goto usage; + } + + if( opt.force_ciphersuite[0] <= 0 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( opt.force_ciphersuite[0] > 0 ) + { + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] ); + + if( opt.max_version != -1 && + ciphersuite_info->min_minor_ver > opt.max_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + if( opt.min_version != -1 && + ciphersuite_info->max_minor_ver < opt.min_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + + /* If the server selects a version that's not supported by + * this suite, then there will be no common ciphersuite... */ + if( opt.max_version == -1 || + opt.max_version > ciphersuite_info->max_minor_ver ) + { + opt.max_version = ciphersuite_info->max_minor_ver; + } + if( opt.min_version < ciphersuite_info->min_minor_ver ) + { + opt.min_version = ciphersuite_info->min_minor_ver; + /* DTLS starts with TLS 1.1 */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + opt.min_version < MBEDTLS_SSL_MINOR_VERSION_2 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + + /* Enable RC4 if needed and not explicitly disabled */ + if( ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + if( opt.arc4 == MBEDTLS_SSL_ARC4_DISABLED ) + { + mbedtls_printf( "forced RC4 ciphersuite with RC4 disabled\n" ); + ret = 2; + goto usage; + } + + opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_opaque != 0 ) + { + /* Ensure that the chosen ciphersuite is PSK-only; we must know + * the ciphersuite in advance to set the correct policy for the + * PSK key slot. This limitation might go away in the future. */ + if( ciphersuite_info->key_exchange != MBEDTLS_KEY_EXCHANGE_PSK || + opt.min_version != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + + /* Determine KDF algorithm the opaque PSK will be used in. */ +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else +#endif /* MBEDTLS_SHA512_C */ + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } + +#if defined(MBEDTLS_ECP_C) + if( opt.curves != NULL ) + { + p = (char *) opt.curves; + i = 0; + + if( strcmp( p, "none" ) == 0 ) + { + curve_list[0] = MBEDTLS_ECP_DP_NONE; + } + else if( strcmp( p, "default" ) != 0 ) + { + /* Leave room for a final NULL in curve list */ + while( i < CURVE_LIST_SIZE - 1 && *p != '\0' ) + { + q = p; + + /* Terminate the current string */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + + if( ( curve_cur = mbedtls_ecp_curve_info_from_name( q ) ) != NULL ) + { + curve_list[i++] = curve_cur->grp_id; + } + else + { + mbedtls_printf( "unknown curve %s\n", q ); + mbedtls_printf( "supported curves: " ); + for( curve_cur = mbedtls_ecp_curve_list(); + curve_cur->grp_id != MBEDTLS_ECP_DP_NONE; + curve_cur++ ) + { + mbedtls_printf( "%s ", curve_cur->name ); + } + mbedtls_printf( "\n" ); + goto exit; + } + } + + mbedtls_printf("Number of curves: %d\n", i ); + + if( i == CURVE_LIST_SIZE - 1 && *p != '\0' ) + { + mbedtls_printf( "curves list too long, maximum %d", + CURVE_LIST_SIZE - 1 ); + goto exit; + } + + curve_list[i] = MBEDTLS_ECP_DP_NONE; + } + } +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + { + p = (char *) opt.alpn_string; + i = 0; + + /* Leave room for a final NULL in alpn_list */ + while( i < ALPN_LIST_SIZE - 1 && *p != '\0' ) + { + alpn_list[i++] = p; + + /* Terminate the current string and move on to next one */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + } + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * 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 -0x%x\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * 1.1. Load the trusted CA + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.ca_path ) ) + if( strcmp( opt.ca_path, "none" ) == 0 ) + ret = 0; + else + ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path ); + else if( strlen( opt.ca_file ) ) + if( strcmp( opt.ca_file, "none" ) == 0 ) + ret = 0; + else + ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + for( i = 0; mbedtls_test_cas[i] != NULL; i++ ) + { + ret = mbedtls_x509_crt_parse( &cacert, + (const unsigned char *) mbedtls_test_cas[i], + mbedtls_test_cas_len[i] ); + if( ret != 0 ) + break; + } +#else + { + ret = 1; + mbedtls_printf( "MBEDTLS_CERTS_C not defined." ); + } +#endif + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + + /* + * 1.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 ) ) + if( strcmp( opt.crt_file, "none" ) == 0 ) + ret = 0; + else + ret = mbedtls_x509_crt_parse_file( &clicert, opt.crt_file ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + ret = mbedtls_x509_crt_parse( &clicert, + (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); +#else + { + ret = 1; + mbedtls_printf("MBEDTLS_CERTS_C not defined."); + } +#endif + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", + -ret ); + goto exit; + } + +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.key_file ) ) + if( strcmp( opt.key_file, "none" ) == 0 ) + ret = 0; + else + ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + ret = mbedtls_pk_parse_key( &pkey, + (const unsigned char *) mbedtls_test_cli_key, + mbedtls_test_cli_key_len, NULL, 0 ); +#else + { + ret = 1; + mbedtls_printf("MBEDTLS_CERTS_C not defined."); + } +#endif + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", + -ret ); + goto exit; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.key_opaque != 0 ) + { + if( ( ret = mbedtls_pk_wrap_as_opaque( &pkey, &key_slot, + PSA_ALG_SHA_256 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! " + "mbedtls_pk_wrap_as_opaque returned -0x%x\n\n", -ret ); + goto exit; + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + mbedtls_printf( " ok (key type: %s)\n", mbedtls_pk_get_name( &pkey ) ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + /* + * 2. Start the connection + */ + if( opt.server_addr == NULL) + opt.server_addr = opt.server_name; + + mbedtls_printf( " . Connecting to %s/%s/%s...", + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? "tcp" : "udp", + opt.server_addr, opt.server_port ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, + opt.server_addr, opt.server_port, + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? + MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( opt.nbio > 0 ) + ret = mbedtls_net_set_nonblock( &server_fd ); + else + ret = mbedtls_net_set_block( &server_fd ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\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, + opt.transport, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", + -ret ); + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* The default algorithms profile disables SHA-1, but our tests still + rely on it heavily. */ + if( opt.allow_sha1 > 0 ) + { + crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ); + mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test ); + mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test ); + } + + if( opt.context_crt_cb == 0 ) + mbedtls_ssl_conf_verify( &conf, my_verify, NULL ); + + memset( peer_crt_info, 0, sizeof( peer_crt_info ) ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( opt.auth_mode != DFL_AUTH_MODE ) + mbedtls_ssl_conf_authmode( &conf, opt.auth_mode ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX ) + mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, + opt.hs_to_max ); + + if( opt.dgram_packing != DFL_DGRAM_PACKING ) + mbedtls_ssl_set_datagram_packing( &ssl, opt.dgram_packing ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = mbedtls_ssl_conf_max_frag_len( &conf, opt.mfl_code ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n", + ret ); + goto exit; + } +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( opt.trunc_hmac != DFL_TRUNC_HMAC ) + mbedtls_ssl_conf_truncated_hmac( &conf, opt.trunc_hmac ); +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( opt.extended_ms != DFL_EXTENDED_MS ) + mbedtls_ssl_conf_extended_master_secret( &conf, opt.extended_ms ); +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( opt.etm != DFL_ETM ) + mbedtls_ssl_conf_encrypt_then_mac( &conf, opt.etm ); +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) + if( opt.recsplit != DFL_RECSPLIT ) + mbedtls_ssl_conf_cbc_record_splitting( &conf, opt.recsplit + ? MBEDTLS_SSL_CBC_RECORD_SPLITTING_ENABLED + : MBEDTLS_SSL_CBC_RECORD_SPLITTING_DISABLED ); +#endif + +#if defined(MBEDTLS_DHM_C) + if( opt.dhmlen != DFL_DHMLEN ) + mbedtls_ssl_conf_dhm_min_bitlen( &conf, opt.dhmlen ); +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_alpn_protocols returned %d\n\n", + ret ); + goto exit; + } +#endif + + 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, opt.read_timeout ); + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_conf_session_tickets( &conf, opt.tickets ); +#endif + + if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) + mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite ); + +#if defined(MBEDTLS_ARC4_C) + if( opt.arc4 != DFL_ARC4 ) + mbedtls_ssl_conf_arc4_support( &conf, opt.arc4 ); +#endif + + if( opt.allow_legacy != DFL_ALLOW_LEGACY ) + mbedtls_ssl_conf_legacy_renegotiation( &conf, opt.allow_legacy ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation( &conf, opt.renegotiation ); +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( strcmp( opt.ca_path, "none" ) != 0 && + strcmp( opt.ca_file, "none" ) != 0 ) + { +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( opt.ca_callback != 0 ) + mbedtls_ssl_conf_ca_cb( &conf, ca_callback, &cacert ); + else +#endif + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + } + if( strcmp( opt.crt_file, "none" ) != 0 && + strcmp( opt.key_file, "none" ) != 0 ) + { + 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; + } + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( opt.curves != NULL && + strcmp( opt.curves, "default" ) != 0 ) + { + mbedtls_ssl_conf_curves( &conf, curve_list ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_opaque != 0 ) + { + /* The algorithm has already been determined earlier. */ + status = psa_allocate_key( &slot ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + + policy = psa_key_policy_init(); + psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); + + status = psa_set_key_policy( slot, &policy ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + + status = psa_import_key( slot, PSA_KEY_TYPE_DERIVE, psk, psk_len ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + + if( ( ret = mbedtls_ssl_conf_psk_opaque( &conf, slot, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk_opaque returned %d\n\n", + ret ); + goto exit; + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_ssl_conf_psk( &conf, psk, psk_len, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk returned %d\n\n", + ret ); + goto exit; + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + + if( opt.min_version != DFL_MIN_VERSION ) + mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, + opt.min_version ); + + if( opt.max_version != DFL_MAX_VERSION ) + mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, + opt.max_version ); + +#if defined(MBEDTLS_SSL_FALLBACK_SCSV) + if( opt.fallback != DFL_FALLBACK ) + mbedtls_ssl_conf_fallback( &conf, opt.fallback ); +#endif + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", + -ret ); + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + 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; + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( opt.ecjpake_pw != DFL_ECJPAKE_PW ) + { + if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, + (const unsigned char *) opt.ecjpake_pw, + strlen( opt.ecjpake_pw ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", + ret ); + goto exit; + } + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( opt.context_crt_cb == 1 ) + mbedtls_ssl_set_verify( &ssl, my_verify, NULL ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( opt.nbio == 2 ) + mbedtls_ssl_set_bio( &ssl, &server_fd, my_send, my_recv, NULL ); + else + mbedtls_ssl_set_bio( &ssl, &server_fd, + mbedtls_net_send, mbedtls_net_recv, + opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.dtls_mtu != DFL_DTLS_MTU ) + mbedtls_ssl_set_mtu( &ssl, opt.dtls_mtu ); +#endif + +#if defined(MBEDTLS_TIMING_C) + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); +#endif + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( opt.ec_max_ops != DFL_EC_MAX_OPS ) + mbedtls_ecp_set_max_ops( opt.ec_max_ops ); +#endif + + mbedtls_printf( " ok\n" ); + + /* + * 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 && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n", + -ret ); + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + mbedtls_printf( + " Unable to verify the server's certificate. " + "Either it is invalid,\n" + " or you didn't set ca_file or ca_path " + "to an appropriate value.\n" + " Alternatively, you may want to use " + "auth_mode=optional for testing purposes.\n" ); + mbedtls_printf( "\n" ); + goto exit; + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + ret = idle( &server_fd, &timer, ret ); +#else + ret = idle( &server_fd, ret ); +#endif + if( ret != 0 ) + goto exit; + } + } + + mbedtls_printf( " ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", + mbedtls_ssl_get_version( &ssl ), + mbedtls_ssl_get_ciphersuite( &ssl ) ); + + if( ( ret = mbedtls_ssl_get_record_expansion( &ssl ) ) >= 0 ) + mbedtls_printf( " [ Record expansion is %d ]\n", ret ); + else + mbedtls_printf( " [ Record expansion is unknown (compression) ]\n" ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + mbedtls_printf( " [ Maximum fragment length is %u ]\n", + (unsigned int) mbedtls_ssl_get_max_frag_len( &ssl ) ); +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + { + const char *alp = mbedtls_ssl_get_alpn_protocol( &ssl ); + mbedtls_printf( " [ Application Layer Protocol is %s ]\n", + alp ? alp : "(none)" ); + } +#endif + + if( opt.reconnect != 0 ) + { + mbedtls_printf(" . Saving session for reuse..." ); + fflush( stdout ); + + if( ( ret = mbedtls_ssl_get_session( &ssl, &saved_session ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_get_session returned -0x%x\n\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * 5. Verify the server certificate + */ + mbedtls_printf( " . Verifying peer X.509 certificate..." ); + + if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), + " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + mbedtls_printf( " . Peer certificate information ...\n" ); + mbedtls_printf( "%s\n", peer_crt_info ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( opt.renegotiate ) + { + /* + * Perform renegotiation (this must be done when the server is waiting + * for input from our side). + */ + mbedtls_printf( " . Performing renegotiation..." ); + fflush( stdout ); + while( ( ret = mbedtls_ssl_renegotiate( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", + ret ); + goto exit; + } + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + + } + mbedtls_printf( " ok\n" ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * 6. Write the GET request + */ + retry_left = opt.max_resend; +send_request: + mbedtls_printf( " > Write to server:" ); + fflush( stdout ); + + len = mbedtls_snprintf( (char *) buf, sizeof( buf ) - 1, GET_REQUEST, + opt.request_page ); + tail_len = (int) strlen( GET_REQUEST_END ); + + /* Add padding to GET request to reach opt.request_size in length */ + if( opt.request_size != DFL_REQUEST_SIZE && + len + tail_len < opt.request_size ) + { + memset( buf + len, 'A', opt.request_size - len - tail_len ); + len += opt.request_size - len - tail_len; + } + + strncpy( (char *) buf + len, GET_REQUEST_END, sizeof( buf ) - len - 1 ); + len += tail_len; + + /* Truncate if request size is smaller than the "natural" size */ + if( opt.request_size != DFL_REQUEST_SIZE && + len > opt.request_size ) + { + len = opt.request_size; + + /* Still end with \r\n unless that's really not possible */ + if( len >= 2 ) buf[len - 2] = '\r'; + if( len >= 1 ) buf[len - 1] = '\n'; + } + + if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + written = 0; + frags = 0; + + do + { + while( ( ret = mbedtls_ssl_write( &ssl, buf + written, + len - written ) ) < 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned -0x%x\n\n", + -ret ); + goto exit; + } + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + } + + frags++; + written += ret; + } + while( written < len ); + } + else /* Not stream, so datagram */ + { + while( 1 ) + { + ret = mbedtls_ssl_write( &ssl, buf, len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + break; + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + } + + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", + ret ); + goto exit; + } + + frags = 1; + written = ret; + + if( written < len ) + { + mbedtls_printf( " warning\n ! request didn't fit into single datagram and " + "was truncated to size %u", (unsigned) written ); + } + } + + buf[written] = '\0'; + mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n", + written, frags, (char *) buf ); + + /* Send a non-empty request if request_size == 0 */ + if ( len == 0 ) + { + opt.request_size = DFL_REQUEST_SIZE; + goto send_request; + } + + /* + * 7. Read the HTTP response + */ + mbedtls_printf( " < Read from server:" ); + fflush( stdout ); + + /* + * TLS and DTLS need different reading styles (stream vs datagram) + */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + do + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + if( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE ) + { + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + continue; + } + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + ret = 0; + goto close_notify; + + case 0: + case MBEDTLS_ERR_NET_CONN_RESET: + mbedtls_printf( " connection was reset by peer\n" ); + ret = 0; + goto reconnect; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", + -ret ); + goto exit; + } + } + + len = ret; + buf[len] = '\0'; + mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); + + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( ret > 0 && buf[len-1] == '\n' ) + { + ret = 0; + break; + } + } + while( 1 ); + } + else /* Not stream, so datagram */ + { + len = sizeof( buf ) - 1; + memset( buf, 0, sizeof( buf ) ); + + while( 1 ) + { + ret = mbedtls_ssl_read( &ssl, buf, len ); + +#if defined(MBEDTLS_ECP_RESTARTABLE) + if( ret == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + continue; +#endif + + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE ) + break; + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + } + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_TIMEOUT: + mbedtls_printf( " timeout\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", -ret ); + goto exit; + } + } + + len = ret; + buf[len] = '\0'; + mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); + ret = 0; + } + + /* + * 7b. Simulate hard reset and reconnect from same port? + */ + if( opt.reconnect_hard != 0 ) + { + opt.reconnect_hard = 0; + + mbedtls_printf( " . Restarting connection from same port..." ); + fflush( stdout ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + memset( peer_crt_info, 0, sizeof( peer_crt_info ) ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", + -ret ); + goto exit; + } + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", + -ret ); + goto exit; + } + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &server_fd, &timer, ret ); +#else + idle( &server_fd, ret ); +#endif + } + } + + mbedtls_printf( " ok\n" ); + + goto send_request; + } + + /* + * 7c. Continue doing data exchanges? + */ + if( --opt.exchanges > 0 ) + goto send_request; + + /* + * 8. Done, cleanly close the connection + */ +close_notify: + mbedtls_printf( " . Closing the connection..." ); + fflush( stdout ); + + /* 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. Reconnect? + */ +reconnect: + if( opt.reconnect != 0 ) + { + --opt.reconnect; + + mbedtls_net_free( &server_fd ); + +#if defined(MBEDTLS_TIMING_C) + if( opt.reco_delay > 0 ) + mbedtls_net_usleep( 1000000 * opt.reco_delay ); +#endif + + mbedtls_printf( " . Reconnecting with saved session..." ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + memset( peer_crt_info, 0, sizeof( peer_crt_info ) ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( ( ret = mbedtls_ssl_session_reset( &ssl ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_session_reset returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( ( ret = mbedtls_ssl_set_session( &ssl, &saved_session ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_session returned %d\n\n", + ret ); + goto exit; + } + + if( ( ret = mbedtls_net_connect( &server_fd, + opt.server_addr, opt.server_port, + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? + MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_connect returned -0x%x\n\n", + -ret ); + goto exit; + } + + if( opt.nbio > 0 ) + ret = mbedtls_net_set_nonblock( &server_fd ); + else + ret = mbedtls_net_set_block( &server_fd ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", + -ret ); + goto exit; + } + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_SSL_WANT_READ && + ret != MBEDTLS_ERR_SSL_WANT_WRITE && + ret != MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", + -ret ); + goto exit; + } + } + + mbedtls_printf( " ok\n" ); + + goto send_request; + } + + /* + * Cleanup 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: -0x%X - %s\n\n", -ret, error_buf ); + } +#endif + + mbedtls_net_free( &server_fd ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free( &clicert ); + mbedtls_x509_crt_free( &cacert ); + mbedtls_pk_free( &pkey ); +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_destroy_key( key_slot ); +#endif +#endif + mbedtls_ssl_session_free( &saved_session ); + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_opaque != 0 ) + { + /* This is ok even if the slot hasn't been + * initialized (we might have jumed here + * immediately because of bad cmd line params, + * for example). */ + status = psa_destroy_key( slot ); + if( status != PSA_SUCCESS ) + { + mbedtls_printf( "Failed to destroy key slot %u - error was %d", + (unsigned) slot, (int) status ); + if( ret == 0 ) + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && + MBEDTLS_USE_PSA_CRYPTO */ + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + // Shell can not handle large exit numbers -> 1 for errors + if( ret < 0 ) + ret = 1; + + return( ret ); +} +#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 MBEDTLS_TIMING_C */ diff --git a/programs/ssl/ssl_fork_server.c b/programs/ssl/ssl_fork_server.c new file mode 100644 index 000000000..b6f1cc4fd --- /dev/null +++ b/programs/ssl/ssl_fork_server.c @@ -0,0 +1,435 @@ +/* + * SSL server demonstration program using fork() for handling multiple clients + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_CERTS_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_CERTS_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"); + return( 0 ); +} +#elif defined(_WIN32) +int main( void ) +{ + mbedtls_printf("_WIN32 defined. This application requires fork() and signals " + "to work correctly.\n"); + return( 0 ); +} +#else + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/timing.h" + +#include +#include + +#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32) +#include +#endif + +#define HTTP_RESPONSE \ + "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ + "

mbed TLS Test Server

\r\n" \ + "

Successful connection using: %s

\r\n" + +#define DEBUG_LEVEL 0 + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +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 ); + 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" ); + + 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_init( &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 ); + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_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 */ diff --git a/programs/ssl/ssl_mail_client.c b/programs/ssl/ssl_mail_client.c new file mode 100644 index 000000000..c73297c2a --- /dev/null +++ b/programs/ssl/ssl_mail_client.c @@ -0,0 +1,871 @@ +/* + * SSL client for SMTP servers + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* Enable definition of gethostname() even when compiling with -std=c99. Must + * be set before config.h, which pulls in glibc's features.h indirectly. + * Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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"); + return( 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 "mbedtls/certs.h" +#include "mbedtls/x509.h" + +#include +#include + +#if !defined(_MSC_VER) || defined(EFIX64) || defined(EFI32) +#include +#else +#include +#endif + +#if defined(_WIN32) || defined(_WIN32_WCE) +#include +#include + +#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= default: all enabled\n" \ + " acceptable ciphersuite names:\n" + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +/* + * 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 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + mbedtls_printf( " . Peer certificate information ...\n" ); + mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", + mbedtls_ssl_get_peer_cert( ssl ) ); + mbedtls_printf( "%s\n", buf ); + + return( 0 ); +} + +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_CERTS_C) && 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_CERTS_C and/or 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 +#if defined(MBEDTLS_CERTS_C) + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); +#else + { + mbedtls_printf("MBEDTLS_CERTS_C not defined."); + goto exit; + } +#endif + 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, "" ); + else +#endif +#if defined(MBEDTLS_CERTS_C) && 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 ); +#else + { + mbedtls_printf("MBEDTLS_CERTS_C or 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 ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( 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 */ diff --git a/programs/ssl/ssl_pthread_server.c b/programs/ssl/ssl_pthread_server.c new file mode 100644 index 000000000..b5026959a --- /dev/null +++ b/programs/ssl/ssl_pthread_server.c @@ -0,0 +1,545 @@ +/* + * SSL server demonstration program using pthread for handling multiple + * clients. + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_CERTS_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_CERTS_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"); + return( 0 ); +} +#else + +#include +#include + +#if defined(_WIN32) +#include +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.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 + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +#define HTTP_RESPONSE \ + "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ + "

mbed TLS Test Server

\r\n" \ + "

Successful connection using: %s

\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, -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, -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, -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, 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, 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, -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 ); + + /* + * 1. 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 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1b. 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", + -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", + -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", -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", 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 + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( ret ); +} + +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_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 */ diff --git a/programs/ssl/ssl_server.c b/programs/ssl/ssl_server.c new file mode 100644 index 000000000..1852b2bad --- /dev/null +++ b/programs/ssl/ssl_server.c @@ -0,0 +1,416 @@ +/* + * SSL server demonstration program + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_CERTS_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_PEM_PARSE_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_CERTS_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"); + return( 0 ); +} +#else + +#include +#include + +#if defined(_WIN32) +#include +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/ssl.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.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" \ + "

mbed TLS Test Server

\r\n" \ + "

Successful connection using: %s

\r\n" + +#define DEBUG_LEVEL 0 + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +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. 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 ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key 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" ); + + /* + * 3. 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" ); + + /* + * 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", -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 ); + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_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 */ diff --git a/programs/ssl/ssl_server2.c b/programs/ssl/ssl_server2.c new file mode 100644 index 000000000..d1e45be3c --- /dev/null +++ b/programs/ssl/ssl_server2.c @@ -0,0 +1,3533 @@ +/* + * SSL client with options + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_calloc calloc +#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_ENTROPY_C) || \ + !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_SRV_C) || \ + !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_CTR_DRBG_C) +int main( void ) +{ + mbedtls_printf("MBEDTLS_ENTROPY_C and/or " + "MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or " + "MBEDTLS_NET_C and/or MBEDTLS_CTR_DRBG_C and/or not defined.\n"); + return( 0 ); +} +#else + +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/certs.h" +#include "mbedtls/x509.h" +#include "mbedtls/error.h" +#include "mbedtls/debug.h" +#include "mbedtls/timing.h" + +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#include "psa/crypto.h" +#include "mbedtls/psa_util.h" +#endif + +#include +#include +#include +#include + +#if !defined(_MSC_VER) +#include +#endif + +#if !defined(_WIN32) +#include +#endif + +#if defined(MBEDTLS_SSL_CACHE_C) +#include "mbedtls/ssl_cache.h" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) +#include "mbedtls/ssl_ticket.h" +#endif + +#if defined(MBEDTLS_SSL_COOKIE_C) +#include "mbedtls/ssl_cookie.h" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#include "mbedtls/memory_buffer_alloc.h" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && defined(MBEDTLS_FS_IO) +#define SNI_OPTION +#endif + +#if defined(_WIN32) +#include +#endif + +/* Size of memory to be allocated for the heap, when using the library's memory + * management and MBEDTLS_MEMORY_BUFFER_ALLOC_C is enabled. */ +#define MEMORY_HEAP_SIZE 120000 + +#define DFL_SERVER_ADDR NULL +#define DFL_SERVER_PORT "4433" +#define DFL_RESPONSE_SIZE -1 +#define DFL_DEBUG_LEVEL 0 +#define DFL_NBIO 0 +#define DFL_EVENT 0 +#define DFL_READ_TIMEOUT 0 +#define DFL_CA_FILE "" +#define DFL_CA_PATH "" +#define DFL_CRT_FILE "" +#define DFL_KEY_FILE "" +#define DFL_CRT_FILE2 "" +#define DFL_KEY_FILE2 "" +#define DFL_ASYNC_OPERATIONS "-" +#define DFL_ASYNC_PRIVATE_DELAY1 ( -1 ) +#define DFL_ASYNC_PRIVATE_DELAY2 ( -1 ) +#define DFL_ASYNC_PRIVATE_ERROR ( 0 ) +#define DFL_PSK "" +#define DFL_PSK_OPAQUE 0 +#define DFL_PSK_LIST_OPAQUE 0 +#define DFL_PSK_IDENTITY "Client_identity" +#define DFL_ECJPAKE_PW NULL +#define DFL_PSK_LIST NULL +#define DFL_FORCE_CIPHER 0 +#define DFL_VERSION_SUITES NULL +#define DFL_RENEGOTIATION MBEDTLS_SSL_RENEGOTIATION_DISABLED +#define DFL_ALLOW_LEGACY -2 +#define DFL_RENEGOTIATE 0 +#define DFL_RENEGO_DELAY -2 +#define DFL_RENEGO_PERIOD ( (uint64_t)-1 ) +#define DFL_EXCHANGES 1 +#define DFL_MIN_VERSION -1 +#define DFL_MAX_VERSION -1 +#define DFL_ARC4 -1 +#define DFL_SHA1 -1 +#define DFL_AUTH_MODE -1 +#define DFL_CERT_REQ_CA_LIST MBEDTLS_SSL_CERT_REQ_CA_LIST_ENABLED +#define DFL_MFL_CODE MBEDTLS_SSL_MAX_FRAG_LEN_NONE +#define DFL_TRUNC_HMAC -1 +#define DFL_TICKETS MBEDTLS_SSL_SESSION_TICKETS_ENABLED +#define DFL_TICKET_TIMEOUT 86400 +#define DFL_CACHE_MAX -1 +#define DFL_CACHE_TIMEOUT -1 +#define DFL_SNI NULL +#define DFL_ALPN_STRING NULL +#define DFL_CURVES NULL +#define DFL_DHM_FILE NULL +#define DFL_TRANSPORT MBEDTLS_SSL_TRANSPORT_STREAM +#define DFL_COOKIES 1 +#define DFL_ANTI_REPLAY -1 +#define DFL_HS_TO_MIN 0 +#define DFL_HS_TO_MAX 0 +#define DFL_DTLS_MTU -1 +#define DFL_BADMAC_LIMIT -1 +#define DFL_DGRAM_PACKING 1 +#define DFL_EXTENDED_MS -1 +#define DFL_ETM -1 +#define DFL_CA_CALLBACK 0 + +#define LONG_RESPONSE "

01-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "02-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "03-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "04-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "05-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "06-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah\r\n" \ + "07-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah-blah

\r\n" + +/* Uncomment LONG_RESPONSE at the end of HTTP_RESPONSE to test sending longer + * packets (for fragmentation purposes) */ +#define HTTP_RESPONSE \ + "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \ + "

mbed TLS Test Server

\r\n" \ + "

Successful connection using: %s

\r\n" // LONG_RESPONSE + +/* + * Size of the basic I/O buffer. Able to hold our default response. + * + * You will need to adapt the mbedtls_ssl_get_bytes_avail() test in ssl-opt.sh + * if you change this value to something outside the range <= 100 or > 500 + */ +#define DFL_IO_BUF_LEN 200 + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +#if defined(MBEDTLS_FS_IO) +#define USAGE_IO \ + " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (pre-loaded)\n" \ + " ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (pre-loaded) (overrides ca_file)\n" \ + " crt_file=%%s Your own cert and chain (in bottom to top order, top may be omitted)\n" \ + " default: see note after key_file2\n" \ + " key_file=%%s default: see note after key_file2\n" \ + " crt_file2=%%s Your second cert and chain (in bottom to top order, top may be omitted)\n" \ + " default: see note after key_file2\n" \ + " key_file2=%%s default: see note below\n" \ + " note: if neither crt_file/key_file nor crt_file2/key_file2 are used,\n" \ + " preloaded certificate(s) and key(s) are used if available\n" \ + " dhm_file=%%s File containing Diffie-Hellman parameters\n" \ + " default: preloaded parameters\n" +#else +#define USAGE_IO \ + "\n" \ + " No file operations available (MBEDTLS_FS_IO not defined)\n" \ + "\n" +#endif /* MBEDTLS_FS_IO */ +#else +#define USAGE_IO "" +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +#define USAGE_SSL_ASYNC \ + " async_operations=%%c... d=decrypt, s=sign (default: -=off)\n" \ + " async_private_delay1=%%d Asynchronous delay for key_file or preloaded key\n" \ + " async_private_delay2=%%d Asynchronous delay for key_file2 and sni\n" \ + " default: -1 (not asynchronous)\n" \ + " async_private_error=%%d Async callback error injection (default=0=none,\n" \ + " 1=start, 2=cancel, 3=resume, negative=first time only)" +#else +#define USAGE_SSL_ASYNC "" +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#define USAGE_PSK_RAW \ + " psk=%%s default: \"\" (in hex, without 0x)\n" \ + " psk_list=%%s default: \"\"\n" \ + " A list of (PSK identity, PSK value) pairs.\n" \ + " The PSK values are in hex, without 0x.\n" \ + " id1,psk1[,id2,psk2[,...]]\n" \ + " psk_identity=%%s default: \"Client_identity\"\n" +#if defined(MBEDTLS_USE_PSA_CRYPTO) +#define USAGE_PSK_SLOT \ + " psk_opaque=%%d default: 0 (don't use opaque static PSK)\n" \ + " Enable this to store the PSK configured through command line\n" \ + " parameter `psk` in a PSA-based key slot.\n" \ + " Note: Currently only supported in conjunction with\n" \ + " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ + " to force a particular PSK-only ciphersuite.\n" \ + " Note: This is to test integration of PSA-based opaque PSKs with\n" \ + " Mbed TLS only. Production systems are likely to configure Mbed TLS\n" \ + " with prepopulated key slots instead of importing raw key material.\n" \ + " psk_list_opaque=%%d default: 0 (don't use opaque dynamic PSKs)\n" \ + " Enable this to store the list of dynamically chosen PSKs configured\n" \ + " through the command line parameter `psk_list` in PSA-based key slots.\n" \ + " Note: Currently only supported in conjunction with\n" \ + " the use of min_version to force TLS 1.2 and force_ciphersuite \n" \ + " to force a particular PSK-only ciphersuite.\n" \ + " Note: This is to test integration of PSA-based opaque PSKs with\n" \ + " Mbed TLS only. Production systems are likely to configure Mbed TLS\n" \ + " with prepopulated key slots instead of importing raw key material.\n" +#else +#define USAGE_PSK_SLOT "" +#endif /* MBEDTLS_USE_PSA_CRYPTO */ +#define USAGE_PSK USAGE_PSK_RAW USAGE_PSK_SLOT +#else +#define USAGE_PSK "" +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) +#define USAGE_CA_CALLBACK \ + " ca_callback=%%d default: 0 (disabled)\n" \ + " Enable this to use the trusted certificate callback function\n" +#else +#define USAGE_CA_CALLBACK "" +#endif /* MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK */ +#if defined(MBEDTLS_SSL_SESSION_TICKETS) +#define USAGE_TICKETS \ + " tickets=%%d default: 1 (enabled)\n" \ + " ticket_timeout=%%d default: 86400 (one day)\n" +#else +#define USAGE_TICKETS "" +#endif /* MBEDTLS_SSL_SESSION_TICKETS */ + +#if defined(MBEDTLS_SSL_CACHE_C) +#define USAGE_CACHE \ + " cache_max=%%d default: cache default (50)\n" \ + " cache_timeout=%%d default: cache default (1d)\n" +#else +#define USAGE_CACHE "" +#endif /* MBEDTLS_SSL_CACHE_C */ + +#if defined(SNI_OPTION) +#define USAGE_SNI \ + " sni=%%s name1,cert1,key1,ca1,crl1,auth1[,...]\n" \ + " default: disabled\n" +#else +#define USAGE_SNI "" +#endif /* SNI_OPTION */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) +#define USAGE_MAX_FRAG_LEN \ + " max_frag_len=%%d default: 16384 (tls default)\n" \ + " options: 512, 1024, 2048, 4096\n" +#else +#define USAGE_MAX_FRAG_LEN "" +#endif /* MBEDTLS_SSL_MAX_FRAGMENT_LENGTH */ + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#define USAGE_TRUNC_HMAC \ + " trunc_hmac=%%d default: library default\n" +#else +#define USAGE_TRUNC_HMAC "" +#endif + +#if defined(MBEDTLS_SSL_ALPN) +#define USAGE_ALPN \ + " alpn=%%s default: \"\" (disabled)\n" \ + " example: spdy/1,http/1.1\n" +#else +#define USAGE_ALPN "" +#endif /* MBEDTLS_SSL_ALPN */ + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#define USAGE_COOKIES \ + " cookies=0/1/-1 default: 1 (enabled)\n" \ + " 0: disabled, -1: library default (broken)\n" +#else +#define USAGE_COOKIES "" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) +#define USAGE_ANTI_REPLAY \ + " anti_replay=0/1 default: (library default: enabled)\n" +#else +#define USAGE_ANTI_REPLAY "" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) +#define USAGE_BADMAC_LIMIT \ + " badmac_limit=%%d default: (library default: disabled)\n" +#else +#define USAGE_BADMAC_LIMIT "" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) +#define USAGE_DTLS \ + " dtls=%%d default: 0 (TLS)\n" \ + " hs_timeout=%%d-%%d default: (library default: 1000-60000)\n" \ + " range of DTLS handshake timeouts in millisecs\n" \ + " mtu=%%d default: (library default: unlimited)\n" \ + " dgram_packing=%%d default: 1 (allowed)\n" \ + " allow or forbid packing of multiple\n" \ + " records within a single datgram.\n" +#else +#define USAGE_DTLS "" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) +#define USAGE_EMS \ + " extended_ms=0/1 default: (library default: on)\n" +#else +#define USAGE_EMS "" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) +#define USAGE_ETM \ + " etm=0/1 default: (library default: on)\n" +#else +#define USAGE_ETM "" +#endif + +#if defined(MBEDTLS_SSL_RENEGOTIATION) +#define USAGE_RENEGO \ + " renegotiation=%%d default: 0 (disabled)\n" \ + " renegotiate=%%d default: 0 (disabled)\n" \ + " renego_delay=%%d default: -2 (library default)\n" \ + " renego_period=%%d default: (2^64 - 1 for TLS, 2^48 - 1 for DTLS)\n" +#else +#define USAGE_RENEGO "" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) +#define USAGE_ECJPAKE \ + " ecjpake_pw=%%s default: none (disabled)\n" +#else +#define USAGE_ECJPAKE "" +#endif + +#if defined(MBEDTLS_ECP_C) +#define USAGE_CURVES \ + " curves=a,b,c,d default: \"default\" (library default)\n" \ + " example: \"secp521r1,brainpoolP512r1\"\n" \ + " - use \"none\" for empty list\n" \ + " - see mbedtls_ecp_curve_list()\n" \ + " for acceptable curve names\n" +#else +#define USAGE_CURVES "" +#endif + +#define USAGE \ + "\n usage: ssl_server2 param=<>...\n" \ + "\n acceptable parameters:\n" \ + " server_addr=%%s default: (all interfaces)\n" \ + " server_port=%%d default: 4433\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " buffer_size=%%d default: 200 \n" \ + " (minimum: 1, max: 16385)\n" \ + " response_size=%%d default: about 152 (basic response)\n" \ + " (minimum: 0, max: 16384)\n" \ + " increases buffer_size if bigger\n"\ + " nbio=%%d default: 0 (blocking I/O)\n" \ + " options: 1 (non-blocking), 2 (added delays)\n" \ + " event=%%d default: 0 (loop)\n" \ + " options: 1 (level-triggered, implies nbio=1),\n" \ + " read_timeout=%%d default: 0 ms (no timeout)\n" \ + "\n" \ + USAGE_DTLS \ + USAGE_COOKIES \ + USAGE_ANTI_REPLAY \ + USAGE_BADMAC_LIMIT \ + "\n" \ + " auth_mode=%%s default: (library default: none)\n" \ + " options: none, optional, required\n" \ + " cert_req_ca_list=%%d default: 1 (send ca list)\n" \ + " options: 1 (send ca list), 0 (don't send)\n" \ + USAGE_IO \ + USAGE_SSL_ASYNC \ + USAGE_SNI \ + "\n" \ + USAGE_PSK \ + USAGE_CA_CALLBACK \ + USAGE_ECJPAKE \ + "\n" \ + " allow_legacy=%%d default: (library default: no)\n" \ + USAGE_RENEGO \ + " exchanges=%%d default: 1\n" \ + "\n" \ + USAGE_TICKETS \ + USAGE_CACHE \ + USAGE_MAX_FRAG_LEN \ + USAGE_TRUNC_HMAC \ + USAGE_ALPN \ + USAGE_EMS \ + USAGE_ETM \ + USAGE_CURVES \ + "\n" \ + " arc4=%%d default: (library default: 0)\n" \ + " allow_sha1=%%d default: 0\n" \ + " min_version=%%s default: (library default: tls1)\n" \ + " max_version=%%s default: (library default: tls1_2)\n" \ + " force_version=%%s default: \"\" (none)\n" \ + " options: ssl3, tls1, tls1_1, tls1_2, dtls1, dtls1_2\n" \ + "\n" \ + " version_suites=a,b,c,d per-version ciphersuites\n" \ + " in order from ssl3 to tls1_2\n" \ + " default: all enabled\n" \ + " force_ciphersuite= default: all enabled\n" \ + " query_config= return 0 if the specified\n" \ + " configuration macro is defined and 1\n" \ + " otherwise. The expansion of the macro\n" \ + " is printed if it is defined\n" \ + " acceptable ciphersuite names:\n" + + +#define ALPN_LIST_SIZE 10 +#define CURVE_LIST_SIZE 20 + +#define PUT_UINT64_BE(out_be,in_le,i) \ +{ \ + (out_be)[(i) + 0] = (unsigned char)( ( (in_le) >> 56 ) & 0xFF ); \ + (out_be)[(i) + 1] = (unsigned char)( ( (in_le) >> 48 ) & 0xFF ); \ + (out_be)[(i) + 2] = (unsigned char)( ( (in_le) >> 40 ) & 0xFF ); \ + (out_be)[(i) + 3] = (unsigned char)( ( (in_le) >> 32 ) & 0xFF ); \ + (out_be)[(i) + 4] = (unsigned char)( ( (in_le) >> 24 ) & 0xFF ); \ + (out_be)[(i) + 5] = (unsigned char)( ( (in_le) >> 16 ) & 0xFF ); \ + (out_be)[(i) + 6] = (unsigned char)( ( (in_le) >> 8 ) & 0xFF ); \ + (out_be)[(i) + 7] = (unsigned char)( ( (in_le) >> 0 ) & 0xFF ); \ +} + +#if defined(MBEDTLS_CHECK_PARAMS) +#include "mbedtls/platform_util.h" +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +/* + * global options + */ +struct options +{ + const char *server_addr; /* address on which the ssl service runs */ + const char *server_port; /* port on which the ssl service runs */ + int debug_level; /* level of debugging */ + int nbio; /* should I/O be blocking? */ + int event; /* loop or event-driven IO? level or edge triggered? */ + uint32_t read_timeout; /* timeout on mbedtls_ssl_read() in milliseconds */ + int response_size; /* pad response with header to requested size */ + uint16_t buffer_size; /* IO buffer size */ + const char *ca_file; /* the file with the CA certificate(s) */ + const char *ca_path; /* the path with the CA certificate(s) reside */ + const char *crt_file; /* the file with the server certificate */ + const char *key_file; /* the file with the server key */ + const char *crt_file2; /* the file with the 2nd server certificate */ + const char *key_file2; /* the file with the 2nd server key */ + const char *async_operations; /* supported SSL asynchronous operations */ + int async_private_delay1; /* number of times f_async_resume needs to be called for key 1, or -1 for no async */ + int async_private_delay2; /* number of times f_async_resume needs to be called for key 2, or -1 for no async */ + int async_private_error; /* inject error in async private callback */ +#if defined(MBEDTLS_USE_PSA_CRYPTO) + int psk_opaque; + int psk_list_opaque; +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + int ca_callback; /* Use callback for trusted certificate list */ +#endif + const char *psk; /* the pre-shared key */ + const char *psk_identity; /* the pre-shared key identity */ + char *psk_list; /* list of PSK id/key pairs for callback */ + const char *ecjpake_pw; /* the EC J-PAKE password */ + int force_ciphersuite[2]; /* protocol/ciphersuite to use, or all */ + const char *version_suites; /* per-version ciphersuites */ + int renegotiation; /* enable / disable renegotiation */ + int allow_legacy; /* allow legacy renegotiation */ + int renegotiate; /* attempt renegotiation? */ + int renego_delay; /* delay before enforcing renegotiation */ + uint64_t renego_period; /* period for automatic renegotiation */ + int exchanges; /* number of data exchanges */ + int min_version; /* minimum protocol version accepted */ + int max_version; /* maximum protocol version accepted */ + int arc4; /* flag for arc4 suites support */ + int allow_sha1; /* flag for SHA-1 support */ + int auth_mode; /* verify mode for connection */ + int cert_req_ca_list; /* should we send the CA list? */ + unsigned char mfl_code; /* code for maximum fragment length */ + int trunc_hmac; /* accept truncated hmac? */ + int tickets; /* enable / disable session tickets */ + int ticket_timeout; /* session ticket lifetime */ + int cache_max; /* max number of session cache entries */ + int cache_timeout; /* expiration delay of session cache entries */ + char *sni; /* string describing sni information */ + const char *curves; /* list of supported elliptic curves */ + const char *alpn_string; /* ALPN supported protocols */ + const char *dhm_file; /* the file with the DH parameters */ + int extended_ms; /* allow negotiation of extended MS? */ + int etm; /* allow negotiation of encrypt-then-MAC? */ + int transport; /* TLS or DTLS? */ + int cookies; /* Use cookies for DTLS? -1 to break them */ + int anti_replay; /* Use anti-replay for DTLS? -1 for default */ + uint32_t hs_to_min; /* Initial value of DTLS handshake timer */ + uint32_t hs_to_max; /* Max value of DTLS handshake timer */ + int dtls_mtu; /* UDP Maximum tranport unit for DTLS */ + int dgram_packing; /* allow/forbid datagram packing */ + int badmac_limit; /* Limit of records with bad MAC */ +} opt; + +int query_config( const char *config ); + +static 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_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. */ + ((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 */ + +/* + * Test recv/send functions that make sure each try returns + * WANT_READ/WANT_WRITE at least once before sucesseding + */ +static int my_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 ); +} + +static int my_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 ); +} + +/* + * Return authmode from string, or -1 on error + */ +static int get_auth_mode( const char *s ) +{ + if( strcmp( s, "none" ) == 0 ) + return( MBEDTLS_SSL_VERIFY_NONE ); + if( strcmp( s, "optional" ) == 0 ) + return( MBEDTLS_SSL_VERIFY_OPTIONAL ); + if( strcmp( s, "required" ) == 0 ) + return( MBEDTLS_SSL_VERIFY_REQUIRED ); + + return( -1 ); +} + +/* + * Used by sni_parse and psk_parse to handle coma-separated lists + */ +#define GET_ITEM( dst ) \ + dst = p; \ + while( *p != ',' ) \ + if( ++p > end ) \ + goto error; \ + *p++ = '\0'; + +#if defined(SNI_OPTION) +typedef struct _sni_entry sni_entry; + +struct _sni_entry { + const char *name; + mbedtls_x509_crt *cert; + mbedtls_pk_context *key; + mbedtls_x509_crt* ca; + mbedtls_x509_crl* crl; + int authmode; + sni_entry *next; +}; + +void sni_free( sni_entry *head ) +{ + sni_entry *cur = head, *next; + + while( cur != NULL ) + { + mbedtls_x509_crt_free( cur->cert ); + mbedtls_free( cur->cert ); + + mbedtls_pk_free( cur->key ); + mbedtls_free( cur->key ); + + mbedtls_x509_crt_free( cur->ca ); + mbedtls_free( cur->ca ); + + mbedtls_x509_crl_free( cur->crl ); + mbedtls_free( cur->crl ); + + next = cur->next; + mbedtls_free( cur ); + cur = next; + } +} + +/* + * Parse a string of sextuples name1,crt1,key1,ca1,crl1,auth1[,...] + * into a usable sni_entry list. For ca1, crl1, auth1, the special value + * '-' means unset. If ca1 is unset, then crl1 is ignored too. + * + * Modifies the input string! This is not production quality! + */ +sni_entry *sni_parse( char *sni_string ) +{ + sni_entry *cur = NULL, *new = NULL; + char *p = sni_string; + char *end = p; + char *crt_file, *key_file, *ca_file, *crl_file, *auth_str; + + while( *end != '\0' ) + ++end; + *end = ','; + + while( p <= end ) + { + if( ( new = mbedtls_calloc( 1, sizeof( sni_entry ) ) ) == NULL ) + { + sni_free( cur ); + return( NULL ); + } + + GET_ITEM( new->name ); + GET_ITEM( crt_file ); + GET_ITEM( key_file ); + GET_ITEM( ca_file ); + GET_ITEM( crl_file ); + GET_ITEM( auth_str ); + + if( ( new->cert = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ) ) == NULL || + ( new->key = mbedtls_calloc( 1, sizeof( mbedtls_pk_context ) ) ) == NULL ) + goto error; + + mbedtls_x509_crt_init( new->cert ); + mbedtls_pk_init( new->key ); + + if( mbedtls_x509_crt_parse_file( new->cert, crt_file ) != 0 || + mbedtls_pk_parse_keyfile( new->key, key_file, "" ) != 0 ) + goto error; + + if( strcmp( ca_file, "-" ) != 0 ) + { + if( ( new->ca = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ) ) == NULL ) + goto error; + + mbedtls_x509_crt_init( new->ca ); + + if( mbedtls_x509_crt_parse_file( new->ca, ca_file ) != 0 ) + goto error; + } + + if( strcmp( crl_file, "-" ) != 0 ) + { + if( ( new->crl = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ) ) == NULL ) + goto error; + + mbedtls_x509_crl_init( new->crl ); + + if( mbedtls_x509_crl_parse_file( new->crl, crl_file ) != 0 ) + goto error; + } + + if( strcmp( auth_str, "-" ) != 0 ) + { + if( ( new->authmode = get_auth_mode( auth_str ) ) < 0 ) + goto error; + } + else + new->authmode = DFL_AUTH_MODE; + + new->next = cur; + cur = new; + } + + return( cur ); + +error: + sni_free( new ); + sni_free( cur ); + return( NULL ); +} + +/* + * SNI callback. + */ +int sni_callback( void *p_info, mbedtls_ssl_context *ssl, + const unsigned char *name, size_t name_len ) +{ + const sni_entry *cur = (const sni_entry *) p_info; + + while( cur != NULL ) + { + if( name_len == strlen( cur->name ) && + memcmp( name, cur->name, name_len ) == 0 ) + { + if( cur->ca != NULL ) + mbedtls_ssl_set_hs_ca_chain( ssl, cur->ca, cur->crl ); + + if( cur->authmode != DFL_AUTH_MODE ) + mbedtls_ssl_set_hs_authmode( ssl, cur->authmode ); + + return( mbedtls_ssl_set_hs_own_cert( ssl, cur->cert, cur->key ) ); + } + + cur = cur->next; + } + + return( -1 ); +} + +#endif /* SNI_OPTION */ + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + +#define HEX2NUM( c ) \ + if( c >= '0' && c <= '9' ) \ + c -= '0'; \ + else if( c >= 'a' && c <= 'f' ) \ + c -= 'a' - 10; \ + else if( c >= 'A' && c <= 'F' ) \ + c -= 'A' - 10; \ + else \ + return( -1 ); + +/* + * Convert a hex string to bytes. + * Return 0 on success, -1 on error. + */ +int unhexify( unsigned char *output, const char *input, size_t *olen ) +{ + unsigned char c; + size_t j; + + *olen = strlen( input ); + if( *olen % 2 != 0 || *olen / 2 > MBEDTLS_PSK_MAX_LEN ) + return( -1 ); + *olen /= 2; + + for( j = 0; j < *olen * 2; j += 2 ) + { + c = input[j]; + HEX2NUM( c ); + output[ j / 2 ] = c << 4; + + c = input[j + 1]; + HEX2NUM( c ); + output[ j / 2 ] |= c; + } + + return( 0 ); +} + +typedef struct _psk_entry psk_entry; + +struct _psk_entry +{ + const char *name; + size_t key_len; + unsigned char key[MBEDTLS_PSK_MAX_LEN]; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_key_handle_t slot; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + psk_entry *next; +}; + +/* + * Free a list of psk_entry's + */ +int psk_free( psk_entry *head ) +{ + psk_entry *next; + + while( head != NULL ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; + psa_key_handle_t const slot = head->slot; + + if( slot != 0 ) + { + status = psa_destroy_key( slot ); + if( status != PSA_SUCCESS ) + return( status ); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + next = head->next; + mbedtls_free( head ); + head = next; + } + + return( 0 ); +} + +/* + * Parse a string of pairs name1,key1[,name2,key2[,...]] + * into a usable psk_entry list. + * + * Modifies the input string! This is not production quality! + */ +psk_entry *psk_parse( char *psk_string ) +{ + psk_entry *cur = NULL, *new = NULL; + char *p = psk_string; + char *end = p; + char *key_hex; + + while( *end != '\0' ) + ++end; + *end = ','; + + while( p <= end ) + { + if( ( new = mbedtls_calloc( 1, sizeof( psk_entry ) ) ) == NULL ) + goto error; + + memset( new, 0, sizeof( psk_entry ) ); + + GET_ITEM( new->name ); + GET_ITEM( key_hex ); + + if( unhexify( new->key, key_hex, &new->key_len ) != 0 ) + goto error; + + new->next = cur; + cur = new; + } + + return( cur ); + +error: + psk_free( new ); + psk_free( cur ); + return( 0 ); +} + +/* + * PSK callback + */ +int psk_callback( void *p_info, mbedtls_ssl_context *ssl, + const unsigned char *name, size_t name_len ) +{ + psk_entry *cur = (psk_entry *) p_info; + + while( cur != NULL ) + { + if( name_len == strlen( cur->name ) && + memcmp( name, cur->name, name_len ) == 0 ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( cur->slot != 0 ) + return( mbedtls_ssl_set_hs_psk_opaque( ssl, cur->slot ) ); + else +#endif + return( mbedtls_ssl_set_hs_psk( ssl, cur->key, cur->key_len ) ); + } + + cur = cur->next; + } + + return( -1 ); +} +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +static mbedtls_net_context listen_fd, client_fd; + +/* Interruption handler to ensure clean exit (for valgrind testing) */ +#if !defined(_WIN32) +static int received_sigterm = 0; +void term_handler( int sig ) +{ + ((void) sig); + received_sigterm = 1; + mbedtls_net_free( &listen_fd ); /* causes mbedtls_net_accept() to abort */ + mbedtls_net_free( &client_fd ); /* causes net_read() to abort */ +} +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +static int ssl_sig_hashes_for_test[] = { +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif +#if defined(MBEDTLS_SHA1_C) + /* Allow SHA-1 as we use it extensively in tests. */ + MBEDTLS_MD_SHA1, +#endif + MBEDTLS_MD_NONE +}; +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/** Return true if \p ret is a status code indicating that there is an + * operation in progress on an SSL connection, and false if it indicates + * success or a fatal error. + * + * The possible operations in progress are: + * + * - A read, when the SSL input buffer does not contain a full message. + * - A write, when the SSL output buffer contains some data that has not + * been sent over the network yet. + * - An asynchronous callback that has not completed yet. */ +static int mbedtls_status_is_ssl_in_progress( int ret ) +{ + return( ret == MBEDTLS_ERR_SSL_WANT_READ || + ret == MBEDTLS_ERR_SSL_WANT_WRITE || + ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); +} + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) +typedef struct +{ + mbedtls_x509_crt *cert; /*!< Certificate corresponding to the key */ + mbedtls_pk_context *pk; /*!< Private key */ + unsigned delay; /*!< Number of resume steps to go through */ + unsigned pk_owned : 1; /*!< Whether to free the pk object on exit */ +} ssl_async_key_slot_t; + +typedef enum { + SSL_ASYNC_INJECT_ERROR_NONE = 0, /*!< Let the callbacks succeed */ + SSL_ASYNC_INJECT_ERROR_START, /*!< Inject error during start */ + SSL_ASYNC_INJECT_ERROR_CANCEL, /*!< Close the connection after async start */ + SSL_ASYNC_INJECT_ERROR_RESUME, /*!< Inject error during resume */ +#define SSL_ASYNC_INJECT_ERROR_MAX SSL_ASYNC_INJECT_ERROR_RESUME +} ssl_async_inject_error_t; + +typedef struct +{ + ssl_async_key_slot_t slots[4]; /* key, key2, sni1, sni2 */ + size_t slots_used; + ssl_async_inject_error_t inject_error; + int (*f_rng)(void *, unsigned char *, size_t); + void *p_rng; +} ssl_async_key_context_t; + +int ssl_async_set_key( ssl_async_key_context_t *ctx, + mbedtls_x509_crt *cert, + mbedtls_pk_context *pk, + int pk_take_ownership, + unsigned delay ) +{ + if( ctx->slots_used >= sizeof( ctx->slots ) / sizeof( *ctx->slots ) ) + return( -1 ); + ctx->slots[ctx->slots_used].cert = cert; + ctx->slots[ctx->slots_used].pk = pk; + ctx->slots[ctx->slots_used].delay = delay; + ctx->slots[ctx->slots_used].pk_owned = pk_take_ownership; + ++ctx->slots_used; + return( 0 ); +} + +#define SSL_ASYNC_INPUT_MAX_SIZE 512 + +typedef enum +{ + ASYNC_OP_SIGN, + ASYNC_OP_DECRYPT, +} ssl_async_operation_type_t; +/* Note that the enum above and the array below need to be kept in sync! + * `ssl_async_operation_names[op]` is the name of op for each value `op` + * of type `ssl_async_operation_type_t`. */ +static const char *const ssl_async_operation_names[] = +{ + "sign", + "decrypt", +}; + +typedef struct +{ + unsigned slot; + ssl_async_operation_type_t operation_type; + mbedtls_md_type_t md_alg; + unsigned char input[SSL_ASYNC_INPUT_MAX_SIZE]; + size_t input_len; + unsigned remaining_delay; +} ssl_async_operation_context_t; + +static int ssl_async_start( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + ssl_async_operation_type_t op_type, + mbedtls_md_type_t md_alg, + const unsigned char *input, + size_t input_len ) +{ + ssl_async_key_context_t *config_data = + mbedtls_ssl_conf_get_async_config_data( ssl->conf ); + unsigned slot; + ssl_async_operation_context_t *ctx = NULL; + const char *op_name = ssl_async_operation_names[op_type]; + + { + char dn[100]; + if( mbedtls_x509_dn_gets( dn, sizeof( dn ), &cert->subject ) > 0 ) + mbedtls_printf( "Async %s callback: looking for DN=%s\n", + op_name, dn ); + } + + /* Look for a private key that matches the public key in cert. + * Since this test code has the private key inside Mbed TLS, + * we call mbedtls_pk_check_pair to match a private key with the + * public key. */ + for( slot = 0; slot < config_data->slots_used; slot++ ) + { + if( mbedtls_pk_check_pair( &cert->pk, + config_data->slots[slot].pk ) == 0 ) + break; + } + if( slot == config_data->slots_used ) + { + mbedtls_printf( "Async %s callback: no key matches this certificate.\n", + op_name ); + return( MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH ); + } + mbedtls_printf( "Async %s callback: using key slot %u, delay=%u.\n", + op_name, slot, config_data->slots[slot].delay ); + + if( config_data->inject_error == SSL_ASYNC_INJECT_ERROR_START ) + { + mbedtls_printf( "Async %s callback: injected error\n", op_name ); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + if( input_len > SSL_ASYNC_INPUT_MAX_SIZE ) + return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA ); + + ctx = mbedtls_calloc( 1, sizeof( *ctx ) ); + if( ctx == NULL ) + return( MBEDTLS_ERR_SSL_ALLOC_FAILED ); + ctx->slot = slot; + ctx->operation_type = op_type; + ctx->md_alg = md_alg; + memcpy( ctx->input, input, input_len ); + ctx->input_len = input_len; + ctx->remaining_delay = config_data->slots[slot].delay; + mbedtls_ssl_set_async_operation_data( ssl, ctx ); + + if( ctx->remaining_delay == 0 ) + return( 0 ); + else + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); +} + +static int ssl_async_sign( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + mbedtls_md_type_t md_alg, + const unsigned char *hash, + size_t hash_len ) +{ + return( ssl_async_start( ssl, cert, + ASYNC_OP_SIGN, md_alg, + hash, hash_len ) ); +} + +static int ssl_async_decrypt( mbedtls_ssl_context *ssl, + mbedtls_x509_crt *cert, + const unsigned char *input, + size_t input_len ) +{ + return( ssl_async_start( ssl, cert, + ASYNC_OP_DECRYPT, MBEDTLS_MD_NONE, + input, input_len ) ); +} + +static int ssl_async_resume( mbedtls_ssl_context *ssl, + unsigned char *output, + size_t *output_len, + size_t output_size ) +{ + ssl_async_operation_context_t *ctx = mbedtls_ssl_get_async_operation_data( ssl ); + ssl_async_key_context_t *config_data = + mbedtls_ssl_conf_get_async_config_data( ssl->conf ); + ssl_async_key_slot_t *key_slot = &config_data->slots[ctx->slot]; + int ret; + const char *op_name; + + if( ctx->remaining_delay > 0 ) + { + --ctx->remaining_delay; + mbedtls_printf( "Async resume (slot %u): call %u more times.\n", + ctx->slot, ctx->remaining_delay ); + return( MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS ); + } + + switch( ctx->operation_type ) + { + case ASYNC_OP_DECRYPT: + ret = mbedtls_pk_decrypt( key_slot->pk, + ctx->input, ctx->input_len, + output, output_len, output_size, + config_data->f_rng, config_data->p_rng ); + break; + case ASYNC_OP_SIGN: + ret = mbedtls_pk_sign( key_slot->pk, + ctx->md_alg, + ctx->input, ctx->input_len, + output, output_len, + config_data->f_rng, config_data->p_rng ); + break; + default: + mbedtls_printf( "Async resume (slot %u): unknown operation type %ld. This shouldn't happen.\n", + ctx->slot, (long) ctx->operation_type ); + mbedtls_free( ctx ); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + break; + } + + op_name = ssl_async_operation_names[ctx->operation_type]; + + if( config_data->inject_error == SSL_ASYNC_INJECT_ERROR_RESUME ) + { + mbedtls_printf( "Async resume callback: %s done but injected error\n", + op_name ); + mbedtls_free( ctx ); + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + mbedtls_printf( "Async resume (slot %u): %s done, status=%d.\n", + ctx->slot, op_name, ret ); + mbedtls_free( ctx ); + return( ret ); +} + +static void ssl_async_cancel( mbedtls_ssl_context *ssl ) +{ + ssl_async_operation_context_t *ctx = mbedtls_ssl_get_async_operation_data( ssl ); + mbedtls_printf( "Async cancel callback.\n" ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + +/* + * Wait for an event from the underlying transport or the timer + * (Used in event-driven IO mode). + */ +#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_USE_PSA_CRYPTO) +static psa_status_t psa_setup_psk_key_slot( psa_key_handle_t slot, + psa_algorithm_t alg, + unsigned char *psk, + size_t psk_len ) +{ + psa_status_t status; + psa_key_policy_t policy; + + policy = psa_key_policy_init(); + psa_key_policy_set_usage( &policy, PSA_KEY_USAGE_DERIVE, alg ); + + status = psa_set_key_policy( slot, &policy ); + if( status != PSA_SUCCESS ) + { + fprintf( stderr, "POLICY\n" ); + return( status ); + } + + status = psa_import_key( slot, PSA_KEY_TYPE_DERIVE, psk, psk_len ); + if( status != PSA_SUCCESS ) + { + fprintf( stderr, "IMPORT\n" ); + return( status ); + } + + return( PSA_SUCCESS ); +} +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + +int main( int argc, char *argv[] ) +{ + int ret = 0, len, written, frags, exchanges_left; + int version_suites[4][2]; + unsigned char* buf = 0; +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_algorithm_t alg = 0; + psa_key_handle_t psk_slot = 0; +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + unsigned char psk[MBEDTLS_PSK_MAX_LEN]; + size_t psk_len = 0; + psk_entry *psk_info = NULL; +#endif + const char *pers = "ssl_server2"; + unsigned char client_ip[16] = { 0 }; + size_t cliip_len; +#if defined(MBEDTLS_SSL_COOKIE_C) + mbedtls_ssl_cookie_ctx cookie_ctx; +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_profile crt_profile_for_test = mbedtls_x509_crt_profile_default; +#endif + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; +#if defined(MBEDTLS_TIMING_C) + mbedtls_timing_delay_context timer; +#endif +#if defined(MBEDTLS_SSL_RENEGOTIATION) + unsigned char renego_period[8] = { 0 }; +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt srvcert; + mbedtls_pk_context pkey; + mbedtls_x509_crt srvcert2; + mbedtls_pk_context pkey2; + int key_cert_init = 0, key_cert_init2 = 0; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + ssl_async_key_context_t ssl_async_keys; +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + mbedtls_dhm_context dhm; +#endif +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_context cache; +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_ticket_context ticket_ctx; +#endif +#if defined(SNI_OPTION) + sni_entry *sni_info = NULL; +#endif +#if defined(MBEDTLS_ECP_C) + mbedtls_ecp_group_id curve_list[CURVE_LIST_SIZE]; + const mbedtls_ecp_curve_info * curve_cur; +#endif +#if defined(MBEDTLS_SSL_ALPN) + const char *alpn_list[ALPN_LIST_SIZE]; +#endif +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + unsigned char alloc_buf[MEMORY_HEAP_SIZE]; +#endif + + int i; + char *p, *q; + const int *list; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + psa_status_t status; +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) + mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) ); +#endif + + /* + * Make sure memory references are valid in case we exit early. + */ + mbedtls_net_init( &client_fd ); + mbedtls_net_init( &listen_fd ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + mbedtls_ctr_drbg_init( &ctr_drbg ); +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_init( &cacert ); + mbedtls_x509_crt_init( &srvcert ); + mbedtls_pk_init( &pkey ); + mbedtls_x509_crt_init( &srvcert2 ); + mbedtls_pk_init( &pkey2 ); +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + memset( &ssl_async_keys, 0, sizeof( ssl_async_keys ) ); +#endif +#endif +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + mbedtls_dhm_init( &dhm ); +#endif +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_init( &cache ); +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_ticket_init( &ticket_ctx ); +#endif +#if defined(MBEDTLS_SSL_ALPN) + memset( (void *) alpn_list, 0, sizeof( alpn_list ) ); +#endif +#if defined(MBEDTLS_SSL_COOKIE_C) + mbedtls_ssl_cookie_init( &cookie_ctx ); +#endif + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + status = psa_crypto_init(); + if( status != PSA_SUCCESS ) + { + mbedtls_fprintf( stderr, "Failed to initialize PSA Crypto implementation: %d\n", + (int) status ); + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } +#endif + +#if !defined(_WIN32) + /* Abort cleanly on SIGTERM and SIGINT */ + signal( SIGTERM, term_handler ); + signal( SIGINT, term_handler ); +#endif + + if( argc == 0 ) + { + usage: + if( ret == 0 ) + ret = 1; + + mbedtls_printf( USAGE ); + + list = mbedtls_ssl_list_ciphersuites(); + while( *list ) + { + mbedtls_printf(" %-42s", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + if( !*list ) + break; + mbedtls_printf(" %s\n", mbedtls_ssl_get_ciphersuite_name( *list ) ); + list++; + } + mbedtls_printf("\n"); + goto exit; + } + + opt.buffer_size = DFL_IO_BUF_LEN; + opt.server_addr = DFL_SERVER_ADDR; + opt.server_port = DFL_SERVER_PORT; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.event = DFL_EVENT; + opt.response_size = DFL_RESPONSE_SIZE; + opt.nbio = DFL_NBIO; + opt.read_timeout = DFL_READ_TIMEOUT; + opt.ca_file = DFL_CA_FILE; + opt.ca_path = DFL_CA_PATH; + opt.crt_file = DFL_CRT_FILE; + opt.key_file = DFL_KEY_FILE; + opt.crt_file2 = DFL_CRT_FILE2; + opt.key_file2 = DFL_KEY_FILE2; + opt.async_operations = DFL_ASYNC_OPERATIONS; + opt.async_private_delay1 = DFL_ASYNC_PRIVATE_DELAY1; + opt.async_private_delay2 = DFL_ASYNC_PRIVATE_DELAY2; + opt.async_private_error = DFL_ASYNC_PRIVATE_ERROR; + opt.psk = DFL_PSK; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + opt.psk_opaque = DFL_PSK_OPAQUE; + opt.psk_list_opaque = DFL_PSK_LIST_OPAQUE; +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + opt.ca_callback = DFL_CA_CALLBACK; +#endif + opt.psk_identity = DFL_PSK_IDENTITY; + opt.psk_list = DFL_PSK_LIST; + opt.ecjpake_pw = DFL_ECJPAKE_PW; + opt.force_ciphersuite[0]= DFL_FORCE_CIPHER; + opt.version_suites = DFL_VERSION_SUITES; + opt.renegotiation = DFL_RENEGOTIATION; + opt.allow_legacy = DFL_ALLOW_LEGACY; + opt.renegotiate = DFL_RENEGOTIATE; + opt.renego_delay = DFL_RENEGO_DELAY; + opt.renego_period = DFL_RENEGO_PERIOD; + opt.exchanges = DFL_EXCHANGES; + opt.min_version = DFL_MIN_VERSION; + opt.max_version = DFL_MAX_VERSION; + opt.arc4 = DFL_ARC4; + opt.allow_sha1 = DFL_SHA1; + opt.auth_mode = DFL_AUTH_MODE; + opt.cert_req_ca_list = DFL_CERT_REQ_CA_LIST; + opt.mfl_code = DFL_MFL_CODE; + opt.trunc_hmac = DFL_TRUNC_HMAC; + opt.tickets = DFL_TICKETS; + opt.ticket_timeout = DFL_TICKET_TIMEOUT; + opt.cache_max = DFL_CACHE_MAX; + opt.cache_timeout = DFL_CACHE_TIMEOUT; + opt.sni = DFL_SNI; + opt.alpn_string = DFL_ALPN_STRING; + opt.curves = DFL_CURVES; + opt.dhm_file = DFL_DHM_FILE; + opt.transport = DFL_TRANSPORT; + opt.cookies = DFL_COOKIES; + opt.anti_replay = DFL_ANTI_REPLAY; + opt.hs_to_min = DFL_HS_TO_MIN; + opt.hs_to_max = DFL_HS_TO_MAX; + opt.dtls_mtu = DFL_DTLS_MTU; + opt.dgram_packing = DFL_DGRAM_PACKING; + opt.badmac_limit = DFL_BADMAC_LIMIT; + opt.extended_ms = DFL_EXTENDED_MS; + opt.etm = DFL_ETM; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "server_port" ) == 0 ) + opt.server_port = q; + else if( strcmp( p, "server_addr" ) == 0 ) + opt.server_addr = q; + else if( strcmp( p, "dtls" ) == 0 ) + { + int t = atoi( q ); + if( t == 0 ) + opt.transport = MBEDTLS_SSL_TRANSPORT_STREAM; + else if( t == 1 ) + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + else + goto usage; + } + 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, "nbio" ) == 0 ) + { + opt.nbio = atoi( q ); + if( opt.nbio < 0 || opt.nbio > 2 ) + goto usage; + } + else if( strcmp( p, "event" ) == 0 ) + { + opt.event = atoi( q ); + if( opt.event < 0 || opt.event > 2 ) + goto usage; + } + else if( strcmp( p, "read_timeout" ) == 0 ) + opt.read_timeout = atoi( q ); + else if( strcmp( p, "buffer_size" ) == 0 ) + { + opt.buffer_size = atoi( q ); + if( opt.buffer_size < 1 || opt.buffer_size > MBEDTLS_SSL_MAX_CONTENT_LEN + 1 ) + goto usage; + } + else if( strcmp( p, "response_size" ) == 0 ) + { + opt.response_size = atoi( q ); + if( opt.response_size < 0 || opt.response_size > MBEDTLS_SSL_MAX_CONTENT_LEN ) + goto usage; + if( opt.buffer_size < opt.response_size ) + opt.buffer_size = opt.response_size; + } + else if( strcmp( p, "ca_file" ) == 0 ) + opt.ca_file = q; + else if( strcmp( p, "ca_path" ) == 0 ) + opt.ca_path = 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, "crt_file2" ) == 0 ) + opt.crt_file2 = q; + else if( strcmp( p, "key_file2" ) == 0 ) + opt.key_file2 = q; + else if( strcmp( p, "dhm_file" ) == 0 ) + opt.dhm_file = q; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + else if( strcmp( p, "async_operations" ) == 0 ) + opt.async_operations = q; + else if( strcmp( p, "async_private_delay1" ) == 0 ) + opt.async_private_delay1 = atoi( q ); + else if( strcmp( p, "async_private_delay2" ) == 0 ) + opt.async_private_delay2 = atoi( q ); + else if( strcmp( p, "async_private_error" ) == 0 ) + { + int n = atoi( q ); + if( n < -SSL_ASYNC_INJECT_ERROR_MAX || + n > SSL_ASYNC_INJECT_ERROR_MAX ) + { + ret = 2; + goto usage; + } + opt.async_private_error = n; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + else if( strcmp( p, "psk" ) == 0 ) + opt.psk = q; +#if defined(MBEDTLS_USE_PSA_CRYPTO) + else if( strcmp( p, "psk_opaque" ) == 0 ) + opt.psk_opaque = atoi( q ); + else if( strcmp( p, "psk_list_opaque" ) == 0 ) + opt.psk_list_opaque = atoi( q ); +#endif +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + else if( strcmp( p, "ca_callback" ) == 0) + opt.ca_callback = atoi( q ); +#endif + else if( strcmp( p, "psk_identity" ) == 0 ) + opt.psk_identity = q; + else if( strcmp( p, "psk_list" ) == 0 ) + opt.psk_list = q; + else if( strcmp( p, "ecjpake_pw" ) == 0 ) + opt.ecjpake_pw = q; + else if( strcmp( p, "force_ciphersuite" ) == 0 ) + { + opt.force_ciphersuite[0] = mbedtls_ssl_get_ciphersuite_id( q ); + + if( opt.force_ciphersuite[0] == 0 ) + { + ret = 2; + goto usage; + } + opt.force_ciphersuite[1] = 0; + } + else if( strcmp( p, "curves" ) == 0 ) + opt.curves = q; + else if( strcmp( p, "version_suites" ) == 0 ) + opt.version_suites = q; + else if( strcmp( p, "renegotiation" ) == 0 ) + { + opt.renegotiation = (atoi( q )) ? + MBEDTLS_SSL_RENEGOTIATION_ENABLED : + MBEDTLS_SSL_RENEGOTIATION_DISABLED; + } + else if( strcmp( p, "allow_legacy" ) == 0 ) + { + switch( atoi( q ) ) + { + case -1: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_BREAK_HANDSHAKE; + break; + case 0: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_NO_RENEGOTIATION; + break; + case 1: + opt.allow_legacy = MBEDTLS_SSL_LEGACY_ALLOW_RENEGOTIATION; + break; + default: goto usage; + } + } + else if( strcmp( p, "renegotiate" ) == 0 ) + { + opt.renegotiate = atoi( q ); + if( opt.renegotiate < 0 || opt.renegotiate > 1 ) + goto usage; + } + else if( strcmp( p, "renego_delay" ) == 0 ) + { + opt.renego_delay = atoi( q ); + } + else if( strcmp( p, "renego_period" ) == 0 ) + { +#if defined(_MSC_VER) + opt.renego_period = _strtoui64( q, NULL, 10 ); +#else + if( sscanf( q, "%" SCNu64, &opt.renego_period ) != 1 ) + goto usage; +#endif /* _MSC_VER */ + if( opt.renego_period < 2 ) + goto usage; + } + else if( strcmp( p, "exchanges" ) == 0 ) + { + opt.exchanges = atoi( q ); + if( opt.exchanges < 0 ) + goto usage; + } + else if( strcmp( p, "min_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_0; + else if( strcmp( q, "tls1" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_1; + else if( strcmp( q, "tls1_1" ) == 0 || + strcmp( q, "dtls1" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + else if( strcmp( q, "tls1_2" ) == 0 || + strcmp( q, "dtls1_2" ) == 0 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + else + goto usage; + } + else if( strcmp( p, "max_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_0; + else if( strcmp( q, "tls1" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_1; + else if( strcmp( q, "tls1_1" ) == 0 || + strcmp( q, "dtls1" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + else if( strcmp( q, "tls1_2" ) == 0 || + strcmp( q, "dtls1_2" ) == 0 ) + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + else + goto usage; + } + else if( strcmp( p, "arc4" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.arc4 = MBEDTLS_SSL_ARC4_DISABLED; break; + case 1: opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "allow_sha1" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.allow_sha1 = 0; break; + case 1: opt.allow_sha1 = 1; break; + default: goto usage; + } + } + else if( strcmp( p, "force_version" ) == 0 ) + { + if( strcmp( q, "ssl3" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_0; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_0; + } + else if( strcmp( q, "tls1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_1; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_1; + } + else if( strcmp( q, "tls1_1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + else if( strcmp( q, "tls1_2" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + } + else if( strcmp( q, "dtls1" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_2; + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + } + else if( strcmp( q, "dtls1_2" ) == 0 ) + { + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.max_version = MBEDTLS_SSL_MINOR_VERSION_3; + opt.transport = MBEDTLS_SSL_TRANSPORT_DATAGRAM; + } + else + goto usage; + } + else if( strcmp( p, "auth_mode" ) == 0 ) + { + if( ( opt.auth_mode = get_auth_mode( q ) ) < 0 ) + goto usage; + } + else if( strcmp( p, "cert_req_ca_list" ) == 0 ) + { + opt.cert_req_ca_list = atoi( q ); + if( opt.cert_req_ca_list < 0 || opt.cert_req_ca_list > 1 ) + goto usage; + } + else if( strcmp( p, "max_frag_len" ) == 0 ) + { + if( strcmp( q, "512" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_512; + else if( strcmp( q, "1024" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_1024; + else if( strcmp( q, "2048" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_2048; + else if( strcmp( q, "4096" ) == 0 ) + opt.mfl_code = MBEDTLS_SSL_MAX_FRAG_LEN_4096; + else + goto usage; + } + else if( strcmp( p, "alpn" ) == 0 ) + { + opt.alpn_string = q; + } + else if( strcmp( p, "trunc_hmac" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_DISABLED; break; + case 1: opt.trunc_hmac = MBEDTLS_SSL_TRUNC_HMAC_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "extended_ms" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: + opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_DISABLED; + break; + case 1: + opt.extended_ms = MBEDTLS_SSL_EXTENDED_MS_ENABLED; + break; + default: goto usage; + } + } + else if( strcmp( p, "etm" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.etm = MBEDTLS_SSL_ETM_DISABLED; break; + case 1: opt.etm = MBEDTLS_SSL_ETM_ENABLED; break; + default: goto usage; + } + } + else if( strcmp( p, "tickets" ) == 0 ) + { + opt.tickets = atoi( q ); + if( opt.tickets < 0 || opt.tickets > 1 ) + goto usage; + } + else if( strcmp( p, "ticket_timeout" ) == 0 ) + { + opt.ticket_timeout = atoi( q ); + if( opt.ticket_timeout < 0 ) + goto usage; + } + else if( strcmp( p, "cache_max" ) == 0 ) + { + opt.cache_max = atoi( q ); + if( opt.cache_max < 0 ) + goto usage; + } + else if( strcmp( p, "cache_timeout" ) == 0 ) + { + opt.cache_timeout = atoi( q ); + if( opt.cache_timeout < 0 ) + goto usage; + } + else if( strcmp( p, "cookies" ) == 0 ) + { + opt.cookies = atoi( q ); + if( opt.cookies < -1 || opt.cookies > 1) + goto usage; + } + else if( strcmp( p, "anti_replay" ) == 0 ) + { + opt.anti_replay = atoi( q ); + if( opt.anti_replay < 0 || opt.anti_replay > 1) + goto usage; + } + else if( strcmp( p, "badmac_limit" ) == 0 ) + { + opt.badmac_limit = atoi( q ); + if( opt.badmac_limit < 0 ) + goto usage; + } + else if( strcmp( p, "hs_timeout" ) == 0 ) + { + if( ( p = strchr( q, '-' ) ) == NULL ) + goto usage; + *p++ = '\0'; + opt.hs_to_min = atoi( q ); + opt.hs_to_max = atoi( p ); + if( opt.hs_to_min == 0 || opt.hs_to_max < opt.hs_to_min ) + goto usage; + } + else if( strcmp( p, "mtu" ) == 0 ) + { + opt.dtls_mtu = atoi( q ); + if( opt.dtls_mtu < 0 ) + goto usage; + } + else if( strcmp( p, "dgram_packing" ) == 0 ) + { + opt.dgram_packing = atoi( q ); + if( opt.dgram_packing != 0 && + opt.dgram_packing != 1 ) + { + goto usage; + } + } + else if( strcmp( p, "sni" ) == 0 ) + { + opt.sni = q; + } + else if( strcmp( p, "query_config" ) == 0 ) + { + return query_config( q ); + } + else + goto usage; + } + + /* Event-driven IO is incompatible with the above custom + * receive and send functions, as the polling builds on + * refers to the underlying net_context. */ + if( opt.event == 1 && opt.nbio != 1 ) + { + mbedtls_printf( "Warning: event-driven IO mandates nbio=1 - overwrite\n" ); + opt.nbio = 1; + } + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( opt.debug_level ); +#endif + buf = mbedtls_calloc( 1, opt.buffer_size + 1 ); + if( buf == NULL ) + { + mbedtls_printf( "Could not allocate %u bytes\n", opt.buffer_size ); + ret = 3; + goto exit; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_opaque != 0 ) + { + if( strlen( opt.psk ) == 0 ) + { + mbedtls_printf( "psk_opaque set but no psk to be imported specified.\n" ); + ret = 2; + goto usage; + } + + if( opt.force_ciphersuite[0] <= 0 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + } + + if( opt.psk_list_opaque != 0 ) + { + if( opt.psk_list == NULL ) + { + mbedtls_printf( "psk_slot set but no psk to be imported specified.\n" ); + ret = 2; + goto usage; + } + + if( opt.force_ciphersuite[0] <= 0 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + if( opt.force_ciphersuite[0] > 0 ) + { + const mbedtls_ssl_ciphersuite_t *ciphersuite_info; + ciphersuite_info = + mbedtls_ssl_ciphersuite_from_id( opt.force_ciphersuite[0] ); + + if( opt.max_version != -1 && + ciphersuite_info->min_minor_ver > opt.max_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + if( opt.min_version != -1 && + ciphersuite_info->max_minor_ver < opt.min_version ) + { + mbedtls_printf( "forced ciphersuite not allowed with this protocol version\n" ); + ret = 2; + goto usage; + } + + /* If we select a version that's not supported by + * this suite, then there will be no common ciphersuite... */ + if( opt.max_version == -1 || + opt.max_version > ciphersuite_info->max_minor_ver ) + { + opt.max_version = ciphersuite_info->max_minor_ver; + } + if( opt.min_version < ciphersuite_info->min_minor_ver ) + { + opt.min_version = ciphersuite_info->min_minor_ver; + /* DTLS starts with TLS 1.1 */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM && + opt.min_version < MBEDTLS_SSL_MINOR_VERSION_2 ) + opt.min_version = MBEDTLS_SSL_MINOR_VERSION_2; + } + + /* Enable RC4 if needed and not explicitly disabled */ + if( ciphersuite_info->cipher == MBEDTLS_CIPHER_ARC4_128 ) + { + if( opt.arc4 == MBEDTLS_SSL_ARC4_DISABLED ) + { + mbedtls_printf("forced RC4 ciphersuite with RC4 disabled\n"); + ret = 2; + goto usage; + } + + opt.arc4 = MBEDTLS_SSL_ARC4_ENABLED; + } + +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_opaque != 0 || opt.psk_list_opaque != 0 ) + { + /* Ensure that the chosen ciphersuite is PSK-only; we must know + * the ciphersuite in advance to set the correct policy for the + * PSK key slot. This limitation might go away in the future. */ + if( ciphersuite_info->key_exchange != MBEDTLS_KEY_EXCHANGE_PSK || + opt.min_version != MBEDTLS_SSL_MINOR_VERSION_3 ) + { + mbedtls_printf( "opaque PSKs are only supported in conjunction with forcing TLS 1.2 and a PSK-only ciphersuite through the 'force_ciphersuite' option.\n" ); + ret = 2; + goto usage; + } + + /* Determine KDF algorithm the opaque PSK will be used in. */ +#if defined(MBEDTLS_SHA512_C) + if( ciphersuite_info->mac == MBEDTLS_MD_SHA384 ) + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_384); + else +#endif /* MBEDTLS_SHA512_C */ + alg = PSA_ALG_TLS12_PSK_TO_MS(PSA_ALG_SHA_256); + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + } + + if( opt.version_suites != NULL ) + { + const char *name[4] = { 0 }; + + /* Parse 4-element coma-separated list */ + for( i = 0, p = (char *) opt.version_suites; + i < 4 && *p != '\0'; + i++ ) + { + name[i] = p; + + /* Terminate the current string and move on to next one */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + } + + if( i != 4 ) + { + mbedtls_printf( "too few values for version_suites\n" ); + ret = 1; + goto exit; + } + + memset( version_suites, 0, sizeof( version_suites ) ); + + /* Get the suites identifiers from their name */ + for( i = 0; i < 4; i++ ) + { + version_suites[i][0] = mbedtls_ssl_get_ciphersuite_id( name[i] ); + + if( version_suites[i][0] == 0 ) + { + mbedtls_printf( "unknown ciphersuite: '%s'\n", name[i] ); + ret = 2; + goto usage; + } + } + } + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + /* + * Unhexify the pre-shared key and parse the list if any given + */ + if( unhexify( psk, opt.psk, &psk_len ) != 0 ) + { + mbedtls_printf( "pre-shared key not valid hex\n" ); + goto exit; + } + + if( opt.psk_list != NULL ) + { + if( ( psk_info = psk_parse( opt.psk_list ) ) == NULL ) + { + mbedtls_printf( "psk_list invalid" ); + goto exit; + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED */ + +#if defined(MBEDTLS_ECP_C) + if( opt.curves != NULL ) + { + p = (char *) opt.curves; + i = 0; + + if( strcmp( p, "none" ) == 0 ) + { + curve_list[0] = MBEDTLS_ECP_DP_NONE; + } + else if( strcmp( p, "default" ) != 0 ) + { + /* Leave room for a final NULL in curve list */ + while( i < CURVE_LIST_SIZE - 1 && *p != '\0' ) + { + q = p; + + /* Terminate the current string */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + + if( ( curve_cur = mbedtls_ecp_curve_info_from_name( q ) ) != NULL ) + { + curve_list[i++] = curve_cur->grp_id; + } + else + { + mbedtls_printf( "unknown curve %s\n", q ); + mbedtls_printf( "supported curves: " ); + for( curve_cur = mbedtls_ecp_curve_list(); + curve_cur->grp_id != MBEDTLS_ECP_DP_NONE; + curve_cur++ ) + { + mbedtls_printf( "%s ", curve_cur->name ); + } + mbedtls_printf( "\n" ); + goto exit; + } + } + + mbedtls_printf("Number of curves: %d\n", i ); + + if( i == CURVE_LIST_SIZE - 1 && *p != '\0' ) + { + mbedtls_printf( "curves list too long, maximum %d", + CURVE_LIST_SIZE - 1 ); + goto exit; + } + + curve_list[i] = MBEDTLS_ECP_DP_NONE; + } + } +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + { + p = (char *) opt.alpn_string; + i = 0; + + /* Leave room for a final NULL in alpn_list */ + while( i < ALPN_LIST_SIZE - 1 && *p != '\0' ) + { + alpn_list[i++] = p; + + /* Terminate the current string and move on to next one */ + while( *p != ',' && *p != '\0' ) + p++; + if( *p == ',' ) + *p++ = '\0'; + } + } +#endif /* MBEDTLS_SSL_ALPN */ + + /* + * 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 -0x%x\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * 1.1. Load the trusted CA + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.ca_path ) ) + if( strcmp( opt.ca_path, "none" ) == 0 ) + ret = 0; + else + ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path ); + else if( strlen( opt.ca_file ) ) + if( strcmp( opt.ca_file, "none" ) == 0 ) + ret = 0; + else + ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ); + else +#endif +#if defined(MBEDTLS_CERTS_C) + for( i = 0; mbedtls_test_cas[i] != NULL; i++ ) + { + ret = mbedtls_x509_crt_parse( &cacert, + (const unsigned char *) mbedtls_test_cas[i], + mbedtls_test_cas_len[i] ); + if( ret != 0 ) + break; + } +#else + { + ret = 1; + mbedtls_printf("MBEDTLS_CERTS_C not defined."); + } +#endif + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + + /* + * 1.2. Load own certificate and private key + */ + mbedtls_printf( " . Loading the server cert. and key..." ); + fflush( stdout ); + +#if defined(MBEDTLS_FS_IO) + if( strlen( opt.crt_file ) && strcmp( opt.crt_file, "none" ) != 0 ) + { + key_cert_init++; + if( ( ret = mbedtls_x509_crt_parse_file( &srvcert, opt.crt_file ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned -0x%x\n\n", + -ret ); + goto exit; + } + } + if( strlen( opt.key_file ) && strcmp( opt.key_file, "none" ) != 0 ) + { + key_cert_init++; + if( ( ret = mbedtls_pk_parse_keyfile( &pkey, opt.key_file, "" ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned -0x%x\n\n", -ret ); + goto exit; + } + } + if( key_cert_init == 1 ) + { + mbedtls_printf( " failed\n ! crt_file without key_file or vice-versa\n\n" ); + goto exit; + } + + if( strlen( opt.crt_file2 ) && strcmp( opt.crt_file2, "none" ) != 0 ) + { + key_cert_init2++; + if( ( ret = mbedtls_x509_crt_parse_file( &srvcert2, opt.crt_file2 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file(2) returned -0x%x\n\n", + -ret ); + goto exit; + } + } + if( strlen( opt.key_file2 ) && strcmp( opt.key_file2, "none" ) != 0 ) + { + key_cert_init2++; + if( ( ret = mbedtls_pk_parse_keyfile( &pkey2, opt.key_file2, "" ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile(2) returned -0x%x\n\n", + -ret ); + goto exit; + } + } + if( key_cert_init2 == 1 ) + { + mbedtls_printf( " failed\n ! crt_file2 without key_file2 or vice-versa\n\n" ); + goto exit; + } +#endif + if( key_cert_init == 0 && + strcmp( opt.crt_file, "none" ) != 0 && + strcmp( opt.key_file, "none" ) != 0 && + key_cert_init2 == 0 && + strcmp( opt.crt_file2, "none" ) != 0 && + strcmp( opt.key_file2, "none" ) != 0 ) + { +#if !defined(MBEDTLS_CERTS_C) + mbedtls_printf( "Not certificated or key provided, and \nMBEDTLS_CERTS_C not defined!\n" ); + goto exit; +#else +#if defined(MBEDTLS_RSA_C) + if( ( ret = mbedtls_x509_crt_parse( &srvcert, + (const unsigned char *) mbedtls_test_srv_crt_rsa, + mbedtls_test_srv_crt_rsa_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse returned -0x%x\n\n", + -ret ); + goto exit; + } + if( ( ret = mbedtls_pk_parse_key( &pkey, + (const unsigned char *) mbedtls_test_srv_key_rsa, + mbedtls_test_srv_key_rsa_len, NULL, 0 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_key returned -0x%x\n\n", + -ret ); + goto exit; + } + key_cert_init = 2; +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) + if( ( ret = mbedtls_x509_crt_parse( &srvcert2, + (const unsigned char *) mbedtls_test_srv_crt_ec, + mbedtls_test_srv_crt_ec_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! x509_crt_parse2 returned -0x%x\n\n", + -ret ); + goto exit; + } + if( ( ret = mbedtls_pk_parse_key( &pkey2, + (const unsigned char *) mbedtls_test_srv_key_ec, + mbedtls_test_srv_key_ec_len, NULL, 0 ) ) != 0 ) + { + mbedtls_printf( " failed\n ! pk_parse_key2 returned -0x%x\n\n", + -ret ); + goto exit; + } + key_cert_init2 = 2; +#endif /* MBEDTLS_ECDSA_C */ +#endif /* MBEDTLS_CERTS_C */ + } + + mbedtls_printf( " ok\n" ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + if( opt.dhm_file != NULL ) + { + mbedtls_printf( " . Loading DHM parameters..." ); + fflush( stdout ); + + if( ( ret = mbedtls_dhm_parse_dhmfile( &dhm, opt.dhm_file ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_dhm_parse_dhmfile returned -0x%04X\n\n", + -ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } +#endif + +#if defined(SNI_OPTION) + if( opt.sni != NULL ) + { + mbedtls_printf( " . Setting up SNI information..." ); + fflush( stdout ); + + if( ( sni_info = sni_parse( opt.sni ) ) == NULL ) + { + mbedtls_printf( " failed\n" ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } +#endif /* SNI_OPTION */ + + /* + * 2. Setup the listening TCP socket + */ + mbedtls_printf( " . Bind on %s://%s:%s/ ...", + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? "tcp" : "udp", + opt.server_addr ? opt.server_addr : "*", + opt.server_port ); + fflush( stdout ); + + if( ( ret = mbedtls_net_bind( &listen_fd, opt.server_addr, opt.server_port, + opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ? + MBEDTLS_NET_PROTO_TCP : MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_bind returned -0x%x\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_SERVER, + opt.transport, + MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_config_defaults returned -0x%x\n\n", -ret ); + goto exit; + } + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* The default algorithms profile disables SHA-1, but our tests still + rely on it heavily. Hence we allow it here. A real-world server + should use the default profile unless there is a good reason not to. */ + if( opt.allow_sha1 > 0 ) + { + crt_profile_for_test.allowed_mds |= MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ); + mbedtls_ssl_conf_cert_profile( &conf, &crt_profile_for_test ); + mbedtls_ssl_conf_sig_hashes( &conf, ssl_sig_hashes_for_test ); + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( opt.auth_mode != DFL_AUTH_MODE ) + mbedtls_ssl_conf_authmode( &conf, opt.auth_mode ); + + if( opt.cert_req_ca_list != DFL_CERT_REQ_CA_LIST ) + mbedtls_ssl_conf_cert_req_ca_list( &conf, opt.cert_req_ca_list ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.hs_to_min != DFL_HS_TO_MIN || opt.hs_to_max != DFL_HS_TO_MAX ) + mbedtls_ssl_conf_handshake_timeout( &conf, opt.hs_to_min, opt.hs_to_max ); + + if( opt.dgram_packing != DFL_DGRAM_PACKING ) + mbedtls_ssl_set_datagram_packing( &ssl, opt.dgram_packing ); +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + if( ( ret = mbedtls_ssl_conf_max_frag_len( &conf, opt.mfl_code ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_max_frag_len returned %d\n\n", ret ); + goto exit; + }; +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC) + if( opt.trunc_hmac != DFL_TRUNC_HMAC ) + mbedtls_ssl_conf_truncated_hmac( &conf, opt.trunc_hmac ); +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) + if( opt.extended_ms != DFL_EXTENDED_MS ) + mbedtls_ssl_conf_extended_master_secret( &conf, opt.extended_ms ); +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) + if( opt.etm != DFL_ETM ) + mbedtls_ssl_conf_encrypt_then_mac( &conf, opt.etm ); +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + if( ( ret = mbedtls_ssl_conf_alpn_protocols( &conf, alpn_list ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_alpn_protocols returned %d\n\n", ret ); + goto exit; + } +#endif + + 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) + if( opt.cache_max != -1 ) + mbedtls_ssl_cache_set_max_entries( &cache, opt.cache_max ); + + if( opt.cache_timeout != -1 ) + mbedtls_ssl_cache_set_timeout( &cache, opt.cache_timeout ); + + mbedtls_ssl_conf_session_cache( &conf, &cache, + mbedtls_ssl_cache_get, + mbedtls_ssl_cache_set ); +#endif + +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + if( opt.tickets == MBEDTLS_SSL_SESSION_TICKETS_ENABLED ) + { + if( ( ret = mbedtls_ssl_ticket_setup( &ticket_ctx, + mbedtls_ctr_drbg_random, &ctr_drbg, + MBEDTLS_CIPHER_AES_256_GCM, + opt.ticket_timeout ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_ticket_setup returned %d\n\n", ret ); + goto exit; + } + + mbedtls_ssl_conf_session_tickets_cb( &conf, + mbedtls_ssl_ticket_write, + mbedtls_ssl_ticket_parse, + &ticket_ctx ); + } +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { +#if defined(MBEDTLS_SSL_COOKIE_C) + if( opt.cookies > 0 ) + { + if( ( ret = mbedtls_ssl_cookie_setup( &cookie_ctx, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_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 ); + } + else +#endif /* MBEDTLS_SSL_COOKIE_C */ +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( opt.cookies == 0 ) + { + mbedtls_ssl_conf_dtls_cookies( &conf, NULL, NULL, NULL ); + } + else +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + { + ; /* Nothing to do */ + } + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) + if( opt.anti_replay != DFL_ANTI_REPLAY ) + mbedtls_ssl_conf_dtls_anti_replay( &conf, opt.anti_replay ); +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) + if( opt.badmac_limit != DFL_BADMAC_LIMIT ) + mbedtls_ssl_conf_dtls_badmac_limit( &conf, opt.badmac_limit ); +#endif + } +#endif /* MBEDTLS_SSL_PROTO_DTLS */ + + if( opt.force_ciphersuite[0] != DFL_FORCE_CIPHER ) + mbedtls_ssl_conf_ciphersuites( &conf, opt.force_ciphersuite ); + +#if defined(MBEDTLS_ARC4_C) + if( opt.arc4 != DFL_ARC4 ) + mbedtls_ssl_conf_arc4_support( &conf, opt.arc4 ); +#endif + + if( opt.version_suites != NULL ) + { + mbedtls_ssl_conf_ciphersuites_for_version( &conf, version_suites[0], + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_0 ); + mbedtls_ssl_conf_ciphersuites_for_version( &conf, version_suites[1], + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_1 ); + mbedtls_ssl_conf_ciphersuites_for_version( &conf, version_suites[2], + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_2 ); + mbedtls_ssl_conf_ciphersuites_for_version( &conf, version_suites[3], + MBEDTLS_SSL_MAJOR_VERSION_3, + MBEDTLS_SSL_MINOR_VERSION_3 ); + } + + if( opt.allow_legacy != DFL_ALLOW_LEGACY ) + mbedtls_ssl_conf_legacy_renegotiation( &conf, opt.allow_legacy ); +#if defined(MBEDTLS_SSL_RENEGOTIATION) + mbedtls_ssl_conf_renegotiation( &conf, opt.renegotiation ); + + if( opt.renego_delay != DFL_RENEGO_DELAY ) + mbedtls_ssl_conf_renegotiation_enforced( &conf, opt.renego_delay ); + + if( opt.renego_period != DFL_RENEGO_PERIOD ) + { + PUT_UINT64_BE( renego_period, opt.renego_period, 0 ); + mbedtls_ssl_conf_renegotiation_period( &conf, renego_period ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( strcmp( opt.ca_path, "none" ) != 0 && + strcmp( opt.ca_file, "none" ) != 0 ) + { +#if defined(MBEDTLS_X509_TRUSTED_CERTIFICATE_CALLBACK) + if( opt.ca_callback != 0 ) + mbedtls_ssl_conf_ca_cb( &conf, ca_callback, &cacert); + else +#endif + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + } + if( key_cert_init ) + { + mbedtls_pk_context *pk = &pkey; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_private_delay1 >= 0 ) + { + ret = ssl_async_set_key( &ssl_async_keys, &srvcert, pk, 0, + opt.async_private_delay1 ); + if( ret < 0 ) + { + mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n", + ret ); + goto exit; + } + pk = NULL; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, pk ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + } + if( key_cert_init2 ) + { + mbedtls_pk_context *pk = &pkey2; +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_private_delay2 >= 0 ) + { + ret = ssl_async_set_key( &ssl_async_keys, &srvcert2, pk, 0, + opt.async_private_delay2 ); + if( ret < 0 ) + { + mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n", + ret ); + goto exit; + } + pk = NULL; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert2, pk ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret ); + goto exit; + } + } + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_operations[0] != '-' ) + { + mbedtls_ssl_async_sign_t *sign = NULL; + mbedtls_ssl_async_decrypt_t *decrypt = NULL; + const char *r; + for( r = opt.async_operations; *r; r++ ) + { + switch( *r ) + { + case 'd': + decrypt = ssl_async_decrypt; + break; + case 's': + sign = ssl_async_sign; + break; + } + } + ssl_async_keys.inject_error = ( opt.async_private_error < 0 ? + - opt.async_private_error : + opt.async_private_error ); + ssl_async_keys.f_rng = mbedtls_ctr_drbg_random; + ssl_async_keys.p_rng = &ctr_drbg; + mbedtls_ssl_conf_async_private_cb( &conf, + sign, + decrypt, + ssl_async_resume, + ssl_async_cancel, + &ssl_async_keys ); + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +#if defined(SNI_OPTION) + if( opt.sni != NULL ) + { + mbedtls_ssl_conf_sni( &conf, sni_callback, sni_info ); +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_private_delay2 >= 0 ) + { + sni_entry *cur; + for( cur = sni_info; cur != NULL; cur = cur->next ) + { + ret = ssl_async_set_key( &ssl_async_keys, + cur->cert, cur->key, 1, + opt.async_private_delay2 ); + if( ret < 0 ) + { + mbedtls_printf( " Test error: ssl_async_set_key failed (%d)\n", + ret ); + goto exit; + } + cur->key = NULL; + } + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( opt.curves != NULL && + strcmp( opt.curves, "default" ) != 0 ) + { + mbedtls_ssl_conf_curves( &conf, curve_list ); + } +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + + if( strlen( opt.psk ) != 0 && strlen( opt.psk_identity ) != 0 ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_opaque != 0 ) + { + status = psa_allocate_key( &psk_slot ); + if( status != PSA_SUCCESS ) + { + fprintf( stderr, "ALLOC FAIL\n" ); + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + + /* The algorithm has already been determined earlier. */ + status = psa_setup_psk_key_slot( psk_slot, alg, psk, psk_len ); + if( status != PSA_SUCCESS ) + { + fprintf( stderr, "SETUP FAIL\n" ); + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + if( ( ret = mbedtls_ssl_conf_psk_opaque( &conf, psk_slot, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_conf_psk_opaque returned %d\n\n", + ret ); + goto exit; + } + } + else +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + if( ( ret = mbedtls_ssl_conf_psk( &conf, psk, psk_len, + (const unsigned char *) opt.psk_identity, + strlen( opt.psk_identity ) ) ) != 0 ) + { + mbedtls_printf( " failed\n mbedtls_ssl_conf_psk returned -0x%04X\n\n", - ret ); + goto exit; + } + } + + if( opt.psk_list != NULL ) + { +#if defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_list_opaque != 0 ) + { + psk_entry *cur_psk; + for( cur_psk = psk_info; cur_psk != NULL; cur_psk = cur_psk->next ) + { + status = psa_allocate_key( &cur_psk->slot ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + + status = psa_setup_psk_key_slot( cur_psk->slot, alg, + cur_psk->key, + cur_psk->key_len ); + if( status != PSA_SUCCESS ) + { + ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED; + goto exit; + } + } + } +#endif /* MBEDTLS_USE_PSA_CRYPTO */ + + mbedtls_ssl_conf_psk_cb( &conf, psk_callback, psk_info ); + } +#endif + +#if defined(MBEDTLS_DHM_C) + /* + * Use different group than default DHM group + */ +#if defined(MBEDTLS_FS_IO) + if( opt.dhm_file != NULL ) + ret = mbedtls_ssl_conf_dh_param_ctx( &conf, &dhm ); +#endif + if( ret != 0 ) + { + mbedtls_printf( " failed\n mbedtls_ssl_conf_dh_param returned -0x%04X\n\n", - ret ); + goto exit; + } +#endif + + if( opt.min_version != DFL_MIN_VERSION ) + mbedtls_ssl_conf_min_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, opt.min_version ); + + if( opt.max_version != DFL_MIN_VERSION ) + mbedtls_ssl_conf_max_version( &conf, MBEDTLS_SSL_MAJOR_VERSION_3, opt.max_version ); + + if( ( ret = mbedtls_ssl_setup( &ssl, &conf ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_setup returned -0x%x\n\n", -ret ); + goto exit; + } + + if( opt.nbio == 2 ) + mbedtls_ssl_set_bio( &ssl, &client_fd, my_send, my_recv, NULL ); + else + mbedtls_ssl_set_bio( &ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, + opt.nbio == 0 ? mbedtls_net_recv_timeout : NULL ); + +#if defined(MBEDTLS_SSL_PROTO_DTLS) + if( opt.dtls_mtu != DFL_DTLS_MTU ) + mbedtls_ssl_set_mtu( &ssl, opt.dtls_mtu ); +#endif + +#if defined(MBEDTLS_TIMING_C) + mbedtls_ssl_set_timer_cb( &ssl, &timer, mbedtls_timing_set_delay, + mbedtls_timing_get_delay ); +#endif + + mbedtls_printf( " ok\n" ); + +reset: +#if !defined(_WIN32) + if( received_sigterm ) + { + mbedtls_printf( " interrupted by SIGTERM (not in net_accept())\n" ); + if( ret == MBEDTLS_ERR_NET_INVALID_CONTEXT ) + ret = 0; + + goto exit; + } +#endif + + if( ret == MBEDTLS_ERR_SSL_CLIENT_RECONNECT ) + { + mbedtls_printf( " ! Client initiated reconnection from same port\n" ); + goto handshake; + } + +#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, + client_ip, sizeof( client_ip ), &cliip_len ) ) != 0 ) + { +#if !defined(_WIN32) + if( received_sigterm ) + { + mbedtls_printf( " interrupted by SIGTERM (in net_accept())\n" ); + if( ret == MBEDTLS_ERR_NET_ACCEPT_FAILED ) + ret = 0; + + goto exit; + } +#endif + + mbedtls_printf( " failed\n ! mbedtls_net_accept returned -0x%x\n\n", -ret ); + goto exit; + } + + if( opt.nbio > 0 ) + ret = mbedtls_net_set_nonblock( &client_fd ); + else + ret = mbedtls_net_set_block( &client_fd ); + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! net_set_(non)block() returned -0x%x\n\n", -ret ); + goto exit; + } + + mbedtls_ssl_conf_read_timeout( &conf, opt.read_timeout ); + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) + if( opt.transport == MBEDTLS_SSL_TRANSPORT_DATAGRAM ) + { + if( ( ret = mbedtls_ssl_set_client_transport_id( &ssl, + client_ip, cliip_len ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_client_transport_id() returned -0x%x\n\n", + -ret ); + goto exit; + } + } +#endif /* MBEDTLS_SSL_DTLS_HELLO_VERIFY */ + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) + if( opt.ecjpake_pw != DFL_ECJPAKE_PW ) + { + if( ( ret = mbedtls_ssl_set_hs_ecjpake_password( &ssl, + (const unsigned char *) opt.ecjpake_pw, + strlen( opt.ecjpake_pw ) ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_set_hs_ecjpake_password returned %d\n\n", ret ); + goto exit; + } + } +#endif + + mbedtls_printf( " ok\n" ); + + /* + * 4. Handshake + */ +handshake: + mbedtls_printf( " . Performing the SSL/TLS handshake..." ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 ) + { +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( ret == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS && + ssl_async_keys.inject_error == SSL_ASYNC_INJECT_ERROR_CANCEL ) + { + mbedtls_printf( " cancelling on injected error\n" ); + break; + } +#endif /* MBEDTLS_SSL_ASYNC_PRIVATE */ + + if( ! mbedtls_status_is_ssl_in_progress( ret ) ) + break; + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + ret = idle( &client_fd, &timer, ret ); +#else + ret = idle( &client_fd, ret ); +#endif + if( ret != 0 ) + goto reset; + } + } + + if( ret == MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED ) + { + mbedtls_printf( " hello verification requested\n" ); + ret = 0; + goto reset; + } + else if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_handshake returned -0x%x\n\n", -ret ); + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + { + char vrfy_buf[512]; + flags = mbedtls_ssl_get_verify_result( &ssl ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } +#endif + +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + if( opt.async_private_error < 0 ) + /* Injected error only the first time round, to test reset */ + ssl_async_keys.inject_error = SSL_ASYNC_INJECT_ERROR_NONE; +#endif + goto reset; + } + else /* ret == 0 */ + { + mbedtls_printf( " ok\n [ Protocol is %s ]\n [ Ciphersuite is %s ]\n", + mbedtls_ssl_get_version( &ssl ), mbedtls_ssl_get_ciphersuite( &ssl ) ); + } + + if( ( ret = mbedtls_ssl_get_record_expansion( &ssl ) ) >= 0 ) + mbedtls_printf( " [ Record expansion is %d ]\n", ret ); + else + mbedtls_printf( " [ Record expansion is unknown (compression) ]\n" ); + +#if defined(MBEDTLS_SSL_MAX_FRAGMENT_LENGTH) + mbedtls_printf( " [ Maximum fragment length is %u ]\n", + (unsigned int) mbedtls_ssl_get_max_frag_len( &ssl ) ); +#endif + +#if defined(MBEDTLS_SSL_ALPN) + if( opt.alpn_string != NULL ) + { + const char *alp = mbedtls_ssl_get_alpn_protocol( &ssl ); + mbedtls_printf( " [ Application Layer Protocol is %s ]\n", + alp ? alp : "(none)" ); + } +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + /* + * 5. Verify the client certificate + */ + mbedtls_printf( " . Verifying peer X.509 certificate..." ); + + if( ( flags = mbedtls_ssl_get_verify_result( &ssl ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + + if( mbedtls_ssl_get_peer_cert( &ssl ) != NULL ) + { + char crt_buf[512]; + + mbedtls_printf( " . Peer certificate information ...\n" ); + mbedtls_x509_crt_info( crt_buf, sizeof( crt_buf ), " ", + mbedtls_ssl_get_peer_cert( &ssl ) ); + mbedtls_printf( "%s\n", crt_buf ); + } +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + + if( opt.exchanges == 0 ) + goto close_notify; + + exchanges_left = opt.exchanges; +data_exchange: + /* + * 6. Read the HTTP Request + */ + mbedtls_printf( " < Read from client:" ); + fflush( stdout ); + + /* + * TLS and DTLS need different reading styles (stream vs datagram) + */ + if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + do + { + int terminated = 0; + len = opt.buffer_size - 1; + memset( buf, 0, opt.buffer_size ); + ret = mbedtls_ssl_read( &ssl, buf, len ); + + if( mbedtls_status_is_ssl_in_progress( ret ) ) + { + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, ret ); +#else + idle( &client_fd, ret ); +#endif + } + + continue; + } + + if( ret <= 0 ) + { + switch( ret ) + { + case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY: + mbedtls_printf( " connection was closed gracefully\n" ); + goto close_notify; + + case 0: + case MBEDTLS_ERR_NET_CONN_RESET: + mbedtls_printf( " connection was reset by peer\n" ); + ret = MBEDTLS_ERR_NET_CONN_RESET; + goto reset; + + default: + mbedtls_printf( " mbedtls_ssl_read returned -0x%x\n", -ret ); + goto reset; + } + } + + if( mbedtls_ssl_get_bytes_avail( &ssl ) == 0 ) + { + len = ret; + buf[len] = '\0'; + mbedtls_printf( " %d bytes read\n\n%s\n", len, (char *) buf ); + + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( buf[len - 1] == '\n' ) + terminated = 1; + } + else + { + int extra_len, ori_len; + unsigned char *larger_buf; + + ori_len = ret; + extra_len = (int) mbedtls_ssl_get_bytes_avail( &ssl ); + + larger_buf = mbedtls_calloc( 1, ori_len + extra_len + 1 ); + if( larger_buf == NULL ) + { + mbedtls_printf( " ! memory allocation failed\n" ); + ret = 1; + goto reset; + } + + memset( larger_buf, 0, ori_len + extra_len ); + memcpy( larger_buf, buf, ori_len ); + + /* This read should never fail and get the whole cached data */ + ret = mbedtls_ssl_read( &ssl, larger_buf + ori_len, extra_len ); + if( ret != extra_len || + mbedtls_ssl_get_bytes_avail( &ssl ) != 0 ) + { + mbedtls_printf( " ! mbedtls_ssl_read failed on cached data\n" ); + ret = 1; + goto reset; + } + + larger_buf[ori_len + extra_len] = '\0'; + mbedtls_printf( " %u bytes read (%u + %u)\n\n%s\n", + ori_len + extra_len, ori_len, extra_len, + (char *) larger_buf ); + + /* End of message should be detected according to the syntax of the + * application protocol (eg HTTP), just use a dummy test here. */ + if( larger_buf[ori_len + extra_len - 1] == '\n' ) + terminated = 1; + + mbedtls_free( larger_buf ); + } + + if( terminated ) + { + ret = 0; + break; + } + } + while( 1 ); + } + else /* Not stream, so datagram */ + { + len = opt.buffer_size - 1; + memset( buf, 0, opt.buffer_size ); + + do + { + /* Without the call to `mbedtls_ssl_check_pending`, it might + * happen that the client sends application data in the same + * datagram as the Finished message concluding the handshake. + * In this case, the application data would be ready to be + * processed while the underlying transport wouldn't signal + * any further incoming data. + * + * See the test 'Event-driven I/O: session-id resume, UDP packing' + * in tests/ssl-opt.sh. + */ + + /* For event-driven IO, wait for socket to become available */ + if( mbedtls_ssl_check_pending( &ssl ) == 0 && + opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, MBEDTLS_ERR_SSL_WANT_READ ); +#else + idle( &client_fd, MBEDTLS_ERR_SSL_WANT_READ ); +#endif + } + + ret = mbedtls_ssl_read( &ssl, buf, len ); + + /* Note that even if `mbedtls_ssl_check_pending` returns true, + * it can happen that the subsequent call to `mbedtls_ssl_read` + * returns `MBEDTLS_ERR_SSL_WANT_READ`, because the pending messages + * might be discarded (e.g. because they are retransmissions). */ + } + while( mbedtls_status_is_ssl_in_progress( ret ) ); + + if( ret <= 0 ) + { + switch( ret ) + { + 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", -ret ); + goto reset; + } + } + + len = ret; + buf[len] = '\0'; + mbedtls_printf( " %d bytes read\n\n%s", len, (char *) buf ); + ret = 0; + } + + /* + * 7a. Request renegotiation while client is waiting for input from us. + * (only on the first exchange, to be able to test retransmission) + */ +#if defined(MBEDTLS_SSL_RENEGOTIATION) + if( opt.renegotiate && exchanges_left == opt.exchanges ) + { + mbedtls_printf( " . Requestion renegotiation..." ); + fflush( stdout ); + + while( ( ret = mbedtls_ssl_renegotiate( &ssl ) ) != 0 ) + { + if( ! mbedtls_status_is_ssl_in_progress( ret ) ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_renegotiate returned %d\n\n", ret ); + goto reset; + } + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, ret ); +#else + idle( &client_fd, ret ); +#endif + } + } + + mbedtls_printf( " ok\n" ); + } +#endif /* MBEDTLS_SSL_RENEGOTIATION */ + + /* + * 7. Write the 200 Response + */ + mbedtls_printf( " > Write to client:" ); + fflush( stdout ); + + len = sprintf( (char *) buf, HTTP_RESPONSE, + mbedtls_ssl_get_ciphersuite( &ssl ) ); + + /* Add padding to the response to reach opt.response_size in length */ + if( opt.response_size != DFL_RESPONSE_SIZE && + len < opt.response_size ) + { + memset( buf + len, 'B', opt.response_size - len ); + len += opt.response_size - len; + } + + /* Truncate if response size is smaller than the "natural" size */ + if( opt.response_size != DFL_RESPONSE_SIZE && + len > opt.response_size ) + { + len = opt.response_size; + + /* Still end with \r\n unless that's really not possible */ + if( len >= 2 ) buf[len - 2] = '\r'; + if( len >= 1 ) buf[len - 1] = '\n'; + } + + if( opt.transport == MBEDTLS_SSL_TRANSPORT_STREAM ) + { + for( written = 0, frags = 0; written < len; written += ret, frags++ ) + { + while( ( ret = mbedtls_ssl_write( &ssl, buf + written, len - written ) ) + <= 0 ) + { + if( ret == MBEDTLS_ERR_NET_CONN_RESET ) + { + mbedtls_printf( " failed\n ! peer closed the connection\n\n" ); + goto reset; + } + + if( ! mbedtls_status_is_ssl_in_progress( ret ) ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto reset; + } + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, ret ); +#else + idle( &client_fd, ret ); +#endif + } + } + } + } + else /* Not stream, so datagram */ + { + while( 1 ) + { + ret = mbedtls_ssl_write( &ssl, buf, len ); + + if( ! mbedtls_status_is_ssl_in_progress( ret ) ) + break; + + /* For event-driven IO, wait for socket to become available */ + if( opt.event == 1 /* level triggered IO */ ) + { +#if defined(MBEDTLS_TIMING_C) + idle( &client_fd, &timer, ret ); +#else + idle( &client_fd, ret ); +#endif + } + } + + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_ssl_write returned %d\n\n", ret ); + goto reset; + } + + frags = 1; + written = ret; + } + + buf[written] = '\0'; + mbedtls_printf( " %d bytes written in %d fragments\n\n%s\n", written, frags, (char *) buf ); + ret = 0; + + /* + * 7b. Continue doing data exchanges? + */ + if( --exchanges_left > 0 ) + goto data_exchange; + + /* + * 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" ); + + goto reset; + + /* + * Cleanup 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: -0x%X - %s\n\n", -ret, error_buf ); + } +#endif + + mbedtls_printf( " . Cleaning up..." ); + fflush( stdout ); + + mbedtls_net_free( &client_fd ); + mbedtls_net_free( &listen_fd ); + +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + mbedtls_dhm_free( &dhm ); +#endif +#if defined(MBEDTLS_X509_CRT_PARSE_C) + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &srvcert ); + mbedtls_pk_free( &pkey ); + mbedtls_x509_crt_free( &srvcert2 ); + mbedtls_pk_free( &pkey2 ); +#endif +#if defined(MBEDTLS_SSL_ASYNC_PRIVATE) + for( i = 0; (size_t) i < ssl_async_keys.slots_used; i++ ) + { + if( ssl_async_keys.slots[i].pk_owned ) + { + mbedtls_pk_free( ssl_async_keys.slots[i].pk ); + mbedtls_free( ssl_async_keys.slots[i].pk ); + ssl_async_keys.slots[i].pk = NULL; + } + } +#endif +#if defined(SNI_OPTION) + sni_free( sni_info ); +#endif +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) + if( ( ret = psk_free( psk_info ) ) != 0 ) + mbedtls_printf( "Failed to list of opaque PSKs - error was %d\n", ret ); +#endif +#if defined(MBEDTLS_DHM_C) && defined(MBEDTLS_FS_IO) + mbedtls_dhm_free( &dhm ); +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED) && \ + defined(MBEDTLS_USE_PSA_CRYPTO) + if( opt.psk_opaque != 0 ) + { + /* This is ok even if the slot hasn't been + * initialized (we might have jumed here + * immediately because of bad cmd line params, + * for example). */ + status = psa_destroy_key( psk_slot ); + if( status != PSA_SUCCESS ) + { + mbedtls_printf( "Failed to destroy key slot %u - error was %d", + (unsigned) psk_slot, (int) status ); + } + } +#endif /* MBEDTLS_KEY_EXCHANGE__SOME__PSK_ENABLED && + MBEDTLS_USE_PSA_CRYPTO */ + + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(MBEDTLS_SSL_CACHE_C) + mbedtls_ssl_cache_free( &cache ); +#endif +#if defined(MBEDTLS_SSL_SESSION_TICKETS) + mbedtls_ssl_ticket_free( &ticket_ctx ); +#endif +#if defined(MBEDTLS_SSL_COOKIE_C) + mbedtls_ssl_cookie_free( &cookie_ctx ); +#endif + + mbedtls_free( buf ); + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) +#if defined(MBEDTLS_MEMORY_DEBUG) + mbedtls_memory_buffer_alloc_status(); +#endif + mbedtls_memory_buffer_alloc_free(); +#endif + + mbedtls_printf( " done.\n" ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + // Shell can not handle large exit numbers -> 1 for errors + if( ret < 0 ) + ret = 1; + + return( ret ); +} +#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 */ diff --git a/programs/test/CMakeLists.txt b/programs/test/CMakeLists.txt index 2b455ee01..59f8d54f1 100644 --- a/programs/test/CMakeLists.txt +++ b/programs/test/CMakeLists.txt @@ -13,6 +13,9 @@ if(TEST_CPP) target_link_libraries(cpp_dummy_build ${libs}) endif() +add_executable(udp_proxy udp_proxy.c) +target_link_libraries(udp_proxy ${libs}) + add_executable(zeroize zeroize.c) target_link_libraries(zeroize ${libs}) @@ -20,6 +23,6 @@ add_executable(query_compile_time_config query_compile_time_config.c) target_sources(query_compile_time_config PUBLIC query_config.c) target_link_libraries(query_compile_time_config ${libs}) -install(TARGETS selftest benchmark query_compile_time_config +install(TARGETS selftest benchmark udp_proxy query_compile_time_config DESTINATION "bin" PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/programs/test/udp_proxy.c b/programs/test/udp_proxy.c new file mode 100644 index 000000000..41739d057 --- /dev/null +++ b/programs/test/udp_proxy.c @@ -0,0 +1,944 @@ +/* + * UDP proxy: emulate an unreliable UDP connexion for DTLS testing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * Warning: this is an internal utility program we use for tests. + * It does break some abstractions from the NET layer, and is thus NOT an + * example of good general usage. + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#include +#define mbedtls_time time +#define mbedtls_time_t time_t +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#define MBEDTLS_EXIT_SUCCESS EXIT_SUCCESS +#define MBEDTLS_EXIT_FAILURE EXIT_FAILURE +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_NET_C) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_NET_C not defined.\n" ); + return( 0 ); +} +#else + +#include "mbedtls/net_sockets.h" +#include "mbedtls/error.h" +#include "mbedtls/ssl.h" +#include "mbedtls/timing.h" + +#include + +/* For select() */ +#if (defined(_WIN32) || defined(_WIN32_WCE)) && !defined(EFIX64) && \ + !defined(EFI32) +#include +#include +#if defined(_MSC_VER) +#if defined(_WIN32_WCE) +#pragma comment( lib, "ws2.lib" ) +#else +#pragma comment( lib, "ws2_32.lib" ) +#endif +#endif /* _MSC_VER */ +#else /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ +#include +#include +#include +#endif /* ( _WIN32 || _WIN32_WCE ) && !EFIX64 && !EFI32 */ + +#define MAX_MSG_SIZE 16384 + 2048 /* max record/datagram size */ + +#define DFL_SERVER_ADDR "localhost" +#define DFL_SERVER_PORT "4433" +#define DFL_LISTEN_ADDR "localhost" +#define DFL_LISTEN_PORT "5556" +#define DFL_PACK 0 + +#if defined(MBEDTLS_TIMING_C) +#define USAGE_PACK \ + " pack=%%d default: 0 (don't pack)\n" \ + " options: t > 0 (pack for t milliseconds)\n" +#else +#define USAGE_PACK +#endif + +#define USAGE \ + "\n usage: udp_proxy param=<>...\n" \ + "\n acceptable parameters:\n" \ + " server_addr=%%s default: localhost\n" \ + " server_port=%%d default: 4433\n" \ + " listen_addr=%%s default: localhost\n" \ + " listen_port=%%d default: 4433\n" \ + "\n" \ + " duplicate=%%d default: 0 (no duplication)\n" \ + " duplicate about 1:N packets randomly\n" \ + " delay=%%d default: 0 (no delayed packets)\n" \ + " delay about 1:N packets randomly\n" \ + " delay_ccs=0/1 default: 0 (don't delay ChangeCipherSpec)\n" \ + " delay_cli=%%s Handshake message from client that should be\n"\ + " delayed. Possible values are 'ClientHello',\n" \ + " 'Certificate', 'CertificateVerify', and\n" \ + " 'ClientKeyExchange'.\n" \ + " May be used multiple times, even for the same\n"\ + " message, in which case the respective message\n"\ + " gets delayed multiple times.\n" \ + " delay_srv=%%s Handshake message from server that should be\n"\ + " delayed. Possible values are 'HelloRequest',\n"\ + " 'ServerHello', 'ServerHelloDone', 'Certificate'\n"\ + " 'ServerKeyExchange', 'NewSessionTicket',\n"\ + " 'HelloVerifyRequest' and ''CertificateRequest'.\n"\ + " May be used multiple times, even for the same\n"\ + " message, in which case the respective message\n"\ + " gets delayed multiple times.\n" \ + " drop=%%d default: 0 (no dropped packets)\n" \ + " drop about 1:N packets randomly\n" \ + " mtu=%%d default: 0 (unlimited)\n" \ + " drop packets larger than N bytes\n" \ + " bad_ad=0/1 default: 0 (don't add bad ApplicationData)\n" \ + " protect_hvr=0/1 default: 0 (don't protect HelloVerifyRequest)\n" \ + " protect_len=%%d default: (don't protect packets of this size)\n" \ + "\n" \ + " seed=%%d default: (use current time)\n" \ + USAGE_PACK \ + "\n" + +/* + * global options + */ + +#define MAX_DELAYED_HS 10 + +static struct options +{ + const char *server_addr; /* address to forward packets to */ + const char *server_port; /* port to forward packets to */ + const char *listen_addr; /* address for accepting client connections */ + const char *listen_port; /* port for accepting client connections */ + + int duplicate; /* duplicate 1 in N packets (none if 0) */ + int delay; /* delay 1 packet in N (none if 0) */ + int delay_ccs; /* delay ChangeCipherSpec */ + char* delay_cli[MAX_DELAYED_HS]; /* handshake types of messages from + * client that should be delayed. */ + uint8_t delay_cli_cnt; /* Number of entries in delay_cli. */ + char* delay_srv[MAX_DELAYED_HS]; /* handshake types of messages from + * server that should be delayed. */ + uint8_t delay_srv_cnt; /* Number of entries in delay_srv. */ + int drop; /* drop 1 packet in N (none if 0) */ + int mtu; /* drop packets larger than this */ + int bad_ad; /* inject corrupted ApplicationData record */ + int protect_hvr; /* never drop or delay HelloVerifyRequest */ + int protect_len; /* never drop/delay packet of the given size*/ + unsigned pack; /* merge packets into single datagram for + * at most \c merge milliseconds if > 0 */ + unsigned int seed; /* seed for "random" events */ +} opt; + +static void exit_usage( const char *name, const char *value ) +{ + if( value == NULL ) + mbedtls_printf( " unknown option or missing value: %s\n", name ); + else + mbedtls_printf( " option %s: illegal value: %s\n", name, value ); + + mbedtls_printf( USAGE ); + exit( 1 ); +} + +static void get_options( int argc, char *argv[] ) +{ + int i; + char *p, *q; + + opt.server_addr = DFL_SERVER_ADDR; + opt.server_port = DFL_SERVER_PORT; + opt.listen_addr = DFL_LISTEN_ADDR; + opt.listen_port = DFL_LISTEN_PORT; + opt.pack = DFL_PACK; + /* Other members default to 0 */ + + opt.delay_cli_cnt = 0; + opt.delay_srv_cnt = 0; + memset( opt.delay_cli, 0, sizeof( opt.delay_cli ) ); + memset( opt.delay_srv, 0, sizeof( opt.delay_srv ) ); + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + exit_usage( p, NULL ); + *q++ = '\0'; + + if( strcmp( p, "server_addr" ) == 0 ) + opt.server_addr = q; + else if( strcmp( p, "server_port" ) == 0 ) + opt.server_port = q; + else if( strcmp( p, "listen_addr" ) == 0 ) + opt.listen_addr = q; + else if( strcmp( p, "listen_port" ) == 0 ) + opt.listen_port = q; + else if( strcmp( p, "duplicate" ) == 0 ) + { + opt.duplicate = atoi( q ); + if( opt.duplicate < 0 || opt.duplicate > 20 ) + exit_usage( p, q ); + } + else if( strcmp( p, "delay" ) == 0 ) + { + opt.delay = atoi( q ); + if( opt.delay < 0 || opt.delay > 20 || opt.delay == 1 ) + exit_usage( p, q ); + } + else if( strcmp( p, "delay_ccs" ) == 0 ) + { + opt.delay_ccs = atoi( q ); + if( opt.delay_ccs < 0 || opt.delay_ccs > 1 ) + exit_usage( p, q ); + } + else if( strcmp( p, "delay_cli" ) == 0 || + strcmp( p, "delay_srv" ) == 0 ) + { + uint8_t *delay_cnt; + char **delay_list; + size_t len; + char *buf; + + if( strcmp( p, "delay_cli" ) == 0 ) + { + delay_cnt = &opt.delay_cli_cnt; + delay_list = opt.delay_cli; + } + else + { + delay_cnt = &opt.delay_srv_cnt; + delay_list = opt.delay_srv; + } + + if( *delay_cnt == MAX_DELAYED_HS ) + { + mbedtls_printf( " too many uses of %s: only %d allowed\n", + p, MAX_DELAYED_HS ); + exit_usage( p, NULL ); + } + + len = strlen( q ); + buf = mbedtls_calloc( 1, len + 1 ); + if( buf == NULL ) + { + mbedtls_printf( " Allocation failure\n" ); + exit( 1 ); + } + memcpy( buf, q, len + 1 ); + + delay_list[ (*delay_cnt)++ ] = buf; + } + else if( strcmp( p, "drop" ) == 0 ) + { + opt.drop = atoi( q ); + if( opt.drop < 0 || opt.drop > 20 || opt.drop == 1 ) + exit_usage( p, q ); + } + else if( strcmp( p, "pack" ) == 0 ) + { +#if defined(MBEDTLS_TIMING_C) + opt.pack = (unsigned) atoi( q ); +#else + mbedtls_printf( " option pack only defined if MBEDTLS_TIMING_C is enabled\n" ); + exit( 1 ); +#endif + } + else if( strcmp( p, "mtu" ) == 0 ) + { + opt.mtu = atoi( q ); + if( opt.mtu < 0 || opt.mtu > MAX_MSG_SIZE ) + exit_usage( p, q ); + } + else if( strcmp( p, "bad_ad" ) == 0 ) + { + opt.bad_ad = atoi( q ); + if( opt.bad_ad < 0 || opt.bad_ad > 1 ) + exit_usage( p, q ); + } + else if( strcmp( p, "protect_hvr" ) == 0 ) + { + opt.protect_hvr = atoi( q ); + if( opt.protect_hvr < 0 || opt.protect_hvr > 1 ) + exit_usage( p, q ); + } + else if( strcmp( p, "protect_len" ) == 0 ) + { + opt.protect_len = atoi( q ); + if( opt.protect_len < 0 ) + exit_usage( p, q ); + } + else if( strcmp( p, "seed" ) == 0 ) + { + opt.seed = atoi( q ); + if( opt.seed == 0 ) + exit_usage( p, q ); + } + else + exit_usage( p, NULL ); + } +} + +static const char *msg_type( unsigned char *msg, size_t len ) +{ + if( len < 1 ) return( "Invalid" ); + switch( msg[0] ) + { + case MBEDTLS_SSL_MSG_CHANGE_CIPHER_SPEC: return( "ChangeCipherSpec" ); + case MBEDTLS_SSL_MSG_ALERT: return( "Alert" ); + case MBEDTLS_SSL_MSG_APPLICATION_DATA: return( "ApplicationData" ); + case MBEDTLS_SSL_MSG_HANDSHAKE: break; /* See below */ + default: return( "Unknown" ); + } + + if( len < 13 + 12 ) return( "Invalid handshake" ); + + /* + * Our handshake message are less than 2^16 bytes long, so they should + * have 0 as the first byte of length, frag_offset and frag_length. + * Otherwise, assume they are encrypted. + */ + if( msg[14] || msg[19] || msg[22] ) return( "Encrypted handshake" ); + + switch( msg[13] ) + { + case MBEDTLS_SSL_HS_HELLO_REQUEST: return( "HelloRequest" ); + case MBEDTLS_SSL_HS_CLIENT_HELLO: return( "ClientHello" ); + case MBEDTLS_SSL_HS_SERVER_HELLO: return( "ServerHello" ); + case MBEDTLS_SSL_HS_HELLO_VERIFY_REQUEST: return( "HelloVerifyRequest" ); + case MBEDTLS_SSL_HS_NEW_SESSION_TICKET: return( "NewSessionTicket" ); + case MBEDTLS_SSL_HS_CERTIFICATE: return( "Certificate" ); + case MBEDTLS_SSL_HS_SERVER_KEY_EXCHANGE: return( "ServerKeyExchange" ); + case MBEDTLS_SSL_HS_CERTIFICATE_REQUEST: return( "CertificateRequest" ); + case MBEDTLS_SSL_HS_SERVER_HELLO_DONE: return( "ServerHelloDone" ); + case MBEDTLS_SSL_HS_CERTIFICATE_VERIFY: return( "CertificateVerify" ); + case MBEDTLS_SSL_HS_CLIENT_KEY_EXCHANGE: return( "ClientKeyExchange" ); + case MBEDTLS_SSL_HS_FINISHED: return( "Finished" ); + default: return( "Unknown handshake" ); + } +} + +#if defined(MBEDTLS_TIMING_C) +/* Return elapsed time in milliseconds since the first call */ +static unsigned ellapsed_time( void ) +{ + static int initialized = 0; + static struct mbedtls_timing_hr_time hires; + + if( initialized == 0 ) + { + (void) mbedtls_timing_get_timer( &hires, 1 ); + initialized = 1; + return( 0 ); + } + + return( mbedtls_timing_get_timer( &hires, 0 ) ); +} + +typedef struct +{ + mbedtls_net_context *ctx; + + const char *description; + + unsigned packet_lifetime; + unsigned num_datagrams; + + unsigned char data[MAX_MSG_SIZE]; + size_t len; + +} ctx_buffer; + +static ctx_buffer outbuf[2]; + +static int ctx_buffer_flush( ctx_buffer *buf ) +{ + int ret; + + mbedtls_printf( " %05u flush %s: %u bytes, %u datagrams, last %u ms\n", + ellapsed_time(), buf->description, + (unsigned) buf->len, buf->num_datagrams, + ellapsed_time() - buf->packet_lifetime ); + + ret = mbedtls_net_send( buf->ctx, buf->data, buf->len ); + + buf->len = 0; + buf->num_datagrams = 0; + + return( ret ); +} + +static unsigned ctx_buffer_time_remaining( ctx_buffer *buf ) +{ + unsigned const cur_time = ellapsed_time(); + + if( buf->num_datagrams == 0 ) + return( (unsigned) -1 ); + + if( cur_time - buf->packet_lifetime >= opt.pack ) + return( 0 ); + + return( opt.pack - ( cur_time - buf->packet_lifetime ) ); +} + +static int ctx_buffer_append( ctx_buffer *buf, + const unsigned char * data, + size_t len ) +{ + int ret; + + if( len > (size_t) INT_MAX ) + return( -1 ); + + if( len > sizeof( buf->data ) ) + { + mbedtls_printf( " ! buffer size %u too large (max %u)\n", + (unsigned) len, (unsigned) sizeof( buf->data ) ); + return( -1 ); + } + + if( sizeof( buf->data ) - buf->len < len ) + { + if( ( ret = ctx_buffer_flush( buf ) ) <= 0 ) + return( ret ); + } + + memcpy( buf->data + buf->len, data, len ); + + buf->len += len; + if( ++buf->num_datagrams == 1 ) + buf->packet_lifetime = ellapsed_time(); + + return( (int) len ); +} +#endif /* MBEDTLS_TIMING_C */ + +static int dispatch_data( mbedtls_net_context *ctx, + const unsigned char * data, + size_t len ) +{ +#if defined(MBEDTLS_TIMING_C) + ctx_buffer *buf = NULL; + if( opt.pack > 0 ) + { + if( outbuf[0].ctx == ctx ) + buf = &outbuf[0]; + else if( outbuf[1].ctx == ctx ) + buf = &outbuf[1]; + + if( buf == NULL ) + return( -1 ); + + return( ctx_buffer_append( buf, data, len ) ); + } +#endif /* MBEDTLS_TIMING_C */ + + return( mbedtls_net_send( ctx, data, len ) ); +} + +typedef struct +{ + mbedtls_net_context *dst; + const char *way; + const char *type; + unsigned len; + unsigned char buf[MAX_MSG_SIZE]; +} packet; + +/* Print packet. Outgoing packets come with a reason (forward, dupl, etc.) */ +void print_packet( const packet *p, const char *why ) +{ +#if defined(MBEDTLS_TIMING_C) + if( why == NULL ) + mbedtls_printf( " %05u dispatch %s %s (%u bytes)\n", + ellapsed_time(), p->way, p->type, p->len ); + else + mbedtls_printf( " %05u dispatch %s %s (%u bytes): %s\n", + ellapsed_time(), p->way, p->type, p->len, why ); +#else + if( why == NULL ) + mbedtls_printf( " dispatch %s %s (%u bytes)\n", + p->way, p->type, p->len ); + else + mbedtls_printf( " dispatch %s %s (%u bytes): %s\n", + p->way, p->type, p->len, why ); +#endif + + fflush( stdout ); +} + +int send_packet( const packet *p, const char *why ) +{ + int ret; + mbedtls_net_context *dst = p->dst; + + /* insert corrupted ApplicationData record? */ + if( opt.bad_ad && + strcmp( p->type, "ApplicationData" ) == 0 ) + { + unsigned char buf[MAX_MSG_SIZE]; + memcpy( buf, p->buf, p->len ); + + if( p->len <= 13 ) + { + mbedtls_printf( " ! can't corrupt empty AD record" ); + } + else + { + ++buf[13]; + print_packet( p, "corrupted" ); + } + + if( ( ret = dispatch_data( dst, buf, p->len ) ) <= 0 ) + { + mbedtls_printf( " ! dispatch returned %d\n", ret ); + return( ret ); + } + } + + print_packet( p, why ); + if( ( ret = dispatch_data( dst, p->buf, p->len ) ) <= 0 ) + { + mbedtls_printf( " ! dispatch returned %d\n", ret ); + return( ret ); + } + + /* Don't duplicate Application Data, only handshake covered */ + if( opt.duplicate != 0 && + strcmp( p->type, "ApplicationData" ) != 0 && + rand() % opt.duplicate == 0 ) + { + print_packet( p, "duplicated" ); + + if( ( ret = dispatch_data( dst, p->buf, p->len ) ) <= 0 ) + { + mbedtls_printf( " ! dispatch returned %d\n", ret ); + return( ret ); + } + } + + return( 0 ); +} + +#define MAX_DELAYED_MSG 5 +static size_t prev_len; +static packet prev[MAX_DELAYED_MSG]; + +void clear_pending( void ) +{ + memset( &prev, 0, sizeof( prev ) ); + prev_len = 0; +} + +void delay_packet( packet *delay ) +{ + if( prev_len == MAX_DELAYED_MSG ) + return; + + memcpy( &prev[prev_len++], delay, sizeof( packet ) ); +} + +int send_delayed() +{ + uint8_t offset; + int ret; + for( offset = 0; offset < prev_len; offset++ ) + { + ret = send_packet( &prev[offset], "delayed" ); + if( ret != 0 ) + return( ret ); + } + + clear_pending(); + return( 0 ); +} + +/* + * Avoid dropping or delaying a packet that was already dropped twice: this + * only results in uninteresting timeouts. We can't rely on type to identify + * packets, since during renegotiation they're all encrypted. So, rely on + * size mod 2048 (which is usually just size). + */ +static unsigned char dropped[2048] = { 0 }; +#define DROP_MAX 2 + +/* + * OpenSSL groups packets in a datagram the first time it sends them, but not + * when it resends them. Count every record as seen the first time. + */ +void update_dropped( const packet *p ) +{ + size_t id = p->len % sizeof( dropped ); + const unsigned char *end = p->buf + p->len; + const unsigned char *cur = p->buf; + size_t len = ( ( cur[11] << 8 ) | cur[12] ) + 13; + + ++dropped[id]; + + /* Avoid counting single record twice */ + if( len == p->len ) + return; + + while( cur < end ) + { + len = ( ( cur[11] << 8 ) | cur[12] ) + 13; + + id = len % sizeof( dropped ); + ++dropped[id]; + + cur += len; + } +} + +int handle_message( const char *way, + mbedtls_net_context *dst, + mbedtls_net_context *src ) +{ + int ret; + packet cur; + size_t id; + + uint8_t delay_idx; + char ** delay_list; + uint8_t delay_list_len; + + /* receive packet */ + if( ( ret = mbedtls_net_recv( src, cur.buf, sizeof( cur.buf ) ) ) <= 0 ) + { + mbedtls_printf( " ! mbedtls_net_recv returned %d\n", ret ); + return( ret ); + } + + cur.len = ret; + cur.type = msg_type( cur.buf, cur.len ); + cur.way = way; + cur.dst = dst; + print_packet( &cur, NULL ); + + id = cur.len % sizeof( dropped ); + + if( strcmp( way, "S <- C" ) == 0 ) + { + delay_list = opt.delay_cli; + delay_list_len = opt.delay_cli_cnt; + } + else + { + delay_list = opt.delay_srv; + delay_list_len = opt.delay_srv_cnt; + } + + /* Check if message type is in the list of messages + * that should be delayed */ + for( delay_idx = 0; delay_idx < delay_list_len; delay_idx++ ) + { + if( delay_list[ delay_idx ] == NULL ) + continue; + + if( strcmp( delay_list[ delay_idx ], cur.type ) == 0 ) + { + /* Delay message */ + delay_packet( &cur ); + + /* Remove entry from list */ + mbedtls_free( delay_list[delay_idx] ); + delay_list[delay_idx] = NULL; + + return( 0 ); + } + } + + /* do we want to drop, delay, or forward it? */ + if( ( opt.mtu != 0 && + cur.len > (unsigned) opt.mtu ) || + ( opt.drop != 0 && + strcmp( cur.type, "ApplicationData" ) != 0 && + ! ( opt.protect_hvr && + strcmp( cur.type, "HelloVerifyRequest" ) == 0 ) && + cur.len != (size_t) opt.protect_len && + dropped[id] < DROP_MAX && + rand() % opt.drop == 0 ) ) + { + update_dropped( &cur ); + } + else if( ( opt.delay_ccs == 1 && + strcmp( cur.type, "ChangeCipherSpec" ) == 0 ) || + ( opt.delay != 0 && + strcmp( cur.type, "ApplicationData" ) != 0 && + ! ( opt.protect_hvr && + strcmp( cur.type, "HelloVerifyRequest" ) == 0 ) && + cur.len != (size_t) opt.protect_len && + dropped[id] < DROP_MAX && + rand() % opt.delay == 0 ) ) + { + delay_packet( &cur ); + } + else + { + /* forward and possibly duplicate */ + if( ( ret = send_packet( &cur, "forwarded" ) ) != 0 ) + return( ret ); + + /* send previously delayed messages if any */ + ret = send_delayed(); + if( ret != 0 ) + return( ret ); + } + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + uint8_t delay_idx; + + mbedtls_net_context listen_fd, client_fd, server_fd; + +#if defined( MBEDTLS_TIMING_C ) + struct timeval tm; +#endif + + struct timeval *tm_ptr = NULL; + + int nb_fds; + fd_set read_fds; + + mbedtls_net_init( &listen_fd ); + mbedtls_net_init( &client_fd ); + mbedtls_net_init( &server_fd ); + + get_options( argc, argv ); + + /* + * Decisions to drop/delay/duplicate packets are pseudo-random: dropping + * exactly 1 in N packets would lead to problems when a flight has exactly + * N packets: the same packet would be dropped on every resend. + * + * In order to be able to reproduce problems reliably, the seed may be + * specified explicitly. + */ + if( opt.seed == 0 ) + { + opt.seed = (unsigned int) time( NULL ); + mbedtls_printf( " . Pseudo-random seed: %u\n", opt.seed ); + } + + srand( opt.seed ); + + /* + * 0. "Connect" to the server + */ + mbedtls_printf( " . Connect to server on UDP/%s/%s ...", + opt.server_addr, opt.server_port ); + fflush( stdout ); + + if( ( ret = mbedtls_net_connect( &server_fd, opt.server_addr, opt.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" ); + + /* + * 1. Setup the "listening" UDP socket + */ + mbedtls_printf( " . Bind on UDP/%s/%s ...", + opt.listen_addr, opt.listen_port ); + fflush( stdout ); + + if( ( ret = mbedtls_net_bind( &listen_fd, opt.listen_addr, opt.listen_port, + MBEDTLS_NET_PROTO_UDP ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_net_bind returned %d\n\n", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 2. Wait until a client connects + */ +accept: + mbedtls_net_free( &client_fd ); + + 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_printf( " ok\n" ); + + /* + * 3. Forward packets forever (kill the process to terminate it) + */ + clear_pending(); + memset( dropped, 0, sizeof( dropped ) ); + + nb_fds = client_fd.fd; + if( nb_fds < server_fd.fd ) + nb_fds = server_fd.fd; + if( nb_fds < listen_fd.fd ) + nb_fds = listen_fd.fd; + ++nb_fds; + +#if defined(MBEDTLS_TIMING_C) + if( opt.pack > 0 ) + { + outbuf[0].ctx = &server_fd; + outbuf[0].description = "S <- C"; + outbuf[0].num_datagrams = 0; + outbuf[0].len = 0; + + outbuf[1].ctx = &client_fd; + outbuf[1].description = "S -> C"; + outbuf[1].num_datagrams = 0; + outbuf[1].len = 0; + } +#endif /* MBEDTLS_TIMING_C */ + + while( 1 ) + { +#if defined(MBEDTLS_TIMING_C) + if( opt.pack > 0 ) + { + unsigned max_wait_server, max_wait_client, max_wait; + max_wait_server = ctx_buffer_time_remaining( &outbuf[0] ); + max_wait_client = ctx_buffer_time_remaining( &outbuf[1] ); + + max_wait = (unsigned) -1; + + if( max_wait_server == 0 ) + ctx_buffer_flush( &outbuf[0] ); + else + max_wait = max_wait_server; + + if( max_wait_client == 0 ) + ctx_buffer_flush( &outbuf[1] ); + else + { + if( max_wait_client < max_wait ) + max_wait = max_wait_client; + } + + if( max_wait != (unsigned) -1 ) + { + tm.tv_sec = max_wait / 1000; + tm.tv_usec = ( max_wait % 1000 ) * 1000; + + tm_ptr = &tm; + } + else + { + tm_ptr = NULL; + } + } +#endif /* MBEDTLS_TIMING_C */ + + FD_ZERO( &read_fds ); + FD_SET( server_fd.fd, &read_fds ); + FD_SET( client_fd.fd, &read_fds ); + FD_SET( listen_fd.fd, &read_fds ); + + if( ( ret = select( nb_fds, &read_fds, NULL, NULL, tm_ptr ) ) < 0 ) + { + perror( "select" ); + goto exit; + } + + if( FD_ISSET( listen_fd.fd, &read_fds ) ) + goto accept; + + if( FD_ISSET( client_fd.fd, &read_fds ) ) + { + if( ( ret = handle_message( "S <- C", + &server_fd, &client_fd ) ) != 0 ) + goto accept; + } + + if( FD_ISSET( server_fd.fd, &read_fds ) ) + { + if( ( ret = handle_message( "S -> C", + &client_fd, &server_fd ) ) != 0 ) + goto accept; + } + + } + + 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: -0x%04X - %s\n\n", - ret, error_buf ); + fflush( stdout ); + } +#endif + + for( delay_idx = 0; delay_idx < MAX_DELAYED_HS; delay_idx++ ) + { + mbedtls_free( opt.delay_cli + delay_idx ); + mbedtls_free( opt.delay_srv + delay_idx ); + } + + mbedtls_net_free( &client_fd ); + mbedtls_net_free( &server_fd ); + mbedtls_net_free( &listen_fd ); + +#if defined(_WIN32) + mbedtls_printf( " Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( exit_code ); +} + +#endif /* MBEDTLS_NET_C */ diff --git a/programs/test/udp_proxy_wrapper.sh b/programs/test/udp_proxy_wrapper.sh new file mode 100755 index 000000000..29033d5d1 --- /dev/null +++ b/programs/test/udp_proxy_wrapper.sh @@ -0,0 +1,117 @@ +#!/bin/sh +# -*-sh-basic-offset: 4-*- +# Usage: udp_proxy_wrapper.sh [PROXY_PARAM...] -- [SERVER_PARAM...] + +set -u + +MBEDTLS_BASE="$(dirname -- "$0")/../.." +TPXY_BIN="$MBEDTLS_BASE/programs/test/udp_proxy" +SRV_BIN="$MBEDTLS_BASE/programs/ssl/ssl_server2" + +: ${VERBOSE:=0} + +stop_proxy() { + if [ -n "${tpxy_pid:-}" ]; then + echo + echo " * Killing proxy (pid $tpxy_pid) ..." + kill $tpxy_pid + fi +} + +stop_server() { + if [ -n "${srv_pid:-}" ]; then + echo + echo " * Killing server (pid $srv_pid) ..." + kill $srv_pid >/dev/null 2>/dev/null + fi +} + +cleanup() { + stop_server + stop_proxy + exit 129 +} + +trap cleanup INT TERM HUP + +# Extract the proxy parameters +tpxy_cmd_snippet='"$TPXY_BIN"' +while [ $# -ne 0 ] && [ "$1" != "--" ]; do + tail="$1" quoted="" + while [ -n "$tail" ]; do + case "$tail" in + *\'*) quoted="${quoted}${tail%%\'*}'\\''" tail="${tail#*\'}";; + *) quoted="${quoted}${tail}"; tail=; false;; + esac + done + tpxy_cmd_snippet="$tpxy_cmd_snippet '$quoted'" + shift +done +unset tail quoted +if [ $# -eq 0 ]; then + echo " * No server arguments (must be preceded by \" -- \") - exit" + exit 3 +fi +shift + +dtls_enabled= +ipv6_in_use= +server_port_orig= +server_addr_orig= +for param; do + case "$param" in + server_port=*) server_port_orig="${param#*=}";; + server_addr=*:*) server_addr_orig="${param#*=}"; ipv6_in_use=1;; + server_addr=*) server_addr_orig="${param#*=}";; + dtls=[!0]*) dtls_enabled=1;; + esac +done + +if [ -z "$dtls_enabled" ] || [ -n "$ipv6_in_use" ]; then + echo >&2 "$0: Couldn't find DTLS enabling, or IPv6 is in use - immediate fallback to server application..." + if [ $VERBOSE -gt 0 ]; then + echo "[ $SRV_BIN $* ]" + fi + exec "$SRV_BIN" "$@" +fi + +if [ -z "$server_port_orig" ]; then + server_port_orig=4433 +fi +echo " * Server port: $server_port_orig" +tpxy_cmd_snippet="$tpxy_cmd_snippet \"listen_port=\$server_port_orig\"" +tpxy_cmd_snippet="$tpxy_cmd_snippet \"server_port=\$server_port\"" + +if [ -n "$server_addr_orig" ]; then + echo " * Server address: $server_addr_orig" + tpxy_cmd_snippet="$tpxy_cmd_snippet \"server_addr=\$server_addr_orig\"" + tpxy_cmd_snippet="$tpxy_cmd_snippet \"listen_addr=\$server_addr_orig\"" +fi + +server_port=$(( server_port_orig + 1 )) +set -- "$@" "server_port=$server_port" +echo " * Intermediate port: $server_port" + +echo " * Start proxy in background ..." +if [ $VERBOSE -gt 0 ]; then + echo "[ $tpxy_cmd_snippet ]" +fi +eval exec "$tpxy_cmd_snippet" >/dev/null 2>&1 & +tpxy_pid=$! + +if [ $VERBOSE -gt 0 ]; then + echo " * Proxy ID: $TPXY_PID" +fi + +echo " * Starting server ..." +if [ $VERBOSE -gt 0 ]; then + echo "[ $SRV_BIN $* ]" +fi + +exec "$SRV_BIN" "$@" >&2 & +srv_pid=$! + +wait $srv_pid + +stop_proxy +return 0 diff --git a/programs/x509/CMakeLists.txt b/programs/x509/CMakeLists.txt new file mode 100644 index 000000000..39b8b5bab --- /dev/null +++ b/programs/x509/CMakeLists.txt @@ -0,0 +1,30 @@ +set(libs + mbedtls +) + +if(USE_PKCS11_HELPER_LIBRARY) + set(libs ${libs} pkcs11-helper) +endif(USE_PKCS11_HELPER_LIBRARY) + +if(ENABLE_ZLIB_SUPPORT) + set(libs ${libs} ${ZLIB_LIBRARIES}) +endif(ENABLE_ZLIB_SUPPORT) + +add_executable(cert_app cert_app.c) +target_link_libraries(cert_app ${libs}) + +add_executable(crl_app crl_app.c) +target_link_libraries(crl_app ${libs}) + +add_executable(req_app req_app.c) +target_link_libraries(req_app ${libs}) + +add_executable(cert_req cert_req.c) +target_link_libraries(cert_req ${libs}) + +add_executable(cert_write cert_write.c) +target_link_libraries(cert_write ${libs}) + +install(TARGETS cert_app crl_app req_app cert_req cert_write + DESTINATION "bin" + PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE) diff --git a/programs/x509/cert_app.c b/programs/x509/cert_app.c new file mode 100644 index 000000000..38fbd51bf --- /dev/null +++ b/programs/x509/cert_app.c @@ -0,0 +1,515 @@ +/* + * Certificate reading application + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_CTR_DRBG_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_X509_CRT_PARSE_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_CTR_DRBG_C not defined.\n"); + return( 0 ); +} +#else + +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/net_sockets.h" +#include "mbedtls/ssl.h" +#include "mbedtls/x509.h" +#include "mbedtls/debug.h" + +#include +#include +#include + +#define MODE_NONE 0 +#define MODE_FILE 1 +#define MODE_SSL 2 + +#define DFL_MODE MODE_NONE +#define DFL_FILENAME "cert.crt" +#define DFL_CA_FILE "" +#define DFL_CRL_FILE "" +#define DFL_CA_PATH "" +#define DFL_SERVER_NAME "localhost" +#define DFL_SERVER_PORT "4433" +#define DFL_DEBUG_LEVEL 0 +#define DFL_PERMISSIVE 0 + +#define USAGE_IO \ + " ca_file=%%s The single file containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (none)\n" \ + " crl_file=%%s The single CRL file you want to use\n" \ + " default: \"\" (none)\n" \ + " ca_path=%%s The path containing the top-level CA(s) you fully trust\n" \ + " default: \"\" (none) (overrides ca_file)\n" + +#define USAGE \ + "\n usage: cert_app param=<>...\n" \ + "\n acceptable parameters:\n" \ + " mode=file|ssl default: none\n" \ + " filename=%%s default: cert.crt\n" \ + USAGE_IO \ + " server_name=%%s default: localhost\n" \ + " server_port=%%d default: 4433\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " permissive=%%d default: 0 (disabled)\n" \ + "\n" + +#if defined(MBEDTLS_CHECK_PARAMS) +#define mbedtls_exit exit +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +/* + * global options + */ +struct options +{ + int mode; /* the mode to run the application in */ + const char *filename; /* filename of the certificate file */ + const char *ca_file; /* the file with the CA certificate(s) */ + const char *crl_file; /* the file with the CRL to use */ + const char *ca_path; /* the path with the CA certificate(s) reside */ + 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 permissive; /* permissive parsing */ +} 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 my_verify( void *data, mbedtls_x509_crt *crt, int depth, uint32_t *flags ) +{ + char buf[1024]; + ((void) data); + + mbedtls_printf( "\nVerify requested for (Depth %d):\n", depth ); + mbedtls_x509_crt_info( buf, sizeof( buf ) - 1, "", crt ); + mbedtls_printf( "%s", buf ); + + if ( ( *flags ) == 0 ) + mbedtls_printf( " This certificate has no flags\n" ); + else + { + mbedtls_x509_crt_verify_info( buf, sizeof( buf ), " ! ", *flags ); + mbedtls_printf( "%s\n", buf ); + } + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_net_context server_fd; + unsigned char buf[1024]; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_ssl_context ssl; + mbedtls_ssl_config conf; + mbedtls_x509_crt cacert; + mbedtls_x509_crl cacrl; + int i, j; + uint32_t flags; + int verify = 0; + char *p, *q; + const char *pers = "cert_app"; + + /* + * Set to sane values + */ + mbedtls_net_init( &server_fd ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_ssl_init( &ssl ); + mbedtls_ssl_config_init( &conf ); + mbedtls_x509_crt_init( &cacert ); +#if defined(MBEDTLS_X509_CRL_PARSE_C) + mbedtls_x509_crl_init( &cacrl ); +#else + /* Zeroize structure as CRL parsing is not supported and we have to pass + it to the verify function */ + memset( &cacrl, 0, sizeof(mbedtls_x509_crl) ); +#endif + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.mode = DFL_MODE; + opt.filename = DFL_FILENAME; + opt.ca_file = DFL_CA_FILE; + opt.crl_file = DFL_CRL_FILE; + opt.ca_path = DFL_CA_PATH; + opt.server_name = DFL_SERVER_NAME; + opt.server_port = DFL_SERVER_PORT; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.permissive = DFL_PERMISSIVE; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + for( j = 0; p + j < q; j++ ) + { + if( argv[i][j] >= 'A' && argv[i][j] <= 'Z' ) + argv[i][j] |= 0x20; + } + + if( strcmp( p, "mode" ) == 0 ) + { + if( strcmp( q, "file" ) == 0 ) + opt.mode = MODE_FILE; + else if( strcmp( q, "ssl" ) == 0 ) + opt.mode = MODE_SSL; + else + goto usage; + } + else if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "ca_file" ) == 0 ) + opt.ca_file = q; + else if( strcmp( p, "crl_file" ) == 0 ) + opt.crl_file = q; + else if( strcmp( p, "ca_path" ) == 0 ) + opt.ca_path = q; + else 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, "permissive" ) == 0 ) + { + opt.permissive = atoi( q ); + if( opt.permissive < 0 || opt.permissive > 1 ) + goto usage; + } + else + goto usage; + } + + /* + * 1.1. Load the trusted CA + */ + mbedtls_printf( " . Loading the CA root certificate ..." ); + fflush( stdout ); + + if( strlen( opt.ca_path ) ) + { + if( ( ret = mbedtls_x509_crt_parse_path( &cacert, opt.ca_path ) ) < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_path returned -0x%x\n\n", -ret ); + goto exit; + } + + verify = 1; + } + else if( strlen( opt.ca_file ) ) + { + if( ( ret = mbedtls_x509_crt_parse_file( &cacert, opt.ca_file ) ) < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned -0x%x\n\n", -ret ); + goto exit; + } + + verify = 1; + } + + mbedtls_printf( " ok (%d skipped)\n", ret ); + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + if( strlen( opt.crl_file ) ) + { + if( ( ret = mbedtls_x509_crl_parse_file( &cacrl, opt.crl_file ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crl_parse returned -0x%x\n\n", -ret ); + goto exit; + } + + verify = 1; + } +#endif + + if( opt.mode == MODE_FILE ) + { + mbedtls_x509_crt crt; + mbedtls_x509_crt *cur = &crt; + mbedtls_x509_crt_init( &crt ); + + /* + * 1.1. Load the certificate(s) + */ + mbedtls_printf( "\n . Loading the certificate(s) ..." ); + fflush( stdout ); + + ret = mbedtls_x509_crt_parse_file( &crt, opt.filename ); + + if( ret < 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file returned %d\n\n", ret ); + mbedtls_x509_crt_free( &crt ); + goto exit; + } + + if( opt.permissive == 0 && ret > 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse failed to parse %d certificates\n\n", ret ); + mbedtls_x509_crt_free( &crt ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the certificate(s) + */ + while( cur != NULL ) + { + mbedtls_printf( " . Peer certificate information ...\n" ); + ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", + cur ); + if( ret == -1 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_info returned %d\n\n", ret ); + mbedtls_x509_crt_free( &crt ); + goto exit; + } + + mbedtls_printf( "%s\n", buf ); + + cur = cur->next; + } + + /* + * 1.3 Verify the certificate + */ + if( verify ) + { + mbedtls_printf( " . Verifying X.509 certificate..." ); + + if( ( ret = mbedtls_x509_crt_verify( &crt, &cacert, &cacrl, NULL, &flags, + my_verify, NULL ) ) != 0 ) + { + char vrfy_buf[512]; + + mbedtls_printf( " failed\n" ); + + mbedtls_x509_crt_verify_info( vrfy_buf, sizeof( vrfy_buf ), " ! ", flags ); + + mbedtls_printf( "%s\n", vrfy_buf ); + } + else + mbedtls_printf( " ok\n" ); + } + + mbedtls_x509_crt_free( &crt ); + } + else if( opt.mode == MODE_SSL ) + { + /* + * 1. 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 ssl_exit; + } + + mbedtls_printf( " ok\n" ); + +#if defined(MBEDTLS_DEBUG_C) + mbedtls_debug_set_threshold( opt.debug_level ); +#endif + + /* + * 2. Start the connection + */ + mbedtls_printf( " . SSL connection 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 ssl_exit; + } + + /* + * 3. Setup stuff + */ + 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; + } + + if( verify ) + { + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_REQUIRED ); + mbedtls_ssl_conf_ca_chain( &conf, &cacert, NULL ); + mbedtls_ssl_conf_verify( &conf, my_verify, NULL ); + } + else + mbedtls_ssl_conf_authmode( &conf, MBEDTLS_SSL_VERIFY_NONE ); + + 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 ssl_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 ssl_exit; + } + + mbedtls_ssl_set_bio( &ssl, &server_fd, mbedtls_net_send, mbedtls_net_recv, NULL ); + + /* + * 4. Handshake + */ + 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 ssl_exit; + } + } + + mbedtls_printf( " ok\n" ); + + /* + * 5. Print the certificate + */ +#if !defined(MBEDTLS_SSL_KEEP_PEER_CERTIFICATE) + mbedtls_printf( " . Peer certificate information ... skipped\n" ); +#else + mbedtls_printf( " . Peer certificate information ...\n" ); + ret = mbedtls_x509_crt_info( (char *) buf, sizeof( buf ) - 1, " ", + mbedtls_ssl_get_peer_cert( &ssl ) ); + if( ret == -1 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crt_info returned %d\n\n", ret ); + goto ssl_exit; + } + + mbedtls_printf( "%s\n", buf ); +#endif /* MBEDTLS_SSL_KEEP_PEER_CERTIFICATE */ + + mbedtls_ssl_close_notify( &ssl ); + +ssl_exit: + mbedtls_ssl_free( &ssl ); + mbedtls_ssl_config_free( &conf ); + } + else + goto usage; + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + mbedtls_net_free( &server_fd ); + mbedtls_x509_crt_free( &cacert ); +#if defined(MBEDTLS_X509_CRL_PARSE_C) + mbedtls_x509_crl_free( &cacrl ); +#endif + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_ENTROPY_C && MBEDTLS_SSL_TLS_C && + MBEDTLS_SSL_CLI_C && MBEDTLS_NET_C && MBEDTLS_RSA_C && + MBEDTLS_X509_CRT_PARSE_C && MBEDTLS_FS_IO && MBEDTLS_CTR_DRBG_C */ diff --git a/programs/x509/cert_req.c b/programs/x509/cert_req.c new file mode 100644 index 000000000..d25ad4c56 --- /dev/null +++ b/programs/x509/cert_req.c @@ -0,0 +1,453 @@ +/* + * Certificate request generation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_X509_CSR_WRITE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_PK_PARSE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_PEM_WRITE_C) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_X509_CSR_WRITE_C and/or MBEDTLS_FS_IO and/or " + "MBEDTLS_PK_PARSE_C and/or MBEDTLS_SHA256_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C " + "not defined.\n"); + return( 0 ); +} +#else + +#include "mbedtls/x509_csr.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#define DFL_FILENAME "keyfile.key" +#define DFL_PASSWORD NULL +#define DFL_DEBUG_LEVEL 0 +#define DFL_OUTPUT_FILENAME "cert.req" +#define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK" +#define DFL_KEY_USAGE 0 +#define DFL_FORCE_KEY_USAGE 0 +#define DFL_NS_CERT_TYPE 0 +#define DFL_FORCE_NS_CERT_TYPE 0 +#define DFL_MD_ALG MBEDTLS_MD_SHA256 + +#define USAGE \ + "\n usage: cert_req param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: keyfile.key\n" \ + " password=%%s default: NULL\n" \ + " debug_level=%%d default: 0 (disabled)\n" \ + " output_file=%%s default: cert.req\n" \ + " subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \ + " key_usage=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " digital_signature\n" \ + " non_repudiation\n" \ + " key_encipherment\n" \ + " data_encipherment\n" \ + " key_agreement\n" \ + " key_cert_sign\n" \ + " crl_sign\n" \ + " force_key_usage=0/1 default: off\n" \ + " Add KeyUsage even if it is empty\n" \ + " ns_cert_type=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " ssl_client\n" \ + " ssl_server\n" \ + " email\n" \ + " object_signing\n" \ + " ssl_ca\n" \ + " email_ca\n" \ + " object_signing_ca\n" \ + " force_ns_cert_type=0/1 default: off\n" \ + " Add NsCertType even if it is empty\n" \ + " md=%%s default: SHA256\n" \ + " possible values:\n" \ + " MD4, MD5, SHA1\n" \ + " SHA224, SHA256\n" \ + " SHA384, SHA512\n" \ + "\n" + +#if defined(MBEDTLS_CHECK_PARAMS) +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +/* + * global options + */ +struct options +{ + const char *filename; /* filename of the key file */ + const char *password; /* password for the key file */ + int debug_level; /* level of debugging */ + const char *output_file; /* where to store the constructed key file */ + const char *subject_name; /* subject name for certificate request */ + unsigned char key_usage; /* key usage flags */ + int force_key_usage; /* Force adding the KeyUsage extension */ + unsigned char ns_cert_type; /* NS cert type */ + int force_ns_cert_type; /* Force adding NsCertType extension */ + mbedtls_md_type_t md_alg; /* Hash algorithm used for signature. */ +} opt; + +int write_certificate_request( mbedtls_x509write_csr *req, const char *output_file, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + FILE *f; + unsigned char output_buf[4096]; + size_t len = 0; + + memset( output_buf, 0, 4096 ); + if( ( ret = mbedtls_x509write_csr_pem( req, output_buf, 4096, f_rng, p_rng ) ) < 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( output_buf, 1, len, f ) != len ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_pk_context key; + char buf[1024]; + int i; + char *p, *q, *r; + mbedtls_x509write_csr req; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const char *pers = "csr example app"; + + /* + * Set to sane values + */ + mbedtls_x509write_csr_init( &req ); + mbedtls_pk_init( &key ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + memset( buf, 0, sizeof( buf ) ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + opt.password = DFL_PASSWORD; + opt.debug_level = DFL_DEBUG_LEVEL; + opt.output_file = DFL_OUTPUT_FILENAME; + opt.subject_name = DFL_SUBJECT_NAME; + opt.key_usage = DFL_KEY_USAGE; + opt.force_key_usage = DFL_FORCE_KEY_USAGE; + opt.ns_cert_type = DFL_NS_CERT_TYPE; + opt.force_ns_cert_type = DFL_FORCE_NS_CERT_TYPE; + opt.md_alg = DFL_MD_ALG; + + for( i = 1; i < argc; i++ ) + { + + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else if( strcmp( p, "password" ) == 0 ) + opt.password = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = 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, "subject_name" ) == 0 ) + { + opt.subject_name = q; + } + else if( strcmp( p, "md" ) == 0 ) + { + if( strcmp( q, "SHA256" ) == 0 ) + { + opt.md_alg = MBEDTLS_MD_SHA256; + } + else if( strcmp( q, "SHA224" ) == 0 ) + { + opt.md_alg = MBEDTLS_MD_SHA224; + } + else +#if defined(MBEDTLS_MD5_C) + if( strcmp( q, "MD5" ) == 0 ) + { + opt.md_alg = MBEDTLS_MD_MD5; + } + else +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_MD4_C) + if( strcmp( q, "MD4" ) == 0 ) + { + opt.md_alg = MBEDTLS_MD_MD4; + } + else +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + if( strcmp( q, "SHA1" ) == 0 ) + { + opt.md_alg = MBEDTLS_MD_SHA1; + } + else +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA512_C) + if( strcmp( q, "SHA384" ) == 0 ) + { + opt.md_alg = MBEDTLS_MD_SHA384; + } + else + if( strcmp( q, "SHA512" ) == 0 ) + { + opt.md_alg = MBEDTLS_MD_SHA512; + } + else +#endif /* MBEDTLS_SHA512_C */ + { + goto usage; + } + } + else if( strcmp( p, "key_usage" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "digital_signature" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + else if( strcmp( q, "non_repudiation" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION; + else if( strcmp( q, "key_encipherment" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + else if( strcmp( q, "data_encipherment" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT; + else if( strcmp( q, "key_agreement" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT; + else if( strcmp( q, "key_cert_sign" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN; + else if( strcmp( q, "crl_sign" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN; + else + goto usage; + + q = r; + } + } + else if( strcmp( p, "force_key_usage" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.force_key_usage = 0; break; + case 1: opt.force_key_usage = 1; break; + default: goto usage; + } + } + else if( strcmp( p, "ns_cert_type" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "ssl_client" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT; + else if( strcmp( q, "ssl_server" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER; + else if( strcmp( q, "email" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL; + else if( strcmp( q, "object_signing" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING; + else if( strcmp( q, "ssl_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA; + else if( strcmp( q, "email_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA; + else if( strcmp( q, "object_signing_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA; + else + goto usage; + + q = r; + } + } + else if( strcmp( p, "force_ns_cert_type" ) == 0 ) + { + switch( atoi( q ) ) + { + case 0: opt.force_ns_cert_type = 0; break; + case 1: opt.force_ns_cert_type = 1; break; + default: goto usage; + } + } + else + goto usage; + } + + mbedtls_x509write_csr_set_md_alg( &req, opt.md_alg ); + + if( opt.key_usage || opt.force_key_usage == 1 ) + mbedtls_x509write_csr_set_key_usage( &req, opt.key_usage ); + + if( opt.ns_cert_type || opt.force_ns_cert_type == 1 ) + mbedtls_x509write_csr_set_ns_cert_type( &req, opt.ns_cert_type ); + + /* + * 0. Seed the PRNG + */ + mbedtls_printf( " . 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", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.0. Check the subject name for validity + */ + mbedtls_printf( " . Checking subject name..." ); + fflush( stdout ); + + if( ( ret = mbedtls_x509write_csr_set_subject_name( &req, opt.subject_name ) ) != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509write_csr_set_subject_name returned %d", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.1. Load the key + */ + mbedtls_printf( " . Loading the private key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_keyfile( &key, opt.filename, opt.password ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile returned %d", ret ); + goto exit; + } + + mbedtls_x509write_csr_set_key( &req, &key ); + + mbedtls_printf( " ok\n" ); + + /* + * 1.2. Writing the request + */ + mbedtls_printf( " . Writing the certificate request ..." ); + fflush( stdout ); + + if( ( ret = write_certificate_request( &req, opt.output_file, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_printf( " failed\n ! write_certifcate_request %d", ret ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + + if( exit_code != MBEDTLS_EXIT_SUCCESS ) + { +#ifdef MBEDTLS_ERROR_C + mbedtls_strerror( ret, buf, sizeof( buf ) ); + mbedtls_printf( " - %s\n", buf ); +#else + mbedtls_printf("\n"); +#endif + } + + mbedtls_x509write_csr_free( &req ); + mbedtls_pk_free( &key ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( exit_code ); +} +#endif /* MBEDTLS_X509_CSR_WRITE_C && MBEDTLS_PK_PARSE_C && MBEDTLS_FS_IO && + MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_PEM_WRITE_C */ diff --git a/programs/x509/cert_write.c b/programs/x509/cert_write.c new file mode 100644 index 000000000..cd39108f2 --- /dev/null +++ b/programs/x509/cert_write.c @@ -0,0 +1,825 @@ +/* + * Certificate generation and signing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_X509_CRT_WRITE_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) || \ + !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) || \ + !defined(MBEDTLS_ERROR_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_PEM_WRITE_C) +int main( void ) +{ + mbedtls_printf( "MBEDTLS_X509_CRT_WRITE_C and/or MBEDTLS_X509_CRT_PARSE_C and/or " + "MBEDTLS_FS_IO and/or MBEDTLS_SHA256_C and/or " + "MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or " + "MBEDTLS_ERROR_C not defined.\n"); + return( 0 ); +} +#else + +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509_csr.h" +#include "mbedtls/entropy.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/md.h" +#include "mbedtls/error.h" + +#include +#include +#include + +#if defined(MBEDTLS_X509_CSR_PARSE_C) +#define USAGE_CSR \ + " request_file=%%s default: (empty)\n" \ + " If request_file is specified, subject_key,\n" \ + " subject_pwd and subject_name are ignored!\n" +#else +#define USAGE_CSR "" +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + +#define DFL_ISSUER_CRT "" +#define DFL_REQUEST_FILE "" +#define DFL_SUBJECT_KEY "subject.key" +#define DFL_ISSUER_KEY "ca.key" +#define DFL_SUBJECT_PWD "" +#define DFL_ISSUER_PWD "" +#define DFL_OUTPUT_FILENAME "cert.crt" +#define DFL_SUBJECT_NAME "CN=Cert,O=mbed TLS,C=UK" +#define DFL_ISSUER_NAME "CN=CA,O=mbed TLS,C=UK" +#define DFL_NOT_BEFORE "20010101000000" +#define DFL_NOT_AFTER "20301231235959" +#define DFL_SERIAL "1" +#define DFL_SELFSIGN 0 +#define DFL_IS_CA 0 +#define DFL_MAX_PATHLEN -1 +#define DFL_KEY_USAGE 0 +#define DFL_NS_CERT_TYPE 0 +#define DFL_VERSION 3 +#define DFL_AUTH_IDENT 1 +#define DFL_SUBJ_IDENT 1 +#define DFL_CONSTRAINTS 1 +#define DFL_DIGEST MBEDTLS_MD_SHA256 + +#define USAGE \ + "\n usage: cert_write param=<>...\n" \ + "\n acceptable parameters:\n" \ + USAGE_CSR \ + " subject_key=%%s default: subject.key\n" \ + " subject_pwd=%%s default: (empty)\n" \ + " subject_name=%%s default: CN=Cert,O=mbed TLS,C=UK\n" \ + "\n" \ + " issuer_crt=%%s default: (empty)\n" \ + " If issuer_crt is specified, issuer_name is\n" \ + " ignored!\n" \ + " issuer_name=%%s default: CN=CA,O=mbed TLS,C=UK\n" \ + "\n" \ + " selfsign=%%d default: 0 (false)\n" \ + " If selfsign is enabled, issuer_name and\n" \ + " issuer_key are required (issuer_crt and\n" \ + " subject_* are ignored\n" \ + " issuer_key=%%s default: ca.key\n" \ + " issuer_pwd=%%s default: (empty)\n" \ + " output_file=%%s default: cert.crt\n" \ + " serial=%%s default: 1\n" \ + " not_before=%%s default: 20010101000000\n"\ + " not_after=%%s default: 20301231235959\n"\ + " is_ca=%%d default: 0 (disabled)\n" \ + " max_pathlen=%%d default: -1 (none)\n" \ + " md=%%s default: SHA256\n" \ + " Supported values:\n" \ + " MD5, SHA1, SHA256, SHA512\n"\ + " version=%%d default: 3\n" \ + " Possible values: 1, 2, 3\n"\ + " subject_identifier=%%s default: 1\n" \ + " Possible values: 0, 1\n" \ + " (Considered for v3 only)\n"\ + " authority_identifier=%%s default: 1\n" \ + " Possible values: 0, 1\n" \ + " (Considered for v3 only)\n"\ + " basic_constraints=%%d default: 1\n" \ + " Possible values: 0, 1\n" \ + " (Considered for v3 only)\n"\ + " key_usage=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " digital_signature\n" \ + " non_repudiation\n" \ + " key_encipherment\n" \ + " data_encipherment\n" \ + " key_agreement\n" \ + " key_cert_sign\n" \ + " crl_sign\n" \ + " (Considered for v3 only)\n"\ + " ns_cert_type=%%s default: (empty)\n" \ + " Comma-separated-list of values:\n" \ + " ssl_client\n" \ + " ssl_server\n" \ + " email\n" \ + " object_signing\n" \ + " ssl_ca\n" \ + " email_ca\n" \ + " object_signing_ca\n" \ + "\n" + +#if defined(MBEDTLS_CHECK_PARAMS) +#define mbedtls_exit exit +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +/* + * global options + */ +struct options +{ + const char *issuer_crt; /* filename of the issuer certificate */ + const char *request_file; /* filename of the certificate request */ + const char *subject_key; /* filename of the subject key file */ + const char *issuer_key; /* filename of the issuer key file */ + const char *subject_pwd; /* password for the subject key file */ + const char *issuer_pwd; /* password for the issuer key file */ + const char *output_file; /* where to store the constructed CRT */ + const char *subject_name; /* subject name for certificate */ + const char *issuer_name; /* issuer name for certificate */ + const char *not_before; /* validity period not before */ + const char *not_after; /* validity period not after */ + const char *serial; /* serial number string */ + int selfsign; /* selfsign the certificate */ + int is_ca; /* is a CA certificate */ + int max_pathlen; /* maximum CA path length */ + int authority_identifier; /* add authority identifier to CRT */ + int subject_identifier; /* add subject identifier to CRT */ + int basic_constraints; /* add basic constraints ext to CRT */ + int version; /* CRT version */ + mbedtls_md_type_t md; /* Hash used for signing */ + unsigned char key_usage; /* key usage flags */ + unsigned char ns_cert_type; /* NS cert type */ +} opt; + +int write_certificate( mbedtls_x509write_cert *crt, const char *output_file, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + FILE *f; + unsigned char output_buf[4096]; + size_t len = 0; + + memset( output_buf, 0, 4096 ); + if( ( ret = mbedtls_x509write_crt_pem( crt, output_buf, 4096, + f_rng, p_rng ) ) < 0 ) + return( ret ); + + len = strlen( (char *) output_buf ); + + if( ( f = fopen( output_file, "w" ) ) == NULL ) + return( -1 ); + + if( fwrite( output_buf, 1, len, f ) != len ) + { + fclose( f ); + return( -1 ); + } + + fclose( f ); + + return( 0 ); +} + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + mbedtls_x509_crt issuer_crt; + mbedtls_pk_context loaded_issuer_key, loaded_subject_key; + mbedtls_pk_context *issuer_key = &loaded_issuer_key, + *subject_key = &loaded_subject_key; + char buf[1024]; + char issuer_name[256]; + int i; + char *p, *q, *r; +#if defined(MBEDTLS_X509_CSR_PARSE_C) + char subject_name[256]; + mbedtls_x509_csr csr; +#endif + mbedtls_x509write_cert crt; + mbedtls_mpi serial; + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const char *pers = "crt example app"; + + /* + * Set to sane values + */ + mbedtls_x509write_crt_init( &crt ); + mbedtls_pk_init( &loaded_issuer_key ); + mbedtls_pk_init( &loaded_subject_key ); + mbedtls_mpi_init( &serial ); + mbedtls_ctr_drbg_init( &ctr_drbg ); + mbedtls_entropy_init( &entropy ); +#if defined(MBEDTLS_X509_CSR_PARSE_C) + mbedtls_x509_csr_init( &csr ); +#endif + mbedtls_x509_crt_init( &issuer_crt ); + memset( buf, 0, 1024 ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.issuer_crt = DFL_ISSUER_CRT; + opt.request_file = DFL_REQUEST_FILE; + opt.subject_key = DFL_SUBJECT_KEY; + opt.issuer_key = DFL_ISSUER_KEY; + opt.subject_pwd = DFL_SUBJECT_PWD; + opt.issuer_pwd = DFL_ISSUER_PWD; + opt.output_file = DFL_OUTPUT_FILENAME; + opt.subject_name = DFL_SUBJECT_NAME; + opt.issuer_name = DFL_ISSUER_NAME; + opt.not_before = DFL_NOT_BEFORE; + opt.not_after = DFL_NOT_AFTER; + opt.serial = DFL_SERIAL; + opt.selfsign = DFL_SELFSIGN; + opt.is_ca = DFL_IS_CA; + opt.max_pathlen = DFL_MAX_PATHLEN; + opt.key_usage = DFL_KEY_USAGE; + opt.ns_cert_type = DFL_NS_CERT_TYPE; + opt.version = DFL_VERSION - 1; + opt.md = DFL_DIGEST; + opt.subject_identifier = DFL_SUBJ_IDENT; + opt.authority_identifier = DFL_AUTH_IDENT; + opt.basic_constraints = DFL_CONSTRAINTS; + + for( i = 1; i < argc; i++ ) + { + + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "request_file" ) == 0 ) + opt.request_file = q; + else if( strcmp( p, "subject_key" ) == 0 ) + opt.subject_key = q; + else if( strcmp( p, "issuer_key" ) == 0 ) + opt.issuer_key = q; + else if( strcmp( p, "subject_pwd" ) == 0 ) + opt.subject_pwd = q; + else if( strcmp( p, "issuer_pwd" ) == 0 ) + opt.issuer_pwd = q; + else if( strcmp( p, "issuer_crt" ) == 0 ) + opt.issuer_crt = q; + else if( strcmp( p, "output_file" ) == 0 ) + opt.output_file = q; + else if( strcmp( p, "subject_name" ) == 0 ) + { + opt.subject_name = q; + } + else if( strcmp( p, "issuer_name" ) == 0 ) + { + opt.issuer_name = q; + } + else if( strcmp( p, "not_before" ) == 0 ) + { + opt.not_before = q; + } + else if( strcmp( p, "not_after" ) == 0 ) + { + opt.not_after = q; + } + else if( strcmp( p, "serial" ) == 0 ) + { + opt.serial = q; + } + else if( strcmp( p, "authority_identifier" ) == 0 ) + { + opt.authority_identifier = atoi( q ); + if( opt.authority_identifier != 0 && + opt.authority_identifier != 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "subject_identifier" ) == 0 ) + { + opt.subject_identifier = atoi( q ); + if( opt.subject_identifier != 0 && + opt.subject_identifier != 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "basic_constraints" ) == 0 ) + { + opt.basic_constraints = atoi( q ); + if( opt.basic_constraints != 0 && + opt.basic_constraints != 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "md" ) == 0 ) + { + if( strcmp( q, "SHA1" ) == 0 ) + opt.md = MBEDTLS_MD_SHA1; + else if( strcmp( q, "SHA256" ) == 0 ) + opt.md = MBEDTLS_MD_SHA256; + else if( strcmp( q, "SHA512" ) == 0 ) + opt.md = MBEDTLS_MD_SHA512; + else if( strcmp( q, "MD5" ) == 0 ) + opt.md = MBEDTLS_MD_MD5; + else + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "version" ) == 0 ) + { + opt.version = atoi( q ); + if( opt.version < 1 || opt.version > 3 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + opt.version--; + } + else if( strcmp( p, "selfsign" ) == 0 ) + { + opt.selfsign = atoi( q ); + if( opt.selfsign < 0 || opt.selfsign > 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "is_ca" ) == 0 ) + { + opt.is_ca = atoi( q ); + if( opt.is_ca < 0 || opt.is_ca > 1 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "max_pathlen" ) == 0 ) + { + opt.max_pathlen = atoi( q ); + if( opt.max_pathlen < -1 || opt.max_pathlen > 127 ) + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + } + else if( strcmp( p, "key_usage" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "digital_signature" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_DIGITAL_SIGNATURE; + else if( strcmp( q, "non_repudiation" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_NON_REPUDIATION; + else if( strcmp( q, "key_encipherment" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_ENCIPHERMENT; + else if( strcmp( q, "data_encipherment" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_DATA_ENCIPHERMENT; + else if( strcmp( q, "key_agreement" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_AGREEMENT; + else if( strcmp( q, "key_cert_sign" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_KEY_CERT_SIGN; + else if( strcmp( q, "crl_sign" ) == 0 ) + opt.key_usage |= MBEDTLS_X509_KU_CRL_SIGN; + else + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + + q = r; + } + } + else if( strcmp( p, "ns_cert_type" ) == 0 ) + { + while( q != NULL ) + { + if( ( r = strchr( q, ',' ) ) != NULL ) + *r++ = '\0'; + + if( strcmp( q, "ssl_client" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT; + else if( strcmp( q, "ssl_server" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER; + else if( strcmp( q, "email" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL; + else if( strcmp( q, "object_signing" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING; + else if( strcmp( q, "ssl_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_SSL_CA; + else if( strcmp( q, "email_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA; + else if( strcmp( q, "object_signing_ca" ) == 0 ) + opt.ns_cert_type |= MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA; + else + { + mbedtls_printf( "Invalid argument for option %s\n", p ); + goto usage; + } + + q = r; + } + } + else + goto usage; + } + + mbedtls_printf("\n"); + + /* + * 0. Seed the PRNG + */ + 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_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_ctr_drbg_seed returned %d - %s\n", + ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + // Parse serial to MPI + // + mbedtls_printf( " . Reading serial number..." ); + fflush( stdout ); + + if( ( ret = mbedtls_mpi_read_string( &serial, 10, opt.serial ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_mpi_read_string " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + // Parse issuer certificate if present + // + if( !opt.selfsign && strlen( opt.issuer_crt ) ) + { + /* + * 1.0.a. Load the certificates + */ + mbedtls_printf( " . Loading the issuer certificate ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_x509_crt_parse_file( &issuer_crt, opt.issuer_crt ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509_crt_parse_file " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = mbedtls_x509_dn_gets( issuer_name, sizeof(issuer_name), + &issuer_crt.subject ); + if( ret < 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + opt.issuer_name = issuer_name; + + mbedtls_printf( " ok\n" ); + } + +#if defined(MBEDTLS_X509_CSR_PARSE_C) + // Parse certificate request if present + // + if( !opt.selfsign && strlen( opt.request_file ) ) + { + /* + * 1.0.b. Load the CSR + */ + mbedtls_printf( " . Loading the certificate request ..." ); + fflush( stdout ); + + if( ( ret = mbedtls_x509_csr_parse_file( &csr, opt.request_file ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = mbedtls_x509_dn_gets( subject_name, sizeof(subject_name), + &csr.subject ); + if( ret < 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509_dn_gets " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + opt.subject_name = subject_name; + subject_key = &csr.pk; + + mbedtls_printf( " ok\n" ); + } +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + + /* + * 1.1. Load the keys + */ + if( !opt.selfsign && !strlen( opt.request_file ) ) + { + mbedtls_printf( " . Loading the subject key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_keyfile( &loaded_subject_key, opt.subject_key, + opt.subject_pwd ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + mbedtls_printf( " . Loading the issuer key ..." ); + fflush( stdout ); + + ret = mbedtls_pk_parse_keyfile( &loaded_issuer_key, opt.issuer_key, + opt.issuer_pwd ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_pk_parse_keyfile " + "returned -x%02x - %s\n\n", -ret, buf ); + goto exit; + } + + // Check if key and issuer certificate match + // + if( strlen( opt.issuer_crt ) ) + { + if( mbedtls_pk_check_pair( &issuer_crt.pk, issuer_key ) != 0 ) + { + mbedtls_printf( " failed\n ! issuer_key does not match " + "issuer certificate\n\n" ); + goto exit; + } + } + + mbedtls_printf( " ok\n" ); + + if( opt.selfsign ) + { + opt.subject_name = opt.issuer_name; + subject_key = issuer_key; + } + + mbedtls_x509write_crt_set_subject_key( &crt, subject_key ); + mbedtls_x509write_crt_set_issuer_key( &crt, issuer_key ); + + /* + * 1.0. Check the names for validity + */ + if( ( ret = mbedtls_x509write_crt_set_subject_name( &crt, opt.subject_name ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject_name " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + if( ( ret = mbedtls_x509write_crt_set_issuer_name( &crt, opt.issuer_name ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_issuer_name " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " . Setting certificate values ..." ); + fflush( stdout ); + + mbedtls_x509write_crt_set_version( &crt, opt.version ); + mbedtls_x509write_crt_set_md_alg( &crt, opt.md ); + + ret = mbedtls_x509write_crt_set_serial( &crt, &serial ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_serial " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + ret = mbedtls_x509write_crt_set_validity( &crt, opt.not_before, opt.not_after ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_validity " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.basic_constraints != 0 ) + { + mbedtls_printf( " . Adding the Basic Constraints extension ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_basic_constraints( &crt, opt.is_ca, + opt.max_pathlen ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! x509write_crt_set_basic_contraints " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + +#if defined(MBEDTLS_SHA1_C) + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.subject_identifier != 0 ) + { + mbedtls_printf( " . Adding the Subject Key Identifier ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_subject_key_identifier( &crt ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_subject" + "_key_identifier returned -0x%04x - %s\n\n", + -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.authority_identifier != 0 ) + { + mbedtls_printf( " . Adding the Authority Key Identifier ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_authority_key_identifier( &crt ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_authority_" + "key_identifier returned -0x%04x - %s\n\n", + -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } +#endif /* MBEDTLS_SHA1_C */ + + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.key_usage != 0 ) + { + mbedtls_printf( " . Adding the Key Usage extension ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_key_usage( &crt, opt.key_usage ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_key_usage " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + if( opt.version == MBEDTLS_X509_CRT_VERSION_3 && + opt.ns_cert_type != 0 ) + { + mbedtls_printf( " . Adding the NS Cert Type extension ..." ); + fflush( stdout ); + + ret = mbedtls_x509write_crt_set_ns_cert_type( &crt, opt.ns_cert_type ); + if( ret != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! mbedtls_x509write_crt_set_ns_cert_type " + "returned -0x%04x - %s\n\n", -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + } + + /* + * 1.2. Writing the certificate + */ + mbedtls_printf( " . Writing the certificate..." ); + fflush( stdout ); + + if( ( ret = write_certificate( &crt, opt.output_file, + mbedtls_ctr_drbg_random, &ctr_drbg ) ) != 0 ) + { + mbedtls_strerror( ret, buf, 1024 ); + mbedtls_printf( " failed\n ! write_certificate -0x%04x - %s\n\n", + -ret, buf ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: +#if defined(MBEDTLS_X509_CSR_PARSE_C) + mbedtls_x509_csr_free( &csr ); +#endif /* MBEDTLS_X509_CSR_PARSE_C */ + mbedtls_x509_crt_free( &issuer_crt ); + mbedtls_x509write_crt_free( &crt ); + mbedtls_pk_free( &loaded_subject_key ); + mbedtls_pk_free( &loaded_issuer_key ); + mbedtls_mpi_free( &serial ); + mbedtls_ctr_drbg_free( &ctr_drbg ); + mbedtls_entropy_free( &entropy ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( exit_code ); +} +#endif /* MBEDTLS_X509_CRT_WRITE_C && MBEDTLS_X509_CRT_PARSE_C && + MBEDTLS_FS_IO && MBEDTLS_ENTROPY_C && MBEDTLS_CTR_DRBG_C && + MBEDTLS_ERROR_C && MBEDTLS_PEM_WRITE_C */ diff --git a/programs/x509/crl_app.c b/programs/x509/crl_app.c new file mode 100644 index 000000000..a95157067 --- /dev/null +++ b/programs/x509/crl_app.c @@ -0,0 +1,164 @@ +/* + * CRL reading application + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_RSA_C) || \ + !defined(MBEDTLS_X509_CRL_PARSE_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_X509_CRL_PARSE_C and/or MBEDTLS_FS_IO not defined.\n"); + return( 0 ); +} +#else + +#include "mbedtls/x509_crl.h" + +#include +#include +#include + +#define DFL_FILENAME "crl.pem" +#define DFL_DEBUG_LEVEL 0 + +#define USAGE \ + "\n usage: crl_app param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: crl.pem\n" \ + "\n" + +#if defined(MBEDTLS_CHECK_PARAMS) +#define mbedtls_exit exit +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +/* + * global options + */ +struct options +{ + const char *filename; /* filename of the certificate file */ +} opt; + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + unsigned char buf[100000]; + mbedtls_x509_crl crl; + int i; + char *p, *q; + + /* + * Set to sane values + */ + mbedtls_x509_crl_init( &crl ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else + goto usage; + } + + /* + * 1.1. Load the CRL + */ + mbedtls_printf( "\n . Loading the CRL ..." ); + fflush( stdout ); + + ret = mbedtls_x509_crl_parse_file( &crl, opt.filename ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crl_parse_file returned %d\n\n", ret ); + mbedtls_x509_crl_free( &crl ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the CRL + */ + mbedtls_printf( " . CRL information ...\n" ); + ret = mbedtls_x509_crl_info( (char *) buf, sizeof( buf ) - 1, " ", &crl ); + if( ret == -1 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_crl_info returned %d\n\n", ret ); + mbedtls_x509_crl_free( &crl ); + goto exit; + } + + mbedtls_printf( "%s\n", buf ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_x509_crl_free( &crl ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_X509_CRL_PARSE_C && + MBEDTLS_FS_IO */ diff --git a/programs/x509/req_app.c b/programs/x509/req_app.c new file mode 100644 index 000000000..04ad119f7 --- /dev/null +++ b/programs/x509/req_app.c @@ -0,0 +1,164 @@ +/* + * Certificate request reading application + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#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_RSA_C) || \ + !defined(MBEDTLS_X509_CSR_PARSE_C) || !defined(MBEDTLS_FS_IO) +int main( void ) +{ + mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_RSA_C and/or " + "MBEDTLS_X509_CSR_PARSE_C and/or MBEDTLS_FS_IO not defined.\n"); + return( 0 ); +} +#else + +#include "mbedtls/x509_csr.h" + +#include +#include +#include + +#define DFL_FILENAME "cert.req" +#define DFL_DEBUG_LEVEL 0 + +#define USAGE \ + "\n usage: req_app param=<>...\n" \ + "\n acceptable parameters:\n" \ + " filename=%%s default: cert.req\n" \ + "\n" + +#if defined(MBEDTLS_CHECK_PARAMS) +#define mbedtls_exit exit +void mbedtls_param_failed( const char *failure_condition, + const char *file, + int line ) +{ + mbedtls_printf( "%s:%i: Input param failed - %s\n", + file, line, failure_condition ); + mbedtls_exit( MBEDTLS_EXIT_FAILURE ); +} +#endif + +/* + * global options + */ +struct options +{ + const char *filename; /* filename of the certificate request */ +} opt; + +int main( int argc, char *argv[] ) +{ + int ret = 1; + int exit_code = MBEDTLS_EXIT_FAILURE; + unsigned char buf[100000]; + mbedtls_x509_csr csr; + int i; + char *p, *q; + + /* + * Set to sane values + */ + mbedtls_x509_csr_init( &csr ); + + if( argc == 0 ) + { + usage: + mbedtls_printf( USAGE ); + goto exit; + } + + opt.filename = DFL_FILENAME; + + for( i = 1; i < argc; i++ ) + { + p = argv[i]; + if( ( q = strchr( p, '=' ) ) == NULL ) + goto usage; + *q++ = '\0'; + + if( strcmp( p, "filename" ) == 0 ) + opt.filename = q; + else + goto usage; + } + + /* + * 1.1. Load the CSR + */ + mbedtls_printf( "\n . Loading the CSR ..." ); + fflush( stdout ); + + ret = mbedtls_x509_csr_parse_file( &csr, opt.filename ); + + if( ret != 0 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_csr_parse_file returned %d\n\n", ret ); + mbedtls_x509_csr_free( &csr ); + goto exit; + } + + mbedtls_printf( " ok\n" ); + + /* + * 1.2 Print the CSR + */ + mbedtls_printf( " . CSR information ...\n" ); + ret = mbedtls_x509_csr_info( (char *) buf, sizeof( buf ) - 1, " ", &csr ); + if( ret == -1 ) + { + mbedtls_printf( " failed\n ! mbedtls_x509_csr_info returned %d\n\n", ret ); + mbedtls_x509_csr_free( &csr ); + goto exit; + } + + mbedtls_printf( "%s\n", buf ); + + exit_code = MBEDTLS_EXIT_SUCCESS; + +exit: + mbedtls_x509_csr_free( &csr ); + +#if defined(_WIN32) + mbedtls_printf( " + Press Enter to exit this program.\n" ); + fflush( stdout ); getchar(); +#endif + + return( exit_code ); +} +#endif /* MBEDTLS_BIGNUM_C && MBEDTLS_RSA_C && MBEDTLS_X509_CSR_PARSE_C && + MBEDTLS_FS_IO */ diff --git a/tests/data_files/Makefile b/tests/data_files/Makefile index e85fd70c2..cfb384d45 100644 --- a/tests/data_files/Makefile +++ b/tests/data_files/Makefile @@ -13,6 +13,8 @@ ## Tools OPENSSL ?= openssl FAKETIME ?= faketime +MBEDTLS_CERT_WRITE ?= $(PWD)/../../programs/x509/cert_write +MBEDTLS_CERT_REQ ?= $(PWD)/../../programs/x509/cert_req ## Build the generated test data. Note that since the final outputs diff --git a/visualc/VS2010/cert_app.vcxproj b/visualc/VS2010/cert_app.vcxproj new file mode 100644 index 000000000..ee7b4a152 --- /dev/null +++ b/visualc/VS2010/cert_app.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {D4D691D4-137C-CBFA-735B-D46636D7E4D8} + Win32Proj + cert_app + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/cert_req.vcxproj b/visualc/VS2010/cert_req.vcxproj new file mode 100644 index 000000000..2645e86a4 --- /dev/null +++ b/visualc/VS2010/cert_req.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE} + Win32Proj + cert_req + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/cert_write.vcxproj b/visualc/VS2010/cert_write.vcxproj new file mode 100644 index 000000000..f714d952d --- /dev/null +++ b/visualc/VS2010/cert_write.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {35E52E46-3BA9-4361-41D3-53663C2E9B8A} + Win32Proj + cert_write + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/crl_app.vcxproj b/visualc/VS2010/crl_app.vcxproj new file mode 100644 index 000000000..b218a8909 --- /dev/null +++ b/visualc/VS2010/crl_app.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {DB904B85-AD31-B7FB-114F-88760CC485F2} + Win32Proj + crl_app + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/dtls_client.vcxproj b/visualc/VS2010/dtls_client.vcxproj new file mode 100644 index 000000000..d9834354d --- /dev/null +++ b/visualc/VS2010/dtls_client.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5} + Win32Proj + dtls_client + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/dtls_server.vcxproj b/visualc/VS2010/dtls_server.vcxproj new file mode 100644 index 000000000..9fb41f74c --- /dev/null +++ b/visualc/VS2010/dtls_server.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317} + Win32Proj + dtls_server + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/mbedTLS.sln b/visualc/VS2010/mbedTLS.sln index 9292b2562..9645016d1 100644 --- a/visualc/VS2010/mbedTLS.sln +++ b/visualc/VS2010/mbedTLS.sln @@ -128,6 +128,51 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "psa_constant_names", "psa_c {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dtls_client", "dtls_client.vcxproj", "{FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dtls_server", "dtls_server.vcxproj", "{BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_client1", "ssl_client1.vcxproj", "{487A2F80-3CA3-678D-88D5-82194872CF08}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_client2", "ssl_client2.vcxproj", "{4E590E9D-E28F-87FF-385B-D58736388231}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_server", "ssl_server.vcxproj", "{E08E0065-896A-7487-DEA5-D3B80B71F975}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_server2", "ssl_server2.vcxproj", "{A4DA7463-1047-BDF5-E1B3-5632CB573F41}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_fork_server", "ssl_fork_server.vcxproj", "{918CD402-047D-8467-E11C-E1132053F916}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mini_client", "mini_client.vcxproj", "{C4FE29EA-266D-5295-4840-976B9B5B3843}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ssl_mail_client", "ssl_mail_client.vcxproj", "{7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "gen_entropy", "gen_entropy.vcxproj", "{DE695064-13C3-18B0-378D-8B22672BF3F4}" ProjectSection(ProjectDependencies) = postProject {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} @@ -153,6 +198,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "selftest", "selftest.vcxpro {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "udp_proxy", "udp_proxy.vcxproj", "{7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zeroize", "zeroize.vcxproj", "{10C01E94-4926-063E-9F56-C84ED190D349}" ProjectSection(ProjectDependencies) = postProject {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} @@ -173,6 +223,31 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "strerror", "strerror.vcxpro {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} EndProjectSection EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_app", "cert_app.vcxproj", "{D4D691D4-137C-CBFA-735B-D46636D7E4D8}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crl_app", "crl_app.vcxproj", "{DB904B85-AD31-B7FB-114F-88760CC485F2}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_req", "cert_req.vcxproj", "{C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "cert_write", "cert_write.vcxproj", "{35E52E46-3BA9-4361-41D3-53663C2E9B8A}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "req_app", "req_app.vcxproj", "{486B1375-5CFA-C2D2-DD89-C9F497BADCB3}" + ProjectSection(ProjectDependencies) = postProject + {46CF2D25-6A36-4189-B59C-E4815388E554} = {46CF2D25-6A36-4189-B59C-E4815388E554} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -389,6 +464,78 @@ Global {A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|Win32.Build.0 = Release|Win32 {A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|x64.ActiveCfg = Release|x64 {A0BAD8F0-69B5-8382-86ED-C36ACBE54117}.Release|x64.Build.0 = Release|x64 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|Win32.ActiveCfg = Debug|Win32 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|Win32.Build.0 = Debug|Win32 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|x64.ActiveCfg = Debug|x64 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Debug|x64.Build.0 = Debug|x64 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|Win32.ActiveCfg = Release|Win32 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|Win32.Build.0 = Release|Win32 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|x64.ActiveCfg = Release|x64 + {FE7AB78F-DBF1-0721-3522-0D7C3011D2E5}.Release|x64.Build.0 = Release|x64 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|Win32.ActiveCfg = Debug|Win32 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|Win32.Build.0 = Debug|Win32 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|x64.ActiveCfg = Debug|x64 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Debug|x64.Build.0 = Debug|x64 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|Win32.ActiveCfg = Release|Win32 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|Win32.Build.0 = Release|Win32 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|x64.ActiveCfg = Release|x64 + {BFE89EAA-D98B-34E1-C5A4-4080F6FFE317}.Release|x64.Build.0 = Release|x64 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|Win32.ActiveCfg = Debug|Win32 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|Win32.Build.0 = Debug|Win32 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|x64.ActiveCfg = Debug|x64 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Debug|x64.Build.0 = Debug|x64 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Release|Win32.ActiveCfg = Release|Win32 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Release|Win32.Build.0 = Release|Win32 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Release|x64.ActiveCfg = Release|x64 + {487A2F80-3CA3-678D-88D5-82194872CF08}.Release|x64.Build.0 = Release|x64 + {4E590E9D-E28F-87FF-385B-D58736388231}.Debug|Win32.ActiveCfg = Debug|Win32 + {4E590E9D-E28F-87FF-385B-D58736388231}.Debug|Win32.Build.0 = Debug|Win32 + {4E590E9D-E28F-87FF-385B-D58736388231}.Debug|x64.ActiveCfg = Debug|x64 + {4E590E9D-E28F-87FF-385B-D58736388231}.Debug|x64.Build.0 = Debug|x64 + {4E590E9D-E28F-87FF-385B-D58736388231}.Release|Win32.ActiveCfg = Release|Win32 + {4E590E9D-E28F-87FF-385B-D58736388231}.Release|Win32.Build.0 = Release|Win32 + {4E590E9D-E28F-87FF-385B-D58736388231}.Release|x64.ActiveCfg = Release|x64 + {4E590E9D-E28F-87FF-385B-D58736388231}.Release|x64.Build.0 = Release|x64 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|Win32.ActiveCfg = Debug|Win32 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|Win32.Build.0 = Debug|Win32 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|x64.ActiveCfg = Debug|x64 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Debug|x64.Build.0 = Debug|x64 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|Win32.ActiveCfg = Release|Win32 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|Win32.Build.0 = Release|Win32 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|x64.ActiveCfg = Release|x64 + {E08E0065-896A-7487-DEA5-D3B80B71F975}.Release|x64.Build.0 = Release|x64 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|Win32.ActiveCfg = Debug|Win32 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|Win32.Build.0 = Debug|Win32 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|x64.ActiveCfg = Debug|x64 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Debug|x64.Build.0 = Debug|x64 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|Win32.ActiveCfg = Release|Win32 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|Win32.Build.0 = Release|Win32 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|x64.ActiveCfg = Release|x64 + {A4DA7463-1047-BDF5-E1B3-5632CB573F41}.Release|x64.Build.0 = Release|x64 + {918CD402-047D-8467-E11C-E1132053F916}.Debug|Win32.ActiveCfg = Debug|Win32 + {918CD402-047D-8467-E11C-E1132053F916}.Debug|Win32.Build.0 = Debug|Win32 + {918CD402-047D-8467-E11C-E1132053F916}.Debug|x64.ActiveCfg = Debug|x64 + {918CD402-047D-8467-E11C-E1132053F916}.Debug|x64.Build.0 = Debug|x64 + {918CD402-047D-8467-E11C-E1132053F916}.Release|Win32.ActiveCfg = Release|Win32 + {918CD402-047D-8467-E11C-E1132053F916}.Release|Win32.Build.0 = Release|Win32 + {918CD402-047D-8467-E11C-E1132053F916}.Release|x64.ActiveCfg = Release|x64 + {918CD402-047D-8467-E11C-E1132053F916}.Release|x64.Build.0 = Release|x64 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|Win32.ActiveCfg = Debug|Win32 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|Win32.Build.0 = Debug|Win32 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|x64.ActiveCfg = Debug|x64 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Debug|x64.Build.0 = Debug|x64 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|Win32.ActiveCfg = Release|Win32 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|Win32.Build.0 = Release|Win32 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|x64.ActiveCfg = Release|x64 + {C4FE29EA-266D-5295-4840-976B9B5B3843}.Release|x64.Build.0 = Release|x64 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|Win32.ActiveCfg = Debug|Win32 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|Win32.Build.0 = Debug|Win32 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|x64.ActiveCfg = Debug|x64 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Debug|x64.Build.0 = Debug|x64 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|Win32.ActiveCfg = Release|Win32 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|Win32.Build.0 = Release|Win32 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|x64.ActiveCfg = Release|x64 + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD}.Release|x64.Build.0 = Release|x64 {DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|Win32.ActiveCfg = Debug|Win32 {DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|Win32.Build.0 = Debug|Win32 {DE695064-13C3-18B0-378D-8B22672BF3F4}.Debug|x64.ActiveCfg = Debug|x64 @@ -429,6 +576,14 @@ Global {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|Win32.Build.0 = Release|Win32 {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|x64.ActiveCfg = Release|x64 {7DBC5F77-3DA1-5F73-8421-E693D95FC66A}.Release|x64.Build.0 = Release|x64 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|Win32.ActiveCfg = Debug|Win32 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|Win32.Build.0 = Debug|Win32 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|x64.ActiveCfg = Debug|x64 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Debug|x64.Build.0 = Debug|x64 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.ActiveCfg = Release|Win32 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|Win32.Build.0 = Release|Win32 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.ActiveCfg = Release|x64 + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A}.Release|x64.Build.0 = Release|x64 {10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.ActiveCfg = Debug|Win32 {10C01E94-4926-063E-9F56-C84ED190D349}.Debug|Win32.Build.0 = Debug|Win32 {10C01E94-4926-063E-9F56-C84ED190D349}.Debug|x64.ActiveCfg = Debug|x64 @@ -461,6 +616,46 @@ Global {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|Win32.Build.0 = Release|Win32 {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|x64.ActiveCfg = Release|x64 {23EF735C-CC4C-3EC4-A75E-903DB340F04A}.Release|x64.Build.0 = Release|x64 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|Win32.ActiveCfg = Debug|Win32 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|Win32.Build.0 = Debug|Win32 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|x64.ActiveCfg = Debug|x64 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Debug|x64.Build.0 = Debug|x64 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|Win32.ActiveCfg = Release|Win32 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|Win32.Build.0 = Release|Win32 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|x64.ActiveCfg = Release|x64 + {D4D691D4-137C-CBFA-735B-D46636D7E4D8}.Release|x64.Build.0 = Release|x64 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|Win32.ActiveCfg = Debug|Win32 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|Win32.Build.0 = Debug|Win32 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|x64.ActiveCfg = Debug|x64 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Debug|x64.Build.0 = Debug|x64 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|Win32.ActiveCfg = Release|Win32 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|Win32.Build.0 = Release|Win32 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|x64.ActiveCfg = Release|x64 + {DB904B85-AD31-B7FB-114F-88760CC485F2}.Release|x64.Build.0 = Release|x64 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|Win32.ActiveCfg = Debug|Win32 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|Win32.Build.0 = Debug|Win32 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|x64.ActiveCfg = Debug|x64 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Debug|x64.Build.0 = Debug|x64 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|Win32.ActiveCfg = Release|Win32 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|Win32.Build.0 = Release|Win32 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|x64.ActiveCfg = Release|x64 + {C9E2AB15-8AEF-DD48-60C3-557ECC5215BE}.Release|x64.Build.0 = Release|x64 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|Win32.ActiveCfg = Debug|Win32 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|Win32.Build.0 = Debug|Win32 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|x64.ActiveCfg = Debug|x64 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Debug|x64.Build.0 = Debug|x64 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|Win32.ActiveCfg = Release|Win32 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|Win32.Build.0 = Release|Win32 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|x64.ActiveCfg = Release|x64 + {35E52E46-3BA9-4361-41D3-53663C2E9B8A}.Release|x64.Build.0 = Release|x64 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|Win32.ActiveCfg = Debug|Win32 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|Win32.Build.0 = Debug|Win32 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|x64.ActiveCfg = Debug|x64 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Debug|x64.Build.0 = Debug|x64 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|Win32.ActiveCfg = Release|Win32 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|Win32.Build.0 = Release|Win32 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|x64.ActiveCfg = Release|x64 + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/visualc/VS2010/mini_client.vcxproj b/visualc/VS2010/mini_client.vcxproj new file mode 100644 index 000000000..1f19a10e9 --- /dev/null +++ b/visualc/VS2010/mini_client.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {C4FE29EA-266D-5295-4840-976B9B5B3843} + Win32Proj + mini_client + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/req_app.vcxproj b/visualc/VS2010/req_app.vcxproj new file mode 100644 index 000000000..70e9e1524 --- /dev/null +++ b/visualc/VS2010/req_app.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {486B1375-5CFA-C2D2-DD89-C9F497BADCB3} + Win32Proj + req_app + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/ssl_client1.vcxproj b/visualc/VS2010/ssl_client1.vcxproj new file mode 100644 index 000000000..2b188fe30 --- /dev/null +++ b/visualc/VS2010/ssl_client1.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {487A2F80-3CA3-678D-88D5-82194872CF08} + Win32Proj + ssl_client1 + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/ssl_client2.vcxproj b/visualc/VS2010/ssl_client2.vcxproj new file mode 100644 index 000000000..21a6f6be0 --- /dev/null +++ b/visualc/VS2010/ssl_client2.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {4E590E9D-E28F-87FF-385B-D58736388231} + Win32Proj + ssl_client2 + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/ssl_fork_server.vcxproj b/visualc/VS2010/ssl_fork_server.vcxproj new file mode 100644 index 000000000..e4fd3620a --- /dev/null +++ b/visualc/VS2010/ssl_fork_server.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {918CD402-047D-8467-E11C-E1132053F916} + Win32Proj + ssl_fork_server + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/ssl_mail_client.vcxproj b/visualc/VS2010/ssl_mail_client.vcxproj new file mode 100644 index 000000000..5341ff5dc --- /dev/null +++ b/visualc/VS2010/ssl_mail_client.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {7C4863A1-941A-C5AE-E1F9-30F062E4B2FD} + Win32Proj + ssl_mail_client + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/ssl_server.vcxproj b/visualc/VS2010/ssl_server.vcxproj new file mode 100644 index 000000000..eccee4f92 --- /dev/null +++ b/visualc/VS2010/ssl_server.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {E08E0065-896A-7487-DEA5-D3B80B71F975} + Win32Proj + ssl_server + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/ssl_server2.vcxproj b/visualc/VS2010/ssl_server2.vcxproj new file mode 100644 index 000000000..0f7d5e75f --- /dev/null +++ b/visualc/VS2010/ssl_server2.vcxproj @@ -0,0 +1,178 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {A4DA7463-1047-BDF5-E1B3-5632CB573F41} + Win32Proj + ssl_server2 + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + + diff --git a/visualc/VS2010/udp_proxy.vcxproj b/visualc/VS2010/udp_proxy.vcxproj new file mode 100644 index 000000000..10b28cde1 --- /dev/null +++ b/visualc/VS2010/udp_proxy.vcxproj @@ -0,0 +1,177 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + + + + + {46cf2d25-6a36-4189-b59c-e4815388e554} + true + + + + {7E2C80FE-3CC3-82B4-0CAD-65DC233DE13A} + Win32Proj + udp_proxy + + + + Application + true + Unicode + + + Application + true + Unicode + + + Application + false + true + Unicode + + + Application + false + true + Unicode + + + + + + + + + + + + + + + + + + + true + $(Configuration)\$(TargetName)\ + + + true + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + false + $(Configuration)\$(TargetName)\ + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + + + Level3 + Disabled + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + NotSet + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + Debug + + + false + + + + + Level3 + + + MaxSpeed + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;%(AdditionalDependencies) + + + + + Level3 + + + MaxSpeed + true + true + WIN64;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + +../../include;../../3rdparty/everest/include/;../../3rdparty/everest/include/everest;../../3rdparty/everest/include/everest/vs2010;../../3rdparty/everest/include/everest/kremlib + + + Console + true + true + true + Release + %(AdditionalDependencies); + + + + + +