osd-contiki/apps/er-coap/er-coap-dtls.c

162 lines
4.5 KiB
C

#include "contiki.h"
#include "contiki-net.h"
#include "er-coap.h"
#include "er-coap-engine.h"
#include "dtls.h"
#include <string.h>
#define DEBUG DEBUG_NONE
#include "dtls_debug.h"
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
static struct dtls_context_t *dtls_ctx = NULL;
static dtls_handler_t coap_dtls_callback = {
.write = coap_dtls_send_to_peer,
.read = coap_dtls_read_from_peer,
.event = NULL,
#ifdef DTLS_PSK
.get_psk_info = coap_dtls_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, &COAP_DTLS_CALLBACK);
}
/* 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. */
int
coap_dtls_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
/*-----------------------------------------------------------------------------------*/
int
coap_dtls_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;
}
/*-----------------------------------------------------------------------------------*/
int
coap_dtls_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;
}