d9269a87717dea87a7e91d0b054fa5c6d8238999
[platform/upstream/iotivity.git] / extlibs / tinydtls / examples / contiki / dtls-server.c
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
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
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
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
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
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
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
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
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 /*---------------------------------------------------------------------------*/
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 /*---------------------------------------------------------------------------*/