/* This is needed for apple */ #define __APPLE_USE_RFC_3542 #include "printf.h" #include //#include #include #include #include #include #include #include #include #include "lwip.h" #include "tinydtls.h" #include "dtls.h" #include "dtls_debug.h" #define DEFAULT_PORT 20220 static const unsigned char ecdsa_priv_key[] = { 0xD9, 0xE2, 0x70, 0x7A, 0x72, 0xDA, 0x6A, 0x05, 0x04, 0x99, 0x5C, 0x86, 0xED, 0xDB, 0xE3, 0xEF, 0xC7, 0xF1, 0xCD, 0x74, 0x83, 0x8F, 0x75, 0x70, 0xC8, 0x07, 0x2D, 0x0A, 0x76, 0x26, 0x1B, 0xD4 }; static const unsigned char ecdsa_pub_key_x[] = { 0xD0, 0x55, 0xEE, 0x14, 0x08, 0x4D, 0x6E, 0x06, 0x15, 0x59, 0x9D, 0xB5, 0x83, 0x91, 0x3E, 0x4A, 0x3E, 0x45, 0x26, 0xA2, 0x70, 0x4D, 0x61, 0xF2, 0x7A, 0x4C, 0xCF, 0xBA, 0x97, 0x58, 0xEF, 0x9A }; static const unsigned char ecdsa_pub_key_y[] = { 0xB4, 0x18, 0xB6, 0x4A, 0xFE, 0x80, 0x30, 0xDA, 0x1D, 0xDC, 0xF4, 0xF4, 0x2E, 0x2F, 0x26, 0x31, 0xD0, 0x43, 0xB1, 0xFB, 0x03, 0xE2, 0x2F, 0x4D, 0x17, 0xDE, 0x43, 0xF9, 0xF9, 0xAD, 0xEE, 0x70 }; /* SIGINT handler: set quit to 1 for graceful termination */ static void handle_sigint(int signum) { // dsrv_stop(dsrv_get_context()); } #ifdef DTLS_PSK /* This function is the "key store" for tinyDTLS. It is called to * retrieve a key for the given identity 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[3] = { { (unsigned char *)"Client_identity", 15, (unsigned char *)"secretPSK", 9 }, { (unsigned char *)"default identity", 16, (unsigned char *)"\x11\x22\x33", 3 }, { (unsigned char *)"\0", 2, (unsigned char *)"", 1 } }; if (type != DTLS_PSK_KEY) { return 0; } 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; } } } return dtls_alert_fatal_create(DTLS_ALERT_DECRYPT_ERROR); } #endif /* DTLS_PSK */ #ifdef DTLS_ECC static int get_ecdsa_key(struct dtls_context_t *ctx, const session_t *session, const dtls_ecdsa_key_t **result) { static const dtls_ecdsa_key_t ecdsa_key = { .curve = DTLS_ECDH_CURVE_SECP256R1, .priv_key = ecdsa_priv_key, .pub_key_x = ecdsa_pub_key_x, .pub_key_y = ecdsa_pub_key_y }; *result = &ecdsa_key; return 0; } static int verify_ecdsa_key(struct dtls_context_t *ctx, const session_t *session, const unsigned char *other_pub_x, const unsigned char *other_pub_y, size_t key_size) { return 0; } #endif /* DTLS_ECC */ #define DTLS_SERVER_CMD_CLOSE "server:close" #define DTLS_SERVER_CMD_RENEGOTIATE "server:renegotiate" static int dtls_event_cb(struct dtls_context_t *ctx, session_t *session, dtls_alert_level_t level, unsigned short code) { printf("dtls_event_cb->%d,%d\n", level, code); return 0; } static int read_from_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { size_t i; printf("read_from_peer->%s\n", data); if (len >= strlen(DTLS_SERVER_CMD_CLOSE) && !memcmp(data, DTLS_SERVER_CMD_CLOSE, strlen(DTLS_SERVER_CMD_CLOSE))) { printf("server: closing connection\n"); dtls_close(ctx, session); return len; } else if (len >= strlen(DTLS_SERVER_CMD_RENEGOTIATE) && !memcmp(data, DTLS_SERVER_CMD_RENEGOTIATE, strlen(DTLS_SERVER_CMD_RENEGOTIATE))) { printf("server: renegotiate connection\n"); dtls_renegotiate(ctx, session); return len; } return dtls_write(ctx, session, data, len); } static int send_to_peer(struct dtls_context_t *ctx, session_t *session, uint8 *data, size_t len) { int fd = *(int *)dtls_get_app_data(ctx); return sendto(fd, data, len, MSG_DONTWAIT, &session->addr.sa, session->size); } static int dtls_handle_read(struct dtls_context_t *ctx) { int *fd; session_t session; static uint8 buf[DTLS_MAX_BUF]; int len; fd = dtls_get_app_data(ctx); assert(fd); memset(&session, 0, sizeof(session_t)); session.size = sizeof(session.addr); len = recvfrom(*fd, buf, sizeof(buf), 0, &session.addr.sa, &session.size); if (len < 0) { printf("recvfrom"); return -1; } else { dtls_debug("got %d bytes from port %d\n", len, ntohs(session.addr.sin.sin_port)); if (sizeof(buf) < len) { dtls_warn("packet was truncated (%d bytes lost)\n", len - sizeof(buf)); } } return dtls_handle_message(ctx, &session, buf, len); } static void usage(const char *program, const char *version) { const char *p; p = strrchr(program, '/'); if (p) { program = ++p; } printf("%s v%s -- DTLS server implementation\n" "(c) 2011-2014 Olaf Bergmann \n\n" "usage: %s [-A address] [-p port] [-v num]\n" "\t-A address\t\tlisten on specified address (default is ::)\n" "\t-p port\t\tlisten on specified port (default is %d)\n" "\t-v num\t\tverbosity level (default: 3)\n", program, version, program, DEFAULT_PORT); } static dtls_handler_t cb = { .net_write = send_to_peer, .net_read = read_from_peer, .event = dtls_event_cb, #ifdef DTLS_PSK .get_psk_info = get_psk_info, #endif /* DTLS_PSK */ #ifdef DTLS_ECC .get_ecdsa_key = get_ecdsa_key, .verify_ecdsa_key = verify_ecdsa_key #endif /* DTLS_ECC */ }; int dtls_server_test(void) { dtls_context_t *the_context = NULL; log_t log_level = DTLS_LOG_WARN;//DTLS_LOG_DEBUG; fd_set rfds, wfds; struct timeval timeout; int fd, result; int on = 1; char ip[16]; struct sockaddr_in listen_addr; memset(&listen_addr, 0, sizeof(struct sockaddr_in)); /* fill extra field for 4.4BSD-based systems (see RFC 3493, section 3.4) */ #if defined(SIN6_LEN) || defined(HAVE_SOCKADDR_IN6_SIN6_LEN) listen_addr.sin6_len = sizeof(struct sockaddr_in6); #endif Get_IPAddress(0, ip); listen_addr.sin_family = AF_INET; listen_addr.sin_port = htons(DEFAULT_PORT); listen_addr.sin_addr.s_addr = inet_addr(ip);//htonl(INADDR_ANY); dtls_set_log_level(log_level); /* init socket and set it to non-blocking */ fd = socket(listen_addr.sin_family, SOCK_DGRAM, 0); if (fd < 0) { dtls_alert("socket: %s\n", strerror(errno)); return 0; } if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) { dtls_alert("setsockopt SO_REUSEADDR: %s\n", strerror(errno)); } #if 0 flags = fcntl(fd, F_GETFL, 0); if (flags < 0 || fcntl(fd, F_SETFL, flags | O_NONBLOCK) < 0) { dtls_alert("fcntl: %s\n", strerror(errno)); goto error; } #endif on = 1; #if LWIP_IPV6 #ifdef IPV6_RECVPKTINFO if (setsockopt(fd, IPPROTO_IPV6, IPV6_RECVPKTINFO, &on, sizeof(on)) < 0) { #else /* IPV6_RECVPKTINFO */ if (setsockopt(fd, IPPROTO_IPV6, IPV6_PKTINFO, &on, sizeof(on)) < 0) { #endif /* IPV6_RECVPKTINFO */ dtls_alert("setsockopt IPV6_PKTINFO: %s\n", strerror(errno)); } #endif if (bind(fd, (struct sockaddr *)&listen_addr, sizeof(listen_addr)) < 0) { dtls_alert("bind: %s\n", strerror(errno)); goto error; } dtls_init(); the_context = dtls_new_context(&fd); dtls_set_handler(the_context, &cb); while (1) { FD_ZERO(&rfds); FD_ZERO(&wfds); FD_SET(fd, &rfds); /* FD_SET(fd, &wfds); */ timeout.tv_sec = 5; timeout.tv_usec = 0; result = select(fd + 1, &rfds, &wfds, 0, &timeout); if (result < 0) { /* error */ if (errno != EINTR) { printf("select"); } } else if (result == 0) { /* timeout */ } else { /* ok */ if (FD_ISSET(fd, &wfds)) ; else if (FD_ISSET(fd, &rfds)) { dtls_handle_read(the_context); } } } error: dtls_free_context(the_context); return (0); }