add public wolfSSL_dtls_export and api tests

This commit is contained in:
Jacob Barthelmeh
2016-05-14 12:49:09 -06:00
parent 3897f78073
commit c8576566cc
5 changed files with 198 additions and 61 deletions

View File

@@ -1001,16 +1001,16 @@ static int dtls_export_load(byte* exp, word32 len, byte ver, WOLFSSL* ssl)
* buf is used to hold the serialized WOLFSSL struct and sz is the size of buf
* passed in.
* On success returns the size of serialized session.*/
int wolfSSL_dtls_export(byte* buf, word32 sz, WOLFSSL* ssl)
int wolfSSL_dtls_export_internal(byte* buf, word32 sz, WOLFSSL* ssl)
{
int ret;
word32 idx = 0;
word32 totalLen = 0;
WOLFSSL_ENTER("wolfSSL_dtls_export");
WOLFSSL_ENTER("wolfSSL_dtls_export_internal");
if (buf == NULL || ssl == NULL) {
WOLFSSL_LEAVE("wolfSSL_dtls_export", BAD_FUNC_ARG);
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BAD_FUNC_ARG);
return BAD_FUNC_ARG;
}
@@ -1022,7 +1022,7 @@ int wolfSSL_dtls_export(byte* buf, word32 sz, WOLFSSL* ssl)
totalLen += DTLS_EXPORT_LEN + ssl->buffers.dtlsCtx.peer.sz;
if (totalLen > sz) {
WOLFSSL_LEAVE("wolfSSL_dtls_export", BUFFER_E);
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", BUFFER_E);
return BUFFER_E;
}
@@ -1035,16 +1035,16 @@ int wolfSSL_dtls_export(byte* buf, word32 sz, WOLFSSL* ssl)
c16toa((word16)DTLS_EXPORT_OPT_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
if ((ret = dtls_export_new(buf + idx, sz - idx, DTLS_EXPORT_VERSION,
ssl)) < 0) {
WOLFSSL_LEAVE("wolfSSL_dtls_export", ret);
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
return ret;
}
idx += DTLS_EXPORT_OPT_SZ;
idx += ret;
/* export keys struct and dtls state -- variable length stored in ret */
idx += DTLS_EXPORT_LEN; /* leave room for length */
if ((ret = ExportKeyState(buf + idx, sz - idx,
DTLS_EXPORT_VERSION, ssl)) < 0) {
WOLFSSL_LEAVE("wolfSSL_dtls_export", ret);
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
return ret;
}
c16toa((word16)ret, buf + idx - DTLS_EXPORT_LEN); idx += ret;
@@ -1053,10 +1053,10 @@ int wolfSSL_dtls_export(byte* buf, word32 sz, WOLFSSL* ssl)
c16toa((word16)DTLS_EXPORT_SPC_SZ, buf + idx); idx += DTLS_EXPORT_LEN;
if ((ret = ExportCipherSpecState(buf + idx, sz - idx,
DTLS_EXPORT_VERSION, ssl)) < 0) {
WOLFSSL_LEAVE("wolfSSL_dtls_export", ret);
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", ret);
return ret;
}
idx += DTLS_EXPORT_SPC_SZ;
idx += ret;
/* export of dtls peer information */
c16toa((word16)ssl->buffers.dtlsCtx.peer.sz, buf + idx);
@@ -1079,7 +1079,7 @@ int wolfSSL_dtls_export(byte* buf, word32 sz, WOLFSSL* ssl)
}
#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
WOLFSSL_LEAVE("wolfSSL_dtls_export", idx);
WOLFSSL_LEAVE("wolfSSL_dtls_export_internal", idx);
return idx;
}
@@ -1090,7 +1090,7 @@ int wolfSSL_dtls_import_internal(byte* buf, word32 sz, WOLFSSL* ssl)
word32 idx = 0;
word16 length = 0;
int version;
int ret, i;
int ret;
WOLFSSL_ENTER("wolfSSL_dtls_import_internal");
/* check at least enough room for protocol and length */
@@ -1185,15 +1185,11 @@ int wolfSSL_dtls_import_internal(byte* buf, word32 sz, WOLFSSL* ssl)
}
/* peer sa is free'd in SSL_ResourceFree */
ssl->buffers.dtlsCtx.peer.sa = XMALLOC(ssl->buffers.dtlsCtx.peer.sz,
ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
if (ssl->buffers.dtlsCtx.peer.sa == NULL) {
if ((ret = wolfSSL_dtls_set_peer(ssl, buf + idx,
ssl->buffers.dtlsCtx.peer.sz)) != SSL_SUCCESS) {
WOLFSSL_MSG("Import DTLS peer info error");
return MEMORY_E;
return ret;
}
XMEMCPY(ssl->buffers.dtlsCtx.peer.sa, buf + idx,
ssl->buffers.dtlsCtx.peer.sz);
idx += ssl->buffers.dtlsCtx.peer.sz;
SetKeysSide(ssl, ENCRYPT_AND_DECRYPT_SIDE);
@@ -1205,17 +1201,9 @@ int wolfSSL_dtls_import_internal(byte* buf, word32 sz, WOLFSSL* ssl)
}
/* make sure is a valid suite used */
ret = MATCH_SUITE_ERROR;
for (i = 0; i < ssl->suites->suiteSz; i += 2) {
if (ssl->suites->suites[i] == ssl->options.cipherSuite0 &&
ssl->suites->suites[i+1] == ssl->options.cipherSuite) {
ret = 0;
break;
}
}
if (ret != 0) {
if (wolfSSL_get_cipher(ssl) == NULL) {
WOLFSSL_MSG("Can not match cipher suite imported");
return ret;
return MATCH_SUITE_ERROR;
}
/* do not allow stream ciphers with DTLS */

View File

@@ -200,6 +200,38 @@ int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func)
}
int wolfSSL_dtls_export(unsigned char* buf, unsigned int* sz, WOLFSSL* ssl)
{
int ret;
WOLFSSL_ENTER("wolfSSL_dtls_export");
if (ssl == NULL || sz == NULL) {
return BAD_FUNC_ARG;
}
if (buf == NULL) {
*sz = MAX_EXPORT_BUFFER;
return 0;
}
/* if not DTLS do nothing */
if (!ssl->options.dtls) {
WOLFSSL_MSG("Currently only DTLS export is supported");
return 0;
}
/* copy over keys, options, and dtls state struct */
ret = wolfSSL_dtls_export_internal(buf, *sz, ssl);
if (ret < 0) {
return ret;
}
return ret;
}
/* returns 0 on success */
int wolfSSL_send_session(WOLFSSL* ssl)
{
int ret;
@@ -221,31 +253,25 @@ int wolfSSL_send_session(WOLFSSL* ssl)
if (!ssl->options.dtls) {
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
WOLFSSL_MSG("Currently only DTLS export is supported");
return SSL_SUCCESS;
return 0;
}
if (ssl->dtls_export) {
/* copy over keys, options, and dtls state struct */
ret = wolfSSL_dtls_export(buf, bufSz, ssl);
if (ret < 0) {
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
/* if no error ret has size of buffer */
ret = ssl->dtls_export(ssl, buf, ret, NULL);
if (ret != SSL_SUCCESS) {
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
return ret;
}
/* copy over keys, options, and dtls state struct */
ret = wolfSSL_dtls_export_internal(buf, bufSz, ssl);
if (ret < 0) {
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
return SSL_SUCCESS;
return ret;
}
else {
/* if no error ret has size of buffer */
ret = ssl->dtls_export(ssl, buf, ret, NULL);
if (ret != SSL_SUCCESS) {
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
return SSL_FAILURE;
return ret;
}
XFREE(buf, ssl->heap, DYNAMIC_TYPE_TMP_BUFFER);
return 0;
}
#endif /* WOLFSSL_DTLS */
#endif /* WOLFSSL_SESSION_EXPORT */
@@ -6641,7 +6667,6 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#ifdef WOLFSSL_DTLS
else {
ssl->options.dtlsHsRetain = 1;
}
#endif /* WOLFSSL_DTLS */
@@ -6931,8 +6956,13 @@ int wolfSSL_DTLS_SetCookieSecret(WOLFSSL* ssl,
#endif /* WOLFSSL_DTLS */
#ifdef WOLFSSL_SESSION_EXPORT
WOLFSSL_MSG("sending session");
wolfSSL_send_session(ssl);
if (ssl->dtls_export) {
if ((ssl->error = wolfSSL_send_session(ssl)) != 0) {
WOLFSSL_MSG("Export DTLS session error");
WOLFSSL_ERROR(ssl->error);
return SSL_FATAL_ERROR;
}
}
#endif
WOLFSSL_LEAVE("SSL_accept()", SSL_SUCCESS);

View File

@@ -493,6 +493,34 @@ static void test_wolfSSL_SetTmpDH_buffer(void)
/* helper functions */
#ifdef HAVE_IO_TESTS_DEPENDENCIES
#ifdef WOLFSSL_SESSION_EXPORT
/* set up function for sending session information */
static int test_export(WOLFSSL* inSsl, byte* buf, word32 sz, void* userCtx)
{
WOLFSSL_CTX* ctx;
WOLFSSL* ssl;
AssertNotNull(inSsl);
AssertNotNull(buf);
AssertIntNE(0, sz);
/* Set ctx to DTLS 1.2 */
ctx = wolfSSL_CTX_new(wolfDTLSv1_2_server_method());
AssertNotNull(ctx);
ssl = wolfSSL_new(ctx);
AssertNotNull(ssl);
AssertIntGE(wolfSSL_dtls_import(ssl, buf, sz), 0);
wolfSSL_free(ssl);
wolfSSL_CTX_free(ctx);
(void)userCtx;
return SSL_SUCCESS;
}
#endif
static THREAD_RETURN WOLFSSL_THREAD test_server_nofail(void* args)
{
SOCKET_T sockfd = 0;
@@ -711,8 +739,8 @@ done2:
return;
}
/* SNI / ALPN helper functions */
#if defined(HAVE_SNI) || defined(HAVE_ALPN)
/* SNI / ALPN / session export helper functions */
#if defined(HAVE_SNI) || defined(HAVE_ALPN) || defined(WOLFSSL_SESSION_EXPORT)
static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
{
@@ -752,6 +780,9 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
#ifdef OPENSSL_EXTRA
wolfSSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
#endif
#ifdef WOLFSSL_SESSION_EXPORT
AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_dtls_set_export(ctx, test_export));
#endif
AssertIntEQ(SSL_SUCCESS, wolfSSL_CTX_load_verify_locations(ctx, cliCert, 0));
@@ -766,9 +797,21 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
callbacks->ctx_ready(ctx);
ssl = wolfSSL_new(ctx);
if (wolfSSL_dtls(ssl)) {
SOCKADDR_IN_T cliAddr;
socklen_t cliLen;
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 1);
CloseSocket(sfd);
cliLen = sizeof(cliAddr);
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 1, 0, 0);
idx = (int)recvfrom(sfd, input, sizeof(input), MSG_PEEK,
(struct sockaddr*)&cliAddr, &cliLen);
AssertIntGT(idx, 0);
wolfSSL_dtls_set_peer(ssl, &cliAddr, cliLen);
}
else {
tcp_accept(&sfd, &cfd, (func_args*)args, port, 0, 0, 0, 1);
CloseSocket(sfd);
}
AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, cfd));
@@ -796,6 +839,20 @@ static THREAD_RETURN WOLFSSL_THREAD run_wolfssl_server(void* args)
}
AssertIntEQ(len, wolfSSL_write(ssl, msg, len));
#ifdef WOLFSSL_SESSION_EXPORT
if (wolfSSL_dtls(ssl)) {
byte* import;
word32 sz;
wolfSSL_dtls_export(NULL, &sz, ssl);
import = (byte*)XMALLOC(sz, NULL, DYNAMIC_TYPE_TMP_BUFFER);
AssertNotNull(import);
idx = wolfSSL_dtls_export(import, &sz, ssl);
AssertIntGE(idx, 0);
AssertIntGE(wolfSSL_dtls_import(ssl, import, idx), 0);
XFREE(import, NULL, DYNAMIC_TYPE_TMP_BUFFER);
}
#endif
#ifdef WOLFSSL_TIRTOS
Task_yield();
#endif
@@ -861,7 +918,12 @@ static void run_wolfssl_client(void* args)
callbacks->ctx_ready(ctx);
ssl = wolfSSL_new(ctx);
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl);
if (wolfSSL_dtls(ssl)) {
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 1, ssl);
}
else {
tcp_connect(&sfd, wolfSSLIP, ((func_args*)args)->signal->port, 0, ssl);
}
AssertIntEQ(SSL_SUCCESS, wolfSSL_set_fd(ssl, sfd));
if (callbacks->ssl_ready)
@@ -894,7 +956,8 @@ static void run_wolfssl_client(void* args)
#endif
}
#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) */
#endif /* defined(HAVE_SNI) || defined(HAVE_ALPN) ||
defined(WOLFSSL_SESSION_EXPORT) */
#endif /* io tests dependencies */
@@ -952,6 +1015,52 @@ static void test_wolfSSL_read_write(void)
#endif
}
static void test_wolfSSL_dtls_export(void)
{
#if defined(HAVE_IO_TESTS_DEPENDENCIES) && defined(WOLFSSL_DTLS) && \
defined(WOLFSSL_SESSION_EXPORT)
tcp_ready ready;
func_args client_args;
func_args server_args;
THREAD_TYPE serverThread;
callback_functions server_cbf;
callback_functions client_cbf;
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
InitTcpReady(&ready);
/* set using dtls */
XMEMSET(&server_cbf, 0, sizeof(callback_functions));
XMEMSET(&client_cbf, 0, sizeof(callback_functions));
server_cbf.method = wolfDTLSv1_2_server_method;
client_cbf.method = wolfDTLSv1_2_client_method;
server_args.callbacks = &server_cbf;
client_args.callbacks = &client_cbf;
server_args.signal = &ready;
client_args.signal = &ready;
start_thread(run_wolfssl_server, &server_args, &serverThread);
wait_tcp_ready(&server_args);
run_wolfssl_client(&client_args);
join_thread(serverThread);
AssertTrue(client_args.return_code);
AssertTrue(server_args.return_code);
FreeTcpReady(&ready);
#ifdef WOLFSSL_TIRTOS
fdOpenSession(Task_self());
#endif
printf(testingFmt, "wolfSSL_dtls_export()");
printf(resultFmt, passed);
#endif
}
/*----------------------------------------------------------------------------*
| TLS extensions tests
*----------------------------------------------------------------------------*/
@@ -1738,6 +1847,7 @@ void ApiTest(void)
test_wolfSSL_SetTmpDH_file();
test_wolfSSL_SetTmpDH_buffer();
test_wolfSSL_read_write();
test_wolfSSL_dtls_export();
/* TLS extensions tests */
test_wolfSSL_UseSNI();

