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