1 /*
2  * Redistribution and use in source and binary forms, with or without
3  * modification, are permitted provided that the following conditions
4  * are met:
5  * 1. Redistributions of source code must retain the above copyright
6  *    notice, this list of conditions and the following disclaimer.
7  * 2. Redistributions in binary form must reproduce the above copyright
8  *    notice, this list of conditions and the following disclaimer in the
9  *    documentation and/or other materials provided with the distribution.
10  * 3. Neither the name of the Institute nor the names of its contributors
11  *    may be used to endorse or promote products derived from this software
12  *    without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * This file is part of the Contiki operating system.
27  *
28  */
29 
30 #include "contiki.h"
31 #include "contiki-lib.h"
32 #include "contiki-net.h"
33 
34 #if UIP_CONF_IPV6_RPL
35 #include "net/rpl/rpl.h"
36 #endif /* UIP_CONF_IPV6_RPL */
37 
38 #include <string.h>
39 
40 #include "tinydtls.h"
41 
42 #ifndef DEBUG
43 #define DEBUG DEBUG_PRINT
44 #endif
45 #include "net/ip/uip-debug.h"
46 
47 #include "debug.h"
48 #include "dtls.h"
49 
50 #ifdef ENABLE_POWERTRACE
51 #include "powertrace.h"
52 #endif
53 
54 #define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
55 #define UIP_UDP_BUF  ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
56 
57 #define MAX_PAYLOAD_LEN 120
58 
59 static struct uip_udp_conn *server_conn;
60 
61 static dtls_context_t *dtls_context;
62 
63 static const unsigned char ecdsa_priv_key[] = {
64 			0xD9, 0xE2, 0x70, 0x7A, 0x72, 0xDA, 0x6A, 0x05,
65 			0x04, 0x99, 0x5C, 0x86, 0xED, 0xDB, 0xE3, 0xEF,
66 			0xC7, 0xF1, 0xCD, 0x74, 0x83, 0x8F, 0x75, 0x70,
67 			0xC8, 0x07, 0x2D, 0x0A, 0x76, 0x26, 0x1B, 0xD4};
68 
69 static const unsigned char ecdsa_pub_key_x[] = {
70 			0xD0, 0x55, 0xEE, 0x14, 0x08, 0x4D, 0x6E, 0x06,
71 			0x15, 0x59, 0x9D, 0xB5, 0x83, 0x91, 0x3E, 0x4A,
72 			0x3E, 0x45, 0x26, 0xA2, 0x70, 0x4D, 0x61, 0xF2,
73 			0x7A, 0x4C, 0xCF, 0xBA, 0x97, 0x58, 0xEF, 0x9A};
74 
75 static const unsigned char ecdsa_pub_key_y[] = {
76 			0xB4, 0x18, 0xB6, 0x4A, 0xFE, 0x80, 0x30, 0xDA,
77 			0x1D, 0xDC, 0xF4, 0xF4, 0x2E, 0x2F, 0x26, 0x31,
78 			0xD0, 0x43, 0xB1, 0xFB, 0x03, 0xE2, 0x2F, 0x4D,
79 			0x17, 0xDE, 0x43, 0xF9, 0xF9, 0xAD, 0xEE, 0x70};
80 
81 static int
read_from_peer(struct dtls_context_t * ctx,session_t * session,uint8 * data,size_t len)82 read_from_peer(struct dtls_context_t *ctx,
83 	       session_t *session, uint8 *data, size_t len) {
84   size_t i;
85   for (i = 0; i < len; i++)
86     PRINTF("%c", data[i]);
87 
88   /* echo incoming application data */
89   dtls_write(ctx, session, data, len);
90   return 0;
91 }
92 
93 static int
send_to_peer(struct dtls_context_t * ctx,session_t * session,uint8 * data,size_t len)94 send_to_peer(struct dtls_context_t *ctx,
95 	     session_t *session, uint8 *data, size_t len) {
96 
97   struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx);
98 
99   uip_ipaddr_copy(&conn->ripaddr, &session->addr);
100   conn->rport = session->port;
101 
102   PRINTF("send to ");
103   PRINT6ADDR(&conn->ripaddr);
104   PRINTF(":%u\n", uip_ntohs(conn->rport));
105 
106   uip_udp_packet_send(conn, data, len);
107 
108   /* Restore server connection to allow data from any node */
109   memset(&conn->ripaddr, 0, sizeof(conn->ripaddr));
110   memset(&conn->rport, 0, sizeof(conn->rport));
111 
112   return len;
113 }
114 
115 #ifdef DTLS_PSK
116 /* This function is the "key store" for tinyDTLS. It is called to
117  * retrieve a key for the given identity within this particular
118  * session. */
119 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)120 get_psk_info(struct dtls_context_t *ctx, const session_t *session,
121 	     dtls_credentials_type_t type,
122 	     const unsigned char *id, size_t id_len,
123 	     unsigned char *result, size_t result_length) {
124 
125   struct keymap_t {
126     unsigned char *id;
127     size_t id_length;
128     unsigned char *key;
129     size_t key_length;
130   } psk[3] = {
131     { (unsigned char *)"Client_identity", 15,
132       (unsigned char *)"secretPSK", 9 },
133     { (unsigned char *)"default identity", 16,
134       (unsigned char *)"\x11\x22\x33", 3 },
135     { (unsigned char *)"\0", 2,
136       (unsigned char *)"", 1 }
137   };
138 
139   if (type != DTLS_PSK_KEY) {
140     return 0;
141   }
142 
143   if (id) {
144     int i;
145     for (i = 0; i < sizeof(psk)/sizeof(struct keymap_t); i++) {
146       if (id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) {
147 	if (result_length < psk[i].key_length) {
148 	  dtls_warn("buffer too small for PSK");
149 	  return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
150 	}
151 
152 	memcpy(result, psk[i].key, psk[i].key_length);
153 	return psk[i].key_length;
154       }
155     }
156   }
157 
158   return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR);
159 }
160 #endif /* DTLS_PSK */
161 
162 #ifdef DTLS_ECC
163 static int
get_ecdsa_key(struct dtls_context_t * ctx,const session_t * session,const dtls_ecdsa_key_t ** result)164 get_ecdsa_key(struct dtls_context_t *ctx,
165 	      const session_t *session,
166 	      const dtls_ecdsa_key_t **result) {
167   static const dtls_ecdsa_key_t ecdsa_key = {
168     .curve = DTLS_ECDH_CURVE_SECP256R1,
169     .priv_key = ecdsa_priv_key,
170     .pub_key_x = ecdsa_pub_key_x,
171     .pub_key_y = ecdsa_pub_key_y
172   };
173 
174   *result = &ecdsa_key;
175   return 0;
176 }
177 
178 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)179 verify_ecdsa_key(struct dtls_context_t *ctx,
180 		 const session_t *session,
181 		 const unsigned char *other_pub_x,
182 		 const unsigned char *other_pub_y,
183 		 size_t key_size) {
184   return 0;
185 }
186 #endif /* DTLS_ECC */
187 
188 PROCESS(udp_server_process, "UDP server process");
189 AUTOSTART_PROCESSES(&udp_server_process);
190 /*---------------------------------------------------------------------------*/
191 static void
dtls_handle_read(dtls_context_t * ctx)192 dtls_handle_read(dtls_context_t *ctx) {
193   session_t session;
194 
195   if(uip_newdata()) {
196     uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr);
197     session.port = UIP_UDP_BUF->srcport;
198     session.size = sizeof(session.addr) + sizeof(session.port);
199 
200     dtls_handle_message(ctx, &session, uip_appdata, uip_datalen());
201   }
202 }
203 /*---------------------------------------------------------------------------*/
204 static void
print_local_addresses(void)205 print_local_addresses(void)
206 {
207   int i;
208   uint8_t state;
209 
210   PRINTF("Server IPv6 addresses: \n");
211   for(i = 0; i < UIP_DS6_ADDR_NB; i++) {
212     state = uip_ds6_if.addr_list[i].state;
213     if(uip_ds6_if.addr_list[i].isused &&
214        (state == ADDR_TENTATIVE || state == ADDR_PREFERRED)) {
215       PRINT6ADDR(&uip_ds6_if.addr_list[i].ipaddr);
216       PRINTF("\n");
217     }
218   }
219 }
220 
221 #if 0
222 static void
223 create_rpl_dag(uip_ipaddr_t *ipaddr)
224 {
225   struct uip_ds6_addr *root_if;
226 
227   root_if = uip_ds6_addr_lookup(ipaddr);
228   if(root_if != NULL) {
229     rpl_dag_t *dag;
230     uip_ipaddr_t prefix;
231 
232     rpl_set_root(RPL_DEFAULT_INSTANCE, ipaddr);
233     dag = rpl_get_any_dag();
234     uip_ip6addr(&prefix, 0xaaaa, 0, 0, 0, 0, 0, 0, 0);
235     rpl_set_prefix(dag, &prefix, 64);
236     PRINTF("created a new RPL dag\n");
237   } else {
238     PRINTF("failed to create a new RPL DAG\n");
239   }
240 }
241 #endif
242 
243 void
init_dtls()244 init_dtls() {
245   static dtls_handler_t cb = {
246     .write = send_to_peer,
247     .read  = read_from_peer,
248     .event = NULL,
249 #ifdef DTLS_PSK
250     .get_psk_info = get_psk_info,
251 #endif /* DTLS_PSK */
252 #ifdef DTLS_ECC
253     .get_ecdsa_key = get_ecdsa_key,
254     .verify_ecdsa_key = verify_ecdsa_key
255 #endif /* DTLS_ECC */
256   };
257 #if 0
258   uip_ipaddr_t ipaddr;
259   /* struct uip_ds6_addr *root_if; */
260 #endif /* UIP_CONF_ROUTER */
261 
262   PRINTF("DTLS server started\n");
263 
264 #if 0  /* TEST */
265   memset(&tmp_addr, 0, sizeof(rimeaddr_t));
266   if(get_eui64_from_eeprom(tmp_addr.u8));
267 #if UIP_CONF_IPV6
268   memcpy(&uip_lladdr.addr, &tmp_addr.u8, 8);
269 #endif
270 #endif /* TEST */
271 
272 #if 0
273 /*   uip_ip6addr(&ipaddr, 0xaaaa, 0, 0, 0, 0, 0, 0, 0); */
274 /*   uip_ds6_set_addr_iid(&ipaddr, &uip_lladdr); */
275 /*   uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); */
276 
277 /*   create_rpl_dag(&ipaddr); */
278 /* #else */
279   /* uip_ds6_addr_add(&ipaddr, 0, ADDR_AUTOCONF); */
280 
281   uip_ip6addr(&ipaddr, 0xaaaa, 0,0,0,0x0200,0,0,0x0003);
282   uip_ds6_addr_add(&ipaddr, 0, ADDR_MANUAL);
283 
284   create_rpl_dag(&ipaddr);
285 #endif /* UIP_CONF_ROUTER */
286 
287   server_conn = udp_new(NULL, 0, NULL);
288   udp_bind(server_conn, UIP_HTONS(20220));
289 
290   dtls_set_log_level(DTLS_LOG_DEBUG);
291 
292   dtls_context = dtls_new_context(server_conn);
293   if (dtls_context)
294     dtls_set_handler(dtls_context, &cb);
295 }
296 
297 /*---------------------------------------------------------------------------*/
PROCESS_THREAD(udp_server_process,ev,data)298 PROCESS_THREAD(udp_server_process, ev, data)
299 {
300   PROCESS_BEGIN();
301 
302   dtls_init();
303   init_dtls();
304 
305   print_local_addresses();
306 
307   if (!dtls_context) {
308     dtls_emerg("cannot create context\n");
309     PROCESS_EXIT();
310   }
311 
312 #ifdef ENABLE_POWERTRACE
313   powertrace_start(CLOCK_SECOND * 2);
314 #endif
315 
316   while(1) {
317     PROCESS_WAIT_EVENT();
318     if(ev == tcpip_event) {
319       dtls_handle_read(dtls_context);
320     }
321 #if 0
322     if (bytes_read > 0) {
323       /* dtls_handle_message(dtls_context, &the_session, readbuf, bytes_read); */
324       read_from_peer(dtls_context, &the_session, readbuf, bytes_read);
325     }
326     dtls_handle_message(ctx, &session, uip_appdata, bytes_read);
327 #endif
328   }
329 
330   PROCESS_END();
331 }
332 /*---------------------------------------------------------------------------*/
333