Merge pull request #432 from JacobBarthelmeh/DTLS-MultiCore

import / export of peer connection information
This commit is contained in:
toddouska 2016-06-06 08:51:24 -07:00
commit 38d5480256
4 changed files with 271 additions and 15 deletions

View File

@ -999,6 +999,90 @@ static int dtls_export_load(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
return idx;
}
static int ExportPeerInfo(WOLFSSL* ssl, byte* exp, word32 len, byte ver)
{
int idx = 0;
int ipSz = DTLS_EXPORT_IP; /* start as max size */
int fam = 0;
word16 port = 0;
char ip[DTLS_EXPORT_IP];
if (ver != 1) {
WOLFSSL_MSG("Export version not supported");
return BAD_FUNC_ARG;
}
if (ssl == NULL || exp == NULL || len < sizeof(ip) + 3 * DTLS_EXPORT_LEN) {
return BAD_FUNC_ARG;
}
if (ssl->ctx->CBGetPeer == NULL) {
WOLFSSL_MSG("No get peer call back set");
return BAD_FUNC_ARG;
}
if (ssl->ctx->CBGetPeer(ssl, ip, &ipSz, &port, &fam) != SSL_SUCCESS) {
WOLFSSL_MSG("Get peer callback error");
return SOCKET_ERROR_E;
}
/* check that ipSz/fam is not negative or too large since user can set cb */
if (ipSz < 0 || ipSz > DTLS_EXPORT_IP || fam < 0) {
WOLFSSL_MSG("Bad ipSz or fam returned from get peer callback");
return SOCKET_ERROR_E;
}
c16toa((word16)fam, exp + idx); idx += DTLS_EXPORT_LEN;
c16toa((word16)ipSz, exp + idx); idx += DTLS_EXPORT_LEN;
XMEMCPY(exp + idx, ip, ipSz); idx += ipSz;
c16toa(port, exp + idx); idx += DTLS_EXPORT_LEN;
return idx;
}
static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver)
{
word16 idx = 0;
word16 ipSz;
word16 fam;
word16 port;
char ip[DTLS_EXPORT_IP];
if (ver != 1) {
WOLFSSL_MSG("Export version not supported");
return BAD_FUNC_ARG;
}
if (ssl == NULL || buf == NULL || len < 3 * DTLS_EXPORT_LEN) {
return BAD_FUNC_ARG;
}
/* import sin family */
ato16(buf + idx, &fam); idx += DTLS_EXPORT_LEN;
/* import ip address idx, and ipSz are unsigned but cast for enum */
ato16(buf + idx, &ipSz); idx += DTLS_EXPORT_LEN;
if (ipSz > sizeof(ip) || (word16)(idx + ipSz + DTLS_EXPORT_LEN) > len) {
return BUFFER_E;
}
XMEMSET(ip, 0, sizeof(ip));
XMEMCPY(ip, buf + idx, ipSz); idx += ipSz;
ip[ipSz] = '\0';
ato16(buf + idx, &port); idx += DTLS_EXPORT_LEN;
/* sanity check for a function to call, then use it to import peer info */
if (ssl->ctx->CBSetPeer == NULL) {
WOLFSSL_MSG("No set peer function");
return BAD_FUNC_ARG;
}
if (ssl->ctx->CBSetPeer(ssl, ip, ipSz, port, fam) != SSL_SUCCESS) {
WOLFSSL_MSG("Error setting peer info");
return SOCKET_ERROR_E;
}
return idx;
}
/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session
* buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
@ -1062,11 +1146,14 @@ int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz)
idx += ret;
/* export of dtls peer information */
c16toa((word16)ssl->buffers.dtlsCtx.peer.sz, buf + idx);
idx += DTLS_EXPORT_LEN;
XMEMCPY(buf + idx, ssl->buffers.dtlsCtx.peer.sa,
ssl->buffers.dtlsCtx.peer.sz);
idx += ssl->buffers.dtlsCtx.peer.sz;
if ((ret = ExportPeerInfo(ssl, buf + idx, sz - idx,
DTLS_EXPORT_VERSION)) < 0) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
return ret;
}
c16toa(ret, buf + idx - DTLS_EXPORT_LEN);
idx += ret;
/* place total length of exported buffer minus 2 bytes protocol/version */
c16toa((word16)(idx - DTLS_EXPORT_LEN), buf + DTLS_EXPORT_LEN);
@ -1172,7 +1259,7 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
WOLFSSL_MSG("Import CipherSpecs struct error");
return ret;
}
idx += length;
idx += ret;
/* perform sanity checks and extract DTLS peer info */
if (DTLS_EXPORT_LEN + idx > sz) {
@ -1180,20 +1267,15 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
return BUFFER_E;
}
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
ssl->buffers.dtlsCtx.peer.sz = length;
if (idx + ssl->buffers.dtlsCtx.peer.sz > sz) {
if (idx + length > sz) {
WOLFSSL_MSG("Import DTLS peer info error");
return BUFFER_E;
}
/* peer sa is free'd in SSL_ResourceFree */
if ((ret = wolfSSL_dtls_set_peer(ssl, buf + idx,
ssl->buffers.dtlsCtx.peer.sz)) != SSL_SUCCESS) {
WOLFSSL_MSG("Import DTLS peer info error");
if ((ret = ImportPeerInfo(ssl, buf + idx, length, version)) < 0) {
WOLFSSL_MSG("Import Peer Addr error");
return ret;
}
idx += ssl->buffers.dtlsCtx.peer.sz;
idx += ret;
SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
@ -1319,6 +1401,10 @@ int InitSSL_Ctx(WOLFSSL_CTX* ctx, WOLFSSL_METHOD* method)
ctx->CBIORecv = EmbedReceiveFrom;
ctx->CBIOSend = EmbedSendTo;
}
#ifdef WOLFSSL_SESSION_EXPORT
ctx->CBGetPeer = EmbedGetPeer;
ctx->CBSetPeer = EmbedSetPeer;
#endif
#endif
#endif /* WOLFSSL_USER_IO */

150
src/io.c
View File

@ -550,6 +550,142 @@ int EmbedGenerateCookie(WOLFSSL* ssl, byte *buf, int sz, void *ctx)
return sz;
}
#ifdef WOLFSSL_SESSION_EXPORT
#ifndef XINET_NTOP
#define XINET_NTOP(a,b,c,d) inet_ntop((a),(b),(c),(d))
#endif
#ifndef XINET_PTON
#define XINET_PTON(a,b,c) inet_pton((a),(b),(c))
#endif
#ifndef XHTONS
#define XHTONS(a) htons((a))
#endif
#ifndef XNTOHS
#define XNTOHS(a) ntohs((a))
#endif
#ifndef WOLFSSL_IP4
#define WOLFSSL_IP4 AF_INET
#endif
#ifndef WOLFSSL_IP6
#define WOLFSSL_IP6 AF_INET6
#endif
typedef struct sockaddr_storage SOCKADDR_S;
typedef struct sockaddr_in SOCKADDR_IN;
typedef struct sockaddr_in6 SOCKADDR_IN6;
/* get the peer information in human readable form (ip, port, family)
* default function assumes BSD sockets
* can be overriden with wolfSSL_CTX_SetIOGetPeer
*/
int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
unsigned short* port, int* fam)
{
SOCKADDR_S peer;
word32 peerSz;
int ret;
if (ssl == NULL || ip == NULL || ipSz == NULL ||
port == NULL || fam == NULL) {
return BAD_FUNC_ARG;
}
/* get peer information stored in ssl struct */
peerSz = sizeof(SOCKADDR_S);
if ((ret = wolfSSL_dtls_get_peer(ssl, (void*)&peer, &peerSz))
!= SSL_SUCCESS) {
return ret;
}
/* extract family, ip, and port */
*fam = ((SOCKADDR_S*)&peer)->ss_family;
switch (*fam) {
case WOLFSSL_IP4:
if (XINET_NTOP(*fam, &(((SOCKADDR_IN*)&peer)->sin_addr),
ip, *ipSz) == NULL) {
WOLFSSL_MSG("XINET_NTOP error");
return SOCKET_ERROR_E;
}
*port = XNTOHS(((SOCKADDR_IN*)&peer)->sin_port);
break;
case WOLFSSL_IP6:
if (XINET_NTOP(*fam, &(((SOCKADDR_IN6*)&peer)->sin6_addr),
ip, *ipSz) == NULL) {
WOLFSSL_MSG("XINET_NTOP error");
return SOCKET_ERROR_E;
}
*port = XNTOHS(((SOCKADDR_IN6*)&peer)->sin6_port);
break;
default:
WOLFSSL_MSG("Unknown family type");
return SOCKET_ERROR_E;
}
ip[*ipSz - 1] = '\0'; /* make sure has terminator */
*ipSz = (word16)XSTRLEN(ip);
return SSL_SUCCESS;
}
/* set the peer information in human readable form (ip, port, family)
* default function assumes BSD sockets
* can be overriden with wolfSSL_CTX_SetIOSetPeer
*/
int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
unsigned short port, int fam)
{
int ret;
SOCKADDR_S addr;
/* sanity checks on arguments */
if (ssl == NULL || ip == NULL || ipSz < 0 || ipSz > DTLS_EXPORT_IP) {
return BAD_FUNC_ARG;
}
addr.ss_family = fam;
switch (addr.ss_family) {
case WOLFSSL_IP4:
if (XINET_PTON(addr.ss_family, ip,
&(((SOCKADDR_IN*)&addr)->sin_addr)) <= 0) {
WOLFSSL_MSG("XINET_PTON error");
return SOCKET_ERROR_E;
}
((SOCKADDR_IN*)&addr)->sin_port = XHTONS(port);
/* peer sa is free'd in SSL_ResourceFree */
if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN*)&addr,
sizeof(SOCKADDR_IN)))!= SSL_SUCCESS) {
WOLFSSL_MSG("Import DTLS peer info error");
return ret;
}
break;
case WOLFSSL_IP6:
if (XINET_PTON(addr.ss_family, ip,
&(((SOCKADDR_IN6*)&addr)->sin6_addr)) <= 0) {
WOLFSSL_MSG("XINET_PTON error");
return SOCKET_ERROR_E;
}
((SOCKADDR_IN6*)&addr)->sin6_port = XHTONS(port);
/* peer sa is free'd in SSL_ResourceFree */
if ((ret = wolfSSL_dtls_set_peer(ssl, (SOCKADDR_IN6*)&addr,
sizeof(SOCKADDR_IN6)))!= SSL_SUCCESS) {
WOLFSSL_MSG("Import DTLS peer info error");
return ret;
}
break;
default:
WOLFSSL_MSG("Unknown address family");
return BUFFER_E;
}
return SSL_SUCCESS;
}
#endif /* WOLFSSL_SESSION_EXPORT */
#endif /* WOLFSSL_DTLS */
#ifdef HAVE_OCSP
@ -1066,6 +1202,20 @@ WOLFSSL_API void* wolfSSL_GetCookieCtx(WOLFSSL* ssl)
return NULL;
}
#ifdef WOLFSSL_SESSION_EXPORT
WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX* ctx, CallbackGetPeer cb)
{
ctx->CBGetPeer = cb;
}
WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX* ctx, CallbackSetPeer cb)
{
ctx->CBSetPeer = cb;
}
#endif /* WOLFSSL_SESSION_EXPORT */
#endif /* WOLFSSL_DTLS */

