mbed port of tinydtls
Embed:
(wiki syntax)
Show/hide line numbers
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
Generated on Thu Jul 14 2022 20:00:56 by 1.7.2