1 /*
2  *  SSL server demonstration program
3  *
4  *  Copyright The Mbed TLS Contributors
5  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6  */
7 
8 #define MBEDTLS_DECLARE_PRIVATE_IDENTIFIERS
9 
10 #include "mbedtls/build_info.h"
11 
12 #include "mbedtls/platform.h"
13 
14 #if !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_CTR_DRBG_C) ||      \
15     !defined(MBEDTLS_NET_C) || !defined(MBEDTLS_SSL_SRV_C) ||           \
16     !defined(MBEDTLS_PEM_PARSE_C) || !defined(MBEDTLS_X509_CRT_PARSE_C)
main(void)17 int main(void)
18 {
19     mbedtls_printf("MBEDTLS_ENTROPY_C and/or MBEDTLS_CTR_DRBG_C and/or "
20                    "MBEDTLS_NET_C and/or MBEDTLS_SSL_SRV_C and/or "
21                    "MBEDTLS_PEM_PARSE_C and/or MBEDTLS_X509_CRT_PARSE_C "
22                    "not defined.\n");
23     mbedtls_exit(0);
24 }
25 #else
26 
27 #include <stdlib.h>
28 #include <string.h>
29 
30 #if defined(_WIN32)
31 #include <windows.h>
32 #endif
33 
34 #include "mbedtls/entropy.h"
35 #include "mbedtls/ctr_drbg.h"
36 #include "mbedtls/x509.h"
37 #include "mbedtls/ssl.h"
38 #include "mbedtls/net_sockets.h"
39 #include "mbedtls/error.h"
40 #include "mbedtls/debug.h"
41 #include "test/certs.h"
42 
43 #if defined(MBEDTLS_SSL_CACHE_C)
44 #include "mbedtls/ssl_cache.h"
45 #endif
46 
47 #define HTTP_RESPONSE \
48     "HTTP/1.0 200 OK\r\nContent-Type: text/html\r\n\r\n" \
49     "<h2>Mbed TLS Test Server</h2>\r\n" \
50     "<p>Successful connection using: %s</p>\r\n"
51 
52 #define DEBUG_LEVEL 0
53 
54 
my_debug(void * ctx,int level,const char * file,int line,const char * str)55 static void my_debug(void *ctx, int level,
56                      const char *file, int line,
57                      const char *str)
58 {
59     ((void) level);
60 
61     mbedtls_fprintf((FILE *) ctx, "%s:%04d: %s", file, line, str);
62     fflush((FILE *) ctx);
63 }
64 
main(void)65 int main(void)
66 {
67     int ret, len;
68     mbedtls_net_context listen_fd, client_fd;
69     unsigned char buf[1024];
70     const char *pers = "ssl_server";
71 
72     mbedtls_entropy_context entropy;
73     mbedtls_ctr_drbg_context ctr_drbg;
74     mbedtls_ssl_context ssl;
75     mbedtls_ssl_config conf;
76     mbedtls_x509_crt srvcert;
77     mbedtls_pk_context pkey;
78 #if defined(MBEDTLS_SSL_CACHE_C)
79     mbedtls_ssl_cache_context cache;
80 #endif
81 
82     mbedtls_net_init(&listen_fd);
83     mbedtls_net_init(&client_fd);
84     mbedtls_ssl_init(&ssl);
85     mbedtls_ssl_config_init(&conf);
86 #if defined(MBEDTLS_SSL_CACHE_C)
87     mbedtls_ssl_cache_init(&cache);
88 #endif
89     mbedtls_x509_crt_init(&srvcert);
90     mbedtls_pk_init(&pkey);
91     mbedtls_entropy_init(&entropy);
92     mbedtls_ctr_drbg_init(&ctr_drbg);
93 
94     psa_status_t status = psa_crypto_init();
95     if (status != PSA_SUCCESS) {
96         mbedtls_fprintf(stderr, "Failed to initialize PSA Crypto implementation: %d\n",
97                         (int) status);
98         ret = MBEDTLS_ERR_SSL_HW_ACCEL_FAILED;
99         goto exit;
100     }
101 
102 #if defined(MBEDTLS_DEBUG_C)
103     mbedtls_debug_set_threshold(DEBUG_LEVEL);
104 #endif
105 
106     /*
107      * 1. Seed the RNG
108      */
109     mbedtls_printf("  . Seeding the random number generator...");
110     fflush(stdout);
111 
112     if ((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy,
113                                      (const unsigned char *) pers,
114                                      strlen(pers))) != 0) {
115         mbedtls_printf(" failed\n  ! mbedtls_ctr_drbg_seed returned %d\n", ret);
116         goto exit;
117     }
118 
119     mbedtls_printf(" ok\n");
120 
121     /*
122      * 2. Load the certificates and private RSA key
123      */
124     mbedtls_printf("\n  . Loading the server cert. and key...");
125     fflush(stdout);
126 
127     /*
128      * This demonstration program uses embedded test certificates.
129      * Instead, you may want to use mbedtls_x509_crt_parse_file() to read the
130      * server and CA certificates, as well as mbedtls_pk_parse_keyfile().
131      */
132     ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_srv_crt,
133                                  mbedtls_test_srv_crt_len);
134     if (ret != 0) {
135         mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret);
136         goto exit;
137     }
138 
139     ret = mbedtls_x509_crt_parse(&srvcert, (const unsigned char *) mbedtls_test_cas_pem,
140                                  mbedtls_test_cas_pem_len);
141     if (ret != 0) {
142         mbedtls_printf(" failed\n  !  mbedtls_x509_crt_parse returned %d\n\n", ret);
143         goto exit;
144     }
145 
146     ret =  mbedtls_pk_parse_key(&pkey, (const unsigned char *) mbedtls_test_srv_key,
147                                 mbedtls_test_srv_key_len, NULL, 0);
148     if (ret != 0) {
149         mbedtls_printf(" failed\n  !  mbedtls_pk_parse_key returned %d\n\n", ret);
150         goto exit;
151     }
152 
153     mbedtls_printf(" ok\n");
154 
155     /*
156      * 3. Setup the listening TCP socket
157      */
158     mbedtls_printf("  . Bind on https://localhost:4433/ ...");
159     fflush(stdout);
160 
161     if ((ret = mbedtls_net_bind(&listen_fd, NULL, "4433", MBEDTLS_NET_PROTO_TCP)) != 0) {
162         mbedtls_printf(" failed\n  ! mbedtls_net_bind returned %d\n\n", ret);
163         goto exit;
164     }
165 
166     mbedtls_printf(" ok\n");
167 
168     /*
169      * 4. Setup stuff
170      */
171     mbedtls_printf("  . Setting up the SSL data....");
172     fflush(stdout);
173 
174     if ((ret = mbedtls_ssl_config_defaults(&conf,
175                                            MBEDTLS_SSL_IS_SERVER,
176                                            MBEDTLS_SSL_TRANSPORT_STREAM,
177                                            MBEDTLS_SSL_PRESET_DEFAULT)) != 0) {
178         mbedtls_printf(" failed\n  ! mbedtls_ssl_config_defaults returned %d\n\n", ret);
179         goto exit;
180     }
181 
182     mbedtls_ssl_conf_dbg(&conf, my_debug, stdout);
183 
184 #if defined(MBEDTLS_SSL_CACHE_C)
185     mbedtls_ssl_conf_session_cache(&conf, &cache,
186                                    mbedtls_ssl_cache_get,
187                                    mbedtls_ssl_cache_set);
188 #endif
189 
190     mbedtls_ssl_conf_ca_chain(&conf, srvcert.next, NULL);
191     if ((ret = mbedtls_ssl_conf_own_cert(&conf, &srvcert, &pkey)) != 0) {
192         mbedtls_printf(" failed\n  ! mbedtls_ssl_conf_own_cert returned %d\n\n", ret);
193         goto exit;
194     }
195 
196     if ((ret = mbedtls_ssl_setup(&ssl, &conf)) != 0) {
197         mbedtls_printf(" failed\n  ! mbedtls_ssl_setup returned %d\n\n", ret);
198         goto exit;
199     }
200 
201     mbedtls_printf(" ok\n");
202 
203 reset:
204 #ifdef MBEDTLS_ERROR_C
205     if (ret != 0) {
206         char error_buf[100];
207         mbedtls_strerror(ret, error_buf, 100);
208         mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf);
209     }
210 #endif
211 
212     mbedtls_net_free(&client_fd);
213 
214     mbedtls_ssl_session_reset(&ssl);
215 
216     /*
217      * 3. Wait until a client connects
218      */
219     mbedtls_printf("  . Waiting for a remote connection ...");
220     fflush(stdout);
221 
222     if ((ret = mbedtls_net_accept(&listen_fd, &client_fd,
223                                   NULL, 0, NULL)) != 0) {
224         mbedtls_printf(" failed\n  ! mbedtls_net_accept returned %d\n\n", ret);
225         goto exit;
226     }
227 
228     mbedtls_ssl_set_bio(&ssl, &client_fd, mbedtls_net_send, mbedtls_net_recv, NULL);
229 
230     mbedtls_printf(" ok\n");
231 
232     /*
233      * 5. Handshake
234      */
235     mbedtls_printf("  . Performing the SSL/TLS handshake...");
236     fflush(stdout);
237 
238     while ((ret = mbedtls_ssl_handshake(&ssl)) != 0) {
239         if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
240             mbedtls_printf(" failed\n  ! mbedtls_ssl_handshake returned %d\n\n", ret);
241             goto reset;
242         }
243     }
244 
245     mbedtls_printf(" ok\n");
246 
247     /*
248      * 6. Read the HTTP Request
249      */
250     mbedtls_printf("  < Read from client:");
251     fflush(stdout);
252 
253     do {
254         len = sizeof(buf) - 1;
255         memset(buf, 0, sizeof(buf));
256         ret = mbedtls_ssl_read(&ssl, buf, len);
257 
258         if (ret == MBEDTLS_ERR_SSL_WANT_READ || ret == MBEDTLS_ERR_SSL_WANT_WRITE) {
259             continue;
260         }
261 
262         if (ret <= 0) {
263             switch (ret) {
264                 case MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY:
265                     mbedtls_printf(" connection was closed gracefully\n");
266                     break;
267 
268                 case MBEDTLS_ERR_NET_CONN_RESET:
269                     mbedtls_printf(" connection was reset by peer\n");
270                     break;
271 
272                 default:
273                     mbedtls_printf(" mbedtls_ssl_read returned -0x%x\n", (unsigned int) -ret);
274                     break;
275             }
276 
277             break;
278         }
279 
280         len = ret;
281         mbedtls_printf(" %d bytes read\n\n%s", len, (char *) buf);
282 
283         if (ret > 0) {
284             break;
285         }
286     } while (1);
287 
288     /*
289      * 7. Write the 200 Response
290      */
291     mbedtls_printf("  > Write to client:");
292     fflush(stdout);
293 
294     len = sprintf((char *) buf, HTTP_RESPONSE,
295                   mbedtls_ssl_get_ciphersuite(&ssl));
296 
297     while ((ret = mbedtls_ssl_write(&ssl, buf, len)) <= 0) {
298         if (ret == MBEDTLS_ERR_NET_CONN_RESET) {
299             mbedtls_printf(" failed\n  ! peer closed the connection\n\n");
300             goto reset;
301         }
302 
303         if (ret != MBEDTLS_ERR_SSL_WANT_READ && ret != MBEDTLS_ERR_SSL_WANT_WRITE) {
304             mbedtls_printf(" failed\n  ! mbedtls_ssl_write returned %d\n\n", ret);
305             goto exit;
306         }
307     }
308 
309     len = ret;
310     mbedtls_printf(" %d bytes written\n\n%s\n", len, (char *) buf);
311 
312     mbedtls_printf("  . Closing the connection...");
313     fflush(stdout);
314 
315     while ((ret = mbedtls_ssl_close_notify(&ssl)) < 0) {
316         if (ret != MBEDTLS_ERR_SSL_WANT_READ &&
317             ret != MBEDTLS_ERR_SSL_WANT_WRITE &&
318             ret != MBEDTLS_ERR_NET_CONN_RESET) {
319             mbedtls_printf(" failed\n  ! mbedtls_ssl_close_notify returned %d\n\n", ret);
320             goto reset;
321         }
322     }
323 
324     mbedtls_printf(" ok\n");
325     fflush(stdout);
326 
327     ret = 0;
328     goto reset;
329 
330 exit:
331 
332 #ifdef MBEDTLS_ERROR_C
333     if (ret != 0) {
334         char error_buf[100];
335         mbedtls_strerror(ret, error_buf, 100);
336         mbedtls_printf("Last error was: %d - %s\n\n", ret, error_buf);
337     }
338 #endif
339 
340     mbedtls_net_free(&client_fd);
341     mbedtls_net_free(&listen_fd);
342     mbedtls_x509_crt_free(&srvcert);
343     mbedtls_pk_free(&pkey);
344     mbedtls_ssl_free(&ssl);
345     mbedtls_ssl_config_free(&conf);
346 #if defined(MBEDTLS_SSL_CACHE_C)
347     mbedtls_ssl_cache_free(&cache);
348 #endif
349     mbedtls_ctr_drbg_free(&ctr_drbg);
350     mbedtls_entropy_free(&entropy);
351     mbedtls_psa_crypto_free();
352 
353     mbedtls_exit(ret);
354 }
355 
356 #endif /* configuration allows running this program */
357