Remove unused pkg dependancy
[platform/upstream/iotivity.git] / extlibs / tinydtls / tests / dtls-server.c
1
2 /* This is needed for apple */
3 #define __APPLE_USE_RFC_3542
4
5 #include "iotivity_config.h"
6 #include <assert.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <errno.h>
10 #ifdef HAVE_UNISTD_H
11 #include <unistd.h>
12 #endif
13 #ifdef HAVE_NETINET_IN_H
14 #include <netinet/in.h>
15 #endif
16 #include <sys/types.h>
17 #ifdef HAVE_SYS_SOCKET_H
18 #include <sys/socket.h>
19 #endif
20 #ifdef HAVE_SYS_TIME_H
21 #include <sys/time.h>
22 #endif
23 #ifdef HAVE_NETDB_H
24 #include <netdb.h>
25 #endif
26 #include <signal.h>
27 #include <getopt.h>
28 #include "platform_features.h"
29
30 #include "tinydtls.h"
31 #include "dtls.h"
32 #include "debug.h"
33
34 #ifdef DTLS_X509
35 #define DTLS_PRIVATE_KEY_SIZE        (32)
36 #define DTLS_PUBLIC_KEY_SIZE         (64)
37 #endif
38
39 #define DEFAULT_PORT 20220
40
41 /**
42  * @struct byte_array
43  *
44  * General purpose byte array structure.
45  *
46  * Contains pointer to array of bytes and it's length.
47  */
48
49 typedef struct
50 {
51     uint8_t *data;    /**< Pointer to the byte array */
52     size_t len;      /**< Data size */
53 } byte_array;
54
55
56 /**@def BYTE_ARRAY_INITIALIZER
57  *
58  * Initializes of existing byte array pointer to \a NULL.
59  */
60 #undef BYTE_ARRAY_INITIALIZER
61 #define BYTE_ARRAY_INITIALIZER {NULL, 0}
62
63 #ifdef DTLS_X509
64 #define X509_OPTIONS         "x:r:u:"
65 #define SERVER_CRT_LEN 295
66 static const unsigned char g_server_certificate[SERVER_CRT_LEN] = {
67         0x00, 0x01, 0x24,
68         0x30, 0x82, 0x01, 0x20, 0x30, 0x81, 0xc4, 0xa0,
69         0x03, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x37,
70         0x30, 0x0c, 0x06, 0x08, 0x2a, 0x86, 0x48, 0xce,
71         0x3d, 0x04, 0x03, 0x02, 0x05, 0x00, 0x30, 0x17,
72         0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55, 0x04,
73         0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61, 0x6c,
74         0x20, 0x49, 0x53, 0x53, 0x55, 0x45, 0x52, 0x30,
75         0x1e, 0x17, 0x0d, 0x31, 0x33, 0x30, 0x31, 0x30,
76         0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
77         0x17, 0x0d, 0x34, 0x39, 0x30, 0x31, 0x30, 0x31,
78         0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30,
79         0x17, 0x31, 0x15, 0x30, 0x13, 0x06, 0x03, 0x55,
80         0x04, 0x03, 0x0c, 0x0c, 0x4c, 0x6f, 0x63, 0x61,
81         0x6c, 0x20, 0x53, 0x45, 0x52, 0x56, 0x45, 0x52,
82         0x30, 0x59, 0x30, 0x13, 0x06, 0x07, 0x2a, 0x86,
83         0x48, 0xce, 0x3d, 0x02, 0x01, 0x06, 0x08, 0x2a,
84         0x86, 0x48, 0xce, 0x3d, 0x03, 0x01, 0x07, 0x03,
85         0x42, 0x00, 0x04, 0x07, 0x88, 0x10, 0xdc, 0x62,
86         0xd7, 0xe6, 0x9b, 0x7c, 0xad, 0x6e, 0x78, 0xb0,
87         0x5f, 0x9a, 0x00, 0x11, 0x74, 0x2c, 0x8b, 0xaf,
88         0x09, 0x65, 0x7c, 0x86, 0x8e, 0x55, 0xcb, 0x39,
89         0x55, 0x72, 0xc6, 0x65, 0x71, 0xcd, 0x03, 0xdc,
90         0x2a, 0x4f, 0x46, 0x5b, 0x14, 0xc8, 0x27, 0x74,
91         0xab, 0xf4, 0x1f, 0xc1, 0x35, 0x0d, 0x42, 0xbc,
92         0xc2, 0x9f, 0xb5, 0xc1, 0x79, 0xb6, 0x8b, 0xca,
93         0xdb, 0xff, 0x82, 0x30, 0x0c, 0x06, 0x08, 0x2a,
94         0x86, 0x48, 0xce, 0x3d, 0x04, 0x03, 0x02, 0x05,
95         0x00, 0x03, 0x49, 0x00, 0x30, 0x46, 0x02, 0x21,
96         0x00, 0xb1, 0x81, 0x81, 0x92, 0x0e, 0x76, 0x7c,
97         0xeb, 0xf5, 0x37, 0xde, 0x27, 0xc4, 0x01, 0xc8,
98         0x96, 0xc3, 0xe5, 0x9f, 0x47, 0x7e, 0x25, 0x92,
99         0xa4, 0xba, 0x22, 0x25, 0xa3, 0x81, 0x19, 0xcf,
100         0x0d, 0x02, 0x21, 0x00, 0xca, 0x92, 0xbe, 0x79,
101         0xc7, 0x82, 0x84, 0x64, 0xc4, 0xc4, 0xf4, 0x3d,
102         0x69, 0x79, 0x68, 0xc0, 0xf1, 0xba, 0xaf, 0x6c,
103         0xbb, 0xdd, 0x54, 0x7d, 0x07, 0xe7, 0x53, 0x3b,
104         0xc3, 0x1b, 0x87, 0x04};
105
106 //default server's key pair
107 static const unsigned char x509_priv_key[] = {
108         0xaa, 0xa3, 0x46, 0xf1, 0x3c, 0x56, 0x5d, 0x08,
109         0x5e, 0x59, 0xba, 0x7f, 0xd2, 0x21, 0x62, 0xc6,
110         0xcc, 0x5d, 0xfa, 0x3f, 0xb5, 0x25, 0xa9, 0x89,
111         0x4f, 0x32, 0xe8, 0x2a, 0xe0, 0xee, 0x9b, 0x4c};
112
113 static const unsigned char x509_pub_key_x[] = {
114         0x07, 0x88, 0x10, 0xdc, 0x62, 0xd7, 0xe6, 0x9b,
115         0x7c, 0xad, 0x6e, 0x78, 0xb0, 0x5f, 0x9a, 0x00,
116         0x11, 0x74, 0x2c, 0x8b, 0xaf, 0x09, 0x65, 0x7c,
117         0x86, 0x8e, 0x55, 0xcb, 0x39, 0x55, 0x72, 0xc6};
118
119 static const unsigned char x509_pub_key_y[] = {
120         0x65, 0x71, 0xcd, 0x03, 0xdc, 0x2a, 0x4f, 0x46,
121         0x5b, 0x14, 0xc8, 0x27, 0x74, 0xab, 0xf4, 0x1f,
122         0xc1, 0x35, 0x0d, 0x42, 0xbc, 0xc2, 0x9f, 0xb5,
123         0xc1, 0x79, 0xb6, 0x8b, 0xca, 0xdb, 0xff, 0x82};
124
125 //default CA pub key
126 static const unsigned char x509_ca_pub_x[] = {
127         0x57, 0x94, 0x7f, 0x98, 0x7a, 0x02, 0x67, 0x09,
128         0x25, 0xc1, 0xcb, 0x5a, 0xf5, 0x46, 0xfb, 0xad,
129         0xf7, 0x68, 0x94, 0x8c, 0xa7, 0xe3, 0xf0, 0x5b,
130         0xc3, 0x6b, 0x5c, 0x9b, 0xd3, 0x7d, 0x74, 0x12
131 };
132
133 static const unsigned char x509_ca_pub_y[] = {
134         0xce, 0x68, 0xbc, 0x55, 0xf5, 0xf8, 0x1b, 0x3d,
135         0xef, 0xed, 0x1f, 0x2b, 0xd2, 0x69, 0x5d, 0xcf,
136         0x79, 0x16, 0xa6, 0xbd, 0x97, 0x96, 0x27, 0x60,
137         0x5d, 0xd1, 0xb7, 0x93, 0xa2, 0x4a, 0x62, 0x4d
138 };
139
140 static const unsigned char client_pub_key_x[] = {
141         0xe3, 0xd1, 0x67, 0x1e, 0xdc, 0x46, 0xf4, 0x19,
142         0x50, 0x15, 0x2e, 0x3a, 0x2f, 0xd8, 0x68, 0x6b,
143         0x37, 0x32, 0x84, 0x9e, 0x83, 0x81, 0xbf, 0x25,
144         0x5d, 0xbb, 0x18, 0x07, 0x3c, 0xbd, 0xf3, 0xab};
145
146 static const unsigned char client_pub_key_y[] = {
147         0xd3, 0xbf, 0x53, 0x59, 0xc9, 0x1e, 0xce, 0x5b,
148         0x39, 0x6a, 0xe5, 0x60, 0xf3, 0x70, 0xdb, 0x66,
149         0xb6, 0x80, 0xcb, 0x65, 0x0b, 0x35, 0x2a, 0x62,
150         0x44, 0x89, 0x63, 0x64, 0x6f, 0x6f, 0xbd, 0xf0};
151
152 static unsigned char x509_server_cert[DTLS_MAX_CERT_SIZE];
153 static size_t x509_server_cert_len = 0;
154 static unsigned char x509_server_priv[DTLS_PRIVATE_KEY_SIZE+1];
155 static size_t x509_server_priv_is_set = 0;
156 static unsigned char x509_ca_pub[DTLS_PUBLIC_KEY_SIZE+1];
157 static size_t x509_ca_pub_is_set = 0;
158
159 static int x509_info_from_file = 0;
160 #endif /*DTLS_X509*/
161 #ifdef DTLS_ECC
162 static const unsigned char ecdsa_priv_key[] = {
163                         0xD9, 0xE2, 0x70, 0x7A, 0x72, 0xDA, 0x6A, 0x05,
164                         0x04, 0x99, 0x5C, 0x86, 0xED, 0xDB, 0xE3, 0xEF,
165                         0xC7, 0xF1, 0xCD, 0x74, 0x83, 0x8F, 0x75, 0x70,
166                         0xC8, 0x07, 0x2D, 0x0A, 0x76, 0x26, 0x1B, 0xD4};
167
168 static const unsigned char ecdsa_pub_key_x[] = {
169                         0xD0, 0x55, 0xEE, 0x14, 0x08, 0x4D, 0x6E, 0x06,
170                         0x15, 0x59, 0x9D, 0xB5, 0x83, 0x91, 0x3E, 0x4A,
171                         0x3E, 0x45, 0x26, 0xA2, 0x70, 0x4D, 0x61, 0xF2,
172                         0x7A, 0x4C, 0xCF, 0xBA, 0x97, 0x58, 0xEF, 0x9A};
173
174 static const unsigned char ecdsa_pub_key_y[] = {
175                         0xB4, 0x18, 0xB6, 0x4A, 0xFE, 0x80, 0x30, 0xDA,
176                         0x1D, 0xDC, 0xF4, 0xF4, 0x2E, 0x2F, 0x26, 0x31,
177                         0xD0, 0x43, 0xB1, 0xFB, 0x03, 0xE2, 0x2F, 0x4D,
178                         0x17, 0xDE, 0x43, 0xF9, 0xF9, 0xAD, 0xEE, 0x70};
179 #endif /*DTLS_ECC*/
180 #if 0
181 /* SIGINT handler: set quit to 1 for graceful termination */
182 void
183 handle_sigint(int signum) {
184   dsrv_stop(dsrv_get_context());
185 }
186 #endif
187
188 #ifdef DTLS_X509
189 ssize_t
190 read_from_file(char *arg, unsigned char *buf, size_t max_buf_len) {
191   FILE *f;
192   ssize_t result = 0;
193
194   f = fopen(arg, "r");
195   if (f == NULL)
196     return -1;
197
198   while (!feof(f)) {
199     size_t bytes_read;
200     bytes_read = fread(buf, 1, max_buf_len, f);
201     if (ferror(f)) {
202       result = -1;
203       break;
204     }
205
206     buf += bytes_read;
207     result += bytes_read;
208     max_buf_len -= bytes_read;
209   }
210
211   fclose(f);
212   return result;
213 }
214 #endif /*DTLS_X509*/
215
216 #ifdef DTLS_PSK
217
218 #define PSK_SERVER_HINT  "Server_identity"
219
220 /* This function is the "key store" for tinyDTLS. It is called to
221  * retrieve a key for the given identity within this particular
222  * session. */
223 static int
224 get_psk_info(struct dtls_context_t *ctx, const session_t *session,
225              dtls_credentials_type_t type,
226              const unsigned char *id, size_t id_len,
227              unsigned char *result, size_t result_length) {
228
229   (void)ctx;
230   (void)session;
231   struct keymap_t {
232     unsigned char *id;
233     size_t id_length;
234     unsigned char *key;
235     size_t key_length;
236   } psk[3] = {
237     { (unsigned char *)"Client_identity", 15,
238       (unsigned char *)"secretPSK", 9 },
239     { (unsigned char *)"default identity", 16,
240       (unsigned char *)"\x11\x22\x33", 3 },
241     { (unsigned char *)"\0", 2,
242       (unsigned char *)"", 1 }
243   };
244
245   switch (type) {
246   case DTLS_PSK_HINT:
247     if (result_length < strlen(PSK_SERVER_HINT)) {
248       dtls_warn("cannot set psk_hint -- buffer too small\n");
249       return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
250     }
251
252     memcpy(result, PSK_SERVER_HINT, strlen(PSK_SERVER_HINT));
253     return strlen(PSK_SERVER_HINT);
254
255   case DTLS_PSK_KEY:
256     if (id) {
257       int i;
258       for (i = 0; i < (int)(sizeof(psk)/sizeof(struct keymap_t)); i++) {
259         if (id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) {
260           if (result_length < psk[i].key_length) {
261             dtls_warn("buffer too small for PSK");
262             return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
263           }
264
265           memcpy(result, psk[i].key, psk[i].key_length);
266           return psk[i].key_length;
267         }
268       }
269     }
270     break;
271
272   default:
273     dtls_warn("unsupported request type: %d\n", type);
274   }
275
276   return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
277 }
278
279 #endif /* DTLS_PSK */
280
281 #ifdef DTLS_ECC
282 static int
283 get_ecdsa_key(struct dtls_context_t *ctx,
284               const session_t *session,
285               const dtls_ecc_key_t **result) {
286     (void)ctx;
287     (void)session;
288   static const dtls_ecc_key_t ecdsa_key = {
289     .curve = DTLS_ECDH_CURVE_SECP256R1,
290     .priv_key = ecdsa_priv_key,
291     .pub_key_x = ecdsa_pub_key_x,
292     .pub_key_y = ecdsa_pub_key_y
293   };
294
295   *result = &ecdsa_key;
296   return 0;
297 }
298
299 static int
300 verify_ecdsa_key(struct dtls_context_t *ctx,
301                  const session_t *session,
302                  const unsigned char *other_pub_x,
303                  const unsigned char *other_pub_y,
304                  size_t key_size) {
305   (void)ctx;
306   (void)session;
307   (void)other_pub_x;
308   (void)other_pub_y;
309   (void)key_size;
310   return 0;
311 }
312 #endif /* DTLS_ECC */
313
314 #ifdef DTLS_X509
315 static int
316 get_x509_key(struct dtls_context_t *ctx,
317           const session_t *session,
318           const dtls_ecc_key_t **result) {
319     (void)ctx;
320     (void)session;
321   static dtls_ecc_key_t ecdsa_key = {
322     .curve = DTLS_ECDH_CURVE_SECP256R1,
323     .priv_key = x509_priv_key,
324     .pub_key_x = x509_pub_key_x,
325     .pub_key_y = x509_pub_key_y
326   };
327   if (x509_info_from_file)
328       ecdsa_key.priv_key = x509_server_priv;
329
330   *result = &ecdsa_key;
331   return 0;
332 }
333
334 static int
335 get_x509_cert(struct dtls_context_t *ctx,
336                 const session_t *session,
337                 const unsigned char **cert,
338                 size_t *cert_size)
339 {
340     (void)ctx;
341     (void)session;
342     if (x509_info_from_file)
343     {
344         *cert = x509_server_cert;
345         *cert_size = x509_server_cert_len;
346     }
347     else
348     {
349         *cert = g_server_certificate;
350         *cert_size = SERVER_CRT_LEN;
351     }
352
353     return 0;
354 }
355
356 static int check_certificate(byte_array cert_der_code, byte_array ca_public_key)
357 {
358     (void)cert_der_code;
359     (void)ca_public_key;
360     return 0;
361 }
362
363 static int verify_x509_cert(struct dtls_context_t *ctx, const session_t *session,
364                                   const unsigned char *cert, size_t cert_size,
365                                   unsigned char *x,
366                                   size_t x_size,
367                                   unsigned char *y,
368                                   size_t y_size)
369 {
370     int ret;
371     const unsigned char *ca_pub_x;
372     const unsigned char *ca_pub_y;
373     byte_array cert_der_code = BYTE_ARRAY_INITIALIZER;
374     byte_array ca_public_key = BYTE_ARRAY_INITIALIZER;
375     unsigned char ca_pub_key[DTLS_PUBLIC_KEY_SIZE];
376     (void)ctx;
377     (void)session;
378
379     if (x509_info_from_file)
380     {
381         ca_pub_x = x509_ca_pub;
382         ca_pub_y = x509_ca_pub + DTLS_PUBLIC_KEY_SIZE/2;
383     }
384     else
385     {
386         ca_pub_x = x509_ca_pub_x;
387         ca_pub_y = x509_ca_pub_y;
388     }
389
390     cert_der_code.data = (uint8_t *)cert;
391     cert_der_code.len = cert_size;
392
393     ca_public_key.len = DTLS_PUBLIC_KEY_SIZE;
394     ca_public_key.data = ca_pub_key;
395     memcpy(ca_public_key.data, ca_pub_x, DTLS_PUBLIC_KEY_SIZE/2);
396     memcpy(ca_public_key.data + DTLS_PUBLIC_KEY_SIZE/2, ca_pub_y, DTLS_PUBLIC_KEY_SIZE/2);
397
398     memcpy(x, client_pub_key_x, x_size);
399     memcpy(y, client_pub_key_y, y_size);
400
401     ret = (int) check_certificate(cert_der_code, ca_public_key);
402
403   return -ret;
404 }
405
406 static int is_x509_active(struct dtls_context_t *ctx)
407 {
408     (void)ctx;
409     return 0;
410 }
411 #endif /* DTLS_X509 */
412
413
414 #define DTLS_SERVER_CMD_CLOSE "server:close"
415 #define DTLS_SERVER_CMD_RENEGOTIATE "server:renegotiate"
416
417 static int
418 read_from_peer(struct dtls_context_t *ctx,
419                session_t *session, uint8 *data, size_t len) {
420   size_t i;
421   for (i = 0; i < len; i++)
422     printf("%c", data[i]);
423   if (len >= strlen(DTLS_SERVER_CMD_CLOSE) &&
424       !memcmp(data, DTLS_SERVER_CMD_CLOSE, strlen(DTLS_SERVER_CMD_CLOSE))) {
425     printf("server: closing connection\n");
426     dtls_close(ctx, session);
427     return len;
428   } else if (len >= strlen(DTLS_SERVER_CMD_RENEGOTIATE) &&
429       !memcmp(data, DTLS_SERVER_CMD_RENEGOTIATE, strlen(DTLS_SERVER_CMD_RENEGOTIATE))) {
430     printf("server: renegotiate connection\n");
431     dtls_renegotiate(ctx, session);
432     return len;
433   }
434
435   return dtls_write(ctx, session, data, len);
436 }
437
438 static int
439 send_to_peer(struct dtls_context_t *ctx, 
440              session_t *session, uint8 *data, size_t len) {
441
442   int fd = *(int *)dtls_get_app_data(ctx);
443   return sendto(fd, data, len, MSG_DONTWAIT,
444                 &session->addr.sa, session->size);
445 }
446
447 static int
448 dtls_handle_read(struct dtls_context_t *ctx) {
449   int *fd;
450   session_t session;
451   static uint8 buf[DTLS_MAX_BUF];
452   int len;
453
454   fd = dtls_get_app_data(ctx);
455
456   assert(fd);
457
458   memset(&session, 0, sizeof(session_t));
459   session.size = sizeof(session.addr);
460   len = recvfrom(*fd, buf, sizeof(buf), MSG_TRUNC,
461                  &session.addr.sa, &session.size);
462
463   if (len < 0) {
464     perror("recvfrom");
465     return -1;
466   } else {
467     dtls_debug("got %d bytes from port %d\n", len, 
468              ntohs(session.addr.sin6.sin6_port));
469     if ((int)(sizeof(buf)) < len) {
470       dtls_warn("packet was truncated (%d bytes lost)\n", len - sizeof(buf));
471     }
472   }
473
474   return dtls_handle_message(ctx, &session, buf, len);
475 }    
476
477 static int
478 resolve_address(const char *server, struct sockaddr *dst) {
479   
480   struct addrinfo *res, *ainfo;
481   struct addrinfo hints;
482   static char addrstr[256];
483   int error;
484
485   memset(addrstr, 0, sizeof(addrstr));
486   if (server && strlen(server) > 0)
487     memcpy(addrstr, server, strlen(server));
488   else
489     memcpy(addrstr, "localhost", 9);
490
491   memset ((char *)&hints, 0, sizeof(hints));
492   hints.ai_socktype = SOCK_DGRAM;
493   hints.ai_family = AF_UNSPEC;
494
495   error = getaddrinfo(addrstr, "", &hints, &res);
496
497   if (error != 0) {
498     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
499     return error;
500   }
501
502   for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
503
504     switch (ainfo->ai_family) {
505     case AF_INET6:
506
507       memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen);
508       return ainfo->ai_addrlen;
509     default:
510       ;
511     }
512   }
513
514   freeaddrinfo(res);
515   return -1;
516 }
517
518 static void
519 usage(const char *program, const char *version) {
520   const char *p;
521
522   p = strrchr( program, '/' );
523   if ( p )
524     program = ++p;
525
526   fprintf(stderr, "%s v%s -- DTLS server implementation\n"
527           "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
528           "usage: %s [-A address] [-p port] [-v num] [-a enable|disable]\n"
529 #ifdef DTLS_X509
530       " [-x file] [-r file] [-u file]"
531 #endif /* DTLS_X509 */
532           "\t-A address\t\tlisten on specified address (default is ::)\n"
533           "\t-p port\t\tlisten on specified port (default is %d)\n"
534           "\t-v num\t\tverbosity level (default: 3)\n"
535           "\t-a enable|disable\t(default: disable)\n"
536           "\t\t\t\tenable:enable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
537           "\t\t\t\tdisable:disable TLS_ECDH_anon_with_AES_128_CBC_SHA_256\n"
538 #ifdef DTLS_X509
539       "\t-x file\tread Server certificate from file\n"
540       "\t-r file\tread Server private key from file\n"
541       "\t-u file\tread CA public key from file\n"
542 #endif /* DTLS_X509 */
543       ,program, version, program, DEFAULT_PORT);
544 }
545
546 static dtls_handler_t cb = {
547   .write = send_to_peer,
548   .read  = read_from_peer,
549   .event = NULL,
550 #ifdef DTLS_PSK
551   .get_psk_info = get_psk_info,
552 #endif /* DTLS_PSK */
553 #ifdef DTLS_ECC
554   .get_ecdsa_key = get_ecdsa_key,
555   .verify_ecdsa_key = verify_ecdsa_key,
556 #endif /* DTLS_ECC */
557 #ifdef DTLS_X509
558   .get_x509_key = get_x509_key,
559   .verify_x509_cert = verify_x509_cert,
560   .get_x509_cert = get_x509_cert,
561   .is_x509_active = is_x509_active,
562 #endif
563
564 };
565
566 int
567 main(int argc, char **argv) {
568   dtls_context_t *the_context = NULL;
569   log_t log_level = DTLS_LOG_WARN;
570   fd_set rfds, wfds;
571   struct timeval timeout;
572   int fd, opt, result;
573   int on = 1;
574   dtls_cipher_enable_t ecdh_anon_enalbe = DTLS_CIPHER_DISABLE;
575   struct sockaddr_in6 listen_addr;
576
577   memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
578
579   /* fill extra field for 4.4BSD-based systems (see RFC 3493, section 3.4) */
580 #if defined(SIN6_LEN) || defined(HAVE_SOCKADDR_IN6_SIN6_LEN)
581   listen_addr.sin6_len = sizeof(struct sockaddr_in6);
582 #endif
583
584   listen_addr.sin6_family = AF_INET6;
585   listen_addr.sin6_port = htons(DEFAULT_PORT);
586   listen_addr.sin6_addr = in6addr_any;
587
588   while ((opt = getopt(argc, argv, "A:p:v:a:")) != -1) {
589     switch (opt) {
590     case 'A' :
591       if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) {
592         fprintf(stderr, "cannot resolve address\n");
593         exit(-1);
594       }
595       break;
596     case 'p' :
597       listen_addr.sin6_port = htons(atoi(optarg));
598       break;
599     case 'v' :
600       log_level = strtol(optarg, NULL, 10);
601       break;
602     case 'a':
603       if( strcmp(optarg, "enable") == 0)
604           ecdh_anon_enalbe = DTLS_CIPHER_ENABLE;
605       break;
606 #ifdef DTLS_X509
607     case 'x' :
608     {
609       ssize_t result = read_from_file(optarg, x509_server_cert, DTLS_MAX_CERT_SIZE);
610       if (result < 0)
611       {
612           dtls_warn("Cannot read Server certificate. Using default\n");
613       }
614       else
615       {
616           x509_server_cert_len = result;
617       }
618       break;
619     }
620     case 'r' :
621     {
622       ssize_t result = read_from_file(optarg, x509_server_priv, DTLS_PRIVATE_KEY_SIZE+1);
623       if (result < 0)
624       {
625           dtls_warn("Cannot read Server private key. Using default\n");
626       }
627       else
628       {
629           x509_server_priv_is_set = result;
630       }
631       break;
632     }
633     case 'u' :
634     {
635       ssize_t result = read_from_file(optarg, x509_ca_pub, DTLS_PUBLIC_KEY_SIZE+1);
636       if (result < 0)
637       {
638           dtls_warn("Cannot read CA public key. Using default\n");
639       }
640       else
641       {
642           x509_ca_pub_is_set = result;
643       }
644       break;
645     }
646 #endif /* DTLS_X509 */
647     default:
648       usage(argv[0], dtls_package_version());
649       exit(1);
650     }
651   }
652
653   dtls_set_log_level(log_level);
654
655 #ifdef DTLS_X509
656   if (x509_server_cert_len && x509_server_priv_is_set && x509_ca_pub_is_set)
657   {
658       x509_info_from_file = 1;
659   }
660   else if(!(x509_server_cert_len || x509_server_priv_is_set || x509_ca_pub_is_set))
661   {
662       x509_info_from_file = 0;
663   }
664   else
665   {
666       fprintf(stderr,"please set -x, -r, -u options simultaneously");
667       usage(argv[0], dtls_package_version());
668       exit(1);
669   }
670 #endif /* DTLS_X509 */
671
672   /* init socket and set it to non-blocking */
673   fd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0);
674
675   if (fd < 0) {
676     dtls_alert("socket: %s\n", strerror(errno));
677     return 0;
678   }
679
680   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, OPTVAL_T(&on), sizeof(on) ) < 0) {
681     dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno));
682   }
683 #if 0
684   flags = fcntl(fd, F_GETFL, 0);
685   if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
686     dtls_alert("fcntl: %s\n", strerror(errno));
687     goto error;
688   }
689 #endif
690   on = 1;
691 #ifdef IPV6_RECVPKTINFO
692   if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) {
693 #else /* IPV6_RECVPKTINFO */
694   if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, OPTVAL_T(&on), sizeof(on) ) < 0) {
695 #endif /* IPV6_RECVPKTINFO */
696     dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
697   }
698
699   if (bind(fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) {
700     dtls_alert("bind: %s\n", strerror(errno));
701     goto error;
702   }
703
704   dtls_init();
705
706   the_context = dtls_new_context(&fd);
707
708   /* enable/disable tls_ecdh_anon_with_aes_128_cbc_sha_256 */
709   dtls_enables_anon_ecdh(the_context, ecdh_anon_enalbe);
710
711   dtls_set_handler(the_context, &cb);
712
713   while (1) {
714     FD_ZERO(&rfds);
715     FD_ZERO(&wfds);
716
717     FD_SET(fd, &rfds);
718     /* FD_SET(fd, &wfds); */
719     
720     timeout.tv_sec = 5;
721     timeout.tv_usec = 0;
722     
723     result = select( fd+1, &rfds, &wfds, 0, &timeout);
724     
725     if (result < 0) {           /* error */
726       if (errno != EINTR)
727         perror("select");
728     } else if (result == 0) {   /* timeout */
729     } else {                    /* ok */
730       if (FD_ISSET(fd, &wfds))
731         ;
732       else if (FD_ISSET(fd, &rfds)) {
733         dtls_handle_read(the_context);
734       }
735     }
736   }
737   
738  error:
739   dtls_free_context(the_context);
740   exit(0);
741 }