View File

@ -957,6 +957,7 @@ enum Misc {
DTLS_EXPORT_MIN_KEY_SZ = 75, /* min amount of bytes used from Keys */
DTLS_EXPORT_SPC_SZ = 16, /* amount of bytes used from CipherSpecs */
DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */
DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */
MAX_EXPORT_BUFFER = 500, /* max size of buffer for exporting */
FINISHED_LABEL_SZ = 15, /* TLS finished label size */
TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
@ -1959,7 +1960,11 @@ struct WOLFSSL_CTX {
#ifdef WOLFSSL_DTLS
CallbackGenCookie CBIOCookie; /* gen cookie callback */
wc_dtls_export dtls_export; /* export function for DTLS session */
#ifdef WOLFSSL_SESSION_EXPORT
CallbackGetPeer CBGetPeer;
CallbackSetPeer CBSetPeer;
#endif
#endif /* WOLFSSL_DTLS */
VerifyCallback verifyCallback; /* cert verification callback */
word32 timeout; /* session timeout */
#ifdef HAVE_ECC

View File

@ -1066,7 +1066,6 @@ WOLFSSL_API void* wolfSSL_GetIOWriteCtx(WOLFSSL* ssl);
WOLFSSL_API void wolfSSL_SetIOReadFlags( WOLFSSL* ssl, int flags);
WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
#ifndef WOLFSSL_USER_IO
/* default IO callbacks */
WOLFSSL_API int EmbedReceive(WOLFSSL* ssl, char* buf, int sz, void* ctx);
@ -1083,6 +1082,22 @@ WOLFSSL_API void wolfSSL_SetIOWriteFlags(WOLFSSL* ssl, int flags);
WOLFSSL_API int EmbedSendTo(WOLFSSL* ssl, char* buf, int sz, void* ctx);
WOLFSSL_API int EmbedGenerateCookie(WOLFSSL* ssl, unsigned char* buf,
int sz, void*);
#ifdef WOLFSSL_SESSION_EXPORT
WOLFSSL_API int EmbedGetPeer(WOLFSSL* ssl, char* ip, int* ipSz,
unsigned short* port, int* fam);
WOLFSSL_API int EmbedSetPeer(WOLFSSL* ssl, char* ip, int ipSz,
unsigned short port, int fam);
typedef int (*CallbackGetPeer)(WOLFSSL* ssl, char* ip, int* ipSz,
unsigned short* port, int* fam);
typedef int (*CallbackSetPeer)(WOLFSSL* ssl, char* ip, int ipSz,
unsigned short port, int fam);
WOLFSSL_API void wolfSSL_CTX_SetIOGetPeer(WOLFSSL_CTX*,
CallbackGetPeer);
WOLFSSL_API void wolfSSL_CTX_SetIOSetPeer(WOLFSSL_CTX*,
CallbackSetPeer);
#endif /* WOLFSSL_SESSION_EXPORT */
#endif /* WOLFSSL_DTLS */
#endif /* WOLFSSL_USER_IO */