add export/import window state only

This commit is contained in:
Jacob Barthelmeh
2019-06-21 15:52:48 -06:00
parent f4548945f7
commit b236a1c32f
4 changed files with 178 additions and 3 deletions

View File

@@ -1131,6 +1131,64 @@ static int ImportPeerInfo(WOLFSSL* ssl, byte* buf, word32 len, byte ver)
}
/* WOLFSSL_LOCAL function that serializes the current WOLFSSL session state only
* 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 state.*/
int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl, byte* buf, word32 sz)
{
int ret;
word32 idx = 0;
word32 totalLen = 0;
WOLFSSL_ENTER("wolfSSL_dtls_export_state_internal");
if (buf == NULL || ssl == NULL) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BAD_FUNC_ARG);
return BAD_FUNC_ARG;
}
totalLen += DTLS_EXPORT_LEN * 2; /* 2 protocol bytes and 2 length bytes */
/* each of the following have a 2 byte length before data */
totalLen += DTLS_EXPORT_LEN + DTLS_EXPORT_KEY_SZ;
if (totalLen > sz) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", BUFFER_E);
return BUFFER_E;
}
buf[idx++] = (byte)DTLS_EXPORT_STATE_PRO;
buf[idx++] = ((byte)DTLS_EXPORT_STATE_PRO & 0xF0) |
((byte)DTLS_EXPORT_VERSION & 0X0F);
idx += DTLS_EXPORT_LEN; /* leave room for total length */
/* export keys struct and dtls state -- variable length stored in ret */
idx += DTLS_EXPORT_LEN; /* leave room for length */
if ((ret = ExportKeyState(ssl, buf + idx, sz - idx,
DTLS_EXPORT_VERSION)) < 0) {
WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", ret);
return ret;
}
c16toa((word16)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);
#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
/* if compiled with debug options then print the version, protocol, size */
{
char debug[256];
XSNPRINTF(debug, sizeof(debug), "Exporting DTLS session state\n"
"\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
, (int)DTLS_EXPORT_VERSION, buf[0], (buf[1] >> 4), idx - 2);
WOLFSSL_MSG(debug);
}
#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
WOLFSSL_LEAVE("wolfSSL_dtls_export_state_internal", idx);
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
* passed in.
@@ -1221,6 +1279,78 @@ int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf, word32 sz)
}
/* On success return amount of buffer consumed */
int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl, byte* buf, word32 sz)
{
word32 idx = 0;
word16 length = 0;
int version;
int ret;
WOLFSSL_ENTER("wolfSSL_dtls_import_state_internal");
/* check at least enough room for protocol and length */
if (sz < DTLS_EXPORT_LEN * 2 || ssl == NULL) {
WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", BAD_FUNC_ARG);
return BAD_FUNC_ARG;
}
if (buf[idx++] != (byte)DTLS_EXPORT_STATE_PRO ||
(buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
WOLFSSL_MSG("Incorrect protocol");
return BAD_FUNC_ARG;
}
version = buf[idx++] & 0x0F;
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
if (length > sz - DTLS_EXPORT_LEN) { /* subtract 2 for protocol */
WOLFSSL_MSG("Buffer size sanity check failed");
return BUFFER_E;
}
#ifdef WOLFSSL_SESSION_EXPORT_DEBUG
/* if compiled with debug options then print the version, protocol, size */
{
char debug[256];
XSNPRINTF(debug, sizeof(debug), "Importing DTLS session state\n"
"\tVersion : %d\n\tProtocol : %02X%01X\n\tLength of: %d\n\n"
, (int)version, buf[0], (buf[1] >> 4), length);
WOLFSSL_MSG(debug);
}
#endif /* WOLFSSL_SESSION_EXPORT_DEBUG */
/* perform sanity checks and extract Options information used */
switch (version) {
case DTLS_EXPORT_VERSION:
break;
default:
WOLFSSL_MSG("Bad export state version");
return BAD_FUNC_ARG;
}
/* perform sanity checks and extract Keys struct */
if (DTLS_EXPORT_LEN + idx > sz) {
WOLFSSL_MSG("Import Key struct error");
return BUFFER_E;
}
ato16(buf + idx, &length); idx += DTLS_EXPORT_LEN;
if (length > DTLS_EXPORT_KEY_SZ || length + idx > sz) {
WOLFSSL_MSG("Import Key struct error");
return BUFFER_E;
}
if ((ret = ImportKeyState(ssl, buf + idx, length, version)) < 0) {
WOLFSSL_MSG("Import Key struct error");
WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret);
return ret;
}
idx += ret;
WOLFSSL_LEAVE("wolfSSL_dtls_import_state_internal", ret);
return ret;
}
/* On success return amount of buffer consumed */
int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
{
@@ -1240,8 +1370,9 @@ int wolfSSL_dtls_import_internal(WOLFSSL* ssl, byte* buf, word32 sz)
if (buf[idx++] != (byte)DTLS_EXPORT_PRO ||
(buf[idx] & 0xF0) != ((byte)DTLS_EXPORT_PRO & 0xF0)) {
/* don't increment on second idx to next get version */
WOLFSSL_MSG("Incorrect protocol");
return BAD_FUNC_ARG;
/* check if importing state only */
return wolfSSL_dtls_import_state_internal(ssl, buf, sz);
}
version = buf[idx++] & 0x0F;

View File

@@ -160,7 +160,7 @@ int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func)
/* This function allows for directly serializing a session rather than using
* callbacks. It has less overhead by removing a temporary buffer and gives
* control over when the session gets serialized. When using callbacks the
* session is always serialized immediatly after the handshake is finished.
* session is always serialized immediately after the handshake is finished.
*
* buf is the argument to contain the serialized session
* sz is the size of the buffer passed in
@@ -191,6 +191,41 @@ int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf, unsigned int* sz)
}
/* This function is similar to wolfSSL_dtls_export but only exports the portion
* of the WOLFSSL structure related to the state of the connection, i.e. peer
* sequence number, epoch, AEAD state etc.
*
* buf is the argument to contain the serialized state, if null then set "sz" to
* buffer size required
* sz is the size of the buffer passed in
* ssl is the WOLFSSL struct to serialize
* returns the size of serialized session on success, 0 on no action, and
* negative value on error */
int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf,
unsigned int* sz)
{
WOLFSSL_ENTER("wolfSSL_dtls_export_state_only");
if (ssl == NULL || sz == NULL) {
return BAD_FUNC_ARG;
}
if (buf == NULL) {
*sz = MAX_EXPORT_STATE_BUFFER;
return 0;
}
/* if not DTLS do nothing */
if (!ssl->options.dtls) {
WOLFSSL_MSG("Currently only DTLS export state is supported");
return 0;
}
/* copy over keys, options, and dtls state struct */
return wolfSSL_dtls_export_state_internal(ssl, buf, *sz);
}
/* returns 0 on success */
int wolfSSL_send_session(WOLFSSL* ssl)
{

View File

@@ -1266,6 +1266,7 @@ enum Misc {
DTLS_HANDSHAKE_FRAG_SZ = 3, /* fragment offset and length are 24 bit */
DTLS_POOL_SZ = 255,/* allowed number of list items in TX pool */
DTLS_EXPORT_PRO = 165,/* wolfSSL protocol for serialized session */
DTLS_EXPORT_STATE_PRO = 166,/* wolfSSL protocol for serialized state */
DTLS_EXPORT_VERSION = 4, /* wolfSSL version for serialized session */
DTLS_EXPORT_OPT_SZ = 60, /* amount of bytes used from Options */
DTLS_EXPORT_VERSION_3 = 3, /* wolfSSL version before TLS 1.3 addition */
@@ -1278,6 +1279,8 @@ enum Misc {
DTLS_EXPORT_LEN = 2, /* 2 bytes for length and protocol */
DTLS_EXPORT_IP = 46, /* max ip size IPv4 mapped IPv6 */
MAX_EXPORT_BUFFER = 514, /* max size of buffer for exporting */
MAX_EXPORT_STATE_BUFFER = DTLS_EXPORT_KEY_SZ + 3 * DTLS_EXPORT_LEN,
/* max size of buffer for exporting state */
FINISHED_LABEL_SZ = 15, /* TLS finished label size */
TLS_FINISHED_SZ = 12, /* TLS has a shorter size */
EXT_MASTER_LABEL_SZ = 22, /* TLS extended master secret label sz */
@@ -1563,6 +1566,10 @@ WOLFSSL_LOCAL ProtocolVersion MakeTLSv1_3(void);
word32 sz);
WOLFSSL_LOCAL int wolfSSL_dtls_export_internal(WOLFSSL* ssl, byte* buf,
word32 sz);
WOLFSSL_LOCAL int wolfSSL_dtls_export_state_internal(WOLFSSL* ssl,
byte* buf, word32 sz);
WOLFSSL_LOCAL int wolfSSL_dtls_import_state_internal(WOLFSSL* ssl,
byte* buf, word32 sz);
WOLFSSL_LOCAL int wolfSSL_send_session(WOLFSSL* ssl);
#endif
#endif

View File

@@ -507,6 +507,8 @@ WOLFSSL_API int wolfSSL_CTX_dtls_set_export(WOLFSSL_CTX* ctx,
WOLFSSL_API int wolfSSL_dtls_set_export(WOLFSSL* ssl, wc_dtls_export func);
WOLFSSL_API int wolfSSL_dtls_export(WOLFSSL* ssl, unsigned char* buf,
unsigned int* sz);
WOLFSSL_API int wolfSSL_dtls_export_state_only(WOLFSSL* ssl, unsigned char* buf,
unsigned int* sz);
#endif /* WOLFSSL_DTLS */
#endif /* WOLFSSL_SESSION_EXPORT */