mbed port of tinydtls

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dtls.h Source File

dtls.h

Go to the documentation of this file.
00001 /* dtls -- a very basic DTLS implementation
00002  *
00003  * Copyright (C) 2011--2013 Olaf Bergmann <bergmann@tzi.org>
00004  *
00005  * Permission is hereby granted, free of charge, to any person
00006  * obtaining a copy of this software and associated documentation
00007  * files (the "Software"), to deal in the Software without
00008  * restriction, including without limitation the rights to use, copy,
00009  * modify, merge, publish, distribute, sublicense, and/or sell copies
00010  * of the Software, and to permit persons to whom the Software is
00011  * furnished to do so, subject to the following conditions:
00012  *
00013  * The above copyright notice and this permission notice shall be
00014  * included in all copies or substantial portions of the Software.
00015  *
00016  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
00017  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00018  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
00019  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
00020  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
00021  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00022  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
00023  * SOFTWARE.
00024  */
00025 
00026 /**
00027  * @file dtls.h
00028  * @brief High level DTLS API and visible structures. 
00029  */
00030 
00031 #ifndef _DTLS_H_
00032 #define _DTLS_H_
00033 
00034 #include <stdint.h>
00035 
00036 #include "t_list.h"
00037 #include "state.h"
00038 #include "peer.h"
00039 
00040 #ifndef WITH_CONTIKI
00041 #include "uthash.h"
00042 #endif /* WITH_CONTIKI */
00043 
00044 #include "alert.h"
00045 #include "crypto.h"
00046 #include "hmac.h"
00047 
00048 #include "config.h"
00049 #include "global.h"
00050 #include "dtls_time.h"
00051 
00052 #ifndef DTLSv12
00053 #define DTLS_VERSION 0xfeff /* DTLS v1.1 */
00054 #else
00055 #define DTLS_VERSION 0xfefd /* DTLS v1.2 */
00056 #endif
00057 
00058 /** Known compression methods
00059  *
00060  * \hideinitializer
00061  */
00062 #define TLS_COMP_NULL      0x00 /* NULL compression */
00063  
00064 typedef enum {
00065   DTLS_KEY_INVALID=0, DTLS_KEY_PSK=1, DTLS_KEY_RPK=2
00066 } dtls_key_type_t;
00067 
00068 typedef struct dtls_key_t {
00069   dtls_key_type_t type;
00070   union {
00071     struct dtls_psk_t {
00072       unsigned char *id;     /**< psk identity */
00073       size_t id_length;      /**< length of psk identity  */
00074       unsigned char *key;    /**< key data */
00075       size_t key_length;     /**< length of key */
00076     } psk;
00077   } key;
00078 } dtls_key_t;
00079 
00080 /** Length of the secret that is used for generating Hello Verify cookies. */
00081 #define DTLS_COOKIE_SECRET_LENGTH 12
00082 
00083 struct dtls_context_t;
00084 
00085 #ifdef __cplusplus
00086 extern "C" {
00087 #endif
00088 
00089 /**
00090  * This structure contains callback functions used by tinydtls to
00091  * communicate with the application. At least the write function must
00092  * be provided. It is called by the DTLS state machine to send packets
00093  * over the network. The read function is invoked to deliver decrypted
00094  * and verfified application data. The third callback is an event
00095  * handler function that is called when alert messages are encountered
00096  * or events generated by the library have occured.
00097  */ 
00098 typedef struct {
00099   /** 
00100    * Called from dtls_handle_message() to send DTLS packets over the
00101    * network. The callback function must use the network interface
00102    * denoted by session->ifindex to send the data.
00103    *
00104    * @param ctx  The current DTLS context.
00105    * @param session The session object, including the address of the
00106    *              remote peer where the data shall be sent.
00107    * @param buf  The data to send.
00108    * @param len  The actual length of @p buf.
00109    * @return The callback function must return the number of bytes 
00110    *         that were sent, or a value less than zero to indicate an 
00111    *         error.
00112    */
00113   int (*write)(struct dtls_context_t *ctx, 
00114            session_t *session, uint8 *buf, size_t len);
00115 
00116   /** 
00117    * Called from dtls_handle_message() deliver application data that was 
00118    * received on the given session. The data is delivered only after
00119    * decryption and verification have succeeded. 
00120    *
00121    * @param ctx  The current DTLS context.
00122    * @param session The session object, including the address of the
00123    *              data's origin. 
00124    * @param buf  The received data packet.
00125    * @param len  The actual length of @p buf.
00126    * @return ignored
00127    */
00128   int (*read)(struct dtls_context_t *ctx, 
00129            session_t *session, uint8 *buf, size_t len);
00130 
00131   /**
00132    * The event handler is called when a message from the alert
00133    * protocol is received or the state of the DTLS session changes.
00134    *
00135    * @param ctx     The current dtls context.
00136    * @param session The session object that was affected.
00137    * @param level   The alert level or @c 0 when an event ocurred that 
00138    *                is not an alert. 
00139    * @param code    Values less than @c 256 indicate alerts, while
00140    *                @c 256 or greater indicate internal DTLS session changes.
00141    * @return ignored
00142    */
00143   int (*event)(struct dtls_context_t *ctx, session_t *session, 
00144         dtls_alert_level_t level, unsigned short code);
00145 
00146   /**
00147    * Called during handshake to lookup the key for @p id in @p
00148    * session. If found, the key must be stored in @p result and 
00149    * the return value must be @c 0. If not found, @p result is 
00150    * undefined and the return value must be less than zero.
00151    *
00152    * @param ctx     The current dtls context.
00153    * @param session The session where the key will be used.
00154    * @param id      The identity of the communicating peer. This value is
00155    *                @c NULL when the DTLS engine requests the local
00156    *                id/key pair to use for session setup.
00157    * @param id_len  The actual length of @p id
00158    * @param result  Must be set to the key object to use.for the given
00159    *                session.
00160    * @return @c 0 if result is set, or less than zero on error.
00161    */
00162   int (*get_key)(struct dtls_context_t *ctx, 
00163          const session_t *session, 
00164          const unsigned char *id, size_t id_len, 
00165          const dtls_key_t **result);
00166 } dtls_handler_t;
00167 
00168 /** Holds global information of the DTLS engine. */
00169 typedef struct dtls_context_t {
00170   unsigned char cookie_secret[DTLS_COOKIE_SECRET_LENGTH];
00171   clock_time_t cookie_secret_age; /**< the time the secret has been generated */
00172 
00173 #ifndef WITH_CONTIKI
00174   dtls_peer_t *peers;       /**< peer hash map */
00175 #else /* WITH_CONTIKI */
00176   LIST_STRUCT(peers);
00177 
00178   struct etimer retransmit_timer; /**< fires when the next packet must be sent */
00179 #endif /* WITH_CONTIKI */
00180 
00181   LIST_STRUCT(sendqueue);   /**< the packets to send */
00182 
00183   void *app;            /**< application-specific data */
00184 
00185   dtls_handler_t *h;        /**< callback handlers */
00186 
00187   unsigned char readbuf[DTLS_MAX_BUF];
00188   unsigned char sendbuf[DTLS_MAX_BUF];
00189 } dtls_context_t;
00190 
00191 /** 
00192  * This function initializes the tinyDTLS memory management and must
00193  * be called first.
00194  */
00195 void dtls_init();
00196 
00197 /** 
00198  * Creates a new context object. The storage allocated for the new
00199  * object must be released with dtls_free_context(). */
00200 dtls_context_t *dtls_new_context(void *app_data);
00201 
00202 /** Releases any storage that has been allocated for \p ctx. */
00203 void dtls_free_context(dtls_context_t *ctx);
00204 
00205 #define dtls_set_app_data(CTX,DATA) ((CTX)->app = (DATA))
00206 #define dtls_get_app_data(CTX) ((CTX)->app)
00207 
00208 /** Sets the callback handler object for @p ctx to @p h. */
00209 static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
00210   ctx->h = h;
00211 }
00212 
00213 /**
00214  * Establishes a DTLS channel with the specified remote peer @p dst.
00215  * This function returns @c 0 if that channel already exists, a value
00216  * greater than zero when a new ClientHello message was sent, and
00217  * a value less than zero on error.
00218  *
00219  * @param ctx    The DTLS context to use.
00220  * @param dst    The remote party to connect to.
00221  * @return A value less than zero on error, greater or equal otherwise.
00222  */
00223 int dtls_connect(dtls_context_t *ctx, const session_t *dst);
00224 
00225 /**
00226  * Establishes a DTLS channel with the specified remote peer.
00227  * This function returns @c 0 if that channel already exists, a value
00228  * greater than zero when a new ClientHello message was sent, and
00229  * a value less than zero on error.
00230  *
00231  * @param ctx    The DTLS context to use.
00232  * @param peer   The peer object that describes the session.
00233  * @return A value less than zero on error, greater or equal otherwise.
00234  */
00235 int dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer);
00236 
00237 /**
00238  * Closes the DTLS connection associated with @p remote. This function
00239  * returns zero on success, and a value less than zero on error.
00240  */
00241 int dtls_close(dtls_context_t *ctx, const session_t *remote);
00242 
00243 /** 
00244  * Writes the application data given in @p buf to the peer specified
00245  * by @p session. 
00246  * 
00247  * @param ctx      The DTLS context to use.
00248  * @param session  The remote transport address and local interface.
00249  * @param buf      The data to write.
00250  * @param len      The actual length of @p data.
00251  * 
00252  * @return The number of bytes written or @c -1 on error.
00253  */
00254 int dtls_write(struct dtls_context_t *ctx, session_t *session, 
00255            uint8 *buf, size_t len);
00256 
00257 /**
00258  * Checks sendqueue of given DTLS context object for any outstanding
00259  * packets to be transmitted. 
00260  *
00261  * @param context The DTLS context object to use.
00262  * @param next    If not NULL, @p next is filled with the timestamp
00263  *  of the next scheduled retransmission, or @c 0 when no packets are
00264  *  waiting.
00265  */
00266 void dtls_check_retransmit(dtls_context_t *context, clock_time_t *next);
00267 
00268 #define DTLS_COOKIE_LENGTH 16
00269 
00270 #define DTLS_CT_CHANGE_CIPHER_SPEC 20
00271 #define DTLS_CT_ALERT              21
00272 #define DTLS_CT_HANDSHAKE          22
00273 #define DTLS_CT_APPLICATION_DATA   23
00274 
00275 /** Generic header structure of the DTLS record layer. */
00276 typedef struct {
00277   uint8 content_type;       /**< content type of the included message */
00278   uint16 version;       /**< Protocol version */
00279   uint16 epoch;             /**< counter for cipher state changes */
00280   uint48 sequence_number;       /**< sequence number */
00281   uint16 length;        /**< length of the following fragment */
00282   /* fragment */
00283 } dtls_record_header_t;
00284 
00285 /* Handshake types */
00286 
00287 #define DTLS_HT_HELLO_REQUEST        0
00288 #define DTLS_HT_CLIENT_HELLO         1
00289 #define DTLS_HT_SERVER_HELLO         2
00290 #define DTLS_HT_HELLO_VERIFY_REQUEST 3
00291 #define DTLS_HT_CERTIFICATE         11
00292 #define DTLS_HT_SERVER_KEY_EXCHANGE 12
00293 #define DTLS_HT_CERTIFICATE_REQUEST 13
00294 #define DTLS_HT_SERVER_HELLO_DONE   14
00295 #define DTLS_HT_CERTIFICATE_VERIFY  15
00296 #define DTLS_HT_CLIENT_KEY_EXCHANGE 16
00297 #define DTLS_HT_FINISHED            20
00298 
00299 /** Header structure for the DTLS handshake protocol. */
00300 typedef struct {
00301   uint8 msg_type; /**< Type of handshake message  (one of DTLS_HT_) */
00302   uint24 length;  /**< length of this message */
00303   uint16 message_seq;   /**< Message sequence number */
00304   uint24 fragment_offset;   /**< Fragment offset. */
00305   uint24 fragment_length;   /**< Fragment length. */
00306   /* body */
00307 } dtls_handshake_header_t;
00308 
00309 /** Structure of the Client Hello message. */
00310 typedef struct {
00311   uint16 version;     /**< Client version */
00312   uint32 gmt_random;      /**< GMT time of the random byte creation */
00313   unsigned char random[28]; /**< Client random bytes */
00314   /* session id (up to 32 bytes) */
00315   /* cookie (up to 32 bytes) */
00316   /* cipher suite (2 to 2^16 -1 bytes) */
00317   /* compression method */
00318 } dtls_client_hello_t;
00319 
00320 /** Structure of the Hello Verify Request. */
00321 typedef struct {
00322   uint16 version;       /**< Server version */
00323   uint8 cookie_length;  /**< Length of the included cookie */
00324   uint8 cookie[];       /**< up to 32 bytes making up the cookie */
00325 } dtls_hello_verify_t;  
00326 
00327 #if 0
00328 /** 
00329  * Checks a received DTLS record for consistency and eventually decrypt,
00330  * verify, decompress and reassemble the contained fragment for 
00331  * delivery to high-lever clients. 
00332  * 
00333  * \param state The DTLS record state for the current session. 
00334  * \param 
00335  */
00336 int dtls_record_read(dtls_state_t *state, uint8 *msg, int msglen);
00337 #endif
00338 
00339 /**
00340  * Retrieves a pointer to the cookie contained in a Client Hello message.
00341  *
00342  * \param hello_msg   Points to the received Client Hello message
00343  * \param msglen      Length of \p hello_msg
00344  * \param cookie      Is set to the beginning of the cookie in the message if
00345  *                    found. Undefined if this function returns \c 0.
00346  * \return \c 0 if no cookie was found, < 0 on error. On success, the return
00347  *         value reflects the cookie's length.
00348  */
00349 int dtls_get_cookie(uint8 *hello_msg, int msglen, uint8 **cookie);
00350 
00351 /** 
00352  * Handles incoming data as DTLS message from given peer.
00353  *
00354  * @param ctx     The dtls context to use.
00355  * @param session The current session
00356  * @param msg     The received data
00357  * @param msglen  The actual length of @p msg.
00358  * @return A value less than zero on error, zero on success.
00359  */
00360 int dtls_handle_message(dtls_context_t *ctx, session_t *session,
00361             uint8 *msg, int msglen);
00362 
00363 /**
00364  * Check if @p session is associated with a peer object in @p context.
00365  * This function returns a pointer to the peer if found, NULL otherwise.
00366  *
00367  * @param context  The DTLS context to search.
00368  * @param session  The remote address and local interface
00369  * @return A pointer to the peer associated with @p session or NULL if
00370  *  none exists.
00371  */
00372 dtls_peer_t *dtls_get_peer(const dtls_context_t *context,
00373                const session_t *session);
00374 
00375 
00376 #endif /* _DTLS_H_ */
00377 
00378 /**
00379  * @mainpage 
00380  *
00381  * @author Olaf Bergmann, TZI Uni Bremen
00382  *
00383  * This library provides a very simple datagram server with DTLS
00384  * support. It is designed to support session multiplexing in
00385  * single-threaded applications and thus targets specifically on
00386  * embedded systems.
00387  *
00388  * @section license License
00389  *
00390  * This software is under the <a 
00391  * href="http://www.opensource.org/licenses/mit-license.php">MIT License</a>.
00392  * 
00393  * @subsection uthash UTHash
00394  *
00395  * This library uses <a href="http://uthash.sourceforge.net/">uthash</a> to manage
00396  * its peers (not used for Contiki). @b uthash uses the <b>BSD revised license</b>, see
00397  * <a href="http://uthash.sourceforge.net/license.html">http://uthash.sourceforge.net/license.html</a>.
00398  *
00399  * @subsection sha256 Aaron D. Gifford's SHA256 Implementation
00400  *
00401  * tinyDTLS provides HMAC-SHA256 with BSD-licensed code from Aaron D. Gifford, 
00402  * see <a href="http://www.aarongifford.com/">www.aarongifford.com</a>.
00403  *
00404  * @subsection aes Rijndael Implementation From OpenBSD
00405  *
00406  * The AES implementation is taken from rijndael.{c,h} contained in the crypto 
00407  * sub-system of the OpenBSD operating system. It is copyright by Vincent Rijmen, *
00408  * Antoon Bosselaers and Paulo Barreto. See <a 
00409  * href="http://www.openbsd.org/cgi-bin/cvsweb/src/sys/crypto/rijndael.c">rijndael.c</a> 
00410  * for License info.
00411  *
00412  * @section download Getting the Files
00413  *
00414  * You can get the sources either from the <a 
00415  * href="http://sourceforge.net/projects/tinydtls/files">downloads</a> section or 
00416  * through git from the <a 
00417  * href="http://sourceforge.net/projects/tinydtls/develop">project develop page</a>.
00418  *
00419  * @section config Configuration
00420  *
00421  * Use @c configure to set up everything for a successful build. For Contiki, use the
00422  * option @c --with-contiki.
00423  *
00424  * @section build Building
00425  *
00426  * After configuration, just type 
00427  * @code
00428 make
00429  * @endcode
00430  * optionally followed by
00431  * @code
00432 make install
00433  * @endcode
00434  * The Contiki version is integrated with the Contiki build system, hence you do not
00435  * need to invoke @c make explicitely. Just add @c tinydtls to the variable @c APPS
00436  * in your @c Makefile.
00437  *
00438  * @addtogroup dtls_usage DTLS Usage
00439  *
00440  * @section dtls_server_example DTLS Server Example
00441  *
00442  * This section shows how to use the DTLS library functions to setup a 
00443  * simple secure UDP echo server. The application is responsible for the
00444  * entire network communication and thus will look like a usual UDP
00445  * server with socket creation and binding and a typical select-loop as
00446  * shown below. The minimum configuration required for DTLS is the 
00447  * creation of the dtls_context_t using dtls_new_context(), and a callback
00448  * for sending data. Received packets are read by the application and
00449  * passed to dtls_handle_message() as shown in @ref dtls_read_cb. 
00450  * For any useful communication to happen, read and write call backs 
00451  * and a key management function should be registered as well. 
00452  * 
00453  * @code 
00454  dtls_context_t *the_context = NULL;
00455  int fd, result;
00456 
00457  static dtls_handler_t cb = {
00458    .write = send_to_peer,
00459    .read  = read_from_peer,
00460    .event = NULL,
00461    .get_key = get_key
00462  };
00463 
00464  fd = socket(...);
00465  if (fd < 0 || bind(fd, ...) < 0)
00466    exit(-1);
00467 
00468  the_context = dtls_new_context(&fd);
00469  dtls_set_handler(the_context, &cb);
00470 
00471  while (1) {
00472    ...initialize fd_set rfds and timeout ...
00473    result = select(fd+1, &rfds, NULL, 0, NULL);
00474     
00475    if (FD_ISSET(fd, &rfds))
00476      dtls_handle_read(the_context);
00477  }
00478 
00479  dtls_free_context(the_context);
00480  * @endcode
00481  * 
00482  * @subsection dtls_read_cb The Read Callback
00483  *
00484  * The DTLS library expects received raw data to be passed to
00485  * dtls_handle_message(). The application is responsible for
00486  * filling a session_t structure with the address data of the
00487  * remote peer as illustrated by the following example:
00488  * 
00489  * @code
00490 int dtls_handle_read(struct dtls_context_t *ctx) {
00491   int *fd;
00492   session_t session;
00493   static uint8 buf[DTLS_MAX_BUF];
00494   int len;
00495 
00496   fd = dtls_get_app_data(ctx);
00497 
00498   assert(fd);
00499 
00500   session.size = sizeof(session.addr);
00501   len = recvfrom(*fd, buf, sizeof(buf), 0, &session.addr.sa, &session.size);
00502   
00503   return len < 0 ? len : dtls_handle_message(ctx, &session, buf, len);
00504 }    
00505  * @endcode 
00506  * 
00507  * Once a new DTLS session was established and DTLS ApplicationData has been
00508  * received, the DTLS server invokes the read callback with the MAC-verified 
00509  * cleartext data as its argument. A read callback for a simple echo server
00510  * could look like this:
00511  * @code
00512 int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
00513   return dtls_write(ctx, session, data, len);
00514 }
00515  * @endcode 
00516  * 
00517  * @subsection dtls_send_cb The Send Callback
00518  * 
00519  * The callback function send_to_peer() is called whenever data must be
00520  * sent over the network. Here, the sendto() system call is used to
00521  * transmit data within the given session. The socket descriptor required
00522  * by sendto() has been registered as application data when the DTLS context
00523  * was created with dtls_new_context().
00524  * Note that it is on the application to buffer the data when it cannot be
00525  * sent at the time this callback is invoked. The following example thus
00526  * is incomplete as it would have to deal with EAGAIN somehow.
00527  * @code
00528 int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
00529   int fd = *(int *)dtls_get_app_data(ctx);
00530   return sendto(fd, data, len, MSG_DONTWAIT, &session->addr.sa, session->size);
00531 }
00532  * @endcode
00533  * 
00534  * @subsection dtls_get_key The Key Storage
00535  *
00536  * When a new DTLS session is created, the library must ask the application
00537  * for keying material. To do so, it invokes the registered call-back function
00538  * get_key() with the current context and session information as parameter.
00539  * When the function is called with the @p id parameter set, the result must
00540  * point to a dtls_key_t structure for the given identity. When @p id is 
00541  * @c NULL, the function must pick a suitable identity and return a pointer to
00542  * the corresponding dtls_key_t structure. The following example shows a
00543  * simple key storage for a pre-shared key for @c Client_identity:
00544  * 
00545  * @code
00546 int get_key(struct dtls_context_t *ctx, 
00547     const session_t *session, 
00548     const unsigned char *id, size_t id_len, 
00549     const dtls_key_t **result) {
00550 
00551   static const dtls_key_t psk = {
00552     .type = DTLS_KEY_PSK,
00553     .key.psk.id = (unsigned char *)"my identity", 
00554     .key.psk.id_length = 11,
00555     .key.psk.key = (unsigned char *)"secret", 
00556     .key.psk.key_length = 6
00557   };
00558    
00559   *result = &psk;
00560   return 0;
00561 }
00562  * @endcode
00563  * 
00564  * @subsection dtls_events The Event Notifier
00565  *
00566  * Applications that want to be notified whenever the status of a DTLS session
00567  * has changed can register an event handling function with the field @c event
00568  * in the dtls_handler_t structure (see \ref dtls_server_example). The call-back
00569  * function is called for alert messages and internal state changes. For alert
00570  * messages, the argument @p level will be set to a value greate than zero, and
00571  * @p code will indicate the notification code. For internal events, @p level
00572  * is @c 0, and @p code a value greater than @c 255. 
00573  *
00574  * Currently, the only defined internal event is @c DTLS_EVENT_CONNECTED. It
00575  * indicates successful establishment of a new DTLS channel.
00576  *
00577  * @code
00578 int handle_event(struct dtls_context_t *ctx, session_t *session, 
00579                  dtls_alert_level_t level, unsigned short code) {
00580   ... do something with event ...
00581   return 0;
00582 }
00583  * @endcode
00584  *
00585  * @section dtls_client_example DTLS Client Example
00586  *
00587  * A DTLS client is constructed like a server but needs to actively setup
00588  * a new session by calling dtls_connect() at some point. As this function
00589  * usually returns before the new DTLS channel is established, the application
00590  * must register an event handler and wait for @c DTLS_EVENT_CONNECT before
00591  * it can send data over the DTLS channel.
00592  *
00593  */
00594 
00595 /**
00596  * @addtogroup contiki Contiki
00597  *
00598  * To use tinyDTLS as Contiki application, place the source code in the directory 
00599  * @c apps/tinydtls in the Contiki source tree and invoke configure with the option
00600  * @c --with-contiki. This will create the tinydtls Makefile and config.h from the
00601  * templates @c Makefile.contiki and @c config.h.contiki instead of the usual 
00602  * templates ending in @c .in.
00603  *
00604  * Then, create a Contiki project with @c APPS += tinydtls in its Makefile. A sample
00605  * server could look like this (with read_from_peer() and get_key() as shown above).
00606  *
00607  * @code
00608 #include "contiki.h"
00609 
00610 #include "config.h"
00611 #include "dtls.h"
00612 
00613 #define UIP_IP_BUF   ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
00614 #define UIP_UDP_BUF  ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
00615 
00616 int send_to_peer(struct dtls_context_t *, session_t *, uint8 *, size_t);
00617 
00618 static struct uip_udp_conn *server_conn;
00619 static dtls_context_t *dtls_context;
00620 
00621 static dtls_handler_t cb = {
00622   .write = send_to_peer,
00623   .read  = read_from_peer,
00624   .event = NULL,
00625   .get_key = get_key
00626 };
00627 
00628 PROCESS(server_process, "DTLS server process");
00629 AUTOSTART_PROCESSES(&server_process);
00630 
00631 PROCESS_THREAD(server_process, ev, data)
00632 {
00633   PROCESS_BEGIN();
00634 
00635   dtls_init();
00636 
00637   server_conn = udp_new(NULL, 0, NULL);
00638   udp_bind(server_conn, UIP_HTONS(5684));
00639 
00640   dtls_context = dtls_new_context(server_conn);
00641   if (!dtls_context) {
00642     dsrv_log(LOG_EMERG, "cannot create context\n");
00643     PROCESS_EXIT();
00644   }
00645 
00646   dtls_set_handler(dtls_context, &cb);
00647 
00648   while(1) {
00649     PROCESS_WAIT_EVENT();
00650     if(ev == tcpip_event && uip_newdata()) {
00651       session_t session;
00652 
00653       uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr);
00654       session.port = UIP_UDP_BUF->srcport;
00655       session.size = sizeof(session.addr) + sizeof(session.port);
00656     
00657       dtls_handle_message(ctx, &session, uip_appdata, uip_datalen());
00658     }
00659   }
00660 
00661   PROCESS_END();
00662 }
00663 
00664 int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) {
00665   struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx);
00666 
00667   uip_ipaddr_copy(&conn->ripaddr, &session->addr);
00668   conn->rport = session->port;
00669 
00670   uip_udp_packet_send(conn, data, len);
00671 
00672   memset(&conn->ripaddr, 0, sizeof(server_conn->ripaddr));
00673   memset(&conn->rport, 0, sizeof(conn->rport));
00674 
00675   return len;
00676 }
00677  * @endcode
00678  */
00679 
00680 #ifdef __cplusplus
00681 }
00682 #endif