1 
2 /* This is needed for apple */
3 #define __APPLE_USE_RFC_3542
4 
5 #include <assert.h>
6 #include <stdio.h>
7 #include <string.h>
8 #include <errno.h>
9 #include <unistd.h>
10 #include <netinet/in.h>
11 #include <sys/types.h>
12 #include <sys/socket.h>
13 #include <sys/time.h>
14 #include <netdb.h>
15 #include <signal.h>
16 
17 #include "tinydtls.h"
18 #include "dtls.h"
19 #include "debug.h"
20 
21 #define DEFAULT_PORT 20220
22 
23 static const unsigned char ecdsa_priv_key[] = {
24 			0xD9, 0xE2, 0x70, 0x7A, 0x72, 0xDA, 0x6A, 0x05,
25 			0x04, 0x99, 0x5C, 0x86, 0xED, 0xDB, 0xE3, 0xEF,
26 			0xC7, 0xF1, 0xCD, 0x74, 0x83, 0x8F, 0x75, 0x70,
27 			0xC8, 0x07, 0x2D, 0x0A, 0x76, 0x26, 0x1B, 0xD4};
28 
29 static const unsigned char ecdsa_pub_key_x[] = {
30 			0xD0, 0x55, 0xEE, 0x14, 0x08, 0x4D, 0x6E, 0x06,
31 			0x15, 0x59, 0x9D, 0xB5, 0x83, 0x91, 0x3E, 0x4A,
32 			0x3E, 0x45, 0x26, 0xA2, 0x70, 0x4D, 0x61, 0xF2,
33 			0x7A, 0x4C, 0xCF, 0xBA, 0x97, 0x58, 0xEF, 0x9A};
34 
35 static const unsigned char ecdsa_pub_key_y[] = {
36 			0xB4, 0x18, 0xB6, 0x4A, 0xFE, 0x80, 0x30, 0xDA,
37 			0x1D, 0xDC, 0xF4, 0xF4, 0x2E, 0x2F, 0x26, 0x31,
38 			0xD0, 0x43, 0xB1, 0xFB, 0x03, 0xE2, 0x2F, 0x4D,
39 			0x17, 0xDE, 0x43, 0xF9, 0xF9, 0xAD, 0xEE, 0x70};
40 
41 #if 0
42 /* SIGINT handler: set quit to 1 for graceful termination */
43 void
44 handle_sigint(int signum) {
45   dsrv_stop(dsrv_get_context());
46 }
47 #endif
48 
49 #ifdef DTLS_PSK
50 /* This function is the "key store" for tinyDTLS. It is called to
51  * retrieve a key for the given identity within this particular
52  * session. */
53 static int
get_psk_info(struct dtls_context_t * ctx,const session_t * session,dtls_credentials_type_t type,const unsigned char * id,size_t id_len,unsigned char * result,size_t result_length)54 get_psk_info(struct dtls_context_t *ctx, const session_t *session,
55 	     dtls_credentials_type_t type,
56 	     const unsigned char *id, size_t id_len,
57 	     unsigned char *result, size_t result_length) {
58 
59   struct keymap_t {
60     unsigned char *id;
61     size_t id_length;
62     unsigned char *key;
63     size_t key_length;
64   } psk[3] = {
65     { (unsigned char *)"Client_identity", 15,
66       (unsigned char *)"secretPSK", 9 },
67     { (unsigned char *)"default identity", 16,
68       (unsigned char *)"\x11\x22\x33", 3 },
69     { (unsigned char *)"\0", 2,
70       (unsigned char *)"", 1 }
71   };
72 
73   if (type != DTLS_PSK_KEY) {
74     return 0;
75   }
76 
77   if (id) {
78     int i;
79     for (i = 0; i < sizeof(psk)/sizeof(struct keymap_t); i++) {
80       if (id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) {
81 	if (result_length < psk[i].key_length) {
82 	  dtls_warn("buffer too small for PSK");
83 	  return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
84 	}
85 
86 	memcpy(result, psk[i].key, psk[i].key_length);
87 	return psk[i].key_length;
88       }
89     }
90   }
91 
92   return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
93 }
94 
95 #endif /* DTLS_PSK */
96 
97 #ifdef DTLS_ECC
98 static int
get_ecdsa_key(struct dtls_context_t * ctx,const session_t * session,const dtls_ecdsa_key_t ** result)99 get_ecdsa_key(struct dtls_context_t *ctx,
100 	      const session_t *session,
101 	      const dtls_ecdsa_key_t **result) {
102   static const dtls_ecdsa_key_t ecdsa_key = {
103     .curve = DTLS_ECDH_CURVE_SECP256R1,
104     .priv_key = ecdsa_priv_key,
105     .pub_key_x = ecdsa_pub_key_x,
106     .pub_key_y = ecdsa_pub_key_y
107   };
108 
109   *result = &ecdsa_key;
110   return 0;
111 }
112 
113 static int
verify_ecdsa_key(struct dtls_context_t * ctx,const session_t * session,const unsigned char * other_pub_x,const unsigned char * other_pub_y,size_t key_size)114 verify_ecdsa_key(struct dtls_context_t *ctx,
115 		 const session_t *session,
116 		 const unsigned char *other_pub_x,
117 		 const unsigned char *other_pub_y,
118 		 size_t key_size) {
119   return 0;
120 }
121 #endif /* DTLS_ECC */
122 
123 #define DTLS_SERVER_CMD_CLOSE "server:close"
124 #define DTLS_SERVER_CMD_RENEGOTIATE "server:renegotiate"
125 
126 static int
read_from_peer(struct dtls_context_t * ctx,session_t * session,uint8 * data,size_t len)127 read_from_peer(struct dtls_context_t *ctx,
128 	       session_t *session, uint8 *data, size_t len) {
129   size_t i;
130   for (i = 0; i < len; i++)
131     printf("%c", data[i]);
132   if (len >= strlen(DTLS_SERVER_CMD_CLOSE) &&
133       !memcmp(data, DTLS_SERVER_CMD_CLOSE, strlen(DTLS_SERVER_CMD_CLOSE))) {
134     printf("server: closing connection\n");
135     dtls_close(ctx, session);
136     return len;
137   } else if (len >= strlen(DTLS_SERVER_CMD_RENEGOTIATE) &&
138       !memcmp(data, DTLS_SERVER_CMD_RENEGOTIATE, strlen(DTLS_SERVER_CMD_RENEGOTIATE))) {
139     printf("server: renegotiate connection\n");
140     dtls_renegotiate(ctx, session);
141     return len;
142   }
143 
144   return dtls_write(ctx, session, data, len);
145 }
146 
147 static int
send_to_peer(struct dtls_context_t * ctx,session_t * session,uint8 * data,size_t len)148 send_to_peer(struct dtls_context_t *ctx,
149 	     session_t *session, uint8 *data, size_t len) {
150 
151   int fd = *(int *)dtls_get_app_data(ctx);
152   return sendto(fd, data, len, MSG_DONTWAIT,
153 		&session->addr.sa, session->size);
154 }
155 
156 static int
dtls_handle_read(struct dtls_context_t * ctx)157 dtls_handle_read(struct dtls_context_t *ctx) {
158   int *fd;
159   session_t session;
160   static uint8 buf[DTLS_MAX_BUF];
161   int len;
162 
163   fd = dtls_get_app_data(ctx);
164 
165   assert(fd);
166 
167   memset(&session, 0, sizeof(session_t));
168   session.size = sizeof(session.addr);
169   len = recvfrom(*fd, buf, sizeof(buf), MSG_TRUNC,
170 		 &session.addr.sa, &session.size);
171 
172   if (len < 0) {
173     perror("recvfrom");
174     return -1;
175   } else {
176     dtls_debug("got %d bytes from port %d\n", len,
177 	     ntohs(session.addr.sin6.sin6_port));
178     if (sizeof(buf) < len) {
179       dtls_warn("packet was truncated (%d bytes lost)\n", len - sizeof(buf));
180     }
181   }
182 
183   return dtls_handle_message(ctx, &session, buf, len);
184 }
185 
186 static int
resolve_address(const char * server,struct sockaddr * dst)187 resolve_address(const char *server, struct sockaddr *dst) {
188 
189   struct addrinfo *res, *ainfo;
190   struct addrinfo hints;
191   static char addrstr[256];
192   int error;
193 
194   memset(addrstr, 0, sizeof(addrstr));
195   if (server && strlen(server) > 0)
196     memcpy(addrstr, server, strlen(server));
197   else
198     memcpy(addrstr, "localhost", 9);
199 
200   memset ((char *)&hints, 0, sizeof(hints));
201   hints.ai_socktype = SOCK_DGRAM;
202   hints.ai_family = AF_UNSPEC;
203 
204   error = getaddrinfo(addrstr, "", &hints, &res);
205 
206   if (error != 0) {
207     fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
208     return error;
209   }
210 
211   for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
212 
213     switch (ainfo->ai_family) {
214     case AF_INET6:
215 
216       memcpy(dst, ainfo->ai_addr, ainfo->ai_addrlen);
217       return ainfo->ai_addrlen;
218     default:
219       ;
220     }
221   }
222 
223   freeaddrinfo(res);
224   return -1;
225 }
226 
227 static void
usage(const char * program,const char * version)228 usage(const char *program, const char *version) {
229   const char *p;
230 
231   p = strrchr( program, '/' );
232   if ( p )
233     program = ++p;
234 
235   fprintf(stderr, "%s v%s -- DTLS server implementation\n"
236 	  "(c) 2011-2014 Olaf Bergmann <bergmann@tzi.org>\n\n"
237 	  "usage: %s [-A address] [-p port] [-v num]\n"
238 	  "\t-A address\t\tlisten on specified address (default is ::)\n"
239 	  "\t-p port\t\tlisten on specified port (default is %d)\n"
240 	  "\t-v num\t\tverbosity level (default: 3)\n",
241 	   program, version, program, DEFAULT_PORT);
242 }
243 
handle_event(struct dtls_context_t * ctx,session_t * session,dtls_alert_level_t level,unsigned short code)244 static int handle_event(struct dtls_context_t *ctx, session_t *session,
245 			dtls_alert_level_t level, unsigned short code)
246 {
247 	printf("event: level %d code %d\n", level, code);
248 	if (level > 0) {
249 		/* alert code, quit */
250 	} else if (level == 0) {
251 		/* internal event */
252 		if (code == DTLS_EVENT_CONNECTED) {
253 			/* We can send data now */
254 		}
255 	}
256 
257 	return 0;
258 }
259 
260 static dtls_handler_t cb = {
261   .write = send_to_peer,
262   .read  = read_from_peer,
263   .event = handle_event,
264 #ifdef DTLS_PSK
265   .get_psk_info = get_psk_info,
266 #endif /* DTLS_PSK */
267 #ifdef DTLS_ECC
268   .get_ecdsa_key = get_ecdsa_key,
269   .verify_ecdsa_key = verify_ecdsa_key
270 #endif /* DTLS_ECC */
271 };
272 
273 int
main(int argc,char ** argv)274 main(int argc, char **argv) {
275   dtls_context_t *the_context = NULL;
276   log_t log_level = DTLS_LOG_WARN;
277   fd_set rfds, wfds;
278   struct timeval timeout;
279   int fd, opt, result;
280   int on = 1;
281   struct sockaddr_in6 listen_addr;
282 
283   memset(&listen_addr, 0, sizeof(struct sockaddr_in6));
284 
285   /* fill extra field for 4.4BSD-based systems (see RFC 3493, section 3.4) */
286 #if defined(SIN6_LEN) || defined(HAVE_SOCKADDR_IN6_SIN6_LEN)
287   listen_addr.sin6_len = sizeof(struct sockaddr_in6);
288 #endif
289 
290   listen_addr.sin6_family = AF_INET6;
291   listen_addr.sin6_port = htons(DEFAULT_PORT);
292   listen_addr.sin6_addr = in6addr_any;
293 
294   while ((opt = getopt(argc, argv, "A:p:v:")) != -1) {
295     switch (opt) {
296     case 'A' :
297       if (resolve_address(optarg, (struct sockaddr *)&listen_addr) < 0) {
298 	fprintf(stderr, "cannot resolve address\n");
299 	exit(-1);
300       }
301       break;
302     case 'p' :
303       listen_addr.sin6_port = htons(atoi(optarg));
304       break;
305     case 'v' :
306       log_level = strtol(optarg, NULL, 10);
307       break;
308     default:
309       usage(argv[0], dtls_package_version());
310       exit(1);
311     }
312   }
313 
314   dtls_set_log_level(log_level);
315 
316   /* init socket and set it to non-blocking */
317   fd = socket(listen_addr.sin6_family, SOCK_DGRAM, 0);
318 
319   if (fd < 0) {
320     dtls_alert("socket: %s\n", strerror(errno));
321     return 0;
322   }
323 
324   if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on) ) < 0) {
325     dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno));
326   }
327 #if 0
328   flags = fcntl(fd, F_GETFL, 0);
329   if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) {
330     dtls_alert("fcntl: %s\n", strerror(errno));
331     goto error;
332   }
333 #endif
334   on = 1;
335 #ifdef IPV6_RECVPKTINFO
336   if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on) ) < 0) {
337 #else /* IPV6_RECVPKTINFO */
338   if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on) ) < 0) {
339 #endif /* IPV6_RECVPKTINFO */
340     dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno));
341   }
342 
343   if (bind(fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) {
344     dtls_alert("bind: %s\n", strerror(errno));
345     goto error;
346   }
347 
348   dtls_init();
349 
350   the_context = dtls_new_context(&fd);
351 
352   dtls_set_handler(the_context, &cb);
353 
354   while (1) {
355     FD_ZERO(&rfds);
356     FD_ZERO(&wfds);
357 
358     FD_SET(fd, &rfds);
359     /* FD_SET(fd, &wfds); */
360 
361     timeout.tv_sec = 5;
362     timeout.tv_usec = 0;
363 
364     result = select( fd+1, &rfds, &wfds, 0, &timeout);
365 
366     if (result < 0) {		/* error */
367       if (errno != EINTR)
368 	perror("select");
369     } else if (result == 0) {	/* timeout */
370     } else {			/* ok */
371       if (FD_ISSET(fd, &wfds))
372 	;
373       else if (FD_ISSET(fd, &rfds)) {
374 	dtls_handle_read(the_context);
375       }
376     }
377   }
378 
379  error:
380   dtls_free_context(the_context);
381   exit(0);
382 }
383