blob: b7be5c0b2cb2dd29eb9bfcc74507a27c55de303e [file] [log] [blame]
Manuel Pégourié-Gonnarde63582a2014-10-14 11:47:21 +02001/*
2 * Simple DTLS server demonstration program
3 *
4 * Copyright (C) 2014, Brainspark B.V.
5 *
Manuel Pégourié-Gonnard3d2c4b72015-01-29 11:33:59 +00006 * This file is part of mbed TLS (https://polarssl.org)
Manuel Pégourié-Gonnarde63582a2014-10-14 11:47:21 +02007 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 */
22
23#if !defined(POLARSSL_CONFIG_FILE)
24#include "polarssl/config.h"
25#else
26#include POLARSSL_CONFIG_FILE
27#endif
28
29#if !defined(POLARSSL_SSL_SRV_C) || !defined(POLARSSL_SSL_PROTO_DTLS) || \
30 !defined(POLARSSL_SSL_COOKIE_C) || !defined(POLARSSL_NET_C) || \
31 !defined(POLARSSL_ENTROPY_C) || !defined(POLARSSL_CTR_DRBG_C) || \
32 !defined(POLARSSL_X509_CRT_PARSE_C) || !defined(POLARSSL_RSA_C) || \
33 !defined(POLARSSL_CERTS_C)
34
35#include <stdio.h>
36int main( void )
37{
38 printf( "POLARSSL_SSL_SRV_C and/or POLARSSL_SSL_PROTO_DTLS and/or "
39 "POLARSSL_SSL_COOKIE_C and/or POLARSSL_NET_C and/or "
40 "POLARSSL_ENTROPY_C and/or POLARSSL_CTR_DRBG_C and/or "
41 "POLARSSL_X509_CRT_PARSE_C and/or POLARSSL_RSA_C and/or "
42 "POLARSSL_CERTS_C not defined.\n" );
43 return( 0 );
44}
45#else
46
47#if defined(_WIN32)
48#include <windows.h>
49#endif
50
51#include <string.h>
52#include <stdlib.h>
53#include <stdio.h>
54
55#include "polarssl/entropy.h"
56#include "polarssl/ctr_drbg.h"
57#include "polarssl/certs.h"
58#include "polarssl/x509.h"
59#include "polarssl/ssl.h"
60#include "polarssl/ssl_cookie.h"
61#include "polarssl/net.h"
62#include "polarssl/error.h"
63#include "polarssl/debug.h"
64
65#if defined(POLARSSL_SSL_CACHE_C)
66#include "polarssl/ssl_cache.h"
67#endif
68
69#define READ_TIMEOUT_MS 10000 /* 5 seconds */
70#define DEBUG_LEVEL 0
71
72static void my_debug( void *ctx, int level, const char *str )
73{
74 ((void) level);
75
76 fprintf( (FILE *) ctx, "%s", str );
77 fflush( (FILE *) ctx );
78}
79
80int main( void )
81{
82 int ret, len;
83 int listen_fd;
84 int client_fd = -1;
85 unsigned char buf[1024];
86 const char *pers = "dtls_server";
87 unsigned char client_ip[16] = { 0 };
88 ssl_cookie_ctx cookie_ctx;
89
90 entropy_context entropy;
91 ctr_drbg_context ctr_drbg;
92 ssl_context ssl;
93 x509_crt srvcert;
94 pk_context pkey;
95#if defined(POLARSSL_SSL_CACHE_C)
96 ssl_cache_context cache;
97#endif
98
99 memset( &ssl, 0, sizeof(ssl_context) );
100 ssl_cookie_init( &cookie_ctx );
101#if defined(POLARSSL_SSL_CACHE_C)
102 ssl_cache_init( &cache );
103#endif
104 x509_crt_init( &srvcert );
105 pk_init( &pkey );
106 entropy_init( &entropy );
107
108#if defined(POLARSSL_DEBUG_C)
109 debug_set_threshold( DEBUG_LEVEL );
110#endif
111
112 /*
113 * 1. Load the certificates and private RSA key
114 */
115 printf( "\n . Loading the server cert. and key..." );
116 fflush( stdout );
117
118 /*
119 * This demonstration program uses embedded test certificates.
120 * Instead, you may want to use x509_crt_parse_file() to read the
121 * server and CA certificates, as well as pk_parse_keyfile().
122 */
123 ret = x509_crt_parse( &srvcert, (const unsigned char *) test_srv_crt,
124 strlen( test_srv_crt ) );
125 if( ret != 0 )
126 {
127 printf( " failed\n ! x509_crt_parse returned %d\n\n", ret );
128 goto exit;
129 }
130
131 ret = x509_crt_parse( &srvcert, (const unsigned char *) test_ca_list,
132 strlen( test_ca_list ) );
133 if( ret != 0 )
134 {
135 printf( " failed\n ! x509_crt_parse returned %d\n\n", ret );
136 goto exit;
137 }
138
139 ret = pk_parse_key( &pkey, (const unsigned char *) test_srv_key,
140 strlen( test_srv_key ), NULL, 0 );
141 if( ret != 0 )
142 {
143 printf( " failed\n ! pk_parse_key returned %d\n\n", ret );
144 goto exit;
145 }
146
147 printf( " ok\n" );
148
149 /*
150 * 2. Setup the "listening" UDP socket
151 */
152 printf( " . Bind on udp/*/4433 ..." );
153 fflush( stdout );
154
155 if( ( ret = net_bind( &listen_fd, NULL, 4433, NET_PROTO_UDP ) ) != 0 )
156 {
157 printf( " failed\n ! net_bind returned %d\n\n", ret );
158 goto exit;
159 }
160
161 printf( " ok\n" );
162
163 /*
164 * 3. Seed the RNG
165 */
166 printf( " . Seeding the random number generator..." );
167 fflush( stdout );
168
169 if( ( ret = ctr_drbg_init( &ctr_drbg, entropy_func, &entropy,
170 (const unsigned char *) pers,
171 strlen( pers ) ) ) != 0 )
172 {
173 printf( " failed\n ! ctr_drbg_init returned %d\n", ret );
174 goto exit;
175 }
176
177 printf( " ok\n" );
178
179 /*
180 * 4. Setup stuff
181 */
182 printf( " . Setting up the DTLS data..." );
183 fflush( stdout );
184
185 if( ( ret = ssl_init( &ssl ) ) != 0 )
186 {
187 printf( " failed\n ! ssl_init returned %d\n\n", ret );
188 goto exit;
189 }
190
191 ssl_set_endpoint( &ssl, SSL_IS_SERVER );
192 ssl_set_transport( &ssl, SSL_TRANSPORT_DATAGRAM );
193 ssl_set_authmode( &ssl, SSL_VERIFY_NONE );
194
195 ssl_set_rng( &ssl, ctr_drbg_random, &ctr_drbg );
196 ssl_set_dbg( &ssl, my_debug, stdout );
197
198#if defined(POLARSSL_SSL_CACHE_C)
199 ssl_set_session_cache( &ssl, ssl_cache_get, &cache,
200 ssl_cache_set, &cache );
201#endif
202
203 ssl_set_ca_chain( &ssl, srvcert.next, NULL, NULL );
204 if( ( ret = ssl_set_own_cert( &ssl, &srvcert, &pkey ) ) != 0 )
205 {
206 printf( " failed\n ! ssl_set_own_cert returned %d\n\n", ret );
207 goto exit;
208 }
209
210 if( ( ret = ssl_cookie_setup( &cookie_ctx,
211 ctr_drbg_random, &ctr_drbg ) ) != 0 )
212 {
213 printf( " failed\n ! ssl_cookie_setup returned %d\n\n", ret );
214 goto exit;
215 }
216
217 ssl_set_dtls_cookies( &ssl, ssl_cookie_write, ssl_cookie_check,
218 &cookie_ctx );
219
220 printf( " ok\n" );
221
222reset:
223#ifdef POLARSSL_ERROR_C
224 if( ret != 0 )
225 {
226 char error_buf[100];
227 polarssl_strerror( ret, error_buf, 100 );
228 printf("Last error was: %d - %s\n\n", ret, error_buf );
229 }
230#endif
231
232 if( client_fd != -1 )
233 net_close( client_fd );
234
235 ssl_session_reset( &ssl );
236
237 /*
238 * 3. Wait until a client connects
239 */
240 client_fd = -1;
241
242 printf( " . Waiting for a remote connection ..." );
243 fflush( stdout );
244
245 if( ( ret = net_accept( listen_fd, &client_fd, client_ip ) ) != 0 )
246 {
247 printf( " failed\n ! net_accept returned %d\n\n", ret );
248 goto exit;
249 }
250
251 /* With UDP, bind_fd is hijacked by client_fd, so bind a new one */
252 if( ( ret = net_bind( &listen_fd, NULL, 4433, NET_PROTO_UDP ) ) != 0 )
253 {
254 printf( " failed\n ! net_bind returned -0x%x\n\n", -ret );
255 goto exit;
256 }
257
258 /* For HelloVerifyRequest cookies */
259 if( ( ret = ssl_set_client_transport_id( &ssl, client_ip,
260 sizeof( client_ip ) ) ) != 0 )
261 {
262 printf( " failed\n ! "
263 "ssl_set_client_tranport_id() returned -0x%x\n\n", -ret );
264 goto exit;
265 }
266
267 ssl_set_bio_timeout( &ssl, &client_fd,
268 net_send, net_recv, net_recv_timeout,
269 READ_TIMEOUT_MS );
270
271 printf( " ok\n" );
272
273 /*
274 * 5. Handshake
275 */
276 printf( " . Performing the DTLS handshake..." );
277 fflush( stdout );
278
279 do ret = ssl_handshake( &ssl );
280 while( ret == POLARSSL_ERR_NET_WANT_READ ||
281 ret == POLARSSL_ERR_NET_WANT_WRITE );
282
283 if( ret == POLARSSL_ERR_SSL_HELLO_VERIFY_REQUIRED )
284 {
285 printf( " hello verification requested\n" );
286 ret = 0;
287 goto reset;
288 }
289 else if( ret != 0 )
290 {
291 printf( " failed\n ! ssl_handshake returned -0x%x\n\n", -ret );
292 goto reset;
293 }
294
295 printf( " ok\n" );
296
297 /*
298 * 6. Read the echo Request
299 */
300 printf( " < Read from client:" );
301 fflush( stdout );
302
303 len = sizeof( buf ) - 1;
304 memset( buf, 0, sizeof( buf ) );
305
306 do ret = ssl_read( &ssl, buf, len );
307 while( ret == POLARSSL_ERR_NET_WANT_READ ||
308 ret == POLARSSL_ERR_NET_WANT_WRITE );
309
310 if( ret <= 0 )
311 {
312 switch( ret )
313 {
314 case POLARSSL_ERR_NET_TIMEOUT:
315 printf( " timeout\n\n" );
316 goto reset;
317
318 case POLARSSL_ERR_SSL_PEER_CLOSE_NOTIFY:
319 printf( " connection was closed gracefully\n" );
320 ret = 0;
321 goto close_notify;
322
323 default:
324 printf( " ssl_read returned -0x%x\n\n", -ret );
325 goto reset;
326 }
327 }
328
329 len = ret;
330 printf( " %d bytes read\n\n%s\n\n", len, buf );
331
332 /*
333 * 7. Write the 200 Response
334 */
335 printf( " > Write to client:" );
336 fflush( stdout );
337
338 do ret = ssl_write( &ssl, buf, len );
339 while( ret == POLARSSL_ERR_NET_WANT_READ ||
340 ret == POLARSSL_ERR_NET_WANT_WRITE );
341
342 if( ret < 0 )
343 {
344 printf( " failed\n ! ssl_write returned %d\n\n", ret );
345 goto exit;
346 }
347
348 len = ret;
349 printf( " %d bytes written\n\n%s\n\n", len, buf );
350
351 /*
352 * 8. Done, cleanly close the connection
353 */
354close_notify:
355 printf( " . Closing the connection..." );
356
357 /* No error checking, the connection might be closed already */
358 do ret = ssl_close_notify( &ssl );
359 while( ret == POLARSSL_ERR_NET_WANT_WRITE );
360 ret = 0;
361
362 printf( " done\n" );
363
364 goto reset;
365
366 /*
367 * Final clean-ups and exit
368 */
369exit:
370
371#ifdef POLARSSL_ERROR_C
372 if( ret != 0 )
373 {
374 char error_buf[100];
375 polarssl_strerror( ret, error_buf, 100 );
376 printf( "Last error was: %d - %s\n\n", ret, error_buf );
377 }
378#endif
379
380 if( client_fd != -1 )
381 net_close( client_fd );
382
383 x509_crt_free( &srvcert );
384 pk_free( &pkey );
385 ssl_free( &ssl );
386 ssl_cookie_free( &cookie_ctx );
387#if defined(POLARSSL_SSL_CACHE_C)
388 ssl_cache_free( &cache );
389#endif
390 ctr_drbg_free( &ctr_drbg );
391 entropy_free( &entropy );
392
393#if defined(_WIN32)
394 printf( " Press Enter to exit this program.\n" );
395 fflush( stdout ); getchar();
396#endif
397
398 /* Shell can not handle large exit numbers -> 1 for errors */
399 if( ret < 0 )
400 ret = 1;
401
402 return( ret );
403}
404#endif /* POLARSSL_SSL_SRV_C && POLARSSL_SSL_PROTO_DTLS &&
405 POLARSSL_SSL_COOKIE_C && POLARSSL_NET_C && POLARSSL_ENTROPY_C &&
406 POLARSSL_CTR_DRBG_C && POLARSSL_X509_CRT_PARSE_C && POLARSSL_RSA_C
407 && POLARSSL_CERTS_C */