View File

@@ -1203,8 +1203,6 @@ typedef struct ProtocolVersion {
} WOLFSSL_PACK ProtocolVersion;
WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(byte* buf, word32 sz, WOLFSSL* ssl);
WOLFSSL_LOCAL int wolfSSL_dtls_export(byte* buf, word32 sz, WOLFSSL* ssl);
WOLFSSL_LOCAL ProtocolVersion MakeSSLv3(void);
WOLFSSL_LOCAL ProtocolVersion MakeTLSv1(void);
WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_1(void);
@@ -1213,6 +1211,14 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_2(void);
#ifdef WOLFSSL_DTLS
WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1(void);
WOLFSSL_LOCAL ProtocolVersion MakeDTLSv1_2(void);
#ifdef WOLFSSL_SESSION_EXPORT
WOLFSSL_LOCAL int wolfSSL_dtls_import_internal(byte* buf, word32 sz,
WOLFSSL* ssl);
WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(byte* buf, word32 sz,
WOLFSSL* ssl);
WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
#endif
#endif

View File

@@ -229,10 +229,13 @@ WOLFSSL_API WOLFSSL_METHOD *wolfTLSv1_2_client_method(void);
#ifdef WOLFSSL_DTLS
typedef int (*wc_dtls_export)(WOLFSSL* ssl,
unsigned char* exportBuffer, unsigned int sz, void* userCtx);
WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf, unsigned int sz);
WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx, wc_dtls_export func);
WOLFSSL_API int wolfSSL_dtls_import(WOLFSSL* ssl, unsigned char* buf,
unsigned int sz);
WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx,
wc_dtls_export func);
WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func);
WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
WOLFSSL_API int wolfSSL_dtls_export(unsigned char* buf, unsigned int* sz,
WOLFSSL* ssl);
#endif /* WOLFSSL_DTLS */
#endif /* WOLFSSL_SESSION_EXPORT */