1 /* dtls -- a very basic DTLS implementation
2  *
3  * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
4  * Copyright (C) 2013 Hauke Mehrtens <hauke@hauke-m.de>
5  *
6  * Permission is hereby granted, free of charge, to any person
7  * obtaining a copy of this software and associated documentation
8  * files (the "Software"), to deal in the Software without
9  * restriction, including without limitation the rights to use, copy,
10  * modify, merge, publish, distribute, sublicense, and/or sell copies
11  * of the Software, and to permit persons to whom the Software is
12  * furnished to do so, subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice shall be
15  * included in all copies or substantial portions of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
21  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
22  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
23  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24  * SOFTWARE.
25  */
26 
27 /**
28  * @file dtls.h
29  * @brief High level DTLS API and visible structures.
30  */
31 
32 #ifndef _DTLS_DTLS_H_
33 #define _DTLS_DTLS_H_
34 
35 #include <stdint.h>
36 
37 #include "t_list.h"
38 #include "state.h"
39 #include "peer.h"
40 
41 #ifndef WITH_CONTIKI
42 #include "uthash.h"
43 #include "t_list.h"
44 #endif /* WITH_CONTIKI */
45 
46 #include "alert.h"
47 #include "crypto.h"
48 #include "hmac.h"
49 
50 #include "global.h"
51 #include "dtls_time.h"
52 
53 #ifndef DTLSv12
54 #define DTLS_VERSION 0xfeff	/* DTLS v1.1 */
55 #else
56 #define DTLS_VERSION 0xfefd	/* DTLS v1.2 */
57 #endif
58 
59 typedef enum dtls_credentials_type_t {
60   DTLS_PSK_HINT, DTLS_PSK_IDENTITY, DTLS_PSK_KEY
61 } dtls_credentials_type_t;
62 
63 typedef struct dtls_ecdsa_key_t {
64   dtls_ecdh_curve curve;
65   const unsigned char *priv_key;	/** < private key as bytes > */
66   const unsigned char *pub_key_x;	/** < x part of the public key for the given private key > */
67   const unsigned char *pub_key_y;	/** < y part of the public key for the given private key > */
68 } dtls_ecdsa_key_t;
69 
70 /** Length of the secret that is used for generating Hello Verify cookies. */
71 #define DTLS_COOKIE_SECRET_LENGTH 12
72 
73 struct dtls_context_t;
74 
75 /**
76  * This structure contains callback functions used by tinydtls to
77  * communicate with the application. At least the write function must
78  * be provided. It is called by the DTLS state machine to send packets
79  * over the network. The read function is invoked to deliver decrypted
80  * and verfified application data. The third callback is an event
81  * handler function that is called when alert messages are encountered
82  * or events generated by the library have occured.
83  */
84 typedef struct {
85   /**
86    * Called from dtls_handle_message() to send DTLS packets over the
87    * network. The callback function must use the network interface
88    * denoted by session->ifindex to send the data.
89    *
90    * @param ctx  The current DTLS context.
91    * @param session The session object, including the address of the
92    *              remote peer where the data shall be sent.
93    * @param buf  The data to send.
94    * @param len  The actual length of @p buf.
95    * @return The callback function must return the number of bytes
96    *         that were sent, or a value less than zero to indicate an
97    *         error.
98    */
99   int (*write)(struct dtls_context_t *ctx,
100 	       session_t *session, uint8 *buf, size_t len);
101 
102   /**
103    * Called from dtls_handle_message() deliver application data that was
104    * received on the given session. The data is delivered only after
105    * decryption and verification have succeeded.
106    *
107    * @param ctx  The current DTLS context.
108    * @param session The session object, including the address of the
109    *              data's origin.
110    * @param buf  The received data packet.
111    * @param len  The actual length of @p buf.
112    * @return ignored
113    */
114   int (*read)(struct dtls_context_t *ctx,
115 	       session_t *session, uint8 *buf, size_t len);
116 
117   /**
118    * The event handler is called when a message from the alert
119    * protocol is received or the state of the DTLS session changes.
120    *
121    * @param ctx     The current dtls context.
122    * @param session The session object that was affected.
123    * @param level   The alert level or @c 0 when an event ocurred that
124    *                is not an alert.
125    * @param code    Values less than @c 256 indicate alerts, while
126    *                @c 256 or greater indicate internal DTLS session changes.
127    * @return ignored
128    */
129   int (*event)(struct dtls_context_t *ctx, session_t *session,
130 		dtls_alert_level_t level, unsigned short code);
131 
132 #ifdef DTLS_PSK
133   /**
134    * Called during handshake to get information related to the
135    * psk key exchange. The type of information requested is
136    * indicated by @p type which will be one of DTLS_PSK_HINT,
137    * DTLS_PSK_IDENTITY, or DTLS_PSK_KEY. The called function
138    * must store the requested item in the buffer @p result of
139    * size @p result_length. On success, the function must return
140    * the actual number of bytes written to @p result, of a
141    * value less than zero on error. The parameter @p desc may
142    * contain additional request information (e.g. the psk_identity
143    * for which a key is requested when @p type == @c DTLS_PSK_KEY.
144    *
145    * @param ctx     The current dtls context.
146    * @param session The session where the key will be used.
147    * @param type    The type of the requested information.
148    * @param desc    Additional request information
149    * @param desc_len The actual length of desc.
150    * @param result  Must be filled with the requested information.
151    * @param result_length  Maximum size of @p result.
152    * @return The number of bytes written to @p result or a value
153    *         less than zero on error.
154    */
155   int (*get_psk_info)(struct dtls_context_t *ctx,
156 		      const session_t *session,
157 		      dtls_credentials_type_t type,
158 		      const unsigned char *desc, size_t desc_len,
159 		      unsigned char *result, size_t result_length);
160 
161 #endif /* DTLS_PSK */
162 
163 #ifdef DTLS_ECC
164   /**
165    * Called during handshake to get the server's or client's ecdsa
166    * key used to authenticate this server or client in this
167    * session. If found, the key must be stored in @p result and
168    * the return value must be @c 0. If not found, @p result is
169    * undefined and the return value must be less than zero.
170    *
171    * If ECDSA should not be supported, set this pointer to NULL.
172    *
173    * Implement this if you want to provide your own certificate to
174    * the other peer. This is mandatory for a server providing ECDSA
175    * support and optional for a client. A client doing DTLS client
176    * authentication has to implementing this callback.
177    *
178    * @param ctx     The current dtls context.
179    * @param session The session where the key will be used.
180    * @param result  Must be set to the key object to used for the given
181    *                session.
182    * @return @c 0 if result is set, or less than zero on error.
183    */
184   int (*get_ecdsa_key)(struct dtls_context_t *ctx,
185 		       const session_t *session,
186 		       const dtls_ecdsa_key_t **result);
187 
188   /**
189    * Called during handshake to check the peer's pubic key in this
190    * session. If the public key matches the session and should be
191    * considerated valid the return value must be @c 0. If not valid,
192    * the return value must be less than zero.
193    *
194    * If ECDSA should not be supported, set this pointer to NULL.
195    *
196    * Implement this if you want to verify the other peers public key.
197    * This is mandatory for a DTLS client doing based ECDSA
198    * authentication. A server implementing this will request the
199    * client to do DTLS client authentication.
200    *
201    * @param ctx          The current dtls context.
202    * @param session      The session where the key will be used.
203    * @param other_pub_x  x component of the public key.
204    * @param other_pub_y  y component of the public key.
205    * @return @c 0 if public key matches, or less than zero on error.
206    * error codes:
207    *   return dtls_alert_fatal_create(DTLS_ALERT_BAD_CERTIFICATE);
208    *   return dtls_alert_fatal_create(DTLS_ALERT_UNSUPPORTED_CERTIFICATE);
209    *   return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_REVOKED);
210    *   return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_EXPIRED);
211    *   return dtls_alert_fatal_create(DTLS_ALERT_CERTIFICATE_UNKNOWN);
212    *   return dtls_alert_fatal_create(DTLS_ALERT_UNKNOWN_CA);
213    */
214   int (*verify_ecdsa_key)(struct dtls_context_t *ctx,
215 			  const session_t *session,
216 			  const unsigned char *other_pub_x,
217 			  const unsigned char *other_pub_y,
218 			  size_t key_size);
219 #endif /* DTLS_ECC */
220 } dtls_handler_t;
221 
222 /** Holds global information of the DTLS engine. */
223 typedef struct dtls_context_t {
224   unsigned char cookie_secret[DTLS_COOKIE_SECRET_LENGTH];
225   clock_time_t cookie_secret_age; /**< the time the secret has been generated */
226 
227 #ifndef WITH_CONTIKI
228   dtls_peer_t *peers;		/**< peer hash map */
229 #else /* WITH_CONTIKI */
230   LIST_STRUCT(peers);
231 
232   struct etimer retransmit_timer; /**< fires when the next packet must be sent */
233 #endif /* WITH_CONTIKI */
234 
235   LIST_STRUCT(sendqueue);	/**< the packets to send */
236 
237   void *app;			/**< application-specific data */
238 
239   dtls_handler_t *h;		/**< callback handlers */
240 
241   unsigned char readbuf[DTLS_MAX_BUF];
242 } dtls_context_t;
243 
244 /**
245  * This function initializes the tinyDTLS memory management and must
246  * be called first.
247  */
248 void dtls_init();
249 
250 /**
251  * Creates a new context object. The storage allocated for the new
252  * object must be released with dtls_free_context(). */
253 dtls_context_t *dtls_new_context(void *app_data);
254 
255 /** Releases any storage that has been allocated for \p ctx. */
256 void dtls_free_context(dtls_context_t *ctx);
257 
258 #define dtls_set_app_data(CTX,DATA) ((CTX)->app = (DATA))
259 #define dtls_get_app_data(CTX) ((CTX)->app)
260 
261 /** Sets the callback handler object for @p ctx to @p h. */
dtls_set_handler(dtls_context_t * ctx,dtls_handler_t * h)262 static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
263   ctx->h = h;
264 }
265 
266 /**
267  * Establishes a DTLS channel with the specified remote peer @p dst.
268  * This function returns @c 0 if that channel already exists, a value
269  * greater than zero when a new ClientHello message was sent, and
270  * a value less than zero on error.
271  *
272  * @param ctx    The DTLS context to use.
273  * @param dst    The remote party to connect to.
274  * @return A value less than zero on error, greater or equal otherwise.
275  */
276 int dtls_connect(dtls_context_t *ctx, const session_t *dst);
277 
278 /**
279  * Establishes a DTLS channel with the specified remote peer.
280  * This function returns @c 0 if that channel already exists, a value
281  * greater than zero when a new ClientHello message was sent, and
282  * a value less than zero on error.
283  *
284  * @param ctx    The DTLS context to use.
285  * @param peer   The peer object that describes the session.
286  * @return A value less than zero on error, greater or equal otherwise.
287  */
288 int dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer);
289 
290 /**
291  * Closes the DTLS connection associated with @p remote. This function
292  * returns zero on success, and a value less than zero on error.
293  */
294 int dtls_close(dtls_context_t *ctx, const session_t *remote);
295 
296 int dtls_renegotiate(dtls_context_t *ctx, const session_t *dst);
297 
298 /**
299  * Writes the application data given in @p buf to the peer specified
300  * by @p session.
301  *
302  * @param ctx      The DTLS context to use.
303  * @param session  The remote transport address and local interface.
304  * @param buf      The data to write.
305  * @param len      The actual length of @p data.
306  *
307  * @return The number of bytes written or @c -1 on error.
308  */
309 int dtls_write(struct dtls_context_t *ctx, session_t *session,
310 	       uint8 *buf, size_t len);
311 
312 /**
313  * Checks sendqueue of given DTLS context object for any outstanding
314  * packets to be transmitted.
315  *
316  * @param context The DTLS context object to use.
317  * @param next    If not NULL, @p next is filled with the timestamp
318  *  of the next scheduled retransmission, or @c 0 when no packets are
319  *  waiting.
320  */
321 void dtls_check_retransmit(dtls_context_t *context, clock_time_t *next);
322 
323 #define DTLS_COOKIE_LENGTH 16
324 
325 #define DTLS_CT_CHANGE_CIPHER_SPEC 20
326 #define DTLS_CT_ALERT              21
327 #define DTLS_CT_HANDSHAKE          22
328 #define DTLS_CT_APPLICATION_DATA   23
329 
330 /** Generic header structure of the DTLS record layer. */
331 typedef struct __attribute__((__packed__)) {
332   uint8 content_type;		/**< content type of the included message */
333   uint16 version;		/**< Protocol version */
334   uint16 epoch;		        /**< counter for cipher state changes */
335   uint48 sequence_number;       /**< sequence number */
336   uint16 length;		/**< length of the following fragment */
337   /* fragment */
338 } dtls_record_header_t;
339 
340 /* Handshake types */
341 
342 #define DTLS_HT_HELLO_REQUEST        0
343 #define DTLS_HT_CLIENT_HELLO         1
344 #define DTLS_HT_SERVER_HELLO         2
345 #define DTLS_HT_HELLO_VERIFY_REQUEST 3
346 #define DTLS_HT_CERTIFICATE         11
347 #define DTLS_HT_SERVER_KEY_EXCHANGE 12
348 #define DTLS_HT_CERTIFICATE_REQUEST 13
349 #define DTLS_HT_SERVER_HELLO_DONE   14
350 #define DTLS_HT_CERTIFICATE_VERIFY  15
351 #define DTLS_HT_CLIENT_KEY_EXCHANGE 16
352 #define DTLS_HT_FINISHED            20
353 
354 /** Header structure for the DTLS handshake protocol. */
355 typedef struct __attribute__((__packed__)) {
356   uint8 msg_type; /**< Type of handshake message  (one of DTLS_HT_) */
357   uint24 length;  /**< length of this message */
358   uint16 message_seq; 	/**< Message sequence number */
359   uint24 fragment_offset;	/**< Fragment offset. */
360   uint24 fragment_length;	/**< Fragment length. */
361   /* body */
362 } dtls_handshake_header_t;
363 
364 /** Structure of the Client Hello message. */
365 typedef struct __attribute__((__packed__)) {
366   uint16 version;	  /**< Client version */
367   uint32 gmt_random;	  /**< GMT time of the random byte creation */
368   unsigned char random[28];	/**< Client random bytes */
369   /* session id (up to 32 bytes) */
370   /* cookie (up to 32 bytes) */
371   /* cipher suite (2 to 2^16 -1 bytes) */
372   /* compression method */
373 } dtls_client_hello_t;
374 
375 /** Structure of the Hello Verify Request. */
376 typedef struct __attribute__((__packed__)) {
377   uint16 version;		/**< Server version */
378   uint8 cookie_length;	/**< Length of the included cookie */
379   uint8 cookie[];		/**< up to 32 bytes making up the cookie */
380 } dtls_hello_verify_t;
381 
382 #if 0
383 /**
384  * Checks a received DTLS record for consistency and eventually decrypt,
385  * verify, decompress and reassemble the contained fragment for
386  * delivery to high-lever clients.
387  *
388  * \param state The DTLS record state for the current session.
389  * \param
390  */
391 int dtls_record_read(dtls_state_t *state, uint8 *msg, int msglen);
392 #endif
393 
394 /**
395  * Handles incoming data as DTLS message from given peer.
396  *
397  * @param ctx     The dtls context to use.
398  * @param session The current session
399  * @param msg     The received data
400  * @param msglen  The actual length of @p msg.
401  * @return A value less than zero on error, zero on success.
402  */
403 int dtls_handle_message(dtls_context_t *ctx, session_t *session,
404 			uint8 *msg, int msglen);
405 
406 /**
407  * Check if @p session is associated with a peer object in @p context.
408  * This function returns a pointer to the peer if found, NULL otherwise.
409  *
410  * @param context  The DTLS context to search.
411  * @param session  The remote address and local interface
412  * @return A pointer to the peer associated with @p session or NULL if
413  *  none exists.
414  */
415 dtls_peer_t *dtls_get_peer(const dtls_context_t *context,
416 			   const session_t *session);
417 
418 
419 #endif /* _DTLS_DTLS_H_ */
420 
421 /**
422  * @mainpage
423  *
424  * @author Olaf Bergmann, TZI Uni Bremen
425  *
426  * This library provides a very simple datagram server with DTLS
427  * support. It is designed to support session multiplexing in
428  * single-threaded applications and thus targets specifically on
429  * embedded systems.
430  *
431  * @section license License
432  *
433  * This software is under the <a
434  * href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>.
435  *
436  * @subsection uthash UTHash
437  *
438  * This library uses <a href="http://uthash.sourceforge.net/">uthash</a> to manage
439  * its peers (not used for Contiki). @b uthash uses the <b>BSD revised license</b>, see
440  * <a href="http://uthash.sourceforge.net/license.html">http://uthash.sourceforge.net/license.html</a>.
441  *
442  * @subsection sha256 Aaron D. Gifford's SHA256 Implementation
443  *
444  * tinyDTLS provides HMAC-SHA256 with BSD-licensed code from Aaron D. Gifford,
445  * see <a href="http://www.aarongifford.com/">www.aarongifford.com</a>.
446  *
447  * @subsection aes Rijndael Implementation From OpenBSD
448  *
449  * The AES implementation is taken from rijndael.{c,h} contained in the crypto
450  * sub-system of the OpenBSD operating system. It is copyright by Vincent Rijmen, *
451  * Antoon Bosselaers and Paulo Barreto. See <a
452  * href="http://www.openbsd.org/cgi-bin/cvsweb/src/sys/crypto/rijndael.c">rijndael.c</a>
453  * for License info.
454  *
455  * @section download Getting the Files
456  *
457  * You can get the sources either from the <a
458  * href="http://sourceforge.net/projects/tinydtls/files">downloads</a> section or
459  * through git from the <a
460  * href="http://sourceforge.net/projects/tinydtls/develop">project develop page</a>.
461  *
462  * @section config Configuration
463  *
464  * Use @c configure to set up everything for a successful build. For Contiki, use the
465  * option @c --with-contiki.
466  *
467  * @section build Building
468  *
469  * After configuration, just type
470  * @code
471 make
472  * @endcode
473  * optionally followed by
474  * @code
475 make install
476  * @endcode
477  * The Contiki version is integrated with the Contiki build system, hence you do not
478  * need to invoke @c make explicitely. Just add @c tinydtls to the variable @c APPS
479  * in your @c Makefile.
480  *
481  * @addtogroup dtls_usage DTLS Usage
482  *
483  * @section dtls_server_example DTLS Server Example
484  *
485  * This section shows how to use the DTLS library functions to setup a
486  * simple secure UDP echo server. The application is responsible for the
487  * entire network communication and thus will look like a usual UDP
488  * server with socket creation and binding and a typical select-loop as
489  * shown below. The minimum configuration required for DTLS is the
490  * creation of the dtls_context_t using dtls_new_context(), and a callback
491  * for sending data. Received packets are read by the application and
492  * passed to dtls_handle_message() as shown in @ref dtls_read_cb.
493  * For any useful communication to happen, read and write call backs
494  * and a key management function should be registered as well.
495  *
496  * @code
497  dtls_context_t *the_context = NULL;
498  int fd, result;
499 
500  static dtls_handler_t cb = {
501    .write = send_to_peer,
502    .read  = read_from_peer,
503    .event = NULL,
504    .get_psk_key = get_psk_key
505  };
506 
507  fd = socket(...);
508  if (fd < 0 || bind(fd, ...) < 0)
509    exit(-1);
510 
511  the_context = dtls_new_context(&fd);
512  dtls_set_handler(the_context, &cb);
513 
514  while (1) {
515    ...initialize fd_set rfds and timeout ...
516    result = select(fd+1, &rfds, NULL, 0, NULL);
517 
518    if (FD_ISSET(fd, &rfds))
519      dtls_handle_read(the_context);
520  }
521 
522  dtls_free_context(the_context);
523  * @endcode
524  *
525  * @subsection dtls_read_cb The Read Callback
526  *
527  * The DTLS library expects received raw data to be passed to
528  * dtls_handle_message(). The application is responsible for
529  * filling a session_t structure with the address data of the
530  * remote peer as illustrated by the following example:
531  *
532  * @code
533 int dtls_handle_read(struct dtls_context_t *ctx) {
534   int *fd;
535   session_t session;
536   static uint8 buf[DTLS_MAX_BUF];
537   int len;
538 
539   fd = dtls_get_app_data(ctx);
540 
541   assert(fd);
542 
543   session.size = sizeof(session.addr);
544   len = recvfrom(*fd, buf, sizeof(buf), 0, &session.addr.sa, &session.size);
545 
546   return len < 0 ? len : dtls_handle_message(ctx, &session, buf, len);
547 }
548  * @endcode
549  *
550  * Once a new DTLS session was established and DTLS ApplicationData has been
551  * received, the DTLS server invokes the read callback with the MAC-verified
552  * cleartext data as its argument. A read callback for a simple echo server
553  * could look like this:
554  * @code
555 int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
556   return dtls_write(ctx, session, data, len);
557 }
558  * @endcode
559  *
560  * @subsection dtls_send_cb The Send Callback
561  *
562  * The callback function send_to_peer() is called whenever data must be
563  * sent over the network. Here, the sendto() system call is used to
564  * transmit data within the given session. The socket descriptor required
565  * by sendto() has been registered as application data when the DTLS context
566  * was created with dtls_new_context().
567  * Note that it is on the application to buffer the data when it cannot be
568  * sent at the time this callback is invoked. The following example thus
569  * is incomplete as it would have to deal with EAGAIN somehow.
570  * @code
571 int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
572   int fd = *(int *)dtls_get_app_data(ctx);
573   return sendto(fd, data, len, MSG_DONTWAIT, &session->addr.sa, session->size);
574 }
575  * @endcode
576  *
577  * @subsection dtls_get_psk_info The Key Storage
578  *
579  * When a new DTLS session is created, the library must ask the application
580  * for keying material. To do so, it invokes the registered call-back function
581  * get_psk_info() with the current context and session information as parameter.
582  * When the call-back function is invoked with the parameter @p type set to
583  * @c DTLS_PSK_IDENTITY, the result parameter @p result must be filled with
584  * the psk_identity_hint in case of a server, or the actual psk_identity in
585  * case of a client. When @p type is @c DTLS_PSK_KEY, the result parameter
586  * must be filled with a key for the given identity @p id. The function must
587  * return the number of bytes written to @p result which must not exceed
588  * @p result_length.
589  * In case of an error, the function must return a negative value that
590  * corresponds to a valid error code defined in alert.h.
591  *
592  * @code
593 int get_psk_info(struct dtls_context_t *ctx UNUSED_PARAM,
594 	    const session_t *session UNUSED_PARAM,
595 	    dtls_credentials_type_t type,
596 	    const unsigned char *id, size_t id_len,
597 	    unsigned char *result, size_t result_length) {
598 
599   switch (type) {
600   case DTLS_PSK_IDENTITY:
601     if (result_length < psk_id_length) {
602       dtls_warn("cannot set psk_identity -- buffer too small\n");
603       return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
604     }
605 
606     memcpy(result, psk_id, psk_id_length);
607     return psk_id_length;
608   case DTLS_PSK_KEY:
609     if (id_len != psk_id_length || memcmp(psk_id, id, id_len) != 0) {
610       dtls_warn("PSK for unknown id requested, exiting\n");
611       return dtls_alert_fatal_create(DTLS_ALERT_ILLEGAL_PARAMETER);
612     } else if (result_length < psk_key_length) {
613       dtls_warn("cannot set psk -- buffer too small\n");
614       return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
615     }
616 
617     memcpy(result, psk_key, psk_key_length);
618     return psk_key_length;
619   default:
620     dtls_warn("unsupported request type: %d\n", type);
621   }
622 
623   return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
624 }
625  * @endcode
626  *
627  * @subsection dtls_events The Event Notifier
628  *
629  * Applications that want to be notified whenever the status of a DTLS session
630  * has changed can register an event handling function with the field @c event
631  * in the dtls_handler_t structure (see \ref dtls_server_example). The call-back
632  * function is called for alert messages and internal state changes. For alert
633  * messages, the argument @p level will be set to a value greater than zero, and
634  * @p code will indicate the notification code. For internal events, @p level
635  * is @c 0, and @p code a value greater than @c 255.
636  *
637  * Internal events are DTLS_EVENT_CONNECTED, @c DTLS_EVENT_CONNECT, and
638  * @c DTLS_EVENT_RENEGOTIATE.
639  *
640  * @code
641 int handle_event(struct dtls_context_t *ctx, session_t *session,
642                  dtls_alert_level_t level, unsigned short code) {
643   ... do something with event ...
644   return 0;
645 }
646  * @endcode
647  *
648  * @section dtls_client_example DTLS Client Example
649  *
650  * A DTLS client is constructed like a server but needs to actively setup
651  * a new session by calling dtls_connect() at some point. As this function
652  * usually returns before the new DTLS channel is established, the application
653  * must register an event handler and wait for @c DTLS_EVENT_CONNECT before
654  * it can send data over the DTLS channel.
655  *
656  */
657 
658 /**
659  * @addtogroup contiki Contiki
660  *
661  * To use tinyDTLS as Contiki application, place the source code in the directory
662  * @c apps/tinydtls in the Contiki source tree and invoke configure with the option
663  * @c --with-contiki. This will define WITH_CONTIKI in tinydtls.h and include
664  * @c Makefile.contiki in the main Makefile. To cross-compile for another platform
665  * you will need to set your host and build system accordingly. For example,
666  * when configuring for ARM, you would invoke
667  * @code
668 ./configure --with-contiki --build=x86_64-linux-gnu --host=arm-none-eabi
669  * @endcode
670  * on an x86_64 linux host.
671  *
672  * Then, create a Contiki project with @c APPS += tinydtls in its Makefile. A sample
673  * server could look like this (with read_from_peer() and get_psk_key() as shown above).
674  *
675  * @code
676 #include "contiki.h"
677 
678 #include "tinydtls.h"
679 #include "dtls.h"
680 
681 #define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
682 #define UIP_UDP_BUF  ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
683 
684 int send_to_peer(struct dtls_context_t *, session_t *, uint8 *, size_t);
685 
686 static struct uip_udp_conn *server_conn;
687 static dtls_context_t *dtls_context;
688 
689 static dtls_handler_t cb = {
690   .write = send_to_peer,
691   .read  = read_from_peer,
692   .event = NULL,
693   .get_psk_key = get_psk_key
694 };
695 
696 PROCESS(server_process, "DTLS server process");
697 AUTOSTART_PROCESSES(&server_process);
698 
699 PROCESS_THREAD(server_process, ev, data)
700 {
701   PROCESS_BEGIN();
702 
703   dtls_init();
704 
705   server_conn = udp_new(NULL, 0, NULL);
706   udp_bind(server_conn, UIP_HTONS(5684));
707 
708   dtls_context = dtls_new_context(server_conn);
709   if (!dtls_context) {
710     dtls_emerg("cannot create context\n");
711     PROCESS_EXIT();
712   }
713 
714   dtls_set_handler(dtls_context, &cb);
715 
716   while(1) {
717     PROCESS_WAIT_EVENT();
718     if(ev == tcpip_event && uip_newdata()) {
719       session_t session;
720 
721       uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr);
722       session.port = UIP_UDP_BUF->srcport;
723       session.size = sizeof(session.addr) + sizeof(session.port);
724 
725       dtls_handle_message(ctx, &session, uip_appdata, uip_datalen());
726     }
727   }
728 
729   PROCESS_END();
730 }
731 
732 int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
733   struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx);
734 
735   uip_ipaddr_copy(&conn->ripaddr, &session->addr);
736   conn->rport = session->port;
737 
738   uip_udp_packet_send(conn, data, len);
739 
740   memset(&conn->ripaddr, 0, sizeof(server_conn->ripaddr));
741   memset(&conn->rport, 0, sizeof(conn->rport));
742 
743   return len;
744 }
745  * @endcode
746  */
747