Fix for x86_64 build fail
[platform/upstream/connectedhomeip.git] / third_party / mbedtls / repo / programs / ssl / ssl_pthread_server.c
1 /*
2  *  SSL server demonstration program using pthread for handling multiple
3  *  clients.
4  *
5  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
6  *  SPDX-License-Identifier: Apache-2.0
7  *
8  *  Licensed under the Apache License, Version 2.0 (the "License"); you may
9  *  not use this file except in compliance with the License.
10  *  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  *  Unless required by applicable law or agreed to in writing, software
15  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
16  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  *  See the License for the specific language governing permissions and
18  *  limitations under the License.
19  *
20  *  This file is part of mbed TLS (https://tls.mbed.org)
21  */
22
23 #if !defined(MBEDTLS_CONFIG_FILE)
24 #include "mbedtls/config.h"
25 #else
26 #include MBEDTLS_CONFIG_FILE
27 #endif
28
29 #if defined(MBEDTLS_PLATFORM_C)
30 #include "mbedtls/platform.h"
31 #else
32 #include <stdio.h>
33 #include <stdlib.h>
34 #define mbedtls_fprintf    fprintf
35 #define mbedtls_printf     printf
36 #define mbedtls_snprintf   snprintf
37 #define mbedtls_exit            exit
38 #define MBEDTLS_EXIT_SUCCESS    EXIT_SUCCESS
39 #define MBEDTLS_EXIT_FAILURE    EXIT_FAILURE
40 #endif
41
42 #if !defined(MBEDTLS_BIGNUM_C) || !defined(MBEDTLS_CERTS_C) ||            \
43     !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_SSL_TLS_C) ||         \
44     !defined(MBEDTLS_SSL_SRV_C) || !defined(MBEDTLS_NET_C) ||             \
45     !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_CTR_DRBG_C) ||            \
46     !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_FS_IO) ||      \
47     !defined(MBEDTLS_THREADING_C) || !defined(MBEDTLS_THREADING_PTHREAD) || \
48     !defined(MBEDTLS_PEM_PARSE_C)
49 int main( void )
50 {
51     mbedtls_printf("MBEDTLS_BIGNUM_C and/or MBEDTLS_CERTS_C and/or MBEDTLS_ENTROPY_C "
52            "and/or MBEDTLS_SSL_TLS_C and/or MBEDTLS_SSL_SRV_C and/or "
53            "MBEDTLS_NET_C and/or MBEDTLS_RSA_C and/or "
54            "MBEDTLS_CTR_DRBG_C and/or MBEDTLS_X509_CRT_PARSE_C and/or "
55            "MBEDTLS_THREADING_C and/or MBEDTLS_THREADING_PTHREAD "
56            "and/or MBEDTLS_PEM_PARSE_C not defined.\n");
57     return( 0 );
58 }
59 #else
60
61 #include <stdlib.h>
62 #include <string.h>
63
64 #if defined(_WIN32)
65 #include <windows.h>
66 #endif
67
68 #include "mbedtls/entropy.h"
69 #include "mbedtls/ctr_drbg.h"
70 #include "mbedtls/certs.h"
71 #include "mbedtls/x509.h"
72 #include "mbedtls/ssl.h"
73 #include "mbedtls/net_sockets.h"
74 #include "mbedtls/error.h"
75
76 #if defined(MBEDTLS_SSL_CACHE_C)
77 #include "mbedtls/ssl_cache.h"
78 #endif
79
80 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
81 #include "mbedtls/memory_buffer_alloc.h"
82 #endif
83
84 #if defined(MBEDTLS_CHECK_PARAMS)
85 #include "mbedtls/platform_util.h"
86 void mbedtls_param_failed( const char *failure_condition,
87                            const char *file,
88                            int line )
89 {
90     mbedtls_printf( "%s:%i: Input param failed - %s\n",
91                     file, line, failure_condition );
92     mbedtls_exit( MBEDTLS_EXIT_FAILURE );
93 }
94 #endif
95
96 #define HTTP_RESPONSE \
97     "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
98     "<h2>mbed TLS Test Server</h2>\r\n" \
99     "<p>Successful connection using: %s</p>\r\n"
100
101 #define DEBUG_LEVEL 0
102
103 #define MAX_NUM_THREADS 5
104
105 mbedtls_threading_mutex_t debug_mutex;
106
107 static void my_mutexed_debug( void *ctx, int level,
108                       const char *file, int line,
109                       const char *str )
110 {
111     long int thread_id = (long int) pthread_self();
112
113     mbedtls_mutex_lock( &debug_mutex );
114
115     ((void) level);
116     mbedtls_fprintf( (FILE *) ctx, "%s:%04d: [ #%ld ] %s",
117                                     file, line, thread_id, str );
118     fflush(  (FILE *) ctx  );
119
120     mbedtls_mutex_unlock( &debug_mutex );
121 }
122
123 typedef struct {
124     mbedtls_net_context client_fd;
125     int thread_complete;
126     const mbedtls_ssl_config *config;
127 } thread_info_t;
128
129 typedef struct {
130     int active;
131     thread_info_t   data;
132     pthread_t       thread;
133 } pthread_info_t;
134
135 static thread_info_t    base_info;
136 static pthread_info_t   threads[MAX_NUM_THREADS];
137
138 static void *handle_ssl_connection( void *data )
139 {
140     int ret, len;
141     thread_info_t *thread_info = (thread_info_t *) data;
142     mbedtls_net_context *client_fd = &thread_info->client_fd;
143     long int thread_id = (long int) pthread_self();
144     unsigned char buf[1024];
145     mbedtls_ssl_context ssl;
146
147     /* Make sure memory references are valid */
148     mbedtls_ssl_init( &ssl );
149
150     mbedtls_printf( "  [ #%ld ]  Setting up SSL/TLS data\n", thread_id );
151
152     /*
153      * 4. Get the SSL context ready
154      */
155     if( ( ret = mbedtls_ssl_setup( &ssl, thread_info->config ) ) != 0 )
156     {
157         mbedtls_printf( "  [ #%ld ]  failed: mbedtls_ssl_setup returned -0x%04x\n",
158                 thread_id, -ret );
159         goto thread_exit;
160     }
161
162     mbedtls_ssl_set_bio( &ssl, client_fd, mbedtls_net_send, mbedtls_net_recv, NULL );
163
164     /*
165      * 5. Handshake
166      */
167     mbedtls_printf( "  [ #%ld ]  Performing the SSL/TLS handshake\n", thread_id );
168
169     while( ( ret = mbedtls_ssl_handshake( &ssl ) ) != 0 )
170     {
171         if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
172         {
173             mbedtls_printf( "  [ #%ld ]  failed: mbedtls_ssl_handshake returned -0x%04x\n",
174                     thread_id, -ret );
175             goto thread_exit;
176         }
177     }
178
179     mbedtls_printf( "  [ #%ld ]  ok\n", thread_id );
180
181     /*
182      * 6. Read the HTTP Request
183      */
184     mbedtls_printf( "  [ #%ld ]  < Read from client\n", thread_id );
185
186     do
187     {
188         len = sizeof( buf ) - 1;
189         memset( buf, 0, sizeof( buf ) );
190         ret = mbedtls_ssl_read( &ssl, buf, len );
191
192         if( ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE )
193             continue;
194
195         if( ret <= 0 )
196         {
197             switch( ret )
198             {
199                 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
200                     mbedtls_printf( "  [ #%ld ]  connection was closed gracefully\n",
201                             thread_id );
202                     goto thread_exit;
203
204                 case MBEDTLS_ERR_NET_CONN_RESET:
205                     mbedtls_printf( "  [ #%ld ]  connection was reset by peer\n",
206                             thread_id );
207                     goto thread_exit;
208
209                 default:
210                     mbedtls_printf( "  [ #%ld ]  mbedtls_ssl_read returned -0x%04x\n",
211                             thread_id, -ret );
212                     goto thread_exit;
213             }
214         }
215
216         len = ret;
217         mbedtls_printf( "  [ #%ld ]  %d bytes read\n=====\n%s\n=====\n",
218                 thread_id, len, (char *) buf );
219
220         if( ret > 0 )
221             break;
222     }
223     while( 1 );
224
225     /*
226      * 7. Write the 200 Response
227      */
228     mbedtls_printf( "  [ #%ld ]  > Write to client:\n", thread_id );
229
230     len = sprintf( (char *) buf, HTTP_RESPONSE,
231                    mbedtls_ssl_get_ciphersuite( &ssl ) );
232
233     while( ( ret = mbedtls_ssl_write( &ssl, buf, len ) ) <= 0 )
234     {
235         if( ret == MBEDTLS_ERR_NET_CONN_RESET )
236         {
237             mbedtls_printf( "  [ #%ld ]  failed: peer closed the connection\n",
238                     thread_id );
239             goto thread_exit;
240         }
241
242         if( ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE )
243         {
244             mbedtls_printf( "  [ #%ld ]  failed: mbedtls_ssl_write returned -0x%04x\n",
245                     thread_id, ret );
246             goto thread_exit;
247         }
248     }
249
250     len = ret;
251     mbedtls_printf( "  [ #%ld ]  %d bytes written\n=====\n%s\n=====\n",
252             thread_id, len, (char *) buf );
253
254     mbedtls_printf( "  [ #%ld ]  . Closing the connection...", thread_id );
255
256     while( ( ret = mbedtls_ssl_close_notify( &ssl ) ) < 0 )
257     {
258         if( ret != MBEDTLS_ERR_SSL_WANT_READ &&
259             ret != MBEDTLS_ERR_SSL_WANT_WRITE )
260         {
261             mbedtls_printf( "  [ #%ld ]  failed: mbedtls_ssl_close_notify returned -0x%04x\n",
262                     thread_id, ret );
263             goto thread_exit;
264         }
265     }
266
267     mbedtls_printf( " ok\n" );
268
269     ret = 0;
270
271 thread_exit:
272
273 #ifdef MBEDTLS_ERROR_C
274     if( ret != 0 )
275     {
276         char error_buf[100];
277         mbedtls_strerror( ret, error_buf, 100 );
278         mbedtls_printf("  [ #%ld ]  Last error was: -0x%04x - %s\n\n",
279                thread_id, -ret, error_buf );
280     }
281 #endif
282
283     mbedtls_net_free( client_fd );
284     mbedtls_ssl_free( &ssl );
285
286     thread_info->thread_complete = 1;
287
288     return( NULL );
289 }
290
291 static int thread_create( mbedtls_net_context *client_fd )
292 {
293     int ret, i;
294
295     /*
296      * Find in-active or finished thread slot
297      */
298     for( i = 0; i < MAX_NUM_THREADS; i++ )
299     {
300         if( threads[i].active == 0 )
301             break;
302
303         if( threads[i].data.thread_complete == 1 )
304         {
305             mbedtls_printf( "  [ main ]  Cleaning up thread %d\n", i );
306             pthread_join(threads[i].thread, NULL );
307             memset( &threads[i], 0, sizeof(pthread_info_t) );
308             break;
309         }
310     }
311
312     if( i == MAX_NUM_THREADS )
313         return( -1 );
314
315     /*
316      * Fill thread-info for thread
317      */
318     memcpy( &threads[i].data, &base_info, sizeof(base_info) );
319     threads[i].active = 1;
320     memcpy( &threads[i].data.client_fd, client_fd, sizeof( mbedtls_net_context ) );
321
322     if( ( ret = pthread_create( &threads[i].thread, NULL, handle_ssl_connection,
323                                 &threads[i].data ) ) != 0 )
324     {
325         return( ret );
326     }
327
328     return( 0 );
329 }
330
331 int main( void )
332 {
333     int ret;
334     mbedtls_net_context listen_fd, client_fd;
335     const char pers[] = "ssl_pthread_server";
336
337     mbedtls_entropy_context entropy;
338     mbedtls_ctr_drbg_context ctr_drbg;
339     mbedtls_ssl_config conf;
340     mbedtls_x509_crt srvcert;
341     mbedtls_x509_crt cachain;
342     mbedtls_pk_context pkey;
343 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
344     unsigned char alloc_buf[100000];
345 #endif
346 #if defined(MBEDTLS_SSL_CACHE_C)
347     mbedtls_ssl_cache_context cache;
348 #endif
349
350 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
351     mbedtls_memory_buffer_alloc_init( alloc_buf, sizeof(alloc_buf) );
352 #endif
353
354 #if defined(MBEDTLS_SSL_CACHE_C)
355     mbedtls_ssl_cache_init( &cache );
356 #endif
357
358     mbedtls_x509_crt_init( &srvcert );
359     mbedtls_x509_crt_init( &cachain );
360
361     mbedtls_ssl_config_init( &conf );
362     mbedtls_ctr_drbg_init( &ctr_drbg );
363     memset( threads, 0, sizeof(threads) );
364     mbedtls_net_init( &listen_fd );
365     mbedtls_net_init( &client_fd );
366
367     mbedtls_mutex_init( &debug_mutex );
368
369     base_info.config = &conf;
370
371     /*
372      * We use only a single entropy source that is used in all the threads.
373      */
374     mbedtls_entropy_init( &entropy );
375
376     /*
377      * 1. Load the certificates and private RSA key
378      */
379     mbedtls_printf( "\n  . Loading the server cert. and key..." );
380     fflush( stdout );
381
382     /*
383      * This demonstration program uses embedded test certificates.
384      * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the
385      * server and CA certificates, as well as mbedtls_pk_parse_keyfile().
386      */
387     ret = mbedtls_x509_crt_parse( &srvcert, (const unsigned char *) mbedtls_test_srv_crt,
388                           mbedtls_test_srv_crt_len );
389     if( ret != 0 )
390     {
391         mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret );
392         goto exit;
393     }
394
395     ret = mbedtls_x509_crt_parse( &cachain, (const unsigned char *) mbedtls_test_cas_pem,
396                           mbedtls_test_cas_pem_len );
397     if( ret != 0 )
398     {
399         mbedtls_printf( " failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret );
400         goto exit;
401     }
402
403     mbedtls_pk_init( &pkey );
404     ret =  mbedtls_pk_parse_key( &pkey, (const unsigned char *) mbedtls_test_srv_key,
405                          mbedtls_test_srv_key_len, NULL, 0 );
406     if( ret != 0 )
407     {
408         mbedtls_printf( " failed\n  !  mbedtls_pk_parse_key returned %d\n\n", ret );
409         goto exit;
410     }
411
412     mbedtls_printf( " ok\n" );
413
414     /*
415      * 1b. Seed the random number generator
416      */
417     mbedtls_printf( "  . Seeding the random number generator..." );
418
419     if( ( ret = mbedtls_ctr_drbg_seed( &ctr_drbg, mbedtls_entropy_func, &entropy,
420                                (const unsigned char *) pers,
421                                strlen( pers ) ) ) != 0 )
422     {
423         mbedtls_printf( " failed: mbedtls_ctr_drbg_seed returned -0x%04x\n",
424                 -ret );
425         goto exit;
426     }
427
428     mbedtls_printf( " ok\n" );
429
430     /*
431      * 1c. Prepare SSL configuration
432      */
433     mbedtls_printf( "  . Setting up the SSL data...." );
434
435     if( ( ret = mbedtls_ssl_config_defaults( &conf,
436                     MBEDTLS_SSL_IS_SERVER,
437                     MBEDTLS_SSL_TRANSPORT_STREAM,
438                     MBEDTLS_SSL_PRESET_DEFAULT ) ) != 0 )
439     {
440         mbedtls_printf( " failed: mbedtls_ssl_config_defaults returned -0x%04x\n",
441                 -ret );
442         goto exit;
443     }
444
445     mbedtls_ssl_conf_rng( &conf, mbedtls_ctr_drbg_random, &ctr_drbg );
446     mbedtls_ssl_conf_dbg( &conf, my_mutexed_debug, stdout );
447
448     /* mbedtls_ssl_cache_get() and mbedtls_ssl_cache_set() are thread-safe if
449      * MBEDTLS_THREADING_C is set.
450      */
451 #if defined(MBEDTLS_SSL_CACHE_C)
452     mbedtls_ssl_conf_session_cache( &conf, &cache,
453                                    mbedtls_ssl_cache_get,
454                                    mbedtls_ssl_cache_set );
455 #endif
456
457     mbedtls_ssl_conf_ca_chain( &conf, &cachain, NULL );
458     if( ( ret = mbedtls_ssl_conf_own_cert( &conf, &srvcert, &pkey ) ) != 0 )
459     {
460         mbedtls_printf( " failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret );
461         goto exit;
462     }
463
464     mbedtls_printf( " ok\n" );
465
466
467     /*
468      * 2. Setup the listening TCP socket
469      */
470     mbedtls_printf( "  . Bind on https://localhost:4433/ ..." );
471     fflush( stdout );
472
473     if( ( ret = mbedtls_net_bind( &listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP ) ) != 0 )
474     {
475         mbedtls_printf( " failed\n  ! mbedtls_net_bind returned %d\n\n", ret );
476         goto exit;
477     }
478
479     mbedtls_printf( " ok\n" );
480
481 reset:
482 #ifdef MBEDTLS_ERROR_C
483     if( ret != 0 )
484     {
485         char error_buf[100];
486         mbedtls_strerror( ret, error_buf, 100 );
487         mbedtls_printf( "  [ main ]  Last error was: -0x%04x - %s\n", -ret, error_buf );
488     }
489 #endif
490
491     /*
492      * 3. Wait until a client connects
493      */
494     mbedtls_printf( "  [ main ]  Waiting for a remote connection\n" );
495
496     if( ( ret = mbedtls_net_accept( &listen_fd, &client_fd,
497                                     NULL, 0, NULL ) ) != 0 )
498     {
499         mbedtls_printf( "  [ main ] failed: mbedtls_net_accept returned -0x%04x\n", ret );
500         goto exit;
501     }
502
503     mbedtls_printf( "  [ main ]  ok\n" );
504     mbedtls_printf( "  [ main ]  Creating a new thread\n" );
505
506     if( ( ret = thread_create( &client_fd ) ) != 0 )
507     {
508         mbedtls_printf( "  [ main ]  failed: thread_create returned %d\n", ret );
509         mbedtls_net_free( &client_fd );
510         goto reset;
511     }
512
513     ret = 0;
514     goto reset;
515
516 exit:
517     mbedtls_x509_crt_free( &srvcert );
518     mbedtls_pk_free( &pkey );
519 #if defined(MBEDTLS_SSL_CACHE_C)
520     mbedtls_ssl_cache_free( &cache );
521 #endif
522     mbedtls_ctr_drbg_free( &ctr_drbg );
523     mbedtls_entropy_free( &entropy );
524     mbedtls_ssl_config_free( &conf );
525
526     mbedtls_net_free( &listen_fd );
527
528     mbedtls_mutex_free( &debug_mutex );
529
530 #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C)
531     mbedtls_memory_buffer_alloc_free();
532 #endif
533
534 #if defined(_WIN32)
535     mbedtls_printf( "  Press Enter to exit this program.\n" );
536     fflush( stdout ); getchar();
537 #endif
538
539     return( ret );
540 }
541
542 #endif /* MBEDTLS_BIGNUM_C && MBEDTLS_CERTS_C && MBEDTLS_ENTROPY_C &&
543           MBEDTLS_SSL_TLS_C && MBEDTLS_SSL_SRV_C && MBEDTLS_NET_C &&
544           MBEDTLS_RSA_C && MBEDTLS_CTR_DRBG_C && MBEDTLS_THREADING_C &&
545           MBEDTLS_THREADING_PTHREAD && MBEDTLS_PEM_PARSE_C */