#include "contiki.h" #include "contiki-net.h" #include "er-coap.h" #include "er-coap-engine.h" #include "dtls.h" #include #define DEBUG DEBUG_NONE #include "dtls_debug.h" /*---------------------------------------------------------------------------*/ #if defined DTLS_CONF_IDENTITY && defined DTLS_CONF_IDENTITY_LENGTH #define DTLS_IDENTITY DTLS_CONF_IDENTITY #define DTLS_IDENTITY_LENGTH DTLS_CONF_IDENTITY_LENGTH #else #define DTLS_IDENTITY "Client_identity" #define DTLS_IDENTITY_LENGTH 15 #endif #if defined DTLS_CONF_PSK_KEY && defined DTLS_CONF_PSK_KEY_LENGTH #define DTLS_PSK_KEY_VALUE DTLS_CONF_PSK_KEY #define DTLS_PSK_KEY_VALUE_LENGTH DTLS_CONF_PSK_KEY_LENGTH #else #warning "DTLS: Using default secret key !" #define DTLS_PSK_KEY_VALUE "secretPSK" #define DTLS_PSK_KEY_VALUE_LENGTH 9 #endif /*---------------------------------------------------------------------------*/ static struct dtls_context_t *dtls_ctx = NULL; static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len); static int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len); 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); static dtls_handler_t dtls_cb = { .write = send_to_peer, .read = read_from_peer, .event = NULL, #ifdef DTLS_PSK .get_psk_info = get_psk_info, #endif #ifdef DTLS_ECC .get_ecdsa_key = NULL, .verify_ecdsa_key = NULL, #endif }; /*-----------------------------------------------------------------------------------*/ void coap_init_communication_layer(uint16_t port) { struct uip_udp_conn *udp_conn = NULL; dtls_init(); dtls_set_log_level(DTLS_LOG_DEBUG); udp_conn = udp_new(NULL, 0, NULL); udp_bind(udp_conn, port); dtls_ctx = dtls_new_context(udp_conn); if(dtls_ctx) { dtls_set_handler(dtls_ctx, &dtls_cb); } /* new connection with remote host */ printf("COAP-DTLS listening on port %u\n", uip_ntohs(udp_conn->lport)); } /*-----------------------------------------------------------------------------------*/ void coap_send_message(uip_ipaddr_t *addr, uint16_t port, uint8_t *data, uint16_t length) { session_t session; dtls_session_init(&session); uip_ipaddr_copy(&session.addr, addr); session.port = port; dtls_write(dtls_ctx, &session, data, length); } /*-----------------------------------------------------------------------------------*/ void coap_handle_receive() { session_t session; if(uip_newdata()) { dtls_session_init(&session); uip_ipaddr_copy(&session.addr, &UIP_IP_BUF->srcipaddr); session.port = UIP_UDP_BUF->srcport; dtls_handle_message(dtls_ctx, &session, uip_appdata, uip_datalen()); } } /* DTLS Specific functions */ /*-----------------------------------------------------------------------------------*/ #ifdef DTLS_PSK /* This function is the "key store" for tinyDTLS. It is called to * retrieve a key for the given identiy within this particular * session. */ 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) { struct keymap_t { unsigned char *id; size_t id_length; unsigned char *key; size_t key_length; } psk[1] = { { (unsigned char *)DTLS_IDENTITY, DTLS_IDENTITY_LENGTH, (unsigned char *)DTLS_PSK_KEY_VALUE, DTLS_PSK_KEY_VALUE_LENGTH }, }; if(type == DTLS_PSK_IDENTITY) { if(id_len) { dtls_debug("got psk_identity_hint: '%.*s'\n", id_len, id); } if(result_length < psk[0].id_length) { dtls_warn("cannot set psk_identity -- buffer too small\n"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, psk[0].id, psk[0].id_length); return psk[0].id_length; } else if(type == DTLS_PSK_KEY) { if(id) { int i; for(i = 0; i < sizeof(psk) / sizeof(struct keymap_t); i++) { if(id_len == psk[i].id_length && memcmp(id, psk[i].id, id_len) == 0) { if(result_length < psk[i].key_length) { dtls_warn("buffer too small for PSK"); return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR); } memcpy(result, psk[i].key, psk[i].key_length); return psk[i].key_length; } } } } else { return 0; } return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR); } #endif /*-----------------------------------------------------------------------------------*/ static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { struct uip_udp_conn *conn = (struct uip_udp_conn *)dtls_get_app_data(ctx); uip_ipaddr_copy(&conn->ripaddr, &session->addr); conn->rport = session->port; uip_udp_packet_send(conn, data, len); /* Restore server connection to allow data from any node */ memset(&conn->ripaddr, 0, sizeof(conn->ripaddr)); memset(&conn->rport, 0, sizeof(conn->rport)); return len; } /*-----------------------------------------------------------------------------------*/ static int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { uip_len = len; memmove(uip_appdata, data, len); coap_receive(ctx); return 0; }