Skip to content

Commit

Permalink
Merge commit '982cbf5ffcc0266c4a50f31bcf1377e1ab9610c8' into ecdh-merge
Browse files Browse the repository at this point in the history
Conflicts:
	Makefile.in
	dtls.c
	dtls.h
  • Loading branch information
hauke committed Jul 29, 2013
2 parents d149bca + 982cbf5 commit 7a4dc27
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 135 deletions.
4 changes: 2 additions & 2 deletions Makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,13 @@ package = @PACKAGE_TARNAME@-@PACKAGE_VERSION@
install := cp

# files and flags
SOURCES:= dtls.c crypto.c ccm.c hmac.c netq.c
SOURCES:= dtls.c crypto.c ccm.c hmac.c netq.c peer.c
ifneq ("@NDEBUG@", "1")
SOURCES += debug.c
endif
OBJECTS:= $(patsubst %.c, %.o, $(SOURCES)) aes/rijndael.o ecc/ecc.o @OPT_OBJS@
HEADERS:=dtls.h hmac.h debug.h config.h uthash.h numeric.h crypto.h global.h ccm.h \
netq.h t_list.h alert.h utlist.h prng.h
netq.h t_list.h alert.h utlist.h prng.h peer.h state.h
CFLAGS:=-Wall -pedantic -std=c99 @CFLAGS@
CPPFLAGS:=@CPPFLAGS@ -DDTLS_CHECK_CONTENTTYPE
SUBDIRS:=tests doc sha2 aes ecc
Expand Down
122 changes: 40 additions & 82 deletions dtls.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,40 +138,11 @@ static const unsigned char cert_asn1_header[] = {

static dtls_context_t the_dtls_context;

#ifndef WITH_CONTIKI
static inline dtls_peer_t *
dtls_malloc_peer() {
return (dtls_peer_t *)malloc(sizeof(dtls_peer_t));
}

static inline void
dtls_free_peer(dtls_peer_t *peer) {
free(peer);
}
#else /* WITH_CONTIKI */
PROCESS(dtls_retransmit_process, "DTLS retransmit process");

#include "memb.h"
MEMB(peer_storage, dtls_peer_t, DTLS_PEER_MAX);

static inline dtls_peer_t *
dtls_malloc_peer() {
return memb_alloc(&peer_storage);
}
static inline void
dtls_free_peer(dtls_peer_t *peer) {
memb_free(&peer_storage, peer);
}
#endif /* WITH_CONTIKI */

void
dtls_init() {
netq_init();
crypto_init();

#ifdef WITH_CONTIKI
memb_init(&peer_storage);
#endif /* WITH_CONTIKI */
peer_init();
}

/* Calls cb_alert() with given arguments if defined, otherwise an
Expand Down Expand Up @@ -205,8 +176,8 @@ static int dtls_send(dtls_context_t *ctx, dtls_peer_t *peer, unsigned char type,
*/
static void dtls_stop_retransmission(dtls_context_t *context, dtls_peer_t *peer);

static dtls_peer_t *
dtls_get_peer(struct dtls_context_t *ctx, const session_t *session) {
dtls_peer_t *
dtls_get_peer(const dtls_context_t *ctx, const session_t *session) {
dtls_peer_t *p = NULL;

#ifndef WITH_CONTIKI
Expand All @@ -220,6 +191,15 @@ dtls_get_peer(struct dtls_context_t *ctx, const session_t *session) {
return p;
}

static void
dtls_add_peer(dtls_context_t *ctx, dtls_peer_t *peer) {
#ifndef WITH_CONTIKI
HASH_ADD_PEER(ctx->peers, session, peer);
#else /* WITH_CONTIKI */
list_add(ctx->peers, peer);
#endif /* WITH_CONTIKI */
}

int
dtls_write(struct dtls_context_t *ctx,
session_t *dst, uint8 *buf, size_t len) {
Expand Down Expand Up @@ -895,32 +875,6 @@ check_client_keyexchange(dtls_context_t *ctx,
return 0;
}

static dtls_peer_t *
dtls_new_peer(dtls_context_t *ctx,
const session_t *session) {
dtls_peer_t *peer;

peer = dtls_malloc_peer();
if (peer) {
memset(peer, 0, sizeof(dtls_peer_t));
memcpy(&peer->session, session, sizeof(session_t));

dtls_dsrv_log_addr(LOG_DEBUG, "dtls_new_peer", session);
/* initially allow the NULL cipher */
peer->security_params.cipher = TLS_NULL_WITH_NULL_NULL;
peer->security_params.compression = TLS_COMPRESSION_NULL;

/* initialize the handshake hash wrt. the hard-coded DTLS version */
debug("DTLSv12: initialize HASH_SHA256\n");
/* TLS 1.2: PRF(secret, label, seed) = P_<hash>(secret, label + seed) */
/* FIXME: we use the default SHA256 here, might need to support other
hash functions as well */
dtls_hash_init(&peer->hs_state.hs_hash);
}

return peer;
}

static inline void
update_hs_hash(dtls_peer_t *peer, uint8 *data, size_t length) {
dtls_dsrv_hexdump_log(LOG_DEBUG, "add MAC data", data, length, 0);
Expand Down Expand Up @@ -2942,7 +2896,7 @@ handle_handshake(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
/* msg contains a Client Hello with a valid cookie, so we can
* safely create the server state machine and continue with
* the handshake. */
peer = dtls_new_peer(ctx, session);
peer = dtls_new_peer(session);
if (!peer) {
dsrv_log(LOG_ALERT, "cannot create peer\n");
return dtls_alert_fatal_create(DTLS_ALERT_INTERNAL_ERROR);
Expand All @@ -2953,12 +2907,7 @@ handle_handshake(dtls_context_t *ctx, dtls_peer_t *peer, session_t *session,
* record with sequence number 0 is a stateless Hello Verify Request.
*/
peer->rseq[5] = 1;

#ifndef WITH_CONTIKI
HASH_ADD_PEER(ctx->peers, session, peer);
#else /* WITH_CONTIKI */
list_add(ctx->peers, peer);
#endif /* WITH_CONTIKI */
dtls_add_peer(ctx, peer);
}

clear_hs_hash(peer);
Expand Down Expand Up @@ -3178,6 +3127,7 @@ dtls_handle_message(dtls_context_t *ctx,
(without MAC and padding) */
int err;

/* check if we have DTLS state for addr/port/ifindex */
peer = dtls_get_peer(ctx, session);

if (!peer) {
Expand Down Expand Up @@ -3347,34 +3297,25 @@ void dtls_free_context(dtls_context_t *ctx) {
}

int
dtls_connect(dtls_context_t *ctx, const session_t *dst) {
dtls_peer_t *peer;
dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer) {
int res;

peer = dtls_get_peer(ctx, dst);

if (peer) {
assert(peer);
if (!peer)
return -1;

/* check if the same peer is already in our list */
if (peer == dtls_get_peer(ctx, &peer->session)) {
debug("found peer, try to re-connect\n");
/* FIXME: send HelloRequest if we are server,
ClientHello with good cookie if client */
return 0;
}

peer = dtls_new_peer(ctx, dst);

if (!peer) {
dsrv_log(LOG_CRIT, "cannot create new peer\n");
return -1;
}

/* set peer role to server: */
peer->role = DTLS_CLIENT;

#ifndef WITH_CONTIKI
HASH_ADD_PEER(ctx->peers, session, peer);
#else /* WITH_CONTIKI */
list_add(ctx->peers, peer);
#endif /* WITH_CONTIKI */
dtls_add_peer(ctx, peer);

/* send ClientHello with empty Cookie */
res = dtls_send_client_hello(ctx, peer, NULL, 0);
Expand All @@ -3386,6 +3327,23 @@ dtls_connect(dtls_context_t *ctx, const session_t *dst) {
return res;
}

int
dtls_connect(dtls_context_t *ctx, const session_t *dst) {
dtls_peer_t *peer;

peer = dtls_get_peer(ctx, dst);

if (!peer)
peer = dtls_new_peer(dst);

if (!peer) {
dsrv_log(LOG_CRIT, "cannot create new peer\n");
return -1;
}

return dtls_connect_peer(ctx, peer);
}

static void
dtls_retransmit(dtls_context_t *context, netq_t *node) {
if (!context || !node)
Expand Down
81 changes: 30 additions & 51 deletions dtls.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* dtls -- a very basic DTLS implementation
*
* Copyright (C) 2011--2012 Olaf Bergmann <[email protected]>
* Copyright (C) 2011--2013 Olaf Bergmann <[email protected]>
* Copyright (C) 2013 Hauke Mehrtens <[email protected]>
*
* Permission is hereby granted, free of charge, to any person
Expand Down Expand Up @@ -33,7 +33,10 @@
#define _DTLS_H_

#include <stdint.h>
#include "config.h"

#include "t_list.h"
#include "state.h"
#include "peer.h"

#ifndef WITH_CONTIKI
#include "uthash.h"
Expand All @@ -51,55 +54,6 @@
#define DTLS_VERSION 0xfefd /* DTLS v1.2 */
#endif

typedef enum {
DTLS_STATE_INIT = 0, DTLS_STATE_WAIT_CLIENTHELLO, DTLS_STATE_WAIT_CLIENTCERTIFICATE,
DTLS_STATE_WAIT_CLIENTKEYEXCHANGE, DTLS_STATE_WAIT_CERTIFICATEVERIFY,
DTLS_STATE_WAIT_CLIENTCHANGECIPHERSPEC,
DTLS_STATE_WAIT_FINISHED, DTLS_STATE_FINISHED,
/* client states */
DTLS_STATE_CLIENTHELLO, DTLS_STATE_WAIT_SERVERCERTIFICATE, DTLS_STATE_WAIT_SERVERKEYEXCHANGE,
DTLS_STATE_WAIT_SERVERHELLODONE, DTLS_STATE_WAIT_SERVERFINISHED,

DTLS_STATE_CONNECTED,
DTLS_STATE_CLOSING,
DTLS_STATE_CLOSED,
} dtls_state_t;

typedef struct {
uint24 mseq; /**< handshake message sequence number counter */

/** pending config that is updated during handshake */
/* FIXME: dtls_security_parameters_t pending_config; */

/* temporary storage for the final handshake hash */
dtls_hash_ctx hs_hash;
} dtls_hs_state_t;

typedef enum { DTLS_CLIENT=0, DTLS_SERVER } dtls_peer_type;

/**
* Holds security parameters, local state and the transport address
* for each peer. */
typedef struct dtls_peer_t {
#ifndef WITH_CONTIKI
UT_hash_handle hh;
#else /* WITH_CONTIKI */
struct dtls_peer_t *next;
#endif /* WITH_CONTIKI */

session_t session; /**< peer address and local interface */

dtls_peer_type role; /**< denotes if this host is DTLS_CLIENT or DTLS_SERVER */
dtls_state_t state; /**< DTLS engine state */
uint16 epoch; /**< counter for cipher state changes*/
uint48 rseq; /**< sequence number of last record sent */

dtls_hs_state_t hs_state; /**< handshake protocol status */

dtls_security_parameters_t security_params;
dtls_handshake_parameters_t handshake_params;
} dtls_peer_t;

typedef struct dtls_psk_key_t {
unsigned char *id; /**< psk identity */
size_t id_length; /**< length of psk identity */
Expand Down Expand Up @@ -311,6 +265,18 @@ static inline void dtls_set_handler(dtls_context_t *ctx, dtls_handler_t *h) {
*/
int dtls_connect(dtls_context_t *ctx, const session_t *dst);

/**
* Establishes a DTLS channel with the specified remote peer.
* This function returns @c 0 if that channel already exists, a value
* greater than zero when a new ClientHello message was sent, and
* a value less than zero on error.
*
* @param ctx The DTLS context to use.
* @param peer The peer object that describes the session.
* @return A value less than zero on error, greater or equal otherwise.
*/
int dtls_connect_peer(dtls_context_t *ctx, dtls_peer_t *peer);

/**
* Closes the DTLS connection associated with @p remote. This function
* returns zero on success, and a value less than zero on error.
Expand Down Expand Up @@ -416,6 +382,19 @@ int dtls_record_read(dtls_state_t *state, uint8 *msg, int msglen);
int dtls_handle_message(dtls_context_t *ctx, session_t *session,
uint8 *msg, int msglen);

/**
* Check if @p session is associated with a peer object in @p context.
* This function returns a pointer to the peer if found, NULL otherwise.
*
* @param context The DTLS context to search.
* @param session The remote address and local interface
* @return A pointer to the peer associated with @p session or NULL if
* none exists.
*/
dtls_peer_t *dtls_get_peer(const dtls_context_t *context,
const session_t *session);


#endif /* _DTLS_H_ */

/**
Expand Down
Loading

0 comments on commit 7a4dc27

Please sign in to comment.