#ifndef _DTLS_DTLS_H_
#define _DTLS_DTLS_H_
#include <stdint.h>
#include "tinydtls.h"
#include "state.h"
#include "peer.h"
#include "uthash.h"
#include "alert.h"
#include "crypto.h"
#include "hmac.h"
#include "global.h"
#include "dtls_time.h"
#ifndef DTLSv12
#define DTLS_VERSION 0xfeff
#else
#define DTLS_VERSION 0xfefd
#endif
typedef enum dtls_credentials_type_t {
DTLS_PSK_HINT, DTLS_PSK_IDENTITY, DTLS_PSK_KEY
} dtls_credentials_type_t;
typedef struct dtls_ecdsa_key_t {
dtls_ecdh_curve curve;
const unsigned char *priv_key;
const unsigned char *pub_key_x;
const unsigned char *pub_key_y;
} dtls_ecdsa_key_t;
#define DTLS_COOKIE_SECRET_LENGTH 12
struct dtls_context_t;
typedef struct {
int (*write)(struct dtls_context_t *ctx,
session_t *session, uint8 *buf, size_t len);
int (*read)(struct dtls_context_t *ctx,
session_t *session, uint8 *buf, size_t len);
int (*event)(struct dtls_context_t *ctx, session_t *session,
dtls_alert_level_t level, unsigned short code);
void (*get_user_parameters)(struct dtls_context_t *ctx, session_t *session,
dtls_user_parameters_t *parameters);
#ifdef DTLS_PSK
int (*get_psk_info)(struct dtls_context_t *ctx,
const session_t *session,
dtls_credentials_type_t type,
const unsigned char *desc, size_t desc_len,
unsigned char *result, size_t result_length);
#endif
#ifdef DTLS_ECC
int (*get_ecdsa_key)(struct dtls_context_t *ctx,
const session_t *session,
const dtls_ecdsa_key_t **result);
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);
#endif
} dtls_handler_t;
struct netq_t;
typedef struct dtls_context_t {
unsigned char cookie_secret[DTLS_COOKIE_SECRET_LENGTH];
clock_time_t cookie_secret_age;
dtls_peer_t *peers;
#ifdef WITH_CONTIKI
struct etimer retransmit_timer;
#endif
struct netq_t *sendqueue;
void *app;
dtls_handler_t *h;
} dtls_context_t;
void dtls_init(void);
dtls_context_t *dtls_new_context(void *app_data);
void dtls_free_context(dtls_context_t *ctx);
#define dtls_set_app_data(CTX,DATA) ((CTX)->app = (DATA))
#define dtls_get_app_data(CTX) ((CTX)->app)
static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
ctx->h = h;
}
int dtls_connect(dtls_context_t *ctx, const session_t *dst);
int dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer);
int dtls_close(dtls_context_t *ctx, const session_t *remote);
int dtls_writev(struct dtls_context_t *ctx,
session_t *session, uint8 *buf_array[],
size_t buf_len_array[], size_t buf_array_len);
int dtls_write(struct dtls_context_t *ctx, session_t *session,
uint8 *buf, size_t len);
void dtls_check_retransmit(dtls_context_t *context, clock_time_t *next);
#define DTLS_COOKIE_LENGTH 16
#define DTLS_CT_CHANGE_CIPHER_SPEC 20
#define DTLS_CT_ALERT 21
#define DTLS_CT_HANDSHAKE 22
#define DTLS_CT_APPLICATION_DATA 23
#ifdef __GNUC__
#define PACK( __Declaration__ ) __Declaration__ __attribute__((__packed__))
#elif defined(_MSC_VER)
#define PACK( __Declaration__ ) __pragma( pack(push, 1) ) __Declaration__ __pragma( pack(pop))
#else
#error "Structure packing is not available for the used compiler."
#endif
PACK(typedef struct) {
uint8 content_type;
uint16 version;
uint16 epoch;
uint48 sequence_number;
uint16 length;
} dtls_record_header_t;
#define DTLS_HT_HELLO_REQUEST 0
#define DTLS_HT_CLIENT_HELLO 1
#define DTLS_HT_SERVER_HELLO 2
#define DTLS_HT_HELLO_VERIFY_REQUEST 3
#define DTLS_HT_CERTIFICATE 11
#define DTLS_HT_SERVER_KEY_EXCHANGE 12
#define DTLS_HT_CERTIFICATE_REQUEST 13
#define DTLS_HT_SERVER_HELLO_DONE 14
#define DTLS_HT_CERTIFICATE_VERIFY 15
#define DTLS_HT_CLIENT_KEY_EXCHANGE 16
#define DTLS_HT_FINISHED 20
#define DTLS_HT_NO_OPTIONAL_MESSAGE -1
PACK(typedef struct) {
uint8 msg_type;
uint24 length;
uint16 message_seq;
uint24 fragment_offset;
uint24 fragment_length;
} dtls_handshake_header_t;
PACK(typedef struct) {
uint16 version;
uint32 gmt_random;
unsigned char random[28];
} dtls_client_hello_t;
PACK(typedef struct) {
uint16 version;
uint8 cookie_length;
uint8 cookie[];
} dtls_hello_verify_t;
#if 0
int dtls_record_read(dtls_state_t *state, uint8 *msg, int msglen);
#endif
int dtls_handle_message(dtls_context_t *ctx, session_t *session,
uint8 *msg, int msglen);
dtls_peer_t *dtls_get_peer(const dtls_context_t *context,
const session_t *session);
void dtls_reset_peer(dtls_context_t *context, dtls_peer_t *peer);
#endif