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